Preliminary support for running Cairo with X servers without the Render extension. This is still horribly slow. Removed many uses of X-specific macros, (eg. XDoubleToFixed)

This commit is contained in:
Carl Worth 2003-09-05 15:29:49 +00:00
parent 4551d78c8f
commit 5b5c172803
23 changed files with 573 additions and 344 deletions

View file

@ -1,3 +1,37 @@
2003-09-05 Carl Worth <cworth@isi.edu>
* configure.in (PKG_CHECK_MODULES): Require libic >= 0.1.1
* src/cairo_surface.c (_create_icformat_for_visual):
(_create_icformat_for_format): Updates for new libic interface.
(cairo_x11_surface_put_image): Rename cairo_surface_put_image to
cairo_x11_surface_put_image.
(_cairo_surface_pull_image):
(_cairo_surface_push_image): First real implementation of
push/pull_image, (thanks for help from Graydon Hoare
<graydon@redhat.com>). This provides support for running Cairo on
X servers that do not have the RENDER extension. (Note: This is
still woefully slow).
* src/cairo_path_stroke.c (_cairo_stroker_join): Switch to
_cairo_fixed functions.
* src/cairo_path_bounds.c (_cairo_path_bounds): Use cairo_fixed
rather than X macros.
* src/cairo_gstate.c (_cairo_gstate_current_point): If not
explicitly set, current point is (0,0) in user space.
(_cairo_gstate_show_text): Fix to place text at user-space origin
if there is no current point.
(_cairo_gstate_show_surface): Optimize to pass NULL mask if alpha
== 1.0.
(_cairo_gstate_show_surface): Fixe to use current_point rather
than (0,0).
* src/cairo.h: Removed cairo_surface_put_image.
* src/Makefile.am (libcairo_la_SOURCES): Added cairo_fixed.c
2003-09-05 Keith Packard <keithp@keithp.com>
* src/cairo_path_stroke.c: comment face computations, check for

View file

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

View file

@ -5,6 +5,7 @@ libcairo_la_SOURCES = \
cairo.c \
cairo.h \
cairo_color.c \
cairo_fixed.c \
cairo_font.c \
cairo_gstate.c \
cairo_matrix.c \

46
src/cairo-fixed.c Normal file
View file

@ -0,0 +1,46 @@
/*
* Copyright © 2003 USC, Information Sciences Institute
*
* 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"
cairo_fixed_t
_cairo_fixed_from_int (int i)
{
return i << 16;
}
cairo_fixed_t
_cairo_fixed_from_double (double d)
{
return (cairo_fixed_t) (d * 65536);
}
double
_cairo_fixed_to_double (cairo_fixed_t f)
{
return ((double) f) / 65536.0;
}

View file

@ -71,6 +71,7 @@ _cairo_font_fini (cairo_font_t *font)
if (font->xft_font)
XftFontClose (font->dpy, font->xft_font);
font->xft_font = NULL;
}

View file

@ -795,12 +795,21 @@ _cairo_gstate_close_path (cairo_gstate_t *gstate)
}
cairo_status_t
_cairo_gstate_current_point (cairo_gstate_t *gstate, double *x, double *y)
_cairo_gstate_current_point (cairo_gstate_t *gstate, double *x_ret, double *y_ret)
{
*x = gstate->current_pt.x;
*y = gstate->current_pt.y;
double x, y;
cairo_matrix_transform_point (&gstate->ctm_inverse, x, y);
if (gstate->has_current_pt) {
x = gstate->current_pt.x;
y = gstate->current_pt.y;
cairo_matrix_transform_point (&gstate->ctm_inverse, &x, &y);
} else {
x = 0.0;
y = 0.0;
}
*x_ret = x;
*y_ret = y;
return CAIRO_STATUS_SUCCESS;
}
@ -861,7 +870,7 @@ _cairo_gstate_stroke (cairo_gstate_t *gstate)
gstate->operator,
gstate->surface,
&traps);
/* restore the matrix originally in the source surface */
if (! gstate->source_is_solid)
cairo_surface_set_matrix (gstate->source, &user_to_source);
@ -944,20 +953,20 @@ _cairo_gstate_clip_and_composite_trapezoids (cairo_gstate_t *gstate,
cairo_surface_destroy (white);
} else {
double xoff, yoff;
int xoff, yoff;
if (traps->traps[0].left.p1.y < traps->traps[0].left.p2.y) {
xoff = traps->traps[0].left.p1.x;
yoff = traps->traps[0].left.p1.y;
xoff = _cairo_fixed_to_double (traps->traps[0].left.p1.x);
yoff = _cairo_fixed_to_double (traps->traps[0].left.p1.y);
} else {
xoff = traps->traps[0].left.p2.x;
yoff = traps->traps[0].left.p2.y;
xoff = _cairo_fixed_to_double (traps->traps[0].left.p2.x);
yoff = _cairo_fixed_to_double (traps->traps[0].left.p2.y);
}
_cairo_surface_composite_trapezoids (gstate->operator,
src, dst,
XFixedToDouble (xoff) - gstate->source_offset.x,
XFixedToDouble (yoff) - gstate->source_offset.y,
xoff - gstate->source_offset.x,
yoff - gstate->source_offset.y,
traps->traps,
traps->num_traps);
}
@ -1115,14 +1124,24 @@ _cairo_gstate_show_text (cairo_gstate_t *gstate, const unsigned char *utf8)
{
cairo_status_t status;
XftFont *xft_font;
double x, y;
cairo_matrix_t user_to_source, device_to_source;
if (gstate->has_current_pt == 0)
return CAIRO_STATUS_NO_CURRENT_POINT;
if (gstate->surface->dpy == 0)
return CAIRO_STATUS_SUCCESS;
/* XXX: I believe this is correct, but it would be much more clear
to have some explicit current_point accesor functions, (one for
user- and one for device-space). */
if (gstate->has_current_pt) {
x = gstate->current_pt.x;
y = gstate->current_pt.y;
} else {
x = 0;
y = 0;
cairo_matrix_transform_point (&gstate->ctm, &x, &y);
}
_cairo_font_resolve_xft_font (&gstate->font, gstate, &xft_font);
status = _cairo_gstate_ensure_source (gstate);
@ -1145,8 +1164,7 @@ _cairo_gstate_show_text (cairo_gstate_t *gstate, const unsigned char *utf8)
xft_font,
gstate->surface->picture,
0, 0,
gstate->current_pt.x,
gstate->current_pt.y,
x, y,
utf8,
strlen ((char *) utf8));
@ -1169,15 +1187,19 @@ _cairo_gstate_show_surface (cairo_gstate_t *gstate,
double device_x, device_y;
double device_width, device_height;
mask = cairo_surface_create_similar_solid (gstate->surface,
CAIRO_FORMAT_A8,
1, 1,
1.0, 1.0, 1.0,
gstate->alpha);
if (mask == NULL)
return CAIRO_STATUS_NO_MEMORY;
if (gstate->alpha != 1.0) {
mask = cairo_surface_create_similar_solid (gstate->surface,
CAIRO_FORMAT_A8,
1, 1,
1.0, 1.0, 1.0,
gstate->alpha);
if (mask == NULL)
return CAIRO_STATUS_NO_MEMORY;
cairo_surface_set_repeat (mask, 1);
cairo_surface_set_repeat (mask, 1);
} else {
mask = NULL;
}
cairo_surface_get_matrix (surface, &user_to_image);
cairo_matrix_multiply (&device_to_image, &gstate->ctm_inverse, &user_to_image);
@ -1187,8 +1209,7 @@ _cairo_gstate_show_surface (cairo_gstate_t *gstate,
cairo_matrix_invert (&image_to_user);
cairo_matrix_multiply (&image_to_device, &image_to_user, &gstate->ctm);
device_x = 0;
device_y = 0;
_cairo_gstate_current_point (gstate, &device_x, &device_y);
device_width = width;
device_height = height;
_cairo_matrix_transform_bounding_box (&image_to_device,
@ -1205,7 +1226,8 @@ _cairo_gstate_show_surface (cairo_gstate_t *gstate,
device_width,
device_height);
cairo_surface_destroy (mask);
if (mask)
cairo_surface_destroy (mask);
/* restore the matrix originally in the surface */
cairo_surface_set_matrix (surface, &user_to_image);

View file

@ -159,10 +159,10 @@ _cairo_path_bounds (cairo_path_t *path, double *x1, double *y1, double *x2, doub
return status;
}
*x1 = XFixedToDouble (bounder.min_x);
*y1 = XFixedToDouble (bounder.min_y);
*x2 = XFixedToDouble (bounder.max_x);
*y2 = XFixedToDouble (bounder.max_y);
*x1 = _cairo_fixed_to_double (bounder.min_x);
*y1 = _cairo_fixed_to_double (bounder.min_y);
*x2 = _cairo_fixed_to_double (bounder.max_x);
*y2 = _cairo_fixed_to_double (bounder.max_y);
_cairo_path_bounder_fini (&bounder);

View file

@ -252,15 +252,15 @@ _cairo_stroker_join (cairo_stroker_t *stroker, cairo_stroke_face_t *in, cairo_st
* device space
*/
/* outer point of incoming line face */
x1 = cairo_fixed_to_double (inpt->x);
y1 = cairo_fixed_to_double (inpt->y);
x1 = _cairo_fixed_to_double (inpt->x);
y1 = _cairo_fixed_to_double (inpt->y);
dx1 = in->usr_vector.x;
dy1 = in->usr_vector.y;
cairo_matrix_transform_distance (&gstate->ctm, &dx1, &dy1);
/* outer point of outgoing line face */
x2 = cairo_fixed_to_double (outpt->x);
y2 = cairo_fixed_to_double (outpt->y);
x2 = _cairo_fixed_to_double (outpt->x);
y2 = _cairo_fixed_to_double (outpt->y);
dx2 = out->usr_vector.x;
dy2 = out->usr_vector.y;
cairo_matrix_transform_distance (&gstate->ctm, &dx2, &dy2);
@ -283,8 +283,8 @@ _cairo_stroker_join (cairo_stroker_t *stroker, cairo_stroke_face_t *in, cairo_st
/*
* Draw the quadrilateral
*/
outer.x = cairo_double_to_fixed (mx);
outer.y = cairo_double_to_fixed (my);
outer.x = _cairo_fixed_from_double (mx);
outer.y = _cairo_fixed_from_double (my);
_cairo_polygon_init (&polygon);
_cairo_polygon_add_edge (&polygon, &in->pt, inpt);
_cairo_polygon_add_edge (&polygon, inpt, &outer);
@ -358,8 +358,8 @@ _cairo_stroker_cap (cairo_stroker_t *stroker, cairo_stroke_face_t *f)
dx *= gstate->line_width / 2.0;
dy *= gstate->line_width / 2.0;
cairo_matrix_transform_distance (&gstate->ctm, &dx, &dy);
fvector.dx = cairo_double_to_fixed (dx);
fvector.dy = cairo_double_to_fixed (dy);
fvector.dx = _cairo_fixed_from_double (dx);
fvector.dy = _cairo_fixed_from_double (dy);
occw.x = f->ccw.x + fvector.dx;
occw.y = f->ccw.y + fvector.dy;
ocw.x = f->cw.x + fvector.dx;
@ -390,8 +390,8 @@ _compute_face (cairo_point_t *pt, cairo_slope_t *slope, cairo_gstate_t *gstate,
XPointDouble usr_vector;
cairo_point_t offset_ccw, offset_cw;
line_dx = cairo_fixed_to_double (slope->dx);
line_dy = cairo_fixed_to_double (slope->dy);
line_dx = _cairo_fixed_to_double (slope->dx);
line_dy = _cairo_fixed_to_double (slope->dy);
/* faces are normal in user space, not device space */
cairo_matrix_transform_distance (&gstate->ctm_inverse, &line_dx, &line_dy);
@ -431,8 +431,8 @@ _compute_face (cairo_point_t *pt, cairo_slope_t *slope, cairo_gstate_t *gstate,
/* back to device space */
cairo_matrix_transform_distance (&gstate->ctm, &face_dx, &face_dy);
offset_ccw.x = cairo_double_to_fixed (face_dx);
offset_ccw.y = cairo_double_to_fixed (face_dy);
offset_ccw.x = _cairo_fixed_from_double (face_dx);
offset_ccw.y = _cairo_fixed_from_double (face_dy);
offset_cw.x = -offset_ccw.x;
offset_cw.y = -offset_ccw.y;
@ -533,8 +533,8 @@ _cairo_stroker_add_edge_dashed (void *closure, cairo_point_t *p1, cairo_point_t
int first = 1;
cairo_stroke_face_t sub_start, sub_end;
dx = cairo_fixed_to_double (p2->x - p1->x);
dy = cairo_fixed_to_double (p2->y - p1->y);
dx = _cairo_fixed_to_double (p2->x - p1->x);
dy = _cairo_fixed_to_double (p2->y - p1->y);
cairo_matrix_transform_distance (&gstate->ctm_inverse, &dx, &dy);
@ -549,8 +549,8 @@ _cairo_stroker_add_edge_dashed (void *closure, cairo_point_t *p1, cairo_point_t
dx2 = dx * (mag - remain)/mag;
dy2 = dy * (mag - remain)/mag;
cairo_matrix_transform_distance (&gstate->ctm, &dx2, &dy2);
fd2.x = cairo_double_to_fixed (dx2);
fd2.y = cairo_double_to_fixed (dy2);
fd2.x = _cairo_fixed_from_double (dx2);
fd2.y = _cairo_fixed_from_double (dy2);
fd2.x += p1->x;
fd2.y += p1->y;
/*

View file

@ -105,8 +105,8 @@ _cairo_pen_init (cairo_pen_t *pen, double radius, cairo_gstate_t *gstate)
double dy = radius * sin (reflect ? -theta : theta);
cairo_pen_vertex_t *v = &pen->vertex[i];
cairo_matrix_transform_distance (&gstate->ctm, &dx, &dy);
v->pt.x = cairo_double_to_fixed (dx);
v->pt.y = cairo_double_to_fixed (dy);
v->pt.x = _cairo_fixed_from_double (dx);
v->pt.y = _cairo_fixed_from_double (dy);
}
_cairo_pen_compute_slopes (pen);

View file

@ -166,8 +166,8 @@ _de_casteljau (cairo_spline_t *spline, cairo_spline_t *s1, cairo_spline_t *s2)
static double
_PointDistanceSquaredToPoint (cairo_point_t *a, cairo_point_t *b)
{
double dx = XFixedToDouble (b->x - a->x);
double dy = XFixedToDouble (b->y - a->y);
double dx = _cairo_fixed_to_double (b->x - a->x);
double dy = _cairo_fixed_to_double (b->y - a->y);
return dx*dx + dy*dy;
}
@ -190,14 +190,14 @@ _PointDistanceSquaredToSegment (cairo_point_t *p, cairo_point_t *p1, cairo_point
u = ((p - p1) . (p2 - p1)) / (||(p2 - p1)|| ^ 2);
*/
dx = XFixedToDouble (p2->x - p1->x);
dy = XFixedToDouble (p2->y - p1->y);
dx = _cairo_fixed_to_double (p2->x - p1->x);
dy = _cairo_fixed_to_double (p2->y - p1->y);
if (dx == 0 && dy == 0)
return _PointDistanceSquaredToPoint (p, p1);
pdx = XFixedToDouble (p->x - p1->x);
pdy = XFixedToDouble (p->y - p1->y);
pdx = _cairo_fixed_to_double (p->x - p1->x);
pdy = _cairo_fixed_to_double (p->y - p1->y);
u = (pdx * dx + pdy * dy) / (dx*dx + dy*dy);

View file

@ -57,6 +57,36 @@ static const XTransform CAIRO_XTRANSFORM_IDENTITY = {
#define CAIRO_SURFACE_RENDER_HAS_PICTURE_TRANSFORM(surface) CAIRO_SURFACE_RENDER_AT_LEAST((surface), 0, 6)
static IcFormat *
_create_icformat_for_visual (Visual *visual)
{
return IcFormatCreateMasks (32, 0,
visual->red_mask,
visual->green_mask,
visual->blue_mask);
}
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;
}
}
cairo_surface_t *
cairo_surface_create_for_drawable (Display *dpy,
Drawable drawable,
@ -72,8 +102,8 @@ cairo_surface_create_for_drawable (Display *dpy,
/* XXX: We should really get this value from somewhere like Xft.dpy */
surface->ppm = 3780;
surface->ref_count = 1;
surface->repeat = 0;
surface->dpy = dpy;
surface->image_data = NULL;
@ -91,47 +121,33 @@ cairo_surface_create_for_drawable (Display *dpy,
surface->render_minor = -1;
}
if (visual)
surface->icformat = _create_icformat_for_visual (visual);
else
surface->icformat = _create_icformat_for_format (format);
/* 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),
visual ?
XRenderFindVisualFormat (dpy, visual) :
XRenderFindStandardFormat (dpy, format),
0, NULL);
else
surface->picture = 0;
surface->ximage = 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? */
surface->width = 0;
surface->height = 0;
return surface;
}
slim_hidden_def(cairo_surface_create_for_drawable)
/* XXX: These definitions are 100% bogus. The problem that needs to be
fixed is that Ic needs to export a real API for passing in
formats. */
#define PICT_FORMAT(bpp,type,a,r,g,b) (((bpp) << 24) | \
((type) << 16) | \
((a) << 12) | \
((r) << 8) | \
((g) << 4) | \
((b)))
/*
* gray/color formats use a visual index instead of argb
*/
#define PICT_VISFORMAT(bpp,type,vi) (((bpp) << 24) | \
((type) << 16) | \
((vi)))
#define PICT_TYPE_A 1
#define PICT_TYPE_ARGB 2
#define PICT_FORMAT_COLOR(f) (PICT_FORMAT_TYPE(f) & 2)
/* 32bpp formats */
#define PICT_a8r8g8b8 PICT_FORMAT(32,PICT_TYPE_ARGB,8,8,8,8)
#define PICT_x8r8g8b8 PICT_FORMAT(32,PICT_TYPE_ARGB,0,8,8,8)
#define PICT_a8 PICT_FORMAT(8,PICT_TYPE_A,8,0,0,0)
#define PICT_a1 PICT_FORMAT(1,PICT_TYPE_A,1,0,0,0)
static int
cairo_format_bpp (cairo_format_t format)
{
@ -158,45 +174,30 @@ cairo_surface_create_for_image (char *data,
int stride)
{
cairo_surface_t *surface;
IcFormat icformat;
IcImage *image;
int bpp;
/* XXX: This all needs to change, (but IcFormatInit interface needs to change first) */
switch (format) {
case CAIRO_FORMAT_ARGB32:
IcFormatInit (&icformat, PICT_a8r8g8b8);
bpp = 32;
break;
case CAIRO_FORMAT_RGB24:
IcFormatInit (&icformat, PICT_x8r8g8b8);
bpp = 32;
break;
case CAIRO_FORMAT_A8:
IcFormatInit (&icformat, PICT_a8);
bpp = 8;
break;
case CAIRO_FORMAT_A1:
IcFormatInit (&icformat, PICT_a1);
bpp = 1;
break;
default:
return NULL;
}
surface = malloc (sizeof (cairo_surface_t));
if (surface == NULL)
return NULL;
surface->icformat = _create_icformat_for_format (format);
/* Assume a default until the user lets us know otherwise */
surface->ppm = 3780;
surface->ref_count = 1;
surface->repeat = 0;
surface->dpy = NULL;
surface->image_data = NULL;
image = IcImageCreateForData ((IcBits *) data, &icformat, width, height, cairo_format_bpp (format), stride);
if (image == NULL) {
surface->width = width;
surface->height = height;
surface->icimage = IcImageCreateForData ((IcBits *) data,
surface->icformat,
width, height,
cairo_format_bpp (format),
stride);
if (surface->icimage == NULL) {
free (surface);
return NULL;
}
@ -211,8 +212,7 @@ cairo_surface_create_for_image (char *data,
surface->render_minor = -1;
surface->picture = 0;
surface->icimage = image;
surface->ximage = NULL;
return surface;
}
@ -322,6 +322,9 @@ cairo_surface_destroy (cairo_surface_t *surface)
if (surface->picture)
XRenderFreePicture (surface->dpy, surface->picture);
if (surface->icformat)
IcFormatDestroy (surface->icformat);
if (surface->icimage)
IcImageDestroy (surface->icimage);
@ -345,17 +348,17 @@ _cairo_surface_ensure_gc (cairo_surface_t *surface)
surface->gc = XCreateGC (surface->dpy, surface->drawable, 0, NULL);
}
cairo_status_t
cairo_surface_put_image (cairo_surface_t *surface,
char *data,
int width,
int height,
int stride)
static cairo_status_t
cairo_x11_surface_put_image (cairo_surface_t *surface,
char *data,
int width,
int height,
int stride)
{
if (surface->picture) {
XImage *image;
unsigned bitmap_pad;
/* XXX: This is obviously bogus. depth needs to be figured out for real */
int depth = 32;
@ -386,16 +389,19 @@ cairo_surface_put_image (cairo_surface_t *surface,
} else {
/* XXX: Need to implement the IcImage method of setting a picture. memcpy? */
}
return CAIRO_STATUS_SUCCESS;
}
/* XXX: Symmetry demands an cairo_surface_get_image as well. */
void
_cairo_surface_pull_image (cairo_surface_t *surface)
{
/* XXX: NYI (Also needs support for pictures with external alpha.)
Window root_ignore;
int x_ignore, y_ignore, bwidth_ignore, depth_ignore;
if (surface == NULL)
return;
if (surface->type == CAIRO_SURFACE_TYPE_ICIMAGE)
return;
@ -404,46 +410,59 @@ _cairo_surface_pull_image (cairo_surface_t *surface)
surface->icimage = NULL;
}
_cairo_surface_ensure_GC (surface);
XGetGeometry(surface->dpy,
surface->drawable,
&root_ignore, &x_ignore, &y_ignore,
&surface->width, &surface->height,
&bwidth_ignore, &depth_ignore);
surface->ximage = XGetImage (surface->dpy,
surface->drawable,
surface->gc,
0, 0,
width, height,
surface->width, surface->height,
AllPlanes, ZPixmap);
surface->icimage = IcImageCreateForData ((IcBits *)(surface->ximage->data),
surface->icformat,
surface->ximage->width,
surface->ximage->height,
surface->ximage->bits_per_pixel,
surface->ximage->bytes_per_line);
IcImageSetRepeat (surface->icimage, surface->repeat);
/* XXX: Evil cast here... */
IcImageSetTransform (surface->icimage, (IcTransform *) &(surface->xtransform));
surface->icimage = IcImageCreateForData (image->data,
IcFormat *format,
int width, int height,
int bpp, int stride);
*/
/* XXX: Add support here for pictures with external alpha. */
}
void
_cairo_surface_push_image (cairo_surface_t *surface)
{
/* XXX: NYI
if (surface == NULL)
return;
if (surface->type == CAIRO_SURFACE_TYPE_ICIMAGE)
return;
if (surface->ximage == NULL)
return;
_cairo_surface_ensure_GC (surface);
_cairo_surface_ensure_gc (surface);
XPutImage (surface->dpy,
surface->drawable,
surface->gc,
surface->ximage,
0, 0,
0, 0,
width, height);
surface->width,
surface->height);
* Foolish XDestroyImage thinks it can free my data, but I won't
stand for it. *
/* Foolish XDestroyImage thinks it can free my data, but I won't
stand for it. */
surface->ximage->data = NULL;
XDestroyImage(surface->ximage);
surface->ximage = NULL;
*/
}
/* XXX: We may want to move to projective matrices at some point. If
@ -487,13 +506,13 @@ cairo_surface_get_matrix (cairo_surface_t *surface, cairo_matrix_t *matrix)
{
XTransform *xtransform = &surface->xtransform;
matrix->m[0][0] = XFixedToDouble (xtransform->matrix[0][0]);
matrix->m[1][0] = XFixedToDouble (xtransform->matrix[0][1]);
matrix->m[2][0] = XFixedToDouble (xtransform->matrix[0][2]);
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] = XFixedToDouble (xtransform->matrix[1][0]);
matrix->m[1][1] = XFixedToDouble (xtransform->matrix[1][1]);
matrix->m[2][1] = XFixedToDouble (xtransform->matrix[1][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;
}
@ -554,6 +573,8 @@ cairo_surface_clip_restore (cairo_surface_t *surface);
cairo_status_t
cairo_surface_set_repeat (cairo_surface_t *surface, int repeat)
{
surface->repeat = repeat;
if (surface->picture) {
unsigned long mask;
XRenderPictureAttributes pa;
@ -604,11 +625,11 @@ _cairo_surface_composite (cairo_operator_t operator,
cairo_surface_get_matrix (src, &matrix);
cairo_surface_set_matrix (src_on_server, &matrix);
cairo_surface_put_image (src_on_server,
(char *) IcImageGetData (src->icimage),
IcImageGetWidth (src->icimage),
IcImageGetHeight (src->icimage),
IcImageGetStride (src->icimage));
cairo_x11_surface_put_image (src_on_server,
(char *) IcImageGetData (src->icimage),
IcImageGetWidth (src->icimage),
IcImageGetHeight (src->icimage),
IcImageGetStride (src->icimage));
}
XRenderComposite (dst->dpy, operator,
@ -623,7 +644,8 @@ _cairo_surface_composite (cairo_operator_t operator,
} else {
_cairo_surface_pull_image (src);
_cairo_surface_pull_image (mask);
if (mask)
_cairo_surface_pull_image (mask);
_cairo_surface_pull_image (dst);
IcComposite (operator,
@ -665,6 +687,9 @@ _cairo_surface_fill_rectangles (cairo_surface_t *surface,
cairo_rectangle_t *rects,
int num_rects)
{
if (num_rects == 0)
return;
if (surface->type == CAIRO_SURFACE_TYPE_DRAWABLE
&& CAIRO_SURFACE_RENDER_HAS_FILL_RECTANGLE (surface)) {
@ -702,7 +727,7 @@ _cairo_surface_composite_trapezoids (cairo_operator_t operator,
cairo_surface_t *dst,
int xSrc,
int ySrc,
const cairo_trapezoid_t *traps,
cairo_trapezoid_t *traps,
int num_traps)
{
if (dst->type == CAIRO_SURFACE_TYPE_DRAWABLE

View file

@ -337,11 +337,11 @@ _det (double a, double b, double c, double d)
static int
_lines_intersect (cairo_line_t *l1, cairo_line_t *l2, cairo_fixed_t *y_intersection)
{
double dx1 = XFixedToDouble (l1->p1.x - l1->p2.x);
double dy1 = XFixedToDouble (l1->p1.y - l1->p2.y);
double dx1 = cairo_fixed_to_double (l1->p1.x - l1->p2.x);
double dy1 = cairo_fixed_to_double (l1->p1.y - l1->p2.y);
double dx2 = XFixedToDouble (l2->p1.x - l2->p2.x);
double dy2 = XFixedToDouble (l2->p1.y - l2->p2.y);
double dx2 = cairo_fixed_to_double (l2->p1.x - l2->p2.x);
double dy2 = cairo_fixed_to_double (l2->p1.y - l2->p2.y);
double l1_det, l2_det;
@ -374,14 +374,14 @@ _compute_x (cairo_line_t *line, cairo_fixed_t y)
static double
_compute_inverse_slope (cairo_line_t *l)
{
return (XFixedToDouble (l->p2.x - l->p1.x) /
XFixedToDouble (l->p2.y - l->p1.y));
return (_cairo_fixed_to_double (l->p2.x - l->p1.x) /
_cairo_fixed_to_double (l->p2.y - l->p1.y));
}
static double
_compute_x_intercept (cairo_line_t *l, double inverse_slope)
{
return XFixedToDouble (l->p1.x) - inverse_slope * XFixedToDouble (l->p1.y);
return _cairo_fixed_to_double (l->p1.x) - inverse_slope * _cairo_fixed_to_double (l->p1.y);
}
static int

View file

@ -446,13 +446,6 @@ cairo_surface_create_similar_solid (cairo_surface_t *other,
extern void __external_linkage
cairo_surface_destroy (cairo_surface_t *surface);
extern cairo_status_t __external_linkage
cairo_surface_put_image (cairo_surface_t *surface,
char *data,
int width,
int height,
int stride);
/* XXX: NYI
extern cairo_status_t __external_linkage
cairo_surface_clip_restore (cairo_surface_t *surface);

46
src/cairo_fixed.c Normal file
View file

@ -0,0 +1,46 @@
/*
* Copyright © 2003 USC, Information Sciences Institute
*
* 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"
cairo_fixed_t
_cairo_fixed_from_int (int i)
{
return i << 16;
}
cairo_fixed_t
_cairo_fixed_from_double (double d)
{
return (cairo_fixed_t) (d * 65536);
}
double
_cairo_fixed_to_double (cairo_fixed_t f)
{
return ((double) f) / 65536.0;
}

View file

@ -71,6 +71,7 @@ _cairo_font_fini (cairo_font_t *font)
if (font->xft_font)
XftFontClose (font->dpy, font->xft_font);
font->xft_font = NULL;
}

View file

@ -795,12 +795,21 @@ _cairo_gstate_close_path (cairo_gstate_t *gstate)
}
cairo_status_t
_cairo_gstate_current_point (cairo_gstate_t *gstate, double *x, double *y)
_cairo_gstate_current_point (cairo_gstate_t *gstate, double *x_ret, double *y_ret)
{
*x = gstate->current_pt.x;
*y = gstate->current_pt.y;
double x, y;
cairo_matrix_transform_point (&gstate->ctm_inverse, x, y);
if (gstate->has_current_pt) {
x = gstate->current_pt.x;
y = gstate->current_pt.y;
cairo_matrix_transform_point (&gstate->ctm_inverse, &x, &y);
} else {
x = 0.0;
y = 0.0;
}
*x_ret = x;
*y_ret = y;
return CAIRO_STATUS_SUCCESS;
}
@ -861,7 +870,7 @@ _cairo_gstate_stroke (cairo_gstate_t *gstate)
gstate->operator,
gstate->surface,
&traps);
/* restore the matrix originally in the source surface */
if (! gstate->source_is_solid)
cairo_surface_set_matrix (gstate->source, &user_to_source);
@ -944,20 +953,20 @@ _cairo_gstate_clip_and_composite_trapezoids (cairo_gstate_t *gstate,
cairo_surface_destroy (white);
} else {
double xoff, yoff;
int xoff, yoff;
if (traps->traps[0].left.p1.y < traps->traps[0].left.p2.y) {
xoff = traps->traps[0].left.p1.x;
yoff = traps->traps[0].left.p1.y;
xoff = _cairo_fixed_to_double (traps->traps[0].left.p1.x);
yoff = _cairo_fixed_to_double (traps->traps[0].left.p1.y);
} else {
xoff = traps->traps[0].left.p2.x;
yoff = traps->traps[0].left.p2.y;
xoff = _cairo_fixed_to_double (traps->traps[0].left.p2.x);
yoff = _cairo_fixed_to_double (traps->traps[0].left.p2.y);
}
_cairo_surface_composite_trapezoids (gstate->operator,
src, dst,
XFixedToDouble (xoff) - gstate->source_offset.x,
XFixedToDouble (yoff) - gstate->source_offset.y,
xoff - gstate->source_offset.x,
yoff - gstate->source_offset.y,
traps->traps,
traps->num_traps);
}
@ -1115,14 +1124,24 @@ _cairo_gstate_show_text (cairo_gstate_t *gstate, const unsigned char *utf8)
{
cairo_status_t status;
XftFont *xft_font;
double x, y;
cairo_matrix_t user_to_source, device_to_source;
if (gstate->has_current_pt == 0)
return CAIRO_STATUS_NO_CURRENT_POINT;
if (gstate->surface->dpy == 0)
return CAIRO_STATUS_SUCCESS;
/* XXX: I believe this is correct, but it would be much more clear
to have some explicit current_point accesor functions, (one for
user- and one for device-space). */
if (gstate->has_current_pt) {
x = gstate->current_pt.x;
y = gstate->current_pt.y;
} else {
x = 0;
y = 0;
cairo_matrix_transform_point (&gstate->ctm, &x, &y);
}
_cairo_font_resolve_xft_font (&gstate->font, gstate, &xft_font);
status = _cairo_gstate_ensure_source (gstate);
@ -1145,8 +1164,7 @@ _cairo_gstate_show_text (cairo_gstate_t *gstate, const unsigned char *utf8)
xft_font,
gstate->surface->picture,
0, 0,
gstate->current_pt.x,
gstate->current_pt.y,
x, y,
utf8,
strlen ((char *) utf8));
@ -1169,15 +1187,19 @@ _cairo_gstate_show_surface (cairo_gstate_t *gstate,
double device_x, device_y;
double device_width, device_height;
mask = cairo_surface_create_similar_solid (gstate->surface,
CAIRO_FORMAT_A8,
1, 1,
1.0, 1.0, 1.0,
gstate->alpha);
if (mask == NULL)
return CAIRO_STATUS_NO_MEMORY;
if (gstate->alpha != 1.0) {
mask = cairo_surface_create_similar_solid (gstate->surface,
CAIRO_FORMAT_A8,
1, 1,
1.0, 1.0, 1.0,
gstate->alpha);
if (mask == NULL)
return CAIRO_STATUS_NO_MEMORY;
cairo_surface_set_repeat (mask, 1);
cairo_surface_set_repeat (mask, 1);
} else {
mask = NULL;
}
cairo_surface_get_matrix (surface, &user_to_image);
cairo_matrix_multiply (&device_to_image, &gstate->ctm_inverse, &user_to_image);
@ -1187,8 +1209,7 @@ _cairo_gstate_show_surface (cairo_gstate_t *gstate,
cairo_matrix_invert (&image_to_user);
cairo_matrix_multiply (&image_to_device, &image_to_user, &gstate->ctm);
device_x = 0;
device_y = 0;
_cairo_gstate_current_point (gstate, &device_x, &device_y);
device_width = width;
device_height = height;
_cairo_matrix_transform_bounding_box (&image_to_device,
@ -1205,7 +1226,8 @@ _cairo_gstate_show_surface (cairo_gstate_t *gstate,
device_width,
device_height);
cairo_surface_destroy (mask);
if (mask)
cairo_surface_destroy (mask);
/* restore the matrix originally in the surface */
cairo_surface_set_matrix (surface, &user_to_image);

View file

@ -159,10 +159,10 @@ _cairo_path_bounds (cairo_path_t *path, double *x1, double *y1, double *x2, doub
return status;
}
*x1 = XFixedToDouble (bounder.min_x);
*y1 = XFixedToDouble (bounder.min_y);
*x2 = XFixedToDouble (bounder.max_x);
*y2 = XFixedToDouble (bounder.max_y);
*x1 = _cairo_fixed_to_double (bounder.min_x);
*y1 = _cairo_fixed_to_double (bounder.min_y);
*x2 = _cairo_fixed_to_double (bounder.max_x);
*y2 = _cairo_fixed_to_double (bounder.max_y);
_cairo_path_bounder_fini (&bounder);

View file

@ -252,15 +252,15 @@ _cairo_stroker_join (cairo_stroker_t *stroker, cairo_stroke_face_t *in, cairo_st
* device space
*/
/* outer point of incoming line face */
x1 = cairo_fixed_to_double (inpt->x);
y1 = cairo_fixed_to_double (inpt->y);
x1 = _cairo_fixed_to_double (inpt->x);
y1 = _cairo_fixed_to_double (inpt->y);
dx1 = in->usr_vector.x;
dy1 = in->usr_vector.y;
cairo_matrix_transform_distance (&gstate->ctm, &dx1, &dy1);
/* outer point of outgoing line face */
x2 = cairo_fixed_to_double (outpt->x);
y2 = cairo_fixed_to_double (outpt->y);
x2 = _cairo_fixed_to_double (outpt->x);
y2 = _cairo_fixed_to_double (outpt->y);
dx2 = out->usr_vector.x;
dy2 = out->usr_vector.y;
cairo_matrix_transform_distance (&gstate->ctm, &dx2, &dy2);
@ -283,8 +283,8 @@ _cairo_stroker_join (cairo_stroker_t *stroker, cairo_stroke_face_t *in, cairo_st
/*
* Draw the quadrilateral
*/
outer.x = cairo_double_to_fixed (mx);
outer.y = cairo_double_to_fixed (my);
outer.x = _cairo_fixed_from_double (mx);
outer.y = _cairo_fixed_from_double (my);
_cairo_polygon_init (&polygon);
_cairo_polygon_add_edge (&polygon, &in->pt, inpt);
_cairo_polygon_add_edge (&polygon, inpt, &outer);
@ -358,8 +358,8 @@ _cairo_stroker_cap (cairo_stroker_t *stroker, cairo_stroke_face_t *f)
dx *= gstate->line_width / 2.0;
dy *= gstate->line_width / 2.0;
cairo_matrix_transform_distance (&gstate->ctm, &dx, &dy);
fvector.dx = cairo_double_to_fixed (dx);
fvector.dy = cairo_double_to_fixed (dy);
fvector.dx = _cairo_fixed_from_double (dx);
fvector.dy = _cairo_fixed_from_double (dy);
occw.x = f->ccw.x + fvector.dx;
occw.y = f->ccw.y + fvector.dy;
ocw.x = f->cw.x + fvector.dx;
@ -390,8 +390,8 @@ _compute_face (cairo_point_t *pt, cairo_slope_t *slope, cairo_gstate_t *gstate,
XPointDouble usr_vector;
cairo_point_t offset_ccw, offset_cw;
line_dx = cairo_fixed_to_double (slope->dx);
line_dy = cairo_fixed_to_double (slope->dy);
line_dx = _cairo_fixed_to_double (slope->dx);
line_dy = _cairo_fixed_to_double (slope->dy);
/* faces are normal in user space, not device space */
cairo_matrix_transform_distance (&gstate->ctm_inverse, &line_dx, &line_dy);
@ -431,8 +431,8 @@ _compute_face (cairo_point_t *pt, cairo_slope_t *slope, cairo_gstate_t *gstate,
/* back to device space */
cairo_matrix_transform_distance (&gstate->ctm, &face_dx, &face_dy);
offset_ccw.x = cairo_double_to_fixed (face_dx);
offset_ccw.y = cairo_double_to_fixed (face_dy);
offset_ccw.x = _cairo_fixed_from_double (face_dx);
offset_ccw.y = _cairo_fixed_from_double (face_dy);
offset_cw.x = -offset_ccw.x;
offset_cw.y = -offset_ccw.y;
@ -533,8 +533,8 @@ _cairo_stroker_add_edge_dashed (void *closure, cairo_point_t *p1, cairo_point_t
int first = 1;
cairo_stroke_face_t sub_start, sub_end;
dx = cairo_fixed_to_double (p2->x - p1->x);
dy = cairo_fixed_to_double (p2->y - p1->y);
dx = _cairo_fixed_to_double (p2->x - p1->x);
dy = _cairo_fixed_to_double (p2->y - p1->y);
cairo_matrix_transform_distance (&gstate->ctm_inverse, &dx, &dy);
@ -549,8 +549,8 @@ _cairo_stroker_add_edge_dashed (void *closure, cairo_point_t *p1, cairo_point_t
dx2 = dx * (mag - remain)/mag;
dy2 = dy * (mag - remain)/mag;
cairo_matrix_transform_distance (&gstate->ctm, &dx2, &dy2);
fd2.x = cairo_double_to_fixed (dx2);
fd2.y = cairo_double_to_fixed (dy2);
fd2.x = _cairo_fixed_from_double (dx2);
fd2.y = _cairo_fixed_from_double (dy2);
fd2.x += p1->x;
fd2.y += p1->y;
/*

View file

@ -105,8 +105,8 @@ _cairo_pen_init (cairo_pen_t *pen, double radius, cairo_gstate_t *gstate)
double dy = radius * sin (reflect ? -theta : theta);
cairo_pen_vertex_t *v = &pen->vertex[i];
cairo_matrix_transform_distance (&gstate->ctm, &dx, &dy);
v->pt.x = cairo_double_to_fixed (dx);
v->pt.y = cairo_double_to_fixed (dy);
v->pt.x = _cairo_fixed_from_double (dx);
v->pt.y = _cairo_fixed_from_double (dy);
}
_cairo_pen_compute_slopes (pen);

View file

@ -166,8 +166,8 @@ _de_casteljau (cairo_spline_t *spline, cairo_spline_t *s1, cairo_spline_t *s2)
static double
_PointDistanceSquaredToPoint (cairo_point_t *a, cairo_point_t *b)
{
double dx = XFixedToDouble (b->x - a->x);
double dy = XFixedToDouble (b->y - a->y);
double dx = _cairo_fixed_to_double (b->x - a->x);
double dy = _cairo_fixed_to_double (b->y - a->y);
return dx*dx + dy*dy;
}
@ -190,14 +190,14 @@ _PointDistanceSquaredToSegment (cairo_point_t *p, cairo_point_t *p1, cairo_point
u = ((p - p1) . (p2 - p1)) / (||(p2 - p1)|| ^ 2);
*/
dx = XFixedToDouble (p2->x - p1->x);
dy = XFixedToDouble (p2->y - p1->y);
dx = _cairo_fixed_to_double (p2->x - p1->x);
dy = _cairo_fixed_to_double (p2->y - p1->y);
if (dx == 0 && dy == 0)
return _PointDistanceSquaredToPoint (p, p1);
pdx = XFixedToDouble (p->x - p1->x);
pdy = XFixedToDouble (p->y - p1->y);
pdx = _cairo_fixed_to_double (p->x - p1->x);
pdy = _cairo_fixed_to_double (p->y - p1->y);
u = (pdx * dx + pdy * dy) / (dx*dx + dy*dy);

View file

@ -57,6 +57,36 @@ static const XTransform CAIRO_XTRANSFORM_IDENTITY = {
#define CAIRO_SURFACE_RENDER_HAS_PICTURE_TRANSFORM(surface) CAIRO_SURFACE_RENDER_AT_LEAST((surface), 0, 6)
static IcFormat *
_create_icformat_for_visual (Visual *visual)
{
return IcFormatCreateMasks (32, 0,
visual->red_mask,
visual->green_mask,
visual->blue_mask);
}
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;
}
}
cairo_surface_t *
cairo_surface_create_for_drawable (Display *dpy,
Drawable drawable,
@ -72,8 +102,8 @@ cairo_surface_create_for_drawable (Display *dpy,
/* XXX: We should really get this value from somewhere like Xft.dpy */
surface->ppm = 3780;
surface->ref_count = 1;
surface->repeat = 0;
surface->dpy = dpy;
surface->image_data = NULL;
@ -91,47 +121,33 @@ cairo_surface_create_for_drawable (Display *dpy,
surface->render_minor = -1;
}
if (visual)
surface->icformat = _create_icformat_for_visual (visual);
else
surface->icformat = _create_icformat_for_format (format);
/* 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),
visual ?
XRenderFindVisualFormat (dpy, visual) :
XRenderFindStandardFormat (dpy, format),
0, NULL);
else
surface->picture = 0;
surface->ximage = 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? */
surface->width = 0;
surface->height = 0;
return surface;
}
slim_hidden_def(cairo_surface_create_for_drawable)
/* XXX: These definitions are 100% bogus. The problem that needs to be
fixed is that Ic needs to export a real API for passing in
formats. */
#define PICT_FORMAT(bpp,type,a,r,g,b) (((bpp) << 24) | \
((type) << 16) | \
((a) << 12) | \
((r) << 8) | \
((g) << 4) | \
((b)))
/*
* gray/color formats use a visual index instead of argb
*/
#define PICT_VISFORMAT(bpp,type,vi) (((bpp) << 24) | \
((type) << 16) | \
((vi)))
#define PICT_TYPE_A 1
#define PICT_TYPE_ARGB 2
#define PICT_FORMAT_COLOR(f) (PICT_FORMAT_TYPE(f) & 2)
/* 32bpp formats */
#define PICT_a8r8g8b8 PICT_FORMAT(32,PICT_TYPE_ARGB,8,8,8,8)
#define PICT_x8r8g8b8 PICT_FORMAT(32,PICT_TYPE_ARGB,0,8,8,8)
#define PICT_a8 PICT_FORMAT(8,PICT_TYPE_A,8,0,0,0)
#define PICT_a1 PICT_FORMAT(1,PICT_TYPE_A,1,0,0,0)
static int
cairo_format_bpp (cairo_format_t format)
{
@ -158,45 +174,30 @@ cairo_surface_create_for_image (char *data,
int stride)
{
cairo_surface_t *surface;
IcFormat icformat;
IcImage *image;
int bpp;
/* XXX: This all needs to change, (but IcFormatInit interface needs to change first) */
switch (format) {
case CAIRO_FORMAT_ARGB32:
IcFormatInit (&icformat, PICT_a8r8g8b8);
bpp = 32;
break;
case CAIRO_FORMAT_RGB24:
IcFormatInit (&icformat, PICT_x8r8g8b8);
bpp = 32;
break;
case CAIRO_FORMAT_A8:
IcFormatInit (&icformat, PICT_a8);
bpp = 8;
break;
case CAIRO_FORMAT_A1:
IcFormatInit (&icformat, PICT_a1);
bpp = 1;
break;
default:
return NULL;
}
surface = malloc (sizeof (cairo_surface_t));
if (surface == NULL)
return NULL;
surface->icformat = _create_icformat_for_format (format);
/* Assume a default until the user lets us know otherwise */
surface->ppm = 3780;
surface->ref_count = 1;
surface->repeat = 0;
surface->dpy = NULL;
surface->image_data = NULL;
image = IcImageCreateForData ((IcBits *) data, &icformat, width, height, cairo_format_bpp (format), stride);
if (image == NULL) {
surface->width = width;
surface->height = height;
surface->icimage = IcImageCreateForData ((IcBits *) data,
surface->icformat,
width, height,
cairo_format_bpp (format),
stride);
if (surface->icimage == NULL) {
free (surface);
return NULL;
}
@ -211,8 +212,7 @@ cairo_surface_create_for_image (char *data,
surface->render_minor = -1;
surface->picture = 0;
surface->icimage = image;
surface->ximage = NULL;
return surface;
}
@ -322,6 +322,9 @@ cairo_surface_destroy (cairo_surface_t *surface)
if (surface->picture)
XRenderFreePicture (surface->dpy, surface->picture);
if (surface->icformat)
IcFormatDestroy (surface->icformat);
if (surface->icimage)
IcImageDestroy (surface->icimage);
@ -345,17 +348,17 @@ _cairo_surface_ensure_gc (cairo_surface_t *surface)
surface->gc = XCreateGC (surface->dpy, surface->drawable, 0, NULL);
}
cairo_status_t
cairo_surface_put_image (cairo_surface_t *surface,
char *data,
int width,
int height,
int stride)
static cairo_status_t
cairo_x11_surface_put_image (cairo_surface_t *surface,
char *data,
int width,
int height,
int stride)
{
if (surface->picture) {
XImage *image;
unsigned bitmap_pad;
/* XXX: This is obviously bogus. depth needs to be figured out for real */
int depth = 32;
@ -386,16 +389,19 @@ cairo_surface_put_image (cairo_surface_t *surface,
} else {
/* XXX: Need to implement the IcImage method of setting a picture. memcpy? */
}
return CAIRO_STATUS_SUCCESS;
}
/* XXX: Symmetry demands an cairo_surface_get_image as well. */
void
_cairo_surface_pull_image (cairo_surface_t *surface)
{
/* XXX: NYI (Also needs support for pictures with external alpha.)
Window root_ignore;
int x_ignore, y_ignore, bwidth_ignore, depth_ignore;
if (surface == NULL)
return;
if (surface->type == CAIRO_SURFACE_TYPE_ICIMAGE)
return;
@ -404,46 +410,59 @@ _cairo_surface_pull_image (cairo_surface_t *surface)
surface->icimage = NULL;
}
_cairo_surface_ensure_GC (surface);
XGetGeometry(surface->dpy,
surface->drawable,
&root_ignore, &x_ignore, &y_ignore,
&surface->width, &surface->height,
&bwidth_ignore, &depth_ignore);
surface->ximage = XGetImage (surface->dpy,
surface->drawable,
surface->gc,
0, 0,
width, height,
surface->width, surface->height,
AllPlanes, ZPixmap);
surface->icimage = IcImageCreateForData ((IcBits *)(surface->ximage->data),
surface->icformat,
surface->ximage->width,
surface->ximage->height,
surface->ximage->bits_per_pixel,
surface->ximage->bytes_per_line);
IcImageSetRepeat (surface->icimage, surface->repeat);
/* XXX: Evil cast here... */
IcImageSetTransform (surface->icimage, (IcTransform *) &(surface->xtransform));
surface->icimage = IcImageCreateForData (image->data,
IcFormat *format,
int width, int height,
int bpp, int stride);
*/
/* XXX: Add support here for pictures with external alpha. */
}
void
_cairo_surface_push_image (cairo_surface_t *surface)
{
/* XXX: NYI
if (surface == NULL)
return;
if (surface->type == CAIRO_SURFACE_TYPE_ICIMAGE)
return;
if (surface->ximage == NULL)
return;
_cairo_surface_ensure_GC (surface);
_cairo_surface_ensure_gc (surface);
XPutImage (surface->dpy,
surface->drawable,
surface->gc,
surface->ximage,
0, 0,
0, 0,
width, height);
surface->width,
surface->height);
* Foolish XDestroyImage thinks it can free my data, but I won't
stand for it. *
/* Foolish XDestroyImage thinks it can free my data, but I won't
stand for it. */
surface->ximage->data = NULL;
XDestroyImage(surface->ximage);
surface->ximage = NULL;
*/
}
/* XXX: We may want to move to projective matrices at some point. If
@ -487,13 +506,13 @@ cairo_surface_get_matrix (cairo_surface_t *surface, cairo_matrix_t *matrix)
{
XTransform *xtransform = &surface->xtransform;
matrix->m[0][0] = XFixedToDouble (xtransform->matrix[0][0]);
matrix->m[1][0] = XFixedToDouble (xtransform->matrix[0][1]);
matrix->m[2][0] = XFixedToDouble (xtransform->matrix[0][2]);
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] = XFixedToDouble (xtransform->matrix[1][0]);
matrix->m[1][1] = XFixedToDouble (xtransform->matrix[1][1]);
matrix->m[2][1] = XFixedToDouble (xtransform->matrix[1][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;
}
@ -554,6 +573,8 @@ cairo_surface_clip_restore (cairo_surface_t *surface);
cairo_status_t
cairo_surface_set_repeat (cairo_surface_t *surface, int repeat)
{
surface->repeat = repeat;
if (surface->picture) {
unsigned long mask;
XRenderPictureAttributes pa;
@ -604,11 +625,11 @@ _cairo_surface_composite (cairo_operator_t operator,
cairo_surface_get_matrix (src, &matrix);
cairo_surface_set_matrix (src_on_server, &matrix);
cairo_surface_put_image (src_on_server,
(char *) IcImageGetData (src->icimage),
IcImageGetWidth (src->icimage),
IcImageGetHeight (src->icimage),
IcImageGetStride (src->icimage));
cairo_x11_surface_put_image (src_on_server,
(char *) IcImageGetData (src->icimage),
IcImageGetWidth (src->icimage),
IcImageGetHeight (src->icimage),
IcImageGetStride (src->icimage));
}
XRenderComposite (dst->dpy, operator,
@ -623,7 +644,8 @@ _cairo_surface_composite (cairo_operator_t operator,
} else {
_cairo_surface_pull_image (src);
_cairo_surface_pull_image (mask);
if (mask)
_cairo_surface_pull_image (mask);
_cairo_surface_pull_image (dst);
IcComposite (operator,
@ -665,6 +687,9 @@ _cairo_surface_fill_rectangles (cairo_surface_t *surface,
cairo_rectangle_t *rects,
int num_rects)
{
if (num_rects == 0)
return;
if (surface->type == CAIRO_SURFACE_TYPE_DRAWABLE
&& CAIRO_SURFACE_RENDER_HAS_FILL_RECTANGLE (surface)) {
@ -702,7 +727,7 @@ _cairo_surface_composite_trapezoids (cairo_operator_t operator,
cairo_surface_t *dst,
int xSrc,
int ySrc,
const cairo_trapezoid_t *traps,
cairo_trapezoid_t *traps,
int num_traps)
{
if (dst->type == CAIRO_SURFACE_TYPE_DRAWABLE

View file

@ -337,11 +337,11 @@ _det (double a, double b, double c, double d)
static int
_lines_intersect (cairo_line_t *l1, cairo_line_t *l2, cairo_fixed_t *y_intersection)
{
double dx1 = XFixedToDouble (l1->p1.x - l1->p2.x);
double dy1 = XFixedToDouble (l1->p1.y - l1->p2.y);
double dx1 = cairo_fixed_to_double (l1->p1.x - l1->p2.x);
double dy1 = cairo_fixed_to_double (l1->p1.y - l1->p2.y);
double dx2 = XFixedToDouble (l2->p1.x - l2->p2.x);
double dy2 = XFixedToDouble (l2->p1.y - l2->p2.y);
double dx2 = cairo_fixed_to_double (l2->p1.x - l2->p2.x);
double dy2 = cairo_fixed_to_double (l2->p1.y - l2->p2.y);
double l1_det, l2_det;
@ -374,14 +374,14 @@ _compute_x (cairo_line_t *line, cairo_fixed_t y)
static double
_compute_inverse_slope (cairo_line_t *l)
{
return (XFixedToDouble (l->p2.x - l->p1.x) /
XFixedToDouble (l->p2.y - l->p1.y));
return (_cairo_fixed_to_double (l->p2.x - l->p1.x) /
_cairo_fixed_to_double (l->p2.y - l->p1.y));
}
static double
_compute_x_intercept (cairo_line_t *l, double inverse_slope)
{
return XFixedToDouble (l->p1.x) - inverse_slope * XFixedToDouble (l->p1.y);
return _cairo_fixed_to_double (l->p1.x) - inverse_slope * _cairo_fixed_to_double (l->p1.y);
}
static int

View file

@ -94,9 +94,6 @@ typedef int32_t cairo_fixed_16_16_t;
/* The common 16.16 format gets a shorter name */
typedef cairo_fixed_16_16_t cairo_fixed_t;
#define cairo_double_to_fixed(f) ((cairo_fixed_t) ((f) * 65536))
#define cairo_fixed_to_double(d) (((double) (d)) / 65536)
typedef struct cairo_point {
cairo_fixed_t x;
cairo_fixed_t y;
@ -241,10 +238,14 @@ typedef enum cairo_surface_type {
} cairo_surface_type_t;
struct cairo_surface {
int width;
int height;
char *image_data;
double ppm;
unsigned int ref_count;
int repeat;
cairo_surface_type_t type;
XTransform xtransform;
@ -259,9 +260,11 @@ struct cairo_surface {
int render_minor;
Picture picture;
XImage *ximage;
/* For TYPE_ICIMAGE */
IcImage *icimage;
IcFormat *icformat;
};
/* XXX: Right now, the cairo_color structure puts unpremultiplied
@ -379,6 +382,16 @@ typedef struct cairo_stroke_face {
cairo_point_double_t usr_vector;
} cairo_stroke_face_t;
/* cairo_fixed.c */
extern cairo_fixed_t __internal_linkage
_cairo_fixed_from_int (int i);
extern cairo_fixed_t __internal_linkage
_cairo_fixed_from_double (double d);
extern double __internal_linkage
_cairo_fixed_to_double (cairo_fixed_t f);
/* cairo_gstate.c */
extern cairo_gstate_t * __internal_linkage
_cairo_gstate_create (void);
@ -711,13 +724,13 @@ _cairo_surface_fill_rectangles (cairo_surface_t *surface,
int num_rects);
extern void __internal_linkage
_cairo_surface_composite_trapezoids (cairo_operator_t operator,
cairo_surface_t *src,
cairo_surface_t *dst,
int xSrc,
int ySrc,
const cairo_trapezoid_t *traps,
int ntraps);
_cairo_surface_composite_trapezoids (cairo_operator_t operator,
cairo_surface_t *src,
cairo_surface_t *dst,
int xSrc,
int ySrc,
cairo_trapezoid_t *traps,
int ntraps);
extern void __internal_linkage
_cairo_surface_pull_image (cairo_surface_t *surface);