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 |