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; }
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); }