Flutter Engine
The Flutter Engine
Loading...
Searching...
No Matches
SkTypeface_win_dw.cpp
Go to the documentation of this file.
1/*
2 * Copyright 2014 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
8
10#if defined(SK_BUILD_FOR_WIN)
11
13
14// SkLeanWindows will include Windows.h, which will pull in all of the GDI defines.
15// GDI #defines GetGlyphIndices to GetGlyphIndicesA or GetGlyphIndicesW, but
16// IDWriteFontFace has a method called GetGlyphIndices. Since this file does
17// not use GDI, undefing GetGlyphIndices makes things less confusing.
18#undef GetGlyphIndices
19
20#include "include/core/SkData.h"
33#include "src/sfnt/SkOTUtils.h"
36
37using namespace skia_private;
38
39SkFontStyle DWriteFontTypeface::GetStyle(IDWriteFont* font, IDWriteFontFace* fontFace) {
40 int weight = font->GetWeight();
41 int width = font->GetStretch();
43 switch (font->GetStyle()) {
44 case DWRITE_FONT_STYLE_NORMAL: slant = SkFontStyle::kUpright_Slant; break;
45 case DWRITE_FONT_STYLE_OBLIQUE: slant = SkFontStyle::kOblique_Slant; break;
46 case DWRITE_FONT_STYLE_ITALIC: slant = SkFontStyle::kItalic_Slant; break;
47 default: SkASSERT(false); break;
48 }
49
50#if defined(NTDDI_WIN10_RS3) && NTDDI_VERSION >= NTDDI_WIN10_RS3
51 [&weight, &width, &slant, fontFace]() -> void {
52 SkTScopedComPtr<IDWriteFontFace5> fontFace5;
53 if (FAILED(fontFace->QueryInterface(&fontFace5))) {
54 return;
55 }
56 if (!fontFace5->HasVariations()) {
57 return;
58 }
59
60 UINT32 fontAxisCount = fontFace5->GetFontAxisValueCount();
61 SkTScopedComPtr<IDWriteFontResource> fontResource;
62 HRV(fontFace5->GetFontResource(&fontResource));
63
64 AutoSTMalloc<8, DWRITE_FONT_AXIS_VALUE> fontAxisValue(fontAxisCount);
65 HRV(fontFace5->GetFontAxisValues(fontAxisValue.get(), fontAxisCount));
66 for (UINT32 axisIndex = 0; axisIndex < fontAxisCount; ++axisIndex) {
67 if (fontAxisValue[axisIndex].axisTag == DWRITE_FONT_AXIS_TAG_WEIGHT) {
68 weight = fontAxisValue[axisIndex].value;
69 }
70 if (fontAxisValue[axisIndex].axisTag == DWRITE_FONT_AXIS_TAG_WIDTH) {
71 SkScalar wdthValue = fontAxisValue[axisIndex].value;
73 }
74 if (fontAxisValue[axisIndex].axisTag == DWRITE_FONT_AXIS_TAG_SLANT &&
76 {
77 if (fontAxisValue[axisIndex].value == 0) {
79 } else {
81 }
82 }
83 }
84 }();
85#endif
86 return SkFontStyle(weight, width, slant);
87}
88
90 IDWriteFactory* factory,
91 IDWriteFontFace* fontFace,
92 IDWriteFont* font,
93 IDWriteFontFamily* fontFamily,
94 sk_sp<Loaders> loaders,
95 const SkFontArguments::Palette& palette)
96{
98 GetStyle(font, fontFace), factory, fontFace, font, fontFamily, std::move(loaders), palette));
99}
100
101HRESULT DWriteFontTypeface::initializePalette() {
102 if (!fIsColorFont) {
103 return S_OK;
104 }
105
106 UINT32 dwPaletteCount = fDWriteFontFace2->GetColorPaletteCount();
107 if (dwPaletteCount == 0) {
108 return S_OK;
109 }
110
111 // Treat out of range palette index values as 0. Still apply overrides.
112 // https://www.w3.org/TR/css-fonts-4/#base-palette-desc
113 UINT32 basePaletteIndex = 0;
114 if (SkTFitsIn<UINT32>(fRequestedPalette.index) &&
115 SkTo<UINT32>(fRequestedPalette.index) < dwPaletteCount)
116 {
117 basePaletteIndex = fRequestedPalette.index;
118 }
119
120 UINT32 dwPaletteEntryCount = fDWriteFontFace2->GetPaletteEntryCount();
121 AutoSTMalloc<8, DWRITE_COLOR_F> dwPaletteEntry(dwPaletteEntryCount);
122 HRM(fDWriteFontFace2->GetPaletteEntries(basePaletteIndex,
123 0, dwPaletteEntryCount,
124 dwPaletteEntry),
125 "Could not retrieve palette entries.");
126
127 fPalette.reset(new SkColor[dwPaletteEntryCount]);
128 fDWPalette.reset(new DWRITE_COLOR_F[dwPaletteEntryCount]);
129 for (UINT32 i = 0; i < dwPaletteEntryCount; ++i) {
130 fPalette[i] = SkColorSetARGB(sk_float_round2int(dwPaletteEntry[i].a * 255),
131 sk_float_round2int(dwPaletteEntry[i].r * 255),
132 sk_float_round2int(dwPaletteEntry[i].g * 255),
133 sk_float_round2int(dwPaletteEntry[i].b * 255));
134 fDWPalette[i] = dwPaletteEntry[i];
135 }
136
137 for (int i = 0; i < fRequestedPalette.overrideCount; ++i) {
139 if (SkTFitsIn<UINT32>(paletteOverride.index) &&
140 SkTo<UINT32>(paletteOverride.index) < dwPaletteEntryCount)
141 {
142 fPalette[paletteOverride.index] = paletteOverride.color;
143
144 // Avoid brace initialization as DWRITE_COLOR_F can be defined as four floats
145 // (dxgitype.h, d3d9types.h) or four unions of two floats (dwrite_2.h, d3dtypes.h).
146 // The type changed in Direct3D 10, but the change does not appear to be documented.
147 const SkColor4f skColor = SkColor4f::FromColor(paletteOverride.color);
148 DWRITE_COLOR_F& dwColor = fDWPalette[paletteOverride.index];
149 dwColor.r = skColor.fR;
150 dwColor.g = skColor.fG;
151 dwColor.b = skColor.fB;
152 dwColor.a = skColor.fA;
153 }
154 }
155 fPaletteEntryCount = dwPaletteEntryCount;
156
157 return S_OK;
158}
159
160DWriteFontTypeface::DWriteFontTypeface(const SkFontStyle& style,
161 IDWriteFactory* factory,
162 IDWriteFontFace* fontFace,
163 IDWriteFont* font,
164 IDWriteFontFamily* fontFamily,
165 sk_sp<Loaders> loaders,
166 const SkFontArguments::Palette& palette)
167 : SkTypeface(style, false)
168 , fFactory(SkRefComPtr(factory))
169 , fDWriteFontFamily(SkRefComPtr(fontFamily))
170 , fDWriteFont(SkRefComPtr(font))
171 , fDWriteFontFace(SkRefComPtr(fontFace))
172 , fRequestedPaletteEntryOverrides(palette.overrideCount
173 ? (SkFontArguments::Palette::Override*)memcpy(
174 new SkFontArguments::Palette::Override[palette.overrideCount],
175 palette.overrides,
176 palette.overrideCount * sizeof(palette.overrides[0]))
177 : nullptr)
178 , fRequestedPalette{palette.index,
179 fRequestedPaletteEntryOverrides.get(), palette.overrideCount }
180 , fPaletteEntryCount(0)
181 , fLoaders(std::move(loaders))
182{
183 if (!SUCCEEDED(fDWriteFontFace->QueryInterface(&fDWriteFontFace1))) {
184 // IUnknown::QueryInterface states that if it fails, punk will be set to nullptr.
185 // http://blogs.msdn.com/b/oldnewthing/archive/2004/03/26/96777.aspx
186 SkASSERT_RELEASE(nullptr == fDWriteFontFace1.get());
187 }
188 if (!SUCCEEDED(fDWriteFontFace->QueryInterface(&fDWriteFontFace2))) {
189 SkASSERT_RELEASE(nullptr == fDWriteFontFace2.get());
190 }
191 if (!SUCCEEDED(fDWriteFontFace->QueryInterface(&fDWriteFontFace4))) {
192 SkASSERT_RELEASE(nullptr == fDWriteFontFace4.get());
193 }
194#if DWRITE_CORE || (defined(NTDDI_WIN11_ZN) && NTDDI_VERSION >= NTDDI_WIN11_ZN)
195 if (!SUCCEEDED(fDWriteFontFace->QueryInterface(&fDWriteFontFace7))) {
196 SkASSERT_RELEASE(nullptr == fDWriteFontFace7/*.get()*/);
197 }
198#endif
199 if (!SUCCEEDED(fFactory->QueryInterface(&fFactory2))) {
200 SkASSERT_RELEASE(nullptr == fFactory2.get());
201 }
202
203 if (fDWriteFontFace1 && fDWriteFontFace1->IsMonospacedFont()) {
204 this->setIsFixedPitch(true);
205 }
206
207 fIsColorFont = fFactory2 && fDWriteFontFace2 && fDWriteFontFace2->IsColorFont();
208 this->initializePalette();
209}
210
212#if DWRITE_CORE || (defined(NTDDI_WIN11_ZN) && NTDDI_VERSION >= NTDDI_WIN11_ZN)
213 if (fDWriteFontFace7) {
214 fDWriteFontFace7->Release();
215 }
216#endif
217}
218
220 // Don't return if any fail, just keep going to free up as much as possible.
221 HRESULT hr;
222
223 hr = fFactory->UnregisterFontCollectionLoader(fDWriteFontCollectionLoader.get());
224 if (FAILED(hr)) {
225 SK_TRACEHR(hr, "FontCollectionLoader");
226 }
227
228 hr = fFactory->UnregisterFontFileLoader(fDWriteFontFileLoader.get());
229 if (FAILED(hr)) {
230 SK_TRACEHR(hr, "FontFileLoader");
231 }
232}
233
234void DWriteFontTypeface::onGetFamilyName(SkString* familyName) const {
235 SkTScopedComPtr<IDWriteLocalizedStrings> familyNames;
236 HRV(fDWriteFontFamily->GetFamilyNames(&familyNames));
237
238 sk_get_locale_string(familyNames.get(), nullptr/*fMgr->fLocaleName.get()*/, familyName);
239}
240
241bool DWriteFontTypeface::onGetPostScriptName(SkString* skPostScriptName) const {
242 SkString localSkPostScriptName;
243 SkTScopedComPtr<IDWriteLocalizedStrings> postScriptNames;
244 BOOL exists = FALSE;
245 if (FAILED(fDWriteFont->GetInformationalStrings(
246 DWRITE_INFORMATIONAL_STRING_POSTSCRIPT_NAME,
247 &postScriptNames,
248 &exists)) ||
249 !exists ||
250 FAILED(sk_get_locale_string(postScriptNames.get(), nullptr, &localSkPostScriptName)))
251 {
252 return false;
253 }
254 if (skPostScriptName) {
255 *skPostScriptName = localSkPostScriptName;
256 }
257 return true;
258}
259
261 bool* serialize) const {
262 // Get the family name.
263 SkTScopedComPtr<IDWriteLocalizedStrings> familyNames;
264 HRV(fDWriteFontFamily->GetFamilyNames(&familyNames));
265
266 SkString utf8FamilyName;
267 sk_get_locale_string(familyNames.get(), nullptr/*fMgr->fLocaleName.get()*/, &utf8FamilyName);
268
269 desc->setFamilyName(utf8FamilyName.c_str());
270 desc->setStyle(this->fontStyle());
271
273 sk_careful_memcpy(desc->setPaletteEntryOverrides(fRequestedPalette.overrideCount),
276
277 desc->setFactoryId(FactoryId);
278 *serialize = SkToBool(fLoaders);
279}
280
282 SkGlyphID glyphs[]) const {
283 fDWriteFontFace->GetGlyphIndices((const UINT32*)uni, count, glyphs);
284}
285
287 return fDWriteFontFace->GetGlyphCount();
288}
289
291
293 DWRITE_FONT_METRICS metrics;
294 fDWriteFontFace->GetMetrics(&metrics);
295 return metrics.designUnitsPerEm;
296}
297
298class LocalizedStrings_IDWriteLocalizedStrings : public SkTypeface::LocalizedStrings {
299public:
300 /** Takes ownership of the IDWriteLocalizedStrings. */
301 explicit LocalizedStrings_IDWriteLocalizedStrings(IDWriteLocalizedStrings* strings)
302 : fIndex(0), fStrings(strings)
303 { }
304
305 bool next(SkTypeface::LocalizedString* localizedString) override {
306 if (fIndex >= fStrings->GetCount()) {
307 return false;
308 }
309
310 // String
311 UINT32 stringLen;
312 HRBM(fStrings->GetStringLength(fIndex, &stringLen), "Could not get string length.");
313
314 SkSMallocWCHAR wString(static_cast<size_t>(stringLen)+1);
315 HRBM(fStrings->GetString(fIndex, wString.get(), stringLen+1), "Could not get string.");
316
317 HRB(sk_wchar_to_skstring(wString.get(), stringLen, &localizedString->fString));
318
319 // Locale
320 UINT32 localeLen;
321 HRBM(fStrings->GetLocaleNameLength(fIndex, &localeLen), "Could not get locale length.");
322
323 SkSMallocWCHAR wLocale(static_cast<size_t>(localeLen)+1);
324 HRBM(fStrings->GetLocaleName(fIndex, wLocale.get(), localeLen+1), "Could not get locale.");
325
326 HRB(sk_wchar_to_skstring(wLocale.get(), localeLen, &localizedString->fLanguage));
327
328 ++fIndex;
329 return true;
330 }
331
332private:
333 UINT32 fIndex;
334 SkTScopedComPtr<IDWriteLocalizedStrings> fStrings;
335};
336
340 if (!nameIter) {
341 SkTScopedComPtr<IDWriteLocalizedStrings> familyNames;
342 HRNM(fDWriteFontFamily->GetFamilyNames(&familyNames), "Could not obtain family names.");
343 nameIter = sk_make_sp<LocalizedStrings_IDWriteLocalizedStrings>(familyNames.release());
344 }
345 return nameIter.release();
346}
347
349 return fDWriteFontFace2 && fDWriteFontFace2->GetColorPaletteCount() > 0;
350}
351
353 SkFontArguments::VariationPosition::Coordinate coordinates[], int coordinateCount) const
354{
355
356#if defined(NTDDI_WIN10_RS3) && NTDDI_VERSION >= NTDDI_WIN10_RS3
357
358 SkTScopedComPtr<IDWriteFontFace5> fontFace5;
359 if (FAILED(fDWriteFontFace->QueryInterface(&fontFace5))) {
360 return -1;
361 }
362
363 // Return 0 if the font is not variable font.
364 if (!fontFace5->HasVariations()) {
365 return 0;
366 }
367
368 UINT32 fontAxisCount = fontFace5->GetFontAxisValueCount();
369 SkTScopedComPtr<IDWriteFontResource> fontResource;
370 HR_GENERAL(fontFace5->GetFontResource(&fontResource), nullptr, -1);
371 UINT32 variableAxisCount = 0;
372 for (UINT32 i = 0; i < fontAxisCount; ++i) {
373 if (fontResource->GetFontAxisAttributes(i) & DWRITE_FONT_AXIS_ATTRIBUTES_VARIABLE) {
374 ++variableAxisCount;
375 }
376 }
377
378 if (!coordinates || coordinateCount < 0 || (unsigned)coordinateCount < variableAxisCount) {
379 return SkTo<int>(variableAxisCount);
380 }
381
382 AutoSTMalloc<8, DWRITE_FONT_AXIS_VALUE> fontAxisValue(fontAxisCount);
383 HR_GENERAL(fontFace5->GetFontAxisValues(fontAxisValue.get(), fontAxisCount), nullptr, -1);
384 UINT32 coordIndex = 0;
385 for (UINT32 axisIndex = 0; axisIndex < fontAxisCount; ++axisIndex) {
386 if (fontResource->GetFontAxisAttributes(axisIndex) & DWRITE_FONT_AXIS_ATTRIBUTES_VARIABLE) {
387 coordinates[coordIndex].axis = SkEndian_SwapBE32(fontAxisValue[axisIndex].axisTag);
388 coordinates[coordIndex].value = fontAxisValue[axisIndex].value;
389 ++coordIndex;
390 }
391 }
392
393 SkASSERT(coordIndex == variableAxisCount);
394 return SkTo<int>(variableAxisCount);
395
396#else
397 return -1;
398#endif
399}
400
402 SkFontParameters::Variation::Axis parameters[], int parameterCount) const
403{
404
405#if defined(NTDDI_WIN10_RS3) && NTDDI_VERSION >= NTDDI_WIN10_RS3
406
407 SkTScopedComPtr<IDWriteFontFace5> fontFace5;
408 if (FAILED(fDWriteFontFace->QueryInterface(&fontFace5))) {
409 return -1;
410 }
411
412 // Return 0 if the font is not variable font.
413 if (!fontFace5->HasVariations()) {
414 return 0;
415 }
416
417 UINT32 fontAxisCount = fontFace5->GetFontAxisValueCount();
418 SkTScopedComPtr<IDWriteFontResource> fontResource;
419 HR_GENERAL(fontFace5->GetFontResource(&fontResource), nullptr, -1);
420 int variableAxisCount = 0;
421 for (UINT32 i = 0; i < fontAxisCount; ++i) {
422 if (fontResource->GetFontAxisAttributes(i) & DWRITE_FONT_AXIS_ATTRIBUTES_VARIABLE) {
423 variableAxisCount++;
424 }
425 }
426
427 if (!parameters || parameterCount < variableAxisCount) {
428 return variableAxisCount;
429 }
430
431 AutoSTMalloc<8, DWRITE_FONT_AXIS_RANGE> fontAxisRange(fontAxisCount);
432 HR_GENERAL(fontResource->GetFontAxisRanges(fontAxisRange.get(), fontAxisCount), nullptr, -1);
433 AutoSTMalloc<8, DWRITE_FONT_AXIS_VALUE> fontAxisDefaultValue(fontAxisCount);
434 HR_GENERAL(fontResource->GetDefaultFontAxisValues(fontAxisDefaultValue.get(), fontAxisCount),
435 nullptr, -1);
436 UINT32 coordIndex = 0;
437
438 for (UINT32 axisIndex = 0; axisIndex < fontAxisCount; ++axisIndex) {
439 if (fontResource->GetFontAxisAttributes(axisIndex) & DWRITE_FONT_AXIS_ATTRIBUTES_VARIABLE) {
440 parameters[coordIndex].tag = SkEndian_SwapBE32(fontAxisDefaultValue[axisIndex].axisTag);
441 parameters[coordIndex].min = fontAxisRange[axisIndex].minValue;
442 parameters[coordIndex].def = fontAxisDefaultValue[axisIndex].value;
443 parameters[coordIndex].max = fontAxisRange[axisIndex].maxValue;
444 parameters[coordIndex].setHidden(fontResource->GetFontAxisAttributes(axisIndex) &
445 DWRITE_FONT_AXIS_ATTRIBUTES_HIDDEN);
446 ++coordIndex;
447 }
448 }
449
450 return variableAxisCount;
451
452#else
453 return -1;
454#endif
455}
456
458 DWRITE_FONT_FACE_TYPE type = fDWriteFontFace->GetType();
459 if (type != DWRITE_FONT_FACE_TYPE_CFF &&
460 type != DWRITE_FONT_FACE_TYPE_TRUETYPE &&
461 type != DWRITE_FONT_FACE_TYPE_TRUETYPE_COLLECTION)
462 {
463 return 0;
464 }
465
466 int ttcIndex;
467 std::unique_ptr<SkStreamAsset> stream = this->openStream(&ttcIndex);
468 return stream.get() ? SkFontStream::GetTableTags(stream.get(), ttcIndex, tags) : 0;
469}
470
472 size_t length, void* data) const
473{
475 if (!table.fExists) {
476 return 0;
477 }
478
479 if (offset > table.fSize) {
480 return 0;
481 }
482 size_t size = std::min(length, table.fSize - offset);
483 if (data) {
484 memcpy(data, table.fData + offset, size);
485 }
486
487 return size;
488}
489
491 const uint8_t* data;
492 UINT32 size;
493 void* lock;
494 BOOL exists;
495 fDWriteFontFace->TryGetFontTable(SkEndian_SwapBE32(tag),
496 reinterpret_cast<const void **>(&data), &size, &lock, &exists);
497 if (!exists) {
498 return nullptr;
499 }
500 struct Context {
501 Context(void* lock, IDWriteFontFace* face) : fLock(lock), fFontFace(SkRefComPtr(face)) {}
502 ~Context() { fFontFace->ReleaseFontTable(fLock); }
503 void* fLock;
504 SkTScopedComPtr<IDWriteFontFace> fFontFace;
505 };
506 return SkData::MakeWithProc(data, size,
507 [](const void*, void* ctx) { delete (Context*)ctx; },
508 new Context(lock, fDWriteFontFace.get()));
509}
510
512 // Skip if the current face index does not match the ttcIndex
513 if (fDWriteFontFace->GetIndex() != SkTo<UINT32>(args.getCollectionIndex())) {
514 return sk_ref_sp(this);
515 }
516
517#if defined(NTDDI_WIN10_RS3) && NTDDI_VERSION >= NTDDI_WIN10_RS3
518
519 SkTScopedComPtr<IDWriteFontFace5> fontFace5;
520
521 if (SUCCEEDED(fDWriteFontFace->QueryInterface(&fontFace5)) && fontFace5->HasVariations()) {
522 UINT32 fontAxisCount = fontFace5->GetFontAxisValueCount();
523 UINT32 argsCoordCount = args.getVariationDesignPosition().coordinateCount;
524 AutoSTMalloc<8, DWRITE_FONT_AXIS_VALUE> fontAxisValue(fontAxisCount);
525 HRN(fontFace5->GetFontAxisValues(fontAxisValue.get(), fontAxisCount));
526
527 for (UINT32 fontIndex = 0; fontIndex < fontAxisCount; ++fontIndex) {
528 for (UINT32 argsIndex = 0; argsIndex < argsCoordCount; ++argsIndex) {
529 if (SkEndian_SwapBE32(fontAxisValue[fontIndex].axisTag) ==
530 args.getVariationDesignPosition().coordinates[argsIndex].axis) {
531 fontAxisValue[fontIndex].value =
532 args.getVariationDesignPosition().coordinates[argsIndex].value;
533 }
534 }
535 }
536 SkTScopedComPtr<IDWriteFontResource> fontResource;
537 HRN(fontFace5->GetFontResource(&fontResource));
538 SkTScopedComPtr<IDWriteFontFace5> newFontFace5;
539 HRN(fontResource->CreateFontFace(fDWriteFont->GetSimulations(),
540 fontAxisValue.get(),
541 fontAxisCount,
542 &newFontFace5));
543
544 SkTScopedComPtr<IDWriteFontFace> newFontFace;
545 HRN(newFontFace5->QueryInterface(&newFontFace));
547 newFontFace.get(),
548 fDWriteFont.get(),
549 fDWriteFontFamily.get(),
550 fLoaders,
551 args.getPalette());
552 }
553
554#endif
555
556 // If the palette args have changed, a new font will need to be created.
557 if (args.getPalette().index != fRequestedPalette.index ||
558 args.getPalette().overrideCount != fRequestedPalette.overrideCount ||
559 memcmp(args.getPalette().overrides, fRequestedPalette.overrides,
561 {
563 fDWriteFontFace.get(),
564 fDWriteFont.get(),
565 fDWriteFontFamily.get(),
566 fLoaders,
567 args.getPalette());
568 }
569
570 return sk_ref_sp(this);
571}
572
573std::unique_ptr<SkStreamAsset> DWriteFontTypeface::onOpenStream(int* ttcIndex) const {
574 *ttcIndex = fDWriteFontFace->GetIndex();
575
576 UINT32 numFiles = 0;
577 HRNM(fDWriteFontFace->GetFiles(&numFiles, nullptr),
578 "Could not get number of font files.");
579 if (numFiles != 1) {
580 return nullptr;
581 }
582
583 SkTScopedComPtr<IDWriteFontFile> fontFile;
584 HRNM(fDWriteFontFace->GetFiles(&numFiles, &fontFile), "Could not get font files.");
585
586 const void* fontFileKey;
587 UINT32 fontFileKeySize;
588 HRNM(fontFile->GetReferenceKey(&fontFileKey, &fontFileKeySize),
589 "Could not get font file reference key.");
590
591 SkTScopedComPtr<IDWriteFontFileLoader> fontFileLoader;
592 HRNM(fontFile->GetLoader(&fontFileLoader), "Could not get font file loader.");
593
594 SkTScopedComPtr<IDWriteFontFileStream> fontFileStream;
595 HRNM(fontFileLoader->CreateStreamFromKey(fontFileKey, fontFileKeySize,
596 &fontFileStream),
597 "Could not create font file stream.");
598
599 return std::unique_ptr<SkStreamAsset>(new SkDWriteFontFileStream(fontFileStream.get()));
600}
601
602std::unique_ptr<SkScalerContext> DWriteFontTypeface::onCreateScalerContext(
603 const SkScalerContextEffects& effects, const SkDescriptor* desc) const
604{
605 return std::make_unique<SkScalerContext_DW>(
606 sk_ref_sp(const_cast<DWriteFontTypeface*>(this)), effects, desc);
607}
608
613 }
614
615 unsigned flagsWeDontSupport = SkScalerContext::kForceAutohinting_Flag |
618 rec->fFlags &= ~flagsWeDontSupport;
619
620 SkFontHinting h = rec->getHinting();
621 // DirectWrite2 allows for hinting to be turned off. Force everything else to normal.
624 }
625 rec->setHinting(h);
626
627#if defined(SK_FONT_HOST_USE_SYSTEM_SETTINGS)
628 IDWriteFactory* factory = sk_get_dwrite_factory();
629 if (factory != nullptr) {
630 SkTScopedComPtr<IDWriteRenderingParams> defaultRenderingParams;
631 if (SUCCEEDED(factory->CreateRenderingParams(&defaultRenderingParams))) {
632 float gamma = defaultRenderingParams->GetGamma();
633 rec->setDeviceGamma(gamma);
634 rec->setPaintGamma(gamma);
635
636 rec->setContrast(defaultRenderingParams->GetEnhancedContrast());
637 }
638 }
639#endif
640}
641
642///////////////////////////////////////////////////////////////////////////////
643//PDF Support
644
645static void glyph_to_unicode_map(IDWriteFontFace* fontFace, DWRITE_UNICODE_RANGE range,
646 UINT32* remainingGlyphCount, UINT32 numGlyphs,
647 SkUnichar* glyphToUnicode)
648{
649 constexpr const int batchSize = 128;
650 UINT32 codepoints[batchSize];
651 UINT16 glyphs[batchSize];
652 for (UINT32 c = range.first; c <= range.last && *remainingGlyphCount != 0; c += batchSize) {
653 UINT32 numBatchedCodePoints = std::min<UINT32>(range.last - c + 1, batchSize);
654 for (UINT32 i = 0; i < numBatchedCodePoints; ++i) {
655 codepoints[i] = c + i;
656 }
657 HRVM(fontFace->GetGlyphIndices(codepoints, numBatchedCodePoints, glyphs),
658 "Failed to get glyph indexes.");
659 for (UINT32 i = 0; i < numBatchedCodePoints; ++i) {
660 UINT16 glyph = glyphs[i];
661 // Intermittent DW bug on Windows 10. See crbug.com/470146.
662 if (glyph >= numGlyphs) {
663 return;
664 }
665 if (0 < glyph && glyphToUnicode[glyph] == 0) {
666 glyphToUnicode[glyph] = c + i; // Always use lowest-index unichar.
667 --*remainingGlyphCount;
668 }
669 }
670 }
671}
672
673void DWriteFontTypeface::getGlyphToUnicodeMap(SkUnichar* glyphToUnicode) const {
674 IDWriteFontFace* face = fDWriteFontFace.get();
675 UINT32 numGlyphs = face->GetGlyphCount();
676 sk_bzero(glyphToUnicode, sizeof(SkUnichar) * numGlyphs);
677 UINT32 remainingGlyphCount = numGlyphs;
678
679 if (fDWriteFontFace1) {
680 IDWriteFontFace1* face1 = fDWriteFontFace1.get();
681 UINT32 numRanges = 0;
682 HRESULT hr = face1->GetUnicodeRanges(0, nullptr, &numRanges);
683 if (hr != E_NOT_SUFFICIENT_BUFFER && FAILED(hr)) {
684 HRVM(hr, "Failed to get number of ranges.");
685 }
686 std::unique_ptr<DWRITE_UNICODE_RANGE[]> ranges(new DWRITE_UNICODE_RANGE[numRanges]);
687 HRVM(face1->GetUnicodeRanges(numRanges, ranges.get(), &numRanges), "Failed to get ranges.");
688 for (UINT32 i = 0; i < numRanges; ++i) {
689 glyph_to_unicode_map(face1, ranges[i], &remainingGlyphCount, numGlyphs, glyphToUnicode);
690 }
691 } else {
692 glyph_to_unicode_map(face, {0, 0x10FFFF}, &remainingGlyphCount, numGlyphs, glyphToUnicode);
693 }
694}
695
696std::unique_ptr<SkAdvancedTypefaceMetrics> DWriteFontTypeface::onGetAdvancedMetrics() const {
697
698 std::unique_ptr<SkAdvancedTypefaceMetrics> info(nullptr);
699
700 DWRITE_FONT_METRICS dwfm;
701 fDWriteFontFace->GetMetrics(&dwfm);
702
704
705 info->fAscent = SkToS16(dwfm.ascent);
706 info->fDescent = SkToS16(dwfm.descent);
707 info->fCapHeight = SkToS16(dwfm.capHeight);
708
709 {
710 SkTScopedComPtr<IDWriteLocalizedStrings> postScriptNames;
711 BOOL exists = FALSE;
712 if (FAILED(fDWriteFont->GetInformationalStrings(
713 DWRITE_INFORMATIONAL_STRING_POSTSCRIPT_NAME,
714 &postScriptNames,
715 &exists)) ||
716 !exists ||
717 FAILED(sk_get_locale_string(postScriptNames.get(), nullptr, &info->fPostScriptName)))
718 {
719 SkDEBUGF("Unable to get postscript name for typeface %p\n", this);
720 }
721 }
722
723 DWRITE_FONT_FACE_TYPE fontType = fDWriteFontFace->GetType();
724 if (fontType != DWRITE_FONT_FACE_TYPE_TRUETYPE &&
725 fontType != DWRITE_FONT_FACE_TYPE_CFF &&
726 fontType != DWRITE_FONT_FACE_TYPE_TRUETYPE_COLLECTION &&
727 fontType != DWRITE_FONT_FACE_TYPE_OPENTYPE_COLLECTION)
728 {
729 return info;
730 }
731
732 // Simulated fonts aren't really TrueType fonts.
733 if (fDWriteFontFace->GetSimulations() == DWRITE_FONT_SIMULATIONS_NONE) {
735 }
736
741 if (!headTable.fExists || !postTable.fExists || !hheaTable.fExists || !os2Table.fExists) {
742 return info;
743 }
744
745 SkOTUtils::SetAdvancedTypefaceFlags(os2Table->version.v4.fsType, info.get());
746
747 // There are versions of DirectWrite which support named instances for system variation fonts,
748 // but no means to indicate that such a typeface is a variation.
750 if (fvarTable.fExists) {
752 }
753
754 //There exist CJK fonts which set the IsFixedPitch and Monospace bits,
755 //but have full width, latin half-width, and half-width kana.
756 bool fixedWidth = (postTable->isFixedPitch &&
757 (1 == SkEndian_SwapBE16(hheaTable->numberOfHMetrics)));
758 //Monospace
759 if (fixedWidth) {
761 }
762 //Italic
763 if (os2Table->version.v0.fsSelection.field.Italic) {
765 }
766 //Serif
768 SerifStyle serifStyle = os2Table->version.v0.panose.data.textAndDisplay.bSerifStyle;
769 if (SkPanose::FamilyType::TextAndDisplay == os2Table->version.v0.panose.bFamilyType) {
770 if (SerifStyle::Cove == serifStyle ||
771 SerifStyle::ObtuseCove == serifStyle ||
772 SerifStyle::SquareCove == serifStyle ||
773 SerifStyle::ObtuseSquareCove == serifStyle ||
774 SerifStyle::Square == serifStyle ||
775 SerifStyle::Thin == serifStyle ||
776 SerifStyle::Bone == serifStyle ||
777 SerifStyle::Exaggerated == serifStyle ||
778 SerifStyle::Triangle == serifStyle)
779 {
781 }
782 //Script
783 } else if (SkPanose::FamilyType::Script == os2Table->version.v0.panose.bFamilyType) {
785 }
786
787 info->fItalicAngle = SkEndian_SwapBE32(postTable->italicAngle) >> 16;
788
789 info->fBBox = SkIRect::MakeLTRB((int32_t)SkEndian_SwapBE16((uint16_t)headTable->xMin),
790 (int32_t)SkEndian_SwapBE16((uint16_t)headTable->yMax),
791 (int32_t)SkEndian_SwapBE16((uint16_t)headTable->xMax),
792 (int32_t)SkEndian_SwapBE16((uint16_t)headTable->yMin));
793 return info;
794}
795
796class StreamFontFileLoader : public IDWriteFontFileLoader {
797public:
798 // IUnknown methods
799 SK_STDMETHODIMP QueryInterface(REFIID iid, void** ppvObject) override;
800 SK_STDMETHODIMP_(ULONG) AddRef() override;
801 SK_STDMETHODIMP_(ULONG) Release() override;
802
803 // IDWriteFontFileLoader methods
804 SK_STDMETHODIMP CreateStreamFromKey(
805 void const* fontFileReferenceKey,
806 UINT32 fontFileReferenceKeySize,
807 IDWriteFontFileStream** fontFileStream) override;
808
809 // Takes ownership of stream.
810 static HRESULT Create(std::unique_ptr<SkStreamAsset> stream,
811 StreamFontFileLoader** streamFontFileLoader) {
812 *streamFontFileLoader = new StreamFontFileLoader(std::move(stream));
813 if (nullptr == *streamFontFileLoader) {
814 return E_OUTOFMEMORY;
815 }
816 return S_OK;
817 }
818
819private:
820 StreamFontFileLoader(std::unique_ptr<SkStreamAsset> stream)
821 : fStream(std::move(stream)), fRefCount(1)
822 {}
823 virtual ~StreamFontFileLoader() { }
824
825 std::unique_ptr<SkStreamAsset> fStream;
826 ULONG fRefCount;
827};
828
829SK_STDMETHODIMP StreamFontFileLoader::QueryInterface(REFIID iid, void** ppvObject) {
830 if (iid == IID_IUnknown || iid == __uuidof(IDWriteFontFileLoader)) {
831 *ppvObject = this;
832 AddRef();
833 return S_OK;
834 } else {
835 *ppvObject = nullptr;
836 return E_NOINTERFACE;
837 }
838}
839
840SK_STDMETHODIMP_(ULONG) StreamFontFileLoader::AddRef() {
841 return InterlockedIncrement(&fRefCount);
842}
843
844SK_STDMETHODIMP_(ULONG) StreamFontFileLoader::Release() {
845 ULONG newCount = InterlockedDecrement(&fRefCount);
846 if (0 == newCount) {
847 delete this;
848 }
849 return newCount;
850}
851
852SK_STDMETHODIMP StreamFontFileLoader::CreateStreamFromKey(
853 void const* fontFileReferenceKey,
854 UINT32 fontFileReferenceKeySize,
855 IDWriteFontFileStream** fontFileStream)
856{
857 SkTScopedComPtr<SkDWriteFontFileStreamWrapper> stream;
858 HR(SkDWriteFontFileStreamWrapper::Create(fStream->duplicate().release(), &stream));
859 *fontFileStream = stream.release();
860 return S_OK;
861}
862
863class StreamFontFileEnumerator : public IDWriteFontFileEnumerator {
864public:
865 // IUnknown methods
866 SK_STDMETHODIMP QueryInterface(REFIID iid, void** ppvObject) override;
867 SK_STDMETHODIMP_(ULONG) AddRef() override;
868 SK_STDMETHODIMP_(ULONG) Release() override;
869
870 // IDWriteFontFileEnumerator methods
871 SK_STDMETHODIMP MoveNext(BOOL* hasCurrentFile) override;
872 SK_STDMETHODIMP GetCurrentFontFile(IDWriteFontFile** fontFile) override;
873
874 static HRESULT Create(IDWriteFactory* factory, IDWriteFontFileLoader* fontFileLoader,
875 StreamFontFileEnumerator** streamFontFileEnumerator) {
876 *streamFontFileEnumerator = new StreamFontFileEnumerator(factory, fontFileLoader);
877 if (nullptr == *streamFontFileEnumerator) {
878 return E_OUTOFMEMORY;
879 }
880 return S_OK;
881 }
882private:
883 StreamFontFileEnumerator(IDWriteFactory* factory, IDWriteFontFileLoader* fontFileLoader);
884 virtual ~StreamFontFileEnumerator() { }
885
886 ULONG fRefCount;
887
888 SkTScopedComPtr<IDWriteFactory> fFactory;
889 SkTScopedComPtr<IDWriteFontFile> fCurrentFile;
890 SkTScopedComPtr<IDWriteFontFileLoader> fFontFileLoader;
891 bool fHasNext;
892};
893
894StreamFontFileEnumerator::StreamFontFileEnumerator(IDWriteFactory* factory,
895 IDWriteFontFileLoader* fontFileLoader)
896 : fRefCount(1)
897 , fFactory(SkRefComPtr(factory))
898 , fCurrentFile()
899 , fFontFileLoader(SkRefComPtr(fontFileLoader))
900 , fHasNext(true)
901{ }
902
903SK_STDMETHODIMP StreamFontFileEnumerator::QueryInterface(REFIID iid, void** ppvObject) {
904 if (iid == IID_IUnknown || iid == __uuidof(IDWriteFontFileEnumerator)) {
905 *ppvObject = this;
906 AddRef();
907 return S_OK;
908 } else {
909 *ppvObject = nullptr;
910 return E_NOINTERFACE;
911 }
912}
913
914SK_STDMETHODIMP_(ULONG) StreamFontFileEnumerator::AddRef() {
915 return InterlockedIncrement(&fRefCount);
916}
917
918SK_STDMETHODIMP_(ULONG) StreamFontFileEnumerator::Release() {
919 ULONG newCount = InterlockedDecrement(&fRefCount);
920 if (0 == newCount) {
921 delete this;
922 }
923 return newCount;
924}
925
926SK_STDMETHODIMP StreamFontFileEnumerator::MoveNext(BOOL* hasCurrentFile) {
927 *hasCurrentFile = FALSE;
928
929 if (!fHasNext) {
930 return S_OK;
931 }
932 fHasNext = false;
933
934 UINT32 fontFileReferenceKey = 0;
935 HR(fFactory->CreateCustomFontFileReference(
936 &fontFileReferenceKey, //cannot be nullptr
937 sizeof(fontFileReferenceKey), //even if this is 0
938 fFontFileLoader.get(),
939 &fCurrentFile));
940
941 *hasCurrentFile = TRUE;
942 return S_OK;
943}
944
945SK_STDMETHODIMP StreamFontFileEnumerator::GetCurrentFontFile(IDWriteFontFile** fontFile) {
946 if (fCurrentFile.get() == nullptr) {
947 *fontFile = nullptr;
948 return E_FAIL;
949 }
950
951 *fontFile = SkRefComPtr(fCurrentFile.get());
952 return S_OK;
953}
954
955class StreamFontCollectionLoader : public IDWriteFontCollectionLoader {
956public:
957 // IUnknown methods
958 SK_STDMETHODIMP QueryInterface(REFIID iid, void** ppvObject) override;
959 SK_STDMETHODIMP_(ULONG) AddRef() override;
960 SK_STDMETHODIMP_(ULONG) Release() override;
961
962 // IDWriteFontCollectionLoader methods
963 SK_STDMETHODIMP CreateEnumeratorFromKey(
964 IDWriteFactory* factory,
965 void const* collectionKey,
966 UINT32 collectionKeySize,
967 IDWriteFontFileEnumerator** fontFileEnumerator) override;
968
969 static HRESULT Create(IDWriteFontFileLoader* fontFileLoader,
970 StreamFontCollectionLoader** streamFontCollectionLoader) {
971 *streamFontCollectionLoader = new StreamFontCollectionLoader(fontFileLoader);
972 if (nullptr == *streamFontCollectionLoader) {
973 return E_OUTOFMEMORY;
974 }
975 return S_OK;
976 }
977private:
978 StreamFontCollectionLoader(IDWriteFontFileLoader* fontFileLoader)
979 : fRefCount(1)
980 , fFontFileLoader(SkRefComPtr(fontFileLoader))
981 { }
982 virtual ~StreamFontCollectionLoader() { }
983
984 ULONG fRefCount;
985 SkTScopedComPtr<IDWriteFontFileLoader> fFontFileLoader;
986};
987
988SK_STDMETHODIMP StreamFontCollectionLoader::QueryInterface(REFIID iid, void** ppvObject) {
989 if (iid == IID_IUnknown || iid == __uuidof(IDWriteFontCollectionLoader)) {
990 *ppvObject = this;
991 AddRef();
992 return S_OK;
993 } else {
994 *ppvObject = nullptr;
995 return E_NOINTERFACE;
996 }
997}
998
999SK_STDMETHODIMP_(ULONG) StreamFontCollectionLoader::AddRef() {
1000 return InterlockedIncrement(&fRefCount);
1001}
1002
1003SK_STDMETHODIMP_(ULONG) StreamFontCollectionLoader::Release() {
1004 ULONG newCount = InterlockedDecrement(&fRefCount);
1005 if (0 == newCount) {
1006 delete this;
1007 }
1008 return newCount;
1009}
1010
1011template <typename T> class SkAutoIDWriteUnregister {
1012public:
1013 SkAutoIDWriteUnregister(IDWriteFactory* factory, T* unregister)
1014 : fFactory(factory), fUnregister(unregister)
1015 { }
1016 SkAutoIDWriteUnregister(const SkAutoIDWriteUnregister&) = delete;
1017 SkAutoIDWriteUnregister& operator=(const SkAutoIDWriteUnregister&) = delete;
1018 SkAutoIDWriteUnregister(SkAutoIDWriteUnregister&&) = delete;
1019 SkAutoIDWriteUnregister& operator=(SkAutoIDWriteUnregister&&) = delete;
1020
1021 ~SkAutoIDWriteUnregister() {
1022 if (fUnregister) {
1023 unregister(fFactory, fUnregister);
1024 }
1025 }
1026
1027 T* detatch() {
1028 T* old = fUnregister;
1029 fUnregister = nullptr;
1030 return old;
1031 }
1032
1033private:
1034 HRESULT unregister(IDWriteFactory* factory, IDWriteFontFileLoader* unregister) {
1035 return factory->UnregisterFontFileLoader(unregister);
1036 }
1037
1038 HRESULT unregister(IDWriteFactory* factory, IDWriteFontCollectionLoader* unregister) {
1039 return factory->UnregisterFontCollectionLoader(unregister);
1040 }
1041
1042 IDWriteFactory* fFactory;
1043 T* fUnregister;
1044};
1045
1046SK_STDMETHODIMP StreamFontCollectionLoader::CreateEnumeratorFromKey(
1047 IDWriteFactory* factory,
1048 void const* collectionKey,
1049 UINT32 collectionKeySize,
1050 IDWriteFontFileEnumerator** fontFileEnumerator)
1051{
1052 SkTScopedComPtr<StreamFontFileEnumerator> enumerator;
1053 HR(StreamFontFileEnumerator::Create(factory, fFontFileLoader.get(), &enumerator));
1054 *fontFileEnumerator = enumerator.release();
1055 return S_OK;
1056}
1057
1058static HRESULT apply_fontargument_variation(SkTScopedComPtr<IDWriteFontFace>& fontFace,
1059 const SkFontArguments& args)
1060{
1061#if defined(NTDDI_WIN10_RS3) && NTDDI_VERSION >= NTDDI_WIN10_RS3
1062
1063 SkTScopedComPtr<IDWriteFontFace5> fontFace5;
1064 if (FAILED(fontFace->QueryInterface(&fontFace5)) || !fontFace5->HasVariations()) {
1065 return S_OK;
1066 }
1067
1068 UINT32 fontAxisCount = fontFace5->GetFontAxisValueCount();
1069 UINT32 argsCoordCount = args.getVariationDesignPosition().coordinateCount;
1070 AutoSTMalloc<8, DWRITE_FONT_AXIS_VALUE> variation(fontAxisCount);
1071 SkTScopedComPtr<IDWriteFontResource> fontResource;
1072 HR(fontFace5->GetFontResource(&fontResource));
1073 HR(fontResource->GetDefaultFontAxisValues(variation, fontAxisCount));
1074
1075 for (UINT32 fontAxisIndex = 0; fontAxisIndex < fontAxisCount; ++fontAxisIndex) {
1076 DWRITE_FONT_AXIS_VALUE& fontCoordinate = variation[fontAxisIndex];
1077
1078 for (UINT32 argsCoordIndex = argsCoordCount; argsCoordIndex --> 0;) {
1080 args.getVariationDesignPosition().coordinates[argsCoordIndex];
1081 if (SkEndian_SwapBE32(fontCoordinate.axisTag) == argsCoordinate.axis) {
1082 fontCoordinate.value = argsCoordinate.value;
1083 break;
1084 }
1085 }
1086 }
1087
1088 SkTScopedComPtr<IDWriteFontFace5> fontFace5_Out;
1089 HR(fontResource->CreateFontFace(DWRITE_FONT_SIMULATIONS_NONE,
1090 variation.get(), fontAxisCount,
1091 &fontFace5_Out));
1092 fontFace.reset();
1093 HR(fontFace5_Out->QueryInterface(&fontFace));
1094#endif
1095 return S_OK;
1096}
1097
1098sk_sp<SkTypeface> DWriteFontTypeface::MakeFromStream(std::unique_ptr<SkStreamAsset> stream,
1099 const SkFontArguments& args) {
1100 // TODO: do we need to use some user provided factory?
1101 IDWriteFactory* factory = sk_get_dwrite_factory();
1102 if (nullptr == factory) {
1103 return nullptr;
1104 }
1105
1106 SkTScopedComPtr<StreamFontFileLoader> fontFileLoader;
1107 HRN(StreamFontFileLoader::Create(std::move(stream), &fontFileLoader));
1108 HRN(factory->RegisterFontFileLoader(fontFileLoader.get()));
1109 SkAutoIDWriteUnregister<StreamFontFileLoader> autoUnregisterFontFileLoader(
1110 factory, fontFileLoader.get());
1111
1112 SkTScopedComPtr<StreamFontCollectionLoader> fontCollectionLoader;
1113 HRN(StreamFontCollectionLoader::Create(fontFileLoader.get(), &fontCollectionLoader));
1114 HRN(factory->RegisterFontCollectionLoader(fontCollectionLoader.get()));
1115 SkAutoIDWriteUnregister<StreamFontCollectionLoader> autoUnregisterFontCollectionLoader(
1116 factory, fontCollectionLoader.get());
1117
1118 SkTScopedComPtr<IDWriteFontCollection> fontCollection;
1119 HRN(factory->CreateCustomFontCollection(fontCollectionLoader.get(), nullptr, 0,
1120 &fontCollection));
1121
1122 // Find the first non-simulated font which has the given ttc index.
1123 UINT32 familyCount = fontCollection->GetFontFamilyCount();
1124 for (UINT32 familyIndex = 0; familyIndex < familyCount; ++familyIndex) {
1125 SkTScopedComPtr<IDWriteFontFamily> fontFamily;
1126 HRN(fontCollection->GetFontFamily(familyIndex, &fontFamily));
1127
1128 UINT32 fontCount = fontFamily->GetFontCount();
1129 for (UINT32 fontIndex = 0; fontIndex < fontCount; ++fontIndex) {
1130 SkTScopedComPtr<IDWriteFont> font;
1131 HRN(fontFamily->GetFont(fontIndex, &font));
1132
1133 // Skip if the current font is simulated
1134 if (font->GetSimulations() != DWRITE_FONT_SIMULATIONS_NONE) {
1135 continue;
1136 }
1137 SkTScopedComPtr<IDWriteFontFace> fontFace;
1138 HRN(font->CreateFontFace(&fontFace));
1139 int faceIndex = fontFace->GetIndex();
1140 int ttcIndex = args.getCollectionIndex();
1141
1142 // Skip if the current face index does not match the ttcIndex
1143 if (faceIndex != ttcIndex) {
1144 continue;
1145 }
1146
1147 apply_fontargument_variation(fontFace, args);
1148
1150 factory, fontFace.get(), font.get(), fontFamily.get(),
1151 sk_make_sp<DWriteFontTypeface::Loaders>(
1152 factory,
1153 autoUnregisterFontFileLoader.detatch(),
1154 autoUnregisterFontCollectionLoader.detatch()),
1155 args.getPalette());
1156 }
1157 }
1158
1159 return nullptr;
1160}
1161
1162#endif//defined(SK_BUILD_FOR_WIN)
static void info(const char *fmt,...) SK_PRINTF_LIKE(1
Definition DM.cpp:213
uint16_t glyphs[5]
int count
static float next(float f)
static sk_sp< Effect > Create()
#define SkASSERT_RELEASE(cond)
Definition SkAssert.h:100
#define SkASSERT(cond)
Definition SkAssert.h:116
uint32_t SkColor
Definition SkColor.h:37
static constexpr SkColor SkColorSetARGB(U8CPU a, U8CPU r, U8CPU g, U8CPU b)
Definition SkColor.h:49
HRESULT sk_wchar_to_skstring(WCHAR *name, int nameLen, SkString *skname)
HRESULT sk_get_locale_string(IDWriteLocalizedStrings *names, const WCHAR *preferedLocale, SkString *skname)
IDWriteFactory * sk_get_dwrite_factory()
#define SkDEBUGF(...)
Definition SkDebug.h:24
#define SkEndian_SwapBE32(n)
Definition SkEndian.h:136
#define SkEndian_SwapBE16(n)
Definition SkEndian.h:135
#define sk_float_round2int(x)
SkFontHinting
Definition SkFontTypes.h:18
@ kNormal
glyph outlines modified to improve constrast
@ kNone
glyph outlines unchanged
static void sk_bzero(void *buffer, size_t size)
Definition SkMalloc.h:105
static void * sk_careful_memcpy(void *dst, const void *src, size_t len)
Definition SkMalloc.h:125
#define SK_STDMETHODIMP_(type)
Definition SkObjBase.h:23
#define SK_STDMETHODIMP
Definition SkObjBase.h:22
sk_sp< T > sk_ref_sp(T *obj)
Definition SkRefCnt.h:381
static constexpr bool SkToBool(const T &x)
Definition SkTo.h:35
constexpr int16_t SkToS16(S x)
Definition SkTo.h:23
uint32_t SkFontTableTag
Definition SkTypeface.h:41
int32_t SkUnichar
Definition SkTypes.h:175
uint16_t SkGlyphID
Definition SkTypes.h:179
SI F table(const skcms_Curve *curve, F v)
int onGetVariationDesignParameters(SkFontParameters::Variation::Axis parameters[], int parameterCount) const override
int onGetUPEM() const override
SkTScopedComPtr< IDWriteFontFace2 > fDWriteFontFace2
std::unique_ptr< SkScalerContext > onCreateScalerContext(const SkScalerContextEffects &, const SkDescriptor *) const override
static sk_sp< SkTypeface > SK_SPI MakeFromStream(std::unique_ptr< SkStreamAsset >, const SkFontArguments &)
SkTypeface::LocalizedStrings * onCreateFamilyNameIterator() const override
SkTScopedComPtr< IDWriteFactory2 > fFactory2
SkTScopedComPtr< IDWriteFactory > fFactory
SkFontArguments::Palette fRequestedPalette
void onFilterRec(SkScalerContextRec *) const override
void getGlyphToUnicodeMap(SkUnichar *glyphToUnicode) const override
size_t onGetTableData(SkFontTableTag, size_t offset, size_t length, void *data) const override
static SkFontStyle GetStyle(IDWriteFont *font, IDWriteFontFace *fontFace)
std::unique_ptr< SkAdvancedTypefaceMetrics > onGetAdvancedMetrics() const override
void onCharsToGlyphs(const SkUnichar *chars, int count, SkGlyphID glyphs[]) const override
std::unique_ptr< SkColor[]> fPalette
~DWriteFontTypeface() override
IDWriteFontFace7 * fDWriteFontFace7
SkTScopedComPtr< IDWriteFontFamily > fDWriteFontFamily
SkTScopedComPtr< IDWriteFontFace1 > fDWriteFontFace1
std::unique_ptr< SkStreamAsset > onOpenStream(int *ttcIndex) const override
int onGetTableTags(SkFontTableTag tags[]) const override
std::unique_ptr< DWRITE_COLOR_F[]> fDWPalette
int onCountGlyphs() const override
bool onGetPostScriptName(SkString *) const override
void getPostScriptGlyphNames(SkString *) const override
bool onGlyphMaskNeedsCurrentColor() const override
sk_sp< SkData > onCopyTableData(SkFontTableTag) const override
void onGetFamilyName(SkString *familyName) const override
static constexpr SkTypeface::FactoryId FactoryId
SkTScopedComPtr< IDWriteFontFace > fDWriteFontFace
SkTScopedComPtr< IDWriteFont > fDWriteFont
int onGetVariationDesignPosition(SkFontArguments::VariationPosition::Coordinate coordinates[], int coordinateCount) const override
static sk_sp< DWriteFontTypeface > Make(IDWriteFactory *factory, IDWriteFontFace *fontFace, IDWriteFont *font, IDWriteFontFamily *fontFamily, sk_sp< Loaders > loaders, const SkFontArguments::Palette &palette)
sk_sp< SkTypeface > onMakeClone(const SkFontArguments &) const override
void onGetFontDescriptor(SkFontDescriptor *, bool *) const override
static HRESULT Create(SkStreamAsset *stream, SkDWriteFontFileStreamWrapper **streamFontFileStream)
static sk_sp< SkData > MakeWithProc(const void *ptr, size_t length, ReleaseProc proc, void *ctx)
Definition SkData.cpp:128
static SkFontStyle::Width SkFontStyleWidthForWidthAxisValue(SkScalar width)
void setPaletteIndex(int paletteIndex)
static int GetTableTags(SkStream *, int ttcIndex, SkFontTableTag tags[])
static sk_sp< LocalizedStrings_NameTable > MakeForFamilyNames(const SkTypeface &typeface)
const char * c_str() const
Definition SkString.h:133
SkFontStyle fontStyle() const
Definition SkTypeface.h:55
void serialize(SkWStream *, SerializeBehavior=SerializeBehavior::kIncludeDataIfLocal) const
std::unique_ptr< SkStreamAsset > openStream(int *ttcIndex) const
T * release()
Definition SkRefCnt.h:324
float SkScalar
Definition extension.cpp:12
static bool b
struct MyStruct a[10]
G_BEGIN_DECLS G_MODULE_EXPORT FlValue * args
size_t length
return FALSE
DEF_SWITCHES_START aot vmservice shared library Name of the *so containing AOT compiled Dart assets for launching the service isolate vm snapshot data
Definition switches.h:41
it will be possible to load the file into Perfetto s trace viewer disable asset Prevents usage of any non test fonts unless they were explicitly Loaded via prefetched default font Indicates whether the embedding started a prefetch of the default font manager before creating the engine run In non interactive keep the shell running after the Dart script has completed enable serial On low power devices with low core running concurrent GC tasks on threads can cause them to contend with the UI thread which could potentially lead to jank This option turns off all concurrent GC activities domain network JSON encoded network policy per domain This overrides the DisallowInsecureConnections switch Embedder can specify whether to allow or disallow insecure connections at a domain level old gen heap size
Definition switches.h:259
font
Font Metadata and Metrics.
const myers::Point & get(const myers::Segment &)
Definition ref_ptr.h:256
SkScalar h
#define T
int32_t width
Point offset
SkTScopedComPtr< IDWriteFactory > fFactory
SkTScopedComPtr< IDWriteFontFileLoader > fDWriteFontFileLoader
SkTScopedComPtr< IDWriteFontCollectionLoader > fDWriteFontCollectionLoader
@ kVariable_FontFlag
May be true for Type1, CFF, or TrueType fonts.
const Override * overrides
static constexpr SkIRect MakeLTRB(int32_t l, int32_t t, int32_t r, int32_t b)
Definition SkRect.h:91
@ kA8_Format
8bits per pixel mask (e.g. antialiasing)
Definition SkMask.h:28
static void SetAdvancedTypefaceFlags(SkOTTableOS2_V4::Type fsType, SkAdvancedTypefaceMetrics *info)
static SkRGBA4f FromColor(SkColor color)
void setPaintGamma(SkScalar pg)
void setDeviceGamma(SkScalar dg)
SkMask::Format fMaskFormat
void setContrast(SkScalar c)
SkFontHinting getHinting() const
void setHinting(SkFontHinting)
int BOOL
#define SUCCEEDED(hr)
DWORD ULONG
#define FAILED(hr)