#include #include #include #include #include #include "svg.h" /* ---------------------------------------------------------------------- * * begin common part * ---------------------------------------------------------------------- */ unsigned int utf8(unsigned char *s) { unsigned int c = s[0]; if ((c & 0x80) == 0) { // 0xxx xxxx return c; } if ((c & 0xc0) != 0xc0) { // 10xx xxxx // not UTF-8 or not first byte // printf("10xx xxxx\n"); return c; } // (c & 0xc0) == 0xc0 if ((c & 0x20) == 0) { // 110y yyyx 10xx xxxx unsigned int d = s[1] & 0x3f; // printf("110y yyyx 10xx xxxx\n"); return (c & 0x1f) << 6 | d ; } if ((c & 0x10) == 0) { // 1110 yyyy 10yx xxxx 10xx xxxx unsigned int d = s[1] & 0x3f, e = s[2] & 0x3f; // printf("1110 yyyy 10yx xxxx 10xx xxxx\n"); return (c & 0xf) << 12 | d << 6 | e; } if ((c & 0x08) == 0) { // 1111 0yyy 10yy xxxx 10xx xxxx 10xx xxxx unsigned int d = s[1] & 0x3f, e = s[2] & 0x3f, f = s[3] & 0x3f; // printf("1111 0yyy 10yy xxxx 10xx xxxx 10xx xxxx\n"); return (c & 0x7) << 18 | d << 12 | e << 6 | f; } if ((c & 0x04) == 0) { // 1111 10yy 10yy yxxx 10xx xxxx 10xx xxxx 10xx xxxx unsigned int d = s[1] & 0x3f, e = s[2] & 0x3f, f = s[3] & 0x3f, g = s[4] & 0x3f; // printf("1111 10yy 10yy yxxx 10xx xxxx 10xx xxxx 10xx xxxx\n"); return (c & 0x3) << 24 | d << 18 | e << 12 | f << 6 | g; } if ((c & 0x02) == 0) { // 1111 110y 10yy yyxx 10xx xxxx 10xx xxxx 10xx xxxx 10xx xxxx unsigned int d = s[1] & 0x3f, e = s[2] & 0x3f, f = s[3] & 0x3f, g = s[4] & 0x3f, h = s[5] & 0x3f; // printf("1111 110y 10yy yyxx 10xx xxxx 10xx xxxx 10xx xxxx 10xx xxxx\n"); return (c & 0x1) << 30 | d << 24 | e << 18 | f << 12 | g << 6 | h; } // printf("1111 111x\n"); return c; // 0xFE or 0xFF } double bound1(double d) { if (d < 0) d = 0.0; if (d > 1) d = 1.0; return d; } unsigned int bound255(int i) { if (i < 0) i = 0; if (i > 255) i = 255; return i; } void randomSeed(unsigned int seed) { srand(seed); } void randomizeByTime(void) { srand((unsigned int)time(NULL)); } double randomInRange(double min, double max) { int r = rand(); return (max - min) * r / RAND_MAX + min; } double radians(double deg) { return deg / 180 * PI; } static double __strokeWeight = 1; void strokeWeight(double arg) { __strokeWeight = arg; } static char __stroke[8] = "none"; void stroke(unsigned int arg) { if (arg > 0xffffff) arg = 0xffffff; sprintf(__stroke, "#%06x", arg); } void noStroke(void) { sprintf(__stroke, "none"); } static double __strokeOpacity = 1; void strokeOpacity(double o) { __strokeOpacity = bound1(o); } static char __fill[8] = "#000000"; void fill(unsigned int arg) { if (arg > 0xffffff) arg = 0xffffff; sprintf(__fill, "#%06x", arg); } void noFill(void) { sprintf(__fill, "none"); } static double __fillOpacity = 1; void fillOpacity(double o) { __fillOpacity = bound1(o); } static const char* __fontFamily = "MS-Mincho"; /* char * __fontFamily = "Times New Roman"; */ static double __fontSize = 12; void textFont(const char* font, double size) { __fontFamily = font; __fontSize = size; } unsigned int rgb255(double r, double g, double b) { unsigned int r1 = bound255((int)r), g1 = bound255((int)g), b1 = bound255((int)b); return (r1 * 0x10000) + (g1 * 0x100) + b1; } unsigned int rgb100(double r, double g, double b) { return rgb255(r * 2.55, g * 2.55, b * 2.55); } unsigned int rgb1(double r, double g, double b) { return rgb255(r * 255, g * 255, b * 255); } unsigned int hsb1(double h, double s, double v) { double r = 0, g = 0, b = 0; h *= 360; while (h >= 360) h -= 360; while (h < 0) h += 360; s = bound1(s); if (s == 0) { r = g = b = v; } else { int H, h1; double f, p, q, t; v = bound1(v); H = (int)h; h1 = H / 60; f = h / 60 - h1; p = v * (1 - s); q = v * (1 - f * s); t = v * (1 - (1 - f) * s); switch (h1) { case 0: r = v; g = t; b = p; break; case 1: r = q; g = v; b = p; break; case 2: r = p; g = v; b = t; break; case 3: r = p; g = q; b = v; break; case 4: r = t; g = p; b = v; break; case 5: r = v; g = p; b = q; break; } } return rgb1(r, g, b); } unsigned int hsb100(double h, double s, double v) { return hsb1(h / 100, s / 100, v / 100); } unsigned int hsb360(double h, double s, double v) { return hsb1(h / 360, s / 100, v / 100); } unsigned int hsb255(double h, double s, double v) { return hsb1(h / 255, s / 255, v / 255); } unsigned int hsl1(double h, double s, double l) { if (l == 0) { /* max = min = 0 */ return hsb1(h, 0, 0); } else if (l <= 0.5) { double diff = s * l; double max = l + diff; double min = l - diff; return hsb1(h, 1 - min / max, max); } else { double diff = s * (1 - l); double max = l + diff; double min = l - diff; return hsb1(h, 1 - min / max, max); } } unsigned int hsl100(double h, double s, double l) { return hsl1(h / 100, s / 100, l / 100); } unsigned int hsl360(double h, double s, double l) { return hsl1(h / 360, s / 100, l / 100); } unsigned int hsl255(double h, double s, double l) { return hsb1(h / 255, s / 255, l / 255); } unsigned int bw255(double v) { return rgb255(v, v, v); } unsigned int bw100(double v) { return bw255(v * 2.55); } unsigned int bw1(double v) { return bw255(v * 255); } double cos360(double deg) { return cos(radians(deg)); } double sin360(double deg) { return sin(radians(deg)); } double* rgb2hsb360(unsigned int rgb, double* ret) { unsigned int b = rgb % 0x100; unsigned int g = rgb / 0x100 % 0x100; unsigned int r = rgb / 0x10000 % 0x100; unsigned int max, min, sub, angle; if (r >= g) { // ? r ? g ? if (g >= b) { // r g b max = r; min = b; sub = g - b; angle = 0; } else if (b >= r) { // b r g max = b; min = g; sub = r - g; angle = 240; } else { // r b g max = r; min = g; sub = g - b; angle = 0; } } else { // ? g ? r ? if (r >= b) { // g r b max = g; min = b; sub = b - r; angle = 120; } else if (b >= g) { // b g r max = b; min = r; sub = r - g; angle = 240; } else { // g b r max = g; min = r; sub = b - r; angle = 120; } } ret[0] = 60 * ((double)sub / (max - min)) + angle; if (ret[0] < 0) ret[0] += 360; ret[1] = 100.0 * (max - min) / max; ret[2] = max / 255.0 * 100; return ret; } unsigned int rotateH360(unsigned int color, double a) { double hsb[3]; rgb2hsb360(color, hsb); hsb[0] += a; return hsb360(hsb[0], hsb[1], hsb[2]); } unsigned int rotateH(unsigned int color) { return rotateH360(color, PHYLLOTAXIS360); } unsigned int addS100(unsigned int color, double a) { double hsb[3]; rgb2hsb360(color, hsb); hsb[1] += a; return hsb360(hsb[0], hsb[1], hsb[2]); } unsigned int scaleS(unsigned int color, double a) { double hsb[3]; rgb2hsb360(color, hsb); hsb[1] *= a; return hsb360(hsb[0], hsb[1], hsb[2]); } unsigned int addB100(unsigned int color, double a) { double hsb[3]; rgb2hsb360(color, hsb); hsb[2] += a; return hsb360(hsb[0], hsb[1], hsb[2]); } unsigned int scaleB(unsigned int color, double a) { double hsb[3]; rgb2hsb360(color, hsb); hsb[2] *= a; return hsb360(hsb[0], hsb[1], hsb[2]); } /* ---------------------------------------------------------------------- * * end common part * ---------------------------------------------------------------------- */ static double width=297, height=210; static int __landscape = 1; #define __leftMargin 15 #define __rightMargin 30 #define __topMargin 15 #define __bottomMargin 15 static int __currentLeftMargin = __leftMargin, __currentRightMargin = __rightMargin; static int __currentTopMargin = __topMargin, __currentBottomMargin = __bottomMargin; void setPageSize(double w, double h) { width = w; height = h; } double centerX() { return width / 2; } double centerY() { return height / 2; } double pageWidth() { return width; } double pageHeight() { return height; } void a4Landscape(void) { width = 297; height = 210; __landscape = 1; __currentLeftMargin = __leftMargin; __currentRightMargin = __rightMargin; __currentTopMargin = __topMargin; __currentBottomMargin = __bottomMargin; } void a4Portrait(void) { width = 210; height = 297; __landscape = 0; __currentTopMargin = __rightMargin; __currentBottomMargin = __leftMargin; __currentLeftMargin = __topMargin; __currentRightMargin = __bottomMargin; } double getWidth(void) { return width; } double getHeight(void) { return height; } static int __gDepth = 0; static int __gSP = 0; void startEnc(const char* enc) { printf("\n", enc); printf("\n"); printf("\n"); randomizeByTime(); __gDepth = 0; __gSP = 0; } void start(void) { /* the default encoding */ /* startEnc("Shift_JIS"); */ startEnc("utf-8"); } #define GSTACK_SIZE 1024 static int __gStack[GSTACK_SIZE] = { 0 }; static void __pushGStack(void) { if (__gSP >= GSTACK_SIZE) { fprintf(stderr, "Stack Overflow!\n"); return; } __gStack[__gSP++] = __gDepth; } static int __popGStack(void) { if (__gSP <= 0) { fprintf(stderr, "Stack Underflow!\n"); return 0; } return __gStack[--__gSP]; } void pushMatrix(void) { __pushGStack(); } void popMatrix(void) { int tmp = __popGStack(); while (__gDepth > tmp) { __gDepth--; printf("\n"); } } void resetMatrix(void) { while (__gDepth > 0) { __gDepth--; printf("\n"); } __gSP = 0; } void translate(double x, double y) { printf("\n", x, y); __gDepth++; } void rotate360(double theta) { printf("\n", theta); __gDepth++; } void rotate(double deg) { rotate360(deg * 180 / PI); } void scale(double sx, double sy) { printf("\n", sx, sy); __gDepth++; } void line(double x1, double y1, double x2, double y2) { printf("\n"); } void rect(double x, double y, double w, double h) { printf("\n"); } void ellipse(double x, double y, double w, double h) { printf("\n", __fill, __fillOpacity); } void triangle(double x1, double y1, double x2, double y2, double x3, double y3) { printf("\n"); } void quad(double x1, double y1, double x2, double y2, double x3, double y3, double x4, double y4) { printf("\n"); } void quadrilateral(double x1, double y1, double x2, double y2, double x3, double y3, double x4, double y4) { printf("\n"); } void arc(double x, double y, double w, double h, double start, double stop) { double x0, y0, x1, y1; int large; if (stop < start) { double tmp = stop; stop = start; start = tmp; } x0 = x + w / 2 * cos(start), y0 = y + h / 2 * sin(start), x1 = x + w / 2 * cos(stop), y1 = y + h / 2 * sin(stop); large = stop - start > PI; printf("\n"); } void arc360(double x, double y, double w, double h, double start, double stop) { arc(x, y, w, h, radians(start), radians(stop)); } void bezier(double ax0, double ay0, double cx0, double cy0, double cx1, double cy1, double ax1, double ay1) { printf("\n"); } void vtext(const char* str, double x, double y, va_list list) { printf("\n", __fill, __fillOpacity); vprintf(str, list); printf("\n"); printf("\n"); } void text(const char* str, double x, double y, ...) { va_list list; va_start(list, y); vtext(str, x, y, list); va_end(list); } static int __first_vertex = 1; void beginShape(void) { printf("\n"); } void image(const char* url, double x, double y, double w, double h) { printf("\n", url); } void use(const char* url, double x, double y, double w, double h) { printf("\n", __fill, __fillOpacity); printf("\n", url); printf("\n"); } void upperBar(double height) { rect(0, 28.5 - height, WIDTH, height); /* printf("\n", __fill, __fillOpacity); printf(" \n"); printf("\n"); */ } void lowerBar(double height) { rect(0, 181.5, WIDTH, height); /* printf("\n", __fill, __fillOpacity); printf(" \n"); printf("\n"); */ } void guideBars(double height) { upperBar(height); lowerBar(height); } void rulers(void) { int i; double tmpW = __strokeWeight; char tmpC[8]; for (i = 0; i < 8; i++) { tmpC[i] = __stroke[i]; } strokeWeight(0.2); stroke(bw1(0)); line(0, 28.5, 20, 28.5); line(277, 28.5, 297, 28.5); line(0, 181.5, 20, 181.5); line(277, 181.5, 297, 181.5); for (i = 0; i < 8; i++) { __stroke[i] = tmpC[i]; } strokeWeight(tmpW); } void trimMark(void) { double sx = 1, sy = 1; double tmpW = __strokeWeight; double tmpO = __strokeOpacity; double tmpQ = __fillOpacity; char tmpC[8]; char tmpF[8]; int i; strokeWeight(0.5); for (i = 0; i < 8; i++) { tmpC[i] = __stroke[i]; } stroke(bw1(0)); strokeOpacity(1); if (__landscape) { line(10 * sx, 10 * sy, 30 * sx, 10 * sy); line(10 * sx, 10 * sy, 10 * sx, 30 * sy); line(10 * sx, 200 * sy, 30 * sx, 200 * sy); line(10 * sx, 200 * sy, 10 * sx, 180 * sy); line(272 * sx, 200 * sy, 252 * sx, 200 * sy); line(272 * sx, 200 * sy, 272 * sx, 180 * sy); } else { line(10 * sx, 10 * sy, 30 * sx, 10 * sy); line(10 * sx, 10 * sy, 10 * sx, 30 * sy); line(10 * sx, 272 * sy, 10 * sx, 252 * sy); line(10 * sx, 272 * sy, 30 * sx, 272 * sy); line(200 * sx, 10 * sy, 200 * sx, 30 * sy); line(200 * sx, 10 * sy, 180, 10 * sy); } noStroke(); for (i = 0; i < 8; i++) { tmpF[i] = __fill[i]; } fill(bw1(0)); fillOpacity(1); if (__landscape) { ellipse(28 * sx, 182 * sy, 4 * sx, 4 * sy); } else { ellipse(28 * sx, 28 * sy, 4 * sx, 4 * sy); } __fillOpacity = tmpQ; for (i = 0; i < 8; i++) { __fill[i] = tmpF[i]; } __strokeOpacity = tmpO; for (i = 0; i < 8; i++) { __stroke[i] = tmpC[i]; } strokeWeight(tmpW); } static void genericSmilieSymbol(const char* id, char* str) { printf("\n", id); printf("\n"); printf("\n"); printf("\n"); printf("\n"); printf("\n"); printf("\n"); printf("\n"); printf("\n"); printf("%s\n", str); printf("\n"); printf("\n"); } void smilieSymbol1(const char* id) { genericSmilieSymbol(id, ""); } void smilieSymbol2(const char* id) { genericSmilieSymbol(id, ""); } void smilieSymbol3(const char* id) { genericSmilieSymbol(id, ""); } void flowerSymbol(const char* id) { printf("\n", id); printf("\n"); printf("\n"); } void heartSymbol(const char* id) { printf("\n", id); printf("\n"); printf("\n"); } /* turtle graphics */ double __turtleX = 148.5, __turtleY = 105, __turtleHeading = 0; #define UP 0 #define CLEAN 1 #define DIRTY 2 #define TURTLE_STACK_SIZE 3072 static double __turtleStack[TURTLE_STACK_SIZE] = { 0 }; static int __turtleSP = 0; void pushTurtle(void) { if (__turtleSP >= TURTLE_STACK_SIZE) { fprintf(stderr, "Turtle Stack Overflow!\n"); return; } __turtleStack[__turtleSP++] = __turtleX; __turtleStack[__turtleSP++] = __turtleY; __turtleStack[__turtleSP++] = __turtleHeading; } void popTurtle(void) { if (__turtleSP <= 0) { fprintf(stderr, "Turtle Stack Underflow!\n"); return; } __turtleHeading = __turtleStack[--__turtleSP]; __turtleY = __turtleStack[--__turtleSP]; __turtleX = __turtleStack[--__turtleSP]; } int __turtlePen = CLEAN; /* up: 0, down: 1, dirty: 2 */ void penUp(void) { if (__turtlePen == DIRTY) { /* endShape(0); */ } __turtlePen = UP; } void finish(void) { penUp(); resetMatrix(); printf("\n"); } void penDown(void) { if (__turtlePen == UP) { __turtlePen = CLEAN; } } void forward(double len) { double dx = len * cos360(__turtleHeading); double dy = len * sin360(__turtleHeading); if (__turtlePen == CLEAN) { __turtlePen = DIRTY; /* beginShape(); vertex(__turtleX, __turtleY); */ } if (__turtlePen == DIRTY) { line(__turtleX, __turtleY, __turtleX + dx, __turtleY + dy); /* vertex(__turtleX + dx, __turtleY + dy); */ } __turtleX += dx; __turtleY += dy; } void backward(double len) { double dx = - len * cos360(__turtleHeading); double dy = - len * sin360(__turtleHeading); __turtleX += dx; __turtleY += dy; } void turn(double angle) { int tmp; __turtleHeading += angle; tmp = (int)__turtleHeading; __turtleHeading -= tmp; if (__turtleHeading < 0) { __turtleHeading += 1; tmp--; } tmp %= 360; if (tmp < 0) { tmp += 360; } __turtleHeading += tmp; } void direction(double dir) { int tmp; __turtleHeading = dir; tmp = (int)__turtleHeading; __turtleHeading -= tmp; if (__turtleHeading < 0) { __turtleHeading += 1; tmp--; } tmp %= 360; if (tmp < 0) { tmp += 360; } __turtleHeading += tmp; } void go(double x, double y) { if (__turtleX != x || __turtleY != y) { if (__turtlePen == DIRTY) { penUp(); __turtleX = x; __turtleY = y; penDown(); } else { __turtleX = x; __turtleY = y; } } } void center(void) { go(148.5, 105); } double getX(void) { return __turtleX; } double getY(void) { return __turtleY; } double getAngle(void) { return __turtleHeading; } void say(const char *str, ...) { va_list list; va_start(list, str); pushMatrix(); translate(__turtleX, __turtleY); rotate360(__turtleHeading); vtext(str, 0, 0, list); popMatrix(); va_end(list); }