8000 Variable fonts by rcombs · Pull Request #792 · libass/libass · GitHub
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content

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

Draft
wants to merge 16 commits into
base: master
Choose a base branch
from
Draft

Variable fonts #792

wants to merge 16 commits into from

Conversation

rcombs
Copy link
Member
@rcombs rcombs commented Jun 20, 2024

Supersedes #789 and #790, and also adds variable font support, along with some other refactoring of font handling.

TODO:

  • Confirm GDI behavior on some edge cases around the STAT table (there are a couple cases where we believe the current behavior here is incorrect); cc @moi15moi
  • Consider cacheing a flag indicating that a given font has already been inserted; just requires a good key:
    • On CoreText and Fontconfig, path+index+psname works, but on DirectWrite this gets more complicated; LOGFONT name works sometimes, but not in the IDWriteFontSet case… maybe add a cache like the fontconfig one?
  • Consider inserting all GDI-compatible font names into a cache at load-time (similar to the fontconfig one) and searching that in find_font instead of iterating the full global list (probably should be a separate PR after this one)
    • Would require a downcase function but that should be fine

Copy link
Contributor
@moi15moi moi15moi left a 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;
Copy link
Contributor

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

Copy link
Member Author

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,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Member Author

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

rcombs added 16 commits June 24, 2024 22:31
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
Copy link
Member
@MrSmile MrSmile left a 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){
Copy link
Member

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
Copy link
Member

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);
Copy link
Member

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)
Copy link
Member

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*));
Copy link
Member

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;
Copy link
Member

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;
Copy link
Member

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;
Copy link
Member

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;
Copy link
Member

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]) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Excess {}.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants
0