aboutsummaryrefslogtreecommitdiffhomepage
path: root/src
diff options
context:
space:
mode:
authorGravatar Herb Derby <herb@google.com>2018-07-20 11:48:38 -0400
committerGravatar Skia Commit-Bot <skia-commit-bot@chromium.org>2018-07-24 14:53:25 +0000
commit81ecdbb7ff36afef9091c1b524baafe67381e70d (patch)
treec9d2a2ace6fecc88bf85e1377c2eeb8d8d007a5a /src
parentab98509717e1d20b8171a631d2923f47ce26fc0e (diff)
Clean up bitmap path
Change-Id: If149194fd86f14bea289ad68262ea99cbbc398b6 Reviewed-on: https://skia-review.googlesource.com/142817 Reviewed-by: Ben Wagner <bungeman@google.com> Commit-Queue: Herb Derby <herb@google.com>
Diffstat (limited to 'src')
-rw-r--r--src/core/SkBitmapDevice.cpp5
-rw-r--r--src/core/SkBitmapDevice.h1
-rw-r--r--src/core/SkDraw.cpp134
-rw-r--r--src/core/SkDraw.h12
-rw-r--r--src/core/SkGlyphRun.cpp50
-rw-r--r--src/core/SkGlyphRun.h26
6 files changed, 207 insertions, 21 deletions
diff --git a/src/core/SkBitmapDevice.cpp b/src/core/SkBitmapDevice.cpp
index cb169dca87..94a4ddcd0d 100644
--- a/src/core/SkBitmapDevice.cpp
+++ b/src/core/SkBitmapDevice.cpp
@@ -572,7 +572,7 @@ void SkBitmapDevice::drawPosText(const void* text, size_t len, const SkScalar xp
}
void SkBitmapDevice::drawGlyphRunList(SkGlyphRunList* glyphRunList) {
-#ifdef SK_SUPPORT_LEGACY_TEXT_BLOB
+#if defined(SK_SUPPORT_LEGACY_TEXT_BLOB)
auto blob = glyphRunList->blob();
if (blob == nullptr) {
@@ -583,7 +583,8 @@ void SkBitmapDevice::drawGlyphRunList(SkGlyphRunList* glyphRunList) {
this->drawTextBlob(blob, origin.x(), origin.y(), paint);
}
#else
- glyphRunList->temporaryShuntToDrawPosText(this, glyphRunList->origin());
+ SkBitmapDeviceFilteredSurfaceProps props(fBitmap, glyphRunList->paint(), fSurfaceProps);
+ LOOP_TILER( drawGlyphRunList(glyphRunList, &props()), nullptr )
#endif
}
diff --git a/src/core/SkBitmapDevice.h b/src/core/SkBitmapDevice.h
index 890f7e1934..379d42ddd1 100644
--- a/src/core/SkBitmapDevice.h
+++ b/src/core/SkBitmapDevice.h
@@ -112,7 +112,6 @@ protected:
*/
void drawPosText(const void* text, size_t len, const SkScalar pos[],
int scalarsPerPos, const SkPoint& offset, const SkPaint& paint) override;
-
void drawGlyphRunList(SkGlyphRunList* glyphRunList) override;
void drawVertices(const SkVertices*, const SkMatrix* bones, int boneCount, SkBlendMode,
const SkPaint& paint) override;
diff --git a/src/core/SkDraw.cpp b/src/core/SkDraw.cpp
index ae1a873f2b..4c9dddf1f5 100644
--- a/src/core/SkDraw.cpp
+++ b/src/core/SkDraw.cpp
@@ -1598,6 +1598,140 @@ void SkDraw::drawPosText(const char text[], size_t byteLength, const SkScalar po
offset, *fMatrix, pos, scalarsPerPosition, cache.get(), drawOneGlyph);
}
+void SkDraw::drawGlyphRunAsPaths(
+ SkGlyphRun* glyphRun, SkPoint origin, const SkSurfaceProps* props) const {
+ // setup our std paint, in hopes of getting hits in the cache
+ const SkPaint& origPaint = glyphRun->paint();
+ SkPaint paint(glyphRun->paint());
+ SkScalar matrixScale = paint.setupForAsPaths();
+
+ SkMatrix matrix;
+ matrix.setScale(matrixScale, matrixScale);
+
+ // Temporarily jam in kFill, so we only ever ask for the raw outline from the cache.
+ paint.setStyle(SkPaint::kFill_Style);
+ paint.setPathEffect(nullptr);
+
+ auto cache = SkStrikeCache::FindOrCreateStrikeExclusive(
+ paint, props, this->scalerContextFlags(), nullptr);
+
+ // Now restore the original settings, so we "draw" with whatever style/stroking.
+ paint.setStyle(origPaint.getStyle());
+ paint.setPathEffect(origPaint.refPathEffect());
+
+ auto eachGlyph = [this, origin, &cache, &matrix, &paint](SkGlyphID glyphID, SkPoint position) {
+ const SkGlyph& glyph = cache->getGlyphIDMetrics(glyphID);
+ if (glyph.fWidth > 0) {
+ const SkPath* path = cache->findPath(glyph);
+ if (path != nullptr) {
+ SkPoint loc = position + origin;
+ matrix[SkMatrix::kMTransX] = loc.fX;
+ matrix[SkMatrix::kMTransY] = loc.fY;
+ this->drawPath(*path, paint, &matrix, false);
+ }
+ }
+ };
+ glyphRun->forEachGlyphAndPosition(eachGlyph);
+}
+
+void SkDraw::drawGlyphRunAsSubpixelMask(
+ SkGlyphCache* cache, SkGlyphRun* glyphRun, SkPoint origin) const {
+
+ SkMatrix matrix = *fMatrix;
+ // Add rounding and origin.
+ SkAxisAlignment axisAlignment = cache->getScalerContext()->computeAxisAlignmentForHText();
+ SkPoint rounding = SkFindAndPlaceGlyph::SubpixelPositionRounding(axisAlignment);
+ matrix.preTranslate(origin.x(), origin.y());
+ matrix.postTranslate(rounding.x(), rounding.y());
+
+ glyphRun->mapPositions(matrix);
+
+ auto paint = glyphRun->paint();
+ // The Blitter Choose needs to be live while using the blitter below.
+ SkAutoBlitterChoose blitterChooser(*this, nullptr, paint);
+ SkAAClipBlitterWrapper wrapper(*fRC, blitterChooser.get());
+ DrawOneGlyph drawOneGlyph(*this, paint, cache, wrapper.getBlitter());
+
+ auto eachGlyph = [cache, &drawOneGlyph, axisAlignment](SkGlyphID glyphID, SkPoint position) {
+ auto subpixelAlignment = [](SkAxisAlignment axisAlignment, SkPoint position) -> SkIPoint {
+
+ if (!SkScalarsAreFinite(position.fX, position.fY)) {
+ return {0, 0};
+ }
+
+ // Only the fractional part of position.fX and position.fY matter, because the result of
+ // this function will just be passed to FixedToSub.
+ switch (axisAlignment) {
+ case kX_SkAxisAlignment:
+ return {SkScalarToFixed(SkScalarFraction(position.fX)), 0};
+ case kY_SkAxisAlignment:
+ return {0, SkScalarToFixed(SkScalarFraction(position.fY))};
+ case kNone_SkAxisAlignment:
+ return {SkScalarToFixed(SkScalarFraction(position.fX)),
+ SkScalarToFixed(SkScalarFraction(position.fY))};
+ }
+ SK_ABORT("Should not get here.");
+ return {0, 0};
+ };
+
+ SkIPoint lookupPosition = subpixelAlignment(axisAlignment, position);
+ const SkGlyph& glyph = cache->getGlyphIDMetrics(
+ glyphID, lookupPosition.x(), lookupPosition.y());
+ if (glyph.fWidth > 0) {
+ drawOneGlyph(glyph, position, SkPoint::Make(0, 0));
+ }
+ };
+ glyphRun->forEachGlyphAndPosition(eachGlyph);
+}
+
+void SkDraw::drawGlyphRunAsFullpixelMask(
+ SkGlyphCache* cache, SkGlyphRun* glyphRun, SkPoint origin) const {
+ SkMatrix matrix = *fMatrix;
+ // Add rounding and origin.
+ matrix.preTranslate(origin.x(), origin.y());
+ matrix.postTranslate(SK_ScalarHalf, SK_ScalarHalf);
+ glyphRun->mapPositions(matrix);
+
+ auto paint = glyphRun->paint();
+ // The Blitter Choose needs to be live while using the blitter below.
+ SkAutoBlitterChoose blitterChooser(*this, nullptr, paint);
+ SkAAClipBlitterWrapper wrapper(*fRC, blitterChooser.get());
+ DrawOneGlyph drawOneGlyph(*this, paint, cache, wrapper.getBlitter());
+
+ auto eachGlyph = [cache, &drawOneGlyph](SkGlyphID glyphID, SkPoint position) {
+ const SkGlyph& glyph = cache->getGlyphIDMetrics(glyphID);
+ if (glyph.fWidth > 0) {
+ drawOneGlyph(glyph, position, SkPoint::Make(0, 0));
+ }
+ };
+ glyphRun->forEachGlyphAndPosition(eachGlyph);
+}
+
+void SkDraw::drawGlyphRunList(SkGlyphRunList* glyphRunList, const SkSurfaceProps* props) const {
+
+ SkDEBUGCODE(this->validate();)
+
+ if (fRC->isEmpty()) {
+ return;
+ }
+
+ SkPoint origin = glyphRunList->origin();
+ for (auto& glyphRun : *glyphRunList) {
+ if (ShouldDrawTextAsPaths(glyphRun.paint(), *fMatrix)) {
+ this->drawGlyphRunAsPaths(&glyphRun, origin, props);
+ } else {
+ auto cache = SkStrikeCache::FindOrCreateStrikeExclusive(
+ glyphRun.paint(), props, this->scalerContextFlags(), fMatrix);
+ if (cache->isSubpixel()) {
+ this->drawGlyphRunAsSubpixelMask(cache.get(), &glyphRun, origin);
+ } else {
+ this->drawGlyphRunAsFullpixelMask(cache.get(), &glyphRun, origin);
+ }
+ }
+ }
+
+}
+
#if defined _WIN32
#pragma warning ( pop )
#endif
diff --git a/src/core/SkDraw.h b/src/core/SkDraw.h
index afd50ea229..deb7451b99 100644
--- a/src/core/SkDraw.h
+++ b/src/core/SkDraw.h
@@ -22,6 +22,8 @@ class SkBitmap;
class SkClipStack;
class SkBaseDevice;
class SkBlitter;
+class SkGlyphRun;
+class SkGlyphRunList;
class SkMatrix;
class SkPath;
class SkRegion;
@@ -65,6 +67,16 @@ public:
void drawPosText(const char text[], size_t byteLength,
const SkScalar pos[], int scalarsPerPosition,
const SkPoint& offset, const SkPaint&, const SkSurfaceProps*) const;
+
+ void drawGlyphRunAsPaths(
+ SkGlyphRun* glyphRun, SkPoint origin, const SkSurfaceProps* props) const;
+
+ void drawGlyphRunAsSubpixelMask(
+ SkGlyphCache* cache, SkGlyphRun* glyphRun, SkPoint origin) const;
+
+ void drawGlyphRunAsFullpixelMask(
+ SkGlyphCache* cache, SkGlyphRun* glyphRun, SkPoint origin) const;
+ void drawGlyphRunList(SkGlyphRunList* glyphRunList, const SkSurfaceProps*) const;
void drawVertices(SkVertices::VertexMode mode, int vertexCount,
const SkPoint vertices[], const SkPoint textures[],
const SkColor colors[], const SkVertices::BoneIndices boneIndices[],
diff --git a/src/core/SkGlyphRun.cpp b/src/core/SkGlyphRun.cpp
index 82dae689f9..cfe63a87b1 100644
--- a/src/core/SkGlyphRun.cpp
+++ b/src/core/SkGlyphRun.cpp
@@ -16,6 +16,7 @@
#include "SkGlyphCache.h"
#include "SkMSAN.h"
#include "SkMakeUnique.h"
+#include "SkMatrix.h"
#include "SkPaint.h"
#include "SkPaintPriv.h"
#include "SkStrikeCache.h"
@@ -38,7 +39,7 @@ static SkTypeface::Encoding convert_encoding(SkPaint::TextEncoding encoding) {
// -- SkGlyphRun -----------------------------------------------------------------------------------
SkGlyphRun::SkGlyphRun(SkPaint&& runPaint,
SkSpan<const uint16_t> denseIndices,
- SkSpan<const SkPoint> positions,
+ SkSpan<SkPoint> positions,
SkSpan<const SkGlyphID> glyphIDs,
SkSpan<const SkGlyphID> uniqueGlyphIDs,
SkSpan<const char> text,
@@ -59,7 +60,7 @@ void SkGlyphRun::eachGlyphToGlyphRun(SkGlyphRun::PerGlyph perGlyph) {
SkGlyphRun run{
std::move(paint),
SkSpan<const uint16_t>{}, // No dense indices for now.
- SkSpan<const SkPoint>{&point, 1},
+ SkSpan<SkPoint>{&point, 1},
SkSpan<const SkGlyphID>{&glyphID, 1},
SkSpan<const SkGlyphID>{},
SkSpan<const char>{},
@@ -76,6 +77,11 @@ void SkGlyphRun::eachGlyphToGlyphRun(SkGlyphRun::PerGlyph perGlyph) {
}
+void SkGlyphRun::mapPositions(const SkMatrix& matrix) {
+ matrix.mapPoints(fPositions.data(), fPositions.data(), (int)fPositions.size());
+}
+
+
void SkGlyphRun::temporaryShuntToDrawPosText(SkBaseDevice* device, SkPoint origin) {
auto pos = (const SkScalar*) this->positions().data();
@@ -208,7 +214,7 @@ void SkGlyphRunBuilder::drawTextAtOrigin(
this->initialize(glyphIDs.size());
}
- auto positions = SkSpan<const SkPoint>{fPositions, glyphIDs.size()};
+ auto positions = SkSpan<SkPoint>{fPositions, glyphIDs.size()};
// Every glyph is at the origin.
sk_bzero((void *)positions.data(), positions.size_bytes());
@@ -254,7 +260,8 @@ void SkGlyphRunBuilder::drawPosText(const SkPaint& paint, const void* bytes,
auto glyphIDs = textToGlyphIDs(paint, bytes, byteLength);
if (!glyphIDs.empty()) {
this->initialize(glyphIDs.size());
- this->simplifyDrawPosText(paint, glyphIDs, pos, fUniqueGlyphIDIndices, fUniqueGlyphIDs);
+ this->simplifyDrawPosText(paint, glyphIDs, pos,
+ fUniqueGlyphIDIndices, fUniqueGlyphIDs, fPositions);
}
this->makeGlyphRunList(paint, nullptr, SkPoint::Make(0, 0));
@@ -310,7 +317,7 @@ void SkGlyphRunBuilder::drawTextBlob(const SkPaint& paint, const SkTextBlob& blo
case SkTextBlob::kFull_Positioning:
uniqueGlyphIDsSize = this->simplifyDrawPosText(
runPaint, glyphIDs, (const SkPoint*)it.pos(),
- currentDenseIndices, currentUniqueGlyphIDs,
+ currentDenseIndices, currentUniqueGlyphIDs, currentPositions,
text, clusters);
break;
default:
@@ -384,7 +391,7 @@ SkSpan<const SkGlyphID> SkGlyphRunBuilder::addDenseAndUnique(
void SkGlyphRunBuilder::makeGlyphRun(
const SkPaint& runPaint,
SkSpan<const SkGlyphID> glyphIDs,
- SkSpan<const SkPoint> positions,
+ SkSpan<SkPoint> positions,
SkSpan<const uint16_t> uniqueGlyphIDIndices,
SkSpan<const SkGlyphID> uniqueGlyphIDs,
SkSpan<const char> text,
@@ -454,7 +461,7 @@ size_t SkGlyphRunBuilder::simplifyDrawText(
this->makeGlyphRun(
paint,
glyphIDs,
- SkSpan<const SkPoint>{positions, runSize},
+ SkSpan<SkPoint>{positions, runSize},
SkSpan<const uint16_t>{uniqueGlyphIDIndicesBuffer, runSize},
unqiueGlyphIDs,
text,
@@ -469,21 +476,35 @@ size_t SkGlyphRunBuilder::simplifyDrawPosTextH(
const SkScalar* xpos, SkScalar constY,
uint16_t* uniqueGlyphIDIndicesBuffer, SkGlyphID* uniqueGlyphIDsBuffer, SkPoint* positions,
SkSpan<const char> text, SkSpan<const uint32_t> clusters) {
+ auto runSize = glyphIDs.size();
auto posCursor = positions;
for (auto x : SkSpan<const SkScalar>{xpos, glyphIDs.size()}) {
*posCursor++ = SkPoint::Make(x, constY);
}
- return this->simplifyDrawPosText(
- paint, glyphIDs, positions,
- uniqueGlyphIDIndicesBuffer, uniqueGlyphIDsBuffer,
- text, clusters);
+ // The dense indices are not used by the rest of the stack yet.
+ SkSpan<const SkGlyphID> uniqueGlyphIDs;
+ #ifdef SK_DEBUG
+ uniqueGlyphIDs = this->addDenseAndUnique(
+ paint, glyphIDs, uniqueGlyphIDIndicesBuffer, uniqueGlyphIDsBuffer);
+ #endif
+
+ this->makeGlyphRun(
+ paint,
+ glyphIDs,
+ SkSpan<SkPoint>{positions, runSize},
+ SkSpan<const SkGlyphID>{uniqueGlyphIDIndicesBuffer, runSize},
+ uniqueGlyphIDs,
+ text,
+ clusters);
+
+ return uniqueGlyphIDs.size();
}
size_t SkGlyphRunBuilder::simplifyDrawPosText(
const SkPaint& paint, SkSpan<const SkGlyphID> glyphIDs, const SkPoint* pos,
- uint16_t* uniqueGlyphIDIndicesBuffer, SkGlyphID* uniqueGlyphIDsBuffer,
+ uint16_t* uniqueGlyphIDIndicesBuffer, SkGlyphID* uniqueGlyphIDsBuffer, SkPoint* positions,
SkSpan<const char> text, SkSpan<const uint32_t> clusters) {
auto runSize = glyphIDs.size();
@@ -494,12 +515,15 @@ size_t SkGlyphRunBuilder::simplifyDrawPosText(
paint, glyphIDs, uniqueGlyphIDIndicesBuffer, uniqueGlyphIDsBuffer);
#endif
+ memcpy(positions, pos, runSize * sizeof(SkPoint));
+
+
// TODO: when using the unique glyph system have a guard that there are actually glyphs like
// drawText above.
this->makeGlyphRun(
paint,
glyphIDs,
- SkSpan<const SkPoint>{pos, runSize},
+ SkSpan<SkPoint>{positions, runSize},
SkSpan<const SkGlyphID>{uniqueGlyphIDIndicesBuffer, runSize},
uniqueGlyphIDs,
text,
diff --git a/src/core/SkGlyphRun.h b/src/core/SkGlyphRun.h
index 0146b1d515..f3b4ff34e3 100644
--- a/src/core/SkGlyphRun.h
+++ b/src/core/SkGlyphRun.h
@@ -41,6 +41,7 @@ public:
size_t size() const { return fSize; }
bool empty() const { return fSize == 0; }
size_t size_bytes() const { return fSize * sizeof(T); }
+ SkSpan<const T> toConst() const { return SkSpan<const T>{fPtr, fSize}; }
private:
T* fPtr;
@@ -52,7 +53,7 @@ public:
SkGlyphRun() = default;
SkGlyphRun(SkPaint&& runPaint,
SkSpan<const uint16_t> denseIndices,
- SkSpan<const SkPoint> positions,
+ SkSpan<SkPoint> positions,
SkSpan<const SkGlyphID> glyphIDs,
SkSpan<const SkGlyphID> uniqueGlyphIDs,
SkSpan<const char> text,
@@ -61,6 +62,13 @@ public:
// A function that turns an SkGlyphRun into an SkGlyphRun for each glyph.
using PerGlyph = std::function<void (SkGlyphRun*, SkPaint*)>;
void eachGlyphToGlyphRun(PerGlyph perGlyph);
+ void mapPositions(const SkMatrix& matrix);
+
+ // The following made a ~5% speed improvement over not using a template.
+ //using PerGlyphPos = std::function<void (SkGlyphID glyphID, SkPoint positions)>;
+ template <typename PerGlyphPos>
+ void forEachGlyphAndPosition(PerGlyphPos perGlyph) const;
+
// The temporaryShunt calls are to allow inter-operating with existing code while glyph runs
// are developed.
@@ -70,7 +78,7 @@ public:
void filloutGlyphsAndPositions(SkGlyphID* glyphIDs, SkPoint* positions);
size_t runSize() const { return fGlyphIDs.size(); }
- SkSpan<const SkPoint> positions() const { return fPositions; }
+ SkSpan<const SkPoint> positions() const { return fPositions.toConst(); }
SkSpan<const SkGlyphID> shuntGlyphsIDs() const { return fGlyphIDs; }
const SkPaint& paint() const { return fRunPaint; }
SkPaint* mutablePaint() { return &fRunPaint; }
@@ -81,7 +89,7 @@ private:
//
const SkSpan<const uint16_t> fUniqueGlyphIDIndices;
//
- const SkSpan<const SkPoint> fPositions;
+ const SkSpan<SkPoint> fPositions;
// This is temporary while converting from the old per glyph code to the bulk code.
const SkSpan<const SkGlyphID> fGlyphIDs;
// The unique glyphs from fGlyphIDs.
@@ -94,6 +102,14 @@ private:
SkPaint fRunPaint;
};
+template <typename PerGlyphPos>
+inline void SkGlyphRun::forEachGlyphAndPosition(PerGlyphPos perGlyph) const {
+ SkPoint* ptCursor = fPositions.data();
+ for (auto glyphID : fGlyphIDs) {
+ perGlyph(glyphID, *ptCursor++);
+ }
+}
+
class SkGlyphRunList {
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
@@ -207,7 +223,7 @@ private:
void makeGlyphRun(
const SkPaint& runPaint,
SkSpan<const SkGlyphID> glyphIDs,
- SkSpan<const SkPoint> positions,
+ SkSpan<SkPoint> positions,
SkSpan<const uint16_t> uniqueGlyphIDIndices,
SkSpan<const SkGlyphID> uniqueGlyphIDs,
SkSpan<const char> text,
@@ -228,7 +244,7 @@ private:
SkSpan<const uint32_t> clusters = SkSpan<const uint32_t>{});
size_t simplifyDrawPosText(
const SkPaint& paint, SkSpan<const SkGlyphID> glyphIDs, const SkPoint* pos,
- uint16_t* uniqueGlyphIDIndices, SkGlyphID* uniqueGlyphIDs,
+ uint16_t* uniqueGlyphIDIndices, SkGlyphID* uniqueGlyphIDs, SkPoint* positions,
SkSpan<const char> text = SkSpan<const char>{},
SkSpan<const uint32_t> clusters = SkSpan<const uint32_t>{});