Moved all libic-related drawing into cairo_image_surface.c

This commit is contained in:
Carl Worth 2003-10-31 10:41:37 +00:00
parent 6dca2ab9d3
commit 32df4d217d
17 changed files with 1997 additions and 1075 deletions

View file

@ -1,3 +1,69 @@
2003-10-31 Carl Worth <cworth@isi.edu>
* Moved all libic-related drawing into cairo_image_surface.c.
Details below:
* src/cairo_xlib_surface.c: Add width, height, format to
cairo_xlib_surface_t.
(_cairo_xlib_surface_get_image):
(_cairo_xlib_surface_set_image): Implement new get_image/set_image
interface instead of pull_image/push_image.
(_cairo_xlib_surface_get_image): Fix memory leak that showed up
with non-Render servers.
(_cairo_xlib_surface_set_matrix): Implement set_matrix with new
interface.
(_render_operator): Translate from cairo_operator_t to
Render-defined operator values rather than assuming they are the
same.
* src/cairo_surface.c: Move all libic-related code into
cairo_image_surface.c. cairo_surface is now a thin wrapper around
concrete surface types, (with fallback code to cairo_image_surface
whenever a backend does not provide support for a particular
function). Remove checks for NULL backend functions.
(_cairo_surface_get_image):
(_cairo_surface_set_image): New interface to replace
pull_image/push_image. Now uses a cairo_image_surface rather than
an IcImage and now also passes it externally rather than storing
it in the surface.
* src/cairo_gstate.c (_cairo_gstate_fini):
(_cairo_gstate_set_target_surface):
(_cairo_gstate_set_rgb_color): Avoid useless calls to
cairo_surface_destroy for NULL surfaces.
(_cairo_gstate_show_surface):
(_cairo_gstate_clip):
(_cairo_gstate_clip_and_composite_trapezoids):
(_cairo_gstate_begin_group): Add status checking for calls to
surface_create_similar, surface_fill_rectangles,
surface_composite, and surface_composite_trapezoids.
* src/cairo_ft_font.c (_cairo_ft_font_show_glyphs): Remove one
gratuitous level of nesting.
(_cairo_ft_font_show_glyphs): Bubble up NULL_MEMORY status.
* src/cairo.h: Portability improvements: Remove include of
X11/extensions/Xrender.h. Move include down near the freetype
include.
cairo_format_t: Eliminate Render-based values for this enum.
cairo_operator_t: Eliminate Render-based values. Drop
disjoint/conjoint operators.
cairo_filter_t: Eliminate libic-based values for this enum.
Add cairo_image_surface_create and cairo_image_surface_create_for_data.
* src/cairo.c (cairo_status_string): Add new CAIRO_STATUS_NULL_POINTER.
This can be returned only if the user passes a NULL object in to a
cairo function.
* src/cairoint.h: Move include of <X11/extensions/Xrender.h> from
cairo.h to here.
* src/Makefile.am (libcairo_la_SOURCES): Add
cairo_image_surface.c. Reformat line continuation characters.
* src/cairoint.h: Remove prototypes for obsolete functions:
_cairo_gstate_set_visual and _cairo_gstate_set_format.
2003-10-30 Carl Worth <cworth@isi.edu>
* src/cairo_xlib_surface.c (_cairo_xlib_surface_destroy): Fix

View file

@ -40,7 +40,7 @@ AC_PATH_XTRA
dnl ===========================================================================
PKG_CHECK_MODULES(CAIRO, slim >= 0.2.0 libic >= 0.1.1 xft xrender >= 0.6)
PKG_CHECK_MODULES(CAIRO, slim >= 0.2.0 libic >= 0.1.3 xft xrender >= 0.6)
AC_SUBST(CAIRO_CFLAGS)
AC_SUBST(CAIRO_LIBS)

View file

@ -1,27 +1,28 @@
lib_LTLIBRARIES = libcairo.la
include_HEADERS = cairo.h cairo-xlib.h
libcairo_la_SOURCES = \
cairo.c \
cairo.h \
cairo_color.c \
cairo_fixed.c \
cairo_font.c \
cairo_ft_font.c \
cairo_gstate.c \
cairo_hull.c \
cairo_matrix.c \
cairo_path.c \
cairo_path_bounds.c \
cairo_path_fill.c \
cairo_path_stroke.c \
cairo_pen.c \
cairo_polygon.c \
cairo_slope.c \
cairo_spline.c \
cairo_surface.c \
cairo_xlib_surface.c \
cairo_traps.c \
libcairo_la_SOURCES = \
cairo.c \
cairo.h \
cairo_color.c \
cairo_fixed.c \
cairo_font.c \
cairo_ft_font.c \
cairo_gstate.c \
cairo_hull.c \
cairo_image_surface.c \
cairo_matrix.c \
cairo_path.c \
cairo_path_bounds.c \
cairo_path_fill.c \
cairo_path_stroke.c \
cairo_pen.c \
cairo_polygon.c \
cairo_slope.c \
cairo_spline.c \
cairo_surface.c \
cairo_traps.c \
cairo_xlib_surface.c \
cairoint.h
libcairo_la_LDFLAGS = -version-info @VERSION_INFO@

View file

@ -427,6 +427,7 @@ _cairo_ft_font_show_glyphs (cairo_font_t *font,
const cairo_glyph_t *glyphs,
int num_glyphs)
{
cairo_status_t status;
int i;
cairo_ft_font_t *ft = NULL;
FT_GlyphSlot glyphslot;
@ -447,68 +448,72 @@ _cairo_ft_font_show_glyphs (cairo_font_t *font,
for (i = 0; i < num_glyphs; i++)
{
unsigned char *bitmap;
FT_Load_Glyph (ft->face, glyphs[i].index, FT_LOAD_DEFAULT);
FT_Render_Glyph (glyphslot, FT_RENDER_MODE_NORMAL);
width = glyphslot->bitmap.width;
height = glyphslot->bitmap.rows;
stride = glyphslot->bitmap.pitch;
bitmap = glyphslot->bitmap.buffer;
x = x0 + glyphs[i].x;
y = y0 + glyphs[i].y;
/* X gets upset with zero-sized images (such as whitespace) */
if (width * height != 0)
{
unsigned char *bitmap = glyphslot->bitmap.buffer;
if (width * height == 0)
continue;
/*
* XXX
* reformat to match libic alignment requirements.
* This should be done before rendering the glyph,
* but that requires using FT_Outline_Get_Bitmap
* function
*/
if (stride & 3)
/*
* XXX
* reformat to match libic alignment requirements.
* This should be done before rendering the glyph,
* but that requires using FT_Outline_Get_Bitmap
* function
*/
if (stride & 3)
{
int nstride = (stride + 3) & ~3;
unsigned char *g, *b;
int h;
bitmap = malloc (nstride * height);
if (!bitmap)
return CAIRO_STATUS_NO_MEMORY;
g = glyphslot->bitmap.buffer;
b = bitmap;
h = height;
while (h--)
{
int nstride = (stride + 3) & ~3;
unsigned char *g, *b;
int h;
bitmap = malloc (nstride * height);
if (!bitmap)
return CAIRO_STATUS_NO_MEMORY;
g = glyphslot->bitmap.buffer;
b = bitmap;
h = height;
while (h--)
{
memcpy (b, g, width);
b += nstride;
g += stride;
}
stride = nstride;
memcpy (b, g, width);
b += nstride;
g += stride;
}
mask = cairo_surface_create_for_image (bitmap,
CAIRO_FORMAT_A8,
width, height, stride);
if (mask == NULL)
{
if (bitmap != glyphslot->bitmap.buffer)
free (bitmap);
return CAIRO_STATUS_NO_MEMORY;
}
_cairo_surface_composite (operator, source, mask, surface,
0, 0, 0, 0,
x + glyphslot->bitmap_left,
y - glyphslot->bitmap_top,
(double)width, (double)height);
cairo_surface_destroy (mask);
stride = nstride;
}
mask = cairo_surface_create_for_image (bitmap,
CAIRO_FORMAT_A8,
width, height, stride);
if (mask == NULL)
{
if (bitmap != glyphslot->bitmap.buffer)
free (bitmap);
}
return CAIRO_STATUS_NO_MEMORY;
}
status = _cairo_surface_composite (operator, source, mask, surface,
0, 0, 0, 0,
x + glyphslot->bitmap_left,
y - glyphslot->bitmap_top,
(double)width, (double)height);
cairo_surface_destroy (mask);
if (bitmap != glyphslot->bitmap.buffer)
free (bitmap);
if (status)
return status;
}
return CAIRO_STATUS_SUCCESS;
}

View file

@ -160,14 +160,17 @@ _cairo_gstate_fini (cairo_gstate_t *gstate)
{
cairo_font_destroy (gstate->font);
cairo_surface_destroy (gstate->surface);
if (gstate->surface)
cairo_surface_destroy (gstate->surface);
gstate->surface = NULL;
cairo_surface_destroy (gstate->source);
if (gstate->source)
cairo_surface_destroy (gstate->source);
gstate->source = NULL;
gstate->source_is_solid = 1;
cairo_surface_destroy (gstate->clip.surface);
if (gstate->clip.surface)
cairo_surface_destroy (gstate->clip.surface);
gstate->clip.surface = NULL;
_cairo_color_fini (&gstate->color);
@ -256,12 +259,14 @@ _cairo_gstate_begin_group (cairo_gstate_t *gstate)
_cairo_color_init (&clear);
_cairo_color_set_alpha (&clear, 0);
_cairo_surface_fill_rectangle (gstate->surface,
status = _cairo_surface_fill_rectangle (gstate->surface,
CAIRO_OPERATOR_SRC,
&clear,
0, 0,
_cairo_surface_get_width (gstate->surface),
_cairo_surface_get_height (gstate->surface));
if (status)
return status;
return CAIRO_STATUS_SUCCESS;
}
@ -316,7 +321,8 @@ _cairo_gstate_set_target_surface (cairo_gstate_t *gstate, cairo_surface_t *surfa
{
double scale;
cairo_surface_destroy (gstate->surface);
if (gstate->surface)
cairo_surface_destroy (gstate->surface);
gstate->surface = surface;
cairo_surface_reference (gstate->surface);
@ -375,7 +381,8 @@ _cairo_gstate_set_rgb_color (cairo_gstate_t *gstate, double red, double green, d
{
_cairo_color_set_rgb (&gstate->color, red, green, blue);
cairo_surface_destroy (gstate->source);
if (gstate->source)
cairo_surface_destroy (gstate->source);
gstate->source = NULL;
gstate->source_offset.x = 0;
@ -1177,6 +1184,8 @@ _cairo_gstate_clip_and_composite_trapezoids (cairo_gstate_t *gstate,
cairo_surface_t *dst,
cairo_traps_t *traps)
{
cairo_status_t status;
if (traps->num_traps == 0)
return CAIRO_STATUS_SUCCESS;
@ -1192,6 +1201,10 @@ _cairo_gstate_clip_and_composite_trapezoids (cairo_gstate_t *gstate,
white = _cairo_surface_create_similar_solid (gstate->surface, CAIRO_FORMAT_A8,
1, 1,
&white_color);
if (white == NULL) {
status = CAIRO_STATUS_NO_MEMORY;
goto BAIL0;
}
cairo_surface_set_repeat (white, 1);
_cairo_color_init (&empty_color);
@ -1201,6 +1214,10 @@ _cairo_gstate_clip_and_composite_trapezoids (cairo_gstate_t *gstate,
gstate->clip.width,
gstate->clip.height,
&empty_color);
if (intermediate == NULL) {
status = CAIRO_STATUS_NO_MEMORY;
goto BAIL1;
}
/* Ugh. The cairo_composite/(Render) interface doesn't allow
an offset for the trapezoids. Need to manually shift all
@ -1221,27 +1238,39 @@ _cairo_gstate_clip_and_composite_trapezoids (cairo_gstate_t *gstate,
t->right.p2.y -= yoff;
}
_cairo_surface_composite_trapezoids (CAIRO_OPERATOR_ADD,
white, intermediate,
0, 0,
traps->traps,
traps->num_traps);
_cairo_surface_composite (CAIRO_OPERATOR_IN,
gstate->clip.surface,
NULL,
intermediate,
0, 0, 0, 0, 0, 0,
gstate->clip.width, gstate->clip.height);
_cairo_surface_composite (operator,
src, intermediate, dst,
0, 0,
0, 0,
gstate->clip.x,
gstate->clip.y,
gstate->clip.width,
gstate->clip.height);
status = _cairo_surface_composite_trapezoids (CAIRO_OPERATOR_ADD,
white, intermediate,
0, 0,
traps->traps,
traps->num_traps);
if (status)
goto BAIL2;
status = _cairo_surface_composite (CAIRO_OPERATOR_IN,
gstate->clip.surface,
NULL,
intermediate,
0, 0, 0, 0, 0, 0,
gstate->clip.width, gstate->clip.height);
if (status)
goto BAIL2;
status = _cairo_surface_composite (operator,
src, intermediate, dst,
0, 0,
0, 0,
gstate->clip.x,
gstate->clip.y,
gstate->clip.width,
gstate->clip.height);
BAIL2:
cairo_surface_destroy (intermediate);
BAIL1:
cairo_surface_destroy (white);
BAIL0:
if (status)
return status;
} else {
int xoff, yoff;
@ -1254,12 +1283,14 @@ _cairo_gstate_clip_and_composite_trapezoids (cairo_gstate_t *gstate,
yoff = _cairo_fixed_to_double (traps->traps[0].left.p2.y);
}
_cairo_surface_composite_trapezoids (gstate->operator,
src, dst,
xoff - gstate->source_offset.x,
yoff - gstate->source_offset.y,
traps->traps,
traps->num_traps);
status = _cairo_surface_composite_trapezoids (gstate->operator,
src, dst,
xoff - gstate->source_offset.x,
yoff - gstate->source_offset.y,
traps->traps,
traps->num_traps);
if (status)
return status;
}
return CAIRO_STATUS_SUCCESS;
@ -1330,11 +1361,16 @@ _cairo_gstate_clip (cairo_gstate_t *gstate)
gstate->clip.width,
gstate->clip.height,
&white_color);
if (gstate->clip.surface == NULL)
return CAIRO_STATUS_NO_MEMORY;
}
alpha_one = _cairo_surface_create_similar_solid (gstate->surface, CAIRO_FORMAT_A8,
1, 1,
&white_color);
if (alpha_one == NULL)
return CAIRO_STATUS_NO_MEMORY;
cairo_surface_set_repeat (alpha_one, 1);
_cairo_traps_init (&traps);
@ -1363,6 +1399,7 @@ _cairo_gstate_show_surface (cairo_gstate_t *gstate,
int width,
int height)
{
cairo_status_t status;
cairo_surface_t *mask;
cairo_matrix_t user_to_image, image_to_user;
cairo_matrix_t image_to_device, device_to_image;
@ -1402,17 +1439,20 @@ _cairo_gstate_show_surface (cairo_gstate_t *gstate,
/* XXX: The rendered size is sometimes 1 or 2 pixels short from
what I expect. Need to fix this. */
_cairo_surface_composite (gstate->operator,
surface, mask, gstate->surface,
device_x, device_y,
0, 0,
device_x, device_y,
device_width,
device_height);
status = _cairo_surface_composite (gstate->operator,
surface, mask, gstate->surface,
device_x, device_y,
0, 0,
device_x, device_y,
device_width,
device_height);
if (mask)
cairo_surface_destroy (mask);
if (status)
return status;
/* restore the matrix originally in the surface */
cairo_surface_set_matrix (surface, &user_to_image);

429
src/cairo-image-surface.c Normal file
View file

@ -0,0 +1,429 @@
/*
* Copyright © 2003 University of Southern California
*
* Permission to use, copy, modify, distribute, and sell this software
* and its documentation for any purpose is hereby granted without
* fee, provided that the above copyright notice appear in all copies
* and that both that copyright notice and this permission notice
* appear in supporting documentation, and that the name of the
* University of Southern California not be used in advertising or
* publicity pertaining to distribution of the software without
* specific, written prior permission. The University of Southern
* California makes no representations about the suitability of this
* software for any purpose. It is provided "as is" without express
* or implied warranty.
*
* THE UNIVERSITY OF SOUTHERN CALIFORNIA DISCLAIMS ALL WARRANTIES WITH
* REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL THE UNIVERSITY OF
* SOUTHERN CALIFORNIA BE LIABLE FOR ANY SPECIAL, INDIRECT OR
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
* OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
* NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
* Author: Carl D. Worth <cworth@isi.edu>
*/
#include "cairoint.h"
static const cairo_surface_backend_t cairo_image_surface_backend;
static int
_cairo_format_bpp (cairo_format_t format)
{
switch (format) {
case CAIRO_FORMAT_A1:
return 1;
case CAIRO_FORMAT_A8:
return 8;
case CAIRO_FORMAT_RGB24:
case CAIRO_FORMAT_ARGB32:
default:
return 32;
}
}
static cairo_image_surface_t *
_cairo_image_surface_create_for_ic_image (IcImage *ic_image)
{
cairo_image_surface_t *surface;
surface = malloc (sizeof (cairo_image_surface_t));
if (surface == NULL)
return NULL;
_cairo_surface_init (&surface->base, &cairo_image_surface_backend);
surface->ic_image = ic_image;
surface->data = (char *) IcImageGetData (ic_image);
surface->owns_data = 0;
surface->width = IcImageGetWidth (ic_image);
surface->height = IcImageGetHeight (ic_image);
surface->stride = IcImageGetStride (ic_image);
surface->depth = IcImageGetDepth (ic_image);
return surface;
}
cairo_image_surface_t *
_cairo_image_surface_create_with_masks (char *data,
cairo_format_masks_t *format,
int width,
int height,
int stride)
{
cairo_image_surface_t *surface;
IcFormat *ic_format;
IcImage *ic_image;
ic_format = IcFormatCreateMasks (format->bpp,
format->alpha_mask,
format->red_mask,
format->green_mask,
format->blue_mask);
ic_image = IcImageCreateForData ((IcBits *) data, ic_format,
width, height, format->bpp, stride);
surface = _cairo_image_surface_create_for_ic_image (ic_image);
IcFormatDestroy (ic_format);
return surface;
}
static IcFormat *
_create_ic_format (cairo_format_t format)
{
switch (format) {
case CAIRO_FORMAT_A1:
return IcFormatCreate (IcFormatNameA1);
break;
case CAIRO_FORMAT_A8:
return IcFormatCreate (IcFormatNameA8);
break;
case CAIRO_FORMAT_RGB24:
return IcFormatCreate (IcFormatNameRGB24);
break;
case CAIRO_FORMAT_ARGB32:
default:
return IcFormatCreate (IcFormatNameARGB32);
break;
}
}
cairo_surface_t *
cairo_image_surface_create (cairo_format_t format,
int width,
int height)
{
cairo_image_surface_t *surface;
IcFormat *ic_format;
IcImage *ic_image;
ic_format = _create_ic_format (format);
ic_image = IcImageCreate (ic_format, width, height);
surface = _cairo_image_surface_create_for_ic_image (ic_image);
IcFormatDestroy (ic_format);
return &surface->base;
}
cairo_surface_t *
cairo_image_surface_create_for_data (char *data,
cairo_format_t format,
int width,
int height,
int stride)
{
cairo_image_surface_t *surface;
IcFormat *ic_format;
IcImage *ic_image;
ic_format = _create_ic_format (format);
ic_image = IcImageCreateForData ((IcBits *) data, ic_format,
width, height,
_cairo_format_bpp (format),
stride);
if (ic_image == NULL)
return NULL;
surface = _cairo_image_surface_create_for_ic_image (ic_image);
IcFormatDestroy (ic_format);
return &surface->base;
}
static cairo_surface_t *
_cairo_image_surface_create_similar (void *abstract_src,
cairo_format_t format,
int width,
int height)
{
return cairo_image_surface_create (format, width, height);
}
static void
_cairo_image_abstract_surface_destroy (void *abstract_surface)
{
cairo_image_surface_t *surface = abstract_surface;
if (surface->ic_image)
IcImageDestroy (surface->ic_image);
if (surface->owns_data)
free (surface->data);
free (surface);
}
void
_cairo_image_surface_assume_ownership_of_data (cairo_image_surface_t *surface)
{
surface->owns_data = 1;
}
static double
_cairo_image_surface_pixels_per_inch (void *abstract_surface)
{
/* XXX: We'll want a way to let the user set this. */
return 96.0;
}
static cairo_image_surface_t *
_cairo_image_surface_get_image (void *abstract_surface)
{
cairo_image_surface_t *surface = abstract_surface;
cairo_surface_reference (&surface->base);
return surface;
}
static cairo_status_t
_cairo_image_surface_set_image (void *abstract_surface,
cairo_image_surface_t *image)
{
if (image == abstract_surface)
return CAIRO_STATUS_SUCCESS;
/* XXX: This case has not yet been implemented. We'll lie for now. */
return CAIRO_STATUS_SUCCESS;
}
static cairo_status_t
_cairo_image_abstract_surface_set_matrix (void *abstract_surface,
cairo_matrix_t *matrix)
{
cairo_image_surface_t *surface = abstract_surface;
return _cairo_image_surface_set_matrix (surface, matrix);
}
cairo_status_t
_cairo_image_surface_set_matrix (cairo_image_surface_t *surface,
cairo_matrix_t *matrix)
{
IcTransform ic_transform;
ic_transform.matrix[0][0] = _cairo_fixed_from_double (matrix->m[0][0]);
ic_transform.matrix[0][1] = _cairo_fixed_from_double (matrix->m[1][0]);
ic_transform.matrix[0][2] = _cairo_fixed_from_double (matrix->m[2][0]);
ic_transform.matrix[1][0] = _cairo_fixed_from_double (matrix->m[0][1]);
ic_transform.matrix[1][1] = _cairo_fixed_from_double (matrix->m[1][1]);
ic_transform.matrix[1][2] = _cairo_fixed_from_double (matrix->m[2][1]);
ic_transform.matrix[2][0] = 0;
ic_transform.matrix[2][1] = 0;
ic_transform.matrix[2][2] = _cairo_fixed_from_double (1);
IcImageSetTransform (surface->ic_image, &ic_transform);
return CAIRO_STATUS_SUCCESS;
}
static cairo_status_t
_cairo_image_surface_set_filter (void *abstract_surface, cairo_filter_t filter)
{
cairo_image_surface_t *surface = abstract_surface;
IcFilter ic_filter;
switch (filter) {
case CAIRO_FILTER_FAST:
ic_filter = IcFilterFast;
break;
case CAIRO_FILTER_GOOD:
ic_filter = IcFilterGood;
break;
case CAIRO_FILTER_BEST:
ic_filter = IcFilterBest;
break;
case CAIRO_FILTER_NEAREST:
ic_filter = IcFilterNearest;
break;
case CAIRO_FILTER_BILINEAR:
ic_filter = IcFilterBilinear;
break;
default:
ic_filter = IcFilterBest;
}
IcImageSetFilter (surface->ic_image, ic_filter);
return CAIRO_STATUS_SUCCESS;
}
static cairo_status_t
_cairo_image_abstract_surface_set_repeat (void *abstract_surface, int repeat)
{
cairo_image_surface_t *surface = abstract_surface;
return _cairo_image_surface_set_repeat (surface, repeat);
}
cairo_status_t
_cairo_image_surface_set_repeat (cairo_image_surface_t *surface, int repeat)
{
IcImageSetRepeat (surface->ic_image, repeat);
return CAIRO_STATUS_SUCCESS;
}
static IcOperator
_ic_operator (cairo_operator_t operator)
{
switch (operator) {
case CAIRO_OPERATOR_CLEAR:
return IcOperatorClear;
case CAIRO_OPERATOR_SRC:
return IcOperatorSrc;
case CAIRO_OPERATOR_DST:
return IcOperatorDst;
case CAIRO_OPERATOR_OVER:
return IcOperatorOver;
case CAIRO_OPERATOR_OVER_REVERSE:
return IcOperatorOverReverse;
case CAIRO_OPERATOR_IN:
return IcOperatorIn;
case CAIRO_OPERATOR_IN_REVERSE:
return IcOperatorInReverse;
case CAIRO_OPERATOR_OUT:
return IcOperatorOut;
case CAIRO_OPERATOR_OUT_REVERSE:
return IcOperatorOutReverse;
case CAIRO_OPERATOR_ATOP:
return IcOperatorAtop;
case CAIRO_OPERATOR_ATOP_REVERSE:
return IcOperatorAtopReverse;
case CAIRO_OPERATOR_XOR:
return IcOperatorXor;
case CAIRO_OPERATOR_ADD:
return IcOperatorAdd;
case CAIRO_OPERATOR_SATURATE:
return IcOperatorSaturate;
default:
return IcOperatorOver;
}
}
static cairo_int_status_t
_cairo_image_surface_composite (cairo_operator_t operator,
cairo_surface_t *generic_src,
cairo_surface_t *generic_mask,
void *abstract_dst,
int src_x,
int src_y,
int mask_x,
int mask_y,
int dst_x,
int dst_y,
unsigned int width,
unsigned int height)
{
cairo_image_surface_t *dst = abstract_dst;
cairo_image_surface_t *src = (cairo_image_surface_t *) generic_src;
cairo_image_surface_t *mask = (cairo_image_surface_t *) generic_mask;
if (generic_src->backend != dst->base.backend ||
(generic_mask && (generic_mask->backend != dst->base.backend)))
{
return CAIRO_INT_STATUS_UNSUPPORTED;
}
IcComposite (_ic_operator (operator),
src->ic_image,
mask ? mask->ic_image : NULL,
dst->ic_image,
src_x, src_y,
mask_x, mask_y,
dst_x, dst_y,
width, height);
return CAIRO_STATUS_SUCCESS;
}
static cairo_int_status_t
_cairo_image_surface_fill_rectangles (void *abstract_surface,
cairo_operator_t operator,
const cairo_color_t *color,
cairo_rectangle_t *rects,
int num_rects)
{
cairo_image_surface_t *surface = abstract_surface;
IcColor ic_color;
ic_color.red = color->red_short;
ic_color.green = color->green_short;
ic_color.blue = color->blue_short;
ic_color.alpha = color->alpha_short;
/* XXX: The IcRectangle cast is evil... it needs to go away somehow. */
IcFillRectangles (_ic_operator(operator), surface->ic_image,
&ic_color, (IcRectangle *) rects, num_rects);
return CAIRO_STATUS_SUCCESS;
}
static cairo_int_status_t
_cairo_image_surface_composite_trapezoids (cairo_operator_t operator,
cairo_surface_t *generic_src,
void *abstract_dst,
int x_src,
int y_src,
cairo_trapezoid_t *traps,
int num_traps)
{
cairo_image_surface_t *dst = abstract_dst;
cairo_image_surface_t *src = (cairo_image_surface_t *) generic_src;
if (generic_src->backend != dst->base.backend)
return CAIRO_INT_STATUS_UNSUPPORTED;
/* XXX: The IcTrapezoid cast is evil and needs to go away somehow. */
IcCompositeTrapezoids (operator, src->ic_image, dst->ic_image,
x_src, y_src, (IcTrapezoid *) traps, num_traps);
return CAIRO_STATUS_SUCCESS;
}
static const cairo_surface_backend_t cairo_image_surface_backend = {
_cairo_image_surface_create_similar,
_cairo_image_abstract_surface_destroy,
_cairo_image_surface_pixels_per_inch,
_cairo_image_surface_get_image,
_cairo_image_surface_set_image,
_cairo_image_abstract_surface_set_matrix,
_cairo_image_surface_set_filter,
_cairo_image_abstract_surface_set_repeat,
_cairo_image_surface_composite,
_cairo_image_surface_fill_rectangles,
_cairo_image_surface_composite_trapezoids,
};

View file

@ -29,78 +29,18 @@
#include "cairoint.h"
static const XTransform CAIRO_XTRANSFORM_IDENTITY = {
{
{65536, 0, 0},
{ 0, 65536, 0},
{ 0, 0, 65536}
}
};
static IcFormat *
_create_icformat_for_format (cairo_format_t format)
{
switch (format) {
case CAIRO_FORMAT_ARGB32:
return IcFormatCreate (IcFormatNameARGB32);
break;
case CAIRO_FORMAT_RGB24:
return IcFormatCreate (IcFormatNameRGB24);
break;
case CAIRO_FORMAT_A8:
return IcFormatCreate (IcFormatNameA8);
break;
case CAIRO_FORMAT_A1:
return IcFormatCreate (IcFormatNameA1);
break;
default:
return NULL;
}
}
void
_cairo_surface_init (cairo_surface_t *surface,
int width,
int height,
cairo_format_t format,
const struct cairo_surface_backend *backend)
const cairo_surface_backend_t *backend)
{
surface->width = width;
surface->height = height;
surface->image_data = NULL;
surface->backend = backend;
surface->ref_count = 1;
_cairo_matrix_init (&surface->matrix);
surface->repeat = 0;
surface->xtransform = CAIRO_XTRANSFORM_IDENTITY;
surface->icimage = NULL;
surface->icformat = _create_icformat_for_format (format);
surface->backend = backend;
}
static int
cairo_format_bpp (cairo_format_t format)
{
switch (format) {
case CAIRO_FORMAT_A1:
return 1;
break;
case CAIRO_FORMAT_A8:
return 8;
break;
case CAIRO_FORMAT_RGB24:
case CAIRO_FORMAT_ARGB32:
default:
return 32;
break;
}
}
static const struct cairo_surface_backend cairo_icimage_surface_backend;
cairo_surface_t *
cairo_surface_create_for_image (char *data,
cairo_format_t format,
@ -108,25 +48,7 @@ cairo_surface_create_for_image (char *data,
int height,
int stride)
{
cairo_surface_t *surface;
surface = malloc (sizeof (cairo_surface_t));
if (surface == NULL)
return NULL;
_cairo_surface_init (surface, width, height, format, &cairo_icimage_surface_backend);
surface->icimage = IcImageCreateForData ((IcBits *) data,
surface->icformat,
width, height,
cairo_format_bpp (format),
stride);
if (surface->icimage == NULL) {
free (surface);
return NULL;
}
return surface;
return cairo_image_surface_create_for_data (data, format, width, height, stride);
}
slim_hidden_def(cairo_surface_create_for_image);
@ -138,6 +60,9 @@ cairo_surface_create_similar (cairo_surface_t *other,
{
cairo_color_t empty;
if (other == NULL)
return NULL;
_cairo_color_init (&empty);
_cairo_color_set_rgb (&empty, 0., 0., 0.);
_cairo_color_set_alpha (&empty, 0.);
@ -152,27 +77,21 @@ _cairo_surface_create_similar_solid (cairo_surface_t *other,
int height,
cairo_color_t *color)
{
cairo_status_t status;
cairo_surface_t *surface = NULL;
if (other->backend->create_similar)
surface = other->backend->create_similar (other, format, width, height);
if (surface == NULL) {
char *data;
int stride;
surface = other->backend->create_similar (other, format, width, height);
if (surface == NULL)
surface = cairo_image_surface_create (format, width, height);
stride = ((width * cairo_format_bpp (format)) + 7) >> 3;
data = malloc (stride * height);
if (data == NULL)
return NULL;
surface = cairo_surface_create_for_image (data, format,
width, height, stride);
/* lodge data in the surface structure to be freed with the surface */
surface->image_data = data;
status = _cairo_surface_fill_rectangle (surface,
CAIRO_OPERATOR_SRC, color,
0, 0, width, height);
if (status) {
cairo_surface_destroy (surface);
return NULL;
}
_cairo_surface_fill_rectangle (surface, CAIRO_OPERATOR_SRC, color, 0, 0, width, height);
return surface;
}
@ -195,105 +114,56 @@ cairo_surface_destroy (cairo_surface_t *surface)
if (surface->ref_count)
return;
if (surface->icformat)
IcFormatDestroy (surface->icformat);
if (surface->icimage)
IcImageDestroy (surface->icimage);
if (surface->backend->destroy)
surface->backend->destroy (surface);
if (surface->image_data)
free (surface->image_data);
surface->image_data = NULL;
free (surface);
}
slim_hidden_def(cairo_surface_destroy);
#define CAIRO_SURFACE_PIXELS_PER_INCH_DEFAULT 96.0
double
_cairo_surface_pixels_per_inch (cairo_surface_t *surface)
{
if (surface->backend->pixels_per_inch)
return surface->backend->pixels_per_inch (surface);
return CAIRO_SURFACE_PIXELS_PER_INCH_DEFAULT;
return surface->backend->pixels_per_inch (surface);
}
void
_cairo_surface_pull_image (cairo_surface_t *surface)
cairo_image_surface_t *
_cairo_surface_get_image (cairo_surface_t *surface)
{
if (surface->backend->pull_image)
surface->backend->pull_image (surface);
return surface->backend->get_image (surface);
}
void
_cairo_surface_push_image (cairo_surface_t *surface)
cairo_status_t
_cairo_surface_set_image (cairo_surface_t *surface, cairo_image_surface_t *image)
{
if (surface->backend->push_image)
surface->backend->push_image (surface);
return surface->backend->set_image (surface, image);
}
/* XXX: We may want to move to projective matrices at some point. If
nothing else, that would eliminate the two different transform data
structures we have here. */
cairo_status_t
cairo_surface_set_matrix (cairo_surface_t *surface, cairo_matrix_t *matrix)
{
cairo_status_t ret = CAIRO_STATUS_SUCCESS;
XTransform *xtransform = &surface->xtransform;
if (surface == NULL)
return CAIRO_STATUS_NULL_POINTER;
xtransform->matrix[0][0] = XDoubleToFixed (matrix->m[0][0]);
xtransform->matrix[0][1] = XDoubleToFixed (matrix->m[1][0]);
xtransform->matrix[0][2] = XDoubleToFixed (matrix->m[2][0]);
cairo_matrix_copy (&surface->matrix, matrix);
xtransform->matrix[1][0] = XDoubleToFixed (matrix->m[0][1]);
xtransform->matrix[1][1] = XDoubleToFixed (matrix->m[1][1]);
xtransform->matrix[1][2] = XDoubleToFixed (matrix->m[2][1]);
xtransform->matrix[2][0] = 0;
xtransform->matrix[2][1] = 0;
xtransform->matrix[2][2] = XDoubleToFixed (1);
if (surface->backend->set_matrix)
ret = surface->backend->set_matrix (surface);
/* XXX: This cast should only occur with a #define hint from libic that it is OK */
if (surface->icimage) {
IcImageSetTransform (surface->icimage, (IcTransform *) xtransform);
}
return ret;
return surface->backend->set_matrix (surface, matrix);
}
slim_hidden_def(cairo_surface_set_matrix);
cairo_status_t
cairo_surface_get_matrix (cairo_surface_t *surface, cairo_matrix_t *matrix)
{
XTransform *xtransform = &surface->xtransform;
if (surface == NULL)
return CAIRO_STATUS_NULL_POINTER;
matrix->m[0][0] = _cairo_fixed_to_double (xtransform->matrix[0][0]);
matrix->m[1][0] = _cairo_fixed_to_double (xtransform->matrix[0][1]);
matrix->m[2][0] = _cairo_fixed_to_double (xtransform->matrix[0][2]);
matrix->m[0][1] = _cairo_fixed_to_double (xtransform->matrix[1][0]);
matrix->m[1][1] = _cairo_fixed_to_double (xtransform->matrix[1][1]);
matrix->m[2][1] = _cairo_fixed_to_double (xtransform->matrix[1][2]);
return CAIRO_STATUS_SUCCESS;
return cairo_matrix_copy (matrix, &surface->matrix);
}
slim_hidden_def(cairo_surface_get_matrix);
cairo_status_t
cairo_surface_set_filter (cairo_surface_t *surface, cairo_filter_t filter)
{
if (surface->icimage) {
IcImageSetFilter (surface->icimage, filter);
}
if (!surface->backend->set_filter)
return CAIRO_STATUS_SUCCESS;
if (surface == NULL)
return CAIRO_STATUS_NULL_POINTER;
return surface->backend->set_filter (surface, filter);
}
@ -316,20 +186,16 @@ cairo_surface_clip_restore (cairo_surface_t *surface);
cairo_status_t
cairo_surface_set_repeat (cairo_surface_t *surface, int repeat)
{
if (surface == NULL)
return CAIRO_STATUS_NULL_POINTER;
surface->repeat = repeat;
if (surface->icimage) {
IcImageSetRepeat (surface->icimage, repeat);
}
if (!surface->backend->set_repeat)
return CAIRO_STATUS_SUCCESS;
return surface->backend->set_repeat (surface, repeat);
}
slim_hidden_def(cairo_surface_set_repeat);
void
cairo_int_status_t
_cairo_surface_composite (cairo_operator_t operator,
cairo_surface_t *src,
cairo_surface_t *mask,
@ -344,36 +210,42 @@ _cairo_surface_composite (cairo_operator_t operator,
unsigned int height)
{
cairo_int_status_t status;
cairo_image_surface_t *src_image, *mask_image, *dst_image;
if (dst->backend->composite) {
status = dst->backend->composite (operator,
src, mask, dst,
src_x, src_y,
mask_x, mask_y,
dst_x, dst_y,
width, height);
if (status == CAIRO_STATUS_SUCCESS)
return;
}
status = dst->backend->composite (operator,
src, mask, dst,
src_x, src_y,
mask_x, mask_y,
dst_x, dst_y,
width, height);
if (status != CAIRO_INT_STATUS_UNSUPPORTED)
return status;
_cairo_surface_pull_image (src);
src_image = _cairo_surface_get_image (src);
if (mask)
_cairo_surface_pull_image (mask);
_cairo_surface_pull_image (dst);
mask_image = _cairo_surface_get_image (mask);
dst_image = _cairo_surface_get_image (dst);
IcComposite (operator,
src->icimage,
mask ? mask->icimage : NULL,
dst->icimage,
src_x, src_y,
mask_x, mask_y,
dst_x, dst_y,
width, height);
dst_image->base.backend->composite (operator,
&src_image->base,
mask ? &mask_image->base : NULL,
dst_image,
src_x, src_y,
mask_x, mask_y,
dst_x, dst_y,
width, height);
_cairo_surface_push_image (dst);
status = _cairo_surface_set_image (dst, dst_image);
cairo_surface_destroy (&src_image->base);
if (mask)
cairo_surface_destroy (&mask_image->base);
cairo_surface_destroy (&dst_image->base);
return status;
}
void
cairo_status_t
_cairo_surface_fill_rectangle (cairo_surface_t *surface,
cairo_operator_t operator,
cairo_color_t *color,
@ -389,10 +261,10 @@ _cairo_surface_fill_rectangle (cairo_surface_t *surface,
rect.width = width;
rect.height = height;
_cairo_surface_fill_rectangles (surface, operator, color, &rect, 1);
return _cairo_surface_fill_rectangles (surface, operator, color, &rect, 1);
}
void
cairo_status_t
_cairo_surface_fill_rectangles (cairo_surface_t *surface,
cairo_operator_t operator,
const cairo_color_t *color,
@ -400,61 +272,65 @@ _cairo_surface_fill_rectangles (cairo_surface_t *surface,
int num_rects)
{
cairo_int_status_t status;
IcColor ic_color;
cairo_image_surface_t *surface_image;
if (num_rects == 0)
return;
return CAIRO_STATUS_SUCCESS;
if (surface->backend->fill_rectangles) {
status = surface->backend->fill_rectangles (surface,
operator,
color,
rects, num_rects);
if (status == CAIRO_STATUS_SUCCESS)
return;
}
status = surface->backend->fill_rectangles (surface,
operator,
color,
rects, num_rects);
if (status != CAIRO_INT_STATUS_UNSUPPORTED)
return status;
ic_color.red = color->red_short;
ic_color.green = color->green_short;
ic_color.blue = color->blue_short;
ic_color.alpha = color->alpha_short;
surface_image = _cairo_surface_get_image (surface);
_cairo_surface_pull_image (surface);
surface_image->base.backend->fill_rectangles (surface_image,
operator,
color,
rects, num_rects);
/* XXX: The IcRectangle cast is evil... it needs to go away somehow. */
IcFillRectangles (operator, surface->icimage,
&ic_color, (IcRectangle *) rects, num_rects);
status = _cairo_surface_set_image (surface, surface_image);
_cairo_surface_push_image (surface);
cairo_surface_destroy (&surface_image->base);
return status;
}
void
cairo_status_t
_cairo_surface_composite_trapezoids (cairo_operator_t operator,
cairo_surface_t *src,
cairo_surface_t *dst,
int xSrc,
int ySrc,
int x_src,
int y_src,
cairo_trapezoid_t *traps,
int num_traps)
{
cairo_int_status_t status;
cairo_image_surface_t *src_image, *dst_image;
if (dst->backend->composite_trapezoids) {
status = dst->backend->composite_trapezoids (operator,
src, dst,
xSrc, ySrc,
traps, num_traps);
if (status == CAIRO_STATUS_SUCCESS)
return;
}
status = dst->backend->composite_trapezoids (operator,
src, dst,
x_src, y_src,
traps, num_traps);
if (status != CAIRO_INT_STATUS_UNSUPPORTED)
return status;
_cairo_surface_pull_image (src);
_cairo_surface_pull_image (dst);
src_image = _cairo_surface_get_image (src);
dst_image = _cairo_surface_get_image (dst);
/* XXX: The IcTrapezoid cast is evil and needs to go away somehow. */
IcCompositeTrapezoids (operator, src->icimage, dst->icimage,
xSrc, ySrc, (IcTrapezoid *) traps, num_traps);
dst_image->base.backend->composite_trapezoids (operator,
&src_image->base,
dst_image,
x_src, y_src,
traps, num_traps);
_cairo_surface_push_image (dst);
status = _cairo_surface_set_image (dst, dst_image);
cairo_surface_destroy (&src_image->base);
cairo_surface_destroy (&dst_image->base);
return status;
}

View file

@ -27,7 +27,6 @@
#include "cairoint.h"
#include "cairo-xlib.h"
#include <X11/Xlibint.h>
void
cairo_set_target_drawable (cairo_t *cr,
@ -49,6 +48,8 @@ cairo_set_target_drawable (cairo_t *cr,
}
cairo_set_target_surface (cr, surface);
/* cairo_set_target_surface takes a reference, so we must destroy ours */
cairo_surface_destroy (surface);
}
@ -60,12 +61,15 @@ typedef struct cairo_xlib_surface {
Drawable drawable;
int owns_pixmap;
Visual *visual;
cairo_format_t format;
int render_major;
int render_minor;
int width;
int height;
Picture picture;
XImage *ximage;
} cairo_xlib_surface_t;
#define CAIRO_SURFACE_RENDER_AT_LEAST(surface, major, minor) \
@ -124,18 +128,23 @@ _cairo_xlib_surface_create_similar (void *abstract_src,
if (!dpy
|| (!CAIRO_SURFACE_RENDER_HAS_COMPOSITE (src)
&& format == CAIRO_FORMAT_ARGB32))
{
return NULL;
}
scr = DefaultScreen (dpy);
pix = XCreatePixmap (dpy, DefaultRootWindow (dpy),
width, height,
_CAIRO_FORMAT_DEPTH (format));
surface = (cairo_xlib_surface_t *)
cairo_xlib_surface_create (dpy, pix, NULL, format, DefaultColormap (dpy, scr));
surface->owns_pixmap = 1;
surface->width = width;
surface->height = height;
return &surface->base;
}
@ -149,15 +158,12 @@ _cairo_xlib_surface_destroy (void *abstract_surface)
if (surface->owns_pixmap)
XFreePixmap (surface->dpy, surface->drawable);
if (surface->ximage) {
surface->ximage->data = NULL;
XDestroyImage(surface->ximage);
}
if (surface->gc)
XFreeGC (surface->dpy, surface->gc);
surface->dpy = 0;
free (surface);
}
static double
@ -167,45 +173,63 @@ _cairo_xlib_surface_pixels_per_inch (void *abstract_surface)
return 96.0;
}
static void
_cairo_xlib_surface_pull_image (void *abstract_surface)
static cairo_image_surface_t *
_cairo_xlib_surface_get_image (void *abstract_surface)
{
cairo_xlib_surface_t *surface = abstract_surface;
cairo_image_surface_t *image;
XImage *ximage;
Window root_ignore;
int x_ignore, y_ignore, bwidth_ignore, depth_ignore;
if (surface == NULL)
return;
XGetGeometry (surface->dpy,
surface->drawable,
&root_ignore, &x_ignore, &y_ignore,
&surface->width, &surface->height,
&bwidth_ignore, &depth_ignore);
if (surface->base.icimage) {
IcImageDestroy (surface->base.icimage);
surface->base.icimage = NULL;
ximage = XGetImage (surface->dpy,
surface->drawable,
0, 0,
surface->width, surface->height,
AllPlanes, ZPixmap);
if (surface->visual) {
cairo_format_masks_t masks;
/* XXX: Add support here for pictures with external alpha? */
masks.bpp = ximage->bits_per_pixel;
masks.alpha_mask = 0;
masks.red_mask = surface->visual->red_mask;
masks.green_mask = surface->visual->green_mask;
masks.blue_mask = surface->visual->blue_mask;
image = _cairo_image_surface_create_with_masks (ximage->data,
&masks,
ximage->width,
ximage->height,
ximage->bytes_per_line);
} else {
image = (cairo_image_surface_t *)
cairo_image_surface_create_for_data (ximage->data,
surface->format,
ximage->width,
ximage->height,
ximage->bytes_per_line);
}
XGetGeometry(surface->dpy,
surface->drawable,
&root_ignore, &x_ignore, &y_ignore,
&surface->base.width, &surface->base.height,
&bwidth_ignore, &depth_ignore);
surface->ximage = XGetImage (surface->dpy,
surface->drawable,
0, 0,
surface->base.width, surface->base.height,
AllPlanes, ZPixmap);
surface->base.icimage = IcImageCreateForData ((IcBits *)(surface->ximage->data),
surface->base.icformat,
surface->ximage->width,
surface->ximage->height,
surface->ximage->bits_per_pixel,
surface->ximage->bytes_per_line);
/* Let the surface take ownership of the data */
/* XXX: Can probably come up with a cleaner API here. */
_cairo_image_surface_assume_ownership_of_data (image);
ximage->data = NULL;
XDestroyImage (ximage);
IcImageSetRepeat (surface->base.icimage, surface->base.repeat);
/* XXX: Evil cast here... */
IcImageSetTransform (surface->base.icimage, (IcTransform *) &(surface->base.xtransform));
/* XXX: Add support here for pictures with external alpha. */
_cairo_image_surface_set_repeat (image, surface->base.repeat);
_cairo_image_surface_set_matrix (image, &(surface->base.matrix));
return image;
}
static void
@ -217,40 +241,72 @@ _cairo_xlib_surface_ensure_gc (cairo_xlib_surface_t *surface)
surface->gc = XCreateGC (surface->dpy, surface->drawable, 0, NULL);
}
static void
_cairo_xlib_surface_push_image (void *abstract_surface)
static cairo_status_t
_cairo_xlib_surface_set_image (void *abstract_surface,
cairo_image_surface_t *image)
{
cairo_xlib_surface_t *surface = abstract_surface;
if (surface == NULL)
return;
XImage *ximage;
unsigned bitmap_pad;
if (surface->ximage == NULL)
return;
if (image->depth > 16)
bitmap_pad = 32;
else if (image->depth > 8)
bitmap_pad = 16;
else
bitmap_pad = 8;
ximage = XCreateImage (surface->dpy,
DefaultVisual(surface->dpy, DefaultScreen(surface->dpy)),
image->depth == 32 ? 24 : image->depth,
ZPixmap,
0,
image->data,
image->width,
image->height,
bitmap_pad,
image->stride);
if (ximage == NULL)
return CAIRO_STATUS_NO_MEMORY;
_cairo_xlib_surface_ensure_gc (surface);
XPutImage (surface->dpy,
surface->drawable,
surface->gc,
surface->ximage,
0, 0,
0, 0,
surface->base.width,
surface->base.height);
XPutImage(surface->dpy, surface->drawable, surface->gc,
ximage, 0, 0, 0, 0,
surface->width,
surface->height);
XDestroyImage(surface->ximage);
surface->ximage = NULL;
/* Foolish XDestroyImage thinks it can free my data, but I won't
stand for it. */
ximage->data = NULL;
XDestroyImage (ximage);
return CAIRO_STATUS_SUCCESS;
}
static cairo_status_t
_cairo_xlib_surface_set_matrix (void *abstract_surface)
_cairo_xlib_surface_set_matrix (void *abstract_surface, cairo_matrix_t *matrix)
{
cairo_xlib_surface_t *surface = abstract_surface;
XTransform xtransform;
if (!surface->picture)
return CAIRO_STATUS_SUCCESS;
xtransform.matrix[0][0] = _cairo_fixed_from_double (matrix->m[0][0]);
xtransform.matrix[0][1] = _cairo_fixed_from_double (matrix->m[1][0]);
xtransform.matrix[0][2] = _cairo_fixed_from_double (matrix->m[2][0]);
xtransform.matrix[1][0] = _cairo_fixed_from_double (matrix->m[0][1]);
xtransform.matrix[1][1] = _cairo_fixed_from_double (matrix->m[1][1]);
xtransform.matrix[1][2] = _cairo_fixed_from_double (matrix->m[2][1]);
xtransform.matrix[2][0] = 0;
xtransform.matrix[2][1] = 0;
xtransform.matrix[2][2] = _cairo_fixed_from_double (1);
if (CAIRO_SURFACE_RENDER_HAS_PICTURE_TRANSFORM (surface))
{
XRenderSetPictureTransform (surface->dpy, surface->picture, &surface->base.xtransform);
XRenderSetPictureTransform (surface->dpy, surface->picture, &xtransform);
} else {
/* XXX: Need support here if using an old RENDER without support
for SetPictureTransform */
@ -259,37 +315,36 @@ _cairo_xlib_surface_set_matrix (void *abstract_surface)
return CAIRO_STATUS_SUCCESS;
}
/* XXX: The Render specification has capitalized versions of these
strings. However, the current implementation is case-sensitive and
expects lowercase versions. */
static char *
_render_filter_name (cairo_filter_t filter)
{
switch (filter) {
case CAIRO_FILTER_FAST:
return "fast";
case CAIRO_FILTER_GOOD:
return "good";
case CAIRO_FILTER_BEST:
return "best";
case CAIRO_FILTER_NEAREST:
return "nearest";
case CAIRO_FILTER_BILINEAR:
return "bilinear";
default:
return "best";
}
}
static cairo_status_t
_cairo_xlib_surface_set_filter (void *abstract_surface, cairo_filter_t filter)
{
cairo_xlib_surface_t *surface = abstract_surface;
char *render_filter;
if (!surface->picture)
return CAIRO_STATUS_SUCCESS;
/* XXX: The Render specification has capitalized versions of these
strings. However, the current implementation is
case-sensitive and expects lowercase versions.
*/
switch (filter) {
case CAIRO_FILTER_FAST:
render_filter = "fast";
case CAIRO_FILTER_GOOD:
render_filter = "good";
case CAIRO_FILTER_BEST:
render_filter = "best";
case CAIRO_FILTER_NEAREST:
render_filter = "nearest";
case CAIRO_FILTER_BILINEAR:
render_filter = "bilinear";
default:
render_filter = "best";
}
XRenderSetPictureFilter (surface->dpy, surface->picture,
_render_filter_name (filter), NULL, 0);
render_filter, NULL, 0);
return CAIRO_STATUS_SUCCESS;
}
@ -312,73 +367,68 @@ _cairo_xlib_surface_set_repeat (void *abstract_surface, int repeat)
return CAIRO_STATUS_SUCCESS;
}
static cairo_status_t
_cairo_xlib_surface_put_image (cairo_xlib_surface_t *surface,
char *data,
int width,
int height,
int stride,
int depth)
{
XImage *image;
unsigned bitmap_pad;
if (!surface->picture)
return CAIRO_STATUS_SUCCESS;
if (depth > 16)
bitmap_pad = 32;
else if (depth > 8)
bitmap_pad = 16;
else
bitmap_pad = 8;
image = XCreateImage(surface->dpy,
DefaultVisual(surface->dpy, DefaultScreen(surface->dpy)),
depth, ZPixmap, 0,
data, width, height,
bitmap_pad,
stride);
if (image == NULL)
return CAIRO_STATUS_NO_MEMORY;
_cairo_xlib_surface_ensure_gc (surface);
XPutImage(surface->dpy, surface->drawable, surface->gc,
image, 0, 0, 0, 0, width, height);
/* Foolish XDestroyImage thinks it can free my data, but I won't
stand for it. */
image->data = NULL;
XDestroyImage(image);
return CAIRO_STATUS_SUCCESS;
}
static cairo_xlib_surface_t *
_cairo_xlib_surface_clone_from (cairo_surface_t *src, cairo_xlib_surface_t *tmpl,
cairo_format_t fmt, int depth)
_cairo_xlib_surface_clone_similar (cairo_surface_t *src,
cairo_xlib_surface_t *template,
cairo_format_t format,
int depth)
{
cairo_matrix_t matrix;
cairo_xlib_surface_t *src_on_server;
cairo_xlib_surface_t *clone;
cairo_image_surface_t *src_image;
_cairo_surface_pull_image (src);
src_image = _cairo_surface_get_image (src);
src_on_server = (cairo_xlib_surface_t *)
_cairo_xlib_surface_create_similar (tmpl, fmt,
IcImageGetWidth (src->icimage),
IcImageGetHeight (src->icimage));
if (src_on_server == NULL)
clone = (cairo_xlib_surface_t *)
_cairo_xlib_surface_create_similar (template, format,
src_image->width,
src_image->height);
if (clone == NULL)
return NULL;
cairo_surface_get_matrix (src, &matrix);
cairo_surface_set_matrix (&src_on_server->base, &matrix);
_cairo_xlib_surface_set_image (clone, src_image);
_cairo_xlib_surface_put_image (src_on_server,
(char *) IcImageGetData (src->icimage),
IcImageGetWidth (src->icimage),
IcImageGetHeight (src->icimage),
IcImageGetStride (src->icimage), depth);
return src_on_server;
_cairo_xlib_surface_set_matrix (clone, &(src_image->base.matrix));
cairo_surface_destroy (&src_image->base);
return clone;
}
static int
_render_operator (cairo_operator_t operator)
{
switch (operator) {
case CAIRO_OPERATOR_CLEAR:
return PictOpClear;
case CAIRO_OPERATOR_SRC:
return PictOpSrc;
case CAIRO_OPERATOR_DST:
return PictOpDst;
case CAIRO_OPERATOR_OVER:
return PictOpOver;
case CAIRO_OPERATOR_OVER_REVERSE:
return PictOpOverReverse;
case CAIRO_OPERATOR_IN:
return PictOpIn;
case CAIRO_OPERATOR_IN_REVERSE:
return PictOpInReverse;
case CAIRO_OPERATOR_OUT:
return PictOpOut;
case CAIRO_OPERATOR_OUT_REVERSE:
return PictOpOutReverse;
case CAIRO_OPERATOR_ATOP:
return PictOpAtop;
case CAIRO_OPERATOR_ATOP_REVERSE:
return PictOpAtopReverse;
case CAIRO_OPERATOR_XOR:
return PictOpXor;
case CAIRO_OPERATOR_ADD:
return PictOpAdd;
case CAIRO_OPERATOR_SATURATE:
return PictOpSaturate;
default:
return PictOpOver;
}
}
static cairo_int_status_t
@ -406,19 +456,22 @@ _cairo_xlib_surface_composite (cairo_operator_t operator,
return CAIRO_INT_STATUS_UNSUPPORTED;
if (generic_src->backend != dst->base.backend || src->dpy != dst->dpy) {
src_clone = _cairo_xlib_surface_clone_from (generic_src, dst, CAIRO_FORMAT_ARGB32, 32);
src_clone = _cairo_xlib_surface_clone_similar (generic_src, dst,
CAIRO_FORMAT_ARGB32, 32);
if (!src_clone)
return CAIRO_INT_STATUS_UNSUPPORTED;
src = src_clone;
}
if (generic_mask && (generic_mask->backend != dst->base.backend || mask->dpy != dst->dpy)) {
mask_clone = _cairo_xlib_surface_clone_from (generic_mask, dst, CAIRO_FORMAT_A8, 8);
mask_clone = _cairo_xlib_surface_clone_similar (generic_mask, dst,
CAIRO_FORMAT_A8, 8);
if (!mask_clone)
return CAIRO_INT_STATUS_UNSUPPORTED;
mask = mask_clone;
}
XRenderComposite (dst->dpy, operator,
XRenderComposite (dst->dpy,
_render_operator (operator),
src->picture,
mask ? mask->picture : 0,
dst->picture,
@ -456,7 +509,9 @@ _cairo_xlib_surface_fill_rectangles (void *abstract_surface,
render_color.alpha = color->alpha_short;
/* XXX: This XRectangle cast is evil... it needs to go away somehow. */
XRenderFillRectangles (surface->dpy, operator, surface->picture,
XRenderFillRectangles (surface->dpy,
_render_operator (operator),
surface->picture,
&render_color, (XRectangle *) rects, num_rects);
return CAIRO_STATUS_SUCCESS;
@ -479,14 +534,17 @@ _cairo_xlib_surface_composite_trapezoids (cairo_operator_t operator,
return CAIRO_INT_STATUS_UNSUPPORTED;
if (generic_src->backend != dst->base.backend || src->dpy != dst->dpy) {
src_clone = _cairo_xlib_surface_clone_from (generic_src, dst, CAIRO_FORMAT_ARGB32, 32);
src_clone = _cairo_xlib_surface_clone_similar (generic_src, dst,
CAIRO_FORMAT_ARGB32, 32);
if (!src_clone)
return CAIRO_INT_STATUS_UNSUPPORTED;
src = src_clone;
}
/* XXX: The XTrapezoid cast is evil and needs to go away somehow. */
XRenderCompositeTrapezoids (dst->dpy, operator, src->picture, dst->picture,
XRenderCompositeTrapezoids (dst->dpy,
_render_operator (operator),
src->picture, dst->picture,
XRenderFindStandardFormat (dst->dpy, PictStandardA8),
xSrc, ySrc, (XTrapezoid *) traps, num_traps);
@ -504,8 +562,8 @@ static const struct cairo_surface_backend cairo_xlib_surface_backend = {
_cairo_xlib_surface_create_similar,
_cairo_xlib_surface_destroy,
_cairo_xlib_surface_pixels_per_inch,
_cairo_xlib_surface_pull_image,
_cairo_xlib_surface_push_image,
_cairo_xlib_surface_get_image,
_cairo_xlib_surface_set_image,
_cairo_xlib_surface_set_matrix,
_cairo_xlib_surface_set_filter,
_cairo_xlib_surface_set_repeat,
@ -522,24 +580,16 @@ cairo_xlib_surface_create (Display *dpy,
Colormap colormap)
{
cairo_xlib_surface_t *surface;
int render_standard;
surface = malloc (sizeof (cairo_xlib_surface_t));
if (surface == NULL)
return NULL;
/* XXX: How to get the proper width/height? Force a roundtrip? And
how can we track the width/height properly? Shall we give up on
supporting Windows and only allow drawing to pixmaps? */
_cairo_surface_init (&surface->base, 0, 0, format, &cairo_xlib_surface_backend);
_cairo_surface_init (&surface->base, &cairo_xlib_surface_backend);
if (visual) {
if (surface->base.icformat)
IcFormatDestroy (surface->base.icformat);
surface->base.icformat = IcFormatCreateMasks (32, 0,
visual->red_mask,
visual->green_mask,
visual->blue_mask);
}
surface->visual = visual;
surface->format = format;
surface->dpy = dpy;
@ -553,18 +603,32 @@ cairo_xlib_surface_create (Display *dpy,
surface->render_minor = -1;
}
switch (format) {
case CAIRO_FORMAT_A1:
render_standard = PictStandardA1;
break;
case CAIRO_FORMAT_A8:
render_standard = PictStandardA8;
break;
case CAIRO_FORMAT_RGB24:
render_standard = PictStandardRGB24;
break;
case CAIRO_FORMAT_ARGB32:
default:
render_standard = PictStandardARGB32;
break;
}
/* XXX: I'm currently ignoring the colormap. Is that bad? */
if (CAIRO_SURFACE_RENDER_HAS_CREATE_PICTURE (surface))
surface->picture = XRenderCreatePicture (dpy, drawable,
visual ?
XRenderFindVisualFormat (dpy, visual) :
XRenderFindStandardFormat (dpy, format),
XRenderFindStandardFormat (dpy, render_standard),
0, NULL);
else
surface->picture = 0;
surface->ximage = NULL;
return (cairo_surface_t *) surface;
}
DEPRECATE (cairo_surface_create_for_drawable, cairo_xlib_surface_create);

View file

@ -28,6 +28,8 @@
#ifndef _CAIRO_XLIB_H_
#define _CAIRO_XLIB_H_
#include <X11/extensions/Xrender.h>
#include "cairo.h"
#ifdef _CAIROINT_H_
#include <slim_export.h>

View file

@ -185,8 +185,8 @@ cairo_set_target_image (cairo_t *cr,
return;
surface = cairo_surface_create_for_image (data,
format,
width, height, stride);
format,
width, height, stride);
if (surface == NULL) {
cr->status = CAIRO_STATUS_NO_MEMORY;
return;
@ -840,6 +840,8 @@ cairo_status_string (cairo_t *cr)
return "invalid matrix (not invertible)";
case CAIRO_STATUS_NO_TARGET_SURFACE:
return "no target surface has been set";
case CAIRO_STATUS_NULL_POINTER:
return "NULL pointer";
}
return "<unknown error status>";

View file

@ -28,8 +28,6 @@
#ifndef _CAIRO_H_
#define _CAIRO_H_
#include <X11/extensions/Xrender.h>
#include <fontconfig/fontconfig.h>
#include <ic.h>
#ifdef _CAIROINT_H_
@ -78,10 +76,10 @@ extern void __external_linkage
cairo_set_target_surface (cairo_t *cr, cairo_surface_t *surface);
typedef enum cairo_format {
CAIRO_FORMAT_ARGB32 = PictStandardARGB32,
CAIRO_FORMAT_RGB24 = PictStandardRGB24,
CAIRO_FORMAT_A8 = PictStandardA8,
CAIRO_FORMAT_A1 = PictStandardA1
CAIRO_FORMAT_ARGB32,
CAIRO_FORMAT_RGB24,
CAIRO_FORMAT_A8,
CAIRO_FORMAT_A1
} cairo_format_t;
extern void __external_linkage
@ -93,46 +91,20 @@ cairo_set_target_image (cairo_t *cr,
int stride);
typedef enum cairo_operator {
CAIRO_OPERATOR_CLEAR = PictOpClear,
CAIRO_OPERATOR_SRC = PictOpSrc,
CAIRO_OPERATOR_DST = PictOpDst,
CAIRO_OPERATOR_OVER = PictOpOver,
CAIRO_OPERATOR_OVER_REVERSE = PictOpOverReverse,
CAIRO_OPERATOR_IN = PictOpIn,
CAIRO_OPERATOR_IN_REVERSE = PictOpInReverse,
CAIRO_OPERATOR_OUT = PictOpOut,
CAIRO_OPERATOR_OUT_REVERSE = PictOpOutReverse,
CAIRO_OPERATOR_ATOP = PictOpAtop,
CAIRO_OPERATOR_ATOP_REVERSE = PictOpAtopReverse,
CAIRO_OPERATOR_XOR = PictOpXor,
CAIRO_OPERATOR_ADD = PictOpAdd,
CAIRO_OPERATOR_SATURATE = PictOpSaturate,
CAIRO_OPERATOR_DISJOINT_CLEAR = PictOpDisjointClear,
CAIRO_OPERATOR_DISJOINT_SRC = PictOpDisjointSrc,
CAIRO_OPERATOR_DISJOINT_DST = PictOpDisjointDst,
CAIRO_OPERATOR_DISJOINT_OVER = PictOpDisjointOver,
CAIRO_OPERATOR_DISJOINT_OVER_REVERSE = PictOpDisjointOverReverse,
CAIRO_OPERATOR_DISJOINT_IN = PictOpDisjointIn,
CAIRO_OPERATOR_DISJOINT_IN_REVERSE = PictOpDisjointInReverse,
CAIRO_OPERATOR_DISJOINT_OUT = PictOpDisjointOut,
CAIRO_OPERATOR_DISJOINT_OUT_REVERSE = PictOpDisjointOutReverse,
CAIRO_OPERATOR_DISJOINT_ATOP = PictOpDisjointAtop,
CAIRO_OPERATOR_DISJOINT_ATOP_REVERSE = PictOpDisjointAtopReverse,
CAIRO_OPERATOR_DISJOINT_XOR = PictOpDisjointXor,
CAIRO_OPERATOR_CONJOINT_CLEAR = PictOpConjointClear,
CAIRO_OPERATOR_CONJOINT_SRC = PictOpConjointSrc,
CAIRO_OPERATOR_CONJOINT_DST = PictOpConjointDst,
CAIRO_OPERATOR_CONJOINT_OVER = PictOpConjointOver,
CAIRO_OPERATOR_CONJOINT_OVER_REVERSE = PictOpConjointOverReverse,
CAIRO_OPERATOR_CONJOINT_IN = PictOpConjointIn,
CAIRO_OPERATOR_CONJOINT_IN_REVERSE = PictOpConjointInReverse,
CAIRO_OPERATOR_CONJOINT_OUT = PictOpConjointOut,
CAIRO_OPERATOR_CONJOINT_OUT_REVERSE = PictOpConjointOutReverse,
CAIRO_OPERATOR_CONJOINT_ATOP = PictOpConjointAtop,
CAIRO_OPERATOR_CONJOINT_ATOP_REVERSE = PictOpConjointAtopReverse,
CAIRO_OPERATOR_CONJOINT_XOR = PictOpConjointXor
CAIRO_OPERATOR_CLEAR,
CAIRO_OPERATOR_SRC,
CAIRO_OPERATOR_DST,
CAIRO_OPERATOR_OVER,
CAIRO_OPERATOR_OVER_REVERSE,
CAIRO_OPERATOR_IN,
CAIRO_OPERATOR_IN_REVERSE,
CAIRO_OPERATOR_OUT,
CAIRO_OPERATOR_OUT_REVERSE,
CAIRO_OPERATOR_ATOP,
CAIRO_OPERATOR_ATOP_REVERSE,
CAIRO_OPERATOR_XOR,
CAIRO_OPERATOR_ADD,
CAIRO_OPERATOR_SATURATE,
} cairo_operator_t;
extern void __external_linkage
@ -430,6 +402,7 @@ cairo_font_current_transform (cairo_font_t *font,
/* Fontconfig/Freetype platform-specific font interface */
#include <fontconfig/fontconfig.h>
#include <freetype/freetype.h>
extern cairo_font_t * __external_linkage
@ -514,7 +487,8 @@ typedef enum cairo_status {
CAIRO_STATUS_INVALID_POP_GROUP,
CAIRO_STATUS_NO_CURRENT_POINT,
CAIRO_STATUS_INVALID_MATRIX,
CAIRO_STATUS_NO_TARGET_SURFACE
CAIRO_STATUS_NO_TARGET_SURFACE,
CAIRO_STATUS_NULL_POINTER
} cairo_status_t;
extern cairo_status_t __external_linkage
@ -566,16 +540,30 @@ extern cairo_status_t __external_linkage
cairo_surface_get_matrix (cairo_surface_t *surface, cairo_matrix_t *matrix);
typedef enum cairo_filter {
CAIRO_FILTER_FAST = IcFilterFast,
CAIRO_FILTER_GOOD = IcFilterGood,
CAIRO_FILTER_BEST = IcFilterBest,
CAIRO_FILTER_NEAREST = IcFilterNearest,
CAIRO_FILTER_BILINEAR = IcFilterBilinear
CAIRO_FILTER_FAST,
CAIRO_FILTER_GOOD,
CAIRO_FILTER_BEST,
CAIRO_FILTER_NEAREST,
CAIRO_FILTER_BILINEAR,
} cairo_filter_t;
extern cairo_status_t __external_linkage
cairo_surface_set_filter (cairo_surface_t *surface, cairo_filter_t filter);
/* Image-surface functions */
cairo_surface_t *
cairo_image_surface_create (cairo_format_t format,
int width,
int height);
cairo_surface_t *
cairo_image_surface_create_for_data (char *data,
cairo_format_t format,
int width,
int height,
int stride);
/* Matrix functions */
extern cairo_matrix_t * __external_linkage

View file

@ -427,6 +427,7 @@ _cairo_ft_font_show_glyphs (cairo_font_t *font,
const cairo_glyph_t *glyphs,
int num_glyphs)
{
cairo_status_t status;
int i;
cairo_ft_font_t *ft = NULL;
FT_GlyphSlot glyphslot;
@ -447,68 +448,72 @@ _cairo_ft_font_show_glyphs (cairo_font_t *font,
for (i = 0; i < num_glyphs; i++)
{
unsigned char *bitmap;
FT_Load_Glyph (ft->face, glyphs[i].index, FT_LOAD_DEFAULT);
FT_Render_Glyph (glyphslot, FT_RENDER_MODE_NORMAL);
width = glyphslot->bitmap.width;
height = glyphslot->bitmap.rows;
stride = glyphslot->bitmap.pitch;
bitmap = glyphslot->bitmap.buffer;
x = x0 + glyphs[i].x;
y = y0 + glyphs[i].y;
/* X gets upset with zero-sized images (such as whitespace) */
if (width * height != 0)
{
unsigned char *bitmap = glyphslot->bitmap.buffer;
if (width * height == 0)
continue;
/*
* XXX
* reformat to match libic alignment requirements.
* This should be done before rendering the glyph,
* but that requires using FT_Outline_Get_Bitmap
* function
*/
if (stride & 3)
/*
* XXX
* reformat to match libic alignment requirements.
* This should be done before rendering the glyph,
* but that requires using FT_Outline_Get_Bitmap
* function
*/
if (stride & 3)
{
int nstride = (stride + 3) & ~3;
unsigned char *g, *b;
int h;
bitmap = malloc (nstride * height);
if (!bitmap)
return CAIRO_STATUS_NO_MEMORY;
g = glyphslot->bitmap.buffer;
b = bitmap;
h = height;
while (h--)
{
int nstride = (stride + 3) & ~3;
unsigned char *g, *b;
int h;
bitmap = malloc (nstride * height);
if (!bitmap)
return CAIRO_STATUS_NO_MEMORY;
g = glyphslot->bitmap.buffer;
b = bitmap;
h = height;
while (h--)
{
memcpy (b, g, width);
b += nstride;
g += stride;
}
stride = nstride;
memcpy (b, g, width);
b += nstride;
g += stride;
}
mask = cairo_surface_create_for_image (bitmap,
CAIRO_FORMAT_A8,
width, height, stride);
if (mask == NULL)
{
if (bitmap != glyphslot->bitmap.buffer)
free (bitmap);
return CAIRO_STATUS_NO_MEMORY;
}
_cairo_surface_composite (operator, source, mask, surface,
0, 0, 0, 0,
x + glyphslot->bitmap_left,
y - glyphslot->bitmap_top,
(double)width, (double)height);
cairo_surface_destroy (mask);
stride = nstride;
}
mask = cairo_surface_create_for_image (bitmap,
CAIRO_FORMAT_A8,
width, height, stride);
if (mask == NULL)
{
if (bitmap != glyphslot->bitmap.buffer)
free (bitmap);
}
return CAIRO_STATUS_NO_MEMORY;
}
status = _cairo_surface_composite (operator, source, mask, surface,
0, 0, 0, 0,
x + glyphslot->bitmap_left,
y - glyphslot->bitmap_top,
(double)width, (double)height);
cairo_surface_destroy (mask);
if (bitmap != glyphslot->bitmap.buffer)
free (bitmap);
if (status)
return status;
}
return CAIRO_STATUS_SUCCESS;
}

View file

@ -160,14 +160,17 @@ _cairo_gstate_fini (cairo_gstate_t *gstate)
{
cairo_font_destroy (gstate->font);
cairo_surface_destroy (gstate->surface);
if (gstate->surface)
cairo_surface_destroy (gstate->surface);
gstate->surface = NULL;
cairo_surface_destroy (gstate->source);
if (gstate->source)
cairo_surface_destroy (gstate->source);
gstate->source = NULL;
gstate->source_is_solid = 1;
cairo_surface_destroy (gstate->clip.surface);
if (gstate->clip.surface)
cairo_surface_destroy (gstate->clip.surface);
gstate->clip.surface = NULL;
_cairo_color_fini (&gstate->color);
@ -256,12 +259,14 @@ _cairo_gstate_begin_group (cairo_gstate_t *gstate)
_cairo_color_init (&clear);
_cairo_color_set_alpha (&clear, 0);
_cairo_surface_fill_rectangle (gstate->surface,
status = _cairo_surface_fill_rectangle (gstate->surface,
CAIRO_OPERATOR_SRC,
&clear,
0, 0,
_cairo_surface_get_width (gstate->surface),
_cairo_surface_get_height (gstate->surface));
if (status)
return status;
return CAIRO_STATUS_SUCCESS;
}
@ -316,7 +321,8 @@ _cairo_gstate_set_target_surface (cairo_gstate_t *gstate, cairo_surface_t *surfa
{
double scale;
cairo_surface_destroy (gstate->surface);
if (gstate->surface)
cairo_surface_destroy (gstate->surface);
gstate->surface = surface;
cairo_surface_reference (gstate->surface);
@ -375,7 +381,8 @@ _cairo_gstate_set_rgb_color (cairo_gstate_t *gstate, double red, double green, d
{
_cairo_color_set_rgb (&gstate->color, red, green, blue);
cairo_surface_destroy (gstate->source);
if (gstate->source)
cairo_surface_destroy (gstate->source);
gstate->source = NULL;
gstate->source_offset.x = 0;
@ -1177,6 +1184,8 @@ _cairo_gstate_clip_and_composite_trapezoids (cairo_gstate_t *gstate,
cairo_surface_t *dst,
cairo_traps_t *traps)
{
cairo_status_t status;
if (traps->num_traps == 0)
return CAIRO_STATUS_SUCCESS;
@ -1192,6 +1201,10 @@ _cairo_gstate_clip_and_composite_trapezoids (cairo_gstate_t *gstate,
white = _cairo_surface_create_similar_solid (gstate->surface, CAIRO_FORMAT_A8,
1, 1,
&white_color);
if (white == NULL) {
status = CAIRO_STATUS_NO_MEMORY;
goto BAIL0;
}
cairo_surface_set_repeat (white, 1);
_cairo_color_init (&empty_color);
@ -1201,6 +1214,10 @@ _cairo_gstate_clip_and_composite_trapezoids (cairo_gstate_t *gstate,
gstate->clip.width,
gstate->clip.height,
&empty_color);
if (intermediate == NULL) {
status = CAIRO_STATUS_NO_MEMORY;
goto BAIL1;
}
/* Ugh. The cairo_composite/(Render) interface doesn't allow
an offset for the trapezoids. Need to manually shift all
@ -1221,27 +1238,39 @@ _cairo_gstate_clip_and_composite_trapezoids (cairo_gstate_t *gstate,
t->right.p2.y -= yoff;
}
_cairo_surface_composite_trapezoids (CAIRO_OPERATOR_ADD,
white, intermediate,
0, 0,
traps->traps,
traps->num_traps);
_cairo_surface_composite (CAIRO_OPERATOR_IN,
gstate->clip.surface,
NULL,
intermediate,
0, 0, 0, 0, 0, 0,
gstate->clip.width, gstate->clip.height);
_cairo_surface_composite (operator,
src, intermediate, dst,
0, 0,
0, 0,
gstate->clip.x,
gstate->clip.y,
gstate->clip.width,
gstate->clip.height);
status = _cairo_surface_composite_trapezoids (CAIRO_OPERATOR_ADD,
white, intermediate,
0, 0,
traps->traps,
traps->num_traps);
if (status)
goto BAIL2;
status = _cairo_surface_composite (CAIRO_OPERATOR_IN,
gstate->clip.surface,
NULL,
intermediate,
0, 0, 0, 0, 0, 0,
gstate->clip.width, gstate->clip.height);
if (status)
goto BAIL2;
status = _cairo_surface_composite (operator,
src, intermediate, dst,
0, 0,
0, 0,
gstate->clip.x,
gstate->clip.y,
gstate->clip.width,
gstate->clip.height);
BAIL2:
cairo_surface_destroy (intermediate);
BAIL1:
cairo_surface_destroy (white);
BAIL0:
if (status)
return status;
} else {
int xoff, yoff;
@ -1254,12 +1283,14 @@ _cairo_gstate_clip_and_composite_trapezoids (cairo_gstate_t *gstate,
yoff = _cairo_fixed_to_double (traps->traps[0].left.p2.y);
}
_cairo_surface_composite_trapezoids (gstate->operator,
src, dst,
xoff - gstate->source_offset.x,
yoff - gstate->source_offset.y,
traps->traps,
traps->num_traps);
status = _cairo_surface_composite_trapezoids (gstate->operator,
src, dst,
xoff - gstate->source_offset.x,
yoff - gstate->source_offset.y,
traps->traps,
traps->num_traps);
if (status)
return status;
}
return CAIRO_STATUS_SUCCESS;
@ -1330,11 +1361,16 @@ _cairo_gstate_clip (cairo_gstate_t *gstate)
gstate->clip.width,
gstate->clip.height,
&white_color);
if (gstate->clip.surface == NULL)
return CAIRO_STATUS_NO_MEMORY;
}
alpha_one = _cairo_surface_create_similar_solid (gstate->surface, CAIRO_FORMAT_A8,
1, 1,
&white_color);
if (alpha_one == NULL)
return CAIRO_STATUS_NO_MEMORY;
cairo_surface_set_repeat (alpha_one, 1);
_cairo_traps_init (&traps);
@ -1363,6 +1399,7 @@ _cairo_gstate_show_surface (cairo_gstate_t *gstate,
int width,
int height)
{
cairo_status_t status;
cairo_surface_t *mask;
cairo_matrix_t user_to_image, image_to_user;
cairo_matrix_t image_to_device, device_to_image;
@ -1402,17 +1439,20 @@ _cairo_gstate_show_surface (cairo_gstate_t *gstate,
/* XXX: The rendered size is sometimes 1 or 2 pixels short from
what I expect. Need to fix this. */
_cairo_surface_composite (gstate->operator,
surface, mask, gstate->surface,
device_x, device_y,
0, 0,
device_x, device_y,
device_width,
device_height);
status = _cairo_surface_composite (gstate->operator,
surface, mask, gstate->surface,
device_x, device_y,
0, 0,
device_x, device_y,
device_width,
device_height);
if (mask)
cairo_surface_destroy (mask);
if (status)
return status;
/* restore the matrix originally in the surface */
cairo_surface_set_matrix (surface, &user_to_image);

429
src/cairo_image_surface.c Normal file
View file

@ -0,0 +1,429 @@
/*
* Copyright © 2003 University of Southern California
*
* Permission to use, copy, modify, distribute, and sell this software
* and its documentation for any purpose is hereby granted without
* fee, provided that the above copyright notice appear in all copies
* and that both that copyright notice and this permission notice
* appear in supporting documentation, and that the name of the
* University of Southern California not be used in advertising or
* publicity pertaining to distribution of the software without
* specific, written prior permission. The University of Southern
* California makes no representations about the suitability of this
* software for any purpose. It is provided "as is" without express
* or implied warranty.
*
* THE UNIVERSITY OF SOUTHERN CALIFORNIA DISCLAIMS ALL WARRANTIES WITH
* REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL THE UNIVERSITY OF
* SOUTHERN CALIFORNIA BE LIABLE FOR ANY SPECIAL, INDIRECT OR
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
* OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
* NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
* Author: Carl D. Worth <cworth@isi.edu>
*/
#include "cairoint.h"
static const cairo_surface_backend_t cairo_image_surface_backend;
static int
_cairo_format_bpp (cairo_format_t format)
{
switch (format) {
case CAIRO_FORMAT_A1:
return 1;
case CAIRO_FORMAT_A8:
return 8;
case CAIRO_FORMAT_RGB24:
case CAIRO_FORMAT_ARGB32:
default:
return 32;
}
}
static cairo_image_surface_t *
_cairo_image_surface_create_for_ic_image (IcImage *ic_image)
{
cairo_image_surface_t *surface;
surface = malloc (sizeof (cairo_image_surface_t));
if (surface == NULL)
return NULL;
_cairo_surface_init (&surface->base, &cairo_image_surface_backend);
surface->ic_image = ic_image;
surface->data = (char *) IcImageGetData (ic_image);
surface->owns_data = 0;
surface->width = IcImageGetWidth (ic_image);
surface->height = IcImageGetHeight (ic_image);
surface->stride = IcImageGetStride (ic_image);
surface->depth = IcImageGetDepth (ic_image);
return surface;
}
cairo_image_surface_t *
_cairo_image_surface_create_with_masks (char *data,
cairo_format_masks_t *format,
int width,
int height,
int stride)
{
cairo_image_surface_t *surface;
IcFormat *ic_format;
IcImage *ic_image;
ic_format = IcFormatCreateMasks (format->bpp,
format->alpha_mask,
format->red_mask,
format->green_mask,
format->blue_mask);
ic_image = IcImageCreateForData ((IcBits *) data, ic_format,
width, height, format->bpp, stride);
surface = _cairo_image_surface_create_for_ic_image (ic_image);
IcFormatDestroy (ic_format);
return surface;
}
static IcFormat *
_create_ic_format (cairo_format_t format)
{
switch (format) {
case CAIRO_FORMAT_A1:
return IcFormatCreate (IcFormatNameA1);
break;
case CAIRO_FORMAT_A8:
return IcFormatCreate (IcFormatNameA8);
break;
case CAIRO_FORMAT_RGB24:
return IcFormatCreate (IcFormatNameRGB24);
break;
case CAIRO_FORMAT_ARGB32:
default:
return IcFormatCreate (IcFormatNameARGB32);
break;
}
}
cairo_surface_t *
cairo_image_surface_create (cairo_format_t format,
int width,
int height)
{
cairo_image_surface_t *surface;
IcFormat *ic_format;
IcImage *ic_image;
ic_format = _create_ic_format (format);
ic_image = IcImageCreate (ic_format, width, height);
surface = _cairo_image_surface_create_for_ic_image (ic_image);
IcFormatDestroy (ic_format);
return &surface->base;
}
cairo_surface_t *
cairo_image_surface_create_for_data (char *data,
cairo_format_t format,
int width,
int height,
int stride)
{
cairo_image_surface_t *surface;
IcFormat *ic_format;
IcImage *ic_image;
ic_format = _create_ic_format (format);
ic_image = IcImageCreateForData ((IcBits *) data, ic_format,
width, height,
_cairo_format_bpp (format),
stride);
if (ic_image == NULL)
return NULL;
surface = _cairo_image_surface_create_for_ic_image (ic_image);
IcFormatDestroy (ic_format);
return &surface->base;
}
static cairo_surface_t *
_cairo_image_surface_create_similar (void *abstract_src,
cairo_format_t format,
int width,
int height)
{
return cairo_image_surface_create (format, width, height);
}
static void
_cairo_image_abstract_surface_destroy (void *abstract_surface)
{
cairo_image_surface_t *surface = abstract_surface;
if (surface->ic_image)
IcImageDestroy (surface->ic_image);
if (surface->owns_data)
free (surface->data);
free (surface);
}
void
_cairo_image_surface_assume_ownership_of_data (cairo_image_surface_t *surface)
{
surface->owns_data = 1;
}
static double
_cairo_image_surface_pixels_per_inch (void *abstract_surface)
{
/* XXX: We'll want a way to let the user set this. */
return 96.0;
}
static cairo_image_surface_t *
_cairo_image_surface_get_image (void *abstract_surface)
{
cairo_image_surface_t *surface = abstract_surface;
cairo_surface_reference (&surface->base);
return surface;
}
static cairo_status_t
_cairo_image_surface_set_image (void *abstract_surface,
cairo_image_surface_t *image)
{
if (image == abstract_surface)
return CAIRO_STATUS_SUCCESS;
/* XXX: This case has not yet been implemented. We'll lie for now. */
return CAIRO_STATUS_SUCCESS;
}
static cairo_status_t
_cairo_image_abstract_surface_set_matrix (void *abstract_surface,
cairo_matrix_t *matrix)
{
cairo_image_surface_t *surface = abstract_surface;
return _cairo_image_surface_set_matrix (surface, matrix);
}
cairo_status_t
_cairo_image_surface_set_matrix (cairo_image_surface_t *surface,
cairo_matrix_t *matrix)
{
IcTransform ic_transform;
ic_transform.matrix[0][0] = _cairo_fixed_from_double (matrix->m[0][0]);
ic_transform.matrix[0][1] = _cairo_fixed_from_double (matrix->m[1][0]);
ic_transform.matrix[0][2] = _cairo_fixed_from_double (matrix->m[2][0]);
ic_transform.matrix[1][0] = _cairo_fixed_from_double (matrix->m[0][1]);
ic_transform.matrix[1][1] = _cairo_fixed_from_double (matrix->m[1][1]);
ic_transform.matrix[1][2] = _cairo_fixed_from_double (matrix->m[2][1]);
ic_transform.matrix[2][0] = 0;
ic_transform.matrix[2][1] = 0;
ic_transform.matrix[2][2] = _cairo_fixed_from_double (1);
IcImageSetTransform (surface->ic_image, &ic_transform);
return CAIRO_STATUS_SUCCESS;
}
static cairo_status_t
_cairo_image_surface_set_filter (void *abstract_surface, cairo_filter_t filter)
{
cairo_image_surface_t *surface = abstract_surface;
IcFilter ic_filter;
switch (filter) {
case CAIRO_FILTER_FAST:
ic_filter = IcFilterFast;
break;
case CAIRO_FILTER_GOOD:
ic_filter = IcFilterGood;
break;
case CAIRO_FILTER_BEST:
ic_filter = IcFilterBest;
break;
case CAIRO_FILTER_NEAREST:
ic_filter = IcFilterNearest;
break;
case CAIRO_FILTER_BILINEAR:
ic_filter = IcFilterBilinear;
break;
default:
ic_filter = IcFilterBest;
}
IcImageSetFilter (surface->ic_image, ic_filter);
return CAIRO_STATUS_SUCCESS;
}
static cairo_status_t
_cairo_image_abstract_surface_set_repeat (void *abstract_surface, int repeat)
{
cairo_image_surface_t *surface = abstract_surface;
return _cairo_image_surface_set_repeat (surface, repeat);
}
cairo_status_t
_cairo_image_surface_set_repeat (cairo_image_surface_t *surface, int repeat)
{
IcImageSetRepeat (surface->ic_image, repeat);
return CAIRO_STATUS_SUCCESS;
}
static IcOperator
_ic_operator (cairo_operator_t operator)
{
switch (operator) {
case CAIRO_OPERATOR_CLEAR:
return IcOperatorClear;
case CAIRO_OPERATOR_SRC:
return IcOperatorSrc;
case CAIRO_OPERATOR_DST:
return IcOperatorDst;
case CAIRO_OPERATOR_OVER:
return IcOperatorOver;
case CAIRO_OPERATOR_OVER_REVERSE:
return IcOperatorOverReverse;
case CAIRO_OPERATOR_IN:
return IcOperatorIn;
case CAIRO_OPERATOR_IN_REVERSE:
return IcOperatorInReverse;
case CAIRO_OPERATOR_OUT:
return IcOperatorOut;
case CAIRO_OPERATOR_OUT_REVERSE:
return IcOperatorOutReverse;
case CAIRO_OPERATOR_ATOP:
return IcOperatorAtop;
case CAIRO_OPERATOR_ATOP_REVERSE:
return IcOperatorAtopReverse;
case CAIRO_OPERATOR_XOR:
return IcOperatorXor;
case CAIRO_OPERATOR_ADD:
return IcOperatorAdd;
case CAIRO_OPERATOR_SATURATE:
return IcOperatorSaturate;
default:
return IcOperatorOver;
}
}
static cairo_int_status_t
_cairo_image_surface_composite (cairo_operator_t operator,
cairo_surface_t *generic_src,
cairo_surface_t *generic_mask,
void *abstract_dst,
int src_x,
int src_y,
int mask_x,
int mask_y,
int dst_x,
int dst_y,
unsigned int width,
unsigned int height)
{
cairo_image_surface_t *dst = abstract_dst;
cairo_image_surface_t *src = (cairo_image_surface_t *) generic_src;
cairo_image_surface_t *mask = (cairo_image_surface_t *) generic_mask;
if (generic_src->backend != dst->base.backend ||
(generic_mask && (generic_mask->backend != dst->base.backend)))
{
return CAIRO_INT_STATUS_UNSUPPORTED;
}
IcComposite (_ic_operator (operator),
src->ic_image,
mask ? mask->ic_image : NULL,
dst->ic_image,
src_x, src_y,
mask_x, mask_y,
dst_x, dst_y,
width, height);
return CAIRO_STATUS_SUCCESS;
}
static cairo_int_status_t
_cairo_image_surface_fill_rectangles (void *abstract_surface,
cairo_operator_t operator,
const cairo_color_t *color,
cairo_rectangle_t *rects,
int num_rects)
{
cairo_image_surface_t *surface = abstract_surface;
IcColor ic_color;
ic_color.red = color->red_short;
ic_color.green = color->green_short;
ic_color.blue = color->blue_short;
ic_color.alpha = color->alpha_short;
/* XXX: The IcRectangle cast is evil... it needs to go away somehow. */
IcFillRectangles (_ic_operator(operator), surface->ic_image,
&ic_color, (IcRectangle *) rects, num_rects);
return CAIRO_STATUS_SUCCESS;
}
static cairo_int_status_t
_cairo_image_surface_composite_trapezoids (cairo_operator_t operator,
cairo_surface_t *generic_src,
void *abstract_dst,
int x_src,
int y_src,
cairo_trapezoid_t *traps,
int num_traps)
{
cairo_image_surface_t *dst = abstract_dst;
cairo_image_surface_t *src = (cairo_image_surface_t *) generic_src;
if (generic_src->backend != dst->base.backend)
return CAIRO_INT_STATUS_UNSUPPORTED;
/* XXX: The IcTrapezoid cast is evil and needs to go away somehow. */
IcCompositeTrapezoids (operator, src->ic_image, dst->ic_image,
x_src, y_src, (IcTrapezoid *) traps, num_traps);
return CAIRO_STATUS_SUCCESS;
}
static const cairo_surface_backend_t cairo_image_surface_backend = {
_cairo_image_surface_create_similar,
_cairo_image_abstract_surface_destroy,
_cairo_image_surface_pixels_per_inch,
_cairo_image_surface_get_image,
_cairo_image_surface_set_image,
_cairo_image_abstract_surface_set_matrix,
_cairo_image_surface_set_filter,
_cairo_image_abstract_surface_set_repeat,
_cairo_image_surface_composite,
_cairo_image_surface_fill_rectangles,
_cairo_image_surface_composite_trapezoids,
};

View file

@ -29,78 +29,18 @@
#include "cairoint.h"
static const XTransform CAIRO_XTRANSFORM_IDENTITY = {
{
{65536, 0, 0},
{ 0, 65536, 0},
{ 0, 0, 65536}
}
};
static IcFormat *
_create_icformat_for_format (cairo_format_t format)
{
switch (format) {
case CAIRO_FORMAT_ARGB32:
return IcFormatCreate (IcFormatNameARGB32);
break;
case CAIRO_FORMAT_RGB24:
return IcFormatCreate (IcFormatNameRGB24);
break;
case CAIRO_FORMAT_A8:
return IcFormatCreate (IcFormatNameA8);
break;
case CAIRO_FORMAT_A1:
return IcFormatCreate (IcFormatNameA1);
break;
default:
return NULL;
}
}
void
_cairo_surface_init (cairo_surface_t *surface,
int width,
int height,
cairo_format_t format,
const struct cairo_surface_backend *backend)
const cairo_surface_backend_t *backend)
{
surface->width = width;
surface->height = height;
surface->image_data = NULL;
surface->backend = backend;
surface->ref_count = 1;
_cairo_matrix_init (&surface->matrix);
surface->repeat = 0;
surface->xtransform = CAIRO_XTRANSFORM_IDENTITY;
surface->icimage = NULL;
surface->icformat = _create_icformat_for_format (format);
surface->backend = backend;
}
static int
cairo_format_bpp (cairo_format_t format)
{
switch (format) {
case CAIRO_FORMAT_A1:
return 1;
break;
case CAIRO_FORMAT_A8:
return 8;
break;
case CAIRO_FORMAT_RGB24:
case CAIRO_FORMAT_ARGB32:
default:
return 32;
break;
}
}
static const struct cairo_surface_backend cairo_icimage_surface_backend;
cairo_surface_t *
cairo_surface_create_for_image (char *data,
cairo_format_t format,
@ -108,25 +48,7 @@ cairo_surface_create_for_image (char *data,
int height,
int stride)
{
cairo_surface_t *surface;
surface = malloc (sizeof (cairo_surface_t));
if (surface == NULL)
return NULL;
_cairo_surface_init (surface, width, height, format, &cairo_icimage_surface_backend);
surface->icimage = IcImageCreateForData ((IcBits *) data,
surface->icformat,
width, height,
cairo_format_bpp (format),
stride);
if (surface->icimage == NULL) {
free (surface);
return NULL;
}
return surface;
return cairo_image_surface_create_for_data (data, format, width, height, stride);
}
slim_hidden_def(cairo_surface_create_for_image);
@ -138,6 +60,9 @@ cairo_surface_create_similar (cairo_surface_t *other,
{
cairo_color_t empty;
if (other == NULL)
return NULL;
_cairo_color_init (&empty);
_cairo_color_set_rgb (&empty, 0., 0., 0.);
_cairo_color_set_alpha (&empty, 0.);
@ -152,27 +77,21 @@ _cairo_surface_create_similar_solid (cairo_surface_t *other,
int height,
cairo_color_t *color)
{
cairo_status_t status;
cairo_surface_t *surface = NULL;
if (other->backend->create_similar)
surface = other->backend->create_similar (other, format, width, height);
if (surface == NULL) {
char *data;
int stride;
surface = other->backend->create_similar (other, format, width, height);
if (surface == NULL)
surface = cairo_image_surface_create (format, width, height);
stride = ((width * cairo_format_bpp (format)) + 7) >> 3;
data = malloc (stride * height);
if (data == NULL)
return NULL;
surface = cairo_surface_create_for_image (data, format,
width, height, stride);
/* lodge data in the surface structure to be freed with the surface */
surface->image_data = data;
status = _cairo_surface_fill_rectangle (surface,
CAIRO_OPERATOR_SRC, color,
0, 0, width, height);
if (status) {
cairo_surface_destroy (surface);
return NULL;
}
_cairo_surface_fill_rectangle (surface, CAIRO_OPERATOR_SRC, color, 0, 0, width, height);
return surface;
}
@ -195,105 +114,56 @@ cairo_surface_destroy (cairo_surface_t *surface)
if (surface->ref_count)
return;
if (surface->icformat)
IcFormatDestroy (surface->icformat);
if (surface->icimage)
IcImageDestroy (surface->icimage);
if (surface->backend->destroy)
surface->backend->destroy (surface);
if (surface->image_data)
free (surface->image_data);
surface->image_data = NULL;
free (surface);
}
slim_hidden_def(cairo_surface_destroy);
#define CAIRO_SURFACE_PIXELS_PER_INCH_DEFAULT 96.0
double
_cairo_surface_pixels_per_inch (cairo_surface_t *surface)
{
if (surface->backend->pixels_per_inch)
return surface->backend->pixels_per_inch (surface);
return CAIRO_SURFACE_PIXELS_PER_INCH_DEFAULT;
return surface->backend->pixels_per_inch (surface);
}
void
_cairo_surface_pull_image (cairo_surface_t *surface)
cairo_image_surface_t *
_cairo_surface_get_image (cairo_surface_t *surface)
{
if (surface->backend->pull_image)
surface->backend->pull_image (surface);
return surface->backend->get_image (surface);
}
void
_cairo_surface_push_image (cairo_surface_t *surface)
cairo_status_t
_cairo_surface_set_image (cairo_surface_t *surface, cairo_image_surface_t *image)
{
if (surface->backend->push_image)
surface->backend->push_image (surface);
return surface->backend->set_image (surface, image);
}
/* XXX: We may want to move to projective matrices at some point. If
nothing else, that would eliminate the two different transform data
structures we have here. */
cairo_status_t
cairo_surface_set_matrix (cairo_surface_t *surface, cairo_matrix_t *matrix)
{
cairo_status_t ret = CAIRO_STATUS_SUCCESS;
XTransform *xtransform = &surface->xtransform;
if (surface == NULL)
return CAIRO_STATUS_NULL_POINTER;
xtransform->matrix[0][0] = XDoubleToFixed (matrix->m[0][0]);
xtransform->matrix[0][1] = XDoubleToFixed (matrix->m[1][0]);
xtransform->matrix[0][2] = XDoubleToFixed (matrix->m[2][0]);
cairo_matrix_copy (&surface->matrix, matrix);
xtransform->matrix[1][0] = XDoubleToFixed (matrix->m[0][1]);
xtransform->matrix[1][1] = XDoubleToFixed (matrix->m[1][1]);
xtransform->matrix[1][2] = XDoubleToFixed (matrix->m[2][1]);
xtransform->matrix[2][0] = 0;
xtransform->matrix[2][1] = 0;
xtransform->matrix[2][2] = XDoubleToFixed (1);
if (surface->backend->set_matrix)
ret = surface->backend->set_matrix (surface);
/* XXX: This cast should only occur with a #define hint from libic that it is OK */
if (surface->icimage) {
IcImageSetTransform (surface->icimage, (IcTransform *) xtransform);
}
return ret;
return surface->backend->set_matrix (surface, matrix);
}
slim_hidden_def(cairo_surface_set_matrix);
cairo_status_t
cairo_surface_get_matrix (cairo_surface_t *surface, cairo_matrix_t *matrix)
{
XTransform *xtransform = &surface->xtransform;
if (surface == NULL)
return CAIRO_STATUS_NULL_POINTER;
matrix->m[0][0] = _cairo_fixed_to_double (xtransform->matrix[0][0]);
matrix->m[1][0] = _cairo_fixed_to_double (xtransform->matrix[0][1]);
matrix->m[2][0] = _cairo_fixed_to_double (xtransform->matrix[0][2]);
matrix->m[0][1] = _cairo_fixed_to_double (xtransform->matrix[1][0]);
matrix->m[1][1] = _cairo_fixed_to_double (xtransform->matrix[1][1]);
matrix->m[2][1] = _cairo_fixed_to_double (xtransform->matrix[1][2]);
return CAIRO_STATUS_SUCCESS;
return cairo_matrix_copy (matrix, &surface->matrix);
}
slim_hidden_def(cairo_surface_get_matrix);
cairo_status_t
cairo_surface_set_filter (cairo_surface_t *surface, cairo_filter_t filter)
{
if (surface->icimage) {
IcImageSetFilter (surface->icimage, filter);
}
if (!surface->backend->set_filter)
return CAIRO_STATUS_SUCCESS;
if (surface == NULL)
return CAIRO_STATUS_NULL_POINTER;
return surface->backend->set_filter (surface, filter);
}
@ -316,20 +186,16 @@ cairo_surface_clip_restore (cairo_surface_t *surface);
cairo_status_t
cairo_surface_set_repeat (cairo_surface_t *surface, int repeat)
{
if (surface == NULL)
return CAIRO_STATUS_NULL_POINTER;
surface->repeat = repeat;
if (surface->icimage) {
IcImageSetRepeat (surface->icimage, repeat);
}
if (!surface->backend->set_repeat)
return CAIRO_STATUS_SUCCESS;
return surface->backend->set_repeat (surface, repeat);
}
slim_hidden_def(cairo_surface_set_repeat);
void
cairo_int_status_t
_cairo_surface_composite (cairo_operator_t operator,
cairo_surface_t *src,
cairo_surface_t *mask,
@ -344,36 +210,42 @@ _cairo_surface_composite (cairo_operator_t operator,
unsigned int height)
{
cairo_int_status_t status;
cairo_image_surface_t *src_image, *mask_image, *dst_image;
if (dst->backend->composite) {
status = dst->backend->composite (operator,
src, mask, dst,
src_x, src_y,
mask_x, mask_y,
dst_x, dst_y,
width, height);
if (status == CAIRO_STATUS_SUCCESS)
return;
}
status = dst->backend->composite (operator,
src, mask, dst,
src_x, src_y,
mask_x, mask_y,
dst_x, dst_y,
width, height);
if (status != CAIRO_INT_STATUS_UNSUPPORTED)
return status;
_cairo_surface_pull_image (src);
src_image = _cairo_surface_get_image (src);
if (mask)
_cairo_surface_pull_image (mask);
_cairo_surface_pull_image (dst);
mask_image = _cairo_surface_get_image (mask);
dst_image = _cairo_surface_get_image (dst);
IcComposite (operator,
src->icimage,
mask ? mask->icimage : NULL,
dst->icimage,
src_x, src_y,
mask_x, mask_y,
dst_x, dst_y,
width, height);
dst_image->base.backend->composite (operator,
&src_image->base,
mask ? &mask_image->base : NULL,
dst_image,
src_x, src_y,
mask_x, mask_y,
dst_x, dst_y,
width, height);
_cairo_surface_push_image (dst);
status = _cairo_surface_set_image (dst, dst_image);
cairo_surface_destroy (&src_image->base);
if (mask)
cairo_surface_destroy (&mask_image->base);
cairo_surface_destroy (&dst_image->base);
return status;
}
void
cairo_status_t
_cairo_surface_fill_rectangle (cairo_surface_t *surface,
cairo_operator_t operator,
cairo_color_t *color,
@ -389,10 +261,10 @@ _cairo_surface_fill_rectangle (cairo_surface_t *surface,
rect.width = width;
rect.height = height;
_cairo_surface_fill_rectangles (surface, operator, color, &rect, 1);
return _cairo_surface_fill_rectangles (surface, operator, color, &rect, 1);
}
void
cairo_status_t
_cairo_surface_fill_rectangles (cairo_surface_t *surface,
cairo_operator_t operator,
const cairo_color_t *color,
@ -400,61 +272,65 @@ _cairo_surface_fill_rectangles (cairo_surface_t *surface,
int num_rects)
{
cairo_int_status_t status;
IcColor ic_color;
cairo_image_surface_t *surface_image;
if (num_rects == 0)
return;
return CAIRO_STATUS_SUCCESS;
if (surface->backend->fill_rectangles) {
status = surface->backend->fill_rectangles (surface,
operator,
color,
rects, num_rects);
if (status == CAIRO_STATUS_SUCCESS)
return;
}
status = surface->backend->fill_rectangles (surface,
operator,
color,
rects, num_rects);
if (status != CAIRO_INT_STATUS_UNSUPPORTED)
return status;
ic_color.red = color->red_short;
ic_color.green = color->green_short;
ic_color.blue = color->blue_short;
ic_color.alpha = color->alpha_short;
surface_image = _cairo_surface_get_image (surface);
_cairo_surface_pull_image (surface);
surface_image->base.backend->fill_rectangles (surface_image,
operator,
color,
rects, num_rects);
/* XXX: The IcRectangle cast is evil... it needs to go away somehow. */
IcFillRectangles (operator, surface->icimage,
&ic_color, (IcRectangle *) rects, num_rects);
status = _cairo_surface_set_image (surface, surface_image);
_cairo_surface_push_image (surface);
cairo_surface_destroy (&surface_image->base);
return status;
}
void
cairo_status_t
_cairo_surface_composite_trapezoids (cairo_operator_t operator,
cairo_surface_t *src,
cairo_surface_t *dst,
int xSrc,
int ySrc,
int x_src,
int y_src,
cairo_trapezoid_t *traps,
int num_traps)
{
cairo_int_status_t status;
cairo_image_surface_t *src_image, *dst_image;
if (dst->backend->composite_trapezoids) {
status = dst->backend->composite_trapezoids (operator,
src, dst,
xSrc, ySrc,
traps, num_traps);
if (status == CAIRO_STATUS_SUCCESS)
return;
}
status = dst->backend->composite_trapezoids (operator,
src, dst,
x_src, y_src,
traps, num_traps);
if (status != CAIRO_INT_STATUS_UNSUPPORTED)
return status;
_cairo_surface_pull_image (src);
_cairo_surface_pull_image (dst);
src_image = _cairo_surface_get_image (src);
dst_image = _cairo_surface_get_image (dst);
/* XXX: The IcTrapezoid cast is evil and needs to go away somehow. */
IcCompositeTrapezoids (operator, src->icimage, dst->icimage,
xSrc, ySrc, (IcTrapezoid *) traps, num_traps);
dst_image->base.backend->composite_trapezoids (operator,
&src_image->base,
dst_image,
x_src, y_src,
traps, num_traps);
_cairo_surface_push_image (dst);
status = _cairo_surface_set_image (dst, dst_image);
cairo_surface_destroy (&src_image->base);
cairo_surface_destroy (&dst_image->base);
return status;
}

View file

@ -27,7 +27,6 @@
#include "cairoint.h"
#include "cairo-xlib.h"
#include <X11/Xlibint.h>
void
cairo_set_target_drawable (cairo_t *cr,
@ -49,6 +48,8 @@ cairo_set_target_drawable (cairo_t *cr,
}
cairo_set_target_surface (cr, surface);
/* cairo_set_target_surface takes a reference, so we must destroy ours */
cairo_surface_destroy (surface);
}
@ -60,12 +61,15 @@ typedef struct cairo_xlib_surface {
Drawable drawable;
int owns_pixmap;
Visual *visual;
cairo_format_t format;
int render_major;
int render_minor;
int width;
int height;
Picture picture;
XImage *ximage;
} cairo_xlib_surface_t;
#define CAIRO_SURFACE_RENDER_AT_LEAST(surface, major, minor) \
@ -124,18 +128,23 @@ _cairo_xlib_surface_create_similar (void *abstract_src,
if (!dpy
|| (!CAIRO_SURFACE_RENDER_HAS_COMPOSITE (src)
&& format == CAIRO_FORMAT_ARGB32))
{
return NULL;
}
scr = DefaultScreen (dpy);
pix = XCreatePixmap (dpy, DefaultRootWindow (dpy),
width, height,
_CAIRO_FORMAT_DEPTH (format));
surface = (cairo_xlib_surface_t *)
cairo_xlib_surface_create (dpy, pix, NULL, format, DefaultColormap (dpy, scr));
surface->owns_pixmap = 1;
surface->width = width;
surface->height = height;
return &surface->base;
}
@ -149,15 +158,12 @@ _cairo_xlib_surface_destroy (void *abstract_surface)
if (surface->owns_pixmap)
XFreePixmap (surface->dpy, surface->drawable);
if (surface->ximage) {
surface->ximage->data = NULL;
XDestroyImage(surface->ximage);
}
if (surface->gc)
XFreeGC (surface->dpy, surface->gc);
surface->dpy = 0;
free (surface);
}
static double
@ -167,45 +173,63 @@ _cairo_xlib_surface_pixels_per_inch (void *abstract_surface)
return 96.0;
}
static void
_cairo_xlib_surface_pull_image (void *abstract_surface)
static cairo_image_surface_t *
_cairo_xlib_surface_get_image (void *abstract_surface)
{
cairo_xlib_surface_t *surface = abstract_surface;
cairo_image_surface_t *image;
XImage *ximage;
Window root_ignore;
int x_ignore, y_ignore, bwidth_ignore, depth_ignore;
if (surface == NULL)
return;
XGetGeometry (surface->dpy,
surface->drawable,
&root_ignore, &x_ignore, &y_ignore,
&surface->width, &surface->height,
&bwidth_ignore, &depth_ignore);
if (surface->base.icimage) {
IcImageDestroy (surface->base.icimage);
surface->base.icimage = NULL;
ximage = XGetImage (surface->dpy,
surface->drawable,
0, 0,
surface->width, surface->height,
AllPlanes, ZPixmap);
if (surface->visual) {
cairo_format_masks_t masks;
/* XXX: Add support here for pictures with external alpha? */
masks.bpp = ximage->bits_per_pixel;
masks.alpha_mask = 0;
masks.red_mask = surface->visual->red_mask;
masks.green_mask = surface->visual->green_mask;
masks.blue_mask = surface->visual->blue_mask;
image = _cairo_image_surface_create_with_masks (ximage->data,
&masks,
ximage->width,
ximage->height,
ximage->bytes_per_line);
} else {
image = (cairo_image_surface_t *)
cairo_image_surface_create_for_data (ximage->data,
surface->format,
ximage->width,
ximage->height,
ximage->bytes_per_line);
}
XGetGeometry(surface->dpy,
surface->drawable,
&root_ignore, &x_ignore, &y_ignore,
&surface->base.width, &surface->base.height,
&bwidth_ignore, &depth_ignore);
surface->ximage = XGetImage (surface->dpy,
surface->drawable,
0, 0,
surface->base.width, surface->base.height,
AllPlanes, ZPixmap);
surface->base.icimage = IcImageCreateForData ((IcBits *)(surface->ximage->data),
surface->base.icformat,
surface->ximage->width,
surface->ximage->height,
surface->ximage->bits_per_pixel,
surface->ximage->bytes_per_line);
/* Let the surface take ownership of the data */
/* XXX: Can probably come up with a cleaner API here. */
_cairo_image_surface_assume_ownership_of_data (image);
ximage->data = NULL;
XDestroyImage (ximage);
IcImageSetRepeat (surface->base.icimage, surface->base.repeat);
/* XXX: Evil cast here... */
IcImageSetTransform (surface->base.icimage, (IcTransform *) &(surface->base.xtransform));
/* XXX: Add support here for pictures with external alpha. */
_cairo_image_surface_set_repeat (image, surface->base.repeat);
_cairo_image_surface_set_matrix (image, &(surface->base.matrix));
return image;
}
static void
@ -217,40 +241,72 @@ _cairo_xlib_surface_ensure_gc (cairo_xlib_surface_t *surface)
surface->gc = XCreateGC (surface->dpy, surface->drawable, 0, NULL);
}
static void
_cairo_xlib_surface_push_image (void *abstract_surface)
static cairo_status_t
_cairo_xlib_surface_set_image (void *abstract_surface,
cairo_image_surface_t *image)
{
cairo_xlib_surface_t *surface = abstract_surface;
if (surface == NULL)
return;
XImage *ximage;
unsigned bitmap_pad;
if (surface->ximage == NULL)
return;
if (image->depth > 16)
bitmap_pad = 32;
else if (image->depth > 8)
bitmap_pad = 16;
else
bitmap_pad = 8;
ximage = XCreateImage (surface->dpy,
DefaultVisual(surface->dpy, DefaultScreen(surface->dpy)),
image->depth == 32 ? 24 : image->depth,
ZPixmap,
0,
image->data,
image->width,
image->height,
bitmap_pad,
image->stride);
if (ximage == NULL)
return CAIRO_STATUS_NO_MEMORY;
_cairo_xlib_surface_ensure_gc (surface);
XPutImage (surface->dpy,
surface->drawable,
surface->gc,
surface->ximage,
0, 0,
0, 0,
surface->base.width,
surface->base.height);
XPutImage(surface->dpy, surface->drawable, surface->gc,
ximage, 0, 0, 0, 0,
surface->width,
surface->height);
XDestroyImage(surface->ximage);
surface->ximage = NULL;
/* Foolish XDestroyImage thinks it can free my data, but I won't
stand for it. */
ximage->data = NULL;
XDestroyImage (ximage);
return CAIRO_STATUS_SUCCESS;
}
static cairo_status_t
_cairo_xlib_surface_set_matrix (void *abstract_surface)
_cairo_xlib_surface_set_matrix (void *abstract_surface, cairo_matrix_t *matrix)
{
cairo_xlib_surface_t *surface = abstract_surface;
XTransform xtransform;
if (!surface->picture)
return CAIRO_STATUS_SUCCESS;
xtransform.matrix[0][0] = _cairo_fixed_from_double (matrix->m[0][0]);
xtransform.matrix[0][1] = _cairo_fixed_from_double (matrix->m[1][0]);
xtransform.matrix[0][2] = _cairo_fixed_from_double (matrix->m[2][0]);
xtransform.matrix[1][0] = _cairo_fixed_from_double (matrix->m[0][1]);
xtransform.matrix[1][1] = _cairo_fixed_from_double (matrix->m[1][1]);
xtransform.matrix[1][2] = _cairo_fixed_from_double (matrix->m[2][1]);
xtransform.matrix[2][0] = 0;
xtransform.matrix[2][1] = 0;
xtransform.matrix[2][2] = _cairo_fixed_from_double (1);
if (CAIRO_SURFACE_RENDER_HAS_PICTURE_TRANSFORM (surface))
{
XRenderSetPictureTransform (surface->dpy, surface->picture, &surface->base.xtransform);
XRenderSetPictureTransform (surface->dpy, surface->picture, &xtransform);
} else {
/* XXX: Need support here if using an old RENDER without support
for SetPictureTransform */
@ -259,37 +315,36 @@ _cairo_xlib_surface_set_matrix (void *abstract_surface)
return CAIRO_STATUS_SUCCESS;
}
/* XXX: The Render specification has capitalized versions of these
strings. However, the current implementation is case-sensitive and
expects lowercase versions. */
static char *
_render_filter_name (cairo_filter_t filter)
{
switch (filter) {
case CAIRO_FILTER_FAST:
return "fast";
case CAIRO_FILTER_GOOD:
return "good";
case CAIRO_FILTER_BEST:
return "best";
case CAIRO_FILTER_NEAREST:
return "nearest";
case CAIRO_FILTER_BILINEAR:
return "bilinear";
default:
return "best";
}
}
static cairo_status_t
_cairo_xlib_surface_set_filter (void *abstract_surface, cairo_filter_t filter)
{
cairo_xlib_surface_t *surface = abstract_surface;
char *render_filter;
if (!surface->picture)
return CAIRO_STATUS_SUCCESS;
/* XXX: The Render specification has capitalized versions of these
strings. However, the current implementation is
case-sensitive and expects lowercase versions.
*/
switch (filter) {
case CAIRO_FILTER_FAST:
render_filter = "fast";
case CAIRO_FILTER_GOOD:
render_filter = "good";
case CAIRO_FILTER_BEST:
render_filter = "best";
case CAIRO_FILTER_NEAREST:
render_filter = "nearest";
case CAIRO_FILTER_BILINEAR:
render_filter = "bilinear";
default:
render_filter = "best";
}
XRenderSetPictureFilter (surface->dpy, surface->picture,
_render_filter_name (filter), NULL, 0);
render_filter, NULL, 0);
return CAIRO_STATUS_SUCCESS;
}
@ -312,73 +367,68 @@ _cairo_xlib_surface_set_repeat (void *abstract_surface, int repeat)
return CAIRO_STATUS_SUCCESS;
}
static cairo_status_t
_cairo_xlib_surface_put_image (cairo_xlib_surface_t *surface,
char *data,
int width,
int height,
int stride,
int depth)
{
XImage *image;
unsigned bitmap_pad;
if (!surface->picture)
return CAIRO_STATUS_SUCCESS;
if (depth > 16)
bitmap_pad = 32;
else if (depth > 8)
bitmap_pad = 16;
else
bitmap_pad = 8;
image = XCreateImage(surface->dpy,
DefaultVisual(surface->dpy, DefaultScreen(surface->dpy)),
depth, ZPixmap, 0,
data, width, height,
bitmap_pad,
stride);
if (image == NULL)
return CAIRO_STATUS_NO_MEMORY;
_cairo_xlib_surface_ensure_gc (surface);
XPutImage(surface->dpy, surface->drawable, surface->gc,
image, 0, 0, 0, 0, width, height);
/* Foolish XDestroyImage thinks it can free my data, but I won't
stand for it. */
image->data = NULL;
XDestroyImage(image);
return CAIRO_STATUS_SUCCESS;
}
static cairo_xlib_surface_t *
_cairo_xlib_surface_clone_from (cairo_surface_t *src, cairo_xlib_surface_t *tmpl,
cairo_format_t fmt, int depth)
_cairo_xlib_surface_clone_similar (cairo_surface_t *src,
cairo_xlib_surface_t *template,
cairo_format_t format,
int depth)
{
cairo_matrix_t matrix;
cairo_xlib_surface_t *src_on_server;
cairo_xlib_surface_t *clone;
cairo_image_surface_t *src_image;
_cairo_surface_pull_image (src);
src_image = _cairo_surface_get_image (src);
src_on_server = (cairo_xlib_surface_t *)
_cairo_xlib_surface_create_similar (tmpl, fmt,
IcImageGetWidth (src->icimage),
IcImageGetHeight (src->icimage));
if (src_on_server == NULL)
clone = (cairo_xlib_surface_t *)
_cairo_xlib_surface_create_similar (template, format,
src_image->width,
src_image->height);
if (clone == NULL)
return NULL;
cairo_surface_get_matrix (src, &matrix);
cairo_surface_set_matrix (&src_on_server->base, &matrix);
_cairo_xlib_surface_set_image (clone, src_image);
_cairo_xlib_surface_put_image (src_on_server,
(char *) IcImageGetData (src->icimage),
IcImageGetWidth (src->icimage),
IcImageGetHeight (src->icimage),
IcImageGetStride (src->icimage), depth);
return src_on_server;
_cairo_xlib_surface_set_matrix (clone, &(src_image->base.matrix));
cairo_surface_destroy (&src_image->base);
return clone;
}
static int
_render_operator (cairo_operator_t operator)
{
switch (operator) {
case CAIRO_OPERATOR_CLEAR:
return PictOpClear;
case CAIRO_OPERATOR_SRC:
return PictOpSrc;
case CAIRO_OPERATOR_DST:
return PictOpDst;
case CAIRO_OPERATOR_OVER:
return PictOpOver;
case CAIRO_OPERATOR_OVER_REVERSE:
return PictOpOverReverse;
case CAIRO_OPERATOR_IN:
return PictOpIn;
case CAIRO_OPERATOR_IN_REVERSE:
return PictOpInReverse;
case CAIRO_OPERATOR_OUT:
return PictOpOut;
case CAIRO_OPERATOR_OUT_REVERSE:
return PictOpOutReverse;
case CAIRO_OPERATOR_ATOP:
return PictOpAtop;
case CAIRO_OPERATOR_ATOP_REVERSE:
return PictOpAtopReverse;
case CAIRO_OPERATOR_XOR:
return PictOpXor;
case CAIRO_OPERATOR_ADD:
return PictOpAdd;
case CAIRO_OPERATOR_SATURATE:
return PictOpSaturate;
default:
return PictOpOver;
}
}
static cairo_int_status_t
@ -406,19 +456,22 @@ _cairo_xlib_surface_composite (cairo_operator_t operator,
return CAIRO_INT_STATUS_UNSUPPORTED;
if (generic_src->backend != dst->base.backend || src->dpy != dst->dpy) {
src_clone = _cairo_xlib_surface_clone_from (generic_src, dst, CAIRO_FORMAT_ARGB32, 32);
src_clone = _cairo_xlib_surface_clone_similar (generic_src, dst,
CAIRO_FORMAT_ARGB32, 32);
if (!src_clone)
return CAIRO_INT_STATUS_UNSUPPORTED;
src = src_clone;
}
if (generic_mask && (generic_mask->backend != dst->base.backend || mask->dpy != dst->dpy)) {
mask_clone = _cairo_xlib_surface_clone_from (generic_mask, dst, CAIRO_FORMAT_A8, 8);
mask_clone = _cairo_xlib_surface_clone_similar (generic_mask, dst,
CAIRO_FORMAT_A8, 8);
if (!mask_clone)
return CAIRO_INT_STATUS_UNSUPPORTED;
mask = mask_clone;
}
XRenderComposite (dst->dpy, operator,
XRenderComposite (dst->dpy,
_render_operator (operator),
src->picture,
mask ? mask->picture : 0,
dst->picture,
@ -456,7 +509,9 @@ _cairo_xlib_surface_fill_rectangles (void *abstract_surface,
render_color.alpha = color->alpha_short;
/* XXX: This XRectangle cast is evil... it needs to go away somehow. */
XRenderFillRectangles (surface->dpy, operator, surface->picture,
XRenderFillRectangles (surface->dpy,
_render_operator (operator),
surface->picture,
&render_color, (XRectangle *) rects, num_rects);
return CAIRO_STATUS_SUCCESS;
@ -479,14 +534,17 @@ _cairo_xlib_surface_composite_trapezoids (cairo_operator_t operator,
return CAIRO_INT_STATUS_UNSUPPORTED;
if (generic_src->backend != dst->base.backend || src->dpy != dst->dpy) {
src_clone = _cairo_xlib_surface_clone_from (generic_src, dst, CAIRO_FORMAT_ARGB32, 32);
src_clone = _cairo_xlib_surface_clone_similar (generic_src, dst,
CAIRO_FORMAT_ARGB32, 32);
if (!src_clone)
return CAIRO_INT_STATUS_UNSUPPORTED;
src = src_clone;
}
/* XXX: The XTrapezoid cast is evil and needs to go away somehow. */
XRenderCompositeTrapezoids (dst->dpy, operator, src->picture, dst->picture,
XRenderCompositeTrapezoids (dst->dpy,
_render_operator (operator),
src->picture, dst->picture,
XRenderFindStandardFormat (dst->dpy, PictStandardA8),
xSrc, ySrc, (XTrapezoid *) traps, num_traps);
@ -504,8 +562,8 @@ static const struct cairo_surface_backend cairo_xlib_surface_backend = {
_cairo_xlib_surface_create_similar,
_cairo_xlib_surface_destroy,
_cairo_xlib_surface_pixels_per_inch,
_cairo_xlib_surface_pull_image,
_cairo_xlib_surface_push_image,
_cairo_xlib_surface_get_image,
_cairo_xlib_surface_set_image,
_cairo_xlib_surface_set_matrix,
_cairo_xlib_surface_set_filter,
_cairo_xlib_surface_set_repeat,
@ -522,24 +580,16 @@ cairo_xlib_surface_create (Display *dpy,
Colormap colormap)
{
cairo_xlib_surface_t *surface;
int render_standard;
surface = malloc (sizeof (cairo_xlib_surface_t));
if (surface == NULL)
return NULL;
/* XXX: How to get the proper width/height? Force a roundtrip? And
how can we track the width/height properly? Shall we give up on
supporting Windows and only allow drawing to pixmaps? */
_cairo_surface_init (&surface->base, 0, 0, format, &cairo_xlib_surface_backend);
_cairo_surface_init (&surface->base, &cairo_xlib_surface_backend);
if (visual) {
if (surface->base.icformat)
IcFormatDestroy (surface->base.icformat);
surface->base.icformat = IcFormatCreateMasks (32, 0,
visual->red_mask,
visual->green_mask,
visual->blue_mask);
}
surface->visual = visual;
surface->format = format;
surface->dpy = dpy;
@ -553,18 +603,32 @@ cairo_xlib_surface_create (Display *dpy,
surface->render_minor = -1;
}
switch (format) {
case CAIRO_FORMAT_A1:
render_standard = PictStandardA1;
break;
case CAIRO_FORMAT_A8:
render_standard = PictStandardA8;
break;
case CAIRO_FORMAT_RGB24:
render_standard = PictStandardRGB24;
break;
case CAIRO_FORMAT_ARGB32:
default:
render_standard = PictStandardARGB32;
break;
}
/* XXX: I'm currently ignoring the colormap. Is that bad? */
if (CAIRO_SURFACE_RENDER_HAS_CREATE_PICTURE (surface))
surface->picture = XRenderCreatePicture (dpy, drawable,
visual ?
XRenderFindVisualFormat (dpy, visual) :
XRenderFindStandardFormat (dpy, format),
XRenderFindStandardFormat (dpy, render_standard),
0, NULL);
else
surface->picture = 0;
surface->ximage = NULL;
return (cairo_surface_t *) surface;
}
DEPRECATE (cairo_surface_create_for_drawable, cairo_xlib_surface_create);

View file

@ -36,6 +36,8 @@
#ifndef _CAIROINT_H_
#define _CAIROINT_H_
#include <X11/extensions/Xrender.h>
#include <assert.h>
#include <stdlib.h>
#include <string.h>
@ -228,7 +230,7 @@ typedef struct cairo_pen {
typedef struct cairo_color cairo_color_t;
struct cairo_font_backend {
typedef struct cairo_font_backend {
cairo_status_t (*font_extents) (cairo_font_t *font,
cairo_font_extents_t *extents);
@ -276,13 +278,14 @@ struct cairo_font_backend {
void (*destroy) (cairo_font_t *font);
};
} cairo_font_backend_t;
/* concrete font backends */
extern const struct cairo_font_backend cairo_ft_font_backend;
typedef struct cairo_image_surface cairo_image_surface_t;
struct cairo_surface_backend {
typedef struct cairo_surface_backend {
cairo_surface_t *
(*create_similar) (void *surface,
cairo_format_t format,
@ -295,14 +298,21 @@ struct cairo_surface_backend {
double
(*pixels_per_inch) (void *surface);
void
(*pull_image) (void *surface);
/* XXX: We could use a better name than get_image here. Something
to suggest the fact that the function will create a new
surface, (and hence that it needs to be destroyed). Perhaps
clone_image or maybe simply clone? */
void
(*push_image) (void *surface);
cairo_image_surface_t *
(*get_image) (void *surface);
cairo_status_t
(*set_matrix) (void *surface);
(*set_image) (void *surface,
cairo_image_surface_t *image);
cairo_status_t
(*set_matrix) (void *surface,
cairo_matrix_t *matrix);
cairo_status_t
(*set_filter) (void *surface,
@ -343,23 +353,42 @@ struct cairo_surface_backend {
int ySrc,
cairo_trapezoid_t *traps,
int num_traps);
} cairo_surface_backend_t;
struct cairo_matrix {
double m[3][2];
};
struct cairo_surface {
int width;
int height;
typedef struct cairo_format_masks {
int bpp;
unsigned long alpha_mask;
unsigned long red_mask;
unsigned long green_mask;
unsigned long blue_mask;
} cairo_format_masks_t;
char *image_data;
struct cairo_surface {
const cairo_surface_backend_t *backend;
unsigned int ref_count;
cairo_matrix_t matrix;
int repeat;
};
XTransform xtransform;
struct cairo_image_surface {
cairo_surface_t base;
IcImage *icimage;
IcFormat *icformat;
/* libic-specific fields */
char *data;
int owns_data;
const struct cairo_surface_backend *backend;
int width;
int height;
int stride;
int depth;
IcImage *ic_image;
};
/* XXX: Right now, the cairo_color structure puts unpremultiplied
@ -380,10 +409,6 @@ struct cairo_color {
unsigned short alpha_short;
};
struct cairo_matrix {
double m[3][2];
};
typedef struct cairo_traps {
cairo_trapezoid_t *traps;
int num_traps;
@ -521,12 +546,6 @@ _cairo_gstate_end_group (cairo_gstate_t *gstate);
extern cairo_status_t __internal_linkage
_cairo_gstate_set_drawable (cairo_gstate_t *gstate, Drawable drawable);
extern cairo_status_t __internal_linkage
_cairo_gstate_set_visual (cairo_gstate_t *gstate, Visual *visual);
extern cairo_status_t __internal_linkage
_cairo_gstate_set_format (cairo_gstate_t *gstate, cairo_format_t format);
extern cairo_status_t __internal_linkage
_cairo_gstate_set_target_surface (cairo_gstate_t *gstate, cairo_surface_t *surface);
@ -896,12 +915,9 @@ _cairo_surface_create_similar_solid (cairo_surface_t *other,
extern void __internal_linkage
_cairo_surface_init (cairo_surface_t *surface,
int width,
int height,
cairo_format_t format,
const struct cairo_surface_backend *backend);
const cairo_surface_backend_t *backend);
extern void __internal_linkage
extern cairo_status_t __internal_linkage
_cairo_surface_fill_rectangle (cairo_surface_t *surface,
cairo_operator_t operator,
cairo_color_t *color,
@ -910,7 +926,7 @@ _cairo_surface_fill_rectangle (cairo_surface_t *surface,
int width,
int height);
extern void __internal_linkage
extern cairo_status_t __internal_linkage
_cairo_surface_composite (cairo_operator_t operator,
cairo_surface_t *src,
cairo_surface_t *mask,
@ -924,14 +940,14 @@ _cairo_surface_composite (cairo_operator_t operator,
unsigned int width,
unsigned int height);
extern void __internal_linkage
extern cairo_status_t __internal_linkage
_cairo_surface_fill_rectangles (cairo_surface_t *surface,
cairo_operator_t operator,
const cairo_color_t *color,
cairo_rectangle_t *rects,
int num_rects);
extern void __internal_linkage
extern cairo_status_t __internal_linkage
_cairo_surface_composite_trapezoids (cairo_operator_t operator,
cairo_surface_t *src,
cairo_surface_t *dst,
@ -943,12 +959,31 @@ _cairo_surface_composite_trapezoids (cairo_operator_t operator,
extern double __internal_linkage
_cairo_surface_pixels_per_inch (cairo_surface_t *surface);
extern void __internal_linkage
_cairo_surface_pull_image (cairo_surface_t *surface);
extern cairo_image_surface_t * __internal_linkage
_cairo_surface_get_image (cairo_surface_t *surface);
extern cairo_status_t __internal_linkage
_cairo_surface_set_image (cairo_surface_t *surface,
cairo_image_surface_t *image);
/* cairo_image_surface.c */
extern cairo_image_surface_t * __internal_linkage
_cairo_image_surface_create_with_masks (char *data,
cairo_format_masks_t *format,
int width,
int height,
int stride);
extern void __internal_linkage
_cairo_surface_push_image (cairo_surface_t *surface);
_cairo_image_surface_assume_ownership_of_data (cairo_image_surface_t *surface);
extern cairo_status_t __internal_linkage
_cairo_image_surface_set_matrix (cairo_image_surface_t *surface,
cairo_matrix_t *matrix);
extern cairo_status_t __internal_linkage
_cairo_image_surface_set_repeat (cairo_image_surface_t *surface, int repeat);
/* cairo_pen.c */
extern cairo_status_t __internal_linkage