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

Commit afc22149 authored by Yuqian Li's avatar Yuqian Li
Browse files

More efficient text rendering on path

Change-Id: I004c15473b527df0f296c54a6a3e9b29505fd9b9
parent 0979352b
Loading
Loading
Loading
Loading
+15 −8
Original line number Diff line number Diff line
@@ -20,6 +20,7 @@
#include "RecordedOp.h"
#include "RenderNode.h"
#include "VectorDrawable.h"
#include "hwui/MinikinUtils.h"

namespace android {
namespace uirenderer {
@@ -541,14 +542,20 @@ void RecordingCanvas::drawGlyphs(const uint16_t* glyphs, const float* positions,
    drawTextDecorations(x, y, totalAdvance, paint);
}

void RecordingCanvas::drawGlyphsOnPath(const uint16_t* glyphs, int glyphCount, const SkPath& path,
            float hOffset, float vOffset, const SkPaint& paint) {
    if (!glyphs || glyphCount <= 0 || PaintUtils::paintWillNotDrawText(paint)) return;
    glyphs = refBuffer<glyph_t>(glyphs, glyphCount);
void RecordingCanvas::drawLayoutOnPath(const minikin::Layout& layout, float hOffset, float vOffset,
        const SkPaint& paint, const SkPath& path, size_t start, size_t end) {
    uint16_t glyphs[1];
    for (size_t i = start; i < end; i++) {
        glyphs[0] = layout.getGlyphId(i);
        float x = hOffset + layout.getX(i);
        float y = vOffset + layout.getY(i);
        if (PaintUtils::paintWillNotDrawText(paint)) return;
        const uint16_t* tempGlyphs = refBuffer<glyph_t>(glyphs, 1);
        addOp(alloc().create_trivial<TextOnPathOp>(
                *(mState.currentSnapshot()->transform),
                getRecordedClip(),
            refPaint(&paint), glyphs, glyphCount, refPath(&path), hOffset, vOffset));
                refPaint(&paint), tempGlyphs, 1, refPath(&path), x, y));
    }
}

void RecordingCanvas::drawBitmap(const SkBitmap* bitmap, const SkPaint* paint) {
+2 −2
Original line number Diff line number Diff line
@@ -196,8 +196,8 @@ protected:
            const SkPaint& paint, float x, float y,
            float boundsLeft, float boundsTop, float boundsRight, float boundsBottom,
            float totalAdvance) override;
    virtual void drawGlyphsOnPath(const uint16_t* glyphs, int count, const SkPath& path,
            float hOffset, float vOffset, const SkPaint& paint) override;
    virtual void drawLayoutOnPath(const minikin::Layout& layout, float hOffset, float vOffset,
            const SkPaint& paint, const SkPath& path, size_t start, size_t end) override;

private:
    const ClipBase* getRecordedClip() {
+28 −3
Original line number Diff line number Diff line
@@ -18,6 +18,7 @@

#include "CanvasProperty.h"
#include "VectorDrawable.h"
#include "hwui/MinikinUtils.h"

#include <SkDrawable.h>
#include <SkDevice.h>
@@ -25,6 +26,7 @@
#include <SkDrawFilter.h>
#include <SkGraphics.h>
#include <SkImage.h>
#include <SkRSXform.h>
#include <SkShader.h>
#include <SkTemplates.h>

@@ -624,9 +626,32 @@ void SkiaCanvas::drawGlyphs(const uint16_t* text, const float* positions, int co
    drawTextDecorations(x, y, totalAdvance, paint);
}

void SkiaCanvas::drawGlyphsOnPath(const uint16_t* glyphs, int count, const SkPath& path,
        float hOffset, float vOffset, const SkPaint& paint) {
    mCanvas->drawTextOnPathHV(glyphs, count << 1, path, hOffset, vOffset, paint);
void SkiaCanvas::drawLayoutOnPath(const minikin::Layout& layout, float hOffset, float vOffset,
        const SkPaint& paint, const SkPath& path, size_t start, size_t end) {
    const int N = end - start;
    SkAutoSMalloc<1024> storage(N * (sizeof(uint16_t) + sizeof(SkRSXform)));
    SkRSXform* xform = (SkRSXform*)storage.get();
    uint16_t* glyphs = (uint16_t*)(xform + N);
    SkPathMeasure meas(path, false);

    for (size_t i = start; i < end; i++) {
        glyphs[i - start] = layout.getGlyphId(i);
        float x = hOffset + layout.getX(i);
        float y = vOffset + layout.getY(i);

        SkPoint pos;
        SkVector tan;
        if (!meas.getPosTan(x, &pos, &tan)) {
            pos.set(x, y);
            tan.set(1, 0);
        }
        xform[i - start].fSCos = tan.x();
        xform[i - start].fSSin = tan.y();
        xform[i - start].fTx   = pos.x() - tan.y() * y;
        xform[i - start].fTy   = pos.y() + tan.x() * y;
    }

    this->asSkCanvas()->drawTextRSXform(glyphs, sizeof(uint16_t) * N, xform, nullptr, paint);
}

// ----------------------------------------------------------------------------
+2 −2
Original line number Diff line number Diff line
@@ -161,8 +161,8 @@ protected:
            const SkPaint& paint, float x, float y,
            float boundsLeft, float boundsTop, float boundsRight, float boundsBottom,
            float totalAdvance) override;
    virtual void drawGlyphsOnPath(const uint16_t* glyphs, int count, const SkPath& path,
            float hOffset, float vOffset, const SkPaint& paint) override;
    virtual void drawLayoutOnPath(const minikin::Layout& layout, float hOffset, float vOffset,
            const SkPaint& paint, const SkPath& path, size_t start, size_t end) override;

private:
    struct SaveRec {
+19 −3
Original line number Diff line number Diff line
@@ -23,6 +23,7 @@
#include <SkPixelRef.h>
#include <SkRect.h>
#include <SkRRect.h>
#include <SkRSXform.h>
#include <SkSurface.h>

#include <memory>
@@ -348,11 +349,26 @@ void SkiaCanvasProxy::onDrawPosTextH(const void* text, size_t byteLength, const

void SkiaCanvasProxy::onDrawTextOnPath(const void* text, size_t byteLength, const SkPath& path,
        const SkMatrix* matrix, const SkPaint& origPaint) {
    // convert to glyphIDs if necessary
    GlyphIDConverter glyphs(text, byteLength, origPaint);
    mCanvas->drawGlyphsOnPath(glyphs.glyphIDs, glyphs.count, path, 0, 0, glyphs.paint);
    SkDEBUGFAIL("SkiaCanvasProxy::onDrawTextOnPath is not supported");
}

void SkiaCanvasProxy::onDrawTextRSXform(const void* text, size_t byteLength,
        const SkRSXform xform[], const SkRect* cullRect, const SkPaint& paint) {
    GlyphIDConverter glyphs(text, byteLength, paint); // Just get count
    SkMatrix localM, currM, origM;
    mCanvas->getMatrix(&currM);
    origM = currM;
    for (int i = 0; i < glyphs.count; i++) {
        localM.setRSXform(*xform++);
        currM.setConcat(origM, localM);
        mCanvas->setMatrix(currM);
        this->onDrawText((char*)text + (byteLength / glyphs.count * i),
                         byteLength / glyphs.count, 0, 0, paint);
    }
    mCanvas->setMatrix(origM);
}


void SkiaCanvasProxy::onDrawTextBlob(const SkTextBlob* blob, SkScalar x, SkScalar y,
        const SkPaint& paint) {
    SkDEBUGFAIL("SkiaCanvasProxy::onDrawTextBlob is not supported");
Loading