aboutsummaryrefslogtreecommitdiffhomepage
path: root/src
diff options
context:
space:
mode:
authorGravatar reed@google.com <reed@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81>2011-11-22 19:42:41 +0000
committerGravatar reed@google.com <reed@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81>2011-11-22 19:42:41 +0000
commitffe49f5380dd5062073efeda70f2f91682c828ca (patch)
treea36192068d5ae373e938b3bb9ac978ef5083f27f /src
parent8caac6447dd68655b57dfe876626a9733b191416 (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.cpp37
-rw-r--r--src/ports/SkFontHost_FreeType.cpp55
-rw-r--r--src/ports/SkFontHost_mac_coretext.cpp22
-rwxr-xr-xsrc/ports/SkFontHost_win.cpp28
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