aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/core
diff options
context:
space:
mode:
authorGravatar Herb Derby <herb@google.com>2018-07-18 13:41:15 -0400
committerGravatar Skia Commit-Bot <skia-commit-bot@chromium.org>2018-07-18 20:54:02 +0000
commit2eacff02f1436e282468670373f5867ab2b27916 (patch)
treeb30485e7fe8b0e11c88fee44a94e2ba8577c56d0 /src/core
parent8364706c02c6ad33637132ff126a48011e4d8b13 (diff)
Redo drawTextRSXForm for glyph runs
Change-Id: Iec9ad6a2c91b16c4e25150902b433fc7aae68a33 Reviewed-on: https://skia-review.googlesource.com/142171 Reviewed-by: Mike Reed <reed@google.com> Commit-Queue: Herb Derby <herb@google.com>
Diffstat (limited to 'src/core')
-rw-r--r--src/core/SkCanvas.cpp9
-rw-r--r--src/core/SkDevice.cpp59
-rw-r--r--src/core/SkDevice.h5
-rw-r--r--src/core/SkGlyphRun.cpp55
-rw-r--r--src/core/SkGlyphRun.h16
5 files changed, 95 insertions, 49 deletions
diff --git a/src/core/SkCanvas.cpp b/src/core/SkCanvas.cpp
index cb98b09b37..8fc431864d 100644
--- a/src/core/SkCanvas.cpp
+++ b/src/core/SkCanvas.cpp
@@ -2478,7 +2478,7 @@ void SkCanvas::onDrawTextOnPath(const void* text, size_t byteLength, const SkPat
LOOPER_END
}
-void SkCanvas::onDrawTextRSXform(const void* text, size_t byteLength, const SkRSXform xform[],
+void SkCanvas::onDrawTextRSXform(const void* text, size_t len, const SkRSXform xform[],
const SkRect* cullRect, const SkPaint& paint) {
if (cullRect && this->quickReject(*cullRect)) {
return;
@@ -2487,7 +2487,12 @@ void SkCanvas::onDrawTextRSXform(const void* text, size_t byteLength, const SkRS
LOOPER_BEGIN(paint, nullptr)
while (iter.next()) {
- iter.fDevice->drawTextRSXform(text, byteLength, xform, looper.paint());
+ fScratchGlyphRunBuilder->drawTextAtOrigin(paint, text, len);
+ auto list = fScratchGlyphRunBuilder->useGlyphRunList();
+ if (!list->empty()) {
+ auto glyphRun = (*list)[0];
+ iter.fDevice->drawGlyphRunRSXform(&glyphRun, xform);
+ }
}
LOOPER_END
diff --git a/src/core/SkDevice.cpp b/src/core/SkDevice.cpp
index 2296d359da..60f8cd861f 100644
--- a/src/core/SkDevice.cpp
+++ b/src/core/SkDevice.cpp
@@ -476,55 +476,34 @@ void SkBaseDevice::drawTextOnPath(const void* text, size_t byteLength,
#include "SkUtils.h"
-void SkBaseDevice::drawTextRSXform(const void* text, size_t len,
- const SkRSXform xform[], const SkPaint& paint) {
- SkPaint::TextEncoding textEncoding = paint.getTextEncoding();
- const char* end = (const char*)text + len;
- SkPaint localPaint(paint);
- SkShader* shader = paint.getShader();
- SkScalar pos[2] = {0.0f, 0.0f};
- SkPoint origin = SkPoint::Make(0, 0);
-
- SkMatrix localM, currM;
- const void* stopText = (const char*)text + len;
- while ((const char*)text < (const char*)stopText) {
- localM.setRSXform(*xform++);
- currM.setConcat(this->ctm(), localM);
- SkAutoDeviceCTMRestore adc(this, currM);
+void SkBaseDevice::drawGlyphRunRSXform(SkGlyphRun* run, const SkRSXform* xform) {
+ const SkMatrix originalCTM = this->ctm();
+ sk_sp<SkShader> shader = sk_ref_sp(run->mutablePaint()->getShader());
+ auto perGlyph = [this, &xform, &originalCTM, shader] (
+ SkGlyphRun* glyphRun, SkPaint* runPaint) {
+ SkMatrix ctm;
+ ctm.setRSXform(*xform++);
// We want to rotate each glyph by the rsxform, but we don't want to rotate "space"
// (i.e. the shader that cares about the ctm) so we have to undo our little ctm trick
// with a localmatrixshader so that the shader draws as if there was no change to the ctm.
if (shader) {
SkMatrix inverse;
- if (localM.invert(&inverse)) {
- localPaint.setShader(shader->makeWithLocalMatrix(inverse));
+ if (ctm.invert(&inverse)) {
+ runPaint->setShader(shader->makeWithLocalMatrix(inverse));
} else {
- localPaint.setShader(nullptr); // can't handle this xform
+ runPaint->setShader(nullptr); // can't handle this xform
}
}
- int subLen = 0;
- switch (textEncoding) {
- case SkPaint::kUTF8_TextEncoding:
- subLen = SkUTF8_CountUTF8Bytes((const char*)text);
- break;
- case SkPaint::kUTF16_TextEncoding:
- {
- const uint16_t* ptr = (const uint16_t*)text;
- (void)SkUTF16_NextUnichar(&ptr, (const uint16_t*)end);
- subLen = SkToInt((const char*)ptr - (const char*)text);
- };
- break;
- case SkPaint::kUTF32_TextEncoding:
- subLen = 4;
- break;
- case SkPaint::kGlyphID_TextEncoding:
- subLen = 2;
- break;
- }
- this->drawPosText(text, subLen, pos, 2, origin, localPaint);
- text = (const char*)text + subLen;
- }
+
+ ctm.setConcat(originalCTM, ctm);
+ this->setCTM(ctm);
+ SkGlyphRunList glyphRunList{glyphRun};
+ this->drawGlyphRunList(&glyphRunList);
+ };
+ run->eachGlyphToGlyphRun(perGlyph);
+ run->mutablePaint()->setShader(shader);
+ this->setCTM(originalCTM);
}
//////////////////////////////////////////////////////////////////////////////////////////
diff --git a/src/core/SkDevice.h b/src/core/SkDevice.h
index 345b90548b..bd327a65c3 100644
--- a/src/core/SkDevice.h
+++ b/src/core/SkDevice.h
@@ -16,8 +16,8 @@
class SkBitmap;
struct SkDrawShadowRec;
+class SkGlyphRun;
class SkGlyphRunList;
-class SkGlyphRunBuilder;
class SkImageFilterCache;
struct SkIRect;
class SkMatrix;
@@ -242,8 +242,7 @@ protected:
virtual void drawTextOnPath(const void* text, size_t len, const SkPath&,
const SkMatrix*, const SkPaint&);
- virtual void drawTextRSXform(const void* text, size_t len, const SkRSXform[],
- const SkPaint&);
+ void drawGlyphRunRSXform(SkGlyphRun* run, const SkRSXform* xform);
virtual void drawSpecial(SkSpecialImage*, int x, int y, const SkPaint&,
SkImage* clipImage, const SkMatrix& clipMatrix);
diff --git a/src/core/SkGlyphRun.cpp b/src/core/SkGlyphRun.cpp
index 3548dfa203..e587dc55c6 100644
--- a/src/core/SkGlyphRun.cpp
+++ b/src/core/SkGlyphRun.cpp
@@ -51,6 +51,31 @@ SkGlyphRun::SkGlyphRun(SkPaint&& runPaint,
, fClusters{clusters}
, fRunPaint{std::move(runPaint)} {}
+
+void SkGlyphRun::eachGlyphToGlyphRun(SkGlyphRun::PerGlyph perGlyph) {
+ SkPaint paint{fRunPaint};
+ SkPoint point;
+ SkGlyphID glyphID;
+ SkGlyphRun run{
+ std::move(paint),
+ SkSpan<const uint16_t>{}, // No dense indices for now.
+ SkSpan<const SkPoint>{&point, 1},
+ SkSpan<const SkGlyphID>{&glyphID, 1},
+ SkSpan<const SkGlyphID>{},
+ SkSpan<const char>{},
+ SkSpan<const uint32_t>{}
+ };
+
+ auto runSize = fTemporaryShuntGlyphIDs.size();
+ auto runPaint = run.mutablePaint();
+ for (size_t i = 0; i < runSize; i++) {
+ glyphID = fTemporaryShuntGlyphIDs[i];
+ point = fPositions[i];
+ perGlyph(&run, runPaint);
+ }
+
+}
+
void SkGlyphRun::temporaryShuntToDrawPosText(SkBaseDevice* device, SkPoint origin) {
auto pos = (const SkScalar*) this->positions().data();
@@ -74,6 +99,7 @@ void SkGlyphRun::filloutGlyphsAndPositions(SkGlyphID* glyphIDs, SkPoint* positio
}
// -- SkGlyphRunList -------------------------------------------------------------------------------
+SkGlyphRunList::SkGlyphRunList() = default;
SkGlyphRunList::SkGlyphRunList(
const SkPaint& paint,
const SkTextBlob* blob,
@@ -84,6 +110,12 @@ SkGlyphRunList::SkGlyphRunList(
, fOrigin{origin}
, fGlyphRuns{glyphRunList} { }
+SkGlyphRunList::SkGlyphRunList(SkGlyphRun* glyphRun)
+ : fOriginalPaint{nullptr}
+ , fOriginalTextBlob{nullptr}
+ , fOrigin{SkPoint::Make(0, 0)}
+ , fGlyphRuns{SkSpan<SkGlyphRun>{glyphRun, 1}} {}
+
uint64_t SkGlyphRunList::uniqueID() const {
return fOriginalTextBlob != nullptr ? fOriginalTextBlob->uniqueID()
: SK_InvalidUniqueID;
@@ -166,6 +198,29 @@ SkSpan<const SkGlyphID> SkGlyphIDSet::uniquifyGlyphIDs(
}
// -- SkGlyphRunBuilder ----------------------------------------------------------------------------
+void SkGlyphRunBuilder::drawTextAtOrigin(
+ const SkPaint& paint, const void* bytes, size_t byteLength) {
+ auto glyphIDs = textToGlyphIDs(paint, bytes, byteLength);
+ if (!glyphIDs.empty()) {
+ this->initialize(glyphIDs.size());
+ }
+
+ auto positions = SkSpan<const SkPoint>{fPositions, glyphIDs.size()};
+
+ // Every glyph is at the origin.
+ sk_bzero((void *)positions.data(), positions.size_bytes());
+
+ this->makeGlyphRun(
+ paint,
+ glyphIDs,
+ positions,
+ SkSpan<const uint16_t>{}, // no dense indices for now.,
+ SkSpan<const SkGlyphID>{},
+ SkSpan<const char>{},
+ SkSpan<const uint32_t>{});
+ this->makeGlyphRunList(paint, nullptr, SkPoint::Make(0, 0));
+}
+
void SkGlyphRunBuilder::drawText(
const SkPaint& paint, const void* bytes, size_t byteLength, SkPoint origin) {
auto glyphIDs = textToGlyphIDs(paint, bytes, byteLength);
diff --git a/src/core/SkGlyphRun.h b/src/core/SkGlyphRun.h
index 001c3c4548..6de4cdc40f 100644
--- a/src/core/SkGlyphRun.h
+++ b/src/core/SkGlyphRun.h
@@ -19,6 +19,7 @@
#include "SkTypes.h"
class SkBaseDevice;
+class SkGlyphRunList;
template <typename T>
class SkSpan {
@@ -55,6 +56,10 @@ public:
SkSpan<const char> text,
SkSpan<const uint32_t> clusters);
+ // A function that turns an SkGlyphRun into an SkGlyphRun for each glyph.
+ using PerGlyph = std::function<void (SkGlyphRun*, SkPaint*)>;
+ void eachGlyphToGlyphRun(PerGlyph perGlyph);
+
// The temporaryShunt calls are to allow inter-operating with existing code while glyph runs
// are developed.
void temporaryShuntToDrawPosText(SkBaseDevice* device, SkPoint origin);
@@ -65,6 +70,7 @@ public:
size_t runSize() const { return fTemporaryShuntGlyphIDs.size(); }
SkSpan<const SkPoint> positions() const { return fPositions; }
const SkPaint& paint() const { return fRunPaint; }
+ SkPaint* mutablePaint() { return &fRunPaint; }
private:
//
@@ -80,11 +86,11 @@ private:
// Original clusters from SkTextBlob if present. Will be empty if not present.
const SkSpan<const uint32_t> fClusters;
// Paint for this run modified to have glyph encoding and left alignment.
- const SkPaint fRunPaint;
+ SkPaint fRunPaint;
};
class SkGlyphRunList {
- const SkPaint* fOriginalPaint{nullptr};
+ const SkPaint* fOriginalPaint{nullptr}; // This should be deleted soon.
// The text blob is needed to hookup the call back that the SkTextBlob destructor calls. It
// should be used for nothing else
const SkTextBlob* fOriginalTextBlob{nullptr};
@@ -92,7 +98,7 @@ class SkGlyphRunList {
SkSpan<SkGlyphRun> fGlyphRuns;
public:
- SkGlyphRunList() = default;
+ SkGlyphRunList();
// Blob maybe null.
SkGlyphRunList(
const SkPaint& paint,
@@ -100,6 +106,8 @@ public:
SkPoint origin,
SkSpan<SkGlyphRun> glyphRunList);
+ SkGlyphRunList(SkGlyphRun* glyphRun);
+
uint64_t uniqueID() const;
bool anyRunsLCD() const;
void temporaryShuntBlobNotifyAddedToCache(uint32_t cacheID) const;
@@ -143,6 +151,7 @@ private:
class SkGlyphRunBuilder {
public:
+ void drawTextAtOrigin(const SkPaint& paint, const void* bytes, size_t byteLength);
void drawText(
const SkPaint& paint, const void* bytes, size_t byteLength, SkPoint origin);
void drawPosTextH(
@@ -152,7 +161,6 @@ public:
const SkPaint& paint, const void* bytes, size_t byteLength, const SkPoint* pos);
void drawTextBlob(const SkPaint& paint, const SkTextBlob& blob, SkPoint origin);
- SkGlyphRun* useGlyphRun();
SkGlyphRunList* useGlyphRunList();
private: