Provide windows font host implementation needed to support TrueType text in pdf backend.
authorvandebo@chromium.org <vandebo@chromium.org@2bbb7eff-a529-9590-31e7-b0007b416f81>
Mon, 14 Feb 2011 23:19:59 +0000 (23:19 +0000)
committervandebo@chromium.org <vandebo@chromium.org@2bbb7eff-a529-9590-31e7-b0007b416f81>
Mon, 14 Feb 2011 23:19:59 +0000 (23:19 +0000)
- Move AdvanceMetric template functions into new file SkAdvancedTypefaceMetrics.cpp

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

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

include/core/SkAdvancedTypefaceMetrics.h
src/core/SkAdvancedTypefaceMetrics.cpp [new file with mode: 0755]
src/core/core_files.mk
src/ports/SkFontHost_FreeType.cpp
src/ports/SkFontHost_win.cpp [changed mode: 0644->0755]
vs/SampleApp/SampleApp.vcxproj

index 0c718d4..033e738 100644 (file)
@@ -107,4 +107,30 @@ public:
     SkTScopedPtr<SkAutoTArray<SkString> > fGlyphNames;
 };
 
+namespace skia_advanced_typeface_metrics_utils {
+
+template <typename Data>
+void resetRange(SkAdvancedTypefaceMetrics::AdvanceMetric<Data>* range,
+                       int startId);
+
+template <typename Data>
+SkAdvancedTypefaceMetrics::AdvanceMetric<Data>* appendRange(
+        SkTScopedPtr<SkAdvancedTypefaceMetrics::AdvanceMetric<Data> >* nextSlot,
+        int startId);
+
+template <typename Data>
+void finishRange(
+        SkAdvancedTypefaceMetrics::AdvanceMetric<Data>* range,
+        int endId,
+        typename SkAdvancedTypefaceMetrics::AdvanceMetric<Data>::MetricType
+                type);
+
+template <typename Data, typename FontHandle>
+SkAdvancedTypefaceMetrics::AdvanceMetric<Data>* getAdvanceData(
+        FontHandle fontHandle,
+        int num_glyphs,
+        bool (*getAdvance)(FontHandle fontHandle, int gId, Data* data));
+
+} // namespace skia_advanced_typeface_metrics_utils
+
 #endif
diff --git a/src/core/SkAdvancedTypefaceMetrics.cpp b/src/core/SkAdvancedTypefaceMetrics.cpp
new file mode 100755 (executable)
index 0000000..1b86fb5
--- /dev/null
@@ -0,0 +1,158 @@
+/*
+ * Copyright (C) 2011 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "SkAdvancedTypefaceMetrics.h"
+#include "SkTypes.h"
+
+#ifdef SK_BUILD_FOR_UNIX
+#include <ft2build.h>
+#include FT_FREETYPE_H
+#endif
+
+namespace skia_advanced_typeface_metrics_utils {
+
+template <typename Data>
+void resetRange(SkAdvancedTypefaceMetrics::AdvanceMetric<Data>* range,
+                int startId) {
+    range->fStartId = startId;
+    range->fAdvance.setCount(0);
+}
+
+template <typename Data>
+SkAdvancedTypefaceMetrics::AdvanceMetric<Data>* appendRange(
+        SkTScopedPtr<SkAdvancedTypefaceMetrics::AdvanceMetric<Data> >* nextSlot,
+        int startId) {
+    nextSlot->reset(new SkAdvancedTypefaceMetrics::AdvanceMetric<Data>);
+    resetRange(nextSlot->get(), startId);
+    return nextSlot->get();
+}
+
+template <typename Data>
+void finishRange(
+        SkAdvancedTypefaceMetrics::AdvanceMetric<Data>* range,
+        int endId,
+        typename SkAdvancedTypefaceMetrics::AdvanceMetric<Data>::MetricType
+                type) {
+    range->fEndId = endId;
+    range->fType = type;
+    int newLength;
+    if (type == SkAdvancedTypefaceMetrics::AdvanceMetric<Data>::kRange) {
+        newLength = endId - range->fStartId + 1;
+    } else {
+        newLength = 1;
+    }
+    SkASSERT(range->fAdvance.count() >= newLength);
+    range->fAdvance.setCount(newLength);
+}
+
+template <typename Data, typename FontHandle>
+SkAdvancedTypefaceMetrics::AdvanceMetric<Data>* getAdvanceData(
+        FontHandle fontHandle,
+        int num_glyphs,
+        bool (*getAdvance)(FontHandle fontHandle, int gId, Data* data)) {
+    // Assuming that an ASCII representation of a width or a glyph id is,
+    // on average, 3 characters long gives the following cut offs for
+    // using different range types:
+    // When currently in a range
+    //  - Removing 4 0's is a win
+    //  - Removing 5 repeats is a win
+    // When not currently in a range
+    //  - Removing 1 0 is a win
+    //  - Removing 3 repeats is a win
+
+    SkTScopedPtr<SkAdvancedTypefaceMetrics::AdvanceMetric<Data> > result;
+    SkAdvancedTypefaceMetrics::AdvanceMetric<Data>* curRange;
+    curRange = appendRange(&result, 0);
+    Data lastAdvance = SK_MinS16;
+    int repeats = 0;
+    for (int gId = 0; gId < num_glyphs; gId++) {
+        Data advance;
+        if (!getAdvance(fontHandle, gId, &advance)) {
+            num_glyphs = (gId > 0) ? gId - 1 : 0;
+            break;
+        }
+        if (advance == lastAdvance) {
+            repeats++;
+        } else if (curRange->fAdvance.count() == repeats + 1) {
+            if (lastAdvance == 0 && repeats >= 0) {
+                resetRange(curRange, gId);
+            } else if (repeats >= 2) {
+                finishRange(curRange, gId - 1,
+                            SkAdvancedTypefaceMetrics::WidthRange::kRun);
+                curRange = appendRange(&curRange->fNext, gId);
+            }
+            repeats = 0;
+        } else {
+            if (lastAdvance == 0 && repeats >= 3) {
+                finishRange(curRange, gId - repeats - 2,
+                            SkAdvancedTypefaceMetrics::WidthRange::kRange);
+                curRange = appendRange(&curRange->fNext, gId);
+            } else if (repeats >= 4) {
+                finishRange(curRange, gId - repeats - 2,
+                            SkAdvancedTypefaceMetrics::WidthRange::kRange);
+                curRange = appendRange(&curRange->fNext, gId - repeats - 1);
+                curRange->fAdvance.append(1, &lastAdvance);
+                finishRange(curRange, gId - 1,
+                            SkAdvancedTypefaceMetrics::WidthRange::kRun);
+                curRange = appendRange(&curRange->fNext, gId);
+            }
+            repeats = 0;
+        }
+        curRange->fAdvance.append(1, &advance);
+        lastAdvance = advance;
+    }
+    finishRange(curRange, num_glyphs - 1,
+                SkAdvancedTypefaceMetrics::WidthRange::kRange);
+    return result.release();
+}
+
+// Make AdvanceMetric template functions available for linking with typename
+// WidthRange and VerticalAdvanceRange.
+#ifdef SK_BUILD_FOR_WIN
+template SkAdvancedTypefaceMetrics::WidthRange* getAdvanceData(
+        HDC hdc,
+        int num_glyphs,
+        bool (*getAdvance)(HDC hdc, int gId, int16_t* data));
+#elif SK_BUILD_FOR_UNIX
+template SkAdvancedTypefaceMetrics::WidthRange* getAdvanceData(
+        FT_Face face,
+        int num_glyphs,
+        bool (*getAdvance)(FT_Face face, int gId, int16_t* data));
+#endif
+template void resetRange(
+        SkAdvancedTypefaceMetrics::WidthRange* range,
+        int startId);
+template SkAdvancedTypefaceMetrics::WidthRange* appendRange(
+        SkTScopedPtr<SkAdvancedTypefaceMetrics::WidthRange >* nextSlot,
+        int startId);
+template void finishRange<int16_t>(
+        SkAdvancedTypefaceMetrics::WidthRange* range,
+        int endId,
+        SkAdvancedTypefaceMetrics::WidthRange::MetricType type);
+
+template void resetRange(
+        SkAdvancedTypefaceMetrics::VerticalAdvanceRange* range,
+        int startId);
+template SkAdvancedTypefaceMetrics::VerticalAdvanceRange* appendRange(
+        SkTScopedPtr<SkAdvancedTypefaceMetrics::VerticalAdvanceRange >*
+            nextSlot,
+        int startId);
+template void finishRange<SkAdvancedTypefaceMetrics::VerticalMetric>(
+        SkAdvancedTypefaceMetrics::VerticalAdvanceRange* range,
+        int endId,
+        SkAdvancedTypefaceMetrics::VerticalAdvanceRange::MetricType type);
+
+} // namespace skia_advanced_typeface_metrics_utils
index 3e3436e..399b1a5 100644 (file)
@@ -1,5 +1,6 @@
 SOURCE := \
     Sk64.cpp \
+    SkAdvancedTypefaceMetrics.cpp \
     SkAlphaRuns.cpp \
     SkBitmap.cpp \
     SkBitmapProcShader.cpp \
index 1b1d47b..7f1e377 100644 (file)
@@ -73,6 +73,8 @@
     #define SkASSERT_CONTINUE(pred)
 #endif
 
+using namespace skia_advanced_typeface_metrics_utils;
+
 //////////////////////////////////////////////////////////////////////////
 
 struct SkFaceRec;
@@ -331,98 +333,14 @@ static bool GetLetterCBox(FT_Face face, char letter, FT_BBox* bbox) {
     return true;
 }
 
-static int16_t getWidthAdvance(FT_Face face, int gId) {
+static bool getWidthAdvance(FT_Face face, int gId, int16_t* data) {
     FT_Fixed advance = 0;
-    SkAssertResult(getAdvances(face, gId, 1, FT_LOAD_NO_SCALE, &advance) == 0);
-    return advance;
-}
-
-template <typename Data>
-static void resetRange(SkAdvancedTypefaceMetrics::AdvanceMetric<Data>* range,
-                       int startId) {
-    range->fStartId = startId;
-    range->fAdvance.setCount(0);
-}
-
-template <typename Data>
-static SkAdvancedTypefaceMetrics::AdvanceMetric<Data>* appendRange(
-        SkTScopedPtr<SkAdvancedTypefaceMetrics::AdvanceMetric<Data> >* nextSlot,
-        int startId) {
-    nextSlot->reset(new SkAdvancedTypefaceMetrics::AdvanceMetric<Data>);
-    resetRange(nextSlot->get(), startId);
-    return nextSlot->get();
-}
-
-template <typename Data>
-static void finishRange(
-        SkAdvancedTypefaceMetrics::AdvanceMetric<Data>* range,
-        int endId,
-        typename SkAdvancedTypefaceMetrics::AdvanceMetric<Data>::MetricType
-                type) {
-    range->fEndId = endId;
-    range->fType = type;
-    int newLength;
-    if (type == SkAdvancedTypefaceMetrics::AdvanceMetric<Data>::kRange)
-        newLength = endId - range->fStartId + 1;
-    else
-        newLength = 1;
-    SkASSERT(range->fAdvance.count() >= newLength);
-    range->fAdvance.setCount(newLength);
-}
-
-template <typename Data>
-static SkAdvancedTypefaceMetrics::AdvanceMetric<Data>* getAdvanceData(
-        FT_Face face, Data (*getAdvance)(FT_Face face, int gId)) {
-    // Assuming that an ASCII representation of a width or a glyph id is,
-    // on average, 3 characters long gives the following cut offs for
-    // using different range types:
-    // When currently in a range
-    //  - Removing 4 0's is a win
-    //  - Removing 5 repeats is a win
-    // When not currently in a range
-    //  - Removing 1 0 is a win
-    //  - Removing 3 repeats is a win
-
-    SkTScopedPtr<SkAdvancedTypefaceMetrics::AdvanceMetric<Data> > result;
-    SkAdvancedTypefaceMetrics::AdvanceMetric<Data>* curRange;
-    curRange = appendRange(&result, 0);
-    Data lastAdvance = SHRT_MIN;
-    int repeats = 0;
-    for (int gId = 0; gId < face->num_glyphs; gId++) {
-        Data advance = getAdvance(face, gId);
-        if (advance == lastAdvance) {
-            repeats++;
-        } else if (curRange->fAdvance.count() == repeats + 1) {
-            if (lastAdvance == 0 && repeats >= 0) {
-                resetRange(curRange, gId);
-            } else if (repeats >= 2) {
-                finishRange(curRange, gId - 1,
-                            SkAdvancedTypefaceMetrics::WidthRange::kRun);
-                curRange = appendRange(&curRange->fNext, gId);
-            }
-            repeats = 0;
-        } else {
-            if (lastAdvance == 0 && repeats >= 3) {
-                finishRange(curRange, gId - repeats - 2,
-                            SkAdvancedTypefaceMetrics::WidthRange::kRange);
-                curRange = appendRange(&curRange->fNext, gId);
-            } else if (repeats >= 4) {
-                finishRange(curRange, gId - repeats - 2,
-                            SkAdvancedTypefaceMetrics::WidthRange::kRange);
-                curRange = appendRange(&curRange->fNext, gId - repeats - 1);
-                curRange->fAdvance.append(1, &lastAdvance);
-                finishRange(curRange, gId - 1,
-                            SkAdvancedTypefaceMetrics::WidthRange::kRun);
-                curRange = appendRange(&curRange->fNext, gId);
-            }
-            repeats = 0;
-        }
-        curRange->fAdvance.append(1, &advance);
-        lastAdvance = advance;
+    if (getAdvances(face, gId, 1, FT_LOAD_NO_SCALE, &advance)) {
+        return false;
     }
-    finishRange(curRange, face->num_glyphs - 1,
-                SkAdvancedTypefaceMetrics::WidthRange::kRange);
-    return result.release();
+    SkASSERT(data);
+    *data = advance;
+    return true;
 }
 
 // static
@@ -499,6 +417,7 @@ SkAdvancedTypefaceMetrics* SkFontHost::GetAdvancedTypefaceMetrics(
     // Figure out a good guess for StemV - Min width of i, I, !, 1.
     // This probably isn't very good with an italic font.
     int16_t min_width = SHRT_MAX;
+    info->fStemV = 0;
     char stem_chars[] = {'i', 'I', '!', '1'};
     for (size_t i = 0; i < SK_ARRAY_COUNT(stem_chars); i++) {
         FT_BBox bbox;
@@ -550,7 +469,7 @@ SkAdvancedTypefaceMetrics* SkFontHost::GetAdvancedTypefaceMetrics(
             info->fGlyphWidths->fAdvance.append(1, &advance);
             finishRange(info->fGlyphWidths.get(), 0,
                         SkAdvancedTypefaceMetrics::WidthRange::kDefault);
-        } else if(!cid) {
+        } else if (!cid) {
             appendRange(&info->fGlyphWidths, 0);
             // So as to not blow out the stack, get advances in batches.
             for (int gID = 0; gID < face->num_glyphs; gID += 128) {
@@ -568,7 +487,8 @@ SkAdvancedTypefaceMetrics* SkFontHost::GetAdvancedTypefaceMetrics(
             finishRange(info->fGlyphWidths.get(), face->num_glyphs - 1,
                         SkAdvancedTypefaceMetrics::WidthRange::kRange);
         } else {
-            info->fGlyphWidths.reset(getAdvanceData(face, &getWidthAdvance));
+            info->fGlyphWidths.reset(
+                getAdvanceData(face, face->num_glyphs, &getWidthAdvance));
         }
 
         if (info->fType == SkAdvancedTypefaceMetrics::kType1_Font) {
old mode 100644 (file)
new mode 100755 (executable)
index dacabac..c2e43fa
@@ -19,6 +19,8 @@
 \r
 #include "SkFontHost.h"\r
 #include "SkDescriptor.h"\r
+#include "SkAdvancedTypefaceMetrics.h"\r
+#include "SkStream.h"\r
 #include "SkThread.h"\r
 \r
 #ifdef WIN32\r
@@ -28,6 +30,8 @@
 // client3d has to undefine this for now\r
 #define CAN_USE_LOGFONT_NAME\r
 \r
+using namespace skia_advanced_typeface_metrics_utils;\r
+\r
 static SkMutex gFTMutex;\r
 \r
 static const uint16_t BUFFERSIZE = (16384 - 32);\r
@@ -456,11 +460,133 @@ SkTypeface* SkFontHost::Deserialize(SkStream* stream) {
     return NULL;\r
 }\r
 \r
+static bool getWidthAdvance(HDC hdc, int gId, int16_t* advance) {\r
+    // Initialize the MAT2 structure to the identify transformation matrix.\r
+    static const MAT2 mat2 = {SkScalarToFIXED(1), SkScalarToFIXED(0),\r
+                        SkScalarToFIXED(0), SkScalarToFIXED(1)};\r
+    int flags = GGO_METRICS | GGO_GLYPH_INDEX;\r
+    GLYPHMETRICS gm;\r
+    if (GDI_ERROR == GetGlyphOutline(hdc, gId, flags, &gm, 0, NULL, &mat2)) {\r
+        return false;\r
+    }\r
+    SkASSERT(advance);\r
+    *advance = gm.gmCellIncX;\r
+    return true;\r
+}\r
+\r
 // static\r
 SkAdvancedTypefaceMetrics* SkFontHost::GetAdvancedTypefaceMetrics(\r
         uint32_t fontID, bool perGlyphInfo) {\r
-    SkASSERT(!"SkFontHost::GetAdvancedTypefaceMetrics unimplemented");\r
-    return NULL;\r
+    SkAutoMutexAcquire ac(gFTMutex);\r
+    LogFontTypeface* rec = LogFontTypeface::FindById(fontID);\r
+    LOGFONT lf = rec->logFont();\r
+    SkAdvancedTypefaceMetrics* info = NULL;\r
+\r
+    HDC hdc = CreateCompatibleDC(NULL);\r
+    HFONT font = CreateFontIndirect(&lf);\r
+    HFONT savefont = (HFONT)SelectObject(hdc, font);\r
+    HFONT designFont = NULL;\r
+\r
+    // To request design units, create a logical font whose height is specified\r
+    // as unitsPerEm.\r
+    OUTLINETEXTMETRIC otm;\r
+    if (!GetOutlineTextMetrics(hdc, sizeof(otm), &otm) ||\r
+        !GetTextFace(hdc, LF_FACESIZE, lf.lfFaceName)) {\r
+        goto Error;\r
+    }\r
+    lf.lfHeight = -SkToS32(otm.otmEMSquare);\r
+    designFont = CreateFontIndirect(&lf);\r
+    SelectObject(hdc, designFont);\r
+    if (!GetOutlineTextMetrics(hdc, sizeof(otm), &otm)) {\r
+        goto Error;\r
+    }\r
+\r
+    info = new SkAdvancedTypefaceMetrics;\r
+#ifdef UNICODE\r
+    // Get the buffer size needed first.\r
+    size_t str_len = WideCharToMultiByte(CP_UTF8, 0, lf.lfFaceName, -1, NULL,\r
+                                         0, NULL, NULL);\r
+    // Allocate a buffer (str_len already has terminating null accounted for).\r
+    char *familyName = new char[str_len];\r
+    // Now actually convert the string.\r
+    WideCharToMultiByte(CP_UTF8, 0, lf.lfFaceName, -1, familyName, str_len,\r
+                          NULL, NULL);\r
+    info->fFontName.set(familyName);\r
+    delete [] familyName;\r
+#else\r
+    info->fFontName.set(lf.lfFaceName);\r
+#endif\r
+\r
+    if (otm.otmTextMetrics.tmPitchAndFamily & TMPF_TRUETYPE) {\r
+        info->fType = SkAdvancedTypefaceMetrics::kTrueType_Font;\r
+    } else {\r
+        info->fType = SkAdvancedTypefaceMetrics::kOther_Font;\r
+    }\r
+    info->fEmSize = otm.otmEMSquare;\r
+    info->fMultiMaster = false;\r
+\r
+    info->fStyle = 0;\r
+    // If this bit is clear the font is a fixed pitch font.\r
+    if (!(otm.otmTextMetrics.tmPitchAndFamily & TMPF_FIXED_PITCH)) {\r
+        info->fStyle |= SkAdvancedTypefaceMetrics::kFixedPitch_Style;\r
+    }\r
+    if (otm.otmTextMetrics.tmItalic) {\r
+        info->fStyle |= SkAdvancedTypefaceMetrics::kItalic_Style;\r
+    }\r
+    // Setting symbolic style by default for now.\r
+    info->fStyle |= SkAdvancedTypefaceMetrics::kSymbolic_Style;\r
+    if (otm.otmTextMetrics.tmPitchAndFamily & FF_ROMAN) {\r
+        info->fStyle |= SkAdvancedTypefaceMetrics::kSerif_Style;\r
+    } else if (otm.otmTextMetrics.tmPitchAndFamily & FF_SCRIPT) {\r
+            info->fStyle |= SkAdvancedTypefaceMetrics::kScript_Style;\r
+    }\r
+\r
+    // The main italic angle of the font, in tenths of a degree counterclockwise\r
+    // from vertical.\r
+    info->fItalicAngle = otm.otmItalicAngle / 10;\r
+    info->fAscent = SkToS16(otm.otmTextMetrics.tmAscent);\r
+    info->fDescent = SkToS16(-otm.otmTextMetrics.tmDescent);\r
+    // TODO(ctguil): Use alternate cap height calculation.\r
+    // MSDN says otmsCapEmHeight is not support but it is returning a value on\r
+    // my Win7 box.\r
+    info->fCapHeight = otm.otmsCapEmHeight;\r
+    info->fBBox =\r
+        SkIRect::MakeLTRB(otm.otmrcFontBox.left, otm.otmrcFontBox.top,\r
+                          otm.otmrcFontBox.right, otm.otmrcFontBox.bottom);\r
+\r
+    // Figure out a good guess for StemV - Min width of i, I, !, 1.\r
+    // This probably isn't very good with an italic font.\r
+    int16_t min_width = SHRT_MAX;\r
+    info->fStemV = 0;\r
+    char stem_chars[] = {'i', 'I', '!', '1'};\r
+    for (size_t i = 0; i < SK_ARRAY_COUNT(stem_chars); i++) {\r
+        ABC abcWidths;\r
+        if (GetCharABCWidths(hdc, stem_chars[i], stem_chars[i], &abcWidths)) {\r
+            int16_t width = abcWidths.abcB;\r
+            if (width > 0 && width < min_width) {\r
+                min_width = width;\r
+                info->fStemV = min_width;\r
+            }\r
+        }\r
+    }\r
+\r
+    // If bit 1 is set, the font may not be embedded in a document.\r
+    // If bit 1 is clear, the font can be embedded.\r
+    // If bit 2 is set, the embedding is read-only.\r
+    if (otm.otmfsType & 0x1) {\r
+        info->fType = SkAdvancedTypefaceMetrics::kNotEmbeddable_Font;\r
+    } else if (perGlyphInfo) {\r
+        info->fGlyphWidths.reset(\r
+            getAdvanceData(hdc, SHRT_MAX, &getWidthAdvance));\r
+    }\r
+\r
+Error:\r
+    SelectObject(hdc, savefont);\r
+    DeleteObject(designFont);\r
+    DeleteObject(font);\r
+    DeleteDC(hdc);\r
+\r
+    return info;\r
 }\r
 \r
 SkTypeface* SkFontHost::CreateTypefaceFromStream(SkStream* stream) {\r
@@ -471,8 +597,25 @@ SkTypeface* SkFontHost::CreateTypefaceFromStream(SkStream* stream) {
 }\r
 \r
 SkStream* SkFontHost::OpenStream(SkFontID uniqueID) {\r
-    SkASSERT(!"SkFontHost::OpenStream unimplemented");\r
-    return NULL;\r
+    SkAutoMutexAcquire ac(gFTMutex);\r
+    LogFontTypeface* rec = LogFontTypeface::FindById(uniqueID);\r
+\r
+    HDC hdc = ::CreateCompatibleDC(NULL);\r
+    HFONT font = CreateFontIndirect(&rec->logFont());\r
+    HFONT savefont = (HFONT)SelectObject(hdc, font);\r
+\r
+    size_t bufferSize = GetFontData(hdc, 0, 0, NULL, 0);\r
+    SkMemoryStream* stream = new SkMemoryStream(bufferSize);\r
+    if (!GetFontData(hdc, 0, 0, (void*)stream->getMemoryBase(), bufferSize)) {\r
+        delete stream;\r
+        stream = NULL;\r
+    }\r
+\r
+    SelectObject(hdc, savefont);\r
+    DeleteObject(font);\r
+    DeleteDC(hdc);\r
+\r
+    return stream;\r
 }\r
 \r
 SkScalerContext* SkFontHost::CreateScalerContext(const SkDescriptor* desc) {\r
index 688e59c..bf0f5fa 100644 (file)
     <ClCompile Include="..\..\samplecode\SampleVertices.cpp" />\r
     <ClCompile Include="..\..\samplecode\SampleXfermodes.cpp" />\r
     <ClCompile Include="..\..\src\core\Sk64.cpp" />\r
+    <ClCompile Include="..\..\src\core\SkAdvancedTypefaceMetrics.cpp" />\r
     <ClCompile Include="..\..\src\core\SkAlphaRuns.cpp" />\r
     <ClCompile Include="..\..\src\core\SkBitmap.cpp" />\r
     <ClCompile Include="..\..\src\core\SkBitmapProcShader.cpp" />\r
   <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />\r
   <ImportGroup Label="ExtensionTargets">\r
   </ImportGroup>\r
-</Project>
\ No newline at end of file
+</Project>\r