Using HarfBuzz's API functions to construct the reverse map is too slow; we
have to call `hb_ot_layout_lookup_get_glyph_alternates` far too often
because it can only handle a single glyph at a time. For this reason we are
going to parse the GSUB table by ourselves.
The new non-local functions are `af_parse_gsub` and `af_map_lookup`.
* src/autofit/afgsub.c, src/autofit/afgsub.h: New files for parsing,
validating, and mapping the `SingleSubst` and `AlternateSubst` subtable
types of a GSUB table.
* src/autofit/autofit.c, src/autofit/rules.mk (AUTOF_DRV_SRC): Updated.
According to specifications, CVT and storage area may or may not be
persistent after modifications by a glyf program. FreeType had always
reset them, which was broken by the last commit.
* src/truetype/ttinterp.c (TT_Load_Context): Set CVT and storage here.
* src/truetype.ttobjs.c (tt_size_run_prep): Prioritize TT_Load_Context.
(tt_size_init_bytecode): Allocate but not set CVT and storage area.
To avoid repeated synchronization, some TT_Size allocations are moved
TT_ExecContext for good. The memory blocks are also consolidated.
* src/truetype/ttinterp.c (TT_{Load,Save,Done}_Context): Remove
synchronization and stack management.
* src/truetype/ttobjs.c (tt_size_{init,done}_bytecode): Manage allocations
and assign them to the execution context.
(tt_size_run_prep): Updated.
This replaces a large number of confusing boolean constructs that
describe the target rendering mode in the execution context with
the straight mode variable. It might fix some hidden bugs when
FT_LOAD_TARGET_XXX were used as flags, which they are not.
The condition that triggers the CV program re-execution is simplified.
These events due the rendering mode change are rather rare and unexpected
and, therefore, should not be over-analyzed. In v40, all mode changes
now trigger the CV program. In v35, only switches to/from mono do.
* src/truetype/ttinterp.h (TT_ExecContext): Replace 'grayscale',
'grayscale_cleartype', 'subpixel_hinting_lean', and 'vertical_lcd_lean'
with the rendering 'mode'.
* src/truetype/ttinterp.c (Ins_GETINFO): Updated.
* src/truetype/ttgload.c (tt_loader_init): Replace 'prep' re-execution
trigger and update 'backward_compatibility' condition.
(tt_loader_set_pp): Updated.
This avoids executing the CV program twice and cleans up the use of
'fpgm' and 'prep' triggers
* src/truetype/ttgload.c (tt_loader_init): Call 'tt_size_init_bytecode'
and 'tt_size_run_prep' explicitly and avoid the call repetition.
* src/truetype/ttobjs.c (tt_size_ready_bytecode): Removed as unused.
(tt_size_init, tt_size_init_bytecode, tt_size_done_bytecode): Remove some
'fpgm' and 'prep' triggers and update.
(tt_size_run_fpgm, tt_size_run_prep): Do not set the pedantic flag here.
* src/truetype/ttobjs.h: Update signatures.
This commit actually implements what commit 43ec023e1a describes.
* src/autofit/ft-hb.c (FT_RTLD_FLAGS): New macro for `dlopen`; it uses
`RTLD_GLOBAL` only if `RTLD_DEFAULT` is available.
This assures that twilight zone is reset before each CV program
execution, including after the rendering mode switch. Fixes#1344.
* src/truetype/ttobjs.c (tt_size_ready_bytecode): Relocate the GS
the twilight zone initiation from here...
(tt_size_run_prep): ... to this function, sho that it is always
done prior to the CV program execution.
* src/truetype/ttobjs.c (TT_Run_Context): Set twilight zone here...
(TT_Load_Context): ... rather than here, as it used to be.
This is a minor change with large code rearrangements.
* src/truetype/ttinterp.c (TT_RunIns): Just loop through instructions
and move all setup to...
(TT_Run_Context): ... here; relocated.
(Compute_Round): Replaced by simple assignment, removed.
This reduces dereferencing when calling the interpreter.
* include/freetype/internal/tttypes.h (TT_Face): Move it from here...
* src/truetype/ttinterp.h (TT_ExecContext): ... to here.
* src/truetype/ttobjs.c (tt_size_init_bytecode): Move its initialization
* src/truetype/ttinterp.c (TT_New_Context): ... to here.
(TT_Run_Context): Updated.
This reduces the number of function calls and data copying events.
* src/truetype/ttinterp.c (TT_Goto_CodeRange): Merge into...
(TT_Set_CodeRange): ... this function.
(TT_Load_Context): Do not set up any zones, copy GS, or prepare the
execution...
(TT_Run_Context): ... do this here instead..
* src/truetype/ttinterp.c (TT_Set_CodeRange): Update signature.
* src/truetype/ttobjs.c (tt_size_run_fpgm, tt_size_run_prep): Call
TT_Run_Context.
* src/truetype/ttgload.c (TT_Hint_Glyph, tt_loader_init): Updated.
Instead of restoring persistent GS variables, we only save modifications
permitted by the CVT program. This reduces the context manipulations.
* src/truetype/ttobjs.h (TT_GraphicsState): Reorder fields.
* src/truetype/ttobjs.c (tt_size_run_fpgm, tt_size_run_prep):
Do not alter the context.
* src/truetype/ttgload.c (TT_Hint_Glyph): Do not reset GS.
(tt_loader_init): Fix potential issue in 'instruct_control' handling.
* src/truetype/ttinterp.c (TT_Run_Context): Fully reset GS.
(TT_Load_Conext): Rearrange and remove the 'size' check, already
performed in FT_Load_Glyph.
(TT_Save_Context): Save only modifiable GS parts.
(tt_default_graphics_state): Updated.
* src/truetype/ttinterp.h (TT_Run_Context): Update signature.
With this commit, the following warning gets removed.
```
In file included from src/autofit/autofit.c:21:0:
src/autofit/ft-hb.c: In function 'ft_hb_funcs_init':
src/autofit/ft-hb.c:75:35: warning:
variable 'version_atleast' set but not used [-Wunused-but-set-variable]
ft_hb_version_atleast_func_t version_atleast = NULL;
^~~~~~~~~~~~~~~
```
* src/autofit/ft-hb.c (ft_hb_funcs_init): Move `NULL` check of
`version_atleast` out of ifdefs.
* CMakeLists.txt: Set `C_VISIBILITY_PRESET` to hidden for non-Windows only.
Windows handles exports with `DLL_EXPORT` defined, and old MinGW
toolchains emit a lot of warnings about visibility attributes not being
supported in this configuration.
* build/unix/configure.raw: Revise visibility attributes checks by compiling a
better test program with `-Werror` in `CFLAGS` so that warnings correctly
indicate unsupported configurations.
Set `have_harfbuzz*` variables explicitly to dynamic for MinGW, since
Windows uses its own `LoadLibrary` call.
This fixes a MinGW configuration error:
```
checking for HARFBUZZ... no
checking for dlopen in -lc... no
checking for dlopen in -ldl... no
configure: error: harfbuzz support requested but library not found
```
Using `RTLD_DEFAULT` we see whether the process already has HarfBuzz linked
in, and reuse it. If this symbol is not defined it is tempting to use
`RTLD_GLOBAL` instead, which would make the library available to the whole
process. However, without `RTLD_DEFAULT`, we would risk loading a second
HarfBuzz library, and if the linker mixes them up, probably giving symbols
from the new library to other clients, we might get into trouble. For this
reason, we do not pass `RTLD_GLOBAL` to `dlopen`; the default is
`RTLD_LOCAL`, and the rest of the process won't see the loaded HarfBuzz and
hopefully all be happy.
Big win, ~20% in measured mega-var font, HarfBuzz's `benchmark-font`
'glyph_h_advances' benchmark.
* src/truetype/ttgxvar.c (TT_Vary_Apply_Glyph_Deltas): Implement it in
loops.
Even if it was explicitly set by either design or normalized APIs.
Also update documentation.
* src/truetype/ttgxvar.c (TT_Set_MM_Blend, TT_Set_Var_Design): Use value -2
of `error` to indicate that we have a non-default instance.
(TT_Set_Named_Instance): Updated.
* src/base/ftmm.c (FT_Set_Var_Design_Coordinates,
FT_Set_Var_Blend_Coordinates): Updated.
Do all math in fixed integer and do a single divide at the end.
Also don't use an array to read deltas; just read them as we go, and skip
(branch-free) when scalar is 0.
30% speedup in measured mega-var font, HarfBuzz's `benchmark-font`
'glyph_h_advances' benchmark.