Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit d8cf9da7 authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Store SkFont in android::Paint"

parents 82296cfe f6d86acb
Loading
Loading
Loading
Loading
+49 −78
Original line number Diff line number Diff line
@@ -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);
    }

+11 −51
Original line number Diff line number Diff line
@@ -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;
        }
    }
};

+6 −8
Original line number Diff line number Diff line
@@ -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;
+16 −22
Original line number Diff line number Diff line
@@ -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;
+43 −35

File changed.

Preview size limit exceeded, changes collapsed.

Loading