PerGlyphOpacityTextRender.cpp
1 #include "pch.h" 2 3 #include "PerGlyphOpacityTextRender.h" 4 5 PerGlyphOpacityTextRender::PerGlyphOpacityTextRender( 6 winrt::com_ptr<ID2D1Factory> pD2DFactory, 7 winrt::com_ptr<ID2D1RenderTarget> rt, 8 winrt::com_ptr<ID2D1SolidColorBrush> baseBrush) : 9 _pD2DFactory{ pD2DFactory.get() }, 10 _rt{ rt.get() }, 11 _baseBrush{ baseBrush.get() } 12 { 13 } 14 15 HRESULT __stdcall PerGlyphOpacityTextRender::DrawGlyphRun(void* /*clientDrawingContext*/, 16 FLOAT baselineOriginX, 17 FLOAT baselineOriginY, 18 DWRITE_MEASURING_MODE measuringMode, 19 _In_ const DWRITE_GLYPH_RUN* glyphRun, 20 _In_ const DWRITE_GLYPH_RUN_DESCRIPTION* /*glyphRunDescription*/, 21 IUnknown* clientDrawingEffect_) noexcept 22 { 23 HRESULT hr = S_OK; 24 if (!clientDrawingEffect_) 25 { 26 _rt->DrawGlyphRun(D2D1_POINT_2F{ .x = baselineOriginX, .y = baselineOriginY }, glyphRun, _baseBrush, measuringMode); 27 return hr; 28 } 29 wil::com_ptr<IUnknown> clientDrawingEffect{ clientDrawingEffect_ }; 30 31 // Create the path geometry. 32 wil::com_ptr<ID2D1PathGeometry> pathGeometry; 33 hr = _pD2DFactory->CreatePathGeometry(&pathGeometry); 34 35 // Write to the path geometry using the geometry sink. 36 wil::com_ptr<ID2D1GeometrySink> pSink; 37 if (SUCCEEDED(hr)) 38 { 39 hr = pathGeometry->Open(&pSink); 40 } 41 42 // Get the glyph run outline geometries back from DirectWrite and place them within the 43 // geometry sink. 44 if (SUCCEEDED(hr)) 45 { 46 hr = glyphRun->fontFace->GetGlyphRunOutline( 47 glyphRun->fontEmSize, 48 glyphRun->glyphIndices, 49 glyphRun->glyphAdvances, 50 glyphRun->glyphOffsets, 51 glyphRun->glyphCount, 52 glyphRun->isSideways, 53 glyphRun->bidiLevel % 2, 54 pSink.get()); 55 } 56 57 if (pSink) 58 { 59 hr = pSink->Close(); 60 } 61 62 // Initialize a matrix to translate the origin of the glyph run. 63 D2D1::Matrix3x2F const matrix = D2D1::Matrix3x2F( 64 1.0f, 0.0f, 0.0f, 1.0f, baselineOriginX, baselineOriginY); 65 66 // Create the transformed geometry 67 wil::com_ptr<ID2D1TransformedGeometry> pTransformedGeometry; 68 if (SUCCEEDED(hr)) 69 { 70 hr = _pD2DFactory->CreateTransformedGeometry(pathGeometry.get(), &matrix, &pTransformedGeometry); 71 } 72 73 float prevOpacity = _baseBrush->GetOpacity(); 74 auto opacityEffect = clientDrawingEffect.try_query<IDrawingEffect>(); 75 76 if (opacityEffect) 77 { 78 const auto temp_opacity = dynamic_cast<OpacityEffect*>(opacityEffect.get()); 79 assert(nullptr != temp_opacity); 80 _baseBrush->SetOpacity(temp_opacity->alpha); 81 } 82 83 84 if (SUCCEEDED(hr)) 85 { 86 _rt->DrawGeometry(pTransformedGeometry.get(), _baseBrush); 87 _rt->FillGeometry(pTransformedGeometry.get(), _baseBrush); 88 _baseBrush->SetOpacity(prevOpacity); 89 } 90 91 return hr; 92 } 93 94 HRESULT __stdcall PerGlyphOpacityTextRender::DrawUnderline(void* /*clientDrawingContext*/, 95 FLOAT /*baselineOriginX*/, 96 FLOAT /*baselineOriginY*/, 97 _In_ const DWRITE_UNDERLINE* /*underline*/, 98 IUnknown* /*clientDrawingEffect*/) noexcept 99 { 100 return E_NOTIMPL; 101 } 102 103 HRESULT __stdcall PerGlyphOpacityTextRender::DrawStrikethrough(void* /*clientDrawingContext*/, 104 FLOAT /*baselineOriginX*/, 105 FLOAT /*baselineOriginY*/, 106 _In_ const DWRITE_STRIKETHROUGH* /*strikethrough*/, 107 IUnknown* /*clientDrawingEffect*/) noexcept 108 { 109 return E_NOTIMPL; 110 } 111 112 HRESULT __stdcall PerGlyphOpacityTextRender::DrawInlineObject(void* /*clientDrawingContext*/, 113 FLOAT /*originX*/, 114 FLOAT /*originY*/, 115 IDWriteInlineObject* /*inlineObject*/, 116 BOOL /*isSideways*/, 117 BOOL /*isRightToLeft*/, 118 IUnknown* /*clientDrawingEffect*/) noexcept 119 { 120 return E_NOTIMPL; 121 } 122 123 HRESULT __stdcall PerGlyphOpacityTextRender::IsPixelSnappingDisabled(void* /*clientDrawingContext*/, BOOL* isDisabled) noexcept 124 { 125 RETURN_HR_IF_NULL(E_INVALIDARG, isDisabled); 126 127 *isDisabled = false; 128 return S_OK; 129 } 130 131 HRESULT __stdcall PerGlyphOpacityTextRender::GetCurrentTransform(void* /*clientDrawingContext*/, DWRITE_MATRIX* transform) noexcept 132 { 133 _rt->GetTransform(reinterpret_cast<D2D1_MATRIX_3X2_F*>(transform)); 134 return S_OK; 135 } 136 137 HRESULT __stdcall PerGlyphOpacityTextRender::GetPixelsPerDip(void* /*clientDrawingContext*/, FLOAT* pixelsPerDip) noexcept 138 { 139 _rt->GetDpi(pixelsPerDip, pixelsPerDip); 140 return S_OK; 141 }