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

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

Issue 1421433004: Add a mutex to protect the DWrite calls. (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: remove stray line Created 5 years, 2 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
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 /* 1 /*
2 * Copyright 2011 Google Inc. 2 * Copyright 2011 Google Inc.
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 "SkTypes.h" 8 #include "SkTypes.h"
9 #undef GetGlyphIndices 9 #undef GetGlyphIndices
10 10
11 #include "SkDWrite.h" 11 #include "SkDWrite.h"
12 #include "SkDWriteGeometrySink.h" 12 #include "SkDWriteGeometrySink.h"
13 #include "SkEndian.h" 13 #include "SkEndian.h"
14 #include "SkGlyph.h" 14 #include "SkGlyph.h"
15 #include "SkHRESULT.h" 15 #include "SkHRESULT.h"
16 #include "SkMaskGamma.h" 16 #include "SkMaskGamma.h"
17 #include "SkMatrix22.h" 17 #include "SkMatrix22.h"
18 #include "SkMutex.h"
18 #include "SkOTTable_EBLC.h" 19 #include "SkOTTable_EBLC.h"
19 #include "SkOTTable_EBSC.h" 20 #include "SkOTTable_EBSC.h"
20 #include "SkOTTable_gasp.h" 21 #include "SkOTTable_gasp.h"
21 #include "SkOTTable_maxp.h" 22 #include "SkOTTable_maxp.h"
22 #include "SkPath.h" 23 #include "SkPath.h"
23 #include "SkScalerContext.h" 24 #include "SkScalerContext.h"
24 #include "SkScalerContext_win_dw.h" 25 #include "SkScalerContext_win_dw.h"
25 #include "SkTScopedComPtr.h" 26 #include "SkTScopedComPtr.h"
26 #include "SkTypeface_win_dw.h" 27 #include "SkTypeface_win_dw.h"
27 28
28 #include <dwrite.h> 29 #include <dwrite.h>
29 #if SK_HAS_DWRITE_1_H 30 #if SK_HAS_DWRITE_1_H
30 # include <dwrite_1.h> 31 # include <dwrite_1.h>
31 #endif 32 #endif
32 33
34 /* Note:
35 * In versions 8 and 8.1 of Windows, some calls in DWrite are not thread safe.
36 * The DWriteFactoryMutex protects the calls that are problematic.
37 */
38 SK_DECLARE_STATIC_MUTEX(DWriteFactoryMutex);
39
40 class Exclusive {
41 public:
42 Exclusive(SkBaseMutex& mutex) : fMutex(mutex) {
43 fMutex.acquire();
44 }
45 ~Exclusive() {
46 fMutex.release();
47 }
48 private:
49 SkBaseMutex& fMutex;
50 };
51
33 static bool isLCD(const SkScalerContext::Rec& rec) { 52 static bool isLCD(const SkScalerContext::Rec& rec) {
34 return SkMask::kLCD16_Format == rec.fMaskFormat; 53 return SkMask::kLCD16_Format == rec.fMaskFormat;
35 } 54 }
36 55
37 static bool is_hinted_without_gasp(DWriteFontTypeface* typeface) { 56 static bool is_hinted_without_gasp(DWriteFontTypeface* typeface) {
57 Exclusive l(DWriteFactoryMutex);
38 AutoTDWriteTable<SkOTTableMaximumProfile> maxp(typeface->fDWriteFontFace.get ()); 58 AutoTDWriteTable<SkOTTableMaximumProfile> maxp(typeface->fDWriteFontFace.get ());
39 if (!maxp.fExists) { 59 if (!maxp.fExists) {
40 return false; 60 return false;
41 } 61 }
42 if (maxp.fSize < sizeof(SkOTTableMaximumProfile::Version::TT)) { 62 if (maxp.fSize < sizeof(SkOTTableMaximumProfile::Version::TT)) {
43 return false; 63 return false;
44 } 64 }
45 if (maxp->version.version != SkOTTableMaximumProfile::Version::TT::VERSION) { 65 if (maxp->version.version != SkOTTableMaximumProfile::Version::TT::VERSION) {
46 return false; 66 return false;
47 } 67 }
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
97 { 117 {
98 range->min = minPPEM + 1; 118 range->min = minPPEM + 1;
99 range->max = maxPPEM; 119 range->max = maxPPEM;
100 return; 120 return;
101 } 121 }
102 minPPEM = maxPPEM; 122 minPPEM = maxPPEM;
103 } 123 }
104 } 124 }
105 125
106 static bool has_bitmap_strike(DWriteFontTypeface* typeface, PPEMRange range) { 126 static bool has_bitmap_strike(DWriteFontTypeface* typeface, PPEMRange range) {
127 Exclusive l(DWriteFactoryMutex);
107 { 128 {
108 AutoTDWriteTable<SkOTTableEmbeddedBitmapLocation> eblc(typeface->fDWrite FontFace.get()); 129 AutoTDWriteTable<SkOTTableEmbeddedBitmapLocation> eblc(typeface->fDWrite FontFace.get());
109 if (!eblc.fExists) { 130 if (!eblc.fExists) {
110 return false; 131 return false;
111 } 132 }
112 if (eblc.fSize < sizeof(SkOTTableEmbeddedBitmapLocation)) { 133 if (eblc.fSize < sizeof(SkOTTableEmbeddedBitmapLocation)) {
113 return false; 134 return false;
114 } 135 }
115 if (eblc->version != SkOTTableEmbeddedBitmapLocation::version_initial) { 136 if (eblc->version != SkOTTableEmbeddedBitmapLocation::version_initial) {
116 return false; 137 return false;
(...skipping 213 matching lines...) Expand 10 before | Expand all | Expand 10 after
330 351
331 glyph->fAdvanceX = 0; 352 glyph->fAdvanceX = 0;
332 glyph->fAdvanceY = 0; 353 glyph->fAdvanceY = 0;
333 354
334 uint16_t glyphId = glyph->getGlyphID(); 355 uint16_t glyphId = glyph->getGlyphID();
335 DWRITE_GLYPH_METRICS gm; 356 DWRITE_GLYPH_METRICS gm;
336 357
337 if (DWRITE_MEASURING_MODE_GDI_CLASSIC == fMeasuringMode || 358 if (DWRITE_MEASURING_MODE_GDI_CLASSIC == fMeasuringMode ||
338 DWRITE_MEASURING_MODE_GDI_NATURAL == fMeasuringMode) 359 DWRITE_MEASURING_MODE_GDI_NATURAL == fMeasuringMode)
339 { 360 {
361 Exclusive l(DWriteFactoryMutex);
340 HRVM(fTypeface->fDWriteFontFace->GetGdiCompatibleGlyphMetrics( 362 HRVM(fTypeface->fDWriteFontFace->GetGdiCompatibleGlyphMetrics(
341 fTextSizeMeasure, 363 fTextSizeMeasure,
342 1.0f, // pixelsPerDip 364 1.0f, // pixelsPerDip
343 &fGsA, 365 &fGsA,
344 DWRITE_MEASURING_MODE_GDI_NATURAL == fMeasuringMode, 366 DWRITE_MEASURING_MODE_GDI_NATURAL == fMeasuringMode,
345 &glyphId, 1, 367 &glyphId, 1,
346 &gm), 368 &gm),
347 "Could not get gdi compatible glyph metrics."); 369 "Could not get gdi compatible glyph metrics.");
348 } else { 370 } else {
371 Exclusive l(DWriteFactoryMutex);
349 HRVM(fTypeface->fDWriteFontFace->GetDesignGlyphMetrics(&glyphId, 1, &gm) , 372 HRVM(fTypeface->fDWriteFontFace->GetDesignGlyphMetrics(&glyphId, 1, &gm) ,
350 "Could not get design metrics."); 373 "Could not get design metrics.");
351 } 374 }
352 375
353 DWRITE_FONT_METRICS dwfm; 376 DWRITE_FONT_METRICS dwfm;
354 fTypeface->fDWriteFontFace->GetMetrics(&dwfm); 377 {
378 Exclusive l(DWriteFactoryMutex);
379 fTypeface->fDWriteFontFace->GetMetrics(&dwfm);
380 }
355 SkScalar advanceX = SkScalarMulDiv(fTextSizeMeasure, 381 SkScalar advanceX = SkScalarMulDiv(fTextSizeMeasure,
356 SkIntToScalar(gm.advanceWidth), 382 SkIntToScalar(gm.advanceWidth),
357 SkIntToScalar(dwfm.designUnitsPerEm)); 383 SkIntToScalar(dwfm.designUnitsPerEm));
358 384
359 SkVector vecs[1] = { { advanceX, 0 } }; 385 SkVector vecs[1] = { { advanceX, 0 } };
360 if (DWRITE_MEASURING_MODE_GDI_CLASSIC == fMeasuringMode || 386 if (DWRITE_MEASURING_MODE_GDI_CLASSIC == fMeasuringMode ||
361 DWRITE_MEASURING_MODE_GDI_NATURAL == fMeasuringMode) 387 DWRITE_MEASURING_MODE_GDI_NATURAL == fMeasuringMode)
362 { 388 {
363 // DirectWrite produced 'compatible' metrics, but while close, 389 // DirectWrite produced 'compatible' metrics, but while close,
364 // the end result is not always an integer as it would be with GDI. 390 // the end result is not always an integer as it would be with GDI.
(...skipping 26 matching lines...) Expand all
391 417
392 DWRITE_GLYPH_RUN run; 418 DWRITE_GLYPH_RUN run;
393 run.glyphCount = 1; 419 run.glyphCount = 1;
394 run.glyphAdvances = &advance; 420 run.glyphAdvances = &advance;
395 run.fontFace = fTypeface->fDWriteFontFace.get(); 421 run.fontFace = fTypeface->fDWriteFontFace.get();
396 run.fontEmSize = SkScalarToFloat(fTextSizeRender); 422 run.fontEmSize = SkScalarToFloat(fTextSizeRender);
397 run.bidiLevel = 0; 423 run.bidiLevel = 0;
398 run.glyphIndices = &glyphId; 424 run.glyphIndices = &glyphId;
399 run.isSideways = FALSE; 425 run.isSideways = FALSE;
400 run.glyphOffsets = &offset; 426 run.glyphOffsets = &offset;
401 427 {
402 SkTScopedComPtr<IDWriteGlyphRunAnalysis> glyphRunAnalysis; 428 Exclusive l(DWriteFactoryMutex);
403 HRM(fTypeface->fFactory->CreateGlyphRunAnalysis( 429 SkTScopedComPtr<IDWriteGlyphRunAnalysis> glyphRunAnalysis;
430 HRM(fTypeface->fFactory->CreateGlyphRunAnalysis(
404 &run, 431 &run,
405 1.0f, // pixelsPerDip, 432 1.0f, // pixelsPerDip,
406 &fXform, 433 &fXform,
407 renderingMode, 434 renderingMode,
408 fMeasuringMode, 435 fMeasuringMode,
409 0.0f, // baselineOriginX, 436 0.0f, // baselineOriginX,
410 0.0f, // baselineOriginY, 437 0.0f, // baselineOriginY,
411 &glyphRunAnalysis), 438 &glyphRunAnalysis),
412 "Could not create glyph run analysis."); 439 "Could not create glyph run analysis.");
413 440
414 HRM(glyphRunAnalysis->GetAlphaTextureBounds(textureType, bbox), 441 HRM(glyphRunAnalysis->GetAlphaTextureBounds(textureType, bbox),
415 "Could not get texture bounds."); 442 "Could not get texture bounds.");
416 443 }
417 return S_OK; 444 return S_OK;
418 } 445 }
419 446
420 /** GetAlphaTextureBounds succeeds but sometimes returns empty bounds like 447 /** GetAlphaTextureBounds succeeds but sometimes returns empty bounds like
421 * { 0x80000000, 0x80000000, 0x80000000, 0x80000000 } 448 * { 0x80000000, 0x80000000, 0x80000000, 0x80000000 }
422 * for small, but not quite zero, sized glyphs. 449 * for small, but not quite zero, sized glyphs.
423 * Only set as non-empty if the returned bounds are non-empty. 450 * Only set as non-empty if the returned bounds are non-empty.
424 */ 451 */
425 static bool glyph_check_and_set_bounds(SkGlyph* glyph, const RECT& bbox) { 452 static bool glyph_check_and_set_bounds(SkGlyph* glyph, const RECT& bbox) {
426 if (bbox.left >= bbox.right || bbox.top >= bbox.bottom) { 453 if (bbox.left >= bbox.right || bbox.top >= bbox.bottom) {
(...skipping 217 matching lines...) Expand 10 before | Expand all | Expand 10 after
644 671
645 DWRITE_GLYPH_RUN run; 672 DWRITE_GLYPH_RUN run;
646 run.glyphCount = 1; 673 run.glyphCount = 1;
647 run.glyphAdvances = &advance; 674 run.glyphAdvances = &advance;
648 run.fontFace = fTypeface->fDWriteFontFace.get(); 675 run.fontFace = fTypeface->fDWriteFontFace.get();
649 run.fontEmSize = SkScalarToFloat(fTextSizeRender); 676 run.fontEmSize = SkScalarToFloat(fTextSizeRender);
650 run.bidiLevel = 0; 677 run.bidiLevel = 0;
651 run.glyphIndices = &index; 678 run.glyphIndices = &index;
652 run.isSideways = FALSE; 679 run.isSideways = FALSE;
653 run.glyphOffsets = &offset; 680 run.glyphOffsets = &offset;
681 {
682 Exclusive l(DWriteFactoryMutex);
683 SkTScopedComPtr<IDWriteGlyphRunAnalysis> glyphRunAnalysis;
684 HRNM(fTypeface->fFactory->CreateGlyphRunAnalysis(&run,
685 1.0f, // pixelsPerDip,
686 &fXform,
687 renderingMode,
688 fMeasuringMode,
689 0.0f, // baselineOriginX,
690 0.0f, // baselineOriginY,
691 &glyphRunAnalysis),
692 "Could not create glyph run analysis.");
654 693
655 SkTScopedComPtr<IDWriteGlyphRunAnalysis> glyphRunAnalysis; 694 //NOTE: this assumes that the glyph has already been measured
656 HRNM(fTypeface->fFactory->CreateGlyphRunAnalysis(&run, 695 //with an exact same glyph run analysis.
657 1.0f, // pixelsPerDip, 696 RECT bbox;
658 &fXform, 697 bbox.left = glyph.fLeft;
659 renderingMode, 698 bbox.top = glyph.fTop;
660 fMeasuringMode, 699 bbox.right = glyph.fLeft + glyph.fWidth;
661 0.0f, // baselineOriginX, 700 bbox.bottom = glyph.fTop + glyph.fHeight;
662 0.0f, // baselineOriginY, 701 HRNM(glyphRunAnalysis->CreateAlphaTexture(textureType,
663 &glyphRunAnalysis), 702 &bbox,
664 "Could not create glyph run analysis."); 703 fBits.begin(),
665 704 sizeNeeded),
666 //NOTE: this assumes that the glyph has already been measured 705 "Could not draw mask.");
667 //with an exact same glyph run analysis. 706 }
668 RECT bbox;
669 bbox.left = glyph.fLeft;
670 bbox.top = glyph.fTop;
671 bbox.right = glyph.fLeft + glyph.fWidth;
672 bbox.bottom = glyph.fTop + glyph.fHeight;
673 HRNM(glyphRunAnalysis->CreateAlphaTexture(textureType,
674 &bbox,
675 fBits.begin(),
676 sizeNeeded),
677 "Could not draw mask.");
678 return fBits.begin(); 707 return fBits.begin();
679 } 708 }
680 709
681 void SkScalerContext_DW::generateImage(const SkGlyph& glyph) { 710 void SkScalerContext_DW::generateImage(const SkGlyph& glyph) {
682 //Create the mask. 711 //Create the mask.
683 DWRITE_RENDERING_MODE renderingMode = fRenderingMode; 712 DWRITE_RENDERING_MODE renderingMode = fRenderingMode;
684 DWRITE_TEXTURE_TYPE textureType = fTextureType; 713 DWRITE_TEXTURE_TYPE textureType = fTextureType;
685 if (glyph.fForceBW) { 714 if (glyph.fForceBW) {
686 renderingMode = DWRITE_RENDERING_MODE_ALIASED; 715 renderingMode = DWRITE_RENDERING_MODE_ALIASED;
687 textureType = DWRITE_TEXTURE_ALIASED_1x1; 716 textureType = DWRITE_TEXTURE_ALIASED_1x1;
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
723 752
724 void SkScalerContext_DW::generatePath(const SkGlyph& glyph, SkPath* path) { 753 void SkScalerContext_DW::generatePath(const SkGlyph& glyph, SkPath* path) {
725 SkASSERT(path); 754 SkASSERT(path);
726 755
727 path->reset(); 756 path->reset();
728 757
729 SkTScopedComPtr<IDWriteGeometrySink> geometryToPath; 758 SkTScopedComPtr<IDWriteGeometrySink> geometryToPath;
730 HRVM(SkDWriteGeometrySink::Create(path, &geometryToPath), 759 HRVM(SkDWriteGeometrySink::Create(path, &geometryToPath),
731 "Could not create geometry to path converter."); 760 "Could not create geometry to path converter.");
732 uint16_t glyphId = glyph.getGlyphID(); 761 uint16_t glyphId = glyph.getGlyphID();
733 //TODO: convert to<->from DIUs? This would make a difference if hinting. 762 {
734 //It may not be needed, it appears that DirectWrite only hints at em size. 763 Exclusive l(DWriteFactoryMutex);
735 HRVM(fTypeface->fDWriteFontFace->GetGlyphRunOutline(SkScalarToFloat(fTextSiz eRender), 764 //TODO: convert to<->from DIUs? This would make a difference if hinting.
736 &glyphId, 765 //It may not be needed, it appears that DirectWrite only hints at em siz e.
737 nullptr, //advances 766 HRVM(fTypeface->fDWriteFontFace->GetGlyphRunOutline(SkScalarToFloat(fTex tSizeRender),
738 nullptr, //offsets 767 &glyphId,
739 1, //num glyphs 768 nullptr, //advances
740 FALSE, //sideways 769 nullptr, //offsets
741 FALSE, //rtl 770 1, //num glyphs
742 geometryToPath.get()), 771 FALSE, //sideways
743 "Could not create glyph outline."); 772 FALSE, //rtl
773 geometryToPath.get()),
774 "Could not create glyph outline.");
775 }
744 776
745 path->transform(fSkXform); 777 path->transform(fSkXform);
746 } 778 }
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698