mirror of
https://gitlab.freedesktop.org/cairo/cairo.git
synced 2026-04-25 00:20:43 +02:00
Moved all libic-related drawing into cairo_image_surface.c
This commit is contained in:
parent
6dca2ab9d3
commit
32df4d217d
17 changed files with 1997 additions and 1075 deletions
66
ChangeLog
66
ChangeLog
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
||||
|
|
|
|||
|
|
@ -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@
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
429
src/cairo-image-surface.c
Normal 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,
|
||||
};
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -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>";
|
||||
|
|
|
|||
92
src/cairo.h
92
src/cairo.h
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
429
src/cairo_image_surface.c
Normal 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,
|
||||
};
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
109
src/cairoint.h
109
src/cairoint.h
|
|
@ -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
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue