diff --git a/ChangeLog b/ChangeLog index 73ac29c36..46764da25 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,74 @@ +2003-07-30 Carl Worth + + * 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 , added + , , and + + * 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 * src/cairo_traps.c (_line_segs_intersect_ceil): We don't need a diff --git a/cairo.pc.in b/cairo.pc.in index 8f45191a7..ab7548be8 100644 --- a/cairo.pc.in +++ b/cairo.pc.in @@ -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} diff --git a/configure.in b/configure.in index 07e02e4ac..e6acbfd00 100644 --- a/configure.in +++ b/configure.in @@ -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) diff --git a/src/Makefile.am b/src/Makefile.am index b63772e52..f12021cc7 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -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@ diff --git a/src/cairo-color.c b/src/cairo-color.c index dab09ad27..9ba5846dc 100644 --- a/src/cairo-color.c +++ b/src/cairo-color.c @@ -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; +} + diff --git a/src/cairo-font.c b/src/cairo-font.c index 001ea0aca..1852b877a 100644 --- a/src/cairo-font.c +++ b/src/cairo-font.c @@ -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); diff --git a/src/cairo-gstate.c b/src/cairo-gstate.c index 043569365..5fc97243b 100644 --- a/src/cairo-gstate.c +++ b/src/cairo-gstate.c @@ -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); diff --git a/src/cairo-path-bounds.c b/src/cairo-path-bounds.c index 6ee193a1e..2335b1d90 100644 --- a/src/cairo-path-bounds.c +++ b/src/cairo-path-bounds.c @@ -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; diff --git a/src/cairo-path-fill.c b/src/cairo-path-fill.c index 47ef95499..80715d71e 100644 --- a/src/cairo-path-fill.c +++ b/src/cairo-path-fill.c @@ -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; diff --git a/src/cairo-path-stroke.c b/src/cairo-path-stroke.c index 059605c29..a68dd6990 100644 --- a/src/cairo-path-stroke.c +++ b/src/cairo-path-stroke.c @@ -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; diff --git a/src/cairo-path.c b/src/cairo-path.c index b2ec57560..6421429c5 100644 --- a/src/cairo-path.c +++ b/src/cairo-path.c @@ -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, ¤t, &pt[0]); + status = (*cb->add_edge) (closure, ¤t, &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, ¤t, &pt[0], &pt[1], &pt[2]); + status = (*cb->add_spline) (closure, ¤t, &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, ¤t, &first); - (*cb->DoneSubPath) (closure, cairo_sub_path_done_join); + (*cb->add_edge) (closure, ¤t, &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); } diff --git a/src/cairo-pen.c b/src/cairo-pen.c index b0ffde964..c7b55913e 100644 --- a/src/cairo-pen.c +++ b/src/cairo-pen.c @@ -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 { diff --git a/src/cairo-polygon.c b/src/cairo-polygon.c index 70817bd93..ba05b70c6 100644 --- a/src/cairo-polygon.c +++ b/src/cairo-polygon.c @@ -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; diff --git a/src/cairo_misc.c b/src/cairo-slope.c similarity index 69% rename from src/cairo_misc.c rename to src/cairo-slope.c index b3f91db59..619ced1db 100644 --- a/src/cairo_misc.c +++ b/src/cairo-slope.c @@ -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); +} + + + + diff --git a/src/cairo-spline.c b/src/cairo-spline.c index 565bf3b73..077f1dbe8 100644 --- a/src/cairo-spline.c +++ b/src/cairo-spline.c @@ -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): diff --git a/src/cairo-surface.c b/src/cairo-surface.c index 1bea568bc..0c662ab0e 100644 --- a/src/cairo-surface.c +++ b/src/cairo-surface.c @@ -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); + } } diff --git a/src/cairo-traps.c b/src/cairo-traps.c index 4434c45d2..b7aa0d6b7 100644 --- a/src/cairo-traps.c +++ b/src/cairo-traps.c @@ -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; diff --git a/src/cairo.c b/src/cairo.c index b6080f00f..d22fd337b 100644 --- a/src/cairo.c +++ b/src/cairo.c @@ -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) { diff --git a/src/cairo.h b/src/cairo.h index 88880c3e0..9dc89ec64 100644 --- a/src/cairo.h +++ b/src/cairo.h @@ -28,7 +28,9 @@ #ifndef _CAIRO_H_ #define _CAIRO_H_ -#include +#include +#include +#include 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 diff --git a/src/cairo_color.c b/src/cairo_color.c index dab09ad27..9ba5846dc 100644 --- a/src/cairo_color.c +++ b/src/cairo_color.c @@ -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; +} + diff --git a/src/cairo_font.c b/src/cairo_font.c index 001ea0aca..1852b877a 100644 --- a/src/cairo_font.c +++ b/src/cairo_font.c @@ -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); diff --git a/src/cairo_gstate.c b/src/cairo_gstate.c index 043569365..5fc97243b 100644 --- a/src/cairo_gstate.c +++ b/src/cairo_gstate.c @@ -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); diff --git a/src/cairo_path.c b/src/cairo_path.c index b2ec57560..6421429c5 100644 --- a/src/cairo_path.c +++ b/src/cairo_path.c @@ -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, ¤t, &pt[0]); + status = (*cb->add_edge) (closure, ¤t, &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, ¤t, &pt[0], &pt[1], &pt[2]); + status = (*cb->add_spline) (closure, ¤t, &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, ¤t, &first); - (*cb->DoneSubPath) (closure, cairo_sub_path_done_join); + (*cb->add_edge) (closure, ¤t, &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); } diff --git a/src/cairo_path_bounds.c b/src/cairo_path_bounds.c index 6ee193a1e..2335b1d90 100644 --- a/src/cairo_path_bounds.c +++ b/src/cairo_path_bounds.c @@ -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; diff --git a/src/cairo_path_fill.c b/src/cairo_path_fill.c index 47ef95499..80715d71e 100644 --- a/src/cairo_path_fill.c +++ b/src/cairo_path_fill.c @@ -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; diff --git a/src/cairo_path_stroke.c b/src/cairo_path_stroke.c index 059605c29..a68dd6990 100644 --- a/src/cairo_path_stroke.c +++ b/src/cairo_path_stroke.c @@ -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; diff --git a/src/cairo_pen.c b/src/cairo_pen.c index b0ffde964..c7b55913e 100644 --- a/src/cairo_pen.c +++ b/src/cairo_pen.c @@ -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 { diff --git a/src/cairo_polygon.c b/src/cairo_polygon.c index 70817bd93..ba05b70c6 100644 --- a/src/cairo_polygon.c +++ b/src/cairo_polygon.c @@ -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; diff --git a/src/cairo_slope.c b/src/cairo_slope.c new file mode 100644 index 000000000..619ced1db --- /dev/null +++ b/src/cairo_slope.c @@ -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 + */ + +#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); +} + + + + diff --git a/src/cairo_spline.c b/src/cairo_spline.c index 565bf3b73..077f1dbe8 100644 --- a/src/cairo_spline.c +++ b/src/cairo_spline.c @@ -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): diff --git a/src/cairo_surface.c b/src/cairo_surface.c index 1bea568bc..0c662ab0e 100644 --- a/src/cairo_surface.c +++ b/src/cairo_surface.c @@ -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); + } } diff --git a/src/cairo_traps.c b/src/cairo_traps.c index 4434c45d2..b7aa0d6b7 100644 --- a/src/cairo_traps.c +++ b/src/cairo_traps.c @@ -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; diff --git a/src/cairoint.h b/src/cairoint.h index 9ca2dbf66..6db2b4a31 100644 --- a/src/cairoint.h +++ b/src/cairoint.h @@ -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