enable color-luminance in font cache (disabled by default)
git-svn-id: http://skia.googlecode.com/svn/trunk@3168 2bbb7eff-a529-9590-31e7-b0007b416f81
This commit is contained in:
parent
4ebf2b4fd2
commit
ce6dbb6b4c
@ -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<SkMask::Format>(fMaskFormat);
|
||||
}
|
||||
|
||||
#ifdef USE_NEW_LUMINANCE
|
||||
unsigned getLuminanceBits() const {
|
||||
return fLumBits;
|
||||
#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;
|
||||
}
|
||||
|
||||
void setLuminanceBits(unsigned lum) {
|
||||
SkASSERT(lum <= kLuminance_Max);
|
||||
fLumBits = lum;
|
||||
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 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);
|
||||
|
@ -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);
|
||||
|
@ -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,6 +1808,7 @@ void SkFontHost::FilterRec(SkScalerContext::Rec* rec) {
|
||||
}
|
||||
rec->setLuminanceBits(lum);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (SkMask::kLCD16_Format == rec->fMaskFormat
|
||||
|| SkMask::kLCD32_Format == rec->fMaskFormat) {
|
||||
|
Loading…
Reference in New Issue
Block a user