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:
parent
dcf9ca1820
commit
c17de1d2b7
@ -113,6 +113,13 @@ public:
|
|||||||
*/
|
*/
|
||||||
bool isEmbolden() const { return SkToBool(fFlags & kEmbolden_PrivFlag); }
|
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.
|
/** Sets whether to always hint glyphs.
|
||||||
If forceAutoHinting is set, instructs the font manager 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);
|
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.
|
/** Whether edge pixels draw opaque or with partial transparency.
|
||||||
|
|
||||||
@return one of: Edging::kAlias, Edging::kAntiAlias, Edging::kSubpixelAntiAlias
|
@return one of: Edging::kAlias, Edging::kAntiAlias, Edging::kSubpixelAntiAlias
|
||||||
@ -493,9 +507,15 @@ private:
|
|||||||
kSubpixel_PrivFlag = 1 << 2,
|
kSubpixel_PrivFlag = 1 << 2,
|
||||||
kLinearMetrics_PrivFlag = 1 << 3,
|
kLinearMetrics_PrivFlag = 1 << 3,
|
||||||
kEmbolden_PrivFlag = 1 << 4,
|
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;
|
sk_sp<SkTypeface> fTypeface;
|
||||||
SkScalar fSize;
|
SkScalar fSize;
|
||||||
|
@ -22,7 +22,7 @@
|
|||||||
#include "src/utils/SkUTF.h"
|
#include "src/utils/SkUTF.h"
|
||||||
|
|
||||||
#define kDefault_Size SkPaintDefaults_TextSize
|
#define kDefault_Size SkPaintDefaults_TextSize
|
||||||
#define kDefault_Flags 0
|
#define kDefault_Flags SkFont::kBaselineSnap_PrivFlag
|
||||||
#define kDefault_Edging SkFont::Edging::kAntiAlias
|
#define kDefault_Edging SkFont::Edging::kAntiAlias
|
||||||
#define kDefault_Hinting SkPaintDefaults_Hinting
|
#define kDefault_Hinting SkPaintDefaults_Hinting
|
||||||
|
|
||||||
@ -87,7 +87,9 @@ void SkFont::setLinearMetrics(bool predicate) {
|
|||||||
void SkFont::setEmbolden(bool predicate) {
|
void SkFont::setEmbolden(bool predicate) {
|
||||||
fFlags = set_clear_mask(fFlags, predicate, kEmbolden_PrivFlag);
|
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) {
|
void SkFont::setEdging(Edging e) {
|
||||||
fEdging = SkToU8(e);
|
fEdging = SkToU8(e);
|
||||||
}
|
}
|
||||||
@ -464,6 +466,7 @@ static bool scalar_is_byte(SkScalar x) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void SkFontPriv::Flatten(const SkFont& font, SkWriteBuffer& buffer) {
|
void SkFontPriv::Flatten(const SkFont& font, SkWriteBuffer& buffer) {
|
||||||
|
SkASSERT(font.fFlags <= SkFont::kAllFlags);
|
||||||
SkASSERT((font.fFlags & ~kMask_For_Flags) == 0);
|
SkASSERT((font.fFlags & ~kMask_For_Flags) == 0);
|
||||||
SkASSERT((font.fEdging & ~kMask_For_Edging) == 0);
|
SkASSERT((font.fEdging & ~kMask_For_Edging) == 0);
|
||||||
SkASSERT((font.fHinting & ~kMask_For_Hinting) == 0);
|
SkASSERT((font.fHinting & ~kMask_For_Hinting) == 0);
|
||||||
|
@ -844,6 +844,9 @@ SkAxisAlignment SkScalerContextRec::computeAxisAlignmentForHText() const {
|
|||||||
// * fPreSkewX (has no effect, but would on vertical text alignment).
|
// * fPreSkewX (has no effect, but would on vertical text alignment).
|
||||||
// In other words, making the text bigger, stretching it along the
|
// In other words, making the text bigger, stretching it along the
|
||||||
// horizontal axis, or fake italicizing it does not move the baseline.
|
// 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]) {
|
if (0 == fPost2x2[1][0]) {
|
||||||
// The x axis is mapped onto the x axis.
|
// 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()) {
|
if (font.isLinearMetrics()) {
|
||||||
flags |= SkScalerContext::kLinearMetrics_Flag;
|
flags |= SkScalerContext::kLinearMetrics_Flag;
|
||||||
}
|
}
|
||||||
|
if (font.isBaselineSnap()) {
|
||||||
|
flags |= SkScalerContext::kBaselineSnap_Flag;
|
||||||
|
}
|
||||||
rec->fFlags = SkToU16(flags);
|
rec->fFlags = SkToU16(flags);
|
||||||
|
|
||||||
// these modify fFlags, so do them after assigning fFlags
|
// these modify fFlags, so do them after assigning fFlags
|
||||||
|
@ -242,6 +242,7 @@ public:
|
|||||||
// only meaningful if fMaskFormat is kA8
|
// only meaningful if fMaskFormat is kA8
|
||||||
kGenA8FromLCD_Flag = 0x0800, // could be 0x200 (bit meaning dependent on fMaskFormat)
|
kGenA8FromLCD_Flag = 0x0800, // could be 0x200 (bit meaning dependent on fMaskFormat)
|
||||||
kLinearMetrics_Flag = 0x1000,
|
kLinearMetrics_Flag = 0x1000,
|
||||||
|
kBaselineSnap_Flag = 0x2000,
|
||||||
};
|
};
|
||||||
|
|
||||||
// computed values
|
// computed values
|
||||||
@ -262,7 +263,7 @@ public:
|
|||||||
return SkToBool(fRec.fFlags & kSubpixelPositioning_Flag);
|
return SkToBool(fRec.fFlags & kSubpixelPositioning_Flag);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isLinearMetrics() const {
|
bool isLinearMetrics() const {
|
||||||
return SkToBool(fRec.fFlags & kLinearMetrics_Flag);
|
return SkToBool(fRec.fFlags & kLinearMetrics_Flag);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -818,6 +818,7 @@ void Viewer::updateTitle() {
|
|||||||
fontFlag(&SkFontFields::fForceAutoHinting, &SkFont::isForceAutoHinting,
|
fontFlag(&SkFontFields::fForceAutoHinting, &SkFont::isForceAutoHinting,
|
||||||
"Force Autohint", "No Force Autohint");
|
"Force Autohint", "No Force Autohint");
|
||||||
fontFlag(&SkFontFields::fEmbolden, &SkFont::isEmbolden, "Fake Bold", "No Fake Bold");
|
fontFlag(&SkFontFields::fEmbolden, &SkFont::isEmbolden, "Fake Bold", "No Fake Bold");
|
||||||
|
fontFlag(&SkFontFields::fBaselineSnap, &SkFont::isBaselineSnap, "BaseSnap", "No BaseSnap");
|
||||||
fontFlag(&SkFontFields::fLinearMetrics, &SkFont::isLinearMetrics,
|
fontFlag(&SkFontFields::fLinearMetrics, &SkFont::isLinearMetrics,
|
||||||
"Linear Metrics", "Non-Linear Metrics");
|
"Linear Metrics", "Non-Linear Metrics");
|
||||||
fontFlag(&SkFontFields::fEmbeddedBitmaps, &SkFont::isEmbeddedBitmaps,
|
fontFlag(&SkFontFields::fEmbeddedBitmaps, &SkFont::isEmbeddedBitmaps,
|
||||||
@ -1182,6 +1183,9 @@ public:
|
|||||||
if (fFontOverrides->fEmbolden) {
|
if (fFontOverrides->fEmbolden) {
|
||||||
font->writable()->setEmbolden(fFont->isEmbolden());
|
font->writable()->setEmbolden(fFont->isEmbolden());
|
||||||
}
|
}
|
||||||
|
if (fFontOverrides->fBaselineSnap) {
|
||||||
|
font->writable()->setBaselineSnap(fFont->isBaselineSnap());
|
||||||
|
}
|
||||||
if (fFontOverrides->fLinearMetrics) {
|
if (fFontOverrides->fLinearMetrics) {
|
||||||
font->writable()->setLinearMetrics(fFont->isLinearMetrics());
|
font->writable()->setLinearMetrics(fFont->isLinearMetrics());
|
||||||
}
|
}
|
||||||
@ -1795,6 +1799,11 @@ void Viewer::drawImGui() {
|
|||||||
&SkFontFields::fEmbolden,
|
&SkFontFields::fEmbolden,
|
||||||
&SkFont::isEmbolden, &SkFont::setEmbolden);
|
&SkFont::isEmbolden, &SkFont::setEmbolden);
|
||||||
|
|
||||||
|
fontFlag("Baseline Snapping",
|
||||||
|
"Default\0No Baseline Snapping\0Baseline Snapping\0\0",
|
||||||
|
&SkFontFields::fBaselineSnap,
|
||||||
|
&SkFont::isBaselineSnap, &SkFont::setBaselineSnap);
|
||||||
|
|
||||||
fontFlag("Linear Text",
|
fontFlag("Linear Text",
|
||||||
"Default\0No Linear Text\0Linear Text\0\0",
|
"Default\0No Linear Text\0Linear Text\0\0",
|
||||||
&SkFontFields::fLinearMetrics,
|
&SkFontFields::fLinearMetrics,
|
||||||
|
@ -56,6 +56,7 @@ public:
|
|||||||
bool fEmbeddedBitmaps = false;
|
bool fEmbeddedBitmaps = false;
|
||||||
bool fLinearMetrics = false;
|
bool fLinearMetrics = false;
|
||||||
bool fEmbolden = false;
|
bool fEmbolden = false;
|
||||||
|
bool fBaselineSnap = false;
|
||||||
};
|
};
|
||||||
struct SkPaintFields {
|
struct SkPaintFields {
|
||||||
bool fPathEffect = false;
|
bool fPathEffect = false;
|
||||||
|
Loading…
Reference in New Issue
Block a user