[cairo-commit] src/cairo-cff-subset.c src/cairo-ft-font.c src/cairoint.h src/cairo-truetype-subset.c src/cairo-type1-subset.c src/win32
Adrian Johnson
ajohnson at kemper.freedesktop.org
Sat May 27 23:48:10 UTC 2017
src/cairo-cff-subset.c | 13 ++++++--
src/cairo-ft-font.c | 67 +++++++++++++++++++++++++++++++++++++++++--
src/cairo-truetype-subset.c | 13 ++++++--
src/cairo-type1-subset.c | 14 ++++++--
src/cairoint.h | 8 +++--
src/win32/cairo-win32-font.c | 12 ++++---
6 files changed, 107 insertions(+), 20 deletions(-)
New commits:
commit 0fd0fd0ae9ad8cfb177bb844091de98c0235917e
Author: Adrian Johnson <ajohnson at redneon.com>
Date: Sun May 28 09:07:54 2017 +0930
subsetting: support variable fonts
If the font is a non default variant, fallback to creating a font from
the outlines.
diff --git a/src/cairo-cff-subset.c b/src/cairo-cff-subset.c
index 775ca61b..bd3bfde7 100644
--- a/src/cairo-cff-subset.c
+++ b/src/cairo-cff-subset.c
@@ -2788,13 +2788,20 @@ _cairo_cff_font_create (cairo_scaled_font_subset_t *scaled_font_subset,
{
const cairo_scaled_font_backend_t *backend;
cairo_int_status_t status;
+ cairo_bool_t is_synthetic;
cairo_cff_font_t *font;
backend = scaled_font_subset->scaled_font->backend;
- /* We need to use a fallback font generated from the synthesized outlines. */
- if (backend->is_synthetic && backend->is_synthetic (scaled_font_subset->scaled_font))
- return CAIRO_INT_STATUS_UNSUPPORTED;
+ /* We need to use a fallback font if this font differs from the CFF outlines. */
+ if (backend->is_synthetic) {
+ status = backend->is_synthetic (scaled_font_subset->scaled_font, &is_synthetic);
+ if (unlikely (status))
+ return status;
+
+ if (is_synthetic)
+ return CAIRO_INT_STATUS_UNSUPPORTED;
+ }
font = calloc (1, sizeof (cairo_cff_font_t));
if (unlikely (font == NULL))
diff --git a/src/cairo-ft-font.c b/src/cairo-ft-font.c
index 74d43cc2..5b367e7b 100644
--- a/src/cairo-ft-font.c
+++ b/src/cairo-ft-font.c
@@ -58,6 +58,7 @@
#include FT_BITMAP_H
#include FT_TRUETYPE_TABLES_H
#include FT_XFREE86_H
+#include FT_MULTIPLE_MASTERS_H
#if HAVE_FT_GLYPHSLOT_EMBOLDEN
#include FT_SYNTHESIS_H
#endif
@@ -2595,11 +2596,71 @@ _cairo_ft_index_to_ucs4(void *abstract_font,
return CAIRO_STATUS_SUCCESS;
}
-static cairo_bool_t
-_cairo_ft_is_synthetic (void *abstract_font)
+static cairo_int_status_t
+_cairo_ft_is_synthetic (void *abstract_font,
+ cairo_bool_t *is_synthetic)
{
+ cairo_int_status_t status = CAIRO_STATUS_SUCCESS;
cairo_ft_scaled_font_t *scaled_font = abstract_font;
- return scaled_font->ft_options.synth_flags != 0;
+ cairo_ft_unscaled_font_t *unscaled = scaled_font->unscaled;
+ FT_Face face;
+ FT_Error error;
+
+ if (scaled_font->ft_options.synth_flags != 0) {
+ *is_synthetic = TRUE;
+ return status;
+ }
+
+ *is_synthetic = FALSE;
+ face = _cairo_ft_unscaled_font_lock_face (unscaled);
+ if (!face)
+ return _cairo_error (CAIRO_STATUS_NO_MEMORY);
+
+ if (face->face_flags & FT_FACE_FLAG_MULTIPLE_MASTERS) {
+ FT_MM_Var *mm_var = NULL;
+ FT_Fixed *coords = NULL;
+ int num_axis, i;
+
+ /* If this is an MM or variable font we can't assume the current outlines
+ * are the same as the font tables */
+ *is_synthetic = TRUE;
+
+ error = FT_Get_MM_Var (face, &mm_var);
+ if (error) {
+ status = _cairo_error (_ft_to_cairo_error (error));
+ goto cleanup;
+ }
+
+ num_axis = mm_var->num_axis;
+ coords = _cairo_malloc_ab (num_axis, sizeof(FT_Fixed));
+ if (!coords) {
+ status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
+ goto cleanup;
+ }
+
+#if FREETYPE_MAJOR > 2 || ( FREETYPE_MAJOR == 2 && FREETYPE_MINOR >= 8)
+ /* If FT_Get_Var_Design_Coordinates() is available, we can check if the
+ * current design coordinates are the default coordinates. In this case
+ * the current outlines match the font tables.
+ */
+ FT_Get_Var_Design_Coordinates (face, num_axis, coords);
+ *is_synthetic = FALSE;
+ for (i = 0; i < num_axis; i++) {
+ if (coords[i] != mm_var->axis[i].def) {
+ *is_synthetic = TRUE;
+ break;
+ }
+ }
+#endif
+
+ cleanup:
+ free (coords);
+ free (mm_var);
+ }
+
+ _cairo_ft_unscaled_font_unlock_face (unscaled);
+
+ return status;
}
static cairo_int_status_t
diff --git a/src/cairo-truetype-subset.c b/src/cairo-truetype-subset.c
index afd396e1..62902cf7 100644
--- a/src/cairo-truetype-subset.c
+++ b/src/cairo-truetype-subset.c
@@ -138,6 +138,7 @@ _cairo_truetype_font_create (cairo_scaled_font_subset_t *scaled_font_subset,
cairo_truetype_font_t **font_return)
{
cairo_status_t status;
+ cairo_bool_t is_synthetic;
cairo_truetype_font_t *font;
const cairo_scaled_font_backend_t *backend;
tt_head_t head;
@@ -158,9 +159,15 @@ _cairo_truetype_font_create (cairo_scaled_font_subset_t *scaled_font_subset,
* return CAIRO_INT_STATUS_UNSUPPORTED;
*/
- /* We need to use a fallback font generated from the synthesized outlines. */
- if (backend->is_synthetic && backend->is_synthetic (scaled_font_subset->scaled_font))
- return CAIRO_INT_STATUS_UNSUPPORTED;
+ /* We need to use a fallback font if this font differs from the glyf outlines. */
+ if (backend->is_synthetic) {
+ status = backend->is_synthetic (scaled_font_subset->scaled_font, &is_synthetic);
+ if (unlikely (status))
+ return status;
+
+ if (is_synthetic)
+ return CAIRO_INT_STATUS_UNSUPPORTED;
+ }
size = sizeof (tt_head_t);
status = backend->load_truetype_table (scaled_font_subset->scaled_font,
diff --git a/src/cairo-type1-subset.c b/src/cairo-type1-subset.c
index b1566350..16f821d9 100644
--- a/src/cairo-type1-subset.c
+++ b/src/cairo-type1-subset.c
@@ -1715,14 +1715,20 @@ _cairo_type1_subset_init (cairo_type1_subset_t *type1_subset,
{
cairo_type1_font_subset_t font;
cairo_status_t status;
+ cairo_bool_t is_synthetic;
unsigned long length;
unsigned int i;
char buf[30];
- /* We need to use a fallback font generated from the synthesized outlines. */
- if (scaled_font_subset->scaled_font->backend->is_synthetic &&
- scaled_font_subset->scaled_font->backend->is_synthetic (scaled_font_subset->scaled_font))
- return CAIRO_INT_STATUS_UNSUPPORTED;
+ /* We need to use a fallback font if this font differs from the type1 outlines. */
+ if (scaled_font_subset->scaled_font->backend->is_synthetic) {
+ status = scaled_font_subset->scaled_font->backend->is_synthetic (scaled_font_subset->scaled_font, &is_synthetic);
+ if (unlikely (status))
+ return status;
+
+ if (is_synthetic)
+ return CAIRO_INT_STATUS_UNSUPPORTED;
+ }
status = _cairo_type1_font_subset_init (&font, scaled_font_subset, hex_encode);
if (unlikely (status))
diff --git a/src/cairoint.h b/src/cairoint.h
index 1ae045c9..4fedf861 100644
--- a/src/cairoint.h
+++ b/src/cairoint.h
@@ -562,8 +562,12 @@ struct _cairo_scaled_font_backend {
unsigned long index,
uint32_t *ucs4);
- cairo_warn cairo_bool_t
- (*is_synthetic)(void *scaled_font);
+ /* Determine if this scaled font differs from the outlines in the font tables.
+ * eg synthesized bold/italic or a non default variant of a variable font.
+ */
+ cairo_warn cairo_int_status_t
+ (*is_synthetic)(void *scaled_font,
+ cairo_bool_t *is_synthetic);
/* For type 1 fonts, return the glyph name for a given glyph index.
* A glyph index and list of glyph names in the Type 1 fonts is provided.
diff --git a/src/win32/cairo-win32-font.c b/src/win32/cairo-win32-font.c
index f5bd22c3..1b86b810 100644
--- a/src/win32/cairo-win32-font.c
+++ b/src/win32/cairo-win32-font.c
@@ -1450,8 +1450,9 @@ exit1:
return status;
}
-static cairo_bool_t
-_cairo_win32_scaled_font_is_synthetic (void *abstract_font)
+static cairo_int_status_t
+_cairo_win32_scaled_font_is_synthetic (void *abstract_font,
+ cairo_bool_t *is_synthetic)
{
cairo_win32_scaled_font_t *scaled_font = abstract_font;
cairo_status_t status;
@@ -1459,6 +1460,7 @@ _cairo_win32_scaled_font_is_synthetic (void *abstract_font)
cairo_bool_t bold;
cairo_bool_t italic;
+ *is_synthetic = FALSE;
status = _cairo_truetype_get_style (&scaled_font->base,
&weight,
&bold,
@@ -1466,13 +1468,13 @@ _cairo_win32_scaled_font_is_synthetic (void *abstract_font)
/* If this doesn't work assume it is not synthetic to avoid
* unnecessary subsetting fallbacks. */
if (status != CAIRO_STATUS_SUCCESS)
- return FALSE;
+ return CAIRO_STATUS_SUCCESS;
if (scaled_font->logfont.lfWeight != weight ||
scaled_font->logfont.lfItalic != italic)
- return TRUE;
+ *is_synthetic = TRUE;
- return FALSE;
+ return CAIRO_STATUS_SUCCESS;
}
static cairo_int_status_t
More information about the cairo-commit
mailing list