Implement SkScalerContext_Windows::generateGlyphCount() and provide access via SkGlyphCache interface.
* This will be used by PDF font code.

Review URL: http://codereview.appspot.com/4261042

git-svn-id: http://skia.googlecode.com/svn/trunk@888 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/include/core/SkScalerContext.h b/include/core/SkScalerContext.h
index 5937819..317658d 100644
--- a/include/core/SkScalerContext.h
+++ b/include/core/SkScalerContext.h
@@ -230,7 +230,7 @@
     */
     SkUnichar glyphIDToChar(uint16_t glyphID);
 
-    unsigned    getGlyphCount() const { return this->generateGlyphCount(); }
+    unsigned    getGlyphCount() { return this->generateGlyphCount(); }
     void        getAdvance(SkGlyph*);
     void        getMetrics(SkGlyph*);
     void        getImage(const SkGlyph&);
@@ -245,7 +245,7 @@
     Rec         fRec;
     unsigned    fBaseGlyphCount;
 
-    virtual unsigned generateGlyphCount() const = 0;
+    virtual unsigned generateGlyphCount() = 0;
     virtual uint16_t generateCharToGlyph(SkUnichar) = 0;
     virtual void generateAdvance(SkGlyph*) = 0;
     virtual void generateMetrics(SkGlyph*) = 0;
diff --git a/src/core/SkGlyphCache.cpp b/src/core/SkGlyphCache.cpp
index 5ed7386..b97699c 100644
--- a/src/core/SkGlyphCache.cpp
+++ b/src/core/SkGlyphCache.cpp
@@ -117,6 +117,10 @@
     return fScalerContext->glyphIDToChar(glyphID);
 }
 
+unsigned SkGlyphCache::getGlyphCount() {
+    return fScalerContext->getGlyphCount();
+}
+
 ///////////////////////////////////////////////////////////////////////////////
 
 const SkGlyph& SkGlyphCache::getUnicharAdvance(SkUnichar charCode) {
diff --git a/src/core/SkGlyphCache.h b/src/core/SkGlyphCache.h
index 16330f8..d6b4fd6 100644
--- a/src/core/SkGlyphCache.h
+++ b/src/core/SkGlyphCache.h
@@ -77,6 +77,10 @@
     */
     SkUnichar glyphToUnichar(uint16_t);
 
+    /** Returns the number of glyphs for this strike.
+    */
+    unsigned getGlyphCount();
+
     /** Return the image associated with the glyph. If it has not been generated
         this will trigger that.
     */
diff --git a/src/core/SkScalerContext.cpp b/src/core/SkScalerContext.cpp
index 697917a..bbe0158 100644
--- a/src/core/SkScalerContext.cpp
+++ b/src/core/SkScalerContext.cpp
@@ -645,7 +645,7 @@
     SkScalerContext_Empty(const SkDescriptor* desc) : SkScalerContext(desc) {}
 
 protected:
-    virtual unsigned generateGlyphCount() const {
+    virtual unsigned generateGlyphCount() {
         return 0;
     }
     virtual uint16_t generateCharToGlyph(SkUnichar uni) {
diff --git a/src/ports/SkFontHost_FreeType.cpp b/src/ports/SkFontHost_FreeType.cpp
index 1a22972..5fb3245 100644
--- a/src/ports/SkFontHost_FreeType.cpp
+++ b/src/ports/SkFontHost_FreeType.cpp
@@ -121,7 +121,7 @@
     }
 
 protected:
-    virtual unsigned generateGlyphCount() const;
+    virtual unsigned generateGlyphCount();
     virtual uint16_t generateCharToGlyph(SkUnichar uni);
     virtual void generateAdvance(SkGlyph* glyph);
     virtual void generateMetrics(SkGlyph* glyph);
@@ -731,7 +731,7 @@
     FT_Outline_Embolden(outline, strength);
 }
 
-unsigned SkScalerContext_FreeType::generateGlyphCount() const {
+unsigned SkScalerContext_FreeType::generateGlyphCount() {
     return fFace->num_glyphs;
 }
 
diff --git a/src/ports/SkFontHost_ascender.cpp b/src/ports/SkFontHost_ascender.cpp
index 88cde38..6f5cf0b 100644
--- a/src/ports/SkFontHost_ascender.cpp
+++ b/src/ports/SkFontHost_ascender.cpp
@@ -22,7 +22,7 @@
     virtual ~SkScalerContext_Ascender();
 
 protected:
-    virtual unsigned generateGlyphCount() const;
+    virtual unsigned generateGlyphCount();
     virtual uint16_t generateCharToGlyph(SkUnichar uni);
     virtual void generateMetrics(SkGlyph* glyph);
     virtual void generateImage(const SkGlyph& glyph);
@@ -102,7 +102,7 @@
     sk_free(fHandle);
 }
 
-unsigned SkScalerContext_Ascender::generateGlyphCount() const
+unsigned SkScalerContext_Ascender::generateGlyphCount()
 {
     return 1000;
 }
diff --git a/src/ports/SkFontHost_mac_atsui.cpp b/src/ports/SkFontHost_mac_atsui.cpp
index 5183730..1d40a42 100644
--- a/src/ports/SkFontHost_mac_atsui.cpp
+++ b/src/ports/SkFontHost_mac_atsui.cpp
@@ -87,7 +87,7 @@
     virtual ~SkScalerContext_Mac();
 
 protected:
-    virtual unsigned generateGlyphCount() const;
+    virtual unsigned generateGlyphCount();
     virtual uint16_t generateCharToGlyph(SkUnichar uni);
     virtual void generateAdvance(SkGlyph* glyph);
     virtual void generateMetrics(SkGlyph* glyph);
@@ -184,7 +184,7 @@
 
 // man, we need to consider caching this, since it is just dependent on
 // fFontID, and not on any of the other settings like matrix or flags
-unsigned SkScalerContext_Mac::generateGlyphCount() const {
+unsigned SkScalerContext_Mac::generateGlyphCount() {
     // The 'maxp' table stores the number of glyphs a offset 4, in 2 bytes
     uint16_t numGlyphs;
     if (SkFontHost::GetTableData(fRec.fFontID,
diff --git a/src/ports/SkFontHost_mac_coretext.cpp b/src/ports/SkFontHost_mac_coretext.cpp
index 4b5c36d..c154027 100644
--- a/src/ports/SkFontHost_mac_coretext.cpp
+++ b/src/ports/SkFontHost_mac_coretext.cpp
@@ -314,7 +314,7 @@
 
 
 protected:
-    unsigned                            generateGlyphCount(void) const;
+    unsigned                            generateGlyphCount(void);
     uint16_t                            generateCharToGlyph(SkUnichar uni);
     void                                generateAdvance(SkGlyph* glyph);
     void                                generateMetrics(SkGlyph* glyph);
@@ -373,7 +373,7 @@
     CFSafeRelease(mFont);
 }
 
-unsigned SkScalerContext_Mac::generateGlyphCount(void) const
+unsigned SkScalerContext_Mac::generateGlyphCount(void)
 {
     return(mGlyphCount);
 }
diff --git a/src/ports/SkFontHost_win.cpp b/src/ports/SkFontHost_win.cpp
index 85a3763..04a50cb 100644
--- a/src/ports/SkFontHost_win.cpp
+++ b/src/ports/SkFontHost_win.cpp
@@ -17,6 +17,7 @@
 #include "SkString.h"

 //#include "SkStream.h"

 

+#include "SkEndian.h"

 #include "SkFontHost.h"

 #include "SkDescriptor.h"

 #include "SkAdvancedTypefaceMetrics.h"

@@ -63,6 +64,32 @@
     return SkFixedToFIXED(SkScalarToFixed(x));

 }

 

+static unsigned calculateGlyphCount(HDC hdc) {

+    // The 'maxp' table stores the number of glyphs at offset 4, in 2 bytes.

+    const DWORD maxpTag = *(DWORD*) "maxp";

+    uint16_t glyphs;

+    if (GetFontData(hdc, maxpTag, 4, &glyphs, sizeof(glyphs)) != GDI_ERROR) {

+        return SkEndian_SwapBE16(glyphs);

+    }

+    

+    // Binary search for glyph count.

+    static const MAT2 mat2 = {{0, 1}, {0, 0}, {0, 0}, {0, 1}};

+    int32_t max = SK_MaxU16 + 1;

+    int32_t min = 0;

+    GLYPHMETRICS gm;

+    while (min < max) {

+        int32_t mid = min + ((max - min) / 2);

+        if (GetGlyphOutlineW(hdc, mid, GGO_METRICS | GGO_GLYPH_INDEX, &gm, 0,

+                             NULL, &mat2) == GDI_ERROR) {

+            max = mid;

+        } else {

+            min = mid + 1;

+        }

+    }

+    SkASSERT(min == max);

+    return min;

+}

+

 static SkTypeface::Style GetFontStyle(const LOGFONT& lf) {

     int style = SkTypeface::kNormal;

     if (lf.lfWeight == FW_SEMIBOLD || lf.lfWeight == FW_DEMIBOLD || lf.lfWeight == FW_BOLD)

@@ -188,7 +215,7 @@
     virtual ~SkScalerContext_Windows();

 

 protected:

-    virtual unsigned generateGlyphCount() const;

+    virtual unsigned generateGlyphCount();

     virtual uint16_t generateCharToGlyph(SkUnichar uni);

     virtual void generateAdvance(SkGlyph* glyph);

     virtual void generateMetrics(SkGlyph* glyph);

@@ -203,10 +230,12 @@
     HFONT        fSavefont;

     HFONT        fFont;

     SCRIPT_CACHE fSC;

+    int          fGlyphCount;

 };

 

 SkScalerContext_Windows::SkScalerContext_Windows(const SkDescriptor* desc)

-        : SkScalerContext(desc), fDDC(0), fFont(0), fSavefont(0), fSC(0) {

+        : SkScalerContext(desc), fDDC(0), fFont(0), fSavefont(0), fSC(0)

+        , fGlyphCount(-1) {

     SkAutoMutexAcquire  ac(gFTMutex);

 

 	fScale = fRec.fTextSize / gCanonicalTextSize;

@@ -239,9 +268,11 @@
     }

 }

 

-unsigned SkScalerContext_Windows::generateGlyphCount() const {

-    return 0xFFFF;

-    //    return fFace->num_glyphs;

+unsigned SkScalerContext_Windows::generateGlyphCount() {

+    if (fGlyphCount < 0) {

+        fGlyphCount = calculateGlyphCount(fDDC);

+    }

+    return fGlyphCount;

 }

 

 uint16_t SkScalerContext_Windows::generateCharToGlyph(SkUnichar uni) {