static void gd_bezier(point* A, int n, int arrow_at_start, int arrow_at_end) { pointf p0, p1, V[4]; int i, j, step; int style[20]; int pen, width; gdImagePtr brush = NULL; if (cstk[SP].pen != P_NONE) { if (cstk[SP].pen == P_DASHED) { for (i = 0; i < 10; i++) style[i] = cstk[SP].pencolor; for (; i < 20; i++) style[i] = gdTransparent; gdImageSetStyle(im, style, 20); pen = gdStyled; } else if (cstk[SP].pen == P_DOTTED) { for (i = 0; i < 2; i++) style[i] = cstk[SP].pencolor; for (; i < 12; i++) style[i] = gdTransparent; gdImageSetStyle(im, style, 12); pen = gdStyled; } else { pen = cstk[SP].pencolor; } #if 0 if (cstk[SP].penwidth != WIDTH_NORMAL) { width=cstk[SP].penwidth; brush = gdImageCreate(width,width); gdImagePaletteCopy(brush, im); gdImageFilledRectangle(brush, 0,0,width-1, width-1, cstk[SP].pencolor); gdImageSetBrush(im, brush); if (pen == gdStyled) pen = gdStyledBrushed; else pen = gdBrushed; } #else width = cstk[SP].penwidth; gdImageSetThickness(im, width); #endif V[3].x = A[0].x; V[3].y = A[0].y; for (i = 0; i+3 < n; i += 3) { V[0] = V[3]; for (j = 1; j <= 3; j++) { V[j].x = A[i+j].x; V[j].y = A[i+j].y; } p0 = gdpt(V[0]); for (step = 1; step <= BEZIERSUBDIVISION; step++) { p1 = gdpt(Bezier(V, 3, (double)step/BEZIERSUBDIVISION, NULL, NULL)); gdImageLine(im, ROUND(p0.x), ROUND(p0.y), ROUND(p1.x), ROUND(p1.y), pen); p0 = p1; } } if (brush) gdImageDestroy(brush); } }
static void gd_polyline(point* A, int n) { pointf p, p1; int i; int style[20]; int pen, width; gdImagePtr brush = NULL; if (cstk[SP].pen != P_NONE) { if (cstk[SP].pen == P_DASHED) { for (i = 0; i < 10; i++) style[i] = cstk[SP].pencolor; for (; i < 20; i++) style[i] = gdTransparent; gdImageSetStyle(im, style, 20); pen = gdStyled; } else if (cstk[SP].pen == P_DOTTED) { for (i = 0; i < 2; i++) style[i] = cstk[SP].pencolor; for (; i < 12; i++) style[i] = gdTransparent; gdImageSetStyle(im, style, 12); pen = gdStyled; } else { pen = cstk[SP].pencolor; } #if 0 if (cstk[SP].penwidth != WIDTH_NORMAL) { width = cstk[SP].penwidth; brush = gdImageCreate(width,width); gdImagePaletteCopy(brush, im); gdImageFilledRectangle(brush, 0,0,width-1,width-1,cstk[SP].pencolor); gdImageSetBrush(im, brush); if (pen == gdStyled) pen = gdStyledBrushed; else pen = gdBrushed; } #else width = cstk[SP].penwidth; gdImageSetThickness(im, width); #endif p.x = A[0].x; p.y = A[0].y; p = gdpt(p); for (i = 1; i < n; i++) { p1.x = A[i].x; p1.y = A[i].y; p1 = gdpt(p1); gdImageLine(im, ROUND(p.x), ROUND(p.y), ROUND(p1.x), ROUND(p1.y), pen); p.x = p1.x; p.y = p1.y; } if (brush) gdImageDestroy(brush); } }
static void gd_user_shape(char *name, point * A, int n, int filled) { gdImagePtr im2 = 0; pointf destul, destlr; pointf ul, lr; /* upper left, lower right */ double sx, sy; /* target size */ double scalex, scaley; /* scale factors */ int i; char *shapeimagefile; if (streq(name, "custom")) shapeimagefile = agget(Curnode, "shapefile"); else shapeimagefile = name; im2 = gd_getshapeimage(shapeimagefile); if (im2) { pointf delta; /* compute dest origin and size */ ul.x = lr.x = A[0].x; ul.y = lr.y = A[0].y; for (i = 1; i < n; i++) { if (ul.x > A[i].x) ul.x = A[i].x; if (ul.y < A[i].y) ul.y = A[i].y; if (lr.y > A[i].y) lr.y = A[i].y; if (lr.x < A[i].x) lr.x = A[i].x; } destul = gdpt(ul); destlr = gdpt(lr); delta.x = destlr.x - destul.x; delta.y = destlr.y - destul.y; scalex = delta.x / (double) (im2->sx); scaley = delta.y / (double) (im2->sy); /* keep aspect ratio fixed by just using the smaller scale */ if (scalex < scaley) { sx = im2->sx * scalex; sy = im2->sy * scalex; } else { sx = im2->sx * scaley; sy = im2->sy * scaley; } if (sx < delta.x) destul.x += (delta.x - sx) / 2.0; if (sy < delta.y) destul.y += (delta.y - sy) / 2.0; sx = ROUND(sx); sy = ROUND(sy); gdImageCopyResized(im, im2, ROUND(destul.x), ROUND(destul.y), 0, 0, sx, sy, im2->sx, im2->sy); } }
static void gd_ellipse(point p, int rx, int ry, int filled) { pointf mp; int i; int style[40]; /* need 2* size for arcs, I don't know why */ int pen, width; gdImagePtr brush = NULL; if (cstk[SP].pen != P_NONE) { if (cstk[SP].pen == P_DASHED) { for (i = 0; i < 20; i++) style[i] = cstk[SP].pencolor; for (; i < 40; i++) style[i] = gdTransparent; gdImageSetStyle(im, style, 40); pen = gdStyled; } else if (cstk[SP].pen == P_DOTTED) { for (i = 0; i < 2; i++) style[i] = cstk[SP].pencolor; for (; i < 24; i++) style[i] = gdTransparent; gdImageSetStyle(im, style, 24); pen = gdStyled; } else { pen = cstk[SP].pencolor; } #if 1 /* use brush instead of Thickness to improve outline appearance */ gdImageSetThickness(im, WIDTH_NORMAL); if (cstk[SP].penwidth != WIDTH_NORMAL) { width = cstk[SP].penwidth; brush = gdImageCreate(width,width); gdImagePaletteCopy(brush, im); gdImageFilledRectangle(brush, 0,0,width-1, width-1, cstk[SP].pencolor); gdImageSetBrush(im, brush); if (pen == gdStyled) pen = gdStyledBrushed; else pen = gdBrushed; } #else width = cstk[SP].penwidth; gdImageSetThickness(im, width); #endif if (Rot) {int t; t = rx; rx = ry; ry = t;} mp.x = p.x; mp.y = p.y; mp = gdpt(mp); if (filled) { gdImageFilledEllipse(im, ROUND(mp.x), ROUND(mp.y), ROUND(Zoom*(rx + rx)), ROUND(Zoom*(ry + ry)), cstk[SP].fillcolor); } gdImageArc(im, ROUND(mp.x), ROUND(mp.y), ROUND(Zoom*(rx + rx)), ROUND(Zoom*(ry + ry)), 0, 360, pen); if (brush) gdImageDestroy(brush); } }
static void gd_polygon(point *A, int n, int filled) { pointf p; int i; gdPoint *points; int style[20]; int pen, width; gdImagePtr brush = NULL; if (cstk[SP].pen != P_NONE) { if (cstk[SP].pen == P_DASHED) { for (i = 0; i < 10; i++) style[i] = cstk[SP].pencolor; for (; i < 20; i++) style[i] = gdTransparent; gdImageSetStyle(im, style, 20); pen = gdStyled; } else if (cstk[SP].pen == P_DOTTED) { for (i = 0; i < 2; i++) style[i] = cstk[SP].pencolor; for (; i < 12; i++) style[i] = gdTransparent; gdImageSetStyle(im, style, 12); pen = gdStyled; } else { pen = cstk[SP].pencolor; } #if 1 /* use brush instead of Thickness to improve end butts */ gdImageSetThickness(im, WIDTH_NORMAL); if (cstk[SP].penwidth != WIDTH_NORMAL) { width=cstk[SP].penwidth * Zoom; brush = gdImageCreate(width,width); gdImagePaletteCopy(brush, im); gdImageFilledRectangle(brush, 0,0,width-1, width-1, cstk[SP].pencolor); gdImageSetBrush(im, brush); if (pen == gdStyled) pen = gdStyledBrushed; else pen = gdBrushed; } #else width = cstk[SP].penwidth; gdImageSetThickness(im, width); #endif points = N_GNEW(n,gdPoint); for (i = 0; i < n; i++) { p.x = A[i].x; p.y = A[i].y; p = gdpt(p); points[i].x = ROUND(p.x); points[i].y = ROUND(p.y); } if (filled) gdImageFilledPolygon(im, points, n, cstk[SP].fillcolor); gdImagePolygon(im, points, n, pen); free(points); if (brush) gdImageDestroy(brush); } }
static void gd_textline(point p, textline_t *line) { char *fontlist, *err; pointf mp,ep; int brect[8]; char *str = line->str; double fontsz = cstk[SP].fontsz; if (cstk[SP].pen == P_NONE) return; fontlist = gd_alternate_fontlist(cstk[SP].fontfam); switch(line->just) { case 'l': mp.x = p.x; break; case 'r': mp.x = p.x - line->width; break; default: case 'n': mp.x = p.x - line->width / 2; break; } ep.y = mp.y = p.y; ep.x = mp.x + line->width; mp = gdpt(mp); if (fontsz <= FONTSIZE_MUCH_TOO_SMALL) { /* ignore entirely */ } else if (fontsz <= FONTSIZE_TOO_SMALL) { /* draw line in place of text */ ep = gdpt(ep); gdImageLine(im, ROUND(mp.x), ROUND(mp.y), ROUND(ep.x), ROUND(ep.y), cstk[SP].pencolor); } else { err = gdImageStringFT(im, brect, cstk[SP].pencolor, fontlist, fontsz, (Rot? 90.0 : 0.0) * PI / 180.0, ROUND(mp.x), ROUND(mp.y), str); if (err) { /* revert to builtin fonts */ gd_missingfont (err, cstk[SP].fontfam); if (fontsz <= 8.5) { gdImageString(im, gdFontTiny, ROUND(mp.x), ROUND(mp.y-9.), (unsigned char *)str, cstk[SP].pencolor); } else if (fontsz <= 9.5) { gdImageString(im, gdFontSmall, ROUND(mp.x), ROUND(mp.y-12.), (unsigned char *)str, cstk[SP].pencolor); } else if (fontsz <= 10.5) { gdImageString(im, gdFontMediumBold, ROUND(mp.x), ROUND(mp.y-13.), (unsigned char *)str, cstk[SP].pencolor); } else if (fontsz <= 11.5) { gdImageString(im, gdFontLarge, ROUND(mp.x), ROUND(mp.y-14.), (unsigned char *)str, cstk[SP].pencolor); } else { gdImageString(im, gdFontGiant, ROUND(mp.x), ROUND(mp.y-15.), (unsigned char *)str, cstk[SP].pencolor); } } } }
static void gd_bezier(point * A, int n, int arrow_at_start, int arrow_at_end, int filled) { pointf p, p0, p1, V[4]; int i, j, step; int style[20]; int pen, width; gdImagePtr brush = NULL; gdPoint F[4]; if (!im) return; if (cstk[SP].pen != P_NONE) { if (cstk[SP].pen == P_DASHED) { for (i = 0; i < 10; i++) style[i] = cstk[SP].pencolor; for (; i < 20; i++) style[i] = transparent; gdImageSetStyle(im, style, 20); pen = gdStyled; } else if (cstk[SP].pen == P_DOTTED) { for (i = 0; i < 2; i++) style[i] = cstk[SP].pencolor; for (; i < 12; i++) style[i] = transparent; gdImageSetStyle(im, style, 12); pen = gdStyled; } else { pen = cstk[SP].pencolor; } width = cstk[SP].penwidth * CompScale; if (width < WIDTH_NORMAL) width = WIDTH_NORMAL; /* gd can't do thin lines */ gdImageSetThickness(im, width); if (width > WIDTH_NORMAL) { brush = gdImageCreate(width, width); gdImagePaletteCopy(brush, im); gdImageFilledRectangle(brush, 0, 0, width - 1, width - 1, cstk[SP].pencolor); gdImageSetBrush(im, brush); if (pen == gdStyled) pen = gdStyledBrushed; else pen = gdBrushed; } p.x = A[0].x; p.y = A[0].y; p = gdpt(p); F[0].x = ROUND(p.x); F[0].y = ROUND(p.y); p.x = A[n-1].x; p.y = A[n-1].y; p = gdpt(p); F[3].x = ROUND(p.x); F[3].y = ROUND(p.y); V[3].x = A[0].x; V[3].y = A[0].y; for (i = 0; i + 3 < n; i += 3) { V[0] = V[3]; for (j = 1; j <= 3; j++) { V[j].x = A[i + j].x; V[j].y = A[i + j].y; } p0 = gdpt(V[0]); for (step = 1; step <= BEZIERSUBDIVISION; step++) { p1 = gdpt(Bezier (V, 3, (double) step / BEZIERSUBDIVISION, NULL, NULL)); gdImageLine(im, ROUND(p0.x), ROUND(p0.y), ROUND(p1.x), ROUND(p1.y), pen); if (filled) { F[1].x = ROUND(p0.x); F[1].y = ROUND(p0.y); F[2].x = ROUND(p1.x); F[2].y = ROUND(p1.y); gdImageFilledPolygon(im, F, 4, cstk[SP].fillcolor); } p0 = p1; } } if (brush) gdImageDestroy(brush); } }
static void gd_textline(point p, textline_t * line) { char *str, *fontlist, *err; pointf mp, ep; int brect[8]; double fontsz; gdFTStringExtra strex; int pencolor; if (!im) return; strex.flags = gdFTEX_RESOLUTION; strex.hdpi = strex.vdpi = Dpi * Zoom; if (cstk[SP].pen == P_NONE) return; pencolor = cstk[SP].pencolor; if (!im->trueColor && cstk[SP].fillcolor == transparent) pencolor = -pencolor; /* disable antialiasing */ if (strstr(cstk[SP].fontfam, "/")) strex.flags |= gdFTEX_FONTPATHNAME; else strex.flags |= gdFTEX_FONTCONFIG; str = line->str; fontlist = gd_alternate_fontlist(cstk[SP].fontfam); fontsz = cstk[SP].fontsz; switch (line->just) { case 'l': mp.x = p.x; break; case 'r': mp.x = p.x - line->width; break; default: case 'n': mp.x = p.x - line->width / 2; break; } ep.y = mp.y = p.y; ep.x = mp.x + line->width; mp = gdpt(mp); if (fontsz <= FONTSIZE_MUCH_TOO_SMALL) { /* ignore entirely */ } else if (fontsz <= FONTSIZE_TOO_SMALL) { /* draw line in place of text */ ep = gdpt(ep); gdImageLine(im, ROUND(mp.x), ROUND(mp.y), ROUND(ep.x), ROUND(ep.y), cstk[SP].pencolor); } else { #ifdef HAVE_GD_FREETYPE err = gdImageStringFTEx(im, brect, pencolor, fontlist, fontsz, Rot ? (PI / 2) : 0, ROUND(mp.x), ROUND(mp.y), str, &strex); #if 0 gdImagePolygon(im, (gdPointPtr) brect, 4, cstk[SP].pencolor); #endif #if 0 fprintf(stderr, "textline: font=%s size=%g pos=%g,%g width=%g dpi=%d width/dpi=%g\n", fontlist, fontsz, mp.x, mp.y, (double) (brect[4] - brect[0]), strex.hdpi, (((double) (brect[4] - brect[0])) / strex.hdpi)); #endif if (err) { /* revert to builtin fonts */ gd_missingfont(err, cstk[SP].fontfam); #endif mp.y += 2; if (fontsz <= 8.5) { gdImageString(im, gdFontTiny, ROUND(mp.x), ROUND(mp.y - 9.), (unsigned char *) str, cstk[SP].pencolor); } else if (fontsz <= 9.5) { gdImageString(im, gdFontSmall, ROUND(mp.x), ROUND(mp.y - 12.), (unsigned char *) str, cstk[SP].pencolor); } else if (fontsz <= 10.5) { gdImageString(im, gdFontMediumBold, ROUND(mp.x), ROUND(mp.y - 13.), (unsigned char *) str, cstk[SP].pencolor); } else if (fontsz <= 11.5) { gdImageString(im, gdFontLarge, ROUND(mp.x), ROUND(mp.y - 14.), (unsigned char *) str, cstk[SP].pencolor); } else { gdImageString(im, gdFontGiant, ROUND(mp.x), ROUND(mp.y - 15.), (unsigned char *) str, cstk[SP].pencolor); } #ifdef HAVE_GD_FREETYPE } #endif } }