1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 #include "ScaledFontDWrite.h"
8 #include "gfxDWriteCommon.h"
9 #include "UnscaledFontDWrite.h"
13 #include "mozilla/FontPropertyTypes.h"
14 #include "mozilla/webrender/WebRenderTypes.h"
15 #include "HelpersD2D.h"
16 #include "StackArray.h"
21 #include "skia/include/core/SkPaint.h"
22 #include "skia/include/core/SkPath.h"
23 #include "skia/include/ports/SkTypeface_win.h"
27 #include "cairo-win32.h"
29 #include "HelpersWinFonts.h"
34 #define GASP_TAG 0x70736167
35 #define GASP_DOGRAY 0x2
37 static inline unsigned short readShort(const char* aBuf
) {
38 return (*aBuf
<< 8) | *(aBuf
+ 1);
41 static bool DoGrayscale(IDWriteFontFace
* aDWFace
, Float ppem
) {
46 aDWFace
->TryGetFontTable(GASP_TAG
, (const void**)&tableData
, &tableSize
,
47 &tableContext
, &exists
);
51 aDWFace
->ReleaseFontTable(tableContext
);
55 unsigned short maxPPEM
; // Stored big-endian
56 unsigned short behavior
; // Stored big-endian
58 unsigned short numRanges
= readShort(tableData
+ 2);
59 if (tableSize
< (UINT
)4 + numRanges
* 4) {
60 aDWFace
->ReleaseFontTable(tableContext
);
63 gaspRange
* ranges
= (gaspRange
*)(tableData
+ 4);
64 for (int i
= 0; i
< numRanges
; i
++) {
65 if (readShort((char*)&ranges
[i
].maxPPEM
) >= ppem
) {
66 if (!(readShort((char*)&ranges
[i
].behavior
) & GASP_DOGRAY
)) {
67 aDWFace
->ReleaseFontTable(tableContext
);
73 aDWFace
->ReleaseFontTable(tableContext
);
78 ScaledFontDWrite::ScaledFontDWrite(IDWriteFontFace
* aFontFace
,
79 const RefPtr
<UnscaledFont
>& aUnscaledFont
,
80 Float aSize
, bool aUseEmbeddedBitmap
,
81 bool aUseMultistrikeBold
, bool aGDIForced
,
82 const gfxFontStyle
* aStyle
)
83 : ScaledFontBase(aUnscaledFont
, aSize
),
85 mUseEmbeddedBitmap(aUseEmbeddedBitmap
),
86 mUseMultistrikeBold(aUseMultistrikeBold
),
87 mGDIForced(aGDIForced
) {
89 mStyle
= SkFontStyle(aStyle
->weight
.ToIntRounded(),
90 DWriteFontStretchFromStretch(aStyle
->stretch
),
91 // FIXME(jwatt): also use kOblique_Slant
92 aStyle
->style
== FontSlantStyle::NORMAL
93 ? SkFontStyle::kUpright_Slant
94 : SkFontStyle::kItalic_Slant
);
98 already_AddRefed
<Path
> ScaledFontDWrite::GetPathForGlyphs(
99 const GlyphBuffer
& aBuffer
, const DrawTarget
* aTarget
) {
100 RefPtr
<PathBuilder
> pathBuilder
= aTarget
->CreatePathBuilder();
102 if (pathBuilder
->GetBackendType() != BackendType::DIRECT2D
&&
103 pathBuilder
->GetBackendType() != BackendType::DIRECT2D1_1
) {
104 return ScaledFontBase::GetPathForGlyphs(aBuffer
, aTarget
);
107 PathBuilderD2D
* pathBuilderD2D
=
108 static_cast<PathBuilderD2D
*>(pathBuilder
.get());
110 CopyGlyphsToSink(aBuffer
, pathBuilderD2D
->GetSink());
112 return pathBuilder
->Finish();
115 SkTypeface
* ScaledFontDWrite::CreateSkTypeface() {
116 RefPtr
<IDWriteFactory
> factory
= Factory::GetDWriteFactory();
121 auto& settings
= DWriteSettings();
122 Float gamma
= settings
.Gamma();
123 // Skia doesn't support a gamma value outside of 0-4, so default to 2.2
124 if (gamma
< 0.0f
|| gamma
> 4.0f
) {
128 Float contrast
= settings
.EnhancedContrast();
129 // Skia doesn't support a contrast value outside of 0-1, so default to 1.0
130 if (contrast
< 0.0f
|| contrast
> 1.0f
) {
134 Float clearTypeLevel
= settings
.ClearTypeLevel();
135 if (clearTypeLevel
< 0.0f
|| clearTypeLevel
> 1.0f
) {
136 clearTypeLevel
= 1.0f
;
139 return SkCreateTypefaceFromDWriteFont(factory
, mFontFace
, mStyle
,
140 (int)settings
.RenderingMode(), gamma
,
141 contrast
, clearTypeLevel
);
144 void ScaledFontDWrite::SetupSkFontDrawOptions(SkFont
& aFont
) {
145 if (ForceGDIMode()) {
146 aFont
.setEmbeddedBitmaps(true);
147 aFont
.setSubpixel(false);
149 aFont
.setEmbeddedBitmaps(UseEmbeddedBitmaps());
150 aFont
.setSubpixel(true);
154 bool ScaledFontDWrite::MayUseBitmaps() {
155 return ForceGDIMode() || UseEmbeddedBitmaps();
158 void ScaledFontDWrite::CopyGlyphsToBuilder(const GlyphBuffer
& aBuffer
,
159 PathBuilder
* aBuilder
,
160 const Matrix
* aTransformHint
) {
161 BackendType backendType
= aBuilder
->GetBackendType();
162 if (backendType
!= BackendType::DIRECT2D
&&
163 backendType
!= BackendType::DIRECT2D1_1
) {
164 ScaledFontBase::CopyGlyphsToBuilder(aBuffer
, aBuilder
, aTransformHint
);
168 PathBuilderD2D
* pathBuilderD2D
= static_cast<PathBuilderD2D
*>(aBuilder
);
170 if (pathBuilderD2D
->IsFigureActive()) {
172 << "Attempting to copy glyphs to PathBuilderD2D with active figure.";
175 CopyGlyphsToSink(aBuffer
, pathBuilderD2D
->GetSink());
178 void ScaledFontDWrite::CopyGlyphsToSink(const GlyphBuffer
& aBuffer
,
179 ID2D1SimplifiedGeometrySink
* aSink
) {
180 std::vector
<UINT16
> indices
;
181 std::vector
<FLOAT
> advances
;
182 std::vector
<DWRITE_GLYPH_OFFSET
> offsets
;
183 indices
.resize(aBuffer
.mNumGlyphs
);
184 advances
.resize(aBuffer
.mNumGlyphs
);
185 offsets
.resize(aBuffer
.mNumGlyphs
);
187 memset(&advances
.front(), 0, sizeof(FLOAT
) * aBuffer
.mNumGlyphs
);
188 for (unsigned int i
= 0; i
< aBuffer
.mNumGlyphs
; i
++) {
189 indices
[i
] = aBuffer
.mGlyphs
[i
].mIndex
;
190 offsets
[i
].advanceOffset
= aBuffer
.mGlyphs
[i
].mPosition
.x
;
191 offsets
[i
].ascenderOffset
= -aBuffer
.mGlyphs
[i
].mPosition
.y
;
194 HRESULT hr
= mFontFace
->GetGlyphRunOutline(
195 mSize
, &indices
.front(), &advances
.front(), &offsets
.front(),
196 aBuffer
.mNumGlyphs
, FALSE
, FALSE
, aSink
);
198 gfxCriticalNote
<< "Failed to copy glyphs to geometry sink. Code: "
203 bool UnscaledFontDWrite::GetFontFileData(FontFileDataOutput aDataCallback
,
205 UINT32 fileCount
= 0;
206 HRESULT hr
= mFontFace
->GetFiles(&fileCount
, nullptr);
208 if (FAILED(hr
) || fileCount
> 1) {
213 if (!aDataCallback
) {
217 RefPtr
<IDWriteFontFile
> file
;
218 hr
= mFontFace
->GetFiles(&fileCount
, getter_AddRefs(file
));
223 const void* referenceKey
;
225 // XXX - This can currently crash for webfonts, as when we get the reference
226 // key out of the file, that can be an invalid reference key for the loader
227 // we use it with. The fix to this is not obvious but it will probably
228 // have to happen inside thebes.
229 hr
= file
->GetReferenceKey(&referenceKey
, &refKeySize
);
234 RefPtr
<IDWriteFontFileLoader
> loader
;
235 hr
= file
->GetLoader(getter_AddRefs(loader
));
240 RefPtr
<IDWriteFontFileStream
> stream
;
241 hr
= loader
->CreateStreamFromKey(referenceKey
, refKeySize
,
242 getter_AddRefs(stream
));
248 hr
= stream
->GetFileSize(&fileSize64
);
249 if (FAILED(hr
) || fileSize64
> UINT32_MAX
) {
254 // Try to catch any device memory exceptions that may occur while attempting
255 // to read the file fragment.
256 void* context
= nullptr;
259 uint32_t fileSize
= static_cast<uint32_t>(fileSize64
);
260 const void* fragmentStart
= nullptr;
261 hr
= stream
->ReadFileFragment(&fragmentStart
, 0, fileSize
, &context
);
263 aDataCallback((uint8_t*)fragmentStart
, fileSize
, mFontFace
->GetIndex(),
267 MOZ_SEH_EXCEPT(EXCEPTION_EXECUTE_HANDLER
) {
268 gfxCriticalNote
<< "Exception occurred reading DWrite font file data";
273 stream
->ReleaseFileFragment(context
);
277 static bool GetFontFileName(RefPtr
<IDWriteFontFace
> aFontFace
,
278 std::vector
<WCHAR
>& aFileName
) {
280 HRESULT hr
= aFontFace
->GetFiles(&numFiles
, nullptr);
282 gfxDebug() << "Failed getting file count for WR font";
284 } else if (numFiles
!= 1) {
285 gfxDebug() << "Invalid file count " << numFiles
<< " for WR font";
289 RefPtr
<IDWriteFontFile
> file
;
290 hr
= aFontFace
->GetFiles(&numFiles
, getter_AddRefs(file
));
292 gfxDebug() << "Failed getting file for WR font";
298 hr
= file
->GetReferenceKey(&key
, &keySize
);
300 gfxDebug() << "Failed getting file ref key for WR font";
303 RefPtr
<IDWriteFontFileLoader
> loader
;
304 hr
= file
->GetLoader(getter_AddRefs(loader
));
306 gfxDebug() << "Failed getting file loader for WR font";
309 RefPtr
<IDWriteLocalFontFileLoader
> localLoader
;
310 loader
->QueryInterface(__uuidof(IDWriteLocalFontFileLoader
),
311 (void**)getter_AddRefs(localLoader
));
313 gfxDebug() << "Failed querying loader interface for WR font";
317 hr
= localLoader
->GetFilePathLengthFromKey(key
, keySize
, &pathLen
);
319 gfxDebug() << "Failed getting path length for WR font";
322 aFileName
.resize(pathLen
+ 1);
323 hr
= localLoader
->GetFilePathFromKey(key
, keySize
, aFileName
.data(),
325 if (FAILED(hr
) || aFileName
.back() != 0) {
326 gfxDebug() << "Failed getting path for WR font";
329 DWORD attribs
= GetFileAttributesW(aFileName
.data());
330 if (attribs
== INVALID_FILE_ATTRIBUTES
) {
331 gfxDebug() << "Invalid file \"" << aFileName
.data() << "\" for WR font";
334 // We leave the null terminator at the end of the returned file name.
338 bool UnscaledFontDWrite::GetFontDescriptor(FontDescriptorOutput aCb
,
344 std::vector
<WCHAR
> fileName
;
345 if (!GetFontFileName(mFontFace
, fileName
)) {
348 uint32_t index
= mFontFace
->GetIndex();
350 aCb(reinterpret_cast<const uint8_t*>(fileName
.data()),
351 fileName
.size() * sizeof(WCHAR
), index
, aBaton
);
355 ScaledFontDWrite::InstanceData::InstanceData(
356 const wr::FontInstanceOptions
* aOptions
,
357 const wr::FontInstancePlatformOptions
* aPlatformOptions
) {
359 if (aOptions
->flags
& wr::FontInstanceFlags::EMBEDDED_BITMAPS
) {
360 mUseEmbeddedBitmap
= true;
362 if (aOptions
->flags
& wr::FontInstanceFlags::SYNTHETIC_BOLD
) {
363 mUseBoldSimulation
= true;
365 if (aOptions
->flags
& wr::FontInstanceFlags::MULTISTRIKE_BOLD
) {
366 mUseMultistrikeBold
= true;
368 if (aOptions
->flags
& wr::FontInstanceFlags::FORCE_GDI
) {
374 bool ScaledFontDWrite::HasVariationSettings() {
375 RefPtr
<IDWriteFontFace5
> ff5
;
376 mFontFace
->QueryInterface(__uuidof(IDWriteFontFace5
),
377 (void**)getter_AddRefs(ff5
));
378 if (!ff5
|| !ff5
->HasVariations()) {
382 uint32_t count
= ff5
->GetFontAxisValueCount();
387 RefPtr
<IDWriteFontResource
> res
;
388 if (FAILED(ff5
->GetFontResource(getter_AddRefs(res
)))) {
392 std::vector
<DWRITE_FONT_AXIS_VALUE
> defaults(count
);
393 if (FAILED(res
->GetDefaultFontAxisValues(defaults
.data(), count
))) {
397 std::vector
<DWRITE_FONT_AXIS_VALUE
> values(count
);
398 if (FAILED(ff5
->GetFontAxisValues(values
.data(), count
))) {
402 for (uint32_t i
= 0; i
< count
; i
++) {
403 DWRITE_FONT_AXIS_ATTRIBUTES attr
= res
->GetFontAxisAttributes(i
);
404 if (attr
& DWRITE_FONT_AXIS_ATTRIBUTES_VARIABLE
) {
405 if (values
[i
].value
!= defaults
[i
].value
) {
414 // Helper for ScaledFontDWrite::GetFontInstanceData: if the font has variation
415 // axes, get their current values into the aOutput vector.
416 static void GetVariationsFromFontFace(IDWriteFontFace
* aFace
,
417 std::vector
<FontVariation
>* aOutput
) {
418 RefPtr
<IDWriteFontFace5
> ff5
;
419 aFace
->QueryInterface(__uuidof(IDWriteFontFace5
),
420 (void**)getter_AddRefs(ff5
));
421 if (!ff5
|| !ff5
->HasVariations()) {
425 uint32_t count
= ff5
->GetFontAxisValueCount();
430 RefPtr
<IDWriteFontResource
> res
;
431 if (FAILED(ff5
->GetFontResource(getter_AddRefs(res
)))) {
435 std::vector
<DWRITE_FONT_AXIS_VALUE
> values(count
);
436 if (FAILED(ff5
->GetFontAxisValues(values
.data(), count
))) {
440 aOutput
->reserve(count
);
441 for (uint32_t i
= 0; i
< count
; i
++) {
442 DWRITE_FONT_AXIS_ATTRIBUTES attr
= res
->GetFontAxisAttributes(i
);
443 if (attr
& DWRITE_FONT_AXIS_ATTRIBUTES_VARIABLE
) {
444 float v
= values
[i
].value
;
445 uint32_t t
= TRUETYPE_TAG(
446 uint8_t(values
[i
].axisTag
), uint8_t(values
[i
].axisTag
>> 8),
447 uint8_t(values
[i
].axisTag
>> 16), uint8_t(values
[i
].axisTag
>> 24));
448 aOutput
->push_back(FontVariation
{uint32_t(t
), float(v
)});
453 bool ScaledFontDWrite::GetFontInstanceData(FontInstanceDataOutput aCb
,
455 InstanceData
instance(this);
457 // If the font has variations, get the list of axis values.
458 std::vector
<FontVariation
> variations
;
459 GetVariationsFromFontFace(mFontFace
, &variations
);
461 aCb(reinterpret_cast<uint8_t*>(&instance
), sizeof(instance
),
462 variations
.data(), variations
.size(), aBaton
);
467 bool ScaledFontDWrite::GetWRFontInstanceOptions(
468 Maybe
<wr::FontInstanceOptions
>* aOutOptions
,
469 Maybe
<wr::FontInstancePlatformOptions
>* aOutPlatformOptions
,
470 std::vector
<FontVariation
>* aOutVariations
) {
471 wr::FontInstanceOptions options
;
472 options
.render_mode
= wr::ToFontRenderMode(GetDefaultAAMode());
473 options
.flags
= wr::FontInstanceFlags
{0};
474 if (HasBoldSimulation()) {
475 options
.flags
|= wr::FontInstanceFlags::SYNTHETIC_BOLD
;
477 if (UseMultistrikeBold()) {
478 options
.flags
|= wr::FontInstanceFlags::MULTISTRIKE_BOLD
;
480 if (UseEmbeddedBitmaps()) {
481 options
.flags
|= wr::FontInstanceFlags::EMBEDDED_BITMAPS
;
483 if (ForceGDIMode()) {
484 options
.flags
|= wr::FontInstanceFlags::FORCE_GDI
;
486 options
.flags
|= wr::FontInstanceFlags::SUBPIXEL_POSITION
;
488 auto& settings
= DWriteSettings();
489 switch (settings
.RenderingMode()) {
490 case DWRITE_RENDERING_MODE_CLEARTYPE_NATURAL_SYMMETRIC
:
491 options
.flags
|= wr::FontInstanceFlags::FORCE_SYMMETRIC
;
493 case DWRITE_RENDERING_MODE_CLEARTYPE_NATURAL
:
494 options
.flags
|= wr::FontInstanceFlags::NO_SYMMETRIC
;
499 if (Factory::GetBGRSubpixelOrder()) {
500 options
.flags
|= wr::FontInstanceFlags::SUBPIXEL_BGR
;
502 options
.synthetic_italics
=
503 wr::DegreesToSyntheticItalics(GetSyntheticObliqueAngle());
505 wr::FontInstancePlatformOptions platformOptions
;
506 platformOptions
.gamma
= uint16_t(std::round(settings
.Gamma() * 100.0f
));
507 platformOptions
.contrast
=
508 uint8_t(std::round(std::min(settings
.EnhancedContrast(), 1.0f
) * 100.0f
));
509 platformOptions
.cleartype_level
=
510 uint8_t(std::round(std::min(settings
.ClearTypeLevel(), 1.0f
) * 100.0f
));
512 *aOutOptions
= Some(options
);
513 *aOutPlatformOptions
= Some(platformOptions
);
515 GetVariationsFromFontFace(mFontFace
, aOutVariations
);
520 DWriteSettings
& ScaledFontDWrite::DWriteSettings() const {
521 return DWriteSettings::Get(mGDIForced
);
524 // Helper for UnscaledFontDWrite::CreateScaledFont: create a clone of the
525 // given IDWriteFontFace, with specified variation-axis values applied.
526 // Returns nullptr in case of failure.
527 static already_AddRefed
<IDWriteFontFace5
> CreateFaceWithVariations(
528 IDWriteFontFace
* aFace
, DWRITE_FONT_SIMULATIONS aSimulations
,
529 const FontVariation
* aVariations
= nullptr, uint32_t aNumVariations
= 0) {
530 auto makeDWriteAxisTag
= [](uint32_t aTag
) {
531 return DWRITE_MAKE_FONT_AXIS_TAG((aTag
>> 24) & 0xff, (aTag
>> 16) & 0xff,
532 (aTag
>> 8) & 0xff, aTag
& 0xff);
536 RefPtr
<IDWriteFontFace5
> ff5
;
537 aFace
->QueryInterface(__uuidof(IDWriteFontFace5
),
538 (void**)getter_AddRefs(ff5
));
543 RefPtr
<IDWriteFontResource
> res
;
544 if (FAILED(ff5
->GetFontResource(getter_AddRefs(res
)))) {
548 std::vector
<DWRITE_FONT_AXIS_VALUE
> fontAxisValues
;
549 if (aNumVariations
) {
550 fontAxisValues
.reserve(aNumVariations
);
551 for (uint32_t i
= 0; i
< aNumVariations
; i
++) {
552 DWRITE_FONT_AXIS_VALUE axisValue
= {
553 makeDWriteAxisTag(aVariations
[i
].mTag
), aVariations
[i
].mValue
};
554 fontAxisValues
.push_back(axisValue
);
557 uint32_t count
= ff5
->GetFontAxisValueCount();
559 fontAxisValues
.resize(count
);
560 if (FAILED(ff5
->GetFontAxisValues(fontAxisValues
.data(), count
))) {
561 fontAxisValues
.clear();
566 RefPtr
<IDWriteFontFace5
> newFace
;
567 if (FAILED(res
->CreateFontFace(aSimulations
, fontAxisValues
.data(),
568 fontAxisValues
.size(),
569 getter_AddRefs(newFace
)))) {
572 return newFace
.forget();
574 MOZ_SEH_EXCEPT(EXCEPTION_EXECUTE_HANDLER
) {
575 gfxCriticalNote
<< "Exception occurred initializing variation face";
580 bool UnscaledFontDWrite::InitBold() {
585 DWRITE_FONT_SIMULATIONS sims
= mFontFace
->GetSimulations();
586 if (sims
& DWRITE_FONT_SIMULATIONS_BOLD
) {
587 mFontFaceBold
= mFontFace
;
590 sims
|= DWRITE_FONT_SIMULATIONS_BOLD
;
592 RefPtr
<IDWriteFontFace5
> ff5
= CreateFaceWithVariations(mFontFace
, sims
);
598 if (FAILED(mFontFace
->GetFiles(&numFiles
, nullptr))) {
601 StackArray
<IDWriteFontFile
*, 1> files(numFiles
);
602 if (FAILED(mFontFace
->GetFiles(&numFiles
, files
.data()))) {
605 HRESULT hr
= Factory::GetDWriteFactory()->CreateFontFace(
606 mFontFace
->GetType(), numFiles
, files
.data(), mFontFace
->GetIndex(),
607 sims
, getter_AddRefs(mFontFaceBold
));
608 for (UINT32 i
= 0; i
< numFiles
; ++i
) {
611 if (FAILED(hr
) || !mFontFaceBold
) {
615 MOZ_SEH_EXCEPT(EXCEPTION_EXECUTE_HANDLER
) {
616 gfxCriticalNote
<< "Exception occurred initializing bold face";
623 already_AddRefed
<ScaledFont
> UnscaledFontDWrite::CreateScaledFont(
624 Float aGlyphSize
, const uint8_t* aInstanceData
,
625 uint32_t aInstanceDataLength
, const FontVariation
* aVariations
,
626 uint32_t aNumVariations
) {
627 if (aInstanceDataLength
< sizeof(ScaledFontDWrite::InstanceData
)) {
628 gfxWarning() << "DWrite scaled font instance data is truncated.";
631 const ScaledFontDWrite::InstanceData
& instanceData
=
632 *reinterpret_cast<const ScaledFontDWrite::InstanceData
*>(aInstanceData
);
634 IDWriteFontFace
* face
= mFontFace
;
635 if (instanceData
.mUseBoldSimulation
) {
637 gfxWarning() << "Failed creating bold IDWriteFontFace.";
640 face
= mFontFaceBold
;
642 DWRITE_FONT_SIMULATIONS sims
= face
->GetSimulations();
644 // If variations are required, we create a separate IDWriteFontFace5 with
645 // the requested settings applied.
646 RefPtr
<IDWriteFontFace5
> ff5
;
647 if (aNumVariations
) {
649 CreateFaceWithVariations(mFontFace
, sims
, aVariations
, aNumVariations
);
653 gfxWarning() << "Failed to create IDWriteFontFace5 with variations.";
657 return MakeAndAddRef
<ScaledFontDWrite
>(
658 face
, this, aGlyphSize
, instanceData
.mUseEmbeddedBitmap
,
659 instanceData
.mUseMultistrikeBold
, instanceData
.mGDIForced
, nullptr);
662 already_AddRefed
<ScaledFont
> UnscaledFontDWrite::CreateScaledFontFromWRFont(
663 Float aGlyphSize
, const wr::FontInstanceOptions
* aOptions
,
664 const wr::FontInstancePlatformOptions
* aPlatformOptions
,
665 const FontVariation
* aVariations
, uint32_t aNumVariations
) {
666 ScaledFontDWrite::InstanceData
instanceData(aOptions
, aPlatformOptions
);
667 return CreateScaledFont(aGlyphSize
, reinterpret_cast<uint8_t*>(&instanceData
),
668 sizeof(instanceData
), aVariations
, aNumVariations
);
671 AntialiasMode
ScaledFontDWrite::GetDefaultAAMode() {
672 AntialiasMode defaultMode
= GetSystemDefaultAAMode();
674 switch (defaultMode
) {
675 case AntialiasMode::SUBPIXEL
:
676 case AntialiasMode::DEFAULT
:
677 if (DWriteSettings().ClearTypeLevel() == 0.0f
) {
678 defaultMode
= AntialiasMode::GRAY
;
681 case AntialiasMode::GRAY
:
682 if (!DoGrayscale(mFontFace
, mSize
)) {
683 defaultMode
= AntialiasMode::NONE
;
686 case AntialiasMode::NONE
:
693 cairo_font_face_t
* ScaledFontDWrite::CreateCairoFontFace(
694 cairo_font_options_t
* aFontOptions
) {
699 return cairo_dwrite_font_face_create_for_dwrite_fontface(nullptr, mFontFace
);
702 void ScaledFontDWrite::PrepareCairoScaledFont(cairo_scaled_font_t
* aFont
) {
704 cairo_dwrite_scaled_font_set_force_GDI_classic(aFont
, true);
708 already_AddRefed
<UnscaledFont
> UnscaledFontDWrite::CreateFromFontDescriptor(
709 const uint8_t* aData
, uint32_t aDataLength
, uint32_t aIndex
) {
710 // Note that despite the type of aData here, it actually points to a 16-bit
711 // Windows font file path (hence the cast to WCHAR* below).
712 if (aDataLength
== 0) {
713 gfxWarning() << "DWrite font descriptor is truncated.";
717 RefPtr
<IDWriteFactory
> factory
= Factory::GetDWriteFactory();
723 RefPtr
<IDWriteFontFile
> fontFile
;
724 HRESULT hr
= factory
->CreateFontFileReference((const WCHAR
*)aData
, nullptr,
725 getter_AddRefs(fontFile
));
730 DWRITE_FONT_FILE_TYPE fileType
;
731 DWRITE_FONT_FACE_TYPE faceType
;
733 hr
= fontFile
->Analyze(&isSupported
, &fileType
, &faceType
, &numFaces
);
734 if (FAILED(hr
) || !isSupported
|| aIndex
>= numFaces
) {
737 IDWriteFontFile
* fontFiles
[1] = {fontFile
.get()};
738 RefPtr
<IDWriteFontFace
> fontFace
;
739 hr
= factory
->CreateFontFace(faceType
, 1, fontFiles
, aIndex
,
740 DWRITE_FONT_SIMULATIONS_NONE
,
741 getter_AddRefs(fontFace
));
745 RefPtr unscaledFont
= new UnscaledFontDWrite(fontFace
, nullptr);
746 return unscaledFont
.forget();
748 MOZ_SEH_EXCEPT(EXCEPTION_EXECUTE_HANDLER
) {
749 gfxCriticalNote
<< "Exception occurred creating unscaledFont for "
750 << NS_ConvertUTF16toUTF8((const char16_t
*)aData
).get();
756 } // namespace mozilla