int main(void) { gdImagePtr im; int white, black, r; gdPointPtr points; im = gdImageCreate(100, 100); if (!im) exit(EXIT_FAILURE); white = gdImageColorAllocate(im, 0xff, 0xff, 0xff); black = gdImageColorAllocate(im, 0, 0, 0); gdImageFilledRectangle(im, 0, 0, 99, 99, white); points = (gdPointPtr)calloc(3, sizeof(gdPoint)); if (!points) { gdImageDestroy(im); exit(EXIT_FAILURE); } points[0].x = 10; points[0].y = 10; gdImageFilledPolygon(im, points, 1, black); r = gdAssertImageEqualsToFile(GDTEST_TOP_DIR "/gdimagefilledpolygon/gdimagefilledpolygon1.png", im); free(points); gdImageDestroy(im); if (!r) exit(EXIT_FAILURE); return EXIT_SUCCESS; }
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); } }
int main(void) { gdImagePtr im; int white, black, r; im = gdImageCreate(100, 100); if (!im) exit(EXIT_FAILURE); white = gdImageColorAllocate(im, 0xff, 0xff, 0xff); black = gdImageColorAllocate(im, 0, 0, 0); gdImageFilledRectangle(im, 0, 0, 99, 99, white); gdImageFilledPolygon(im, NULL, 0, black); /* no effect */ gdImageFilledPolygon(im, NULL, -1, black); /* no effect */ r = gdAssertImageEqualsToFile(GDTEST_TOP_DIR "/gdimagefilledpolygon/gdimagefilledpolygon0.png", im); gdImageDestroy(im); if (!r) exit(EXIT_FAILURE); return EXIT_SUCCESS; }
/* prints the arrow into the image poined to by the pointer with given color*/ void ocin_vis_arrow::print(gdImagePtr im, float scale_val) { int thick = ((int)((float)thickness *scale_val)) + 1; int scaled_a_size = (int) ((float)(a_size - 4) *scale_val) + 4; // create points for arrow head based on scale factor if (dir == S) { points[1].x = x2 - scaled_a_size; points[1].y = y2 - scaled_a_size; points[2].x = x2 + scaled_a_size; points[2].y = y2 - scaled_a_size; } else if (dir == E) { points[1].x = x2 - scaled_a_size; points[1].y = y2 + scaled_a_size; points[2].x = x2 - scaled_a_size; points[2].y = y2 - scaled_a_size; } else if (dir == N) { points[1].x = x2 - scaled_a_size; points[1].y = y2 + scaled_a_size; points[2].x = x2 + scaled_a_size; points[2].y = y2 + scaled_a_size; } else if (dir == W) { points[1].x = x2 + scaled_a_size; points[1].y = y2 + scaled_a_size; points[2].x = x2 + scaled_a_size; points[2].y = y2 - scaled_a_size; } // setup the arrow head points points[0].x = x2; // first point is end of the line points[0].y = y2; // select the color for the arrow head int cnt = 255 - ((int)(250.0*scale_val)); cnt = cnt &0xfffffffe; // make sure we have an even number // (?) int color; color = gdImageColorResolve(im, cnt, cnt, cnt); // if (cnt < 0) { // color = gdImageColorResolve(im, 0, 255+cnt, (cnt*-1)); // } else { // color = gdImageColorResolve(im, cnt, 255-cnt, 0); // } // draw the arrowhead first (why not) gdImageFilledPolygon(im, points, 3, color); // then the line gdImageSetThickness(im, thick); gdImageLine(im, x1, y1, x2, y2, color); }
void doFilledPolygon(FILE *stream) { gdPoint points[10]; int n, i, c; n = getNumber(stream); for (i = 0; i < n; i++) { points[i].x = viewx(getNumber(stream)); points[i].y = viewy(getNumber(stream)); } c = getColor(getNumber(stream)); gdImageFilledPolygon(image, points, n, c); }
result_t Image::filledPolygon(v8::Local<v8::Array> points, int32_t color) { if (!m_image) return CHECK_ERROR(CALL_E_INVALID_CALL); std::vector < gdPoint > pts; result_t hr = getPoints(points, pts); if (hr < 0) return hr; gdImageFilledPolygon(m_image, pts.data(), (int32_t) pts.size(), color); return 0; }
static void fill_polygon(PLStream *pls) { png_Dev *dev=(png_Dev *)pls->dev; int i; gdPoint *points=NULL; if (pls->dev_npts < 1) return; points = malloc((size_t)pls->dev_npts * sizeof(gdPoint)); for (i = 0; i < pls->dev_npts; i++) { points[i].x = pls->dev_x[i]/dev->scale; points[i].y = dev->pngy - (pls->dev_y[i]/dev->scale); } #if GD2_VERS >= 2 if (dev->smooth==1) { gdImageSetAntiAliased(dev->im_out,dev->colour); gdImageFilledPolygon(dev->im_out, points, pls->dev_npts, gdAntiAliased); } else { gdImageFilledPolygon(dev->im_out, points, pls->dev_npts, dev->colour); } #else gdImageFilledPolygon(dev->im_out, points, pls->dev_npts, dev->colour); #endif free(points); }
void draw_block(gdImagePtr g, int x, int y, int size, int color) { gdPoint block[4]; block[0].x = x; block[0].y = y; block[1].x = x + size; block[1].y = y; block[2].x = x + size; block[2].y = y + size; block[3].x = x; block[3].y = y + size; gdImageFilledPolygon(g, block, 4, color); }
void gdoFilledTriangle(struct ADrawTag *ctx, unsigned int x1, unsigned int y1, unsigned int x2, unsigned int y2, unsigned int x3, unsigned int y3) { gdPoint p[3]; p[0].x = x1; p[0].y = y1; p[1].x = x2; p[1].y = y2; p[2].x = x3; p[2].y = y3; gdImageFilledPolygon(getGdoImg(ctx), p, 3, getGdoPen(ctx)); }
void doArrow(FILE *stream) { float x1, y1, x2, y2; int vx, vy, size, c; gdPoint triangle[3]; x1 = getFloat(stream); y1 = getFloat(stream); x2 = getFloat(stream); y2 = getFloat(stream); size = getNumber(stream); c = getColor(getNumber(stream)); vx = viewx(x2); vy = viewy(y2); triangle[0].x = vx; triangle[0].y = vy; gdImageLine(image, viewx(x1), viewy(y1), vx, vy, c); if (y1 == y2) { if (x2 > x1) { /* horizontal, pointing right */ triangle[1].x = vx - size; triangle[1].y = vy - size; triangle[2].x = vx - size; triangle[2].y = vy + size; } else { /* horizontal, pointing left */ triangle[1].x = vx + size; triangle[1].y = vy - size; triangle[2].x = vx + size; triangle[2].y = vy + size; } } else { if (y2 > y1) { /* vertical, pointing up */ triangle[1].x = vx - size; triangle[1].y = vy - size; triangle[2].x = vx + size; triangle[2].y = vy - size; } else { /* horizontal, pointing left */ triangle[1].x = vx - size; triangle[1].y = vy + size; triangle[2].x = vx + size; triangle[2].y = vy + size; } } gdImageFilledPolygon(image, triangle, 3, c); }
gdImagePtr renderDrawing(ei::DnaDrawing *d) { // make new image, true color, with alpha support gdImagePtr img = 0; img = gdImageCreateTrueColor(ei::Tools::maxWidth, ei::Tools::maxHeight); if (0 == img) { std::cout << "Could not create image" << std::endl; return 0; } gdImageAlphaBlending(img, 1); int black = gdTrueColor(0,0,0); // also acts as background // render image: // * for each polygon: ei::DnaPolygonList *polys = d->polygons(); ei::DnaPolygonList::iterator iter; for (iter = polys->begin(); iter != polys->end(); iter++) { ei::DnaPolygon *poly = *iter; // ** allocate its color & alpha ei::DnaBrush *brush = poly->brush(); int color = gdTrueColorAlpha(brush->r, brush->g, brush->b, brush->a); // ** render a closed polygon: // *** make array of gdPoints ei::DnaPointList *points = poly->points(); gdPoint gdPts[points->size()]; // *** translate points ei::DnaPointList::iterator eachPt; for (int i=0; i < points->size(); i++) { gdPts[i].x = (*points)[i]->x; gdPts[i].y = (*points)[i]->y; } // *** render via gdImageFilledPolygon(). gdImageFilledPolygon(img, gdPts, points->size(), color); } return img; }
int GIFoutputGraphic(Metafile *mf, int num, Gint code, Gint num_pt, Gpoint *pos) { int imf; mf_cgmo **cgmo = &mf->cgmo; for (imf = 0; imf < num; ++imf) { Gint i; GIFmetafile *meta = find_meta(cgmo[imf]); assert(meta); assert(num_pt > 0); meta->resize = 0; /* Not OK to resize */ /* Trivial accept and reject clipping of points. */ { int xlo = 1, xhi = 1, yhi = 1, ylo = 1; Gfloat lolimit = -1, hilimit = 2; int i; for (i=1; i < num_pt; ++i){ float x = pos[i].x; float y = pos[i].y; xlo &= (x < lolimit); xhi &= (x > hilimit); ylo &= (y < lolimit); yhi &= (y > hilimit); } if (xlo || xhi || ylo || yhi) return OK; /* If any points are extreme, toss the polygon. Someday, there will be a real clipping algorithm */ for (i=1; i < num_pt; ++i){ float x = pos[i].x; float y = pos[i].y; if (x < -10. || x > 10. || y < -10 || y > 10){ msgWarn("GIFoutputGraphic: Bad NDC point %f %f\n", x, y); return OK; } } } switch(code){ case GKSM_FILL_AREA: { gdPointPtr tpts = (gdPointPtr)umalloc(sizeof(gdPoint) * num_pt); assert(tpts); xform(meta, pos->x, pos->y, &tpts[0].x, &tpts[0].y); #ifdef DEBUG printf("--------------------------------------\n"); printf("Transform: (%f, %f) -> (%d,%d)\n", pos->x, pos->y, tpts[0].x, tpts[0].y); #endif ++pos; for (i=1; i < num_pt; ++i, ++pos){ xform(meta, pos->x, pos->y, &tpts[i].x, &tpts[i].y); #ifdef DEBUG printf("Transform: (%f, %f) -> (%d,%d)\n", pos->x, pos->y, tpts[i].x, tpts[i].y); #endif } if (meta->fillStyleIndex == 0){ gdImagePolygon(meta->image, tpts, num_pt, meta->fillIndex); } else { /* Eliminate colinear points (bug in gd.c) */ stripColinear(tpts, &num_pt); gdImageFilledPolygon(meta->image, tpts, num_pt, meta->fillIndex); } free(tpts); } break; case GKSM_POLYLINE: { int lineIndex = meta->styleIndex == 1 ? meta->lineIndex : gdStyled; gdPointPtr tpts = (gdPointPtr)umalloc(sizeof(gdPoint) * num_pt); assert(tpts); for (i=0; i < num_pt; ++i, ++pos){ xform(meta, pos->x, pos->y, &tpts[i].x, &tpts[i].y); } gdImageWideLines(meta->image, tpts, num_pt, lineIndex, meta->lineWidth); free(tpts); } break; case GKSM_POLYMARKER: msgWarn("GIFoutputGraphics: polymarker unsupported\n"); break; default: msgWarn("GIFoutputGraphics: Unknown code %d\n", code); } } return OK; }
static void vrml_polygon(GVJ_t *job, pointf * A, int np, int filled) { FILE *out = job->output_file; obj_state_t *obj = job->obj; node_t *n; edge_t *e; double z = obj->z; pointf p, mp; gdPoint *points; int i, pen; gdImagePtr brush = NULL; double theta; switch (obj->type) { case ROOTGRAPH_OBJTYPE: fprintf(out, " Background { skyColor %.3f %.3f %.3f }\n", obj->fillcolor.u.rgba[0] / 255., obj->fillcolor.u.rgba[1] / 255., obj->fillcolor.u.rgba[2] / 255.); Saw_skycolor = TRUE; break; case CLUSTER_OBJTYPE: break; case NODE_OBJTYPE: n = obj->u.n; pen = set_penstyle(job, im, brush); points = N_GNEW(np, gdPoint); for (i = 0; i < np; i++) { mp = vrml_node_point(job, n, A[i]); points[i].x = ROUND(mp.x); points[i].y = ROUND(mp.y); } if (filled) gdImageFilledPolygon(im, points, np, color_index(im, obj->fillcolor)); gdImagePolygon(im, points, np, pen); free(points); if (brush) gdImageDestroy(brush); fprintf(out, "Shape {\n"); fprintf(out, " appearance Appearance {\n"); fprintf(out, " material Material {\n"); fprintf(out, " ambientIntensity 0.33\n"); fprintf(out, " diffuseColor 1 1 1\n"); fprintf(out, " }\n"); fprintf(out, " texture ImageTexture { url \"node%d.png\" }\n", n->id); fprintf(out, " }\n"); fprintf(out, " geometry Extrusion {\n"); fprintf(out, " crossSection ["); for (i = 0; i < np; i++) { p.x = A[i].x - ND_coord_i(n).x; p.y = A[i].y - ND_coord_i(n).y; fprintf(out, " %.3f %.3f,", p.x, p.y); } p.x = A[0].x - ND_coord_i(n).x; p.y = A[0].y - ND_coord_i(n).y; fprintf(out, " %.3f %.3f ]\n", p.x, p.y); fprintf(out, " spine [ %d %d %.3f, %d %d %.3f ]\n", ND_coord_i(n).x, ND_coord_i(n).y, z - .01, ND_coord_i(n).x, ND_coord_i(n).y, z + .01); fprintf(out, " }\n"); fprintf(out, "}\n"); break; case EDGE_OBJTYPE: e = obj->u.e; if (np != 3) { static int flag; if (!flag) { flag++; agerr(AGWARN, "vrml_polygon: non-triangle arrowheads not supported - ignoring\n"); } } if (IsSegment) { doArrowhead (job, A); return; } p.x = p.y = 0.0; for (i = 0; i < np; i++) { p.x += A[i].x; p.y += A[i].y; } p.x = p.x / np; p.y = p.y / np; /* it is bad to know that A[1] is the aiming point, but we do */ theta = atan2((A[0].y + A[2].y) / 2.0 - A[1].y, (A[0].x + A[2].x) / 2.0 - A[1].x) + M_PI / 2.0; /* this is gruesome, but how else can we get z coord */ if (DIST2(p, ND_coord_i(e->tail)) < DIST2(p, ND_coord_i(e->head))) z = obj->tail_z; else z = obj->head_z; /* FIXME: arrow vector ought to follow z coord of bezier */ fprintf(out, "Transform {\n"); fprintf(out, " translation %.3f %.3f %.3f\n", p.x, p.y, z); fprintf(out, " children [\n"); fprintf(out, " Transform {\n"); fprintf(out, " rotation 0 0 1 %.3f\n", theta); fprintf(out, " children [\n"); fprintf(out, " Shape {\n"); fprintf(out, " geometry Cone {bottomRadius %.3f height %.3f }\n", obj->penwidth * 2.5, obj->penwidth * 10.0); fprintf(out, " appearance USE E%d\n", e->id); fprintf(out, " }\n"); fprintf(out, " ]\n"); fprintf(out, " }\n"); fprintf(out, " ]\n"); fprintf(out, "}\n"); break; } }
void gdImageFilledArc (gdImagePtr im, int cx, int cy, int width, int height, int s, int e, int color, int style) { gdPoint pt[7]; gdPoint axis_pt[4]; int angle; int have_s = 0; int have_e = 0; int flip_x = 0; int flip_y = 0; int conquer = 0; int i; int a; int b; int x; int y; long s_sin = 0; long s_cos = 0; long e_sin = 0; long e_cos = 0; long w; /* a * 2 */ long h; /* b * 2 */ long x2; /* x * 2 */ long y2; /* y * 2 */ long lx2; /* x * 2 (line) */ long ly2; /* y * 2 (line) */ long ws; /* (a * 2)^2 */ long hs; /* (b * 2)^2 */ long whs; /* (a * 2)^2 * (b * 2)^2 */ long g; /* decision variable */ long lg; /* decision variable (line) */ width = (width & 1) ? (width + 1) : (width); height = (height & 1) ? (height + 1) : (height); a = width / 2; b = height / 2; axis_pt[0].x = a; axis_pt[0].y = 0; axis_pt[1].x = 0; axis_pt[1].y = b; axis_pt[2].x = -a; axis_pt[2].y = 0; axis_pt[3].x = 0; axis_pt[3].y = -b; if (s == e) return; if ((e - s) >= 360) { s = 0; e = 0; } while (s < 0) s += 360; while (s >= 360) s -= 360; while (e < 0) e += 360; while (e >= 360) e -= 360; if (e <= s) e += 360; /* I'm assuming a chord-rule at the moment. Need to add origin to get a * pie-rule, but will need to set chord-rule before recursion... */ for (i = 0; i < 4; i++) { if ((s < (i + 1) * 90) && (e > (i + 1) * 90)) { gdImageFilledArc (im, cx, cy, width, height, s, (i + 1) * 90, color, gdChord); pt[0] = gdArcClosest (width, height, s); pt[0].x += cx; pt[0].y += cy; pt[1].x = cx + axis_pt[(i + 1) & 3].x; pt[1].y = cy + axis_pt[(i + 1) & 3].y; if (e <= (i + 2) * 90) { gdImageFilledArc (im, cx, cy, width, height, (i + 1) * 90, e, color, gdChord); pt[2] = gdArcClosest (width, height, e); pt[2].x += cx; pt[2].y += cy; if (style == gdChord) { gdImageFilledPolygon (im, pt, 3, color); gdImagePolygon (im, pt, 3, color); } else if (style == gdPie) { pt[3].x = cx; pt[3].y = cy; gdImageFilledPolygon (im, pt, 4, color); gdImagePolygon (im, pt, 4, color); } } else { gdImageFilledArc (im, cx, cy, width, height, (i + 1) * 90, (i + 2) * 90, color, gdChord); pt[2].x = cx + axis_pt[(i + 2) & 3].x; pt[2].y = cy + axis_pt[(i + 2) & 3].y; if (e <= (i + 3) * 90) { gdImageFilledArc (im, cx, cy, width, height, (i + 2) * 90, e, color, gdChord); pt[3] = gdArcClosest (width, height, e); pt[3].x += cx; pt[3].y += cy; if (style == gdChord) { gdImageFilledPolygon (im, pt, 4, color); gdImagePolygon (im, pt, 4, color); } else if (style == gdPie) { pt[4].x = cx; pt[4].y = cy; gdImageFilledPolygon (im, pt, 5, color); gdImagePolygon (im, pt, 5, color); } } else { gdImageFilledArc (im, cx, cy, width, height, (i + 2) * 90, (i + 3) * 90, color, gdChord); pt[3].x = cx + axis_pt[(i + 3) & 3].x; pt[3].y = cy + axis_pt[(i + 3) & 3].y; if (e <= (i + 4) * 90) { gdImageFilledArc (im, cx, cy, width, height, (i + 3) * 90, e, color, gdChord); pt[4] = gdArcClosest (width, height, e); pt[4].x += cx; pt[4].y += cy; if (style == gdChord) { gdImageFilledPolygon (im, pt, 5, color); gdImagePolygon (im, pt, 5, color); } else if (style == gdPie) { pt[5].x = cx; pt[5].y = cy; gdImageFilledPolygon (im, pt, 6, color); gdImagePolygon (im, pt, 6, color); } } else { gdImageFilledArc (im, cx, cy, width, height, (i + 3) * 90, (i + 4) * 90, color, gdChord); pt[4].x = cx + axis_pt[(i + 4) & 3].x; pt[4].y = cy + axis_pt[(i + 4) & 3].y; gdImageFilledArc (im, cx, cy, width, height, (i + 4) * 90, e, color, gdChord); pt[5] = gdArcClosest (width, height, e); pt[5].x += cx; pt[5].y += cy; if (style == gdChord) { gdImageFilledPolygon (im, pt, 6, color); gdImagePolygon (im, pt, 6, color); } else if (style == gdPie) { pt[6].x = cx; pt[6].y = cy; gdImageFilledPolygon (im, pt, 7, color); gdImagePolygon (im, pt, 7, color); } } } } return; } } /* At this point we have only arcs that lies within a quadrant - * map this to first quadrant... */ if ((s >= 90) && (e <= 180)) { angle = s; s = 180 - e; e = 180 - angle; flip_x = 1; } if ((s >= 180) && (e <= 270)) { s = s - 180; e = e - 180; flip_x = 1; flip_y = 1; } if ((s >= 270) && (e <= 360)) { angle = s; s = 360 - e; e = 360 - angle; flip_y = 1; } if (s == 0) { s_sin = 0; s_cos = (long) ((double) 32768); } else { s_sin = (long) ((double) 32768 * sin ((double) s * M_PI / (double) 180)); s_cos = (long) ((double) 32768 * cos ((double) s * M_PI / (double) 180)); } if (e == 0) { e_sin = (long) ((double) 32768); e_cos = 0; } else { e_sin = (long) ((double) 32768 * sin ((double) e * M_PI / (double) 180)); e_cos = (long) ((double) 32768 * cos ((double) e * M_PI / (double) 180)); } w = (long) width; h = (long) height; ws = w * w; hs = h * h; whs = 1; while ((ws > 32768) || (hs > 32768)) { ws = (ws + 1) / 2; /* Unfortunate limitations on integers makes */ hs = (hs + 1) / 2; /* drawing large ellipses problematic... */ whs *= 2; } while ((ws * hs) > (0x04000000L / whs)) { ws = (ws + 1) / 2; hs = (hs + 1) / 2; whs *= 2; } whs *= ws * hs; pt[0].x = w / 2; pt[0].y = 0; pt[2].x = 0; pt[2].y = h / 2; have_s = 0; have_e = 0; if (s == 0) have_s = 1; if (e == 90) have_e = 1; x2 = w; y2 = 0; /* Starting point is exactly on ellipse */ g = x2 - 1; g = g * g * hs + 4 * ws - whs; while ((x2 * hs) > (y2 * ws)) /* Keep |tangent| > 1 */ { y2 += 2; g += ws * 4 * (y2 + 1); if (g > 0) /* Need to drop */ { x2 -= 2; g -= hs * 4 * x2; } if ((have_s == 0) && ((s_sin * x2) <= (y2 * s_cos))) { pt[0].x = (int) (x2 / 2); pt[0].y = (int) (y2 / 2); have_s = 1; } if ((have_e == 0) && ((e_sin * x2) <= (y2 * e_cos))) { pt[2].x = (int) (x2 / 2); pt[2].y = (int) (y2 / 2); have_e = 1; } } pt[1].x = (int) (x2 / 2); pt[1].y = (int) (y2 / 2); x2 = 0; y2 = h; /* Starting point is exactly on ellipse */ g = y2 - 1; g = g * g * ws + 4 * hs - whs; while ((x2 * hs) < (y2 * ws)) { x2 += 2; g += hs * 4 * (x2 + 1); if (g > 0) /* Need to drop */ { y2 -= 2; g -= ws * 4 * y2; } if ((have_s == 0) && ((s_sin * x2) >= (y2 * s_cos))) { pt[0].x = (int) (x2 / 2); pt[0].y = (int) (y2 / 2); have_s = 1; } if ((have_e == 0) && ((e_sin * x2) >= (y2 * e_cos))) { pt[2].x = (int) (x2 / 2); pt[2].y = (int) (y2 / 2); have_e = 1; } } if ((have_s == 0) || (have_e == 0)) return; /* Bizarre case */ if (style == gdPie) { pt[3] = pt[0]; pt[4] = pt[1]; pt[5] = pt[2]; pt[0].x = cx + (flip_x ? (-pt[0].x) : pt[0].x); pt[0].y = cy + (flip_y ? (-pt[0].y) : pt[0].y); pt[1].x = cx; pt[1].y = cy; pt[2].x = cx + (flip_x ? (-pt[2].x) : pt[2].x); pt[2].y = cy + (flip_y ? (-pt[2].y) : pt[2].y); gdImageFilledPolygon (im, pt, 3, color); gdImagePolygon (im, pt, 3, color); pt[0] = pt[3]; pt[1] = pt[4]; pt[2] = pt[5]; } if (((s_cos * hs) > (s_sin * ws)) && ((e_cos * hs) < (e_sin * ws))) { /* the points are on different parts of the curve... * this is too tricky to try to handle, so divide and conquer: */ pt[3] = pt[0]; pt[4] = pt[1]; pt[5] = pt[2]; pt[0].x = cx + (flip_x ? (-pt[0].x) : pt[0].x); pt[0].y = cy + (flip_y ? (-pt[0].y) : pt[0].y); pt[1].x = cx + (flip_x ? (-pt[1].x) : pt[1].x); pt[1].y = cy + (flip_y ? (-pt[1].y) : pt[1].y); pt[2].x = cx + (flip_x ? (-pt[2].x) : pt[2].x); pt[2].y = cy + (flip_y ? (-pt[2].y) : pt[2].y); gdImageFilledPolygon (im, pt, 3, color); gdImagePolygon (im, pt, 3, color); pt[0] = pt[3]; pt[2] = pt[4]; conquer = 1; } if (conquer || (((s_cos * hs) > (s_sin * ws)) && ((e_cos * hs) > (e_sin * ws)))) { /* This is the best bit... */ /* steep line + ellipse */ /* go up & left from pt[0] to pt[2] */ x2 = w; y2 = 0; /* Starting point is exactly on ellipse */ g = x2 - 1; g = g * g * hs + 4 * ws - whs; while ((x2 * hs) > (y2 * ws)) /* Keep |tangent| > 1 */ { if ((s_sin * x2) <= (y2 * s_cos)) break; y2 += 2; g += ws * 4 * (y2 + 1); if (g > 0) /* Need to drop */ { x2 -= 2; g -= hs * 4 * x2; } } lx2 = x2; ly2 = y2; lg = lx2 * (pt[0].y - pt[2].y) - ly2 * (pt[0].x - pt[2].x); lg = (lx2 - 1) * (pt[0].y - pt[2].y) - (ly2 + 2) * (pt[0].x - pt[2].x) - lg; while (y2 < (2 * pt[2].y)) { y2 += 2; g += ws * 4 * (y2 + 1); if (g > 0) /* Need to drop */ { x2 -= 2; g -= hs * 4 * x2; } ly2 += 2; lg -= 2 * (pt[0].x - pt[2].x); if (lg < 0) /* Need to drop */ { lx2 -= 2; lg -= 2 * (pt[0].y - pt[2].y); } y = (int) (y2 / 2); for (x = (int) (lx2 / 2); x <= (int) (x2 / 2); x++) { gdImageSetPixel (im, ((flip_x) ? (cx - x) : (cx + x)), ((flip_y) ? (cy - y) : (cy + y)), color); } } } if (conquer) { pt[0] = pt[4]; pt[2] = pt[5]; } if (conquer || (((s_cos * hs) < (s_sin * ws)) && ((e_cos * hs) < (e_sin * ws)))) { /* This is the best bit... */ /* gradual line + ellipse */ /* go down & right from pt[2] to pt[0] */ x2 = 0; y2 = h; /* Starting point is exactly on ellipse */ g = y2 - 1; g = g * g * ws + 4 * hs - whs; while ((x2 * hs) < (y2 * ws)) { x2 += 2; g += hs * 4 * (x2 + 1); if (g > 0) /* Need to drop */ { y2 -= 2; g -= ws * 4 * y2; } if ((e_sin * x2) >= (y2 * e_cos)) break; } lx2 = x2; ly2 = y2; lg = lx2 * (pt[0].y - pt[2].y) - ly2 * (pt[0].x - pt[2].x); lg = (lx2 + 2) * (pt[0].y - pt[2].y) - (ly2 - 1) * (pt[0].x - pt[2].x) - lg; while (x2 < (2 * pt[0].x)) { x2 += 2; g += hs * 4 * (x2 + 1); if (g > 0) /* Need to drop */ { y2 -= 2; g -= ws * 4 * y2; } lx2 += 2; lg += 2 * (pt[0].y - pt[2].y); if (lg < 0) /* Need to drop */ { ly2 -= 2; lg += 2 * (pt[0].x - pt[2].x); } x = (int) (x2 / 2); for (y = (int) (ly2 / 2); y <= (int) (y2 / 2); y++) { gdImageSetPixel (im, ((flip_x) ? (cx - x) : (cx + x)), ((flip_y) ? (cy - y) : (cy + y)), color); } } } }
/* ======================================================= *\ * PIE * * Notes: * always drawn from 12:00 position clockwise * 'missing' slices don't get labels * sum(val[0], ... val[num_points-1]) is assumed to be 100% \* ======================================================= */ void GDC_out_pie( short IMGWIDTH, short IMGHEIGHT, FILE *img_fptr, /* open file pointer */ GDCPIE_TYPE type, int num_points, char *lbl[], /* data labels */ float val[] ) /* data */ { int i; gdImagePtr im; int BGColor, LineColor, PlotColor, EdgeColor, EdgeColorShd; CREATE_ARRAY1( SliceColor, int, num_points ); /* int SliceColor[num_points] */ CREATE_ARRAY1( SliceColorShd, int, num_points ); /* int SliceColorShd[num_points] */ float rad = 0.0; /* radius */ float ellipsex = 1.0; float ellipsey = 1.0 - (float)GDCPIE_perspective/100.0; float tot_val = 0.0; float pscl; int cx, /* affects PX() */ cy; /* affects PY() */ /* ~ 1% for a size of 100 pixs */ /* label sizes will more dictate this */ float min_grphable = ( GDCPIE_other_threshold < 0? 100.0/(float)MIN(IMGWIDTH,IMGHEIGHT): (float)GDCPIE_other_threshold )/100.0; short num_slices1 = 0, num_slices2 = 0; char any_too_small = FALSE; CREATE_ARRAY1( others, char, num_points ); /* char others[num_points] */ CREATE_ARRAY2( slice_angle, float, 3, num_points ); /* float slice_angle[3][num_points] */ /* must be used with others[] */ char threeD = ( type == GDC_3DPIE ); int xdepth_3D = 0, /* affects PX() */ ydepth_3D = 0; /* affects PY() */ int do3Dx = 0, /* reserved for macro use */ do3Dy = 0; CREATE_ARRAY2( pct_lbl, char, num_points, 16 ); /* sizeof or strlen (GDCPIE_percent_fmt)? */ CREATE_ARRAY1( pct_ftsz, struct fnt_sz_t, num_points ); /* struct fnt_sz_t lbl_ftsz[num_points] */ CREATE_ARRAY1( lbl_ftsz, struct fnt_sz_t, num_points ); /* struct fnt_sz_t lbl_ftsz[num_points] */ #ifdef HAVE_LIBFREETYPE char *gdcpie_title_font = GDCPIE_title_font; char *gdcpie_label_font = GDCPIE_label_font; double gdcpie_title_ptsize = GDCPIE_title_ptsize; double gdcpie_label_ptsize = GDCPIE_label_ptsize; #else char *gdcpie_title_font = NULL; char *gdcpie_label_font = NULL; double gdcpie_title_ptsize = 0.0; double gdcpie_label_ptsize = 0.0; #endif /* GDCPIE_3d_angle = MOD_360(90-GDCPIE_3d_angle+360); */ pie_3D_rad = TO_RAD( GDCPIE_3d_angle ); xdepth_3D = threeD? (int)( cos((double)MOD_2PI(M_PI_2-pie_3D_rad+2.0*M_PI)) * GDCPIE_3d_depth ): 0; ydepth_3D = threeD? (int)( sin((double)MOD_2PI(M_PI_2-pie_3D_rad+2.0*M_PI)) * GDCPIE_3d_depth ): 0; /* xdepth_3D = threeD? (int)( cos(pie_3D_rad) * GDCPIE_3d_depth ): 0; */ /* ydepth_3D = threeD? (int)( sin(pie_3D_rad) * GDCPIE_3d_depth ): 0; */ load_font_conversions(); /* ----- get total value ----- */ for( i=0; i<num_points; ++i ) tot_val += val[i]; /* ----- pie sizing ----- */ /* ----- make width room for labels, depth, etc.: ----- */ /* ----- determine pie's radius ----- */ { int title_hgt = GDCPIE_title? 1 /* title? horizontal text line */ + GDCfnt_sz( GDCPIE_title, GDCPIE_title_size, gdcpie_title_font, gdcpie_title_ptsize, 0.0, NULL ).h + 2: 0; float last = 0.0; float label_explode_limit = 0.0; int cheight, cwidth; /* maximum: no labels, explosions */ /* gotta start somewhere */ rad = (float)MIN( (IMGWIDTH/2)/ellipsex-(1+ABS(xdepth_3D)), (IMGHEIGHT/2)/ellipsey-(1+ABS(ydepth_3D))-title_hgt ); /* ok fix center, i.e., no floating re labels, explosion, etc. */ cx = IMGWIDTH/2 /* - xdepth_3D */ ; cy = (IMGHEIGHT-title_hgt)/2 + title_hgt /* + ydepth_3D */ ; cheight = (IMGHEIGHT- title_hgt)/2 /* - ydepth_3D */ ; cwidth = cx; /* walk around pie. determine spacing to edge */ for( i=0; i<num_points; ++i ) { float this_pct = val[i]/tot_val; /* should never be > 100% */ float this = this_pct*(2.0*M_PI); /* pie-portion */ if( (this_pct > min_grphable) || /* too small */ (!GDCPIE_missing || !GDCPIE_missing[i]) ) /* still want angles */ { int this_explode = GDCPIE_explode? GDCPIE_explode[i]: 0; double this_sin; double this_cos; slice_angle[0][i] = this/2.0+last; /* mid-point on full pie */ slice_angle[1][i] = last; /* 1st on full pie */ slice_angle[2][i] = this+last; /* 2nd on full pie */ this_sin = ellipsex*sin( (double)slice_angle[0][i] ); this_cos = ellipsey*cos( (double)slice_angle[0][i] ); if( !GDCPIE_missing || !(GDCPIE_missing[i]) ) { short lbl_wdth = 0, lbl_hgt = 0; float this_y_explode_limit, this_x_explode_limit; /* start slice label height, width */ /* accounting for PCT placement, font */ pct_ftsz[i].h = 0; pct_ftsz[i].w = 0; if( GDCPIE_percent_fmt && GDCPIE_percent_labels != GDCPIE_PCT_NONE ) { sprintf( pct_lbl[i], GDCPIE_percent_fmt, this_pct * 100.0 ); pct_ftsz[i] = GDCfnt_sz( pct_lbl[i], GDCPIE_label_size, gdcpie_label_font, gdcpie_label_ptsize, 0.0, NULL ); lbl_wdth = pct_ftsz[i].w; lbl_hgt = pct_ftsz[i].h; } if( lbl && lbl[i] ) { lbl_ftsz[i] = GDCfnt_sz( lbl[i], GDCPIE_label_size, gdcpie_label_font, gdcpie_label_ptsize, 0.0, NULL ); if( GDCPIE_percent_labels == GDCPIE_PCT_ABOVE || GDCPIE_percent_labels == GDCPIE_PCT_BELOW ) { lbl_wdth = MAX( pct_ftsz[i].w, lbl_ftsz[i].w ); lbl_hgt = pct_ftsz[i].h + lbl_ftsz[i].h + 1; } else if( GDCPIE_percent_labels == GDCPIE_PCT_RIGHT || GDCPIE_percent_labels == GDCPIE_PCT_LEFT ) { lbl_wdth = pct_ftsz[i].w + lbl_ftsz[i].w + 1; lbl_hgt = MAX( pct_ftsz[i].h, lbl_ftsz[i].h ); } else /* GDCPIE_PCT_NONE */ { lbl_wdth = lbl_ftsz[i].w; lbl_hgt = lbl_ftsz[i].h; } } else lbl_wdth = lbl_hgt = 0; /* end label height, width */ /* diamiter limited by this point's: explosion, label */ /* (radius to box @ slice_angle) - (explode) - (projected label size) */ /* radius constraint due to labels */ this_y_explode_limit = (float)this_cos==0.0? FLT_MAX: ( (float)( (double)cheight/ABS(this_cos) ) - (float)( this_explode + (lbl&&lbl[i]? GDCPIE_label_dist: 0) ) - (float)( lbl_hgt/2 ) / (float)ABS(this_cos) ); this_x_explode_limit = (float)this_sin==0.0? FLT_MAX: ( (float)( (double)cwidth/ABS(this_sin) ) - (float)( this_explode + (lbl&&lbl[i]? GDCPIE_label_dist: 0) ) - (float)( lbl_wdth ) / (float)ABS(this_sin) ); rad = MIN( rad, this_y_explode_limit ); rad = MIN( rad, this_x_explode_limit ); /* ok at this radius (which is most likely larger than final) */ /* adjust for inter-label spacing */ /* if( lbl[i] && *lbl[i] ) */ /* { */ /* char which_edge = slice_angle[0][i] > M_PI? +1: -1; // which semi */ /* last_label_yedge = cheight - (int)( (rad + // top or bottom of label */ /* (float)(this_explode + */ /* (float)GDCPIE_label_dist)) * (float)this_cos ) + */ /* ( (GDC_fontc[GDCPIE_label_size].h+1)/2 + */ /* GDC_label_spacing )*which_edge; */ /* } */ /* radius constriant due to exploded depth */ /* at each edge of the slice, and the middle */ /* this is really stupid */ /* this section uses a different algorithm then above, but does the same thing */ /* could be combined, but each is ugly enough! */ /* PROTECT /0 */ if( threeD ) { short j; int this_y_explode_pos; int this_x_explode_pos; /* first N E S W (actually no need for N) */ if( (slice_angle[1][i] < M_PI_2 && M_PI_2 < slice_angle[2][i]) && /* E */ (this_x_explode_pos=OX(i,M_PI_2,1)) > cx+cwidth ) rad -= (float)ABS( (double)(1+this_x_explode_pos-(cx+cwidth))/sin(M_PI_2) ); if( (slice_angle[1][i] < 3.0*M_PI_2 && 3.0*M_PI_2 < slice_angle[2][i]) && /* W */ (this_x_explode_pos=OX(i,3.0*M_PI_2,1)) < cx-cwidth ) rad -= (float)ABS( (double)(this_x_explode_pos-(cx+cwidth))/sin(3.0*M_PI_2) ); if( (slice_angle[1][i] < M_PI && M_PI < slice_angle[2][i]) && /* S */ (this_y_explode_pos=OY(i,M_PI,1)) > cy+cheight ) rad -= (float)ABS( (double)(1+this_y_explode_pos-(cy+cheight))/cos(M_PI) ); for( j=0; j<3; ++j ) { this_y_explode_pos = IY(i,j,1); if( this_y_explode_pos < cy-cheight ) rad -= (float)ABS( (double)((cy-cheight)-this_y_explode_pos)/cos((double)slice_angle[j][i]) ); if( this_y_explode_pos > cy+cheight ) rad -= (float)ABS( (double)(1+this_y_explode_pos-(cy+cheight))/cos((double)slice_angle[j][i]) ); this_x_explode_pos = IX(i,j,1); if( this_x_explode_pos < cx-cwidth ) rad -= (float)ABS( (double)((cx-cwidth)-this_x_explode_pos)/sin((double)slice_angle[j][i]) ); if( this_x_explode_pos > cx+cwidth ) rad -= (float)ABS( (double)(1+this_x_explode_pos-(cx+cwidth))/sin((double)slice_angle[j][i]) ); } } } others[i] = FALSE; } else { others[i] = TRUE; slice_angle[0][i] = -FLT_MAX; } last += this; } } /* ----- go ahead and start the image ----- */ im = gdImageCreate( IMGWIDTH, IMGHEIGHT ); /* --- allocate the requested colors --- */ BGColor = clrallocate( im, GDCPIE_BGColor ); LineColor = clrallocate( im, GDCPIE_LineColor ); PlotColor = clrallocate( im, GDCPIE_PlotColor ); if( GDCPIE_EdgeColor != GDC_NOCOLOR ) { EdgeColor = clrallocate( im, GDCPIE_EdgeColor ); if( threeD ) EdgeColorShd = clrshdallocate( im, GDCPIE_EdgeColor ); } /* --- set color for each slice --- */ for( i=0; i<num_points; ++i ) if( GDCPIE_Color ) { unsigned long slc_clr = GDCPIE_Color[i]; SliceColor[i] = clrallocate( im, slc_clr ); if( threeD ) SliceColorShd[i] = clrshdallocate( im, slc_clr ); } else { SliceColor[i] = PlotColor; if( threeD ) SliceColorShd[i] = clrshdallocate( im, GDCPIE_PlotColor ); } pscl = (2.0*M_PI)/tot_val; /* ----- calc: smallest a slice can be ----- */ /* 1/2 circum / num slices per side. */ /* determined by number of labels that'll fit (height) */ /* scale to user values */ /* ( M_PI / (IMGHEIGHT / (SFONTHGT+1)) ) */ /* min_grphable = tot_val / */ /* ( 2.0 * (float)IMGHEIGHT / (float)(SFONTHGT+1+TFONTHGT+2) ); */ if( threeD ) { /* draw background shaded pie */ { float rad1 = rad * 3.0/4.0; for( i=0; i<num_points; ++i ) if( !(others[i]) && (!GDCPIE_missing || !GDCPIE_missing[i]) ) { int edge_color = GDCPIE_EdgeColor == GDC_NOCOLOR? SliceColorShd[i]: EdgeColorShd; gdImageLine( im, CX(i,1), CY(i,1), IX(i,1,1), IY(i,1,1), edge_color ); gdImageLine( im, CX(i,1), CY(i,1), IX(i,2,1), IY(i,2,1), edge_color ); gdImageArc( im, CX(i,1), CY(i,1), (int)(rad*ellipsex*2.0), (int)(rad*ellipsey*2.0), TO_INT_DEG_FLOOR(slice_angle[1][i])+270, TO_INT_DEG_CEIL(slice_angle[2][i])+270, edge_color ); /* gdImageFilledArc( im, CX(i,1), CY(i,1), */ /* rad*ellipsex*2, rad*ellipsey*2, */ /* TO_INT_DEG_FLOOR(slice_angle[1][i])+270, */ /* TO_INT_DEG_CEIL(slice_angle[2][i])+270, */ /* SliceColorShd[i], */ /* gdPie ); */ /* attempt to fill, if slice is wide enough */ if( (ABS(IX(i,1,1)-IX(i,2,1)) + ABS(IY(i,1,1)-IY(i,2,1))) > 2 ) { float rad = rad1; /* local override */ gdImageFillToBorder( im, IX(i,0,1), IY(i,0,1), edge_color, SliceColorShd[i] ); } } } /* fill in connection to foreground pie */ /* this is where we earn our keep */ { int t, num_slice_angles = 0; CREATE_ARRAY1( tmp_slice, struct tmp_slice_t, 4*num_points+4 ); /* should only need 2*num_points+2 */ for( i=0; i<num_points; ++i ) if( !GDCPIE_missing || !GDCPIE_missing[i] ) { if( RAD_DIST1(slice_angle[1][i]) < RAD_DIST2(slice_angle[0][i]) ) tmp_slice[num_slice_angles].hidden = FALSE; else tmp_slice[num_slice_angles].hidden = TRUE; tmp_slice[num_slice_angles].i = i; tmp_slice[num_slice_angles].slice = slice_angle[0][i]; tmp_slice[num_slice_angles++].angle = slice_angle[1][i]; if( RAD_DIST1(slice_angle[2][i]) < RAD_DIST2(slice_angle[0][i]) ) tmp_slice[num_slice_angles].hidden = FALSE; else tmp_slice[num_slice_angles].hidden = TRUE; tmp_slice[num_slice_angles].i = i; tmp_slice[num_slice_angles].slice = slice_angle[0][i]; tmp_slice[num_slice_angles++].angle = slice_angle[2][i]; /* identify which 2 slices (i) have a tangent parallel to depth angle */ if( slice_angle[1][i]<MOD_2PI(pie_3D_rad+M_PI_2) && slice_angle[2][i]>MOD_2PI(pie_3D_rad+M_PI_2) ) { tmp_slice[num_slice_angles].i = i; tmp_slice[num_slice_angles].hidden = FALSE; tmp_slice[num_slice_angles].slice = slice_angle[0][i]; tmp_slice[num_slice_angles++].angle = MOD_2PI( pie_3D_rad+M_PI_2 ); } if( slice_angle[1][i]<MOD_2PI(pie_3D_rad+3.0*M_PI_2) && slice_angle[2][i]>MOD_2PI(pie_3D_rad+3.0*M_PI_2) ) { tmp_slice[num_slice_angles].i = i; tmp_slice[num_slice_angles].hidden = FALSE; tmp_slice[num_slice_angles].slice = slice_angle[0][i]; tmp_slice[num_slice_angles++].angle = MOD_2PI( pie_3D_rad+3.0*M_PI_2 ); } } qsort( tmp_slice, num_slice_angles, sizeof(struct tmp_slice_t), ocmpr ); for( t=0; t<num_slice_angles; ++t ) { gdPoint gdp[4]; i = tmp_slice[t].i; gdp[0].x = CX(i,0); gdp[0].y = CY(i,0); gdp[1].x = CX(i,1); gdp[1].y = CY(i,1); gdp[2].x = OX(i,tmp_slice[t].angle,1); gdp[2].y = OY(i,tmp_slice[t].angle,1); gdp[3].x = OX(i,tmp_slice[t].angle,0); gdp[3].y = OY(i,tmp_slice[t].angle,0); if( !(tmp_slice[t].hidden) ) gdImageFilledPolygon( im, gdp, 4, SliceColorShd[i] ); else { rad -= 2.0; /* no peeking */ gdp[0].x = OX(i,slice_angle[0][i],0); gdp[0].y = OY(i,slice_angle[0][i],0); gdp[1].x = OX(i,slice_angle[0][i],1); gdp[1].y = OY(i,slice_angle[0][i],1); rad += 2.0; gdp[2].x = OX(i,slice_angle[1][i],1); gdp[2].y = OY(i,slice_angle[1][i],1); gdp[3].x = OX(i,slice_angle[1][i],0); gdp[3].y = OY(i,slice_angle[1][i],0); gdImageFilledPolygon( im, gdp, 4, SliceColorShd[i] ); gdp[2].x = OX(i,slice_angle[2][i],1); gdp[2].y = OY(i,slice_angle[2][i],1); gdp[3].x = OX(i,slice_angle[2][i],0); gdp[3].y = OY(i,slice_angle[2][i],0); gdImageFilledPolygon( im, gdp, 4, SliceColorShd[i] ); } if( GDCPIE_EdgeColor != GDC_NOCOLOR ) { gdImageLine( im, CX(i,0), CY(i,0), CX(i,1), CY(i,1), EdgeColorShd ); gdImageLine( im, OX(i,tmp_slice[t].angle,0), OY(i,tmp_slice[t].angle,0), OX(i,tmp_slice[t].angle,1), OY(i,tmp_slice[t].angle,1), EdgeColorShd ); } } FREE_ARRAY1( tmp_slice ); } } /* ----- pie face ----- */ { /* float last = 0.0; */ float rad1 = rad * 3.0/4.0; for( i=0; i<num_points; ++i ) if( !others[i] && (!GDCPIE_missing || !GDCPIE_missing[i]) ) { int edge_color = GDCPIE_EdgeColor == GDC_NOCOLOR? SliceColor[i]: EdgeColorShd; /* last += val[i]; */ /* EXPLODE_CX_CY( slice_angle[0][i], i ); */ gdImageLine( im, CX(i,0), CY(i,0), IX(i,1,0), IY(i,1,0), edge_color ); gdImageLine( im, CX(i,0), CY(i,0), IX(i,2,0), IY(i,2,0), edge_color ); gdImageArc( im, CX(i,0), CY(i,0), (int)(rad*ellipsex*2.0), (int)(rad*ellipsey*2.0), (TO_INT_DEG_FLOOR(slice_angle[1][i])+270)%360, (TO_INT_DEG_CEIL(slice_angle[2][i])+270)%360, edge_color ); /* antialiasing here */ /* likely only on the face? */ /* bugs in gd2.0.0 */ /* arc doesn't honor deg>360 */ /* arcs from gdImageFilledArc() don't match with gdImageArc() */ /* angles are off */ /* doesn't always fill completely */ /* gdImageFilledArc( im, CX(i,0), CY(i,0), */ /* (int)(rad*ellipsex*2.0), (int)(rad*ellipsey*2.0), */ /* (TO_INT_DEG_FLOOR(slice_angle[1][i])+270)%360, */ /* (TO_INT_DEG_CEIL(slice_angle[2][i])+270)%360, */ /* SliceColor[i], */ /* gdPie ); */ /* attempt to fill, if slice is wide enough */ { float rad = rad1; /* local override */ if( (ABS(IX(i,1,1)-IX(i,2,1)) + ABS(IY(i,1,1)-IY(i,2,1))) > 2 ) { gdImageFillToBorder( im, IX(i,0,0), IY(i,0,0), edge_color, SliceColor[i] ); } /* catch missed pixels on narrow slices */ gdImageLine( im, CX(i,0), CY(i,0), IX(i,0,0), IY(i,0,0), SliceColor[i] ); } } } if( GDCPIE_title ) { struct fnt_sz_t tftsz = GDCfnt_sz( GDCPIE_title, GDCPIE_title_size, gdcpie_title_font, gdcpie_title_ptsize, 0.0, NULL ); GDCImageStringNL( im, &GDC_fontc[GDCPIE_title_size], gdcpie_title_font, gdcpie_title_ptsize, 0.0, IMGWIDTH/2 - tftsz.w/2, 1, GDCPIE_title, LineColor, GDC_JUSTIFY_CENTER, NULL ); } /* labels */ if( lbl ) { float liner = rad; rad += GDCPIE_label_dist; for( i=0; i<num_points; ++i ) { if( !others[i] && (!GDCPIE_missing || !GDCPIE_missing[i]) ) { int lblx, pctx, lbly, pcty, linex, liney; lbly = (liney = IY(i,0,0))-lbl_ftsz[i].h / 2; lblx = pctx = linex = IX(i,0,0); if( slice_angle[0][i] > M_PI ) /* which semicircle */ { lblx -= lbl_ftsz[i].w; pctx = lblx; ++linex; } else --linex; switch( GDCPIE_percent_labels ) { case GDCPIE_PCT_LEFT: if( slice_angle[0][i] > M_PI ) pctx -= lbl_ftsz[i].w-1; else lblx += pct_ftsz[i].w+1; pcty = IY(i,0,0) - ( 1+pct_ftsz[i].h ) / 2; break; case GDCPIE_PCT_RIGHT: if( slice_angle[0][i] > M_PI ) lblx -= pct_ftsz[i].w-1; else pctx += lbl_ftsz[i].w+1; pcty = IY(i,0,0) - ( 1+pct_ftsz[i].h ) / 2; break; case GDCPIE_PCT_ABOVE: lbly += (1+pct_ftsz[i].h) / 2; pcty = lbly - pct_ftsz[i].h; break; case GDCPIE_PCT_BELOW: lbly -= (1+pct_ftsz[i].h) / 2; pcty = lbly + lbl_ftsz[i].h; break; case GDCPIE_PCT_NONE: default:; } if( GDCPIE_percent_labels != GDCPIE_PCT_NONE ) GDCImageStringNL( im, &GDC_fontc[GDCPIE_label_size], gdcpie_label_font, gdcpie_label_ptsize, 0.0, slice_angle[0][i] <= M_PI? pctx: pctx+lbl_ftsz[i].w-pct_ftsz[i].w, pcty, pct_lbl[i], LineColor, GDC_JUSTIFY_CENTER, NULL ); if( lbl[i] ) GDCImageStringNL( im, &GDC_fontc[GDCPIE_label_size], gdcpie_label_font, gdcpie_label_ptsize, 0.0, lblx, lbly, lbl[i], LineColor, slice_angle[0][i] <= M_PI? GDC_JUSTIFY_LEFT: GDC_JUSTIFY_RIGHT, NULL ); if( GDCPIE_label_line ) { float rad = liner; gdImageLine( im, linex, liney, IX(i,0,0), IY(i,0,0), LineColor ); } } } rad -= GDCPIE_label_dist; } fflush( img_fptr ); switch( GDC_image_type ) { #ifdef HAVE_JPEG case GDC_JPEG: gdImageJpeg( im, img_fptr, GDC_jpeg_quality ); break; #endif case GDC_WBMP: gdImageWBMP( im, PlotColor, img_fptr ); break; case GDC_GIF: gdImageGif( im, img_fptr); break; case GDC_PNG: default: gdImagePng( im, img_fptr ); } FREE_ARRAY1( lbl_ftsz ); FREE_ARRAY1( pct_ftsz ); FREE_ARRAY2( pct_lbl ); FREE_ARRAY2( slice_angle ); FREE_ARRAY1( others ); FREE_ARRAY1( SliceColorShd ); FREE_ARRAY1( SliceColor ); gdImageDestroy(im); return; }
void CarApp::draw_buttons(int selection) { logger->log(DEBUG, "CarApp::draw_buttons", "start"); int i, top, col, blue; gdPoint points[3]; int brect[8]; int white = gdTrueColor(255,255,255); char *font = conf->get_value("font"); col = gdTrueColor(64,64,198); blue = gdTrueColor(64,64,198); for(i=0; i<6; i++) { top = i * button_height; if (i == selection) col = gdTrueColor(100, 110, 216); else col = gdTrueColor(57, 76, 116); /* special colors for the mute button) */ if (sound->is_mute() && (i == MUTE) && (i != selection)) col = gdTrueColor(200, 94, 94); else if (sound->is_mute() && (i == MUTE) && (i == selection)) col = gdTrueColor(255, 120, 120); gdImageFilledRectangle(fb->img, 1, top+1, button_width - 2, top + button_height - 2, col); if (i == MUTE) { gdImageStringFT(fb->img, &brect[0], white, font, 14, 0.0, 20, 45, "Mute"); } else if (i == UP) { col = gdTrueColor(180, 60, 60); points[0].x = MARGIN + (button_width / 2); points[0].y = top + 20; points[1].x = MARGIN + 20; points[1].y = top + button_height - 20; points[2].x = MARGIN + button_width - 20; points[2].y = top + button_height - 20; gdImageFilledPolygon(fb->img, points, 3, col); gdImagePolygon(fb->img, points, 3, 0); } else if (i ==DOWN) { col = gdTrueColor(180, 60, 60); points[0].x = MARGIN + 20; points[0].y = top + 20; points[1].x = MARGIN + button_width - 20; points[1].y = top + 20; points[2].x = MARGIN + (button_width / 2); points[2].y = top + button_height - 20; gdImageFilledPolygon(fb->img, points, 3, col); gdImagePolygon(fb->img, points, 3, 0); } else if (i == RIGHT) { col = gdTrueColor(100, 160, 100); points[0].x = MARGIN + 20; points[0].y = top + 20; points[1].x = MARGIN + button_width - 20; points[1].y = top + (button_height) / 2; points[2].x = MARGIN + 20; points[2].y = top + button_height - 20; gdImageFilledPolygon(fb->img, points, 3, col); gdImagePolygon(fb->img, points, 3, 0); } else if (i == LEFT) { col = gdTrueColor(100, 160, 100); points[0].x = MARGIN + button_width - 20; points[0].y = top + 20; points[1].x = MARGIN + 20; points[1].y = top + (button_height) / 2; points[2].x = MARGIN + button_width - 20; points[2].y = top + button_height - 20; gdImageFilledPolygon(fb->img, points, 3, col); gdImagePolygon(fb->img, points, 3, 0); } else if (i == MENU) { gdImageStringFT(fb->img, &brect[0], white, font, 14, 0.0, 17, 445, "Menu"); } } fb->update(0, 0, button_width, fb->height-1); logger->log(DEBUG, "CarApp::draw_buttons", "end"); }
int main (void) { #ifdef HAVE_LIBPNG /* Input and output files */ FILE *in; FILE *out; /* Input and output images */ gdImagePtr im_in = 0, im_out = 0; /* Brush image */ gdImagePtr brush; /* Color indexes */ int white; int blue; int red; int green; /* Points for polygon */ gdPoint points[3]; int i; /* Create output image, in true color. */ im_out = gdImageCreateTrueColor (256 + 384, 384); /* 2.0.2: first color allocated would automatically be background in a palette based image. Since this is a truecolor image, with an automatic background of black, we must fill it explicitly. */ white = gdImageColorAllocate (im_out, 255, 255, 255); gdImageFilledRectangle (im_out, 0, 0, gdImageSX (im_out), gdImageSY (im_out), white); /* Set transparent color. */ gdImageColorTransparent (im_out, white); /* Try to load demoin.png and paste part of it into the output image. */ in = fopen ("demoin.png", "rb"); if (!in) { fprintf (stderr, "Can't load source image; this demo\n"); fprintf (stderr, "is much more impressive if demoin.png\n"); fprintf (stderr, "is available.\n"); im_in = 0; } else { int a; im_in = gdImageCreateFromPng (in); fclose (in); /* Now copy, and magnify as we do so */ gdImageCopyResampled (im_out, im_in, 32, 32, 0, 0, 192, 192, 255, 255); /* Now display variously rotated space shuttles in a circle of our own */ for (a = 0; (a < 360); a += 45) { int cx = cos (a * .0174532925) * 128; int cy = -sin (a * .0174532925) * 128; gdImageCopyRotated (im_out, im_in, 256 + 192 + cx, 192 + cy, 0, 0, gdImageSX (im_in), gdImageSY (im_in), a); } } red = gdImageColorAllocate (im_out, 255, 0, 0); green = gdImageColorAllocate (im_out, 0, 255, 0); blue = gdImageColorAllocate (im_out, 0, 0, 255); /* Fat Rectangle */ gdImageSetThickness (im_out, 4); gdImageLine (im_out, 16, 16, 240, 16, green); gdImageLine (im_out, 240, 16, 240, 240, green); gdImageLine (im_out, 240, 240, 16, 240, green); gdImageLine (im_out, 16, 240, 16, 16, green); gdImageSetThickness (im_out, 1); /* Circle */ gdImageArc (im_out, 128, 128, 60, 20, 0, 720, blue); /* Arc */ gdImageArc (im_out, 128, 128, 40, 40, 90, 270, blue); /* Flood fill: doesn't do much on a continuously variable tone jpeg original. */ gdImageFill (im_out, 8, 8, blue); /* Polygon */ points[0].x = 64; points[0].y = 0; points[1].x = 0; points[1].y = 128; points[2].x = 128; points[2].y = 128; gdImageFilledPolygon (im_out, points, 3, green); /* 2.0.12: Antialiased Polygon */ gdImageSetAntiAliased (im_out, green); for (i = 0; (i < 3); i++) { points[i].x += 128; } gdImageFilledPolygon (im_out, points, 3, gdAntiAliased); /* Brush. A fairly wild example also involving a line style! */ if (im_in) { int style[8]; brush = gdImageCreateTrueColor (16, 16); gdImageCopyResized (brush, im_in, 0, 0, 0, 0, gdImageSX (brush), gdImageSY (brush), gdImageSX (im_in), gdImageSY (im_in)); gdImageSetBrush (im_out, brush); /* With a style, so they won't overprint each other. Normally, they would, yielding a fat-brush effect. */ style[0] = 0; style[1] = 0; style[2] = 0; style[3] = 0; style[4] = 0; style[5] = 0; style[6] = 0; style[7] = 1; gdImageSetStyle (im_out, style, 8); /* Draw the styled, brushed line */ gdImageLine (im_out, 0, 255, 255, 0, gdStyledBrushed); } /* Text (non-truetype; see gdtestft for a freetype demo) */ gdImageString (im_out, gdFontGiant, 32, 32, (unsigned char *) "hi", red); gdImageStringUp (im_out, gdFontSmall, 64, 64, (unsigned char *) "hi", red); /* Random antialiased lines; coordinates all over the image, but the output will respect a small clipping rectangle */ gdImageSetClip(im_out, 0, gdImageSY(im_out) - 100, 100, gdImageSY(im_out)); /* Fixed seed for reproducibility of results */ srand(100); for (i = 0; (i < 100); i++) { int x1 = rand() % gdImageSX(im_out); int y1 = rand() % gdImageSY(im_out); int x2 = rand() % gdImageSX(im_out); int y2 = rand() % gdImageSY(im_out); gdImageSetAntiAliased(im_out, white); gdImageLine (im_out, x1, y1, x2, y2, gdAntiAliased); } /* Make output image interlaced (progressive, in the case of JPEG) */ gdImageInterlace (im_out, 1); out = fopen ("demoout.png", "wb"); /* Write PNG */ gdImagePng (im_out, out); fclose (out); /* 2.0.12: also write a paletteized version */ out = fopen ("demooutp.png", "wb"); gdImageTrueColorToPalette (im_out, 0, 256); gdImagePng (im_out, out); fclose (out); gdImageDestroy (im_out); if (im_in) { gdImageDestroy (im_in); } #else fprintf (stderr, "No PNG library support.\n"); #endif /* HAVE_LIBPNG */ return 0; }
int main(void) { /* Input and output files */ FILE *in; FILE *out; /* Input and output images */ gdImagePtr im_in, im_out; /* Brush image */ gdImagePtr brush; /* Color indexes */ int white; int blue; int red; int green; /* Points for polygon */ gdPoint points[3]; /* Create output image, 128 by 128 pixels. */ im_out = gdImageCreate(128, 128); /* First color allocated is background. */ white = gdImageColorAllocate(im_out, 255, 255, 255); /* Set transparent color. */ gdImageColorTransparent(im_out, white); /* Try to load demoin.png and paste part of it into the output image. */ in = fopen("demoin.png", "rb"); if (!in) { fprintf(stderr, "Can't load source image; this demo\n"); fprintf(stderr, "is much more impressive if demoin.png\n"); fprintf(stderr, "is available.\n"); im_in = 0; } else { im_in = gdImageCreateFromPng(in); fclose(in); /* Now copy, and magnify as we do so */ gdImageCopyResized(im_out, im_in, 16, 16, 0, 0, 96, 96, 127, 127); } red = gdImageColorAllocate(im_out, 255, 0, 0); green = gdImageColorAllocate(im_out, 0, 255, 0); blue = gdImageColorAllocate(im_out, 0, 0, 255); /* Rectangle */ gdImageLine(im_out, 8, 8, 120, 8, green); gdImageLine(im_out, 120, 8, 120, 120, green); gdImageLine(im_out, 120, 120, 8, 120, green); gdImageLine(im_out, 8, 120, 8, 8, green); /* Circle */ gdImageArc(im_out, 64, 64, 30, 10, 0, 360, blue); /* Arc */ gdImageArc(im_out, 64, 64, 20, 20, 45, 135, blue); /* Flood fill */ gdImageFill(im_out, 4, 4, blue); /* Polygon */ points[0].x = 32; points[0].y = 0; points[1].x = 0; points[1].y = 64; points[2].x = 64; points[2].y = 64; gdImageFilledPolygon(im_out, points, 3, green); /* Brush. A fairly wild example also involving a line style! */ if (im_in) { int style[8]; brush = gdImageCreate(8, 8); gdImageCopyResized(brush, im_in, 0, 0, 0, 0, gdImageSX(brush), gdImageSY(brush), gdImageSX(im_in), gdImageSY(im_in)); gdImageSetBrush(im_out, brush); /* With a style, so they won't overprint each other. Normally, they would, yielding a fat-brush effect. */ style[0] = 0; style[1] = 0; style[2] = 0; style[3] = 0; style[4] = 0; style[5] = 0; style[6] = 0; style[7] = 1; gdImageSetStyle(im_out, style, 8); /* Draw the styled, brushed line */ gdImageLine(im_out, 0, 127, 127, 0, gdStyledBrushed); } /* Text */ gdImageString(im_out, gdFontGiant, 16, 16, (unsigned char *) "hi", red); gdImageStringUp(im_out, gdFontSmall, 32, 32, (unsigned char *) "hi", red); /* Make output image interlaced (allows "fade in" in some viewers, and in the latest web browsers) */ gdImageInterlace(im_out, 1); out = fopen("demoout.png", "wb"); /* Write PNG */ gdImagePng(im_out, out); fclose(out); gdImageDestroy(im_out); if (im_in) { gdImageDestroy(im_in); } return 0; }
int renderVectorSymbolGD(imageObj *img, double x, double y, symbolObj *symbol, symbolStyleObj *style) { int bRotated = MS_FALSE; int j,k; gdImagePtr ip; gdPoint mPoints[MS_MAXVECTORPOINTS]; gdPoint oldpnt,newpnt; int fc,oc; if(!(ip = MS_IMAGE_GET_GDIMAGEPTR(img))) return MS_FAILURE; SETPEN(ip, style->color); SETPEN(ip, style->outlinecolor); fc = style->color ? style->color->pen : -1; oc = style->outlinecolor ? style->outlinecolor->pen : -1; if(oc==-1 && fc ==-1) { return MS_SUCCESS; } if (style->rotation != 0.0) { bRotated = MS_TRUE; symbol = rotateVectorSymbolPoints(symbol, style->rotation); if(!symbol) { return MS_FAILURE; } } /* We avoid MS_NINT in this context because the potentially variable handling of 0.5 rounding is often a problem for symbols which are often an odd size (ie. 7pixels) and so if "p" is integral the value is always on a 0.5 boundary - bug 1716 */ x -= style->scale*.5*symbol->sizex; y -= style->scale*.5*symbol->sizey; if(symbol->filled) { /* if filled */ k = 0; /* point counter */ for(j=0; j < symbol->numpoints; j++) { if((symbol->points[j].x == -99) && (symbol->points[j].y == -99)) { /* new polygon (PENUP) */ if(k>2) { if(fc >= 0) gdImageFilledPolygon(ip, mPoints, k, fc); if(oc >= 0) gdImagePolygon(ip, mPoints, k, oc); } k = 0; /* reset point counter */ } else { mPoints[k].x = MS_NINT(style->scale*symbol->points[j].x + x); mPoints[k].y = MS_NINT(style->scale*symbol->points[j].y + y); k++; } } if(fc >= 0) gdImageFilledPolygon(ip, mPoints, k, fc); if(oc >= 0) gdImagePolygon(ip, mPoints, k, oc); } else { /* NOT filled */ if(oc >= 0) fc = oc; /* try the outline color (reference maps sometimes do this when combining a box and a custom vector marker */ oldpnt.x = MS_NINT(style->scale*symbol->points[0].x + x); /* convert first point in marker */ oldpnt.y = MS_NINT(style->scale*symbol->points[0].y + y); gdImageSetThickness(ip, style->outlinewidth); for(j=1; j < symbol->numpoints; j++) { /* step through the marker */ if((symbol->points[j].x != -99) || (symbol->points[j].y != -99)) { if((symbol->points[j-1].x == -99) && (symbol->points[j-1].y == -99)) { /* Last point was PENUP, now a new beginning */ oldpnt.x = MS_NINT(style->scale*symbol->points[j].x + x); oldpnt.y = MS_NINT(style->scale*symbol->points[j].y + y); } else { newpnt.x = MS_NINT(style->scale*symbol->points[j].x + x); newpnt.y = MS_NINT(style->scale*symbol->points[j].y + y); gdImageLine(ip, oldpnt.x, oldpnt.y, newpnt.x, newpnt.y, fc); oldpnt = newpnt; } } } /* end for loop */ gdImageSetThickness(ip, 1); /* restore thinkness */ } /* end if-then-else */ if(bRotated) { msFreeSymbol(symbol); /* clean up */ msFree(symbol); } return MS_SUCCESS; }
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); } }