boolean gdiplus_textlayout(textpara_t *para, char **fontpath) { /* ensure GDI+ is started up: since we get called outside of a job, we can't rely on GDI+ startup then */ UseGdiplus(); Layout* layout = new Layout(para->fontname, para->fontsize, para->str); /* measure the text */ /* NOTE: use TextRenderingHintAntiAlias + GetGenericTypographic to get a layout without extra space at beginning and end */ RectF boundingBox; DeviceContext deviceContext; Graphics measureGraphics(deviceContext.hdc); measureGraphics.SetTextRenderingHint(TextRenderingHintAntiAlias); measureGraphics.MeasureString( &layout->text[0], layout->text.size(), layout->font, PointF(0.0f, 0.0f), GetGenericTypographic(), &boundingBox); FontFamily fontFamily; layout->font->GetFamily(&fontFamily); int style = layout->font->GetStyle(); para->layout = (void*)layout; para->free_layout = &gdiplus_free_layout; para->width = boundingBox.Width; para->height = layout->font->GetHeight(&measureGraphics); para->yoffset_layout = fontFamily.GetCellAscent(style) * para->fontsize / fontFamily.GetEmHeight(style); /* convert design units to pixels */ para->yoffset_centerline = 0; return TRUE; };
// -------------------------------------------------------------- GFontWin32GDIPlus::GFontWin32GDIPlus( Font* nativeFont, const char * faceName, int size, int properties) : mNativeFont(nativeFont), mName(faceName), mSize(size), mFontProp(properties) { DWORD count = (DWORD)mbstowcs(NULL, faceName, strlen(faceName)); WCHAR * wstr = (WCHAR*) malloc ((count + 1) * sizeof(WCHAR)); mbstowcs(wstr, faceName, strlen(faceName)); FontCollection fc; FontFamily ff (wstr, &fc); int style; switch (properties) { case kFontBold: style = FontStyleBold; break; case kFontItalic: style = FontStyleItalic; break; case kFontBold+kFontItalic: style = FontStyleBoldItalic; break; case kFontUnderline: style = FontStyleUnderline; break; default: style = FontStyleRegular; } mEmHeight = ff.GetEmHeight(style); float ratio = mEmHeight ? (float)mEmHeight / size : 1.f; mAscent = ff.GetCellAscent(style) / ratio; mDescent = ff.GetCellDescent(style) / ratio; free (wstr); }
void CButtonCx::DrawString(CDC *drawDC, LPDRAWITEMSTRUCT lpDrawItemStruct) { // テキストを得る。 CString title; GetWindowText(title); // テキストが空の場合および GDI+ Font/Brush が設定されていない場合何もしない。 if (title.IsEmpty() || m_GpFont == NULL || m_GpBrush == NULL) { return; } // 透過モードにする。 drawDC->SetBkMode(TRANSPARENT); // テキストの描画位置 CRect rect = (CRect) (lpDrawItemStruct->rcItem); // クライアント四角形の取得 // マージン設定 rect.top += m_Margin.top; rect.left += m_Margin.left; rect.bottom -= m_Margin.bottom; rect.right -= m_Margin.right; CArray<CString, CString> arr; arr.RemoveAll(); CString resToken; int curPos = 0; resToken = title.Tokenize(L"\r\n", curPos); while (resToken != L"") { arr.Add(resToken); resToken = title.Tokenize(L"\r\n", curPos); } if (m_FontType == FT_GDI_PLUS || m_FontType == FT_AUTO) // GDI+ { Gdiplus::Graphics g(drawDC->m_hDC); const Gdiplus::PointF pointF(0.0, 0.0); Gdiplus::RectF extentF; for (int i = 0; i < arr.GetCount(); i++) { CRect r; r.top = (LONG) (((double) rect.Height()) / arr.GetCount() * i); r.bottom = (LONG) (((double) rect.Height()) / arr.GetCount() * (i + 1)); r.left = rect.left; r.right = rect.right; g.MeasureString(arr.GetAt(i), arr.GetAt(i).GetLength() + 1, m_GpFont, pointF, &extentF); // "+ 1" for workdaround REAL y; FontFamily ff; m_GpFont->GetFamily(&ff); REAL ascent = (REAL) ff.GetCellAscent(FontStyleRegular); REAL lineSpacing = (REAL) ff.GetLineSpacing(FontStyleRegular); y = r.CenterPoint().y - (extentF.Height * ascent / lineSpacing) / 2; Gdiplus::PointF pt(rect.CenterPoint().x - (extentF.Width / 2), y); Gdiplus::RectF rectF(pt.X, pt.Y, (REAL) extentF.Width, (REAL) extentF.Height); g.SetTextRenderingHint(TextRenderingHintAntiAlias); g.DrawString(arr.GetAt(i), -1, m_GpFont, rectF, m_GpStringformat, m_GpBrush); } } else // GDI { for (int i = 0; i < arr.GetCount(); i++) { CRect r; r.top = rect.top + (LONG) (((double) rect.Height()) / arr.GetCount() * i); r.bottom = rect.top + (LONG) (((double) rect.Height()) / arr.GetCount() * (i + 1)); r.left = rect.left; r.right = rect.right; CRect rectI; CSize extent; HGDIOBJ oldFont = drawDC->SelectObject(m_Font); GetTextExtentPoint32(drawDC->m_hDC, arr.GetAt(i), arr.GetAt(i).GetLength() + 1, &extent); rectI.top = r.top + (r.Height() - extent.cy) / 2; rectI.bottom = rectI.top + extent.cy; rectI.left = r.left; rectI.right = r.right; DrawText(drawDC->m_hDC, arr.GetAt(i), arr.GetAt(i).GetLength(), r, DT_CENTER | DT_VCENTER | DT_SINGLELINE); drawDC->SelectObject(oldFont); } } // いつか DirectWrite 描画に対応したいものである。。。 }