зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1427641 - patch 3 - Add variation data to the cairo_ft_*_font objects, so they can properly track instances of the same font resource used with different variation parameters. r=lsalzman
This commit is contained in:
Родитель
5080cdedd5
Коммит
88ac266967
|
@ -397,7 +397,7 @@ ScaledFontFontconfig::CreateFromInstanceData(const InstanceData& aInstanceData,
|
||||||
FcPatternAddDouble(pattern, FC_PIXEL_SIZE, aSize);
|
FcPatternAddDouble(pattern, FC_PIXEL_SIZE, aSize);
|
||||||
aInstanceData.SetupPattern(pattern);
|
aInstanceData.SetupPattern(pattern);
|
||||||
|
|
||||||
cairo_font_face_t* font = cairo_ft_font_face_create_for_pattern(pattern);
|
cairo_font_face_t* font = cairo_ft_font_face_create_for_pattern(pattern, nullptr, 0);
|
||||||
if (cairo_font_face_status(font) != CAIRO_STATUS_SUCCESS) {
|
if (cairo_font_face_status(font) != CAIRO_STATUS_SUCCESS) {
|
||||||
gfxWarning() << "Failed creating Cairo font face for Fontconfig pattern";
|
gfxWarning() << "Failed creating Cairo font face for Fontconfig pattern";
|
||||||
FcPatternDestroy(pattern);
|
FcPatternDestroy(pattern);
|
||||||
|
|
|
@ -54,6 +54,7 @@
|
||||||
#include FT_IMAGE_H
|
#include FT_IMAGE_H
|
||||||
#include FT_BITMAP_H
|
#include FT_BITMAP_H
|
||||||
#include FT_TRUETYPE_TABLES_H
|
#include FT_TRUETYPE_TABLES_H
|
||||||
|
#include FT_MULTIPLE_MASTERS_H
|
||||||
#if HAVE_FT_GLYPHSLOT_EMBOLDEN
|
#if HAVE_FT_GLYPHSLOT_EMBOLDEN
|
||||||
#include FT_SYNTHESIS_H
|
#include FT_SYNTHESIS_H
|
||||||
#endif
|
#endif
|
||||||
|
@ -164,6 +165,10 @@ struct _cairo_ft_unscaled_font {
|
||||||
char *filename;
|
char *filename;
|
||||||
int id;
|
int id;
|
||||||
|
|
||||||
|
/* For variation fonts, the variation coordinates to apply to each axis. */
|
||||||
|
const FT_Fixed *var_coords;
|
||||||
|
int num_var_coords;
|
||||||
|
|
||||||
/* We temporarily scale the unscaled font as needed */
|
/* We temporarily scale the unscaled font as needed */
|
||||||
cairo_bool_t have_scale;
|
cairo_bool_t have_scale;
|
||||||
cairo_matrix_t current_scale;
|
cairo_matrix_t current_scale;
|
||||||
|
@ -360,6 +365,8 @@ _cairo_ft_unscaled_font_init_key (cairo_ft_unscaled_font_t *key,
|
||||||
cairo_bool_t from_face,
|
cairo_bool_t from_face,
|
||||||
char *filename,
|
char *filename,
|
||||||
int id,
|
int id,
|
||||||
|
const FT_Fixed *var_coords,
|
||||||
|
int num_var_coords,
|
||||||
FT_Face face)
|
FT_Face face)
|
||||||
{
|
{
|
||||||
unsigned long hash;
|
unsigned long hash;
|
||||||
|
@ -368,12 +375,16 @@ _cairo_ft_unscaled_font_init_key (cairo_ft_unscaled_font_t *key,
|
||||||
key->filename = filename;
|
key->filename = filename;
|
||||||
key->id = id;
|
key->id = id;
|
||||||
key->face = face;
|
key->face = face;
|
||||||
|
key->var_coords = var_coords;
|
||||||
|
key->num_var_coords = num_var_coords;
|
||||||
|
|
||||||
hash = _cairo_hash_string (filename);
|
hash = _cairo_hash_string (filename);
|
||||||
/* the constants are just arbitrary primes */
|
/* the constants are just arbitrary primes */
|
||||||
hash += ((unsigned long) id) * 1607;
|
hash += ((unsigned long) id) * 1607;
|
||||||
hash += ((unsigned long) face) * 2137;
|
hash += ((unsigned long) face) * 2137;
|
||||||
|
|
||||||
|
hash = _cairo_hash_bytes (hash, var_coords, num_var_coords * sizeof(FT_Fixed));
|
||||||
|
|
||||||
key->base.hash_entry.hash = hash;
|
key->base.hash_entry.hash = hash;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -403,6 +414,8 @@ _cairo_ft_unscaled_font_init (cairo_ft_unscaled_font_t *unscaled,
|
||||||
cairo_bool_t from_face,
|
cairo_bool_t from_face,
|
||||||
const char *filename,
|
const char *filename,
|
||||||
int id,
|
int id,
|
||||||
|
const FT_Fixed *var_coords,
|
||||||
|
int num_var_coords,
|
||||||
FT_Face face)
|
FT_Face face)
|
||||||
{
|
{
|
||||||
_cairo_unscaled_font_init (&unscaled->base,
|
_cairo_unscaled_font_init (&unscaled->base,
|
||||||
|
@ -410,7 +423,7 @@ _cairo_ft_unscaled_font_init (cairo_ft_unscaled_font_t *unscaled,
|
||||||
|
|
||||||
if (from_face) {
|
if (from_face) {
|
||||||
unscaled->from_face = TRUE;
|
unscaled->from_face = TRUE;
|
||||||
_cairo_ft_unscaled_font_init_key (unscaled, TRUE, NULL, 0, face);
|
_cairo_ft_unscaled_font_init_key (unscaled, TRUE, NULL, 0, var_coords, num_var_coords, face);
|
||||||
} else {
|
} else {
|
||||||
char *filename_copy;
|
char *filename_copy;
|
||||||
|
|
||||||
|
@ -421,7 +434,7 @@ _cairo_ft_unscaled_font_init (cairo_ft_unscaled_font_t *unscaled,
|
||||||
if (unlikely (filename_copy == NULL))
|
if (unlikely (filename_copy == NULL))
|
||||||
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
|
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
|
||||||
|
|
||||||
_cairo_ft_unscaled_font_init_key (unscaled, FALSE, filename_copy, id, NULL);
|
_cairo_ft_unscaled_font_init_key (unscaled, FALSE, filename_copy, id, var_coords, num_var_coords, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
unscaled->have_scale = FALSE;
|
unscaled->have_scale = FALSE;
|
||||||
|
@ -454,6 +467,11 @@ _cairo_ft_unscaled_font_fini (cairo_ft_unscaled_font_t *unscaled)
|
||||||
unscaled->filename = NULL;
|
unscaled->filename = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (unscaled->var_coords) {
|
||||||
|
free (unscaled->var_coords);
|
||||||
|
unscaled->var_coords = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
CAIRO_MUTEX_FINI (unscaled->mutex);
|
CAIRO_MUTEX_FINI (unscaled->mutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -465,12 +483,17 @@ _cairo_ft_unscaled_font_keys_equal (const void *key_a,
|
||||||
const cairo_ft_unscaled_font_t *unscaled_b = key_b;
|
const cairo_ft_unscaled_font_t *unscaled_b = key_b;
|
||||||
|
|
||||||
if (unscaled_a->id == unscaled_b->id &&
|
if (unscaled_a->id == unscaled_b->id &&
|
||||||
unscaled_a->from_face == unscaled_b->from_face)
|
unscaled_a->from_face == unscaled_b->from_face &&
|
||||||
|
unscaled_a->num_var_coords == unscaled_b->num_var_coords)
|
||||||
{
|
{
|
||||||
if (unscaled_a->from_face)
|
if (unscaled_a->from_face)
|
||||||
return unscaled_a->face == unscaled_b->face;
|
return unscaled_a->face == unscaled_b->face;
|
||||||
|
|
||||||
if (unscaled_a->filename == NULL && unscaled_b->filename == NULL)
|
if (unscaled_a->num_var_coords > 0 &&
|
||||||
|
(memcmp (unscaled_a->var_coords, unscaled_b->var_coords,
|
||||||
|
unscaled_a->num_var_coords * sizeof(FT_Fixed)) != 0))
|
||||||
|
return FALSE;
|
||||||
|
else if (unscaled_a->filename == NULL && unscaled_b->filename == NULL)
|
||||||
return TRUE;
|
return TRUE;
|
||||||
else if (unscaled_a->filename == NULL || unscaled_b->filename == NULL)
|
else if (unscaled_a->filename == NULL || unscaled_b->filename == NULL)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
@ -489,17 +512,20 @@ _cairo_ft_unscaled_font_create_internal (cairo_bool_t from_face,
|
||||||
char *filename,
|
char *filename,
|
||||||
int id,
|
int id,
|
||||||
FT_Face font_face,
|
FT_Face font_face,
|
||||||
|
const FT_Fixed *var_coords,
|
||||||
|
int num_var_coords,
|
||||||
cairo_ft_unscaled_font_t **out)
|
cairo_ft_unscaled_font_t **out)
|
||||||
{
|
{
|
||||||
cairo_ft_unscaled_font_t key, *unscaled;
|
cairo_ft_unscaled_font_t key, *unscaled;
|
||||||
cairo_ft_unscaled_font_map_t *font_map;
|
cairo_ft_unscaled_font_map_t *font_map;
|
||||||
|
FT_Fixed* new_var_coords = NULL;
|
||||||
cairo_status_t status;
|
cairo_status_t status;
|
||||||
|
|
||||||
font_map = _cairo_ft_unscaled_font_map_lock ();
|
font_map = _cairo_ft_unscaled_font_map_lock ();
|
||||||
if (unlikely (font_map == NULL))
|
if (unlikely (font_map == NULL))
|
||||||
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
|
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
|
||||||
|
|
||||||
_cairo_ft_unscaled_font_init_key (&key, from_face, filename, id, font_face);
|
_cairo_ft_unscaled_font_init_key (&key, from_face, filename, id, var_coords, num_var_coords, font_face);
|
||||||
|
|
||||||
/* Return existing unscaled font if it exists in the hash table. */
|
/* Return existing unscaled font if it exists in the hash table. */
|
||||||
unscaled = _cairo_hash_table_lookup (font_map->hash_table,
|
unscaled = _cairo_hash_table_lookup (font_map->hash_table,
|
||||||
|
@ -516,7 +542,17 @@ _cairo_ft_unscaled_font_create_internal (cairo_bool_t from_face,
|
||||||
goto UNWIND_FONT_MAP_LOCK;
|
goto UNWIND_FONT_MAP_LOCK;
|
||||||
}
|
}
|
||||||
|
|
||||||
status = _cairo_ft_unscaled_font_init (unscaled, from_face, filename, id, font_face);
|
/* If we have variation coordinate data, make a copy to save in the unscaled_font */
|
||||||
|
if (var_coords && num_var_coords) {
|
||||||
|
new_var_coords = malloc (num_var_coords * sizeof(FT_Fixed));
|
||||||
|
if (unlikely (!new_var_coords)) {
|
||||||
|
status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
|
||||||
|
goto UNWIND_VAR_COORDS;
|
||||||
|
}
|
||||||
|
memcpy (new_var_coords, var_coords, num_var_coords * sizeof(FT_Fixed));
|
||||||
|
}
|
||||||
|
|
||||||
|
status = _cairo_ft_unscaled_font_init (unscaled, from_face, filename, id, new_var_coords, num_var_coords, font_face);
|
||||||
if (unlikely (status))
|
if (unlikely (status))
|
||||||
goto UNWIND_UNSCALED_MALLOC;
|
goto UNWIND_UNSCALED_MALLOC;
|
||||||
|
|
||||||
|
@ -535,6 +571,8 @@ UNWIND_UNSCALED_FONT_INIT:
|
||||||
_cairo_ft_unscaled_font_fini (unscaled);
|
_cairo_ft_unscaled_font_fini (unscaled);
|
||||||
UNWIND_UNSCALED_MALLOC:
|
UNWIND_UNSCALED_MALLOC:
|
||||||
free (unscaled);
|
free (unscaled);
|
||||||
|
UNWIND_VAR_COORDS:
|
||||||
|
free (new_var_coords);
|
||||||
UNWIND_FONT_MAP_LOCK:
|
UNWIND_FONT_MAP_LOCK:
|
||||||
_cairo_ft_unscaled_font_map_unlock ();
|
_cairo_ft_unscaled_font_map_unlock ();
|
||||||
return status;
|
return status;
|
||||||
|
@ -544,6 +582,7 @@ UNWIND_FONT_MAP_LOCK:
|
||||||
#if CAIRO_HAS_FC_FONT
|
#if CAIRO_HAS_FC_FONT
|
||||||
static cairo_status_t
|
static cairo_status_t
|
||||||
_cairo_ft_unscaled_font_create_for_pattern (FcPattern *pattern,
|
_cairo_ft_unscaled_font_create_for_pattern (FcPattern *pattern,
|
||||||
|
const FT_Fixed *var_coords, int num_var_coords,
|
||||||
cairo_ft_unscaled_font_t **out)
|
cairo_ft_unscaled_font_t **out)
|
||||||
{
|
{
|
||||||
FT_Face font_face = NULL;
|
FT_Face font_face = NULL;
|
||||||
|
@ -576,15 +615,17 @@ _cairo_ft_unscaled_font_create_for_pattern (FcPattern *pattern,
|
||||||
DONE:
|
DONE:
|
||||||
return _cairo_ft_unscaled_font_create_internal (font_face != NULL,
|
return _cairo_ft_unscaled_font_create_internal (font_face != NULL,
|
||||||
filename, id, font_face,
|
filename, id, font_face,
|
||||||
|
var_coords, num_var_coords,
|
||||||
out);
|
out);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static cairo_status_t
|
static cairo_status_t
|
||||||
_cairo_ft_unscaled_font_create_from_face (FT_Face face,
|
_cairo_ft_unscaled_font_create_from_face (FT_Face face, const FT_Fixed *var_coords, int num_var_coords,
|
||||||
cairo_ft_unscaled_font_t **out)
|
cairo_ft_unscaled_font_t **out)
|
||||||
{
|
{
|
||||||
return _cairo_ft_unscaled_font_create_internal (TRUE, NULL, 0, face, out);
|
return _cairo_ft_unscaled_font_create_internal (TRUE, NULL, 0, face,
|
||||||
|
var_coords, num_var_coords, out);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -684,6 +725,19 @@ _cairo_ft_unscaled_font_lock_face (cairo_ft_unscaled_font_t *unscaled)
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (unscaled->var_coords) {
|
||||||
|
typedef FT_UInt (*SetCoordsFunc)(FT_Face, FT_UInt, FT_Fixed*);
|
||||||
|
static SetCoordsFunc setCoords;
|
||||||
|
static cairo_bool_t firstTime = TRUE;
|
||||||
|
if (firstTime) {
|
||||||
|
firstTime = FALSE;
|
||||||
|
(SetCoordsFunc)dlsym(RTLD_DEFAULT, "FT_Set_Var_Design_Coordinates");
|
||||||
|
}
|
||||||
|
if (setCoords) {
|
||||||
|
(*setCoords)(face, unscaled->num_var_coords, unscaled->var_coords);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
unscaled->face = face;
|
unscaled->face = face;
|
||||||
|
|
||||||
font_map->num_open_faces++;
|
font_map->num_open_faces++;
|
||||||
|
@ -3066,7 +3120,7 @@ _cairo_ft_resolve_pattern (FcPattern *pattern,
|
||||||
goto FREE_PATTERN;
|
goto FREE_PATTERN;
|
||||||
}
|
}
|
||||||
|
|
||||||
status = _cairo_ft_unscaled_font_create_for_pattern (resolved, &unscaled);
|
status = _cairo_ft_unscaled_font_create_for_pattern (resolved, NULL, 0, &unscaled);
|
||||||
if (unlikely (status || unscaled == NULL)) {
|
if (unlikely (status || unscaled == NULL)) {
|
||||||
font_face = (cairo_font_face_t *)&_cairo_font_face_nil;
|
font_face = (cairo_font_face_t *)&_cairo_font_face_nil;
|
||||||
goto FREE_RESOLVED;
|
goto FREE_RESOLVED;
|
||||||
|
@ -3123,14 +3177,17 @@ FREE_PATTERN:
|
||||||
* cairo_font_face_destroy() when you are done using it.
|
* cairo_font_face_destroy() when you are done using it.
|
||||||
**/
|
**/
|
||||||
cairo_font_face_t *
|
cairo_font_face_t *
|
||||||
cairo_ft_font_face_create_for_pattern (FcPattern *pattern)
|
cairo_ft_font_face_create_for_pattern (FcPattern *pattern,
|
||||||
|
const FT_Fixed *var_coords, int num_var_coords)
|
||||||
{
|
{
|
||||||
cairo_ft_unscaled_font_t *unscaled;
|
cairo_ft_unscaled_font_t *unscaled;
|
||||||
cairo_font_face_t *font_face;
|
cairo_font_face_t *font_face;
|
||||||
cairo_ft_options_t ft_options;
|
cairo_ft_options_t ft_options;
|
||||||
cairo_status_t status;
|
cairo_status_t status;
|
||||||
|
|
||||||
status = _cairo_ft_unscaled_font_create_for_pattern (pattern, &unscaled);
|
status = _cairo_ft_unscaled_font_create_for_pattern (pattern,
|
||||||
|
var_coords, num_var_coords,
|
||||||
|
&unscaled);
|
||||||
if (unlikely (status))
|
if (unlikely (status))
|
||||||
return (cairo_font_face_t *) &_cairo_font_face_nil;
|
return (cairo_font_face_t *) &_cairo_font_face_nil;
|
||||||
if (unlikely (unscaled == NULL)) {
|
if (unlikely (unscaled == NULL)) {
|
||||||
|
@ -3200,14 +3257,18 @@ cairo_ft_font_face_create_for_pattern (FcPattern *pattern)
|
||||||
**/
|
**/
|
||||||
cairo_font_face_t *
|
cairo_font_face_t *
|
||||||
cairo_ft_font_face_create_for_ft_face (FT_Face face,
|
cairo_ft_font_face_create_for_ft_face (FT_Face face,
|
||||||
int load_flags)
|
int load_flags,
|
||||||
|
const FT_Fixed *var_coords,
|
||||||
|
int num_var_coords)
|
||||||
{
|
{
|
||||||
cairo_ft_unscaled_font_t *unscaled;
|
cairo_ft_unscaled_font_t *unscaled;
|
||||||
cairo_font_face_t *font_face;
|
cairo_font_face_t *font_face;
|
||||||
cairo_ft_options_t ft_options;
|
cairo_ft_options_t ft_options;
|
||||||
cairo_status_t status;
|
cairo_status_t status;
|
||||||
|
|
||||||
status = _cairo_ft_unscaled_font_create_from_face (face, &unscaled);
|
status = _cairo_ft_unscaled_font_create_from_face (face,
|
||||||
|
var_coords, num_var_coords,
|
||||||
|
&unscaled);
|
||||||
if (unlikely (status))
|
if (unlikely (status))
|
||||||
return (cairo_font_face_t *)&_cairo_font_face_nil;
|
return (cairo_font_face_t *)&_cairo_font_face_nil;
|
||||||
|
|
||||||
|
|
|
@ -54,7 +54,9 @@ CAIRO_BEGIN_DECLS
|
||||||
|
|
||||||
cairo_public cairo_font_face_t *
|
cairo_public cairo_font_face_t *
|
||||||
cairo_ft_font_face_create_for_ft_face (FT_Face face,
|
cairo_ft_font_face_create_for_ft_face (FT_Face face,
|
||||||
int load_flags);
|
int load_flags,
|
||||||
|
const FT_Fixed *var_coords,
|
||||||
|
int num_var_coords);
|
||||||
|
|
||||||
cairo_public FT_Face
|
cairo_public FT_Face
|
||||||
cairo_ft_scaled_font_lock_face (cairo_scaled_font_t *scaled_font);
|
cairo_ft_scaled_font_lock_face (cairo_scaled_font_t *scaled_font);
|
||||||
|
@ -65,7 +67,9 @@ cairo_ft_scaled_font_unlock_face (cairo_scaled_font_t *scaled_font);
|
||||||
#if CAIRO_HAS_FC_FONT
|
#if CAIRO_HAS_FC_FONT
|
||||||
|
|
||||||
cairo_public cairo_font_face_t *
|
cairo_public cairo_font_face_t *
|
||||||
cairo_ft_font_face_create_for_pattern (FcPattern *pattern);
|
cairo_ft_font_face_create_for_pattern (FcPattern *pattern,
|
||||||
|
const FT_Fixed *var_coords,
|
||||||
|
int num_var_coords);
|
||||||
|
|
||||||
cairo_public void
|
cairo_public void
|
||||||
cairo_ft_font_options_substitute (const cairo_font_options_t *options,
|
cairo_ft_font_options_substitute (const cairo_font_options_t *options,
|
||||||
|
|
|
@ -207,32 +207,18 @@ gfxFT2FontBase::InitMetrics()
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// For variation fonts, figure out the variation coordinates to be applied
|
if (!mStyle.variationSettings.IsEmpty()) {
|
||||||
// for each axis, in freetype's order (which may not match the order of
|
SetupVarCoords(face, mStyle.variationSettings, &mCoords);
|
||||||
// axes in mStyle.variationSettings, so we need to search by axis tag).
|
|
||||||
if (face->face_flags & FT_FACE_FLAG_MULTIPLE_MASTERS) {
|
|
||||||
typedef FT_UInt (*GetVarFunc)(FT_Face, FT_MM_Var**);
|
|
||||||
typedef FT_UInt (*SetCoordsFunc)(FT_Face, FT_UInt, FT_Fixed*);
|
|
||||||
static GetVarFunc getVar =
|
|
||||||
(GetVarFunc)dlsym(RTLD_DEFAULT, "FT_Get_MM_Var");
|
|
||||||
static SetCoordsFunc setCoords =
|
|
||||||
(SetCoordsFunc)dlsym(RTLD_DEFAULT, "FT_Set_Var_Design_Coordinates");
|
|
||||||
FT_MM_Var* ftVar;
|
|
||||||
if (getVar && setCoords && FT_Err_Ok == (*getVar)(face, &ftVar)) {
|
|
||||||
for (unsigned i = 0; i < ftVar->num_axis; ++i) {
|
|
||||||
mCoords.AppendElement(ftVar->axis[i].def);
|
|
||||||
for (const auto& v : mStyle.variationSettings) {
|
|
||||||
if (ftVar->axis[i].tag == v.mTag) {
|
|
||||||
FT_Fixed val = v.mValue * 0x10000;
|
|
||||||
val = std::min(val, ftVar->axis[i].maximum);
|
|
||||||
val = std::max(val, ftVar->axis[i].minimum);
|
|
||||||
mCoords[i] = val;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
free(ftVar);
|
|
||||||
if (!mCoords.IsEmpty()) {
|
if (!mCoords.IsEmpty()) {
|
||||||
|
typedef FT_UInt (*SetCoordsFunc)(FT_Face, FT_UInt, FT_Fixed*);
|
||||||
|
static SetCoordsFunc setCoords;
|
||||||
|
static bool firstTime = true;
|
||||||
|
if (firstTime) {
|
||||||
|
firstTime = false;
|
||||||
|
setCoords = (SetCoordsFunc)
|
||||||
|
dlsym(RTLD_DEFAULT, "FT_Set_Var_Design_Coordinates");
|
||||||
|
}
|
||||||
|
if (setCoords) {
|
||||||
(*setCoords)(face, mCoords.Length(), mCoords.Elements());
|
(*setCoords)(face, mCoords.Length(), mCoords.Elements());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -581,3 +567,40 @@ gfxFT2FontBase::SetupCairoFont(DrawTarget* aDrawTarget)
|
||||||
cairo_set_scaled_font(gfxFont::RefCairo(aDrawTarget), cairoFont);
|
cairo_set_scaled_font(gfxFont::RefCairo(aDrawTarget), cairoFont);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// For variation fonts, figure out the variation coordinates to be applied
|
||||||
|
// for each axis, in freetype's order (which may not match the order of
|
||||||
|
// axes in mStyle.variationSettings, so we need to search by axis tag).
|
||||||
|
/*static*/
|
||||||
|
void
|
||||||
|
gfxFT2FontBase::SetupVarCoords(FT_Face aFace,
|
||||||
|
const nsTArray<gfxFontVariation>& aVariations,
|
||||||
|
nsTArray<FT_Fixed>* aCoords)
|
||||||
|
{
|
||||||
|
aCoords->TruncateLength(0);
|
||||||
|
if (aFace->face_flags & FT_FACE_FLAG_MULTIPLE_MASTERS) {
|
||||||
|
typedef FT_UInt (*GetVarFunc)(FT_Face, FT_MM_Var**);
|
||||||
|
static GetVarFunc getVar;
|
||||||
|
static bool firstTime = true;
|
||||||
|
if (firstTime) {
|
||||||
|
firstTime = false;
|
||||||
|
getVar = (GetVarFunc)dlsym(RTLD_DEFAULT, "FT_Get_MM_Var");
|
||||||
|
}
|
||||||
|
FT_MM_Var* ftVar;
|
||||||
|
if (getVar && FT_Err_Ok == (*getVar)(aFace, &ftVar)) {
|
||||||
|
for (unsigned i = 0; i < ftVar->num_axis; ++i) {
|
||||||
|
aCoords->AppendElement(ftVar->axis[i].def);
|
||||||
|
for (const auto& v : aVariations) {
|
||||||
|
if (ftVar->axis[i].tag == v.mTag) {
|
||||||
|
FT_Fixed val = v.mValue * 0x10000;
|
||||||
|
val = std::min(val, ftVar->axis[i].maximum);
|
||||||
|
val = std::max(val, ftVar->axis[i].minimum);
|
||||||
|
(*aCoords)[i] = val;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
free(ftVar);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -38,6 +38,10 @@ public:
|
||||||
|
|
||||||
virtual FontType GetType() const override { return FONT_TYPE_FT2; }
|
virtual FontType GetType() const override { return FONT_TYPE_FT2; }
|
||||||
|
|
||||||
|
static void SetupVarCoords(FT_Face aFace,
|
||||||
|
const nsTArray<gfxFontVariation>& aVariations,
|
||||||
|
nsTArray<FT_Fixed>* aCoords);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
uint32_t GetCharExtents(char aChar, cairo_text_extents_t* aExtents);
|
uint32_t GetCharExtents(char aChar, cairo_text_extents_t* aExtents);
|
||||||
void InitMetrics();
|
void InitMetrics();
|
||||||
|
|
|
@ -390,7 +390,7 @@ FT2FontEntry::CreateFontEntry(FT_Face aFace,
|
||||||
int flags = gfxPlatform::GetPlatform()->FontHintingEnabled() ?
|
int flags = gfxPlatform::GetPlatform()->FontHintingEnabled() ?
|
||||||
FT_LOAD_DEFAULT :
|
FT_LOAD_DEFAULT :
|
||||||
(FT_LOAD_NO_AUTOHINT | FT_LOAD_NO_HINTING);
|
(FT_LOAD_NO_AUTOHINT | FT_LOAD_NO_HINTING);
|
||||||
fe->mFontFace = cairo_ft_font_face_create_for_ft_face(aFace, flags);
|
fe->mFontFace = cairo_ft_font_face_create_for_ft_face(aFace, flags, nullptr, 0);
|
||||||
FTUserFontData *userFontData = new FTUserFontData(aFace, aFontData);
|
FTUserFontData *userFontData = new FTUserFontData(aFace, aFontData);
|
||||||
cairo_font_face_set_user_data(fe->mFontFace, &sFTUserFontDataKey,
|
cairo_font_face_set_user_data(fe->mFontFace, &sFTUserFontDataKey,
|
||||||
userFontData, FTFontDestroyFunc);
|
userFontData, FTFontDestroyFunc);
|
||||||
|
@ -434,7 +434,7 @@ FT2FontEntry::CairoFontFace()
|
||||||
int flags = gfxPlatform::GetPlatform()->FontHintingEnabled() ?
|
int flags = gfxPlatform::GetPlatform()->FontHintingEnabled() ?
|
||||||
FT_LOAD_DEFAULT :
|
FT_LOAD_DEFAULT :
|
||||||
(FT_LOAD_NO_AUTOHINT | FT_LOAD_NO_HINTING);
|
(FT_LOAD_NO_AUTOHINT | FT_LOAD_NO_HINTING);
|
||||||
mFontFace = cairo_ft_font_face_create_for_ft_face(face, flags);
|
mFontFace = cairo_ft_font_face_create_for_ft_face(face, flags, nullptr, 0);
|
||||||
FTUserFontData *userFontData = new FTUserFontData(face, face.FontData());
|
FTUserFontData *userFontData = new FTUserFontData(face, face.FontData());
|
||||||
cairo_font_face_set_user_data(mFontFace, &sFTUserFontDataKey,
|
cairo_font_face_set_user_data(mFontFace, &sFTUserFontDataKey,
|
||||||
userFontData, FTFontDestroyFunc);
|
userFontData, FTFontDestroyFunc);
|
||||||
|
|
|
@ -694,8 +694,19 @@ gfxFontconfigFontEntry::CreateScaledFont(FcPattern* aRenderPattern,
|
||||||
FcPatternAddBool(aRenderPattern, FC_EMBEDDED_BITMAP, FcFalse);
|
FcPatternAddBool(aRenderPattern, FC_EMBEDDED_BITMAP, FcFalse);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
AutoTArray<FT_Fixed,8> coords;
|
||||||
|
if (!aStyle->variationSettings.IsEmpty()) {
|
||||||
|
FT_Face ftFace = GetFTFace();
|
||||||
|
if (ftFace) {
|
||||||
|
gfxFT2FontBase::SetupVarCoords(ftFace, aStyle->variationSettings,
|
||||||
|
&coords);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
cairo_font_face_t *face =
|
cairo_font_face_t *face =
|
||||||
cairo_ft_font_face_create_for_pattern(aRenderPattern);
|
cairo_ft_font_face_create_for_pattern(aRenderPattern,
|
||||||
|
coords.Elements(),
|
||||||
|
coords.Length());
|
||||||
|
|
||||||
if (mFontData) {
|
if (mFontData) {
|
||||||
// for data fonts, add the face/data pointer to the cairo font face
|
// for data fonts, add the face/data pointer to the cairo font face
|
||||||
|
@ -928,6 +939,24 @@ gfxFontconfigFontEntry::CreateFontInstance(const gfxFontStyle *aFontStyle,
|
||||||
return newFont;
|
return newFont;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
FT_Face
|
||||||
|
gfxFontconfigFontEntry::GetFTFace()
|
||||||
|
{
|
||||||
|
if (!mFTFaceInitialized) {
|
||||||
|
mFTFaceInitialized = true;
|
||||||
|
FcChar8 *filename;
|
||||||
|
if (FcPatternGetString(mFontPattern, FC_FILE, 0, &filename) != FcResultMatch) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
int index;
|
||||||
|
if (FcPatternGetInteger(mFontPattern, FC_INDEX, 0, &index) != FcResultMatch) {
|
||||||
|
index = 0; // default to 0 if not found in pattern
|
||||||
|
}
|
||||||
|
mFTFace = Factory::NewFTFace(nullptr, ToCharPtr(filename), index);
|
||||||
|
}
|
||||||
|
return mFTFace;
|
||||||
|
}
|
||||||
|
|
||||||
nsresult
|
nsresult
|
||||||
gfxFontconfigFontEntry::CopyFontTable(uint32_t aTableTag,
|
gfxFontconfigFontEntry::CopyFontTable(uint32_t aTableTag,
|
||||||
nsTArray<uint8_t>& aBuffer)
|
nsTArray<uint8_t>& aBuffer)
|
||||||
|
@ -935,34 +964,19 @@ gfxFontconfigFontEntry::CopyFontTable(uint32_t aTableTag,
|
||||||
NS_ASSERTION(!mIsDataUserFont,
|
NS_ASSERTION(!mIsDataUserFont,
|
||||||
"data fonts should be reading tables directly from memory");
|
"data fonts should be reading tables directly from memory");
|
||||||
|
|
||||||
if (!mFTFaceInitialized) {
|
FT_Face face = GetFTFace();
|
||||||
mFTFaceInitialized = true;
|
if (!face) {
|
||||||
FcChar8 *filename;
|
|
||||||
if (FcPatternGetString(mFontPattern, FC_FILE, 0, &filename) != FcResultMatch) {
|
|
||||||
return NS_ERROR_FAILURE;
|
|
||||||
}
|
|
||||||
int index;
|
|
||||||
if (FcPatternGetInteger(mFontPattern, FC_INDEX, 0, &index) != FcResultMatch) {
|
|
||||||
index = 0; // default to 0 if not found in pattern
|
|
||||||
}
|
|
||||||
mFTFace = Factory::NewFTFace(nullptr, ToCharPtr(filename), index);
|
|
||||||
if (!mFTFace) {
|
|
||||||
return NS_ERROR_FAILURE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!mFTFace) {
|
|
||||||
return NS_ERROR_NOT_AVAILABLE;
|
return NS_ERROR_NOT_AVAILABLE;
|
||||||
}
|
}
|
||||||
|
|
||||||
FT_ULong length = 0;
|
FT_ULong length = 0;
|
||||||
if (FT_Load_Sfnt_Table(mFTFace, aTableTag, 0, nullptr, &length) != 0) {
|
if (FT_Load_Sfnt_Table(face, aTableTag, 0, nullptr, &length) != 0) {
|
||||||
return NS_ERROR_NOT_AVAILABLE;
|
return NS_ERROR_NOT_AVAILABLE;
|
||||||
}
|
}
|
||||||
if (!aBuffer.SetLength(length, fallible)) {
|
if (!aBuffer.SetLength(length, fallible)) {
|
||||||
return NS_ERROR_OUT_OF_MEMORY;
|
return NS_ERROR_OUT_OF_MEMORY;
|
||||||
}
|
}
|
||||||
if (FT_Load_Sfnt_Table(mFTFace, aTableTag, 0, aBuffer.Elements(), &length) != 0) {
|
if (FT_Load_Sfnt_Table(face, aTableTag, 0, aBuffer.Elements(), &length) != 0) {
|
||||||
aBuffer.Clear();
|
aBuffer.Clear();
|
||||||
return NS_ERROR_FAILURE;
|
return NS_ERROR_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
|
@ -112,6 +112,8 @@ public:
|
||||||
nsresult ReadCMAP(FontInfoData *aFontInfoData = nullptr) override;
|
nsresult ReadCMAP(FontInfoData *aFontInfoData = nullptr) override;
|
||||||
bool TestCharacterMap(uint32_t aCh) override;
|
bool TestCharacterMap(uint32_t aCh) override;
|
||||||
|
|
||||||
|
FT_Face GetFTFace();
|
||||||
|
|
||||||
hb_blob_t* GetFontTable(uint32_t aTableTag) override;
|
hb_blob_t* GetFontTable(uint32_t aTableTag) override;
|
||||||
|
|
||||||
void ForgetHBFace() override;
|
void ForgetHBFace() override;
|
||||||
|
|
Загрузка…
Ссылка в новой задаче