Revert "Revert "Return POD from generateMetrics() rather than mutate SkGlyph""
This reverts commit 3b83ce679ed656c3a347aec594f111170e0077de.
Fix was to copy over extraBits from glyph to glyphmetrics
Change-Id: Iaf771d2461544936b380911f7dca65cbbbb444bb
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/729800
Reviewed-by: Ben Wagner <bungeman@google.com>
Commit-Queue: Ben Wagner <bungeman@google.com>
diff --git a/src/core/SkScalerContext.cpp b/src/core/SkScalerContext.cpp
index b7b26ac..7b784cc 100644
--- a/src/core/SkScalerContext.cpp
+++ b/src/core/SkScalerContext.cpp
@@ -231,26 +231,43 @@
glyph.fWidth = 0;
glyph.fHeight = 0;
};
+
SkGlyph glyph{packedID};
- glyph.fMaskFormat = format;
- // Must call to allow the subclass to determine the glyph representation to use.
- this->generateMetrics(&glyph, alloc);
- SkDEBUGCODE(glyph.fAdvancesBoundsFormatAndInitialPathDone = true;)
- if (fGenerateImageFromPath) {
+ glyph.fMaskFormat = format; // subclass may return a different value
+ const auto mx = this->generateMetrics(glyph, alloc);
+ SkASSERT(!mx.neverRequestPath || !mx.computeFromPath);
+
+ glyph.fAdvanceX = mx.advance.fX;
+ glyph.fAdvanceY = mx.advance.fY;
+ glyph.fMaskFormat = mx.maskFormat;
+ glyph.fScalerContextBits = mx.extraBits;
+
+ if (mx.computeFromPath || (fGenerateImageFromPath && !mx.neverRequestPath)) {
+ SkDEBUGCODE(glyph.fAdvancesBoundsFormatAndInitialPathDone = true;)
this->internalGetPath(glyph, alloc);
const SkPath* devPath = glyph.path();
if (devPath) {
- // generateMetrics may have modified the glyph fMaskFormat.
- glyph.fMaskFormat = format;
const bool doVert = SkToBool(fRec.fFlags & SkScalerContext::kLCD_Vertical_Flag);
const bool a8LCD = SkToBool(fRec.fFlags & SkScalerContext::kGenA8FromLCD_Flag);
const bool hairline = glyph.pathIsHairline();
if (!GenerateMetricsFromPath(&glyph, *devPath, format, doVert, a8LCD, hairline)) {
zeroBounds(glyph);
- return glyph;
}
}
+ } else {
+ if (!SkRectPriv::Is16Bit(mx.bounds)) {
+ zeroBounds(glyph);
+ } else {
+ glyph.fLeft = SkTo<int16_t>( mx.bounds.fLeft);
+ glyph.fTop = SkTo<int16_t>( mx.bounds.fTop);
+ glyph.fWidth = SkTo<uint16_t>(mx.bounds.width());
+ glyph.fHeight = SkTo<uint16_t>(mx.bounds.height());
+ }
+ if (mx.neverRequestPath) {
+ glyph.setPath(alloc, nullptr, false);
+ }
}
+ SkDEBUGCODE(glyph.fAdvancesBoundsFormatAndInitialPathDone = true;)
// if either dimension is empty, zap the image bounds of the glyph
if (0 == glyph.fWidth || 0 == glyph.fHeight) {
@@ -1254,9 +1271,8 @@
: SkScalerContext(std::move(typeface), effects, desc) {}
protected:
- void generateMetrics(SkGlyph* glyph, SkArenaAlloc*) override {
- glyph->fMaskFormat = fRec.fMaskFormat;
- glyph->zeroMetrics();
+ GlyphMetrics generateMetrics(const SkGlyph& glyph, SkArenaAlloc*) override {
+ return {glyph.maskFormat()};
}
void generateImage(const SkGlyph& glyph) override {}
bool generatePath(const SkGlyph& glyph, SkPath* path) override {
diff --git a/src/core/SkScalerContext.h b/src/core/SkScalerContext.h
index e8a8a71..fbe82f4 100644
--- a/src/core/SkScalerContext.h
+++ b/src/core/SkScalerContext.h
@@ -363,11 +363,26 @@
protected:
SkScalerContextRec fRec;
- /** Generates the contents of glyph.fWidth, fHeight, fTop, fLeft,
- * as well as fAdvanceX and fAdvanceY if not already set.
- * The fMaskFormat will already be set to a requested format but may be changed.
- */
- virtual void generateMetrics(SkGlyph* glyph, SkArenaAlloc*) = 0;
+ struct GlyphMetrics {
+ SkVector advance;
+ SkIRect bounds;
+ SkMask::Format maskFormat;
+ uint16_t extraBits;
+ bool neverRequestPath;
+ bool computeFromPath;
+
+ GlyphMetrics(SkMask::Format format)
+ : advance{0, 0}
+ , bounds{0, 0, 0, 0}
+ , maskFormat(format)
+ , extraBits(0)
+ , neverRequestPath(false)
+ , computeFromPath(false)
+ {}
+ };
+
+ virtual GlyphMetrics generateMetrics(const SkGlyph&, SkArenaAlloc*) = 0;
+
static bool GenerateMetricsFromPath(
SkGlyph* glyph, const SkPath& path, SkMask::Format format,
bool verticalLCD, bool a8FromLCD, bool hairline);
diff --git a/src/core/SkTypeface_remote.cpp b/src/core/SkTypeface_remote.cpp
index 2f227a5..a7930b2 100644
--- a/src/core/SkTypeface_remote.cpp
+++ b/src/core/SkTypeface_remote.cpp
@@ -23,17 +23,18 @@
: SkScalerContext{std::move(tf), effects, desc}
, fDiscardableManager{std::move(manager)} {}
-void SkScalerContextProxy::generateMetrics(SkGlyph* glyph, SkArenaAlloc*) {
+SkScalerContext::GlyphMetrics SkScalerContextProxy::generateMetrics(const SkGlyph& glyph,
+ SkArenaAlloc*) {
TRACE_EVENT1("skia", "generateMetrics", "rec", TRACE_STR_COPY(this->getRec().dump().c_str()));
if (this->getProxyTypeface()->isLogging()) {
SkDebugf("GlyphCacheMiss generateMetrics looking for glyph: %x\n generateMetrics: %s\n",
- glyph->getPackedID().value(), this->getRec().dump().c_str());
+ glyph.getPackedID().value(), this->getRec().dump().c_str());
}
- glyph->fMaskFormat = fRec.fMaskFormat;
- glyph->zeroMetrics();
fDiscardableManager->notifyCacheMiss(
- SkStrikeClient::CacheMissType::kGlyphMetrics, fRec.fTextSize);
+ SkStrikeClient::CacheMissType::kGlyphMetrics, fRec.fTextSize);
+
+ return {glyph.maskFormat()};
}
void SkScalerContextProxy::generateImage(const SkGlyph& glyph) {
diff --git a/src/core/SkTypeface_remote.h b/src/core/SkTypeface_remote.h
index 9a7142b..32cbe66 100644
--- a/src/core/SkTypeface_remote.h
+++ b/src/core/SkTypeface_remote.h
@@ -30,9 +30,9 @@
sk_sp<SkStrikeClient::DiscardableHandleManager> manager);
protected:
- void generateMetrics(SkGlyph* glyph, SkArenaAlloc*) override;
+ GlyphMetrics generateMetrics(const SkGlyph&, SkArenaAlloc*) override;
void generateImage(const SkGlyph& glyph) override;
- bool generatePath(const SkGlyph& glyphID, SkPath* path) override;
+ bool generatePath(const SkGlyph& glyph, SkPath* path) override;
sk_sp<SkDrawable> generateDrawable(const SkGlyph&) override;
void generateFontMetrics(SkFontMetrics* metrics) override;
SkTypefaceProxy* getProxyTypeface() const;
diff --git a/src/ports/SkFontHost_FreeType.cpp b/src/ports/SkFontHost_FreeType.cpp
index 39b4157..967609e 100644
--- a/src/ports/SkFontHost_FreeType.cpp
+++ b/src/ports/SkFontHost_FreeType.cpp
@@ -444,7 +444,7 @@
}
protected:
- void generateMetrics(SkGlyph* glyph, SkArenaAlloc*) override;
+ GlyphMetrics generateMetrics(const SkGlyph&, SkArenaAlloc*) override;
void generateImage(const SkGlyph& glyph) override;
bool generatePath(const SkGlyph& glyph, SkPath* path) override;
sk_sp<SkDrawable> generateDrawable(const SkGlyph&) override;
@@ -472,10 +472,10 @@
FT_Error setupSize();
static bool getBoundsOfCurrentOutlineGlyph(FT_GlyphSlot glyph, SkRect* bounds);
- static void setGlyphBounds(SkGlyph* glyph, SkRect* bounds, bool subpixel);
+ static SkIRect computeGlyphBounds(const SkGlyph&, SkRect* bounds, bool subpixel);
bool getCBoxForLetter(char letter, FT_BBox* bbox);
// Caller must lock f_t_mutex() before calling this function.
- void updateGlyphBoundsIfLCD(SkGlyph* glyph);
+ void updateGlyphBoundsIfLCD(GlyphMetrics* mx);
// Caller must lock f_t_mutex() before calling this function.
// update FreeType2 glyph slot with glyph emboldened
void emboldenIfNeeded(FT_Face face, FT_GlyphSlot glyph, SkGlyphID gid);
@@ -1105,41 +1105,31 @@
return true;
}
-void SkScalerContext_FreeType::setGlyphBounds(SkGlyph* glyph, SkRect* bounds, bool subpixel) {
+SkIRect SkScalerContext_FreeType::computeGlyphBounds(const SkGlyph& glyph, SkRect* bounds,
+ bool subpixel) {
SkIRect irect;
if (bounds->isEmpty()) {
irect = SkIRect::MakeEmpty();
} else {
if (subpixel) {
- bounds->offset(SkFixedToScalar(glyph->getSubXFixed()),
- SkFixedToScalar(glyph->getSubYFixed()));
+ bounds->offset(SkFixedToScalar(glyph.getSubXFixed()),
+ SkFixedToScalar(glyph.getSubYFixed()));
}
-
irect = bounds->roundOut();
- if (!SkTFitsIn<decltype(glyph->fWidth )>(irect.width ()) ||
- !SkTFitsIn<decltype(glyph->fHeight)>(irect.height()) ||
- !SkTFitsIn<decltype(glyph->fTop )>(irect.top ()) ||
- !SkTFitsIn<decltype(glyph->fLeft )>(irect.left ()) )
- {
- irect = SkIRect::MakeEmpty();
- }
}
- glyph->fWidth = SkToU16(irect.width ());
- glyph->fHeight = SkToU16(irect.height());
- glyph->fTop = SkToS16(irect.top ());
- glyph->fLeft = SkToS16(irect.left ());
+ return irect;
}
-void SkScalerContext_FreeType::updateGlyphBoundsIfLCD(SkGlyph* glyph) {
- if (glyph->fMaskFormat == SkMask::kLCD16_Format &&
- glyph->fWidth > 0 && glyph->fHeight > 0)
+void SkScalerContext_FreeType::updateGlyphBoundsIfLCD(GlyphMetrics* mx) {
+ if (mx->maskFormat == SkMask::kLCD16_Format &&
+ mx->bounds.width() > 0 && mx->bounds.height() > 0)
{
if (fLCDIsVert) {
- glyph->fHeight += 2;
- glyph->fTop -= 1;
+ mx->bounds.fBottom += 1;
+ mx->bounds.fTop -= 1;
} else {
- glyph->fWidth += 2;
- glyph->fLeft -= 1;
+ mx->bounds.fRight += 1;
+ mx->bounds.fLeft -= 1;
}
}
}
@@ -1160,12 +1150,14 @@
return mechanism && policy;
}
-void SkScalerContext_FreeType::generateMetrics(SkGlyph* glyph, SkArenaAlloc* alloc) {
+SkScalerContext::GlyphMetrics SkScalerContext_FreeType::generateMetrics(const SkGlyph& glyph,
+ SkArenaAlloc* alloc) {
SkAutoMutexExclusive ac(f_t_mutex());
+ GlyphMetrics mx(glyph.maskFormat());
+
if (this->setupSize()) {
- glyph->zeroMetrics();
- return;
+ return mx;
}
FT_Bool haveLayers = false;
@@ -1175,14 +1167,14 @@
SkRect bounds = SkRect::MakeEmpty();
#ifdef TT_SUPPORT_COLRV1
FT_OpaquePaint opaqueLayerPaint{nullptr, 1};
- if (FT_Get_Color_Glyph_Paint(fFace, glyph->getGlyphID(),
+ if (FT_Get_Color_Glyph_Paint(fFace, glyph.getGlyphID(),
FT_COLOR_INCLUDE_ROOT_TRANSFORM, &opaqueLayerPaint)) {
haveLayers = true;
- glyph->fScalerContextBits = ScalerContextBits::COLRv1;
+ mx.extraBits = ScalerContextBits::COLRv1;
// COLRv1 optionally provides a ClipBox.
FT_ClipBox clipBox;
- if (FT_Get_Color_Glyph_ClipBox(fFace, glyph->getGlyphID(), &clipBox)) {
+ if (FT_Get_Color_Glyph_ClipBox(fFace, glyph.getGlyphID(), &clipBox)) {
// Find bounding box of clip box corner points, needed when clipbox is transformed.
FT_BBox bbox;
bbox.xMin = clipBox.bottom_left.x;
@@ -1201,11 +1193,10 @@
// Traverse the glyph graph with a focus on measuring the required bounding box.
// The call to computeColrV1GlyphBoundingBox may modify the face.
// Reset the face to load the base glyph for metrics.
- if (!computeColrV1GlyphBoundingBox(fFace, glyph->getGlyphID(), &bounds) ||
+ if (!computeColrV1GlyphBoundingBox(fFace, glyph.getGlyphID(), &bounds) ||
this->setupSize())
{
- glyph->zeroMetrics();
- return;
+ return mx;
}
}
}
@@ -1221,12 +1212,11 @@
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.
- while (FT_Get_Color_Glyph_Layer(fFace, glyph->getGlyphID(), &layerGlyphIndex,
+ while (FT_Get_Color_Glyph_Layer(fFace, glyph.getGlyphID(), &layerGlyphIndex,
&layerColorIndex, &layerIterator)) {
haveLayers = true;
if (FT_Load_Glyph(fFace, layerGlyphIndex, flags)) {
- glyph->zeroMetrics();
- return;
+ return mx;
}
SkRect currentBounds;
@@ -1235,37 +1225,36 @@
}
}
if (haveLayers) {
- glyph->fScalerContextBits = ScalerContextBits::COLRv0;
+ mx.extraBits = ScalerContextBits::COLRv0;
}
}
if (haveLayers) {
- glyph->fMaskFormat = SkMask::kARGB32_Format;
- glyph->setPath(alloc, nullptr, false);
- setGlyphBounds(glyph, &bounds, this->isSubpixel());
+ mx.maskFormat = SkMask::kARGB32_Format;
+ mx.neverRequestPath = true;
+ mx.bounds = computeGlyphBounds(glyph, &bounds, this->isSubpixel());
}
}
#endif //FT_COLOR_H
// Even if haveLayers, the base glyph must be loaded to get the metrics.
- if (FT_Load_Glyph(fFace, glyph->getGlyphID(), fLoadGlyphFlags | FT_LOAD_BITMAP_METRICS_ONLY)) {
- glyph->zeroMetrics();
- return;
+ if (FT_Load_Glyph(fFace, glyph.getGlyphID(), fLoadGlyphFlags | FT_LOAD_BITMAP_METRICS_ONLY)) {
+ return mx;
}
if (!haveLayers) {
- emboldenIfNeeded(fFace, fFace->glyph, glyph->getGlyphID());
+ emboldenIfNeeded(fFace, fFace->glyph, glyph.getGlyphID());
if (fFace->glyph->format == FT_GLYPH_FORMAT_OUTLINE) {
SkRect bounds;
if (!getBoundsOfCurrentOutlineGlyph(fFace->glyph, &bounds)) {
bounds = SkRect::MakeEmpty();
}
- setGlyphBounds(glyph, &bounds, this->isSubpixel());
- updateGlyphBoundsIfLCD(glyph);
+ mx.bounds = computeGlyphBounds(glyph, &bounds, this->isSubpixel());
+ updateGlyphBoundsIfLCD(&mx);
} else if (fFace->glyph->format == FT_GLYPH_FORMAT_BITMAP) {
- glyph->setPath(alloc, nullptr, false);
+ mx.neverRequestPath = true;
if (this->isVertical()) {
FT_Vector vector;
@@ -1277,7 +1266,7 @@
}
if (fFace->glyph->bitmap.pixel_mode == FT_PIXEL_MODE_BGRA) {
- glyph->fMaskFormat = SkMask::kARGB32_Format;
+ mx.maskFormat = SkMask::kARGB32_Format;
}
SkRect bounds = SkRect::MakeXYWH(SkIntToScalar(fFace->glyph->bitmap_left ),
@@ -1285,13 +1274,14 @@
SkIntToScalar(fFace->glyph->bitmap.width),
SkIntToScalar(fFace->glyph->bitmap.rows ));
fMatrix22Scalar.mapRect(&bounds);
- setGlyphBounds(glyph, &bounds, this->shouldSubpixelBitmap(*glyph, fMatrix22Scalar));
+ mx.bounds = computeGlyphBounds(glyph, &bounds,
+ this->shouldSubpixelBitmap(glyph, fMatrix22Scalar));
#if defined(FT_CONFIG_OPTION_SVG)
} else if (fFace->glyph->format == FT_GLYPH_FORMAT_SVG) {
- glyph->fScalerContextBits = ScalerContextBits::SVG;
- glyph->fMaskFormat = SkMask::kARGB32_Format;
- glyph->setPath(alloc, nullptr, false);
+ mx.extraBits = ScalerContextBits::SVG;
+ mx.maskFormat = SkMask::kARGB32_Format;
+ mx.neverRequestPath = true;
SkPictureRecorder recorder;
SkRect infiniteRect = SkRect::MakeLTRB(-SK_ScalarInfinity, -SK_ScalarInfinity,
@@ -1299,48 +1289,47 @@
sk_sp<SkBBoxHierarchy> bboxh = SkRTreeFactory()();
SkSpan<SkColor> palette(fFaceRec->fSkPalette.get(), fFaceRec->fFTPaletteEntryCount);
SkCanvas* recordingCanvas = recorder.beginRecording(infiniteRect, bboxh);
- if (!this->drawSVGGlyph(fFace, *glyph, fLoadGlyphFlags, palette, recordingCanvas)) {
- glyph->zeroMetrics();
- return;
+ if (!this->drawSVGGlyph(fFace, glyph, fLoadGlyphFlags, palette, recordingCanvas)) {
+ return mx;
}
sk_sp<SkPicture> pic = recorder.finishRecordingAsPicture();
SkRect bounds = pic->cullRect();
SkASSERT(bounds.isFinite());
// drawSVGGlyph already applied the subpixel positioning.
- setGlyphBounds(glyph, &bounds, false);
+ mx.bounds = computeGlyphBounds(glyph, &bounds, false);
#endif // FT_CONFIG_OPTION_SVG
} else {
SkDEBUGFAIL("unknown glyph format");
- glyph->zeroMetrics();
- return;
+ return mx;
}
}
if (this->isVertical()) {
if (fDoLinearMetrics) {
const SkScalar advanceScalar = SkFT_FixedToScalar(fFace->glyph->linearVertAdvance);
- glyph->fAdvanceX = SkScalarToFloat(fMatrix22Scalar.getSkewX() * advanceScalar);
- glyph->fAdvanceY = SkScalarToFloat(fMatrix22Scalar.getScaleY() * advanceScalar);
+ mx.advance.fX = SkScalarToFloat(fMatrix22Scalar.getSkewX() * advanceScalar);
+ mx.advance.fY = SkScalarToFloat(fMatrix22Scalar.getScaleY() * advanceScalar);
} else {
- glyph->fAdvanceX = -SkFDot6ToFloat(fFace->glyph->advance.x);
- glyph->fAdvanceY = SkFDot6ToFloat(fFace->glyph->advance.y);
+ mx.advance.fX = -SkFDot6ToFloat(fFace->glyph->advance.x);
+ mx.advance.fY = SkFDot6ToFloat(fFace->glyph->advance.y);
}
} else {
if (fDoLinearMetrics) {
const SkScalar advanceScalar = SkFT_FixedToScalar(fFace->glyph->linearHoriAdvance);
- glyph->fAdvanceX = SkScalarToFloat(fMatrix22Scalar.getScaleX() * advanceScalar);
- glyph->fAdvanceY = SkScalarToFloat(fMatrix22Scalar.getSkewY() * advanceScalar);
+ mx.advance.fX = SkScalarToFloat(fMatrix22Scalar.getScaleX() * advanceScalar);
+ mx.advance.fY = SkScalarToFloat(fMatrix22Scalar.getSkewY() * advanceScalar);
} else {
- glyph->fAdvanceX = SkFDot6ToFloat(fFace->glyph->advance.x);
- glyph->fAdvanceY = -SkFDot6ToFloat(fFace->glyph->advance.y);
+ mx.advance.fX = SkFDot6ToFloat(fFace->glyph->advance.x);
+ mx.advance.fY = -SkFDot6ToFloat(fFace->glyph->advance.y);
}
}
#ifdef ENABLE_GLYPH_SPEW
LOG_INFO("Metrics(glyph:%d flags:0x%x) w:%d\n", glyph->getGlyphID(), fLoadGlyphFlags, glyph->fWidth);
#endif
+ return mx;
}
void SkScalerContext_FreeType::generateImage(const SkGlyph& glyph) {
diff --git a/src/ports/SkFontHost_win.cpp b/src/ports/SkFontHost_win.cpp
index 5b17b6a..cf32f03 100644
--- a/src/ports/SkFontHost_win.cpp
+++ b/src/ports/SkFontHost_win.cpp
@@ -572,7 +572,7 @@
bool isValid() const;
protected:
- void generateMetrics(SkGlyph* glyph, SkArenaAlloc*) override;
+ GlyphMetrics generateMetrics(const SkGlyph&, SkArenaAlloc*) override;
void generateImage(const SkGlyph& glyph) override;
bool generatePath(const SkGlyph& glyph, SkPath* path) override;
void generateFontMetrics(SkFontMetrics*) override;
@@ -805,56 +805,53 @@
return fDDC && fFont;
}
-void SkScalerContext_GDI::generateMetrics(SkGlyph* glyph, SkArenaAlloc* alloc) {
+SkScalerContext::GlyphMetrics SkScalerContext_GDI::generateMetrics(const SkGlyph& glyph,
+ SkArenaAlloc*) {
SkASSERT(fDDC);
- glyph->fMaskFormat = fRec.fMaskFormat;
+ GlyphMetrics mx(glyph.maskFormat());
if (fType == SkScalerContext_GDI::kBitmap_Type || fType == SkScalerContext_GDI::kLine_Type) {
SIZE size;
- WORD glyphs = glyph->getGlyphID();
+ WORD glyphs = glyph.getGlyphID();
+ int width, height;
if (0 == GetTextExtentPointI(fDDC, &glyphs, 1, &size)) {
- glyph->fWidth = SkToS16(fTM.tmMaxCharWidth);
- glyph->fHeight = SkToS16(fTM.tmHeight);
+ width = fTM.tmMaxCharWidth;
+ height = fTM.tmHeight;
} else {
- glyph->fWidth = SkToS16(size.cx);
- glyph->fHeight = SkToS16(size.cy);
+ width = size.cx;
+ height = size.cy;
}
- glyph->fTop = SkToS16(-fTM.tmAscent);
// Bitmap FON cannot underhang, but vector FON may.
// There appears no means of determining underhang of vector FON.
- glyph->fLeft = SkToS16(0);
- glyph->fAdvanceX = glyph->width();
- glyph->fAdvanceY = 0;
+ int left = 0;
+ int top = -fTM.tmAscent;
+
+ mx.bounds = SkIRect::MakeXYWH(left, top, width, height);
+ mx.advance = SkVector{(float)width, 0};
// Vector FON will transform nicely, but bitmap FON do not.
if (fType == SkScalerContext_GDI::kLine_Type) {
- SkRect bounds = SkRect::MakeXYWH(glyph->fLeft, glyph->fTop,
- glyph->width(), glyph->height());
+ SkRect bounds = SkRect::MakeXYWH(left, top, width, height);
SkMatrix m;
m.setAll(SkFIXEDToScalar(fMat22.eM11), -SkFIXEDToScalar(fMat22.eM21), 0,
-SkFIXEDToScalar(fMat22.eM12), SkFIXEDToScalar(fMat22.eM22), 0,
0, 0, 1);
m.mapRect(&bounds);
- bounds.roundOut(&bounds);
- glyph->fLeft = SkScalarTruncToInt(bounds.fLeft);
- glyph->fTop = SkScalarTruncToInt(bounds.fTop);
- glyph->fWidth = SkScalarTruncToInt(bounds.width());
- glyph->fHeight = SkScalarTruncToInt(bounds.height());
+ bounds.roundOut(&mx.bounds);
}
// Apply matrix to advance.
- glyph->fAdvanceY = -SkFIXEDToFloat(fMat22.eM12) * glyph->fAdvanceX;
- glyph->fAdvanceX *= SkFIXEDToFloat(fMat22.eM11);
+ mx.advance.fY = -SkFIXEDToFloat(fMat22.eM12) * mx.advance.fX;
+ mx.advance.fX *= SkFIXEDToFloat(fMat22.eM11);
// These do not have an outline path at all.
- glyph->setPath(alloc, nullptr, false);
-
- return;
+ mx.neverRequestPath = true;
+ return mx;
}
- UINT glyphId = glyph->getGlyphID();
+ UINT glyphId = glyph.getGlyphID();
GLYPHMETRICS gm;
sk_bzero(&gm, sizeof(gm));
@@ -864,8 +861,7 @@
LogFontTypeface::EnsureAccessible(this->getTypeface());
status = GetGlyphOutlineW(fDDC, glyphId, GGO_METRICS | GGO_GLYPH_INDEX, &gm, 0, nullptr, &fMat22);
if (GDI_ERROR == status) {
- glyph->zeroMetrics();
- return;
+ return mx;
}
}
@@ -879,43 +875,34 @@
empty = (0 == bufferSize);
}
- glyph->fTop = SkToS16(-gm.gmptGlyphOrigin.y);
- glyph->fLeft = SkToS16(gm.gmptGlyphOrigin.x);
- if (empty) {
- glyph->fWidth = 0;
- glyph->fHeight = 0;
- } else {
+
+ if (!empty) {
+ int y = -gm.gmptGlyphOrigin.y;
+ int x = gm.gmptGlyphOrigin.x;
// Outset, since the image may bleed out of the black box.
// For embedded bitmaps the black box should be exact.
// For outlines we need to outset by 1 in all directions for bleed.
// For ClearType we need to outset by 2 for bleed.
- glyph->fWidth = gm.gmBlackBoxX + 4;
- glyph->fHeight = gm.gmBlackBoxY + 4;
- glyph->fTop -= 2;
- glyph->fLeft -= 2;
+ mx.bounds = SkIRect::MakeXYWH(x, y, gm.gmBlackBoxX, gm.gmBlackBoxY).makeOutset(2, 2);
}
// TODO(benjaminwagner): What is the type of gm.gmCellInc[XY]?
- glyph->fAdvanceX = (float)((int)gm.gmCellIncX);
- glyph->fAdvanceY = (float)((int)gm.gmCellIncY);
+ mx.advance.fX = (float)((int)gm.gmCellIncX);
+ mx.advance.fY = (float)((int)gm.gmCellIncY);
if ((fTM.tmPitchAndFamily & TMPF_VECTOR) && this->isLinearMetrics()) {
sk_bzero(&gm, sizeof(gm));
status = GetGlyphOutlineW(fDDC, glyphId, GGO_METRICS | GGO_GLYPH_INDEX, &gm, 0, nullptr, &fHighResMat22);
if (GDI_ERROR != status) {
- SkPoint advance;
- fHiResMatrix.mapXY(SkIntToScalar(gm.gmCellIncX), SkIntToScalar(gm.gmCellIncY), &advance);
- glyph->fAdvanceX = SkScalarToFloat(advance.fX);
- glyph->fAdvanceY = SkScalarToFloat(advance.fY);
+ mx.advance = fHiResMatrix.mapXY(SkIntToScalar(gm.gmCellIncX),
+ SkIntToScalar(gm.gmCellIncY));
}
} else if (!isAxisAligned(this->fRec)) {
status = GetGlyphOutlineW(fDDC, glyphId, GGO_METRICS | GGO_GLYPH_INDEX, &gm, 0, nullptr, &fGsA);
if (GDI_ERROR != status) {
- SkPoint advance;
- fG_inv.mapXY(SkIntToScalar(gm.gmCellIncX), SkIntToScalar(gm.gmCellIncY), &advance);
- glyph->fAdvanceX = SkScalarToFloat(advance.fX);
- glyph->fAdvanceY = SkScalarToFloat(advance.fY);
+ mx.advance = fG_inv.mapXY(SkIntToScalar(gm.gmCellIncX), SkIntToScalar(gm.gmCellIncY));
}
}
+ return mx;
}
static const MAT2 gMat2Identity = {{0, 1}, {0, 0}, {0, 0}, {0, 1}};
diff --git a/src/ports/SkScalerContext_mac_ct.cpp b/src/ports/SkScalerContext_mac_ct.cpp
index a788660..5743814 100644
--- a/src/ports/SkScalerContext_mac_ct.cpp
+++ b/src/ports/SkScalerContext_mac_ct.cpp
@@ -293,23 +293,21 @@
return image;
}
-void SkScalerContext_Mac::generateMetrics(SkGlyph* glyph, SkArenaAlloc* alloc) {
- glyph->fMaskFormat = fRec.fMaskFormat;
+SkScalerContext::GlyphMetrics SkScalerContext_Mac::generateMetrics(const SkGlyph& glyph,
+ SkArenaAlloc*) {
+ GlyphMetrics mx(glyph.maskFormat());
- if (((SkTypeface_Mac*)this->getTypeface())->fHasColorGlyphs) {
- glyph->setPath(alloc, nullptr, false);
- }
+ mx.neverRequestPath = ((SkTypeface_Mac*)this->getTypeface())->fHasColorGlyphs;
- const CGGlyph cgGlyph = (CGGlyph) glyph->getGlyphID();
- glyph->zeroMetrics();
+ const CGGlyph cgGlyph = (CGGlyph)glyph.getGlyphID();
// The following block produces cgAdvance in CG units (pixels, y up).
CGSize cgAdvance;
CTFontGetAdvancesForGlyphs(fCTFont.get(), kCTFontOrientationHorizontal,
&cgGlyph, &cgAdvance, 1);
cgAdvance = CGSizeApplyAffineTransform(cgAdvance, fTransform);
- glyph->fAdvanceX = SkFloatFromCGFloat(cgAdvance.width);
- glyph->fAdvanceY = -SkFloatFromCGFloat(cgAdvance.height);
+ mx.advance.fX = SkFloatFromCGFloat(cgAdvance.width);
+ mx.advance.fY = -SkFloatFromCGFloat(cgAdvance.height);
// The following produces skBounds in SkGlyph units (pixels, y down),
// or returns early if skBounds would be empty.
@@ -335,12 +333,12 @@
if (0 == cgAdvance.width && 0 == cgAdvance.height) {
SkUniqueCFRef<CGPathRef> path(CTFontCreatePathForGlyph(fCTFont.get(), cgGlyph,nullptr));
if (!path || CGPathIsEmpty(path.get())) {
- return;
+ return mx;
}
}
if (SkCGRectIsEmpty(cgBounds)) {
- return;
+ return mx;
}
// Convert cgBounds to SkGlyph units (pixels, y down).
@@ -351,27 +349,17 @@
// Currently the bounds are based on being rendered at (0,0).
// The top left must not move, since that is the base from which subpixel positioning is offset.
if (fDoSubPosition) {
- skBounds.fRight += SkFixedToFloat(glyph->getSubXFixed());
- skBounds.fBottom += SkFixedToFloat(glyph->getSubYFixed());
+ skBounds.fRight += SkFixedToFloat(glyph.getSubXFixed());
+ skBounds.fBottom += SkFixedToFloat(glyph.getSubYFixed());
}
- // We're trying to pack left and top into int16_t,
- // and width and height into uint16_t, after outsetting by 1.
- if (!SkRect::MakeXYWH(-32767, -32767, 65535, 65535).contains(skBounds)) {
- return;
- }
-
- SkIRect skIBounds;
- skBounds.roundOut(&skIBounds);
+ skBounds.roundOut(&mx.bounds);
// Expand the bounds by 1 pixel, to give CG room for anti-aliasing.
// Note that this outset is to allow room for LCD smoothed glyphs. However, the correct outset
// is not currently known, as CG dilates the outlines by some percentage.
// Note that if this context is A8 and not back-forming from LCD, there is no need to outset.
- skIBounds.outset(1, 1);
- glyph->fLeft = SkToS16(skIBounds.fLeft);
- glyph->fTop = SkToS16(skIBounds.fTop);
- glyph->fWidth = SkToU16(skIBounds.width());
- glyph->fHeight = SkToU16(skIBounds.height());
+ mx.bounds.outset(1, 1);
+ return mx;
}
static constexpr uint8_t sk_pow2_table(size_t i) {
diff --git a/src/ports/SkScalerContext_mac_ct.h b/src/ports/SkScalerContext_mac_ct.h
index 5e96a0b..1bd50f8 100644
--- a/src/ports/SkScalerContext_mac_ct.h
+++ b/src/ports/SkScalerContext_mac_ct.h
@@ -44,7 +44,7 @@
SkScalerContext_Mac(sk_sp<SkTypeface_Mac>, const SkScalerContextEffects&, const SkDescriptor*);
protected:
- void generateMetrics(SkGlyph* glyph, SkArenaAlloc*) override;
+ GlyphMetrics generateMetrics(const SkGlyph&, SkArenaAlloc*) override;
void generateImage(const SkGlyph& glyph) override;
bool generatePath(const SkGlyph& glyph, SkPath* path) override;
void generateFontMetrics(SkFontMetrics*) override;
diff --git a/src/ports/SkScalerContext_win_dw.cpp b/src/ports/SkScalerContext_win_dw.cpp
index f3aee45..4af558a 100644
--- a/src/ports/SkScalerContext_win_dw.cpp
+++ b/src/ports/SkScalerContext_win_dw.cpp
@@ -1391,13 +1391,13 @@
}
}
-bool SkScalerContext_DW::generateColorV1Metrics(SkGlyph* glyph) {
+bool SkScalerContext_DW::generateColorV1Metrics(const SkGlyph& glyph, SkIRect* ibounds) {
DWriteFontTypeface* typeface = this->getDWriteTypeface();
IDWriteFontFace7* fontFace = typeface->fDWriteFontFace7/*.get()*/;
if (!fontFace) {
return false;
}
- UINT32 glyphIndex = glyph->getGlyphID();
+ UINT32 glyphIndex = glyph.getGlyphID();
SkTScopedComPtr<IDWritePaintReader> paintReader;
HRESULT hr;
@@ -1428,8 +1428,8 @@
SkScalar scale = fTextSizeRender;
matrix.preScale(scale, scale);
if (this->isSubpixel()) {
- matrix.postTranslate(SkFixedToScalar(glyph->getSubXFixed()),
- SkFixedToScalar(glyph->getSubYFixed()));
+ matrix.postTranslate(SkFixedToScalar(glyph.getSubXFixed()),
+ SkFixedToScalar(glyph.getSubYFixed()));
}
SkRect r;
@@ -1443,22 +1443,21 @@
r = sk_rect_from(clipBox);
matrix.mapRect(&r);
}
- SetGlyphBounds(glyph, r);
+ r.roundOut(ibounds);
return true;
}
#else // DWRITE_CORE || (defined(NTDDI_WIN11_ZN) && NTDDI_VERSION >= NTDDI_WIN11_ZN)
-bool SkScalerContext_DW::generateColorV1Metrics(SkGlyph*) { return false; }
+bool SkScalerContext_DW::generateColorV1Metrics(const SkGlyph&, SkIRect*) { return false; }
bool SkScalerContext_DW::generateColorV1Image(const SkGlyph&) { return false; }
bool SkScalerContext_DW::drawColorV1Image(const SkGlyph&, SkCanvas&) { return false; }
#endif // DWRITE_CORE || (defined(NTDDI_WIN11_ZN) && NTDDI_VERSION >= NTDDI_WIN11_ZN)
-bool SkScalerContext_DW::setAdvance(SkGlyph* glyph) {
- glyph->fAdvanceX = 0;
- glyph->fAdvanceY = 0;
- uint16_t glyphId = glyph->getGlyphID();
+bool SkScalerContext_DW::setAdvance(const SkGlyph& glyph, SkVector* advance) {
+ *advance = {0, 0};
+ uint16_t glyphId = glyph.getGlyphID();
DWriteFontTypeface* typeface = this->getDWriteTypeface();
// DirectWrite treats all out of bounds glyph ids as having the same data as glyph 0.
@@ -1496,34 +1495,32 @@
}
SkScalar advanceX = fTextSizeMeasure * gm.advanceWidth / dwfm.designUnitsPerEm;
- SkVector advance = { advanceX, 0 };
+ *advance = { advanceX, 0 };
if (DWRITE_MEASURING_MODE_GDI_CLASSIC == fMeasuringMode ||
DWRITE_MEASURING_MODE_GDI_NATURAL == fMeasuringMode)
{
// DirectWrite produced 'compatible' metrics, but while close,
// the end result is not always an integer as it would be with GDI.
- advance.fX = SkScalarRoundToScalar(advance.fX);
+ advance->fX = SkScalarRoundToScalar(advance->fX);
}
- fSkXform.mapVectors(&advance, 1);
-
- glyph->fAdvanceX = SkScalarToFloat(advance.fX);
- glyph->fAdvanceY = SkScalarToFloat(advance.fY);
+ fSkXform.mapVectors(advance, 1);
return true;
}
-bool SkScalerContext_DW::generateDWMetrics(SkGlyph* glyph,
+bool SkScalerContext_DW::generateDWMetrics(const SkGlyph& glyph,
DWRITE_RENDERING_MODE renderingMode,
- DWRITE_TEXTURE_TYPE textureType)
+ DWRITE_TEXTURE_TYPE textureType,
+ SkIRect* ibounds)
{
DWriteFontTypeface* typeface = this->getDWriteTypeface();
//Measure raster size.
- fXform.dx = SkFixedToFloat(glyph->getSubXFixed());
- fXform.dy = SkFixedToFloat(glyph->getSubYFixed());
+ fXform.dx = SkFixedToFloat(glyph.getSubXFixed());
+ fXform.dy = SkFixedToFloat(glyph.getSubYFixed());
FLOAT advance = 0;
- UINT16 glyphId = glyph->getGlyphID();
+ UINT16 glyphId = glyph.getGlyphID();
DWRITE_GLYPH_OFFSET offset;
offset.advanceOffset = 0.0f;
@@ -1585,17 +1582,7 @@
return false;
}
- // We're trying to pack left and top into int16_t,
- // and width and height into uint16_t, after outsetting by 1.
- if (!SkIRect::MakeXYWH(-32767, -32767, 65535, 65535).contains(
- SkIRect::MakeLTRB(bbox.left, bbox.top, bbox.right, bbox.bottom))) {
- return false;
- }
-
- glyph->fWidth = SkToU16(bbox.right - bbox.left);
- glyph->fHeight = SkToU16(bbox.bottom - bbox.top);
- glyph->fLeft = SkToS16(bbox.left);
- glyph->fTop = SkToS16(bbox.top);
+ *ibounds = SkIRect::MakeLTRB(bbox.left, bbox.top, bbox.right, bbox.bottom);
return true;
}
@@ -1628,26 +1615,9 @@
return true;
}
-void SkScalerContext_DW::SetGlyphBounds(SkGlyph* glyph, const SkRect& bounds) {
- SkIRect ibounds = bounds.roundOut();
-
- if (!SkTFitsIn<decltype(glyph->fWidth )>(ibounds.width ()) ||
- !SkTFitsIn<decltype(glyph->fHeight)>(ibounds.height()) ||
- !SkTFitsIn<decltype(glyph->fTop )>(ibounds.top ()) ||
- !SkTFitsIn<decltype(glyph->fLeft )>(ibounds.left ()) )
- {
- ibounds = SkIRect::MakeEmpty();
- }
-
- glyph->fWidth = SkToU16(ibounds.width ());
- glyph->fHeight = SkToU16(ibounds.height());
- glyph->fTop = SkToS16(ibounds.top ());
- glyph->fLeft = SkToS16(ibounds.left ());
-}
-
-bool SkScalerContext_DW::generateColorMetrics(SkGlyph* glyph) {
+bool SkScalerContext_DW::generateColorMetrics(const SkGlyph& glyph, SkIRect* ibounds) {
SkTScopedComPtr<IDWriteColorGlyphRunEnumerator> colorLayers;
- if (!getColorGlyphRun(*glyph, &colorLayers)) {
+ if (!getColorGlyphRun(glyph, &colorLayers)) {
return false;
}
SkASSERT(colorLayers.get());
@@ -1679,28 +1649,27 @@
}
SkMatrix matrix = fSkXform;
if (this->isSubpixel()) {
- matrix.postTranslate(SkFixedToScalar(glyph->getSubXFixed()),
- SkFixedToScalar(glyph->getSubYFixed()));
+ matrix.postTranslate(SkFixedToScalar(glyph.getSubXFixed()),
+ SkFixedToScalar(glyph.getSubYFixed()));
}
matrix.mapRect(&bounds);
- SetGlyphBounds(glyph, bounds);
+ bounds.roundOut(ibounds);
return true;
}
-bool SkScalerContext_DW::generateSVGMetrics(SkGlyph* glyph) {
+bool SkScalerContext_DW::generateSVGMetrics(const SkGlyph& glyph, SkIRect* ibounds) {
SkPictureRecorder recorder;
SkRect infiniteRect = SkRect::MakeLTRB(-SK_ScalarInfinity, -SK_ScalarInfinity,
SK_ScalarInfinity, SK_ScalarInfinity);
sk_sp<SkBBoxHierarchy> bboxh = SkRTreeFactory()();
SkCanvas* recordingCanvas = recorder.beginRecording(infiniteRect, bboxh);
- if (!this->drawSVGImage(*glyph, *recordingCanvas)) {
+ if (!this->drawSVGImage(glyph, *recordingCanvas)) {
return false;
}
sk_sp<SkPicture> pic = recorder.finishRecordingAsPicture();
SkRect bounds = pic->cullRect();
SkASSERT(bounds.isFinite());
-
- SetGlyphBounds(glyph, bounds);
+ bounds.roundOut(ibounds);
return true;
}
@@ -1721,14 +1690,14 @@
}
}
-bool SkScalerContext_DW::generatePngMetrics(SkGlyph* glyph) {
+bool SkScalerContext_DW::generatePngMetrics(const SkGlyph& glyph, SkIRect* ibounds) {
IDWriteFontFace4* fontFace4 = this->getDWriteTypeface()->fDWriteFontFace4.get();
if (!fontFace4) {
return false;
}
DWRITE_GLYPH_IMAGE_FORMATS imageFormats;
- HRBM(fontFace4->GetGlyphImageFormats(glyph->getGlyphID(), 0, UINT32_MAX, &imageFormats),
+ HRBM(fontFace4->GetGlyphImageFormats(glyph.getGlyphID(), 0, UINT32_MAX, &imageFormats),
"Cannot get glyph image formats.");
if (!(imageFormats & DWRITE_GLYPH_IMAGE_FORMATS_PNG)) {
return false;
@@ -1736,7 +1705,7 @@
DWRITE_GLYPH_IMAGE_DATA glyphData;
void* glyphDataContext;
- HRBM(fontFace4->GetGlyphImageData(glyph->getGlyphID(),
+ HRBM(fontFace4->GetGlyphImageData(glyph.getGlyphID(),
fTextSizeRender,
DWRITE_GLYPH_IMAGE_FORMATS_PNG,
&glyphData,
@@ -1765,59 +1734,58 @@
matrix.preScale(scale, scale);
matrix.preTranslate(-glyphData.horizontalLeftOrigin.x, -glyphData.horizontalLeftOrigin.y);
if (this->isSubpixel()) {
- matrix.postTranslate(SkFixedToScalar(glyph->getSubXFixed()),
- SkFixedToScalar(glyph->getSubYFixed()));
+ matrix.postTranslate(SkFixedToScalar(glyph.getSubXFixed()),
+ SkFixedToScalar(glyph.getSubYFixed()));
}
matrix.mapRect(&bounds);
- SetGlyphBounds(glyph, bounds);
+ bounds.roundOut(ibounds);
return true;
}
-void SkScalerContext_DW::generateMetrics(SkGlyph* glyph, SkArenaAlloc* alloc) {
- glyph->fWidth = 0;
- glyph->fHeight = 0;
- glyph->fLeft = 0;
- glyph->fTop = 0;
- glyph->fScalerContextBits = ScalerContextBits::NONE;
+SkScalerContext::GlyphMetrics SkScalerContext_DW::generateMetrics(const SkGlyph& glyph,
+ SkArenaAlloc* alloc) {
+ GlyphMetrics mx(glyph.maskFormat());
- if (!this->setAdvance(glyph)) {
- return;
+ mx.extraBits = ScalerContextBits::NONE;
+
+ if (!this->setAdvance(glyph, &mx.advance)) {
+ return mx;
}
DWriteFontTypeface* typeface = this->getDWriteTypeface();
if (typeface->fIsColorFont) {
- if (generateColorV1Metrics(glyph)) {
- glyph->fMaskFormat = SkMask::kARGB32_Format;
- glyph->fScalerContextBits |= ScalerContextBits::COLRv1;
- glyph->setPath(alloc, nullptr, false);
- return;
+ if (generateColorV1Metrics(glyph, &mx.bounds)) {
+ mx.maskFormat = SkMask::kARGB32_Format;
+ mx.extraBits |= ScalerContextBits::COLRv1;
+ mx.neverRequestPath = true;
+ return mx;
}
- if (generateColorMetrics(glyph)) {
- glyph->fMaskFormat = SkMask::kARGB32_Format;
- glyph->fScalerContextBits |= ScalerContextBits::COLR;
- glyph->setPath(alloc, nullptr, false);
- return;
+ if (generateColorMetrics(glyph, &mx.bounds)) {
+ mx.maskFormat = SkMask::kARGB32_Format;
+ mx.extraBits |= ScalerContextBits::COLR;
+ mx.neverRequestPath = true;
+ return mx;
}
- if (generateSVGMetrics(glyph)) {
- glyph->fMaskFormat = SkMask::kARGB32_Format;
- glyph->fScalerContextBits |= ScalerContextBits::SVG;
- glyph->setPath(alloc, nullptr, false);
- return;
+ if (generateSVGMetrics(glyph, &mx.bounds)) {
+ mx.maskFormat = SkMask::kARGB32_Format;
+ mx.extraBits |= ScalerContextBits::SVG;
+ mx.neverRequestPath = true;
+ return mx;
}
- if (generatePngMetrics(glyph)) {
- glyph->fMaskFormat = SkMask::kARGB32_Format;
- glyph->fScalerContextBits |= ScalerContextBits::PNG;
- glyph->setPath(alloc, nullptr, false);
- return;
+ if (generatePngMetrics(glyph, &mx.bounds)) {
+ mx.maskFormat = SkMask::kARGB32_Format;
+ mx.extraBits |= ScalerContextBits::PNG;
+ mx.neverRequestPath = true;
+ return mx;
}
}
- if (this->generateDWMetrics(glyph, fRenderingMode, fTextureType)) {
- glyph->fScalerContextBits = ScalerContextBits::DW;
- return;
+ if (this->generateDWMetrics(glyph, fRenderingMode, fTextureType, &mx.bounds)) {
+ mx.extraBits = ScalerContextBits::DW;
+ return mx;
}
// GetAlphaTextureBounds succeeds but returns an empty RECT if there are no
@@ -1828,30 +1796,21 @@
{
if (this->generateDWMetrics(glyph,
DWRITE_RENDERING_MODE_ALIASED,
- DWRITE_TEXTURE_ALIASED_1x1))
+ DWRITE_TEXTURE_ALIASED_1x1,
+ &mx.bounds))
{
- glyph->fMaskFormat = SkMask::kBW_Format;
- glyph->fScalerContextBits = ScalerContextBits::DW_1;
- return;
+ mx.maskFormat = SkMask::kBW_Format;
+ mx.extraBits = ScalerContextBits::DW_1;
+ return mx;
}
}
// TODO: Try DWRITE_TEXTURE_CLEARTYPE_3x1 if DWRITE_TEXTURE_ALIASED_1x1 fails
// GetAlphaTextureBounds can fail for various reasons.
// As a fallback, attempt to generate the metrics and image from the path.
- SkDEBUGCODE(glyph->fAdvancesBoundsFormatAndInitialPathDone = true;)
- this->getPath(*glyph, alloc);
- const SkPath* devPath = glyph->path();
- if (devPath) {
- // Sometimes all the above fails. If so, try to create the glyph from path.
- const SkMask::Format format = glyph->maskFormat();
- const bool doVert = SkToBool(fRec.fFlags & SkScalerContext::kLCD_Vertical_Flag);
- const bool a8LCD = SkToBool(fRec.fFlags & SkScalerContext::kGenA8FromLCD_Flag);
- const bool hairline = glyph->pathIsHairline();
- if (GenerateMetricsFromPath(glyph, *devPath, format, doVert, a8LCD, hairline)) {
- glyph->fScalerContextBits = ScalerContextBits::PATH;
- }
- }
+ mx.computeFromPath = true;
+ mx.extraBits = ScalerContextBits::PATH;
+ return mx;
}
void SkScalerContext_DW::generateFontMetrics(SkFontMetrics* metrics) {
diff --git a/src/ports/SkScalerContext_win_dw.h b/src/ports/SkScalerContext_win_dw.h
index 01f3e4e..494bb44 100644
--- a/src/ports/SkScalerContext_win_dw.h
+++ b/src/ports/SkScalerContext_win_dw.h
@@ -32,14 +32,14 @@
~SkScalerContext_DW() override;
protected:
- void generateMetrics(SkGlyph* glyph, SkArenaAlloc*) override;
+ GlyphMetrics generateMetrics(const SkGlyph&, SkArenaAlloc*) override;
void generateImage(const SkGlyph& glyph) override;
bool generatePath(const SkGlyph&, SkPath*) override;
sk_sp<SkDrawable> generateDrawable(const SkGlyph&) override;
void generateFontMetrics(SkFontMetrics*) override;
private:
- bool setAdvance(SkGlyph* glyph);
+ bool setAdvance(const SkGlyph&, SkVector*);
struct ScalerContextBits {
using value_type = decltype(SkGlyph::fScalerContextBits);
@@ -74,30 +74,28 @@
}
bool generateColorV1PaintBounds(SkMatrix*, SkRect*, IDWritePaintReader&, DWRITE_PAINT_ELEMENT const &);
- bool generateColorV1Metrics(SkGlyph*);
+ bool generateColorV1Metrics(const SkGlyph&, SkIRect*);
bool generateColorV1Image(const SkGlyph&);
bool drawColorV1Paint(SkCanvas&, IDWritePaintReader&, DWRITE_PAINT_ELEMENT const &);
bool drawColorV1Image(const SkGlyph&, SkCanvas&);
bool getColorGlyphRun(const SkGlyph&, IDWriteColorGlyphRunEnumerator**);
- bool generateColorMetrics(SkGlyph*);
+ bool generateColorMetrics(const SkGlyph&, SkIRect*);
bool generateColorImage(const SkGlyph&);
bool drawColorImage(const SkGlyph&, SkCanvas&);
- bool generateSVGMetrics(SkGlyph*);
+ bool generateSVGMetrics(const SkGlyph&, SkIRect*);
bool generateSVGImage(const SkGlyph&);
bool drawSVGImage(const SkGlyph&, SkCanvas&);
- bool generatePngMetrics(SkGlyph*);
+ bool generatePngMetrics(const SkGlyph&, SkIRect*);
bool generatePngImage(const SkGlyph&);
bool drawPngImage(const SkGlyph&, SkCanvas&);
- bool generateDWMetrics(SkGlyph*, DWRITE_RENDERING_MODE, DWRITE_TEXTURE_TYPE);
+ bool generateDWMetrics(const SkGlyph&, DWRITE_RENDERING_MODE, DWRITE_TEXTURE_TYPE, SkIRect*);
const void* getDWMaskBits(const SkGlyph&, DWRITE_RENDERING_MODE, DWRITE_TEXTURE_TYPE);
bool generateDWImage(const SkGlyph&);
- static void SetGlyphBounds(SkGlyph* glyph, const SkRect& bounds);
-
SkTDArray<uint8_t> fBits;
/** The total matrix without the text height scale. */
SkMatrix fSkXform;
diff --git a/src/ports/SkTypeface_fontations.cpp b/src/ports/SkTypeface_fontations.cpp
index 874de15..98a7d0a 100644
--- a/src/ports/SkTypeface_fontations.cpp
+++ b/src/ports/SkTypeface_fontations.cpp
@@ -159,26 +159,22 @@
}
protected:
- void generateMetrics(SkGlyph* glyph, SkArenaAlloc*) override {
- glyph->fMaskFormat = fRec.fMaskFormat;
- glyph->zeroMetrics();
+ GlyphMetrics generateMetrics(const SkGlyph& glyph, SkArenaAlloc*) override {
+ GlyphMetrics mx(fRec.fMaskFormat);
SkVector scale;
SkMatrix remainingMatrix;
- if (!glyph ||
- !fRec.computeMatrices(
+ if (!fRec.computeMatrices(
SkScalerContextRec::PreMatrixScale::kVertical, &scale, &remainingMatrix)) {
- return false;
+ return mx;
}
float x_advance = 0.0f;
x_advance = fontations_ffi::advance_width_or_zero(
- fBridgeFontRef, scale.y(), fBridgeNormalizedCoords, glyph->getGlyphID());
+ fBridgeFontRef, scale.y(), fBridgeNormalizedCoords, glyph.getGlyphID());
// TODO(drott): y-advance?
- const SkVector advance = remainingMatrix.mapXY(x_advance, SkFloatToScalar(0.f));
- glyph->fAdvanceX = SkScalarToFloat(advance.fX);
- glyph->fAdvanceY = SkScalarToFloat(advance.fY);
-
- // Always generates from paths, so SkScalerContext::makeGlyph will figure the bounds.
+ mx.advance = remainingMatrix.mapXY(x_advance, SkFloatToScalar(0.f));
+ mx.computeFromPath = true;
+ return mx;
}
void generateImage(const SkGlyph&) override { SK_ABORT("Should have generated from path."); }
diff --git a/src/utils/SkCustomTypeface.cpp b/src/utils/SkCustomTypeface.cpp
index 255dd1f..a574c7c 100644
--- a/src/utils/SkCustomTypeface.cpp
+++ b/src/utils/SkCustomTypeface.cpp
@@ -253,33 +253,25 @@
}
protected:
- void generateMetrics(SkGlyph* glyph, SkArenaAlloc* alloc) override {
- glyph->zeroMetrics();
+ GlyphMetrics generateMetrics(const SkGlyph& glyph, SkArenaAlloc*) override {
+ GlyphMetrics mx(glyph.maskFormat());
const SkUserTypeface* tf = this->userTF();
- auto advance = fMatrix.mapXY(tf->fGlyphRecs[glyph->getGlyphID()].fAdvance, 0);
+ mx.advance = fMatrix.mapXY(tf->fGlyphRecs[glyph.getGlyphID()].fAdvance, 0);
- glyph->fAdvanceX = advance.fX;
- glyph->fAdvanceY = advance.fY;
-
- const auto& rec = tf->fGlyphRecs[glyph->getGlyphID()];
+ const auto& rec = tf->fGlyphRecs[glyph.getGlyphID()];
if (rec.isDrawable()) {
- glyph->fMaskFormat = SkMask::kARGB32_Format;
+ mx.maskFormat = SkMask::kARGB32_Format;
SkRect bounds = fMatrix.mapRect(rec.fBounds);
- bounds.offset(SkFixedToScalar(glyph->getSubXFixed()),
- SkFixedToScalar(glyph->getSubYFixed()));
-
- SkIRect ibounds;
- bounds.roundOut(&ibounds);
- glyph->fLeft = ibounds.fLeft;
- glyph->fTop = ibounds.fTop;
- glyph->fWidth = ibounds.width();
- glyph->fHeight = ibounds.height();
+ bounds.offset(SkFixedToScalar(glyph.getSubXFixed()),
+ SkFixedToScalar(glyph.getSubYFixed()));
+ bounds.roundOut(&mx.bounds);
// These do not have an outline path.
- glyph->setPath(alloc, nullptr, false);
+ mx.neverRequestPath = true;
}
+ return mx;
}
void generateImage(const SkGlyph& glyph) override {
diff --git a/tools/fonts/RandomScalerContext.cpp b/tools/fonts/RandomScalerContext.cpp
index f25aa66..69fd6c1 100644
--- a/tools/fonts/RandomScalerContext.cpp
+++ b/tools/fonts/RandomScalerContext.cpp
@@ -26,7 +26,7 @@
bool fFakeIt);
protected:
- void generateMetrics(SkGlyph*, SkArenaAlloc*) override;
+ GlyphMetrics generateMetrics(const SkGlyph&, SkArenaAlloc*) override;
void generateImage(const SkGlyph&) override;
bool generatePath(const SkGlyph&, SkPath*) override;
sk_sp<SkDrawable> generateDrawable(const SkGlyph&) override;
@@ -53,49 +53,58 @@
fProxy->forceGenerateImageFromPath();
}
-void RandomScalerContext::generateMetrics(SkGlyph* glyph, SkArenaAlloc* alloc) {
+SkScalerContext::GlyphMetrics RandomScalerContext::generateMetrics(const SkGlyph& origGlyph,
+ SkArenaAlloc* alloc) {
// Here we will change the mask format of the glyph
// NOTE: this may be overridden by the base class (e.g. if a mask filter is applied).
SkMask::Format format = SkMask::kA8_Format;
- switch (glyph->getGlyphID() % 4) {
+ switch (origGlyph.getGlyphID() % 4) {
case 0: format = SkMask::kLCD16_Format; break;
case 1: format = SkMask::kA8_Format; break;
case 2: format = SkMask::kARGB32_Format; break;
case 3: format = SkMask::kBW_Format; break;
}
- *glyph = fProxy->internalMakeGlyph(glyph->getPackedID(), format, alloc);
+ auto glyph = fProxy->internalMakeGlyph(origGlyph.getPackedID(), format, alloc);
- if (fFakeIt || (glyph->getGlyphID() % 4) != 2) {
- return;
+ GlyphMetrics mx(SkMask::kA8_Format);
+ mx.advance.fX = glyph.fAdvanceX;
+ mx.advance.fY = glyph.fAdvanceY;
+ mx.bounds = SkIRect::MakeXYWH(glyph.left(), glyph.top(), glyph.width(), glyph.height());
+ mx.maskFormat = glyph.maskFormat();
+ mx.extraBits = glyph.fScalerContextBits;
+
+ if (fFakeIt || (glyph.getGlyphID() % 4) != 2) {
+ mx.neverRequestPath = glyph.setPathHasBeenCalled() && !glyph.path();
+ mx.computeFromPath = !mx.neverRequestPath;
+ return mx;
}
- fProxy->getPath(*glyph, alloc);
- if (!glyph->path()) {
- return;
+ fProxy->getPath(glyph, alloc);
+ if (!glyph.path()) {
+ mx.neverRequestPath = true;
+ return mx;
}
// The proxy glyph has a path, but this glyph does not.
// Stash the proxy glyph so it can be used later.
- const SkGlyph* proxyGlyph = fProxyGlyphs.set(glyph->getPackedID(), std::move(*glyph));
+ const auto packedID = glyph.getPackedID();
+ const SkGlyph* proxyGlyph = fProxyGlyphs.set(packedID, std::move(glyph));
const SkPath& proxyPath = *proxyGlyph->path();
- *glyph = SkGlyph(glyph->getPackedID());
- glyph->setPath(alloc, nullptr, false);
- glyph->fMaskFormat = SkMask::kARGB32_Format;
- glyph->fAdvanceX = proxyGlyph->fAdvanceX;
- glyph->fAdvanceY = proxyGlyph->fAdvanceY;
+ mx.neverRequestPath = true;
+ mx.maskFormat = SkMask::kARGB32_Format;
+ mx.advance.fX = proxyGlyph->fAdvanceX;
+ mx.advance.fY = proxyGlyph->fAdvanceY;
+ mx.extraBits = proxyGlyph->fScalerContextBits;
SkRect storage;
const SkPaint& paint = this->getRandomTypeface()->paint();
const SkRect& newBounds =
paint.doComputeFastBounds(proxyPath.getBounds(), &storage, SkPaint::kFill_Style);
- SkIRect ibounds;
- newBounds.roundOut(&ibounds);
- glyph->fLeft = ibounds.fLeft;
- glyph->fTop = ibounds.fTop;
- glyph->fWidth = ibounds.width();
- glyph->fHeight = ibounds.height();
+ newBounds.roundOut(&mx.bounds);
+
+ return mx;
}
void RandomScalerContext::generateImage(const SkGlyph& glyph) {
diff --git a/tools/fonts/TestSVGTypeface.cpp b/tools/fonts/TestSVGTypeface.cpp
index 0f716c2..eae5744 100644
--- a/tools/fonts/TestSVGTypeface.cpp
+++ b/tools/fonts/TestSVGTypeface.cpp
@@ -122,12 +122,9 @@
TestSVGTypeface::Glyph::Glyph() : fOrigin{0, 0}, fAdvance(0) {}
TestSVGTypeface::Glyph::~Glyph() {}
-void TestSVGTypeface::getAdvance(SkGlyph* glyph) const {
- SkGlyphID glyphID = glyph->getGlyphID();
- glyphID = glyphID < fGlyphCount ? glyphID : 0;
-
- glyph->fAdvanceX = fGlyphs[glyphID].fAdvance;
- glyph->fAdvanceY = 0;
+SkVector TestSVGTypeface::getAdvance(SkGlyphID glyphID) const {
+ glyphID = glyphID < fGlyphCount ? glyphID : 0;
+ return {fGlyphs[glyphID].fAdvance, 0};
}
void TestSVGTypeface::getFontMetrics(SkFontMetrics* metrics) const { *metrics = fFontMetrics; }
@@ -189,23 +186,18 @@
return static_cast<TestSVGTypeface*>(this->getTypeface());
}
- void setAdvance(SkGlyph* glyph) {
- this->getTestSVGTypeface()->getAdvance(glyph);
-
- const SkVector advance =
- fMatrix.mapXY(SkFloatToScalar(glyph->fAdvanceX), SkFloatToScalar(glyph->fAdvanceY));
- glyph->fAdvanceX = SkScalarToFloat(advance.fX);
- glyph->fAdvanceY = SkScalarToFloat(advance.fY);
+ SkVector computeAdvance(SkGlyphID glyphID) {
+ auto advance = this->getTestSVGTypeface()->getAdvance(glyphID);
+ return fMatrix.mapXY(advance.fX, advance.fY);
}
- void generateMetrics(SkGlyph* glyph, SkArenaAlloc* alloc) override {
- SkGlyphID glyphID = glyph->getGlyphID();
+ GlyphMetrics generateMetrics(const SkGlyph& glyph, SkArenaAlloc*) override {
+ SkGlyphID glyphID = glyph.getGlyphID();
glyphID = glyphID < this->getTestSVGTypeface()->fGlyphCount ? glyphID : 0;
- glyph->zeroMetrics();
- glyph->fMaskFormat = SkMask::kARGB32_Format;
- glyph->setPath(alloc, nullptr, false);
- this->setAdvance(glyph);
+ GlyphMetrics mx(SkMask::kARGB32_Format);
+ mx.neverRequestPath = true;
+ mx.advance = this->computeAdvance(glyph.getGlyphID());
TestSVGTypeface::Glyph& glyphData = this->getTestSVGTypeface()->fGlyphs[glyphID];
@@ -215,16 +207,11 @@
containerSize.fWidth,
containerSize.fHeight);
fMatrix.mapRect(&newBounds);
- SkScalar dx = SkFixedToScalar(glyph->getSubXFixed());
- SkScalar dy = SkFixedToScalar(glyph->getSubYFixed());
+ SkScalar dx = SkFixedToScalar(glyph.getSubXFixed());
+ SkScalar dy = SkFixedToScalar(glyph.getSubYFixed());
newBounds.offset(dx, dy);
-
- SkIRect ibounds;
- newBounds.roundOut(&ibounds);
- glyph->fLeft = ibounds.fLeft;
- glyph->fTop = ibounds.fTop;
- glyph->fWidth = ibounds.width();
- glyph->fHeight = ibounds.height();
+ newBounds.roundOut(&mx.bounds);
+ return mx;
}
void generateImage(const SkGlyph& glyph) override {
diff --git a/tools/fonts/TestSVGTypeface.h b/tools/fonts/TestSVGTypeface.h
index f4f8ee0..1901945 100644
--- a/tools/fonts/TestSVGTypeface.h
+++ b/tools/fonts/TestSVGTypeface.h
@@ -52,7 +52,7 @@
class TestSVGTypeface : public SkTypeface {
public:
~TestSVGTypeface() override;
- void getAdvance(SkGlyph* glyph) const;
+ SkVector getAdvance(SkGlyphID) const;
void getFontMetrics(SkFontMetrics* metrics) const;
static sk_sp<TestSVGTypeface> Default();
diff --git a/tools/fonts/TestTypeface.cpp b/tools/fonts/TestTypeface.cpp
index f4029a5..008f3ca 100644
--- a/tools/fonts/TestTypeface.cpp
+++ b/tools/fonts/TestTypeface.cpp
@@ -127,13 +127,11 @@
TestTypeface::TestTypeface(sk_sp<SkTestFont> testFont, const SkFontStyle& style)
: SkTypeface(style, false), fTestFont(std::move(testFont)) {}
-void TestTypeface::getAdvance(SkGlyph* glyph) {
- SkGlyphID glyphID = glyph->getGlyphID();
- glyphID = glyphID < fTestFont->fCharCodesCount ? glyphID : 0;
+SkVector TestTypeface::getAdvance(SkGlyphID glyphID) const {
+ glyphID = glyphID < fTestFont->fCharCodesCount ? glyphID : 0;
// TODO(benjaminwagner): Update users to use floats.
- glyph->fAdvanceX = SkFixedToFloat(fTestFont->fWidths[glyphID]);
- glyph->fAdvanceY = 0;
+ return {SkFixedToFloat(fTestFont->fWidths[glyphID]), 0};
}
void TestTypeface::getFontMetrics(SkFontMetrics* metrics) { *metrics = fTestFont->fMetrics; }
@@ -260,15 +258,13 @@
return static_cast<TestTypeface*>(this->getTypeface());
}
- void generateMetrics(SkGlyph* glyph, SkArenaAlloc*) override {
- glyph->zeroMetrics();
+ GlyphMetrics generateMetrics(const SkGlyph& glyph, SkArenaAlloc*) override {
+ GlyphMetrics mx(glyph.maskFormat());
- this->getTestTypeface()->getAdvance(glyph);
+ auto advance = this->getTestTypeface()->getAdvance(glyph.getGlyphID());
- const SkVector advance =
- fMatrix.mapXY(SkFloatToScalar(glyph->fAdvanceX), SkFloatToScalar(glyph->fAdvanceY));
- glyph->fAdvanceX = SkScalarToFloat(advance.fX);
- glyph->fAdvanceY = SkScalarToFloat(advance.fY);
+ mx.advance = fMatrix.mapXY(advance.fX, advance.fY);
+ return mx;
// Always generates from paths, so SkScalerContext::makeGlyph will figure the bounds.
}
diff --git a/tools/fonts/TestTypeface.h b/tools/fonts/TestTypeface.h
index de4077c..a93bed2 100644
--- a/tools/fonts/TestTypeface.h
+++ b/tools/fonts/TestTypeface.h
@@ -78,7 +78,7 @@
};
static const List& Typefaces();
- void getAdvance(SkGlyph* glyph);
+ SkVector getAdvance(SkGlyphID) const;
void getFontMetrics(SkFontMetrics* metrics);
SkPath getPath(SkGlyphID glyph);