Store SkFont in android::Paint
Test: CTS Change-Id: I974fad5a7a8cf54007f0a30f4fe4ae6eb6e01ae1
This commit is contained in:
@@ -28,6 +28,7 @@
|
||||
|
||||
#include "SkBlurDrawLooper.h"
|
||||
#include "SkColorFilter.h"
|
||||
#include "SkFont.h"
|
||||
#include "SkFontTypes.h"
|
||||
#include "SkMaskFilter.h"
|
||||
#include "SkPath.h"
|
||||
@@ -69,9 +70,21 @@ static JMetricsID gFontMetrics_fieldID;
|
||||
static jclass gFontMetricsInt_class;
|
||||
static JMetricsID gFontMetricsInt_fieldID;
|
||||
|
||||
static void defaultSettingsForAndroid(Paint* paint) {
|
||||
// GlyphID encoding is required because we are using Harfbuzz shaping
|
||||
paint->setTextEncoding(kGlyphID_SkTextEncoding);
|
||||
static void getPosTextPath(const SkFont& font, const uint16_t glyphs[], int count,
|
||||
const SkPoint pos[], SkPath* dst) {
|
||||
struct Rec {
|
||||
SkPath* fDst;
|
||||
const SkPoint* fPos;
|
||||
} rec = { dst, pos };
|
||||
font.getPaths(glyphs, count, [](const SkPath* src, const SkMatrix& mx, void* ctx) {
|
||||
Rec* rec = (Rec*)ctx;
|
||||
if (src) {
|
||||
SkMatrix tmp(mx);
|
||||
tmp.postTranslate(rec->fPos->fX, rec->fPos->fY);
|
||||
rec->fDst->addPath(*src, tmp);
|
||||
}
|
||||
rec->fPos += 1;
|
||||
}, &rec);
|
||||
}
|
||||
|
||||
namespace PaintGlue {
|
||||
@@ -88,18 +101,7 @@ namespace PaintGlue {
|
||||
}
|
||||
|
||||
static jlong init(JNIEnv* env, jobject) {
|
||||
static_assert(1 << 0 == SkPaint::kAntiAlias_Flag, "paint_flags_mismatch");
|
||||
static_assert(1 << 2 == SkPaint::kDither_Flag, "paint_flags_mismatch");
|
||||
static_assert(1 << 3 == SkPaint::kUnderlineText_ReserveFlag, "paint_flags_mismatch");
|
||||
static_assert(1 << 4 == SkPaint::kStrikeThruText_ReserveFlag, "paint_flags_mismatch");
|
||||
static_assert(1 << 5 == SkPaint::kFakeBoldText_Flag, "paint_flags_mismatch");
|
||||
static_assert(1 << 6 == SkPaint::kLinearText_Flag, "paint_flags_mismatch");
|
||||
static_assert(1 << 7 == SkPaint::kSubpixelText_Flag, "paint_flags_mismatch");
|
||||
static_assert(1 << 10 == SkPaint::kEmbeddedBitmapText_Flag, "paint_flags_mismatch");
|
||||
|
||||
Paint* obj = new Paint();
|
||||
defaultSettingsForAndroid(obj);
|
||||
return reinterpret_cast<jlong>(obj);
|
||||
return reinterpret_cast<jlong>(new Paint);
|
||||
}
|
||||
|
||||
static jlong initWithPaint(JNIEnv* env, jobject clazz, jlong paintHandle) {
|
||||
@@ -288,10 +290,11 @@ namespace PaintGlue {
|
||||
pos[i].fX = x + layout.getX(i);
|
||||
pos[i].fY = y + layout.getY(i);
|
||||
}
|
||||
const SkFont& font = paint->getSkFont();
|
||||
if (start == 0) {
|
||||
paint->getPosTextPath(glyphs + start, (end - start) << 1, pos + start, path);
|
||||
getPosTextPath(font, glyphs, end, pos, path);
|
||||
} else {
|
||||
paint->getPosTextPath(glyphs + start, (end - start) << 1, pos + start, &tmpPath);
|
||||
getPosTextPath(font, glyphs + start, end - start, pos + start, &tmpPath);
|
||||
path->addPath(tmpPath);
|
||||
}
|
||||
}
|
||||
@@ -321,7 +324,6 @@ namespace PaintGlue {
|
||||
x += MinikinUtils::xOffsetForTextAlign(paint, layout);
|
||||
Paint::Align align = paint->getTextAlign();
|
||||
paint->setTextAlign(Paint::kLeft_Align);
|
||||
paint->setTextEncoding(kGlyphID_SkTextEncoding);
|
||||
GetTextFunctor f(layout, path, x, y, paint, glyphs, pos);
|
||||
MinikinUtils::forFontRun(layout, paint, f);
|
||||
paint->setTextAlign(align);
|
||||
@@ -584,20 +586,21 @@ namespace PaintGlue {
|
||||
const int kElegantDescent = -500;
|
||||
const int kElegantLeading = 0;
|
||||
Paint* paint = reinterpret_cast<Paint*>(paintHandle);
|
||||
SkFont* font = &paint->getSkFont();
|
||||
const Typeface* typeface = paint->getAndroidTypeface();
|
||||
typeface = Typeface::resolveDefault(typeface);
|
||||
minikin::FakedFont baseFont = typeface->fFontCollection->baseFontFaked(typeface->fStyle);
|
||||
float saveSkewX = paint->getTextSkewX();
|
||||
bool savefakeBold = paint->isFakeBoldText();
|
||||
MinikinFontSkia::populateSkPaint(paint, baseFont.font->typeface().get(), baseFont.fakery);
|
||||
SkScalar spacing = paint->getFontMetrics(metrics);
|
||||
float saveSkewX = font->getSkewX();
|
||||
bool savefakeBold = font->isEmbolden();
|
||||
MinikinFontSkia::populateSkFont(font, baseFont.font->typeface().get(), baseFont.fakery);
|
||||
SkScalar spacing = font->getMetrics(metrics);
|
||||
// The populateSkPaint call may have changed fake bold / text skew
|
||||
// because we want to measure with those effects applied, so now
|
||||
// restore the original settings.
|
||||
paint->setTextSkewX(saveSkewX);
|
||||
paint->setFakeBoldText(savefakeBold);
|
||||
font->setSkewX(saveSkewX);
|
||||
font->setEmbolden(savefakeBold);
|
||||
if (paint->getFamilyVariant() == minikin::FamilyVariant::ELEGANT) {
|
||||
SkScalar size = paint->getTextSize();
|
||||
SkScalar size = font->getSize();
|
||||
metrics->fTop = -size * kElegantTop / 2048;
|
||||
metrics->fBottom = -size * kElegantBottom / 2048;
|
||||
metrics->fAscent = -size * kElegantAscent / 2048;
|
||||
@@ -646,9 +649,7 @@ namespace PaintGlue {
|
||||
// ------------------ @CriticalNative ---------------------------
|
||||
|
||||
static void reset(jlong objHandle) {
|
||||
Paint* obj = reinterpret_cast<Paint*>(objHandle);
|
||||
obj->reset();
|
||||
defaultSettingsForAndroid(obj);
|
||||
reinterpret_cast<Paint*>(objHandle)->reset();
|
||||
}
|
||||
|
||||
static void assign(jlong dstPaintHandle, jlong srcPaintHandle) {
|
||||
@@ -657,31 +658,13 @@ namespace PaintGlue {
|
||||
*dst = *src;
|
||||
}
|
||||
|
||||
// Equivalent to the Java Paint's FILTER_BITMAP_FLAG.
|
||||
static const uint32_t sFilterBitmapFlag = 0x02;
|
||||
|
||||
static jint getFlags(jlong paintHandle) {
|
||||
Paint* nativePaint = reinterpret_cast<Paint*>(paintHandle);
|
||||
uint32_t result = nativePaint->getFlags();
|
||||
result &= ~sFilterBitmapFlag; // Filtering no longer stored in this bit. Mask away.
|
||||
if (nativePaint->getFilterQuality() != kNone_SkFilterQuality) {
|
||||
result |= sFilterBitmapFlag;
|
||||
}
|
||||
return static_cast<jint>(result);
|
||||
uint32_t flags = reinterpret_cast<Paint*>(paintHandle)->getJavaFlags();
|
||||
return static_cast<jint>(flags);
|
||||
}
|
||||
|
||||
static void setFlags(jlong paintHandle, jint flags) {
|
||||
Paint* nativePaint = reinterpret_cast<Paint*>(paintHandle);
|
||||
// Instead of modifying 0x02, change the filter level.
|
||||
nativePaint->setFilterQuality(flags & sFilterBitmapFlag
|
||||
? kLow_SkFilterQuality
|
||||
: kNone_SkFilterQuality);
|
||||
// Don't pass through filter flag, which is no longer stored in paint's flags.
|
||||
flags &= ~sFilterBitmapFlag;
|
||||
// Use the existing value for 0x02.
|
||||
const uint32_t existing0x02Flag = nativePaint->getFlags() & sFilterBitmapFlag;
|
||||
flags |= existing0x02Flag;
|
||||
nativePaint->setFlags(flags);
|
||||
reinterpret_cast<Paint*>(paintHandle)->setJavaFlags(flags);
|
||||
}
|
||||
|
||||
static jint getHinting(jlong paintHandle) {
|
||||
@@ -699,37 +682,23 @@ namespace PaintGlue {
|
||||
}
|
||||
|
||||
static void setLinearText(jlong paintHandle, jboolean linearText) {
|
||||
reinterpret_cast<Paint*>(paintHandle)->setLinearText(linearText);
|
||||
reinterpret_cast<Paint*>(paintHandle)->getSkFont().setLinearMetrics(linearText);
|
||||
}
|
||||
|
||||
static void setSubpixelText(jlong paintHandle, jboolean subpixelText) {
|
||||
reinterpret_cast<Paint*>(paintHandle)->setSubpixelText(subpixelText);
|
||||
reinterpret_cast<Paint*>(paintHandle)->getSkFont().setSubpixel(subpixelText);
|
||||
}
|
||||
|
||||
static void setUnderlineText(jlong paintHandle, jboolean underlineText) {
|
||||
Paint* paint = reinterpret_cast<Paint*>(paintHandle);
|
||||
uint32_t flags = paint->getFlags();
|
||||
if (underlineText) {
|
||||
flags |= Paint::kUnderlineText_ReserveFlag;
|
||||
} else {
|
||||
flags &= ~Paint::kUnderlineText_ReserveFlag;
|
||||
}
|
||||
paint->setFlags(flags);
|
||||
reinterpret_cast<Paint*>(paintHandle)->setUnderline(underlineText);
|
||||
}
|
||||
|
||||
static void setStrikeThruText(jlong paintHandle, jboolean strikeThruText) {
|
||||
Paint* paint = reinterpret_cast<Paint*>(paintHandle);
|
||||
uint32_t flags = paint->getFlags();
|
||||
if (strikeThruText) {
|
||||
flags |= Paint::kStrikeThruText_ReserveFlag;
|
||||
} else {
|
||||
flags &= ~Paint::kStrikeThruText_ReserveFlag;
|
||||
}
|
||||
paint->setFlags(flags);
|
||||
reinterpret_cast<Paint*>(paintHandle)->setStrikeThru(strikeThruText);
|
||||
}
|
||||
|
||||
static void setFakeBoldText(jlong paintHandle, jboolean fakeBoldText) {
|
||||
reinterpret_cast<Paint*>(paintHandle)->setFakeBoldText(fakeBoldText);
|
||||
reinterpret_cast<Paint*>(paintHandle)->getSkFont().setEmbolden(fakeBoldText);
|
||||
}
|
||||
|
||||
static void setFilterBitmap(jlong paintHandle, jboolean filterBitmap) {
|
||||
@@ -907,27 +876,29 @@ namespace PaintGlue {
|
||||
}
|
||||
|
||||
static jfloat getTextSize(jlong paintHandle) {
|
||||
return SkScalarToFloat(reinterpret_cast<Paint*>(paintHandle)->getTextSize());
|
||||
return SkScalarToFloat(reinterpret_cast<Paint*>(paintHandle)->getSkFont().getSize());
|
||||
}
|
||||
|
||||
static void setTextSize(jlong paintHandle, jfloat textSize) {
|
||||
reinterpret_cast<Paint*>(paintHandle)->setTextSize(textSize);
|
||||
if (textSize >= 0) {
|
||||
reinterpret_cast<Paint*>(paintHandle)->getSkFont().setSize(textSize);
|
||||
}
|
||||
}
|
||||
|
||||
static jfloat getTextScaleX(jlong paintHandle) {
|
||||
return SkScalarToFloat(reinterpret_cast<Paint*>(paintHandle)->getTextScaleX());
|
||||
return SkScalarToFloat(reinterpret_cast<Paint*>(paintHandle)->getSkFont().getScaleX());
|
||||
}
|
||||
|
||||
static void setTextScaleX(jlong paintHandle, jfloat scaleX) {
|
||||
reinterpret_cast<Paint*>(paintHandle)->setTextScaleX(scaleX);
|
||||
reinterpret_cast<Paint*>(paintHandle)->getSkFont().setScaleX(scaleX);
|
||||
}
|
||||
|
||||
static jfloat getTextSkewX(jlong paintHandle) {
|
||||
return SkScalarToFloat(reinterpret_cast<Paint*>(paintHandle)->getTextSkewX());
|
||||
return SkScalarToFloat(reinterpret_cast<Paint*>(paintHandle)->getSkFont().getSkewX());
|
||||
}
|
||||
|
||||
static void setTextSkewX(jlong paintHandle, jfloat skewX) {
|
||||
reinterpret_cast<Paint*>(paintHandle)->setTextSkewX(skewX);
|
||||
reinterpret_cast<Paint*>(paintHandle)->getSkFont().setSkewX(skewX);
|
||||
}
|
||||
|
||||
static jfloat getLetterSpacing(jlong paintHandle) {
|
||||
@@ -979,7 +950,7 @@ namespace PaintGlue {
|
||||
if (metrics.hasUnderlinePosition(&position)) {
|
||||
return SkScalarToFloat(position);
|
||||
} else {
|
||||
const SkScalar textSize = reinterpret_cast<Paint*>(paintHandle)->getTextSize();
|
||||
const SkScalar textSize = reinterpret_cast<Paint*>(paintHandle)->getSkFont().getSize();
|
||||
return SkScalarToFloat(Paint::kStdUnderline_Top * textSize);
|
||||
}
|
||||
}
|
||||
@@ -991,18 +962,18 @@ namespace PaintGlue {
|
||||
if (metrics.hasUnderlineThickness(&thickness)) {
|
||||
return SkScalarToFloat(thickness);
|
||||
} else {
|
||||
const SkScalar textSize = reinterpret_cast<Paint*>(paintHandle)->getTextSize();
|
||||
const SkScalar textSize = reinterpret_cast<Paint*>(paintHandle)->getSkFont().getSize();
|
||||
return SkScalarToFloat(Paint::kStdUnderline_Thickness * textSize);
|
||||
}
|
||||
}
|
||||
|
||||
static jfloat getStrikeThruPosition(jlong paintHandle) {
|
||||
const SkScalar textSize = reinterpret_cast<Paint*>(paintHandle)->getTextSize();
|
||||
const SkScalar textSize = reinterpret_cast<Paint*>(paintHandle)->getSkFont().getSize();
|
||||
return SkScalarToFloat(Paint::kStdStrikeThru_Top * textSize);
|
||||
}
|
||||
|
||||
static jfloat getStrikeThruThickness(jlong paintHandle) {
|
||||
const SkScalar textSize = reinterpret_cast<Paint*>(paintHandle)->getTextSize();
|
||||
const SkScalar textSize = reinterpret_cast<Paint*>(paintHandle)->getSkFont().getSize();
|
||||
return SkScalarToFloat(Paint::kStdStrikeThru_Thickness * textSize);
|
||||
}
|
||||
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
|
||||
#include "core_jni_helpers.h"
|
||||
|
||||
#include "hwui/Paint.h"
|
||||
#include "hwui/PaintFilter.h"
|
||||
#include "SkPaint.h"
|
||||
|
||||
@@ -29,11 +30,15 @@ namespace android {
|
||||
class PaintFlagsFilter : public PaintFilter {
|
||||
public:
|
||||
PaintFlagsFilter(uint32_t clearFlags, uint32_t setFlags) {
|
||||
fClearFlags = static_cast<uint16_t>(clearFlags & SkPaint::kAllFlags);
|
||||
fSetFlags = static_cast<uint16_t>(setFlags & SkPaint::kAllFlags);
|
||||
fClearFlags = static_cast<uint16_t>(clearFlags);
|
||||
fSetFlags = static_cast<uint16_t>(setFlags);
|
||||
}
|
||||
void filter(SkPaint* paint) override {
|
||||
paint->setFlags((paint->getFlags() & ~fClearFlags) | fSetFlags);
|
||||
uint32_t flags = Paint::GetSkPaintJavaFlags(*paint);
|
||||
Paint::SetSkPaintJavaFlags(paint, (flags & ~fClearFlags) | fSetFlags);
|
||||
}
|
||||
void filterFullPaint(Paint* paint) override {
|
||||
paint->setJavaFlags((paint->getJavaFlags() & ~fClearFlags) | fSetFlags);
|
||||
}
|
||||
|
||||
private:
|
||||
@@ -41,33 +46,6 @@ private:
|
||||
uint16_t fSetFlags;
|
||||
};
|
||||
|
||||
// Custom version of PaintFlagsDrawFilter that also calls setFilterQuality.
|
||||
class CompatPaintFlagsFilter : public PaintFlagsFilter {
|
||||
public:
|
||||
CompatPaintFlagsFilter(uint32_t clearFlags, uint32_t setFlags, SkFilterQuality desiredQuality)
|
||||
: PaintFlagsFilter(clearFlags, setFlags)
|
||||
, fDesiredQuality(desiredQuality) {
|
||||
}
|
||||
|
||||
virtual void filter(SkPaint* paint) {
|
||||
PaintFlagsFilter::filter(paint);
|
||||
paint->setFilterQuality(fDesiredQuality);
|
||||
}
|
||||
|
||||
private:
|
||||
const SkFilterQuality fDesiredQuality;
|
||||
};
|
||||
|
||||
// Returns whether flags contains FILTER_BITMAP_FLAG. If flags does, remove it.
|
||||
static inline bool hadFiltering(jint& flags) {
|
||||
// Equivalent to the Java Paint's FILTER_BITMAP_FLAG.
|
||||
static const uint32_t sFilterBitmapFlag = 0x02;
|
||||
|
||||
const bool result = (flags & sFilterBitmapFlag) != 0;
|
||||
flags &= ~sFilterBitmapFlag;
|
||||
return result;
|
||||
}
|
||||
|
||||
class PaintFilterGlue {
|
||||
public:
|
||||
|
||||
@@ -78,29 +56,11 @@ public:
|
||||
|
||||
static jlong CreatePaintFlagsFilter(JNIEnv* env, jobject clazz,
|
||||
jint clearFlags, jint setFlags) {
|
||||
PaintFilter* filter = nullptr;
|
||||
if (clearFlags | setFlags) {
|
||||
// Mask both groups of flags to remove FILTER_BITMAP_FLAG, which no
|
||||
// longer has a Skia equivalent flag (instead it corresponds to
|
||||
// calling setFilterQuality), and keep track of which group(s), if
|
||||
// any, had the flag set.
|
||||
const bool turnFilteringOn = hadFiltering(setFlags);
|
||||
const bool turnFilteringOff = hadFiltering(clearFlags);
|
||||
|
||||
PaintFilter* filter;
|
||||
if (turnFilteringOn) {
|
||||
// Turning filtering on overrides turning it off.
|
||||
filter = new CompatPaintFlagsFilter(clearFlags, setFlags,
|
||||
kLow_SkFilterQuality);
|
||||
} else if (turnFilteringOff) {
|
||||
filter = new CompatPaintFlagsFilter(clearFlags, setFlags,
|
||||
kNone_SkFilterQuality);
|
||||
} else {
|
||||
filter = new PaintFlagsFilter(clearFlags, setFlags);
|
||||
}
|
||||
return reinterpret_cast<jlong>(filter);
|
||||
} else {
|
||||
return NULL;
|
||||
filter = new PaintFlagsFilter(clearFlags, setFlags);
|
||||
}
|
||||
return reinterpret_cast<jlong>(filter);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -682,12 +682,11 @@ void SkiaCanvas::drawGlyphs(ReadGlyphFunc glyphFunc, int count, const Paint& pai
|
||||
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::drawGlyphs(ReadGlyphFunc glyphFunc, int count, const Paint& pai
|
||||
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;
|
||||
|
||||
@@ -39,34 +39,28 @@ static inline void drawStroke(SkScalar left, SkScalar right, SkScalar top, SkSca
|
||||
}
|
||||
|
||||
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 @@ void Canvas::drawTextDecorations(float x, float y, float length, const Paint& pa
|
||||
}
|
||||
}
|
||||
|
||||
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 @@ public:
|
||||
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 @@ public:
|
||||
private:
|
||||
const minikin::Layout& layout;
|
||||
Canvas* canvas;
|
||||
const SkPaint& paint;
|
||||
const Paint& paint;
|
||||
float x;
|
||||
float y;
|
||||
minikin::MinikinRect& bounds;
|
||||
|
||||
@@ -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 @@ MinikinFontSkia::MinikinFontSkia(sk_sp<SkTypeface> typeface, const void* fontDat
|
||||
, 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 @@ float MinikinFontSkia::GetHorizontalAdvance(uint32_t glyph_id, const minikin::Mi
|
||||
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::GetBounds(minikin::MinikinRect* bounds, uint32_t glyph_id,
|
||||
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 @@ std::shared_ptr<minikin::MinikinFont> MinikinFontSkia::createFontWithVariation(
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
#include <cutils/compiler.h>
|
||||
#include <minikin/MinikinFont.h>
|
||||
|
||||
class SkPaint;
|
||||
class SkFont;
|
||||
class SkTypeface;
|
||||
|
||||
namespace android {
|
||||
@@ -54,12 +54,12 @@ public:
|
||||
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;
|
||||
|
||||
@@ -30,16 +30,17 @@ namespace android {
|
||||
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;
|
||||
|
||||
@@ -63,27 +63,29 @@ public:
|
||||
// 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);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
|
||||
#include <cutils/compiler.h>
|
||||
|
||||
#include <SkFont.h>
|
||||
#include <SkPaint.h>
|
||||
#include <string>
|
||||
|
||||
@@ -46,7 +47,6 @@ public:
|
||||
|
||||
Paint();
|
||||
Paint(const Paint& paint);
|
||||
Paint(const SkPaint& paint); // NOLINT(google-explicit-constructor)
|
||||
~Paint();
|
||||
|
||||
Paint& operator=(const Paint& other);
|
||||
@@ -54,6 +54,17 @@ public:
|
||||
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 @@ public:
|
||||
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 @@ private:
|
||||
// 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
|
||||
|
||||
@@ -12,6 +12,7 @@ public:
|
||||
* The implementation may modify the paint as they wish.
|
||||
*/
|
||||
virtual void filter(SkPaint*) = 0;
|
||||
virtual void filterFullPaint(Paint*) = 0;
|
||||
};
|
||||
|
||||
} // namespace android
|
||||
|
||||
@@ -24,10 +24,16 @@ Paint::Paint()
|
||||
, 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 @@ Paint::Paint(const Paint& paint)
|
||||
, 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 @@ Paint& Paint::operator=(const Paint& other) {
|
||||
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
|
||||
|
||||
@@ -78,24 +78,21 @@ sp<DeferredLayerUpdater> TestUtils::createTextureLayerUpdater(
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
@@ -278,10 +278,10 @@ public:
|
||||
|
||||
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);
|
||||
|
||||
@@ -51,7 +51,7 @@ public:
|
||||
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));
|
||||
}
|
||||
|
||||
|
||||
@@ -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 @@ class ListOfFadedTextAnimation : public TestListViewSceneBase {
|
||||
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));
|
||||
|
||||
|
||||
@@ -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 @@ class ListViewAnimation : public TestListViewSceneBase {
|
||||
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));
|
||||
|
||||
|
||||
@@ -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 @@ public:
|
||||
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);
|
||||
|
||||
@@ -41,9 +41,9 @@ public:
|
||||
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) {
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
*/
|
||||
|
||||
#include "TestSceneBase.h"
|
||||
#include "hwui/Paint.h"
|
||||
|
||||
class TextAnimation;
|
||||
|
||||
@@ -28,9 +29,9 @@ public:
|
||||
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++) {
|
||||
|
||||
@@ -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 @@ private:
|
||||
[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);
|
||||
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user