ArtSVPRenderAAIter * art_svp_render_aa_iter (const ArtSVP *svp, int x0, int y0, int x1, int y1) { ArtSVPRenderAAIter *iter = art_new (ArtSVPRenderAAIter, 1); iter->svp = svp; iter->y = y0; iter->x0 = x0; iter->x1 = x1; iter->seg_ix = 0; iter->active_segs = art_new (int, svp->n_segs); iter->cursor = art_new (int, svp->n_segs); iter->seg_x = art_new (artfloat, svp->n_segs); iter->seg_dx = art_new (artfloat, svp->n_segs); iter->steps = art_new (ArtSVPRenderAAStep, x1 - x0); iter->n_active_segs = 0; return iter; }
/** * gnome_canvas_path_def_new_sized: * @length: number of points to allocate for the path * * This function creates a new #gnome_canvas_path_def with @length * number of points allocated. It is useful, if you know the exact * number of points in path, so you can avoid automatic point * array reallocation. * * Returns: the new canvas path definition */ GnomeCanvasPathDef * gnome_canvas_path_def_new_sized (gint length) { GnomeCanvasPathDef * path; g_return_val_if_fail (length > 0, NULL); path = g_new (GnomeCanvasPathDef, 1); path->refcount = 1; path->bpath = art_new (ArtBpath, length); path->end = 0; path->bpath[path->end].code = ART_END; path->length = length; path->sbpath = FALSE; path->hascpt = FALSE; path->posset = FALSE; path->moving = FALSE; path->allclosed = TRUE; path->allopen = TRUE; return path; }
/** * art_vpath_new_vpath_array: Generate a heap-based ArtVpath-array from a vpath iterator * @src: Source Iterator * Return value: Newly allocated vpath **/ ArtVpath *art_vpath_new_vpath_array(ArtVpathIterator *src) { ArtVpath *result; ArtVpath *current; int n_result, n_result_max; if (!src->current(src)) return 0; n_result = 0; n_result_max = 16; result = art_new (ArtVpath, n_result_max); while(1) { current = src->current(src); if (!current) break; art_vpath_add_point (&result, &n_result, &n_result_max, current->code, current->x, current->y); if (current->code == ART_END) break; src->next(src); } return result; }
static gboolean CORBA_SVP_Segment_to_SVPSeg (MateComponent_Canvas_SVPSegment *seg, ArtSVPSeg *art_seg) { int i; art_seg->points = art_new (ArtPoint, seg->points._length); if (!art_seg->points) return FALSE; art_seg->dir = seg->up ? 0 : 1; art_seg->bbox.x0 = seg->bbox.x0; art_seg->bbox.x1 = seg->bbox.x1; art_seg->bbox.y0 = seg->bbox.y0; art_seg->bbox.y1 = seg->bbox.y1; art_seg->n_points = seg->points._length; for (i = 0; i < art_seg->n_points; i++){ art_seg->points [i].x = seg->points._buffer [i].x; art_seg->points [i].y = seg->points._buffer [i].y; } return TRUE; }
/** * art_svp_from_vpath_raw: Stroke a vector path, raw version * @vpath: #ArtVPath to stroke. * @join: Join style. * @cap: Cap style. * @line_width: Width of stroke. * @miter_limit: Miter limit. * @flatness: Flatness. * * Exactly the same as art_svp_vpath_stroke(), except that the resulting * stroke outline may self-intersect and have regions of winding number * greater than 1. * * Return value: Resulting raw stroked outline in svp format. **/ ArtVpath * art_svp_vpath_stroke_raw (ArtVpath *vpath, ArtPathStrokeJoinType join, ArtPathStrokeCapType cap, double line_width, double miter_limit, double flatness) { int begin_idx, end_idx; int i; ArtVpath *forw, *rev; int n_forw, n_rev; int n_forw_max, n_rev_max; ArtVpath *result; int n_result, n_result_max; double half_lw = 0.5 * line_width; int closed; int last, this, next, second; double dx, dy; n_forw_max = 16; forw = art_new (ArtVpath, n_forw_max); n_rev_max = 16; rev = art_new (ArtVpath, n_rev_max); n_result = 0; n_result_max = 16; result = art_new (ArtVpath, n_result_max); for (begin_idx = 0; vpath[begin_idx].code != ART_END; begin_idx = end_idx) { n_forw = 0; n_rev = 0; closed = (vpath[begin_idx].code == ART_MOVETO); /* we don't know what the first point joins with until we get to the last point and see if it's closed. So we start with the second line in the path. Note: this is not strictly true (we now know it's closed from the opening pathcode), but why fix code that isn't broken? */ this = begin_idx; /* skip over identical points at the beginning of the subpath */ for (i = this + 1; vpath[i].code == ART_LINETO; i++) { dx = vpath[i].x - vpath[this].x; dy = vpath[i].y - vpath[this].y; if (dx * dx + dy * dy > EPSILON_2) break; } next = i; second = next; /* invariant: this doesn't coincide with next */ while (vpath[next].code == ART_LINETO) { last = this; this = next; /* skip over identical points after the beginning of the subpath */ for (i = this + 1; vpath[i].code == ART_LINETO; i++) { dx = vpath[i].x - vpath[this].x; dy = vpath[i].y - vpath[this].y; if (dx * dx + dy * dy > EPSILON_2) break; } next = i; if (vpath[next].code != ART_LINETO) { /* reached end of path */ /* make "closed" detection conform to PostScript semantics (i.e. explicit closepath code rather than just the fact that end of the path is the beginning) */ if (closed && vpath[this].x == vpath[begin_idx].x && vpath[this].y == vpath[begin_idx].y) { int j; /* path is closed, render join to beginning */ render_seg (&forw, &n_forw, &n_forw_max, &rev, &n_rev, &n_rev_max, vpath, last, this, second, join, half_lw, miter_limit, flatness); #ifdef VERBOSE printf ("%% forw %d, rev %d\n", n_forw, n_rev); #endif /* do forward path */ art_vpath_add_point (&result, &n_result, &n_result_max, ART_MOVETO, forw[n_forw - 1].x, forw[n_forw - 1].y); for (j = 0; j < n_forw; j++) art_vpath_add_point (&result, &n_result, &n_result_max, ART_LINETO, forw[j].x, forw[j].y); /* do reverse path, reversed */ art_vpath_add_point (&result, &n_result, &n_result_max, ART_MOVETO, rev[0].x, rev[0].y); for (j = n_rev - 1; j >= 0; j--) art_vpath_add_point (&result, &n_result, &n_result_max, ART_LINETO, rev[j].x, rev[j].y); } else { /* path is open */ int j; /* add to forw rather than result to ensure that forw has at least one point. */ render_cap (&forw, &n_forw, &n_forw_max, vpath, last, this, cap, half_lw, flatness); art_vpath_add_point (&result, &n_result, &n_result_max, ART_MOVETO, forw[0].x, forw[0].y); for (j = 1; j < n_forw; j++) art_vpath_add_point (&result, &n_result, &n_result_max, ART_LINETO, forw[j].x, forw[j].y); for (j = n_rev - 1; j >= 0; j--) art_vpath_add_point (&result, &n_result, &n_result_max, ART_LINETO, rev[j].x, rev[j].y); render_cap (&result, &n_result, &n_result_max, vpath, second, begin_idx, cap, half_lw, flatness); art_vpath_add_point (&result, &n_result, &n_result_max, ART_LINETO, forw[0].x, forw[0].y); } } else render_seg (&forw, &n_forw, &n_forw_max, &rev, &n_rev, &n_rev_max, vpath, last, this, next, join, half_lw, miter_limit, flatness); } end_idx = next; } art_free (forw); art_free (rev); #ifdef VERBOSE printf ("%% n_result = %d\n", n_result); #endif art_vpath_add_point (&result, &n_result, &n_result_max, ART_END, 0, 0); return result; }
void art_draw_poly(art_buffer_p buffer, art_context_p context, int filled, float *x, float *y, int n, int closed) { ArtVpath *vec, *vec2; ArtSVP *svp; double dash_data[2]; ArtVpathDash dash; ArtDRect drect; ArtIRect irect; int i, mark = 0; vec = art_new(ArtVpath, n + 1 + closed); for(i = 0; i < n; i++) { vec[mark].code = i ? ART_LINETO : ART_MOVETO; if(i == 0 || i == n - 1 || hypot(x[i] - vec[mark - 1].x, (buffer->height - y[i]) - vec[mark - 1].y) > 1.0) { vec[mark].x = x[i]; vec[mark].y = buffer->height - y[i]; mark++; } } n = mark; if(closed) { vec[n].code = ART_LINETO; vec[n].x = vec[0].x; vec[n].y = vec[0].y; } vec[n + closed].code = ART_END; vec[n + closed].x = 0; vec[n + closed].y = 0; if(context->current_dash_on > 0) { dash.offset = 0; dash_data[0] = context->current_dash_on; dash_data[1] = context->current_dash_off; dash.n_dash = 2; dash.dash = dash_data; vec2 = art_vpath_dash(vec, &dash); art_free(vec); vec = vec2; } if(filled) svp = art_svp_from_vpath(vec); else svp = art_svp_vpath_stroke(vec, context->current_jointype, context->current_captype, context->current_linewidth, context->current_miterlimit, context->current_flatness); art_free(vec); art_drect_svp(&drect, svp); art_drect_to_irect(&irect, &drect); if(irect.x1 > buffer->width) irect.x1 = buffer->width; if(irect.y1 > buffer->height) irect.y1 = buffer->height; if(irect.x0 < 0) irect.x0 = 0; if(irect.y0 < 0) irect.y0 = 0; art_rgb_svp_alpha(svp, irect.x0, irect.y0, irect.x1, irect.y1, context->current_color, buffer->buffer + (irect.y0 * buffer->width + irect.x0) * 3, buffer->width * 3, NULL); art_svp_free(svp); }
/** * art_bez_path_to_vec: Create vpath from bezier path. * @bez: Bezier path. * @flatness: Flatness control. * * Creates a vector path closely approximating the bezier path defined by * @bez. The @flatness argument controls the amount of subdivision. In * general, the resulting vpath deviates by at most @flatness pixels * from the "ideal" path described by @bez. * * Return value: Newly allocated vpath. **/ ArtVpath * art_bez_path_to_vec (const ArtBpath *bez, double flatness) { ArtVpath *vec; int vec_n, vec_n_max; int bez_index; double x, y; vec_n = 0; vec_n_max = RENDER_SIZE; vec = art_new (ArtVpath, vec_n_max); /* Initialization is unnecessary because of the precondition that the bezier path does not begin with LINETO or CURVETO, but is here to make the code warning-free. */ x = 0; y = 0; bez_index = 0; do { #ifdef VERBOSE printf ("%s %g %g\n", bez[bez_index].code == ART_CURVETO ? "curveto" : bez[bez_index].code == ART_LINETO ? "lineto" : bez[bez_index].code == ART_MOVETO ? "moveto" : bez[bez_index].code == ART_MOVETO_OPEN ? "moveto-open" : "end", bez[bez_index].x3, bez[bez_index].y3); #endif /* make sure space for at least one more code */ if (vec_n >= vec_n_max) art_expand (vec, ArtVpath, vec_n_max); switch (bez[bez_index].code) { case ART_MOVETO_OPEN: case ART_MOVETO: case ART_LINETO: x = bez[bez_index].x3; y = bez[bez_index].y3; vec[vec_n].code = bez[bez_index].code; vec[vec_n].x = x; vec[vec_n].y = y; vec_n++; break; case ART_END: vec[vec_n].code = bez[bez_index].code; vec[vec_n].x = 0; vec[vec_n].y = 0; vec_n++; break; case ART_CURVETO: #ifdef VERBOSE printf ("%g,%g %g,%g %g,%g %g,%g\n", x, y, bez[bez_index].x1, bez[bez_index].y1, bez[bez_index].x2, bez[bez_index].y2, bez[bez_index].x3, bez[bez_index].y3); #endif art_vpath_render_bez (&vec, &vec_n, &vec_n_max, x, y, bez[bez_index].x1, bez[bez_index].y1, bez[bez_index].x2, bez[bez_index].y2, bez[bez_index].x3, bez[bez_index].y3, flatness); x = bez[bez_index].x3; y = bez[bez_index].y3; break; } } while (bez[bez_index++].code != ART_END); return vec; }
static ArtVpath* gfxline_to_ArtVpath(gfxline_t*line, char fill) { ArtVpath *vec = NULL; int pos=0,len=0; gfxline_t*l2; double x=0,y=0; /* factor which determines into how many line fragments a spline is converted */ double subfraction = 2.4;//0.3 l2 = line; while(l2) { if(l2->type == gfx_moveTo) { pos ++; } else if(l2->type == gfx_lineTo) { pos ++; } else if(l2->type == gfx_splineTo) { int parts = (int)(sqrt(fabs(l2->x-2*l2->sx+x) + fabs(l2->y-2*l2->sy+y))*subfraction); if(!parts) parts = 1; pos += parts + 1; } x = l2->x; y = l2->y; l2 = l2->next; } pos++; len = pos; vec = art_new (ArtVpath, len+1); pos = 0; l2 = line; int lastmove=-1; while(l2) { if(l2->type == gfx_moveTo) { vec[pos].code = ART_MOVETO_OPEN; vec[pos].x = l2->x; vec[pos].y = l2->y; lastmove=pos; pos++; assert(pos<=len); } else if(l2->type == gfx_lineTo) { vec[pos].code = ART_LINETO; vec[pos].x = l2->x; vec[pos].y = l2->y; pos++; assert(pos<=len); } else if(l2->type == gfx_splineTo) { int i; int parts = (int)(sqrt(fabs(l2->x-2*l2->sx+x) + fabs(l2->y-2*l2->sy+y))*subfraction); if(!parts) parts = 1; double stepsize = 1.0/parts; for(i=0;i<=parts;i++) { double t = (double)i*stepsize; vec[pos].code = ART_LINETO; vec[pos].x = l2->x*t*t + 2*l2->sx*t*(1-t) + x*(1-t)*(1-t); vec[pos].y = l2->y*t*t + 2*l2->sy*t*(1-t) + y*(1-t)*(1-t); pos++; assert(pos<=len); } } x = l2->x; y = l2->y; /* let closed line segments start w/ MOVETO instead of MOVETO_OPEN */ if(lastmove>=0 && l2->type!=gfx_moveTo && (!l2->next || l2->next->type == gfx_moveTo)) { if(vec[lastmove].x == l2->x && vec[lastmove].y == l2->y) { assert(vec[lastmove].code == ART_MOVETO_OPEN); vec[lastmove].code = ART_MOVETO; } } l2 = l2->next; } vec[pos++].code = ART_END; assert(pos == len); if(!fill) { /* Fix "dotted" lines. Those are lines where singular points are created by a moveto x,y lineto x,y combination. We "fix" these by shifting the point in the lineto a little bit to the right These should only occur in strokes, not in fills, so do this only when we know we're not filling. */ int t; for(t=0;vec[t].code!=ART_END;t++) { if(t>0 && (vec[t-1].code==ART_MOVETO_OPEN || vec[t-1].code==ART_MOVETO) && vec[t].code==ART_LINETO && vec[t+1].code!=ART_LINETO && vec[t-1].x == vec[t].x && vec[t-1].y == vec[t].y) { vec[t].x += 0.01; } } } /* Find adjacent identical points. If an ajdacent pair of identical points is found, the second one is removed. So moveto x,y lineto x,y becomes moveto x,y lineto x,y lineto x,y becomes lineto x,y lineto x,y moveto x,y becomes lineto x,y moveto x,y moveto x,y becomes moveto x,y lineto x,y lineto x2,y2 becomes lineto x2,y2 (if dir(x,y) ~= dir(x2,y2)) */ pos = 0; int outpos = 0; while(1) { if(vec[pos].code == ART_END) { vec[outpos++] = vec[pos++]; break; } char samedir = 0, samepoint = 0; if(outpos) { double dx = vec[pos].x-vec[pos-1].x; double dy = vec[pos].y-vec[pos-1].y; /*if(pos<len-1 && vec[pos].code == ART_LINETO && vec[pos+1].code == ART_LINETO) { double dx2 = vec[pos+1].x-vec[pos].x; double dy2 = vec[pos+1].y-vec[pos].y; if(fabs(dx*dy2 - dy*dx2) < 0.0001 && dx*dx2 + dy*dy2 >= 0) { samedir=1; } }*/ if(fabs(dx) + fabs(dy) < 0.0001) { samepoint=1; } } if(!samepoint && !samedir) { vec[outpos++] = vec[pos++]; } else { pos++; // skip } } return vec; }