Store SkFont in android::Paint
Test: CTS
Change-Id: I974fad5a7a8cf54007f0a30f4fe4ae6eb6e01ae1
diff --git a/libs/hwui/SkiaCanvas.cpp b/libs/hwui/SkiaCanvas.cpp
index cc62fdc..54a91f4 100644
--- a/libs/hwui/SkiaCanvas.cpp
+++ b/libs/hwui/SkiaCanvas.cpp
@@ -682,12 +682,11 @@
float y, float boundsLeft, float boundsTop, float boundsRight,
float boundsBottom, float totalAdvance) {
if (count <= 0 || paint.nothingToDraw()) return;
- SkPaint paintCopy(paint);
+ Paint paintCopy(paint);
if (mPaintFilter) {
- mPaintFilter->filter(&paintCopy);
+ mPaintFilter->filterFullPaint(&paintCopy);
}
- SkFont font = SkFont::LEGACY_ExtractFromPaint(paintCopy);
- SkASSERT(paintCopy.getTextEncoding() == kGlyphID_SkTextEncoding);
+ const SkFont& font = paintCopy.getSkFont();
// Stroke with a hairline is drawn on HW with a fill style for compatibility with Android O and
// older.
if (!mCanvasOwned && sApiLevel <= 27 && paintCopy.getStrokeWidth() <= 0 &&
@@ -710,12 +709,11 @@
void SkiaCanvas::drawLayoutOnPath(const minikin::Layout& layout, float hOffset, float vOffset,
const Paint& paint, const SkPath& path, size_t start,
size_t end) {
- SkPaint paintCopy(paint);
+ Paint paintCopy(paint);
if (mPaintFilter) {
- mPaintFilter->filter(&paintCopy);
+ mPaintFilter->filterFullPaint(&paintCopy);
}
- SkFont font = SkFont::LEGACY_ExtractFromPaint(paintCopy);
- SkASSERT(paintCopy.getTextEncoding() == kGlyphID_SkTextEncoding);
+ const SkFont& font = paintCopy.getSkFont();
const int N = end - start;
SkTextBlobBuilder builder;
diff --git a/libs/hwui/hwui/Canvas.cpp b/libs/hwui/hwui/Canvas.cpp
index 277148e..5231486 100644
--- a/libs/hwui/hwui/Canvas.cpp
+++ b/libs/hwui/hwui/Canvas.cpp
@@ -39,34 +39,28 @@
}
void Canvas::drawTextDecorations(float x, float y, float length, const Paint& paint) {
- uint32_t flags;
- PaintFilter* paintFilter = getPaintFilter();
- if (paintFilter) {
- SkPaint paintCopy(paint);
- paintFilter->filter(&paintCopy);
- flags = paintCopy.getFlags();
- } else {
- flags = paint.getFlags();
- }
- if (flags & (SkPaint::kUnderlineText_ReserveFlag | SkPaint::kStrikeThruText_ReserveFlag)) {
+ // paint has already been filtered by our caller, so we can ignore any filter
+ const bool strikeThru = paint.isStrikeThru();
+ const bool underline = paint.isUnderline();
+ if (strikeThru || underline) {
const SkScalar left = x;
const SkScalar right = x + length;
- if (flags & SkPaint::kUnderlineText_ReserveFlag) {
+ const float textSize = paint.getSkFont().getSize();
+ if (underline) {
SkFontMetrics metrics;
- paint.getFontMetrics(&metrics);
+ paint.getSkFont().getMetrics(&metrics);
SkScalar position;
if (!metrics.hasUnderlinePosition(&position)) {
- position = paint.getTextSize() * Paint::kStdUnderline_Top;
+ position = textSize * Paint::kStdUnderline_Top;
}
SkScalar thickness;
if (!metrics.hasUnderlineThickness(&thickness)) {
- thickness = paint.getTextSize() * Paint::kStdUnderline_Thickness;
+ thickness = textSize * Paint::kStdUnderline_Thickness;
}
const SkScalar top = y + position;
drawStroke(left, right, top, thickness, paint, this);
}
- if (flags & SkPaint::kStrikeThruText_ReserveFlag) {
- const float textSize = paint.getTextSize();
+ if (strikeThru) {
const float position = textSize * Paint::kStdStrikeThru_Top;
const SkScalar thickness = textSize * Paint::kStdStrikeThru_Thickness;
const SkScalar top = y + position;
@@ -75,19 +69,19 @@
}
}
-static void simplifyPaint(int color, SkPaint* paint) {
+static void simplifyPaint(int color, Paint* paint) {
paint->setColor(color);
paint->setShader(nullptr);
paint->setColorFilter(nullptr);
paint->setLooper(nullptr);
- paint->setStrokeWidth(4 + 0.04 * paint->getTextSize());
+ paint->setStrokeWidth(4 + 0.04 * paint->getSkFont().getSize());
paint->setStrokeJoin(SkPaint::kRound_Join);
paint->setLooper(nullptr);
}
class DrawTextFunctor {
public:
- DrawTextFunctor(const minikin::Layout& layout, Canvas* canvas, const SkPaint& paint, float x,
+ DrawTextFunctor(const minikin::Layout& layout, Canvas* canvas, const Paint& paint, float x,
float y, minikin::MinikinRect& bounds, float totalAdvance)
: layout(layout)
, canvas(canvas)
@@ -123,14 +117,14 @@
bool darken = channelSum < (128 * 3);
// outline
- SkPaint outlinePaint(paint);
+ Paint outlinePaint(paint);
simplifyPaint(darken ? SK_ColorWHITE : SK_ColorBLACK, &outlinePaint);
outlinePaint.setStyle(SkPaint::kStrokeAndFill_Style);
canvas->drawGlyphs(glyphFunc, glyphCount, outlinePaint, x, y, bounds.mLeft, bounds.mTop,
bounds.mRight, bounds.mBottom, totalAdvance);
// inner
- SkPaint innerPaint(paint);
+ Paint innerPaint(paint);
simplifyPaint(darken ? SK_ColorBLACK : SK_ColorWHITE, &innerPaint);
innerPaint.setStyle(SkPaint::kFill_Style);
canvas->drawGlyphs(glyphFunc, glyphCount, innerPaint, x, y, bounds.mLeft, bounds.mTop,
@@ -145,7 +139,7 @@
private:
const minikin::Layout& layout;
Canvas* canvas;
- const SkPaint& paint;
+ const Paint& paint;
float x;
float y;
minikin::MinikinRect& bounds;
diff --git a/libs/hwui/hwui/MinikinSkia.cpp b/libs/hwui/hwui/MinikinSkia.cpp
index 84292c8..375f5bc 100644
--- a/libs/hwui/hwui/MinikinSkia.cpp
+++ b/libs/hwui/hwui/MinikinSkia.cpp
@@ -17,8 +17,9 @@
#include "MinikinSkia.h"
#include <SkFontDescriptor.h>
+#include <SkFont.h>
+#include <SkFontMetrics.h>
#include <SkFontMgr.h>
-#include <SkPaint.h>
#include <SkTypeface.h>
#include <log/log.h>
@@ -40,25 +41,24 @@
, mAxes(axes)
, mFilePath(filePath) {}
-static void MinikinFontSkia_SetSkiaPaint(const minikin::MinikinFont* font, SkPaint* skPaint,
- const minikin::MinikinPaint& paint,
- const minikin::FontFakery& fakery) {
- skPaint->setTextEncoding(kGlyphID_SkTextEncoding);
- skPaint->setTextSize(paint.size);
- skPaint->setTextScaleX(paint.scaleX);
- skPaint->setTextSkewX(paint.skewX);
- MinikinFontSkia::unpackPaintFlags(skPaint, paint.paintFlags);
+static void MinikinFontSkia_SetSkiaFont(const minikin::MinikinFont* font, SkFont* skFont,
+ const minikin::MinikinPaint& paint,
+ const minikin::FontFakery& fakery) {
+ skFont->setSize(paint.size);
+ skFont->setScaleX(paint.scaleX);
+ skFont->setSkewX(paint.skewX);
+ MinikinFontSkia::unpackFontFlags(skFont, paint.fontFlags);
// Apply font fakery on top of user-supplied flags.
- MinikinFontSkia::populateSkPaint(skPaint, font, fakery);
+ MinikinFontSkia::populateSkFont(skFont, font, fakery);
}
float MinikinFontSkia::GetHorizontalAdvance(uint32_t glyph_id, const minikin::MinikinPaint& paint,
const minikin::FontFakery& fakery) const {
- SkPaint skPaint;
+ SkFont skFont;
uint16_t glyph16 = glyph_id;
SkScalar skWidth;
- MinikinFontSkia_SetSkiaPaint(this, &skPaint, paint, fakery);
- skPaint.getTextWidths(&glyph16, sizeof(glyph16), &skWidth, NULL);
+ MinikinFontSkia_SetSkiaFont(this, &skFont, paint, fakery);
+ skFont.getWidths(&glyph16, 1, &skWidth);
#ifdef VERBOSE
ALOGD("width for typeface %d glyph %d = %f", mTypeface->uniqueID(), glyph_id, skWidth);
#endif
@@ -68,11 +68,11 @@
void MinikinFontSkia::GetBounds(minikin::MinikinRect* bounds, uint32_t glyph_id,
const minikin::MinikinPaint& paint,
const minikin::FontFakery& fakery) const {
- SkPaint skPaint;
+ SkFont skFont;
uint16_t glyph16 = glyph_id;
SkRect skBounds;
- MinikinFontSkia_SetSkiaPaint(this, &skPaint, paint, fakery);
- skPaint.getTextWidths(&glyph16, sizeof(glyph16), NULL, &skBounds);
+ MinikinFontSkia_SetSkiaFont(this, &skFont, paint, fakery);
+ skFont.getWidths(&glyph16, 1, nullptr, &skBounds);
bounds->mLeft = skBounds.fLeft;
bounds->mTop = skBounds.fTop;
bounds->mRight = skBounds.fRight;
@@ -82,10 +82,10 @@
void MinikinFontSkia::GetFontExtent(minikin::MinikinExtent* extent,
const minikin::MinikinPaint& paint,
const minikin::FontFakery& fakery) const {
- SkPaint skPaint;
- MinikinFontSkia_SetSkiaPaint(this, &skPaint, paint, fakery);
+ SkFont skFont;
+ MinikinFontSkia_SetSkiaFont(this, &skFont, paint, fakery);
SkFontMetrics metrics;
- skPaint.getFontMetrics(&metrics);
+ skFont.getMetrics(&metrics);
extent->ascent = metrics.fAscent;
extent->descent = metrics.fDescent;
}
@@ -137,28 +137,36 @@
ttcIndex, variations);
}
-uint32_t MinikinFontSkia::packPaintFlags(const SkPaint* paint) {
- uint32_t flags = paint->getFlags();
- unsigned hinting = static_cast<unsigned>(paint->getHinting());
- // select only flags that might affect text layout
- flags &= (SkPaint::kAntiAlias_Flag | SkPaint::kFakeBoldText_Flag | SkPaint::kLinearText_Flag |
- SkPaint::kSubpixelText_Flag | SkPaint::kEmbeddedBitmapText_Flag |
- SkPaint::kAutoHinting_Flag);
- flags |= (hinting << 16);
+// hinting<<16 | edging<<8 | bools:5bits
+uint32_t MinikinFontSkia::packFontFlags(const SkFont& font) {
+ uint32_t flags = (unsigned)font.getHinting() << 16;
+ flags |= (unsigned)font.getEdging() << 8;
+ flags |= font.isEmbolden() << minikin::Embolden_Shift;
+ flags |= font.isLinearMetrics() << minikin::LinearMetrics_Shift;
+ flags |= font.isSubpixel() << minikin::Subpixel_Shift;
+ flags |= font.isEmbeddedBitmaps() << minikin::EmbeddedBitmaps_Shift;
+ flags |= font.isForceAutoHinting() << minikin::ForceAutoHinting_Shift;
return flags;
}
-void MinikinFontSkia::unpackPaintFlags(SkPaint* paint, uint32_t paintFlags) {
- paint->setFlags(paintFlags & SkPaint::kAllFlags);
- paint->setHinting(static_cast<SkFontHinting>(paintFlags >> 16));
+void MinikinFontSkia::unpackFontFlags(SkFont* font, uint32_t flags) {
+ // We store hinting in the top 16 bits (only need 2 of them)
+ font->setHinting((SkFontHinting)(flags >> 16));
+ // We store edging in bits 8:15 (only need 2 of them)
+ font->setEdging((SkFont::Edging)((flags >> 8) & 0xFF));
+ font->setEmbolden( (flags & minikin::Embolden_Flag) != 0);
+ font->setLinearMetrics( (flags & minikin::LinearMetrics_Flag) != 0);
+ font->setSubpixel( (flags & minikin::Subpixel_Flag) != 0);
+ font->setEmbeddedBitmaps( (flags & minikin::EmbeddedBitmaps_Flag) != 0);
+ font->setForceAutoHinting((flags & minikin::ForceAutoHinting_Flag) != 0);
}
-void MinikinFontSkia::populateSkPaint(SkPaint* paint, const MinikinFont* font,
- minikin::FontFakery fakery) {
- paint->setTypeface(reinterpret_cast<const MinikinFontSkia*>(font)->RefSkTypeface());
- paint->setFakeBoldText(paint->isFakeBoldText() || fakery.isFakeBold());
+void MinikinFontSkia::populateSkFont(SkFont* skFont, const MinikinFont* font,
+ minikin::FontFakery fakery) {
+ skFont->setTypeface(reinterpret_cast<const MinikinFontSkia*>(font)->RefSkTypeface());
+ skFont->setEmbolden(skFont->isEmbolden() || fakery.isFakeBold());
if (fakery.isFakeItalic()) {
- paint->setTextSkewX(paint->getTextSkewX() - 0.25f);
+ skFont->setSkewX(skFont->getSkewX() - 0.25f);
}
}
}
diff --git a/libs/hwui/hwui/MinikinSkia.h b/libs/hwui/hwui/MinikinSkia.h
index 55576b7..ad46b23 100644
--- a/libs/hwui/hwui/MinikinSkia.h
+++ b/libs/hwui/hwui/MinikinSkia.h
@@ -21,7 +21,7 @@
#include <cutils/compiler.h>
#include <minikin/MinikinFont.h>
-class SkPaint;
+class SkFont;
class SkTypeface;
namespace android {
@@ -54,12 +54,12 @@
std::shared_ptr<minikin::MinikinFont> createFontWithVariation(
const std::vector<minikin::FontVariation>&) const;
- static uint32_t packPaintFlags(const SkPaint* paint);
- static void unpackPaintFlags(SkPaint* paint, uint32_t paintFlags);
+ static uint32_t packFontFlags(const SkFont&);
+ static void unpackFontFlags(SkFont*, uint32_t fontFlags);
// set typeface and fake bold/italic parameters
- static void populateSkPaint(SkPaint* paint, const minikin::MinikinFont* font,
- minikin::FontFakery fakery);
+ static void populateSkFont(SkFont*, const minikin::MinikinFont* font,
+ minikin::FontFakery fakery);
private:
sk_sp<SkTypeface> mTypeface;
diff --git a/libs/hwui/hwui/MinikinUtils.cpp b/libs/hwui/hwui/MinikinUtils.cpp
index ba240fe..733f8e4 100644
--- a/libs/hwui/hwui/MinikinUtils.cpp
+++ b/libs/hwui/hwui/MinikinUtils.cpp
@@ -30,16 +30,17 @@
minikin::MinikinPaint MinikinUtils::prepareMinikinPaint(const Paint* paint,
const Typeface* typeface) {
const Typeface* resolvedFace = Typeface::resolveDefault(typeface);
+ const SkFont& font = paint->getSkFont();
minikin::MinikinPaint minikinPaint(resolvedFace->fFontCollection);
/* Prepare minikin Paint */
minikinPaint.size =
- paint->isLinearText() ? paint->getTextSize() : static_cast<int>(paint->getTextSize());
- minikinPaint.scaleX = paint->getTextScaleX();
- minikinPaint.skewX = paint->getTextSkewX();
+ font.isLinearMetrics() ? font.getSize() : static_cast<int>(font.getSize());
+ minikinPaint.scaleX = font.getScaleX();
+ minikinPaint.skewX = font.getSkewX();
minikinPaint.letterSpacing = paint->getLetterSpacing();
minikinPaint.wordSpacing = paint->getWordSpacing();
- minikinPaint.paintFlags = MinikinFontSkia::packPaintFlags(paint);
+ minikinPaint.fontFlags = MinikinFontSkia::packFontFlags(font);
minikinPaint.localeListId = paint->getMinikinLocaleListId();
minikinPaint.familyVariant = paint->getFamilyVariant();
minikinPaint.fontStyle = resolvedFace->fStyle;
diff --git a/libs/hwui/hwui/MinikinUtils.h b/libs/hwui/hwui/MinikinUtils.h
index d27d544..cbf4095 100644
--- a/libs/hwui/hwui/MinikinUtils.h
+++ b/libs/hwui/hwui/MinikinUtils.h
@@ -63,27 +63,29 @@
// f is a functor of type void f(size_t start, size_t end);
template <typename F>
ANDROID_API static void forFontRun(const minikin::Layout& layout, Paint* paint, F& f) {
- float saveSkewX = paint->getTextSkewX();
- bool savefakeBold = paint->isFakeBoldText();
+ float saveSkewX = paint->getSkFont().getSkewX();
+ bool savefakeBold = paint->getSkFont().isEmbolden();
const minikin::MinikinFont* curFont = nullptr;
size_t start = 0;
size_t nGlyphs = layout.nGlyphs();
for (size_t i = 0; i < nGlyphs; i++) {
const minikin::MinikinFont* nextFont = layout.getFont(i);
if (i > 0 && nextFont != curFont) {
- MinikinFontSkia::populateSkPaint(paint, curFont, layout.getFakery(start));
+ SkFont* skfont = &paint->getSkFont();
+ MinikinFontSkia::populateSkFont(skfont, curFont, layout.getFakery(start));
f(start, i);
- paint->setTextSkewX(saveSkewX);
- paint->setFakeBoldText(savefakeBold);
+ skfont->setSkewX(saveSkewX);
+ skfont->setEmbolden(savefakeBold);
start = i;
}
curFont = nextFont;
}
if (nGlyphs > start) {
- MinikinFontSkia::populateSkPaint(paint, curFont, layout.getFakery(start));
+ SkFont* skfont = &paint->getSkFont();
+ MinikinFontSkia::populateSkFont(skfont, curFont, layout.getFakery(start));
f(start, nGlyphs);
- paint->setTextSkewX(saveSkewX);
- paint->setFakeBoldText(savefakeBold);
+ skfont->setSkewX(saveSkewX);
+ skfont->setEmbolden(savefakeBold);
}
}
};
diff --git a/libs/hwui/hwui/Paint.h b/libs/hwui/hwui/Paint.h
index 92ffda9..601b3c2 100644
--- a/libs/hwui/hwui/Paint.h
+++ b/libs/hwui/hwui/Paint.h
@@ -21,6 +21,7 @@
#include <cutils/compiler.h>
+#include <SkFont.h>
#include <SkPaint.h>
#include <string>
@@ -46,7 +47,6 @@
Paint();
Paint(const Paint& paint);
- Paint(const SkPaint& paint); // NOLINT(google-explicit-constructor)
~Paint();
Paint& operator=(const Paint& other);
@@ -54,6 +54,17 @@
friend bool operator==(const Paint& a, const Paint& b);
friend bool operator!=(const Paint& a, const Paint& b) { return !(a == b); }
+ SkFont& getSkFont() { return mFont; }
+ const SkFont& getSkFont() const { return mFont; }
+
+ // These shadow the methods on SkPaint, but we need to so we can keep related
+ // attributes in-sync.
+
+ void reset();
+ void setAntiAlias(bool);
+
+ // End method shadowing
+
void setLetterSpacing(float letterSpacing) { mLetterSpacing = letterSpacing; }
float getLetterSpacing() const { return mLetterSpacing; }
@@ -94,7 +105,31 @@
Align getTextAlign() const { return mAlign; }
void setTextAlign(Align align) { mAlign = align; }
+ bool isStrikeThru() const { return mStrikeThru; }
+ void setStrikeThru(bool st) { mStrikeThru = st; }
+
+ bool isUnderline() const { return mUnderline; }
+ void setUnderline(bool u) { mUnderline = u; }
+
+ bool isDevKern() const { return mDevKern; }
+ void setDevKern(bool d) { mDevKern = d; }
+
+ // The Java flags (Paint.java) no longer fit into the native apis directly.
+ // These methods handle converting to and from them and the native representations
+ // in android::Paint.
+
+ uint32_t getJavaFlags() const;
+ void setJavaFlags(uint32_t);
+
+ // Helpers that return or apply legacy java flags to SkPaint, ignoring all flags
+ // that are meant for SkFont or Paint (e.g. underline, strikethru)
+ // The only respected flags are : [ antialias, dither, filterBitmap ]
+ static uint32_t GetSkPaintJavaFlags(const SkPaint&);
+ static void SetSkPaintJavaFlags(SkPaint*, uint32_t flags);
+
private:
+ SkFont mFont;
+
float mLetterSpacing = 0;
float mWordSpacing = 0;
std::string mFontFeatureSettings;
@@ -107,6 +142,9 @@
// nullptr is valid: it means the default typeface.
const Typeface* mTypeface = nullptr;
Align mAlign = kLeft_Align;
+ bool mStrikeThru = false;
+ bool mUnderline = false;
+ bool mDevKern = false;
};
} // namespace android
diff --git a/libs/hwui/hwui/PaintFilter.h b/libs/hwui/hwui/PaintFilter.h
index bf5627e..0e7b619 100644
--- a/libs/hwui/hwui/PaintFilter.h
+++ b/libs/hwui/hwui/PaintFilter.h
@@ -12,6 +12,7 @@
* The implementation may modify the paint as they wish.
*/
virtual void filter(SkPaint*) = 0;
+ virtual void filterFullPaint(Paint*) = 0;
};
} // namespace android
diff --git a/libs/hwui/hwui/PaintImpl.cpp b/libs/hwui/hwui/PaintImpl.cpp
index bdbf5ca..d2903f0 100644
--- a/libs/hwui/hwui/PaintImpl.cpp
+++ b/libs/hwui/hwui/PaintImpl.cpp
@@ -24,10 +24,16 @@
, mWordSpacing(0)
, mFontFeatureSettings()
, mMinikinLocaleListId(0)
- , mFamilyVariant(minikin::FamilyVariant::DEFAULT) {}
+ , mFamilyVariant(minikin::FamilyVariant::DEFAULT) {
+ // SkPaint::antialiasing defaults to false, but
+ // SkFont::edging defaults to kAntiAlias. To keep them
+ // insync, we manually set the font to kAilas.
+ mFont.setEdging(SkFont::Edging::kAlias);
+}
Paint::Paint(const Paint& paint)
: SkPaint(paint)
+ , mFont(paint.mFont)
, mLetterSpacing(paint.mLetterSpacing)
, mWordSpacing(paint.mWordSpacing)
, mFontFeatureSettings(paint.mFontFeatureSettings)
@@ -35,20 +41,17 @@
, mFamilyVariant(paint.mFamilyVariant)
, mHyphenEdit(paint.mHyphenEdit)
, mTypeface(paint.mTypeface)
- , mAlign(paint.mAlign) {}
+ , mAlign(paint.mAlign)
+ , mStrikeThru(paint.mStrikeThru)
+ , mUnderline(paint.mUnderline)
+ , mDevKern(paint.mDevKern) {}
-Paint::Paint(const SkPaint& paint)
- : SkPaint(paint)
- , mLetterSpacing(0)
- , mWordSpacing(0)
- , mFontFeatureSettings()
- , mMinikinLocaleListId(0)
- , mFamilyVariant(minikin::FamilyVariant::DEFAULT) {}
Paint::~Paint() {}
Paint& Paint::operator=(const Paint& other) {
SkPaint::operator=(other);
+ mFont = other.mFont;
mLetterSpacing = other.mLetterSpacing;
mWordSpacing = other.mWordSpacing;
mFontFeatureSettings = other.mFontFeatureSettings;
@@ -57,15 +60,136 @@
mHyphenEdit = other.mHyphenEdit;
mTypeface = other.mTypeface;
mAlign = other.mAlign;
+ mStrikeThru = other.mStrikeThru;
+ mUnderline = other.mUnderline;
+ mDevKern = other.mDevKern;
return *this;
}
bool operator==(const Paint& a, const Paint& b) {
return static_cast<const SkPaint&>(a) == static_cast<const SkPaint&>(b) &&
+ a.mFont == b.mFont &&
a.mLetterSpacing == b.mLetterSpacing && a.mWordSpacing == b.mWordSpacing &&
a.mFontFeatureSettings == b.mFontFeatureSettings &&
a.mMinikinLocaleListId == b.mMinikinLocaleListId &&
a.mFamilyVariant == b.mFamilyVariant && a.mHyphenEdit == b.mHyphenEdit &&
- a.mTypeface == b.mTypeface && a.mAlign == b.mAlign;
+ a.mTypeface == b.mTypeface && a.mAlign == b.mAlign &&
+ a.mStrikeThru == b.mStrikeThru && a.mUnderline == b.mUnderline &&
+ a.mDevKern == b.mDevKern;
}
+
+void Paint::reset() {
+ SkPaint::reset();
+
+ mFont = SkFont();
+ mFont.setEdging(SkFont::Edging::kAlias);
+
+ mStrikeThru = false;
+ mUnderline = false;
+ mDevKern = false;
+}
+
+void Paint::setAntiAlias(bool aa) {
+ // Java does not support/understand subpixel(lcd) antialiasing
+ SkASSERT(mFont.getEdging() != SkFont::Edging::kSubpixelAntiAlias);
+ // JavaPaint antialiasing affects both the SkPaint and SkFont settings.
+ SkPaint::setAntiAlias(aa);
+ mFont.setEdging(aa ? SkFont::Edging::kAntiAlias : SkFont::Edging::kAlias);
+}
+
+////////////////// Java flags compatibility //////////////////
+
+/* Flags are tricky. Java has its own idea of the "paint" flags, but they don't really
+ match up with skia anymore, so we have to do some shuffling in get/set flags()
+
+ 3 flags apply to SkPaint (antialias, dither, filter -> enum)
+ 5 flags (merged with antialias) are for SkFont
+ 2 flags are for minikin::Paint (underline and strikethru)
+*/
+
+// flags relating to SkPaint
+static const uint32_t sAntiAliasFlag = 0x01; // affects paint and font-edging
+static const uint32_t sFilterBitmapFlag = 0x02; // maps to enum
+static const uint32_t sDitherFlag = 0x04;
+// flags relating to SkFont
+static const uint32_t sFakeBoldFlag = 0x020;
+static const uint32_t sLinearMetrics = 0x040;
+static const uint32_t sSubpixelMetrics = 0x080;
+static const uint32_t sEmbeddedBitmaps = 0x400;
+static const uint32_t sForceAutoHinting = 0x800;
+// flags related to minikin::Paint
+static const uint32_t sUnderlineFlag = 0x08;
+static const uint32_t sStrikeThruFlag = 0x10;
+// flags no longer supported on native side (but mirrored for compatibility)
+static const uint32_t sDevKernFlag = 0x100;
+
+static uint32_t paintToLegacyFlags(const SkPaint& paint) {
+ uint32_t flags = 0;
+ flags |= -(int)paint.isAntiAlias() & sAntiAliasFlag;
+ flags |= -(int)paint.isDither() & sDitherFlag;
+ if (paint.getFilterQuality() != kNone_SkFilterQuality) {
+ flags |= sFilterBitmapFlag;
+ }
+ return flags;
+}
+
+static uint32_t fontToLegacyFlags(const SkFont& font) {
+ uint32_t flags = 0;
+ flags |= -(int)font.isEmbolden() & sFakeBoldFlag;
+ flags |= -(int)font.isLinearMetrics() & sLinearMetrics;
+ flags |= -(int)font.isSubpixel() & sSubpixelMetrics;
+ flags |= -(int)font.isEmbeddedBitmaps() & sEmbeddedBitmaps;
+ flags |= -(int)font.isForceAutoHinting() & sForceAutoHinting;
+ return flags;
+}
+
+static void applyLegacyFlagsToPaint(uint32_t flags, SkPaint* paint) {
+ paint->setAntiAlias((flags & sAntiAliasFlag) != 0);
+ paint->setDither ((flags & sDitherFlag) != 0);
+
+ if (flags & sFilterBitmapFlag) {
+ paint->setFilterQuality(kLow_SkFilterQuality);
+ } else {
+ paint->setFilterQuality(kNone_SkFilterQuality);
+ }
+}
+
+static void applyLegacyFlagsToFont(uint32_t flags, SkFont* font) {
+ font->setEmbolden ((flags & sFakeBoldFlag) != 0);
+ font->setLinearMetrics ((flags & sLinearMetrics) != 0);
+ font->setSubpixel ((flags & sSubpixelMetrics) != 0);
+ font->setEmbeddedBitmaps ((flags & sEmbeddedBitmaps) != 0);
+ font->setForceAutoHinting((flags & sForceAutoHinting) != 0);
+
+ if (flags & sAntiAliasFlag) {
+ font->setEdging(SkFont::Edging::kAntiAlias);
+ } else {
+ font->setEdging(SkFont::Edging::kAlias);
+ }
+}
+
+uint32_t Paint::GetSkPaintJavaFlags(const SkPaint& paint) {
+ return paintToLegacyFlags(paint);
+}
+
+void Paint::SetSkPaintJavaFlags(SkPaint* paint, uint32_t flags) {
+ applyLegacyFlagsToPaint(flags, paint);
+}
+
+uint32_t Paint::getJavaFlags() const {
+ uint32_t flags = paintToLegacyFlags(*this) | fontToLegacyFlags(mFont);
+ flags |= -(int)mStrikeThru & sStrikeThruFlag;
+ flags |= -(int)mUnderline & sUnderlineFlag;
+ flags |= -(int)mDevKern & sDevKernFlag;
+ return flags;
+}
+
+void Paint::setJavaFlags(uint32_t flags) {
+ applyLegacyFlagsToPaint(flags, this);
+ applyLegacyFlagsToFont(flags, &mFont);
+ mStrikeThru = (flags & sStrikeThruFlag) != 0;
+ mUnderline = (flags & sUnderlineFlag) != 0;
+ mDevKern = (flags & sDevKernFlag) != 0;
+}
+
} // namespace android
diff --git a/libs/hwui/tests/common/TestUtils.cpp b/libs/hwui/tests/common/TestUtils.cpp
index 16a27598..a9f651d 100644
--- a/libs/hwui/tests/common/TestUtils.cpp
+++ b/libs/hwui/tests/common/TestUtils.cpp
@@ -78,24 +78,21 @@
return layerUpdater;
}
-void TestUtils::drawUtf8ToCanvas(Canvas* canvas, const char* text, const SkPaint& paint, float x,
+void TestUtils::drawUtf8ToCanvas(Canvas* canvas, const char* text, const Paint& paint, float x,
float y) {
auto utf16 = asciiToUtf16(text);
uint32_t length = strlen(text);
- Paint glyphPaint(paint);
- glyphPaint.setTextEncoding(kGlyphID_SkTextEncoding);
+
canvas->drawText(utf16.get(), length, // text buffer
0, length, // draw range
0, length, // context range
- x, y, minikin::Bidi::LTR, glyphPaint, nullptr, nullptr /* measured text */);
+ x, y, minikin::Bidi::LTR, paint, nullptr, nullptr /* measured text */);
}
-void TestUtils::drawUtf8ToCanvas(Canvas* canvas, const char* text, const SkPaint& paint,
+void TestUtils::drawUtf8ToCanvas(Canvas* canvas, const char* text, const Paint& paint,
const SkPath& path) {
auto utf16 = asciiToUtf16(text);
- Paint glyphPaint(paint);
- glyphPaint.setTextEncoding(kGlyphID_SkTextEncoding);
- canvas->drawTextOnPath(utf16.get(), strlen(text), minikin::Bidi::LTR, path, 0, 0, glyphPaint,
+ canvas->drawTextOnPath(utf16.get(), strlen(text), minikin::Bidi::LTR, path, 0, 0, paint,
nullptr);
}
diff --git a/libs/hwui/tests/common/TestUtils.h b/libs/hwui/tests/common/TestUtils.h
index 6a1ca5a..e7124df 100644
--- a/libs/hwui/tests/common/TestUtils.h
+++ b/libs/hwui/tests/common/TestUtils.h
@@ -278,10 +278,10 @@
static SkColor interpolateColor(float fraction, SkColor start, SkColor end);
- static void drawUtf8ToCanvas(Canvas* canvas, const char* text, const SkPaint& paint, float x,
+ static void drawUtf8ToCanvas(Canvas* canvas, const char* text, const Paint& paint, float x,
float y);
- static void drawUtf8ToCanvas(Canvas* canvas, const char* text, const SkPaint& paint,
+ static void drawUtf8ToCanvas(Canvas* canvas, const char* text, const Paint& paint,
const SkPath& path);
static std::unique_ptr<uint16_t[]> asciiToUtf16(const char* str);
diff --git a/libs/hwui/tests/common/scenes/GlyphStressAnimation.cpp b/libs/hwui/tests/common/scenes/GlyphStressAnimation.cpp
index f0a5e9d..0795d13 100644
--- a/libs/hwui/tests/common/scenes/GlyphStressAnimation.cpp
+++ b/libs/hwui/tests/common/scenes/GlyphStressAnimation.cpp
@@ -51,7 +51,7 @@
paint.setAntiAlias(true);
paint.setColor(Color::Black);
for (int i = 0; i < 5; i++) {
- paint.setTextSize(10 + (frameNr % 20) + i * 20);
+ paint.getSkFont().setSize(10 + (frameNr % 20) + i * 20);
TestUtils::drawUtf8ToCanvas(canvas.get(), text, paint, 0, 100 * (i + 2));
}
diff --git a/libs/hwui/tests/common/scenes/ListOfFadedTextAnimation.cpp b/libs/hwui/tests/common/scenes/ListOfFadedTextAnimation.cpp
index 58c9980..ecaaf48 100644
--- a/libs/hwui/tests/common/scenes/ListOfFadedTextAnimation.cpp
+++ b/libs/hwui/tests/common/scenes/ListOfFadedTextAnimation.cpp
@@ -16,7 +16,7 @@
#include "TestSceneBase.h"
#include "tests/common/TestListViewSceneBase.h"
-
+#include "hwui/Paint.h"
#include <SkGradientShader.h>
class ListOfFadedTextAnimation;
@@ -33,8 +33,8 @@
canvas.drawColor(Color::White, SkBlendMode::kSrcOver);
int length = dp(100);
canvas.saveLayer(0, 0, length, itemHeight, nullptr, SaveFlags::HasAlphaLayer);
- SkPaint textPaint;
- textPaint.setTextSize(dp(20));
+ Paint textPaint;
+ textPaint.getSkFont().setSize(dp(20));
textPaint.setAntiAlias(true);
TestUtils::drawUtf8ToCanvas(&canvas, "not that long long text", textPaint, dp(10), dp(30));
diff --git a/libs/hwui/tests/common/scenes/ListViewAnimation.cpp b/libs/hwui/tests/common/scenes/ListViewAnimation.cpp
index 4111bd2..feb881f 100644
--- a/libs/hwui/tests/common/scenes/ListViewAnimation.cpp
+++ b/libs/hwui/tests/common/scenes/ListViewAnimation.cpp
@@ -16,6 +16,7 @@
#include "TestSceneBase.h"
#include "tests/common/TestListViewSceneBase.h"
+#include "hwui/Paint.h"
#include <SkFont.h>
#include <cstdio>
@@ -83,14 +84,14 @@
roundRectPaint.setColor(Color::White);
canvas.drawRoundRect(0, 0, itemWidth, itemHeight, dp(6), dp(6), roundRectPaint);
- SkPaint textPaint;
+ Paint textPaint;
textPaint.setColor(rand() % 2 ? Color::Black : Color::Grey_500);
- textPaint.setTextSize(dp(20));
+ textPaint.getSkFont().setSize(dp(20));
textPaint.setAntiAlias(true);
char buf[256];
snprintf(buf, sizeof(buf), "This card is #%d", cardId);
TestUtils::drawUtf8ToCanvas(&canvas, buf, textPaint, itemHeight, dp(25));
- textPaint.setTextSize(dp(15));
+ textPaint.getSkFont().setSize(dp(15));
TestUtils::drawUtf8ToCanvas(&canvas, "This is some more text on the card", textPaint,
itemHeight, dp(45));
diff --git a/libs/hwui/tests/common/scenes/MagnifierAnimation.cpp b/libs/hwui/tests/common/scenes/MagnifierAnimation.cpp
index aa537b4..f6cff1c 100644
--- a/libs/hwui/tests/common/scenes/MagnifierAnimation.cpp
+++ b/libs/hwui/tests/common/scenes/MagnifierAnimation.cpp
@@ -17,6 +17,7 @@
#include "TestSceneBase.h"
#include "renderthread/RenderProxy.h"
#include "utils/Color.h"
+#include "hwui/Paint.h"
class MagnifierAnimation;
@@ -37,9 +38,9 @@
canvas.drawColor(Color::White, SkBlendMode::kSrcOver);
card = TestUtils::createNode(
0, 0, width, height, [&](RenderProperties& props, Canvas& canvas) {
- SkPaint paint;
+ Paint paint;
paint.setAntiAlias(true);
- paint.setTextSize(50);
+ paint.getSkFont().setSize(50);
paint.setColor(Color::Black);
TestUtils::drawUtf8ToCanvas(&canvas, "Test string", paint, 10, 400);
diff --git a/libs/hwui/tests/common/scenes/SaveLayer2Animation.cpp b/libs/hwui/tests/common/scenes/SaveLayer2Animation.cpp
index 3befce4..8630be8 100644
--- a/libs/hwui/tests/common/scenes/SaveLayer2Animation.cpp
+++ b/libs/hwui/tests/common/scenes/SaveLayer2Animation.cpp
@@ -41,9 +41,9 @@
int top = bounds.fTop;
mBluePaint.setColor(SkColorSetARGB(255, 0, 0, 255));
- mBluePaint.setTextSize(padding);
+ mBluePaint.getSkFont().setSize(padding);
mGreenPaint.setColor(SkColorSetARGB(255, 0, 255, 0));
- mGreenPaint.setTextSize(padding);
+ mGreenPaint.getSkFont().setSize(padding);
// interleave drawText and drawRect with saveLayer ops
for (int i = 0; i < regions; i++, top += smallRectHeight) {
diff --git a/libs/hwui/tests/common/scenes/TextAnimation.cpp b/libs/hwui/tests/common/scenes/TextAnimation.cpp
index a16b1784..d3090367 100644
--- a/libs/hwui/tests/common/scenes/TextAnimation.cpp
+++ b/libs/hwui/tests/common/scenes/TextAnimation.cpp
@@ -15,6 +15,7 @@
*/
#include "TestSceneBase.h"
+#include "hwui/Paint.h"
class TextAnimation;
@@ -28,9 +29,9 @@
canvas.drawColor(Color::White, SkBlendMode::kSrcOver);
card = TestUtils::createNode(0, 0, width, height, [](RenderProperties& props,
Canvas& canvas) {
- SkPaint paint;
+ Paint paint;
paint.setAntiAlias(true);
- paint.setTextSize(50);
+ paint.getSkFont().setSize(50);
paint.setColor(Color::Black);
for (int i = 0; i < 10; i++) {
diff --git a/libs/hwui/tests/common/scenes/TvApp.cpp b/libs/hwui/tests/common/scenes/TvApp.cpp
index 286f5f1..229c7f3 100644
--- a/libs/hwui/tests/common/scenes/TvApp.cpp
+++ b/libs/hwui/tests/common/scenes/TvApp.cpp
@@ -17,6 +17,7 @@
#include "SkBlendMode.h"
#include "TestSceneBase.h"
#include "tests/common/BitmapAllocationTestUtils.h"
+#include "hwui/Paint.h"
class TvApp;
class TvAppNoRoundedCorner;
@@ -116,13 +117,13 @@
[text, text2](RenderProperties& props, Canvas& canvas) {
canvas.drawColor(0xFFFFEEEE, SkBlendMode::kSrcOver);
- SkPaint paint;
+ Paint paint;
paint.setAntiAlias(true);
- paint.setTextSize(24);
+ paint.getSkFont().setSize(24);
paint.setColor(Color::Black);
TestUtils::drawUtf8ToCanvas(&canvas, text, paint, 10, 30);
- paint.setTextSize(20);
+ paint.getSkFont().setSize(20);
TestUtils::drawUtf8ToCanvas(&canvas, text2, paint, 10, 54);
});