/ src / modules / MeasureTool / MeasureToolCore / PerGlyphOpacityTextRender.cpp
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  }