summaryrefslogtreecommitdiff
path: root/src/cairo-quartz-font.c
diff options
context:
space:
mode:
authorJohn Ralls <jralls@ceridwen.us>2022-04-12 16:44:05 -0700
committerJohn Ralls <jralls@ceridwen.us>2022-04-25 11:29:52 -0700
commitc755e48c2e5da7f10956de1c3560180510e84d1f (patch)
tree2c8f582f34f24fb7a57f3ff8ec337f70076623ce /src/cairo-quartz-font.c
parentc6dc5df61264be1bec2e622355b97c6c45d236fc (diff)
downloadcairo-c755e48c2e5da7f10956de1c3560180510e84d1f.tar.gz
[quartz] Implement color font support.
Diffstat (limited to 'src/cairo-quartz-font.c')
-rw-r--r--src/cairo-quartz-font.c61
1 files changed, 51 insertions, 10 deletions
diff --git a/src/cairo-quartz-font.c b/src/cairo-quartz-font.c
index 9e667e0d6..000a0e237 100644
--- a/src/cairo-quartz-font.c
+++ b/src/cairo-quartz-font.c
@@ -76,8 +76,10 @@ static const CGFloat font_scale = 1.0;
#if MAC_OS_X_VERSION_MIN_REQUIRED < 1080
#define FONT_ORIENTATION_HORIZONTAL kCTFontHorizontalOrientation
+#define FONT_COLOR_GLYPHS kCTFontTraitColorGlyphs
#else
#define FONT_ORIENTATION_HORIZONTAL kCTFontOrientationHorizontal
+#define FONT_COLOR_GLYPHS kCTFontColorGlyphsTrait
#endif
static void
@@ -410,7 +412,6 @@ _cairo_quartz_init_glyph_metrics (cairo_quartz_scaled_font_t *font,
extents.y_bearing = - ymax;
extents.width = xmax - xmin;
extents.height = ymax - ymin;
-
extents.x_advance = advance.width;
extents.y_advance = advance.height;
@@ -522,9 +523,19 @@ _cairo_quartz_init_glyph_path (cairo_quartz_scaled_font_t *font,
return CAIRO_STATUS_SUCCESS;
}
+static cairo_bool_t
+_cairo_quartz_font_has_color_glyphs (void *abstract_font)
+{
+ cairo_quartz_scaled_font_t *face = (cairo_quartz_scaled_font_t*)abstract_font;
+ CTFontSymbolicTraits traits = CTFontGetSymbolicTraits (face->ctFont);
+ return traits & FONT_COLOR_GLYPHS;
+}
+
static cairo_int_status_t
_cairo_quartz_init_glyph_surface (cairo_quartz_scaled_font_t *font,
- cairo_scaled_glyph_t *scaled_glyph)
+ cairo_scaled_glyph_t *scaled_glyph,
+ cairo_scaled_glyph_info_t info,
+ const cairo_color_t *fg_color)
{
cairo_int_status_t status = CAIRO_STATUS_SUCCESS;
cairo_image_surface_t *surface = NULL;
@@ -538,6 +549,8 @@ _cairo_quartz_init_glyph_surface (cairo_quartz_scaled_font_t *font,
CGAffineTransform textMatrix;
CGRect glyphRect, glyphRectInt;
CGPoint glyphOrigin;
+ cairo_bool_t is_color = info & CAIRO_SCALED_GLYPH_INFO_COLOR_SURFACE;
+ cairo_format_t format = is_color ? CAIRO_FORMAT_ARGB32 : CAIRO_FORMAT_A8;
#ifdef DEBUG
fprintf (stderr, "[0x%04x] bearing: %f %f width %f height %f advances %f %f\n",
@@ -562,6 +575,19 @@ _cairo_quartz_init_glyph_surface (cairo_quartz_scaled_font_t *font,
return CAIRO_STATUS_SUCCESS;
}
+/* Note: Certain opentype color fonts have the ability to provide a
+ * mixture of color and not-color glyphs. The Core Text API doesn't
+ * expose a way to query individual glyphs and at the level that that
+ * API is written it's not supposed to matter. The following code will
+ * cheerfully render any glyph requested onto the image surface. If
+ * the font is capable of color and
+ * COLOR_SCALED_GLYPH_INFO_COLOR_SURFACE is set then you get back a
+ * CAIRO_FORMAT_ARGB32 surface. If a foreground color is provided then
+ * the glyph will be drawn in that color, otherwise it will be black.
+ */
+ if (unlikely (is_color && ! _cairo_quartz_font_has_color_glyphs (font)))
+ return CAIRO_INT_STATUS_UNSUPPORTED;
+
/* scale(1,-1) * font->base.scale * scale(1,-1) */
textMatrix = CGAffineTransformMake (font->base.scale.xx,
-font->base.scale.yx,
@@ -587,37 +613,47 @@ _cairo_quartz_init_glyph_surface (cairo_quartz_scaled_font_t *font,
width = glyphRectInt.size.width;
height = glyphRectInt.size.height;
- surface = (cairo_image_surface_t*) cairo_image_surface_create (CAIRO_FORMAT_A8, width, height);
+ surface = (cairo_image_surface_t*) cairo_image_surface_create (format, width, height);
if (surface->base.status)
return surface->base.status;
if (surface->width != 0 && surface->height != 0) {
+ CGColorSpaceRef colorspace = is_color ? CGColorSpaceCreateDeviceRGB () : NULL;
+ CGBitmapInfo bitinfo = is_color ? kCGBitmapByteOrder32Host | kCGImageAlphaPremultipliedFirst : kCGImageAlphaOnly;
+
CGContextRef cgContext = CGBitmapContextCreate (surface->data,
surface->width,
surface->height,
8,
surface->stride,
- NULL,
- kCGImageAlphaOnly);
+ colorspace,
+ bitinfo);
if (cgContext == NULL) {
cairo_surface_destroy (&surface->base);
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
}
+ if (fg_color)
+ CGContextSetRGBFillColor (cgContext, fg_color->red, fg_color->green, fg_color->blue, fg_color->alpha);
_cairo_quartz_set_antialiasing (cgContext, font->base.options.antialias);
CGContextSetAlpha (cgContext, 1.0);
CGContextTranslateCTM (cgContext, -glyphOrigin.x, -glyphOrigin.y);
CGContextConcatCTM (cgContext, textMatrix);
CTFontDrawGlyphs (font->ctFont, &glyph, &CGPointZero, 1, cgContext);
CGContextRelease (cgContext);
+ CGColorSpaceRelease (colorspace);
}
cairo_surface_set_device_offset (&surface->base,
- glyphOrigin.x,
height + glyphOrigin.y);
+ cairo_surface_mark_dirty (&surface->base);
- _cairo_scaled_glyph_set_surface (scaled_glyph, &font->base, surface);
+ if (is_color)
+ _cairo_scaled_glyph_set_color_surface (scaled_glyph, &font->base, surface, fg_color != NULL);
+ else
+ _cairo_scaled_glyph_set_surface (scaled_glyph, &font->base, surface);
return status;
}
@@ -637,8 +673,10 @@ _cairo_quartz_scaled_glyph_init (void *abstract_font,
if (!status && (info & CAIRO_SCALED_GLYPH_INFO_PATH))
status = _cairo_quartz_init_glyph_path (font, scaled_glyph);
- if (!status && (info & CAIRO_SCALED_GLYPH_INFO_SURFACE))
- status = _cairo_quartz_init_glyph_surface (font, scaled_glyph);
+ if (!status && (info & (CAIRO_SCALED_GLYPH_INFO_SURFACE |
+ CAIRO_SCALED_GLYPH_INFO_COLOR_SURFACE )))
+ status = _cairo_quartz_init_glyph_surface (font, scaled_glyph,
+ info, foreground_color);
return status;
}
@@ -694,8 +732,11 @@ static const cairo_scaled_font_backend_t _cairo_quartz_scaled_font_backend = {
_cairo_quartz_ucs4_to_index,
_cairo_quartz_load_truetype_table,
NULL, /*index_to_ucs4*/
-}; /* is_synthetic, index_to_glyph_name, load_type1_data, has_color_glyphs */
-
+ NULL, /* is_synthetic */
+ NULL, /* index_to_glyph_name */
+ NULL, /* load_type1_data */
+ _cairo_quartz_font_has_color_glyphs
+};
/*
* private methods that the quartz surface uses
*/