aboutsummaryrefslogtreecommitdiffhomepage
path: root/src
diff options
context:
space:
mode:
authorGravatar joshualitt <joshualitt@chromium.org>2015-04-14 12:17:27 -0700
committerGravatar Commit bot <commit-bot@chromium.org>2015-04-14 12:17:27 -0700
commit9e36c1a9306f052331550dab4728b9875127bfb5 (patch)
treedc081124538053c3d28376cb767527326da74d25 /src
parent8fe8fffdfa7464c6f7da773b8660a2043f4998e0 (diff)
Start canonicalizing color for all A8 textblobs
Diffstat (limited to 'src')
-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
4 files changed, 98 insertions, 36 deletions
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;