mirror of
https://gitlab.freedesktop.org/cairo/cairo.git
synced 2026-05-05 20:28:02 +02:00
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:
parent
9d44136ef8
commit
0fd0fd0ae9
6 changed files with 107 additions and 20 deletions
|
|
@ -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))
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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))
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue