/* * Copyright 2014 Google Inc. * * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file.
*/ #include"src/utils/win/SkDWriteNTDDI_VERSION.h"
// Korean fonts Gulim, Dotum, Batang, Gungsuh have bitmap strikes that get // artifically emboldened by Windows without antialiasing. Korean users prefer // these over the synthetic boldening performed by Skia. So let's make an // exception for fonts with bitmap strikes and allow passing through Windows // simulations for those, until Skia provides more control over simulations in // font matching, see https://crbug.com/1258378 bool HasBitmapStrikes(const SkTScopedComPtr<IDWriteFont>& font) {
SkTScopedComPtr<IDWriteFontFace> fontFace;
HRB(font->CreateFontFace(&fontFace));
// Iterate calls to GetFirstMatchingFont incrementally removing bold or italic // styling that can trigger the simulations. Implementing it this way gets us a // IDWriteFont that can be used as before and has the correct information on its // own style. Stripping simulations from IDWriteFontFace is possible via // IDWriteFontList1, IDWriteFontFaceReference and CreateFontFace, but this way // we won't have a matching IDWriteFont which is still used in get_style().
HRESULT FirstMatchingFontWithoutSimulations(const SkTScopedComPtr<IDWriteFontFamily>& family,
DWriteStyle dwStyle,
SkTScopedComPtr<IDWriteFont>& font) { bool noSimulations = false; while (!noSimulations) {
SkTScopedComPtr<IDWriteFont> searchFont;
HR(family->GetFirstMatchingFont(
dwStyle.fWeight, dwStyle.fWidth, dwStyle.fSlant, &searchFont));
DWRITE_FONT_SIMULATIONS simulations = searchFont->GetSimulations(); // If we still get simulations even though we're not asking for bold or // italic, we can't help it and exit the loop.
// IDWriteFontFace5 introduced both Equals and HasVariations
SkTScopedComPtr<IDWriteFontFace5> cshFontFace5;
SkTScopedComPtr<IDWriteFontFace5> ctxFontFace5;
cshFace->fDWriteFontFace->QueryInterface(&cshFontFace5);
ctxFace->fDWriteFontFace->QueryInterface(&ctxFontFace5); if (cshFontFace5 && ctxFontFace5) { return cshFontFace5->Equals(ctxFontFace5.get());
}
bool same;
//Check to see if the two fonts are identical.
HRB(are_same(cshFace->fDWriteFont.get(), ctxFace->fDWriteFont, same)); if (same) { returntrue;
}
HRB(are_same(cshFace->fDWriteFontFace.get(), ctxFace->fDWriteFontFace, same)); if (same) { returntrue;
}
//Check if the two fonts share the same loader and have the same key.
UINT32 cshNumFiles;
UINT32 ctxNumFiles;
HRB(cshFace->fDWriteFontFace->GetFiles(&cshNumFiles, nullptr));
HRB(ctxFace->fDWriteFontFace->GetFiles(&ctxNumFiles, nullptr)); if (cshNumFiles != ctxNumFiles) { returnfalse;
}
//TODO: better means than comparing name strings? //NOTE: .ttc and fake bold/italic will end up here.
SkTScopedComPtr<IDWriteLocalizedStrings> cshFamilyNames;
SkTScopedComPtr<IDWriteLocalizedStrings> cshFaceNames;
HRB(cshFace->fDWriteFontFamily->GetFamilyNames(&cshFamilyNames));
HRB(cshFace->fDWriteFont->GetFaceNames(&cshFaceNames));
UINT32 cshFamilyNameLength;
UINT32 cshFaceNameLength;
HRB(cshFamilyNames->GetStringLength(0, &cshFamilyNameLength));
HRB(cshFaceNames->GetStringLength(0, &cshFaceNameLength));
UINT32 index; BOOL exists;
HRNM(fFontCollection->FindFamilyName(dwFamilyName.get(), &index, &exists), "Failed while finding family by name."); if (!exists) { return nullptr;
}
// IDWriteTextRenderer methods
SK_STDMETHODIMP DrawGlyphRun( void* clientDrawingContext, FLOAT baselineOriginX, FLOAT baselineOriginY,
DWRITE_MEASURING_MODE measuringMode,
DWRITE_GLYPH_RUN const* glyphRun,
DWRITE_GLYPH_RUN_DESCRIPTION const* glyphRunDescription,
IUnknown* clientDrawingEffect) override
{ if (!glyphRun->fontFace) {
HRM(E_INVALIDARG, "Glyph run without font face.");
}
SkTScopedComPtr<IDWriteFont> font;
HRM(fOuter->fFontCollection->GetFontFromFontFace(glyphRun->fontFace, &font), "Could not get font from font face.");
// It is possible that the font passed does not actually have the requested character, // due to no font being found and getting the fallback font. // Check that the font actually contains the requested character. BOOL exists;
HRM(font->HasCharacter(fCharacter, &exists), "Could not find character.");
if (exists) {
SkTScopedComPtr<IDWriteFontFamily> fontFamily;
HRM(font->GetFontFamily(&fontFamily), "Could not get family.");
fResolvedTypeface = fOuter->makeTypefaceFromDWriteFont(glyphRun->fontFace,
font.get(),
fontFamily.get());
fHasSimulations = (font->GetSimulations() != DWRITE_FONT_SIMULATIONS_NONE) &&
!HasBitmapStrikes(font);
}
SK_STDMETHODIMP_(DWRITE_READING_DIRECTION) GetParagraphReadingDirection() override { // TODO: this is also interesting. return DWRITE_READING_DIRECTION_LEFT_TO_RIGHT;
}
SkTScopedComPtr<IDWriteFontFace> fontFace;
HRNM(font->CreateFontFace(&fontFace), "Could not get font face from font.");
SkTScopedComPtr<IDWriteFontFamily> fontFamily;
HRNM(font->GetFontFamily(&fontFamily), "Could not get family from font."); return this->makeTypefaceFromDWriteFont(fontFace.get(), font.get(), fontFamily.get());
}
bool noSimulations = false;
sk_sp<SkTypeface> returnTypeface(nullptr); while (!noSimulations) {
SkTScopedComPtr<IDWriteTextFormat> fallbackFormat;
HRNM(fFactory->CreateTextFormat(dwFamilyName ? dwFamilyName : L"",
fFontCollection.get(),
dwStyle.fWeight,
dwStyle.fSlant,
dwStyle.fWidth,
72.0f,
dwBcp47,
&fallbackFormat), "Could not create text format.");
// No matter how the font collection is set on this IDWriteTextLayout, it is not possible to // disable use of the system font collection in fallback.
SkTScopedComPtr<IDWriteTextLayout> fallbackLayout;
HRNM(fFactory->CreateTextLayout(
str, strLen, fallbackFormat.get(), 200.0f, 200.0f, &fallbackLayout), "Could not create text layout.");
SkTScopedComPtr<FontFallbackRenderer> fontFallbackRenderer( new FontFallbackRenderer(this, character));
HRNM(fallbackLayout->SetFontCollection(fFontCollection.get(), {0, strLen}), "Could not set layout font collection.");
HRNM(fallbackLayout->Draw(nullptr, fontFallbackRenderer.get(), 50.0f, 50.0f), "Could not draw layout with renderer.");
if (!fontFamily) { if (fFontFallback) { return this->fallback(nullptr, dwStyle, fLocaleName.get(), 32);
} // SPI_GETNONCLIENTMETRICS lfMessageFont can fail in Win8. (DisallowWin32kSystemCalls) // layoutFallback causes DCHECK in Chromium. (Uses system font collection.)
HRNM(this->getByFamilyName(fDefaultFamilyName, &fontFamily), "Could not create DWrite font family from LOGFONT.");
}
if (!fontFamily) { // Could not obtain the default font.
HRNM(fFontCollection->GetFontFamily(0, &fontFamily), "Could not get default-default font family.");
}
SkTScopedComPtr<IDWriteFont> font;
HRNM(FirstMatchingFontWithoutSimulations(fontFamily, dwStyle, font), "No font found from family.");
SkTScopedComPtr<IDWriteFontFace> fontFace;
HRNM(font->CreateFontFace(&fontFace), "Could not create font face.");
void SkFontStyleSet_DirectWrite::getStyle(int index, SkFontStyle* fs, SkString* styleName) {
SkTScopedComPtr<IDWriteFont> font;
HRVM(fFontFamily->GetFont(index, &font), "Could not get font.");
if (fs) {
SkTScopedComPtr<IDWriteFontFace> face;
HRVM(font->CreateFontFace(&face), "Could not get face.");
*fs = DWriteFontTypeface::GetStyle(font.get(), face.get());
}
if (styleName) {
SkTScopedComPtr<IDWriteLocalizedStrings> faceNames; if (SUCCEEDED(font->GetFaceNames(&faceNames))) {
sk_get_locale_string(faceNames.get(), fFontMgr->fLocaleName.get(), styleName);
}
}
}
SkTScopedComPtr<IDWriteFontCollection> systemFontCollection; if (nullptr == collection) {
HRNM(factory->GetSystemFontCollection(&systemFontCollection, FALSE), "Could not get system font collection.");
collection = systemFontCollection.get();
}
// It is possible to have been provided a font fallback when factory2 is not available.
SkTScopedComPtr<IDWriteFontFallback> systemFontFallback; if (nullptr == fallback) {
SkTScopedComPtr<IDWriteFactory2> factory2; if (!SUCCEEDED(factory->QueryInterface(&factory2))) { // IUnknown::QueryInterface states that if it fails, punk will be set to nullptr. // http://blogs.msdn.com/b/oldnewthing/archive/2004/03/26/96777.aspx
SkASSERT_RELEASE(nullptr == factory2.get());
} else {
HRNM(factory2->GetSystemFontFallback(&systemFontFallback), "Could not get system fallback.");
fallback = systemFontFallback.get();
}
}
// Dynamically load GetUserDefaultLocaleName function, as it is not available on XP.
SkGetUserDefaultLocaleNameProc getUserDefaultLocaleNameProc = nullptr;
HRESULT hr = SkGetGetUserDefaultLocaleNameProc(&getUserDefaultLocaleNameProc); if (nullptr == getUserDefaultLocaleNameProc) {
SK_TRACEHR(hr, "Could not get GetUserDefaultLocaleName.");
} else { int size = getUserDefaultLocaleNameProc(localeNameStorage, LOCALE_NAME_MAX_LENGTH); if (size) {
localeName = localeNameStorage;
localeNameLen = size;
}
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.