Chromium Code Reviews| 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 |