Filter TextBlob paints in Viewer.
In particular this allows subpixel positioning to be forced for
drawing.
Change-Id: I2c88311f075944fef66fe5ba0237804aa5755800
Reviewed-on: https://skia-review.googlesource.com/156370
Reviewed-by: Herb Derby <herb@google.com>
Commit-Queue: Ben Wagner <bungeman@google.com>
diff --git a/tools/viewer/Viewer.cpp b/tools/viewer/Viewer.cpp
index 7cd03fe..5919654 100644
--- a/tools/viewer/Viewer.cpp
+++ b/tools/viewer/Viewer.cpp
@@ -985,6 +985,73 @@
OveridePaintFilterCanvas(SkCanvas* canvas, SkPaint* paint, Viewer::SkPaintFields* fields)
: SkPaintFilterCanvas(canvas), fPaint(paint), fPaintOverrides(fields)
{ }
+ const SkTextBlob* filterTextBlob(const SkPaint& paint, const SkTextBlob* blob,
+ sk_sp<SkTextBlob>* cache) {
+ bool blobWillChange = false;
+ for (SkTextBlobRunIterator it(blob); !it.done(); it.next()) {
+ SkPaint blobPaint = paint;
+ it.applyFontToPaint(&blobPaint);
+ SkTCopyOnFirstWrite<SkPaint> filteredPaint(blobPaint);
+ bool shouldDraw = this->onFilter(&filteredPaint, kTextBlob_Type);
+ if (blobPaint != *filteredPaint || !shouldDraw) {
+ blobWillChange = true;
+ break;
+ }
+ }
+ if (!blobWillChange) {
+ return blob;
+ }
+
+ SkTextBlobBuilder builder;
+ for (SkTextBlobRunIterator it(blob); !it.done(); it.next()) {
+ SkPaint blobPaint = paint;
+ it.applyFontToPaint(&blobPaint);
+ SkTCopyOnFirstWrite<SkPaint> filteredPaint(blobPaint);
+ bool shouldDraw = this->onFilter(&filteredPaint, kTextBlob_Type);
+ if (!shouldDraw) {
+ continue;
+ }
+
+ const SkTextBlobBuilder::RunBuffer& runBuffer
+ = it.positioning() == SkTextBlobRunIterator::kDefault_Positioning
+ ? SkTextBlobBuilderPriv::AllocRunText(&builder, *filteredPaint,
+ it.offset().x(),it.offset().y(), it.glyphCount(), it.textSize(), SkString())
+ : it.positioning() == SkTextBlobRunIterator::kHorizontal_Positioning
+ ? SkTextBlobBuilderPriv::AllocRunTextPosH(&builder, *filteredPaint,
+ it.offset().y(), it.glyphCount(), it.textSize(), SkString())
+ : it.positioning() == SkTextBlobRunIterator::kFull_Positioning
+ ? SkTextBlobBuilderPriv::AllocRunTextPos(&builder, *filteredPaint,
+ it.glyphCount(), it.textSize(), SkString())
+ : (SkASSERT_RELEASE(false), SkTextBlobBuilder::RunBuffer());
+ uint32_t glyphCount = it.glyphCount();
+ if (it.glyphs()) {
+ size_t glyphSize = sizeof(decltype(*it.glyphs()));
+ memcpy(runBuffer.glyphs, it.glyphs(), glyphCount * glyphSize);
+ }
+ if (it.pos()) {
+ size_t posSize = sizeof(decltype(*it.pos()));
+ uint8_t positioning = it.positioning();
+ memcpy(runBuffer.pos, it.pos(), glyphCount * positioning * posSize);
+ }
+ if (it.text()) {
+ size_t textSize = sizeof(decltype(*it.text()));
+ uint32_t textCount = it.textSize();
+ memcpy(runBuffer.utf8text, it.text(), textCount * textSize);
+ }
+ if (it.clusters()) {
+ size_t clusterSize = sizeof(decltype(*it.clusters()));
+ memcpy(runBuffer.clusters, it.clusters(), glyphCount * clusterSize);
+ }
+ }
+ *cache = builder.make();
+ return cache->get();
+ }
+ void onDrawTextBlob(const SkTextBlob* blob, SkScalar x, SkScalar y,
+ const SkPaint& paint) override {
+ sk_sp<SkTextBlob> cache;
+ this->SkPaintFilterCanvas::onDrawTextBlob(
+ this->filterTextBlob(paint, blob, &cache), x, y, paint);
+ }
bool onFilter(SkTCopyOnFirstWrite<SkPaint>* paint, Type) const override {
if (*paint == nullptr) {
return true;