From aa06e7a53fcf37b703188260ee5644a2a22a5e01 Mon Sep 17 00:00:00 2001 From: "vladimir%pobox.com" Date: Tue, 26 Sep 2006 22:21:56 +0000 Subject: [PATCH] b=354388, Update cairo to cairo 2006-09-26 trunk, r=me --- gfx/cairo/cairo-clip-extract-rectangles.patch | 312 ---- gfx/cairo/cairo-debug-helpers.patch | 245 --- gfx/cairo/cairo/src/Makefile.in | 15 +- gfx/cairo/cairo/src/cairo-arc.c | 4 +- gfx/cairo/cairo/src/cairo-array.c | 20 +- gfx/cairo/cairo/src/cairo-atsui-font.c | 56 +- gfx/cairo/cairo/src/cairo-clip-private.h | 12 +- gfx/cairo/cairo/src/cairo-clip.c | 151 +- gfx/cairo/cairo/src/cairo-deprecated.h | 139 ++ gfx/cairo/cairo/src/cairo-directfb-surface.c | 403 ++--- gfx/cairo/cairo/src/cairo-directfb.h | 3 +- gfx/cairo/cairo/src/cairo-font-options.c | 9 + gfx/cairo/cairo/src/cairo-font-subset.c | 812 --------- gfx/cairo/cairo/src/cairo-font.c | 15 +- gfx/cairo/cairo/src/cairo-ft-font.c | 102 +- gfx/cairo/cairo/src/cairo-ft-private.h | 7 +- gfx/cairo/cairo/src/cairo-gstate.c | 147 +- gfx/cairo/cairo/src/cairo-hash.c | 2 +- gfx/cairo/cairo/src/cairo-image-surface.c | 98 +- gfx/cairo/cairo/src/cairo-lzw.c | 11 +- gfx/cairo/cairo/src/cairo-matrix.c | 19 +- .../cairo/src/cairo-meta-surface-private.h | 2 +- gfx/cairo/cairo/src/cairo-meta-surface.c | 114 +- gfx/cairo/cairo/src/cairo-nquartz-surface.c | 98 +- gfx/cairo/cairo/src/cairo-nquartz.h | 10 +- ...t-subset-private.h => cairo-os2-private.h} | 66 +- gfx/cairo/cairo/src/cairo-os2-surface.c | 1135 +++++++++++++ gfx/cairo/cairo/src/cairo-os2.h | 201 +++ .../cairo/src/cairo-output-stream-private.h | 12 +- gfx/cairo/cairo/src/cairo-output-stream.c | 34 +- gfx/cairo/cairo/src/cairo-paginated-surface.c | 37 +- gfx/cairo/cairo/src/cairo-path-data.c | 6 - gfx/cairo/cairo/src/cairo-path-stroke.c | 7 +- gfx/cairo/cairo/src/cairo-path.c | 15 +- gfx/cairo/cairo/src/cairo-pattern.c | 289 +++- gfx/cairo/cairo/src/cairo-pdf-surface.c | 151 +- gfx/cairo/cairo/src/cairo-pdf.h | 2 +- gfx/cairo/cairo/src/cairo-platform.h | 2 +- gfx/cairo/cairo/src/cairo-png.c | 13 +- gfx/cairo/cairo/src/cairo-ps-surface.c | 113 +- gfx/cairo/cairo/src/cairo-quartz-private.h | 10 +- gfx/cairo/cairo/src/cairo-quartz-surface.c | 263 ++- gfx/cairo/cairo/src/cairo-rename.h | 33 +- .../src/cairo-scaled-font-subsets-private.h | 39 +- .../cairo/src/cairo-scaled-font-subsets.c | 6 +- gfx/cairo/cairo/src/cairo-scaled-font.c | 141 +- gfx/cairo/cairo/src/cairo-surface.c | 184 +- gfx/cairo/cairo/src/cairo-svg-surface.c | 33 +- .../cairo/src/cairo-truetype-subset-private.h | 170 ++ gfx/cairo/cairo/src/cairo-truetype-subset.c | 883 ++++++++++ gfx/cairo/cairo/src/cairo-type1-fallback.c | 746 ++++++++ gfx/cairo/cairo/src/cairo-type1-subset.c | 144 +- gfx/cairo/cairo/src/cairo-win32-font.c | 179 +- gfx/cairo/cairo/src/cairo-win32-private.h | 3 + gfx/cairo/cairo/src/cairo-win32-surface.c | 319 ++-- gfx/cairo/cairo/src/cairo-xcb-surface.c | 295 ++-- gfx/cairo/cairo/src/cairo-xlib-private.h | 6 + gfx/cairo/cairo/src/cairo-xlib-surface.c | 57 +- gfx/cairo/cairo/src/cairo.c | 274 ++- gfx/cairo/cairo/src/cairo.h | 236 ++- gfx/cairo/cairo/src/cairoint.h | 278 ++- gfx/cairo/cairo/src/test-fallback-surface.c | 3 + gfx/cairo/cairo/src/test-paginated-surface.c | 12 +- gfx/cairo/device-offset-scale.patch | 1496 ----------------- gfx/cairo/libpixman/src/fbcompose.c | 77 +- gfx/cairo/libpixman/src/fbmmx.c | 10 +- gfx/cairo/libpixman/src/fbmmx.h | 21 + gfx/cairo/libpixman/src/fbpict.c | 14 +- gfx/cairo/libpixman/src/iccolor.c | 1 - gfx/cairo/libpixman/src/icformat.c | 25 +- gfx/cairo/libpixman/src/icimage.c | 28 +- gfx/cairo/libpixman/src/icimage.h | 2 +- gfx/cairo/libpixman/src/icint.h | 15 +- gfx/cairo/libpixman/src/icrect.c | 1 - gfx/cairo/libpixman/src/ictri.c | 6 +- gfx/cairo/libpixman/src/icutil.c | 2 +- gfx/cairo/libpixman/src/pixman-remap.h | 154 +- gfx/cairo/libpixman/src/pixman.h | 122 +- gfx/cairo/libpixman/src/pixregion.c | 61 +- gfx/cairo/libpixman/src/renderedge.h | 10 +- gfx/cairo/libpixman/src/slim_internal.h | 5 +- gfx/cairo/push-pop-group.patch | 734 -------- gfx/thebes/public/gfxPattern.h | 10 +- gfx/thebes/src/cairo-xlib-utils.c | 47 +- gfx/thebes/src/gfxContext.cpp | 10 +- 85 files changed, 6594 insertions(+), 5460 deletions(-) delete mode 100644 gfx/cairo/cairo-clip-extract-rectangles.patch delete mode 100644 gfx/cairo/cairo-debug-helpers.patch create mode 100644 gfx/cairo/cairo/src/cairo-deprecated.h delete mode 100644 gfx/cairo/cairo/src/cairo-font-subset.c rename gfx/cairo/cairo/src/{cairo-font-subset-private.h => cairo-os2-private.h} (52%) create mode 100644 gfx/cairo/cairo/src/cairo-os2-surface.c create mode 100644 gfx/cairo/cairo/src/cairo-os2.h create mode 100644 gfx/cairo/cairo/src/cairo-truetype-subset-private.h create mode 100644 gfx/cairo/cairo/src/cairo-truetype-subset.c create mode 100644 gfx/cairo/cairo/src/cairo-type1-fallback.c delete mode 100644 gfx/cairo/device-offset-scale.patch delete mode 100644 gfx/cairo/push-pop-group.patch diff --git a/gfx/cairo/cairo-clip-extract-rectangles.patch b/gfx/cairo/cairo-clip-extract-rectangles.patch deleted file mode 100644 index 6da28ac09510..000000000000 --- a/gfx/cairo/cairo-clip-extract-rectangles.patch +++ /dev/null @@ -1,312 +0,0 @@ -Index: gfx/cairo/cairo/src/cairo.h -=================================================================== -RCS file: /home/rocallahan/mozilla-cvs-mirror/mozilla/gfx/cairo/cairo/src/cairo.h,v -retrieving revision 1.9 -diff -u -t -p -1 -2 -r1.9 cairo.h ---- gfx/cairo/cairo/src/cairo.h 10 Feb 2006 02:20:34 -0000 1.9 -+++ gfx/cairo/cairo/src/cairo.h 21 Feb 2006 23:17:08 -0000 -@@ -1129,24 +1129,42 @@ cairo_public cairo_path_t * - cairo_copy_path (cairo_t *cr); - - cairo_public cairo_path_t * - cairo_copy_path_flat (cairo_t *cr); - - cairo_public void - cairo_append_path (cairo_t *cr, - cairo_path_t *path); - - cairo_public void - cairo_path_destroy (cairo_path_t *path); - -+/** -+ * cairo_clip_rect_t: -+ * -+ * A data structure for holding clip rectangles. -+ */ -+typedef struct _cairo_clip_rect { -+ double x, y, width, height; -+} cairo_clip_rect_t; -+ -+cairo_public cairo_bool_t -+cairo_has_clip (cairo_t *cr); -+ -+cairo_public cairo_bool_t -+cairo_extract_clip_rectangles (cairo_t *cr, -+ int max_rectangles, -+ cairo_clip_rect_t *rectangles_out, -+ int *num_rectangles_out); -+ - /* Error status queries */ - - cairo_public cairo_status_t - cairo_status (cairo_t *cr); - - cairo_public const char * - cairo_status_to_string (cairo_status_t status); - - /* Surface manipulation */ - - cairo_public cairo_surface_t * - cairo_surface_create_similar (cairo_surface_t *other, -Index: gfx/cairo/cairo/src/cairoint.h -=================================================================== -RCS file: /home/rocallahan/mozilla-cvs-mirror/mozilla/gfx/cairo/cairo/src/cairoint.h,v -retrieving revision 1.19 -diff -u -t -p -1 -2 -r1.19 cairoint.h ---- gfx/cairo/cairo/src/cairoint.h 10 Feb 2006 02:51:12 -0000 1.19 -+++ gfx/cairo/cairo/src/cairoint.h 21 Feb 2006 23:18:00 -0000 -@@ -1229,24 +1229,33 @@ cairo_private cairo_status_t - _cairo_gstate_in_fill (cairo_gstate_t *gstate, - cairo_path_fixed_t *path, - double x, - double y, - cairo_bool_t *inside_ret); - - cairo_private cairo_status_t - _cairo_gstate_clip (cairo_gstate_t *gstate, cairo_path_fixed_t *path); - - cairo_private cairo_status_t - _cairo_gstate_reset_clip (cairo_gstate_t *gstate); - -+cairo_private cairo_bool_t -+_cairo_gstate_has_clip (cairo_gstate_t *gstate); -+ -+cairo_private cairo_bool_t -+_cairo_gstate_extract_clip_rectangles (cairo_gstate_t *gstate, -+ int max_rectangles, -+ cairo_clip_rect_t *rectangles_out, -+ int *num_rectangles_out); -+ - cairo_private cairo_status_t - _cairo_gstate_show_surface (cairo_gstate_t *gstate, - cairo_surface_t *surface, - double x, - double y, - double width, - double height); - - cairo_private cairo_status_t - _cairo_gstate_select_font_face (cairo_gstate_t *gstate, - const char *family, - cairo_font_slant_t slant, -Index: gfx/cairo/cairo/src/cairo-clip-private.h -=================================================================== -RCS file: /home/rocallahan/mozilla-cvs-mirror/mozilla/gfx/cairo/cairo/src/cairo-clip-private.h,v -retrieving revision 1.2 -diff -u -t -p -1 -2 -r1.2 cairo-clip-private.h ---- gfx/cairo/cairo/src/cairo-clip-private.h 10 Jan 2006 22:56:38 -0000 1.2 -+++ gfx/cairo/cairo/src/cairo-clip-private.h 7 Feb 2006 22:44:42 -0000 -@@ -105,13 +105,22 @@ _cairo_clip_intersect_to_rectangle (cair - cairo_private cairo_status_t - _cairo_clip_intersect_to_region (cairo_clip_t *clip, - pixman_region16_t *region); - - cairo_private cairo_status_t - _cairo_clip_combine_to_surface (cairo_clip_t *clip, - cairo_operator_t op, - cairo_surface_t *dst, - int dst_x, - int dst_y, - const cairo_rectangle_t *extents); - -+cairo_private cairo_bool_t -+_cairo_clip_has_clip (cairo_clip_t *clip); -+ -+cairo_private cairo_bool_t -+_cairo_clip_extract_rectangles (cairo_clip_t *clip, -+ int max_rectangles, -+ cairo_clip_rect_t *rectangles_out, -+ int *num_rectangles_out); -+ - #endif /* CAIRO_CLIP_PRIVATE_H */ -Index: gfx/cairo/cairo/src/cairo-clip.c -=================================================================== -RCS file: /home/rocallahan/mozilla-cvs-mirror/mozilla/gfx/cairo/cairo/src/cairo-clip.c,v -retrieving revision 1.3 -diff -u -t -p -1 -2 -r1.3 cairo-clip.c ---- gfx/cairo/cairo/src/cairo-clip.c 10 Jan 2006 22:56:38 -0000 1.3 -+++ gfx/cairo/cairo/src/cairo-clip.c 21 Feb 2006 23:19:34 -0000 -@@ -450,12 +450,62 @@ _cairo_clip_clip (cairo_clip_t *cl - - status = _cairo_clip_intersect_region (clip, &traps, target); - if (status != CAIRO_INT_STATUS_UNSUPPORTED) - goto bail; - - status = _cairo_clip_intersect_mask (clip, &traps, antialias, target); - - bail: - _cairo_traps_fini (&traps); - - return status; - } -+ -+cairo_bool_t -+_cairo_clip_has_clip (cairo_clip_t *clip) -+{ -+ return clip->region != NULL || clip->surface != NULL || clip->path != NULL; -+} -+ -+static cairo_bool_t -+_cairo_region_to_clip_rectangles (pixman_region16_t *region, -+ int max_rectangles, -+ cairo_clip_rect_t *rectangles_out, -+ int *num_rectangles_out) -+{ -+ int n_boxes, i; -+ pixman_box16_t *boxes; -+ -+ /* no region -> we can't represent it as rectangles */ -+ if (region == NULL) -+ return FALSE; -+ -+ n_boxes = pixman_region_num_rects (region); -+ *num_rectangles_out = n_boxes; -+ if (n_boxes > max_rectangles) -+ return FALSE; -+ -+ boxes = pixman_region_rects (region); -+ -+ for (i = 0; i < n_boxes; i++) { -+ rectangles_out[i].x = boxes[i].x1; -+ rectangles_out[i].y = boxes[i].y1; -+ rectangles_out[i].width = boxes[i].x2 - boxes[i].x1; -+ rectangles_out[i].height = boxes[i].y2 - boxes[i].y1; -+ } -+ -+ return TRUE; -+} -+ -+cairo_bool_t -+_cairo_clip_extract_rectangles (cairo_clip_t *clip, -+ int max_rectangles, -+ cairo_clip_rect_t *rectangles_out, -+ int *num_rectangles_out) -+{ -+ /* can't handle paths or surfaces for now */ -+ if (clip->path != NULL || clip->surface != NULL) -+ return FALSE; -+ -+ return _cairo_region_to_clip_rectangles (clip->region, -+ max_rectangles, rectangles_out, num_rectangles_out); -+} -Index: gfx/cairo/cairo/src/cairo-gstate.c -=================================================================== -RCS file: /home/rocallahan/mozilla-cvs-mirror/mozilla/gfx/cairo/cairo/src/cairo-gstate.c,v -retrieving revision 1.4 -diff -u -t -p -1 -2 -r1.4 cairo-gstate.c ---- gfx/cairo/cairo/src/cairo-gstate.c 10 Jan 2006 22:56:38 -0000 1.4 -+++ gfx/cairo/cairo/src/cairo-gstate.c 21 Feb 2006 23:18:13 -0000 -@@ -1174,24 +1174,42 @@ _cairo_gstate_reset_clip (cairo_gstate_t - { - return _cairo_clip_reset (&gstate->clip); - } - - cairo_status_t - _cairo_gstate_clip (cairo_gstate_t *gstate, cairo_path_fixed_t *path) - { - return _cairo_clip_clip (&gstate->clip, - path, gstate->fill_rule, gstate->tolerance, - gstate->antialias, gstate->target); - } - -+cairo_bool_t -+_cairo_gstate_has_clip (cairo_gstate_t *gstate) -+{ -+ return _cairo_clip_has_clip (&gstate->clip); -+} -+ -+cairo_bool_t -+_cairo_gstate_extract_clip_rectangles (cairo_gstate_t *gstate, -+ int max_rectangles, -+ cairo_clip_rect_t *rectangles_out, -+ int *num_rectangles_out) -+{ -+ return _cairo_clip_extract_rectangles (&gstate->clip, -+ max_rectangles, -+ rectangles_out, -+ num_rectangles_out); -+} -+ - static void - _cairo_gstate_unset_scaled_font (cairo_gstate_t *gstate) - { - if (gstate->scaled_font) { - cairo_scaled_font_destroy (gstate->scaled_font); - gstate->scaled_font = NULL; - } - } - - cairo_status_t - _cairo_gstate_select_font_face (cairo_gstate_t *gstate, - const char *family, -Index: gfx/cairo/cairo/src/cairo.c -=================================================================== -RCS file: /home/rocallahan/mozilla-cvs-mirror/mozilla/gfx/cairo/cairo/src/cairo.c,v -retrieving revision 1.11 -diff -u -t -p -1 -2 -r1.11 cairo.c ---- gfx/cairo/cairo/src/cairo.c 10 Feb 2006 02:56:14 -0000 1.11 -+++ gfx/cairo/cairo/src/cairo.c 21 Feb 2006 23:17:34 -0000 -@@ -2575,24 +2575,63 @@ cairo_get_group_target (cairo_t *cr) - * with it. - **/ - cairo_path_t * - cairo_copy_path (cairo_t *cr) - { - if (cr->status) - return (cairo_path_t*) &_cairo_path_nil; - - return _cairo_path_data_create (&cr->path, cr->gstate); - } - - /** -+ * cairo_has_clip -+ * @cr: a cairo context -+ * -+ * Returns TRUE if the cairo context has any clipping active, otherwise -+ * FALSE. -+ */ -+cairo_bool_t -+cairo_has_clip (cairo_t *cr) -+{ -+ if (cr->status) -+ return FALSE; -+ return _cairo_gstate_has_clip (cr->gstate); -+} -+ -+/** -+ * cairo_extract_clip_rectangles -+ * @cr: a cairo context -+ * @max_rectangles: the maximum number of rectangles to be returned -+ * @rectangles_out: the output buffer for the rectangles -+ * @num_rectangles_out: the number of rectangles returned -+ * -+ * If the current clip can be expressed as the union of at most -+ * 'max_rectangles' device-coordinate rectangles, then we fill in the array -+ * with the rectangles, and return True. Otherwise we return False. When there -+ * is no clipping active, we return False. -+ */ -+cairo_bool_t -+cairo_extract_clip_rectangles (cairo_t *cr, -+ int max_rectangles, -+ cairo_clip_rect_t *rectangles_out, -+ int *num_rectangles_out) -+{ -+ if (cr->status) -+ return FALSE; -+ return _cairo_gstate_extract_clip_rectangles (cr->gstate, max_rectangles, -+ rectangles_out, num_rectangles_out); -+} -+ -+/** - * cairo_copy_path_flat: - * @cr: a cairo context - * - * Gets a flattened copy of the current path and returns it to the - * user as a #cairo_path_t. See #cairo_path_data_t for hints on - * how to iterate over the returned data structure. - * - * This function is like cairo_copy_path() except that any curves - * in the path will be approximated with piecewise-linear - * approximations, (accurate to within the current tolerance - * value). That is, the result is guaranteed to not have any elements - * of type %CAIRO_PATH_CURVE_TO which will instead be replaced by a diff --git a/gfx/cairo/cairo-debug-helpers.patch b/gfx/cairo/cairo-debug-helpers.patch deleted file mode 100644 index 6812071584b2..000000000000 --- a/gfx/cairo/cairo-debug-helpers.patch +++ /dev/null @@ -1,245 +0,0 @@ -Index: src/cairo-debug.c -=================================================================== ---- src/cairo-debug.c.orig -+++ src/cairo-debug.c -@@ -35,6 +35,8 @@ - - #include "cairoint.h" - -+#include "cairo-clip-private.h" -+ - /** - * cairo_debug_reset_static_data: - * -@@ -70,3 +72,192 @@ cairo_debug_reset_static_data (void) - #endif - } - -+/* -+ * clip dumper -+ */ -+void -+cairo_debug_dump_clip (struct _cairo_clip *clip, -+ FILE *fp) -+{ -+ fprintf (fp, "clip %p: %s ", (clip->mode == CAIRO_CLIP_MODE_PATH ? "PATH" : -+ clip->mode == CAIRO_CLIP_MODE_REGION ? "REGION" : -+ clip->mode == CAIRO_CLIP_MODE_MASK ? "MASK" : -+ "INVALID?!")); -+ if (clip->mode == CAIRO_CLIP_MODE_PATH) { -+ fprintf (fp, "\n=== clip path ===\n"); -+ } else if (clip->mode == CAIRO_CLIP_MODE_REGION) { -+ if (!clip->region) { -+ fprintf (fp, "region = NULL"); -+ } else if (pixman_region_num_rects (clip->region) == 1) { -+ pixman_box16_t *rects = pixman_region_rects (clip->region); -+ fprintf (fp, "region [%d %d %d %d]", -+ rects[0].x1, rects[0].y1, -+ rects[0].x2, rects[0].y2); -+ } else { -+ pixman_box16_t *rects = pixman_region_rects (clip->region); -+ int i, nr = pixman_region_num_rects(clip->region); -+ fprintf (fp, "region (%d rects)\n", nr); -+ for (i = 0; i < nr; i++) { -+ fprintf (fp, "rect %d: [%d %d %d %d]", i, -+ rects[nr].x1, rects[nr].y1, -+ rects[nr].x2, rects[nr].y2); -+ } -+ } -+ } else if (clip->mode == CAIRO_CLIP_MODE_MASK) { -+ fprintf (fp, "mask, surface: %p rect: [%d %d %d %d]", clip->surface, -+ clip->surface_rect.x, clip->surface_rect.y, clip->surface_rect.width, clip->surface_rect.height); -+ } -+ -+ fprintf (fp, "\n"); -+} -+ -+/* -+ * path dumper -+ */ -+ -+typedef struct _cairo_debug_path_dump_closure { -+ unsigned int op_count; -+ FILE *fp; -+} cairo_debug_path_dump_closure_t; -+ -+static cairo_status_t -+_cairo_debug_path_move_to (void *closure, -+ cairo_point_t *point) -+{ -+ cairo_debug_path_dump_closure_t *fdc = -+ (cairo_debug_path_dump_closure_t*) closure; -+ fprintf (fdc->fp, "%d: moveto (%f, %f)\n", -+ fdc->op_count++, -+ _cairo_fixed_to_double(point->x), -+ _cairo_fixed_to_double(point->y)); -+ return CAIRO_STATUS_SUCCESS; -+} -+ -+static cairo_status_t -+_cairo_debug_path_line_to (void *closure, -+ cairo_point_t *point) -+{ -+ cairo_debug_path_dump_closure_t *fdc = -+ (cairo_debug_path_dump_closure_t*) closure; -+ fprintf (fdc->fp, "%d: lineto (%f, %f)\n", -+ fdc->op_count++, -+ _cairo_fixed_to_double(point->x), -+ _cairo_fixed_to_double(point->y)); -+ return CAIRO_STATUS_SUCCESS; -+} -+ -+static cairo_status_t -+_cairo_debug_path_curve_to (void *closure, -+ cairo_point_t *p0, -+ cairo_point_t *p1, -+ cairo_point_t *p2) -+{ -+ cairo_debug_path_dump_closure_t *fdc = -+ (cairo_debug_path_dump_closure_t*) closure; -+ fprintf (fdc->fp, "%d: curveto (%f, %f) (%f, %f) (%f, %f)\n", -+ fdc->op_count++, -+ _cairo_fixed_to_double(p0->x), -+ _cairo_fixed_to_double(p0->y), -+ _cairo_fixed_to_double(p1->x), -+ _cairo_fixed_to_double(p1->y), -+ _cairo_fixed_to_double(p2->x), -+ _cairo_fixed_to_double(p2->y)); -+ return CAIRO_STATUS_SUCCESS; -+} -+ -+static cairo_status_t -+_cairo_debug_path_close_path (void *closure) -+{ -+ cairo_debug_path_dump_closure_t *fdc = -+ (cairo_debug_path_dump_closure_t*) closure; -+ fprintf (fdc->fp, "%d: close\n", -+ fdc->op_count++); -+ return CAIRO_STATUS_SUCCESS; -+} -+ -+/** -+ * cairo_debug_dump_path -+ * @path: a #cairo_path_fixed_t -+ * @fp: the file pointer where to dump the given path -+ * -+ * Dumps @path in human-readable form to @fp. -+ */ -+void -+cairo_debug_dump_path (cairo_path_fixed_t *path, -+ FILE *fp) -+{ -+ cairo_debug_path_dump_closure_t fdc; -+ fdc.fp = fp; -+ fdc.op_count = 0; -+ -+ fprintf (fp, "=== path %p ===\n", path); -+ _cairo_path_fixed_interpret (path, -+ CAIRO_DIRECTION_FORWARD, -+ _cairo_debug_path_move_to, -+ _cairo_debug_path_line_to, -+ _cairo_debug_path_curve_to, -+ _cairo_debug_path_close_path, -+ &fdc); -+ fprintf (fp, "======================\n"); -+} -+ -+/* -+ * traps dumping -+ */ -+ -+/** -+ * cairo_debug_dump_traps -+ * @traps: a #cairo_traps_t -+ * @fp: the file pointer where to dump the traps -+ * -+ * Dumps @traps in human-readable form to @fp. -+ */ -+void -+cairo_debug_dump_traps (cairo_traps_t *traps, -+ FILE *fp) -+{ -+ fprintf (fp, "=== traps %p ===\n", traps); -+ fprintf (fp, "extents: (%f, %f) (%f, %f)\n", -+ _cairo_fixed_to_double (traps->extents.p1.x), -+ _cairo_fixed_to_double (traps->extents.p1.y), -+ _cairo_fixed_to_double (traps->extents.p2.x), -+ _cairo_fixed_to_double (traps->extents.p2.y)); -+ -+ cairo_debug_dump_trapezoid_array (traps->traps, -+ traps->num_traps, -+ fp); -+ -+ fprintf (fp, "=======================\n"); -+} -+ -+/** -+ * cairo_debug_dump_trapezoid_array -+ * @traps: a #cairo_trapezoid_t pointer -+ * @num_traps: the number of trapezoids in @traps -+ * @fp: the file pointer where to dump the traps -+ * -+ * Dumps num_traps in the @traps array in human-readable form to @fp. -+ */ -+void -+cairo_debug_dump_trapezoid_array (cairo_trapezoid_t *traps, -+ int num_traps, -+ FILE *fp) -+{ -+ int i; -+ -+ for (i = 0; i < num_traps; i++) { -+ fprintf (fp, "% 3d: t: %f b: %f l: (%f,%f)->(%f,%f) r: (%f,%f)->(%f,%f)\n", -+ i, -+ _cairo_fixed_to_double (traps[i].top), -+ _cairo_fixed_to_double (traps[i].bottom), -+ _cairo_fixed_to_double (traps[i].left.p1.x), -+ _cairo_fixed_to_double (traps[i].left.p1.y), -+ _cairo_fixed_to_double (traps[i].left.p2.x), -+ _cairo_fixed_to_double (traps[i].left.p2.y), -+ _cairo_fixed_to_double (traps[i].right.p1.x), -+ _cairo_fixed_to_double (traps[i].right.p1.y), -+ _cairo_fixed_to_double (traps[i].right.p2.x), -+ _cairo_fixed_to_double (traps[i].right.p2.y)); -+ } -+} -+ -Index: src/cairo-debug.h -=================================================================== ---- src/cairo-debug.h.orig -+++ src/cairo-debug.h -@@ -37,12 +37,34 @@ - #define CAIRO_DEBUG_H - - #include -+#include - - CAIRO_BEGIN_DECLS - -+struct _cairo_path_fixed; -+struct _cairo_traps; -+struct _cairo_trapezoid; -+struct _cairo_clip; -+ - void - cairo_debug_reset_static_data (void); - -+void -+cairo_debug_dump_clip (struct _cairo_clip *clip, -+ FILE *fp); -+void -+cairo_debug_dump_path (struct _cairo_path_fixed *path, -+ FILE *fp); -+ -+void -+cairo_debug_dump_traps (struct _cairo_traps *traps, -+ FILE *fp); -+ -+void -+cairo_debug_dump_trapezoid_array (struct _cairo_trapezoid *traps, -+ int num_traps, -+ FILE *fp); -+ - CAIRO_END_DECLS - - #endif /* CAIRO_H */ diff --git a/gfx/cairo/cairo/src/Makefile.in b/gfx/cairo/cairo/src/Makefile.in index abfa310310af..01855ee752bb 100644 --- a/gfx/cairo/cairo/src/Makefile.in +++ b/gfx/cairo/cairo/src/Makefile.in @@ -102,7 +102,7 @@ CSRCS = \ cairo-wideint.c \ $(NULL) -EXPORTS = cairo.h cairo-features.h cairo-platform.h cairo-rename.h +EXPORTS = cairo.h cairo-features.h cairo-platform.h cairo-deprecated.h cairo-rename.h ifeq ($(MOZ_WIDGET_TOOLKIT),windows) @@ -132,11 +132,12 @@ EXPORTS += cairo-beos.h endif ifeq ($(MOZ_WIDGET_TOOLKIT),gtk2) -CSRCS += cairo-font-subset.c \ - cairo-base85-stream.c \ +CSRCS += cairo-base85-stream.c \ cairo-pdf-surface.c \ cairo-ps-surface.c \ - cairo-type1-subset.c + cairo-type1-subset.c \ + cairo-type1-fallback.c \ + cairo-truetype-subset.c EXPORTS += cairo-ps.h cairo-pdf.h endif @@ -172,3 +173,9 @@ FORCE_STATIC_LIB = 1 FORCE_USE_PIC = 1 include $(topsrcdir)/config/rules.mk + +DEFINES += -DPACKAGE_VERSION="\"moz\"" -DPACKAGE_BUGREPORT="\"http://bugzilla.mozilla.org/\"" + +ifeq ($(MOZ_WIDGET_TOOLKIT),windows) +DEFINES += -DCAIRO_WIN32_STATIC_BUILD +endif diff --git a/gfx/cairo/cairo/src/cairo-arc.c b/gfx/cairo/cairo/src/cairo-arc.c index fdef6a32570a..2bf6c89f0b12 100644 --- a/gfx/cairo/cairo/src/cairo-arc.c +++ b/gfx/cairo/cairo/src/cairo-arc.c @@ -231,7 +231,7 @@ _cairo_arc_in_direction (cairo_t *cr, } /** - * _cairo_arc_path_negative: + * _cairo_arc_path * @cr: a cairo context * @xc: X position of the center of the arc * @yc: Y position of the center of the arc @@ -266,7 +266,7 @@ _cairo_arc_path (cairo_t *cr, * @angle2: the end angle, in radians * @ctm: the current transformation matrix * @tolerance: the current tolerance value - * @path: the path onto which th earc will be appended + * @path: the path onto which the arc will be appended * * Compute a path for the given arc (defined in the negative * direction) and append it onto the current path within @cr. The arc diff --git a/gfx/cairo/cairo/src/cairo-array.c b/gfx/cairo/cairo/src/cairo-array.c index baf17659ac99..1d9354a89600 100644 --- a/gfx/cairo/cairo/src/cairo-array.c +++ b/gfx/cairo/cairo/src/cairo-array.c @@ -159,7 +159,7 @@ _cairo_array_grow_by (cairo_array_t *array, int additional) * beyond @num_elements are simply "forgotten". **/ void -_cairo_array_truncate (cairo_array_t *array, int num_elements) +_cairo_array_truncate (cairo_array_t *array, unsigned int num_elements) { assert (! array->is_snapshot); @@ -187,7 +187,7 @@ _cairo_array_truncate (cairo_array_t *array, int num_elements) * ... use values[i] here ... **/ void * -_cairo_array_index (cairo_array_t *array, int index) +_cairo_array_index (cairo_array_t *array, unsigned int index) { /* We allow an index of 0 for the no-elements case. * This makes for cleaner calling code which will often look like: @@ -203,7 +203,7 @@ _cairo_array_index (cairo_array_t *array, int index) if (index == 0 && array->num_elements == 0) return NULL; - assert (0 <= index && index < array->num_elements); + assert (index < array->num_elements); return (void *) &(*array->elements)[index * array->element_size]; } @@ -287,7 +287,7 @@ _cairo_array_append_multiple (cairo_array_t *array, **/ cairo_status_t _cairo_array_allocate (cairo_array_t *array, - int num_elements, + unsigned int num_elements, void **elements) { cairo_status_t status; @@ -318,6 +318,18 @@ _cairo_array_num_elements (cairo_array_t *array) return array->num_elements; } +/** + * _cairo_array_size: + * + * Return value: The number of elements for which there is currently + * space allocated in array. + **/ +int +_cairo_array_size (cairo_array_t *array) +{ + return array->size; +} + /* cairo_user_data_array_t */ typedef struct { diff --git a/gfx/cairo/cairo/src/cairo-atsui-font.c b/gfx/cairo/cairo/src/cairo-atsui-font.c index 832211e6e14a..973160daa9f8 100644 --- a/gfx/cairo/cairo/src/cairo-atsui-font.c +++ b/gfx/cairo/cairo/src/cairo-atsui-font.c @@ -227,22 +227,30 @@ _cairo_atsui_font_create_scaled (cairo_font_face_t *font_face, font->style = CreateSizedCopyOfStyle(style, &font->base.scale); - Fixed theSize = FloatToFixed(1.0); - const ATSUAttributeTag theFontStyleTags[] = { kATSUSizeTag }; - const ByteCount theFontStyleSizes[] = { sizeof(Fixed) }; - ATSUAttributeValuePtr theFontStyleValues[] = { &theSize }; - err = ATSUSetAttributes(style, - sizeof(theFontStyleTags) / - sizeof(ATSUAttributeTag), theFontStyleTags, - theFontStyleSizes, theFontStyleValues); + { + Fixed theSize = FloatToFixed(1.0); + const ATSUAttributeTag theFontStyleTags[] = { kATSUSizeTag }; + const ByteCount theFontStyleSizes[] = { sizeof(Fixed) }; + ATSUAttributeValuePtr theFontStyleValues[] = { &theSize }; + + err = ATSUSetAttributes(style, + sizeof(theFontStyleTags) / + sizeof(ATSUAttributeTag), theFontStyleTags, + theFontStyleSizes, theFontStyleValues); + if (err != noErr) { + status = CAIRO_STATUS_NO_MEMORY; + goto FAIL; + } + } font->unscaled_style = style; - font->fontID = font_id; *font_out = &font->base; status = _cairo_atsui_font_set_metrics (font); + + FAIL: if (status) { cairo_scaled_font_destroy (&font->base); return status; @@ -318,15 +326,17 @@ _cairo_atsui_font_create_toy(cairo_toy_font_face_t *toy_face, kFontNoLanguageCode, &fontID); } - ATSUAttributeTag styleTags[] = - { kATSUQDItalicTag, kATSUQDBoldfaceTag, kATSUFontTag }; - ATSUAttributeValuePtr styleValues[] = { &isItalic, &isBold, &fontID }; - ByteCount styleSizes[] = - { sizeof(Boolean), sizeof(Boolean), sizeof(ATSUFontID) }; + { + ATSUAttributeTag styleTags[] = + { kATSUQDItalicTag, kATSUQDBoldfaceTag, kATSUFontTag }; + ATSUAttributeValuePtr styleValues[] = { &isItalic, &isBold, &fontID }; + ByteCount styleSizes[] = + { sizeof(Boolean), sizeof(Boolean), sizeof(ATSUFontID) }; - err = ATSUSetAttributes(style, - sizeof(styleTags) / sizeof(styleTags[0]), - styleTags, styleSizes, styleValues); + err = ATSUSetAttributes(style, + sizeof(styleTags) / sizeof(styleTags[0]), + styleTags, styleSizes, styleValues); + } return _cairo_atsui_font_create_scaled (&toy_face->base, fontID, style, font_matrix, ctm, options, font_out); @@ -580,6 +590,10 @@ _cairo_atsui_font_old_show_glyphs (void *abstract_font, cairo_bool_t can_draw_directly; cairo_rectangle_int16_t rect; + ATSFontRef atsFont; + CGFontRef cgFont; + CGAffineTransform textTransform; + /* Check if we can draw directly to the destination surface */ can_draw_directly = _cairo_surface_is_quartz (generic_surface) && _cairo_pattern_is_opaque_solid (pattern) && @@ -637,14 +651,12 @@ _cairo_atsui_font_old_show_glyphs (void *abstract_font, CGContextSaveGState (drawingContext); } - ATSFontRef atsFont = FMGetATSFontRefFromFont(font->fontID); - CGFontRef cgFont = CGFontCreateWithPlatformFont(&atsFont); + atsFont = FMGetATSFontRefFromFont(font->fontID); + cgFont = CGFontCreateWithPlatformFont(&atsFont); CGContextSetFont(drawingContext, cgFont); - CGAffineTransform textTransform = - CGAffineTransformMakeWithCairoFontScale(&font->base.scale); - + textTransform = CGAffineTransformMakeWithCairoFontScale(&font->base.scale); textTransform = CGAffineTransformScale(textTransform, 1.0f, -1.0f); CGContextSetFontSize(drawingContext, 1.0); diff --git a/gfx/cairo/cairo/src/cairo-clip-private.h b/gfx/cairo/cairo/src/cairo-clip-private.h index 9f07d286b1d1..d3255fae694c 100644 --- a/gfx/cairo/cairo/src/cairo-clip-private.h +++ b/gfx/cairo/cairo/src/cairo-clip-private.h @@ -38,6 +38,8 @@ #include "cairo-path-fixed-private.h" +extern cairo_private const cairo_rectangle_list_t _cairo_rectangles_nil; + struct _cairo_clip_path { unsigned int ref_count; cairo_path_fixed_t path; @@ -124,13 +126,7 @@ _cairo_clip_translate (cairo_clip_t *clip, cairo_fixed_t tx, cairo_fixed_t ty); -cairo_private cairo_bool_t -_cairo_clip_has_clip (cairo_clip_t *clip); - -cairo_private cairo_bool_t -_cairo_clip_extract_rectangles (cairo_clip_t *clip, - int max_rectangles, - cairo_clip_rect_t *rectangles_out, - int *num_rectangles_out); +cairo_private cairo_rectangle_list_t* +_cairo_clip_copy_rectangles (cairo_clip_t *clip, cairo_gstate_t *gstate); #endif /* CAIRO_CLIP_PRIVATE_H */ diff --git a/gfx/cairo/cairo/src/cairo-clip.c b/gfx/cairo/cairo/src/cairo-clip.c index 7e4718d3dce4..a0f67fa859fa 100644 --- a/gfx/cairo/cairo/src/cairo-clip.c +++ b/gfx/cairo/cairo/src/cairo-clip.c @@ -118,6 +118,39 @@ _cairo_clip_reset (cairo_clip_t *clip) return CAIRO_STATUS_SUCCESS; } +static cairo_status_t +_cairo_clip_path_intersect_to_rectangle (cairo_clip_path_t *clip_path, + cairo_rectangle_int16_t *rectangle) +{ + while (clip_path) { + cairo_status_t status; + cairo_traps_t traps; + cairo_box_t extents; + cairo_rectangle_int16_t extents_rect; + + _cairo_traps_init (&traps); + + status = _cairo_path_fixed_fill_to_traps (&clip_path->path, + clip_path->fill_rule, + clip_path->tolerance, + &traps); + if (status) { + _cairo_traps_fini (&traps); + return status; + } + + _cairo_traps_extents (&traps, &extents); + _cairo_box_round_to_rectangle (&extents, &extents_rect); + _cairo_rectangle_intersect (rectangle, &extents_rect); + + _cairo_traps_fini (&traps); + + clip_path = clip_path->prev; + } + + return CAIRO_STATUS_SUCCESS; +} + cairo_status_t _cairo_clip_intersect_to_rectangle (cairo_clip_t *clip, cairo_rectangle_int16_t *rectangle) @@ -126,7 +159,12 @@ _cairo_clip_intersect_to_rectangle (cairo_clip_t *clip, return CAIRO_STATUS_SUCCESS; if (clip->path) { - /* Intersect path extents here. */ + cairo_status_t status; + + status = _cairo_clip_path_intersect_to_rectangle (clip->path, + rectangle); + if (status) + return status; } if (clip->region) { @@ -535,52 +573,89 @@ _cairo_clip_init_deep_copy (cairo_clip_t *clip, } } -cairo_bool_t -_cairo_clip_has_clip (cairo_clip_t *clip) -{ - return clip->region != NULL || clip->surface != NULL || clip->path != NULL; -} +const cairo_rectangle_list_t _cairo_rectangles_nil = + { CAIRO_STATUS_NO_MEMORY, NULL, 0 }; +static const cairo_rectangle_list_t _cairo_rectangles_not_representable = + { CAIRO_STATUS_CLIP_NOT_REPRESENTABLE, NULL, 0 }; static cairo_bool_t -_cairo_region_to_clip_rectangles (pixman_region16_t *region, - int max_rectangles, - cairo_clip_rect_t *rectangles_out, - int *num_rectangles_out) +_cairo_clip_rect_to_user (cairo_gstate_t *gstate, + double x, double y, double width, double height, + cairo_rectangle_t *rectangle) { - int n_boxes, i; - pixman_box16_t *boxes; + double x2 = x + width; + double y2 = y + height; + cairo_bool_t is_tight; - /* no region -> we can't represent it as rectangles */ - if (region == NULL) - return FALSE; + _cairo_gstate_backend_to_user_rectangle (gstate, &x, &y, &x2, &y2, &is_tight); + rectangle->x = x; + rectangle->y = y; + rectangle->width = x2 - x; + rectangle->height = y2 - y; + return is_tight; +} - n_boxes = pixman_region_num_rects (region); - *num_rectangles_out = n_boxes; - if (n_boxes > max_rectangles) - return FALSE; +cairo_private cairo_rectangle_list_t* +_cairo_clip_copy_rectangles (cairo_clip_t *clip, cairo_gstate_t *gstate) +{ + cairo_rectangle_list_t *list; + cairo_rectangle_t *rectangles; + int n_boxes; - boxes = pixman_region_rects (region); - - for (i = 0; i < n_boxes; i++) { - rectangles_out[i].x = boxes[i].x1; - rectangles_out[i].y = boxes[i].y1; - rectangles_out[i].width = boxes[i].x2 - boxes[i].x1; - rectangles_out[i].height = boxes[i].y2 - boxes[i].y1; + if (clip->path || clip->surface) + return (cairo_rectangle_list_t*) &_cairo_rectangles_not_representable; + + n_boxes = clip->region ? pixman_region_num_rects (clip->region) : 1; + rectangles = malloc (sizeof (cairo_rectangle_t)*n_boxes); + if (rectangles == NULL) + return (cairo_rectangle_list_t*) &_cairo_rectangles_nil; + + if (clip->region) { + pixman_box16_t *boxes; + int i; + + boxes = pixman_region_rects (clip->region); + for (i = 0; i < n_boxes; ++i) { + if (!_cairo_clip_rect_to_user(gstate, boxes[i].x1, boxes[i].y1, + boxes[i].x2 - boxes[i].x1, + boxes[i].y2 - boxes[i].y1, + &rectangles[i])) { + free (rectangles); + return (cairo_rectangle_list_t*) + &_cairo_rectangles_not_representable; + } + } + } else { + cairo_rectangle_int16_t extents; + _cairo_surface_get_extents (_cairo_gstate_get_target (gstate), &extents); + if (!_cairo_clip_rect_to_user(gstate, extents.x, extents.y, + extents.width, extents.height, + rectangles)) { + free (rectangles); + return (cairo_rectangle_list_t*) + &_cairo_rectangles_not_representable; + } } - return TRUE; + list = malloc (sizeof (cairo_rectangle_list_t)); + if (list == NULL) { + free (rectangles); + return (cairo_rectangle_list_t*) &_cairo_rectangles_nil; + } + + list->status = CAIRO_STATUS_SUCCESS; + list->rectangles = rectangles; + list->num_rectangles = n_boxes; + return list; } -cairo_bool_t -_cairo_clip_extract_rectangles (cairo_clip_t *clip, - int max_rectangles, - cairo_clip_rect_t *rectangles_out, - int *num_rectangles_out) +void +cairo_rectangle_list_destroy (cairo_rectangle_list_t *rectangle_list) { - /* can't handle paths or surfaces for now */ - if (clip->path != NULL || clip->surface != NULL) - return FALSE; - - return _cairo_region_to_clip_rectangles (clip->region, - max_rectangles, rectangles_out, num_rectangles_out); + if (rectangle_list == NULL || rectangle_list == &_cairo_rectangles_nil || + rectangle_list == &_cairo_rectangles_not_representable) + return; + + free (rectangle_list->rectangles); + free (rectangle_list); } diff --git a/gfx/cairo/cairo/src/cairo-deprecated.h b/gfx/cairo/cairo/src/cairo-deprecated.h new file mode 100644 index 000000000000..77523c447f29 --- /dev/null +++ b/gfx/cairo/cairo/src/cairo-deprecated.h @@ -0,0 +1,139 @@ +/* cairo - a vector graphics library with display and print output + * + * Copyright © 2006 Red Hat, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it either under the terms of the GNU Lesser General Public + * License version 2.1 as published by the Free Software Foundation + * (the "LGPL") or, at your option, under the terms of the Mozilla + * Public License Version 1.1 (the "MPL"). If you do not alter this + * notice, a recipient may use your version of this file under either + * the MPL or the LGPL. + * + * You should have received a copy of the LGPL along with this library + * in the file COPYING-LGPL-2.1; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * You should have received a copy of the MPL along with this library + * in the file COPYING-MPL-1.1 + * + * The contents of this file are subject to the Mozilla Public License + * Version 1.1 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY + * OF ANY KIND, either express or implied. See the LGPL or the MPL for + * the specific language governing rights and limitations. + * + * The Original Code is the cairo graphics library. + * + * The Initial Developer of the Original Code is Red Hat, Inc. + * + * Contributor(s): + * Carl D. Worth + */ + +#ifndef CAIRO_DEPRECATED_H +#define CAIRO_DEPRECATED_H + +/* The CAIRO_FORMAT_RGB16_565 value was added in cairo 1.2.0 as part + * of fixing cairo's xlib backend to work with X servers advertising a + * 16-bit, 565 visual. But as it turned out, adding this format to + * #cairo_format_t was not necessary, and was a mistake, (cairo's xlib + * backend can work fine with 16-bit visuals in the same way it works + * with BGR visuals without any BGR formats in + * #cairo_format_t). + * + * Additionally, the support for the RGB16_565 format was never + * completely implemented. So while this format value is currently + * deprecated, it may eventually acquire complete support in the future. + */ +#define CAIRO_FORMAT_RGB16_565 4 + +#ifndef _CAIROINT_H_ + +/* Obsolete functions. These definitions exist to coerce the compiler + * into providing a little bit of guidance with its error + * messages. The idea is to help users port their old code without + * having to dig through lots of documentation. + * + * The first set of REPLACED_BY functions is for functions whose names + * have just been changed. So fixing these up is mechanical, (and + * automated by means of the cairo/util/cairo-api-update script. + * + * The second set of DEPRECATED_BY functions is for functions where + * the replacement is used in a different way, (ie. different + * arguments, multiple functions instead of one, etc). Fixing these up + * will require a bit more work on the user's part, (and hopefully we + * can get cairo-api-update to find these and print some guiding + * information). + */ +#define cairo_current_font_extents cairo_current_font_extents_REPLACED_BY_cairo_font_extents +#define cairo_get_font_extents cairo_get_font_extents_REPLACED_BY_cairo_font_extents +#define cairo_current_operator cairo_current_operator_REPLACED_BY_cairo_get_operator +#define cairo_current_tolerance cairo_current_tolerance_REPLACED_BY_cairo_get_tolerance +#define cairo_current_point cairo_current_point_REPLACED_BY_cairo_get_current_point +#define cairo_current_fill_rule cairo_current_fill_rule_REPLACED_BY_cairo_get_fill_rule +#define cairo_current_line_width cairo_current_line_width_REPLACED_BY_cairo_get_line_width +#define cairo_current_line_cap cairo_current_line_cap_REPLACED_BY_cairo_get_line_cap +#define cairo_current_line_join cairo_current_line_join_REPLACED_BY_cairo_get_line_join +#define cairo_current_miter_limit cairo_current_miter_limit_REPLACED_BY_cairo_get_miter_limit +#define cairo_current_matrix cairo_current_matrix_REPLACED_BY_cairo_get_matrix +#define cairo_current_target_surface cairo_current_target_surface_REPLACED_BY_cairo_get_target +#define cairo_get_status cairo_get_status_REPLACED_BY_cairo_status +#define cairo_concat_matrix cairo_concat_matrix_REPLACED_BY_cairo_transform +#define cairo_scale_font cairo_scale_font_REPLACED_BY_cairo_set_font_size +#define cairo_select_font cairo_select_font_REPLACED_BY_cairo_select_font_face +#define cairo_transform_font cairo_transform_font_REPLACED_BY_cairo_set_font_matrix +#define cairo_transform_point cairo_transform_point_REPLACED_BY_cairo_user_to_device +#define cairo_transform_distance cairo_transform_distance_REPLACED_BY_cairo_user_to_device_distance +#define cairo_inverse_transform_point cairo_inverse_transform_point_REPLACED_BY_cairo_device_to_user +#define cairo_inverse_transform_distance cairo_inverse_transform_distance_REPLACED_BY_cairo_device_to_user_distance +#define cairo_init_clip cairo_init_clip_REPLACED_BY_cairo_reset_clip +#define cairo_surface_create_for_image cairo_surface_create_for_image_REPLACED_BY_cairo_image_surface_create_for_data +#define cairo_default_matrix cairo_default_matrix_REPLACED_BY_cairo_identity_matrix +#define cairo_matrix_set_affine cairo_matrix_set_affine_REPLACED_BY_cairo_matrix_init +#define cairo_matrix_set_identity cairo_matrix_set_identity_REPLACED_BY_cairo_matrix_init_identity +#define cairo_pattern_add_color_stop cairo_pattern_add_color_stop_REPLACED_BY_cairo_pattern_add_color_stop_rgba +#define cairo_set_rgb_color cairo_set_rgb_color_REPLACED_BY_cairo_set_source_rgb +#define cairo_set_pattern cairo_set_pattern_REPLACED_BY_cairo_set_source +#define cairo_xlib_surface_create_for_pixmap_with_visual cairo_xlib_surface_create_for_pixmap_with_visual_REPLACED_BY_cairo_xlib_surface_create +#define cairo_xlib_surface_create_for_window_with_visual cairo_xlib_surface_create_for_window_with_visual_REPLACED_BY_cairo_xlib_surface_create +#define cairo_xcb_surface_create_for_pixmap_with_visual cairo_xcb_surface_create_for_pixmap_with_visual_REPLACED_BY_cairo_xcb_surface_create +#define cairo_xcb_surface_create_for_window_with_visual cairo_xcb_surface_create_for_window_with_visual_REPLACED_BY_cairo_xcb_surface_create +#define cairo_ps_surface_set_dpi cairo_ps_surface_set_dpi_REPLACED_BY_cairo_surface_set_fallback_resolution +#define cairo_pdf_surface_set_dpi cairo_pdf_surface_set_dpi_REPLACED_BY_cairo_surface_set_fallback_resolution +#define cairo_svg_surface_set_dpi cairo_svg_surface_set_dpi_REPLACED_BY_cairo_surface_set_fallback_resolution + +#define cairo_current_path cairo_current_path_DEPRECATED_BY_cairo_copy_path +#define cairo_current_path_flat cairo_current_path_flat_DEPRECATED_BY_cairo_copy_path_flat +#define cairo_get_path cairo_get_path_DEPRECATED_BY_cairo_copy_path +#define cairo_get_path_flat cairo_get_path_flat_DEPRECATED_BY_cairo_get_path_flat +#define cairo_set_alpha cairo_set_alpha_DEPRECATED_BY_cairo_set_source_rgba_OR_cairo_paint_with_alpha +#define cairo_show_surface cairo_show_surface_DEPRECATED_BY_cairo_set_source_surface_AND_cairo_paint +#define cairo_copy cairo_copy_DEPRECATED_BY_cairo_create_AND_MANY_INDIVIDUAL_FUNCTIONS +#define cairo_surface_set_repeat cairo_surface_set_repeat_DEPRECATED_BY_cairo_pattern_set_extend +#define cairo_surface_set_matrix cairo_surface_set_matrix_DEPRECATED_BY_cairo_pattern_set_matrix +#define cairo_surface_get_matrix cairo_surface_get_matrix_DEPRECATED_BY_cairo_pattern_get_matrix +#define cairo_surface_set_filter cairo_surface_set_filter_DEPRECATED_BY_cairo_pattern_set_filter +#define cairo_surface_get_filter cairo_surface_get_filter_DEPRECATED_BY_cairo_pattern_get_filter +#define cairo_matrix_create cairo_matrix_create_DEPRECATED_BY_cairo_matrix_t +#define cairo_matrix_destroy cairo_matrix_destroy_DEPRECATED_BY_cairo_matrix_t +#define cairo_matrix_copy cairo_matrix_copy_DEPRECATED_BY_cairo_matrix_t +#define cairo_matrix_get_affine cairo_matrix_get_affine_DEPRECATED_BY_cairo_matrix_t +#define cairo_set_target_surface cairo_set_target_surface_DEPRECATED_BY_cairo_create +#define cairo_set_target_glitz cairo_set_target_glitz_DEPRECATED_BY_cairo_glitz_surface_create +#define cairo_set_target_image cairo_set_target_image_DEPRECATED_BY_cairo_image_surface_create_for_data +#define cairo_set_target_pdf cairo_set_target_pdf_DEPRECATED_BY_cairo_pdf_surface_create +#define cairo_set_target_png cairo_set_target_png_DEPRECATED_BY_cairo_surface_write_to_png +#define cairo_set_target_ps cairo_set_target_ps_DEPRECATED_BY_cairo_ps_surface_create +#define cairo_set_target_quartz cairo_set_target_quartz_DEPRECATED_BY_cairo_quartz_surface_create +#define cairo_set_target_win32 cairo_set_target_win32_DEPRECATED_BY_cairo_win32_surface_create +#define cairo_set_target_xcb cairo_set_target_xcb_DEPRECATED_BY_cairo_xcb_surface_create +#define cairo_set_target_drawable cairo_set_target_drawable_DEPRECATED_BY_cairo_xlib_surface_create +#define cairo_get_status_string cairo_get_status_string_DEPRECATED_BY_cairo_status_AND_cairo_status_to_string +#define cairo_status_string cairo_status_string_DEPRECATED_BY_cairo_status_AND_cairo_status_to_string + +#endif + +#endif /* CAIRO_DEPRECATED_H */ diff --git a/gfx/cairo/cairo/src/cairo-directfb-surface.c b/gfx/cairo/cairo/src/cairo-directfb-surface.c index cb9a667c9066..fdff40accd50 100644 --- a/gfx/cairo/cairo/src/cairo-directfb-surface.c +++ b/gfx/cairo/cairo/src/cairo-directfb-surface.c @@ -38,6 +38,7 @@ #include #include #include +#include #include @@ -50,15 +51,20 @@ #include "cairoint.h" +/* + * Rectangle works fine. + */ +#define DFB_RECTANGLES 1 + /* * Composite works fine. */ -#define DFB_COMPOSITE 1 +#define DFB_COMPOSITE 1 /* * CompositeTrapezoids works (without antialiasing). */ -#define DFB_COMPOSITE_TRAPEZOIDS 1 +#define DFB_COMPOSITE_TRAPEZOIDS 0 /* * ShowGlyphs works fine. @@ -73,31 +79,24 @@ D_DEBUG_DOMAIN (Cairo_DirectFB, "Cairo/DirectFB", "Cairo DirectFB backend"); typedef struct _cairo_directfb_surface { cairo_surface_t base; - cairo_format_t format; - IDirectFB *dfb; - IDirectFBSurface *surface; - IDirectFBSurface *buffer; - + int owner; + IDirectFBSurface *dfbsurface; /* color buffer */ cairo_surface_t *color; DFBRegion *clips; int n_clips; - - cairo_surface_t *buffer_image; - + DFBRegion *dirty_region; int width; int height; - - bool local; } cairo_directfb_surface_t; typedef struct _cairo_directfb_font_cache { IDirectFB *dfb; - IDirectFBSurface *buffer; + IDirectFBSurface *dfbsurface; int width; int height; @@ -132,17 +131,17 @@ static cairo_surface_backend_t cairo_directfb_surface_backend; reg.x2 = cli->x2;\ if (reg.y2 > cli->y2)\ reg.y2 = cli->y2;\ - (surface)->buffer->SetClip ((surface)->buffer, ®);\ + (surface)->dfbsurface->SetClip ((surface)->dfbsurface, ®);\ }\ else {\ - (surface)->buffer->SetClip ((surface)->buffer,\ + (surface)->dfbsurface->SetClip ((surface)->dfbsurface,\ &(surface)->clips[k]);\ }\ func;\ }\ }\ else {\ - (surface)->buffer->SetClip ((surface)->buffer, clip);\ + (surface)->dfbsurface->SetClip ((surface)->dfbsurface, clip);\ func;\ }\ } @@ -325,78 +324,77 @@ _directfb_buffer_surface_create (IDirectFB *dfb, static cairo_status_t _directfb_acquire_surface (cairo_directfb_surface_t *surface, - DFBSurfaceLockFlags lock_flags) + cairo_rectangle_int16_t *intrest_rec, + cairo_image_surface_t **image_out, + cairo_rectangle_int16_t *image_rect_out, + void **image_extra, + DFBSurfaceLockFlags lock_flags) { - if (!surface->local) { - int width, height; - - surface->surface->GetSize (surface->surface, &width, &height); + void *data; + int pitch; + IDirectFBSurface *buffer; + DFBRectangle source_rect; + cairo_format_t cairo_format; + cairo_format = surface->format; - if (surface->width != width || surface->height != height) { - DFBSurfacePixelFormat format; - - if (surface->buffer_image) { - cairo_surface_destroy (surface->buffer_image); - surface->buffer_image = NULL; - } - - if (surface->buffer) - surface->buffer->Release (surface->buffer); - - surface->surface->GetPixelFormat (surface->surface, &format); - surface->format = directfb_to_cairo_format (format); - - if (surface->format == -1) { - D_DEBUG_AT (Cairo_DirectFB, "%s buffer for surface.\n", - surface->buffer ? "Reallocating" : "Allocating"); - - surface->buffer = _directfb_buffer_surface_create (surface->dfb, - DSPF_ARGB, width, height); - if (!surface->buffer) - return CAIRO_STATUS_NO_MEMORY; - - surface->buffer->Blit (surface->buffer, - surface->surface, NULL, 0, 0); - - surface->format = CAIRO_FORMAT_ARGB32; - } - else { - surface->surface->AddRef (surface->surface); - surface->buffer = surface->surface; - } - - surface->width = width; - surface->height = height; + if (surface->format == -1) { + if( intrest_rec ) { + source_rect.x = intrest_rec->x; + source_rect.y = intrest_rec->y; + source_rect.w = intrest_rec->width; + source_rect.h = intrest_rec->height; + }else { + source_rect.x=0; + source_rect.y=0; + surface->dfbsurface->GetSize (surface->dfbsurface,&source_rect.w, &source_rect.h); } + D_DEBUG_AT (Cairo_DirectFB, "%s buffer for surface.\n", + surface->dfbsurface ? "Reallocating" : "Allocating"); + cairo_format = directfb_to_cairo_format(DSPF_ARGB); + buffer = _directfb_buffer_surface_create (surface->dfb,DSPF_ARGB,source_rect.w,source_rect.h); + if (!buffer) + goto ERROR; + *image_extra = buffer; + buffer->SetBlittingFlags (buffer,DSBLIT_BLEND_ALPHACHANNEL | DSBLIT_COLORIZE); + buffer->Blit (buffer,surface->dfbsurface,&source_rect,0,0); + } else { + /*might be a subsurface get the offset*/ + surface->dfbsurface->GetVisibleRectangle (surface->dfbsurface,&source_rect); + buffer = surface->dfbsurface; + *image_extra = buffer; } - - if (lock_flags) { - void *data; - int pitch; - DFBResult ret; + - ret = surface->buffer->Lock (surface->buffer, - lock_flags, &data, &pitch); - if (ret) { - DirectFBError ("IDirectFBSurface::Lock()", ret); - return CAIRO_STATUS_NO_MEMORY; - } + if( buffer->Lock (buffer,lock_flags, &data, &pitch) ) + goto ERROR; - if (!surface->buffer_image) { - surface->buffer_image = cairo_image_surface_create_for_data (data, - surface->format, surface->width, - surface->height, pitch); - if (!surface->buffer_image) { - surface->buffer->Unlock (surface->buffer); - return CAIRO_STATUS_NO_MEMORY; - } - } - else { - cairo_surface_reference (surface->buffer_image); - } + *image_out = (cairo_image_surface_t *)cairo_image_surface_create_for_data (data, + cairo_format,source_rect.w,source_rect.h, pitch); + if (*image_out == NULL ) + goto ERROR; + + if (image_rect_out) { + image_rect_out->x = source_rect.x; + image_rect_out->y = source_rect.y; + image_rect_out->width = source_rect.w; + image_rect_out->height = source_rect.h; + }else { + /*lock for read*/ + cairo_surface_t *sur = &((*image_out)->base); + /*might be a subsurface*/ + if( buffer == surface->dfbsurface ) + cairo_surface_set_device_offset (sur,source_rect.x,source_rect.y); } - - return CAIRO_STATUS_SUCCESS; + return CAIRO_STATUS_SUCCESS; + + ERROR: + *image_extra = NULL; + if( buffer ) { + buffer->Unlock (buffer); + if( buffer != surface->dfbsurface) + buffer->Release(buffer); + } + return CAIRO_STATUS_NO_MEMORY; } @@ -415,33 +413,30 @@ _cairo_directfb_surface_create_similar (void *abstract_src, "%s( src=%p, content=0x%x, width=%d, height=%d).\n", __FUNCTION__, source, content, width, height); + width = (width <= 0) ? 1 : width; + height = (height<= 0) ? 1 : height; + format = _cairo_format_from_content (content); - surface = calloc (1, sizeof(cairo_directfb_surface_t)); if (!surface) return NULL; - surface->surface = _directfb_buffer_surface_create (source->dfb, + surface->dfbsurface = _directfb_buffer_surface_create (source->dfb, cairo_to_directfb_format (format), - MAX (width, 8), MAX (height, 8) ); - if (!surface->surface) { + width, height); + assert(surface->dfbsurface); + + surface->owner = TRUE; + if (!surface->dfbsurface) { + assert(0); free (surface); return NULL; } _cairo_surface_init (&surface->base, &cairo_directfb_surface_backend,content); - - - source->dfb->AddRef (source->dfb); surface->dfb = source->dfb; - - surface->surface->AddRef (surface->surface); - surface->buffer = surface->surface; - surface->format = format; surface->width = width; surface->height = height; - surface->local = true; - return &surface->base; } @@ -453,11 +448,6 @@ _cairo_directfb_surface_finish (void *data) D_DEBUG_AT (Cairo_DirectFB, "%s( surface=%p ).\n", __FUNCTION__, surface); - if (surface->buffer_image) { - cairo_surface_destroy (surface->buffer_image); - surface->buffer_image = NULL; - } - if (surface->clips) { free (surface->clips); surface->clips = NULL; @@ -469,18 +459,13 @@ _cairo_directfb_surface_finish (void *data) surface->color = NULL; } - if (surface->buffer) { - surface->buffer->Release (surface->buffer); - surface->buffer = NULL; - } - - if (surface->surface) { - surface->surface->Release (surface->surface); - surface->surface = NULL; + if (surface->dfbsurface) { + if( surface->owner ) + surface->dfbsurface->Release (surface->dfbsurface); + surface->dfbsurface = NULL; } if (surface->dfb) { - surface->dfb->Release (surface->dfb); surface->dfb = NULL; } @@ -493,22 +478,9 @@ _cairo_directfb_surface_acquire_source_image (void *abstract_s void **image_extra) { cairo_directfb_surface_t *surface = abstract_surface; - cairo_status_t ret; - D_DEBUG_AT (Cairo_DirectFB, "%s( surface=%p ).\n", __FUNCTION__, surface); - - ret = _directfb_acquire_surface (surface, DSLF_READ); - if (ret) - return ret; - - if (image_out) - *image_out = (cairo_image_surface_t *)surface->buffer_image; - - if (image_extra) - *image_extra = surface; - - return CAIRO_STATUS_SUCCESS; + return _directfb_acquire_surface (surface,NULL,image_out,NULL,image_extra,DSLF_READ); } static void @@ -517,11 +489,16 @@ _cairo_directfb_surface_release_source_image (void *abstract_su void *image_extra) { cairo_directfb_surface_t *surface = abstract_surface; + IDirectFBSurface *buffer = image_extra; D_DEBUG_AT (Cairo_DirectFB, "%s( surface=%p ).\n", __FUNCTION__, surface); - surface->buffer->Unlock (surface->buffer); + buffer->Unlock (buffer); + if (surface->dfbsurface != buffer) { + buffer->Release (buffer); + } + cairo_surface_destroy (&image->base); } static cairo_status_t @@ -532,29 +509,12 @@ _cairo_directfb_surface_acquire_dest_image (void *abstract_sur void **image_extra) { cairo_directfb_surface_t *surface = abstract_surface; - cairo_status_t ret; D_DEBUG_AT (Cairo_DirectFB, "%s( surface=%p ).\n", __FUNCTION__, surface); - ret = _directfb_acquire_surface (surface, DSLF_READ | DSLF_WRITE); - if (ret) - return ret; - - if (image_out) - *image_out = (cairo_image_surface_t *)surface->buffer_image; - - if (image_rect_out) { - image_rect_out->x = 0; - image_rect_out->y = 0; - image_rect_out->width = surface->width; - image_rect_out->height = surface->height; - } - - if (image_extra) - *image_extra = interest_rect; - - return CAIRO_STATUS_SUCCESS; + return _directfb_acquire_surface (surface,interest_rect,image_out,image_rect_out,image_extra, + DSLF_READ | DSLF_WRITE); } static void @@ -565,11 +525,24 @@ _cairo_directfb_surface_release_dest_image (void *abstract_surf void *image_extra) { cairo_directfb_surface_t *surface = abstract_surface; + IDirectFBSurface *buffer = image_extra; D_DEBUG_AT (Cairo_DirectFB, "%s( surface=%p ).\n", __FUNCTION__, surface); - - surface->buffer->Unlock (surface->buffer); + buffer->Unlock (buffer); + + if (surface->dfbsurface != buffer) { + DFBRegion region = { x1:interest_rect->x, y1:interest_rect->y, + x2:interest_rect->x+interest_rect->width-1, + y2:interest_rect->y+interest_rect->height-1 }; + surface->dfbsurface->SetClip (surface->dfbsurface, ®ion); + //surface->dfbsurface->SetBlittingFlags (surface->dfbsurface, + // DSBLIT_BLEND_ALPHACHANNEL | DSBLIT_COLORIZE); + surface->dfbsurface->Blit (surface->dfbsurface,buffer,NULL, + image_rect->x,image_rect->y); + buffer->Release (buffer); + } + cairo_surface_destroy (&image->base); } static cairo_status_t @@ -603,7 +576,7 @@ _cairo_directfb_surface_clone_similar (void *abstract_surface, if (!clone) return CAIRO_STATUS_NO_MEMORY; - ret = clone->buffer->Lock (clone->buffer, + ret = clone->dfbsurface->Lock (clone->dfbsurface, DSLF_WRITE, (void *)&dst, &pitch); if (ret) { DirectFBError ("IDirectFBSurface::Lock()", ret); @@ -628,7 +601,7 @@ _cairo_directfb_surface_clone_similar (void *abstract_surface, } } - clone->buffer->Unlock (clone->buffer); + clone->dfbsurface->Unlock (clone->dfbsurface); *clone_out = &clone->base; @@ -701,10 +674,6 @@ _directfb_prepare_composite (cairo_directfb_surface_t *dst, color.a = color.r = color.g = color.b = 0xff; } - ret = _directfb_acquire_surface (dst, 0); - if (ret) - return ret; - if (src_pattern->type == CAIRO_PATTERN_TYPE_SOLID) { cairo_solid_pattern_t *pattern = (cairo_solid_pattern_t *)src_pattern; @@ -716,12 +685,12 @@ _directfb_prepare_composite (cairo_directfb_surface_t *dst, } src = (cairo_directfb_surface_t *)dst->color; - src->buffer->SetColor (src->buffer, + src->dfbsurface->SetColor (src->dfbsurface, pattern->color.red_short >> 8, pattern->color.green_short >> 8, pattern->color.blue_short >> 8, pattern->color.alpha_short >> 8); - src->buffer->FillRectangle (src->buffer, 0, 0, 1, 1); + src->dfbsurface->FillRectangle (src->dfbsurface, 0, 0, 1, 1); cairo_matrix_init_identity (&src_attr.matrix); src_attr.matrix = src_pattern->matrix; @@ -736,12 +705,6 @@ _directfb_prepare_composite (cairo_directfb_surface_t *dst, (cairo_surface_t **)&src, &src_attr); if (ret) return ret; - - ret = _directfb_acquire_surface (src, 0); - if (ret) { - _cairo_pattern_release_surface (src_pattern, &src->base, &src_attr); - return ret; - } } if (color.a != 0xff) @@ -749,15 +712,15 @@ _directfb_prepare_composite (cairo_directfb_surface_t *dst, if (color.r != 0xff || color.g != 0xff || color.b != 0xff) flags |= DSBLIT_COLORIZE; - dst->buffer->SetBlittingFlags (dst->buffer, flags); + dst->dfbsurface->SetBlittingFlags (dst->dfbsurface, flags); if (flags & (DSBLIT_BLEND_COLORALPHA | DSBLIT_BLEND_ALPHACHANNEL)) { - dst->buffer->SetSrcBlendFunction (dst->buffer, sblend); - dst->buffer->SetDstBlendFunction (dst->buffer, dblend); + dst->dfbsurface->SetSrcBlendFunction (dst->dfbsurface, sblend); + dst->dfbsurface->SetDstBlendFunction (dst->dfbsurface, dblend); } if (flags & (DSBLIT_BLEND_COLORALPHA | DSBLIT_COLORIZE)) - dst->buffer->SetColor (dst->buffer, color.r, color.g, color.b, color.a); + dst->dfbsurface->SetColor (dst->dfbsurface, color.r, color.g, color.b, color.a); *ret_src = src; *ret_src_attr = src_attr; @@ -822,8 +785,8 @@ _cairo_directfb_surface_composite (cairo_operator_t op, D_DEBUG_AT (Cairo_DirectFB, "Running Blit().\n"); RUN_CLIPPED( dst, NULL, - dst->buffer->Blit (dst->buffer, - src->buffer, &sr, dst_x, dst_y)); + dst->dfbsurface->Blit (dst->dfbsurface, + src->dfbsurface, &sr, dst_x, dst_y)); ret = CAIRO_STATUS_SUCCESS; } else if (src_attr.extend == CAIRO_EXTEND_REPEAT) { @@ -837,8 +800,8 @@ _cairo_directfb_surface_composite (cairo_operator_t op, D_DEBUG_AT (Cairo_DirectFB, "Running TileBlit().\n"); RUN_CLIPPED( dst, &clip, - dst->buffer->TileBlit (dst->buffer, - src->buffer, &sr, dst_x, dst_y)); + dst->dfbsurface->TileBlit (dst->dfbsurface, + src->dfbsurface, &sr, dst_x, dst_y)); ret = CAIRO_STATUS_SUCCESS; } } @@ -852,7 +815,7 @@ _cairo_directfb_surface_composite (cairo_operator_t op, */ src_x = src_y = 0; - dst->buffer->GetAccelerationMask (dst->buffer, src->buffer, &accel); + dst->dfbsurface->GetAccelerationMask (dst->dfbsurface, src->dfbsurface, &accel); if (m->xy != 0.0 || m->yx != 0.0) { if (accel & DFXL_TEXTRIANGLES) { @@ -898,8 +861,8 @@ _cairo_directfb_surface_composite (cairo_operator_t op, D_DEBUG_AT (Cairo_DirectFB, "Running TextureTriangles().\n"); RUN_CLIPPED (dst, NULL, - dst->buffer->TextureTriangles (dst->buffer, - src->buffer, v, NULL, 4, DTTF_FAN)); + dst->dfbsurface->TextureTriangles (dst->dfbsurface, + src->dfbsurface, v, NULL, 4, DTTF_FAN)); ret = CAIRO_STATUS_SUCCESS; } } @@ -926,8 +889,8 @@ _cairo_directfb_surface_composite (cairo_operator_t op, D_DEBUG_AT (Cairo_DirectFB, "Running StretchBlit().\n"); RUN_CLIPPED (dst, NULL, - dst->buffer->StretchBlit (dst->buffer, - src->buffer, &sr, &dr)); + dst->dfbsurface->StretchBlit (dst->dfbsurface, + src->dfbsurface, &sr, &dr)); ret = CAIRO_STATUS_SUCCESS; } } @@ -939,6 +902,7 @@ _cairo_directfb_surface_composite (cairo_operator_t op, } #endif /* DFB_COMPOSITE */ +#if DFB_RECTANGLES static cairo_int_status_t _cairo_directfb_surface_fill_rectangles (void *abstract_surface, cairo_operator_t op, @@ -947,7 +911,6 @@ _cairo_directfb_surface_fill_rectangles (void *abstract_surface, int n_rects) { cairo_directfb_surface_t *dst = abstract_surface; - cairo_status_t ret; DFBSurfaceDrawingFlags flags; DFBSurfaceBlendFunction sblend; DFBSurfaceBlendFunction dblend; @@ -961,17 +924,13 @@ _cairo_directfb_surface_fill_rectangles (void *abstract_surface, if (_directfb_get_operator (op, &flags, NULL, &sblend, &dblend)) return CAIRO_INT_STATUS_UNSUPPORTED; - ret = _directfb_acquire_surface (dst, 0); - if (ret) - return ret; - - dst->buffer->SetDrawingFlags (dst->buffer, flags); + dst->dfbsurface->SetDrawingFlags (dst->dfbsurface, flags); if (flags & DSDRAW_BLEND) { - dst->buffer->SetSrcBlendFunction (dst->buffer, sblend); - dst->buffer->SetDstBlendFunction (dst->buffer, dblend); + dst->dfbsurface->SetSrcBlendFunction (dst->dfbsurface, sblend); + dst->dfbsurface->SetDstBlendFunction (dst->dfbsurface, dblend); } - dst->buffer->SetColor (dst->buffer, color->red_short >> 8, + dst->dfbsurface->SetColor (dst->dfbsurface, color->red_short >> 8, color->green_short >> 8, color->blue_short >> 8, color->alpha_short >> 8 ); @@ -984,10 +943,11 @@ _cairo_directfb_surface_fill_rectangles (void *abstract_surface, } RUN_CLIPPED (dst, NULL, - dst->buffer->FillRectangles (dst->buffer, r, n_rects)); + dst->dfbsurface->FillRectangles (dst->dfbsurface, r, n_rects)); return CAIRO_STATUS_SUCCESS; } +#endif #if DFB_COMPOSITE_TRAPEZOIDS static cairo_int_status_t @@ -1028,7 +988,7 @@ _cairo_directfb_surface_composite_trapezoids (cairo_operator_t op, if (ret) return ret; - dst->buffer->GetAccelerationMask (dst->buffer, src->buffer, &accel); + dst->dfbsurface->GetAccelerationMask (dst->dfbsurface, src->dfbsurface, &accel); ret = CAIRO_INT_STATUS_UNSUPPORTED; @@ -1118,7 +1078,7 @@ _cairo_directfb_surface_composite_trapezoids (cairo_operator_t op, D_DEBUG_AT (Cairo_DirectFB, "Running TextureTriangles().\n"); RUN_CLIPPED (dst, NULL, - dst->buffer->TextureTriangles (dst->buffer, src->buffer, + dst->dfbsurface->TextureTriangles (dst->dfbsurface, src->dfbsurface, vertex, NULL, n, DTTF_LIST)); ret = CAIRO_STATUS_SUCCESS; @@ -1146,7 +1106,8 @@ _cairo_directfb_surface_set_clip_region (void *abstract_surface, int i; if (surface->n_clips != n_boxes) { - free (surface->clips); + if( surface->clips ) + free (surface->clips); surface->clips = malloc (n_boxes * sizeof(DFBRegion)); if (!surface->clips) { @@ -1202,25 +1163,24 @@ _cairo_directfb_surface_mark_dirty_rectangle (void *abstract_surface, int width, int height) { +#if 0 cairo_directfb_surface_t *surface = abstract_surface; D_DEBUG_AT (Cairo_DirectFB, "%s( surface=%p, x=%d, y=%d, width=%d, height=%d ).\n", __FUNCTION__, surface, x, y, width, height); - - if (surface->surface != surface->buffer) { - DFBRegion region = { x1:x, y1:y, x2:x+width-1, y2:y+height-1 }; - surface->buffer->SetClip (surface->buffer, ®ion); - surface->buffer->SetBlittingFlags (surface->buffer, DSBLIT_NOFX); - surface->buffer->Blit (surface->buffer, surface->surface, NULL, 0, 0); - } - + if( !surface->dirty_region ) + surface->dirty_region = malloc(sizeof(DFBRegion)); + if (!dirty_region) + return CAIRO_STATUS_NO_MEMORY; +#endif return CAIRO_STATUS_SUCCESS; } static cairo_status_t _cairo_directfb_surface_flush (void *abstract_surface) { +#if 0 cairo_directfb_surface_t *surface = abstract_surface; D_DEBUG_AT (Cairo_DirectFB, @@ -1231,7 +1191,7 @@ _cairo_directfb_surface_flush (void *abstract_surface) surface->surface->SetBlittingFlags (surface->surface, DSBLIT_NOFX); surface->surface->Blit (surface->surface, surface->buffer, NULL, 0, 0); } - +#endif return CAIRO_STATUS_SUCCESS; } @@ -1245,13 +1205,13 @@ _directfb_allocate_font_cache (IDirectFB *dfb, int width, int height) if (!cache) return NULL; - cache->buffer = _directfb_buffer_surface_create( dfb, DSPF_A8, width, height); - if (!cache->buffer) { + cache->dfbsurface = _directfb_buffer_surface_create( dfb, DSPF_A8, width, height); + if (!cache->dfbsurface) { free (cache); return NULL; } - dfb->AddRef (dfb); + //dfb->AddRef (dfb); cache->dfb = dfb; cache->width = width; @@ -1263,8 +1223,7 @@ _directfb_allocate_font_cache (IDirectFB *dfb, int width, int height) static void _directfb_destroy_font_cache (cairo_directfb_font_cache_t *cache) { - cache->buffer->Release (cache->buffer); - cache->dfb->Release (cache->dfb); + cache->dfbsurface->Release (cache->dfbsurface); free (cache); } @@ -1386,8 +1345,8 @@ _directfb_acquire_font_cache (cairo_directfb_surface_t *surface, if (!new_cache) return CAIRO_STATUS_NO_MEMORY; - new_cache->buffer->Blit (new_cache->buffer, - cache->buffer, NULL, 0, 0); + new_cache->dfbsurface->Blit (new_cache->dfbsurface, + cache->dfbsurface, NULL, 0, 0); _directfb_destroy_font_cache (cache); scaled_font->surface_private = cache = new_cache; @@ -1409,7 +1368,7 @@ _directfb_acquire_font_cache (cairo_directfb_surface_t *surface, unsigned char *data; int pitch; - if (cache->buffer->Lock (cache->buffer, + if (cache->dfbsurface->Lock (cache->dfbsurface, DSLF_WRITE, (void *)&data, &pitch)) return CAIRO_STATUS_NO_MEMORY; @@ -1437,7 +1396,7 @@ _directfb_acquire_font_cache (cairo_directfb_surface_t *surface, } } - cache->buffer->Unlock (cache->buffer); + cache->dfbsurface->Unlock (cache->dfbsurface); } cache->x = x; @@ -1509,10 +1468,6 @@ _cairo_directfb_surface_show_glyphs ( void *abstract_dst, sblend == DSBF_DESTALPHA || sblend == DSBF_INVDESTALPHA) return CAIRO_INT_STATUS_UNSUPPORTED; - ret = _directfb_acquire_surface (dst, 0); - if (ret) - return ret; - ret = _directfb_acquire_font_cache (dst, scaled_font, glyphs, num_glyphs, &cache, &rects[0], &points[0], &num); if (ret) { @@ -1536,16 +1491,16 @@ _cairo_directfb_surface_show_glyphs ( void *abstract_dst, dblend = DSBF_INVSRCALPHA; } - dst->buffer->SetBlittingFlags (dst->buffer, flags); - dst->buffer->SetSrcBlendFunction (dst->buffer, sblend); - dst->buffer->SetDstBlendFunction (dst->buffer, dblend); - dst->buffer->SetColor (dst->buffer, color.r, color.g, color.b, color.a); + dst->dfbsurface->SetBlittingFlags (dst->dfbsurface, flags); + dst->dfbsurface->SetSrcBlendFunction (dst->dfbsurface, sblend); + dst->dfbsurface->SetDstBlendFunction (dst->dfbsurface, dblend); + dst->dfbsurface->SetColor (dst->dfbsurface, color.r, color.g, color.b, color.a); D_DEBUG_AT (Cairo_DirectFB, "Running BatchBlit().\n"); RUN_CLIPPED (dst, NULL, - dst->buffer->BatchBlit (dst->buffer, - cache->buffer, rects, points, num)); + dst->dfbsurface->BatchBlit (dst->dfbsurface, + cache->dfbsurface, rects, points, num)); return CAIRO_STATUS_SUCCESS; } @@ -1566,7 +1521,11 @@ static cairo_surface_backend_t cairo_directfb_surface_backend = { #else NULL,/*composite*/ #endif +#if DFB_RECTANGLES _cairo_directfb_surface_fill_rectangles,/*fill_rectangles*/ +#else + NULL,/*fill_rectangles*/ +#endif #if DFB_COMPOSITE_TRAPEZOIDS _cairo_directfb_surface_composite_trapezoids,/*composite_trapezoids*/ #else @@ -1642,27 +1601,23 @@ cairo_directfb_surface_create (IDirectFB *dfb, IDirectFBSurface *dfbsurface) { DFBSurfacePixelFormat format; cairo_directfb_surface_t *surface; - + + assert(dfb); + assert(dfb); cairo_directfb_surface_backend_init (dfb); surface = calloc (1, sizeof(cairo_directfb_surface_t)); - if (!surface) + if (!surface) return NULL; dfbsurface->GetPixelFormat (dfbsurface, &format); _cairo_surface_init (&surface->base, &cairo_directfb_surface_backend, _directfb_format_to_content(format)); - - dfb->AddRef (dfb); + surface->owner = FALSE; surface->dfb = dfb; - dfbsurface->AddRef (dfbsurface); - surface->surface = dfbsurface; - - if (_directfb_acquire_surface (surface, 0)) { - cairo_surface_destroy ((cairo_surface_t *)surface); - return NULL; - } - + surface->dfbsurface = dfbsurface; + dfbsurface->GetSize (dfbsurface,&surface->width, &surface->height); + surface->format = directfb_to_cairo_format(format); return &surface->base; } diff --git a/gfx/cairo/cairo/src/cairo-directfb.h b/gfx/cairo/cairo/src/cairo-directfb.h index b7771967b2cf..845f3de68283 100644 --- a/gfx/cairo/cairo/src/cairo-directfb.h +++ b/gfx/cairo/cairo/src/cairo-directfb.h @@ -43,7 +43,8 @@ CAIRO_BEGIN_DECLS -cairo_surface_t * cairo_directfb_surface_create (IDirectFB *dfb,IDirectFBSurface *surface); +cairo_public cairo_surface_t * +cairo_directfb_surface_create (IDirectFB *dfb,IDirectFBSurface *surface); CAIRO_END_DECLS diff --git a/gfx/cairo/cairo/src/cairo-font-options.c b/gfx/cairo/cairo/src/cairo-font-options.c index e3a5f75c0903..2b0cd988b598 100644 --- a/gfx/cairo/cairo/src/cairo-font-options.c +++ b/gfx/cairo/cairo/src/cairo-font-options.c @@ -95,6 +95,7 @@ cairo_font_options_create (void) return options; } +slim_hidden_def (cairo_font_options_create); /** * cairo_font_options_copy: @@ -137,6 +138,7 @@ cairo_font_options_destroy (cairo_font_options_t *options) free (options); } +slim_hidden_def (cairo_font_options_destroy); /** * cairo_font_options_status: @@ -182,6 +184,7 @@ cairo_font_options_merge (cairo_font_options_t *options, if (other->hint_metrics != CAIRO_HINT_METRICS_DEFAULT) options->hint_metrics = other->hint_metrics; } +slim_hidden_def (cairo_font_options_merge); /** * cairo_font_options_equal: @@ -201,6 +204,7 @@ cairo_font_options_equal (const cairo_font_options_t *options, options->hint_style == other->hint_style && options->hint_metrics == other->hint_metrics); } +slim_hidden_def (cairo_font_options_equal); /** * cairo_font_options_hash: @@ -222,6 +226,7 @@ cairo_font_options_hash (const cairo_font_options_t *options) (options->hint_style << 8) | (options->hint_metrics << 16)); } +slim_hidden_def (cairo_font_options_hash); /** * cairo_font_options_set_antialias: @@ -240,6 +245,7 @@ cairo_font_options_set_antialias (cairo_font_options_t *options, options->antialias = antialias; } +slim_hidden_def (cairo_font_options_set_antialias); /** * cairo_font_options_get_antialias: @@ -275,6 +281,7 @@ cairo_font_options_set_subpixel_order (cairo_font_options_t *options, options->subpixel_order = subpixel_order; } +slim_hidden_def (cairo_font_options_set_subpixel_order); /** * cairo_font_options_get_subpixel_order: @@ -310,6 +317,7 @@ cairo_font_options_set_hint_style (cairo_font_options_t *options, options->hint_style = hint_style; } +slim_hidden_def (cairo_font_options_set_hint_style); /** * cairo_font_options_get_hint_style: @@ -345,6 +353,7 @@ cairo_font_options_set_hint_metrics (cairo_font_options_t *options, options->hint_metrics = hint_metrics; } +slim_hidden_def (cairo_font_options_set_hint_metrics); /** * cairo_font_options_get_hint_metrics: diff --git a/gfx/cairo/cairo/src/cairo-font-subset.c b/gfx/cairo/cairo/src/cairo-font-subset.c deleted file mode 100644 index dc21d14907aa..000000000000 --- a/gfx/cairo/cairo/src/cairo-font-subset.c +++ /dev/null @@ -1,812 +0,0 @@ -/* cairo - a vector graphics library with display and print output - * - * Copyright © 2004 Red Hat, Inc - * - * This library is free software; you can redistribute it and/or - * modify it either under the terms of the GNU Lesser General Public - * License version 2.1 as published by the Free Software Foundation - * (the "LGPL") or, at your option, under the terms of the Mozilla - * Public License Version 1.1 (the "MPL"). If you do not alter this - * notice, a recipient may use your version of this file under either - * the MPL or the LGPL. - * - * You should have received a copy of the LGPL along with this library - * in the file COPYING-LGPL-2.1; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * You should have received a copy of the MPL along with this library - * in the file COPYING-MPL-1.1 - * - * The contents of this file are subject to the Mozilla Public License - * Version 1.1 (the "License"); you may not use this file except in - * compliance with the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY - * OF ANY KIND, either express or implied. See the LGPL or the MPL for - * the specific language governing rights and limitations. - * - * The Original Code is the cairo graphics library. - * - * The Initial Developer of the Original Code is Red Hat, Inc. - * - * Contributor(s): - * Kristian Høgsberg - */ - -#include "cairoint.h" -#include "cairo-scaled-font-subsets-private.h" - -/* XXX: Eventually, we need to handle other font backends */ -#include "cairo-ft-private.h" - -#include -#include FT_FREETYPE_H -#include FT_OUTLINE_H -#include FT_TRUETYPE_TAGS_H -#include FT_TRUETYPE_TABLES_H - -typedef struct ft_subset_glyph ft_subset_glyph_t; -struct ft_subset_glyph { - int parent_index; - unsigned long location; -}; - -typedef struct _cairo_ft_font { - - cairo_scaled_font_subset_t *scaled_font_subset; - - struct { - cairo_unscaled_font_t *unscaled_font; - unsigned int font_id; - char *base_font; - int num_glyphs; - int *widths; - long x_min, y_min, x_max, y_max; - long ascent, descent; - } base; - - ft_subset_glyph_t *glyphs; - FT_Face face; - int checksum_index; - cairo_array_t output; - int *parent_to_subset; - cairo_status_t status; - -} cairo_pdf_ft_font_t; - -static int -cairo_pdf_ft_font_use_glyph (cairo_pdf_ft_font_t *font, int glyph); - -#define ARRAY_LENGTH(a) ( (sizeof (a)) / (sizeof ((a)[0])) ) - -#define SFNT_VERSION 0x00010000 - -#ifdef WORDS_BIGENDIAN - -#define cpu_to_be16(v) (v) -#define be16_to_cpu(v) (v) -#define cpu_to_be32(v) (v) -#define be32_to_cpu(v) (v) - -#else - -static inline unsigned short -cpu_to_be16(unsigned short v) -{ - return (v << 8) | (v >> 8); -} - -static inline unsigned short -be16_to_cpu(unsigned short v) -{ - return cpu_to_be16 (v); -} - -static inline unsigned long -cpu_to_be32(unsigned long v) -{ - return (cpu_to_be16 (v) << 16) | cpu_to_be16 (v >> 16); -} - -static inline unsigned long -be32_to_cpu(unsigned long v) -{ - return cpu_to_be32 (v); -} - -#endif - -static cairo_status_t -_cairo_pdf_ft_font_create (cairo_scaled_font_subset_t *scaled_font_subset, - cairo_pdf_ft_font_t **font_return) -{ - cairo_unscaled_font_t *unscaled_font; - cairo_ft_unscaled_font_t *ft_unscaled_font; - cairo_status_t status = CAIRO_STATUS_NO_MEMORY; - cairo_pdf_ft_font_t *font; - FT_Face face; - unsigned long size; - int i, j; - - /* XXX: Need to fix this to work with a general cairo_unscaled_font_t. */ - if (!_cairo_scaled_font_is_ft (scaled_font_subset->scaled_font)) - return CAIRO_INT_STATUS_UNSUPPORTED; - - if (_cairo_ft_scaled_font_is_vertical (scaled_font_subset->scaled_font)) - return CAIRO_INT_STATUS_UNSUPPORTED; - - unscaled_font = _cairo_ft_scaled_font_get_unscaled_font (scaled_font_subset->scaled_font); - - ft_unscaled_font = (cairo_ft_unscaled_font_t *) unscaled_font; - - face = _cairo_ft_unscaled_font_lock_face (ft_unscaled_font); - if (face == NULL) - /* Assume out of memory */ - return CAIRO_STATUS_NO_MEMORY; - - /* We currently only support freetype truetype fonts. */ - size = 0; - if (!FT_IS_SFNT (face) || - FT_Load_Sfnt_Table (face, TTAG_glyf, 0, NULL, &size) != 0) - return CAIRO_INT_STATUS_UNSUPPORTED; - - font = malloc (sizeof (cairo_pdf_ft_font_t)); - if (font == NULL) - return CAIRO_STATUS_NO_MEMORY; - - font->scaled_font_subset = scaled_font_subset; - - font->base.unscaled_font = _cairo_unscaled_font_reference (unscaled_font); - - _cairo_array_init (&font->output, sizeof (char)); - if (_cairo_array_grow_by (&font->output, 4096) != CAIRO_STATUS_SUCCESS) - goto fail1; - - font->glyphs = calloc (face->num_glyphs + 1, sizeof (ft_subset_glyph_t)); - if (font->glyphs == NULL) - goto fail2; - - font->parent_to_subset = calloc (face->num_glyphs, sizeof (int)); - if (font->parent_to_subset == NULL) - goto fail3; - - font->base.num_glyphs = 0; - font->base.x_min = face->bbox.xMin; - font->base.y_min = face->bbox.yMin; - font->base.x_max = face->bbox.xMax; - font->base.y_max = face->bbox.yMax; - font->base.ascent = face->ascender; - font->base.descent = face->descender; - font->base.base_font = strdup (face->family_name); - if (font->base.base_font == NULL) - goto fail4; - - for (i = 0, j = 0; font->base.base_font[j]; j++) { - if (font->base.base_font[j] == ' ') - continue; - font->base.base_font[i++] = font->base.base_font[j]; - } - font->base.base_font[i] = '\0'; - - font->base.widths = calloc (face->num_glyphs, sizeof (int)); - if (font->base.widths == NULL) - goto fail5; - - _cairo_ft_unscaled_font_unlock_face (ft_unscaled_font); - - font->status = CAIRO_STATUS_SUCCESS; - - *font_return = font; - - return CAIRO_STATUS_SUCCESS; - - fail5: - free (font->base.base_font); - fail4: - free (font->parent_to_subset); - fail3: - free (font->glyphs); - fail2: - _cairo_array_fini (&font->output); - fail1: - free (font); - - return status; -} - -static void -cairo_pdf_ft_font_destroy (cairo_pdf_ft_font_t *font) -{ - _cairo_unscaled_font_destroy (font->base.unscaled_font); - free (font->base.base_font); - free (font->parent_to_subset); - free (font->glyphs); - _cairo_array_fini (&font->output); - free (font); -} - -static cairo_status_t -cairo_pdf_ft_font_allocate_write_buffer (cairo_pdf_ft_font_t *font, - size_t length, - unsigned char **buffer) -{ - cairo_status_t status; - - status = _cairo_array_allocate (&font->output, length, (void **) buffer); - if (status) - return status; - - return CAIRO_STATUS_SUCCESS; -} - -static cairo_status_t -cairo_pdf_ft_font_write (cairo_pdf_ft_font_t *font, - const void *data, size_t length) -{ - cairo_status_t status; - - status = _cairo_array_append_multiple (&font->output, data, length); - if (status) - return status; - - return CAIRO_STATUS_SUCCESS; -} - -static void -cairo_pdf_ft_font_write_be16 (cairo_pdf_ft_font_t *font, - unsigned short value) -{ - unsigned short be16_value; - - be16_value = cpu_to_be16 (value); - cairo_pdf_ft_font_write (font, &be16_value, sizeof be16_value); -} - -static void -cairo_pdf_ft_font_write_be32 (cairo_pdf_ft_font_t *font, unsigned long value) -{ - unsigned long be32_value; - - be32_value = cpu_to_be32 (value); - cairo_pdf_ft_font_write (font, &be32_value, sizeof be32_value); -} - -static unsigned long -cairo_pdf_ft_font_align_output (cairo_pdf_ft_font_t *font) -{ - int length, aligned, pad; - unsigned char *ignored; - - length = _cairo_array_num_elements (&font->output); - aligned = (length + 3) & ~3; - pad = aligned - length; - - if (pad) - cairo_pdf_ft_font_allocate_write_buffer (font, pad, &ignored); - - return aligned; -} - -static int -cairo_pdf_ft_font_write_cmap_table (cairo_pdf_ft_font_t *font, unsigned long tag) -{ - int i; - - cairo_pdf_ft_font_write_be16 (font, 0); - cairo_pdf_ft_font_write_be16 (font, 1); - - cairo_pdf_ft_font_write_be16 (font, 1); - cairo_pdf_ft_font_write_be16 (font, 0); - cairo_pdf_ft_font_write_be32 (font, 12); - - /* Output a format 6 encoding table. */ - - cairo_pdf_ft_font_write_be16 (font, 6); - cairo_pdf_ft_font_write_be16 (font, 10 + 2 * (font->base.num_glyphs - 1)); - cairo_pdf_ft_font_write_be16 (font, 0); - cairo_pdf_ft_font_write_be16 (font, 1); /* First glyph */ - cairo_pdf_ft_font_write_be16 (font, font->base.num_glyphs - 1); - for (i = 1; i < font->base.num_glyphs; i++) - cairo_pdf_ft_font_write_be16 (font, i); - - return font->status; -} - -static int -cairo_pdf_ft_font_write_generic_table (cairo_pdf_ft_font_t *font, - unsigned long tag) -{ - cairo_status_t status; - unsigned char *buffer; - unsigned long size; - - size = 0; - FT_Load_Sfnt_Table (font->face, tag, 0, NULL, &size); - status = cairo_pdf_ft_font_allocate_write_buffer (font, size, &buffer); - /* XXX: Need to check status here. */ - FT_Load_Sfnt_Table (font->face, tag, 0, buffer, &size); - - return 0; -} - -typedef struct composite_glyph composite_glyph_t; -struct composite_glyph { - unsigned short flags; - unsigned short index; - unsigned short args[7]; /* 1 to 7 arguments depending on value of flags */ -}; - -typedef struct glyph_data glyph_data_t; -struct glyph_data { - short num_contours; - char data[8]; - composite_glyph_t glyph; -}; - -/* composite_glyph_t flags */ -#define ARG_1_AND_2_ARE_WORDS 0x0001 -#define WE_HAVE_A_SCALE 0x0008 -#define MORE_COMPONENTS 0x0020 -#define WE_HAVE_AN_X_AND_Y_SCALE 0x0040 -#define WE_HAVE_A_TWO_BY_TWO 0x0080 - -static void -cairo_pdf_ft_font_remap_composite_glyph (cairo_pdf_ft_font_t *font, - unsigned char *buffer) -{ - glyph_data_t *glyph_data; - composite_glyph_t *composite_glyph; - int num_args; - int has_more_components; - unsigned short flags; - unsigned short index; - - glyph_data = (glyph_data_t *) buffer; - if ((short)be16_to_cpu (glyph_data->num_contours) >= 0) - return; - - composite_glyph = &glyph_data->glyph; - do { - flags = be16_to_cpu (composite_glyph->flags); - has_more_components = flags & MORE_COMPONENTS; - index = cairo_pdf_ft_font_use_glyph (font, be16_to_cpu (composite_glyph->index)); - composite_glyph->index = cpu_to_be16 (index); - num_args = 1; - if (flags & ARG_1_AND_2_ARE_WORDS) - num_args += 1; - if (flags & WE_HAVE_A_SCALE) - num_args += 1; - else if (flags & WE_HAVE_AN_X_AND_Y_SCALE) - num_args += 2; - else if (flags & WE_HAVE_A_TWO_BY_TWO) - num_args += 3; - composite_glyph = (composite_glyph_t *) &(composite_glyph->args[num_args]); - } while (has_more_components); -} - -static int -cairo_pdf_ft_font_write_glyf_table (cairo_pdf_ft_font_t *font, - unsigned long tag) -{ - cairo_status_t status; - unsigned long start_offset, index, size; - TT_Header *header; - unsigned long begin, end; - unsigned char *buffer; - int i; - union { - unsigned char *bytes; - unsigned short *short_offsets; - unsigned long *long_offsets; - } u; - - header = FT_Get_Sfnt_Table (font->face, ft_sfnt_head); - if (header->Index_To_Loc_Format == 0) - size = sizeof (short) * (font->face->num_glyphs + 1); - else - size = sizeof (long) * (font->face->num_glyphs + 1); - - u.bytes = malloc (size); - if (u.bytes == NULL) { - font->status = CAIRO_STATUS_NO_MEMORY; - return font->status; - } - FT_Load_Sfnt_Table (font->face, TTAG_loca, 0, u.bytes, &size); - - start_offset = _cairo_array_num_elements (&font->output); - for (i = 0; i < font->base.num_glyphs; i++) { - index = font->glyphs[i].parent_index; - if (header->Index_To_Loc_Format == 0) { - begin = be16_to_cpu (u.short_offsets[index]) * 2; - end = be16_to_cpu (u.short_offsets[index + 1]) * 2; - } - else { - begin = be32_to_cpu (u.long_offsets[index]); - end = be32_to_cpu (u.long_offsets[index + 1]); - } - - size = end - begin; - - font->glyphs[i].location = - cairo_pdf_ft_font_align_output (font) - start_offset; - status = cairo_pdf_ft_font_allocate_write_buffer (font, size, &buffer); - if (status) - break; - if (size != 0) { - FT_Load_Sfnt_Table (font->face, TTAG_glyf, begin, buffer, &size); - cairo_pdf_ft_font_remap_composite_glyph (font, buffer); - } - } - - font->glyphs[i].location = - cairo_pdf_ft_font_align_output (font) - start_offset; - - free (u.bytes); - - return font->status; -} - -static int -cairo_pdf_ft_font_write_head_table (cairo_pdf_ft_font_t *font, - unsigned long tag) -{ - TT_Header *head; - - head = FT_Get_Sfnt_Table (font->face, ft_sfnt_head); - - cairo_pdf_ft_font_write_be32 (font, head->Table_Version); - cairo_pdf_ft_font_write_be32 (font, head->Font_Revision); - - font->checksum_index = _cairo_array_num_elements (&font->output); - cairo_pdf_ft_font_write_be32 (font, 0); - cairo_pdf_ft_font_write_be32 (font, head->Magic_Number); - - cairo_pdf_ft_font_write_be16 (font, head->Flags); - cairo_pdf_ft_font_write_be16 (font, head->Units_Per_EM); - - cairo_pdf_ft_font_write_be32 (font, head->Created[0]); - cairo_pdf_ft_font_write_be32 (font, head->Created[1]); - cairo_pdf_ft_font_write_be32 (font, head->Modified[0]); - cairo_pdf_ft_font_write_be32 (font, head->Modified[1]); - - cairo_pdf_ft_font_write_be16 (font, head->xMin); - cairo_pdf_ft_font_write_be16 (font, head->yMin); - cairo_pdf_ft_font_write_be16 (font, head->xMax); - cairo_pdf_ft_font_write_be16 (font, head->yMax); - - cairo_pdf_ft_font_write_be16 (font, head->Mac_Style); - cairo_pdf_ft_font_write_be16 (font, head->Lowest_Rec_PPEM); - - cairo_pdf_ft_font_write_be16 (font, head->Font_Direction); - cairo_pdf_ft_font_write_be16 (font, head->Index_To_Loc_Format); - cairo_pdf_ft_font_write_be16 (font, head->Glyph_Data_Format); - - return font->status; -} - -static int cairo_pdf_ft_font_write_hhea_table (cairo_pdf_ft_font_t *font, unsigned long tag) -{ - TT_HoriHeader *hhea; - - hhea = FT_Get_Sfnt_Table (font->face, ft_sfnt_hhea); - - cairo_pdf_ft_font_write_be32 (font, hhea->Version); - cairo_pdf_ft_font_write_be16 (font, hhea->Ascender); - cairo_pdf_ft_font_write_be16 (font, hhea->Descender); - cairo_pdf_ft_font_write_be16 (font, hhea->Line_Gap); - - cairo_pdf_ft_font_write_be16 (font, hhea->advance_Width_Max); - - cairo_pdf_ft_font_write_be16 (font, hhea->min_Left_Side_Bearing); - cairo_pdf_ft_font_write_be16 (font, hhea->min_Right_Side_Bearing); - cairo_pdf_ft_font_write_be16 (font, hhea->xMax_Extent); - cairo_pdf_ft_font_write_be16 (font, hhea->caret_Slope_Rise); - cairo_pdf_ft_font_write_be16 (font, hhea->caret_Slope_Run); - cairo_pdf_ft_font_write_be16 (font, hhea->caret_Offset); - - cairo_pdf_ft_font_write_be16 (font, 0); - cairo_pdf_ft_font_write_be16 (font, 0); - cairo_pdf_ft_font_write_be16 (font, 0); - cairo_pdf_ft_font_write_be16 (font, 0); - - cairo_pdf_ft_font_write_be16 (font, hhea->metric_Data_Format); - cairo_pdf_ft_font_write_be16 (font, font->base.num_glyphs); - - return font->status; -} - -static int -cairo_pdf_ft_font_write_hmtx_table (cairo_pdf_ft_font_t *font, - unsigned long tag) -{ - cairo_status_t status; - unsigned long entry_size; - short *p; - int i; - - for (i = 0; i < font->base.num_glyphs; i++) { - entry_size = 2 * sizeof (short); - status = cairo_pdf_ft_font_allocate_write_buffer (font, entry_size, - (unsigned char **) &p); - /* XXX: Need to check status here. */ - FT_Load_Sfnt_Table (font->face, TTAG_hmtx, - font->glyphs[i].parent_index * entry_size, - (FT_Byte *) p, &entry_size); - font->base.widths[i] = be16_to_cpu (p[0]); - } - - return font->status; -} - -static int -cairo_pdf_ft_font_write_loca_table (cairo_pdf_ft_font_t *font, - unsigned long tag) -{ - int i; - TT_Header *header; - - header = FT_Get_Sfnt_Table (font->face, ft_sfnt_head); - - if (header->Index_To_Loc_Format == 0) { - for (i = 0; i < font->base.num_glyphs + 1; i++) - cairo_pdf_ft_font_write_be16 (font, font->glyphs[i].location / 2); - } - else { - for (i = 0; i < font->base.num_glyphs + 1; i++) - cairo_pdf_ft_font_write_be32 (font, font->glyphs[i].location); - } - - return font->status; -} - -static int -cairo_pdf_ft_font_write_maxp_table (cairo_pdf_ft_font_t *font, - unsigned long tag) -{ - TT_MaxProfile *maxp; - - maxp = FT_Get_Sfnt_Table (font->face, ft_sfnt_maxp); - - cairo_pdf_ft_font_write_be32 (font, maxp->version); - cairo_pdf_ft_font_write_be16 (font, font->base.num_glyphs); - cairo_pdf_ft_font_write_be16 (font, maxp->maxPoints); - cairo_pdf_ft_font_write_be16 (font, maxp->maxContours); - cairo_pdf_ft_font_write_be16 (font, maxp->maxCompositePoints); - cairo_pdf_ft_font_write_be16 (font, maxp->maxCompositeContours); - cairo_pdf_ft_font_write_be16 (font, maxp->maxZones); - cairo_pdf_ft_font_write_be16 (font, maxp->maxTwilightPoints); - cairo_pdf_ft_font_write_be16 (font, maxp->maxStorage); - cairo_pdf_ft_font_write_be16 (font, maxp->maxFunctionDefs); - cairo_pdf_ft_font_write_be16 (font, maxp->maxInstructionDefs); - cairo_pdf_ft_font_write_be16 (font, maxp->maxStackElements); - cairo_pdf_ft_font_write_be16 (font, maxp->maxSizeOfInstructions); - cairo_pdf_ft_font_write_be16 (font, maxp->maxComponentElements); - cairo_pdf_ft_font_write_be16 (font, maxp->maxComponentDepth); - - return font->status; -} - -typedef struct table table_t; -struct table { - unsigned long tag; - int (*write) (cairo_pdf_ft_font_t *font, unsigned long tag); -}; - -static const table_t truetype_tables[] = { - /* As we write out the glyf table we remap composite glyphs. - * Remapping composite glyphs will reference the sub glyphs the - * composite glyph is made up of. That needs to be done first so - * we have all the glyphs in the subset before going further. */ - { TTAG_glyf, cairo_pdf_ft_font_write_glyf_table }, - { TTAG_cmap, cairo_pdf_ft_font_write_cmap_table }, - { TTAG_cvt, cairo_pdf_ft_font_write_generic_table }, - { TTAG_fpgm, cairo_pdf_ft_font_write_generic_table }, - { TTAG_head, cairo_pdf_ft_font_write_head_table }, - { TTAG_hhea, cairo_pdf_ft_font_write_hhea_table }, - { TTAG_hmtx, cairo_pdf_ft_font_write_hmtx_table }, - { TTAG_loca, cairo_pdf_ft_font_write_loca_table }, - { TTAG_maxp, cairo_pdf_ft_font_write_maxp_table }, - { TTAG_name, cairo_pdf_ft_font_write_generic_table }, - { TTAG_prep, cairo_pdf_ft_font_write_generic_table }, -}; - -static cairo_status_t -cairo_pdf_ft_font_write_offset_table (cairo_pdf_ft_font_t *font) -{ - cairo_status_t status; - unsigned char *table_buffer; - size_t table_buffer_length; - unsigned short search_range, entry_selector, range_shift; - int num_tables; - - num_tables = ARRAY_LENGTH (truetype_tables); - search_range = 1; - entry_selector = 0; - while (search_range * 2 <= num_tables) { - search_range *= 2; - entry_selector++; - } - search_range *= 16; - range_shift = num_tables * 16 - search_range; - - cairo_pdf_ft_font_write_be32 (font, SFNT_VERSION); - cairo_pdf_ft_font_write_be16 (font, num_tables); - cairo_pdf_ft_font_write_be16 (font, search_range); - cairo_pdf_ft_font_write_be16 (font, entry_selector); - cairo_pdf_ft_font_write_be16 (font, range_shift); - - /* XXX: Why are we allocating a table here and then ignoring the - * returned buffer? This should result in garbage in the output - * file, correct? Is this just unfinished code? -cworth. */ - table_buffer_length = ARRAY_LENGTH (truetype_tables) * 16; - status = cairo_pdf_ft_font_allocate_write_buffer (font, table_buffer_length, - &table_buffer); - if (status) - return status; - - return font->status; -} - -static unsigned long -cairo_pdf_ft_font_calculate_checksum (cairo_pdf_ft_font_t *font, - unsigned long start, unsigned long end) -{ - unsigned long *padded_end; - unsigned long *p; - unsigned long checksum; - char *data; - - checksum = 0; - data = _cairo_array_index (&font->output, 0); - p = (unsigned long *) (data + start); - padded_end = (unsigned long *) (data + ((end + 3) & ~3)); - while (p < padded_end) - checksum += *p++; - - return checksum; -} - -static void -cairo_pdf_ft_font_update_entry (cairo_pdf_ft_font_t *font, int index, unsigned long tag, - unsigned long start, unsigned long end) -{ - unsigned long *entry; - - entry = _cairo_array_index (&font->output, 12 + 16 * index); - entry[0] = cpu_to_be32 (tag); - entry[1] = cpu_to_be32 (cairo_pdf_ft_font_calculate_checksum (font, start, end)); - entry[2] = cpu_to_be32 (start); - entry[3] = cpu_to_be32 (end - start); -} - -static cairo_status_t -cairo_pdf_ft_font_generate (void *abstract_font, - const char **data, unsigned long *length) -{ - cairo_ft_unscaled_font_t *ft_unscaled_font; - cairo_pdf_ft_font_t *font = abstract_font; - unsigned long start, end, next, checksum, *checksum_location; - int i; - - /* XXX: It would be cleaner to do something besides this cast - * here. Perhaps cairo_pdf_ft_font_t should just have the - * cairo_ft_unscaled_font_t rather than having the generic - * cairo_unscaled_font_t in the base class? */ - ft_unscaled_font = (cairo_ft_unscaled_font_t *) font->base.unscaled_font; - - font->face = _cairo_ft_unscaled_font_lock_face (ft_unscaled_font); - - if (cairo_pdf_ft_font_write_offset_table (font)) - goto fail; - - start = cairo_pdf_ft_font_align_output (font); - end = start; - - end = 0; - for (i = 0; i < ARRAY_LENGTH (truetype_tables); i++) { - if (truetype_tables[i].write (font, truetype_tables[i].tag)) - goto fail; - - end = _cairo_array_num_elements (&font->output); - next = cairo_pdf_ft_font_align_output (font); - cairo_pdf_ft_font_update_entry (font, i, truetype_tables[i].tag, - start, end); - start = next; - } - - checksum = - 0xb1b0afba - cairo_pdf_ft_font_calculate_checksum (font, 0, end); - checksum_location = _cairo_array_index (&font->output, font->checksum_index); - *checksum_location = cpu_to_be32 (checksum); - - *data = _cairo_array_index (&font->output, 0); - *length = _cairo_array_num_elements (&font->output); - - fail: - _cairo_ft_unscaled_font_unlock_face (ft_unscaled_font); - font->face = NULL; - - return font->status; -} - -static int -cairo_pdf_ft_font_use_glyph (cairo_pdf_ft_font_t *font, int glyph) -{ - if (font->parent_to_subset[glyph] == 0) { - font->parent_to_subset[glyph] = font->base.num_glyphs; - font->glyphs[font->base.num_glyphs].parent_index = glyph; - font->base.num_glyphs++; - } - - return font->parent_to_subset[glyph]; -} - -cairo_status_t -_cairo_truetype_subset_init (cairo_truetype_subset_t *truetype_subset, - cairo_scaled_font_subset_t *font_subset) -{ - cairo_pdf_ft_font_t *font; - cairo_status_t status; - const char *data = NULL; /* squelch bogus compiler warning */ - unsigned long parent_glyph, length = 0; /* squelch bogus compiler warning */ - int i; - - status = _cairo_pdf_ft_font_create (font_subset, &font); - if (status) - return status; - - for (i = 0; i < font->scaled_font_subset->num_glyphs; i++) { - parent_glyph = font->scaled_font_subset->glyphs[i]; - cairo_pdf_ft_font_use_glyph (font, parent_glyph); - } - - status = cairo_pdf_ft_font_generate (font, &data, &length); - if (status) - goto fail1; - - truetype_subset->base_font = strdup (font->base.base_font); - if (truetype_subset->base_font == NULL) - goto fail1; - - truetype_subset->widths = calloc (sizeof (int), font->base.num_glyphs); - if (truetype_subset->widths == NULL) - goto fail2; - for (i = 0; i < font->base.num_glyphs; i++) - truetype_subset->widths[i] = font->base.widths[i]; - - truetype_subset->x_min = font->base.x_min; - truetype_subset->y_min = font->base.y_min; - truetype_subset->x_max = font->base.x_max; - truetype_subset->y_max = font->base.y_max; - truetype_subset->ascent = font->base.ascent; - truetype_subset->descent = font->base.descent; - - truetype_subset->data = malloc (length); - if (truetype_subset->data == NULL) - goto fail3; - - memcpy (truetype_subset->data, data, length); - truetype_subset->data_length = length; - - cairo_pdf_ft_font_destroy (font); - - return CAIRO_STATUS_SUCCESS; - - fail3: - free (truetype_subset->widths); - fail2: - free (truetype_subset->base_font); - fail1: - cairo_pdf_ft_font_destroy (font); - - return status; -} - -void -_cairo_truetype_subset_fini (cairo_truetype_subset_t *subset) -{ - free (subset->base_font); - free (subset->widths); - free (subset->data); -} - diff --git a/gfx/cairo/cairo/src/cairo-font.c b/gfx/cairo/cairo/src/cairo-font.c index 5ef8b6c556ec..373068673e4a 100644 --- a/gfx/cairo/cairo/src/cairo-font.c +++ b/gfx/cairo/cairo/src/cairo-font.c @@ -49,7 +49,7 @@ static const cairo_font_face_backend_t _cairo_toy_font_face_backend; const cairo_font_face_t _cairo_font_face_nil = { { 0 }, /* hash_entry */ CAIRO_STATUS_NO_MEMORY, /* status */ - -1, /* ref_count */ + CAIRO_REF_COUNT_INVALID, /* ref_count */ { 0, 0, 0, NULL }, /* user_data */ &_cairo_toy_font_face_backend }; @@ -82,7 +82,7 @@ cairo_font_face_reference (cairo_font_face_t *font_face) if (font_face == NULL) return NULL; - if (font_face->ref_count == (unsigned int)-1) + if (font_face->ref_count == CAIRO_REF_COUNT_INVALID) return font_face; /* We would normally assert (font_face->ref_count >0) here but we @@ -93,6 +93,7 @@ cairo_font_face_reference (cairo_font_face_t *font_face) return font_face; } +slim_hidden_def (cairo_font_face_reference); /** * cairo_font_face_destroy: @@ -108,7 +109,7 @@ cairo_font_face_destroy (cairo_font_face_t *font_face) if (font_face == NULL) return; - if (font_face->ref_count == (unsigned int)-1) + if (font_face->ref_count == CAIRO_REF_COUNT_INVALID) return; assert (font_face->ref_count > 0); @@ -129,12 +130,16 @@ cairo_font_face_destroy (cairo_font_face_t *font_face) free (font_face); } +slim_hidden_def (cairo_font_face_destroy); /** * cairo_font_face_get_type: * @font_face: a #cairo_font_face_t * - * Return value: The type of @font_face. See #cairo_font_type_t. + * This function returns the type of the backend used to create + * a font face. See #cairo_font_type_t for available types. + * + * Return value: The type of @font_face. * * Since: 1.2 **/ @@ -202,7 +207,7 @@ cairo_font_face_set_user_data (cairo_font_face_t *font_face, void *user_data, cairo_destroy_func_t destroy) { - if (font_face->ref_count == -1) + if (font_face->ref_count == CAIRO_REF_COUNT_INVALID) return CAIRO_STATUS_NO_MEMORY; return _cairo_user_data_array_set_data (&font_face->user_data, diff --git a/gfx/cairo/cairo/src/cairo-ft-font.c b/gfx/cairo/cairo/src/cairo-ft-font.c index 18aa68ced5f9..25fabc994d91 100644 --- a/gfx/cairo/cairo/src/cairo-ft-font.c +++ b/gfx/cairo/cairo/src/cairo-ft-font.c @@ -48,6 +48,7 @@ #include FT_FREETYPE_H #include FT_OUTLINE_H #include FT_IMAGE_H +#include FT_TRUETYPE_TABLES_H #if HAVE_FT_GLYPHSLOT_EMBOLDEN #include FT_SYNTHESIS_H #endif @@ -97,6 +98,7 @@ struct _cairo_ft_unscaled_font { double y_scale; /* Extracted Y scale factor */ cairo_bool_t have_shape; /* true if the current scale has a non-scale component*/ cairo_matrix_t current_shape; + FT_Matrix Current_Shape; int lock; /* count of how many times this font has been locked */ @@ -550,6 +552,7 @@ _cairo_ft_unscaled_font_lock_face (cairo_ft_unscaled_font_t *unscaled) return face; } +slim_hidden_def (cairo_ft_scaled_font_lock_face); /* Unlock unscaled font locked with _cairo_ft_unscaled_font_lock_face */ @@ -560,6 +563,7 @@ _cairo_ft_unscaled_font_unlock_face (cairo_ft_unscaled_font_t *unscaled) unscaled->lock--; } +slim_hidden_def (cairo_ft_scaled_font_unlock_face); static void _compute_transform (cairo_ft_font_transform_t *sf, @@ -601,7 +605,6 @@ _cairo_ft_unscaled_font_set_scale (cairo_ft_unscaled_font_t *unscaled, { cairo_ft_font_transform_t sf; FT_Matrix mat; - FT_UInt pixel_width, pixel_height; FT_Error error; assert (unscaled->face != NULL); @@ -631,6 +634,7 @@ _cairo_ft_unscaled_font_set_scale (cairo_ft_unscaled_font_t *unscaled, mat.xy != 0x00000 || mat.yy != 0x10000); + unscaled->Current_Shape = mat; cairo_matrix_init (&unscaled->current_shape, sf.shape[0][0], sf.shape[0][1], sf.shape[1][0], sf.shape[1][1], @@ -639,19 +643,16 @@ _cairo_ft_unscaled_font_set_scale (cairo_ft_unscaled_font_t *unscaled, FT_Set_Transform(unscaled->face, &mat, NULL); if ((unscaled->face->face_flags & FT_FACE_FLAG_SCALABLE) != 0) { - pixel_width = sf.x_scale; - pixel_height = sf.y_scale; error = FT_Set_Char_Size (unscaled->face, sf.x_scale * 64.0, sf.y_scale * 64.0, 0, 0); + assert (error == 0); } else { double min_distance = DBL_MAX; int i; int best_i = 0; - pixel_width = pixel_height = 0; - for (i = 0; i < unscaled->face->num_fixed_sizes; i++) { #if HAVE_FT_BITMAP_SIZE_Y_PPEM double size = unscaled->face->available_sizes[i].y_ppem / 64.; @@ -675,9 +676,8 @@ _cairo_ft_unscaled_font_set_scale (cairo_ft_unscaled_font_t *unscaled, error = FT_Set_Pixel_Sizes (unscaled->face, unscaled->face->available_sizes[best_i].width, unscaled->face->available_sizes[best_i].height); + assert (error == 0); } - - assert (error == 0); } /* Empirically-derived subpixel filtering values thanks to Keith @@ -978,6 +978,7 @@ _render_glyph_outline (FT_Face face, switch (font_options->subpixel_order) { case CAIRO_SUBPIXEL_ORDER_RGB: case CAIRO_SUBPIXEL_ORDER_BGR: + case CAIRO_SUBPIXEL_ORDER_DEFAULT: default: matrix.xx *= 3; hmul = 3; @@ -1231,6 +1232,8 @@ _get_pattern_ft_options (FcPattern *pattern) antialias = FcTrue; if (antialias) { + cairo_subpixel_order_t subpixel_order; + if (!bitmap) ft_options.load_flags |= FT_LOAD_NO_BITMAP; @@ -1245,25 +1248,28 @@ _get_pattern_ft_options (FcPattern *pattern) switch (rgba) { case FC_RGBA_RGB: - ft_options.base.subpixel_order = CAIRO_SUBPIXEL_ORDER_RGB; + subpixel_order = CAIRO_SUBPIXEL_ORDER_RGB; break; case FC_RGBA_BGR: - ft_options.base.subpixel_order = CAIRO_SUBPIXEL_ORDER_BGR; + subpixel_order = CAIRO_SUBPIXEL_ORDER_BGR; break; case FC_RGBA_VRGB: - ft_options.base.subpixel_order = CAIRO_SUBPIXEL_ORDER_VRGB; + subpixel_order = CAIRO_SUBPIXEL_ORDER_VRGB; break; case FC_RGBA_VBGR: - ft_options.base.subpixel_order = CAIRO_SUBPIXEL_ORDER_VBGR; + subpixel_order = CAIRO_SUBPIXEL_ORDER_VBGR; break; case FC_RGBA_UNKNOWN: case FC_RGBA_NONE: default: + subpixel_order = CAIRO_SUBPIXEL_ORDER_DEFAULT; break; } - if (ft_options.base.subpixel_order != CAIRO_SUBPIXEL_ORDER_DEFAULT) + if (subpixel_order != CAIRO_SUBPIXEL_ORDER_DEFAULT) { + ft_options.base.subpixel_order = subpixel_order; ft_options.base.antialias = CAIRO_ANTIALIAS_SUBPIXEL; + } #ifdef FC_HINT_STYLE if (FcPatternGetInteger (pattern, @@ -1458,7 +1464,7 @@ _cairo_ft_scaled_font_create (cairo_ft_unscaled_font_t *unscaled, fs_metrics.ascent = DOUBLE_FROM_26_6(metrics->ascender) * y_factor; fs_metrics.descent = DOUBLE_FROM_26_6(- metrics->descender) * y_factor; fs_metrics.height = DOUBLE_FROM_26_6(metrics->height) * y_factor; - if (!(scaled_font->ft_options.load_flags & FT_LOAD_VERTICAL_LAYOUT)) { + if (!_cairo_ft_scaled_font_is_vertical (&scaled_font->base)) { fs_metrics.max_x_advance = DOUBLE_FROM_26_6(metrics->max_advance) * x_factor; fs_metrics.max_y_advance = 0; } else { @@ -1471,7 +1477,7 @@ _cairo_ft_scaled_font_create (cairo_ft_unscaled_font_t *unscaled, fs_metrics.ascent = face->ascender / scale; fs_metrics.descent = - face->descender / scale; fs_metrics.height = face->height / scale; - if (!(scaled_font->ft_options.load_flags & FT_LOAD_VERTICAL_LAYOUT)) { + if (!_cairo_ft_scaled_font_is_vertical (&scaled_font->base)) { fs_metrics.max_x_advance = face->max_advance_width / scale; fs_metrics.max_y_advance = 0; } else { @@ -1726,16 +1732,21 @@ _decompose_glyph_outline (FT_Face face, * Translate glyph to match its metrics. */ static void -_cairo_ft_scaled_glyph_vertical_layout_bearing_fix (FT_GlyphSlot glyph) +_cairo_ft_scaled_glyph_vertical_layout_bearing_fix (void *abstract_font, + FT_GlyphSlot glyph) { - FT_Pos x = glyph->metrics.vertBearingX - glyph->metrics.horiBearingX; - FT_Pos y = -glyph->metrics.vertBearingY - glyph->metrics.horiBearingY; + cairo_ft_scaled_font_t *scaled_font = abstract_font; + FT_Vector vector; - if (glyph->format == FT_GLYPH_FORMAT_OUTLINE) - FT_Outline_Translate(&glyph->outline, x, y); - else if (glyph->format == FT_GLYPH_FORMAT_BITMAP) { - glyph->bitmap_left += x / 64; - glyph->bitmap_top += y / 64; + vector.x = glyph->metrics.vertBearingX - glyph->metrics.horiBearingX; + vector.y = -glyph->metrics.vertBearingY - glyph->metrics.horiBearingY; + + if (glyph->format == FT_GLYPH_FORMAT_OUTLINE) { + FT_Vector_Transform (&vector, &scaled_font->unscaled->Current_Shape); + FT_Outline_Translate(&glyph->outline, vector.x, vector.y); + } else if (glyph->format == FT_GLYPH_FORMAT_BITMAP) { + glyph->bitmap_left += vector.x / 64; + glyph->bitmap_top += vector.y / 64; } } @@ -1796,7 +1807,7 @@ _cairo_ft_scaled_glyph_init (void *abstract_font, #endif if (vertical_layout) - _cairo_ft_scaled_glyph_vertical_layout_bearing_fix (glyph); + _cairo_ft_scaled_glyph_vertical_layout_bearing_fix (scaled_font, glyph); if (info & CAIRO_SCALED_GLYPH_INFO_METRICS) { /* @@ -1815,8 +1826,7 @@ _cairo_ft_scaled_glyph_init (void *abstract_font, y_factor = 1 / unscaled->y_scale; /* - * Note: the font's coordinate system is upside down from ours, so the - * Y coordinates of the bearing and advance need to be negated. + * Note: Y coordinates of the horizontal bearing need to be negated. * * Scale metrics back to glyph space from the scaled glyph space returned * by FreeType @@ -1934,7 +1944,7 @@ _cairo_ft_scaled_glyph_init (void *abstract_font, FT_GlyphSlot_Embolden (glyph); #endif if (vertical_layout) - _cairo_ft_scaled_glyph_vertical_layout_bearing_fix (glyph); + _cairo_ft_scaled_glyph_vertical_layout_bearing_fix (scaled_font, glyph); } if (glyph->format == FT_GLYPH_FORMAT_OUTLINE) @@ -1990,6 +2000,36 @@ _cairo_ft_show_glyphs (void *abstract_font, return CAIRO_INT_STATUS_UNSUPPORTED; } +static cairo_int_status_t +_cairo_ft_load_truetype_table (void *abstract_font, + unsigned long tag, + long offset, + unsigned char *buffer, + unsigned long *length) +{ + cairo_ft_scaled_font_t *scaled_font = abstract_font; + cairo_ft_unscaled_font_t *unscaled = scaled_font->unscaled; + FT_Face face; + cairo_status_t status = CAIRO_INT_STATUS_UNSUPPORTED; + + if (_cairo_ft_scaled_font_is_vertical (&scaled_font->base)) + return CAIRO_INT_STATUS_UNSUPPORTED; + +#if HAVE_FT_LOAD_SFNT_TABLE + face = _cairo_ft_unscaled_font_lock_face (unscaled); + if (!face) + return CAIRO_STATUS_NO_MEMORY; + + if (FT_IS_SFNT (face) && + FT_Load_Sfnt_Table (face, tag, offset, buffer, length) == 0) + status = CAIRO_STATUS_SUCCESS; + + _cairo_ft_unscaled_font_unlock_face (unscaled); +#endif + + return status; +} + const cairo_scaled_font_backend_t cairo_ft_scaled_font_backend = { CAIRO_FONT_TYPE_FT, _cairo_ft_scaled_font_create_toy, @@ -1998,6 +2038,7 @@ const cairo_scaled_font_backend_t cairo_ft_scaled_font_backend = { NULL, /* text_to_glyphs */ _cairo_ft_ucs4_to_index, _cairo_ft_show_glyphs, + _cairo_ft_load_truetype_table, }; /* cairo_ft_font_face_t */ @@ -2157,6 +2198,10 @@ cairo_ft_font_options_substitute (const cairo_font_options_t *options, if (FcPatternGet (pattern, FC_ANTIALIAS, 0, &v) == FcResultNoMatch) { FcPatternAddBool (pattern, FC_ANTIALIAS, options->antialias != CAIRO_ANTIALIAS_NONE); + if (options->antialias != CAIRO_ANTIALIAS_SUBPIXEL) { + FcPatternDel (pattern, FC_RGBA); + FcPatternAddInteger (pattern, FC_RGBA, FC_RGBA_NONE); + } } } @@ -2204,6 +2249,9 @@ cairo_ft_font_options_substitute (const cairo_font_options_t *options, int hint_style; switch (options->hint_style) { + case CAIRO_HINT_STYLE_NONE: + hint_style = FC_HINT_NONE; + break; case CAIRO_HINT_STYLE_SLIGHT: hint_style = FC_HINT_SLIGHT; break; @@ -2211,6 +2259,7 @@ cairo_ft_font_options_substitute (const cairo_font_options_t *options, hint_style = FC_HINT_MEDIUM; break; case CAIRO_HINT_STYLE_FULL: + case CAIRO_HINT_STYLE_DEFAULT: default: hint_style = FC_HINT_FULL; break; @@ -2221,6 +2270,7 @@ cairo_ft_font_options_substitute (const cairo_font_options_t *options, #endif } } +slim_hidden_def (cairo_ft_font_options_substitute); /** * cairo_ft_font_face_create_for_pattern: diff --git a/gfx/cairo/cairo/src/cairo-ft-private.h b/gfx/cairo/cairo/src/cairo-ft-private.h index 34c5d9c86580..3e28f5e24e23 100644 --- a/gfx/cairo/cairo/src/cairo-ft-private.h +++ b/gfx/cairo/cairo/src/cairo-ft-private.h @@ -64,11 +64,14 @@ _cairo_ft_unscaled_font_lock_face (cairo_ft_unscaled_font_t *unscaled); cairo_private void _cairo_ft_unscaled_font_unlock_face (cairo_ft_unscaled_font_t *unscaled); -cairo_bool_t +cairo_private cairo_bool_t _cairo_ft_scaled_font_is_vertical (cairo_scaled_font_t *scaled_font); +slim_hidden_proto (cairo_ft_font_options_substitute); +slim_hidden_proto (cairo_ft_scaled_font_lock_face); +slim_hidden_proto (cairo_ft_scaled_font_unlock_face); + CAIRO_END_DECLS #endif /* CAIRO_HAS_FT_FONT */ - #endif /* CAIRO_FT_PRIVATE_H */ diff --git a/gfx/cairo/cairo/src/cairo-gstate.c b/gfx/cairo/cairo/src/cairo-gstate.c index 5053ba669cda..8beb8c49c9b0 100644 --- a/gfx/cairo/cairo/src/cairo-gstate.c +++ b/gfx/cairo/cairo/src/cairo-gstate.c @@ -492,9 +492,9 @@ _cairo_gstate_get_line_join (cairo_gstate_t *gstate) } cairo_status_t -_cairo_gstate_set_dash (cairo_gstate_t *gstate, double *dash, int num_dashes, double offset) +_cairo_gstate_set_dash (cairo_gstate_t *gstate, const double *dash, int num_dashes, double offset) { - int i; + unsigned int i; double dash_total; if (gstate->stroke_style.dash) @@ -706,6 +706,25 @@ _cairo_gstate_backend_to_user (cairo_gstate_t *gstate, double *x, double *y) cairo_matrix_transform_point (&gstate->ctm_inverse, x, y); } +void +_cairo_gstate_backend_to_user_rectangle (cairo_gstate_t *gstate, + double *x1, double *y1, + double *x2, double *y2, + cairo_bool_t *is_tight) +{ + double width = *x2 - *x1; + double height = *y2 - *y1; + cairo_matrix_t matrix_inverse; + + cairo_matrix_multiply (&matrix_inverse, &gstate->ctm_inverse, + &gstate->target->device_transform_inverse); + _cairo_matrix_transform_bounding_box ( + &matrix_inverse, x1, y1, &width, &height, is_tight); + + *x2 = *x1 + width; + *y2 = *y1 + height; +} + /* XXX: NYI cairo_status_t _cairo_gstate_stroke_to_path (cairo_gstate_t *gstate) @@ -1041,6 +1060,29 @@ _cairo_gstate_show_page (cairo_gstate_t *gstate) return status; } +static void +_cairo_gstate_traps_extents_to_user_rectangle (cairo_gstate_t *gstate, + cairo_traps_t *traps, + double *x1, double *y1, + double *x2, double *y2) +{ + cairo_box_t extents; + + _cairo_traps_extents (traps, &extents); + + if (extents.p1.x >= extents.p2.x || extents.p1.y >= extents.p2.y) { + /* no traps, so we actually won't draw anything */ + *x1 = *y1 = *x2 = *y2 = 0; + } else { + *x1 = _cairo_fixed_to_double (extents.p1.x); + *y1 = _cairo_fixed_to_double (extents.p1.y); + *x2 = _cairo_fixed_to_double (extents.p2.x); + *y2 = _cairo_fixed_to_double (extents.p2.y); + + _cairo_gstate_backend_to_user_rectangle (gstate, x1, y1, x2, y2, NULL); + } +} + cairo_status_t _cairo_gstate_stroke_extents (cairo_gstate_t *gstate, cairo_path_fixed_t *path, @@ -1049,7 +1091,6 @@ _cairo_gstate_stroke_extents (cairo_gstate_t *gstate, { cairo_status_t status; cairo_traps_t traps; - cairo_box_t extents; _cairo_traps_init (&traps); @@ -1059,20 +1100,10 @@ _cairo_gstate_stroke_extents (cairo_gstate_t *gstate, &gstate->ctm_inverse, gstate->tolerance, &traps); - if (status) - goto BAIL; + if (status == CAIRO_STATUS_SUCCESS) { + _cairo_gstate_traps_extents_to_user_rectangle(gstate, &traps, x1, y1, x2, y2); + } - _cairo_traps_extents (&traps, &extents); - - *x1 = _cairo_fixed_to_double (extents.p1.x); - *y1 = _cairo_fixed_to_double (extents.p1.y); - *x2 = _cairo_fixed_to_double (extents.p2.x); - *y2 = _cairo_fixed_to_double (extents.p2.y); - - _cairo_gstate_backend_to_user (gstate, x1, y1); - _cairo_gstate_backend_to_user (gstate, x2, y2); - -BAIL: _cairo_traps_fini (&traps); return status; @@ -1094,20 +1125,10 @@ _cairo_gstate_fill_extents (cairo_gstate_t *gstate, gstate->fill_rule, gstate->tolerance, &traps); - if (status) - goto BAIL; + if (status == CAIRO_STATUS_SUCCESS) { + _cairo_gstate_traps_extents_to_user_rectangle(gstate, &traps, x1, y1, x2, y2); + } - _cairo_traps_extents (&traps, &extents); - - *x1 = _cairo_fixed_to_double (extents.p1.x); - *y1 = _cairo_fixed_to_double (extents.p1.y); - *x2 = _cairo_fixed_to_double (extents.p2.x); - *y2 = _cairo_fixed_to_double (extents.p2.y); - - _cairo_gstate_backend_to_user (gstate, x1, y1); - _cairo_gstate_backend_to_user (gstate, x2, y2); - -BAIL: _cairo_traps_fini (&traps); return status; @@ -1127,6 +1148,40 @@ _cairo_gstate_clip (cairo_gstate_t *gstate, cairo_path_fixed_t *path) gstate->antialias, gstate->target); } +cairo_status_t +_cairo_gstate_clip_extents (cairo_gstate_t *gstate, + double *x1, + double *y1, + double *x2, + double *y2) +{ + cairo_rectangle_int16_t extents; + cairo_status_t status; + + status = _cairo_surface_get_extents (gstate->target, &extents); + if (status) + return status; + + status = _cairo_clip_intersect_to_rectangle (&gstate->clip, &extents); + if (status) + return status; + + *x1 = extents.x; + *y1 = extents.y; + *x2 = extents.x + extents.width; + *y2 = extents.y + extents.height; + + _cairo_gstate_backend_to_user_rectangle (gstate, x1, y1, x2, y2, NULL); + + return CAIRO_STATUS_SUCCESS; +} + +cairo_rectangle_list_t* +_cairo_gstate_copy_clip_rectangles (cairo_gstate_t *gstate) +{ + return _cairo_clip_copy_rectangles (&gstate->clip, gstate); +} + static void _cairo_gstate_unset_scaled_font (cairo_gstate_t *gstate) { @@ -1411,7 +1466,7 @@ _cairo_gstate_glyph_extents (cairo_gstate_t *gstate, cairo_status_t _cairo_gstate_show_glyphs (cairo_gstate_t *gstate, - cairo_glyph_t *glyphs, + const cairo_glyph_t *glyphs, int num_glyphs) { cairo_status_t status; @@ -1436,10 +1491,12 @@ _cairo_gstate_show_glyphs (cairo_gstate_t *gstate, for (i = 0; i < num_glyphs; ++i) { - transformed_glyphs[i] = glyphs[i]; - _cairo_gstate_user_to_device (gstate, - &transformed_glyphs[i].x, - &transformed_glyphs[i].y); + transformed_glyphs[i].index = glyphs[i].index; + transformed_glyphs[i].x = glyphs[i].x + gstate->font_matrix.x0; + transformed_glyphs[i].y = glyphs[i].y + gstate->font_matrix.y0; + _cairo_gstate_user_to_backend (gstate, + &transformed_glyphs[i].x, + &transformed_glyphs[i].y); } _cairo_gstate_copy_transformed_source (gstate, &source_pattern.base); @@ -1477,7 +1534,9 @@ _cairo_gstate_glyph_path (cairo_gstate_t *gstate, for (i = 0; i < num_glyphs; ++i) { - transformed_glyphs[i] = glyphs[i]; + transformed_glyphs[i].index = glyphs[i].index; + transformed_glyphs[i].x = glyphs[i].x + gstate->font_matrix.x0; + transformed_glyphs[i].y = glyphs[i].y + gstate->font_matrix.y0; _cairo_gstate_user_to_backend (gstate, &(transformed_glyphs[i].x), &(transformed_glyphs[i].y)); @@ -1505,21 +1564,3 @@ _cairo_gstate_get_antialias (cairo_gstate_t *gstate) { return gstate->antialias; } - -cairo_bool_t -_cairo_gstate_has_clip (cairo_gstate_t *gstate) -{ - return _cairo_clip_has_clip (&gstate->clip); -} - -cairo_bool_t -_cairo_gstate_extract_clip_rectangles (cairo_gstate_t *gstate, - int max_rectangles, - cairo_clip_rect_t *rectangles_out, - int *num_rectangles_out) -{ - return _cairo_clip_extract_rectangles (&gstate->clip, - max_rectangles, - rectangles_out, - num_rectangles_out); -} diff --git a/gfx/cairo/cairo/src/cairo-hash.c b/gfx/cairo/cairo/src/cairo-hash.c index a9909a264ade..948cd232f898 100644 --- a/gfx/cairo/cairo/src/cairo-hash.c +++ b/gfx/cairo/cairo/src/cairo-hash.c @@ -115,7 +115,7 @@ static const cairo_hash_table_arrangement_t hash_table_arrangements [] = { { 268435456, 590559793, 590559791 } }; -#define NUM_HASH_TABLE_ARRANGEMENTS (sizeof(hash_table_arrangements)/sizeof(hash_table_arrangements[0])) +#define NUM_HASH_TABLE_ARRANGEMENTS ((int)(sizeof(hash_table_arrangements)/sizeof(hash_table_arrangements[0]))) struct _cairo_hash_table { cairo_hash_keys_equal_func_t keys_equal; diff --git a/gfx/cairo/cairo/src/cairo-image-surface.c b/gfx/cairo/cairo/src/cairo-image-surface.c index 4a8f52b19fab..62040d85fbf1 100644 --- a/gfx/cairo/cairo/src/cairo-image-surface.c +++ b/gfx/cairo/cairo/src/cairo-image-surface.c @@ -44,8 +44,6 @@ _cairo_format_bpp (cairo_format_t format) return 1; case CAIRO_FORMAT_A8: return 8; - case CAIRO_FORMAT_RGB16_565: - return 16; case CAIRO_FORMAT_RGB24: case CAIRO_FORMAT_ARGB32: return 32; @@ -90,22 +88,33 @@ _cairo_image_surface_create_for_pixman_image (pixman_image_t *pixman_image, static cairo_format_t _cairo_format_from_pixman_format (pixman_format_t *pixman_format) { - int bpp, am, rm, gm, bm; + unsigned int bpp, am, rm, gm, bm; pixman_format_get_masks (pixman_format, &bpp, &am, &rm, &gm, &bm); + /* See definition of cairo_internal_format_t for an explanation of + * the CAIRO_INTERNAL_FORMAT values used here. */ switch (bpp) { case 32: - if (am == 0xff000000 && - rm == 0x00ff0000 && - gm == 0x0000ff00 && - bm == 0x000000ff) - return CAIRO_FORMAT_ARGB32; - if (am == 0x0 && - rm == 0x00ff0000 && - gm == 0x0000ff00 && - bm == 0x000000ff) - return CAIRO_FORMAT_RGB24; + if (am == 0xff000000) { + if (rm == 0x00ff0000 && + gm == 0x0000ff00 && + bm == 0x000000ff) + return CAIRO_FORMAT_ARGB32; + if (rm == 0x000000ff && + gm == 0x0000ff00 && + bm == 0x00ff0000) + return CAIRO_INTERNAL_FORMAT_ABGR32; + } else if (am == 0x0) { + if (rm == 0x00ff0000 && + gm == 0x0000ff00 && + bm == 0x000000ff) + return CAIRO_FORMAT_RGB24; + if (rm == 0x000000ff && + gm == 0x0000ff00 && + bm == 0x00ff0000) + return CAIRO_INTERNAL_FORMAT_BGR24; + } break; case 16: if (am == 0x0 && @@ -131,13 +140,13 @@ _cairo_format_from_pixman_format (pixman_format_t *pixman_format) } fprintf (stderr, - "Error: Cairo does not yet support the requested image format:\n" + "Error: Cairo " PACKAGE_VERSION " does not yet support the requested image format:\n" "\tDepth: %d\n" "\tAlpha mask: 0x%08x\n" "\tRed mask: 0x%08x\n" "\tGreen mask: 0x%08x\n" "\tBlue mask: 0x%08x\n" - "Please file an enhacement request (quoting the above) at:\n" + "Please file an enhancement request (quoting the above) at:\n" PACKAGE_BUGREPORT "\n", bpp, am, rm, gm, bm); @@ -145,6 +154,10 @@ _cairo_format_from_pixman_format (pixman_format_t *pixman_format) return (cairo_format_t) -1; } +/* XXX: This function really should be eliminated. We don't really + * want to advertise a cairo image surface that supports any possible + * format. A minimal step would be to replace this function with one + * that accepts a cairo_internal_format_t rather than mask values. */ cairo_surface_t * _cairo_image_surface_create_with_masks (unsigned char *data, cairo_format_masks_t *format, @@ -196,9 +209,6 @@ _create_pixman_format (cairo_format_t format) case CAIRO_FORMAT_A8: return pixman_format_create (PIXMAN_FORMAT_NAME_A8); break; - case CAIRO_FORMAT_RGB16_565: - return pixman_format_create (PIXMAN_FORMAT_NAME_RGB16_565); - break; case CAIRO_FORMAT_RGB24: return pixman_format_create (PIXMAN_FORMAT_NAME_RGB24); break; @@ -260,6 +270,7 @@ cairo_image_surface_create (cairo_format_t format, return surface; } +slim_hidden_def (cairo_image_surface_create); cairo_surface_t * _cairo_image_surface_create_with_content (cairo_content_t content, @@ -339,6 +350,7 @@ cairo_image_surface_create_for_data (unsigned char *data, return surface; } +slim_hidden_def (cairo_image_surface_create_for_data); cairo_surface_t * _cairo_image_surface_create_for_data_with_content (unsigned char *data, @@ -400,6 +412,8 @@ cairo_image_surface_get_format (cairo_surface_t *surface) return 0; } + assert (CAIRO_FORMAT_VALID (image_surface->format)); + return image_surface->format; } @@ -423,6 +437,7 @@ cairo_image_surface_get_width (cairo_surface_t *surface) return image_surface->width; } +slim_hidden_def (cairo_image_surface_get_width); /** * cairo_image_surface_get_height: @@ -444,6 +459,7 @@ cairo_image_surface_get_height (cairo_surface_t *surface) return image_surface->height; } +slim_hidden_def (cairo_image_surface_get_height); /** * cairo_image_surface_get_stride: @@ -491,11 +507,20 @@ _cairo_format_from_content (cairo_content_t content) cairo_content_t _cairo_content_from_format (cairo_format_t format) { - switch (format) { + /* XXX: Use an int to avoid the warnings from mixed cairo_format_t + * and cairo_internal_format_t values. The warnings are extremely + * valuable since mixing enums can lead to subtle bugs. It's just + * that cairo_internal_format_t is an interim approach to getting + * bug #7294 fixed so we can release cairo 1.2.2 . */ + int f = format; + + switch (f) { case CAIRO_FORMAT_ARGB32: + case CAIRO_INTERNAL_FORMAT_ABGR32: return CAIRO_CONTENT_COLOR_ALPHA; case CAIRO_FORMAT_RGB24: case CAIRO_FORMAT_RGB16_565: + case CAIRO_INTERNAL_FORMAT_BGR24: return CAIRO_CONTENT_COLOR; case CAIRO_FORMAT_A8: case CAIRO_FORMAT_A1: @@ -639,6 +664,12 @@ _cairo_image_surface_set_filter (cairo_image_surface_t *surface, cairo_filter_t case CAIRO_FILTER_BILINEAR: pixman_filter = PIXMAN_FILTER_BILINEAR; break; + case CAIRO_FILTER_GAUSSIAN: + /* XXX: The GAUSSIAN value has no implementation in cairo + * whatsoever, so it was really a mistake to have it in the + * API. We could fix this by officially deprecating it, or + * else inventing semantics and providing an actual + * implementation for it. */ default: pixman_filter = PIXMAN_FILTER_BEST; } @@ -895,6 +926,9 @@ _cairo_image_surface_composite_trapezoids (cairo_operator_t op, mask_stride = (width + 31)/8; mask_bpp = 1; break; + case CAIRO_ANTIALIAS_GRAY: + case CAIRO_ANTIALIAS_SUBPIXEL: + case CAIRO_ANTIALIAS_DEFAULT: default: format = pixman_format_create (PIXMAN_FORMAT_NAME_A8); mask_stride = (width + 3) & ~3; @@ -1015,3 +1049,29 @@ const cairo_surface_backend_t cairo_image_surface_backend = { _cairo_image_surface_get_extents, NULL /* old_show_glyphs */ }; + +/* A convenience function for when one needs to coerce an image + * surface to an alternate format. */ +cairo_image_surface_t * +_cairo_image_surface_clone (cairo_image_surface_t *surface, + cairo_format_t format) +{ + cairo_image_surface_t *clone; + cairo_t *cr; + double x, y; + + clone = (cairo_image_surface_t *) + cairo_image_surface_create (format, + surface->width, surface->height); + + cr = cairo_create (&clone->base); + cairo_surface_get_device_offset (&surface->base, &x, &y); + cairo_set_source_surface (cr, &surface->base, x, y); + cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE); + cairo_paint (cr); + cairo_destroy (cr); + + cairo_surface_set_device_offset (&clone->base, x, y); + + return clone; +} diff --git a/gfx/cairo/cairo/src/cairo-lzw.c b/gfx/cairo/cairo/src/cairo-lzw.c index d8776db72eaf..ac9ef41bd6b5 100644 --- a/gfx/cairo/cairo/src/cairo-lzw.c +++ b/gfx/cairo/cairo/src/cairo-lzw.c @@ -43,7 +43,7 @@ typedef struct _lzw_buf { int data_size; int num_data; uint32_t pending; - int pending_bits; + unsigned int pending_bits; } lzw_buf_t; /* An lzw_buf_t is a simple, growable chunk of memory for holding @@ -67,6 +67,10 @@ _lzw_buf_init (lzw_buf_t *buf, int size) size = 16; buf->status = CAIRO_STATUS_SUCCESS; + buf->data_size = size; + buf->num_data = 0; + buf->pending = 0; + buf->pending_bits = 0; buf->data = malloc (size); if (buf->data == NULL) { @@ -74,11 +78,6 @@ _lzw_buf_init (lzw_buf_t *buf, int size) buf->status = CAIRO_STATUS_NO_MEMORY; return; } - - buf->data_size = size; - buf->num_data = 0; - buf->pending = 0; - buf->pending_bits = 0; } /* Increase the buffer size by doubling. diff --git a/gfx/cairo/cairo/src/cairo-matrix.c b/gfx/cairo/cairo/src/cairo-matrix.c index e418ef38e8be..339079f7511e 100644 --- a/gfx/cairo/cairo/src/cairo-matrix.c +++ b/gfx/cairo/cairo/src/cairo-matrix.c @@ -170,6 +170,7 @@ cairo_matrix_translate (cairo_matrix_t *matrix, double tx, double ty) cairo_matrix_multiply (matrix, &tmp, matrix); } +slim_hidden_def (cairo_matrix_translate); /** * cairo_matrix_init_scale: @@ -357,7 +358,8 @@ slim_hidden_def(cairo_matrix_transform_point); void _cairo_matrix_transform_bounding_box (const cairo_matrix_t *matrix, double *x, double *y, - double *width, double *height) + double *width, double *height, + cairo_bool_t *is_tight) { int i; double quad_x[4], quad_y[4]; @@ -404,6 +406,21 @@ _cairo_matrix_transform_bounding_box (const cairo_matrix_t *matrix, *y = min_y; *width = max_x - min_x; *height = max_y - min_y; + + if (is_tight) { + /* it's tight if and only if the four corner points form an axis-aligned + rectangle. + And that's true if and only if we can derive corners 0 and 3 from + corners 1 and 2 in one of two straightforward ways... + We could use a tolerance here but for now we'll fall back to FALSE in the case + of floating point error. + */ + *is_tight = + (quad_x[1] == quad_x[0] && quad_y[1] == quad_y[3] && + quad_x[2] == quad_x[3] && quad_y[2] == quad_y[0]) || + (quad_x[1] == quad_x[3] && quad_y[1] == quad_y[0] && + quad_x[2] == quad_x[0] && quad_y[2] == quad_y[3]); + } } static void diff --git a/gfx/cairo/cairo/src/cairo-meta-surface-private.h b/gfx/cairo/cairo/src/cairo-meta-surface-private.h index 24b1b47061ff..3f2d390ce1cc 100644 --- a/gfx/cairo/cairo/src/cairo-meta-surface-private.h +++ b/gfx/cairo/cairo/src/cairo-meta-surface-private.h @@ -97,7 +97,7 @@ typedef struct _cairo_command_show_glyphs { cairo_operator_t op; cairo_pattern_union_t source; cairo_glyph_t *glyphs; - int num_glyphs; + unsigned int num_glyphs; cairo_scaled_font_t *scaled_font; } cairo_command_show_glyphs_t; diff --git a/gfx/cairo/cairo/src/cairo-meta-surface.c b/gfx/cairo/cairo/src/cairo-meta-surface.c index 3fe6bc2dfd10..d6beaf007023 100644 --- a/gfx/cairo/cairo/src/cairo-meta-surface.c +++ b/gfx/cairo/cairo/src/cairo-meta-surface.c @@ -615,6 +615,26 @@ static const cairo_surface_backend_t cairo_meta_surface_backend = { _cairo_meta_surface_snapshot }; +static cairo_path_fixed_t * +_cairo_command_get_path (cairo_command_t *command) +{ + switch (command->type) { + case CAIRO_COMMAND_PAINT: + case CAIRO_COMMAND_MASK: + case CAIRO_COMMAND_SHOW_GLYPHS: + return NULL; + case CAIRO_COMMAND_STROKE: + return &command->stroke.path; + case CAIRO_COMMAND_FILL: + return &command->fill.path; + case CAIRO_COMMAND_INTERSECT_CLIP_PATH: + return command->intersect_clip_path.path_pointer; + } + + ASSERT_NOT_REACHED; + return NULL; +} + cairo_status_t _cairo_meta_surface_replay (cairo_surface_t *surface, cairo_surface_t *target) @@ -624,6 +644,9 @@ _cairo_meta_surface_replay (cairo_surface_t *surface, int i, num_elements; cairo_int_status_t status; cairo_clip_t clip; + cairo_bool_t has_device_transform = _cairo_surface_has_device_transform (target); + cairo_matrix_t *device_transform = &target->device_transform; + cairo_path_fixed_t path_copy, *dev_path; meta = (cairo_meta_surface_t *) surface; status = CAIRO_STATUS_SUCCESS; @@ -634,89 +657,118 @@ _cairo_meta_surface_replay (cairo_surface_t *surface, elements = _cairo_array_index (&meta->commands, 0); for (i = meta->replay_start_idx; i < num_elements; i++) { command = elements[i]; - switch (command->type) { - case CAIRO_COMMAND_PAINT: + + /* For all commands except intersect_clip_path, we have to + * ensure the current clip gets set on the surface. */ + if (command->type != CAIRO_COMMAND_INTERSECT_CLIP_PATH) { status = _cairo_surface_set_clip (target, &clip); if (status) break; + } + dev_path = _cairo_command_get_path (command); + if (dev_path && has_device_transform) { + _cairo_path_fixed_init_copy (&path_copy, dev_path); + _cairo_path_fixed_device_transform (&path_copy, device_transform); + dev_path = &path_copy; + } + + switch (command->type) { + case CAIRO_COMMAND_PAINT: status = _cairo_surface_paint (target, command->paint.op, &command->paint.source.base); break; - case CAIRO_COMMAND_MASK: - status = _cairo_surface_set_clip (target, &clip); - if (status) - break; - status = _cairo_surface_mask (target, command->mask.op, &command->mask.source.base, &command->mask.mask.base); break; - case CAIRO_COMMAND_STROKE: - status = _cairo_surface_set_clip (target, &clip); - if (status) - break; + { + cairo_matrix_t dev_ctm = command->stroke.ctm; + cairo_matrix_t dev_ctm_inverse = command->stroke.ctm_inverse; + cairo_matrix_t tmp; + + if (has_device_transform) { + cairo_matrix_multiply (&dev_ctm, &dev_ctm, device_transform); + tmp = surface->device_transform; + status = cairo_matrix_invert (&tmp); + assert (status == CAIRO_STATUS_SUCCESS); + cairo_matrix_multiply (&dev_ctm_inverse, &tmp, &dev_ctm_inverse); + } status = _cairo_surface_stroke (target, command->stroke.op, &command->stroke.source.base, - &command->stroke.path, + dev_path, &command->stroke.style, - &command->stroke.ctm, - &command->stroke.ctm_inverse, + &dev_ctm, + &dev_ctm_inverse, command->stroke.tolerance, command->stroke.antialias); break; - + } case CAIRO_COMMAND_FILL: - status = _cairo_surface_set_clip (target, &clip); - if (status) - break; - status = _cairo_surface_fill (target, command->fill.op, &command->fill.source.base, - &command->fill.path, + dev_path, command->fill.fill_rule, command->fill.tolerance, command->fill.antialias); break; - case CAIRO_COMMAND_SHOW_GLYPHS: - status = _cairo_surface_set_clip (target, &clip); - if (status) - break; + { + cairo_glyph_t *glyphs = command->show_glyphs.glyphs; + cairo_glyph_t *dev_glyphs = glyphs; + int i, num_glyphs = command->show_glyphs.num_glyphs; + + if (has_device_transform) { + dev_glyphs = malloc (sizeof (cairo_glyph_t) * num_glyphs); + if (dev_glyphs == NULL) { + status = CAIRO_STATUS_NO_MEMORY; + break; + } + for (i = 0; i < num_glyphs; i++) { + dev_glyphs[i] = glyphs[i]; + cairo_matrix_transform_point (device_transform, + &dev_glyphs[i].x, + &dev_glyphs[i].y); + } + } status = _cairo_surface_show_glyphs (target, command->show_glyphs.op, &command->show_glyphs.source.base, - command->show_glyphs.glyphs, - command->show_glyphs.num_glyphs, + dev_glyphs, num_glyphs, command->show_glyphs.scaled_font); - break; + if (dev_glyphs != glyphs) + free (dev_glyphs); + + break; + } case CAIRO_COMMAND_INTERSECT_CLIP_PATH: /* XXX Meta surface clipping is broken and requires some * cairo-gstate.c rewriting. Work around it for now. */ - if (command->intersect_clip_path.path_pointer == NULL) + if (dev_path == NULL) status = _cairo_clip_reset (&clip); else - status = _cairo_clip_clip (&clip, - command->intersect_clip_path.path_pointer, + status = _cairo_clip_clip (&clip, dev_path, command->intersect_clip_path.fill_rule, command->intersect_clip_path.tolerance, command->intersect_clip_path.antialias, target); break; - default: ASSERT_NOT_REACHED; } + if (dev_path == &path_copy) + _cairo_path_fixed_fini (&path_copy); + if (status) break; } diff --git a/gfx/cairo/cairo/src/cairo-nquartz-surface.c b/gfx/cairo/cairo/src/cairo-nquartz-surface.c index e052fe29be7c..9f87f8c6fcd0 100644 --- a/gfx/cairo/cairo/src/cairo-nquartz-surface.c +++ b/gfx/cairo/cairo/src/cairo-nquartz-surface.c @@ -31,7 +31,7 @@ * The Initial Developer of the Original Code is Mozilla Corporation. * * Contributor(s): - * Vladimir Vukicevic + * Vladimir Vukicevic */ #include @@ -50,28 +50,28 @@ #undef NQUARTZ_DEBUG #ifdef NQUARTZ_DEBUG -#define ND(_x) fprintf _x +#define ND(_x) fprintf _x #else -#define ND(_x) do {} while(0) +#define ND(_x) do {} while(0) #endif /* This method is private, but it exists. Its params are are exposed * as args to the NS* method, but not as CG. */ enum PrivateCGCompositeMode { - kPrivateCGCompositeClear = 0, - kPrivateCGCompositeCopy = 1, - kPrivateCGCompositeSourceOver = 2, - kPrivateCGCompositeSourceIn = 3, - kPrivateCGCompositeSourceOut = 4, - kPrivateCGCompositeSourceAtop = 5, - kPrivateCGCompositeDestinationOver = 6, - kPrivateCGCompositeDestinationIn = 7, - kPrivateCGCompositeDestinationOut = 8, - kPrivateCGCompositeDestinationAtop = 9, - kPrivateCGCompositeXOR = 10, - kPrivateCGCompositePlusDarker = 11, // (max (0, (1-d) + (1-s))) - kPrivateCGCompositePlusLighter = 12, // (min (1, s + d)) + kPrivateCGCompositeClear = 0, + kPrivateCGCompositeCopy = 1, + kPrivateCGCompositeSourceOver = 2, + kPrivateCGCompositeSourceIn = 3, + kPrivateCGCompositeSourceOut = 4, + kPrivateCGCompositeSourceAtop = 5, + kPrivateCGCompositeDestinationOver = 6, + kPrivateCGCompositeDestinationIn = 7, + kPrivateCGCompositeDestinationOut = 8, + kPrivateCGCompositeDestinationAtop = 9, + kPrivateCGCompositeXOR = 10, + kPrivateCGCompositePlusDarker = 11, // (max (0, (1-d) + (1-s))) + kPrivateCGCompositePlusLighter = 12, // (min (1, s + d)) }; typedef enum PrivateCGCompositeMode PrivateCGCompositeMode; CG_EXTERN void CGContextSetCompositeOperation (CGContextRef, PrivateCGCompositeMode); @@ -683,8 +683,8 @@ _cairo_nquartz_setup_source (cairo_nquartz_surface_t *surface, // pattern (which may be stack allocated) CGContextSaveGState(surface->cgContext); - CGColorSpaceRef patternSpace = CGColorSpaceCreatePattern(NULL); - CGContextSetFillColorSpace (surface->cgContext, patternSpace); + CGColorSpaceRef patternSpace = CGColorSpaceCreatePattern(NULL); + CGContextSetFillColorSpace (surface->cgContext, patternSpace); CGContextSetFillPattern (surface->cgContext, pattern, &patternAlpha); CGColorSpaceRelease (patternSpace); @@ -732,7 +732,7 @@ static void ImageDataReleaseFunc(void *info, const void *data, size_t size) { if (data != NULL) { - free((void *) data); + free((void *) data); } } @@ -941,7 +941,7 @@ _cairo_nquartz_surface_acquire_dest_image (void *abstract_surface, status = _cairo_nquartz_get_image (surface, image_out, &data); if (status) - return status; + return status; *image_extra = data; @@ -1521,7 +1521,7 @@ _cairo_nquartz_surface_create_internal (CGContextRef cgContext, /* Init the base surface */ surface = malloc(sizeof(cairo_nquartz_surface_t)); if (surface == NULL) { - _cairo_error (CAIRO_STATUS_NO_MEMORY); + _cairo_error (CAIRO_STATUS_NO_MEMORY); return NULL; } @@ -1578,7 +1578,7 @@ cairo_nquartz_surface_create_for_agl_context (AGLContext aglContext, if (!surf) { CGContextRelease (cgc); // create_internal will have set an error - return (cairo_surface_t*) &_cairo_surface_nil; + return (cairo_surface_t*) &_cairo_surface_nil; } return (cairo_surface_t *) surf; @@ -1600,7 +1600,7 @@ cairo_nquartz_surface_create_for_cg_context (CGContextRef cgContext, if (!surf) { CGContextRelease (cgContext); // create_internal will have set an error - return (cairo_surface_t*) &_cairo_surface_nil; + return (cairo_surface_t*) &_cairo_surface_nil; } return (cairo_surface_t *) surf; @@ -1643,17 +1643,17 @@ cairo_nquartz_surface_create (cairo_format_t format, * quantities. */ _cairo_error (CAIRO_STATUS_INVALID_FORMAT); - return (cairo_surface_t*) &_cairo_surface_nil; + return (cairo_surface_t*) &_cairo_surface_nil; } else { _cairo_error (CAIRO_STATUS_INVALID_FORMAT); - return (cairo_surface_t*) &_cairo_surface_nil; + return (cairo_surface_t*) &_cairo_surface_nil; } imageData = malloc (height * stride); if (!imageData) { CGColorSpaceRelease (cgColorspace); _cairo_error (CAIRO_STATUS_NO_MEMORY); - return (cairo_surface_t*) &_cairo_surface_nil; + return (cairo_surface_t*) &_cairo_surface_nil; } cgc = CGBitmapContextCreate (imageData, @@ -1666,7 +1666,7 @@ cairo_nquartz_surface_create (cairo_format_t format, CGColorSpaceRelease (cgColorspace); if (!cgc) { - _cairo_error (CAIRO_STATUS_NO_MEMORY); + _cairo_error (CAIRO_STATUS_NO_MEMORY); return (cairo_surface_t*) &_cairo_surface_nil; } @@ -1675,7 +1675,7 @@ cairo_nquartz_surface_create (cairo_format_t format, if (!surf) { CGContextRelease (cgc); // create_internal will have set an error - return (cairo_surface_t*) &_cairo_surface_nil; + return (cairo_surface_t*) &_cairo_surface_nil; } surf->imageData = imageData; @@ -1714,34 +1714,34 @@ void ExportCGImageToPNGFile(CGImageRef inImageRef, char* dest) // create the data reference result = QTNewDataReferenceFromFullPathCFString(inPath, kQTNativeDefaultPathStyle, - 0, &dataRef, &dataRefType); + 0, &dataRef, &dataRefType); if (NULL != dataRef && noErr == result) { - // get the PNG exporter - result = OpenADefaultComponent(GraphicsExporterComponentType, kQTFileTypePNG, - &grex); + // get the PNG exporter + result = OpenADefaultComponent(GraphicsExporterComponentType, kQTFileTypePNG, + &grex); - if (grex) { - // tell the exporter where to find its source image - result = GraphicsExportSetInputCGImage(grex, inImageRef); + if (grex) { + // tell the exporter where to find its source image + result = GraphicsExportSetInputCGImage(grex, inImageRef); - if (noErr == result) { - // tell the exporter where to save the exporter image - result = GraphicsExportSetOutputDataReference(grex, dataRef, - dataRefType); + if (noErr == result) { + // tell the exporter where to save the exporter image + result = GraphicsExportSetOutputDataReference(grex, dataRef, + dataRefType); - if (noErr == result) { - // write the PNG file - result = GraphicsExportDoExport(grex, &sizeWritten); - } - } + if (noErr == result) { + // write the PNG file + result = GraphicsExportDoExport(grex, &sizeWritten); + } + } - // remember to close the component - CloseComponent(grex); - } + // remember to close the component + CloseComponent(grex); + } - // remember to dispose of the data reference handle - DisposeHandle(dataRef); + // remember to dispose of the data reference handle + DisposeHandle(dataRef); } } #endif diff --git a/gfx/cairo/cairo/src/cairo-nquartz.h b/gfx/cairo/cairo/src/cairo-nquartz.h index c8f981bf95c1..c6c58e751078 100644 --- a/gfx/cairo/cairo/src/cairo-nquartz.h +++ b/gfx/cairo/cairo/src/cairo-nquartz.h @@ -46,29 +46,29 @@ CAIRO_BEGIN_DECLS -cairo_surface_t * +cairo_public cairo_surface_t * cairo_nquartz_surface_create (cairo_format_t format, unsigned int width, unsigned int height); #ifdef CAIRO_NQUARTZ_SUPPORT_AGL -cairo_surface_t * +cairo_public cairo_surface_t * cairo_nquartz_surface_create_for_agl_context (AGLContext aglContext, unsigned int width, unsigned int height, cairo_bool_t y_grows_down); #endif -cairo_surface_t * +cairo_public cairo_surface_t * cairo_nquartz_surface_create_for_cg_context (CGContextRef cgContext, unsigned int width, unsigned int height, cairo_bool_t y_grows_down); -cairo_bool_t +cairo_public cairo_bool_t cairo_surface_is_nquartz (cairo_surface_t *surf); -CGContextRef +cairo_public CGContextRef cairo_nquartz_surface_get_cg_context (cairo_surface_t *surf); CAIRO_END_DECLS diff --git a/gfx/cairo/cairo/src/cairo-font-subset-private.h b/gfx/cairo/cairo/src/cairo-os2-private.h similarity index 52% rename from gfx/cairo/cairo/src/cairo-font-subset-private.h rename to gfx/cairo/cairo/src/cairo-os2-private.h index 4b9235bdbdeb..9ed0c7cdd5dc 100644 --- a/gfx/cairo/cairo/src/cairo-font-subset-private.h +++ b/gfx/cairo/cairo/src/cairo-os2-private.h @@ -1,6 +1,7 @@ +/* vim: set sw=4 sts=4 et cin: */ /* cairo - a vector graphics library with display and print output * - * Copyright © 2004 Red Hat, Inc + * Copyright (c) 2005-2006 netlabs.org * * This library is free software; you can redistribute it and/or * modify it either under the terms of the GNU Lesser General Public @@ -27,41 +28,50 @@ * * The Original Code is the cairo graphics library. * - * The Initial Developer of the Original Code is Red Hat, Inc. + * The Initial Developer of the Original Code is + * Doodle * * Contributor(s): - * Kristian Høgsberg + * Peter Weilbacher */ -#include "cairoint.h" +#ifndef CAIRO_OS2_PRIVATE_H +#define CAIRO_OS2_PRIVATE_H -#ifndef CAIRO_FONT_SUBSET_PRIVATE_H -#define CAIRO_FONT_SUBSET_PRIVATE_H +#define INCL_DOS +#define INCL_DOSSEMAPHORES +#define INCL_DOSERRORS +#define INCL_WIN +#define INCL_GPI +#ifdef __WATCOMC__ +# include +#else +# include +#endif -typedef struct cairo_font_subset_backend cairo_font_subset_backend_t; -typedef struct cairo_font_subset cairo_font_subset_t; -struct cairo_font_subset { - cairo_font_subset_backend_t *backend; - cairo_unscaled_font_t *unscaled_font; - unsigned int font_id; - char *base_font; - int num_glyphs; - int *widths; - long x_min, y_min, x_max, y_max; - long ascent, descent; -}; +#include +#include -cairo_private int -_cairo_font_subset_use_glyph (cairo_font_subset_t *font, int glyph); +typedef struct _cairo_os2_surface +{ + cairo_surface_t base; -cairo_private cairo_status_t -_cairo_font_subset_generate (cairo_font_subset_t *font, - const char **data, unsigned long *length); + /* Mutex semaphore to protect private fields from concurrent access */ + HMTX hmtx_use_private_fields; + /* Private fields: */ + HPS hps_client_window; + HWND hwnd_client_window; + BITMAPINFO2 bitmap_info; + unsigned char *pixels; + cairo_image_surface_t *image_surface; + int pixel_array_lend_count; + HEV hev_pixel_array_came_back; -cairo_private void -_cairo_font_subset_destroy (cairo_font_subset_t *font); + RECTL rcl_dirty_area; + cairo_bool_t dirty_area_present; -cairo_private cairo_font_subset_t * -_cairo_font_subset_create (cairo_unscaled_font_t *unscaled_font); + /* General flags: */ + cairo_bool_t blit_as_changes; +} cairo_os2_surface_t; -#endif /* CAIRO_FONT_SUBSET_PRIVATE_H */ +#endif /* CAIRO_OS2_PRIVATE_H */ diff --git a/gfx/cairo/cairo/src/cairo-os2-surface.c b/gfx/cairo/cairo/src/cairo-os2-surface.c new file mode 100644 index 000000000000..59718bb38360 --- /dev/null +++ b/gfx/cairo/cairo/src/cairo-os2-surface.c @@ -0,0 +1,1135 @@ +/* vim: set sw=4 sts=4 et cin: */ +/* cairo - a vector graphics library with display and print output + * + * Copyright (c) 2005-2006 netlabs.org + * + * This library is free software; you can redistribute it and/or + * modify it either under the terms of the GNU Lesser General Public + * License version 2.1 as published by the Free Software Foundation + * (the "LGPL") or, at your option, under the terms of the Mozilla + * Public License Version 1.1 (the "MPL"). If you do not alter this + * notice, a recipient may use your version of this file under either + * the MPL or the LGPL. + * + * You should have received a copy of the LGPL along with this library + * in the file COPYING-LGPL-2.1; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * You should have received a copy of the MPL along with this library + * in the file COPYING-MPL-1.1 + * + * The contents of this file are subject to the Mozilla Public License + * Version 1.1 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY + * OF ANY KIND, either express or implied. See the LGPL or the MPL for + * the specific language governing rights and limitations. + * + * The Original Code is the cairo graphics library. + * + * The Initial Developer of the Original Code is + * Doodle + * + * Contributor(s): + * Peter Weilbacher + */ + +#include +#include +#include +#ifdef BUILD_CAIRO_DLL +# define INCL_WIN +# define INCL_GPI +# define INCL_DOS +# define INCL_DOSERRORS +# include +# include "cairo-os2.h" +# ifndef __WATCOMC__ +# include +# endif +#endif +#include "cairoint.h" +#include "cairo-os2-private.h" +#include "fontconfig/fontconfig.h" + +/* + * Here comes the extra API for the OS/2 platform. Currently it consists + * of two extra functions, the cairo_os2_init () and the + * cairo_os2_fini (). Both of them are called automatically if + * Cairo is compiled to be a DLL file, but you have to call them before + * using the Cairo API if you link to Cairo statically! + * + * You'll also find the code in here which deals with DLL initialization + * and termination, if the code is built to be a DLL. + * (if BUILD_CAIRO_DLL is defined) + */ + +/* Initialization counter: */ +static int cairo_os2_initialization_count = 0; + +/* The mutex semaphores Cairo uses all around: */ +HMTX cairo_toy_font_face_hash_table_mutex = 0; +HMTX cairo_scaled_font_map_mutex = 0; +HMTX _global_image_glyph_cache_mutex = 0; +#ifdef CAIRO_HAS_FT_FONT +HMTX cairo_ft_unscaled_font_map_mutex = 0; +#endif + +static void inline +DisableFPUException (void) +{ + unsigned short usCW; + + /* Some OS/2 PM API calls modify the FPU Control Word, + * but forget to restore it. + * + * This can result in XCPT_FLOAT_INVALID_OPCODE exceptions, + * so to be sure, we disable Invalid Opcode FPU exception + * before using FPU stuffs. + */ + usCW = _control87 (0, 0); + usCW = usCW | EM_INVALID | 0x80; + _control87 (usCW, MCW_EM | 0x80); +} + +cairo_public void +cairo_os2_init (void) +{ + /* This may initialize some stuffs, like create mutex semaphores etc.. */ + + cairo_os2_initialization_count++; + if (cairo_os2_initialization_count > 1) return; + + DisableFPUException (); + + /* Create the mutex semaphores we'll use! */ + + /* cairo-font.c: */ + DosCreateMutexSem (NULL, &cairo_toy_font_face_hash_table_mutex, 0, FALSE); + DosCreateMutexSem (NULL, &cairo_scaled_font_map_mutex, 0, FALSE); + DosCreateMutexSem (NULL, &_global_image_glyph_cache_mutex, 0, FALSE); + +#ifdef CAIRO_HAS_FT_FONT + /* cairo-ft-font.c: */ + DosCreateMutexSem (NULL, &cairo_ft_unscaled_font_map_mutex, 0, FALSE); +#endif + + /* Initialize FontConfig */ + FcInit (); +} + +cairo_public void +cairo_os2_fini (void) +{ + /* This has to uninitialize some stuffs, like destroy mutex semaphores etc.. */ + + if (cairo_os2_initialization_count <= 0) return; + cairo_os2_initialization_count--; + if (cairo_os2_initialization_count > 0) return; + + DisableFPUException (); + + /* Free allocated memories! */ + /* (Check cairo_debug_reset_static_date () for an example of this!) */ + _cairo_font_reset_static_data (); +#ifdef CAIRO_HAS_FT_FONT + _cairo_ft_font_reset_static_data (); +#endif + + /* Destroy the mutex semaphores we've created! */ + /* cairo-font.c: */ + if (cairo_toy_font_face_hash_table_mutex) { + DosCloseMutexSem (cairo_toy_font_face_hash_table_mutex); + cairo_toy_font_face_hash_table_mutex = 0; + } + if (cairo_scaled_font_map_mutex) { + DosCloseMutexSem (cairo_scaled_font_map_mutex); + cairo_scaled_font_map_mutex = 0; + } + if (_global_image_glyph_cache_mutex) { + DosCloseMutexSem (_global_image_glyph_cache_mutex); + _global_image_glyph_cache_mutex = 0; + } + +#ifdef CAIRO_HAS_FT_FONT + /* cairo-ft-font.c: */ + if (cairo_ft_unscaled_font_map_mutex) { + DosCloseMutexSem (cairo_ft_unscaled_font_map_mutex); + cairo_ft_unscaled_font_map_mutex = 0; + } +#endif + + /* Uninitialize FontConfig */ + FcFini (); + +#ifdef __WATCOMC__ + /* It can happen that the libraries we use have memory leaks, + * so there are still memory chunks allocated at this point. + * In these cases, Watcom might still have a bigger memory chunk, + * called "the heap" allocated from the OS. + * As we want to minimize the memory we lose from the point of + * view of the OS, we call this function to shrink that heap + * as much as possible. + */ + _heapshrink (); +#endif +} + +#ifdef BUILD_CAIRO_DLL +/* The main DLL entry for DLL initialization and uninitialization */ +/* Only include this code if we're about to build a DLL. */ + +#ifdef __WATCOMC__ +unsigned _System +LibMain (unsigned hmod, + unsigned termination) +#else +unsigned long _System +_DLL_InitTerm (unsigned long hModule, + unsigned long termination) +#endif +{ + if (termination) { + /* Unloading the DLL */ + cairo_os2_fini (); + +#ifndef __WATCOMC__ + /* Uninitialize RTL of GCC */ + __ctordtorTerm (); + _CRT_term (); +#endif + return 1; + } else { + /* Loading the DLL */ +#ifndef __WATCOMC__ + /* Initialize RTL of GCC */ + if (_CRT_init () != 0) + return 0; + __ctordtorInit (); +#endif + + cairo_os2_init (); + return 1; + } +} + +#endif /* BUILD_CAIRO_DLL */ + +/* + * The following part of the source file contains the code which might + * be called the "core" of the OS/2 backend support. This contains the + * OS/2 surface support functions and structures. + */ + +/* Forward declaration */ +static const cairo_surface_backend_t cairo_os2_surface_backend; + +/* Unpublished API: + * GpiEnableYInversion = PMGPI.723 + * GpiQueryYInversion = PMGPI.726 + * BOOL APIENTRY GpiEnableYInversion (HPS hps, LONG lHeight); + * LONG APIENTRY GpiQueryYInversion (HPS hps); + */ +BOOL APIENTRY GpiEnableYInversion (HPS hps, LONG lHeight); +LONG APIENTRY GpiQueryYInversion (HPS hps); + +#ifdef __WATCOMC__ +/* Function declaration for GpiDrawBits () (missing from OpenWatcom headers) */ +LONG APIENTRY GpiDrawBits (HPS hps, + PVOID pBits, + PBITMAPINFO2 pbmiInfoTable, + LONG lCount, + PPOINTL aptlPoints, + LONG lRop, + ULONG flOptions); +#endif + +static void +_cairo_os2_surface_blit_pixels (cairo_os2_surface_t *surface, + HPS hps_begin_paint, + PRECTL prcl_begin_paint_rect) +{ + POINTL aptlPoints[4]; + LONG lOldYInversion; + + /* Enable Y Inversion for the HPS, so the + * GpiDrawBits will work with upside-top image, not with upside-down image! + */ + lOldYInversion = GpiQueryYInversion (hps_begin_paint); + GpiEnableYInversion (hps_begin_paint, surface->bitmap_info.cy-1); + + /* Target coordinates (Noninclusive) */ + aptlPoints[0].x = prcl_begin_paint_rect->xLeft; + aptlPoints[0].y = prcl_begin_paint_rect->yBottom; + + aptlPoints[1].x = prcl_begin_paint_rect->xRight-1; + aptlPoints[1].y = prcl_begin_paint_rect->yTop-1; + + /* Source coordinates (Inclusive) */ + aptlPoints[2].x = prcl_begin_paint_rect->xLeft; + aptlPoints[2].y = prcl_begin_paint_rect->yBottom; + + aptlPoints[3].x = prcl_begin_paint_rect->xRight; + aptlPoints[3].y = (prcl_begin_paint_rect->yTop); + + /* Some extra checking for limits + * (Dunno if really needed, but had some crashes sometimes without it, + * while developing the code...) + */ + { + int i; + for (i = 0; i < 4; i++) { + if (aptlPoints[i].x < 0) + aptlPoints[i].x = 0; + if (aptlPoints[i].y < 0) + aptlPoints[i].y = 0; + if (aptlPoints[i].x > (LONG) surface->bitmap_info.cx) + aptlPoints[i].x = (LONG) surface->bitmap_info.cx; + if (aptlPoints[i].y > (LONG) surface->bitmap_info.cy) + aptlPoints[i].y = (LONG) surface->bitmap_info.cy; + } + } + + /* Debug code to draw rectangle limits */ +#if 0 + { + int x, y; + unsigned char *pixels; + + pixels = surface->pixels; + for (x = 0; x < surface->bitmap_info.cx; x++) { + for (y = 0; y < surface->bitmap_info.cy; y++) { + if ((x == 0) || + (y == 0) || + (x == y) || + (x >= surface->bitmap_info.cx-1) || + (y >= surface->bitmap_info.cy-1)) + { + pixels[y*surface->bitmap_info.cx*4+x*4] = 255; + } + } + } + } +#endif + GpiDrawBits (hps_begin_paint, + surface->pixels, + &(surface->bitmap_info), + 4, + aptlPoints, + ROP_SRCCOPY, + BBO_IGNORE); + + /* Restore Y inversion */ + GpiEnableYInversion (hps_begin_paint, lOldYInversion); +} + +static void +_cairo_os2_surface_get_pixels_from_screen (cairo_os2_surface_t *surface, + HPS hps_begin_paint, + PRECTL prcl_begin_paint_rect) +{ + HPS hps; + HDC hdc; + HAB hab; + SIZEL sizlTemp; + HBITMAP hbmpTemp; + BITMAPINFO2 bmi2Temp; + POINTL aptlPoints[4]; + int y; + unsigned char *pchTemp; + + /* To copy pixels from screen to our buffer, we do the following steps: + * + * - Blit pixels from screen to a HBITMAP: + * -- Create Memory Device Context + * -- Create a PS into it + * -- Create a HBITMAP + * -- Select HBITMAP into memory PS + * -- Blit dirty pixels from screen to HBITMAP + * - Copy HBITMAP lines (pixels) into our buffer + * - Free resources + * + * These steps will require an Anchor Block (HAB). However, + * WinQUeryAnchorBlock () documentation says that HAB is not + * used in current OS/2 implementations, OS/2 deduces all information + * it needs from the TID. Anyway, we'd be in trouble if we'd have to + * get a HAB where we only know a HPS... + * So, we'll simply use a fake HAB. + */ + + hab = (HAB) 1; /* OS/2 doesn't really use HAB... */ + + /* Create a memory device context */ + hdc = DevOpenDC (hab, OD_MEMORY,"*",0L, NULL, NULLHANDLE); + if (!hdc) { + return; + } + + /* Create a memory PS */ + sizlTemp.cx = prcl_begin_paint_rect->xRight - prcl_begin_paint_rect->xLeft; + sizlTemp.cy = prcl_begin_paint_rect->yTop - prcl_begin_paint_rect->yBottom; + hps = GpiCreatePS (hab, + hdc, + &sizlTemp, + PU_PELS | GPIT_NORMAL | GPIA_ASSOC ); + if (!hps) { + DevCloseDC (hdc); + return; + } + + /* Create an uninitialized bitmap. */ + /* Prepare BITMAPINFO2 structure for our buffer */ + memset (&bmi2Temp, 0, sizeof (bmi2Temp)); + bmi2Temp.cbFix = sizeof (BITMAPINFOHEADER2); + bmi2Temp.cx = sizlTemp.cx; + bmi2Temp.cy = sizlTemp.cy; + bmi2Temp.cPlanes = 1; + bmi2Temp.cBitCount = 32; + + hbmpTemp = GpiCreateBitmap (hps, + (PBITMAPINFOHEADER2) &bmi2Temp, + 0, + NULL, + NULL); + + if (!hbmpTemp) { + GpiDestroyPS (hps); + DevCloseDC (hdc); + return; + } + + /* Select the bitmap into the memory device context. */ + GpiSetBitmap (hps, hbmpTemp); + + /* Target coordinates (Noninclusive) */ + aptlPoints[0].x = 0; + aptlPoints[0].y = 0; + + aptlPoints[1].x = sizlTemp.cx; + aptlPoints[1].y = sizlTemp.cy; + + /* Source coordinates (Inclusive) */ + aptlPoints[2].x = prcl_begin_paint_rect->xLeft; + aptlPoints[2].y = surface->bitmap_info.cy - prcl_begin_paint_rect->yBottom; + + aptlPoints[3].x = prcl_begin_paint_rect->xRight; + aptlPoints[3].y = surface->bitmap_info.cy - prcl_begin_paint_rect->yTop; + + /* Blit pixels from screen to bitmap */ + GpiBitBlt (hps, + hps_begin_paint, + 4, + aptlPoints, + ROP_SRCCOPY, + BBO_IGNORE); + + /* Now we have to extract the pixels from the bitmap. */ + pchTemp = + surface->pixels + + (prcl_begin_paint_rect->yBottom)*surface->bitmap_info.cx*4 + + prcl_begin_paint_rect->xLeft*4; + for (y = 0; y < sizlTemp.cy; y++) { + /* Get one line of pixels */ + GpiQueryBitmapBits (hps, + sizlTemp.cy - y - 1, /* lScanStart */ + 1, /* lScans */ + pchTemp, + &bmi2Temp); + + /* Go for next line */ + pchTemp += surface->bitmap_info.cx*4; + } + + /* Clean up resources */ + GpiSetBitmap (hps, (HBITMAP) NULL); + GpiDeleteBitmap (hbmpTemp); + GpiDestroyPS (hps); + DevCloseDC (hdc); +} + +static cairo_status_t +_cairo_os2_surface_acquire_source_image (void *abstract_surface, + cairo_image_surface_t **image_out, + void **image_extra) +{ + cairo_os2_surface_t *local_os2_surface; + + local_os2_surface = (cairo_os2_surface_t *) abstract_surface; + if ((!local_os2_surface) || + (local_os2_surface->base.backend != &cairo_os2_surface_backend)) + { + /* Invalid parameter (wrong surface)! */ + return CAIRO_STATUS_SURFACE_TYPE_MISMATCH; + } + + DosRequestMutexSem (local_os2_surface->hmtx_use_private_fields, SEM_INDEFINITE_WAIT); + + /* Increase lend counter */ + local_os2_surface->pixel_array_lend_count++; + + *image_out = local_os2_surface->image_surface; + *image_extra = NULL; + + DosReleaseMutexSem (local_os2_surface->hmtx_use_private_fields); + + return CAIRO_STATUS_SUCCESS; +} + +static void +_cairo_os2_surface_release_source_image (void *abstract_surface, + cairo_image_surface_t *image, + void *image_extra) +{ + cairo_os2_surface_t *local_os2_surface; + + local_os2_surface = (cairo_os2_surface_t *) abstract_surface; + if ((!local_os2_surface) || + (local_os2_surface->base.backend != &cairo_os2_surface_backend)) + { + /* Invalid parameter (wrong surface)! */ + return; + } + + /* Decrease Lend counter! */ + DosRequestMutexSem (local_os2_surface->hmtx_use_private_fields, SEM_INDEFINITE_WAIT); + + if (local_os2_surface->pixel_array_lend_count > 0) + local_os2_surface->pixel_array_lend_count--; + DosPostEventSem (local_os2_surface->hev_pixel_array_came_back); + + DosReleaseMutexSem (local_os2_surface->hmtx_use_private_fields); + return; +} + +static cairo_status_t +_cairo_os2_surface_acquire_dest_image (void *abstract_surface, + cairo_rectangle_int16_t *interest_rect, + cairo_image_surface_t **image_out, + cairo_rectangle_int16_t *image_rect, + void **image_extra) +{ + cairo_os2_surface_t *local_os2_surface; + + local_os2_surface = (cairo_os2_surface_t *) abstract_surface; + if ((!local_os2_surface) || + (local_os2_surface->base.backend != &cairo_os2_surface_backend)) + { + /* Invalid parameter (wrong surface)! */ + return CAIRO_STATUS_SURFACE_TYPE_MISMATCH; + } + + DosRequestMutexSem (local_os2_surface->hmtx_use_private_fields, SEM_INDEFINITE_WAIT); + + /* Increase lend counter */ + local_os2_surface->pixel_array_lend_count++; + + *image_out = local_os2_surface->image_surface; + *image_extra = NULL; + + image_rect->x = 0; + image_rect->y = 0; + image_rect->width = local_os2_surface->bitmap_info.cx; + image_rect->height = local_os2_surface->bitmap_info.cy; + + DosReleaseMutexSem (local_os2_surface->hmtx_use_private_fields); + + return CAIRO_STATUS_SUCCESS; +} + +static void +_cairo_os2_surface_release_dest_image (void *abstract_surface, + cairo_rectangle_int16_t *interest_rect, + cairo_image_surface_t *image, + cairo_rectangle_int16_t *image_rect, + void *image_extra) +{ + cairo_os2_surface_t *local_os2_surface; + RECTL rclToBlit; + + local_os2_surface = (cairo_os2_surface_t *) abstract_surface; + if ((!local_os2_surface) || + (local_os2_surface->base.backend != &cairo_os2_surface_backend)) + { + /* Invalid parameter (wrong surface)! */ + return; + } + + /* So, we got back the image, and if all goes well, then + * something has been changed inside the interest_rect. + * So, we blit it to the screen! + */ + + if (local_os2_surface->blit_as_changes) { + /* Get mutex, we'll work with the pixel array! */ + if (DosRequestMutexSem (local_os2_surface->hmtx_use_private_fields, SEM_INDEFINITE_WAIT)!=NO_ERROR) { + /* Could not get mutex! */ + return; + } + + if (local_os2_surface->hwnd_client_window) { + /* We know the HWND, so let's invalidate the window region, + * so the application will redraw itself, using the + * cairo_os2_surface_refresh_window () API from its own PM thread. + * + * This is the safe method, which should be preferred every time. + */ + rclToBlit.xLeft = interest_rect->x; + rclToBlit.xRight = interest_rect->x+interest_rect->width; /* Noninclusive */ + rclToBlit.yTop = local_os2_surface->bitmap_info.cy - (interest_rect->y); + rclToBlit.yBottom = local_os2_surface->bitmap_info.cy - (interest_rect->y+interest_rect->height); /* Noninclusive */ + + WinInvalidateRect (local_os2_surface->hwnd_client_window, + &rclToBlit, + FALSE); + } else { + /* We don't know the HWND, so try to blit the pixels from here! + * Please note that it can be problematic if this is not the PM thread! + * + * It can cause internal PM stuffs to be scewed up, for some reason. + * Please always tell the HWND to the surface using the + * cairo_os2_surface_set_hwnd () API, and call cairo_os2_surface_refresh_window () + * from your WM_PAINT, if it's possible! + */ + rclToBlit.xLeft = interest_rect->x; + rclToBlit.xRight = interest_rect->x+interest_rect->width; /* Noninclusive */ + rclToBlit.yBottom = interest_rect->y; + rclToBlit.yTop = interest_rect->y+interest_rect->height; /* Noninclusive */ + /* Now blit there the stuffs! */ + _cairo_os2_surface_blit_pixels (local_os2_surface, + local_os2_surface->hps_client_window, + &rclToBlit); + } + + DosReleaseMutexSem (local_os2_surface->hmtx_use_private_fields); + } + /* Also decrease Lend counter! */ + DosRequestMutexSem (local_os2_surface->hmtx_use_private_fields, SEM_INDEFINITE_WAIT); + + if (local_os2_surface->pixel_array_lend_count > 0) + local_os2_surface->pixel_array_lend_count--; + DosPostEventSem (local_os2_surface->hev_pixel_array_came_back); + + DosReleaseMutexSem (local_os2_surface->hmtx_use_private_fields); +} + +static cairo_int_status_t +_cairo_os2_surface_get_extents (void *abstract_surface, + cairo_rectangle_int16_t *rectangle) +{ + cairo_os2_surface_t *local_os2_surface; + + local_os2_surface = (cairo_os2_surface_t *) abstract_surface; + if ((!local_os2_surface) || + (local_os2_surface->base.backend != &cairo_os2_surface_backend)) + { + /* Invalid parameter (wrong surface)! */ + return CAIRO_STATUS_SURFACE_TYPE_MISMATCH; + } + + rectangle->x = 0; + rectangle->y = 0; + rectangle->width = local_os2_surface->bitmap_info.cx; + rectangle->height = local_os2_surface->bitmap_info.cy; + + return CAIRO_STATUS_SUCCESS; +} + +cairo_surface_t * +cairo_os2_surface_create (HPS hps_client_window, + int width, + int height) +{ + cairo_os2_surface_t *local_os2_surface; + int rc; + + /* Check the size of the window */ + if ((width <= 0) || + (height <= 0)) + { + /* Invalid window size! */ + _cairo_error (CAIRO_STATUS_NO_MEMORY); + return (cairo_surface_t *) &_cairo_surface_nil; + } + + local_os2_surface = (cairo_os2_surface_t *) malloc (sizeof (cairo_os2_surface_t)); + if (!local_os2_surface) { + /* Not enough memory! */ + _cairo_error (CAIRO_STATUS_NO_MEMORY); + return (cairo_surface_t *) &_cairo_surface_nil; + } + + /* Initialize the OS/2 specific parts of the surface! */ + + /* Create mutex semaphore */ + rc = DosCreateMutexSem (NULL, + &(local_os2_surface->hmtx_use_private_fields), + 0, + FALSE); + if (rc != NO_ERROR) { + /* Could not create mutex semaphore! */ + _cairo_error (CAIRO_STATUS_NO_MEMORY); + return (cairo_surface_t *) &_cairo_surface_nil; + } + + /* Save PS handle */ + local_os2_surface->hps_client_window = hps_client_window; + + /* Defaults */ + local_os2_surface->hwnd_client_window = NULLHANDLE; + local_os2_surface->blit_as_changes = TRUE; + local_os2_surface->pixel_array_lend_count = 0; + rc = DosCreateEventSem (NULL, + &(local_os2_surface->hev_pixel_array_came_back), + 0, + FALSE); + + if (rc != NO_ERROR) { + /* Could not create event semaphore! */ + DosCloseMutexSem (local_os2_surface->hmtx_use_private_fields); + free (local_os2_surface); + _cairo_error (CAIRO_STATUS_NO_MEMORY); + return (cairo_surface_t *) &_cairo_surface_nil; + } + + /* Prepare BITMAPINFO2 structure for our buffer */ + memset (&(local_os2_surface->bitmap_info), 0, sizeof (local_os2_surface->bitmap_info)); + local_os2_surface->bitmap_info.cbFix = sizeof (BITMAPINFOHEADER2); + local_os2_surface->bitmap_info.cx = width; + local_os2_surface->bitmap_info.cy = height; + local_os2_surface->bitmap_info.cPlanes = 1; + local_os2_surface->bitmap_info.cBitCount = 32; + + /* Allocate memory for pixels */ + local_os2_surface->pixels = (unsigned char *) malloc (width * height * 4); + if (!(local_os2_surface->pixels)) { + /* Not enough memory for the pixels! */ + DosCloseEventSem (local_os2_surface->hev_pixel_array_came_back); + DosCloseMutexSem (local_os2_surface->hmtx_use_private_fields); + free (local_os2_surface); + _cairo_error (CAIRO_STATUS_NO_MEMORY); + return (cairo_surface_t *) &_cairo_surface_nil; + } + + /* This is possibly not needed, malloc'd space is + * usually zero'd out! + */ + /* + memset (local_os2_surface->pixels, 0x00, swpTemp.cx * swpTemp.cy * 4); + */ + + /* Create image surface from pixel array */ + local_os2_surface->image_surface = (cairo_image_surface_t *) + cairo_image_surface_create_for_data (local_os2_surface->pixels, + CAIRO_FORMAT_ARGB32, + width, /* Width */ + height, /* Height */ + width * 4); /* Rowstride */ + + if (local_os2_surface->image_surface->base.status) { + /* Could not create image surface! */ + free (local_os2_surface->pixels); + DosCloseEventSem (local_os2_surface->hev_pixel_array_came_back); + DosCloseMutexSem (local_os2_surface->hmtx_use_private_fields); + free (local_os2_surface); + _cairo_error (CAIRO_STATUS_NO_MEMORY); + return (cairo_surface_t *) &_cairo_surface_nil; + } + + /* Initialize base surface */ + _cairo_surface_init (&local_os2_surface->base, + &cairo_os2_surface_backend, + _cairo_content_from_format (CAIRO_FORMAT_ARGB32)); + + return (cairo_surface_t *)local_os2_surface; +} + +int +cairo_os2_surface_set_size (cairo_surface_t *surface, + int new_width, + int new_height, + int timeout) +{ + cairo_os2_surface_t *local_os2_surface; + unsigned char *pchNewPixels; + int rc; + cairo_image_surface_t *pNewImageSurface; + + local_os2_surface = (cairo_os2_surface_t *) surface; + if ((!local_os2_surface) || + (local_os2_surface->base.backend != &cairo_os2_surface_backend)) + { + /* Invalid parameter (wrong surface)! */ + return CAIRO_STATUS_SURFACE_TYPE_MISMATCH; + } + + if ((new_width <= 0) || + (new_height <= 0)) + { + /* Invalid size! */ + return CAIRO_STATUS_NO_MEMORY; + } + + /* Allocate memory for new stuffs */ + pchNewPixels = (unsigned char *) malloc (new_width * new_height * 4); + if (!pchNewPixels) { + /* Not enough memory for the pixels! + * Everything remains the same! + */ + return CAIRO_STATUS_NO_MEMORY; + } + + /* This is possibly not needed, malloc'd space is usually + * already zero'd out! + */ + /* + memset (pchNewPixels, 0x00, new_width * new_height * 4); + */ + + /* Create image surface from new pixel array */ + pNewImageSurface = (cairo_image_surface_t *) + cairo_image_surface_create_for_data (pchNewPixels, + CAIRO_FORMAT_ARGB32, + new_width, /* Width */ + new_height, /* Height */ + new_width * 4); /* Rowstride */ + + if (pNewImageSurface->base.status) { + /* Could not create image surface! + * Everything remains the same! + */ + free (pchNewPixels); + return CAIRO_STATUS_NO_MEMORY; + } + + /* Okay, new memory allocated, so it's time to swap old buffers + * to new ones! + */ + if (DosRequestMutexSem (local_os2_surface->hmtx_use_private_fields, SEM_INDEFINITE_WAIT)!=NO_ERROR) { + /* Could not get mutex! + * Everything remains the same! + */ + cairo_surface_destroy ((cairo_surface_t *) pNewImageSurface); + free (pchNewPixels); + return CAIRO_STATUS_NO_MEMORY; + } + + /* We have to make sure that we won't destroy a surface which + * is lent to some other code (Cairo is drawing into it)! + */ + while (local_os2_surface->pixel_array_lend_count > 0) { + ULONG ulPostCount; + DosResetEventSem (local_os2_surface->hev_pixel_array_came_back, &ulPostCount); + DosReleaseMutexSem (local_os2_surface->hmtx_use_private_fields); + /* Wait for somebody to return the pixels! */ + rc = DosWaitEventSem (local_os2_surface->hev_pixel_array_came_back, timeout); + if (rc != NO_ERROR) { + /* Either timeout or something wrong... Exit. */ + cairo_surface_destroy ((cairo_surface_t *) pNewImageSurface); + free (pchNewPixels); + return CAIRO_STATUS_NO_MEMORY; + } + /* Okay, grab mutex and check counter again! */ + if (DosRequestMutexSem (local_os2_surface->hmtx_use_private_fields, SEM_INDEFINITE_WAIT) + != NO_ERROR) + { + /* Could not get mutex! + * Everything remains the same! + */ + cairo_surface_destroy ((cairo_surface_t *) pNewImageSurface); + free (pchNewPixels); + return CAIRO_STATUS_NO_MEMORY; + } + } + + /* Destroy old image surface */ + cairo_surface_destroy ((cairo_surface_t *) (local_os2_surface->image_surface)); + /* Destroy old pixel buffer */ + free (local_os2_surface->pixels); + /* Set new image surface */ + local_os2_surface->image_surface = pNewImageSurface; + /* Set new pixel buffer */ + local_os2_surface->pixels = pchNewPixels; + /* Change bitmap2 structure */ + local_os2_surface->bitmap_info.cx = new_width; + local_os2_surface->bitmap_info.cy = new_height; + + DosReleaseMutexSem (local_os2_surface->hmtx_use_private_fields); + return CAIRO_STATUS_SUCCESS; +} + +void +cairo_os2_surface_refresh_window (cairo_surface_t *surface, + HPS hps_begin_paint, + PRECTL prcl_begin_paint_rect) +{ + cairo_os2_surface_t *local_os2_surface; + RECTL rclTemp; + + local_os2_surface = (cairo_os2_surface_t *) surface; + if ((!local_os2_surface) || + (local_os2_surface->base.backend != &cairo_os2_surface_backend)) + { + /* Invalid parameter (wrong surface)! */ + return; + } + + /* Manage defaults (NULLs) */ + if (!hps_begin_paint) + hps_begin_paint = local_os2_surface->hps_client_window; + + if (prcl_begin_paint_rect == NULL) { + /* Update the whole window! */ + rclTemp.xLeft = 0; + rclTemp.xRight = local_os2_surface->bitmap_info.cx; + rclTemp.yTop = local_os2_surface->bitmap_info.cy; + rclTemp.yBottom = 0; + } else { + /* Use the rectangle we got passed as parameter! */ + rclTemp.xLeft = prcl_begin_paint_rect->xLeft; + rclTemp.xRight = prcl_begin_paint_rect->xRight; + rclTemp.yTop = local_os2_surface->bitmap_info.cy - prcl_begin_paint_rect->yBottom; + rclTemp.yBottom = local_os2_surface->bitmap_info.cy - prcl_begin_paint_rect->yTop ; + } + + /* Get mutex, we'll work with the pixel array! */ + if (DosRequestMutexSem (local_os2_surface->hmtx_use_private_fields, SEM_INDEFINITE_WAIT) + != NO_ERROR) + { + /* Could not get mutex! */ + return; + } + + if ((local_os2_surface->dirty_area_present) && + (local_os2_surface->rcl_dirty_area.xLeft == rclTemp.xLeft) && + (local_os2_surface->rcl_dirty_area.xRight == rclTemp.xRight) && + (local_os2_surface->rcl_dirty_area.yTop == rclTemp.yTop) && + (local_os2_surface->rcl_dirty_area.yBottom == rclTemp.yBottom)) + { + /* Aha, this call was because of a dirty area, so in this case we + * have to blit the pixels from the screen to the surface! + */ + local_os2_surface->dirty_area_present = FALSE; + _cairo_os2_surface_get_pixels_from_screen (local_os2_surface, + hps_begin_paint, + &rclTemp); + } else { + /* Okay, we have the surface, have the HPS + * (might be from WinBeginPaint () or from WinGetPS () ) + * Now blit there the stuffs! + */ + _cairo_os2_surface_blit_pixels (local_os2_surface, + hps_begin_paint, + &rclTemp); + } + + DosReleaseMutexSem (local_os2_surface->hmtx_use_private_fields); +} + +static cairo_status_t +_cairo_os2_surface_finish (void *abstract_surface) +{ + cairo_os2_surface_t *local_os2_surface; + + local_os2_surface = (cairo_os2_surface_t *) abstract_surface; + if ((!local_os2_surface) || + (local_os2_surface->base.backend != &cairo_os2_surface_backend)) + { + /* Invalid parameter (wrong surface)! */ + return CAIRO_STATUS_SURFACE_TYPE_MISMATCH; + } + + DosRequestMutexSem (local_os2_surface->hmtx_use_private_fields, SEM_INDEFINITE_WAIT); + + /* Destroy old image surface */ + cairo_surface_destroy ((cairo_surface_t *) (local_os2_surface->image_surface)); + /* Destroy old pixel buffer */ + free (local_os2_surface->pixels); + DosCloseMutexSem (local_os2_surface->hmtx_use_private_fields); + DosCloseEventSem (local_os2_surface->hev_pixel_array_came_back); + + /* The memory itself will be free'd by the cairo_surface_destroy () + * who called us. + */ + + return CAIRO_STATUS_SUCCESS; +} + +void +cairo_os2_surface_set_hwnd (cairo_surface_t *surface, + HWND hwnd_client_window) +{ + cairo_os2_surface_t *local_os2_surface; + + local_os2_surface = (cairo_os2_surface_t *) surface; + if ((!local_os2_surface) || + (local_os2_surface->base.backend != &cairo_os2_surface_backend)) + { + /* Invalid parameter (wrong surface)! */ + return; + } + + if (DosRequestMutexSem (local_os2_surface->hmtx_use_private_fields, SEM_INDEFINITE_WAIT) + != NO_ERROR) + { + /* Could not get mutex! */ + return; + } + + local_os2_surface->hwnd_client_window = hwnd_client_window; + + DosReleaseMutexSem (local_os2_surface->hmtx_use_private_fields); +} + +void +cairo_os2_surface_set_manual_window_refresh (cairo_surface_t *surface, + cairo_bool_t manual_refresh) +{ + cairo_os2_surface_t *local_os2_surface; + + local_os2_surface = (cairo_os2_surface_t *) surface; + if ((!local_os2_surface) || + (local_os2_surface->base.backend != &cairo_os2_surface_backend)) + { + /* Invalid parameter (wrong surface)! */ + return; + } + + local_os2_surface->blit_as_changes = !manual_refresh; +} + +cairo_bool_t +cairo_os2_surface_get_manual_window_refresh (cairo_surface_t *surface) +{ + cairo_os2_surface_t *local_os2_surface; + + local_os2_surface = (cairo_os2_surface_t *) surface; + if ((!local_os2_surface) || + (local_os2_surface->base.backend != &cairo_os2_surface_backend)) + { + /* Invalid parameter (wrong surface)! */ + return FALSE; + } + + return !(local_os2_surface->blit_as_changes); +} + +static cairo_status_t +_cairo_os2_surface_mark_dirty_rectangle (void *surface, + int x, + int y, + int width, + int height) +{ + cairo_os2_surface_t *local_os2_surface; + RECTL rclToBlit; + + local_os2_surface = (cairo_os2_surface_t *) surface; + if ((!local_os2_surface) || + (local_os2_surface->base.backend != &cairo_os2_surface_backend)) + { + /* Invalid parameter (wrong surface)! */ + return CAIRO_STATUS_SURFACE_TYPE_MISMATCH; + } + + /* Get mutex, we'll work with the pixel array! */ + if (DosRequestMutexSem (local_os2_surface->hmtx_use_private_fields, SEM_INDEFINITE_WAIT) + != NO_ERROR) + { + /* Could not get mutex! */ + return CAIRO_STATUS_NO_MEMORY; + } + + /* Check for defaults */ + if (width < 0) + width = local_os2_surface->bitmap_info.cx; + if (height < 0) + height = local_os2_surface->bitmap_info.cy; + + if (local_os2_surface->hwnd_client_window) { + /* We know the HWND, so let's invalidate the window region, + * so the application will redraw itself, using the + * cairo_os2_surface_refresh_window () API from its own PM thread. + * From that function we'll note that it's not a redraw but a + * dirty-rectangle deal stuff, so we'll handle the things from + * there. + * + * This is the safe method, which should be preferred every time. + */ + rclToBlit.xLeft = x; + rclToBlit.xRight = x + width; /* Noninclusive */ + rclToBlit.yTop = local_os2_surface->bitmap_info.cy - (y); + rclToBlit.yBottom = local_os2_surface->bitmap_info.cy - (y + height); /* Noninclusive */ + +#if 0 + if (local_os2_surface->dirty_area_present) { + /* Yikes, there is already a dirty area which should be + * cleaned up, but we'll overwrite it. Sorry. + * TODO: Something clever should be done here. + */ + } +#endif + + /* Set up dirty area reminder stuff */ + memcpy (&(local_os2_surface->rcl_dirty_area), &rclToBlit, sizeof (RECTL)); + local_os2_surface->dirty_area_present = TRUE; + + /* Invalidate window area */ + WinInvalidateRect (local_os2_surface->hwnd_client_window, + &rclToBlit, + FALSE); + } else { + /* We don't know the HWND, so try to blit the pixels from here! + * Please note that it can be problematic if this is not the PM thread! + * + * It can cause internal PM stuffs to be scewed up, for some reason. + * Please always tell the HWND to the surface using the + * cairo_os2_surface_set_hwnd () API, and call cairo_os2_surface_refresh_window () + * from your WM_PAINT, if it's possible! + */ + + rclToBlit.xLeft = x; + rclToBlit.xRight = x + width; /* Noninclusive */ + rclToBlit.yBottom = y; + rclToBlit.yTop = y + height; /* Noninclusive */ + /* Now get the pixels from the screen! */ + _cairo_os2_surface_get_pixels_from_screen (local_os2_surface, + local_os2_surface->hps_client_window, + &rclToBlit); + } + + DosReleaseMutexSem (local_os2_surface->hmtx_use_private_fields); + + return CAIRO_STATUS_SUCCESS; +} + +static const cairo_surface_backend_t cairo_os2_surface_backend = { + CAIRO_SURFACE_TYPE_OS2, + NULL, /* create_similar */ + _cairo_os2_surface_finish, + _cairo_os2_surface_acquire_source_image, + _cairo_os2_surface_release_source_image, + _cairo_os2_surface_acquire_dest_image, + _cairo_os2_surface_release_dest_image, + NULL, /* clone_similar */ + NULL, /* composite */ + NULL, /* fill_rectangles */ + NULL, /* composite_trapezoids */ + NULL, /* copy_page */ + NULL, /* show_page */ + NULL, /* set_clip_region */ + NULL, /* intersect_clip_path */ + _cairo_os2_surface_get_extents, + NULL, /* old_show_glyphs */ + NULL, /* get_font_options */ + NULL, /* flush */ + _cairo_os2_surface_mark_dirty_rectangle, + NULL, /* scaled_font_fini */ + NULL, /* scaled_glyph_fini */ + NULL, /* paint */ + NULL, /* mask */ + NULL, /* stroke */ + NULL, /* fill */ + NULL, /* show_glyphs */ + NULL /* snapshot */ +}; diff --git a/gfx/cairo/cairo/src/cairo-os2.h b/gfx/cairo/cairo/src/cairo-os2.h new file mode 100644 index 000000000000..3e1b4aad4824 --- /dev/null +++ b/gfx/cairo/cairo/src/cairo-os2.h @@ -0,0 +1,201 @@ +/* vim: set sw=4 sts=4 et cin: */ +/* cairo - a vector graphics library with display and print output + * + * Copyright (c) 2005-2006 netlabs.org + * + * This library is free software; you can redistribute it and/or + * modify it either under the terms of the GNU Lesser General Public + * License version 2.1 as published by the Free Software Foundation + * (the "LGPL") or, at your option, under the terms of the Mozilla + * Public License Version 1.1 (the "MPL"). If you do not alter this + * notice, a recipient may use your version of this file under either + * the MPL or the LGPL. + * + * You should have received a copy of the LGPL along with this library + * in the file COPYING-LGPL-2.1; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * You should have received a copy of the MPL along with this library + * in the file COPYING-MPL-1.1 + * + * The contents of this file are subject to the Mozilla Public License + * Version 1.1 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY + * OF ANY KIND, either express or implied. See the LGPL or the MPL for + * the specific language governing rights and limitations. + * + * The Original Code is the cairo graphics library. + * + * The Initial Developer of the Original Code is + * Doodle + * + * Contributor(s): + * Peter Weilbacher + */ + +#ifndef _CAIRO_OS2_H_ +#define _CAIRO_OS2_H_ + +#include + +CAIRO_BEGIN_DECLS + +/* The OS/2 Specific Cairo API */ + +/* cairo_os2_init () : */ +/* */ +/* Initializes the Cairo library. This function is automatically */ +/* called if Cairo was compiled to be a DLL (however it's not a */ +/* problem if it's called multiple times), but if you link to */ +/* Cairo statically, you have to call it once to set up Cairo's */ +/* internal structures and mutexes. */ + +cairo_public void +cairo_os2_init (void); + +/* cairo_os2_fini () : */ +/* */ +/* Uninitializes the Cairo library. This function is automatically */ +/* called if Cairo was compiled to be a DLL (however it's not a */ +/* problem if it's called multiple times), but if you link to */ +/* Cairo statically, you have to call it once to shut down Cairo, */ +/* to let it free all the resources it has allocated. */ + +cairo_public void +cairo_os2_fini (void); + +#if CAIRO_HAS_OS2_SURFACE + +/* cairo_os2_surface_create () : */ +/* */ +/* Create a Cairo surface which is bounded to a given presentation */ +/* space (HPS). The surface will be created to have the given */ +/* size. */ +/* By default: Every change to the surface will be made visible */ +/* immediately by blitting it into the window. This */ +/* can be changed with the */ +/* cairo_os2_surface_set_manual_window_refresh () API. */ +/* Note that the surface will contain garbage when created, so the */ +/* pixels have to be initialized by hand first. You can use the */ +/* Cairo functions to fill it with black, or use the */ +/* cairo_surface_mark_dirty () API to fill the surface with pixels */ +/* from the window/HPS. */ + +cairo_public cairo_surface_t * +cairo_os2_surface_create (HPS hps_client_window, + int width, + int height); + +/* cairo_os2_surface_set_hwnd () : */ +/* */ +/* Sets window handle for surface. If Cairo wants to blit into the */ +/* window because it's set that it should blit as the surface */ +/* changes (see cairo_os2_surface_set_manual_window_refresh () API),*/ +/* then there are two ways it can choose: */ +/* If it knows the HWND of the surface, then it invalidates that */ +/* area, so the application will get a WM_PAINT message and it can */ +/* call cairo_os2_surface_refresh_window () to redraw that area. */ +/* Otherwise cairo itself will use the HPS it got at surface */ +/* creation time, and blit the pixels itself. */ +/* It's also a solution, but experience shows that if this happens */ +/* from a non-PM thread, then it can screw up PM internals. */ +/* */ +/* So, best solution is to set the HWND for the surface after the */ +/* surface creation, so every blit will be done from application's */ +/* message processing loop, which is the safest way to do. */ + +cairo_public void +cairo_os2_surface_set_hwnd (cairo_surface_t *surface, + HWND hwnd_client_window); + +/* cairo_os2_surface_set_size () : */ +/* */ +/* When the client window is resized, call this API so the */ +/* underlaying surface will also be resized. This function will */ +/* reallocate everything, so you'll have to redraw everything in */ +/* the surface after this call. */ +/* The surface will contain garbage after the resizing, just like */ +/* after cairo_os2_surface_create (), so all those notes also apply */ +/* here, please read that! */ +/* */ +/* The timeout value is in milliseconds, and tells how much the */ +/* function should wait on other parts of the program to release */ +/* the buffers. It is necessary, because it can be that Cairo is */ +/* just drawing something into the surface while we want to */ +/* destroy and recreate it. */ +/* Returns CAIRO_STATUS_SUCCESS if the surface could be resized, */ +/* or returns other error code if */ +/* - the surface is not a real OS/2 Surface */ +/* - there is not enough memory to resize the surface */ +/* - waiting for all the buffers to be released timed out */ + +cairo_public int +cairo_os2_surface_set_size (cairo_surface_t *surface, + int new_width, + int new_height, + int timeout); + +/* cairo_os2_surface_refresh_window () : */ +/* */ +/* This function can be used to force a repaint of a given area */ +/* of the client window. Most of the time it is called from the */ +/* WM_PAINT processing of the window proc. However, it can be */ +/* called anytime if a given part of the window has to be updated. */ +/* */ +/* The function expects a HPS of the window, and a RECTL to tell */ +/* which part of the window should be redrawn. */ +/* The returned values of WinBeginPaint () is just perfect here, */ +/* but you can also get the HPS by using the WinGetPS () function, */ +/* and you can assemble your own update rect by hand. */ +/* If the hps_begin_paint parameter is NULL, the function will use */ +/* the HPS you passed in to cairo_os2_surface_create (). If the */ +/* prcl_begin_paint_rect parameter is NULL, the function will query */ +/* the current window size and repaint the whole window. */ +/* */ +/* Cairo/2 assumes that if you told the HWND to the surface using */ +/* the cairo_os2_surface_set_hwnd () API, then this function will */ +/* be called by the application every time it gets a WM_PAINT for */ +/* that HWND. If the HWND is told to the surface, Cairo uses this */ +/* function to handle dirty areas too, so you were warned. :) */ + +cairo_public void +cairo_os2_surface_refresh_window (cairo_surface_t *surface, + HPS hps_begin_paint, + PRECTL prcl_begin_paint_rect); + +/* cairo_os2_surface_set_manual_window_refresh () : */ +/* */ +/* This API can tell Cairo if it should show every change to this */ +/* surface immediately in the window, or if it should be cached */ +/* and will only be visible if the user calls the */ +/* cairo_os2_surface_refresh_window () API explicitly. */ +/* If the HWND was not told to Cairo, then it will use the HPS to */ +/* blit the graphics. Otherwise it will invalidate the given */ +/* window region so the user will get WM_PAINT to redraw that area */ +/* of the window. */ +/* */ +/* So, if you're only interested in displaying the final result */ +/* after several drawing operations, you might get better */ +/* performance if you put the surface into a manual refresh mode */ +/* by passing a true value to cairo_os2_surface_set_manual_refresh()*/ +/* and then calling cairo_os2_surface_refresh() whenever desired. */ + +cairo_public void +cairo_os2_surface_set_manual_window_refresh (cairo_surface_t *surface, + cairo_bool_t manual_refresh); + +/* cairo_os2_surface_get_manual_window_refresh () : */ +/* */ +/* This API can return the current mode of the surface. It is */ +/* TRUE by default. */ + +cairo_public cairo_bool_t +cairo_os2_surface_get_manual_window_refresh (cairo_surface_t *surface); + +#endif /* CAIRO_HAS_OS2_SURFACE */ + +CAIRO_END_DECLS + +#endif /* _CAIRO_OS2_H_ */ diff --git a/gfx/cairo/cairo/src/cairo-output-stream-private.h b/gfx/cairo/cairo/src/cairo-output-stream-private.h index d1eeeeb49ccf..913fb607534a 100644 --- a/gfx/cairo/cairo/src/cairo-output-stream-private.h +++ b/gfx/cairo/cairo/src/cairo-output-stream-private.h @@ -60,7 +60,7 @@ _cairo_output_stream_init (cairo_output_stream_t *stream, cairo_output_stream_write_func_t write_func, cairo_output_stream_close_func_t close_func); -cairo_private void +cairo_private cairo_status_t _cairo_output_stream_fini (cairo_output_stream_t *stream); @@ -86,10 +86,16 @@ _cairo_output_stream_create (cairo_write_func_t write_func, cairo_close_func_t close_func, void *closure); -cairo_private void +/* Returns the final status value associated with this object, just + * before its last gasp. This final status value will capture any + * status failure returned by the stream's close_func as well. */ +cairo_private cairo_status_t _cairo_output_stream_close (cairo_output_stream_t *stream); -cairo_private void +/* Returns the final status value associated with this object, just + * before its last gasp. This final status value will capture any + * status failure returned by the stream's close_func as well. */ +cairo_private cairo_status_t _cairo_output_stream_destroy (cairo_output_stream_t *stream); cairo_private void diff --git a/gfx/cairo/cairo/src/cairo-output-stream.c b/gfx/cairo/cairo/src/cairo-output-stream.c index 96ff8ce0ceeb..f9e527f33c1d 100644 --- a/gfx/cairo/cairo/src/cairo-output-stream.c +++ b/gfx/cairo/cairo/src/cairo-output-stream.c @@ -57,13 +57,12 @@ _cairo_output_stream_init (cairo_output_stream_t *stream, stream->closed = FALSE; } -cairo_private void +cairo_private cairo_status_t _cairo_output_stream_fini (cairo_output_stream_t *stream) { - _cairo_output_stream_close (stream); + return _cairo_output_stream_close (stream); } - const cairo_output_stream_t cairo_output_stream_nil = { NULL, /* write_func */ NULL, /* close_func */ @@ -130,37 +129,44 @@ _cairo_output_stream_create (cairo_write_func_t write_func, return &stream->base; } -void +cairo_status_t _cairo_output_stream_close (cairo_output_stream_t *stream) { cairo_status_t status; if (stream->closed) - return; + return stream->status; if (stream == &cairo_output_stream_nil || stream == &cairo_output_stream_nil_write_error) { - return; + return stream->status; } if (stream->close_func) { status = stream->close_func (stream); - if (status) + /* Don't overwrite a pre-existing status failure. */ + if (stream->status == CAIRO_STATUS_SUCCESS) stream->status = status; } stream->closed = TRUE; + + return stream->status; } -void +cairo_status_t _cairo_output_stream_destroy (cairo_output_stream_t *stream) { - if (stream == NULL) - return; + cairo_status_t status; - _cairo_output_stream_fini (stream); + if (stream == NULL) + return CAIRO_STATUS_NULL_POINTER; + + status = _cairo_output_stream_fini (stream); free (stream); + + return status; } void @@ -184,7 +190,7 @@ _cairo_output_stream_write_hex_string (cairo_output_stream_t *stream, { const char hex_chars[] = "0123456789abcdef"; char buffer[2]; - int i, column; + unsigned int i, column; if (stream->status) return; @@ -459,8 +465,10 @@ _cairo_output_stream_create_for_filename (const char *filename) return (cairo_output_stream_t *) &cairo_output_stream_nil_write_error; stream = malloc (sizeof *stream); - if (stream == NULL) + if (stream == NULL) { + fclose (file); return (cairo_output_stream_t *) &cairo_output_stream_nil; + } _cairo_output_stream_init (&stream->base, stdio_write, stdio_close); stream->file = file; diff --git a/gfx/cairo/cairo/src/cairo-paginated-surface.c b/gfx/cairo/cairo/src/cairo-paginated-surface.c index 4938b381a514..d4977786fd28 100644 --- a/gfx/cairo/cairo/src/cairo-paginated-surface.c +++ b/gfx/cairo/cairo/src/cairo-paginated-surface.c @@ -163,6 +163,25 @@ _cairo_paginated_surface_finish (void *abstract_surface) return CAIRO_STATUS_SUCCESS; } +static cairo_surface_t * +_cairo_paginated_surface_create_image_surface (void *abstract_surface, + int width, + int height) +{ + cairo_paginated_surface_t *surface = abstract_surface; + cairo_surface_t *image; + cairo_font_options_t options; + + image = _cairo_image_surface_create_with_content (surface->content, + width, + height); + + cairo_surface_get_font_options (&surface->base, &options); + _cairo_surface_set_font_options (image, &options); + + return image; +} + static cairo_status_t _cairo_paginated_surface_acquire_source_image (void *abstract_surface, cairo_image_surface_t **image_out, @@ -174,9 +193,9 @@ _cairo_paginated_surface_acquire_source_image (void *abstract_surface, _cairo_surface_get_extents (surface->target, &extents); - image = _cairo_image_surface_create_with_content (surface->content, - extents.width, - extents.height); + image = _cairo_paginated_surface_create_image_surface (surface, + extents.width, + extents.height); _cairo_meta_surface_replay (surface->meta, image); @@ -221,9 +240,9 @@ _paint_page (cairo_paginated_surface_t *surface) double y_scale = surface->base.y_fallback_resolution / 72.0; cairo_matrix_t matrix; - image = _cairo_image_surface_create_with_content (surface->content, - surface->width * x_scale, - surface->height * y_scale); + image = _cairo_paginated_surface_create_image_surface (surface, + surface->width * x_scale, + surface->height * y_scale); _cairo_surface_set_device_scale (image, x_scale, y_scale); _cairo_meta_surface_replay (surface->meta, image); @@ -460,9 +479,9 @@ _cairo_paginated_surface_snapshot (void *abstract_other) _cairo_surface_get_extents (other->target, &extents); - surface = _cairo_image_surface_create_with_content (other->content, - extents.width, - extents.height); + surface = _cairo_paginated_surface_create_image_surface (other, + extents.width, + extents.height); _cairo_meta_surface_replay (other->meta, surface); diff --git a/gfx/cairo/cairo/src/cairo-path-data.c b/gfx/cairo/cairo/src/cairo-path-data.c index 2407e72f5902..cd1519210bf3 100644 --- a/gfx/cairo/cairo/src/cairo-path-data.c +++ b/gfx/cairo/cairo/src/cairo-path-data.c @@ -125,9 +125,6 @@ _cpdc_close_path (void *closure) cpdc->count += 1; - cpdc->current_point.x = 0; - cpdc->current_point.y = 0; - return CAIRO_STATUS_SUCCESS; } @@ -304,9 +301,6 @@ _cpdp_close_path (void *closure) cpdp->data += data->header.length; - cpdp->current_point.x = 0; - cpdp->current_point.y = 0; - return CAIRO_STATUS_SUCCESS; } diff --git a/gfx/cairo/cairo/src/cairo-path-stroke.c b/gfx/cairo/cairo/src/cairo-path-stroke.c index 4ba321ef2ee8..792fbfa06573 100644 --- a/gfx/cairo/cairo/src/cairo-path-stroke.c +++ b/gfx/cairo/cairo/src/cairo-path-stroke.c @@ -59,7 +59,7 @@ typedef struct cairo_stroker { cairo_stroke_face_t first_face; cairo_bool_t dashed; - int dash_index; + unsigned int dash_index; int dash_on; double dash_remain; } cairo_stroker_t; @@ -114,7 +114,7 @@ _cairo_stroker_start_dash (cairo_stroker_t *stroker) { double offset; int on = 1; - int i = 0; + unsigned int i = 0; offset = stroker->style->dash_offset; @@ -699,6 +699,8 @@ _cairo_stroker_line_to_dashed (void *closure, cairo_point_t *point) cairo_point_t *p2 = point; cairo_slope_t slope; + stroker->has_sub_path = stroker->dash_on; + if (p1->x == p2->x && p1->y == p2->y) return CAIRO_STATUS_SUCCESS; @@ -758,6 +760,7 @@ _cairo_stroker_line_to_dashed (void *closure, cairo_point_t *point) return status; } } + stroker->has_sub_path = TRUE; } if (remain) { /* diff --git a/gfx/cairo/cairo/src/cairo-path.c b/gfx/cairo/cairo/src/cairo-path.c index b0c094ed1b87..9549f8d3f7ae 100644 --- a/gfx/cairo/cairo/src/cairo-path.c +++ b/gfx/cairo/cairo/src/cairo-path.c @@ -228,8 +228,13 @@ _cairo_path_fixed_line_to (cairo_path_fixed_t *path, point.x = x; point.y = y; + /* When there is not yet a current point, the line_to operation + * becomes a move_to instead. Note: We have to do this by + * explicitly calling into _cairo_path_fixed_line_to to ensure + * that the last_move_point state is updated properly. + */ if (! path->has_current_point) - status = _cairo_path_fixed_add (path, CAIRO_PATH_OP_MOVE_TO, &point, 1); + status = _cairo_path_fixed_move_to (path, point.x, point.y); else status = _cairo_path_fixed_add (path, CAIRO_PATH_OP_LINE_TO, &point, 1); @@ -328,9 +333,11 @@ _cairo_path_fixed_close_path (cairo_path_fixed_t *path) if (status) return status; - path->current_point.x = path->last_move_point.x; - path->current_point.y = path->last_move_point.y; - path->has_current_point = TRUE; + status = _cairo_path_fixed_move_to (path, + path->last_move_point.x, + path->last_move_point.y); + if (status) + return status; return CAIRO_STATUS_SUCCESS; } diff --git a/gfx/cairo/cairo/src/cairo-pattern.c b/gfx/cairo/cairo/src/cairo-pattern.c index 54d2e927b5cd..a2a08e05c8b1 100644 --- a/gfx/cairo/cairo/src/cairo-pattern.c +++ b/gfx/cairo/cairo/src/cairo-pattern.c @@ -1,3 +1,4 @@ +/* -*- Mode: c; c-basic-offset: 4; indent-tabs-mode: t; tab-width: 8; -*- */ /* cairo - a vector graphics library with display and print output * * Copyright © 2004 David Reveman @@ -31,7 +32,7 @@ const cairo_solid_pattern_t cairo_pattern_nil = { { CAIRO_PATTERN_TYPE_SOLID, /* type */ - (unsigned int)-1, /* ref_count */ + CAIRO_REF_COUNT_INVALID, /* ref_count */ CAIRO_STATUS_NO_MEMORY, /* status */ { 1., 0., 0., 1., 0., 0., }, /* matrix */ CAIRO_FILTER_DEFAULT, /* filter */ @@ -40,7 +41,7 @@ const cairo_solid_pattern_t cairo_pattern_nil = { static const cairo_solid_pattern_t cairo_pattern_nil_null_pointer = { { CAIRO_PATTERN_TYPE_SOLID, /* type */ - (unsigned int)-1, /* ref_count */ + CAIRO_REF_COUNT_INVALID, /* ref_count */ CAIRO_STATUS_NULL_POINTER,/* status */ { 1., 0., 0., 1., 0., 0., }, /* matrix */ CAIRO_FILTER_DEFAULT, /* filter */ @@ -49,7 +50,7 @@ static const cairo_solid_pattern_t cairo_pattern_nil_null_pointer = { static const cairo_solid_pattern_t cairo_pattern_nil_file_not_found = { { CAIRO_PATTERN_TYPE_SOLID, /* type */ - (unsigned int)-1, /* ref_count */ + CAIRO_REF_COUNT_INVALID, /* ref_count */ CAIRO_STATUS_FILE_NOT_FOUND, /* status */ { 1., 0., 0., 1., 0., 0., }, /* matrix */ CAIRO_FILTER_DEFAULT, /* filter */ @@ -58,7 +59,7 @@ static const cairo_solid_pattern_t cairo_pattern_nil_file_not_found = { static const cairo_solid_pattern_t cairo_pattern_nil_read_error = { { CAIRO_PATTERN_TYPE_SOLID, /* type */ - (unsigned int)-1, /* ref_count */ + CAIRO_REF_COUNT_INVALID, /* ref_count */ CAIRO_STATUS_READ_ERROR, /* status */ { 1., 0., 0., 1., 0., 0., }, /* matrix */ CAIRO_FILTER_DEFAULT, /* filter */ @@ -68,17 +69,17 @@ static const cairo_solid_pattern_t cairo_pattern_nil_read_error = { static const cairo_pattern_t * _cairo_pattern_nil_for_status (cairo_status_t status) { - switch (status) { - case CAIRO_STATUS_NULL_POINTER: + /* A switch statement would be more natural here, but we're + * avoiding that to prevent a "false positive" warning from + * -Wswitch-enum, (and I don't want to maintain a list of all + * status values here). */ + if (status == CAIRO_STATUS_NULL_POINTER) return &cairo_pattern_nil_null_pointer.base; - case CAIRO_STATUS_FILE_NOT_FOUND: + if (status == CAIRO_STATUS_FILE_NOT_FOUND) return &cairo_pattern_nil_file_not_found.base; - case CAIRO_STATUS_READ_ERROR: + if (status == CAIRO_STATUS_READ_ERROR) return &cairo_pattern_nil_read_error.base; - default: - case CAIRO_STATUS_NO_MEMORY: - return &cairo_pattern_nil.base; - } + return &cairo_pattern_nil.base; } /** @@ -331,6 +332,7 @@ cairo_pattern_create_rgb (double red, double green, double blue) return pattern; } +slim_hidden_def (cairo_pattern_create_rgb); /** * cairo_pattern_create_rgba: @@ -373,6 +375,7 @@ cairo_pattern_create_rgba (double red, double green, double blue, return pattern; } +slim_hidden_def (cairo_pattern_create_rgba); /** * cairo_pattern_create_for_surface: @@ -410,6 +413,7 @@ cairo_pattern_create_for_surface (cairo_surface_t *surface) return &pattern->base; } +slim_hidden_def (cairo_pattern_create_for_surface); /** * cairo_pattern_create_linear: @@ -457,10 +461,10 @@ cairo_pattern_create_linear (double x0, double y0, double x1, double y1) * cairo_pattern_create_radial: * @cx0: x coordinate for the center of the start circle * @cy0: y coordinate for the center of the start circle - * @radius0: radius of the start cirle + * @radius0: radius of the start circle * @cx1: x coordinate for the center of the end circle * @cy1: y coordinate for the center of the end circle - * @radius1: radius of the end cirle + * @radius1: radius of the end circle * * Creates a new radial gradient cairo_pattern_t between the two * circles defined by (x0, y0, c0) and (x1, y1, c0). Before using the @@ -514,7 +518,7 @@ cairo_pattern_reference (cairo_pattern_t *pattern) if (pattern == NULL) return NULL; - if (pattern->ref_count == (unsigned int)-1) + if (pattern->ref_count == CAIRO_REF_COUNT_INVALID) return pattern; assert (pattern->ref_count > 0); @@ -523,12 +527,16 @@ cairo_pattern_reference (cairo_pattern_t *pattern) return pattern; } +slim_hidden_def (cairo_pattern_reference); /** * cairo_pattern_get_type: * @pattern: a #cairo_pattern_t * - * Return value: The type of @pattern. See #cairo_pattern_type_t. + * This function returns the type a pattern. + * See #cairo_pattern_type_t for available types. + * + * Return value: The type of @pattern. * * Since: 1.2 **/ @@ -537,6 +545,7 @@ cairo_pattern_get_type (cairo_pattern_t *pattern) { return pattern->type; } +slim_hidden_def (cairo_pattern_get_type); /** * cairo_pattern_status: @@ -568,7 +577,7 @@ cairo_pattern_destroy (cairo_pattern_t *pattern) if (pattern == NULL) return; - if (pattern->ref_count == (unsigned int)-1) + if (pattern->ref_count == CAIRO_REF_COUNT_INVALID) return; assert (pattern->ref_count > 0); @@ -580,6 +589,7 @@ cairo_pattern_destroy (cairo_pattern_t *pattern) _cairo_pattern_fini (pattern); free (pattern); } +slim_hidden_def (cairo_pattern_destroy); static void _cairo_pattern_add_color_stop (cairo_gradient_pattern_t *pattern, @@ -591,7 +601,7 @@ _cairo_pattern_add_color_stop (cairo_gradient_pattern_t *pattern, { pixman_gradient_stop_t *new_stops; cairo_fixed_t x; - int i; + unsigned int i; new_stops = realloc (pattern->stops, (pattern->n_stops + 1) * sizeof (pixman_gradient_stop_t)); @@ -761,6 +771,7 @@ cairo_pattern_set_matrix (cairo_pattern_t *pattern, pattern->matrix = *matrix; } +slim_hidden_def (cairo_pattern_set_matrix); /** * cairo_pattern_get_matrix: @@ -824,6 +835,7 @@ cairo_pattern_get_extend (cairo_pattern_t *pattern) { return pattern->extend; } +slim_hidden_def (cairo_pattern_get_extend); void _cairo_pattern_transform (cairo_pattern_t *pattern, @@ -1079,7 +1091,7 @@ _cairo_pattern_is_opaque_solid (const cairo_pattern_t *pattern) static cairo_bool_t _gradient_is_opaque (const cairo_gradient_pattern_t *gradient) { - int i; + unsigned int i; for (i = 0; i < gradient->n_stops; i++) if (! CAIRO_ALPHA_IS_OPAQUE (gradient->stops[i].color.alpha)) @@ -1466,67 +1478,234 @@ _cairo_pattern_get_extents (cairo_pattern_t *pattern, } /** - * cairo_pattern_get_solid_color + * cairo_pattern_get_rgba * @pattern: a #cairo_pattern_t - * @r, @g, @b, @a: a double to return a color value in. must not be NULL. + * @red: return value for red component of color, or %NULL + * @green: return value for green component of color, or %NULL + * @blue: return value for blue component of color, or %NULL + * @alpha: return value for alpha component of color, or %NULL * * Gets the solid color for a solid color pattern. * - * Return value: CAIRO_STATUS_SUCCESS, or - * CAIRO_STATUS_PATTERN_TYPE_MISMATCH if the pattern is not a solid + * Return value: %CAIRO_STATUS_SUCCESS, or + * %CAIRO_STATUS_PATTERN_TYPE_MISMATCH if the pattern is not a solid * color pattern. + * + * Since: 1.4 **/ cairo_status_t -cairo_pattern_get_solid_color (cairo_pattern_t *pattern, - double *r, double *g, double *b, double *a) +cairo_pattern_get_rgba (cairo_pattern_t *pattern, + double *red, double *green, + double *blue, double *alpha) { cairo_solid_pattern_t *solid = (cairo_solid_pattern_t*) pattern; - - assert(r && g && b && a); + double r0, g0, b0, a0; if (pattern->type != CAIRO_PATTERN_TYPE_SOLID) - return CAIRO_STATUS_PATTERN_TYPE_MISMATCH; + return CAIRO_STATUS_PATTERN_TYPE_MISMATCH; - _cairo_color_get_rgba (&solid->color, r, g, b, a); + _cairo_color_get_rgba (&solid->color, &r0, &g0, &b0, &a0); + + if (red) + *red = r0; + if (green) + *green = g0; + if (blue) + *blue = b0; + if (alpha) + *alpha = a0; return CAIRO_STATUS_SUCCESS; } /** - * cairo_pattern_get_color_stop + * cairo_pattern_get_surface * @pattern: a #cairo_pattern_t - * @stop_index: a number from 0 to 1 minus the number of color stops - * @offset: a double representing the color stop offset - * @r, @g, @b, @a: a double to return a color value in. must not be NULL. + * @surface: return value for surface of pattern, or %NULL + * + * Gets the surface of a surface pattern. The reference returned in + * @surface is owned by the pattern; the caller should call + * cairo_surface_reference() if the surface is to be retained. * - * Gets the color stop from a gradient pattern. The caller should - * keep increasing stop_index until this function returns CAIRO_STATUS_INVALID_INDEX + * Return value: %CAIRO_STATUS_SUCCESS, or + * %CAIRO_STATUS_PATTERN_TYPE_MISMATCH if the pattern is not a surface + * pattern. * - * Return value: CAIRO_STATUS_SUCCESS, or CAIRO_STATUS_INVALID_INDEX if there - * is no stop at the given index. If the pattern is not a gradient pattern, - * CAIRO_STATUS_PATTERN_TYPE_MISMATCH is returned. + * Since: 1.4 **/ cairo_status_t -cairo_pattern_get_color_stop (cairo_pattern_t *pattern, - int stop_index, double *offset, - double *r, double *g, double *b, double *a) +cairo_pattern_get_surface (cairo_pattern_t *pattern, + cairo_surface_t **surface) { - cairo_gradient_pattern_t *gradient = (cairo_gradient_pattern_t*) pattern; + cairo_surface_pattern_t *spat = (cairo_surface_pattern_t*) pattern; - assert(offset && r && g && b && a); + if (pattern->type != CAIRO_PATTERN_TYPE_SURFACE) + return CAIRO_STATUS_PATTERN_TYPE_MISMATCH; - if (pattern->type != CAIRO_PATTERN_TYPE_LINEAR || - pattern->type != CAIRO_PATTERN_TYPE_RADIAL) - return CAIRO_STATUS_PATTERN_TYPE_MISMATCH; - - if (stop_index < 0 || stop_index >= gradient->n_stops) - return CAIRO_STATUS_INVALID_INDEX; - - *offset = _cairo_fixed_to_double(gradient->stops[stop_index].x); - *r = gradient->stops[stop_index].color.red / (double) 0xffff; - *g = gradient->stops[stop_index].color.green / (double) 0xffff; - *b = gradient->stops[stop_index].color.blue / (double) 0xffff; - *a = gradient->stops[stop_index].color.alpha / (double) 0xffff; + if (surface) + *surface = spat->surface; + + return CAIRO_STATUS_SUCCESS; +} + +/** + * cairo_pattern_get_color_stop_rgba + * @pattern: a #cairo_pattern_t + * @index: index of the stop to return data for + * @red: return value for red component of color, or %NULL + * @green: return value for green component of color, or %NULL + * @blue: return value for blue component of color, or %NULL + * @alpha: return value for alpha component of color, or %NULL + * + * Gets the color and offset information at the given @index for a + * gradient pattern. Values of @index are 0 to 1 less than the number + * returned by cairo_pattern_get_color_stop_count(). + * + * Return value: %CAIRO_STATUS_SUCCESS, or %CAIRO_STATUS_INVALID_INDEX + * if @index is not valid for the given pattern. If the pattern is + * not a gradient pattern, %CAIRO_STATUS_PATTERN_TYPE_MISMATCH is + * returned. + * + * Since: 1.4 + **/ +cairo_status_t +cairo_pattern_get_color_stop_rgba (cairo_pattern_t *pattern, + int index, double *offset, + double *red, double *green, + double *blue, double *alpha) +{ + cairo_gradient_pattern_t *gradient = (cairo_gradient_pattern_t*) pattern; + + if (pattern->type != CAIRO_PATTERN_TYPE_LINEAR && + pattern->type != CAIRO_PATTERN_TYPE_RADIAL) + return CAIRO_STATUS_PATTERN_TYPE_MISMATCH; + + if (index < 0 || index >= gradient->n_stops) + return CAIRO_STATUS_INVALID_INDEX; + + if (offset) + *offset = _cairo_fixed_to_double(gradient->stops[index].x); + if (red) + *red = gradient->stops[index].color.red / (double) 0xffff; + if (green) + *green = gradient->stops[index].color.green / (double) 0xffff; + if (blue) + *blue = gradient->stops[index].color.blue / (double) 0xffff; + if (alpha) + *alpha = gradient->stops[index].color.alpha / (double) 0xffff; + + return CAIRO_STATUS_SUCCESS; +} + +/** + * cairo_pattern_get_color_stop_count + * @pattern: a #cairo_pattern_t + * @count: return value for the number of color stops, or %NULL + * + * Gets the number of color stops specified in the given gradient + * pattern. + * + * Return value: %CAIRO_STATUS_SUCCESS, or + * %CAIRO_STATUS_PATTERN_TYPE_MISMATCH if @pattern is not a gradient + * pattern. + * + * Since: 1.4 + */ +cairo_status_t +cairo_pattern_get_color_stop_count (cairo_pattern_t *pattern, + int *count) +{ + cairo_gradient_pattern_t *gradient = (cairo_gradient_pattern_t*) pattern; + + if (pattern->type != CAIRO_PATTERN_TYPE_LINEAR && + pattern->type != CAIRO_PATTERN_TYPE_RADIAL) + return CAIRO_STATUS_PATTERN_TYPE_MISMATCH; + + if (count) + *count = gradient->n_stops; + + return CAIRO_STATUS_SUCCESS; +} + +/** + * cairo_pattern_get_linear_points + * @pattern: a #cairo_pattern_t + * @x0: return value for the x coordinate of the first point, or %NULL + * @y0: return value for the y coordinate of the first point, or %NULL + * @x1: return value for the x coordinate of the second point, or %NULL + * @y1: return value for the y coordinate of the second point, or %NULL + * + * Gets the gradient endpoints for a linear gradient. + * + * Return value: %CAIRO_STATUS_SUCCESS, or + * %CAIRO_STATUS_PATTERN_TYPE_MISMATCH if @pattern is not a linear + * gradient pattern. + * + * Since: 1.4 + **/ +cairo_status_t +cairo_pattern_get_linear_points (cairo_pattern_t *pattern, + double *x0, double *y0, + double *x1, double *y1) +{ + cairo_linear_pattern_t *linear = (cairo_linear_pattern_t*) pattern; + + if (pattern->type != CAIRO_PATTERN_TYPE_LINEAR) + return CAIRO_STATUS_PATTERN_TYPE_MISMATCH; + + if (x0) + *x0 = _cairo_fixed_to_double (linear->gradient.p1.x); + if (y0) + *y0 = _cairo_fixed_to_double (linear->gradient.p1.y); + if (x1) + *x1 = _cairo_fixed_to_double (linear->gradient.p2.x); + if (y1) + *y1 = _cairo_fixed_to_double (linear->gradient.p2.y); + + return CAIRO_STATUS_SUCCESS; +} + +/** + * cairo_pattern_get_radial_circles + * @pattern: a #cairo_pattern_t + * @x0: return value for the x coordinate of the center of the first (inner) circle, or %NULL + * @y0: return value for the y coordinate of the center of the first (inner) circle, or %NULL + * @r0: return value for the radius of the first (inner) circle, or %NULL + * @x1: return value for the x coordinate of the center of the second (outer) circle, or %NULL + * @y1: return value for the y coordinate of the center of the second (outer) circle, or %NULL + * @r1: return value for the radius of the second (outer) circle, or %NULL + * + * Gets the gradient endpoint circles for a radial gradient, each + * specified as a center coordinate and a radius. + * + * Return value: %CAIRO_STATUS_SUCCESS, or + * %CAIRO_STATUS_PATTERN_TYPE_MISMATCH if @pattern is not a radial + * gradient pattern. + * + * Since: 1.4 + **/ +cairo_status_t +cairo_pattern_get_radial_circles (cairo_pattern_t *pattern, + double *x0, double *y0, double *r0, + double *x1, double *y1, double *r1) +{ + cairo_radial_pattern_t *radial = (cairo_radial_pattern_t*) pattern; + + if (pattern->type != CAIRO_PATTERN_TYPE_RADIAL) + return CAIRO_STATUS_PATTERN_TYPE_MISMATCH; + + if (x0) + *x0 = _cairo_fixed_to_double (radial->gradient.inner.x); + if (y0) + *y0 = _cairo_fixed_to_double (radial->gradient.inner.y); + if (r0) + *r0 = _cairo_fixed_to_double (radial->gradient.inner.radius); + if (x1) + *x1 = _cairo_fixed_to_double (radial->gradient.outer.x); + if (y1) + *y1 = _cairo_fixed_to_double (radial->gradient.outer.y); + if (r1) + *r1 = _cairo_fixed_to_double (radial->gradient.outer.radius); return CAIRO_STATUS_SUCCESS; } diff --git a/gfx/cairo/cairo/src/cairo-pdf-surface.c b/gfx/cairo/cairo/src/cairo-pdf-surface.c index 663097f21296..6106284e2058 100644 --- a/gfx/cairo/cairo/src/cairo-pdf-surface.c +++ b/gfx/cairo/cairo/src/cairo-pdf-surface.c @@ -40,7 +40,6 @@ #include "cairo-pdf.h" #include "cairo-pdf-test.h" #include "cairo-scaled-font-subsets-private.h" -#include "cairo-ft-private.h" #include "cairo-paginated-surface-private.h" #include "cairo-path-fixed-private.h" #include "cairo-output-stream-private.h" @@ -296,6 +295,8 @@ _cairo_pdf_surface_create_for_stream_internal (cairo_output_stream_t *output, /* Document header */ _cairo_output_stream_printf (surface->output, "%%PDF-1.4\r\n"); + _cairo_output_stream_printf (surface->output, + "%%%c%c%c%c\r\n", 181, 237, 174, 251); return _cairo_paginated_surface_create (&surface->base, CAIRO_CONTENT_COLOR_ALPHA, @@ -453,19 +454,6 @@ _cairo_pdf_surface_clear (cairo_pdf_surface_t *surface) _cairo_array_truncate (&surface->streams, 0); } -static cairo_surface_t * -_cairo_pdf_surface_create_similar (void *abstract_src, - cairo_content_t content, - int width, - int height) -{ - cairo_format_t format = _cairo_format_from_content (content); - - /* Just return an image for now, until PDF surface can be used - * as source. */ - return cairo_image_surface_create (format, width, height); -} - static cairo_pdf_resource_t _cairo_pdf_surface_open_stream (cairo_pdf_surface_t *surface, const char *fmt, @@ -558,8 +546,7 @@ _cairo_pdf_surface_finish (void *abstract_surface) "%%%%EOF\r\n", offset); - status = _cairo_output_stream_get_status (surface->output); - _cairo_output_stream_destroy (surface->output); + status = _cairo_output_stream_destroy (surface->output); _cairo_array_fini (&surface->objects); _cairo_array_fini (&surface->pages); @@ -893,8 +880,12 @@ emit_surface_pattern (cairo_pdf_surface_t *surface, xstep = image->width; ystep = image->height; break; + /* All the reset should have been analyzed away, so this case + * should be unreachable. */ + case CAIRO_EXTEND_REFLECT: + case CAIRO_EXTEND_PAD: default: - ASSERT_NOT_REACHED; /* all others should be analyzed away */ + ASSERT_NOT_REACHED; xstep = 0; ystep = 0; } @@ -1081,8 +1072,7 @@ emit_pattern_stops (cairo_pdf_surface_t *surface, cairo_gradient_pattern_t *patt { cairo_pdf_resource_t function; cairo_pdf_color_stop_t *allstops, *stops; - unsigned int n_stops; - unsigned int i; + unsigned int i, n_stops; function = _cairo_pdf_surface_new_object (surface); @@ -1472,6 +1462,7 @@ _cairo_pdf_surface_get_font_options (void *abstract_surface, cairo_font_options_set_hint_style (options, CAIRO_HINT_STYLE_NONE); cairo_font_options_set_hint_metrics (options, CAIRO_HINT_METRICS_OFF); + cairo_font_options_set_antialias (options, CAIRO_ANTIALIAS_GRAY); } static cairo_pdf_resource_t @@ -1587,31 +1578,22 @@ _cairo_pdf_surface_write_pages (cairo_pdf_surface_t *surface) } static cairo_status_t -_cairo_pdf_surface_emit_type1_font_subset (cairo_pdf_surface_t *surface, - cairo_scaled_font_subset_t *font_subset) +_cairo_pdf_surface_emit_type1_font (cairo_pdf_surface_t *surface, + cairo_scaled_font_subset_t *font_subset, + cairo_type1_subset_t *subset) { cairo_pdf_resource_t stream, descriptor, subset_resource; - cairo_status_t status; cairo_pdf_font_t font; - cairo_type1_subset_t subset; unsigned long length, compressed_length; char *compressed; - int i; - char name[64]; + unsigned int i; - snprintf (name, sizeof name, "CairoFont-%d-%d", - font_subset->font_id, font_subset->subset_id); - status = _cairo_type1_subset_init (&subset, name, font_subset); - if (status) - return status; /* We ignore the zero-trailer and set Length3 to 0. */ - length = subset.header_length + subset.data_length; - compressed = compress_dup (subset.data, length, &compressed_length); - if (compressed == NULL) { - _cairo_type1_subset_fini (&subset); + length = subset->header_length + subset->data_length; + compressed = compress_dup (subset->data, length, &compressed_length); + if (compressed == NULL) return CAIRO_STATUS_NO_MEMORY; - } stream = _cairo_pdf_surface_new_object (surface); _cairo_output_stream_printf (surface->output, @@ -1625,8 +1607,8 @@ _cairo_pdf_surface_emit_type1_font_subset (cairo_pdf_surface_t *surface, "stream\r\n", stream.id, compressed_length, - subset.header_length, - subset.data_length); + subset->header_length, + subset->data_length); _cairo_output_stream_write (surface->output, compressed, compressed_length); _cairo_output_stream_printf (surface->output, "\r\n" @@ -1651,13 +1633,13 @@ _cairo_pdf_surface_emit_type1_font_subset (cairo_pdf_surface_t *surface, ">>\r\n" "endobj\r\n", descriptor.id, - subset.base_font, - subset.x_min, - subset.y_min, - subset.x_max, - subset.y_max, - subset.ascent, - subset.descent, + subset->base_font, + subset->x_min, + subset->y_min, + subset->x_max, + subset->y_max, + subset->ascent, + subset->descent, stream.id); subset_resource = _cairo_pdf_surface_new_object (surface); @@ -1671,14 +1653,14 @@ _cairo_pdf_surface_emit_type1_font_subset (cairo_pdf_surface_t *surface, " /FontDescriptor %d 0 R\r\n" " /Widths [", subset_resource.id, - subset.base_font, - font_subset->num_glyphs, + subset->base_font, + font_subset->num_glyphs - 1, descriptor.id); for (i = 0; i < font_subset->num_glyphs; i++) _cairo_output_stream_printf (surface->output, " %d", - subset.widths[i]); + subset->widths[i]); _cairo_output_stream_printf (surface->output, " ]\r\n" @@ -1690,11 +1672,51 @@ _cairo_pdf_surface_emit_type1_font_subset (cairo_pdf_surface_t *surface, font.subset_resource = subset_resource; _cairo_array_append (&surface->fonts, &font); - _cairo_type1_subset_fini (&subset); - return CAIRO_STATUS_SUCCESS; } +#if CAIRO_HAS_FT_FONT +static cairo_status_t +_cairo_pdf_surface_emit_type1_font_subset (cairo_pdf_surface_t *surface, + cairo_scaled_font_subset_t *font_subset) +{ + cairo_status_t status; + cairo_type1_subset_t subset; + char name[64]; + + snprintf (name, sizeof name, "CairoFont-%d-%d", + font_subset->font_id, font_subset->subset_id); + status = _cairo_type1_subset_init (&subset, name, font_subset, FALSE); + if (status) + return status; + + status = _cairo_pdf_surface_emit_type1_font (surface, font_subset, &subset); + + _cairo_type1_subset_fini (&subset); + return status; +} +#endif + +static cairo_status_t +_cairo_pdf_surface_emit_type1_fallback_font (cairo_pdf_surface_t *surface, + cairo_scaled_font_subset_t *font_subset) +{ + cairo_status_t status; + cairo_type1_subset_t subset; + char name[64]; + + snprintf (name, sizeof name, "CairoFont-%d-%d", + font_subset->font_id, font_subset->subset_id); + status = _cairo_type1_fallback_init (&subset, name, font_subset); + if (status) + return status; + + status = _cairo_pdf_surface_emit_type1_font (surface, font_subset, &subset); + + _cairo_type1_fallback_fini (&subset); + return status; +} + static cairo_status_t _cairo_pdf_surface_emit_truetype_font_subset (cairo_pdf_surface_t *surface, cairo_scaled_font_subset_t *font_subset) @@ -1705,7 +1727,7 @@ _cairo_pdf_surface_emit_truetype_font_subset (cairo_pdf_surface_t *surface, cairo_truetype_subset_t subset; unsigned long compressed_length; char *compressed; - int i; + unsigned int i; status = _cairo_truetype_subset_init (&subset, font_subset); if (status) @@ -1774,7 +1796,7 @@ _cairo_pdf_surface_emit_truetype_font_subset (cairo_pdf_surface_t *surface, " /Widths [", subset_resource.id, subset.base_font, - font_subset->num_glyphs, + font_subset->num_glyphs - 1, descriptor.id); for (i = 0; i < font_subset->num_glyphs; i++) @@ -1864,7 +1886,11 @@ _cairo_pdf_surface_emit_bitmap_glyph (cairo_pdf_surface_t *surface, return status; image = scaled_glyph->surface; - assert (image->format == CAIRO_FORMAT_A1); + if (image->format != CAIRO_FORMAT_A1) { + image = _cairo_image_surface_clone (image, CAIRO_FORMAT_A1); + if (cairo_surface_status (&image->base)) + return cairo_surface_status (&image->base); + } *glyph_ret = _cairo_pdf_surface_open_stream (surface, NULL); @@ -1906,6 +1932,9 @@ _cairo_pdf_surface_emit_bitmap_glyph (cairo_pdf_surface_t *surface, _cairo_pdf_surface_close_stream (surface); + if (image != scaled_glyph->surface) + cairo_surface_destroy (&image->base); + return CAIRO_STATUS_SUCCESS; } @@ -1938,7 +1967,7 @@ _cairo_pdf_surface_emit_type3_font_subset (cairo_pdf_surface_t *surface, cairo_pdf_resource_t *glyphs, encoding, char_procs, subset_resource; cairo_pdf_font_t font; cairo_matrix_t matrix; - int i; + unsigned int i; glyphs = malloc (font_subset->num_glyphs * sizeof (cairo_pdf_resource_t)); if (glyphs == NULL) { @@ -1978,6 +2007,8 @@ _cairo_pdf_surface_emit_type3_font_subset (cairo_pdf_surface_t *surface, ">>\r\n" "endobj\r\n"); + free (glyphs); + subset_resource = _cairo_pdf_surface_new_object (surface); matrix = font_subset->scaled_font->scale; cairo_matrix_invert (&matrix); @@ -2026,14 +2057,20 @@ _cairo_pdf_surface_emit_font_subset (cairo_scaled_font_subset_t *font_subset, cairo_pdf_surface_t *surface = closure; cairo_status_t status; +#if CAIRO_HAS_FT_FONT status = _cairo_pdf_surface_emit_type1_font_subset (surface, font_subset); if (status != CAIRO_INT_STATUS_UNSUPPORTED) return; +#endif status = _cairo_pdf_surface_emit_truetype_font_subset (surface, font_subset); if (status != CAIRO_INT_STATUS_UNSUPPORTED) return; + status = _cairo_pdf_surface_emit_type1_fallback_font (surface, font_subset); + if (status != CAIRO_INT_STATUS_UNSUPPORTED) + return; + status = _cairo_pdf_surface_emit_type3_font_subset (surface, font_subset); if (status != CAIRO_INT_STATUS_UNSUPPORTED) return; @@ -2451,12 +2488,14 @@ _cairo_pdf_surface_emit_stroke_style (cairo_pdf_surface_t *surface, _cairo_pdf_line_join (style->line_join)); if (style->num_dashes) { - int d; + unsigned int d; _cairo_output_stream_printf (surface->output, "["); for (d = 0; d < style->num_dashes; d++) _cairo_output_stream_printf (surface->output, " %f", style->dash[d]); _cairo_output_stream_printf (surface->output, "] %f d\r\n", style->dash_offset); + } else { + _cairo_output_stream_printf (surface->output, "[] 0.0 d\r\n"); } _cairo_output_stream_printf (surface->output, @@ -2577,7 +2616,7 @@ _cairo_pdf_surface_show_glyphs (void *abstract_surface, cairo_scaled_font_t *scaled_font) { cairo_pdf_surface_t *surface = abstract_surface; - int current_subset_id = -1; + unsigned int current_subset_id = (unsigned int)-1; unsigned int font_id, subset_id, subset_glyph_index; cairo_status_t status; int i; @@ -2636,7 +2675,7 @@ _cairo_pdf_surface_set_paginated_mode (void *abstract_surface, static const cairo_surface_backend_t cairo_pdf_surface_backend = { CAIRO_SURFACE_TYPE_PDF, - _cairo_pdf_surface_create_similar, + NULL, /* create_similar */ _cairo_pdf_surface_finish, NULL, /* acquire_source_image */ NULL, /* release_source_image */ diff --git a/gfx/cairo/cairo/src/cairo-pdf.h b/gfx/cairo/cairo/src/cairo-pdf.h index 53699d4185fa..52a8974040b8 100644 --- a/gfx/cairo/cairo/src/cairo-pdf.h +++ b/gfx/cairo/cairo/src/cairo-pdf.h @@ -54,7 +54,7 @@ cairo_pdf_surface_create_for_stream (cairo_write_func_t write_func, double width_in_points, double height_in_points); -void +cairo_public void cairo_pdf_surface_set_size (cairo_surface_t *surface, double width_in_points, double height_in_points); diff --git a/gfx/cairo/cairo/src/cairo-platform.h b/gfx/cairo/cairo/src/cairo-platform.h index 8484442e34d4..502c4f37fdd7 100644 --- a/gfx/cairo/cairo/src/cairo-platform.h +++ b/gfx/cairo/cairo/src/cairo-platform.h @@ -47,7 +47,7 @@ #define CVISIBILITY_HIDDEN #endif -// In libxul builds we don't ever want to export cairo symbols +/* In libxul builds we don't ever want to export cairo symbols */ #define cairo_public extern CVISIBILITY_HIDDEN #define CCALLBACK #define CCALLBACK_DECL diff --git a/gfx/cairo/cairo/src/cairo-png.c b/gfx/cairo/cairo/src/cairo-png.c index d656016358ba..3b33b5463cfe 100644 --- a/gfx/cairo/cairo/src/cairo-png.c +++ b/gfx/cairo/cairo/src/cairo-png.c @@ -35,15 +35,15 @@ * Kristian Høgsberg */ -#include #include #include "cairoint.h" +#include /* Unpremultiplies data and converts native endian ARGB => RGBA bytes */ static void unpremultiply_data (png_structp png, png_row_infop row_info, png_bytep data) { - int i; + unsigned int i; for (i = 0; i < row_info->rowbytes; i += 4) { uint8_t *b = &data[i]; @@ -67,7 +67,7 @@ unpremultiply_data (png_structp png, png_row_infop row_info, png_bytep data) static void convert_data_to_bytes (png_structp png, png_row_infop row_info, png_bytep data) { - int i; + unsigned int i; for (i = 0; i < row_info->rowbytes; i += 4) { uint8_t *b = &data[i]; @@ -88,7 +88,7 @@ write_png (cairo_surface_t *surface, void *closure) { int i; - cairo_status_t status = CAIRO_STATUS_SUCCESS; + volatile cairo_status_t status = CAIRO_STATUS_SUCCESS; cairo_image_surface_t *image; void *image_extra; png_struct *png; @@ -287,6 +287,7 @@ cairo_surface_write_to_png_stream (cairo_surface_t *surface, return write_png (surface, stream_write_func, &png_closure); } +slim_hidden_def (cairo_surface_write_to_png_stream); static INLINE int multiply_alpha (int alpha, int color) @@ -301,7 +302,7 @@ premultiply_data (png_structp png, png_row_infop row_info, png_bytep data) { - int i; + unsigned int i; for (i = 0; i < row_info->rowbytes; i += 4) { uint8_t *base = &data[i]; @@ -332,7 +333,7 @@ read_png (png_rw_ptr read_func, { cairo_surface_t *surface = (cairo_surface_t*) &_cairo_surface_nil; png_byte *data = NULL; - int i; + unsigned int i; png_struct *png = NULL; png_info *info; png_uint_32 png_width, png_height, stride; diff --git a/gfx/cairo/cairo/src/cairo-ps-surface.c b/gfx/cairo/cairo/src/cairo-ps-surface.c index 3856aa231d72..7403b0ec0fda 100644 --- a/gfx/cairo/cairo/src/cairo-ps-surface.c +++ b/gfx/cairo/cairo/src/cairo-ps-surface.c @@ -43,9 +43,9 @@ #include "cairo-scaled-font-subsets-private.h" #include "cairo-paginated-surface-private.h" #include "cairo-meta-surface-private.h" -#include "cairo-ft-private.h" #include "cairo-output-stream-private.h" +#include #include #include @@ -313,6 +313,8 @@ _cairo_ps_surface_emit_path (cairo_ps_surface_t *surface, _cairo_ps_surface_path_close_path, &path_info); + if (status == CAIRO_STATUS_SUCCESS) + status = _cairo_output_stream_get_status (word_wrap); _cairo_output_stream_destroy (word_wrap); return status; @@ -385,6 +387,7 @@ _cairo_ps_surface_emit_header (cairo_ps_surface_t *surface) } } +#if CAIRO_HAS_FT_FONT static cairo_status_t _cairo_ps_surface_emit_type1_font_subset (cairo_ps_surface_t *surface, cairo_scaled_font_subset_t *font_subset) @@ -398,7 +401,7 @@ _cairo_ps_surface_emit_type1_font_subset (cairo_ps_surface_t *surface, snprintf (name, sizeof name, "CairoFont-%d-%d", font_subset->font_id, font_subset->subset_id); - status = _cairo_type1_subset_init (&subset, name, font_subset); + status = _cairo_type1_subset_init (&subset, name, font_subset, TRUE); if (status) return status; @@ -414,6 +417,35 @@ _cairo_ps_surface_emit_type1_font_subset (cairo_ps_surface_t *surface, return CAIRO_STATUS_SUCCESS; } +#endif + +static cairo_status_t +_cairo_ps_surface_emit_type1_font_fallback (cairo_ps_surface_t *surface, + cairo_scaled_font_subset_t *font_subset) +{ + cairo_type1_subset_t subset; + cairo_status_t status; + int length; + char name[64]; + + snprintf (name, sizeof name, "CairoFont-%d-%d", + font_subset->font_id, font_subset->subset_id); + status = _cairo_type1_fallback_init (&subset, name, font_subset); + if (status) + return status; + + /* FIXME: Figure out document structure convention for fonts */ + + _cairo_output_stream_printf (surface->final_stream, + "%% _cairo_ps_surface_emit_type1_font_subset\n"); + + length = subset.header_length + subset.data_length + subset.trailer_length; + _cairo_output_stream_write (surface->final_stream, subset.data, length); + + _cairo_type1_fallback_fini (&subset); + + return CAIRO_STATUS_SUCCESS; +} static cairo_status_t _cairo_ps_surface_emit_truetype_font_subset (cairo_ps_surface_t *surface, @@ -423,7 +455,7 @@ _cairo_ps_surface_emit_truetype_font_subset (cairo_ps_surface_t *surface, { cairo_truetype_subset_t subset; cairo_status_t status; - int i; + unsigned int i, begin, end; status = _cairo_truetype_subset_init (&subset, font_subset); if (status) @@ -464,17 +496,27 @@ _cairo_ps_surface_emit_truetype_font_subset (cairo_ps_surface_t *surface, _cairo_output_stream_printf (surface->final_stream, "end readonly def\n"); - /* FIXME: We need to break up fonts bigger than 64k so we don't - * exceed string size limitation. At glyph boundaries. Stupid - * postscript. */ _cairo_output_stream_printf (surface->final_stream, - "/sfnts [<"); - - _cairo_output_stream_write_hex_string (surface->final_stream, - subset.data, subset.data_length); + "/sfnts [\n"); + begin = 0; + end = 0; + for (i = 0; i < subset.num_string_offsets; i++) { + end = subset.string_offsets[i]; + _cairo_output_stream_printf (surface->final_stream,"<"); + _cairo_output_stream_write_hex_string (surface->final_stream, + subset.data + begin, end - begin); + _cairo_output_stream_printf (surface->final_stream,"00>\n"); + begin = end; + } + if (subset.data_length > end) { + _cairo_output_stream_printf (surface->final_stream,"<"); + _cairo_output_stream_write_hex_string (surface->final_stream, + subset.data + end, subset.data_length - end); + _cairo_output_stream_printf (surface->final_stream,"00>\n"); + } _cairo_output_stream_printf (surface->final_stream, - ">] def\n" + "] def\n" "FontName currentdict end definefont pop\n"); _cairo_truetype_subset_fini (&subset); @@ -535,7 +577,11 @@ _cairo_ps_surface_emit_bitmap_glyph_data (cairo_ps_surface_t *surface, &scaled_glyph); image = scaled_glyph->surface; - assert (image->format == CAIRO_FORMAT_A1); + if (image->format != CAIRO_FORMAT_A1) { + image = _cairo_image_surface_clone (image, CAIRO_FORMAT_A1); + if (cairo_surface_status (&image->base)) + return cairo_surface_status (&image->base); + } _cairo_output_stream_printf (surface->final_stream, "0 0 %f %f %f %f setcachedevice\n", @@ -554,12 +600,12 @@ _cairo_ps_surface_emit_bitmap_glyph_data (cairo_ps_surface_t *surface, " /BitsPerComponent 1\n", image->width, image->height, - image->base.device_transform.xx, - image->base.device_transform.yx, - image->base.device_transform.xy, - image->base.device_transform.yy, - image->base.device_transform.x0, - - image->base.device_transform.y0); + image->base.device_transform_inverse.xx, + image->base.device_transform_inverse.yx, + image->base.device_transform_inverse.xy, + image->base.device_transform_inverse.yy, + image->base.device_transform_inverse.x0, + image->base.device_transform_inverse.y0); _cairo_output_stream_printf (surface->final_stream, " /DataSource {<"); @@ -579,6 +625,9 @@ _cairo_ps_surface_emit_bitmap_glyph_data (cairo_ps_surface_t *surface, _cairo_output_stream_printf (surface->final_stream, "imagemask\n"); + if (image != scaled_glyph->surface) + cairo_surface_destroy (&image->base); + return CAIRO_STATUS_SUCCESS; } @@ -615,7 +664,7 @@ _cairo_ps_surface_emit_type3_font_subset (cairo_ps_surface_t *surface, { cairo_matrix_t matrix; - int i; + unsigned int i; _cairo_output_stream_printf (surface->final_stream, "%% _cairo_ps_surface_emit_type3_font_subset\n"); @@ -663,14 +712,20 @@ _cairo_ps_surface_emit_font_subset (cairo_scaled_font_subset_t *font_subset, cairo_ps_surface_t *surface = closure; cairo_status_t status; +#if CAIRO_HAS_FT_FONT status = _cairo_ps_surface_emit_type1_font_subset (surface, font_subset); if (status != CAIRO_INT_STATUS_UNSUPPORTED) return; +#endif status = _cairo_ps_surface_emit_truetype_font_subset (surface, font_subset); if (status != CAIRO_INT_STATUS_UNSUPPORTED) return; + status = _cairo_ps_surface_emit_type1_font_fallback (surface, font_subset); + if (status != CAIRO_INT_STATUS_UNSUPPORTED) + return; + status = _cairo_ps_surface_emit_type3_font_subset (surface, font_subset); if (status != CAIRO_INT_STATUS_UNSUPPORTED) return; @@ -1126,19 +1181,6 @@ cairo_ps_surface_dsc_begin_page_setup (cairo_surface_t *surface) } } -static cairo_surface_t * -_cairo_ps_surface_create_similar (void *abstract_src, - cairo_content_t content, - int width, - int height) -{ - cairo_format_t format = _cairo_format_from_content (content); - - /* Just return an image for now, until PS surface can be used - * as source. */ - return cairo_image_surface_create (format, width, height); -} - static cairo_status_t _cairo_ps_surface_finish (void *abstract_surface) { @@ -1474,7 +1516,7 @@ static cairo_status_t emit_image (cairo_ps_surface_t *surface, cairo_image_surface_t *image, cairo_matrix_t *matrix, - char *name) + const char *name) { cairo_status_t status; unsigned char *rgb, *compressed; @@ -1788,6 +1830,7 @@ _cairo_ps_surface_get_font_options (void *abstract_surface, cairo_font_options_set_hint_style (options, CAIRO_HINT_STYLE_NONE); cairo_font_options_set_hint_metrics (options, CAIRO_HINT_METRICS_OFF); + cairo_font_options_set_antialias (options, CAIRO_ANTIALIAS_GRAY); } static cairo_int_status_t @@ -2056,7 +2099,7 @@ _cairo_ps_surface_show_glyphs (void *abstract_surface, { cairo_ps_surface_t *surface = abstract_surface; cairo_output_stream_t *stream = surface->stream; - int current_subset_id = -1; + unsigned int current_subset_id = -1; unsigned int font_id, subset_id, subset_glyph_index; cairo_status_t status; int i; @@ -2113,7 +2156,7 @@ _cairo_ps_surface_set_paginated_mode (void *abstract_surface, static const cairo_surface_backend_t cairo_ps_surface_backend = { CAIRO_SURFACE_TYPE_PS, - _cairo_ps_surface_create_similar, + NULL, /* create_similar */ _cairo_ps_surface_finish, NULL, /* acquire_source_image */ NULL, /* release_source_image */ diff --git a/gfx/cairo/cairo/src/cairo-quartz-private.h b/gfx/cairo/cairo/src/cairo-quartz-private.h index de6b91531428..f9db501c92bd 100644 --- a/gfx/cairo/cairo/src/cairo-quartz-private.h +++ b/gfx/cairo/cairo/src/cairo-quartz-private.h @@ -44,15 +44,11 @@ typedef struct cairo_quartz_surface { CGContextRef context; - cairo_bool_t flipped; + cairo_bool_t y_grows_down; - int width; - int height; + cairo_rectangle_int16_t extents; - cairo_image_surface_t *image; - pixman_region16_t *clip_region; - - CGImageRef cgImage; + pixman_region16_t *clip_region; } cairo_quartz_surface_t; cairo_bool_t diff --git a/gfx/cairo/cairo/src/cairo-quartz-surface.c b/gfx/cairo/cairo/src/cairo-quartz-surface.c index e1715bfdea9c..cff15af2bc1c 100644 --- a/gfx/cairo/cairo/src/cairo-quartz-surface.c +++ b/gfx/cairo/cairo/src/cairo-quartz-surface.c @@ -37,28 +37,14 @@ #include "cairo-private.h" #include "cairo-quartz-private.h" -static void -ImageDataReleaseFunc(void *info, const void *data, size_t size) -{ - if (data != NULL) { - free((void *) data); - } -} - static cairo_status_t _cairo_quartz_surface_finish(void *abstract_surface) { cairo_quartz_surface_t *surface = abstract_surface; - if (surface->image) - cairo_surface_destroy(&surface->image->base); + if (surface->clip_region) + pixman_region_destroy (surface->clip_region); - if (surface->cgImage) - CGImageRelease(surface->cgImage); - - if (surface->clip_region) - pixman_region_destroy (surface->clip_region); - return CAIRO_STATUS_SUCCESS; } @@ -67,117 +53,127 @@ _cairo_quartz_surface_acquire_source_image(void *abstract_surface, cairo_image_surface_t **image_out, void **image_extra) { - cairo_quartz_surface_t *surface = abstract_surface; - CGColorSpaceRef colorSpace; - void *imageData; - UInt32 imageDataSize, rowBytes; - CGDataProviderRef dataProvider; + cairo_quartz_surface_t *surface = abstract_surface; - /* We keep a cached (cairo_image_surface_t *) in the cairo_quartz_surface_t - * struct. If the window is ever drawn to without going through Cairo, then - * we would need to refetch the pixel data from the window into the cached - * image surface. - */ - if (surface->image) { - cairo_surface_reference(&surface->image->base); + if (CGBitmapContextGetBitmapInfo (surface->context) != 0) { + /* XXX: We can create an image out of the bitmap here */ + } - *image_out = surface->image; - return CAIRO_STATUS_SUCCESS; - } - - colorSpace = CGColorSpaceCreateDeviceRGB(); - - - rowBytes = surface->width * 4; - imageDataSize = rowBytes * surface->height; - imageData = malloc(imageDataSize); - - dataProvider = - CGDataProviderCreateWithData(NULL, imageData, imageDataSize, - ImageDataReleaseFunc); - - surface->cgImage = CGImageCreate(surface->width, - surface->height, - 8, - 32, - rowBytes, - colorSpace, - kCGImageAlphaPremultipliedFirst, - dataProvider, - NULL, - false, kCGRenderingIntentDefault); - - CGColorSpaceRelease(colorSpace); - CGDataProviderRelease(dataProvider); - - surface->image = (cairo_image_surface_t *) - cairo_image_surface_create_for_data(imageData, - CAIRO_FORMAT_ARGB32, - surface->width, - surface->height, rowBytes); - if (surface->image->base.status) { - if (surface->cgImage) - CGImageRelease(surface->cgImage); - return CAIRO_STATUS_NO_MEMORY; - } - - *image_out = surface->image; - *image_extra = NULL; - - return CAIRO_STATUS_SUCCESS; + return CAIRO_INT_STATUS_UNSUPPORTED; } static cairo_status_t -_cairo_quartz_surface_acquire_dest_image(void *abstract_surface, - cairo_rectangle_int16_t * interest_rect, - cairo_image_surface_t ** - image_out, - cairo_rectangle_int16_t * image_rect, - void **image_extra) +_cairo_quartz_surface_acquire_dest_image(void *abstract_surface, + cairo_rectangle_int16_t *interest_rect, + cairo_image_surface_t **image_out, + cairo_rectangle_int16_t *image_rect, + void **image_extra) { cairo_quartz_surface_t *surface = abstract_surface; + cairo_surface_t *image_surface; + unsigned char *data; + int x1, y1, x2, y2; - image_rect->x = 0; - image_rect->y = 0; - image_rect->width = surface->image->width; - image_rect->height = surface->image->height; + x1 = surface->extents.x; + x2 = surface->extents.x + surface->extents.width; + y1 = surface->extents.y; + y2 = surface->extents.y + surface->extents.height; - *image_out = surface->image; - if (image_extra) + if (interest_rect->x > x1) + x1 = interest_rect->x; + if (interest_rect->y > y1) + y1 = interest_rect->y; + if (interest_rect->x + interest_rect->width < x2) + x2 = interest_rect->x + interest_rect->width; + if (interest_rect->y + interest_rect->height < y2) + y2 = interest_rect->y + interest_rect->height; + + if (x1 >= x2 || y1 >= y2) { + *image_out = NULL; *image_extra = NULL; + return CAIRO_STATUS_SUCCESS; + } + + image_rect->x = x1; + image_rect->y = y1; + image_rect->width = x2 - x1; + image_rect->height = y2 - y1; + + data = calloc (image_rect->width * image_rect->height * 4, 1); + image_surface = cairo_image_surface_create_for_data (data, + CAIRO_FORMAT_ARGB32, + image_rect->width, + image_rect->height, + image_rect->width * 4); + + *image_out = (cairo_image_surface_t *)image_surface; + *image_extra = data; + return CAIRO_STATUS_SUCCESS; + + return CAIRO_INT_STATUS_UNSUPPORTED; } +static CGImageRef +create_image_from_surface (cairo_image_surface_t *image_surface, void *data) +{ + CGImageRef image; + CGColorSpaceRef color_space; + CGDataProviderRef data_provider; + int width, height; + + width = cairo_image_surface_get_width ((cairo_surface_t *)image_surface); + height = cairo_image_surface_get_height ((cairo_surface_t *)image_surface); + + color_space = CGColorSpaceCreateDeviceRGB(); + data_provider = CGDataProviderCreateWithData (NULL, data, + width * height * 4, NULL); + image = CGImageCreate (width, height, + 8, 32, + width * 4, + color_space, + kCGImageAlphaPremultipliedFirst, + data_provider, + NULL, + FALSE, kCGRenderingIntentDefault); + + CGColorSpaceRelease (color_space); + CGDataProviderRelease (data_provider); + + return image; +} static void -_cairo_quartz_surface_release_dest_image(void *abstract_surface, - cairo_rectangle_int16_t * - intersect_rect, - cairo_image_surface_t * image, - cairo_rectangle_int16_t * image_rect, - void *image_extra) +_cairo_quartz_surface_release_dest_image(void *abstract_surface, + cairo_rectangle_int16_t *intersect_rect, + cairo_image_surface_t *image, + cairo_rectangle_int16_t *image_rect, + void *image_extra) { cairo_quartz_surface_t *surface = abstract_surface; + CGImageRef image_ref; + CGRect rect; - if (surface->image == image) { - CGRect rect; + image_ref = create_image_from_surface (image, image_extra); - rect = CGRectMake(0, 0, surface->width, surface->height); + rect = CGRectMake (image_rect->x, image_rect->y, image_rect->width, image_rect->height); - if (surface->flipped) { - CGContextSaveGState (surface->context); - CGContextTranslateCTM (surface->context, 0, surface->height); - CGContextScaleCTM (surface->context, 1, -1); - } - - CGContextDrawImage(surface->context, rect, surface->cgImage); - - if (surface->flipped) - CGContextRestoreGState (surface->context); - - memset(surface->image->data, 0, surface->width * surface->height * 4); + if (surface->y_grows_down) { + CGContextSaveGState (surface->context); + CGContextTranslateCTM (surface->context, 0, image_rect->height + 2 * image_rect->y); + CGContextScaleCTM (surface->context, 1, -1); } + + CGContextDrawImage(surface->context, rect, image_ref); + CFRelease (image_ref); + + if (surface->y_grows_down) { + CGContextRestoreGState (surface->context); + } + + cairo_surface_destroy ((cairo_surface_t *)image); + free (image_extra); } static cairo_int_status_t @@ -185,33 +181,26 @@ _cairo_quartz_surface_set_clip_region(void *abstract_surface, pixman_region16_t * region) { cairo_quartz_surface_t *surface = abstract_surface; - unsigned int serial; - serial = _cairo_surface_allocate_clip_serial (&surface->image->base); + if (surface->clip_region) + pixman_region_destroy (surface->clip_region); - if (surface->clip_region) - pixman_region_destroy (surface->clip_region); - - if (region) { - surface->clip_region = pixman_region_create (); - pixman_region_copy (surface->clip_region, region); - } else - surface->clip_region = NULL; - - return _cairo_surface_set_clip_region(&surface->image->base, - region, serial); + if (region) { + surface->clip_region = pixman_region_create (); + pixman_region_copy (surface->clip_region, region); + } else + surface->clip_region = NULL; + + return CAIRO_STATUS_SUCCESS; } static cairo_int_status_t -_cairo_quartz_surface_get_extents (void *abstract_surface, - cairo_rectangle_int16_t * rectangle) +_cairo_quartz_surface_get_extents (void *abstract_surface, + cairo_rectangle_int16_t *rectangle) { cairo_quartz_surface_t *surface = abstract_surface; - rectangle->x = 0; - rectangle->y = 0; - rectangle->width = surface->width; - rectangle->height = surface->height; + *rectangle = surface->extents; return CAIRO_STATUS_SUCCESS; } @@ -236,12 +225,13 @@ static const struct _cairo_surface_backend cairo_quartz_surface_backend = { NULL /* old_show_glyphs */ }; - cairo_surface_t *cairo_quartz_surface_create(CGContextRef context, - cairo_bool_t flipped, - int width, int height) + int width, + int height, + cairo_bool_t y_grows_down) { cairo_quartz_surface_t *surface; + CGRect clip_box; surface = malloc(sizeof(cairo_quartz_surface_t)); if (surface == NULL) { @@ -249,20 +239,19 @@ cairo_surface_t *cairo_quartz_surface_create(CGContextRef context, return (cairo_surface_t*) &_cairo_surface_nil; } + /* XXX: The content value here might be totally wrong. */ _cairo_surface_init(&surface->base, &cairo_quartz_surface_backend, - CAIRO_CONTENT_COLOR_ALPHA); + CAIRO_CONTENT_COLOR_ALPHA); surface->context = context; - surface->width = width; - surface->height = height; - surface->image = NULL; - surface->cgImage = NULL; - surface->clip_region = NULL; - surface->flipped = flipped; + surface->clip_region = NULL; + surface->y_grows_down = y_grows_down; - /* Set up the image surface which Cairo draws into and we blit to & from. */ - void *foo; - _cairo_quartz_surface_acquire_source_image(surface, &surface->image, &foo); + clip_box = CGContextGetClipBoundingBox (context); + surface->extents.x = clip_box.origin.x; + surface->extents.y = clip_box.origin.y; + surface->extents.width = clip_box.size.width; + surface->extents.height = clip_box.size.height; return (cairo_surface_t *) surface; } diff --git a/gfx/cairo/cairo/src/cairo-rename.h b/gfx/cairo/cairo/src/cairo-rename.h index 82a7f5b33a83..acb4bf852702 100644 --- a/gfx/cairo/cairo/src/cairo-rename.h +++ b/gfx/cairo/cairo/src/cairo-rename.h @@ -1,3 +1,8 @@ +#define _cairo_pdf_test_force_fallbacks _moz__cairo_pdf_test_force_fallbacks +#define _cairo_ps_test_force_fallbacks _moz__cairo_ps_test_force_fallbacks +#define _cairo_scaled_font_test_set_max_glyphs_cached_per_font _moz__cairo_scaled_font_test_set_max_glyphs_cached_per_font +#define _cairo_svg_test_force_fallbacks _moz__cairo_svg_test_force_fallbacks +#define _cairo_xlib_test_disable_render _moz__cairo_xlib_test_disable_render #define cairo_append_path _moz_cairo_append_path #define cairo_arc _moz_cairo_arc #define cairo_arc_negative _moz_cairo_arc_negative @@ -6,8 +11,10 @@ #define cairo_beos_surface_create _moz_cairo_beos_surface_create #define cairo_beos_surface_create_for_bitmap _moz_cairo_beos_surface_create_for_bitmap #define cairo_clip _moz_cairo_clip +#define cairo_clip_extents _moz_cairo_clip_extents #define cairo_clip_preserve _moz_cairo_clip_preserve #define cairo_close_path _moz_cairo_close_path +#define cairo_copy_clip_rectangles _moz_cairo_copy_clip_rectangles #define cairo_copy_page _moz_cairo_copy_page #define cairo_copy_path _moz_cairo_copy_path #define cairo_copy_path_flat _moz_cairo_copy_path_flat @@ -22,7 +29,7 @@ #define cairo_destroy _moz_cairo_destroy #define cairo_device_to_user _moz_cairo_device_to_user #define cairo_device_to_user_distance _moz_cairo_device_to_user_distance -#define cairo_extract_clip_rectangles _moz_cairo_extract_clip_rectangles +#define cairo_directfb_surface_create _moz_cairo_directfb_surface_create #define cairo_fill _moz_cairo_fill #define cairo_fill_extents _moz_cairo_fill_extents #define cairo_fill_preserve _moz_cairo_fill_preserve @@ -55,6 +62,8 @@ #define cairo_ft_scaled_font_unlock_face _moz_cairo_ft_scaled_font_unlock_face #define cairo_get_antialias _moz_cairo_get_antialias #define cairo_get_current_point _moz_cairo_get_current_point +#define cairo_get_dash _moz_cairo_get_dash +#define cairo_get_dash_count _moz_cairo_get_dash_count #define cairo_get_fill_rule _moz_cairo_get_fill_rule #define cairo_get_font_face _moz_cairo_get_font_face #define cairo_get_font_matrix _moz_cairo_get_font_matrix @@ -72,7 +81,6 @@ #define cairo_glitz_surface_create _moz_cairo_glitz_surface_create #define cairo_glyph_extents _moz_cairo_glyph_extents #define cairo_glyph_path _moz_cairo_glyph_path -#define cairo_has_clip _moz_cairo_has_clip #define cairo_identity_matrix _moz_cairo_identity_matrix #define cairo_image_surface_create _moz_cairo_image_surface_create #define cairo_image_surface_create_for_data _moz_cairo_image_surface_create_for_data @@ -103,6 +111,18 @@ #define cairo_move_to _moz_cairo_move_to #define cairo_new_path _moz_cairo_new_path #define cairo_new_sub_path _moz_cairo_new_sub_path +#define cairo_nquartz_surface_create _moz_cairo_nquartz_surface_create +#define cairo_nquartz_surface_create_for_agl_context _moz_cairo_nquartz_surface_create_for_agl_context +#define cairo_nquartz_surface_create_for_cg_context _moz_cairo_nquartz_surface_create_for_cg_context +#define cairo_nquartz_surface_get_cg_context _moz_cairo_nquartz_surface_get_cg_context +#define cairo_os2_fini _moz_cairo_os2_fini +#define cairo_os2_init _moz_cairo_os2_init +#define cairo_os2_surface_create _moz_cairo_os2_surface_create +#define cairo_os2_surface_get_manual_window_refresh _moz_cairo_os2_surface_get_manual_window_refresh +#define cairo_os2_surface_refresh_window _moz_cairo_os2_surface_refresh_window +#define cairo_os2_surface_set_hwnd _moz_cairo_os2_surface_set_hwnd +#define cairo_os2_surface_set_manual_window_refresh _moz_cairo_os2_surface_set_manual_window_refresh +#define cairo_os2_surface_set_size _moz_cairo_os2_surface_set_size #define cairo_paint _moz_cairo_paint #define cairo_paint_with_alpha _moz_cairo_paint_with_alpha #define cairo_path_destroy _moz_cairo_path_destroy @@ -114,9 +134,15 @@ #define cairo_pattern_create_rgb _moz_cairo_pattern_create_rgb #define cairo_pattern_create_rgba _moz_cairo_pattern_create_rgba #define cairo_pattern_destroy _moz_cairo_pattern_destroy +#define cairo_pattern_get_color_stop_count _moz_cairo_pattern_get_color_stop_count +#define cairo_pattern_get_color_stop_rgba _moz_cairo_pattern_get_color_stop_rgba #define cairo_pattern_get_extend _moz_cairo_pattern_get_extend #define cairo_pattern_get_filter _moz_cairo_pattern_get_filter +#define cairo_pattern_get_linear_points _moz_cairo_pattern_get_linear_points #define cairo_pattern_get_matrix _moz_cairo_pattern_get_matrix +#define cairo_pattern_get_radial_circles _moz_cairo_pattern_get_radial_circles +#define cairo_pattern_get_rgba _moz_cairo_pattern_get_rgba +#define cairo_pattern_get_surface _moz_cairo_pattern_get_surface #define cairo_pattern_get_type _moz_cairo_pattern_get_type #define cairo_pattern_reference _moz_cairo_pattern_reference #define cairo_pattern_set_extend _moz_cairo_pattern_set_extend @@ -125,6 +151,7 @@ #define cairo_pattern_status _moz_cairo_pattern_status #define cairo_pdf_surface_create _moz_cairo_pdf_surface_create #define cairo_pdf_surface_create_for_stream _moz_cairo_pdf_surface_create_for_stream +#define cairo_pdf_surface_set_size _moz_cairo_pdf_surface_set_size #define cairo_pop_group _moz_cairo_pop_group #define cairo_pop_group_to_source _moz_cairo_pop_group_to_source #define cairo_profile_surface_create _moz_cairo_profile_surface_create @@ -139,6 +166,7 @@ #define cairo_push_group_with_content _moz_cairo_push_group_with_content #define cairo_quartz_surface_create _moz_cairo_quartz_surface_create #define cairo_rectangle _moz_cairo_rectangle +#define cairo_rectangle_list_destroy _moz_cairo_rectangle_list_destroy #define cairo_reference _moz_cairo_reference #define cairo_rel_curve_to _moz_cairo_rel_curve_to #define cairo_rel_line_to _moz_cairo_rel_line_to @@ -198,6 +226,7 @@ #define cairo_surface_get_font_options _moz_cairo_surface_get_font_options #define cairo_surface_get_type _moz_cairo_surface_get_type #define cairo_surface_get_user_data _moz_cairo_surface_get_user_data +#define cairo_surface_is_nquartz _moz_cairo_surface_is_nquartz #define cairo_surface_is_profile _moz_cairo_surface_is_profile #define cairo_surface_mark_dirty _moz_cairo_surface_mark_dirty #define cairo_surface_mark_dirty_rectangle _moz_cairo_surface_mark_dirty_rectangle diff --git a/gfx/cairo/cairo/src/cairo-scaled-font-subsets-private.h b/gfx/cairo/cairo/src/cairo-scaled-font-subsets-private.h index facbed8da6cc..d44ef5632ec1 100644 --- a/gfx/cairo/cairo/src/cairo-scaled-font-subsets-private.h +++ b/gfx/cairo/cairo/src/cairo-scaled-font-subsets-private.h @@ -50,7 +50,7 @@ typedef struct _cairo_scaled_font_subset { * Value of glyphs array is scaled_font_glyph_index. */ unsigned long *glyphs; - int num_glyphs; + unsigned int num_glyphs; } cairo_scaled_font_subset_t; /** @@ -187,6 +187,8 @@ typedef struct _cairo_truetype_subset { long ascent, descent; char *data; unsigned long data_length; + unsigned long *string_offsets; + unsigned long num_string_offsets; } cairo_truetype_subset_t; /** @@ -237,6 +239,7 @@ typedef struct _cairo_type1_subset { * _cairo_type1_subset_init: * @type1_subset: a #cairo_type1_subset_t to initialize * @font_subset: the #cairo_scaled_font_subset_t to initialize from + * @hex_encode: if true the encrypted portion of the font is hex encoded * * If possible (depending on the format of the underlying * cairo_scaled_font_t and the font backend in use) generate a type1 @@ -251,7 +254,8 @@ typedef struct _cairo_type1_subset { cairo_private cairo_status_t _cairo_type1_subset_init (cairo_type1_subset_t *type_subset, const char *name, - cairo_scaled_font_subset_t *font_subset); + cairo_scaled_font_subset_t *font_subset, + cairo_bool_t hex_encode); /** * _cairo_type1_subset_fini: @@ -264,4 +268,35 @@ _cairo_type1_subset_init (cairo_type1_subset_t *type_subset, cairo_private void _cairo_type1_subset_fini (cairo_type1_subset_t *subset); +/** + * _cairo_type1_fallback_init: + * @type1_subset: a #cairo_type1_subset_t to initialize + * @font_subset: the #cairo_scaled_font_subset_t to initialize from + * + * If possible (depending on the format of the underlying + * cairo_scaled_font_t and the font backend in use) generate a type1 + * file corresponding to @font_subset and initialize @type1_subset + * with information about the subset and the type1 data. + * + * Return value: CAIRO_STATUS_SUCCESS if successful, + * CAIRO_INT_STATUS_UNSUPPORTED if the font can't be subset as a type1 + * file, or an non-zero value indicating an error. Possible errors + * include CAIRO_STATUS_NO_MEMORY. + **/ +cairo_private cairo_status_t +_cairo_type1_fallback_init (cairo_type1_subset_t *type_subset, + const char *name, + cairo_scaled_font_subset_t *font_subset); + +/** + * _cairo_type1_fallback_fini: + * @type1_subset: a #cairo_type1_subset_t + * + * Free all resources associated with @type1_subset. After this call, + * @type1_subset should not be used again without a subsequent call to + * _cairo_truetype_type1_init() again first. + **/ +cairo_private void +_cairo_type1_fallback_fini (cairo_type1_subset_t *subset); + #endif /* CAIRO_SCALED_FONT_SUBSETS_PRIVATE_H */ diff --git a/gfx/cairo/cairo/src/cairo-scaled-font-subsets.c b/gfx/cairo/cairo/src/cairo-scaled-font-subsets.c index 112925cd103e..0c428e7c3afd 100644 --- a/gfx/cairo/cairo/src/cairo-scaled-font-subsets.c +++ b/gfx/cairo/cairo/src/cairo-scaled-font-subsets.c @@ -73,9 +73,9 @@ typedef struct _cairo_sub_font_glyph { typedef struct _cairo_sub_font_collection { unsigned long *glyphs; /* scaled_font_glyph_index */ - int glyphs_size; - int max_glyph; - int num_glyphs; + unsigned int glyphs_size; + unsigned int max_glyph; + unsigned int num_glyphs; unsigned int subset_id; diff --git a/gfx/cairo/cairo/src/cairo-scaled-font.c b/gfx/cairo/cairo/src/cairo-scaled-font.c index 50f4875a865d..47e96e5face6 100644 --- a/gfx/cairo/cairo/src/cairo-scaled-font.c +++ b/gfx/cairo/cairo/src/cairo-scaled-font.c @@ -1,4 +1,4 @@ -/* $Id: cairo-scaled-font.c,v 1.10 2006/07/13 20:19:37 vladimir%pobox.com Exp $ +/* $Id: cairo-scaled-font.c,v 1.11 2006/09/26 22:21:55 vladimir%pobox.com Exp $ * * Copyright © 2005 Keith Packard * @@ -74,7 +74,7 @@ _cairo_scaled_glyph_destroy (void *abstract_glyph) static const cairo_scaled_font_t _cairo_scaled_font_nil = { { 0 }, /* hash_entry */ CAIRO_STATUS_NO_MEMORY, /* status */ - -1, /* ref_count */ + CAIRO_REF_COUNT_INVALID, /* ref_count */ NULL, /* font_face */ { 1., 0., 0., 1., 0, 0}, /* font_matrix */ { 1., 0., 0., 1., 0, 0}, /* ctm */ @@ -123,7 +123,10 @@ _cairo_scaled_font_set_error (cairo_scaled_font_t *scaled_font, * cairo_scaled_font_get_type: * @scaled_font: a #cairo_scaled_font_t * - * Return value: The type of @scaled_font. See #cairo_font_type_t. + * This function returns the type of the backend used to create + * a scaled font. See #cairo_font_type_t for available types. + * + * Return value: The type of @scaled_font. * * Since: 1.2 **/ @@ -223,13 +226,15 @@ void _cairo_scaled_font_map_destroy (void) { int i; - cairo_scaled_font_map_t *font_map = cairo_scaled_font_map; + cairo_scaled_font_map_t *font_map; cairo_scaled_font_t *scaled_font; - if (font_map == NULL) - return; + CAIRO_MUTEX_LOCK (cairo_scaled_font_map_mutex); - CAIRO_MUTEX_UNLOCK (cairo_scaled_font_map_mutex); + font_map = cairo_scaled_font_map; + if (font_map == NULL) { + goto CLEANUP_MUTEX_LOCK; + } for (i = 0; i < font_map->num_holdovers; i++) { scaled_font = font_map->holdovers[i]; @@ -247,6 +252,9 @@ _cairo_scaled_font_map_destroy (void) free (cairo_scaled_font_map); cairo_scaled_font_map = NULL; + + CLEANUP_MUTEX_LOCK: + CAIRO_MUTEX_UNLOCK (cairo_scaled_font_map_mutex); } /* Fowler / Noll / Vo (FNV) Hash (http://www.isthe.com/chongo/tech/comp/fnv/) @@ -490,6 +498,7 @@ UNWIND_FONT_MAP_LOCK: UNWIND: return NULL; } +slim_hidden_def (cairo_scaled_font_create); /** * cairo_scaled_font_reference: @@ -510,7 +519,7 @@ cairo_scaled_font_reference (cairo_scaled_font_t *scaled_font) if (scaled_font == NULL) return NULL; - if (scaled_font->ref_count == (unsigned int)-1) + if (scaled_font->ref_count == CAIRO_REF_COUNT_INVALID) return scaled_font; /* We would normally assert (scaled_font->ref_count > 0) here, but @@ -548,6 +557,7 @@ cairo_scaled_font_reference (cairo_scaled_font_t *scaled_font) return scaled_font; } +slim_hidden_def (cairo_scaled_font_reference); /** * cairo_scaled_font_destroy: @@ -565,7 +575,7 @@ cairo_scaled_font_destroy (cairo_scaled_font_t *scaled_font) if (scaled_font == NULL) return; - if (scaled_font->ref_count == (unsigned int)-1) + if (scaled_font->ref_count == CAIRO_REF_COUNT_INVALID) return; /* cairo_scaled_font_t objects are cached and shared between @@ -608,6 +618,7 @@ cairo_scaled_font_destroy (cairo_scaled_font_t *scaled_font) } _cairo_scaled_font_map_unlock (); } +slim_hidden_def (cairo_scaled_font_destroy); /* Public font API follows. */ @@ -624,6 +635,7 @@ cairo_scaled_font_extents (cairo_scaled_font_t *scaled_font, { *extents = scaled_font->extents; } +slim_hidden_def (cairo_scaled_font_extents); /** * cairo_scaled_font_text_extents: @@ -749,6 +761,7 @@ cairo_scaled_font_glyph_extents (cairo_scaled_font_t *scaled_font, extents->x_advance = x_pos - glyphs[0].x; extents->y_advance = y_pos - glyphs[0].y; } +slim_hidden_def (cairo_scaled_font_glyph_extents); cairo_status_t _cairo_scaled_font_text_to_glyphs (cairo_scaled_font_t *scaled_font, @@ -758,7 +771,7 @@ _cairo_scaled_font_text_to_glyphs (cairo_scaled_font_t *scaled_font, cairo_glyph_t **glyphs, int *num_glyphs) { - size_t i; + int i; uint32_t *ucs4 = NULL; cairo_status_t status = CAIRO_STATUS_SUCCESS; cairo_scaled_glyph_t *scaled_glyph; @@ -1049,6 +1062,74 @@ _scaled_glyph_path_close_path (void *abstract_closure) return _cairo_path_fixed_close_path (closure->path); } + +/** + * _trace_mask_to_path: + * @bitmap: An alpha mask (either CAIRO_FORMAT_A1 or _A8) + * @path: An initialized path to hold the result + * + * Given a mask surface, (an alpha image), fill out the provided path + * so that when filled it would result in something that approximates + * the mask. + * + * Note: The current tracing code here is extremely primitive. It + * operates only on an A1 surface, (converting an A8 surface to A1 if + * necessary), and performs the tracing by drawing a little square + * around each pixel that is on in the mask. We do not pretend that + * this is a high-quality result. But we are leaving it up to somone + * who cares enough about getting a better result to implement + * something more sophisticated. + **/ +static cairo_status_t +_trace_mask_to_path (cairo_image_surface_t *mask, + cairo_path_fixed_t *path) +{ + cairo_image_surface_t *a1_mask; + unsigned char *row, *byte_ptr, byte; + int rows, cols, bytes_per_row; + int x, y, bit; + double xoff, yoff; + + if (mask->format == CAIRO_FORMAT_A1) + a1_mask = mask; + else + a1_mask = _cairo_image_surface_clone (mask, CAIRO_FORMAT_A1); + + if (cairo_surface_status (&a1_mask->base)) + return cairo_surface_status (&a1_mask->base); + + cairo_surface_get_device_offset (&mask->base, &xoff, &yoff); + + bytes_per_row = (a1_mask->width + 7) / 8; + for (y = 0, row = a1_mask->data, rows = a1_mask->height; rows; row += a1_mask->stride, rows--, y++) { + for (x = 0, byte_ptr = row, cols = (a1_mask->width + 7) / 8; cols; byte_ptr++, cols--) { + byte = CAIRO_BITSWAP8_IF_LITTLE_ENDIAN (*byte_ptr); + for (bit = 7; bit >= 0 && x < a1_mask->width; bit--, x++) { + if (byte & (1 << bit)) { + _cairo_path_fixed_move_to (path, + _cairo_fixed_from_int (x + xoff), + _cairo_fixed_from_int (y + yoff)); + _cairo_path_fixed_rel_line_to (path, + _cairo_fixed_from_int (1), + _cairo_fixed_from_int (0)); + _cairo_path_fixed_rel_line_to (path, + _cairo_fixed_from_int (0), + _cairo_fixed_from_int (1)); + _cairo_path_fixed_rel_line_to (path, + _cairo_fixed_from_int (-1), + _cairo_fixed_from_int (0)); + _cairo_path_fixed_close_path (path); + } + } + } + } + + if (a1_mask != mask) + cairo_surface_destroy (&a1_mask->base); + + return CAIRO_STATUS_SUCCESS; +} + cairo_status_t _cairo_scaled_font_glyph_path (cairo_scaled_font_t *scaled_font, const cairo_glyph_t *glyphs, @@ -1058,6 +1139,7 @@ _cairo_scaled_font_glyph_path (cairo_scaled_font_t *scaled_font, cairo_status_t status; int i; cairo_scaled_glyph_path_closure_t closure; + cairo_path_fixed_t *glyph_path; if (scaled_font->status) return scaled_font->status; @@ -1070,19 +1152,42 @@ _cairo_scaled_font_glyph_path (cairo_scaled_font_t *scaled_font, glyphs[i].index, CAIRO_SCALED_GLYPH_INFO_PATH, &scaled_glyph); - if (status) + if (status == CAIRO_STATUS_SUCCESS) + glyph_path = scaled_glyph->path; + else if (status != CAIRO_INT_STATUS_UNSUPPORTED) return status; + /* If the font is incapable of providing a path, then we'll + * have to trace our own from a surface. */ + if (status == CAIRO_INT_STATUS_UNSUPPORTED) { + status = _cairo_scaled_glyph_lookup (scaled_font, + glyphs[i].index, + CAIRO_SCALED_GLYPH_INFO_SURFACE, + &scaled_glyph); + + glyph_path = _cairo_path_fixed_create (); + if (glyph_path == NULL) + return CAIRO_STATUS_NO_MEMORY; + + status = _trace_mask_to_path (scaled_glyph->surface, glyph_path); + if (status) { + _cairo_path_fixed_destroy (glyph_path); + return status; + } + } + closure.offset.x = _cairo_fixed_from_double (glyphs[i].x); closure.offset.y = _cairo_fixed_from_double (glyphs[i].y); - status = _cairo_path_fixed_interpret (scaled_glyph->path, + status = _cairo_path_fixed_interpret (glyph_path, CAIRO_DIRECTION_FORWARD, _scaled_glyph_path_move_to, _scaled_glyph_path_line_to, _scaled_glyph_path_curve_to, _scaled_glyph_path_close_path, &closure); + if (glyph_path != scaled_glyph->path) + _cairo_path_fixed_destroy (glyph_path); } return CAIRO_STATUS_SUCCESS; @@ -1152,9 +1257,9 @@ _cairo_scaled_glyph_set_metrics (cairo_scaled_glyph_t *scaled_glyph, scaled_glyph->metrics.x_advance = fs_metrics->x_advance; scaled_glyph->metrics.y_advance = fs_metrics->y_advance; - cairo_matrix_transform_point (&scaled_font->font_matrix, - &scaled_glyph->metrics.x_advance, - &scaled_glyph->metrics.y_advance); + cairo_matrix_transform_distance (&scaled_font->font_matrix, + &scaled_glyph->metrics.x_advance, + &scaled_glyph->metrics.y_advance); scaled_glyph->bbox.p1.x = _cairo_fixed_from_double (min_device_x); scaled_glyph->bbox.p1.y = _cairo_fixed_from_double (min_device_y); @@ -1298,6 +1403,8 @@ _cairo_scaled_glyph_lookup (cairo_scaled_font_t *scaled_font, * cairo_scaled_font_get_font_face: * @scaled_font: a #cairo_scaled_font_t * + * Gets the font face that this scaled font was created for. + * * Return value: The #cairo_font_face_t with which @scaled_font was * created. * @@ -1311,6 +1418,7 @@ cairo_scaled_font_get_font_face (cairo_scaled_font_t *scaled_font) return scaled_font->font_face; } +slim_hidden_def (cairo_scaled_font_get_font_face); /** * cairo_scaled_font_get_font_matrix: @@ -1333,6 +1441,7 @@ cairo_scaled_font_get_font_matrix (cairo_scaled_font_t *scaled_font, *font_matrix = scaled_font->font_matrix; } +slim_hidden_def (cairo_scaled_font_get_font_matrix); /** * cairo_scaled_font_get_ctm: @@ -1354,6 +1463,7 @@ cairo_scaled_font_get_ctm (cairo_scaled_font_t *scaled_font, *ctm = scaled_font->ctm; } +slim_hidden_def (cairo_scaled_font_get_ctm); /** * cairo_scaled_font_get_font_options: @@ -1376,3 +1486,4 @@ cairo_scaled_font_get_font_options (cairo_scaled_font_t *scaled_font, _cairo_font_options_init_copy (options, &scaled_font->options); } +slim_hidden_def (cairo_scaled_font_get_font_options); diff --git a/gfx/cairo/cairo/src/cairo-surface.c b/gfx/cairo/cairo/src/cairo-surface.c index e01c2c9e1638..cbbe89a0acdc 100644 --- a/gfx/cairo/cairo/src/cairo-surface.c +++ b/gfx/cairo/cairo/src/cairo-surface.c @@ -45,7 +45,7 @@ const cairo_surface_t _cairo_surface_nil = { &cairo_image_surface_backend, /* backend */ CAIRO_SURFACE_TYPE_IMAGE, CAIRO_CONTENT_COLOR, - -1, /* ref_count */ + CAIRO_REF_COUNT_INVALID, /* ref_count */ CAIRO_STATUS_NO_MEMORY, /* status */ FALSE, /* finished */ { 0, /* size */ @@ -63,15 +63,23 @@ const cairo_surface_t _cairo_surface_nil = { }, /* device_transform_inverse */ 0.0, /* x_fallback_resolution */ 0.0, /* y_fallback_resolution */ + NULL, /* clip */ 0, /* next_clip_serial */ - 0 /* current_clip_serial */ + 0, /* current_clip_serial */ + FALSE, /* is_snapshot */ + FALSE, /* has_font_options */ + { CAIRO_ANTIALIAS_DEFAULT, + CAIRO_SUBPIXEL_ORDER_DEFAULT, + CAIRO_HINT_STYLE_DEFAULT, + CAIRO_HINT_METRICS_DEFAULT + } /* font_options */ }; const cairo_surface_t _cairo_surface_nil_file_not_found = { &cairo_image_surface_backend, /* backend */ CAIRO_SURFACE_TYPE_IMAGE, CAIRO_CONTENT_COLOR, - -1, /* ref_count */ + CAIRO_REF_COUNT_INVALID, /* ref_count */ CAIRO_STATUS_FILE_NOT_FOUND, /* status */ FALSE, /* finished */ { 0, /* size */ @@ -89,15 +97,23 @@ const cairo_surface_t _cairo_surface_nil_file_not_found = { }, /* device_transform_inverse */ 0.0, /* x_fallback_resolution */ 0.0, /* y_fallback_resolution */ + NULL, /* clip */ 0, /* next_clip_serial */ - 0 /* current_clip_serial */ + 0, /* current_clip_serial */ + FALSE, /* is_snapshot */ + FALSE, /* has_font_options */ + { CAIRO_ANTIALIAS_DEFAULT, + CAIRO_SUBPIXEL_ORDER_DEFAULT, + CAIRO_HINT_STYLE_DEFAULT, + CAIRO_HINT_METRICS_DEFAULT + } /* font_options */ }; const cairo_surface_t _cairo_surface_nil_read_error = { &cairo_image_surface_backend, /* backend */ CAIRO_SURFACE_TYPE_IMAGE, CAIRO_CONTENT_COLOR, - -1, /* ref_count */ + CAIRO_REF_COUNT_INVALID, /* ref_count */ CAIRO_STATUS_READ_ERROR, /* status */ FALSE, /* finished */ { 0, /* size */ @@ -115,8 +131,16 @@ const cairo_surface_t _cairo_surface_nil_read_error = { }, /* device_transform_inverse */ 0.0, /* x_fallback_resolution */ 0.0, /* y_fallback_resolution */ + NULL, /* clip */ 0, /* next_clip_serial */ - 0 /* current_clip_serial */ + 0, /* current_clip_serial */ + FALSE, /* is_snapshot */ + FALSE, /* has_font_options */ + { CAIRO_ANTIALIAS_DEFAULT, + CAIRO_SUBPIXEL_ORDER_DEFAULT, + CAIRO_HINT_STYLE_DEFAULT, + CAIRO_HINT_METRICS_DEFAULT + } /* font_options */ }; static void @@ -157,7 +181,10 @@ _cairo_surface_set_error (cairo_surface_t *surface, * cairo_surface_get_type: * @surface: a #cairo_surface_t * - * Return value: The type of @surface. See #cairo_surface_type_t. + * This function returns the type of the backend used to create + * a surface. See #cairo_surface_type_t for available types. + * + * Return value: The type of @surface. * * Since: 1.2 **/ @@ -170,6 +197,7 @@ cairo_surface_get_type (cairo_surface_t *surface) * surface. */ return surface->type; } +slim_hidden_def (cairo_surface_get_type); /** * cairo_surface_get_content: @@ -205,6 +233,7 @@ cairo_surface_status (cairo_surface_t *surface) { return surface->status; } +slim_hidden_def (cairo_surface_status); void _cairo_surface_init (cairo_surface_t *surface, @@ -234,6 +263,8 @@ _cairo_surface_init (cairo_surface_t *surface, surface->current_clip_serial = 0; surface->is_snapshot = FALSE; + + surface->has_font_options = FALSE; } cairo_surface_t * @@ -242,15 +273,28 @@ _cairo_surface_create_similar_scratch (cairo_surface_t *other, int width, int height) { + cairo_surface_t *surface = NULL; + cairo_font_options_t options; + cairo_format_t format = _cairo_format_from_content (content); if (other->status) return (cairo_surface_t*) &_cairo_surface_nil; if (other->backend->create_similar) - return other->backend->create_similar (other, content, width, height); - else - return cairo_image_surface_create (format, width, height); + surface = other->backend->create_similar (other, content, width, height); + + if (!surface) + surface = cairo_image_surface_create (format, width, height); + + cairo_surface_get_font_options (other, &options); + _cairo_surface_set_font_options (surface, &options); + + cairo_surface_set_fallback_resolution (surface, + other->x_fallback_resolution, + other->y_fallback_resolution); + + return surface; } /** @@ -261,9 +305,12 @@ _cairo_surface_create_similar_scratch (cairo_surface_t *other, * @height: height of the new surface (in device-space units) * * Create a new surface that is as compatible as possible with an - * existing surface. The new surface will use the same backend as - * @other unless that is not possible for some reason. The type of the - * returned surface may be examined with cairo_surface_get_type(). + * existing surface. For example the new surface will have the same + * fallback resolution and font options as @other. Generally, the new + * surface will also use the same backend as @other, unless that is + * not possible for some reason. The type of the returned surface may + * be examined with cairo_surface_get_type(). + * * Initially the surface contents are all 0 (transparent if contents * have transparency, black otherwise.) * @@ -293,6 +340,7 @@ cairo_surface_create_similar (cairo_surface_t *other, width, height, CAIRO_COLOR_TRANSPARENT); } +slim_hidden_def (cairo_surface_create_similar); cairo_surface_t * _cairo_surface_create_similar_solid (cairo_surface_t *other, @@ -362,7 +410,7 @@ cairo_surface_reference (cairo_surface_t *surface) if (surface == NULL) return NULL; - if (surface->ref_count == (unsigned int)-1) + if (surface->ref_count == CAIRO_REF_COUNT_INVALID) return surface; assert (surface->ref_count > 0); @@ -371,6 +419,7 @@ cairo_surface_reference (cairo_surface_t *surface) return surface; } +slim_hidden_def (cairo_surface_reference); /** * cairo_surface_destroy: @@ -386,7 +435,7 @@ cairo_surface_destroy (cairo_surface_t *surface) if (surface == NULL) return; - if (surface->ref_count == (unsigned int)-1) + if (surface->ref_count == CAIRO_REF_COUNT_INVALID) return; assert (surface->ref_count > 0); @@ -452,6 +501,7 @@ cairo_surface_finish (cairo_surface_t *surface) surface->finished = TRUE; } +slim_hidden_def (cairo_surface_finish); /** * cairo_surface_get_user_data: @@ -495,13 +545,40 @@ cairo_surface_set_user_data (cairo_surface_t *surface, void *user_data, cairo_destroy_func_t destroy) { - if (surface->ref_count == -1) + if (surface->ref_count == CAIRO_REF_COUNT_INVALID) return CAIRO_STATUS_NO_MEMORY; return _cairo_user_data_array_set_data (&surface->user_data, key, user_data, destroy); } +/** + * _cairo_surface_set_font_options: + * @surface: a #cairo_surface_t + * @options: a #cairo_font_options_t object that contains the + * options to use for this surface instead of backend's default + * font options. + * + * Sets the default font rendering options for the surface. + * This is useful to correctly propagate default font options when + * falling back to an image surface in a backend implementation. + * This affects the options returned in cairo_surface_get_font_options(). + * + * If @options is %NULL the surface options are reset to those of + * the backend default. + **/ +void +_cairo_surface_set_font_options (cairo_surface_t *surface, + cairo_font_options_t *options) +{ + if (options) { + surface->has_font_options = TRUE; + _cairo_font_options_init_copy (&surface->font_options, options); + } else { + surface->has_font_options = FALSE; + } +} + /** * cairo_surface_get_font_options: * @surface: a #cairo_surface_t @@ -518,12 +595,19 @@ void cairo_surface_get_font_options (cairo_surface_t *surface, cairo_font_options_t *options) { - if (!surface->finished && surface->backend->get_font_options) { - surface->backend->get_font_options (surface, options); - } else { - _cairo_font_options_init_default (options); + if (!surface->has_font_options) { + surface->has_font_options = TRUE; + + if (!surface->finished && surface->backend->get_font_options) { + surface->backend->get_font_options (surface, &surface->font_options); + } else { + _cairo_font_options_init_default (&surface->font_options); + } } + + _cairo_font_options_init_copy (options, &surface->font_options); } +slim_hidden_def (cairo_surface_get_font_options); /** * cairo_surface_flush: @@ -630,6 +714,7 @@ cairo_surface_mark_dirty_rectangle (cairo_surface_t *surface, _cairo_surface_set_error (surface, status); } } +slim_hidden_def (cairo_surface_mark_dirty_rectangle); /** * _cairo_surface_set_device_scale: @@ -712,6 +797,7 @@ cairo_surface_set_device_offset (cairo_surface_t *surface, surface->device_transform_inverse.x0 = - x_offset; surface->device_transform_inverse.y0 = - y_offset; } +slim_hidden_def (cairo_surface_set_device_offset); /** * cairo_surface_get_device_offset: @@ -732,6 +818,7 @@ cairo_surface_get_device_offset (cairo_surface_t *surface, *x_offset = surface->device_transform.x0; *y_offset = surface->device_transform.y0; } +slim_hidden_def (cairo_surface_get_device_offset); /** * cairo_surface_set_fallback_resolution: @@ -771,6 +858,7 @@ cairo_surface_set_fallback_resolution (cairo_surface_t *surface, surface->x_fallback_resolution = x_pixels_per_inch; surface->y_fallback_resolution = y_pixels_per_inch; } +slim_hidden_def (cairo_surface_set_fallback_resolution); cairo_bool_t _cairo_surface_has_device_transform (cairo_surface_t *surface) @@ -1702,9 +1790,9 @@ _cairo_surface_show_glyphs (cairo_surface_t *surface, cairo_scaled_font_t *scaled_font) { cairo_status_t status; - cairo_glyph_t *dev_glyphs = (cairo_glyph_t*) glyphs; cairo_scaled_font_t *dev_scaled_font = scaled_font; cairo_pattern_union_t dev_source; + cairo_matrix_t font_matrix; assert (! surface->is_snapshot); @@ -1718,60 +1806,44 @@ _cairo_surface_show_glyphs (cairo_surface_t *surface, surface, &dev_source.base); - if (_cairo_surface_has_device_transform (surface)) + cairo_scaled_font_get_font_matrix (scaled_font, &font_matrix); + + if (_cairo_surface_has_device_transform (surface) && + ! _cairo_matrix_is_integer_translation (&surface->device_transform, NULL, NULL)) { - int i; + cairo_font_options_t *font_options; + cairo_matrix_t dev_ctm; - dev_glyphs = malloc (sizeof(cairo_glyph_t) * num_glyphs); - if (!dev_glyphs) - return CAIRO_STATUS_NO_MEMORY; + font_options = cairo_font_options_create (); - for (i = 0; i < num_glyphs; i++) { - dev_glyphs[i].index = glyphs[i].index; - dev_glyphs[i].x = glyphs[i].x; - dev_glyphs[i].y = glyphs[i].y; - cairo_matrix_transform_point (&surface->device_transform, - &dev_glyphs[i].x, - &dev_glyphs[i].y); - } - - if (! _cairo_matrix_is_integer_translation (&surface->device_transform, NULL, NULL)) { - cairo_font_options_t *font_options; - cairo_matrix_t font_matrix, dev_ctm; - - font_options = cairo_font_options_create (); - - cairo_scaled_font_get_font_matrix (scaled_font, &font_matrix); - cairo_scaled_font_get_ctm (scaled_font, &dev_ctm); - cairo_matrix_multiply (&dev_ctm, &dev_ctm, &surface->device_transform); - cairo_scaled_font_get_font_options (scaled_font, font_options); - dev_scaled_font = cairo_scaled_font_create (cairo_scaled_font_get_font_face (scaled_font), - &font_matrix, - &dev_ctm, - font_options); - cairo_font_options_destroy (font_options); - } + cairo_scaled_font_get_ctm (scaled_font, &dev_ctm); + cairo_matrix_multiply (&dev_ctm, &dev_ctm, &surface->device_transform); + cairo_scaled_font_get_font_options (scaled_font, font_options); + dev_scaled_font = cairo_scaled_font_create (cairo_scaled_font_get_font_face (scaled_font), + &font_matrix, + &dev_ctm, + font_options); + cairo_font_options_destroy (font_options); } if (surface->backend->show_glyphs) { status = surface->backend->show_glyphs (surface, op, &dev_source.base, - dev_glyphs, num_glyphs, + glyphs, num_glyphs, dev_scaled_font); if (status != CAIRO_INT_STATUS_UNSUPPORTED) goto FINISH; } status = _cairo_surface_fallback_show_glyphs (surface, op, &dev_source.base, - dev_glyphs, num_glyphs, + glyphs, num_glyphs, dev_scaled_font); FINISH: - if (dev_glyphs != glyphs) - free (dev_glyphs); - if (dev_scaled_font != scaled_font) cairo_scaled_font_destroy (dev_scaled_font); + _cairo_pattern_fini (&dev_source.base); + return status; } diff --git a/gfx/cairo/cairo/src/cairo-svg-surface.c b/gfx/cairo/cairo/src/cairo-svg-surface.c index b3915064a98f..d4c60b616132 100644 --- a/gfx/cairo/cairo/src/cairo-svg-surface.c +++ b/gfx/cairo/cairo/src/cairo-svg-surface.c @@ -42,7 +42,6 @@ #include "cairo-svg.h" #include "cairo-svg-test.h" #include "cairo-path-fixed-private.h" -#include "cairo-ft-private.h" #include "cairo-meta-surface-private.h" #include "cairo-paginated-surface-private.h" #include "cairo-scaled-font-subsets-private.h" @@ -290,7 +289,7 @@ cairo_svg_surface_restrict_to_version (cairo_surface_t *abstract_surface, return; } - if (version >= 0 && version < CAIRO_SVG_VERSION_LAST) + if (version < CAIRO_SVG_VERSION_LAST) surface->document->svg_version = version; } @@ -330,7 +329,7 @@ cairo_svg_get_versions (cairo_svg_version_t const **versions, const char * cairo_svg_version_to_string (cairo_svg_version_t version) { - if (version < 0 || version >= CAIRO_SVG_VERSION_LAST) + if (version >= CAIRO_SVG_VERSION_LAST) return NULL; return _cairo_svg_version_strings[version]; @@ -574,7 +573,11 @@ _cairo_svg_document_emit_bitmap_glyph_data (cairo_svg_document_t *document, return status; image = scaled_glyph->surface; - assert (image->format == CAIRO_FORMAT_A1); + if (image->format != CAIRO_FORMAT_A1) { + image = _cairo_image_surface_clone (image, CAIRO_FORMAT_A1); + if (cairo_surface_status (&image->base)) + return cairo_surface_status (&image->base); + } _cairo_output_stream_printf (document->xml_node_glyphs, "xml_node_glyphs, " transform", ">/n", &image->base.device_transform); @@ -593,6 +596,10 @@ _cairo_svg_document_emit_bitmap_glyph_data (cairo_svg_document_t *document, } } _cairo_output_stream_printf (document->xml_node_glyphs, "\n"); + + if (image != scaled_glyph->surface) + cairo_surface_destroy (&image->base); + return CAIRO_STATUS_SUCCESS; } @@ -626,7 +633,7 @@ _cairo_svg_document_emit_font_subset (cairo_scaled_font_subset_t *font_subset, void *closure) { cairo_svg_document_t *document = closure; - int i; + unsigned int i; for (i = 0; i < font_subset->num_glyphs; i++) { _cairo_svg_document_emit_glyph (document, @@ -898,7 +905,7 @@ emit_meta_surface (cairo_svg_document_t *document, cairo_output_stream_t *contents; cairo_meta_surface_t *meta; cairo_meta_snapshot_t *snapshot; - int num_elements; + unsigned int num_elements; unsigned int i, id; num_elements = document->meta_snapshots.num_elements; @@ -1100,7 +1107,7 @@ emit_pattern_stops (cairo_output_stream_t *output, double start_offset) { double offset; - int i; + unsigned int i; for (i = 0; i < pattern->n_stops; i++) { offset = start_offset + (1 - start_offset ) * @@ -1602,7 +1609,7 @@ _cairo_svg_surface_intersect_clip_path (void *dst, cairo_svg_surface_t *surface = dst; cairo_svg_document_t *document = surface->document; cairo_status_t status; - int i; + unsigned int i; if (path == NULL) { for (i = 0; i < surface->clip_level; i++) @@ -1638,10 +1645,11 @@ static void _cairo_svg_surface_get_font_options (void *abstract_surface, cairo_font_options_t *options) { - _cairo_font_options_init_default (options); + _cairo_font_options_init_default (options); - cairo_font_options_set_hint_style (options, CAIRO_HINT_STYLE_NONE); - cairo_font_options_set_hint_metrics (options, CAIRO_HINT_METRICS_OFF); + cairo_font_options_set_hint_style (options, CAIRO_HINT_STYLE_NONE); + cairo_font_options_set_hint_metrics (options, CAIRO_HINT_METRICS_OFF); + cairo_font_options_set_antialias (options, CAIRO_ANTIALIAS_GRAY); } static const cairo_surface_backend_t cairo_svg_surface_backend = { @@ -1795,8 +1803,7 @@ _cairo_svg_document_finish (cairo_svg_document_t *document) _cairo_output_stream_destroy (document->xml_node_glyphs); _cairo_output_stream_destroy (document->xml_node_defs); - status = _cairo_output_stream_get_status (output); - _cairo_output_stream_destroy (output); + status = _cairo_output_stream_destroy (output); for (i = 0; i < document->meta_snapshots.num_elements; i++) { snapshot = _cairo_array_index (&document->meta_snapshots, i); diff --git a/gfx/cairo/cairo/src/cairo-truetype-subset-private.h b/gfx/cairo/cairo/src/cairo-truetype-subset-private.h new file mode 100644 index 000000000000..51bf906d166c --- /dev/null +++ b/gfx/cairo/cairo/src/cairo-truetype-subset-private.h @@ -0,0 +1,170 @@ +/* cairo - a vector graphics library with display and print output + * + * Copyright © 2006 Red Hat, Inc + * + * This library is free software; you can redistribute it and/or + * modify it either under the terms of the GNU Lesser General Public + * License version 2.1 as published by the Free Software Foundation + * (the "LGPL") or, at your option, under the terms of the Mozilla + * Public License Version 1.1 (the "MPL"). If you do not alter this + * notice, a recipient may use your version of this file under either + * the MPL or the LGPL. + * + * You should have received a copy of the LGPL along with this library + * in the file COPYING-LGPL-2.1; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * You should have received a copy of the MPL along with this library + * in the file COPYING-MPL-1.1 + * + * The contents of this file are subject to the Mozilla Public License + * Version 1.1 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY + * OF ANY KIND, either express or implied. See the LGPL or the MPL for + * the specific language governing rights and limitations. + * + * The Original Code is the cairo graphics library. + * + * The Initial Developer of the Original Code is Red Hat, Inc. + * + * Contributor(s): + * Kristian Høgsberg + * Adrian Johnson + */ + +#ifndef CAIRO_TRUETYPE_SUBSET_PRIVATE_H +#define CAIRO_TRUETYPE_SUBSET_PRIVATE_H + +#include "cairoint.h" + +/* The structs defined here should strictly follow the TrueType + * specification and not be padded. We use only 16-bit integer + * in their definition to guarantee that. The fields of type + * "FIXED" in the TT spec are broken into two *_1 and *_2 16-bit + * parts, and 64-bit members are broken into four. + * + * The test truetype-tables in the test suite makes sure that + * these tables have the right size. Please update that test + * if you add new tables/structs that should be packed. + */ + +#define MAKE_TT_TAG(a, b, c, d) (a<<24 | b<<16 | c<<8 | d) +#define TT_TAG_cmap MAKE_TT_TAG('c','m','a','p') +#define TT_TAG_cvt MAKE_TT_TAG('c','v','t',' ') +#define TT_TAG_fpgm MAKE_TT_TAG('f','p','g','m') +#define TT_TAG_glyf MAKE_TT_TAG('g','l','y','f') +#define TT_TAG_head MAKE_TT_TAG('h','e','a','d') +#define TT_TAG_hhea MAKE_TT_TAG('h','h','e','a') +#define TT_TAG_hmtx MAKE_TT_TAG('h','m','t','x') +#define TT_TAG_loca MAKE_TT_TAG('l','o','c','a') +#define TT_TAG_maxp MAKE_TT_TAG('m','a','x','p') +#define TT_TAG_name MAKE_TT_TAG('n','a','m','e') +#define TT_TAG_prep MAKE_TT_TAG('p','r','e','p') + +/* All tt_* structs are big-endian */ +typedef struct _tt_head { + int16_t version_1; + int16_t version_2; + int16_t revision_1; + int16_t revision_2; + uint16_t checksum_1; + uint16_t checksum_2; + uint16_t magic_1; + uint16_t magic_2; + uint16_t flags; + uint16_t units_per_em; + int16_t created_1; + int16_t created_2; + int16_t created_3; + int16_t created_4; + int16_t modified_1; + int16_t modified_2; + int16_t modified_3; + int16_t modified_4; + int16_t x_min; /* FWORD */ + int16_t y_min; /* FWORD */ + int16_t x_max; /* FWORD */ + int16_t y_max; /* FWORD */ + uint16_t mac_style; + uint16_t lowest_rec_pppem; + int16_t font_direction_hint; + int16_t index_to_loc_format; + int16_t glyph_data_format; +} tt_head_t; + +typedef struct _tt_hhea { + int16_t version_1; + int16_t version_2; + int16_t ascender; /* FWORD */ + int16_t descender; /* FWORD */ + int16_t line_gap; /* FWORD */ + uint16_t advance_max_width; /* UFWORD */ + int16_t min_left_side_bearing; /* FWORD */ + int16_t min_right_side_bearing; /* FWORD */ + int16_t x_max_extent; /* FWORD */ + int16_t caret_slope_rise; + int16_t caret_slope_run; + int16_t reserved[5]; + int16_t metric_data_format; + uint16_t num_hmetrics; +} tt_hhea_t; + +typedef struct _tt_maxp { + int16_t version_1; + int16_t version_2; + uint16_t num_glyphs; + uint16_t max_points; + uint16_t max_contours; + uint16_t max_composite_points; + uint16_t max_composite_contours; + uint16_t max_zones; + uint16_t max_twilight_points; + uint16_t max_storage; + uint16_t max_function_defs; + uint16_t max_instruction_defs; + uint16_t max_stack_elements; + uint16_t max_size_of_instructions; + uint16_t max_component_elements; + uint16_t max_component_depth; +} tt_maxp_t; + +typedef struct _tt_name_record { + uint16_t platform; + uint16_t encoding; + uint16_t language; + uint16_t name; + uint16_t length; + uint16_t offset; +} tt_name_record_t; + +typedef struct _tt_name { + uint16_t format; + uint16_t num_records; + uint16_t strings_offset; + tt_name_record_t records[1]; +} tt_name_t; + + + +/* composite_glyph_t flags */ +#define TT_ARG_1_AND_2_ARE_WORDS 0x0001 +#define TT_WE_HAVE_A_SCALE 0x0008 +#define TT_MORE_COMPONENTS 0x0020 +#define TT_WE_HAVE_AN_X_AND_Y_SCALE 0x0040 +#define TT_WE_HAVE_A_TWO_BY_TWO 0x0080 + +typedef struct _tt_composite_glyph { + uint16_t flags; + uint16_t index; + uint16_t args[7]; /* 1 to 7 arguments depending on value of flags */ +} tt_composite_glyph_t; + +typedef struct _tt_glyph_data { + int16_t num_contours; + int8_t data[8]; + tt_composite_glyph_t glyph; +} tt_glyph_data_t; + +#endif /* CAIRO_TRUETYPE_SUBSET_PRIVATE_H */ diff --git a/gfx/cairo/cairo/src/cairo-truetype-subset.c b/gfx/cairo/cairo/src/cairo-truetype-subset.c new file mode 100644 index 000000000000..c5e1799e99ae --- /dev/null +++ b/gfx/cairo/cairo/src/cairo-truetype-subset.c @@ -0,0 +1,883 @@ +/* cairo - a vector graphics library with display and print output + * + * Copyright © 2004 Red Hat, Inc + * + * This library is free software; you can redistribute it and/or + * modify it either under the terms of the GNU Lesser General Public + * License version 2.1 as published by the Free Software Foundation + * (the "LGPL") or, at your option, under the terms of the Mozilla + * Public License Version 1.1 (the "MPL"). If you do not alter this + * notice, a recipient may use your version of this file under either + * the MPL or the LGPL. + * + * You should have received a copy of the LGPL along with this library + * in the file COPYING-LGPL-2.1; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * You should have received a copy of the MPL along with this library + * in the file COPYING-MPL-1.1 + * + * The contents of this file are subject to the Mozilla Public License + * Version 1.1 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY + * OF ANY KIND, either express or implied. See the LGPL or the MPL for + * the specific language governing rights and limitations. + * + * The Original Code is the cairo graphics library. + * + * The Initial Developer of the Original Code is Red Hat, Inc. + * + * Contributor(s): + * Kristian Høgsberg + * Adrian Johnson + */ + +#include +#include "cairoint.h" +#include "cairo-scaled-font-subsets-private.h" +#include "cairo-truetype-subset-private.h" + + +typedef struct subset_glyph subset_glyph_t; +struct subset_glyph { + int parent_index; + unsigned long location; +}; + +typedef struct _cairo_truetype_font { + + cairo_scaled_font_subset_t *scaled_font_subset; + + struct { + char *base_font; + unsigned int num_glyphs; + int *widths; + long x_min, y_min, x_max, y_max; + long ascent, descent; + } base; + + subset_glyph_t *glyphs; + const cairo_scaled_font_backend_t *backend; + int num_glyphs_in_face; + int checksum_index; + cairo_array_t output; + cairo_array_t string_offsets; + unsigned long last_offset; + unsigned long last_boundary; + int *parent_to_subset; + cairo_status_t status; + +} cairo_truetype_font_t; + +static int +cairo_truetype_font_use_glyph (cairo_truetype_font_t *font, int glyph); + +#define ARRAY_LENGTH(a) ( (sizeof (a)) / (sizeof ((a)[0])) ) + +#define SFNT_VERSION 0x00010000 +#define SFNT_STRING_MAX_LENGTH 65535 + +#ifdef WORDS_BIGENDIAN + +#define cpu_to_be16(v) (v) +#define be16_to_cpu(v) (v) +#define cpu_to_be32(v) (v) +#define be32_to_cpu(v) (v) + +#else + +static inline uint16_t +cpu_to_be16(uint16_t v) +{ + return (v << 8) | (v >> 8); +} + +static inline uint16_t +be16_to_cpu(uint16_t v) +{ + return cpu_to_be16 (v); +} + +static inline uint32_t +cpu_to_be32(uint32_t v) +{ + return (cpu_to_be16 (v) << 16) | cpu_to_be16 (v >> 16); +} + +static inline uint32_t +be32_to_cpu(uint32_t v) +{ + return cpu_to_be32 (v); +} + +#endif + +static cairo_status_t +_cairo_truetype_font_create (cairo_scaled_font_subset_t *scaled_font_subset, + cairo_truetype_font_t **font_return) +{ + cairo_status_t status = CAIRO_STATUS_NO_MEMORY; + cairo_truetype_font_t *font; + const cairo_scaled_font_backend_t *backend; + tt_head_t head; + tt_hhea_t hhea; + tt_maxp_t maxp; + tt_name_t *name; + tt_name_record_t *record; + unsigned long size; + int i, j; + + backend = scaled_font_subset->scaled_font->backend; + if (!backend->load_truetype_table) + return CAIRO_INT_STATUS_UNSUPPORTED; + + /* FIXME: We should either support subsetting vertical fonts, or fail on + * vertical. Currently font_options_t doesn't have vertical flag, but + * it should be added in the future. For now, the freetype backend + * returns UNSUPPORTED in load_truetype_table if the font is vertical. + * + * if (cairo_font_options_get_vertical_layout (scaled_font_subset->scaled_font)) + * return CAIRO_INT_STATUS_UNSUPPORTED; + */ + + size = sizeof (tt_head_t); + if (backend->load_truetype_table (scaled_font_subset->scaled_font, + TT_TAG_head, 0, (unsigned char *) &head, + &size) != CAIRO_STATUS_SUCCESS) + return CAIRO_INT_STATUS_UNSUPPORTED; + + size = sizeof (tt_maxp_t); + if (backend->load_truetype_table (scaled_font_subset->scaled_font, + TT_TAG_maxp, 0, (unsigned char *) &maxp, + &size) != CAIRO_STATUS_SUCCESS) + return CAIRO_INT_STATUS_UNSUPPORTED; + + size = sizeof (tt_hhea_t); + if (backend->load_truetype_table (scaled_font_subset->scaled_font, + TT_TAG_hhea, 0, (unsigned char *) &hhea, + &size) != CAIRO_STATUS_SUCCESS) + return CAIRO_INT_STATUS_UNSUPPORTED; + + size = 0; + if (backend->load_truetype_table (scaled_font_subset->scaled_font, + TT_TAG_name, 0, NULL, + &size) != CAIRO_STATUS_SUCCESS) + return CAIRO_INT_STATUS_UNSUPPORTED; + name = malloc(size); + if (name == NULL) + return CAIRO_STATUS_NO_MEMORY; + backend->load_truetype_table (scaled_font_subset->scaled_font, + TT_TAG_name, 0, (unsigned char *) name, + &size); + + font = malloc (sizeof (cairo_truetype_font_t)); + if (font == NULL) + goto fail0; + + font->backend = backend; + font->num_glyphs_in_face = be16_to_cpu (maxp.num_glyphs); + font->scaled_font_subset = scaled_font_subset; + + font->last_offset = 0; + font->last_boundary = 0; + _cairo_array_init (&font->output, sizeof (char)); + if (_cairo_array_grow_by (&font->output, 4096) != CAIRO_STATUS_SUCCESS) + goto fail1; + font->glyphs = calloc (font->num_glyphs_in_face + 1, sizeof (subset_glyph_t)); + if (font->glyphs == NULL) + goto fail2; + + font->parent_to_subset = calloc (font->num_glyphs_in_face, sizeof (int)); + if (font->parent_to_subset == NULL) + goto fail3; + + font->base.num_glyphs = 0; + font->base.x_min = be16_to_cpu (head.x_min); + font->base.y_min = be16_to_cpu (head.y_min); + font->base.x_max = be16_to_cpu (head.x_max); + font->base.y_max = be16_to_cpu (head.y_max); + font->base.ascent = be16_to_cpu (hhea.ascender); + font->base.descent = be16_to_cpu (hhea.descender); + + /* Extract the font name from the name table. At present this + * just looks for the Mac platform/Roman encoded font name. It + * should be extended to use any suitable font name in the + * name table. If the mac/roman font name is not found a + * CairoFont-x-y name is created. + */ + font->base.base_font = NULL; + for (i = 0; i < be16_to_cpu(name->num_records); i++) { + record = &(name->records[i]); + if ((be16_to_cpu (record->platform) == 1) && + (be16_to_cpu (record->encoding) == 0) && + (be16_to_cpu (record->name) == 4)) { + font->base.base_font = malloc (be16_to_cpu(record->length) + 1); + if (font->base.base_font) { + strncpy(font->base.base_font, + ((char*)name) + be16_to_cpu (name->strings_offset) + be16_to_cpu (record->offset), + be16_to_cpu (record->length)); + font->base.base_font[be16_to_cpu (record->length)] = 0; + } + break; + } + } + + free (name); + name = NULL; + + if (font->base.base_font == NULL) { + font->base.base_font = malloc (30); + if (font->base.base_font == NULL) + goto fail4; + snprintf(font->base.base_font, 30, "CairoFont-%u-%u", + scaled_font_subset->font_id, + scaled_font_subset->subset_id); + } + + for (i = 0, j = 0; font->base.base_font[j]; j++) { + if (font->base.base_font[j] == ' ') + continue; + font->base.base_font[i++] = font->base.base_font[j]; + } + font->base.base_font[i] = '\0'; + + font->base.widths = calloc (font->num_glyphs_in_face, sizeof (int)); + if (font->base.widths == NULL) + goto fail5; + + _cairo_array_init (&font->string_offsets, sizeof (unsigned long)); + if (_cairo_array_grow_by (&font->string_offsets, 10) != CAIRO_STATUS_SUCCESS) + goto fail6; + + font->status = CAIRO_STATUS_SUCCESS; + + *font_return = font; + + return CAIRO_STATUS_SUCCESS; + + fail6: + free (font->base.widths); + fail5: + free (font->base.base_font); + fail4: + free (font->parent_to_subset); + fail3: + free (font->glyphs); + fail2: + _cairo_array_fini (&font->output); + fail1: + free (font); + fail0: + if (name) + free (name); + return status; +} + +static void +cairo_truetype_font_destroy (cairo_truetype_font_t *font) +{ + _cairo_array_fini (&font->string_offsets); + free (font->base.widths); + free (font->base.base_font); + free (font->parent_to_subset); + free (font->glyphs); + _cairo_array_fini (&font->output); + free (font); +} + +static cairo_status_t +cairo_truetype_font_allocate_write_buffer (cairo_truetype_font_t *font, + size_t length, + unsigned char **buffer) +{ + cairo_status_t status; + + status = _cairo_array_allocate (&font->output, length, (void **) buffer); + if (status) + return status; + + return CAIRO_STATUS_SUCCESS; +} + +static cairo_status_t +cairo_truetype_font_write (cairo_truetype_font_t *font, + const void *data, + size_t length) +{ + cairo_status_t status; + + status = _cairo_array_append_multiple (&font->output, data, length); + if (status) + return status; + + return CAIRO_STATUS_SUCCESS; +} + +static void +cairo_truetype_font_write_be16 (cairo_truetype_font_t *font, + uint16_t value) +{ + uint16_t be16_value; + + be16_value = cpu_to_be16 (value); + cairo_truetype_font_write (font, &be16_value, sizeof be16_value); +} + +static void +cairo_truetype_font_write_be32 (cairo_truetype_font_t *font, + uint32_t value) +{ + uint32_t be32_value; + + be32_value = cpu_to_be32 (value); + cairo_truetype_font_write (font, &be32_value, sizeof be32_value); +} + +static unsigned long +cairo_truetype_font_align_output (cairo_truetype_font_t *font) +{ + int length, aligned, pad; + unsigned char *padding; + + length = _cairo_array_num_elements (&font->output); + aligned = (length + 3) & ~3; + pad = aligned - length; + + if (pad) { + cairo_truetype_font_allocate_write_buffer (font, pad, &padding); + memset (padding, 0, pad); + } + + return aligned; +} + +static void +cairo_truetype_font_check_boundary (cairo_truetype_font_t *font, + unsigned long boundary) +{ + if (boundary - font->last_offset > SFNT_STRING_MAX_LENGTH) + { + _cairo_array_append(&font->string_offsets, &font->last_boundary); + font->last_offset = font->last_boundary; + } + font->last_boundary = boundary; +} + +static int +cairo_truetype_font_write_cmap_table (cairo_truetype_font_t *font, + unsigned long tag) +{ + unsigned int i; + + cairo_truetype_font_write_be16 (font, 0); + cairo_truetype_font_write_be16 (font, 1); + + cairo_truetype_font_write_be16 (font, 1); + cairo_truetype_font_write_be16 (font, 0); + cairo_truetype_font_write_be32 (font, 12); + + /* Output a format 6 encoding table. */ + + cairo_truetype_font_write_be16 (font, 6); + cairo_truetype_font_write_be16 (font, 10 + 2 * (font->base.num_glyphs - 1)); + cairo_truetype_font_write_be16 (font, 0); + cairo_truetype_font_write_be16 (font, 1); /* First glyph */ + cairo_truetype_font_write_be16 (font, font->base.num_glyphs - 1); + for (i = 1; i < font->base.num_glyphs; i++) + cairo_truetype_font_write_be16 (font, i); + + return font->status; +} + +static int +cairo_truetype_font_write_generic_table (cairo_truetype_font_t *font, + unsigned long tag) +{ + cairo_status_t status; + unsigned char *buffer; + unsigned long size; + + size = 0; + if (font->backend->load_truetype_table( font->scaled_font_subset->scaled_font, + tag, 0, NULL, &size) != CAIRO_STATUS_SUCCESS) { + font->status = CAIRO_INT_STATUS_UNSUPPORTED; + return font->status; + } + status = cairo_truetype_font_allocate_write_buffer (font, size, &buffer); + /* XXX: Need to check status here. */ + font->backend->load_truetype_table (font->scaled_font_subset->scaled_font, + tag, 0, buffer, &size); + return 0; +} + +static void +cairo_truetype_font_remap_composite_glyph (cairo_truetype_font_t *font, + unsigned char *buffer) +{ + tt_glyph_data_t *glyph_data; + tt_composite_glyph_t *composite_glyph; + int num_args; + int has_more_components; + unsigned short flags; + unsigned short index; + + glyph_data = (tt_glyph_data_t *) buffer; + if ((int16_t)be16_to_cpu (glyph_data->num_contours) >= 0) + return; + + composite_glyph = &glyph_data->glyph; + do { + flags = be16_to_cpu (composite_glyph->flags); + has_more_components = flags & TT_MORE_COMPONENTS; + index = cairo_truetype_font_use_glyph (font, be16_to_cpu (composite_glyph->index)); + composite_glyph->index = cpu_to_be16 (index); + num_args = 1; + if (flags & TT_ARG_1_AND_2_ARE_WORDS) + num_args += 1; + if (flags & TT_WE_HAVE_A_SCALE) + num_args += 1; + else if (flags & TT_WE_HAVE_AN_X_AND_Y_SCALE) + num_args += 2; + else if (flags & TT_WE_HAVE_A_TWO_BY_TWO) + num_args += 3; + composite_glyph = (tt_composite_glyph_t *) &(composite_glyph->args[num_args]); + } while (has_more_components); +} + +static int +cairo_truetype_font_write_glyf_table (cairo_truetype_font_t *font, + unsigned long tag) +{ + cairo_status_t status; + unsigned long start_offset, index, size, next; + tt_head_t header; + unsigned long begin, end; + unsigned char *buffer; + unsigned int i; + union { + unsigned char *bytes; + uint16_t *short_offsets; + uint32_t *long_offsets; + } u; + + size = sizeof (tt_head_t); + font->backend->load_truetype_table (font->scaled_font_subset->scaled_font, + TT_TAG_head, 0, (unsigned char*) &header, &size); + + if (be16_to_cpu (header.index_to_loc_format) == 0) + size = sizeof (int16_t) * (font->num_glyphs_in_face + 1); + else + size = sizeof (int32_t) * (font->num_glyphs_in_face + 1); + + u.bytes = malloc (size); + if (u.bytes == NULL) { + font->status = CAIRO_STATUS_NO_MEMORY; + return font->status; + } + if (font->backend->load_truetype_table (font->scaled_font_subset->scaled_font, + TT_TAG_loca, 0, u.bytes, &size) != CAIRO_STATUS_SUCCESS) { + font->status = CAIRO_INT_STATUS_UNSUPPORTED; + return font->status; + } + + start_offset = _cairo_array_num_elements (&font->output); + for (i = 0; i < font->base.num_glyphs; i++) { + index = font->glyphs[i].parent_index; + if (be16_to_cpu (header.index_to_loc_format) == 0) { + begin = be16_to_cpu (u.short_offsets[index]) * 2; + end = be16_to_cpu (u.short_offsets[index + 1]) * 2; + } + else { + begin = be32_to_cpu (u.long_offsets[index]); + end = be32_to_cpu (u.long_offsets[index + 1]); + } + + size = end - begin; + + next = cairo_truetype_font_align_output (font); + cairo_truetype_font_check_boundary (font, next); + font->glyphs[i].location = next - start_offset; + + status = cairo_truetype_font_allocate_write_buffer (font, size, &buffer); + if (status) + break; + if (size != 0) { + font->backend->load_truetype_table (font->scaled_font_subset->scaled_font, + TT_TAG_glyf, begin, buffer, &size); + cairo_truetype_font_remap_composite_glyph (font, buffer); + } + } + + font->glyphs[i].location = + cairo_truetype_font_align_output (font) - start_offset; + + free (u.bytes); + + return font->status; +} + +static int +cairo_truetype_font_write_head_table (cairo_truetype_font_t *font, + unsigned long tag) +{ + unsigned char *buffer; + unsigned long size; + + size = 0; + font->backend->load_truetype_table (font->scaled_font_subset->scaled_font, + tag, 0, NULL, &size); + font->checksum_index = _cairo_array_num_elements (&font->output) + 8; + font->status = cairo_truetype_font_allocate_write_buffer (font, size, &buffer); + font->backend->load_truetype_table( font->scaled_font_subset->scaled_font, + tag, 0, buffer, &size); + return font->status; +} + +static int cairo_truetype_font_write_hhea_table (cairo_truetype_font_t *font, unsigned long tag) +{ + tt_hhea_t *hhea; + unsigned long size; + + size = sizeof (tt_hhea_t); + font->status = cairo_truetype_font_allocate_write_buffer (font, size, (unsigned char **) &hhea); + font->backend->load_truetype_table (font->scaled_font_subset->scaled_font, + tag, 0, (unsigned char *) hhea, &size); + hhea->num_hmetrics = cpu_to_be16 ((uint16_t)(font->base.num_glyphs)); + return font->status; +} + +static int +cairo_truetype_font_write_hmtx_table (cairo_truetype_font_t *font, + unsigned long tag) +{ + cairo_status_t status; + unsigned long size; + unsigned long long_entry_size; + unsigned long short_entry_size; + short *p; + unsigned int i; + tt_hhea_t hhea; + int num_hmetrics; + + size = sizeof (tt_hhea_t); + font->backend->load_truetype_table (font->scaled_font_subset->scaled_font, + TT_TAG_hhea, 0, (unsigned char*) &hhea, &size); + num_hmetrics = be16_to_cpu(hhea.num_hmetrics); + + for (i = 0; i < font->base.num_glyphs; i++) { + long_entry_size = 2 * sizeof (int16_t); + short_entry_size = sizeof (int16_t); + status = cairo_truetype_font_allocate_write_buffer (font, long_entry_size, + (unsigned char **) &p); + if (font->glyphs[i].parent_index < num_hmetrics) { + if (font->backend->load_truetype_table (font->scaled_font_subset->scaled_font, + TT_TAG_hmtx, + font->glyphs[i].parent_index * long_entry_size, + (unsigned char *) p, &long_entry_size) != CAIRO_STATUS_SUCCESS) { + font->status = CAIRO_INT_STATUS_UNSUPPORTED; + return font->status; + } + } + else + { + if (font->backend->load_truetype_table (font->scaled_font_subset->scaled_font, + TT_TAG_hmtx, + (num_hmetrics - 1) * long_entry_size, + (unsigned char *) p, &short_entry_size) != CAIRO_STATUS_SUCCESS) { + font->status = CAIRO_INT_STATUS_UNSUPPORTED; + return font->status; + } + font->backend->load_truetype_table (font->scaled_font_subset->scaled_font, + TT_TAG_hmtx, + (num_hmetrics - 1) * long_entry_size + + (font->glyphs[i].parent_index - num_hmetrics) + * short_entry_size, + (unsigned char *) (p+1), &short_entry_size); + } + font->base.widths[i] = be16_to_cpu (p[0]); + } + + return font->status; +} + +static int +cairo_truetype_font_write_loca_table (cairo_truetype_font_t *font, + unsigned long tag) +{ + unsigned int i; + tt_head_t header; + unsigned long size; + + size = sizeof(tt_head_t); + font->backend->load_truetype_table (font->scaled_font_subset->scaled_font, + TT_TAG_head, 0, (unsigned char*) &header, &size); + + if (be16_to_cpu (header.index_to_loc_format) == 0) + { + for (i = 0; i < font->base.num_glyphs + 1; i++) + cairo_truetype_font_write_be16 (font, font->glyphs[i].location / 2); + } else { + for (i = 0; i < font->base.num_glyphs + 1; i++) + cairo_truetype_font_write_be32 (font, font->glyphs[i].location); + } + + return font->status; +} + +static int +cairo_truetype_font_write_maxp_table (cairo_truetype_font_t *font, + unsigned long tag) +{ + tt_maxp_t *maxp; + unsigned long size; + + size = sizeof (tt_maxp_t); + font->status = cairo_truetype_font_allocate_write_buffer (font, size, (unsigned char **) &maxp); + font->backend->load_truetype_table (font->scaled_font_subset->scaled_font, + tag, 0, (unsigned char *) maxp, &size); + maxp->num_glyphs = cpu_to_be16 (font->base.num_glyphs); + return font->status; +} + +typedef struct table table_t; +struct table { + unsigned long tag; + int (*write) (cairo_truetype_font_t *font, unsigned long tag); +}; + +static const table_t truetype_tables[] = { + /* As we write out the glyf table we remap composite glyphs. + * Remapping composite glyphs will reference the sub glyphs the + * composite glyph is made up of. That needs to be done first so + * we have all the glyphs in the subset before going further. */ + { TT_TAG_glyf, cairo_truetype_font_write_glyf_table }, + { TT_TAG_cmap, cairo_truetype_font_write_cmap_table }, + { TT_TAG_cvt, cairo_truetype_font_write_generic_table }, + { TT_TAG_fpgm, cairo_truetype_font_write_generic_table }, + { TT_TAG_head, cairo_truetype_font_write_head_table }, + { TT_TAG_hhea, cairo_truetype_font_write_hhea_table }, + { TT_TAG_hmtx, cairo_truetype_font_write_hmtx_table }, + { TT_TAG_loca, cairo_truetype_font_write_loca_table }, + { TT_TAG_maxp, cairo_truetype_font_write_maxp_table }, + { TT_TAG_name, cairo_truetype_font_write_generic_table }, + { TT_TAG_prep, cairo_truetype_font_write_generic_table }, +}; + +static cairo_status_t +cairo_truetype_font_write_offset_table (cairo_truetype_font_t *font) +{ + cairo_status_t status; + unsigned char *table_buffer; + size_t table_buffer_length; + unsigned short search_range, entry_selector, range_shift; + int num_tables; + + num_tables = ARRAY_LENGTH (truetype_tables); + search_range = 1; + entry_selector = 0; + while (search_range * 2 <= num_tables) { + search_range *= 2; + entry_selector++; + } + search_range *= 16; + range_shift = num_tables * 16 - search_range; + + cairo_truetype_font_write_be32 (font, SFNT_VERSION); + cairo_truetype_font_write_be16 (font, num_tables); + cairo_truetype_font_write_be16 (font, search_range); + cairo_truetype_font_write_be16 (font, entry_selector); + cairo_truetype_font_write_be16 (font, range_shift); + + /* Allocate space for the table directory. Each directory entry + * will be filled in by cairo_truetype_font_update_entry() after + * the table is written. */ + table_buffer_length = ARRAY_LENGTH (truetype_tables) * 16; + status = cairo_truetype_font_allocate_write_buffer (font, table_buffer_length, + &table_buffer); + if (status) + return status; + + return font->status; +} + +static uint32_t +cairo_truetype_font_calculate_checksum (cairo_truetype_font_t *font, + unsigned long start, + unsigned long end) +{ + uint32_t *padded_end; + uint32_t *p; + uint32_t checksum; + char *data; + + checksum = 0; + data = _cairo_array_index (&font->output, 0); + p = (uint32_t *) (data + start); + padded_end = (uint32_t *) (data + ((end + 3) & ~3)); + while (p < padded_end) + checksum += *p++; + + return checksum; +} + +static void +cairo_truetype_font_update_entry (cairo_truetype_font_t *font, + int index, + unsigned long tag, + unsigned long start, + unsigned long end) +{ + uint32_t *entry; + + entry = _cairo_array_index (&font->output, 12 + 16 * index); + entry[0] = cpu_to_be32 ((uint32_t)tag); + entry[1] = cpu_to_be32 (cairo_truetype_font_calculate_checksum (font, start, end)); + entry[2] = cpu_to_be32 ((uint32_t)start); + entry[3] = cpu_to_be32 ((uint32_t)(end - start)); +} + +static cairo_status_t +cairo_truetype_font_generate (cairo_truetype_font_t *font, + const char **data, + unsigned long *length, + const unsigned long **string_offsets, + unsigned long *num_strings) +{ + unsigned long start, end, next; + uint32_t checksum, *checksum_location; + unsigned int i; + + if (cairo_truetype_font_write_offset_table (font)) + goto fail; + + start = cairo_truetype_font_align_output (font); + end = start; + + end = 0; + for (i = 0; i < ARRAY_LENGTH (truetype_tables); i++) { + if (truetype_tables[i].write (font, truetype_tables[i].tag)) + goto fail; + + end = _cairo_array_num_elements (&font->output); + next = cairo_truetype_font_align_output (font); + cairo_truetype_font_update_entry (font, i, truetype_tables[i].tag, + start, end); + cairo_truetype_font_check_boundary (font, next); + start = next; + } + + checksum = + 0xb1b0afba - cairo_truetype_font_calculate_checksum (font, 0, end); + checksum_location = _cairo_array_index (&font->output, font->checksum_index); + *checksum_location = cpu_to_be32 (checksum); + + *data = _cairo_array_index (&font->output, 0); + *length = _cairo_array_num_elements (&font->output); + *num_strings = _cairo_array_num_elements (&font->string_offsets); + if (*num_strings != 0) + *string_offsets = _cairo_array_index (&font->string_offsets, 0); + else + *string_offsets = NULL; + + fail: + return font->status; +} + +static int +cairo_truetype_font_use_glyph (cairo_truetype_font_t *font, int glyph) +{ + if (font->parent_to_subset[glyph] == 0) { + font->parent_to_subset[glyph] = font->base.num_glyphs; + font->glyphs[font->base.num_glyphs].parent_index = glyph; + font->base.num_glyphs++; + } + + return font->parent_to_subset[glyph]; +} + +cairo_status_t +_cairo_truetype_subset_init (cairo_truetype_subset_t *truetype_subset, + cairo_scaled_font_subset_t *font_subset) +{ + cairo_truetype_font_t *font; + cairo_status_t status; + const char *data = NULL; /* squelch bogus compiler warning */ + unsigned long length = 0; /* squelch bogus compiler warning */ + unsigned long parent_glyph, offsets_length; + unsigned int i; + const unsigned long *string_offsets = NULL; + unsigned long num_strings = 0; + + status = _cairo_truetype_font_create (font_subset, &font); + if (status) + return status; + + for (i = 0; i < font->scaled_font_subset->num_glyphs; i++) { + parent_glyph = font->scaled_font_subset->glyphs[i]; + cairo_truetype_font_use_glyph (font, parent_glyph); + } + + status = cairo_truetype_font_generate (font, &data, &length, + &string_offsets, &num_strings); + if (status) + goto fail1; + + truetype_subset->base_font = strdup (font->base.base_font); + if (truetype_subset->base_font == NULL) + goto fail1; + + truetype_subset->widths = calloc (sizeof (int), font->base.num_glyphs); + if (truetype_subset->widths == NULL) + goto fail2; + for (i = 0; i < font->base.num_glyphs; i++) + truetype_subset->widths[i] = font->base.widths[i]; + + truetype_subset->x_min = font->base.x_min; + truetype_subset->y_min = font->base.y_min; + truetype_subset->x_max = font->base.x_max; + truetype_subset->y_max = font->base.y_max; + truetype_subset->ascent = font->base.ascent; + truetype_subset->descent = font->base.descent; + + truetype_subset->data = malloc (length); + if (truetype_subset->data == NULL) + goto fail3; + + memcpy (truetype_subset->data, data, length); + truetype_subset->data_length = length; + + offsets_length = num_strings * sizeof (unsigned long); + truetype_subset->string_offsets = malloc (offsets_length); + if (truetype_subset->string_offsets == NULL) + goto fail4; + + memcpy (truetype_subset->string_offsets, string_offsets, offsets_length); + truetype_subset->num_string_offsets = num_strings; + + cairo_truetype_font_destroy (font); + + return CAIRO_STATUS_SUCCESS; + + fail4: + free (truetype_subset->data); + fail3: + free (truetype_subset->widths); + fail2: + free (truetype_subset->base_font); + fail1: + cairo_truetype_font_destroy (font); + + return status; +} + +void +_cairo_truetype_subset_fini (cairo_truetype_subset_t *subset) +{ + free (subset->base_font); + free (subset->widths); + free (subset->data); + free (subset->string_offsets); +} + diff --git a/gfx/cairo/cairo/src/cairo-type1-fallback.c b/gfx/cairo/cairo/src/cairo-type1-fallback.c new file mode 100644 index 000000000000..ea4826b13c40 --- /dev/null +++ b/gfx/cairo/cairo/src/cairo-type1-fallback.c @@ -0,0 +1,746 @@ +/* cairo - a vector graphics library with display and print output + * + * Copyright © 2006 Red Hat, Inc + * + * This library is free software; you can redistribute it and/or + * modify it either under the terms of the GNU Lesser General Public + * License version 2.1 as published by the Free Software Foundation + * (the "LGPL") or, at your option, under the terms of the Mozilla + * Public License Version 1.1 (the "MPL"). If you do not alter this + * notice, a recipient may use your version of this file under either + * the MPL or the LGPL. + * + * You should have received a copy of the LGPL along with this library + * in the file COPYING-LGPL-2.1; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * You should have received a copy of the MPL along with this library + * in the file COPYING-MPL-1.1 + * + * The contents of this file are subject to the Mozilla Public License + * Version 1.1 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY + * OF ANY KIND, either express or implied. See the LGPL or the MPL for + * the specific language governing rights and limitations. + * + * The Original Code is the cairo graphics library. + * + * The Initial Developer of the Original Code is Red Hat, Inc. + * + * Contributor(s): + * Adrian Johnson + */ + +#include "cairoint.h" +#include "cairo-scaled-font-subsets-private.h" +#include "cairo-path-fixed-private.h" +#include "cairo-output-stream-private.h" + +typedef struct _cairo_type1_font { + int *widths; + + cairo_scaled_font_subset_t *scaled_font_subset; + cairo_scaled_font_t *type1_scaled_font; + + cairo_array_t contents; + + double x_min, y_min, x_max, y_max; + + const char *data; + unsigned long header_size; + unsigned long data_size; + unsigned long trailer_size; + int bbox_position; + int bbox_max_chars; + + cairo_output_stream_t *output; + + unsigned short eexec_key; + cairo_bool_t hex_encode; + int hex_column; +} cairo_type1_font_t; + +static cairo_status_t +cairo_type1_font_create (cairo_scaled_font_subset_t *scaled_font_subset, + cairo_type1_font_t **subset_return) +{ + cairo_type1_font_t *font; + cairo_font_face_t *font_face; + cairo_matrix_t font_matrix; + cairo_matrix_t ctm; + cairo_font_options_t font_options; + + font = calloc (1, sizeof (cairo_type1_font_t)); + if (font == NULL) + return CAIRO_STATUS_NO_MEMORY; + + font->widths = calloc (scaled_font_subset->num_glyphs, + sizeof (int)); + if (font->widths == NULL) { + free (font); + return CAIRO_STATUS_NO_MEMORY; + } + + font->scaled_font_subset = scaled_font_subset; + + font_face = cairo_scaled_font_get_font_face (scaled_font_subset->scaled_font); + + cairo_matrix_init_scale (&font_matrix, 1000, 1000); + cairo_matrix_init_identity (&ctm); + + _cairo_font_options_init_default (&font_options); + cairo_font_options_set_hint_style (&font_options, CAIRO_HINT_STYLE_NONE); + cairo_font_options_set_hint_metrics (&font_options, CAIRO_HINT_METRICS_OFF); + + font->type1_scaled_font = cairo_scaled_font_create (font_face, + &font_matrix, + &ctm, + &font_options); + + _cairo_array_init (&font->contents, sizeof (unsigned char)); + + *subset_return = font; + + return CAIRO_STATUS_SUCCESS; +} + +/* Magic constants for the type1 eexec encryption */ +static const unsigned short encrypt_c1 = 52845, encrypt_c2 = 22719; +static const unsigned short private_dict_key = 55665; +static const unsigned short charstring_key = 4330; + +/* Charstring commands. If the high byte is 0 the command is encoded + * with a single byte. */ +#define CHARSTRING_sbw 0x0c07 +#define CHARSTRING_rmoveto 0x0015 +#define CHARSTRING_rlineto 0x0005 +#define CHARSTRING_rcurveto 0x0008 +#define CHARSTRING_closepath 0x0009 +#define CHARSTRING_endchar 0x000e + +/* Before calling this function, the caller must allocate sufficient + * space in data (see _cairo_array_grow_by). The maxium number of + * bytes that will be used is 2. + */ +static void +charstring_encode_command (cairo_array_t *data, int command) +{ + cairo_status_t status; + int orig_size; + unsigned char buf[5]; + unsigned char *p = buf; + + if (command & 0xff00) + *p++ = command >> 8; + *p++ = command & 0x00ff; + + /* Ensure the array doesn't grow, which allows this function to + * have no possibility of failure. */ + orig_size = _cairo_array_size (data); + status = _cairo_array_append_multiple (data, buf, p - buf); + + assert (status == CAIRO_STATUS_SUCCESS); + assert (_cairo_array_size (data) == orig_size); +} + +/* Before calling this function, the caller must allocate sufficient + * space in data (see _cairo_array_grow_by). The maxium number of + * bytes that will be used is 5. + */ +static void +charstring_encode_integer (cairo_array_t *data, int i) +{ + cairo_status_t status; + int orig_size; + unsigned char buf[10]; + unsigned char *p = buf; + + if (i >= -107 && i <= 107) { + *p++ = i + 139; + } else if (i >= 108 && i <= 1131) { + i -= 108; + *p++ = (i >> 8)+ 247; + *p++ = i & 0xff; + } else if (i >= -1131 && i <= -108) { + i = -i - 108; + *p++ = (i >> 8)+ 251; + *p++ = i & 0xff; + } else { + *p++ = 0xff; + *p++ = i >> 24; + *p++ = (i >> 16) & 0xff; + *p++ = (i >> 8) & 0xff; + *p++ = i & 0xff; + } + + /* Ensure the array doesn't grow, which allows this function to + * have no possibility of failure. */ + orig_size = _cairo_array_size (data); + status = _cairo_array_append_multiple (data, buf, p - buf); + + assert (status == CAIRO_STATUS_SUCCESS); + assert (_cairo_array_size (data) == orig_size); +} + +typedef struct _ps_path_info { + cairo_array_t *data; + int current_x, current_y; +} t1_path_info_t; + +static cairo_status_t +_charstring_move_to (void *closure, + cairo_point_t *point) +{ + t1_path_info_t *path_info = (t1_path_info_t *) closure; + int dx, dy; + cairo_status_t status; + + status = _cairo_array_grow_by (path_info->data, 12); + if (status) + return status; + + dx = _cairo_fixed_integer_part (point->x) - path_info->current_x; + dy = _cairo_fixed_integer_part (point->y) - path_info->current_y; + charstring_encode_integer (path_info->data, dx); + charstring_encode_integer (path_info->data, dy); + path_info->current_x += dx; + path_info->current_y += dy; + + charstring_encode_command (path_info->data, CHARSTRING_rmoveto); + + return CAIRO_STATUS_SUCCESS; +} + +static cairo_status_t +_charstring_line_to (void *closure, + cairo_point_t *point) +{ + t1_path_info_t *path_info = (t1_path_info_t *) closure; + int dx, dy; + cairo_status_t status; + + status = _cairo_array_grow_by (path_info->data, 12); + if (status) + return status; + + dx = _cairo_fixed_integer_part (point->x) - path_info->current_x; + dy = _cairo_fixed_integer_part (point->y) - path_info->current_y; + charstring_encode_integer (path_info->data, dx); + charstring_encode_integer (path_info->data, dy); + path_info->current_x += dx; + path_info->current_y += dy; + + charstring_encode_command (path_info->data, CHARSTRING_rlineto); + + return CAIRO_STATUS_SUCCESS; +} + +static cairo_status_t +_charstring_curve_to (void *closure, + cairo_point_t *point1, + cairo_point_t *point2, + cairo_point_t *point3) +{ + t1_path_info_t *path_info = (t1_path_info_t *) closure; + int dx1, dy1, dx2, dy2, dx3, dy3; + cairo_status_t status; + + status = _cairo_array_grow_by (path_info->data, 32); + if (status) + return status; + + dx1 = _cairo_fixed_integer_part (point1->x) - path_info->current_x; + dy1 = _cairo_fixed_integer_part (point1->y) - path_info->current_y; + dx2 = _cairo_fixed_integer_part (point2->x) - path_info->current_x - dx1; + dy2 = _cairo_fixed_integer_part (point2->y) - path_info->current_y - dy1; + dx3 = _cairo_fixed_integer_part (point3->x) - path_info->current_x - dx1 - dx2; + dy3 = _cairo_fixed_integer_part (point3->y) - path_info->current_y - dy1 - dy2; + charstring_encode_integer (path_info->data, dx1); + charstring_encode_integer (path_info->data, dy1); + charstring_encode_integer (path_info->data, dx2); + charstring_encode_integer (path_info->data, dy2); + charstring_encode_integer (path_info->data, dx3); + charstring_encode_integer (path_info->data, dy3); + path_info->current_x += dx1 + dx2 + dx3; + path_info->current_y += dy1 + dy2 + dy3; + charstring_encode_command (path_info->data, CHARSTRING_rcurveto); + + return CAIRO_STATUS_SUCCESS; +} + +static cairo_status_t +_charstring_close_path (void *closure) +{ + cairo_status_t status; + t1_path_info_t *path_info = (t1_path_info_t *) closure; + + status = _cairo_array_grow_by (path_info->data, 2); + if (status) + return status; + + charstring_encode_command (path_info->data, CHARSTRING_closepath); + + return CAIRO_STATUS_SUCCESS; +} + +static void +charstring_encrypt (cairo_array_t *data) +{ + unsigned char *d, *end; + uint16_t c, p, r; + + r = charstring_key; + d = (unsigned char *) _cairo_array_index (data, 0); + end = d + _cairo_array_num_elements (data); + while (d < end) { + p = *d; + c = p ^ (r >> 8); + r = (c + r) * encrypt_c1 + encrypt_c2; + *d++ = c; + } +} + +static cairo_int_status_t +create_notdef_charstring (cairo_array_t *data) +{ + cairo_status_t status; + + /* We're passing constants below, so we know the 0 values will + * only use 1 byte each, and the 500 values will use 2 bytes + * each. Then 2 more for each of the commands is 10 total. */ + status = _cairo_array_grow_by (data, 10); + if (status) + return status; + + charstring_encode_integer (data, 0); + charstring_encode_integer (data, 0); + + /* The width and height is arbitrary. */ + charstring_encode_integer (data, 500); + charstring_encode_integer (data, 500); + charstring_encode_command (data, CHARSTRING_sbw); + + charstring_encode_command (data, CHARSTRING_endchar); + + return CAIRO_STATUS_SUCCESS; +} + +static cairo_int_status_t +cairo_type1_font_create_charstring (cairo_type1_font_t *font, + int subset_index, + int glyph_index, + cairo_array_t *data) +{ + cairo_int_status_t status; + cairo_scaled_glyph_t *scaled_glyph; + t1_path_info_t path_info; + cairo_text_extents_t *metrics; + + /* This call may return CAIRO_INT_STATUS_UNSUPPORTED for bitmap fonts. */ + status = _cairo_scaled_glyph_lookup (font->type1_scaled_font, + glyph_index, + CAIRO_SCALED_GLYPH_INFO_METRICS| + CAIRO_SCALED_GLYPH_INFO_PATH, + &scaled_glyph); + if (status) + return status; + + metrics = &scaled_glyph->metrics; + if (subset_index == 0) { + font->x_min = metrics->x_bearing; + font->y_min = metrics->y_bearing; + font->x_max = metrics->x_bearing + metrics->width; + font->y_max = metrics->y_bearing + metrics->height; + } else { + if (metrics->x_bearing < font->x_min) + font->x_min = metrics->x_bearing; + if (metrics->y_bearing < font->y_min) + font->y_min = metrics->y_bearing; + if (metrics->x_bearing + metrics->width > font->x_max) + font->x_max = metrics->x_bearing + metrics->width; + if (metrics->y_bearing + metrics->height > font->y_max) + font->y_max = metrics->y_bearing + metrics->height; + } + font->widths[subset_index] = metrics->width; + + status = _cairo_array_grow_by (data, 30); + if (status) + return status; + + charstring_encode_integer (data, (int) scaled_glyph->metrics.x_bearing); + charstring_encode_integer (data, (int) scaled_glyph->metrics.y_bearing); + charstring_encode_integer (data, (int) scaled_glyph->metrics.width); + charstring_encode_integer (data, (int) scaled_glyph->metrics.height); + charstring_encode_command (data, CHARSTRING_sbw); + + path_info.data = data; + path_info.current_x = (int) scaled_glyph->metrics.x_bearing; + path_info.current_y = (int) scaled_glyph->metrics.y_bearing; + _cairo_path_fixed_interpret (scaled_glyph->path, + CAIRO_DIRECTION_FORWARD, + _charstring_move_to, + _charstring_line_to, + _charstring_curve_to, + _charstring_close_path, + &path_info); + + charstring_encode_command (path_info.data, CHARSTRING_endchar); + + return CAIRO_STATUS_SUCCESS; +} + +static cairo_int_status_t +cairo_type1_font_write_charstrings (cairo_type1_font_t *font, + cairo_output_stream_t *encrypted_output) +{ + cairo_status_t status = CAIRO_STATUS_SUCCESS; + unsigned char zeros[] = { 0, 0, 0, 0 }; + cairo_array_t data; + unsigned int i; + int length; + + _cairo_array_init (&data, sizeof (unsigned char)); + status = _cairo_array_grow_by (&data, 1024); + if (status) + goto fail; + + _cairo_output_stream_printf (encrypted_output, + "2 index /CharStrings %d dict dup begin\n", + font->scaled_font_subset->num_glyphs + 1); + + for (i = 0; i < font->scaled_font_subset->num_glyphs; i++) { + _cairo_array_truncate (&data, 0); + /* four "random" bytes required by encryption algorithm */ + _cairo_array_append_multiple (&data, zeros, 4); + status = cairo_type1_font_create_charstring (font, i, + font->scaled_font_subset->glyphs[i], + &data); + if (status) + goto fail; + charstring_encrypt (&data); + length = _cairo_array_num_elements (&data); + _cairo_output_stream_printf (encrypted_output, "/g%d %d RD ", i, length); + _cairo_output_stream_write (encrypted_output, + _cairo_array_index (&data, 0), + length); + _cairo_output_stream_printf (encrypted_output, " ND\n"); + } + + /* All type 1 fonts must have a /.notdef charstring */ + + _cairo_array_truncate (&data, 0); + /* four "random" bytes required by encryption algorithm */ + _cairo_array_append_multiple (&data, zeros, 4); + create_notdef_charstring (&data); + charstring_encrypt (&data); + length = _cairo_array_num_elements (&data); + _cairo_output_stream_printf (encrypted_output, "/.notdef %d RD ", length); + _cairo_output_stream_write (encrypted_output, + _cairo_array_index (&data, 0), + length); + _cairo_output_stream_printf (encrypted_output, " ND\n"); + +fail: + _cairo_array_fini (&data); + return status; +} + +static cairo_status_t +cairo_type1_font_write_header (cairo_type1_font_t *font, + const char *name) +{ + cairo_matrix_t matrix; + unsigned int i; + const char spaces[50] = " "; + + matrix = font->type1_scaled_font->scale; + matrix.xy = -matrix.xy; + matrix.yy = -matrix.yy; + cairo_matrix_invert (&matrix); + + _cairo_output_stream_printf (font->output, + "%%!FontType1-1.1 %s 1.0\n" + "11 dict begin\n" + "/FontName /%s def\n" + "/PaintType 0 def\n" + "/FontType 1 def\n" + "/FontMatrix [%f %f %f %f 0 0] readonly def\n", + name, + name, + matrix.xx, + matrix.yx, + matrix.xy, + matrix.yy); + + /* We don't know the bbox values until after the charstrings have + * been generated. Reserve some space and fill in the bbox + * later. */ + + /* Worst case for four signed ints with spaces between each number */ + font->bbox_max_chars = 50; + + _cairo_output_stream_printf (font->output, "/FontBBox {"); + font->bbox_position = _cairo_output_stream_get_position (font->output); + _cairo_output_stream_write (font->output, spaces, font->bbox_max_chars); + + _cairo_output_stream_printf (font->output, + "} readonly def\n" + "/Encoding 256 array\n" + "0 1 255 {1 index exch /.notdef put} for\n"); + for (i = 0; i < font->scaled_font_subset->num_glyphs; i++) + _cairo_output_stream_printf (font->output, "dup %d /g%d put\n", i, i); + _cairo_output_stream_printf (font->output, + "readonly def\n" + "currentdict end\n" + "currentfile eexec\n"); + + return CAIRO_STATUS_SUCCESS; +} + +static cairo_status_t +cairo_type1_write_stream_encrypted (void *closure, + const unsigned char *data, + unsigned int length) +{ + const unsigned char *in, *end; + uint16_t c, p; + static const char hex_digits[16] = "0123456789abcdef"; + char digits[3]; + cairo_type1_font_t *font = closure; + + in = (const unsigned char *) data; + end = (const unsigned char *) data + length; + while (in < end) { + p = *in++; + c = p ^ (font->eexec_key >> 8); + font->eexec_key = (c + font->eexec_key) * encrypt_c1 + encrypt_c2; + + if (font->hex_encode) { + digits[0] = hex_digits[c >> 4]; + digits[1] = hex_digits[c & 0x0f]; + digits[2] = '\n'; + font->hex_column += 2; + + if (font->hex_column == 78) { + _cairo_output_stream_write (font->output, digits, 3); + font->hex_column = 0; + } else { + _cairo_output_stream_write (font->output, digits, 2); + } + } else { + digits[0] = c; + _cairo_output_stream_write (font->output, digits, 1); + } + } + + return CAIRO_STATUS_SUCCESS; +} + +static cairo_int_status_t +cairo_type1_font_write_private_dict (cairo_type1_font_t *font, + const char *name) +{ + cairo_int_status_t status; + cairo_output_stream_t *encrypted_output; + + font->eexec_key = private_dict_key; + font->hex_encode = TRUE; + font->hex_column = 0; + encrypted_output = _cairo_output_stream_create ( + cairo_type1_write_stream_encrypted, + NULL, + font); + if (encrypted_output == NULL) + goto fail; + + /* Note: the first four spaces at the start of this private dict + * are the four "random" bytes of plaintext required by the + * encryption algorithm */ + _cairo_output_stream_printf (encrypted_output, + " dup /Private 9 dict dup begin\n" + "/RD {string currentfile exch readstring pop}" + " executeonly def\n" + "/ND {noaccess def} executeonly def\n" + "/NP {noaccess put} executeonly def\n" + "/BlueValues [] def\n" + "/MinFeature {16 16} def\n" + "/lenIV 4 def\n" + "/password 5839 def\n"); + + status = cairo_type1_font_write_charstrings (font, encrypted_output); + if (status) + goto fail; + + _cairo_output_stream_printf (encrypted_output, + "end\n" + "end\n" + "readonly put\n" + "noaccess put\n" + "dup /FontName get exch definefont pop\n" + "mark currentfile closefile\n"); + + if (status == CAIRO_STATUS_SUCCESS) + status = _cairo_output_stream_get_status (encrypted_output); + fail: + _cairo_output_stream_destroy (encrypted_output); + + return status; +} + +static cairo_status_t +cairo_type1_font_write_trailer(cairo_type1_font_t *font) +{ + int i; + static const char zeros[65] = + "0000000000000000000000000000000000000000000000000000000000000000\n"; + + for (i = 0; i < 8; i++) + _cairo_output_stream_write (font->output, zeros, sizeof zeros); + + _cairo_output_stream_printf (font->output, "cleartomark\n"); + + return CAIRO_STATUS_SUCCESS; +} + +static cairo_status_t +cairo_type1_write_stream (void *closure, + const unsigned char *data, + unsigned int length) +{ + cairo_type1_font_t *font = closure; + + return _cairo_array_append_multiple (&font->contents, data, length); +} + +static cairo_int_status_t +cairo_type1_font_write (cairo_type1_font_t *font, + const char *name) +{ + cairo_int_status_t status; + + cairo_type1_font_write_header (font, name); + font->header_size = _cairo_output_stream_get_position (font->output); + + status = cairo_type1_font_write_private_dict (font, name); + if (status) + return status; + + font->data_size = _cairo_output_stream_get_position (font->output) - + font->header_size; + + cairo_type1_font_write_trailer (font); + font->trailer_size = + _cairo_output_stream_get_position (font->output) - + font->header_size - font->data_size; + + return CAIRO_STATUS_SUCCESS; +} + +static cairo_int_status_t +cairo_type1_font_generate (cairo_type1_font_t *font, const char *name) +{ + cairo_int_status_t status; + + status = _cairo_array_grow_by (&font->contents, 4096); + if (status) + return status; + + font->output = _cairo_output_stream_create (cairo_type1_write_stream, NULL, font); + + status = cairo_type1_font_write (font, name); + if (status) + return status; + + font->data = _cairo_array_index (&font->contents, 0); + + return CAIRO_STATUS_SUCCESS; +} + +static void +cairo_type1_font_destroy (cairo_type1_font_t *font) +{ + free (font->widths); + _cairo_array_fini (&font->contents); + cairo_scaled_font_destroy (font->type1_scaled_font); + free (font); +} + +cairo_status_t +_cairo_type1_fallback_init (cairo_type1_subset_t *type1_subset, + const char *name, + cairo_scaled_font_subset_t *scaled_font_subset) +{ + cairo_type1_font_t *font; + cairo_status_t status; + unsigned long length; + unsigned int i, len; + + status = cairo_type1_font_create (scaled_font_subset, &font); + if (status) + return status; + + status = cairo_type1_font_generate (font, name); + if (status) + goto fail1; + + type1_subset->base_font = strdup (name); + if (type1_subset->base_font == NULL) + goto fail1; + + type1_subset->widths = calloc (sizeof (int), font->scaled_font_subset->num_glyphs); + if (type1_subset->widths == NULL) + goto fail2; + for (i = 0; i < font->scaled_font_subset->num_glyphs; i++) + type1_subset->widths[i] = font->widths[i]; + + type1_subset->x_min = (int) font->x_min; + type1_subset->y_min = (int) font->y_min; + type1_subset->x_max = (int) font->x_max; + type1_subset->y_max = (int) font->y_max; + type1_subset->ascent = (int) font->y_max; + type1_subset->descent = (int) font->y_min; + + length = font->header_size + font->data_size + + font->trailer_size; + type1_subset->data = malloc (length); + if (type1_subset->data == NULL) + goto fail3; + + memcpy (type1_subset->data, + _cairo_array_index (&font->contents, 0), length); + + len = snprintf(type1_subset->data + font->bbox_position, + font->bbox_max_chars, + "%d %d %d %d", + (int)type1_subset->x_min, + (int)type1_subset->y_min, + (int)type1_subset->x_max, + (int)type1_subset->y_max); + type1_subset->data[font->bbox_position + len] = ' '; + + type1_subset->header_length = font->header_size; + type1_subset->data_length = font->data_size; + type1_subset->trailer_length = font->trailer_size; + + cairo_type1_font_destroy (font); + return CAIRO_STATUS_SUCCESS; + + fail3: + free (type1_subset->widths); + fail2: + free (type1_subset->base_font); + fail1: + cairo_type1_font_destroy (font); + + return status; +} + +void +_cairo_type1_fallback_fini (cairo_type1_subset_t *subset) +{ + free (subset->base_font); + free (subset->widths); + free (subset->data); +} diff --git a/gfx/cairo/cairo/src/cairo-type1-subset.c b/gfx/cairo/cairo/src/cairo-type1-subset.c index 1daa2f477dc3..6f1be2cd2dc5 100644 --- a/gfx/cairo/cairo/src/cairo-type1-subset.c +++ b/gfx/cairo/cairo/src/cairo-type1-subset.c @@ -53,7 +53,7 @@ typedef struct _cairo_type1_font_subset { cairo_unscaled_font_t *unscaled_font; unsigned int font_id; char *base_font; - int num_glyphs; + unsigned int num_glyphs; long x_min, y_min, x_max, y_max; long ascent, descent; @@ -103,7 +103,8 @@ typedef struct _cairo_type1_font_subset { static cairo_status_t _cairo_type1_font_subset_create (cairo_unscaled_font_t *unscaled_font, - cairo_type1_font_subset_t **subset_return) + cairo_type1_font_subset_t **subset_return, + cairo_bool_t hex_encode) { cairo_ft_unscaled_font_t *ft_unscaled_font; FT_Face face; @@ -145,6 +146,7 @@ _cairo_type1_font_subset_create (cairo_unscaled_font_t *unscaled_font, if (font->glyphs == NULL) goto fail2; + font->hex_encode = hex_encode; font->num_glyphs = 0; for (i = 0; i < face->num_glyphs; i++) font->glyphs[i].subset_index = -1; @@ -185,7 +187,7 @@ static const unsigned short charstring_key = 4330; static cairo_bool_t is_ps_delimiter(int c) { - const static char delimiters[] = "()[]{}<>/% \t\r\n"; + static const char delimiters[] = "()[]{}<>/% \t\r\n"; return strchr (delimiters, c) != NULL; } @@ -252,7 +254,7 @@ cairo_type1_font_subset_write_header (cairo_type1_font_subset_t *font, const char *name) { const char *start, *end, *segment_end; - int i; + unsigned int i; segment_end = font->header_segment + font->header_segment_size; @@ -399,7 +401,7 @@ static int cairo_type1_font_subset_lookup_glyph (cairo_type1_font_subset_t *font, const char *glyph_name, int length) { - int i; + unsigned int i; for (i = 0; i < font->base.num_glyphs; i++) { if (font->glyphs[i].name && @@ -414,7 +416,7 @@ cairo_type1_font_subset_lookup_glyph (cairo_type1_font_subset_t *font, static cairo_status_t cairo_type1_font_subset_get_glyph_names_and_widths (cairo_type1_font_subset_t *font) { - int i; + unsigned int i; char buffer[256]; FT_Error error; @@ -481,45 +483,86 @@ cairo_type1_font_subset_decode_integer (const unsigned char *p, int *integer) } static const char *ps_standard_encoding[256] = { - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0 */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 16 */ - "space", "exclam", "quotedbl", "numbersign", /* 32 */ - "dollar", "percent", "ampersand", "quoteright", - "parenleft", "parenright", "asterisk", "plus", - "comma", "hyphen", "period", "slash", - "zero", "one", "two", "three", /* 48 */ - "four", "five", "six", "seven", "eight", - "nine", "colon", "semicolon", "less", - "equal", "greater", "question", "at", - "A", "B", "C", "D", "E", "F", "G", "H", /* 64 */ - "I", "J", "K", "L", "M", "N", "O", "P", - "Q", "R", "S", "T", "U", "V", "W", "X", /* 80 */ - "Y", "Z", "bracketleft", "backslash", - "bracketright", "asciicircum", "underscore", "quoteleft", - "a", "b", "c", "d", "e", "f", "g", "h", /* 96 */ - "i", "j", "k", "l", "m", "n", "o", "p", - "q", "r", "s", "t", "u", "v", "w", "x", /* 112 */ - "y", "z", "braceleft", "bar", - "braceright", "asciitilde", 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 128 */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 144 */ - "exclamdown", "cent", "sterling", "fraction", - "yen", "florin", "section", "currency", - "quotesingle", "quotedblleft", "guillemotleft", "guilsinglleft", - "guilsinglright", "fi", "fl", NULL, - "endash", "dagger", "daggerdbl", "periodcentered", /* 160 */ - NULL, "paragraph", "bullet", "quotesinglbase", - "quotedblbase", "quotedblright", "guillemotright", "ellipsis", - "perthousand", NULL, "questiondown", NULL, - "grave", "acute", "circumflex", "tilde", /* 176 */ - "macron", "breve", "dotaccent", "dieresis", - NULL, "ring", "cedilla", NULL, - "hungarumlaut", "ogonek", "caron", "emdash", - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 192 */ - "AE", 0, "ordfeminine", 0, 0, 0, 0, "Lslash", /* 208 */ - "Oslash", "OE", "ordmasculine", 0, 0, 0, 0, 0, - "ae", 0, 0, 0, "dotlessi", 0, 0, "lslash", /* 224 */ - "oslash", "oe", "germandbls", 0, 0, 0, 0 + /* 0 */ + NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, + /* 16 */ + NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, + /* 32 */ + "space", "exclam", "quotedbl", "numbersign", + "dollar", "percent", "ampersand", "quoteright", + "parenleft", "parenright", "asterisk", "plus", + "comma", "hyphen", "period", "slash", + /* 48 */ + "zero", "one", "two", "three", + "four", "five", "six", "seven", + "eight", "nine", "colon", "semicolon", + "less", "equal", "greater", "question", + /* 64 */ + "at", "A", "B", "C", + "D", "E", "F", "G", + "H", "I", "J", "K", + "L", "M", "N", "O", + /* 80 */ + "P", "Q", "R", "S", + "T", "U", "V", "W", + "X", "Y", "Z", "bracketleft", + "backslash", "bracketright", "asciicircum", "underscore", + /* 96 */ + "quoteleft", "a", "b", "c", + "d", "e", "f", "g", + "h", "i", "j", "k", + "l", "m", "n", "o", + /* 112 */ + "p", "q", "r", "s", + "t", "u", "v", "w", + "x", "y", "z", "braceleft", + "bar", "braceright", "asciitilde", NULL, + /* 128 */ + NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, + /* 144 */ + NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, + /* 160 */ + NULL, "exclamdown", "cent", "sterling", + "fraction", "yen", "florin", "section", + "currency", "quotesingle", "quotedblleft", "guillemotleft", + "guilsinglleft","guilsinglright","fi", "fl", + /* 176 */ + NULL, "endash", "dagger", "daggerdbl", + "periodcentered",NULL, "paragraph", "bullet", + "quotesinglbase","quotedblbase","quotedblright","guillemotright", + "ellipsis", "perthousand", NULL, "questiondown", + /* 192 */ + NULL, "grave", "acute", "circumflex", + "tilde", "macron", "breve", "dotaccent", + "dieresis", NULL, "ring", "cedilla", + NULL, "hungarumlaut", "ogonek", "caron", + /* 208 */ + "emdash", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, + /* 224 */ + NULL, "AE", NULL, "ordfeminine", + NULL, NULL, NULL, NULL, + "Lslash", "Oslash", "OE", "ordmasculine", + NULL, NULL, NULL, NULL, + /* 240 */ + NULL, "ae", NULL, NULL, + NULL, "dotlessi", NULL, NULL, + "lslash", "oslash", "oe", "germandbls", + NULL, NULL, NULL, NULL }; static void @@ -859,7 +902,6 @@ cairo_type1_font_subset_write (cairo_type1_font_subset_t *font, } font->eexec_key = private_dict_key; - font->hex_encode = TRUE; font->hex_column = 0; cairo_type1_font_subset_write_private_dict (font, name); @@ -929,7 +971,7 @@ static void cairo_type1_font_subset_destroy (void *abstract_font) { cairo_type1_font_subset_t *font = abstract_font; - int i; + unsigned int i; /* If the subset generation failed, some of the pointers below may * be NULL depending on at which point the error occurred. */ @@ -953,12 +995,13 @@ cairo_type1_font_subset_destroy (void *abstract_font) cairo_status_t _cairo_type1_subset_init (cairo_type1_subset_t *type1_subset, const char *name, - cairo_scaled_font_subset_t *scaled_font_subset) + cairo_scaled_font_subset_t *scaled_font_subset, + cairo_bool_t hex_encode) { cairo_type1_font_subset_t *font; cairo_status_t status; unsigned long parent_glyph, length; - int i; + unsigned int i; cairo_unscaled_font_t *unscaled_font; /* XXX: Need to fix this to work with a general cairo_unscaled_font_t. */ @@ -967,7 +1010,7 @@ _cairo_type1_subset_init (cairo_type1_subset_t *type1_subset, unscaled_font = _cairo_ft_scaled_font_get_unscaled_font (scaled_font_subset->scaled_font); - status = _cairo_type1_font_subset_create (unscaled_font, &font); + status = _cairo_type1_font_subset_create (unscaled_font, &font, hex_encode); if (status) return status; @@ -1038,4 +1081,3 @@ _cairo_type1_subset_fini (cairo_type1_subset_t *subset) free (subset->widths); free (subset->data); } - diff --git a/gfx/cairo/cairo/src/cairo-win32-font.c b/gfx/cairo/cairo/src/cairo-win32-font.c index c7817e1c1de6..ee8cd3e76e49 100644 --- a/gfx/cairo/cairo/src/cairo-win32-font.c +++ b/gfx/cairo/cairo/src/cairo-win32-font.c @@ -50,6 +50,8 @@ #define TT_PRIM_CSPLINE 3 #endif +#define OPENTYPE_CFF_TAG 0x20464643 + const cairo_scaled_font_backend_t cairo_win32_scaled_font_backend; typedef struct { @@ -97,6 +99,8 @@ typedef struct { HFONT scaled_hfont; HFONT unscaled_hfont; + cairo_bool_t glyph_indexing; + cairo_bool_t delete_scaled_hfont; } cairo_win32_scaled_font_t; @@ -233,6 +237,8 @@ _win32_scaled_font_create (LOGFONTW *logfont, cairo_matrix_t scale; cairo_status_t status; + _cairo_win32_initialize (); + f = malloc (sizeof(cairo_win32_scaled_font_t)); if (f == NULL) return NULL; @@ -464,6 +470,8 @@ _cairo_win32_scaled_font_create_toy (cairo_toy_font_face_t *toy_face, int face_name_len; cairo_status_t status; + _cairo_win32_initialize (); + status = _cairo_utf8_to_utf16 (toy_face->family, -1, &face_name, &face_name_len); if (status) @@ -720,6 +728,12 @@ _cairo_win32_scaled_font_set_metrics (cairo_win32_scaled_font_t *scaled_font) } + if ((metrics.tmPitchAndFamily & TMPF_TRUETYPE) || + (GetFontData (hdc, OPENTYPE_CFF_TAG, 0, NULL, 0) != GDI_ERROR)) + scaled_font->glyph_indexing = TRUE; + else + scaled_font->glyph_indexing = FALSE; + _cairo_scaled_font_set_metrics (&scaled_font->base, &extents); return CAIRO_STATUS_SUCCESS; @@ -734,12 +748,18 @@ _cairo_win32_scaled_font_init_glyph_metrics (cairo_win32_scaled_font_t *scaled_f cairo_status_t status; cairo_text_extents_t extents; HDC hdc; + UINT glyph_index_option; hdc = _get_global_font_dc (); if (!hdc) return CAIRO_STATUS_NO_MEMORY; - if (scaled_font->preserve_axes) { + if (scaled_font->glyph_indexing) + glyph_index_option = GGO_GLYPH_INDEX; + else + glyph_index_option = 0; + + if (scaled_font->preserve_axes && scaled_font->base.options.hint_style != CAIRO_HINT_METRICS_OFF) { /* If we aren't rotating / skewing the axes, then we get the metrics * from the GDI in device space and convert to font space. */ @@ -747,7 +767,7 @@ _cairo_win32_scaled_font_init_glyph_metrics (cairo_win32_scaled_font_t *scaled_f if (status) return status; if (GetGlyphOutlineW (hdc, _cairo_scaled_glyph_index (scaled_glyph), - GGO_METRICS | GGO_GLYPH_INDEX, + GGO_METRICS | glyph_index_option, &metrics, 0, NULL, &matrix) == GDI_ERROR) { status = _cairo_win32_print_gdi_error ("_cairo_win32_scaled_font_init_glyph_metrics:GetGlyphOutlineW"); memset (&metrics, 0, sizeof (GLYPHMETRICS)); @@ -786,7 +806,7 @@ _cairo_win32_scaled_font_init_glyph_metrics (cairo_win32_scaled_font_t *scaled_f */ status = _cairo_win32_scaled_font_select_unscaled_font (&scaled_font->base, hdc); if (GetGlyphOutlineW (hdc, _cairo_scaled_glyph_index (scaled_glyph), - GGO_METRICS | GGO_GLYPH_INDEX, + GGO_METRICS | glyph_index_option, &metrics, 0, NULL, &matrix) == GDI_ERROR) { status = _cairo_win32_print_gdi_error ("_cairo_win32_scaled_font_init_glyph_metrics:GetGlyphOutlineW"); memset (&metrics, 0, sizeof (GLYPHMETRICS)); @@ -829,6 +849,7 @@ _cairo_win32_scaled_font_glyph_bbox (void *abstract_font, GLYPHMETRICS metrics; cairo_status_t status; int i; + UINT glyph_index_option; if (!hdc) return CAIRO_STATUS_NO_MEMORY; @@ -837,11 +858,16 @@ _cairo_win32_scaled_font_glyph_bbox (void *abstract_font, if (status) return status; + if (scaled_font->glyph_indexing) + glyph_index_option = GGO_GLYPH_INDEX; + else + glyph_index_option = 0; + for (i = 0; i < num_glyphs; i++) { int x = floor (0.5 + glyphs[i].x); int y = floor (0.5 + glyphs[i].y); - GetGlyphOutlineW (hdc, glyphs[i].index, GGO_METRICS | GGO_GLYPH_INDEX, + GetGlyphOutlineW (hdc, glyphs[i].index, GGO_METRICS | glyph_index_option, &metrics, 0, NULL, &matrix); if (i == 0 || x1 > x + metrics.gmptGlyphOrigin.x) @@ -897,16 +923,22 @@ _flush_glyphs (cairo_glyph_state_t *state) int dx = 0; WCHAR * elements; int * dx_elements; + UINT glyph_index_option; status = _cairo_array_append (&state->dx, &dx); if (status) return status; + if (state->scaled_font->glyph_indexing) + glyph_index_option = ETO_GLYPH_INDEX; + else + glyph_index_option = 0; + elements = _cairo_array_index (&state->glyphs, 0); dx_elements = _cairo_array_index (&state->dx, 0); if (!ExtTextOutW (state->hdc, state->start_x, state->last_y, - ETO_GLYPH_INDEX, + glyph_index_option, NULL, elements, state->glyphs.num_elements, @@ -1079,7 +1111,7 @@ _compute_a8_mask (cairo_win32_surface_t *mask_surface) return &image8->base; } -static cairo_status_t +static cairo_int_status_t _cairo_win32_scaled_font_glyph_init (void *abstract_font, cairo_scaled_glyph_t *scaled_glyph, cairo_scaled_glyph_info_t info) @@ -1220,10 +1252,45 @@ _cairo_win32_scaled_font_show_glyphs (void *abstract_font, } } -static cairo_fixed_t -_cairo_fixed_from_FIXED (FIXED f) +static cairo_int_status_t +_cairo_win32_scaled_font_load_truetype_table (void *abstract_font, + unsigned long tag, + long offset, + unsigned char *buffer, + unsigned long *length) { - return *((cairo_fixed_t *)&f); + HDC hdc; + cairo_status_t status = CAIRO_STATUS_SUCCESS; + + cairo_win32_scaled_font_t *scaled_font = abstract_font; + hdc = _get_global_font_dc (); + if (!hdc) + return CAIRO_STATUS_NO_MEMORY; + + tag = (tag&0x000000ff)<<24 | (tag&0x0000ff00)<<8 | (tag&0x00ff0000)>>8 | (tag&0xff000000)>>24; + status = _cairo_win32_scaled_font_select_unscaled_font (&scaled_font->base, hdc); + + *length = GetFontData (hdc, tag, offset, buffer, *length); + if (*length == GDI_ERROR) + status = CAIRO_INT_STATUS_UNSUPPORTED; + + _cairo_win32_scaled_font_done_unscaled_font (&scaled_font->base); + + return status; +} + +static void +_cairo_win32_transform_FIXED_to_fixed (cairo_matrix_t *matrix, + FIXED Fx, FIXED Fy, + cairo_fixed_t *fx, cairo_fixed_t *fy) +{ + double x, y; + + x = _cairo_fixed_to_double (*((cairo_fixed_t *)&Fx)); + y = _cairo_fixed_to_double (*((cairo_fixed_t *)&Fy)); + cairo_matrix_transform_point (matrix, &x, &y); + *fx = _cairo_fixed_from_double (x); + *fy = _cairo_fixed_from_double (y); } static cairo_status_t @@ -1237,6 +1304,9 @@ _cairo_win32_scaled_font_init_glyph_path (cairo_win32_scaled_font_t *scaled_font DWORD bytesGlyph; unsigned char *buffer, *ptr; cairo_path_fixed_t *path; + cairo_matrix_t transform; + cairo_fixed_t x, y; + UINT glyph_index_option; hdc = _get_global_font_dc (); if (!hdc) @@ -1246,12 +1316,24 @@ _cairo_win32_scaled_font_init_glyph_path (cairo_win32_scaled_font_t *scaled_font if (!path) return CAIRO_STATUS_NO_MEMORY; - status = cairo_win32_scaled_font_select_font (&scaled_font->base, hdc); + if (scaled_font->base.options.hint_style == CAIRO_HINT_STYLE_NONE) { + status = _cairo_win32_scaled_font_select_unscaled_font (&scaled_font->base, hdc); + transform = scaled_font->base.scale; + cairo_matrix_scale (&transform, 1.0/scaled_font->em_square, 1.0/scaled_font->em_square); + } else { + status = cairo_win32_scaled_font_select_font (&scaled_font->base, hdc); + cairo_matrix_init_identity(&transform); + } if (status) goto CLEANUP_PATH; + if (scaled_font->glyph_indexing) + glyph_index_option = GGO_GLYPH_INDEX; + else + glyph_index_option = 0; + bytesGlyph = GetGlyphOutlineW (hdc, _cairo_scaled_glyph_index (scaled_glyph), - GGO_NATIVE | GGO_GLYPH_INDEX, + GGO_NATIVE | glyph_index_option, &metrics, 0, NULL, &matrix); if (bytesGlyph == GDI_ERROR) { @@ -1267,7 +1349,7 @@ _cairo_win32_scaled_font_init_glyph_path (cairo_win32_scaled_font_t *scaled_font } if (GetGlyphOutlineW (hdc, _cairo_scaled_glyph_index (scaled_glyph), - GGO_NATIVE | GGO_GLYPH_INDEX, + GGO_NATIVE | glyph_index_option, &metrics, bytesGlyph, buffer, &matrix) == GDI_ERROR) { status = _cairo_win32_print_gdi_error ("_cairo_win32_scaled_font_glyph_path"); free (buffer); @@ -1280,9 +1362,11 @@ _cairo_win32_scaled_font_init_glyph_path (cairo_win32_scaled_font_t *scaled_font ptr += sizeof (TTPOLYGONHEADER); - _cairo_path_fixed_move_to (path, - _cairo_fixed_from_FIXED (header->pfxStart.x), - _cairo_fixed_from_FIXED (header->pfxStart.y)); + _cairo_win32_transform_FIXED_to_fixed (&transform, + header->pfxStart.x, + header->pfxStart.y, + &x, &y); + _cairo_path_fixed_move_to (path, x, y); while (ptr < endPoly) { TTPOLYCURVE *curve = (TTPOLYCURVE *)ptr; @@ -1291,26 +1375,36 @@ _cairo_win32_scaled_font_init_glyph_path (cairo_win32_scaled_font_t *scaled_font switch (curve->wType) { case TT_PRIM_LINE: for (i = 0; i < curve->cpfx; i++) { - _cairo_path_fixed_line_to (path, - _cairo_fixed_from_FIXED (points[i].x), - _cairo_fixed_from_FIXED (points[i].y)); + _cairo_win32_transform_FIXED_to_fixed (&transform, + points[i].x, + points[i].y, + &x, &y); + _cairo_path_fixed_line_to (path, x, y); } break; case TT_PRIM_QSPLINE: for (i = 0; i < curve->cpfx - 1; i++) { cairo_fixed_t p1x, p1y, p2x, p2y, cx, cy, c1x, c1y, c2x, c2y; _cairo_path_fixed_get_current_point (path, &p1x, &p1y); - cx = _cairo_fixed_from_FIXED (points[i].x); - cy = _cairo_fixed_from_FIXED (points[i].y); + _cairo_win32_transform_FIXED_to_fixed (&transform, + points[i].x, + points[i].y, + &cx, &cy); if (i + 1 == curve->cpfx - 1) { - p2x = _cairo_fixed_from_FIXED (points[i + 1].x); - p2y = _cairo_fixed_from_FIXED (points[i + 1].y); + _cairo_win32_transform_FIXED_to_fixed (&transform, + points[i + 1].x, + points[i + 1].y, + &p2x, &p2y); } else { /* records with more than one curve use interpolation for control points, per http://support.microsoft.com/kb/q87115/ */ - p2x = (cx + _cairo_fixed_from_FIXED (points[i + 1].x)) / 2; - p2y = (cy + _cairo_fixed_from_FIXED (points[i + 1].y)) / 2; + _cairo_win32_transform_FIXED_to_fixed (&transform, + points[i + 1].x, + points[i + 1].y, + &x, &y); + p2x = (cx + x) / 2; + p2y = (cy + y) / 2; } c1x = 2 * cx / 3 + p1x / 3; @@ -1323,13 +1417,20 @@ _cairo_win32_scaled_font_init_glyph_path (cairo_win32_scaled_font_t *scaled_font break; case TT_PRIM_CSPLINE: for (i = 0; i < curve->cpfx - 2; i += 2) { - _cairo_path_fixed_curve_to (path, - _cairo_fixed_from_FIXED (points[i].x), - _cairo_fixed_from_FIXED (points[i].y), - _cairo_fixed_from_FIXED (points[i + 1].x), - _cairo_fixed_from_FIXED (points[i + 1].y), - _cairo_fixed_from_FIXED (points[i + 2].x), - _cairo_fixed_from_FIXED (points[i + 2].y)); + cairo_fixed_t x1, y1, x2, y2; + _cairo_win32_transform_FIXED_to_fixed (&transform, + points[i].x, + points[i].y, + &x, &y); + _cairo_win32_transform_FIXED_to_fixed (&transform, + points[i + 1].x, + points[i + 1].y, + &x1, &y1); + _cairo_win32_transform_FIXED_to_fixed (&transform, + points[i + 2].x, + points[i + 2].y, + &x2, &y2); + _cairo_path_fixed_curve_to (path, x, y, x1, y1, x2, y2); } break; } @@ -1363,6 +1464,7 @@ const cairo_scaled_font_backend_t cairo_win32_scaled_font_backend = { _cairo_win32_scaled_font_text_to_glyphs, NULL, /* ucs4_to_index */ _cairo_win32_scaled_font_show_glyphs, + _cairo_win32_scaled_font_load_truetype_table, }; /* cairo_win32_font_face_t */ @@ -1391,6 +1493,8 @@ _cairo_win32_font_face_scaled_font_create (void *abstract_face, { cairo_win32_font_face_t *font_face = abstract_face; + _cairo_win32_initialize (); + *font = _win32_scaled_font_create (&font_face->logfont, font_face->hfont, &font_face->base, @@ -1428,6 +1532,8 @@ cairo_win32_font_face_create_for_logfontw (LOGFONTW *logfont) { cairo_win32_font_face_t *font_face; + _cairo_win32_initialize (); + font_face = malloc (sizeof (cairo_win32_font_face_t)); if (!font_face) { _cairo_error (CAIRO_STATUS_NO_MEMORY); @@ -1461,6 +1567,8 @@ cairo_win32_font_face_create_for_hfont (HFONT font) { cairo_win32_font_face_t *font_face; + _cairo_win32_initialize (); + font_face = malloc (sizeof (cairo_win32_font_face_t)); if (!font_face) { _cairo_error (CAIRO_STATUS_NO_MEMORY); @@ -1563,9 +1671,6 @@ cairo_win32_scaled_font_done_font (cairo_scaled_font_t *scaled_font) double cairo_win32_scaled_font_get_metrics_factor (cairo_scaled_font_t *scaled_font) { - if (cairo_scaled_font_get_type (scaled_font) != CAIRO_FONT_TYPE_WIN32) - return 1.0; - return 1. / ((cairo_win32_scaled_font_t *)scaled_font)->logical_scale; } @@ -1574,9 +1679,6 @@ cairo_win32_scaled_font_get_logical_to_device (cairo_scaled_font_t *scaled_font, cairo_matrix_t *logical_to_device) { cairo_win32_scaled_font_t *win_font = (cairo_win32_scaled_font_t *)scaled_font; - if (cairo_scaled_font_get_type (scaled_font) != CAIRO_FONT_TYPE_WIN32) - return; - *logical_to_device = win_font->logical_to_device; } @@ -1585,8 +1687,5 @@ cairo_win32_scaled_font_get_device_to_logical (cairo_scaled_font_t *scaled_font, cairo_matrix_t *device_to_logical) { cairo_win32_scaled_font_t *win_font = (cairo_win32_scaled_font_t *)scaled_font; - if (cairo_scaled_font_get_type (scaled_font) != CAIRO_FONT_TYPE_WIN32) - return; - *device_to_logical = win_font->device_to_logical; } diff --git a/gfx/cairo/cairo/src/cairo-win32-private.h b/gfx/cairo/cairo/src/cairo-win32-private.h index b9c9ce1a6ff1..872c74e6b5bb 100644 --- a/gfx/cairo/cairo/src/cairo-win32-private.h +++ b/gfx/cairo/cairo/src/cairo-win32-private.h @@ -102,4 +102,7 @@ _cairo_win32_print_gdi_error (const char *context); cairo_bool_t _cairo_surface_is_win32 (cairo_surface_t *surface); +void +_cairo_win32_initialize (); + #endif /* CAIRO_WIN32_PRIVATE_H */ diff --git a/gfx/cairo/cairo/src/cairo-win32-surface.c b/gfx/cairo/cairo/src/cairo-win32-surface.c index 6fec274c7ea6..31ac9b1ce347 100644 --- a/gfx/cairo/cairo/src/cairo-win32-surface.c +++ b/gfx/cairo/cairo/src/cairo-win32-surface.c @@ -1,4 +1,4 @@ -/* -*- Mode: c; c-basic-offset: 4; indent-tabs-mode: t; tab-width: 8; -*- */ +/* -*- Mode: c; tab-width: 8; c-basic-offset: 4; indent-tabs-mode: t; -*- */ /* Cairo - a vector graphics library with display and print output * * Copyright © 2005 Red Hat, Inc. @@ -49,6 +49,9 @@ #define SB_NONE 0x00000000 #endif +#define PELS_72DPI (72. / 0.0254) +#define NIL_SURFACE ((cairo_surface_t*)&_cairo_surface_nil) + static const cairo_surface_backend_t cairo_win32_surface_backend; /** @@ -104,7 +107,7 @@ _cairo_win32_flags_for_dc (HDC dc) */ flags |= CAIRO_WIN32_SURFACE_CAN_BITBLT; flags |= CAIRO_WIN32_SURFACE_CAN_ALPHABLEND; - /*flags |= CAIRO_WIN32_SURFACE_CAN_STRETCHBLT;*/ + flags |= CAIRO_WIN32_SURFACE_CAN_STRETCHBLT; } else { int cap; @@ -115,10 +118,8 @@ _cairo_win32_flags_for_dc (HDC dc) cap = GetDeviceCaps(dc, RASTERCAPS); if (cap & RC_BITBLT) flags |= CAIRO_WIN32_SURFACE_CAN_BITBLT; -/* if (cap & RC_STRETCHBLT) flags |= CAIRO_WIN32_SURFACE_CAN_STRETCHBLT; -*/ } return flags; @@ -176,8 +177,8 @@ _create_dc_and_bitmap (cairo_win32_surface_t *surface, bitmap_info->bmiHeader.biWidth = width == 0 ? 1 : width; bitmap_info->bmiHeader.biHeight = height == 0 ? -1 : - height; /* top-down */ bitmap_info->bmiHeader.biSizeImage = 0; - bitmap_info->bmiHeader.biXPelsPerMeter = 72. / 0.0254; /* unused here */ - bitmap_info->bmiHeader.biYPelsPerMeter = 72. / 0.0254; /* unused here */ + bitmap_info->bmiHeader.biXPelsPerMeter = PELS_72DPI; /* unused here */ + bitmap_info->bmiHeader.biYPelsPerMeter = PELS_72DPI; /* unused here */ bitmap_info->bmiHeader.biPlanes = 1; switch (format) { @@ -185,6 +186,8 @@ _create_dc_and_bitmap (cairo_win32_surface_t *surface, * break if we do, especially if we don't set up an image * fallback. It could be a bug with using a 24bpp pixman image * (and creating one with masks). So treat them like 32bpp. + * NOTE: This causes problems when using BitBlt/AlphaBlend/etc! + * see end of file. */ case CAIRO_FORMAT_RGB24: case CAIRO_FORMAT_ARGB32: @@ -308,10 +311,12 @@ _cairo_win32_surface_create_for_dc (HDC original_dc, char *bits; int rowstride; + _cairo_win32_initialize (); + surface = malloc (sizeof (cairo_win32_surface_t)); if (surface == NULL) { _cairo_error (CAIRO_STATUS_NO_MEMORY); - return &_cairo_surface_nil; + return NIL_SURFACE; } status = _create_dc_and_bitmap (surface, original_dc, format, @@ -358,10 +363,10 @@ _cairo_win32_surface_create_for_dc (HDC original_dc, if (status == CAIRO_STATUS_NO_MEMORY) { _cairo_error (CAIRO_STATUS_NO_MEMORY); - return &_cairo_surface_nil; + return NIL_SURFACE; } else { _cairo_error (status); - return &_cairo_surface_nil; + return NIL_SURFACE; } } @@ -441,7 +446,7 @@ _cairo_win32_surface_get_subimage (cairo_win32_surface_t *surface, cairo_win32_surface_t **local_out) { cairo_win32_surface_t *local; - cairo_status_t status; + cairo_int_status_t status; cairo_content_t content = _cairo_content_from_format (surface->format); local = @@ -450,13 +455,22 @@ _cairo_win32_surface_get_subimage (cairo_win32_surface_t *surface, if (local->base.status) return CAIRO_STATUS_NO_MEMORY; - if (!BitBlt (local->dc, - 0, 0, - width, height, - surface->dc, - x, y, - SRCCOPY)) { - /* If we fail to BitBlt here, most likely the source is a printer. + status = CAIRO_INT_STATUS_UNSUPPORTED; + + if ((local->flags & CAIRO_WIN32_SURFACE_CAN_BITBLT) && + BitBlt (local->dc, + 0, 0, + width, height, + surface->dc, + x, y, + SRCCOPY)) + { + status = CAIRO_STATUS_SUCCESS; + } + + if (status) { + /* If we failed here, most likely the source or dest doesn't + * support BitBlt/AlphaBlend (e.g. a printer). * You can't reliably get bits from a printer DC, so just fill in * the surface as white (common case for printing). */ @@ -471,14 +485,6 @@ _cairo_win32_surface_get_subimage (cairo_win32_surface_t *surface, *local_out = local; return CAIRO_STATUS_SUCCESS; - - FAIL: - status = _cairo_win32_print_gdi_error ("_cairo_win32_surface_get_subimage"); - - if (local) - cairo_surface_destroy (&local->base); - - return status; } static cairo_status_t @@ -690,10 +696,21 @@ _composite_alpha_blend (cairo_win32_surface_t *dst, if (!(dst->flags & CAIRO_WIN32_SURFACE_CAN_ALPHABLEND)) return CAIRO_INT_STATUS_UNSUPPORTED; + if (src->format == CAIRO_FORMAT_RGB24 && dst->format == CAIRO_FORMAT_ARGB32) + { + /* Both of these are represented as 32bpp internally, and AlphaBlend + * DOES NOT throw away source alpha is AC_SRC_ALPHA is not specified, + * it just multiplies it by the SourceConstantAlpha, along with the + * R G B components. + * XXX there has to be a way to do this! + */ + return CAIRO_INT_STATUS_UNSUPPORTED; + } + blend_function.BlendOp = AC_SRC_OVER; blend_function.BlendFlags = 0; blend_function.SourceConstantAlpha = alpha; - blend_function.AlphaFormat = src->format == CAIRO_FORMAT_ARGB32 ? AC_SRC_ALPHA : 0; + blend_function.AlphaFormat = (src->format == CAIRO_FORMAT_ARGB32) ? AC_SRC_ALPHA : 0; /*oldstretchmode = SetStretchBltMode(dst->dc, HALFTONE);*/ if (!alpha_blend (dst->dc, @@ -730,11 +747,19 @@ _cairo_win32_surface_composite (cairo_operator_t op, int itx, ity; double scalex, scaley; cairo_fixed_t x0_fixed, y0_fixed; + int orig_dst_x = dst_x, orig_dst_y = dst_y; + int real_src_width, real_src_height; int src_width, src_height; int dst_width, dst_height; - + cairo_bool_t needs_alpha, needs_scale; + cairo_image_surface_t *src_image = NULL; + +#if 0 + fprintf (stderr, "composite: %d %p %p %p [%d %d] [%d %d] [%d %d] %dx%d\n", + op, pattern, mask_pattern, abstract_dst, src_x, src_y, mask_x, mask_y, dst_x, dst_y, width, height); +#endif /* If the destination can't do any of these, then * we may as well give up, since this is what we'll @@ -769,8 +794,20 @@ _cairo_win32_surface_composite (cairo_operator_t op, src_surface_pattern = (cairo_surface_pattern_t *)pattern; src = (cairo_win32_surface_t *)src_surface_pattern->surface; - if (src->base.backend != dst->base.backend) + /* Disable this StretchDIBits optimization for now */ +#if 0 + if (src->base.type == CAIRO_SURFACE_TYPE_IMAGE) { + src_image = (cairo_image_surface_t*) src; + + if (src_image->format != CAIRO_FORMAT_RGB24 || + alpha != 255 || + src_image->stride != (src_image->width * 4)) + return CAIRO_INT_STATUS_UNSUPPORTED; + } else +#endif + if (src->base.backend != dst->base.backend) { return CAIRO_INT_STATUS_UNSUPPORTED; + } #if 0 fprintf (stderr, "Before check: (%d %d) [%d %d] -> [%d %d %d %d] {mat %f %f %f %f}\n", @@ -793,7 +830,7 @@ _cairo_win32_surface_composite (cairo_operator_t op, { return CAIRO_INT_STATUS_UNSUPPORTED; } - + itx = _cairo_fixed_integer_part(x0_fixed); ity = _cairo_fixed_integer_part(y0_fixed); @@ -803,105 +840,67 @@ _cairo_win32_surface_composite (cairo_operator_t op, src_x += itx; src_y += ity; -#if 0 - if (scalex != 1.0 || scaley != 1.0) { - /* we already know that the destination is an integer rectangle; - * we need to see if the source is also. - */ - cairo_fixed_t sx0 = _cairo_fixed_from_double(src_x * scalex); - cairo_fixed_t sy0 = _cairo_fixed_from_double(src_y * scaley); - cairo_fixed_t sw = _cairo_fixed_from_double((src->extents.width - src_x) * scalex); - cairo_fixed_t sh = _cairo_fixed_from_double((src->extents.height - src_y) * scaley); - - fprintf (stderr, "sx0 sy0 sw sh: %f %f %f %f\n", - _cairo_fixed_to_double(sx0), _cairo_fixed_to_double(sy0), - _cairo_fixed_to_double(sw), _cairo_fixed_to_double(sh)); - - if (!_cairo_fixed_is_integer(sw) || - !_cairo_fixed_is_integer(sh) || - !_cairo_fixed_is_integer(sx0) || - !_cairo_fixed_is_integer(sy0)) - { - return CAIRO_INT_STATUS_UNSUPPORTED; - } - } -#endif - if (scalex <= 0.0 || scaley <= 0.0) return CAIRO_STATUS_SUCCESS; -#if 0 - fprintf (stderr, "Before fixup: (%d %d) src: [%d %d] -> dst: [%d %d %d %d] itsc {%d %d %f %f}\n", - src->extents.width, src->extents.height, - src_x, src_y, - dst_x, dst_y, width, height, - itx, ity, scalex, scaley); -#endif + if (scalex != 1.0 || scaley != 1.0) + return CAIRO_INT_STATUS_UNSUPPORTED; - /* Fix up src coordinates; the src coords and size must be within the - * bounds of the source surface. - * XXX the region not covered should be appropriately rendered! - * - for OVER/SOURCE with RGB24 source -> opaque black - * - for SOURCE with ARGB32 source -> 100% transparent black + /* If the src coordinates are outside of the source surface bounds, + * we have to fix them up, because this is an error for the GDI + * functions. + * XXX Make sure to correctly clear out the unpainted region. */ - src_x *= scalex; - src_y *= scaley; if (src_x < 0) { - width += src_x / scalex; - dst_x -= src_x / scalex; + width += src_x; + dst_x -= src_x; src_x = 0; } if (src_y < 0) { - height += src_y / scaley; - dst_y -= src_y / scaley; + height += src_y; + dst_y -= src_y; src_y = 0; } - if (src_x + width > (src->extents.width / scalex)) - dst_width = (src->extents.width / scalex) - src_x; + if (src_x + width > src->extents.width) + dst_width = src->extents.width - src_x; else dst_width = width; - if (src_y + height > (src->extents.height / scaley)) - dst_height = (src->extents.height / scaley) - src_y; + if (src_y + height > src->extents.height) + dst_height = src->extents.height - src_y; else dst_height = height; - /* If we're scaling up an iamge, we may have - * less than 1 pixel's worth of width/height map - * into 1 row in the destination. If this is the case, - * we need to clip to the destination's width/height, - * and then figure out the next source/dest width/height combo - * where there is an integer match. - * - * For now, just let cairo scale that case. THIS IS NOT IDEAL, - * as the scaling algorithms aren't identical! + + src_width = dst_width; + src_height = dst_height; + + /* + * Figure out what action to take. + * XXX handle SOURCE with alpha != 255 */ - if (!_cairo_fixed_is_integer(_cairo_fixed_from_double(dst_width * scalex)) || - !_cairo_fixed_is_integer(_cairo_fixed_from_double(dst_height * scaley))) - return CAIRO_INT_STATUS_UNSUPPORTED; - - src_width = dst_width * scalex; - src_height = dst_height * scaley; - if (alpha == 255 && - (op == CAIRO_OPERATOR_SOURCE || - (src->format == CAIRO_FORMAT_RGB24 && op == CAIRO_OPERATOR_OVER))) + (dst->format == src->format) && + ((op == CAIRO_OPERATOR_SOURCE && (dst->format == CAIRO_FORMAT_ARGB32 || + dst->format == CAIRO_FORMAT_RGB24)) || + (op == CAIRO_OPERATOR_OVER && dst->format == CAIRO_FORMAT_RGB24))) { needs_alpha = FALSE; - } else if ((src->format == CAIRO_FORMAT_RGB24 || src->format == CAIRO_FORMAT_ARGB32) && - (dst->format == CAIRO_FORMAT_RGB24 || dst->format == CAIRO_FORMAT_ARGB32) && - op == CAIRO_OPERATOR_OVER) + } else if ((op == CAIRO_OPERATOR_OVER || op == CAIRO_OPERATOR_SOURCE) && + (src->format == CAIRO_FORMAT_RGB24 || src->format == CAIRO_FORMAT_ARGB32) && + (dst->format == CAIRO_FORMAT_RGB24 || dst->format == CAIRO_FORMAT_ARGB32)) { needs_alpha = TRUE; } else { return CAIRO_INT_STATUS_UNSUPPORTED; } - + if (scalex == 1.0 && scaley == 1.0) { needs_scale = FALSE; } else { + /* Should never be reached until we turn StretchBlt back on */ needs_scale = TRUE; } @@ -912,8 +911,32 @@ _cairo_win32_surface_composite (cairo_operator_t op, fflush (stderr); #endif - /* Then do BitBlt, StretchBlt, AlphaBlend, or MaskBlt */ - if (!needs_alpha) { + /* Then do BitBlt, StretchDIBits, StretchBlt, AlphaBlend, or MaskBlt */ + if (src_image) { + BITMAPINFO bi; + bi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER); + bi.bmiHeader.biWidth = src_image->width; + bi.bmiHeader.biHeight = src_image->height; + bi.bmiHeader.biSizeImage = 0; + bi.bmiHeader.biXPelsPerMeter = PELS_72DPI; + bi.bmiHeader.biYPelsPerMeter = PELS_72DPI; + bi.bmiHeader.biPlanes = 1; + bi.bmiHeader.biBitCount = 32; + bi.bmiHeader.biCompression = BI_RGB; + bi.bmiHeader.biClrUsed = 0; + bi.bmiHeader.biClrImportant = 0; + + if (!StretchDIBits (dst->dc, + dst_x, dst_y, dst_width, dst_height, + src_x, src_y, src_width, src_height, + src_image->data, + &bi, + DIB_RGB_COLORS, + SRCCOPY)) + return _cairo_win32_print_gdi_error ("_cairo_win32_surface_composite(StretchDIBits)"); + + return CAIRO_STATUS_SUCCESS; + } else if (!needs_alpha) { /* BitBlt or StretchBlt? */ if (!needs_scale && (dst->flags & CAIRO_WIN32_SURFACE_CAN_BITBLT)) { if (!BitBlt (dst->dc, @@ -922,15 +945,14 @@ _cairo_win32_surface_composite (cairo_operator_t op, src->dc, src_x, src_y, SRCCOPY)) - return _cairo_win32_print_gdi_error ("_cairo_win32_surface_composite"); + return _cairo_win32_print_gdi_error ("_cairo_win32_surface_composite(BitBlt)"); return CAIRO_STATUS_SUCCESS; } else if (dst->flags & CAIRO_WIN32_SURFACE_CAN_STRETCHBLT) { /* StretchBlt? */ /* XXX check if we want HALFTONE, based on the src filter */ - int oldmode = SetStretchBltMode(dst->dc, HALFTONE); BOOL success; - + int oldmode = SetStretchBltMode(dst->dc, HALFTONE); success = StretchBlt(dst->dc, dst_x, dst_y, dst_width, dst_height, @@ -944,11 +966,11 @@ _cairo_win32_surface_composite (cairo_operator_t op, _cairo_win32_print_gdi_error ("StretchBlt"); return CAIRO_INT_STATUS_UNSUPPORTED; } - + return CAIRO_STATUS_SUCCESS; } } else if (needs_alpha && !needs_scale) { - return _composite_alpha_blend (dst, src, alpha, + return _composite_alpha_blend (dst, src, alpha, src_x, src_y, src_width, src_height, dst_x, dst_y, dst_width, dst_height); } @@ -1348,13 +1370,15 @@ cairo_win32_surface_create (HDC hdc) int depth; cairo_format_t format; + _cairo_win32_initialize (); + /* Try to figure out the drawing bounds for the Device context */ if (GetClipBox (hdc, &rect) == ERROR) { _cairo_win32_print_gdi_error ("cairo_win32_surface_create"); /* XXX: Can we make a more reasonable guess at the error cause here? */ _cairo_error (CAIRO_STATUS_NO_MEMORY); - return &_cairo_surface_nil; + return NIL_SURFACE; } if (GetDeviceCaps(hdc, TECHNOLOGY) == DT_RASDISPLAY) { @@ -1372,7 +1396,7 @@ cairo_win32_surface_create (HDC hdc) else { _cairo_win32_print_gdi_error("cairo_win32_surface_create(bad BITSPIXEL)"); _cairo_error (CAIRO_STATUS_NO_MEMORY); - return &_cairo_surface_nil; + return NIL_SURFACE; } } else { format = CAIRO_FORMAT_RGB24; @@ -1381,7 +1405,7 @@ cairo_win32_surface_create (HDC hdc) surface = malloc (sizeof (cairo_win32_surface_t)); if (surface == NULL) { _cairo_error (CAIRO_STATUS_NO_MEMORY); - return &_cairo_surface_nil; + return NIL_SURFACE; } surface->image = NULL; @@ -1398,15 +1422,15 @@ cairo_win32_surface_create (HDC hdc) surface->clip_rect.height = rect.bottom - rect.top; if (surface->clip_rect.width == 0 || - surface->clip_rect.height == 0) + surface->clip_rect.height == 0) { - surface->saved_clip = NULL; + surface->saved_clip = NULL; } else { - surface->saved_clip = CreateRectRgn (0, 0, 0, 0); - if (GetClipRgn (hdc, surface->saved_clip) == 0) { - DeleteObject(surface->saved_clip); - surface->saved_clip = NULL; - } + surface->saved_clip = CreateRectRgn (0, 0, 0, 0); + if (GetClipRgn (hdc, surface->saved_clip) == 0) { + DeleteObject(surface->saved_clip); + surface->saved_clip = NULL; + } } surface->extents = surface->clip_rect; @@ -1435,17 +1459,31 @@ cairo_win32_surface_create (HDC hdc) **/ cairo_surface_t * cairo_win32_surface_create_with_dib (cairo_format_t format, - int width, - int height) + int width, + int height) { return _cairo_win32_surface_create_for_dc (NULL, format, width, height); } +/** + * cairo_win32_surface_create_with_ddb: + * @format: format of pixels in the surface to create + * @width: width of the surface, in pixels + * @height: height of the surface, in pixels + * + * Creates a device-independent-bitmap surface not associated with + * any particular existing surface or device context. The created + * bitmap will be unititialized. + * + * Return value: the newly created surface + * + * Since: 1.4 + **/ cairo_surface_t * cairo_win32_surface_create_with_ddb (HDC hdc, - cairo_format_t format, - int width, - int height) + cairo_format_t format, + int width, + int height) { cairo_win32_surface_t *new_surf; HBITMAP ddb; @@ -1536,8 +1574,10 @@ cairo_win32_surface_get_dc (cairo_surface_t *surface) * as the DIB of the Win32 surface. If the passed-in win32 surface * is not a DIB surface, NULL is returned. * - * Return value: a #cairo_surface_t (reference owned by the win32 cairo_surface_t), + * Return value: a #cairo_surface_t (owned by the win32 cairo_surface_t), * or NULL if the win32 surface is not a DIB. + * + * Since: 1.4 */ cairo_surface_t * cairo_win32_surface_get_image (cairo_surface_t *surface) @@ -1581,18 +1621,34 @@ static const cairo_surface_backend_t cairo_win32_surface_backend = { NULL /* snapshot */ }; -#if 0 /* * Without pthread, on win32 we need to initialize all the 'mutex'es * before use. It is guaranteed that DllMain will get called single * threaded before any other function. * Initializing more than finally needed should not matter much. */ -#ifndef HAVE_PTHREAD_H +#if !defined(HAVE_PTHREAD_H) + CRITICAL_SECTION cairo_toy_font_face_hash_table_mutex; CRITICAL_SECTION cairo_scaled_font_map_mutex; CRITICAL_SECTION cairo_ft_unscaled_font_map_mutex; +static int _cairo_win32_initialized = 0; + +void +_cairo_win32_initialize () { + if (_cairo_win32_initialized) + return; + + /* every 'mutex' from CAIRO_MUTEX_DECALRE needs to be initialized here */ + InitializeCriticalSection (&cairo_toy_font_face_hash_table_mutex); + InitializeCriticalSection (&cairo_scaled_font_map_mutex); + InitializeCriticalSection (&cairo_ft_unscaled_font_map_mutex); + + _cairo_win32_initialized = 1; +} + +#if !defined(CAIRO_WIN32_STATIC_BUILD) BOOL WINAPI DllMain (HINSTANCE hinstDLL, DWORD fdwReason, @@ -1601,10 +1657,7 @@ DllMain (HINSTANCE hinstDLL, switch (fdwReason) { case DLL_PROCESS_ATTACH: - /* every 'mutex' from CAIRO_MUTEX_DECALRE needs to be initialized here */ - InitializeCriticalSection (&cairo_toy_font_face_hash_table_mutex); - InitializeCriticalSection (&cairo_scaled_font_map_mutex); - InitializeCriticalSection (&cairo_ft_unscaled_font_map_mutex); + _cairo_win32_initialize(); break; case DLL_PROCESS_DETACH: DeleteCriticalSection (&cairo_toy_font_face_hash_table_mutex); @@ -1616,3 +1669,17 @@ DllMain (HINSTANCE hinstDLL, } #endif #endif + +/* Notes: + * + * Win32 alpha-understanding functions + * + * BitBlt - will copy full 32 bits from a 32bpp DIB to result + * (so it's safe to use for ARGB32->ARGB32 SOURCE blits) + * (but not safe going RGB24->ARGB32, if RGB24 is also represented + * as a 32bpp DIB, since the alpha isn't discarded!) + * + * AlphaBlend - if both the source and dest have alpha, even if AC_SRC_ALPHA isn't set, + * it will still copy over the src alpha, because the SCA value (255) will be + * multiplied by all the src components. + */ diff --git a/gfx/cairo/cairo/src/cairo-xcb-surface.c b/gfx/cairo/cairo/src/cairo-xcb-surface.c index 15e45e8d9883..f60bc3b32478 100644 --- a/gfx/cairo/cairo/src/cairo-xcb-surface.c +++ b/gfx/cairo/cairo/src/cairo-xcb-surface.c @@ -37,35 +37,10 @@ #include "cairoint.h" #include "cairo-xcb.h" #include "cairo-xcb-xrender.h" +#include #define AllPlanes ((unsigned long)~0L) -static XCBRenderPICTFORMAT -format_from_visual(XCBConnection *c, XCBVISUALID visual) -{ - static const XCBRenderPICTFORMAT nil = { 0 }; - XCBRenderQueryPictFormatsRep *r; - XCBRenderPICTSCREENIter si; - XCBRenderPICTDEPTHIter di; - XCBRenderPICTVISUALIter vi; - - r = XCBRenderQueryPictFormatsReply(c, XCBRenderQueryPictFormats(c), 0); - if(!r) - return nil; - - for(si = XCBRenderQueryPictFormatsScreensIter(r); si.rem; XCBRenderPICTSCREENNext(&si)) - for(di = XCBRenderPICTSCREENDepthsIter(si.data); di.rem; XCBRenderPICTDEPTHNext(&di)) - for(vi = XCBRenderPICTDEPTHVisualsIter(di.data); vi.rem; XCBRenderPICTVISUALNext(&vi)) - if(vi.data->visual.id == visual.id) - { - XCBRenderPICTFORMAT ret = vi.data->format; - free(r); - return ret; - } - - return nil; -} - static cairo_content_t _xcb_render_format_to_content (XCBRenderPICTFORMINFO *xrender_format) { @@ -92,95 +67,6 @@ _xcb_render_format_to_content (XCBRenderPICTFORMINFO *xrender_format) } -/* XXX: Why is this ridiculously complex compared to the equivalent - * function in cairo-xlib-surface.c */ -static XCBRenderPICTFORMINFO -_format_from_cairo(XCBConnection *c, cairo_format_t fmt) -{ - XCBRenderPICTFORMINFO ret = {{ 0 }}; - struct tmpl_t { - XCBRenderDIRECTFORMAT direct; - CARD8 depth; - }; - static const struct tmpl_t templates[] = { - /* CAIRO_FORMAT_ARGB32 */ - { - { - 16, 0xff, - 8, 0xff, - 0, 0xff, - 24, 0xff - }, - 32 - }, - /* CAIRO_FORMAT_RGB24 */ - { - { - 16, 0xff, - 8, 0xff, - 0, 0xff, - 0, 0x00 - }, - 24 - }, - /* CAIRO_FORMAT_A8 */ - { - { - 0, 0x00, - 0, 0x00, - 0, 0x00, - 0, 0xff - }, - 8 - }, - /* CAIRO_FORMAT_A1 */ - { - { - 0, 0x00, - 0, 0x00, - 0, 0x00, - 0, 0x01 - }, - 1 - }, - }; - const struct tmpl_t *tmpl; - XCBRenderQueryPictFormatsRep *r; - XCBRenderPICTFORMINFOIter fi; - - if(fmt < 0 || fmt >= (sizeof(templates) / sizeof(*templates))) - return ret; - tmpl = templates + fmt; - - r = XCBRenderQueryPictFormatsReply(c, XCBRenderQueryPictFormats(c), 0); - if(!r) - return ret; - - for(fi = XCBRenderQueryPictFormatsFormatsIter(r); fi.rem; XCBRenderPICTFORMINFONext(&fi)) - { - const XCBRenderDIRECTFORMAT *t, *f; - if(fi.data->type != XCBRenderPictTypeDirect) - continue; - if(fi.data->depth != tmpl->depth) - continue; - t = &tmpl->direct; - f = &fi.data->direct; - if(t->red_mask && (t->red_mask != f->red_mask || t->red_shift != f->red_shift)) - continue; - if(t->green_mask && (t->green_mask != f->green_mask || t->green_shift != f->green_shift)) - continue; - if(t->blue_mask && (t->blue_mask != f->blue_mask || t->blue_shift != f->blue_shift)) - continue; - if(t->alpha_mask && (t->alpha_mask != f->alpha_mask || t->alpha_shift != f->alpha_shift)) - continue; - - ret = *fi.data; - } - - free(r); - return ret; -} - /* * Instead of taking two round trips for each blending request, * assume that if a particular drawable fails GetImage that it will @@ -209,6 +95,9 @@ typedef struct cairo_xcb_surface { int height; int depth; + XCBRECTANGLE *clip_rects; + int num_clip_rects; + XCBRenderPICTURE picture; XCBRenderPICTFORMINFO format; int has_format; @@ -265,7 +154,7 @@ _cairo_xcb_surface_create_similar (void *abstract_src, XCBDRAWABLE d; cairo_xcb_surface_t *surface; cairo_format_t format = _cairo_format_from_content (content); - XCBRenderPICTFORMINFO xrender_format = _format_from_cairo (dpy, format); + XCBRenderPICTFORMINFO *xrender_format; /* As a good first approximation, if the display doesn't have COMPOSITE, * we're better off using image surfaces for all temporary operations @@ -280,9 +169,11 @@ _cairo_xcb_surface_create_similar (void *abstract_src, width <= 0 ? 1 : width, height <= 0 ? 1 : height); + xrender_format = XCBRenderUtilFindStandardFormat (XCBRenderUtilQueryFormats (dpy), format); + /* XXX: what to do if xrender_format is null? */ surface = (cairo_xcb_surface_t *) cairo_xcb_surface_create_with_xrender_format (dpy, d, src->screen, - &xrender_format, + xrender_format, width, height); if (surface->base.status) { _cairo_error (CAIRO_STATUS_NO_MEMORY); @@ -307,6 +198,8 @@ _cairo_xcb_surface_finish (void *abstract_surface) if (surface->gc.xid) XCBFreeGC (surface->dpy, surface->gc); + free (surface->clip_rects); + surface->dpy = NULL; return CAIRO_STATUS_SUCCESS; @@ -565,6 +458,26 @@ _get_image_surface (cairo_xcb_surface_t *surface, return CAIRO_STATUS_NO_MEMORY; } +static void +_cairo_xcb_surface_set_picture_clip_rects (cairo_xcb_surface_t *surface) +{ + if (surface->num_clip_rects) + XCBRenderSetPictureClipRectangles (surface->dpy, surface->picture, + 0, 0, + surface->num_clip_rects, + surface->clip_rects); +} + +static void +_cairo_xcb_surface_set_gc_clip_rects (cairo_xcb_surface_t *surface) +{ + if (surface->num_clip_rects) + XCBSetClipRectangles(surface->dpy, XCBClipOrderingYXSorted, surface->gc, + 0, 0, + surface->num_clip_rects, + surface->clip_rects ); +} + static void _cairo_xcb_surface_ensure_gc (cairo_xcb_surface_t *surface) { @@ -573,6 +486,7 @@ _cairo_xcb_surface_ensure_gc (cairo_xcb_surface_t *surface) surface->gc = XCBGCONTEXTNew(surface->dpy); XCBCreateGC (surface->dpy, surface->gc, surface->drawable, 0, 0); + _cairo_xcb_surface_set_gc_clip_rects(surface); } static cairo_status_t @@ -1000,7 +914,8 @@ _cairo_xcb_surface_composite_trapezoids (cairo_operator_t op, cairo_int_status_t status; int render_reference_x, render_reference_y; int render_src_x, render_src_y; - XCBRenderPICTFORMINFO render_format; + int cairo_format; + XCBRenderPICTFORMINFO *render_format; if (!CAIRO_SURFACE_RENDER_HAS_TRAPEZOIDS (dst)) return CAIRO_INT_STATUS_UNSUPPORTED; @@ -1025,30 +940,94 @@ _cairo_xcb_surface_composite_trapezoids (cairo_operator_t op, switch (antialias) { case CAIRO_ANTIALIAS_NONE: - render_format = _format_from_cairo (dst->dpy, CAIRO_FORMAT_A1); + cairo_format = CAIRO_FORMAT_A1; break; default: - render_format = _format_from_cairo (dst->dpy, CAIRO_FORMAT_A8); + cairo_format = CAIRO_FORMAT_A8; break; } + render_format = XCBRenderUtilFindStandardFormat (XCBRenderUtilQueryFormats (dst->dpy), cairo_format); + /* XXX: what to do if render_format is null? */ /* XXX: The XTrapezoid cast is evil and needs to go away somehow. */ - /* XXX: _format_from_cairo is slow. should cache something. */ status = _cairo_xcb_surface_set_attributes (src, &attributes); if (status == CAIRO_STATUS_SUCCESS) XCBRenderTrapezoids (dst->dpy, _render_operator (op), src->picture, dst->picture, - render_format.id, + render_format->id, render_src_x + attributes.x_offset, render_src_y + attributes.y_offset, - num_traps, (XCBRenderTRAP *) traps); + num_traps, (XCBRenderTRAPEZOID *) traps); _cairo_pattern_release_surface (pattern, &src->base, &attributes); return status; } +static cairo_int_status_t +_cairo_xcb_surface_set_clip_region (void *abstract_surface, + pixman_region16_t *region) +{ + cairo_xcb_surface_t *surface = abstract_surface; + + if (surface->clip_rects) { + free (surface->clip_rects); + surface->clip_rects = NULL; + } + + surface->num_clip_rects = 0; + + if (region == NULL) { + if (surface->gc.xid) { + CARD32 mask = XCBGCClipMask; + CARD32 pa[] = { XCBNone }; + + XCBChangeGC (surface->dpy, surface->gc, mask, pa); + } + + if (surface->has_format && surface->picture.xid) { + CARD32 mask = XCBRenderCPClipMask; + CARD32 pa[] = { XCBNone }; + + XCBRenderChangePicture (surface->dpy, surface->picture, mask, pa); + } + } else { + pixman_box16_t *boxes; + XCBRECTANGLE *rects = NULL; + int n_boxes, i; + + n_boxes = pixman_region_num_rects (region); + if (n_boxes > 0) { + rects = malloc (sizeof(XCBRECTANGLE) * n_boxes); + if (rects == NULL) + return CAIRO_STATUS_NO_MEMORY; + } else { + rects = NULL; + } + + boxes = pixman_region_rects (region); + + for (i = 0; i < n_boxes; i++) { + rects[i].x = boxes[i].x1; + rects[i].y = boxes[i].y1; + rects[i].width = boxes[i].x2 - boxes[i].x1; + rects[i].height = boxes[i].y2 - boxes[i].y1; + } + + surface->clip_rects = rects; + surface->num_clip_rects = n_boxes; + + if (surface->gc.xid) + _cairo_xcb_surface_set_gc_clip_rects (surface); + + if (surface->picture.xid) + _cairo_xcb_surface_set_picture_clip_rects (surface); + } + + return CAIRO_STATUS_SUCCESS; +} + static cairo_int_status_t _cairo_xcb_surface_get_extents (void *abstract_surface, cairo_rectangle_int16_t *rectangle) @@ -1078,7 +1057,7 @@ static const cairo_surface_backend_t cairo_xcb_surface_backend = { _cairo_xcb_surface_composite_trapezoids, NULL, /* copy_page */ NULL, /* show_page */ - NULL, /* _cairo_xcb_surface_set_clip_region */ + _cairo_xcb_surface_set_clip_region, NULL, /* intersect_clip_path */ _cairo_xcb_surface_get_extents, NULL, /* old_show_glyphs */ @@ -1103,26 +1082,6 @@ _cairo_surface_is_xcb (cairo_surface_t *surface) return surface->backend == &cairo_xcb_surface_backend; } -static void -query_render_version (XCBConnection *c, cairo_xcb_surface_t *surface) -{ - XCBRenderQueryVersionRep *r; - - surface->render_major = -1; - surface->render_minor = -1; - - if (!XCBRenderInit(c)) - return; - - r = XCBRenderQueryVersionReply(c, XCBRenderQueryVersion(c, 0, 6), 0); - if (!r) - return; - - surface->render_major = r->major_version; - surface->render_minor = r->minor_version; - free(r); -} - static cairo_surface_t * _cairo_xcb_surface_create_internal (XCBConnection *dpy, XCBDRAWABLE drawable, @@ -1134,6 +1093,7 @@ _cairo_xcb_surface_create_internal (XCBConnection *dpy, int depth) { cairo_xcb_surface_t *surface; + const XCBRenderQueryVersionRep *r; surface = malloc (sizeof (cairo_xcb_surface_t)); if (surface == NULL) { @@ -1163,6 +1123,9 @@ _cairo_xcb_surface_create_internal (XCBConnection *dpy, surface->height = height; surface->depth = depth; + surface->clip_rects = NULL; + surface->num_clip_rects = 0; + if (format) { surface->depth = format->depth; } else if (visual) { @@ -1189,30 +1152,40 @@ _cairo_xcb_surface_create_internal (XCBConnection *dpy, ; } - query_render_version(dpy, surface); + surface->render_major = -1; + surface->render_minor = -1; + + r = XCBRenderUtilQueryVersion(dpy); + if (r) { + surface->render_major = r->major_version; + surface->render_minor = r->minor_version; + } surface->picture.xid = 0; if (CAIRO_SURFACE_RENDER_HAS_CREATE_PICTURE (surface)) { - XCBRenderPICTFORMAT pict_format = {0}; - XCBRenderPICTFORMINFO format_info; + static const XCBRenderPICTFORMAT nil = { 0 }; + const XCBRenderPICTFORMAT *pict_format = &nil; - surface->picture = XCBRenderPICTURENew(dpy); - - if (!format) { - if (visual) { - pict_format = format_from_visual (dpy, visual->visual_id); - } else if (depth == 1) { - format_info = _format_from_cairo (dpy, CAIRO_FORMAT_A1); - pict_format = format_info.id; - } - XCBRenderCreatePicture (dpy, surface->picture, drawable, - pict_format, 0, NULL); - } else { - XCBRenderCreatePicture (dpy, surface->picture, drawable, - format->id, 0, NULL); + if (format) { + pict_format = &format->id; + } else if (visual) { + XCBRenderPICTVISUAL *pict_visual; + pict_visual = XCBRenderUtilFindVisualFormat (XCBRenderUtilQueryFormats (dpy), visual->visual_id); + if (pict_visual) + pict_format = &pict_visual->format; + } else if (depth == 1) { + XCBRenderPICTFORMINFO *format_info; + format_info = XCBRenderUtilFindStandardFormat (XCBRenderUtilQueryFormats (dpy), CAIRO_FORMAT_A1); + if (format_info) + pict_format = &format_info->id; } + + /* XXX: if pict_format is nil, should we still call CreatePicture? */ + surface->picture = XCBRenderPICTURENew(dpy); + XCBRenderCreatePicture (dpy, surface->picture, drawable, + *pict_format, 0, NULL); } return (cairo_surface_t *) surface; diff --git a/gfx/cairo/cairo/src/cairo-xlib-private.h b/gfx/cairo/cairo/src/cairo-xlib-private.h index f319dcc742b8..94d1d5a62065 100644 --- a/gfx/cairo/cairo/src/cairo-xlib-private.h +++ b/gfx/cairo/cairo/src/cairo-xlib-private.h @@ -51,4 +51,10 @@ struct _cairo_xlib_screen_info { cairo_private cairo_xlib_screen_info_t * _cairo_xlib_screen_info_get (Display *display, Screen *screen); +#if CAIRO_HAS_XLIB_XRENDER_SURFACE + +#include "cairo-xlib-xrender.h" + +#endif + #endif /* CAIRO_XLIB_PRIVATE_H */ diff --git a/gfx/cairo/cairo/src/cairo-xlib-surface.c b/gfx/cairo/cairo/src/cairo-xlib-surface.c index cac6787f77ee..76eb378c3c8c 100644 --- a/gfx/cairo/cairo/src/cairo-xlib-surface.c +++ b/gfx/cairo/cairo/src/cairo-xlib-surface.c @@ -219,10 +219,11 @@ _cairo_xlib_surface_create_similar_with_format (void *abstract_src, /* As a good first approximation, if the display doesn't have even * the most elementary RENDER operation, then we're better off - * using image surfaces for all temporary operations + * using image surfaces for all temporary operations, so return NULL + * and let the fallback code happen. */ if (!CAIRO_SURFACE_RENDER_HAS_COMPOSITE(src)) { - return cairo_image_surface_create (format, width, height); + return NULL; } pix = XCreatePixmap (dpy, RootWindowOfScreen (src->screen), @@ -747,7 +748,7 @@ _draw_image_surface (cairo_xlib_surface_t *surface, int dst_y) { XImage ximage; - int bpp, alpha, red, green, blue; + unsigned int bpp, alpha, red, green, blue; int native_byte_order = _native_byte_order_lsb () ? LSBFirst : MSBFirst; pixman_format_get_masks (pixman_image_get_format (image->pixman_image), @@ -874,6 +875,9 @@ _cairo_xlib_surface_clone_similar (void *abstract_surface, } else if (_cairo_surface_is_image (src)) { cairo_image_surface_t *image_src = (cairo_image_surface_t *)src; + if (! CAIRO_FORMAT_VALID (image_src->format)) + return CAIRO_INT_STATUS_UNSUPPORTED; + clone = (cairo_xlib_surface_t *) _cairo_xlib_surface_create_similar_with_format (surface, image_src->format, image_src->width, image_src->height); @@ -934,7 +938,7 @@ static cairo_status_t _cairo_xlib_surface_set_filter (cairo_xlib_surface_t *surface, cairo_filter_t filter) { - char *render_filter; + const char *render_filter; if (!surface->src_picture) return CAIRO_STATUS_SUCCESS; @@ -963,13 +967,19 @@ _cairo_xlib_surface_set_filter (cairo_xlib_surface_t *surface, case CAIRO_FILTER_BILINEAR: render_filter = FilterBilinear; break; + case CAIRO_FILTER_GAUSSIAN: + /* XXX: The GAUSSIAN value has no implementation in cairo + * whatsoever, so it was really a mistake to have it in the + * API. We could fix this by officially deprecating it, or + * else inventing semantics and providing an actual + * implementation for it. */ default: render_filter = FilterBest; break; } XRenderSetPictureFilter (surface->dpy, surface->src_picture, - render_filter, NULL, 0); + (char *) render_filter, NULL, 0); return CAIRO_STATUS_SUCCESS; } @@ -1372,6 +1382,7 @@ _cairo_xlib_surface_composite (cairo_operator_t op, dst_x, dst_y, width, height); break; + case DO_UNSUPPORTED: default: ASSERT_NOT_REACHED; } @@ -1561,6 +1572,9 @@ _cairo_xlib_surface_composite_trapezoids (cairo_operator_t op, case CAIRO_ANTIALIAS_NONE: pict_format = XRenderFindStandardFormat (dst->dpy, PictStandardA1); break; + case CAIRO_ANTIALIAS_GRAY: + case CAIRO_ANTIALIAS_SUBPIXEL: + case CAIRO_ANTIALIAS_DEFAULT: default: pict_format = XRenderFindStandardFormat (dst->dpy, PictStandardA8); break; @@ -2423,7 +2437,7 @@ _cairo_xlib_surface_add_glyph (Display *dpy, break; case CAIRO_FORMAT_ARGB32: if (_native_byte_order_lsb() != (ImageByteOrder (dpy) == LSBFirst)) { - int c = glyph_surface->stride * glyph_surface->height; + unsigned int c = glyph_surface->stride * glyph_surface->height; unsigned char *d; unsigned char *new, *n; @@ -2434,7 +2448,7 @@ _cairo_xlib_surface_add_glyph (Display *dpy, } n = new; d = data; - while ((c -= 4) >= 0) + while (c >= 4) { n[3] = d[0]; n[2] = d[1]; @@ -2442,6 +2456,7 @@ _cairo_xlib_surface_add_glyph (Display *dpy, n[0] = d[3]; d += 4; n += 4; + c -= 4; } data = new; } @@ -2674,12 +2689,13 @@ _cairo_xlib_surface_show_glyphs (void *abstract_dst, cairo_surface_attributes_t attributes; cairo_xlib_surface_t *src = NULL; + cairo_glyph_t *output_glyphs; const cairo_glyph_t *glyphs_chunk; int glyphs_remaining, chunk_size, max_chunk_size; cairo_scaled_glyph_t *scaled_glyph; cairo_xlib_surface_font_private_t *font_private; - int i; + int i, o; unsigned long max_index = 0; cairo_xlib_surface_show_glyphs_func_t show_glyphs_func; @@ -2723,6 +2739,13 @@ _cairo_xlib_surface_show_glyphs (void *abstract_dst, (font_private != NULL && font_private->dpy != dst->dpy)) return CAIRO_INT_STATUS_UNSUPPORTED; + /* We make a copy of the glyphs so that we can elide any size-zero + * glyphs to workaround an X server bug, (present in at least Xorg + * 7.1 without EXA). */ + output_glyphs = malloc (num_glyphs * sizeof (cairo_glyph_t)); + if (output_glyphs == NULL) + return CAIRO_STATUS_NO_MEMORY; + /* After passing all those tests, we're now committed to rendering * these glyphs or to fail trying. We first upload any glyphs to * the X server that it doesn't have already, then we draw @@ -2781,7 +2804,7 @@ _cairo_xlib_surface_show_glyphs (void *abstract_dst, goto BAIL; /* Send all unsent glyphs to the server, and count the max of the glyph indices */ - for (i = 0; i < num_glyphs; i++) { + for (i = 0, o = 0; i < num_glyphs; i++) { if (glyphs[i].index > max_index) max_index = glyphs[i].index; status = _cairo_scaled_glyph_lookup (scaled_font, @@ -2790,11 +2813,18 @@ _cairo_xlib_surface_show_glyphs (void *abstract_dst, &scaled_glyph); if (status != CAIRO_STATUS_SUCCESS) goto BAIL; - if (scaled_glyph->surface_private == NULL) { - _cairo_xlib_surface_add_glyph (dst->dpy, scaled_font, scaled_glyph); - scaled_glyph->surface_private = (void *) 1; + /* Don't put any size-zero glyphs into output_glyphs to avoid + * an X server bug which stops rendering glyphs after the + * first size-zero glyph. */ + if (scaled_glyph->surface->width && scaled_glyph->surface->height) { + output_glyphs[o++] = glyphs[i]; + if (scaled_glyph->surface_private == NULL) { + _cairo_xlib_surface_add_glyph (dst->dpy, scaled_font, scaled_glyph); + scaled_glyph->surface_private = (void *) 1; + } } } + num_glyphs = o; _cairo_xlib_surface_ensure_dst_picture (dst); @@ -2811,7 +2841,7 @@ _cairo_xlib_surface_show_glyphs (void *abstract_dst, } max_chunk_size /= sz_xGlyphElt; - for (glyphs_remaining = num_glyphs, glyphs_chunk = glyphs; + for (glyphs_remaining = num_glyphs, glyphs_chunk = output_glyphs; glyphs_remaining; glyphs_remaining -= chunk_size, glyphs_chunk += chunk_size) { @@ -2826,6 +2856,7 @@ _cairo_xlib_surface_show_glyphs (void *abstract_dst, BAIL: _cairo_scaled_font_thaw_cache (scaled_font); + free (output_glyphs); if (src) _cairo_pattern_release_surface (src_pattern, &src->base, &attributes); diff --git a/gfx/cairo/cairo/src/cairo.c b/gfx/cairo/cairo/src/cairo.c index 906fc5d6dfe5..1a7da532b5e4 100644 --- a/gfx/cairo/cairo/src/cairo.c +++ b/gfx/cairo/cairo/src/cairo.c @@ -1,3 +1,4 @@ +/* -*- Mode: c; c-basic-offset: 4; indent-tabs-mode: t; tab-width: 8; -*- */ /* cairo - a vector graphics library with display and print output * * Copyright © 2002 University of Southern California @@ -44,7 +45,7 @@ #define CAIRO_TOLERANCE_MINIMUM 0.0002 /* We're limited by 16 bits of sub-pixel precision */ static const cairo_t cairo_nil = { - (unsigned int)-1, /* ref_count */ + CAIRO_REF_COUNT_INVALID, /* ref_count */ CAIRO_STATUS_NO_MEMORY, /* status */ { /* path */ NULL, NULL, /* op_buf_head, op_buf_tail */ @@ -62,7 +63,7 @@ static const cairo_t cairo_nil = { * a bit of a pain, but it should be easy to always catch as long as * one adds a new test case to test a trigger of the new status value. */ -#define CAIRO_STATUS_LAST_STATUS CAIRO_STATUS_INVALID_DSC_COMMENT +#define CAIRO_STATUS_LAST_STATUS CAIRO_STATUS_INVALID_INDEX /** * _cairo_error: @@ -206,6 +207,7 @@ cairo_create (cairo_surface_t *target) return cr; } +slim_hidden_def (cairo_create); /** * cairo_reference: @@ -223,7 +225,7 @@ cairo_reference (cairo_t *cr) if (cr == NULL) return NULL; - if (cr->ref_count == (unsigned int)-1) + if (cr->ref_count == CAIRO_REF_COUNT_INVALID) return cr; assert (cr->ref_count > 0); @@ -247,7 +249,7 @@ cairo_destroy (cairo_t *cr) if (cr == NULL) return; - if (cr->ref_count == (unsigned int)-1) + if (cr->ref_count == CAIRO_REF_COUNT_INVALID) return; assert (cr->ref_count > 0); @@ -267,6 +269,7 @@ cairo_destroy (cairo_t *cr) free (cr); } +slim_hidden_def (cairo_destroy); /** * cairo_save: @@ -571,6 +574,7 @@ cairo_set_operator (cairo_t *cr, cairo_operator_t op) if (cr->status) _cairo_set_error (cr, cr->status); } +slim_hidden_def (cairo_set_operator); /** * cairo_set_source_rgb @@ -674,6 +678,7 @@ cairo_set_source_surface (cairo_t *cr, cairo_set_source (cr, pattern); cairo_pattern_destroy (pattern); } +slim_hidden_def (cairo_set_source_surface); /** * cairo_set_source @@ -714,6 +719,7 @@ cairo_set_source (cairo_t *cr, cairo_pattern_t *source) if (cr->status) _cairo_set_error (cr, cr->status); } +slim_hidden_def (cairo_set_source); /** * cairo_get_source: @@ -928,10 +934,10 @@ cairo_set_line_join (cairo_t *cr, cairo_line_join_t line_join) * #CAIRO_STATUS_INVALID_DASH. **/ void -cairo_set_dash (cairo_t *cr, - double *dashes, - int num_dashes, - double offset) +cairo_set_dash (cairo_t *cr, + const double *dashes, + int num_dashes, + double offset) { if (cr->status) return; @@ -942,6 +948,64 @@ cairo_set_dash (cairo_t *cr, _cairo_set_error (cr, cr->status); } +/** + * cairo_get_dash_count: + * @cr: a #cairo_t + * @count: return value for the number of dash values, or %NULL + * + * Gets the length of the dash array in @cr. + * + * Return value: %CAIRO_STATUS_SUCCESS, or error status set on + * @cr. + * + * Since: 1.4 + */ +cairo_status_t +cairo_get_dash_count (cairo_t *cr, + int *count) +{ + if (cr->status) + return cr->status; + + if (count) + *count = cr->gstate->stroke_style.num_dashes; + + return CAIRO_STATUS_SUCCESS; +} + +/** + * cairo_get_dash: + * @cr: a #cairo_t + * @dashes: return value for the dash array, or %NULL + * @offset: return value for the current dash offset, or %NULL + * + * Gets the current dash array. If not %NULL, @dashes should be big + * enough to hold at least the number of values returned by + * cairo_get_dash_count(). + * + * Return value: %CAIRO_STATUS_SUCCESS, or error status set on + * @cr. + * + * Since: 1.4 + **/ +cairo_status_t +cairo_get_dash (cairo_t *cr, + double *dashes, + double *offset) +{ + if (cr->status) + return cr->status; + + memcpy (dashes, + cr->gstate->stroke_style.dash, + sizeof(double) * cr->gstate->stroke_style.num_dashes); + + if (offset) + *offset = cr->gstate->stroke_style.dash_offset; + + return CAIRO_STATUS_SUCCESS; +} + void cairo_set_miter_limit (cairo_t *cr, double limit) { @@ -1268,6 +1332,7 @@ cairo_line_to (cairo_t *cr, double x, double y) if (cr->status) _cairo_set_error (cr, cr->status); } +slim_hidden_def (cairo_line_to); /** * cairo_curve_to: @@ -1321,6 +1386,7 @@ cairo_curve_to (cairo_t *cr, if (cr->status) _cairo_set_error (cr, cr->status); } +slim_hidden_def (cairo_curve_to); /** * cairo_arc: @@ -1645,6 +1711,14 @@ cairo_stroke_to_path (cairo_t *cr) * * If there is no current point before the call to cairo_close_path, * this function will have no effect. + * + * Note: As of cairo version 1.2.4 any call to cairo_close_path will + * place an explicit MOVE_TO element into the path immediately after + * the CLOSE_PATH element, (which can be seen in cairo_copy_path() for + * example). This can simplify path processing in some cases as it may + * not be necessary to save the "last move_to point" during processing + * as the MOVE_TO immediately after the CLOSE_PATH will provide that + * point. **/ void cairo_close_path (cairo_t *cr) @@ -1675,6 +1749,7 @@ cairo_paint (cairo_t *cr) if (cr->status) _cairo_set_error (cr, cr->status); } +slim_hidden_def (cairo_paint); /** * cairo_paint_with_alpha: @@ -1722,7 +1797,7 @@ cairo_paint_with_alpha (cairo_t *cr, * * A drawing operator that paints the current source * using the alpha channel of @pattern as a mask. (Opaque - * areas of @mask are painted with the source, transparent + * areas of @pattern are painted with the source, transparent * areas are not painted.) */ void @@ -1746,6 +1821,7 @@ cairo_mask (cairo_t *cr, if (cr->status) _cairo_set_error (cr, cr->status); } +slim_hidden_def (cairo_mask); /** * cairo_mask_surface: @@ -1887,6 +1963,15 @@ cairo_fill_preserve (cairo_t *cr) } slim_hidden_def(cairo_fill_preserve); +/** + * cairo_copy_page: + * @cr: a cairo context + * + * Emits the current page for backends that support multiple pages, but + * doesn't clear it, so, the contents of the current page will be retained + * for the next page too. Use cairo_show_page() if you want to get an + * empty page after the emission. + **/ void cairo_copy_page (cairo_t *cr) { @@ -1898,6 +1983,13 @@ cairo_copy_page (cairo_t *cr) _cairo_set_error (cr, cr->status); } +/** + * cairo_show_page: + * @cr: a cairo context + * + * Emits and clears the current page for backends that support multiple + * pages. Use cairo_copy_page() if you don't want to clear the page. + **/ void cairo_show_page (cairo_t *cr) { @@ -1909,6 +2001,20 @@ cairo_show_page (cairo_t *cr) _cairo_set_error (cr, cr->status); } +/** + * cairo_in_stroke: + * @cr: a cairo context + * @x: X coordinate of the point to test + * @y: Y coordinate of the point to test + * + * Tests whether the given point is on the area stroked by doing a + * cairo_stroke() operation on @cr given the current path and stroking + * parameters. + * + * See cairo_stroke, cairo_set_line_width(), cairo_set_line_join(), + * cairo_set_line_cap(), cairo_set_dash(), and + * cairo_stroke_preserve(). + **/ cairo_bool_t cairo_in_stroke (cairo_t *cr, double x, double y) { @@ -1926,6 +2032,18 @@ cairo_in_stroke (cairo_t *cr, double x, double y) return inside; } +/** + * cairo_in_fill: + * @cr: a cairo context + * @x: X coordinate of the point to test + * @y: Y coordinate of the point to test + * + * Tests whether the given point is on the area filled by doing a + * cairo_stroke() operation on @cr given the current path and filling + * parameters. + * + * See cairo_fill(), cairo_set_fill_rule() and cairo_fill_preserve(). + **/ cairo_bool_t cairo_in_fill (cairo_t *cr, double x, double y) { @@ -1945,6 +2063,19 @@ cairo_in_fill (cairo_t *cr, double x, double y) return inside; } +/** + * cairo_stroke_extents: + * @cr: a cairo context + * @x1: left of the resulting extents + * @y1: top of the resulting extents + * @x2: right of the resulting extents + * @y2: bottom of the resulting extents + * + * Computes a bounding box in user coordinates covering all area that will + * be stroked by the current path with the current stroking parameters. If + * the current path is empty, returns an empty rectangle. Surface dimensions + * and clipping are not taken into account. + **/ void cairo_stroke_extents (cairo_t *cr, double *x1, double *y1, double *x2, double *y2) @@ -1959,6 +2090,19 @@ cairo_stroke_extents (cairo_t *cr, _cairo_set_error (cr, cr->status); } +/** + * cairo_fill_extents: + * @cr: a cairo context + * @x1: left of the resulting extents + * @y1: top of the resulting extents + * @x2: right of the resulting extents + * @y2: bottom of the resulting extents + * + * Computes a bounding box in user coordinates covering all area that will + * be filled by the current path. If the current path is empty, returns an + * empty rectangle. Surface dimensions and clipping are not taken into + * account. + **/ void cairo_fill_extents (cairo_t *cr, double *x1, double *y1, double *x2, double *y2) @@ -2064,6 +2208,67 @@ cairo_reset_clip (cairo_t *cr) _cairo_set_error (cr, cr->status); } +/** + * cairo_clip_extents: + * @cr: a cairo context + * @x1: left of the resulting extents + * @y1: top of the resulting extents + * @x2: right of the resulting extents + * @y2: bottom of the resulting extents + * + * Computes a bounding box in user coordinates covering the area inside the + * current clip. + **/ +void +cairo_clip_extents (cairo_t *cr, + double *x1, double *y1, + double *x2, double *y2) +{ + if (cr->status) + return; + + cr->status = _cairo_gstate_clip_extents (cr->gstate, x1, y1, x2, y2); + if (cr->status) + _cairo_set_error (cr, cr->status); +} + +static cairo_rectangle_list_t * +_cairo_rectangle_list_create_for_status (cairo_status_t status) +{ + cairo_rectangle_list_t *list; + + list = malloc (sizeof (cairo_rectangle_list_t)); + if (list == NULL) + return (cairo_rectangle_list_t*) &_cairo_rectangles_nil; + list->status = status; + list->rectangles = NULL; + list->num_rectangles = 0; + return list; +} + +/** + * cairo_copy_clip_rectangles: + * + * Returns the current clip region as a list of rectangles in user coordinates. + * Never returns %NULL. + * + * The status in the list may be CAIRO_STATUS_CLIP_NOT_REPRESENTABLE to + * indicate that the clip region cannot be represented as a list of + * user-space rectangles. The status may have other values to indicate + * other errors. + * + * The caller must always call cairo_rectangle_list_destroy on the result of + * this function. + **/ +cairo_rectangle_list_t * +cairo_copy_clip_rectangles (cairo_t *cr) +{ + if (cr->status) + return _cairo_rectangle_list_create_for_status (cr->status); + + return _cairo_gstate_copy_clip_rectangles (cr->gstate); +} + /** * cairo_select_font_face: * @cr: a #cairo_t @@ -2478,7 +2683,7 @@ cairo_show_text (cairo_t *cr, const char *utf8) } void -cairo_show_glyphs (cairo_t *cr, cairo_glyph_t *glyphs, int num_glyphs) +cairo_show_glyphs (cairo_t *cr, const cairo_glyph_t *glyphs, int num_glyphs) { if (cr->status) return; @@ -2564,6 +2769,7 @@ cairo_get_tolerance (cairo_t *cr) { return _cairo_gstate_get_tolerance (cr->gstate); } +slim_hidden_def (cairo_get_tolerance); /** * cairo_get_antialias: @@ -2707,6 +2913,7 @@ cairo_get_matrix (cairo_t *cr, cairo_matrix_t *matrix) { _cairo_gstate_get_matrix (cr->gstate, matrix); } +slim_hidden_def (cairo_get_matrix); /** * cairo_get_target: @@ -2862,7 +3069,8 @@ cairo_append_path (cairo_t *cr, } if (path->status) { - if (path->status <= CAIRO_STATUS_LAST_STATUS) + if (path->status > CAIRO_STATUS_SUCCESS && + path->status <= CAIRO_STATUS_LAST_STATUS) _cairo_set_error (cr, path->status); else _cairo_set_error (cr, CAIRO_STATUS_INVALID_STATUS); @@ -2892,6 +3100,7 @@ cairo_status (cairo_t *cr) { return cr->status; } +slim_hidden_def (cairo_status); /** * cairo_status_to_string: @@ -2947,6 +3156,10 @@ cairo_status_to_string (cairo_status_t status) return "invalid value for a dash setting"; case CAIRO_STATUS_INVALID_DSC_COMMENT: return "invalid value for a DSC comment"; + case CAIRO_STATUS_INVALID_INDEX: + return "invalid index passed to getter"; + case CAIRO_STATUS_CLIP_NOT_REPRESENTABLE: + return "clip region not representable in desired format"; } return ""; @@ -2960,42 +3173,3 @@ _cairo_restrict_value (double *value, double min, double max) else if (*value > max) *value = max; } - -/** - * cairo_has_clip - * @cr: a cairo context - * - * Returns TRUE if the cairo context has any clipping active, otherwise - * FALSE. - */ -cairo_bool_t -cairo_has_clip (cairo_t *cr) -{ - if (cr->status) - return FALSE; - return _cairo_gstate_has_clip (cr->gstate); -} - -/** - * cairo_extract_clip_rectangles - * @cr: a cairo context - * @max_rectangles: the maximum number of rectangles to be returned - * @rectangles_out: the output buffer for the rectangles - * @num_rectangles_out: the number of rectangles returned - * - * If the current clip can be expressed as the union of at most - * 'max_rectangles' device-coordinate rectangles, then we fill in the array - * with the rectangles, and return True. Otherwise we return False. When there - * is no clipping active, we return False. - */ -cairo_bool_t -cairo_extract_clip_rectangles (cairo_t *cr, - int max_rectangles, - cairo_clip_rect_t *rectangles_out, - int *num_rectangles_out) -{ - if (cr->status) - return FALSE; - return _cairo_gstate_extract_clip_rectangles (cr->gstate, max_rectangles, - rectangles_out, num_rectangles_out); -} diff --git a/gfx/cairo/cairo/src/cairo.h b/gfx/cairo/cairo/src/cairo.h index e0b00086856a..7a3b653bed54 100644 --- a/gfx/cairo/cairo/src/cairo.h +++ b/gfx/cairo/cairo/src/cairo.h @@ -39,6 +39,7 @@ #define CAIRO_H #include +#include CAIRO_BEGIN_DECLS @@ -168,12 +169,16 @@ typedef struct _cairo_user_data_key { * @CAIRO_STATUS_FILE_NOT_FOUND: file not found * @CAIRO_STATUS_INVALID_DASH: invalid value for a dash setting * @CAIRO_STATUS_INVALID_DSC_COMMENT: invalid value for a DSC comment (Since 1.2) - * @CAIRO_STATUS_INVALID_INDEX: invalid index value for a getter (Since 1.3+) + * @CAIRO_STATUS_INVALID_INDEX: invalid index passed to getter + * @CAIRO_STATUS_CLIP_NOT_REPRESENTABLE: clip region not representable in desired format (Since 1.4) * * #cairo_status_t is used to indicate errors that can occur when * using Cairo. In some cases it is returned directly by functions. * but when using #cairo_t, the last error, if any, is stored in * the context and can be retrieved with cairo_status(). + * + * New entries may be added in future versions. Use cairo_status_to_string() + * to get a human-readable representation of an error message. **/ typedef enum _cairo_status { CAIRO_STATUS_SUCCESS = 0, @@ -197,7 +202,8 @@ typedef enum _cairo_status { CAIRO_STATUS_FILE_NOT_FOUND, CAIRO_STATUS_INVALID_DASH, CAIRO_STATUS_INVALID_DSC_COMMENT, - CAIRO_STATUS_INVALID_INDEX + CAIRO_STATUS_INVALID_INDEX, + CAIRO_STATUS_CLIP_NOT_REPRESENTABLE } cairo_status_t; /** @@ -376,6 +382,8 @@ cairo_set_antialias (cairo_t *cr, cairo_antialias_t antialias); * or have a tricky intersection such as intersecting tangent to the path. * (Note that filling is not actually implemented in this way. This * is just a description of the rule that is applied.) + * + * New entries may be added in future versions. **/ typedef enum _cairo_fill_rule { CAIRO_FILL_RULE_WINDING, @@ -415,10 +423,10 @@ cairo_public void cairo_set_line_join (cairo_t *cr, cairo_line_join_t line_join); cairo_public void -cairo_set_dash (cairo_t *cr, - double *dashes, - int num_dashes, - double offset); +cairo_set_dash (cairo_t *cr, + const double *dashes, + int num_dashes, + double offset); cairo_public void cairo_set_miter_limit (cairo_t *cr, double limit); @@ -583,6 +591,38 @@ cairo_clip (cairo_t *cr); cairo_public void cairo_clip_preserve (cairo_t *cr); +cairo_public void +cairo_clip_extents (cairo_t *cr, + double *x1, double *y1, + double *x2, double *y2); + +/** + * cairo_rectangle_t: + * + * A data structure for holding a rectangle. + */ +typedef struct _cairo_rectangle { + double x, y, width, height; +} cairo_rectangle_t; + +/** + * cairo_rectangle_list_t: + * + * A data structure for holding a dynamically allocated + * array of rectangles. + */ +typedef struct _cairo_rectangle_list { + cairo_status_t status; + cairo_rectangle_t *rectangles; + int num_rectangles; +} cairo_rectangle_list_t; + +cairo_public cairo_rectangle_list_t * +cairo_copy_clip_rectangles (cairo_t *cr); + +cairo_public void +cairo_rectangle_list_destroy (cairo_rectangle_list_t *rectangle_list); + /* Font/Text functions */ /** @@ -777,6 +817,8 @@ typedef enum _cairo_subpixel_order { * involves distorting them, it also reduces the faithfulness * to the original outline shapes. Not all of the outline hinting * styles are supported by all font backends. + * + * New entries may be added in future versions. */ typedef enum _cairo_hint_style { CAIRO_HINT_STYLE_DEFAULT, @@ -889,7 +931,7 @@ cairo_public void cairo_show_text (cairo_t *cr, const char *utf8); cairo_public void -cairo_show_glyphs (cairo_t *cr, cairo_glyph_t *glyphs, int num_glyphs); +cairo_show_glyphs (cairo_t *cr, const cairo_glyph_t *glyphs, int num_glyphs); cairo_public cairo_font_face_t * cairo_get_font_face (cairo_t *cr); @@ -961,6 +1003,8 @@ cairo_font_face_status (cairo_font_face_t *font_face); * The behavior of calling a type-specific function with a scaled font * of the wrong type is undefined. * + * New entries may be added in future versions. + * * Since: 1.2 */ typedef enum _cairo_font_type { @@ -1065,7 +1109,11 @@ cairo_get_line_join (cairo_t *cr); cairo_public double cairo_get_miter_limit (cairo_t *cr); -/* XXX: How to do cairo_get_dash??? Do we want to switch to a cairo_dash object? */ +cairo_public cairo_status_t +cairo_get_dash_count (cairo_t *cr, int *count); + +cairo_public cairo_status_t +cairo_get_dash (cairo_t *cr, double *dashes, double *offset); cairo_public void cairo_get_matrix (cairo_t *cr, cairo_matrix_t *matrix); @@ -1160,8 +1208,8 @@ union _cairo_path_data_t { * @num_data: the number of elements in the data array * * A data structure for holding a path. This data structure serves as - * the return value for cairo_copy_path_data() and - * cairo_copy_path_data_flat() as well the input value for + * the return value for cairo_copy_path() and + * cairo_copy_path_flat() as well the input value for * cairo_append_path(). * * See #cairo_path_data_t for hints on how to iterate over the @@ -1191,24 +1239,6 @@ cairo_append_path (cairo_t *cr, cairo_public void cairo_path_destroy (cairo_path_t *path); -/** - * cairo_clip_rect_t: - * - * A data structure for holding clip rectangles. - */ -typedef struct _cairo_clip_rect { - double x, y, width, height; -} cairo_clip_rect_t; - -cairo_public cairo_bool_t -cairo_has_clip (cairo_t *cr); - -cairo_public cairo_bool_t -cairo_extract_clip_rectangles (cairo_t *cr, - int max_rectangles, - cairo_clip_rect_t *rectangles_out, - int *num_rectangles_out); - /* Error status queries */ cairo_public cairo_status_t @@ -1250,6 +1280,7 @@ cairo_surface_status (cairo_surface_t *surface); * @CAIRO_SURFACE_TYPE_BEOS: The surface is of type beos * @CAIRO_SURFACE_TYPE_DIRECTFB: The surface is of type directfb * @CAIRO_SURFACE_TYPE_SVG: The surface is of type svg + * @CAIRO_SURFACE_TYPE_OS2: The surface is of type os2 * * #cairo_surface_type_t is used to describe the type of a given * surface. The surface types are also known as "backends" or "surface @@ -1270,6 +1301,8 @@ cairo_surface_status (cairo_surface_t *surface); * The behavior of calling a type-specific function with a surface of * the wrong type is undefined. * + * New entries may be added in future versions. + * * Since: 1.2 */ typedef enum _cairo_surface_type { @@ -1284,7 +1317,8 @@ typedef enum _cairo_surface_type { CAIRO_SURFACE_TYPE_BEOS, CAIRO_SURFACE_TYPE_DIRECTFB, CAIRO_SURFACE_TYPE_SVG, - CAIRO_SURFACE_TYPE_NQUARTZ + CAIRO_SURFACE_TYPE_NQUARTZ, + CAIRO_SURFACE_TYPE_OS2 } cairo_surface_type_t; cairo_public cairo_surface_type_t @@ -1368,19 +1402,24 @@ cairo_surface_set_fallback_resolution (cairo_surface_t *surface, * endianess of the platform. On a big-endian machine, the * first pixel is in the uppermost bit, on a little-endian * machine the first pixel is in the least-significant bit. - * @CAIRO_FORMAT_RGB16_565: each pixel is a 16-bit quantity, - * with red in the upper 5 bits, then green in the next 6, - * then blue in the lowest 5 bits. (Since 1.2) + * @CAIRO_FORMAT_RGB16_565: This format value is deprecated. It has + * never been properly implemented in cairo and should not be used + * by applications. (since 1.2) * * #cairo_format_t is used to identify the memory format of * image data. + * + * New entries may be added in future versions. */ typedef enum _cairo_format { CAIRO_FORMAT_ARGB32, CAIRO_FORMAT_RGB24, CAIRO_FORMAT_A8, - CAIRO_FORMAT_A1, - CAIRO_FORMAT_RGB16_565 + CAIRO_FORMAT_A1 + /* The value of 4 is reserved by a deprecated enum value. + * The next format added must have an explicit value of 5. + CAIRO_FORMAT_RGB16_565 = 4, + */ } cairo_format_t; cairo_public cairo_surface_t * @@ -1476,6 +1515,8 @@ cairo_pattern_status (cairo_pattern_t *pattern); * gradient patterns (either LINEAR or RADIAL). Otherwise the pattern * will be shutdown and put into an error state. * + * New entries may be added in future versions. + * * Since: 1.2 */ typedef enum _cairo_pattern_type { @@ -1507,15 +1548,6 @@ cairo_public void cairo_pattern_get_matrix (cairo_pattern_t *pattern, cairo_matrix_t *matrix); -cairo_public cairo_status_t -cairo_pattern_get_solid_color (cairo_pattern_t *pattern, - double *r, double *g, double *b, double *a); - -cairo_public cairo_status_t -cairo_pattern_get_color_stop (cairo_pattern_t *pattern, - int stop_index, double *offset, - double *r, double *g, double *b, double *a); - /** * cairo_extend_t * @CAIRO_EXTEND_NONE: pixels outside of the source pattern @@ -1529,6 +1561,8 @@ cairo_pattern_get_color_stop (cairo_pattern_t *pattern, * * #cairo_extend_t is used to describe how the area outside * of a pattern will be drawn. + * + * New entries may be added in future versions. */ typedef enum _cairo_extend { CAIRO_EXTEND_NONE, @@ -1558,6 +1592,36 @@ cairo_pattern_set_filter (cairo_pattern_t *pattern, cairo_filter_t filter); cairo_public cairo_filter_t cairo_pattern_get_filter (cairo_pattern_t *pattern); +cairo_public cairo_status_t +cairo_pattern_get_rgba (cairo_pattern_t *pattern, + double *red, double *green, + double *blue, double *alpha); + +cairo_public cairo_status_t +cairo_pattern_get_surface (cairo_pattern_t *pattern, + cairo_surface_t **surface); + + +cairo_public cairo_status_t +cairo_pattern_get_color_stop_rgba (cairo_pattern_t *pattern, + int index, double *offset, + double *red, double *green, + double *blue, double *alpha); + +cairo_public cairo_status_t +cairo_pattern_get_color_stop_count (cairo_pattern_t *pattern, + int *count); + +cairo_public cairo_status_t +cairo_pattern_get_linear_points (cairo_pattern_t *pattern, + double *x0, double *y0, + double *x1, double *y1); + +cairo_public cairo_status_t +cairo_pattern_get_radial_circles (cairo_pattern_t *pattern, + double *x0, double *y0, double *r0, + double *x1, double *y1, double *r1); + /* Matrix functions */ cairo_public void @@ -1610,92 +1674,6 @@ cairo_matrix_transform_point (const cairo_matrix_t *matrix, cairo_public void cairo_debug_reset_static_data (void); -#ifndef _CAIROINT_H_ - -/* Obsolete functions. These definitions exist to coerce the compiler - * into providing a little bit of guidance with its error - * messages. The idea is to help users port their old code without - * having to dig through lots of documentation. - * - * The first set of REPLACED_BY functions is for functions whose names - * have just been changed. So fixing these up is mechanical, (and - * automated by means of the cairo/util/cairo-api-update script. - * - * The second set of DEPRECATED_BY functions is for functions where - * the replacement is used in a different way, (ie. different - * arguments, multiple functions instead of one, etc). Fixing these up - * will require a bit more work on the user's part, (and hopefully we - * can get cairo-api-update to find these and print some guiding - * information). - */ -#define cairo_current_font_extents cairo_current_font_extents_REPLACED_BY_cairo_font_extents -#define cairo_get_font_extents cairo_get_font_extents_REPLACED_BY_cairo_font_extents -#define cairo_current_operator cairo_current_operator_REPLACED_BY_cairo_get_operator -#define cairo_current_tolerance cairo_current_tolerance_REPLACED_BY_cairo_get_tolerance -#define cairo_current_point cairo_current_point_REPLACED_BY_cairo_get_current_point -#define cairo_current_fill_rule cairo_current_fill_rule_REPLACED_BY_cairo_get_fill_rule -#define cairo_current_line_width cairo_current_line_width_REPLACED_BY_cairo_get_line_width -#define cairo_current_line_cap cairo_current_line_cap_REPLACED_BY_cairo_get_line_cap -#define cairo_current_line_join cairo_current_line_join_REPLACED_BY_cairo_get_line_join -#define cairo_current_miter_limit cairo_current_miter_limit_REPLACED_BY_cairo_get_miter_limit -#define cairo_current_matrix cairo_current_matrix_REPLACED_BY_cairo_get_matrix -#define cairo_current_target_surface cairo_current_target_surface_REPLACED_BY_cairo_get_target -#define cairo_get_status cairo_get_status_REPLACED_BY_cairo_status -#define cairo_concat_matrix cairo_concat_matrix_REPLACED_BY_cairo_transform -#define cairo_scale_font cairo_scale_font_REPLACED_BY_cairo_set_font_size -#define cairo_select_font cairo_select_font_REPLACED_BY_cairo_select_font_face -#define cairo_transform_font cairo_transform_font_REPLACED_BY_cairo_set_font_matrix -#define cairo_transform_point cairo_transform_point_REPLACED_BY_cairo_user_to_device -#define cairo_transform_distance cairo_transform_distance_REPLACED_BY_cairo_user_to_device_distance -#define cairo_inverse_transform_point cairo_inverse_transform_point_REPLACED_BY_cairo_device_to_user -#define cairo_inverse_transform_distance cairo_inverse_transform_distance_REPLACED_BY_cairo_device_to_user_distance -#define cairo_init_clip cairo_init_clip_REPLACED_BY_cairo_reset_clip -#define cairo_surface_create_for_image cairo_surface_create_for_image_REPLACED_BY_cairo_image_surface_create_for_data -#define cairo_default_matrix cairo_default_matrix_REPLACED_BY_cairo_identity_matrix -#define cairo_matrix_set_affine cairo_matrix_set_affine_REPLACED_BY_cairo_matrix_init -#define cairo_matrix_set_identity cairo_matrix_set_identity_REPLACED_BY_cairo_matrix_init_identity -#define cairo_pattern_add_color_stop cairo_pattern_add_color_stop_REPLACED_BY_cairo_pattern_add_color_stop_rgba -#define cairo_set_rgb_color cairo_set_rgb_color_REPLACED_BY_cairo_set_source_rgb -#define cairo_set_pattern cairo_set_pattern_REPLACED_BY_cairo_set_source -#define cairo_xlib_surface_create_for_pixmap_with_visual cairo_xlib_surface_create_for_pixmap_with_visual_REPLACED_BY_cairo_xlib_surface_create -#define cairo_xlib_surface_create_for_window_with_visual cairo_xlib_surface_create_for_window_with_visual_REPLACED_BY_cairo_xlib_surface_create -#define cairo_xcb_surface_create_for_pixmap_with_visual cairo_xcb_surface_create_for_pixmap_with_visual_REPLACED_BY_cairo_xcb_surface_create -#define cairo_xcb_surface_create_for_window_with_visual cairo_xcb_surface_create_for_window_with_visual_REPLACED_BY_cairo_xcb_surface_create -#define cairo_ps_surface_set_dpi cairo_ps_surface_set_dpi_REPLACED_BY_cairo_surface_set_fallback_resolution -#define cairo_pdf_surface_set_dpi cairo_pdf_surface_set_dpi_REPLACED_BY_cairo_surface_set_fallback_resolution -#define cairo_svg_surface_set_dpi cairo_svg_surface_set_dpi_REPLACED_BY_cairo_surface_set_fallback_resolution - -#define cairo_current_path cairo_current_path_DEPRECATED_BY_cairo_copy_path -#define cairo_current_path_flat cairo_current_path_flat_DEPRECATED_BY_cairo_copy_path_flat -#define cairo_get_path cairo_get_path_DEPRECATED_BY_cairo_copy_path -#define cairo_get_path_flat cairo_get_path_flat_DEPRECATED_BY_cairo_get_path_flat -#define cairo_set_alpha cairo_set_alpha_DEPRECATED_BY_cairo_set_source_rgba_OR_cairo_paint_with_alpha -#define cairo_show_surface cairo_show_surface_DEPRECATED_BY_cairo_set_source_surface_AND_cairo_paint -#define cairo_copy cairo_copy_DEPRECATED_BY_cairo_create_AND_MANY_INDIVIDUAL_FUNCTIONS -#define cairo_surface_set_repeat cairo_surface_set_repeat_DEPRECATED_BY_cairo_pattern_set_extend -#define cairo_surface_set_matrix cairo_surface_set_matrix_DEPRECATED_BY_cairo_pattern_set_matrix -#define cairo_surface_get_matrix cairo_surface_get_matrix_DEPRECATED_BY_cairo_pattern_get_matrix -#define cairo_surface_set_filter cairo_surface_set_filter_DEPRECATED_BY_cairo_pattern_set_filter -#define cairo_surface_get_filter cairo_surface_get_filter_DEPRECATED_BY_cairo_pattern_get_filter -#define cairo_matrix_create cairo_matrix_create_DEPRECATED_BY_cairo_matrix_t -#define cairo_matrix_destroy cairo_matrix_destroy_DEPRECATED_BY_cairo_matrix_t -#define cairo_matrix_copy cairo_matrix_copy_DEPRECATED_BY_cairo_matrix_t -#define cairo_matrix_get_affine cairo_matrix_get_affine_DEPRECATED_BY_cairo_matrix_t -#define cairo_set_target_surface cairo_set_target_surface_DEPRECATED_BY_cairo_create -#define cairo_set_target_glitz cairo_set_target_glitz_DEPRECATED_BY_cairo_glitz_surface_create -#define cairo_set_target_image cairo_set_target_image_DEPRECATED_BY_cairo_image_surface_create_for_data -#define cairo_set_target_pdf cairo_set_target_pdf_DEPRECATED_BY_cairo_pdf_surface_create -#define cairo_set_target_png cairo_set_target_png_DEPRECATED_BY_cairo_surface_write_to_png -#define cairo_set_target_ps cairo_set_target_ps_DEPRECATED_BY_cairo_ps_surface_create -#define cairo_set_target_quartz cairo_set_target_quartz_DEPRECATED_BY_cairo_quartz_surface_create -#define cairo_set_target_win32 cairo_set_target_win32_DEPRECATED_BY_cairo_win32_surface_create -#define cairo_set_target_xcb cairo_set_target_xcb_DEPRECATED_BY_cairo_xcb_surface_create -#define cairo_set_target_drawable cairo_set_target_drawable_DEPRECATED_BY_cairo_xlib_surface_create -#define cairo_get_status_string cairo_get_status_string_DEPRECATED_BY_cairo_status_AND_cairo_status_to_string -#define cairo_status_string cairo_status_string_DEPRECATED_BY_cairo_status_AND_cairo_status_to_string - -#endif - CAIRO_END_DECLS #endif /* CAIRO_H */ diff --git a/gfx/cairo/cairo/src/cairoint.h b/gfx/cairo/cairo/src/cairoint.h index cad6f6069c8a..335a70aade1b 100644 --- a/gfx/cairo/cairo/src/cairoint.h +++ b/gfx/cairo/cairo/src/cairoint.h @@ -65,19 +65,21 @@ #include "cairo.h" #include -CAIRO_BEGIN_DECLS - -#ifndef PACKAGE_BUGREPORT -#define PACKAGE_BUGREPORT "(unknown)" +#ifdef _MSC_VER +#define snprintf _snprintf +#define inline __inline #endif +CAIRO_BEGIN_DECLS + #if __GNUC__ >= 3 && defined(__ELF__) -# define slim_hidden_proto(name) slim_hidden_proto1(name, INT_##name) -# define slim_hidden_def(name) slim_hidden_def1(name, INT_##name) +# define slim_hidden_proto(name) slim_hidden_proto1(name, slim_hidden_int_name(name)) +# define slim_hidden_def(name) slim_hidden_def1(name, slim_hidden_int_name(name)) +# define slim_hidden_int_name(name) INT_##name # define slim_hidden_proto1(name, internal) \ extern __typeof (name) name \ __asm__ (slim_hidden_asmname (internal)) \ - cairo_private; + cairo_private # define slim_hidden_def1(name, internal) \ extern __typeof (name) EXT_##name __asm__(slim_hidden_asmname(name)) \ __attribute__((__alias__(slim_hidden_asmname(internal)))) @@ -147,7 +149,12 @@ CAIRO_BEGIN_DECLS #endif #if !defined(CAIRO_MUTEX_DECLARE) && defined CAIRO_HAS_WIN32_SURFACE -# define WIN32_LEAN_AND_MEAN +# ifndef WIN32_LEAN_AND_MEAN +# define WIN32_LEAN_AND_MEAN +# endif +# ifndef WINVER +# define WINVER 0xFFFFF /* use newest and greatest */ +# endif # include /* the real initialization must take place in DllMain */ # define CAIRO_MUTEX_DECLARE(name) extern CRITICAL_SECTION name; @@ -156,6 +163,17 @@ CAIRO_BEGIN_DECLS # define CAIRO_MUTEX_UNLOCK(name) LeaveCriticalSection (&name) #endif +#if defined(__OS2__) && !defined(CAIRO_MUTEX_DECLARE) +# define INCL_BASE +# define INCL_PM +# include + +# define CAIRO_MUTEX_DECLARE(name) extern HMTX name +# define CAIRO_MUTEX_DECLARE_GLOBAL(name) extern HMTX name +# define CAIRO_MUTEX_LOCK(name) DosRequestMutexSem(name, SEM_INDEFINITE_WAIT) +# define CAIRO_MUTEX_UNLOCK(name) DosReleaseMutexSem(name) +#endif + #if !defined(CAIRO_MUTEX_DECLARE) && defined CAIRO_HAS_BEOS_SURFACE cairo_private void _cairo_beos_lock(void*); cairo_private void _cairo_beos_unlock(void*); @@ -198,6 +216,8 @@ do { \ assert (NOT_REACHED); \ } while (0) +#define CAIRO_REF_COUNT_INVALID ((unsigned int) -1) + #include "cairo-wideint-private.h" typedef int32_t cairo_fixed_16_16_t; @@ -282,6 +302,35 @@ typedef enum cairo_internal_surface_type { CAIRO_INTERNAL_SURFACE_TYPE_TEST_PAGINATED } cairo_internal_surface_type_t; +/* For xlib fallbacks, we use image surfaces with formats that match + * the visual of the X server. There are a couple of common X server + * visuals for which we do not have corresponding public + * cairo_format_t values, since we do not plan on always guaranteeing + * that cairo will be able to draw to these formats. + * + * So, currently pixman does provide support for these formats. It's + * possible that in the future we will change the implementation to + * instead convert to a supported format. This would allow us to be + * able to simplify pixman to handle fewer formats. + * + * The RGB16_565 case could probably have been handled this same way, + * (and in fact we could still change it to do so, and maybe just + * leave the value in the enum but deprecate it entirely). We can't + * drop the value since it did appear in cairo 1.2.0 so it might + * appear in code, (particularly bindings which are thorough about + * things like that). But we did neglect to update CAIRO_FORMAT_VALID + * for 1.2 so we know that no functional code is out there relying on + * being able to create an image surface with a 565 format, (which is + * good since things like write_to_png are missing support for the 565 + * format. + * + * NOTE: The implementation of CAIRO_FORMAT_VALID *must* *not* + * consider these internal formats as valid. */ +typedef enum cairo_internal_format { + CAIRO_INTERNAL_FORMAT_ABGR32 = 0x1000, + CAIRO_INTERNAL_FORMAT_BGR24 +} cairo_internal_format_t; + typedef enum cairo_direction { CAIRO_DIRECTION_FORWARD, CAIRO_DIRECTION_REVERSE @@ -356,9 +405,9 @@ _cairo_rectangle_intersect (cairo_rectangle_int16_t *dest, cairo_rectangle_int16 typedef struct _cairo_array cairo_array_t; struct _cairo_array { - int size; - int num_elements; - int element_size; + unsigned int size; + unsigned int num_elements; + unsigned int element_size; char **elements; cairo_bool_t is_snapshot; @@ -378,7 +427,7 @@ cairo_private cairo_status_t _cairo_array_grow_by (cairo_array_t *array, int additional); cairo_private void -_cairo_array_truncate (cairo_array_t *array, int length); +_cairo_array_truncate (cairo_array_t *array, unsigned int num_elements); cairo_private cairo_status_t _cairo_array_append (cairo_array_t *array, const void *element); @@ -390,11 +439,11 @@ _cairo_array_append_multiple (cairo_array_t *array, cairo_private cairo_status_t _cairo_array_allocate (cairo_array_t *array, - int num_elements, + unsigned int num_elements, void **elements); cairo_private void * -_cairo_array_index (cairo_array_t *array, int index); +_cairo_array_index (cairo_array_t *array, unsigned int index); cairo_private void _cairo_array_copy_element (cairo_array_t *array, int index, void *dst); @@ -402,6 +451,9 @@ _cairo_array_copy_element (cairo_array_t *array, int index, void *dst); cairo_private int _cairo_array_num_elements (cairo_array_t *array); +cairo_private int +_cairo_array_size (cairo_array_t *array); + typedef cairo_array_t cairo_user_data_array_t; cairo_private void @@ -433,7 +485,7 @@ typedef struct _cairo_font_face_backend cairo_font_face_backend_t; */ typedef struct _cairo_unscaled_font { cairo_hash_entry_t hash_entry; - int ref_count; + unsigned int ref_count; const cairo_unscaled_font_backend_t *backend; } cairo_unscaled_font_t; @@ -463,7 +515,7 @@ struct _cairo_scaled_font { /* useful bits for _cairo_scaled_font_nil */ cairo_status_t status; - int ref_count; + unsigned int ref_count; /* hash key members */ cairo_font_face_t *font_face; /* may be NULL */ @@ -492,7 +544,7 @@ struct _cairo_font_face { /* hash_entry must be first */ cairo_hash_entry_t hash_entry; cairo_status_t status; - int ref_count; + unsigned int ref_count; cairo_user_data_array_t user_data; const cairo_font_face_backend_t *backend; }; @@ -580,6 +632,12 @@ struct _cairo_scaled_font_backend { const cairo_glyph_t *glyphs, int num_glyphs); + cairo_int_status_t + (*load_truetype_table)(void *scaled_font, + unsigned long tag, + long offset, + unsigned char *buffer, + unsigned long *length); }; struct _cairo_font_face_backend { @@ -624,7 +682,7 @@ typedef struct _cairo_stroke_style { cairo_line_join_t line_join; double miter_limit; double *dash; - int num_dashes; + unsigned int num_dashes; double dash_offset; } cairo_stroke_style_t; @@ -899,6 +957,14 @@ struct _cairo_surface { /* A "snapshot" surface is immutable. See _cairo_surface_snapshot. */ cairo_bool_t is_snapshot; + + /* + * Surface font options, falling back to backend's default options, + * and set using _cairo_surface_set_font_options(), and propagated by + * cairo_surface_create_similar(). + */ + cairo_bool_t has_font_options; + cairo_font_options_t font_options; }; struct _cairo_image_surface { @@ -974,7 +1040,7 @@ typedef struct _cairo_gradient_pattern { cairo_pattern_t base; pixman_gradient_stop_t *stops; - int n_stops; + unsigned int n_stops; } cairo_gradient_pattern_t; typedef struct _cairo_linear_pattern { @@ -1168,7 +1234,7 @@ cairo_private cairo_line_join_t _cairo_gstate_get_line_join (cairo_gstate_t *gstate); cairo_private cairo_status_t -_cairo_gstate_set_dash (cairo_gstate_t *gstate, double *dash, int num_dashes, double offset); +_cairo_gstate_set_dash (cairo_gstate_t *gstate, const double *dash, int num_dashes, double offset); cairo_private cairo_status_t _cairo_gstate_set_miter_limit (cairo_gstate_t *gstate, double limit); @@ -1217,6 +1283,12 @@ _cairo_gstate_user_to_backend (cairo_gstate_t *gstate, double *x, double *y); cairo_private void _cairo_gstate_backend_to_user (cairo_gstate_t *gstate, double *x, double *y); +cairo_private void +_cairo_gstate_backend_to_user_rectangle (cairo_gstate_t *gstate, + double *x1, double *y1, + double *x2, double *y2, + cairo_bool_t *is_tight); + cairo_private cairo_status_t _cairo_gstate_paint (cairo_gstate_t *gstate); @@ -1268,6 +1340,16 @@ _cairo_gstate_clip (cairo_gstate_t *gstate, cairo_path_fixed_t *path); cairo_private cairo_status_t _cairo_gstate_reset_clip (cairo_gstate_t *gstate); +cairo_private cairo_status_t +_cairo_gstate_clip_extents (cairo_gstate_t *gstate, + double *x1, + double *y1, + double *x2, + double *y2); + +cairo_private cairo_rectangle_list_t* +_cairo_gstate_copy_clip_rectangles (cairo_gstate_t *gstate); + cairo_private cairo_status_t _cairo_gstate_show_surface (cairo_gstate_t *gstate, cairo_surface_t *surface, @@ -1330,7 +1412,7 @@ _cairo_gstate_glyph_extents (cairo_gstate_t *gstate, cairo_private cairo_status_t _cairo_gstate_show_glyphs (cairo_gstate_t *gstate, - cairo_glyph_t *glyphs, + const cairo_glyph_t *glyphs, int num_glyphs); cairo_private cairo_status_t @@ -1676,6 +1758,10 @@ _cairo_surface_init (cairo_surface_t *surface, const cairo_surface_backend_t *backend, cairo_content_t content); +cairo_private void +_cairo_surface_set_font_options (cairo_surface_t *surface, + cairo_font_options_t *options); + cairo_private cairo_clip_mode_t _cairo_surface_get_clip_mode (cairo_surface_t *surface); @@ -1894,8 +1980,37 @@ _cairo_surface_has_device_transform (cairo_surface_t *surface); /* cairo_image_surface.c */ -#define CAIRO_FORMAT_VALID(format) ((format) >= CAIRO_FORMAT_ARGB32 && \ - (format) <= CAIRO_FORMAT_A1) +/* XXX: In cairo 1.2.0 we added a new CAIRO_FORMAT_RGB16_565 but + * neglected to adjust this macro. The net effect is that it's + * impossible to externally create an image surface with this + * format. This is perhaps a good thing since we also neglected to fix + * up things like cairo_surface_write_to_png for the new format + * (-Wswitch-enum will tell you where). Is it obvious that format was + * added in haste? + * + * The reason for the new format was to allow the xlib backend to be + * used on X servers with a 565 visual. So the new format did its job + * for that, even without being considered "valid" for the sake of + * things like cairo_image_surface_create. + * + * Since 1.2.0 we ran into the same situtation with X servers with BGR + * visuals. This time we invented cairo_internal_format_t instead, + * (see it for more discussion). + * + * The punchline is that CAIRO_FORMAT_VALID must not conside any + * internal format to be valid. Also we need to decide if the + * RGB16_565 should be moved to instead be an internal format. If so, + * this macro need not change for it. (We probably will need to leave + * an RGB16_565 value in the header files for the sake of code that + * might have that value in it.) + * + * If we do decide to start fully supporting RGB16_565 as an external + * format, then CAIRO_FORMAT_VALID needs to be adjusted to include + * it. But that should not happen before all necessary code is fixed + * to support it (at least cairo_surface_write_to_png and a few spots + * in cairo-xlib-surface.c--again see -Wswitch-enum). + */ +#define CAIRO_FORMAT_VALID(format) ((format) <= CAIRO_FORMAT_A1) #define CAIRO_CONTENT_VALID(content) ((content) && \ (((content) & ~(CAIRO_CONTENT_COLOR | \ @@ -1948,6 +2063,10 @@ cairo_private cairo_int_status_t _cairo_image_surface_set_clip_region (void *abstract_surface, pixman_region16_t *region); +cairo_private cairo_image_surface_t * +_cairo_image_surface_clone (cairo_image_surface_t *surface, + cairo_format_t format); + cairo_private cairo_bool_t _cairo_surface_is_image (const cairo_surface_t *surface); @@ -2039,7 +2158,8 @@ _cairo_matrix_get_affine (const cairo_matrix_t *matrix, cairo_private void _cairo_matrix_transform_bounding_box (const cairo_matrix_t *matrix, double *x, double *y, - double *width, double *height); + double *width, double *height, + cairo_bool_t *is_tight); cairo_private void _cairo_matrix_compute_determinant (const cairo_matrix_t *matrix, double *det); @@ -2153,7 +2273,7 @@ _cairo_pattern_transform (cairo_pattern_t *pattern, cairo_private cairo_bool_t _cairo_pattern_is_opaque_solid (const cairo_pattern_t *pattern); -cairo_bool_t +cairo_private cairo_bool_t _cairo_pattern_is_opaque (const cairo_pattern_t *abstract_pattern); cairo_private cairo_int_status_t @@ -2227,32 +2347,88 @@ cairo_private int _cairo_dtostr (char *buffer, size_t size, double d); /* Avoid unnecessary PLT entries. */ -slim_hidden_proto(cairo_get_current_point) -slim_hidden_proto(cairo_fill_preserve) -slim_hidden_proto(cairo_clip_preserve) -slim_hidden_proto(cairo_close_path) -slim_hidden_proto(cairo_matrix_invert) -slim_hidden_proto(cairo_matrix_multiply) -slim_hidden_proto(cairo_matrix_scale) -slim_hidden_proto(cairo_matrix_init) -slim_hidden_proto(cairo_matrix_init_identity) -slim_hidden_proto(cairo_matrix_init_translate) -slim_hidden_proto(cairo_matrix_init_scale) -slim_hidden_proto(cairo_matrix_init_rotate) -slim_hidden_proto(cairo_matrix_transform_distance) -slim_hidden_proto(cairo_matrix_transform_point) -slim_hidden_proto(cairo_move_to) -slim_hidden_proto(cairo_new_path) -slim_hidden_proto(cairo_rel_line_to) -slim_hidden_proto(cairo_restore) -slim_hidden_proto(cairo_save) -slim_hidden_proto(cairo_stroke_preserve) -slim_hidden_proto(cairo_surface_destroy) -slim_hidden_proto(cairo_surface_get_content) -slim_hidden_proto(cairo_push_group) -slim_hidden_proto(cairo_push_group_with_content) -slim_hidden_proto(cairo_pop_group) -slim_hidden_proto(cairo_pop_group_to_source) +slim_hidden_proto (cairo_clip_preserve); +slim_hidden_proto (cairo_close_path); +slim_hidden_proto (cairo_create); +slim_hidden_proto (cairo_curve_to); +slim_hidden_proto (cairo_destroy); +slim_hidden_proto (cairo_fill_preserve); +slim_hidden_proto (cairo_font_face_destroy); +slim_hidden_proto (cairo_font_face_reference); +slim_hidden_proto (cairo_font_options_create); +slim_hidden_proto (cairo_font_options_destroy); +slim_hidden_proto (cairo_font_options_equal); +slim_hidden_proto (cairo_font_options_hash); +slim_hidden_proto (cairo_font_options_merge); +slim_hidden_proto (cairo_font_options_set_antialias); +slim_hidden_proto (cairo_font_options_set_hint_metrics); +slim_hidden_proto (cairo_font_options_set_hint_style); +slim_hidden_proto (cairo_font_options_set_subpixel_order); +slim_hidden_proto (cairo_get_current_point); +slim_hidden_proto (cairo_get_matrix); +slim_hidden_proto (cairo_get_tolerance); +slim_hidden_proto (cairo_image_surface_create); +slim_hidden_proto (cairo_image_surface_create_for_data); +slim_hidden_proto (cairo_image_surface_get_height); +slim_hidden_proto (cairo_image_surface_get_width); +slim_hidden_proto (cairo_line_to); +slim_hidden_proto (cairo_mask); +slim_hidden_proto (cairo_matrix_init); +slim_hidden_proto (cairo_matrix_init_identity); +slim_hidden_proto (cairo_matrix_init_rotate); +slim_hidden_proto (cairo_matrix_init_scale); +slim_hidden_proto (cairo_matrix_init_translate); +slim_hidden_proto (cairo_matrix_invert); +slim_hidden_proto (cairo_matrix_multiply); +slim_hidden_proto (cairo_matrix_scale); +slim_hidden_proto (cairo_matrix_transform_distance); +slim_hidden_proto (cairo_matrix_transform_point); +slim_hidden_proto (cairo_matrix_translate); +slim_hidden_proto (cairo_move_to); +slim_hidden_proto (cairo_new_path); +slim_hidden_proto (cairo_paint); +slim_hidden_proto (cairo_pattern_create_for_surface); +slim_hidden_proto (cairo_pattern_create_rgb); +slim_hidden_proto (cairo_pattern_create_rgba); +slim_hidden_proto (cairo_pattern_destroy); +slim_hidden_proto (cairo_pattern_get_extend); +slim_hidden_proto (cairo_pattern_get_type); +slim_hidden_proto (cairo_pattern_reference); +slim_hidden_proto (cairo_pattern_set_matrix); +slim_hidden_proto (cairo_pop_group); +slim_hidden_proto (cairo_pop_group_to_source); +slim_hidden_proto (cairo_push_group); +slim_hidden_proto (cairo_push_group_with_content); +slim_hidden_proto (cairo_rel_line_to); +slim_hidden_proto (cairo_restore); +slim_hidden_proto (cairo_save); +slim_hidden_proto (cairo_scaled_font_create); +slim_hidden_proto (cairo_scaled_font_destroy); +slim_hidden_proto (cairo_scaled_font_extents); +slim_hidden_proto (cairo_scaled_font_get_ctm); +slim_hidden_proto (cairo_scaled_font_get_font_face); +slim_hidden_proto (cairo_scaled_font_get_font_matrix); +slim_hidden_proto (cairo_scaled_font_get_font_options); +slim_hidden_proto (cairo_scaled_font_glyph_extents); +slim_hidden_proto (cairo_scaled_font_reference); +slim_hidden_proto (cairo_set_operator); +slim_hidden_proto (cairo_set_source); +slim_hidden_proto (cairo_set_source_surface); +slim_hidden_proto (cairo_status); +slim_hidden_proto (cairo_stroke_preserve); +slim_hidden_proto (cairo_surface_create_similar); +slim_hidden_proto (cairo_surface_destroy); +slim_hidden_proto (cairo_surface_finish); +slim_hidden_proto (cairo_surface_get_content); +slim_hidden_proto (cairo_surface_get_device_offset); +slim_hidden_proto (cairo_surface_get_font_options); +slim_hidden_proto (cairo_surface_get_type); +slim_hidden_proto (cairo_surface_mark_dirty_rectangle); +slim_hidden_proto (cairo_surface_reference); +slim_hidden_proto (cairo_surface_set_device_offset); +slim_hidden_proto (cairo_surface_set_fallback_resolution); +slim_hidden_proto (cairo_surface_status); +slim_hidden_proto (cairo_surface_write_to_png_stream); CAIRO_END_DECLS diff --git a/gfx/cairo/cairo/src/test-fallback-surface.c b/gfx/cairo/cairo/src/test-fallback-surface.c index 5c3c08c3ba01..479c8ef62e5e 100644 --- a/gfx/cairo/cairo/src/test-fallback-surface.c +++ b/gfx/cairo/cairo/src/test-fallback-surface.c @@ -64,6 +64,8 @@ typedef struct _test_fallback_surface { const cairo_private cairo_surface_backend_t test_fallback_surface_backend; +slim_hidden_proto (_test_fallback_surface_create); + cairo_surface_t * _test_fallback_surface_create (cairo_content_t content, int width, @@ -89,6 +91,7 @@ _test_fallback_surface_create (cairo_content_t content, return &surface->base; } +slim_hidden_def (_test_fallback_surface_create); static cairo_surface_t * _test_fallback_surface_create_similar (void *abstract_surface, diff --git a/gfx/cairo/cairo/src/test-paginated-surface.c b/gfx/cairo/cairo/src/test-paginated-surface.c index 1bdab6bb5cbf..4548df561758 100644 --- a/gfx/cairo/cairo/src/test-paginated-surface.c +++ b/gfx/cairo/cairo/src/test-paginated-surface.c @@ -95,6 +95,16 @@ _test_paginated_surface_create_for_data (unsigned char *data, &test_paginated_surface_paginated_backend); } +static cairo_status_t +_test_paginated_surface_finish (void *abstract_surface) +{ + test_paginated_surface_t *surface = abstract_surface; + + cairo_surface_destroy (surface->target); + + return CAIRO_STATUS_SUCCESS; +} + static cairo_int_status_t _test_paginated_surface_set_clip_region (void *abstract_surface, pixman_region16_t *region) @@ -247,7 +257,7 @@ static const cairo_surface_backend_t test_paginated_surface_backend = { * surface backend interface as historical cruft and ignore it. */ NULL, /* create_similar */ - NULL, /* finish */ + _test_paginated_surface_finish, NULL, /* acquire_source_image */ NULL, /* release_source_image */ NULL, /* acquire_dest_image */ diff --git a/gfx/cairo/device-offset-scale.patch b/gfx/cairo/device-offset-scale.patch deleted file mode 100644 index f2f2503ae1f7..000000000000 --- a/gfx/cairo/device-offset-scale.patch +++ /dev/null @@ -1,1496 +0,0 @@ -Index: src/cairo-gstate.c -=================================================================== ---- src/cairo-gstate.c.orig 2006-02-10 11:20:53.187500000 -0800 -+++ src/cairo-gstate.c 2006-02-10 14:05:49.891625000 -0800 -@@ -508,37 +508,10 @@ - return gstate->stroke_style.miter_limit; - } - --static void --_cairo_gstate_apply_device_transform (cairo_gstate_t *gstate, -- cairo_matrix_t *matrix) --{ -- if (gstate->target->device_x_scale != 1.0 || -- gstate->target->device_y_scale != 1.0) -- { -- cairo_matrix_scale (matrix, -- gstate->target->device_x_scale, -- gstate->target->device_y_scale); -- } --} -- --static void --_cairo_gstate_apply_device_inverse_transform (cairo_gstate_t *gstate, -- cairo_matrix_t *matrix) --{ -- if (gstate->target->device_x_scale != 1.0 || -- gstate->target->device_y_scale != 1.0) -- { -- cairo_matrix_scale (matrix, -- 1/gstate->target->device_x_scale, -- 1/gstate->target->device_y_scale); -- } --} -- - void - _cairo_gstate_get_matrix (cairo_gstate_t *gstate, cairo_matrix_t *matrix) - { - *matrix = gstate->ctm; -- _cairo_gstate_apply_device_inverse_transform (gstate, matrix); - } - - cairo_status_t -@@ -624,9 +597,6 @@ - if (status) - return status; - -- _cairo_gstate_apply_device_transform (gstate, &gstate->ctm); -- _cairo_gstate_apply_device_inverse_transform (gstate, &gstate->ctm_inverse); -- - return CAIRO_STATUS_SUCCESS; - } - -@@ -638,9 +608,6 @@ - cairo_matrix_init_identity (&gstate->ctm); - cairo_matrix_init_identity (&gstate->ctm_inverse); - -- _cairo_gstate_apply_device_transform (gstate, &gstate->ctm); -- _cairo_gstate_apply_device_inverse_transform (gstate, &gstate->ctm_inverse); -- - return CAIRO_STATUS_SUCCESS; - } - -@@ -682,15 +649,11 @@ - _cairo_gstate_user_to_backend (cairo_gstate_t *gstate, double *x, double *y) - { - cairo_matrix_transform_point (&gstate->ctm, x, y); -- *x += gstate->target->device_x_offset; -- *y += gstate->target->device_y_offset; - } - - void - _cairo_gstate_backend_to_user (cairo_gstate_t *gstate, double *x, double *y) - { -- *x -= gstate->target->device_x_offset; -- *y -= gstate->target->device_y_offset; - cairo_matrix_transform_point (&gstate->ctm_inverse, x, y); - } - -@@ -711,16 +674,8 @@ - cairo_pattern_t *original, - cairo_matrix_t *ctm_inverse) - { -- cairo_matrix_t tmp_matrix = *ctm_inverse; -- - _cairo_pattern_init_copy (pattern, original); -- -- if (gstate->target) -- cairo_matrix_translate (&tmp_matrix, -- - gstate->target->device_x_offset, -- - gstate->target->device_y_offset); -- -- _cairo_pattern_transform (pattern, &tmp_matrix); -+ _cairo_pattern_transform (pattern, ctm_inverse); - } - - static void -@@ -1401,9 +1356,6 @@ - if (status || !glyphs || !num_glyphs || !(*glyphs) || !(num_glyphs)) - return status; - -- _cairo_gstate_apply_device_transform (gstate, &gstate->ctm); -- _cairo_gstate_apply_device_inverse_transform (gstate, &gstate->ctm_inverse); -- - return CAIRO_STATUS_SUCCESS; - } - -@@ -1440,9 +1392,6 @@ - glyphs, num_glyphs, - extents); - -- _cairo_gstate_apply_device_transform (gstate, &gstate->ctm); -- _cairo_gstate_apply_device_inverse_transform (gstate, &gstate->ctm_inverse); -- - return CAIRO_STATUS_SUCCESS; - } - -Index: src/cairo-path.c -=================================================================== ---- src/cairo-path.c.orig 2006-02-10 11:20:53.188500000 -0800 -+++ src/cairo-path.c 2006-02-10 11:30:54.359375000 -0800 -@@ -548,3 +548,40 @@ - - return CAIRO_STATUS_SUCCESS; - } -+ -+void -+_cairo_path_fixed_offset_and_scale (cairo_path_fixed_t *path, -+ cairo_fixed_t offx, -+ cairo_fixed_t offy, -+ cairo_fixed_t scalex, -+ cairo_fixed_t scaley) -+{ -+ cairo_path_arg_buf_t *arg_buf = path->arg_buf_head; -+ int i; -+ cairo_int64_t i64temp; -+ cairo_fixed_t fixedtemp; -+ -+ while (arg_buf) { -+ for (i = 0; i < arg_buf->num_points; i++) { -+ /* CAIRO_FIXED_ONE? */ -+ if (scalex == 0x00010000) { -+ arg_buf->points[i].x += offx; -+ } else { -+ fixedtemp = arg_buf->points[i].x + offx; -+ i64temp = _cairo_int32x32_64_mul (fixedtemp, scalex); -+ arg_buf->points[i].x = _cairo_int64_to_int32(_cairo_int64_rsl (i64temp, 16)); -+ } -+ -+ if (scaley == 0x00010000) { -+ arg_buf->points[i].y += offy; -+ } else { -+ fixedtemp = arg_buf->points[i].y + offy; -+ i64temp = _cairo_int32x32_64_mul (fixedtemp, scaley); -+ arg_buf->points[i].y = _cairo_int64_to_int32(_cairo_int64_rsl (i64temp, 16)); -+ } -+ } -+ -+ arg_buf = arg_buf->next; -+ } -+} -+ -Index: src/cairo-surface-fallback.c -=================================================================== ---- src/cairo-surface-fallback.c.orig 2006-02-10 11:20:53.190500000 -0800 -+++ src/cairo-surface-fallback.c 2006-02-10 11:30:54.375000000 -0800 -@@ -214,6 +214,21 @@ - */ - _cairo_pattern_init_for_surface (&dst_pattern, dst); - -+ /* Set a translation on dst_pattern equivalent to the surface -+ * device offset, to make sure it's in the right place when -+ * composited. -+ */ -+ if (dst->device_x_offset != 0.0 || -+ dst->device_y_offset != 0.0 || -+ dst->device_x_scale != 1.0 || -+ dst->device_y_scale != 1.0) -+ { -+ cairo_matrix_t txmat; -+ cairo_matrix_init_scale (&txmat, dst->device_x_scale, dst->device_y_scale); -+ cairo_matrix_translate (&txmat, dst->device_x_offset, dst->device_y_offset); -+ cairo_pattern_set_matrix ((cairo_pattern_t*) &dst_pattern, &txmat); -+ } -+ - status = _cairo_surface_composite (CAIRO_OPERATOR_SOURCE, - &dst_pattern.base, NULL, intermediate, - extents->x, extents->y, -@@ -888,7 +903,8 @@ - op, - src, dst, - extents->x, extents->y, -- extents->x - dst_x, extents->y - dst_y, -+ extents->x - dst_x + dst->device_x_offset, -+ extents->y - dst_y + dst->device_y_offset, - extents->width, extents->height, - glyph_info->glyphs, - glyph_info->num_glyphs); -@@ -982,6 +998,11 @@ - _cairo_surface_release_source_image (surface, - image, &image_extra); - -+ snapshot->device_x_offset = surface->device_x_offset; -+ snapshot->device_y_offset = surface->device_y_offset; -+ snapshot->device_x_scale = surface->device_x_scale; -+ snapshot->device_y_scale = surface->device_y_scale; -+ - snapshot->is_snapshot = TRUE; - - return snapshot; -@@ -1011,12 +1032,17 @@ - return status; - } - -- status = state.image->base.backend->composite (op, src, mask, -- &state.image->base, -- src_x, src_y, mask_x, mask_y, -- dst_x - state.image_rect.x, -- dst_y - state.image_rect.y, -- width, height); -+ /* We know this will never fail with the image backend; but -+ * instead of calling into it directly, we call -+ * _cairo_surface_composite so that we get the correct device -+ * offset handling. -+ */ -+ status = _cairo_surface_composite (op, src, mask, -+ &state.image->base, -+ src_x, src_y, mask_x, mask_y, -+ dst_x - state.image_rect.x, -+ dst_y - state.image_rect.y, -+ width, height); - _fallback_fini (&state); - - return status; -@@ -1086,9 +1112,9 @@ - rects = offset_rects; - } - -- status = state.image->base.backend->fill_rectangles (&state.image->base, -- op, color, -- rects, num_rects); -+ status = _cairo_surface_fill_rectangles (&state.image->base, -+ op, color, -+ rects, num_rects); - - free (offset_rects); - -@@ -1127,39 +1153,25 @@ - /* If the destination image isn't at 0,0, we need to offset the trapezoids */ - - if (state.image_rect.x != 0 || state.image_rect.y != 0) { -- -- cairo_fixed_t xoff = _cairo_fixed_from_int (state.image_rect.x); -- cairo_fixed_t yoff = _cairo_fixed_from_int (state.image_rect.y); -- - offset_traps = malloc (sizeof (cairo_trapezoid_t) * num_traps); - if (!offset_traps) { - status = CAIRO_STATUS_NO_MEMORY; - goto DONE; - } - -- for (i = 0; i < num_traps; i++) { -- offset_traps[i].top = traps[i].top - yoff; -- offset_traps[i].bottom = traps[i].bottom - yoff; -- offset_traps[i].left.p1.x = traps[i].left.p1.x - xoff; -- offset_traps[i].left.p1.y = traps[i].left.p1.y - yoff; -- offset_traps[i].left.p2.x = traps[i].left.p2.x - xoff; -- offset_traps[i].left.p2.y = traps[i].left.p2.y - yoff; -- offset_traps[i].right.p1.x = traps[i].right.p1.x - xoff; -- offset_traps[i].right.p1.y = traps[i].right.p1.y - yoff; -- offset_traps[i].right.p2.x = traps[i].right.p2.x - xoff; -- offset_traps[i].right.p2.y = traps[i].right.p2.y - yoff; -- } -- -+ _cairo_trapezoid_array_translate_and_scale (offset_traps, traps, num_traps, -+ - state.image_rect.x, - state.image_rect.y, -+ 1.0, 1.0); - traps = offset_traps; - } - -- state.image->base.backend->composite_trapezoids (op, pattern, -- &state.image->base, -- antialias, -- src_x, src_y, -- dst_x - state.image_rect.x, -- dst_y - state.image_rect.y, -- width, height, traps, num_traps); -+ _cairo_surface_composite_trapezoids (op, pattern, -+ &state.image->base, -+ antialias, -+ src_x, src_y, -+ dst_x - state.image_rect.x, -+ dst_y - state.image_rect.y, -+ width, height, traps, num_traps); - if (offset_traps) - free (offset_traps); - -Index: src/cairo-surface.c -=================================================================== ---- src/cairo-surface.c.orig 2006-02-10 11:20:53.191500000 -0800 -+++ src/cairo-surface.c 2006-02-10 11:30:54.375000000 -0800 -@@ -89,6 +89,22 @@ - 0 /* current_clip_serial */ - }; - -+/* N.B.: set_device_offset already transforms the device offsets by the scale -+ * before storing in device_[xy]_scale -+ */ -+ -+/* Helper macros for transforming surface coords to backend coords */ -+#define BACKEND_X(_surf, _sx) ((_sx)*((_surf)->device_x_scale)+((_surf)->device_x_offset)) -+#define BACKEND_Y(_surf, _sy) ((_sy)*((_surf)->device_y_scale)+((_surf)->device_y_offset)) -+#define BACKEND_X_SIZE(_surf, _sx) ((_sx)*((_surf)->device_x_scale)) -+#define BACKEND_Y_SIZE(_surf, _sy) ((_sy)*((_surf)->device_y_scale)) -+ -+/* Helper macros for transforming backend coords to surface coords */ -+#define SURFACE_X(_surf, _bx) (((_bx)-((_surf)->device_x_offset))/((_surf)->device_x_scale)) -+#define SURFACE_Y(_surf, _by) (((_by)-((_surf)->device_y_offset))/((_surf)->device_y_scale)) -+#define SURFACE_X_SIZE(_surf, _bx) ((_bx)/((_surf)->device_x_scale)) -+#define SURFACE_Y_SIZE(_surf, _by) ((_by)/((_surf)->device_y_scale)) -+ - /** - * _cairo_surface_set_error: - * @surface: a surface -@@ -533,7 +549,10 @@ - if (surface->backend->mark_dirty_rectangle) { - cairo_status_t status; - -- status = surface->backend->mark_dirty_rectangle (surface, x, y, width, height); -+ status = surface->backend->mark_dirty_rectangle (surface, -+ BACKEND_X(surface, x), -+ BACKEND_Y(surface, y), -+ width, height); - - if (status) - _cairo_surface_set_error (surface, status); -@@ -578,6 +597,25 @@ - } - - /** -+ * cairo_surface_get_device_offset: -+ * @surface: a #cairo_surface_t -+ * @x_offset: the offset in the X direction, in device units -+ * @y_offset: the offset in the Y direction, in device units -+ * -+ * Returns a previous device offset set by -+ * cairo_surface_set_device_offset(). -+ * -+ **/ -+void -+cairo_surface_get_device_offset (cairo_surface_t *surface, -+ double *x_offset, -+ double *y_offset) -+{ -+ *x_offset = surface->device_x_offset; -+ *y_offset = surface->device_y_offset; -+} -+ -+/** - * _cairo_surface_acquire_source_image: - * @surface: a #cairo_surface_t - * @image_out: location to store a pointer to an image surface that -@@ -628,6 +666,7 @@ - * @surface: a #cairo_surface_t - * @interest_rect: area of @surface for which fallback drawing is being done. - * A value of %NULL indicates that the entire surface is desired. -+ * XXXX I'd like to get rid of being able to pass NULL here (nothing seems to) - * @image_out: location to store a pointer to an image surface that includes at least - * the intersection of @interest_rect with the visible area of @surface. - * This surface could be @surface itself, a surface held internal to @surface, -@@ -660,10 +699,26 @@ - cairo_rectangle_t *image_rect, - void **image_extra) - { -+ cairo_rectangle_t dev_interest_rect; -+ cairo_status_t status; -+ - assert (!surface->finished); - -- return surface->backend->acquire_dest_image (surface, interest_rect, -- image_out, image_rect, image_extra); -+ if (interest_rect) { -+ dev_interest_rect = *interest_rect; -+ dev_interest_rect.x = BACKEND_X(surface, dev_interest_rect.x); -+ dev_interest_rect.y = BACKEND_Y(surface, dev_interest_rect.y); -+ } -+ -+ status = surface->backend->acquire_dest_image (surface, -+ interest_rect ? &dev_interest_rect : NULL, -+ image_out, image_rect, image_extra); -+ -+ /* move image_rect back into surface coordinates from backend device coordinates */ -+ image_rect->x = SURFACE_X(surface, image_rect->x); -+ image_rect->y = SURFACE_Y(surface, image_rect->y); -+ -+ return status; - } - - /** -@@ -685,10 +740,22 @@ - cairo_rectangle_t *image_rect, - void *image_extra) - { -+ cairo_rectangle_t dev_interest_rect; -+ - assert (!surface->finished); - -+ /* move image_rect into backend device coords (opposite of acquire_dest_image) */ -+ image_rect->x = BACKEND_X(surface, image_rect->x); -+ image_rect->y = BACKEND_Y(surface, image_rect->y); -+ -+ if (interest_rect) { -+ dev_interest_rect = *interest_rect; -+ dev_interest_rect.x = BACKEND_X(surface, dev_interest_rect.x); -+ dev_interest_rect.y = BACKEND_Y(surface, dev_interest_rect.y); -+ } -+ - if (surface->backend->release_dest_image) -- surface->backend->release_dest_image (surface, interest_rect, -+ surface->backend->release_dest_image (surface, &dev_interest_rect, - image, image_rect, image_extra); - } - -@@ -724,6 +791,13 @@ - return CAIRO_INT_STATUS_UNSUPPORTED; - - status = surface->backend->clone_similar (surface, src, clone_out); -+ if (status == CAIRO_STATUS_SUCCESS) { -+ (*clone_out)->device_x_offset = src->device_x_offset; -+ (*clone_out)->device_y_offset = src->device_y_offset; -+ (*clone_out)->device_x_scale = src->device_x_scale; -+ (*clone_out)->device_y_scale = src->device_y_scale; -+ } -+ - if (status != CAIRO_INT_STATUS_UNSUPPORTED) - return status; - -@@ -732,6 +806,12 @@ - return status; - - status = surface->backend->clone_similar (surface, &image->base, clone_out); -+ if (status == CAIRO_STATUS_SUCCESS) { -+ (*clone_out)->device_x_offset = src->device_x_offset; -+ (*clone_out)->device_y_offset = src->device_y_offset; -+ (*clone_out)->device_x_scale = src->device_x_scale; -+ (*clone_out)->device_y_scale = src->device_y_scale; -+ } - - /* If the above failed point, we could implement a full fallback - * using acquire_dest_image, but that's going to be very -@@ -804,11 +884,29 @@ - return CAIRO_STATUS_SURFACE_FINISHED; - - if (dst->backend->composite) { -+ int backend_src_x = src_x; -+ int backend_src_y = src_y; -+ int backend_mask_x = mask_x; -+ int backend_mask_y = mask_y; -+ -+ if (src->type == CAIRO_PATTERN_SURFACE) { -+ cairo_surface_t *src_surface = ((cairo_surface_pattern_t*)src)->surface; -+ backend_src_x = BACKEND_X(src_surface, src_x); -+ backend_src_y = BACKEND_Y(src_surface, src_y); -+ } -+ -+ if (mask && mask->type == CAIRO_PATTERN_SURFACE) { -+ cairo_surface_t *mask_surface = ((cairo_surface_pattern_t*)mask)->surface; -+ backend_mask_x = BACKEND_X(mask_surface, mask_x); -+ backend_mask_y = BACKEND_Y(mask_surface, mask_y); -+ } -+ - status = dst->backend->composite (op, - src, mask, dst, -- src_x, src_y, -- mask_x, mask_y, -- dst_x, dst_y, -+ backend_src_x, backend_src_y, -+ backend_mask_x, backend_mask_y, -+ BACKEND_X(dst, dst_x), -+ BACKEND_Y(dst, dst_y), - width, height); - if (status != CAIRO_INT_STATUS_UNSUPPORTED) - return status; -@@ -937,6 +1035,8 @@ - int num_rects) - { - cairo_int_status_t status; -+ cairo_rectangle_t *dev_rects = NULL; -+ int i; - - assert (! surface->is_snapshot); - -@@ -950,8 +1050,26 @@ - return CAIRO_STATUS_SUCCESS; - - if (surface->backend->fill_rectangles) { -- status = surface->backend->fill_rectangles (surface, op, color, -- rects, num_rects); -+ if (surface->device_x_offset != 0.0 || -+ surface->device_y_offset != 0.0 || -+ surface->device_x_scale != 1.0 || -+ surface->device_y_scale != 1.0) -+ { -+ dev_rects = malloc(sizeof(cairo_rectangle_t) * num_rects); -+ for (i = 0; i < num_rects; i++) { -+ dev_rects[i].x = BACKEND_X(surface, rects[i].x); -+ dev_rects[i].y = BACKEND_Y(surface, rects[i].y); -+ -+ dev_rects[i].width = BACKEND_X_SIZE(surface, rects[i].width); -+ dev_rects[i].height = BACKEND_Y_SIZE(surface, rects[i].height); -+ } -+ } -+ -+ status = surface->backend->fill_rectangles (surface, -+ op, -+ color, -+ dev_rects ? dev_rects : rects, num_rects); -+ free (dev_rects); - if (status != CAIRO_INT_STATUS_UNSUPPORTED) - return status; - } -@@ -1012,10 +1130,31 @@ - - if (surface->backend->stroke) { - cairo_status_t status; -+ cairo_path_fixed_t *dev_path = path; -+ cairo_path_fixed_t real_dev_path; -+ -+ if (surface->device_x_offset != 0.0 || -+ surface->device_y_offset != 0.0 || -+ surface->device_x_scale != 1.0 || -+ surface->device_y_scale != 1.0) -+ { -+ _cairo_path_fixed_init_copy (&real_dev_path, path); -+ _cairo_path_fixed_offset_and_scale (&real_dev_path, -+ _cairo_fixed_from_double (surface->device_x_offset), -+ _cairo_fixed_from_double (surface->device_y_offset), -+ _cairo_fixed_from_double (surface->device_x_scale), -+ _cairo_fixed_from_double (surface->device_y_scale)); -+ dev_path = &real_dev_path; -+ } -+ - status = surface->backend->stroke (surface, op, source, -- path, stroke_style, -+ dev_path, stroke_style, - ctm, ctm_inverse, - tolerance, antialias); -+ -+ if (dev_path == &real_dev_path) -+ _cairo_path_fixed_fini (&real_dev_path); -+ - if (status != CAIRO_INT_STATUS_UNSUPPORTED) - return status; - } -@@ -1036,13 +1175,33 @@ - cairo_antialias_t antialias) - { - cairo_status_t status; -+ cairo_path_fixed_t *dev_path = path; -+ cairo_path_fixed_t real_dev_path; - - assert (! surface->is_snapshot); - - if (surface->backend->fill) { -+ if (surface->device_x_offset != 0.0 || -+ surface->device_y_offset != 0.0 || -+ surface->device_x_scale != 1.0 || -+ surface->device_y_scale != 1.0) -+ { -+ _cairo_path_fixed_init_copy (&real_dev_path, path); -+ _cairo_path_fixed_offset_and_scale (&real_dev_path, -+ _cairo_fixed_from_double (surface->device_x_offset), -+ _cairo_fixed_from_double (surface->device_y_offset), -+ _cairo_fixed_from_double (surface->device_x_scale), -+ _cairo_fixed_from_double (surface->device_y_scale)); -+ dev_path = &real_dev_path; -+ } -+ - status = surface->backend->fill (surface, op, source, -- path, fill_rule, -+ dev_path, fill_rule, - tolerance, antialias); -+ -+ if (dev_path == &real_dev_path) -+ _cairo_path_fixed_fini (&real_dev_path); -+ - if (status != CAIRO_INT_STATUS_UNSUPPORTED) - return status; - } -@@ -1067,6 +1226,7 @@ - int num_traps) - { - cairo_int_status_t status; -+ cairo_trapezoid_t *dev_traps = NULL; - - assert (! dst->is_snapshot); - -@@ -1082,13 +1242,36 @@ - return CAIRO_STATUS_SURFACE_FINISHED; - - if (dst->backend->composite_trapezoids) { -+ if (dst->device_x_offset != 0.0 || -+ dst->device_y_offset != 0.0 || -+ dst->device_x_scale != 1.0 || -+ dst->device_y_scale != 1.0) -+ { -+ dev_traps = malloc (sizeof (cairo_trapezoid_t) * num_traps); -+ if (!dev_traps) -+ return CAIRO_STATUS_NO_MEMORY; -+ -+ _cairo_trapezoid_array_translate_and_scale -+ (dev_traps, traps, num_traps, -+ dst->device_x_offset, -+ dst->device_y_offset, -+ dst->device_x_scale, -+ dst->device_y_scale); -+ } -+ -+ - status = dst->backend->composite_trapezoids (op, - pattern, dst, - antialias, - src_x, src_y, -- dst_x, dst_y, -+ BACKEND_X(dst, dst_x), -+ BACKEND_Y(dst, dst_y), -+ // XXX what the heck do I do with width/height? -+ // they're not the same for src and dst! - width, height, -- traps, num_traps); -+ dev_traps ? dev_traps : traps, num_traps); -+ free (dev_traps); -+ - if (status != CAIRO_INT_STATUS_UNSUPPORTED) - return status; - } -@@ -1235,6 +1418,9 @@ - pixman_region16_t *region, - unsigned int serial) - { -+ pixman_region16_t *dev_region = NULL; -+ cairo_status_t status; -+ - if (surface->status) - return surface->status; - -@@ -1242,10 +1428,50 @@ - return CAIRO_STATUS_SURFACE_FINISHED; - - assert (surface->backend->set_clip_region != NULL); -- -+ -+ if (surface->device_x_offset != 0.0 || -+ surface->device_y_offset != 0.0 || -+ surface->device_x_scale != 1.0 || -+ surface->device_y_scale != 1.0) -+ { -+ dev_region = pixman_region_create (); -+ if (surface->device_x_scale == 1.0 && -+ surface->device_y_scale == 1.0) -+ { -+ pixman_region_copy (dev_region, region); -+ pixman_region_translate (dev_region, surface->device_x_offset, surface->device_y_offset); -+ } else { -+ int i, nr = pixman_region_num_rects (region); -+ pixman_box16_t *rects = pixman_region_rects (region); -+ for (i = 0; i < nr; i++) { -+ pixman_box16_t tmpb; -+ pixman_region16_t *tmpr; -+ -+ tmpb.x1 = BACKEND_X(surface, rects[i].x1); -+ tmpb.y1 = BACKEND_Y(surface, rects[i].y1); -+ tmpb.x2 = BACKEND_X(surface, rects[i].x2); -+ tmpb.y2 = BACKEND_Y(surface, rects[i].y2); -+ -+ tmpr = pixman_region_create_simple (&tmpb); -+ -+ pixman_region_append (dev_region, tmpr); -+ pixman_region_destroy (tmpr); -+ } -+ -+ pixman_region_validate (dev_region, &i); -+ } -+ -+ region = dev_region; -+ } -+ - surface->current_clip_serial = serial; - -- return surface->backend->set_clip_region (surface, region); -+ status = surface->backend->set_clip_region (surface, region); -+ -+ if (dev_region) -+ pixman_region_destroy (dev_region); -+ -+ return status; - } - - cairo_int_status_t -@@ -1255,6 +1481,10 @@ - double tolerance, - cairo_antialias_t antialias) - { -+ cairo_path_fixed_t *dev_path = path; -+ cairo_path_fixed_t real_dev_path; -+ cairo_status_t status; -+ - if (surface->status) - return surface->status; - -@@ -1263,11 +1493,30 @@ - - assert (surface->backend->intersect_clip_path != NULL); - -- return surface->backend->intersect_clip_path (surface, -- path, -- fill_rule, -- tolerance, -- antialias); -+ if (surface->device_x_offset != 0.0 || -+ surface->device_y_offset != 0.0 || -+ surface->device_x_scale != 1.0 || -+ surface->device_y_scale != 1.0) -+ { -+ _cairo_path_fixed_init_copy (&real_dev_path, path); -+ _cairo_path_fixed_offset_and_scale (&real_dev_path, -+ _cairo_fixed_from_double (surface->device_x_offset), -+ _cairo_fixed_from_double (surface->device_y_offset), -+ _cairo_fixed_from_double (surface->device_x_scale), -+ _cairo_fixed_from_double (surface->device_y_scale)); -+ dev_path = &real_dev_path; -+ } -+ -+ status = surface->backend->intersect_clip_path (surface, -+ dev_path, -+ fill_rule, -+ tolerance, -+ antialias); -+ -+ if (dev_path == &real_dev_path) -+ _cairo_path_fixed_fini (&real_dev_path); -+ -+ return status; - } - - static cairo_status_t -@@ -1283,11 +1532,11 @@ - if (status) - return status; - -- return surface->backend->intersect_clip_path (surface, -- &clip_path->path, -- clip_path->fill_rule, -- clip_path->tolerance, -- clip_path->antialias); -+ return _cairo_surface_intersect_clip_path (surface, -+ &clip_path->path, -+ clip_path->fill_rule, -+ clip_path->tolerance, -+ clip_path->antialias); - } - - /** -@@ -1390,13 +1639,20 @@ - _cairo_surface_get_extents (cairo_surface_t *surface, - cairo_rectangle_t *rectangle) - { -+ cairo_status_t status; -+ - if (surface->status) - return surface->status; - - if (surface->finished) - return CAIRO_STATUS_SURFACE_FINISHED; - -- return surface->backend->get_extents (surface, rectangle); -+ status = surface->backend->get_extents (surface, rectangle); -+ -+ rectangle->x = SURFACE_X(surface, rectangle->x); -+ rectangle->y = SURFACE_Y(surface, rectangle->y); -+ -+ return status; - } - - cairo_status_t -@@ -1408,13 +1664,34 @@ - cairo_scaled_font_t *scaled_font) - { - cairo_status_t status; -+ cairo_glyph_t *dev_glyphs = NULL; - - assert (! surface->is_snapshot); - - if (surface->backend->show_glyphs) { -+ if (surface->device_x_offset != 0.0 || -+ surface->device_y_offset != 0.0 || -+ surface->device_x_scale != 1.0 || -+ surface->device_y_scale != 1.0) -+ { -+ int i; -+ -+ dev_glyphs = malloc (sizeof(cairo_glyph_t) * num_glyphs); -+ if (!dev_glyphs) -+ return CAIRO_STATUS_NO_MEMORY; -+ -+ for (i = 0; i < num_glyphs; i++) { -+ dev_glyphs[i].index = glyphs[i].index; -+ // err, we really should scale the size of the glyphs, no? -+ dev_glyphs[i].x = BACKEND_X(surface, glyphs[i].x); -+ dev_glyphs[i].y = BACKEND_Y(surface, glyphs[i].y); -+ } -+ } -+ - status = surface->backend->show_glyphs (surface, op, source, -- glyphs, num_glyphs, -- scaled_font); -+ dev_glyphs ? dev_glyphs : glyphs, -+ num_glyphs, scaled_font); -+ free (dev_glyphs); - if (status != CAIRO_INT_STATUS_UNSUPPORTED) - return status; - } -@@ -1444,6 +1721,7 @@ - int num_glyphs) - { - cairo_status_t status; -+ cairo_glyph_t *dev_glyphs = NULL; - - assert (! dst->is_snapshot); - -@@ -1453,14 +1731,35 @@ - if (dst->finished) - return CAIRO_STATUS_SURFACE_FINISHED; - -- if (dst->backend->old_show_glyphs) -+ if (dst->backend->old_show_glyphs) { -+ if (dst->device_x_offset != 0.0 || -+ dst->device_y_offset != 0.0 || -+ dst->device_x_scale != 1.0 || -+ dst->device_y_scale != 1.0) -+ { -+ int i; -+ -+ dev_glyphs = malloc(sizeof(cairo_glyph_t) * num_glyphs); -+ for (i = 0; i < num_glyphs; i++) { -+ dev_glyphs[i] = glyphs[i]; -+ // err, we really should scale the size of the glyphs, no? -+ dev_glyphs[i].x = BACKEND_X(dst, dev_glyphs[i].x); -+ dev_glyphs[i].y = BACKEND_Y(dst, dev_glyphs[i].y); -+ } -+ -+ glyphs = dev_glyphs; -+ } -+ - status = dst->backend->old_show_glyphs (scaled_font, - op, pattern, dst, - source_x, source_y, -- dest_x, dest_y, -+ BACKEND_X(dst, dest_x), -+ BACKEND_Y(dst, dest_y), - width, height, - glyphs, num_glyphs); -- else -+ -+ free (dev_glyphs); -+ } else - status = CAIRO_INT_STATUS_UNSUPPORTED; - - return status; -@@ -1570,7 +1869,15 @@ - cairo_rectangle_t *mask_rectangle = NULL; - - assert (! dst->is_snapshot); -- -+ -+ /* This is a little odd; this function is called from the xlib/image surfaces, -+ * where the coordinates have already been transformed by the device_xy_offset. -+ * We need to undo this before running through this function, -+ * otherwise those offsets get applied twice. -+ */ -+ dst_x = SURFACE_X(dst, dst_x); -+ dst_y = SURFACE_Y(dst, dst_y); -+ - /* The RENDER/libpixman operators are clipped to the bounds of the untransformed, - * non-repeating sources and masks. Other sources and masks can be ignored. - */ -@@ -1645,6 +1952,10 @@ - cairo_rectangle_t *mask_rectangle = NULL; - - assert (! dst->is_snapshot); -+ -+ /* See comment at start of _cairo_surface_composite_fixup_unbounded */ -+ dst_x = SURFACE_X(dst, dst_x); -+ dst_y = SURFACE_Y(dst, dst_y); - - /* The RENDER/libpixman operators are clipped to the bounds of the untransformed, - * non-repeating sources and masks. Other sources and masks can be ignored. -Index: src/cairo-traps.c -=================================================================== ---- src/cairo-traps.c.orig 2006-02-10 11:20:53.192500000 -0800 -+++ src/cairo-traps.c 2006-02-10 11:30:54.375000000 -0800 -@@ -258,6 +258,54 @@ - } - } - -+void -+_cairo_trapezoid_array_translate_and_scale (cairo_trapezoid_t *offset_traps, -+ cairo_trapezoid_t *src_traps, -+ int num_traps, -+ double tx, double ty, -+ double sx, double sy) -+{ -+ int i; -+ cairo_fixed_t xoff = _cairo_fixed_from_double (tx); -+ cairo_fixed_t yoff = _cairo_fixed_from_double (ty); -+ -+ if (sx == 1.0 && sy == 1.0) { -+ for (i = 0; i < num_traps; i++) { -+ offset_traps[i].top = src_traps[i].top + yoff; -+ offset_traps[i].bottom = src_traps[i].bottom + yoff; -+ offset_traps[i].left.p1.x = src_traps[i].left.p1.x + xoff; -+ offset_traps[i].left.p1.y = src_traps[i].left.p1.y + yoff; -+ offset_traps[i].left.p2.x = src_traps[i].left.p2.x + xoff; -+ offset_traps[i].left.p2.y = src_traps[i].left.p2.y + yoff; -+ offset_traps[i].right.p1.x = src_traps[i].right.p1.x + xoff; -+ offset_traps[i].right.p1.y = src_traps[i].right.p1.y + yoff; -+ offset_traps[i].right.p2.x = src_traps[i].right.p2.x + xoff; -+ offset_traps[i].right.p2.y = src_traps[i].right.p2.y + yoff; -+ } -+ } else { -+ cairo_fixed_t xsc = _cairo_fixed_from_double (sx); -+ cairo_fixed_t ysc = _cairo_fixed_from_double (sy); -+ -+ for (i = 0; i < num_traps; i++) { -+#define FIXED_MUL(_a, _b) \ -+ (_cairo_int64_to_int32(_cairo_int64_rsl(_cairo_int32x32_64_mul((_a), (_b)), 16))) -+ -+ offset_traps[i].top = FIXED_MUL(src_traps[i].top + yoff, ysc); -+ offset_traps[i].bottom = FIXED_MUL(src_traps[i].bottom + yoff, ysc); -+ offset_traps[i].left.p1.x = FIXED_MUL(src_traps[i].left.p1.x + xoff, xsc); -+ offset_traps[i].left.p1.y = FIXED_MUL(src_traps[i].left.p1.y + yoff, ysc); -+ offset_traps[i].left.p2.x = FIXED_MUL(src_traps[i].left.p2.x + xoff, xsc); -+ offset_traps[i].left.p2.y = FIXED_MUL(src_traps[i].left.p2.y + yoff, ysc); -+ offset_traps[i].right.p1.x = FIXED_MUL(src_traps[i].right.p1.x + xoff, xsc); -+ offset_traps[i].right.p1.y = FIXED_MUL(src_traps[i].right.p1.y + yoff, ysc); -+ offset_traps[i].right.p2.x = FIXED_MUL(src_traps[i].right.p2.x + xoff, xsc); -+ offset_traps[i].right.p2.y = FIXED_MUL(src_traps[i].right.p2.y + yoff, ysc); -+ -+#undef FIXED_MUL -+ } -+ } -+} -+ - cairo_status_t - _cairo_traps_tessellate_triangle (cairo_traps_t *traps, cairo_point_t t[3]) - { -@@ -859,4 +907,3 @@ - - return CAIRO_STATUS_SUCCESS; - } -- -Index: src/cairoint.h -=================================================================== ---- src/cairoint.h.orig 2006-02-10 11:20:53.195500000 -0800 -+++ src/cairoint.h 2006-02-10 14:05:49.896625000 -0800 -@@ -1466,6 +1466,13 @@ - double *x1, double *y1, - double *x2, double *y2); - -+cairo_private void -+_cairo_path_fixed_offset_and_scale (cairo_path_fixed_t *path, -+ cairo_fixed_t offx, -+ cairo_fixed_t offy, -+ cairo_fixed_t scalex, -+ cairo_fixed_t scaley); -+ - /* cairo_path_fill.c */ - cairo_private cairo_status_t - _cairo_path_fixed_fill_to_traps (cairo_path_fixed_t *path, -@@ -1996,6 +2003,13 @@ - _cairo_traps_extract_region (cairo_traps_t *tr, - pixman_region16_t **region); - -+cairo_private void -+_cairo_trapezoid_array_translate_and_scale (cairo_trapezoid_t *offset_traps, -+ cairo_trapezoid_t *src_traps, -+ int num_traps, -+ double tx, double ty, -+ double sx, double sy); -+ - /* cairo_slope.c */ - cairo_private void - _cairo_slope_init (cairo_slope_t *slope, cairo_point_t *a, cairo_point_t *b); -Index: test/buffer-diff.c -=================================================================== ---- test/buffer-diff.c.orig 2006-02-10 11:20:53.204500000 -0800 -+++ test/buffer-diff.c 2006-02-10 11:30:54.390625000 -0800 -@@ -62,7 +62,9 @@ - unsigned char *_buf_diff, - int width, - int height, -- int stride, -+ int stride_a, -+ int stride_b, -+ int stride_diff, - pixman_bits_t mask) - { - int x, y; -@@ -72,12 +74,14 @@ - pixman_bits_t *buf_b = (pixman_bits_t*)_buf_b; - pixman_bits_t *buf_diff = (pixman_bits_t*)_buf_diff; - -- stride /= sizeof(pixman_bits_t); -+ stride_a /= sizeof(pixman_bits_t); -+ stride_b /= sizeof(pixman_bits_t); -+ stride_diff /= sizeof(pixman_bits_t); - for (y = 0; y < height; y++) - { -- row_a = buf_a + y * stride; -- row_b = buf_b + y * stride; -- row = buf_diff + y * stride; -+ row_a = buf_a + y * stride_a; -+ row_b = buf_b + y * stride_b; -+ row = buf_diff + y * stride_diff; - for (x = 0; x < width; x++) - { - /* check if the pixels are the same */ -@@ -112,9 +116,12 @@ - unsigned char *buf_diff, - int width, - int height, -- int stride) -+ int stride_a, -+ int stride_b, -+ int stride_diff) - { -- return buffer_diff_core(buf_a, buf_b, buf_diff, width, height, stride, 0xffffffff); -+ return buffer_diff_core(buf_a, buf_b, buf_diff, -+ width, height, stride_a, stride_b, stride_diff, 0xffffffff); - } - - int -@@ -123,9 +130,12 @@ - unsigned char *buf_diff, - int width, - int height, -- int stride) -+ int stride_a, -+ int stride_b, -+ int stride_diff) - { -- return buffer_diff_core(buf_a, buf_b, buf_diff, width, height, stride, 0x00ffffff); -+ return buffer_diff_core(buf_a, buf_b, buf_diff, -+ width, height, stride_a, stride_b, stride_diff, 0x00ffffff); - } - - /* Image comparison code courtesy of Richard Worth -@@ -136,11 +146,16 @@ - int - image_diff (const char *filename_a, - const char *filename_b, -- const char *filename_diff) -+ const char *filename_diff, -+ int ax, -+ int ay, -+ int bx, -+ int by) - { - int pixels_changed; - unsigned int width_a, height_a, stride_a; - unsigned int width_b, height_b, stride_b; -+ unsigned int stride_diff; - unsigned char *buf_a, *buf_b, *buf_diff; - read_png_status_t status; - -@@ -154,9 +169,13 @@ - return -1; - } - -+ width_a -= ax; -+ height_a -= ay; -+ width_b -= bx; -+ height_b -= by; -+ - if (width_a != width_b || -- height_a != height_b || -- stride_a != stride_b) -+ height_a != height_b) - { - cairo_test_log ("Error: Image size mismatch: (%dx%d@%d) vs. (%dx%d@%d)\n" - " for %s vs. %s\n", -@@ -168,17 +187,27 @@ - return -1; - } - -- buf_diff = xcalloc (stride_a * height_a, 1); -+ stride_diff = 4 * width_a; -+ buf_diff = xcalloc (stride_diff * height_a, 1); - -- pixels_changed = buffer_diff (buf_a, buf_b, buf_diff, -- width_a, height_a, stride_a); -+ pixels_changed = buffer_diff (buf_a + (ay * stride_a) + ax * 4, -+ buf_b + (by * stride_b) + by * 4, -+ buf_diff, -+ width_a, height_a, -+ stride_a, stride_b, stride_diff); - - if (pixels_changed) { -- FILE *png_file = fopen (filename_diff, "wb"); -- write_png_argb32 (buf_diff, png_file, width_a, height_a, stride_a); -- fclose (png_file); -+ FILE *png_file; -+ if (filename_diff) -+ png_file = fopen (filename_diff, "wb"); -+ else -+ png_file = stdout; -+ write_png_argb32 (buf_diff, png_file, width_a, height_a, stride_diff); -+ if (png_file != stdout) -+ fclose (png_file); - } else { -- xunlink (filename_diff); -+ if (filename_diff) -+ xunlink (filename_diff); - } - - free (buf_a); -@@ -204,7 +233,11 @@ - int - image_diff_flattened (const char *filename_a, - const char *filename_b, -- const char *filename_diff) -+ const char *filename_diff, -+ int ax, -+ int ay, -+ int bx, -+ int by) - { - int pixels_changed; - unsigned int width_a, height_a, stride_a; -@@ -225,6 +258,11 @@ - return -1; - } - -+ width_a -= ax; -+ height_a -= ay; -+ width_b -= bx; -+ height_b -= by; -+ - if (width_a != width_b || - height_a != height_b || - stride_a != stride_b) -@@ -252,6 +290,8 @@ - CAIRO_FORMAT_ARGB32, - width_b, height_b, - stride_b); -+ cairo_surface_set_device_offset (b_flat_surface, -bx, -by); -+ - cr = cairo_create (b_flat_surface); - - cairo_set_source_rgb (cr, 1, 1, 1); -@@ -263,8 +303,11 @@ - cairo_surface_destroy (b_flat_surface); - cairo_surface_destroy (buf_b_surface); - -- pixels_changed = buffer_diff (buf_a, b_flat, buf_diff, -- width_a, height_a, stride_a); -+ pixels_changed = buffer_diff (buf_a + (ay * stride_a) + ax * 4, -+ b_flat, -+ buf_diff, -+ width_a, height_a, -+ width_a, height_a, stride_a); - - if (pixels_changed) { - FILE *png_file = fopen (filename_diff, "wb"); -Index: test/buffer-diff.h -=================================================================== ---- test/buffer-diff.h.orig 2006-02-10 11:20:53.212500000 -0800 -+++ test/buffer-diff.h 2006-02-10 11:30:54.390625000 -0800 -@@ -36,7 +36,9 @@ - unsigned char *buf_diff, - int width, - int height, -- int stride); -+ int stride_a, -+ int stride_b, -+ int stride_diff); - - /* Returns number of pixels changed ignoring the alpha channel. - * Also fills in a "diff" buffer intended to visually show where the -@@ -48,7 +50,10 @@ - unsigned char *buf_diff, - int width, - int height, -- int stride); -+ int stride_a, -+ int stride_b, -+ int stride_diff); -+ - - /* Returns number of pixels changed, (or -1 on error). - * Also saves a "diff" image intended to visually show where the -@@ -57,13 +62,21 @@ - int - image_diff (const char *filename_a, - const char *filename_b, -- const char *filename_diff); -+ const char *filename_diff, -+ int ax, -+ int ay, -+ int bx, -+ int by); - - /* Like image_diff, but blending the contents of b over white first. */ - int - image_diff_flattened (const char *filename_a, - const char *filename_b, -- const char *filename_diff); -+ const char *filename_diff, -+ int ax, -+ int ay, -+ int bx, -+ int by); - - - #endif -Index: test/cairo-test.c -=================================================================== ---- test/cairo-test.c.orig 2006-02-10 11:20:53.217500000 -0800 -+++ test/cairo-test.c 2006-02-10 11:30:54.421875000 -0800 -@@ -61,6 +61,8 @@ - #define CAIRO_TEST_REF_SUFFIX "-ref.png" - #define CAIRO_TEST_DIFF_SUFFIX "-diff.png" - -+#define NUM_DEVICE_OFFSETS 2 -+ - /* A fake format we use for the flattened ARGB output of the PS and - * PDF surfaces. */ - #define CAIRO_TEST_CONTENT_COLOR_ALPHA_FLATTENED -1 -@@ -1345,12 +1347,13 @@ - static cairo_test_status_t - cairo_test_for_target (cairo_test_t *test, - cairo_test_draw_function_t draw, -- cairo_test_target_t *target) -+ cairo_test_target_t *target, -+ int dev_offset) - { - cairo_test_status_t status; - cairo_surface_t *surface; - cairo_t *cr; -- char *png_name, *ref_name, *diff_name; -+ char *png_name, *ref_name, *diff_name, *offset_str; - char *srcdir; - char *format; - cairo_test_status_t ret; -@@ -1361,8 +1364,13 @@ - srcdir = "."; - format = _cairo_test_content_name (target->content); - -- xasprintf (&png_name, "%s-%s-%s%s", test->name, -- target->name, format, CAIRO_TEST_PNG_SUFFIX); -+ if (dev_offset) -+ xasprintf (&offset_str, "-%d", dev_offset); -+ else -+ offset_str = strdup(""); -+ -+ xasprintf (&png_name, "%s-%s-%s%s%s", test->name, -+ target->name, format, offset_str, CAIRO_TEST_PNG_SUFFIX); - xasprintf (&ref_name, "%s/%s-%s-%s%s", srcdir, test->name, - target->name, format, CAIRO_TEST_REF_SUFFIX); - if (access (ref_name, F_OK) != 0) { -@@ -1376,17 +1384,30 @@ - xasprintf (&ref_name, "%s/%s-%s%s", srcdir, test->name, - format,CAIRO_TEST_REF_SUFFIX); - } -- xasprintf (&diff_name, "%s-%s-%s%s", test->name, -- target->name, format, CAIRO_TEST_DIFF_SUFFIX); -+ xasprintf (&diff_name, "%s-%s-%s%s%s", test->name, -+ target->name, format, offset_str, CAIRO_TEST_DIFF_SUFFIX); - - /* Run the actual drawing code. */ -+ if (test->width && test->height) { -+ test->width += dev_offset; -+ test->height += dev_offset; -+ } -+ - surface = (target->create_target_surface) (test, target->content, &target->closure); -+ -+ if (test->width && test->height) { -+ test->width -= dev_offset; -+ test->height -= dev_offset;; -+ } -+ - if (surface == NULL) { - cairo_test_log ("Error: Failed to set %s target\n", target->name); - ret = CAIRO_TEST_UNTESTED; - goto UNWIND_STRINGS; - } - -+ cairo_surface_set_device_offset (surface, dev_offset, dev_offset); -+ - cr = cairo_create (surface); - - /* Clear to transparent (or black) depending on whether the target -@@ -1420,9 +1441,9 @@ - int pixels_changed; - (target->write_to_png) (surface, png_name); - if (target->content == CAIRO_TEST_CONTENT_COLOR_ALPHA_FLATTENED) -- pixels_changed = image_diff_flattened (png_name, ref_name, diff_name); -+ pixels_changed = image_diff_flattened (png_name, ref_name, diff_name, dev_offset, dev_offset, 0, 0); - else -- pixels_changed = image_diff (png_name, ref_name, diff_name); -+ pixels_changed = image_diff (png_name, ref_name, diff_name, dev_offset, dev_offset, 0, 0); - if (pixels_changed) { - if (pixels_changed > 0) - cairo_test_log ("Error: %d pixels differ from reference image %s\n", -@@ -1447,6 +1468,7 @@ - free (png_name); - free (ref_name); - free (diff_name); -+ free (offset_str); - - return ret; - } -@@ -1455,7 +1477,7 @@ - cairo_test_expecting (cairo_test_t *test, cairo_test_draw_function_t draw, - cairo_test_status_t expectation) - { -- int i, num_targets; -+ int i, j, num_targets; - const char *tname; - cairo_test_status_t status, ret; - cairo_test_target_t **targets_to_test; -@@ -1599,39 +1621,45 @@ - */ - ret = CAIRO_TEST_UNTESTED; - for (i = 0; i < num_targets; i++) { -- cairo_test_target_t *target = targets_to_test[i]; -- cairo_test_log ("Testing %s with %s target\n", test->name, target->name); -- printf ("%s-%s-%s:\t", test->name, target->name, -- _cairo_test_content_name (target->content)); -- -- status = cairo_test_for_target (test, draw, target); -- -- cairo_test_log ("TEST: %s TARGET: %s FORMAT: %s RESULT: ", -- test->name, target->name, -- _cairo_test_content_name (target->content)); -- -- switch (status) { -- case CAIRO_TEST_SUCCESS: -- printf ("PASS\n"); -- cairo_test_log ("PASS\n"); -- if (ret == CAIRO_TEST_UNTESTED) -- ret = CAIRO_TEST_SUCCESS; -- break; -- case CAIRO_TEST_UNTESTED: -- printf ("UNTESTED\n"); -- cairo_test_log ("UNTESTED\n"); -- break; -- default: -- case CAIRO_TEST_FAILURE: -- if (expectation == CAIRO_TEST_FAILURE) { -- printf ("XFAIL\n"); -- cairo_test_log ("XFAIL\n"); -- } else { -- printf ("FAIL\n"); -- cairo_test_log ("FAIL\n"); -+ for (j = 0; j < NUM_DEVICE_OFFSETS; j++) { -+ cairo_test_target_t *target = targets_to_test[i]; -+ int dev_offset = j * 25; -+ -+ cairo_test_log ("Testing %s with %s target (dev offset %d)\n", test->name, target->name, dev_offset); -+ printf ("%s-%s-%s [%d]:\t", test->name, target->name, -+ _cairo_test_content_name (target->content), -+ dev_offset); -+ -+ status = cairo_test_for_target (test, draw, target, dev_offset); -+ -+ cairo_test_log ("TEST: %s TARGET: %s FORMAT: %s OFFSET: %d RESULT: ", -+ test->name, target->name, -+ _cairo_test_content_name (target->content), -+ dev_offset); -+ -+ switch (status) { -+ case CAIRO_TEST_SUCCESS: -+ printf ("PASS\n"); -+ cairo_test_log ("PASS\n"); -+ if (ret == CAIRO_TEST_UNTESTED) -+ ret = CAIRO_TEST_SUCCESS; -+ break; -+ case CAIRO_TEST_UNTESTED: -+ printf ("UNTESTED\n"); -+ cairo_test_log ("UNTESTED\n"); -+ break; -+ default: -+ case CAIRO_TEST_FAILURE: -+ if (expectation == CAIRO_TEST_FAILURE) { -+ printf ("XFAIL\n"); -+ cairo_test_log ("XFAIL\n"); -+ } else { -+ printf ("FAIL\n"); -+ cairo_test_log ("FAIL\n"); -+ } -+ ret = status; -+ break; - } -- ret = status; -- break; - } - } - if (ret == CAIRO_TEST_UNTESTED) -Index: test/imagediff.c -=================================================================== ---- test/imagediff.c.orig 2006-02-10 11:20:53.225500000 -0800 -+++ test/imagediff.c 2006-02-10 11:30:54.421875000 -0800 -@@ -34,48 +34,31 @@ - int - main (int argc, char *argv[]) - { -- unsigned char *buffer_a; -- unsigned int width_a, height_a, stride_a; -- unsigned char *buffer_b; -- unsigned int width_b, height_b, stride_b; -- -- unsigned char *buffer; -- unsigned int width, height, stride; -- int buffer_size, total_pixels_changed; -+ int total_pixels_changed; - -- if (argc < 2) { -- fprintf (stderr, "Usage: %s image1.png image2.png\n", argv[0]); -+ unsigned int ax, ay, bx, by; -+ -+ if (argc != 3 && argc != 7) { -+ fprintf (stderr, "Usage: %s image1.png image2.png [ax ay bx by]\n", argv[0]); - fprintf (stderr, "Computes an output image designed to present a \"visual diff\" such that even\n"); - fprintf (stderr, "small errors in single pixels are readily apparent in the output.\n"); - fprintf (stderr, "The output image is written on stdout.\n"); - exit (1); - } - -- read_png_argb32 (argv[1], &buffer_a, &width_a, &height_a, &stride_a); -- read_png_argb32 (argv[2], &buffer_b, &width_b, &height_b, &stride_b); -- -- if ((width_a == width_b) && (height_a == height_b) && (stride_a == stride_b)) -- { -- width = width_a; -- height = height_a; -- stride = stride_a; -+ if (argc == 7) { -+ ax = strtoul (argv[3], NULL, 0); -+ ay = strtoul (argv[4], NULL, 0); -+ bx = strtoul (argv[5], NULL, 0); -+ by = strtoul (argv[6], NULL, 0); - } else { -- fprintf (stderr, "Error. Both images must be the same size\n"); -- return 1; -+ ax = ay = bx = by = 0; - } - -- buffer_size = stride * height; -- buffer = xmalloc (buffer_size); -- -- total_pixels_changed = buffer_diff (buffer_a, buffer_b, buffer, -- width_a, height_a, stride_a); -- -+ total_pixels_changed = image_diff (argv[1], argv[2], NULL, ax, ay, bx, by); - - if (total_pixels_changed) - fprintf (stderr, "Total pixels changed: %d\n", total_pixels_changed); -- write_png_argb32 (buffer, stdout, width, height, stride); -- -- free (buffer); - - return total_pixels_changed; - } -Index: test/xlib-surface.c -=================================================================== ---- test/xlib-surface.c.orig 2006-02-10 11:20:53.229500000 -0800 -+++ test/xlib-surface.c 2006-02-10 11:30:54.421875000 -0800 -@@ -160,6 +160,8 @@ - diff_data + offset, - SIZE - OFFSCREEN_OFFSET, - SIZE - OFFSCREEN_OFFSET, -+ 4 * SIZE, -+ 4 * SIZE, - 4 * SIZE); - } else { - result = !buffer_diff_noalpha (reference_data, -@@ -167,6 +169,8 @@ - diff_data, - SIZE, - SIZE, -+ 4 * SIZE, -+ 4 * SIZE, - 4 * SIZE); - } - diff --git a/gfx/cairo/libpixman/src/fbcompose.c b/gfx/cairo/libpixman/src/fbcompose.c index 03bb5d513eba..79b73aa432ec 100644 --- a/gfx/cairo/libpixman/src/fbcompose.c +++ b/gfx/cairo/libpixman/src/fbcompose.c @@ -28,6 +28,7 @@ #endif #include "pixman-xserver-compat.h" #include "fbpict.h" +#include "fbmmx.h" #ifdef RENDER @@ -3092,8 +3093,8 @@ static void fbFetchTransformed(PicturePtr pict, int x, int y, int width, CARD32 if (pict->filter == PIXMAN_FILTER_NEAREST || pict->filter == PIXMAN_FILTER_FAST) { if (pict->repeat == RepeatNormal) { - if (PIXREGION_NUM_RECTS(pict->pCompositeClip) == 1) { - box = pict->pCompositeClip->extents; + if (PIXREGION_NUM_RECTS(pict->pSourceClip) == 1) { + box = pict->pSourceClip->extents; for (i = 0; i < width; ++i) { if (!mask || mask[i] & maskBits) { @@ -3128,7 +3129,7 @@ static void fbFetchTransformed(PicturePtr pict, int x, int y, int width, CARD32 y = MOD(v.vector[1]>>16, pict->pDrawable->height); x = MOD(v.vector[0]>>16, pict->pDrawable->width); } - if (pixman_region_contains_point (pict->pCompositeClip, x, y, &box)) + if (pixman_region_contains_point (pict->pSourceClip, x, y, &box)) buffer[i] = fetch(bits + (y + pict->pDrawable->y)*stride, x + pict->pDrawable->x, indexed); else buffer[i] = 0; @@ -3140,8 +3141,8 @@ static void fbFetchTransformed(PicturePtr pict, int x, int y, int width, CARD32 } } } else { - if (PIXREGION_NUM_RECTS(pict->pCompositeClip) == 1) { - box = pict->pCompositeClip->extents; + if (PIXREGION_NUM_RECTS(pict->pSourceClip) == 1) { + box = pict->pSourceClip->extents; for (i = 0; i < width; ++i) { if (!mask || mask[i] & maskBits) { @@ -3175,7 +3176,7 @@ static void fbFetchTransformed(PicturePtr pict, int x, int y, int width, CARD32 y = v.vector[1]>>16; x = v.vector[0]>>16; } - if (pixman_region_contains_point (pict->pCompositeClip, x, y, &box)) + if (pixman_region_contains_point (pict->pSourceClip, x, y, &box)) buffer[i] = fetch(bits + (y + pict->pDrawable->y)*stride, x + pict->pDrawable->x, indexed); else buffer[i] = 0; @@ -3194,8 +3195,8 @@ static void fbFetchTransformed(PicturePtr pict, int x, int y, int width, CARD32 unit.vector[1] -= unit.vector[2]/2; if (pict->repeat == RepeatNormal) { - if (PIXREGION_NUM_RECTS(pict->pCompositeClip) == 1) { - box = pict->pCompositeClip->extents; + if (PIXREGION_NUM_RECTS(pict->pSourceClip) == 1) { + box = pict->pSourceClip->extents; for (i = 0; i < width; ++i) { if (!mask || mask[i] & maskBits) { @@ -3298,14 +3299,14 @@ static void fbFetchTransformed(PicturePtr pict, int x, int y, int width, CARD32 b = bits + (y1 + pict->pDrawable->y)*stride; - tl = pixman_region_contains_point(pict->pCompositeClip, x1, y1, &box) + tl = pixman_region_contains_point(pict->pSourceClip, x1, y1, &box) ? fetch(b, x1 + pict->pDrawable->x, indexed) : 0; - tr = pixman_region_contains_point(pict->pCompositeClip, x2, y1, &box) + tr = pixman_region_contains_point(pict->pSourceClip, x2, y1, &box) ? fetch(b, x2 + pict->pDrawable->x, indexed) : 0; b = bits + (y2 + pict->pDrawable->y)*stride; - bl = pixman_region_contains_point(pict->pCompositeClip, x1, y2, &box) + bl = pixman_region_contains_point(pict->pSourceClip, x1, y2, &box) ? fetch(b, x1 + pict->pDrawable->x, indexed) : 0; - br = pixman_region_contains_point(pict->pCompositeClip, x2, y2, &box) + br = pixman_region_contains_point(pict->pSourceClip, x2, y2, &box) ? fetch(b, x2 + pict->pDrawable->x, indexed) : 0; ft = FbGet8(tl,0) * idistx + FbGet8(tr,0) * distx; @@ -3329,8 +3330,8 @@ static void fbFetchTransformed(PicturePtr pict, int x, int y, int width, CARD32 } } } else { - if (PIXREGION_NUM_RECTS(pict->pCompositeClip) == 1) { - box = pict->pCompositeClip->extents; + if (PIXREGION_NUM_RECTS(pict->pSourceClip) == 1) { + box = pict->pSourceClip->extents; for (i = 0; i < width; ++i) { if (!mask || mask[i] & maskBits) { @@ -3431,14 +3432,14 @@ static void fbFetchTransformed(PicturePtr pict, int x, int y, int width, CARD32 b = bits + (y1 + pict->pDrawable->y)*stride; x_off = x1 + pict->pDrawable->x; - tl = pixman_region_contains_point(pict->pCompositeClip, x1, y1, &box) + tl = pixman_region_contains_point(pict->pSourceClip, x1, y1, &box) ? fetch(b, x_off, indexed) : 0; - tr = pixman_region_contains_point(pict->pCompositeClip, x2, y1, &box) + tr = pixman_region_contains_point(pict->pSourceClip, x2, y1, &box) ? fetch(b, x_off + 1, indexed) : 0; b += stride; - bl = pixman_region_contains_point(pict->pCompositeClip, x1, y2, &box) + bl = pixman_region_contains_point(pict->pSourceClip, x1, y2, &box) ? fetch(b, x_off, indexed) : 0; - br = pixman_region_contains_point(pict->pCompositeClip, x2, y2, &box) + br = pixman_region_contains_point(pict->pSourceClip, x2, y2, &box) ? fetch(b, x_off + 1, indexed) : 0; ft = FbGet8(tl,0) * idistx + FbGet8(tr,0) * distx; @@ -3500,7 +3501,7 @@ static void fbFetchTransformed(PicturePtr pict, int x, int y, int width, CARD32 for (x = x1; x < x2; x++) { if (*p) { int tx = (pict->repeat == RepeatNormal) ? MOD (x, pict->pDrawable->width) : x; - if (pixman_region_contains_point (pict->pCompositeClip, tx, ty, &box)) { + if (pixman_region_contains_point (pict->pSourceClip, tx, ty, &box)) { FbBits *b = bits + (ty + pict->pDrawable->y)*stride; CARD32 c = fetch(b, tx + pict->pDrawable->x, indexed); @@ -3755,6 +3756,24 @@ fbCompositeRect (const FbComposeData *data, CARD32 *scanline_buffer) if (!compose) return; + /* XXX: The non-MMX version of some of the fbCompose functions + * overwrite the source or mask data (ones that use + * fbCombineMaskC, fbCombineMaskAlphaC, or fbCombineMaskValueC + * as helpers). This causes problems with the optimization in + * this function that only fetches the source or mask once if + * possible. If we're on a non-MMX machine, disable this + * optimization as a bandaid fix. + * + * https://bugs.freedesktop.org/show_bug.cgi?id=5777 + */ +#ifdef USE_MMX + if (!fbHaveMMX()) +#endif + { + srcClass = SourcePictClassUnknown; + maskClass = SourcePictClassUnknown; + } + for (i = 0; i < data->height; ++i) { /* fill first half of scanline with source */ if (fetchSrc) @@ -3764,7 +3783,7 @@ fbCompositeRect (const FbComposeData *data, CARD32 *scanline_buffer) /* fetch mask before source so that fetching of source can be optimized */ fetchMask (data->mask, data->xMask, data->yMask + i, - data->width, mask_buffer, 0, 0); + data->width, mask_buffer, NULL, 0); if (maskClass == SourcePictClassHorizontal) fetchMask = NULL; @@ -3773,7 +3792,7 @@ fbCompositeRect (const FbComposeData *data, CARD32 *scanline_buffer) if (srcClass == SourcePictClassHorizontal) { fetchSrc (data->src, data->xSrc, data->ySrc + i, - data->width, src_buffer, 0, 0); + data->width, src_buffer, NULL, 0); fetchSrc = NULL; } else @@ -3786,7 +3805,7 @@ fbCompositeRect (const FbComposeData *data, CARD32 *scanline_buffer) else if (fetchMask) { fetchMask (data->mask, data->xMask, data->yMask + i, - data->width, mask_buffer, 0, 0); + data->width, mask_buffer, NULL, 0); } if (store) @@ -3794,7 +3813,7 @@ fbCompositeRect (const FbComposeData *data, CARD32 *scanline_buffer) /* fill dest into second half of scanline */ if (fetchDest) fetchDest (data->dest, data->xDest, data->yDest + i, - data->width, dest_buffer, 0, 0); + data->width, dest_buffer, NULL, 0); /* blend */ compose (dest_buffer, src_buffer, mask_buffer, data->width); @@ -3814,8 +3833,8 @@ fbCompositeRect (const FbComposeData *data, CARD32 *scanline_buffer) } else { - CARD32 *src_mask_buffer = 0; /* squelch bogus compiler warning */ - CARD32 *mask_buffer = 0; + CARD32 *src_mask_buffer = NULL; /* squelch bogus compiler warning */ + CARD32 *mask_buffer = NULL; CombineFuncU compose = composeFunctions.combineU[data->op]; if (!compose) return; @@ -3832,7 +3851,7 @@ fbCompositeRect (const FbComposeData *data, CARD32 *scanline_buffer) /* fetch mask before source so that fetching of source can be optimized */ fetchMask (data->mask, data->xMask, data->yMask + i, - data->width, mask_buffer, 0, 0); + data->width, mask_buffer, NULL, 0); if (maskClass == SourcePictClassHorizontal) fetchMask = NULL; @@ -3841,7 +3860,7 @@ fbCompositeRect (const FbComposeData *data, CARD32 *scanline_buffer) if (srcClass == SourcePictClassHorizontal) { fetchSrc (data->src, data->xSrc, data->ySrc + i, - data->width, src_buffer, 0, 0); + data->width, src_buffer, NULL, 0); if (mask_buffer) { @@ -3870,7 +3889,7 @@ fbCompositeRect (const FbComposeData *data, CARD32 *scanline_buffer) else if (fetchMask) { fetchMask (data->mask, data->xMask, data->yMask + i, - data->width, mask_buffer, 0, 0); + data->width, mask_buffer, NULL, 0); fbCombineInU (mask_buffer, src_buffer, data->width); @@ -3882,7 +3901,7 @@ fbCompositeRect (const FbComposeData *data, CARD32 *scanline_buffer) /* fill dest into second half of scanline */ if (fetchDest) fetchDest (data->dest, data->xDest, data->yDest + i, - data->width, dest_buffer, 0, 0); + data->width, dest_buffer, NULL, 0); /* blend */ compose (dest_buffer, src_mask_buffer, data->width); diff --git a/gfx/cairo/libpixman/src/fbmmx.c b/gfx/cairo/libpixman/src/fbmmx.c index 00856ef7252a..4d603bf785ed 100644 --- a/gfx/cairo/libpixman/src/fbmmx.c +++ b/gfx/cairo/libpixman/src/fbmmx.c @@ -1060,7 +1060,7 @@ fbCompositeSolidMask_nx8888x8888Cmmx (pixman_operator_t op, while (height--) { - int twidth = width; + unsigned int twidth = width; CARD32 *p = (CARD32 *)maskLine; CARD32 *q = (CARD32 *)dstLine; @@ -2020,7 +2020,7 @@ fbCompositeSolidMask_nx8888x0565Cmmx (pixman_operator_t op, while (height--) { - int twidth = width; + unsigned int twidth = width; CARD32 *p = (CARD32 *)maskLine; CARD16 *q = (CARD16 *)dstLine; @@ -2270,7 +2270,7 @@ fbSolidFillmmx (FbPixels *pDraw, while (height--) { - int w; + unsigned int w; CARD8 *d = byte_line; byte_line += stride; w = byte_width; @@ -2386,7 +2386,7 @@ fbCopyAreammx (FbPixels *pSrc, while (height--) { - int w; + unsigned int w; CARD8 *s = src_bytes; CARD8 *d = dst_bytes; src_bytes += src_stride; @@ -2401,7 +2401,7 @@ fbCopyAreammx (FbPixels *pSrc, d += 2; } - while (w >= 4 && ((unsigned int)d & 7)) + while (w >= 4 && ((unsigned long)d & 7)) { *(CARD32 *)d = *(CARD32 *)s; diff --git a/gfx/cairo/libpixman/src/fbmmx.h b/gfx/cairo/libpixman/src/fbmmx.h index 1a6a27d25034..531bcbab44e1 100644 --- a/gfx/cairo/libpixman/src/fbmmx.h +++ b/gfx/cairo/libpixman/src/fbmmx.h @@ -29,6 +29,7 @@ #ifdef USE_MMX #if !defined(__amd64__) && !defined(__x86_64__) +pixman_private Bool fbHaveMMX(void); #else #define fbHaveMMX() TRUE @@ -40,8 +41,10 @@ Bool fbHaveMMX(void); #ifdef USE_MMX +pixman_private void fbComposeSetupMMX(void); +pixman_private void fbCompositeSolidMask_nx8888x0565Cmmx (pixman_operator_t op, PicturePtr pSrc, PicturePtr pMask, @@ -54,6 +57,7 @@ void fbCompositeSolidMask_nx8888x0565Cmmx (pixman_operator_t op, INT16 yDst, CARD16 width, CARD16 height); +pixman_private void fbCompositeSrcAdd_8888x8888mmx (pixman_operator_t op, PicturePtr pSrc, PicturePtr pMask, @@ -66,6 +70,7 @@ void fbCompositeSrcAdd_8888x8888mmx (pixman_operator_t op, INT16 yDst, CARD16 width, CARD16 height); +pixman_private void fbCompositeSolidMask_nx8888x8888Cmmx (pixman_operator_t op, PicturePtr pSrc, PicturePtr pMask, @@ -78,6 +83,7 @@ void fbCompositeSolidMask_nx8888x8888Cmmx (pixman_operator_t op, INT16 yDst, CARD16 width, CARD16 height); +pixman_private void fbCompositeSolidMask_nx8x8888mmx (pixman_operator_t op, PicturePtr pSrc, PicturePtr pMask, @@ -90,6 +96,7 @@ void fbCompositeSolidMask_nx8x8888mmx (pixman_operator_t op, INT16 yDst, CARD16 width, CARD16 height); +pixman_private void fbCompositeSolidMaskSrc_nx8x8888mmx (pixman_operator_t op, PicturePtr pSrc, PicturePtr pMask, @@ -102,6 +109,7 @@ void fbCompositeSolidMaskSrc_nx8x8888mmx (pixman_operator_t op, INT16 yDst, CARD16 width, CARD16 height); +pixman_private void fbCompositeSrcAdd_8000x8000mmx (pixman_operator_t op, PicturePtr pSrc, PicturePtr pMask, @@ -114,6 +122,7 @@ void fbCompositeSrcAdd_8000x8000mmx (pixman_operator_t op, INT16 yDst, CARD16 width, CARD16 height); +pixman_private void fbCompositeSrc_8888RevNPx8888mmx (pixman_operator_t op, PicturePtr pSrc, PicturePtr pMask, @@ -126,6 +135,7 @@ void fbCompositeSrc_8888RevNPx8888mmx (pixman_operator_t op, INT16 yDst, CARD16 width, CARD16 height); +pixman_private void fbCompositeSrc_8888RevNPx0565mmx (pixman_operator_t op, PicturePtr pSrc, PicturePtr pMask, @@ -138,6 +148,7 @@ void fbCompositeSrc_8888RevNPx0565mmx (pixman_operator_t op, INT16 yDst, CARD16 width, CARD16 height); +pixman_private void fbCompositeSolid_nx8888mmx (pixman_operator_t op, PicturePtr pSrc, PicturePtr pMask, @@ -150,6 +161,7 @@ void fbCompositeSolid_nx8888mmx (pixman_operator_t op, INT16 yDst, CARD16 width, CARD16 height); +pixman_private void fbCompositeSolid_nx0565mmx (pixman_operator_t op, PicturePtr pSrc, PicturePtr pMask, @@ -162,6 +174,7 @@ void fbCompositeSolid_nx0565mmx (pixman_operator_t op, INT16 yDst, CARD16 width, CARD16 height); +pixman_private void fbCompositeSolidMask_nx8x0565mmx (pixman_operator_t op, PicturePtr pSrc, PicturePtr pMask, @@ -174,6 +187,7 @@ void fbCompositeSolidMask_nx8x0565mmx (pixman_operator_t op, INT16 yDst, CARD16 width, CARD16 height); +pixman_private void fbCompositeSrc_x888x8x8888mmx (pixman_operator_t op, PicturePtr pSrc, PicturePtr pMask, @@ -186,6 +200,7 @@ void fbCompositeSrc_x888x8x8888mmx (pixman_operator_t op, INT16 yDst, CARD16 width, CARD16 height); +pixman_private void fbCompositeSrc_8888x8x8888mmx (pixman_operator_t op, PicturePtr pSrc, PicturePtr pMask, @@ -198,6 +213,7 @@ void fbCompositeSrc_8888x8x8888mmx (pixman_operator_t op, INT16 yDst, CARD16 width, CARD16 height); +pixman_private void fbCompositeSrc_8888x8888mmx (pixman_operator_t op, PicturePtr pSrc, PicturePtr pMask, @@ -210,6 +226,7 @@ void fbCompositeSrc_8888x8888mmx (pixman_operator_t op, INT16 yDst, CARD16 width, CARD16 height); +pixman_private Bool fbCopyAreammx (FbPixels *pSrc, FbPixels *pDst, int src_x, @@ -218,6 +235,8 @@ Bool fbCopyAreammx (FbPixels *pSrc, int dst_y, int width, int height); + +pixman_private void fbCompositeCopyAreammx (pixman_operator_t op, PicturePtr pSrc, PicturePtr pMask, @@ -230,6 +249,8 @@ void fbCompositeCopyAreammx (pixman_operator_t op, INT16 yDst, CARD16 width, CARD16 height); + +pixman_private Bool fbSolidFillmmx (FbPixels *pDraw, int x, int y, diff --git a/gfx/cairo/libpixman/src/fbpict.c b/gfx/cairo/libpixman/src/fbpict.c index 6f454c631616..675d1fb41bd8 100644 --- a/gfx/cairo/libpixman/src/fbpict.c +++ b/gfx/cairo/libpixman/src/fbpict.c @@ -1349,7 +1349,7 @@ pixman_composite (pixman_operator_t op, Bool maskAlphaMap = FALSE; Bool dstAlphaMap = pDst->alphaMap != 0; int x_msk, y_msk, x_src, y_src, x_dst, y_dst; - int w, h, w_this, h_this; + unsigned int w, h, w_this, h_this; #ifdef USE_MMX static Bool mmx_setup = FALSE; @@ -1798,6 +1798,17 @@ pixman_composite (pixman_operator_t op, } } break; + case PIXMAN_OPERATOR_CLEAR: + case PIXMAN_OPERATOR_DST: + case PIXMAN_OPERATOR_OVER_REVERSE: + case PIXMAN_OPERATOR_IN: + case PIXMAN_OPERATOR_IN_REVERSE: + case PIXMAN_OPERATOR_OUT: + case PIXMAN_OPERATOR_OUT_REVERSE: + case PIXMAN_OPERATOR_ATOP: + case PIXMAN_OPERATOR_ATOP_REVERSE: + case PIXMAN_OPERATOR_XOR: + case PIXMAN_OPERATOR_SATURATE: default: /* For any operator not specifically handled above we default out to the general code. */ func = NULL; @@ -1891,7 +1902,6 @@ pixman_composite (pixman_operator_t op, } pixman_region_destroy (region); } -slim_hidden_def(pixman_composite); /* The CPU detection code needs to be in a file not compiled with * "-mmmx -msse", as gcc would generate CMOV instructions otherwise diff --git a/gfx/cairo/libpixman/src/iccolor.c b/gfx/cairo/libpixman/src/iccolor.c index 716382f44495..26b4aaf5764a 100644 --- a/gfx/cairo/libpixman/src/iccolor.c +++ b/gfx/cairo/libpixman/src/iccolor.c @@ -53,7 +53,6 @@ pixman_color_to_pixel (const pixman_format_t *format, a = a << format->alpha; *pixel = r|g|b|a; } -slim_hidden_def(pixman_color_to_pixel); static uint16_t FbFillColor (uint32_t pixel, int bits) diff --git a/gfx/cairo/libpixman/src/icformat.c b/gfx/cairo/libpixman/src/icformat.c index 62a171da8aae..bf93a6c9461f 100644 --- a/gfx/cairo/libpixman/src/icformat.c +++ b/gfx/cairo/libpixman/src/icformat.c @@ -23,7 +23,7 @@ #include "icint.h" -#define Mask(n) ((n) == 32 ? 0xffffffff : ((1 << (n))-1)) +#define Mask(n) ((n) == 32 ? 0xffffffff : (unsigned) ((1 << (n))-1)) pixman_format_t * pixman_format_create (pixman_format_name_t name) @@ -53,6 +53,18 @@ pixman_format_create (pixman_format_name_t name) 0xf800, 0x07e0, 0x001f); + case PIXMAN_FORMAT_NAME_ABGR32: + return pixman_format_create_masks (32, + 0xff000000, + 0x000000ff, + 0x0000ff00, + 0x00ff0000); + case PIXMAN_FORMAT_NAME_BGR24: + return pixman_format_create_masks (32, + 0x0, + 0x000000ff, + 0x0000ff00, + 0x00ff0000); } return NULL; @@ -159,7 +171,6 @@ pixman_format_init (pixman_format_t *format, int format_code) (format->blueMask << format->blue) | (format->greenMask << format->green)); } -slim_hidden_def(pixman_format_init); void pixman_format_destroy (pixman_format_t *format) @@ -169,11 +180,11 @@ pixman_format_destroy (pixman_format_t *format) void pixman_format_get_masks (pixman_format_t *format, - int *bpp, - int *alpha_mask, - int *red_mask, - int *green_mask, - int *blue_mask) + unsigned int *bpp, + unsigned int *alpha_mask, + unsigned int *red_mask, + unsigned int *green_mask, + unsigned int *blue_mask) { *bpp = PICT_FORMAT_BPP (format->format_code); diff --git a/gfx/cairo/libpixman/src/icimage.c b/gfx/cairo/libpixman/src/icimage.c index 9cf05491871c..44c4c8b34bc1 100644 --- a/gfx/cairo/libpixman/src/icimage.c +++ b/gfx/cairo/libpixman/src/icimage.c @@ -45,7 +45,6 @@ pixman_image_create (pixman_format_t *format, return image; } -slim_hidden_def(pixman_image_create); pixman_image_t * pixman_image_create_for_data (FbBits *data, pixman_format_t *format, int width, int height, int bpp, int stride) @@ -188,8 +187,8 @@ _pixman_create_source_image (void) pixman_image_t *image; image = (pixman_image_t *) malloc (sizeof (pixman_image_t)); - image->pDrawable = 0; - image->pixels = 0; + image->pDrawable = NULL; + image->pixels = NULL; image->format_code = PICT_a8r8g8b8; pixman_image_init (image); @@ -206,18 +205,18 @@ pixman_image_create_linear_gradient (const pixman_linear_gradient_t *gradient, pixman_image_t *image; if (n_stops < 2) - return 0; + return NULL; image = _pixman_create_source_image (); if (!image) - return 0; + return NULL; linear = malloc (sizeof (pixman_linear_gradient_image_t) + sizeof (pixman_gradient_stop_t) * n_stops); if (!linear) { free (image); - return 0; + return NULL; } linear->stops = (pixman_gradient_stop_t *) (linear + 1); @@ -233,8 +232,9 @@ pixman_image_create_linear_gradient (const pixman_linear_gradient_t *gradient, if (_pixman_init_gradient (&image->pSourcePict->gradient, stops, n_stops)) { + free (linear); free (image); - return 0; + return NULL; } return image; @@ -250,18 +250,18 @@ pixman_image_create_radial_gradient (const pixman_radial_gradient_t *gradient, double x; if (n_stops < 2) - return 0; + return NULL; image = _pixman_create_source_image (); if (!image) - return 0; + return NULL; radial = malloc (sizeof (pixman_radial_gradient_image_t) + sizeof (pixman_gradient_stop_t) * n_stops); if (!radial) { free (image); - return 0; + return NULL; } radial->stops = (pixman_gradient_stop_t *) (radial + 1); @@ -288,8 +288,9 @@ pixman_image_create_radial_gradient (const pixman_radial_gradient_t *gradient, if (_pixman_init_gradient (&image->pSourcePict->gradient, stops, n_stops)) { + free (radial); free (image); - return 0; + return NULL; } return image; @@ -367,7 +368,6 @@ pixman_image_set_component_alpha (pixman_image_t *image, if (image) image->componentAlpha = component_alpha; } -slim_hidden_def(pixman_image_set_component_alpha); int pixman_image_set_transform (pixman_image_t *image, @@ -410,7 +410,6 @@ pixman_image_set_repeat (pixman_image_t *image, if (image) image->repeat = repeat; } -slim_hidden_def(pixman_image_set_repeat); void pixman_image_set_filter (pixman_image_t *image, @@ -468,7 +467,7 @@ pixman_image_get_data (pixman_image_t *image) if (image->pixels) return image->pixels->data; - return 0; + return NULL; } void @@ -503,7 +502,6 @@ pixman_image_destroy (pixman_image_t *image) free (image); } -slim_hidden_def(pixman_image_destroy); void pixman_image_destroyClip (pixman_image_t *image) diff --git a/gfx/cairo/libpixman/src/icimage.h b/gfx/cairo/libpixman/src/icimage.h index eff1be24d7d0..82202a71e561 100644 --- a/gfx/cairo/libpixman/src/icimage.h +++ b/gfx/cairo/libpixman/src/icimage.h @@ -243,7 +243,7 @@ FbComputeCompositeRegion (pixman_region16_t *region, uint16_t width, uint16_t height); -int +pixman_private int miIsSolidAlpha (pixman_image_t *src); /* diff --git a/gfx/cairo/libpixman/src/icint.h b/gfx/cairo/libpixman/src/icint.h index e1265eb31a34..a489bb7b4fef 100644 --- a/gfx/cairo/libpixman/src/icint.h +++ b/gfx/cairo/libpixman/src/icint.h @@ -33,8 +33,6 @@ #include #include -#include "slim_internal.h" - #ifndef __GNUC__ #define __inline #endif @@ -813,7 +811,7 @@ fbRasterizeTrapezoid (pixman_image_t *pMask, # endif #else # define ICINT_NEED_IC_ONES -int +pixman_private int _FbOnes(unsigned long mask); #endif @@ -852,17 +850,6 @@ pixman_private int pixman_transform_point (pixman_transform_t *transform, pixman_vector_t *vector); -/* Avoid unnessecary PLT entries. */ - -slim_hidden_proto(pixman_image_create) -slim_hidden_proto(pixman_color_to_pixel) -slim_hidden_proto(pixman_format_init) -slim_hidden_proto(pixman_image_destroy) -slim_hidden_proto(pixman_fill_rectangles) -slim_hidden_proto(pixman_image_set_component_alpha) -slim_hidden_proto(pixman_image_set_repeat) -slim_hidden_proto(pixman_composite) - #include "icrop.h" /* XXX: For now, I'm just wholesale pasting Xserver/render/picture.h here: */ diff --git a/gfx/cairo/libpixman/src/icrect.c b/gfx/cairo/libpixman/src/icrect.c index 7253bfa18431..e4d0c12aade2 100644 --- a/gfx/cairo/libpixman/src/icrect.c +++ b/gfx/cairo/libpixman/src/icrect.c @@ -363,4 +363,3 @@ bail1: ; } } -slim_hidden_def(pixman_fill_rectangles); diff --git a/gfx/cairo/libpixman/src/ictri.c b/gfx/cairo/libpixman/src/ictri.c index 09902abd6063..408023994fba 100644 --- a/gfx/cairo/libpixman/src/ictri.c +++ b/gfx/cairo/libpixman/src/ictri.c @@ -143,7 +143,7 @@ pixman_composite_triangles (pixman_operator_t op, const pixman_triangle_t *tris, int ntris) { - pixman_box16_t bounds; + pixman_box16_t bounds = {0, 0, 0, 0}; /* shut gcc up */ pixman_image_t *image = NULL; int xDst, yDst; int xRel, yRel; @@ -215,7 +215,7 @@ pixman_composite_tri_strip (pixman_operator_t op, int npoints) { pixman_triangle_t tri; - pixman_box16_t bounds; + pixman_box16_t bounds = {0, 0, 0, 0}; /* shut gcc up */ pixman_image_t *image = NULL; int xDst, yDst; int xRel, yRel; @@ -292,7 +292,7 @@ pixman_composite_tri_fan (pixman_operator_t op, int npoints) { pixman_triangle_t tri; - pixman_box16_t bounds; + pixman_box16_t bounds = {0, 0, 0, 0}; /* shut gcc up */ pixman_image_t *image = NULL; const pixman_point_fixed_t *first; int xDst, yDst; diff --git a/gfx/cairo/libpixman/src/icutil.c b/gfx/cairo/libpixman/src/icutil.c index e1c7fd08b009..55ee293428f1 100644 --- a/gfx/cairo/libpixman/src/icutil.c +++ b/gfx/cairo/libpixman/src/icutil.c @@ -281,5 +281,5 @@ fbStippleTable(int bits) case 8: return fbStipple8Bits; } - return 0; + return NULL; } diff --git a/gfx/cairo/libpixman/src/pixman-remap.h b/gfx/cairo/libpixman/src/pixman-remap.h index 17a00e5fdfe3..45a4477af408 100644 --- a/gfx/cairo/libpixman/src/pixman-remap.h +++ b/gfx/cairo/libpixman/src/pixman-remap.h @@ -1,79 +1,79 @@ -#define pixman_add_trapezoids _moz_cairo_pixman_add_trapezoids -#define pixman_color_to_pixel _moz_cairo_pixman_color_to_pixel -#define composeFunctions _moz_cairo_pixman_compose_functions -#define fbComposeSetupMMX _moz_cairo_pixman_compose_setup_mmx -#define pixman_composite _moz_cairo_pixman_composite -#define fbCompositeCopyAreammx _moz_cairo_pixman_composite_copy_area_mmx -#define fbCompositeSolidMask_nx8888x0565Cmmx _moz_cairo_pixman_composite_solid_mask_nx8888x0565Cmmx -#define fbCompositeSolidMask_nx8888x8888Cmmx _moz_cairo_pixman_composite_solid_mask_nx8888x8888Cmmx -#define fbCompositeSolidMask_nx8x0565mmx _moz_cairo_pixman_composite_solid_mask_nx8x0565mmx -#define fbCompositeSolidMask_nx8x8888mmx _moz_cairo_pixman_composite_solid_mask_nx8x8888mmx -#define fbCompositeSolidMaskSrc_nx8x8888mmx _moz_cairo_pixman_composite_solid_mask_src_nx8x8888mmx -#define fbCompositeSolid_nx0565mmx _moz_cairo_pixman_composite_solid_nx0565mmx -#define fbCompositeSolid_nx8888mmx _moz_cairo_pixman_composite_solid_nx8888mmx -#define fbCompositeSrc_8888RevNPx0565mmx _moz_cairo_pixman_composite_src_8888RevNPx0565mmx -#define fbCompositeSrc_8888RevNPx8888mmx _moz_cairo_pixman_composite_src_8888RevNPx8888_mmx -#define fbCompositeSrc_8888x8888mmx _moz_cairo_pixman_composite_src_8888x8888mmx -#define fbCompositeSrc_8888x8x8888mmx _moz_cairo_pixman_composite_src_8888x8x8888mmx -#define fbCompositeSrcAdd_8000x8000mmx _moz_cairo_pixman_composite_src_add_8000x8000mmx -#define fbCompositeSrcAdd_8888x8888mmx _moz_cairo_pixman_composite_src_add_8888x8888mmx -#define fbCompositeSrc_x888x8x8888mmx _moz_cairo_pixman_composite_src_x888x8x8888mmx -#define pixman_composite_trapezoids _moz_cairo_pixman_composite_trapezoids -#define pixman_composite_tri_fan _moz_cairo_pixman_composite_tri_fan -#define pixman_composite_tri_strip _moz_cairo_pixman_composite_tri_strip -#define pixman_composite_triangles _moz_cairo_pixman_composite_triangles -#define fbCopyAreammx _moz_cairo_pixman_copy_area_mmx -#define pixman_fill_rectangle _moz_cairo_pixman_fill_rectangle -#define pixman_fill_rectangles _moz_cairo_pixman_fill_rectangles -#define pixman_format_create _moz_cairo_pixman_format_create -#define pixman_format_create_masks _moz_cairo_pixman_format_create_masks -#define pixman_format_destroy _moz_cairo_pixman_format_destroy -#define pixman_format_get_masks _moz_cairo_pixman_format_get_masks -#define pixman_format_init _moz_cairo_pixman_format_init +#define pixman_add_trapezoids _cairo_pixman_add_trapezoids +#define pixman_color_to_pixel _cairo_pixman_color_to_pixel +#define composeFunctions _cairo_pixman_compose_functions +#define fbComposeSetupMMX _cairo_pixman_compose_setup_mmx +#define pixman_composite _cairo_pixman_composite +#define fbCompositeCopyAreammx _cairo_pixman_composite_copy_area_mmx +#define fbCompositeSolidMask_nx8888x0565Cmmx _cairo_pixman_composite_solid_mask_nx8888x0565Cmmx +#define fbCompositeSolidMask_nx8888x8888Cmmx _cairo_pixman_composite_solid_mask_nx8888x8888Cmmx +#define fbCompositeSolidMask_nx8x0565mmx _cairo_pixman_composite_solid_mask_nx8x0565mmx +#define fbCompositeSolidMask_nx8x8888mmx _cairo_pixman_composite_solid_mask_nx8x8888mmx +#define fbCompositeSolidMaskSrc_nx8x8888mmx _cairo_pixman_composite_solid_mask_src_nx8x8888mmx +#define fbCompositeSolid_nx0565mmx _cairo_pixman_composite_solid_nx0565mmx +#define fbCompositeSolid_nx8888mmx _cairo_pixman_composite_solid_nx8888mmx +#define fbCompositeSrc_8888RevNPx0565mmx _cairo_pixman_composite_src_8888RevNPx0565mmx +#define fbCompositeSrc_8888RevNPx8888mmx _cairo_pixman_composite_src_8888RevNPx8888_mmx +#define fbCompositeSrc_8888x8888mmx _cairo_pixman_composite_src_8888x8888mmx +#define fbCompositeSrc_8888x8x8888mmx _cairo_pixman_composite_src_8888x8x8888mmx +#define fbCompositeSrcAdd_8000x8000mmx _cairo_pixman_composite_src_add_8000x8000mmx +#define fbCompositeSrcAdd_8888x8888mmx _cairo_pixman_composite_src_add_8888x8888mmx +#define fbCompositeSrc_x888x8x8888mmx _cairo_pixman_composite_src_x888x8x8888mmx +#define pixman_composite_trapezoids _cairo_pixman_composite_trapezoids +#define pixman_composite_tri_fan _cairo_pixman_composite_tri_fan +#define pixman_composite_tri_strip _cairo_pixman_composite_tri_strip +#define pixman_composite_triangles _cairo_pixman_composite_triangles +#define fbCopyAreammx _cairo_pixman_copy_area_mmx +#define pixman_fill_rectangle _cairo_pixman_fill_rectangle +#define pixman_fill_rectangles _cairo_pixman_fill_rectangles +#define pixman_format_create _cairo_pixman_format_create +#define pixman_format_create_masks _cairo_pixman_format_create_masks +#define pixman_format_destroy _cairo_pixman_format_destroy +#define pixman_format_get_masks _cairo_pixman_format_get_masks +#define pixman_format_init _cairo_pixman_format_init #if defined(USE_MMX) && !defined(__amd64__) && !defined(__x86_64__) -#define fbHaveMMX _moz_cairo_pixman_have_mmx +#define fbHaveMMX _cairo_pixman_have_mmx #endif -#define pixman_image_create _moz_cairo_pixman_image_create -#define pixman_image_create_for_data _moz_cairo_pixman_image_create_for_data -#define pixman_image_destroy _moz_cairo_pixman_image_destroy -#define pixman_image_get_data _moz_cairo_pixman_image_get_data -#define pixman_image_get_depth _moz_cairo_pixman_image_get_depth -#define pixman_image_get_format _moz_cairo_pixman_image_get_format -#define pixman_image_get_height _moz_cairo_pixman_image_get_height -#define pixman_image_get_stride _moz_cairo_pixman_image_get_stride -#define pixman_image_get_width _moz_cairo_pixman_image_get_width -#define pixman_image_set_clip_region _moz_cairo_pixman_image_set_clip_region -#define pixman_image_set_component_alpha _moz_cairo_pixman_image_set_component_alpha -#define pixman_image_set_filter _moz_cairo_pixman_image_set_filter -#define pixman_image_set_repeat _moz_cairo_pixman_image_set_repeat -#define pixman_image_set_transform _moz_cairo_pixman_image_set_transform -#define pixman_image_create_linear_gradient _moz_cairo_pixman_image_create_linear_gradient -#define pixman_image_create_radial_gradient _moz_cairo_pixman_image_create_radial_gradient -#define miIsSolidAlpha _moz_cairo_pixman_is_solid_alpha -#define pixman_pixel_to_color _moz_cairo_pixman_pixel_to_color -#define pixman_region_append _moz_cairo_pixman_region_append -#define pixman_region_contains_point _moz_cairo_pixman_region_contains_point -#define pixman_region_contains_rectangle _moz_cairo_pixman_region_contains_rectangle -#define pixman_region_copy _moz_cairo_pixman_region_copy -#define pixman_region_create _moz_cairo_pixman_region_create -#define pixman_region_create_simple _moz_cairo_pixman_region_create_simple -#define pixman_region_destroy _moz_cairo_pixman_region_destroy -#define pixman_region_empty _moz_cairo_pixman_region_empty -#define pixman_region_extents _moz_cairo_pixman_region_extents -#define pixman_region_intersect _moz_cairo_pixman_region_intersect -#define pixman_region_inverse _moz_cairo_pixman_region_inverse -#define pixman_region_not_empty _moz_cairo_pixman_region_not_empty -#define pixman_region_num_rects _moz_cairo_pixman_region_num_rects -#define pixman_region_rects _moz_cairo_pixman_region_rects -#define pixman_region_reset _moz_cairo_pixman_region_reset -#define pixman_region_subtract _moz_cairo_pixman_region_subtract -#define pixman_region_translate _moz_cairo_pixman_region_translate -#define pixman_region_union _moz_cairo_pixman_region_union -#define pixman_region_union_rect _moz_cairo_pixman_region_union_rect -#define pixman_region_validate _moz_cairo_pixman_region_validate -#define RenderEdgeInit _moz_cairo_pixman_render_edge_init -#define RenderEdgeStep _moz_cairo_pixman_render_edge_step -#define RenderLineFixedEdgeInit _moz_cairo_pixman_render_line_fixed_edge_init -#define RenderSampleCeilY _moz_cairo_pixman_render_sample_ceil_y -#define RenderSampleFloorY _moz_cairo_pixman_render_sample_floor_y -#define fbSolidFillmmx _moz_cairo_pixman_solid_fill_mmx +#define pixman_image_create _cairo_pixman_image_create +#define pixman_image_create_for_data _cairo_pixman_image_create_for_data +#define pixman_image_destroy _cairo_pixman_image_destroy +#define pixman_image_get_data _cairo_pixman_image_get_data +#define pixman_image_get_depth _cairo_pixman_image_get_depth +#define pixman_image_get_format _cairo_pixman_image_get_format +#define pixman_image_get_height _cairo_pixman_image_get_height +#define pixman_image_get_stride _cairo_pixman_image_get_stride +#define pixman_image_get_width _cairo_pixman_image_get_width +#define pixman_image_set_clip_region _cairo_pixman_image_set_clip_region +#define pixman_image_set_component_alpha _cairo_pixman_image_set_component_alpha +#define pixman_image_set_filter _cairo_pixman_image_set_filter +#define pixman_image_set_repeat _cairo_pixman_image_set_repeat +#define pixman_image_set_transform _cairo_pixman_image_set_transform +#define pixman_image_create_linear_gradient _cairo_pixman_image_create_linear_gradient +#define pixman_image_create_radial_gradient _cairo_pixman_image_create_radial_gradient +#define miIsSolidAlpha _cairo_pixman_is_solid_alpha +#define pixman_pixel_to_color _cairo_pixman_pixel_to_color +#define pixman_region_append _cairo_pixman_region_append +#define pixman_region_contains_point _cairo_pixman_region_contains_point +#define pixman_region_contains_rectangle _cairo_pixman_region_contains_rectangle +#define pixman_region_copy _cairo_pixman_region_copy +#define pixman_region_create _cairo_pixman_region_create +#define pixman_region_create_simple _cairo_pixman_region_create_simple +#define pixman_region_destroy _cairo_pixman_region_destroy +#define pixman_region_empty _cairo_pixman_region_empty +#define pixman_region_extents _cairo_pixman_region_extents +#define pixman_region_intersect _cairo_pixman_region_intersect +#define pixman_region_inverse _cairo_pixman_region_inverse +#define pixman_region_not_empty _cairo_pixman_region_not_empty +#define pixman_region_num_rects _cairo_pixman_region_num_rects +#define pixman_region_rects _cairo_pixman_region_rects +#define pixman_region_reset _cairo_pixman_region_reset +#define pixman_region_subtract _cairo_pixman_region_subtract +#define pixman_region_translate _cairo_pixman_region_translate +#define pixman_region_union _cairo_pixman_region_union +#define pixman_region_union_rect _cairo_pixman_region_union_rect +#define pixman_region_validate _cairo_pixman_region_validate +#define RenderEdgeInit _cairo_pixman_render_edge_init +#define RenderEdgeStep _cairo_pixman_render_edge_step +#define RenderLineFixedEdgeInit _cairo_pixman_render_line_fixed_edge_init +#define RenderSampleCeilY _cairo_pixman_render_sample_ceil_y +#define RenderSampleFloorY _cairo_pixman_render_sample_floor_y +#define fbSolidFillmmx _cairo_pixman_solid_fill_mmx diff --git a/gfx/cairo/libpixman/src/pixman.h b/gfx/cairo/libpixman/src/pixman.h index ca24e338eea1..309e5e655b84 100644 --- a/gfx/cairo/libpixman/src/pixman.h +++ b/gfx/cairo/libpixman/src/pixman.h @@ -99,6 +99,14 @@ SOFTWARE. #include "pixman-remap.h" +#if (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 3)) && defined(__ELF__) +#define pixman_private __attribute__((__visibility__("hidden"))) +#elif defined(__SUNPRO_C) && (__SUNPRO_C >= 0x550) +#define pixman_private __hidden +#else /* not gcc >= 3.3 and not Sun Studio >= 8 */ +#define pixman_private +#endif + #if defined(__cplusplus) || defined(c_plusplus) extern "C" { #endif @@ -118,37 +126,37 @@ typedef enum { /* creation/destruction */ -pixman_region16_t * +pixman_private pixman_region16_t * pixman_region_create (void); -pixman_region16_t * +pixman_private pixman_region16_t * pixman_region_create_simple (pixman_box16_t *extents); -void +pixman_private void pixman_region_destroy (pixman_region16_t *region); /* manipulation */ -void +pixman_private void pixman_region_translate (pixman_region16_t *region, int x, int y); -pixman_region_status_t +pixman_private pixman_region_status_t pixman_region_copy (pixman_region16_t *dest, pixman_region16_t *source); -pixman_region_status_t +pixman_private pixman_region_status_t pixman_region_intersect (pixman_region16_t *newReg, pixman_region16_t *reg1, pixman_region16_t *reg2); -pixman_region_status_t +pixman_private pixman_region_status_t pixman_region_union (pixman_region16_t *newReg, pixman_region16_t *reg1, pixman_region16_t *reg2); -pixman_region_status_t +pixman_private pixman_region_status_t pixman_region_union_rect(pixman_region16_t *dest, pixman_region16_t *source, int x, int y, unsigned int width, unsigned int height); -pixman_region_status_t +pixman_private pixman_region_status_t pixman_region_subtract (pixman_region16_t *regD, pixman_region16_t *regM, pixman_region16_t *regS); -pixman_region_status_t +pixman_private pixman_region_status_t pixman_region_inverse (pixman_region16_t *newReg, pixman_region16_t *reg1, pixman_box16_t *invRect); /* XXX: Need to fix this so it doesn't depend on an X data structure @@ -159,10 +167,10 @@ RectsTopixman_region16_t (int nrects, xRectanglePtr prect, int ctype); /* querying */ /* XXX: These should proably be combined: pixman_region_get_rects? */ -int +pixman_private int pixman_region_num_rects (pixman_region16_t *region); -pixman_box16_t * +pixman_private pixman_box16_t * pixman_region_rects (pixman_region16_t *region); /* XXX: Change to an enum */ @@ -170,36 +178,36 @@ pixman_region_rects (pixman_region16_t *region); #define rgnIN 1 #define rgnPART 2 -int +pixman_private int pixman_region_contains_point (pixman_region16_t *region, int x, int y, pixman_box16_t *box); -int +pixman_private int pixman_region_contains_rectangle (pixman_region16_t *pixman_region16_t, pixman_box16_t *prect); -int +pixman_private int pixman_region_not_empty (pixman_region16_t *region); -pixman_box16_t * +pixman_private pixman_box16_t * pixman_region_extents (pixman_region16_t *region); /* mucking around */ /* WARNING: calling pixman_region_append may leave dest as an invalid region. Follow-up with pixman_region_validate to fix it up. */ -pixman_region_status_t +pixman_private pixman_region_status_t pixman_region_append (pixman_region16_t *dest, pixman_region16_t *region); -pixman_region_status_t +pixman_private pixman_region_status_t pixman_region_validate (pixman_region16_t *badreg, int *pOverlap); /* Unclassified functionality * XXX: Do all of these need to be exported? */ -void +pixman_private void pixman_region_reset (pixman_region16_t *region, pixman_box16_t *pBox); -void +pixman_private void pixman_region_empty (pixman_region16_t *region); /* ic.h */ @@ -227,37 +235,39 @@ typedef enum pixman_format_name { PIXMAN_FORMAT_NAME_RGB24, PIXMAN_FORMAT_NAME_A8, PIXMAN_FORMAT_NAME_A1, - PIXMAN_FORMAT_NAME_RGB16_565 + PIXMAN_FORMAT_NAME_RGB16_565, + PIXMAN_FORMAT_NAME_ABGR32, + PIXMAN_FORMAT_NAME_BGR24 } pixman_format_name_t; typedef struct pixman_format pixman_format_t; -pixman_format_t * +pixman_private pixman_format_t * pixman_format_create (pixman_format_name_t name); -pixman_format_t * +pixman_private pixman_format_t * pixman_format_create_masks (int bpp, int alpha_mask, int red_mask, int green_mask, int blue_mask); -void +pixman_private void pixman_format_destroy (pixman_format_t *format); -void +pixman_private void pixman_format_get_masks (pixman_format_t *format, - int *bpp, - int *alpha_mask, - int *red_mask, - int *green_mask, - int *blue_mask); + unsigned int *bpp, + unsigned int *alpha_mask, + unsigned int *red_mask, + unsigned int *green_mask, + unsigned int *blue_mask); /* icimage.c */ typedef struct pixman_image pixman_image_t; -pixman_image_t * +pixman_private pixman_image_t * pixman_image_create (pixman_format_t *format, int width, int height); @@ -282,16 +292,16 @@ pixman_image_create (pixman_format_t *format, typedef uint32_t pixman_bits_t; #endif -pixman_image_t * +pixman_private pixman_image_t * pixman_image_create_for_data (pixman_bits_t *data, pixman_format_t *format, int width, int height, int bpp, int stride); -void +pixman_private void pixman_image_destroy (pixman_image_t *image); -int +pixman_private int pixman_image_set_clip_region (pixman_image_t *image, pixman_region16_t *region); @@ -366,11 +376,11 @@ typedef enum { PIXMAN_FILTER_BILINEAR } pixman_filter_t; -void +pixman_private void pixman_image_set_component_alpha (pixman_image_t *image, int component_alpha); -int +pixman_private int pixman_image_set_transform (pixman_image_t *image, pixman_transform_t *transform); @@ -382,57 +392,57 @@ typedef enum { PIXMAN_REPEAT_REFLECT } pixman_repeat_t; -void +pixman_private void pixman_image_set_repeat (pixman_image_t *image, pixman_repeat_t repeat); -void +pixman_private void pixman_image_set_filter (pixman_image_t *image, pixman_filter_t filter); -int +pixman_private int pixman_image_get_width (pixman_image_t *image); -int +pixman_private int pixman_image_get_height (pixman_image_t *image); -int +pixman_private int pixman_image_get_stride (pixman_image_t *image); -int +pixman_private int pixman_image_get_depth (pixman_image_t *image); -pixman_format_t * +pixman_private pixman_format_t * pixman_image_get_format (pixman_image_t *image); -pixman_bits_t * +pixman_private pixman_bits_t * pixman_image_get_data (pixman_image_t *image); -pixman_image_t * +pixman_private pixman_image_t * pixman_image_create_linear_gradient (const pixman_linear_gradient_t *gradient, const pixman_gradient_stop_t *stops, int n_stops); -pixman_image_t * +pixman_private pixman_image_t * pixman_image_create_radial_gradient (const pixman_radial_gradient_t *gradient, const pixman_gradient_stop_t *stops, int n_stops); /* iccolor.c */ -void +pixman_private void pixman_color_to_pixel (const pixman_format_t *format, const pixman_color_t *color, pixman_bits_t *pixel); -void +pixman_private void pixman_pixel_to_color (const pixman_format_t *format, pixman_bits_t pixel, pixman_color_t *color); /* icrect.c */ -void +pixman_private void pixman_fill_rectangle (pixman_operator_t op, pixman_image_t *dst, const pixman_color_t *color, @@ -441,7 +451,7 @@ pixman_fill_rectangle (pixman_operator_t op, unsigned int width, unsigned int height); -void +pixman_private void pixman_fill_rectangles (pixman_operator_t op, pixman_image_t *dst, const pixman_color_t *color, @@ -450,7 +460,7 @@ pixman_fill_rectangles (pixman_operator_t op, /* ictrap.c */ -void +pixman_private void pixman_composite_trapezoids (pixman_operator_t op, pixman_image_t *src, pixman_image_t *dst, @@ -459,7 +469,7 @@ pixman_composite_trapezoids (pixman_operator_t op, const pixman_trapezoid_t *traps, int ntrap); -void +pixman_private void pixman_add_trapezoids (pixman_image_t *dst, int x_off, int y_off, @@ -468,7 +478,7 @@ pixman_add_trapezoids (pixman_image_t *dst, /* ictri.c */ -void +pixman_private void pixman_composite_triangles (pixman_operator_t op, pixman_image_t *src, pixman_image_t *dst, @@ -477,7 +487,7 @@ pixman_composite_triangles (pixman_operator_t op, const pixman_triangle_t *tris, int ntris); -void +pixman_private void pixman_composite_tri_strip (pixman_operator_t op, pixman_image_t *src, pixman_image_t *dst, @@ -486,7 +496,7 @@ pixman_composite_tri_strip (pixman_operator_t op, const pixman_point_fixed_t *points, int npoints); -void +pixman_private void pixman_composite_tri_fan (pixman_operator_t op, pixman_image_t *src, pixman_image_t *dst, @@ -497,7 +507,7 @@ pixman_composite_tri_fan (pixman_operator_t op, /* ic.c */ -void +pixman_private void pixman_composite (pixman_operator_t op, pixman_image_t *iSrc, pixman_image_t *iMask, diff --git a/gfx/cairo/libpixman/src/pixregion.c b/gfx/cairo/libpixman/src/pixregion.c index aa756abefc49..5112157caab3 100644 --- a/gfx/cairo/libpixman/src/pixregion.c +++ b/gfx/cairo/libpixman/src/pixregion.c @@ -50,7 +50,6 @@ SOFTWARE. #include #include "pixregionint.h" -#include "slim_internal.h" #if defined (__GNUC__) && !defined (NO_INLINES) #define INLINE __inline @@ -89,10 +88,6 @@ pixman_init (pixman_region16_t *region, pixman_box16_t *rect); static void pixman_uninit (pixman_region16_t *region); -slim_hidden_proto(pixman_region_create_simple) -slim_hidden_proto(pixman_region_copy) -slim_hidden_proto(pixman_region_union) - /* * The functions in this file implement the Region abstraction used extensively * throughout the X11 sample server. A Region is simply a set of disjoint @@ -327,7 +322,6 @@ pixman_region_create_simple (pixman_box16_t *extents) return region; } -slim_hidden_def(pixman_region_create_simple); /***************************************************************** * RegionInit(pReg, rect, size) @@ -452,7 +446,6 @@ pixman_region_copy(pixman_region16_t *dst, pixman_region16_t *src) dst->data->numRects * sizeof(pixman_box16_t)); return PIXMAN_REGION_STATUS_SUCCESS; } -slim_hidden_def(pixman_region_copy); /*====================================================================== * Generic Region Operator @@ -988,10 +981,9 @@ pixman_region_intersectO ( } pixman_region_status_t -pixman_region_intersect(newReg, reg1, reg2) - pixman_region16_t * newReg; /* destination Region */ - pixman_region16_t * reg1; - pixman_region16_t * reg2; /* source regions */ +pixman_region_intersect(pixman_region16_t * newReg, + pixman_region16_t * reg1, + pixman_region16_t * reg2) { good(reg1); good(reg2); @@ -1233,7 +1225,6 @@ pixman_region_union(pixman_region16_t *newReg, pixman_region16_t *reg1, pixman_r good(newReg); return PIXMAN_REGION_STATUS_SUCCESS; } -slim_hidden_def(pixman_region_union); /*====================================================================== * Batch Rectangle Union @@ -1257,9 +1248,8 @@ slim_hidden_def(pixman_region_union); * */ pixman_region_status_t -pixman_region_append(dstrgn, rgn) - pixman_region16_t * dstrgn; - pixman_region16_t * rgn; +pixman_region_append(pixman_region16_t * dstrgn, + pixman_region16_t * rgn) { int numRects, dnumRects, size; pixman_box16_t *new, *old; @@ -1442,9 +1432,8 @@ QuickSortRects( */ pixman_region_status_t -pixman_region_validate(badreg, pOverlap) - pixman_region16_t * badreg; - int *pOverlap; +pixman_region_validate(pixman_region16_t * badreg, + int *pOverlap) { /* Descriptor for regions under construction in Step 2. */ typedef struct { @@ -1858,10 +1847,9 @@ pixman_region_subtractO ( *----------------------------------------------------------------------- */ pixman_region_status_t -pixman_region_subtract(regD, regM, regS) - pixman_region16_t * regD; - pixman_region16_t * regM; - pixman_region16_t * regS; +pixman_region_subtract(pixman_region16_t * regD, + pixman_region16_t * regM, + pixman_region16_t * regS) { int overlap; /* result ignored */ @@ -1923,10 +1911,9 @@ pixman_region_subtract(regD, regM, regS) *----------------------------------------------------------------------- */ pixman_region_status_t -pixman_region_inverse(newReg, reg1, invRect) - pixman_region16_t * newReg; /* Destination region */ - pixman_region16_t * reg1; /* Region to invert */ - pixman_box16_t * invRect; /* Bounding box for inversion */ +pixman_region_inverse(pixman_region16_t * newReg, /* Destination region */ + pixman_region16_t * reg1, /* Region to invert */ + pixman_box16_t * invRect) /* Bounding box for inversion */ { pixman_region16_t invReg; /* Quick and dirty region made from the * bounding box */ @@ -1983,9 +1970,8 @@ pixman_region_inverse(newReg, reg1, invRect) */ int -pixman_region_contains_rectangle(region, prect) - pixman_region16_t * region; - pixman_box16_t * prect; +pixman_region_contains_rectangle(pixman_region16_t * region, + pixman_box16_t * prect) { int x; int y; @@ -2200,11 +2186,11 @@ pixman_region_reset(pixman_region16_t *region, pixman_box16_t *box) region->data = (pixman_region16_data_t *)NULL; } +/* box is "return" value */ int -pixman_region_contains_point(region, x, y, box) - pixman_region16_t * region; - int x, y; - pixman_box16_t * box; /* "return" value */ +pixman_region_contains_point(pixman_region16_t * region, + int x, int y, + pixman_box16_t * box) { pixman_box16_t *pbox, *pboxEnd; int numRects; @@ -2235,8 +2221,7 @@ pixman_region_contains_point(region, x, y, box) } int -pixman_region_not_empty(region) - pixman_region16_t * region; +pixman_region_not_empty(pixman_region16_t * region) { good(region); return(!PIXREGION_NIL(region)); @@ -2252,8 +2237,7 @@ pixman_region16_broken(pixman_region16_t * region) */ void -pixman_region_empty(region) - pixman_region16_t * region; +pixman_region_empty(pixman_region16_t * region) { good(region); freeData(region); @@ -2263,8 +2247,7 @@ pixman_region_empty(region) } pixman_box16_t * -pixman_region_extents(region) - pixman_region16_t * region; +pixman_region_extents(pixman_region16_t * region) { good(region); return(®ion->extents); diff --git a/gfx/cairo/libpixman/src/renderedge.h b/gfx/cairo/libpixman/src/renderedge.h index 522e5034e635..55561ea7fcae 100644 --- a/gfx/cairo/libpixman/src/renderedge.h +++ b/gfx/cairo/libpixman/src/renderedge.h @@ -128,16 +128,16 @@ typedef struct { } \ } -xFixed +pixman_private xFixed RenderSampleCeilY (xFixed y, int bpp); -xFixed +pixman_private xFixed RenderSampleFloorY (xFixed y, int bpp); -void +pixman_private void RenderEdgeStep (RenderEdge *e, int n); -void +pixman_private void RenderEdgeInit (RenderEdge *e, int bpp, xFixed y_start, @@ -146,7 +146,7 @@ RenderEdgeInit (RenderEdge *e, xFixed x_bot, xFixed y_bot); -void +pixman_private void RenderLineFixedEdgeInit (RenderEdge *e, int bpp, xFixed y, diff --git a/gfx/cairo/libpixman/src/slim_internal.h b/gfx/cairo/libpixman/src/slim_internal.h index 742059c699ad..3d1e9a64f76a 100644 --- a/gfx/cairo/libpixman/src/slim_internal.h +++ b/gfx/cairo/libpixman/src/slim_internal.h @@ -78,8 +78,9 @@ level. */ #if __GNUC__ >= 3 && defined(__ELF__) -# define slim_hidden_proto(name) slim_hidden_proto1(name, INT_##name) -# define slim_hidden_def(name) slim_hidden_def1(name, INT_##name) +# define slim_hidden_proto(name) slim_hidden_proto1(name, slim_hidden_int_name(name)) +# define slim_hidden_def(name) slim_hidden_def1(name, slim_hidden_int_name(name)) +# define slim_hidden_int_name(name) INT_##name # define slim_hidden_proto1(name, internal) \ extern __typeof (name) name \ __asm__ (slim_hidden_asmname (internal)) \ diff --git a/gfx/cairo/push-pop-group.patch b/gfx/cairo/push-pop-group.patch deleted file mode 100644 index 8ce42ec68f1b..000000000000 --- a/gfx/cairo/push-pop-group.patch +++ /dev/null @@ -1,734 +0,0 @@ -Index: src/cairo-gstate-private.h -=================================================================== ---- src/cairo-gstate-private.h.orig 2006-02-09 17:51:53.843750000 -0800 -+++ src/cairo-gstate-private.h 2006-02-09 18:03:23.546875000 -0800 -@@ -55,7 +55,9 @@ - - cairo_clip_t clip; - -- cairo_surface_t *target; -+ cairo_surface_t *target; /* The target to which all rendering is directed */ -+ cairo_surface_t *parent_target; /* The previous target which was receiving rendering */ -+ cairo_surface_t *original_target; /* The original target the initial gstate was created with */ - - cairo_matrix_t ctm; - cairo_matrix_t ctm_inverse; -Index: src/cairo-gstate.c -=================================================================== ---- src/cairo-gstate.c.orig 2006-02-09 18:01:01.859375000 -0800 -+++ src/cairo-gstate.c 2006-02-09 18:03:23.562500000 -0800 -@@ -119,6 +119,8 @@ - _cairo_clip_init (&gstate->clip, target); - - gstate->target = cairo_surface_reference (target); -+ gstate->parent_target = NULL; -+ gstate->original_target = cairo_surface_reference (target); - - _cairo_gstate_identity_matrix (gstate); - gstate->source_ctm_inverse = gstate->ctm_inverse; -@@ -166,6 +168,9 @@ - _cairo_clip_init_copy (&gstate->clip, &other->clip); - - gstate->target = cairo_surface_reference (other->target); -+ /* parent_target is always set to NULL; it's only ever set by redirect_target */ -+ gstate->parent_target = NULL; -+ gstate->original_target = cairo_surface_reference (other->original_target); - - gstate->ctm = other->ctm; - gstate->ctm_inverse = other->ctm_inverse; -@@ -194,6 +199,12 @@ - cairo_surface_destroy (gstate->target); - gstate->target = NULL; - -+ cairo_surface_destroy (gstate->parent_target); -+ gstate->parent_target = NULL; -+ -+ cairo_surface_destroy (gstate->original_target); -+ gstate->target = NULL; -+ - cairo_pattern_destroy (gstate->source); - gstate->source = NULL; - } -@@ -248,94 +259,153 @@ - gstate->target = cairo_surface_reference (target); - } - --/* Push rendering off to an off-screen group. */ --/* XXX: Rethinking this API --cairo_status_t --_cairo_gstate_begin_group (cairo_gstate_t *gstate) -+static cairo_status_t -+_cairo_gstate_recursive_apply_clip_path (cairo_gstate_t *gstate, -+ cairo_clip_path_t *cpath) - { -- Pixmap pix; -- unsigned int width, height; -- -- gstate->parent_surface = gstate->target; -- -- width = _cairo_surface_get_width (gstate->target); -- height = _cairo_surface_get_height (gstate->target); -+ cairo_status_t status; - -- pix = XCreatePixmap (gstate->dpy, -- _cairo_surface_get_drawable (gstate->target), -- width, height, -- _cairo_surface_get_depth (gstate->target)); -- if (pix == 0) -- return CAIRO_STATUS_NO_MEMORY; -+ if (cpath == NULL) -+ return CAIRO_STATUS_SUCCESS; - -- gstate->target = cairo_surface_create (gstate->dpy); -- if (gstate->target->status) -- return gstate->target->status; -- -- _cairo_surface_set_drawableWH (gstate->target, pix, width, height); -- -- status = _cairo_surface_fill_rectangle (gstate->target, -- CAIRO_OPERATOR_CLEAR, -- CAIRO_COLOR_TRANSPARENT, -- 0, 0, -- _cairo_surface_get_width (gstate->target), -- _cairo_surface_get_height (gstate->target)); -- if (status) -- return status; -+ status = _cairo_gstate_recursive_apply_clip_path (gstate, cpath->prev); -+ if (status) -+ return status; - -- return CAIRO_STATUS_SUCCESS; -+ return _cairo_clip_clip (&gstate->clip, -+ &cpath->path, -+ cpath->fill_rule, -+ cpath->tolerance, -+ cpath->antialias, -+ gstate->target); - } --*/ - --/* Complete the current offscreen group, composing its contents onto the parent surface. */ --/* XXX: Rethinking this API --cairo_status_t --_cairo_gstate_end_group (cairo_gstate_t *gstate) -+/** -+ * _cairo_gstate_redirect_target: -+ * @gstate: a #cairo_gstate_t -+ * @child: the new child target -+ * -+ * Redirect @gstate rendering to a "child" target. The original -+ * "parent" target with which the gstate was created will not be -+ * affected. See _cairo_gstate_get_target(). -+ * -+ * Unless the redirected target has the same device offsets as the -+ * original #cairo_t target, the clip will be INVALID after this call, -+ * and the caller should either recreate or reset the clip. -+ **/ -+void -+_cairo_gstate_redirect_target (cairo_gstate_t *gstate, cairo_surface_t *child) - { -- Pixmap pix; -- cairo_color_t mask_color; -- cairo_surface_t mask; -- -- if (gstate->parent_surface == NULL) -- return CAIRO_STATUS_INVALID_POP_GROUP; -- -- _cairo_surface_init (&mask, gstate->dpy); -- _cairo_color_init (&mask_color); -- -- _cairo_surface_set_solid_color (&mask, &mask_color); -- -- * 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. * -- _cairo_surface_composite (gstate->op, -- gstate->target, -- mask, -- gstate->parent_surface, -- 0, 0, -- 0, 0, -- 0, 0, -- _cairo_surface_get_width (gstate->target), -- _cairo_surface_get_height (gstate->target)); -- -- _cairo_surface_fini (&mask); -- -- pix = _cairo_surface_get_drawable (gstate->target); -- XFreePixmap (gstate->dpy, pix); -- -- cairo_surface_destroy (gstate->target); -- gstate->target = gstate->parent_surface; -- gstate->parent_surface = NULL; -+ /* If this gstate is already redirected, this is an error; we need a -+ * new gstate to be able to redirect */ -+ assert (gstate->parent_target == NULL); -+ -+ /* Set up our new parent_target based on our current target; -+ * gstate->parent_target will take the ref that is held by gstate->target -+ */ -+ cairo_surface_destroy (gstate->parent_target); -+ gstate->parent_target = gstate->target; -+ -+ /* Now set up our new target; we overwrite gstate->target directly, -+ * since its ref is now owned by gstate->parent_target */ -+ gstate->target = cairo_surface_reference (child); -+ -+ /* Check that the new surface's clip mode is compatible */ -+ if (gstate->clip.mode != _cairo_surface_get_clip_mode (child)) { -+ /* clip is not compatible; try to recreate it */ -+ /* XXX - saving the clip path always might be useful here, -+ * so that we could recover non-CLIP_MODE_PATH clips */ -+ if (gstate->clip.mode == CAIRO_CLIP_MODE_PATH) { -+ cairo_clip_t saved_clip = gstate->clip; -+ -+ _cairo_clip_init (&gstate->clip, child); -+ -+ /* unwind the path and re-apply */ -+ _cairo_gstate_recursive_apply_clip_path (gstate, saved_clip.path); -+ -+ _cairo_clip_fini (&saved_clip); -+ } else { -+ /* uh, not sure what to do here.. */ -+ _cairo_clip_fini (&gstate->clip); -+ _cairo_clip_init (&gstate->clip, child); -+ } -+ } else { -+ /* clip is compatible; allocate a new serial for the new surface. */ -+ if (gstate->clip.serial) -+ gstate->clip.serial = _cairo_surface_allocate_clip_serial (child); -+ } -+} - -- return CAIRO_STATUS_SUCCESS; -+/** -+ * _cairo_gstate_is_redirected -+ * @gstate: a #cairo_gstate_t -+ * -+ * Return value: TRUE if the gstate is redirected to a traget -+ * different than the original, FALSE otherwise. -+ **/ -+cairo_bool_t -+_cairo_gstate_is_redirected (cairo_gstate_t *gstate) -+{ -+ return (gstate->target != gstate->original_target); - } --*/ - -+/** -+ * _cairo_gstate_get_target: -+ * @gstate: a #cairo_gstate_t -+ * -+ * Return the current drawing target; if drawing is not redirected, -+ * this will be the same as _cairo_gstate_get_original_target(). -+ * -+ * Return value: the current target surface -+ **/ - cairo_surface_t * - _cairo_gstate_get_target (cairo_gstate_t *gstate) - { - return gstate->target; - } - -+/** -+ * _cairo_gstate_get_parent_target: -+ * @gstate: a #cairo_gstate_t -+ * -+ * Return the parent surface of the current drawing target surface; -+ * if this particular gstate isn't a redirect gstate, this will return NULL. -+ **/ -+cairo_surface_t * -+_cairo_gstate_get_parent_target (cairo_gstate_t *gstate) -+{ -+ return gstate->parent_target; -+} -+ -+/** -+ * _cairo_gstate_get_original_target: -+ * @gstate: a #cairo_gstate_t -+ * -+ * Return the original target with which @gstate was created. This -+ * function always returns the original target independent of any -+ * child target that may have been set with -+ * _cairo_gstate_redirect_target. -+ * -+ * Return value: the original target surface -+ **/ -+cairo_surface_t * -+_cairo_gstate_get_original_target (cairo_gstate_t *gstate) -+{ -+ return gstate->original_target; -+} -+ -+/** -+ * _cairo_gstate_get_clip: -+ * @gstate: a #cairo_gstate_t -+ * -+ * Return value: a pointer to the gstate's cairo_clip_t structure. -+ */ -+cairo_clip_t * -+_cairo_gstate_get_clip (cairo_gstate_t *gstate) -+{ -+ return &gstate->clip; -+} -+ - cairo_status_t - _cairo_gstate_set_source (cairo_gstate_t *gstate, - cairo_pattern_t *source) -Index: src/cairo.c -=================================================================== ---- src/cairo.c.orig 2006-02-09 17:51:53.846750000 -0800 -+++ src/cairo.c 2006-02-09 18:56:40.375000000 -0800 -@@ -347,33 +347,133 @@ - } - slim_hidden_def(moz_cairo_set_target); - --/* XXX: I want to rethink this API -+/** -+ * cairo_push_group: -+ * @cr: a cairo context -+ * -+ * Pushes a CAIRO_CONTENT_COLOR_ALPHA temporary surface onto -+ * the rendering stack, redirecting all rendering into it. -+ * See cairo_push_group_with_content(). -+ */ -+ - void - cairo_push_group (cairo_t *cr) - { -- if (cr->status) -- return; -+ cairo_push_group_with_content (cr, CAIRO_CONTENT_COLOR_ALPHA); -+} -+slim_hidden_def(cairo_push_group); - -- cr->status = cairoPush (cr); -- if (cr->status) -- return; -+/** -+ * cairo_push_group_with_content: -+ * @cr: a cairo context -+ * @content: a %cairo_content_t indicating the type of group that -+ * will be created -+ * -+ * Pushes a temporary surface onto the rendering stack, redirecting -+ * all rendering into it. The surface dimensions are the size of -+ * the current clipping bounding box. Initially, this surface -+ * is painted with CAIRO_OPERATOR_CLEAR. -+ * -+ * cairo_push_group() calls cairo_save() so that any changes to the -+ * graphics state will not be visible after cairo_pop_group() or -+ * cairo_pop_group_with_alpha(). See cairo_pop_group() and -+ * cairo_pop_group_with_alpha(). -+ */ - -- cr->status = _cairo_gstate_begin_group (cr->gstate); -+void -+cairo_push_group_with_content (cairo_t *cr, cairo_content_t content) -+{ -+ cairo_status_t status; -+ cairo_rectangle_t extents; -+ cairo_surface_t *group_surface = NULL; -+ -+ /* Get the extents that we'll use in creating our new group surface */ -+ _cairo_surface_get_extents (_cairo_gstate_get_target (cr->gstate), &extents); -+ status = _cairo_clip_intersect_to_rectangle (_cairo_gstate_get_clip (cr->gstate), &extents); -+ if (status != CAIRO_STATUS_SUCCESS) -+ goto bail; -+ -+ group_surface = cairo_surface_create_similar (_cairo_gstate_get_target (cr->gstate), -+ content, -+ extents.width, -+ extents.height); -+ status = cairo_surface_status (group_surface); -+ if (status) -+ goto bail; -+ -+ /* Set device offsets on the new surface so that logically it appears at -+ * the same location on the parent surface. */ -+ cairo_surface_set_device_offset (group_surface, -extents.x, -extents.y); -+ -+ /* create a new gstate for the redirect */ -+ cairo_save (cr); -+ if (cr->status) -+ goto bail; -+ -+ _cairo_gstate_redirect_target (cr->gstate, group_surface); -+ -+bail: -+ cairo_surface_destroy (group_surface); -+ if (status) -+ _cairo_set_error (cr, status); - } -+slim_hidden_def(cairo_push_group_with_content); - --void -+cairo_pattern_t * - cairo_pop_group (cairo_t *cr) - { -- if (cr->status) -- return; -+ cairo_surface_t *group_surface, *parent_target; -+ cairo_pattern_t *group_pattern = NULL; -+ cairo_matrix_t group_matrix; -+ -+ /* Grab the active surfaces */ -+ group_surface = _cairo_gstate_get_target (cr->gstate); -+ parent_target = _cairo_gstate_get_parent_target (cr->gstate); -+ -+ /* Verify that we are at the right nesting level */ -+ if (parent_target == NULL) { -+ _cairo_set_error (cr, CAIRO_STATUS_INVALID_POP_GROUP); -+ return NULL; -+ } -+ -+ /* We need to save group_surface before we restore; we don't need -+ * to reference parent_target and original_target, since the -+ * gstate will still hold refs to them once we restore. */ -+ cairo_surface_reference (group_surface); -+ -+ cairo_restore (cr); - -- cr->status = _cairo_gstate_end_group (cr->gstate); - if (cr->status) -- return; -+ goto done; -+ -+ group_pattern = cairo_pattern_create_for_surface (group_surface); -+ if (!group_pattern) { -+ cr->status = CAIRO_STATUS_NO_MEMORY; -+ goto done; -+ } -+ -+ _cairo_gstate_get_matrix (cr->gstate, &group_matrix); -+ cairo_pattern_set_matrix (group_pattern, &group_matrix); -+done: -+ cairo_surface_destroy (group_surface); - -- cr->status = cairoPop (cr); -+ return group_pattern; - } --*/ -+slim_hidden_def(cairo_pop_group); -+ -+void -+cairo_pop_group_to_source (cairo_t *cr) -+{ -+ cairo_pattern_t *group_pattern; -+ -+ group_pattern = cairo_pop_group (cr); -+ if (!group_pattern) -+ return; -+ -+ cairo_set_source (cr, group_pattern); -+ cairo_pattern_destroy (group_pattern); -+} -+slim_hidden_def(cairo_pop_group_to_source); - - /** - * cairo_set_operator: -@@ -2421,6 +2521,30 @@ - if (cr->status) - return (cairo_surface_t*) &_cairo_surface_nil; - -+ return _cairo_gstate_get_original_target (cr->gstate); -+} -+ -+/** -+ * cairo_get_group_target: -+ * @cr: a cairo context -+ * -+ * Gets the target surface for the current transparency group -+ * started by the last cairo_push_group() call on the cairo -+ * context. -+ * -+ * This function may return NULL if there is no transparency -+ * group on the target. -+ * -+ * Return value: the target group surface, or NULL if none. This -+ * object is owned by cairo. To keep a reference to it, you must call -+ * cairo_surface_reference(). -+ **/ -+cairo_surface_t * -+cairo_get_group_target (cairo_t *cr) -+{ -+ if (cr->status) -+ return (cairo_surface_t*) &_cairo_surface_nil; -+ - return _cairo_gstate_get_target (cr->gstate); - } - -Index: src/cairo.h -=================================================================== ---- src/cairo.h.orig 2006-02-09 17:51:53.847750000 -0800 -+++ src/cairo.h 2006-02-09 18:04:02.390625000 -0800 -@@ -197,6 +197,26 @@ - } cairo_status_t; - - /** -+ * cairo_content_t -+ * @CAIRO_CONTENT_COLOR: The surface will hold color content only. -+ * @CAIRO_CONTENT_ALPHA: The surface will hold alpha content only. -+ * @CAIRO_CONTENT_COLOR_ALPHA: The surface will hold color and alpha content. -+ * -+ * @cairo_content_t is used to describe the content that a surface will -+ * contain, whether color information, alpha information (translucence -+ * vs. opacity), or both. -+ * -+ * Note: The large values here are designed to keep cairo_content_t -+ * values distinct from cairo_format_t values so that the -+ * implementation can detect the error if users confuse the two types. -+ */ -+typedef enum _cairo_content { -+ CAIRO_CONTENT_COLOR = 0x1000, -+ CAIRO_CONTENT_ALPHA = 0x2000, -+ CAIRO_CONTENT_COLOR_ALPHA = 0x3000 -+} cairo_content_t; -+ -+/** - * cairo_write_func_t: - * @closure: the output closure - * @data: the buffer containing the data to write -@@ -255,13 +275,17 @@ - cairo_public void - moz_cairo_set_target (cairo_t *cr, cairo_surface_t *target); - --/* XXX: I want to rethink this API - cairo_public void - cairo_push_group (cairo_t *cr); - - cairo_public void -+cairo_push_group_with_content (cairo_t *cr, cairo_content_t content); -+ -+cairo_public cairo_pattern_t * - cairo_pop_group (cairo_t *cr); --*/ -+ -+cairo_public void -+cairo_pop_group_to_source (cairo_t *cr); - - /* Modify state */ - -@@ -996,6 +1020,9 @@ - cairo_public cairo_surface_t * - cairo_get_target (cairo_t *cr); - -+cairo_public cairo_surface_t * -+cairo_get_group_target (cairo_t *cr); -+ - typedef enum _cairo_path_data_type { - CAIRO_PATH_MOVE_TO, - CAIRO_PATH_LINE_TO, -@@ -1121,26 +1148,6 @@ - - /* Surface manipulation */ - --/** -- * cairo_content_t -- * @CAIRO_CONTENT_COLOR: The surface will hold color content only. -- * @CAIRO_CONTENT_ALPHA: The surface will hold alpha content only. -- * @CAIRO_CONTENT_COLOR_ALPHA: The surface will hold color and alpha content. -- * -- * @cairo_content_t is used to describe the content that a surface will -- * contain, whether color information, alpha information (translucence -- * vs. opacity), or both. -- * -- * Note: The large values here are designed to keep cairo_content_t -- * values distinct from cairo_format_t values so that the -- * implementation can detect the error if users confuse the two types. -- */ --typedef enum _cairo_content { -- CAIRO_CONTENT_COLOR = 0x1000, -- CAIRO_CONTENT_ALPHA = 0x2000, -- CAIRO_CONTENT_COLOR_ALPHA = 0x3000 --} cairo_content_t; -- - cairo_public cairo_surface_t * - cairo_surface_create_similar (cairo_surface_t *other, - cairo_content_t content, -Index: src/cairoint.h -=================================================================== ---- src/cairoint.h.orig 2006-02-09 18:01:01.890625000 -0800 -+++ src/cairoint.h 2006-02-09 18:51:23.265625000 -0800 -@@ -1077,9 +1077,24 @@ - cairo_private void - _moz_cairo_gstate_set_target (cairo_gstate_t *gstate, cairo_surface_t *target); - -+cairo_private cairo_bool_t -+_cairo_gstate_is_redirected (cairo_gstate_t *gstate); -+ -+cairo_private void -+_cairo_gstate_redirect_target (cairo_gstate_t *gstate, cairo_surface_t *child); -+ - cairo_private cairo_surface_t * - _cairo_gstate_get_target (cairo_gstate_t *gstate); - -+cairo_private cairo_surface_t * -+_cairo_gstate_get_parent_target (cairo_gstate_t *gstate); -+ -+cairo_private cairo_surface_t * -+_cairo_gstate_get_original_target (cairo_gstate_t *gstate); -+ -+cairo_private cairo_clip_t * -+_cairo_gstate_get_clip (cairo_gstate_t *gstate); -+ - cairo_private cairo_status_t - _cairo_gstate_set_source (cairo_gstate_t *gstate, cairo_pattern_t *source); - -@@ -2189,6 +2204,10 @@ - slim_hidden_proto(cairo_save) - slim_hidden_proto(cairo_stroke_preserve) - slim_hidden_proto(cairo_surface_destroy) -+slim_hidden_proto(cairo_push_group) -+slim_hidden_proto(cairo_push_group_with_content) -+slim_hidden_proto(cairo_pop_group) -+slim_hidden_proto(cairo_pop_group_to_source) - slim_hidden_proto(moz_cairo_set_target) - - CAIRO_END_DECLS -Index: test/Makefile.am -=================================================================== ---- test/Makefile.am.orig 2006-02-09 17:51:53.912750000 -0800 -+++ test/Makefile.am 2006-02-09 18:03:23.671875000 -0800 -@@ -59,7 +59,8 @@ - unantialiased-shapes \ - unbounded-operator \ - user-data \ --rel-path -+rel-path \ -+push-group - - if HAVE_PTHREAD - TESTS += pthread-show-text -@@ -346,6 +347,7 @@ - user_data_LDADD = $(LDADDS) - rel_path_LDADD = $(LDADDS) - xlib_surface_LDADD = $(LDADDS) -+push_group_LDADD = $(LDADDS) - - noinst_PROGRAMS = imagediff png-flatten - imagediff_LDADD = $(LDADDS) -Index: test/push-group.c -=================================================================== ---- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ test/push-group.c 2006-02-09 18:03:23.671875000 -0800 -@@ -0,0 +1,119 @@ -+/* -+ * Copyright © 2005 Mozilla Corporation -+ * -+ * 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 -+ * Mozilla Corporation not be used in advertising or publicity pertaining to -+ * distribution of the software without specific, written prior -+ * permission. Mozilla Corporation makes no representations about the -+ * suitability of this software for any purpose. It is provided "as -+ * is" without express or implied warranty. -+ * -+ * MOZILLA CORPORATION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS -+ * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND -+ * FITNESS, IN NO EVENT SHALL MOZILLA CORPORATION 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: Vladimir Vukicevic -+ */ -+ -+ -+#include "cairo-test.h" -+ -+ -+#define UNIT_SIZE 100 -+#define PAD 5 -+#define INNER_PAD 10 -+ -+#define WIDTH (UNIT_SIZE + PAD) + PAD -+#define HEIGHT (UNIT_SIZE + PAD) + PAD -+ -+cairo_test_t test = { -+ "push-group", -+ "Verify that cairo_push_group works.", -+ WIDTH, HEIGHT -+}; -+ -+static cairo_test_status_t -+draw (cairo_t *cr, int width, int height) -+{ -+ cairo_pattern_t *gradient; -+ int i, j; -+ -+ gradient = cairo_pattern_create_linear (UNIT_SIZE - (INNER_PAD*2), 0, -+ UNIT_SIZE - (INNER_PAD*2), UNIT_SIZE - (INNER_PAD*2)); -+ cairo_pattern_add_color_stop_rgba (gradient, 0.0, 0.3, 0.3, 0.3, 1.0); -+ cairo_pattern_add_color_stop_rgba (gradient, 1.0, 1.0, 1.0, 1.0, 1.0); -+ -+ for (j = 0; j < 1; j++) { -+ for (i = 0; i < 1; i++) { -+ double x = (i * UNIT_SIZE) + (i + 1) * PAD; -+ double y = (j * UNIT_SIZE) + (j + 1) * PAD; -+ -+ cairo_save (cr); -+ -+ cairo_translate (cr, x, y); -+ -+ /* draw a gradient background */ -+ cairo_save (cr); -+ cairo_translate (cr, INNER_PAD, INNER_PAD); -+ cairo_new_path (cr); -+ cairo_rectangle (cr, 0, 0, -+ UNIT_SIZE - (INNER_PAD*2), UNIT_SIZE - (INNER_PAD*2)); -+ cairo_set_source (cr, gradient); -+ cairo_fill (cr); -+ cairo_restore (cr); -+ -+ /* clip to the unit size */ -+ cairo_rectangle (cr, 0, 0, -+ UNIT_SIZE, UNIT_SIZE); -+ cairo_clip (cr); -+ -+ cairo_rectangle (cr, 0, 0, -+ UNIT_SIZE, UNIT_SIZE); -+ cairo_set_source_rgba (cr, 0, 0, 0, 1); -+ cairo_set_line_width (cr, 2); -+ cairo_stroke (cr); -+ -+ /* start a group */ -+ cairo_push_group (cr); -+ -+ /* draw diamond */ -+ cairo_move_to (cr, UNIT_SIZE / 2, 0); -+ cairo_line_to (cr, UNIT_SIZE , UNIT_SIZE / 2); -+ cairo_line_to (cr, UNIT_SIZE / 2, UNIT_SIZE); -+ cairo_line_to (cr, 0 , UNIT_SIZE / 2); -+ cairo_close_path (cr); -+ cairo_set_source_rgba (cr, 0, 0, 1, 1); -+ cairo_fill (cr); -+ -+ /* draw circle */ -+ cairo_arc (cr, -+ UNIT_SIZE / 2, UNIT_SIZE / 2, -+ UNIT_SIZE / 3.5, -+ 0, M_PI * 2); -+ cairo_set_source_rgba (cr, 1, 0, 0, 1); -+ cairo_fill (cr); -+ -+ /* end group and paint */ -+ cairo_pop_group_to_source (cr); -+ cairo_paint_with_alpha (cr, 0.5); -+ -+ cairo_restore (cr); -+ } -+ } -+ -+ return CAIRO_TEST_SUCCESS; -+} -+ -+int -+main (void) -+{ -+ return cairo_test (&test, draw); -+} diff --git a/gfx/thebes/public/gfxPattern.h b/gfx/thebes/public/gfxPattern.h index 947f54844fbf..ea6d82e5ba79 100644 --- a/gfx/thebes/public/gfxPattern.h +++ b/gfx/thebes/public/gfxPattern.h @@ -121,11 +121,11 @@ public: /* returns TRUE if it succeeded */ PRBool GetSolidColor(gfxRGBA& aColor) { - return cairo_pattern_get_solid_color(mPattern, - &aColor.r, - &aColor.g, - &aColor.b, - &aColor.a) == CAIRO_STATUS_SUCCESS; + return cairo_pattern_get_rgba(mPattern, + &aColor.r, + &aColor.g, + &aColor.b, + &aColor.a) == CAIRO_STATUS_SUCCESS; } protected: diff --git a/gfx/thebes/src/cairo-xlib-utils.c b/gfx/thebes/src/cairo-xlib-utils.c index 6bf6c4dd51a7..3625043efe84 100644 --- a/gfx/thebes/src/cairo-xlib-utils.c +++ b/gfx/thebes/src/cairo-xlib-utils.c @@ -114,7 +114,6 @@ _intersect_interval (double a_begin, double a_end, double b_begin, double b_end, return *out_begin < *out_end; } -#define MAX_STATIC_CLIP_RECTANGLES 50 static cairo_bool_t _get_rectangular_clip (cairo_t *cr, int bounds_x, int bounds_y, @@ -123,24 +122,31 @@ _get_rectangular_clip (cairo_t *cr, XRectangle *rectangles, int max_rectangles, int *num_rectangles) { - cairo_clip_rect_t clips[MAX_STATIC_CLIP_RECTANGLES]; - int count; + cairo_rectangle_list_t *cliplist; + cairo_rectangle_t *clips; int i; double b_x = bounds_x; double b_y = bounds_y; double b_x_most = bounds_x + bounds_width; double b_y_most = bounds_y + bounds_height; int rect_count = 0; - - if (!cairo_has_clip (cr)) { - *need_clip = False; - return True; + cairo_bool_t retval = True; + + cliplist = cairo_copy_clip_rectangles (cr); + if (cliplist->status != CAIRO_STATUS_SUCCESS) { + retval = False; + goto FINISH; } - if (!cairo_extract_clip_rectangles (cr, MAX_STATIC_CLIP_RECTANGLES, clips, &count)) - return False; + if (cliplist->num_rectangles == 0) { + *num_rectangles = 0; + *need_clip = True; + goto FINISH; + } - for (i = 0; i < count; ++i) { + clips = cliplist->rectangles; + + for (i = 0; i < cliplist->num_rectangles; ++i) { double intersect_x, intersect_y, intersect_x_most, intersect_y_most; /* the clip is always in surface backend coordinates (i.e. native backend coords) */ @@ -148,7 +154,7 @@ _get_rectangular_clip (cairo_t *cr, b_y >= clips[i].y && b_y_most <= clips[i].y + clips[i].height) { /* the bounds are entirely inside the clip region so we don't need to clip. */ *need_clip = False; - return True; + goto FINISH; } if (_intersect_interval (b_x, b_x_most, clips[i].x, clips[i].x + clips[i].width, @@ -157,14 +163,19 @@ _get_rectangular_clip (cairo_t *cr, &intersect_y, &intersect_y_most)) { XRectangle *rect = &rectangles[rect_count]; - if (rect_count >= max_rectangles) - return False; + if (rect_count >= max_rectangles) { + retval = False; + goto FINISH; + } if (!_convert_coord_to_short (intersect_x, &rect->x) || !_convert_coord_to_short (intersect_y, &rect->y) || !_convert_coord_to_unsigned_short (intersect_x_most - intersect_x, &rect->width) || !_convert_coord_to_unsigned_short (intersect_y_most - intersect_y, &rect->height)) - return False; + { + retval = False; + goto FINISH; + } ++rect_count; } @@ -172,9 +183,15 @@ _get_rectangular_clip (cairo_t *cr, *need_clip = True; *num_rectangles = rect_count; - return True; + +FINISH: + cairo_rectangle_list_destroy (cliplist); + + return retval; } +#define MAX_STATIC_CLIP_RECTANGLES 50 + /** * Try the direct path. * @param status the status returned by the callback, if we took the direct path diff --git a/gfx/thebes/src/gfxContext.cpp b/gfx/thebes/src/gfxContext.cpp index ba271415a504..abb265f7fa11 100644 --- a/gfx/thebes/src/gfxContext.cpp +++ b/gfx/thebes/src/gfxContext.cpp @@ -569,11 +569,11 @@ gfxContext::SetColor(const gfxRGBA& c) PRBool gfxContext::GetColor(gfxRGBA& c) { - return cairo_pattern_get_solid_color(cairo_get_source(mCairo), - &c.r, - &c.g, - &c.b, - &c.a) == CAIRO_STATUS_SUCCESS; + return cairo_pattern_get_rgba(cairo_get_source(mCairo), + &c.r, + &c.g, + &c.b, + &c.a) == CAIRO_STATUS_SUCCESS; } void