diff --git a/include/core/SkFont.h b/include/core/SkFont.h index 8f32363cb9..ba4dc37196 100644 --- a/include/core/SkFont.h +++ b/include/core/SkFont.h @@ -113,6 +113,13 @@ public: */ bool isEmbolden() const { return SkToBool(fFlags & kEmbolden_PrivFlag); } + /** Returns true if baselines will be snapped to pixel positions when the current transformation + matrix is axis aligned. + + @return baselines may be snapped to pixels + */ + bool isBaselineSnap() const { return SkToBool(fFlags & kBaselineSnap_PrivFlag); } + /** Sets whether to always hint glyphs. If forceAutoHinting is set, instructs the font manager to always hint glyphs. @@ -149,6 +156,13 @@ public: */ void setEmbolden(bool embolden); + /** Requests that baselines be snapped to pixels when the current transformation matrix is axis + aligned. + + @param baselineSnap setting for baseline snapping to pixels + */ + void setBaselineSnap(bool baselineSnap); + /** Whether edge pixels draw opaque or with partial transparency. @return one of: Edging::kAlias, Edging::kAntiAlias, Edging::kSubpixelAntiAlias @@ -493,9 +507,15 @@ private: kSubpixel_PrivFlag = 1 << 2, kLinearMetrics_PrivFlag = 1 << 3, kEmbolden_PrivFlag = 1 << 4, + kBaselineSnap_PrivFlag = 1 << 5, }; - static constexpr unsigned kAllFlags = 0x1F; + static constexpr unsigned kAllFlags = kForceAutoHinting_PrivFlag + | kEmbeddedBitmaps_PrivFlag + | kSubpixel_PrivFlag + | kLinearMetrics_PrivFlag + | kEmbolden_PrivFlag + | kBaselineSnap_PrivFlag; sk_sp fTypeface; SkScalar fSize; diff --git a/src/core/SkFont.cpp b/src/core/SkFont.cpp index 9ecfd689e5..fdfbf66a96 100644 --- a/src/core/SkFont.cpp +++ b/src/core/SkFont.cpp @@ -22,7 +22,7 @@ #include "src/utils/SkUTF.h" #define kDefault_Size SkPaintDefaults_TextSize -#define kDefault_Flags 0 +#define kDefault_Flags SkFont::kBaselineSnap_PrivFlag #define kDefault_Edging SkFont::Edging::kAntiAlias #define kDefault_Hinting SkPaintDefaults_Hinting @@ -87,7 +87,9 @@ void SkFont::setLinearMetrics(bool predicate) { void SkFont::setEmbolden(bool predicate) { fFlags = set_clear_mask(fFlags, predicate, kEmbolden_PrivFlag); } - +void SkFont::setBaselineSnap(bool predicate) { + fFlags = set_clear_mask(fFlags, predicate, kBaselineSnap_PrivFlag); +} void SkFont::setEdging(Edging e) { fEdging = SkToU8(e); } @@ -464,6 +466,7 @@ static bool scalar_is_byte(SkScalar x) { } void SkFontPriv::Flatten(const SkFont& font, SkWriteBuffer& buffer) { + SkASSERT(font.fFlags <= SkFont::kAllFlags); SkASSERT((font.fFlags & ~kMask_For_Flags) == 0); SkASSERT((font.fEdging & ~kMask_For_Edging) == 0); SkASSERT((font.fHinting & ~kMask_For_Hinting) == 0); diff --git a/src/core/SkScalerContext.cpp b/src/core/SkScalerContext.cpp index 1dfa0a22f7..fb783c965f 100644 --- a/src/core/SkScalerContext.cpp +++ b/src/core/SkScalerContext.cpp @@ -844,6 +844,9 @@ SkAxisAlignment SkScalerContextRec::computeAxisAlignmentForHText() const { // * fPreSkewX (has no effect, but would on vertical text alignment). // In other words, making the text bigger, stretching it along the // horizontal axis, or fake italicizing it does not move the baseline. + if (!SkToBool(fFlags & SkScalerContext::kBaselineSnap_Flag)) { + return kNone_SkAxisAlignment; + } if (0 == fPost2x2[1][0]) { // The x axis is mapped onto the x axis. @@ -1073,6 +1076,9 @@ void SkScalerContext::MakeRecAndEffects(const SkFont& font, const SkPaint& paint if (font.isLinearMetrics()) { flags |= SkScalerContext::kLinearMetrics_Flag; } + if (font.isBaselineSnap()) { + flags |= SkScalerContext::kBaselineSnap_Flag; + } rec->fFlags = SkToU16(flags); // these modify fFlags, so do them after assigning fFlags diff --git a/src/core/SkScalerContext.h b/src/core/SkScalerContext.h index 9e6c9bed76..c592fb7fda 100644 --- a/src/core/SkScalerContext.h +++ b/src/core/SkScalerContext.h @@ -242,6 +242,7 @@ public: // only meaningful if fMaskFormat is kA8 kGenA8FromLCD_Flag = 0x0800, // could be 0x200 (bit meaning dependent on fMaskFormat) kLinearMetrics_Flag = 0x1000, + kBaselineSnap_Flag = 0x2000, }; // computed values @@ -262,7 +263,7 @@ public: return SkToBool(fRec.fFlags & kSubpixelPositioning_Flag); } - bool isLinearMetrics() const { + bool isLinearMetrics() const { return SkToBool(fRec.fFlags & kLinearMetrics_Flag); } diff --git a/tools/viewer/Viewer.cpp b/tools/viewer/Viewer.cpp index 556c8a491a..f468e05666 100644 --- a/tools/viewer/Viewer.cpp +++ b/tools/viewer/Viewer.cpp @@ -818,6 +818,7 @@ void Viewer::updateTitle() { fontFlag(&SkFontFields::fForceAutoHinting, &SkFont::isForceAutoHinting, "Force Autohint", "No Force Autohint"); fontFlag(&SkFontFields::fEmbolden, &SkFont::isEmbolden, "Fake Bold", "No Fake Bold"); + fontFlag(&SkFontFields::fBaselineSnap, &SkFont::isBaselineSnap, "BaseSnap", "No BaseSnap"); fontFlag(&SkFontFields::fLinearMetrics, &SkFont::isLinearMetrics, "Linear Metrics", "Non-Linear Metrics"); fontFlag(&SkFontFields::fEmbeddedBitmaps, &SkFont::isEmbeddedBitmaps, @@ -1182,6 +1183,9 @@ public: if (fFontOverrides->fEmbolden) { font->writable()->setEmbolden(fFont->isEmbolden()); } + if (fFontOverrides->fBaselineSnap) { + font->writable()->setBaselineSnap(fFont->isBaselineSnap()); + } if (fFontOverrides->fLinearMetrics) { font->writable()->setLinearMetrics(fFont->isLinearMetrics()); } @@ -1795,6 +1799,11 @@ void Viewer::drawImGui() { &SkFontFields::fEmbolden, &SkFont::isEmbolden, &SkFont::setEmbolden); + fontFlag("Baseline Snapping", + "Default\0No Baseline Snapping\0Baseline Snapping\0\0", + &SkFontFields::fBaselineSnap, + &SkFont::isBaselineSnap, &SkFont::setBaselineSnap); + fontFlag("Linear Text", "Default\0No Linear Text\0Linear Text\0\0", &SkFontFields::fLinearMetrics, diff --git a/tools/viewer/Viewer.h b/tools/viewer/Viewer.h index 1ebc927002..6d49c94915 100644 --- a/tools/viewer/Viewer.h +++ b/tools/viewer/Viewer.h @@ -56,6 +56,7 @@ public: bool fEmbeddedBitmaps = false; bool fLinearMetrics = false; bool fEmbolden = false; + bool fBaselineSnap = false; }; struct SkPaintFields { bool fPathEffect = false;