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(); }
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); }
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; }
/* 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; }
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; }
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); }
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); }
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; }