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 call_ensure_accessible(lf); | |
148 if (0 == GetTextMetrics(hdc, &textMetric)) { | |
149 textMetric.tmPitchAndFamily = TMPF_TRUETYPE; | |
vandebo (ex-Chrome)
2013/07/15 17:32:56
Maybe put this on line 146 to make it more obvious
bungeman-skia
2013/07/15 18:21:36
Done. I dislike unneeded stores, but I suppose I d
| |
150 } | |
151 } | |
152 | |
153 if (!(textMetric.tmPitchAndFamily & TMPF_VECTOR)) { | |
154 return textMetric.tmLastChar; | |
155 } | |
156 | |
144 // The 'maxp' table stores the number of glyphs at offset 4, in 2 bytes. | 157 // 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; | 158 uint16_t glyphs; |
148 if (GetFontData(hdc, maxpTag, 4, &glyphs, sizeof(glyphs)) != GDI_ERROR) { | 159 if (GDI_ERROR != GetFontData(hdc, SkOTTableMaximumProfile::TAG, 4, &glyphs, sizeof(glyphs))) { |
149 return SkEndian_SwapBE16(glyphs); | 160 return SkEndian_SwapBE16(glyphs); |
150 } | 161 } |
151 | 162 |
152 // Binary search for glyph count. | 163 // Binary search for glyph count. |
153 static const MAT2 mat2 = {{0, 1}, {0, 0}, {0, 0}, {0, 1}}; | 164 static const MAT2 mat2 = {{0, 1}, {0, 0}, {0, 0}, {0, 1}}; |
154 int32_t max = SK_MaxU16 + 1; | 165 int32_t max = SK_MaxU16 + 1; |
155 int32_t min = 0; | 166 int32_t min = 0; |
156 GLYPHMETRICS gm; | 167 GLYPHMETRICS gm; |
157 while (min < max) { | 168 while (min < max) { |
158 int32_t mid = min + ((max - min) / 2); | 169 int32_t mid = min + ((max - min) / 2); |
159 if (GetGlyphOutlineW(hdc, mid, GGO_METRICS | GGO_GLYPH_INDEX, &gm, 0, | 170 if (GetGlyphOutlineW(hdc, mid, GGO_METRICS | GGO_GLYPH_INDEX, &gm, 0, |
160 NULL, &mat2) == GDI_ERROR) { | 171 NULL, &mat2) == GDI_ERROR) { |
161 max = mid; | 172 max = mid; |
162 } else { | 173 } else { |
163 min = mid + 1; | 174 min = mid + 1; |
164 } | 175 } |
165 } | 176 } |
166 SkASSERT(min == max); | 177 SkASSERT(min == max); |
167 return min; | 178 return min; |
168 } | 179 } |
169 | 180 |
181 static unsigned calculateUPEM(HDC hdc, const LOGFONT& lf) { | |
182 TEXTMETRIC textMetric; | |
vandebo (ex-Chrome)
2013/07/15 17:32:56
If you pull this out into a helper function you co
bungeman-skia
2013/07/15 18:21:36
This doesn't want to be in a helper, it wants to b
| |
183 if (0 == GetTextMetrics(hdc, &textMetric)) { | |
184 call_ensure_accessible(lf); | |
185 if (0 == GetTextMetrics(hdc, &textMetric)) { | |
186 textMetric.tmPitchAndFamily = TMPF_TRUETYPE; | |
187 } | |
188 } | |
189 | |
190 if (!(textMetric.tmPitchAndFamily & TMPF_VECTOR)) { | |
191 return textMetric.tmMaxCharWidth; | |
192 } | |
193 | |
194 OUTLINETEXTMETRIC otm; | |
195 unsigned int otmRet = GetOutlineTextMetrics(hdc, sizeof(otm), &otm); | |
196 if (0 == otmRet) { | |
197 call_ensure_accessible(lf); | |
198 otmRet = GetOutlineTextMetrics(hdc, sizeof(otm), &otm); | |
199 } | |
200 | |
201 return (0 == otmRet) ? 0 : otm.otmEMSquare; | |
202 } | |
203 | |
170 class LogFontTypeface : public SkTypeface { | 204 class LogFontTypeface : public SkTypeface { |
171 public: | 205 public: |
172 LogFontTypeface(SkTypeface::Style style, SkFontID fontID, const LOGFONT& lf, bool serializeAsStream = false) : | 206 LogFontTypeface(SkTypeface::Style style, SkFontID fontID, const LOGFONT& lf, bool serializeAsStream = false) : |
173 SkTypeface(style, fontID, false), fLogFont(lf), fSerializeAsStream(seria lizeAsStream) { | 207 SkTypeface(style, fontID, false), fLogFont(lf), fSerializeAsStream(seria lizeAsStream) { |
174 | 208 |
175 // If the font has cubic outlines, it will not be rendered with ClearTyp e. | 209 // If the font has cubic outlines, it will not be rendered with ClearTyp e. |
176 HFONT font = CreateFontIndirect(&lf); | 210 HFONT font = CreateFontIndirect(&lf); |
177 | 211 |
178 HDC deviceContext = ::CreateCompatibleDC(NULL); | 212 HDC deviceContext = ::CreateCompatibleDC(NULL); |
179 HFONT savefont = (HFONT)SelectObject(deviceContext, font); | 213 HFONT savefont = (HFONT)SelectObject(deviceContext, font); |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
221 } | 255 } |
222 | 256 |
223 protected: | 257 protected: |
224 virtual SkStream* onOpenStream(int* ttcIndex) const SK_OVERRIDE; | 258 virtual SkStream* onOpenStream(int* ttcIndex) const SK_OVERRIDE; |
225 virtual SkScalerContext* onCreateScalerContext(const SkDescriptor*) const SK _OVERRIDE; | 259 virtual SkScalerContext* onCreateScalerContext(const SkDescriptor*) const SK _OVERRIDE; |
226 virtual void onFilterRec(SkScalerContextRec*) const SK_OVERRIDE; | 260 virtual void onFilterRec(SkScalerContextRec*) const SK_OVERRIDE; |
227 virtual SkAdvancedTypefaceMetrics* onGetAdvancedTypefaceMetrics( | 261 virtual SkAdvancedTypefaceMetrics* onGetAdvancedTypefaceMetrics( |
228 SkAdvancedTypefaceMetrics::PerGlyphInfo, | 262 SkAdvancedTypefaceMetrics::PerGlyphInfo, |
229 const uint32_t*, uint32_t) const SK_OVERRIDE; | 263 const uint32_t*, uint32_t) const SK_OVERRIDE; |
230 virtual void onGetFontDescriptor(SkFontDescriptor*, bool*) const SK_OVERRIDE ; | 264 virtual void onGetFontDescriptor(SkFontDescriptor*, bool*) const SK_OVERRIDE ; |
265 virtual int onCountGlyphs() const SK_OVERRIDE; | |
266 virtual int onGetUPEM() const SK_OVERRIDE; | |
231 }; | 267 }; |
232 | 268 |
233 class FontMemResourceTypeface : public LogFontTypeface { | 269 class FontMemResourceTypeface : public LogFontTypeface { |
234 public: | 270 public: |
235 /** | 271 /** |
236 * Takes ownership of fontMemResource. | 272 * Takes ownership of fontMemResource. |
237 */ | 273 */ |
238 FontMemResourceTypeface(SkTypeface::Style style, SkFontID fontID, const LOGF ONT& lf, HANDLE fontMemResource) : | 274 FontMemResourceTypeface(SkTypeface::Style style, SkFontID fontID, const LOGF ONT& lf, HANDLE fontMemResource) : |
239 LogFontTypeface(style, fontID, lf, true), fFontMemResource(fontMemResour ce) { | 275 LogFontTypeface(style, fontID, lf, true), fFontMemResource(fontMemResour ce) { |
240 } | 276 } |
(...skipping 476 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
717 ::ScriptFreeCache(&fSC); | 753 ::ScriptFreeCache(&fSC); |
718 } | 754 } |
719 } | 755 } |
720 | 756 |
721 bool SkScalerContext_Windows::isValid() const { | 757 bool SkScalerContext_Windows::isValid() const { |
722 return fDDC && fFont; | 758 return fDDC && fFont; |
723 } | 759 } |
724 | 760 |
725 unsigned SkScalerContext_Windows::generateGlyphCount() { | 761 unsigned SkScalerContext_Windows::generateGlyphCount() { |
726 if (fGlyphCount < 0) { | 762 if (fGlyphCount < 0) { |
727 if (fType == SkScalerContext_Windows::kBitmap_Type) { | 763 fGlyphCount = calculateGlyphCount( |
728 return fTM.tmLastChar; | 764 fDDC, static_cast<const LogFontTypeface*>(this->getTyp eface())->fLogFont); |
729 } | |
730 fGlyphCount = calculateOutlineGlyphCount(fDDC); | |
731 } | 765 } |
732 return fGlyphCount; | 766 return fGlyphCount; |
733 } | 767 } |
734 | 768 |
735 uint16_t SkScalerContext_Windows::generateCharToGlyph(SkUnichar uni) { | 769 uint16_t SkScalerContext_Windows::generateCharToGlyph(SkUnichar uni) { |
736 uint16_t index = 0; | 770 uint16_t index = 0; |
737 WCHAR c[2]; | 771 WCHAR c[2]; |
738 // TODO(ctguil): Support characters that generate more than one glyph. | 772 // TODO(ctguil): Support characters that generate more than one glyph. |
739 if (SkUTF16_FromUnichar(uni, (uint16_t*)c) == 1) { | 773 if (SkUTF16_FromUnichar(uni, (uint16_t*)c) == 1) { |
740 // Type1 fonts fail with uniscribe API. Use GetGlyphIndices for plane 0. | 774 // 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 } | 1473 } |
1440 if (!otmRet || !GetTextFace(hdc, LF_FACESIZE, lf.lfFaceName)) { | 1474 if (!otmRet || !GetTextFace(hdc, LF_FACESIZE, lf.lfFaceName)) { |
1441 goto Error; | 1475 goto Error; |
1442 } | 1476 } |
1443 lf.lfHeight = -SkToS32(otm.otmEMSquare); | 1477 lf.lfHeight = -SkToS32(otm.otmEMSquare); |
1444 designFont = CreateFontIndirect(&lf); | 1478 designFont = CreateFontIndirect(&lf); |
1445 SelectObject(hdc, designFont); | 1479 SelectObject(hdc, designFont); |
1446 if (!GetOutlineTextMetrics(hdc, sizeof(otm), &otm)) { | 1480 if (!GetOutlineTextMetrics(hdc, sizeof(otm), &otm)) { |
1447 goto Error; | 1481 goto Error; |
1448 } | 1482 } |
1449 glyphCount = calculateOutlineGlyphCount(hdc); | 1483 glyphCount = calculateGlyphCount(hdc, fLogFont); |
1450 | 1484 |
1451 info = new SkAdvancedTypefaceMetrics; | 1485 info = new SkAdvancedTypefaceMetrics; |
1452 info->fEmSize = otm.otmEMSquare; | 1486 info->fEmSize = otm.otmEMSquare; |
1453 info->fMultiMaster = false; | 1487 info->fMultiMaster = false; |
1454 info->fLastGlyphID = SkToU16(glyphCount - 1); | 1488 info->fLastGlyphID = SkToU16(glyphCount - 1); |
1455 info->fStyle = 0; | 1489 info->fStyle = 0; |
1456 tchar_to_skstring(lf.lfFaceName, &info->fFontName); | 1490 tchar_to_skstring(lf.lfFaceName, &info->fFontName); |
1457 | 1491 |
1458 if (perGlyphInfo & SkAdvancedTypefaceMetrics::kToUnicode_PerGlyphInfo) { | 1492 if (perGlyphInfo & SkAdvancedTypefaceMetrics::kToUnicode_PerGlyphInfo) { |
1459 populate_glyph_to_unicode(hdc, glyphCount, &(info->fGlyphToUnicode)); | 1493 populate_glyph_to_unicode(hdc, glyphCount, &(info->fGlyphToUnicode)); |
(...skipping 217 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1677 } | 1711 } |
1678 } | 1712 } |
1679 | 1713 |
1680 SelectObject(hdc, savefont); | 1714 SelectObject(hdc, savefont); |
1681 DeleteObject(font); | 1715 DeleteObject(font); |
1682 DeleteDC(hdc); | 1716 DeleteDC(hdc); |
1683 | 1717 |
1684 return stream; | 1718 return stream; |
1685 } | 1719 } |
1686 | 1720 |
1721 int LogFontTypeface::onCountGlyphs() const { | |
1722 HDC hdc = ::CreateCompatibleDC(NULL); | |
1723 HFONT font = CreateFontIndirect(&fLogFont); | |
1724 HFONT savefont = (HFONT)SelectObject(hdc, font); | |
1725 | |
1726 unsigned int glyphCount = calculateGlyphCount(hdc, fLogFont); | |
1727 | |
1728 SelectObject(hdc, savefont); | |
1729 DeleteObject(font); | |
1730 DeleteDC(hdc); | |
1731 | |
1732 return glyphCount; | |
1733 } | |
1734 | |
1735 int LogFontTypeface::onGetUPEM() const { | |
1736 HDC hdc = ::CreateCompatibleDC(NULL); | |
1737 HFONT font = CreateFontIndirect(&fLogFont); | |
1738 HFONT savefont = (HFONT)SelectObject(hdc, font); | |
1739 | |
1740 unsigned int upem = calculateUPEM(hdc, fLogFont); | |
1741 | |
1742 SelectObject(hdc, savefont); | |
1743 DeleteObject(font); | |
1744 DeleteDC(hdc); | |
1745 | |
1746 return upem; | |
1747 } | |
1748 | |
1687 SkScalerContext* LogFontTypeface::onCreateScalerContext(const SkDescriptor* desc ) const { | 1749 SkScalerContext* LogFontTypeface::onCreateScalerContext(const SkDescriptor* desc ) const { |
1688 SkScalerContext_Windows* ctx = SkNEW_ARGS(SkScalerContext_Windows, | 1750 SkScalerContext_Windows* ctx = SkNEW_ARGS(SkScalerContext_Windows, |
1689 (const_cast<LogFontTypeface*>(th is), desc)); | 1751 (const_cast<LogFontTypeface*>(th is), desc)); |
1690 if (!ctx->isValid()) { | 1752 if (!ctx->isValid()) { |
1691 SkDELETE(ctx); | 1753 SkDELETE(ctx); |
1692 ctx = NULL; | 1754 ctx = NULL; |
1693 } | 1755 } |
1694 return ctx; | 1756 return ctx; |
1695 } | 1757 } |
1696 | 1758 |
(...skipping 247 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1944 return this->createFromStream(stream); | 2006 return this->createFromStream(stream); |
1945 } | 2007 } |
1946 | 2008 |
1947 private: | 2009 private: |
1948 SkTDArray<ENUMLOGFONTEX> fLogFontArray; | 2010 SkTDArray<ENUMLOGFONTEX> fLogFontArray; |
1949 }; | 2011 }; |
1950 | 2012 |
1951 SkFontMgr* SkFontMgr::Factory() { | 2013 SkFontMgr* SkFontMgr::Factory() { |
1952 return SkNEW(SkFontMgrGDI); | 2014 return SkNEW(SkFontMgrGDI); |
1953 } | 2015 } |
OLD | NEW |