|
From: | Ahmet Göksu |
Subject: | Re: Progress update on adjustments database branch. |
Date: | Mon, 19 Jun 2023 23:08:34 +0300 |
Hello Craig (and Ahmet),
sorry for the very late reply, but right now there is soon the end of
the semester here in Austria, which means a lot of extra exams and
meetings.
To implement this adjustment, I inserted a step after all other
alignment steps in af_latin_hints_apply, which corrects the results
of the previous steps to ensure proper separation.
I think this is the right solution.
The function implementing that step looks up the glyph index to
determine what type of vertical separation is needed, or if it
doesn't apply. To do this, it uses a reverse character map that was
calculated by looking up every unicode code point referenced in the
adjustment database in the font's cmap and stored with the global
metrics.
As mentioned earlier, if everything works fine, this must be
eventually expanded to also cover glyphs only accessible via the
'GSUB' table.
I have also learned that fonts using multiple contours where a
single one would do isn't an unusual case, so a mode that does not
need to assume the bottom shape is 1 contour will be the next thing
I do.
Yes, this can happen especially in Variation Fonts.
Here are some pictures demonstrating the changes:
https://imgur.com/a/HXGY2oJ
Very nice! Please also post some images with text paragraphs at
different sizes so we get a feeling for the whole thing (see below
also).
BTW, please attach images directly to your e-mails so that they get
stored in the e-mail list archive, too.
Here are my main concerns about this approach:
- Because vertical separation adjustments are a step after all other
steps, they have the potential to clash with assumptions made by
the previous steps, or to violate constraints. Does anyone know
of issues I should watch out for?
I'm not aware of any. I consider the adjustments database as
something similar to the family of DELTA instructions in TrueType
bytecode, which are used for last-moment fixes to adjust certain glyph
points at certain PPEM values to ensure good rendering. This is
always done as the very last thing, right before rendering.
- To determine which contours are higher or lower, and to adjust
their position, the algorithm makes multiple passes through all
points in the glyph. Could this be a performance issue?
Ahmet, this would be a nice cooperation – can you test Craig's branch
with your code to check that?
- When the assumptions the algorithm makes are broken, it can do
extreme modifications to the glyph's shape. For example, this is
what happens when you tell it that the double quotes character
should be adjusted with the "one glyph stacked on another" mode:
https://imgur.com/a/JrUTMrQ
The algorithm arbitrarily chose one of the quotes as being higher,
and pushed it until it cleared the other one by a pixel. This
would happen in practice if someone mapped codepoint i to double
quotes in their font. How much of an issue is this? Do any fonts
do this?
FreeType always assumes that fonts do not cheat. In other words, the
mapping from the input character to the output character *must* be
correct. It was common practice in the days of very old Windows
versions (more than 20 years ago) that some fonts abuse the ASCII
range for, say, Hebrew glyphs because correct support was lacking.
Today, this is no longer an issue. So: no, this isn't an issue at
all.
I could prevent it by limiting the distance it can push something up
by a pixel or two.
This might be a good idea in general since sometimes glyphs are
designed in weird ways: For example, the two vertical strokes of the
doublequote character might have different vertical positions, and
such 'inaccuracies' (in the broadest sense) must not lead to bad
results.
- Werner previously suggested that a gap of less than one pixel,
instead of one full pixel as I'm currently doing, might be better
in some cases. Does anyone know of such a case?
'Waterfall images' of short paragraphs can answer this, I think, so
please post them for some selected fonts. BTW, I can also imagine the
opposite, namely that a separation of one pixel might not be
sufficiently large for some PPEM values to produce good-looking
output.
Werner
Test | Baseline | Benchmark |
---|---|---|
Load | 5.696 | 5.731 |
Load_Advances (Normal) | 4.633 | 4.656 |
Load_Advances (Fast) | 0.025 | 0.028 |
Load_Advances (Unscaled) | 0.024 | 0.026 |
Render | 3.618 | 3.607 |
Get_Glyph | 1.305 | 1.267 |
Get_Char_Index | 0.030 | 0.029 |
New_Face | 44.960 | 44.760 |
Embolden | 1.923 | 1.934 |
Stroke | 28.034 | 30.089 |
Get_BBox | 0.950 | 1.099 |
Get_CBox | 0.739 | 1.035 |
Test | Baseline | Benchmark |
---|---|---|
Load | 9.095 | 7.746 |
Load_Advances (Normal) | 7.753 | 7.354 |
Load_Advances (Fast) | 0.028 | 0.027 |
Load_Advances (Unscaled) | 0.025 | 0.025 |
Render | 3.740 | 3.950 |
Get_Glyph | 1.363 | 1.563 |
Get_Char_Index | 0.028 | 0.038 |
New_Face | 53.040 | 108.360 |
Embolden | 2.198 | 2.384 |
Stroke | 27.562 | 28.089 |
Get_BBox | 1.053 | 1.186 |
Get_CBox | 0.766 | 0.875 |
Test | Baseline | Benchmark |
---|---|---|
Load | 9.996 | 9.527 |
Load_Advances (Normal) | 8.718 | 9.458 |
Load_Advances (Fast) | 0.027 | 0.028 |
Load_Advances (Unscaled) | 0.024 | 0.039 |
Render | 4.139 | 4.242 |
Get_Glyph | 1.391 | 1.437 |
Get_Char_Index | 0.029 | 0.028 |
New_Face | 55.300 | 56.060 |
Embolden | 2.973 | 3.019 |
Stroke | 38.105 | 54.042 |
Get_BBox | 1.243 | 1.516 |
Get_CBox | 0.795 | 1.043 |
Test | Baseline | Benchmark |
---|---|---|
Load | 5.135 | 6.175 |
Load_Advances (Normal) | 4.866 | 5.195 |
Load_Advances (Fast) | 0.027 | 0.026 |
Load_Advances (Unscaled) | 0.025 | 0.025 |
Render | 3.472 | 3.514 |
Get_Glyph | 1.302 | 1.363 |
Get_Char_Index | 0.029 | 0.028 |
New_Face | 50.500 | 50.240 |
Embolden | 2.262 | 2.448 |
Stroke | 25.451 | 27.640 |
Get_BBox | 0.989 | 1.131 |
Get_CBox | 0.713 | 0.769 |
Test | Baseline | Benchmark |
---|---|---|
Load | 6.442 | 5.734 |
Load_Advances (Normal) | 4.672 | 4.898 |
Load_Advances (Fast) | 0.026 | 0.026 |
Load_Advances (Unscaled) | 0.024 | 0.025 |
Render | 3.493 | 3.645 |
Get_Glyph | 1.299 | 1.335 |
Get_Char_Index | 0.029 | 0.029 |
New_Face | 49.640 | 50.360 |
Embolden | 2.165 | 2.259 |
Stroke | 24.816 | 25.547 |
Get_BBox | 0.977 | 1.028 |
Get_CBox | 0.716 | 0.748 |
[Prev in Thread] | Current Thread | [Next in Thread] |