Bug 454059 - Add [minimal] tag support to cairo-quartz-surface.c. r=jrmuizel
authorJonathan Kew <jkew@mozilla.com>
Tue, 11 May 2021 17:00:29 +0000
changeset 579407 47fc505e89a85d56d6ff8f3d363f99d97468bcec
parent 579406 d23a00ef79accfd49223199bf0d62a4639c300a4
child 579408 37a85c239237499f5b51eae2959793559c3c9130
push id142975
push userjkew@mozilla.com
push dateTue, 11 May 2021 17:03:25 +0000
treeherderautoland@26b31c2612b4 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjrmuizel
bugs454059
milestone90.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 454059 - Add [minimal] tag support to cairo-quartz-surface.c. r=jrmuizel This implements a subset of the tag() function on the quartz surface backend; just enough to support generating links in PDF output. In particular, the only tag type supported is Link, and we require the link area to be passed as a list of rects in the 'begin' call; we don't support accumulating all drawing operations between 'begin' and 'end' into a link area. Differential Revision: https://phabricator.services.mozilla.com/D114206
gfx/cairo/cairo/src/cairo-quartz-surface.c
gfx/cairo/cairo/src/moz.build
--- a/gfx/cairo/cairo/src/cairo-quartz-surface.c
+++ b/gfx/cairo/cairo/src/cairo-quartz-surface.c
@@ -43,16 +43,17 @@
 #include "cairo-compositor-private.h"
 #include "cairo-default-context-private.h"
 #include "cairo-error-private.h"
 #include "cairo-image-surface-inline.h"
 #include "cairo-pattern-private.h"
 #include "cairo-surface-backend-private.h"
 #include "cairo-surface-clipper-private.h"
 #include "cairo-recording-surface-private.h"
+#include "cairo-tag-attributes-private.h"
 
 #include <dlfcn.h>
 
 #ifndef RTLD_DEFAULT
 #define RTLD_DEFAULT ((void *) 0)
 #endif
 
 #include <limits.h>
@@ -2308,16 +2309,80 @@ static cairo_status_t
 	    CGContextEOClip (surface->cgContext);
     }
 
     ND ((stderr, "-- intersect_clip_path\n"));
 
     return CAIRO_STATUS_SUCCESS;
 }
 
+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;
+    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
+       link tags to define the clickable area is not implemented. */
+    if (!begin)
+        return status;
+
+    status = _cairo_tag_parse_link_attributes (attributes, &link_attrs);
+    if (unlikely (status))
+	return status;
+
+    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);
+
+        for (i = 0; i < num_rects; i++) {
+            CGRect link_rect;
+            cairo_rectangle_t rectf;
+
+            _cairo_array_copy_element (&link_attrs.rects, i, &rectf);
+
+            link_rect =
+                CGRectMake (rectf.x,
+                            surface->extents.height - rectf.y - rectf.height,
+                            rectf.width,
+                            rectf.height);
+
+            CGPDFContextSetURLForRect (surface->cgContext, url, link_rect);
+        }
+
+        CFRelease (url);
+    }
+
+    _cairo_array_fini (&link_attrs.rects);
+    free (link_attrs.dest);
+    free (link_attrs.uri);
+    free (link_attrs.file);
+
+    return status;
+}
+
 // 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_finish,
 
     _cairo_default_context_create,
 
@@ -2341,16 +2406,21 @@ static const struct _cairo_surface_backe
     NULL, /* mark_dirty_rectangle */
 
     _cairo_quartz_surface_paint,
     _cairo_quartz_surface_mask,
     _cairo_quartz_surface_stroke,
     _cairo_quartz_surface_fill,
     NULL,  /* fill-stroke */
     _cairo_quartz_surface_glyphs,
+
+    NULL,  /* has_show_text_glyphs */
+    NULL,  /* show_text_glyphs */
+    NULL,  /* get_supported_mime_types */
+    _cairo_quartz_surface_tag   /* tag */
 };
 
 cairo_quartz_surface_t *
 _cairo_quartz_surface_create_internal (CGContextRef cgContext,
 				       cairo_content_t content,
 				       unsigned int width,
 				       unsigned int height)
 {
--- a/gfx/cairo/cairo/src/moz.build
+++ b/gfx/cairo/cairo/src/moz.build
@@ -24,17 +24,16 @@ if CONFIG['MOZ_WIDGET_TOOLKIT'] not in (
     SOURCES += [
         'cairo-base85-stream.c',
         'cairo-cff-subset.c',
         'cairo-deflate-stream.c',
         'cairo-pdf-interchange.c',
         'cairo-pdf-operators.c',
         'cairo-pdf-shading.c',
         'cairo-pdf-surface.c',
-        'cairo-tag-attributes.c',
         'cairo-tag-stack.c',
         'cairo-truetype-subset.c',
         'cairo-type1-fallback.c',
         'cairo-type1-glyph-names.c',
         'cairo-type1-subset.c',
         'cairo-type3-glyph-surface.c',
     ]
 
@@ -200,16 +199,17 @@ UNIFIED_SOURCES += [
     'cairo-stroke-dash.c',
     'cairo-stroke-style.c',
     'cairo-surface-clipper.c',
     'cairo-surface-fallback.c',
     'cairo-surface-offset.c',
     'cairo-surface-snapshot.c',
     'cairo-surface-subsurface.c',
     'cairo-surface.c',
+    'cairo-tag-attributes.c',
     'cairo-tee-surface.c',
     'cairo-tor22-scan-converter.c',
     'cairo-toy-font-face.c',
     'cairo-traps.c',
     'cairo-tristrip.c',
     'cairo-unicode.c',
     'cairo-user-font.c',
     'cairo-version.c',