Thu 09 Oct 2014 06:12:18 PM UTC, original submission:
Although clients shouldn't be asking for vertical metrics from fonts that don't support it, this should not return random/unitialized values.
This can occur in FT 2.5.3 when requesting vertical metrics from a font with embedded sbit data and no vertical metrics tables. One such font is kochi-mincho-subst.ttf.
The problem occurs in truetype load_sbit_image (ttgload.c). The sfnt's load_sbit_image function is called with an uninitialized TT_SBit_MetricsRec. This can call through to tt_face_load_sbit_image in ttsbit.c. If the table type is EBLC this calls tt_sbit_decoder_init, which sets the decoder to point at the uninitialized metrics struct, then calls tt_sbit_decoder_load_image. If the index format is 1, this does not load metrics directly, but goes to tt_sbit_decoder_load_bitmap. Here, if glyph_format is 2, this calls tt_sbit_decoder_load_metrics with 0 for 'big'. This sets the horizontal metrics in the decoder, but leaves the vertical metrics untouched, so they retain their uninitialized values.
Back in load_sbit_image, the error value is 0, so the metrics data, including the uninitialized vertical bearing and vertical advance, is copied into the glyph metrics. If FT_LOAD_VERTICAL_LAYOUT has been called, the glyphs' bitmap_left/_top values are set with these uninitialized values as well.
When this returns to TT_Load_Glyph, if the font is scalable, a loader is initialized and the glyph outline bbox is read via TT_Load_Glyph_Header. Metrics are read there, this time using TT_Get_H/VMetrics, which in this case synthesizes vertical metrics from the os2 table. These metrics are used to set the linear advances. There's a failsafe to set the horizontal advance if it is 0, but nothing to set the vertical advance, or the other metrics.
The end result is a glyph metrics field in which the vertical bearing and advance can be random values. If the FT_LOAD_VERTICAL_LAYOUT flag is set, the bitmap_left and _top values are random as well. This means that a subsequent call to FT_Glyph_Get_CBox, since this is a bitmap glyph, returns a garbage bounding box.
Note that FT_Get_Advance, if LOAD_ADVANCE_FAST_CHECK returns true, will return the advances from TT_Get_V/HMetrics. This is why FT_Get_Advance will return a reasonable advance for vertical metrics from this font, though TT_Load_Glyph does not.
While it's incorrect for clients to ask for vertical metrics from fonts that do not support them, I believe it's an error to return uninitialized data, particularly with no warning. This is especially unexpected since FT_Get_Advance can be used to get a usable vertical advance in this case (e.g. in HarfBuzz).
|