OLD | NEW |
1 /* | 1 /* |
2 * Copyright 2006 The Android Open Source Project | 2 * Copyright 2006 The Android Open Source Project |
3 * | 3 * |
4 * Use of this source code is governed by a BSD-style license that can be | 4 * Use of this source code is governed by a BSD-style license that can be |
5 * found in the LICENSE file. | 5 * found in the LICENSE file. |
6 */ | 6 */ |
7 | 7 |
8 #include "SkAdvancedTypefaceMetrics.h" | 8 #include "SkAdvancedTypefaceMetrics.h" |
9 #include "SkBase64.h" | 9 #include "SkBase64.h" |
10 #include "SkColorPriv.h" | 10 #include "SkColorPriv.h" |
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
80 return true; | 80 return true; |
81 } | 81 } |
82 #endif | 82 #endif |
83 return rec.getHinting() == SkPaint::kNo_Hinting || rec.getHinting() == SkPai
nt::kSlight_Hinting; | 83 return rec.getHinting() == SkPaint::kNo_Hinting || rec.getHinting() == SkPai
nt::kSlight_Hinting; |
84 } | 84 } |
85 | 85 |
86 using namespace skia_advanced_typeface_metrics_utils; | 86 using namespace skia_advanced_typeface_metrics_utils; |
87 | 87 |
88 static void tchar_to_skstring(const TCHAR t[], SkString* s) { | 88 static void tchar_to_skstring(const TCHAR t[], SkString* s) { |
89 #ifdef UNICODE | 89 #ifdef UNICODE |
90 size_t sSize = WideCharToMultiByte(CP_UTF8, 0, t, -1, NULL, 0, NULL, NULL); | 90 size_t sSize = WideCharToMultiByte(CP_UTF8, 0, t, -1, nullptr, 0, nullptr, n
ullptr); |
91 s->resize(sSize); | 91 s->resize(sSize); |
92 WideCharToMultiByte(CP_UTF8, 0, t, -1, s->writable_str(), sSize, NULL, NULL)
; | 92 WideCharToMultiByte(CP_UTF8, 0, t, -1, s->writable_str(), sSize, nullptr, nu
llptr); |
93 #else | 93 #else |
94 s->set(t); | 94 s->set(t); |
95 #endif | 95 #endif |
96 } | 96 } |
97 | 97 |
98 static void dcfontname_to_skstring(HDC deviceContext, const LOGFONT& lf, SkStrin
g* familyName) { | 98 static void dcfontname_to_skstring(HDC deviceContext, const LOGFONT& lf, SkStrin
g* familyName) { |
99 int fontNameLen; //length of fontName in TCHARS. | 99 int fontNameLen; //length of fontName in TCHARS. |
100 if (0 == (fontNameLen = GetTextFace(deviceContext, 0, NULL))) { | 100 if (0 == (fontNameLen = GetTextFace(deviceContext, 0, nullptr))) { |
101 call_ensure_accessible(lf); | 101 call_ensure_accessible(lf); |
102 if (0 == (fontNameLen = GetTextFace(deviceContext, 0, NULL))) { | 102 if (0 == (fontNameLen = GetTextFace(deviceContext, 0, nullptr))) { |
103 fontNameLen = 0; | 103 fontNameLen = 0; |
104 } | 104 } |
105 } | 105 } |
106 | 106 |
107 SkAutoSTArray<LF_FULLFACESIZE, TCHAR> fontName(fontNameLen+1); | 107 SkAutoSTArray<LF_FULLFACESIZE, TCHAR> fontName(fontNameLen+1); |
108 if (0 == GetTextFace(deviceContext, fontNameLen, fontName.get())) { | 108 if (0 == GetTextFace(deviceContext, fontNameLen, fontName.get())) { |
109 call_ensure_accessible(lf); | 109 call_ensure_accessible(lf); |
110 if (0 == GetTextFace(deviceContext, fontNameLen, fontName.get())) { | 110 if (0 == GetTextFace(deviceContext, fontNameLen, fontName.get())) { |
111 fontName[0] = 0; | 111 fontName[0] = 0; |
112 } | 112 } |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
162 } | 162 } |
163 | 163 |
164 // Binary search for glyph count. | 164 // Binary search for glyph count. |
165 static const MAT2 mat2 = {{0, 1}, {0, 0}, {0, 0}, {0, 1}}; | 165 static const MAT2 mat2 = {{0, 1}, {0, 0}, {0, 0}, {0, 1}}; |
166 int32_t max = SK_MaxU16 + 1; | 166 int32_t max = SK_MaxU16 + 1; |
167 int32_t min = 0; | 167 int32_t min = 0; |
168 GLYPHMETRICS gm; | 168 GLYPHMETRICS gm; |
169 while (min < max) { | 169 while (min < max) { |
170 int32_t mid = min + ((max - min) / 2); | 170 int32_t mid = min + ((max - min) / 2); |
171 if (GetGlyphOutlineW(hdc, mid, GGO_METRICS | GGO_GLYPH_INDEX, &gm, 0, | 171 if (GetGlyphOutlineW(hdc, mid, GGO_METRICS | GGO_GLYPH_INDEX, &gm, 0, |
172 NULL, &mat2) == GDI_ERROR) { | 172 nullptr, &mat2) == GDI_ERROR) { |
173 max = mid; | 173 max = mid; |
174 } else { | 174 } else { |
175 min = mid + 1; | 175 min = mid + 1; |
176 } | 176 } |
177 } | 177 } |
178 SkASSERT(min == max); | 178 SkASSERT(min == max); |
179 return min; | 179 return min; |
180 } | 180 } |
181 | 181 |
182 static unsigned calculateUPEM(HDC hdc, const LOGFONT& lf) { | 182 static unsigned calculateUPEM(HDC hdc, const LOGFONT& lf) { |
(...skipping 22 matching lines...) Expand all Loading... |
205 public: | 205 public: |
206 LogFontTypeface(const SkFontStyle& style, const LOGFONT& lf, bool serializeA
sStream) | 206 LogFontTypeface(const SkFontStyle& style, const LOGFONT& lf, bool serializeA
sStream) |
207 : SkTypeface(style, SkTypefaceCache::NewFontID(), false) | 207 : SkTypeface(style, SkTypefaceCache::NewFontID(), false) |
208 , fLogFont(lf) | 208 , fLogFont(lf) |
209 , fSerializeAsStream(serializeAsStream) | 209 , fSerializeAsStream(serializeAsStream) |
210 { | 210 { |
211 | 211 |
212 // If the font has cubic outlines, it will not be rendered with ClearTyp
e. | 212 // If the font has cubic outlines, it will not be rendered with ClearTyp
e. |
213 HFONT font = CreateFontIndirect(&lf); | 213 HFONT font = CreateFontIndirect(&lf); |
214 | 214 |
215 HDC deviceContext = ::CreateCompatibleDC(NULL); | 215 HDC deviceContext = ::CreateCompatibleDC(nullptr); |
216 HFONT savefont = (HFONT)SelectObject(deviceContext, font); | 216 HFONT savefont = (HFONT)SelectObject(deviceContext, font); |
217 | 217 |
218 TEXTMETRIC textMetric; | 218 TEXTMETRIC textMetric; |
219 if (0 == GetTextMetrics(deviceContext, &textMetric)) { | 219 if (0 == GetTextMetrics(deviceContext, &textMetric)) { |
220 call_ensure_accessible(lf); | 220 call_ensure_accessible(lf); |
221 if (0 == GetTextMetrics(deviceContext, &textMetric)) { | 221 if (0 == GetTextMetrics(deviceContext, &textMetric)) { |
222 textMetric.tmPitchAndFamily = TMPF_TRUETYPE; | 222 textMetric.tmPitchAndFamily = TMPF_TRUETYPE; |
223 } | 223 } |
224 } | 224 } |
225 if (deviceContext) { | 225 if (deviceContext) { |
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
313 } | 313 } |
314 | 314 |
315 /** | 315 /** |
316 * This guy is public. It first searches the cache, and if a match is not found
, | 316 * This guy is public. It first searches the cache, and if a match is not found
, |
317 * it creates a new face. | 317 * it creates a new face. |
318 */ | 318 */ |
319 SkTypeface* SkCreateTypefaceFromLOGFONT(const LOGFONT& origLF) { | 319 SkTypeface* SkCreateTypefaceFromLOGFONT(const LOGFONT& origLF) { |
320 LOGFONT lf = origLF; | 320 LOGFONT lf = origLF; |
321 make_canonical(&lf); | 321 make_canonical(&lf); |
322 SkTypeface* face = SkTypefaceCache::FindByProcAndRef(FindByLogFont, &lf); | 322 SkTypeface* face = SkTypefaceCache::FindByProcAndRef(FindByLogFont, &lf); |
323 if (NULL == face) { | 323 if (nullptr == face) { |
324 face = LogFontTypeface::Create(lf); | 324 face = LogFontTypeface::Create(lf); |
325 SkTypefaceCache::Add(face, get_style(lf)); | 325 SkTypefaceCache::Add(face, get_style(lf)); |
326 } | 326 } |
327 return face; | 327 return face; |
328 } | 328 } |
329 | 329 |
330 /** | 330 /** |
331 * The created SkTypeface takes ownership of fontMemResource. | 331 * The created SkTypeface takes ownership of fontMemResource. |
332 */ | 332 */ |
333 SkTypeface* SkCreateFontMemResourceTypefaceFromLOGFONT(const LOGFONT& origLF, HA
NDLE fontMemResource) { | 333 SkTypeface* SkCreateFontMemResourceTypefaceFromLOGFONT(const LOGFONT& origLF, HA
NDLE fontMemResource) { |
334 LOGFONT lf = origLF; | 334 LOGFONT lf = origLF; |
335 make_canonical(&lf); | 335 make_canonical(&lf); |
336 // We'll never get a cache hit, so no point in putting this in SkTypefaceCac
he. | 336 // We'll never get a cache hit, so no point in putting this in SkTypefaceCac
he. |
337 return FontMemResourceTypeface::Create(lf, fontMemResource); | 337 return FontMemResourceTypeface::Create(lf, fontMemResource); |
338 } | 338 } |
339 | 339 |
340 /** | 340 /** |
341 * This guy is public | 341 * This guy is public |
342 */ | 342 */ |
343 void SkLOGFONTFromTypeface(const SkTypeface* face, LOGFONT* lf) { | 343 void SkLOGFONTFromTypeface(const SkTypeface* face, LOGFONT* lf) { |
344 if (NULL == face) { | 344 if (nullptr == face) { |
345 *lf = get_default_font(); | 345 *lf = get_default_font(); |
346 } else { | 346 } else { |
347 *lf = static_cast<const LogFontTypeface*>(face)->fLogFont; | 347 *lf = static_cast<const LogFontTypeface*>(face)->fLogFont; |
348 } | 348 } |
349 } | 349 } |
350 | 350 |
351 // Construct Glyph to Unicode table. | 351 // Construct Glyph to Unicode table. |
352 // Unicode code points that require conjugate pairs in utf16 are not | 352 // Unicode code points that require conjugate pairs in utf16 are not |
353 // supported. | 353 // supported. |
354 // TODO(arthurhsu): Add support for conjugate pairs. It looks like that may | 354 // TODO(arthurhsu): Add support for conjugate pairs. It looks like that may |
355 // require parsing the TTF cmap table (platform 4, encoding 12) directly instead | 355 // require parsing the TTF cmap table (platform 4, encoding 12) directly instead |
356 // of calling GetFontUnicodeRange(). | 356 // of calling GetFontUnicodeRange(). |
357 static void populate_glyph_to_unicode(HDC fontHdc, const unsigned glyphCount, | 357 static void populate_glyph_to_unicode(HDC fontHdc, const unsigned glyphCount, |
358 SkTDArray<SkUnichar>* glyphToUnicode) { | 358 SkTDArray<SkUnichar>* glyphToUnicode) { |
359 DWORD glyphSetBufferSize = GetFontUnicodeRanges(fontHdc, NULL); | 359 DWORD glyphSetBufferSize = GetFontUnicodeRanges(fontHdc, nullptr); |
360 if (!glyphSetBufferSize) { | 360 if (!glyphSetBufferSize) { |
361 return; | 361 return; |
362 } | 362 } |
363 | 363 |
364 SkAutoTDeleteArray<BYTE> glyphSetBuffer(new BYTE[glyphSetBufferSize]); | 364 SkAutoTDeleteArray<BYTE> glyphSetBuffer(new BYTE[glyphSetBufferSize]); |
365 GLYPHSET* glyphSet = | 365 GLYPHSET* glyphSet = |
366 reinterpret_cast<LPGLYPHSET>(glyphSetBuffer.get()); | 366 reinterpret_cast<LPGLYPHSET>(glyphSetBuffer.get()); |
367 if (GetFontUnicodeRanges(fontHdc, glyphSet) != glyphSetBufferSize) { | 367 if (GetFontUnicodeRanges(fontHdc, glyphSet) != glyphSetBufferSize) { |
368 return; | 368 return; |
369 } | 369 } |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
409 struct MyBitmapInfo : public BITMAPINFO { | 409 struct MyBitmapInfo : public BITMAPINFO { |
410 RGBQUAD fMoreSpaceForColors[1]; | 410 RGBQUAD fMoreSpaceForColors[1]; |
411 }; | 411 }; |
412 | 412 |
413 class HDCOffscreen { | 413 class HDCOffscreen { |
414 public: | 414 public: |
415 HDCOffscreen() { | 415 HDCOffscreen() { |
416 fFont = 0; | 416 fFont = 0; |
417 fDC = 0; | 417 fDC = 0; |
418 fBM = 0; | 418 fBM = 0; |
419 fBits = NULL; | 419 fBits = nullptr; |
420 fWidth = fHeight = 0; | 420 fWidth = fHeight = 0; |
421 fIsBW = false; | 421 fIsBW = false; |
422 } | 422 } |
423 | 423 |
424 ~HDCOffscreen() { | 424 ~HDCOffscreen() { |
425 if (fDC) { | 425 if (fDC) { |
426 DeleteDC(fDC); | 426 DeleteDC(fDC); |
427 } | 427 } |
428 if (fBM) { | 428 if (fBM) { |
429 DeleteObject(fBM); | 429 DeleteObject(fBM); |
(...skipping 18 matching lines...) Expand all Loading... |
448 bool fIsBW; | 448 bool fIsBW; |
449 }; | 449 }; |
450 | 450 |
451 const void* HDCOffscreen::draw(const SkGlyph& glyph, bool isBW, | 451 const void* HDCOffscreen::draw(const SkGlyph& glyph, bool isBW, |
452 size_t* srcRBPtr) { | 452 size_t* srcRBPtr) { |
453 // Can we share the scalercontext's fDDC, so we don't need to create | 453 // Can we share the scalercontext's fDDC, so we don't need to create |
454 // a separate fDC here? | 454 // a separate fDC here? |
455 if (0 == fDC) { | 455 if (0 == fDC) { |
456 fDC = CreateCompatibleDC(0); | 456 fDC = CreateCompatibleDC(0); |
457 if (0 == fDC) { | 457 if (0 == fDC) { |
458 return NULL; | 458 return nullptr; |
459 } | 459 } |
460 SetGraphicsMode(fDC, GM_ADVANCED); | 460 SetGraphicsMode(fDC, GM_ADVANCED); |
461 SetBkMode(fDC, TRANSPARENT); | 461 SetBkMode(fDC, TRANSPARENT); |
462 SetTextAlign(fDC, TA_LEFT | TA_BASELINE); | 462 SetTextAlign(fDC, TA_LEFT | TA_BASELINE); |
463 SelectObject(fDC, fFont); | 463 SelectObject(fDC, fFont); |
464 | 464 |
465 COLORREF color = 0x00FFFFFF; | 465 COLORREF color = 0x00FFFFFF; |
466 SkDEBUGCODE(COLORREF prev =) SetTextColor(fDC, color); | 466 SkDEBUGCODE(COLORREF prev =) SetTextColor(fDC, color); |
467 SkASSERT(prev != CLR_INVALID); | 467 SkASSERT(prev != CLR_INVALID); |
468 } | 468 } |
(...skipping 22 matching lines...) Expand all Loading... |
491 info.bmiHeader.biWidth = biWidth; | 491 info.bmiHeader.biWidth = biWidth; |
492 info.bmiHeader.biHeight = fHeight; | 492 info.bmiHeader.biHeight = fHeight; |
493 info.bmiHeader.biPlanes = 1; | 493 info.bmiHeader.biPlanes = 1; |
494 info.bmiHeader.biBitCount = isBW ? 1 : 32; | 494 info.bmiHeader.biBitCount = isBW ? 1 : 32; |
495 info.bmiHeader.biCompression = BI_RGB; | 495 info.bmiHeader.biCompression = BI_RGB; |
496 if (isBW) { | 496 if (isBW) { |
497 info.bmiHeader.biClrUsed = 2; | 497 info.bmiHeader.biClrUsed = 2; |
498 } | 498 } |
499 fBM = CreateDIBSection(fDC, &info, DIB_RGB_COLORS, &fBits, 0, 0); | 499 fBM = CreateDIBSection(fDC, &info, DIB_RGB_COLORS, &fBits, 0, 0); |
500 if (0 == fBM) { | 500 if (0 == fBM) { |
501 return NULL; | 501 return nullptr; |
502 } | 502 } |
503 SelectObject(fDC, fBM); | 503 SelectObject(fDC, fBM); |
504 } | 504 } |
505 | 505 |
506 // erase | 506 // erase |
507 size_t srcRB = isBW ? (biWidth >> 3) : (fWidth << 2); | 507 size_t srcRB = isBW ? (biWidth >> 3) : (fWidth << 2); |
508 size_t size = fHeight * srcRB; | 508 size_t size = fHeight * srcRB; |
509 memset(fBits, 0, size); | 509 memset(fBits, 0, size); |
510 | 510 |
511 XFORM xform = fXform; | 511 XFORM xform = fXform; |
512 xform.eDx = (float)-glyph.fLeft; | 512 xform.eDx = (float)-glyph.fLeft; |
513 xform.eDy = (float)-glyph.fTop; | 513 xform.eDy = (float)-glyph.fTop; |
514 SetWorldTransform(fDC, &xform); | 514 SetWorldTransform(fDC, &xform); |
515 | 515 |
516 uint16_t glyphID = glyph.getGlyphID(); | 516 uint16_t glyphID = glyph.getGlyphID(); |
517 BOOL ret = ExtTextOutW(fDC, 0, 0, ETO_GLYPH_INDEX, NULL, reinterpret_cast<LP
CWSTR>(&glyphID), 1, NULL); | 517 BOOL ret = ExtTextOutW(fDC, 0, 0, ETO_GLYPH_INDEX, nullptr, reinterpret_cast
<LPCWSTR>(&glyphID), 1, nullptr); |
518 GdiFlush(); | 518 GdiFlush(); |
519 if (0 == ret) { | 519 if (0 == ret) { |
520 return NULL; | 520 return nullptr; |
521 } | 521 } |
522 *srcRBPtr = srcRB; | 522 *srcRBPtr = srcRB; |
523 // offset to the start of the image | 523 // offset to the start of the image |
524 return (const char*)fBits + (fHeight - glyph.fHeight) * srcRB; | 524 return (const char*)fBits + (fHeight - glyph.fHeight) * srcRB; |
525 } | 525 } |
526 | 526 |
527 ////////////////////////////////////////////////////////////////////////////// | 527 ////////////////////////////////////////////////////////////////////////////// |
528 #define BUFFERSIZE (1 << 13) | 528 #define BUFFERSIZE (1 << 13) |
529 | 529 |
530 class SkScalerContext_GDI : public SkScalerContext { | 530 class SkScalerContext_GDI : public SkScalerContext { |
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
599 const SkDescriptor* desc) | 599 const SkDescriptor* desc) |
600 : SkScalerContext(rawTypeface, desc) | 600 : SkScalerContext(rawTypeface, desc) |
601 , fDDC(0) | 601 , fDDC(0) |
602 , fSavefont(0) | 602 , fSavefont(0) |
603 , fFont(0) | 603 , fFont(0) |
604 , fSC(0) | 604 , fSC(0) |
605 , fGlyphCount(-1) | 605 , fGlyphCount(-1) |
606 { | 606 { |
607 LogFontTypeface* typeface = reinterpret_cast<LogFontTypeface*>(rawTypeface); | 607 LogFontTypeface* typeface = reinterpret_cast<LogFontTypeface*>(rawTypeface); |
608 | 608 |
609 fDDC = ::CreateCompatibleDC(NULL); | 609 fDDC = ::CreateCompatibleDC(nullptr); |
610 if (!fDDC) { | 610 if (!fDDC) { |
611 return; | 611 return; |
612 } | 612 } |
613 SetGraphicsMode(fDDC, GM_ADVANCED); | 613 SetGraphicsMode(fDDC, GM_ADVANCED); |
614 SetBkMode(fDDC, TRANSPARENT); | 614 SetBkMode(fDDC, TRANSPARENT); |
615 | 615 |
616 // When GDI hinting, remove the entire Y scale from sA and GsA. (Prevents 'l
inear' metrics.) | 616 // When GDI hinting, remove the entire Y scale from sA and GsA. (Prevents 'l
inear' metrics.) |
617 // When not hinting, remove only the integer Y scale from sA and GsA. (Appli
ed by GDI.) | 617 // When not hinting, remove only the integer Y scale from sA and GsA. (Appli
ed by GDI.) |
618 SkScalerContextRec::PreMatrixScale scaleConstraints = | 618 SkScalerContextRec::PreMatrixScale scaleConstraints = |
619 (fRec.getHinting() == SkPaint::kNo_Hinting || fRec.getHinting() == SkPai
nt::kSlight_Hinting) | 619 (fRec.getHinting() == SkPaint::kNo_Hinting || fRec.getHinting() == SkPai
nt::kSlight_Hinting) |
(...skipping 179 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
799 fType == SkScalerContext_GDI::kLine_Type) | 799 fType == SkScalerContext_GDI::kLine_Type) |
800 /*&& winVer < Vista */) | 800 /*&& winVer < Vista */) |
801 ) | 801 ) |
802 { | 802 { |
803 index = 0; | 803 index = 0; |
804 } | 804 } |
805 } else { | 805 } else { |
806 // Use uniscribe to detemine glyph index for non-BMP characters. | 806 // Use uniscribe to detemine glyph index for non-BMP characters. |
807 static const int numWCHAR = 2; | 807 static const int numWCHAR = 2; |
808 static const int maxItems = 2; | 808 static const int maxItems = 2; |
809 // MSDN states that this can be NULL, but some things don't work then. | 809 // MSDN states that this can be nullptr, but some things don't work then
. |
810 SCRIPT_CONTROL sc = { 0 }; | 810 SCRIPT_CONTROL sc = { 0 }; |
811 // Add extra item to SCRIPT_ITEM to work around a bug (now documented). | 811 // Add extra item to SCRIPT_ITEM to work around a bug (now documented). |
812 // https://bugzilla.mozilla.org/show_bug.cgi?id=366643 | 812 // https://bugzilla.mozilla.org/show_bug.cgi?id=366643 |
813 SCRIPT_ITEM si[maxItems + 1]; | 813 SCRIPT_ITEM si[maxItems + 1]; |
814 int numItems; | 814 int numItems; |
815 HRZM(ScriptItemize(utf16, numWCHAR, maxItems, &sc, NULL, si, &numItems), | 815 HRZM(ScriptItemize(utf16, numWCHAR, maxItems, &sc, nullptr, si, &numItem
s), |
816 "Could not itemize character."); | 816 "Could not itemize character."); |
817 | 817 |
818 // Sometimes ScriptShape cannot find a glyph for a non-BMP and returns 2
space glyphs. | 818 // Sometimes ScriptShape cannot find a glyph for a non-BMP and returns 2
space glyphs. |
819 static const int maxGlyphs = 2; | 819 static const int maxGlyphs = 2; |
820 SCRIPT_VISATTR vsa[maxGlyphs]; | 820 SCRIPT_VISATTR vsa[maxGlyphs]; |
821 WORD outGlyphs[maxGlyphs]; | 821 WORD outGlyphs[maxGlyphs]; |
822 WORD logClust[numWCHAR]; | 822 WORD logClust[numWCHAR]; |
823 int numGlyphs; | 823 int numGlyphs; |
824 HRZM(ScriptShape(fDDC, &fSC, utf16, numWCHAR, maxGlyphs, &si[0].a, | 824 HRZM(ScriptShape(fDDC, &fSC, utf16, numWCHAR, maxGlyphs, &si[0].a, |
825 outGlyphs, logClust, vsa, &numGlyphs), | 825 outGlyphs, logClust, vsa, &numGlyphs), |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
876 glyph->fAdvanceX = SkFixedMul(SkFIXEDToFixed(fMat22.eM11), glyph->fAdvan
ceX); | 876 glyph->fAdvanceX = SkFixedMul(SkFIXEDToFixed(fMat22.eM11), glyph->fAdvan
ceX); |
877 | 877 |
878 return; | 878 return; |
879 } | 879 } |
880 | 880 |
881 UINT glyphId = glyph->getGlyphID(); | 881 UINT glyphId = glyph->getGlyphID(); |
882 | 882 |
883 GLYPHMETRICS gm; | 883 GLYPHMETRICS gm; |
884 sk_bzero(&gm, sizeof(gm)); | 884 sk_bzero(&gm, sizeof(gm)); |
885 | 885 |
886 DWORD status = GetGlyphOutlineW(fDDC, glyphId, GGO_METRICS | GGO_GLYPH_INDEX
, &gm, 0, NULL, &fMat22); | 886 DWORD status = GetGlyphOutlineW(fDDC, glyphId, GGO_METRICS | GGO_GLYPH_INDEX
, &gm, 0, nullptr, &fMat22); |
887 if (GDI_ERROR == status) { | 887 if (GDI_ERROR == status) { |
888 LogFontTypeface::EnsureAccessible(this->getTypeface()); | 888 LogFontTypeface::EnsureAccessible(this->getTypeface()); |
889 status = GetGlyphOutlineW(fDDC, glyphId, GGO_METRICS | GGO_GLYPH_INDEX,
&gm, 0, NULL, &fMat22); | 889 status = GetGlyphOutlineW(fDDC, glyphId, GGO_METRICS | GGO_GLYPH_INDEX,
&gm, 0, nullptr, &fMat22); |
890 if (GDI_ERROR == status) { | 890 if (GDI_ERROR == status) { |
891 glyph->zeroMetrics(); | 891 glyph->zeroMetrics(); |
892 return; | 892 return; |
893 } | 893 } |
894 } | 894 } |
895 | 895 |
896 bool empty = false; | 896 bool empty = false; |
897 // The black box is either the embedded bitmap size or the outline extent. | 897 // The black box is either the embedded bitmap size or the outline extent. |
898 // It is 1x1 if nothing is to be drawn, but will also be 1x1 if something ve
ry small | 898 // It is 1x1 if nothing is to be drawn, but will also be 1x1 if something ve
ry small |
899 // is to be drawn, like a '.'. We need to outset '.' but do not wish to outs
et ' '. | 899 // is to be drawn, like a '.'. We need to outset '.' but do not wish to outs
et ' '. |
900 if (1 == gm.gmBlackBoxX && 1 == gm.gmBlackBoxY) { | 900 if (1 == gm.gmBlackBoxX && 1 == gm.gmBlackBoxY) { |
901 // If GetGlyphOutline with GGO_NATIVE returns 0, we know there was no ou
tline. | 901 // If GetGlyphOutline with GGO_NATIVE returns 0, we know there was no ou
tline. |
902 DWORD bufferSize = GetGlyphOutlineW(fDDC, glyphId, GGO_NATIVE | GGO_GLYP
H_INDEX, &gm, 0, NULL, &fMat22); | 902 DWORD bufferSize = GetGlyphOutlineW(fDDC, glyphId, GGO_NATIVE | GGO_GLYP
H_INDEX, &gm, 0, nullptr, &fMat22); |
903 empty = (0 == bufferSize); | 903 empty = (0 == bufferSize); |
904 } | 904 } |
905 | 905 |
906 glyph->fTop = SkToS16(-gm.gmptGlyphOrigin.y); | 906 glyph->fTop = SkToS16(-gm.gmptGlyphOrigin.y); |
907 glyph->fLeft = SkToS16(gm.gmptGlyphOrigin.x); | 907 glyph->fLeft = SkToS16(gm.gmptGlyphOrigin.x); |
908 if (empty) { | 908 if (empty) { |
909 glyph->fWidth = 0; | 909 glyph->fWidth = 0; |
910 glyph->fHeight = 0; | 910 glyph->fHeight = 0; |
911 } else { | 911 } else { |
912 // Outset, since the image may bleed out of the black box. | 912 // Outset, since the image may bleed out of the black box. |
913 // For embedded bitmaps the black box should be exact. | 913 // For embedded bitmaps the black box should be exact. |
914 // For outlines we need to outset by 1 in all directions for bleed. | 914 // For outlines we need to outset by 1 in all directions for bleed. |
915 // For ClearType we need to outset by 2 for bleed. | 915 // For ClearType we need to outset by 2 for bleed. |
916 glyph->fWidth = gm.gmBlackBoxX + 4; | 916 glyph->fWidth = gm.gmBlackBoxX + 4; |
917 glyph->fHeight = gm.gmBlackBoxY + 4; | 917 glyph->fHeight = gm.gmBlackBoxY + 4; |
918 glyph->fTop -= 2; | 918 glyph->fTop -= 2; |
919 glyph->fLeft -= 2; | 919 glyph->fLeft -= 2; |
920 } | 920 } |
921 glyph->fAdvanceX = SkIntToFixed(gm.gmCellIncX); | 921 glyph->fAdvanceX = SkIntToFixed(gm.gmCellIncX); |
922 glyph->fAdvanceY = SkIntToFixed(gm.gmCellIncY); | 922 glyph->fAdvanceY = SkIntToFixed(gm.gmCellIncY); |
923 glyph->fRsbDelta = 0; | 923 glyph->fRsbDelta = 0; |
924 glyph->fLsbDelta = 0; | 924 glyph->fLsbDelta = 0; |
925 | 925 |
926 if (this->isSubpixel()) { | 926 if (this->isSubpixel()) { |
927 sk_bzero(&gm, sizeof(gm)); | 927 sk_bzero(&gm, sizeof(gm)); |
928 status = GetGlyphOutlineW(fDDC, glyphId, GGO_METRICS | GGO_GLYPH_INDEX,
&gm, 0, NULL, &fHighResMat22); | 928 status = GetGlyphOutlineW(fDDC, glyphId, GGO_METRICS | GGO_GLYPH_INDEX,
&gm, 0, nullptr, &fHighResMat22); |
929 if (GDI_ERROR != status) { | 929 if (GDI_ERROR != status) { |
930 SkPoint advance; | 930 SkPoint advance; |
931 fHiResMatrix.mapXY(SkIntToScalar(gm.gmCellIncX), SkIntToScalar(gm.gm
CellIncY), &advance); | 931 fHiResMatrix.mapXY(SkIntToScalar(gm.gmCellIncX), SkIntToScalar(gm.gm
CellIncY), &advance); |
932 glyph->fAdvanceX = SkScalarToFixed(advance.fX); | 932 glyph->fAdvanceX = SkScalarToFixed(advance.fX); |
933 glyph->fAdvanceY = SkScalarToFixed(advance.fY); | 933 glyph->fAdvanceY = SkScalarToFixed(advance.fY); |
934 } | 934 } |
935 } else if (!isAxisAligned(this->fRec)) { | 935 } else if (!isAxisAligned(this->fRec)) { |
936 status = GetGlyphOutlineW(fDDC, glyphId, GGO_METRICS | GGO_GLYPH_INDEX,
&gm, 0, NULL, &fGsA); | 936 status = GetGlyphOutlineW(fDDC, glyphId, GGO_METRICS | GGO_GLYPH_INDEX,
&gm, 0, nullptr, &fGsA); |
937 if (GDI_ERROR != status) { | 937 if (GDI_ERROR != status) { |
938 SkPoint advance; | 938 SkPoint advance; |
939 fG_inv.mapXY(SkIntToScalar(gm.gmCellIncX), SkIntToScalar(gm.gmCellIn
cY), &advance); | 939 fG_inv.mapXY(SkIntToScalar(gm.gmCellIncX), SkIntToScalar(gm.gmCellIn
cY), &advance); |
940 glyph->fAdvanceX = SkScalarToFixed(advance.fX); | 940 glyph->fAdvanceX = SkScalarToFixed(advance.fX); |
941 glyph->fAdvanceY = SkScalarToFixed(advance.fY); | 941 glyph->fAdvanceY = SkScalarToFixed(advance.fY); |
942 } | 942 } |
943 } | 943 } |
944 } | 944 } |
945 | 945 |
946 static const MAT2 gMat2Identity = {{0, 1}, {0, 0}, {0, 0}, {0, 1}}; | 946 static const MAT2 gMat2Identity = {{0, 1}, {0, 0}, {0, 0}, {0, 1}}; |
947 void SkScalerContext_GDI::generateFontMetrics(SkPaint::FontMetrics* metrics) { | 947 void SkScalerContext_GDI::generateFontMetrics(SkPaint::FontMetrics* metrics) { |
948 if (NULL == metrics) { | 948 if (nullptr == metrics) { |
949 return; | 949 return; |
950 } | 950 } |
951 sk_bzero(metrics, sizeof(*metrics)); | 951 sk_bzero(metrics, sizeof(*metrics)); |
952 | 952 |
953 SkASSERT(fDDC); | 953 SkASSERT(fDDC); |
954 | 954 |
955 #ifndef SK_GDI_ALWAYS_USE_TEXTMETRICS_FOR_FONT_METRICS | 955 #ifndef SK_GDI_ALWAYS_USE_TEXTMETRICS_FOR_FONT_METRICS |
956 if (fType == SkScalerContext_GDI::kBitmap_Type || fType == SkScalerContext_G
DI::kLine_Type) { | 956 if (fType == SkScalerContext_GDI::kBitmap_Type || fType == SkScalerContext_G
DI::kLine_Type) { |
957 #endif | 957 #endif |
958 metrics->fTop = SkIntToScalar(-fTM.tmAscent); | 958 metrics->fTop = SkIntToScalar(-fTM.tmAscent); |
(...skipping 265 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1224 } | 1224 } |
1225 | 1225 |
1226 void SkScalerContext_GDI::generateImage(const SkGlyph& glyph) { | 1226 void SkScalerContext_GDI::generateImage(const SkGlyph& glyph) { |
1227 SkASSERT(fDDC); | 1227 SkASSERT(fDDC); |
1228 | 1228 |
1229 const bool isBW = SkMask::kBW_Format == fRec.fMaskFormat; | 1229 const bool isBW = SkMask::kBW_Format == fRec.fMaskFormat; |
1230 const bool isAA = !isLCD(fRec); | 1230 const bool isAA = !isLCD(fRec); |
1231 | 1231 |
1232 size_t srcRB; | 1232 size_t srcRB; |
1233 const void* bits = fOffscreen.draw(glyph, isBW, &srcRB); | 1233 const void* bits = fOffscreen.draw(glyph, isBW, &srcRB); |
1234 if (NULL == bits) { | 1234 if (nullptr == bits) { |
1235 LogFontTypeface::EnsureAccessible(this->getTypeface()); | 1235 LogFontTypeface::EnsureAccessible(this->getTypeface()); |
1236 bits = fOffscreen.draw(glyph, isBW, &srcRB); | 1236 bits = fOffscreen.draw(glyph, isBW, &srcRB); |
1237 if (NULL == bits) { | 1237 if (nullptr == bits) { |
1238 sk_bzero(glyph.fImage, glyph.computeImageSize()); | 1238 sk_bzero(glyph.fImage, glyph.computeImageSize()); |
1239 return; | 1239 return; |
1240 } | 1240 } |
1241 } | 1241 } |
1242 | 1242 |
1243 if (!isBW) { | 1243 if (!isBW) { |
1244 const uint8_t* table; | 1244 const uint8_t* table; |
1245 //The offscreen contains a GDI blit if isAA and kGenA8FromLCD_Flag is no
t set. | 1245 //The offscreen contains a GDI blit if isAA and kGenA8FromLCD_Flag is no
t set. |
1246 //Otherwise the offscreen contains a ClearType blit. | 1246 //Otherwise the offscreen contains a ClearType blit. |
1247 if (isAA && !(fRec.fFlags & SkScalerContext::kGenA8FromLCD_Flag)) { | 1247 if (isAA && !(fRec.fFlags & SkScalerContext::kGenA8FromLCD_Flag)) { |
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1315 class GDIGlyphbufferPointIter { | 1315 class GDIGlyphbufferPointIter { |
1316 public: | 1316 public: |
1317 GDIGlyphbufferPointIter(const uint8_t* glyphbuf, DWORD total_size) | 1317 GDIGlyphbufferPointIter(const uint8_t* glyphbuf, DWORD total_size) |
1318 : fHeaderIter(glyphbuf, total_size), fCurveIter(), fPointIter() | 1318 : fHeaderIter(glyphbuf, total_size), fCurveIter(), fPointIter() |
1319 { } | 1319 { } |
1320 | 1320 |
1321 POINTFX const * next() { | 1321 POINTFX const * next() { |
1322 nextHeader: | 1322 nextHeader: |
1323 if (!fCurveIter.isSet()) { | 1323 if (!fCurveIter.isSet()) { |
1324 const TTPOLYGONHEADER* header = fHeaderIter.next(); | 1324 const TTPOLYGONHEADER* header = fHeaderIter.next(); |
1325 if (NULL == header) { | 1325 if (nullptr == header) { |
1326 return NULL; | 1326 return nullptr; |
1327 } | 1327 } |
1328 fCurveIter.set(header); | 1328 fCurveIter.set(header); |
1329 const TTPOLYCURVE* curve = fCurveIter.next(); | 1329 const TTPOLYCURVE* curve = fCurveIter.next(); |
1330 if (NULL == curve) { | 1330 if (nullptr == curve) { |
1331 return NULL; | 1331 return nullptr; |
1332 } | 1332 } |
1333 fPointIter.set(curve); | 1333 fPointIter.set(curve); |
1334 return &header->pfxStart; | 1334 return &header->pfxStart; |
1335 } | 1335 } |
1336 | 1336 |
1337 const POINTFX* nextPoint = fPointIter.next(); | 1337 const POINTFX* nextPoint = fPointIter.next(); |
1338 if (NULL == nextPoint) { | 1338 if (nullptr == nextPoint) { |
1339 const TTPOLYCURVE* curve = fCurveIter.next(); | 1339 const TTPOLYCURVE* curve = fCurveIter.next(); |
1340 if (NULL == curve) { | 1340 if (nullptr == curve) { |
1341 fCurveIter.set(); | 1341 fCurveIter.set(); |
1342 goto nextHeader; | 1342 goto nextHeader; |
1343 } else { | 1343 } else { |
1344 fPointIter.set(curve); | 1344 fPointIter.set(curve); |
1345 } | 1345 } |
1346 nextPoint = fPointIter.next(); | 1346 nextPoint = fPointIter.next(); |
1347 } | 1347 } |
1348 return nextPoint; | 1348 return nextPoint; |
1349 } | 1349 } |
1350 | 1350 |
1351 WORD currentCurveType() { | 1351 WORD currentCurveType() { |
1352 return fPointIter.fCurveType; | 1352 return fPointIter.fCurveType; |
1353 } | 1353 } |
1354 | 1354 |
1355 private: | 1355 private: |
1356 /** Iterates over all of the polygon headers in a glyphbuf. */ | 1356 /** Iterates over all of the polygon headers in a glyphbuf. */ |
1357 class GDIPolygonHeaderIter { | 1357 class GDIPolygonHeaderIter { |
1358 public: | 1358 public: |
1359 GDIPolygonHeaderIter(const uint8_t* glyphbuf, DWORD total_size) | 1359 GDIPolygonHeaderIter(const uint8_t* glyphbuf, DWORD total_size) |
1360 : fCurPolygon(reinterpret_cast<const TTPOLYGONHEADER*>(glyphbuf)) | 1360 : fCurPolygon(reinterpret_cast<const TTPOLYGONHEADER*>(glyphbuf)) |
1361 , fEndPolygon(SkTAddOffset<const TTPOLYGONHEADER>(glyphbuf, total_si
ze)) | 1361 , fEndPolygon(SkTAddOffset<const TTPOLYGONHEADER>(glyphbuf, total_si
ze)) |
1362 { } | 1362 { } |
1363 | 1363 |
1364 const TTPOLYGONHEADER* next() { | 1364 const TTPOLYGONHEADER* next() { |
1365 if (fCurPolygon >= fEndPolygon) { | 1365 if (fCurPolygon >= fEndPolygon) { |
1366 return NULL; | 1366 return nullptr; |
1367 } | 1367 } |
1368 const TTPOLYGONHEADER* thisPolygon = fCurPolygon; | 1368 const TTPOLYGONHEADER* thisPolygon = fCurPolygon; |
1369 fCurPolygon = SkTAddOffset<const TTPOLYGONHEADER>(fCurPolygon, fCurP
olygon->cb); | 1369 fCurPolygon = SkTAddOffset<const TTPOLYGONHEADER>(fCurPolygon, fCurP
olygon->cb); |
1370 return thisPolygon; | 1370 return thisPolygon; |
1371 } | 1371 } |
1372 private: | 1372 private: |
1373 const TTPOLYGONHEADER* fCurPolygon; | 1373 const TTPOLYGONHEADER* fCurPolygon; |
1374 const TTPOLYGONHEADER* fEndPolygon; | 1374 const TTPOLYGONHEADER* fEndPolygon; |
1375 }; | 1375 }; |
1376 | 1376 |
1377 /** Iterates over all of the polygon curves in a polygon header. */ | 1377 /** Iterates over all of the polygon curves in a polygon header. */ |
1378 class GDIPolygonCurveIter { | 1378 class GDIPolygonCurveIter { |
1379 public: | 1379 public: |
1380 GDIPolygonCurveIter() : fCurCurve(NULL), fEndCurve(NULL) { } | 1380 GDIPolygonCurveIter() : fCurCurve(nullptr), fEndCurve(nullptr) { } |
1381 | 1381 |
1382 GDIPolygonCurveIter(const TTPOLYGONHEADER* curPolygon) | 1382 GDIPolygonCurveIter(const TTPOLYGONHEADER* curPolygon) |
1383 : fCurCurve(SkTAddOffset<const TTPOLYCURVE>(curPolygon, sizeof(TTPOL
YGONHEADER))) | 1383 : fCurCurve(SkTAddOffset<const TTPOLYCURVE>(curPolygon, sizeof(TTPOL
YGONHEADER))) |
1384 , fEndCurve(SkTAddOffset<const TTPOLYCURVE>(curPolygon, curPolygon->
cb)) | 1384 , fEndCurve(SkTAddOffset<const TTPOLYCURVE>(curPolygon, curPolygon->
cb)) |
1385 { } | 1385 { } |
1386 | 1386 |
1387 bool isSet() { return fCurCurve != NULL; } | 1387 bool isSet() { return fCurCurve != nullptr; } |
1388 | 1388 |
1389 void set(const TTPOLYGONHEADER* curPolygon) { | 1389 void set(const TTPOLYGONHEADER* curPolygon) { |
1390 fCurCurve = SkTAddOffset<const TTPOLYCURVE>(curPolygon, sizeof(TTPOL
YGONHEADER)); | 1390 fCurCurve = SkTAddOffset<const TTPOLYCURVE>(curPolygon, sizeof(TTPOL
YGONHEADER)); |
1391 fEndCurve = SkTAddOffset<const TTPOLYCURVE>(curPolygon, curPolygon->
cb); | 1391 fEndCurve = SkTAddOffset<const TTPOLYCURVE>(curPolygon, curPolygon->
cb); |
1392 } | 1392 } |
1393 void set() { | 1393 void set() { |
1394 fCurCurve = NULL; | 1394 fCurCurve = nullptr; |
1395 fEndCurve = NULL; | 1395 fEndCurve = nullptr; |
1396 } | 1396 } |
1397 | 1397 |
1398 const TTPOLYCURVE* next() { | 1398 const TTPOLYCURVE* next() { |
1399 if (fCurCurve >= fEndCurve) { | 1399 if (fCurCurve >= fEndCurve) { |
1400 return NULL; | 1400 return nullptr; |
1401 } | 1401 } |
1402 const TTPOLYCURVE* thisCurve = fCurCurve; | 1402 const TTPOLYCURVE* thisCurve = fCurCurve; |
1403 fCurCurve = SkTAddOffset<const TTPOLYCURVE>(fCurCurve, size_of_TTPOL
YCURVE(*fCurCurve)); | 1403 fCurCurve = SkTAddOffset<const TTPOLYCURVE>(fCurCurve, size_of_TTPOL
YCURVE(*fCurCurve)); |
1404 return thisCurve; | 1404 return thisCurve; |
1405 } | 1405 } |
1406 private: | 1406 private: |
1407 size_t size_of_TTPOLYCURVE(const TTPOLYCURVE& curve) { | 1407 size_t size_of_TTPOLYCURVE(const TTPOLYCURVE& curve) { |
1408 return 2*sizeof(WORD) + curve.cpfx*sizeof(POINTFX); | 1408 return 2*sizeof(WORD) + curve.cpfx*sizeof(POINTFX); |
1409 } | 1409 } |
1410 const TTPOLYCURVE* fCurCurve; | 1410 const TTPOLYCURVE* fCurCurve; |
1411 const TTPOLYCURVE* fEndCurve; | 1411 const TTPOLYCURVE* fEndCurve; |
1412 }; | 1412 }; |
1413 | 1413 |
1414 /** Iterates over all of the polygon points in a polygon curve. */ | 1414 /** Iterates over all of the polygon points in a polygon curve. */ |
1415 class GDIPolygonCurvePointIter { | 1415 class GDIPolygonCurvePointIter { |
1416 public: | 1416 public: |
1417 GDIPolygonCurvePointIter() : fCurveType(0), fCurPoint(NULL), fEndPoint(N
ULL) { } | 1417 GDIPolygonCurvePointIter() : fCurveType(0), fCurPoint(nullptr), fEndPoin
t(nullptr) { } |
1418 | 1418 |
1419 GDIPolygonCurvePointIter(const TTPOLYCURVE* curPolygon) | 1419 GDIPolygonCurvePointIter(const TTPOLYCURVE* curPolygon) |
1420 : fCurveType(curPolygon->wType) | 1420 : fCurveType(curPolygon->wType) |
1421 , fCurPoint(&curPolygon->apfx[0]) | 1421 , fCurPoint(&curPolygon->apfx[0]) |
1422 , fEndPoint(&curPolygon->apfx[curPolygon->cpfx]) | 1422 , fEndPoint(&curPolygon->apfx[curPolygon->cpfx]) |
1423 { } | 1423 { } |
1424 | 1424 |
1425 bool isSet() { return fCurPoint != NULL; } | 1425 bool isSet() { return fCurPoint != nullptr; } |
1426 | 1426 |
1427 void set(const TTPOLYCURVE* curPolygon) { | 1427 void set(const TTPOLYCURVE* curPolygon) { |
1428 fCurveType = curPolygon->wType; | 1428 fCurveType = curPolygon->wType; |
1429 fCurPoint = &curPolygon->apfx[0]; | 1429 fCurPoint = &curPolygon->apfx[0]; |
1430 fEndPoint = &curPolygon->apfx[curPolygon->cpfx]; | 1430 fEndPoint = &curPolygon->apfx[curPolygon->cpfx]; |
1431 } | 1431 } |
1432 void set() { | 1432 void set() { |
1433 fCurPoint = NULL; | 1433 fCurPoint = nullptr; |
1434 fEndPoint = NULL; | 1434 fEndPoint = nullptr; |
1435 } | 1435 } |
1436 | 1436 |
1437 const POINTFX* next() { | 1437 const POINTFX* next() { |
1438 if (fCurPoint >= fEndPoint) { | 1438 if (fCurPoint >= fEndPoint) { |
1439 return NULL; | 1439 return nullptr; |
1440 } | 1440 } |
1441 const POINTFX* thisPoint = fCurPoint; | 1441 const POINTFX* thisPoint = fCurPoint; |
1442 ++fCurPoint; | 1442 ++fCurPoint; |
1443 return thisPoint; | 1443 return thisPoint; |
1444 } | 1444 } |
1445 | 1445 |
1446 WORD fCurveType; | 1446 WORD fCurveType; |
1447 private: | 1447 private: |
1448 const POINTFX* fCurPoint; | 1448 const POINTFX* fCurPoint; |
1449 const POINTFX* fEndPoint; | 1449 const POINTFX* fEndPoint; |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1498 // Advance past this TTPOLYCURVE. | 1498 // Advance past this TTPOLYCURVE. |
1499 cur_poly += sizeof(WORD) * 2 + sizeof(POINTFX) * pc->cpfx; | 1499 cur_poly += sizeof(WORD) * 2 + sizeof(POINTFX) * pc->cpfx; |
1500 } | 1500 } |
1501 cur_glyph += th->cb; | 1501 cur_glyph += th->cb; |
1502 path->close(); | 1502 path->close(); |
1503 } | 1503 } |
1504 } | 1504 } |
1505 | 1505 |
1506 #define move_next_expected_hinted_point(iter, pElem) do {\ | 1506 #define move_next_expected_hinted_point(iter, pElem) do {\ |
1507 pElem = iter.next(); \ | 1507 pElem = iter.next(); \ |
1508 if (NULL == pElem) return false; \ | 1508 if (nullptr == pElem) return false; \ |
1509 } while(0) | 1509 } while(0) |
1510 | 1510 |
1511 // It is possible for the hinted and unhinted versions of the same path to have | 1511 // It is possible for the hinted and unhinted versions of the same path to have |
1512 // a different number of points due to GDI's handling of flipped points. | 1512 // a different number of points due to GDI's handling of flipped points. |
1513 // If this is detected, this will return false. | 1513 // If this is detected, this will return false. |
1514 static bool sk_path_from_gdi_paths(SkPath* path, const uint8_t* glyphbuf, DWORD
total_size, | 1514 static bool sk_path_from_gdi_paths(SkPath* path, const uint8_t* glyphbuf, DWORD
total_size, |
1515 GDIGlyphbufferPointIter hintedYs) { | 1515 GDIGlyphbufferPointIter hintedYs) { |
1516 const uint8_t* cur_glyph = glyphbuf; | 1516 const uint8_t* cur_glyph = glyphbuf; |
1517 const uint8_t* end_glyph = glyphbuf + total_size; | 1517 const uint8_t* end_glyph = glyphbuf + total_size; |
1518 | 1518 |
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1584 { | 1584 { |
1585 GLYPHMETRICS gm; | 1585 GLYPHMETRICS gm; |
1586 | 1586 |
1587 DWORD total_size = GetGlyphOutlineW(fDDC, glyph.getGlyphID(), flags, &gm, BU
FFERSIZE, glyphbuf->get(), &fMat22); | 1587 DWORD total_size = GetGlyphOutlineW(fDDC, glyph.getGlyphID(), flags, &gm, BU
FFERSIZE, glyphbuf->get(), &fMat22); |
1588 // Sometimes GetGlyphOutlineW returns a number larger than BUFFERSIZE even i
f BUFFERSIZE > 0. | 1588 // Sometimes GetGlyphOutlineW returns a number larger than BUFFERSIZE even i
f BUFFERSIZE > 0. |
1589 // It has been verified that this does not involve a buffer overrun. | 1589 // It has been verified that this does not involve a buffer overrun. |
1590 if (GDI_ERROR == total_size || total_size > BUFFERSIZE) { | 1590 if (GDI_ERROR == total_size || total_size > BUFFERSIZE) { |
1591 // GDI_ERROR because the BUFFERSIZE was too small, or because the data w
as not accessible. | 1591 // GDI_ERROR because the BUFFERSIZE was too small, or because the data w
as not accessible. |
1592 // When the data is not accessable GetGlyphOutlineW fails rather quickly
, | 1592 // When the data is not accessable GetGlyphOutlineW fails rather quickly
, |
1593 // so just try to get the size. If that fails then ensure the data is ac
cessible. | 1593 // so just try to get the size. If that fails then ensure the data is ac
cessible. |
1594 total_size = GetGlyphOutlineW(fDDC, glyph.getGlyphID(), flags, &gm, 0, N
ULL, &fMat22); | 1594 total_size = GetGlyphOutlineW(fDDC, glyph.getGlyphID(), flags, &gm, 0, n
ullptr, &fMat22); |
1595 if (GDI_ERROR == total_size) { | 1595 if (GDI_ERROR == total_size) { |
1596 LogFontTypeface::EnsureAccessible(this->getTypeface()); | 1596 LogFontTypeface::EnsureAccessible(this->getTypeface()); |
1597 total_size = GetGlyphOutlineW(fDDC, glyph.getGlyphID(), flags, &gm,
0, NULL, &fMat22); | 1597 total_size = GetGlyphOutlineW(fDDC, glyph.getGlyphID(), flags, &gm,
0, nullptr, &fMat22); |
1598 if (GDI_ERROR == total_size) { | 1598 if (GDI_ERROR == total_size) { |
1599 // GetGlyphOutlineW is known to fail for some characters, such a
s spaces. | 1599 // GetGlyphOutlineW is known to fail for some characters, such a
s spaces. |
1600 // In these cases, just return that the glyph does not have a sh
ape. | 1600 // In these cases, just return that the glyph does not have a sh
ape. |
1601 return 0; | 1601 return 0; |
1602 } | 1602 } |
1603 } | 1603 } |
1604 | 1604 |
1605 glyphbuf->reset(total_size); | 1605 glyphbuf->reset(total_size); |
1606 | 1606 |
1607 DWORD ret = GetGlyphOutlineW(fDDC, glyph.getGlyphID(), flags, &gm, total
_size, glyphbuf->get(), &fMat22); | 1607 DWORD ret = GetGlyphOutlineW(fDDC, glyph.getGlyphID(), flags, &gm, total
_size, glyphbuf->get(), &fMat22); |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1661 sk_path_from_gdi_path(path, glyphbuf, total_size); | 1661 sk_path_from_gdi_path(path, glyphbuf, total_size); |
1662 } | 1662 } |
1663 } | 1663 } |
1664 } | 1664 } |
1665 | 1665 |
1666 static void logfont_for_name(const char* familyName, LOGFONT* lf) { | 1666 static void logfont_for_name(const char* familyName, LOGFONT* lf) { |
1667 sk_bzero(lf, sizeof(LOGFONT)); | 1667 sk_bzero(lf, sizeof(LOGFONT)); |
1668 #ifdef UNICODE | 1668 #ifdef UNICODE |
1669 // Get the buffer size needed first. | 1669 // Get the buffer size needed first. |
1670 size_t str_len = ::MultiByteToWideChar(CP_UTF8, 0, familyName, | 1670 size_t str_len = ::MultiByteToWideChar(CP_UTF8, 0, familyName, |
1671 -1, NULL, 0); | 1671 -1, nullptr, 0); |
1672 // Allocate a buffer (str_len already has terminating null | 1672 // Allocate a buffer (str_len already has terminating null |
1673 // accounted for). | 1673 // accounted for). |
1674 wchar_t *wideFamilyName = new wchar_t[str_len]; | 1674 wchar_t *wideFamilyName = new wchar_t[str_len]; |
1675 // Now actually convert the string. | 1675 // Now actually convert the string. |
1676 ::MultiByteToWideChar(CP_UTF8, 0, familyName, -1, | 1676 ::MultiByteToWideChar(CP_UTF8, 0, familyName, -1, |
1677 wideFamilyName, str_len); | 1677 wideFamilyName, str_len); |
1678 ::wcsncpy(lf->lfFaceName, wideFamilyName, LF_FACESIZE - 1); | 1678 ::wcsncpy(lf->lfFaceName, wideFamilyName, LF_FACESIZE - 1); |
1679 delete [] wideFamilyName; | 1679 delete [] wideFamilyName; |
1680 lf->lfFaceName[LF_FACESIZE-1] = L'\0'; | 1680 lf->lfFaceName[LF_FACESIZE-1] = L'\0'; |
1681 #else | 1681 #else |
1682 ::strncpy(lf->lfFaceName, familyName, LF_FACESIZE - 1); | 1682 ::strncpy(lf->lfFaceName, familyName, LF_FACESIZE - 1); |
1683 lf->lfFaceName[LF_FACESIZE - 1] = '\0'; | 1683 lf->lfFaceName[LF_FACESIZE - 1] = '\0'; |
1684 #endif | 1684 #endif |
1685 } | 1685 } |
1686 | 1686 |
1687 void LogFontTypeface::onGetFamilyName(SkString* familyName) const { | 1687 void LogFontTypeface::onGetFamilyName(SkString* familyName) const { |
1688 // Get the actual name of the typeface. The logfont may not know this. | 1688 // Get the actual name of the typeface. The logfont may not know this. |
1689 HFONT font = CreateFontIndirect(&fLogFont); | 1689 HFONT font = CreateFontIndirect(&fLogFont); |
1690 | 1690 |
1691 HDC deviceContext = ::CreateCompatibleDC(NULL); | 1691 HDC deviceContext = ::CreateCompatibleDC(nullptr); |
1692 HFONT savefont = (HFONT)SelectObject(deviceContext, font); | 1692 HFONT savefont = (HFONT)SelectObject(deviceContext, font); |
1693 | 1693 |
1694 dcfontname_to_skstring(deviceContext, fLogFont, familyName); | 1694 dcfontname_to_skstring(deviceContext, fLogFont, familyName); |
1695 | 1695 |
1696 if (deviceContext) { | 1696 if (deviceContext) { |
1697 ::SelectObject(deviceContext, savefont); | 1697 ::SelectObject(deviceContext, savefont); |
1698 ::DeleteDC(deviceContext); | 1698 ::DeleteDC(deviceContext); |
1699 } | 1699 } |
1700 if (font) { | 1700 if (font) { |
1701 ::DeleteObject(font); | 1701 ::DeleteObject(font); |
1702 } | 1702 } |
1703 } | 1703 } |
1704 | 1704 |
1705 void LogFontTypeface::onGetFontDescriptor(SkFontDescriptor* desc, | 1705 void LogFontTypeface::onGetFontDescriptor(SkFontDescriptor* desc, |
1706 bool* isLocalStream) const { | 1706 bool* isLocalStream) const { |
1707 SkString familyName; | 1707 SkString familyName; |
1708 this->onGetFamilyName(&familyName); | 1708 this->onGetFamilyName(&familyName); |
1709 desc->setFamilyName(familyName.c_str()); | 1709 desc->setFamilyName(familyName.c_str()); |
1710 *isLocalStream = this->fSerializeAsStream; | 1710 *isLocalStream = this->fSerializeAsStream; |
1711 } | 1711 } |
1712 | 1712 |
1713 static bool getWidthAdvance(HDC hdc, int gId, int16_t* advance) { | 1713 static bool getWidthAdvance(HDC hdc, int gId, int16_t* advance) { |
1714 // Initialize the MAT2 structure to the identify transformation matrix. | 1714 // Initialize the MAT2 structure to the identify transformation matrix. |
1715 static const MAT2 mat2 = {SkScalarToFIXED(1), SkScalarToFIXED(0), | 1715 static const MAT2 mat2 = {SkScalarToFIXED(1), SkScalarToFIXED(0), |
1716 SkScalarToFIXED(0), SkScalarToFIXED(1)}; | 1716 SkScalarToFIXED(0), SkScalarToFIXED(1)}; |
1717 int flags = GGO_METRICS | GGO_GLYPH_INDEX; | 1717 int flags = GGO_METRICS | GGO_GLYPH_INDEX; |
1718 GLYPHMETRICS gm; | 1718 GLYPHMETRICS gm; |
1719 if (GDI_ERROR == GetGlyphOutline(hdc, gId, flags, &gm, 0, NULL, &mat2)) { | 1719 if (GDI_ERROR == GetGlyphOutline(hdc, gId, flags, &gm, 0, nullptr, &mat2)) { |
1720 return false; | 1720 return false; |
1721 } | 1721 } |
1722 SkASSERT(advance); | 1722 SkASSERT(advance); |
1723 *advance = gm.gmCellIncX; | 1723 *advance = gm.gmCellIncX; |
1724 return true; | 1724 return true; |
1725 } | 1725 } |
1726 | 1726 |
1727 SkAdvancedTypefaceMetrics* LogFontTypeface::onGetAdvancedTypefaceMetrics( | 1727 SkAdvancedTypefaceMetrics* LogFontTypeface::onGetAdvancedTypefaceMetrics( |
1728 PerGlyphInfo perGlyphInfo, | 1728 PerGlyphInfo perGlyphInfo, |
1729 const uint32_t* glyphIDs, | 1729 const uint32_t* glyphIDs, |
1730 uint32_t glyphIDsCount) const { | 1730 uint32_t glyphIDsCount) const { |
1731 LOGFONT lf = fLogFont; | 1731 LOGFONT lf = fLogFont; |
1732 SkAdvancedTypefaceMetrics* info = NULL; | 1732 SkAdvancedTypefaceMetrics* info = nullptr; |
1733 | 1733 |
1734 HDC hdc = CreateCompatibleDC(NULL); | 1734 HDC hdc = CreateCompatibleDC(nullptr); |
1735 HFONT font = CreateFontIndirect(&lf); | 1735 HFONT font = CreateFontIndirect(&lf); |
1736 HFONT savefont = (HFONT)SelectObject(hdc, font); | 1736 HFONT savefont = (HFONT)SelectObject(hdc, font); |
1737 HFONT designFont = NULL; | 1737 HFONT designFont = nullptr; |
1738 | 1738 |
1739 const char stem_chars[] = {'i', 'I', '!', '1'}; | 1739 const char stem_chars[] = {'i', 'I', '!', '1'}; |
1740 int16_t min_width; | 1740 int16_t min_width; |
1741 unsigned glyphCount; | 1741 unsigned glyphCount; |
1742 | 1742 |
1743 // To request design units, create a logical font whose height is specified | 1743 // To request design units, create a logical font whose height is specified |
1744 // as unitsPerEm. | 1744 // as unitsPerEm. |
1745 OUTLINETEXTMETRIC otm; | 1745 OUTLINETEXTMETRIC otm; |
1746 unsigned int otmRet = GetOutlineTextMetrics(hdc, sizeof(otm), &otm); | 1746 unsigned int otmRet = GetOutlineTextMetrics(hdc, sizeof(otm), &otm); |
1747 if (0 == otmRet) { | 1747 if (0 == otmRet) { |
(...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1845 SelectObject(hdc, savefont); | 1845 SelectObject(hdc, savefont); |
1846 DeleteObject(designFont); | 1846 DeleteObject(designFont); |
1847 DeleteObject(font); | 1847 DeleteObject(font); |
1848 DeleteDC(hdc); | 1848 DeleteDC(hdc); |
1849 | 1849 |
1850 return info; | 1850 return info; |
1851 } | 1851 } |
1852 | 1852 |
1853 //Dummy representation of a Base64 encoded GUID from create_unique_font_name. | 1853 //Dummy representation of a Base64 encoded GUID from create_unique_font_name. |
1854 #define BASE64_GUID_ID "XXXXXXXXXXXXXXXXXXXXXXXX" | 1854 #define BASE64_GUID_ID "XXXXXXXXXXXXXXXXXXXXXXXX" |
1855 //Length of GUID representation from create_id, including NULL terminator. | 1855 //Length of GUID representation from create_id, including nullptr terminator. |
1856 #define BASE64_GUID_ID_LEN SK_ARRAY_COUNT(BASE64_GUID_ID) | 1856 #define BASE64_GUID_ID_LEN SK_ARRAY_COUNT(BASE64_GUID_ID) |
1857 | 1857 |
1858 static_assert(BASE64_GUID_ID_LEN < LF_FACESIZE, "GUID_longer_than_facesize"); | 1858 static_assert(BASE64_GUID_ID_LEN < LF_FACESIZE, "GUID_longer_than_facesize"); |
1859 | 1859 |
1860 /** | 1860 /** |
1861 NameID 6 Postscript names cannot have the character '/'. | 1861 NameID 6 Postscript names cannot have the character '/'. |
1862 It would be easier to hex encode the GUID, but that is 32 bytes, | 1862 It would be easier to hex encode the GUID, but that is 32 bytes, |
1863 and many systems have issues with names longer than 28 bytes. | 1863 and many systems have issues with names longer than 28 bytes. |
1864 The following need not be any standard base64 encoding. | 1864 The following need not be any standard base64 encoding. |
1865 The encoded value is never decoded. | 1865 The encoded value is never decoded. |
(...skipping 26 matching lines...) Expand all Loading... |
1892 GUID guid = {}; | 1892 GUID guid = {}; |
1893 if (FAILED(CoCreateGuid(&guid))) { | 1893 if (FAILED(CoCreateGuid(&guid))) { |
1894 return E_UNEXPECTED; | 1894 return E_UNEXPECTED; |
1895 } | 1895 } |
1896 format_guid_b64(guid, buffer, bufferSize); | 1896 format_guid_b64(guid, buffer, bufferSize); |
1897 | 1897 |
1898 return S_OK; | 1898 return S_OK; |
1899 } | 1899 } |
1900 | 1900 |
1901 /** | 1901 /** |
1902 Introduces a font to GDI. On failure will return NULL. The returned handle | 1902 Introduces a font to GDI. On failure will return nullptr. The returned handle |
1903 should eventually be passed to RemoveFontMemResourceEx. | 1903 should eventually be passed to RemoveFontMemResourceEx. |
1904 */ | 1904 */ |
1905 static HANDLE activate_font(SkData* fontData) { | 1905 static HANDLE activate_font(SkData* fontData) { |
1906 DWORD numFonts = 0; | 1906 DWORD numFonts = 0; |
1907 //AddFontMemResourceEx just copies the data, but does not specify const. | 1907 //AddFontMemResourceEx just copies the data, but does not specify const. |
1908 HANDLE fontHandle = AddFontMemResourceEx(const_cast<void*>(fontData->data())
, | 1908 HANDLE fontHandle = AddFontMemResourceEx(const_cast<void*>(fontData->data())
, |
1909 static_cast<DWORD>(fontData->size()
), | 1909 static_cast<DWORD>(fontData->size()
), |
1910 0, | 1910 0, |
1911 &numFonts); | 1911 &numFonts); |
1912 | 1912 |
1913 if (fontHandle != NULL && numFonts < 1) { | 1913 if (fontHandle != nullptr && numFonts < 1) { |
1914 RemoveFontMemResourceEx(fontHandle); | 1914 RemoveFontMemResourceEx(fontHandle); |
1915 return NULL; | 1915 return nullptr; |
1916 } | 1916 } |
1917 | 1917 |
1918 return fontHandle; | 1918 return fontHandle; |
1919 } | 1919 } |
1920 | 1920 |
1921 // Does not affect ownership of stream. | 1921 // Does not affect ownership of stream. |
1922 static SkTypeface* create_from_stream(SkStreamAsset* stream) { | 1922 static SkTypeface* create_from_stream(SkStreamAsset* stream) { |
1923 // Create a unique and unpredictable font name. | 1923 // Create a unique and unpredictable font name. |
1924 // Avoids collisions and access from CSS. | 1924 // Avoids collisions and access from CSS. |
1925 char familyName[BASE64_GUID_ID_LEN]; | 1925 char familyName[BASE64_GUID_ID_LEN]; |
1926 const int familyNameSize = SK_ARRAY_COUNT(familyName); | 1926 const int familyNameSize = SK_ARRAY_COUNT(familyName); |
1927 if (FAILED(create_unique_font_name(familyName, familyNameSize))) { | 1927 if (FAILED(create_unique_font_name(familyName, familyNameSize))) { |
1928 return NULL; | 1928 return nullptr; |
1929 } | 1929 } |
1930 | 1930 |
1931 // Change the name of the font. | 1931 // Change the name of the font. |
1932 SkAutoTUnref<SkData> rewrittenFontData(SkOTUtils::RenameFont(stream, familyN
ame, familyNameSize-1)); | 1932 SkAutoTUnref<SkData> rewrittenFontData(SkOTUtils::RenameFont(stream, familyN
ame, familyNameSize-1)); |
1933 if (NULL == rewrittenFontData.get()) { | 1933 if (nullptr == rewrittenFontData.get()) { |
1934 return NULL; | 1934 return nullptr; |
1935 } | 1935 } |
1936 | 1936 |
1937 // Register the font with GDI. | 1937 // Register the font with GDI. |
1938 HANDLE fontReference = activate_font(rewrittenFontData.get()); | 1938 HANDLE fontReference = activate_font(rewrittenFontData.get()); |
1939 if (NULL == fontReference) { | 1939 if (nullptr == fontReference) { |
1940 return NULL; | 1940 return nullptr; |
1941 } | 1941 } |
1942 | 1942 |
1943 // Create the typeface. | 1943 // Create the typeface. |
1944 LOGFONT lf; | 1944 LOGFONT lf; |
1945 logfont_for_name(familyName, &lf); | 1945 logfont_for_name(familyName, &lf); |
1946 | 1946 |
1947 return SkCreateFontMemResourceTypefaceFromLOGFONT(lf, fontReference); | 1947 return SkCreateFontMemResourceTypefaceFromLOGFONT(lf, fontReference); |
1948 } | 1948 } |
1949 | 1949 |
1950 SkStreamAsset* LogFontTypeface::onOpenStream(int* ttcIndex) const { | 1950 SkStreamAsset* LogFontTypeface::onOpenStream(int* ttcIndex) const { |
1951 *ttcIndex = 0; | 1951 *ttcIndex = 0; |
1952 | 1952 |
1953 const DWORD kTTCTag = | 1953 const DWORD kTTCTag = |
1954 SkEndian_SwapBE32(SkSetFourByteTag('t', 't', 'c', 'f')); | 1954 SkEndian_SwapBE32(SkSetFourByteTag('t', 't', 'c', 'f')); |
1955 LOGFONT lf = fLogFont; | 1955 LOGFONT lf = fLogFont; |
1956 | 1956 |
1957 HDC hdc = ::CreateCompatibleDC(NULL); | 1957 HDC hdc = ::CreateCompatibleDC(nullptr); |
1958 HFONT font = CreateFontIndirect(&lf); | 1958 HFONT font = CreateFontIndirect(&lf); |
1959 HFONT savefont = (HFONT)SelectObject(hdc, font); | 1959 HFONT savefont = (HFONT)SelectObject(hdc, font); |
1960 | 1960 |
1961 SkMemoryStream* stream = NULL; | 1961 SkMemoryStream* stream = nullptr; |
1962 DWORD tables[2] = {kTTCTag, 0}; | 1962 DWORD tables[2] = {kTTCTag, 0}; |
1963 for (int i = 0; i < SK_ARRAY_COUNT(tables); i++) { | 1963 for (int i = 0; i < SK_ARRAY_COUNT(tables); i++) { |
1964 DWORD bufferSize = GetFontData(hdc, tables[i], 0, NULL, 0); | 1964 DWORD bufferSize = GetFontData(hdc, tables[i], 0, nullptr, 0); |
1965 if (bufferSize == GDI_ERROR) { | 1965 if (bufferSize == GDI_ERROR) { |
1966 call_ensure_accessible(lf); | 1966 call_ensure_accessible(lf); |
1967 bufferSize = GetFontData(hdc, tables[i], 0, NULL, 0); | 1967 bufferSize = GetFontData(hdc, tables[i], 0, nullptr, 0); |
1968 } | 1968 } |
1969 if (bufferSize != GDI_ERROR) { | 1969 if (bufferSize != GDI_ERROR) { |
1970 stream = new SkMemoryStream(bufferSize); | 1970 stream = new SkMemoryStream(bufferSize); |
1971 if (GetFontData(hdc, tables[i], 0, (void*)stream->getMemoryBase(), b
ufferSize)) { | 1971 if (GetFontData(hdc, tables[i], 0, (void*)stream->getMemoryBase(), b
ufferSize)) { |
1972 break; | 1972 break; |
1973 } else { | 1973 } else { |
1974 delete stream; | 1974 delete stream; |
1975 stream = NULL; | 1975 stream = nullptr; |
1976 } | 1976 } |
1977 } | 1977 } |
1978 } | 1978 } |
1979 | 1979 |
1980 SelectObject(hdc, savefont); | 1980 SelectObject(hdc, savefont); |
1981 DeleteObject(font); | 1981 DeleteObject(font); |
1982 DeleteDC(hdc); | 1982 DeleteDC(hdc); |
1983 | 1983 |
1984 return stream; | 1984 return stream; |
1985 } | 1985 } |
(...skipping 22 matching lines...) Expand all Loading... |
2008 } | 2008 } |
2009 } | 2009 } |
2010 } | 2010 } |
2011 } | 2011 } |
2012 | 2012 |
2013 static uint16_t nonBmpCharToGlyph(HDC hdc, SCRIPT_CACHE* scriptCache, const WCHA
R utf16[2]) { | 2013 static uint16_t nonBmpCharToGlyph(HDC hdc, SCRIPT_CACHE* scriptCache, const WCHA
R utf16[2]) { |
2014 uint16_t index = 0; | 2014 uint16_t index = 0; |
2015 // Use uniscribe to detemine glyph index for non-BMP characters. | 2015 // Use uniscribe to detemine glyph index for non-BMP characters. |
2016 static const int numWCHAR = 2; | 2016 static const int numWCHAR = 2; |
2017 static const int maxItems = 2; | 2017 static const int maxItems = 2; |
2018 // MSDN states that this can be NULL, but some things don't work then. | 2018 // MSDN states that this can be nullptr, but some things don't work then. |
2019 SCRIPT_CONTROL scriptControl = { 0 }; | 2019 SCRIPT_CONTROL scriptControl = { 0 }; |
2020 // Add extra item to SCRIPT_ITEM to work around a bug (now documented). | 2020 // Add extra item to SCRIPT_ITEM to work around a bug (now documented). |
2021 // https://bugzilla.mozilla.org/show_bug.cgi?id=366643 | 2021 // https://bugzilla.mozilla.org/show_bug.cgi?id=366643 |
2022 SCRIPT_ITEM si[maxItems + 1]; | 2022 SCRIPT_ITEM si[maxItems + 1]; |
2023 int numItems; | 2023 int numItems; |
2024 HRZM(ScriptItemize(utf16, numWCHAR, maxItems, &scriptControl, NULL, si, &num
Items), | 2024 HRZM(ScriptItemize(utf16, numWCHAR, maxItems, &scriptControl, nullptr, si, &
numItems), |
2025 "Could not itemize character."); | 2025 "Could not itemize character."); |
2026 | 2026 |
2027 // Sometimes ScriptShape cannot find a glyph for a non-BMP and returns 2 spa
ce glyphs. | 2027 // Sometimes ScriptShape cannot find a glyph for a non-BMP and returns 2 spa
ce glyphs. |
2028 static const int maxGlyphs = 2; | 2028 static const int maxGlyphs = 2; |
2029 SCRIPT_VISATTR vsa[maxGlyphs]; | 2029 SCRIPT_VISATTR vsa[maxGlyphs]; |
2030 WORD outGlyphs[maxGlyphs]; | 2030 WORD outGlyphs[maxGlyphs]; |
2031 WORD logClust[numWCHAR]; | 2031 WORD logClust[numWCHAR]; |
2032 int numGlyphs; | 2032 int numGlyphs; |
2033 HRZM(ScriptShape(hdc, scriptCache, utf16, numWCHAR, maxGlyphs, &si[0].a, | 2033 HRZM(ScriptShape(hdc, scriptCache, utf16, numWCHAR, maxGlyphs, &si[0].a, |
2034 outGlyphs, logClust, vsa, &numGlyphs), | 2034 outGlyphs, logClust, vsa, &numGlyphs), |
2035 "Could not shape character."); | 2035 "Could not shape character."); |
2036 if (1 == numGlyphs) { | 2036 if (1 == numGlyphs) { |
2037 index = outGlyphs[0]; | 2037 index = outGlyphs[0]; |
2038 } | 2038 } |
2039 return index; | 2039 return index; |
2040 } | 2040 } |
2041 | 2041 |
2042 class SkAutoHDC { | 2042 class SkAutoHDC { |
2043 public: | 2043 public: |
2044 SkAutoHDC(const LOGFONT& lf) | 2044 SkAutoHDC(const LOGFONT& lf) |
2045 : fHdc(::CreateCompatibleDC(NULL)) | 2045 : fHdc(::CreateCompatibleDC(nullptr)) |
2046 , fFont(::CreateFontIndirect(&lf)) | 2046 , fFont(::CreateFontIndirect(&lf)) |
2047 , fSavefont((HFONT)SelectObject(fHdc, fFont)) | 2047 , fSavefont((HFONT)SelectObject(fHdc, fFont)) |
2048 { } | 2048 { } |
2049 ~SkAutoHDC() { | 2049 ~SkAutoHDC() { |
2050 SelectObject(fHdc, fSavefont); | 2050 SelectObject(fHdc, fSavefont); |
2051 DeleteObject(fFont); | 2051 DeleteObject(fFont); |
2052 DeleteDC(fHdc); | 2052 DeleteDC(fHdc); |
2053 } | 2053 } |
2054 operator HDC() { return fHdc; } | 2054 operator HDC() { return fHdc; } |
2055 private: | 2055 private: |
(...skipping 12 matching lines...) Expand all Loading... |
2068 if (0 == GetTextMetrics(hdc, &tm)) { | 2068 if (0 == GetTextMetrics(hdc, &tm)) { |
2069 call_ensure_accessible(fLogFont); | 2069 call_ensure_accessible(fLogFont); |
2070 if (0 == GetTextMetrics(hdc, &tm)) { | 2070 if (0 == GetTextMetrics(hdc, &tm)) { |
2071 tm.tmPitchAndFamily = TMPF_TRUETYPE; | 2071 tm.tmPitchAndFamily = TMPF_TRUETYPE; |
2072 } | 2072 } |
2073 } | 2073 } |
2074 bool Ox1FHack = !(tm.tmPitchAndFamily & TMPF_VECTOR) /*&& winVer < Vista */; | 2074 bool Ox1FHack = !(tm.tmPitchAndFamily & TMPF_VECTOR) /*&& winVer < Vista */; |
2075 | 2075 |
2076 SkAutoSTMalloc<256, uint16_t> scratchGlyphs; | 2076 SkAutoSTMalloc<256, uint16_t> scratchGlyphs; |
2077 uint16_t* glyphs; | 2077 uint16_t* glyphs; |
2078 if (userGlyphs != NULL) { | 2078 if (userGlyphs != nullptr) { |
2079 glyphs = userGlyphs; | 2079 glyphs = userGlyphs; |
2080 } else { | 2080 } else { |
2081 glyphs = scratchGlyphs.reset(glyphCount); | 2081 glyphs = scratchGlyphs.reset(glyphCount); |
2082 } | 2082 } |
2083 | 2083 |
2084 SCRIPT_CACHE sc = 0; | 2084 SCRIPT_CACHE sc = 0; |
2085 switch (encoding) { | 2085 switch (encoding) { |
2086 case SkTypeface::kUTF8_Encoding: { | 2086 case SkTypeface::kUTF8_Encoding: { |
2087 static const int scratchCount = 256; | 2087 static const int scratchCount = 256; |
2088 WCHAR scratch[scratchCount]; | 2088 WCHAR scratch[scratchCount]; |
(...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2182 | 2182 |
2183 for (int i = 0; i < glyphCount; ++i) { | 2183 for (int i = 0; i < glyphCount; ++i) { |
2184 if (0 == glyphs[i]) { | 2184 if (0 == glyphs[i]) { |
2185 return i; | 2185 return i; |
2186 } | 2186 } |
2187 } | 2187 } |
2188 return glyphCount; | 2188 return glyphCount; |
2189 } | 2189 } |
2190 | 2190 |
2191 int LogFontTypeface::onCountGlyphs() const { | 2191 int LogFontTypeface::onCountGlyphs() const { |
2192 HDC hdc = ::CreateCompatibleDC(NULL); | 2192 HDC hdc = ::CreateCompatibleDC(nullptr); |
2193 HFONT font = CreateFontIndirect(&fLogFont); | 2193 HFONT font = CreateFontIndirect(&fLogFont); |
2194 HFONT savefont = (HFONT)SelectObject(hdc, font); | 2194 HFONT savefont = (HFONT)SelectObject(hdc, font); |
2195 | 2195 |
2196 unsigned int glyphCount = calculateGlyphCount(hdc, fLogFont); | 2196 unsigned int glyphCount = calculateGlyphCount(hdc, fLogFont); |
2197 | 2197 |
2198 SelectObject(hdc, savefont); | 2198 SelectObject(hdc, savefont); |
2199 DeleteObject(font); | 2199 DeleteObject(font); |
2200 DeleteDC(hdc); | 2200 DeleteDC(hdc); |
2201 | 2201 |
2202 return glyphCount; | 2202 return glyphCount; |
2203 } | 2203 } |
2204 | 2204 |
2205 int LogFontTypeface::onGetUPEM() const { | 2205 int LogFontTypeface::onGetUPEM() const { |
2206 HDC hdc = ::CreateCompatibleDC(NULL); | 2206 HDC hdc = ::CreateCompatibleDC(nullptr); |
2207 HFONT font = CreateFontIndirect(&fLogFont); | 2207 HFONT font = CreateFontIndirect(&fLogFont); |
2208 HFONT savefont = (HFONT)SelectObject(hdc, font); | 2208 HFONT savefont = (HFONT)SelectObject(hdc, font); |
2209 | 2209 |
2210 unsigned int upem = calculateUPEM(hdc, fLogFont); | 2210 unsigned int upem = calculateUPEM(hdc, fLogFont); |
2211 | 2211 |
2212 SelectObject(hdc, savefont); | 2212 SelectObject(hdc, savefont); |
2213 DeleteObject(font); | 2213 DeleteObject(font); |
2214 DeleteDC(hdc); | 2214 DeleteDC(hdc); |
2215 | 2215 |
2216 return upem; | 2216 return upem; |
2217 } | 2217 } |
2218 | 2218 |
2219 SkTypeface::LocalizedStrings* LogFontTypeface::onCreateFamilyNameIterator() cons
t { | 2219 SkTypeface::LocalizedStrings* LogFontTypeface::onCreateFamilyNameIterator() cons
t { |
2220 SkTypeface::LocalizedStrings* nameIter = | 2220 SkTypeface::LocalizedStrings* nameIter = |
2221 SkOTUtils::LocalizedStrings_NameTable::CreateForFamilyNames(*this); | 2221 SkOTUtils::LocalizedStrings_NameTable::CreateForFamilyNames(*this); |
2222 if (NULL == nameIter) { | 2222 if (nullptr == nameIter) { |
2223 SkString familyName; | 2223 SkString familyName; |
2224 this->getFamilyName(&familyName); | 2224 this->getFamilyName(&familyName); |
2225 SkString language("und"); //undetermined | 2225 SkString language("und"); //undetermined |
2226 nameIter = new SkOTUtils::LocalizedStrings_SingleName(familyName, langua
ge); | 2226 nameIter = new SkOTUtils::LocalizedStrings_SingleName(familyName, langua
ge); |
2227 } | 2227 } |
2228 return nameIter; | 2228 return nameIter; |
2229 } | 2229 } |
2230 | 2230 |
2231 int LogFontTypeface::onGetTableTags(SkFontTableTag tags[]) const { | 2231 int LogFontTypeface::onGetTableTags(SkFontTableTag tags[]) const { |
2232 SkSFNTHeader header; | 2232 SkSFNTHeader header; |
(...skipping 15 matching lines...) Expand all Loading... |
2248 } | 2248 } |
2249 } | 2249 } |
2250 return numTables; | 2250 return numTables; |
2251 } | 2251 } |
2252 | 2252 |
2253 size_t LogFontTypeface::onGetTableData(SkFontTableTag tag, size_t offset, | 2253 size_t LogFontTypeface::onGetTableData(SkFontTableTag tag, size_t offset, |
2254 size_t length, void* data) const | 2254 size_t length, void* data) const |
2255 { | 2255 { |
2256 LOGFONT lf = fLogFont; | 2256 LOGFONT lf = fLogFont; |
2257 | 2257 |
2258 HDC hdc = ::CreateCompatibleDC(NULL); | 2258 HDC hdc = ::CreateCompatibleDC(nullptr); |
2259 HFONT font = CreateFontIndirect(&lf); | 2259 HFONT font = CreateFontIndirect(&lf); |
2260 HFONT savefont = (HFONT)SelectObject(hdc, font); | 2260 HFONT savefont = (HFONT)SelectObject(hdc, font); |
2261 | 2261 |
2262 tag = SkEndian_SwapBE32(tag); | 2262 tag = SkEndian_SwapBE32(tag); |
2263 if (NULL == data) { | 2263 if (nullptr == data) { |
2264 length = 0; | 2264 length = 0; |
2265 } | 2265 } |
2266 DWORD bufferSize = GetFontData(hdc, tag, (DWORD) offset, data, (DWORD) lengt
h); | 2266 DWORD bufferSize = GetFontData(hdc, tag, (DWORD) offset, data, (DWORD) lengt
h); |
2267 if (bufferSize == GDI_ERROR) { | 2267 if (bufferSize == GDI_ERROR) { |
2268 call_ensure_accessible(lf); | 2268 call_ensure_accessible(lf); |
2269 bufferSize = GetFontData(hdc, tag, (DWORD) offset, data, (DWORD) length)
; | 2269 bufferSize = GetFontData(hdc, tag, (DWORD) offset, data, (DWORD) length)
; |
2270 } | 2270 } |
2271 | 2271 |
2272 SelectObject(hdc, savefont); | 2272 SelectObject(hdc, savefont); |
2273 DeleteObject(font); | 2273 DeleteObject(font); |
2274 DeleteDC(hdc); | 2274 DeleteDC(hdc); |
2275 | 2275 |
2276 return bufferSize == GDI_ERROR ? 0 : bufferSize; | 2276 return bufferSize == GDI_ERROR ? 0 : bufferSize; |
2277 } | 2277 } |
2278 | 2278 |
2279 SkScalerContext* LogFontTypeface::onCreateScalerContext(const SkDescriptor* desc
) const { | 2279 SkScalerContext* LogFontTypeface::onCreateScalerContext(const SkDescriptor* desc
) const { |
2280 SkScalerContext_GDI* ctx = new SkScalerContext_GDI(const_cast<LogFontTypefac
e*>(this), desc); | 2280 SkScalerContext_GDI* ctx = new SkScalerContext_GDI(const_cast<LogFontTypefac
e*>(this), desc); |
2281 if (!ctx->isValid()) { | 2281 if (!ctx->isValid()) { |
2282 delete ctx; | 2282 delete ctx; |
2283 ctx = NULL; | 2283 ctx = nullptr; |
2284 } | 2284 } |
2285 return ctx; | 2285 return ctx; |
2286 } | 2286 } |
2287 | 2287 |
2288 void LogFontTypeface::onFilterRec(SkScalerContextRec* rec) const { | 2288 void LogFontTypeface::onFilterRec(SkScalerContextRec* rec) const { |
2289 if (rec->fFlags & SkScalerContext::kLCD_BGROrder_Flag || | 2289 if (rec->fFlags & SkScalerContext::kLCD_BGROrder_Flag || |
2290 rec->fFlags & SkScalerContext::kLCD_Vertical_Flag) | 2290 rec->fFlags & SkScalerContext::kLCD_Vertical_Flag) |
2291 { | 2291 { |
2292 rec->fMaskFormat = SkMask::kA8_Format; | 2292 rec->fMaskFormat = SkMask::kA8_Format; |
2293 rec->fFlags |= SkScalerContext::kGenA8FromLCD_Flag; | 2293 rec->fFlags |= SkScalerContext::kGenA8FromLCD_Flag; |
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2371 } | 2371 } |
2372 | 2372 |
2373 class SkFontStyleSetGDI : public SkFontStyleSet { | 2373 class SkFontStyleSetGDI : public SkFontStyleSet { |
2374 public: | 2374 public: |
2375 SkFontStyleSetGDI(const TCHAR familyName[]) { | 2375 SkFontStyleSetGDI(const TCHAR familyName[]) { |
2376 LOGFONT lf; | 2376 LOGFONT lf; |
2377 sk_bzero(&lf, sizeof(lf)); | 2377 sk_bzero(&lf, sizeof(lf)); |
2378 lf.lfCharSet = DEFAULT_CHARSET; | 2378 lf.lfCharSet = DEFAULT_CHARSET; |
2379 _tcscpy_s(lf.lfFaceName, familyName); | 2379 _tcscpy_s(lf.lfFaceName, familyName); |
2380 | 2380 |
2381 HDC hdc = ::CreateCompatibleDC(NULL); | 2381 HDC hdc = ::CreateCompatibleDC(nullptr); |
2382 ::EnumFontFamiliesEx(hdc, &lf, enum_family_proc, (LPARAM)&fArray, 0); | 2382 ::EnumFontFamiliesEx(hdc, &lf, enum_family_proc, (LPARAM)&fArray, 0); |
2383 ::DeleteDC(hdc); | 2383 ::DeleteDC(hdc); |
2384 } | 2384 } |
2385 | 2385 |
2386 int count() override { | 2386 int count() override { |
2387 return fArray.count(); | 2387 return fArray.count(); |
2388 } | 2388 } |
2389 | 2389 |
2390 void getStyle(int index, SkFontStyle* fs, SkString* styleName) override { | 2390 void getStyle(int index, SkFontStyle* fs, SkString* styleName) override { |
2391 if (fs) { | 2391 if (fs) { |
(...skipping 25 matching lines...) Expand all Loading... |
2417 SkTDArray<ENUMLOGFONTEX> fArray; | 2417 SkTDArray<ENUMLOGFONTEX> fArray; |
2418 }; | 2418 }; |
2419 | 2419 |
2420 class SkFontMgrGDI : public SkFontMgr { | 2420 class SkFontMgrGDI : public SkFontMgr { |
2421 public: | 2421 public: |
2422 SkFontMgrGDI() { | 2422 SkFontMgrGDI() { |
2423 LOGFONT lf; | 2423 LOGFONT lf; |
2424 sk_bzero(&lf, sizeof(lf)); | 2424 sk_bzero(&lf, sizeof(lf)); |
2425 lf.lfCharSet = DEFAULT_CHARSET; | 2425 lf.lfCharSet = DEFAULT_CHARSET; |
2426 | 2426 |
2427 HDC hdc = ::CreateCompatibleDC(NULL); | 2427 HDC hdc = ::CreateCompatibleDC(nullptr); |
2428 ::EnumFontFamiliesEx(hdc, &lf, enum_family_proc, (LPARAM)&fLogFontArray,
0); | 2428 ::EnumFontFamiliesEx(hdc, &lf, enum_family_proc, (LPARAM)&fLogFontArray,
0); |
2429 ::DeleteDC(hdc); | 2429 ::DeleteDC(hdc); |
2430 } | 2430 } |
2431 | 2431 |
2432 protected: | 2432 protected: |
2433 int onCountFamilies() const override { | 2433 int onCountFamilies() const override { |
2434 return fLogFontArray.count(); | 2434 return fLogFontArray.count(); |
2435 } | 2435 } |
2436 | 2436 |
2437 void onGetFamilyName(int index, SkString* familyName) const override { | 2437 void onGetFamilyName(int index, SkString* familyName) const override { |
2438 SkASSERT((unsigned)index < (unsigned)fLogFontArray.count()); | 2438 SkASSERT((unsigned)index < (unsigned)fLogFontArray.count()); |
2439 tchar_to_skstring(fLogFontArray[index].elfLogFont.lfFaceName, familyName
); | 2439 tchar_to_skstring(fLogFontArray[index].elfLogFont.lfFaceName, familyName
); |
2440 } | 2440 } |
2441 | 2441 |
2442 SkFontStyleSet* onCreateStyleSet(int index) const override { | 2442 SkFontStyleSet* onCreateStyleSet(int index) const override { |
2443 SkASSERT((unsigned)index < (unsigned)fLogFontArray.count()); | 2443 SkASSERT((unsigned)index < (unsigned)fLogFontArray.count()); |
2444 return new SkFontStyleSetGDI(fLogFontArray[index].elfLogFont.lfFaceName)
; | 2444 return new SkFontStyleSetGDI(fLogFontArray[index].elfLogFont.lfFaceName)
; |
2445 } | 2445 } |
2446 | 2446 |
2447 SkFontStyleSet* onMatchFamily(const char familyName[]) const override { | 2447 SkFontStyleSet* onMatchFamily(const char familyName[]) const override { |
2448 if (NULL == familyName) { | 2448 if (nullptr == familyName) { |
2449 familyName = ""; // do we need this check??? | 2449 familyName = ""; // do we need this check??? |
2450 } | 2450 } |
2451 LOGFONT lf; | 2451 LOGFONT lf; |
2452 logfont_for_name(familyName, &lf); | 2452 logfont_for_name(familyName, &lf); |
2453 return new SkFontStyleSetGDI(lf.lfFaceName); | 2453 return new SkFontStyleSetGDI(lf.lfFaceName); |
2454 } | 2454 } |
2455 | 2455 |
2456 virtual SkTypeface* onMatchFamilyStyle(const char familyName[], | 2456 virtual SkTypeface* onMatchFamilyStyle(const char familyName[], |
2457 const SkFontStyle& fontstyle) const o
verride { | 2457 const SkFontStyle& fontstyle) const o
verride { |
2458 // could be in base impl | 2458 // could be in base impl |
2459 SkAutoTUnref<SkFontStyleSet> sset(this->matchFamily(familyName)); | 2459 SkAutoTUnref<SkFontStyleSet> sset(this->matchFamily(familyName)); |
2460 return sset->matchStyle(fontstyle); | 2460 return sset->matchStyle(fontstyle); |
2461 } | 2461 } |
2462 | 2462 |
2463 virtual SkTypeface* onMatchFamilyStyleCharacter(const char familyName[], con
st SkFontStyle&, | 2463 virtual SkTypeface* onMatchFamilyStyleCharacter(const char familyName[], con
st SkFontStyle&, |
2464 const char* bcp47[], int bcp
47Count, | 2464 const char* bcp47[], int bcp
47Count, |
2465 SkUnichar character) const o
verride { | 2465 SkUnichar character) const o
verride { |
2466 return NULL; | 2466 return nullptr; |
2467 } | 2467 } |
2468 | 2468 |
2469 virtual SkTypeface* onMatchFaceStyle(const SkTypeface* familyMember, | 2469 virtual SkTypeface* onMatchFaceStyle(const SkTypeface* familyMember, |
2470 const SkFontStyle& fontstyle) const ove
rride { | 2470 const SkFontStyle& fontstyle) const ove
rride { |
2471 // could be in base impl | 2471 // could be in base impl |
2472 SkString familyName; | 2472 SkString familyName; |
2473 ((LogFontTypeface*)familyMember)->getFamilyName(&familyName); | 2473 ((LogFontTypeface*)familyMember)->getFamilyName(&familyName); |
2474 return this->matchFamilyStyle(familyName.c_str(), fontstyle); | 2474 return this->matchFamilyStyle(familyName.c_str(), fontstyle); |
2475 } | 2475 } |
2476 | 2476 |
2477 SkTypeface* onCreateFromStream(SkStreamAsset* bareStream, int ttcIndex) cons
t override { | 2477 SkTypeface* onCreateFromStream(SkStreamAsset* bareStream, int ttcIndex) cons
t override { |
2478 SkAutoTDelete<SkStreamAsset> stream(bareStream); | 2478 SkAutoTDelete<SkStreamAsset> stream(bareStream); |
2479 return create_from_stream(stream); | 2479 return create_from_stream(stream); |
2480 } | 2480 } |
2481 | 2481 |
2482 SkTypeface* onCreateFromData(SkData* data, int ttcIndex) const override { | 2482 SkTypeface* onCreateFromData(SkData* data, int ttcIndex) const override { |
2483 // could be in base impl | 2483 // could be in base impl |
2484 return this->createFromStream(new SkMemoryStream(data)); | 2484 return this->createFromStream(new SkMemoryStream(data)); |
2485 } | 2485 } |
2486 | 2486 |
2487 SkTypeface* onCreateFromFile(const char path[], int ttcIndex) const override
{ | 2487 SkTypeface* onCreateFromFile(const char path[], int ttcIndex) const override
{ |
2488 // could be in base impl | 2488 // could be in base impl |
2489 return this->createFromStream(SkStream::NewFromFile(path)); | 2489 return this->createFromStream(SkStream::NewFromFile(path)); |
2490 } | 2490 } |
2491 | 2491 |
2492 virtual SkTypeface* onLegacyCreateTypeface(const char familyName[], | 2492 virtual SkTypeface* onLegacyCreateTypeface(const char familyName[], |
2493 unsigned styleBits) const overrid
e { | 2493 unsigned styleBits) const overrid
e { |
2494 LOGFONT lf; | 2494 LOGFONT lf; |
2495 if (NULL == familyName) { | 2495 if (nullptr == familyName) { |
2496 lf = get_default_font(); | 2496 lf = get_default_font(); |
2497 } else { | 2497 } else { |
2498 logfont_for_name(familyName, &lf); | 2498 logfont_for_name(familyName, &lf); |
2499 } | 2499 } |
2500 | 2500 |
2501 SkTypeface::Style style = (SkTypeface::Style)styleBits; | 2501 SkTypeface::Style style = (SkTypeface::Style)styleBits; |
2502 lf.lfWeight = (style & SkTypeface::kBold) != 0 ? FW_BOLD : FW_NORMAL; | 2502 lf.lfWeight = (style & SkTypeface::kBold) != 0 ? FW_BOLD : FW_NORMAL; |
2503 lf.lfItalic = ((style & SkTypeface::kItalic) != 0); | 2503 lf.lfItalic = ((style & SkTypeface::kItalic) != 0); |
2504 return SkCreateTypefaceFromLOGFONT(lf); | 2504 return SkCreateTypefaceFromLOGFONT(lf); |
2505 } | 2505 } |
2506 | 2506 |
2507 private: | 2507 private: |
2508 SkTDArray<ENUMLOGFONTEX> fLogFontArray; | 2508 SkTDArray<ENUMLOGFONTEX> fLogFontArray; |
2509 }; | 2509 }; |
2510 | 2510 |
2511 /////////////////////////////////////////////////////////////////////////////// | 2511 /////////////////////////////////////////////////////////////////////////////// |
2512 | 2512 |
2513 SkFontMgr* SkFontMgr_New_GDI() { return new SkFontMgrGDI; } | 2513 SkFontMgr* SkFontMgr_New_GDI() { return new SkFontMgrGDI; } |
OLD | NEW |