-
Notifications
You must be signed in to change notification settings - Fork 2.6k
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
Set overlap bit on every glyph in every VF and keep it set #4405
Comments
Don’t know if it is useful but this is the code I put in Cascadia Code’s build script to solve this problem:
|
I remember reading on the FreeType devel list that FT will switch to more expensive supersamling mode when encountering overlap bits, which is why setting them indiscriminately may be a bad idea. The script by @aaronbell is what we use in production to quickly set the bit if needed, per glyph :) No idea if something needs to be done for CFF2. |
This thread summarizes the state of the conversation around this as of late 2020 fonttools/fonttools#2059 |
FYI fonttools has pretty much this exact function in the instancer library: https://github.com/fonttools/fonttools/blob/main/Lib/fontTools/varLib/instancer/__init__.py#L1075 |
https://jsbin.com/xewuzew has examples of the problems which can better solved when these bits are set |
Please also keep in mind that these flags don’t currently make it into WOFF2 (there is no space for them). There is a proposal for revision to include them ( https://www.w3.org/TR/WOFF2/#p1 ) but I don’t know the implementation status of it. Certainly WOFF2 encoders (like fontTools or woff2_compress) and WOFF2 decoders (the libraries that are used by the browsers) will have to be updated to take this into account. The bits are retained in WOFF (1.0). |
I don’t know when these changes into WOFF2 will be adopted (into the spec, and into the software). Or perhaps something already silently is supporting these changes? If not, then for now I believe still WOFF 1.0 is a "safer" format for VF delivery than WOFF2. |
I fear that is indeed what we want, unless we think the reality is that most glyphs do have overlaps so we wouldn't really save much by avoiding setting it unnecessarily.
@garretrieger when do you expect the code change for this to hit https://github.com/google/woff2? |
Lorp: “It seems to me that the spec has been 100% clear on this since the early 1990s, and therefore I don’t agree with any suggestions to bypass it.” Adam: “ Please also keep in mind that these flags don’t currently make it into WOFF2 (there is no space for them).” wow. |
A quick glance through one master in a large multi-script project suggests that the ballpark may be many rather than most. n=1. |
I wrote this script to set the overlap bits and count how many overlaps there are: from __future__ import annotations
import argparse
from typing import Any, Mapping
import pathops
from fontTools.ttLib import TTFont
from fontTools.ttLib.removeOverlaps import componentsOverlap, skPathFromGlyph
from fontTools.ttLib.tables import _g_l_y_f
def set_overlap_bits_if_overlapping(varfont: TTFont) -> tuple[int, int]:
glyph_set = varfont.getGlyphSet()
glyf_table: _g_l_y_f.table__g_l_y_f = varfont["glyf"]
flag_overlap_compound = _g_l_y_f.OVERLAP_COMPOUND
flag_overlap_simple = _g_l_y_f.flagOverlapSimple
overlapping_contours = 0
overlapping_components = 0
for glyph_name in glyf_table.keys():
glyph = glyf_table[glyph_name]
# Set OVERLAP_COMPOUND bit for compound glyphs
if glyph.isComposite() and componentsOverlap(glyph, glyph_set):
overlapping_components += 1
glyph.components[0].flags |= flag_overlap_compound
# Set OVERLAP_SIMPLE bit for simple glyphs
elif glyph.numberOfContours > 0 and glyph_overlaps(glyph_name, glyph_set):
overlapping_contours += 1
glyph.flags[0] |= flag_overlap_simple
return (overlapping_contours, overlapping_components)
def glyph_overlaps(glyph_name: str, glyph_set: Mapping[str, Any]) -> bool:
path = skPathFromGlyph(glyph_name, glyph_set)
path2 = pathops.simplify(path, clockwise=path.clockwise) # remove overlaps
if path != path2:
return True
return False
parser = argparse.ArgumentParser()
parser.add_argument("font", nargs="+", type=TTFont)
parsed_args = parser.parse_args()
fonts: list[TTFont] = parsed_args.font
for font in fonts:
ocont, ocomp = set_overlap_bits_if_overlapping(font)
num_glyphs = font["maxp"].numGlyphs
ocont_p = ocont / num_glyphs
ocomp_p = ocomp / num_glyphs
print(
font.reader.file.name,
f"{num_glyphs} glyphs, {ocont} overlapping contours ({ocont_p:.2%}), {ocomp} overlapping components ({ocomp_p:.2%})",
)
font.save("a.ttf") I get the following exemplary results for some git master copies:
|
Lol. Range 14% - 98% overlapping. Now we know. :) |
If you want, I can run the script over https://github.com/googlefonts/noto-fonts/tree/main/unhinted/variable-ttf and also try to write a program to benchmark FreeType (not sure how long that would take though and how useful it would be -- I imagine setting the bits on the glyphs that need them and praying it's not too slow is the best we can do). |
Actually, running it over all of Noto's VFs is easy:
So yeah, a lot of variation depending on script I suppose. Running the script was fairly quick though, so I imagine in the typical non-CJK case, checking for overlap is fast enough to be on by default. |
Only at the default position in design space iiuc? How likely do we think it is the answer changes as you meander about the designspace? |
This would be very informative |
I have an updated implementation for https://github.com/google/woff2 written up that I'm just finalizing. Hopefully should be able to PR it next week. |
Yes :) Hm! I have no idea and it would take me some time to test this. |
What's the status here @m4rc1e? |
This issue impacts the Roboto family update as of the latest PR with variable font format files (#7231). Moving it into Q2 and we'll address how to approach it in advance of landing the Roboto format update. |
@emmamarichal Can I ask you to collaborate with Marc on this? Let's come up with a solution for Roboto that works across the rest of the catalog. It can be design outline changes, a compiler solution, a font editor solution, ... |
@m4rc1e mind summarizing the current consensus on the approach to our overlap bit flag settings in this thread? |
@rsheeter can we consider this an issue that will be addressed in the internal pipeline and in no further need of a new approach in the fonts? Will backlog for now and we can move it back into our work plan if we can define an improved approach for our VF format files. |
It would be actively harmful to do as this issues title suggests. I suggest we close it and open more targeted issues if necessary. |
Thanks Rod! That's great news for upstream :D |
In order for TT VFs to be correctly rendered with outlines, each glyph in the glyf table needs to have the overlap bit set, or ideally each glyph that has overlaps although that's more complicated to implement.
And we need string regression checks to prevent that slipping, and that will be easier as well if it's just all VF glyphs I suppose.
The text was updated successfully, but these errors were encountered: