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.); }
static WCHAR *fontStyleName(struct fontCollection *fc, IDWriteFont *font) { IDWriteLocalizedStrings *str; WCHAR *wstr; HRESULT hr; hr = font->GetFaceNames(&str); if (hr != S_OK) logHRESULT(L"error getting font style name for font dialog", hr); wstr = fontCollectionCorrectString(fc, str); str->Release(); return wstr; }
WCHAR *uiprivFontCollectionFamilyName(fontCollection *fc, IDWriteFontFamily *family) { IDWriteLocalizedStrings *names; WCHAR *str; HRESULT hr; hr = family->GetFamilyNames(&names); if (hr != S_OK) logHRESULT(L"error getting names of font out", hr); str = uiprivFontCollectionCorrectString(fc, names); names->Release(); return str; }
HRESULT GetGDIFamilyNameFromDWriteFont(IDWriteFont* font, WCHAR* buffer, UINT bufferSize) { IDWriteLocalizedStrings* strings; BOOL stringsExist; HRESULT hr = font->GetInformationalStrings( DWRITE_INFORMATIONAL_STRING_WIN32_FAMILY_NAMES, &strings, &stringsExist); if (SUCCEEDED(hr) && stringsExist) { hr = strings->GetString(0, buffer, bufferSize); } return hr; }
HRESULT GetFamilyNameFromDWriteFontFamily( IDWriteFontFamily* fontFamily, WCHAR* buffer, const UINT bufferSize) { IDWriteLocalizedStrings* dwFamilyNames; HRESULT hr = fontFamily->GetFamilyNames(&dwFamilyNames); if (SUCCEEDED(hr)) { // TODO: Determine the best index? hr = dwFamilyNames->GetString(0, buffer, bufferSize); dwFamilyNames->Release(); } return hr; }
bool TextFormatD2D::GetFamilyNameFromDWFontFamily(IDWriteFontFamily* fontFamily, WCHAR* buffer, const UINT bufferSize) { bool result = false; IDWriteLocalizedStrings* dwFamilyNames; HRESULT hr = fontFamily->GetFamilyNames(&dwFamilyNames); if (SUCCEEDED(hr)) { // TODO: Determine the best index? hr = dwFamilyNames->GetString(0, buffer, bufferSize); result = SUCCEEDED(hr); dwFamilyNames->Release(); } return result; }
IDictionary<CultureInfo^, System::String^>^ DWrite::Font::FaceNames::get() { if (m_faceNames == nullptr) { IDWriteLocalizedStrings* names = NULL; try { CommonUtils::VerifyResult(GetInterface<IDWriteFont>()->GetFaceNames(&names)); if (names) m_faceNames = CommonUtils::GetCultureNameDictionary(names); } finally { if (names) names->Release(); } }
static void initFontInfo(QFontEngineDirectWrite *fe, const QFontDef &request, int dpi, IDWriteFont *font) { fe->fontDef = request; IDWriteFontFamily *fontFamily = NULL; HRESULT hr = font->GetFontFamily(&fontFamily); IDWriteLocalizedStrings *familyNames = NULL; if (SUCCEEDED(hr)) hr = fontFamily->GetFamilyNames(&familyNames); UINT32 index = 0; BOOL exists = false; wchar_t localeName[LOCALE_NAME_MAX_LENGTH]; if (SUCCEEDED(hr)) { 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; UINT32 length = 0; if (SUCCEEDED(hr)) hr = familyNames->GetStringLength(index, &length); wchar_t *name = new (std::nothrow) wchar_t[length+1]; if (name == NULL) hr = E_OUTOFMEMORY; // Get the family name. if (SUCCEEDED(hr)) hr = familyNames->GetString(index, name, length + 1); if (SUCCEEDED(hr)) fe->fontDef.family = QString::fromWCharArray(name); delete[] name; if (familyNames != NULL) familyNames->Release(); if (FAILED(hr)) qErrnoWarning(hr, "initFontInfo: Failed to get family name"); if (fe->fontDef.pointSize < 0) fe->fontDef.pointSize = fe->fontDef.pixelSize * 72. / dpi; else if (fe->fontDef.pixelSize == -1) fe->fontDef.pixelSize = qRound(fe->fontDef.pointSize * dpi / 72.); }
HRESULT DWriteCreateResources(HDC hdc, wchar_t *text, HFONT hfont) { HRESULT hr = S_OK; // If the DirectWrite factory doesn't exist, create the resources, // only create these resources once. if (!g_pDWriteFactory) { HWND hwnd; RECT r; // DirectWrite variables. IDWriteFontFamily* pFontFamily = NULL; IDWriteFont* pFont = NULL; IDWriteLocalizedStrings* pFamilyNames = NULL; // Logical (GDI) font. LOGFONT lf = {}; UINT32 length = 0; UINT32 index = 0; float fontSize = 0; // length of the string UINT32 textLength = 0; wchar_t *name = NULL; // Get a handle to the DC and the window rect. hwnd = WindowFromDC(hdc); GetClientRect(hwnd, &r); // Calculate the string length. textLength = UINT32(wcslen(text)); // Create the DirectWrite factory. hr = DWriteCreateFactory( DWRITE_FACTORY_TYPE_SHARED, __uuidof(IDWriteFactory), reinterpret_cast<IUnknown**>(&g_pDWriteFactory) ); // Create a GDI interop interface. if (SUCCEEDED(hr)) { hr = g_pDWriteFactory->GetGdiInterop(&g_pGdiInterop); } if (SUCCEEDED(hr)) { // Get a logical font from the font handle. GetObject(hfont, sizeof(LOGFONT), &lf); } // Convert to a DirectWrite font. if (SUCCEEDED(hr)) { hr = g_pGdiInterop->CreateFontFromLOGFONT(&lf, &pFont); } // Get the font family. if (SUCCEEDED(hr)) { hr = pFont->GetFontFamily(&pFontFamily); } // Get a list of localized family names. if (SUCCEEDED(hr)) { hr = pFontFamily->GetFamilyNames(&pFamilyNames); } // Select the first locale. This is OK, because we are not displaying the family name. index = 0; // Get the length of the family name. if (SUCCEEDED(hr)) { hr = pFamilyNames->GetStringLength(index, &length); } if (SUCCEEDED(hr)) { // Allocate a new string. name = new (std::nothrow) wchar_t[length+1]; if (name == NULL) { hr = E_OUTOFMEMORY; } } // Get the actual family name. if (SUCCEEDED(hr)) { hr = pFamilyNames->GetString(index, name, length+1); } if (SUCCEEDED(hr)) { // Calculate the font size. fontSize = (float) -MulDiv(lf.lfHeight, 96, GetDeviceCaps(hdc, LOGPIXELSY)); } // Create a text format using the converted font information. if (SUCCEEDED(hr)) { hr = g_pDWriteFactory->CreateTextFormat( name, // Font family name. NULL, pFont->GetWeight(), pFont->GetStyle(), pFont->GetStretch(), fontSize, L"en-us", &g_pTextFormat ); } // Create a text layout. if (SUCCEEDED(hr)) { hr = g_pDWriteFactory->CreateTextLayout( text, textLength, g_pTextFormat, 1024.0f, 480.0f, &g_pTextLayout ); } // Underline and strikethrough are part of a LOGFONT structure, but are not // part of a DWrite font object so we must set them using the text layout. if(lf.lfUnderline) { DWRITE_TEXT_RANGE textRange = {0, textLength}; g_pTextLayout->SetUnderline(true, textRange); } if(lf.lfStrikeOut) { DWRITE_TEXT_RANGE textRange = {0, textLength}; g_pTextLayout->SetStrikethrough(true, textRange); } // Create a bitmap render target for our custom renderer. if (SUCCEEDED(hr)) { hr = g_pGdiInterop->CreateBitmapRenderTarget(hdc, r.right, r.bottom, &g_pBitmapRenderTarget); } // Create default rendering params for our custom renderer. if (SUCCEEDED(hr)) { hr = g_pDWriteFactory->CreateRenderingParams(&g_pRenderingParams); } if (SUCCEEDED(hr)) { // Initialize the custom renderer class. g_pGdiTextRenderer = new (std::nothrow) GdiTextRenderer(g_pBitmapRenderTarget, g_pRenderingParams); } // Clean up local interfaces. SafeRelease(&pFontFamily); SafeRelease(&pFont); SafeRelease(&pFamilyNames); } return hr; }
HRESULT DWriteContext::SetLOGFONT(const LOGFONTW &logFont, float fontSize) { // Most of this function is copy from: http://msdn.microsoft.com/en-us/library/windows/desktop/dd941783(v=vs.85).aspx HRESULT hr = S_OK; IDWriteFont *font = NULL; IDWriteFontFamily *fontFamily = NULL; IDWriteLocalizedStrings *localizedFamilyNames = NULL; if (SUCCEEDED(hr)) { hr = mGdiInterop->CreateFontFromLOGFONT(&logFont, &font); } // Get the font family to which this font belongs. if (SUCCEEDED(hr)) { hr = font->GetFontFamily(&fontFamily); } // Get the family names. This returns an object that encapsulates one or // more names with the same meaning but in different languages. if (SUCCEEDED(hr)) { hr = fontFamily->GetFamilyNames(&localizedFamilyNames); } // Get the family name at index zero. If we were going to display the name // we'd want to try to find one that matched the use locale, but for // purposes of creating a text format object any language will do. wchar_t familyName[100]; if (SUCCEEDED(hr)) { hr = localizedFamilyNames->GetString(0, familyName, ARRAYSIZE(familyName)); } if (SUCCEEDED(hr)) { // If no font size was passed in use the lfHeight of the LOGFONT. if (fontSize == 0) { // Convert from pixels to DIPs. fontSize = PixelsToDipsY(logFont.lfHeight); if (fontSize < 0) { // Negative lfHeight represents the size of the em unit. fontSize = -fontSize; } else { // Positive lfHeight represents the cell height (ascent + // descent). DWRITE_FONT_METRICS fontMetrics; font->GetMetrics(&fontMetrics); // Convert the cell height (ascent + descent) from design units // to ems. float cellHeight = static_cast<float>( fontMetrics.ascent + fontMetrics.descent) / fontMetrics.designUnitsPerEm; // Divide the font size by the cell height to get the font em // size. fontSize /= cellHeight; } } } // The text format includes a locale name. Ideally, this would be the // language of the text, which may or may not be the same as the primary // language of the user. However, for our purposes the user locale will do. wchar_t localeName[LOCALE_NAME_MAX_LENGTH]; if (SUCCEEDED(hr)) { if (GetUserDefaultLocaleName(localeName, LOCALE_NAME_MAX_LENGTH) == 0) hr = HRESULT_FROM_WIN32(GetLastError()); } if (SUCCEEDED(hr)) { // Create the text format object. hr = mDWriteFactory->CreateTextFormat( familyName, NULL, // no custom font collection font->GetWeight(), font->GetStyle(), font->GetStretch(), fontSize, localeName, &mTextFormat); } if (SUCCEEDED(hr)) { mFontWeight = static_cast<DWRITE_FONT_WEIGHT>(logFont.lfWeight); mFontStyle = logFont.lfItalic ? DWRITE_FONT_STYLE_ITALIC : DWRITE_FONT_STYLE_NORMAL; } SafeRelease(&localizedFamilyNames); SafeRelease(&fontFamily); SafeRelease(&font); return hr; }
static void fontDialogDrawSampleText(struct fontDialog *f, ID2D1RenderTarget *rt) { D2D1_COLOR_F color; D2D1_BRUSH_PROPERTIES props; ID2D1SolidColorBrush *black; IDWriteFont *font; IDWriteLocalizedStrings *sampleStrings; BOOL exists; WCHAR *sample; WCHAR *family; IDWriteTextFormat *format; D2D1_RECT_F rect; HRESULT hr; color.r = 0.0; color.g = 0.0; color.b = 0.0; color.a = 1.0; ZeroMemory(&props, sizeof (D2D1_BRUSH_PROPERTIES)); props.opacity = 1.0; // identity matrix props.transform._11 = 1; props.transform._22 = 1; hr = rt->CreateSolidColorBrush( &color, &props, &black); if (hr != S_OK) logHRESULT(L"error creating solid brush", hr); font = (IDWriteFont *) cbGetItemData(f->styleCombobox, (WPARAM) f->curStyle); hr = font->GetInformationalStrings(DWRITE_INFORMATIONAL_STRING_SAMPLE_TEXT, &sampleStrings, &exists); if (hr != S_OK) exists = FALSE; if (exists) { sample = fontCollectionCorrectString(f->fc, sampleStrings); sampleStrings->Release(); } else sample = L"The quick brown fox jumps over the lazy dog."; // DirectWrite doesn't allow creating a text format from a font; we need to get this ourselves family = cbGetItemText(f->familyCombobox, f->curFamily); hr = dwfactory->CreateTextFormat(family, NULL, font->GetWeight(), font->GetStyle(), font->GetStretch(), // typographic points are 1/72 inch; this parameter is 1/96 inch // fortunately Microsoft does this too, in https://msdn.microsoft.com/en-us/library/windows/desktop/dd371554%28v=vs.85%29.aspx f->curSize * (96.0 / 72.0), // see http://stackoverflow.com/questions/28397971/idwritefactorycreatetextformat-failing and https://msdn.microsoft.com/en-us/library/windows/desktop/dd368203.aspx // TODO use the current locale again? L"", &format); if (hr != S_OK) logHRESULT(L"error creating IDWriteTextFormat", hr); uiFree(family); rect.left = 0; rect.top = 0; rect.right = realGetSize(rt).width; rect.bottom = realGetSize(rt).height; rt->DrawText(sample, wcslen(sample), format, &rect, black, // TODO really? D2D1_DRAW_TEXT_OPTIONS_NONE, DWRITE_MEASURING_MODE_NATURAL); format->Release(); if (exists) uiFree(sample); black->Release(); }
void wmain() { IDWriteFactory* pDWriteFactory = NULL; HRESULT hr = DWriteCreateFactory( DWRITE_FACTORY_TYPE_SHARED, __uuidof(IDWriteFactory), reinterpret_cast<IUnknown**>(&pDWriteFactory) ); IDWriteFontCollection* pFontCollection = NULL; // Get the system font collection. if (SUCCEEDED(hr)) { hr = pDWriteFactory->GetSystemFontCollection(&pFontCollection); } UINT32 familyCount = 0; // Get the number of font families in the collection. if (SUCCEEDED(hr)) { familyCount = pFontCollection->GetFontFamilyCount(); } for (UINT32 i = 0; i < familyCount; ++i) { IDWriteFontFamily* pFontFamily = NULL; // Get the font family. if (SUCCEEDED(hr)) { hr = pFontCollection->GetFontFamily(i, &pFontFamily); } IDWriteLocalizedStrings* pFamilyNames = NULL; // Get a list of localized strings for the family name. if (SUCCEEDED(hr)) { hr = pFontFamily->GetFamilyNames(&pFamilyNames); } UINT32 index = 0; BOOL exists = false; wchar_t localeName[LOCALE_NAME_MAX_LENGTH]; if (SUCCEEDED(hr)) { // Get the default locale for this user. int defaultLocaleSuccess = GetUserDefaultLocaleName(localeName, LOCALE_NAME_MAX_LENGTH); // If the default locale is returned, find that locale name, otherwise use "en-us". if (defaultLocaleSuccess) { hr = pFamilyNames->FindLocaleName(localeName, &index, &exists); } else { hr = pFamilyNames->FindLocaleName(L"en-us", &index, &exists); } } // If the specified locale doesn't exist, select the first on the list. if (!exists) index = 0; UINT32 length = 0; // Get the string length. if (SUCCEEDED(hr)) { hr = pFamilyNames->GetStringLength(index, &length); } // Allocate a string big enough to hold the name. wchar_t* name = new (std::nothrow) wchar_t[length+1]; if (name == NULL) { hr = E_OUTOFMEMORY; } // Get the family name. if (SUCCEEDED(hr)) { hr = pFamilyNames->GetString(index, name, length+1); } if (SUCCEEDED(hr)) { // Print out the family name. wprintf(L"%s\n", name); } SafeRelease(&pFontFamily); SafeRelease(&pFamilyNames); delete [] name; } SafeRelease(&pFontCollection); SafeRelease(&pDWriteFactory); }