aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorGravatar bungeman@google.com <bungeman@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81>2012-08-24 17:46:11 +0000
committerGravatar bungeman@google.com <bungeman@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81>2012-08-24 17:46:11 +0000
commitfd668cfffe3fdcfbf6e0b858343a62818d337590 (patch)
tree593fd990decefe58cb80b4f1cf4aa7d397f8d0ec
parent0032407e294aecc9306e1610c0cf0d998c9a5cfe (diff)
Fix greenish text rendering on Linux.
-rw-r--r--gyp/core.gyp1
-rw-r--r--gyp/ports.gyp17
-rw-r--r--src/core/SkMaskGamma.cpp9
-rw-r--r--src/core/SkPaint.cpp7
-rw-r--r--src/core/SkScalerContext.h5
-rw-r--r--src/ports/SkFontHost_FreeType.cpp51
6 files changed, 72 insertions, 18 deletions
diff --git a/gyp/core.gyp b/gyp/core.gyp
index 47a46ac3b8..806626a53d 100644
--- a/gyp/core.gyp
+++ b/gyp/core.gyp
@@ -27,7 +27,6 @@
],
'link_settings': {
'libraries': [
- '-lfreetype',
'-lpthread',
],
},
diff --git a/gyp/ports.gyp b/gyp/ports.gyp
index 34c0540d75..f070ac600e 100644
--- a/gyp/ports.gyp
+++ b/gyp/ports.gyp
@@ -37,12 +37,23 @@
],
'conditions': [
[ 'skia_os in ["linux", "freebsd", "openbsd", "solaris"]', {
+ 'defines': [
+ #The font host requires at least FreeType 2.3.0 at runtime.
+ 'SK_FONTHOST_FREETYPE_RUNTIME_VERSION=0x020300',
+ 'SK_CAN_USE_DLOPEN=1',
+ ],
'sources': [
'../src/ports/SkThread_pthread.cpp',
'../src/ports/SkFontHost_FreeType.cpp',
'../src/ports/SkFontHost_FreeType_common.cpp',
'../src/ports/SkFontHost_linux.cpp',
],
+ 'link_settings': {
+ 'libraries': [
+ '-lfreetype',
+ '-ldl',
+ ],
+ },
}],
[ 'skia_os == "mac"', {
'include_dirs': [
@@ -100,6 +111,12 @@
],
}],
[ 'skia_os == "android"', {
+ 'defines': [
+ #Android provides at least FreeType 2.4.0 at runtime.
+ 'SK_FONTHOST_FREETYPE_RUNTIME_VERSION=0x020400',
+ #Skia should not use dlopen on Android.
+ 'SK_CAN_USE_DLOPEN=0',
+ ],
'sources!': [
'../src/ports/SkDebug_stdio.cpp',
],
diff --git a/src/core/SkMaskGamma.cpp b/src/core/SkMaskGamma.cpp
index 47903fbdbb..449a78de93 100644
--- a/src/core/SkMaskGamma.cpp
+++ b/src/core/SkMaskGamma.cpp
@@ -53,9 +53,12 @@ void SkTMaskGamma_build_correcting_lut(uint8_t table[256], U8CPU srcI, SkScalar
const SkColorSpaceLuminance& dstConvert) {
const float src = (float)srcI / 255.0f;
const float linSrc = srcConvert.toLuma(src);
- //Guess at the dst.
- const float linDst = 1.0f - linSrc;
- const float dst = dstConvert.fromLuma(linDst);
+ //Guess at the dst. The perceptual inverse provides smaller visual
+ //discontinuities when slight changes to desaturated colors cause a channel
+ //to map to a different correcting lut with neighboring srcI.
+ //See https://code.google.com/p/chromium/issues/detail?id=141425#c59 .
+ const float dst = 1.0f - src;
+ const float linDst = dstConvert.toLuma(dst);
//Contrast value tapers off to 0 as the src luminance becomes white
const float adjustedContrast = SkScalarToFloat(contrast) * linDst;
diff --git a/src/core/SkPaint.cpp b/src/core/SkPaint.cpp
index 9c810be214..6ea03b4c8e 100644
--- a/src/core/SkPaint.cpp
+++ b/src/core/SkPaint.cpp
@@ -1706,8 +1706,11 @@ void SkScalerContext::PostMakeRec(const SkPaint& paint, SkScalerContext::Rec* re
SkColor color = rec->getLuminanceColor();
SkAutoMutexAcquire ama(gMaskGammaCacheMutex);
U8CPU lum = cachedPaintLuminance(rec->getPaintGamma())->computeLuminance(color);
- // HACK: Prevents green from being pre-blended as white.
- lum -= ((255 - lum) * lum) / 255;
+ //If we are asked to look like LCD, look like LCD.
+ if (!(rec->fFlags & SkScalerContext::kGenA8FromLCD_Flag)) {
+ // HACK: Prevents green from being pre-blended as white.
+ lum -= ((255 - lum) * lum) / 255;
+ }
// reduce to our finite number of bits
SkMaskGamma* maskGamma = cachedMaskGamma(rec->getContrast(),
diff --git a/src/core/SkScalerContext.h b/src/core/SkScalerContext.h
index 085e31d959..2443aafe6e 100644
--- a/src/core/SkScalerContext.h
+++ b/src/core/SkScalerContext.h
@@ -108,8 +108,9 @@ struct SkScalerContextRec {
//The following typedef hides from the rest of the implementation the number of
//most significant bits to consider when creating mask gamma tables. Two bits
//per channel was chosen as a balance between fidelity (more bits) and cache
-//sizes (fewer bits).
-typedef SkTMaskGamma<2, 2, 2> SkMaskGamma;
+//sizes (fewer bits). Three bits per channel was chosen when #303942; (used by
+//the Chrome UI) turned out too green.
+typedef SkTMaskGamma<3, 3, 3> SkMaskGamma;
class SkScalerContext {
public:
diff --git a/src/ports/SkFontHost_FreeType.cpp b/src/ports/SkFontHost_FreeType.cpp
index 45ae7ecffc..3d6b574616 100644
--- a/src/ports/SkFontHost_FreeType.cpp
+++ b/src/ports/SkFontHost_FreeType.cpp
@@ -24,6 +24,9 @@
#include "SkTemplates.h"
#include "SkThread.h"
+#if defined(SK_CAN_USE_DLOPEN)
+#include <dlfcn.h>
+#endif
#include <ft2build.h>
#include FT_FREETYPE_H
#include FT_OUTLINE_H
@@ -83,23 +86,51 @@ static bool gLCDSupportValid; // true iff |gLCDSupport| has been set.
static bool gLCDSupport; // true iff LCD is supported by the runtime.
static int gLCDExtra; // number of extra pixels for filtering.
+// FT_Library_SetLcdFilterWeights was introduced in FreeType 2.4.0.
+// The following platforms provide FreeType of at least 2.4.0.
+// Ubuntu >= 11.04 (previous deprecated April 2013)
+// Debian >= 6.0 (good)
+// OpenSuse >= 11.4 (previous deprecated January 2012 / Nov 2013 for Evergreen 11.2)
+// Fedora >= 14 (good)
+// Android >= Gingerbread (good)
+typedef FT_Error (*FT_Library_SetLcdFilterWeightsProc)(FT_Library, unsigned char*);
+
/////////////////////////////////////////////////////////////////////////
-static bool
-InitFreetype() {
+static bool InitFreetype() {
FT_Error err = FT_Init_FreeType(&gFTLibrary);
if (err) {
return false;
}
- // Setup LCD filtering. This reduces colour fringes for LCD rendered
- // glyphs.
+ // Setup LCD filtering. This reduces color fringes for LCD smoothed glyphs.
#ifdef FT_LCD_FILTER_H
- err = FT_Library_SetLcdFilter(gFTLibrary, FT_LCD_FILTER_DEFAULT);
-// err = FT_Library_SetLcdFilter(gFTLibrary, FT_LCD_FILTER_LIGHT);
- gLCDSupport = err == 0;
- if (gLCDSupport) {
- gLCDExtra = 2; //DEFAULT and LIGHT add one pixel to each side.
+ //Use light as default, as FT_LCD_FILTER_DEFAULT adds up to 0x110.
+ err = FT_Library_SetLcdFilter(gFTLibrary, FT_LCD_FILTER_LIGHT);
+ if (0 == err) {
+ gLCDSupport = true;
+ gLCDExtra = 2; //Using a filter adds one full pixel to each side.
+
+ static unsigned char gaussianLikeWeights[] = { 0x17, 0x40, 0x52, 0x40, 0x17 };
+ //static unsigned char triangleLikeWeights[] = { 0x1C, 0x39, 0x56, 0x39, 0x1C };
+
+#if defined(SK_FONTHOST_FREETYPE_RUNTIME_VERSION) && \
+ SK_FONTHOST_FREETYPE_RUNTIME_VERSION > 0x020400
+ err = FT_Library_SetLcdFilterWeights(gFTLibrary, gaussianLikeWeights);
+#elif defined(SK_CAN_USE_DLOPEN) && SK_CAN_USE_DLOPEN == 1
+ //The FreeType library is already loaded, so symbols are available in process.
+ void* self = dlopen(NULL, RTLD_LAZY);
+ if (NULL != self) {
+ FT_Library_SetLcdFilterWeightsProc setLcdFilterWeights;
+ //The following cast is non-standard, but safe for POSIX.
+ *reinterpret_cast<void**>(&setLcdFilterWeights) = dlsym(self, "FT_Library_SetLcdFilterWeights");
+ dlclose(self);
+
+ if (NULL != setLcdFilterWeights) {
+ err = setLcdFilterWeights(gFTLibrary, gaussianLikeWeights);
+ }
+ }
+#endif
}
#else
gLCDSupport = false;
@@ -610,7 +641,7 @@ void SkFontHost::FilterRec(SkScalerContext::Rec* rec) {
if (rec->fTextSize > SkIntToScalar(1 << 14)) {
rec->fTextSize = SkIntToScalar(1 << 14);
}
-
+
if (!gLCDSupportValid) {
InitFreetype();
FT_Done_FreeType(gFTLibrary);