diff --git a/gfx/cairo/README b/gfx/cairo/README index df9d443a6c8..3e2989ddf3e 100644 --- a/gfx/cairo/README +++ b/gfx/cairo/README @@ -7,20 +7,10 @@ http://www.cairographics.org/. VERSIONS: - cairo (1.4.2) + cairo (1.3.12 tagged snapshot) glitz 0.5.2 (cvs - 2006-01-10) ***** NOTE FOR VISUAL C++ 6.0 ***** VC6 is not supported. Please upgrade to VC8. -==== Patches ==== - -All patches in the cairo tree are surrounded by "MOZILLA_CAIRO_NOT_DEFINED" (which should NOT be defined). - -Some specific things: - -max-font-size.patch: Clamp freetype font size to 1000 to avoid overflow issues - -fbcompose-bandaid.patch: Disable "optimized" code in non-MMX case due to bugs - diff --git a/gfx/cairo/cairo/src/Makefile.in b/gfx/cairo/cairo/src/Makefile.in index 83a56c92962..c128e377a9e 100644 --- a/gfx/cairo/cairo/src/Makefile.in +++ b/gfx/cairo/cairo/src/Makefile.in @@ -129,11 +129,6 @@ endif ifneq (,$(filter mac cocoa,$(MOZ_WIDGET_TOOLKIT))) CSRCS += cairo-quartz-surface.c cairo-atsui-font.c EXPORTS += cairo-quartz.h cairo-atsui.h - -ifdef MOZ_ENABLE_CAIRO_GFX -CSRCS += cairo-nquartz-surface.c -EXPORTS += cairo-nquartz.h -endif endif ifeq ($(MOZ_WIDGET_TOOLKIT),beos) diff --git a/gfx/cairo/cairo/src/cairo-atsui-font.c b/gfx/cairo/cairo/src/cairo-atsui-font.c index a26e76ffa1c..e8d57105c74 100644 --- a/gfx/cairo/cairo/src/cairo-atsui-font.c +++ b/gfx/cairo/cairo/src/cairo-atsui-font.c @@ -82,9 +82,6 @@ struct _cairo_atsui_font { ATSUStyle style; ATSUStyle unscaled_style; ATSUFontID fontID; - - Fixed size; - CGAffineTransform font_matrix; }; struct _cairo_atsui_font_face { @@ -149,6 +146,47 @@ cairo_atsui_font_face_create_for_atsu_font_id (ATSUFontID font_id) return &font_face->base; } +static CGContextRef +CGBitmapContextCreateWithCairoImageSurface (const cairo_image_surface_t * surface) +{ + CGContextRef contextRef; + CGColorSpaceRef colorSpace; + int bits_per_comp, alpha; + + /* Create a CGBitmapContext for the dest surface for drawing into */ + if (surface->depth == 1) { + colorSpace = CGColorSpaceCreateDeviceGray (); + bits_per_comp = 1; + alpha = kCGImageAlphaNone; + } else if (surface->depth == 8) { + colorSpace = CGColorSpaceCreateDeviceGray (); + bits_per_comp = 8; + alpha = kCGImageAlphaNone; + } else if (surface->depth == 24) { + colorSpace = CGColorSpaceCreateDeviceRGB (); + bits_per_comp = 8; + alpha = kCGImageAlphaNoneSkipFirst | CG_BITMAP_BYTE_ORDER_FLAG; + } else if (surface->depth == 32) { + colorSpace = CGColorSpaceCreateDeviceRGB (); + bits_per_comp = 8; + alpha = kCGImageAlphaPremultipliedFirst | CG_BITMAP_BYTE_ORDER_FLAG; + } else { + /* not reached */ + return NULL; + } + + contextRef = CGBitmapContextCreate (surface->data, + surface->width, + surface->height, + bits_per_comp, + surface->stride, + colorSpace, + alpha); + CGColorSpaceRelease (colorSpace); + + return contextRef; +} + static CGAffineTransform CGAffineTransformMakeWithCairoFontScale(const cairo_matrix_t *scale) { @@ -157,19 +195,29 @@ CGAffineTransformMakeWithCairoFontScale(const cairo_matrix_t *scale) 0, 0); } +static CGAffineTransform +CGAffineTransformMakeWithCairoScaleFactors(const cairo_matrix_t *scale) +{ + double xscale = 1.0; + double yscale = 1.0; + _cairo_matrix_compute_scale_factors(scale, &xscale, &yscale, 1); + return CGAffineTransformMake(xscale, 0, + 0, yscale, + 0, 0); +} + static ATSUStyle -CreateSizedCopyOfStyle(ATSUStyle inStyle, - const Fixed *theSize, - const CGAffineTransform *theTransform) +CreateSizedCopyOfStyle(ATSUStyle inStyle, const cairo_matrix_t *scale) { ATSUStyle style; OSStatus err; - const ATSUAttributeTag theFontStyleTags[] = { kATSUSizeTag, - kATSUFontMatrixTag }; - const ByteCount theFontStyleSizes[] = { sizeof(Fixed), - sizeof(CGAffineTransform) }; - ATSUAttributeValuePtr theFontStyleValues[] = { (Fixed *)theSize, - (CGAffineTransform *)theTransform }; + + /* Set the style's size */ + Fixed theSize = FloatToFixed(1.0); + CGAffineTransform theTransform = CGAffineTransformMakeWithCairoScaleFactors(scale); + const ATSUAttributeTag theFontStyleTags[] = { kATSUSizeTag, kATSUFontMatrixTag }; + const ByteCount theFontStyleSizes[] = { sizeof(Fixed), sizeof(CGAffineTransform) }; + ATSUAttributeValuePtr theFontStyleValues[] = { &theSize, &theTransform }; err = ATSUCreateAndCopyStyle(inStyle, &style); @@ -225,8 +273,6 @@ _cairo_atsui_font_create_scaled (cairo_font_face_t *font_face, cairo_atsui_font_t *font = NULL; OSStatus err; cairo_status_t status; - double xscale = 1.0; - double yscale = 1.0; font = malloc(sizeof(cairo_atsui_font_t)); if (font == NULL) @@ -235,14 +281,7 @@ _cairo_atsui_font_create_scaled (cairo_font_face_t *font_face, _cairo_scaled_font_init(&font->base, font_face, font_matrix, ctm, options, &cairo_atsui_scaled_font_backend); - _cairo_matrix_compute_scale_factors (&font->base.scale, - &xscale, &yscale, 1); - font->font_matrix = CGAffineTransformMake (1., 0., - 0., yscale/xscale, - 0., 0.); - font->size = FloatToFixed (xscale); - - font->style = CreateSizedCopyOfStyle (style, &font->size, &font->font_matrix); + font->style = CreateSizedCopyOfStyle(style, &font->base.scale); { Fixed theSize = FloatToFixed(1.0); @@ -441,19 +480,11 @@ OSStatus _close_path_for_metrics(void *callback_data) return noErr; } -static GlyphID -_cairo_atsui_scaled_glyph_index (cairo_scaled_glyph_t *scaled_glyph) { - unsigned long index = _cairo_scaled_glyph_index (scaled_glyph); - if (index > 0xffff) - return kATSDeletedGlyphcode; - return index; -} - static cairo_status_t _cairo_atsui_font_init_glyph_metrics (cairo_atsui_font_t *scaled_font, cairo_scaled_glyph_t *scaled_glyph) { - cairo_text_extents_t extents = {0, 0, 0, 0, 0, 0}; + cairo_text_extents_t extents; OSStatus err, callback_err; ATSGlyphScreenMetrics metricsH; static ATSCubicMoveToUPP moveProc = NULL; @@ -461,17 +492,10 @@ _cairo_atsui_font_init_glyph_metrics (cairo_atsui_font_t *scaled_font, static ATSCubicCurveToUPP curveProc = NULL; static ATSCubicClosePathUPP closePathProc = NULL; CGMutablePathRef path; - GlyphID theGlyph = _cairo_atsui_scaled_glyph_index (scaled_glyph); + GlyphID theGlyph = _cairo_scaled_glyph_index (scaled_glyph); double xscale, yscale; CGRect rect; - if (theGlyph == kATSDeletedGlyphcode) { - _cairo_scaled_glyph_set_metrics (scaled_glyph, - &scaled_font->base, - &extents); - return CAIRO_STATUS_SUCCESS; - } - /* We calculate the advance from the screen metrics. We * could probably take this from the glyph path. */ @@ -479,7 +503,7 @@ _cairo_atsui_font_init_glyph_metrics (cairo_atsui_font_t *scaled_font, 1, &theGlyph, 0, false, false, &metricsH); if (err != noErr) - return CAIRO_STATUS_NO_MEMORY; + return CAIRO_INT_STATUS_UNSUPPORTED; /* Scale down to font units.*/ _cairo_matrix_compute_scale_factors (&scaled_font->base.scale, @@ -508,8 +532,11 @@ _cairo_atsui_font_init_glyph_metrics (cairo_atsui_font_t *scaled_font, (void *)path, &callback_err); if (err != noErr) { + /* This could potentially happen for bitmap fonts, where + * no paths are available. + */ CGPathRelease (path); - return CAIRO_STATUS_NO_MEMORY; + return CAIRO_INT_STATUS_UNSUPPORTED; } rect = CGPathGetBoundingBox (path); @@ -609,7 +636,6 @@ _cairo_atsui_scaled_font_init_glyph_path (cairo_atsui_font_t *scaled_font, static ATSCubicLineToUPP lineProc = NULL; static ATSCubicCurveToUPP curveProc = NULL; static ATSCubicClosePathUPP closePathProc = NULL; - GlyphID theGlyph = _cairo_atsui_scaled_glyph_index (scaled_glyph); OSStatus err; cairo_atsui_scaled_path_t scaled_path; cairo_matrix_t *font_to_device = &scaled_font->base.scale; @@ -617,17 +643,6 @@ _cairo_atsui_scaled_font_init_glyph_path (cairo_atsui_font_t *scaled_font, double xscale; double yscale; - scaled_path.path = _cairo_path_fixed_create (); - if (!scaled_path.path) - return CAIRO_STATUS_NO_MEMORY; - - if (theGlyph == kATSDeletedGlyphcode) { - _cairo_scaled_glyph_set_path (scaled_glyph, &scaled_font->base, - scaled_path.path); - - return CAIRO_STATUS_SUCCESS; - } - /* extract the rotation/shear component of the scale matrix. */ _cairo_matrix_compute_scale_factors (font_to_device, &xscale, &yscale, 1); cairo_matrix_init (&unscaled_font_to_device, @@ -638,6 +653,9 @@ _cairo_atsui_scaled_font_init_glyph_path (cairo_atsui_font_t *scaled_font, cairo_matrix_scale (&unscaled_font_to_device, 1.0/xscale, 1.0/yscale); scaled_path.scale = &unscaled_font_to_device; + scaled_path.path = _cairo_path_fixed_create (); + if (!scaled_path.path) + return CAIRO_STATUS_NO_MEMORY; if (moveProc == NULL) { moveProc = NewATSCubicMoveToUPP(_move_to); @@ -647,7 +665,7 @@ _cairo_atsui_scaled_font_init_glyph_path (cairo_atsui_font_t *scaled_font, } err = ATSUGlyphGetCubicPaths(scaled_font->style, - theGlyph, + _cairo_scaled_glyph_index (scaled_glyph), moveProc, lineProc, curveProc, @@ -673,7 +691,7 @@ _cairo_atsui_scaled_font_init_glyph_surface (cairo_atsui_font_t *scaled_font, cairo_scaled_font_t base = scaled_font->base; cairo_font_extents_t extents = base.extents; - GlyphID theGlyph = _cairo_atsui_scaled_glyph_index (scaled_glyph); + GlyphID theGlyph = _cairo_scaled_glyph_index (scaled_glyph); ATSGlyphScreenMetrics metricsH; double left, bottom, width, height; double xscale, yscale; @@ -681,16 +699,6 @@ _cairo_atsui_scaled_font_init_glyph_surface (cairo_atsui_font_t *scaled_font, CGAffineTransform transform; - if (theGlyph == kATSDeletedGlyphcode) { - surface = (cairo_image_surface_t *)cairo_image_surface_create (CAIRO_FORMAT_A8, 2, 2); - if (!surface) - return CAIRO_STATUS_NO_MEMORY; - _cairo_scaled_glyph_set_surface (scaled_glyph, - &base, - surface); - return CAIRO_STATUS_SUCCESS; - } - /* Compute a box to contain the glyph mask. The vertical * sizes come from the font extents; extra pixels are * added to account for fractional sizes. @@ -746,23 +754,10 @@ _cairo_atsui_scaled_font_init_glyph_surface (cairo_atsui_font_t *scaled_font, if (!surface) return CAIRO_STATUS_NO_MEMORY; - /* Create a CGBitmapContext for the dest surface for drawing into */ - { - CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceGray (); - - drawingContext = CGBitmapContextCreate (surface->data, - surface->width, - surface->height, - 8, - surface->stride, - colorSpace, - kCGImageAlphaNone); - CGColorSpaceRelease (colorSpace); - } - + drawingContext = CGBitmapContextCreateWithCairoImageSurface (surface); if (!drawingContext) { cairo_surface_destroy ((cairo_surface_t *)surface); - return CAIRO_STATUS_NO_MEMORY; + return CAIRO_INT_STATUS_UNSUPPORTED; } atsFont = FMGetATSFontRefFromFont (scaled_font->fontID); @@ -844,9 +839,6 @@ _cairo_atsui_font_text_to_glyphs (void *abstract_font, cairo_atsui_font_t *font = abstract_font; ItemCount glyphCount; int i; - CGPoint point; - double xscale, yscale; - CGAffineTransform device_to_user_scale; status = _cairo_utf8_to_utf16 ((unsigned char *)utf8, -1, &utf16, &n16); if (status) @@ -873,18 +865,9 @@ _cairo_atsui_font_text_to_glyphs (void *abstract_font, return CAIRO_STATUS_NO_MEMORY; } - _cairo_matrix_compute_scale_factors (&font->base.ctm, &xscale, &yscale, 1); - device_to_user_scale = - CGAffineTransformInvert (CGAffineTransformMake (xscale, 0, - 0, yscale, - 0, 0)); for (i = 0; i < *num_glyphs; i++) { (*glyphs)[i].index = layoutRecords[i].glyphID; - /* ATSLayoutRecord.realPos is in device units, convert to user units */ - point = CGPointMake (FixedToFloat (layoutRecords[i].realPos), 0); - point = CGPointApplyAffineTransform (point, device_to_user_scale); - - (*glyphs)[i].x = x + point.x; + (*glyphs)[i].x = x + FixedToFloat(layoutRecords[i].realPos); (*glyphs)[i].y = y; } @@ -898,6 +881,158 @@ _cairo_atsui_font_text_to_glyphs (void *abstract_font, return CAIRO_STATUS_SUCCESS; } +static cairo_int_status_t +_cairo_atsui_font_old_show_glyphs (void *abstract_font, + cairo_operator_t op, + cairo_pattern_t *pattern, + cairo_surface_t *generic_surface, + int source_x, + int source_y, + int dest_x, + int dest_y, + unsigned int width, + unsigned int height, + cairo_glyph_t *glyphs, + int num_glyphs) +{ + cairo_atsui_font_t *font = abstract_font; + CGContextRef drawingContext; + cairo_image_surface_t *destImageSurface; + int i; + void *extra = NULL; + cairo_bool_t can_draw_directly; + cairo_rectangle_int16_t rect; + cairo_quartz_surface_t *surface = (cairo_quartz_surface_t *)generic_surface; + + ATSFontRef atsFont; + CGFontRef cgFont; + CGAffineTransform textTransform; + + if (!_cairo_surface_is_quartz (generic_surface)) + return CAIRO_INT_STATUS_UNSUPPORTED; + + /* Check if we can draw directly to the destination surface */ + can_draw_directly = _cairo_pattern_is_opaque_solid (pattern) && + op == CAIRO_OPERATOR_OVER; + + if (!can_draw_directly) { + rect.x = dest_x; + rect.y = dest_y; + rect.width = width; + rect.height = height; + + _cairo_surface_acquire_dest_image(generic_surface, + &rect, + &destImageSurface, + &rect, + &extra); + + drawingContext = CGBitmapContextCreateWithCairoImageSurface (destImageSurface); + if (!drawingContext) + return CAIRO_INT_STATUS_UNSUPPORTED; + + CGContextTranslateCTM(drawingContext, 0, destImageSurface->height); + CGContextScaleCTM(drawingContext, 1.0f, -1.0f); + } else { + drawingContext = ((cairo_quartz_surface_t *)generic_surface)->context; + CGContextSaveGState (drawingContext); + } + + atsFont = FMGetATSFontRefFromFont(font->fontID); + cgFont = CGFontCreateWithPlatformFont(&atsFont); + + CGContextSetFont(drawingContext, cgFont); + + if (font->base.options.antialias == CAIRO_ANTIALIAS_NONE) { + CGContextSetShouldAntialias (drawingContext, false); + } + + textTransform = CGAffineTransformMakeWithCairoFontScale(&font->base.scale); + textTransform = CGAffineTransformScale(textTransform, 1.0f, -1.0f); + + CGContextSetFontSize(drawingContext, 1.0); + CGContextSetTextMatrix(drawingContext, textTransform); + + if (pattern->type == CAIRO_PATTERN_TYPE_SOLID && + _cairo_pattern_is_opaque_solid(pattern)) + { + cairo_solid_pattern_t *solid = (cairo_solid_pattern_t *)pattern; + CGContextSetRGBFillColor(drawingContext, + solid->color.red, + solid->color.green, + solid->color.blue, 1.0f); + } else { + CGContextSetRGBFillColor(drawingContext, 0.0f, 0.0f, 0.0f, 0.0f); + } + + if (surface->clip_region) { + pixman_box16_t *boxes = pixman_region_rects (surface->clip_region); + int num_boxes = pixman_region_num_rects (surface->clip_region); + CGRect stack_rects[10]; + CGRect *rects; + int i; + + /* XXX: Return-value of malloc needs to be checked for + * NULL. Can someone fix this who is more familiar with + * the cleanup needed in this function? + */ + if (num_boxes > 10) + rects = malloc (sizeof (CGRect) * num_boxes); + else + rects = stack_rects; + + for (i = 0; i < num_boxes; i++) { + rects[i].origin.x = boxes[i].x1; + rects[i].origin.y = boxes[i].y1; + rects[i].size.width = boxes[i].x2 - boxes[i].x1; + rects[i].size.height = boxes[i].y2 - boxes[i].y1; + } + + CGContextClipToRects (drawingContext, rects, num_boxes); + + if (rects != stack_rects) + free(rects); + } + + /* TODO - bold and italic text + * + * We could draw the text using ATSUI and get bold, italics + * etc. for free, but ATSUI does a lot of text layout work + * that we don't really need... + */ + + for (i = 0; i < num_glyphs; i++) { + CGGlyph theGlyph = glyphs[i].index; + + /* round glyph locations to the nearest pixel */ + /* XXX: FRAGILE: We're ignoring device_transform scaling here. A bug? */ + CGContextShowGlyphsAtPoint(drawingContext, + _cairo_lround (glyphs[i].x), + _cairo_lround (glyphs[i].y), + &theGlyph, 1); + } + + if (!can_draw_directly) { + CGContextRelease(drawingContext); + + _cairo_surface_release_dest_image(generic_surface, + &rect, + destImageSurface, + &rect, + extra); + } else { + CGContextRestoreGState (drawingContext); + } + + return CAIRO_STATUS_SUCCESS; +} + +cairo_bool_t +_cairo_scaled_font_is_atsui (cairo_scaled_font_t *sfont) +{ + return (sfont->backend == &cairo_atsui_scaled_font_backend); +} + ATSUStyle _cairo_atsui_scaled_font_get_atsu_style (cairo_scaled_font_t *sfont) { @@ -914,30 +1049,6 @@ _cairo_atsui_scaled_font_get_atsu_font_id (cairo_scaled_font_t *sfont) return afont->fontID; } -static cairo_int_status_t -_cairo_atsui_load_truetype_table (void *abstract_font, - unsigned long tag, - long offset, - unsigned char *buffer, - unsigned long *length) -{ - cairo_atsui_font_t *scaled_font = abstract_font; - ATSFontRef atsFont; - OSStatus err; - - atsFont = FMGetATSFontRefFromFont (scaled_font->fontID); - err = ATSFontGetTable ( atsFont, tag, - (ByteOffset) offset, - (ByteCount) *length, - buffer, - length); - if (err != noErr) { - return CAIRO_INT_STATUS_UNSUPPORTED; - } - - return CAIRO_STATUS_SUCCESS; -} - const cairo_scaled_font_backend_t cairo_atsui_scaled_font_backend = { CAIRO_FONT_TYPE_ATSUI, _cairo_atsui_font_create_toy, @@ -945,8 +1056,6 @@ const cairo_scaled_font_backend_t cairo_atsui_scaled_font_backend = { _cairo_atsui_font_scaled_glyph_init, _cairo_atsui_font_text_to_glyphs, NULL, /* ucs4_to_index */ - NULL, /* show_glyphs */ - _cairo_atsui_load_truetype_table, - NULL, /* map_glyphs_to_unicode */ + _cairo_atsui_font_old_show_glyphs, }; diff --git a/gfx/cairo/cairo/src/cairo-bentley-ottmann.c b/gfx/cairo/cairo/src/cairo-bentley-ottmann.c index 928b6cd5646..4a72a8d0d88 100644 --- a/gfx/cairo/cairo/src/cairo-bentley-ottmann.c +++ b/gfx/cairo/cairo/src/cairo-bentley-ottmann.c @@ -121,7 +121,7 @@ typedef struct _cairo_bo_event { #define SKIP_ELT_TO_EVENT(elt) SKIP_LIST_ELT_TO_DATA (cairo_bo_event_t, (elt)) typedef struct _cairo_bo_event_queue { - cairo_skip_list_t intersection_queue; + skip_list_t intersection_queue; cairo_bo_event_t *startstop_events; cairo_bo_event_t **sorted_startstop_event_ptrs; @@ -129,9 +129,9 @@ typedef struct _cairo_bo_event_queue { unsigned num_startstop_events; } cairo_bo_event_queue_t; -/* This structure extends cairo_skip_list_t, which must come first. */ +/* This structure extends skip_list_t, which must come first. */ typedef struct _cairo_bo_sweep_line { - cairo_skip_list_t active_edges; + skip_list_t active_edges; cairo_bo_edge_t *head; cairo_bo_edge_t *tail; int32_t current_y; @@ -697,7 +697,7 @@ _cairo_bo_event_queue_insert (cairo_bo_event_queue_t *queue, cairo_bo_event_t *event) { /* Don't insert if there's already an equivalent intersection event in the queue. */ - _cairo_skip_list_insert (&queue->intersection_queue, event, + skip_list_insert (&queue->intersection_queue, event, event->type == CAIRO_BO_EVENT_TYPE_INTERSECTION); } @@ -706,7 +706,7 @@ _cairo_bo_event_queue_delete (cairo_bo_event_queue_t *queue, cairo_bo_event_t *event) { if (CAIRO_BO_EVENT_TYPE_INTERSECTION == event->type) - _cairo_skip_list_delete_given ( &queue->intersection_queue, &event->elt ); + skip_list_delete_given ( &queue->intersection_queue, &event->elt ); } static cairo_bo_event_t * @@ -740,7 +740,7 @@ _cairo_bo_event_queue_init (cairo_bo_event_queue_t *event_queue, memset (event_queue, 0, sizeof(*event_queue)); - _cairo_skip_list_init (&event_queue->intersection_queue, + skip_list_init (&event_queue->intersection_queue, cairo_bo_event_compare_abstract, sizeof (cairo_bo_event_t)); if (0 == num_edges) @@ -789,7 +789,7 @@ _cairo_bo_event_queue_init (cairo_bo_event_queue_t *event_queue, static void _cairo_bo_event_queue_fini (cairo_bo_event_queue_t *event_queue) { - _cairo_skip_list_fini (&event_queue->intersection_queue); + skip_list_fini (&event_queue->intersection_queue); if (event_queue->startstop_events) free (event_queue->startstop_events); if (event_queue->sorted_startstop_event_ptrs) @@ -834,7 +834,7 @@ _cairo_bo_event_queue_insert_if_intersect_below_current_y (cairo_bo_event_queue_ static void _cairo_bo_sweep_line_init (cairo_bo_sweep_line_t *sweep_line) { - _cairo_skip_list_init (&sweep_line->active_edges, + skip_list_init (&sweep_line->active_edges, _sweep_line_elt_compare, sizeof (sweep_line_elt_t)); sweep_line->head = NULL; @@ -845,7 +845,7 @@ _cairo_bo_sweep_line_init (cairo_bo_sweep_line_t *sweep_line) static void _cairo_bo_sweep_line_fini (cairo_bo_sweep_line_t *sweep_line) { - _cairo_skip_list_fini (&sweep_line->active_edges); + skip_list_fini (&sweep_line->active_edges); } static void @@ -856,7 +856,7 @@ _cairo_bo_sweep_line_insert (cairo_bo_sweep_line_t *sweep_line, sweep_line_elt_t *sweep_line_elt; cairo_bo_edge_t **prev_of_next, **next_of_prev; - sweep_line_elt = _cairo_skip_list_insert (&sweep_line->active_edges, &edge, + sweep_line_elt = skip_list_insert (&sweep_line->active_edges, &edge, 1 /* unique inserts*/); next_elt = sweep_line_elt->elt.next[0]; @@ -884,7 +884,7 @@ _cairo_bo_sweep_line_delete (cairo_bo_sweep_line_t *sweep_line, { cairo_bo_edge_t **left_next, **right_prev; - _cairo_skip_list_delete_given (&sweep_line->active_edges, &edge->sweep_line_elt->elt); + skip_list_delete_given (&sweep_line->active_edges, &edge->sweep_line_elt->elt); left_next = &sweep_line->head; if (edge->prev) @@ -975,7 +975,7 @@ _cairo_bo_event_queue_print (cairo_bo_event_queue_t *event_queue) { skip_elt_t *elt; /* XXX: fixme to print the start/stop array too. */ - cairo_skip_list_t *queue = &event_queue->intersection_queue; + skip_list_t *queue = &event_queue->intersection_queue; cairo_bo_event_t *event; printf ("Event queue:\n"); @@ -1767,7 +1767,7 @@ int main (void) { char random_name[] = "random-XX"; - cairo_bo_edge_t random_edges[MAX_RANDOM], *edge; + static cairo_bo_edge_t random_edges[MAX_RANDOM], *edge; unsigned int i, num_random; test_t *test; diff --git a/gfx/cairo/cairo/src/cairo-cff-subset.c b/gfx/cairo/cairo/src/cairo-cff-subset.c index b35498940b8..d26ee870cab 100644 --- a/gfx/cairo/cairo/src/cairo-cff-subset.c +++ b/gfx/cairo/cairo/src/cairo-cff-subset.c @@ -31,7 +31,6 @@ * * Contributor(s): * Adrian Johnson - * Eugeniy Meshcheryakov */ #include "cairoint.h" @@ -82,13 +81,6 @@ typedef struct _cff_dict_operator { int operand_offset; } cff_dict_operator_t; -typedef struct _cff_charset { - cairo_bool_t is_builtin; - const uint16_t *sids; - const unsigned char *data; - int length; -} cff_charset_t; - typedef struct _cairo_cff_font { cairo_scaled_font_subset_t *scaled_font_subset; @@ -108,14 +100,11 @@ typedef struct _cairo_cff_font { cairo_array_t global_sub_index; cairo_array_t local_sub_index; int num_glyphs; - cff_charset_t charset; - int charset_offset; /* Subsetted Font Data */ char *subset_font_name; cairo_array_t charstrings_subset_index; cairo_array_t strings_subset_index; - cairo_array_t charset_subset; cairo_array_t output; /* Subset Metrics */ @@ -125,6 +114,34 @@ typedef struct _cairo_cff_font { } cairo_cff_font_t; +#ifdef WORDS_BIGENDIAN + +#define cpu_to_be16(v) (v) +#define be16_to_cpu(v) (v) +#define cpu_to_be32(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); +} + +#endif + /* Encoded integer using maximum sized encoding. This is required for * operands that are later modified after encoding. */ static unsigned char * @@ -488,6 +505,20 @@ fail: return status; } +static void +cff_dict_remove (cairo_hash_table_t *dict, unsigned short operator) +{ + cff_dict_operator_t key, *op; + + _cairo_dict_init_key (&key, operator); + if (_cairo_hash_table_lookup (dict, &key.base, + (cairo_hash_entry_t **) &op)) + { + free (op->operand); + _cairo_hash_table_remove (dict, (cairo_hash_entry_t *) op); + } +} + static unsigned char * cff_dict_get_operands (cairo_hash_table_t *dict, unsigned short operator, @@ -711,19 +742,12 @@ cairo_cff_font_read_top_dict (cairo_cff_font_t *font) decode_integer (operand, &offset); cairo_cff_font_read_private_dict (font, font->data + offset, size); - operand = cff_dict_get_operands (font->top_dict, CHARSET_OP, &size); - if (!operand) - font->charset_offset = 0; - else { - decode_integer (operand, &offset); - font->charset_offset = offset; - } + cff_dict_remove (font->top_dict, CHARSET_OP); /* Use maximum sized encoding to reserve space for later modification. */ end_buf = encode_integer_max (buf, 0); cff_dict_set_operands (font->top_dict, CHARSTRINGS_OP, buf, end_buf - buf); cff_dict_set_operands (font->top_dict, ENCODING_OP, buf, end_buf - buf); - cff_dict_set_operands (font->top_dict, CHARSET_OP, buf, end_buf - buf); /* Private has two operands - size and offset */ end_buf = encode_integer_max (end_buf, 0); cff_dict_set_operands (font->top_dict, PRIVATE_OP, buf, end_buf - buf); @@ -746,138 +770,6 @@ cairo_cff_font_read_global_subroutines (cairo_cff_font_t *font) return cff_index_read (&font->global_sub_index, &font->current_ptr, font->data_end); } -static cairo_int_status_t -cff_charset_read_data (cff_charset_t *charset, const unsigned char *data, - const unsigned char *data_end, int num_glyphs) -{ - const unsigned char *p = data; - - num_glyphs -= 1; /* do not count .notdef */ - - if (p + 1 > data_end) - return CAIRO_INT_STATUS_UNSUPPORTED; - - switch (*p++) { - case 0: - if (p + num_glyphs*2 > data_end) - return CAIRO_INT_STATUS_UNSUPPORTED; - charset->is_builtin = FALSE; - charset->data = data; - charset->length = num_glyphs * 2 + 1; - break; - case 1: - while (num_glyphs > 0) { - if (p + 3 > data_end) - return CAIRO_INT_STATUS_UNSUPPORTED; - num_glyphs -= p[2] + 1; - p += 3; - } - if (num_glyphs < 0) - return CAIRO_INT_STATUS_UNSUPPORTED; - charset->is_builtin = FALSE; - charset->data = data; - charset->length = p - data; - break; - case 2: - while (num_glyphs > 0) { - if (p + 4 > data_end) - return CAIRO_INT_STATUS_UNSUPPORTED; - num_glyphs -= be16_to_cpu(*(uint16_t *)(p + 2)) + 1; - p += 4; - } - if (num_glyphs < 0) - return CAIRO_INT_STATUS_UNSUPPORTED; - charset->is_builtin = FALSE; - charset->data = data; - charset->length = p - data; - break; - default: - return CAIRO_INT_STATUS_UNSUPPORTED; - } - - return CAIRO_STATUS_SUCCESS; -} - -static const uint16_t ISOAdobe_charset[] = { - 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, - 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, - 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, - 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, - 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, - 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, - 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, - 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, - 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, - 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, - 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, - 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, - 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, - 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, - 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, - 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, - 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, - 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, - 222, 223, 224, 225, 226, 227, 228, -}; - -static const uint16_t Expert_charset[] = { - 1, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 13, - 14, 15, 99, 239, 240, 241, 242, 243, 244, 245, 246, 247, - 248, 27, 28, 249, 250, 251, 252, 253, 254, 255, 256, 257, - 258, 259, 260, 261, 262, 263, 264, 265, 266, 109, 110, - 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, - 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, - 289, 290, 291, 292, 293, 294, 295, 296, 297, 298, 299, - 300, 301, 302, 303, 304, 305, 306, 307, 308, 309, 310, - 311, 312, 313, 314, 315, 316, 317, 318, 158, 155, 163, - 319, 320, 321, 322, 323, 324, 325, 326, 150, 164, 169, - 327, 328, 329, 330, 331, 332, 333, 334, 335, 336, 337, - 338, 339, 340, 341, 342, 343, 344, 345, 346, 347, 348, - 349, 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, - 360, 361, 362, 363, 364, 365, 366, 367, 368, 369, 370, - 371, 372, 373, 374, 375, 376, 377, 378, -}; - -static const uint16_t ExpertSubset_charset[] = { - 1, 231, 232, 235, 236, 237, 238, 13, 14, 15, 99, 239, 240, - 241, 242, 243, 244, 245, 246, 247, 248, 27, 28, 249, 250, - 251, 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, - 263, 264, 265, 266, 109, 110, 267, 268, 269, 270, 272, - 300, 301, 302, 305, 314, 315, 158, 155, 163, 320, 321, - 322, 323, 324, 325, 326, 150, 164, 169, 327, 328, 329, - 330, 331, 332, 333, 334, 335, 336, 337, 338, 339, 340, - 341, 342, 343, 344, 345, 346, -}; - -static cairo_int_status_t -cairo_cff_font_read_charset (cairo_cff_font_t *font) -{ - switch (font->charset_offset) { - case 0: - /* ISOAdobe charset */ - font->charset.is_builtin = TRUE; - font->charset.sids = ISOAdobe_charset; - font->charset.length = sizeof (ISOAdobe_charset); - return CAIRO_STATUS_SUCCESS; - case 1: - /* Expert charset */ - font->charset.is_builtin = TRUE; - font->charset.sids = Expert_charset; - font->charset.length = sizeof (Expert_charset); - return CAIRO_STATUS_SUCCESS; - case 2: - /* ExpertSubset charset */; - font->charset.is_builtin = TRUE; - font->charset.sids = ExpertSubset_charset; - font->charset.length = sizeof (ExpertSubset_charset); - return CAIRO_STATUS_SUCCESS; - default: - break; - } - return cff_charset_read_data (&font->charset, font->data + (unsigned)font->charset_offset, - font->data_end, font->num_glyphs); -} - typedef cairo_int_status_t (*font_read_t) (cairo_cff_font_t *font); @@ -887,8 +779,6 @@ static const font_read_t font_read_funcs[] = { cairo_cff_font_read_top_dict, cairo_cff_font_read_strings, cairo_cff_font_read_global_subroutines, - /* non-contiguous */ - cairo_cff_font_read_charset, }; static cairo_int_status_t @@ -1008,80 +898,6 @@ cairo_cff_font_subset_charstrings (cairo_cff_font_t *font) return CAIRO_STATUS_SUCCESS; } -static uint16_t -cff_sid_from_gid (const cff_charset_t *charset, int gid) -{ - const uint16_t *sids; - const unsigned char *p; - int prev_glyph; - - if (charset->is_builtin) { - if (gid - 1 < charset->length / 2) - return charset->sids[gid - 1]; - } - else { - /* no need to check sizes here, this was done during reading */ - switch (charset->data[0]) { - case 0: - sids = (const uint16_t *)(charset->data + 1); - return be16_to_cpu(sids[gid - 1]); - case 1: - prev_glyph = 1; - for (p = charset->data + 1; p < charset->data + charset->length; p += 3) { - if (gid <= prev_glyph + p[2]) { - uint16_t sid = be16_to_cpu(*(const uint16_t *)p); - return sid + gid - prev_glyph; - } - prev_glyph += p[2] + 1; - } - break; - case 2: - prev_glyph = 1; - for (p = charset->data + 1; p < charset->data + charset->length; p += 4) { - uint16_t nLeft = be16_to_cpu(*(const uint16_t *)(p + 2)); - if (gid <= prev_glyph + nLeft) { - uint16_t sid = be16_to_cpu(*(const uint16_t *)p); - return sid + gid - prev_glyph; - } - prev_glyph += nLeft + 1; - } - break; - default: - break; - } - } - return 0; -} - -static cairo_status_t -cairo_cff_font_subset_charset (cairo_cff_font_t *font) -{ - unsigned int i; - - for (i = 0; i < font->scaled_font_subset->num_glyphs; i++) { - int gid = font->scaled_font_subset->glyphs[i]; - uint16_t original_sid = cff_sid_from_gid(&font->charset, gid); - uint16_t new_sid; - cff_index_element_t *element; - cairo_status_t status; - - if (original_sid >= NUM_STD_STRINGS) { - element = _cairo_array_index (&font->strings_index, original_sid - NUM_STD_STRINGS); - new_sid = NUM_STD_STRINGS + _cairo_array_num_elements (&font->strings_subset_index); - status = cff_index_append (&font->strings_subset_index, element->data, element->length); - if (status) - return status; - } - else - new_sid = original_sid; - - status = _cairo_array_append(&font->charset_subset, &new_sid); - if (status) - return status; - } - return CAIRO_STATUS_SUCCESS; -} - static cairo_status_t cairo_cff_font_subset_font (cairo_cff_font_t *font) { @@ -1094,10 +910,6 @@ cairo_cff_font_subset_font (cairo_cff_font_t *font) return status; status = cairo_cff_font_subset_charstrings (font); - if (status) - return status; - - status = cairo_cff_font_subset_charset (font); return status; } @@ -1226,27 +1038,6 @@ cairo_cff_font_write_encoding (cairo_cff_font_t *font) return _cairo_array_append_multiple (&font->output, buf, 4); } -static cairo_status_t -cairo_cff_font_write_charset (cairo_cff_font_t *font) -{ - unsigned char format = 0; - unsigned int i; - cairo_status_t status; - - cairo_cff_font_set_topdict_operator_to_cur_pos (font, CHARSET_OP); - status = _cairo_array_append (&font->output, &format); - if (status) - return status; - - for (i = 0; i < (unsigned)_cairo_array_num_elements(&font->charset_subset); i++) { - uint16_t sid = cpu_to_be16(*(uint16_t *)_cairo_array_index(&font->charset_subset, i)); - status = _cairo_array_append_multiple (&font->output, &sid, sizeof(sid)); - if (status) - return status; - } - return CAIRO_STATUS_SUCCESS; -} - static cairo_status_t cairo_cff_font_write_charstrings (cairo_cff_font_t *font) { @@ -1307,7 +1098,6 @@ static const font_write_t font_write_funcs[] = { cairo_cff_font_write_strings, cairo_cff_font_write_global_subrs, cairo_cff_font_write_encoding, - cairo_cff_font_write_charset, cairo_cff_font_write_charstrings, cairo_cff_font_write_private_dict_and_local_sub, }; @@ -1555,7 +1345,6 @@ _cairo_cff_font_create (cairo_scaled_font_subset_t *scaled_font_subset, cff_index_init (&font->local_sub_index); cff_index_init (&font->charstrings_subset_index); cff_index_init (&font->strings_subset_index); - _cairo_array_init (&font->charset_subset, sizeof(uint16_t)); free (name); *font_return = font; @@ -1594,7 +1383,6 @@ cairo_cff_font_destroy (cairo_cff_font_t *font) cff_index_fini (&font->local_sub_index); cff_index_fini (&font->charstrings_subset_index); cff_index_fini (&font->strings_subset_index); - _cairo_array_fini (&font->charset_subset); free (font); } diff --git a/gfx/cairo/cairo/src/cairo-clip.c b/gfx/cairo/cairo/src/cairo-clip.c index efecd89efd2..605589bb936 100644 --- a/gfx/cairo/cairo/src/cairo-clip.c +++ b/gfx/cairo/cairo/src/cairo-clip.c @@ -48,10 +48,7 @@ _cairo_clip_path_destroy (cairo_clip_path_t *clip_path); void _cairo_clip_init (cairo_clip_t *clip, cairo_surface_t *target) { - if (target) - clip->mode = _cairo_surface_get_clip_mode (target); - else - clip->mode = CAIRO_CLIP_MODE_MASK; + clip->mode = _cairo_surface_get_clip_mode (target); clip->surface = NULL; clip->surface_rect.x = 0; diff --git a/gfx/cairo/cairo/src/cairo-color.c b/gfx/cairo/cairo/src/cairo-color.c index ad6316e10ef..a3488392661 100644 --- a/gfx/cairo/cairo/src/cairo-color.c +++ b/gfx/cairo/cairo/src/cairo-color.c @@ -95,8 +95,7 @@ _cairo_color_init_rgb (cairo_color_t *color, * then special-casing the result of an input value of 1.0 so that it * maps to 65535 instead of 65536. */ -uint16_t -_cairo_color_double_to_short (double d) +static inline uint16_t _color_to_short (double d) { uint32_t i; i = (uint32_t) (d * 65536); @@ -107,10 +106,10 @@ _cairo_color_double_to_short (double d) static void _cairo_color_compute_shorts (cairo_color_t *color) { - color->red_short = _cairo_color_double_to_short (color->red * color->alpha); - color->green_short = _cairo_color_double_to_short (color->green * color->alpha); - color->blue_short = _cairo_color_double_to_short (color->blue * color->alpha); - color->alpha_short = _cairo_color_double_to_short (color->alpha); + color->red_short = _color_to_short (color->red * color->alpha); + color->green_short = _color_to_short (color->green * color->alpha); + color->blue_short = _color_to_short (color->blue * color->alpha); + color->alpha_short = _color_to_short (color->alpha); } void diff --git a/gfx/cairo/cairo/src/cairo-directfb-surface.c b/gfx/cairo/cairo/src/cairo-directfb-surface.c index 686510d61ed..46a4c7f6a74 100644 --- a/gfx/cairo/cairo/src/cairo-directfb-surface.c +++ b/gfx/cairo/cairo/src/cairo-directfb-surface.c @@ -52,9 +52,9 @@ /* - * Rectangle causes problems (see bugs 361377, 359553, 359243 in Gnome BTS). + * Rectangle works fine. */ -#define DFB_RECTANGLES 0 +#define DFB_RECTANGLES 1 /* * Composite works fine. diff --git a/gfx/cairo/cairo/src/cairo-directfb.h b/gfx/cairo/cairo/src/cairo-directfb.h index 795a0dc167b..845f3de6828 100644 --- a/gfx/cairo/cairo/src/cairo-directfb.h +++ b/gfx/cairo/cairo/src/cairo-directfb.h @@ -48,8 +48,5 @@ cairo_directfb_surface_create (IDirectFB *dfb,IDirectFBSurface *surface); CAIRO_END_DECLS -#else /*CAIRO_HAS_DIRECTFB_SURFACE*/ -# error Cairo was not compiled with support for the directfb backend #endif /*CAIRO_HAS_DIRECTFB_SURFACE*/ - #endif /*CAIRO_DIRECTFB_H*/ diff --git a/gfx/cairo/cairo/src/cairo-features.h.in b/gfx/cairo/cairo/src/cairo-features.h.in index 5eaf0a8fc83..0b5d7dcf5b1 100644 --- a/gfx/cairo/cairo/src/cairo-features.h.in +++ b/gfx/cairo/cairo/src/cairo-features.h.in @@ -52,10 +52,10 @@ #endif #define CAIRO_VERSION_MAJOR 1 -#define CAIRO_VERSION_MINOR 4 -#define CAIRO_VERSION_MICRO 2 +#define CAIRO_VERSION_MINOR 3 +#define CAIRO_VERSION_MICRO 12 -#define CAIRO_VERSION_STRING "1.4.2" +#define CAIRO_VERSION_STRING "1.3.12" @PS_SURFACE_FEATURE@ diff --git a/gfx/cairo/cairo/src/cairo-font.c b/gfx/cairo/cairo/src/cairo-font.c index cacc5899da9..373068673e4 100644 --- a/gfx/cairo/cairo/src/cairo-font.c +++ b/gfx/cairo/cairo/src/cairo-font.c @@ -1,4 +1,3 @@ -/* -*- 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 @@ -66,31 +65,25 @@ _cairo_font_face_init (cairo_font_face_t *font_face, _cairo_user_data_array_init (&font_face->user_data); } -/* This mutex protects both cairo_toy_font_hash_table as well as - reference count manipulations for all cairo_font_face_t. */ -CAIRO_MUTEX_DECLARE (_cairo_font_face_mutex); - /** * cairo_font_face_reference: - * @font_face: a #cairo_font_face_t, (may be %NULL in which case this + * @font_face: a #cairo_font_face_t, (may be NULL in which case this * function does nothing). * * Increases the reference count on @font_face by one. This prevents * @font_face from being destroyed until a matching call to * cairo_font_face_destroy() is made. * - * The number of references to a #cairo_font_face_t can be get using - * cairo_font_face_get_reference_count(). - * * Return value: the referenced #cairo_font_face_t. **/ cairo_font_face_t * cairo_font_face_reference (cairo_font_face_t *font_face) { - if (font_face == NULL || font_face->ref_count == CAIRO_REF_COUNT_INVALID) - return font_face; + if (font_face == NULL) + return NULL; - CAIRO_MUTEX_LOCK (_cairo_font_face_mutex); + if (font_face->ref_count == CAIRO_REF_COUNT_INVALID) + return font_face; /* We would normally assert (font_face->ref_count >0) here but we * can't get away with that due to the zombie case as documented @@ -98,8 +91,6 @@ cairo_font_face_reference (cairo_font_face_t *font_face) font_face->ref_count++; - CAIRO_MUTEX_UNLOCK (_cairo_font_face_mutex); - return font_face; } slim_hidden_def (cairo_font_face_reference); @@ -115,19 +106,16 @@ slim_hidden_def (cairo_font_face_reference); void cairo_font_face_destroy (cairo_font_face_t *font_face) { - if (font_face == NULL || font_face->ref_count == CAIRO_REF_COUNT_INVALID) + if (font_face == NULL) return; - CAIRO_MUTEX_LOCK (_cairo_font_face_mutex); + if (font_face->ref_count == CAIRO_REF_COUNT_INVALID) + return; assert (font_face->ref_count > 0); - if (--(font_face->ref_count) > 0) { - CAIRO_MUTEX_UNLOCK (_cairo_font_face_mutex); + if (--(font_face->ref_count) > 0) return; - } - - CAIRO_MUTEX_UNLOCK (_cairo_font_face_mutex); font_face->backend->destroy (font_face); @@ -146,7 +134,7 @@ slim_hidden_def (cairo_font_face_destroy); /** * cairo_font_face_get_type: - * @font_face: a font face + * @font_face: a #cairo_font_face_t * * This function returns the type of the backend used to create * a font face. See #cairo_font_type_t for available types. @@ -161,26 +149,6 @@ cairo_font_face_get_type (cairo_font_face_t *font_face) return font_face->backend->type; } -/** - * cairo_font_face_get_reference_count: - * @font_face: a #cairo_font_face_t - * - * Returns the current reference count of @font_face. - * - * Return value: the current reference count of @font_face. If the - * object is a nil object, 0 will be returned. - * - * Since: 1.4 - **/ -unsigned int -cairo_font_face_get_reference_count (cairo_font_face_t *font_face) -{ - if (font_face == NULL || font_face->ref_count == CAIRO_REF_COUNT_INVALID) - return 0; - - return font_face->ref_count; -} - /** * cairo_font_face_status: * @font_face: a #cairo_font_face_t @@ -258,16 +226,16 @@ _cairo_toy_font_face_keys_equal (const void *key_a, * our cache and mapping from cairo_font_face_t => cairo_scaled_font_t * works. Once the corresponding cairo_font_face_t objects fall out of * downstream caches, we don't need them in this hash table anymore. - * - * Modifications to this hash table are protected by - * _cairo_font_face_mutex. */ + static cairo_hash_table_t *cairo_toy_font_face_hash_table = NULL; +CAIRO_MUTEX_DECLARE (cairo_toy_font_face_hash_table_mutex); + static cairo_hash_table_t * _cairo_toy_font_face_hash_table_lock (void) { - CAIRO_MUTEX_LOCK (_cairo_font_face_mutex); + CAIRO_MUTEX_LOCK (cairo_toy_font_face_hash_table_mutex); if (cairo_toy_font_face_hash_table == NULL) { @@ -275,7 +243,7 @@ _cairo_toy_font_face_hash_table_lock (void) _cairo_hash_table_create (_cairo_toy_font_face_keys_equal); if (cairo_toy_font_face_hash_table == NULL) { - CAIRO_MUTEX_UNLOCK (_cairo_font_face_mutex); + CAIRO_MUTEX_UNLOCK (cairo_toy_font_face_hash_table_mutex); return NULL; } } @@ -286,7 +254,7 @@ _cairo_toy_font_face_hash_table_lock (void) static void _cairo_toy_font_face_hash_table_unlock (void) { - CAIRO_MUTEX_UNLOCK (_cairo_font_face_mutex); + CAIRO_MUTEX_UNLOCK (cairo_toy_font_face_hash_table_mutex); } /** @@ -395,11 +363,8 @@ _cairo_toy_font_face_create (const char *family, &key.base.hash_entry, (cairo_hash_entry_t **) &font_face)) { - /* We increment the reference count here manually to avoid - double-locking. */ - font_face->base.ref_count++; _cairo_toy_font_face_hash_table_unlock (); - return &font_face->base; + return cairo_font_face_reference (&font_face->base); } /* Otherwise create it and insert into hash table. */ @@ -506,11 +471,8 @@ _cairo_font_reset_static_data (void) { _cairo_scaled_font_map_destroy (); - /* We manually acquire the lock rather than calling - * cairo_toy_font_face_hash_table_lock simply to avoid - * creating the table only to destroy it again. */ - CAIRO_MUTEX_LOCK (_cairo_font_face_mutex); + CAIRO_MUTEX_LOCK (cairo_toy_font_face_hash_table_mutex); _cairo_hash_table_destroy (cairo_toy_font_face_hash_table); cairo_toy_font_face_hash_table = NULL; - CAIRO_MUTEX_UNLOCK (_cairo_font_face_mutex); + CAIRO_MUTEX_UNLOCK (cairo_toy_font_face_hash_table_mutex); } diff --git a/gfx/cairo/cairo/src/cairo-ft-font.c b/gfx/cairo/cairo/src/cairo-ft-font.c index 6174d1415c1..660f8531e88 100644 --- a/gfx/cairo/cairo/src/cairo-ft-font.c +++ b/gfx/cairo/cairo/src/cairo-ft-font.c @@ -62,11 +62,9 @@ */ #define MAX_OPEN_FACES 10 -#ifndef MOZILLA_CAIRO_NOT_DEFINED /* This is the maximum font size we allow to be passed to FT_Set_Char_Size */ #define MAX_FONT_SIZE 1000 -#endif /* !MOZILLA_CAIRO_NOT_DEFINED */ /* * The simple 2x2 matrix is converted into separate scale and shape @@ -106,8 +104,7 @@ struct _cairo_ft_unscaled_font { cairo_matrix_t current_shape; FT_Matrix Current_Shape; - cairo_mutex_t mutex; - int lock_count; + int lock; /* count of how many times this font has been locked */ cairo_ft_font_face_t *faces; /* Linked list of faces for this font */ }; @@ -156,7 +153,7 @@ typedef struct _cairo_ft_unscaled_font_map { static cairo_ft_unscaled_font_map_t *cairo_ft_unscaled_font_map = NULL; -CAIRO_MUTEX_DECLARE(_cairo_ft_unscaled_font_map_mutex); +CAIRO_MUTEX_DECLARE(cairo_ft_unscaled_font_map_mutex); static void _font_map_release_face_lock_held (cairo_ft_unscaled_font_map_t *font_map, @@ -214,7 +211,7 @@ _cairo_ft_unscaled_font_map_destroy (void) cairo_ft_unscaled_font_t *unscaled; cairo_ft_unscaled_font_map_t *font_map; - CAIRO_MUTEX_LOCK (_cairo_ft_unscaled_font_map_mutex); + CAIRO_MUTEX_LOCK (cairo_ft_unscaled_font_map_mutex); if (cairo_ft_unscaled_font_map) { font_map = cairo_ft_unscaled_font_map; @@ -247,20 +244,20 @@ _cairo_ft_unscaled_font_map_destroy (void) cairo_ft_unscaled_font_map = NULL; } - CAIRO_MUTEX_UNLOCK (_cairo_ft_unscaled_font_map_mutex); + CAIRO_MUTEX_UNLOCK (cairo_ft_unscaled_font_map_mutex); } static cairo_ft_unscaled_font_map_t * _cairo_ft_unscaled_font_map_lock (void) { - CAIRO_MUTEX_LOCK (_cairo_ft_unscaled_font_map_mutex); + CAIRO_MUTEX_LOCK (cairo_ft_unscaled_font_map_mutex); if (cairo_ft_unscaled_font_map == NULL) { _cairo_ft_unscaled_font_map_create (); if (cairo_ft_unscaled_font_map == NULL) { - CAIRO_MUTEX_UNLOCK (_cairo_ft_unscaled_font_map_mutex); + CAIRO_MUTEX_UNLOCK (cairo_ft_unscaled_font_map_mutex); return NULL; } } @@ -271,7 +268,7 @@ _cairo_ft_unscaled_font_map_lock (void) static void _cairo_ft_unscaled_font_map_unlock (void) { - CAIRO_MUTEX_UNLOCK (_cairo_ft_unscaled_font_map_mutex); + CAIRO_MUTEX_UNLOCK (cairo_ft_unscaled_font_map_mutex); } static void @@ -340,8 +337,7 @@ _cairo_ft_unscaled_font_init (cairo_ft_unscaled_font_t *unscaled, } unscaled->have_scale = FALSE; - CAIRO_MUTEX_INIT (&unscaled->mutex); - unscaled->lock_count = 0; + unscaled->lock = 0; unscaled->faces = NULL; @@ -374,8 +370,6 @@ _cairo_ft_unscaled_font_fini (cairo_ft_unscaled_font_t *unscaled) free (unscaled->filename); unscaled->filename = NULL; } - - CAIRO_MUTEX_FINI (&unscaled->mutex); } static int @@ -507,7 +501,7 @@ _has_unlocked_face (void *entry) { cairo_ft_unscaled_font_t *unscaled = entry; - return (unscaled->lock_count == 0 && unscaled->face); + return (unscaled->lock == 0 && unscaled->face); } /* Ensures that an unscaled font has a face object. If we exceed @@ -522,47 +516,44 @@ _cairo_ft_unscaled_font_lock_face (cairo_ft_unscaled_font_t *unscaled) cairo_ft_unscaled_font_map_t *font_map; FT_Face face = NULL; - CAIRO_MUTEX_LOCK (unscaled->mutex); - unscaled->lock_count++; - - if (unscaled->face) + if (unscaled->face) { + unscaled->lock++; return unscaled->face; + } /* If this unscaled font was created from an FT_Face then we just * returned it above. */ assert (!unscaled->from_face); font_map = _cairo_ft_unscaled_font_map_lock (); + assert (font_map != NULL); + + while (font_map->num_open_faces >= MAX_OPEN_FACES) { - assert (font_map != NULL); + cairo_ft_unscaled_font_t *entry; - while (font_map->num_open_faces >= MAX_OPEN_FACES) - { - cairo_ft_unscaled_font_t *entry; + entry = _cairo_hash_table_random_entry (font_map->hash_table, + _has_unlocked_face); + if (entry == NULL) + break; - entry = _cairo_hash_table_random_entry (font_map->hash_table, - _has_unlocked_face); - if (entry == NULL) - break; - - _font_map_release_face_lock_held (font_map, entry); - } + _font_map_release_face_lock_held (font_map, entry); } - _cairo_ft_unscaled_font_map_unlock (); if (FT_New_Face (font_map->ft_library, unscaled->filename, unscaled->id, &face) != FT_Err_Ok) - { - CAIRO_MUTEX_UNLOCK (unscaled->mutex); - return NULL; - } + goto FAIL; unscaled->face = face; + unscaled->lock++; font_map->num_open_faces++; + FAIL: + _cairo_ft_unscaled_font_map_unlock (); + return face; } slim_hidden_def (cairo_ft_scaled_font_lock_face); @@ -572,11 +563,9 @@ slim_hidden_def (cairo_ft_scaled_font_lock_face); void _cairo_ft_unscaled_font_unlock_face (cairo_ft_unscaled_font_t *unscaled) { - assert (unscaled->lock_count > 0); + assert (unscaled->lock > 0); - unscaled->lock_count--; - - CAIRO_MUTEX_UNLOCK (unscaled->mutex); + unscaled->lock--; } slim_hidden_def (cairo_ft_scaled_font_unlock_face); @@ -658,7 +647,6 @@ _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) { -#ifndef MOZILLA_CAIRO_NOT_DEFINED double x_scale = sf.x_scale; double y_scale = sf.y_scale; if (x_scale > MAX_FONT_SIZE) { @@ -668,16 +656,10 @@ _cairo_ft_unscaled_font_set_scale (cairo_ft_unscaled_font_t *unscaled, y_scale = MAX_FONT_SIZE; } - error = FT_Set_Char_Size (unscaled->face, - sf.x_scale * 64.0, - sf.y_scale * 64.0, - 0, 0); -#else error = FT_Set_Char_Size (unscaled->face, x_scale * 64.0, y_scale * 64.0, 0, 0); -#endif /* MOZCAIRO */ assert (error == 0); } else { double min_distance = DBL_MAX; @@ -1519,8 +1501,6 @@ _cairo_ft_scaled_font_create (cairo_ft_unscaled_font_t *unscaled, _cairo_scaled_font_set_metrics (&scaled_font->base, &fs_metrics); - _cairo_ft_unscaled_font_unlock_face (unscaled); - return &scaled_font->base; } @@ -1800,13 +1780,10 @@ _cairo_ft_scaled_glyph_init (void *abstract_font, cairo_bool_t vertical_layout = FALSE; cairo_status_t status = CAIRO_STATUS_SUCCESS; - face = _cairo_ft_unscaled_font_lock_face (unscaled); + face = cairo_ft_scaled_font_lock_face (abstract_font); if (!face) return CAIRO_STATUS_NO_MEMORY; - _cairo_ft_unscaled_font_set_scale (scaled_font->unscaled, - &scaled_font->base.scale); - /* Ignore global advance unconditionally */ load_flags |= FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH; @@ -1846,8 +1823,6 @@ _cairo_ft_scaled_glyph_init (void *abstract_font, _cairo_ft_scaled_glyph_vertical_layout_bearing_fix (scaled_font, glyph); if (info & CAIRO_SCALED_GLYPH_INFO_METRICS) { - - cairo_bool_t hint_metrics = scaled_font->base.options.hint_metrics != CAIRO_HINT_METRICS_OFF; /* * Compute font-space metrics */ @@ -1873,7 +1848,8 @@ _cairo_ft_scaled_glyph_init (void *abstract_font, * FreeType, then we need to do the metric hinting ourselves. */ - if (hint_metrics && (load_flags & FT_LOAD_NO_HINTING)) + if ((scaled_font->base.options.hint_metrics != CAIRO_HINT_METRICS_OFF) && + (load_flags & FT_LOAD_NO_HINTING)) { FT_Pos x1, x2; FT_Pos y1, y2; @@ -1920,20 +1896,14 @@ _cairo_ft_scaled_glyph_init (void *abstract_font, fs_metrics.x_bearing = DOUBLE_FROM_26_6 (metrics->horiBearingX) * x_factor; fs_metrics.y_bearing = DOUBLE_FROM_26_6 (-metrics->horiBearingY) * y_factor; - if (hint_metrics || glyph->format != FT_GLYPH_FORMAT_OUTLINE) - fs_metrics.x_advance = DOUBLE_FROM_26_6 (metrics->horiAdvance) * x_factor; - else - fs_metrics.x_advance = DOUBLE_FROM_16_16 (glyph->linearHoriAdvance) * x_factor; + fs_metrics.x_advance = DOUBLE_FROM_26_6 (metrics->horiAdvance) * x_factor; fs_metrics.y_advance = 0 * y_factor; } else { fs_metrics.x_bearing = DOUBLE_FROM_26_6 (metrics->vertBearingX) * x_factor; fs_metrics.y_bearing = DOUBLE_FROM_26_6 (metrics->vertBearingY) * y_factor; fs_metrics.x_advance = 0 * x_factor; - if (hint_metrics || glyph->format != FT_GLYPH_FORMAT_OUTLINE) - fs_metrics.y_advance = DOUBLE_FROM_26_6 (metrics->vertAdvance) * y_factor; - else - fs_metrics.y_advance = DOUBLE_FROM_26_6 (glyph->linearVertAdvance) * y_factor; + fs_metrics.y_advance = DOUBLE_FROM_26_6 (metrics->vertAdvance) * y_factor; } } @@ -1976,7 +1946,7 @@ _cairo_ft_scaled_glyph_init (void *abstract_font, load_flags | FT_LOAD_NO_BITMAP); if (error) { - _cairo_ft_unscaled_font_unlock_face (unscaled); + cairo_ft_scaled_font_unlock_face (abstract_font); return CAIRO_STATUS_NO_MEMORY; } #if HAVE_FT_GLYPHSLOT_EMBOLDEN @@ -2004,7 +1974,7 @@ _cairo_ft_scaled_glyph_init (void *abstract_font, path); } FAIL: - _cairo_ft_unscaled_font_unlock_face (unscaled); + cairo_ft_scaled_font_unlock_face (abstract_font); return status; } @@ -2056,38 +2026,6 @@ _cairo_ft_load_truetype_table (void *abstract_font, return status; } -static void -_cairo_ft_map_glyphs_to_unicode (void *abstract_font, - cairo_scaled_font_subset_t *font_subset) -{ - cairo_ft_scaled_font_t *scaled_font = abstract_font; - cairo_ft_unscaled_font_t *unscaled = scaled_font->unscaled; - FT_Face face; - FT_UInt glyph; - unsigned long charcode; - unsigned int i; - int count; - - face = _cairo_ft_unscaled_font_lock_face (unscaled); - if (!face) - return; - - count = font_subset->num_glyphs; - charcode = FT_Get_First_Char( face, &glyph); - while (glyph != 0 && count > 0) - { - for (i = 0; i < font_subset->num_glyphs; i++) { - if (font_subset->glyphs[i] == glyph) { - font_subset->to_unicode[i] = charcode; - count--; - break; - } - } - charcode = FT_Get_Next_Char(face, charcode, &glyph); - } - _cairo_ft_unscaled_font_unlock_face (unscaled); -} - const cairo_scaled_font_backend_t cairo_ft_scaled_font_backend = { CAIRO_FONT_TYPE_FT, _cairo_ft_scaled_font_create_toy, @@ -2097,7 +2035,6 @@ const cairo_scaled_font_backend_t cairo_ft_scaled_font_backend = { _cairo_ft_ucs4_to_index, NULL, /* show_glyphs */ _cairo_ft_load_truetype_table, - _cairo_ft_map_glyphs_to_unicode, }; /* cairo_ft_font_face_t */ @@ -2455,14 +2392,13 @@ cairo_ft_font_face_create_for_ft_face (FT_Face face, * of times. * * You must be careful when using this function in a library or in a - * threaded application, because freetype's design makes it unsafe to - * call freetype functions simultaneously from multiple threads, (even - * if using distinct FT_Face objects). Because of this, application - * code that acquires an FT_Face object with this call must add it's - * own locking to protect any use of that object, (and which also must - * protect any other calls into cairo as almost any cairo function - * might result in a call into the freetype library). - * + * threaded application, because other threads may lock faces that + * share the same #FT_Face object. For this reason, you must call + * cairo_ft_lock() before locking any face objects, and + * cairo_ft_unlock() after you are done. (These functions are not yet + * implemented, so this function cannot be currently safely used in a + * threaded application.) + * Return value: The #FT_Face object for @font, scaled appropriately, * or %NULL if @scaled_font is in an error state (see * cairo_scaled_font_status()) or there is insufficient memory. @@ -2485,14 +2421,6 @@ cairo_ft_scaled_font_lock_face (cairo_scaled_font_t *abstract_font) _cairo_ft_unscaled_font_set_scale (scaled_font->unscaled, &scaled_font->base.scale); - /* NOTE: We deliberately release the unscaled font's mutex here, - * so that we are not holding a lock across two separate calls to - * cairo function, (which would give the application some - * opportunity for creating deadlock. This is obviously unsafe, - * but as documented, the user must add manual locking when using - * this function. */ - CAIRO_MUTEX_UNLOCK (scaled_font->unscaled->mutex); - return face; } @@ -2513,12 +2441,6 @@ cairo_ft_scaled_font_unlock_face (cairo_scaled_font_t *abstract_font) if (scaled_font->base.status) return; - /* NOTE: We released the unscaled font's mutex at the end of - * cairo_ft_scaled_font_lock_face, so we have to acquire it again - * as _cairo_ft_unscaled_font_unlock_face expects it to be held - * when we call into it. */ - CAIRO_MUTEX_LOCK (scaled_font->unscaled->mutex); - _cairo_ft_unscaled_font_unlock_face (scaled_font->unscaled); } diff --git a/gfx/cairo/cairo/src/cairo-glitz-surface.c b/gfx/cairo/cairo/src/cairo-glitz-surface.c index b9e4f72d2b7..f492739177c 100644 --- a/gfx/cairo/cairo/src/cairo-glitz-surface.c +++ b/gfx/cairo/cairo/src/cairo-glitz-surface.c @@ -594,7 +594,7 @@ _cairo_glitz_pattern_acquire_surface (cairo_pattern_t *pattern, unsigned int *pixels; unsigned int i, n_base_params; glitz_buffer_t *buffer; - static const glitz_pixel_format_t format = { + static glitz_pixel_format_t format = { GLITZ_FOURCC_RGB, { 32, @@ -686,12 +686,12 @@ _cairo_glitz_pattern_acquire_surface (cairo_pattern_t *pattern, { cairo_radial_pattern_t *grad = (cairo_radial_pattern_t *) pattern; - params[0] = grad->gradient.c1.x; - params[1] = grad->gradient.c1.y; - params[2] = grad->gradient.c1.radius; - params[3] = grad->gradient.c2.x; - params[4] = grad->gradient.c2.y; - params[5] = grad->gradient.c2.radius; + params[0] = grad->gradient.inner.x; + params[1] = grad->gradient.inner.y; + params[2] = grad->gradient.inner.radius; + params[3] = grad->gradient.outer.x; + params[4] = grad->gradient.outer.y; + params[5] = grad->gradient.outer.radius; attr->filter = GLITZ_FILTER_RADIAL_GRADIENT; } @@ -976,7 +976,7 @@ _cairo_glitz_surface_fill_rectangles (void *abstract_dst, (glitz_rectangle_t *) rects, n_rects); } break; case CAIRO_OPERATOR_CLEAR: { - static const glitz_color_t glitz_color = { 0, 0, 0, 0 }; + static glitz_color_t glitz_color = { 0, 0, 0, 0 }; glitz_set_rectangles (dst->surface, &glitz_color, (glitz_rectangle_t *) rects, n_rects); @@ -1095,7 +1095,7 @@ _cairo_glitz_surface_composite_trapezoids (cairo_operator_t op, if (op == CAIRO_OPERATOR_ADD || n_traps <= 1) { - static const glitz_color_t clear_black = { 0, 0, 0, 0 }; + static glitz_color_t clear_black = { 0, 0, 0, 0 }; glitz_color_t color; glitz_geometry_format_t format; int n_trap_added; @@ -1941,7 +1941,7 @@ _cairo_glitz_surface_old_show_glyphs (cairo_scaled_font_t *scaled_font, int i, cached_glyphs = 0; int remaining_glyps = num_glyphs; glitz_float_t x1, y1, x2, y2; - static const glitz_vertex_format_t format = { + static glitz_vertex_format_t format = { GLITZ_PRIMITIVE_QUADS, GLITZ_DATA_TYPE_FLOAT, sizeof (glitz_float_t) * 4, diff --git a/gfx/cairo/cairo/src/cairo-gstate.c b/gfx/cairo/cairo/src/cairo-gstate.c index b75a90baab7..a740d868cca 100644 --- a/gfx/cairo/cairo/src/cairo-gstate.c +++ b/gfx/cairo/cairo/src/cairo-gstate.c @@ -42,9 +42,16 @@ #include "cairo-clip-private.h" #include "cairo-gstate-private.h" +static cairo_status_t +_cairo_gstate_init (cairo_gstate_t *gstate, + cairo_surface_t *target); + static cairo_status_t _cairo_gstate_init_copy (cairo_gstate_t *gstate, cairo_gstate_t *other); +static void +_cairo_gstate_fini (cairo_gstate_t *gstate); + static cairo_status_t _cairo_gstate_ensure_font_face (cairo_gstate_t *gstate); @@ -60,7 +67,40 @@ _cairo_gstate_transform_glyphs_to_backend (cairo_gstate_t *gstate, int num_glyphs, cairo_glyph_t *transformed_glyphs); -cairo_status_t +/** + * _cairo_gstate_create: + * @target: a #cairo_surface_t, not NULL + * + * Create a new #cairo_gstate_t to draw to target with all graphics + * state parameters set to defaults. gstate->next will be set to NULL + * and may be used by the caller to chain #cairo_gstate_t objects + * together. + * + * Return value: a new #cairo_gstate_t or NULL if there is + * insufficient memory. + **/ +cairo_gstate_t * +_cairo_gstate_create (cairo_surface_t *target) +{ + cairo_status_t status; + cairo_gstate_t *gstate; + + assert (target != NULL); + + gstate = malloc (sizeof (cairo_gstate_t)); + if (gstate == NULL) + return NULL; + + status = _cairo_gstate_init (gstate, target); + if (status) { + free (gstate); + return NULL; + } + + return gstate; +} + +static cairo_status_t _cairo_gstate_init (cairo_gstate_t *gstate, cairo_surface_t *target) { @@ -149,7 +189,7 @@ _cairo_gstate_init_copy (cairo_gstate_t *gstate, cairo_gstate_t *other) return CAIRO_STATUS_SUCCESS; } -void +static void _cairo_gstate_fini (cairo_gstate_t *gstate) { _cairo_stroke_style_fini (&gstate->stroke_style); @@ -682,8 +722,8 @@ _cairo_gstate_backend_to_user_rectangle (cairo_gstate_t *gstate, cairo_matrix_multiply (&matrix_inverse, &gstate->ctm_inverse, &gstate->target->device_transform_inverse); - _cairo_matrix_transform_bounding_box (&matrix_inverse, - x1, y1, x2, y2, is_tight); + cairo_matrix_transform_bounding_box (&matrix_inverse, + x1, y1, x2, y2, is_tight); } /* XXX: NYI @@ -915,11 +955,6 @@ _cairo_gstate_in_stroke (cairo_gstate_t *gstate, cairo_status_t status = CAIRO_STATUS_SUCCESS; cairo_traps_t traps; - if (gstate->stroke_style.line_width <= 0.0) { - *inside_ret = FALSE; - return CAIRO_STATUS_SUCCESS; - } - _cairo_gstate_user_to_backend (gstate, &x, &y); _cairo_traps_init (&traps); @@ -1038,23 +1073,12 @@ _cairo_gstate_traps_extents_to_user_rectangle (cairo_gstate_t *gstate, if (extents.p1.x >= extents.p2.x || extents.p1.y >= extents.p2.y) { /* no traps, so we actually won't draw anything */ - if (x1) - *x1 = 0.0; - if (y1) - *y1 = 0.0; - if (x2) - *x2 = 0.0; - if (y2) - *y2 = 0.0; + *x1 = *y1 = *x2 = *y2 = 0; } else { - if (x1) - *x1 = _cairo_fixed_to_double (extents.p1.x); - if (y1) - *y1 = _cairo_fixed_to_double (extents.p1.y); - if (x2) - *x2 = _cairo_fixed_to_double (extents.p2.x); - if (y2) - *y2 = _cairo_fixed_to_double (extents.p2.y); + *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); } @@ -1069,18 +1093,6 @@ _cairo_gstate_stroke_extents (cairo_gstate_t *gstate, cairo_status_t status; cairo_traps_t traps; - if (gstate->stroke_style.line_width <= 0.0) { - if (x1) - *x1 = 0.0; - if (y1) - *y1 = 0.0; - if (x2) - *x2 = 0.0; - if (y2) - *y2 = 0.0; - return CAIRO_STATUS_SUCCESS; - } - _cairo_traps_init (&traps); status = _cairo_path_fixed_stroke_to_traps (path, @@ -1153,15 +1165,11 @@ _cairo_gstate_clip_extents (cairo_gstate_t *gstate, status = _cairo_clip_intersect_to_rectangle (&gstate->clip, &extents); if (status) return status; - - if (x1) - *x1 = extents.x; - if (y1) - *y1 = extents.y; - if (x2) - *x2 = extents.x + extents.width; - if (y2) - *y2 = extents.y + extents.height; + + *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); @@ -1263,21 +1271,6 @@ _cairo_gstate_get_font_face (cairo_gstate_t *gstate, return CAIRO_STATUS_SUCCESS; } -cairo_status_t -_cairo_gstate_get_scaled_font (cairo_gstate_t *gstate, - cairo_scaled_font_t **scaled_font) -{ - cairo_status_t status; - - status = _cairo_gstate_ensure_scaled_font (gstate); - if (status) - return status; - - *scaled_font = gstate->scaled_font; - - return CAIRO_STATUS_SUCCESS; -} - /* * Like everything else in this file, fonts involve Too Many Coordinate Spaces; * it is easy to get confused about what's going on. diff --git a/gfx/cairo/cairo/src/cairo-image-surface.c b/gfx/cairo/cairo/src/cairo-image-surface.c index 627901216b0..1b5215f9b8f 100644 --- a/gfx/cairo/cairo/src/cairo-image-surface.c +++ b/gfx/cairo/cairo/src/cairo-image-surface.c @@ -1116,7 +1116,6 @@ _cairo_image_surface_clone (cairo_image_surface_t *surface, cairo_image_surface_create (format, surface->width, surface->height); - /* Use _cairo_surface_composite directly */ cr = cairo_create (&clone->base); cairo_surface_get_device_offset (&surface->base, &x, &y); cairo_set_source_surface (cr, &surface->base, x, y); diff --git a/gfx/cairo/cairo/src/cairo-matrix.c b/gfx/cairo/cairo/src/cairo-matrix.c index b689f2aaff7..0ad0ddeb9af 100644 --- a/gfx/cairo/cairo/src/cairo-matrix.c +++ b/gfx/cairo/cairo/src/cairo-matrix.c @@ -356,10 +356,10 @@ cairo_matrix_transform_point (const cairo_matrix_t *matrix, double *x, double *y slim_hidden_def(cairo_matrix_transform_point); void -_cairo_matrix_transform_bounding_box (const cairo_matrix_t *matrix, - double *x1, double *y1, - double *x2, double *y2, - cairo_bool_t *is_tight) +cairo_matrix_transform_bounding_box (const cairo_matrix_t *matrix, + double *x1, double *y1, + double *x2, double *y2, + cairo_bool_t *is_tight) { int i; double quad_x[4], quad_y[4]; @@ -417,6 +417,7 @@ _cairo_matrix_transform_bounding_box (const cairo_matrix_t *matrix, quad_x[2] == quad_x[0] && quad_y[2] == quad_y[3]); } } +slim_hidden_def(cairo_matrix_transform_bounding_box); static void _cairo_matrix_scalar_multiply (cairo_matrix_t *matrix, double scalar) diff --git a/gfx/cairo/cairo/src/cairo-os2-surface.c b/gfx/cairo/cairo/src/cairo-os2-surface.c index f6ec8f6256c..92bd711c66d 100644 --- a/gfx/cairo/cairo/src/cairo-os2-surface.c +++ b/gfx/cairo/cairo/src/cairo-os2-surface.c @@ -69,11 +69,11 @@ static int cairo_os2_initialization_count = 0; /* The mutex semaphores Cairo uses all around: */ -HMTX _cairo_scaled_font_map_mutex = 0; +HMTX cairo_toy_font_face_hash_table_mutex = 0; +HMTX cairo_scaled_font_map_mutex = 0; HMTX _global_image_glyph_cache_mutex = 0; -HMTX _cairo_font_face_mutex = 0; #ifdef CAIRO_HAS_FT_FONT -HMTX _cairo_ft_unscaled_font_map_mutex = 0; +HMTX cairo_ft_unscaled_font_map_mutex = 0; #endif static void inline @@ -106,13 +106,13 @@ cairo_os2_init (void) /* Create the mutex semaphores we'll use! */ /* cairo-font.c: */ - DosCreateMutexSem (NULL, &_cairo_scaled_font_map_mutex, 0, FALSE); + 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); - DosCreateMutexSem (NULL, &_cairo_font_face_mutex, 0, FALSE); #ifdef CAIRO_HAS_FT_FONT /* cairo-ft-font.c: */ - DosCreateMutexSem (NULL, &_cairo_ft_unscaled_font_map_mutex, 0, FALSE); + DosCreateMutexSem (NULL, &cairo_ft_unscaled_font_map_mutex, 0, FALSE); #endif /* Initialize FontConfig */ @@ -139,24 +139,24 @@ cairo_os2_fini (void) /* Destroy the mutex semaphores we've created! */ /* cairo-font.c: */ - if (_cairo_scaled_font_map_mutex) { - DosCloseMutexSem (_cairo_scaled_font_map_mutex); - _cairo_scaled_font_map_mutex = 0; + 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; } - if (_cairo_font_face_mutex) { - DosCloseMutexSem (_cairo_font_face_mutex); - _cairo_font_face_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; + if (cairo_ft_unscaled_font_map_mutex) { + DosCloseMutexSem (cairo_ft_unscaled_font_map_mutex); + cairo_ft_unscaled_font_map_mutex = 0; } #endif diff --git a/gfx/cairo/cairo/src/cairo-os2.h b/gfx/cairo/cairo/src/cairo-os2.h index 6a6c04d5b8b..3e1b4aad482 100644 --- a/gfx/cairo/cairo/src/cairo-os2.h +++ b/gfx/cairo/cairo/src/cairo-os2.h @@ -194,8 +194,6 @@ cairo_os2_surface_set_manual_window_refresh (cairo_surface_t *surface, cairo_public cairo_bool_t cairo_os2_surface_get_manual_window_refresh (cairo_surface_t *surface); -#else /* CAIRO_HAS_OS2_SURFACE */ -# error Cairo was not compiled with support for the OS/2 backend #endif /* CAIRO_HAS_OS2_SURFACE */ CAIRO_END_DECLS diff --git a/gfx/cairo/cairo/src/cairo-output-stream.c b/gfx/cairo/cairo/src/cairo-output-stream.c index df3ae4d4334..f9e527f33c1 100644 --- a/gfx/cairo/cairo/src/cairo-output-stream.c +++ b/gfx/cairo/cairo/src/cairo-output-stream.c @@ -224,10 +224,6 @@ _cairo_dtostr (char *buffer, size_t size, double d) char *p; int decimal_len; - /* Omit the minus sign from negative zero. */ - if (d == 0.0) - d = 0.0; - snprintf (buffer, size, "%f", d); locale_data = localeconv (); diff --git a/gfx/cairo/cairo/src/cairo-paginated-surface.c b/gfx/cairo/cairo/src/cairo-paginated-surface.c index c8e46124f99..b313ac1f518 100644 --- a/gfx/cairo/cairo/src/cairo-paginated-surface.c +++ b/gfx/cairo/cairo/src/cairo-paginated-surface.c @@ -70,7 +70,6 @@ typedef struct _cairo_paginated_surface { * fallbacks. */ cairo_surface_t *meta; - int page_num; cairo_bool_t page_is_blank; } cairo_paginated_surface_t; @@ -123,7 +122,6 @@ _cairo_paginated_surface_create (cairo_surface_t *target, if (cairo_surface_status (surface->meta)) goto FAIL_CLEANUP_SURFACE; - surface->page_num = 1; surface->page_is_blank = TRUE; return &surface->base; @@ -157,22 +155,12 @@ static cairo_status_t _cairo_paginated_surface_finish (void *abstract_surface) { cairo_paginated_surface_t *surface = abstract_surface; - cairo_status_t status = CAIRO_STATUS_SUCCESS; - - if (surface->page_is_blank == FALSE || surface->page_num == 1) - status = _cairo_paginated_surface_show_page (abstract_surface); - - if (status == CAIRO_STATUS_SUCCESS) - cairo_surface_finish (surface->target); - - if (status == CAIRO_STATUS_SUCCESS) - cairo_surface_finish (surface->meta); - - cairo_surface_destroy (surface->target); cairo_surface_destroy (surface->meta); - return status; + cairo_surface_destroy (surface->target); + + return CAIRO_STATUS_SUCCESS; } static cairo_surface_t * @@ -300,8 +288,6 @@ _cairo_paginated_surface_copy_page (void *abstract_surface) _paint_page (surface); - surface->page_num++; - /* XXX: It might make sense to add some suport here for calling * _cairo_surface_copy_page on the target surface. It would be an * optimization for the output, (so that PostScript could include @@ -310,7 +296,9 @@ _cairo_paginated_surface_copy_page (void *abstract_surface) * show_page and we implement the copying by simply not destroying * the meta-surface. */ - return _cairo_surface_show_page (surface->target); + _cairo_surface_show_page (surface->target); + + return CAIRO_STATUS_SUCCESS; } static cairo_int_status_t @@ -334,7 +322,6 @@ _cairo_paginated_surface_show_page (void *abstract_surface) if (cairo_surface_status (surface->meta)) return cairo_surface_status (surface->meta); - surface->page_num++; surface->page_is_blank = TRUE; return CAIRO_STATUS_SUCCESS; @@ -455,7 +442,6 @@ _cairo_paginated_surface_show_glyphs (void *abstract_surface, cairo_scaled_font_t *scaled_font) { cairo_paginated_surface_t *surface = abstract_surface; - cairo_int_status_t status; /* Optimize away erasing of nothing. */ if (surface->page_is_blank && op == CAIRO_OPERATOR_CLEAR) @@ -463,23 +449,9 @@ _cairo_paginated_surface_show_glyphs (void *abstract_surface, surface->page_is_blank = FALSE; - /* Since this is a "wrapping" surface, we're calling back into - * _cairo_surface_show_glyphs from within a call to the same. - * Since _cairo_surface_show_glyphs acquires a mutex, we release - * and re-acquire the mutex around this nested call. - * - * Yes, this is ugly, but we consider it pragmatic as compared to - * adding locking code to all 18 surface-backend-specific - * show_glyphs functions, (which would get less testing and likely - * lead to bugs). - */ - CAIRO_MUTEX_UNLOCK (scaled_font->mutex); - status = _cairo_surface_show_glyphs (surface->meta, op, source, - glyphs, num_glyphs, - scaled_font); - CAIRO_MUTEX_LOCK (scaled_font->mutex); - - return status; + return _cairo_surface_show_glyphs (surface->meta, op, source, + glyphs, num_glyphs, + scaled_font); } static cairo_surface_t * diff --git a/gfx/cairo/cairo/src/cairo-path-fill.c b/gfx/cairo/cairo/src/cairo-path-fill.c index b1b7a120d27..7377960f8b6 100644 --- a/gfx/cairo/cairo/src/cairo-path-fill.c +++ b/gfx/cairo/cairo/src/cairo-path-fill.c @@ -35,7 +35,6 @@ */ #include "cairoint.h" -#include "cairo-path-fixed-private.h" typedef struct cairo_filler { double tolerance; @@ -170,10 +169,6 @@ _cairo_filler_close_path (void *closure) return CAIRO_STATUS_SUCCESS; } -static cairo_int_status_t -_cairo_path_fixed_fill_rectangle (cairo_path_fixed_t *path, - cairo_traps_t *traps); - cairo_status_t _cairo_path_fixed_fill_to_traps (cairo_path_fixed_t *path, cairo_fill_rule_t fill_rule, @@ -183,12 +178,6 @@ _cairo_path_fixed_fill_to_traps (cairo_path_fixed_t *path, cairo_status_t status = CAIRO_STATUS_SUCCESS; cairo_filler_t filler; - /* Before we do anything else, we use a special-case filler for - * a device-axis aligned rectangle if possible. */ - status = _cairo_path_fixed_fill_rectangle (path, traps); - if (status != CAIRO_INT_STATUS_UNSUPPORTED) - return status; - _cairo_filler_init (&filler, tolerance, traps); status = _cairo_path_fixed_interpret (path, @@ -216,84 +205,3 @@ BAIL: return status; } - -/* This special-case filler supports only a path that describes a - * device-axis aligned rectangle. It exists to avoid the overhead of - * the general tessellator when drawing very common rectangles. - * - * If the path described anything but a device-axis aligned rectangle, - * this function will return CAIRO_INT_STATUS_UNSUPPORTED. - */ -static cairo_int_status_t -_cairo_path_fixed_fill_rectangle (cairo_path_fixed_t *path, - cairo_traps_t *traps) -{ - cairo_path_buf_t *buf = path->buf_head; - int final; - - /* Ensure the path has the operators we expect for a rectangular path. - */ - if (buf == NULL || buf->num_ops < 5) - return CAIRO_INT_STATUS_UNSUPPORTED; - - if (buf->op[0] != CAIRO_PATH_OP_MOVE_TO || - buf->op[1] != CAIRO_PATH_OP_LINE_TO || - buf->op[2] != CAIRO_PATH_OP_LINE_TO || - buf->op[3] != CAIRO_PATH_OP_LINE_TO) - { - return CAIRO_INT_STATUS_UNSUPPORTED; - } - - /* Now, there are choices. The rectangle might end with a LINE_TO - * (to the original point), but this isn't required. If it - * doesn't, then it must end with a CLOSE_PATH. */ - if (buf->op[4] == CAIRO_PATH_OP_LINE_TO) { - if (buf->points[4].x != buf->points[0].x || - buf->points[4].y != buf->points[0].y) - { - return CAIRO_INT_STATUS_UNSUPPORTED; - } - } else if (buf->op[4] != CAIRO_PATH_OP_CLOSE_PATH) { - return CAIRO_INT_STATUS_UNSUPPORTED; - } - - /* Finally, a trailing CLOSE_PATH or MOVE_TO after the rectangle - * is fine. But anything more than that means we must return - * unsupported. */ - final = 5; - if (final < buf->num_ops && - buf->op[final] == CAIRO_PATH_OP_CLOSE_PATH) - { - final++; - } - if (final < buf->num_ops && - buf->op[final] == CAIRO_PATH_OP_MOVE_TO) - { - final++; - } - if (final < buf->num_ops) - return CAIRO_INT_STATUS_UNSUPPORTED; - - /* Now that we've verified the operators, we must ensure that the - * path coordinates are consistent with a rectangle. There are two - * choices here. */ - if (buf->points[0].y == buf->points[1].y && - buf->points[1].x == buf->points[2].x && - buf->points[2].y == buf->points[3].y && - buf->points[3].x == buf->points[0].x) - { - return _cairo_traps_tessellate_convex_quad (traps, - buf->points); - } - - if (buf->points[0].x == buf->points[1].x && - buf->points[1].y == buf->points[2].y && - buf->points[2].x == buf->points[3].x && - buf->points[3].y == buf->points[0].y) - { - return _cairo_traps_tessellate_convex_quad (traps, - buf->points); - } - - return CAIRO_INT_STATUS_UNSUPPORTED; -} diff --git a/gfx/cairo/cairo/src/cairo-path-fixed-private.h b/gfx/cairo/cairo/src/cairo-path-fixed-private.h index 65401f34911..12ca6186c3e 100644 --- a/gfx/cairo/cairo/src/cairo-path-fixed-private.h +++ b/gfx/cairo/cairo/src/cairo-path-fixed-private.h @@ -42,30 +42,34 @@ typedef enum cairo_path_op { CAIRO_PATH_OP_CURVE_TO = 2, CAIRO_PATH_OP_CLOSE_PATH = 3 } __attribute__ ((packed)) cairo_path_op_t; /* Don't want 32 bits if we can avoid it. */ -/* XXX Shall we just not use char instead of hoping for __attribute__ working? */ -/* make cairo_path_fixed fit a 512 bytes. about 50 items */ -#define CAIRO_PATH_BUF_SIZE ((512 - 12 * sizeof (void*)) \ - / (sizeof (cairo_point_t) + sizeof (cairo_path_op_t))) +#define CAIRO_PATH_BUF_SIZE 64 -typedef struct _cairo_path_buf { - struct _cairo_path_buf *next, *prev; +typedef struct _cairo_path_op_buf { int num_ops; - int num_points; - cairo_path_op_t op[CAIRO_PATH_BUF_SIZE]; + + struct _cairo_path_op_buf *next, *prev; +} cairo_path_op_buf_t; + +typedef struct _cairo_path_arg_buf { + int num_points; cairo_point_t points[CAIRO_PATH_BUF_SIZE]; -} cairo_path_buf_t; + struct _cairo_path_arg_buf *next, *prev; +} cairo_path_arg_buf_t; struct _cairo_path_fixed { + cairo_path_op_buf_t *op_buf_head; + cairo_path_op_buf_t *op_buf_tail; + + cairo_path_arg_buf_t *arg_buf_head; + cairo_path_arg_buf_t *arg_buf_tail; + cairo_point_t last_move_point; cairo_point_t current_point; unsigned int has_current_point : 1; unsigned int has_curve_to : 1; - - cairo_path_buf_t *buf_tail; - cairo_path_buf_t buf_head[1]; }; #endif /* CAIRO_PATH_FIXED_PRIVATE_H */ diff --git a/gfx/cairo/cairo/src/cairo-path-fixed.c b/gfx/cairo/cairo/src/cairo-path-fixed.c index 4845ada2175..3505c668bbb 100644 --- a/gfx/cairo/cairo/src/cairo-path-fixed.c +++ b/gfx/cairo/cairo/src/cairo-path-fixed.c @@ -48,33 +48,42 @@ _cairo_path_fixed_add (cairo_path_fixed_t *path, int num_points); static void -_cairo_path_fixed_add_buf (cairo_path_fixed_t *path, - cairo_path_buf_t *buf); - -static cairo_path_buf_t * -_cairo_path_buf_create (void); +_cairo_path_fixed_add_op_buf (cairo_path_fixed_t *path, + cairo_path_op_buf_t *op_buf); static void -_cairo_path_buf_destroy (cairo_path_buf_t *buf); +_cairo_path_fixed_add_arg_buf (cairo_path_fixed_t *path, + cairo_path_arg_buf_t *arg_buf); + +static cairo_path_op_buf_t * +_cairo_path_op_buf_create (void); static void -_cairo_path_buf_add_op (cairo_path_buf_t *buf, - cairo_path_op_t op); +_cairo_path_op_buf_destroy (cairo_path_op_buf_t *op_buf); static void -_cairo_path_buf_add_points (cairo_path_buf_t *buf, - cairo_point_t *points, - int num_points); +_cairo_path_op_buf_add_op (cairo_path_op_buf_t *op_buf, + cairo_path_op_t op); + +static cairo_path_arg_buf_t * +_cairo_path_arg_buf_create (void); + +static void +_cairo_path_arg_buf_destroy (cairo_path_arg_buf_t *arg_buf); + +static void +_cairo_path_arg_buf_add_points (cairo_path_arg_buf_t *arg_buf, + cairo_point_t *points, + int num_points); void _cairo_path_fixed_init (cairo_path_fixed_t *path) { - path->buf_head->next = NULL; - path->buf_head->prev = NULL; - path->buf_tail = path->buf_head; + path->op_buf_head = NULL; + path->op_buf_tail = NULL; - path->buf_head->num_ops = 0; - path->buf_head->num_points = 0; + path->arg_buf_head = NULL; + path->arg_buf_tail = NULL; path->current_point.x = 0; path->current_point.y = 0; @@ -87,7 +96,8 @@ cairo_status_t _cairo_path_fixed_init_copy (cairo_path_fixed_t *path, cairo_path_fixed_t *other) { - cairo_path_buf_t *buf, *other_buf; + cairo_path_op_buf_t *op_buf, *other_op_buf; + cairo_path_arg_buf_t *arg_buf, *other_arg_buf; _cairo_path_fixed_init (path); path->current_point = other->current_point; @@ -95,23 +105,30 @@ _cairo_path_fixed_init_copy (cairo_path_fixed_t *path, path->has_curve_to = other->has_curve_to; path->last_move_point = other->last_move_point; - path->buf_head->num_ops = other->buf_head->num_ops; - path->buf_head->num_points = other->buf_head->num_points; - memcpy (path->buf_head->op, other->buf_head->op, - other->buf_head->num_ops * sizeof (other->buf_head->op[0])); - memcpy (path->buf_head->points, other->buf_head->points, - other->buf_head->num_points * sizeof (other->buf_head->points[0])); - for (other_buf = other->buf_head->next; - other_buf; - other_buf = other_buf->next) + for (other_op_buf = other->op_buf_head; + other_op_buf; + other_op_buf = other_op_buf->next) { - buf = _cairo_path_buf_create (); - if (buf == NULL) { + op_buf = _cairo_path_op_buf_create (); + if (op_buf == NULL) { _cairo_path_fixed_fini (path); return CAIRO_STATUS_NO_MEMORY; } - memcpy (buf, other_buf, sizeof (cairo_path_buf_t)); - _cairo_path_fixed_add_buf (path, buf); + memcpy (op_buf, other_op_buf, sizeof (cairo_path_op_buf_t)); + _cairo_path_fixed_add_op_buf (path, op_buf); + } + + for (other_arg_buf = other->arg_buf_head; + other_arg_buf; + other_arg_buf = other_arg_buf->next) + { + arg_buf = _cairo_path_arg_buf_create (); + if (arg_buf == NULL) { + _cairo_path_fixed_fini (path); + return CAIRO_STATUS_NO_MEMORY; + } + memcpy (arg_buf, other_arg_buf, sizeof (cairo_path_arg_buf_t)); + _cairo_path_fixed_add_arg_buf (path, arg_buf); } return CAIRO_STATUS_SUCCESS; @@ -131,19 +148,22 @@ _cairo_path_fixed_create (void) void _cairo_path_fixed_fini (cairo_path_fixed_t *path) { - cairo_path_buf_t *buf; + cairo_path_op_buf_t *op_buf; + cairo_path_arg_buf_t *arg_buf; - buf = path->buf_head->next; - while (buf) { - cairo_path_buf_t *this = buf; - buf = buf->next; - _cairo_path_buf_destroy (this); + while (path->op_buf_head) { + op_buf = path->op_buf_head; + path->op_buf_head = op_buf->next; + _cairo_path_op_buf_destroy (op_buf); } - path->buf_head->next = NULL; - path->buf_head->prev = NULL; - path->buf_tail = path->buf_head; - path->buf_head->num_ops = 0; - path->buf_head->num_points = 0; + path->op_buf_tail = NULL; + + while (path->arg_buf_head) { + arg_buf = path->arg_buf_head; + path->arg_buf_head = arg_buf->next; + _cairo_path_arg_buf_destroy (arg_buf); + } + path->arg_buf_tail = NULL; path->has_current_point = FALSE; path->has_curve_to = FALSE; @@ -169,11 +189,11 @@ _cairo_path_fixed_move_to (cairo_path_fixed_t *path, /* If the previous op was also a MOVE_TO, then just change its * point rather than adding a new op. */ - if (path->buf_tail && path->buf_tail->num_ops && - path->buf_tail->op[path->buf_tail->num_ops - 1] == CAIRO_PATH_OP_MOVE_TO) + if (path->op_buf_tail && path->op_buf_tail->num_ops && + path->op_buf_tail->op[path->op_buf_tail->num_ops - 1] == CAIRO_PATH_OP_MOVE_TO) { cairo_point_t *last_move_to_point; - last_move_to_point = &path->buf_tail->points[path->buf_tail->num_points - 1]; + last_move_to_point = &path->arg_buf_tail->points[path->arg_buf_tail->num_points - 1]; *last_move_to_point = point; } else { status = _cairo_path_fixed_add (path, CAIRO_PATH_OP_MOVE_TO, &point, 1); @@ -356,77 +376,133 @@ _cairo_path_fixed_add (cairo_path_fixed_t *path, cairo_point_t *points, int num_points) { - if (path->buf_tail->num_ops + 1 > CAIRO_PATH_BUF_SIZE || - path->buf_tail->num_points + num_points > CAIRO_PATH_BUF_SIZE) + if (path->op_buf_tail == NULL || + path->op_buf_tail->num_ops + 1 > CAIRO_PATH_BUF_SIZE) { - cairo_path_buf_t *buf; + cairo_path_op_buf_t *op_buf; - buf = _cairo_path_buf_create (); - if (buf == NULL) + op_buf = _cairo_path_op_buf_create (); + if (op_buf == NULL) return CAIRO_STATUS_NO_MEMORY; - _cairo_path_fixed_add_buf (path, buf); + _cairo_path_fixed_add_op_buf (path, op_buf); } - _cairo_path_buf_add_op (path->buf_tail, op); - _cairo_path_buf_add_points (path->buf_tail, points, num_points); + _cairo_path_op_buf_add_op (path->op_buf_tail, op); + + if (path->arg_buf_tail == NULL || + path->arg_buf_tail->num_points + num_points > CAIRO_PATH_BUF_SIZE) + { + cairo_path_arg_buf_t *arg_buf; + + arg_buf = _cairo_path_arg_buf_create (); + + if (arg_buf == NULL) + return CAIRO_STATUS_NO_MEMORY; + + _cairo_path_fixed_add_arg_buf (path, arg_buf); + } + + _cairo_path_arg_buf_add_points (path->arg_buf_tail, points, num_points); return CAIRO_STATUS_SUCCESS; } static void -_cairo_path_fixed_add_buf (cairo_path_fixed_t *path, - cairo_path_buf_t *buf) +_cairo_path_fixed_add_op_buf (cairo_path_fixed_t *path, + cairo_path_op_buf_t *op_buf) { - buf->next = NULL; - buf->prev = path->buf_tail; + op_buf->next = NULL; + op_buf->prev = path->op_buf_tail; - path->buf_tail->next = buf; - path->buf_tail = buf; -} - -static cairo_path_buf_t * -_cairo_path_buf_create (void) -{ - cairo_path_buf_t *buf; - - buf = malloc (sizeof (cairo_path_buf_t)); - - if (buf) { - buf->next = NULL; - buf->prev = NULL; - buf->num_ops = 0; - buf->num_points = 0; + if (path->op_buf_tail) { + path->op_buf_tail->next = op_buf; + } else { + path->op_buf_head = op_buf; } - return buf; + path->op_buf_tail = op_buf; } static void -_cairo_path_buf_destroy (cairo_path_buf_t *buf) +_cairo_path_fixed_add_arg_buf (cairo_path_fixed_t *path, + cairo_path_arg_buf_t *arg_buf) { - free (buf); + arg_buf->next = NULL; + arg_buf->prev = path->arg_buf_tail; + + if (path->arg_buf_tail) { + path->arg_buf_tail->next = arg_buf; + } else { + path->arg_buf_head = arg_buf; + } + + path->arg_buf_tail = arg_buf; } -static void -_cairo_path_buf_add_op (cairo_path_buf_t *buf, - cairo_path_op_t op) +static cairo_path_op_buf_t * +_cairo_path_op_buf_create (void) { - buf->op[buf->num_ops++] = op; + cairo_path_op_buf_t *op_buf; + + op_buf = malloc (sizeof (cairo_path_op_buf_t)); + + if (op_buf) { + op_buf->num_ops = 0; + op_buf->next = NULL; + } + + return op_buf; } static void -_cairo_path_buf_add_points (cairo_path_buf_t *buf, - cairo_point_t *points, - int num_points) +_cairo_path_op_buf_destroy (cairo_path_op_buf_t *op_buf) +{ + free (op_buf); +} + +static void +_cairo_path_op_buf_add_op (cairo_path_op_buf_t *op_buf, + cairo_path_op_t op) +{ + op_buf->op[op_buf->num_ops++] = op; +} + +static cairo_path_arg_buf_t * +_cairo_path_arg_buf_create (void) +{ + cairo_path_arg_buf_t *arg_buf; + + arg_buf = malloc (sizeof (cairo_path_arg_buf_t)); + + if (arg_buf) { + arg_buf->num_points = 0; + arg_buf->next = NULL; + } + + return arg_buf; +} + +static void +_cairo_path_arg_buf_destroy (cairo_path_arg_buf_t *arg_buf) +{ + free (arg_buf); +} + +static void +_cairo_path_arg_buf_add_points (cairo_path_arg_buf_t *arg_buf, + cairo_point_t *points, + int num_points) { int i; for (i=0; i < num_points; i++) { - buf->points[buf->num_points++] = points[i]; + arg_buf->points[arg_buf->num_points++] = points[i]; } } +#define CAIRO_PATH_OP_MAX_ARGS 3 + static int const num_args[] = { 1, /* cairo_path_move_to */ @@ -445,43 +521,61 @@ _cairo_path_fixed_interpret (cairo_path_fixed_t *path, void *closure) { cairo_status_t status; - cairo_path_buf_t *buf; + int i, arg; + cairo_path_op_buf_t *op_buf; cairo_path_op_t op; + cairo_path_arg_buf_t *arg_buf = path->arg_buf_head; + int buf_i = 0; + cairo_point_t point[CAIRO_PATH_OP_MAX_ARGS]; cairo_bool_t forward = (dir == CAIRO_DIRECTION_FORWARD); int step = forward ? 1 : -1; - for (buf = forward ? path->buf_head : path->buf_tail; - buf; - buf = forward ? buf->next : buf->prev) + for (op_buf = forward ? path->op_buf_head : path->op_buf_tail; + op_buf; + op_buf = forward ? op_buf->next : op_buf->prev) { - cairo_point_t *points; - int start, stop, i; + int start, stop; if (forward) { start = 0; - stop = buf->num_ops; - points = buf->points; + stop = op_buf->num_ops; } else { - start = buf->num_ops - 1; + start = op_buf->num_ops - 1; stop = -1; - points = buf->points + buf->num_points; } for (i=start; i != stop; i += step) { - op = buf->op[i]; + op = op_buf->op[i]; if (! forward) { - points -= num_args[op]; + if (buf_i == 0) { + arg_buf = arg_buf->prev; + buf_i = arg_buf->num_points; + } + buf_i -= num_args[op]; + } + + for (arg = 0; arg < num_args[op]; arg++) { + point[arg] = arg_buf->points[buf_i]; + buf_i++; + if (buf_i >= arg_buf->num_points) { + arg_buf = arg_buf->next; + buf_i = 0; + } + } + + if (! forward) { + buf_i -= num_args[op]; } switch (op) { case CAIRO_PATH_OP_MOVE_TO: - status = (*move_to) (closure, &points[0]); + status = (*move_to) (closure, &point[0]); break; case CAIRO_PATH_OP_LINE_TO: - status = (*line_to) (closure, &points[0]); + status = (*line_to) (closure, &point[0]); break; case CAIRO_PATH_OP_CURVE_TO: - status = (*curve_to) (closure, &points[0], &points[1], &points[2]); + status = (*curve_to) (closure, &point[0], &point[1], &point[2]); break; case CAIRO_PATH_OP_CLOSE_PATH: default: @@ -490,11 +584,6 @@ _cairo_path_fixed_interpret (cairo_path_fixed_t *path, } if (status) return status; - - if (forward) { - points += num_args[op]; - } - } } @@ -508,31 +597,31 @@ _cairo_path_fixed_offset_and_scale (cairo_path_fixed_t *path, cairo_fixed_t scalex, cairo_fixed_t scaley) { - cairo_path_buf_t *buf = path->buf_head; + cairo_path_arg_buf_t *arg_buf = path->arg_buf_head; int i; cairo_int64_t i64temp; cairo_fixed_t fixedtemp; - while (buf) { - for (i = 0; i < buf->num_points; i++) { + while (arg_buf) { + for (i = 0; i < arg_buf->num_points; i++) { if (scalex == CAIRO_FIXED_ONE) { - buf->points[i].x += offx; + arg_buf->points[i].x += offx; } else { - fixedtemp = buf->points[i].x + offx; + fixedtemp = arg_buf->points[i].x + offx; i64temp = _cairo_int32x32_64_mul (fixedtemp, scalex); - buf->points[i].x = _cairo_int64_to_int32(_cairo_int64_rsl (i64temp, 16)); + arg_buf->points[i].x = _cairo_int64_to_int32(_cairo_int64_rsl (i64temp, 16)); } if (scaley == CAIRO_FIXED_ONE) { - buf->points[i].y += offy; + arg_buf->points[i].y += offy; } else { - fixedtemp = buf->points[i].y + offy; + fixedtemp = arg_buf->points[i].y + offy; i64temp = _cairo_int32x32_64_mul (fixedtemp, scaley); - buf->points[i].y = _cairo_int64_to_int32(_cairo_int64_rsl (i64temp, 16)); + arg_buf->points[i].y = _cairo_int64_to_int32(_cairo_int64_rsl (i64temp, 16)); } } - buf = buf->next; + arg_buf = arg_buf->next; } } diff --git a/gfx/cairo/cairo/src/cairo-path-stroke.c b/gfx/cairo/cairo/src/cairo-path-stroke.c index 09bafbf8e71..519434c40f5 100644 --- a/gfx/cairo/cairo/src/cairo-path-stroke.c +++ b/gfx/cairo/cairo/src/cairo-path-stroke.c @@ -51,7 +51,7 @@ typedef struct cairo_stroker { cairo_point_t current_point; cairo_point_t first_point; - cairo_bool_t has_initial_sub_path; + cairo_bool_t has_sub_path; cairo_bool_t has_current_face; cairo_stroke_face_t current_face; @@ -61,8 +61,7 @@ typedef struct cairo_stroker { cairo_bool_t dashed; unsigned int dash_index; - cairo_bool_t dash_on; - cairo_bool_t dash_starts_on; + int dash_on; double dash_remain; } cairo_stroker_t; @@ -115,7 +114,7 @@ static void _cairo_stroker_start_dash (cairo_stroker_t *stroker) { double offset; - cairo_bool_t on = TRUE; + int on = 1; unsigned int i = 0; offset = stroker->style->dash_offset; @@ -125,13 +124,13 @@ _cairo_stroker_start_dash (cairo_stroker_t *stroker) segment shrinks to zero it will be skipped over. */ while (offset > 0.0 && offset >= stroker->style->dash[i]) { offset -= stroker->style->dash[i]; - on = !on; + on = 1-on; if (++i == stroker->style->num_dashes) i = 0; } stroker->dashed = TRUE; stroker->dash_index = i; - stroker->dash_on = stroker->dash_starts_on = on; + stroker->dash_on = on; stroker->dash_remain = stroker->style->dash[i] - offset; } @@ -143,7 +142,7 @@ _cairo_stroker_step_dash (cairo_stroker_t *stroker, double step) stroker->dash_index++; if (stroker->dash_index == stroker->style->num_dashes) stroker->dash_index = 0; - stroker->dash_on = !stroker->dash_on; + stroker->dash_on = 1-stroker->dash_on; stroker->dash_remain = stroker->style->dash[stroker->dash_index]; } } @@ -168,7 +167,7 @@ _cairo_stroker_init (cairo_stroker_t *stroker, stroker->has_current_face = FALSE; stroker->has_first_face = FALSE; - stroker->has_initial_sub_path = FALSE; + stroker->has_sub_path = FALSE; if (stroker->style->dash) _cairo_stroker_start_dash (stroker); @@ -467,25 +466,17 @@ _cairo_stroker_add_caps (cairo_stroker_t *stroker) { cairo_status_t status; /* check for a degenerative sub_path */ - if (stroker->has_initial_sub_path + if (stroker->has_sub_path && !stroker->has_first_face && !stroker->has_current_face && stroker->style->line_cap == CAIRO_LINE_JOIN_ROUND) { /* pick an arbitrary slope to use */ cairo_slope_t slope = {1, 0}; - cairo_stroke_face_t face; + _compute_face (&stroker->first_point, &slope, stroker, &stroker->first_face); - /* arbitrarily choose first_point - * first_point and current_point should be the same */ - _compute_face (&stroker->first_point, &slope, stroker, &face); - - status = _cairo_stroker_add_leading_cap (stroker, &face); - if (status) - return status; - status = _cairo_stroker_add_trailing_cap (stroker, &face); - if (status) - return status; + stroker->has_first_face = stroker->has_current_face = TRUE; + stroker->current_face = stroker->first_face; } if (stroker->has_first_face) { @@ -603,7 +594,6 @@ _cairo_stroker_move_to (void *closure, cairo_point_t *point) cairo_status_t status; cairo_stroker_t *stroker = closure; - /* Cap the start and end of the previous sub path as needed */ status = _cairo_stroker_add_caps (stroker); if (status) return status; @@ -613,7 +603,7 @@ _cairo_stroker_move_to (void *closure, cairo_point_t *point) stroker->has_first_face = FALSE; stroker->has_current_face = FALSE; - stroker->has_initial_sub_path = FALSE; + stroker->has_sub_path = FALSE; return CAIRO_STATUS_SUCCESS; } @@ -638,7 +628,7 @@ _cairo_stroker_line_to (void *closure, cairo_point_t *point) cairo_point_t *p2 = point; cairo_slope_t slope; - stroker->has_initial_sub_path = TRUE; + stroker->has_sub_path = TRUE; if (p1->x == p2->x && p1->y == p2->y) return CAIRO_STATUS_SUCCESS; @@ -650,14 +640,14 @@ _cairo_stroker_line_to (void *closure, cairo_point_t *point) return status; if (stroker->has_current_face) { - /* Join with final face from previous segment */ status = _cairo_stroker_join (stroker, &stroker->current_face, &start); if (status) return status; - } else if (!stroker->has_first_face) { - /* Save sub path's first face in case needed for closing join */ - stroker->first_face = start; - stroker->has_first_face = TRUE; + } else { + if (!stroker->has_first_face) { + stroker->first_face = start; + stroker->has_first_face = TRUE; + } } stroker->current_face = end; stroker->has_current_face = TRUE; @@ -675,16 +665,17 @@ _cairo_stroker_line_to_dashed (void *closure, cairo_point_t *point) { cairo_status_t status = CAIRO_STATUS_SUCCESS; cairo_stroker_t *stroker = closure; - double mag, remain, step_length = 0; + double mag, remain, tmp; double dx, dy; double dx2, dy2; cairo_point_t fd1, fd2; + cairo_bool_t first = TRUE; cairo_stroke_face_t sub_start, sub_end; cairo_point_t *p1 = &stroker->current_point; cairo_point_t *p2 = point; cairo_slope_t slope; - stroker->has_initial_sub_path = stroker->dash_starts_on; + stroker->has_sub_path = stroker->dash_on; if (p1->x == p2->x && p1->y == p2->y) return CAIRO_STATUS_SUCCESS; @@ -696,75 +687,90 @@ _cairo_stroker_line_to_dashed (void *closure, cairo_point_t *point) cairo_matrix_transform_distance (stroker->ctm_inverse, &dx, &dy); - mag = sqrt (dx * dx + dy * dy); + mag = sqrt (dx *dx + dy * dy); remain = mag; fd1 = *p1; while (remain) { - step_length = MIN (stroker->dash_remain, remain); - remain -= step_length; - dx2 = dx * (mag - remain)/mag; + tmp = stroker->dash_remain; + if (tmp > remain) + tmp = remain; + remain -= tmp; + dx2 = dx * (mag - remain)/mag; dy2 = dy * (mag - remain)/mag; cairo_matrix_transform_distance (stroker->ctm, &dx2, &dy2); - fd2.x = _cairo_fixed_from_double (dx2) + p1->x; - fd2.y = _cairo_fixed_from_double (dy2) + p1->y; - + fd2.x = _cairo_fixed_from_double (dx2); + fd2.y = _cairo_fixed_from_double (dy2); + fd2.x += p1->x; + fd2.y += p1->y; + /* + * XXX simplify this case analysis + */ if (stroker->dash_on) { status = _cairo_stroker_add_sub_edge (stroker, &fd1, &fd2, &slope, &sub_start, &sub_end); if (status) return status; - - if (stroker->has_current_face) { - /* Join with final face from previous segment */ - status = _cairo_stroker_join (stroker, &stroker->current_face, &sub_start); - stroker->has_current_face = FALSE; - if (status) - return status; - } else if (!stroker->has_first_face && stroker->dash_starts_on) { - /* Save sub path's first face in case needed for closing join */ - stroker->first_face = sub_start; - stroker->has_first_face = TRUE; - } else { - /* Cap dash start if not connecting to a previous segment */ + if (!first) { + /* + * Not first dash in this segment, cap start + */ status = _cairo_stroker_add_leading_cap (stroker, &sub_start); if (status) return status; + } else { + /* + * First in this segment, join to any current_face, else + * if at start of sub-path, mark position, else + * cap + */ + if (stroker->has_current_face) { + status = _cairo_stroker_join (stroker, &stroker->current_face, &sub_start); + if (status) + return status; + } else { + if (!stroker->has_first_face) { + stroker->first_face = sub_start; + stroker->has_first_face = TRUE; + } else { + status = _cairo_stroker_add_leading_cap (stroker, &sub_start); + if (status) + return status; + } + } + stroker->has_sub_path = TRUE; } - if (remain) { - /* Cap dash end if not at end of segment */ + /* + * Cap if not at end of segment + */ status = _cairo_stroker_add_trailing_cap (stroker, &sub_end); if (status) return status; } else { + /* + * Mark previous line face and fix up next time + * through + */ stroker->current_face = sub_end; stroker->has_current_face = TRUE; } } else { - if (stroker->has_current_face) { - /* Cap final face from previous segment */ - status = _cairo_stroker_add_trailing_cap (stroker, &stroker->current_face); - if (status) - return status; - stroker->has_current_face = FALSE; + /* + * If starting with off dash, check previous face + * and cap if necessary + */ + if (first) { + if (stroker->has_current_face) { + status = _cairo_stroker_add_trailing_cap (stroker, &stroker->current_face); + if (status) + return status; + } } + if (!remain) + stroker->has_current_face = FALSE; } - _cairo_stroker_step_dash (stroker, step_length); + _cairo_stroker_step_dash (stroker, tmp); fd1 = fd2; - } - - if (stroker->dash_on && !stroker->has_current_face) { - /* This segment ends on a transition to dash_on, compute a new face - * and add cap for the begining of the next dash_on step. - * - * Note: this will create a degenerate cap if this is not the last line - * in the path. Whether this behaviour is desirable or not is debatable. - * On one side these degnerate caps can not be reproduced with regular path stroking. - * On the other side Acroread 7 also produces the degenerate caps. */ - _compute_face (point, &slope, stroker, &stroker->current_face); - stroker->has_current_face = TRUE; - status = _cairo_stroker_add_leading_cap (stroker, &stroker->current_face); - if (status) - return status; + first = FALSE; } stroker->current_point = *point; @@ -801,9 +807,11 @@ _cairo_stroker_curve_to (void *closure, status = _cairo_stroker_join (stroker, &stroker->current_face, &start); if (status) return status; - } else if (!stroker->has_first_face) { - stroker->first_face = start; - stroker->has_first_face = TRUE; + } else { + if (!stroker->has_first_face) { + stroker->first_face = start; + stroker->has_first_face = TRUE; + } } stroker->current_face = end; stroker->has_current_face = TRUE; @@ -920,18 +928,16 @@ _cairo_stroker_close_path (void *closure) return status; if (stroker->has_first_face && stroker->has_current_face) { - /* Join first and final faces of sub path */ status = _cairo_stroker_join (stroker, &stroker->current_face, &stroker->first_face); if (status) return status; } else { - /* Cap the start and end of the sub path as needed */ status = _cairo_stroker_add_caps (stroker); if (status) return status; } - stroker->has_initial_sub_path = FALSE; + stroker->has_sub_path = FALSE; stroker->has_first_face = FALSE; stroker->has_current_face = FALSE; @@ -990,7 +996,6 @@ _cairo_path_fixed_stroke_to_traps (cairo_path_fixed_t *path, if (status) goto BAIL; - /* Cap the start and end of the final sub path as needed */ status = _cairo_stroker_add_caps (&stroker); BAIL: @@ -1282,17 +1287,16 @@ _cairo_path_fixed_stroke_rectilinear (cairo_path_fixed_t *path, NULL, _cairo_rectilinear_stroker_close_path, &rectilinear_stroker); - if (status) - goto BAIL; + if (status) { + _cairo_traps_fini (traps); + return status; + } status = _cairo_rectilinear_stroker_emit_segments (&rectilinear_stroker); - -BAIL: + if (status) + return status; _cairo_rectilinear_stroker_fini (&rectilinear_stroker); - if (status) - _cairo_traps_fini (traps); - - return status; + return CAIRO_STATUS_SUCCESS; } diff --git a/gfx/cairo/cairo/src/cairo-path.c b/gfx/cairo/cairo/src/cairo-path.c index 7c2374c2a4f..544abf3fa10 100644 --- a/gfx/cairo/cairo/src/cairo-path.c +++ b/gfx/cairo/cairo/src/cairo-path.c @@ -465,19 +465,19 @@ _cairo_path_append_to_context (const cairo_path_t *path, p = &path->data[i]; switch (p->header.type) { case CAIRO_PATH_MOVE_TO: - if (p->header.length < 2) + if (p->header.length != 2) return CAIRO_STATUS_INVALID_PATH_DATA; cairo_move_to (cr, p[1].point.x, p[1].point.y); break; case CAIRO_PATH_LINE_TO: - if (p->header.length < 2) + if (p->header.length != 2) return CAIRO_STATUS_INVALID_PATH_DATA; cairo_line_to (cr, p[1].point.x, p[1].point.y); break; case CAIRO_PATH_CURVE_TO: - if (p->header.length < 4) + if (p->header.length != 4) return CAIRO_STATUS_INVALID_PATH_DATA; cairo_curve_to (cr, p[1].point.x, p[1].point.y, @@ -485,7 +485,7 @@ _cairo_path_append_to_context (const cairo_path_t *path, p[3].point.x, p[3].point.y); break; case CAIRO_PATH_CLOSE_PATH: - if (p->header.length < 1) + if (p->header.length != 1) return CAIRO_STATUS_INVALID_PATH_DATA; cairo_close_path (cr); break; diff --git a/gfx/cairo/cairo/src/cairo-pattern.c b/gfx/cairo/cairo/src/cairo-pattern.c index f076259b525..bc12a9d7f07 100644 --- a/gfx/cairo/cairo/src/cairo-pattern.c +++ b/gfx/cairo/cairo/src/cairo-pattern.c @@ -34,7 +34,6 @@ const cairo_solid_pattern_t cairo_pattern_nil = { { CAIRO_PATTERN_TYPE_SOLID, /* type */ CAIRO_REF_COUNT_INVALID, /* ref_count */ CAIRO_STATUS_NO_MEMORY, /* status */ - { 0, 0, 0, NULL }, /* user_data */ { 1., 0., 0., 1., 0., 0., }, /* matrix */ CAIRO_FILTER_DEFAULT, /* filter */ CAIRO_EXTEND_GRADIENT_DEFAULT }, /* extend */ @@ -44,7 +43,6 @@ static const cairo_solid_pattern_t cairo_pattern_nil_null_pointer = { { CAIRO_PATTERN_TYPE_SOLID, /* type */ CAIRO_REF_COUNT_INVALID, /* ref_count */ CAIRO_STATUS_NULL_POINTER,/* status */ - { 0, 0, 0, NULL }, /* user_data */ { 1., 0., 0., 1., 0., 0., }, /* matrix */ CAIRO_FILTER_DEFAULT, /* filter */ CAIRO_EXTEND_GRADIENT_DEFAULT }, /* extend */ @@ -86,8 +84,6 @@ _cairo_pattern_init (cairo_pattern_t *pattern, cairo_pattern_type_t type) pattern->ref_count = 1; pattern->status = CAIRO_STATUS_SUCCESS; - _cairo_user_data_array_init (&pattern->user_data); - if (type == CAIRO_PATTERN_TYPE_SURFACE) pattern->extend = CAIRO_EXTEND_SURFACE_DEFAULT; else @@ -117,15 +113,11 @@ _cairo_gradient_pattern_init_copy (cairo_gradient_pattern_t *pattern, *dst = *src; } - if (other->stops == other->stops_embedded) - pattern->stops = pattern->stops_embedded; - else if (other->stops) + if (other->n_stops) { - pattern->stops = malloc (other->stops_size * + pattern->stops = malloc (other->n_stops * sizeof (pixman_gradient_stop_t)); if (pattern->stops == NULL) { - pattern->stops_size = 0; - pattern->n_stops = 0; _cairo_pattern_set_error (&pattern->base, CAIRO_STATUS_NO_MEMORY); return; } @@ -173,8 +165,6 @@ _cairo_pattern_init_copy (cairo_pattern_t *pattern, void _cairo_pattern_fini (cairo_pattern_t *pattern) { - _cairo_user_data_array_fini (&pattern->user_data); - switch (pattern->type) { case CAIRO_PATTERN_TYPE_SOLID: break; @@ -189,7 +179,7 @@ _cairo_pattern_fini (cairo_pattern_t *pattern) cairo_gradient_pattern_t *gradient = (cairo_gradient_pattern_t *) pattern; - if (gradient->stops && gradient->stops != gradient->stops_embedded) + if (gradient->stops) free (gradient->stops); } break; } @@ -225,9 +215,8 @@ _cairo_pattern_init_gradient (cairo_gradient_pattern_t *pattern, { _cairo_pattern_init (&pattern->base, type); - pattern->n_stops = 0; - pattern->stops_size = 0; - pattern->stops = NULL; + pattern->stops = NULL; + pattern->n_stops = 0; } void @@ -249,12 +238,12 @@ _cairo_pattern_init_radial (cairo_radial_pattern_t *pattern, { _cairo_pattern_init_gradient (&pattern->base, CAIRO_PATTERN_TYPE_RADIAL); - pattern->gradient.c1.x = _cairo_fixed_from_double (cx0); - pattern->gradient.c1.y = _cairo_fixed_from_double (cy0); - pattern->gradient.c1.radius = _cairo_fixed_from_double (fabs (radius0)); - pattern->gradient.c2.x = _cairo_fixed_from_double (cx1); - pattern->gradient.c2.y = _cairo_fixed_from_double (cy1); - pattern->gradient.c2.radius = _cairo_fixed_from_double (fabs (radius1)); + pattern->gradient.inner.x = _cairo_fixed_from_double (cx0); + pattern->gradient.inner.y = _cairo_fixed_from_double (cy0); + pattern->gradient.inner.radius = _cairo_fixed_from_double (fabs (radius0)); + pattern->gradient.outer.x = _cairo_fixed_from_double (cx1); + pattern->gradient.outer.y = _cairo_fixed_from_double (cy1); + pattern->gradient.outer.radius = _cairo_fixed_from_double (fabs (radius1)); } cairo_pattern_t * @@ -501,15 +490,15 @@ cairo_pattern_create_radial (double cx0, double cy0, double radius0, * @pattern from being destroyed until a matching call to * cairo_pattern_destroy() is made. * - * The number of references to a #cairo_pattern_t can be get using - * cairo_pattern_get_reference_count(). - * * Return value: the referenced #cairo_pattern_t. **/ cairo_pattern_t * cairo_pattern_reference (cairo_pattern_t *pattern) { - if (pattern == NULL || pattern->ref_count == CAIRO_REF_COUNT_INVALID) + if (pattern == NULL) + return NULL; + + if (pattern->ref_count == CAIRO_REF_COUNT_INVALID) return pattern; assert (pattern->ref_count > 0); @@ -566,7 +555,10 @@ slim_hidden_def (cairo_pattern_status); void cairo_pattern_destroy (cairo_pattern_t *pattern) { - if (pattern == NULL || pattern->ref_count == CAIRO_REF_COUNT_INVALID) + if (pattern == NULL) + return; + + if (pattern->ref_count == CAIRO_REF_COUNT_INVALID) return; assert (pattern->ref_count > 0); @@ -580,116 +572,6 @@ cairo_pattern_destroy (cairo_pattern_t *pattern) } slim_hidden_def (cairo_pattern_destroy); -/** - * cairo_pattern_get_reference_count: - * @pattern: a #cairo_pattern_t - * - * Returns the current reference count of @pattern. - * - * Return value: the current reference count of @pattern. If the - * object is a nil object, 0 will be returned. - * - * Since: 1.4 - **/ -unsigned int -cairo_pattern_get_reference_count (cairo_pattern_t *pattern) -{ - if (pattern == NULL || pattern->ref_count == CAIRO_REF_COUNT_INVALID) - return 0; - - return pattern->ref_count; -} - -/** - * cairo_pattern_get_user_data: - * @pattern: a #cairo_pattern_t - * @key: the address of the #cairo_user_data_key_t the user data was - * attached to - * - * Return user data previously attached to @pattern using the - * specified key. If no user data has been attached with the given - * key this function returns %NULL. - * - * Return value: the user data previously attached or %NULL. - * - * Since: 1.4 - **/ -void * -cairo_pattern_get_user_data (cairo_pattern_t *pattern, - const cairo_user_data_key_t *key) -{ - return _cairo_user_data_array_get_data (&pattern->user_data, - key); -} - -/** - * cairo_pattern_set_user_data: - * @pattern: a #cairo_pattern_t - * @key: the address of a #cairo_user_data_key_t to attach the user data to - * @user_data: the user data to attach to the #cairo_pattern_t - * @destroy: a #cairo_destroy_func_t which will be called when the - * #cairo_t is destroyed or when new user data is attached using the - * same key. - * - * Attach user data to @pattern. To remove user data from a surface, - * call this function with the key that was used to set it and %NULL - * for @data. - * - * Return value: %CAIRO_STATUS_SUCCESS or %CAIRO_STATUS_NO_MEMORY if a - * slot could not be allocated for the user data. - * - * Since: 1.4 - **/ -cairo_status_t -cairo_pattern_set_user_data (cairo_pattern_t *pattern, - const cairo_user_data_key_t *key, - void *user_data, - cairo_destroy_func_t destroy) -{ - if (pattern->ref_count == CAIRO_REF_COUNT_INVALID) - return CAIRO_STATUS_NO_MEMORY; - - return _cairo_user_data_array_set_data (&pattern->user_data, - key, user_data, destroy); -} - -/* make room for at least one more color stop */ -static cairo_status_t -_cairo_pattern_gradient_grow (cairo_gradient_pattern_t *pattern) -{ - pixman_gradient_stop_t *new_stops; - int old_size = pattern->stops_size; - int embedded_size = sizeof (pattern->stops_embedded) / sizeof (pattern->stops_embedded[0]); - int new_size = 2 * MAX (old_size, 4); - - /* we have a local buffer at pattern->stops_embedded. try to fulfill the request - * from there. */ - if (old_size < embedded_size) { - pattern->stops = pattern->stops_embedded; - pattern->stops_size = embedded_size; - return CAIRO_STATUS_SUCCESS; - } - - assert (pattern->n_stops <= pattern->stops_size); - - if (pattern->stops == pattern->stops_embedded) { - new_stops = malloc (new_size * sizeof (pixman_gradient_stop_t)); - if (new_stops) - memcpy (new_stops, pattern->stops, old_size * sizeof (pixman_gradient_stop_t)); - } else { - new_stops = realloc (pattern->stops, new_size * sizeof (pixman_gradient_stop_t)); - } - - if (new_stops == NULL) { - return CAIRO_STATUS_NO_MEMORY; - } - - pattern->stops = new_stops; - pattern->stops_size = new_size; - - return CAIRO_STATUS_SUCCESS; -} - static void _cairo_pattern_add_color_stop (cairo_gradient_pattern_t *pattern, double offset, @@ -698,38 +580,38 @@ _cairo_pattern_add_color_stop (cairo_gradient_pattern_t *pattern, double blue, double alpha) { - pixman_gradient_stop_t *stops; + pixman_gradient_stop_t *new_stops; cairo_fixed_t x; unsigned int i; - if (pattern->n_stops >= pattern->stops_size) { - cairo_status_t status = _cairo_pattern_gradient_grow (pattern); - if (status) { - _cairo_pattern_set_error (&pattern->base, CAIRO_STATUS_NO_MEMORY); - return; - } + new_stops = realloc (pattern->stops, (pattern->n_stops + 1) * + sizeof (pixman_gradient_stop_t)); + if (new_stops == NULL) + { + _cairo_pattern_set_error (&pattern->base, CAIRO_STATUS_NO_MEMORY); + return; } - stops = pattern->stops; + pattern->stops = new_stops; x = _cairo_fixed_from_double (offset); for (i = 0; i < pattern->n_stops; i++) { - if (x < stops[i].x) + if (x < new_stops[i].x) { - memmove (&stops[i + 1], &stops[i], + memmove (&new_stops[i + 1], &new_stops[i], sizeof (pixman_gradient_stop_t) * (pattern->n_stops - i)); break; } } - stops[i].x = x; + new_stops[i].x = x; - stops[i].color.red = _cairo_color_double_to_short (red); - stops[i].color.green = _cairo_color_double_to_short (green); - stops[i].color.blue = _cairo_color_double_to_short (blue); - stops[i].color.alpha = _cairo_color_double_to_short (alpha); + new_stops[i].color.red = red * 65535.0; + new_stops[i].color.green = green * 65535.0; + new_stops[i].color.blue = blue * 65535.0; + new_stops[i].color.alpha = alpha * 65535.0; pattern->n_stops++; } @@ -885,15 +767,6 @@ cairo_pattern_get_matrix (cairo_pattern_t *pattern, cairo_matrix_t *matrix) *matrix = pattern->matrix; } -/** - * cairo_pattern_set_filter: - * @pattern: a #cairo_pattern_t - * @filter: a #cairo_filter_t describing the filter to use for resizing - * the pattern - * - * Sets the filter to be used for resizing when using this pattern. - * See #cairo_filter_t for details on each filter. - **/ void cairo_pattern_set_filter (cairo_pattern_t *pattern, cairo_filter_t filter) { @@ -903,15 +776,6 @@ cairo_pattern_set_filter (cairo_pattern_t *pattern, cairo_filter_t filter) pattern->filter = filter; } -/** - * cairo_pattern_get_filter: - * @pattern: a #cairo_pattern_t - * - * Gets the current filter for a pattern. See #cairo_filter_t - * for details on each filter. - * - * Return value: the current filter used for resizing the pattern. - **/ cairo_filter_t cairo_pattern_get_filter (cairo_pattern_t *pattern) { @@ -1280,63 +1144,6 @@ _cairo_pattern_acquire_surface_for_surface (cairo_surface_pattern_t *pattern, ty = 0; } - /* XXX: Hack: - * - * The way we currently support CAIRO_EXTEND_REFLECT is to create - * an image twice bigger on each side, and create a pattern of four - * images such that the new image, when repeated, has the same effect - * of reflecting the original pattern. - * - * This is because the reflect support in pixman is broken and we - * pass repeat instead of reflect to pixman. See - * _cairo_image_surface_set_attributes() for that. - */ - if (attr->extend == CAIRO_EXTEND_REFLECT) { - cairo_t *cr; - int w,h; - - cairo_rectangle_int16_t extents; - status = _cairo_surface_get_extents (pattern->surface, &extents); - if (status) - return status; - - attr->extend = CAIRO_EXTEND_REPEAT; - - x = extents.x; - y = extents.y; - w = 2 * extents.width; - h = 2 * extents.height; - - *out = cairo_surface_create_similar (dst, dst->content, w, h); - if (!*out) - return CAIRO_STATUS_NO_MEMORY; - - (*out)->device_transform = pattern->surface->device_transform; - (*out)->device_transform_inverse = pattern->surface->device_transform_inverse; - - cr = cairo_create (*out); - - cairo_set_source_surface (cr, pattern->surface, -x, -y); - cairo_paint (cr); - - cairo_scale (cr, -1, +1); - cairo_set_source_surface (cr, pattern->surface, x-w, -y); - cairo_paint (cr); - - cairo_scale (cr, +1, -1); - cairo_set_source_surface (cr, pattern->surface, x-w, y-h); - cairo_paint (cr); - - cairo_scale (cr, -1, +1); - cairo_set_source_surface (cr, pattern->surface, -x, y-h); - cairo_paint (cr); - - status = cairo_status (cr); - cairo_destroy (cr); - - return status; - } - if (_cairo_surface_is_image (dst)) { cairo_image_surface_t *image; @@ -1352,16 +1159,10 @@ _cairo_pattern_acquire_surface_for_surface (cairo_surface_pattern_t *pattern, } else { - cairo_rectangle_int16_t extents; - status = _cairo_surface_get_extents (pattern->surface, &extents); - if (status) - return status; - /* If we're repeating, we just play it safe and clone the entire surface. */ - /* If requested width and height are -1, clone the entire surface. - * This is relied on in the svg backend. */ - if (attr->extend == CAIRO_EXTEND_REPEAT || - (width == (unsigned int) -1 && height == (unsigned int) -1)) { + if (attr->extend == CAIRO_EXTEND_REPEAT) { + cairo_rectangle_int16_t extents; + status = _cairo_surface_get_extents (pattern->surface, &extents); x = extents.x; y = extents.y; width = extents.width; @@ -1378,19 +1179,13 @@ _cairo_pattern_acquire_surface_for_surface (cairo_surface_pattern_t *pattern, double y2 = y + height; cairo_bool_t is_tight; - _cairo_matrix_transform_bounding_box (&attr->matrix, - &x1, &y1, &x2, &y2, - &is_tight); - - /* The transform_bounding_box call may have resulted - * in a region larger than the surface, but we never - * want to clone more than the surface itself, (we - * know we're not repeating at this point due to the - * above. */ - x = MAX (0, floor (x1)); - y = MAX (0, floor (y1)); - width = MIN (extents.width, ceil (x2)) - x; - height = MIN (extents.height, ceil (y2)) - y; + cairo_matrix_transform_bounding_box (&attr->matrix, + &x1, &y1, &x2, &y2, + &is_tight); + x = floor (x1); + y = floor (y1); + width = ceil (x2) - x; + height = ceil (y2) - y; } x += tx; y += ty; @@ -1398,29 +1193,6 @@ _cairo_pattern_acquire_surface_for_surface (cairo_surface_pattern_t *pattern, status = _cairo_surface_clone_similar (dst, pattern->surface, x, y, width, height, out); - - if (status == CAIRO_INT_STATUS_UNSUPPORTED) { - - cairo_t *cr; - - *out = cairo_surface_create_similar (dst, dst->content, - width, height); - if (!*out) - return CAIRO_STATUS_NO_MEMORY; - - (*out)->device_transform = pattern->surface->device_transform; - (*out)->device_transform_inverse = pattern->surface->device_transform_inverse; - - /* XXX Use _cairo_surface_composite directly */ - cr = cairo_create (*out); - - cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE); - cairo_set_source_surface (cr, pattern->surface, -x, -y); - cairo_paint (cr); - - status = cairo_status (cr); - cairo_destroy (cr); - } } return status; @@ -1484,10 +1256,10 @@ _cairo_pattern_acquire_surface (cairo_pattern_t *pattern, cairo_color_t color; _cairo_color_init_rgba (&color, - src->stops->color.red / 65535.0, - src->stops->color.green / 65535.0, - src->stops->color.blue / 65535.0, - src->stops->color.alpha / 65535.0); + src->stops->color.red / 65536.0, + src->stops->color.green / 65536.0, + src->stops->color.blue / 65536.0, + src->stops->color.alpha / 65536.0); _cairo_pattern_init_solid (&solid, &color); } @@ -1679,7 +1451,6 @@ _cairo_pattern_get_extents (cairo_pattern_t *pattern, imatrix = pattern->matrix; cairo_matrix_invert (&imatrix); - /* XXX Use _cairo_matrix_transform_bounding_box here */ for (sy = 0; sy <= 1; sy++) { for (sx = 0; sx <= 1; sx++) { x = surface_extents.x + sx * surface_extents.width; @@ -1798,7 +1569,6 @@ cairo_pattern_get_surface (cairo_pattern_t *pattern, * cairo_pattern_get_color_stop_rgba * @pattern: a #cairo_pattern_t * @index: index of the stop to return data for - * @offset: return value for the offset of the stop, or %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 @@ -1915,12 +1685,12 @@ cairo_pattern_get_linear_points (cairo_pattern_t *pattern, /** * cairo_pattern_get_radial_circles * @pattern: a #cairo_pattern_t - * @x0: return value for the x coordinate of the center of the first circle, or %NULL - * @y0: return value for the y coordinate of the center of the first circle, or %NULL - * @r0: return value for the radius of the first circle, or %NULL - * @x1: return value for the x coordinate of the center of the second circle, or %NULL - * @y1: return value for the y coordinate of the center of the second circle, or %NULL - * @r1: return value for the radius of the second circle, or %NULL + * @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. @@ -1942,17 +1712,17 @@ cairo_pattern_get_radial_circles (cairo_pattern_t *pattern, return CAIRO_STATUS_PATTERN_TYPE_MISMATCH; if (x0) - *x0 = _cairo_fixed_to_double (radial->gradient.c1.x); + *x0 = _cairo_fixed_to_double (radial->gradient.inner.x); if (y0) - *y0 = _cairo_fixed_to_double (radial->gradient.c1.y); + *y0 = _cairo_fixed_to_double (radial->gradient.inner.y); if (r0) - *r0 = _cairo_fixed_to_double (radial->gradient.c1.radius); + *r0 = _cairo_fixed_to_double (radial->gradient.inner.radius); if (x1) - *x1 = _cairo_fixed_to_double (radial->gradient.c2.x); + *x1 = _cairo_fixed_to_double (radial->gradient.outer.x); if (y1) - *y1 = _cairo_fixed_to_double (radial->gradient.c2.y); + *y1 = _cairo_fixed_to_double (radial->gradient.outer.y); if (r1) - *r1 = _cairo_fixed_to_double (radial->gradient.c2.radius); + *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 924b80c03f8..9c6c8e8c7de 100644 --- a/gfx/cairo/cairo/src/cairo-pdf-surface.c +++ b/gfx/cairo/cairo/src/cairo-pdf-surface.c @@ -277,8 +277,7 @@ _cairo_pdf_surface_create_for_stream_internal (cairo_output_stream_t *output, _cairo_array_init (&surface->streams, sizeof (cairo_pdf_resource_t)); _cairo_array_init (&surface->alphas, sizeof (double)); - surface->font_subsets = _cairo_scaled_font_subsets_create (PDF_SURFACE_MAX_GLYPHS_PER_FONT, - PDF_SURFACE_MAX_GLYPHS_PER_FONT); + surface->font_subsets = _cairo_scaled_font_subsets_create (PDF_SURFACE_MAX_GLYPHS_PER_FONT); if (! surface->font_subsets) { _cairo_error (CAIRO_STATUS_NO_MEMORY); free (surface); @@ -380,9 +379,7 @@ cairo_pdf_surface_create (const char *filename, status = _cairo_output_stream_get_status (output); if (status) { _cairo_error (status); - return (status == CAIRO_STATUS_WRITE_ERROR) ? - (cairo_surface_t*) &_cairo_surface_nil_write_error : - (cairo_surface_t*) &_cairo_surface_nil; + return (cairo_surface_t*) &_cairo_surface_nil; } return _cairo_pdf_surface_create_for_stream_internal (output, @@ -657,7 +654,7 @@ compress_dup (const void *data, unsigned long data_size, * no SMask object will be emitted and *id_ret will be set to 0. */ static cairo_status_t -_cairo_pdf_surface_emit_smask (cairo_pdf_surface_t *surface, +emit_smask (cairo_pdf_surface_t *surface, cairo_image_surface_t *image, cairo_pdf_resource_t *stream_ret) { @@ -728,7 +725,7 @@ _cairo_pdf_surface_emit_smask (cairo_pdf_surface_t *surface, /* Emit image data into the given surface, providing a resource that * can be used to reference the data in image_ret. */ static cairo_status_t -_cairo_pdf_surface_emit_image (cairo_pdf_surface_t *surface, +emit_image (cairo_pdf_surface_t *surface, cairo_image_surface_t *image, cairo_pdf_resource_t *image_ret) { @@ -747,7 +744,7 @@ _cairo_pdf_surface_emit_image (cairo_pdf_surface_t *surface, /* These are the only image formats we currently support, (which * makes things a lot simpler here). This is enforced through - * _cairo_pdf_surface_analyze_operation which only accept source surfaces of + * _analyze_operation which only accept source surfaces of * CONTENT_COLOR or CONTENT_COLOR_ALPHA. */ assert (image->format == CAIRO_FORMAT_RGB24 || image->format == CAIRO_FORMAT_ARGB32); @@ -797,7 +794,7 @@ _cairo_pdf_surface_emit_image (cairo_pdf_surface_t *surface, need_smask = FALSE; if (image->format == CAIRO_FORMAT_ARGB32) { - status = _cairo_pdf_surface_emit_smask (surface, image, &smask); + status = emit_smask (surface, image, &smask); if (status) goto CLEANUP_COMPRESSED; @@ -841,7 +838,7 @@ _cairo_pdf_surface_emit_image (cairo_pdf_surface_t *surface, } static cairo_status_t -_cairo_pdf_surface_emit_solid_pattern (cairo_pdf_surface_t *surface, +emit_solid_pattern (cairo_pdf_surface_t *surface, cairo_solid_pattern_t *pattern) { cairo_pdf_resource_t alpha; @@ -866,80 +863,77 @@ _cairo_pdf_surface_emit_solid_pattern (cairo_pdf_surface_t *surface, } static cairo_status_t -_cairo_pdf_surface_emit_surface_pattern (cairo_pdf_surface_t *surface, +emit_surface_pattern (cairo_pdf_surface_t *surface, cairo_surface_pattern_t *pattern) { cairo_pdf_resource_t stream; - cairo_surface_t *pat_surface; - cairo_surface_attributes_t pat_attr; cairo_image_surface_t *image; void *image_extra; cairo_status_t status = CAIRO_STATUS_SUCCESS; cairo_pdf_resource_t alpha, image_resource = {0}; /* squelch bogus compiler warning */ cairo_matrix_t cairo_p2d, pdf_p2d; cairo_extend_t extend = cairo_pattern_get_extend (&pattern->base); - double xstep, ystep; + int xstep, ystep; cairo_rectangle_int16_t surface_extents; /* XXX: Should do something clever here for PDF source surfaces ? */ _cairo_pdf_surface_pause_content_stream (surface); - status = _cairo_pattern_acquire_surface ((cairo_pattern_t *)pattern, - (cairo_surface_t *)surface, - 0, 0, -1, -1, - &pat_surface, &pat_attr); + status = _cairo_surface_acquire_source_image (pattern->surface, &image, &image_extra); if (status) return status; - status = _cairo_surface_acquire_source_image (pat_surface, &image, &image_extra); - if (status) - goto BAIL2; - - status = _cairo_pdf_surface_emit_image (surface, image, &image_resource); + status = emit_image (surface, image, &image_resource); if (status) goto BAIL; _cairo_surface_get_extents (&surface->base, &surface_extents); switch (extend) { - /* We implement EXTEND_PAD like EXTEND_NONE for now */ - case CAIRO_EXTEND_PAD: case CAIRO_EXTEND_NONE: { - /* In PS/PDF, (as far as I can tell), all patterns are + /* In PDF, (as far as I can tell), all patterns are * repeating. So we support cairo's EXTEND_NONE semantics * by setting the repeat step size to a size large enough * to guarantee that no more than a single occurrence will * be visible. * - * First, map the surface extents into pattern space (since - * xstep and ystep are in pattern space). Then use an upper - * bound on the length of the diagonal of the pattern image - * and the surface as repeat size. This guarantees to never - * repeat visibly. + * First, map the pattern's extents through the inverse + * pattern matrix to compute the device-space bounds of + * the desired single occurrence. Then consider the bounds + * of (the union of this rectangle with the target surface + * extents). If the repeat size is larger than the + * diagonal of the bounds of the union, then it is + * guaranteed to never repeat visibly. */ double x1 = 0.0, y1 = 0.0; - double x2 = surface->width, y2 = surface->height; - _cairo_matrix_transform_bounding_box (&pattern->base.matrix, - &x1, &y1, &x2, &y2, - NULL); - + double x2 = image->width, y2 = image->height; + cairo_matrix_t surface_to_device = pattern->base.matrix; + cairo_matrix_invert (&surface_to_device); + cairo_matrix_transform_bounding_box (&surface_to_device, + &x1, &y1, &x2, &y2, + NULL); /* Rather than computing precise bounds of the union, just * add the surface extents unconditionally. We only * required an answer that's large enough, we don't really - * care if it's not as tight as possible.*/ - xstep = ystep = ceil ((x2 - x1) + (y2 - y1) + - image->width + image->height); + * care if it's not as tight as possible. */ + x1 = MAX (fabs(x1), fabs(x2)) + surface_extents.width; + y1 = MAX (fabs(y1), fabs(y2)) + surface_extents.height; + /* Similarly, don't bother computing the square root to + * determine the length of the final diagonal. */ + xstep = _cairo_lround (ceil (x1 * y1)); + ystep = _cairo_lround (ceil (x1 * y1)); } break; case CAIRO_EXTEND_REPEAT: - case CAIRO_EXTEND_REFLECT: xstep = image->width; ystep = image->height; break; - /* All the rest (if any) should have been analyzed away, so this - * case should be unreachable. */ + /* All the rest should have been analyzed away, so this case + * should be unreachable. */ + case CAIRO_EXTEND_REFLECT: + case CAIRO_EXTEND_PAD: default: ASSERT_NOT_REACHED; xstep = 0; @@ -986,8 +980,8 @@ _cairo_pdf_surface_emit_surface_pattern (cairo_pdf_surface_t *surface, stream = _cairo_pdf_surface_open_stream (surface, FALSE, " /BBox [0 0 %d %d]\r\n" - " /XStep %f\r\n" - " /YStep %f\r\n" + " /XStep %d\r\n" + " /YStep %d\r\n" " /PatternType 1\r\n" " /TilingType 1\r\n" " /PaintType 1\r\n" @@ -1022,9 +1016,7 @@ _cairo_pdf_surface_emit_surface_pattern (cairo_pdf_surface_t *surface, stream.id, stream.id, alpha.id); BAIL: - _cairo_surface_release_source_image (pat_surface, image, image_extra); - BAIL2: - _cairo_pattern_release_surface ((cairo_pattern_t *)pattern, pat_surface, &pat_attr); + _cairo_surface_release_source_image (pattern->surface, image, image_extra); return status; } @@ -1036,7 +1028,7 @@ typedef struct _cairo_pdf_color_stop { } cairo_pdf_color_stop_t; static cairo_pdf_resource_t -_cairo_pdf_surface_emit_linear_colorgradient (cairo_pdf_surface_t *surface, +emit_linear_colorgradient (cairo_pdf_surface_t *surface, cairo_pdf_color_stop_t *stop1, cairo_pdf_color_stop_t *stop2) { @@ -1065,7 +1057,7 @@ _cairo_pdf_surface_emit_linear_colorgradient (cairo_pdf_surface_t *surface, } static cairo_pdf_resource_t -_cairo_pdf_surface_emit_stitched_colorgradient (cairo_pdf_surface_t *surface, +emit_stitched_colorgradient (cairo_pdf_surface_t *surface, unsigned int n_stops, cairo_pdf_color_stop_t stops[]) { @@ -1074,7 +1066,7 @@ _cairo_pdf_surface_emit_stitched_colorgradient (cairo_pdf_surface_t *surface, /* emit linear gradients between pairs of subsequent stops... */ for (i = 0; i < n_stops-1; i++) { - stops[i].gradient = _cairo_pdf_surface_emit_linear_colorgradient (surface, + stops[i].gradient = emit_linear_colorgradient (surface, &stops[i], &stops[i+1]); } @@ -1127,7 +1119,7 @@ _cairo_pdf_surface_emit_stitched_colorgradient (cairo_pdf_surface_t *surface, #define COLOR_STOP_EPSILON 1e-6 static cairo_pdf_resource_t -_cairo_pdf_surface_emit_pattern_stops (cairo_pdf_surface_t *surface, cairo_gradient_pattern_t *pattern) +emit_pattern_stops (cairo_pdf_surface_t *surface, cairo_gradient_pattern_t *pattern) { cairo_pdf_resource_t function; cairo_pdf_color_stop_t *allstops, *stops; @@ -1170,11 +1162,11 @@ _cairo_pdf_surface_emit_pattern_stops (cairo_pdf_surface_t *surface, cairo_gradi if (n_stops == 2) { /* no need for stitched function */ - function = _cairo_pdf_surface_emit_linear_colorgradient (surface, &stops[0], &stops[1]); + function = emit_linear_colorgradient (surface, &stops[0], &stops[1]); } else { /* multiple stops: stitch. XXX possible optimization: regulary spaced * stops do not require stitching. XXX */ - function = _cairo_pdf_surface_emit_stitched_colorgradient (surface, + function = emit_stitched_colorgradient (surface, n_stops, stops); } @@ -1185,7 +1177,7 @@ _cairo_pdf_surface_emit_pattern_stops (cairo_pdf_surface_t *surface, cairo_gradi } static cairo_status_t -_cairo_pdf_surface_emit_linear_pattern (cairo_pdf_surface_t *surface, cairo_linear_pattern_t *pattern) +emit_linear_pattern (cairo_pdf_surface_t *surface, cairo_linear_pattern_t *pattern) { cairo_pdf_resource_t function, pattern_resource, alpha; double x0, y0, x1, y1; @@ -1193,7 +1185,7 @@ _cairo_pdf_surface_emit_linear_pattern (cairo_pdf_surface_t *surface, cairo_line _cairo_pdf_surface_pause_content_stream (surface); - function = _cairo_pdf_surface_emit_pattern_stops (surface, &pattern->base); + function = emit_pattern_stops (surface, &pattern->base); if (function.id == 0) return CAIRO_STATUS_NO_MEMORY; @@ -1248,7 +1240,7 @@ _cairo_pdf_surface_emit_linear_pattern (cairo_pdf_surface_t *surface, cairo_line } static cairo_status_t -_cairo_pdf_surface_emit_radial_pattern (cairo_pdf_surface_t *surface, cairo_radial_pattern_t *pattern) +emit_radial_pattern (cairo_pdf_surface_t *surface, cairo_radial_pattern_t *pattern) { cairo_pdf_resource_t function, pattern_resource, alpha; double x0, y0, x1, y1, r0, r1; @@ -1256,20 +1248,20 @@ _cairo_pdf_surface_emit_radial_pattern (cairo_pdf_surface_t *surface, cairo_radi _cairo_pdf_surface_pause_content_stream (surface); - function = _cairo_pdf_surface_emit_pattern_stops (surface, &pattern->base); + function = emit_pattern_stops (surface, &pattern->base); if (function.id == 0) return CAIRO_STATUS_NO_MEMORY; p2u = pattern->base.base.matrix; cairo_matrix_invert (&p2u); - x0 = _cairo_fixed_to_double (pattern->gradient.c1.x); - y0 = _cairo_fixed_to_double (pattern->gradient.c1.y); - r0 = _cairo_fixed_to_double (pattern->gradient.c1.radius); + x0 = _cairo_fixed_to_double (pattern->gradient.inner.x); + y0 = _cairo_fixed_to_double (pattern->gradient.inner.y); + r0 = _cairo_fixed_to_double (pattern->gradient.inner.radius); cairo_matrix_transform_point (&p2u, &x0, &y0); - x1 = _cairo_fixed_to_double (pattern->gradient.c2.x); - y1 = _cairo_fixed_to_double (pattern->gradient.c2.y); - r1 = _cairo_fixed_to_double (pattern->gradient.c2.radius); + x1 = _cairo_fixed_to_double (pattern->gradient.outer.x); + y1 = _cairo_fixed_to_double (pattern->gradient.outer.y); + r1 = _cairo_fixed_to_double (pattern->gradient.outer.radius); cairo_matrix_transform_point (&p2u, &x1, &y1); /* FIXME: This is surely crack, but how should you scale a radius @@ -1324,20 +1316,20 @@ _cairo_pdf_surface_emit_radial_pattern (cairo_pdf_surface_t *surface, cairo_radi } static cairo_status_t -_cairo_pdf_surface_emit_pattern (cairo_pdf_surface_t *surface, cairo_pattern_t *pattern) +emit_pattern (cairo_pdf_surface_t *surface, cairo_pattern_t *pattern) { switch (pattern->type) { case CAIRO_PATTERN_TYPE_SOLID: - return _cairo_pdf_surface_emit_solid_pattern (surface, (cairo_solid_pattern_t *) pattern); + return emit_solid_pattern (surface, (cairo_solid_pattern_t *) pattern); case CAIRO_PATTERN_TYPE_SURFACE: - return _cairo_pdf_surface_emit_surface_pattern (surface, (cairo_surface_pattern_t *) pattern); + return emit_surface_pattern (surface, (cairo_surface_pattern_t *) pattern); case CAIRO_PATTERN_TYPE_LINEAR: - return _cairo_pdf_surface_emit_linear_pattern (surface, (cairo_linear_pattern_t *) pattern); + return emit_linear_pattern (surface, (cairo_linear_pattern_t *) pattern); case CAIRO_PATTERN_TYPE_RADIAL: - return _cairo_pdf_surface_emit_radial_pattern (surface, (cairo_radial_pattern_t *) pattern); + return emit_radial_pattern (surface, (cairo_radial_pattern_t *) pattern); } @@ -1638,90 +1630,11 @@ _cairo_pdf_surface_write_pages (cairo_pdf_surface_t *surface) "endobj\r\n"); } -static cairo_pdf_resource_t -_cairo_pdf_surface_emit_toUnicode_stream (cairo_pdf_surface_t *surface, - cairo_scaled_font_subset_t *font_subset) -{ - const cairo_scaled_font_backend_t *backend; - cairo_pdf_resource_t stream; - unsigned int i; - - if (font_subset->to_unicode == NULL) { - stream.id = 0; - return stream; - } - - if (_cairo_truetype_create_glyph_to_unicode_map (font_subset) != CAIRO_STATUS_SUCCESS) { - backend = font_subset->scaled_font->backend; - if (backend->map_glyphs_to_unicode == NULL) { - stream.id = 0; - return stream; - } - backend->map_glyphs_to_unicode (font_subset->scaled_font, font_subset); - } - - stream = _cairo_pdf_surface_open_stream (surface, FALSE, NULL); - _cairo_output_stream_printf (surface->output, - "/CIDInit /ProcSet findresource begin\r\n" - "12 dict begin\r\n" - "begincmap\r\n" - "/CIDSystemInfo\r\n" - "<< /Registry (Cairo)\r\n" - " /Ordering (ToUnicode-%d-%d)\r\n" - " /Supplement 0\r\n" - ">> def\r\n" - "/CMapName /Cairo-ToUnicode-%d-%d def\r\n" - "/CMapType 2 def\r\n" - "1 begincodespacerange\r\n" - "<00> \r\n" - "endcodespacerange\r\n", - font_subset->font_id, - font_subset->subset_id, - font_subset->font_id, - font_subset->subset_id); - - /* The CMap specification has a limit of 100 characters per beginbfchar operator */ - _cairo_output_stream_printf (surface->output, - "%d beginbfchar\r\n", - font_subset->num_glyphs > 100 ? 100 : font_subset->num_glyphs); - for (i = 0; i < font_subset->num_glyphs; i++) { - if (i != 0 && i % 100 == 0) { - _cairo_output_stream_printf (surface->output, - "endbfchar\r\n" - "%d beginbfchar\r\n", - font_subset->num_glyphs - i > 100 ? 100 : font_subset->num_glyphs - i); - } - _cairo_output_stream_printf (surface->output, - "<%02x> <%04x>\r\n", - i, font_subset->to_unicode[i]); - } - _cairo_output_stream_printf (surface->output, - "endbfchar\r\n"); - - if (font_subset->num_glyphs < 256) { - _cairo_output_stream_printf (surface->output, - "1 beginnotdefrange\r\n" - "<%02x> 0\r\n" - "endnotdefrange\r\n", - font_subset->num_glyphs); - } - - _cairo_output_stream_printf (surface->output, - "endcmap\r\n" - "CMapName currentdict /CMap defineresource pop\r\n" - "end\r\n" - "end\r\n"); - - _cairo_pdf_surface_close_stream (surface); - - return stream; -} - static cairo_status_t _cairo_pdf_surface_emit_cff_font_subset (cairo_pdf_surface_t *surface, cairo_scaled_font_subset_t *font_subset) { - cairo_pdf_resource_t stream, descriptor, subset_resource, to_unicode_stream; + cairo_pdf_resource_t stream, descriptor, subset_resource; cairo_status_t status; cairo_pdf_font_t font; cairo_cff_subset_t subset; @@ -1759,8 +1672,6 @@ _cairo_pdf_surface_emit_cff_font_subset (cairo_pdf_surface_t *surface, "endobj\r\n"); free (compressed); - to_unicode_stream = _cairo_pdf_surface_emit_toUnicode_stream (surface, font_subset); - descriptor = _cairo_pdf_surface_new_object (surface); _cairo_output_stream_printf (surface->output, "%d 0 obj\r\n" @@ -1799,7 +1710,7 @@ _cairo_pdf_surface_emit_cff_font_subset (cairo_pdf_surface_t *surface, " /Widths [", subset_resource.id, subset.base_font, - font_subset->num_glyphs - 1, + font_subset->num_glyphs, descriptor.id); for (i = 0; i < font_subset->num_glyphs; i++) @@ -1808,14 +1719,7 @@ _cairo_pdf_surface_emit_cff_font_subset (cairo_pdf_surface_t *surface, subset.widths[i]); _cairo_output_stream_printf (surface->output, - " ]\r\n"); - - if (to_unicode_stream.id != 0) - _cairo_output_stream_printf (surface->output, - " /ToUnicode %d 0 R\r\n", - to_unicode_stream.id); - - _cairo_output_stream_printf (surface->output, + " ]\r\n" ">>\r\n" "endobj\r\n"); @@ -1834,7 +1738,7 @@ _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, to_unicode_stream; + cairo_pdf_resource_t stream, descriptor, subset_resource; cairo_pdf_font_t font; unsigned long length, compressed_length; char *compressed; @@ -1868,8 +1772,6 @@ _cairo_pdf_surface_emit_type1_font (cairo_pdf_surface_t *surface, "endobj\r\n"); free (compressed); - to_unicode_stream = _cairo_pdf_surface_emit_toUnicode_stream (surface, font_subset); - descriptor = _cairo_pdf_surface_new_object (surface); _cairo_output_stream_printf (surface->output, "%d 0 obj\r\n" @@ -1917,14 +1819,7 @@ _cairo_pdf_surface_emit_type1_font (cairo_pdf_surface_t *surface, subset->widths[i]); _cairo_output_stream_printf (surface->output, - " ]\r\n"); - - if (to_unicode_stream.id != 0) - _cairo_output_stream_printf (surface->output, - " /ToUnicode %d 0 R\r\n", - to_unicode_stream.id); - - _cairo_output_stream_printf (surface->output, + " ]\r\n" ">>\r\n" "endobj\r\n"); @@ -1978,13 +1873,11 @@ _cairo_pdf_surface_emit_type1_fallback_font (cairo_pdf_surface_t *surface, return status; } -#define PDF_UNITS_PER_EM 1000 - static cairo_status_t _cairo_pdf_surface_emit_truetype_font_subset (cairo_pdf_surface_t *surface, cairo_scaled_font_subset_t *font_subset) { - cairo_pdf_resource_t stream, descriptor, encoding, subset_resource, to_unicode_stream; + cairo_pdf_resource_t stream, descriptor, subset_resource; cairo_status_t status; cairo_pdf_font_t font; cairo_truetype_subset_t subset; @@ -2021,19 +1914,17 @@ _cairo_pdf_surface_emit_truetype_font_subset (cairo_pdf_surface_t *surface, "endobj\r\n"); free (compressed); - to_unicode_stream = _cairo_pdf_surface_emit_toUnicode_stream (surface, font_subset); - descriptor = _cairo_pdf_surface_new_object (surface); _cairo_output_stream_printf (surface->output, "%d 0 obj\r\n" "<< /Type /FontDescriptor\r\n" - " /FontName /%s\r\n" + " /FontName /7%s\r\n" " /Flags 4\r\n" " /FontBBox [ %ld %ld %ld %ld ]\r\n" " /ItalicAngle 0\r\n" " /Ascent %ld\r\n" " /Descent %ld\r\n" - " /CapHeight %ld\r\n" + " /CapHeight 500\r\n" " /StemV 80\r\n" " /StemH 80\r\n" " /FontFile2 %u 0 R\r\n" @@ -2041,30 +1932,14 @@ _cairo_pdf_surface_emit_truetype_font_subset (cairo_pdf_surface_t *surface, "endobj\r\n", descriptor.id, subset.base_font, - (long)(subset.x_min*PDF_UNITS_PER_EM), - (long)(subset.y_min*PDF_UNITS_PER_EM), - (long)(subset.x_max*PDF_UNITS_PER_EM), - (long)(subset.y_max*PDF_UNITS_PER_EM), - (long)(subset.ascent*PDF_UNITS_PER_EM), - (long)(subset.descent*PDF_UNITS_PER_EM), - (long)(subset.y_max*PDF_UNITS_PER_EM), + subset.x_min, + subset.y_min, + subset.x_max, + subset.y_max, + subset.ascent, + subset.descent, stream.id); - encoding = _cairo_pdf_surface_new_object (surface); - _cairo_output_stream_printf (surface->output, - "%d 0 obj\r\n" - "<< /Type /Encoding\r\n" - " /Differences [0 ", - encoding.id); - - for (i = 0; i < font_subset->num_glyphs; i++) - _cairo_output_stream_printf (surface->output, "/g%d ", i); - - _cairo_output_stream_printf (surface->output, - " ]\r\n" - ">>\r\n" - "endobj\r\n"); - subset_resource = _cairo_pdf_surface_new_object (surface); _cairo_output_stream_printf (surface->output, "%d 0 obj\r\n" @@ -2074,28 +1949,19 @@ _cairo_pdf_surface_emit_truetype_font_subset (cairo_pdf_surface_t *surface, " /FirstChar 0\r\n" " /LastChar %d\r\n" " /FontDescriptor %d 0 R\r\n" - " /Encoding %d 0 R\r\n" " /Widths [", subset_resource.id, subset.base_font, font_subset->num_glyphs - 1, - descriptor.id, - encoding.id); + descriptor.id); for (i = 0; i < font_subset->num_glyphs; i++) _cairo_output_stream_printf (surface->output, - " %ld", - (long)(subset.widths[i]*PDF_UNITS_PER_EM)); - - _cairo_output_stream_printf (surface->output, - " ]\r\n"); - - if (to_unicode_stream.id != 0) - _cairo_output_stream_printf (surface->output, - " /ToUnicode %d 0 R\r\n", - to_unicode_stream.id); + " %d", + subset.widths[i]); _cairo_output_stream_printf (surface->output, + " ]\r\n" ">>\r\n" "endobj\r\n"); @@ -2159,16 +2025,13 @@ static cairo_int_status_t _cairo_pdf_surface_emit_bitmap_glyph (cairo_pdf_surface_t *surface, cairo_scaled_font_t *scaled_font, unsigned long glyph_index, - cairo_pdf_resource_t *glyph_ret, - cairo_box_t *bbox, - double *width) + cairo_pdf_resource_t *glyph_ret) { cairo_scaled_glyph_t *scaled_glyph; cairo_status_t status; cairo_image_surface_t *image; unsigned char *row, *byte; int rows, cols; - double x_advance, y_advance; status = _cairo_scaled_glyph_lookup (scaled_font, glyph_index, @@ -2178,12 +2041,6 @@ _cairo_pdf_surface_emit_bitmap_glyph (cairo_pdf_surface_t *surface, if (status) return status; - x_advance = scaled_glyph->metrics.x_advance; - y_advance = scaled_glyph->metrics.y_advance; - cairo_matrix_transform_distance (&scaled_font->ctm, &x_advance, &y_advance); - *bbox = scaled_glyph->bbox; - *width = x_advance; - image = scaled_glyph->surface; if (image->format != CAIRO_FORMAT_A1) { image = _cairo_image_surface_clone (image, CAIRO_FORMAT_A1); @@ -2191,18 +2048,17 @@ _cairo_pdf_surface_emit_bitmap_glyph (cairo_pdf_surface_t *surface, return cairo_surface_status (&image->base); } - *glyph_ret = _cairo_pdf_surface_open_stream (surface, TRUE, NULL); + *glyph_ret = _cairo_pdf_surface_open_stream (surface, FALSE, NULL); _cairo_output_stream_printf (surface->output, - "%f 0 %f %f %f %f d1\r\n", - x_advance, + "0 0 %f %f %f %f d1\r\n", _cairo_fixed_to_double (scaled_glyph->bbox.p1.x), - _cairo_fixed_to_double (scaled_glyph->bbox.p2.y), + - _cairo_fixed_to_double (scaled_glyph->bbox.p2.y), _cairo_fixed_to_double (scaled_glyph->bbox.p2.x), - _cairo_fixed_to_double (scaled_glyph->bbox.p1.y)); + - _cairo_fixed_to_double (scaled_glyph->bbox.p1.y)); _cairo_output_stream_printf (surface->output, - "%f 0 0 %f %f %f cm\r\n", + "%f 0.0 0.0 %f %f %f cm\r\n", _cairo_fixed_to_double (scaled_glyph->bbox.p2.x) - _cairo_fixed_to_double (scaled_glyph->bbox.p1.x), _cairo_fixed_to_double (scaled_glyph->bbox.p1.y) - _cairo_fixed_to_double (scaled_glyph->bbox.p2.y), _cairo_fixed_to_double (scaled_glyph->bbox.p1.x), @@ -2241,9 +2097,7 @@ static void _cairo_pdf_surface_emit_glyph (cairo_pdf_surface_t *surface, cairo_scaled_font_t *scaled_font, unsigned long glyph_index, - cairo_pdf_resource_t *glyph_ret, - cairo_box_t *bbox, - double *width) + cairo_pdf_resource_t *glyph_ret) { cairo_status_t status; @@ -2255,9 +2109,7 @@ _cairo_pdf_surface_emit_glyph (cairo_pdf_surface_t *surface, status = _cairo_pdf_surface_emit_bitmap_glyph (surface, scaled_font, glyph_index, - glyph_ret, - bbox, - width); + glyph_ret); if (status) _cairo_surface_set_error (&surface->base, status); @@ -2267,13 +2119,10 @@ static cairo_status_t _cairo_pdf_surface_emit_type3_font_subset (cairo_pdf_surface_t *surface, cairo_scaled_font_subset_t *font_subset) { - cairo_pdf_resource_t *glyphs, encoding, char_procs, subset_resource, to_unicode_stream; + cairo_pdf_resource_t *glyphs, encoding, char_procs, subset_resource; cairo_pdf_font_t font; cairo_matrix_t matrix; - double *widths; unsigned int i; - cairo_box_t font_bbox = {{0,0},{0,0}}; - cairo_box_t bbox = {{0,0},{0,0}}; glyphs = malloc (font_subset->num_glyphs * sizeof (cairo_pdf_resource_t)); if (glyphs == NULL) { @@ -2281,35 +2130,11 @@ _cairo_pdf_surface_emit_type3_font_subset (cairo_pdf_surface_t *surface, return CAIRO_STATUS_NO_MEMORY; } - widths = malloc (font_subset->num_glyphs * sizeof (double)); - if (widths == NULL) { - free (glyphs); - _cairo_surface_set_error (&surface->base, CAIRO_STATUS_NO_MEMORY); - return CAIRO_STATUS_NO_MEMORY; - } - for (i = 0; i < font_subset->num_glyphs; i++) { _cairo_pdf_surface_emit_glyph (surface, font_subset->scaled_font, font_subset->glyphs[i], - &glyphs[i], - &bbox, - &widths[i]); - if (i == 0) { - font_bbox.p1.x = bbox.p1.x; - font_bbox.p1.y = bbox.p1.y; - font_bbox.p2.x = bbox.p2.x; - font_bbox.p2.y = bbox.p2.y; - } else { - if (bbox.p1.x < font_bbox.p1.x) - font_bbox.p1.x = bbox.p1.x; - if (bbox.p1.y < font_bbox.p1.y) - font_bbox.p1.y = bbox.p1.y; - if (bbox.p2.x > font_bbox.p2.x) - font_bbox.p2.x = bbox.p2.x; - if (bbox.p2.y > font_bbox.p2.y) - font_bbox.p2.y = bbox.p2.y; - } + &glyphs[i]); } encoding = _cairo_pdf_surface_new_object (surface); @@ -2339,8 +2164,6 @@ _cairo_pdf_surface_emit_type3_font_subset (cairo_pdf_surface_t *surface, free (glyphs); - to_unicode_stream = _cairo_pdf_surface_emit_toUnicode_stream (surface, font_subset); - subset_resource = _cairo_pdf_surface_new_object (surface); matrix = font_subset->scaled_font->scale; cairo_matrix_invert (&matrix); @@ -2348,17 +2171,13 @@ _cairo_pdf_surface_emit_type3_font_subset (cairo_pdf_surface_t *surface, "%d 0 obj\r\n" "<< /Type /Font\r\n" " /Subtype /Type3\r\n" - " /FontBBox [%f %f %f %f]\r\n" + " /FontBBox [0 0 0 0]\r\n" " /FontMatrix [ %f %f %f %f 0 0 ]\r\n" " /Encoding %d 0 R\r\n" " /CharProcs %d 0 R\r\n" " /FirstChar 0\r\n" " /LastChar %d\r\n", subset_resource.id, - _cairo_fixed_to_double (font_bbox.p1.x), - _cairo_fixed_to_double (font_bbox.p1.y), - _cairo_fixed_to_double (font_bbox.p2.x), - _cairo_fixed_to_double (font_bbox.p2.y), matrix.xx, matrix.yx, -matrix.xy, @@ -2370,15 +2189,9 @@ _cairo_pdf_surface_emit_type3_font_subset (cairo_pdf_surface_t *surface, _cairo_output_stream_printf (surface->output, " /Widths ["); for (i = 0; i < font_subset->num_glyphs; i++) - _cairo_output_stream_printf (surface->output, " %f", widths[i]); + _cairo_output_stream_printf (surface->output, " 0"); _cairo_output_stream_printf (surface->output, "]\r\n"); - free (widths); - - if (to_unicode_stream.id != 0) - _cairo_output_stream_printf (surface->output, - " /ToUnicode %d 0 R\r\n", - to_unicode_stream.id); _cairo_output_stream_printf (surface->output, ">>\r\n" @@ -2393,8 +2206,8 @@ _cairo_pdf_surface_emit_type3_font_subset (cairo_pdf_surface_t *surface, } static void -_cairo_pdf_surface_emit_unscaled_font_subset (cairo_scaled_font_subset_t *font_subset, - void *closure) +_cairo_pdf_surface_emit_font_subset (cairo_scaled_font_subset_t *font_subset, + void *closure) { cairo_pdf_surface_t *surface = closure; cairo_status_t status; @@ -2416,14 +2229,6 @@ _cairo_pdf_surface_emit_unscaled_font_subset (cairo_scaled_font_subset_t *font_s status = _cairo_pdf_surface_emit_type1_fallback_font (surface, font_subset); if (status != CAIRO_INT_STATUS_UNSUPPORTED) return; -} - -static void -_cairo_pdf_surface_emit_scaled_font_subset (cairo_scaled_font_subset_t *font_subset, - void *closure) -{ - cairo_pdf_surface_t *surface = closure; - cairo_status_t status; status = _cairo_pdf_surface_emit_type3_font_subset (surface, font_subset); if (status != CAIRO_INT_STATUS_UNSUPPORTED) @@ -2435,12 +2240,9 @@ _cairo_pdf_surface_emit_font_subsets (cairo_pdf_surface_t *surface) { cairo_status_t status; - status = _cairo_scaled_font_subsets_foreach_unscaled (surface->font_subsets, - _cairo_pdf_surface_emit_unscaled_font_subset, - surface); - status = _cairo_scaled_font_subsets_foreach_scaled (surface->font_subsets, - _cairo_pdf_surface_emit_scaled_font_subset, - surface); + status = _cairo_scaled_font_subsets_foreach (surface->font_subsets, + _cairo_pdf_surface_emit_font_subset, + surface); _cairo_scaled_font_subsets_destroy (surface->font_subsets); surface->font_subsets = NULL; @@ -2450,6 +2252,114 @@ _cairo_pdf_surface_emit_font_subsets (cairo_pdf_surface_t *surface) return CAIRO_STATUS_SUCCESS; } +#if 0 +static cairo_status_t +_cairo_pdf_surface_write_fonts (cairo_pdf_surface_t *surface) +{ + cairo_font_subset_t *font; + cairo_pdf_resource_t font_resource; + int num_fonts, i, j; + const char *data; + char *compressed; + unsigned long data_size, compressed_size; + cairo_pdf_resource_t stream, descriptor; + cairo_status_t status = CAIRO_STATUS_SUCCESS; + + num_fonts = _cairo_array_num_elements (&surface->fonts); + for (i = 0; i < num_fonts; i++) { + _cairo_array_copy_element (&surface->fonts, i, &font); + + status = _cairo_font_subset_generate (font, &data, &data_size); + if (status) + goto fail; + + compressed = compress_dup (data, data_size, &compressed_size); + if (compressed == NULL) { + status = CAIRO_STATUS_NO_MEMORY; + goto fail; + } + + stream = _cairo_pdf_surface_new_object (surface); + _cairo_output_stream_printf (surface->output, + "%d 0 obj\r\n" + "<< /Filter /FlateDecode\r\n" + " /Length %lu\r\n" + " /Length1 %lu\r\n" + ">>\r\n" + "stream\r\n", + stream.id, + compressed_size, + data_size); + _cairo_output_stream_write (surface->output, compressed, compressed_size); + _cairo_output_stream_printf (surface->output, + "\r\n" + "endstream\r\n" + "endobj\r\n"); + free (compressed); + + descriptor = _cairo_pdf_surface_new_object (surface); + _cairo_output_stream_printf (surface->output, + "%d 0 obj\r\n" + "<< /Type /FontDescriptor\r\n" + " /FontName /7%s\r\n" + " /Flags 4\r\n" + " /FontBBox [ %ld %ld %ld %ld ]\r\n" + " /ItalicAngle 0\r\n" + " /Ascent %ld\r\n" + " /Descent %ld\r\n" + " /CapHeight 500\r\n" + " /StemV 80\r\n" + " /StemH 80\r\n" + " /FontFile2 %u 0 R\r\n" + ">>\r\n" + "endobj\r\n", + descriptor.id, + font->base_font, + font->x_min, + font->y_min, + font->x_max, + font->y_max, + font->ascent, + font->descent, + stream.id); + + font_resource.id = font->font_id; + _cairo_pdf_surface_update_object (surface, font_resource); + _cairo_output_stream_printf (surface->output, + "%d 0 obj\r\n" + "<< /Type /Font\r\n" + " /Subtype /TrueType\r\n" + " /BaseFont /%s\r\n" + " /FirstChar 0\r\n" + " /LastChar %d\r\n" + " /FontDescriptor %d 0 R\r\n" + " /Widths ", + font->font_id, + font->base_font, + font->num_glyphs, + descriptor.id); + + _cairo_output_stream_printf (surface->output, + "["); + + for (j = 0; j < font->num_glyphs; j++) + _cairo_output_stream_printf (surface->output, + " %d", + font->widths[j]); + + _cairo_output_stream_printf (surface->output, + " ]\r\n" + ">>\r\n" + "endobj\r\n"); + + fail: + _cairo_font_subset_destroy (font); + } + + return status; +} +#endif + static cairo_pdf_resource_t _cairo_pdf_surface_write_catalog (cairo_pdf_surface_t *surface) { @@ -2534,12 +2444,9 @@ _cairo_pdf_surface_write_page (cairo_pdf_surface_t *surface) stream.id); } _cairo_output_stream_printf (surface->output, - " ]\r\n" - " /Group <<\r\n" - " /Type /Group\r\n" - " /S /Transparency\r\n" - " /CS /DeviceRGB\r\n" - " >>\r\n" + " ]\r\n"); + + _cairo_output_stream_printf (surface->output, ">>\r\n" "endobj\r\n"); @@ -2571,11 +2478,10 @@ _surface_pattern_supported (cairo_surface_pattern_t *pattern) switch (extend) { case CAIRO_EXTEND_NONE: case CAIRO_EXTEND_REPEAT: - case CAIRO_EXTEND_REFLECT: - /* There's no point returning FALSE for EXTEND_PAD, as the image - * surface does not currently implement it either */ - case CAIRO_EXTEND_PAD: return TRUE; + case CAIRO_EXTEND_REFLECT: + case CAIRO_EXTEND_PAD: + return FALSE; } ASSERT_NOT_REACHED; @@ -2615,7 +2521,7 @@ _cairo_pdf_test_force_fallbacks (void) } static cairo_int_status_t -__cairo_pdf_surface_operation_supported (cairo_pdf_surface_t *surface, +_operation_supported (cairo_pdf_surface_t *surface, cairo_operator_t op, cairo_pattern_t *pattern) { @@ -2634,11 +2540,11 @@ __cairo_pdf_surface_operation_supported (cairo_pdf_surface_t *surface, } static cairo_int_status_t -_cairo_pdf_surface_analyze_operation (cairo_pdf_surface_t *surface, +_analyze_operation (cairo_pdf_surface_t *surface, cairo_operator_t op, cairo_pattern_t *pattern) { - if (__cairo_pdf_surface_operation_supported (surface, op, pattern)) + if (_operation_supported (surface, op, pattern)) return CAIRO_STATUS_SUCCESS; else return CAIRO_INT_STATUS_UNSUPPORTED; @@ -2653,7 +2559,7 @@ _cairo_pdf_surface_paint (void *abstract_surface, cairo_status_t status; if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE) - return _cairo_pdf_surface_analyze_operation (surface, op, source); + return _analyze_operation (surface, op, source); /* XXX: It would be nice to be able to assert this condition * here. But, we actually allow one 'cheat' that is used when @@ -2662,10 +2568,10 @@ _cairo_pdf_surface_paint (void *abstract_surface, * possible only because there is nothing between the fallback * images and the paper, nor is anything painted above. */ /* - assert (__cairo_pdf_surface_operation_supported (op, source)); + assert (_operation_supported (op, source)); */ - status = _cairo_pdf_surface_emit_pattern (surface, source); + status = emit_pattern (surface, source); if (status) return status; @@ -2774,11 +2680,11 @@ _cairo_pdf_surface_stroke (void *abstract_surface, cairo_status_t status; if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE) - return _cairo_pdf_surface_analyze_operation (surface, op, source); + return _analyze_operation (surface, op, source); - assert (__cairo_pdf_surface_operation_supported (surface, op, source)); + assert (_operation_supported (surface, op, source)); - status = _cairo_pdf_surface_emit_pattern (surface, source); + status = emit_pattern (surface, source); if (status) return status; @@ -2823,11 +2729,11 @@ _cairo_pdf_surface_fill (void *abstract_surface, pdf_path_info_t info; if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE) - return _cairo_pdf_surface_analyze_operation (surface, op, source); + return _analyze_operation (surface, op, source); - assert (__cairo_pdf_surface_operation_supported (surface, op, source)); + assert (_operation_supported (surface, op, source)); - status = _cairo_pdf_surface_emit_pattern (surface, source); + status = emit_pattern (surface, source); if (status) return status; @@ -2876,11 +2782,11 @@ _cairo_pdf_surface_show_glyphs (void *abstract_surface, int i; if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE) - return _cairo_pdf_surface_analyze_operation (surface, op, source); + return _analyze_operation (surface, op, source); - assert (__cairo_pdf_surface_operation_supported (surface, op, source)); + assert (_operation_supported (surface, op, source)); - status = _cairo_pdf_surface_emit_pattern (surface, source); + status = emit_pattern (surface, source); if (status) return status; @@ -2920,7 +2826,7 @@ _cairo_pdf_surface_show_glyphs (void *abstract_surface, _cairo_output_stream_printf (surface->output, "%f %f Td <%02x> Tj\r\n", (glyphs[i].x - glyphs[i-1].x)/scaled_font->scale.xx, - (glyphs[i].y - glyphs[i-1].y)/-scaled_font->scale.yy, + (glyphs[i].y - glyphs[i-1].y)/scaled_font->scale.yy, subset_glyph_index); } } diff --git a/gfx/cairo/cairo/src/cairo-polygon.c b/gfx/cairo/cairo/src/cairo-polygon.c index 52c72b710d1..dc9d3805b16 100644 --- a/gfx/cairo/cairo/src/cairo-polygon.c +++ b/gfx/cairo/cairo/src/cairo-polygon.c @@ -40,7 +40,7 @@ /* private functions */ static cairo_status_t -_cairo_polygon_grow (cairo_polygon_t *polygon); +_cairo_polygon_grow_by (cairo_polygon_t *polygon, int additional); void _cairo_polygon_init (cairo_polygon_t *polygon) @@ -50,55 +50,42 @@ _cairo_polygon_init (cairo_polygon_t *polygon) polygon->edges_size = 0; polygon->edges = NULL; - polygon->has_current_point = FALSE; + polygon->has_current_point = 0; } void _cairo_polygon_fini (cairo_polygon_t *polygon) { - if (polygon->edges && polygon->edges != polygon->edges_embedded) + if (polygon->edges_size) { free (polygon->edges); + polygon->edges = NULL; + polygon->edges_size = 0; + polygon->num_edges = 0; + } - polygon->edges = NULL; - polygon->edges_size = 0; - polygon->num_edges = 0; - - polygon->has_current_point = FALSE; + polygon->has_current_point = 0; } -/* make room for at least one more edge */ static cairo_status_t -_cairo_polygon_grow (cairo_polygon_t *polygon) +_cairo_polygon_grow_by (cairo_polygon_t *polygon, int additional) { cairo_edge_t *new_edges; int old_size = polygon->edges_size; - int embedded_size = sizeof (polygon->edges_embedded) / sizeof (polygon->edges_embedded[0]); - int new_size = 2 * MAX (old_size, 16); + int new_size = polygon->num_edges + additional; - /* we have a local buffer at polygon->edges_embedded. try to fulfill the request - * from there. */ - if (old_size < embedded_size) { - polygon->edges = polygon->edges_embedded; - polygon->edges_size = embedded_size; + if (new_size <= polygon->edges_size) { return CAIRO_STATUS_SUCCESS; } - assert (polygon->num_edges <= polygon->edges_size); - - if (polygon->edges == polygon->edges_embedded) { - new_edges = malloc (new_size * sizeof (cairo_edge_t)); - if (new_edges) - memcpy (new_edges, polygon->edges, old_size * sizeof (cairo_edge_t)); - } else { - new_edges = realloc (polygon->edges, new_size * sizeof (cairo_edge_t)); - } + polygon->edges_size = new_size; + new_edges = realloc (polygon->edges, polygon->edges_size * sizeof (cairo_edge_t)); if (new_edges == NULL) { + polygon->edges_size = old_size; return CAIRO_STATUS_NO_MEMORY; } polygon->edges = new_edges; - polygon->edges_size = new_size; return CAIRO_STATUS_SUCCESS; } @@ -115,7 +102,8 @@ _cairo_polygon_add_edge (cairo_polygon_t *polygon, cairo_point_t *p1, cairo_poin } if (polygon->num_edges >= polygon->edges_size) { - status = _cairo_polygon_grow (polygon); + int additional = polygon->edges_size ? polygon->edges_size : 16; + status = _cairo_polygon_grow_by (polygon, additional); if (status) { return status; } @@ -146,7 +134,7 @@ _cairo_polygon_move_to (cairo_polygon_t *polygon, cairo_point_t *point) if (! polygon->has_current_point) polygon->first_point = *point; polygon->current_point = *point; - polygon->has_current_point = TRUE; + polygon->has_current_point = 1; return CAIRO_STATUS_SUCCESS; } @@ -177,7 +165,7 @@ _cairo_polygon_close (cairo_polygon_t *polygon) if (status) return status; - polygon->has_current_point = FALSE; + polygon->has_current_point = 0; } return CAIRO_STATUS_SUCCESS; diff --git a/gfx/cairo/cairo/src/cairo-private.h b/gfx/cairo/cairo/src/cairo-private.h index 14cc79aea20..7051f7ebd18 100644 --- a/gfx/cairo/cairo/src/cairo-private.h +++ b/gfx/cairo/cairo/src/cairo-private.h @@ -44,12 +44,9 @@ struct _cairo { cairo_status_t status; - cairo_user_data_array_t user_data; + cairo_path_fixed_t path; cairo_gstate_t *gstate; - cairo_gstate_t gstate_tail[1]; - - cairo_path_fixed_t path[1]; }; #endif /* CAIRO_PRIVATE_H */ diff --git a/gfx/cairo/cairo/src/cairo-ps-surface.c b/gfx/cairo/cairo/src/cairo-ps-surface.c index 5f43e98c797..45d9fe70b1c 100644 --- a/gfx/cairo/cairo/src/cairo-ps-surface.c +++ b/gfx/cairo/cairo/src/cairo-ps-surface.c @@ -484,18 +484,18 @@ _cairo_ps_surface_emit_truetype_font_subset (cairo_ps_surface_t *surface, /* FIXME: Figure out how subset->x_max etc maps to the /FontBBox */ - for (i = 0; i < font_subset->num_glyphs; i++) + for (i = 1; i < font_subset->num_glyphs; i++) _cairo_output_stream_printf (surface->final_stream, "Encoding %d /g%d put\n", i, i); _cairo_output_stream_printf (surface->final_stream, "/CharStrings %d dict dup begin\n" "/.notdef 0 def\n", - font_subset->num_glyphs + 1); + font_subset->num_glyphs); - for (i = 0; i < font_subset->num_glyphs; i++) + for (i = 1; i < font_subset->num_glyphs; i++) _cairo_output_stream_printf (surface->final_stream, - "/g%d %d def\n", i, i + 1); + "/g%d %d def\n", i, i); _cairo_output_stream_printf (surface->final_stream, "end readonly def\n"); @@ -709,8 +709,8 @@ _cairo_ps_surface_emit_type3_font_subset (cairo_ps_surface_t *surface, static void -_cairo_ps_surface_emit_unscaled_font_subset (cairo_scaled_font_subset_t *font_subset, - void *closure) +_cairo_ps_surface_emit_font_subset (cairo_scaled_font_subset_t *font_subset, + void *closure) { cairo_ps_surface_t *surface = closure; cairo_status_t status; @@ -728,14 +728,6 @@ _cairo_ps_surface_emit_unscaled_font_subset (cairo_scaled_font_subset_t *font_su status = _cairo_ps_surface_emit_type1_font_fallback (surface, font_subset); if (status != CAIRO_INT_STATUS_UNSUPPORTED) return; -} - -static void -_cairo_ps_surface_emit_scaled_font_subset (cairo_scaled_font_subset_t *font_subset, - void *closure) -{ - cairo_ps_surface_t *surface = closure; - cairo_status_t status; status = _cairo_ps_surface_emit_type3_font_subset (surface, font_subset); if (status != CAIRO_INT_STATUS_UNSUPPORTED) @@ -750,12 +742,9 @@ _cairo_ps_surface_emit_font_subsets (cairo_ps_surface_t *surface) _cairo_output_stream_printf (surface->final_stream, "%% _cairo_ps_surface_emit_font_subsets\n"); - status = _cairo_scaled_font_subsets_foreach_unscaled (surface->font_subsets, - _cairo_ps_surface_emit_unscaled_font_subset, - surface); - status = _cairo_scaled_font_subsets_foreach_scaled (surface->font_subsets, - _cairo_ps_surface_emit_scaled_font_subset, - surface); + status = _cairo_scaled_font_subsets_foreach (surface->font_subsets, + _cairo_ps_surface_emit_font_subset, + surface); _cairo_scaled_font_subsets_destroy (surface->font_subsets); surface->font_subsets = NULL; @@ -809,8 +798,7 @@ _cairo_ps_surface_create_for_stream_internal (cairo_output_stream_t *stream, if (status) goto CLEANUP_TMPFILE; - surface->font_subsets = _cairo_scaled_font_subsets_create (PS_SURFACE_MAX_GLYPHS_PER_FONT, - PS_SURFACE_MAX_GLYPHS_PER_FONT); + surface->font_subsets = _cairo_scaled_font_subsets_create (PS_SURFACE_MAX_GLYPHS_PER_FONT); if (! surface->font_subsets) goto CLEANUP_OUTPUT_STREAM; @@ -880,9 +868,7 @@ cairo_ps_surface_create (const char *filename, status = _cairo_output_stream_get_status (stream); if (status) { _cairo_error (status); - return (status == CAIRO_STATUS_WRITE_ERROR) ? - (cairo_surface_t*) &_cairo_surface_nil_write_error : - (cairo_surface_t*) &_cairo_surface_nil; + return (cairo_surface_t*) &_cairo_surface_nil; } return _cairo_ps_surface_create_for_stream_internal (stream, @@ -1337,37 +1323,9 @@ color_is_gray (cairo_color_t *color) static cairo_bool_t surface_pattern_supported (const cairo_surface_pattern_t *pattern) { - cairo_extend_t extend; - - if (pattern->surface->backend->acquire_source_image == NULL) - return FALSE; - - /* Does an ALPHA-only source surface even make sense? Maybe, but I - * don't think it's worth the extra code to support it. */ - -/* XXX: Need to write this function here... - content = cairo_surface_get_content (pattern->surface); - if (content == CAIRO_CONTENT_ALPHA) - return FALSE; -*/ - - /* Cast away the const, trusting get_extend not to muck with it. - * And I really wish I had a way to cast away just the const, and - * not potentially coerce this pointer to an incorrect type at the - * same time. :-( - */ - extend = cairo_pattern_get_extend ((cairo_pattern_t*)&pattern->base); - switch (extend) { - case CAIRO_EXTEND_NONE: - case CAIRO_EXTEND_REPEAT: - case CAIRO_EXTEND_REFLECT: - /* There's no point returning FALSE for EXTEND_PAD, as the image - * surface does not currently implement it either */ - case CAIRO_EXTEND_PAD: + if (pattern->surface->backend->acquire_source_image != NULL) return TRUE; - } - ASSERT_NOT_REACHED; return FALSE; } @@ -1404,7 +1362,7 @@ _cairo_ps_test_force_fallbacks (void) } static cairo_int_status_t -_cairo_ps_surface_operation_supported (cairo_ps_surface_t *surface, +operation_supported (cairo_ps_surface_t *surface, cairo_operator_t op, const cairo_pattern_t *pattern) { @@ -1424,11 +1382,11 @@ _cairo_ps_surface_operation_supported (cairo_ps_surface_t *surface, } static cairo_int_status_t -_cairo_ps_surface_analyze_operation (cairo_ps_surface_t *surface, +_analyze_operation (cairo_ps_surface_t *surface, cairo_operator_t op, const cairo_pattern_t *pattern) { - if (_cairo_ps_surface_operation_supported (surface, op, pattern)) + if (operation_supported (surface, op, pattern)) return CAIRO_STATUS_SUCCESS; else return CAIRO_INT_STATUS_UNSUPPORTED; @@ -1558,8 +1516,9 @@ _string_array_stream_create (cairo_output_stream_t *output) * surface we can render natively in PS. */ static cairo_status_t -_cairo_ps_surface_emit_image (cairo_ps_surface_t *surface, +emit_image (cairo_ps_surface_t *surface, cairo_image_surface_t *image, + cairo_matrix_t *matrix, const char *name) { cairo_status_t status; @@ -1668,14 +1627,17 @@ _cairo_ps_surface_emit_image (cairo_ps_surface_t *surface, " /%sDataIndex %sDataIndex 1 add def\n" " %sDataIndex %sData length 1 sub gt { /%sDataIndex 0 def } if\n" " } /ASCII85Decode filter /LZWDecode filter\n" - " /ImageMatrix [ 1 0 0 1 0 0 ]\n" + " /ImageMatrix [ %f %f %f %f %f %f ]\n" " >>\n" " image\n" "} def\n", name, opaque_image->width, opaque_image->height, - name, name, name, name, name, name, name); + name, name, name, name, name, name, name, + matrix->xx, matrix->yx, + matrix->xy, matrix->yy, + 0.0, 0.0); status = CAIRO_STATUS_SUCCESS; @@ -1690,7 +1652,7 @@ _cairo_ps_surface_emit_image (cairo_ps_surface_t *surface, } static void -_cairo_ps_surface_emit_solid_pattern (cairo_ps_surface_t *surface, +emit_solid_pattern (cairo_ps_surface_t *surface, cairo_solid_pattern_t *pattern) { if (color_is_gray (&pattern->color)) @@ -1706,13 +1668,12 @@ _cairo_ps_surface_emit_solid_pattern (cairo_ps_surface_t *surface, } static void -_cairo_ps_surface_emit_surface_pattern (cairo_ps_surface_t *surface, +emit_surface_pattern (cairo_ps_surface_t *surface, cairo_surface_pattern_t *pattern) { double bbox_width, bbox_height; - double xstep, ystep; + int xstep, ystep; cairo_matrix_t inverse = pattern->base.matrix; - cairo_matrix_invert (&inverse); if (_cairo_surface_is_meta (pattern->surface)) { @@ -1733,49 +1694,32 @@ _cairo_ps_surface_emit_surface_pattern (cairo_ps_surface_t *surface, &image_extra); assert (status == CAIRO_STATUS_SUCCESS); - _cairo_ps_surface_emit_image (surface, image, "MyPattern"); + emit_image (surface, image, &pattern->base.matrix, "MyPattern"); bbox_width = image->width; bbox_height = image->height; + cairo_matrix_transform_distance (&inverse, + &bbox_width, &bbox_height); + /* In PostScript, (as far as I can tell), all patterns are + * repeating. So we support cairo's EXTEND_NONE semantics by + * setting the repeat step size to the larger of the image size + * and the extents of the destination surface. That way we + * guarantee the pattern will not repeat. + */ switch (pattern->base.extend) { - /* We implement EXTEND_PAD like EXTEND_NONE for now */ - case CAIRO_EXTEND_PAD: case CAIRO_EXTEND_NONE: - { - /* In PS/PDF, (as far as I can tell), all patterns are - * repeating. So we support cairo's EXTEND_NONE semantics - * by setting the repeat step size to a size large enough - * to guarantee that no more than a single occurrence will - * be visible. - * - * First, map the surface extents into pattern space (since - * xstep and ystep are in pattern space). Then use an upper - * bound on the length of the diagonal of the pattern image - * and the surface as repeat size. This guarantees to never - * repeat visibly. - */ - double x1 = 0.0, y1 = 0.0; - double x2 = surface->width, y2 = surface->height; - _cairo_matrix_transform_bounding_box (&pattern->base.matrix, - &x1, &y1, &x2, &y2, - NULL); - - /* Rather than computing precise bounds of the union, just - * add the surface extents unconditionally. We only - * required an answer that's large enough, we don't really - * care if it's not as tight as possible.*/ - xstep = ystep = ceil ((x2 - x1) + (y2 - y1) + - image->width + image->height); + xstep = MAX (image->width, surface->width); + ystep = MAX (image->height, surface->height); break; - } case CAIRO_EXTEND_REPEAT: - case CAIRO_EXTEND_REFLECT: xstep = image->width; ystep = image->height; break; - /* All the rest (if any) should have been analyzed away, so these - * cases should be unreachable. */ + /* All the rest should have been analyzed away, so these cases + * should be unreachable. */ + case CAIRO_EXTEND_REFLECT: + case CAIRO_EXTEND_PAD: default: ASSERT_NOT_REACHED; xstep = 0; @@ -1790,39 +1734,37 @@ _cairo_ps_surface_emit_surface_pattern (cairo_ps_surface_t *surface, " /PaintType 1\n" " /TilingType 1\n"); _cairo_output_stream_printf (surface->stream, - " /BBox [0 0 %f %f]\n", - bbox_width, bbox_height); + " /BBox [0 0 %d %d]\n", + (int) bbox_width, (int) bbox_height); _cairo_output_stream_printf (surface->stream, - " /XStep %f /YStep %f\n", + " /XStep %d /YStep %d\n", xstep, ystep); _cairo_output_stream_printf (surface->stream, " /PaintProc { MyPattern } bind\n" ">>\n"); _cairo_output_stream_printf (surface->stream, - "[ %f %f %f %f %f %f ]\n", - inverse.xx, inverse.yx, - inverse.xy, inverse.yy, + "[ 1 0 0 1 %f %f ]\n", inverse.x0, inverse.y0); _cairo_output_stream_printf (surface->stream, "makepattern setpattern\n"); } static void -_cairo_ps_surface_emit_linear_pattern (cairo_ps_surface_t *surface, +emit_linear_pattern (cairo_ps_surface_t *surface, cairo_linear_pattern_t *pattern) { /* XXX: NYI */ } static void -_cairo_ps_surface_emit_radial_pattern (cairo_ps_surface_t *surface, +emit_radial_pattern (cairo_ps_surface_t *surface, cairo_radial_pattern_t *pattern) { /* XXX: NYI */ } static void -_cairo_ps_surface_emit_pattern (cairo_ps_surface_t *surface, cairo_pattern_t *pattern) +emit_pattern (cairo_ps_surface_t *surface, cairo_pattern_t *pattern) { /* FIXME: We should keep track of what pattern is currently set in * the postscript file and only emit code if we're setting a @@ -1830,19 +1772,19 @@ _cairo_ps_surface_emit_pattern (cairo_ps_surface_t *surface, cairo_pattern_t *pa switch (pattern->type) { case CAIRO_PATTERN_TYPE_SOLID: - _cairo_ps_surface_emit_solid_pattern (surface, (cairo_solid_pattern_t *) pattern); + emit_solid_pattern (surface, (cairo_solid_pattern_t *) pattern); break; case CAIRO_PATTERN_TYPE_SURFACE: - _cairo_ps_surface_emit_surface_pattern (surface, (cairo_surface_pattern_t *) pattern); + emit_surface_pattern (surface, (cairo_surface_pattern_t *) pattern); break; case CAIRO_PATTERN_TYPE_LINEAR: - _cairo_ps_surface_emit_linear_pattern (surface, (cairo_linear_pattern_t *) pattern); + emit_linear_pattern (surface, (cairo_linear_pattern_t *) pattern); break; case CAIRO_PATTERN_TYPE_RADIAL: - _cairo_ps_surface_emit_radial_pattern (surface, (cairo_radial_pattern_t *) pattern); + emit_radial_pattern (surface, (cairo_radial_pattern_t *) pattern); break; } } @@ -1932,7 +1874,7 @@ _cairo_ps_surface_paint (void *abstract_surface, cairo_rectangle_int16_t extents, pattern_extents; if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE) - return _cairo_ps_surface_analyze_operation (surface, op, source); + return _analyze_operation (surface, op, source); /* XXX: It would be nice to be able to assert this condition * here. But, we actually allow one 'cheat' that is used when @@ -1941,7 +1883,7 @@ _cairo_ps_surface_paint (void *abstract_surface, * possible only because there is nothing between the fallback * images and the paper, nor is anything painted above. */ /* - assert (__cairo_ps_surface_operation_supported (op, source)); + assert (_operation_supported (op, source)); */ _cairo_output_stream_printf (stream, @@ -1951,7 +1893,7 @@ _cairo_ps_surface_paint (void *abstract_surface, _cairo_pattern_get_extents (source, &pattern_extents); _cairo_rectangle_intersect (&extents, &pattern_extents); - _cairo_ps_surface_emit_pattern (surface, source); + emit_pattern (surface, source); _cairo_output_stream_printf (stream, "%d %d M\n", extents.x, extents.y); @@ -2019,9 +1961,9 @@ _cairo_ps_surface_stroke (void *abstract_surface, double dash_offset = style->dash_offset; if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE) - return _cairo_ps_surface_analyze_operation (surface, op, source); + return _analyze_operation (surface, op, source); - assert (_cairo_ps_surface_operation_supported (surface, op, source)); + assert (operation_supported (surface, op, source)); _cairo_output_stream_printf (stream, @@ -2090,7 +2032,7 @@ _cairo_ps_surface_stroke (void *abstract_surface, } } - _cairo_ps_surface_emit_pattern (surface, source); + emit_pattern (surface, source); _cairo_output_stream_printf (stream, "gsave\n"); @@ -2150,14 +2092,14 @@ _cairo_ps_surface_fill (void *abstract_surface, const char *ps_operator; if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE) - return _cairo_ps_surface_analyze_operation (surface, op, source); + return _analyze_operation (surface, op, source); - assert (_cairo_ps_surface_operation_supported (surface, op, source)); + assert (operation_supported (surface, op, source)); _cairo_output_stream_printf (stream, "%% _cairo_ps_surface_fill\n"); - _cairo_ps_surface_emit_pattern (surface, source); + emit_pattern (surface, source); /* We're filling not stroking, so we pass CAIRO_LINE_CAP_ROUND. */ status = _cairo_ps_surface_emit_path (surface, stream, path, @@ -2208,9 +2150,9 @@ _cairo_ps_surface_show_glyphs (void *abstract_surface, cairo_output_stream_t *word_wrap; if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE) - return _cairo_ps_surface_analyze_operation (surface, op, source); + return _analyze_operation (surface, op, source); - assert (_cairo_ps_surface_operation_supported (surface, op, source)); + assert (operation_supported (surface, op, source)); _cairo_output_stream_printf (stream, "%% _cairo_ps_surface_show_glyphs\n"); @@ -2220,7 +2162,7 @@ _cairo_ps_surface_show_glyphs (void *abstract_surface, num_glyphs_unsigned = num_glyphs; - _cairo_ps_surface_emit_pattern (surface, source); + emit_pattern (surface, source); glyph_ids = malloc (num_glyphs_unsigned*sizeof (cairo_ps_glyph_id_t)); if (glyph_ids == NULL) return CAIRO_STATUS_NO_MEMORY; diff --git a/gfx/cairo/cairo/src/cairo-quartz-private.h b/gfx/cairo/cairo/src/cairo-quartz-private.h index 23d7d4be51f..f9db501c92b 100644 --- a/gfx/cairo/cairo/src/cairo-quartz-private.h +++ b/gfx/cairo/cairo/src/cairo-quartz-private.h @@ -1,7 +1,6 @@ /* cairo - a vector graphics library with display and print output * * Copyright © 2004 Calum Robinson - * Copyright (C) 2006,2007 Mozilla Corporation * * This library is free software; you can redistribute it and/or * modify it either under the terms of the GNU Lesser General Public @@ -32,43 +31,36 @@ * * Contributor(s): * Calum Robinson - * Vladimir Vukicevic */ #ifndef CAIRO_QUARTZ_PRIVATE_H #define CAIRO_QUARTZ_PRIVATE_H #include - -#ifdef CAIRO_HAS_QUARTZ_SURFACE #include typedef struct cairo_quartz_surface { cairo_surface_t base; - void *imageData; + CGContextRef context; - CGContextRef cgContext; - CGAffineTransform cgContextBaseCTM; + cairo_bool_t y_grows_down; cairo_rectangle_int16_t extents; - /* These are stored while drawing operations are in place, set up - * by quartz_setup_source() and quartz_finish_source() - */ - CGAffineTransform imageTransform; - CGImageRef sourceImage; - CGShadingRef sourceShading; - CGPatternRef sourcePattern; + pixman_region16_t *clip_region; } cairo_quartz_surface_t; -#endif /* CAIRO_HAS_QUARTZ_SURFACE */ -#if CAIRO_HAS_ATSUI_FONT +cairo_bool_t +_cairo_surface_is_quartz (cairo_surface_t *surface); + +cairo_bool_t +_cairo_scaled_font_is_atsui (cairo_scaled_font_t *sfont); + ATSUStyle _cairo_atsui_scaled_font_get_atsu_style (cairo_scaled_font_t *sfont); ATSUFontID _cairo_atsui_scaled_font_get_atsu_font_id (cairo_scaled_font_t *sfont); -#endif /* CAIRO_HAS_ATSUI_FONT */ #endif /* CAIRO_QUARTZ_PRIVATE_H */ diff --git a/gfx/cairo/cairo/src/cairo-quartz-surface.c b/gfx/cairo/cairo/src/cairo-quartz-surface.c index 33f3a10ca48..151961c5e19 100644 --- a/gfx/cairo/cairo/src/cairo-quartz-surface.c +++ b/gfx/cairo/cairo/src/cairo-quartz-surface.c @@ -1,7 +1,6 @@ -/* -*- Mode: c; c-basic-offset: 4; indent-tabs-mode: t; tab-width: 8; -*- */ /* cairo - a vector graphics library with display and print output * - * Copyright 2006, 2007 Mozilla Corporation + * Copyright © 2004 Calum Robinson * * This library is free software; you can redistribute it and/or * modify it either under the terms of the GNU Lesser General Public @@ -28,1749 +27,239 @@ * * The Original Code is the cairo graphics library. * - * The Initial Developer of the Original Code is Mozilla Corporation. + * The Initial Developer of the Original Code is Calum Robinson * * Contributor(s): - * Vladimir Vukicevic + * Calum Robinson */ -#include - #include "cairoint.h" - +#include "cairo-private.h" #include "cairo-quartz-private.h" -#undef QUARTZ_DEBUG - -#ifdef QUARTZ_DEBUG -#define ND(_x) fprintf _x -#else -#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)) -}; -typedef enum PrivateCGCompositeMode PrivateCGCompositeMode; -CG_EXTERN void CGContextSetCompositeOperation (CGContextRef, PrivateCGCompositeMode); -CG_EXTERN void CGContextResetCTM (CGContextRef); -CG_EXTERN void CGContextSetCTM (CGContextRef, CGAffineTransform); -CG_EXTERN void CGContextResetClip (CGContextRef); -CG_EXTERN CGSize CGContextGetPatternPhase (CGContextRef); - -/* We need to work with the 10.3 SDK as well (and 10.3 machines; luckily, 10.3.9 - * has all the stuff we care about, just some of it isn't exported in the SDK. - */ -#ifndef kCGBitmapByteOrder32Host -#define USE_10_3_WORKAROUNDS -#define kCGBitmapAlphaInfoMask 0x1F -#define kCGBitmapByteOrderMask 0x7000 -#define kCGBitmapByteOrder32Host 0 - -typedef uint32_t CGBitmapInfo; - -/* public in 10.4, present in 10.3.9 */ -CG_EXTERN void CGContextReplacePathWithStrokedPath (CGContextRef); -CG_EXTERN CGImageRef CGBitmapContextCreateImage (CGContextRef); -#endif - - -/* - * Utility functions - */ - -static void quartz_surface_to_png (cairo_quartz_surface_t *nq, char *dest); -static void quartz_image_to_png (CGImageRef, char *dest); - -/* - * Cairo path -> Quartz path conversion helpers - */ - -/* cairo path -> mutable path */ static cairo_status_t -_cairo_path_to_quartz_path_move_to (void *closure, cairo_point_t *point) +_cairo_quartz_surface_finish(void *abstract_surface) { - CGPathMoveToPoint ((CGMutablePathRef) closure, NULL, - _cairo_fixed_to_double(point->x), _cairo_fixed_to_double(point->y)); - return CAIRO_STATUS_SUCCESS; -} + cairo_quartz_surface_t *surface = abstract_surface; -static cairo_status_t -_cairo_path_to_quartz_path_line_to (void *closure, cairo_point_t *point) -{ - CGPathAddLineToPoint ((CGMutablePathRef) closure, NULL, - _cairo_fixed_to_double(point->x), _cairo_fixed_to_double(point->y)); - return CAIRO_STATUS_SUCCESS; -} - -static cairo_status_t -_cairo_path_to_quartz_path_curve_to (void *closure, cairo_point_t *p0, cairo_point_t *p1, cairo_point_t *p2) -{ - CGPathAddCurveToPoint ((CGMutablePathRef) closure, NULL, - _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_path_to_quartz_path_close_path (void *closure) -{ - CGPathCloseSubpath ((CGMutablePathRef) closure); - return CAIRO_STATUS_SUCCESS; -} - -/* cairo path -> execute in context */ -static cairo_status_t -_cairo_path_to_quartz_context_move_to (void *closure, cairo_point_t *point) -{ - //ND((stderr, "moveto: %f %f\n", _cairo_fixed_to_double(point->x), _cairo_fixed_to_double(point->y))); - CGContextMoveToPoint ((CGContextRef) closure, - _cairo_fixed_to_double(point->x), _cairo_fixed_to_double(point->y)); - return CAIRO_STATUS_SUCCESS; -} - -static cairo_status_t -_cairo_path_to_quartz_context_line_to (void *closure, cairo_point_t *point) -{ - //ND((stderr, "lineto: %f %f\n", _cairo_fixed_to_double(point->x), _cairo_fixed_to_double(point->y))); - if (CGContextIsPathEmpty ((CGContextRef) closure)) - CGContextMoveToPoint ((CGContextRef) closure, - _cairo_fixed_to_double(point->x), _cairo_fixed_to_double(point->y)); - else - CGContextAddLineToPoint ((CGContextRef) closure, - _cairo_fixed_to_double(point->x), _cairo_fixed_to_double(point->y)); - return CAIRO_STATUS_SUCCESS; -} - -static cairo_status_t -_cairo_path_to_quartz_context_curve_to (void *closure, cairo_point_t *p0, cairo_point_t *p1, cairo_point_t *p2) -{ - //ND( (stderr, "curveto: %f,%f %f,%f %f,%f\n", - // _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))); - - CGContextAddCurveToPoint ((CGContextRef) closure, - _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_path_to_quartz_context_close_path (void *closure) -{ - //ND((stderr, "closepath\n")); - CGContextClosePath ((CGContextRef) closure); - return CAIRO_STATUS_SUCCESS; -} - -static cairo_status_t -_cairo_quartz_cairo_path_to_quartz_path (cairo_path_fixed_t *path, - CGMutablePathRef cgPath) -{ - return _cairo_path_fixed_interpret (path, - CAIRO_DIRECTION_FORWARD, - _cairo_path_to_quartz_path_move_to, - _cairo_path_to_quartz_path_line_to, - _cairo_path_to_quartz_path_curve_to, - _cairo_path_to_quartz_path_close_path, - cgPath); -} - -static cairo_status_t -_cairo_quartz_cairo_path_to_quartz_context (cairo_path_fixed_t *path, - CGContextRef cgc) -{ - return _cairo_path_fixed_interpret (path, - CAIRO_DIRECTION_FORWARD, - _cairo_path_to_quartz_context_move_to, - _cairo_path_to_quartz_context_line_to, - _cairo_path_to_quartz_context_curve_to, - _cairo_path_to_quartz_context_close_path, - cgc); -} - -/* - * Misc helpers/callbacks - */ - -static PrivateCGCompositeMode -_cairo_quartz_cairo_operator_to_quartz (cairo_operator_t op) -{ - switch (op) { - case CAIRO_OPERATOR_CLEAR: - return kPrivateCGCompositeClear; - case CAIRO_OPERATOR_SOURCE: - return kPrivateCGCompositeCopy; - case CAIRO_OPERATOR_OVER: - return kPrivateCGCompositeSourceOver; - case CAIRO_OPERATOR_IN: - /* XXX This doesn't match image output */ - return kPrivateCGCompositeSourceIn; - case CAIRO_OPERATOR_OUT: - /* XXX This doesn't match image output */ - return kPrivateCGCompositeSourceOut; - case CAIRO_OPERATOR_ATOP: - return kPrivateCGCompositeSourceAtop; - - case CAIRO_OPERATOR_DEST: - /* XXX this is handled specially (noop)! */ - return kPrivateCGCompositeCopy; - case CAIRO_OPERATOR_DEST_OVER: - return kPrivateCGCompositeDestinationOver; - case CAIRO_OPERATOR_DEST_IN: - /* XXX This doesn't match image output */ - return kPrivateCGCompositeDestinationIn; - case CAIRO_OPERATOR_DEST_OUT: - return kPrivateCGCompositeDestinationOut; - case CAIRO_OPERATOR_DEST_ATOP: - /* XXX This doesn't match image output */ - return kPrivateCGCompositeDestinationAtop; - - case CAIRO_OPERATOR_XOR: - return kPrivateCGCompositeXOR; /* This will generate strange results */ - case CAIRO_OPERATOR_ADD: - return kPrivateCGCompositePlusLighter; - case CAIRO_OPERATOR_SATURATE: - /* XXX This doesn't match image output for SATURATE; there's no equivalent */ - return kPrivateCGCompositePlusDarker; /* ??? */ - } - - - return kPrivateCGCompositeCopy; -} - -static CGLineCap -_cairo_quartz_cairo_line_cap_to_quartz (cairo_line_cap_t ccap) -{ - switch (ccap) { - case CAIRO_LINE_CAP_BUTT: return kCGLineCapButt; break; - case CAIRO_LINE_CAP_ROUND: return kCGLineCapRound; break; - case CAIRO_LINE_CAP_SQUARE: return kCGLineCapSquare; break; - } - - return kCGLineCapButt; -} - -static CGLineJoin -_cairo_quartz_cairo_line_join_to_quartz (cairo_line_join_t cjoin) -{ - switch (cjoin) { - case CAIRO_LINE_JOIN_MITER: return kCGLineJoinMiter; break; - case CAIRO_LINE_JOIN_ROUND: return kCGLineJoinRound; break; - case CAIRO_LINE_JOIN_BEVEL: return kCGLineJoinBevel; break; - } - - return kCGLineJoinMiter; -} - -static void -_cairo_quartz_cairo_matrix_to_quartz (const cairo_matrix_t *src, - CGAffineTransform *dst) -{ - dst->a = src->xx; - dst->b = src->xy; - dst->c = src->yx; - dst->d = src->yy; - dst->tx = src->x0; - dst->ty = src->y0; -} - -/* - * Source -> Quartz setup and finish functions - */ - -static void -ComputeGradientValue (void *info, const float *in, float *out) -{ - float fdist = *in; /* 0.0 .. 1.0 */ - cairo_fixed_16_16_t fdist_fix = _cairo_fixed_from_double(*in); - cairo_gradient_pattern_t *grad = (cairo_gradient_pattern_t*) info; - unsigned int i; - - for (i = 0; i < grad->n_stops; i++) { - if (grad->stops[i].x > fdist_fix) - break; - } - - if (i == 0 || i == grad->n_stops) { - if (i == grad->n_stops) - --i; - out[0] = grad->stops[i].color.red / 65535.; - out[1] = grad->stops[i].color.green / 65535.; - out[2] = grad->stops[i].color.blue / 65535.; - out[3] = grad->stops[i].color.alpha / 65535.; - } else { - float ax = _cairo_fixed_to_double(grad->stops[i-1].x); - float bx = _cairo_fixed_to_double(grad->stops[i].x) - ax; - float bp = (fdist - ax)/bx; - float ap = 1.0 - bp; - - out[0] = - (grad->stops[i-1].color.red / 65535.) * ap + - (grad->stops[i].color.red / 65535.) * bp; - out[1] = - (grad->stops[i-1].color.green / 65535.) * ap + - (grad->stops[i].color.green / 65535.) * bp; - out[2] = - (grad->stops[i-1].color.blue / 65535.) * ap + - (grad->stops[i].color.blue / 65535.) * bp; - out[3] = - (grad->stops[i-1].color.alpha / 65535.) * ap + - (grad->stops[i].color.alpha / 65535.) * bp; - } -} - -static CGFunctionRef -CreateGradientFunction (cairo_gradient_pattern_t *gpat) -{ - static const float input_value_range[2] = { 0.f, 1.f }; - static const float output_value_ranges[8] = { 0.f, 1.f, 0.f, 1.f, 0.f, 1.f, 0.f, 1.f }; - static const CGFunctionCallbacks callbacks = { - 0, ComputeGradientValue, (CGFunctionReleaseInfoCallback) cairo_pattern_destroy - }; - - return CGFunctionCreate (gpat, - 1, - input_value_range, - 4, - output_value_ranges, - &callbacks); -} - -static CGShadingRef -_cairo_quartz_cairo_gradient_pattern_to_quartz (cairo_pattern_t *abspat) -{ - cairo_matrix_t mat; - double x0, y0; - - if (abspat->type != CAIRO_PATTERN_TYPE_LINEAR && - abspat->type != CAIRO_PATTERN_TYPE_RADIAL) - return NULL; - - /* We can only do this if we have an identity pattern matrix; - * otherwise fall back through to the generic pattern case. - * XXXperf we could optimize this by creating a pattern with the shading; - * but we'd need to know the extents to do that. - * ... but we don't care; we can use the surface extents for it - * XXXtodo - implement gradients with non-identity pattern matrices - */ - cairo_pattern_get_matrix (abspat, &mat); - if (mat.xx != 1.0 || mat.yy != 1.0 || mat.xy != 0.0 || mat.yx != 0.0) - return NULL; - - x0 = mat.x0; - y0 = mat.y0; - - if (abspat->type == CAIRO_PATTERN_TYPE_LINEAR) { - cairo_linear_pattern_t *lpat = (cairo_linear_pattern_t*) abspat; - CGShadingRef shading; - CGPoint start, end; - CGFunctionRef gradFunc; - CGColorSpaceRef rgb = CGColorSpaceCreateDeviceRGB(); - - start = CGPointMake (_cairo_fixed_to_double (lpat->gradient.p1.x) - x0, - _cairo_fixed_to_double (lpat->gradient.p1.y) - y0); - end = CGPointMake (_cairo_fixed_to_double (lpat->gradient.p2.x) - x0, - _cairo_fixed_to_double (lpat->gradient.p2.y) - y0); - - cairo_pattern_reference (abspat); - gradFunc = CreateGradientFunction ((cairo_gradient_pattern_t*) lpat); - shading = CGShadingCreateAxial (rgb, - start, end, - gradFunc, - true, true); - CGColorSpaceRelease(rgb); - CGFunctionRelease(gradFunc); - - return shading; - } - - if (abspat->type == CAIRO_PATTERN_TYPE_RADIAL) { - cairo_radial_pattern_t *rpat = (cairo_radial_pattern_t*) abspat; - CGShadingRef shading; - CGPoint start, end; - CGFunctionRef gradFunc; - CGColorSpaceRef rgb = CGColorSpaceCreateDeviceRGB(); - - start = CGPointMake (_cairo_fixed_to_double (rpat->gradient.c1.x) - x0, - _cairo_fixed_to_double (rpat->gradient.c1.y) - y0); - end = CGPointMake (_cairo_fixed_to_double (rpat->gradient.c2.x) - x0, - _cairo_fixed_to_double (rpat->gradient.c2.y) - y0); - - cairo_pattern_reference (abspat); - gradFunc = CreateGradientFunction ((cairo_gradient_pattern_t*) rpat); - shading = CGShadingCreateRadial (rgb, - start, - _cairo_fixed_to_double (rpat->gradient.c1.radius), - end, - _cairo_fixed_to_double (rpat->gradient.c2.radius), - gradFunc, - true, true); - CGColorSpaceRelease(rgb); - CGFunctionRelease(gradFunc); - - return shading; - } - - /* Shouldn't be reached */ - ASSERT_NOT_REACHED; - return NULL; -} - - -/* Generic cairo_pattern -> CGPattern function */ -static void -SurfacePatternDrawFunc (void *info, CGContextRef context) -{ - cairo_surface_pattern_t *spat = (cairo_surface_pattern_t *) info; - cairo_surface_t *pat_surf = spat->surface; - - cairo_quartz_surface_t *quartz_surf = NULL; - - cairo_bool_t flip = FALSE; - - CGImageRef img; - - if (cairo_surface_get_type(pat_surf) != CAIRO_SURFACE_TYPE_QUARTZ) { - /* This sucks; we should really store a dummy quartz surface - * for passing in here - * XXXtodo store a dummy quartz surface somewhere for handing off to clone_similar - * XXXtodo/perf don't use clone if the source surface is an image surface! Instead, - * just create the CGImage directly! - */ - - cairo_surface_t *dummy = cairo_quartz_surface_create (CAIRO_FORMAT_ARGB32, 1, 1); - cairo_surface_t *new_surf = NULL; - cairo_rectangle_int16_t rect; - - _cairo_surface_get_extents (pat_surf, &rect); - - _cairo_surface_clone_similar (dummy, pat_surf, rect.x, rect.y, - rect.width, rect.height, &new_surf); - - cairo_surface_destroy(dummy); - - quartz_surf = (cairo_quartz_surface_t *) new_surf; - } else { - /* If it's a quartz surface, we can try to see if it's a CGBitmapContext; - * we do this when we call CGBitmapContextCreateImage below. - */ - cairo_surface_reference (pat_surf); - quartz_surf = (cairo_quartz_surface_t*) pat_surf; - - /* XXXtodo WHY does this need to be flipped? Writing this stuff - * to disk shows that in both this path and the path above the source image - * has an identical orientation, and the destination context at all times has a Y - * flip. So why do we need to flip in this case? - */ - flip = TRUE; - } - - img = CGBitmapContextCreateImage (quartz_surf->cgContext); - - if (!img) { - // ... give up. - ND((stderr, "CGBitmapContextCreateImage failed\n")); - cairo_surface_destroy ((cairo_surface_t*)quartz_surf); - return; - } - - if (flip) { - CGContextTranslateCTM (context, 0, CGImageGetHeight(img)); - CGContextScaleCTM (context, 1, -1); - } - - CGRect imageBounds; - imageBounds.size = CGSizeMake (CGImageGetWidth(img), CGImageGetHeight(img)); - imageBounds.origin.x = 0; - imageBounds.origin.y = 0; - - CGContextDrawImage (context, imageBounds, img); - - CGImageRelease (img); - - cairo_surface_destroy ((cairo_surface_t*) quartz_surf); -} - -/* Borrowed from cairo-meta-surface */ -static cairo_status_t -_init_pattern_with_snapshot (cairo_pattern_t *pattern, - const cairo_pattern_t *other) -{ - _cairo_pattern_init_copy (pattern, other); - - if (pattern->type == CAIRO_PATTERN_TYPE_SURFACE) { - cairo_surface_pattern_t *surface_pattern = - (cairo_surface_pattern_t *) pattern; - cairo_surface_t *surface = surface_pattern->surface; - - surface_pattern->surface = _cairo_surface_snapshot (surface); - - cairo_surface_destroy (surface); - - if (surface_pattern->surface->status) - return surface_pattern->surface->status; - } - - return CAIRO_STATUS_SUCCESS; -} - -static CGPatternRef -_cairo_quartz_cairo_repeating_surface_pattern_to_quartz (cairo_quartz_surface_t *dest, - cairo_pattern_t *abspat) -{ - cairo_surface_pattern_t *spat; - cairo_surface_t *pat_surf; - cairo_rectangle_int16_t extents; - - CGRect pbounds; - CGAffineTransform ptransform, stransform; - CGPatternCallbacks cb = { 0, - SurfacePatternDrawFunc, - (CGFunctionReleaseInfoCallback) cairo_pattern_destroy }; - CGPatternRef cgpat; - float rw, rh; - - cairo_pattern_union_t *snap_pattern = NULL; - cairo_pattern_t *target_pattern = abspat; - - cairo_matrix_t m; - /* SURFACE is the only type we'll handle here */ - if (abspat->type != CAIRO_PATTERN_TYPE_SURFACE) - return NULL; - - spat = (cairo_surface_pattern_t *) abspat; - pat_surf = spat->surface; - - _cairo_surface_get_extents (pat_surf, &extents); - pbounds.origin.x = 0; - pbounds.origin.y = 0; - pbounds.size.width = extents.width; - pbounds.size.height = extents.height; - - m = spat->base.matrix; - cairo_matrix_invert(&m); - _cairo_quartz_cairo_matrix_to_quartz (&m, &stransform); - - /* The pattern matrix is relative to the bottom left, again; the - * incoming cairo pattern matrix is relative to the upper left. - * So we take the pattern matrix and the original context matrix, - * which gives us the correct base translation/y flip. - */ - ptransform = CGAffineTransformConcat(stransform, dest->cgContextBaseCTM); - -#ifdef QUARTZ_DEBUG - ND((stderr, " pbounds: %f %f %f %f\n", pbounds.origin.x, pbounds.origin.y, pbounds.size.width, pbounds.size.height)); - ND((stderr, " pattern xform: t: %f %f xx: %f xy: %f yx: %f yy: %f\n", ptransform.tx, ptransform.ty, ptransform.a, ptransform.b, ptransform.c, ptransform.d)); - CGAffineTransform xform = CGContextGetCTM(dest->cgContext); - ND((stderr, " context xform: t: %f %f xx: %f xy: %f yx: %f yy: %f\n", xform.tx, xform.ty, xform.a, xform.b, xform.c, xform.d)); -#endif - - // kjs seems to indicate this should work (setting to 0,0 to avoid - // tiling); however, the pattern CTM scaling ends up being NaN in - // the pattern draw function if either rw or rh are 0. - // XXXtodo get pattern drawing working with extend options - // XXXtodo/perf optimize CAIRO_EXTEND_NONE to a single DrawImage instead of a pattern -#if 0 - if (spat->base.extend == CAIRO_EXTEND_NONE) { - /* XXX wasteful; this will keep drawing the pattern in the - * original location. We need to set up the clip region - * instead to do this right. - */ - rw = 0; - rh = 0; - } else if (spat->base.extend == CAIRO_EXTEND_REPEAT) { - rw = extents.width; - rh = extents.height; - } else if (spat->base.extend == CAIRO_EXTEND_REFLECT) { - /* XXX broken; need to emulate by reflecting the image into 4 quadrants - * and then tiling that - */ - rw = extents.width; - rh = extents.height; - } else { - /* CAIRO_EXTEND_PAD */ - /* XXX broken. */ - rw = 0; - rh = 0; - } -#else - rw = extents.width; - rh = extents.height; -#endif - - /* XXX fixme: only do snapshots if the context is for printing, or get rid of the - other block if it doesn't fafect performance */ - if (1 /* context is for printing */) { - snap_pattern = (cairo_pattern_union_t*) malloc(sizeof(cairo_pattern_union_t)); - target_pattern = (cairo_pattern_t*) snap_pattern; - _init_pattern_with_snapshot (target_pattern, abspat); - } else { - cairo_pattern_reference (abspat); - target_pattern = abspat; - } - - cgpat = CGPatternCreate (target_pattern, - pbounds, - ptransform, - rw, rh, - kCGPatternTilingConstantSpacing, /* kCGPatternTilingNoDistortion, */ - TRUE, - &cb); - return cgpat; -} - -typedef enum { - DO_SOLID, - DO_SHADING, - DO_PATTERN, - DO_UNSUPPORTED -} cairo_quartz_action_t; - -static cairo_quartz_action_t -_cairo_quartz_setup_source (cairo_quartz_surface_t *surface, - cairo_pattern_t *source) -{ - assert (!(surface->sourceImage || surface->sourceShading || surface->sourcePattern)); - - if (source->type == CAIRO_PATTERN_TYPE_SOLID) { - cairo_solid_pattern_t *solid = (cairo_solid_pattern_t *) source; - - CGContextSetRGBStrokeColor (surface->cgContext, - solid->color.red, - solid->color.green, - solid->color.blue, - solid->color.alpha); - CGContextSetRGBFillColor (surface->cgContext, - solid->color.red, - solid->color.green, - solid->color.blue, - solid->color.alpha); - - return DO_SOLID; - } else if (source->type == CAIRO_PATTERN_TYPE_LINEAR || - source->type == CAIRO_PATTERN_TYPE_RADIAL) - { - CGShadingRef shading = _cairo_quartz_cairo_gradient_pattern_to_quartz (source); - if (!shading) - return DO_UNSUPPORTED; - - surface->sourceShading = shading; - - return DO_SHADING; - } else if (source->type == CAIRO_PATTERN_TYPE_SURFACE) { - CGPatternRef pattern = _cairo_quartz_cairo_repeating_surface_pattern_to_quartz (surface, source); - if (!pattern) - return DO_UNSUPPORTED; - - float patternAlpha = 1.0f; - - // Save before we change the pattern, colorspace, etc. so that - // we can restore and make sure that quartz releases our - // pattern (which may be stack allocated) - CGContextSaveGState(surface->cgContext); - - CGColorSpaceRef patternSpace = CGColorSpaceCreatePattern(NULL); - CGContextSetFillColorSpace (surface->cgContext, patternSpace); - CGContextSetFillPattern (surface->cgContext, pattern, &patternAlpha); - CGContextSetStrokeColorSpace (surface->cgContext, patternSpace); - CGContextSetStrokePattern (surface->cgContext, pattern, &patternAlpha); - CGColorSpaceRelease (patternSpace); - - /* Quartz likes to munge the pattern phase (as yet unexplained - * why); force it to 0,0 as we've already baked in the correct - * pattern translation into the pattern matrix - */ - CGContextSetPatternPhase (surface->cgContext, CGSizeMake(0,0)); - - surface->sourcePattern = pattern; - - return DO_PATTERN; - } else { - return DO_UNSUPPORTED; - } - - ASSERT_NOT_REACHED; -} - -static void -_cairo_quartz_teardown_source (cairo_quartz_surface_t *surface, - cairo_pattern_t *source) -{ - if (surface->sourceImage) { - // nothing to do; we don't use sourceImage yet - } - - if (surface->sourceShading) { - CGShadingRelease(surface->sourceShading); - surface->sourceShading = NULL; - } - - if (surface->sourcePattern) { - CGPatternRelease(surface->sourcePattern); - // To tear down the pattern and colorspace - CGContextRestoreGState(surface->cgContext); - - surface->sourcePattern = NULL; - } -} - -/* - * get source/dest image implementation - */ - -static void -ImageDataReleaseFunc(void *info, const void *data, size_t size) -{ - if (data != NULL) { - free((void *) data); - } -} - -/* Read the image from the surface's front buffer */ -static cairo_int_status_t -_cairo_quartz_get_image (cairo_quartz_surface_t *surface, - cairo_image_surface_t **image_out, - unsigned char **data_out) -{ - unsigned char *imageData; - cairo_image_surface_t *isurf; - - if (CGBitmapContextGetBitsPerPixel(surface->cgContext) != 0) { - unsigned int stride; - unsigned int bitinfo; - unsigned int bpc, bpp; - CGColorSpaceRef colorspace; - unsigned int color_comps; - - imageData = (unsigned char *) CGBitmapContextGetData(surface->cgContext); -#ifdef USE_10_3_WORKAROUNDS - bitinfo = CGBitmapContextGetAlphaInfo (surface->cgContext); -#else - bitinfo = CGBitmapContextGetBitmapInfo (surface->cgContext); -#endif - stride = CGBitmapContextGetBytesPerRow (surface->cgContext); - bpp = CGBitmapContextGetBitsPerPixel (surface->cgContext); - bpc = CGBitmapContextGetBitsPerComponent (surface->cgContext); - - // let's hope they don't add YUV under us - colorspace = CGBitmapContextGetColorSpace (surface->cgContext); - color_comps = CGColorSpaceGetNumberOfComponents(colorspace); - - // XXX TODO: We can handle all of these by converting to - // pixman masks, including non-native-endian masks - if (bpc != 8) - return CAIRO_INT_STATUS_UNSUPPORTED; - - if (bpp != 32 && bpp != 8) - return CAIRO_INT_STATUS_UNSUPPORTED; - - if (color_comps != 3 && color_comps != 1) - return CAIRO_INT_STATUS_UNSUPPORTED; - - if (bpp == 32 && color_comps == 3 && - (bitinfo & kCGBitmapAlphaInfoMask) == kCGImageAlphaPremultipliedFirst && - (bitinfo & kCGBitmapByteOrderMask) == kCGBitmapByteOrder32Host) - { - isurf = (cairo_image_surface_t *) - cairo_image_surface_create_for_data (imageData, - CAIRO_FORMAT_ARGB32, - surface->extents.width, - surface->extents.height, - stride); - } else if (bpp == 32 && color_comps == 3 && - (bitinfo & kCGBitmapAlphaInfoMask) == kCGImageAlphaNoneSkipFirst && - (bitinfo & kCGBitmapByteOrderMask) == kCGBitmapByteOrder32Host) - { - isurf = (cairo_image_surface_t *) - cairo_image_surface_create_for_data (imageData, - CAIRO_FORMAT_RGB24, - surface->extents.width, - surface->extents.height, - stride); - } else if (bpp == 8 && color_comps == 1) - { - isurf = (cairo_image_surface_t *) - cairo_image_surface_create_for_data (imageData, - CAIRO_FORMAT_A8, - surface->extents.width, - surface->extents.height, - stride); - } else { - return CAIRO_INT_STATUS_UNSUPPORTED; - } - } else { - return CAIRO_INT_STATUS_UNSUPPORTED; - } - - *image_out = isurf; - return CAIRO_STATUS_SUCCESS; -} - -/* - * Cairo surface backend implementations - */ - -static cairo_status_t -_cairo_quartz_surface_finish (void *abstract_surface) -{ - cairo_quartz_surface_t *surface = (cairo_quartz_surface_t *) abstract_surface; - - ND((stderr, "_cairo_quartz_surface_finish[%p] cgc: %p\n", surface, surface->cgContext)); - - /* Restore our saved gstate that we use to reset clipping */ - CGContextRestoreGState (surface->cgContext); - - CGContextRelease (surface->cgContext); - - surface->cgContext = NULL; - - if (surface->imageData) { - free (surface->imageData); - surface->imageData = NULL; - } + if (surface->clip_region) + pixman_region_destroy (surface->clip_region); return CAIRO_STATUS_SUCCESS; } static cairo_status_t -_cairo_quartz_surface_acquire_source_image (void *abstract_surface, - cairo_image_surface_t **image_out, - void **image_extra) -{ - cairo_quartz_surface_t *surface = (cairo_quartz_surface_t *) abstract_surface; - - //ND((stderr, "%p _cairo_quartz_surface_acquire_source_image\n", surface)); - - *image_extra = NULL; - - return _cairo_quartz_get_image (surface, image_out, NULL); -} - -static cairo_status_t -_cairo_quartz_surface_acquire_dest_image (void *abstract_surface, - cairo_rectangle_int16_t *interest_rect, +_cairo_quartz_surface_acquire_source_image(void *abstract_surface, cairo_image_surface_t **image_out, - cairo_rectangle_int16_t *image_rect, void **image_extra) { - cairo_quartz_surface_t *surface = (cairo_quartz_surface_t *) abstract_surface; - cairo_int_status_t status; + cairo_quartz_surface_t *surface = abstract_surface; + +#if 0 + if (CGBitmapContextGetBitmapInfo (surface->context) != 0) { + /* XXX: We can create an image out of the bitmap here */ + } +#endif + + 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_t *surface = abstract_surface; + cairo_surface_t *image_surface; unsigned char *data; + int x1, y1, x2, y2; - ND((stderr, "%p _cairo_quartz_surface_acquire_dest_image\n", surface)); + x1 = surface->extents.x; + x2 = surface->extents.x + surface->extents.width; + y1 = surface->extents.y; + y2 = surface->extents.y + surface->extents.height; - *image_rect = surface->extents; + 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; - status = _cairo_quartz_get_image (surface, image_out, &data); - if (status) - return status; + 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 *interest_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 = (cairo_quartz_surface_t *) abstract_surface; - unsigned char *imageData = (unsigned char *) image_extra; + cairo_quartz_surface_t *surface = abstract_surface; + CGImageRef image_ref; + CGRect rect; - //ND((stderr, "%p _cairo_quartz_surface_release_dest_image\n", surface)); + image_ref = create_image_from_surface (image, image_extra); - if (!CGBitmapContextGetData (surface->cgContext)) { - CGDataProviderRef dataProvider; - CGImageRef img; + rect = CGRectMake (image_rect->x, image_rect->y, image_rect->width, image_rect->height); - dataProvider = CGDataProviderCreateWithData (NULL, imageData, - surface->extents.width * surface->extents.height * 4, - ImageDataReleaseFunc); - - img = CGImageCreate (surface->extents.width, surface->extents.height, - 8, 32, - surface->extents.width * 4, - CGColorSpaceCreateDeviceRGB(), - kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Host, - dataProvider, - NULL, - false, - kCGRenderingIntentDefault); - - CGContextSetCompositeOperation (surface->cgContext, kPrivateCGCompositeCopy); - - CGContextDrawImage (surface->cgContext, - CGRectMake (0, 0, surface->extents.width, surface->extents.height), - img); - - CGImageRelease (img); - CGDataProviderRelease (dataProvider); - - ND((stderr, "Image for surface %p was recovered from a bitmap\n", surface)); + if (surface->y_grows_down) { + CGContextSaveGState (surface->context); + CGContextTranslateCTM (surface->context, 0, image_rect->height + 2 * image_rect->y); + CGContextScaleCTM (surface->context, 1, -1); } - cairo_surface_destroy ((cairo_surface_t *) image); -} + CGContextDrawImage(surface->context, rect, image_ref); + CFRelease (image_ref); -static cairo_surface_t * -_cairo_quartz_surface_create_similar (void *abstract_surface, - cairo_content_t content, - int width, - int height) -{ - /*cairo_quartz_surface_t *surface = (cairo_quartz_surface_t *) abstract_surface;*/ - - cairo_format_t format; - - if (content == CAIRO_CONTENT_COLOR_ALPHA) - format = CAIRO_FORMAT_ARGB32; - else if (content == CAIRO_CONTENT_COLOR) - format = CAIRO_FORMAT_RGB24; - else if (content == CAIRO_CONTENT_ALPHA) - format = CAIRO_FORMAT_A8; - else - return NULL; - - return cairo_quartz_surface_create (format, width, height); -} - -static cairo_status_t -_cairo_quartz_surface_clone_similar (void *abstract_surface, - cairo_surface_t *src, - int src_x, - int src_y, - int width, - int height, - cairo_surface_t **clone_out) -{ - cairo_quartz_surface_t *surface = (cairo_quartz_surface_t *) abstract_surface; - cairo_quartz_surface_t *new_surface = NULL; - cairo_format_t new_format; - - CGImageRef quartz_image = NULL; - - if (cairo_surface_get_type(src) == CAIRO_SURFACE_TYPE_QUARTZ) { - cairo_quartz_surface_t *qsurf = (cairo_quartz_surface_t *) src; - quartz_image = CGBitmapContextCreateImage (qsurf->cgContext); - new_format = CAIRO_FORMAT_ARGB32; /* XXX bogus; recover a real format from the image */ - } else if (_cairo_surface_is_image (src)) { - cairo_image_surface_t *isurf = (cairo_image_surface_t *) src; - CGDataProviderRef dataProvider; - CGColorSpaceRef cgColorspace; - CGBitmapInfo bitinfo; - int bitsPerComponent, bitsPerPixel; - - if (isurf->format == CAIRO_FORMAT_ARGB32) { - cgColorspace = CGColorSpaceCreateDeviceRGB(); - bitinfo = kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Host; - bitsPerComponent = 8; - bitsPerPixel = 32; - } else if (isurf->format == CAIRO_FORMAT_RGB24) { - cgColorspace = CGColorSpaceCreateDeviceRGB(); - bitinfo = kCGImageAlphaNoneSkipFirst | kCGBitmapByteOrder32Host; - bitsPerComponent = 8; - bitsPerPixel = 32; - } else if (isurf->format == CAIRO_FORMAT_A8) { - cgColorspace = CGColorSpaceCreateDeviceGray(); - bitinfo = kCGImageAlphaNone; - bitsPerComponent = 8; - bitsPerPixel = 8; - } else { - /* SUPPORT A1, maybe */ - return CAIRO_INT_STATUS_UNSUPPORTED; - } - - new_format = isurf->format; - - dataProvider = CGDataProviderCreateWithData (NULL, - isurf->data, - isurf->height * isurf->stride, - NULL); - - quartz_image = CGImageCreate (isurf->width, isurf->height, - bitsPerComponent, - bitsPerPixel, - isurf->stride, - cgColorspace, - bitinfo, - dataProvider, - NULL, - false, - kCGRenderingIntentDefault); - CGDataProviderRelease (dataProvider); - CGColorSpaceRelease (cgColorspace); - } else { - return CAIRO_INT_STATUS_UNSUPPORTED; + if (surface->y_grows_down) { + CGContextRestoreGState (surface->context); } - if (!quartz_image) - return CAIRO_INT_STATUS_UNSUPPORTED; + cairo_surface_destroy ((cairo_surface_t *)image); + free (image_extra); +} - new_surface = (cairo_quartz_surface_t *) - cairo_quartz_surface_create (new_format, - CGImageGetWidth (quartz_image), - CGImageGetHeight (quartz_image)); - if (!new_surface || new_surface->base.status) - return CAIRO_INT_STATUS_UNSUPPORTED; +static cairo_int_status_t +_cairo_quartz_surface_set_clip_region(void *abstract_surface, + pixman_region16_t * region) +{ + cairo_quartz_surface_t *surface = abstract_surface; - CGContextSetCompositeOperation (new_surface->cgContext, - kPrivateCGCompositeCopy); + if (surface->clip_region) + pixman_region_destroy (surface->clip_region); - quartz_image_to_png (quartz_image, NULL); - - CGContextDrawImage (new_surface->cgContext, - CGRectMake (src_x, src_y, width, height), - quartz_image); - CGImageRelease (quartz_image); - - *clone_out = (cairo_surface_t*) new_surface; + 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 *extents) +_cairo_quartz_surface_get_extents (void *abstract_surface, + cairo_rectangle_int16_t *rectangle) { - cairo_quartz_surface_t *surface = (cairo_quartz_surface_t *) abstract_surface; + cairo_quartz_surface_t *surface = abstract_surface; - *extents = surface->extents; + *rectangle = surface->extents; return CAIRO_STATUS_SUCCESS; } -static cairo_int_status_t -_cairo_quartz_surface_paint (void *abstract_surface, - cairo_operator_t op, - cairo_pattern_t *source) -{ - cairo_quartz_surface_t *surface = (cairo_quartz_surface_t *) abstract_surface; - cairo_int_status_t rv = CAIRO_STATUS_SUCCESS; - cairo_quartz_action_t action; - - ND((stderr, "%p _cairo_quartz_surface_paint op %d source->type %d\n", surface, op, source->type)); - - if (op == CAIRO_OPERATOR_DEST) - return CAIRO_STATUS_SUCCESS; - - CGContextSetCompositeOperation (surface->cgContext, _cairo_quartz_cairo_operator_to_quartz (op)); - - action = _cairo_quartz_setup_source (surface, source); - - if (action == DO_SOLID || action == DO_PATTERN) { - CGContextFillRect (surface->cgContext, CGRectMake(surface->extents.x, - surface->extents.y, - surface->extents.width, - surface->extents.height)); - } else if (action == DO_SHADING) { - CGContextDrawShading (surface->cgContext, surface->sourceShading); - } else { - rv = CAIRO_INT_STATUS_UNSUPPORTED; - } - - _cairo_quartz_teardown_source (surface, source); - - ND((stderr, "-- paint\n")); - return rv; -} - -static cairo_int_status_t -_cairo_quartz_surface_fill (void *abstract_surface, - cairo_operator_t op, - cairo_pattern_t *source, - cairo_path_fixed_t *path, - cairo_fill_rule_t fill_rule, - double tolerance, - cairo_antialias_t antialias) -{ - cairo_quartz_surface_t *surface = (cairo_quartz_surface_t *) abstract_surface; - cairo_int_status_t rv = CAIRO_STATUS_SUCCESS; - cairo_quartz_action_t action; - - ND((stderr, "%p _cairo_quartz_surface_fill op %d source->type %d\n", surface, op, source->type)); - - if (op == CAIRO_OPERATOR_DEST) - return CAIRO_STATUS_SUCCESS; - - CGContextSaveGState (surface->cgContext); - - CGContextSetShouldAntialias (surface->cgContext, (antialias != CAIRO_ANTIALIAS_NONE)); - CGContextSetCompositeOperation (surface->cgContext, _cairo_quartz_cairo_operator_to_quartz (op)); - - action = _cairo_quartz_setup_source (surface, source); - if (action == DO_UNSUPPORTED) { - CGContextRestoreGState (surface->cgContext); - return CAIRO_INT_STATUS_UNSUPPORTED; - } - - CGContextBeginPath (surface->cgContext); - _cairo_quartz_cairo_path_to_quartz_context (path, surface->cgContext); - - if (action == DO_SOLID || action == DO_PATTERN) { - if (fill_rule == CAIRO_FILL_RULE_WINDING) - CGContextFillPath (surface->cgContext); - else - CGContextEOFillPath (surface->cgContext); - } else if (action == DO_SHADING) { - - // we have to clip and then paint the shading; we can't fill - // with the shading - if (fill_rule == CAIRO_FILL_RULE_WINDING) - CGContextClip (surface->cgContext); - else - CGContextEOClip (surface->cgContext); - - CGContextDrawShading (surface->cgContext, surface->sourceShading); - } else { - rv = CAIRO_INT_STATUS_UNSUPPORTED; - } - - _cairo_quartz_teardown_source (surface, source); - - CGContextRestoreGState (surface->cgContext); - - ND((stderr, "-- fill\n")); - return rv; -} - -static cairo_int_status_t -_cairo_quartz_surface_stroke (void *abstract_surface, - cairo_operator_t op, - cairo_pattern_t *source, - cairo_path_fixed_t *path, - cairo_stroke_style_t *style, - cairo_matrix_t *ctm, - cairo_matrix_t *ctm_inverse, - double tolerance, - cairo_antialias_t antialias) -{ - cairo_quartz_surface_t *surface = (cairo_quartz_surface_t *) abstract_surface; - cairo_int_status_t rv = CAIRO_STATUS_SUCCESS; - cairo_quartz_action_t action; - - ND((stderr, "%p _cairo_quartz_surface_stroke op %d source->type %d\n", surface, op, source->type)); - - if (op == CAIRO_OPERATOR_DEST) - return CAIRO_STATUS_SUCCESS; - - CGContextSaveGState (surface->cgContext); - - // Turning antialiasing off causes misrendering with - // single-pixel lines (e.g. 20,10.5 -> 21,10.5 end up being rendered as 2 pixels) - //CGContextSetShouldAntialias (surface->cgContext, (antialias != CAIRO_ANTIALIAS_NONE)); - CGContextSetLineWidth (surface->cgContext, style->line_width); - CGContextSetLineCap (surface->cgContext, _cairo_quartz_cairo_line_cap_to_quartz (style->line_cap)); - CGContextSetLineJoin (surface->cgContext, _cairo_quartz_cairo_line_join_to_quartz (style->line_join)); - CGContextSetMiterLimit (surface->cgContext, style->miter_limit); - - if (style->dash && style->num_dashes) { -#define STATIC_DASH 32 - float sdash[STATIC_DASH]; - float *fdash = sdash; - unsigned int k; - if (style->num_dashes > STATIC_DASH) - fdash = malloc (sizeof(float)*style->num_dashes); - - for (k = 0; k < style->num_dashes; k++) - fdash[k] = (float) style->dash[k]; - - CGContextSetLineDash (surface->cgContext, style->dash_offset, fdash, style->num_dashes); - - if (fdash != sdash) - free (fdash); - } - - CGContextSetCompositeOperation (surface->cgContext, _cairo_quartz_cairo_operator_to_quartz (op)); - - action = _cairo_quartz_setup_source (surface, source); - if (action == DO_UNSUPPORTED) { - CGContextRestoreGState (surface->cgContext); - return CAIRO_INT_STATUS_UNSUPPORTED; - } - - CGContextBeginPath (surface->cgContext); - _cairo_quartz_cairo_path_to_quartz_context (path, surface->cgContext); - - if (action == DO_SOLID || action == DO_PATTERN) { - CGContextStrokePath (surface->cgContext); - } else if (action == DO_SHADING) { - // we have to clip and then paint the shading; first we have to convert - // the stroke to a path that we can fill - CGContextReplacePathWithStrokedPath (surface->cgContext); - CGContextClip (surface->cgContext); - - CGContextDrawShading (surface->cgContext, surface->sourceShading); - } else { - rv = CAIRO_INT_STATUS_UNSUPPORTED; - } - - _cairo_quartz_teardown_source (surface, source); - - CGContextRestoreGState (surface->cgContext); - - ND((stderr, "-- stroke\n")); - return rv; -} - -#if CAIRO_HAS_ATSUI_FONT -static cairo_int_status_t -_cairo_quartz_surface_show_glyphs (void *abstract_surface, - cairo_operator_t op, - cairo_pattern_t *source, - cairo_glyph_t *glyphs, - int num_glyphs, - cairo_scaled_font_t *scaled_font) -{ - cairo_quartz_surface_t *surface = (cairo_quartz_surface_t *) abstract_surface; - cairo_int_status_t rv = CAIRO_STATUS_SUCCESS; - cairo_quartz_action_t action; - int i; - - if (num_glyphs <= 0) - return CAIRO_STATUS_SUCCESS; - - if (op == CAIRO_OPERATOR_DEST) - return CAIRO_STATUS_SUCCESS; - - if (cairo_scaled_font_get_type (scaled_font) != CAIRO_FONT_TYPE_ATSUI) - return CAIRO_INT_STATUS_UNSUPPORTED; - - CGContextSaveGState (surface->cgContext); - - action = _cairo_quartz_setup_source (surface, source); - if (action == DO_SOLID || action == DO_PATTERN) { - CGContextSetTextDrawingMode (surface->cgContext, kCGTextFill); - } else if (action == DO_SHADING) { - CGContextSetTextDrawingMode (surface->cgContext, kCGTextClip); - } else { - /* Unsupported */ - CGContextRestoreGState (surface->cgContext); - return CAIRO_INT_STATUS_UNSUPPORTED; - } - - CGContextSetCompositeOperation (surface->cgContext, _cairo_quartz_cairo_operator_to_quartz (op)); - - ATSUFontID fid = _cairo_atsui_scaled_font_get_atsu_font_id (scaled_font); - ATSFontRef atsfref = FMGetATSFontRefFromFont (fid); - CGFontRef cgfref = CGFontCreateWithPlatformFont (&atsfref); - - CGContextSetFont (surface->cgContext, cgfref); - CGFontRelease (cgfref); - - /* So this should include the size; I don't know if I need to extract the - * size from this and call CGContextSetFontSize.. will I get crappy hinting - * with this 1.0 size business? Or will CG just multiply that size into the - * text matrix? - */ - //ND((stderr, "show_glyphs: glyph 0 at: %f, %f\n", glyphs[0].x, glyphs[0].y)); - CGAffineTransform cairoTextTransform, textTransform, ctm; - _cairo_quartz_cairo_matrix_to_quartz (&scaled_font->font_matrix, &cairoTextTransform); - - textTransform = CGAffineTransformMakeTranslation (glyphs[0].x, glyphs[0].y); - textTransform = CGAffineTransformScale (textTransform, 1.0, -1.0); - textTransform = CGAffineTransformConcat (cairoTextTransform, textTransform); - - ctm = CGAffineTransformMake (scaled_font->ctm.xx, - -scaled_font->ctm.yx, - -scaled_font->ctm.xy, - scaled_font->ctm.yy, - 0., 0.); - textTransform = CGAffineTransformConcat (ctm, textTransform); - - CGContextSetTextMatrix (surface->cgContext, textTransform); - CGContextSetFontSize (surface->cgContext, 1.0); - - // XXXtodo/perf: stack storage for glyphs/sizes -#define STATIC_BUF_SIZE 64 - CGGlyph glyphs_static[STATIC_BUF_SIZE]; - CGSize cg_advances_static[STATIC_BUF_SIZE]; - CGGlyph *cg_glyphs = &glyphs_static[0]; - CGSize *cg_advances = &cg_advances_static[0]; - - if (num_glyphs > STATIC_BUF_SIZE) { - cg_glyphs = (CGGlyph*) malloc(sizeof(CGGlyph) * num_glyphs); - cg_advances = (CGSize*) malloc(sizeof(CGSize) * num_glyphs); - } - - double xprev = glyphs[0].x; - double yprev = glyphs[0].y; - - cg_glyphs[0] = glyphs[0].index; - cg_advances[0].width = 0; - cg_advances[0].height = 0; - - for (i = 1; i < num_glyphs; i++) { - cg_glyphs[i] = glyphs[i].index; - cg_advances[i-1].width = glyphs[i].x - xprev; - cg_advances[i-1].height = glyphs[i].y - yprev; - xprev = glyphs[i].x; - yprev = glyphs[i].y; - } - -#if 0 - for (i = 0; i < num_glyphs; i++) { - ND((stderr, "[%d: %d %f,%f]\n", i, cg_glyphs[i], cg_advances[i].width, cg_advances[i].height)); - } -#endif - - CGContextShowGlyphsWithAdvances (surface->cgContext, - cg_glyphs, - cg_advances, - num_glyphs); - - if (cg_glyphs != &glyphs_static[0]) { - free (cg_glyphs); - free (cg_advances); - } - - if (action == DO_SHADING) - CGContextDrawShading (surface->cgContext, surface->sourceShading); - - _cairo_quartz_teardown_source (surface, source); - - CGContextRestoreGState (surface->cgContext); - - return rv; -} -#endif /* CAIRO_HAS_ATSUI_FONT */ - -static cairo_int_status_t -_cairo_quartz_surface_mask (void *abstract_surface, - cairo_operator_t op, - cairo_pattern_t *source, - cairo_pattern_t *mask) -{ - cairo_quartz_surface_t *surface = (cairo_quartz_surface_t *) abstract_surface; - cairo_int_status_t rv = CAIRO_STATUS_SUCCESS; - - ND((stderr, "%p _cairo_quartz_surface_mask op %d source->type %d mask->type %d\n", surface, op, source->type, mask->type)); - - if (mask->type == CAIRO_PATTERN_TYPE_SOLID) { - /* This is easy; we just need to paint with the alpha. */ - cairo_solid_pattern_t *solid_mask = (cairo_solid_pattern_t *) mask; - - CGContextSetAlpha (surface->cgContext, solid_mask->color.alpha); - } else { - /* So, CGContextClipToMask is not present in 10.3.9, so we're - * doomed; if we have imageData, we can do fallback, otherwise - * just pretend success. - */ - if (surface->imageData) - return CAIRO_INT_STATUS_UNSUPPORTED; - - return CAIRO_STATUS_SUCCESS; - } - - rv = _cairo_quartz_surface_paint (surface, op, source); - - if (mask->type == CAIRO_PATTERN_TYPE_SOLID) { - CGContextSetAlpha (surface->cgContext, 1.0); - } - - ND((stderr, "-- mask\n")); - - return rv; -} - -static cairo_int_status_t -_cairo_quartz_surface_intersect_clip_path (void *abstract_surface, - cairo_path_fixed_t *path, - cairo_fill_rule_t fill_rule, - double tolerance, - cairo_antialias_t antialias) -{ - cairo_quartz_surface_t *surface = (cairo_quartz_surface_t *) abstract_surface; - - ND((stderr, "%p _cairo_quartz_surface_intersect_clip_path path: %p\n", surface, path)); - - if (path == NULL) { - /* If we're being asked to reset the clip, we can only do it - * by restoring the gstate to our previous saved one, and - * saving it again. - * - * Note that this assumes that ALL quartz surface creation - * functions will do a SaveGState first; we do this in create_internal. - */ - CGContextRestoreGState (surface->cgContext); - CGContextSaveGState (surface->cgContext); - } else { - CGContextBeginPath (surface->cgContext); - _cairo_quartz_cairo_path_to_quartz_context (path, surface->cgContext); - if (fill_rule == CAIRO_FILL_RULE_WINDING) - CGContextClip (surface->cgContext); - else - CGContextEOClip (surface->cgContext); - } - - ND((stderr, "-- intersect_clip_path\n")); - - return CAIRO_STATUS_SUCCESS; -} - -// XXXtodo implement show_page; need to figure out how to handle begin/end - static const struct _cairo_surface_backend cairo_quartz_surface_backend = { CAIRO_SURFACE_TYPE_QUARTZ, - _cairo_quartz_surface_create_similar, + NULL, /* create_similar */ _cairo_quartz_surface_finish, _cairo_quartz_surface_acquire_source_image, NULL, /* release_source_image */ _cairo_quartz_surface_acquire_dest_image, _cairo_quartz_surface_release_dest_image, - _cairo_quartz_surface_clone_similar, + NULL, /* clone_similar */ NULL, /* composite */ NULL, /* fill_rectangles */ NULL, /* composite_trapezoids */ NULL, /* copy_page */ NULL, /* show_page */ - NULL, /* set_clip_region */ - _cairo_quartz_surface_intersect_clip_path, + _cairo_quartz_surface_set_clip_region, + NULL, /* intersect_clip_path */ _cairo_quartz_surface_get_extents, - NULL, /* old_show_glyphs */ - NULL, /* get_font_options */ - NULL, /* flush */ - NULL, /* mark_dirty_rectangle */ - NULL, /* scaled_font_fini */ - NULL, /* scaled_glyph_fini */ - - _cairo_quartz_surface_paint, - _cairo_quartz_surface_mask, - _cairo_quartz_surface_stroke, - _cairo_quartz_surface_fill, -#if CAIRO_HAS_ATSUI_FONT - _cairo_quartz_surface_show_glyphs, -#else - NULL, /* surface_show_glyphs */ -#endif /* CAIRO_HAS_ATSUI_FONT */ - - NULL, /* snapshot */ + NULL /* old_show_glyphs */ }; -static cairo_quartz_surface_t * -_cairo_quartz_surface_create_internal (CGContextRef cgContext, - cairo_content_t content, - unsigned int width, - unsigned int height) +cairo_surface_t *cairo_quartz_surface_create(CGContextRef context, + int width, + int height, + cairo_bool_t y_grows_down) { cairo_quartz_surface_t *surface; + CGRect clip_box; - /* Init the base surface */ surface = malloc(sizeof(cairo_quartz_surface_t)); if (surface == NULL) { _cairo_error (CAIRO_STATUS_NO_MEMORY); - return NULL; + return (cairo_surface_t*) &_cairo_surface_nil; } - memset(surface, 0, sizeof(cairo_quartz_surface_t)); - + /* XXX: The content value here might be totally wrong. */ _cairo_surface_init(&surface->base, &cairo_quartz_surface_backend, - content); + CAIRO_CONTENT_COLOR_ALPHA); - /* Save our extents */ - surface->extents.x = surface->extents.y = 0; - surface->extents.width = width; - surface->extents.height = height; + surface->context = context; + surface->clip_region = NULL; + surface->y_grows_down = y_grows_down; - /* Save so we can always get back to a known-good CGContext -- this is - * required for proper behaviour of intersect_clip_path(NULL) - */ - CGContextSaveGState (cgContext); + 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; - surface->cgContext = cgContext; - surface->cgContextBaseCTM = CGContextGetCTM (cgContext); - - surface->imageData = NULL; - - return surface; + return (cairo_surface_t *) surface; } - -/** - * cairo_quartz_surface_create_for_cg_context - * @cgContext: the existing CGContext for which to create the surface - * @width: width of the surface, in pixels - * @height: height of the surface, in pixels - * - * Creates a Quartz surface that wraps the given CGContext. The - * CGContext is assumed to be in the QuickDraw coordinate space (that - * is, with the origin at the upper left and the Y axis increasing - * downward.) If the CGContext is in the Quartz coordinate space (with - * the origin at the bottom left), then it should be flipped before - * this function is called: - * - * - * GContextTranslateCTM (cgContext, 0.0, height); - * CGContextScaleCTM (cgContext, 1.0, -1.0); - * - * - * A very small number of Cairo operations cannot be translated to - * Quartz operations; those operations will fail on this surface. - * If all Cairo operations are required to succeed, consider rendering - * to a surface created by cairo_quartz_surface_create() and then copying - * the result to the CGContext. - * - * Return value: the newly created Cairo surface. - * - * Since: 1.4 - **/ -cairo_surface_t * -cairo_quartz_surface_create_for_cg_context (CGContextRef cgContext, - unsigned int width, - unsigned int height) +int +_cairo_surface_is_quartz (cairo_surface_t *surface) { - cairo_quartz_surface_t *surf; - - CGContextRetain (cgContext); - - surf = _cairo_quartz_surface_create_internal (cgContext, CAIRO_CONTENT_COLOR_ALPHA, - width, height); - if (!surf) { - CGContextRelease (cgContext); - // create_internal will have set an error - return (cairo_surface_t*) &_cairo_surface_nil; - } - - return (cairo_surface_t *) surf; + return surface->backend == &cairo_quartz_surface_backend; } - -/** - * cairo_quartz_surface_create - * @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 Quartz surface backed by a CGBitmap. The surface is - * created using the Device RGB (or Device Gray, for A8) color space. - * All Cairo operations, including those that require software - * rendering, will succeed on this surface. - * - * Return value: the newly created surface. - * - * Since: 1.4 - **/ -cairo_surface_t * -cairo_quartz_surface_create (cairo_format_t format, - unsigned int width, - unsigned int height) -{ - cairo_quartz_surface_t *surf; - CGContextRef cgc; - CGColorSpaceRef cgColorspace; - CGBitmapInfo bitinfo; - void *imageData; - int stride; - int bitsPerComponent; - - if (format == CAIRO_FORMAT_ARGB32) { - cgColorspace = CGColorSpaceCreateDeviceRGB(); - stride = width * 4; - bitinfo = kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Host; - bitsPerComponent = 8; - } else if (format == CAIRO_FORMAT_RGB24) { - cgColorspace = CGColorSpaceCreateDeviceRGB(); - stride = width * 4; - bitinfo = kCGImageAlphaNoneSkipFirst | kCGBitmapByteOrder32Host; - bitsPerComponent = 8; - } else if (format == CAIRO_FORMAT_A8) { - cgColorspace = CGColorSpaceCreateDeviceGray(); - if (width % 4 == 0) - stride = width; - else - stride = (width & ~3) + 4; - bitinfo = kCGImageAlphaNone; - bitsPerComponent = 8; - } else if (format == CAIRO_FORMAT_A1) { - /* I don't think we can usefully support this, as defined by - * cairo_format_t -- these are 1-bit pixels stored in 32-bit - * quantities. - */ - _cairo_error (CAIRO_STATUS_INVALID_FORMAT); - return (cairo_surface_t*) &_cairo_surface_nil; - } else { - _cairo_error (CAIRO_STATUS_INVALID_FORMAT); - 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; - } - - cgc = CGBitmapContextCreate (imageData, - width, - height, - bitsPerComponent, - stride, - cgColorspace, - bitinfo); - CGColorSpaceRelease (cgColorspace); - - if (!cgc) { - _cairo_error (CAIRO_STATUS_NO_MEMORY); - return (cairo_surface_t*) &_cairo_surface_nil; - } - - /* flip the Y axis */ - CGContextTranslateCTM (cgc, 0.0, height); - CGContextScaleCTM (cgc, 1.0, -1.0); - - surf = _cairo_quartz_surface_create_internal (cgc, _cairo_content_from_format (format), - width, height); - if (!surf) { - CGContextRelease (cgc); - // create_internal will have set an error - return (cairo_surface_t*) &_cairo_surface_nil; - } - - surf->imageData = imageData; - - return (cairo_surface_t *) surf; -} - -/** - * cairo_quartz_surface_get_cg_context - * @surface: the Cairo Quartz surface - * - * Returns the CGContextRef that the given Quartz surface is backed - * by. - * - * Return value: the CGContextRef for the given surface. - * - * Since: 1.4 - **/ -CGContextRef -cairo_quartz_surface_get_cg_context (cairo_surface_t *surface) -{ - cairo_quartz_surface_t *quartz = (cairo_quartz_surface_t*)surface; - - if (cairo_surface_get_type(surface) != CAIRO_SURFACE_TYPE_QUARTZ) - return NULL; - - return quartz->cgContext; -} - - -/* Debug stuff */ - -#ifdef QUARTZ_DEBUG - -#include - -void ExportCGImageToPNGFile(CGImageRef inImageRef, char* dest) -{ - Handle dataRef = NULL; - OSType dataRefType; - CFStringRef inPath = CFStringCreateWithCString(NULL, dest, kCFStringEncodingASCII); - - GraphicsExportComponent grex = 0; - unsigned long sizeWritten; - - ComponentResult result; - - // create the data reference - result = QTNewDataReferenceFromFullPathCFString(inPath, kQTNativeDefaultPathStyle, - 0, &dataRef, &dataRefType); - - if (NULL != dataRef && noErr == result) { - // 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 (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); - } - } - - // remember to close the component - CloseComponent(grex); - } - - // remember to dispose of the data reference handle - DisposeHandle(dataRef); - } -} -#endif - -void -quartz_image_to_png (CGImageRef imgref, char *dest) -{ -#if 0 - static int sctr = 0; - char sptr[] = "/Users/vladimir/Desktop/barXXXXX.png"; - - if (dest == NULL) { - fprintf (stderr, "** Writing %p to bar%d\n", imgref, sctr); - sprintf (sptr, "/Users/vladimir/Desktop/bar%d.png", sctr); - sctr++; - dest = sptr; - } - - ExportCGImageToPNGFile(imgref, dest); -#endif -} - -void -quartz_surface_to_png (cairo_quartz_surface_t *nq, char *dest) -{ -#if 0 - static int sctr = 0; - char sptr[] = "/Users/vladimir/Desktop/fooXXXXX.png"; - - if (nq->base.type != CAIRO_SURFACE_TYPE_QUARTZ) { - fprintf (stderr, "** quartz_surface_to_png: surface %p isn't quartz!\n", nq); - return; - } - - if (dest == NULL) { - fprintf (stderr, "** Writing %p to foo%d\n", nq, sctr); - sprintf (sptr, "/Users/vladimir/Desktop/foo%d.png", sctr); - sctr++; - dest = sptr; - } - - CGImageRef imgref = CGBitmapContextCreateImage (nq->cgContext); - if (imgref == NULL) { - fprintf (stderr, "quartz surface at %p is not a bitmap context!\n", nq); - return; - } - - ExportCGImageToPNGFile(imgref, dest); - - CGImageRelease(imgref); -#endif -} - diff --git a/gfx/cairo/cairo/src/cairo-quartz.h b/gfx/cairo/cairo/src/cairo-quartz.h index 5d78d391393..286efe8b87c 100644 --- a/gfx/cairo/cairo/src/cairo-quartz.h +++ b/gfx/cairo/cairo/src/cairo-quartz.h @@ -1,6 +1,6 @@ /* cairo - a vector graphics library with display and print output * - * Copyright 2006, 2007 Mozilla Corporation + * Copyright © 2002 University of Southern California * * This library is free software; you can redistribute it and/or * modify it either under the terms of the GNU Lesser General Public @@ -27,10 +27,11 @@ * * The Original Code is the cairo graphics library. * - * The Initial Developer of the Original Code is Mozilla Corporation. + * The Initial Developer of the Original Code is University of Southern + * California. * * Contributor(s): - * Vladimir Vukicevic + * Carl D. Worth */ #ifndef CAIRO_QUARTZ_H @@ -45,17 +46,10 @@ CAIRO_BEGIN_DECLS cairo_public cairo_surface_t * -cairo_quartz_surface_create (cairo_format_t format, - unsigned int width, - unsigned int height); - -cairo_public cairo_surface_t * -cairo_quartz_surface_create_for_cg_context (CGContextRef cgContext, - unsigned int width, - unsigned int height); - -cairo_public CGContextRef -cairo_quartz_surface_get_cg_context (cairo_surface_t *surface); +cairo_quartz_surface_create (CGContextRef context, + int width, + int height, + cairo_bool_t y_grows_down); CAIRO_END_DECLS diff --git a/gfx/cairo/cairo/src/cairo-rename.h b/gfx/cairo/cairo/src/cairo-rename.h index 44f5e2a408a..935f22df6d2 100644 --- a/gfx/cairo/cairo/src/cairo-rename.h +++ b/gfx/cairo/cairo/src/cairo-rename.h @@ -115,10 +115,6 @@ #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 @@ -238,7 +234,6 @@ #define cairo_surface_get_reference_count _moz_cairo_surface_get_reference_count #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_mark_dirty _moz_cairo_surface_mark_dirty #define cairo_surface_mark_dirty_rectangle _moz_cairo_surface_mark_dirty_rectangle #define cairo_surface_reference _moz_cairo_surface_reference 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 510434049ba..2c81fdc63fe 100644 --- a/gfx/cairo/cairo/src/cairo-scaled-font-subsets-private.h +++ b/gfx/cairo/cairo/src/cairo-scaled-font-subsets-private.h @@ -41,17 +41,23 @@ typedef struct _cairo_scaled_font_subsets cairo_scaled_font_subsets_t; +typedef struct _cairo_scaled_font_subset { + cairo_scaled_font_t *scaled_font; + unsigned int font_id; + unsigned int subset_id; + + /* Index of glyphs array is subset_glyph_index. + * Value of glyphs array is scaled_font_glyph_index. + */ + unsigned long *glyphs; + unsigned int num_glyphs; +} cairo_scaled_font_subset_t; + /** * _cairo_scaled_font_subsets_create: - * - * @max_glyphs_per_unscaled_subset: the maximum number of glyphs that - * should appear in any unscaled subset. A value of 0 indicates that - * no unscaled subset will be created. All glyphs will mapped to - * scaled subsets. - * - * @max_glyphs_per_scaled_subset: the maximum number of glyphs that - * should appear in any scaled subset. A value of 0 indicates that - * no scaled subset will be created. + * @max_glyphs_per_subset: the maximum number of glyphs that should + * appear in any subset. A value of 0 indicates that there is no limit + * to the number of glyphs per subset. * * Create a new #cairo_scaled_font_subsets_t object which can be used * to create subsets of any number of cairo_scaled_font_t @@ -60,16 +66,12 @@ typedef struct _cairo_scaled_font_subsets cairo_scaled_font_subsets_t; * subsets with glyph indices packed into the range * [0 .. max_glyphs_per_subset). * - * @max_glyphs_per_unscaled_subset and @max_glyphs_per_scaled_subset - * cannot both be 0. - * * Return value: a pointer to the newly creates font subsets. The * caller owns this object and should call * _cairo_scaled_font_subsets_destroy() when done with it. **/ cairo_private cairo_scaled_font_subsets_t * -_cairo_scaled_font_subsets_create (int max_glyphs_unscaled_per_subset, - int max_glyphs_scaled_per_subset); +_cairo_scaled_font_subsets_create (int max_glyphs_per_subset); /** * _cairo_scaled_font_subsets_destroy: @@ -148,7 +150,7 @@ typedef void * @font_subset_callback: a function to be called for each font subset * @closure: closure data for the callback function * - * Iterate over each unique scaled font subset as created by calls to + * Iterate over each unique font subset as created by calls to * _cairo_scaled_font_subsets_map_glyph(). A subset is determined by * unique pairs of (font_id, subset_id) as returned by * _cairo_scaled_font_subsets_map_glyph(). @@ -173,44 +175,9 @@ typedef void * CAIRO_STATUS_NO_MEMORY. **/ cairo_private cairo_status_t -_cairo_scaled_font_subsets_foreach_scaled (cairo_scaled_font_subsets_t *font_subsets, - cairo_scaled_font_subset_callback_func_t font_subset_callback, - void *closure); - -/** - * _cairo_scaled_font_subsets_foreach_unscaled: - * @font_subsets: a #cairo_scaled_font_subsets_t - * @font_subset_callback: a function to be called for each font subset - * @closure: closure data for the callback function - * - * Iterate over each unique unscaled font subset as created by calls to - * _cairo_scaled_font_subsets_map_glyph(). A subset is determined by - * unique pairs of (font_id, subset_id) as returned by - * _cairo_scaled_font_subsets_map_glyph(). - * - * For each subset, @font_subset_callback will be called and will be - * provided with both a #cairo_scaled_font_subset_t object containing - * all the glyphs in the subset as well as the value of @closure. - * - * The #cairo_scaled_font_subset_t object contains the scaled_font, - * the font_id, and the subset_id corresponding to all glyphs - * belonging to the subset. In addition, it contains an array providing - * a mapping between subset glyph indices and the original scaled font - * glyph indices. - * - * The index of the array corresponds to subset_glyph_index values - * returned by _cairo_scaled_font_subsets_map_glyph() while the - * values of the array correspond to the scaled_font_glyph_index - * values passed as input to the same function. - * - * Return value: CAIRO_STATUS_SUCCESS if successful, or a non-zero - * value indicating an error. Possible errors include - * CAIRO_STATUS_NO_MEMORY. - **/ -cairo_private cairo_status_t -_cairo_scaled_font_subsets_foreach_unscaled (cairo_scaled_font_subsets_t *font_subsets, - cairo_scaled_font_subset_callback_func_t font_subset_callback, - void *closure); +_cairo_scaled_font_subsets_foreach (cairo_scaled_font_subsets_t *font_subsets, + cairo_scaled_font_subset_callback_func_t font_subset_callback, + void *closure); typedef struct _cairo_cff_subset { char *base_font; @@ -255,9 +222,9 @@ _cairo_cff_subset_fini (cairo_cff_subset_t *cff_subset); typedef struct _cairo_truetype_subset { char *base_font; - double *widths; - double x_min, y_min, x_max, y_max; - double ascent, descent; + int *widths; + long x_min, y_min, x_max, y_max; + long ascent, descent; char *data; unsigned long data_length; unsigned long *string_offsets; @@ -394,21 +361,4 @@ _cairo_type1_fallback_init_hex (cairo_type1_subset_t *type_subset, cairo_private void _cairo_type1_fallback_fini (cairo_type1_subset_t *subset); -/** - * _cairo_truetype_create_glyph_to_unicode_map: - * @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) assign - * the unicode character of each glyph in font_subset to - * fontsubset->to_unicode. - * - * Return value: CAIRO_STATUS_SUCCESS if successful, - * CAIRO_INT_STATUS_UNSUPPORTED if the unicode encoding of - * the glyphs is not available. Possible errors include - * CAIRO_STATUS_NO_MEMORY. - **/ -cairo_private cairo_int_status_t -_cairo_truetype_create_glyph_to_unicode_map (cairo_scaled_font_subset_t *font_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 d98cba2f862..0c428e7c3af 100644 --- a/gfx/cairo/cairo/src/cairo-scaled-font-subsets.c +++ b/gfx/cairo/cairo/src/cairo-scaled-font-subsets.c @@ -43,21 +43,16 @@ #include "cairo-scaled-font-subsets-private.h" struct _cairo_scaled_font_subsets { - int max_glyphs_per_unscaled_subset_limit; - int max_glyphs_per_unscaled_subset_used; - cairo_hash_table_t *unscaled_sub_fonts; - - int max_glyphs_per_scaled_subset_limit; - int max_glyphs_per_scaled_subset_used; - cairo_hash_table_t *scaled_sub_fonts; - + int max_glyphs_per_subset_limit; + int max_glyphs_per_subset_used; int num_sub_fonts; + + cairo_hash_table_t *sub_fonts; }; typedef struct _cairo_sub_font { cairo_hash_entry_t base; - cairo_bool_t is_scaled; cairo_scaled_font_subsets_t *parent; cairo_scaled_font_t *scaled_font; unsigned int font_id; @@ -168,34 +163,22 @@ _cairo_sub_fonts_equal (const void *key_a, const void *key_b) const cairo_sub_font_t *sub_font_a = key_a; const cairo_sub_font_t *sub_font_b = key_b; - if (sub_font_a->is_scaled) - return sub_font_a->scaled_font == sub_font_b->scaled_font; - else - return sub_font_a->scaled_font->font_face == sub_font_b->scaled_font->font_face; + return sub_font_a->scaled_font == sub_font_b->scaled_font; } static void _cairo_sub_font_init_key (cairo_sub_font_t *sub_font, cairo_scaled_font_t *scaled_font) { - if (sub_font->is_scaled) - { - sub_font->base.hash = (unsigned long) scaled_font; - sub_font->scaled_font = scaled_font; - } - else - { - sub_font->base.hash = (unsigned long) scaled_font->font_face; - sub_font->scaled_font = scaled_font; - } + sub_font->base.hash = (unsigned long) scaled_font; + sub_font->scaled_font = scaled_font; } static cairo_sub_font_t * _cairo_sub_font_create (cairo_scaled_font_subsets_t *parent, cairo_scaled_font_t *scaled_font, unsigned int font_id, - int max_glyphs_per_subset, - cairo_bool_t is_scaled) + int max_glyphs_per_subset) { cairo_sub_font_t *sub_font; @@ -203,7 +186,6 @@ _cairo_sub_font_create (cairo_scaled_font_subsets_t *parent, if (sub_font == NULL) return NULL; - sub_font->is_scaled = is_scaled; _cairo_sub_font_init_key (sub_font, scaled_font); sub_font->parent = parent; @@ -244,27 +226,6 @@ _cairo_sub_font_pluck (void *entry, void *closure) _cairo_sub_font_destroy (sub_font); } -static cairo_status_t -_cairo_sub_font_lookup_glyph (cairo_sub_font_t *sub_font, - unsigned long scaled_font_glyph_index, - unsigned int *subset_id, - unsigned int *subset_glyph_index) -{ - cairo_sub_font_glyph_t key, *sub_font_glyph; - - _cairo_sub_font_glyph_init_key (&key, scaled_font_glyph_index); - if (_cairo_hash_table_lookup (sub_font->sub_font_glyphs, &key.base, - (cairo_hash_entry_t **) &sub_font_glyph)) - { - *subset_id = sub_font_glyph->subset_id; - *subset_glyph_index = sub_font_glyph->subset_glyph_index; - - return CAIRO_STATUS_SUCCESS; - } - - return CAIRO_STATUS_NULL_POINTER; -} - static cairo_status_t _cairo_sub_font_map_glyph (cairo_sub_font_t *sub_font, unsigned long scaled_font_glyph_index, @@ -278,7 +239,8 @@ _cairo_sub_font_map_glyph (cairo_sub_font_t *sub_font, if (! _cairo_hash_table_lookup (sub_font->sub_font_glyphs, &key.base, (cairo_hash_entry_t **) &sub_font_glyph)) { - if (sub_font->num_glyphs_in_current_subset == sub_font->max_glyphs_per_subset) + if (sub_font->max_glyphs_per_subset && + sub_font->num_glyphs_in_current_subset == sub_font->max_glyphs_per_subset) { sub_font->current_subset++; sub_font->num_glyphs_in_current_subset = 0; @@ -290,16 +252,8 @@ _cairo_sub_font_map_glyph (cairo_sub_font_t *sub_font, if (sub_font_glyph == NULL) return CAIRO_STATUS_NO_MEMORY; - if (sub_font->is_scaled) - { - if (sub_font->num_glyphs_in_current_subset > sub_font->parent->max_glyphs_per_scaled_subset_used) - sub_font->parent->max_glyphs_per_scaled_subset_used = sub_font->num_glyphs_in_current_subset; - } - else - { - if (sub_font->num_glyphs_in_current_subset > sub_font->parent->max_glyphs_per_unscaled_subset_used) - sub_font->parent->max_glyphs_per_unscaled_subset_used = sub_font->num_glyphs_in_current_subset; - } + if (sub_font->num_glyphs_in_current_subset > sub_font->parent->max_glyphs_per_subset_used) + sub_font->parent->max_glyphs_per_subset_used = sub_font->num_glyphs_in_current_subset; status = _cairo_hash_table_insert (sub_font->sub_font_glyphs, &sub_font_glyph->base); if (status) @@ -319,7 +273,6 @@ _cairo_sub_font_collect (void *entry, void *closure) cairo_sub_font_collection_t *collection = closure; cairo_scaled_font_subset_t subset; int i; - unsigned int j; for (i = 0; i <= sub_font->current_subset; i++) { collection->subset_id = i; @@ -338,26 +291,14 @@ _cairo_sub_font_collect (void *entry, void *closure) subset.subset_id = i; subset.glyphs = collection->glyphs; subset.num_glyphs = collection->num_glyphs; - /* No need to check for out of memory here. If to_unicode is NULL, the PDF - * surface does not emit an ToUnicode stream */ - subset.to_unicode = malloc (collection->num_glyphs*sizeof(unsigned long)); - if (subset.to_unicode) { - for (j = 0; j < collection->num_glyphs; j++) { - /* default unicode character required when mapping fails */ - subset.to_unicode[j] = 0xfffd; - } - } - (collection->font_subset_callback) (&subset, - collection->font_subset_callback_closure); - if (subset.to_unicode != NULL) - free (subset.to_unicode); + (collection->font_subset_callback) (&subset, + collection->font_subset_callback_closure); } } cairo_scaled_font_subsets_t * -_cairo_scaled_font_subsets_create (int max_glyphs_per_unscaled_subset, - int max_glyphs_per_scaled_subset) +_cairo_scaled_font_subsets_create (int max_glyphs_per_subset) { cairo_scaled_font_subsets_t *subsets; @@ -365,23 +306,12 @@ _cairo_scaled_font_subsets_create (int max_glyphs_per_unscaled_subset, if (subsets == NULL) return NULL; - subsets->max_glyphs_per_unscaled_subset_limit = max_glyphs_per_unscaled_subset; - subsets->max_glyphs_per_unscaled_subset_used = 0; - - subsets->max_glyphs_per_scaled_subset_limit = max_glyphs_per_scaled_subset; - subsets->max_glyphs_per_scaled_subset_used = 0; - + subsets->max_glyphs_per_subset_limit = max_glyphs_per_subset; + subsets->max_glyphs_per_subset_used = 0; subsets->num_sub_fonts = 0; - subsets->unscaled_sub_fonts = _cairo_hash_table_create (_cairo_sub_fonts_equal); - if (! subsets->unscaled_sub_fonts) { - free (subsets); - return NULL; - } - - subsets->scaled_sub_fonts = _cairo_hash_table_create (_cairo_sub_fonts_equal); - if (! subsets->scaled_sub_fonts) { - free (subsets->unscaled_sub_fonts); + subsets->sub_fonts = _cairo_hash_table_create (_cairo_sub_fonts_equal); + if (! subsets->sub_fonts) { free (subsets); return NULL; } @@ -392,11 +322,8 @@ _cairo_scaled_font_subsets_create (int max_glyphs_per_unscaled_subset, void _cairo_scaled_font_subsets_destroy (cairo_scaled_font_subsets_t *subsets) { - _cairo_hash_table_foreach (subsets->scaled_sub_fonts, _cairo_sub_font_pluck, subsets->scaled_sub_fonts); - _cairo_hash_table_destroy (subsets->scaled_sub_fonts); - - _cairo_hash_table_foreach (subsets->unscaled_sub_fonts, _cairo_sub_font_pluck, subsets->unscaled_sub_fonts); - _cairo_hash_table_destroy (subsets->unscaled_sub_fonts); + _cairo_hash_table_foreach (subsets->sub_fonts, _cairo_sub_font_pluck, subsets->sub_fonts); + _cairo_hash_table_destroy (subsets->sub_fonts); free (subsets); } @@ -409,106 +336,38 @@ _cairo_scaled_font_subsets_map_glyph (cairo_scaled_font_subsets_t *subsets, unsigned int *subset_glyph_index) { cairo_sub_font_t key, *sub_font; - cairo_scaled_glyph_t *scaled_glyph; cairo_status_t status; - /* Lookup glyph in unscaled subsets */ - if (subsets->max_glyphs_per_unscaled_subset_limit > 0) { - key.is_scaled = FALSE; - _cairo_sub_font_init_key (&key, scaled_font); - if (_cairo_hash_table_lookup (subsets->unscaled_sub_fonts, &key.base, - (cairo_hash_entry_t **) &sub_font)) - { - status = _cairo_sub_font_lookup_glyph (sub_font, scaled_font_glyph_index, - subset_id, subset_glyph_index); - if (status == CAIRO_STATUS_SUCCESS) { - *font_id = sub_font->font_id; - return CAIRO_STATUS_SUCCESS; - } - } + _cairo_sub_font_init_key (&key, scaled_font); + if (! _cairo_hash_table_lookup (subsets->sub_fonts, &key.base, + (cairo_hash_entry_t **) &sub_font)) + { + sub_font = _cairo_sub_font_create (subsets, scaled_font, + subsets->num_sub_fonts++, + subsets->max_glyphs_per_subset_limit); + if (sub_font == NULL) + return CAIRO_STATUS_NO_MEMORY; + + status = _cairo_hash_table_insert (subsets->sub_fonts, + &sub_font->base); + if (status) + return status; } - /* Lookup glyph in scaled subsets */ - if (subsets->max_glyphs_per_scaled_subset_limit > 0) { - key.is_scaled = TRUE; - _cairo_sub_font_init_key (&key, scaled_font); - if (_cairo_hash_table_lookup (subsets->scaled_sub_fonts, &key.base, - (cairo_hash_entry_t **) &sub_font)) - { - status = _cairo_sub_font_lookup_glyph (sub_font, scaled_font_glyph_index, - subset_id, subset_glyph_index); - if (status == CAIRO_STATUS_SUCCESS) { - *font_id = sub_font->font_id; - return CAIRO_STATUS_SUCCESS; - } - } - } - - /* Glyph not found. Determine whether the glyph is outline or - * bitmap and add to the appropriate subset */ - status = _cairo_scaled_glyph_lookup (scaled_font, - scaled_font_glyph_index, - CAIRO_SCALED_GLYPH_INFO_PATH, - &scaled_glyph); - if (status == 0 && subsets->max_glyphs_per_unscaled_subset_limit > 0) { - /* Path available. Add to unscaled subset. */ - key.is_scaled = FALSE; - _cairo_sub_font_init_key (&key, scaled_font); - if (! _cairo_hash_table_lookup (subsets->unscaled_sub_fonts, &key.base, - (cairo_hash_entry_t **) &sub_font)) - { - sub_font = _cairo_sub_font_create (subsets, scaled_font, - subsets->num_sub_fonts++, - subsets->max_glyphs_per_unscaled_subset_limit, - FALSE); - if (sub_font == NULL) - return CAIRO_STATUS_NO_MEMORY; - - status = _cairo_hash_table_insert (subsets->unscaled_sub_fonts, - &sub_font->base); - if (status) - return status; - } - } else if (subsets->max_glyphs_per_scaled_subset_limit > 0) { - /* No path available. Add to scaled subset. */ - key.is_scaled = TRUE; - _cairo_sub_font_init_key (&key, scaled_font); - if (! _cairo_hash_table_lookup (subsets->scaled_sub_fonts, &key.base, - (cairo_hash_entry_t **) &sub_font)) - { - sub_font = _cairo_sub_font_create (subsets, scaled_font, - subsets->num_sub_fonts++, - subsets->max_glyphs_per_scaled_subset_limit, - TRUE); - if (sub_font == NULL) - return CAIRO_STATUS_NO_MEMORY; - - status = _cairo_hash_table_insert (subsets->scaled_sub_fonts, - &sub_font->base); - if (status) - return status; - } - } else { - return CAIRO_INT_STATUS_UNSUPPORTED; - } *font_id = sub_font->font_id; return _cairo_sub_font_map_glyph (sub_font, scaled_font_glyph_index, - subset_id, subset_glyph_index); + subset_id, subset_glyph_index); } -static cairo_status_t -_cairo_scaled_font_subsets_foreach_internal (cairo_scaled_font_subsets_t *font_subsets, - cairo_scaled_font_subset_callback_func_t font_subset_callback, - void *closure, - cairo_bool_t is_scaled) +cairo_private cairo_status_t +_cairo_scaled_font_subsets_foreach (cairo_scaled_font_subsets_t *font_subsets, + cairo_scaled_font_subset_callback_func_t font_subset_callback, + void *closure) { cairo_sub_font_collection_t collection; - if (is_scaled) - collection.glyphs_size = font_subsets->max_glyphs_per_scaled_subset_used; - else - collection.glyphs_size = font_subsets->max_glyphs_per_unscaled_subset_used; + collection.glyphs_size = font_subsets->max_glyphs_per_subset_used; collection.glyphs = malloc (collection.glyphs_size * sizeof(unsigned long)); if (collection.glyphs == NULL) return CAIRO_STATUS_NO_MEMORY; @@ -516,36 +375,10 @@ _cairo_scaled_font_subsets_foreach_internal (cairo_scaled_font_subsets_t collection.font_subset_callback = font_subset_callback; collection.font_subset_callback_closure = closure; - if (is_scaled) - _cairo_hash_table_foreach (font_subsets->scaled_sub_fonts, - _cairo_sub_font_collect, &collection); - else - _cairo_hash_table_foreach (font_subsets->unscaled_sub_fonts, - _cairo_sub_font_collect, &collection); + _cairo_hash_table_foreach (font_subsets->sub_fonts, + _cairo_sub_font_collect, &collection); free (collection.glyphs); return CAIRO_STATUS_SUCCESS; } - -cairo_private cairo_status_t -_cairo_scaled_font_subsets_foreach_scaled (cairo_scaled_font_subsets_t *font_subsets, - cairo_scaled_font_subset_callback_func_t font_subset_callback, - void *closure) -{ - return _cairo_scaled_font_subsets_foreach_internal (font_subsets, - font_subset_callback, - closure, - TRUE); -} - -cairo_private cairo_status_t -_cairo_scaled_font_subsets_foreach_unscaled (cairo_scaled_font_subsets_t *font_subsets, - cairo_scaled_font_subset_callback_func_t font_subset_callback, - void *closure) -{ - return _cairo_scaled_font_subsets_foreach_internal (font_subsets, - font_subset_callback, - closure, - FALSE); -} diff --git a/gfx/cairo/cairo/src/cairo-scaled-font.c b/gfx/cairo/cairo/src/cairo-scaled-font.c index 6efde8002e6..6da6106a32a 100644 --- a/gfx/cairo/cairo/src/cairo-scaled-font.c +++ b/gfx/cairo/cairo/src/cairo-scaled-font.c @@ -1,5 +1,5 @@ -/* -*- Mode: c; c-basic-offset: 4; indent-tabs-mode: t; tab-width: 8; -*- */ -/* +/* $Id: cairo-scaled-font.c,v 1.15 2007/04/03 19:21:53 vladimir%pobox.com Exp $ + * * Copyright © 2005 Keith Packard * * This library is free software; you can redistribute it and/or @@ -71,11 +71,10 @@ _cairo_scaled_glyph_destroy (void *abstract_glyph) free (scaled_glyph); } -const cairo_scaled_font_t _cairo_scaled_font_nil = { +static const cairo_scaled_font_t _cairo_scaled_font_nil = { { 0 }, /* hash_entry */ CAIRO_STATUS_NO_MEMORY, /* status */ CAIRO_REF_COUNT_INVALID, /* ref_count */ - { 0, 0, 0, NULL }, /* user_data */ NULL, /* font_face */ { 1., 0., 0., 1., 0, 0}, /* font_matrix */ { 1., 0., 0., 1., 0, 0}, /* ctm */ @@ -85,7 +84,6 @@ const cairo_scaled_font_t _cairo_scaled_font_nil = { CAIRO_HINT_METRICS_DEFAULT} , { 1., 0., 0., 1., 0, 0}, /* scale */ { 0., 0., 0., 0., 0. }, /* extents */ - CAIRO_MUTEX_NIL_INITIALIZER,/* mutex */ NULL, /* glyphs */ NULL, /* surface_backend */ NULL, /* surface_private */ @@ -185,7 +183,7 @@ typedef struct _cairo_scaled_font_map { static cairo_scaled_font_map_t *cairo_scaled_font_map = NULL; -CAIRO_MUTEX_DECLARE (_cairo_scaled_font_map_mutex); +CAIRO_MUTEX_DECLARE (cairo_scaled_font_map_mutex); static int _cairo_scaled_font_keys_equal (const void *abstract_key_a, const void *abstract_key_b); @@ -193,7 +191,7 @@ _cairo_scaled_font_keys_equal (const void *abstract_key_a, const void *abstract_ static cairo_scaled_font_map_t * _cairo_scaled_font_map_lock (void) { - CAIRO_MUTEX_LOCK (_cairo_scaled_font_map_mutex); + CAIRO_MUTEX_LOCK (cairo_scaled_font_map_mutex); if (cairo_scaled_font_map == NULL) { cairo_scaled_font_map = malloc (sizeof (cairo_scaled_font_map_t)); @@ -214,14 +212,14 @@ _cairo_scaled_font_map_lock (void) CLEANUP_SCALED_FONT_MAP: free (cairo_scaled_font_map); CLEANUP_MUTEX_LOCK: - CAIRO_MUTEX_UNLOCK (_cairo_scaled_font_map_mutex); + CAIRO_MUTEX_UNLOCK (cairo_scaled_font_map_mutex); return NULL; } static void _cairo_scaled_font_map_unlock (void) { - CAIRO_MUTEX_UNLOCK (_cairo_scaled_font_map_mutex); + CAIRO_MUTEX_UNLOCK (cairo_scaled_font_map_mutex); } void @@ -231,7 +229,7 @@ _cairo_scaled_font_map_destroy (void) cairo_scaled_font_map_t *font_map; cairo_scaled_font_t *scaled_font; - CAIRO_MUTEX_LOCK (_cairo_scaled_font_map_mutex); + CAIRO_MUTEX_LOCK (cairo_scaled_font_map_mutex); font_map = cairo_scaled_font_map; if (font_map == NULL) { @@ -256,7 +254,7 @@ _cairo_scaled_font_map_destroy (void) cairo_scaled_font_map = NULL; CLEANUP_MUTEX_LOCK: - CAIRO_MUTEX_UNLOCK (_cairo_scaled_font_map_mutex); + CAIRO_MUTEX_UNLOCK (cairo_scaled_font_map_mutex); } /* Fowler / Noll / Vo (FNV) Hash (http://www.isthe.com/chongo/tech/comp/fnv/) @@ -354,8 +352,6 @@ _cairo_scaled_font_init (cairo_scaled_font_t *scaled_font, { scaled_font->ref_count = 1; - _cairo_user_data_array_init (&scaled_font->user_data); - _cairo_scaled_font_init_key (scaled_font, font_face, font_matrix, ctm, options); @@ -365,7 +361,6 @@ _cairo_scaled_font_init (cairo_scaled_font_t *scaled_font, &scaled_font->font_matrix, &scaled_font->ctm); - CAIRO_MUTEX_INIT (&scaled_font->mutex); scaled_font->glyphs = _cairo_cache_create (_cairo_scaled_glyph_keys_equal, _cairo_scaled_glyph_destroy, max_glyphs_cached_per_font); @@ -390,15 +385,6 @@ _cairo_scaled_font_thaw_cache (cairo_scaled_font_t *scaled_font) _cairo_cache_thaw (scaled_font->glyphs); } -void -_cairo_scaled_font_reset_cache (cairo_scaled_font_t *scaled_font) -{ - _cairo_cache_destroy (scaled_font->glyphs); - scaled_font->glyphs = _cairo_cache_create (_cairo_scaled_glyph_keys_equal, - _cairo_scaled_glyph_destroy, - max_glyphs_cached_per_font); -} - void _cairo_scaled_font_set_metrics (cairo_scaled_font_t *scaled_font, cairo_font_extents_t *fs_metrics) @@ -430,15 +416,12 @@ _cairo_scaled_font_fini (cairo_scaled_font_t *scaled_font) if (scaled_font->glyphs != NULL) _cairo_cache_destroy (scaled_font->glyphs); - CAIRO_MUTEX_FINI (&scaled_font->mutex); - if (scaled_font->surface_backend != NULL && scaled_font->surface_backend->scaled_font_fini != NULL) scaled_font->surface_backend->scaled_font_fini (scaled_font); scaled_font->backend->fini (scaled_font); - _cairo_user_data_array_fini (&scaled_font->user_data); } /** @@ -476,7 +459,7 @@ cairo_scaled_font_create (cairo_font_face_t *font_face, font_map = _cairo_scaled_font_map_lock (); if (font_map == NULL) - return NULL; + goto UNWIND; _cairo_scaled_font_init_key (&key, font_face, font_matrix, ctm, options); @@ -484,6 +467,70 @@ cairo_scaled_font_create (cairo_font_face_t *font_face, /* Return existing scaled_font if it exists in the hash table. */ if (_cairo_hash_table_lookup (font_map->hash_table, &key.hash_entry, (cairo_hash_entry_t**) &scaled_font)) + { + _cairo_scaled_font_map_unlock (); + return cairo_scaled_font_reference (scaled_font); + } + + /* Otherwise create it and insert it into the hash table. */ + status = font_face->backend->scaled_font_create (font_face, font_matrix, + ctm, options, &scaled_font); + if (status) + goto UNWIND_FONT_MAP_LOCK; + + status = _cairo_hash_table_insert (font_map->hash_table, + &scaled_font->hash_entry); + if (status) + goto UNWIND_SCALED_FONT_CREATE; + + _cairo_scaled_font_map_unlock (); + + return scaled_font; + +UNWIND_SCALED_FONT_CREATE: + /* We can't call _cairo_scaled_font_destroy here since it expects + * that the font has already been successfully inserted into the + * hash table. */ + _cairo_scaled_font_fini (scaled_font); + free (scaled_font); +UNWIND_FONT_MAP_LOCK: + _cairo_scaled_font_map_unlock (); +UNWIND: + return NULL; +} +slim_hidden_def (cairo_scaled_font_create); + +/** + * cairo_scaled_font_reference: + * @scaled_font: a #cairo_scaled_font_t, (may be NULL in which case + * this function does nothing) + * + * Increases the reference count on @scaled_font by one. This prevents + * @scaled_font from being destroyed until a matching call to + * cairo_scaled_font_destroy() is made. + * + * Returns: the referenced #cairo_scaled_font_t + **/ +cairo_scaled_font_t * +cairo_scaled_font_reference (cairo_scaled_font_t *scaled_font) +{ + cairo_scaled_font_map_t *font_map; + + if (scaled_font == NULL) + return NULL; + + if (scaled_font->ref_count == CAIRO_REF_COUNT_INVALID) + return scaled_font; + + /* We would normally assert (scaled_font->ref_count > 0) here, but + * we are using ref_count == 0 as a legitimate case for the + * holdovers array. See below. */ + + /* cairo_scaled_font_t objects are cached and shared between + * threads. This works because these objects are immutable. Except + * that the reference count is mutable, so we have to do locking + * around any modification of the reference count. */ + font_map = _cairo_scaled_font_map_lock (); { /* If the original reference count is 0, then this font must have * been found in font_map->holdovers, (which means this caching is @@ -503,64 +550,8 @@ cairo_scaled_font_create (cairo_font_face_t *font_face, (font_map->num_holdovers - i) * sizeof (cairo_scaled_font_t*)); } - /* We increment the reference count manually here, (rather - * than calling into cairo_scaled_font_reference), since we - * must modify the reference count while our lock is still - * held. */ scaled_font->ref_count++; - _cairo_scaled_font_map_unlock (); - } else { - /* Otherwise create it and insert it into the hash table. */ - status = font_face->backend->scaled_font_create (font_face, font_matrix, - ctm, options, &scaled_font); - if (status) { - _cairo_scaled_font_map_unlock (); - return NULL; - } - status = _cairo_hash_table_insert (font_map->hash_table, - &scaled_font->hash_entry); - _cairo_scaled_font_map_unlock (); - - if (status) { - /* We can't call _cairo_scaled_font_destroy here since it expects - * that the font has already been successfully inserted into the - * hash table. */ - _cairo_scaled_font_fini (scaled_font); - free (scaled_font); - return NULL; - } - } - - return scaled_font; -} -slim_hidden_def (cairo_scaled_font_create); - -/** - * cairo_scaled_font_reference: - * @scaled_font: a #cairo_scaled_font_t, (may be NULL in which case - * this function does nothing) - * - * Increases the reference count on @scaled_font by one. This prevents - * @scaled_font from being destroyed until a matching call to - * cairo_scaled_font_destroy() is made. - * - * The number of references to a #cairo_scaled_font_t can be get using - * cairo_scaled_font_get_reference_count(). - * - * Returns: the referenced #cairo_scaled_font_t - **/ -cairo_scaled_font_t * -cairo_scaled_font_reference (cairo_scaled_font_t *scaled_font) -{ - if (scaled_font == NULL || scaled_font->ref_count == CAIRO_REF_COUNT_INVALID) - return scaled_font; - - _cairo_scaled_font_map_lock (); - { - assert (scaled_font->ref_count > 0); - - scaled_font->ref_count++; } _cairo_scaled_font_map_unlock (); @@ -580,11 +571,17 @@ void cairo_scaled_font_destroy (cairo_scaled_font_t *scaled_font) { cairo_scaled_font_map_t *font_map; - cairo_scaled_font_t *lru = NULL; - if (scaled_font == NULL || scaled_font->ref_count == CAIRO_REF_COUNT_INVALID) + if (scaled_font == NULL) return; + if (scaled_font->ref_count == CAIRO_REF_COUNT_INVALID) + return; + + /* cairo_scaled_font_t objects are cached and shared between + * threads. This works because these objects are immutable. Except + * that the reference count is mutable, so we have to do locking + * around any modification of the reference count. */ font_map = _cairo_scaled_font_map_lock (); { assert (font_map != NULL); @@ -598,13 +595,17 @@ cairo_scaled_font_destroy (cairo_scaled_font_t *scaled_font) * soon. To make room for it, we do actually destroy the * least-recently-used holdover. */ - if (font_map->num_holdovers == CAIRO_SCALED_FONT_MAX_HOLDOVERS) - { + if (font_map->num_holdovers == CAIRO_SCALED_FONT_MAX_HOLDOVERS) { + cairo_scaled_font_t *lru; + lru = font_map->holdovers[0]; assert (lru->ref_count == 0); _cairo_hash_table_remove (font_map->hash_table, &lru->hash_entry); + _cairo_scaled_font_fini (lru); + free (lru); + font_map->num_holdovers--; memmove (&font_map->holdovers[0], &font_map->holdovers[1], @@ -616,93 +617,9 @@ cairo_scaled_font_destroy (cairo_scaled_font_t *scaled_font) } } _cairo_scaled_font_map_unlock (); - - /* If we pulled an item from the holdovers array, (while the font - * map lock was held, of course), then there is no way that anyone - * else could have acquired a reference to it. So we can now - * safely call fini on it without any lock held. This is desirable - * as we never want to call into any backend function with a lock - * held. */ - if (lru) { - _cairo_scaled_font_fini (lru); - free (lru); - } } slim_hidden_def (cairo_scaled_font_destroy); -/** - * cairo_scaled_font_get_reference_count: - * @scaled_font: a #cairo_scaled_font_t - * - * Returns the current reference count of @scaled_font. - * - * Return value: the current reference count of @scaled_font. If the - * object is a nil object, 0 will be returned. - * - * Since: 1.4 - **/ -unsigned int -cairo_scaled_font_get_reference_count (cairo_scaled_font_t *scaled_font) -{ - if (scaled_font == NULL || scaled_font->ref_count == CAIRO_REF_COUNT_INVALID) - return 0; - - return scaled_font->ref_count; -} - -/** - * cairo_scaled_font_get_user_data: - * @scaled_font: a #cairo_scaled_font_t - * @key: the address of the #cairo_user_data_key_t the user data was - * attached to - * - * Return user data previously attached to @scaled_font using the - * specified key. If no user data has been attached with the given - * key this function returns %NULL. - * - * Return value: the user data previously attached or %NULL. - * - * Since: 1.4 - **/ -void * -cairo_scaled_font_get_user_data (cairo_scaled_font_t *scaled_font, - const cairo_user_data_key_t *key) -{ - return _cairo_user_data_array_get_data (&scaled_font->user_data, - key); -} - -/** - * cairo_scaled_font_set_user_data: - * @scaled_font: a #cairo_scaled_font_t - * @key: the address of a #cairo_user_data_key_t to attach the user data to - * @user_data: the user data to attach to the #cairo_scaled_font_t - * @destroy: a #cairo_destroy_func_t which will be called when the - * #cairo_t is destroyed or when new user data is attached using the - * same key. - * - * Attach user data to @scaled_font. To remove user data from a surface, - * call this function with the key that was used to set it and %NULL - * for @data. - * - * Return value: %CAIRO_STATUS_SUCCESS or %CAIRO_STATUS_NO_MEMORY if a - * slot could not be allocated for the user data. - * - * Since: 1.4 - **/ -cairo_status_t -cairo_scaled_font_set_user_data (cairo_scaled_font_t *scaled_font, - const cairo_user_data_key_t *key, - void *user_data, - cairo_destroy_func_t destroy) -{ - if (scaled_font->ref_count == CAIRO_REF_COUNT_INVALID) - return CAIRO_STATUS_NO_MEMORY; - - return _cairo_user_data_array_set_data (&scaled_font->user_data, - key, user_data, destroy); -} - /* Public font API follows. */ /** @@ -794,8 +711,6 @@ cairo_scaled_font_glyph_extents (cairo_scaled_font_t *scaled_font, if (scaled_font->status) return; - CAIRO_MUTEX_LOCK (scaled_font->mutex); - for (i = 0; i < num_glyphs; i++) { double left, top, right, bottom; @@ -805,7 +720,7 @@ cairo_scaled_font_glyph_extents (cairo_scaled_font_t *scaled_font, &scaled_glyph); if (status) { _cairo_scaled_font_set_error (scaled_font, status); - goto UNLOCK; + return; } /* "Ink" extents should skip "invisible" glyphs */ @@ -859,9 +774,6 @@ cairo_scaled_font_glyph_extents (cairo_scaled_font_t *scaled_font, extents->x_advance = 0.0; extents->y_advance = 0.0; } - - UNLOCK: - CAIRO_MUTEX_UNLOCK (scaled_font->mutex); } slim_hidden_def (cairo_scaled_font_glyph_extents); @@ -884,26 +796,24 @@ _cairo_scaled_font_text_to_glyphs (cairo_scaled_font_t *scaled_font, return CAIRO_STATUS_SUCCESS; } - CAIRO_MUTEX_LOCK (scaled_font->mutex); - if (scaled_font->backend->text_to_glyphs) { status = scaled_font->backend->text_to_glyphs (scaled_font, x, y, utf8, glyphs, num_glyphs); if (status != CAIRO_INT_STATUS_UNSUPPORTED) - goto DONE; + return status; } status = _cairo_utf8_to_ucs4 ((unsigned char*)utf8, -1, &ucs4, num_glyphs); if (status) - goto DONE; + return status; *glyphs = (cairo_glyph_t *) malloc ((*num_glyphs) * (sizeof (cairo_glyph_t))); if (*glyphs == NULL) { status = CAIRO_STATUS_NO_MEMORY; - goto DONE; + goto FAIL; } for (i = 0; i < *num_glyphs; i++) { @@ -919,18 +829,15 @@ _cairo_scaled_font_text_to_glyphs (cairo_scaled_font_t *scaled_font, if (status) { free (*glyphs); *glyphs = NULL; - goto DONE; + goto FAIL; } x += scaled_glyph->metrics.x_advance; y += scaled_glyph->metrics.y_advance; } - DONE: - CAIRO_MUTEX_UNLOCK (scaled_font->mutex); - - if (ucs4) - free (ucs4); + FAIL: + free (ucs4); return status; } @@ -1431,8 +1338,6 @@ _cairo_scaled_glyph_set_path (cairo_scaled_glyph_t *scaled_glyph, * If the desired info is not available, (for example, when trying to * get INFO_PATH with a bitmapped font), this function will return * CAIRO_INT_STATUS_UNSUPPORTED. - * - * NOTE: This function must be called with scaled_font->mutex held. **/ cairo_int_status_t _cairo_scaled_glyph_lookup (cairo_scaled_font_t *scaled_font, @@ -1448,6 +1353,8 @@ _cairo_scaled_glyph_lookup (cairo_scaled_font_t *scaled_font, if (scaled_font->status) return scaled_font->status; + CAIRO_MUTEX_LOCK (cairo_scaled_font_map_mutex); + key.hash = index; /* * Check cache for glyph @@ -1518,6 +1425,8 @@ _cairo_scaled_glyph_lookup (cairo_scaled_font_t *scaled_font, *scaled_glyph_ret = scaled_glyph; } + CAIRO_MUTEX_UNLOCK (cairo_scaled_font_map_mutex); + return status; } diff --git a/gfx/cairo/cairo/src/cairo-skiplist-private.h b/gfx/cairo/cairo/src/cairo-skiplist-private.h index b152f4b15de..d776ad642d9 100644 --- a/gfx/cairo/cairo/src/cairo-skiplist-private.h +++ b/gfx/cairo/cairo/src/cairo-skiplist-private.h @@ -34,7 +34,7 @@ * a skip_elt_t, (which will be allocated with variable size). * * The caller must also pass the size of the structure to - * _cairo_skip_list_init. + * skip_list_init. */ typedef struct _skip_elt { int prev_index; @@ -45,16 +45,16 @@ typedef struct _skip_elt { #define SKIP_LIST_ELT_TO_DATA(type, elt) ((type *) ((char *) (elt) - (sizeof (type) - sizeof (skip_elt_t)))) typedef int -(*cairo_skip_list_compare_t) (void *list, void *a, void *b); +(*skip_list_compare_t) (void *list, void *a, void *b); typedef struct _skip_list { - cairo_skip_list_compare_t compare; + skip_list_compare_t compare; size_t elt_size; size_t data_size; skip_elt_t *chains[MAX_LEVEL]; skip_elt_t *freelists[MAX_LEVEL]; int max_level; -} cairo_skip_list_t; +} skip_list_t; /* Initialize a new skip list. The compare function accepts a pointer * to the list as well as pointers to two elements. The function must @@ -65,8 +65,8 @@ typedef struct _skip_list { * list elements must have as its final member a skip_elt_t */ cairo_private void -_cairo_skip_list_init (cairo_skip_list_t *list, - cairo_skip_list_compare_t compare, +skip_list_init (skip_list_t *list, + skip_list_compare_t compare, size_t elt_size); @@ -74,7 +74,7 @@ _cairo_skip_list_init (cairo_skip_list_t *list, * in it. (XXX: currently this simply deletes all elements.) */ cairo_private void -_cairo_skip_list_fini (cairo_skip_list_t *list); +skip_list_fini (skip_list_t *list); /* Insert a new element into the list at the correct sort order as * determined by compare. If unique is true, then duplicate elements @@ -82,18 +82,18 @@ _cairo_skip_list_fini (cairo_skip_list_t *list); * Otherwise data will be copied (elt_size bytes from via * memcpy) and the new element is returned. */ cairo_private void * -_cairo_skip_list_insert (cairo_skip_list_t *list, void *data, int unique); +skip_list_insert (skip_list_t *list, void *data, int unique); /* Find an element which compare considers equal to */ cairo_private void * -_cairo_skip_list_find (cairo_skip_list_t *list, void *data); +skip_list_find (skip_list_t *list, void *data); /* Delete an element which compare considers equal to */ cairo_private void -_cairo_skip_list_delete (cairo_skip_list_t *list, void *data); +skip_list_delete (skip_list_t *list, void *data); /* Delete the given element from the list. */ cairo_private void -_cairo_skip_list_delete_given (cairo_skip_list_t *list, skip_elt_t *given); +skip_list_delete_given (skip_list_t *list, skip_elt_t *given); #endif diff --git a/gfx/cairo/cairo/src/cairo-skiplist.c b/gfx/cairo/cairo/src/cairo-skiplist.c index 451ecb06df0..6dc4e3c20a5 100644 --- a/gfx/cairo/cairo/src/cairo-skiplist.c +++ b/gfx/cairo/cairo/src/cairo-skiplist.c @@ -34,7 +34,7 @@ /* Four 256 element lookup tables back to back implementing a linear * feedback shift register of degree 32. */ -static unsigned const _cairo_lfsr_random_lut[1024] = { +static unsigned const lfsr_lut[1024] = { 0x00000000, 0x9a795537, 0xae8bff59, 0x34f2aa6e, 0xc76eab85, 0x5d17feb2, 0x69e554dc, 0xf39c01eb, 0x14a4023d, 0x8edd570a, 0xba2ffd64, 0x2056a853, 0xd3caa9b8, 0x49b3fc8f, 0x7d4156e1, 0xe73803d6, 0x2948047a, 0xb331514d, @@ -207,25 +207,24 @@ static unsigned const _cairo_lfsr_random_lut[1024] = { 0xeaa6b0df, 0x6a98c0b4, 0x184c1316, 0x9872637d, 0x8249a6f7, 0x0277d69c, 0xb63e2de3, 0x36005d88, 0x2c3b9802, 0xac05e869}; -static unsigned _cairo_lfsr_random_state = 0x12345678; - static unsigned lfsr_random(void) { + static unsigned state = 0x12345678; unsigned next; - next = _cairo_lfsr_random_lut[((_cairo_lfsr_random_state>> 0) & 0xFF) + 0*256]; - next ^= _cairo_lfsr_random_lut[((_cairo_lfsr_random_state>> 8) & 0xFF) + 1*256]; - next ^= _cairo_lfsr_random_lut[((_cairo_lfsr_random_state>>16) & 0xFF) + 2*256]; - next ^= _cairo_lfsr_random_lut[((_cairo_lfsr_random_state>>24) & 0xFF) + 3*256]; - return _cairo_lfsr_random_state = next; + next = lfsr_lut[((state>> 0) & 0xFF) + 0*256]; + next ^= lfsr_lut[((state>> 8) & 0xFF) + 1*256]; + next ^= lfsr_lut[((state>>16) & 0xFF) + 2*256]; + next ^= lfsr_lut[((state>>24) & 0xFF) + 3*256]; + return state = next; } /* * Initialize an empty skip list */ void -_cairo_skip_list_init (cairo_skip_list_t *list, - cairo_skip_list_compare_t compare, +skip_list_init (skip_list_t *list, + skip_list_compare_t compare, size_t elt_size) { int i; @@ -243,13 +242,13 @@ _cairo_skip_list_init (cairo_skip_list_t *list, } void -_cairo_skip_list_fini (cairo_skip_list_t *list) +skip_list_fini (skip_list_t *list) { skip_elt_t *elt; int i; while ((elt = list->chains[0])) { - _cairo_skip_list_delete_given (list, elt); + skip_list_delete_given (list, elt); } for (i=0; ifreelists[i]; @@ -284,7 +283,7 @@ random_level (void) } static void * -alloc_node_for_level (cairo_skip_list_t *list, unsigned level) +alloc_node_for_level (skip_list_t *list, unsigned level) { if (list->freelists[level-1]) { skip_elt_t *elt = list->freelists[level-1]; @@ -295,7 +294,7 @@ alloc_node_for_level (cairo_skip_list_t *list, unsigned level) } static void -free_elt (cairo_skip_list_t *list, skip_elt_t *elt) +free_elt (skip_list_t *list, skip_elt_t *elt) { elt->prev = list->freelists[elt->prev_index]; list->freelists[elt->prev_index] = elt; @@ -305,7 +304,7 @@ free_elt (cairo_skip_list_t *list, skip_elt_t *elt) * Insert 'data' into the list */ void * -_cairo_skip_list_insert (cairo_skip_list_t *list, void *data, int unique) +skip_list_insert (skip_list_t *list, void *data, int unique) { skip_elt_t **update[MAX_LEVEL]; skip_elt_t *prev[MAX_LEVEL]; @@ -370,7 +369,7 @@ _cairo_skip_list_insert (cairo_skip_list_t *list, void *data, int unique) } void * -_cairo_skip_list_find (cairo_skip_list_t *list, void *data) +skip_list_find (skip_list_t *list, void *data) { int i; skip_elt_t **next = list->chains; @@ -395,7 +394,7 @@ _cairo_skip_list_find (cairo_skip_list_t *list, void *data) } void -_cairo_skip_list_delete (cairo_skip_list_t *list, void *data) +skip_list_delete (skip_list_t *list, void *data) { skip_elt_t **update[MAX_LEVEL], *prev[MAX_LEVEL]; skip_elt_t *elt, **next; @@ -431,7 +430,7 @@ _cairo_skip_list_delete (cairo_skip_list_t *list, void *data) } void -_cairo_skip_list_delete_given (cairo_skip_list_t *list, skip_elt_t *given) +skip_list_delete_given (skip_list_t *list, skip_elt_t *given) { skip_elt_t **update[MAX_LEVEL], *prev[MAX_LEVEL]; skip_elt_t *elt, **next; diff --git a/gfx/cairo/cairo/src/cairo-slope.c b/gfx/cairo/cairo/src/cairo-slope.c index 78664c5386f..2c888e404d4 100644 --- a/gfx/cairo/cairo/src/cairo-slope.c +++ b/gfx/cairo/cairo/src/cairo-slope.c @@ -51,7 +51,7 @@ _cairo_slope_init (cairo_slope_t *slope, cairo_point_t *a, cairo_point_t *b) difference between a and b is less than PI. < 0 => a less positive than b - == 0 => a equal to b + == 0 => a equal to be > 0 => a more positive than b */ int @@ -67,12 +67,6 @@ _cairo_slope_compare (cairo_slope_t *a, cairo_slope_t *b) if (diff < 0) return -1; - /* special-case zero vectors. the intended logic here is: - * zero vectors all compare equal, and more positive than any - * non-zero vector. - */ - if (a->dx == 0 && a->dy == 0 && b->dx == 0 && b->dy ==0) - return 0; if (a->dx == 0 && a->dy == 0) return 1; if (b->dx == 0 && b->dy ==0) diff --git a/gfx/cairo/cairo/src/cairo-spline.c b/gfx/cairo/cairo/src/cairo-spline.c index 3624bfc348c..900d3ca0b55 100644 --- a/gfx/cairo/cairo/src/cairo-spline.c +++ b/gfx/cairo/cairo/src/cairo-spline.c @@ -37,7 +37,7 @@ #include "cairoint.h" static cairo_status_t -_cairo_spline_grow (cairo_spline_t *spline); +_cairo_spline_grow_by (cairo_spline_t *spline, int additional); static cairo_status_t _cairo_spline_add_point (cairo_spline_t *spline, cairo_point_t *point); @@ -90,47 +90,31 @@ _cairo_spline_init (cairo_spline_t *spline, void _cairo_spline_fini (cairo_spline_t *spline) { - if (spline->points && spline->points != spline->points_embedded) - free (spline->points); - - spline->points = NULL; - spline->points_size = 0; spline->num_points = 0; + spline->points_size = 0; + free (spline->points); + spline->points = NULL; } -/* make room for at least one more point */ static cairo_status_t -_cairo_spline_grow (cairo_spline_t *spline) +_cairo_spline_grow_by (cairo_spline_t *spline, int additional) { cairo_point_t *new_points; int old_size = spline->points_size; - int embedded_size = sizeof (spline->points_embedded) / sizeof (spline->points_embedded[0]); - int new_size = 2 * MAX (old_size, 16); + int new_size = spline->num_points + additional; - /* we have a local buffer at spline->points_embedded. try to fulfill the request - * from there. */ - if (old_size < embedded_size) { - spline->points = spline->points_embedded; - spline->points_size = embedded_size; + if (new_size <= spline->points_size) return CAIRO_STATUS_SUCCESS; - } - assert (spline->num_points <= spline->points_size); - - if (spline->points == spline->points_embedded) { - new_points = malloc (new_size * sizeof (cairo_point_t)); - if (new_points) - memcpy (new_points, spline->points, old_size * sizeof (cairo_point_t)); - } else { - new_points = realloc (spline->points, new_size * sizeof (cairo_point_t)); - } + spline->points_size = new_size; + new_points = realloc (spline->points, spline->points_size * sizeof (cairo_point_t)); if (new_points == NULL) { + spline->points_size = old_size; return CAIRO_STATUS_NO_MEMORY; } spline->points = new_points; - spline->points_size = new_size; return CAIRO_STATUS_SUCCESS; } @@ -148,7 +132,8 @@ _cairo_spline_add_point (cairo_spline_t *spline, cairo_point_t *point) } if (spline->num_points >= spline->points_size) { - status = _cairo_spline_grow (spline); + int additional = spline->points_size ? spline->points_size : 32; + status = _cairo_spline_grow_by (spline, additional); if (status) return status; } diff --git a/gfx/cairo/cairo/src/cairo-surface.c b/gfx/cairo/cairo/src/cairo-surface.c index 92efa00571b..ca7a937c318 100644 --- a/gfx/cairo/cairo/src/cairo-surface.c +++ b/gfx/cairo/cairo/src/cairo-surface.c @@ -41,45 +41,107 @@ #include "cairo-surface-fallback-private.h" #include "cairo-clip-private.h" -#define DEFINE_NIL_SURFACE(status, name) \ -const cairo_surface_t name = { \ - &cairo_image_surface_backend, /* backend */ \ - CAIRO_SURFACE_TYPE_IMAGE, \ - CAIRO_CONTENT_COLOR, \ - CAIRO_REF_COUNT_INVALID, /* ref_count */ \ - status, /* status */ \ - FALSE, /* finished */ \ - { 0, /* size */ \ - 0, /* num_elements */ \ - 0, /* element_size */ \ - NULL, /* elements */ \ - }, /* user_data */ \ - { 1.0, 0.0, \ - 0.0, 1.0, \ - 0.0, 0.0 \ - }, /* device_transform */ \ - { 1.0, 0.0, \ - 0.0, 1.0, \ - 0.0, 0.0 \ - }, /* device_transform_inverse */ \ - 0.0, /* x_fallback_resolution */ \ - 0.0, /* y_fallback_resolution */ \ - NULL, /* clip */ \ - 0, /* next_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 = { + &cairo_image_surface_backend, /* backend */ + CAIRO_SURFACE_TYPE_IMAGE, + CAIRO_CONTENT_COLOR, + CAIRO_REF_COUNT_INVALID, /* ref_count */ + CAIRO_STATUS_NO_MEMORY, /* status */ + FALSE, /* finished */ + { 0, /* size */ + 0, /* num_elements */ + 0, /* element_size */ + NULL, /* elements */ + }, /* user_data */ + { 1.0, 0.0, + 0.0, 1.0, + 0.0, 0.0 + }, /* device_transform */ + { 1.0, 0.0, + 0.0, 1.0, + 0.0, 0.0 + }, /* device_transform_inverse */ + 0.0, /* x_fallback_resolution */ + 0.0, /* y_fallback_resolution */ + NULL, /* clip */ + 0, /* next_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 */ +}; -DEFINE_NIL_SURFACE(CAIRO_STATUS_NO_MEMORY, _cairo_surface_nil); -DEFINE_NIL_SURFACE(CAIRO_STATUS_FILE_NOT_FOUND, _cairo_surface_nil_file_not_found); -DEFINE_NIL_SURFACE(CAIRO_STATUS_READ_ERROR, _cairo_surface_nil_read_error); -DEFINE_NIL_SURFACE(CAIRO_STATUS_WRITE_ERROR, _cairo_surface_nil_write_error); +const cairo_surface_t _cairo_surface_nil_file_not_found = { + &cairo_image_surface_backend, /* backend */ + CAIRO_SURFACE_TYPE_IMAGE, + CAIRO_CONTENT_COLOR, + CAIRO_REF_COUNT_INVALID, /* ref_count */ + CAIRO_STATUS_FILE_NOT_FOUND, /* status */ + FALSE, /* finished */ + { 0, /* size */ + 0, /* num_elements */ + 0, /* element_size */ + NULL, /* elements */ + }, /* user_data */ + { 1.0, 0.0, + 0.0, 1.0, + 0.0, 0.0 + }, /* device_transform */ + { 1.0, 0.0, + 0.0, 1.0, + 0.0, 0.0 + }, /* device_transform_inverse */ + 0.0, /* x_fallback_resolution */ + 0.0, /* y_fallback_resolution */ + NULL, /* clip */ + 0, /* next_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, + CAIRO_REF_COUNT_INVALID, /* ref_count */ + CAIRO_STATUS_READ_ERROR, /* status */ + FALSE, /* finished */ + { 0, /* size */ + 0, /* num_elements */ + 0, /* element_size */ + NULL, /* elements */ + }, /* user_data */ + { 1.0, 0.0, + 0.0, 1.0, + 0.0, 0.0 + }, /* device_transform */ + { 1.0, 0.0, + 0.0, 1.0, + 0.0, 0.0 + }, /* device_transform_inverse */ + 0.0, /* x_fallback_resolution */ + 0.0, /* y_fallback_resolution */ + NULL, /* clip */ + 0, /* next_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 _cairo_surface_copy_pattern_for_destination (const cairo_pattern_t *pattern, @@ -141,12 +203,10 @@ slim_hidden_def (cairo_surface_get_type); * cairo_surface_get_content: * @surface: a #cairo_surface_t * - * This function returns the content type of @surface which indicates - * whether the surface contains color and/or alpha information. See + * Return value: The content type of @surface which indicates whether + * the surface contains color and/or alpha information. See * #cairo_content_t. * - * Return value: The content type of @surface. - * * Since: 1.2 **/ cairo_content_t @@ -221,23 +281,12 @@ _cairo_surface_create_similar_scratch (cairo_surface_t *other, if (other->status) return (cairo_surface_t*) &_cairo_surface_nil; - if (other->backend->create_similar) { + if (other->backend->create_similar) surface = other->backend->create_similar (other, content, width, height); - /* It's not an error if the backend didn't create a valid - * surface---it may just not be supported. */ - if (surface && surface->status) { - cairo_surface_destroy (surface); - surface = NULL; - } - } - if (surface == NULL) + if (!surface) surface = cairo_image_surface_create (format, width, height); - /* If any error occurred, then return the nil surface we received. */ - if (surface->status) - return surface; - cairo_surface_get_font_options (other, &options); _cairo_surface_set_font_options (surface, &options); @@ -353,15 +402,15 @@ _cairo_surface_get_clip_mode (cairo_surface_t *surface) * @surface from being destroyed until a matching call to * cairo_surface_destroy() is made. * - * The number of references to a #cairo_surface_t can be get using - * cairo_surface_get_reference_count(). - * * Return value: the referenced #cairo_surface_t. **/ cairo_surface_t * cairo_surface_reference (cairo_surface_t *surface) { - if (surface == NULL || surface->ref_count == CAIRO_REF_COUNT_INVALID) + if (surface == NULL) + return NULL; + + if (surface->ref_count == CAIRO_REF_COUNT_INVALID) return surface; assert (surface->ref_count > 0); @@ -383,7 +432,10 @@ slim_hidden_def (cairo_surface_reference); void cairo_surface_destroy (cairo_surface_t *surface) { - if (surface == NULL || surface->ref_count == CAIRO_REF_COUNT_INVALID) + if (surface == NULL) + return; + + if (surface->ref_count == CAIRO_REF_COUNT_INVALID) return; assert (surface->ref_count > 0); @@ -392,8 +444,7 @@ cairo_surface_destroy (cairo_surface_t *surface) if (surface->ref_count) return; - if (! surface->finished) - cairo_surface_finish (surface); + cairo_surface_finish (surface); _cairo_user_data_array_fini (&surface->user_data); @@ -401,26 +452,6 @@ cairo_surface_destroy (cairo_surface_t *surface) } slim_hidden_def(cairo_surface_destroy); -/** - * cairo_surface_get_reference_count: - * @surface: a #cairo_surface_t - * - * Returns the current reference count of @surface. - * - * Return value: the current reference count of @surface. If the - * object is a nil object, 0 will be returned. - * - * Since: 1.4 - **/ -unsigned int -cairo_surface_get_reference_count (cairo_surface_t *surface) -{ - if (surface == NULL || surface->ref_count == CAIRO_REF_COUNT_INVALID) - return 0; - - return surface->ref_count; -} - /** * cairo_surface_finish: * @surface: the #cairo_surface_t to finish @@ -444,12 +475,6 @@ cairo_surface_finish (cairo_surface_t *surface) { cairo_status_t status; - if (surface == NULL) - return; - - if (surface->ref_count == CAIRO_REF_COUNT_INVALID) - return; - if (surface->finished) { _cairo_surface_set_error (surface, CAIRO_STATUS_SURFACE_FINISHED); return; @@ -790,10 +815,8 @@ cairo_surface_get_device_offset (cairo_surface_t *surface, double *x_offset, double *y_offset) { - if (x_offset) - *x_offset = surface->device_transform.x0; - if (y_offset) - *y_offset = surface->device_transform.y0; + *x_offset = surface->device_transform.x0; + *y_offset = surface->device_transform.y0; } slim_hidden_def (cairo_surface_get_device_offset); @@ -1001,7 +1024,7 @@ _cairo_surface_clone_similar (cairo_surface_t *surface, status = surface->backend->clone_similar (surface, src, src_x, src_y, width, height, clone_out); - if (status == CAIRO_STATUS_SUCCESS && *clone_out != src) + if (status == CAIRO_STATUS_SUCCESS) (*clone_out)->device_transform = src->device_transform; if (status != CAIRO_INT_STATUS_UNSUPPORTED) @@ -1013,10 +1036,8 @@ _cairo_surface_clone_similar (cairo_surface_t *surface, status = surface->backend->clone_similar (surface, &image->base, src_x, src_y, width, height, clone_out); - if (status == CAIRO_STATUS_SUCCESS && *clone_out != src) { + if (status == CAIRO_STATUS_SUCCESS) (*clone_out)->device_transform = src->device_transform; - (*clone_out)->device_transform_inverse = src->device_transform_inverse; - } /* If the above failed point, we could implement a full fallback * using acquire_dest_image, but that's going to be very @@ -1255,6 +1276,12 @@ _cairo_surface_paint (cairo_surface_t *surface, assert (! surface->is_snapshot); + if (source->type == CAIRO_PATTERN_TYPE_SURFACE && + (source->extend == CAIRO_EXTEND_REFLECT || source->extend == CAIRO_EXTEND_PAD)) + { + return CAIRO_STATUS_NO_MEMORY; + } + _cairo_surface_copy_pattern_for_destination (source, surface, &dev_source.base); if (surface->backend->paint) { @@ -1283,6 +1310,12 @@ _cairo_surface_mask (cairo_surface_t *surface, assert (! surface->is_snapshot); + if (source->type == CAIRO_PATTERN_TYPE_SURFACE && + (source->extend == CAIRO_EXTEND_REFLECT || source->extend == CAIRO_EXTEND_PAD)) + { + return CAIRO_STATUS_NO_MEMORY; + } + _cairo_surface_copy_pattern_for_destination (source, surface, &dev_source.base); _cairo_surface_copy_pattern_for_destination (mask, surface, &dev_mask.base); @@ -1321,6 +1354,12 @@ _cairo_surface_stroke (cairo_surface_t *surface, assert (! surface->is_snapshot); + if (source->type == CAIRO_PATTERN_TYPE_SURFACE && + (source->extend == CAIRO_EXTEND_REFLECT || source->extend == CAIRO_EXTEND_PAD)) + { + return CAIRO_STATUS_NO_MEMORY; + } + _cairo_surface_copy_pattern_for_destination (source, surface, &dev_source.base); if (surface->backend->stroke) { @@ -1360,6 +1399,12 @@ _cairo_surface_fill (cairo_surface_t *surface, assert (! surface->is_snapshot); + if (source->type == CAIRO_PATTERN_TYPE_SURFACE && + (source->extend == CAIRO_EXTEND_REFLECT || source->extend == CAIRO_EXTEND_PAD)) + { + return CAIRO_STATUS_NO_MEMORY; + } + _cairo_surface_copy_pattern_for_destination (source, surface, &dev_source.base); if (surface->backend->fill) { @@ -1761,6 +1806,12 @@ _cairo_surface_show_glyphs (cairo_surface_t *surface, assert (! surface->is_snapshot); + if (source->type == CAIRO_PATTERN_TYPE_SURFACE && + (source->extend == CAIRO_EXTEND_REFLECT || source->extend == CAIRO_EXTEND_PAD)) + { + return CAIRO_STATUS_NO_MEMORY; + } + if (!num_glyphs) return CAIRO_STATUS_SUCCESS; @@ -1788,22 +1839,19 @@ _cairo_surface_show_glyphs (cairo_surface_t *surface, cairo_font_options_destroy (font_options); } - CAIRO_MUTEX_LOCK (dev_scaled_font->mutex); - - status = CAIRO_INT_STATUS_UNSUPPORTED; - - if (surface->backend->show_glyphs) + if (surface->backend->show_glyphs) { status = surface->backend->show_glyphs (surface, op, &dev_source.base, glyphs, num_glyphs, dev_scaled_font); + if (status != CAIRO_INT_STATUS_UNSUPPORTED) + goto FINISH; + } - if (status == CAIRO_INT_STATUS_UNSUPPORTED) - status = _cairo_surface_fallback_show_glyphs (surface, op, &dev_source.base, - glyphs, num_glyphs, - dev_scaled_font); - - CAIRO_MUTEX_UNLOCK (dev_scaled_font->mutex); + status = _cairo_surface_fallback_show_glyphs (surface, op, &dev_source.base, + glyphs, num_glyphs, + dev_scaled_font); +FINISH: if (dev_scaled_font != scaled_font) cairo_scaled_font_destroy (dev_scaled_font); @@ -2089,5 +2137,17 @@ _cairo_surface_copy_pattern_for_destination (const cairo_pattern_t *pattern, } } +/** + * cairo_surface_get_reference_count + * @surface: the #cairo_surface_t to fetch the reference count for + * + * Returns the number of references to this surface that are held. + */ +unsigned int +cairo_surface_get_reference_count (cairo_surface_t *surface) +{ + return surface->ref_count; +} + /* LocalWords: rasterized */ diff --git a/gfx/cairo/cairo/src/cairo-svg-surface.c b/gfx/cairo/cairo/src/cairo-svg-surface.c index 5cb9ce0b97f..534ba01f967 100644 --- a/gfx/cairo/cairo/src/cairo-svg-surface.c +++ b/gfx/cairo/cairo/src/cairo-svg-surface.c @@ -240,9 +240,7 @@ cairo_svg_surface_create (const char *filename, status = _cairo_output_stream_get_status (stream); if (status) { _cairo_error (status); - return (status == CAIRO_STATUS_WRITE_ERROR) ? - (cairo_surface_t *) &_cairo_surface_nil_write_error : - (cairo_surface_t *) &_cairo_surface_nil; + return (cairo_surface_t *) &_cairo_surface_nil; } return _cairo_svg_surface_create_for_stream_internal (stream, width, height, CAIRO_SVG_VERSION_1_1); @@ -477,7 +475,7 @@ _cairo_svg_surface_show_page (void *abstract_surface) } static void -_cairo_svg_surface_emit_transform (cairo_output_stream_t *output, +emit_transform (cairo_output_stream_t *output, char const *attribute_str, char const *trailer, cairo_matrix_t *matrix) @@ -565,7 +563,7 @@ _cairo_svg_path_close_path (void *closure) } static cairo_status_t -_cairo_svg_surface_emit_path (cairo_output_stream_t *output, +emit_path (cairo_output_stream_t *output, cairo_path_fixed_t *path, cairo_matrix_t *ctm_inverse) { @@ -608,7 +606,7 @@ _cairo_svg_document_emit_outline_glyph_data (cairo_svg_document_t *document, _cairo_output_stream_printf (document->xml_node_glyphs, "xml_node_glyphs, scaled_glyph->path, NULL); + status = emit_path (document->xml_node_glyphs, scaled_glyph->path, NULL); _cairo_output_stream_printf (document->xml_node_glyphs, "/>\n"); @@ -644,7 +642,7 @@ _cairo_svg_document_emit_bitmap_glyph_data (cairo_svg_document_t *document, } _cairo_output_stream_printf (document->xml_node_glyphs, "xml_node_glyphs, " transform", ">/n", &image->base.device_transform); + emit_transform (document->xml_node_glyphs, " transform", ">/n", &image->base.device_transform); for (y = 0, row = image->data, rows = image->height; rows; row += image->stride, rows--, y++) { for (x = 0, byte = row, cols = (image->width + 7) / 8; cols; byte++, cols--) { @@ -676,7 +674,7 @@ _cairo_svg_document_emit_glyph (cairo_svg_document_t *document, cairo_status_t status; _cairo_output_stream_printf (document->xml_node_glyphs, - "\n", + "\n", font_id, subset_glyph_index); @@ -709,9 +707,9 @@ _cairo_svg_document_emit_font_subset (cairo_scaled_font_subset_t *font_subset, static void _cairo_svg_document_emit_font_subsets (cairo_svg_document_t *document) { - _cairo_scaled_font_subsets_foreach_scaled (document->font_subsets, - _cairo_svg_document_emit_font_subset, - document); + _cairo_scaled_font_subsets_foreach (document->font_subsets, + _cairo_svg_document_emit_font_subset, + document); _cairo_scaled_font_subsets_destroy (document->font_subsets); document->font_subsets = NULL; } @@ -737,7 +735,7 @@ _cairo_svg_test_force_fallbacks (void) } static cairo_int_status_t -__cairo_svg_surface_operation_supported (cairo_svg_surface_t *surface, +_operation_supported (cairo_svg_surface_t *surface, cairo_operator_t op, const cairo_pattern_t *pattern) { @@ -754,11 +752,11 @@ __cairo_svg_surface_operation_supported (cairo_svg_surface_t *surface, } static cairo_int_status_t -_cairo_svg_surface_analyze_operation (cairo_svg_surface_t *surface, +_analyze_operation (cairo_svg_surface_t *surface, cairo_operator_t op, const cairo_pattern_t *pattern) { - if (__cairo_svg_surface_operation_supported (surface, op, pattern)) + if (_operation_supported (surface, op, pattern)) return CAIRO_STATUS_SUCCESS; else return CAIRO_INT_STATUS_UNSUPPORTED; @@ -801,7 +799,7 @@ _cairo_svg_surface_finish (void *abstract_surface) } static void -_cairo_svg_surface_emit_alpha_filter (cairo_svg_document_t *document) +emit_alpha_filter (cairo_svg_document_t *document) { if (document->alpha_filter) return; @@ -916,27 +914,19 @@ _cairo_surface_base64_encode (cairo_surface_t *surface, } static cairo_status_t -_cairo_svg_surface_emit_composite_image_pattern (cairo_output_stream_t *output, +emit_composite_image_pattern (cairo_output_stream_t *output, cairo_svg_surface_t *svg_surface, cairo_surface_pattern_t *pattern, int pattern_id, const char *extra_attributes) { - cairo_surface_t *surface; - cairo_surface_attributes_t surface_attr; - cairo_rectangle_int16_t extents; + cairo_image_surface_t *image; cairo_status_t status; cairo_matrix_t p2u; + void *image_extra; - status = _cairo_pattern_acquire_surface ((cairo_pattern_t *)pattern, - (cairo_surface_t *)svg_surface, - 0, 0, (unsigned int)-1, (unsigned int)-1, - &surface, &surface_attr); - if (status) - return status; - - status = _cairo_surface_get_extents (surface, &extents); - + status = _cairo_surface_acquire_source_image (pattern->surface, + &image, &image_extra); if (status) return status; @@ -949,37 +939,36 @@ _cairo_svg_surface_emit_composite_image_pattern (cairo_output_stream_t *outp "patternUnits=\"userSpaceOnUse\" " "width=\"%d\" height=\"%d\"", pattern_id, - extents.width, extents.height); - _cairo_svg_surface_emit_transform (output, " patternTransform", ">\n", &p2u); + image->width, image->height); + emit_transform (output, " patternTransform", ">\n", &p2u); } _cairo_output_stream_printf (output, " width, image->height); if (pattern_id == invalid_pattern_id) - _cairo_svg_surface_emit_transform (output, " transform", "", &p2u); + emit_transform (output, " transform", "", &p2u); if (extra_attributes) _cairo_output_stream_printf (output, " %s", extra_attributes); _cairo_output_stream_printf (output, " xlink:href=\""); - status = _cairo_surface_base64_encode (surface, output); + status = _cairo_surface_base64_encode (pattern->surface, output); _cairo_output_stream_printf (output, "\"/>\n"); if (pattern_id != invalid_pattern_id) _cairo_output_stream_printf (output, "\n"); - _cairo_pattern_release_surface ((cairo_pattern_t *)pattern, - surface, &surface_attr); + _cairo_surface_release_source_image (pattern->surface, image, image_extra); return status; } static int -_cairo_svg_surface_emit_meta_surface (cairo_svg_document_t *document, +emit_meta_surface (cairo_svg_document_t *document, cairo_meta_surface_t *surface) { cairo_surface_t *paginated_surface; @@ -1021,7 +1010,7 @@ _cairo_svg_surface_emit_meta_surface (cairo_svg_document_t *document, _cairo_array_append (&document->meta_snapshots, &new_snapshot); if (meta->content == CAIRO_CONTENT_ALPHA) { - _cairo_svg_surface_emit_alpha_filter (document); + emit_alpha_filter (document); _cairo_output_stream_printf (document->xml_node_defs, "surface; - id = _cairo_svg_surface_emit_meta_surface (document, meta_surface); + id = emit_meta_surface (document, meta_surface); p2u = pattern->base.matrix; cairo_matrix_invert (&p2u); @@ -1092,7 +1081,7 @@ _cairo_svg_surface_emit_composite_meta_pattern (cairo_output_stream_t *output, pattern_id, meta_surface->width_pixels, meta_surface->height_pixels); - _cairo_svg_surface_emit_transform (output, " patternTransform", ">\n", &p2u); + emit_transform (output, " patternTransform", ">\n", &p2u); } _cairo_output_stream_printf (output, @@ -1100,7 +1089,7 @@ _cairo_svg_surface_emit_composite_meta_pattern (cairo_output_stream_t *output, id); if (pattern_id == invalid_pattern_id) - _cairo_svg_surface_emit_transform (output, " transform", "", &p2u); + emit_transform (output, " transform", "", &p2u); if (extra_attributes) _cairo_output_stream_printf (output, " %s", extra_attributes); @@ -1114,7 +1103,7 @@ _cairo_svg_surface_emit_composite_meta_pattern (cairo_output_stream_t *output, } static cairo_status_t -_cairo_svg_surface_emit_composite_pattern (cairo_output_stream_t *output, +emit_composite_pattern (cairo_output_stream_t *output, cairo_svg_surface_t *surface, cairo_surface_pattern_t *pattern, int pattern_id, @@ -1122,16 +1111,16 @@ _cairo_svg_surface_emit_composite_pattern (cairo_output_stream_t *output, { if (_cairo_surface_is_meta (pattern->surface)) { - return _cairo_svg_surface_emit_composite_meta_pattern (output, surface, pattern, + return emit_composite_meta_pattern (output, surface, pattern, pattern_id, extra_attributes); } - return _cairo_svg_surface_emit_composite_image_pattern (output, surface, pattern, + return emit_composite_image_pattern (output, surface, pattern, pattern_id, extra_attributes); } static void -_cairo_svg_surface_emit_operator (cairo_output_stream_t *output, +emit_operator (cairo_output_stream_t *output, cairo_svg_surface_t *surface, cairo_operator_t op) { @@ -1153,7 +1142,7 @@ _cairo_svg_surface_emit_operator (cairo_output_stream_t *output, } static void -_cairo_svg_surface_emit_solid_pattern (cairo_svg_surface_t *surface, +emit_solid_pattern (cairo_svg_surface_t *surface, cairo_solid_pattern_t *pattern, cairo_output_stream_t *style, cairo_bool_t is_stroke) @@ -1169,7 +1158,7 @@ _cairo_svg_surface_emit_solid_pattern (cairo_svg_surface_t *surface, } static void -_cairo_svg_surface_emit_surface_pattern (cairo_svg_surface_t *surface, +emit_surface_pattern (cairo_svg_surface_t *surface, cairo_surface_pattern_t *pattern, cairo_output_stream_t *style, cairo_bool_t is_stroke) @@ -1178,7 +1167,7 @@ _cairo_svg_surface_emit_surface_pattern (cairo_svg_surface_t *surface, int pattern_id; pattern_id = document->pattern_id++; - _cairo_svg_surface_emit_composite_pattern (document->xml_node_defs, surface, pattern, + emit_composite_pattern (document->xml_node_defs, surface, pattern, pattern_id, NULL); _cairo_output_stream_printf (style, @@ -1188,169 +1177,30 @@ _cairo_svg_surface_emit_surface_pattern (cairo_svg_surface_t *surface, } static void -_cairo_svg_surface_emit_pattern_stops (cairo_output_stream_t *output, +emit_pattern_stops (cairo_output_stream_t *output, cairo_gradient_pattern_t const *pattern, - double start_offset, - cairo_bool_t reverse_stops, - cairo_bool_t emulate_reflect) + double start_offset) { - pixman_gradient_stop_t *stops; double offset; - unsigned int n_stops; unsigned int i; - if (pattern->n_stops < 1) - return; - - if (pattern->n_stops == 1) { - _cairo_output_stream_printf (output, - "\n", - _cairo_fixed_to_double (pattern->stops[0].x), - pattern->stops[0].color.red / 655.35, - pattern->stops[0].color.green / 655.35, - pattern->stops[0].color.blue / 655.35, - pattern->stops[0].color.alpha / 65535.0); - return; - } - - if (emulate_reflect || reverse_stops) { - n_stops = emulate_reflect ? pattern->n_stops * 2 - 2: pattern->n_stops; - stops = malloc (sizeof (pixman_gradient_stop_t) * n_stops); - - for (i = 0; i < pattern->n_stops; i++) { - if (reverse_stops) { - stops[i] = pattern->stops[pattern->n_stops - i - 1]; - stops[i].x = _cairo_fixed_from_double (1.0 - _cairo_fixed_to_double (stops[i].x)); - } else - stops[i] = pattern->stops[i]; - if (emulate_reflect) { - stops[i].x /= 2; - if (i > 0 && i < (pattern->n_stops - 1)) { - if (reverse_stops) { - stops[i + pattern->n_stops - 1] = pattern->stops[i]; - stops[i + pattern->n_stops - 1].x = - _cairo_fixed_from_double (0.5 + 0.5 - * _cairo_fixed_to_double (stops[i + pattern->n_stops - 1].x)); - } else { - stops[i + pattern->n_stops - 1] = pattern->stops[pattern->n_stops - i - 1]; - stops[i + pattern->n_stops - 1].x = - _cairo_fixed_from_double (1 - 0.5 - * _cairo_fixed_to_double (stops [i + pattern->n_stops - 1].x)); - } - } - } - } - } else { - n_stops = pattern->n_stops; - stops = pattern->stops; - } - - if (start_offset >= 0.0) - for (i = 0; i < n_stops; i++) { - offset = start_offset + (1 - start_offset ) * - _cairo_fixed_to_double (stops[i].x); - _cairo_output_stream_printf (output, - "\n", - offset, - stops[i].color.red / 655.35, - stops[i].color.green / 655.35, - stops[i].color.blue / 655.35, - stops[i].color.alpha / 65535.0); - } - else { - cairo_bool_t found = FALSE; - unsigned int offset_index; - pixman_color_t offset_color_start, offset_color_stop; - - for (i = 0; i < n_stops; i++) { - if (_cairo_fixed_to_double (stops[i].x) >= -start_offset) { - if (i > 0) { - if (stops[i].x != stops[i-1].x) { - double x0, x1; - pixman_color_t *color0, *color1; - - x0 = _cairo_fixed_to_double (stops[i-1].x); - x1 = _cairo_fixed_to_double (stops[i].x); - color0 = &stops[i-1].color; - color1 = &stops[i].color; - offset_color_start.red = color0->red + (color1->red - color0->red) - * (-start_offset - x0) / (x1 - x0); - offset_color_start.green = color0->green + (color1->green - color0->green) - * (-start_offset - x0) / (x1 - x0); - offset_color_start.blue = color0->blue + (color1->blue - color0->blue) - * (-start_offset - x0) / (x1 - x0); - offset_color_start.alpha = color0->alpha + (color1->alpha - color0->alpha) - * (-start_offset - x0) / (x1 - x0); - offset_color_stop = offset_color_start; - } else { - offset_color_stop = stops[i-1].color; - offset_color_start = stops[i].color; - } - } else - offset_color_stop = offset_color_start = stops[i].color; - offset_index = i; - found = TRUE; - break; - } - } - - if (!found) { - offset_index = n_stops - 1; - offset_color_stop = offset_color_start = stops[offset_index].color; - } - + for (i = 0; i < pattern->n_stops; i++) { + offset = start_offset + (1 - start_offset ) * + _cairo_fixed_to_double (pattern->stops[i].x); _cairo_output_stream_printf (output, - "\n", - offset_color_start.red / 655.35, - offset_color_start.green / 655.35, - offset_color_start.blue / 655.35, - offset_color_start.alpha / 65535.0); - for (i = offset_index; i < n_stops; i++) { - _cairo_output_stream_printf (output, - "\n", - _cairo_fixed_to_double (stops[i].x) + start_offset, - stops[i].color.red / 655.35, - stops[i].color.green / 655.35, - stops[i].color.blue / 655.35, - stops[i].color.alpha / 65535.0); - } - for (i = 0; i < offset_index; i++) { - _cairo_output_stream_printf (output, - "\n", - 1.0 + _cairo_fixed_to_double (stops[i].x) + start_offset, - stops[i].color.red / 655.35, - stops[i].color.green / 655.35, - stops[i].color.blue / 655.35, - stops[i].color.alpha / 65535.0); - } - - _cairo_output_stream_printf (output, - "\n", - offset_color_stop.red / 655.35, - offset_color_stop.green / 655.35, - offset_color_stop.blue / 655.35, - offset_color_stop.alpha / 65535.0); - + offset, + pattern->stops[i].color.red / 655.35, + pattern->stops[i].color.green / 655.35, + pattern->stops[i].color.blue / 655.35, + pattern->stops[i].color.alpha / 65535.0); } - - if (reverse_stops || emulate_reflect) - free (stops); } static void -_cairo_svg_surface_emit_pattern_extend (cairo_output_stream_t *output, +emit_pattern_extend (cairo_output_stream_t *output, cairo_pattern_t *pattern) { switch (pattern->extend) { @@ -1361,13 +1211,15 @@ _cairo_svg_surface_emit_pattern_extend (cairo_output_stream_t *output, _cairo_output_stream_printf (output, "spreadMethod=\"reflect\" "); break; case CAIRO_EXTEND_NONE: + break; case CAIRO_EXTEND_PAD: + /* FIXME not implemented */ break; } } static void -_cairo_svg_surface_emit_linear_pattern (cairo_svg_surface_t *surface, +emit_linear_pattern (cairo_svg_surface_t *surface, cairo_linear_pattern_t *pattern, cairo_output_stream_t *style, cairo_bool_t is_stroke) @@ -1388,12 +1240,12 @@ _cairo_svg_surface_emit_linear_pattern (cairo_svg_surface_t *surface, document->linear_pattern_id, x0, y0, x1, y1); - _cairo_svg_surface_emit_pattern_extend (document->xml_node_defs, &pattern->base.base), + emit_pattern_extend (document->xml_node_defs, &pattern->base.base), p2u = pattern->base.base.matrix; cairo_matrix_invert (&p2u); - _cairo_svg_surface_emit_transform (document->xml_node_defs, "gradientTransform", ">\n", &p2u); + emit_transform (document->xml_node_defs, "gradientTransform", ">\n", &p2u); - _cairo_svg_surface_emit_pattern_stops (document->xml_node_defs ,&pattern->base, 0.0, FALSE, FALSE); + emit_pattern_stops (document->xml_node_defs ,&pattern->base, 0.0); _cairo_output_stream_printf (document->xml_node_defs, "\n"); @@ -1407,160 +1259,46 @@ _cairo_svg_surface_emit_linear_pattern (cairo_svg_surface_t *surface, } static void -_cairo_svg_surface_emit_radial_pattern (cairo_svg_surface_t *surface, +emit_radial_pattern (cairo_svg_surface_t *surface, cairo_radial_pattern_t *pattern, cairo_output_stream_t *style, cairo_bool_t is_stroke) { cairo_svg_document_t *document = surface->document; cairo_matrix_t p2u; - cairo_extend_t extend; double x0, y0, x1, y1, r0, r1; double fx, fy; - cairo_bool_t reverse_stops; - pixman_circle_t *c0, *c1; - extend = pattern->base.base.extend; + x0 = _cairo_fixed_to_double (pattern->gradient.inner.x); + y0 = _cairo_fixed_to_double (pattern->gradient.inner.y); + r0 = _cairo_fixed_to_double (pattern->gradient.inner.radius); + x1 = _cairo_fixed_to_double (pattern->gradient.outer.x); + y1 = _cairo_fixed_to_double (pattern->gradient.outer.y); + r1 = _cairo_fixed_to_double (pattern->gradient.outer.radius); - if (pattern->gradient.c1.radius < pattern->gradient.c2.radius) { - c0 = &pattern->gradient.c1; - c1 = &pattern->gradient.c2; - reverse_stops = FALSE; - } else { - c0 = &pattern->gradient.c2; - c1 = &pattern->gradient.c1; - reverse_stops = TRUE; - } + /* SVG doesn't have a start radius, so computing now SVG focal coordinates + * and emulating start radius by translating color stops. + * FIXME: We also need to emulate cairo behaviour inside start circle when + * extend != CAIRO_EXTEND_NONE. + * FIXME: Handle radius1 <= radius0 */ + fx = (r1 * x0 - r0 * x1) / (r1 - r0); + fy = (r1 * y0 - r0 * y1) / (r1 - r0); - x0 = _cairo_fixed_to_double (c0->x); - y0 = _cairo_fixed_to_double (c0->y); - r0 = _cairo_fixed_to_double (c0->radius); - x1 = _cairo_fixed_to_double (c1->x); - y1 = _cairo_fixed_to_double (c1->y); - r1 = _cairo_fixed_to_double (c1->radius); + _cairo_output_stream_printf (document->xml_node_defs, + "radial_pattern_id, + x1, y1, + fx, fy, r1); + emit_pattern_extend (document->xml_node_defs, &pattern->base.base), p2u = pattern->base.base.matrix; cairo_matrix_invert (&p2u); + emit_transform (document->xml_node_defs, "gradientTransform", ">\n", &p2u); - if (pattern->gradient.c1.radius == pattern->gradient.c2.radius) { - _cairo_output_stream_printf (document->xml_node_defs, - "radial_pattern_id, - x1, y1, - x1, y1, r1); - - _cairo_svg_surface_emit_transform (document->xml_node_defs, "gradientTransform", ">\n", &p2u); - - if (extend == CAIRO_EXTEND_NONE || - pattern->base.n_stops < 1) - _cairo_output_stream_printf (document->xml_node_defs, - "\n"); - else { - _cairo_output_stream_printf (document->xml_node_defs, - "\n", - pattern->base.stops[0].color.red / 655.35, - pattern->base.stops[0].color.green / 655.35, - pattern->base.stops[0].color.blue / 655.35, - pattern->base.stops[0].color.alpha / 65535.0); - if (pattern->base.n_stops > 1) - _cairo_output_stream_printf (document->xml_node_defs, - "\n", - pattern->base.stops[1].color.red / 655.35, - pattern->base.stops[1].color.green / 655.35, - pattern->base.stops[1].color.blue / 655.35, - pattern->base.stops[1].color.alpha / 65535.0); - } - - } else { - double offset, r, x, y; - cairo_bool_t emulate_reflect = FALSE; - - fx = (r1 * x0 - r0 * x1) / (r1 - r0); - fy = (r1 * y0 - r0 * y1) / (r1 - r0); - - /* SVG doesn't support the inner circle and use instead a gradient focal. - * That means we need to emulate the cairo behaviour by processing the - * cairo gradient stops. - * The CAIRO_EXTENT_NONE and CAIRO_EXTENT_PAD modes are quite easy to handle, - * it's just a matter of stop position translation and calculation of - * the corresponding SVG radial gradient focal. - * The CAIRO_EXTENT_REFLECT and CAIRO_EXTEND_REPEAT modes require to compute a new - * radial gradient, with an new outer circle, equal to r1 - r0 in the CAIRO_EXTEND_REPEAT - * case, and 2 * (r1 - r0) in the CAIRO_EXTENT_REFLECT case, and a new gradient stop - * list that maps to the original cairo stop list. - */ - if ((extend == CAIRO_EXTEND_REFLECT - || extend == CAIRO_EXTEND_REPEAT) - && r0 > 0.0) { - double r_org = r1; - - if (extend == CAIRO_EXTEND_REFLECT) { - r1 = 2 * r1 - r0; - emulate_reflect = TRUE; - } - - offset = fmod (r1, r1 - r0) / (r1 - r0) - 1.0; - r = r1 - r0; - - /* New position of outer circle. */ - x = r * (x1 - fx) / r_org + fx; - y = r * (y1 - fy) / r_org + fy; - - x1 = x; - y1 = y; - r1 = r; - r0 = 0.0; - } else { - offset = r0 / r1; - } - - _cairo_output_stream_printf (document->xml_node_defs, - "radial_pattern_id, - x1, y1, - fx, fy, r1); - - if (emulate_reflect) - _cairo_output_stream_printf (document->xml_node_defs, "spreadMethod=\"repeat\" "); - else - _cairo_svg_surface_emit_pattern_extend (document->xml_node_defs, &pattern->base.base); - _cairo_svg_surface_emit_transform (document->xml_node_defs, "gradientTransform", ">\n", &p2u); - - /* To support cairo's EXTEND_NONE, (for which SVG has no similar - * notion), we add transparent color stops on either end of the - * user-provided stops. */ - if (extend == CAIRO_EXTEND_NONE) { - _cairo_output_stream_printf (document->xml_node_defs, - "\n"); - if (r0 != 0.0) - _cairo_output_stream_printf (document->xml_node_defs, - "\n", - r0 / r1); - } - _cairo_svg_surface_emit_pattern_stops (document->xml_node_defs, &pattern->base, offset, - reverse_stops, emulate_reflect); - if (pattern->base.base.extend == CAIRO_EXTEND_NONE) - _cairo_output_stream_printf (document->xml_node_defs, - "\n"); - } + emit_pattern_stops (document->xml_node_defs, &pattern->base, r0 / r1); _cairo_output_stream_printf (document->xml_node_defs, "\n"); @@ -1574,24 +1312,24 @@ _cairo_svg_surface_emit_radial_pattern (cairo_svg_surface_t *surface, } static void -_cairo_svg_surface_emit_pattern (cairo_svg_surface_t *surface, cairo_pattern_t *pattern, +emit_pattern (cairo_svg_surface_t *surface, cairo_pattern_t *pattern, cairo_output_stream_t *output, cairo_bool_t is_stroke) { switch (pattern->type) { case CAIRO_PATTERN_TYPE_SOLID: - _cairo_svg_surface_emit_solid_pattern (surface, (cairo_solid_pattern_t *) pattern, output, is_stroke); + emit_solid_pattern (surface, (cairo_solid_pattern_t *) pattern, output, is_stroke); break; case CAIRO_PATTERN_TYPE_SURFACE: - _cairo_svg_surface_emit_surface_pattern (surface, (cairo_surface_pattern_t *) pattern, output, is_stroke); + emit_surface_pattern (surface, (cairo_surface_pattern_t *) pattern, output, is_stroke); break; case CAIRO_PATTERN_TYPE_LINEAR: - _cairo_svg_surface_emit_linear_pattern (surface, (cairo_linear_pattern_t *) pattern, output, is_stroke); + emit_linear_pattern (surface, (cairo_linear_pattern_t *) pattern, output, is_stroke); break; case CAIRO_PATTERN_TYPE_RADIAL: - _cairo_svg_surface_emit_radial_pattern (surface, (cairo_radial_pattern_t *) pattern, output, is_stroke); + emit_radial_pattern (surface, (cairo_radial_pattern_t *) pattern, output, is_stroke); break; } } @@ -1609,20 +1347,20 @@ _cairo_svg_surface_fill (void *abstract_surface, cairo_status_t status; if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE) - return _cairo_svg_surface_analyze_operation (surface, op, source); + return _analyze_operation (surface, op, source); - assert (__cairo_svg_surface_operation_supported (surface, op, source)); + assert (_operation_supported (surface, op, source)); _cairo_output_stream_printf (surface->xml_node, "xml_node, surface, op); - _cairo_svg_surface_emit_pattern (surface, source, surface->xml_node, FALSE); + emit_operator (surface->xml_node, surface, op); + emit_pattern (surface, source, surface->xml_node, FALSE); _cairo_output_stream_printf (surface->xml_node, "\" "); - status = _cairo_svg_surface_emit_path (surface->xml_node, path, NULL); + status = emit_path (surface->xml_node, path, NULL); _cairo_output_stream_printf (surface->xml_node, "/>\n"); @@ -1649,7 +1387,7 @@ _cairo_svg_surface_get_extents (void *abstract_surface, } static cairo_status_t -_cairo_svg_surface_emit_paint (cairo_output_stream_t *output, +emit_paint (cairo_output_stream_t *output, cairo_svg_surface_t *surface, cairo_operator_t op, cairo_pattern_t *source, @@ -1657,7 +1395,7 @@ _cairo_svg_surface_emit_paint (cairo_output_stream_t *output, { if (source->type == CAIRO_PATTERN_TYPE_SURFACE && source->extend == CAIRO_EXTEND_NONE) - return _cairo_svg_surface_emit_composite_pattern (output, + return emit_composite_pattern (output, surface, (cairo_surface_pattern_t *) source, invalid_pattern_id, @@ -1668,8 +1406,8 @@ _cairo_svg_surface_emit_paint (cairo_output_stream_t *output, "width=\"%f\" height=\"%f\" " "style=\"", surface->width, surface->height); - _cairo_svg_surface_emit_operator (output, surface, op); - _cairo_svg_surface_emit_pattern (surface, source, output, FALSE); + emit_operator (output, surface, op); + emit_pattern (surface, source, output, FALSE); _cairo_output_stream_printf (output, " stroke: none;\""); if (extra_attributes) @@ -1689,7 +1427,7 @@ _cairo_svg_surface_paint (void *abstract_surface, cairo_svg_surface_t *surface = abstract_surface; if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE) - return _cairo_svg_surface_analyze_operation (surface, op, source); + return _analyze_operation (surface, op, source); /* XXX: It would be nice to be able to assert this condition * here. But, we actually allow one 'cheat' that is used when @@ -1698,7 +1436,7 @@ _cairo_svg_surface_paint (void *abstract_surface, * possible only because there is nothing between the fallback * images and the paper, nor is anything painted above. */ /* - assert (__cairo_svg_surface_operation_supported (surface, op, source)); + assert (_operation_supported (surface, op, source)); */ /* Emulation of clear and source operators, when no clipping region @@ -1729,7 +1467,7 @@ _cairo_svg_surface_paint (void *abstract_surface, } } - _cairo_svg_surface_emit_paint (surface->xml_node, surface, op, source, NULL); + emit_paint (surface->xml_node, surface, op, source, NULL); return CAIRO_STATUS_SUCCESS; } @@ -1746,13 +1484,13 @@ _cairo_svg_surface_mask (void *abstract_surface, char buffer[64]; if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE) - return _cairo_svg_surface_analyze_operation (surface, op, source); + return _analyze_operation (surface, op, source); - assert (__cairo_svg_surface_operation_supported (surface, op, source)); + assert (_operation_supported (surface, op, source)); - _cairo_svg_surface_emit_alpha_filter (document); + emit_alpha_filter (document); - /* _cairo_svg_surface_emit_paint() will output a pattern definition to + /* emit_paint() will output a pattern definition to * document->xml_node_defs so we need to write the mask element to * a temporary stream and then copy that to xml_node_defs. */ mask_stream = _cairo_memory_stream_create (); @@ -1760,7 +1498,7 @@ _cairo_svg_surface_mask (void *abstract_surface, "\n" " \n", document->mask_id); - _cairo_svg_surface_emit_paint (mask_stream, surface, op, mask, NULL); + emit_paint (mask_stream, surface, op, mask, NULL); _cairo_output_stream_printf (mask_stream, " \n" "\n"); @@ -1769,7 +1507,7 @@ _cairo_svg_surface_mask (void *abstract_surface, snprintf (buffer, sizeof buffer, "mask=\"url(#mask%d);\"", document->mask_id); - _cairo_svg_surface_emit_paint (surface->xml_node, surface, op, source, buffer); + emit_paint (surface->xml_node, surface, op, source, buffer); document->mask_id++; @@ -1793,9 +1531,9 @@ _cairo_svg_surface_stroke (void *abstract_dst, unsigned int i; if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE) - return _cairo_svg_surface_analyze_operation (surface, op, source); + return _analyze_operation (surface, op, source); - assert (__cairo_svg_surface_operation_supported (surface, op, source)); + assert (_operation_supported (surface, op, source)); switch (stroke_style->line_cap) { case CAIRO_LINE_CAP_BUTT: @@ -1834,8 +1572,8 @@ _cairo_svg_surface_stroke (void *abstract_dst, line_cap, line_join); - _cairo_svg_surface_emit_pattern (surface, source, surface->xml_node, TRUE); - _cairo_svg_surface_emit_operator (surface->xml_node, surface, op); + emit_pattern (surface, source, surface->xml_node, TRUE); + emit_operator (surface->xml_node, surface, op); if (stroke_style->num_dashes > 0) { _cairo_output_stream_printf (surface->xml_node, "stroke-dasharray: "); @@ -1858,9 +1596,9 @@ _cairo_svg_surface_stroke (void *abstract_dst, "stroke-miterlimit: %f;\" ", stroke_style->miter_limit); - status = _cairo_svg_surface_emit_path (surface->xml_node, path, ctm_inverse); + status = emit_path (surface->xml_node, path, ctm_inverse); - _cairo_svg_surface_emit_transform (surface->xml_node, " transform", "/>\n", ctm); + emit_transform (surface->xml_node, " transform", "/>\n", ctm); return status; } @@ -1881,9 +1619,9 @@ _cairo_svg_surface_show_glyphs (void *abstract_surface, int i; if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE) - return _cairo_svg_surface_analyze_operation (surface, op, pattern); + return _analyze_operation (surface, op, pattern); - assert (__cairo_svg_surface_operation_supported (surface, op, pattern)); + assert (_operation_supported (surface, op, pattern)); if (num_glyphs <= 0) return CAIRO_STATUS_SUCCESS; @@ -1895,7 +1633,7 @@ _cairo_svg_surface_show_glyphs (void *abstract_surface, goto FALLBACK; _cairo_output_stream_printf (surface->xml_node, "xml_node, FALSE); + emit_pattern (surface, pattern, surface->xml_node, FALSE); _cairo_output_stream_printf (surface->xml_node, "\">\n"); for (i = 0; i < num_glyphs; i++) { @@ -1960,7 +1698,7 @@ _cairo_svg_surface_intersect_clip_path (void *dst, "\n" " clip_id); - status = _cairo_svg_surface_emit_path (document->xml_node_defs, path, NULL); + status = emit_path (document->xml_node_defs, path, NULL); _cairo_output_stream_printf (document->xml_node_defs, "/>\n" "\n"); @@ -2034,7 +1772,7 @@ _cairo_svg_document_create (cairo_output_stream_t *output_stream, } /* The use of defs for font glyphs imposes no per-subset limit. */ - document->font_subsets = _cairo_scaled_font_subsets_create (0, INT_MAX); + document->font_subsets = _cairo_scaled_font_subsets_create (0); if (document->font_subsets == NULL) { _cairo_error (CAIRO_STATUS_NO_MEMORY); free (document); diff --git a/gfx/cairo/cairo/src/cairo-traps.c b/gfx/cairo/cairo/src/cairo-traps.c index dd5837bf5de..9b3931fce16 100644 --- a/gfx/cairo/cairo/src/cairo-traps.c +++ b/gfx/cairo/cairo/src/cairo-traps.c @@ -1,6 +1,5 @@ /* * Copyright © 2002 Keith Packard - * Copyright © 2007 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 @@ -41,7 +40,7 @@ /* private functions */ static cairo_status_t -_cairo_traps_grow (cairo_traps_t *traps); +_cairo_traps_grow_by (cairo_traps_t *traps, int additional); static cairo_status_t _cairo_traps_add_trap (cairo_traps_t *traps, cairo_fixed_t top, cairo_fixed_t bottom, @@ -50,6 +49,18 @@ _cairo_traps_add_trap (cairo_traps_t *traps, cairo_fixed_t top, cairo_fixed_t bo static int _compare_point_fixed_by_y (const void *av, const void *bv); +static int +_compare_cairo_edge_by_top (const void *av, const void *bv); + +static int +_compare_cairo_edge_by_slope (const void *av, const void *bv); + +static cairo_fixed_16_16_t +_compute_x (cairo_line_t *line, cairo_fixed_t y); + +static int +_line_segs_intersect_ceil (cairo_line_t *left, cairo_line_t *right, cairo_fixed_t *y_ret); + void _cairo_traps_init (cairo_traps_t *traps) { @@ -59,19 +70,19 @@ _cairo_traps_init (cairo_traps_t *traps) traps->traps_size = 0; traps->traps = NULL; - traps->extents.p1.x = traps->extents.p1.y = INT32_MAX; - traps->extents.p2.x = traps->extents.p2.y = INT32_MIN; + traps->extents.p1.x = traps->extents.p1.y = INT16_MAX << 16; + traps->extents.p2.x = traps->extents.p2.y = INT16_MIN << 16; } void _cairo_traps_fini (cairo_traps_t *traps) { - if (traps->traps && traps->traps != traps->traps_embedded) + if (traps->traps_size) { free (traps->traps); - - traps->traps = NULL; - traps->traps_size = 0; - traps->num_traps = 0; + traps->traps = NULL; + traps->traps_size = 0; + traps->num_traps = 0; + } } /** @@ -89,7 +100,7 @@ _cairo_traps_init_box (cairo_traps_t *traps, { _cairo_traps_init (traps); - traps->status = _cairo_traps_grow (traps); + traps->status = _cairo_traps_grow_by (traps, 1); if (traps->status) return traps->status; @@ -123,7 +134,8 @@ _cairo_traps_add_trap (cairo_traps_t *traps, cairo_fixed_t top, cairo_fixed_t bo } if (traps->num_traps >= traps->traps_size) { - traps->status = _cairo_traps_grow (traps); + int inc = traps->traps_size ? traps->traps_size : 32; + traps->status = _cairo_traps_grow_by (traps, inc); if (traps->status) return traps->status; } @@ -181,43 +193,29 @@ _cairo_traps_add_trap_from_points (cairo_traps_t *traps, cairo_fixed_t top, cair return _cairo_traps_add_trap (traps, top, bottom, &left, &right); } -/* make room for at least one more trap */ static cairo_status_t -_cairo_traps_grow (cairo_traps_t *traps) +_cairo_traps_grow_by (cairo_traps_t *traps, int additional) { cairo_trapezoid_t *new_traps; int old_size = traps->traps_size; - int embedded_size = sizeof (traps->traps_embedded) / sizeof (traps->traps_embedded[0]); - int new_size = 2 * MAX (old_size, 16); - - /* we have a local buffer at traps->traps_embedded. try to fulfill the request - * from there. */ - if (old_size < embedded_size) { - traps->traps = traps->traps_embedded; - traps->traps_size = embedded_size; - return traps->status; - } - - assert (traps->num_traps <= traps->traps_size); + int new_size = traps->num_traps + additional; if (traps->status) return traps->status; - if (traps->traps == traps->traps_embedded) { - new_traps = malloc (new_size * sizeof (cairo_trapezoid_t)); - if (new_traps) - memcpy (new_traps, traps->traps, old_size * sizeof (cairo_trapezoid_t)); - } else { - new_traps = realloc (traps->traps, new_size * sizeof (cairo_trapezoid_t)); - } + if (new_size <= traps->traps_size) + return traps->status; + + traps->traps_size = new_size; + new_traps = realloc (traps->traps, traps->traps_size * sizeof (cairo_trapezoid_t)); if (new_traps == NULL) { + traps->traps_size = old_size; traps->status = CAIRO_STATUS_NO_MEMORY; return traps->status; } traps->traps = new_traps; - traps->traps_size = new_size; return traps->status; } @@ -311,20 +309,57 @@ _cairo_trapezoid_array_translate_and_scale (cairo_trapezoid_t *offset_traps, } } -/* A triangle is simply a degenerate case of a convex - * quadrilateral. We would not benefit from having any distinct - * implementation of triangle vs. quadrilateral tessellation here. */ cairo_status_t _cairo_traps_tessellate_triangle (cairo_traps_t *traps, cairo_point_t t[3]) { - cairo_point_t quad[4]; + cairo_line_t line; + cairo_fixed_16_16_t intersect; + cairo_point_t tsort[3]; - quad[0] = t[0]; - quad[1] = t[0]; - quad[2] = t[1]; - quad[3] = t[2]; + memcpy (tsort, t, 3 * sizeof (cairo_point_t)); + qsort (tsort, 3, sizeof (cairo_point_t), _compare_point_fixed_by_y); - return _cairo_traps_tessellate_convex_quad (traps, quad); + /* horizontal top edge requires special handling */ + if (tsort[0].y == tsort[1].y) { + if (tsort[0].x < tsort[1].x) + _cairo_traps_add_trap_from_points (traps, + tsort[1].y, tsort[2].y, + tsort[0], tsort[2], + tsort[1], tsort[2]); + else + _cairo_traps_add_trap_from_points (traps, + tsort[1].y, tsort[2].y, + tsort[1], tsort[2], + tsort[0], tsort[2]); + return traps->status; + } + + line.p1 = tsort[0]; + line.p2 = tsort[1]; + + intersect = _compute_x (&line, tsort[2].y); + + if (intersect < tsort[2].x) { + _cairo_traps_add_trap_from_points (traps, + tsort[0].y, tsort[1].y, + tsort[0], tsort[1], + tsort[0], tsort[2]); + _cairo_traps_add_trap_from_points (traps, + tsort[1].y, tsort[2].y, + tsort[1], tsort[2], + tsort[0], tsort[2]); + } else { + _cairo_traps_add_trap_from_points (traps, + tsort[0].y, tsort[1].y, + tsort[0], tsort[2], + tsort[0], tsort[1]); + _cairo_traps_add_trap_from_points (traps, + tsort[1].y, tsort[2].y, + tsort[0], tsort[2], + tsort[1], tsort[2]); + } + + return traps->status; } cairo_status_t @@ -332,8 +367,6 @@ _cairo_traps_tessellate_convex_quad (cairo_traps_t *traps, cairo_point_t q[4]) { int a, b, c, d; int i; - cairo_slope_t ab, ad; - cairo_bool_t b_left_of_d; /* Choose a as a point with minimal y */ a = 0; @@ -353,50 +386,24 @@ _cairo_traps_tessellate_convex_quad (cairo_traps_t *traps, cairo_point_t q[4]) } /* Without freedom left to choose anything else, we have four - * cases to tessellate. - * - * First, we have to determine the Y-axis sort of the four - * vertices, (either abcd or abdc). After that we need to detemine - * which edges will be "left" and which will be "right" in the - * resulting trapezoids. This can be determined by computing a - * slope comparison of ab and ad to determine if b is left of d or - * not. - * - * Note that "left of" here is in the sense of which edges should - * be the left vs. right edges of the trapezoid. In particular, b - * left of d does *not* mean that b.x is less than d.x. - * - * This should hopefully be made clear in the lame ASCII art - * below. Since the same slope comparison is used in all cases, we - * compute it before testing for the Y-value sort. */ - - /* Note: If a == b then the ab slope doesn't give us any - * information. In that case, we can replace it with the ac (or - * equivalenly the bc) slope which gives us exactly the same - * information we need. At worst the names of the identifiers ab - * and b_left_of_d are inaccurate in this case, (would be ac, and - * c_left_of_d). */ - if (q[a].x == q[b].x && q[a].y == q[b].y) - _cairo_slope_init (&ab, &q[a], &q[c]); - else - _cairo_slope_init (&ab, &q[a], &q[b]); - - _cairo_slope_init (&ad, &q[a], &q[d]); - - b_left_of_d = (_cairo_slope_compare (&ab, &ad) > 0); - - if (q[c].y <= q[d].y) { - if (b_left_of_d) { - /* Y-sort is abcd and b is left of d, (slope(ab) > slope (ad)) + * cases to tessellate which we can distinguish by comparing c.y + * to d.y and then by comparing b.x to d.x. And then for any of + * these cases there is a trivial way to emit three + * trapezoids. The 4 cases and their trapezoids are described and + * implemented below: + */ + if (q[c].y < q[d].y) { + if (q[b].x < q[d].x) { + /* c.y < d.y && b.x < d.x * - * top bot left right - * _a a a - * / / /| |\ a.y b.y ab ad - * b / b | b \ - * / / | | \ \ b.y c.y bc ad - * c / c | c \ - * | / \| \ \ c.y d.y cd ad - * d d d + * top bot left right + * a + * / | a.y b.y ab ad + * b | + * | | b.y c.y bc ad + * c | + * \ | c.y d.y cd ad + * d */ _cairo_traps_add_trap_from_points (traps, q[a].y, q[b].y, @@ -408,15 +415,15 @@ _cairo_traps_tessellate_convex_quad (cairo_traps_t *traps, cairo_point_t q[4]) q[c].y, q[d].y, q[c], q[d], q[a], q[d]); } else { - /* Y-sort is abcd and b is right of d, (slope(ab) <= slope (ad)) + /* c.y < d.y && b.x >= d.x * - * a a a_ - * /| |\ \ \ a.y b.y ad ab - * / b | b \ b - * / / | | \ \ b.y c.y ad bc - * / c | c \ c - * / / |/ \ | c.y d.y ad cd - * d d d + * a + * | \ a.y b.y ad ab + * | b + * | | b.y c.y ad bc + * | c + * | / c.y d.y ad cd + * d */ _cairo_traps_add_trap_from_points (traps, q[a].y, q[b].y, @@ -429,16 +436,16 @@ _cairo_traps_tessellate_convex_quad (cairo_traps_t *traps, cairo_point_t q[4]) q[a], q[d], q[c], q[d]); } } else { - if (b_left_of_d) { - /* Y-sort is abdc and b is left of d, (slope (ab) > slope (ad)) + if (q[b].x < q[d].x) { + /* c.y >= d.y && b.x < d.x * - * a a a - * // / \ |\ a.y b.y ab ad - * /b/ b \ b \ - * / / \ \ \ \ b.y d.y bc ad - * /d/ \ d \ d - * // \ / \| d.y c.y bc dc - * c c c + * a + * / \ a.y b.y ab ad + * b \ + * \ \ b.y d.y bc ad + * \ d + * \ / d.y c.y bc dc + * c */ _cairo_traps_add_trap_from_points (traps, q[a].y, q[b].y, @@ -450,15 +457,15 @@ _cairo_traps_tessellate_convex_quad (cairo_traps_t *traps, cairo_point_t q[4]) q[d].y, q[c].y, q[b], q[c], q[d], q[c]); } else { - /* Y-sort is abdc and b is right of d, (slope (ab) <= slope (ad)) + /* c.y >= d.y && b.x >= d.x * - * a a a - * /| / \ \\ a.y b.y ad ab - * / b / b \b\ - * / / / / \ \ b.y d.y ad bc - * d / d / \d\ - * |/ \ / \\ d.y c.y dc bc - * c c c + * a + * / \ a.y b.y ad ab + * / b + * / / b.y d.y ad bc + * d / + * \ / d.y c.y dc bc + * c */ _cairo_traps_add_trap_from_points (traps, q[a].y, q[b].y, @@ -475,6 +482,400 @@ _cairo_traps_tessellate_convex_quad (cairo_traps_t *traps, cairo_point_t q[4]) return traps->status; } +static int +_compare_cairo_edge_by_top (const void *av, const void *bv) +{ + const cairo_edge_t *a = av, *b = bv; + + return a->edge.p1.y - b->edge.p1.y; +} + +/* Return value is: + > 0 if a is "clockwise" from b, (in a mathematical, not a graphical sense) + == 0 if slope (a) == slope (b) + < 0 if a is "counter-clockwise" from b +*/ +static int +_compare_cairo_edge_by_slope (const void *av, const void *bv) +{ + const cairo_edge_t *a = av, *b = bv; + cairo_fixed_32_32_t d; + + cairo_fixed_48_16_t a_dx = a->edge.p2.x - a->edge.p1.x; + cairo_fixed_48_16_t a_dy = a->edge.p2.y - a->edge.p1.y; + cairo_fixed_48_16_t b_dx = b->edge.p2.x - b->edge.p1.x; + cairo_fixed_48_16_t b_dy = b->edge.p2.y - b->edge.p1.y; + + d = b_dy * a_dx - a_dy * b_dx; + + if (d > 0) + return 1; + else if (d == 0) + return 0; + else + return -1; +} + +static int +_compare_cairo_edge_by_current_x_slope (const void *av, const void *bv) +{ + const cairo_edge_t *a = av, *b = bv; + int ret; + + ret = a->current_x - b->current_x; + if (ret == 0) + ret = _compare_cairo_edge_by_slope (a, b); + return ret; +} + +/* XXX: Both _compute_x and _compute_inverse_slope will divide by zero + for horizontal lines. Now, we "know" that when we are tessellating + polygons that the polygon data structure discards all horizontal + edges, but there's nothing here to guarantee that. I suggest the + following: + + A) Move all of the polygon tessellation code out of xrtraps.c and + into xrpoly.c, (in order to be in the same module as the code + discarding horizontal lines). + + OR + + B) Re-implement the line intersection in a way that avoids all + division by zero. Here's one approach. The only disadvantage + might be that that there are not meaningful names for all of the + sub-computations -- just a bunch of determinants. I haven't + looked at complexity, (both are probably similar and it probably + doesn't matter much anyway). + */ + +/* XXX: Keith's new intersection code is much cleaner, and uses + * sufficient precision for correctly sorting intersections according + * to the analysis in Hobby's paper. + * + * But, when we enable this code, some things are failing, (eg. the + * stars in test/fill_rule get filled wrong). This could indicate a + * bug in one of tree places: + * + * 1) The new intersection code in this file + * + * 2) cairo_wideint.c (which is only exercised here) + * + * 3) In the current tessellator, (where the old intersection + * code, with its mystic increments could be masking the bug). + * + * It will likely be easier to revisit this when the new tessellation + * code is in place. So, for now, we'll simply disable the new + * intersection code. + */ + +#define CAIRO_TRAPS_USE_NEW_INTERSECTION_CODE 0 + +#if CAIRO_TRAPS_USE_NEW_INTERSECTION_CODE +static const cairo_fixed_32_32_t +_det16_32 (cairo_fixed_16_16_t a, + cairo_fixed_16_16_t b, + cairo_fixed_16_16_t c, + cairo_fixed_16_16_t d) +{ + return _cairo_int64_sub (_cairo_int32x32_64_mul (a, d), + _cairo_int32x32_64_mul (b, c)); +} + +static const cairo_fixed_64_64_t +_det32_64 (cairo_fixed_32_32_t a, + cairo_fixed_32_32_t b, + cairo_fixed_32_32_t c, + cairo_fixed_32_32_t d) +{ + return _cairo_int128_sub (_cairo_int64x64_128_mul (a, d), + _cairo_int64x64_128_mul (b, c)); +} + +static const cairo_fixed_32_32_t +_fixed_16_16_to_fixed_32_32 (cairo_fixed_16_16_t a) +{ + return _cairo_int64_lsl (_cairo_int32_to_int64 (a), 16); +} + +static int +_line_segs_intersect_ceil (cairo_line_t *l1, cairo_line_t *l2, cairo_fixed_t *y_intersection) +{ + cairo_fixed_16_16_t dx1, dx2, dy1, dy2; + cairo_fixed_32_32_t den_det; + cairo_fixed_32_32_t l1_det, l2_det; + cairo_fixed_64_64_t num_det; + cairo_fixed_32_32_t intersect_32_32; + cairo_fixed_48_16_t intersect_48_16; + cairo_fixed_16_16_t intersect_16_16; + cairo_quorem128_t qr; + + dx1 = l1->p1.x - l1->p2.x; + dy1 = l1->p1.y - l1->p2.y; + dx2 = l2->p1.x - l2->p2.x; + dy2 = l2->p1.y - l2->p2.y; + den_det = _det16_32 (dx1, dy1, + dx2, dy2); + + if (_cairo_int64_eq (den_det, _cairo_int32_to_int64(0))) + return 0; + + l1_det = _det16_32 (l1->p1.x, l1->p1.y, + l1->p2.x, l1->p2.y); + l2_det = _det16_32 (l2->p1.x, l2->p1.y, + l2->p2.x, l2->p2.y); + + num_det = _det32_64 (l1_det, _fixed_16_16_to_fixed_32_32 (dy1), + l2_det, _fixed_16_16_to_fixed_32_32 (dy2)); + + /* + * Ok, this one is a bit tricky in fixed point, the denominator + * needs to be left with 32-bits of fraction so that the + * result of the divide ends up with 32-bits of fraction (64 - 32 = 32) + */ + qr = _cairo_int128_divrem (num_det, _cairo_int64_to_int128 (den_det)); + + intersect_32_32 = _cairo_int128_to_int64 (qr.quo); + + /* + * Find the ceiling of the quotient -- divrem returns + * the quotient truncated towards zero, so if the + * quotient should be positive (num_den and den_det have same sign) + * bump the quotient up by one. + */ + + if (_cairo_int128_ne (qr.rem, _cairo_int32_to_int128 (0)) && + (_cairo_int128_ge (num_det, _cairo_int32_to_int128 (0)) == + _cairo_int64_ge (den_det, _cairo_int32_to_int64 (0)))) + { + intersect_32_32 = _cairo_int64_add (intersect_32_32, + _cairo_int32_to_int64 (1)); + } + + /* + * Now convert from 32.32 to 48.16 and take the ceiling; + * this requires adding in 15 1 bits and shifting the result + */ + + intersect_32_32 = _cairo_int64_add (intersect_32_32, + _cairo_int32_to_int64 ((1 << 16) - 1)); + intersect_48_16 = _cairo_int64_rsa (intersect_32_32, 16); + + /* + * And drop the top bits + */ + intersect_16_16 = _cairo_int64_to_int32 (intersect_48_16); + + *y_intersection = intersect_16_16; + + return 1; +} +#endif /* CAIRO_TRAPS_USE_NEW_INTERSECTION_CODE */ + +static cairo_fixed_16_16_t +_compute_x (cairo_line_t *line, cairo_fixed_t y) +{ + cairo_fixed_16_16_t dx = line->p2.x - line->p1.x; + cairo_fixed_32_32_t ex = (cairo_fixed_48_16_t) (y - line->p1.y) * (cairo_fixed_48_16_t) dx; + cairo_fixed_16_16_t dy = line->p2.y - line->p1.y; + + return line->p1.x + (ex / dy); +} + +#if ! CAIRO_TRAPS_USE_NEW_INTERSECTION_CODE +static double +_compute_inverse_slope (cairo_line_t *l) +{ + return (_cairo_fixed_to_double (l->p2.x - l->p1.x) / + _cairo_fixed_to_double (l->p2.y - l->p1.y)); +} + +static double +_compute_x_intercept (cairo_line_t *l, double inverse_slope) +{ + return _cairo_fixed_to_double (l->p1.x) - inverse_slope * _cairo_fixed_to_double (l->p1.y); +} + +static int +_line_segs_intersect_ceil (cairo_line_t *l1, cairo_line_t *l2, cairo_fixed_t *y_ret) +{ + /* + * x = m1y + b1 + * x = m2y + b2 + * m1y + b1 = m2y + b2 + * y * (m1 - m2) = b2 - b1 + * y = (b2 - b1) / (m1 - m2) + */ + cairo_fixed_16_16_t y_intersect; + double m1 = _compute_inverse_slope (l1); + double b1 = _compute_x_intercept (l1, m1); + double m2 = _compute_inverse_slope (l2); + double b2 = _compute_x_intercept (l2, m2); + + if (m1 == m2) + return 0; + + y_intersect = _cairo_fixed_from_double ((b2 - b1) / (m1 - m2)); + + if (m1 < m2) { + cairo_line_t *t; + t = l1; + l1 = l2; + l2 = t; + } + + /* Assuming 56 bits of floating point precision, the intersection + is accurate within one sub-pixel coordinate. We must ensure + that we return a value that is at or after the intersection. At + most, we must increment once. */ + if (_compute_x (l2, y_intersect) > _compute_x (l1, y_intersect)) + y_intersect++; + /* XXX: Hmm... Keith's error calculations said we'd at most be off + by one sub-pixel. But, I found that the paint-fill-BE-01.svg + test from the W3C SVG conformance suite definitely requires two + increments. + + It could be that we need one to overcome the error, and another + to round up. + + It would be nice to be sure this code is correct, (but we can't + do the while loop as it will work for way to long on + exceedingly distant intersections with large errors that we + really don't care about anyway as they will be ignored by the + calling function. + */ + if (_compute_x (l2, y_intersect) > _compute_x (l1, y_intersect)) + y_intersect++; + /* XXX: hmm... now I found "intersection_killer" inside xrspline.c + that requires 3 increments. Clearly, we haven't characterized + this completely yet. */ + if (_compute_x (l2, y_intersect) > _compute_x (l1, y_intersect)) + y_intersect++; + /* I think I've found the answer to our problems. The insight is + that everytime we round we are changing the slopes of the + relevant lines, so we may be introducing new intersections that + we miss, so everything breaks apart. John Hobby wrote a paper + on how to fix this: + + [Hobby93c] John D. Hobby, Practical Segment Intersection with + Finite Precision Output, Computation Geometry Theory and + Applications, 13(4), 1999. + + Available online (2003-08017): + + http://cm.bell-labs.com/cm/cs/doc/93/2-27.ps.gz + + Now we just need to go off and implement that. + */ + + *y_ret = y_intersect; + + return 1; +} +#endif /* CAIRO_TRAPS_USE_NEW_INTERSECTION_CODE */ + +/* The algorithm here is pretty simple: + + inactive = [edges] + y = min_p1_y (inactive) + + while (num_active || num_inactive) { + active = all edges containing y + + next_y = min ( min_p2_y (active), min_p1_y (inactive), min_intersection (active) ) + + fill_traps (active, y, next_y, fill_rule) + + y = next_y + } + + The invariants that hold during fill_traps are: + + All edges in active contain both y and next_y + No edges in active intersect within y and next_y + + These invariants mean that fill_traps is as simple as sorting the + active edges, forming a trapezoid between each adjacent pair. Then, + either the even-odd or winding rule is used to determine whether to + emit each of these trapezoids. + + Warning: This function obliterates the edges of the polygon provided. +*/ +cairo_status_t +_cairo_traps_tessellate_polygon (cairo_traps_t *traps, + cairo_polygon_t *poly, + cairo_fill_rule_t fill_rule) +{ + int i, active, inactive; + cairo_fixed_t y, y_next, intersect; + int in_out, num_edges = poly->num_edges; + cairo_edge_t *edges = poly->edges; + + if (num_edges == 0) + return CAIRO_STATUS_SUCCESS; + + qsort (edges, num_edges, sizeof (cairo_edge_t), _compare_cairo_edge_by_top); + + y = edges[0].edge.p1.y; + active = 0; + inactive = 0; + while (active < num_edges) { + while (inactive < num_edges && edges[inactive].edge.p1.y <= y) + inactive++; + + for (i = active; i < inactive; i++) + edges[i].current_x = _compute_x (&edges[i].edge, y); + + qsort (&edges[active], inactive - active, + sizeof (cairo_edge_t), _compare_cairo_edge_by_current_x_slope); + + /* find next inflection point */ + y_next = edges[active].edge.p2.y; + + for (i = active; i < inactive; i++) { + if (edges[i].edge.p2.y < y_next) + y_next = edges[i].edge.p2.y; + /* check intersect */ + if (i != inactive - 1 && edges[i].current_x != edges[i+1].current_x) + if (_line_segs_intersect_ceil (&edges[i].edge, &edges[i+1].edge, + &intersect)) + if (intersect > y && intersect < y_next) + y_next = intersect; + } + /* check next inactive point */ + if (inactive < num_edges && edges[inactive].edge.p1.y < y_next) + y_next = edges[inactive].edge.p1.y; + + /* walk the active edges generating trapezoids */ + in_out = 0; + for (i = active; i < inactive - 1; i++) { + if (fill_rule == CAIRO_FILL_RULE_WINDING) { + if (edges[i].clockWise) + in_out++; + else + in_out--; + if (in_out == 0) + continue; + } else { + in_out++; + if ((in_out & 1) == 0) + continue; + } + _cairo_traps_add_trap (traps, y, y_next, &edges[i].edge, &edges[i+1].edge); + } + + /* delete inactive edges */ + for (i = active; i < inactive; i++) { + if (edges[i].edge.p2.y <= y_next) { + memmove (&edges[active+1], &edges[active], (i - active) * sizeof (cairo_edge_t)); + active++; + } + } + + y = y_next; + } + return traps->status; +} + static cairo_bool_t _cairo_trap_contains (cairo_trapezoid_t *t, cairo_point_t *pt) { diff --git a/gfx/cairo/cairo/src/cairo-truetype-subset-private.h b/gfx/cairo/cairo/src/cairo-truetype-subset-private.h index e4be77ce182..e9b2c47e47c 100644 --- a/gfx/cairo/cairo/src/cairo-truetype-subset-private.h +++ b/gfx/cairo/cairo/src/cairo-truetype-subset-private.h @@ -62,33 +62,9 @@ #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_post MAKE_TT_TAG('p','o','s','t') #define TT_TAG_prep MAKE_TT_TAG('p','r','e','p') /* All tt_* structs are big-endian */ -typedef struct _tt_cmap_index { - uint16_t platform; - uint16_t encoding; - uint32_t offset; -} tt_cmap_index_t; - -typedef struct _tt_cmap { - uint16_t version; - uint16_t num_tables; - tt_cmap_index_t index[1]; -} tt_cmap_t; - -typedef struct _segment_map { - uint16_t format; - uint16_t length; - uint16_t version; - uint16_t segCountX2; - uint16_t searchRange; - uint16_t entrySelector; - uint16_t rangeShift; - uint16_t endCount[1]; -} tt_segment_map_t; - typedef struct _tt_head { int16_t version_1; int16_t version_2; diff --git a/gfx/cairo/cairo/src/cairo-truetype-subset.c b/gfx/cairo/cairo/src/cairo-truetype-subset.c index 7e77bb8aaae..86509dfb19a 100644 --- a/gfx/cairo/cairo/src/cairo-truetype-subset.c +++ b/gfx/cairo/cairo/src/cairo-truetype-subset.c @@ -56,7 +56,6 @@ typedef struct _cairo_truetype_font { int *widths; long x_min, y_min, x_max, y_max; long ascent, descent; - int units_per_em; } base; subset_glyph_t *glyphs; @@ -80,6 +79,41 @@ cairo_truetype_font_use_glyph (cairo_truetype_font_t *font, int glyph); #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) @@ -166,9 +200,6 @@ _cairo_truetype_font_create (cairo_scaled_font_subset_t *scaled_font_subset, font->base.y_max = (int16_t) be16_to_cpu (head.y_max); font->base.ascent = (int16_t) be16_to_cpu (hhea.ascender); font->base.descent = (int16_t) be16_to_cpu (hhea.descender); - font->base.units_per_em = (int16_t) be16_to_cpu (head.units_per_em); - if (font->base.units_per_em == 0) - font->base.units_per_em = 2048; /* Extract the font name from the name table. At present this * just looks for the Mac platform/Roman encoded font name. It @@ -340,45 +371,22 @@ cairo_truetype_font_write_cmap_table (cairo_truetype_font_t *font, { unsigned int i; - cairo_truetype_font_write_be16 (font, 0); /* Table version */ - cairo_truetype_font_write_be16 (font, 2); /* Num tables */ + cairo_truetype_font_write_be16 (font, 0); + cairo_truetype_font_write_be16 (font, 1); - cairo_truetype_font_write_be16 (font, 3); /* Platform */ - cairo_truetype_font_write_be16 (font, 0); /* Encoding */ - cairo_truetype_font_write_be32 (font, 20); /* Offset to start of table */ - - cairo_truetype_font_write_be16 (font, 1); /* Platform */ - cairo_truetype_font_write_be16 (font, 0); /* Encoding */ - cairo_truetype_font_write_be32 (font, 52); /* Offset to start of table */ - - /* Output a format 4 encoding table. */ - - cairo_truetype_font_write_be16 (font, 4); /* Format */ - cairo_truetype_font_write_be16 (font, 32); /* Length */ - cairo_truetype_font_write_be16 (font, 0); /* Version */ - cairo_truetype_font_write_be16 (font, 4); /* 2*segcount */ - cairo_truetype_font_write_be16 (font, 4); /* searchrange */ - cairo_truetype_font_write_be16 (font, 1); /* entry selector */ - cairo_truetype_font_write_be16 (font, 0); /* rangeshift */ - cairo_truetype_font_write_be16 (font, 0xf000 + font->base.num_glyphs - 2); /* end count[0] */ - cairo_truetype_font_write_be16 (font, 0xffff); /* end count[1] */ - cairo_truetype_font_write_be16 (font, 0); /* reserved */ - cairo_truetype_font_write_be16 (font, 0xf000); /* startCode[0] */ - cairo_truetype_font_write_be16 (font, 0xffff); /* startCode[1] */ - cairo_truetype_font_write_be16 (font, 0x1001); /* delta[0] */ - cairo_truetype_font_write_be16 (font, 1); /* delta[1] */ - cairo_truetype_font_write_be16 (font, 0); /* rangeOffset[0] */ - cairo_truetype_font_write_be16 (font, 0); /* rangeOffset[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, 0); /* First character */ - cairo_truetype_font_write_be16 (font, font->base.num_glyphs); - for (i = 0; i < font->base.num_glyphs; i++) - cairo_truetype_font_write_be16 (font, i + 1); + 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; } @@ -524,9 +532,6 @@ cairo_truetype_font_write_head_table (cairo_truetype_font_t *font, 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); - /* set checkSumAdjustment to 0 for table checksum calcualtion */ - *(uint32_t *)(buffer + 8) = 0; - return font->status; } @@ -635,65 +640,28 @@ cairo_truetype_font_write_maxp_table (cairo_truetype_font_t *font, return font->status; } -static int -cairo_truetype_font_write_post_table (cairo_truetype_font_t *font, - unsigned long tag) -{ - char buf[10]; - int n; - unsigned i; - - cairo_truetype_font_write_be32 (font, 0x00020000); - cairo_truetype_font_write_be32 (font, 0); - cairo_truetype_font_write_be16 (font, 0); - cairo_truetype_font_write_be16 (font, 1); - cairo_truetype_font_write_be32 (font, 0); - cairo_truetype_font_write_be32 (font, 0); - cairo_truetype_font_write_be32 (font, 0); - cairo_truetype_font_write_be32 (font, 0); - cairo_truetype_font_write_be32 (font, 0); - cairo_truetype_font_write_be16 (font, font->base.num_glyphs); - cairo_truetype_font_write_be16 (font, 0); - for (i = 1; i < font->base.num_glyphs; i++) - cairo_truetype_font_write_be16 (font, i + 257); - - for (i = 1; i < font->base.num_glyphs; i++) { - n = snprintf(buf + 1, 9, "g%d", i - 1); - buf[0] = n; - cairo_truetype_font_write (font, buf, n + 1); - } - - return font->status; -} - typedef struct table table_t; struct table { unsigned long tag; int (*write) (cairo_truetype_font_t *font, unsigned long tag); - int pos; /* position in the font directory */ }; 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. - * - * The third column in this table is the order in which the - * directory entries will appear in the table directory. - * The table directory must be sorted in tag order. */ - { TT_TAG_glyf, cairo_truetype_font_write_glyf_table, 3 }, - { TT_TAG_cmap, cairo_truetype_font_write_cmap_table, 0 }, - { TT_TAG_cvt, cairo_truetype_font_write_generic_table, 1 }, - { TT_TAG_fpgm, cairo_truetype_font_write_generic_table, 2 }, - { TT_TAG_head, cairo_truetype_font_write_head_table, 4 }, - { TT_TAG_hhea, cairo_truetype_font_write_hhea_table, 5 }, - { TT_TAG_hmtx, cairo_truetype_font_write_hmtx_table, 6 }, - { TT_TAG_loca, cairo_truetype_font_write_loca_table, 7 }, - { TT_TAG_maxp, cairo_truetype_font_write_maxp_table, 8 }, - { TT_TAG_name, cairo_truetype_font_write_generic_table, 9 }, - { TT_TAG_post, cairo_truetype_font_write_post_table, 10 }, - { TT_TAG_prep, cairo_truetype_font_write_generic_table, 11 }, + * 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 @@ -748,7 +716,7 @@ cairo_truetype_font_calculate_checksum (cairo_truetype_font_t *font, p = (uint32_t *) (data + start); padded_end = (uint32_t *) (data + ((end + 3) & ~3)); while (p < padded_end) - checksum += be32_to_cpu(*p++); + checksum += *p++; return checksum; } @@ -793,7 +761,7 @@ cairo_truetype_font_generate (cairo_truetype_font_t *font, end = _cairo_array_num_elements (&font->output); next = cairo_truetype_font_align_output (font); - cairo_truetype_font_update_entry (font, truetype_tables[i].pos, truetype_tables[i].tag, + cairo_truetype_font_update_entry (font, i, truetype_tables[i].tag, start, end); cairo_truetype_font_check_boundary (font, next); start = next; @@ -845,10 +813,6 @@ _cairo_truetype_subset_init (cairo_truetype_subset_t *truetype_subset, if (status) return status; - /* Add the notdef glyph. This is required at glyph index 0 - * in the subsetted font. */ - cairo_truetype_font_use_glyph (font, 0); - 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); @@ -863,23 +827,18 @@ _cairo_truetype_subset_init (cairo_truetype_subset_t *truetype_subset, if (truetype_subset->base_font == NULL) goto fail1; - /* The widths array returned must contain only widths for - * the glyphs in font_subset. The notdef glyph at index 0 - * and any subglyphs appended after font_subset->num_glyphs - * are omitted. */ - truetype_subset->widths = calloc (sizeof (double), - font->scaled_font_subset->num_glyphs); + truetype_subset->widths = calloc (sizeof (int), font->base.num_glyphs); if (truetype_subset->widths == NULL) goto fail2; - for (i = 0; i < font->scaled_font_subset->num_glyphs; i++) - truetype_subset->widths[i] = (double)font->base.widths[i + 1]/font->base.units_per_em; + for (i = 0; i < font->base.num_glyphs; i++) + truetype_subset->widths[i] = font->base.widths[i]; - truetype_subset->x_min = (double)font->base.x_min/font->base.units_per_em; - truetype_subset->y_min = (double)font->base.y_min/font->base.units_per_em; - truetype_subset->x_max = (double)font->base.x_max/font->base.units_per_em; - truetype_subset->y_max = (double)font->base.y_max/font->base.units_per_em; - truetype_subset->ascent = (double)font->base.ascent/font->base.units_per_em; - truetype_subset->descent = (double)font->base.descent/font->base.units_per_em; + 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) @@ -921,145 +880,3 @@ _cairo_truetype_subset_fini (cairo_truetype_subset_t *subset) free (subset->string_offsets); } -static cairo_int_status_t -_cairo_truetype_map_glyphs_to_unicode (cairo_scaled_font_subset_t *font_subset, - unsigned long table_offset) -{ - cairo_status_t status = CAIRO_INT_STATUS_UNSUPPORTED; - const cairo_scaled_font_backend_t *backend; - tt_segment_map_t *map; - char buf[4]; - unsigned int num_segments, i, j; - unsigned long size; - uint16_t *start_code; - uint16_t *end_code; - uint16_t *delta; - uint16_t *range_offset; - uint16_t *glyph_array; - uint16_t g_id, c; - - backend = font_subset->scaled_font->backend; - size = 4; - if (backend->load_truetype_table (font_subset->scaled_font, - TT_TAG_cmap, table_offset, - (unsigned char *) &buf, - &size) != CAIRO_STATUS_SUCCESS) { - return CAIRO_INT_STATUS_UNSUPPORTED; - } - - /* All table formats have the same first two words */ - map = (tt_segment_map_t *) buf; - if (be16_to_cpu (map->format) != 4) - return CAIRO_INT_STATUS_UNSUPPORTED; - - size = be16_to_cpu (map->length); - map = malloc (size); - if (map == NULL) - return CAIRO_STATUS_NO_MEMORY; - if (backend->load_truetype_table (font_subset->scaled_font, - TT_TAG_cmap, table_offset, - (unsigned char *) map, - &size) != CAIRO_STATUS_SUCCESS) { - goto fail; - } - - num_segments = be16_to_cpu (map->segCountX2)/2; - end_code = map->endCount; - start_code = &(end_code[num_segments + 1]); - delta = &(start_code[num_segments]); - range_offset = &(delta[num_segments]); - glyph_array = &(range_offset[num_segments]); - - i = 0; - while (i < font_subset->num_glyphs) { - g_id = (uint16_t) font_subset->glyphs[i]; - - /* search for glyph in segments - * with rangeOffset=0 */ - for (j = 0; j < num_segments; j++) { - c = g_id - be16_to_cpu (delta[j]); - if (range_offset[j] == 0 && - c >= be16_to_cpu (start_code[j]) && - c <= be16_to_cpu (end_code[j])) - { - font_subset->to_unicode[i] = c; - goto next_glyph; - } - } - - /* search for glyph in segments with rangeOffset=1 */ - for (j = 0; j < num_segments; j++) { - if (range_offset[j] != 0) { - uint16_t *glyph_ids = &range_offset[j] + be16_to_cpu (range_offset[j])/2; - int range_size = be16_to_cpu (end_code[j]) - be16_to_cpu (start_code[j]) + 1; - uint16_t g_id_be = cpu_to_be16 (g_id); - int k; - - for (k = 0; k < range_size; k++) { - if (glyph_ids[k] == g_id_be) { - font_subset->to_unicode[i] = be16_to_cpu (start_code[j]) + k; - goto next_glyph; - } - } - } - } - - next_glyph: - i++; - } - status = CAIRO_STATUS_SUCCESS; -fail: - free (map); - - return status; -} - -cairo_int_status_t -_cairo_truetype_create_glyph_to_unicode_map (cairo_scaled_font_subset_t *font_subset) -{ - cairo_status_t status = CAIRO_INT_STATUS_UNSUPPORTED; - const cairo_scaled_font_backend_t *backend; - tt_cmap_t *cmap; - char buf[4]; - int num_tables, i; - unsigned long size; - - backend = font_subset->scaled_font->backend; - if (!backend->load_truetype_table) - return CAIRO_INT_STATUS_UNSUPPORTED; - - size = 4; - if (backend->load_truetype_table (font_subset->scaled_font, - TT_TAG_cmap, 0, (unsigned char *) &buf, - &size) != CAIRO_STATUS_SUCCESS) - return CAIRO_INT_STATUS_UNSUPPORTED; - - cmap = (tt_cmap_t *) buf; - num_tables = be16_to_cpu (cmap->num_tables); - size = 4 + num_tables*sizeof(tt_cmap_index_t); - cmap = malloc (size); - if (cmap == NULL) - return CAIRO_STATUS_NO_MEMORY; - if (backend->load_truetype_table (font_subset->scaled_font, - TT_TAG_cmap, 0, (unsigned char *) cmap, - &size) != CAIRO_STATUS_SUCCESS) { - status = CAIRO_INT_STATUS_UNSUPPORTED; - goto cleanup; - } - - /* Find a table with Unicode mapping */ - for (i = 0; i < num_tables; i++) { - if (be16_to_cpu (cmap->index[i].platform) == 3 && - be16_to_cpu (cmap->index[i].encoding) == 1) { - status = _cairo_truetype_map_glyphs_to_unicode (font_subset, - be32_to_cpu (cmap->index[i].offset)); - if (status != CAIRO_INT_STATUS_UNSUPPORTED) - goto cleanup; - } - } - -cleanup: - free (cmap); - - return status; -} diff --git a/gfx/cairo/cairo/src/cairo-type1-fallback.c b/gfx/cairo/cairo/src/cairo-type1-fallback.c index a183b28b497..4776faf6d67 100644 --- a/gfx/cairo/cairo/src/cairo-type1-fallback.c +++ b/gfx/cairo/cairo/src/cairo-type1-fallback.c @@ -34,7 +34,6 @@ */ #include "cairoint.h" -#include "cairo-type1-private.h" #include "cairo-scaled-font-subsets-private.h" #include "cairo-path-fixed-private.h" #include "cairo-output-stream-private.h" @@ -117,6 +116,11 @@ fail: return CAIRO_STATUS_NO_MEMORY; } +/* 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 @@ -297,13 +301,13 @@ charstring_encrypt (cairo_array_t *data) unsigned char *d, *end; uint16_t c, p, r; - r = CAIRO_TYPE1_CHARSTRING_KEY; + 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) * CAIRO_TYPE1_ENCRYPT_C1 + CAIRO_TYPE1_ENCRYPT_C2; + r = (c + r) * encrypt_c1 + encrypt_c2; *d++ = c; } } @@ -530,7 +534,7 @@ cairo_type1_write_stream_encrypted (void *closure, while (in < end) { p = *in++; c = p ^ (font->eexec_key >> 8); - font->eexec_key = (c + font->eexec_key) * CAIRO_TYPE1_ENCRYPT_C1 + CAIRO_TYPE1_ENCRYPT_C2; + font->eexec_key = (c + font->eexec_key) * encrypt_c1 + encrypt_c2; if (font->hex_encode) { digits[0] = hex_digits[c >> 4]; @@ -560,7 +564,7 @@ cairo_type1_font_write_private_dict (cairo_type1_font_t *font, cairo_int_status_t status; cairo_output_stream_t *encrypted_output; - font->eexec_key = CAIRO_TYPE1_PRIVATE_DICT_KEY; + font->eexec_key = private_dict_key; font->hex_column = 0; encrypted_output = _cairo_output_stream_create ( cairo_type1_write_stream_encrypted, @@ -676,9 +680,8 @@ static void cairo_type1_font_destroy (cairo_type1_font_t *font) { free (font->widths); - cairo_scaled_font_destroy (font->type1_scaled_font); _cairo_array_fini (&font->contents); - _cairo_output_stream_destroy (font->output); + cairo_scaled_font_destroy (font->type1_scaled_font); free (font); } diff --git a/gfx/cairo/cairo/src/cairo-type1-subset.c b/gfx/cairo/cairo/src/cairo-type1-subset.c index e4f5015dd7b..4455ca59fa6 100644 --- a/gfx/cairo/cairo/src/cairo-type1-subset.c +++ b/gfx/cairo/cairo/src/cairo-type1-subset.c @@ -34,7 +34,6 @@ */ #include "cairoint.h" -#include "cairo-type1-private.h" #include "cairo-scaled-font-subsets-private.h" #include "cairo-output-stream-private.h" @@ -108,7 +107,6 @@ _cairo_type1_font_subset_create (cairo_unscaled_font_t *unscaled_font, cairo_bool_t hex_encode) { cairo_ft_unscaled_font_t *ft_unscaled_font; - cairo_status_t status; FT_Face face; PS_FontInfoRec font_info; cairo_type1_font_subset_t *font; @@ -118,16 +116,12 @@ _cairo_type1_font_subset_create (cairo_unscaled_font_t *unscaled_font, face = _cairo_ft_unscaled_font_lock_face (ft_unscaled_font); - if (FT_Get_PS_Font_Info(face, &font_info) != 0) { - status = CAIRO_INT_STATUS_UNSUPPORTED; - goto fail1; - } + if (FT_Get_PS_Font_Info(face, &font_info) != 0) + return CAIRO_INT_STATUS_UNSUPPORTED; font = calloc (sizeof (cairo_type1_font_subset_t), 1); - if (font == NULL) { - status = CAIRO_STATUS_NO_MEMORY; - goto fail1; - } + if (font == NULL) + return CAIRO_STATUS_NO_MEMORY; font->base.unscaled_font = _cairo_unscaled_font_reference (unscaled_font); font->base.num_glyphs = face->num_glyphs; @@ -138,10 +132,8 @@ _cairo_type1_font_subset_create (cairo_unscaled_font_t *unscaled_font, font->base.ascent = face->ascender; font->base.descent = face->descender; font->base.base_font = strdup (face->family_name); - if (font->base.base_font == NULL) { - status = CAIRO_STATUS_NO_MEMORY; - goto fail2; - } + if (font->base.base_font == NULL) + goto fail1; for (i = 0, j = 0; font->base.base_font[j]; j++) { if (font->base.base_font[j] == ' ') @@ -151,10 +143,8 @@ _cairo_type1_font_subset_create (cairo_unscaled_font_t *unscaled_font, font->base.base_font[i] = '\0'; font->glyphs = calloc (face->num_glyphs, sizeof font->glyphs[0]); - if (font->glyphs == NULL) { - status = CAIRO_STATUS_NO_MEMORY; - goto fail3; - } + if (font->glyphs == NULL) + goto fail2; font->hex_encode = hex_encode; font->num_glyphs = 0; @@ -169,15 +159,12 @@ _cairo_type1_font_subset_create (cairo_unscaled_font_t *unscaled_font, return CAIRO_STATUS_SUCCESS; - fail3: - free (font->base.base_font); fail2: - _cairo_unscaled_font_destroy (unscaled_font); - free (font); + free (font->base.base_font); fail1: - _cairo_ft_unscaled_font_unlock_face (ft_unscaled_font); + free (font); - return status; + return CAIRO_STATUS_NO_MEMORY; } static int @@ -192,6 +179,11 @@ cairo_type1_font_subset_use_glyph (cairo_type1_font_subset_t *font, int glyph) return font->glyphs[glyph].subset_index; } +/* Magic constants for the type1 eexec encryption */ +static const unsigned short c1 = 52845, c2 = 22719; +static const unsigned short private_dict_key = 55665; +static const unsigned short charstring_key = 4330; + static cairo_bool_t is_ps_delimiter(int c) { @@ -333,7 +325,7 @@ cairo_type1_font_subset_write_encrypted (cairo_type1_font_subset_t *font, while (in < end) { p = *in++; c = p ^ (font->eexec_key >> 8); - font->eexec_key = (c + font->eexec_key) * CAIRO_TYPE1_ENCRYPT_C1 + CAIRO_TYPE1_ENCRYPT_C2; + font->eexec_key = (c + font->eexec_key) * c1 + c2; if (font->hex_encode) { digits[0] = hex_digits[c >> 4]; @@ -357,7 +349,7 @@ cairo_type1_font_subset_write_encrypted (cairo_type1_font_subset_t *font, static cairo_status_t cairo_type1_font_subset_decrypt_eexec_segment (cairo_type1_font_subset_t *font) { - unsigned short r = CAIRO_TYPE1_PRIVATE_DICT_KEY; + unsigned short r = private_dict_key; unsigned char *in, *end; char *out; int c, p; @@ -380,7 +372,7 @@ cairo_type1_font_subset_decrypt_eexec_segment (cairo_type1_font_subset_t *font) c = *in++; } p = c ^ (r >> 8); - r = (c + r) * CAIRO_TYPE1_ENCRYPT_C1 + CAIRO_TYPE1_ENCRYPT_C2; + r = (c + r) * c1 + c2; *out++ = p; } @@ -460,13 +452,13 @@ cairo_type1_font_subset_get_glyph_names_and_widths (cairo_type1_font_subset_t *f static void cairo_type1_font_subset_decrypt_charstring (const unsigned char *in, int size, unsigned char *out) { - unsigned short r = CAIRO_TYPE1_CHARSTRING_KEY; + unsigned short r = charstring_key; int c, p, i; for (i = 0; i < size; i++) { c = *in++; p = c ^ (r >> 8); - r = (c + r) * CAIRO_TYPE1_ENCRYPT_C1 + CAIRO_TYPE1_ENCRYPT_C2; + r = (c + r) * c1 + c2; *out++ = p; } } @@ -1012,7 +1004,7 @@ cairo_type1_font_subset_write (cairo_type1_font_subset_t *font, return font->status = CAIRO_INT_STATUS_UNSUPPORTED; } - font->eexec_key = CAIRO_TYPE1_PRIVATE_DICT_KEY; + font->eexec_key = private_dict_key; font->hex_column = 0; cairo_type1_font_subset_write_private_dict (font, name); diff --git a/gfx/cairo/cairo/src/cairo-win32-font.c b/gfx/cairo/cairo/src/cairo-win32-font.c index de81c0a262e..139a73b34df 100644 --- a/gfx/cairo/cairo/src/cairo-win32-font.c +++ b/gfx/cairo/cairo/src/cairo-win32-font.c @@ -693,7 +693,7 @@ _cairo_win32_scaled_font_set_metrics (cairo_win32_scaled_font_t *scaled_font) if (!hdc) return CAIRO_STATUS_NO_MEMORY; - if (scaled_font->preserve_axes || scaled_font->base.options.hint_metrics == CAIRO_HINT_METRICS_OFF) { + if (scaled_font->preserve_axes) { /* For 90-degree rotations (including 0), we get the metrics * from the GDI in logical space, then convert back to font space */ @@ -723,7 +723,7 @@ _cairo_win32_scaled_font_set_metrics (cairo_win32_scaled_font_t *scaled_font) _cairo_win32_scaled_font_done_unscaled_font (&scaled_font->base); extents.ascent = (double)metrics.tmAscent / scaled_font->em_square; - extents.descent = (double)metrics.tmDescent / scaled_font->em_square; + extents.descent = metrics.tmDescent * scaled_font->em_square; extents.height = (double)(metrics.tmHeight + metrics.tmExternalLeading) / scaled_font->em_square; extents.max_x_advance = (double)(metrics.tmMaxCharWidth) / scaled_font->em_square; extents.max_y_advance = 0; @@ -1281,20 +1281,6 @@ _cairo_win32_scaled_font_load_truetype_table (void *abstract_font, return status; } -static void -_cairo_win32_scaled_font_map_glyphs_to_unicode (void *abstract_font, - cairo_scaled_font_subset_t *font_subset) -{ - cairo_win32_scaled_font_t *scaled_font = abstract_font; - unsigned int i; - - if (scaled_font->glyph_indexing) - return; - - for (i = 0; i < font_subset->num_glyphs; i++) - font_subset->to_unicode[i] = font_subset->glyphs[i]; -} - static void _cairo_win32_transform_FIXED_to_fixed (cairo_matrix_t *matrix, FIXED Fx, FIXED Fy, @@ -1481,7 +1467,6 @@ const cairo_scaled_font_backend_t cairo_win32_scaled_font_backend = { NULL, /* ucs4_to_index */ _cairo_win32_scaled_font_show_glyphs, _cairo_win32_scaled_font_load_truetype_table, - _cairo_win32_scaled_font_map_glyphs_to_unicode, }; /* cairo_win32_font_face_t */ @@ -1664,7 +1649,7 @@ cairo_win32_scaled_font_select_font (cairo_scaled_font_t *scaled_font, /** * cairo_win32_scaled_font_done_font: - * @scaled_font: A scaled font from the Win32 font backend. + * @scaled_font: A #cairo_scaled_font_t from the Win32 font backend. * * Releases any resources allocated by cairo_win32_scaled_font_select_font() **/ @@ -1675,7 +1660,7 @@ cairo_win32_scaled_font_done_font (cairo_scaled_font_t *scaled_font) /** * cairo_win32_scaled_font_get_metrics_factor: - * @scaled_font: a scaled font from the Win32 font backend + * @scaled_font: a #cairo_scaled_font_t from the Win32 font backend * * Gets a scale factor between logical coordinates in the coordinate * space used by cairo_win32_scaled_font_select_font() (that is, the @@ -1691,16 +1676,6 @@ cairo_win32_scaled_font_get_metrics_factor (cairo_scaled_font_t *scaled_font) return 1. / ((cairo_win32_scaled_font_t *)scaled_font)->logical_scale; } -/** - * cairo_win32_scaled_font_get_logical_to_device: - * @scaled_font: a scaled font from the Win32 font backend - * @logical_to_device: matrix to return - * - * Gets the transformation mapping the logical space used by @scaled_font - * to device space. - * - * Since: 1.4 - **/ void cairo_win32_scaled_font_get_logical_to_device (cairo_scaled_font_t *scaled_font, cairo_matrix_t *logical_to_device) @@ -1709,16 +1684,6 @@ cairo_win32_scaled_font_get_logical_to_device (cairo_scaled_font_t *scaled_font, *logical_to_device = win_font->logical_to_device; } -/** - * cairo_win32_scaled_font_get_device_to_logical: - * @scaled_font: a scaled font from the Win32 font backend - * @device_to_logical: matrix to return - * - * Gets the transformation mapping device space to the logical space - * used by @scaled_font. - * - * Since: 1.4 - **/ void cairo_win32_scaled_font_get_device_to_logical (cairo_scaled_font_t *scaled_font, cairo_matrix_t *device_to_logical) diff --git a/gfx/cairo/cairo/src/cairo-win32-private.h b/gfx/cairo/cairo/src/cairo-win32-private.h index 8256b20964f..ce574dc3d13 100644 --- a/gfx/cairo/cairo/src/cairo-win32-private.h +++ b/gfx/cairo/cairo/src/cairo-win32-private.h @@ -46,11 +46,7 @@ #define SB_NONE 0 #endif -#if MOZILLA_CAIRO_NOT_DEFINED -#define WIN32_FONT_LOGICAL_SCALE 32 -#else #define WIN32_FONT_LOGICAL_SCALE 1 -#endif typedef struct _cairo_win32_surface { cairo_surface_t base; diff --git a/gfx/cairo/cairo/src/cairo-win32-surface.c b/gfx/cairo/cairo/src/cairo-win32-surface.c index 9123b82a0e0..4025b94eca4 100644 --- a/gfx/cairo/cairo/src/cairo-win32-surface.c +++ b/gfx/cairo/cairo/src/cairo-win32-surface.c @@ -1487,7 +1487,6 @@ _cairo_win32_surface_show_glyphs (void *surface, int num_glyphs, cairo_scaled_font_t *scaled_font) { -#if CAIRO_HAS_WIN32_FONT cairo_win32_surface_t *dst = surface; WORD glyph_buf_stack[STACK_GLYPH_SIZE]; @@ -1581,8 +1580,8 @@ _cairo_win32_surface_show_glyphs (void *surface, next_logical_x = _cairo_lround (next_user_x); next_logical_y = _cairo_lround (next_user_y); - dxy_buf[j] = _cairo_lround (next_logical_x - logical_x); - dxy_buf[j+1] = _cairo_lround (next_logical_y - logical_y); + dxy_buf[j] = _cairo_lround ((next_logical_x - logical_x) * WIN32_FONT_LOGICAL_SCALE); + dxy_buf[j+1] = _cairo_lround ((next_logical_y - logical_y) * WIN32_FONT_LOGICAL_SCALE); logical_x = next_logical_x; logical_y = next_logical_y; @@ -1608,9 +1607,6 @@ _cairo_win32_surface_show_glyphs (void *surface, free(dxy_buf); } return (win_result) ? CAIRO_STATUS_SUCCESS : CAIRO_INT_STATUS_UNSUPPORTED; -#else - return CAIRO_INT_STATUS_UNSUPPORTED; -#endif } #undef STACK_GLYPH_SIZE @@ -1732,7 +1728,6 @@ cairo_win32_surface_create_with_dib (cairo_format_t format, /** * cairo_win32_surface_create_with_ddb: - * @hdc: the DC to create a surface for * @format: format of pixels in the surface to create * @width: width of the surface, in pixels * @height: height of the surface, in pixels @@ -1895,11 +1890,9 @@ static const cairo_surface_backend_t cairo_win32_surface_backend = { */ #if !defined(HAVE_PTHREAD_H) -CRITICAL_SECTION _cairo_scaled_font_map_mutex; -#ifdef CAIRO_HAS_FT_FONT -CRITICAL_SECTION _cairo_ft_unscaled_font_map_mutex; -#endif -CRITICAL_SECTION _cairo_font_face_mutex; +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; @@ -1909,11 +1902,9 @@ _cairo_win32_initialize (void) { return; /* every 'mutex' from CAIRO_MUTEX_DECALRE needs to be initialized here */ - InitializeCriticalSection (&_cairo_scaled_font_map_mutex); -#ifdef CAIRO_HAS_FT_FONT - InitializeCriticalSection (&_cairo_ft_unscaled_font_map_mutex); -#endif - InitializeCriticalSection (&_cairo_font_face_mutex); + 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; } @@ -1930,11 +1921,9 @@ DllMain (HINSTANCE hinstDLL, _cairo_win32_initialize(); break; case DLL_PROCESS_DETACH: - DeleteCriticalSection (&_cairo_scaled_font_map_mutex); -#ifdef CAIRO_HAS_FT_FONT - DeleteCriticalSection (&_cairo_ft_unscaled_font_map_mutex); -#endif - DeleteCriticalSection (&_cairo_font_face_mutex); + DeleteCriticalSection (&cairo_toy_font_face_hash_table_mutex); + DeleteCriticalSection (&cairo_scaled_font_map_mutex); + DeleteCriticalSection (&cairo_ft_unscaled_font_map_mutex); break; } return TRUE; diff --git a/gfx/cairo/cairo/src/cairo-xcb-surface.c b/gfx/cairo/cairo/src/cairo-xcb-surface.c index 08979611909..2fdf8a1d53b 100644 --- a/gfx/cairo/cairo/src/cairo-xcb-surface.c +++ b/gfx/cairo/cairo/src/cairo-xcb-surface.c @@ -1289,9 +1289,10 @@ _create_a8_picture (cairo_xcb_surface_t *surface, = _CAIRO_FORMAT_TO_XRENDER_FORMAT (surface->dpy, CAIRO_FORMAT_A8); xcb_rectangle_t rect = { 0, 0, width, height }; - xcb_create_pixmap (surface->dpy, 8, pixmap, surface->drawable, - width <= 0 ? 1 : width, - height <= 0 ? 1 : height); + xcb_create_pixmap (surface->dpy, pixmap, surface->drawable, + width <= 0 ? 1 : width, + height <= 0 ? 1 : height, + 8); xcb_render_create_picture (surface->dpy, picture, pixmap, format->id, mask, values); xcb_render_fill_rectangles (surface->dpy, XCB_RENDER_PICT_OP_SRC, picture, *color, 1, &rect); xcb_free_pixmap (surface->dpy, pixmap); diff --git a/gfx/cairo/cairo/src/cairo-xlib-private.h b/gfx/cairo/cairo/src/cairo-xlib-private.h index 8ba46a2ec35..ed9bc34ed09 100644 --- a/gfx/cairo/cairo/src/cairo-xlib-private.h +++ b/gfx/cairo/cairo/src/cairo-xlib-private.h @@ -37,14 +37,6 @@ #include "cairo-xlib.h" typedef struct _cairo_xlib_screen_info cairo_xlib_screen_info_t; -typedef struct _cairo_xlib_hook cairo_xlib_hook_t; - -struct _cairo_xlib_hook { - cairo_xlib_hook_t *next; - void (*func) (Display *display, void *data); - void *data; - void *key; -}; struct _cairo_xlib_screen_info { cairo_xlib_screen_info_t *next; @@ -54,22 +46,17 @@ struct _cairo_xlib_screen_info { cairo_bool_t has_render; cairo_font_options_t font_options; - - cairo_xlib_hook_t *close_display_hooks; }; cairo_private cairo_xlib_screen_info_t * _cairo_xlib_screen_info_get (Display *display, Screen *screen); -cairo_private cairo_bool_t -_cairo_xlib_add_close_display_hook (Display *display, void (*func) (Display *, void *), void *data, void *key); -cairo_private void -_cairo_xlib_remove_close_display_hook (Display *display, void *key); - #if CAIRO_HAS_XLIB_XRENDER_SURFACE #include "cairo-xlib-xrender.h" +#if 0 slim_hidden_proto (cairo_xlib_surface_create_with_xrender_format); +#endif #endif diff --git a/gfx/cairo/cairo/src/cairo-xlib-screen.c b/gfx/cairo/cairo/src/cairo-xlib-screen.c index 4c34608a2e0..cbdb540d392 100644 --- a/gfx/cairo/cairo/src/cairo-xlib-screen.c +++ b/gfx/cairo/cairo/src/cairo-xlib-screen.c @@ -247,36 +247,31 @@ CAIRO_MUTEX_DECLARE(_xlib_screen_mutex); static cairo_xlib_screen_info_t *_cairo_xlib_screen_list = NULL; +/* XXX: From this function we should also run through and cleanup + * anything else that still has a pointer to this Display*. For + * example, we should clean up any Xlib-specific glyph caches. */ static int _cairo_xlib_close_display (Display *dpy, XExtCodes *codes) { - cairo_xlib_screen_info_t *info, **prev, *next; + cairo_xlib_screen_info_t *info, *prev; /* * Unhook from the global list */ CAIRO_MUTEX_LOCK (_xlib_screen_mutex); - prev = &_cairo_xlib_screen_list; - for (info = _cairo_xlib_screen_list; info; info = next) { - next = info->next; + prev = NULL; + for (info = _cairo_xlib_screen_list; info; info = info->next) { if (info->display == dpy) { - *prev = next; - /* call all registered shutdown routines */ - while (info->close_display_hooks) { - cairo_xlib_hook_t *hook = info->close_display_hooks; - info->close_display_hooks = hook->next; - - hook->func (dpy, hook->data); - - free (hook); - } + if (prev) + prev->next = info->next; + else + _cairo_xlib_screen_list = info->next; free (info); - } else { - prev = &info->next; + break; } + prev = info; } - *prev = NULL; CAIRO_MUTEX_UNLOCK (_xlib_screen_mutex); /* Return value in accordance with requirements of @@ -296,11 +291,6 @@ _cairo_xlib_screen_info_reset (void) for (info = _cairo_xlib_screen_list; info; info = next) { next = info->next; - while (info->close_display_hooks) { - cairo_xlib_hook_t *hook = info->close_display_hooks; - info->close_display_hooks = hook->next; - free (hook); - } free (info); } @@ -310,8 +300,8 @@ _cairo_xlib_screen_info_reset (void) } -static cairo_xlib_screen_info_t * -_cairo_xlib_screen_info_get_unlocked (Display *dpy, Screen *screen) +cairo_xlib_screen_info_t * +_cairo_xlib_screen_info_get (Display *dpy, Screen *screen) { cairo_xlib_screen_info_t *info; cairo_xlib_screen_info_t **prev; @@ -319,60 +309,6 @@ _cairo_xlib_screen_info_get_unlocked (Display *dpy, Screen *screen) XExtCodes *codes; cairo_bool_t seen_display = FALSE; - for (prev = &_cairo_xlib_screen_list; (info = *prev); prev = &(*prev)->next) - { - if (info->display == dpy) { - seen_display = TRUE; - if (info->screen == screen || screen == NULL) { - /* - * MRU the list - */ - if (prev != &_cairo_xlib_screen_list) { - *prev = info->next; - info->next = _cairo_xlib_screen_list; - _cairo_xlib_screen_list = info; - } - break; - } - } - } - - if (info) - return info; - - info = malloc (sizeof (cairo_xlib_screen_info_t)); - if (!info) - return NULL; - - if (!seen_display) { - codes = XAddExtension (dpy); - if (!codes) { - free (info); - return NULL; - } - - XESetCloseDisplay (dpy, codes->extension, _cairo_xlib_close_display); - } - - info->display = dpy; - info->screen = screen; - info->has_render = (XRenderQueryExtension (dpy, &event_base, &error_base) && - (XRenderFindVisualFormat (dpy, DefaultVisual (dpy, DefaultScreen (dpy))) != 0)); - - info->close_display_hooks = NULL; - - _cairo_xlib_init_screen_font_options (info); - - info->next = _cairo_xlib_screen_list; - _cairo_xlib_screen_list = info; - - return info; -} -cairo_xlib_screen_info_t * -_cairo_xlib_screen_info_get (Display *dpy, Screen *screen) -{ - cairo_xlib_screen_info_t *info; - /* There is an apparent deadlock between this mutex and the * mutex for the display, but it's actually safe. For the * app to call XCloseDisplay() while any other thread is @@ -382,87 +318,67 @@ _cairo_xlib_screen_info_get (Display *dpy, Screen *screen) */ CAIRO_MUTEX_LOCK (_xlib_screen_mutex); - info = _cairo_xlib_screen_info_get_unlocked (dpy, screen); + for (prev = &_cairo_xlib_screen_list; (info = *prev); prev = &(*prev)->next) + { + if (info->display == dpy) { + seen_display = TRUE; + if (info->screen == screen) + { + /* + * MRU the list + */ + if (prev != &_cairo_xlib_screen_list) + { + *prev = info->next; + info->next = _cairo_xlib_screen_list; + _cairo_xlib_screen_list = info; + } + break; + } + } + } + if (info) + goto out; + + info = malloc (sizeof (cairo_xlib_screen_info_t)); + if (!info) + goto out; + + if (!seen_display) { + codes = XAddExtension (dpy); + if (!codes) { + free (info); + info = NULL; + goto out; + } + + XESetCloseDisplay (dpy, codes->extension, _cairo_xlib_close_display); + } + + info->display = dpy; + info->screen = screen; + info->has_render = (XRenderQueryExtension (dpy, &event_base, &error_base) && + (XRenderFindVisualFormat (dpy, DefaultVisual (dpy, DefaultScreen (dpy))) != 0)); + + _cairo_xlib_init_screen_font_options (info); + + info->next = _cairo_xlib_screen_list; + _cairo_xlib_screen_list = info; + + out: CAIRO_MUTEX_UNLOCK (_xlib_screen_mutex); return info; } -cairo_bool_t -_cairo_xlib_add_close_display_hook (Display *dpy, void (*func) (Display *, void *), void *data, void *key) -{ - cairo_xlib_screen_info_t *info; - cairo_xlib_hook_t *hook; - cairo_xlib_hook_t **prev; - cairo_bool_t success = FALSE; - - CAIRO_MUTEX_LOCK (_xlib_screen_mutex); - - info = _cairo_xlib_screen_info_get_unlocked (dpy, NULL); - if (!info) - goto unlock; - - for (prev = &info->close_display_hooks; (hook = *prev); prev = &hook->next) - { - if (hook->key == key) { - /* - * MRU the list - */ - if (prev != &info->close_display_hooks) { - *prev = hook->next; - hook->next = info->close_display_hooks; - info->close_display_hooks = hook; - } - break; - } - } - - if (!hook) { - hook = malloc (sizeof (cairo_xlib_hook_t)); - if (!hook) - goto unlock; - hook->func = func; - hook->data = data; - hook->key = key; - hook->next = info->close_display_hooks; - info->close_display_hooks = hook; - } - - success = TRUE; - unlock: - CAIRO_MUTEX_UNLOCK (_xlib_screen_mutex); - return success; -} - -void -_cairo_xlib_remove_close_display_hook (Display *dpy, void *key) -{ - cairo_xlib_screen_info_t *info; - cairo_xlib_hook_t *hook; - cairo_xlib_hook_t **prev; - - CAIRO_MUTEX_LOCK (_xlib_screen_mutex); - - info = _cairo_xlib_screen_info_get_unlocked (dpy, NULL); - if (!info) - goto unlock; - - for (prev = &info->close_display_hooks; (hook = *prev); prev = &hook->next) - { - if (hook->key == key) { - *prev = hook->next; - free (hook); - break; - } - } - -unlock: - CAIRO_MUTEX_UNLOCK (_xlib_screen_mutex); -} - void _cairo_xlib_screen_reset_static_data (void) { _cairo_xlib_screen_info_reset (); + +#if HAVE_XRMFINALIZE + XrmFinalize (); +#endif + } diff --git a/gfx/cairo/cairo/src/cairo-xlib-surface.c b/gfx/cairo/cairo/src/cairo-xlib-surface.c index 7f1392deac3..d076d9c18cd 100644 --- a/gfx/cairo/cairo/src/cairo-xlib-surface.c +++ b/gfx/cairo/cairo/src/cairo-xlib-surface.c @@ -610,27 +610,24 @@ _get_image_surface (cairo_xlib_surface_t *surface, _swap_ximage_to_native (ximage); /* - * Compute the pixel format masks from either a XrenderFormat or - * else from a visual; failing that we assume the drawable is an - * alpha-only pixmap as it could only have been created that way - * through the cairo_xlib_surface_create_for_bitmap function. + * Compute the pixel format masks from either a visual or a + * XRenderFormat, failing we assume the drawable is an + * alpha-only pixmap as it could only have been created + * that way through the cairo_xlib_surface_create_for_bitmap + * function. */ - if (surface->xrender_format) { - masks.bpp = ximage->bits_per_pixel; - masks.red_mask = (unsigned long) surface->xrender_format->direct.redMask - << surface->xrender_format->direct.red; - masks.green_mask = (unsigned long) surface->xrender_format->direct.greenMask - << surface->xrender_format->direct.green; - masks.blue_mask = (unsigned long) surface->xrender_format->direct.blueMask - << surface->xrender_format->direct.blue; - masks.alpha_mask = (unsigned long) surface->xrender_format->direct.alphaMask - << surface->xrender_format->direct.alpha; - } else if (surface->visual) { + if (surface->visual) { masks.bpp = ximage->bits_per_pixel; masks.alpha_mask = 0; masks.red_mask = surface->visual->red_mask; masks.green_mask = surface->visual->green_mask; masks.blue_mask = surface->visual->blue_mask; + } else if (surface->xrender_format) { + masks.bpp = ximage->bits_per_pixel; + masks.red_mask = (unsigned long)surface->xrender_format->direct.redMask << surface->xrender_format->direct.red; + masks.green_mask = (unsigned long)surface->xrender_format->direct.greenMask << surface->xrender_format->direct.green; + masks.blue_mask = (unsigned long)surface->xrender_format->direct.blueMask << surface->xrender_format->direct.blue; + masks.alpha_mask = (unsigned long)surface->xrender_format->direct.alphaMask << surface->xrender_format->direct.alpha; } else { masks.bpp = ximage->bits_per_pixel; masks.red_mask = 0; @@ -2022,7 +2019,9 @@ cairo_xlib_surface_create_with_xrender_format (Display *dpy, return _cairo_xlib_surface_create_internal (dpy, drawable, screen, NULL, format, width, height, 0); } +#if 0 slim_hidden_def (cairo_xlib_surface_create_with_xrender_format); +#endif /** * cairo_xlib_surface_set_size: @@ -2271,24 +2270,6 @@ typedef struct _cairo_xlib_surface_font_private { XRenderPictFormat *xrender_format; } cairo_xlib_surface_font_private_t; -static void -_cairo_xlib_surface_remove_scaled_font (Display *dpy, - void *data) -{ - cairo_scaled_font_t *scaled_font = data; - cairo_xlib_surface_font_private_t *font_private = scaled_font->surface_private; - - _cairo_scaled_font_reset_cache (scaled_font); - - /* separate function to avoid deadlock if we tried to remove the - * close display hook ala _cairo_xlib_surface_scaled_font_fini() */ - if (font_private) { - XRenderFreeGlyphSet (font_private->dpy, font_private->glyphset); - free (font_private); - scaled_font->surface_private = NULL; - } -} - static cairo_status_t _cairo_xlib_surface_font_init (Display *dpy, cairo_scaled_font_t *scaled_font, @@ -2296,11 +2277,6 @@ _cairo_xlib_surface_font_init (Display *dpy, { cairo_xlib_surface_font_private_t *font_private; - if (!_cairo_xlib_add_close_display_hook (dpy, - _cairo_xlib_surface_remove_scaled_font, - scaled_font, scaled_font)) - return CAIRO_STATUS_NO_MEMORY; - font_private = malloc (sizeof (cairo_xlib_surface_font_private_t)); if (!font_private) return CAIRO_STATUS_NO_MEMORY; @@ -2311,7 +2287,6 @@ _cairo_xlib_surface_font_init (Display *dpy, font_private->glyphset = XRenderCreateGlyphSet (dpy, font_private->xrender_format); scaled_font->surface_private = font_private; scaled_font->surface_backend = &cairo_xlib_surface_backend; - return CAIRO_STATUS_SUCCESS; } @@ -2321,7 +2296,6 @@ _cairo_xlib_surface_scaled_font_fini (cairo_scaled_font_t *scaled_font) cairo_xlib_surface_font_private_t *font_private = scaled_font->surface_private; if (font_private) { - _cairo_xlib_remove_close_display_hook (font_private->dpy, scaled_font); XRenderFreeGlyphSet (font_private->dpy, font_private->glyphset); free (font_private); } diff --git a/gfx/cairo/cairo/src/cairo.c b/gfx/cairo/cairo/src/cairo.c index 21303debd05..2e522a63be2 100644 --- a/gfx/cairo/cairo/src/cairo.c +++ b/gfx/cairo/cairo/src/cairo.c @@ -47,18 +47,15 @@ static const cairo_t cairo_nil = { CAIRO_REF_COUNT_INVALID, /* ref_count */ CAIRO_STATUS_NO_MEMORY, /* status */ - { 0, 0, 0, NULL }, /* user_data */ - NULL, /* gstate */ - {{ /* gstate_tail */ - 0 - }}, - {{ /* path */ + { /* path */ + NULL, NULL, /* op_buf_head, op_buf_tail */ + NULL, NULL, /* arg_buf_head, arg_buf_tail */ { 0, 0 }, /* last_move_point */ { 0, 0 }, /* current point */ FALSE, /* has_current_point */ - FALSE, /* has_curve_to */ - NULL, {{0}} /* buf_tail, buf_head */ - }} + FALSE /* has_curve_to */ + }, + NULL /* gstate */ }; #include @@ -198,17 +195,18 @@ cairo_create (cairo_surface_t *target) cr->status = CAIRO_STATUS_SUCCESS; - _cairo_user_data_array_init (&cr->user_data); - - cr->gstate = cr->gstate_tail; - _cairo_gstate_init (cr->gstate, target); - - _cairo_path_fixed_init (cr->path); + _cairo_path_fixed_init (&cr->path); if (target == NULL) { + cr->gstate = NULL; _cairo_set_error (cr, CAIRO_STATUS_NULL_POINTER); + return cr; } + cr->gstate = _cairo_gstate_create (target); + if (cr->gstate == NULL) + _cairo_set_error (cr, CAIRO_STATUS_NO_MEMORY); + return cr; } slim_hidden_def (cairo_create); @@ -221,15 +219,15 @@ slim_hidden_def (cairo_create); * @cr from being destroyed until a matching call to cairo_destroy() * is made. * - * The number of references to a #cairo_t can be get using - * cairo_get_reference_count(). - * * Return value: the referenced #cairo_t. **/ cairo_t * cairo_reference (cairo_t *cr) { - if (cr == NULL || cr->ref_count == CAIRO_REF_COUNT_INVALID) + if (cr == NULL) + return NULL; + + if (cr->ref_count == CAIRO_REF_COUNT_INVALID) return cr; assert (cr->ref_count > 0); @@ -250,7 +248,10 @@ cairo_reference (cairo_t *cr) void cairo_destroy (cairo_t *cr) { - if (cr == NULL || cr->ref_count == CAIRO_REF_COUNT_INVALID) + if (cr == NULL) + return; + + if (cr->ref_count == CAIRO_REF_COUNT_INVALID) return; assert (cr->ref_count > 0); @@ -259,96 +260,19 @@ cairo_destroy (cairo_t *cr) if (cr->ref_count) return; - while (cr->gstate != cr->gstate_tail) { + while (cr->gstate) { cairo_gstate_t *tmp = cr->gstate; cr->gstate = tmp->next; _cairo_gstate_destroy (tmp); } - _cairo_gstate_fini (cr->gstate); - - _cairo_path_fixed_fini (cr->path); - - _cairo_user_data_array_fini (&cr->user_data); + _cairo_path_fixed_fini (&cr->path); free (cr); } slim_hidden_def (cairo_destroy); -/** - * cairo_get_user_data: - * @cr: a #cairo_t - * @key: the address of the #cairo_user_data_key_t the user data was - * attached to - * - * Return user data previously attached to @cr using the specified - * key. If no user data has been attached with the given key this - * function returns %NULL. - * - * Return value: the user data previously attached or %NULL. - * - * Since: 1.4 - **/ -void * -cairo_get_user_data (cairo_t *cr, - const cairo_user_data_key_t *key) -{ - return _cairo_user_data_array_get_data (&cr->user_data, - key); -} - -/** - * cairo_set_user_data: - * @cr: a #cairo_t - * @key: the address of a #cairo_user_data_key_t to attach the user data to - * @user_data: the user data to attach to the #cairo_t - * @destroy: a #cairo_destroy_func_t which will be called when the - * #cairo_t is destroyed or when new user data is attached using the - * same key. - * - * Attach user data to @cr. To remove user data from a surface, - * call this function with the key that was used to set it and %NULL - * for @data. - * - * Return value: %CAIRO_STATUS_SUCCESS or %CAIRO_STATUS_NO_MEMORY if a - * slot could not be allocated for the user data. - * - * Since: 1.4 - **/ -cairo_status_t -cairo_set_user_data (cairo_t *cr, - const cairo_user_data_key_t *key, - void *user_data, - cairo_destroy_func_t destroy) -{ - if (cr->ref_count == CAIRO_REF_COUNT_INVALID) - return CAIRO_STATUS_NO_MEMORY; - - return _cairo_user_data_array_set_data (&cr->user_data, - key, user_data, destroy); -} - -/** - * cairo_get_reference_count: - * @cr: a #cairo_t - * - * Returns the current reference count of @cr. - * - * Return value: the current reference count of @cr. If the - * object is a nil object, 0 will be returned. - * - * Since: 1.4 - **/ -unsigned int -cairo_get_reference_count (cairo_t *cr) -{ - if (cr == NULL || cr->ref_count == CAIRO_REF_COUNT_INVALID) - return 0; - - return cr->ref_count; -} - /** * cairo_save: * @cr: a #cairo_t @@ -401,15 +325,13 @@ cairo_restore (cairo_t *cr) if (cr->status) return; - if (cr->gstate == cr->gstate_tail) { - _cairo_set_error (cr, CAIRO_STATUS_INVALID_RESTORE); - return; - } - top = cr->gstate; cr->gstate = top->next; _cairo_gstate_destroy (top); + + if (cr->gstate == NULL) + _cairo_set_error (cr, CAIRO_STATUS_INVALID_RESTORE); } slim_hidden_def(cairo_restore); @@ -933,8 +855,8 @@ cairo_set_line_width (cairo_t *cr, double width) /** * cairo_set_line_cap: - * @cr: a cairo context - * @line_cap: a line cap style + * @cr: a cairo context, as a #cairo_t + * @line_cap: a line cap style, as a #cairo_line_cap_t * * Sets the current line cap style within the cairo context. See * #cairo_line_cap_t for details about how the available line cap @@ -958,8 +880,8 @@ cairo_set_line_cap (cairo_t *cr, cairo_line_cap_t line_cap) /** * cairo_set_line_join: - * @cr: a cairo context - * @line_join: a line joint style + * @cr: a cairo context, as a #cairo_t + * @line_join: a line joint style, as a #cairo_line_join_t * * Sets the current line join style within the cairo context. See * #cairo_line_join_t for details about how the available line join @@ -1032,13 +954,11 @@ cairo_set_dash (cairo_t *cr, * cairo_get_dash_count: * @cr: a #cairo_t * - * This function returns the length of the dash array in @cr (0 if dashing - * is not currently in effect). + * Returns the length of the dash array in @cr (0 if dashing is not + * currently in effect). * * See also cairo_set_dash() and cairo_get_dash(). * - * Return value: the length of the dash array, or 0 if no dash array set. - * * Since: 1.4 */ int @@ -1073,25 +993,6 @@ cairo_get_dash (cairo_t *cr, *offset = cr->gstate->stroke_style.dash_offset; } -/** - * cairo_set_miter_limit: - * @cr: a cairo context - * @limit: miter limit to set - * - * Sets the current miter limit within the cairo context. - * - * If the current line join style is set to %CAIRO_LINE_JOIN_MITER - * (see cairo_set_line_join()), the miter limit is used to determine - * whether the lines should be joined with a bevel instead of a miter. - * Cairo divides the length of the miter by the line width. - * If the result is greater than the miter limit, the style is - * converted to a bevel. - * - * As with the other stroke parameters, the current line miter limit is - * examined by cairo_stroke(), cairo_stroke_extents(), and - * cairo_stroke_to_path(), but does not have any effect during path - * construction. - **/ void cairo_set_miter_limit (cairo_t *cr, double limit) { @@ -1147,7 +1048,6 @@ cairo_scale (cairo_t *cr, double sx, double sy) if (cr->status) _cairo_set_error (cr, cr->status); } -slim_hidden_def (cairo_scale); /** * cairo_rotate: @@ -1332,7 +1232,7 @@ cairo_new_path (cairo_t *cr) if (cr->status) return; - _cairo_path_fixed_fini (cr->path); + _cairo_path_fixed_fini (&cr->path); } slim_hidden_def(cairo_new_path); @@ -1357,7 +1257,7 @@ cairo_move_to (cairo_t *cr, double x, double y) x_fixed = _cairo_fixed_from_double (x); y_fixed = _cairo_fixed_from_double (y); - cr->status = _cairo_path_fixed_move_to (cr->path, x_fixed, y_fixed); + cr->status = _cairo_path_fixed_move_to (&cr->path, x_fixed, y_fixed); if (cr->status) _cairo_set_error (cr, cr->status); } @@ -1387,7 +1287,7 @@ cairo_new_sub_path (cairo_t *cr) if (cr->status) return; - _cairo_path_fixed_new_sub_path (cr->path); + _cairo_path_fixed_new_sub_path (&cr->path); } /** @@ -1415,7 +1315,7 @@ cairo_line_to (cairo_t *cr, double x, double y) x_fixed = _cairo_fixed_from_double (x); y_fixed = _cairo_fixed_from_double (y); - cr->status = _cairo_path_fixed_line_to (cr->path, x_fixed, y_fixed); + cr->status = _cairo_path_fixed_line_to (&cr->path, x_fixed, y_fixed); if (cr->status) _cairo_set_error (cr, cr->status); } @@ -1466,7 +1366,7 @@ cairo_curve_to (cairo_t *cr, x3_fixed = _cairo_fixed_from_double (x3); y3_fixed = _cairo_fixed_from_double (y3); - cr->status = _cairo_path_fixed_curve_to (cr->path, + cr->status = _cairo_path_fixed_curve_to (&cr->path, x1_fixed, y1_fixed, x2_fixed, y2_fixed, x3_fixed, y3_fixed); @@ -1632,7 +1532,7 @@ cairo_rel_move_to (cairo_t *cr, double dx, double dy) dx_fixed = _cairo_fixed_from_double (dx); dy_fixed = _cairo_fixed_from_double (dy); - cr->status = _cairo_path_fixed_rel_move_to (cr->path, dx_fixed, dy_fixed); + cr->status = _cairo_path_fixed_rel_move_to (&cr->path, dx_fixed, dy_fixed); if (cr->status) _cairo_set_error (cr, cr->status); } @@ -1667,7 +1567,7 @@ cairo_rel_line_to (cairo_t *cr, double dx, double dy) dx_fixed = _cairo_fixed_from_double (dx); dy_fixed = _cairo_fixed_from_double (dy); - cr->status = _cairo_path_fixed_rel_line_to (cr->path, dx_fixed, dy_fixed); + cr->status = _cairo_path_fixed_rel_line_to (&cr->path, dx_fixed, dy_fixed); if (cr->status) _cairo_set_error (cr, cr->status); } @@ -1725,7 +1625,7 @@ cairo_rel_curve_to (cairo_t *cr, dx3_fixed = _cairo_fixed_from_double (dx3); dy3_fixed = _cairo_fixed_from_double (dy3); - cr->status = _cairo_path_fixed_rel_curve_to (cr->path, + cr->status = _cairo_path_fixed_rel_curve_to (&cr->path, dx1_fixed, dy1_fixed, dx2_fixed, dy2_fixed, dx3_fixed, dy3_fixed); @@ -1813,7 +1713,7 @@ cairo_close_path (cairo_t *cr) if (cr->status) return; - cr->status = _cairo_path_fixed_close_path (cr->path); + cr->status = _cairo_path_fixed_close_path (&cr->path); if (cr->status) _cairo_set_error (cr, cr->status); } @@ -2003,7 +1903,7 @@ cairo_stroke_preserve (cairo_t *cr) if (cr->status) return; - cr->status = _cairo_gstate_stroke (cr->gstate, cr->path); + cr->status = _cairo_gstate_stroke (cr->gstate, &cr->path); if (cr->status) _cairo_set_error (cr, cr->status); } @@ -2044,7 +1944,7 @@ cairo_fill_preserve (cairo_t *cr) if (cr->status) return; - cr->status = _cairo_gstate_fill (cr->gstate, cr->path); + cr->status = _cairo_gstate_fill (cr->gstate, &cr->path); if (cr->status) _cairo_set_error (cr, cr->status); } @@ -2114,7 +2014,7 @@ cairo_in_stroke (cairo_t *cr, double x, double y) return 0; cr->status = _cairo_gstate_in_stroke (cr->gstate, - cr->path, + &cr->path, x, y, &inside); if (cr->status) return 0; @@ -2146,7 +2046,7 @@ cairo_in_fill (cairo_t *cr, double x, double y) return 0; cr->status = _cairo_gstate_in_fill (cr->gstate, - cr->path, + &cr->path, x, y, &inside); if (cr->status) { _cairo_set_error (cr, cr->status); @@ -2182,7 +2082,7 @@ cairo_stroke_extents (cairo_t *cr, return; cr->status = _cairo_gstate_stroke_extents (cr->gstate, - cr->path, + &cr->path, x1, y1, x2, y2); if (cr->status) _cairo_set_error (cr, cr->status); @@ -2212,7 +2112,7 @@ cairo_fill_extents (cairo_t *cr, return; cr->status = _cairo_gstate_fill_extents (cr->gstate, - cr->path, + &cr->path, x1, y1, x2, y2); if (cr->status) _cairo_set_error (cr, cr->status); @@ -2276,7 +2176,7 @@ cairo_clip_preserve (cairo_t *cr) if (cr->status) return; - cr->status = _cairo_gstate_clip (cr->gstate, cr->path); + cr->status = _cairo_gstate_clip (cr->gstate, &cr->path); if (cr->status) _cairo_set_error (cr, cr->status); } @@ -2351,9 +2251,8 @@ _cairo_rectangle_list_create_in_error (cairo_status_t status) /** * cairo_copy_clip_rectangle_list: - * @cr: a cairo context * - * Gets the current clip region as a list of rectangles in user coordinates. + * 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 @@ -2364,8 +2263,6 @@ _cairo_rectangle_list_create_in_error (cairo_status_t status) * The caller must always call cairo_rectangle_list_destroy on the result of * this function. * - * Returns: the current clip region as a list of rectangles in user coordinates. - * * Since: 1.4 **/ cairo_rectangle_list_t * @@ -2406,6 +2303,34 @@ cairo_select_font_face (cairo_t *cr, _cairo_set_error (cr, cr->status); } +/** + * cairo_get_font_face: + * @cr: a #cairo_t + * + * Gets the current font face for a #cairo_t. + * + * Return value: the current font object. Can return %NULL + * on out-of-memory or if the context is already in + * an error state. This object is owned by cairo. To keep + * a reference to it, you must call cairo_font_face_reference(). + **/ +cairo_font_face_t * +cairo_get_font_face (cairo_t *cr) +{ + cairo_font_face_t *font_face; + + if (cr->status) + return (cairo_font_face_t*) &_cairo_font_face_nil; + + cr->status = _cairo_gstate_get_font_face (cr->gstate, &font_face); + if (cr->status) { + _cairo_set_error (cr, cr->status); + return (cairo_font_face_t*) &_cairo_font_face_nil; + } + + return font_face; +} + /** * cairo_font_extents: * @cr: a #cairo_t @@ -2447,41 +2372,6 @@ cairo_set_font_face (cairo_t *cr, _cairo_set_error (cr, cr->status); } -/** - * cairo_get_font_face: - * @cr: a #cairo_t - * - * Gets the current font face for a #cairo_t. - * - * Return value: the current font face. This object is owned by - * cairo. To keep a reference to it, you must call - * cairo_font_face_reference. - * - * This function never returns %NULL. If memory cannot be allocated, a - * special "nil" #cairo_font_face_t object will be returned on which - * cairo_font_face_status() returns %CAIRO_STATUS_NO_MEMORY. Using - * this nil object will cause its error state to propagate to other - * objects it is passed to, (for example, calling - * cairo_set_font_face() with a nil font will trigger an error that - * will shutdown the cairo_t object). - **/ -cairo_font_face_t * -cairo_get_font_face (cairo_t *cr) -{ - cairo_font_face_t *font_face; - - if (cr->status) - return (cairo_font_face_t*) &_cairo_font_face_nil; - - cr->status = _cairo_gstate_get_font_face (cr->gstate, &font_face); - if (cr->status) { - _cairo_set_error (cr, cr->status); - return (cairo_font_face_t*) &_cairo_font_face_nil; - } - - return font_face; -} - /** * cairo_set_font_size: * @cr: a #cairo_t @@ -2626,43 +2516,6 @@ BAIL: _cairo_set_error (cr, cr->status); } -/** - * cairo_get_scaled_font: - * @cr: a #cairo_t - * - * Gets the current scaled font for a #cairo_t. - * - * Return value: the current scaled font. This object is owned by - * cairo. To keep a reference to it, you must call - * cairo_scaled_font_reference(). - * - * This function never returns %NULL. If memory cannot be allocated, a - * special "nil" #cairo_scaled_font_t object will be returned on which - * cairo_scaled_font_status() returns %CAIRO_STATUS_NO_MEMORY. Using - * this nil object will cause its error state to propagate to other - * objects it is passed to, (for example, calling - * cairo_set_scaled_font() with a nil font will trigger an error that - * will shutdown the cairo_t object). - * - * Since: 1.4 - **/ -cairo_scaled_font_t * -cairo_get_scaled_font (cairo_t *cr) -{ - cairo_scaled_font_t *scaled_font; - - if (cr->status) - return (cairo_scaled_font_t *)&_cairo_scaled_font_nil; - - cr->status = _cairo_gstate_get_scaled_font (cr->gstate, &scaled_font); - if (cr->status) { - _cairo_set_error (cr, cr->status); - return (cairo_scaled_font_t *)&_cairo_scaled_font_nil; - } - - return scaled_font; -} - /** * cairo_text_extents: * @cr: a #cairo_t @@ -2782,9 +2635,9 @@ cairo_glyph_extents (cairo_t *cr, * * NOTE: The cairo_show_text() function call is part of what the cairo * designers call the "toy" text API. It is convenient for short demos - * and simple programs, but it is not expected to be adequate for - * serious text-using applications. See cairo_show_glyphs() for the - * "real" text display API in cairo. + * and simple programs, but it is not expected to be adequate for the + * most serious of text-using applications. See cairo_show_glyphs() + * for the "real" text display API in cairo. **/ void cairo_show_text (cairo_t *cr, const char *utf8) @@ -2834,16 +2687,6 @@ cairo_show_text (cairo_t *cr, const char *utf8) _cairo_set_error (cr, cr->status); } -/** - * cairo_show_glyphs: - * @cr: a cairo context - * @glyphs: array of glyphs to show - * @num_glyphs: number of glyphs to show - * - * A drawing operator that generates the shape from an array of glyphs, - * rendered according to the current font_face, font_size - * (font_matrix), and font_options. - **/ void cairo_show_glyphs (cairo_t *cr, const cairo_glyph_t *glyphs, int num_glyphs) { @@ -2858,35 +2701,10 @@ cairo_show_glyphs (cairo_t *cr, const cairo_glyph_t *glyphs, int num_glyphs) _cairo_set_error (cr, cr->status); } -/** - * cairo_text_path: - * @cr: a cairo context - * @utf8: a string of text encoded in UTF-8 - * - * Adds closed paths for text to the current path. The generated - * path if filled, achieves an effect similar to that of - * cairo_show_text(). - * - * Text conversion and positioning is done similar to cairo_show_text(). - * - * Like cairo_show_text(), After this call the current point is - * moved to the origin of where the next glyph would be placed in - * this same progression. That is, the current point will be at - * the origin of the final glyph offset by its advance values. - * This allows for chaining multiple calls to to cairo_text_path() - * without having to set current point in between. - * - * NOTE: The cairo_text_path() function call is part of what the cairo - * designers call the "toy" text API. It is convenient for short demos - * and simple programs, but it is not expected to be adequate for - * serious text-using applications. See cairo_glyph_path() for the - * "real" text path API in cairo. - **/ void cairo_text_path (cairo_t *cr, const char *utf8) { - cairo_text_extents_t extents; - cairo_glyph_t *glyphs = NULL, *last_glyph; + cairo_glyph_t *glyphs = NULL; int num_glyphs; double x, y; @@ -2899,32 +2717,16 @@ cairo_text_path (cairo_t *cr, const char *utf8) x, y, &glyphs, &num_glyphs); - if (cr->status) - goto BAIL; - - if (num_glyphs == 0) + if (cr->status) { + if (glyphs) + free (glyphs); + _cairo_set_error (cr, cr->status); return; + } cr->status = _cairo_gstate_glyph_path (cr->gstate, glyphs, num_glyphs, - cr->path); - - if (cr->status) - goto BAIL; - - last_glyph = &glyphs[num_glyphs - 1]; - cr->status = _cairo_gstate_glyph_extents (cr->gstate, - last_glyph, 1, - &extents); - - if (cr->status) - goto BAIL; - - x = last_glyph->x + extents.x_advance; - y = last_glyph->y + extents.y_advance; - cairo_move_to (cr, x, y); - - BAIL: + &cr->path); if (glyphs) free (glyphs); @@ -2932,16 +2734,6 @@ cairo_text_path (cairo_t *cr, const char *utf8) _cairo_set_error (cr, cr->status); } -/** - * cairo_glyph_path: - * @cr: a cairo context - * @glyphs: array of glyphs to show - * @num_glyphs: number of glyphs to show - * - * Adds closed paths for the glyphs to the current path. The generated - * path if filled, achieves an effect similar to that of - * cairo_show_glyphs(). - **/ void cairo_glyph_path (cairo_t *cr, const cairo_glyph_t *glyphs, int num_glyphs) { @@ -2950,7 +2742,7 @@ cairo_glyph_path (cairo_t *cr, const cairo_glyph_t *glyphs, int num_glyphs) cr->status = _cairo_gstate_glyph_path (cr->gstate, glyphs, num_glyphs, - cr->path); + &cr->path); if (cr->status) _cairo_set_error (cr, cr->status); } @@ -3026,7 +2818,7 @@ cairo_get_current_point (cairo_t *cr, double *x_ret, double *y_ret) cairo_fixed_t x_fixed, y_fixed; double x, y; - status = _cairo_path_fixed_get_current_point (cr->path, &x_fixed, &y_fixed); + status = _cairo_path_fixed_get_current_point (&cr->path, &x_fixed, &y_fixed); if (status == CAIRO_STATUS_NO_CURRENT_POINT) { x = 0.0; y = 0.0; @@ -3061,12 +2853,10 @@ cairo_get_fill_rule (cairo_t *cr) * cairo_get_line_width: * @cr: a cairo context * - * This function returns the current line width value exactly as set by + * Return value: the current line width value exactly as set by * cairo_set_line_width(). Note that the value is unchanged even if * the CTM has changed between the calls to cairo_set_line_width() and * cairo_get_line_width(). - * - * Return value: the current line width. **/ double cairo_get_line_width (cairo_t *cr) @@ -3218,7 +3008,7 @@ cairo_copy_path (cairo_t *cr) if (cr->status) return _cairo_path_create_in_error (cr->status); - return _cairo_path_create (cr->path, cr->gstate); + return _cairo_path_create (&cr->path, cr->gstate); } /** @@ -3260,7 +3050,7 @@ cairo_copy_path_flat (cairo_t *cr) if (cr->status) return _cairo_path_create_in_error (cr->status); - return _cairo_path_create_flat (cr->path, cr->gstate); + return _cairo_path_create_flat (&cr->path, cr->gstate); } /** diff --git a/gfx/cairo/cairo/src/cairo.h b/gfx/cairo/cairo/src/cairo.h index a80efde210e..779da17e5ee 100644 --- a/gfx/cairo/cairo/src/cairo.h +++ b/gfx/cairo/cairo/src/cairo.h @@ -72,7 +72,7 @@ cairo_version_string (void); * /* do something */ * } * - **/ + */ typedef int cairo_bool_t; /** @@ -80,13 +80,6 @@ typedef int cairo_bool_t; * * A #cairo_t contains the current state of the rendering device, * including coordinates of yet to be drawn shapes. - * - * Cairo contexts, as #cairo_t objects are named, are central to - * cairo and all drawing with cairo is always done to a #cairo_t - * object. - * - * Memory management of #cairo_t is done with - * cairo_reference() and cairo_destroy(). **/ typedef struct _cairo cairo_t; @@ -95,17 +88,13 @@ typedef struct _cairo cairo_t; * * A #cairo_surface_t represents an image, either as the destination * of a drawing operation or as source when drawing onto another - * surface. To draw to a #cairo_surface_t, create a cairo context - * with the surface as the target, using cairo_create(). - * - * There are different subtypes of #cairo_surface_t for + * surface. There are different subtypes of cairo_surface_t for * different drawing backends; for example, cairo_image_surface_create() * creates a bitmap image in memory. - * The type of a surface can be queried with cairo_surface_get_type(). * * Memory management of #cairo_surface_t is done with * cairo_surface_reference() and cairo_surface_destroy(). - **/ + */ typedef struct _cairo_surface cairo_surface_t; /** @@ -131,25 +120,6 @@ typedef struct _cairo_matrix { double x0; double y0; } cairo_matrix_t; -/** - * cairo_pattern_t: - * - * A #cairo_pattern_t represents a source when drawing onto a - * surface. There are different subtypes of #cairo_pattern_t, - * for different types of sources; for example, - * cairo_pattern_create_rgb() creates a pattern for a solid - * opaque color. - * - * Other than various cairo_pattern_create_type - * functions, some of the pattern types can be implicitly created - * using vairous cairo_set_source_type functions; - * for example cairo_set_source_rgb(). - * - * The type of a pattern can be queried with cairo_pattern_get_type(). - * - * Memory management of #cairo_pattern_t is done with - * cairo_pattern_reference() and cairo_pattern_destroy(). - **/ typedef struct _cairo_pattern cairo_pattern_t; /** @@ -159,7 +129,7 @@ typedef struct _cairo_pattern cairo_pattern_t; * #cairo_destroy_func_t the type of function which is called when a * data element is destroyed. It is passed the pointer to the data * element and should free any memory and resources allocated for it. - **/ + */ typedef void (*cairo_destroy_func_t) (void *data); /** @@ -171,7 +141,7 @@ typedef void (*cairo_destroy_func_t) (void *data); * and there is no need to initialize the object; only the unique * address of a #cairo_data_key_t object is used. Typically, you * would just use the address of a static #cairo_data_key_t object. - **/ + */ typedef struct _cairo_user_data_key { int unused; } cairo_user_data_key_t; @@ -249,7 +219,7 @@ typedef enum _cairo_status { * 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, @@ -271,7 +241,7 @@ typedef enum _cairo_content { * CAIRO_STATUS_WRITE_ERROR otherwise. * * Returns: the status code of the write operation - **/ + */ typedef cairo_status_t (*cairo_write_func_t) (void *closure, const unsigned char *data, unsigned int length); @@ -291,7 +261,7 @@ typedef cairo_status_t (*cairo_write_func_t) (void *closure, * CAIRO_STATUS_READ_ERROR otherwise. * * Returns: the status code of the read operation - **/ + */ typedef cairo_status_t (*cairo_read_func_t) (void *closure, unsigned char *data, unsigned int length); @@ -306,19 +276,6 @@ cairo_reference (cairo_t *cr); cairo_public void cairo_destroy (cairo_t *cr); -cairo_public unsigned int -cairo_get_reference_count (cairo_t *cr); - -cairo_public void * -cairo_get_user_data (cairo_t *cr, - const cairo_user_data_key_t *key); - -cairo_public cairo_status_t -cairo_set_user_data (cairo_t *cr, - const cairo_user_data_key_t *key, - void *user_data, - cairo_destroy_func_t destroy); - cairo_public void cairo_save (cairo_t *cr); @@ -445,7 +402,7 @@ cairo_set_line_width (cairo_t *cr, double width); * @CAIRO_LINE_CAP_ROUND: use a round ending, the center of the circle is the end point * @CAIRO_LINE_CAP_SQUARE: use squared ending, the center of the square is the end point * - * Specifies how to render the endpoint of a line when stroking. + * enumeration for style of line-endings **/ typedef enum _cairo_line_cap { CAIRO_LINE_CAP_BUTT, @@ -456,17 +413,6 @@ typedef enum _cairo_line_cap { cairo_public void cairo_set_line_cap (cairo_t *cr, cairo_line_cap_t line_cap); -/** - * cairo_line_join_t - * @CAIRO_LINE_JOIN_MITER: use a sharp (angled) corner, see - * cairo_set_miter_limit() - * @CAIRO_LINE_JOIN_ROUND: use a rounded join, the center of the circle is the - * joint point - * @CAIRO_LINE_JOIN_BEVEL: use a cut-off join, the join is cut off at half - * the line width from the joint point - * - * Specifies how to render the junction of two lines when stroking. - **/ typedef enum _cairo_line_join { CAIRO_LINE_JOIN_MITER, CAIRO_LINE_JOIN_ROUND, @@ -652,30 +598,23 @@ cairo_clip_extents (cairo_t *cr, /** * cairo_rectangle_t: - * @x: X coordinate of the left side of the rectangle - * @y: Y coordinate of the the top side of the rectangle - * @width: width of the rectangle - * @height: height of the rectangle - * + * * A data structure for holding a rectangle. * * Since: 1.4 - **/ + */ typedef struct _cairo_rectangle { double x, y, width, height; } cairo_rectangle_t; /** * cairo_rectangle_list_t: - * @status: Error status of the rectangle list - * @rectangles: Array containing the rectangles - * @num_rectangles: Number of rectangles in this list * * A data structure for holding a dynamically allocated * array of rectangles. * * Since: 1.4 - **/ + */ typedef struct _cairo_rectangle_list { cairo_status_t status; cairo_rectangle_t *rectangles; @@ -697,14 +636,7 @@ cairo_rectangle_list_destroy (cairo_rectangle_list_t *rectangle_list); * resolution. A cairo_scaled_font_t is most useful for low-level font * usage where a library or application wants to cache a reference * to a scaled font to speed up the computation of metrics. - * - * There are various types of scaled fonts, depending on the - * font backend they use. The type of a - * scaled font can be queried using cairo_scaled_font_get_type(). - * - * Memory management of #cairo_scaled_font_t is done with - * cairo_scaled_font_reference() and cairo_scaled_font_destroy(). - **/ + */ typedef struct _cairo_scaled_font cairo_scaled_font_t; /** @@ -716,14 +648,7 @@ typedef struct _cairo_scaled_font cairo_scaled_font_t; * directions) . A font face can be set on a #cairo_t by using * cairo_set_font_face(); the size and font matrix are set with * cairo_set_font_size() and cairo_set_font_matrix(). - * - * There are various types of font faces, depending on the - * font backend they use. The type of a - * font face can be queried using cairo_font_face_get_type(). - * - * Memory management of #cairo_font_face_t is done with - * cairo_font_face_reference() and cairo_font_face_destroy(). - **/ + */ typedef struct _cairo_font_face cairo_font_face_t; /** @@ -782,7 +707,7 @@ typedef struct { * doubled. They will change slightly due to hinting (so you can't * assume that metrics are independent of the transformation matrix), * but otherwise will remain unchanged. - **/ + */ typedef struct { double x_bearing; double y_bearing; @@ -832,7 +757,7 @@ typedef struct { * not be doubled. They will change slightly due to hinting (so you * can't assume that metrics are independent of the transformation * matrix), but otherwise will remain unchanged. - **/ + */ typedef struct { double ascent; double descent; @@ -841,27 +766,12 @@ typedef struct { double max_y_advance; } cairo_font_extents_t; -/** - * cairo_font_slant_t: - * @CAIRO_FONT_SLANT_NORMAL: Upright font style - * @CAIRO_FONT_SLANT_ITALIC: Italic font style - * @CAIRO_FONT_SLANT_OBLIQUE: Oblique font style - * - * Specifies variants of a font face based on their slant. - **/ typedef enum _cairo_font_slant { CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_SLANT_ITALIC, CAIRO_FONT_SLANT_OBLIQUE } cairo_font_slant_t; -/** - * cairo_font_weight_t: - * @CAIRO_FONT_WEIGHT_NORMAL: Normal font weight - * @CAIRO_FONT_WEIGHT_BOLD: Bold font weight - * - * Specifies variants of a font face based on their weight. - **/ typedef enum _cairo_font_weight { CAIRO_FONT_WEIGHT_NORMAL, CAIRO_FONT_WEIGHT_BOLD @@ -913,7 +823,7 @@ typedef enum _cairo_subpixel_order { * styles are supported by all font backends. * * New entries may be added in future versions. - **/ + */ typedef enum _cairo_hint_style { CAIRO_HINT_STYLE_DEFAULT, CAIRO_HINT_STYLE_NONE, @@ -934,33 +844,13 @@ typedef enum _cairo_hint_style { * device space. Doing this improves the consistency of * letter and line spacing, however it also means that text * will be laid out differently at different zoom factors. - **/ + */ typedef enum _cairo_hint_metrics { CAIRO_HINT_METRICS_DEFAULT, CAIRO_HINT_METRICS_OFF, CAIRO_HINT_METRICS_ON } cairo_hint_metrics_t; -/** - * cairo_font_options_t: - * - * An opaque structure holding all options that are used when - * rendering fonts. - * - * Individual features of a #cairo_font_options_t can be set or - * accessed using functions named - * cairo_font_options_set_feature_name and - * cairo_font_options_get_feature_name, like - * cairo_font_options_set_antialias() and - * cairo_font_options_get_antialias(). - * - * New features may be added to a #cairo_font_options_t in the - * future. For this reason, cairo_font_options_copy(), - * cairo_font_options_equal(), cairo_font_options_merge(), and - * cairo_font_options_hash() should be used to copy, check - * for equality, merge, or compute a hash value of - * #cairo_font_options_t objects. - **/ typedef struct _cairo_font_options cairo_font_options_t; cairo_public cairo_font_options_t * @@ -1037,30 +927,25 @@ cairo_public void cairo_get_font_options (cairo_t *cr, cairo_font_options_t *options); -cairo_public void -cairo_set_font_face (cairo_t *cr, cairo_font_face_t *font_face); - -cairo_public cairo_font_face_t * -cairo_get_font_face (cairo_t *cr); - cairo_public void cairo_set_scaled_font (cairo_t *cr, const cairo_scaled_font_t *scaled_font); -cairo_public cairo_scaled_font_t * -cairo_get_scaled_font (cairo_t *cr); - cairo_public void cairo_show_text (cairo_t *cr, const char *utf8); cairo_public void cairo_show_glyphs (cairo_t *cr, const cairo_glyph_t *glyphs, int num_glyphs); -cairo_public void -cairo_text_path (cairo_t *cr, const char *utf8); +cairo_public cairo_font_face_t * +cairo_get_font_face (cairo_t *cr); cairo_public void -cairo_glyph_path (cairo_t *cr, const cairo_glyph_t *glyphs, int num_glyphs); +cairo_font_extents (cairo_t *cr, + cairo_font_extents_t *extents); + +cairo_public void +cairo_set_font_face (cairo_t *cr, cairo_font_face_t *font_face); cairo_public void cairo_text_extents (cairo_t *cr, @@ -1074,8 +959,10 @@ cairo_glyph_extents (cairo_t *cr, cairo_text_extents_t *extents); cairo_public void -cairo_font_extents (cairo_t *cr, - cairo_font_extents_t *extents); +cairo_text_path (cairo_t *cr, const char *utf8); + +cairo_public void +cairo_glyph_path (cairo_t *cr, const cairo_glyph_t *glyphs, int num_glyphs); /* Generic identifier for a font style */ @@ -1085,9 +972,6 @@ cairo_font_face_reference (cairo_font_face_t *font_face); cairo_public void cairo_font_face_destroy (cairo_font_face_t *font_face); -cairo_public unsigned int -cairo_font_face_get_reference_count (cairo_font_face_t *font_face); - cairo_public cairo_status_t cairo_font_face_status (cairo_font_face_t *font_face); @@ -1126,7 +1010,7 @@ cairo_font_face_status (cairo_font_face_t *font_face); * New entries may be added in future versions. * * Since: 1.2 - **/ + */ typedef enum _cairo_font_type { CAIRO_FONT_TYPE_TOY, CAIRO_FONT_TYPE_FT, @@ -1161,25 +1045,12 @@ cairo_scaled_font_reference (cairo_scaled_font_t *scaled_font); cairo_public void cairo_scaled_font_destroy (cairo_scaled_font_t *scaled_font); -cairo_public unsigned int -cairo_scaled_font_get_reference_count (cairo_scaled_font_t *scaled_font); - cairo_public cairo_status_t cairo_scaled_font_status (cairo_scaled_font_t *scaled_font); cairo_public cairo_font_type_t cairo_scaled_font_get_type (cairo_scaled_font_t *scaled_font); -cairo_public void * -cairo_scaled_font_get_user_data (cairo_scaled_font_t *scaled_font, - const cairo_user_data_key_t *key); - -cairo_public cairo_status_t -cairo_scaled_font_set_user_data (cairo_scaled_font_t *scaled_font, - const cairo_user_data_key_t *key, - void *user_data, - cairo_destroy_func_t destroy); - cairo_public void cairo_scaled_font_extents (cairo_scaled_font_t *scaled_font, cairo_font_extents_t *extents); @@ -1257,17 +1128,6 @@ cairo_get_target (cairo_t *cr); cairo_public cairo_surface_t * cairo_get_group_target (cairo_t *cr); -/** - * cairo_path_data_type_t: - * @CAIRO_PATH_MOVE_TO: A move-to operation - * @CAIRO_PATH_LINE_TO: A line-to operation - * @CAIRO_PATH_CURVE_TO: A curve-to operation - * @CAIRO_PATH_CLOSE_PATH: A close-path operation - * - * #cairo_path_data_t is used to describe the type of one portion - * of a path when represented as a #cairo_path_t. - * See #cairo_path_data_t for details. - **/ typedef enum _cairo_path_data_type { CAIRO_PATH_MOVE_TO, CAIRO_PATH_LINE_TO, @@ -1289,7 +1149,8 @@ typedef enum _cairo_path_data_type { * the array, (one header followed by 0 or more points). The length * value of the header is the number of array elements for the current * portion including the header, (ie. length == 1 + # of points), and - * where the number of points for each element type is as follows: + * where the number of points for each element type must be as + * follows: * * * %CAIRO_PATH_MOVE_TO: 1 point @@ -1332,14 +1193,6 @@ typedef enum _cairo_path_data_type { * } * cairo_path_destroy (path); * - * - * As of cairo 1.4, cairo does not mind if there are more elements in - * a portion of the path than needed. Such elements can be used by - * users of the cairo API to hold extra values in the path data - * structure. For this reason, it is recommended that applications - * always use data->header.length to - * iterate over the path data, instead of hardcoding the number of - * elements for each element type. **/ typedef union _cairo_path_data_t cairo_path_data_t; union _cairo_path_data_t { @@ -1415,12 +1268,12 @@ cairo_surface_finish (cairo_surface_t *surface); cairo_public void cairo_surface_destroy (cairo_surface_t *surface); -cairo_public unsigned int -cairo_surface_get_reference_count (cairo_surface_t *surface); - cairo_public cairo_status_t cairo_surface_status (cairo_surface_t *surface); +cairo_public unsigned int +cairo_surface_get_reference_count (cairo_surface_t *surface); + /** * cairo_surface_type_t * @CAIRO_SURFACE_TYPE_IMAGE: The surface is of type image @@ -1458,7 +1311,7 @@ cairo_surface_status (cairo_surface_t *surface); * New entries may be added in future versions. * * Since: 1.2 - **/ + */ typedef enum _cairo_surface_type { CAIRO_SURFACE_TYPE_IMAGE, CAIRO_SURFACE_TYPE_PDF, @@ -1471,6 +1324,7 @@ typedef enum _cairo_surface_type { CAIRO_SURFACE_TYPE_BEOS, CAIRO_SURFACE_TYPE_DIRECTFB, CAIRO_SURFACE_TYPE_SVG, + CAIRO_SURFACE_TYPE_NQUARTZ, CAIRO_SURFACE_TYPE_OS2 } cairo_surface_type_t; @@ -1563,7 +1417,7 @@ cairo_surface_set_fallback_resolution (cairo_surface_t *surface, * image data. * * New entries may be added in future versions. - **/ + */ typedef enum _cairo_format { CAIRO_FORMAT_ARGB32, CAIRO_FORMAT_RGB24, @@ -1639,22 +1493,9 @@ cairo_pattern_reference (cairo_pattern_t *pattern); cairo_public void cairo_pattern_destroy (cairo_pattern_t *pattern); -cairo_public unsigned int -cairo_pattern_get_reference_count (cairo_pattern_t *pattern); - cairo_public cairo_status_t cairo_pattern_status (cairo_pattern_t *pattern); -cairo_public void * -cairo_pattern_get_user_data (cairo_pattern_t *pattern, - const cairo_user_data_key_t *key); - -cairo_public cairo_status_t -cairo_pattern_set_user_data (cairo_pattern_t *pattern, - const cairo_user_data_key_t *key, - void *user_data, - cairo_destroy_func_t destroy); - /** * cairo_pattern_type_t * @CAIRO_PATTERN_TYPE_SOLID: The pattern is a solid (uniform) @@ -1684,7 +1525,7 @@ cairo_pattern_set_user_data (cairo_pattern_t *pattern, * New entries may be added in future versions. * * Since: 1.2 - **/ + */ typedef enum _cairo_pattern_type { CAIRO_PATTERN_TYPE_SOLID, CAIRO_PATTERN_TYPE_SURFACE, @@ -1729,7 +1570,7 @@ cairo_pattern_get_matrix (cairo_pattern_t *pattern, * of a pattern will be drawn. * * New entries may be added in future versions. - **/ + */ typedef enum _cairo_extend { CAIRO_EXTEND_NONE, CAIRO_EXTEND_REPEAT, @@ -1836,6 +1677,12 @@ cairo_public void cairo_matrix_transform_point (const cairo_matrix_t *matrix, double *x, double *y); +cairo_public void +cairo_matrix_transform_bounding_box (const cairo_matrix_t *matrix, + double *x1, double *y1, + double *x2, double *y2, + cairo_bool_t *is_tight); + /* Functions to be used while debugging (not intended for use in production code) */ cairo_public void cairo_debug_reset_static_data (void); diff --git a/gfx/cairo/cairo/src/cairoint.h b/gfx/cairo/cairo/src/cairoint.h index d50a7892e72..28c39b31eb8 100644 --- a/gfx/cairo/cairo/src/cairoint.h +++ b/gfx/cairo/cairo/src/cairoint.h @@ -73,7 +73,7 @@ CAIRO_BEGIN_DECLS -#if __GNUC__ >= 3 && defined(__ELF__) && !defined(__sun) +#if __GNUC__ >= 3 && defined(__ELF__) # 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 @@ -102,7 +102,7 @@ CAIRO_BEGIN_DECLS #endif /* slim_internal.h */ -#if (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 3)) && defined(__ELF__) && !defined(__sun) +#if (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 3)) && defined(__ELF__) #define cairo_private __attribute__((__visibility__("hidden"))) #elif defined(__SUNPRO_C) && (__SUNPRO_C >= 0x550) #define cairo_private __hidden @@ -134,20 +134,13 @@ CAIRO_BEGIN_DECLS #define __attribute__(x) #endif -#if MOZILLA_CAIRO_NOT_DEFINED +#if 0 #if HAVE_PTHREAD_H # include # define CAIRO_MUTEX_DECLARE(name) static pthread_mutex_t name = PTHREAD_MUTEX_INITIALIZER -# define CAIRO_MUTEX_DECLARE_GLOBAL(name) pthread_mutex_t name = PTHREAD_MUTEX_INITIALIZER +#define CAIRO_MUTEX_DECLARE_GLOBAL(name) pthread_mutex_t name = PTHREAD_MUTEX_INITIALIZER # define CAIRO_MUTEX_LOCK(name) pthread_mutex_lock (&name) # define CAIRO_MUTEX_UNLOCK(name) pthread_mutex_unlock (&name) -typedef pthread_mutex_t cairo_mutex_t; -#define CAIRO_MUTEX_INIT(mutex) do { \ - pthread_mutex_t tmp_mutex = PTHREAD_MUTEX_INITIALIZER; \ - memcpy (mutex, &tmp_mutex, sizeof (tmp_mutex)); \ -} while (0) -# define CAIRO_MUTEX_FINI(mutex) pthread_mutex_destroy (mutex) -# define CAIRO_MUTEX_NIL_INITIALIZER PTHREAD_MUTEX_INITIALIZER #endif #if !defined(CAIRO_MUTEX_DECLARE) && defined CAIRO_HAS_WIN32_SURFACE @@ -167,10 +160,6 @@ typedef pthread_mutex_t cairo_mutex_t; # define CAIRO_MUTEX_DECLARE_GLOBAL(name) extern LPCRITICAL_SECTION name; # define CAIRO_MUTEX_LOCK(name) EnterCriticalSection (&name) # define CAIRO_MUTEX_UNLOCK(name) LeaveCriticalSection (&name) -typedef CRITICAL_SECTION cairo_mutex_t; -# define CAIRO_MUTEX_INIT(mutex) InitializeCriticalSection (mutex) -# define CAIRO_MUTEX_FINI(mutex) DeleteCriticalSection (mutex) -# define CAIRO_MUTEX_NIL_INITIALIZER { 0 } #endif #if defined(__OS2__) && !defined(CAIRO_MUTEX_DECLARE) @@ -182,10 +171,6 @@ typedef CRITICAL_SECTION cairo_mutex_t; # 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) -typedef HMTX cairo_mutex_t; -# define CAIRO_MUTEX_INIT(mutex) DosCreateMutexSem (NULL, mutex, 0L, FALSE) -# define CAIRO_MUTEX_FINI(mutex) DosCloseMutexSem (*(mutex)) -# define CAIRO_MUTEX_NIL_INITIALIZER 0 #endif #if !defined(CAIRO_MUTEX_DECLARE) && defined CAIRO_HAS_BEOS_SURFACE @@ -196,29 +181,14 @@ cairo_private void _cairo_beos_unlock(void*); # define CAIRO_MUTEX_DECLARE_GLOBAL(name) extern void* name; # define CAIRO_MUTEX_LOCK(name) _cairo_beos_lock (&name) # define CAIRO_MUTEX_UNLOCK(name) _cairo_beos_unlock (&name) -# error "XXX: Someone who understands BeOS needs to add definitions for" \ - " cairo_mutex_t, CAIRO_MUTEX_INIT, and CAIRO_MUTEX_FINI," \ - " to cairoint.h" -typedef ??? cairo_mutex_t; -# define CAIRO_MUTEX_INIT(mutex) ??? -# define CAIRO_MUTEX_FINI(mutex) ??? -# define CAIRO_MUTEX_NIL_INITIALIZER {} #endif -#endif /* MOZILLA_CAIRO_NOT_REACHED */ +#endif #ifndef CAIRO_MUTEX_DECLARE -#if MOZILLA_CAIRO_NOT_DEFINED -# error "No mutex declarations. Cairo will not work with multiple threads." \ - "(Remove this #error directive to acknowledge & accept this limitation)." -#endif -typedef void *cairo_mutex_t; # define CAIRO_MUTEX_DECLARE(name) # define CAIRO_MUTEX_DECLARE_GLOBAL(name) # define CAIRO_MUTEX_LOCK(name) # define CAIRO_MUTEX_UNLOCK(name) -#define CAIRO_MUTEX_INIT(mutex) (*(mutex) = 0) -#define CAIRO_MUTEX_FINI(mutex) -#define CAIRO_MUTEX_NIL_INITIALIZER 0 #endif #undef MIN @@ -239,18 +209,6 @@ typedef void *cairo_mutex_t; #define M_PI 3.14159265358979323846 #endif -#ifndef MOZILLA_CAIRO_NOT_DEFINED -#ifndef INT32_MAX -# ifdef INT_MAX -# define INT32_MAX INT_MAX -# define INT32_MIN INT_MIN -# else -# define INT32_MAX 2147483647 -# define INT32_MIN (-2147483647 - 1) -# endif -#endif -#endif - /* Size in bytes of buffer to use off the stack per functions. * Mostly used by text functions. For larger allocations, they'll * malloc(). */ @@ -292,41 +250,6 @@ typedef cairo_fixed_16_16_t cairo_fixed_t; #define CAIRO_BITSWAP8_IF_LITTLE_ENDIAN(c) CAIRO_BITSWAP8(c) #endif -#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 - #include "cairo-hash-private.h" #include "cairo-cache-private.h" @@ -441,14 +364,15 @@ typedef struct _cairo_edge { } cairo_edge_t; typedef struct _cairo_polygon { - cairo_point_t first_point; - cairo_point_t current_point; - cairo_bool_t has_current_point; - int num_edges; int edges_size; cairo_edge_t *edges; - cairo_edge_t edges_embedded[8]; + + cairo_point_t first_point; + cairo_point_t current_point; + int has_current_point; + + int closed; } cairo_polygon_t; typedef struct _cairo_spline { @@ -460,7 +384,6 @@ typedef struct _cairo_spline { int num_points; int points_size; cairo_point_t *points; - cairo_point_t points_embedded[8]; } cairo_spline_t; typedef struct _cairo_pen_vertex { @@ -600,43 +523,12 @@ typedef struct _cairo_scaled_glyph { #define _cairo_scaled_glyph_set_index(g,i) ((g)->cache_entry.hash = (i)) struct _cairo_scaled_font { - /* For most cairo objects, the rule for multiple threads is that - * the user is responsible for any locking if the same object is - * manipulated from multiple threads simultaneously. - * - * However, with the caching that cairo does for scaled fonts, a - * user can easily end up with the same cairo_scaled_font object - * being manipulated from multiple threads without the user ever - * being aware of this, (and in fact, unable to control it). - * - * So, as a special exception, the cairo implementation takes care - * of all locking needed for cairo_scaled_font_t. Most of what is - * in the scaled font is immutable, (which is what allows for the - * sharing in the first place). The things that are modified and - * the locks protecting them are as follows: - * - * 1. The reference count (scaled_font->ref_count) - * - * Modifications to the reference count are protected by the - * _cairo_scaled_font_map_mutex. This is because the reference - * count of a scaled font is intimately related with the font - * map itself, (and the magic holdovers array). - * - * 2. The cache of glyphs (scaled_font->glyphs) - * 3. The backend private data (scaled_font->surface_backend, - * scaled_font->surface_private) - * - * Modifications to these fields are protected with locks on - * scaled_font->mutex in the generic scaled_font code. - */ - /* must be first to be stored in a hash table */ cairo_hash_entry_t hash_entry; /* useful bits for _cairo_scaled_font_nil */ cairo_status_t status; unsigned int ref_count; - cairo_user_data_array_t user_data; /* hash key members */ cairo_font_face_t *font_face; /* may be NULL */ @@ -647,10 +539,6 @@ struct _cairo_scaled_font { /* "live" scaled_font members */ cairo_matrix_t scale; /* font space => device space */ cairo_font_extents_t extents; /* user space */ - - /* The mutex protects modification to all subsequent fields. */ - cairo_mutex_t mutex; - cairo_cache_t *glyphs; /* glyph index -> cairo_scaled_glyph_t */ /* @@ -710,19 +598,6 @@ typedef enum _cairo_scaled_glyph_info { CAIRO_SCALED_GLYPH_INFO_PATH = (1 << 2) } cairo_scaled_glyph_info_t; -typedef struct _cairo_scaled_font_subset { - cairo_scaled_font_t *scaled_font; - unsigned int font_id; - unsigned int subset_id; - - /* Index of glyphs array is subset_glyph_index. - * Value of glyphs array is scaled_font_glyph_index. - */ - unsigned long *glyphs; - unsigned long *to_unicode; - unsigned int num_glyphs; -} cairo_scaled_font_subset_t; - struct _cairo_scaled_font_backend { cairo_font_type_t type; @@ -776,11 +651,6 @@ struct _cairo_scaled_font_backend { long offset, unsigned char *buffer, unsigned long *length); - - void - (*map_glyphs_to_unicode)(void *scaled_font, - cairo_scaled_font_subset_t *font_subset); - }; struct _cairo_font_face_backend { @@ -1172,14 +1042,12 @@ typedef enum { #define CAIRO_FILTER_DEFAULT CAIRO_FILTER_BEST struct _cairo_pattern { - cairo_pattern_type_t type; - unsigned int ref_count; - cairo_status_t status; - cairo_user_data_array_t user_data; - - cairo_matrix_t matrix; - cairo_filter_t filter; - cairo_extend_t extend; + cairo_pattern_type_t type; + unsigned int ref_count; + cairo_status_t status; + cairo_matrix_t matrix; + cairo_filter_t filter; + cairo_extend_t extend; }; typedef struct _cairo_solid_pattern { @@ -1198,10 +1066,8 @@ typedef struct _cairo_surface_pattern { typedef struct _cairo_gradient_pattern { cairo_pattern_t base; - unsigned int n_stops; - unsigned int stops_size; pixman_gradient_stop_t *stops; - pixman_gradient_stop_t stops_embedded[2]; + unsigned int n_stops; } cairo_gradient_pattern_t; typedef struct _cairo_linear_pattern { @@ -1244,12 +1110,10 @@ typedef struct _cairo_surface_attributes { typedef struct _cairo_traps { cairo_status_t status; - cairo_box_t extents; - + cairo_trapezoid_t *traps; int num_traps; int traps_size; - cairo_trapezoid_t *traps; - cairo_trapezoid_t traps_embedded[1]; + cairo_box_t extents; } cairo_traps_t; #define CAIRO_FONT_SLANT_DEFAULT CAIRO_FONT_SLANT_NORMAL @@ -1332,19 +1196,15 @@ cairo_private int _cairo_fixed_integer_ceil (cairo_fixed_t f); /* cairo_gstate.c */ -cairo_private cairo_status_t -_cairo_gstate_init (cairo_gstate_t *gstate, - cairo_surface_t *target); - -cairo_private void -_cairo_gstate_fini (cairo_gstate_t *gstate); - cairo_private cairo_gstate_t * -_cairo_gstate_clone (cairo_gstate_t *gstate); +_cairo_gstate_create (cairo_surface_t *target); cairo_private void _cairo_gstate_destroy (cairo_gstate_t *gstate); +cairo_private cairo_gstate_t * +_cairo_gstate_clone (cairo_gstate_t *gstate); + cairo_private cairo_bool_t _cairo_gstate_is_redirected (cairo_gstate_t *gstate); @@ -1560,10 +1420,6 @@ cairo_private cairo_status_t _cairo_gstate_get_font_face (cairo_gstate_t *gstate, cairo_font_face_t **font_face); -cairo_private cairo_status_t -_cairo_gstate_get_scaled_font (cairo_gstate_t *gstate, - cairo_scaled_font_t **scaled_font); - cairo_private cairo_status_t _cairo_gstate_get_font_extents (cairo_gstate_t *gstate, cairo_font_extents_t *extents); @@ -1611,9 +1467,6 @@ _cairo_stock_color (cairo_stock_t stock); #define CAIRO_COLOR_BLACK _cairo_stock_color (CAIRO_STOCK_BLACK) #define CAIRO_COLOR_TRANSPARENT _cairo_stock_color (CAIRO_STOCK_TRANSPARENT) -cairo_private uint16_t -_cairo_color_double_to_short (double d); - cairo_private void _cairo_color_init (cairo_color_t *color); @@ -1652,15 +1505,11 @@ _cairo_scaled_font_freeze_cache (cairo_scaled_font_t *scaled_font); cairo_private void _cairo_scaled_font_thaw_cache (cairo_scaled_font_t *scaled_font); -cairo_private void -_cairo_scaled_font_reset_cache (cairo_scaled_font_t *scaled_font); - cairo_private void _cairo_scaled_font_set_error (cairo_scaled_font_t *scaled_font, cairo_status_t status); extern const cairo_private cairo_font_face_t _cairo_font_face_nil; -extern const cairo_private cairo_scaled_font_t _cairo_scaled_font_nil; cairo_private void _cairo_font_face_init (cairo_font_face_t *font_face, @@ -1911,7 +1760,6 @@ _cairo_stroke_style_fini (cairo_stroke_style_t *style); extern const cairo_private cairo_surface_t _cairo_surface_nil; extern const cairo_private cairo_surface_t _cairo_surface_nil_read_error; -extern const cairo_private cairo_surface_t _cairo_surface_nil_write_error; extern const cairo_private cairo_surface_t _cairo_surface_nil_file_not_found; cairo_private void @@ -2337,12 +2185,6 @@ _cairo_matrix_get_affine (const cairo_matrix_t *matrix, double *xy, double *yy, double *x0, double *y0); -cairo_private void -_cairo_matrix_transform_bounding_box (const cairo_matrix_t *matrix, - double *x1, double *y1, - double *x2, double *y2, - cairo_bool_t *is_tight); - cairo_private void _cairo_matrix_compute_determinant (const cairo_matrix_t *matrix, double *det); @@ -2578,6 +2420,7 @@ 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_transform_bounding_box); slim_hidden_proto (cairo_matrix_translate); slim_hidden_proto (cairo_move_to); slim_hidden_proto (cairo_new_path); @@ -2598,7 +2441,6 @@ 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_scale); slim_hidden_proto (cairo_scaled_font_create); slim_hidden_proto (cairo_scaled_font_destroy); slim_hidden_proto (cairo_scaled_font_extents); @@ -2625,13 +2467,8 @@ 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_version_string); - -#if CAIRO_HAS_PNG_FUNCTIONS - slim_hidden_proto (cairo_surface_write_to_png_stream); - -#endif +slim_hidden_proto (cairo_version_string); CAIRO_END_DECLS diff --git a/gfx/cairo/cairo/src/test-fallback-surface.c b/gfx/cairo/cairo/src/test-fallback-surface.c index 21ee19077fb..479c8ef62e5 100644 --- a/gfx/cairo/cairo/src/test-fallback-surface.c +++ b/gfx/cairo/cairo/src/test-fallback-surface.c @@ -64,10 +64,10 @@ typedef struct _test_fallback_surface { const cairo_private cairo_surface_backend_t test_fallback_surface_backend; -slim_hidden_proto (_cairo_test_fallback_surface_create); +slim_hidden_proto (_test_fallback_surface_create); cairo_surface_t * -_cairo_test_fallback_surface_create (cairo_content_t content, +_test_fallback_surface_create (cairo_content_t content, int width, int height) { @@ -91,7 +91,7 @@ _cairo_test_fallback_surface_create (cairo_content_t content, return &surface->base; } -slim_hidden_def (_cairo_test_fallback_surface_create); +slim_hidden_def (_test_fallback_surface_create); static cairo_surface_t * _test_fallback_surface_create_similar (void *abstract_surface, @@ -101,7 +101,7 @@ _test_fallback_surface_create_similar (void *abstract_surface, { assert (CAIRO_CONTENT_VALID (content)); - return _cairo_test_fallback_surface_create (content, + return _test_fallback_surface_create (content, width, height); } diff --git a/gfx/cairo/cairo/src/test-fallback-surface.h b/gfx/cairo/cairo/src/test-fallback-surface.h index 744b303a1e0..25603072e90 100644 --- a/gfx/cairo/cairo/src/test-fallback-surface.h +++ b/gfx/cairo/cairo/src/test-fallback-surface.h @@ -41,7 +41,7 @@ CAIRO_BEGIN_DECLS cairo_surface_t * -_cairo_test_fallback_surface_create (cairo_content_t content, +_test_fallback_surface_create (cairo_content_t content, int width, int height); diff --git a/gfx/cairo/cairo/src/test-meta-surface.c b/gfx/cairo/cairo/src/test-meta-surface.c index 6c5877971ed..7939b6e93fc 100644 --- a/gfx/cairo/cairo/src/test-meta-surface.c +++ b/gfx/cairo/cairo/src/test-meta-surface.c @@ -68,7 +68,7 @@ static cairo_int_status_t _test_meta_surface_show_page (void *abstract_surface); cairo_surface_t * -_cairo_test_meta_surface_create (cairo_content_t content, +_test_meta_surface_create (cairo_content_t content, int width, int height) { @@ -252,27 +252,12 @@ _test_meta_surface_show_glyphs (void *abstract_surface, cairo_scaled_font_t *scaled_font) { test_meta_surface_t *surface = abstract_surface; - cairo_int_status_t status; surface->image_reflects_meta = FALSE; - /* Since this is a "wrapping" surface, we're calling back into - * _cairo_surface_show_glyphs from within a call to the same. - * Since _cairo_surface_show_glyphs acquires a mutex, we release - * and re-acquire the mutex around this nested call. - * - * Yes, this is ugly, but we consider it pragmatic as compared to - * adding locking code to all 18 surface-backend-specific - * show_glyphs functions, (which would get less testing and likely - * lead to bugs). - */ - CAIRO_MUTEX_UNLOCK (scaled_font->mutex); - status = _cairo_surface_show_glyphs (surface->meta, op, source, - glyphs, num_glyphs, - scaled_font); - CAIRO_MUTEX_LOCK (scaled_font->mutex); - - return status; + return _cairo_surface_show_glyphs (surface->meta, op, source, + glyphs, num_glyphs, + scaled_font); } static cairo_surface_t * diff --git a/gfx/cairo/cairo/src/test-meta-surface.h b/gfx/cairo/cairo/src/test-meta-surface.h index c036bb9c89c..4022ab7ffee 100644 --- a/gfx/cairo/cairo/src/test-meta-surface.h +++ b/gfx/cairo/cairo/src/test-meta-surface.h @@ -41,7 +41,7 @@ CAIRO_BEGIN_DECLS cairo_surface_t * -_cairo_test_meta_surface_create (cairo_content_t content, +_test_meta_surface_create (cairo_content_t content, int width, int height); diff --git a/gfx/cairo/cairo/src/test-paginated-surface.c b/gfx/cairo/cairo/src/test-paginated-surface.c index d82749f69d9..544efcf5a91 100644 --- a/gfx/cairo/cairo/src/test-paginated-surface.c +++ b/gfx/cairo/cairo/src/test-paginated-surface.c @@ -61,7 +61,7 @@ static const cairo_surface_backend_t test_paginated_surface_backend; static const cairo_paginated_surface_backend_t test_paginated_surface_paginated_backend; cairo_surface_t * -_cairo_test_paginated_surface_create_for_data (unsigned char *data, +_test_paginated_surface_create_for_data (unsigned char *data, cairo_content_t content, int width, int height, @@ -233,27 +233,12 @@ _test_paginated_surface_show_glyphs (void *abstract_surface, cairo_scaled_font_t *scaled_font) { test_paginated_surface_t *surface = abstract_surface; - cairo_int_status_t status; if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE) return CAIRO_STATUS_SUCCESS; - /* Since this is a "wrapping" surface, we're calling back into - * _cairo_surface_show_glyphs from within a call to the same. - * Since _cairo_surface_show_glyphs acquires a mutex, we release - * and re-acquire the mutex around this nested call. - * - * Yes, this is ugly, but we consider it pragmatic as compared to - * adding locking code to all 18 surface-backend-specific - * show_glyphs functions, (which would get less testing and likely - * lead to bugs). - */ - CAIRO_MUTEX_UNLOCK (scaled_font->mutex); - status = _cairo_surface_show_glyphs (surface->target, op, source, - glyphs, num_glyphs, scaled_font); - CAIRO_MUTEX_LOCK (scaled_font->mutex); - - return status; + return _cairo_surface_show_glyphs (surface->target, op, source, + glyphs, num_glyphs, scaled_font); } static void diff --git a/gfx/cairo/cairo/src/test-paginated-surface.h b/gfx/cairo/cairo/src/test-paginated-surface.h index 4879cfcd100..df5500290b4 100644 --- a/gfx/cairo/cairo/src/test-paginated-surface.h +++ b/gfx/cairo/cairo/src/test-paginated-surface.h @@ -41,7 +41,7 @@ CAIRO_BEGIN_DECLS cairo_surface_t * -_cairo_test_paginated_surface_create_for_data (unsigned char *data, +_test_paginated_surface_create_for_data (unsigned char *data, cairo_content_t content, int width, int height, diff --git a/gfx/cairo/libpixman/src/fbcompose.c b/gfx/cairo/libpixman/src/fbcompose.c index ef0be03567f..3ec25830d7e 100644 --- a/gfx/cairo/libpixman/src/fbcompose.c +++ b/gfx/cairo/libpixman/src/fbcompose.c @@ -28,9 +28,7 @@ #endif #include "pixman-xserver-compat.h" #include "fbpict.h" -#ifndef MOZILLA_CAIRO_NOT_DEFINED #include "fbmmx.h" -#endif /* MOZCAIRO */ #ifdef RENDER @@ -40,7 +38,6 @@ #define _USE_MATH_DEFINES #endif -#include #include #ifndef M_PI @@ -2743,13 +2740,12 @@ typedef struct CARD32 right_rb; int32_t left_x; int32_t right_x; + int32_t width_x; int32_t stepper; pixman_gradient_stop_t *stops; int num_stops; unsigned int spread; - - int need_reset; } GradientWalker; static void @@ -2761,14 +2757,13 @@ _gradient_walker_init (GradientWalker *walker, walker->stops = pGradient->gradient.stops; walker->left_x = 0; walker->right_x = 0x10000; + walker->width_x = 0; /* will force a reset */ walker->stepper = 0; walker->left_ag = 0; walker->left_rb = 0; walker->right_ag = 0; walker->right_rb = 0; walker->spread = spread; - - walker->need_reset = TRUE; } static void @@ -2858,15 +2853,13 @@ _gradient_walker_reset (GradientWalker *walker, pixman_color_t *tmp_c; int32_t tmp_x; - tmp_x = 0x10000 - right_x; - right_x = 0x10000 - left_x; + tmp_x = 0x20000 - right_x; + right_x = 0x20000 - left_x; left_x = tmp_x; tmp_c = right_c; right_c = left_c; left_c = tmp_c; - - x = 0x10000 - x; } left_x += (pos - x); right_x += (pos - x); @@ -2900,28 +2893,27 @@ _gradient_walker_reset (GradientWalker *walker, walker->left_x = left_x; walker->right_x = right_x; + walker->width_x = right_x - left_x; walker->left_ag = ((left_c->alpha >> 8) << 16) | (left_c->green >> 8); walker->left_rb = ((left_c->red & 0xff00) << 8) | (left_c->blue >> 8); walker->right_ag = ((right_c->alpha >> 8) << 16) | (right_c->green >> 8); walker->right_rb = ((right_c->red & 0xff00) << 8) | (right_c->blue >> 8); - if ( walker->left_x == walker->right_x || + if ( walker->width_x == 0 || ( walker->left_ag == walker->right_ag && walker->left_rb == walker->right_rb ) ) { + walker->width_x = 1; walker->stepper = 0; } else { - int32_t width = right_x - left_x; - walker->stepper = ((1 << 24) + width/2)/width; + walker->stepper = ((1 << 24) + walker->width_x/2)/walker->width_x; } - - walker->need_reset = FALSE; } #define GRADIENT_WALKER_NEED_RESET(w,x) \ - ( (w)->need_reset || (x) < (w)->left_x || (x) >= (w)->right_x) + ( (x) < (w)->left_x || (x) - (w)->left_x >= (w)->width_x ) /* the following assumes that GRADIENT_WALKER_NEED_RESET(w,x) is FALSE */ static CARD32 @@ -2956,6 +2948,8 @@ _gradient_walker_pixel (GradientWalker *walker, return (color | (t1 & 0xff00ff) | (t2 & 0xff00)); } + + static void fbFetchSourcePict(PicturePtr pict, int x, int y, int width, CARD32 *buffer, CARD32 *mask, CARD32 maskBits) { SourcePictPtr pGradient = pict->pSourcePict; @@ -3087,128 +3081,13 @@ static void fbFetchSourcePict(PicturePtr pict, int x, int y, int width, CARD32 * } } } else { - -/* - * In the radial gradient problem we are given two circles (c₁,r₁) and - * (c₂,r₂) that define the gradient itself. Then, for any point p, we - * must compute the value(s) of t within [0.0, 1.0] representing the - * circle(s) that would color the point. - * - * There are potentially two values of t since the point p can be - * colored by both sides of the circle, (which happens whenever one - * circle is not entirely contained within the other). - * - * If we solve for a value of t that is outside of [0.0, 1.0] then we - * use the extend mode (NONE, REPEAT, REFLECT, or PAD) to map to a - * value within [0.0, 1.0]. - * - * Here is an illustration of the problem: - * - * p₂ - * p • - * • ╲ - * · ╲r₂ - * p₁ · ╲ - * • θ╲ - * ╲ ╌╌• - * ╲r₁ · c₂ - * θ╲ · - * ╌╌• - * c₁ - * - * Given (c₁,r₁), (c₂,r₂) and p, we must find an angle θ such that two - * points p₁ and p₂ on the two circles are collinear with p. Then, the - * desired value of t is the ratio of the length of p₁p to the length - * of p₁p₂. - * - * So, we have six unknown values: (p₁x, p₁y), (p₂x, p₂y), θ and t. - * We can also write six equations that constrain the problem: - * - * Point p₁ is a distance r₁ from c₁ at an angle of θ: - * - * 1. p₁x = c₁x + r₁·cos θ - * 2. p₁y = c₁y + r₁·sin θ - * - * Point p₂ is a distance r₂ from c₂ at an angle of θ: - * - * 3. p₂x = c₂x + r2·cos θ - * 4. p₂y = c₂y + r2·sin θ - * - * Point p lies at a fraction t along the line segment p₁p₂: - * - * 5. px = t·p₂x + (1-t)·p₁x - * 6. py = t·p₂y + (1-t)·p₁y - * - * To solve, first subtitute 1-4 into 5 and 6: - * - * px = t·(c₂x + r₂·cos θ) + (1-t)·(c₁x + r₁·cos θ) - * py = t·(c₂y + r₂·sin θ) + (1-t)·(c₁y + r₁·sin θ) - * - * Then solve each for cos θ and sin θ expressed as a function of t: - * - * cos θ = (-(c₂x - c₁x)·t + (px - c₁x)) / ((r₂-r₁)·t + r₁) - * sin θ = (-(c₂y - c₁y)·t + (py - c₁y)) / ((r₂-r₁)·t + r₁) - * - * To simplify this a bit, we define new variables for several of the - * common terms as shown below: - * - * p₂ - * p • - * • ╲ - * · ┆ ╲r₂ - * p₁ · ┆ ╲ - * • pdy┆ ╲ - * ╲ ┆ •c₂ - * ╲r₁ ┆ · ┆ - * ╲ ·┆ ┆cdy - * •╌╌╌╌┴╌╌╌╌╌╌╌┘ - * c₁ pdx cdx - * - * cdx = (c₂x - c₁x) - * cdy = (c₂y - c₁y) - * dr = r₂-r₁ - * pdx = px - c₁x - * pdy = py - c₁y - * - * Note that cdx, cdy, and dr do not depend on point p at all, so can - * be pre-computed for the entire gradient. The simplifed equations - * are now: - * - * cos θ = (-cdx·t + pdx) / (dr·t + r₁) - * sin θ = (-cdy·t + pdy) / (dr·t + r₁) - * - * Finally, to get a single function of t and eliminate the last - * unknown θ, we use the identity sin²θ + cos²θ = 1. First, square - * each equation, (we knew a quadratic was coming since it must be - * possible to obtain two solutions in some cases): - * - * cos²θ = (cdx²t² - 2·cdx·pdx·t + pdx²) / (dr²·t² + 2·r₁·dr·t + r₁²) - * sin²θ = (cdy²t² - 2·cdy·pdy·t + pdy²) / (dr²·t² + 2·r₁·dr·t + r₁²) - * - * Then add both together, set the result equal to 1, and express as a - * standard quadratic equation in t of the form At² + Bt + C = 0 - * - * (cdx² + cdy² - dr²)·t² - 2·(cdx·pdx + cdy·pdy + r₁·dr)·t + (pdx² + pdy² - r₁²) = 0 - * - * In other words: - * - * A = cdx² + cdy² - dr² - * B = -2·(pdx·cdx + pdy·cdy + r₁·dr) - * C = pdx² + pdy² - r₁² - * - * And again, notice that A does not depend on p, so can be - * precomputed. From here we just use the quadratic formula to solve - * for t: - * - * t = (-2·B ± ⎷(B² - 4·A·C)) / 2·A - */ /* radial or conical */ Bool projective = FALSE; double cx = 1.; double cy = 0.; double cz = 0.; - double rx = x + 0.5; - double ry = y + 0.5; + double rx = x; + double ry = y; double rz = 1.; if (pict->transform) { @@ -3230,36 +3109,23 @@ static void fbFetchSourcePict(PicturePtr pict, int x, int y, int width, CARD32 * } if (pGradient->type == SourcePictTypeRadial) { - pixman_radial_gradient_image_t *radial; - radial = &pGradient->radial; if (!projective) { + rx -= pGradient->radial.fx; + ry -= pGradient->radial.fy; + while (buffer < end) { + double b, c, det, s; + if (!mask || *mask++ & maskBits) { - double pdx, pdy; - double B, C; - double det; - double c1x = xFixedToDouble (radial->c1.x); - double c1y = xFixedToDouble (radial->c1.y); - double r1 = xFixedToDouble (radial->c1.radius); - xFixed_48_16 t; + xFixed_48_16 t; - pdx = rx - c1x; - pdy = ry - c1y; + b = 2*(rx*pGradient->radial.dx + ry*pGradient->radial.dy); + c = -(rx*rx + ry*ry); + det = (b * b) - (4 * pGradient->radial.a * c); + s = (-b + sqrt(det))/(2. * pGradient->radial.a); - B = -2 * ( pdx * radial->cdx - + pdy * radial->cdy - + r1 * radial->dr); - C = (pdx * pdx + pdy * pdy - r1 * r1); - - det = (B * B) - (4 * radial->A * C); - if (det < 0.0) - det = 0.0; - - if (radial->A < 0) - t = (xFixed_48_16) ((- B - sqrt(det)) / (2.0 * radial->A) * 65536); - else - t = (xFixed_48_16) ((- B + sqrt(det)) / (2.0 * radial->A) * 65536); + t = (xFixed_48_16)((s*pGradient->radial.m + pGradient->radial.b)*65536); *buffer = _gradient_walker_pixel (&walker, t); } @@ -3268,12 +3134,35 @@ static void fbFetchSourcePict(PicturePtr pict, int x, int y, int width, CARD32 * ry += cy; } } else { - /* In cairo, we don't have projective transformed - * radial gradients---so I'm not going to bother - * implementing something untested and broken - * here. Instead, someone trying to get this code into - * shape for use in the X server can fix this here. */ - assert (0); + while (buffer < end) { + double x, y; + double b, c, det, s; + + if (!mask || *mask++ & maskBits) + { + xFixed_48_16 t; + + if (rz != 0) { + x = rx/rz; + y = ry/rz; + } else { + x = y = 0.; + } + x -= pGradient->radial.fx; + y -= pGradient->radial.fy; + b = 2*(x*pGradient->radial.dx + y*pGradient->radial.dy); + c = -(x*x + y*y); + det = (b * b) - (4 * pGradient->radial.a * c); + s = (-b + sqrt(det))/(2. * pGradient->radial.a); + t = (xFixed_48_16)((s*pGradient->radial.m + pGradient->radial.b)*65536); + + *buffer = _gradient_walker_pixel (&walker, t); + } + ++buffer; + rx += cx; + ry += cy; + rz += cz; + } } } else /* SourcePictTypeConical */ { double a = pGradient->conical.angle/(180.*65536); @@ -4038,7 +3927,6 @@ fbCompositeRect (const FbComposeData *data, CARD32 *scanline_buffer) if (!compose) return; -#ifndef MOZILLA_CAIRO_NOT_DEFINED /* XXX: The non-MMX version of some of the fbCompose functions * overwrite the source or mask data (ones that use * fbCombineMaskC, fbCombineMaskAlphaC, or fbCombineMaskValueC @@ -4056,7 +3944,6 @@ fbCompositeRect (const FbComposeData *data, CARD32 *scanline_buffer) srcClass = SourcePictClassUnknown; maskClass = SourcePictClassUnknown; } -#endif /* MOZCAIRO */ for (i = 0; i < data->height; ++i) { /* fill first half of scanline with source */ diff --git a/gfx/cairo/libpixman/src/fbmmx.c b/gfx/cairo/libpixman/src/fbmmx.c index 387d4b46e68..0751e3cf928 100644 --- a/gfx/cairo/libpixman/src/fbmmx.c +++ b/gfx/cairo/libpixman/src/fbmmx.c @@ -157,11 +157,6 @@ static const MMXData c = #define MC(x) c.mmx_##x #endif -/* cast to void* in the middle to shut gcc up warning about - * "dereferencing type-punned pointers". - */ -#define M64(x) (*(__m64*)(void*)(&x)) - static __inline__ __m64 shift (__m64 v, int s) { @@ -1472,6 +1467,8 @@ fbCompositeSrc_8888x0565mmx (pixman_operator_t op, fbComposeGetStart (pDst, xDst, yDst, CARD16, dstStride, dstLine, 1); fbComposeGetStart (pSrc, xSrc, ySrc, CARD32, srcStride, srcLine, 1); + assert (pSrc->pDrawable == pMask->pDrawable); + while (height--) { dst = dstLine; @@ -1500,22 +1497,46 @@ fbCompositeSrc_8888x0565mmx (pixman_operator_t op, while (w >= 4) { + CARD32 s0, s1, s2, s3; + unsigned char a0, a1, a2, a3; __m64 vsrc0, vsrc1, vsrc2, vsrc3; - __m64 vdest; - vsrc0 = load8888(*(src + 0)); - vsrc1 = load8888(*(src + 1)); - vsrc2 = load8888(*(src + 2)); - vsrc3 = load8888(*(src + 3)); + s0 = *src; + s1 = *(src + 1); + s2 = *(src + 2); + s3 = *(src + 3); - vdest = *(__m64 *)dst; - - vdest = pack565(over(vsrc0, expand_alpha(vsrc0), expand565(vdest, 0)), vdest, 0); - vdest = pack565(over(vsrc1, expand_alpha(vsrc1), expand565(vdest, 1)), vdest, 1); - vdest = pack565(over(vsrc2, expand_alpha(vsrc2), expand565(vdest, 2)), vdest, 2); - vdest = pack565(over(vsrc3, expand_alpha(vsrc3), expand565(vdest, 3)), vdest, 3); - - *(__m64 *)dst = vdest; + a0 = (s0 >> 24); + a1 = (s1 >> 24); + a2 = (s2 >> 24); + a3 = (s3 >> 24); + + vsrc0 = load8888(s0); + vsrc1 = load8888(s1); + vsrc2 = load8888(s2); + vsrc3 = load8888(s3); + + if ((a0 & a1 & a2 & a3) == 0xFF) + { + __m64 vdest; + vdest = pack565(vsrc0, _mm_setzero_si64(), 0); + vdest = pack565(vsrc1, vdest, 1); + vdest = pack565(vsrc2, vdest, 2); + vdest = pack565(vsrc3, vdest, 3); + + *(__m64 *)dst = vdest; + } + else if (a0 | a1 | a2 | a3) + { + __m64 vdest = *(__m64 *)dst; + + vdest = pack565(over(vsrc0, expand_alpha(vsrc0), expand565(vdest, 0)), vdest, 0); + vdest = pack565(over(vsrc1, expand_alpha(vsrc1), expand565(vdest, 1)), vdest, 1); + vdest = pack565(over(vsrc2, expand_alpha(vsrc2), expand565(vdest, 2)), vdest, 2); + vdest = pack565(over(vsrc3, expand_alpha(vsrc3), expand565(vdest, 3)), vdest, 3); + + *(__m64 *)dst = vdest; + } w -= 4; dst += 4; @@ -1596,7 +1617,7 @@ fbCompositeSolidMask_nx8x8888mmx (pixman_operator_t op, if (m) { - __m64 vdest = in_over(vsrc, vsrca, expand_alpha_rev (M64(m)), load8888(*dst)); + __m64 vdest = in_over(vsrc, vsrca, expand_alpha_rev (*(__m64*)(&m)), load8888(*dst)); *dst = store8888(vdest); } @@ -1624,8 +1645,8 @@ fbCompositeSolidMask_nx8x8888mmx (pixman_operator_t op, vdest = *(__m64 *)dst; - dest0 = in_over(vsrc, vsrca, expand_alpha_rev (M64(m0)), expand8888(vdest, 0)); - dest1 = in_over(vsrc, vsrca, expand_alpha_rev (M64(m1)), expand8888(vdest, 1)); + dest0 = in_over(vsrc, vsrca, expand_alpha_rev (*(__m64*)(&m0)), expand8888(vdest, 0)); + dest1 = in_over(vsrc, vsrca, expand_alpha_rev (*(__m64*)(&m1)), expand8888(vdest, 1)); *(__m64 *)dst = pack8888(dest0, dest1); } @@ -1644,7 +1665,7 @@ fbCompositeSolidMask_nx8x8888mmx (pixman_operator_t op, if (m) { __m64 vdest = load8888(*dst); - vdest = in_over(vsrc, vsrca, expand_alpha_rev (M64(m)), vdest); + vdest = in_over(vsrc, vsrca, expand_alpha_rev (*(__m64*)(&m)), vdest); *dst = store8888(vdest); } @@ -1714,7 +1735,7 @@ fbCompositeSolidMaskSrc_nx8x8888mmx (pixman_operator_t op, if (m) { - __m64 vdest = in(vsrc, expand_alpha_rev (M64(m))); + __m64 vdest = in(vsrc, expand_alpha_rev (*(__m64*)(&m))); *dst = store8888(vdest); } else @@ -1746,8 +1767,8 @@ fbCompositeSolidMaskSrc_nx8x8888mmx (pixman_operator_t op, vdest = *(__m64 *)dst; - dest0 = in(vsrc, expand_alpha_rev (M64(m0))); - dest1 = in(vsrc, expand_alpha_rev (M64(m1))); + dest0 = in(vsrc, expand_alpha_rev (*(__m64*)(&m0))); + dest1 = in(vsrc, expand_alpha_rev (*(__m64*)(&m1))); *(__m64 *)dst = pack8888(dest0, dest1); } @@ -1770,7 +1791,7 @@ fbCompositeSolidMaskSrc_nx8x8888mmx (pixman_operator_t op, if (m) { __m64 vdest = load8888(*dst); - vdest = in(vsrc, expand_alpha_rev (M64(m))); + vdest = in(vsrc, expand_alpha_rev (*(__m64*)(&m))); *dst = store8888(vdest); } else @@ -1825,7 +1846,7 @@ fbCompositeSolidMask_nx8x0565mmx (pixman_operator_t op, vsrca = expand_alpha (vsrc); vsrc16 = pack565(vsrc, _mm_setzero_si64(), 0); - src16 = *(ullong*)(void*)(&vsrc16); + src16 = *(ullong*)(&vsrc16); srcsrcsrcsrc = (ullong)src16 << 48 | (ullong)src16 << 32 | (ullong)src16 << 16 | (ullong)src16; @@ -1847,7 +1868,7 @@ fbCompositeSolidMask_nx8x0565mmx (pixman_operator_t op, if (m) { __m64 vd = _mm_cvtsi32_si64 (*dst); - __m64 vdest = in_over(vsrc, vsrca, expand_alpha_rev (M64(m)), expand565(vd, 0)); + __m64 vdest = in_over(vsrc, vsrca, expand_alpha_rev (*(__m64*)(&m)), expand565(vd, 0)); *dst = _mm_cvtsi64_si32 (pack565(vdest, _mm_setzero_si64(), 0)); } @@ -1877,13 +1898,13 @@ fbCompositeSolidMask_nx8x0565mmx (pixman_operator_t op, vdest = *(__m64 *)dst; - vm0 = M64(m0); + vm0 = *(__m64*)(&m0); vdest = pack565(in_over(vsrc, vsrca, expand_alpha_rev(vm0), expand565(vdest, 0)), vdest, 0); - vm1 = M64(m1); + vm1 = *(__m64*)(&m1); vdest = pack565(in_over(vsrc, vsrca, expand_alpha_rev(vm1), expand565(vdest, 1)), vdest, 1); - vm2 = M64(m2); + vm2 = *(__m64*)(&m2); vdest = pack565(in_over(vsrc, vsrca, expand_alpha_rev(vm2), expand565(vdest, 2)), vdest, 2); - vm3 = M64(m3); + vm3 = *(__m64*)(&m3); vdest = pack565(in_over(vsrc, vsrca, expand_alpha_rev(vm3), expand565(vdest, 3)), vdest, 3); *(__m64 *)dst = vdest; @@ -1903,7 +1924,7 @@ fbCompositeSolidMask_nx8x0565mmx (pixman_operator_t op, if (m) { __m64 vd = _mm_cvtsi32_si64 (*dst); - __m64 vdest = in_over(vsrc, vsrca, expand_alpha_rev (M64(m)), expand565(vd, 0)); + __m64 vdest = in_over(vsrc, vsrca, expand_alpha_rev (*(__m64*)(&m)), expand565(vd, 0)); *dst = _mm_cvtsi64_si32 (pack565(vdest, _mm_setzero_si64(), 0)); } @@ -2634,7 +2655,7 @@ fbSolidFillmmx (FbPixels *pDraw, } fill = ((ullong)xor << 32) | xor; - vfill = M64(fill); + vfill = *(__m64*)&fill; while (height--) { diff --git a/gfx/cairo/libpixman/src/fbpict.c b/gfx/cairo/libpixman/src/fbpict.c index 0bd989fe08d..63b1cbcf050 100644 --- a/gfx/cairo/libpixman/src/fbpict.c +++ b/gfx/cairo/libpixman/src/fbpict.c @@ -2123,9 +2123,7 @@ static unsigned int detectCPUFeatures(void) { features |= SSE; if (result & (1 << 26)) features |= SSE2; - if ((features & MMX) && !(features & SSE) && - (strcmp(vendor, "AuthenticAMD") == 0 || - strcmp(vendor, "Geode by NSC") == 0)) { + if ((result & MMX) && !(result & SSE) && (strcmp(vendor, "AuthenticAMD") == 0)) { /* check for AMD MMX extensions */ #ifdef __GNUC__ diff --git a/gfx/cairo/libpixman/src/icimage.c b/gfx/cairo/libpixman/src/icimage.c index 4d957a0fc37..44c4c8b34bc 100644 --- a/gfx/cairo/libpixman/src/icimage.c +++ b/gfx/cairo/libpixman/src/icimage.c @@ -247,6 +247,7 @@ pixman_image_create_radial_gradient (const pixman_radial_gradient_t *gradient, { pixman_radial_gradient_image_t *radial; pixman_image_t *image; + double x; if (n_stops < 2) return NULL; @@ -269,14 +270,19 @@ pixman_image_create_radial_gradient (const pixman_radial_gradient_t *gradient, memcpy (radial->stops, stops, sizeof (pixman_gradient_stop_t) * n_stops); radial->type = SourcePictTypeRadial; - radial->c1 = gradient->c1; - radial->c2 = gradient->c2; - radial->cdx = xFixedToDouble (gradient->c2.x - gradient->c1.x); - radial->cdy = xFixedToDouble (gradient->c2.y - gradient->c1.y); - radial->dr = xFixedToDouble (gradient->c2.radius - gradient->c1.radius); - radial->A = ( radial->cdx * radial->cdx - + radial->cdy * radial->cdy - - radial->dr * radial->dr); + x = (double) gradient->inner.radius / (double) gradient->outer.radius; + radial->dx = (gradient->outer.x - gradient->inner.x); + radial->dy = (gradient->outer.y - gradient->inner.y); + radial->fx = (gradient->inner.x) - x * radial->dx; + radial->fy = (gradient->inner.y) - x * radial->dy; + radial->m = 1. / (1 + x); + radial->b = -x * radial->m; + radial->dx /= 65536.; + radial->dy /= 65536.; + radial->fx /= 65536.; + radial->fy /= 65536.; + x = gradient->outer.radius / 65536.; + radial->a = x * x - radial->dx * radial->dx - radial->dy * radial->dy; image->pSourcePict = (pixman_source_image_t *) radial; diff --git a/gfx/cairo/libpixman/src/icimage.h b/gfx/cairo/libpixman/src/icimage.h index bbf41b99c02..82202a71e56 100644 --- a/gfx/cairo/libpixman/src/icimage.h +++ b/gfx/cairo/libpixman/src/icimage.h @@ -101,12 +101,13 @@ typedef struct _pixman_radial_gradient_image { int stopRange; uint32_t *colorTable; int colorTableSize; - pixman_circle_t c1; - pixman_circle_t c2; - double cdx; - double cdy; - double dr; - double A; + double fx; + double fy; + double dx; + double dy; + double a; + double m; + double b; } pixman_radial_gradient_image_t; typedef struct _pixman_conical_gradient_image { diff --git a/gfx/cairo/libpixman/src/icint.h b/gfx/cairo/libpixman/src/icint.h index 47a2220059b..93795b056f9 100644 --- a/gfx/cairo/libpixman/src/icint.h +++ b/gfx/cairo/libpixman/src/icint.h @@ -1026,7 +1026,6 @@ typedef xFixed_16_16 xFixed; #define IntToxFixed(i) ((xFixed) (i) << XFIXED_BITS) #define xFixedE ((xFixed) 1) #define xFixed1 (IntToxFixed(1)) -#define xFixedToDouble(f) (double) ((f) / (double) xFixed1) #define xFixed1MinusE (xFixed1 - xFixedE) #define xFixedFrac(f) ((f) & xFixed1MinusE) #define xFixedFloor(f) ((f) & ~xFixed1MinusE) diff --git a/gfx/cairo/libpixman/src/pixman-remap.h b/gfx/cairo/libpixman/src/pixman-remap.h index 290df328123..9426ab80986 100644 --- a/gfx/cairo/libpixman/src/pixman-remap.h +++ b/gfx/cairo/libpixman/src/pixman-remap.h @@ -1,80 +1,80 @@ -#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_8888x0565mmx _cairo_pixman_composite_src_8888x0565mmx -#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 +#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_8888x0565mmx _moz_cairo_pixman_composite_src_8888x0565mmx +#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 #if defined(USE_MMX) && !defined(__amd64__) && !defined(__x86_64__) -#define fbHaveMMX _cairo_pixman_have_mmx +#define fbHaveMMX _moz_cairo_pixman_have_mmx #endif -#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 +#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 diff --git a/gfx/cairo/libpixman/src/pixman.h b/gfx/cairo/libpixman/src/pixman.h index 9120eb6ed1e..309e5e655b8 100644 --- a/gfx/cairo/libpixman/src/pixman.h +++ b/gfx/cairo/libpixman/src/pixman.h @@ -99,7 +99,7 @@ SOFTWARE. #include "pixman-remap.h" -#if (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 3)) && defined(__ELF__) && !defined(__sun__) +#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 @@ -364,8 +364,8 @@ typedef struct pixman_linear_gradient { } pixman_linear_gradient_t; typedef struct pixman_radial_gradient { - pixman_circle_t c1; - pixman_circle_t c2; + pixman_circle_t inner; + pixman_circle_t outer; } pixman_radial_gradient_t; typedef enum { diff --git a/gfx/cairo/libpixman/src/slim_internal.h b/gfx/cairo/libpixman/src/slim_internal.h new file mode 100644 index 00000000000..4cf74961ef1 --- /dev/null +++ b/gfx/cairo/libpixman/src/slim_internal.h @@ -0,0 +1,106 @@ +/* slim - Shared Library Interface Macros + * + * Copyright © 2003 Richard Henderson + * + * 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 Richard Henderson + * not be used in advertising or publicity pertaining to distribution + * of the software without specific, written prior permission. + * Richard Henderson makes no representations about the suitability of this + * software for any purpose. It is provided "as is" without express + * or implied warranty. + * + * RICHARD HENDERSON DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN + * NO EVENT SHALL RICHARD HENDERSON 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: Richard Henderson + */ + +#ifndef _SLIM_INTERNAL_H_ +#define _SLIM_INTERNAL_H_ 1 + +/* XXX THIS DOCUMENTATION IS BLOODY WRONG. SOMEONE DID NOT ACTUALLY + CONSULT WITH THE COMPILERS THEY CLAIMED TO SUPPORT */ +/* This macro marks a symbol as STV_HIDDEN, which prevents it from being + added to the dynamic symbol table of the shared library. This prevents + users of the library from knowingly or unknowingly accessing library + internals that may change in future releases. It also allows the + compiler to generate slightly more efficient code in some cases. + + The macro should be placed either immediately before the return type in + a function declaration: + + pixman_private int + somefunction(void); + + or after a data name, + XXX THIS IS WRONG. YOU CAN NOT DO THIS WITH THE COMPILERS THAT + THIS PACKAGE CLAIMS TO SUPPORT. + extern int somedata pixman_private; + + The ELF visibility attribute did not exist before gcc 3.3. */ +/* ??? Not marked with "slim" because that makes it look too much + like the function name instead of just an attribute. */ + +#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 + +/* The following macros are used for PLT bypassing. First of all, + you need to have the function prototyped somewhere, say in foo.h: + + int foo (int __bar); + + If calls to foo within libfoo.so should always go to foo defined + in libfoo.so, then in fooint.h you add: + + slim_hidden_proto (foo) + + and after the foo function definition: + + int foo (int __bar) + { + return __bar; + } + slim_hidden_def (foo); + + This works by arranging for the C symbol "foo" to be renamed to + "INT_foo" at the assembly level, which is marked pixman_private. + We then create another symbol at the same address (an alias) with + the C symbol "EXT_foo", which is renamed to "foo" at the assembly + level. */ + +#if __GNUC__ >= 3 && defined(__ELF__) +# 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)) \ + pixman_private; +# define slim_hidden_def1(name, internal) \ + extern __typeof (name) EXT_##name __asm__(slim_hidden_asmname(name)) \ + __attribute__((__alias__(slim_hidden_asmname(internal)))) +# define slim_hidden_ulp slim_hidden_ulp1(__USER_LABEL_PREFIX__) +# define slim_hidden_ulp1(x) slim_hidden_ulp2(x) +# define slim_hidden_ulp2(x) #x +# define slim_hidden_asmname(name) slim_hidden_asmname1(name) +# define slim_hidden_asmname1(name) slim_hidden_ulp #name +#else +# define slim_hidden_proto(name) +# define slim_hidden_def(name) +#endif + +#endif /* _SLIM_INTERNAL_H_ */ diff --git a/gfx/thebes/src/gfxASurface.cpp b/gfx/thebes/src/gfxASurface.cpp index 2cb8bec8b8f..0547ee5012d 100644 --- a/gfx/thebes/src/gfxASurface.cpp +++ b/gfx/thebes/src/gfxASurface.cpp @@ -50,7 +50,7 @@ #include "gfxXlibSurface.h" #endif -#ifdef CAIRO_HAS_NQUARTZ_SURFACE +#ifdef CAIRO_HAS_QUARTZ_SURFACE #include "gfxQuartzSurface.h" #endif @@ -139,8 +139,8 @@ gfxASurface::Wrap (cairo_surface_t *csurf) result = new gfxXlibSurface(csurf); } #endif -#ifdef CAIRO_HAS_NQUARTZ_SURFACE - else if (stype == CAIRO_SURFACE_TYPE_NQUARTZ) { +#ifdef CAIRO_HAS_QUARTZ_SURFACE + else if (stype == CAIRO_SURFACE_TYPE_QUARTZ) { result = new gfxQuartzSurface(csurf); } #endif diff --git a/gfx/thebes/src/gfxMatrix.cpp b/gfx/thebes/src/gfxMatrix.cpp index 602aa18e0f5..3ec31a9580a 100644 --- a/gfx/thebes/src/gfxMatrix.cpp +++ b/gfx/thebes/src/gfxMatrix.cpp @@ -108,60 +108,12 @@ gfxMatrix::Transform(const gfxRect& rect) const gfxRect gfxMatrix::TransformBounds(const gfxRect& rect) const { - /* Code taken from cairo-matrix.c, _cairo_matrix_transform_bounding_box isn't public */ - int i; - double quad_x[4], quad_y[4]; - double min_x, max_x; - double min_y, max_y; + double x0 = rect.pos.x; + double y0 = rect.pos.y; + double x1 = rect.pos.x + rect.size.width; + double y1 = rect.pos.y + rect.size.height; - quad_x[0] = rect.pos.x; - quad_y[0] = rect.pos.y; - cairo_matrix_transform_point (CONST_CAIRO_MATRIX(this), &quad_x[0], &quad_y[0]); + cairo_matrix_transform_bounding_box(CONST_CAIRO_MATRIX(this), &x0, &y0, &x1, &y1, NULL); - quad_x[1] = rect.pos.x + rect.size.width; - quad_y[1] = rect.pos.y; - cairo_matrix_transform_point (CONST_CAIRO_MATRIX(this), &quad_x[1], &quad_y[1]); - - quad_x[2] = rect.pos.x; - quad_y[2] = rect.pos.y + rect.size.height; - cairo_matrix_transform_point (CONST_CAIRO_MATRIX(this), &quad_x[2], &quad_y[2]); - - quad_x[3] = rect.pos.x + rect.size.width; - quad_y[3] = rect.pos.y + rect.size.height; - cairo_matrix_transform_point (CONST_CAIRO_MATRIX(this), &quad_x[3], &quad_y[3]); - - min_x = max_x = quad_x[0]; - min_y = max_y = quad_y[0]; - - for (i = 1; i < 4; i++) { - if (quad_x[i] < min_x) - min_x = quad_x[i]; - if (quad_x[i] > max_x) - max_x = quad_x[i]; - - if (quad_y[i] < min_y) - min_y = quad_y[i]; - if (quad_y[i] > max_y) - max_y = quad_y[i]; - } - - // we don't compute this now -#if 0 - 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]); - } -#endif - - return gfxRect(min_x, min_y, max_x - min_x, max_y - min_y); + return gfxRect(x0, y0, x1 - x0, y1 - y0); }