Skip to content

Commit 094b3ea

Browse files
Ben WagnerSkia Commit-Bot
authored andcommitted
Simplify FreeType glyph bounds.
Avoid the unnecessary round trip through SkScalar, and set the bounds of glyphs which overflow to empty. Change-Id: I8715fa977085903ec4710df7cd8f4505ac24ad6a Reviewed-on: https://skia-review.googlesource.com/152386 Commit-Queue: Ben Wagner <[email protected]> Reviewed-by: Herb Derby <[email protected]>
1 parent a8cdc17 commit 094b3ea

File tree

1 file changed

+64
-62
lines changed

1 file changed

+64
-62
lines changed

src/ports/SkFontHost_FreeType.cpp

Lines changed: 64 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -1177,75 +1177,79 @@ void SkScalerContext_FreeType::generateMetrics(SkGlyph* glyph) {
11771177
}
11781178
emboldenIfNeeded(fFace, fFace->glyph, glyph->getGlyphID());
11791179

1180-
switch ( fFace->glyph->format ) {
1181-
case FT_GLYPH_FORMAT_OUTLINE:
1182-
if (0 == fFace->glyph->outline.n_contours) {
1183-
glyph->fWidth = 0;
1184-
glyph->fHeight = 0;
1185-
glyph->fTop = 0;
1186-
glyph->fLeft = 0;
1187-
} else {
1188-
FT_BBox bbox;
1189-
1180+
if (fFace->glyph->format == FT_GLYPH_FORMAT_OUTLINE) {
1181+
using FT_PosLimits = std::numeric_limits<FT_Pos>;
1182+
FT_BBox bounds = { FT_PosLimits::max(), FT_PosLimits::max(),
1183+
FT_PosLimits::min(), FT_PosLimits::min() };
11901184
#ifdef FT_COLOR_H
1191-
SkRect bounds = SkRect::MakeEmpty();
1192-
1193-
FT_LayerIterator layerIterator;
1194-
layerIterator.p = NULL;
1195-
FT_Bool haveLayers = false;
1196-
FT_UInt layerGlyphIndex;
1197-
FT_UInt layerColorIndex;
1198-
while (FT_Get_Color_Glyph_Layer(fFace,
1199-
glyph->getGlyphID(),
1200-
&layerGlyphIndex,
1201-
&layerColorIndex,
1202-
&layerIterator)) {
1203-
haveLayers = true;
1204-
err = FT_Load_Glyph(fFace, layerGlyphIndex,
1205-
fLoadGlyphFlags | FT_LOAD_BITMAP_METRICS_ONLY);
1206-
if (err != 0) {
1207-
glyph->zeroMetrics();
1208-
return;
1209-
}
1210-
emboldenIfNeeded(fFace, fFace->glyph, layerGlyphIndex);
1211-
1212-
if (0 < fFace->glyph->outline.n_contours) {
1213-
getBBoxForCurrentGlyph(glyph, &bbox, true);
1185+
FT_Bool haveLayers = false;
1186+
FT_LayerIterator layerIterator = { 0, 0, nullptr };
1187+
FT_UInt layerGlyphIndex;
1188+
FT_UInt layerColorIndex;
1189+
while (FT_Get_Color_Glyph_Layer(fFace, glyph->getGlyphID(),
1190+
&layerGlyphIndex, &layerColorIndex, &layerIterator))
1191+
{
1192+
haveLayers = true;
1193+
err = FT_Load_Glyph(fFace, layerGlyphIndex,
1194+
fLoadGlyphFlags | FT_LOAD_BITMAP_METRICS_ONLY);
1195+
if (err != 0) {
1196+
glyph->zeroMetrics();
1197+
return;
1198+
}
1199+
emboldenIfNeeded(fFace, fFace->glyph, layerGlyphIndex);
12141200

1215-
SkRect layerBounds = SkRect::MakeLTRB(SkFDot6ToScalar(bbox.xMin),
1216-
SkFDot6ToScalar(-bbox.yMax),
1217-
SkFDot6ToScalar(bbox.xMax),
1218-
SkFDot6ToScalar(-bbox.yMin)
1219-
);
1201+
if (0 < fFace->glyph->outline.n_contours) {
1202+
FT_BBox bbox;
1203+
getBBoxForCurrentGlyph(glyph, &bbox, true);
12201204

1221-
bounds.join(layerBounds);
1222-
}
1205+
// Union
1206+
bounds.xMin = std::min(bbox.xMin, bounds.xMin);
1207+
bounds.yMin = std::min(bbox.yMin, bounds.yMin);
1208+
bounds.xMax = std::max(bbox.xMax, bounds.xMax);
1209+
bounds.yMax = std::max(bbox.yMax, bounds.yMax);
12231210
}
1211+
}
12241212

1225-
if (haveLayers) {
1226-
glyph->fMaskFormat = SkMask::kARGB32_Format;
1227-
1228-
SkIRect ibounds = bounds.roundOut();
1229-
glyph->fWidth = SkToU16(ibounds.width());
1230-
glyph->fHeight = SkToU16(ibounds.height());
1231-
glyph->fTop = SkToS16(ibounds.top());
1232-
glyph->fLeft = SkToS16(ibounds.left());
1233-
} else {
1213+
if (haveLayers) {
1214+
glyph->fMaskFormat = SkMask::kARGB32_Format;
1215+
if (!(bounds.xMin < bounds.xMax && bounds.yMin < bounds.yMax)) {
1216+
bounds = { 0, 0, 0, 0 };
1217+
}
1218+
} else {
12341219
#endif
1235-
getBBoxForCurrentGlyph(glyph, &bbox, true);
1236-
1237-
glyph->fWidth = SkToU16(SkFDot6Floor(bbox.xMax - bbox.xMin));
1238-
glyph->fHeight = SkToU16(SkFDot6Floor(bbox.yMax - bbox.yMin));
1239-
glyph->fTop = -SkToS16(SkFDot6Floor(bbox.yMax));
1240-
glyph->fLeft = SkToS16(SkFDot6Floor(bbox.xMin));
1241-
#ifdef FT_COLOR_H
1220+
if (0 < fFace->glyph->outline.n_contours) {
1221+
getBBoxForCurrentGlyph(glyph, &bounds, true);
1222+
} else {
1223+
bounds = { 0, 0, 0, 0 };
12421224
}
1225+
#ifdef FT_COLOR_H
1226+
}
12431227
#endif
1244-
updateGlyphIfLCD(glyph);
1228+
// Round out, no longer dot6.
1229+
bounds.xMin = SkFDot6Floor(bounds.xMin);
1230+
bounds.yMin = SkFDot6Floor(bounds.yMin);
1231+
bounds.xMax = SkFDot6Ceil (bounds.xMax);
1232+
bounds.yMax = SkFDot6Ceil (bounds.yMax);
1233+
1234+
FT_Pos width = bounds.xMax - bounds.xMin;
1235+
FT_Pos height = bounds.yMax - bounds.yMin;
1236+
FT_Pos top = -bounds.yMax; // Freetype y-up, Skia y-down.
1237+
FT_Pos left = bounds.xMin;
1238+
if (!SkTFitsIn<decltype(glyph->fWidth )>(width ) ||
1239+
!SkTFitsIn<decltype(glyph->fHeight)>(height) ||
1240+
!SkTFitsIn<decltype(glyph->fTop )>(top ) ||
1241+
!SkTFitsIn<decltype(glyph->fLeft )>(left ) )
1242+
{
1243+
width = height = top = left = 0;
12451244
}
1246-
break;
12471245

1248-
case FT_GLYPH_FORMAT_BITMAP:
1246+
glyph->fWidth = SkToU16(width );
1247+
glyph->fHeight = SkToU16(height);
1248+
glyph->fTop = SkToS16(top );
1249+
glyph->fLeft = SkToS16(left );
1250+
updateGlyphIfLCD(glyph);
1251+
1252+
} else if (fFace->glyph->format == FT_GLYPH_FORMAT_BITMAP) {
12491253
if (this->isVertical()) {
12501254
FT_Vector vector;
12511255
vector.x = fFace->glyph->metrics.vertBearingX - fFace->glyph->metrics.horiBearingX;
@@ -1275,9 +1279,7 @@ void SkScalerContext_FreeType::generateMetrics(SkGlyph* glyph) {
12751279
glyph->fTop = SkToS16(irect.top());
12761280
glyph->fLeft = SkToS16(irect.left());
12771281
}
1278-
break;
1279-
1280-
default:
1282+
} else {
12811283
SkDEBUGFAIL("unknown glyph format");
12821284
glyph->zeroMetrics();
12831285
return;

0 commit comments

Comments
 (0)