Plumb FreeType glyph loading flags for COLRv0.

Previously, FreeType was always instructed to hint or autohint the layer
glyphs of COLRv0 fonts. Instead, pass the appropriate loading flags
through so that the layer glyphs will be created similarly to how the
base glyph would be handled. The behavior change is gated on
SK_IGNORE_FREETYPE_COLRV0_LOAD_FLAGS_FIX because this will require
rebaselining some Blink layout tests.

Also ensure that COLRv1 subglyphs are never hinted or autohinted for
now. These are a bit more complex and allowing hinting will need to be
handled separately.

Bug: skia:12956
Change-Id: Ia69f7a0e207b1af885ed5039f9e53007125b707e
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/510876
Reviewed-by: Ben Wagner <bungeman@google.com>
Reviewed-by: Dominik Röttsches <drott@google.com>
Commit-Queue: Ben Wagner <bungeman@google.com>
This commit is contained in:
Ben Wagner 2022-02-18 16:18:14 -05:00 committed by SkCQ
parent cd0e202767
commit ed0e1a8af7
3 changed files with 37 additions and 31 deletions

View File

@ -1381,7 +1381,7 @@ void SkScalerContext_FreeType::generateImage(const SkGlyph& glyph) {
}
SkSpan<SkColor> palette(fFaceRec->fSkPalette.get(), fFaceRec->fFTPaletteEntryCount);
generateGlyphImage(fFace, palette, glyph, *bitmapMatrix);
generateGlyphImage(fFace, glyph, fLoadGlyphFlags, palette, *bitmapMatrix);
}
sk_sp<SkDrawable> SkScalerContext_FreeType::generateDrawable(const SkGlyph& glyph) {
@ -1409,7 +1409,7 @@ sk_sp<SkDrawable> SkScalerContext_FreeType::generateDrawable(const SkGlyph& glyp
emboldenIfNeeded(fFace, fFace->glyph, glyph.getGlyphID());
SkSpan<SkColor> palette(fFaceRec->fSkPalette.get(), fFaceRec->fFTPaletteEntryCount);
return generateGlyphDrawable(fFace, palette, glyph);
return generateGlyphDrawable(fFace, glyph, fLoadGlyphFlags, palette);
}
bool SkScalerContext_FreeType::generatePath(const SkGlyph& glyph, SkPath* path) {

View File

@ -1237,10 +1237,11 @@ bool colrv1_start_glyph_bounds(SkMatrix *ctm,
} // namespace
#ifdef FT_COLOR_H
bool SkScalerContext_FreeType_Base::drawColorGlyph(SkCanvas* canvas,
FT_Face face,
bool SkScalerContext_FreeType_Base::drawColorGlyph(FT_Face face,
const SkGlyph& glyph,
uint32_t loadGlyphFlags,
SkSpan<SkColor> palette,
const SkGlyph& glyph) {
SkCanvas* canvas) {
SkPaint paint;
paint.setAntiAlias(true);
@ -1272,7 +1273,7 @@ bool SkScalerContext_FreeType_Base::drawColorGlyph(SkCanvas* canvas,
paint.setColor(palette[layerColorIndex]);
}
SkPath path;
if (this->generateFacePath(face, layerGlyphIndex, &path)) {
if (this->generateFacePath(face, layerGlyphIndex, loadGlyphFlags, &path)) {
canvas->drawPath(path, paint);
}
}
@ -1280,11 +1281,11 @@ bool SkScalerContext_FreeType_Base::drawColorGlyph(SkCanvas* canvas,
}
#endif // FT_COLOR_H
void SkScalerContext_FreeType_Base::generateGlyphImage(
FT_Face face,
SkSpan<SkColor> customPalette,
const SkGlyph& glyph,
const SkMatrix& bitmapTransform)
void SkScalerContext_FreeType_Base::generateGlyphImage(FT_Face face,
const SkGlyph& glyph,
uint32_t loadGlyphFlags,
SkSpan<SkColor> customPalette,
const SkMatrix& bitmapTransform)
{
const bool doBGR = SkToBool(fRec.fFlags & SkScalerContext::kLCD_BGROrder_Flag);
const bool doVert = SkToBool(fRec.fFlags & SkScalerContext::kLCD_Vertical_Flag);
@ -1327,7 +1328,8 @@ void SkScalerContext_FreeType_Base::generateGlyphImage(
SkFixedToScalar(glyph.getSubYFixed()));
}
bool haveLayers = this->drawColorGlyph(&canvas, face, customPalette, glyph);
bool haveLayers = this->drawColorGlyph(face, glyph, loadGlyphFlags,
customPalette, &canvas);
if (!haveLayers) {
SkDebugf("Could not get layers (neither v0, nor v1) from %s fontFace.",
@ -1645,12 +1647,14 @@ bool generateGlyphPathStatic(FT_Face face, SkPath* path) {
return true;
}
bool generateFacePathStatic(FT_Face face, SkGlyphID glyphID, SkPath* path) {
uint32_t flags = 0; //fLoadGlyphFlags;
flags |= FT_LOAD_NO_BITMAP; // ignore embedded bitmaps so we're sure to get the outline
flags &= ~FT_LOAD_RENDER; // don't scan convert (we just want the outline)
bool generateFacePathStatic(FT_Face face, SkGlyphID glyphID, uint32_t loadGlyphFlags, SkPath* path){
#ifdef SK_IGNORE_FREETYPE_COLRV0_LOAD_FLAGS_FIX
loadGlyphFlags = 0;
#endif
loadGlyphFlags |= FT_LOAD_NO_BITMAP; // ignore embedded bitmaps so we're sure to get the outline
loadGlyphFlags &= ~FT_LOAD_RENDER; // don't scan convert (we just want the outline)
FT_Error err = FT_Load_Glyph(face, glyphID, flags);
FT_Error err = FT_Load_Glyph(face, glyphID, loadGlyphFlags);
if (err != 0) {
path->reset();
return false;
@ -1668,16 +1672,17 @@ bool generateFacePathCOLRv1(FT_Face face, SkGlyphID glyphID, SkPath* path) {
uint32_t flags = 0;
flags |= FT_LOAD_NO_BITMAP; // ignore embedded bitmaps so we're sure to get the outline
flags &= ~FT_LOAD_RENDER; // don't scan convert (we just want the outline)
flags |= FT_LOAD_NO_HINTING;
flags |= FT_LOAD_NO_AUTOHINT;
flags |= FT_LOAD_IGNORE_TRANSFORM;
using DoneFTSize = SkFunctionWrapper<decltype(FT_Done_Size), FT_Done_Size>;
std::unique_ptr<std::remove_pointer_t<FT_Size>, DoneFTSize> unscaledFtSize([face]() -> FT_Size {
FT_Size size;
FT_Error err = FT_New_Size(face, &size);
if (err != 0) {
SK_TRACEFTR(err, "FT_New_Size(%s) failed in generateFacePathStaticCOLRv1.", face->family_name);
SK_TRACEFTR(err, "FT_New_Size(%s) failed in generateFacePathStaticCOLRv1.",
face->family_name);
return nullptr;
}
return size;
@ -1733,8 +1738,9 @@ bool SkScalerContext_FreeType_Base::generateGlyphPath(FT_Face face, SkPath* path
bool SkScalerContext_FreeType_Base::generateFacePath(FT_Face face,
SkGlyphID glyphID,
uint32_t loadGlyphFlags,
SkPath* path) {
return generateFacePathStatic(face, glyphID, path);
return generateFacePathStatic(face, glyphID, loadGlyphFlags, path);
}
bool SkScalerContext_FreeType_Base::computeColrV1GlyphBoundingBox(FT_Face face,
@ -1764,12 +1770,12 @@ bool SkScalerContext_FreeType_Base::computeColrV1GlyphBoundingBox(FT_Face face,
}
sk_sp<SkDrawable> SkScalerContext_FreeType_Base::generateGlyphDrawable(
FT_Face face, SkSpan<SkColor> palette, const SkGlyph& glyph) {
FT_Face face, const SkGlyph& glyph, uint32_t loadGlyphFlags, SkSpan<SkColor> palette) {
#ifdef FT_COLOR_H
if (face->glyph->format == FT_GLYPH_FORMAT_OUTLINE && glyph.isColor()) {
SkPictureRecorder recorder;
SkCanvas* recordingCanvas = recorder.beginRecording(SkRect::Make(glyph.mask().fBounds));
if (!this->drawColorGlyph(recordingCanvas, face, palette, glyph)) {
if (!this->drawColorGlyph(face, glyph, loadGlyphFlags, palette, recordingCanvas)) {
return nullptr;
}
return recorder.finishRecordingAsDrawable();

View File

@ -47,14 +47,14 @@ protected:
: INHERITED(std::move(typeface), effects, desc)
{}
bool drawColorGlyph(SkCanvas*, FT_Face, SkSpan<SkColor> palette, const SkGlyph&);
void generateGlyphImage(FT_Face face,
SkSpan<SkColor> palette,
const SkGlyph& glyph,
const SkMatrix& bitmapTransform);
bool generateGlyphPath(FT_Face face, SkPath* path);
bool generateFacePath(FT_Face face, SkGlyphID glyphID, SkPath* path);
sk_sp<SkDrawable> generateGlyphDrawable(FT_Face face, SkSpan<SkColor> palette, const SkGlyph&);
bool drawColorGlyph(FT_Face, const SkGlyph&, uint32_t loadGlyphFlags,
SkSpan<SkColor> palette, SkCanvas*);
void generateGlyphImage(FT_Face, const SkGlyph&, uint32_t loadGlyphFlags,
SkSpan<SkColor> palette, const SkMatrix& bitmapTransform);
bool generateGlyphPath(FT_Face, SkPath*);
bool generateFacePath(FT_Face, SkGlyphID, uint32_t loadGlyphFlags, SkPath*);
sk_sp<SkDrawable> generateGlyphDrawable(FT_Face, const SkGlyph&, uint32_t loadGlyphFlags,
SkSpan<SkColor> palette);
// Computes a bounding box for a COLRv1 glyph id in FT_BBox 26.6 format and FreeType's y-up
// coordinate space.