ULONG GetBestFontAttributes(IDWriteFontCollection* fontCollection, const WCHAR* fontFamilyName, const FontFaceInfo& desiredAttributes) { DWRITE_FONT_WEIGHT fontWeight = desiredAttributes.fontWeight; DWRITE_FONT_STYLE fontStyle = desiredAttributes.fontStyle; DWRITE_FONT_STRETCH fontStretch = desiredAttributes.fontStretch; IDWriteFontFamily* fontFamily = NULL; IDWriteFont* font = NULL; if (SUCCEEDED(GetFontFamily(fontCollection, fontFamilyName, &fontFamily))) { if (SUCCEEDED(fontFamily->GetFirstMatchingFont(fontWeight, fontStretch, fontStyle, &font))) { fontWeight = font->GetWeight(); fontStyle = font->GetStyle(); fontStretch = font->GetStretch(); } } SafeRelease(&font); SafeRelease(&fontFamily); FontFaceInfo fontFaceInfo(L"", fontWeight, fontStyle, fontStretch); return fontFaceInfo.PackedFontAttributes(); }
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.); }
const float getFontHeightToEmSizeFactor(Font& font, IDWriteFontCollection& dwFontCollection) { // To set the font size factor, we need to get the font metrics BOOL fontFound; uint32 fontIndex; // Search for the font in the font collection using the font name HRESULT hr = dwFontCollection.FindFamilyName (font.getTypefaceName().toWideCharPointer(), &fontIndex, &fontFound); if (! fontFound) fontIndex = 0; IDWriteFontFamily* dwFontFamily = nullptr; hr = dwFontCollection.GetFontFamily (fontIndex, &dwFontFamily); IDWriteFont* dwFont = nullptr; hr = dwFontFamily->GetFirstMatchingFont (DWRITE_FONT_WEIGHT_NORMAL, DWRITE_FONT_STRETCH_NORMAL, DWRITE_FONT_STYLE_NORMAL, &dwFont); IDWriteFontFace* dwFontFace = nullptr; hr = dwFont->CreateFontFace (&dwFontFace); // Font metrics are in font design units DWRITE_FONT_METRICS dwFontMetrics; dwFontFace->GetMetrics (&dwFontMetrics); const float totalHeight = std::abs ((float) dwFontMetrics.ascent) + std::abs ((float) dwFontMetrics.descent); const float fontHeightToEmSizeFactor = (float) dwFontMetrics.designUnitsPerEm / totalHeight; safeRelease (&dwFontFace); safeRelease (&dwFont); safeRelease (&dwFontFamily); return fontHeightToEmSizeFactor; }
static void familyChanged(struct fontDialog *f) { LRESULT pos; BOOL selected; IDWriteFontFamily *family; IDWriteFont *font, *matchFont; DWRITE_FONT_WEIGHT weight; DWRITE_FONT_STYLE style; DWRITE_FONT_STRETCH stretch; UINT32 i, n; UINT32 matching; WCHAR *label; HRESULT hr; selected = cbGetCurSel(f->familyCombobox, &pos); if (!selected) // on deselect, do nothing return; f->curFamily = pos; family = (IDWriteFontFamily *) cbGetItemData(f->familyCombobox, (WPARAM) (f->curFamily)); // for the nearest style match // when we select a new family, we want the nearest style to the previously selected one to be chosen // this is how the Choose Font sample does it hr = family->GetFirstMatchingFont( f->weight, f->stretch, f->style, &matchFont); if (hr != S_OK) logHRESULT(L"error finding first matching font to previous style in font dialog", hr); // we can't just compare pointers; a "newly created" object comes out // the Choose Font sample appears to do this instead weight = matchFont->GetWeight(); style = matchFont->GetStyle(); stretch = matchFont->GetStretch(); matchFont->Release(); // TODO test mutliple streteches; all the fonts I have have only one stretch value? wipeStylesBox(f); n = family->GetFontCount(); matching = 0; // a safe/suitable default just in case for (i = 0; i < n; i++) { hr = family->GetFont(i, &font); if (hr != S_OK) logHRESULT(L"error getting font for filling styles box", hr); label = fontStyleName(f->fc, font); pos = cbAddString(f->styleCombobox, label); uiFree(label); cbSetItemData(f->styleCombobox, (WPARAM) pos, (LPARAM) font); if (font->GetWeight() == weight && font->GetStyle() == style && font->GetStretch() == stretch) matching = i; } // and now, load the match cbSetCurSel(f->styleCombobox, (WPARAM) matching); styleChanged(f); }
/* IDWriteGdiInterop methods */ virtual HRESULT STDMETHODCALLTYPE CreateFontFromLOGFONT( LOGFONTW const *logFont, IDWriteFont **font) { OutputDebugString("delegate_dwrite_gdi_interop::CreateFontFromLOGFONT"); HRESULT result; UINT32 index; BOOL exists; result = mycoll_->FindFamilyName(logFont->lfFaceName, &index, &exists); if (SUCCEEDED(result)) { result = E_FAIL; if (exists != FALSE) { IDWriteFontFamily *family; result = mycoll_->GetFontFamily(index, &family); if (SUCCEEDED(result)) { result = family->GetFirstMatchingFont( (DWRITE_FONT_WEIGHT)logFont->lfWeight, DWRITE_FONT_STRETCH_NORMAL, DWRITE_FONT_STYLE_NORMAL, font); iunknown_release(family); } } } if (FAILED(result)) { OutputDebugString("delegate_dwrite_gdi_interop::CreateFontFromLOGFONT -> fallback"); result = orig_this->CreateFontFromLOGFONT(logFont, font); } return result; }
static cairo_status_t _cairo_dwrite_font_face_create_for_toy (cairo_toy_font_face_t *toy_face, cairo_font_face_t **font_face) { WCHAR *face_name; int face_name_len; if (!DWriteFactory::Instance()) { return (cairo_status_t)CAIRO_INT_STATUS_UNSUPPORTED; } face_name_len = MultiByteToWideChar(CP_UTF8, 0, toy_face->family, -1, NULL, 0); face_name = new WCHAR[face_name_len]; MultiByteToWideChar(CP_UTF8, 0, toy_face->family, -1, face_name, face_name_len); IDWriteFontFamily *family = DWriteFactory::FindSystemFontFamily(face_name); delete face_name; if (!family) { *font_face = (cairo_font_face_t*)&_cairo_font_face_nil; return CAIRO_STATUS_FONT_TYPE_MISMATCH; } DWRITE_FONT_WEIGHT weight; switch (toy_face->weight) { case CAIRO_FONT_WEIGHT_BOLD: weight = DWRITE_FONT_WEIGHT_BOLD; break; case CAIRO_FONT_WEIGHT_NORMAL: default: weight = DWRITE_FONT_WEIGHT_NORMAL; break; } DWRITE_FONT_STYLE style; switch (toy_face->slant) { case CAIRO_FONT_SLANT_ITALIC: style = DWRITE_FONT_STYLE_ITALIC; break; case CAIRO_FONT_SLANT_OBLIQUE: style = DWRITE_FONT_STYLE_OBLIQUE; break; case CAIRO_FONT_SLANT_NORMAL: default: style = DWRITE_FONT_STYLE_NORMAL; break; } cairo_dwrite_font_face_t *face = (cairo_dwrite_font_face_t*)malloc(sizeof(cairo_dwrite_font_face_t)); HRESULT hr = family->GetFirstMatchingFont(weight, DWRITE_FONT_STRETCH_NORMAL, style, &face->font); if (SUCCEEDED(hr)) { // Cannot use C++ style new since cairo deallocates this. *font_face = (cairo_font_face_t*)face; _cairo_font_face_init (&(*(_cairo_dwrite_font_face**)font_face)->base, &_cairo_dwrite_font_face_backend); } else { free(face); } return CAIRO_STATUS_SUCCESS; }
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); }
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 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; }
HRESULT GetFonts(IDWriteFontCollection* fontCollection, const WCHAR* fontFamilyName, IN OUT std::vector<IDWriteFont*>& fonts) { HRESULT hr = S_OK; IDWriteFontFamily* fontFamily = NULL; IDWriteFont* font = NULL; hr = GetFontFamily(fontCollection, fontFamilyName, &fontFamily); if (SUCCEEDED(hr)) { UINT32 fontCount = fontFamily->GetFontCount(); // Read font variant in the family. try { for (UINT32 i = 0; i != fontCount; ++i) { hr = fontFamily->GetFont(i, &font); if (FAILED(hr)) break; fonts.push_back(font); SafeDetach(&font); } } catch (...) { hr = ExceptionToHResult(); } } SafeRelease(&font); SafeRelease(&fontFamily); return hr; }
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; }
void QWinRTFontDatabase::populateFamily(const QString &familyName) { IDWriteFontFamily *fontFamily = m_fontFamilies.value(familyName); if (!fontFamily) { qWarning("The font family %s was not found.", qPrintable(familyName)); return; } bool fontRegistered = false; const int fontCount = fontFamily->GetFontCount(); for (int j = 0; j < fontCount; ++j) { ComPtr<IDWriteFont> font; HRESULT hr = fontFamily->GetFont(j, &font); if (FAILED(hr)) { qWarning("Unable to get font: %s", qPrintable(qt_error_string(hr))); continue; } // Skip simulated faces if (font->GetSimulations() != DWRITE_FONT_SIMULATIONS_NONE) continue; ComPtr<IDWriteFontFace> baseFontFace; hr = font->CreateFontFace(&baseFontFace); if (FAILED(hr)) { qWarning("Unable to create base font face: %s", qPrintable(qt_error_string(hr))); continue; } ComPtr<IDWriteFontFace1> fontFace; hr = baseFontFace.As(&fontFace); if (FAILED(hr)) { qWarning("Unable to create font face: %s", qPrintable(qt_error_string(hr))); continue; } // We can't deal with multi-file fonts quint32 fileCount; hr = fontFace->GetFiles(&fileCount, NULL); if (FAILED(hr)) { qWarning("Unable to get font file count: %s", qPrintable(qt_error_string(hr))); continue; } if (fileCount != 1) continue; ComPtr<IDWriteLocalizedStrings> informationalStrings; BOOL exists; hr = font->GetInformationalStrings(DWRITE_INFORMATIONAL_STRING_MANUFACTURER, &informationalStrings, &exists); if (FAILED(hr)) { qWarning("Unable to get font foundry: %s", qPrintable(qt_error_string(hr))); continue; } QString foundryName; if (exists) { quint32 length; hr = informationalStrings->GetStringLength(0, &length); if (FAILED(hr)) qWarning("Unable to get foundry name length: %s", qPrintable(qt_error_string(hr))); if (SUCCEEDED(hr)) { QVector<wchar_t> buffer(length + 1); hr = informationalStrings->GetString(0, buffer.data(), buffer.size()); if (FAILED(hr)) qWarning("Unable to get foundry name: %s", qPrintable(qt_error_string(hr))); if (SUCCEEDED(hr)) foundryName = QString::fromWCharArray(buffer.data(), length); } } QFont::Weight weight; switch (font->GetWeight()) { case DWRITE_FONT_WEIGHT_THIN: case DWRITE_FONT_WEIGHT_EXTRA_LIGHT: case DWRITE_FONT_WEIGHT_LIGHT: case DWRITE_FONT_WEIGHT_SEMI_LIGHT: weight = QFont::Light; break; default: case DWRITE_FONT_WEIGHT_NORMAL: case DWRITE_FONT_WEIGHT_MEDIUM: weight = QFont::Normal; break; case DWRITE_FONT_WEIGHT_DEMI_BOLD: weight = QFont::DemiBold; break; case DWRITE_FONT_WEIGHT_BOLD: case DWRITE_FONT_WEIGHT_EXTRA_BOLD: weight = QFont::Bold; break; case DWRITE_FONT_WEIGHT_BLACK: case DWRITE_FONT_WEIGHT_EXTRA_BLACK: weight = QFont::Black; break; } QFont::Style style; switch (font->GetStyle()) { default: case DWRITE_FONT_STYLE_NORMAL: style = QFont::StyleNormal; break; case DWRITE_FONT_STYLE_OBLIQUE: style = QFont::StyleOblique; break; case DWRITE_FONT_STYLE_ITALIC: style = QFont::StyleItalic; break; } QFont::Stretch stretch; switch (font->GetStretch()) { default: case DWRITE_FONT_STRETCH_UNDEFINED: case DWRITE_FONT_STRETCH_NORMAL: stretch = QFont::Unstretched; break; case DWRITE_FONT_STRETCH_ULTRA_CONDENSED: stretch = QFont::UltraCondensed; break; case DWRITE_FONT_STRETCH_EXTRA_CONDENSED: stretch = QFont::ExtraCondensed; break; case DWRITE_FONT_STRETCH_CONDENSED: stretch = QFont::Condensed; break; case DWRITE_FONT_STRETCH_SEMI_CONDENSED: stretch = QFont::SemiCondensed; break; case DWRITE_FONT_STRETCH_SEMI_EXPANDED: stretch = QFont::SemiExpanded; break; case DWRITE_FONT_STRETCH_EXPANDED: stretch = QFont::Expanded; break; case DWRITE_FONT_STRETCH_EXTRA_EXPANDED: stretch = QFont::ExtraExpanded; break; case DWRITE_FONT_STRETCH_ULTRA_EXPANDED: stretch = QFont::UltraExpanded; break; } const bool fixedPitch = fontFace->IsMonospacedFont(); quint32 unicodeRange[4]; quint32 actualRangeCount; hr = fontFace->GetUnicodeRanges( 2, reinterpret_cast<DWRITE_UNICODE_RANGE *>(unicodeRange), &actualRangeCount); if (FAILED(hr) && hr != E_NOT_SUFFICIENT_BUFFER) { // Ignore insufficient buffer; we only need 4 indices qWarning("Unable to get font unicode range: %s", qPrintable(qt_error_string(hr))); continue; } quint32 codePageRange[2] = { 0, 0 }; QSupportedWritingSystems writingSystems = QPlatformFontDatabase::writingSystemsFromTrueTypeBits(unicodeRange, codePageRange); IDWriteFontFile *fontFile; hr = fontFace->GetFiles(&fileCount, &fontFile); if (FAILED(hr)) { qWarning("Unable to get font file: %s", qPrintable(qt_error_string(hr))); continue; } FontDescription description = { fontFace->GetIndex(), QUuid::createUuid().toByteArray() }; m_fonts.insert(fontFile, description); registerFont(familyName, QString(), foundryName, weight, style, stretch, true, true, 0, fixedPitch, writingSystems, fontFile); fontRegistered = true; } // Always populate something to avoid an assert if (!fontRegistered) { registerFont(familyName, QString(), QString(), QFont::Normal, QFont::StyleNormal, QFont::Unstretched, false, false, 0, false, QSupportedWritingSystems(), 0); } }
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); }
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; }