Detect that we're drawing to a device that has per-pixel alpha, and if so,
authorreed@google.com <reed@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81>
Fri, 30 Sep 2011 20:31:25 +0000 (20:31 +0000)
committerreed@google.com <reed@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81>
Fri, 30 Sep 2011 20:31:25 +0000 (20:31 +0000)
disable LCD text.

Add experimental flag to force AA in fontscaler (windows-only). Hope to remove
this later.

git-svn-id: http://skia.googlecode.com/svn/trunk@2387 2bbb7eff-a529-9590-31e7-b0007b416f81

src/core/SkBlitter_ARGB32.cpp
src/core/SkDevice.cpp
src/core/SkPaint.cpp
src/ports/SkFontHost_win.cpp

index af55aba..4e2916a 100644 (file)
@@ -60,18 +60,16 @@ static void blit_lcd16_row(SkPMColor dst[], const uint16_t src[],
         maskG = maskG * srcA >> 8;
         maskB = maskB * srcA >> 8;
 
-        int maskA = SkMax32(SkMax32(maskR, maskG), maskB);
-
-        int dstA = SkGetPackedA32(d);
         int dstR = SkGetPackedR32(d);
         int dstG = SkGetPackedG32(d);
         int dstB = SkGetPackedB32(d);
 
-        // nocheck version for now, until we cleanup GDI's garbage bits
-        dst[i] = SkPackARGB32NoCheck(blend32(0xFF, dstA, maskA),
-                                     blend32(srcR, dstR, maskR),
-                                     blend32(srcG, dstG, maskG),
-                                     blend32(srcB, dstB, maskB));
+        // LCD blitting is only supported if the dst is known/required\
+        // to be opaque
+        dst[i] = SkPackARGB32(0xFF,
+                              blend32(srcR, dstR, maskR),
+                              blend32(srcG, dstG, maskG),
+                              blend32(srcB, dstB, maskB));
     }
 }
 
@@ -105,18 +103,16 @@ static void blit_lcd16_opaque_row(SkPMColor dst[], const uint16_t src[],
         maskG = upscale31To32(maskG);
         maskB = upscale31To32(maskB);
 
-        int maskA = SkMax32(SkMax32(maskR, maskG), maskB);
-
-        int dstA = SkGetPackedA32(d);
         int dstR = SkGetPackedR32(d);
         int dstG = SkGetPackedG32(d);
         int dstB = SkGetPackedB32(d);
 
-        // nocheck version for now, until we cleanup GDI's garbage bits
-        dst[i] = SkPackARGB32NoCheck(blend32(0xFF, dstA, maskA),
-                                     blend32(srcR, dstR, maskR),
-                                     blend32(srcG, dstG, maskG),
-                                     blend32(srcB, dstB, maskB));
+        // LCD blitting is only supported if the dst is known/required
+        // to be opaque
+        dst[i] = SkPackARGB32(0xFF,
+                              blend32(srcR, dstR, maskR),
+                              blend32(srcG, dstG, maskG),
+                              blend32(srcB, dstB, maskB));
     }
 }
 
@@ -150,14 +146,13 @@ static void blit_lcd32_row(SkPMColor dst[], const uint32_t src[],
         maskG = maskG * srcA >> 8;
         maskB = maskB * srcA >> 8;
 
-        int maskA = SkMax32(SkMax32(maskR, maskG), maskB);
-
-        int dstA = SkGetPackedA32(d);
         int dstR = SkGetPackedR32(d);
         int dstG = SkGetPackedG32(d);
         int dstB = SkGetPackedB32(d);
 
-        dst[i] = SkPackARGB32(SkAlphaBlend(0xFF, dstA, maskA),
+        // LCD blitting is only supported if the dst is known/required
+        // to be opaque
+        dst[i] = SkPackARGB32(0xFF,
                               SkAlphaBlend(srcR, dstR, maskR),
                               SkAlphaBlend(srcG, dstG, maskG),
                               SkAlphaBlend(srcB, dstB, maskB));
index 69f86cc..c88ad9a 100644 (file)
@@ -219,12 +219,13 @@ void SkDevice::drawDevice(const SkDraw& draw, SkDevice* device,
 ///////////////////////////////////////////////////////////////////////////////
 
 bool SkDevice::filterTextFlags(const SkPaint& paint, TextFlags* flags) {
-    if (!paint.isLCDRenderText()) {
+    if (!paint.isLCDRenderText() || !paint.isAntiAlias()) {
         // we're cool with the paint as is
         return false;
     }
 
     if (SkBitmap::kARGB_8888_Config != fBitmap.config() ||
+        !fBitmap.isOpaque() ||
         paint.getShader() ||
         paint.getXfermode() || // unless its srcover
         paint.getMaskFilter() ||
@@ -235,6 +236,10 @@ bool SkDevice::filterTextFlags(const SkPaint& paint, TextFlags* flags) {
         paint.getStyle() != SkPaint::kFill_Style) {
         // turn off lcd
         flags->fFlags = paint.getFlags() & ~SkPaint::kLCDRenderText_Flag;
+#ifdef SK_BUILD_FOR_WIN
+        // flag that we *really* want AA
+        flags->fFlags |= SkPaint::kForceAAText_Flag;
+#endif
         flags->fHinting = paint.getHinting();
         return true;
     }
index 9197add..b2f5d8e 100644 (file)
@@ -1340,6 +1340,11 @@ void SkScalerContext::MakeRec(const SkPaint& paint,
     if (paint.isAutohinted()) {
         flags |= SkScalerContext::kAutohinting_Flag;
     }
+#ifdef SK_BUILD_FOR_WIN
+    if (paint.getFlags() & SkPaint::kForceAAText_Flag) {
+        flags |= SkScalerContext::kForceAA_Flag;
+    }
+#endif
     rec->fFlags = SkToU16(flags);
 
     // setHinting modifies fFlags, so do this last
index e265c13..87dbb80 100755 (executable)
@@ -31,11 +31,6 @@ template <typename T> T* SkTAddByteOffset(T* ptr, size_t byteOffset) {
     return (T*)((char*)ptr + byteOffset);
 }
 
-// When we request ANTIALIAS quality, we often seemt to get BW instead
-// This flag "fixes" that by actually requesting LCD output, and filtering
-// it down to gray-aa
-#define FORCE_AA_BY_CAPTURING_LCD_OUTPUT
-
 // define this in your Makefile or .gyp to enforce AA requests
 // which GDI ignores at small sizes. This flag guarantees AA
 // for rotated text, regardless of GDI's notions.
@@ -483,11 +478,15 @@ static BYTE compute_quality(const SkScalerContext::Rec& rec) {
         case SkMask::kLCD32_Format:
             return CLEARTYPE_QUALITY;
         default:
-#ifdef FORCE_AA_BY_CAPTURING_LCD_OUTPUT
-            return CLEARTYPE_QUALITY;
-#else
-            return ANTIALIASED_QUALITY;
-#endif
+            // here we just want AA, but we may have to force the issue
+            // since sometimes GDI will instead really give us BW
+            // (for some fonts and some sizes)
+            if (rec.fFlags & SkScalerContext::kForceAA_Flag) {
+                return CLEARTYPE_QUALITY;
+            } else {
+                return ANTIALIASED_QUALITY;
+            }
+            break;
     }
 }
 
@@ -697,19 +696,11 @@ void SkScalerContext_Windows::generateFontMetrics(SkPaint::FontMetrics* mx, SkPa
 // whenever we copy it into skia's buffer
 
 static inline uint8_t rgb_to_a8(SkGdiRGB rgb) {
-#ifdef FORCE_AA_BY_CAPTURING_LCD_OUTPUT
     int r = (rgb >> 16) & 0xFF;
     int g = (rgb >>  8) & 0xFF;
     int b = (rgb >>  0) & 0xFF;
 
-//    int ave = (r * 5 + g * 6 + b * 5) >> 4;
-    int ave = (r * 2 + g * 5 + b) >> 3;  // luminance
-
-    return ave;
-#else
-    // can pick any component (low 3 bytes), since we're grayscale
-    return rgb & 0xFF;
-#endif
+    return (r * 2 + g * 5 + b) >> 3;  // luminance
 }
 
 static inline uint16_t rgb_to_lcd16(SkGdiRGB rgb) {
@@ -1309,6 +1300,11 @@ 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);
+    }
 }
 
 //////////////////////////////////////////////////////////////////////////