HRESULT CCustomTextRenderer::XCustomTextRenderer::_DrawOutlinedGlyphRun(
CRenderTarget* pRenderTarget,
COutlinedTextEffect* pEffect,
const CD2DPointF& point,
const DWRITE_GLYPH_RUN* pGlyphRun,
DWRITE_MEASURING_MODE measuringMode)
{
ASSERT(pRenderTarget && pRenderTarget->IsValid());
ASSERT(pEffect && pEffect->IsValid());
// get the Direct2D resources contained the COutlinedTextEffect object
CD2DBrush* pOutlineBrush = pEffect->GetOutlineBrush();
ASSERT(pOutlineBrush && pOutlineBrush->IsValid());
CD2DBrush* pFillBrush = pEffect->GetFillBrush();
ASSERT(pFillBrush && pFillBrush->IsValid());
// get outline stroke width and RTL flag
FLOAT fStrokeWidth = pEffect->GetStrokeWidth();
BOOL bIsRightToLeft = pEffect->IsRightToLeft();
// create path geometry
CD2DPathGeometry pathGeometry = (pRenderTarget);
HRESULT hr = pathGeometry.Create(pRenderTarget);
ASSERT(SUCCEEDED(hr));
if (FAILED(hr)) return hr;
// create a geometry sink which will be called back
// to perform outline drawing operations
CD2DGeometrySink geometrySink(pathGeometry);
ASSERT(geometrySink.IsValid());
// get IDWriteFontFace interface from DWRITE_GLYPH_RUN structure
IDWriteFontFace* pFontFace = pGlyphRun->fontFace;
// call IDWriteFontFace::GetGlyphRunOutline passing data
// contained in DWRITE_GLYPH_RUN and the geometry sink
hr = pFontFace->GetGlyphRunOutline(pGlyphRun->fontEmSize,
pGlyphRun->glyphIndices, pGlyphRun->glyphAdvances,
pGlyphRun->glyphOffsets, pGlyphRun->glyphCount,
pGlyphRun->isSideways, bIsRightToLeft, geometrySink);
if (FAILED(hr)) return hr;
geometrySink.Close();
// keep in mind the render target transform matrix
D2D1_MATRIX_3X2_F oldMatrix;
pRenderTarget->GetTransform(&oldMatrix);
// translate the render target according to baseline coordinates
pRenderTarget->SetTransform(D2D1::Matrix3x2F::Translation(point.x, point.y));
// draw the outline and fill the geometry path
pRenderTarget->DrawGeometry(&pathGeometry, pOutlineBrush, fStrokeWidth);
pRenderTarget->FillGeometry(&pathGeometry, pFillBrush);
// restore the initial render target transform
pRenderTarget->SetTransform(oldMatrix);
return S_OK;
// well, maybe this method needs a little bit of refactoring. :)
}