diff options
Diffstat (limited to 'gfx/cairo/12-quartz-named-destination.patch')
-rw-r--r-- | gfx/cairo/12-quartz-named-destination.patch | 166 |
1 files changed, 166 insertions, 0 deletions
diff --git a/gfx/cairo/12-quartz-named-destination.patch b/gfx/cairo/12-quartz-named-destination.patch new file mode 100644 index 0000000000..b750087bc9 --- /dev/null +++ b/gfx/cairo/12-quartz-named-destination.patch @@ -0,0 +1,166 @@ +# HG changeset patch +# User Jonathan Kew <jkew@mozilla.com> +# Date 1628081557 0 +# Wed Aug 04 12:52:37 2021 +0000 +# Node ID 2635200eb5ec6f6eff1ecd0fad1ef029f0b994af +# Parent 99c4916f4a924ede94aee9044fe3f753d2e2be2d +Bug 1892913 - patch 14 - Add cairo-quartz-surface named-destination support from bug 1722300 patch 3. + +diff --git a/gfx/cairo/cairo/src/cairo-quartz-surface.c b/gfx/cairo/cairo/src/cairo-quartz-surface.c +--- a/gfx/cairo/cairo/src/cairo-quartz-surface.c ++++ b/gfx/cairo/cairo/src/cairo-quartz-surface.c +@@ -2192,24 +2192,13 @@ static cairo_status_t + } + + static cairo_int_status_t +-_cairo_quartz_surface_tag (void *abstract_surface, +- cairo_bool_t begin, +- const char *tag_name, +- const char *attributes, +- const cairo_pattern_t *source, +- const cairo_stroke_style_t *style, +- const cairo_matrix_t *ctm, +- const cairo_matrix_t *ctm_inverse, +- const cairo_clip_t *clip) ++_cairo_quartz_surface_link (cairo_quartz_surface_t *surface, ++ cairo_bool_t begin, ++ const char *attributes) + { + cairo_link_attrs_t link_attrs; + cairo_int_status_t status = CAIRO_STATUS_SUCCESS; + int i, num_rects; +- cairo_quartz_surface_t *surface = (cairo_quartz_surface_t *) abstract_surface; +- +- /* Currently the only tag we support is "Link" */ +- if (strcmp (tag_name, "Link")) +- return CAIRO_INT_STATUS_UNSUPPORTED; + + /* We only process the 'begin' tag, and expect a rect attribute; + using the extents of the drawing operations enclosed by the begin/end +@@ -2223,11 +2212,24 @@ static cairo_int_status_t + + num_rects = _cairo_array_num_elements (&link_attrs.rects); + if (num_rects > 0) { +- CFURLRef url = CFURLCreateWithBytes (NULL, +- (const UInt8 *) link_attrs.uri, +- strlen (link_attrs.uri), +- kCFStringEncodingUTF8, +- NULL); ++ /* Create either a named destination or a URL, depending which is present ++ in the link attributes. */ ++ CFURLRef url = NULL; ++ CFStringRef name = NULL; ++ if (link_attrs.uri && *link_attrs.uri) ++ url = CFURLCreateWithBytes (NULL, ++ (const UInt8 *) link_attrs.uri, ++ strlen (link_attrs.uri), ++ kCFStringEncodingUTF8, ++ NULL); ++ else if (link_attrs.dest && *link_attrs.dest) ++ name = CFStringCreateWithBytes (kCFAllocatorDefault, ++ (const UInt8 *) link_attrs.dest, ++ strlen (link_attrs.dest), ++ kCFStringEncodingUTF8, ++ FALSE); ++ else /* silently ignore link that doesn't have a usable target */ ++ goto cleanup; + + for (i = 0; i < num_rects; i++) { + CGRect link_rect; +@@ -2241,12 +2243,19 @@ static cairo_int_status_t + rectf.width, + rectf.height); + +- CGPDFContextSetURLForRect (surface->cgContext, url, link_rect); ++ if (url) ++ CGPDFContextSetURLForRect (surface->cgContext, url, link_rect); ++ else ++ CGPDFContextSetDestinationForRect (surface->cgContext, name, link_rect); + } + +- CFRelease (url); ++ if (url) ++ CFRelease (url); ++ else ++ CFRelease (name); + } + ++cleanup: + _cairo_array_fini (&link_attrs.rects); + free (link_attrs.dest); + free (link_attrs.uri); +@@ -2255,6 +2264,74 @@ static cairo_int_status_t + return status; + } + ++static cairo_int_status_t ++_cairo_quartz_surface_dest (cairo_quartz_surface_t *surface, ++ cairo_bool_t begin, ++ const char *attributes) ++{ ++ cairo_dest_attrs_t dest_attrs; ++ cairo_int_status_t status = CAIRO_STATUS_SUCCESS; ++ double x = 0, y = 0; ++ ++ /* We only process the 'begin' tag, and expect 'x' and 'y' attributes. */ ++ if (!begin) ++ return status; ++ ++ status = _cairo_tag_parse_dest_attributes (attributes, &dest_attrs); ++ if (unlikely (status)) ++ return status; ++ ++ if (unlikely (!dest_attrs.name || !strlen (dest_attrs.name))) ++ goto cleanup; ++ ++ CFStringRef name = CFStringCreateWithBytes (kCFAllocatorDefault, ++ (const UInt8 *) dest_attrs.name, ++ strlen (dest_attrs.name), ++ kCFStringEncodingUTF8, ++ FALSE); ++ ++ if (dest_attrs.x_valid) ++ x = dest_attrs.x; ++ if (dest_attrs.y_valid) ++ y = dest_attrs.y; ++ ++ CGPDFContextAddDestinationAtPoint (surface->cgContext, ++ name, ++ CGPointMake (x, surface->extents.height - y)); ++ CFRelease (name); ++ ++cleanup: ++ free (dest_attrs.name); ++ ++ return status; ++} ++ ++static cairo_int_status_t ++_cairo_quartz_surface_tag (void *abstract_surface, ++ cairo_bool_t begin, ++ const char *tag_name, ++ const char *attributes, ++ const cairo_pattern_t *source, ++ const cairo_stroke_style_t *style, ++ const cairo_matrix_t *ctm, ++ const cairo_matrix_t *ctm_inverse, ++ const cairo_clip_t *clip) ++{ ++ cairo_link_attrs_t link_attrs; ++ int i, num_rects; ++ cairo_quartz_surface_t *surface = (cairo_quartz_surface_t *) abstract_surface; ++ ++ /* Currently the only tags we support are CAIRO_TAG_LINK and CAIRO_TAG_DEST */ ++ if (!strcmp (tag_name, CAIRO_TAG_LINK)) ++ return _cairo_quartz_surface_link (surface, begin, attributes); ++ ++ if (!strcmp (tag_name, CAIRO_TAG_DEST)) ++ return _cairo_quartz_surface_dest (surface, begin, attributes); ++ ++ /* Unknown tag names are silently ignored here. */ ++ return CAIRO_INT_STATUS_SUCCESS; ++} ++ + // XXXtodo implement show_page; need to figure out how to handle begin/end + + static const cairo_surface_backend_t cairo_quartz_surface_backend = { |