| OLD | NEW |
| 1 | 1 |
| 2 /* | 2 /* |
| 3 * Copyright 2006 The Android Open Source Project | 3 * Copyright 2006 The Android Open Source Project |
| 4 * | 4 * |
| 5 * Use of this source code is governed by a BSD-style license that can be | 5 * Use of this source code is governed by a BSD-style license that can be |
| 6 * found in the LICENSE file. | 6 * found in the LICENSE file. |
| 7 */ | 7 */ |
| 8 | 8 |
| 9 #include "SkAdvancedTypefaceMetrics.h" | 9 #include "SkAdvancedTypefaceMetrics.h" |
| 10 #include "SkBase64.h" | 10 #include "SkBase64.h" |
| 11 #include "SkColorPriv.h" | 11 #include "SkColorPriv.h" |
| 12 #include "SkData.h" | 12 #include "SkData.h" |
| 13 #include "SkDescriptor.h" | 13 #include "SkDescriptor.h" |
| 14 #include "SkFontDescriptor.h" | 14 #include "SkFontDescriptor.h" |
| 15 #include "SkFontHost.h" | 15 #include "SkFontHost.h" |
| 16 #include "SkGlyph.h" | 16 #include "SkGlyph.h" |
| 17 #include "SkMaskGamma.h" | 17 #include "SkMaskGamma.h" |
| 18 #include "SkOTTable_maxp.h" |
| 18 #include "SkOTUtils.h" | 19 #include "SkOTUtils.h" |
| 19 #include "SkPath.h" | 20 #include "SkPath.h" |
| 20 #include "SkStream.h" | 21 #include "SkStream.h" |
| 21 #include "SkString.h" | 22 #include "SkString.h" |
| 22 #include "SkTemplates.h" | 23 #include "SkTemplates.h" |
| 23 #include "SkThread.h" | 24 #include "SkThread.h" |
| 24 #include "SkTypeface_win.h" | 25 #include "SkTypeface_win.h" |
| 25 #include "SkTypefaceCache.h" | 26 #include "SkTypefaceCache.h" |
| 26 #include "SkUtils.h" | 27 #include "SkUtils.h" |
| 27 | 28 |
| (...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 133 return *(FIXED*)(&x); | 134 return *(FIXED*)(&x); |
| 134 } | 135 } |
| 135 static inline SkFixed SkFIXEDToFixed(FIXED x) { | 136 static inline SkFixed SkFIXEDToFixed(FIXED x) { |
| 136 return *(SkFixed*)(&x); | 137 return *(SkFixed*)(&x); |
| 137 } | 138 } |
| 138 | 139 |
| 139 static inline FIXED SkScalarToFIXED(SkScalar x) { | 140 static inline FIXED SkScalarToFIXED(SkScalar x) { |
| 140 return SkFixedToFIXED(SkScalarToFixed(x)); | 141 return SkFixedToFIXED(SkScalarToFixed(x)); |
| 141 } | 142 } |
| 142 | 143 |
| 143 static unsigned calculateOutlineGlyphCount(HDC hdc) { | 144 static unsigned calculateGlyphCount(HDC hdc, const LOGFONT& lf) { |
| 145 TEXTMETRIC textMetric; |
| 146 if (0 == GetTextMetrics(hdc, &textMetric)) { |
| 147 textMetric.tmPitchAndFamily = TMPF_VECTOR; |
| 148 call_ensure_accessible(lf); |
| 149 GetTextMetrics(hdc, &textMetric); |
| 150 } |
| 151 |
| 152 if (!(textMetric.tmPitchAndFamily & TMPF_VECTOR)) { |
| 153 return textMetric.tmLastChar; |
| 154 } |
| 155 |
| 144 // The 'maxp' table stores the number of glyphs at offset 4, in 2 bytes. | 156 // The 'maxp' table stores the number of glyphs at offset 4, in 2 bytes. |
| 145 const DWORD maxpTag = | |
| 146 SkEndian_SwapBE32(SkSetFourByteTag('m', 'a', 'x', 'p')); | |
| 147 uint16_t glyphs; | 157 uint16_t glyphs; |
| 148 if (GetFontData(hdc, maxpTag, 4, &glyphs, sizeof(glyphs)) != GDI_ERROR) { | 158 if (GDI_ERROR != GetFontData(hdc, SkOTTableMaximumProfile::TAG, 4, &glyphs,
sizeof(glyphs))) { |
| 149 return SkEndian_SwapBE16(glyphs); | 159 return SkEndian_SwapBE16(glyphs); |
| 150 } | 160 } |
| 151 | 161 |
| 152 // Binary search for glyph count. | 162 // Binary search for glyph count. |
| 153 static const MAT2 mat2 = {{0, 1}, {0, 0}, {0, 0}, {0, 1}}; | 163 static const MAT2 mat2 = {{0, 1}, {0, 0}, {0, 0}, {0, 1}}; |
| 154 int32_t max = SK_MaxU16 + 1; | 164 int32_t max = SK_MaxU16 + 1; |
| 155 int32_t min = 0; | 165 int32_t min = 0; |
| 156 GLYPHMETRICS gm; | 166 GLYPHMETRICS gm; |
| 157 while (min < max) { | 167 while (min < max) { |
| 158 int32_t mid = min + ((max - min) / 2); | 168 int32_t mid = min + ((max - min) / 2); |
| 159 if (GetGlyphOutlineW(hdc, mid, GGO_METRICS | GGO_GLYPH_INDEX, &gm, 0, | 169 if (GetGlyphOutlineW(hdc, mid, GGO_METRICS | GGO_GLYPH_INDEX, &gm, 0, |
| 160 NULL, &mat2) == GDI_ERROR) { | 170 NULL, &mat2) == GDI_ERROR) { |
| 161 max = mid; | 171 max = mid; |
| 162 } else { | 172 } else { |
| 163 min = mid + 1; | 173 min = mid + 1; |
| 164 } | 174 } |
| 165 } | 175 } |
| 166 SkASSERT(min == max); | 176 SkASSERT(min == max); |
| 167 return min; | 177 return min; |
| 168 } | 178 } |
| 169 | 179 |
| 180 static unsigned calculateUPEM(HDC hdc, const LOGFONT& lf) { |
| 181 TEXTMETRIC textMetric; |
| 182 if (0 == GetTextMetrics(hdc, &textMetric)) { |
| 183 textMetric.tmPitchAndFamily = TMPF_VECTOR; |
| 184 call_ensure_accessible(lf); |
| 185 GetTextMetrics(hdc, &textMetric); |
| 186 } |
| 187 |
| 188 if (!(textMetric.tmPitchAndFamily & TMPF_VECTOR)) { |
| 189 return textMetric.tmMaxCharWidth; |
| 190 } |
| 191 |
| 192 OUTLINETEXTMETRIC otm; |
| 193 unsigned int otmRet = GetOutlineTextMetrics(hdc, sizeof(otm), &otm); |
| 194 if (0 == otmRet) { |
| 195 call_ensure_accessible(lf); |
| 196 otmRet = GetOutlineTextMetrics(hdc, sizeof(otm), &otm); |
| 197 } |
| 198 |
| 199 return (0 == otmRet) ? 0 : otm.otmEMSquare; |
| 200 } |
| 201 |
| 170 class LogFontTypeface : public SkTypeface { | 202 class LogFontTypeface : public SkTypeface { |
| 171 public: | 203 public: |
| 172 LogFontTypeface(SkTypeface::Style style, SkFontID fontID, const LOGFONT& lf,
bool serializeAsStream = false) : | 204 LogFontTypeface(SkTypeface::Style style, SkFontID fontID, const LOGFONT& lf,
bool serializeAsStream = false) : |
| 173 SkTypeface(style, fontID, false), fLogFont(lf), fSerializeAsStream(seria
lizeAsStream) { | 205 SkTypeface(style, fontID, false), fLogFont(lf), fSerializeAsStream(seria
lizeAsStream) { |
| 174 | 206 |
| 175 // If the font has cubic outlines, it will not be rendered with ClearTyp
e. | 207 // If the font has cubic outlines, it will not be rendered with ClearTyp
e. |
| 176 HFONT font = CreateFontIndirect(&lf); | 208 HFONT font = CreateFontIndirect(&lf); |
| 177 | 209 |
| 178 HDC deviceContext = ::CreateCompatibleDC(NULL); | 210 HDC deviceContext = ::CreateCompatibleDC(NULL); |
| 179 HFONT savefont = (HFONT)SelectObject(deviceContext, font); | 211 HFONT savefont = (HFONT)SelectObject(deviceContext, font); |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 221 } | 253 } |
| 222 | 254 |
| 223 protected: | 255 protected: |
| 224 virtual SkStream* onOpenStream(int* ttcIndex) const SK_OVERRIDE; | 256 virtual SkStream* onOpenStream(int* ttcIndex) const SK_OVERRIDE; |
| 225 virtual SkScalerContext* onCreateScalerContext(const SkDescriptor*) const SK
_OVERRIDE; | 257 virtual SkScalerContext* onCreateScalerContext(const SkDescriptor*) const SK
_OVERRIDE; |
| 226 virtual void onFilterRec(SkScalerContextRec*) const SK_OVERRIDE; | 258 virtual void onFilterRec(SkScalerContextRec*) const SK_OVERRIDE; |
| 227 virtual SkAdvancedTypefaceMetrics* onGetAdvancedTypefaceMetrics( | 259 virtual SkAdvancedTypefaceMetrics* onGetAdvancedTypefaceMetrics( |
| 228 SkAdvancedTypefaceMetrics::PerGlyphInfo, | 260 SkAdvancedTypefaceMetrics::PerGlyphInfo, |
| 229 const uint32_t*, uint32_t) const SK_OVERRIDE; | 261 const uint32_t*, uint32_t) const SK_OVERRIDE; |
| 230 virtual void onGetFontDescriptor(SkFontDescriptor*, bool*) const SK_OVERRIDE
; | 262 virtual void onGetFontDescriptor(SkFontDescriptor*, bool*) const SK_OVERRIDE
; |
| 263 virtual int onCountGlyphs() const SK_OVERRIDE; |
| 264 virtual int onGetUPEM() const SK_OVERRIDE; |
| 231 }; | 265 }; |
| 232 | 266 |
| 233 class FontMemResourceTypeface : public LogFontTypeface { | 267 class FontMemResourceTypeface : public LogFontTypeface { |
| 234 public: | 268 public: |
| 235 /** | 269 /** |
| 236 * Takes ownership of fontMemResource. | 270 * Takes ownership of fontMemResource. |
| 237 */ | 271 */ |
| 238 FontMemResourceTypeface(SkTypeface::Style style, SkFontID fontID, const LOGF
ONT& lf, HANDLE fontMemResource) : | 272 FontMemResourceTypeface(SkTypeface::Style style, SkFontID fontID, const LOGF
ONT& lf, HANDLE fontMemResource) : |
| 239 LogFontTypeface(style, fontID, lf, true), fFontMemResource(fontMemResour
ce) { | 273 LogFontTypeface(style, fontID, lf, true), fFontMemResource(fontMemResour
ce) { |
| 240 } | 274 } |
| (...skipping 476 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 717 ::ScriptFreeCache(&fSC); | 751 ::ScriptFreeCache(&fSC); |
| 718 } | 752 } |
| 719 } | 753 } |
| 720 | 754 |
| 721 bool SkScalerContext_Windows::isValid() const { | 755 bool SkScalerContext_Windows::isValid() const { |
| 722 return fDDC && fFont; | 756 return fDDC && fFont; |
| 723 } | 757 } |
| 724 | 758 |
| 725 unsigned SkScalerContext_Windows::generateGlyphCount() { | 759 unsigned SkScalerContext_Windows::generateGlyphCount() { |
| 726 if (fGlyphCount < 0) { | 760 if (fGlyphCount < 0) { |
| 727 if (fType == SkScalerContext_Windows::kBitmap_Type) { | 761 fGlyphCount = calculateGlyphCount( |
| 728 return fTM.tmLastChar; | 762 fDDC, static_cast<const LogFontTypeface*>(this->getTyp
eface())->fLogFont); |
| 729 } | |
| 730 fGlyphCount = calculateOutlineGlyphCount(fDDC); | |
| 731 } | 763 } |
| 732 return fGlyphCount; | 764 return fGlyphCount; |
| 733 } | 765 } |
| 734 | 766 |
| 735 uint16_t SkScalerContext_Windows::generateCharToGlyph(SkUnichar uni) { | 767 uint16_t SkScalerContext_Windows::generateCharToGlyph(SkUnichar uni) { |
| 736 uint16_t index = 0; | 768 uint16_t index = 0; |
| 737 WCHAR c[2]; | 769 WCHAR c[2]; |
| 738 // TODO(ctguil): Support characters that generate more than one glyph. | 770 // TODO(ctguil): Support characters that generate more than one glyph. |
| 739 if (SkUTF16_FromUnichar(uni, (uint16_t*)c) == 1) { | 771 if (SkUTF16_FromUnichar(uni, (uint16_t*)c) == 1) { |
| 740 // Type1 fonts fail with uniscribe API. Use GetGlyphIndices for plane 0. | 772 // Type1 fonts fail with uniscribe API. Use GetGlyphIndices for plane 0. |
| (...skipping 698 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1439 } | 1471 } |
| 1440 if (!otmRet || !GetTextFace(hdc, LF_FACESIZE, lf.lfFaceName)) { | 1472 if (!otmRet || !GetTextFace(hdc, LF_FACESIZE, lf.lfFaceName)) { |
| 1441 goto Error; | 1473 goto Error; |
| 1442 } | 1474 } |
| 1443 lf.lfHeight = -SkToS32(otm.otmEMSquare); | 1475 lf.lfHeight = -SkToS32(otm.otmEMSquare); |
| 1444 designFont = CreateFontIndirect(&lf); | 1476 designFont = CreateFontIndirect(&lf); |
| 1445 SelectObject(hdc, designFont); | 1477 SelectObject(hdc, designFont); |
| 1446 if (!GetOutlineTextMetrics(hdc, sizeof(otm), &otm)) { | 1478 if (!GetOutlineTextMetrics(hdc, sizeof(otm), &otm)) { |
| 1447 goto Error; | 1479 goto Error; |
| 1448 } | 1480 } |
| 1449 glyphCount = calculateOutlineGlyphCount(hdc); | 1481 glyphCount = calculateGlyphCount(hdc, fLogFont); |
| 1450 | 1482 |
| 1451 info = new SkAdvancedTypefaceMetrics; | 1483 info = new SkAdvancedTypefaceMetrics; |
| 1452 info->fEmSize = otm.otmEMSquare; | 1484 info->fEmSize = otm.otmEMSquare; |
| 1453 info->fMultiMaster = false; | 1485 info->fMultiMaster = false; |
| 1454 info->fLastGlyphID = SkToU16(glyphCount - 1); | 1486 info->fLastGlyphID = SkToU16(glyphCount - 1); |
| 1455 info->fStyle = 0; | 1487 info->fStyle = 0; |
| 1456 tchar_to_skstring(lf.lfFaceName, &info->fFontName); | 1488 tchar_to_skstring(lf.lfFaceName, &info->fFontName); |
| 1457 | 1489 |
| 1458 if (perGlyphInfo & SkAdvancedTypefaceMetrics::kToUnicode_PerGlyphInfo) { | 1490 if (perGlyphInfo & SkAdvancedTypefaceMetrics::kToUnicode_PerGlyphInfo) { |
| 1459 populate_glyph_to_unicode(hdc, glyphCount, &(info->fGlyphToUnicode)); | 1491 populate_glyph_to_unicode(hdc, glyphCount, &(info->fGlyphToUnicode)); |
| (...skipping 217 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1677 } | 1709 } |
| 1678 } | 1710 } |
| 1679 | 1711 |
| 1680 SelectObject(hdc, savefont); | 1712 SelectObject(hdc, savefont); |
| 1681 DeleteObject(font); | 1713 DeleteObject(font); |
| 1682 DeleteDC(hdc); | 1714 DeleteDC(hdc); |
| 1683 | 1715 |
| 1684 return stream; | 1716 return stream; |
| 1685 } | 1717 } |
| 1686 | 1718 |
| 1719 int LogFontTypeface::onCountGlyphs() const { |
| 1720 HDC hdc = ::CreateCompatibleDC(NULL); |
| 1721 HFONT font = CreateFontIndirect(&fLogFont); |
| 1722 HFONT savefont = (HFONT)SelectObject(hdc, font); |
| 1723 |
| 1724 unsigned int glyphCount = calculateGlyphCount(hdc, fLogFont); |
| 1725 |
| 1726 SelectObject(hdc, savefont); |
| 1727 DeleteObject(font); |
| 1728 DeleteDC(hdc); |
| 1729 |
| 1730 return glyphCount; |
| 1731 } |
| 1732 |
| 1733 int LogFontTypeface::onGetUPEM() const { |
| 1734 HDC hdc = ::CreateCompatibleDC(NULL); |
| 1735 HFONT font = CreateFontIndirect(&fLogFont); |
| 1736 HFONT savefont = (HFONT)SelectObject(hdc, font); |
| 1737 |
| 1738 unsigned int upem = calculateUPEM(hdc, fLogFont); |
| 1739 |
| 1740 SelectObject(hdc, savefont); |
| 1741 DeleteObject(font); |
| 1742 DeleteDC(hdc); |
| 1743 |
| 1744 return upem; |
| 1745 } |
| 1746 |
| 1687 SkScalerContext* LogFontTypeface::onCreateScalerContext(const SkDescriptor* desc
) const { | 1747 SkScalerContext* LogFontTypeface::onCreateScalerContext(const SkDescriptor* desc
) const { |
| 1688 SkScalerContext_Windows* ctx = SkNEW_ARGS(SkScalerContext_Windows, | 1748 SkScalerContext_Windows* ctx = SkNEW_ARGS(SkScalerContext_Windows, |
| 1689 (const_cast<LogFontTypeface*>(th
is), desc)); | 1749 (const_cast<LogFontTypeface*>(th
is), desc)); |
| 1690 if (!ctx->isValid()) { | 1750 if (!ctx->isValid()) { |
| 1691 SkDELETE(ctx); | 1751 SkDELETE(ctx); |
| 1692 ctx = NULL; | 1752 ctx = NULL; |
| 1693 } | 1753 } |
| 1694 return ctx; | 1754 return ctx; |
| 1695 } | 1755 } |
| 1696 | 1756 |
| (...skipping 247 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1944 return this->createFromStream(stream); | 2004 return this->createFromStream(stream); |
| 1945 } | 2005 } |
| 1946 | 2006 |
| 1947 private: | 2007 private: |
| 1948 SkTDArray<ENUMLOGFONTEX> fLogFontArray; | 2008 SkTDArray<ENUMLOGFONTEX> fLogFontArray; |
| 1949 }; | 2009 }; |
| 1950 | 2010 |
| 1951 SkFontMgr* SkFontMgr::Factory() { | 2011 SkFontMgr* SkFontMgr::Factory() { |
| 1952 return SkNEW(SkFontMgrGDI); | 2012 return SkNEW(SkFontMgrGDI); |
| 1953 } | 2013 } |
| OLD | NEW |