More efficient text rendering on path
Change-Id: I004c15473b527df0f296c54a6a3e9b29505fd9b9
This commit is contained in:
@@ -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);
|
||||
addOp(alloc().create_trivial<TextOnPathOp>(
|
||||
*(mState.currentSnapshot()->transform),
|
||||
getRecordedClip(),
|
||||
refPaint(&paint), glyphs, glyphCount, refPath(&path), hOffset, vOffset));
|
||||
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), tempGlyphs, 1, refPath(&path), x, y));
|
||||
}
|
||||
}
|
||||
|
||||
void RecordingCanvas::drawBitmap(const SkBitmap* bitmap, const SkPaint* paint) {
|
||||
|
||||
@@ -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() {
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -81,6 +81,8 @@ protected:
|
||||
SkScalar constY, const SkPaint&) override;
|
||||
virtual void onDrawTextOnPath(const void* text, size_t byteLength, const SkPath& path,
|
||||
const SkMatrix* matrix, const SkPaint&) override;
|
||||
virtual void onDrawTextRSXform(const void* text, size_t byteLength, const SkRSXform[],
|
||||
const SkRect* cullRect, const SkPaint& paint);
|
||||
virtual void onDrawTextBlob(const SkTextBlob* blob, SkScalar x, SkScalar y,
|
||||
const SkPaint& paint) override;
|
||||
|
||||
|
||||
@@ -185,13 +185,7 @@ public:
|
||||
}
|
||||
|
||||
void operator()(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);
|
||||
canvas->drawGlyphsOnPath(glyphs, 1, path, x, y, paint);
|
||||
}
|
||||
canvas->drawLayoutOnPath(layout, hOffset, vOffset, paint, path, start, end);
|
||||
}
|
||||
private:
|
||||
const minikin::Layout& layout;
|
||||
|
||||
@@ -26,6 +26,10 @@
|
||||
#include <SkCanvas.h>
|
||||
#include <SkMatrix.h>
|
||||
|
||||
namespace minikin {
|
||||
class Layout;
|
||||
}
|
||||
|
||||
namespace android {
|
||||
|
||||
namespace uirenderer {
|
||||
@@ -242,10 +246,8 @@ protected:
|
||||
const SkPaint& paint, float x, float y,
|
||||
float boundsLeft, float boundsTop, float boundsRight, float boundsBottom,
|
||||
float totalAdvance) = 0;
|
||||
/** drawTextOnPath: count is of glyphs */
|
||||
virtual void drawGlyphsOnPath(const uint16_t* glyphs, int count, const SkPath& path,
|
||||
float hOffset, float vOffset, const SkPaint& paint) = 0;
|
||||
|
||||
virtual void drawLayoutOnPath(const minikin::Layout& layout, float hOffset, float vOffset,
|
||||
const SkPaint& paint, const SkPath& path, size_t start, size_t end) = 0;
|
||||
friend class DrawTextFunctor;
|
||||
friend class DrawTextOnPathFunctor;
|
||||
friend class uirenderer::SkiaCanvasProxy;
|
||||
|
||||
Reference in New Issue
Block a user