mirror of
https://gitlab.freedesktop.org/cairo/cairo.git
synced 2026-01-16 21:50:29 +01:00
src/cairo.h src/cairo_surface.c src/cairo-xlib.h src/cairo_xlib_surface.c: Move cairo_xlib_surface_set_device_offset() to a generic cairo_surface_set_device_offset().
Take the surface's device offset into account. Update.
This commit is contained in:
parent
0b09748296
commit
e66e4c7b8c
15 changed files with 350 additions and 276 deletions
11
ChangeLog
11
ChangeLog
|
|
@ -1,3 +1,14 @@
|
|||
2005-03-17 Owen Taylor <otaylor@redhat.com>
|
||||
|
||||
* src/cairo.h src/cairo_surface.c src/cairo-xlib.h
|
||||
src/cairo_xlib_surface.c: Move cairo_xlib_surface_set_device_offset()
|
||||
to a generic cairo_surface_set_device_offset().
|
||||
|
||||
* src/cairo_gstate.c: Take the surface's device offset into
|
||||
account.
|
||||
|
||||
* doc/public/cairo-sections.txt: Update.
|
||||
|
||||
2005-03-17 Owen Taylor <otaylor@redhat.com>
|
||||
|
||||
* src/cairo_matrix.c: Fix the docs to to correctly describe
|
||||
|
|
|
|||
|
|
@ -25,7 +25,9 @@ cairo_glitz_surface_create
|
|||
<FILE>cairo-pdf</FILE>
|
||||
<TITLE>PDF Backend</TITLE>
|
||||
cairo_set_target_pdf
|
||||
cairo_set_target_pdf_as_file
|
||||
cairo_pdf_surface_create
|
||||
cairo_pdf_surface_create_for_file
|
||||
</SECTION>
|
||||
|
||||
<SECTION>
|
||||
|
|
@ -75,7 +77,6 @@ cairo_xlib_surface_create_for_pixmap
|
|||
cairo_xlib_surface_create_for_pixmap_with_visual
|
||||
cairo_xlib_surface_create_for_window_with_visual
|
||||
cairo_xlib_surface_set_size
|
||||
cairo_xlib_surface_set_device_offset
|
||||
</SECTION>
|
||||
|
||||
<SECTION>
|
||||
|
|
@ -86,6 +87,7 @@ cairo_surface_create_for_image
|
|||
cairo_surface_create_similar
|
||||
cairo_surface_reference
|
||||
cairo_surface_destroy
|
||||
cairo_surface_finish
|
||||
cairo_surface_set_repeat
|
||||
cairo_surface_set_matrix
|
||||
cairo_surface_get_matrix
|
||||
|
|
@ -93,6 +95,7 @@ cairo_surface_set_filter
|
|||
cairo_surface_get_filter
|
||||
cairo_surface_set_user_data
|
||||
cairo_surface_get_user_data
|
||||
cairo_surface_set_device_offset
|
||||
</SECTION>
|
||||
|
||||
<SECTION>
|
||||
|
|
@ -243,6 +246,7 @@ cairo_image_surface_create
|
|||
cairo_image_surface_create_for_data
|
||||
cairo_destroy_func_t
|
||||
cairo_user_data_key_t
|
||||
cairo_write_func_t
|
||||
<SUBSECTION Private>
|
||||
CAIRO_API_SHAKEUP_FLAG_DAY
|
||||
CAIRO_BEGIN_DECLS
|
||||
|
|
|
|||
|
|
@ -23,7 +23,24 @@ PDF Backend
|
|||
</para>
|
||||
|
||||
@cr:
|
||||
@write_func:
|
||||
@destroy_closure_func:
|
||||
@closure:
|
||||
@width_inches:
|
||||
@height_inches:
|
||||
@x_pixels_per_inch:
|
||||
@y_pixels_per_inch:
|
||||
<!-- # Unused Parameters # -->
|
||||
@file:
|
||||
|
||||
|
||||
<!-- ##### FUNCTION cairo_set_target_pdf_as_file ##### -->
|
||||
<para>
|
||||
|
||||
</para>
|
||||
|
||||
@cr:
|
||||
@fp:
|
||||
@width_inches:
|
||||
@height_inches:
|
||||
@x_pixels_per_inch:
|
||||
|
|
@ -35,7 +52,24 @@ PDF Backend
|
|||
|
||||
</para>
|
||||
|
||||
@write_func:
|
||||
@destroy_closure_func:
|
||||
@closure:
|
||||
@width_inches:
|
||||
@height_inches:
|
||||
@x_pixels_per_inch:
|
||||
@y_pixels_per_inch:
|
||||
@Returns:
|
||||
<!-- # Unused Parameters # -->
|
||||
@file:
|
||||
|
||||
|
||||
<!-- ##### FUNCTION cairo_pdf_surface_create_for_file ##### -->
|
||||
<para>
|
||||
|
||||
</para>
|
||||
|
||||
@fp:
|
||||
@width_inches:
|
||||
@height_inches:
|
||||
@x_pixels_per_inch:
|
||||
|
|
|
|||
|
|
@ -64,6 +64,15 @@ cairo_surface_t
|
|||
@surface:
|
||||
|
||||
|
||||
<!-- ##### FUNCTION cairo_surface_finish ##### -->
|
||||
<para>
|
||||
|
||||
</para>
|
||||
|
||||
@surface:
|
||||
@Returns:
|
||||
|
||||
|
||||
<!-- ##### FUNCTION cairo_surface_set_repeat ##### -->
|
||||
<para>
|
||||
|
||||
|
|
@ -137,3 +146,13 @@ cairo_surface_t
|
|||
@Returns:
|
||||
|
||||
|
||||
<!-- ##### FUNCTION cairo_surface_set_device_offset ##### -->
|
||||
<para>
|
||||
|
||||
</para>
|
||||
|
||||
@surface:
|
||||
@x_offset:
|
||||
@y_offset:
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -85,13 +85,3 @@ XLib Backend
|
|||
@height:
|
||||
|
||||
|
||||
<!-- ##### FUNCTION cairo_xlib_surface_set_device_offset ##### -->
|
||||
<para>
|
||||
|
||||
</para>
|
||||
|
||||
@surface:
|
||||
@x_offset:
|
||||
@y_offset:
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -995,6 +995,8 @@ Drawing contexts.
|
|||
@CAIRO_STATUS_NULL_POINTER:
|
||||
@CAIRO_STATUS_INVALID_STRING:
|
||||
@CAIRO_STATUS_INVALID_PATH_DATA:
|
||||
@CAIRO_STATUS_WRITE_ERROR:
|
||||
@CAIRO_STATUS_SURFACE_FINISHED:
|
||||
|
||||
<!-- ##### FUNCTION cairo_status ##### -->
|
||||
<para>
|
||||
|
|
@ -1074,3 +1076,14 @@ End:
|
|||
|
||||
@unused:
|
||||
|
||||
<!-- ##### USER_FUNCTION cairo_write_func_t ##### -->
|
||||
<para>
|
||||
|
||||
</para>
|
||||
|
||||
@closure:
|
||||
@data:
|
||||
@length:
|
||||
@Returns:
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -723,6 +723,26 @@ _cairo_gstate_inverse_transform_point (cairo_gstate_t *gstate, double *x, double
|
|||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static void
|
||||
_cairo_gstate_user_to_backend (cairo_gstate_t *gstate, double *x, double *y)
|
||||
{
|
||||
cairo_matrix_transform_point (&gstate->ctm, x, y);
|
||||
if (gstate->surface) {
|
||||
*x += gstate->surface->device_x_offset;
|
||||
*y += gstate->surface->device_y_offset;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
_cairo_gstate_backend_to_user (cairo_gstate_t *gstate, double *x, double *y)
|
||||
{
|
||||
if (gstate->surface) {
|
||||
*x -= gstate->surface->device_x_offset;
|
||||
*y -= gstate->surface->device_y_offset;
|
||||
}
|
||||
cairo_matrix_transform_point (&gstate->ctm_inverse, x, y);
|
||||
}
|
||||
|
||||
cairo_status_t
|
||||
_cairo_gstate_inverse_transform_distance (cairo_gstate_t *gstate, double *dx, double *dy)
|
||||
{
|
||||
|
|
@ -744,7 +764,7 @@ _cairo_gstate_move_to (cairo_gstate_t *gstate, double x, double y)
|
|||
{
|
||||
cairo_point_t point;
|
||||
|
||||
cairo_matrix_transform_point (&gstate->ctm, &x, &y);
|
||||
_cairo_gstate_user_to_backend (gstate, &x, &y);
|
||||
|
||||
point.x = _cairo_fixed_from_double (x);
|
||||
point.y = _cairo_fixed_from_double (y);
|
||||
|
|
@ -757,7 +777,7 @@ _cairo_gstate_line_to (cairo_gstate_t *gstate, double x, double y)
|
|||
{
|
||||
cairo_point_t point;
|
||||
|
||||
cairo_matrix_transform_point (&gstate->ctm, &x, &y);
|
||||
_cairo_gstate_user_to_backend (gstate, &x, &y);
|
||||
|
||||
point.x = _cairo_fixed_from_double (x);
|
||||
point.y = _cairo_fixed_from_double (y);
|
||||
|
|
@ -773,9 +793,9 @@ _cairo_gstate_curve_to (cairo_gstate_t *gstate,
|
|||
{
|
||||
cairo_point_t p0, p1, p2;
|
||||
|
||||
cairo_matrix_transform_point (&gstate->ctm, &x0, &y0);
|
||||
cairo_matrix_transform_point (&gstate->ctm, &x1, &y1);
|
||||
cairo_matrix_transform_point (&gstate->ctm, &x2, &y2);
|
||||
_cairo_gstate_user_to_backend (gstate, &x0, &y0);
|
||||
_cairo_gstate_user_to_backend (gstate, &x1, &y1);
|
||||
_cairo_gstate_user_to_backend (gstate, &x2, &y2);
|
||||
|
||||
p0.x = _cairo_fixed_from_double (x0);
|
||||
p0.y = _cairo_fixed_from_double (y0);
|
||||
|
|
@ -1146,7 +1166,7 @@ _cairo_gstate_get_current_point (cairo_gstate_t *gstate, double *x_ret, double *
|
|||
} else {
|
||||
x = _cairo_fixed_to_double (point.x);
|
||||
y = _cairo_fixed_to_double (point.y);
|
||||
cairo_matrix_transform_point (&gstate->ctm_inverse, &x, &y);
|
||||
_cairo_gstate_backend_to_user (gstate, &x, &y);
|
||||
}
|
||||
|
||||
if (x_ret)
|
||||
|
|
@ -1289,6 +1309,11 @@ _cairo_gstate_interpret_path (cairo_gstate_t *gstate,
|
|||
_cairo_path_init_copy (&path, &gstate->path);
|
||||
|
||||
cairo_matrix_copy (&gpi.ctm_inverse, &gstate->ctm_inverse);
|
||||
if (gstate->surface)
|
||||
cairo_matrix_translate (&gpi.ctm_inverse,
|
||||
- gstate->surface->device_x_offset,
|
||||
- gstate->surface->device_y_offset);
|
||||
|
||||
gpi.tolerance = gstate->tolerance;
|
||||
|
||||
gpi.move_to = move_to;
|
||||
|
|
@ -1309,6 +1334,20 @@ _cairo_gstate_interpret_path (cairo_gstate_t *gstate,
|
|||
&gpi);
|
||||
}
|
||||
|
||||
static void
|
||||
_cairo_gstate_pattern_transform (cairo_gstate_t *gstate,
|
||||
cairo_pattern_t *pattern)
|
||||
{
|
||||
cairo_matrix_t tmp_matrix = gstate->ctm_inverse;
|
||||
|
||||
if (gstate->surface)
|
||||
cairo_matrix_translate (&tmp_matrix,
|
||||
- gstate->surface->device_x_offset,
|
||||
- gstate->surface->device_y_offset);
|
||||
|
||||
_cairo_pattern_transform (pattern, &tmp_matrix);
|
||||
}
|
||||
|
||||
/* XXX: gstate->alpha will be going away before too long, and when it
|
||||
* does, it may make sense for this function to just disappear.
|
||||
*/
|
||||
|
|
@ -1318,7 +1357,7 @@ _cairo_gstate_pattern_init_copy (cairo_gstate_t *gstate,
|
|||
cairo_pattern_t *src)
|
||||
{
|
||||
_cairo_pattern_init_copy (&pattern->base, src);
|
||||
_cairo_pattern_transform (&pattern->base, &gstate->ctm_inverse);
|
||||
_cairo_gstate_pattern_transform (gstate, &pattern->base);
|
||||
_cairo_pattern_set_alpha (&pattern->base, gstate->alpha);
|
||||
}
|
||||
|
||||
|
|
@ -1363,7 +1402,7 @@ _cairo_gstate_in_stroke (cairo_gstate_t *gstate,
|
|||
cairo_status_t status = CAIRO_STATUS_SUCCESS;
|
||||
cairo_traps_t traps;
|
||||
|
||||
cairo_matrix_transform_point (&gstate->ctm, &x, &y);
|
||||
_cairo_gstate_user_to_backend (gstate, &x, &y);
|
||||
|
||||
_cairo_pen_init (&gstate->pen_regular, gstate->line_width / 2.0, gstate);
|
||||
|
||||
|
|
@ -1658,7 +1697,7 @@ _cairo_gstate_in_fill (cairo_gstate_t *gstate,
|
|||
cairo_status_t status = CAIRO_STATUS_SUCCESS;
|
||||
cairo_traps_t traps;
|
||||
|
||||
cairo_matrix_transform_point (&gstate->ctm, &x, &y);
|
||||
_cairo_gstate_user_to_backend (gstate, &x, &y);
|
||||
|
||||
_cairo_traps_init (&traps);
|
||||
|
||||
|
|
@ -1714,8 +1753,8 @@ _cairo_gstate_stroke_extents (cairo_gstate_t *gstate,
|
|||
*x2 = _cairo_fixed_to_double (extents.p2.x);
|
||||
*y2 = _cairo_fixed_to_double (extents.p2.y);
|
||||
|
||||
cairo_matrix_transform_point (&gstate->ctm_inverse, x1, y1);
|
||||
cairo_matrix_transform_point (&gstate->ctm_inverse, x2, y2);
|
||||
_cairo_gstate_backend_to_user (gstate, x1, y1);
|
||||
_cairo_gstate_backend_to_user (gstate, x2, y2);
|
||||
|
||||
BAIL:
|
||||
_cairo_traps_fini (&traps);
|
||||
|
|
@ -1745,8 +1784,8 @@ _cairo_gstate_fill_extents (cairo_gstate_t *gstate,
|
|||
*x2 = _cairo_fixed_to_double (extents.p2.x);
|
||||
*y2 = _cairo_fixed_to_double (extents.p2.y);
|
||||
|
||||
cairo_matrix_transform_point (&gstate->ctm_inverse, x1, y1);
|
||||
cairo_matrix_transform_point (&gstate->ctm_inverse, x2, y2);
|
||||
_cairo_gstate_backend_to_user (gstate, x1, y1);
|
||||
_cairo_gstate_backend_to_user (gstate, x2, y2);
|
||||
|
||||
BAIL:
|
||||
_cairo_traps_fini (&traps);
|
||||
|
|
@ -2004,9 +2043,9 @@ _cairo_gstate_show_surface (cairo_gstate_t *gstate,
|
|||
*/
|
||||
|
||||
cairo_status_t status = CAIRO_STATUS_SUCCESS;
|
||||
cairo_matrix_t image_to_user, image_to_device;
|
||||
double device_x, device_y;
|
||||
double device_width, device_height;
|
||||
cairo_matrix_t image_to_user, image_to_device, image_to_backend;
|
||||
double backend_x, backend_y;
|
||||
double backend_width, backend_height;
|
||||
cairo_surface_pattern_t pattern;
|
||||
cairo_box_t pattern_extents;
|
||||
cairo_rectangle_t extents;
|
||||
|
|
@ -2014,13 +2053,23 @@ _cairo_gstate_show_surface (cairo_gstate_t *gstate,
|
|||
cairo_surface_get_matrix (surface, &image_to_user);
|
||||
cairo_matrix_invert (&image_to_user);
|
||||
cairo_matrix_multiply (&image_to_device, &image_to_user, &gstate->ctm);
|
||||
if (gstate->surface) {
|
||||
cairo_matrix_t device_to_backend;
|
||||
|
||||
_cairo_matrix_set_translate (&device_to_backend,
|
||||
gstate->surface->device_x_offset,
|
||||
gstate->surface->device_y_offset);
|
||||
cairo_matrix_multiply (&image_to_backend, &image_to_device, &device_to_backend);
|
||||
} else {
|
||||
image_to_backend = image_to_device;
|
||||
}
|
||||
|
||||
_cairo_gstate_get_current_point (gstate, &device_x, &device_y);
|
||||
device_width = width;
|
||||
device_height = height;
|
||||
_cairo_matrix_transform_bounding_box (&image_to_device,
|
||||
&device_x, &device_y,
|
||||
&device_width, &device_height);
|
||||
_cairo_gstate_get_current_point (gstate, &backend_x, &backend_y);
|
||||
backend_width = width;
|
||||
backend_height = height;
|
||||
_cairo_matrix_transform_bounding_box (&image_to_backend,
|
||||
&backend_x, &backend_y,
|
||||
&backend_width, &backend_height);
|
||||
|
||||
_cairo_pattern_init_for_surface (&pattern, surface);
|
||||
|
||||
|
|
@ -2033,13 +2082,13 @@ _cairo_gstate_show_surface (cairo_gstate_t *gstate,
|
|||
else
|
||||
pattern.base.extend = CAIRO_EXTEND_NONE;
|
||||
|
||||
_cairo_pattern_transform (&pattern.base, &gstate->ctm_inverse);
|
||||
_cairo_gstate_pattern_transform (gstate, &pattern.base);
|
||||
_cairo_pattern_set_alpha (&pattern.base, gstate->alpha);
|
||||
|
||||
pattern_extents.p1.x = _cairo_fixed_from_double (device_x);
|
||||
pattern_extents.p1.y = _cairo_fixed_from_double (device_y);
|
||||
pattern_extents.p2.x = _cairo_fixed_from_double (device_x + device_width);
|
||||
pattern_extents.p2.y = _cairo_fixed_from_double (device_y + device_height);
|
||||
pattern_extents.p1.x = _cairo_fixed_from_double (backend_x);
|
||||
pattern_extents.p1.y = _cairo_fixed_from_double (backend_y);
|
||||
pattern_extents.p2.x = _cairo_fixed_from_double (backend_x + backend_width);
|
||||
pattern_extents.p2.y = _cairo_fixed_from_double (backend_y + backend_height);
|
||||
_cairo_box_round_to_rectangle (&pattern_extents, &extents);
|
||||
|
||||
if (gstate->clip.surface)
|
||||
|
|
@ -2334,8 +2383,8 @@ _cairo_gstate_text_to_glyphs (cairo_gstate_t *gstate,
|
|||
} else {
|
||||
origin_x = _cairo_fixed_to_double (point.x);
|
||||
origin_y = _cairo_fixed_to_double (point.y);
|
||||
cairo_matrix_transform_point (&gstate->ctm_inverse,
|
||||
&origin_x, &origin_y);
|
||||
_cairo_gstate_backend_to_user (gstate,
|
||||
&origin_x, &origin_y);
|
||||
}
|
||||
|
||||
status = _cairo_font_text_to_glyphs (gstate->font,
|
||||
|
|
@ -2417,9 +2466,9 @@ _cairo_gstate_show_glyphs (cairo_gstate_t *gstate,
|
|||
for (i = 0; i < num_glyphs; ++i)
|
||||
{
|
||||
transformed_glyphs[i] = glyphs[i];
|
||||
cairo_matrix_transform_point (&gstate->ctm,
|
||||
&transformed_glyphs[i].x,
|
||||
&transformed_glyphs[i].y);
|
||||
_cairo_gstate_user_to_backend (gstate,
|
||||
&transformed_glyphs[i].x,
|
||||
&transformed_glyphs[i].y);
|
||||
}
|
||||
|
||||
status = _cairo_font_glyph_bbox (gstate->font,
|
||||
|
|
@ -2552,9 +2601,9 @@ _cairo_gstate_glyph_path (cairo_gstate_t *gstate,
|
|||
for (i = 0; i < num_glyphs; ++i)
|
||||
{
|
||||
transformed_glyphs[i] = glyphs[i];
|
||||
cairo_matrix_transform_point (&gstate->ctm,
|
||||
&(transformed_glyphs[i].x),
|
||||
&(transformed_glyphs[i].y));
|
||||
_cairo_gstate_user_to_backend (gstate,
|
||||
&(transformed_glyphs[i].x),
|
||||
&(transformed_glyphs[i].y));
|
||||
}
|
||||
|
||||
status = _cairo_font_glyph_path (gstate->font,
|
||||
|
|
|
|||
|
|
@ -59,6 +59,9 @@ _cairo_surface_init (cairo_surface_t *surface,
|
|||
_cairo_matrix_init (&surface->matrix);
|
||||
surface->filter = CAIRO_FILTER_NEAREST;
|
||||
surface->repeat = 0;
|
||||
|
||||
surface->device_x_offset = 0;
|
||||
surface->device_y_offset = 0;
|
||||
}
|
||||
|
||||
cairo_surface_t *
|
||||
|
|
@ -290,6 +293,33 @@ cairo_surface_set_user_data (cairo_surface_t *surface,
|
|||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* cairo_surface_set_device_offset:
|
||||
* @surface: a #cairo_surface_t
|
||||
* @x_offset: the offset in the X direction, in device units
|
||||
* @y_offset: the offset in the Y direction, in device units
|
||||
*
|
||||
* Sets an offset that is added to the device coordinates determined
|
||||
* by the CTM when drawing to @surface. One use case for this function
|
||||
* is when we want to create a #cairo_surface_t that redirects drawing
|
||||
* for a portion of an onscreen surface to an offscreen surface in a
|
||||
* way that is completely invisible to the user of the cairo
|
||||
* API. Setting a transformation via cairo_translate() isn't
|
||||
* sufficient to do this, since functions like
|
||||
* cairo_inverse_transform_point() will expose the hidden offset.
|
||||
*
|
||||
* Note that the offset only affects drawing to the surface, not using
|
||||
* the surface in a surface pattern.
|
||||
**/
|
||||
void
|
||||
cairo_surface_set_device_offset (cairo_surface_t *surface,
|
||||
double x_offset,
|
||||
double y_offset)
|
||||
{
|
||||
surface->device_x_offset = x_offset;
|
||||
surface->device_y_offset = y_offset;
|
||||
}
|
||||
|
||||
double
|
||||
_cairo_surface_pixels_per_inch (cairo_surface_t *surface)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -105,9 +105,6 @@ struct _cairo_xlib_surface {
|
|||
int height;
|
||||
int depth;
|
||||
|
||||
int x_offset;
|
||||
int y_offset;
|
||||
|
||||
Picture picture;
|
||||
};
|
||||
|
||||
|
|
@ -252,8 +249,8 @@ _get_image_surface (cairo_xlib_surface_t *surface,
|
|||
if (interest_rect) {
|
||||
cairo_rectangle_t rect;
|
||||
|
||||
rect.x = interest_rect->x + surface->x_offset;
|
||||
rect.y = interest_rect->y + surface->x_offset;
|
||||
rect.x = interest_rect->x;
|
||||
rect.y = interest_rect->y;
|
||||
rect.width = interest_rect->width;
|
||||
rect.height = interest_rect->width;
|
||||
|
||||
|
|
@ -273,8 +270,8 @@ _get_image_surface (cairo_xlib_surface_t *surface,
|
|||
}
|
||||
|
||||
if (image_rect) {
|
||||
image_rect->x = x1 - surface->x_offset;
|
||||
image_rect->y = y1 - surface->y_offset;
|
||||
image_rect->x = x1;
|
||||
image_rect->y = y1;
|
||||
image_rect->width = x2 - x1;
|
||||
image_rect->height = y2 - y1;
|
||||
}
|
||||
|
|
@ -396,7 +393,7 @@ _draw_image_surface (cairo_xlib_surface_t *surface,
|
|||
|
||||
_cairo_xlib_surface_ensure_gc (surface);
|
||||
XPutImage(surface->dpy, surface->drawable, surface->gc,
|
||||
ximage, 0, 0, dst_x + surface->x_offset, dst_y + surface->y_offset,
|
||||
ximage, 0, 0, dst_x, dst_y,
|
||||
image->width, image->height);
|
||||
|
||||
/* Foolish XDestroyImage thinks it can free my data, but I won't
|
||||
|
|
@ -735,7 +732,7 @@ _cairo_xlib_surface_composite (cairo_operator_t operator,
|
|||
src_x + src_attr.x_offset,
|
||||
src_y + src_attr.y_offset,
|
||||
0, 0,
|
||||
dst_x + dst->x_offset, dst_y + dst->y_offset,
|
||||
dst_x, dst_y,
|
||||
width, height);
|
||||
}
|
||||
}
|
||||
|
|
@ -748,20 +745,6 @@ _cairo_xlib_surface_composite (cairo_operator_t operator,
|
|||
return status;
|
||||
}
|
||||
|
||||
static void
|
||||
_translate_rects (cairo_rectangle_t *rects,
|
||||
int num_rects,
|
||||
int x_offset,
|
||||
int y_offset)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < num_rects; i++) {
|
||||
rects[i].x += x_offset;
|
||||
rects[i].y += y_offset;
|
||||
}
|
||||
}
|
||||
|
||||
static cairo_int_status_t
|
||||
_cairo_xlib_surface_fill_rectangles (void *abstract_surface,
|
||||
cairo_operator_t operator,
|
||||
|
|
@ -780,10 +763,6 @@ _cairo_xlib_surface_fill_rectangles (void *abstract_surface,
|
|||
render_color.blue = color->blue_short;
|
||||
render_color.alpha = color->alpha_short;
|
||||
|
||||
if (surface->x_offset != 0 || surface->y_offset != 0)
|
||||
_translate_rects (rects, num_rects,
|
||||
surface->x_offset, surface->y_offset);
|
||||
|
||||
/* XXX: This XRectangle cast is evil... it needs to go away somehow. */
|
||||
XRenderFillRectangles (surface->dpy,
|
||||
_render_operator (operator),
|
||||
|
|
@ -793,31 +772,6 @@ _cairo_xlib_surface_fill_rectangles (void *abstract_surface,
|
|||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static void
|
||||
_translate_traps (cairo_trapezoid_t *traps,
|
||||
int num_traps,
|
||||
int x_offset,
|
||||
int y_offset)
|
||||
{
|
||||
cairo_fixed_t xoff, yoff;
|
||||
int i;
|
||||
|
||||
xoff = _cairo_fixed_from_int (x_offset);
|
||||
yoff = _cairo_fixed_from_int (y_offset);
|
||||
|
||||
for (i = 0; i < num_traps; i++) {
|
||||
traps[i].top += yoff;
|
||||
traps[i].bottom += yoff;
|
||||
traps[i].left.p1.x += xoff;
|
||||
traps[i].left.p1.y += yoff;
|
||||
traps[i].left.p2.x += xoff;
|
||||
traps[i].left.p2.y += yoff;
|
||||
traps[i].right.p1.x += xoff;
|
||||
traps[i].right.p1.y += yoff;
|
||||
traps[i].right.p2.x += xoff;
|
||||
traps[i].right.p2.y += yoff;
|
||||
}
|
||||
}
|
||||
static cairo_int_status_t
|
||||
_cairo_xlib_surface_composite_trapezoids (cairo_operator_t operator,
|
||||
cairo_pattern_t *pattern,
|
||||
|
|
@ -848,9 +802,6 @@ _cairo_xlib_surface_composite_trapezoids (cairo_operator_t operator,
|
|||
if (status)
|
||||
return status;
|
||||
|
||||
if (dst->x_offset != 0 || dst->y_offset != 0)
|
||||
_translate_traps (traps, num_traps, dst->x_offset, dst->y_offset);
|
||||
|
||||
if (traps[0].left.p1.y < traps[0].left.p2.y) {
|
||||
render_reference_x = _cairo_fixed_integer_floor (traps[0].left.p1.x);
|
||||
render_reference_y = _cairo_fixed_integer_floor (traps[0].left.p1.y);
|
||||
|
|
@ -859,8 +810,8 @@ _cairo_xlib_surface_composite_trapezoids (cairo_operator_t operator,
|
|||
render_reference_y = _cairo_fixed_integer_floor (traps[0].left.p2.y);
|
||||
}
|
||||
|
||||
render_src_x = src_x + render_reference_x - (dst_x + dst->x_offset);
|
||||
render_src_y = src_y + render_reference_y - (dst_y + dst->y_offset);
|
||||
render_src_x = src_x + render_reference_x - dst_x;
|
||||
render_src_y = src_y + render_reference_y - dst_y;
|
||||
|
||||
/* XXX: The XTrapezoid cast is evil and needs to go away somehow. */
|
||||
status = _cairo_xlib_surface_set_attributes (src, &attributes);
|
||||
|
|
@ -923,8 +874,8 @@ _cairo_xlib_surface_set_clip_region (void *abstract_surface,
|
|||
boxes = pixman_region_rects (region);
|
||||
|
||||
for (i = 0; i < n_boxes; i++) {
|
||||
rects[i].x = boxes[i].x1 + surface->x_offset;
|
||||
rects[i].y = boxes[i].y1 + surface->y_offset;
|
||||
rects[i].x = boxes[i].x1;
|
||||
rects[i].y = boxes[i].y1;
|
||||
rects[i].width = boxes[i].x2 - boxes[i].x1;
|
||||
rects[i].height = boxes[i].y2 - boxes[i].y1;
|
||||
}
|
||||
|
|
@ -999,8 +950,6 @@ _cairo_xlib_surface_create_internal (Display *dpy,
|
|||
surface->owns_pixmap = FALSE;
|
||||
surface->width = -1;
|
||||
surface->height = -1;
|
||||
surface->x_offset = 0;
|
||||
surface->y_offset = 0;
|
||||
|
||||
if (visual) {
|
||||
int i, j, k;
|
||||
|
|
@ -1204,34 +1153,6 @@ cairo_xlib_surface_set_size (cairo_surface_t *surface,
|
|||
xlib_surface->height = height;
|
||||
}
|
||||
|
||||
/**
|
||||
* cairo_xlib_surface_set_device_offset:
|
||||
* @surface: a #cairo_surface_t for the XLib backend
|
||||
* @x_offset: offset in the X direction, in pixels
|
||||
* @y_offset: offset in the Y direction, in pixels
|
||||
*
|
||||
* Sets an offset that is added to the device coordinates determined
|
||||
* by the CTM when drawing to @surface. This is useful when we want
|
||||
* to redirect drawing to a window to a backing pixmap for a portion
|
||||
* of the window in a way that is completely invisible to the user
|
||||
* of the Cairo API. Setting a transformation via cairo_translate() isn't
|
||||
* sufficient to do this, since functions like
|
||||
* cairo_inverse_transform_point() will expose the hidden offset.
|
||||
*
|
||||
* Note that the offset only affects drawing to the surface, not using
|
||||
* the surface in a surface pattern.
|
||||
**/
|
||||
void
|
||||
cairo_xlib_surface_set_device_offset (cairo_surface_t *surface,
|
||||
int x_offset,
|
||||
int y_offset)
|
||||
{
|
||||
cairo_xlib_surface_t *xlib_surface = (cairo_xlib_surface_t *)surface;
|
||||
|
||||
xlib_surface->x_offset = x_offset;
|
||||
xlib_surface->y_offset = y_offset;
|
||||
}
|
||||
|
||||
/* RENDER glyphset cache code */
|
||||
|
||||
typedef struct glyphset_cache {
|
||||
|
|
@ -1488,8 +1409,8 @@ _cairo_xlib_surface_show_glyphs32 (cairo_font_t *font,
|
|||
elts[i].chars = &(chars[i]);
|
||||
elts[i].nchars = 1;
|
||||
elts[i].glyphset = g->glyphset;
|
||||
thisX = (int) floor (glyphs[i].x + 0.5) + self->x_offset;
|
||||
thisY = (int) floor (glyphs[i].y + 0.5) + self->y_offset;
|
||||
thisX = (int) floor (glyphs[i].x + 0.5);
|
||||
thisY = (int) floor (glyphs[i].y + 0.5);
|
||||
elts[i].xOff = thisX - lastX;
|
||||
elts[i].yOff = thisY - lastY;
|
||||
lastX = thisX;
|
||||
|
|
@ -1565,8 +1486,8 @@ _cairo_xlib_surface_show_glyphs16 (cairo_font_t *font,
|
|||
elts[i].chars = &(chars[i]);
|
||||
elts[i].nchars = 1;
|
||||
elts[i].glyphset = g->glyphset;
|
||||
thisX = (int) floor (glyphs[i].x + 0.5) + self->x_offset;
|
||||
thisY = (int) floor (glyphs[i].y + 0.5) + self->y_offset;
|
||||
thisX = (int) floor (glyphs[i].x + 0.5);
|
||||
thisY = (int) floor (glyphs[i].y + 0.5);
|
||||
elts[i].xOff = thisX - lastX;
|
||||
elts[i].yOff = thisY - lastY;
|
||||
lastX = thisX;
|
||||
|
|
@ -1641,8 +1562,8 @@ _cairo_xlib_surface_show_glyphs8 (cairo_font_t *font,
|
|||
elts[i].chars = &(chars[i]);
|
||||
elts[i].nchars = 1;
|
||||
elts[i].glyphset = g->glyphset;
|
||||
thisX = (int) floor (glyphs[i].x + 0.5) + self->x_offset;
|
||||
thisY = (int) floor (glyphs[i].y + 0.5) + self->y_offset;
|
||||
thisX = (int) floor (glyphs[i].x + 0.5);
|
||||
thisY = (int) floor (glyphs[i].y + 0.5);
|
||||
elts[i].xOff = thisX - lastX;
|
||||
elts[i].yOff = thisY - lastY;
|
||||
lastX = thisX;
|
||||
|
|
|
|||
|
|
@ -80,11 +80,6 @@ cairo_xlib_surface_set_size (cairo_surface_t *surface,
|
|||
int width,
|
||||
int height);
|
||||
|
||||
void
|
||||
cairo_xlib_surface_set_device_offset (cairo_surface_t *surface,
|
||||
int x_offset,
|
||||
int y_offset);
|
||||
|
||||
CAIRO_END_DECLS
|
||||
|
||||
#endif /* CAIRO_HAS_XLIB_SURFACE */
|
||||
|
|
|
|||
|
|
@ -883,6 +883,11 @@ cairo_surface_set_user_data (cairo_surface_t *surface,
|
|||
void *user_data,
|
||||
cairo_destroy_func_t destroy);
|
||||
|
||||
void
|
||||
cairo_surface_set_device_offset (cairo_surface_t *surface,
|
||||
double x_offset,
|
||||
double y_offset);
|
||||
|
||||
/* Image-surface functions */
|
||||
|
||||
cairo_surface_t *
|
||||
|
|
|
|||
|
|
@ -723,6 +723,26 @@ _cairo_gstate_inverse_transform_point (cairo_gstate_t *gstate, double *x, double
|
|||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static void
|
||||
_cairo_gstate_user_to_backend (cairo_gstate_t *gstate, double *x, double *y)
|
||||
{
|
||||
cairo_matrix_transform_point (&gstate->ctm, x, y);
|
||||
if (gstate->surface) {
|
||||
*x += gstate->surface->device_x_offset;
|
||||
*y += gstate->surface->device_y_offset;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
_cairo_gstate_backend_to_user (cairo_gstate_t *gstate, double *x, double *y)
|
||||
{
|
||||
if (gstate->surface) {
|
||||
*x -= gstate->surface->device_x_offset;
|
||||
*y -= gstate->surface->device_y_offset;
|
||||
}
|
||||
cairo_matrix_transform_point (&gstate->ctm_inverse, x, y);
|
||||
}
|
||||
|
||||
cairo_status_t
|
||||
_cairo_gstate_inverse_transform_distance (cairo_gstate_t *gstate, double *dx, double *dy)
|
||||
{
|
||||
|
|
@ -744,7 +764,7 @@ _cairo_gstate_move_to (cairo_gstate_t *gstate, double x, double y)
|
|||
{
|
||||
cairo_point_t point;
|
||||
|
||||
cairo_matrix_transform_point (&gstate->ctm, &x, &y);
|
||||
_cairo_gstate_user_to_backend (gstate, &x, &y);
|
||||
|
||||
point.x = _cairo_fixed_from_double (x);
|
||||
point.y = _cairo_fixed_from_double (y);
|
||||
|
|
@ -757,7 +777,7 @@ _cairo_gstate_line_to (cairo_gstate_t *gstate, double x, double y)
|
|||
{
|
||||
cairo_point_t point;
|
||||
|
||||
cairo_matrix_transform_point (&gstate->ctm, &x, &y);
|
||||
_cairo_gstate_user_to_backend (gstate, &x, &y);
|
||||
|
||||
point.x = _cairo_fixed_from_double (x);
|
||||
point.y = _cairo_fixed_from_double (y);
|
||||
|
|
@ -773,9 +793,9 @@ _cairo_gstate_curve_to (cairo_gstate_t *gstate,
|
|||
{
|
||||
cairo_point_t p0, p1, p2;
|
||||
|
||||
cairo_matrix_transform_point (&gstate->ctm, &x0, &y0);
|
||||
cairo_matrix_transform_point (&gstate->ctm, &x1, &y1);
|
||||
cairo_matrix_transform_point (&gstate->ctm, &x2, &y2);
|
||||
_cairo_gstate_user_to_backend (gstate, &x0, &y0);
|
||||
_cairo_gstate_user_to_backend (gstate, &x1, &y1);
|
||||
_cairo_gstate_user_to_backend (gstate, &x2, &y2);
|
||||
|
||||
p0.x = _cairo_fixed_from_double (x0);
|
||||
p0.y = _cairo_fixed_from_double (y0);
|
||||
|
|
@ -1146,7 +1166,7 @@ _cairo_gstate_get_current_point (cairo_gstate_t *gstate, double *x_ret, double *
|
|||
} else {
|
||||
x = _cairo_fixed_to_double (point.x);
|
||||
y = _cairo_fixed_to_double (point.y);
|
||||
cairo_matrix_transform_point (&gstate->ctm_inverse, &x, &y);
|
||||
_cairo_gstate_backend_to_user (gstate, &x, &y);
|
||||
}
|
||||
|
||||
if (x_ret)
|
||||
|
|
@ -1289,6 +1309,11 @@ _cairo_gstate_interpret_path (cairo_gstate_t *gstate,
|
|||
_cairo_path_init_copy (&path, &gstate->path);
|
||||
|
||||
cairo_matrix_copy (&gpi.ctm_inverse, &gstate->ctm_inverse);
|
||||
if (gstate->surface)
|
||||
cairo_matrix_translate (&gpi.ctm_inverse,
|
||||
- gstate->surface->device_x_offset,
|
||||
- gstate->surface->device_y_offset);
|
||||
|
||||
gpi.tolerance = gstate->tolerance;
|
||||
|
||||
gpi.move_to = move_to;
|
||||
|
|
@ -1309,6 +1334,20 @@ _cairo_gstate_interpret_path (cairo_gstate_t *gstate,
|
|||
&gpi);
|
||||
}
|
||||
|
||||
static void
|
||||
_cairo_gstate_pattern_transform (cairo_gstate_t *gstate,
|
||||
cairo_pattern_t *pattern)
|
||||
{
|
||||
cairo_matrix_t tmp_matrix = gstate->ctm_inverse;
|
||||
|
||||
if (gstate->surface)
|
||||
cairo_matrix_translate (&tmp_matrix,
|
||||
- gstate->surface->device_x_offset,
|
||||
- gstate->surface->device_y_offset);
|
||||
|
||||
_cairo_pattern_transform (pattern, &tmp_matrix);
|
||||
}
|
||||
|
||||
/* XXX: gstate->alpha will be going away before too long, and when it
|
||||
* does, it may make sense for this function to just disappear.
|
||||
*/
|
||||
|
|
@ -1318,7 +1357,7 @@ _cairo_gstate_pattern_init_copy (cairo_gstate_t *gstate,
|
|||
cairo_pattern_t *src)
|
||||
{
|
||||
_cairo_pattern_init_copy (&pattern->base, src);
|
||||
_cairo_pattern_transform (&pattern->base, &gstate->ctm_inverse);
|
||||
_cairo_gstate_pattern_transform (gstate, &pattern->base);
|
||||
_cairo_pattern_set_alpha (&pattern->base, gstate->alpha);
|
||||
}
|
||||
|
||||
|
|
@ -1363,7 +1402,7 @@ _cairo_gstate_in_stroke (cairo_gstate_t *gstate,
|
|||
cairo_status_t status = CAIRO_STATUS_SUCCESS;
|
||||
cairo_traps_t traps;
|
||||
|
||||
cairo_matrix_transform_point (&gstate->ctm, &x, &y);
|
||||
_cairo_gstate_user_to_backend (gstate, &x, &y);
|
||||
|
||||
_cairo_pen_init (&gstate->pen_regular, gstate->line_width / 2.0, gstate);
|
||||
|
||||
|
|
@ -1658,7 +1697,7 @@ _cairo_gstate_in_fill (cairo_gstate_t *gstate,
|
|||
cairo_status_t status = CAIRO_STATUS_SUCCESS;
|
||||
cairo_traps_t traps;
|
||||
|
||||
cairo_matrix_transform_point (&gstate->ctm, &x, &y);
|
||||
_cairo_gstate_user_to_backend (gstate, &x, &y);
|
||||
|
||||
_cairo_traps_init (&traps);
|
||||
|
||||
|
|
@ -1714,8 +1753,8 @@ _cairo_gstate_stroke_extents (cairo_gstate_t *gstate,
|
|||
*x2 = _cairo_fixed_to_double (extents.p2.x);
|
||||
*y2 = _cairo_fixed_to_double (extents.p2.y);
|
||||
|
||||
cairo_matrix_transform_point (&gstate->ctm_inverse, x1, y1);
|
||||
cairo_matrix_transform_point (&gstate->ctm_inverse, x2, y2);
|
||||
_cairo_gstate_backend_to_user (gstate, x1, y1);
|
||||
_cairo_gstate_backend_to_user (gstate, x2, y2);
|
||||
|
||||
BAIL:
|
||||
_cairo_traps_fini (&traps);
|
||||
|
|
@ -1745,8 +1784,8 @@ _cairo_gstate_fill_extents (cairo_gstate_t *gstate,
|
|||
*x2 = _cairo_fixed_to_double (extents.p2.x);
|
||||
*y2 = _cairo_fixed_to_double (extents.p2.y);
|
||||
|
||||
cairo_matrix_transform_point (&gstate->ctm_inverse, x1, y1);
|
||||
cairo_matrix_transform_point (&gstate->ctm_inverse, x2, y2);
|
||||
_cairo_gstate_backend_to_user (gstate, x1, y1);
|
||||
_cairo_gstate_backend_to_user (gstate, x2, y2);
|
||||
|
||||
BAIL:
|
||||
_cairo_traps_fini (&traps);
|
||||
|
|
@ -2004,9 +2043,9 @@ _cairo_gstate_show_surface (cairo_gstate_t *gstate,
|
|||
*/
|
||||
|
||||
cairo_status_t status = CAIRO_STATUS_SUCCESS;
|
||||
cairo_matrix_t image_to_user, image_to_device;
|
||||
double device_x, device_y;
|
||||
double device_width, device_height;
|
||||
cairo_matrix_t image_to_user, image_to_device, image_to_backend;
|
||||
double backend_x, backend_y;
|
||||
double backend_width, backend_height;
|
||||
cairo_surface_pattern_t pattern;
|
||||
cairo_box_t pattern_extents;
|
||||
cairo_rectangle_t extents;
|
||||
|
|
@ -2014,13 +2053,23 @@ _cairo_gstate_show_surface (cairo_gstate_t *gstate,
|
|||
cairo_surface_get_matrix (surface, &image_to_user);
|
||||
cairo_matrix_invert (&image_to_user);
|
||||
cairo_matrix_multiply (&image_to_device, &image_to_user, &gstate->ctm);
|
||||
if (gstate->surface) {
|
||||
cairo_matrix_t device_to_backend;
|
||||
|
||||
_cairo_matrix_set_translate (&device_to_backend,
|
||||
gstate->surface->device_x_offset,
|
||||
gstate->surface->device_y_offset);
|
||||
cairo_matrix_multiply (&image_to_backend, &image_to_device, &device_to_backend);
|
||||
} else {
|
||||
image_to_backend = image_to_device;
|
||||
}
|
||||
|
||||
_cairo_gstate_get_current_point (gstate, &device_x, &device_y);
|
||||
device_width = width;
|
||||
device_height = height;
|
||||
_cairo_matrix_transform_bounding_box (&image_to_device,
|
||||
&device_x, &device_y,
|
||||
&device_width, &device_height);
|
||||
_cairo_gstate_get_current_point (gstate, &backend_x, &backend_y);
|
||||
backend_width = width;
|
||||
backend_height = height;
|
||||
_cairo_matrix_transform_bounding_box (&image_to_backend,
|
||||
&backend_x, &backend_y,
|
||||
&backend_width, &backend_height);
|
||||
|
||||
_cairo_pattern_init_for_surface (&pattern, surface);
|
||||
|
||||
|
|
@ -2033,13 +2082,13 @@ _cairo_gstate_show_surface (cairo_gstate_t *gstate,
|
|||
else
|
||||
pattern.base.extend = CAIRO_EXTEND_NONE;
|
||||
|
||||
_cairo_pattern_transform (&pattern.base, &gstate->ctm_inverse);
|
||||
_cairo_gstate_pattern_transform (gstate, &pattern.base);
|
||||
_cairo_pattern_set_alpha (&pattern.base, gstate->alpha);
|
||||
|
||||
pattern_extents.p1.x = _cairo_fixed_from_double (device_x);
|
||||
pattern_extents.p1.y = _cairo_fixed_from_double (device_y);
|
||||
pattern_extents.p2.x = _cairo_fixed_from_double (device_x + device_width);
|
||||
pattern_extents.p2.y = _cairo_fixed_from_double (device_y + device_height);
|
||||
pattern_extents.p1.x = _cairo_fixed_from_double (backend_x);
|
||||
pattern_extents.p1.y = _cairo_fixed_from_double (backend_y);
|
||||
pattern_extents.p2.x = _cairo_fixed_from_double (backend_x + backend_width);
|
||||
pattern_extents.p2.y = _cairo_fixed_from_double (backend_y + backend_height);
|
||||
_cairo_box_round_to_rectangle (&pattern_extents, &extents);
|
||||
|
||||
if (gstate->clip.surface)
|
||||
|
|
@ -2334,8 +2383,8 @@ _cairo_gstate_text_to_glyphs (cairo_gstate_t *gstate,
|
|||
} else {
|
||||
origin_x = _cairo_fixed_to_double (point.x);
|
||||
origin_y = _cairo_fixed_to_double (point.y);
|
||||
cairo_matrix_transform_point (&gstate->ctm_inverse,
|
||||
&origin_x, &origin_y);
|
||||
_cairo_gstate_backend_to_user (gstate,
|
||||
&origin_x, &origin_y);
|
||||
}
|
||||
|
||||
status = _cairo_font_text_to_glyphs (gstate->font,
|
||||
|
|
@ -2417,9 +2466,9 @@ _cairo_gstate_show_glyphs (cairo_gstate_t *gstate,
|
|||
for (i = 0; i < num_glyphs; ++i)
|
||||
{
|
||||
transformed_glyphs[i] = glyphs[i];
|
||||
cairo_matrix_transform_point (&gstate->ctm,
|
||||
&transformed_glyphs[i].x,
|
||||
&transformed_glyphs[i].y);
|
||||
_cairo_gstate_user_to_backend (gstate,
|
||||
&transformed_glyphs[i].x,
|
||||
&transformed_glyphs[i].y);
|
||||
}
|
||||
|
||||
status = _cairo_font_glyph_bbox (gstate->font,
|
||||
|
|
@ -2552,9 +2601,9 @@ _cairo_gstate_glyph_path (cairo_gstate_t *gstate,
|
|||
for (i = 0; i < num_glyphs; ++i)
|
||||
{
|
||||
transformed_glyphs[i] = glyphs[i];
|
||||
cairo_matrix_transform_point (&gstate->ctm,
|
||||
&(transformed_glyphs[i].x),
|
||||
&(transformed_glyphs[i].y));
|
||||
_cairo_gstate_user_to_backend (gstate,
|
||||
&(transformed_glyphs[i].x),
|
||||
&(transformed_glyphs[i].y));
|
||||
}
|
||||
|
||||
status = _cairo_font_glyph_path (gstate->font,
|
||||
|
|
|
|||
|
|
@ -59,6 +59,9 @@ _cairo_surface_init (cairo_surface_t *surface,
|
|||
_cairo_matrix_init (&surface->matrix);
|
||||
surface->filter = CAIRO_FILTER_NEAREST;
|
||||
surface->repeat = 0;
|
||||
|
||||
surface->device_x_offset = 0;
|
||||
surface->device_y_offset = 0;
|
||||
}
|
||||
|
||||
cairo_surface_t *
|
||||
|
|
@ -290,6 +293,33 @@ cairo_surface_set_user_data (cairo_surface_t *surface,
|
|||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* cairo_surface_set_device_offset:
|
||||
* @surface: a #cairo_surface_t
|
||||
* @x_offset: the offset in the X direction, in device units
|
||||
* @y_offset: the offset in the Y direction, in device units
|
||||
*
|
||||
* Sets an offset that is added to the device coordinates determined
|
||||
* by the CTM when drawing to @surface. One use case for this function
|
||||
* is when we want to create a #cairo_surface_t that redirects drawing
|
||||
* for a portion of an onscreen surface to an offscreen surface in a
|
||||
* way that is completely invisible to the user of the cairo
|
||||
* API. Setting a transformation via cairo_translate() isn't
|
||||
* sufficient to do this, since functions like
|
||||
* cairo_inverse_transform_point() will expose the hidden offset.
|
||||
*
|
||||
* Note that the offset only affects drawing to the surface, not using
|
||||
* the surface in a surface pattern.
|
||||
**/
|
||||
void
|
||||
cairo_surface_set_device_offset (cairo_surface_t *surface,
|
||||
double x_offset,
|
||||
double y_offset)
|
||||
{
|
||||
surface->device_x_offset = x_offset;
|
||||
surface->device_y_offset = y_offset;
|
||||
}
|
||||
|
||||
double
|
||||
_cairo_surface_pixels_per_inch (cairo_surface_t *surface)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -105,9 +105,6 @@ struct _cairo_xlib_surface {
|
|||
int height;
|
||||
int depth;
|
||||
|
||||
int x_offset;
|
||||
int y_offset;
|
||||
|
||||
Picture picture;
|
||||
};
|
||||
|
||||
|
|
@ -252,8 +249,8 @@ _get_image_surface (cairo_xlib_surface_t *surface,
|
|||
if (interest_rect) {
|
||||
cairo_rectangle_t rect;
|
||||
|
||||
rect.x = interest_rect->x + surface->x_offset;
|
||||
rect.y = interest_rect->y + surface->x_offset;
|
||||
rect.x = interest_rect->x;
|
||||
rect.y = interest_rect->y;
|
||||
rect.width = interest_rect->width;
|
||||
rect.height = interest_rect->width;
|
||||
|
||||
|
|
@ -273,8 +270,8 @@ _get_image_surface (cairo_xlib_surface_t *surface,
|
|||
}
|
||||
|
||||
if (image_rect) {
|
||||
image_rect->x = x1 - surface->x_offset;
|
||||
image_rect->y = y1 - surface->y_offset;
|
||||
image_rect->x = x1;
|
||||
image_rect->y = y1;
|
||||
image_rect->width = x2 - x1;
|
||||
image_rect->height = y2 - y1;
|
||||
}
|
||||
|
|
@ -396,7 +393,7 @@ _draw_image_surface (cairo_xlib_surface_t *surface,
|
|||
|
||||
_cairo_xlib_surface_ensure_gc (surface);
|
||||
XPutImage(surface->dpy, surface->drawable, surface->gc,
|
||||
ximage, 0, 0, dst_x + surface->x_offset, dst_y + surface->y_offset,
|
||||
ximage, 0, 0, dst_x, dst_y,
|
||||
image->width, image->height);
|
||||
|
||||
/* Foolish XDestroyImage thinks it can free my data, but I won't
|
||||
|
|
@ -735,7 +732,7 @@ _cairo_xlib_surface_composite (cairo_operator_t operator,
|
|||
src_x + src_attr.x_offset,
|
||||
src_y + src_attr.y_offset,
|
||||
0, 0,
|
||||
dst_x + dst->x_offset, dst_y + dst->y_offset,
|
||||
dst_x, dst_y,
|
||||
width, height);
|
||||
}
|
||||
}
|
||||
|
|
@ -748,20 +745,6 @@ _cairo_xlib_surface_composite (cairo_operator_t operator,
|
|||
return status;
|
||||
}
|
||||
|
||||
static void
|
||||
_translate_rects (cairo_rectangle_t *rects,
|
||||
int num_rects,
|
||||
int x_offset,
|
||||
int y_offset)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < num_rects; i++) {
|
||||
rects[i].x += x_offset;
|
||||
rects[i].y += y_offset;
|
||||
}
|
||||
}
|
||||
|
||||
static cairo_int_status_t
|
||||
_cairo_xlib_surface_fill_rectangles (void *abstract_surface,
|
||||
cairo_operator_t operator,
|
||||
|
|
@ -780,10 +763,6 @@ _cairo_xlib_surface_fill_rectangles (void *abstract_surface,
|
|||
render_color.blue = color->blue_short;
|
||||
render_color.alpha = color->alpha_short;
|
||||
|
||||
if (surface->x_offset != 0 || surface->y_offset != 0)
|
||||
_translate_rects (rects, num_rects,
|
||||
surface->x_offset, surface->y_offset);
|
||||
|
||||
/* XXX: This XRectangle cast is evil... it needs to go away somehow. */
|
||||
XRenderFillRectangles (surface->dpy,
|
||||
_render_operator (operator),
|
||||
|
|
@ -793,31 +772,6 @@ _cairo_xlib_surface_fill_rectangles (void *abstract_surface,
|
|||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static void
|
||||
_translate_traps (cairo_trapezoid_t *traps,
|
||||
int num_traps,
|
||||
int x_offset,
|
||||
int y_offset)
|
||||
{
|
||||
cairo_fixed_t xoff, yoff;
|
||||
int i;
|
||||
|
||||
xoff = _cairo_fixed_from_int (x_offset);
|
||||
yoff = _cairo_fixed_from_int (y_offset);
|
||||
|
||||
for (i = 0; i < num_traps; i++) {
|
||||
traps[i].top += yoff;
|
||||
traps[i].bottom += yoff;
|
||||
traps[i].left.p1.x += xoff;
|
||||
traps[i].left.p1.y += yoff;
|
||||
traps[i].left.p2.x += xoff;
|
||||
traps[i].left.p2.y += yoff;
|
||||
traps[i].right.p1.x += xoff;
|
||||
traps[i].right.p1.y += yoff;
|
||||
traps[i].right.p2.x += xoff;
|
||||
traps[i].right.p2.y += yoff;
|
||||
}
|
||||
}
|
||||
static cairo_int_status_t
|
||||
_cairo_xlib_surface_composite_trapezoids (cairo_operator_t operator,
|
||||
cairo_pattern_t *pattern,
|
||||
|
|
@ -848,9 +802,6 @@ _cairo_xlib_surface_composite_trapezoids (cairo_operator_t operator,
|
|||
if (status)
|
||||
return status;
|
||||
|
||||
if (dst->x_offset != 0 || dst->y_offset != 0)
|
||||
_translate_traps (traps, num_traps, dst->x_offset, dst->y_offset);
|
||||
|
||||
if (traps[0].left.p1.y < traps[0].left.p2.y) {
|
||||
render_reference_x = _cairo_fixed_integer_floor (traps[0].left.p1.x);
|
||||
render_reference_y = _cairo_fixed_integer_floor (traps[0].left.p1.y);
|
||||
|
|
@ -859,8 +810,8 @@ _cairo_xlib_surface_composite_trapezoids (cairo_operator_t operator,
|
|||
render_reference_y = _cairo_fixed_integer_floor (traps[0].left.p2.y);
|
||||
}
|
||||
|
||||
render_src_x = src_x + render_reference_x - (dst_x + dst->x_offset);
|
||||
render_src_y = src_y + render_reference_y - (dst_y + dst->y_offset);
|
||||
render_src_x = src_x + render_reference_x - dst_x;
|
||||
render_src_y = src_y + render_reference_y - dst_y;
|
||||
|
||||
/* XXX: The XTrapezoid cast is evil and needs to go away somehow. */
|
||||
status = _cairo_xlib_surface_set_attributes (src, &attributes);
|
||||
|
|
@ -923,8 +874,8 @@ _cairo_xlib_surface_set_clip_region (void *abstract_surface,
|
|||
boxes = pixman_region_rects (region);
|
||||
|
||||
for (i = 0; i < n_boxes; i++) {
|
||||
rects[i].x = boxes[i].x1 + surface->x_offset;
|
||||
rects[i].y = boxes[i].y1 + surface->y_offset;
|
||||
rects[i].x = boxes[i].x1;
|
||||
rects[i].y = boxes[i].y1;
|
||||
rects[i].width = boxes[i].x2 - boxes[i].x1;
|
||||
rects[i].height = boxes[i].y2 - boxes[i].y1;
|
||||
}
|
||||
|
|
@ -999,8 +950,6 @@ _cairo_xlib_surface_create_internal (Display *dpy,
|
|||
surface->owns_pixmap = FALSE;
|
||||
surface->width = -1;
|
||||
surface->height = -1;
|
||||
surface->x_offset = 0;
|
||||
surface->y_offset = 0;
|
||||
|
||||
if (visual) {
|
||||
int i, j, k;
|
||||
|
|
@ -1204,34 +1153,6 @@ cairo_xlib_surface_set_size (cairo_surface_t *surface,
|
|||
xlib_surface->height = height;
|
||||
}
|
||||
|
||||
/**
|
||||
* cairo_xlib_surface_set_device_offset:
|
||||
* @surface: a #cairo_surface_t for the XLib backend
|
||||
* @x_offset: offset in the X direction, in pixels
|
||||
* @y_offset: offset in the Y direction, in pixels
|
||||
*
|
||||
* Sets an offset that is added to the device coordinates determined
|
||||
* by the CTM when drawing to @surface. This is useful when we want
|
||||
* to redirect drawing to a window to a backing pixmap for a portion
|
||||
* of the window in a way that is completely invisible to the user
|
||||
* of the Cairo API. Setting a transformation via cairo_translate() isn't
|
||||
* sufficient to do this, since functions like
|
||||
* cairo_inverse_transform_point() will expose the hidden offset.
|
||||
*
|
||||
* Note that the offset only affects drawing to the surface, not using
|
||||
* the surface in a surface pattern.
|
||||
**/
|
||||
void
|
||||
cairo_xlib_surface_set_device_offset (cairo_surface_t *surface,
|
||||
int x_offset,
|
||||
int y_offset)
|
||||
{
|
||||
cairo_xlib_surface_t *xlib_surface = (cairo_xlib_surface_t *)surface;
|
||||
|
||||
xlib_surface->x_offset = x_offset;
|
||||
xlib_surface->y_offset = y_offset;
|
||||
}
|
||||
|
||||
/* RENDER glyphset cache code */
|
||||
|
||||
typedef struct glyphset_cache {
|
||||
|
|
@ -1488,8 +1409,8 @@ _cairo_xlib_surface_show_glyphs32 (cairo_font_t *font,
|
|||
elts[i].chars = &(chars[i]);
|
||||
elts[i].nchars = 1;
|
||||
elts[i].glyphset = g->glyphset;
|
||||
thisX = (int) floor (glyphs[i].x + 0.5) + self->x_offset;
|
||||
thisY = (int) floor (glyphs[i].y + 0.5) + self->y_offset;
|
||||
thisX = (int) floor (glyphs[i].x + 0.5);
|
||||
thisY = (int) floor (glyphs[i].y + 0.5);
|
||||
elts[i].xOff = thisX - lastX;
|
||||
elts[i].yOff = thisY - lastY;
|
||||
lastX = thisX;
|
||||
|
|
@ -1565,8 +1486,8 @@ _cairo_xlib_surface_show_glyphs16 (cairo_font_t *font,
|
|||
elts[i].chars = &(chars[i]);
|
||||
elts[i].nchars = 1;
|
||||
elts[i].glyphset = g->glyphset;
|
||||
thisX = (int) floor (glyphs[i].x + 0.5) + self->x_offset;
|
||||
thisY = (int) floor (glyphs[i].y + 0.5) + self->y_offset;
|
||||
thisX = (int) floor (glyphs[i].x + 0.5);
|
||||
thisY = (int) floor (glyphs[i].y + 0.5);
|
||||
elts[i].xOff = thisX - lastX;
|
||||
elts[i].yOff = thisY - lastY;
|
||||
lastX = thisX;
|
||||
|
|
@ -1641,8 +1562,8 @@ _cairo_xlib_surface_show_glyphs8 (cairo_font_t *font,
|
|||
elts[i].chars = &(chars[i]);
|
||||
elts[i].nchars = 1;
|
||||
elts[i].glyphset = g->glyphset;
|
||||
thisX = (int) floor (glyphs[i].x + 0.5) + self->x_offset;
|
||||
thisY = (int) floor (glyphs[i].y + 0.5) + self->y_offset;
|
||||
thisX = (int) floor (glyphs[i].x + 0.5);
|
||||
thisY = (int) floor (glyphs[i].y + 0.5);
|
||||
elts[i].xOff = thisX - lastX;
|
||||
elts[i].yOff = thisY - lastY;
|
||||
lastX = thisX;
|
||||
|
|
|
|||
|
|
@ -673,6 +673,9 @@ struct _cairo_surface {
|
|||
cairo_matrix_t matrix;
|
||||
cairo_filter_t filter;
|
||||
int repeat;
|
||||
|
||||
double device_x_offset;
|
||||
double device_y_offset;
|
||||
};
|
||||
|
||||
struct _cairo_image_surface {
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue