Esempio n. 1
0
static int
bbox_image_plane_data(gx_image_enum_common_t * info,
		      const gx_image_plane_t * planes, int height,
		      int *rows_used)
{
    gx_device *dev = info->dev;
    gx_device_bbox *const bdev = (gx_device_bbox *)dev;
    gx_device *tdev = bdev->target;
    bbox_image_enum *pbe = (bbox_image_enum *) info;
    const gx_clip_path *pcpath = pbe->pcpath;
    gs_rect sbox, dbox;
    gs_point corners[4];
    gs_fixed_rect ibox;
    int code;

    code = gx_image_plane_data_rows(pbe->target_info, planes, height,
				    rows_used);
    if (code != 1 && !pbe->params_are_const)
	bbox_image_copy_target_info(pbe);
    sbox.p.x = pbe->x0;
    sbox.p.y = pbe->y;
    sbox.q.x = pbe->x1;
    sbox.q.y = pbe->y = min(pbe->y + height, pbe->height);
    gs_bbox_transform_only(&sbox, &pbe->matrix, corners);
    gs_points_bbox(corners, &dbox);
    ibox.p.x = float2fixed(dbox.p.x);
    ibox.p.y = float2fixed(dbox.p.y);
    ibox.q.x = float2fixed(dbox.q.x);
    ibox.q.y = float2fixed(dbox.q.y);
    if (pcpath != NULL &&
	!gx_cpath_includes_rectangle(pcpath, ibox.p.x, ibox.p.y,
				     ibox.q.x, ibox.q.y)
	) {
	/* Let the target do the drawing, but drive two triangles */
	/* through the clipping path to get an accurate bounding box. */
	gx_device_clip cdev;
	gx_drawing_color devc;
	fixed x0 = float2fixed(corners[0].x), y0 = float2fixed(corners[0].y);
	fixed bx2 = float2fixed(corners[2].x) - x0, by2 = float2fixed(corners[2].y) - y0;

	gx_make_clip_device_on_stack(&cdev, pcpath, dev);
	set_nonclient_dev_color(&devc, bdev->black);  /* any non-white color will do */
	bdev->target = NULL;
	gx_default_fill_triangle((gx_device *) & cdev, x0, y0,
				 float2fixed(corners[1].x) - x0,
				 float2fixed(corners[1].y) - y0,
				 bx2, by2, &devc, lop_default);
	gx_default_fill_triangle((gx_device *) & cdev, x0, y0,
				 float2fixed(corners[3].x) - x0,
				 float2fixed(corners[3].y) - y0,
				 bx2, by2, &devc, lop_default);
	bdev->target = tdev;
    } else {
	/* Just use the bounding box. */
	BBOX_ADD_RECT(bdev, ibox.p.x, ibox.p.y, ibox.q.x, ibox.q.y);
    }
    return code;
}
Esempio n. 2
0
static int
bbox_transform_either(const gs_rect * pbox_in, const gs_matrix * pmat,
                      gs_rect * pbox_out,
     int (*point_xform) (floatp, floatp, const gs_matrix *, gs_point *))
{
    int code;

    /*
     * In principle, we could transform only one point and two
     * distance vectors; however, because of rounding, we will only
     * get fully consistent results if we transform all 4 points.
     * We must compute the max and min after transforming,
     * since a rotation may be involved.
     */
    gs_point pts[4];

    if ((code = bbox_transform_either_only(pbox_in, pmat, pts, point_xform)) < 0)
        return code;
    return gs_points_bbox(pts, pbox_out);
}