Esempio n. 1
0
/*
 * Put a segment of an enumerated path on the output file.
 * pe_op is assumed to be valid and non-zero.
 */
int
gdev_vector_dopath_segment(gdev_vector_dopath_state_t *state, int pe_op,
                           gs_fixed_point vs[3])
{
    gx_device_vector *vdev = state->vdev;
    const gs_matrix *const pmat = &state->scale_mat;
    gs_point vp[3];
    int code;

    switch (pe_op) {
        case gs_pe_moveto:
            code = gs_point_transform_inverse(fixed2float(vs[0].x),
                                       fixed2float(vs[0].y), pmat, &vp[0]);
            if (code < 0)
                return code;
            if (state->first)
                state->start = vp[0], state->first = false;
            code = vdev_proc(vdev, moveto)
                (vdev, 0/*unused*/, 0/*unused*/, vp[0].x, vp[0].y,
                 state->type);
            state->prev = vp[0];
            break;
        case gs_pe_lineto:
        case gs_pe_gapto: /* FIXME */
            code = gs_point_transform_inverse(fixed2float(vs[0].x),
                                       fixed2float(vs[0].y), pmat, &vp[0]);
            if (code < 0)
                return code;
            code = vdev_proc(vdev, lineto)
                (vdev, state->prev.x, state->prev.y, vp[0].x, vp[0].y,
                 state->type);
            state->prev = vp[0];
            break;
        case gs_pe_curveto:
            code = gs_point_transform_inverse(fixed2float(vs[0].x),
                                       fixed2float(vs[0].y), pmat, &vp[0]);
            if (code < 0)
                return code;
            code = gs_point_transform_inverse(fixed2float(vs[1].x),
                                       fixed2float(vs[1].y), pmat, &vp[1]);
            if (code < 0)
                return code;
            gs_point_transform_inverse(fixed2float(vs[2].x),
                                       fixed2float(vs[2].y), pmat, &vp[2]);
            code = vdev_proc(vdev, curveto)
                (vdev, state->prev.x, state->prev.y, vp[0].x, vp[0].y,
                 vp[1].x, vp[1].y, vp[2].x, vp[2].y, state->type);
            state->prev = vp[2];
            break;
        case gs_pe_closepath:
            code = vdev_proc(vdev, closepath)
                (vdev, state->prev.x, state->prev.y, state->start.x,
                 state->start.y, state->type);
            state->prev = state->start;
            break;
        default:		/* can't happen */
            return -1;
    }
    return code;
}
Esempio n. 2
0
/* otherwise, return the element type. */
int
gs_path_enum_next(gs_path_enum * penum, gs_point ppts[3])
{
    gs_fixed_point fpts[3];
    int pe_op = gx_path_enum_next(penum, fpts);
    int code;

    switch (pe_op) {
	case 0:		/* all done */
	case gs_pe_closepath:
	    break;
	case gs_pe_curveto:
	    if ((code = gs_point_transform_inverse(
						      fixed2float(fpts[1].x),
						      fixed2float(fpts[1].y),
					      &penum->mat, &ppts[1])) < 0 ||
		(code = gs_point_transform_inverse(
						      fixed2float(fpts[2].x),
						      fixed2float(fpts[2].y),
						&penum->mat, &ppts[2])) < 0)
		return code;
	    /* falls through */
	case gs_pe_moveto:
	case gs_pe_lineto:
	    if ((code = gs_point_transform_inverse(
						      fixed2float(fpts[0].x),
						      fixed2float(fpts[0].y),
						&penum->mat, &ppts[0])) < 0)
		return code;
	default:		/* error */
	    break;
    }
    return pe_op;
}
Esempio n. 3
0
int
gs_itransform(gs_state * pgs, floatp x, floatp y, gs_point * pt)
{				/* If the matrix isn't skewed, we get more accurate results */
    /* by using transform_inverse than by using the inverse matrix. */
    if (!is_skewed(&pgs->ctm)) {
        return gs_point_transform_inverse(x, y, &ctm_only(pgs), pt);
    } else {
        ensure_inverse_valid(pgs);
        return gs_point_transform(x, y, &pgs->ctm_inverse, pt);
    }
}
Esempio n. 4
0
int
gdev_vector_dopath(gx_device_vector *vdev, const gx_path * ppath,
                   gx_path_type_t type, const gs_matrix *pmat)
{
    bool do_close =
        (type & (gx_path_type_stroke | gx_path_type_always_close)) != 0;
    gs_fixed_rect rbox;
    gx_path_rectangular_type rtype = gx_path_is_rectangular(ppath, &rbox);
    gs_path_enum cenum;
    gdev_vector_dopath_state_t state;
    gs_fixed_point line_start, line_end;
    bool incomplete_line = false;
    bool need_moveto = false;
    int code;

    gdev_vector_dopath_init(&state, vdev, type, pmat);
    /*
     * if the path type is stroke, we only recognize closed
     * rectangles; otherwise, we recognize all rectangles.
     * Note that for stroking with a transformation, we can't use dorect,
     * which requires (untransformed) device coordinates.
     */
    if (rtype != prt_none &&
        (!(type & gx_path_type_stroke) || rtype == prt_closed) &&
        (pmat == 0 || is_xxyy(pmat) || is_xyyx(pmat)) &&
        (state.scale_mat.xx == 1.0 && state.scale_mat.yy == 1.0 &&
         is_xxyy(&state.scale_mat) &&
         is_fzero2(state.scale_mat.tx, state.scale_mat.ty))
        ) {
        gs_point p, q;

        gs_point_transform_inverse((double)rbox.p.x, (double)rbox.p.y,
                                   &state.scale_mat, &p);
        gs_point_transform_inverse((double)rbox.q.x, (double)rbox.q.y,
                                   &state.scale_mat, &q);
        code = vdev_proc(vdev, dorect)(vdev, (fixed)p.x, (fixed)p.y,
                                       (fixed)q.x, (fixed)q.y, type);
        if (code >= 0)
            return code;
        /* If the dorect proc failed, use a general path. */
    }
    code = vdev_proc(vdev, beginpath)(vdev, type);
    if (code < 0)
        return code;
    gx_path_enum_init(&cenum, ppath);
    for (;;) {
        gs_fixed_point vs[3];
        int pe_op = gx_path_enum_next(&cenum, vs);

    sw:
        if (type & gx_path_type_optimize) {
        opt:
            /* RJW: We fail to optimize gaptos */
            if (pe_op == gs_pe_lineto) {
                if (!incomplete_line) {
                    line_end = vs[0];
                    incomplete_line = true;
                    continue;
                }
                /*
                 * Merge collinear horizontal or vertical line segments
                 * going in the same direction.
                 */
                if (vs[0].x == line_end.x) {
                    if (vs[0].x == line_start.x &&
                        coord_between(line_start.y, line_end.y, vs[0].y)
                        ) {
                        line_end.y = vs[0].y;
                        continue;
                    }
                } else if (vs[0].y == line_end.y) {
                    if (vs[0].y == line_start.y &&
                        coord_between(line_start.x, line_end.x, vs[0].x)
                        ) {
                        line_end.x = vs[0].x;
                        continue;
                    }
                }
            }
            if (incomplete_line) {
                if (need_moveto) {	/* see gs_pe_moveto case */
                    code = gdev_vector_dopath_segment(&state, gs_pe_moveto,
                                                      &line_start);
                    if (code < 0)
                        return code;
                    need_moveto = false;
                }
                code = gdev_vector_dopath_segment(&state, gs_pe_lineto,
                                                  &line_end);
                if (code < 0)
                    return code;
                line_start = line_end;
                incomplete_line = false;
                goto opt;
            }
        }
        switch (pe_op) {
        case 0:		/* done */
        done:
            code = vdev_proc(vdev, endpath)(vdev, type);
            return (code < 0 ? code : 0);
        case gs_pe_curveto:
            if (need_moveto) {	/* see gs_pe_moveto case */
                code = gdev_vector_dopath_segment(&state, gs_pe_moveto,
                                                  &line_start);
                if (code < 0)
                    return code;
                need_moveto = false;
            }
            line_start = vs[2];
            goto draw;
        case gs_pe_moveto:
            /*
             * A bug in Acrobat Reader 4 causes it to draw a single pixel
             * for a fill with an isolated moveto.  If we're doing a fill
             * without a stroke, defer emitting a moveto until we know that
             * the subpath has more elements.
             */
            line_start = vs[0];
            if (!(type & gx_path_type_stroke) && (type & gx_path_type_fill)) {
                need_moveto = true;
                continue;
            }
            goto draw;
        case gs_pe_lineto:
        case gs_pe_gapto:
            if (need_moveto) {	/* see gs_pe_moveto case */
                code = gdev_vector_dopath_segment(&state, gs_pe_moveto,
                                                  &line_start);
                if (code < 0)
                    return code;
                need_moveto = false;
            }
            line_start = vs[0];
            goto draw;
        case gs_pe_closepath:
            if (need_moveto) {	/* see gs_pe_moveto case */
                need_moveto = false;
                continue;
            }
            if (!do_close) {
                pe_op = gx_path_enum_next(&cenum, vs);
                if (pe_op == 0)
                    goto done;
                code = gdev_vector_dopath_segment(&state, gs_pe_closepath, vs);
                if (code < 0)
                    return code;
                goto sw;
            }
            /* falls through */
        draw:
            code = gdev_vector_dopath_segment(&state, pe_op, vs);
            if (code < 0)
                return code;
        }
        incomplete_line = false; /* only needed if optimizing */
    }
}