aboutsummaryrefslogtreecommitdiffhomepage
path: root/src
diff options
context:
space:
mode:
authorGravatar reed@google.com <reed@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81>2012-02-10 22:01:45 +0000
committerGravatar reed@google.com <reed@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81>2012-02-10 22:01:45 +0000
commitce6dbb6b4ce3f36e0a2245b215dc48b68df35c41 (patch)
tree00a3201b5f2e51ca07f85e25c61aa847db8673af /src
parent4ebf2b4fd20e973edb38668acb6f208afa51cd05 (diff)
enable color-luminance in font cache (disabled by default)
git-svn-id: http://skia.googlecode.com/svn/trunk@3168 2bbb7eff-a529-9590-31e7-b0007b416f81
Diffstat (limited to 'src')
-rw-r--r--src/core/SkPaint.cpp22
-rw-r--r--src/ports/SkFontHost_mac_coretext.cpp107
2 files changed, 126 insertions, 3 deletions
diff --git a/src/core/SkPaint.cpp b/src/core/SkPaint.cpp
index 7d418f4b1c..4026acbae4 100644
--- a/src/core/SkPaint.cpp
+++ b/src/core/SkPaint.cpp
@@ -1293,6 +1293,15 @@ static bool justAColor(const SkPaint& paint, SkColor* color) {
return true;
}
+#ifdef SK_USE_COLOR_LUMINANCE
+static SkColor computeLuminanceColor(const SkPaint& paint) {
+ SkColor c;
+ if (!justAColor(paint, &c)) {
+ c = SkColorSetRGB(0x7F, 0x80, 0x7F);
+ }
+ return c;
+}
+#else
// returns 0..kLuminance_Max
static unsigned computeLuminance(const SkPaint& paint) {
SkColor c;
@@ -1316,6 +1325,7 @@ static unsigned computeLuminance(const SkPaint& paint) {
// if we're not a single color, return the middle of the luminance range
return SkScalerContext::kLuminance_Max >> 1;
}
+#endif
// Beyond this size, LCD doesn't appreciably improve quality, but it always
// cost more RAM and draws slower, so we set a cap.
@@ -1446,7 +1456,11 @@ void SkScalerContext::MakeRec(const SkPaint& paint,
// these modify fFlags, so do them after assigning fFlags
rec->setHinting(computeHinting(paint));
+#ifdef SK_USE_COLOR_LUMINANCE
+ rec->setLuminanceColor(computeLuminanceColor(paint));
+#else
rec->setLuminanceBits(computeLuminance(paint));
+#endif
/* Allow the fonthost to modify our rec before we use it as a key into the
cache. This way if we're asking for something that they will ignore,
@@ -1457,7 +1471,11 @@ void SkScalerContext::MakeRec(const SkPaint& paint,
// No need to differentiate gamma if we're BW
if (SkMask::kBW_Format == rec->fMaskFormat) {
+#ifdef SK_USE_COLOR_LUMINANCE
+ rec->setLuminanceColor(0);
+#else
rec->setLuminanceBits(0);
+#endif
}
}
@@ -1481,7 +1499,11 @@ void SkPaint::descriptorProc(const SkMatrix* deviceMatrix,
SkScalerContext::MakeRec(*this, deviceMatrix, &rec);
if (ignoreGamma) {
+#ifdef SK_USE_COLOR_LUMINANCE
+ rec.setLuminanceColor(0);
+#else
rec.setLuminanceBits(0);
+#endif
}
size_t descSize = sizeof(rec);
diff --git a/src/ports/SkFontHost_mac_coretext.cpp b/src/ports/SkFontHost_mac_coretext.cpp
index 9c69ed7043..0500508383 100644
--- a/src/ports/SkFontHost_mac_coretext.cpp
+++ b/src/ports/SkFontHost_mac_coretext.cpp
@@ -132,7 +132,7 @@ static void sk_memset_rect(void* ptr, U8CPU byte, size_t width, size_t height,
typedef uint32_t CGRGBPixel;
static unsigned CGRGBPixel_getAlpha(CGRGBPixel pixel) {
- return pixel >> 24;
+ return pixel & 0xFF;
}
// The calls to support subpixel are present in 10.5, but are not included in
@@ -593,7 +593,12 @@ private:
SkMatrix fVerticalMatrix; // unit rotated
SkMatrix fMatrix; // with font size
SkMatrix fAdjustBadMatrix; // lion-specific fix
+#ifdef SK_USE_COLOR_LUMINANCE
+ Offscreen fBlackScreen;
+ Offscreen fWhiteScreen;
+#else
Offscreen fOffscreen;
+#endif
CTFontRef fCTFont;
CTFontRef fCTVerticalFont; // for vertical advance
CGFontRef fCGFont;
@@ -1052,7 +1057,7 @@ static void build_power_table(uint8_t table[], float ee) {
for (int i = 0; i < 256; i++) {
float x = i / 255.f;
x = powf(x, ee);
- int xx = SkScalarRound(SkFloatToScalar(x * 255));
+ int xx = SkScalarRoundToInt(SkFloatToScalar(x * 255));
table[i] = SkToU8(xx);
}
}
@@ -1069,6 +1074,7 @@ static const uint8_t* getInverseTable(bool isWhite) {
return isWhite ? gWhiteTable : gTable;
}
+
static void invertGammaMask(bool isWhite, CGRGBPixel rgb[], int width,
int height, size_t rb) {
const uint8_t* table = getInverseTable(isWhite);
@@ -1097,6 +1103,49 @@ static void cgpixels_to_bits(uint8_t dst[], const CGRGBPixel src[], int count) {
}
}
+static int lerpScale(int dst, int src, int scale) {
+ return dst + (scale * (src - dst) >> 23);
+}
+
+static CGRGBPixel lerpPixel(CGRGBPixel dst, CGRGBPixel src,
+ int scaleR, int scaleG, int scaleB) {
+ int sr = (src >> 16) & 0xFF;
+ int sg = (src >> 8) & 0xFF;
+ int sb = (src >> 0) & 0xFF;
+ int dr = (dst >> 16) & 0xFF;
+ int dg = (dst >> 8) & 0xFF;
+ int db = (dst >> 0) & 0xFF;
+
+ int rr = lerpScale(dr, sr, scaleR);
+ int rg = lerpScale(dg, sg, scaleG);
+ int rb = lerpScale(db, sb, scaleB);
+ return (rr << 16) | (rg << 8) | rb;
+}
+
+static void lerpPixels(CGRGBPixel dst[], const CGRGBPixel src[], int width,
+ int height, int rowBytes, int lumBits) {
+#ifdef SK_USE_COLOR_LUMINANCE
+ int scaleR = (1 << 23) * SkColorGetR(lumBits) / 0xFF;
+ int scaleG = (1 << 23) * SkColorGetG(lumBits) / 0xFF;
+ int scaleB = (1 << 23) * SkColorGetB(lumBits) / 0xFF;
+#else
+ int scale = (1 << 23) * lumBits / SkScalerContext::kLuminance_Max;
+ int scaleR = scale;
+ int scaleG = scale;
+ int scaleB = scale;
+#endif
+
+ for (int y = 0; y < height; ++y) {
+ for (int x = 0; x < width; ++x) {
+ // bit-not the src, since it was drawn from black, so we need the
+ // compliment of those bits
+ dst[x] = lerpPixel(dst[x], ~src[x], scaleR, scaleG, scaleB);
+ }
+ src = (CGRGBPixel*)((char*)src + rowBytes);
+ dst = (CGRGBPixel*)((char*)dst + rowBytes);
+ }
+}
+
#if 1
static inline int r32_to_16(int x) { return SkR32ToR16(x); }
static inline int g32_to_16(int x) { return SkG32ToG16(x); }
@@ -1141,6 +1190,10 @@ static inline uint32_t rgb_to_lcd32(CGRGBPixel rgb) {
void SkScalerContext_Mac::generateImage(const SkGlyph& glyph) {
CGGlyph cgGlyph = (CGGlyph) glyph.getGlyphID(fBaseGlyphCount);
+#ifdef SK_USE_COLOR_LUMINANCE
+ unsigned lumBits = fRec.getLuminanceColor();
+ uint32_t xorMask = 0;
+#else
bool fgColorIsWhite = true;
bool isWhite = fRec.getLuminanceByte() >= WHITE_LUMINANCE_LIMIT;
bool isBlack = fRec.getLuminanceByte() <= BLACK_LUMINANCE_LIMIT;
@@ -1161,18 +1214,64 @@ void SkScalerContext_Mac::generateImage(const SkGlyph& glyph) {
invertGamma = true;
}
}
+#endif
size_t cgRowBytes;
+#ifdef SK_USE_COLOR_LUMINANCE
+ CGRGBPixel* cgPixels;
+
+ // 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);
+ CGRGBPixel* wtPixels = NULL;
+ CGRGBPixel* bkPixels = NULL;
+ bool needBlack = true;
+ bool needWhite = true;
+
+ if (!isLCD || (SK_ColorWHITE == lumBits)) {
+ needBlack = false;
+ } else if (SK_ColorBLACK == lumBits) {
+ needWhite = false;
+ }
+
+ if (needBlack) {
+ bkPixels = fBlackScreen.getCG(*this, glyph, false, cgGlyph, &cgRowBytes);
+ cgPixels = bkPixels;
+ xorMask = ~0;
+ }
+ if (needWhite) {
+ wtPixels = fWhiteScreen.getCG(*this, glyph, true, cgGlyph, &cgRowBytes);
+ cgPixels = wtPixels;
+ xorMask = 0;
+ }
+
+ if (wtPixels && bkPixels) {
+ lerpPixels(wtPixels, bkPixels, glyph.fWidth, glyph.fHeight, cgRowBytes,
+#ifdef SK_USE_COLOR_LUMINANCE
+ ~lumBits);
+#else
+ SkScalerContext::kLuminance_Max - lumBits);
+#endif
+ }
+ }
+#else
CGRGBPixel* cgPixels = fOffscreen.getCG(*this, glyph, fgColorIsWhite, cgGlyph,
&cgRowBytes);
+#endif
// Draw the glyph
if (cgPixels != NULL) {
+#ifdef SK_USE_COLOR_LUMINANCE
+#else
if (invertGamma) {
invertGammaMask(isWhite, (uint32_t*)cgPixels,
glyph.fWidth, glyph.fHeight, cgRowBytes);
}
+#endif
int width = glyph.fWidth;
switch (glyph.fMaskFormat) {
@@ -1697,6 +1796,7 @@ void SkFontHost::FilterRec(SkScalerContext::Rec* rec) {
// for compatibility at the moment, discretize luminance to 3 settings
// black, white, gray. This helps with fontcache utilization, since we
// won't create multiple entries that in the end map to the same results.
+#ifndef SK_USE_COLOR_LUMINANCE
{
unsigned lum = rec->getLuminanceByte();
if (lum <= BLACK_LUMINANCE_LIMIT) {
@@ -1708,7 +1808,8 @@ void SkFontHost::FilterRec(SkScalerContext::Rec* rec) {
}
rec->setLuminanceBits(lum);
}
-
+#endif
+
if (SkMask::kLCD16_Format == rec->fMaskFormat
|| SkMask::kLCD32_Format == rec->fMaskFormat) {
if (supports_LCD()) {