예제 #1
0
/* Check whether color is a shading with BBox. */
int
gx_dc_pattern2_is_rectangular_cell(const gx_device_color * pdevc, gx_device * pdev, gs_fixed_rect *rect)
{
    if (gx_dc_is_pattern2_color(pdevc) && gx_dc_pattern2_color_has_bbox(pdevc) &&
            (*dev_proc(pdev, dev_spec_op))(pdev, gxdso_pattern_shading_area, NULL, 0) == 0) {
        gs_pattern2_instance_t *pinst = (gs_pattern2_instance_t *)pdevc->ccolor.pattern;
        const gs_shading_t *psh = pinst->templat.Shading;
        gs_fixed_point p, q;

        if (is_xxyy(&ctm_only(pinst->saved)))
            if (psh->params.have_BBox) {
                int code = gs_point_transform2fixed(&pinst->saved->ctm,
                            psh->params.BBox.p.x, psh->params.BBox.p.y, &p);
                if (code < 0)
                    return code;
                code = gs_point_transform2fixed(&pinst->saved->ctm,
                            psh->params.BBox.q.x, psh->params.BBox.q.y, &q);
                if (code < 0)
                    return code;
                if (p.x > q.x) {
                    p.x ^= q.x; q.x ^= p.x; p.x ^= q.x;
                }
                if (p.y > q.y) {
                    p.y ^= q.y; q.y ^= p.y; p.y ^= q.y;
                }
                rect->p = p;
                rect->q = q;
                return 1;
            }
    }
    return 0;
}
예제 #2
0
/* the character, as opposed to just computing the side bearing and width. */
void
gs_type1_finish_init(gs_type1_state * pcis)
{
    gs_imager_state *pis = pcis->pis;
    const int max_coeff_bits = 11;	/* max coefficient in char space */

    /* Set up the fixed version of the transformation. */
    gx_matrix_to_fixed_coeff(&ctm_only(pis), &pcis->fc, max_coeff_bits);

    /* Set the current point of the path to the origin, */
    pcis->origin.x = pcis->path->position.x;
    pcis->origin.y = pcis->path->position.y;

    /* Initialize hint-related scalars. */
    pcis->asb_diff = pcis->adxy.x = pcis->adxy.y = 0;
    pcis->base_lsb = 0;
    pcis->flex_count = flex_max;	/* not in Flex */
    pcis->vs_offset.x = pcis->vs_offset.y = 0;


    /* Compute the flatness needed for accurate rendering. */
    pcis->flatness = gs_char_flatness(pis, 0.001);

    pcis->init_done = 1;
}
예제 #3
0
int
gs_upathbbox(gs_state * pgs, gs_rect * pbox, bool include_moveto)
{
    gs_fixed_rect fbox;		/* box in device coordinates */
    gs_rect dbox;
    int code = gx_path_bbox_set(pgs->path, &fbox);

    if (code < 0)
	return code;
    /* If the path ends with a moveto and include_moveto is true, */
    /* include the moveto in the bounding box. */
    if (path_last_is_moveto(pgs->path) && include_moveto) {
	gs_fixed_point pt;

	code = gx_path_current_point_inline(pgs->path, &pt);
        if (code < 0)
	    return code;
	if (pt.x < fbox.p.x)
	    fbox.p.x = pt.x;
	if (pt.y < fbox.p.y)
	    fbox.p.y = pt.y;
	if (pt.x > fbox.q.x)
	    fbox.q.x = pt.x;
	if (pt.y > fbox.q.y)
	    fbox.q.y = pt.y;
    }
    /* Transform the result back to user coordinates. */
    dbox.p.x = fixed2float(fbox.p.x);
    dbox.p.y = fixed2float(fbox.p.y);
    dbox.q.x = fixed2float(fbox.q.x);
    dbox.q.y = fixed2float(fbox.q.y);
    return gs_bbox_transform_inverse(&dbox, &ctm_only(pgs), pbox);
}
예제 #4
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);
    }
}
예제 #5
0
static int
ctm_set_inverse(gs_state * pgs)
{
    int code = gs_matrix_invert(&ctm_only(pgs), &pgs->ctm_inverse);

    print_inverse(pgs);
    if (code < 0)
        return code;
    pgs->ctm_inverse_valid = true;
    return 0;
}
예제 #6
0
int
gs_rotate(gs_state * pgs, floatp ang)
{
    int code = gs_matrix_rotate(&ctm_only(pgs), ang,
                                &ctm_only_writable(pgs));

    pgs->ctm_inverse_valid = false, pgs->char_tm_valid = false;
#ifdef DEBUG
    if (gs_debug_c('x'))
        dlprintf1("[x]rotate: %f\n", ang), trace_ctm(pgs);
#endif
    return code;
}
예제 #7
0
/* This is just a bridge to an old code. */
int
gx_dc_pattern2_shade_bbox_transform2fixed(const gs_rect * rect, const gs_imager_state * pis,
                           gs_fixed_rect * rfixed)
{
    gs_rect dev_rect;
    int code = gs_bbox_transform(rect, &ctm_only(pis), &dev_rect);

    if (code >= 0) {
        rfixed->p.x = float2fixed(dev_rect.p.x);
        rfixed->p.y = float2fixed(dev_rect.p.y);
        rfixed->q.x = float2fixed(dev_rect.q.x);
        rfixed->q.y = float2fixed(dev_rect.q.y);
    }
    return code;
}
예제 #8
0
int
gs_concat(gs_state * pgs, const gs_matrix * pmat)
{
    gs_matrix cmat;
    int code = gs_matrix_multiply(pmat, &ctm_only(pgs), &cmat);

    if (code < 0)
        return code;
    update_ctm(pgs, cmat.tx, cmat.ty);
    set_ctm_only(pgs, cmat);
#ifdef DEBUG
    if (gs_debug_c('x'))
        dlprintf("[x]concat:\n"), trace_matrix(pmat), trace_ctm(pgs);
#endif
    return code;
}
예제 #9
0
RELOC_PTRS_END

static int
is_image_visible(const gs_image_common_t * pic, gs_state * pgs, gx_clip_path *pcpath)
{
    /* HACK : We need the source image size here, 
       but gs_image_common_t doesn't pass it.
       We would like to move Width, Height to gs_image_common,
       but gs_image2_t appears to have those fields of double type.
     */
    if (pic->type->begin_typed_image == gx_begin_image1) {
	gs_image1_t *pim = (gs_image1_t *) pic;
	gs_rect image_rect = {{0, 0}, {0, 0}};
	gs_rect device_rect;
	gs_int_rect device_int_rect;
	gs_matrix mat;
	int code;

	image_rect.q.x = pim->Width;
	image_rect.q.y = pim->Height;
	if (pic->ImageMatrix.xx == ctm_only(pgs).xx &&
            pic->ImageMatrix.xy == ctm_only(pgs).xy &&
            pic->ImageMatrix.yx == ctm_only(pgs).yx &&
            pic->ImageMatrix.yy == ctm_only(pgs).yy) {
            /* Handle common special case separately to accept singular matrix */
            mat.xx = mat.yy = 1.;
            mat.yx = mat.xy = 0.;
            mat.tx = ctm_only(pgs).tx - pic->ImageMatrix.tx;
            mat.ty = ctm_only(pgs).ty - pic->ImageMatrix.ty;
        } else {
	code = gs_matrix_invert(&pic->ImageMatrix, &mat);
	if (code < 0)
	    return code;
	code = gs_matrix_multiply(&mat, &ctm_only(pgs), &mat);
	if (code < 0)
	    return code;
        }
	code = gs_bbox_transform(&image_rect, &mat, &device_rect);
	if (code < 0)
	    return code;
	device_int_rect.p.x = (int)floor(device_rect.p.x);
	device_int_rect.p.y = (int)floor(device_rect.p.y);
	device_int_rect.q.x = (int)ceil(device_rect.q.x);
	device_int_rect.q.y = (int)ceil(device_rect.q.y);
	if (!gx_cpath_rect_visible(pcpath, &device_int_rect))
	    return 0;
    }
    return 1;
}
예제 #10
0
void
xps_bounds_in_user_space(xps_context_t *ctx, gs_rect *ubox)
{
    gx_clip_path *clip_path;
    gs_rect dbox;
    int code;

    code = gx_effective_clip_path(ctx->pgs, &clip_path);
    if (code < 0)
        gs_warn("gx_effective_clip_path failed");

    dbox.p.x = fixed2float(clip_path->outer_box.p.x);
    dbox.p.y = fixed2float(clip_path->outer_box.p.y);
    dbox.q.x = fixed2float(clip_path->outer_box.q.x);
    dbox.q.y = fixed2float(clip_path->outer_box.q.y);
    gs_bbox_transform_inverse(&dbox, &ctm_only(ctx->pgs), ubox);
}
예제 #11
0
/* The caller must supply a string to the first call of gs_type1_interpret. */
int
gs_type1_init(register gs_type1_state *pis, gs_show_enum *penum,
  int charpath_flag, int paint_type, gs_type1_data *pdata)
{	gs_state *pgs = penum->pgs;
	pis->penum = penum;
	pis->pgs = pgs;
	pis->pdata = pdata;
	pis->charpath_flag = charpath_flag;
	pis->paint_type = paint_type;
	pis->os_count = 0;
	pis->ips_count = 1;
	pis->seac_base = -1;
	pis->in_dotsection = 0;
	pis->vstem3_set = 0;
	pis->vs_offset.x = pis->vs_offset.y = 0;
	reset_stem_hints(pis);
	gx_matrix_to_fixed_coeff(&ctm_only(pgs), &pis->fc, max_coeff_bits);
	compute_font_hints(&pis->fh, &pgs->ctm, pdata);
	/* Set the current point of the path to the origin, */
	/* in anticipation of the initial [h]sbw. */
	{ gx_path *ppath = pgs->path;
	  ppath->position.x = pgs->ctm.tx_fixed;
	  ppath->position.y = pgs->ctm.ty_fixed;
	}
	/* Set the flatness to a value that is likely to produce */
	/* reasonably good-looking curves, regardless of its */
	/* current value in the graphics state. */
	   {	/* If the character is very small, set the flatness */
		/* to zero, which will produce very accurate curves. */
		float cxx = pgs->ctm.xx, cyy = pgs->ctm.yy;
		if ( cxx < 0 ) cxx = -cxx;
		if ( cyy < 0 ) cyy = -cyy;
		if ( cyy > cxx ) cxx = cyy;
		if ( is_skewed(&pgs->ctm) )
		   {	float cxy = pgs->ctm.xy, cyx = pgs->ctm.yx;
			if ( cxy < 0 ) cxy = -cxy;
			if ( cyx < 0 ) cyx = -cyx;
			if ( cxy > cxx ) cxx = cxy;
			if ( cyx > cxx ) cxx = cyx;
		   }
		/* Now cxx is approximately one character space unit */
		/* in device pixels. */
		pis->flatness = (cxx >= 0.2 ? cxx : 0.0);
	   }
	return 0;
}
예제 #12
0
/* Note that this may be based on a font other than the current font. */
int
gs_setcharmatrix(gs_state * pgs, const gs_matrix * pmat)
{
    gs_matrix cmat;
    int code = gs_matrix_multiply(pmat, &ctm_only(pgs), &cmat);

    if (code < 0)
        return code;
    update_matrix_fixed(pgs->char_tm, cmat.tx, cmat.ty);
    char_tm_only(pgs) = cmat;
#ifdef DEBUG
    if (gs_debug_c('x'))
        dlprintf("[x]setting char_tm:"), trace_matrix_fixed(&pgs->char_tm);
#endif
    pgs->char_tm_valid = true;
    return 0;
}
예제 #13
0
/* Set the bounding box for the current path. */
int
gs_setbbox(gs_state * pgs, double llx, double lly, double urx, double ury)
{
    gs_rect ubox, dbox;
    gs_fixed_rect obox, bbox;
    gx_path *ppath = pgs->path;
    int code;

    if (llx > urx || lly > ury)
        return_error(gs_error_rangecheck);
    /* Transform box to device coordinates. */
    ubox.p.x = llx;
    ubox.p.y = lly;
    ubox.q.x = urx;
    ubox.q.y = ury;
    if ((code = gs_bbox_transform(&ubox, &ctm_only(pgs), &dbox)) < 0)
        return code;
    /* Round the corners in opposite directions. */
    /* Because we can't predict the magnitude of the dbox values, */
    /* we add/subtract the slop after fixing. */
    if (dbox.p.x < fixed2float(min_fixed + box_rounding_slop_fixed) ||
        dbox.p.y < fixed2float(min_fixed + box_rounding_slop_fixed) ||
        dbox.q.x >= fixed2float(max_fixed - box_rounding_slop_fixed + fixed_epsilon) ||
        dbox.q.y >= fixed2float(max_fixed - box_rounding_slop_fixed + fixed_epsilon)
        )
        return_error(gs_error_limitcheck);
    bbox.p.x =
        (fixed) floor(dbox.p.x * fixed_scale) - box_rounding_slop_fixed;
    bbox.p.y =
        (fixed) floor(dbox.p.y * fixed_scale) - box_rounding_slop_fixed;
    bbox.q.x =
        (fixed) ceil(dbox.q.x * fixed_scale) + box_rounding_slop_fixed;
    bbox.q.y =
        (fixed) ceil(dbox.q.y * fixed_scale) + box_rounding_slop_fixed;
    if (gx_path_bbox_set(ppath, &obox) >= 0) {	/* Take the union of the bboxes. */
        ppath->bbox.p.x = min(obox.p.x, bbox.p.x);
        ppath->bbox.p.y = min(obox.p.y, bbox.p.y);
        ppath->bbox.q.x = max(obox.q.x, bbox.q.x);
        ppath->bbox.q.y = max(obox.q.y, bbox.q.y);
    } else {			/* empty path *//* Just set the bbox. */
        ppath->bbox = bbox;
    }
    ppath->bbox_set = 1;
    return 0;
}
예제 #14
0
static inline int
gs_arc_add_inline(gs_state *pgs, bool cw, floatp xc, floatp yc, floatp rad, 
		    floatp a1, floatp a2, bool add)
{
    gs_point p3;
    int code = gs_imager_arc_add(pgs->path, (gs_imager_state *)pgs, cw, xc, yc, rad, a1, a2, add, &p3);

    if (code < 0)
	return code;

#if !PRECISE_CURRENTPOINT
    return gx_setcurrentpoint_from_path((gs_imager_state *)pgs, pgs->path);
#else
    pgs->current_point_valid = true;
    return gs_point_transform(p3.x, p3.y, &ctm_only(pgs), &pgs->current_point);
#endif

}
예제 #15
0
int
gs_translate(gs_state * pgs, floatp dx, floatp dy)
{
    gs_point pt;
    int code;

    if ((code = gs_distance_transform(dx, dy, &ctm_only(pgs), &pt)) < 0)
        return code;
    pt.x = (float)pt.x + pgs->ctm.tx;
    pt.y = (float)pt.y + pgs->ctm.ty;
    update_ctm(pgs, pt.x, pt.y);
#ifdef DEBUG
    if (gs_debug_c('x'))
        dlprintf4("[x]translate: %f %f -> %f %f\n",
                  dx, dy, pt.x, pt.y),
            trace_ctm(pgs);
#endif
    return 0;
}
예제 #16
0
static int
bbox_image_begin(const gs_imager_state * pis, const gs_matrix * pmat,
		 const gs_image_common_t * pic, const gs_int_rect * prect,
		 const gx_clip_path * pcpath, gs_memory_t * memory,
		 bbox_image_enum ** ppbe)
{
    int code;
    gs_matrix mat;
    bbox_image_enum *pbe;

    if (pmat == 0)
	pmat = &ctm_only(pis);
    if ((code = gs_matrix_invert(&pic->ImageMatrix, &mat)) < 0 ||
	(code = gs_matrix_multiply(&mat, pmat, &mat)) < 0
	)
	return code;
    pbe = gs_alloc_struct(memory, bbox_image_enum, &st_bbox_image_enum,
			  "bbox_image_begin");
    if (pbe == 0)
	return_error(gs_error_VMerror);
    pbe->memory = memory;
    pbe->matrix = mat;
    pbe->pcpath = pcpath;
    pbe->target_info = 0;	/* in case no target */
    pbe->params_are_const = false;	/* check the first time */
    if (prect) {
	pbe->x0 = prect->p.x, pbe->x1 = prect->q.x;
	pbe->y = prect->p.y, pbe->height = prect->q.y - prect->p.y;
    } else {
	gs_int_point size;
	int code = (*pic->type->source_size) (pis, pic, &size);

	if (code < 0) {
	    gs_free_object(memory, pbe, "bbox_image_begin");
	    return code;
	}
	pbe->x0 = 0, pbe->x1 = size.x;
	pbe->y = 0, pbe->height = size.y;
    }
    *ppbe = pbe;
    return 0;
}
예제 #17
0
static int
pdf_make_form_dict(gx_device_pdf * pdev, const gs_pdf14trans_params_t * pparams,
			    const gs_imager_state * pis, 
			    const cos_dict_t *group_dict, cos_dict_t *form_dict)
{
    cos_array_t *bbox_array;
    float bbox[4];
    gs_rect bbox_rect;
    int code;


    code = gs_bbox_transform(&pparams->bbox, &ctm_only(pis), &bbox_rect);
    if (code < 0)
	return code;
    bbox[0] = bbox_rect.p.x;
    bbox[1] = bbox_rect.p.y;
    bbox[2] = bbox_rect.q.x;
    bbox[3] = bbox_rect.q.y;
    code = cos_dict_put_c_key_string(form_dict, "/Type", (const byte *)"/XObject", 8);
    if (code < 0)
	return code;
    code = cos_dict_put_c_key_string(form_dict, "/Subtype", (const byte *)"/Form", 5);
    if (code < 0)
	return code;
    code = cos_dict_put_c_key_int(form_dict, "/FormType", 1);
    if (code < 0)
	return code;
    code = cos_dict_put_c_key_string(form_dict, "/Matrix", (const byte *)"[1 0 0 1 0 0]", 13);
    if (code < 0)
	return code;
    bbox_array = cos_array_from_floats(pdev, bbox, 4, "pdf_begin_transparency_group");
    if (bbox_array == NULL)
	return_error(gs_error_VMerror);
    code = cos_dict_put_c_key_object(form_dict, "/BBox", (cos_object_t *)bbox_array);
    if (code < 0)
	return code;
    return cos_dict_put_c_key_object(form_dict, "/Group", (cos_object_t *)group_dict);
}
예제 #18
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);
}
예제 #19
0
	char buf[MAX_REF_CHARS + 6 + 1]; /* +6 for /R# Do\n */

	sprintf(buf, "/R%ld Do\n", pcs_image->id);
	cos_stream_add_bytes(pcos, (const byte *)buf, strlen(buf));
    }

    return 0;
}

/* Store pattern 1 parameters to cos dictionary. */
int 
pdf_store_pattern1_params(gx_device_pdf *pdev, pdf_resource_t *pres, 
			gs_pattern1_instance_t *pinst)
{
    gs_pattern1_template_t *t = &pinst->template;
    gs_matrix smat = ctm_only((gs_imager_state *)pinst->saved);
    double scale_x = pdev->HWResolution[0] / 72.0;
    double scale_y = pdev->HWResolution[1] / 72.0;
    cos_dict_t *pcd = cos_stream_dict((cos_stream_t *)pres->object);
    cos_dict_t *pcd_Resources = cos_dict_alloc(pdev, "pdf_pattern(Resources)");
    float bbox[4];
    int code;

    if (pcd == NULL || pcd_Resources == NULL)
	return_error(gs_error_VMerror);
    pdev->substream_Resources = pcd_Resources;
    bbox[0] = t->BBox.p.x;
    bbox[1] = t->BBox.p.y;
    bbox[2] = t->BBox.q.x;
    bbox[3] = t->BBox.q.y;
    /* The graphics library assumes a shifted origin to provide 
예제 #20
0
int
gs_dtransform(gs_state * pgs, floatp dx, floatp dy, gs_point * pt)
{
    return gs_distance_transform(dx, dy, &ctm_only(pgs), pt);
}
예제 #21
0
int
gs_transform(gs_state * pgs, floatp x, floatp y, gs_point * pt)
{
    return gs_point_transform(x, y, &ctm_only(pgs), pt);
}
예제 #22
0
int
xps_high_level_pattern(xps_context_t *ctx)
{
    gs_matrix m;
    gs_rect bbox;
    gs_fixed_rect clip_box;
    int code;
    gx_device_color *pdc = gs_currentdevicecolor_inline(ctx->pgs);
    const gs_client_pattern *ppat = gs_getpattern(&pdc->ccolor);
    gs_pattern1_instance_t *pinst =
        (gs_pattern1_instance_t *)gs_currentcolor(ctx->pgs)->pattern;

    code = gx_pattern_cache_add_dummy_entry((gs_imager_state *)ctx->pgs,
        pinst, ctx->pgs->device->color_info.depth);
    if (code < 0)
        return code;

    code = gs_gsave(ctx->pgs);
    if (code < 0)
        return code;

    dev_proc(ctx->pgs->device, get_initial_matrix)(ctx->pgs->device, &m);
    gs_setmatrix(ctx->pgs, &m);
    code = gs_bbox_transform(&ppat->BBox, &ctm_only(ctx->pgs), &bbox);
    if (code < 0) {
        gs_grestore(ctx->pgs);
        return code;
    }
    clip_box.p.x = float2fixed(bbox.p.x);
    clip_box.p.y = float2fixed(bbox.p.y);
    clip_box.q.x = float2fixed(bbox.q.x);
    clip_box.q.y = float2fixed(bbox.q.y);
    code = gx_clip_to_rectangle(ctx->pgs, &clip_box);
    if (code < 0) {
        gs_grestore(ctx->pgs);
        return code;
    }

    {
        pattern_accum_param_s param;
        param.pinst = (void *)pinst;
        param.graphics_state = (void *)ctx->pgs;
        param.pinst_id = pinst->id;

        code = (*dev_proc(ctx->pgs->device, dev_spec_op))((gx_device *)ctx->pgs->device,
            gxdso_pattern_start_accum, &param, sizeof(pattern_accum_param_s));
    }

    if (code < 0) {
        gs_grestore(ctx->pgs);
        return code;
    }

    code = xps_paint_tiling_brush(&pdc->ccolor, ctx->pgs);
    if (code) {
        gs_grestore(ctx->pgs);
        return gs_rethrow(code, "high level pattern brush function failed");
    }

    code = gs_grestore(ctx->pgs);
    if (code < 0)
        return code;

    {
        pattern_accum_param_s param;
        param.pinst = (void *)pinst;
        param.graphics_state = (void *)ctx->pgs;
        param.pinst_id = pinst->id;

        code = (*dev_proc(ctx->pgs->device, dev_spec_op))((gx_device *)ctx->pgs->device,
            gxdso_pattern_finish_accum, &param, sizeof(pattern_accum_param_s));
    }

    return code;
}
예제 #23
0
static int
charstring_execchar_aux(i_ctx_t *i_ctx_p, gs_text_enum_t *penum, gs_font *pfont)
{
    os_ptr op = osp;
    gs_font_base *const pbfont = (gs_font_base *) pfont;
    gs_font_type1 *const pfont1 = (gs_font_type1 *) pfont;
    const gs_type1_data *pdata;
    gs_type1exec_state cxs;
    gs_type1_state *const pcis = &cxs.cis;
    gs_rect FontBBox = pfont1->FontBBox;
    int code;

    if (penum->current_font->FontType == ft_CID_encrypted) {
        if (FontBBox.q.x <= FontBBox.p.x && FontBBox.q.y <= FontBBox.p.y) {
            gs_font_cid0 *pfcid0 = (gs_font_cid0 *)penum->current_font;

            FontBBox = pfcid0->FontBBox;
        }
    }

    pdata = &pfont1->data;
    /*
     * Any reasonable implementation would execute something like
     *    1 setmiterlimit 0 setlinejoin 0 setlinecap
     * here, but the Adobe implementations don't.
     *
     * If this is a stroked font, set the stroke width.
     */
    if (pfont->PaintType)
        gs_setlinewidth(igs, pfont->StrokeWidth);
    check_estack(3);		/* for continuations */
    /*
     * Execute the definition of the character.
     */
    if (r_is_proc(op))
        return zchar_exec_char_proc(i_ctx_p);
    /*
     * The definition must be a Type 1 CharString.
     * Note that we do not require read access: this is deliberate.
     */
    check_type(*op, t_string);
    if (r_size(op) <= max(pdata->lenIV, 0))
        return_error(e_invalidfont);
    /*
     * In order to make character oversampling work, we must
     * set up the cache before calling .type1addpath.
     * To do this, we must get the bounding box from the FontBBox,
     * and the width from the CharString or the Metrics.
     * If the FontBBox isn't valid, we can't do any of this.
     */

    if ((penum->FontBBox_as_Metrics2.x == 0 &&
         penum->FontBBox_as_Metrics2.y == 0) ||
        gs_rootfont(igs)->WMode == 0 ) {
        code = zchar_get_metrics(pbfont, op - 1, cxs.sbw);
        if (code < 0)
            return code;
        cxs.present = code;
        cxs.use_FontBBox_as_Metrics2 = false;
    }  else {  /* pass here if FontType==9,11 && WMode==1*/
        cxs.sbw[0] = penum->FontBBox_as_Metrics2.x / 2;
        cxs.sbw[1] = penum->FontBBox_as_Metrics2.y;
        cxs.sbw[2] = 0;
        cxs.sbw[3] = -penum->FontBBox_as_Metrics2.x; /* Sic! */
        cxs.use_FontBBox_as_Metrics2 = true;
        cxs.present = metricsNone;
    }
    /* Establish a current point. */
    code = gs_moveto(igs, 0.0, 0.0);
    if (code < 0)
        return code;
    code = type1_exec_init(pcis, penum, igs, pfont1);
    if (code < 0)
        return code;
    gs_type1_set_callback_data(pcis, &cxs);
    if (FontBBox.q.x > FontBBox.p.x &&
        FontBBox.q.y > FontBBox.p.y
        ) {
        /* The FontBBox appears to be valid. */
        op_proc_t exec_cont = 0;

        cxs.char_bbox = pfont1->FontBBox;
        code = type1exec_bbox(i_ctx_p, penum, &cxs, pfont, &exec_cont);
        if (code >= 0 && exec_cont != 0)
            code = (*exec_cont)(i_ctx_p);
        return code;
    } else {
        /* The FontBBox is not valid */
        const ref *opstr = op;
        ref other_subr;
        const gs_matrix * pctm = &ctm_only(igs);

        /* First, check for singular CTM */
        if (pctm->xx * pctm->yy == pctm->xy * pctm->yx) {
           /* The code below won't be able to find the FontBBox but we
            * don't need it anyway. Set an empty box and consider it valid.
            */
            op_proc_t exec_cont = 0;

            cxs.char_bbox.p.x = 0;
            cxs.char_bbox.p.y = 0;
            cxs.char_bbox.q.x = 0;
            cxs.char_bbox.q.y = 0;
            code = type1exec_bbox(i_ctx_p, penum, &cxs, pfont, &exec_cont);
            if (code >= 0 && exec_cont != 0)
                code = (*exec_cont)(i_ctx_p);
            return code;
        }
        /* Now we create the path first, then do the setcachedevice.
         * If we are oversampling (in this case, only for anti-
         * aliasing, not just to improve quality), we have to
         * create the path twice, since we can't know the
         * oversampling factor until after setcachedevice.
         */
        switch (cxs.present) {
            case metricsSideBearingAndWidth: {
                gs_point pt;

                pt.x = cxs.sbw[0], pt.y = cxs.sbw[1];
                gs_type1_set_lsb(pcis, &pt);
            }
            /* fall through */
            case metricsWidthOnly: {
                gs_point pt;

                pt.x = cxs.sbw[2], pt.y = cxs.sbw[3];
                gs_type1_set_width(pcis, &pt);
            }
        }

        /* Continue interpreting. */
      icont:
        code = type1_continue_dispatch(i_ctx_p, &cxs, opstr, &other_subr, 4);
        op = osp;		/* OtherSubrs might change it */
        switch (code) {
            case 0:		/* all done */
                return nobbox_finish(i_ctx_p, &cxs);
            default:		/* code < 0, error */
                return code;
            case type1_result_callothersubr:	/* unknown OtherSubr */
                return type1_call_OtherSubr(i_ctx_p, &cxs, nobbox_continue,
                                            &other_subr);
            case type1_result_sbw:	/* [h]sbw, just continue */
                switch (cxs.present) {
                    case metricsNone:
                        cxs.sbw[0] = fixed2float(pcis->lsb.x);
                        cxs.sbw[1] = fixed2float(pcis->lsb.y);
                    /* fall through */
                    case metricsWidthOnly:
                        cxs.sbw[2] = fixed2float(pcis->width.x);
                        cxs.sbw[3] = fixed2float(pcis->width.y);
                }
                opstr = 0;
                goto icont;
        }
    }
}
예제 #24
0
int
gs_imager_idtransform(const gs_imager_state * pis, floatp dx, floatp dy,
                      gs_point * pt)
{
    return gs_distance_transform_inverse(dx, dy, &ctm_only(pis), pt);
}
예제 #25
0
/*
 * Continue interpreting a Type 2 charstring.  If str != 0, it is taken as
 * the byte string to interpret.  Return 0 on successful completion, <0 on
 * error, or >0 when client intervention is required (or allowed).  The int*
 * argument is only for compatibility with the Type 1 charstring interpreter.
 */
int
gs_type2_interpret(gs_type1_state * pcis, const gs_glyph_data_t *pgd,
                   int *ignore_pindex)
{
    gs_font_type1 *pfont = pcis->pfont;
    gs_type1_data *pdata = &pfont->data;
    t1_hinter *h = &pcis->h;
    bool encrypted = pdata->lenIV >= 0;
    fixed cstack[ostack_size];
    cs_ptr csp;
#define clear CLEAR_CSTACK(cstack, csp)
    ip_state_t *ipsp = &pcis->ipstack[pcis->ips_count - 1];
    register const byte *cip;
    register crypt_state state;
    register int c;
    cs_ptr ap;
    bool vertical;
    int code = 0;

/****** FAKE THE REGISTRY ******/
    struct {
        float *values;
        uint size;
    } Registry[1];

    Registry[0].values = pcis->pfont->data.WeightVector.values;

    switch (pcis->init_done) {
        case -1:
            t1_hinter__init(h, pcis->path);
            break;
        case 0:
            gs_type1_finish_init(pcis);	/* sets origin */
            code = t1_hinter__set_mapping(h, &pcis->pis->ctm,
                            &pfont->FontMatrix, &pfont->base->FontMatrix,
                            pcis->scale.x.log2_unit, pcis->scale.x.log2_unit,
                            pcis->scale.x.log2_unit - pcis->log2_subpixels.x,
                            pcis->scale.y.log2_unit - pcis->log2_subpixels.y,
                            pcis->origin.x, pcis->origin.y,
                            gs_currentaligntopixels(pfont->dir));
            if (code < 0)
                return code;
            code = t1_hinter__set_font_data(h, 2, pdata, pcis->no_grid_fitting,
                            pcis->pfont->is_resource);
            if (code < 0)
                return code;
            break;
        default /*case 1 */ :
            break;
    }
    INIT_CSTACK(cstack, csp, pcis);

    if (pgd == 0)
        goto cont;
    ipsp->cs_data = *pgd;
    cip = pgd->bits.data;
    if (cip == 0)
        return (gs_note_error(gs_error_invalidfont));
  call:state = crypt_charstring_seed;
    if (encrypted) {
        int skip = pdata->lenIV;

        /* Skip initial random bytes */
        for (; skip > 0; ++cip, --skip)
            decrypt_skip_next(*cip, state);
    }
    goto top;
  cont:if (ipsp < pcis->ipstack || ipsp->ip == 0)
        return (gs_note_error(gs_error_invalidfont));
    cip = ipsp->ip;
    state = ipsp->dstate;
  top:for (;;) {
        uint c0 = *cip++;

        charstring_next(c0, state, c, encrypted);
        if (c >= c_num1) {
            /* This is a number, decode it and push it on the stack. */

            if (c < c_pos2_0) {	/* 1-byte number */
                decode_push_num1(csp, cstack, c);
            } else if (c < cx_num4) {	/* 2-byte number */
                decode_push_num2(csp, cstack, c, cip, state, encrypted);
            } else if (c == cx_num4) {	/* 4-byte number */
                long lw;

                decode_num4(lw, cip, state, encrypted);
                /* 32-bit numbers are 16:16. */
                CS_CHECK_PUSH(csp, cstack);
                *++csp = arith_rshift(lw, 16 - _fixed_shift);
            } else		/* not possible */
                return_error(gs_error_invalidfont);
          pushed:if_debug3('1', "[1]%d: (%d) %f\n",
                      (int)(csp - cstack), c, fixed2float(*csp));
            continue;
        }
#ifdef DEBUG
        if (gs_debug['1']) {
            static const char *const c2names[] =
            {char2_command_names};

            if (c2names[c] == 0)
                dlprintf2("[1]0x%lx: %02x??\n", (ulong) (cip - 1), c);
            else
                dlprintf3("[1]0x%lx: %02x %s\n", (ulong) (cip - 1), c,
                          c2names[c]);
        }
#endif
        switch ((char_command) c) {
#define cnext clear; goto top

                /* Commands with identical functions in Type 1 and Type 2, */
                /* except for 'escape'. */

            case c_undef0:
            case c_undef2:
            case c_undef17:
                return_error(gs_error_invalidfont);
            case c_callsubr:
                c = fixed2int_var(*csp) + pdata->subroutineNumberBias;
                code = pdata->procs.subr_data
                    (pfont, c, false, &ipsp[1].cs_data);
              subr:if (code < 0) {
                    /* Calling a Subr with an out-of-range index is clearly a error:
                     * the Adobe documentation says the results of doing this are
                     * undefined. However, we have seen a PDF file produced by Adobe
                     * PDF Library 4.16 that included a Type 2 font that called an
                     * out-of-range Subr, and Acrobat Reader did not signal an error.
                     * Therefore, we ignore such calls.
                     */
                    cip++;
                    goto top;
                }
                --csp;
                ipsp->ip = cip, ipsp->dstate = state;
                ++ipsp;
                cip = ipsp->cs_data.bits.data;
                goto call;
            case c_return:
                gs_glyph_data_free(&ipsp->cs_data, "gs_type2_interpret");
                --ipsp;
                goto cont;
            case c_undoc15:
                /* See gstype1.h for information on this opcode. */
                cnext;

                /* Commands with similar but not identical functions */
                /* in Type 1 and Type 2 charstrings. */

            case cx_hstem:
                goto hstem;
            case cx_vstem:
                goto vstem;
            case cx_vmoveto:
                check_first_operator(csp > cstack);
                code = t1_hinter__rmoveto(h, 0, *csp);
              move:
              cc:
                if (code < 0)
                    return code;
                goto pp;
            case cx_rlineto:
                for (ap = cstack; ap + 1 <= csp; ap += 2) {
                    code = t1_hinter__rlineto(h, ap[0], ap[1]);
                    if (code < 0)
                        return code;
                }
              pp:
                cnext;
            case cx_hlineto:
                vertical = false;
                goto hvl;
            case cx_vlineto:
                vertical = true;
              hvl:for (ap = cstack; ap <= csp; vertical = !vertical, ++ap) {
                    if (vertical) {
                        code = t1_hinter__rlineto(h, 0, ap[0]);
                    } else {
                        code = t1_hinter__rlineto(h, ap[0], 0);
                    }
                    if (code < 0)
                        return code;
                }
                goto pp;
            case cx_rrcurveto:
                for (ap = cstack; ap + 5 <= csp; ap += 6) {
                    code = t1_hinter__rcurveto(h, ap[0], ap[1], ap[2],
                                            ap[3], ap[4], ap[5]);
                    if (code < 0)
                        return code;
                }
                goto pp;
            case cx_endchar:
                /*
                 * It is a feature of Type 2 CharStrings that if endchar is
                 * invoked with 4 or 5 operands, it is equivalent to the
                 * Type 1 seac operator. In this case, the asb operand of
                 * seac is missing: we assume it is the same as the
                 * l.s.b. of the accented character.  This feature was
                 * undocumented until the 16 March 2000 version of the Type
                 * 2 Charstring Format specification, but, thankfully, is
                 * described in that revision.
                 */
                if (csp >= cstack + 3) {
                    check_first_operator(csp > cstack + 3);
                    code = gs_type1_seac(pcis, cstack, 0, ipsp);
                    if (code < 0)
                        return code;
                    clear;
                    cip = ipsp->cs_data.bits.data;
                    goto call;
                }
                /*
                 * This might be the only operator in the charstring.
                 * In this case, there might be a width on the stack.
                 */
                check_first_operator(csp >= cstack);
                if (pcis->seac_accent < 0) {
                    code = t1_hinter__endglyph(h);
                    if (code < 0)
                        return code;
                    code = gx_setcurrentpoint_from_path(pcis->pis, pcis->path);
                    if (code < 0)
                        return code;
                } else {
                    t1_hinter__setcurrentpoint(h, pcis->save_adxy.x + pcis->origin_offset.x,
                                                  pcis->save_adxy.y + pcis->origin_offset.y);
                    code = t1_hinter__end_subglyph(h);
                    if (code < 0)
                        return code;
                }
                code = gs_type1_endchar(pcis);
                if (code == 1) {
                    /*
                     * Reset the total hint count so that hintmask will
                     * parse its following data correctly.
                     * (gs_type1_endchar already reset the actual hint
                     * tables.)
                     */
                    pcis->num_hints = 0;
                    /* do accent of seac */
                    ipsp = &pcis->ipstack[pcis->ips_count - 1];
                    cip = ipsp->cs_data.bits.data;
                    goto call;
                }
                return code;
            case cx_rmoveto:
                /* See vmoveto above re closing the subpath. */
                check_first_operator(!((csp - cstack) & 1));
                if (csp > cstack + 1) {
                  /* Some Type 2 charstrings omit the vstemhm operator before rmoveto,
                     even though this is only allowed before hintmask and cntrmask.
                     Thanks to Felix Pahl.
                   */
                  type2_vstem(pcis, csp - 2, cstack);
                  cstack [0] = csp [-1];
                  cstack [1] = csp [ 0];
                  csp = cstack + 1;
                }
                code = t1_hinter__rmoveto(h, csp[-1], *csp);
                goto move;
            case cx_hmoveto:
                /* See vmoveto above re closing the subpath. */
                check_first_operator(csp > cstack);
                code = t1_hinter__rmoveto(h, *csp, 0);
                goto move;
            case cx_vhcurveto:
                vertical = true;
                goto hvc;
            case cx_hvcurveto:
                vertical = false;
              hvc:for (ap = cstack; ap + 3 <= csp; vertical = !vertical, ap += 4) {
                    gs_fixed_point pt[2] = {{0, 0}, {0, 0}};
                    if (vertical) {
                        pt[0].y = ap[0];
                        pt[1].x = ap[3];
                        if (ap + 4 == csp)
                            pt[1].y = ap[4];
                    } else {
                        pt[0].x = ap[0];
                        if (ap + 4 == csp)
                            pt[1].x = ap[4];
                        pt[1].y = ap[3];
                    }
                    code = t1_hinter__rcurveto(h, pt[0].x, pt[0].y, ap[1], ap[2], pt[1].x, pt[1].y);
                    if (code < 0)
                        return code;
                }
                goto pp;

                        /***********************
                         * New Type 2 commands *
                         ***********************/

            case c2_blend:
                {
                    int n = fixed2int_var(*csp);
                    int num_values = csp - cstack;
                    gs_font_type1 *pfont = pcis->pfont;
                    int k = pfont->data.WeightVector.count;
                    int i, j;
                    cs_ptr base, deltas;

                    base = csp - 1 - num_values;
                    deltas = base + n - 1;
                    for (j = 0; j < n; j++, base++, deltas += k - 1)
                        for (i = 1; i < k; i++)
                            *base += (fixed)(deltas[i] *
                                pfont->data.WeightVector.values[i]);
                }
                cnext;
            case c2_hstemhm:
              hstem:check_first_operator(!((csp - cstack) & 1));
                {
                    fixed x = 0;

                    for (ap = cstack; ap + 1 <= csp; x += ap[1], ap += 2) {
                            code = t1_hinter__hstem(h, x += ap[0], ap[1]);
                            if (code < 0)
                                return code;
                    }
                }
                pcis->num_hints += (csp + 1 - cstack) >> 1;
                cnext;
            case c2_hintmask:
                /*
                 * A hintmask at the beginning of the CharString is
                 * equivalent to vstemhm + hintmask.  For simplicity, we use
                 * this interpretation everywhere.
                 */
            case c2_cntrmask:
                check_first_operator(!((csp - cstack) & 1));
                type2_vstem(pcis, csp, cstack);
                /*
                 * We should clear the stack here only if this is the
                 * initial mask operator that includes the implicit
                 * vstemhm, but currently this is too much trouble to
                 * detect.
                 */
                clear;
                {
                    byte mask[max_total_stem_hints / 8];
                    int i;

                    for (i = 0; i < pcis->num_hints; ++cip, i += 8) {
                        charstring_next(*cip, state, mask[i >> 3], encrypted);
                        if_debug1('1', " 0x%02x", mask[i >> 3]);
                    }
                    if_debug0('1', "\n");
                    ipsp->ip = cip;
                    ipsp->dstate = state;
                    if (c == c2_cntrmask) {
                        /****** NYI ******/
                    } else {	/* hintmask or equivalent */
                        if_debug0('1', "[1]hstem hints:\n");
                        if_debug0('1', "[1]vstem hints:\n");
                        code = t1_hinter__hint_mask(h, mask);
                        if (code < 0)
                            return code;
                    }
                }
                break;
            case c2_vstemhm:
              vstem:check_first_operator(!((csp - cstack) & 1));
                type2_vstem(pcis, csp, cstack);
                cnext;
            case c2_rcurveline:
                for (ap = cstack; ap + 5 <= csp; ap += 6) {
                    code = t1_hinter__rcurveto(h, ap[0], ap[1], ap[2], ap[3],
                                            ap[4], ap[5]);
                    if (code < 0)
                        return code;
                }
                code = t1_hinter__rlineto(h, ap[0], ap[1]);
                goto cc;
            case c2_rlinecurve:
                for (ap = cstack; ap + 7 <= csp; ap += 2) {
                    code = t1_hinter__rlineto(h, ap[0], ap[1]);
                    if (code < 0)
                        return code;
                }
                code = t1_hinter__rcurveto(h, ap[0], ap[1], ap[2], ap[3],
                                        ap[4], ap[5]);
                goto cc;
            case c2_vvcurveto:
                ap = cstack;
                {
                    int n = csp + 1 - cstack;
                    fixed dxa = (n & 1 ? *ap++ : 0);

                    for (; ap + 3 <= csp; ap += 4) {
                        code = t1_hinter__rcurveto(h, dxa, ap[0], ap[1], ap[2],
                                                fixed_0, ap[3]);
                        if (code < 0)
                            return code;
                        dxa = 0;
                    }
                }
                goto pp;
            case c2_hhcurveto:
                ap = cstack;
                {
                    int n = csp + 1 - cstack;
                    fixed dya = (n & 1 ? *ap++ : 0);

                    for (; ap + 3 <= csp; ap += 4) {
                        code = t1_hinter__rcurveto(h, ap[0], dya, ap[1], ap[2],
                                                ap[3], fixed_0);
                        if (code < 0)
                            return code;
                        dya = 0;
                    }
                }
                goto pp;
            case c2_shortint:
                {
                    int c1, c2;

                    charstring_next(*cip, state, c1, encrypted);
                    ++cip;
                    charstring_next(*cip, state, c2, encrypted);
                    ++cip;
                    CS_CHECK_PUSH(csp, cstack);
                    *++csp = int2fixed((((c1 ^ 0x80) - 0x80) << 8) + c2);
                }
                goto pushed;
            case c2_callgsubr:
                c = fixed2int_var(*csp) + pdata->gsubrNumberBias;
                code = pdata->procs.subr_data
                    (pfont, c, true, &ipsp[1].cs_data);
                goto subr;
            case cx_escape:
                charstring_next(*cip, state, c, encrypted);
                ++cip;
#ifdef DEBUG
                if (gs_debug['1'] && c < char2_extended_command_count) {
                    static const char *const ce2names[] =
                    {char2_extended_command_names};

                    if (ce2names[c] == 0)
                        dlprintf2("[1]0x%lx: %02x??\n", (ulong) (cip - 1), c);
                    else
                        dlprintf3("[1]0x%lx: %02x %s\n", (ulong) (cip - 1), c,
                                  ce2names[c]);
                }
#endif
                switch ((char2_extended_command) c) {
                    case ce2_and:
                        csp[-1] = ((csp[-1] != 0) & (*csp != 0) ? fixed_1 : 0);
                        --csp;
                        break;
                    case ce2_or:
                        csp[-1] = (csp[-1] | *csp ? fixed_1 : 0);
                        --csp;
                        break;
                    case ce2_not:
                        *csp = (*csp ? 0 : fixed_1);
                        break;
                    case ce2_store:
                        {
                            int i, n = fixed2int_var(*csp);
                            float *to = Registry[fixed2int_var(csp[-3])].values +
                            fixed2int_var(csp[-2]);
                            const fixed *from =
                            pcis->transient_array + fixed2int_var(csp[-1]);

                            for (i = 0; i < n; ++i)
                                to[i] = fixed2float(from[i]);
                        }
                        csp -= 4;
                        break;
                    case ce2_abs:
                        if (*csp < 0)
                            *csp = -*csp;
                        break;
                    case ce2_add:
                        csp[-1] += *csp;
                        --csp;
                        break;
                    case ce2_sub:
                        csp[-1] -= *csp;
                        --csp;
                        break;
                    case ce2_div:
                        csp[-1] = float2fixed((double)csp[-1] / *csp);
                        --csp;
                        break;
                    case ce2_load:
                        /* The specification says there is no j (starting index */
                        /* in registry array) argument.... */
                        {
                            int i, n = fixed2int_var(*csp);
                            const float *from = Registry[fixed2int_var(csp[-2])].values;
                            fixed *to =
                            pcis->transient_array + fixed2int_var(csp[-1]);

                            for (i = 0; i < n; ++i)
                                to[i] = float2fixed(from[i]);
                        }
                        csp -= 3;
                        break;
                    case ce2_neg:
                        *csp = -*csp;
                        break;
                    case ce2_eq:
                        csp[-1] = (csp[-1] == *csp ? fixed_1 : 0);
                        --csp;
                        break;
                    case ce2_drop:
                        --csp;
                        break;
                    case ce2_put:
                        pcis->transient_array[fixed2int_var(*csp)] = csp[-1];
                        csp -= 2;
                        break;
                    case ce2_get:
                        *csp = pcis->transient_array[fixed2int_var(*csp)];
                        break;
                    case ce2_ifelse:
                        if (csp[-1] > *csp)
                            csp[-3] = csp[-2];
                        csp -= 3;
                        break;
                    case ce2_random:
                        CS_CHECK_PUSH(csp, cstack);
                        ++csp;
                        /****** NYI ******/
                        break;
                    case ce2_mul:
                        {
                            double prod = fixed2float(csp[-1]) * *csp;

                            csp[-1] =
                                (prod > max_fixed ? max_fixed :
                                 prod < min_fixed ? min_fixed : (fixed)prod);
                        }
                        --csp;
                        break;
                    case ce2_sqrt:
                        if (*csp >= 0)
                            *csp = float2fixed(sqrt(fixed2float(*csp)));
                        break;
                    case ce2_dup:
                        CS_CHECK_PUSH(csp, cstack);
                        csp[1] = *csp;
                        ++csp;
                        break;
                    case ce2_exch:
                        {
                            fixed top = *csp;

                            *csp = csp[-1], csp[-1] = top;
                        }
                        break;
                    case ce2_index:
                        *csp =
                            (*csp < 0 ? csp[-1] : csp[-1 - fixed2int_var(csp[-1])]);
                        break;
                    case ce2_roll:
                        {
                            int distance = fixed2int_var(*csp);
                            int count = fixed2int_var(csp[-1]);
                            cs_ptr bot;

                            csp -= 2;
                            if (count < 0 || count > csp + 1 - cstack)
                                return_error(gs_error_invalidfont);
                            if (count == 0)
                                break;
                            if (distance < 0)
                                distance = count - (-distance % count);
                            bot = csp + 1 - count;
                            while (--distance >= 0) {
                                fixed top = *csp;

                                memmove(bot + 1, bot,
                                        (count - 1) * sizeof(fixed));
                                *bot = top;
                            }
                        }
                        break;
                    case ce2_hflex:
                        csp[6] = fixed_half;	/* fd/100 */
                        csp[4] = *csp, csp[5] = 0;	/* dx6, dy6 */
                        csp[2] = csp[-1], csp[3] = -csp[-4];	/* dx5, dy5 */
                        *csp = csp[-2], csp[1] = 0;	/* dx4, dy4 */
                        csp[-2] = csp[-3], csp[-1] = 0;		/* dx3, dy3 */
                        csp[-3] = csp[-4], csp[-4] = csp[-5];	/* dx2, dy2 */
                        csp[-5] = 0;	/* dy1 */
                        csp += 6;
                        goto flex;
                    case ce2_flex:
                        *csp /= 100;	/* fd/100 */
flex:			{
                            fixed x_join = csp[-12] + csp[-10] + csp[-8];
                            fixed y_join = csp[-11] + csp[-9] + csp[-7];
                            fixed x_end = x_join + csp[-6] + csp[-4] + csp[-2];
                            fixed y_end = y_join + csp[-5] + csp[-3] + csp[-1];
                            gs_point join, end;
                            double flex_depth;

                            if ((code =
                                 gs_distance_transform(fixed2float(x_join),
                                                       fixed2float(y_join),
                                                       &ctm_only(pcis->pis),
                                                       &join)) < 0 ||
                                (code =
                                 gs_distance_transform(fixed2float(x_end),
                                                       fixed2float(y_end),
                                                       &ctm_only(pcis->pis),
                                                       &end)) < 0
                                )
                                return code;
                            /*
                             * Use the X or Y distance depending on whether
                             * the curve is more horizontal or more
                             * vertical.
                             */
                            if (any_abs(end.y) > any_abs(end.x))
                                flex_depth = join.x;
                            else
                                flex_depth = join.y;
                            if (fabs(flex_depth) < fixed2float(*csp)) {
                                /* Do flex as line. */
                                code = t1_hinter__rlineto(h, x_end, y_end);
                            } else {
                                /*
                                 * Do flex as curve.  We can't jump to rrc,
                                 * because the flex operators don't clear
                                 * the stack (!).
                                 */
                                code = t1_hinter__rcurveto(h,
                                        csp[-12], csp[-11], csp[-10],
                                        csp[-9], csp[-8], csp[-7]);
                                if (code < 0)
                                    return code;
                                code = t1_hinter__rcurveto(h,
                                        csp[-6], csp[-5], csp[-4],
                                        csp[-3], csp[-2], csp[-1]);
                            }
                            if (code < 0)
                                return code;
                            csp -= 13;
                        }
                        cnext;
                    case ce2_hflex1:
                        csp[4] = fixed_half;	/* fd/100 */
                        csp[2] = *csp;          /* dx6 */
                        csp[3] = -(csp[-7] + csp[-5] + csp[-1]);	/* dy6 */
                        *csp = csp[-2], csp[1] = csp[-1];	/* dx5, dy5 */
                        csp[-2] = csp[-3], csp[-1] = 0;		/* dx4, dy4 */
                        csp[-3] = 0;	/* dy3 */
                        csp += 4;
                        goto flex;
                    case ce2_flex1:
                        {
                            fixed dx = csp[-10] + csp[-8] + csp[-6] + csp[-4] + csp[-2];
                            fixed dy = csp[-9] + csp[-7] + csp[-5] + csp[-3] + csp[-1];

                            if (any_abs(dx) > any_abs(dy))
                                csp[1] = -dy;	/* d6 is dx6 */
                            else
                                csp[1] = *csp, *csp = -dx;	/* d6 is dy6 */
                        }
                        csp[2] = fixed_half;	/* fd/100 */
                        csp += 2;
                        goto flex;
                }
                break;

                /* Fill up the dispatch up to 32. */

              case_c2_undefs:
            default:		/* pacify compiler */
                return_error(gs_error_invalidfont);
        }
    }
}
예제 #26
0
int
gs_currentmatrix(const gs_state * pgs, gs_matrix * pmat)
{
    *pmat = ctm_only(pgs);
    return 0;
}