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 "UnscaledFontDWrite.h"
12 #include "mozilla/FontPropertyTypes.h"
13 #include "mozilla/webrender/WebRenderTypes.h"
14 #include "HelpersD2D.h"
15 #include "StackArray.h"
19 // Currently, we build with WINVER=0x601 (Win7), which means newer
20 // declarations in dwrite_3.h will not be visible. Also, we don't
21 // yet have the Fall Creators Update SDK available on build machines,
22 // so even with updated WINVER, some of the interfaces we need would
24 // To work around this, until the build environment is updated,
25 // we #include an extra header that contains copies of the relevant
26 // classes/interfaces we need.
27 #if !defined(__MINGW32__) && WINVER < 0x0A00
28 # include "dw-extra.h"
32 # include "PathSkia.h"
33 # include "skia/include/core/SkPaint.h"
34 # include "skia/include/core/SkPath.h"
35 # include "skia/include/ports/SkTypeface_win.h"
40 #ifdef USE_CAIRO_SCALED_FONT
41 # include "cairo-win32.h"
44 #include "HelpersWinFonts.h"
49 #define GASP_TAG 0x70736167
50 #define GASP_DOGRAY 0x2
52 static inline unsigned short readShort(const char* aBuf
) {
53 return (*aBuf
<< 8) | *(aBuf
+ 1);
56 static bool DoGrayscale(IDWriteFontFace
* aDWFace
, Float ppem
) {
61 aDWFace
->TryGetFontTable(GASP_TAG
, (const void**)&tableData
, &tableSize
,
62 &tableContext
, &exists
);
66 aDWFace
->ReleaseFontTable(tableContext
);
70 unsigned short maxPPEM
; // Stored big-endian
71 unsigned short behavior
; // Stored big-endian
73 unsigned short numRanges
= readShort(tableData
+ 2);
74 if (tableSize
< (UINT
)4 + numRanges
* 4) {
75 aDWFace
->ReleaseFontTable(tableContext
);
78 gaspRange
* ranges
= (gaspRange
*)(tableData
+ 4);
79 for (int i
= 0; i
< numRanges
; i
++) {
80 if (readShort((char*)&ranges
[i
].maxPPEM
) > ppem
) {
81 if (!(readShort((char*)&ranges
[i
].behavior
) & GASP_DOGRAY
)) {
82 aDWFace
->ReleaseFontTable(tableContext
);
88 aDWFace
->ReleaseFontTable(tableContext
);
93 static inline DWRITE_FONT_STRETCH
DWriteFontStretchFromStretch(
94 FontStretch aStretch
) {
95 if (aStretch
== FontStretch::UltraCondensed()) {
96 return DWRITE_FONT_STRETCH_ULTRA_CONDENSED
;
98 if (aStretch
== FontStretch::ExtraCondensed()) {
99 return DWRITE_FONT_STRETCH_EXTRA_CONDENSED
;
101 if (aStretch
== FontStretch::Condensed()) {
102 return DWRITE_FONT_STRETCH_CONDENSED
;
104 if (aStretch
== FontStretch::SemiCondensed()) {
105 return DWRITE_FONT_STRETCH_SEMI_CONDENSED
;
107 if (aStretch
== FontStretch::Normal()) {
108 return DWRITE_FONT_STRETCH_NORMAL
;
110 if (aStretch
== FontStretch::SemiExpanded()) {
111 return DWRITE_FONT_STRETCH_SEMI_EXPANDED
;
113 if (aStretch
== FontStretch::Expanded()) {
114 return DWRITE_FONT_STRETCH_EXPANDED
;
116 if (aStretch
== FontStretch::ExtraExpanded()) {
117 return DWRITE_FONT_STRETCH_EXTRA_EXPANDED
;
119 if (aStretch
== FontStretch::UltraExpanded()) {
120 return DWRITE_FONT_STRETCH_ULTRA_EXPANDED
;
122 return DWRITE_FONT_STRETCH_UNDEFINED
;
125 ScaledFontDWrite::ScaledFontDWrite(
126 IDWriteFontFace
* aFontFace
, const RefPtr
<UnscaledFont
>& aUnscaledFont
,
127 Float aSize
, bool aUseEmbeddedBitmap
, DWRITE_RENDERING_MODE aRenderingMode
,
128 IDWriteRenderingParams
* aParams
, Float aGamma
, Float aContrast
,
129 Float aClearTypeLevel
, const gfxFontStyle
* aStyle
)
130 : ScaledFontBase(aUnscaledFont
, aSize
),
131 mFontFace(aFontFace
),
132 mUseEmbeddedBitmap(aUseEmbeddedBitmap
),
133 mRenderingMode(aRenderingMode
),
136 mContrast(aContrast
),
137 mClearTypeLevel(aClearTypeLevel
) {
139 mStyle
= SkFontStyle(aStyle
->weight
.ToIntRounded(),
140 DWriteFontStretchFromStretch(aStyle
->stretch
),
141 // FIXME(jwatt): also use kOblique_Slant
142 aStyle
->style
== FontSlantStyle::Normal()
143 ? SkFontStyle::kUpright_Slant
144 : SkFontStyle::kItalic_Slant
);
148 already_AddRefed
<Path
> ScaledFontDWrite::GetPathForGlyphs(
149 const GlyphBuffer
& aBuffer
, const DrawTarget
* aTarget
) {
150 RefPtr
<PathBuilder
> pathBuilder
= aTarget
->CreatePathBuilder();
152 if (pathBuilder
->GetBackendType() != BackendType::DIRECT2D
&&
153 pathBuilder
->GetBackendType() != BackendType::DIRECT2D1_1
) {
154 return ScaledFontBase::GetPathForGlyphs(aBuffer
, aTarget
);
157 PathBuilderD2D
* pathBuilderD2D
=
158 static_cast<PathBuilderD2D
*>(pathBuilder
.get());
160 CopyGlyphsToSink(aBuffer
, pathBuilderD2D
->GetSink());
162 return pathBuilder
->Finish();
166 SkTypeface
* ScaledFontDWrite::CreateSkTypeface() {
167 RefPtr
<IDWriteFactory
> factory
= Factory::GetDWriteFactory();
172 Float gamma
= mGamma
;
173 // Skia doesn't support a gamma value outside of 0-4, so default to 2.2
174 if (gamma
< 0.0f
|| gamma
> 4.0f
) {
178 Float contrast
= mContrast
;
179 // Skia doesn't support a contrast value outside of 0-1, so default to 1.0
180 if (contrast
< 0.0f
|| contrast
> 1.0f
) {
184 Float clearTypeLevel
= mClearTypeLevel
;
185 if (clearTypeLevel
< 0.0f
|| clearTypeLevel
> 1.0f
) {
186 clearTypeLevel
= 1.0f
;
189 return SkCreateTypefaceFromDWriteFont(factory
, mFontFace
, mStyle
,
190 (int)mRenderingMode
, gamma
, contrast
,
194 void ScaledFontDWrite::SetupSkFontDrawOptions(SkFont
& aFont
) {
195 if (ForceGDIMode()) {
196 aFont
.setEmbeddedBitmaps(true);
197 aFont
.setSubpixel(false);
199 aFont
.setEmbeddedBitmaps(UseEmbeddedBitmaps());
200 aFont
.setSubpixel(true);
205 void ScaledFontDWrite::CopyGlyphsToBuilder(const GlyphBuffer
& aBuffer
,
206 PathBuilder
* aBuilder
,
207 const Matrix
* aTransformHint
) {
208 BackendType backendType
= aBuilder
->GetBackendType();
209 if (backendType
== BackendType::CAPTURE
) {
210 StreamingGeometrySink
sink(aBuilder
);
211 CopyGlyphsToSink(aBuffer
, &sink
);
215 if (backendType
!= BackendType::DIRECT2D
&&
216 backendType
!= BackendType::DIRECT2D1_1
) {
217 ScaledFontBase::CopyGlyphsToBuilder(aBuffer
, aBuilder
, aTransformHint
);
221 PathBuilderD2D
* pathBuilderD2D
= static_cast<PathBuilderD2D
*>(aBuilder
);
223 if (pathBuilderD2D
->IsFigureActive()) {
225 << "Attempting to copy glyphs to PathBuilderD2D with active figure.";
228 CopyGlyphsToSink(aBuffer
, pathBuilderD2D
->GetSink());
231 void ScaledFontDWrite::CopyGlyphsToSink(const GlyphBuffer
& aBuffer
,
232 ID2D1SimplifiedGeometrySink
* aSink
) {
233 std::vector
<UINT16
> indices
;
234 std::vector
<FLOAT
> advances
;
235 std::vector
<DWRITE_GLYPH_OFFSET
> offsets
;
236 indices
.resize(aBuffer
.mNumGlyphs
);
237 advances
.resize(aBuffer
.mNumGlyphs
);
238 offsets
.resize(aBuffer
.mNumGlyphs
);
240 memset(&advances
.front(), 0, sizeof(FLOAT
) * aBuffer
.mNumGlyphs
);
241 for (unsigned int i
= 0; i
< aBuffer
.mNumGlyphs
; i
++) {
242 indices
[i
] = aBuffer
.mGlyphs
[i
].mIndex
;
243 offsets
[i
].advanceOffset
= aBuffer
.mGlyphs
[i
].mPosition
.x
;
244 offsets
[i
].ascenderOffset
= -aBuffer
.mGlyphs
[i
].mPosition
.y
;
247 HRESULT hr
= mFontFace
->GetGlyphRunOutline(
248 mSize
, &indices
.front(), &advances
.front(), &offsets
.front(),
249 aBuffer
.mNumGlyphs
, FALSE
, FALSE
, aSink
);
251 gfxCriticalNote
<< "Failed to copy glyphs to geometry sink. Code: "
256 bool UnscaledFontDWrite::GetFontFileData(FontFileDataOutput aDataCallback
,
258 UINT32 fileCount
= 0;
259 HRESULT hr
= mFontFace
->GetFiles(&fileCount
, nullptr);
261 if (FAILED(hr
) || fileCount
> 1) {
266 if (!aDataCallback
) {
270 RefPtr
<IDWriteFontFile
> file
;
271 hr
= mFontFace
->GetFiles(&fileCount
, getter_AddRefs(file
));
276 const void* referenceKey
;
278 // XXX - This can currently crash for webfonts, as when we get the reference
279 // key out of the file, that can be an invalid reference key for the loader
280 // we use it with. The fix to this is not obvious but it will probably
281 // have to happen inside thebes.
282 hr
= file
->GetReferenceKey(&referenceKey
, &refKeySize
);
287 RefPtr
<IDWriteFontFileLoader
> loader
;
288 hr
= file
->GetLoader(getter_AddRefs(loader
));
293 RefPtr
<IDWriteFontFileStream
> stream
;
294 hr
= loader
->CreateStreamFromKey(referenceKey
, refKeySize
,
295 getter_AddRefs(stream
));
301 hr
= stream
->GetFileSize(&fileSize64
);
302 if (FAILED(hr
) || fileSize64
> UINT32_MAX
) {
307 uint32_t fileSize
= static_cast<uint32_t>(fileSize64
);
308 const void* fragmentStart
;
310 hr
= stream
->ReadFileFragment(&fragmentStart
, 0, fileSize
, &context
);
315 aDataCallback((uint8_t*)fragmentStart
, fileSize
, mFontFace
->GetIndex(),
318 stream
->ReleaseFileFragment(context
);
323 static bool GetFontFileName(RefPtr
<IDWriteFontFace
> aFontFace
,
324 std::vector
<WCHAR
>& aFileName
) {
326 HRESULT hr
= aFontFace
->GetFiles(&numFiles
, nullptr);
328 gfxDebug() << "Failed getting file count for WR font";
330 } else if (numFiles
!= 1) {
331 gfxDebug() << "Invalid file count " << numFiles
<< " for WR font";
335 RefPtr
<IDWriteFontFile
> file
;
336 hr
= aFontFace
->GetFiles(&numFiles
, getter_AddRefs(file
));
338 gfxDebug() << "Failed getting file for WR font";
344 hr
= file
->GetReferenceKey(&key
, &keySize
);
346 gfxDebug() << "Failed getting file ref key for WR font";
349 RefPtr
<IDWriteFontFileLoader
> loader
;
350 hr
= file
->GetLoader(getter_AddRefs(loader
));
352 gfxDebug() << "Failed getting file loader for WR font";
355 RefPtr
<IDWriteLocalFontFileLoader
> localLoader
;
356 loader
->QueryInterface(__uuidof(IDWriteLocalFontFileLoader
),
357 (void**)getter_AddRefs(localLoader
));
359 gfxDebug() << "Failed querying loader interface for WR font";
363 hr
= localLoader
->GetFilePathLengthFromKey(key
, keySize
, &pathLen
);
365 gfxDebug() << "Failed getting path length for WR font";
368 aFileName
.resize(pathLen
+ 1);
369 hr
= localLoader
->GetFilePathFromKey(key
, keySize
, aFileName
.data(),
371 if (FAILED(hr
) || aFileName
.back() != 0) {
372 gfxDebug() << "Failed getting path for WR font";
375 DWORD attribs
= GetFileAttributesW(aFileName
.data());
376 if (attribs
== INVALID_FILE_ATTRIBUTES
) {
377 gfxDebug() << "Invalid file \"" << aFileName
.data() << "\" for WR font";
380 aFileName
.pop_back();
384 bool UnscaledFontDWrite::GetFontDescriptor(FontDescriptorOutput aCb
,
390 std::vector
<WCHAR
> fileName
;
391 if (!GetFontFileName(mFontFace
, fileName
)) {
394 uint32_t index
= mFontFace
->GetIndex();
396 aCb(reinterpret_cast<const uint8_t*>(fileName
.data()),
397 fileName
.size() * sizeof(WCHAR
), index
, aBaton
);
401 ScaledFontDWrite::InstanceData::InstanceData(
402 const wr::FontInstanceOptions
* aOptions
,
403 const wr::FontInstancePlatformOptions
* aPlatformOptions
)
404 : mUseEmbeddedBitmap(false),
405 mApplySyntheticBold(false),
406 mRenderingMode(DWRITE_RENDERING_MODE_DEFAULT
),
409 mClearTypeLevel(1.0f
) {
411 if (aOptions
->flags
& wr::FontInstanceFlags::EMBEDDED_BITMAPS
) {
412 mUseEmbeddedBitmap
= true;
414 if (aOptions
->flags
& wr::FontInstanceFlags::SYNTHETIC_BOLD
) {
415 mApplySyntheticBold
= true;
417 if (aOptions
->flags
& wr::FontInstanceFlags::FORCE_GDI
) {
418 mRenderingMode
= DWRITE_RENDERING_MODE_GDI_CLASSIC
;
419 } else if (aOptions
->flags
& wr::FontInstanceFlags::FORCE_SYMMETRIC
) {
420 mRenderingMode
= DWRITE_RENDERING_MODE_CLEARTYPE_NATURAL_SYMMETRIC
;
421 } else if (aOptions
->flags
& wr::FontInstanceFlags::NO_SYMMETRIC
) {
422 mRenderingMode
= DWRITE_RENDERING_MODE_CLEARTYPE_NATURAL
;
425 if (aPlatformOptions
) {
426 mGamma
= aPlatformOptions
->gamma
/ 100.0f
;
427 mContrast
= aPlatformOptions
->contrast
/ 100.0f
;
428 mClearTypeLevel
= aPlatformOptions
->cleartype_level
/ 100.0f
;
432 // Helper for ScaledFontDWrite::GetFontInstanceData: if the font has variation
433 // axes, get their current values into the aOutput vector.
434 static void GetVariationsFromFontFace(IDWriteFontFace
* aFace
,
435 std::vector
<FontVariation
>* aOutput
) {
436 RefPtr
<IDWriteFontFace5
> ff5
;
437 aFace
->QueryInterface(__uuidof(IDWriteFontFace5
),
438 (void**)getter_AddRefs(ff5
));
439 if (!ff5
|| !ff5
->HasVariations()) {
443 uint32_t count
= ff5
->GetFontAxisValueCount();
448 RefPtr
<IDWriteFontResource
> res
;
449 if (FAILED(ff5
->GetFontResource(getter_AddRefs(res
)))) {
453 std::vector
<DWRITE_FONT_AXIS_VALUE
> values(count
);
454 if (FAILED(ff5
->GetFontAxisValues(values
.data(), count
))) {
458 aOutput
->reserve(count
);
459 for (uint32_t i
= 0; i
< count
; i
++) {
460 DWRITE_FONT_AXIS_ATTRIBUTES attr
= res
->GetFontAxisAttributes(i
);
461 if (attr
& DWRITE_FONT_AXIS_ATTRIBUTES_VARIABLE
) {
462 float v
= values
[i
].value
;
463 uint32_t t
= TRUETYPE_TAG(
464 uint8_t(values
[i
].axisTag
), uint8_t(values
[i
].axisTag
>> 8),
465 uint8_t(values
[i
].axisTag
>> 16), uint8_t(values
[i
].axisTag
>> 24));
466 aOutput
->push_back(FontVariation
{uint32_t(t
), float(v
)});
471 bool ScaledFontDWrite::GetFontInstanceData(FontInstanceDataOutput aCb
,
473 InstanceData
instance(this);
475 // If the font has variations, get the list of axis values.
476 std::vector
<FontVariation
> variations
;
477 GetVariationsFromFontFace(mFontFace
, &variations
);
479 aCb(reinterpret_cast<uint8_t*>(&instance
), sizeof(instance
),
480 variations
.data(), variations
.size(), aBaton
);
485 bool ScaledFontDWrite::GetWRFontInstanceOptions(
486 Maybe
<wr::FontInstanceOptions
>* aOutOptions
,
487 Maybe
<wr::FontInstancePlatformOptions
>* aOutPlatformOptions
,
488 std::vector
<FontVariation
>* aOutVariations
) {
489 wr::FontInstanceOptions options
;
490 options
.render_mode
= wr::ToFontRenderMode(GetDefaultAAMode());
491 options
.flags
= wr::FontInstanceFlags
{0};
492 if (HasSyntheticBold()) {
493 options
.flags
|= wr::FontInstanceFlags::SYNTHETIC_BOLD
;
495 if (UseEmbeddedBitmaps()) {
496 options
.flags
|= wr::FontInstanceFlags::EMBEDDED_BITMAPS
;
498 if (ForceGDIMode()) {
499 options
.flags
|= wr::FontInstanceFlags::FORCE_GDI
;
501 options
.flags
|= wr::FontInstanceFlags::SUBPIXEL_POSITION
;
503 switch (GetRenderingMode()) {
504 case DWRITE_RENDERING_MODE_CLEARTYPE_NATURAL_SYMMETRIC
:
505 options
.flags
|= wr::FontInstanceFlags::FORCE_SYMMETRIC
;
507 case DWRITE_RENDERING_MODE_CLEARTYPE_NATURAL
:
508 options
.flags
|= wr::FontInstanceFlags::NO_SYMMETRIC
;
513 if (Factory::GetBGRSubpixelOrder()) {
514 options
.flags
|= wr::FontInstanceFlags::SUBPIXEL_BGR
;
516 options
.bg_color
= wr::ToColorU(DeviceColor());
517 options
.synthetic_italics
=
518 wr::DegreesToSyntheticItalics(GetSyntheticObliqueAngle());
520 wr::FontInstancePlatformOptions platformOptions
;
521 platformOptions
.gamma
= uint16_t(std::round(mGamma
* 100.0f
));
522 platformOptions
.contrast
=
523 uint8_t(std::round(std::min(mContrast
, 1.0f
) * 100.0f
));
524 platformOptions
.cleartype_level
=
525 uint8_t(std::round(std::min(mClearTypeLevel
, 1.0f
) * 100.0f
));
527 *aOutOptions
= Some(options
);
528 *aOutPlatformOptions
= Some(platformOptions
);
530 GetVariationsFromFontFace(mFontFace
, aOutVariations
);
535 // Helper for UnscaledFontDWrite::CreateScaledFont: create a clone of the
536 // given IDWriteFontFace, with specified variation-axis values applied.
537 // Returns nullptr in case of failure.
538 static already_AddRefed
<IDWriteFontFace5
> CreateFaceWithVariations(
539 IDWriteFontFace
* aFace
, DWRITE_FONT_SIMULATIONS aSimulations
,
540 const FontVariation
* aVariations
= nullptr, uint32_t aNumVariations
= 0) {
541 auto makeDWriteAxisTag
= [](uint32_t aTag
) {
542 return DWRITE_MAKE_FONT_AXIS_TAG((aTag
>> 24) & 0xff, (aTag
>> 16) & 0xff,
543 (aTag
>> 8) & 0xff, aTag
& 0xff);
546 RefPtr
<IDWriteFontFace5
> ff5
;
547 aFace
->QueryInterface(__uuidof(IDWriteFontFace5
),
548 (void**)getter_AddRefs(ff5
));
553 RefPtr
<IDWriteFontResource
> res
;
554 if (FAILED(ff5
->GetFontResource(getter_AddRefs(res
)))) {
558 std::vector
<DWRITE_FONT_AXIS_VALUE
> fontAxisValues
;
559 if (aNumVariations
) {
560 fontAxisValues
.reserve(aNumVariations
);
561 for (uint32_t i
= 0; i
< aNumVariations
; i
++) {
562 DWRITE_FONT_AXIS_VALUE axisValue
= {
563 makeDWriteAxisTag(aVariations
[i
].mTag
), aVariations
[i
].mValue
};
564 fontAxisValues
.push_back(axisValue
);
567 uint32_t count
= ff5
->GetFontAxisValueCount();
569 fontAxisValues
.resize(count
);
570 if (FAILED(ff5
->GetFontAxisValues(fontAxisValues
.data(), count
))) {
571 fontAxisValues
.clear();
576 RefPtr
<IDWriteFontFace5
> newFace
;
577 if (FAILED(res
->CreateFontFace(aSimulations
, fontAxisValues
.data(),
578 fontAxisValues
.size(),
579 getter_AddRefs(newFace
)))) {
583 return newFace
.forget();
586 bool UnscaledFontDWrite::InitBold() {
591 DWRITE_FONT_SIMULATIONS sims
= mFontFace
->GetSimulations();
592 if (sims
& DWRITE_FONT_SIMULATIONS_BOLD
) {
593 mFontFaceBold
= mFontFace
;
596 sims
|= DWRITE_FONT_SIMULATIONS_BOLD
;
598 RefPtr
<IDWriteFontFace5
> ff5
= CreateFaceWithVariations(mFontFace
, sims
);
603 if (FAILED(mFontFace
->GetFiles(&numFiles
, nullptr))) {
606 StackArray
<IDWriteFontFile
*, 1> files(numFiles
);
607 if (FAILED(mFontFace
->GetFiles(&numFiles
, files
.data()))) {
610 HRESULT hr
= Factory::GetDWriteFactory()->CreateFontFace(
611 mFontFace
->GetType(), numFiles
, files
.data(), mFontFace
->GetIndex(),
612 sims
, getter_AddRefs(mFontFaceBold
));
613 for (UINT32 i
= 0; i
< numFiles
; ++i
) {
616 if (FAILED(hr
) || !mFontFaceBold
) {
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
.mApplySyntheticBold
) {
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 RefPtr
<ScaledFontBase
> scaledFont
= new ScaledFontDWrite(
658 face
, this, aGlyphSize
, instanceData
.mUseEmbeddedBitmap
,
659 instanceData
.mRenderingMode
, nullptr, instanceData
.mGamma
,
660 instanceData
.mContrast
, instanceData
.mClearTypeLevel
);
662 return scaledFont
.forget();
665 already_AddRefed
<ScaledFont
> UnscaledFontDWrite::CreateScaledFontFromWRFont(
666 Float aGlyphSize
, const wr::FontInstanceOptions
* aOptions
,
667 const wr::FontInstancePlatformOptions
* aPlatformOptions
,
668 const FontVariation
* aVariations
, uint32_t aNumVariations
) {
669 ScaledFontDWrite::InstanceData
instanceData(aOptions
, aPlatformOptions
);
670 return CreateScaledFont(aGlyphSize
, reinterpret_cast<uint8_t*>(&instanceData
),
671 sizeof(instanceData
), aVariations
, aNumVariations
);
674 AntialiasMode
ScaledFontDWrite::GetDefaultAAMode() {
675 AntialiasMode defaultMode
= GetSystemDefaultAAMode();
677 switch (defaultMode
) {
678 case AntialiasMode::SUBPIXEL
:
679 case AntialiasMode::DEFAULT
:
680 if (mClearTypeLevel
== 0.0f
) {
681 defaultMode
= AntialiasMode::GRAY
;
684 case AntialiasMode::GRAY
:
685 if (!DoGrayscale(mFontFace
, mSize
)) {
686 defaultMode
= AntialiasMode::NONE
;
689 case AntialiasMode::NONE
:
696 #ifdef USE_CAIRO_SCALED_FONT
697 cairo_font_face_t
* ScaledFontDWrite::CreateCairoFontFace(
698 cairo_font_options_t
* aFontOptions
) {
703 return cairo_dwrite_font_face_create_for_dwrite_fontface(nullptr, mFontFace
);
706 void ScaledFontDWrite::PrepareCairoScaledFont(cairo_scaled_font_t
* aFont
) {
707 if (mRenderingMode
== DWRITE_RENDERING_MODE_GDI_CLASSIC
) {
708 cairo_dwrite_scaled_font_set_force_GDI_classic(aFont
, true);
713 already_AddRefed
<UnscaledFont
> UnscaledFontDWrite::CreateFromFontDescriptor(
714 const uint8_t* aData
, uint32_t aDataLength
, uint32_t aIndex
) {
715 if (aDataLength
== 0) {
716 gfxWarning() << "DWrite font descriptor is truncated.";
720 RefPtr
<IDWriteFactory
> factory
= Factory::GetDWriteFactory();
724 RefPtr
<IDWriteFontFile
> fontFile
;
725 HRESULT hr
= factory
->CreateFontFileReference((const WCHAR
*)aData
, nullptr,
726 getter_AddRefs(fontFile
));
731 DWRITE_FONT_FILE_TYPE fileType
;
732 DWRITE_FONT_FACE_TYPE faceType
;
734 hr
= fontFile
->Analyze(&isSupported
, &fileType
, &faceType
, &numFaces
);
735 if (FAILED(hr
) || !isSupported
|| aIndex
>= numFaces
) {
738 IDWriteFontFile
* fontFiles
[1] = {fontFile
.get()};
739 RefPtr
<IDWriteFontFace
> fontFace
;
740 hr
= factory
->CreateFontFace(faceType
, 1, fontFiles
, aIndex
,
741 DWRITE_FONT_SIMULATIONS_NONE
,
742 getter_AddRefs(fontFace
));
746 RefPtr
<UnscaledFont
> unscaledFont
= new UnscaledFontDWrite(fontFace
, nullptr);
747 return unscaledFont
.forget();
751 } // namespace mozilla