subsetting: support variable fonts

If the font is a non default variant, fallback to creating a font from
the outlines.
This commit is contained in:
Adrian Johnson 2017-05-28 09:07:54 +09:30
parent 9d44136ef8
commit 0fd0fd0ae9
6 changed files with 107 additions and 20 deletions

View file

@ -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))

View file

@ -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

View file

@ -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,

View file

@ -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))

View file

@ -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.

View file

@ -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