Add a way to disable baseline snapping.

Skia has traditionally snapped horizontal and vertical baslines to
pixels as a kind of baseline hinting. This is a feature which cannot
reliably be implemented from the outside and tends to make static text
better looking by ensuring the baselines are consistent. However, with
animation like scrolling or flying and resizing text the animation
suffers. Allow the user to disable the baseline snapping.

Change-Id: I6ee1c12a07242d10c08ae4b75c73e4e28c860790
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/237124
Commit-Queue: Ben Wagner <bungeman@google.com>
Reviewed-by: Mike Reed <reed@google.com>
Reviewed-by: Florin Malita <fmalita@chromium.org>
This commit is contained in:
Ben Wagner 2019-08-26 16:59:09 -04:00 committed by Skia Commit-Bot
parent dcf9ca1820
commit c17de1d2b7
6 changed files with 44 additions and 4 deletions

View File

@ -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<SkTypeface> fTypeface;
SkScalar fSize;

View File

@ -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);

View File

@ -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

View File

@ -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);
}

View File

@ -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,

View File

@ -56,6 +56,7 @@ public:
bool fEmbeddedBitmaps = false;
bool fLinearMetrics = false;
bool fEmbolden = false;
bool fBaselineSnap = false;
};
struct SkPaintFields {
bool fPathEffect = false;