aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--gm/mixedtextblobs.cpp26
-rw-r--r--gm/textblobcolortrans.cpp100
-rw-r--r--gm/textbloblooper.cpp1
-rw-r--r--gyp/gmslides.gypi1
-rw-r--r--include/core/SkPaint.h8
-rw-r--r--include/core/SkTextBlob.h1
-rw-r--r--src/core/SkPaint.cpp6
-rw-r--r--src/core/SkTextBlob.cpp7
-rw-r--r--src/gpu/GrAtlasTextContext.cpp100
-rw-r--r--src/gpu/GrAtlasTextContext.h21
-rw-r--r--tools/sk_tool_utils.cpp17
-rw-r--r--tools/sk_tool_utils.h5
12 files changed, 237 insertions, 56 deletions
diff --git a/gm/mixedtextblobs.cpp b/gm/mixedtextblobs.cpp
index 7aaaa52cf0..20b91accfd 100644
--- a/gm/mixedtextblobs.cpp
+++ b/gm/mixedtextblobs.cpp
@@ -16,21 +16,6 @@
namespace skiagm {
-static void add_to_text_blob(SkTextBlobBuilder* builder, const char* text, const SkPaint& origPaint,
- SkScalar x, SkScalar y) {
- SkPaint paint(origPaint);
- SkTDArray<uint16_t> glyphs;
-
- size_t len = strlen(text);
- glyphs.append(paint.textToGlyphs(text, len, NULL));
- paint.textToGlyphs(text, len, glyphs.begin());
-
- paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
- const SkTextBlobBuilder::RunBuffer& run = builder->allocRun(paint, glyphs.count(), x, y,
- NULL);
- memcpy(run.glyphs, glyphs.begin(), glyphs.count() * sizeof(uint16_t));
-}
-
static void draw_blob(SkCanvas* canvas, const SkTextBlob* blob, const SkPaint& skPaint,
const SkRect& clipRect) {
SkPaint clipHairline;
@@ -91,7 +76,7 @@ protected:
paint.measureText(text, strlen(text), &bounds);
SkScalar yOffset = bounds.height();
- add_to_text_blob(&builder, text, paint, 10, yOffset);
+ sk_tool_utils::add_to_text_blob(&builder, text, paint, 10, yOffset);
SkScalar corruptedAx = bounds.width();
SkScalar corruptedAy = yOffset;
@@ -107,8 +92,8 @@ protected:
paint.setSubpixelText(true);
paint.setLCDRenderText(true);
paint.measureText(text, strlen(text), &bounds);
- add_to_text_blob(&builder, text, paint, xOffset - bounds.width() * 0.25f,
- yOffset - bounds.height() * 0.5f);
+ sk_tool_utils::add_to_text_blob(&builder, text, paint, xOffset - bounds.width() * 0.25f,
+ yOffset - bounds.height() * 0.5f);
yOffset += bounds.height();
// color emoji
@@ -117,13 +102,14 @@ protected:
paint.setTypeface(fEmojiTypeface);
text = fEmojiText;
paint.measureText(text, strlen(text), &bounds);
- add_to_text_blob(&builder, text, paint, xOffset - bounds.width() * 0.3f, yOffset);
+ sk_tool_utils::add_to_text_blob(&builder, text, paint, xOffset - bounds.width() * 0.3f,
+ yOffset);
// Corrupted font
paint.setTextSize(12);
text = "aA";
paint.setTypeface(fReallyBigATypeface);
- add_to_text_blob(&builder, text, paint, corruptedAx, corruptedAy);
+ sk_tool_utils::add_to_text_blob(&builder, text, paint, corruptedAx, corruptedAy);
fBlob.reset(builder.build());
}
diff --git a/gm/textblobcolortrans.cpp b/gm/textblobcolortrans.cpp
new file mode 100644
index 0000000000..cb4686e6e7
--- /dev/null
+++ b/gm/textblobcolortrans.cpp
@@ -0,0 +1,100 @@
+/*
+ * Copyright 2015 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "gm.h"
+
+#include "Resources.h"
+#include "SkCanvas.h"
+#include "SkGradientShader.h"
+#include "SkStream.h"
+#include "SkTextBlob.h"
+#include "SkTypeface.h"
+
+namespace skiagm {
+class TextBlobColorTrans : public GM {
+public:
+ // This gm tests that textblobs can be translated and have their colors regenerated
+ // correctly. With smaller atlas sizes, it can also trigger regeneration of texture coords on
+ // the GPU backend
+ TextBlobColorTrans() { }
+
+protected:
+ void onOnceBeforeDraw() override {
+ SkTextBlobBuilder builder;
+
+ // make textblob
+ // Large text is used to trigger atlas eviction
+ SkPaint paint;
+ paint.setTextSize(256);
+ const char* text = "AB";
+ sk_tool_utils::set_portable_typeface(&paint);
+
+ SkRect bounds;
+ paint.measureText(text, strlen(text), &bounds);
+
+ SkScalar yOffset = bounds.height();
+ sk_tool_utils::add_to_text_blob(&builder, text, paint, 0, yOffset - 30);
+
+ // A8
+ paint.setTextSize(28);
+ text = "The quick brown fox jumps over the lazy dog.";
+ paint.setSubpixelText(false);
+ paint.setLCDRenderText(false);
+ paint.measureText(text, strlen(text), &bounds);
+ sk_tool_utils::add_to_text_blob(&builder, text, paint, 0, yOffset - 8);
+
+ // build
+ fBlob.reset(builder.build());
+ }
+
+ SkString onShortName() override {
+ return SkString("textblobcolortrans");
+ }
+
+ SkISize onISize() override {
+ return SkISize::Make(kWidth, kHeight);
+ }
+
+ void onDraw(SkCanvas* canvas) override {
+
+ canvas->drawColor(SK_ColorGRAY);
+
+ SkPaint paint;
+ canvas->translate(10, 40);
+
+ SkRect bounds = fBlob->bounds();
+
+ // Colors were chosen to map to pairs of canonical colors. The GPU Backend will cache A8
+ // Texture Blobs based on the canonical color they map to. Canonical colors are used to
+ // create masks. For A8 there are 8 of them.
+ SkColor colors[] = {SK_ColorCYAN, SK_ColorLTGRAY, SK_ColorYELLOW, SK_ColorWHITE};
+
+ size_t count = SK_ARRAY_COUNT(colors);
+ size_t colorIndex = 0;
+ for (int y = 0; y + SkScalarFloorToInt(bounds.height()) < kHeight;
+ y += SkScalarFloorToInt(bounds.height())) {
+ paint.setColor(colors[colorIndex++ % count]);
+ canvas->save();
+ canvas->translate(0, SkIntToScalar(y));
+ canvas->drawTextBlob(fBlob, 0, 0, paint);
+ canvas->restore();
+ }
+ }
+
+private:
+ SkAutoTUnref<const SkTextBlob> fBlob;
+
+ static const int kWidth = 675;
+ static const int kHeight = 1600;
+
+ typedef GM INHERITED;
+};
+
+//////////////////////////////////////////////////////////////////////////////
+
+DEF_GM( return SkNEW(TextBlobColorTrans); )
+}
diff --git a/gm/textbloblooper.cpp b/gm/textbloblooper.cpp
index 253945f123..2fbd30b3cf 100644
--- a/gm/textbloblooper.cpp
+++ b/gm/textbloblooper.cpp
@@ -23,6 +23,7 @@ namespace skiagm {
static const int kWidth = 1250;
static const int kHeight = 700;
+// Unlike the variant in sk_tool_utils, this version positions the glyphs on a diagonal
static void add_to_text_blob(SkTextBlobBuilder* builder, const char* text, const SkPaint& origPaint,
SkScalar x, SkScalar y) {
SkPaint paint(origPaint);
diff --git a/gyp/gmslides.gypi b/gyp/gmslides.gypi
index 02297c32b3..3f02937663 100644
--- a/gyp/gmslides.gypi
+++ b/gyp/gmslides.gypi
@@ -211,6 +211,7 @@
'../gm/tallstretchedbitmaps.cpp',
'../gm/textblob.cpp',
'../gm/textbloblooper.cpp',
+ '../gm/textblobcolortrans.cpp',
'../gm/textblobshader.cpp',
'../gm/texturedomaineffect.cpp',
'../gm/thinrects.cpp',
diff --git a/include/core/SkPaint.h b/include/core/SkPaint.h
index 991a727f93..e4be06e03e 100644
--- a/include/core/SkPaint.h
+++ b/include/core/SkPaint.h
@@ -1076,6 +1076,13 @@ private:
void (*proc)(SkTypeface*, const SkDescriptor*, void*),
void* context, bool ignoreGamma = false) const;
+ /*
+ * The luminance color is used to determine which Gamma Canonical color to map to. This is
+ * really only used by backends which want to cache glyph masks, and need some way to know if
+ * they need to generate new masks based off a given color.
+ */
+ SkColor computeLuminanceColor() const;
+
static void Term();
enum {
@@ -1129,6 +1136,7 @@ private:
friend class GrPathRendering;
friend class GrTextContext;
friend class GrGLPathRendering;
+ friend class SkScalerContext;
friend class SkTextToPathIter;
friend class SkCanonicalizePaint;
};
diff --git a/include/core/SkTextBlob.h b/include/core/SkTextBlob.h
index a091f05f5f..b1ae456689 100644
--- a/include/core/SkTextBlob.h
+++ b/include/core/SkTextBlob.h
@@ -68,6 +68,7 @@ private:
const SkPoint& offset() const;
void applyFontToPaint(SkPaint*) const;
GlyphPositioning positioning() const;
+ bool isLCD() const;
private:
const RunRecord* fCurrentRun;
diff --git a/src/core/SkPaint.cpp b/src/core/SkPaint.cpp
index 2c1745d00b..9f76355aac 100644
--- a/src/core/SkPaint.cpp
+++ b/src/core/SkPaint.cpp
@@ -1291,9 +1291,9 @@ static bool justAColor(const SkPaint& paint, SkColor* color) {
return true;
}
-static SkColor computeLuminanceColor(const SkPaint& paint) {
+SkColor SkPaint::computeLuminanceColor() const {
SkColor c;
- if (!justAColor(paint, &c)) {
+ if (!justAColor(*this, &c)) {
c = SkColorSetRGB(0x7F, 0x80, 0x7F);
}
return c;
@@ -1463,7 +1463,7 @@ void SkScalerContext::MakeRec(const SkPaint& paint,
// these modify fFlags, so do them after assigning fFlags
rec->setHinting(computeHinting(paint));
- rec->setLuminanceColor(computeLuminanceColor(paint));
+ rec->setLuminanceColor(paint.computeLuminanceColor());
if (NULL == deviceProperties) {
rec->setDeviceGamma(SK_GAMMA_EXPONENT);
diff --git a/src/core/SkTextBlob.cpp b/src/core/SkTextBlob.cpp
index 3d396deba5..6ea081d764 100644
--- a/src/core/SkTextBlob.cpp
+++ b/src/core/SkTextBlob.cpp
@@ -47,6 +47,9 @@ public:
bool operator!=(const RunFont& other) const {
return !(*this == other);
}
+
+ uint32_t flags() const { return fFlags; }
+
private:
const static uint32_t kFlagsMask =
SkPaint::kAntiAlias_Flag |
@@ -343,6 +346,10 @@ void SkTextBlob::RunIterator::applyFontToPaint(SkPaint* paint) const {
fCurrentRun->font().applyToPaint(paint);
}
+bool SkTextBlob::RunIterator::isLCD() const {
+ return SkToBool(fCurrentRun->font().flags() & SkPaint::kLCDRenderText_Flag);
+}
+
SkTextBlobBuilder::SkTextBlobBuilder()
: fStorageSize(0)
, fStorageUsed(0)
diff --git a/src/gpu/GrAtlasTextContext.cpp b/src/gpu/GrAtlasTextContext.cpp
index 9dbe6312cb..59a875e422 100644
--- a/src/gpu/GrAtlasTextContext.cpp
+++ b/src/gpu/GrAtlasTextContext.cpp
@@ -91,13 +91,47 @@ bool GrAtlasTextContext::canDraw(const GrRenderTarget*,
return !SkDraw::ShouldDrawTextAsPaths(skPaint, viewMatrix);
}
+GrColor GrAtlasTextContext::ComputeCanonicalColor(const SkPaint& paint, bool lcd) {
+ GrColor canonicalColor = paint.computeLuminanceColor();
+ if (lcd) {
+ // This is the correct computation, but there are tons of cases where LCD can be overridden.
+ // For now we just regenerate if any run in a textblob has LCD.
+ // TODO figure out where all of these overrides are and see if we can incorporate that logic
+ // at a higher level *OR* use sRGB
+ SkASSERT(false);
+ //canonicalColor = SkMaskGamma::CanonicalColor(canonicalColor);
+ } else {
+ // A8, though can have mixed BMP text but it shouldn't matter because BMP text won't have
+ // gamma corrected masks anyways, nor color
+ U8CPU lum = SkComputeLuminance(SkColorGetR(canonicalColor),
+ SkColorGetG(canonicalColor),
+ SkColorGetB(canonicalColor));
+ // reduce to our finite number of bits
+ canonicalColor = SkMaskGamma::CanonicalColor(SkColorSetRGB(lum, lum, lum));
+ }
+ return canonicalColor;
+}
+
+// TODO if this function ever shows up in profiling, then we can compute this value when the
+// textblob is being built and cache it. However, for the time being textblobs mostly only have 1
+// run so this is not a big deal to compute here.
+bool GrAtlasTextContext::HasLCD(const SkTextBlob* blob) {
+ SkTextBlob::RunIterator it(blob);
+ for (; !it.done(); it.next()) {
+ if (it.isLCD()) {
+ return true;
+ }
+ }
+ return false;
+}
+
bool GrAtlasTextContext::MustRegenerateBlob(SkScalar* outTransX, SkScalar* outTransY,
const BitmapTextBlob& blob, const SkPaint& paint,
const SkMaskFilter::BlurRec& blurRec,
const SkMatrix& viewMatrix, SkScalar x, SkScalar y) {
- // Color can affect the mask
- // TODO we can adjust the color within specific gamma slots
- if (blob.fColor != paint.getColor()) {
+ // If we have LCD text then our canonical color will be set to transparent, in this case we have
+ // to regenerate the blob on any color change
+ if (blob.fKey.fCanonicalColor == SK_ColorTRANSPARENT && blob.fPaintColor != paint.getColor()) {
return true;
}
@@ -180,7 +214,6 @@ void GrAtlasTextContext::drawTextBlob(GrRenderTarget* rt, const GrClip& clip,
const SkTextBlob* blob, SkScalar x, SkScalar y,
SkDrawFilter* drawFilter, const SkIRect& clipBounds) {
SkAutoTUnref<BitmapTextBlob> cacheBlob;
-
SkMaskFilter::BlurRec blurRec;
BitmapTextBlob::Key key;
// It might be worth caching these things, but its not clear at this time
@@ -191,9 +224,17 @@ void GrAtlasTextContext::drawTextBlob(GrRenderTarget* rt, const GrClip& clip,
drawFilter);
if (canCache) {
+ bool hasLCD = HasLCD(blob);
+ // TODO we want to figure out a way to be able to use the canonical color on LCD text,
+ // see the note on ComputeCanonicalColor above. We pick a dummy value for LCD text to
+ // ensure we always match the same key
+ GrColor canonicalColor = hasLCD ? SK_ColorTRANSPARENT :
+ ComputeCanonicalColor(skPaint, hasLCD);
+
key.fUniqueID = blob->uniqueID();
key.fStyle = skPaint.getStyle();
key.fHasBlur = SkToBool(mf);
+ key.fCanonicalColor = canonicalColor;
cacheBlob.reset(SkSafeRef(fCache->find(key)));
}
@@ -203,6 +244,11 @@ void GrAtlasTextContext::drawTextBlob(GrRenderTarget* rt, const GrClip& clip,
SkScalar transX = 0.f;
SkScalar transY = 0.f;
+ // Though for the time being runs in the textblob can override the paint, they only touch font
+ // info.
+ GrPaint grPaint;
+ SkPaint2GrPaintShader(fContext, rt, skPaint, viewMatrix, true, &grPaint);
+
if (cacheBlob) {
if (MustRegenerateBlob(&transX, &transY, *cacheBlob, skPaint, blurRec, viewMatrix, x, y)) {
// We have to remake the blob because changes may invalidate our masks.
@@ -211,11 +257,11 @@ void GrAtlasTextContext::drawTextBlob(GrRenderTarget* rt, const GrClip& clip,
fCache->remove(cacheBlob);
cacheBlob.reset(SkRef(fCache->createCachedBlob(blob, key, blurRec, skPaint,
kGrayTextVASize)));
- this->regenerateTextBlob(cacheBlob, skPaint, viewMatrix, blob, x, y, drawFilter,
- clipRect);
+ this->regenerateTextBlob(cacheBlob, skPaint, grPaint.getColor(), viewMatrix, blob, x, y,
+ drawFilter, clipRect);
} else {
- // If we can reuse the blob, then make sure we update the blob's viewmatrix and x/y
- // offsets to reflect the results of any translations we may apply in generateGeometry
+ // If we can reuse the blob, then make sure we update the blob's viewmatrix, and x/y
+ // offsets
cacheBlob->fViewMatrix = viewMatrix;
cacheBlob->fX = x;
cacheBlob->fY = y;
@@ -228,26 +274,23 @@ void GrAtlasTextContext::drawTextBlob(GrRenderTarget* rt, const GrClip& clip,
} else {
cacheBlob.reset(fCache->createBlob(blob, kGrayTextVASize));
}
- this->regenerateTextBlob(cacheBlob, skPaint, viewMatrix, blob, x, y, drawFilter, clipRect);
+ this->regenerateTextBlob(cacheBlob, skPaint, grPaint.getColor(), viewMatrix, blob, x, y,
+ drawFilter, clipRect);
}
- // Though for the time being runs in the textblob can override the paint, they only touch font
- // info.
- GrPaint grPaint;
- SkPaint2GrPaintShader(fContext, rt, skPaint, viewMatrix, true, &grPaint);
-
+ cacheBlob->fPaintColor = skPaint.getColor();
this->flush(fContext->getTextTarget(), blob, cacheBlob, rt, skPaint, grPaint, drawFilter,
clip, viewMatrix, clipBounds, x, y, transX, transY);
}
void GrAtlasTextContext::regenerateTextBlob(BitmapTextBlob* cacheBlob,
- const SkPaint& skPaint, const SkMatrix& viewMatrix,
+ const SkPaint& skPaint, GrColor color,
+ const SkMatrix& viewMatrix,
const SkTextBlob* blob, SkScalar x, SkScalar y,
SkDrawFilter* drawFilter, const SkIRect& clipRect) {
cacheBlob->fViewMatrix = viewMatrix;
cacheBlob->fX = x;
cacheBlob->fY = y;
- cacheBlob->fColor = skPaint.getColor();
// Regenerate textblob
SkPaint runPaint = skPaint;
@@ -290,17 +333,17 @@ void GrAtlasTextContext::regenerateTextBlob(BitmapTextBlob* cacheBlob,
switch (it.positioning()) {
case SkTextBlob::kDefault_Positioning:
- this->internalDrawText(cacheBlob, run, cache, runPaint, viewMatrix,
+ this->internalDrawText(cacheBlob, run, cache, runPaint, color, viewMatrix,
(const char *)it.glyphs(), textLen,
x + offset.x(), y + offset.y(), clipRect);
break;
case SkTextBlob::kHorizontal_Positioning:
- this->internalDrawPosText(cacheBlob, run, cache, runPaint, viewMatrix,
+ this->internalDrawPosText(cacheBlob, run, cache, runPaint, color, viewMatrix,
(const char*)it.glyphs(), textLen, it.pos(), 1,
SkPoint::Make(x, y + offset.y()), clipRect);
break;
case SkTextBlob::kFull_Positioning:
- this->internalDrawPosText(cacheBlob, run, cache, runPaint, viewMatrix,
+ this->internalDrawPosText(cacheBlob, run, cache, runPaint, color, viewMatrix,
(const char*)it.glyphs(), textLen, it.pos(), 2,
SkPoint::Make(x, y), clipRect);
break;
@@ -331,7 +374,8 @@ void GrAtlasTextContext::onDrawText(GrRenderTarget* rt, const GrClip& clip,
// setup cache
SkGlyphCache* cache = this->setupCache(&blob->fRuns[0], skPaint, viewMatrix);
- this->internalDrawText(blob, 0, cache, skPaint, viewMatrix, text, byteLength, x, y, clipRect);
+ this->internalDrawText(blob, 0, cache, skPaint, paint.getColor(), viewMatrix, text, byteLength,
+ x, y, clipRect);
SkGlyphCache::AttachCache(cache);
this->flush(fContext->getTextTarget(), blob, rt, skPaint, paint, clip, viewMatrix);
@@ -339,6 +383,7 @@ void GrAtlasTextContext::onDrawText(GrRenderTarget* rt, const GrClip& clip,
void GrAtlasTextContext::internalDrawText(BitmapTextBlob* blob, int runIndex,
SkGlyphCache* cache, const SkPaint& skPaint,
+ GrColor color,
const SkMatrix& viewMatrix,
const char text[], size_t byteLength,
SkScalar x, SkScalar y, const SkIRect& clipRect) {
@@ -417,7 +462,7 @@ void GrAtlasTextContext::internalDrawText(BitmapTextBlob* blob, int runIndex,
GrGlyph::kCoverage_MaskStyle),
Sk48Dot16FloorToInt(fx),
Sk48Dot16FloorToInt(fy),
- skPaint.getColor(),
+ color,
fontScaler,
clipRect);
}
@@ -442,8 +487,8 @@ void GrAtlasTextContext::onDrawPosText(GrRenderTarget* rt, const GrClip& clip,
// setup cache
SkGlyphCache* cache = this->setupCache(&blob->fRuns[0], skPaint, viewMatrix);
- this->internalDrawPosText(blob, 0, cache, skPaint, viewMatrix, text, byteLength, pos,
- scalarsPerPosition, offset, clipRect);
+ this->internalDrawPosText(blob, 0, cache, skPaint, paint.getColor(), viewMatrix, text,
+ byteLength, pos, scalarsPerPosition, offset, clipRect);
SkGlyphCache::AttachCache(cache);
this->flush(fContext->getTextTarget(), blob, rt, skPaint, paint, clip, viewMatrix);
@@ -451,6 +496,7 @@ void GrAtlasTextContext::onDrawPosText(GrRenderTarget* rt, const GrClip& clip,
void GrAtlasTextContext::internalDrawPosText(BitmapTextBlob* blob, int runIndex,
SkGlyphCache* cache, const SkPaint& skPaint,
+ GrColor color,
const SkMatrix& viewMatrix,
const char text[], size_t byteLength,
const SkScalar pos[], int scalarsPerPosition,
@@ -508,7 +554,7 @@ void GrAtlasTextContext::internalDrawPosText(BitmapTextBlob* blob, int runIndex,
GrGlyph::kCoverage_MaskStyle),
Sk48Dot16FloorToInt(fx),
Sk48Dot16FloorToInt(fy),
- skPaint.getColor(),
+ color,
fontScaler,
clipRect);
}
@@ -546,7 +592,7 @@ void GrAtlasTextContext::internalDrawPosText(BitmapTextBlob* blob, int runIndex,
GrGlyph::kCoverage_MaskStyle),
Sk48Dot16FloorToInt(fx),
Sk48Dot16FloorToInt(fy),
- skPaint.getColor(),
+ color,
fontScaler,
clipRect);
}
@@ -574,7 +620,7 @@ void GrAtlasTextContext::internalDrawPosText(BitmapTextBlob* blob, int runIndex,
GrGlyph::kCoverage_MaskStyle),
Sk48Dot16FloorToInt(fx),
Sk48Dot16FloorToInt(fy),
- skPaint.getColor(),
+ color,
fontScaler,
clipRect);
}
@@ -602,7 +648,7 @@ void GrAtlasTextContext::internalDrawPosText(BitmapTextBlob* blob, int runIndex,
GrGlyph::kCoverage_MaskStyle),
Sk48Dot16FloorToInt(fx),
Sk48Dot16FloorToInt(fy),
- skPaint.getColor(),
+ color,
fontScaler,
clipRect);
}
diff --git a/src/gpu/GrAtlasTextContext.h b/src/gpu/GrAtlasTextContext.h
index c999e1f0af..62b5207538 100644
--- a/src/gpu/GrAtlasTextContext.h
+++ b/src/gpu/GrAtlasTextContext.h
@@ -57,8 +57,8 @@ private:
*
* The only thing(aside from a memcopy) required to flush a BitmapTextBlob is to ensure that
* the GrAtlas will not evict anything the Blob needs.
- * TODO this is currently a bug
*/
+ // TODO Pack these bytes
struct BitmapTextBlob : public SkRefCnt {
SK_DECLARE_INTERNAL_LLIST_INTERFACE(BitmapTextBlob);
@@ -127,8 +127,8 @@ private:
mutable SkScalar fTotalXError;
mutable SkScalar fTotalYError;
#endif
+ SkColor fPaintColor;
SkTArray<BigGlyph> fBigGlyphs;
- GrColor fColor; // the original color on the paint
SkMatrix fViewMatrix;
SkScalar fX;
SkScalar fY;
@@ -149,10 +149,15 @@ private:
struct Key {
Key() {
- memset(this, 0, sizeof(Key));
+ sk_bzero(this, sizeof(Key));
}
uint32_t fUniqueID;
SkPaint::Style fStyle;
+ // Color may affect the gamma of the mask we generate, but in a fairly limited way.
+ // Each color is assigned to on of a fixed number of buckets based on its
+ // luminance. For each luminance bucket there is a "canonical color" that
+ // represents the bucket. This functionality is currently only supported for A8
+ SkColor fCanonicalColor;
bool fHasBlur;
bool operator==(const Key& other) const {
@@ -207,23 +212,27 @@ private:
const GrPaint&, const GrClip&, const SkMatrix& viewMatrix);
void internalDrawText(BitmapTextBlob*, int runIndex, SkGlyphCache*, const SkPaint&,
- const SkMatrix& viewMatrix, const char text[], size_t byteLength,
+ GrColor color, const SkMatrix& viewMatrix,
+ const char text[], size_t byteLength,
SkScalar x, SkScalar y, const SkIRect& clipRect);
void internalDrawPosText(BitmapTextBlob*, int runIndex, SkGlyphCache*, const SkPaint&,
- const SkMatrix& viewMatrix,
+ GrColor color, const SkMatrix& viewMatrix,
const char text[], size_t byteLength,
const SkScalar pos[], int scalarsPerPosition,
const SkPoint& offset, const SkIRect& clipRect);
// sets up the descriptor on the blob and returns a detached cache. Client must attach
+ inline static GrColor ComputeCanonicalColor(const SkPaint&, bool lcd);
inline SkGlyphCache* setupCache(Run*, const SkPaint&, const SkMatrix& viewMatrix);
static inline bool MustRegenerateBlob(SkScalar* outTransX, SkScalar* outTransY,
const BitmapTextBlob&, const SkPaint&,
const SkMaskFilter::BlurRec&,
const SkMatrix& viewMatrix, SkScalar x, SkScalar y);
- void regenerateTextBlob(BitmapTextBlob* bmp, const SkPaint& skPaint, const SkMatrix& viewMatrix,
+ void regenerateTextBlob(BitmapTextBlob* bmp, const SkPaint& skPaint, GrColor,
+ const SkMatrix& viewMatrix,
const SkTextBlob* blob, SkScalar x, SkScalar y,
SkDrawFilter* drawFilter, const SkIRect& clipRect);
+ inline static bool HasLCD(const SkTextBlob*);
GrBatchTextStrike* fCurrStrike;
GrTextBlobCache* fCache;
diff --git a/tools/sk_tool_utils.cpp b/tools/sk_tool_utils.cpp
index c3e574a08e..1a88086a41 100644
--- a/tools/sk_tool_utils.cpp
+++ b/tools/sk_tool_utils.cpp
@@ -12,6 +12,7 @@
#include "SkCanvas.h"
#include "SkShader.h"
#include "SkTestScalerContext.h"
+#include "SkTextBlob.h"
DEFINE_bool(portableFonts, false, "Use portable fonts");
DEFINE_bool(resourceFonts, false, "Use resource fonts");
@@ -77,4 +78,20 @@ void draw_checkerboard(SkCanvas* canvas, SkColor c1, SkColor c2, int size) {
canvas->drawPaint(paint);
}
+void add_to_text_blob(SkTextBlobBuilder* builder, const char* text, const SkPaint& origPaint,
+ SkScalar x, SkScalar y) {
+ SkPaint paint(origPaint);
+ SkTDArray<uint16_t> glyphs;
+
+ size_t len = strlen(text);
+ glyphs.append(paint.textToGlyphs(text, len, NULL));
+ paint.textToGlyphs(text, len, glyphs.begin());
+
+ paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
+ const SkTextBlobBuilder::RunBuffer& run = builder->allocRun(paint, glyphs.count(), x, y,
+ NULL);
+ memcpy(run.glyphs, glyphs.begin(), glyphs.count() * sizeof(uint16_t));
+}
+
+
} // namespace sk_tool_utils
diff --git a/tools/sk_tool_utils.h b/tools/sk_tool_utils.h
index 0299e742d2..d9345a6b92 100644
--- a/tools/sk_tool_utils.h
+++ b/tools/sk_tool_utils.h
@@ -19,6 +19,7 @@ class SkCanvas;
class SkPaint;
class SkShader;
class SkTestFont;
+class SkTextBlobBuilder;
namespace sk_tool_utils {
@@ -69,6 +70,10 @@ namespace sk_tool_utils {
}
};
+ // A helper for inserting a drawtext call into a SkTextBlobBuilder
+ void add_to_text_blob(SkTextBlobBuilder* builder, const char* text, const SkPaint& origPaint,
+ SkScalar x, SkScalar y);
+
} // namespace sk_tool_utils
#endif // sk_tool_utils_DEFINED