suport A8 grayscale text with COLOR_LUMINANCE build option
git-svn-id: http://skia.googlecode.com/svn/trunk@3197 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/src/core/SkPaint.cpp b/src/core/SkPaint.cpp
index 86bc49e..3b9714e 100644
--- a/src/core/SkPaint.cpp
+++ b/src/core/SkPaint.cpp
@@ -1302,13 +1302,29 @@
return c;
}
+#define assert_byte(x) SkASSERT(0 == ((x) >> 8))
+
static U8CPU reduce_lumbits(U8CPU x) {
static const uint8_t gReduceBits[] = {
0x0, 0x55, 0xAA, 0xFF
};
+ assert_byte(x);
return gReduceBits[x >> 6];
}
+static unsigned computeLuminance(SkColor c) {
+ int r = SkColorGetR(c);
+ int g = SkColorGetG(c);
+ int b = SkColorGetB(c);
+ // compute luminance
+ // R=0.2126 G=0.7152 B=0.0722
+ // scaling by 127 yields 27, 92, 9
+ int luminance = r * 27 + g * 92 + b * 9;
+ luminance >>= 7;
+ assert_byte(luminance);
+ return luminance;
+}
+
#else
// returns 0..kLuminance_Max
static unsigned computeLuminance(const SkPaint& paint) {
@@ -1477,22 +1493,38 @@
*/
SkFontHost::FilterRec(rec);
- // No need to differentiate gamma if we're BW
- if (SkMask::kBW_Format == rec->fMaskFormat) {
+ switch (rec->fMaskFormat) {
+ case SkMask::kLCD16_Format:
+ case SkMask::kLCD32_Format: {
#ifdef SK_USE_COLOR_LUMINANCE
- rec->setLuminanceColor(0);
+ // filter down the luminance color to a finite number of bits
+ SkColor c = rec->getLuminanceColor();
+ c = SkColorSetRGB(reduce_lumbits(SkColorGetR(c)),
+ reduce_lumbits(SkColorGetG(c)),
+ reduce_lumbits(SkColorGetB(c)));
+ rec->setLuminanceColor(c);
+#endif
+ break;
+ }
+ case SkMask::kA8_Format: {
+#ifdef SK_USE_COLOR_LUMINANCE
+ // filter down the luminance to a single component, since A8 can't
+ // use per-component information
+ unsigned lum = computeLuminance(rec->getLuminanceColor());
+ // reduce to our finite number of bits
+ lum = reduce_lumbits(lum);
+ rec->setLuminanceColor(SkColorSetRGB(lum, lum, lum));
+#endif
+ break;
+ }
+ case SkMask::kBW_Format:
+ // No need to differentiate gamma if we're BW
+#ifdef SK_USE_COLOR_LUMINANCE
+ rec->setLuminanceColor(0);
#else
- rec->setLuminanceBits(0);
+ rec->setLuminanceBits(0);
#endif
- } else {
-#ifdef SK_USE_COLOR_LUMINANCE
- // filter down the luminance color to a finite number of bits
- SkColor c = rec->getLuminanceColor();
- c = SkColorSetRGB(reduce_lumbits(SkColorGetR(c)),
- reduce_lumbits(SkColorGetG(c)),
- reduce_lumbits(SkColorGetB(c)));
- rec->setLuminanceColor(c);
-#endif
+ break;
}
}
diff --git a/src/ports/SkFontHost_mac_coretext.cpp b/src/ports/SkFontHost_mac_coretext.cpp
index 19b91ad..e5fedc1 100644
--- a/src/ports/SkFontHost_mac_coretext.cpp
+++ b/src/ports/SkFontHost_mac_coretext.cpp
@@ -1081,6 +1081,28 @@
return isWhite ? gWhiteTable : gTable;
}
+static const uint8_t* getGammaTable(U8CPU luminance) {
+ static uint8_t gGammaTables[4][256];
+ static bool gInited;
+ if (!gInited) {
+#if 1
+ float start = 1.1;
+ float stop = 2.1;
+ for (int i = 0; i < 4; ++i) {
+ float g = start + (stop - start) * i / 3;
+ build_power_table(gGammaTables[i], 1/g);
+ }
+#else
+ build_power_table(gGammaTables[0], 1);
+ build_power_table(gGammaTables[1], 1);
+ build_power_table(gGammaTables[2], 1);
+ build_power_table(gGammaTables[3], 1);
+#endif
+ gInited = true;
+ }
+ SkASSERT(0 == (luminance >> 8));
+ return gGammaTables[luminance >> 6];
+}
static void invertGammaMask(bool isWhite, CGRGBPixel rgb[], int width,
int height, size_t rb) {
@@ -1197,9 +1219,18 @@
void SkScalerContext_Mac::generateImage(const SkGlyph& glyph) {
CGGlyph cgGlyph = (CGGlyph) glyph.getGlyphID(fBaseGlyphCount);
+ const bool isLCD = isLCDFormat(glyph.fMaskFormat);
+ const bool isBW = SkMask::kBW_Format == glyph.fMaskFormat;
+ const bool isA8 = !isLCD && !isBW;
+
#ifdef SK_USE_COLOR_LUMINANCE
unsigned lumBits = fRec.getLuminanceColor();
uint32_t xorMask = 0;
+
+ if (isA8) {
+ // for A8, we just want a component (they're all the same)
+ lumBits = SkColorGetR(lumBits);
+ }
#else
bool fgColorIsWhite = true;
bool isWhite = fRec.getLuminanceByte() >= WHITE_LUMINANCE_LIMIT;
@@ -1212,7 +1243,7 @@
* extract the r,g,b values, invert-them, and now we have the original
* src mask components, which we pack into our 16bit mask.
*/
- if (isLCDFormat(glyph.fMaskFormat)) {
+ if (isLCD) {
if (isBlack) {
xorMask = ~0;
fgColorIsWhite = false;
@@ -1226,19 +1257,15 @@
size_t cgRowBytes;
#ifdef SK_USE_COLOR_LUMINANCE
CGRGBPixel* cgPixels;
+ const uint8_t* gammaTable = NULL;
- // If we're gray or lum==max, we just want WHITE
- // If lum is 0 we just want BLACK
- // Else lerp
-
- {
- bool isLCD = isLCDFormat(glyph.fMaskFormat);
+ if (isLCD) {
CGRGBPixel* wtPixels = NULL;
CGRGBPixel* bkPixels = NULL;
bool needBlack = true;
bool needWhite = true;
- if (!isLCD || (SK_ColorWHITE == lumBits)) {
+ if (SK_ColorWHITE == lumBits) {
needBlack = false;
} else if (SK_ColorBLACK == lumBits) {
needWhite = false;
@@ -1257,11 +1284,12 @@
if (wtPixels && bkPixels) {
lerpPixels(wtPixels, bkPixels, glyph.fWidth, glyph.fHeight, cgRowBytes,
-#ifdef SK_USE_COLOR_LUMINANCE
~lumBits);
-#else
- SkScalerContext::kLuminance_Max - lumBits);
-#endif
+ }
+ } else { // isA8 or isBW
+ cgPixels = fWhiteScreen.getCG(*this, glyph, true, cgGlyph, &cgRowBytes);
+ if (isA8) {
+ gammaTable = getGammaTable(lumBits);
}
}
#else
@@ -1310,7 +1338,11 @@
size_t dstRB = glyph.rowBytes();
for (int y = 0; y < glyph.fHeight; y++) {
for (int i = 0; i < width; ++i) {
- dst[i] = CGRGBPixel_getAlpha(cgPixels[i]);
+ unsigned alpha8 = CGRGBPixel_getAlpha(cgPixels[i]);
+#ifdef SK_USE_COLOR_LUMINANCE
+ alpha8 = gammaTable[alpha8];
+#endif
+ dst[i] = alpha8;
}
cgPixels = (CGRGBPixel*)((char*)cgPixels + cgRowBytes);
dst += dstRB;
@@ -1801,7 +1833,7 @@
rec->setHinting(h);
#ifdef SK_USE_COLOR_LUMINANCE
- {
+ if (isLCDFormat(rec->fMaskFormat)) {
SkColor c = rec->getLuminanceColor();
// apply our chosen scaling between Black and White cg output
int r = SkColorGetR(c)*2/3;