aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/core
diff options
context:
space:
mode:
authorGravatar jvanverth <jvanverth@google.com>2014-06-09 12:04:55 -0700
committerGravatar Commit bot <commit-bot@chromium.org>2014-06-09 12:04:55 -0700
commit4d517fdbb145cb95e5e935470df331e1b6667cfc (patch)
tree277a6a4f0296f9a0c49eb6e4f3397bc1ff0d70c1 /src/core
parent8405ef9854858b2527bf03b7e7abb1c0da59411d (diff)
Gamma correction for distance field text.
Handles both non-LCD and LCD text. Uses a texture to look up the gamma correction values for a given text color or luminance. BUG=skia: R=reed@google.com, bungeman@google.com, robertphillips@google.com, bsalomon@google.com Author: jvanverth@google.com Review URL: https://codereview.chromium.org/258883002
Diffstat (limited to 'src/core')
-rw-r--r--src/core/SkGlyphCache.h65
-rw-r--r--src/core/SkMaskGamma.h16
-rw-r--r--src/core/SkPaint.cpp42
-rw-r--r--src/core/SkScalerContext.h11
4 files changed, 111 insertions, 23 deletions
diff --git a/src/core/SkGlyphCache.h b/src/core/SkGlyphCache.h
index 8b404dcc09..d18b61a0a9 100644
--- a/src/core/SkGlyphCache.h
+++ b/src/core/SkGlyphCache.h
@@ -244,37 +244,72 @@ private:
friend class SkGlyphCache_Globals;
};
-class SkAutoGlyphCache {
+class SkAutoGlyphCacheBase {
public:
- SkAutoGlyphCache(SkGlyphCache* cache) : fCache(cache) {}
- SkAutoGlyphCache(SkTypeface* typeface, const SkDescriptor* desc) {
+ SkGlyphCache* getCache() const { return fCache; }
+
+ void release() {
+ if (fCache) {
+ SkGlyphCache::AttachCache(fCache);
+ fCache = NULL;
+ }
+ }
+
+protected:
+ // Hide the constructors so we can't create one of these directly.
+ // Create SkAutoGlyphCache or SkAutoGlyphCacheNoCache instead.
+ SkAutoGlyphCacheBase(SkGlyphCache* cache) : fCache(cache) {}
+ SkAutoGlyphCacheBase(SkTypeface* typeface, const SkDescriptor* desc) {
fCache = SkGlyphCache::DetachCache(typeface, desc);
}
+ SkAutoGlyphCacheBase(const SkPaint& paint,
+ const SkDeviceProperties* deviceProperties,
+ const SkMatrix* matrix) {
+ fCache = NULL;
+ }
+ SkAutoGlyphCacheBase() {}
+
+ SkGlyphCache* fCache;
+
+private:
+ static bool DetachProc(const SkGlyphCache*, void*);
+};
+
+class SkAutoGlyphCache : public SkAutoGlyphCacheBase {
+public:
+ SkAutoGlyphCache(SkGlyphCache* cache) : SkAutoGlyphCacheBase(cache) {}
+ SkAutoGlyphCache(SkTypeface* typeface, const SkDescriptor* desc) :
+ SkAutoGlyphCacheBase(typeface, desc) {}
SkAutoGlyphCache(const SkPaint& paint,
const SkDeviceProperties* deviceProperties,
const SkMatrix* matrix) {
- fCache = paint.detachCache(deviceProperties, matrix);
+ fCache = paint.detachCache(deviceProperties, matrix, false);
}
- ~SkAutoGlyphCache() {
+ SkAutoGlyphCache() : SkAutoGlyphCacheBase() {
if (fCache) {
SkGlyphCache::AttachCache(fCache);
}
}
+};
+#define SkAutoGlyphCache(...) SK_REQUIRE_LOCAL_VAR(SkAutoGlyphCache)
- SkGlyphCache* getCache() const { return fCache; }
-
- void release() {
+class SkAutoGlyphCacheNoGamma : public SkAutoGlyphCacheBase {
+public:
+ SkAutoGlyphCacheNoGamma(SkGlyphCache* cache) : SkAutoGlyphCacheBase(cache) {}
+ SkAutoGlyphCacheNoGamma(SkTypeface* typeface, const SkDescriptor* desc) :
+ SkAutoGlyphCacheBase(typeface, desc) {}
+ SkAutoGlyphCacheNoGamma(const SkPaint& paint,
+ const SkDeviceProperties* deviceProperties,
+ const SkMatrix* matrix) {
+ fCache = paint.detachCache(deviceProperties, matrix, true);
+ }
+ SkAutoGlyphCacheNoGamma() : SkAutoGlyphCacheBase() {
if (fCache) {
SkGlyphCache::AttachCache(fCache);
- fCache = NULL;
}
}
-
-private:
- SkGlyphCache* fCache;
-
- static bool DetachProc(const SkGlyphCache*, void*);
};
-#define SkAutoGlyphCache(...) SK_REQUIRE_LOCAL_VAR(SkAutoGlyphCache)
+#define SkAutoGlyphCacheNoGamma(...) SK_REQUIRE_LOCAL_VAR(SkAutoGlyphCacheNoGamma)
+
#endif
diff --git a/src/core/SkMaskGamma.h b/src/core/SkMaskGamma.h
index 1f2b73caac..08ed97f913 100644
--- a/src/core/SkMaskGamma.h
+++ b/src/core/SkMaskGamma.h
@@ -136,6 +136,22 @@ public:
*/
PreBlend preBlend(SkColor color) const;
+ /**
+ * Get dimensions for the full table set, so it can be allocated as a block.
+ */
+ void getGammaTableDimensions(int* tableWidth, int* numTables) const {
+ *tableWidth = 256;
+ *numTables = (1 << MAX_LUM_BITS);
+ }
+
+ /**
+ * Provides direct access to the full table set, so it can be uploaded
+ * into a texture.
+ */
+ const uint8_t* getGammaTables() const {
+ return (const uint8_t*) fGammaTables;
+ }
+
private:
static const int MAX_LUM_BITS =
B_LUM_BITS > (R_LUM_BITS > G_LUM_BITS ? R_LUM_BITS : G_LUM_BITS)
diff --git a/src/core/SkPaint.cpp b/src/core/SkPaint.cpp
index 78d947020b..b08b2c6da7 100644
--- a/src/core/SkPaint.cpp
+++ b/src/core/SkPaint.cpp
@@ -1814,10 +1814,8 @@ void SkScalerContext::PostMakeRec(const SkPaint&, SkScalerContext::Rec* rec) {
/*
* ignoreGamma tells us that the caller just wants metrics that are unaffected
- * by gamma correction, so we jam the luminance field to 0 (most common value
- * for black text) in hopes that we get a cache hit easier. A better solution
- * would be for the fontcache lookup to know to ignore the luminance field
- * entirely, but not sure how to do that and keep it fast.
+ * by gamma correction, so we set the rec to ignore preblend: i.e. gamma = 1,
+ * contrast = 0, luminanceColor = transparent black.
*/
void SkPaint::descriptorProc(const SkDeviceProperties* deviceProperties,
const SkMatrix* deviceMatrix,
@@ -1827,7 +1825,7 @@ void SkPaint::descriptorProc(const SkDeviceProperties* deviceProperties,
SkScalerContext::MakeRec(*this, deviceProperties, deviceMatrix, &rec);
if (ignoreGamma) {
- rec.setLuminanceColor(0);
+ rec.ignorePreBlend();
}
size_t descSize = sizeof(rec);
@@ -1951,9 +1949,10 @@ void SkPaint::descriptorProc(const SkDeviceProperties* deviceProperties,
}
SkGlyphCache* SkPaint::detachCache(const SkDeviceProperties* deviceProperties,
- const SkMatrix* deviceMatrix) const {
+ const SkMatrix* deviceMatrix,
+ bool ignoreGamma) const {
SkGlyphCache* cache;
- this->descriptorProc(deviceProperties, deviceMatrix, DetachDescProc, &cache, false);
+ this->descriptorProc(deviceProperties, deviceMatrix, DetachDescProc, &cache, ignoreGamma);
return cache;
}
@@ -1969,6 +1968,33 @@ SkMaskGamma::PreBlend SkScalerContext::GetMaskPreBlend(const SkScalerContext::Re
return maskGamma.preBlend(rec.getLuminanceColor());
}
+size_t SkScalerContext::GetGammaLUTSize(SkScalar contrast, SkScalar paintGamma,
+ SkScalar deviceGamma, int* width, int* height) {
+ SkAutoMutexAcquire ama(gMaskGammaCacheMutex);
+ const SkMaskGamma& maskGamma = cachedMaskGamma(contrast,
+ paintGamma,
+ deviceGamma);
+
+ maskGamma.getGammaTableDimensions(width, height);
+ size_t size = (*width)*(*height)*sizeof(uint8_t);
+
+ return size;
+}
+
+void SkScalerContext::GetGammaLUTData(SkScalar contrast, SkScalar paintGamma, SkScalar deviceGamma,
+ void* data) {
+ SkAutoMutexAcquire ama(gMaskGammaCacheMutex);
+ const SkMaskGamma& maskGamma = cachedMaskGamma(contrast,
+ paintGamma,
+ deviceGamma);
+ int width, height;
+ maskGamma.getGammaTableDimensions(&width, &height);
+ size_t size = width*height*sizeof(uint8_t);
+ const uint8_t* gammaTables = maskGamma.getGammaTables();
+ memcpy(data, gammaTables, size);
+}
+
+
///////////////////////////////////////////////////////////////////////////////
#include "SkStream.h"
@@ -2557,7 +2583,7 @@ SkTextToPathIter::SkTextToPathIter( const char text[], size_t length,
fPaint.setPathEffect(NULL);
}
- fCache = fPaint.detachCache(NULL, NULL);
+ fCache = fPaint.detachCache(NULL, NULL, false);
SkPaint::Style style = SkPaint::kFill_Style;
SkPathEffect* pe = NULL;
diff --git a/src/core/SkScalerContext.h b/src/core/SkScalerContext.h
index f18d217f62..af83685eb6 100644
--- a/src/core/SkScalerContext.h
+++ b/src/core/SkScalerContext.h
@@ -184,6 +184,17 @@ public:
void getPath(const SkGlyph&, SkPath*);
void getFontMetrics(SkPaint::FontMetrics*);
+ /** Return the size in bytes of the associated gamma lookup table
+ */
+ static size_t GetGammaLUTSize(SkScalar contrast, SkScalar paintGamma, SkScalar deviceGamma,
+ int* width, int* height);
+
+ /** Get the associated gamma lookup table. The 'data' pointer must point to pre-allocated
+ memory, with size in bytes greater than or equal to the return value of getGammaLUTSize().
+ */
+ static void GetGammaLUTData(SkScalar contrast, SkScalar paintGamma, SkScalar deviceGamma,
+ void* data);
+
#ifdef SK_BUILD_FOR_ANDROID
unsigned getBaseGlyphCount(SkUnichar charCode);