Improve the SkAdvancedTypefaceMetrics interface w.r.t. vertical advances.

Add a template function to type safe-combine bits of a bit field.

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

git-svn-id: http://skia.googlecode.com/svn/trunk@1020 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/include/core/SkAdvancedTypefaceMetrics.h b/include/core/SkAdvancedTypefaceMetrics.h
index 033e738..f536a56 100644
--- a/include/core/SkAdvancedTypefaceMetrics.h
+++ b/include/core/SkAdvancedTypefaceMetrics.h
@@ -76,6 +76,14 @@
 
     SkIRect fBBox;  // The bounding box of all glyphs (in font units).
 
+    // The type of advance data wanted.
+    enum PerGlyphInfo {
+      kNo_PerGlyphInfo         = 0x0, // Don't populate any per glyph info.
+      kHAdvance_PerGlyphInfo   = 0x1, // Populate horizontal advance data.
+      kVAdvance_PerGlyphInfo   = 0x2, // Populate vertical advance data.
+      kGlyphNames_PerGlyphInfo = 0x4, // Populate glyph names (Type 1 only).
+    };
+
     template <typename Data>
     struct AdvanceMetric {
         enum MetricType {
diff --git a/include/core/SkFontHost.h b/include/core/SkFontHost.h
index 3c69251..72faed7 100644
--- a/include/core/SkFontHost.h
+++ b/include/core/SkFontHost.h
@@ -177,14 +177,14 @@
     ///////////////////////////////////////////////////////////////////////////
 
     /** Retrieve detailed typeface metrics.  Used by the PDF backend.
-        @param perGlyphInfo Indicate if the glyph specific information.
-        @param perGlyphInfo Indicate if the glyph specific information (advances
-                            and names) should be populated.
+        @param perGlyphInfo Indicate what glyph specific information (advances,
+                            names, etc.) should be populated.
         @return The returned object has already been referenced.  NULL is
                 returned if the font is not found.
      */
     static SkAdvancedTypefaceMetrics* GetAdvancedTypefaceMetrics(
-            SkFontID fontID, bool perGlyphInfo);
+            SkFontID fontID,
+            SkAdvancedTypefaceMetrics::PerGlyphInfo perGlyphInfo);
 
     /** Return the number of tables in the font
      */
diff --git a/include/core/SkTypeface.h b/include/core/SkTypeface.h
index c3b0f50..abbde04 100644
--- a/include/core/SkTypeface.h
+++ b/include/core/SkTypeface.h
@@ -17,6 +17,7 @@
 #ifndef SkTypeface_DEFINED
 #define SkTypeface_DEFINED
 
+#include "SkAdvancedTypefaceMetrics.h"
 #include "SkRefCnt.h"
 
 class SkStream;
@@ -136,11 +137,15 @@
     static SkTypeface* Deserialize(SkStream*);
 
     /** Retrieve detailed typeface metrics.  Used by the PDF backend.
-        @param perGlyphInfo Indicate if the glyph specific information (advances
-                            and names) should be populated.
+        @param perGlyphInfo Indicate what glyph specific information (advances,
+                            names, etc.) should be populated.
         @return The returned object has already been referenced.
      */
     SkAdvancedTypefaceMetrics* getAdvancedTypefaceMetrics(
+            SkAdvancedTypefaceMetrics::PerGlyphInfo perGlyphInfo) const;
+
+    // Temporary: for transition purposes.
+    SkAdvancedTypefaceMetrics* getAdvancedTypefaceMetrics(
             bool perGlyphInfo) const;
 
 protected:
diff --git a/include/core/SkTypes.h b/include/core/SkTypes.h
index 1290935..1a3a2e5 100644
--- a/include/core/SkTypes.h
+++ b/include/core/SkTypes.h
@@ -318,6 +318,13 @@
 
 ///////////////////////////////////////////////////////////////////////////////
 
+/** Use to combine multiple bits in a bitmask in a type safe way.
+ */
+template <typename T>
+T SkTBitOr(T a, T b) {
+    return (T)(a | b);
+}
+
 /**
  *  Use to cast a pointer to a different type, and maintaining strict-aliasing
  */
diff --git a/src/core/SkTypeface.cpp b/src/core/SkTypeface.cpp
index 7eeaf19..dc7ff89 100644
--- a/src/core/SkTypeface.cpp
+++ b/src/core/SkTypeface.cpp
@@ -14,6 +14,7 @@
  * limitations under the License.
  */
 
+#include "SkAdvancedTypefaceMetrics.h"
 #include "SkTypeface.h"
 #include "SkFontHost.h"
 
@@ -76,6 +77,15 @@
 }
 
 SkAdvancedTypefaceMetrics* SkTypeface::getAdvancedTypefaceMetrics(
-        bool perGlyphInfo) const {
+        SkAdvancedTypefaceMetrics::PerGlyphInfo perGlyphInfo) const {
     return SkFontHost::GetAdvancedTypefaceMetrics(fUniqueID, perGlyphInfo);
 }
+
+// Temporary: for transitions purposes only.
+SkAdvancedTypefaceMetrics* SkTypeface::getAdvancedTypefaceMetrics(
+        bool perGlyphInfo) const {
+    SkASSERT(!perGlyphInfo);
+    return SkFontHost::GetAdvancedTypefaceMetrics(
+            fUniqueID,
+            SkAdvancedTypefaceMetrics::kNo_PerGlyphInfo);
+}
diff --git a/src/pdf/SkPDFFont.cpp b/src/pdf/SkPDFFont.cpp
index 83caea5..9a2180d 100644
--- a/src/pdf/SkPDFFont.cpp
+++ b/src/pdf/SkPDFFont.cpp
@@ -28,6 +28,7 @@
 #include "SkScalar.h"
 #include "SkStream.h"
 #include "SkTypeface.h"
+#include "SkTypes.h"
 #include "SkUtils.h"
 
 namespace {
@@ -411,7 +412,9 @@
         fontInfo = relatedFont->fFontInfo;
         fontDescriptor = relatedFont->fDescriptor.get();
     } else {
-        fontInfo = SkFontHost::GetAdvancedTypefaceMetrics(fontID, true);
+        fontInfo = SkFontHost::GetAdvancedTypefaceMetrics(fontID, SkTBitOr(
+                SkAdvancedTypefaceMetrics::kHAdvance_PerGlyphInfo,
+                SkAdvancedTypefaceMetrics::kGlyphNames_PerGlyphInfo));
         SkSafeUnref(fontInfo.get());  // SkRefPtr and Get both took a reference.
     }
 
diff --git a/src/ports/SkFontHost_FONTPATH.cpp b/src/ports/SkFontHost_FONTPATH.cpp
index 98f4ba5..afab874 100644
--- a/src/ports/SkFontHost_FONTPATH.cpp
+++ b/src/ports/SkFontHost_FONTPATH.cpp
@@ -271,7 +271,8 @@
 
 // static
 SkAdvancedTypefaceMetrics* SkFontHost::GetAdvancedTypefaceMetrics(
-        uint32_t fontID, bool perGlyphInfo) {
+        uint32_t fontID,
+        SkAdvancedTypefaceMetrics::PerGlyphInfo perGlyphInfo) {
     sk_throw();  // not implemented
     return NULL;
 }
diff --git a/src/ports/SkFontHost_FreeType.cpp b/src/ports/SkFontHost_FreeType.cpp
index 1c0b269..e058a36 100644
--- a/src/ports/SkFontHost_FreeType.cpp
+++ b/src/ports/SkFontHost_FreeType.cpp
@@ -344,7 +344,8 @@
 
 // static
 SkAdvancedTypefaceMetrics* SkFontHost::GetAdvancedTypefaceMetrics(
-        uint32_t fontID, bool perGlyphInfo) {
+        uint32_t fontID,
+        SkAdvancedTypefaceMetrics::PerGlyphInfo perGlyphInfo) {
 #if defined(SK_BUILD_FOR_MAC) || defined(ANDROID)
     return NULL;
 #else
@@ -386,12 +387,6 @@
         }
     }
 
-    SkASSERT(!FT_HAS_VERTICAL(face));
-#ifdef FT_IS_CID_KEYED
-    SkASSERT(FT_IS_CID_KEYED(face) ==
-             (info->fType == SkAdvancedTypefaceMetrics::kType1CID_Font));
-#endif
-
     info->fStyle = 0;
     if (FT_IS_FIXED_WIDTH(face))
         info->fStyle |= SkAdvancedTypefaceMetrics::kFixedPitch_Style;
@@ -463,8 +458,12 @@
     info->fBBox = SkIRect::MakeLTRB(face->bbox.xMin, face->bbox.yMax,
                                     face->bbox.xMax, face->bbox.yMin);
 
-    if (perGlyphInfo && canEmbed(face) && FT_IS_SCALABLE(face) &&
-            info->fType != SkAdvancedTypefaceMetrics::kOther_Font) {
+    if (!canEmbed(face) || !FT_IS_SCALABLE(face) || 
+            info->fType == SkAdvancedTypefaceMetrics::kOther_Font) {
+        perGlyphInfo = SkAdvancedTypefaceMetrics::kNo_PerGlyphInfo;
+    }
+
+    if (perGlyphInfo & SkAdvancedTypefaceMetrics::kHAdvance_PerGlyphInfo) {
         if (FT_IS_FIXED_WIDTH(face)) {
             appendRange(&info->fGlyphWidths, 0);
             int16_t advance = face->max_advance_width;
@@ -492,18 +491,24 @@
             info->fGlyphWidths.reset(
                 getAdvanceData(face, face->num_glyphs, &getWidthAdvance));
         }
+    }
 
-        if (info->fType == SkAdvancedTypefaceMetrics::kType1_Font) {
-            // Postscript fonts may contain more than 255 glyphs, so we end up
-            // using multiple font descriptions with a glyph ordering.  Record
-            // the name of each glyph.
-            info->fGlyphNames.reset(
-                    new SkAutoTArray<SkString>(face->num_glyphs));
-            for (int gID = 0; gID < face->num_glyphs; gID++) {
-                char glyphName[128];  // PS limit for names is 127 bytes.
-                FT_Get_Glyph_Name(face, gID, glyphName, 128);
-                info->fGlyphNames->get()[gID].set(glyphName);
-            }
+    if (perGlyphInfo & SkAdvancedTypefaceMetrics::kVAdvance_PerGlyphInfo &&
+            FT_HAS_VERTICAL(face)) {
+        SkASSERT(false);  // Not implemented yet.
+    }
+
+    if (perGlyphInfo & SkAdvancedTypefaceMetrics::kGlyphNames_PerGlyphInfo &&
+            info->fType == SkAdvancedTypefaceMetrics::kType1_Font) {
+        // Postscript fonts may contain more than 255 glyphs, so we end up
+        // using multiple font descriptions with a glyph ordering.  Record
+        // the name of each glyph.
+        info->fGlyphNames.reset(
+                new SkAutoTArray<SkString>(face->num_glyphs));
+        for (int gID = 0; gID < face->num_glyphs; gID++) {
+            char glyphName[128];  // PS limit for names is 127 bytes.
+            FT_Get_Glyph_Name(face, gID, glyphName, 128);
+            info->fGlyphNames->get()[gID].set(glyphName);
         }
     }
 
diff --git a/src/ports/SkFontHost_mac_atsui.cpp b/src/ports/SkFontHost_mac_atsui.cpp
index 1d40a42..5bc438a 100644
--- a/src/ports/SkFontHost_mac_atsui.cpp
+++ b/src/ports/SkFontHost_mac_atsui.cpp
@@ -481,7 +481,8 @@
 
 // static
 SkAdvancedTypefaceMetrics* SkFontHost::GetAdvancedTypefaceMetrics(
-        uint32_t fontID, bool perGlyphInfo) {
+        uint32_t fontID,
+        SkAdvancedTypefaceMetrics::PerGlyphInfo perGlyphInfo) {
     SkASSERT(!"SkFontHost::GetAdvancedTypefaceMetrics unimplemented");
     return NULL;
 }
diff --git a/src/ports/SkFontHost_mac_coretext.cpp b/src/ports/SkFontHost_mac_coretext.cpp
index 6ffe17b..5f75d19 100644
--- a/src/ports/SkFontHost_mac_coretext.cpp
+++ b/src/ports/SkFontHost_mac_coretext.cpp
@@ -676,7 +676,8 @@
 
 // static
 SkAdvancedTypefaceMetrics* SkFontHost::GetAdvancedTypefaceMetrics(
-        uint32_t fontID, bool perGlyphInfo) {
+        uint32_t fontID,
+        SkAdvancedTypefaceMetrics::PerGlyphInfo perGlyphInfo) {
     SkASSERT(!"SkFontHost::GetAdvancedTypefaceMetrics unimplemented");
     return NULL;
 }
diff --git a/src/ports/SkFontHost_none.cpp b/src/ports/SkFontHost_none.cpp
index d56c94a..91546f8 100644
--- a/src/ports/SkFontHost_none.cpp
+++ b/src/ports/SkFontHost_none.cpp
@@ -35,7 +35,8 @@
 
 // static
 SkAdvancedTypefaceMetrics* SkFontHost::GetAdvancedTypefaceMetrics(
-        uint32_t fontID, bool perGlyphInfo) {
+        uint32_t fontID,
+        SkAdvancedTypefaceMetrics::PerGlyphInfo perGlyphInfo) {
     SkASSERT(!"SkFontHost::GetAdvancedTypefaceMetrics unimplemented");
     return NULL;
 }
diff --git a/src/ports/SkFontHost_simple.cpp b/src/ports/SkFontHost_simple.cpp
index 60334e7..54d326e 100644
--- a/src/ports/SkFontHost_simple.cpp
+++ b/src/ports/SkFontHost_simple.cpp
@@ -592,7 +592,8 @@
 
 #if 0
 SkAdvancedTypefaceMetrics* SkFontHost::GetAdvancedTypefaceMetrics(
-        uint32_t fontID, bool perGlyphInfo) {
+        uint32_t fontID,
+        SkAdvancedTypefaceMetrics::PerGlyphInfo perGlyphInfo) {
     SkASSERT(!"SkFontHost::GetAdvancedTypefaceMetrics unimplemented");
     return NULL;
 }
diff --git a/src/ports/SkFontHost_win.cpp b/src/ports/SkFontHost_win.cpp
index e6f83c1..d95bd80 100644
--- a/src/ports/SkFontHost_win.cpp
+++ b/src/ports/SkFontHost_win.cpp
@@ -613,7 +613,8 @@
 
 // static
 SkAdvancedTypefaceMetrics* SkFontHost::GetAdvancedTypefaceMetrics(
-        uint32_t fontID, bool perGlyphInfo) {
+        uint32_t fontID,
+        SkAdvancedTypefaceMetrics::PerGlyphInfo perGlyphInfo) {
     SkAutoMutexAcquire ac(gFTMutex);
     LogFontTypeface* rec = LogFontTypeface::FindById(fontID);
     LOGFONT lf = rec->logFont();
@@ -721,7 +722,7 @@
     // If bit 2 is set, the embedding is read-only.
     if (otm.otmfsType & 0x1) {
         info->fType = SkAdvancedTypefaceMetrics::kNotEmbeddable_Font;
-    } else if (perGlyphInfo) {
+    } else if (perGlyphInfo & kHAdvance_PerGlyphInfo) {
         info->fGlyphWidths.reset(
             getAdvanceData(hdc, glyphCount, &getWidthAdvance));
     }