Made all changes necessary to abandon the Xc library, (sucking the functionality up into cairo_surface_t instead). Eliminated most of the remaining X datatypes (XFixed, XPointFixed, XLineFixed, XTrapezoid). Fixed some numerical problems relating to pen initialization and intersection calculation.

This commit is contained in:
Carl Worth 2003-07-30 08:30:50 +00:00
parent 2026b1c44a
commit e97cfd5eae
33 changed files with 1930 additions and 968 deletions

View file

@ -1,3 +1,74 @@
2003-07-30 Carl Worth <cworth@isi.edu>
* src/cairo_traps.c (_line_segs_intersect_ceil): Add one more
conditional intersect to push past some fill bugs.
* src/cairo_surface.c (cairo_surface_create_for_drawable):
(cairo_surface_create_for_image):
(cairo_surface_put_image):
(_cairo_surface_pull_image):
(_cairo_surface_push_image):
(cairo_surface_set_matrix):
(cairo_surface_get_matrix):
(cairo_surface_set_repeat):
(_cairo_surface_composite):
(_cairo_surface_fill_rectangle):
(_cairo_surface_fill_rectangles):
(_cairo_surface_composite_trapezoids): Absorb all functionality
previously in the Xc library.
* src/cairo_pen.c (_cairo_pen_init): Don't store floating point
theta in the pen. Instead, sort vertices by fixed point slope
comparisons.
(_cairo_pen_add_points): Fixed to remove duplicate pen vertices
appearing at beginning and end of vertex array.
(_pen_vertex_compare): New fixed-point "angle" comparison for pen
vertices. A bit trickier than before, but much more accurate.
* src/cairo_path_stroke.c (_cairo_stroker_face_clockwise): Share
clockwise calculation with other modules.
* src/cairo_path_bounds.c:
* src/cairo_path_fill.c:
* src/cairo_path_stroke.c:
* src/cairo_pen.c:
* src/cairo_polygon.c:
* src/cairo_spline.c:
* src/cairo_traps.c:
* src/cairo_path.c: Replaced all references to
XFixed, XPointFixed, XLineFixed, and XTrapezoid with new
cairo_fixed_t, cairo_point_t, cairo_line_t, and cairo_trapezoid_t.
* src/cairo_path.c: (_cairo_path_interpret): Made the path
interpreter callback names consistent, (eg. add_edge rather than
AddEdge).
* src/cairo_gstate.c (_cairo_gstate_text_extents): Now silently
exits for a non X surface, (avoids a crash until we can implement
the libic text backend).
* src/cairo_gstate.c (_cairo_gstate_end_group):
(_cairo_gstate_clip_and_composite_trapezoids):
(_cairo_gstate_show_surface): Replaced all XcCalls with
corresponding cairo_surface_calls.
* src/cairo_gstate.c (_cairo_gstate_transform_point):
(_cairo_gstate_transform_font):
(_cairo_gstate_text_extents): Renamed from the garbled names
(eg. cairo_gstateransform_point) leftover from the great renaming.
* src/cairo_color.c (_cairo_color_set_rgb): Reworked cairo_color_t
to eliminate reference to an XcColor object.
* src/cairo.h: Dropped include of <Xc.h>, added
<X11/extensions/Xrender.h>, <fontconfig/fontconfig.h>, and <ic.h>
* src/cairo.c (cairo_get_fill_rule): Added missing cairo_get_fill_rule.
* configure.in (PKG_CHECK_MODULES): Drops xc, add libic
* cairo.pc.in (Requires): Drop xc, add libic.
2003-07-25 Carl Worth <cworth@isi.edu>
* src/cairo_traps.c (_line_segs_intersect_ceil): We don't need a

View file

@ -7,7 +7,7 @@ Name: cairo
Description: Multi-platform 2D graphics library
Version: @VERSION@
Requires: xc xft
Requires: libic xft
Libs: -L${libdir} -lcairo -lm
Cflags: -I${includedir}

View file

@ -24,7 +24,7 @@ AC_SUBST(VERSION_INFO)
dnl ===========================================================================
XC_REQUIRED=0.1.0
LIBIC_REQUIRES=0.1.0
XFT_REQUIRED=2.1.1
dnl ===========================================================================
@ -45,7 +45,7 @@ AC_PATH_XTRA
dnl ===========================================================================
PKG_CHECK_MODULES(CAIRO, xc >= $XC_REQUIRED xft >= $XFT_REQUIRED)
PKG_CHECK_MODULES(CAIRO, xft >= $XFT_REQUIRED, libic >= $LIBIC_REQUIRED)
AC_SUBST(CAIRO_CFLAGS)
AC_SUBST(CAIRO_LIBS)

View file

@ -2,23 +2,23 @@ lib_LTLIBRARIES = libcairo.la
include_HEADERS = cairo.h
libcairo_la_SOURCES = \
cairo.h \
cairo.c \
cairoint.h \
cairo.h \
cairo_color.c \
cairo_font.c \
cairo_gstate.c \
cairo_matrix.c \
cairo_misc.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_traps.c \
cairoint.h
libcairo_la_LDFLAGS = -version-info @VERSION_INFO@

View file

@ -27,10 +27,13 @@
#include "cairoint.h"
static cairo_color_t CAIRO_COLOR_DEFAULT = { 1.0, 1.0, 1.0, 1.0, {0xffff, 0xffff, 0xffff, 0xffff}};
static cairo_color_t CAIRO_COLOR_DEFAULT = {
1.0, 1.0, 1.0, 1.0,
0xffff, 0xffff, 0xffff, 0xffff
};
static void
_cairo_color_compute_xc_color (cairo_color_t *color);
_cairo_color_compute_shorts (cairo_color_t *color);
void
_cairo_color_init (cairo_color_t *color)
@ -44,31 +47,22 @@ _cairo_color_fini (cairo_color_t *color)
/* Nothing to do here */
}
static void
_cairo_color_compute_xc_color (cairo_color_t *color)
{
color->xc_color.red = color->red * color->alpha * 0xffff;
color->xc_color.green = color->green * color->alpha * 0xffff;
color->xc_color.blue = color->blue * color->alpha * 0xffff;
color->xc_color.alpha = color->alpha * 0xffff;
}
void
_cairo_color_set_rgb (cairo_color_t *color, double red, double green, double blue)
{
color->red = red;
color->red = red;
color->green = green;
color->blue = blue;
color->blue = blue;
_cairo_color_compute_xc_color (color);
_cairo_color_compute_shorts (color);
}
void
_cairo_color_get_rgb (cairo_color_t *color, double *red, double *green, double *blue)
{
*red = color->red;
*red = color->red;
*green = color->green;
*blue = color->blue;
*blue = color->blue;
}
void
@ -76,5 +70,15 @@ _cairo_color_set_alpha (cairo_color_t *color, double alpha)
{
color->alpha = alpha;
_cairo_color_compute_xc_color (color);
_cairo_color_compute_shorts (color);
}
static void
_cairo_color_compute_shorts (cairo_color_t *color)
{
color->red_short = (color->red * color->alpha) * 0xffff;
color->green_short = (color->green * color->alpha) * 0xffff;
color->blue_short = (color->blue * color->alpha) * 0xffff;
color->alpha_short = color->alpha * 0xffff;
}

View file

@ -154,7 +154,7 @@ _cairo_font_resolve_xft_font (cairo_font_t *font, cairo_gstate_t *gstate, XftFon
FcPatternAddMatrix (pattern, "matrix", &fc_matrix);
/* XXX: Need to abandon Xft and use Xc instead */
/* XXX: Need to make a generic (non-Xft) backend for text. */
/* When I do that I can throw away these Display pointers */
font->dpy = gstate->surface->dpy;
match = XftFontMatch (font->dpy, DefaultScreen (font->dpy), pattern, &result);

View file

@ -227,12 +227,12 @@ _cairo_gstate_begin_group (cairo_gstate_t *gstate)
_cairo_color_init (&clear);
_cairo_color_set_alpha (&clear, 0);
XcFillRectangle (CAIRO_OPERATOR_SRC,
_cairo_surface_get_xc_surface (gstate->surface),
&clear.xc_color,
0, 0,
_cairo_surface_get_width (gstate->surface),
_cairo_surface_get_height (gstate->surface));
_cairo_surface_fill_rectangle (gstate->surface,
CAIRO_OPERATOR_SRC,
&clear,
0, 0,
_cairo_surface_get_width (gstate->surface),
_cairo_surface_get_height (gstate->surface));
return CAIRO_STATUS_SUCCESS;
}
@ -259,15 +259,15 @@ _cairo_gstate_end_group (cairo_gstate_t *gstate)
* XXX: This could be made much more efficient by using
_cairo_surface_get_damaged_width/Height if cairo_surface_t actually kept
track of such informaton. *
XcComposite (gstate->operator,
_cairo_surface_get_xc_surface (gstate->surface),
_cairo_surface_get_xc_surface (&mask),
_cairo_surface_get_xc_surface (gstate->parent_surface),
0, 0,
0, 0,
0, 0,
_cairo_surface_get_width (gstate->surface),
_cairo_surface_get_height (gstate->surface));
_cairo_surface_composite (gstate->operator,
gstate->surface,
mask,
gstate->parent_surface,
0, 0,
0, 0,
0, 0,
_cairo_surface_get_width (gstate->surface),
_cairo_surface_get_height (gstate->surface));
_cairo_surface_fini (&mask);
@ -415,6 +415,12 @@ _cairo_gstate_set_fill_rule (cairo_gstate_t *gstate, cairo_fill_rule_t fill_rule
return CAIRO_STATUS_SUCCESS;
}
cairo_status_t
_cairo_gstate_get_fill_rule (cairo_gstate_t *gstate)
{
return gstate->fill_rule;
}
cairo_status_t
_cairo_gstate_set_line_width (cairo_gstate_t *gstate, double width)
{
@ -495,7 +501,7 @@ _cairo_gstate_get_miter_limit (cairo_gstate_t *gstate)
}
cairo_status_t
cairo_gstate_translate (cairo_gstate_t *gstate, double tx, double ty)
_cairo_gstate_translate (cairo_gstate_t *gstate, double tx, double ty)
{
cairo_matrix_t tmp;
@ -597,7 +603,7 @@ _cairo_gstate_identity_matrix (cairo_gstate_t *gstate)
}
cairo_status_t
cairo_gstateransform_point (cairo_gstate_t *gstate, double *x, double *y)
_cairo_gstate_transform_point (cairo_gstate_t *gstate, double *x, double *y)
{
cairo_matrix_transform_point (&gstate->ctm, x, y);
@ -605,7 +611,7 @@ cairo_gstateransform_point (cairo_gstate_t *gstate, double *x, double *y)
}
cairo_status_t
cairo_gstateransform_distance (cairo_gstate_t *gstate, double *dx, double *dy)
_cairo_gstate_transform_distance (cairo_gstate_t *gstate, double *dx, double *dy)
{
cairo_matrix_transform_distance (&gstate->ctm, dx, dy);
@ -760,6 +766,17 @@ _cairo_gstate_rel_curve_to (cairo_gstate_t *gstate,
return status;
}
/* XXX: NYI
cairo_status_t
_cairo_gstate_stroke_path (cairo_gstate_t *gstate)
{
cairo_status_t status;
_cairo_pen_init (&gstate
return CAIRO_STATUS_SUCCESS;
}
*/
cairo_status_t
_cairo_gstate_close_path (cairo_gstate_t *gstate)
{
@ -823,12 +840,12 @@ _cairo_gstate_clip_and_composite_trapezoids (cairo_gstate_t *gstate,
cairo_surface_t *dst,
cairo_traps_t *traps)
{
if (traps->num_xtraps == 0)
if (traps->num_traps == 0)
return CAIRO_STATUS_SUCCESS;
if (gstate->clip.surface) {
XFixed xoff, yoff;
XTrapezoid *t;
cairo_fixed_t xoff, yoff;
cairo_trapezoid_t *t;
int i;
cairo_surface_t *intermediate, *white;
@ -844,12 +861,13 @@ _cairo_gstate_clip_and_composite_trapezoids (cairo_gstate_t *gstate,
gstate->clip.height,
0.0, 0.0, 0.0, 0.0);
/* Ugh. The Xc/ (Render) interface doesn't allow an offset for
the trapezoids. Need to manually shift all the coordinates
to align with the offset origin of the clip surface. */
/* Ugh. The cairo_composite/(Render) interface doesn't allow
an offset for the trapezoids. Need to manually shift all
the coordinates to align with the offset origin of the clip
surface. */
xoff = XDoubleToFixed (gstate->clip.x);
yoff = XDoubleToFixed (gstate->clip.y);
for (i=0, t=traps->xtraps; i < traps->num_xtraps; i++, t++) {
for (i=0, t=traps->traps; i < traps->num_traps; i++, t++) {
t->top -= yoff;
t->bottom -= yoff;
t->left.p1.x -= xoff;
@ -862,49 +880,45 @@ _cairo_gstate_clip_and_composite_trapezoids (cairo_gstate_t *gstate,
t->right.p2.y -= yoff;
}
XcCompositeTrapezoids (CAIRO_OPERATOR_ADD,
white->xc_surface,
intermediate->xc_surface,
0, 0,
traps->xtraps,
traps->num_xtraps);
XcComposite (CAIRO_OPERATOR_IN,
gstate->clip.surface->xc_surface,
NULL,
intermediate->xc_surface,
0, 0, 0, 0, 0, 0,
gstate->clip.width, gstate->clip.height);
XcComposite (operator,
src->xc_surface,
intermediate->xc_surface,
dst->xc_surface,
0, 0,
0, 0,
gstate->clip.x,
gstate->clip.y,
gstate->clip.width,
gstate->clip.height);
_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);
cairo_surface_destroy (intermediate);
cairo_surface_destroy (white);
} else {
double xoff, yoff;
if (traps->xtraps[0].left.p1.y < traps->xtraps[0].left.p2.y) {
xoff = traps->xtraps[0].left.p1.x;
yoff = traps->xtraps[0].left.p1.y;
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;
} else {
xoff = traps->xtraps[0].left.p2.x;
yoff = traps->xtraps[0].left.p2.y;
xoff = traps->traps[0].left.p2.x;
yoff = traps->traps[0].left.p2.y;
}
XcCompositeTrapezoids (gstate->operator,
src->xc_surface,
dst->xc_surface,
XFixedToDouble (xoff) - gstate->pattern_offset.x,
XFixedToDouble (yoff) - gstate->pattern_offset.y,
traps->xtraps,
traps->num_xtraps);
_cairo_surface_composite_trapezoids (gstate->operator,
src, dst,
XFixedToDouble (xoff) - gstate->pattern_offset.x,
XFixedToDouble (yoff) - gstate->pattern_offset.y,
traps->traps,
traps->num_traps);
}
return CAIRO_STATUS_SUCCESS;
@ -996,28 +1010,30 @@ _cairo_gstate_scale_font (cairo_gstate_t *gstate, double scale)
}
cairo_status_t
cairo_gstateransform_font (cairo_gstate_t *gstate,
double a, double b,
double c, double d)
_cairo_gstate_transform_font (cairo_gstate_t *gstate,
double a, double b,
double c, double d)
{
return cairo_font_transform (&gstate->font,
a, b, c, d);
}
cairo_status_t
cairo_gstateext_extents (cairo_gstate_t *gstate,
const unsigned char *utf8,
double *x, double *y,
double *width, double *height,
double *dx, double *dy)
_cairo_gstate_text_extents (cairo_gstate_t *gstate,
const unsigned char *utf8,
double *x, double *y,
double *width, double *height,
double *dx, double *dy)
{
XftFont *xft_font;
XGlyphInfo extents;
if (gstate->surface->dpy == 0)
return CAIRO_STATUS_SUCCESS;
_cairo_font_resolve_xft_font (&gstate->font, gstate, &xft_font);
/* XXX: Need to abandon Xft and use Xc instead */
/* (until I do, this call will croak on IcImage cairo_surface_ts */
/* XXX: Need to make a generic (non-Xft) backend for text. */
XftTextExtentsUtf8 (gstate->surface->dpy,
xft_font,
utf8,
@ -1050,14 +1066,12 @@ _cairo_gstate_show_text (cairo_gstate_t *gstate, const unsigned char *utf8)
_cairo_font_resolve_xft_font (&gstate->font, gstate, &xft_font);
/* XXX: Need to abandon Xft and use Xc instead */
/* (until I do, this call will croak on IcImage cairo_surface_ts */
/* (also, this means text clipping isn't working. Basically text is broken.) */
/* XXX: Need to make a generic (non-Xft) backend for text. */
XftTextRenderUtf8 (gstate->surface->dpy,
gstate->operator,
_cairo_surface_get_picture (gstate->solid),
gstate->solid->picture,
xft_font,
_cairo_surface_get_picture (gstate->surface),
gstate->surface->picture,
0, 0,
gstate->current_pt.x,
gstate->current_pt.y,
@ -1107,15 +1121,13 @@ _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. */
XcComposite (gstate->operator,
surface->xc_surface,
mask->xc_surface,
gstate->surface->xc_surface,
device_x, device_y,
0, 0,
device_x, device_y,
device_width,
device_height);
_cairo_surface_composite (gstate->operator,
surface, mask, gstate->surface,
device_x, device_y,
0, 0,
device_x, device_y,
device_width,
device_height);
cairo_surface_destroy (mask);

View file

@ -30,10 +30,10 @@
typedef struct cairo_path_bounder {
int has_pt;
XFixed min_x;
XFixed min_y;
XFixed max_x;
XFixed max_y;
cairo_fixed_t min_x;
cairo_fixed_t min_y;
cairo_fixed_t max_x;
cairo_fixed_t max_y;
} cairo_path_bounder_t;
static void
@ -43,14 +43,15 @@ static void
_cairo_path_bounder_fini (cairo_path_bounder_t *bounder);
static cairo_status_t
_cairo_path_bounder_add_point (cairo_path_bounder_t *bounder, XPointFixed *pt);
_cairo_path_bounder_add_point (cairo_path_bounder_t *bounder, cairo_point_t *pt);
static cairo_status_t
_cairo_path_bounder_add_edge (void *closure, XPointFixed *p1, XPointFixed *p2);
_cairo_path_bounder_add_edge (void *closure, cairo_point_t *p1, cairo_point_t *p2);
static cairo_status_t
_cairo_path_bounder_add_spline (void *closure,
XPointFixed *a, XPointFixed *b, XPointFixed *c, XPointFixed *d);
cairo_point_t *a, cairo_point_t *b,
cairo_point_t *c, cairo_point_t *d);
static cairo_status_t
_cairo_path_bounder_done_sub_path (void *closure, cairo_sub_path_done_t done);
@ -71,7 +72,7 @@ _cairo_path_bounder_fini (cairo_path_bounder_t *bounder)
}
static cairo_status_t
_cairo_path_bounder_add_point (cairo_path_bounder_t *bounder, XPointFixed *pt)
_cairo_path_bounder_add_point (cairo_path_bounder_t *bounder, cairo_point_t *pt)
{
if (bounder->has_pt) {
if (pt->x < bounder->min_x)
@ -98,7 +99,7 @@ _cairo_path_bounder_add_point (cairo_path_bounder_t *bounder, XPointFixed *pt)
}
static cairo_status_t
_cairo_path_bounder_add_edge (void *closure, XPointFixed *p1, XPointFixed *p2)
_cairo_path_bounder_add_edge (void *closure, cairo_point_t *p1, cairo_point_t *p2)
{
cairo_path_bounder_t *bounder = closure;
@ -110,7 +111,8 @@ _cairo_path_bounder_add_edge (void *closure, XPointFixed *p1, XPointFixed *p2)
static cairo_status_t
_cairo_path_bounder_add_spline (void *closure,
XPointFixed *a, XPointFixed *b, XPointFixed *c, XPointFixed *d)
cairo_point_t *a, cairo_point_t *b,
cairo_point_t *c, cairo_point_t *d)
{
cairo_path_bounder_t *bounder = closure;

View file

@ -41,10 +41,12 @@ static void
_cairo_filler_fini (cairo_filler_t *filler);
static cairo_status_t
_cairo_filler_add_edge (void *closure, XPointFixed *p1, XPointFixed *p2);
_cairo_filler_add_edge (void *closure, cairo_point_t *p1, cairo_point_t *p2);
static cairo_status_t
_cairo_filler_add_spline (void *closure, XPointFixed *a, XPointFixed *b, XPointFixed *c, XPointFixed *d);
_cairo_filler_add_spline (void *closure,
cairo_point_t *a, cairo_point_t *b,
cairo_point_t *c, cairo_point_t *d);
static cairo_status_t
_cairo_filler_done_sub_path (void *closure, cairo_sub_path_done_t done);
@ -68,7 +70,7 @@ _cairo_filler_fini (cairo_filler_t *filler)
}
static cairo_status_t
_cairo_filler_add_edge (void *closure, XPointFixed *p1, XPointFixed *p2)
_cairo_filler_add_edge (void *closure, cairo_point_t *p1, cairo_point_t *p2)
{
cairo_filler_t *filler = closure;
cairo_polygon_t *polygon = &filler->polygon;
@ -77,7 +79,9 @@ _cairo_filler_add_edge (void *closure, XPointFixed *p1, XPointFixed *p2)
}
static cairo_status_t
_cairo_filler_add_spline (void *closure, XPointFixed *a, XPointFixed *b, XPointFixed *c, XPointFixed *d)
_cairo_filler_add_spline (void *closure,
cairo_point_t *a, cairo_point_t *b,
cairo_point_t *c, cairo_point_t *d)
{
int i;
cairo_status_t status = CAIRO_STATUS_SUCCESS;

View file

@ -49,13 +49,15 @@ static void
_cairo_stroker_fini (cairo_stroker_t *stroker);
static cairo_status_t
_cairo_stroker_add_edge (void *closure, XPointFixed *p1, XPointFixed *p2);
_cairo_stroker_add_edge (void *closure, cairo_point_t *p1, cairo_point_t *p2);
static cairo_status_t
_cairo_stroker_add_edge_dashed (void *closure, XPointFixed *p1, XPointFixed *p2);
_cairo_stroker_add_edge_dashed (void *closure, cairo_point_t *p1, cairo_point_t *p2);
static cairo_status_t
_cairo_stroker_add_spline (void *closure, XPointFixed *a, XPointFixed *b, XPointFixed *c, XPointFixed *d);
_cairo_stroker_add_spline (void *closure,
cairo_point_t *a, cairo_point_t *b,
cairo_point_t *c, cairo_point_t *d);
static cairo_status_t
_cairo_stroker_done_sub_path (void *closure, cairo_sub_path_done_t done);
@ -64,7 +66,7 @@ static cairo_status_t
_cairo_stroker_done_path (void *closure);
static void
_translate_point (XPointFixed *pt, XPointFixed *offset);
_translate_point (cairo_point_t *pt, cairo_point_t *offset);
static int
_cairo_stroker_face_clockwise (cairo_stroke_face_t *in, cairo_stroke_face_t *out);
@ -125,7 +127,7 @@ _cairo_stroker_fini (cairo_stroker_t *stroker)
}
static void
_translate_point (XPointFixed *pt, XPointFixed *offset)
_translate_point (cairo_point_t *pt, cairo_point_t *offset)
{
pt->x += offset->x;
pt->y += offset->y;
@ -134,14 +136,12 @@ _translate_point (XPointFixed *pt, XPointFixed *offset)
static int
_cairo_stroker_face_clockwise (cairo_stroke_face_t *in, cairo_stroke_face_t *out)
{
XPointDouble d_in, d_out;
cairo_slope_t in_slope, out_slope;
d_in.x = XFixedToDouble (in->cw.x - in->pt.x);
d_in.y = XFixedToDouble (in->cw.y - in->pt.y);
d_out.x = XFixedToDouble (out->cw.x - out->pt.x);
d_out.y = XFixedToDouble (out->cw.y - out->pt.y);
_cairo_slope_init (&in_slope, &in->pt, &in->cw);
_cairo_slope_init (&out_slope, &out->pt, &out->cw);
return d_out.y * d_in.x > d_in.y * d_out.x;
return _cairo_slope_clockwise (&in_slope, &out_slope);
}
static cairo_status_t
@ -150,7 +150,7 @@ _cairo_stroker_join (cairo_stroker_t *stroker, cairo_stroke_face_t *in, cairo_st
cairo_status_t status;
cairo_gstate_t *gstate = stroker->gstate;
int clockwise = _cairo_stroker_face_clockwise (out, in);
XPointFixed *inpt, *outpt;
cairo_point_t *inpt, *outpt;
if (in->cw.x == out->cw.x
&& in->cw.y == out->cw.y
@ -171,7 +171,7 @@ _cairo_stroker_join (cairo_stroker_t *stroker, cairo_stroke_face_t *in, cairo_st
case CAIRO_LINE_JOIN_ROUND: {
int i;
int start, step, stop;
XPointFixed tri[3], initial, final;
cairo_point_t tri[3], initial, final;
cairo_pen_t *pen = &gstate->pen_regular;
tri[0] = in->pt;
@ -219,7 +219,7 @@ _cairo_stroker_join (cairo_stroker_t *stroker, cairo_stroke_face_t *in, cairo_st
XDouble x1, y1, x2, y2;
XDouble mx, my;
XDouble dx1, dx2, dy1, dy2;
XPointFixed outer;
cairo_point_t outer;
x1 = XFixedToDouble (inpt->x);
y1 = XFixedToDouble (inpt->y);
@ -256,7 +256,7 @@ _cairo_stroker_join (cairo_stroker_t *stroker, cairo_stroke_face_t *in, cairo_st
/* fall through ... */
}
case CAIRO_LINE_JOIN_BEVEL: {
XPointFixed tri[3];
cairo_point_t tri[3];
tri[0] = in->pt;
tri[1] = *inpt;
tri[2] = *outpt;
@ -279,8 +279,8 @@ _cairo_stroker_cap (cairo_stroker_t *stroker, cairo_stroke_face_t *f)
case CAIRO_LINE_CAP_ROUND: {
int i;
int start, stop;
cairo_slope_fixed_t slope;
XPointFixed tri[3];
cairo_slope_t slope;
cairo_point_t tri[3];
cairo_pen_t *pen = &gstate->pen_regular;
slope = f->dev_vector;
@ -303,8 +303,8 @@ _cairo_stroker_cap (cairo_stroker_t *stroker, cairo_stroke_face_t *f)
}
case CAIRO_LINE_CAP_SQUARE: {
double dx, dy;
cairo_slope_fixed_t fvector;
XPointFixed occw, ocw;
cairo_slope_t fvector;
cairo_point_t occw, ocw;
cairo_polygon_t polygon;
_cairo_polygon_init (&polygon);
@ -338,12 +338,12 @@ _cairo_stroker_cap (cairo_stroker_t *stroker, cairo_stroke_face_t *f)
}
static void
_compute_face (XPointFixed *pt, cairo_slope_fixed_t *slope, cairo_gstate_t *gstate, cairo_stroke_face_t *face)
_compute_face (cairo_point_t *pt, cairo_slope_t *slope, cairo_gstate_t *gstate, cairo_stroke_face_t *face)
{
double mag, tmp;
double dx, dy;
XPointDouble usr_vector;
XPointFixed offset_ccw, offset_cw;
cairo_point_t offset_ccw, offset_cw;
dx = XFixedToDouble (slope->dx);
dy = XFixedToDouble (slope->dy);
@ -388,12 +388,12 @@ _compute_face (XPointFixed *pt, cairo_slope_fixed_t *slope, cairo_gstate_t *gsta
}
static cairo_status_t
_cairo_stroker_add_sub_edge (cairo_stroker_t *stroker, XPointFixed *p1, XPointFixed *p2,
_cairo_stroker_add_sub_edge (cairo_stroker_t *stroker, cairo_point_t *p1, cairo_point_t *p2,
cairo_stroke_face_t *start, cairo_stroke_face_t *end)
{
cairo_gstate_t *gstate = stroker->gstate;
XPointFixed quad[4];
cairo_slope_fixed_t slope;
cairo_point_t quad[4];
cairo_slope_t slope;
if (p1->x == p2->x && p1->y == p2->y) {
/* XXX: Need to rethink how this case should be handled, (both
@ -402,7 +402,7 @@ _cairo_stroker_add_sub_edge (cairo_stroker_t *stroker, XPointFixed *p1, XPointFi
return CAIRO_STATUS_SUCCESS;
}
_compute_slope (p1, p2, &slope);
_cairo_slope_init (&slope, p1, p2);
_compute_face (p1, &slope, gstate, start);
/* XXX: This could be optimized slightly by not calling
@ -419,7 +419,7 @@ _cairo_stroker_add_sub_edge (cairo_stroker_t *stroker, XPointFixed *p1, XPointFi
}
static cairo_status_t
_cairo_stroker_add_edge (void *closure, XPointFixed *p1, XPointFixed *p2)
_cairo_stroker_add_edge (void *closure, cairo_point_t *p1, cairo_point_t *p2)
{
cairo_status_t status;
cairo_stroker_t *stroker = closure;
@ -458,7 +458,7 @@ _cairo_stroker_add_edge (void *closure, XPointFixed *p1, XPointFixed *p2)
* Dashed lines. Cap each dash end, join around turns when on
*/
static cairo_status_t
_cairo_stroker_add_edge_dashed (void *closure, XPointFixed *p1, XPointFixed *p2)
_cairo_stroker_add_edge_dashed (void *closure, cairo_point_t *p1, cairo_point_t *p2)
{
cairo_status_t status = CAIRO_STATUS_SUCCESS;
cairo_stroker_t *stroker = closure;
@ -466,7 +466,7 @@ _cairo_stroker_add_edge_dashed (void *closure, XPointFixed *p1, XPointFixed *p2)
double mag, remain, tmp;
double dx, dy;
double dx2, dy2;
XPointFixed fd1, fd2;
cairo_point_t fd1, fd2;
int first = 1;
cairo_stroke_face_t sub_start, sub_end;
@ -564,7 +564,9 @@ _cairo_stroker_add_edge_dashed (void *closure, XPointFixed *p1, XPointFixed *p2)
}
static cairo_status_t
_cairo_stroker_add_spline (void *closure, XPointFixed *a, XPointFixed *b, XPointFixed *c, XPointFixed *d)
_cairo_stroker_add_spline (void *closure,
cairo_point_t *a, cairo_point_t *b,
cairo_point_t *c, cairo_point_t *d)
{
cairo_status_t status = CAIRO_STATUS_SUCCESS;
cairo_stroker_t *stroker = closure;
@ -572,7 +574,7 @@ _cairo_stroker_add_spline (void *closure, XPointFixed *a, XPointFixed *b, XPoint
cairo_spline_t spline;
cairo_pen_t pen;
cairo_stroke_face_t start, end;
XPointFixed extra_points[4];
cairo_point_t extra_points[4];
status = _cairo_spline_init (&spline, a, b, c, d);
if (status == cairo_int_status_degenerate)
@ -645,7 +647,7 @@ _cairo_stroker_done_sub_path (void *closure, cairo_sub_path_done_t done)
/* fall through... */
case cairo_sub_path_done_cap:
if (stroker->have_first) {
XPointFixed t;
cairo_point_t t;
/* The initial cap needs an outward facing vector. Reverse everything */
stroker->first.usr_vector.x = -stroker->first.usr_vector.x;
stroker->first.usr_vector.y = -stroker->first.usr_vector.y;
@ -702,8 +704,8 @@ _cairo_path_stroke_to_traps (cairo_path_t *path, cairo_gstate_t *gstate, cairo_t
_cairo_stroker_init (&stroker, gstate, traps);
status = _cairo_path_interpret (path,
cairo_path_direction_forward,
callbacks, &stroker);
cairo_path_direction_forward,
callbacks, &stroker);
if (status) {
_cairo_stroker_fini (&stroker);
return status;

View file

@ -30,7 +30,7 @@
/* private functions */
static cairo_status_t
_cairo_path_add (cairo_path_t *path, cairo_path_op_t op, XPointFixed *pts, int num_pts);
_cairo_path_add (cairo_path_t *path, cairo_path_op_t op, cairo_point_t *pts, int num_pts);
static void
_cairo_path_add_op_buf (cairo_path_t *path, cairo_path_op_buf_t *op);
@ -60,7 +60,7 @@ static void
_cairo_path_arg_buf_destroy (cairo_path_arg_buf_t *buf);
static void
_cairo_path_arg_buf_add (cairo_path_arg_buf_t *arg, XPointFixed *pts, int num_pts);
_cairo_path_arg_buf_add (cairo_path_arg_buf_t *arg, cairo_point_t *pts, int num_pts);
void
_cairo_path_init (cairo_path_t *path)
@ -125,7 +125,7 @@ _cairo_path_fini (cairo_path_t *path)
cairo_status_t
_cairo_path_move_to (cairo_path_t *path, double x, double y)
{
XPointFixed pt;
cairo_point_t pt;
pt.x = XDoubleToFixed (x);
pt.y = XDoubleToFixed (y);
@ -136,7 +136,7 @@ _cairo_path_move_to (cairo_path_t *path, double x, double y)
cairo_status_t
_cairo_path_line_to (cairo_path_t *path, double x, double y)
{
XPointFixed pt;
cairo_point_t pt;
pt.x = XDoubleToFixed (x);
pt.y = XDoubleToFixed (y);
@ -150,7 +150,7 @@ _cairo_path_curve_to (cairo_path_t *path,
double x2, double y2,
double x3, double y3)
{
XPointFixed pt[3];
cairo_point_t pt[3];
pt[0].x = XDoubleToFixed (x1);
pt[0].y = XDoubleToFixed (y1);
@ -171,7 +171,7 @@ _cairo_path_close_path (cairo_path_t *path)
}
static cairo_status_t
_cairo_path_add (cairo_path_t *path, cairo_path_op_t op, XPointFixed *pts, int num_pts)
_cairo_path_add (cairo_path_t *path, cairo_path_op_t op, cairo_point_t *pts, int num_pts)
{
cairo_status_t status;
@ -300,7 +300,7 @@ _cairo_path_arg_buf_destroy (cairo_path_arg_buf_t *arg)
}
static void
_cairo_path_arg_buf_add (cairo_path_arg_buf_t *arg, XPointFixed *pts, int num_pts)
_cairo_path_arg_buf_add (cairo_path_arg_buf_t *arg, cairo_point_t *pts, int num_pts)
{
int i;
@ -328,9 +328,9 @@ _cairo_path_interpret (cairo_path_t *path, cairo_path_direction_t dir, const cai
cairo_path_op_t op;
cairo_path_arg_buf_t *arg_buf = path->arg_head;
int buf_i = 0;
XPointFixed pt[CAIRO_PATH_OP_MAX_ARGS];
XPointFixed current = {0, 0};
XPointFixed first = {0, 0};
cairo_point_t pt[CAIRO_PATH_OP_MAX_ARGS];
cairo_point_t current = {0, 0};
cairo_point_t first = {0, 0};
int has_current = 0;
int has_edge = 0;
int step = (dir == cairo_path_direction_forward) ? 1 : -1;
@ -375,7 +375,7 @@ _cairo_path_interpret (cairo_path_t *path, cairo_path_direction_t dir, const cai
switch (op) {
case cairo_path_op_move_to:
if (has_edge) {
status = (*cb->DoneSubPath) (closure, cairo_sub_path_done_cap);
status = (*cb->done_sub_path) (closure, cairo_sub_path_done_cap);
if (status)
return status;
}
@ -386,7 +386,7 @@ _cairo_path_interpret (cairo_path_t *path, cairo_path_direction_t dir, const cai
break;
case cairo_path_op_line_to:
if (has_current) {
status = (*cb->AddEdge) (closure, &current, &pt[0]);
status = (*cb->add_edge) (closure, &current, &pt[0]);
if (status)
return status;
current = pt[0];
@ -400,7 +400,7 @@ _cairo_path_interpret (cairo_path_t *path, cairo_path_direction_t dir, const cai
break;
case cairo_path_op_curve_to:
if (has_current) {
status = (*cb->AddSpline) (closure, &current, &pt[0], &pt[1], &pt[2]);
status = (*cb->add_spline) (closure, &current, &pt[0], &pt[1], &pt[2]);
if (status)
return status;
current = pt[2];
@ -414,8 +414,8 @@ _cairo_path_interpret (cairo_path_t *path, cairo_path_direction_t dir, const cai
break;
case cairo_path_op_close_path:
if (has_edge) {
(*cb->AddEdge) (closure, &current, &first);
(*cb->DoneSubPath) (closure, cairo_sub_path_done_join);
(*cb->add_edge) (closure, &current, &first);
(*cb->done_sub_path) (closure, cairo_sub_path_done_join);
}
current.x = 0;
current.y = 0;
@ -428,9 +428,9 @@ _cairo_path_interpret (cairo_path_t *path, cairo_path_direction_t dir, const cai
}
}
if (has_edge)
(*cb->DoneSubPath) (closure, cairo_sub_path_done_cap);
(*cb->done_sub_path) (closure, cairo_sub_path_done_cap);
return (*cb->DonePath) (closure);
return (*cb->done_path) (closure);
}

View file

@ -34,13 +34,7 @@ static void
_cairo_pen_compute_slopes (cairo_pen_t *pen);
static int
_slope_clockwise (cairo_slope_fixed_t *a, cairo_slope_fixed_t *b);
static int
_slope_counter_clockwise (cairo_slope_fixed_t *a, cairo_slope_fixed_t *b);
static int
_cairo_pen_vertex_compare_by_theta (const void *a, const void *b);
_pen_vertex_compare (const void *av, const void *bv);
static cairo_status_t
_cairo_pen_stroke_spline_half (cairo_pen_t *pen, cairo_spline_t *spline, cairo_pen_stroke_direction_t dir, cairo_polygon_t *polygon);
@ -60,8 +54,6 @@ cairo_status_t
_cairo_pen_init (cairo_pen_t *pen, double radius, cairo_gstate_t *gstate)
{
int i;
cairo_pen_vertex_t *v;
double dx, dy;
if (pen->num_vertices) {
/* XXX: It would be nice to notice that the pen is already properly constructed.
@ -87,17 +79,13 @@ _cairo_pen_init (cairo_pen_t *pen, double radius, cairo_gstate_t *gstate)
}
for (i=0; i < pen->num_vertices; i++) {
v = &pen->vertex[i];
v->theta = 2 * M_PI * i / (double) pen->num_vertices;
dx = radius * cos (v->theta);
dy = radius * sin (v->theta);
double theta = 2 * M_PI * i / (double) pen->num_vertices;
double dx = radius * cos (theta);
double dy = radius * sin (theta);
cairo_pen_vertex_t *v = &pen->vertex[i];
cairo_matrix_transform_distance (&gstate->ctm, &dx, &dy);
v->pt.x = XDoubleToFixed (dx);
v->pt.y = XDoubleToFixed (dy);
/* Recompute theta in device space */
v->theta = atan2 (v->pt.y, v->pt.x);
if (v->theta < 0)
v->theta += 2 * M_PI;
}
_cairo_pen_compute_slopes (pen);
@ -128,26 +116,10 @@ _cairo_pen_init_copy (cairo_pen_t *pen, cairo_pen_t *other)
return CAIRO_STATUS_SUCCESS;
}
static int
_cairo_pen_vertex_compare_by_theta (const void *a, const void *b)
{
double diff;
const cairo_pen_vertex_t *va = a;
const cairo_pen_vertex_t *vb = b;
diff = va->theta - vb->theta;
if (diff < 0)
return -1;
else if (diff > 0)
return 1;
else
return 0;
}
cairo_status_t
_cairo_pen_add_points (cairo_pen_t *pen, XPointFixed *pt, int num_pts)
_cairo_pen_add_points (cairo_pen_t *pen, cairo_point_t *pt, int num_pts)
{
int i, j;
int i;
cairo_pen_vertex_t *v, *v_next, *new_vertex;
pen->num_vertices += num_pts;
@ -162,21 +134,18 @@ _cairo_pen_add_points (cairo_pen_t *pen, XPointFixed *pt, int num_pts)
for (i=0; i < num_pts; i++) {
v = &pen->vertex[pen->num_vertices-(i+1)];
v->pt = pt[i];
v->theta = atan2 (v->pt.y, v->pt.x);
if (v->theta < 0)
v->theta += 2 * M_PI;
}
qsort (pen->vertex, pen->num_vertices, sizeof (cairo_pen_vertex_t), _cairo_pen_vertex_compare_by_theta);
qsort (pen->vertex, pen->num_vertices, sizeof (cairo_pen_vertex_t), _pen_vertex_compare);
/* eliminate any duplicate vertices */
for (i=0; i < pen->num_vertices - 1; i++ ) {
for (i=0; i < pen->num_vertices; i++ ) {
v = &pen->vertex[i];
v_next = &pen->vertex[i+1];
if (v->pt.x == v_next->pt.x && v->pt.y == v_next->pt.y) {
for (j=i+1; j < pen->num_vertices - 1; j++)
pen->vertex[j] = pen->vertex[j+1];
v_next = (i < pen->num_vertices - 1) ? &pen->vertex[i+1] : &pen->vertex[0];
if (_pen_vertex_compare (v, v_next) == 0) {
pen->num_vertices--;
memmove (&pen->vertex[i], &pen->vertex[i+1],
(pen->num_vertices - i) * sizeof (cairo_pen_vertex_t));
/* There may be more of the same duplicate, check again */
i--;
}
@ -219,34 +188,53 @@ _cairo_pen_compute_slopes (cairo_pen_t *pen)
v = &pen->vertex[i];
next = &pen->vertex[(i + 1) % pen->num_vertices];
_compute_slope (&prev->pt, &v->pt, &v->slope_cw);
_compute_slope (&v->pt, &next->pt, &v->slope_ccw);
_cairo_slope_init (&v->slope_cw, &prev->pt, &v->pt);
_cairo_slope_init (&v->slope_ccw, &v->pt, &next->pt);
}
}
/* Is a clockwise of b?
/* Is a further clockwise from (1,0) than b?
*
* NOTE: The strict equality here is not significant in and of itself,
* but there are functions up above that are sensitive to it,
* (cf. _cairo_pen_find_active_cw_vertex_index).
* There are a two special cases to consider:
* 1) a and b are not in the same half plane.
* 2) both a and b are on the X axis
* After that, the computation is a simple slope comparison.
*/
static int
_slope_clockwise (cairo_slope_fixed_t *a, cairo_slope_fixed_t *b)
_pen_vertex_compare (const void *av, const void *bv)
{
return ((cairo_fixed_48_16_t) b->dy * (cairo_fixed_48_16_t) a->dx
> (cairo_fixed_48_16_t) a->dy * (cairo_fixed_48_16_t) b->dx);
}
const cairo_pen_vertex_t *a = av;
const cairo_pen_vertex_t *b = bv;
cairo_fixed_48_16_t diff;
static int
_slope_counter_clockwise (cairo_slope_fixed_t *a, cairo_slope_fixed_t *b)
{
return ! _slope_clockwise (a, b);
int a_above = a->pt.y >= 0;
int b_above = b->pt.y >= 0;
if (a_above != b_above)
return b_above - a_above;
if (a->pt.y == 0 && b->pt.y == 0) {
int a_right = a->pt.x >= 0;
int b_right = b->pt.x >= 0;
if (a_right != b_right)
return b_right - a_right;
}
diff = ((cairo_fixed_48_16_t) a->pt.y * (cairo_fixed_48_16_t) b->pt.x
- (cairo_fixed_48_16_t) b->pt.y * (cairo_fixed_48_16_t) a->pt.x);
if (diff > 0)
return 1;
if (diff < 0)
return -1;
return 0;
}
/* Find active pen vertex for clockwise edge of stroke at the given slope.
*
* NOTE: The behavior of this function is sensitive to the sense of
* the inequality within _slope_clockwise/_slope_counter_clockwise.
* the inequality within _cairo_slope_clockwise/_cairo_slope_counter_clockwise.
*
* The issue is that the slope_ccw member of one pen vertex will be
* equivalent to the slope_cw member of the next pen vertex in a
@ -255,14 +243,14 @@ _slope_counter_clockwise (cairo_slope_fixed_t *a, cairo_slope_fixed_t *b)
*/
cairo_status_t
_cairo_pen_find_active_cw_vertex_index (cairo_pen_t *pen,
cairo_slope_fixed_t *slope,
cairo_slope_t *slope,
int *active)
{
int i;
for (i=0; i < pen->num_vertices; i++) {
if (_slope_clockwise (slope, &pen->vertex[i].slope_ccw)
&& _slope_counter_clockwise (slope, &pen->vertex[i].slope_cw))
if (_cairo_slope_clockwise (slope, &pen->vertex[i].slope_ccw)
&& _cairo_slope_counter_clockwise (slope, &pen->vertex[i].slope_cw))
break;
}
@ -274,23 +262,23 @@ _cairo_pen_find_active_cw_vertex_index (cairo_pen_t *pen,
/* Find active pen vertex for counterclockwise edge of stroke at the given slope.
*
* NOTE: The behavior of this function is sensitive to the sense of
* the inequality within _slope_clockwise/_slope_counter_clockwise.
* the inequality within _cairo_slope_clockwise/_cairo_slope_counter_clockwise.
*/
cairo_status_t
_cairo_pen_find_active_ccw_vertex_index (cairo_pen_t *pen,
cairo_slope_fixed_t *slope,
cairo_slope_t *slope,
int *active)
{
int i;
cairo_slope_fixed_t slope_reverse;
cairo_slope_t slope_reverse;
slope_reverse = *slope;
slope_reverse.dx = -slope_reverse.dx;
slope_reverse.dy = -slope_reverse.dy;
for (i=pen->num_vertices-1; i >= 0; i--) {
if (_slope_counter_clockwise (&pen->vertex[i].slope_ccw, &slope_reverse)
&& _slope_clockwise (&pen->vertex[i].slope_cw, &slope_reverse))
if (_cairo_slope_counter_clockwise (&pen->vertex[i].slope_ccw, &slope_reverse)
&& _cairo_slope_clockwise (&pen->vertex[i].slope_cw, &slope_reverse))
break;
}
@ -309,9 +297,9 @@ _cairo_pen_stroke_spline_half (cairo_pen_t *pen,
cairo_status_t status;
int start, stop, step;
int active = 0;
XPointFixed hull_pt;
cairo_slope_fixed_t slope, initial_slope, final_slope;
XPointFixed *pt = spline->pts;
cairo_point_t hull_pt;
cairo_slope_t slope, initial_slope, final_slope;
cairo_point_t *pt = spline->pts;
int num_pts = spline->num_pts;
if (dir == cairo_pen_stroke_direction_forward) {
@ -345,11 +333,11 @@ _cairo_pen_stroke_spline_half (cairo_pen_t *pen,
if (i + step == stop)
slope = final_slope;
else
_compute_slope (&pt[i], &pt[i+step], &slope);
if (_slope_counter_clockwise (&slope, &pen->vertex[active].slope_ccw)) {
_cairo_slope_init (&slope, &pt[i], &pt[i+step]);
if (_cairo_slope_counter_clockwise (&slope, &pen->vertex[active].slope_ccw)) {
if (++active == pen->num_vertices)
active = 0;
} else if (_slope_clockwise (&slope, &pen->vertex[active].slope_cw)) {
} else if (_cairo_slope_clockwise (&slope, &pen->vertex[active].slope_cw)) {
if (--active == -1)
active = pen->num_vertices - 1;
} else {

View file

@ -36,8 +36,7 @@ static cairo_status_t
_cairo_polygon_grow_by (cairo_polygon_t *polygon, int additional);
static void
_cairo_polygon_set_last_point (cairo_polygon_t *polygon, XPointFixed *pt);
_cairo_polygon_set_last_point (cairo_polygon_t *polygon, cairo_point_t *pt);
void
_cairo_polygon_init (cairo_polygon_t *polygon)
@ -94,14 +93,14 @@ _cairo_polygon_grow_by (cairo_polygon_t *polygon, int additional)
}
static void
_cairo_polygon_set_last_point (cairo_polygon_t *polygon, XPointFixed *pt)
_cairo_polygon_set_last_point (cairo_polygon_t *polygon, cairo_point_t *pt)
{
polygon->last_pt = *pt;
polygon->last_pt_defined = 1;
}
cairo_status_t
_cairo_polygon_add_edge (cairo_polygon_t *polygon, XPointFixed *p1, XPointFixed *p2)
_cairo_polygon_add_edge (cairo_polygon_t *polygon, cairo_point_t *p1, cairo_point_t *p2)
{
cairo_status_t status;
cairo_edge_t *edge;
@ -144,7 +143,7 @@ _cairo_polygon_add_edge (cairo_polygon_t *polygon, XPointFixed *p1, XPointFixed
}
cairo_status_t
_cairo_polygon_add_point (cairo_polygon_t *polygon, XPointFixed *pt)
_cairo_polygon_add_point (cairo_polygon_t *polygon, cairo_point_t *pt)
{
cairo_status_t status = CAIRO_STATUS_SUCCESS;

View file

@ -28,9 +28,31 @@
#include "cairoint.h"
void
_compute_slope (XPointFixed *a, XPointFixed *b, cairo_slope_fixed_t *slope)
_cairo_slope_init (cairo_slope_t *slope, cairo_point_t *a, cairo_point_t *b)
{
slope->dx = b->x - a->x;
slope->dy = b->y - a->y;
}
/* Is a clockwise of b?
*
* NOTE: The strict equality here is not significant in and of itself,
* but there are functions up above that are sensitive to it,
* (cf. _cairo_pen_find_active_cw_vertex_index).
*/
int
_cairo_slope_clockwise (cairo_slope_t *a, cairo_slope_t *b)
{
return ((cairo_fixed_48_16_t) b->dy * (cairo_fixed_48_16_t) a->dx
> (cairo_fixed_48_16_t) a->dy * (cairo_fixed_48_16_t) b->dx);
}
int
_cairo_slope_counter_clockwise (cairo_slope_t *a, cairo_slope_t *b)
{
return ! _cairo_slope_clockwise (a, b);
}

View file

@ -31,10 +31,10 @@ static cairo_status_t
_cairo_spline_grow_by (cairo_spline_t *spline, int additional);
static cairo_status_t
_cairo_spline_add_point (cairo_spline_t *spline, XPointFixed *pt);
_cairo_spline_add_point (cairo_spline_t *spline, cairo_point_t *pt);
static void
_lerp_half (XPointFixed *a, XPointFixed *b, XPointFixed *result);
_lerp_half (cairo_point_t *a, cairo_point_t *b, cairo_point_t *result);
static void
_de_casteljau (cairo_spline_t *spline, cairo_spline_t *s1, cairo_spline_t *s2);
@ -48,7 +48,9 @@ _cairo_spline_decompose_into (cairo_spline_t *spline, double tolerance_squared,
#define CAIRO_SPLINE_GROWTH_INC 100
cairo_int_status_t
_cairo_spline_init (cairo_spline_t *spline, XPointFixed *a, XPointFixed *b, XPointFixed *c, XPointFixed *d)
_cairo_spline_init (cairo_spline_t *spline,
cairo_point_t *a, cairo_point_t *b,
cairo_point_t *c, cairo_point_t *d)
{
spline->a = *a;
spline->b = *b;
@ -56,21 +58,21 @@ _cairo_spline_init (cairo_spline_t *spline, XPointFixed *a, XPointFixed *b, XP
spline->d = *d;
if (a->x != b->x || a->y != b->y) {
_compute_slope (&spline->a, &spline->b, &spline->initial_slope);
_cairo_slope_init (&spline->initial_slope, &spline->a, &spline->b);
} else if (a->x != c->x || a->y != c->y) {
_compute_slope (&spline->a, &spline->c, &spline->initial_slope);
_cairo_slope_init (&spline->initial_slope, &spline->a, &spline->c);
} else if (a->x != d->x || a->y != d->y) {
_compute_slope (&spline->a, &spline->d, &spline->initial_slope);
_cairo_slope_init (&spline->initial_slope, &spline->a, &spline->d);
} else {
return cairo_int_status_degenerate;
}
if (c->x != d->x || c->y != d->y) {
_compute_slope (&spline->c, &spline->d, &spline->final_slope);
_cairo_slope_init (&spline->final_slope, &spline->c, &spline->d);
} else if (b->x != d->x || b->y != d->y) {
_compute_slope (&spline->b, &spline->d, &spline->final_slope);
_cairo_slope_init (&spline->final_slope, &spline->b, &spline->d);
} else {
_compute_slope (&spline->a, &spline->d, &spline->final_slope);
_cairo_slope_init (&spline->final_slope, &spline->a, &spline->d);
}
spline->num_pts = 0;
@ -92,7 +94,7 @@ _cairo_spline_fini (cairo_spline_t *spline)
static cairo_status_t
_cairo_spline_grow_by (cairo_spline_t *spline, int additional)
{
XPointFixed *new_pts;
cairo_point_t *new_pts;
int old_size = spline->pts_size;
int new_size = spline->num_pts + additional;
@ -100,7 +102,7 @@ _cairo_spline_grow_by (cairo_spline_t *spline, int additional)
return CAIRO_STATUS_SUCCESS;
spline->pts_size = new_size;
new_pts = realloc (spline->pts, spline->pts_size * sizeof (XPointFixed));
new_pts = realloc (spline->pts, spline->pts_size * sizeof (cairo_point_t));
if (new_pts == NULL) {
spline->pts_size = old_size;
@ -113,7 +115,7 @@ _cairo_spline_grow_by (cairo_spline_t *spline, int additional)
}
static cairo_status_t
_cairo_spline_add_point (cairo_spline_t *spline, XPointFixed *pt)
_cairo_spline_add_point (cairo_spline_t *spline, cairo_point_t *pt)
{
cairo_status_t status;
@ -130,7 +132,7 @@ _cairo_spline_add_point (cairo_spline_t *spline, XPointFixed *pt)
}
static void
_lerp_half (XPointFixed *a, XPointFixed *b, XPointFixed *result)
_lerp_half (cairo_point_t *a, cairo_point_t *b, cairo_point_t *result)
{
result->x = a->x + ((b->x - a->x) >> 1);
result->y = a->y + ((b->y - a->y) >> 1);
@ -139,9 +141,9 @@ _lerp_half (XPointFixed *a, XPointFixed *b, XPointFixed *result)
static void
_de_casteljau (cairo_spline_t *spline, cairo_spline_t *s1, cairo_spline_t *s2)
{
XPointFixed ab, bc, cd;
XPointFixed abbc, bccd;
XPointFixed final;
cairo_point_t ab, bc, cd;
cairo_point_t abbc, bccd;
cairo_point_t final;
_lerp_half (&spline->a, &spline->b, &ab);
_lerp_half (&spline->b, &spline->c, &bc);
@ -162,7 +164,7 @@ _de_casteljau (cairo_spline_t *spline, cairo_spline_t *s1, cairo_spline_t *s2)
}
static double
_PointDistanceSquaredToPoint (XPointFixed *a, XPointFixed *b)
_PointDistanceSquaredToPoint (cairo_point_t *a, cairo_point_t *b)
{
double dx = XFixedToDouble (b->x - a->x);
double dy = XFixedToDouble (b->y - a->y);
@ -171,12 +173,12 @@ _PointDistanceSquaredToPoint (XPointFixed *a, XPointFixed *b)
}
static double
_PointDistanceSquaredToSegment (XPointFixed *p, XPointFixed *p1, XPointFixed *p2)
_PointDistanceSquaredToSegment (cairo_point_t *p, cairo_point_t *p1, cairo_point_t *p2)
{
double u;
double dx, dy;
double pdx, pdy;
XPointFixed px;
cairo_point_t px;
/* intersection point (px):

View file

@ -29,6 +29,34 @@
#include "cairoint.h"
static const XTransform CAIRO_XTRANSFORM_IDENTITY = {
{
{65536, 0, 0},
{ 0, 65536, 0},
{ 0, 0, 65536}
}
};
#define CAIRO_SURFACE_RENDER_AT_LEAST(surface, major, minor) \
(((surface)->render_major > major) ? 1 \
: ((surface)->render_major == major) ? ((surface)->render_minor >= minor) : 0)
#define CAIRO_SURFACE_RENDER_HAS_CREATE_PICTURE(surface) CAIRO_SURFACE_RENDER_AT_LEAST((surface), 0, 0)
#define CAIRO_SURFACE_RENDER_HAS_COMPOSITE(surface) CAIRO_SURFACE_RENDER_AT_LEAST((surface), 0, 0)
#define CAIRO_SURFACE_RENDER_HAS_FILL_RECTANGLE(surface) CAIRO_SURFACE_RENDER_AT_LEAST((surface), 0, 1)
#define CAIRO_SURFACE_RENDER_HAS_FILL_RECTANGLES(surface) CAIRO_SURFACE_RENDER_AT_LEAST((surface), 0, 1)
#define CAIRO_SURFACE_RENDER_HAS_DISJOINT(surface) CAIRO_SURFACE_RENDER_AT_LEAST((surface), 0, 2)
#define CAIRO_SURFACE_RENDER_HAS_CONJOINT(surface) CAIRO_SURFACE_RENDER_AT_LEAST((surface), 0, 2)
#define CAIRO_SURFACE_RENDER_HAS_TRAPEZOIDS(surface) CAIRO_SURFACE_RENDER_AT_LEAST((surface), 0, 4)
#define CAIRO_SURFACE_RENDER_HAS_TRIANGLES(surface) CAIRO_SURFACE_RENDER_AT_LEAST((surface), 0, 4)
#define CAIRO_SURFACE_RENDER_HAS_TRISTRIP(surface) CAIRO_SURFACE_RENDER_AT_LEAST((surface), 0, 4)
#define CAIRO_SURFACE_RENDER_HAS_TRIFAN(surface) CAIRO_SURFACE_RENDER_AT_LEAST((surface), 0, 4)
#define CAIRO_SURFACE_RENDER_HAS_PICTURE_TRANSFORM(surface) CAIRO_SURFACE_RENDER_AT_LEAST((surface), 0, 6)
cairo_surface_t *
cairo_surface_create_for_drawable (Display *dpy,
Drawable drawable,
@ -42,20 +70,35 @@ cairo_surface_create_for_drawable (Display *dpy,
if (surface == NULL)
return NULL;
surface->dpy = dpy;
surface->image_data = NULL;
surface->xc_surface = XcSurfaceCreateForDrawable (dpy, drawable, visual, format, colormap);
if (surface->xc_surface == NULL) {
free (surface);
return NULL;
}
/* XXX: We should really get this value from somewhere like Xft.dpy */
surface->ppm = 3780;
surface->ref_count = 1;
surface->dpy = dpy;
surface->image_data = NULL;
surface->icimage = NULL;
surface->type = CAIRO_SURFACE_TYPE_DRAWABLE;
surface->xtransform = CAIRO_XTRANSFORM_IDENTITY;
surface->gc = 0;
surface->drawable = drawable;
surface->visual = visual;
if (! XRenderQueryVersion (dpy, &surface->render_major, &surface->render_minor)) {
surface->render_major = -1;
surface->render_minor = -1;
}
/* 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),
0, NULL);
return surface;
}
@ -144,25 +187,31 @@ cairo_surface_create_for_image (char *data,
if (surface == NULL)
return NULL;
/* Assume a default until the user lets us know otherwise */
surface->ppm = 3780;
surface->ref_count = 1;
surface->dpy = NULL;
surface->image_data = NULL;
image = IcImageCreateForData ((IcBits *) data, &icformat, width, height, cairo_format_bpp (format), stride);
if (image == NULL) {
free (surface);
return NULL;
}
surface->xc_surface = XcSurfaceCreateForIcImage (image);
if (surface->xc_surface == NULL) {
IcImageDestroy (image);
free (surface);
return NULL;
}
surface->type = CAIRO_SURFACE_TYPE_ICIMAGE;
surface->xtransform = CAIRO_XTRANSFORM_IDENTITY;
/* Assume a default until the user lets us know otherwise */
surface->ppm = 3780;
surface->gc = 0;
surface->drawable = 0;
surface->visual = NULL;
surface->render_major = -1;
surface->render_minor = -1;
surface->ref_count = 1;
surface->picture = 0;
surface->icimage = image;
return surface;
}
@ -205,8 +254,6 @@ cairo_surface_create_similar_solid (cairo_surface_t *other,
cairo_surface_t *surface = NULL;
cairo_color_t color;
/* XXX: create_similar should perhaps move down to Xc, (then we
could drop xrsurface->dpy as well) */
if (other->dpy) {
Display *dpy = other->dpy;
int scr = DefaultScreen (dpy);
@ -270,32 +317,130 @@ cairo_surface_destroy (cairo_surface_t *surface)
if (surface->ref_count)
return;
surface->dpy = 0;
XcSurfaceDestroy (surface->xc_surface);
surface->xc_surface = NULL;
if (surface->picture)
XRenderFreePicture (surface->dpy, surface->picture);
if (surface->icimage)
IcImageDestroy (surface->icimage);
if (surface->image_data)
free (surface->image_data);
surface->image_data = NULL;
surface->dpy = 0;
free (surface);
}
static void
_cairo_surface_ensure_gc (cairo_surface_t *surface)
{
if (surface->gc)
return;
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)
char *data,
int width,
int height,
int stride)
{
XcSurfacePutImage (surface->xc_surface, data,
width, height, 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;
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_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);
} 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 */
/* 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.)
if (surface->type == CAIRO_SURFACE_TYPE_ICIMAGE)
return;
if (surface->icimage) {
IcImageDestroy (surface->icimage);
surface->icimage = NULL;
}
_cairo_surface_ensure_GC (surface);
surface->ximage = XGetImage (surface->dpy,
surface->drawable,
surface->gc,
0, 0,
width, height,
AllPlanes, ZPixmap);
surface->icimage = IcImageCreateForData (image->data,
IcFormat *format,
int width, int height,
int bpp, int stride);
*/
}
void
_cairo_surface_push_image (cairo_surface_t *surface)
{
/* XXX: NYI
if (surface->type == CAIRO_SURFACE_TYPE_ICIMAGE)
return;
if (surface->ximage == NULL)
return;
_cairo_surface_ensure_GC (surface);
XPutImage (surface->dpy,
surface->drawable,
surface->gc,
surface->ximage,
0, 0,
0, 0,
width, height);
* 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
nothing else, that would eliminate the two different transform data
@ -303,22 +448,31 @@ cairo_surface_put_image (cairo_surface_t *surface,
cairo_status_t
cairo_surface_set_matrix (cairo_surface_t *surface, cairo_matrix_t *matrix)
{
XTransform xtransform;
XTransform *xtransform = &surface->xtransform;
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]);
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]);
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[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);
xtransform->matrix[2][0] = 0;
xtransform->matrix[2][1] = 0;
xtransform->matrix[2][2] = XDoubleToFixed (1);
XcSurfaceSetTransform (surface->xc_surface,
&xtransform);
if (surface->picture) {
if (CAIRO_SURFACE_RENDER_HAS_PICTURE_TRANSFORM (surface))
XRenderSetPictureTransform (surface->dpy, surface->picture, xtransform);
/* XXX: Need support here if using an old RENDER without support
for SetPictureTransform */
}
/* 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 CAIRO_STATUS_SUCCESS;
}
@ -326,51 +480,134 @@ cairo_surface_set_matrix (cairo_surface_t *surface, cairo_matrix_t *matrix)
cairo_status_t
cairo_surface_get_matrix (cairo_surface_t *surface, cairo_matrix_t *matrix)
{
XTransform xtransform;
XTransform *xtransform = &surface->xtransform;
XcSurfaceGetTransform (surface->xc_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] = 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][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] = XFixedToDouble (xtransform->matrix[1][0]);
matrix->m[1][1] = XFixedToDouble (xtransform->matrix[1][1]);
matrix->m[2][1] = XFixedToDouble (xtransform->matrix[1][2]);
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";
}
}
cairo_status_t
cairo_surface_set_filter (cairo_surface_t *surface, cairo_filter_t filter)
{
XcSurfaceSetFilter (surface->xc_surface, filter);
if (surface->picture) {
XRenderSetPictureFilter (surface->dpy, surface->picture,
_render_filter_name (filter), NULL, 0);
}
if (surface->icimage) {
IcImageSetFilter (surface->icimage, filter);
}
return CAIRO_STATUS_SUCCESS;
}
/* XXX: The Xc version of this function isn't quite working yet
/* XXX: NYI
cairo_status_t
cairo_surface_set_clip_region (cairo_surface_t *surface, Region region)
cairo_surface_clip_rectangle (cairo_surface_t *surface,
int x, int y,
int width, int height)
{
XcSurfaceSetClipRegion (surface->xc_surface, region);
return CAIRO_STATUS_SUCCESS;
}
*/
/* XXX: NYI
cairo_status_t
cairo_surface_clip_restore (cairo_surface_t *surface);
*/
cairo_status_t
cairo_surface_set_repeat (cairo_surface_t *surface, int repeat)
{
XcSurfaceSetRepeat (surface->xc_surface, repeat);
if (surface->picture) {
unsigned long mask;
XRenderPictureAttributes pa;
mask = CPRepeat;
pa.repeat = repeat;
XRenderChangePicture (surface->dpy, surface->picture, mask, &pa);
}
if (surface->icimage) {
IcImageSetRepeat (surface->icimage, repeat);
}
return CAIRO_STATUS_SUCCESS;
}
/* XXX: This function is going away, right? */
Picture
_cairo_surface_get_picture (cairo_surface_t *surface)
void
_cairo_surface_composite (cairo_operator_t operator,
cairo_surface_t *src,
cairo_surface_t *mask,
cairo_surface_t *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)
{
return XcSurfaceGetPicture (surface->xc_surface);
if (dst->type == CAIRO_SURFACE_TYPE_DRAWABLE
&& CAIRO_SURFACE_RENDER_HAS_COMPOSITE (dst)
&& src->dpy == dst->dpy
&& (mask == NULL || mask->dpy == dst->dpy)) {
XRenderComposite (dst->dpy, operator,
src->picture,
mask ? mask->picture : 0,
dst->picture,
src_x, src_y,
mask_x, mask_y,
dst_x, dst_y,
width, height);
} else {
_cairo_surface_pull_image (src);
_cairo_surface_pull_image (mask);
_cairo_surface_pull_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);
_cairo_surface_push_image (dst);
}
}
void
@ -382,10 +619,80 @@ _cairo_surface_fill_rectangle (cairo_surface_t *surface,
int width,
int height)
{
XcFillRectangle (operator,
surface->xc_surface,
&color->xc_color,
x, y,
width, height);
cairo_rectangle_t rect;
rect.x = x;
rect.y = y;
rect.width = width;
rect.height = height;
_cairo_surface_fill_rectangles (surface, operator, color, &rect, 1);
}
void
_cairo_surface_fill_rectangles (cairo_surface_t *surface,
cairo_operator_t operator,
const cairo_color_t *color,
cairo_rectangle_t *rects,
int num_rects)
{
if (surface->type == CAIRO_SURFACE_TYPE_DRAWABLE
&& CAIRO_SURFACE_RENDER_HAS_FILL_RECTANGLE (surface)) {
XRenderColor render_color;
render_color.red = color->red_short;
render_color.green = color->green_short;
render_color.blue = color->blue_short;
render_color.alpha = color->alpha_short;
/* XXX: This XRectangle cast is evil... it needs to go away somehow. */
XRenderFillRectangles (surface->dpy, operator, surface->picture,
&render_color, (XRectangle *) rects, num_rects);
} else {
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;
_cairo_surface_pull_image (surface);
/* XXX: The IcRectangle cast is evil... it needs to go away somehow. */
IcFillRectangles (operator, surface->icimage,
&ic_color, (IcRectangle *) rects, num_rects);
_cairo_surface_push_image (surface);
}
}
void
_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 num_traps)
{
if (dst->type == CAIRO_SURFACE_TYPE_DRAWABLE
&& CAIRO_SURFACE_RENDER_HAS_TRAPEZOIDS (dst)
&& src->dpy == dst->dpy) {
/* XXX: The XTrapezoid cast is evil and needs to go away somehow. */
XRenderCompositeTrapezoids (dst->dpy, operator, src->picture, dst->picture,
XRenderFindStandardFormat (dst->dpy, PictStandardA8),
xSrc, ySrc, (XTrapezoid *) traps, num_traps);
} else {
_cairo_surface_pull_image (src);
_cairo_surface_pull_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);
_cairo_surface_push_image (dst);
}
}

View file

@ -32,13 +32,13 @@ static cairo_status_t
cairo_traps_grow_by (cairo_traps_t *traps, int additional);
cairo_status_t
cairo_traps_add_trap (cairo_traps_t *traps, XFixed top, XFixed bottom,
XLineFixed *left, XLineFixed *right);
cairo_traps_add_trap (cairo_traps_t *traps, cairo_fixed_t top, cairo_fixed_t bottom,
cairo_line_t *left, cairo_line_t *right);
cairo_status_t
cairo_traps_add_trap_from_points (cairo_traps_t *traps, XFixed top, XFixed bottom,
XPointFixed left_p1, XPointFixed left_p2,
XPointFixed right_p1, XPointFixed right_p2);
cairo_traps_add_trap_from_points (cairo_traps_t *traps, cairo_fixed_t top, cairo_fixed_t bottom,
cairo_point_t left_p1, cairo_point_t left_p2,
cairo_point_t right_p1, cairo_point_t right_p2);
static int
_compare_point_fixed_by_y (const void *av, const void *bv);
@ -50,72 +50,72 @@ static int
_compare_cairo_edge_by_slope (const void *av, const void *bv);
static cairo_fixed_16_16_t
_compute_x (XLineFixed *line, XFixed y);
_compute_x (cairo_line_t *line, cairo_fixed_t y);
static double
_compute_inverse_slope (XLineFixed *l);
_compute_inverse_slope (cairo_line_t *l);
static double
_compute_x_intercept (XLineFixed *l, double inverse_slope);
_compute_x_intercept (cairo_line_t *l, double inverse_slope);
static XFixed
_line_segs_intersect_ceil (XLineFixed *left, XLineFixed *right, XFixed *y_ret);
static cairo_fixed_t
_line_segs_intersect_ceil (cairo_line_t *left, cairo_line_t *right, cairo_fixed_t *y_ret);
void
cairo_traps_init (cairo_traps_t *traps)
{
traps->num_xtraps = 0;
traps->num_traps = 0;
traps->xtraps_size = 0;
traps->xtraps = NULL;
traps->traps_size = 0;
traps->traps = NULL;
}
void
cairo_traps_fini (cairo_traps_t *traps)
{
if (traps->xtraps_size) {
free (traps->xtraps);
traps->xtraps = NULL;
traps->xtraps_size = 0;
traps->num_xtraps = 0;
if (traps->traps_size) {
free (traps->traps);
traps->traps = NULL;
traps->traps_size = 0;
traps->num_traps = 0;
}
}
cairo_status_t
cairo_traps_add_trap (cairo_traps_t *traps, XFixed top, XFixed bottom,
XLineFixed *left, XLineFixed *right)
cairo_traps_add_trap (cairo_traps_t *traps, cairo_fixed_t top, cairo_fixed_t bottom,
cairo_line_t *left, cairo_line_t *right)
{
cairo_status_t status;
XTrapezoid *trap;
cairo_trapezoid_t *trap;
if (top == bottom) {
return CAIRO_STATUS_SUCCESS;
}
if (traps->num_xtraps >= traps->xtraps_size) {
if (traps->num_traps >= traps->traps_size) {
status = cairo_traps_grow_by (traps, CAIRO_TRAPS_GROWTH_INC);
if (status)
return status;
}
trap = &traps->xtraps[traps->num_xtraps];
trap = &traps->traps[traps->num_traps];
trap->top = top;
trap->bottom = bottom;
trap->left = *left;
trap->right = *right;
traps->num_xtraps++;
traps->num_traps++;
return CAIRO_STATUS_SUCCESS;
}
cairo_status_t
cairo_traps_add_trap_from_points (cairo_traps_t *traps, XFixed top, XFixed bottom,
XPointFixed left_p1, XPointFixed left_p2,
XPointFixed right_p1, XPointFixed right_p2)
cairo_traps_add_trap_from_points (cairo_traps_t *traps, cairo_fixed_t top, cairo_fixed_t bottom,
cairo_point_t left_p1, cairo_point_t left_p2,
cairo_point_t right_p1, cairo_point_t right_p2)
{
XLineFixed left;
XLineFixed right;
cairo_line_t left;
cairo_line_t right;
left.p1 = left_p1;
left.p2 = left_p2;
@ -129,23 +129,23 @@ cairo_traps_add_trap_from_points (cairo_traps_t *traps, XFixed top, XFixed botto
static cairo_status_t
cairo_traps_grow_by (cairo_traps_t *traps, int additional)
{
XTrapezoid *new_xtraps;
int old_size = traps->xtraps_size;
int new_size = traps->num_xtraps + additional;
cairo_trapezoid_t *new_traps;
int old_size = traps->traps_size;
int new_size = traps->num_traps + additional;
if (new_size <= traps->xtraps_size) {
if (new_size <= traps->traps_size) {
return CAIRO_STATUS_SUCCESS;
}
traps->xtraps_size = new_size;
new_xtraps = realloc (traps->xtraps, traps->xtraps_size * sizeof (XTrapezoid));
traps->traps_size = new_size;
new_traps = realloc (traps->traps, traps->traps_size * sizeof (cairo_trapezoid_t));
if (new_xtraps == NULL) {
traps->xtraps_size = old_size;
if (new_traps == NULL) {
traps->traps_size = old_size;
return CAIRO_STATUS_NO_MEMORY;
}
traps->xtraps = new_xtraps;
traps->traps = new_traps;
return CAIRO_STATUS_SUCCESS;
}
@ -153,7 +153,7 @@ cairo_traps_grow_by (cairo_traps_t *traps, int additional)
static int
_compare_point_fixed_by_y (const void *av, const void *bv)
{
const XPointFixed *a = av, *b = bv;
const cairo_point_t *a = av, *b = bv;
int ret = a->y - b->y;
if (ret == 0) {
@ -163,15 +163,15 @@ _compare_point_fixed_by_y (const void *av, const void *bv)
}
cairo_status_t
cairo_traps_tessellate_triangle (cairo_traps_t *traps, XPointFixed t[3])
cairo_traps_tessellate_triangle (cairo_traps_t *traps, cairo_point_t t[3])
{
cairo_status_t status;
XLineFixed line;
cairo_line_t line;
cairo_fixed_16_16_t intersect;
XPointFixed tsort[3];
cairo_point_t tsort[3];
memcpy (tsort, t, 3 * sizeof (XPointFixed));
qsort (tsort, 3, sizeof (XPointFixed), _compare_point_fixed_by_y);
memcpy (tsort, t, 3 * sizeof (cairo_point_t));
qsort (tsort, 3, sizeof (cairo_point_t), _compare_point_fixed_by_y);
/* horizontal top edge requires special handling */
if (tsort[0].y == tsort[1].y) {
@ -226,11 +226,11 @@ cairo_traps_tessellate_triangle (cairo_traps_t *traps, XPointFixed t[3])
/* Warning: This function reorders the elements of the array provided. */
cairo_status_t
cairo_traps_tessellate_rectangle (cairo_traps_t *traps, XPointFixed q[4])
cairo_traps_tessellate_rectangle (cairo_traps_t *traps, cairo_point_t q[4])
{
cairo_status_t status;
qsort (q, 4, sizeof (XPointFixed), _compare_point_fixed_by_y);
qsort (q, 4, sizeof (cairo_point_t), _compare_point_fixed_by_y);
if (q[1].x > q[2].x) {
status = cairo_traps_add_trap_from_points (traps,
@ -335,7 +335,7 @@ _det (double a, double b, double c, double d)
}
static int
_lines_intersect (XLineFixed *l1, XLineFixed *l2, XFixed *y_intersection)
_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);
@ -362,7 +362,7 @@ _lines_intersect (XLineFixed *l1, XLineFixed *l2, XFixed *y_intersection)
}
*/
static cairo_fixed_16_16_t
_compute_x (XLineFixed *line, XFixed y)
_compute_x (cairo_line_t *line, cairo_fixed_t y)
{
cairo_fixed_16_16_t dx = line->p2.x - line->p1.x;
cairo_fixed_32_32_t ex = (cairo_fixed_48_16_t) (y - line->p1.y) * (cairo_fixed_48_16_t) dx;
@ -372,20 +372,20 @@ _compute_x (XLineFixed *line, XFixed y)
}
static double
_compute_inverse_slope (XLineFixed *l)
_compute_inverse_slope (cairo_line_t *l)
{
return (XFixedToDouble (l->p2.x - l->p1.x) /
XFixedToDouble (l->p2.y - l->p1.y));
}
static double
_compute_x_intercept (XLineFixed *l, double inverse_slope)
_compute_x_intercept (cairo_line_t *l, double inverse_slope)
{
return XFixedToDouble (l->p1.x) - inverse_slope * XFixedToDouble (l->p1.y);
}
static int
_line_segs_intersect_ceil (XLineFixed *l1, XLineFixed *l2, XFixed *y_ret)
_line_segs_intersect_ceil (cairo_line_t *l1, cairo_line_t *l2, cairo_fixed_t *y_ret)
{
/*
* x = m1y + b1
@ -406,7 +406,7 @@ _line_segs_intersect_ceil (XLineFixed *l1, XLineFixed *l2, XFixed *y_ret)
y_intersect = XDoubleToFixed ((b2 - b1) / (m1 - m2));
if (m1 < m2) {
XLineFixed *t;
cairo_line_t *t;
t = l1;
l1 = l2;
l2 = t;
@ -418,6 +418,22 @@ _line_segs_intersect_ceil (XLineFixed *l1, XLineFixed *l2, XFixed *y_ret)
most, we must increment once. */
if (_compute_x (l2, y_intersect) > _compute_x (l1, y_intersect))
y_intersect++;
/* XXX: Hmm... Keith's error calculations said we'd at most be off
by one sub-pixel. But, I found that the paint-fill-BE-01.svg
test from the W3C SVG conformance suite definitely requires two
increments.
It could be that we need one to overcome the error, and another
to round up.
It would be nice to be sure this code is correct, (but we can't
do the while loop as it will work for way to long on
exceedingly distant intersections with large errors that we
really don't care about anyway as they will be ignored by the
calling function.
*/
if (_compute_x (l2, y_intersect) > _compute_x (l1, y_intersect))
y_intersect++;
*y_ret = y_intersect;
@ -458,7 +474,7 @@ cairo_traps_tessellate_polygon (cairo_traps_t *traps,
{
cairo_status_t status;
int i, active, inactive;
XFixed y, y_next, intersect;
cairo_fixed_t y, y_next, intersect;
int in_out, num_edges = poly->num_edges;
cairo_edge_t *edges = poly->edges;

View file

@ -160,12 +160,6 @@ cairo_set_target_surface (cairo_t *cr, cairo_surface_t *surface)
cr->status = _cairo_gstate_set_target_surface (cr->gstate, surface);
}
cairo_surface_t *
cairo_get_target_surface (cairo_t *cr)
{
return _cairo_gstate_get_target_surface (cr->gstate);
}
void
cairo_set_target_drawable (cairo_t *cr,
Display *dpy,
@ -225,12 +219,6 @@ cairo_set_operator (cairo_t *cr, cairo_operator_t op)
cr->status = _cairo_gstate_set_operator (cr->gstate, op);
}
cairo_operator_t
cairo_get_operator (cairo_t *cr)
{
return _cairo_gstate_get_operator (cr->gstate);
}
void
cairo_set_rgb_color (cairo_t *cr, double red, double green, double blue)
{
@ -244,16 +232,6 @@ cairo_set_rgb_color (cairo_t *cr, double red, double green, double blue)
cr->status = _cairo_gstate_set_rgb_color (cr->gstate, red, green, blue);
}
void
cairo_get_rgb_color (cairo_t *cr, double *red, double *green, double *blue)
{
/* XXX: Should we do anything with the return values in the error case? */
if (cr->status)
return;
cr->status = _cairo_gstate_get_rgb_color (cr->gstate, red, green, blue);
}
void
cairo_set_pattern (cairo_t *cr, cairo_surface_t *pattern)
{
@ -274,12 +252,6 @@ cairo_set_tolerance (cairo_t *cr, double tolerance)
cr->status = _cairo_gstate_set_tolerance (cr->gstate, tolerance);
}
double
cairo_get_tolerance (cairo_t *cr)
{
return _cairo_gstate_get_tolerance (cr->gstate);
}
void
cairo_set_alpha (cairo_t *cr, double alpha)
{
@ -291,12 +263,6 @@ cairo_set_alpha (cairo_t *cr, double alpha)
cr->status = _cairo_gstate_set_alpha (cr->gstate, alpha);
}
double
cairo_get_alpha (cairo_t *cr)
{
return _cairo_gstate_get_alpha (cr->gstate);
}
void
cairo_set_fill_rule (cairo_t *cr, cairo_fill_rule_t fill_rule)
{
@ -315,12 +281,6 @@ cairo_set_line_width (cairo_t *cr, double width)
cr->status = _cairo_gstate_set_line_width (cr->gstate, width);
}
double
cairo_get_line_width (cairo_t *cr)
{
return _cairo_gstate_get_line_width (cr->gstate);
}
void
cairo_set_line_cap (cairo_t *cr, cairo_line_cap_t line_cap)
{
@ -330,12 +290,6 @@ cairo_set_line_cap (cairo_t *cr, cairo_line_cap_t line_cap)
cr->status = _cairo_gstate_set_line_cap (cr->gstate, line_cap);
}
cairo_line_cap_t
cairo_get_line_cap (cairo_t *cr)
{
return _cairo_gstate_get_line_cap (cr->gstate);
}
void
cairo_set_line_join (cairo_t *cr, cairo_line_join_t line_join)
{
@ -345,12 +299,6 @@ cairo_set_line_join (cairo_t *cr, cairo_line_join_t line_join)
cr->status = _cairo_gstate_set_line_join (cr->gstate, line_join);
}
cairo_line_join_t
cairo_get_line_join (cairo_t *cr)
{
return _cairo_gstate_get_line_join (cr->gstate);
}
void
cairo_set_dash (cairo_t *cr, double *dashes, int ndash, double offset)
{
@ -369,12 +317,6 @@ cairo_set_miter_limit (cairo_t *cr, double limit)
cr->status = _cairo_gstate_set_miter_limit (cr->gstate, limit);
}
double
cairo_get_miter_limit (cairo_t *cr)
{
return _cairo_gstate_get_miter_limit (cr->gstate);
}
void
cairo_translate (cairo_t *cr, double tx, double ty)
{
@ -446,7 +388,7 @@ cairo_transform_point (cairo_t *cr, double *x, double *y)
if (cr->status)
return;
cr->status = cairo_gstateransform_point (cr->gstate, x, y);
cr->status = cairo_gstate_transform_point (cr->gstate, x, y);
}
void
@ -455,7 +397,7 @@ cairo_transform_distance (cairo_t *cr, double *dx, double *dy)
if (cr->status)
return;
cr->status = cairo_gstateransform_distance (cr->gstate, dx, dy);
cr->status = cairo_gstate_transform_distance (cr->gstate, dx, dy);
}
void
@ -513,9 +455,9 @@ cairo_curve_to (cairo_t *cr,
return;
cr->status = _cairo_gstate_curve_to (cr->gstate,
x1, y1,
x2, y2,
x3, y3);
x1, y1,
x2, y2,
x3, y3);
}
void
@ -546,9 +488,9 @@ cairo_rel_curve_to (cairo_t *cr,
return;
cr->status = _cairo_gstate_rel_curve_to (cr->gstate,
dx1, dy1,
dx2, dy2,
dx3, dy3);
dx1, dy1,
dx2, dy2,
dx3, dy3);
}
void
@ -566,6 +508,17 @@ cairo_rectangle (cairo_t *cr,
cairo_close_path (cr);
}
/* XXX: NYI
void
cairo_stroke_path (cairo_t *cr)
{
if (cr->status)
return;
cr->status = _cairo_gstate_stroke_path (cr->gstate);
}
*/
void
cairo_close_path (cairo_t *cr)
{
@ -575,16 +528,6 @@ cairo_close_path (cairo_t *cr)
cr->status = _cairo_gstate_close_path (cr->gstate);
}
void
cairo_get_current_point (cairo_t *cr, double *x, double *y)
{
/* XXX: Should we do anything with the return values in the error case? */
if (cr->status)
return;
cr->status = _cairo_gstate_get_current_point (cr->gstate, x, y);
}
void
cairo_stroke (cairo_t *cr)
{
@ -638,8 +581,8 @@ cairo_transform_font (cairo_t *cr,
if (cr->status)
return;
cr->status = cairo_gstateransform_font (cr->gstate,
a, b, c, d);
cr->status = cairo_gstate_transform_font (cr->gstate,
a, b, c, d);
}
void
@ -652,8 +595,8 @@ cairo_text_extents (cairo_t *cr,
if (cr->status)
return;
cr->status = cairo_gstateext_extents (cr->gstate, utf8,
x, y, width, height, dx, dy);
cr->status = cairo_gstate_text_extents (cr->gstate, utf8,
x, y, width, height, dx, dy);
}
void
@ -678,6 +621,73 @@ cairo_show_surface (cairo_t *cr,
surface, width, height);
}
cairo_operator_t
cairo_get_operator (cairo_t *cr)
{
return _cairo_gstate_get_operator (cr->gstate);
}
void
cairo_get_rgb_color (cairo_t *cr, double *red, double *green, double *blue)
{
_cairo_gstate_get_rgb_color (cr->gstate, red, green, blue);
}
double
cairo_get_alpha (cairo_t *cr)
{
return _cairo_gstate_get_alpha (cr->gstate);
}
double
cairo_get_tolerance (cairo_t *cr)
{
return _cairo_gstate_get_tolerance (cr->gstate);
}
void
cairo_get_current_point (cairo_t *cr, double *x, double *y)
{
_cairo_gstate_get_current_point (cr->gstate, x, y);
}
cairo_fill_rule_t
cairo_get_fill_rule (cairo_t *cr)
{
return _cairo_gstate_get_fill_rule (cr->gstate);
}
double
cairo_get_line_width (cairo_t *cr)
{
return _cairo_gstate_get_line_width (cr->gstate);
}
cairo_line_cap_t
cairo_get_line_cap (cairo_t *cr)
{
return _cairo_gstate_get_line_cap (cr->gstate);
}
cairo_line_join_t
cairo_get_line_join (cairo_t *cr)
{
return _cairo_gstate_get_line_join (cr->gstate);
}
double
cairo_get_miter_limit (cairo_t *cr)
{
return _cairo_gstate_get_miter_limit (cr->gstate);
}
cairo_surface_t *
cairo_get_target_surface (cairo_t *cr)
{
return _cairo_gstate_get_target_surface (cr->gstate);
}
cairo_status_t
cairo_get_status (cairo_t *cr)
{

View file

@ -28,7 +28,9 @@
#ifndef _CAIRO_H_
#define _CAIRO_H_
#include <Xc.h>
#include <X11/extensions/Xrender.h>
#include <fontconfig/fontconfig.h>
#include <ic.h>
typedef struct cairo cairo_t;
typedef struct cairo_surface cairo_surface_t;
@ -131,18 +133,33 @@ cairo_set_operator (cairo_t *cr, cairo_operator_t op);
/* XXX: Probably want to bite the bullet and expose a cairo_color_t object */
/* XXX: I've been trying to come up with a sane way to specify:
cairo_set_color (cairo_t *cr, cairo_color_t *color);
Keith wants to be able to support super-luminescent colors,
(premultiplied colors with R/G/B greater than alpha). The current
API does not allow that. Adding a premulitplied RGBA cairo_color_t
would do the trick.
One problem though is that alpha is currently orthogonal to
color. For example, show_surface uses gstate->alpha but ignores the
color. So, it doesn't seem be right to have cairo_set_color modify
the behavior of cairo_show_surface.
*/
void
cairo_set_rgb_color (cairo_t *cr, double red, double green, double blue);
void
cairo_set_alpha (cairo_t *cr, double alpha);
void
cairo_set_pattern (cairo_t *cr, cairo_surface_t *pattern);
void
cairo_set_tolerance (cairo_t *cr, double tolerance);
void
cairo_set_alpha (cairo_t *cr, double alpha);
typedef enum cairo_fill_rule {
CAIRO_FILL_RULE_WINDING,
CAIRO_FILL_RULE_EVEN_ODD
@ -239,14 +256,26 @@ cairo_rel_line_to (cairo_t *cr, double dx, double dy);
void
cairo_rel_curve_to (cairo_t *cr,
double dx1, double dy1,
double dx2, double dy2,
double dx3, double dy3);
double dx1, double dy1,
double dx2, double dy2,
double dx3, double dy3);
void
cairo_rectangle (cairo_t *cr,
double x, double y,
double width, double height);
double x, double y,
double width, double height);
/* XXX: This is the same name that PostScript uses, but to me the name
suggests an actual drawing operation ala cairo_stroke --- especially
since I want to add a cairo_path_t and with that it would be
natural to have "cairo_stroke_path (cairo_t *, cairo_path_t *)"
Maybe we could use something like "cairo_outline_path (cairo_t *)"?
*/
/* XXX: NYI
void
cairo_stroke_path (cairo_t *cr);
*/
void
cairo_close_path (cairo_t *cr);
@ -306,14 +335,14 @@ cairo_get_operator (cairo_t *cr);
void
cairo_get_rgb_color (cairo_t *cr, double *red, double *green, double *blue);
double
cairo_get_alpha (cairo_t *cr);
/* XXX: Do we want cairo_get_pattern as well? */
double
cairo_get_tolerance (cairo_t *cr);
double
cairo_get_alpha (cairo_t *cr);
void
cairo_get_current_point (cairo_t *cr, double *x, double *y);
@ -369,23 +398,23 @@ cairo_get_status_string (cairo_t *cr);
*/
cairo_surface_t *
cairo_surface_create_for_drawable (Display *dpy,
Drawable drawable,
Visual *visual,
cairo_format_t format,
Colormap colormap);
Drawable drawable,
Visual *visual,
cairo_format_t format,
Colormap colormap);
cairo_surface_t *
cairo_surface_create_for_image (char *data,
cairo_format_t format,
int width,
int height,
int stride);
cairo_format_t format,
int width,
int height,
int stride);
cairo_surface_t *
cairo_surface_create_similar (cairo_surface_t *other,
cairo_format_t format,
int width,
int height);
cairo_format_t format,
int width,
int height);
/* XXX: One problem with having RGB and A here in one function is that
it introduces the question of pre-multiplied vs. non-pre-multiplied
@ -393,28 +422,31 @@ cairo_surface_create_similar (cairo_surface_t *other,
other public functions need it. */
cairo_surface_t *
cairo_surface_create_similar_solid (cairo_surface_t *other,
cairo_format_t format,
int width,
int height,
double red,
double green,
double blue,
double alpha);
cairo_format_t format,
int width,
int height,
double red,
double green,
double blue,
double alpha);
void
cairo_surface_destroy (cairo_surface_t *surface);
/* XXX: Should this take an X/Y offset as well? (Probably) */
cairo_status_t
cairo_surface_put_image (cairo_surface_t *surface,
char *data,
int width,
int height,
int stride);
char *data,
int width,
int height,
int stride);
/* XXX: The Xc version of this function isn't quite working yet
/* XXX: NYI
cairo_status_t
cairo_surface_set_clip_region (cairo_surface_t *surface, Region region);
cairo_surface_clip_restore (cairo_surface_t *surface);
cairo_status_t
cairo_surface_clip_rectangle (cairo_surface_t *surface,
int x, int y,
int width, int height);
*/
/* XXX: Note: The current Render/Ic implementations don't do the right
@ -429,11 +461,11 @@ cairo_status_t
cairo_surface_get_matrix (cairo_surface_t *surface, cairo_matrix_t *matrix);
typedef enum cairo_filter {
CAIRO_FILTER_FAST = XcFilterFast,
CAIRO_FILTER_GOOD = XcFilterGood,
CAIRO_FILTER_BEST = XcFilterBest,
CAIRO_FILTER_NEAREST = XcFilterNearest,
CAIRO_FILTER_BILINEAR = XcFilterBilinear
CAIRO_FILTER_FAST = IcFilterFast,
CAIRO_FILTER_GOOD = IcFilterGood,
CAIRO_FILTER_BEST = IcFilterBest,
CAIRO_FILTER_NEAREST = IcFilterNearest,
CAIRO_FILTER_BILINEAR = IcFilterBilinear
} cairo_filter_t;
cairo_status_t

View file

@ -27,10 +27,13 @@
#include "cairoint.h"
static cairo_color_t CAIRO_COLOR_DEFAULT = { 1.0, 1.0, 1.0, 1.0, {0xffff, 0xffff, 0xffff, 0xffff}};
static cairo_color_t CAIRO_COLOR_DEFAULT = {
1.0, 1.0, 1.0, 1.0,
0xffff, 0xffff, 0xffff, 0xffff
};
static void
_cairo_color_compute_xc_color (cairo_color_t *color);
_cairo_color_compute_shorts (cairo_color_t *color);
void
_cairo_color_init (cairo_color_t *color)
@ -44,31 +47,22 @@ _cairo_color_fini (cairo_color_t *color)
/* Nothing to do here */
}
static void
_cairo_color_compute_xc_color (cairo_color_t *color)
{
color->xc_color.red = color->red * color->alpha * 0xffff;
color->xc_color.green = color->green * color->alpha * 0xffff;
color->xc_color.blue = color->blue * color->alpha * 0xffff;
color->xc_color.alpha = color->alpha * 0xffff;
}
void
_cairo_color_set_rgb (cairo_color_t *color, double red, double green, double blue)
{
color->red = red;
color->red = red;
color->green = green;
color->blue = blue;
color->blue = blue;
_cairo_color_compute_xc_color (color);
_cairo_color_compute_shorts (color);
}
void
_cairo_color_get_rgb (cairo_color_t *color, double *red, double *green, double *blue)
{
*red = color->red;
*red = color->red;
*green = color->green;
*blue = color->blue;
*blue = color->blue;
}
void
@ -76,5 +70,15 @@ _cairo_color_set_alpha (cairo_color_t *color, double alpha)
{
color->alpha = alpha;
_cairo_color_compute_xc_color (color);
_cairo_color_compute_shorts (color);
}
static void
_cairo_color_compute_shorts (cairo_color_t *color)
{
color->red_short = (color->red * color->alpha) * 0xffff;
color->green_short = (color->green * color->alpha) * 0xffff;
color->blue_short = (color->blue * color->alpha) * 0xffff;
color->alpha_short = color->alpha * 0xffff;
}

View file

@ -154,7 +154,7 @@ _cairo_font_resolve_xft_font (cairo_font_t *font, cairo_gstate_t *gstate, XftFon
FcPatternAddMatrix (pattern, "matrix", &fc_matrix);
/* XXX: Need to abandon Xft and use Xc instead */
/* XXX: Need to make a generic (non-Xft) backend for text. */
/* When I do that I can throw away these Display pointers */
font->dpy = gstate->surface->dpy;
match = XftFontMatch (font->dpy, DefaultScreen (font->dpy), pattern, &result);

View file

@ -227,12 +227,12 @@ _cairo_gstate_begin_group (cairo_gstate_t *gstate)
_cairo_color_init (&clear);
_cairo_color_set_alpha (&clear, 0);
XcFillRectangle (CAIRO_OPERATOR_SRC,
_cairo_surface_get_xc_surface (gstate->surface),
&clear.xc_color,
0, 0,
_cairo_surface_get_width (gstate->surface),
_cairo_surface_get_height (gstate->surface));
_cairo_surface_fill_rectangle (gstate->surface,
CAIRO_OPERATOR_SRC,
&clear,
0, 0,
_cairo_surface_get_width (gstate->surface),
_cairo_surface_get_height (gstate->surface));
return CAIRO_STATUS_SUCCESS;
}
@ -259,15 +259,15 @@ _cairo_gstate_end_group (cairo_gstate_t *gstate)
* XXX: This could be made much more efficient by using
_cairo_surface_get_damaged_width/Height if cairo_surface_t actually kept
track of such informaton. *
XcComposite (gstate->operator,
_cairo_surface_get_xc_surface (gstate->surface),
_cairo_surface_get_xc_surface (&mask),
_cairo_surface_get_xc_surface (gstate->parent_surface),
0, 0,
0, 0,
0, 0,
_cairo_surface_get_width (gstate->surface),
_cairo_surface_get_height (gstate->surface));
_cairo_surface_composite (gstate->operator,
gstate->surface,
mask,
gstate->parent_surface,
0, 0,
0, 0,
0, 0,
_cairo_surface_get_width (gstate->surface),
_cairo_surface_get_height (gstate->surface));
_cairo_surface_fini (&mask);
@ -415,6 +415,12 @@ _cairo_gstate_set_fill_rule (cairo_gstate_t *gstate, cairo_fill_rule_t fill_rule
return CAIRO_STATUS_SUCCESS;
}
cairo_status_t
_cairo_gstate_get_fill_rule (cairo_gstate_t *gstate)
{
return gstate->fill_rule;
}
cairo_status_t
_cairo_gstate_set_line_width (cairo_gstate_t *gstate, double width)
{
@ -495,7 +501,7 @@ _cairo_gstate_get_miter_limit (cairo_gstate_t *gstate)
}
cairo_status_t
cairo_gstate_translate (cairo_gstate_t *gstate, double tx, double ty)
_cairo_gstate_translate (cairo_gstate_t *gstate, double tx, double ty)
{
cairo_matrix_t tmp;
@ -597,7 +603,7 @@ _cairo_gstate_identity_matrix (cairo_gstate_t *gstate)
}
cairo_status_t
cairo_gstateransform_point (cairo_gstate_t *gstate, double *x, double *y)
_cairo_gstate_transform_point (cairo_gstate_t *gstate, double *x, double *y)
{
cairo_matrix_transform_point (&gstate->ctm, x, y);
@ -605,7 +611,7 @@ cairo_gstateransform_point (cairo_gstate_t *gstate, double *x, double *y)
}
cairo_status_t
cairo_gstateransform_distance (cairo_gstate_t *gstate, double *dx, double *dy)
_cairo_gstate_transform_distance (cairo_gstate_t *gstate, double *dx, double *dy)
{
cairo_matrix_transform_distance (&gstate->ctm, dx, dy);
@ -760,6 +766,17 @@ _cairo_gstate_rel_curve_to (cairo_gstate_t *gstate,
return status;
}
/* XXX: NYI
cairo_status_t
_cairo_gstate_stroke_path (cairo_gstate_t *gstate)
{
cairo_status_t status;
_cairo_pen_init (&gstate
return CAIRO_STATUS_SUCCESS;
}
*/
cairo_status_t
_cairo_gstate_close_path (cairo_gstate_t *gstate)
{
@ -823,12 +840,12 @@ _cairo_gstate_clip_and_composite_trapezoids (cairo_gstate_t *gstate,
cairo_surface_t *dst,
cairo_traps_t *traps)
{
if (traps->num_xtraps == 0)
if (traps->num_traps == 0)
return CAIRO_STATUS_SUCCESS;
if (gstate->clip.surface) {
XFixed xoff, yoff;
XTrapezoid *t;
cairo_fixed_t xoff, yoff;
cairo_trapezoid_t *t;
int i;
cairo_surface_t *intermediate, *white;
@ -844,12 +861,13 @@ _cairo_gstate_clip_and_composite_trapezoids (cairo_gstate_t *gstate,
gstate->clip.height,
0.0, 0.0, 0.0, 0.0);
/* Ugh. The Xc/ (Render) interface doesn't allow an offset for
the trapezoids. Need to manually shift all the coordinates
to align with the offset origin of the clip surface. */
/* Ugh. The cairo_composite/(Render) interface doesn't allow
an offset for the trapezoids. Need to manually shift all
the coordinates to align with the offset origin of the clip
surface. */
xoff = XDoubleToFixed (gstate->clip.x);
yoff = XDoubleToFixed (gstate->clip.y);
for (i=0, t=traps->xtraps; i < traps->num_xtraps; i++, t++) {
for (i=0, t=traps->traps; i < traps->num_traps; i++, t++) {
t->top -= yoff;
t->bottom -= yoff;
t->left.p1.x -= xoff;
@ -862,49 +880,45 @@ _cairo_gstate_clip_and_composite_trapezoids (cairo_gstate_t *gstate,
t->right.p2.y -= yoff;
}
XcCompositeTrapezoids (CAIRO_OPERATOR_ADD,
white->xc_surface,
intermediate->xc_surface,
0, 0,
traps->xtraps,
traps->num_xtraps);
XcComposite (CAIRO_OPERATOR_IN,
gstate->clip.surface->xc_surface,
NULL,
intermediate->xc_surface,
0, 0, 0, 0, 0, 0,
gstate->clip.width, gstate->clip.height);
XcComposite (operator,
src->xc_surface,
intermediate->xc_surface,
dst->xc_surface,
0, 0,
0, 0,
gstate->clip.x,
gstate->clip.y,
gstate->clip.width,
gstate->clip.height);
_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);
cairo_surface_destroy (intermediate);
cairo_surface_destroy (white);
} else {
double xoff, yoff;
if (traps->xtraps[0].left.p1.y < traps->xtraps[0].left.p2.y) {
xoff = traps->xtraps[0].left.p1.x;
yoff = traps->xtraps[0].left.p1.y;
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;
} else {
xoff = traps->xtraps[0].left.p2.x;
yoff = traps->xtraps[0].left.p2.y;
xoff = traps->traps[0].left.p2.x;
yoff = traps->traps[0].left.p2.y;
}
XcCompositeTrapezoids (gstate->operator,
src->xc_surface,
dst->xc_surface,
XFixedToDouble (xoff) - gstate->pattern_offset.x,
XFixedToDouble (yoff) - gstate->pattern_offset.y,
traps->xtraps,
traps->num_xtraps);
_cairo_surface_composite_trapezoids (gstate->operator,
src, dst,
XFixedToDouble (xoff) - gstate->pattern_offset.x,
XFixedToDouble (yoff) - gstate->pattern_offset.y,
traps->traps,
traps->num_traps);
}
return CAIRO_STATUS_SUCCESS;
@ -996,28 +1010,30 @@ _cairo_gstate_scale_font (cairo_gstate_t *gstate, double scale)
}
cairo_status_t
cairo_gstateransform_font (cairo_gstate_t *gstate,
double a, double b,
double c, double d)
_cairo_gstate_transform_font (cairo_gstate_t *gstate,
double a, double b,
double c, double d)
{
return cairo_font_transform (&gstate->font,
a, b, c, d);
}
cairo_status_t
cairo_gstateext_extents (cairo_gstate_t *gstate,
const unsigned char *utf8,
double *x, double *y,
double *width, double *height,
double *dx, double *dy)
_cairo_gstate_text_extents (cairo_gstate_t *gstate,
const unsigned char *utf8,
double *x, double *y,
double *width, double *height,
double *dx, double *dy)
{
XftFont *xft_font;
XGlyphInfo extents;
if (gstate->surface->dpy == 0)
return CAIRO_STATUS_SUCCESS;
_cairo_font_resolve_xft_font (&gstate->font, gstate, &xft_font);
/* XXX: Need to abandon Xft and use Xc instead */
/* (until I do, this call will croak on IcImage cairo_surface_ts */
/* XXX: Need to make a generic (non-Xft) backend for text. */
XftTextExtentsUtf8 (gstate->surface->dpy,
xft_font,
utf8,
@ -1050,14 +1066,12 @@ _cairo_gstate_show_text (cairo_gstate_t *gstate, const unsigned char *utf8)
_cairo_font_resolve_xft_font (&gstate->font, gstate, &xft_font);
/* XXX: Need to abandon Xft and use Xc instead */
/* (until I do, this call will croak on IcImage cairo_surface_ts */
/* (also, this means text clipping isn't working. Basically text is broken.) */
/* XXX: Need to make a generic (non-Xft) backend for text. */
XftTextRenderUtf8 (gstate->surface->dpy,
gstate->operator,
_cairo_surface_get_picture (gstate->solid),
gstate->solid->picture,
xft_font,
_cairo_surface_get_picture (gstate->surface),
gstate->surface->picture,
0, 0,
gstate->current_pt.x,
gstate->current_pt.y,
@ -1107,15 +1121,13 @@ _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. */
XcComposite (gstate->operator,
surface->xc_surface,
mask->xc_surface,
gstate->surface->xc_surface,
device_x, device_y,
0, 0,
device_x, device_y,
device_width,
device_height);
_cairo_surface_composite (gstate->operator,
surface, mask, gstate->surface,
device_x, device_y,
0, 0,
device_x, device_y,
device_width,
device_height);
cairo_surface_destroy (mask);

View file

@ -30,7 +30,7 @@
/* private functions */
static cairo_status_t
_cairo_path_add (cairo_path_t *path, cairo_path_op_t op, XPointFixed *pts, int num_pts);
_cairo_path_add (cairo_path_t *path, cairo_path_op_t op, cairo_point_t *pts, int num_pts);
static void
_cairo_path_add_op_buf (cairo_path_t *path, cairo_path_op_buf_t *op);
@ -60,7 +60,7 @@ static void
_cairo_path_arg_buf_destroy (cairo_path_arg_buf_t *buf);
static void
_cairo_path_arg_buf_add (cairo_path_arg_buf_t *arg, XPointFixed *pts, int num_pts);
_cairo_path_arg_buf_add (cairo_path_arg_buf_t *arg, cairo_point_t *pts, int num_pts);
void
_cairo_path_init (cairo_path_t *path)
@ -125,7 +125,7 @@ _cairo_path_fini (cairo_path_t *path)
cairo_status_t
_cairo_path_move_to (cairo_path_t *path, double x, double y)
{
XPointFixed pt;
cairo_point_t pt;
pt.x = XDoubleToFixed (x);
pt.y = XDoubleToFixed (y);
@ -136,7 +136,7 @@ _cairo_path_move_to (cairo_path_t *path, double x, double y)
cairo_status_t
_cairo_path_line_to (cairo_path_t *path, double x, double y)
{
XPointFixed pt;
cairo_point_t pt;
pt.x = XDoubleToFixed (x);
pt.y = XDoubleToFixed (y);
@ -150,7 +150,7 @@ _cairo_path_curve_to (cairo_path_t *path,
double x2, double y2,
double x3, double y3)
{
XPointFixed pt[3];
cairo_point_t pt[3];
pt[0].x = XDoubleToFixed (x1);
pt[0].y = XDoubleToFixed (y1);
@ -171,7 +171,7 @@ _cairo_path_close_path (cairo_path_t *path)
}
static cairo_status_t
_cairo_path_add (cairo_path_t *path, cairo_path_op_t op, XPointFixed *pts, int num_pts)
_cairo_path_add (cairo_path_t *path, cairo_path_op_t op, cairo_point_t *pts, int num_pts)
{
cairo_status_t status;
@ -300,7 +300,7 @@ _cairo_path_arg_buf_destroy (cairo_path_arg_buf_t *arg)
}
static void
_cairo_path_arg_buf_add (cairo_path_arg_buf_t *arg, XPointFixed *pts, int num_pts)
_cairo_path_arg_buf_add (cairo_path_arg_buf_t *arg, cairo_point_t *pts, int num_pts)
{
int i;
@ -328,9 +328,9 @@ _cairo_path_interpret (cairo_path_t *path, cairo_path_direction_t dir, const cai
cairo_path_op_t op;
cairo_path_arg_buf_t *arg_buf = path->arg_head;
int buf_i = 0;
XPointFixed pt[CAIRO_PATH_OP_MAX_ARGS];
XPointFixed current = {0, 0};
XPointFixed first = {0, 0};
cairo_point_t pt[CAIRO_PATH_OP_MAX_ARGS];
cairo_point_t current = {0, 0};
cairo_point_t first = {0, 0};
int has_current = 0;
int has_edge = 0;
int step = (dir == cairo_path_direction_forward) ? 1 : -1;
@ -375,7 +375,7 @@ _cairo_path_interpret (cairo_path_t *path, cairo_path_direction_t dir, const cai
switch (op) {
case cairo_path_op_move_to:
if (has_edge) {
status = (*cb->DoneSubPath) (closure, cairo_sub_path_done_cap);
status = (*cb->done_sub_path) (closure, cairo_sub_path_done_cap);
if (status)
return status;
}
@ -386,7 +386,7 @@ _cairo_path_interpret (cairo_path_t *path, cairo_path_direction_t dir, const cai
break;
case cairo_path_op_line_to:
if (has_current) {
status = (*cb->AddEdge) (closure, &current, &pt[0]);
status = (*cb->add_edge) (closure, &current, &pt[0]);
if (status)
return status;
current = pt[0];
@ -400,7 +400,7 @@ _cairo_path_interpret (cairo_path_t *path, cairo_path_direction_t dir, const cai
break;
case cairo_path_op_curve_to:
if (has_current) {
status = (*cb->AddSpline) (closure, &current, &pt[0], &pt[1], &pt[2]);
status = (*cb->add_spline) (closure, &current, &pt[0], &pt[1], &pt[2]);
if (status)
return status;
current = pt[2];
@ -414,8 +414,8 @@ _cairo_path_interpret (cairo_path_t *path, cairo_path_direction_t dir, const cai
break;
case cairo_path_op_close_path:
if (has_edge) {
(*cb->AddEdge) (closure, &current, &first);
(*cb->DoneSubPath) (closure, cairo_sub_path_done_join);
(*cb->add_edge) (closure, &current, &first);
(*cb->done_sub_path) (closure, cairo_sub_path_done_join);
}
current.x = 0;
current.y = 0;
@ -428,9 +428,9 @@ _cairo_path_interpret (cairo_path_t *path, cairo_path_direction_t dir, const cai
}
}
if (has_edge)
(*cb->DoneSubPath) (closure, cairo_sub_path_done_cap);
(*cb->done_sub_path) (closure, cairo_sub_path_done_cap);
return (*cb->DonePath) (closure);
return (*cb->done_path) (closure);
}

View file

@ -30,10 +30,10 @@
typedef struct cairo_path_bounder {
int has_pt;
XFixed min_x;
XFixed min_y;
XFixed max_x;
XFixed max_y;
cairo_fixed_t min_x;
cairo_fixed_t min_y;
cairo_fixed_t max_x;
cairo_fixed_t max_y;
} cairo_path_bounder_t;
static void
@ -43,14 +43,15 @@ static void
_cairo_path_bounder_fini (cairo_path_bounder_t *bounder);
static cairo_status_t
_cairo_path_bounder_add_point (cairo_path_bounder_t *bounder, XPointFixed *pt);
_cairo_path_bounder_add_point (cairo_path_bounder_t *bounder, cairo_point_t *pt);
static cairo_status_t
_cairo_path_bounder_add_edge (void *closure, XPointFixed *p1, XPointFixed *p2);
_cairo_path_bounder_add_edge (void *closure, cairo_point_t *p1, cairo_point_t *p2);
static cairo_status_t
_cairo_path_bounder_add_spline (void *closure,
XPointFixed *a, XPointFixed *b, XPointFixed *c, XPointFixed *d);
cairo_point_t *a, cairo_point_t *b,
cairo_point_t *c, cairo_point_t *d);
static cairo_status_t
_cairo_path_bounder_done_sub_path (void *closure, cairo_sub_path_done_t done);
@ -71,7 +72,7 @@ _cairo_path_bounder_fini (cairo_path_bounder_t *bounder)
}
static cairo_status_t
_cairo_path_bounder_add_point (cairo_path_bounder_t *bounder, XPointFixed *pt)
_cairo_path_bounder_add_point (cairo_path_bounder_t *bounder, cairo_point_t *pt)
{
if (bounder->has_pt) {
if (pt->x < bounder->min_x)
@ -98,7 +99,7 @@ _cairo_path_bounder_add_point (cairo_path_bounder_t *bounder, XPointFixed *pt)
}
static cairo_status_t
_cairo_path_bounder_add_edge (void *closure, XPointFixed *p1, XPointFixed *p2)
_cairo_path_bounder_add_edge (void *closure, cairo_point_t *p1, cairo_point_t *p2)
{
cairo_path_bounder_t *bounder = closure;
@ -110,7 +111,8 @@ _cairo_path_bounder_add_edge (void *closure, XPointFixed *p1, XPointFixed *p2)
static cairo_status_t
_cairo_path_bounder_add_spline (void *closure,
XPointFixed *a, XPointFixed *b, XPointFixed *c, XPointFixed *d)
cairo_point_t *a, cairo_point_t *b,
cairo_point_t *c, cairo_point_t *d)
{
cairo_path_bounder_t *bounder = closure;

View file

@ -41,10 +41,12 @@ static void
_cairo_filler_fini (cairo_filler_t *filler);
static cairo_status_t
_cairo_filler_add_edge (void *closure, XPointFixed *p1, XPointFixed *p2);
_cairo_filler_add_edge (void *closure, cairo_point_t *p1, cairo_point_t *p2);
static cairo_status_t
_cairo_filler_add_spline (void *closure, XPointFixed *a, XPointFixed *b, XPointFixed *c, XPointFixed *d);
_cairo_filler_add_spline (void *closure,
cairo_point_t *a, cairo_point_t *b,
cairo_point_t *c, cairo_point_t *d);
static cairo_status_t
_cairo_filler_done_sub_path (void *closure, cairo_sub_path_done_t done);
@ -68,7 +70,7 @@ _cairo_filler_fini (cairo_filler_t *filler)
}
static cairo_status_t
_cairo_filler_add_edge (void *closure, XPointFixed *p1, XPointFixed *p2)
_cairo_filler_add_edge (void *closure, cairo_point_t *p1, cairo_point_t *p2)
{
cairo_filler_t *filler = closure;
cairo_polygon_t *polygon = &filler->polygon;
@ -77,7 +79,9 @@ _cairo_filler_add_edge (void *closure, XPointFixed *p1, XPointFixed *p2)
}
static cairo_status_t
_cairo_filler_add_spline (void *closure, XPointFixed *a, XPointFixed *b, XPointFixed *c, XPointFixed *d)
_cairo_filler_add_spline (void *closure,
cairo_point_t *a, cairo_point_t *b,
cairo_point_t *c, cairo_point_t *d)
{
int i;
cairo_status_t status = CAIRO_STATUS_SUCCESS;

View file

@ -49,13 +49,15 @@ static void
_cairo_stroker_fini (cairo_stroker_t *stroker);
static cairo_status_t
_cairo_stroker_add_edge (void *closure, XPointFixed *p1, XPointFixed *p2);
_cairo_stroker_add_edge (void *closure, cairo_point_t *p1, cairo_point_t *p2);
static cairo_status_t
_cairo_stroker_add_edge_dashed (void *closure, XPointFixed *p1, XPointFixed *p2);
_cairo_stroker_add_edge_dashed (void *closure, cairo_point_t *p1, cairo_point_t *p2);
static cairo_status_t
_cairo_stroker_add_spline (void *closure, XPointFixed *a, XPointFixed *b, XPointFixed *c, XPointFixed *d);
_cairo_stroker_add_spline (void *closure,
cairo_point_t *a, cairo_point_t *b,
cairo_point_t *c, cairo_point_t *d);
static cairo_status_t
_cairo_stroker_done_sub_path (void *closure, cairo_sub_path_done_t done);
@ -64,7 +66,7 @@ static cairo_status_t
_cairo_stroker_done_path (void *closure);
static void
_translate_point (XPointFixed *pt, XPointFixed *offset);
_translate_point (cairo_point_t *pt, cairo_point_t *offset);
static int
_cairo_stroker_face_clockwise (cairo_stroke_face_t *in, cairo_stroke_face_t *out);
@ -125,7 +127,7 @@ _cairo_stroker_fini (cairo_stroker_t *stroker)
}
static void
_translate_point (XPointFixed *pt, XPointFixed *offset)
_translate_point (cairo_point_t *pt, cairo_point_t *offset)
{
pt->x += offset->x;
pt->y += offset->y;
@ -134,14 +136,12 @@ _translate_point (XPointFixed *pt, XPointFixed *offset)
static int
_cairo_stroker_face_clockwise (cairo_stroke_face_t *in, cairo_stroke_face_t *out)
{
XPointDouble d_in, d_out;
cairo_slope_t in_slope, out_slope;
d_in.x = XFixedToDouble (in->cw.x - in->pt.x);
d_in.y = XFixedToDouble (in->cw.y - in->pt.y);
d_out.x = XFixedToDouble (out->cw.x - out->pt.x);
d_out.y = XFixedToDouble (out->cw.y - out->pt.y);
_cairo_slope_init (&in_slope, &in->pt, &in->cw);
_cairo_slope_init (&out_slope, &out->pt, &out->cw);
return d_out.y * d_in.x > d_in.y * d_out.x;
return _cairo_slope_clockwise (&in_slope, &out_slope);
}
static cairo_status_t
@ -150,7 +150,7 @@ _cairo_stroker_join (cairo_stroker_t *stroker, cairo_stroke_face_t *in, cairo_st
cairo_status_t status;
cairo_gstate_t *gstate = stroker->gstate;
int clockwise = _cairo_stroker_face_clockwise (out, in);
XPointFixed *inpt, *outpt;
cairo_point_t *inpt, *outpt;
if (in->cw.x == out->cw.x
&& in->cw.y == out->cw.y
@ -171,7 +171,7 @@ _cairo_stroker_join (cairo_stroker_t *stroker, cairo_stroke_face_t *in, cairo_st
case CAIRO_LINE_JOIN_ROUND: {
int i;
int start, step, stop;
XPointFixed tri[3], initial, final;
cairo_point_t tri[3], initial, final;
cairo_pen_t *pen = &gstate->pen_regular;
tri[0] = in->pt;
@ -219,7 +219,7 @@ _cairo_stroker_join (cairo_stroker_t *stroker, cairo_stroke_face_t *in, cairo_st
XDouble x1, y1, x2, y2;
XDouble mx, my;
XDouble dx1, dx2, dy1, dy2;
XPointFixed outer;
cairo_point_t outer;
x1 = XFixedToDouble (inpt->x);
y1 = XFixedToDouble (inpt->y);
@ -256,7 +256,7 @@ _cairo_stroker_join (cairo_stroker_t *stroker, cairo_stroke_face_t *in, cairo_st
/* fall through ... */
}
case CAIRO_LINE_JOIN_BEVEL: {
XPointFixed tri[3];
cairo_point_t tri[3];
tri[0] = in->pt;
tri[1] = *inpt;
tri[2] = *outpt;
@ -279,8 +279,8 @@ _cairo_stroker_cap (cairo_stroker_t *stroker, cairo_stroke_face_t *f)
case CAIRO_LINE_CAP_ROUND: {
int i;
int start, stop;
cairo_slope_fixed_t slope;
XPointFixed tri[3];
cairo_slope_t slope;
cairo_point_t tri[3];
cairo_pen_t *pen = &gstate->pen_regular;
slope = f->dev_vector;
@ -303,8 +303,8 @@ _cairo_stroker_cap (cairo_stroker_t *stroker, cairo_stroke_face_t *f)
}
case CAIRO_LINE_CAP_SQUARE: {
double dx, dy;
cairo_slope_fixed_t fvector;
XPointFixed occw, ocw;
cairo_slope_t fvector;
cairo_point_t occw, ocw;
cairo_polygon_t polygon;
_cairo_polygon_init (&polygon);
@ -338,12 +338,12 @@ _cairo_stroker_cap (cairo_stroker_t *stroker, cairo_stroke_face_t *f)
}
static void
_compute_face (XPointFixed *pt, cairo_slope_fixed_t *slope, cairo_gstate_t *gstate, cairo_stroke_face_t *face)
_compute_face (cairo_point_t *pt, cairo_slope_t *slope, cairo_gstate_t *gstate, cairo_stroke_face_t *face)
{
double mag, tmp;
double dx, dy;
XPointDouble usr_vector;
XPointFixed offset_ccw, offset_cw;
cairo_point_t offset_ccw, offset_cw;
dx = XFixedToDouble (slope->dx);
dy = XFixedToDouble (slope->dy);
@ -388,12 +388,12 @@ _compute_face (XPointFixed *pt, cairo_slope_fixed_t *slope, cairo_gstate_t *gsta
}
static cairo_status_t
_cairo_stroker_add_sub_edge (cairo_stroker_t *stroker, XPointFixed *p1, XPointFixed *p2,
_cairo_stroker_add_sub_edge (cairo_stroker_t *stroker, cairo_point_t *p1, cairo_point_t *p2,
cairo_stroke_face_t *start, cairo_stroke_face_t *end)
{
cairo_gstate_t *gstate = stroker->gstate;
XPointFixed quad[4];
cairo_slope_fixed_t slope;
cairo_point_t quad[4];
cairo_slope_t slope;
if (p1->x == p2->x && p1->y == p2->y) {
/* XXX: Need to rethink how this case should be handled, (both
@ -402,7 +402,7 @@ _cairo_stroker_add_sub_edge (cairo_stroker_t *stroker, XPointFixed *p1, XPointFi
return CAIRO_STATUS_SUCCESS;
}
_compute_slope (p1, p2, &slope);
_cairo_slope_init (&slope, p1, p2);
_compute_face (p1, &slope, gstate, start);
/* XXX: This could be optimized slightly by not calling
@ -419,7 +419,7 @@ _cairo_stroker_add_sub_edge (cairo_stroker_t *stroker, XPointFixed *p1, XPointFi
}
static cairo_status_t
_cairo_stroker_add_edge (void *closure, XPointFixed *p1, XPointFixed *p2)
_cairo_stroker_add_edge (void *closure, cairo_point_t *p1, cairo_point_t *p2)
{
cairo_status_t status;
cairo_stroker_t *stroker = closure;
@ -458,7 +458,7 @@ _cairo_stroker_add_edge (void *closure, XPointFixed *p1, XPointFixed *p2)
* Dashed lines. Cap each dash end, join around turns when on
*/
static cairo_status_t
_cairo_stroker_add_edge_dashed (void *closure, XPointFixed *p1, XPointFixed *p2)
_cairo_stroker_add_edge_dashed (void *closure, cairo_point_t *p1, cairo_point_t *p2)
{
cairo_status_t status = CAIRO_STATUS_SUCCESS;
cairo_stroker_t *stroker = closure;
@ -466,7 +466,7 @@ _cairo_stroker_add_edge_dashed (void *closure, XPointFixed *p1, XPointFixed *p2)
double mag, remain, tmp;
double dx, dy;
double dx2, dy2;
XPointFixed fd1, fd2;
cairo_point_t fd1, fd2;
int first = 1;
cairo_stroke_face_t sub_start, sub_end;
@ -564,7 +564,9 @@ _cairo_stroker_add_edge_dashed (void *closure, XPointFixed *p1, XPointFixed *p2)
}
static cairo_status_t
_cairo_stroker_add_spline (void *closure, XPointFixed *a, XPointFixed *b, XPointFixed *c, XPointFixed *d)
_cairo_stroker_add_spline (void *closure,
cairo_point_t *a, cairo_point_t *b,
cairo_point_t *c, cairo_point_t *d)
{
cairo_status_t status = CAIRO_STATUS_SUCCESS;
cairo_stroker_t *stroker = closure;
@ -572,7 +574,7 @@ _cairo_stroker_add_spline (void *closure, XPointFixed *a, XPointFixed *b, XPoint
cairo_spline_t spline;
cairo_pen_t pen;
cairo_stroke_face_t start, end;
XPointFixed extra_points[4];
cairo_point_t extra_points[4];
status = _cairo_spline_init (&spline, a, b, c, d);
if (status == cairo_int_status_degenerate)
@ -645,7 +647,7 @@ _cairo_stroker_done_sub_path (void *closure, cairo_sub_path_done_t done)
/* fall through... */
case cairo_sub_path_done_cap:
if (stroker->have_first) {
XPointFixed t;
cairo_point_t t;
/* The initial cap needs an outward facing vector. Reverse everything */
stroker->first.usr_vector.x = -stroker->first.usr_vector.x;
stroker->first.usr_vector.y = -stroker->first.usr_vector.y;
@ -702,8 +704,8 @@ _cairo_path_stroke_to_traps (cairo_path_t *path, cairo_gstate_t *gstate, cairo_t
_cairo_stroker_init (&stroker, gstate, traps);
status = _cairo_path_interpret (path,
cairo_path_direction_forward,
callbacks, &stroker);
cairo_path_direction_forward,
callbacks, &stroker);
if (status) {
_cairo_stroker_fini (&stroker);
return status;

View file

@ -34,13 +34,7 @@ static void
_cairo_pen_compute_slopes (cairo_pen_t *pen);
static int
_slope_clockwise (cairo_slope_fixed_t *a, cairo_slope_fixed_t *b);
static int
_slope_counter_clockwise (cairo_slope_fixed_t *a, cairo_slope_fixed_t *b);
static int
_cairo_pen_vertex_compare_by_theta (const void *a, const void *b);
_pen_vertex_compare (const void *av, const void *bv);
static cairo_status_t
_cairo_pen_stroke_spline_half (cairo_pen_t *pen, cairo_spline_t *spline, cairo_pen_stroke_direction_t dir, cairo_polygon_t *polygon);
@ -60,8 +54,6 @@ cairo_status_t
_cairo_pen_init (cairo_pen_t *pen, double radius, cairo_gstate_t *gstate)
{
int i;
cairo_pen_vertex_t *v;
double dx, dy;
if (pen->num_vertices) {
/* XXX: It would be nice to notice that the pen is already properly constructed.
@ -87,17 +79,13 @@ _cairo_pen_init (cairo_pen_t *pen, double radius, cairo_gstate_t *gstate)
}
for (i=0; i < pen->num_vertices; i++) {
v = &pen->vertex[i];
v->theta = 2 * M_PI * i / (double) pen->num_vertices;
dx = radius * cos (v->theta);
dy = radius * sin (v->theta);
double theta = 2 * M_PI * i / (double) pen->num_vertices;
double dx = radius * cos (theta);
double dy = radius * sin (theta);
cairo_pen_vertex_t *v = &pen->vertex[i];
cairo_matrix_transform_distance (&gstate->ctm, &dx, &dy);
v->pt.x = XDoubleToFixed (dx);
v->pt.y = XDoubleToFixed (dy);
/* Recompute theta in device space */
v->theta = atan2 (v->pt.y, v->pt.x);
if (v->theta < 0)
v->theta += 2 * M_PI;
}
_cairo_pen_compute_slopes (pen);
@ -128,26 +116,10 @@ _cairo_pen_init_copy (cairo_pen_t *pen, cairo_pen_t *other)
return CAIRO_STATUS_SUCCESS;
}
static int
_cairo_pen_vertex_compare_by_theta (const void *a, const void *b)
{
double diff;
const cairo_pen_vertex_t *va = a;
const cairo_pen_vertex_t *vb = b;
diff = va->theta - vb->theta;
if (diff < 0)
return -1;
else if (diff > 0)
return 1;
else
return 0;
}
cairo_status_t
_cairo_pen_add_points (cairo_pen_t *pen, XPointFixed *pt, int num_pts)
_cairo_pen_add_points (cairo_pen_t *pen, cairo_point_t *pt, int num_pts)
{
int i, j;
int i;
cairo_pen_vertex_t *v, *v_next, *new_vertex;
pen->num_vertices += num_pts;
@ -162,21 +134,18 @@ _cairo_pen_add_points (cairo_pen_t *pen, XPointFixed *pt, int num_pts)
for (i=0; i < num_pts; i++) {
v = &pen->vertex[pen->num_vertices-(i+1)];
v->pt = pt[i];
v->theta = atan2 (v->pt.y, v->pt.x);
if (v->theta < 0)
v->theta += 2 * M_PI;
}
qsort (pen->vertex, pen->num_vertices, sizeof (cairo_pen_vertex_t), _cairo_pen_vertex_compare_by_theta);
qsort (pen->vertex, pen->num_vertices, sizeof (cairo_pen_vertex_t), _pen_vertex_compare);
/* eliminate any duplicate vertices */
for (i=0; i < pen->num_vertices - 1; i++ ) {
for (i=0; i < pen->num_vertices; i++ ) {
v = &pen->vertex[i];
v_next = &pen->vertex[i+1];
if (v->pt.x == v_next->pt.x && v->pt.y == v_next->pt.y) {
for (j=i+1; j < pen->num_vertices - 1; j++)
pen->vertex[j] = pen->vertex[j+1];
v_next = (i < pen->num_vertices - 1) ? &pen->vertex[i+1] : &pen->vertex[0];
if (_pen_vertex_compare (v, v_next) == 0) {
pen->num_vertices--;
memmove (&pen->vertex[i], &pen->vertex[i+1],
(pen->num_vertices - i) * sizeof (cairo_pen_vertex_t));
/* There may be more of the same duplicate, check again */
i--;
}
@ -219,34 +188,53 @@ _cairo_pen_compute_slopes (cairo_pen_t *pen)
v = &pen->vertex[i];
next = &pen->vertex[(i + 1) % pen->num_vertices];
_compute_slope (&prev->pt, &v->pt, &v->slope_cw);
_compute_slope (&v->pt, &next->pt, &v->slope_ccw);
_cairo_slope_init (&v->slope_cw, &prev->pt, &v->pt);
_cairo_slope_init (&v->slope_ccw, &v->pt, &next->pt);
}
}
/* Is a clockwise of b?
/* Is a further clockwise from (1,0) than b?
*
* NOTE: The strict equality here is not significant in and of itself,
* but there are functions up above that are sensitive to it,
* (cf. _cairo_pen_find_active_cw_vertex_index).
* There are a two special cases to consider:
* 1) a and b are not in the same half plane.
* 2) both a and b are on the X axis
* After that, the computation is a simple slope comparison.
*/
static int
_slope_clockwise (cairo_slope_fixed_t *a, cairo_slope_fixed_t *b)
_pen_vertex_compare (const void *av, const void *bv)
{
return ((cairo_fixed_48_16_t) b->dy * (cairo_fixed_48_16_t) a->dx
> (cairo_fixed_48_16_t) a->dy * (cairo_fixed_48_16_t) b->dx);
}
const cairo_pen_vertex_t *a = av;
const cairo_pen_vertex_t *b = bv;
cairo_fixed_48_16_t diff;
static int
_slope_counter_clockwise (cairo_slope_fixed_t *a, cairo_slope_fixed_t *b)
{
return ! _slope_clockwise (a, b);
int a_above = a->pt.y >= 0;
int b_above = b->pt.y >= 0;
if (a_above != b_above)
return b_above - a_above;
if (a->pt.y == 0 && b->pt.y == 0) {
int a_right = a->pt.x >= 0;
int b_right = b->pt.x >= 0;
if (a_right != b_right)
return b_right - a_right;
}
diff = ((cairo_fixed_48_16_t) a->pt.y * (cairo_fixed_48_16_t) b->pt.x
- (cairo_fixed_48_16_t) b->pt.y * (cairo_fixed_48_16_t) a->pt.x);
if (diff > 0)
return 1;
if (diff < 0)
return -1;
return 0;
}
/* Find active pen vertex for clockwise edge of stroke at the given slope.
*
* NOTE: The behavior of this function is sensitive to the sense of
* the inequality within _slope_clockwise/_slope_counter_clockwise.
* the inequality within _cairo_slope_clockwise/_cairo_slope_counter_clockwise.
*
* The issue is that the slope_ccw member of one pen vertex will be
* equivalent to the slope_cw member of the next pen vertex in a
@ -255,14 +243,14 @@ _slope_counter_clockwise (cairo_slope_fixed_t *a, cairo_slope_fixed_t *b)
*/
cairo_status_t
_cairo_pen_find_active_cw_vertex_index (cairo_pen_t *pen,
cairo_slope_fixed_t *slope,
cairo_slope_t *slope,
int *active)
{
int i;
for (i=0; i < pen->num_vertices; i++) {
if (_slope_clockwise (slope, &pen->vertex[i].slope_ccw)
&& _slope_counter_clockwise (slope, &pen->vertex[i].slope_cw))
if (_cairo_slope_clockwise (slope, &pen->vertex[i].slope_ccw)
&& _cairo_slope_counter_clockwise (slope, &pen->vertex[i].slope_cw))
break;
}
@ -274,23 +262,23 @@ _cairo_pen_find_active_cw_vertex_index (cairo_pen_t *pen,
/* Find active pen vertex for counterclockwise edge of stroke at the given slope.
*
* NOTE: The behavior of this function is sensitive to the sense of
* the inequality within _slope_clockwise/_slope_counter_clockwise.
* the inequality within _cairo_slope_clockwise/_cairo_slope_counter_clockwise.
*/
cairo_status_t
_cairo_pen_find_active_ccw_vertex_index (cairo_pen_t *pen,
cairo_slope_fixed_t *slope,
cairo_slope_t *slope,
int *active)
{
int i;
cairo_slope_fixed_t slope_reverse;
cairo_slope_t slope_reverse;
slope_reverse = *slope;
slope_reverse.dx = -slope_reverse.dx;
slope_reverse.dy = -slope_reverse.dy;
for (i=pen->num_vertices-1; i >= 0; i--) {
if (_slope_counter_clockwise (&pen->vertex[i].slope_ccw, &slope_reverse)
&& _slope_clockwise (&pen->vertex[i].slope_cw, &slope_reverse))
if (_cairo_slope_counter_clockwise (&pen->vertex[i].slope_ccw, &slope_reverse)
&& _cairo_slope_clockwise (&pen->vertex[i].slope_cw, &slope_reverse))
break;
}
@ -309,9 +297,9 @@ _cairo_pen_stroke_spline_half (cairo_pen_t *pen,
cairo_status_t status;
int start, stop, step;
int active = 0;
XPointFixed hull_pt;
cairo_slope_fixed_t slope, initial_slope, final_slope;
XPointFixed *pt = spline->pts;
cairo_point_t hull_pt;
cairo_slope_t slope, initial_slope, final_slope;
cairo_point_t *pt = spline->pts;
int num_pts = spline->num_pts;
if (dir == cairo_pen_stroke_direction_forward) {
@ -345,11 +333,11 @@ _cairo_pen_stroke_spline_half (cairo_pen_t *pen,
if (i + step == stop)
slope = final_slope;
else
_compute_slope (&pt[i], &pt[i+step], &slope);
if (_slope_counter_clockwise (&slope, &pen->vertex[active].slope_ccw)) {
_cairo_slope_init (&slope, &pt[i], &pt[i+step]);
if (_cairo_slope_counter_clockwise (&slope, &pen->vertex[active].slope_ccw)) {
if (++active == pen->num_vertices)
active = 0;
} else if (_slope_clockwise (&slope, &pen->vertex[active].slope_cw)) {
} else if (_cairo_slope_clockwise (&slope, &pen->vertex[active].slope_cw)) {
if (--active == -1)
active = pen->num_vertices - 1;
} else {

View file

@ -36,8 +36,7 @@ static cairo_status_t
_cairo_polygon_grow_by (cairo_polygon_t *polygon, int additional);
static void
_cairo_polygon_set_last_point (cairo_polygon_t *polygon, XPointFixed *pt);
_cairo_polygon_set_last_point (cairo_polygon_t *polygon, cairo_point_t *pt);
void
_cairo_polygon_init (cairo_polygon_t *polygon)
@ -94,14 +93,14 @@ _cairo_polygon_grow_by (cairo_polygon_t *polygon, int additional)
}
static void
_cairo_polygon_set_last_point (cairo_polygon_t *polygon, XPointFixed *pt)
_cairo_polygon_set_last_point (cairo_polygon_t *polygon, cairo_point_t *pt)
{
polygon->last_pt = *pt;
polygon->last_pt_defined = 1;
}
cairo_status_t
_cairo_polygon_add_edge (cairo_polygon_t *polygon, XPointFixed *p1, XPointFixed *p2)
_cairo_polygon_add_edge (cairo_polygon_t *polygon, cairo_point_t *p1, cairo_point_t *p2)
{
cairo_status_t status;
cairo_edge_t *edge;
@ -144,7 +143,7 @@ _cairo_polygon_add_edge (cairo_polygon_t *polygon, XPointFixed *p1, XPointFixed
}
cairo_status_t
_cairo_polygon_add_point (cairo_polygon_t *polygon, XPointFixed *pt)
_cairo_polygon_add_point (cairo_polygon_t *polygon, cairo_point_t *pt)
{
cairo_status_t status = CAIRO_STATUS_SUCCESS;

58
src/cairo_slope.c Normal file
View file

@ -0,0 +1,58 @@
/*
* Copyright © 2002 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"
void
_cairo_slope_init (cairo_slope_t *slope, cairo_point_t *a, cairo_point_t *b)
{
slope->dx = b->x - a->x;
slope->dy = b->y - a->y;
}
/* Is a clockwise of b?
*
* NOTE: The strict equality here is not significant in and of itself,
* but there are functions up above that are sensitive to it,
* (cf. _cairo_pen_find_active_cw_vertex_index).
*/
int
_cairo_slope_clockwise (cairo_slope_t *a, cairo_slope_t *b)
{
return ((cairo_fixed_48_16_t) b->dy * (cairo_fixed_48_16_t) a->dx
> (cairo_fixed_48_16_t) a->dy * (cairo_fixed_48_16_t) b->dx);
}
int
_cairo_slope_counter_clockwise (cairo_slope_t *a, cairo_slope_t *b)
{
return ! _cairo_slope_clockwise (a, b);
}

View file

@ -31,10 +31,10 @@ static cairo_status_t
_cairo_spline_grow_by (cairo_spline_t *spline, int additional);
static cairo_status_t
_cairo_spline_add_point (cairo_spline_t *spline, XPointFixed *pt);
_cairo_spline_add_point (cairo_spline_t *spline, cairo_point_t *pt);
static void
_lerp_half (XPointFixed *a, XPointFixed *b, XPointFixed *result);
_lerp_half (cairo_point_t *a, cairo_point_t *b, cairo_point_t *result);
static void
_de_casteljau (cairo_spline_t *spline, cairo_spline_t *s1, cairo_spline_t *s2);
@ -48,7 +48,9 @@ _cairo_spline_decompose_into (cairo_spline_t *spline, double tolerance_squared,
#define CAIRO_SPLINE_GROWTH_INC 100
cairo_int_status_t
_cairo_spline_init (cairo_spline_t *spline, XPointFixed *a, XPointFixed *b, XPointFixed *c, XPointFixed *d)
_cairo_spline_init (cairo_spline_t *spline,
cairo_point_t *a, cairo_point_t *b,
cairo_point_t *c, cairo_point_t *d)
{
spline->a = *a;
spline->b = *b;
@ -56,21 +58,21 @@ _cairo_spline_init (cairo_spline_t *spline, XPointFixed *a, XPointFixed *b, XP
spline->d = *d;
if (a->x != b->x || a->y != b->y) {
_compute_slope (&spline->a, &spline->b, &spline->initial_slope);
_cairo_slope_init (&spline->initial_slope, &spline->a, &spline->b);
} else if (a->x != c->x || a->y != c->y) {
_compute_slope (&spline->a, &spline->c, &spline->initial_slope);
_cairo_slope_init (&spline->initial_slope, &spline->a, &spline->c);
} else if (a->x != d->x || a->y != d->y) {
_compute_slope (&spline->a, &spline->d, &spline->initial_slope);
_cairo_slope_init (&spline->initial_slope, &spline->a, &spline->d);
} else {
return cairo_int_status_degenerate;
}
if (c->x != d->x || c->y != d->y) {
_compute_slope (&spline->c, &spline->d, &spline->final_slope);
_cairo_slope_init (&spline->final_slope, &spline->c, &spline->d);
} else if (b->x != d->x || b->y != d->y) {
_compute_slope (&spline->b, &spline->d, &spline->final_slope);
_cairo_slope_init (&spline->final_slope, &spline->b, &spline->d);
} else {
_compute_slope (&spline->a, &spline->d, &spline->final_slope);
_cairo_slope_init (&spline->final_slope, &spline->a, &spline->d);
}
spline->num_pts = 0;
@ -92,7 +94,7 @@ _cairo_spline_fini (cairo_spline_t *spline)
static cairo_status_t
_cairo_spline_grow_by (cairo_spline_t *spline, int additional)
{
XPointFixed *new_pts;
cairo_point_t *new_pts;
int old_size = spline->pts_size;
int new_size = spline->num_pts + additional;
@ -100,7 +102,7 @@ _cairo_spline_grow_by (cairo_spline_t *spline, int additional)
return CAIRO_STATUS_SUCCESS;
spline->pts_size = new_size;
new_pts = realloc (spline->pts, spline->pts_size * sizeof (XPointFixed));
new_pts = realloc (spline->pts, spline->pts_size * sizeof (cairo_point_t));
if (new_pts == NULL) {
spline->pts_size = old_size;
@ -113,7 +115,7 @@ _cairo_spline_grow_by (cairo_spline_t *spline, int additional)
}
static cairo_status_t
_cairo_spline_add_point (cairo_spline_t *spline, XPointFixed *pt)
_cairo_spline_add_point (cairo_spline_t *spline, cairo_point_t *pt)
{
cairo_status_t status;
@ -130,7 +132,7 @@ _cairo_spline_add_point (cairo_spline_t *spline, XPointFixed *pt)
}
static void
_lerp_half (XPointFixed *a, XPointFixed *b, XPointFixed *result)
_lerp_half (cairo_point_t *a, cairo_point_t *b, cairo_point_t *result)
{
result->x = a->x + ((b->x - a->x) >> 1);
result->y = a->y + ((b->y - a->y) >> 1);
@ -139,9 +141,9 @@ _lerp_half (XPointFixed *a, XPointFixed *b, XPointFixed *result)
static void
_de_casteljau (cairo_spline_t *spline, cairo_spline_t *s1, cairo_spline_t *s2)
{
XPointFixed ab, bc, cd;
XPointFixed abbc, bccd;
XPointFixed final;
cairo_point_t ab, bc, cd;
cairo_point_t abbc, bccd;
cairo_point_t final;
_lerp_half (&spline->a, &spline->b, &ab);
_lerp_half (&spline->b, &spline->c, &bc);
@ -162,7 +164,7 @@ _de_casteljau (cairo_spline_t *spline, cairo_spline_t *s1, cairo_spline_t *s2)
}
static double
_PointDistanceSquaredToPoint (XPointFixed *a, XPointFixed *b)
_PointDistanceSquaredToPoint (cairo_point_t *a, cairo_point_t *b)
{
double dx = XFixedToDouble (b->x - a->x);
double dy = XFixedToDouble (b->y - a->y);
@ -171,12 +173,12 @@ _PointDistanceSquaredToPoint (XPointFixed *a, XPointFixed *b)
}
static double
_PointDistanceSquaredToSegment (XPointFixed *p, XPointFixed *p1, XPointFixed *p2)
_PointDistanceSquaredToSegment (cairo_point_t *p, cairo_point_t *p1, cairo_point_t *p2)
{
double u;
double dx, dy;
double pdx, pdy;
XPointFixed px;
cairo_point_t px;
/* intersection point (px):

View file

@ -29,6 +29,34 @@
#include "cairoint.h"
static const XTransform CAIRO_XTRANSFORM_IDENTITY = {
{
{65536, 0, 0},
{ 0, 65536, 0},
{ 0, 0, 65536}
}
};
#define CAIRO_SURFACE_RENDER_AT_LEAST(surface, major, minor) \
(((surface)->render_major > major) ? 1 \
: ((surface)->render_major == major) ? ((surface)->render_minor >= minor) : 0)
#define CAIRO_SURFACE_RENDER_HAS_CREATE_PICTURE(surface) CAIRO_SURFACE_RENDER_AT_LEAST((surface), 0, 0)
#define CAIRO_SURFACE_RENDER_HAS_COMPOSITE(surface) CAIRO_SURFACE_RENDER_AT_LEAST((surface), 0, 0)
#define CAIRO_SURFACE_RENDER_HAS_FILL_RECTANGLE(surface) CAIRO_SURFACE_RENDER_AT_LEAST((surface), 0, 1)
#define CAIRO_SURFACE_RENDER_HAS_FILL_RECTANGLES(surface) CAIRO_SURFACE_RENDER_AT_LEAST((surface), 0, 1)
#define CAIRO_SURFACE_RENDER_HAS_DISJOINT(surface) CAIRO_SURFACE_RENDER_AT_LEAST((surface), 0, 2)
#define CAIRO_SURFACE_RENDER_HAS_CONJOINT(surface) CAIRO_SURFACE_RENDER_AT_LEAST((surface), 0, 2)
#define CAIRO_SURFACE_RENDER_HAS_TRAPEZOIDS(surface) CAIRO_SURFACE_RENDER_AT_LEAST((surface), 0, 4)
#define CAIRO_SURFACE_RENDER_HAS_TRIANGLES(surface) CAIRO_SURFACE_RENDER_AT_LEAST((surface), 0, 4)
#define CAIRO_SURFACE_RENDER_HAS_TRISTRIP(surface) CAIRO_SURFACE_RENDER_AT_LEAST((surface), 0, 4)
#define CAIRO_SURFACE_RENDER_HAS_TRIFAN(surface) CAIRO_SURFACE_RENDER_AT_LEAST((surface), 0, 4)
#define CAIRO_SURFACE_RENDER_HAS_PICTURE_TRANSFORM(surface) CAIRO_SURFACE_RENDER_AT_LEAST((surface), 0, 6)
cairo_surface_t *
cairo_surface_create_for_drawable (Display *dpy,
Drawable drawable,
@ -42,20 +70,35 @@ cairo_surface_create_for_drawable (Display *dpy,
if (surface == NULL)
return NULL;
surface->dpy = dpy;
surface->image_data = NULL;
surface->xc_surface = XcSurfaceCreateForDrawable (dpy, drawable, visual, format, colormap);
if (surface->xc_surface == NULL) {
free (surface);
return NULL;
}
/* XXX: We should really get this value from somewhere like Xft.dpy */
surface->ppm = 3780;
surface->ref_count = 1;
surface->dpy = dpy;
surface->image_data = NULL;
surface->icimage = NULL;
surface->type = CAIRO_SURFACE_TYPE_DRAWABLE;
surface->xtransform = CAIRO_XTRANSFORM_IDENTITY;
surface->gc = 0;
surface->drawable = drawable;
surface->visual = visual;
if (! XRenderQueryVersion (dpy, &surface->render_major, &surface->render_minor)) {
surface->render_major = -1;
surface->render_minor = -1;
}
/* 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),
0, NULL);
return surface;
}
@ -144,25 +187,31 @@ cairo_surface_create_for_image (char *data,
if (surface == NULL)
return NULL;
/* Assume a default until the user lets us know otherwise */
surface->ppm = 3780;
surface->ref_count = 1;
surface->dpy = NULL;
surface->image_data = NULL;
image = IcImageCreateForData ((IcBits *) data, &icformat, width, height, cairo_format_bpp (format), stride);
if (image == NULL) {
free (surface);
return NULL;
}
surface->xc_surface = XcSurfaceCreateForIcImage (image);
if (surface->xc_surface == NULL) {
IcImageDestroy (image);
free (surface);
return NULL;
}
surface->type = CAIRO_SURFACE_TYPE_ICIMAGE;
surface->xtransform = CAIRO_XTRANSFORM_IDENTITY;
/* Assume a default until the user lets us know otherwise */
surface->ppm = 3780;
surface->gc = 0;
surface->drawable = 0;
surface->visual = NULL;
surface->render_major = -1;
surface->render_minor = -1;
surface->ref_count = 1;
surface->picture = 0;
surface->icimage = image;
return surface;
}
@ -205,8 +254,6 @@ cairo_surface_create_similar_solid (cairo_surface_t *other,
cairo_surface_t *surface = NULL;
cairo_color_t color;
/* XXX: create_similar should perhaps move down to Xc, (then we
could drop xrsurface->dpy as well) */
if (other->dpy) {
Display *dpy = other->dpy;
int scr = DefaultScreen (dpy);
@ -270,32 +317,130 @@ cairo_surface_destroy (cairo_surface_t *surface)
if (surface->ref_count)
return;
surface->dpy = 0;
XcSurfaceDestroy (surface->xc_surface);
surface->xc_surface = NULL;
if (surface->picture)
XRenderFreePicture (surface->dpy, surface->picture);
if (surface->icimage)
IcImageDestroy (surface->icimage);
if (surface->image_data)
free (surface->image_data);
surface->image_data = NULL;
surface->dpy = 0;
free (surface);
}
static void
_cairo_surface_ensure_gc (cairo_surface_t *surface)
{
if (surface->gc)
return;
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)
char *data,
int width,
int height,
int stride)
{
XcSurfacePutImage (surface->xc_surface, data,
width, height, 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;
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_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);
} 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 */
/* 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.)
if (surface->type == CAIRO_SURFACE_TYPE_ICIMAGE)
return;
if (surface->icimage) {
IcImageDestroy (surface->icimage);
surface->icimage = NULL;
}
_cairo_surface_ensure_GC (surface);
surface->ximage = XGetImage (surface->dpy,
surface->drawable,
surface->gc,
0, 0,
width, height,
AllPlanes, ZPixmap);
surface->icimage = IcImageCreateForData (image->data,
IcFormat *format,
int width, int height,
int bpp, int stride);
*/
}
void
_cairo_surface_push_image (cairo_surface_t *surface)
{
/* XXX: NYI
if (surface->type == CAIRO_SURFACE_TYPE_ICIMAGE)
return;
if (surface->ximage == NULL)
return;
_cairo_surface_ensure_GC (surface);
XPutImage (surface->dpy,
surface->drawable,
surface->gc,
surface->ximage,
0, 0,
0, 0,
width, height);
* 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
nothing else, that would eliminate the two different transform data
@ -303,22 +448,31 @@ cairo_surface_put_image (cairo_surface_t *surface,
cairo_status_t
cairo_surface_set_matrix (cairo_surface_t *surface, cairo_matrix_t *matrix)
{
XTransform xtransform;
XTransform *xtransform = &surface->xtransform;
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]);
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]);
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[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);
xtransform->matrix[2][0] = 0;
xtransform->matrix[2][1] = 0;
xtransform->matrix[2][2] = XDoubleToFixed (1);
XcSurfaceSetTransform (surface->xc_surface,
&xtransform);
if (surface->picture) {
if (CAIRO_SURFACE_RENDER_HAS_PICTURE_TRANSFORM (surface))
XRenderSetPictureTransform (surface->dpy, surface->picture, xtransform);
/* XXX: Need support here if using an old RENDER without support
for SetPictureTransform */
}
/* 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 CAIRO_STATUS_SUCCESS;
}
@ -326,51 +480,134 @@ cairo_surface_set_matrix (cairo_surface_t *surface, cairo_matrix_t *matrix)
cairo_status_t
cairo_surface_get_matrix (cairo_surface_t *surface, cairo_matrix_t *matrix)
{
XTransform xtransform;
XTransform *xtransform = &surface->xtransform;
XcSurfaceGetTransform (surface->xc_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] = 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][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] = XFixedToDouble (xtransform->matrix[1][0]);
matrix->m[1][1] = XFixedToDouble (xtransform->matrix[1][1]);
matrix->m[2][1] = XFixedToDouble (xtransform->matrix[1][2]);
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";
}
}
cairo_status_t
cairo_surface_set_filter (cairo_surface_t *surface, cairo_filter_t filter)
{
XcSurfaceSetFilter (surface->xc_surface, filter);
if (surface->picture) {
XRenderSetPictureFilter (surface->dpy, surface->picture,
_render_filter_name (filter), NULL, 0);
}
if (surface->icimage) {
IcImageSetFilter (surface->icimage, filter);
}
return CAIRO_STATUS_SUCCESS;
}
/* XXX: The Xc version of this function isn't quite working yet
/* XXX: NYI
cairo_status_t
cairo_surface_set_clip_region (cairo_surface_t *surface, Region region)
cairo_surface_clip_rectangle (cairo_surface_t *surface,
int x, int y,
int width, int height)
{
XcSurfaceSetClipRegion (surface->xc_surface, region);
return CAIRO_STATUS_SUCCESS;
}
*/
/* XXX: NYI
cairo_status_t
cairo_surface_clip_restore (cairo_surface_t *surface);
*/
cairo_status_t
cairo_surface_set_repeat (cairo_surface_t *surface, int repeat)
{
XcSurfaceSetRepeat (surface->xc_surface, repeat);
if (surface->picture) {
unsigned long mask;
XRenderPictureAttributes pa;
mask = CPRepeat;
pa.repeat = repeat;
XRenderChangePicture (surface->dpy, surface->picture, mask, &pa);
}
if (surface->icimage) {
IcImageSetRepeat (surface->icimage, repeat);
}
return CAIRO_STATUS_SUCCESS;
}
/* XXX: This function is going away, right? */
Picture
_cairo_surface_get_picture (cairo_surface_t *surface)
void
_cairo_surface_composite (cairo_operator_t operator,
cairo_surface_t *src,
cairo_surface_t *mask,
cairo_surface_t *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)
{
return XcSurfaceGetPicture (surface->xc_surface);
if (dst->type == CAIRO_SURFACE_TYPE_DRAWABLE
&& CAIRO_SURFACE_RENDER_HAS_COMPOSITE (dst)
&& src->dpy == dst->dpy
&& (mask == NULL || mask->dpy == dst->dpy)) {
XRenderComposite (dst->dpy, operator,
src->picture,
mask ? mask->picture : 0,
dst->picture,
src_x, src_y,
mask_x, mask_y,
dst_x, dst_y,
width, height);
} else {
_cairo_surface_pull_image (src);
_cairo_surface_pull_image (mask);
_cairo_surface_pull_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);
_cairo_surface_push_image (dst);
}
}
void
@ -382,10 +619,80 @@ _cairo_surface_fill_rectangle (cairo_surface_t *surface,
int width,
int height)
{
XcFillRectangle (operator,
surface->xc_surface,
&color->xc_color,
x, y,
width, height);
cairo_rectangle_t rect;
rect.x = x;
rect.y = y;
rect.width = width;
rect.height = height;
_cairo_surface_fill_rectangles (surface, operator, color, &rect, 1);
}
void
_cairo_surface_fill_rectangles (cairo_surface_t *surface,
cairo_operator_t operator,
const cairo_color_t *color,
cairo_rectangle_t *rects,
int num_rects)
{
if (surface->type == CAIRO_SURFACE_TYPE_DRAWABLE
&& CAIRO_SURFACE_RENDER_HAS_FILL_RECTANGLE (surface)) {
XRenderColor render_color;
render_color.red = color->red_short;
render_color.green = color->green_short;
render_color.blue = color->blue_short;
render_color.alpha = color->alpha_short;
/* XXX: This XRectangle cast is evil... it needs to go away somehow. */
XRenderFillRectangles (surface->dpy, operator, surface->picture,
&render_color, (XRectangle *) rects, num_rects);
} else {
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;
_cairo_surface_pull_image (surface);
/* XXX: The IcRectangle cast is evil... it needs to go away somehow. */
IcFillRectangles (operator, surface->icimage,
&ic_color, (IcRectangle *) rects, num_rects);
_cairo_surface_push_image (surface);
}
}
void
_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 num_traps)
{
if (dst->type == CAIRO_SURFACE_TYPE_DRAWABLE
&& CAIRO_SURFACE_RENDER_HAS_TRAPEZOIDS (dst)
&& src->dpy == dst->dpy) {
/* XXX: The XTrapezoid cast is evil and needs to go away somehow. */
XRenderCompositeTrapezoids (dst->dpy, operator, src->picture, dst->picture,
XRenderFindStandardFormat (dst->dpy, PictStandardA8),
xSrc, ySrc, (XTrapezoid *) traps, num_traps);
} else {
_cairo_surface_pull_image (src);
_cairo_surface_pull_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);
_cairo_surface_push_image (dst);
}
}

View file

@ -32,13 +32,13 @@ static cairo_status_t
cairo_traps_grow_by (cairo_traps_t *traps, int additional);
cairo_status_t
cairo_traps_add_trap (cairo_traps_t *traps, XFixed top, XFixed bottom,
XLineFixed *left, XLineFixed *right);
cairo_traps_add_trap (cairo_traps_t *traps, cairo_fixed_t top, cairo_fixed_t bottom,
cairo_line_t *left, cairo_line_t *right);
cairo_status_t
cairo_traps_add_trap_from_points (cairo_traps_t *traps, XFixed top, XFixed bottom,
XPointFixed left_p1, XPointFixed left_p2,
XPointFixed right_p1, XPointFixed right_p2);
cairo_traps_add_trap_from_points (cairo_traps_t *traps, cairo_fixed_t top, cairo_fixed_t bottom,
cairo_point_t left_p1, cairo_point_t left_p2,
cairo_point_t right_p1, cairo_point_t right_p2);
static int
_compare_point_fixed_by_y (const void *av, const void *bv);
@ -50,72 +50,72 @@ static int
_compare_cairo_edge_by_slope (const void *av, const void *bv);
static cairo_fixed_16_16_t
_compute_x (XLineFixed *line, XFixed y);
_compute_x (cairo_line_t *line, cairo_fixed_t y);
static double
_compute_inverse_slope (XLineFixed *l);
_compute_inverse_slope (cairo_line_t *l);
static double
_compute_x_intercept (XLineFixed *l, double inverse_slope);
_compute_x_intercept (cairo_line_t *l, double inverse_slope);
static XFixed
_line_segs_intersect_ceil (XLineFixed *left, XLineFixed *right, XFixed *y_ret);
static cairo_fixed_t
_line_segs_intersect_ceil (cairo_line_t *left, cairo_line_t *right, cairo_fixed_t *y_ret);
void
cairo_traps_init (cairo_traps_t *traps)
{
traps->num_xtraps = 0;
traps->num_traps = 0;
traps->xtraps_size = 0;
traps->xtraps = NULL;
traps->traps_size = 0;
traps->traps = NULL;
}
void
cairo_traps_fini (cairo_traps_t *traps)
{
if (traps->xtraps_size) {
free (traps->xtraps);
traps->xtraps = NULL;
traps->xtraps_size = 0;
traps->num_xtraps = 0;
if (traps->traps_size) {
free (traps->traps);
traps->traps = NULL;
traps->traps_size = 0;
traps->num_traps = 0;
}
}
cairo_status_t
cairo_traps_add_trap (cairo_traps_t *traps, XFixed top, XFixed bottom,
XLineFixed *left, XLineFixed *right)
cairo_traps_add_trap (cairo_traps_t *traps, cairo_fixed_t top, cairo_fixed_t bottom,
cairo_line_t *left, cairo_line_t *right)
{
cairo_status_t status;
XTrapezoid *trap;
cairo_trapezoid_t *trap;
if (top == bottom) {
return CAIRO_STATUS_SUCCESS;
}
if (traps->num_xtraps >= traps->xtraps_size) {
if (traps->num_traps >= traps->traps_size) {
status = cairo_traps_grow_by (traps, CAIRO_TRAPS_GROWTH_INC);
if (status)
return status;
}
trap = &traps->xtraps[traps->num_xtraps];
trap = &traps->traps[traps->num_traps];
trap->top = top;
trap->bottom = bottom;
trap->left = *left;
trap->right = *right;
traps->num_xtraps++;
traps->num_traps++;
return CAIRO_STATUS_SUCCESS;
}
cairo_status_t
cairo_traps_add_trap_from_points (cairo_traps_t *traps, XFixed top, XFixed bottom,
XPointFixed left_p1, XPointFixed left_p2,
XPointFixed right_p1, XPointFixed right_p2)
cairo_traps_add_trap_from_points (cairo_traps_t *traps, cairo_fixed_t top, cairo_fixed_t bottom,
cairo_point_t left_p1, cairo_point_t left_p2,
cairo_point_t right_p1, cairo_point_t right_p2)
{
XLineFixed left;
XLineFixed right;
cairo_line_t left;
cairo_line_t right;
left.p1 = left_p1;
left.p2 = left_p2;
@ -129,23 +129,23 @@ cairo_traps_add_trap_from_points (cairo_traps_t *traps, XFixed top, XFixed botto
static cairo_status_t
cairo_traps_grow_by (cairo_traps_t *traps, int additional)
{
XTrapezoid *new_xtraps;
int old_size = traps->xtraps_size;
int new_size = traps->num_xtraps + additional;
cairo_trapezoid_t *new_traps;
int old_size = traps->traps_size;
int new_size = traps->num_traps + additional;
if (new_size <= traps->xtraps_size) {
if (new_size <= traps->traps_size) {
return CAIRO_STATUS_SUCCESS;
}
traps->xtraps_size = new_size;
new_xtraps = realloc (traps->xtraps, traps->xtraps_size * sizeof (XTrapezoid));
traps->traps_size = new_size;
new_traps = realloc (traps->traps, traps->traps_size * sizeof (cairo_trapezoid_t));
if (new_xtraps == NULL) {
traps->xtraps_size = old_size;
if (new_traps == NULL) {
traps->traps_size = old_size;
return CAIRO_STATUS_NO_MEMORY;
}
traps->xtraps = new_xtraps;
traps->traps = new_traps;
return CAIRO_STATUS_SUCCESS;
}
@ -153,7 +153,7 @@ cairo_traps_grow_by (cairo_traps_t *traps, int additional)
static int
_compare_point_fixed_by_y (const void *av, const void *bv)
{
const XPointFixed *a = av, *b = bv;
const cairo_point_t *a = av, *b = bv;
int ret = a->y - b->y;
if (ret == 0) {
@ -163,15 +163,15 @@ _compare_point_fixed_by_y (const void *av, const void *bv)
}
cairo_status_t
cairo_traps_tessellate_triangle (cairo_traps_t *traps, XPointFixed t[3])
cairo_traps_tessellate_triangle (cairo_traps_t *traps, cairo_point_t t[3])
{
cairo_status_t status;
XLineFixed line;
cairo_line_t line;
cairo_fixed_16_16_t intersect;
XPointFixed tsort[3];
cairo_point_t tsort[3];
memcpy (tsort, t, 3 * sizeof (XPointFixed));
qsort (tsort, 3, sizeof (XPointFixed), _compare_point_fixed_by_y);
memcpy (tsort, t, 3 * sizeof (cairo_point_t));
qsort (tsort, 3, sizeof (cairo_point_t), _compare_point_fixed_by_y);
/* horizontal top edge requires special handling */
if (tsort[0].y == tsort[1].y) {
@ -226,11 +226,11 @@ cairo_traps_tessellate_triangle (cairo_traps_t *traps, XPointFixed t[3])
/* Warning: This function reorders the elements of the array provided. */
cairo_status_t
cairo_traps_tessellate_rectangle (cairo_traps_t *traps, XPointFixed q[4])
cairo_traps_tessellate_rectangle (cairo_traps_t *traps, cairo_point_t q[4])
{
cairo_status_t status;
qsort (q, 4, sizeof (XPointFixed), _compare_point_fixed_by_y);
qsort (q, 4, sizeof (cairo_point_t), _compare_point_fixed_by_y);
if (q[1].x > q[2].x) {
status = cairo_traps_add_trap_from_points (traps,
@ -335,7 +335,7 @@ _det (double a, double b, double c, double d)
}
static int
_lines_intersect (XLineFixed *l1, XLineFixed *l2, XFixed *y_intersection)
_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);
@ -362,7 +362,7 @@ _lines_intersect (XLineFixed *l1, XLineFixed *l2, XFixed *y_intersection)
}
*/
static cairo_fixed_16_16_t
_compute_x (XLineFixed *line, XFixed y)
_compute_x (cairo_line_t *line, cairo_fixed_t y)
{
cairo_fixed_16_16_t dx = line->p2.x - line->p1.x;
cairo_fixed_32_32_t ex = (cairo_fixed_48_16_t) (y - line->p1.y) * (cairo_fixed_48_16_t) dx;
@ -372,20 +372,20 @@ _compute_x (XLineFixed *line, XFixed y)
}
static double
_compute_inverse_slope (XLineFixed *l)
_compute_inverse_slope (cairo_line_t *l)
{
return (XFixedToDouble (l->p2.x - l->p1.x) /
XFixedToDouble (l->p2.y - l->p1.y));
}
static double
_compute_x_intercept (XLineFixed *l, double inverse_slope)
_compute_x_intercept (cairo_line_t *l, double inverse_slope)
{
return XFixedToDouble (l->p1.x) - inverse_slope * XFixedToDouble (l->p1.y);
}
static int
_line_segs_intersect_ceil (XLineFixed *l1, XLineFixed *l2, XFixed *y_ret)
_line_segs_intersect_ceil (cairo_line_t *l1, cairo_line_t *l2, cairo_fixed_t *y_ret)
{
/*
* x = m1y + b1
@ -406,7 +406,7 @@ _line_segs_intersect_ceil (XLineFixed *l1, XLineFixed *l2, XFixed *y_ret)
y_intersect = XDoubleToFixed ((b2 - b1) / (m1 - m2));
if (m1 < m2) {
XLineFixed *t;
cairo_line_t *t;
t = l1;
l1 = l2;
l2 = t;
@ -418,6 +418,22 @@ _line_segs_intersect_ceil (XLineFixed *l1, XLineFixed *l2, XFixed *y_ret)
most, we must increment once. */
if (_compute_x (l2, y_intersect) > _compute_x (l1, y_intersect))
y_intersect++;
/* XXX: Hmm... Keith's error calculations said we'd at most be off
by one sub-pixel. But, I found that the paint-fill-BE-01.svg
test from the W3C SVG conformance suite definitely requires two
increments.
It could be that we need one to overcome the error, and another
to round up.
It would be nice to be sure this code is correct, (but we can't
do the while loop as it will work for way to long on
exceedingly distant intersections with large errors that we
really don't care about anyway as they will be ignored by the
calling function.
*/
if (_compute_x (l2, y_intersect) > _compute_x (l1, y_intersect))
y_intersect++;
*y_ret = y_intersect;
@ -458,7 +474,7 @@ cairo_traps_tessellate_polygon (cairo_traps_t *traps,
{
cairo_status_t status;
int i, active, inactive;
XFixed y, y_next, intersect;
cairo_fixed_t y, y_next, intersect;
int in_out, num_edges = poly->num_edges;
cairo_edge_t *edges = poly->edges;

View file

@ -70,6 +70,40 @@ typedef long long int cairo_fixed_32_32_t;
typedef cairo_fixed_32_32_t cairo_fixed_48_16_t;
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;
typedef struct cairo_point {
cairo_fixed_t x;
cairo_fixed_t y;
} cairo_point_t;
typedef struct cairo_slope
{
cairo_fixed_t dx;
cairo_fixed_t dy;
} cairo_slope_t;
typedef struct cairo_point_double {
double x;
double y;
} cairo_point_double_t;
typedef struct cairo_line {
cairo_point_t p1;
cairo_point_t p2;
} cairo_line_t;
typedef struct cairo_trapezoid {
cairo_fixed_t top, bottom;
cairo_line_t left, right;
} cairo_trapezoid_t;
typedef struct cairo_rectangle_int {
short x, y;
unsigned short width, height;
} cairo_rectangle_t;
/* Sure wish C had a real enum type so that this would be distinct
from cairo_status_t. Oh well, without that, I'll use this bogus 1000
offset */
@ -95,10 +129,10 @@ typedef enum cairo_sub_path_done {
} cairo_sub_path_done_t;
typedef struct cairo_path_callbacks {
cairo_status_t (*AddEdge) (void *closure, XPointFixed *p1, XPointFixed *p2);
cairo_status_t (*AddSpline) (void *closure, XPointFixed *a, XPointFixed *b, XPointFixed *c, XPointFixed *d);
cairo_status_t (*DoneSubPath) (void *closure, cairo_sub_path_done_t done);
cairo_status_t (*DonePath) (void *closure);
cairo_status_t (*add_edge) (void *closure, cairo_point_t *p1, cairo_point_t *p2);
cairo_status_t (*add_spline) (void *closure, cairo_point_t *a, cairo_point_t *b, cairo_point_t *c, cairo_point_t *d);
cairo_status_t (*done_sub_path) (void *closure, cairo_sub_path_done_t done);
cairo_status_t (*done_path) (void *closure);
} cairo_path_callbacks_t;
#define CAIRO_PATH_BUF_SZ 64
@ -112,7 +146,7 @@ typedef struct cairo_path_op_buf {
typedef struct cairo_path_arg_buf {
int num_pts;
XPointFixed pt[CAIRO_PATH_BUF_SZ];
cairo_point_t pt[CAIRO_PATH_BUF_SZ];
struct cairo_path_arg_buf *next, *prev;
} cairo_path_arg_buf_t;
@ -126,10 +160,10 @@ typedef struct cairo_path {
} cairo_path_t;
typedef struct cairo_edge {
XLineFixed edge;
Bool clockWise;
cairo_line_t edge;
int clockWise;
XFixed current_x;
cairo_fixed_16_16_t current_x;
} cairo_edge_t;
typedef struct cairo_polygon {
@ -137,29 +171,23 @@ typedef struct cairo_polygon {
int edges_size;
cairo_edge_t *edges;
XPointFixed first_pt;
cairo_point_t first_pt;
int first_pt_defined;
XPointFixed last_pt;
cairo_point_t last_pt;
int last_pt_defined;
int closed;
} cairo_polygon_t;
typedef struct cairo_slope_fixed
{
XFixed dx;
XFixed dy;
} cairo_slope_fixed_t;
typedef struct cairo_spline {
XPointFixed a, b, c, d;
cairo_point_t a, b, c, d;
cairo_slope_fixed_t initial_slope;
cairo_slope_fixed_t final_slope;
cairo_slope_t initial_slope;
cairo_slope_t final_slope;
int num_pts;
int pts_size;
XPointFixed *pts;
cairo_point_t *pts;
} cairo_spline_t;
/* XXX: This can go away once incremental spline tessellation is working */
@ -169,11 +197,10 @@ typedef enum cairo_pen_stroke_direction {
} cairo_pen_stroke_direction_t;
typedef struct _cairo_pen_vertex {
XPointFixed pt;
cairo_point_t pt;
double theta;
cairo_slope_fixed_t slope_ccw;
cairo_slope_fixed_t slope_cw;
cairo_slope_t slope_ccw;
cairo_slope_t slope_cw;
} cairo_pen_vertex_t;
typedef struct cairo_pen {
@ -184,24 +211,51 @@ typedef struct cairo_pen {
cairo_pen_vertex_t *vertex;
} cairo_pen_t;
typedef enum cairo_surface_type {
CAIRO_SURFACE_TYPE_DRAWABLE,
CAIRO_SURFACE_TYPE_ICIMAGE
} cairo_surface_type_t;
struct cairo_surface {
Display *dpy;
char *image_data;
XcSurface *xc_surface;
double ppm;
unsigned int ref_count;
cairo_surface_type_t type;
XTransform xtransform;
/* For TYPE_DRAWABLE */
Display *dpy;
GC gc;
Drawable drawable;
Visual *visual;
int render_major;
int render_minor;
Picture picture;
/* For TYPE_ICIMAGE */
IcImage *icimage;
};
/* XXX: Right now, the cairo_color structure puts unpremultiplied
color in the doubles and premultiplied color in the shorts. Yes,
this is crazy insane, (but at least we don't export this
madness). I'm still working on a cleaner API, but in the meantime,
at least this does prevent precision loss in color when changing
alpha. */
typedef struct cairo_color {
double red;
double green;
double blue;
double alpha;
XcColor xc_color;
unsigned short red_short;
unsigned short green_short;
unsigned short blue_short;
unsigned short alpha_short;
} cairo_color_t;
struct cairo_matrix {
@ -209,9 +263,9 @@ struct cairo_matrix {
};
typedef struct cairo_traps {
int num_xtraps;
int xtraps_size;
XTrapezoid *xtraps;
cairo_trapezoid_t *traps;
int num_traps;
int traps_size;
} cairo_traps_t;
#define CAIRO_FONT_KEY_DEFAULT "serif"
@ -265,7 +319,7 @@ typedef struct cairo_gstate {
cairo_surface_t *surface;
cairo_surface_t *solid;
cairo_surface_t *pattern;
XPointDouble pattern_offset;
cairo_point_double_t pattern_offset;
cairo_clip_rec_t clip;
@ -278,8 +332,8 @@ typedef struct cairo_gstate {
cairo_path_t path;
XPointDouble last_move_pt;
XPointDouble current_pt;
cairo_point_double_t last_move_pt;
cairo_point_double_t current_pt;
int has_current_pt;
cairo_pen_t pen_regular;
@ -293,11 +347,11 @@ struct cairo {
};
typedef struct cairo_stroke_face {
XPointFixed ccw;
XPointFixed pt;
XPointFixed cw;
cairo_slope_fixed_t dev_vector;
XPointDouble usr_vector;
cairo_point_t ccw;
cairo_point_t pt;
cairo_point_t cw;
cairo_slope_t dev_vector;
cairo_point_double_t usr_vector;
} cairo_stroke_face_t;
/* cairo_gstate_t.c */
@ -370,6 +424,9 @@ _cairo_gstate_get_alpha (cairo_gstate_t *gstate);
cairo_status_t
_cairo_gstate_set_fill_rule (cairo_gstate_t *gstate, cairo_fill_rule_t fill_rule);
cairo_fill_rule_t
_cairo_gstate_get_fill_rule (cairo_gstate_t *gstate);
cairo_status_t
_cairo_gstate_set_line_width (cairo_gstate_t *gstate, double width);
@ -421,10 +478,10 @@ cairo_status_t
_cairo_gstate_identity_matrix (cairo_gstate_t *gstate);
cairo_status_t
cairo_gstateransform_point (cairo_gstate_t *gstate, double *x, double *y);
cairo_gstate_transform_point (cairo_gstate_t *gstate, double *x, double *y);
cairo_status_t
cairo_gstateransform_distance (cairo_gstate_t *gstate, double *dx, double *dy);
cairo_gstate_transform_distance (cairo_gstate_t *gstate, double *dx, double *dy);
cairo_status_t
_cairo_gstate_inverse_transform_point (cairo_gstate_t *gstate, double *x, double *y);
@ -459,6 +516,11 @@ _cairo_gstate_rel_curve_to (cairo_gstate_t *gstate,
double dx2, double dy2,
double dx3, double dy3);
/* XXX: NYI
cairo_status_t
_cairo_gstate_stroke_path (cairo_gstate_t *gstate);
*/
cairo_status_t
_cairo_gstate_close_path (cairo_gstate_t *gstate);
@ -481,16 +543,16 @@ cairo_status_t
_cairo_gstate_scale_font (cairo_gstate_t *gstate, double scale);
cairo_status_t
cairo_gstateransform_font (cairo_gstate_t *gstate,
double a, double b,
double c, double d);
cairo_gstate_transform_font (cairo_gstate_t *gstate,
double a, double b,
double c, double d);
cairo_status_t
cairo_gstateext_extents (cairo_gstate_t *gstate,
const unsigned char *utf8,
double *x, double *y,
double *width, double *height,
double *dx, double *dy);
cairo_gstate_text_extents (cairo_gstate_t *gstate,
const unsigned char *utf8,
double *x, double *y,
double *width, double *height,
double *dx, double *dy);
cairo_status_t
_cairo_gstate_show_text (cairo_gstate_t *gstate, const unsigned char *utf8);
@ -591,13 +653,6 @@ _cairo_path_stroke_to_traps (cairo_path_t *path, cairo_gstate_t *gstate, cairo_t
void
_cairo_surface_reference (cairo_surface_t *surface);
XcSurface *
_cairo_surface_get_xc_surface (cairo_surface_t *surface);
/* XXX: This function is going away, right? */
Picture
_cairo_surface_get_picture (cairo_surface_t *surface);
void
_cairo_surface_fill_rectangle (cairo_surface_t *surface,
cairo_operator_t operator,
@ -607,6 +662,42 @@ _cairo_surface_fill_rectangle (cairo_surface_t *surface,
int width,
int height);
void
_cairo_surface_composite (cairo_operator_t operator,
cairo_surface_t *src,
cairo_surface_t *mask,
cairo_surface_t *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);
void
_cairo_surface_fill_rectangles (cairo_surface_t *surface,
cairo_operator_t operator,
const cairo_color_t *color,
cairo_rectangle_t *rects,
int num_rects);
void
_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);
void
_cairo_surface_pull_image (cairo_surface_t *surface);
void
_cairo_surface_push_image (cairo_surface_t *surface);
/* cairo_pen_t.c */
cairo_status_t
_cairo_pen_init (cairo_pen_t *pen, double radius, cairo_gstate_t *gstate);
@ -621,23 +712,23 @@ void
_cairo_pen_fini (cairo_pen_t *pen);
cairo_status_t
_cairo_pen_add_points (cairo_pen_t *pen, XPointFixed *pt, int num_pts);
_cairo_pen_add_points (cairo_pen_t *pen, cairo_point_t *pt, int num_pts);
cairo_status_t
_cairo_pen_add_points_for_slopes (cairo_pen_t *pen,
XPointFixed *a,
XPointFixed *b,
XPointFixed *c,
XPointFixed *d);
cairo_point_t *a,
cairo_point_t *b,
cairo_point_t *c,
cairo_point_t *d);
cairo_status_t
_cairo_pen_find_active_cw_vertex_index (cairo_pen_t *pen,
cairo_slope_fixed_t *slope,
cairo_slope_t *slope,
int *active);
cairo_status_t
_cairo_pen_find_active_ccw_vertex_index (cairo_pen_t *pen,
cairo_slope_fixed_t *slope,
cairo_slope_t *slope,
int *active);
cairo_status_t
@ -654,10 +745,10 @@ void
_cairo_polygon_fini (cairo_polygon_t *polygon);
cairo_status_t
_cairo_polygon_add_edge (cairo_polygon_t *polygon, XPointFixed *p1, XPointFixed *p2);
_cairo_polygon_add_edge (cairo_polygon_t *polygon, cairo_point_t *p1, cairo_point_t *p2);
cairo_status_t
_cairo_polygon_add_point (cairo_polygon_t *polygon, XPointFixed *pt);
_cairo_polygon_add_point (cairo_polygon_t *polygon, cairo_point_t *pt);
cairo_status_t
_cairo_polygon_close (cairo_polygon_t *polygon);
@ -665,10 +756,10 @@ _cairo_polygon_close (cairo_polygon_t *polygon);
/* cairo_spline_t.c */
cairo_int_status_t
_cairo_spline_init (cairo_spline_t *spline,
XPointFixed *a,
XPointFixed *b,
XPointFixed *c,
XPointFixed *d);
cairo_point_t *a,
cairo_point_t *b,
cairo_point_t *c,
cairo_point_t *d);
cairo_status_t
_cairo_spline_decompose (cairo_spline_t *spline, double tolerance);
@ -714,19 +805,25 @@ void
cairo_traps_fini (cairo_traps_t *traps);
cairo_status_t
cairo_traps_tessellate_triangle (cairo_traps_t *traps, XPointFixed t[3]);
cairo_traps_tessellate_triangle (cairo_traps_t *traps, cairo_point_t t[3]);
cairo_status_t
cairo_traps_tessellate_rectangle (cairo_traps_t *traps, XPointFixed q[4]);
cairo_traps_tessellate_rectangle (cairo_traps_t *traps, cairo_point_t q[4]);
cairo_status_t
cairo_traps_tessellate_polygon (cairo_traps_t *traps,
cairo_polygon_t *poly,
cairo_fill_rule_t fill_rule);
/* cairo_misc.c */
/* cairo_slope.c */
void
_compute_slope (XPointFixed *a, XPointFixed *b, cairo_slope_fixed_t *slope);
_cairo_slope_init (cairo_slope_t *slope, cairo_point_t *a, cairo_point_t *b);
int
_cairo_slope_clockwise (cairo_slope_t *a, cairo_slope_t *b);
int
_cairo_slope_counter_clockwise (cairo_slope_t *a, cairo_slope_t *b);
#endif