Пример #1
0
static void gx_ttfExport__MoveTo(ttfExport *self, FloatPoint *p)
{
    gx_ttfExport *e = (gx_ttfExport *)self;

    if (!e->error)
        e->error = gx_path_add_point(e->path, float2fixed(p->x), float2fixed(p->y));
}
Пример #2
0
int
gs_moveto(gs_state *pgs, floatp x, floatp y)
{   int code;
    gs_fixed_point pt;
    if ( (code = gs_point_transform2fixed(&pgs->ctm, x, y, &pt)) >= 0 )
        code = gx_path_add_point(pgs->path, pt.x, pt.y);
    return code;
}
Пример #3
0
/* We know ppath != ppath_old. */
int
gx_path_copy_reversed(const gx_path *ppath_old, gx_path *ppath, int init)
{	const subpath *psub = ppath_old->first_subpath;
#ifdef DEBUG
if ( gs_debug['p'] )
	gx_dump_path(ppath_old, "before reversepath");
#endif
	if ( init )
		gx_path_init(ppath, &ppath_old->memory_procs);
nsp:	while ( psub )
	   {	const segment *pseg = psub->last;
		const segment *prev;
		int code = gx_path_add_point(ppath, pseg->pt.x, pseg->pt.y);
		if ( code < 0 )
		   {	gx_path_release(ppath);
			return code;
		   }
		for ( ; ; pseg = prev )
		   {	prev = pseg->prev;
			switch ( pseg->type )
			   {
			case s_start:
				/* Finished subpath */
				if ( psub->closed )
					code = gx_path_close_subpath(ppath);
				psub = (const subpath *)psub->last->next;
				goto nsp;
			case s_curve:
			   {	const curve_segment *pc = (const curve_segment *)pseg;
				code = gx_path_add_curve(ppath,
					pc->p2.x, pc->p2.y,
					pc->p1.x, pc->p1.y,
					prev->pt.x, prev->pt.y);
				break;
			   }
			case s_line:
			case s_line_close:
				code = gx_path_add_line(ppath, prev->pt.x, prev->pt.y);
				break;
			   }
			if ( code )
			   {	gx_path_release(ppath);
				return code;
			   }
		   }
		/* not reached */
	}
	ppath->position = ppath_old->position;		/* restore current point */
#ifdef DEBUG
if ( gs_debug['p'] )
	gx_dump_path(ppath, "after reversepath");
#endif
	return 0;
}
Пример #4
0
/* relatives. */
int
gx_path_add_char_path(gx_path * to_path, gx_path * from_path,
                      gs_char_path_mode mode)
{
    int code;
    gs_fixed_rect bbox;

    switch (mode) {
        default:		/* shouldn't happen! */
            gx_path_new(from_path);
            return 0;
        case cpm_charwidth: {
            gs_fixed_point cpt;

            code = gx_path_current_point(from_path, &cpt);
            if (code < 0)
                break;
            return gx_path_add_point(to_path, cpt.x, cpt.y);
        }
        case cpm_true_charpath:
        case cpm_false_charpath:
            return gx_path_add_path(to_path, from_path);
        case cpm_true_charboxpath:
            gx_path_bbox(from_path, &bbox);
            code = gx_path_add_rectangle(to_path, bbox.p.x, bbox.p.y,
                                         bbox.q.x, bbox.q.y);
            break;
        case cpm_false_charboxpath:
            gx_path_bbox(from_path, &bbox);
            code = gx_path_add_point(to_path, bbox.p.x, bbox.p.y);
            if (code >= 0)
                code = gx_path_add_line(to_path, bbox.q.x, bbox.q.y);
            break;
    }
    if (code < 0)
        return code;
    gx_path_new(from_path);
    return 0;
}
Пример #5
0
/* This is a special case of adding a closed polygon. */
int
gx_path_add_rectangle(gx_path * ppath, fixed x0, fixed y0, fixed x1, fixed y1)
{
    gs_fixed_point pts[3];
    int code;

    pts[0].x = x0;
    pts[1].x = pts[2].x = x1;
    pts[2].y = y0;
    pts[0].y = pts[1].y = y1;
    if ((code = gx_path_add_point(ppath, x0, y0)) < 0 ||
        (code = gx_path_add_lines(ppath, pts, 3)) < 0 ||
        (code = gx_path_close_subpath(ppath)) < 0
        )
        return code;
    return 0;
}
Пример #6
0
int
gs_moveto_aux(gs_imager_state *pis, gx_path *ppath, floatp x, floatp y)
{
    gs_fixed_point pt;
    int code;

    code = clamp_point_aux(pis->clamp_coordinates, &pt, x, y);
    if (code < 0)
	return code;
    code = gx_path_add_point(ppath, pt.x, pt.y);
    if (code < 0)
	return code;
    ppath->start_flags = ppath->state_flags;
    gx_setcurrentpoint(pis, x, y);
    pis->subpath_start = pis->current_point;
    pis->current_point_valid = true;
    return 0;
}
Пример #7
0
/*
 * Reverse a path.  We know ppath != ppath_old.
 * NOTE: in releases 5.01 and earlier, the implicit line added by closepath
 * became the first segment of the reversed path.  Starting in release
 * 5.02, the code follows the Adobe implementation (and LanguageLevel 3
 * specification), in which this line becomes the *last* segment of the
 * reversed path.  This can produce some quite unintuitive results.
 *
 * The order of the subpaths is unspecified in the PLRM, but the CPSI
 * reverses the subpaths, and the CET (11-05 p6, test 3) tests for it.
 */
int
gx_path_copy_reversed(const gx_path * ppath_old, gx_path * ppath)
{
    const subpath *psub = ppath_old->current_subpath;

#ifdef DEBUG
    if (gs_debug_c('P'))
	gx_dump_path(ppath_old, "before reversepath");
#endif
 nsp:
    if (psub) {
	const segment *prev = psub->last;
	const segment *pseg;
	segment_notes notes =
	    (prev == (const segment *)psub ? sn_none :
	     psub->next->notes);
	segment_notes prev_notes;
	int code;

	if (!psub->is_closed) {
	    code = gx_path_add_point(ppath, prev->pt.x, prev->pt.y);
	    if (code < 0)
		return code;
	}
	/*
	 * The do ... while structure of this loop is artificial,
	 * designed solely to keep compilers from complaining about
	 * 'statement not reached' or 'end-of-loop code not reached'.
	 * The normal exit from this loop is the goto statement in
	 * the s_start arm of the switch.
	 */
	do {
	    pseg = prev;
	    prev_notes = notes;
	    prev = pseg->prev;
	    notes = pseg->notes;
	    prev_notes = (prev_notes & sn_not_first) |
		(notes & ~sn_not_first);
	    switch (pseg->type) {
		case s_start:
		    /* Finished subpath */
		    if (psub->is_closed) {
			code =
			    gx_path_close_subpath_notes(ppath, prev_notes);
			if (code < 0)
			    return code;
		    }
		    do {
			psub = (const subpath *)psub->prev;
		    } while (psub && psub->type != s_start);
		    goto nsp;
		case s_curve:
		    {
			const curve_segment *pc =
			(const curve_segment *)pseg;

			code = gx_path_add_curve_notes(ppath,
						       pc->p2.x, pc->p2.y,
						       pc->p1.x, pc->p1.y,
					prev->pt.x, prev->pt.y, prev_notes);
			break;
		    }
		case s_line:
		    code = gx_path_add_line_notes(ppath,
					prev->pt.x, prev->pt.y, prev_notes);
		    break;
		case s_line_close:
		    /* Skip the closing line. */
		    code = gx_path_add_point(ppath, prev->pt.x,
					     prev->pt.y);
		    break;
		default:	/* not possible */
		    return_error(gs_error_Fatal);
	    }
	} while (code >= 0);
	return code;		/* only reached if code < 0 */
    }
#undef sn_not_end
    /*
     * In the Adobe implementations, reversepath discards a trailing
     * moveto unless the path consists only of a moveto.  We reproduce
     * this behavior here, even though we consider it a bug.
     */
    if (ppath_old->first_subpath == 0 &&
	path_last_is_moveto(ppath_old)
	) {
	int code = gx_path_add_point(ppath, ppath_old->position.x,
				     ppath_old->position.y);

	if (code < 0)
	    return code;
    }
#ifdef DEBUG
    if (gs_debug_c('P'))
	gx_dump_path(ppath, "after reversepath");
#endif
    return 0;
}
Пример #8
0
static int
subpath_expand_dashes(const subpath * psub, gx_path * ppath,
		   const gs_imager_state * pis, const gx_dash_params * dash)
{
    const float *pattern = dash->pattern;
    int count, index;
    bool ink_on;
    double elt_length;
    fixed x0 = psub->pt.x, y0 = psub->pt.y;
    fixed x, y;
    const segment *pseg;
    int wrap = (dash->init_ink_on && psub->is_closed ? -1 : 0);
    int drawing = wrap;
    segment_notes notes = ~sn_not_first;
    const gx_line_params *pgs_lp = gs_currentlineparams_inline(pis);
    bool zero_length = true;
    int code;

    if ((code = gx_path_add_point(ppath, x0, y0)) < 0)
	return code;
    /*
     * To do the right thing at the beginning of a closed path, we have
     * to skip any initial line, and then redo it at the end of the
     * path.  Drawing = -1 while skipping, 0 while drawing normally, and
     * 1 on the second round.  Note that drawing != 0 implies ink_on.
     */
  top:count = dash->pattern_size;
    ink_on = dash->init_ink_on;
    index = dash->init_index;
    elt_length = dash->init_dist_left;
    x = x0, y = y0;
    pseg = (const segment *)psub;
    while ((pseg = pseg->next) != 0 && pseg->type != s_start) {
	fixed sx = pseg->pt.x, sy = pseg->pt.y;
	fixed udx = sx - x, udy = sy - y;
	double length, dx, dy;
	double scale = 1;
	double left;

	if (!(udx | udy)) {	/* degenerate */
	    if (pgs_lp->dot_length == 0 &&
		pgs_lp->cap != gs_cap_round) {
		/* From PLRM, stroke operator :
		   If a subpath is degenerate (consists of a single-point closed path 
		   or of two or more points at the same coordinates), 
		   stroke paints it only if round line caps have been specified */
		if (zero_length || pseg->type != s_line_close)
		    continue;
	    }
	    dx = 0, dy = 0, length = 0;
	} else {
  	    gs_point d;

	    zero_length = false;
	    dx = udx, dy = udy;	/* scaled as fixed */
	    gs_imager_idtransform(pis, dx, dy, &d);
	    length = hypot(d.x, d.y) * (1.0 / fixed_1);
	    if (gs_imager_currentdashadapt(pis)) {
		double reps = length / dash->pattern_length;

		scale = reps / ceil(reps);
		/* Ensure we're starting at the start of a */
		/* repetition.  (This shouldn't be necessary, */
		/* but it is.) */
		count = dash->pattern_size;
		ink_on = dash->init_ink_on;
		index = dash->init_index;
		elt_length = dash->init_dist_left * scale;
	    }
	}
	left = length;
	while (left > elt_length) {	/* We are using up the line segment. */
	    double fraction = elt_length / length;
	    fixed fx = (fixed) (dx * fraction);
	    fixed fy = (fixed) (dy * fraction);
	    fixed nx = x + fx;
	    fixed ny = y + fy;

	    if (ink_on) {
		if (drawing >= 0) {
		    if (left >= elt_length && any_abs(fx) + any_abs(fy) < fixed_half)
			code = gx_path_add_dash_notes(ppath, nx, ny, udx, udy, 
				notes & pseg->notes);
		    else
			code = gx_path_add_line_notes(ppath, nx, ny,
						  notes & pseg->notes);
		}
		notes |= sn_not_first;
	    } else {
		if (drawing > 0)	/* done */
		    return 0;
		code = gx_path_add_point(ppath, nx, ny);
		notes &= ~sn_not_first;
		drawing = 0;
	    }
	    if (code < 0)
		return code;
	    left -= elt_length;
	    ink_on = !ink_on;
	    if (++index == count)
		index = 0;
	    elt_length = pattern[index] * scale;
	    x = nx, y = ny;
	}
	elt_length -= left;
	/* Handle the last dash of a segment. */
      on:if (ink_on) {
	    if (drawing >= 0) {
		if (pseg->type == s_line_close && drawing > 0)
		    code = gx_path_close_subpath_notes(ppath,
						 notes & pseg->notes);
		else if (any_abs(sx - x) + any_abs(sy - y) < fixed_half)
		    code = gx_path_add_dash_notes(ppath, sx, sy, udx, udy, 
			    notes & pseg->notes);
		else
		    code = gx_path_add_line_notes(ppath, sx, sy,
					notes & pseg->notes);
		notes |= sn_not_first;
	    }
	} else {
	    code = gx_path_add_point(ppath, sx, sy);
	    notes &= ~sn_not_first;
	    if (elt_length < fixed2float(fixed_epsilon) &&
		(pseg->next == 0 || pseg->next->type == s_start || elt_length == 0)) {		
				/*
				 * Ink is off, but we're within epsilon of the end
				 * of the dash element.  
				 * "Stretch" a little so we get a dot.
				 * Also if the next dash pattern is zero length,
				 * use the last segment orientation.
				 */
		double elt_length1;

		if (code < 0)
		    return code;
		if (++index == count)
		    index = 0;
		elt_length1 = pattern[index] * scale;
		if (pseg->next == 0 || pseg->next->type == s_start) {
		    elt_length = elt_length1;
		    left = 0;
		    ink_on = true;
		    goto on;
		}
		/* Looking ahead one dash pattern element.
		   If it is zero length, apply to the current segment 
		   (at its end). */
		if (elt_length1 == 0) {
		    left = 0;
		    code = gx_path_add_dash_notes(ppath, sx, sy, udx, udy,
				    notes & pseg->notes);
		    if (++index == count)
			index = 0;
		    elt_length = pattern[index] * scale;
		    ink_on = false;
		} else if (--index == 0) {
		    /* Revert lookahead. */
		    index = count - 1;
		}
	    }
	    if (drawing > 0)	/* done */
		return code;
	    drawing = 0;
	}
	if (code < 0)
	    return code;
	x = sx, y = sy;
    }
    /* Check for wraparound. */
    if (wrap && drawing <= 0) {	/* We skipped some initial lines. */
	/* Go back and do them now. */
	drawing = 1;
	goto top;
    }
    return 0;
}
Пример #9
0
/* Internal routine for adding an arc to the path. */
static int
arc_add(const arc_curve_params_t * arc, bool is_quadrant)
{
    gx_path *path = arc->ppath;
    gs_imager_state *pis = arc->pis;
    double x0 = arc->p0.x, y0 = arc->p0.y;
    double xt = arc->pt.x, yt = arc->pt.y;
    floatp fraction;
    gs_fixed_point p0, p2, p3, pt;
    int code;

    if ((arc->action != arc_nothing &&
#if !PRECISE_CURRENTPOINT
	 (code = gs_point_transform2fixed(&pis->ctm, x0, y0, &p0)) < 0) ||
	(code = gs_point_transform2fixed(&pis->ctm, xt, yt, &pt)) < 0 ||
	(code = gs_point_transform2fixed(&pis->ctm, arc->p3.x, arc->p3.y, &p3)) < 0
#else
	 (code = gs_point_transform2fixed_rounding(&pis->ctm, x0, y0, &p0)) < 0) ||
	(code = gs_point_transform2fixed_rounding(&pis->ctm, xt, yt, &pt)) < 0 ||
	(code = gs_point_transform2fixed_rounding(&pis->ctm, arc->p3.x, arc->p3.y, &p3)) < 0
#endif
	)
	return code;
#if PRECISE_CURRENTPOINT
    if (!path_position_valid(path))
	gs_point_transform(arc->p0.x, arc->p0.y, &ctm_only(arc->pis), &pis->subpath_start);
#endif
    code = (arc->action == arc_nothing ?
	  (p0.x = path->position.x, p0.y = path->position.y, 0) :
	  arc->action == arc_lineto && path_position_valid(path) ?
	  gx_path_add_line(path, p0.x, p0.y) :
	  /* action == arc_moveto, or lineto with no current point */
	  gx_path_add_point(path, p0.x, p0.y));
    if (code < 0)
	return code;
    /* Compute the fraction coefficient for the curve. */
    /* See gx_path_add_partial_arc for details. */
    if (is_quadrant) {
	/* one of |dx| and |dy| is r, the other is zero */
	fraction = quarter_arc_fraction;
	if (arc->fast_quadrant > 0) {
	    /*
	     * The CTM is well-behaved, and we have pre-calculated the delta
	     * from the circumference points to the control points.
	     */
	    fixed delta = arc->quadrant_delta;

	    if (pt.x != p0.x)
		p0.x = (pt.x > p0.x ? p0.x + delta : p0.x - delta);
	    if (pt.y != p0.y)
		p0.y = (pt.y > p0.y ? p0.y + delta : p0.y - delta);
	    p2.x = (pt.x == p3.x ? p3.x :
		    pt.x > p3.x ? p3.x + delta : p3.x - delta);
	    p2.y = (pt.y == p3.y ? p3.y :
		    pt.y > p3.y ? p3.y + delta : p3.y - delta);
	    goto add;
	}
    } else {
	double r = arc->radius;
	floatp dx = xt - x0, dy = yt - y0;
	double dist = dx * dx + dy * dy;
	double r2 = r * r;

	if (dist >= r2 * 1.0e8)	/* almost zero radius; */
	    /* the >= catches dist == r == 0 */
	    fraction = 0.0;
	else
	    fraction = (4.0 / 3.0) / (1 + sqrt(1 + dist / r2));
    }
    p0.x += (fixed)((pt.x - p0.x) * fraction);
    p0.y += (fixed)((pt.y - p0.y) * fraction);
    p2.x = p3.x + (fixed)((pt.x - p3.x) * fraction);
    p2.y = p3.y + (fixed)((pt.y - p3.y) * fraction);
add:
    if_debug8('r',
	      "[r]Arc f=%f p0=(%f,%f) pt=(%f,%f) p3=(%f,%f) action=%d\n",
	      fraction, x0, y0, xt, yt, arc->p3.x, arc->p3.y,
	      (int)arc->action);

    /* Open-code gx_path_add_partial_arc_notes */
    return gx_path_add_curve_notes(path, p0.x, p0.y, p2.x, p2.y, p3.x, p3.y,
				   arc->notes | sn_from_arc);
}