Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(434)

Side by Side Diff: src/ports/SkFontHost_win.cpp

Issue 19231003: Implement onCountGlyphs and onGetUPEM on Windows. (Closed) Base URL: http://skia.googlecode.com/svn/trunk/
Patch Set: Created 7 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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
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
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
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
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
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
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 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698