diff options
author | vandebo@chromium.org <vandebo@chromium.org@2bbb7eff-a529-9590-31e7-b0007b416f81> | 2011-02-14 23:19:59 +0000 |
---|---|---|
committer | vandebo@chromium.org <vandebo@chromium.org@2bbb7eff-a529-9590-31e7-b0007b416f81> | 2011-02-14 23:19:59 +0000 |
commit | 6f72d1eacd66d2a9c0059962a75c0ca6a99ff98e (patch) | |
tree | ab77ed84f87aeccd58b334279a901b07797ace18 | |
parent | 97b624529c014b93cabffac5f0ef5a5842473a4b (diff) |
Provide windows font host implementation needed to support TrueType text in pdf backend.
- 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
-rw-r--r-- | include/core/SkAdvancedTypefaceMetrics.h | 26 | ||||
-rwxr-xr-x | src/core/SkAdvancedTypefaceMetrics.cpp | 158 | ||||
-rw-r--r-- | src/core/core_files.mk | 1 | ||||
-rw-r--r-- | src/ports/SkFontHost_FreeType.cpp | 104 | ||||
-rwxr-xr-x[-rw-r--r--] | src/ports/SkFontHost_win.cpp | 151 | ||||
-rw-r--r-- | vs/SampleApp/SampleApp.vcxproj | 3 |
6 files changed, 346 insertions, 97 deletions
diff --git a/include/core/SkAdvancedTypefaceMetrics.h b/include/core/SkAdvancedTypefaceMetrics.h index 0c718d4f32..033e738c8a 100644 --- a/include/core/SkAdvancedTypefaceMetrics.h +++ b/include/core/SkAdvancedTypefaceMetrics.h @@ -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 index 0000000000..1b86fb5fac --- /dev/null +++ b/src/core/SkAdvancedTypefaceMetrics.cpp @@ -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 diff --git a/src/core/core_files.mk b/src/core/core_files.mk index 3e3436e9cc..399b1a5a65 100644 --- a/src/core/core_files.mk +++ b/src/core/core_files.mk @@ -1,5 +1,6 @@ SOURCE := \ Sk64.cpp \ + SkAdvancedTypefaceMetrics.cpp \ SkAlphaRuns.cpp \ SkBitmap.cpp \ SkBitmapProcShader.cpp \ diff --git a/src/ports/SkFontHost_FreeType.cpp b/src/ports/SkFontHost_FreeType.cpp index 1b1d47b5ce..7f1e377260 100644 --- a/src/ports/SkFontHost_FreeType.cpp +++ b/src/ports/SkFontHost_FreeType.cpp @@ -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) { diff --git a/src/ports/SkFontHost_win.cpp b/src/ports/SkFontHost_win.cpp index dacabac87c..c2e43fa129 100644..100755 --- a/src/ports/SkFontHost_win.cpp +++ b/src/ports/SkFontHost_win.cpp @@ -19,6 +19,8 @@ #include "SkFontHost.h"
#include "SkDescriptor.h"
+#include "SkAdvancedTypefaceMetrics.h"
+#include "SkStream.h"
#include "SkThread.h"
#ifdef WIN32
@@ -28,6 +30,8 @@ // client3d has to undefine this for now
#define CAN_USE_LOGFONT_NAME
+using namespace skia_advanced_typeface_metrics_utils;
+
static SkMutex gFTMutex;
static const uint16_t BUFFERSIZE = (16384 - 32);
@@ -456,11 +460,133 @@ SkTypeface* SkFontHost::Deserialize(SkStream* stream) { return NULL;
}
+static bool getWidthAdvance(HDC hdc, int gId, int16_t* advance) {
+ // Initialize the MAT2 structure to the identify transformation matrix.
+ static const MAT2 mat2 = {SkScalarToFIXED(1), SkScalarToFIXED(0),
+ SkScalarToFIXED(0), SkScalarToFIXED(1)};
+ int flags = GGO_METRICS | GGO_GLYPH_INDEX;
+ GLYPHMETRICS gm;
+ if (GDI_ERROR == GetGlyphOutline(hdc, gId, flags, &gm, 0, NULL, &mat2)) {
+ return false;
+ }
+ SkASSERT(advance);
+ *advance = gm.gmCellIncX;
+ return true;
+}
+
// static
SkAdvancedTypefaceMetrics* SkFontHost::GetAdvancedTypefaceMetrics(
uint32_t fontID, bool perGlyphInfo) {
- SkASSERT(!"SkFontHost::GetAdvancedTypefaceMetrics unimplemented");
- return NULL;
+ SkAutoMutexAcquire ac(gFTMutex);
+ LogFontTypeface* rec = LogFontTypeface::FindById(fontID);
+ LOGFONT lf = rec->logFont();
+ SkAdvancedTypefaceMetrics* info = NULL;
+
+ HDC hdc = CreateCompatibleDC(NULL);
+ HFONT font = CreateFontIndirect(&lf);
+ HFONT savefont = (HFONT)SelectObject(hdc, font);
+ HFONT designFont = NULL;
+
+ // To request design units, create a logical font whose height is specified
+ // as unitsPerEm.
+ OUTLINETEXTMETRIC otm;
+ if (!GetOutlineTextMetrics(hdc, sizeof(otm), &otm) ||
+ !GetTextFace(hdc, LF_FACESIZE, lf.lfFaceName)) {
+ goto Error;
+ }
+ lf.lfHeight = -SkToS32(otm.otmEMSquare);
+ designFont = CreateFontIndirect(&lf);
+ SelectObject(hdc, designFont);
+ if (!GetOutlineTextMetrics(hdc, sizeof(otm), &otm)) {
+ goto Error;
+ }
+
+ info = new SkAdvancedTypefaceMetrics;
+#ifdef UNICODE
+ // Get the buffer size needed first.
+ size_t str_len = WideCharToMultiByte(CP_UTF8, 0, lf.lfFaceName, -1, NULL,
+ 0, NULL, NULL);
+ // Allocate a buffer (str_len already has terminating null accounted for).
+ char *familyName = new char[str_len];
+ // Now actually convert the string.
+ WideCharToMultiByte(CP_UTF8, 0, lf.lfFaceName, -1, familyName, str_len,
+ NULL, NULL);
+ info->fFontName.set(familyName);
+ delete [] familyName;
+#else
+ info->fFontName.set(lf.lfFaceName);
+#endif
+
+ if (otm.otmTextMetrics.tmPitchAndFamily & TMPF_TRUETYPE) {
+ info->fType = SkAdvancedTypefaceMetrics::kTrueType_Font;
+ } else {
+ info->fType = SkAdvancedTypefaceMetrics::kOther_Font;
+ }
+ info->fEmSize = otm.otmEMSquare;
+ info->fMultiMaster = false;
+
+ info->fStyle = 0;
+ // If this bit is clear the font is a fixed pitch font.
+ if (!(otm.otmTextMetrics.tmPitchAndFamily & TMPF_FIXED_PITCH)) {
+ info->fStyle |= SkAdvancedTypefaceMetrics::kFixedPitch_Style;
+ }
+ if (otm.otmTextMetrics.tmItalic) {
+ info->fStyle |= SkAdvancedTypefaceMetrics::kItalic_Style;
+ }
+ // Setting symbolic style by default for now.
+ info->fStyle |= SkAdvancedTypefaceMetrics::kSymbolic_Style;
+ if (otm.otmTextMetrics.tmPitchAndFamily & FF_ROMAN) {
+ info->fStyle |= SkAdvancedTypefaceMetrics::kSerif_Style;
+ } else if (otm.otmTextMetrics.tmPitchAndFamily & FF_SCRIPT) {
+ info->fStyle |= SkAdvancedTypefaceMetrics::kScript_Style;
+ }
+
+ // The main italic angle of the font, in tenths of a degree counterclockwise
+ // from vertical.
+ info->fItalicAngle = otm.otmItalicAngle / 10;
+ info->fAscent = SkToS16(otm.otmTextMetrics.tmAscent);
+ info->fDescent = SkToS16(-otm.otmTextMetrics.tmDescent);
+ // TODO(ctguil): Use alternate cap height calculation.
+ // MSDN says otmsCapEmHeight is not support but it is returning a value on
+ // my Win7 box.
+ info->fCapHeight = otm.otmsCapEmHeight;
+ info->fBBox =
+ SkIRect::MakeLTRB(otm.otmrcFontBox.left, otm.otmrcFontBox.top,
+ otm.otmrcFontBox.right, otm.otmrcFontBox.bottom);
+
+ // 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++) {
+ ABC abcWidths;
+ if (GetCharABCWidths(hdc, stem_chars[i], stem_chars[i], &abcWidths)) {
+ int16_t width = abcWidths.abcB;
+ if (width > 0 && width < min_width) {
+ min_width = width;
+ info->fStemV = min_width;
+ }
+ }
+ }
+
+ // If bit 1 is set, the font may not be embedded in a document.
+ // If bit 1 is clear, the font can be embedded.
+ // If bit 2 is set, the embedding is read-only.
+ if (otm.otmfsType & 0x1) {
+ info->fType = SkAdvancedTypefaceMetrics::kNotEmbeddable_Font;
+ } else if (perGlyphInfo) {
+ info->fGlyphWidths.reset(
+ getAdvanceData(hdc, SHRT_MAX, &getWidthAdvance));
+ }
+
+Error:
+ SelectObject(hdc, savefont);
+ DeleteObject(designFont);
+ DeleteObject(font);
+ DeleteDC(hdc);
+
+ return info;
}
SkTypeface* SkFontHost::CreateTypefaceFromStream(SkStream* stream) {
@@ -471,8 +597,25 @@ SkTypeface* SkFontHost::CreateTypefaceFromStream(SkStream* stream) { }
SkStream* SkFontHost::OpenStream(SkFontID uniqueID) {
- SkASSERT(!"SkFontHost::OpenStream unimplemented");
- return NULL;
+ SkAutoMutexAcquire ac(gFTMutex);
+ LogFontTypeface* rec = LogFontTypeface::FindById(uniqueID);
+
+ HDC hdc = ::CreateCompatibleDC(NULL);
+ HFONT font = CreateFontIndirect(&rec->logFont());
+ HFONT savefont = (HFONT)SelectObject(hdc, font);
+
+ size_t bufferSize = GetFontData(hdc, 0, 0, NULL, 0);
+ SkMemoryStream* stream = new SkMemoryStream(bufferSize);
+ if (!GetFontData(hdc, 0, 0, (void*)stream->getMemoryBase(), bufferSize)) {
+ delete stream;
+ stream = NULL;
+ }
+
+ SelectObject(hdc, savefont);
+ DeleteObject(font);
+ DeleteDC(hdc);
+
+ return stream;
}
SkScalerContext* SkFontHost::CreateScalerContext(const SkDescriptor* desc) {
diff --git a/vs/SampleApp/SampleApp.vcxproj b/vs/SampleApp/SampleApp.vcxproj index 688e59ce6d..bf0f5fa62d 100644 --- a/vs/SampleApp/SampleApp.vcxproj +++ b/vs/SampleApp/SampleApp.vcxproj @@ -293,6 +293,7 @@ <ClCompile Include="..\..\samplecode\SampleVertices.cpp" />
<ClCompile Include="..\..\samplecode\SampleXfermodes.cpp" />
<ClCompile Include="..\..\src\core\Sk64.cpp" />
+ <ClCompile Include="..\..\src\core\SkAdvancedTypefaceMetrics.cpp" />
<ClCompile Include="..\..\src\core\SkAlphaRuns.cpp" />
<ClCompile Include="..\..\src\core\SkBitmap.cpp" />
<ClCompile Include="..\..\src\core\SkBitmapProcShader.cpp" />
@@ -476,4 +477,4 @@ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
-</Project>
\ No newline at end of file +</Project>
|