From: reed@google.com Date: Fri, 10 Feb 2012 22:01:45 +0000 (+0000) Subject: enable color-luminance in font cache (disabled by default) X-Git-Tag: accepted/tizen/5.0/unified/20181102.025319~16857 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=ce6dbb6b4ce3f36e0a2245b215dc48b68df35c41;p=platform%2Fupstream%2FlibSkiaSharp.git enable color-luminance in font cache (disabled by default) git-svn-id: http://skia.googlecode.com/svn/trunk@3168 2bbb7eff-a529-9590-31e7-b0007b416f81 --- diff --git a/include/core/SkScalerContext.h b/include/core/SkScalerContext.h index b2f6a57..7a83bd7 100644 --- a/include/core/SkScalerContext.h +++ b/include/core/SkScalerContext.h @@ -16,6 +16,9 @@ #include "SkPath.h" #include "SkPoint.h" +//#define SK_USE_COLOR_LUMINANCE +//#define USE_FULL_LUMI + class SkDescriptor; class SkMaskFilter; class SkPathEffect; @@ -154,8 +157,6 @@ struct SkGlyph { void toMask(SkMask* mask) const; }; -//#define USE_NEW_LUMINANCE - class SkScalerContext { public: enum Flags { @@ -181,7 +182,7 @@ public: // Perhaps we can store this (instead) in fMaskFormat, in hight bit? kGenA8FromLCD_Flag = 0x0800, -#ifdef USE_NEW_LUMINANCE +#ifdef SK_USE_COLOR_LUMINANCE kLuminance_Bits = 3, #else // luminance : 0 for black text, kLuminance_Max for white text @@ -193,8 +194,9 @@ public: // computed values enum { kHinting_Mask = kHintingBit1_Flag | kHintingBit2_Flag, +#ifdef SK_USE_COLOR_LUMINANCE +#else kLuminance_Max = (1 << kLuminance_Bits) - 1, -#ifndef USE_NEW_LUMINANCE kLuminance_Mask = kLuminance_Max << kLuminance_Shift, #endif }; @@ -205,7 +207,7 @@ public: SkScalar fTextSize, fPreScaleX, fPreSkewX; SkScalar fPost2x2[2][2]; SkScalar fFrameWidth, fMiterLimit; -#ifdef USE_NEW_LUMINANCE +#ifdef SK_USE_COLOR_LUMINANCE uint32_t fLumBits; #endif uint8_t fMaskFormat; @@ -233,14 +235,35 @@ public: return static_cast(fMaskFormat); } -#ifdef USE_NEW_LUMINANCE - unsigned getLuminanceBits() const { +#ifdef SK_USE_COLOR_LUMINANCE + static unsigned ColorToLumBits(U8CPU x) { + SkASSERT(x <= 0xFF); + return x >> 7; + } + static U8CPU LumBitsToColor(unsigned x) { + SkASSERT(x <= 1); + return x * 0xFF; + } + + SkColor getLuminanceColor() const { +#ifdef USE_FULL_LUMI return fLumBits; +#else + unsigned bits = fLumBits; + return SkColorSetRGB(LumBitsToColor((bits >> 2) & 1), + LumBitsToColor((bits >> 1) & 1), + LumBitsToColor((bits >> 0) & 1)); +#endif } - void setLuminanceBits(unsigned lum) { - SkASSERT(lum <= kLuminance_Max); - fLumBits = lum; + void setLuminanceColor(SkColor c) { +#ifdef USE_FULL_LUMI + fLumBits = c; +#else + fLumBits = (ColorToLumBits(SkColorGetR(c)) << 2) | + (ColorToLumBits(SkColorGetG(c)) << 1) | + (ColorToLumBits(SkColorGetB(c)) << 0); +#endif } #else unsigned getLuminanceBits() const { @@ -251,7 +274,6 @@ public: SkASSERT(lum <= kLuminance_Max); fFlags = (fFlags & ~kLuminance_Mask) | (lum << kLuminance_Shift); } -#endif U8CPU getLuminanceByte() const { SkASSERT(3 == kLuminance_Bits); @@ -260,6 +282,7 @@ public: lum |= (lum << kLuminance_Bits*2); return lum >> (4*kLuminance_Bits - 8); } +#endif }; SkScalerContext(const SkDescriptor* desc); diff --git a/src/core/SkPaint.cpp b/src/core/SkPaint.cpp index 7d418f4..4026acb 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 9c69ed7..0500508 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()) {