Add SkFontHost::FilterRect() which allows the font host to filter our request
authorreed@android.com <reed@android.com@2bbb7eff-a529-9590-31e7-b0007b416f81>
Wed, 22 Jul 2009 19:52:11 +0000 (19:52 +0000)
committerreed@android.com <reed@android.com@2bbb7eff-a529-9590-31e7-b0007b416f81>
Wed, 22 Jul 2009 19:52:11 +0000 (19:52 +0000)
before we turn it into a font-cache entry, for the cases where the scaler will
ignore and/or collapse certain feature requests (e.g. doesn't support all levels
of hinting)

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

include/config/SkUserConfig.h
include/core/SkFontHost.h
include/core/SkMask.h
include/core/SkScalerContext.h
src/core/SkPaint.cpp
src/ports/SkFontHost_FreeType.cpp
src/ports/SkFontHost_mac.cpp

index 2d51204..ccdf40f 100644 (file)
 /*  To enable additional blitters (and fontscaler code) to support separate
     alpha channels for R G B channels, define SK_SUPPORT_LCDTEXT
  */
-#define SK_SUPPORT_LCDTEXT
+//#define SK_SUPPORT_LCDTEXT
 
 /*  If SK_DEBUG is defined, then you can optionally define SK_SUPPORT_UNITTEST
     which will run additional self-tests at startup. These can take a long time,
index 12f20a0..752c352 100644 (file)
@@ -131,6 +131,20 @@ public:
 
     ///////////////////////////////////////////////////////////////////////////
 
+    /** Given a filled-out rec, the fonthost may decide to modify it to reflect
+        what the host is actually capable of fulfilling. For example, if the
+        rec is requesting a level of hinting that, for this host, maps some
+        other level (e.g. kFull -> kNormal), it should update the rec to reflect
+        what will actually be done. This is an optimization so that the font
+        cache does not contain different recs (i.e. keys) that in reality map to
+        the same output.
+     
+        A lazy (but valid) fonthost can do nothing in its FilterRec routine.
+     */
+    static void FilterRec(SkScalerContext::Rec* rec);
+
+    ///////////////////////////////////////////////////////////////////////////
+    
     /** Return the number of tables in the font
      */
     static int CountTables(SkFontID);
index 8c041e4..4139d0b 100644 (file)
@@ -126,6 +126,10 @@ struct SkMask {
         kJustRenderImage_CreateMode,        //!< render into preallocate mask
         kComputeBoundsAndRenderImage_CreateMode  //!< compute bounds, alloc image and render into it
     };
+    
+    static bool FormatIsLCD(Format fm) {
+        return kHorizontalLCD_Format == fm || kVerticalLCD_Format == fm;
+    }
 };
 
 #endif
index dbe8ecb..dd01bc6 100644 (file)
@@ -152,8 +152,8 @@ public:
         kGammaForWhite_Flag = 0x08, // illegal to set both Gamma flags
         // together, these two flags resulting in a two bit value which matches
         // up with the SkPaint::Hinting enum.
-        kHintingBit1        = 0x10,
-        kHintingBit2        = 0x20,
+        kHintingBit1_Flag   = 0x10,
+        kHintingBit2_Flag   = 0x20,
     };
     struct Rec {
         uint32_t    fFontID;
@@ -174,9 +174,17 @@ public:
         }
 
         void setHinting(SkPaint::Hinting hinting) {
-            fFlags = (fFlags & ~(kHintingBit1 | kHintingBit2)) |
+            fFlags = (fFlags & ~(kHintingBit1_Flag | kHintingBit2_Flag)) |
                      (static_cast<int>(hinting) << 4);
         }
+
+        SkMask::Format getFormat() const {
+            return static_cast<SkMask::Format>(fMaskFormat);
+        }
+
+        bool isLCD() const {
+            return SkMask::FormatIsLCD(this->getFormat());
+        }
     };
 
     SkScalerContext(const SkDescriptor* desc);
index b136733..cb78734 100644 (file)
@@ -1137,9 +1137,11 @@ static SkMask::Format computeMaskFormat(const SkPaint& paint)
     return SkMask::kBW_Format;
 }
 
-void SkScalerContext::MakeRec(const SkPaint& paint, const SkMatrix* deviceMatrix, Rec* rec)
+void SkScalerContext::MakeRec(const SkPaint& paint,
+                              const SkMatrix* deviceMatrix, Rec* rec)
 {
-    SkASSERT(deviceMatrix == NULL || (deviceMatrix->getType() & SkMatrix::kPerspective_Mask) == 0);
+    SkASSERT(deviceMatrix == NULL ||
+             (deviceMatrix->getType() & SkMatrix::kPerspective_Mask) == 0);
 
     rec->fFontID = SkTypeface::UniqueID(paint.getTypeface());
     rec->fTextSize = paint.getTextSize();
@@ -1201,6 +1203,13 @@ void SkScalerContext::MakeRec(const SkPaint& paint, const SkMatrix* deviceMatrix
     rec->fMaskFormat = SkToU8(computeMaskFormat(paint));
     rec->fFlags = SkToU8(flags);
     rec->setHinting(paint.getHinting());
+
+    /*  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,
+        they can modify our rec up front, so we don't create duplicate cache
+        entries.
+     */
+    SkFontHost::FilterRec(rec);
 }
 
 #define MIN_SIZE_FOR_EFFECT_BUFFER  1024
index fa10362..b350202 100644 (file)
@@ -262,6 +262,14 @@ static void unref_ft_face(FT_Face face) {
 
 ///////////////////////////////////////////////////////////////////////////
 
+void SkFontHost::FilterRec(SkScalerContext::Rec* rec) {
+    // collapse full->normaling hinting if we're not doing LCD
+    SkPaint::Hinting h = rec->getHinting();
+    if (SkPaint::kFull_Hinting == h && !rec->isLCD()) {
+        rec->setHinting(SkPaint::kNormal_Hinting);
+    }
+}
+
 SkScalerContext_FreeType::SkScalerContext_FreeType(const SkDescriptor* desc)
         : SkScalerContext(desc) {
     SkAutoMutexAcquire  ac(gFTMutex);
index c807be7..aac0034 100755 (executable)
@@ -106,6 +106,22 @@ private:
     static OSStatus Close(void *cb);
 };
 
+void SkFontHost::FilterRec(SkScalerContext::Rec* rec) {
+    // we only support 2 levels of hinting
+    SkPaint::Hinting h = rec->getHinting();
+    if (SkPaint::kSlight_Hinting == h) {
+        h = SkPaint::kNo_Hinting;
+    } else if (SkPaint::kFull_Hinting == h) {
+        h = SkPaint::kNormal_Hinting;
+    }
+    rec->setHinting(h);
+
+    // we don't support LCD text
+    if (SkMask::FormatIsLCD((SkMask::Format)rec->fMaskFormat)) {
+        rec->fMaskFormat = SkMask::kA8_Format;
+    }
+}
+
 SkScalerContext_Mac::SkScalerContext_Mac(const SkDescriptor* desc)
     : SkScalerContext(desc), fLayout(0), fStyle(0)
 {