void QWindowsFontEngineDirectWrite::initFontInfo(const QFontDef &request, int dpi, IDWriteFont *font) { fontDef = request; IDWriteFontFamily *fontFamily = NULL; HRESULT hr = font->GetFontFamily(&fontFamily); IDWriteLocalizedStrings *familyNames = NULL; if (SUCCEEDED(hr)) hr = fontFamily->GetFamilyNames(&familyNames); UINT32 index = 0; if (SUCCEEDED(hr)) { BOOL exists = false; wchar_t localeName[LOCALE_NAME_MAX_LENGTH]; int defaultLocaleSuccess = GetUserDefaultLocaleName(localeName, LOCALE_NAME_MAX_LENGTH); if (defaultLocaleSuccess) hr = familyNames->FindLocaleName(localeName, &index, &exists); if (SUCCEEDED(hr) && !exists) hr = familyNames->FindLocaleName(L"en-us", &index, &exists); if (!exists) index = 0; } // Get the family name. if (SUCCEEDED(hr)) { UINT32 length = 0; hr = familyNames->GetStringLength(index, &length); if (SUCCEEDED(hr)) { QVarLengthArray<wchar_t, 128> name(length+1); hr = familyNames->GetString(index, name.data(), name.size()); if (SUCCEEDED(hr)) fontDef.family = QString::fromWCharArray(name.constData()); } } if (familyNames != NULL) familyNames->Release(); if (fontFamily) fontFamily->Release(); if (FAILED(hr)) qErrnoWarning(hr, "initFontInfo: Failed to get family name"); if (fontDef.pointSize < 0) fontDef.pointSize = fontDef.pixelSize * 72. / dpi; else if (fontDef.pixelSize == -1) fontDef.pixelSize = qRound(fontDef.pointSize * dpi / 72.); }
bool CDirectWriteRenderer::GetFontMetrics(CDirectWriteFont &Font, FontMetrics *pMetrics) { if (pMetrics == nullptr) return false; if (m_pRenderTarget == nullptr) return false; HRESULT hr = E_UNEXPECTED; IDWriteTextFormat *pTextFormat = Font.GetTextFormat(); if (pTextFormat != nullptr) { IDWriteFontCollection *pFontCollection; hr = pTextFormat->GetFontCollection(&pFontCollection); if (SUCCEEDED(hr)) { WCHAR szName[256]; hr = pTextFormat->GetFontFamilyName(szName, lengthof(szName)); if (SUCCEEDED(hr)) { UINT32 Index; BOOL fExists; hr = pFontCollection->FindFamilyName(szName, &Index, &fExists); if (SUCCEEDED(hr)) { IDWriteFontFamily *pFontFamily; hr = pFontCollection->GetFontFamily(Index, &pFontFamily); if (SUCCEEDED(hr)) { IDWriteFont *pFont; hr = pFontFamily->GetFirstMatchingFont( pTextFormat->GetFontWeight(), pTextFormat->GetFontStretch(), pTextFormat->GetFontStyle(), &pFont); if (SUCCEEDED(hr)) { DWRITE_FONT_METRICS Metrics; pFont->GetMetrics(&Metrics); const float Ratio = pTextFormat->GetFontSize() / static_cast<float>(Metrics.designUnitsPerEm); pMetrics->Ascent = Metrics.ascent * Ratio; pMetrics->Descent = Metrics.descent * Ratio; pMetrics->LineGap = Metrics.lineGap * Ratio; pFont->Release(); } pFontFamily->Release(); } } } } pFontCollection->Release(); } return SUCCEEDED(hr); }
HRESULT GetFamilyNameFromDWriteFont(IDWriteFont* font, WCHAR* buffer, const UINT bufferSize) { IDWriteFontFamily* dwriteFontFamily; HRESULT hr = font->GetFontFamily(&dwriteFontFamily); if (SUCCEEDED(hr)) { hr = GetFamilyNameFromDWriteFontFamily(dwriteFontFamily, buffer, bufferSize); dwriteFontFamily->Release(); } return hr; }
void loadInitialFontDialogParams(struct fontDialogParams *params) { struct fontCollection *fc; IDWriteFontFamily *family; IDWriteFont *font; HRESULT hr; // Our preferred font is Arial 10 Regular. // 10 comes from the official font dialog. // Arial Regular is a reasonable, if arbitrary, default; it's similar to the defaults on other systems. // If Arial isn't found, we'll use Helvetica and then MS Sans Serif as fallbacks, and if not, we'll just grab the first font family in the collection. // We need the correct localized name for Regular (and possibly Arial too? let's say yes to be safe), so let's grab the strings from DirectWrite instead of hardcoding them. fc = loadFontCollection(); family = tryFindFamily(fc->fonts, L"Arial"); if (family == NULL) { family = tryFindFamily(fc->fonts, L"Helvetica"); if (family == NULL) { family = tryFindFamily(fc->fonts, L"MS Sans Serif"); if (family == NULL) { hr = fc->fonts->GetFontFamily(0, &family); if (hr != S_OK) logHRESULT(L"error getting first font out of font collection (worst case scenario)", hr); } } } // next part is simple: just get the closest match to regular hr = family->GetFirstMatchingFont( DWRITE_FONT_WEIGHT_NORMAL, DWRITE_FONT_STRETCH_NORMAL, DWRITE_FONT_STYLE_NORMAL, &font); if (hr != S_OK) logHRESULT(L"error getting Regular font from Arial", hr); params->font = font; params->size = 10; params->familyName = fontCollectionFamilyName(fc, family); params->styleName = fontStyleName(fc, font); // don't release font; we still need it family->Release(); fontCollectionFree(fc); }
IDWriteFont* FindDWriteFontInFontCollectionByGDIFamilyName( IDWriteFontCollection* fontCollection, const WCHAR* gdiFamilyName) { const UINT32 fontCollectionFamilyCount = fontCollection->GetFontFamilyCount(); for (UINT32 i = 0; i < fontCollectionFamilyCount; ++i) { IDWriteFontFamily* fontFamily; HRESULT hr = fontCollection->GetFontFamily(i, &fontFamily); if (SUCCEEDED(hr)) { IDWriteFont* font = FindDWriteFontInFontFamilyByGDIFamilyName( fontFamily, gdiFamilyName); fontFamily->Release(); if (font) { return font; } } } return nullptr; }
int main(void) { int argc; LPWSTR *argv; WCHAR *fontname, *string; int len; HDC dc; HFONT font, prevfont; IDWriteFontCollection *sysfc; UINT32 index; BOOL exists; IDWriteFontFamily *dwfamily; IDWriteFont *dwfont; IDWriteFontFace *dwface; featurePreparer *features; HRESULT hr; // TODO would using wmain() be adequate? argv = CommandLineToArgvW(GetCommandLineW(), &argc); if (argv == NULL) dieLE("error getting command-line arguments"); if (argc != 3) { fprintf(stderr, "usage: %ws font string\n", argv[0]); return 1; } fontname = argv[1]; string = argv[2]; len = wcslen(string); // DirectWrite requires COM hr = CoInitialize(NULL); if (hr != S_OK) die("error initializing COM", hr); // Uniscribe requires a device context with the font to use dc = GetDC(NULL); if (dc == NULL) dieLE("error getting screen HDC for Uniscribe"); // TODO DEFAULT_CHARSET might affect the results we get font = CreateFontW(0, 0, 0, 0, 0, FALSE, FALSE, FALSE, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH | FF_DONTCARE, fontname); if (font == NULL) dieLE("error creating font for Uniscribe"); prevfont = (HFONT) SelectObject(dc, font); if (prevfont == NULL) dieLE("error selecting font into HDC for Uniscribe"); // and initialize DirectWrite hr = DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED, __uuidof (IDWriteFactory), (IUnknown **) (&dwfactory)); if (hr != S_OK) die("error initializing DirectWrite", hr); // and load the font *there* hr = dwfactory->GetSystemFontCollection(&sysfc, TRUE); if (hr != S_OK) die("error loading DirectWrite system font collection", hr); hr = sysfc->FindFamilyName(fontname, &index, &exists); if (hr != S_OK) die("error finding DirectWrite font family", hr); if (!exists) die("font not found in DirectWrite system font collection", E_FAIL); hr = sysfc->GetFontFamily(index, &dwfamily); if (hr != S_OK) die("error loading DirectWrite font family", hr); hr = dwfamily->GetFirstMatchingFont(DWRITE_FONT_WEIGHT_NORMAL, DWRITE_FONT_STRETCH_NORMAL, DWRITE_FONT_STYLE_NORMAL, &dwfont); if (hr != S_OK) die("error loading DirectWrite font object", hr); hr = dwfont->CreateFontFace(&dwface); if (hr != S_OK) die("error creating DirectWrite font face", hr); // first, uniscribe only; no features are used // uniscribeTest(dc, string, len, NULL, // doScriptItemize, doScriptShape, "Uniscribe"); // next, unprepared features (NULL values) features = new featurePreparer; //features->add('z','e','r','o',1); //features->add('f','r','a','c',1);features->prepare(len); // uniscribeTest(dc, string, len, features, // doScriptItemizeOpenType, doScriptShapeOpenType, "Uniscribe OpenType"); directwriteAnalyzerTest(dwface, string, len, features); delete features; dwface->Release(); dwfont->Release(); dwfamily->Release(); sysfc->Release(); dwfactory->Release(); SelectObject(dc, prevfont); DeleteObject(font); ReleaseDC(NULL, dc); CoUninitialize(); return 0; }