Protect FreeType face with mixed glyph formats.

It is possible for a single glyph to have multiple representations. In a
COLRv0 or COLRv1 font the outlines of the sub glyphs must be used as
layers or clips. Ensure that bitmaps and SVG representations are
explicitly excluded when loading glyphs with the express purpose of
retrieving any available outline.

Note that this does not touch the flags used in generatePath because in
that case a path should only be loaded if the glyph representation for
rendering is actually outline based.

Change-Id: I499e23aa20dacead81c7f76980039f139fa8edce
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/530676
Reviewed-by: Herb Derby <herb@google.com>
Commit-Queue: Ben Wagner <bungeman@google.com>
This commit is contained in:
Ben Wagner 2022-04-15 17:38:51 -04:00 committed by SkCQ
parent 21ca05d8bf
commit dc07bc6562
2 changed files with 15 additions and 8 deletions

View File

@ -1088,7 +1088,7 @@ bool SkScalerContext_FreeType::getCBoxForLetter(char letter, FT_BBox* bbox) {
if (!glyph_id) { if (!glyph_id) {
return false; return false;
} }
if (FT_Load_Glyph(fFace, glyph_id, fLoadGlyphFlags) != 0) { if (FT_Load_Glyph(fFace, glyph_id, fLoadGlyphFlags)) {
return false; return false;
} }
if (fFace->glyph->format != FT_GLYPH_FORMAT_OUTLINE) { if (fFace->glyph->format != FT_GLYPH_FORMAT_OUTLINE) {
@ -1209,13 +1209,16 @@ void SkScalerContext_FreeType::generateMetrics(SkGlyph* glyph, SkArenaAlloc* all
FT_LayerIterator layerIterator = { 0, 0, nullptr }; FT_LayerIterator layerIterator = { 0, 0, nullptr };
FT_UInt layerGlyphIndex; FT_UInt layerGlyphIndex;
FT_UInt layerColorIndex; FT_UInt layerColorIndex;
FT_Int32 flags = fLoadGlyphFlags;
flags |= FT_LOAD_BITMAP_METRICS_ONLY; // Don't decode any bitmaps.
flags |= FT_LOAD_NO_BITMAP; // Ignore embedded bitmaps.
flags &= ~FT_LOAD_RENDER; // Don't scan convert.
flags &= ~FT_LOAD_COLOR; // Ignore SVG.
// For COLRv0 compute the glyph bounding box from the union of layer bounding boxes. // For COLRv0 compute the glyph bounding box from the union of layer bounding boxes.
while (FT_Get_Color_Glyph_Layer(fFace, glyph->getGlyphID(), &layerGlyphIndex, while (FT_Get_Color_Glyph_Layer(fFace, glyph->getGlyphID(), &layerGlyphIndex,
&layerColorIndex, &layerIterator)) { &layerColorIndex, &layerIterator)) {
haveLayers = true; haveLayers = true;
if (FT_Load_Glyph(fFace, layerGlyphIndex, if (FT_Load_Glyph(fFace, layerGlyphIndex, flags)) {
fLoadGlyphFlags | FT_LOAD_BITMAP_METRICS_ONLY))
{
glyph->zeroMetrics(); glyph->zeroMetrics();
return; return;
} }

View File

@ -1660,8 +1660,10 @@ bool generateGlyphPathStatic(FT_Face face, SkPath* path) {
} }
bool generateFacePathStatic(FT_Face face, SkGlyphID glyphID, uint32_t loadGlyphFlags, SkPath* path){ bool generateFacePathStatic(FT_Face face, SkGlyphID glyphID, uint32_t loadGlyphFlags, SkPath* path){
loadGlyphFlags |= FT_LOAD_NO_BITMAP; // ignore embedded bitmaps so we're sure to get the outline loadGlyphFlags |= FT_LOAD_BITMAP_METRICS_ONLY; // Don't decode any bitmaps.
loadGlyphFlags &= ~FT_LOAD_RENDER; // don't scan convert (we just want the outline) loadGlyphFlags |= FT_LOAD_NO_BITMAP; // Ignore embedded bitmaps.
loadGlyphFlags &= ~FT_LOAD_RENDER; // Don't scan convert.
loadGlyphFlags &= ~FT_LOAD_COLOR; // Ignore SVG.
if (FT_Load_Glyph(face, glyphID, loadGlyphFlags)) { if (FT_Load_Glyph(face, glyphID, loadGlyphFlags)) {
path->reset(); path->reset();
return false; return false;
@ -1672,8 +1674,10 @@ bool generateFacePathStatic(FT_Face face, SkGlyphID glyphID, uint32_t loadGlyphF
#ifdef TT_SUPPORT_COLRV1 #ifdef TT_SUPPORT_COLRV1
bool generateFacePathCOLRv1(FT_Face face, SkGlyphID glyphID, SkPath* path) { bool generateFacePathCOLRv1(FT_Face face, SkGlyphID glyphID, SkPath* path) {
uint32_t flags = 0; uint32_t flags = 0;
flags |= FT_LOAD_NO_BITMAP; // ignore embedded bitmaps so we're sure to get the outline flags |= FT_LOAD_BITMAP_METRICS_ONLY; // Don't decode any bitmaps.
flags &= ~FT_LOAD_RENDER; // don't scan convert (we just want the outline) flags |= FT_LOAD_NO_BITMAP; // Ignore embedded bitmaps.
flags &= ~FT_LOAD_RENDER; // Don't scan convert.
flags &= ~FT_LOAD_COLOR; // Ignore SVG.
flags |= FT_LOAD_NO_HINTING; flags |= FT_LOAD_NO_HINTING;
flags |= FT_LOAD_NO_AUTOHINT; flags |= FT_LOAD_NO_AUTOHINT;
flags |= FT_LOAD_IGNORE_TRANSFORM; flags |= FT_LOAD_IGNORE_TRANSFORM;