diff options
author | reed@google.com <reed@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81> | 2011-11-22 19:42:41 +0000 |
---|---|---|
committer | reed@google.com <reed@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81> | 2011-11-22 19:42:41 +0000 |
commit | ffe49f5380dd5062073efeda70f2f91682c828ca (patch) | |
tree | a36192068d5ae373e938b3bb9ac978ef5083f27f /src | |
parent | 8caac6447dd68655b57dfe876626a9733b191416 (diff) |
store 3 bits of luminance, but (for now) discretize that in fonthost::filterec
for backward compatibility
git-svn-id: http://skia.googlecode.com/svn/trunk@2732 2bbb7eff-a529-9590-31e7-b0007b416f81
Diffstat (limited to 'src')
-rw-r--r-- | src/core/SkPaint.cpp | 37 | ||||
-rw-r--r-- | src/ports/SkFontHost_FreeType.cpp | 55 | ||||
-rw-r--r-- | src/ports/SkFontHost_mac_coretext.cpp | 22 | ||||
-rwxr-xr-x | src/ports/SkFontHost_win.cpp | 28 |
4 files changed, 101 insertions, 41 deletions
diff --git a/src/core/SkPaint.cpp b/src/core/SkPaint.cpp index e89e281406..5f5514dbe7 100644 --- a/src/core/SkPaint.cpp +++ b/src/core/SkPaint.cpp @@ -1076,7 +1076,7 @@ SkScalar SkPaint::getFontMetrics(FontMetrics* metrics, SkScalar zoom) const { metrics = &storage; } - this->descriptorProc(zoomPtr, FontMetricsDescProc, metrics); + this->descriptorProc(zoomPtr, FontMetricsDescProc, metrics, true); if (scale) { metrics->fTop = SkScalarMul(metrics->fTop, scale); @@ -1283,24 +1283,21 @@ static bool justAColor(const SkPaint& paint, SkColor* color) { } // returns 0..kLuminance_Max -static unsigned computeGammaFlag(const SkPaint& paint) { +static unsigned computeLuminance(const SkPaint& paint) { SkColor c; if (justAColor(paint, &c)) { int r = SkColorGetR(c); int g = SkColorGetG(c); int b = SkColorGetB(c); // compute luminance to 11 bits (0..0x3F) - int luminance = r * 2 + g * 5 + b >> 3; - - if (luminance <= 0x40) { - return SkScalerContext::kGammaForBlack_Flag; - } - if (luminance >= 0xA0) { - return SkScalerContext::kGammaForWhite_Flag; - } + int luminance = r * 2 + g * 5 + b; + SkASSERT(luminance <= 0x7FF); + luminance >>= 11 - SkScalerContext::kLuminance_Bits; + SkASSERT(luminance <= SkScalerContext::kLuminance_Max); + return luminance; } // if we're not a single color, return the middle of the luminance range - return 0; + return SkScalerContext::kLuminance_Max >> 1; } // Beyond this size, LCD doesn't appreciably improve quality, but it always @@ -1354,7 +1351,7 @@ void SkScalerContext::MakeRec(const SkPaint& paint, SkPaint::Style style = paint.getStyle(); SkScalar strokeWidth = paint.getStrokeWidth(); - unsigned flags = computeGammaFlag(paint); + unsigned flags = 0; if (paint.isFakeBoldText()) { #ifdef SK_USE_FREETYPE_EMBOLDEN @@ -1427,8 +1424,9 @@ void SkScalerContext::MakeRec(const SkPaint& paint, } rec->fFlags = SkToU16(flags); - // setHinting modifies fFlags, so do this last + // these modify fFlags, so do them after assigning fFlags rec->setHinting(computeHinting(paint)); + rec->setLuminanceBits(computeLuminance(paint)); /* 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, @@ -1439,8 +1437,7 @@ void SkScalerContext::MakeRec(const SkPaint& paint, // No need to differentiate gamma if we're BW if (SkMask::kBW_Format == rec->fMaskFormat) { - rec->fFlags &= ~(SkScalerContext::kGammaForBlack_Flag | - SkScalerContext::kGammaForWhite_Flag); + rec->setLuminanceBits(0); } } @@ -1450,6 +1447,13 @@ void SkScalerContext::MakeRec(const SkPaint& paint, #define TEST_DESC #endif +/* + * 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. + */ void SkPaint::descriptorProc(const SkMatrix* deviceMatrix, void (*proc)(const SkDescriptor*, void*), void* context, bool ignoreGamma) const { @@ -1457,8 +1461,7 @@ void SkPaint::descriptorProc(const SkMatrix* deviceMatrix, SkScalerContext::MakeRec(*this, deviceMatrix, &rec); if (ignoreGamma) { - rec.fFlags &= ~(SkScalerContext::kGammaForBlack_Flag | - SkScalerContext::kGammaForWhite_Flag); + rec.setLuminanceBits(0); } size_t descSize = sizeof(rec); diff --git a/src/ports/SkFontHost_FreeType.cpp b/src/ports/SkFontHost_FreeType.cpp index 4bc7870f9c..6ac81f47af 100644 --- a/src/ports/SkFontHost_FreeType.cpp +++ b/src/ports/SkFontHost_FreeType.cpp @@ -95,6 +95,8 @@ static SkFaceRec* gFaceRecHead; static bool gLCDSupportValid; // true iff |gLCDSupport| has been set. static bool gLCDSupport; // true iff LCD is supported by the runtime. +static const uint8_t* gGammaTables[2]; + ///////////////////////////////////////////////////////////////////////// // See http://freetype.sourceforge.net/freetype2/docs/reference/ft2-bitmap_handling.html#FT_Bitmap_Embolden @@ -601,6 +603,9 @@ SkAdvancedTypefaceMetrics* SkFontHost::GetAdvancedTypefaceMetrics( /////////////////////////////////////////////////////////////////////////// +#define BLACK_LUMINANCE_LIMIT 0x40 +#define WHITE_LUMINANCE_LIMIT 0xA0 + static bool bothZero(SkScalar a, SkScalar b) { return 0 == a && 0 == b; } @@ -640,6 +645,26 @@ void SkFontHost::FilterRec(SkScalerContext::Rec* rec) { } #endif rec->setHinting(h); + + // 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. + { + unsigned lum = rec->getLuminanceByte(); + if (gGammaTables[0] || gGammaTables[1]) { + if (lum <= BLACK_LUMINANCE_LIMIT) { + lum = 0; + } else if (lum >= WHITE_LUMINANCE_LIMIT) { + lum = SkScalerContext::kLuminance_Max; + } else { + lum = SkScalerContext::kLuminance_Max >> 1; + } + } else { + lum = 0; // no gamma correct, so use 0 since SkPaint uses that + // when measuring text w/o regard for luminance + } + rec->setLuminanceBits(lum); + } } #ifdef SK_BUILD_FOR_ANDROID @@ -665,6 +690,7 @@ SkScalerContext_FreeType::SkScalerContext_FreeType(const SkDescriptor* desc) if (!InitFreetype()) { sk_throw(); } + SkFontHost::GetGammaTables(gGammaTables); } ++gFTCount; @@ -1230,21 +1256,22 @@ void SkScalerContext_FreeType::generateImage(const SkGlyph& glyph) { goto ERROR; } - if ((fRec.fFlags & (kGammaForBlack_Flag | kGammaForBlack_Flag)) && - SkMask::kA8_Format == glyph.fMaskFormat) { - const uint8_t* tables[2]; - SkFontHost::GetGammaTables(tables); - int index = (fRec.fFlags & kGammaForBlack_Flag) ? 0 : 1; - if (tables[index]) { - const uint8_t* SK_RESTRICT table = tables[index]; - uint8_t* SK_RESTRICT dst = (uint8_t*)glyph.fImage; - unsigned rowBytes = glyph.rowBytes(); - - for (int y = glyph.fHeight - 1; y >= 0; --y) { - for (int x = glyph.fWidth - 1; x >= 0; --x) { - dst[x] = table[dst[x]]; + if (gGammaTables[0] || gGammaTables[1]) { + bool isWhite = fRec.getLuminanceByte() >= WHITE_LUMINANCE_LIMIT; + bool isBlack = fRec.getLuminanceByte() <= BLACK_LUMINANCE_LIMIT; + if ((isWhite | isBlack) && SkMask::kA8_Format == glyph.fMaskFormat) { + int index = isBlack ? 0 : 1; + if (gGammaTables[index]) { + const uint8_t* SK_RESTRICT table = gGammaTables[index]; + uint8_t* SK_RESTRICT dst = (uint8_t*)glyph.fImage; + unsigned rowBytes = glyph.rowBytes(); + + for (int y = glyph.fHeight - 1; y >= 0; --y) { + for (int x = glyph.fWidth - 1; x >= 0; --x) { + dst[x] = table[dst[x]]; + } + dst += rowBytes; } - dst += rowBytes; } } } diff --git a/src/ports/SkFontHost_mac_coretext.cpp b/src/ports/SkFontHost_mac_coretext.cpp index 866721e0dd..b125265f40 100644 --- a/src/ports/SkFontHost_mac_coretext.cpp +++ b/src/ports/SkFontHost_mac_coretext.cpp @@ -1099,12 +1099,15 @@ static inline uint32_t rgb_to_lcd32(CGRGBPixel rgb) { return SkPackARGB32(0xFF, r, g, b); } +#define BLACK_LUMINANCE_LIMIT 0x40 +#define WHITE_LUMINANCE_LIMIT 0xA0 + void SkScalerContext_Mac::generateImage(const SkGlyph& glyph) { CGGlyph cgGlyph = (CGGlyph) glyph.getGlyphID(fBaseGlyphCount); bool fgColorIsWhite = true; - bool isBlack = SkToBool(fRec.fFlags & SkScalerContext::kGammaForBlack_Flag); - bool isWhite = SkToBool(fRec.fFlags & SkScalerContext::kGammaForWhite_Flag); + bool isWhite = fRec.getLuminanceByte() >= WHITE_LUMINANCE_LIMIT; + bool isBlack = fRec.getLuminanceByte() <= BLACK_LUMINANCE_LIMIT; uint32_t xorMask; bool invertGamma = false; @@ -1662,6 +1665,21 @@ void SkFontHost::FilterRec(SkScalerContext::Rec* rec) { } rec->setHinting(h); + // 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. + { + unsigned lum = rec->getLuminanceByte(); + if (lum <= BLACK_LUMINANCE_LIMIT) { + lum = 0; + } else if (lum >= WHITE_LUMINANCE_LIMIT) { + lum = SkScalerContext::kLuminance_Max; + } else { + lum = SkScalerContext::kLuminance_Max >> 1; + } + rec->setLuminanceBits(lum); + } + if (SkMask::kLCD16_Format == rec->fMaskFormat || SkMask::kLCD32_Format == rec->fMaskFormat) { if (supports_LCD()) { diff --git a/src/ports/SkFontHost_win.cpp b/src/ports/SkFontHost_win.cpp index 141cb41247..87f894cb70 100755 --- a/src/ports/SkFontHost_win.cpp +++ b/src/ports/SkFontHost_win.cpp @@ -853,6 +853,9 @@ static inline unsigned clamp255(unsigned x) { return x - (x >> 8); } +#define WHITE_LUMINANCE_LIMIT 0xA0 +#define BLACK_LUMINANCE_LIMIT 0x40 + void SkScalerContext_Windows::generateImage(const SkGlyph& glyph) { SkAutoMutexAcquire ac(gFTMutex); @@ -860,9 +863,8 @@ void SkScalerContext_Windows::generateImage(const SkGlyph& glyph) { const bool isBW = SkMask::kBW_Format == fRec.fMaskFormat; const bool isAA = !isLCD(fRec); - - bool isWhite = SkToBool(fRec.fFlags & SkScalerContext::kGammaForWhite_Flag); - bool isBlack = SkToBool(fRec.fFlags & SkScalerContext::kGammaForBlack_Flag); + bool isWhite = fRec.getLuminanceByte() >= WHITE_LUMINANCE_LIMIT; + bool isBlack = fRec.getLuminanceByte() <= BLACK_LUMINANCE_LIMIT; SkASSERT(!(isWhite && isBlack)); SkASSERT(!isBW || (!isWhite && !isBlack)); @@ -1302,6 +1304,21 @@ void SkFontHost::FilterRec(SkScalerContext::Rec* rec) { #endif rec->setHinting(h); + // 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. + { + unsigned lum = rec->getLuminanceByte(); + if (lum <= BLACK_LUMINANCE_LIMIT) { + lum = 0; + } else if (lum >= WHITE_LUMINANCE_LIMIT) { + lum = SkScalerContext::kLuminance_Max; + } else { + lum = SkScalerContext::kLuminance_Max >> 1; + } + rec->setLuminanceBits(lum); + } + // turn this off since GDI might turn A8 into BW! Need a bigger fix. #if 0 // Disable LCD when rotated, since GDI's output is ugly @@ -1315,11 +1332,6 @@ void SkFontHost::FilterRec(SkScalerContext::Rec* rec) { rec->fMaskFormat = SkMask::kLCD32_Format; } #endif - // don't specify gamma if we BW (perhaps caller should do this check) - if (SkMask::kBW_Format == rec->fMaskFormat) { - rec->fFlags &= ~(SkScalerContext::kGammaForBlack_Flag | - SkScalerContext::kGammaForWhite_Flag); - } } #endif // WIN32 |