-
Notifications
You must be signed in to change notification settings - Fork 226
Variable fonts #792
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Variable fonts #792
Conversation
9fb6470
to
45288ac
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Here is the first check.
Also, if I request Bahnschrift Semibold
, libass will actually select Bahnschrift Regular
. I haven't checked exactly why it happen, but it may be because the provider extended_family is Bahnschrift Semibold
and will be used for all the face of Bahnschrift which shouldn't be the case.
I used DirectWrite.
|
||
for (j = 0; j < variants->num_axis; j++) { | ||
if (a->tag == variants->axis[j].tag) { | ||
a->fvar_idx = j; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is incorrect.
For example, Alegreya - Original.zip
has 2 DesignAxisRecord (wght and ital) in the STAT table, but the fvar table only has 1 axis (wght).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The sample font alone doesn't tell me much without knowing how it behaves in GDI. What's this supposed to do?
* \return success | ||
*/ | ||
static void | ||
compute_variant_data(struct VariantData *data, const FT_Var_Named_Style *variant, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You don't use the GDI score algorithm.
Here is the algorithm: https://github.com/moi15moi/FontCollector/blob/7d82835aab9de817a4953f50bf69c9e688acb7ce/font_collector/font/font_parser.py#L96-L141
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm hoping we can document behavior in specific edge cases here (in particular, the documented behavior for format-4 tables differs from that code, and I'd like to confirm exactly what happens in those cases).
We run a search once with just the original name and no extended matches, then run substitutions, then run again with extended matches allowed.
This no longer adds any marginal cost.
This keeps an internal cache of all known names for all fonts, and loads them in when requested. This means that font metadata can be loaded on-demand using freetype, as with all other providers.
This removes dead provider-driven name handling code, unifies paths for system and memory fonts, and paves the way for variable font support. Notable behavior change: all GDI-compatible names we find are now stored in the families array; no distinction is made between family, full, and postscript names. This will allow for some simplification of matching code, and is necessary for variable font support.
- Inserts a copy of a font with different metadata for each named instance - When searching for a font, tries to match on sub-names by iteratively truncating at spaces
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not an expert on font selection, so mostly comments about cosmetics.
@@ -458,8 +458,10 @@ static int add_face(ASS_FontSelector *fontsel, ASS_Font *font, uint32_t ch) | |||
ass_charmap_magic(font->library, face); | |||
set_font_metrics(face); | |||
|
|||
font->faces[font->n_faces] = face; | |||
font->faces_uid[font->n_faces] = uid; | |||
font->faces[font->n_faces] = (ASS_Face){ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Style nit: I think it should be space here (ASS_Face) {
.
@@ -325,6 +325,54 @@ const CacheDesc glyph_metrics_cache_desc = { | |||
}; | |||
|
|||
|
|||
#ifdef CONFIG_FONTCONFIG |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe we should think about separating individual cache implementations from generic cache code? Number of caches grows and now ass_cache.c
consists of a ton of unrelated code.
{ | ||
FontconfigNameHashKey *k = key; | ||
FontconfigNameHashValue *v = value; | ||
free((char*)k->name.str); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Style nit: spaces (char *) k
.
#ifdef CONFIG_FONTCONFIG | ||
// describes list of known fonts corresponding to a given fontconfig name | ||
START(fontconfig_name, fontconfig_name_hash_key) | ||
STRING(name) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it would be more logically correct to use ASS_StringView
as cache key directly, but in that case automatic function generation wouldn't work. Maybe we should make string functions compatible with cache interface?
|
||
if (value->size >= value->capacity) { | ||
size_t new_cap = FFMAX(value->capacity, 1) * 2; | ||
void *resized = ass_realloc_array(value->patterns, new_cap, sizeof(FcPattern*)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Wouldn't it be better to use ASS_REALLOC_ARRAY
macro?
Also style: sizeof(FcPattern *)
.
if (!stat->value_groups) | ||
return false; | ||
|
||
int i, j; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Better to use loop-local counters.
compute_variant_data(struct VariantData *data, const FT_Var_Named_Style *variant, | ||
const struct STAT *stat) | ||
{ | ||
int i, j, k; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Better to use loop-local counters.
struct AppendedName *append = &data->appended_names[data->nb_appended_names++]; | ||
append->include_in_family = !elide_from_family; | ||
append->id = g->name_id; | ||
append->index = (FT_UInt)-1; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Style nit: space (FT_UInt) -1
.
struct AppendedName *append = &data->appended_names[data->nb_appended_names++]; | ||
append->include_in_family = false; | ||
append->id = stat->elidedFallbackNameID; | ||
append->index = (FT_UInt)-1; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Style nit: space (FT_UInt) -1
.
if (family_dup[len] == ' ') | ||
family_dup[len] = 0; | ||
|
||
if (!family_dup[len]) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Excess {}
.
Supersedes #789 and #790, and also adds variable font support, along with some other refactoring of font handling.
TODO:
find_font
instead of iterating the full global list (probably should be a separate PR after this one)