OSDN Git Service

Add support for Color Emoji (WIP)
authorTakashi Sawanaka <sdottaka@users.sourceforge.net>
Sun, 24 Nov 2019 22:43:43 +0000 (07:43 +0900)
committerTakashi Sawanaka <sdottaka@users.sourceforge.net>
Sun, 24 Nov 2019 22:43:43 +0000 (07:43 +0900)
Add support for Color Emoji (WIP)

63 files changed:
Externals/crystaledit/Sample/SampleStatic.vs2017.vcxproj
Externals/crystaledit/Sample/SampleStatic.vs2017.vcxproj.filters
Externals/crystaledit/Sample/SampleStatic.vs2019.vcxproj
Externals/crystaledit/Sample/SampleStatic.vs2019.vcxproj.filters
Externals/crystaledit/editlib/ccrystalrenderer.h [new file with mode: 0644]
Externals/crystaledit/editlib/ccrystalrendererdirectwrite.cpp [new file with mode: 0644]
Externals/crystaledit/editlib/ccrystalrendererdirectwrite.h [new file with mode: 0644]
Externals/crystaledit/editlib/ccrystalrenderergdi.cpp [new file with mode: 0644]
Externals/crystaledit/editlib/ccrystalrenderergdi.h [new file with mode: 0644]
Externals/crystaledit/editlib/ccrystaltextview.cpp
Externals/crystaledit/editlib/ccrystaltextview.h
Src/GhostTextView.cpp
Src/GhostTextView.h
Src/MainFrm.cpp
Src/Merge.cpp
Src/Merge.rc
Src/Merge.vs2017.vcxproj
Src/Merge.vs2017.vcxproj.filters
Src/Merge.vs2019.vcxproj
Src/Merge.vs2019.vcxproj.filters
Src/Merge2.rc
Src/MergeEditView.cpp
Src/OptionsDef.h
Src/OptionsInit.cpp
Src/PropEditor.cpp
Src/PropEditor.h
Src/res/mg_icons.png [new file with mode: 0644]
Src/resource.h
Translations/WinMerge/Basque.po
Translations/WinMerge/Brazilian.po
Translations/WinMerge/Bulgarian.po
Translations/WinMerge/Catalan.po
Translations/WinMerge/ChineseSimplified.po
Translations/WinMerge/ChineseTraditional.po
Translations/WinMerge/Croatian.po
Translations/WinMerge/Czech.po
Translations/WinMerge/Danish.po
Translations/WinMerge/Dutch.po
Translations/WinMerge/English.pot
Translations/WinMerge/Finnish.po
Translations/WinMerge/French.po
Translations/WinMerge/Galician.po
Translations/WinMerge/German.po
Translations/WinMerge/Greek.po
Translations/WinMerge/Hungarian.po
Translations/WinMerge/Italian.po
Translations/WinMerge/Japanese.po
Translations/WinMerge/Korean.po
Translations/WinMerge/Lithuanian.po
Translations/WinMerge/Norwegian.po
Translations/WinMerge/Persian.po
Translations/WinMerge/Polish.po
Translations/WinMerge/Portuguese.po
Translations/WinMerge/Romanian.po
Translations/WinMerge/Russian.po
Translations/WinMerge/Serbian.po
Translations/WinMerge/Sinhala.po
Translations/WinMerge/Slovak.po
Translations/WinMerge/Slovenian.po
Translations/WinMerge/Spanish.po
Translations/WinMerge/Swedish.po
Translations/WinMerge/Turkish.po
Translations/WinMerge/Ukrainian.po

index 00c41ab..db0d823 100644 (file)
     <ClCompile Include="..\editlib\basic.cpp" />\r
     <ClCompile Include="..\editlib\batch.cpp" />\r
     <ClCompile Include="..\editlib\ccrystaleditview.cpp" />\r
+    <ClCompile Include="..\editlib\ccrystalrendererdirectdraw.cpp" />\r
+    <ClCompile Include="..\editlib\ccrystalrenderergdi.cpp" />\r
     <ClCompile Include="..\editlib\ccrystaltextbuffer.cpp" />\r
     <ClCompile Include="..\editlib\ccrystaltextmarkers.cpp" />\r
     <ClCompile Include="..\editlib\ccrystaltextview.cpp" />\r
   </ItemGroup>\r
   <ItemGroup>\r
     <ClInclude Include="..\editlib\ccrystaleditview.h" />\r
+    <ClInclude Include="..\editlib\ccrystalrenderer.h" />\r
+    <ClInclude Include="..\editlib\ccrystalrendererdirectdraw.h" />\r
+    <ClInclude Include="..\editlib\ccrystalrenderergdi.h" />\r
     <ClInclude Include="..\editlib\ccrystaltextbuffer.h" />\r
     <ClInclude Include="..\editlib\ccrystaltextmarkers.h" />\r
     <ClInclude Include="..\editlib\ccrystaltextview.h" />\r
index ca2a712..803668f 100644 (file)
     <ClCompile Include="..\editlib\icu.cpp">\r
       <Filter>editlib</Filter>\r
     </ClCompile>\r
+    <ClCompile Include="..\editlib\ccrystalrendererdirectdraw.cpp">\r
+      <Filter>editlib</Filter>\r
+    </ClCompile>\r
+    <ClCompile Include="..\editlib\ccrystalrenderergdi.cpp">\r
+      <Filter>editlib</Filter>\r
+    </ClCompile>\r
   </ItemGroup>\r
   <ItemGroup>\r
     <ResourceCompile Include="Sample.rc">\r
     <ClInclude Include="..\editlib\icu.hpp">\r
       <Filter>editlib</Filter>\r
     </ClInclude>\r
+    <ClInclude Include="..\editlib\ccrystalrenderer.h">\r
+      <Filter>editlib</Filter>\r
+    </ClInclude>\r
+    <ClInclude Include="..\editlib\ccrystalrendererdirectdraw.h">\r
+      <Filter>editlib</Filter>\r
+    </ClInclude>\r
+    <ClInclude Include="..\editlib\ccrystalrenderergdi.h">\r
+      <Filter>editlib</Filter>\r
+    </ClInclude>\r
   </ItemGroup>\r
   <ItemGroup>\r
     <Image Include="res\mg_icons.bmp">\r
index 554bc79..7a91d67 100644 (file)
     <ClCompile Include="..\editlib\basic.cpp" />
     <ClCompile Include="..\editlib\batch.cpp" />
     <ClCompile Include="..\editlib\ccrystaleditview.cpp" />
+    <ClCompile Include="..\editlib\ccrystalrendererdirectdraw.cpp" />
+    <ClCompile Include="..\editlib\ccrystalrenderergdi.cpp" />
     <ClCompile Include="..\editlib\ccrystaltextbuffer.cpp" />
     <ClCompile Include="..\editlib\ccrystaltextmarkers.cpp" />
     <ClCompile Include="..\editlib\ccrystaltextview.cpp" />
   </ItemGroup>
   <ItemGroup>
     <ClInclude Include="..\editlib\ccrystaleditview.h" />
+    <ClInclude Include="..\editlib\ccrystalrenderer.h" />
+    <ClInclude Include="..\editlib\ccrystalrendererdirectdraw.h" />
+    <ClInclude Include="..\editlib\ccrystalrenderergdi.h" />
     <ClInclude Include="..\editlib\ccrystaltextbuffer.h" />
     <ClInclude Include="..\editlib\ccrystaltextmarkers.h" />
     <ClInclude Include="..\editlib\ccrystaltextview.h" />
index e9e35d2..05af213 100644 (file)
     <ClCompile Include="..\editlib\icu.cpp">
       <Filter>editlib</Filter>
     </ClCompile>
+    <ClCompile Include="..\editlib\ccrystalrendererdirectdraw.cpp">
+      <Filter>editlib</Filter>
+    </ClCompile>
+    <ClCompile Include="..\editlib\ccrystalrenderergdi.cpp">
+      <Filter>editlib</Filter>
+    </ClCompile>
   </ItemGroup>
   <ItemGroup>
     <ResourceCompile Include="Sample.rc">
     <ClInclude Include="..\editlib\icu.hpp">
       <Filter>editlib</Filter>
     </ClInclude>
+    <ClInclude Include="..\editlib\ccrystalrenderer.h">
+      <Filter>editlib</Filter>
+    </ClInclude>
+    <ClInclude Include="..\editlib\ccrystalrendererdirectdraw.h">
+      <Filter>editlib</Filter>
+    </ClInclude>
+    <ClInclude Include="..\editlib\ccrystalrenderergdi.h">
+      <Filter>editlib</Filter>
+    </ClInclude>
   </ItemGroup>
   <ItemGroup>
     <Image Include="res\mg_icons.bmp">
diff --git a/Externals/crystaledit/editlib/ccrystalrenderer.h b/Externals/crystaledit/editlib/ccrystalrenderer.h
new file mode 100644 (file)
index 0000000..7f4c00d
--- /dev/null
@@ -0,0 +1,46 @@
+/** 
+ * @file  ccrystalrenderer.h
+ *
+ * @brief Declaration file for CCrystalRenderer
+ */
+
+#pragma once
+
+////////////////////////////////////////////////////////////////////////////
+// Forward class declarations
+
+
+////////////////////////////////////////////////////////////////////////////
+// CCrystalRenderer class declaration
+
+
+struct CCrystalRenderer
+{
+       /** @brief Width of icons printed in the margin. */
+       static const UINT MARGIN_ICON_WIDTH = 12;
+       /** @brief Height of icons printed in the margin. */
+       static const UINT MARGIN_ICON_HEIGHT = 12;
+
+       virtual ~CCrystalRenderer() {};
+
+       virtual void BindDC(const CDC& dc, const CRect& rc) = 0;
+       virtual void BeginDraw() = 0;
+       virtual bool EndDraw() = 0;
+       virtual void SetFont(const LOGFONT &lf) = 0;
+       virtual void SwitchFont(bool italic, bool bold) = 0;
+       virtual CSize GetCharWidthHeight() = 0;
+       virtual bool GetCharWidth(unsigned start, unsigned end, int *nWidthArray) = 0;
+       virtual void SetTextColor(COLORREF clr) = 0;
+       virtual void SetBkColor(COLORREF clr) = 0;
+       virtual void DrawText(int x, int y, const CRect &rc, const TCHAR *text, size_t len, const int nWidths[]) = 0;
+       virtual void FillRectangle(const CRect &rc) = 0;
+       virtual void FillSolidRectangle(const CRect &rc, COLORREF color) = 0;
+       virtual void DrawRoundRectangle(int left, int top , int right, int bottom, int width, int height) = 0;
+       virtual void PushAxisAlignedClip(const CRect &rc) = 0;
+       virtual void PopAxisAlignedClip() = 0;
+       virtual void DrawMarginIcon(int x, int y, int iconIndex) = 0;
+       virtual void DrawMarginLineNumber(int x, int y, int number) = 0;
+       virtual void DrawBoundaryLine(int left, int right, int y) = 0;
+       virtual void DrawLineCursor(int left, int right, int y, int height) = 0;
+};
+
diff --git a/Externals/crystaledit/editlib/ccrystalrendererdirectwrite.cpp b/Externals/crystaledit/editlib/ccrystalrendererdirectwrite.cpp
new file mode 100644 (file)
index 0000000..e631ba0
--- /dev/null
@@ -0,0 +1,616 @@
+/**
+ * @file  ccrystalrendererdirectdraw.cpp
+ *
+ * @brief Implementation of the CCrystalRendererDirectWrite class
+ */
+
+#ifdef _WIN64
+#undef WINVER
+#define WINVER 0x0a00
+#include <afxwin.h>
+#include "ccrystalrendererdirectwrite.h"
+#include "resource.h"
+#include <d2d1_3.h>
+#include <dwrite_3.h>
+#include <vector>
+#include <algorithm>
+#include <utility>
+
+struct CustomGlyphRun : public DWRITE_GLYPH_RUN
+{
+       CustomGlyphRun(const DWRITE_GLYPH_RUN& glyphRun, float charWidth = 0, float charHeight = 0)
+               : DWRITE_GLYPH_RUN(glyphRun)
+               , sumCharWidth(0)
+       {
+               float minScale = 1.0f;
+               glyphAdvances = new float[glyphCount];
+               std::vector<DWRITE_GLYPH_METRICS> glyphMetrics(glyphCount);
+               glyphRun.fontFace->GetDesignGlyphMetrics(glyphIndices, glyphCount, glyphMetrics.data(), isSideways);
+               DWRITE_FONT_METRICS fontFaceMetrics;
+               glyphRun.fontFace->GetMetrics(&fontFaceMetrics);
+               for (unsigned i = 0; i < glyphCount; ++i)
+               {
+                       const_cast<float*>(glyphAdvances)[i] = static_cast<int>(charWidth)
+                               * ((charWidth < glyphRun.glyphAdvances[i]) ? 2.0f : 1.0f);
+                       sumCharWidth += glyphAdvances[i];
+                       float scaleX = glyphAdvances[i] / glyphRun.glyphAdvances[i];
+                       if (minScale > scaleX)
+                               minScale = scaleX;
+
+                       float height = (glyphMetrics[i].advanceHeight - glyphMetrics[i].topSideBearing - glyphMetrics[i].bottomSideBearing)
+                               * glyphRun.fontEmSize / fontFaceMetrics.designUnitsPerEm;
+                       float scaleY = charHeight / height;
+                       if (minScale > scaleY)
+                               minScale = scaleY;
+               }
+               fontEmSize *= minScale;
+       }
+
+       CustomGlyphRun(const CustomGlyphRun& other)
+               : DWRITE_GLYPH_RUN(other)
+               , sumCharWidth(other.sumCharWidth)
+       {
+               glyphAdvances = new float[other.glyphCount];
+               for (unsigned i = 0; i < other.glyphCount; ++i)
+                       const_cast<float*>(glyphAdvances)[i] = other.glyphAdvances[i];
+       }
+
+       ~CustomGlyphRun()
+       {
+               delete[] glyphAdvances;
+       }
+
+       float sumCharWidth;
+};
+
+struct DrawGlyphRunParams
+{
+       DrawGlyphRunParams(
+               float fBaselineOriginXOther,
+               float fBaselineOriginYOther,
+               DWRITE_MEASURING_MODE measuringModeOther,
+               const DWRITE_GLYPH_RUN& glyphRunOther)
+               : glyphRun(glyphRunOther)
+               , fBaselineOriginX(fBaselineOriginXOther)
+               , fBaselineOriginY(fBaselineOriginYOther)
+               , measuringMode(measuringModeOther)
+       {
+               glyphRun.glyphAdvances = new FLOAT[glyphRunOther.glyphCount];
+               glyphRun.glyphIndices = new UINT16[glyphRunOther.glyphCount];
+               glyphRun.glyphOffsets = glyphRunOther.glyphOffsets ? new DWRITE_GLYPH_OFFSET[glyphRunOther.glyphCount] : nullptr;
+               glyphRun.fontFace->AddRef();
+               for (unsigned i = 0; i < glyphRunOther.glyphCount; ++i)
+               {
+                       const_cast<float *>(glyphRun.glyphAdvances)[i] = glyphRunOther.glyphAdvances[i];
+                       const_cast<UINT16 *>(glyphRun.glyphIndices)[i] = glyphRunOther.glyphIndices[i];
+                       if (glyphRunOther.glyphOffsets)
+                               const_cast<DWRITE_GLYPH_OFFSET *>(glyphRun.glyphOffsets)[i] = glyphRunOther.glyphOffsets[i];
+               }
+       }
+
+       DrawGlyphRunParams(const DrawGlyphRunParams &other)
+               : glyphRun(other.glyphRun)
+               , fBaselineOriginX(other.fBaselineOriginX)
+               , fBaselineOriginY(other.fBaselineOriginY)
+               , measuringMode(other.measuringMode)
+       {
+               glyphRun.glyphAdvances = new FLOAT[other.glyphRun.glyphCount];
+               glyphRun.glyphIndices = new UINT16[other.glyphRun.glyphCount];
+               glyphRun.glyphOffsets = other.glyphRun.glyphOffsets ? new DWRITE_GLYPH_OFFSET[other.glyphRun.glyphCount] : nullptr;
+               glyphRun.fontFace->AddRef();
+               for (unsigned i = 0; i < other.glyphRun.glyphCount; ++i)
+               {
+                       const_cast<FLOAT *>(glyphRun.glyphAdvances)[i] = other.glyphRun.glyphAdvances[i];
+                       const_cast<UINT16 *>(glyphRun.glyphIndices)[i] = other.glyphRun.glyphIndices[i];
+                       if (other.glyphRun.glyphOffsets)
+                               const_cast<DWRITE_GLYPH_OFFSET *>(glyphRun.glyphOffsets)[i] = other.glyphRun.glyphOffsets[i];
+               }
+       }
+
+       ~DrawGlyphRunParams()
+       {
+               delete glyphRun.glyphAdvances;
+               delete glyphRun.glyphIndices;
+               delete glyphRun.glyphOffsets;
+               glyphRun.fontFace->Release();
+       }
+
+       FLOAT fBaselineOriginX;
+       FLOAT fBaselineOriginY;
+       DWRITE_MEASURING_MODE measuringMode;
+       DWRITE_GLYPH_RUN glyphRun;
+};
+
+class CDrawingContext
+{
+public:
+       CDrawingContext(CRenderTarget* pRenderTarget)
+       : m_pRenderTarget(pRenderTarget)
+       {
+       }
+
+       CRenderTarget* m_pRenderTarget;
+       std::vector<DrawGlyphRunParams> m_drawGlyphRunParams;
+};
+
+class CCustomTextRenderer : public CCmdTarget
+{
+       DECLARE_DYNAMIC(CCustomTextRenderer)
+public:
+       CCustomTextRenderer() = default;
+       virtual ~CCustomTextRenderer() = default;
+       IDWriteTextRenderer* Get();
+public:
+       DECLARE_INTERFACE_MAP()
+       BEGIN_INTERFACE_PART(CustomTextRenderer, IDWriteTextRenderer)
+       // override IDWriteTextRenderer
+       STDMETHOD(DrawGlyphRun)(void*, FLOAT, FLOAT, DWRITE_MEASURING_MODE, const DWRITE_GLYPH_RUN*,
+                       const DWRITE_GLYPH_RUN_DESCRIPTION*, IUnknown*);
+       STDMETHOD(DrawInlineObject)(void*, FLOAT, FLOAT, IDWriteInlineObject*, BOOL, BOOL, IUnknown*);
+       STDMETHOD(DrawStrikethrough)(void*, FLOAT, FLOAT, const DWRITE_STRIKETHROUGH*, IUnknown*);
+       STDMETHOD(DrawUnderline)(void*, FLOAT, FLOAT, const DWRITE_UNDERLINE*, IUnknown*);
+       // override IDWritePixelSnapping
+       STDMETHOD(GetCurrentTransform)(void*, DWRITE_MATRIX*);
+       STDMETHOD(GetPixelsPerDip)(void*, FLOAT*);
+       STDMETHOD(IsPixelSnappingDisabled)(void*, BOOL*);
+       // implementation helpers
+       END_INTERFACE_PART(CustomTextRenderer)
+};
+
+inline IDWriteTextRenderer* CCustomTextRenderer::Get()
+{
+       return &m_xCustomTextRenderer;
+}
+
+IMPLEMENT_DYNAMIC(CCustomTextRenderer, CCmdTarget)
+
+BEGIN_INTERFACE_MAP(CCustomTextRenderer, CCmdTarget)
+       INTERFACE_PART(CCustomTextRenderer, __uuidof(IDWriteTextRenderer), CustomTextRenderer)
+END_INTERFACE_MAP()
+
+STDMETHODIMP CCustomTextRenderer::XCustomTextRenderer::DrawGlyphRun(void* pClientDrawingContext,
+       FLOAT fBaselineOriginX, FLOAT fBaselineOriginY, DWRITE_MEASURING_MODE measuringMode,
+       const DWRITE_GLYPH_RUN* pGlyphRun, const DWRITE_GLYPH_RUN_DESCRIPTION* pGlyphRunDescription,
+       IUnknown* pClientDrawingEffect)
+{
+       CDrawingContext* pDrawingContext = static_cast<CDrawingContext*>(pClientDrawingContext);
+       pDrawingContext->m_drawGlyphRunParams.push_back(
+               DrawGlyphRunParams{fBaselineOriginX, fBaselineOriginY, measuringMode, *pGlyphRun});
+       return S_OK;
+}
+
+STDMETHODIMP CCustomTextRenderer::XCustomTextRenderer::DrawInlineObject(void* pClientDrawingContext,
+       FLOAT fOriginX, FLOAT fOriginY, IDWriteInlineObject* pInlineObject,
+       BOOL bIsSideways, BOOL bIsRightToLeft,
+       IUnknown* pClientDrawingEffect)
+{
+       return E_NOTIMPL;
+}
+
+STDMETHODIMP CCustomTextRenderer::XCustomTextRenderer::DrawStrikethrough(void* pClientDrawingContext,
+       FLOAT fBaselineOriginX, FLOAT fBaselineOriginY, const DWRITE_STRIKETHROUGH* pStrikethrough,
+       IUnknown* pClientDrawingEffect)
+{
+       return E_NOTIMPL;
+}
+
+STDMETHODIMP CCustomTextRenderer::XCustomTextRenderer::DrawUnderline(void* pClientDrawingContext,
+       FLOAT fBaselineOriginX, FLOAT fBaselineOriginY, const DWRITE_UNDERLINE* pUnderline,
+       IUnknown* pClientDrawingEffect)
+{
+       return E_NOTIMPL;
+}
+
+STDMETHODIMP CCustomTextRenderer::XCustomTextRenderer::GetCurrentTransform(void* pClientDrawingContext, DWRITE_MATRIX* pTransform)
+{
+       CDrawingContext* pDrawingContext = static_cast<CDrawingContext*>(pClientDrawingContext);
+       pDrawingContext->m_pRenderTarget->GetTransform((D2D1_MATRIX_3X2_F*)pTransform);
+       return S_OK;
+}
+
+STDMETHODIMP CCustomTextRenderer::XCustomTextRenderer::GetPixelsPerDip(void* pClientDrawingContext, FLOAT* pfPixelsPerDip)
+{
+       CDrawingContext* pDrawingContext = static_cast<CDrawingContext*>(pClientDrawingContext);
+       *pfPixelsPerDip = pDrawingContext->m_pRenderTarget->GetDpi().width / 96.0f;
+       return S_OK;
+}
+
+STDMETHODIMP CCustomTextRenderer::XCustomTextRenderer::IsPixelSnappingDisabled(void* pClientDrawingContext, BOOL* pbIsDisabled)
+{
+       *pbIsDisabled = FALSE;
+       return S_OK;
+}
+
+STDMETHODIMP_(ULONG) CCustomTextRenderer::XCustomTextRenderer::AddRef()
+{
+       METHOD_PROLOGUE(CCustomTextRenderer, CustomTextRenderer);
+       return pThis->ExternalAddRef();
+}
+
+STDMETHODIMP_(ULONG) CCustomTextRenderer::XCustomTextRenderer::Release()
+{
+       METHOD_PROLOGUE(CCustomTextRenderer, CustomTextRenderer);
+       return pThis->ExternalRelease();
+}
+
+STDMETHODIMP CCustomTextRenderer::XCustomTextRenderer::QueryInterface(REFIID iid, LPVOID far* ppvObj)
+{
+       METHOD_PROLOGUE(CCustomTextRenderer, CustomTextRenderer);
+       return pThis->ExternalQueryInterface(&iid, ppvObj);
+}
+
+/////////////////////////////////////////////////////////////////////////////
+// CCrystalRendererDirectWrite construction/destruction
+
+
+CCrystalRendererDirectWrite::CCrystalRendererDirectWrite(int nRenderingMode)
+       : m_pCurrentTextFormat{ nullptr }, m_charSize{}, m_lfBaseFont{}, m_fontAscent(0)
+       , m_pTextBrush(new CD2DSolidColorBrush(&m_renderTarget, D2D1::ColorF(D2D1::ColorF::Black)))
+       , m_pTempBrush(new CD2DSolidColorBrush(&m_renderTarget, D2D1::ColorF(D2D1::ColorF::Black)))
+       , m_pBackgroundBrush(new CD2DSolidColorBrush(&m_renderTarget, D2D1::ColorF(D2D1::ColorF::White)))
+       , m_pTextRenderer(new CCustomTextRenderer())
+{
+  const auto props = D2D1::RenderTargetProperties(
+      D2D1_RENDER_TARGET_TYPE_DEFAULT,
+      D2D1::PixelFormat(DXGI_FORMAT_B8G8R8A8_UNORM, D2D1_ALPHA_MODE_IGNORE),
+      0,
+      0,
+      D2D1_RENDER_TARGET_USAGE_NONE,
+      D2D1_FEATURE_LEVEL_DEFAULT
+  );
+
+  m_renderTarget.Create(props);
+  IDWriteFactory *pWriteFactory = AfxGetD2DState()->GetWriteFactory();
+  CComPtr<IDWriteRenderingParams> pTextRenderingParams, pTextRenderingParams2;
+  pWriteFactory->CreateRenderingParams(&pTextRenderingParams);
+  pWriteFactory->CreateCustomRenderingParams(
+         pTextRenderingParams->GetGamma(),
+         pTextRenderingParams->GetEnhancedContrast(),
+         1.0f,
+         pTextRenderingParams->GetPixelGeometry(),
+         static_cast<DWRITE_RENDERING_MODE>(nRenderingMode),
+         &pTextRenderingParams2);
+  m_renderTarget.SetTextRenderingParams(pTextRenderingParams2);
+  m_renderTarget.SetDpi(CD2DSizeF(96.0F, 96.0F));
+}
+
+CCrystalRendererDirectWrite::~CCrystalRendererDirectWrite ()
+{
+}
+
+void CCrystalRendererDirectWrite::BindDC(const CDC& dc, const CRect& rc)
+{
+       m_renderTarget.BindDC(dc, rc);
+}
+
+void CCrystalRendererDirectWrite::BeginDraw()
+{
+       m_renderTarget.BeginDraw();
+}
+
+bool CCrystalRendererDirectWrite::EndDraw()
+{
+       return (SUCCEEDED(m_renderTarget.EndDraw()));
+}
+
+static D2D1_SIZE_F GetCharWidthHeight(IDWriteTextFormat *pTextFormat)
+{
+       CComPtr<IDWriteTextLayout> pTextLayout;
+       AfxGetD2DState()->GetWriteFactory()->CreateTextLayout(L"W", 1, pTextFormat, 0, 0, &pTextLayout);
+       DWRITE_TEXT_METRICS textMetrics{};
+       pTextLayout->GetMetrics(&textMetrics);
+       return {textMetrics.width, textMetrics.height};
+}
+
+static float GetFontAscent(IDWriteTextFormat* pTextFormat)
+{
+       CComPtr<IDWriteFontCollection> pFontCollection;
+       pTextFormat->GetFontCollection(&pFontCollection);
+       if (pFontCollection)
+       {
+               CComPtr<IDWriteFontFamily> pFontFamily;
+               pFontCollection->GetFontFamily(0, &pFontFamily);
+               if (pFontFamily)
+               {
+                       CComPtr<IDWriteFont> pFont;
+                       pFontFamily->GetFont(0, &pFont);
+                       if (pFont)
+                       {
+                               DWRITE_FONT_METRICS fontMetrics;
+                               pFont->GetMetrics(&fontMetrics);
+                               return fontMetrics.ascent * (pTextFormat->GetFontSize() / fontMetrics.designUnitsPerEm);
+                       }
+               }
+       }
+       return pTextFormat->GetFontSize() * 0.7f;
+}
+
+void CCrystalRendererDirectWrite::SetFont(const LOGFONT &lf)
+{
+       m_lfBaseFont = lf;
+       for (int nIndex = 0; nIndex < 4; ++nIndex)
+       {
+               bool bold = (nIndex & 1) != 0;
+               bool italic = (nIndex & 2) != 0;
+               m_pTextFormat[nIndex].reset(new CD2DTextFormat(&m_renderTarget,
+                       lf.lfFaceName[0] ? lf.lfFaceName : L"Courier New",
+                       static_cast<FLOAT>(abs(lf.lfHeight == 0 ? 11 : lf.lfHeight)),
+                       bold ? DWRITE_FONT_WEIGHT_BOLD : DWRITE_FONT_WEIGHT_NORMAL,
+                       italic ? DWRITE_FONT_STYLE_ITALIC : DWRITE_FONT_STYLE_NORMAL));
+               IDWriteTextFormat *pTextFormat = m_pTextFormat[nIndex]->Get();
+               pTextFormat->SetTextAlignment(DWRITE_TEXT_ALIGNMENT_LEADING);
+               pTextFormat->SetParagraphAlignment(DWRITE_PARAGRAPH_ALIGNMENT_NEAR);
+               pTextFormat->SetWordWrapping(DWRITE_WORD_WRAPPING_NO_WRAP);
+       }
+       m_pCurrentTextFormat = m_pTextFormat[0].get();
+       m_pFont.reset();
+       m_charSize = ::GetCharWidthHeight(m_pTextFormat[3]->Get());
+       m_fontAscent = ::GetFontAscent(m_pTextFormat[3]->Get());
+}
+
+void CCrystalRendererDirectWrite::SwitchFont(bool italic, bool bold)
+{
+       int nIndex = 0;
+       if (bold)
+               nIndex |= 1;
+       if (italic)
+               nIndex |= 2;
+       m_pCurrentTextFormat = m_pTextFormat[nIndex].get();
+}
+
+CSize CCrystalRendererDirectWrite::GetCharWidthHeight()
+{
+       if (m_pTextFormat[3] == nullptr)
+               SetFont(m_lfBaseFont);
+       return CSize(static_cast<int>(m_charSize.width), static_cast<int>(m_charSize.height));
+}
+
+bool CCrystalRendererDirectWrite::GetCharWidth(unsigned start, unsigned end, int * nWidthArray)
+{
+       if (!m_pFont)
+       {
+               m_pFont.reset(new CFont());
+               m_pFont->CreateFontIndirect(&m_lfBaseFont);
+       }
+       CClientDC dc (CWnd::GetDesktopWindow());
+       CFont *pOldFont = dc.SelectObject(m_pFont.get());
+       bool succeeded = !!GetCharWidth32(dc.m_hDC, start, end, nWidthArray);
+       dc.SelectObject(pOldFont);
+       return succeeded;
+}
+
+void CCrystalRendererDirectWrite::SetTextColor(COLORREF clr)
+{
+       m_pTextBrush->SetColor(ColorRefToColorF(clr));
+}
+
+void CCrystalRendererDirectWrite::SetBkColor(COLORREF clr)
+{
+       m_pBackgroundBrush->SetColor(ColorRefToColorF(clr));
+}
+
+void CCrystalRendererDirectWrite::FillRectangle(const CRect &rc)
+{
+       m_renderTarget.FillRectangle(CD2DRectF(rc), m_pBackgroundBrush.get());
+}
+
+void CCrystalRendererDirectWrite::FillSolidRectangle(const CRect &rc, COLORREF color)
+{
+       m_pTempBrush->SetColor(ColorRefToColorF(color));
+       m_renderTarget.FillRectangle(CD2DRectF(rc), m_pTempBrush.get());
+}
+
+void CCrystalRendererDirectWrite::DrawRoundRectangle(int left, int top, int right, int bottom, int width, int height)
+{
+       m_renderTarget.DrawRoundedRectangle(
+               D2D1_ROUNDED_RECT{ {static_cast<float>(left), static_cast<float>(top), static_cast<float>(right), static_cast<float>(bottom)},
+               static_cast<float>(width), static_cast<float>(height) }, m_pTextBrush.get());
+}
+
+void CCrystalRendererDirectWrite::PushAxisAlignedClip(const CRect & rc)
+{
+       m_renderTarget.PushAxisAlignedClip(rc);
+}
+
+void CCrystalRendererDirectWrite::PopAxisAlignedClip()
+{
+       m_renderTarget.PopAxisAlignedClip();
+}
+
+void CCrystalRendererDirectWrite::DrawMarginIcon(int x, int y, int iconIndex)
+{
+       if (!m_pIconBitmap)
+       {
+               m_pIconBitmap.reset(new CD2DBitmap(nullptr, static_cast<UINT>(IDR_MARGIN_ICONS_PNG), L"IMAGE"));
+               m_pIconBitmap->Create(&m_renderTarget);
+       }
+       auto size = m_pIconBitmap->GetPixelSize();
+       CD2DRectF rcSrc{static_cast<float>(iconIndex * MARGIN_ICON_WIDTH), 0.0f, static_cast<float>((iconIndex + 1) * MARGIN_ICON_WIDTH), static_cast<float>(MARGIN_ICON_HEIGHT)};
+       m_renderTarget.DrawBitmap(m_pIconBitmap.get(),
+               { static_cast<float>(x), static_cast<float>(y),
+                static_cast<float>(x + MARGIN_ICON_WIDTH), static_cast<float>(y + MARGIN_ICON_HEIGHT) },
+               1.0f, D2D1_BITMAP_INTERPOLATION_MODE_LINEAR, &rcSrc);
+}
+
+void CCrystalRendererDirectWrite::DrawMarginLineNumber(int x, int y, int number)
+{
+       TCHAR szNumbers[32];
+       int len = wsprintf(szNumbers, _T("%d"), number);
+       m_renderTarget.DrawText(szNumbers,
+               { static_cast<float>(x) - m_charSize.width * len - 4, static_cast<float>(y),
+                 static_cast<float>(x), static_cast<float>(y + m_charSize.height) },
+               m_pTextBrush.get(), m_pTextFormat[0].get());
+}
+
+void CCrystalRendererDirectWrite::DrawBoundaryLine(int left, int right, int y)
+{
+       m_pTempBrush->SetColor(ColorRefToColorF(0));
+       m_renderTarget.DrawLine(
+               { static_cast<float>(left), static_cast<float>(y) },
+               { static_cast<float>(right), static_cast<float>(y) }, m_pTempBrush.get());
+}
+
+void CCrystalRendererDirectWrite::DrawLineCursor(int left, int right, int y, int height)
+{
+       m_pTempBrush->SetColor(ColorRefToColorF(0));
+       m_pTempBrush->SetOpacity(0.5f);
+       m_renderTarget.DrawLine(
+               { static_cast<float>(left), static_cast<float>(y) },
+               { static_cast<float>(right), static_cast<float>(y) },
+               m_pTempBrush.get(), static_cast<float>(1));
+       m_pTempBrush->SetOpacity(1.0f);
+}
+
+void CCrystalRendererDirectWrite::DrawText(int x, int y, const CRect &rc, const TCHAR *text, size_t len, const int nWidths[])
+{
+       CD2DRectF rcF(rc);
+
+       m_renderTarget.PushAxisAlignedClip(rcF);
+
+       m_renderTarget.FillRectangle(rcF, m_pBackgroundBrush.get());
+
+       D2D1_COLOR_F textColor = m_pTextBrush->GetColor();
+       D2D1_COLOR_F backColor = m_pBackgroundBrush->GetColor();
+       if (memcmp(&textColor, &backColor, sizeof(D2D1_COLOR_F)) != 0)
+       {
+               CDrawingContext drawingContext{ &m_renderTarget };
+               CComPtr<IDWriteTextLayout> pTextLayout;
+               AfxGetD2DState()->GetWriteFactory()->CreateTextLayout(text, static_cast<unsigned>(len),
+                       *m_pCurrentTextFormat,
+                       rcF.right - rcF.left, rcF.bottom - rcF.top, &pTextLayout);
+               pTextLayout->Draw(&drawingContext, m_pTextRenderer->Get(), 0, 0);
+
+               std::vector<std::pair<size_t, float>> orders;
+               for (size_t i = 0; i < drawingContext.m_drawGlyphRunParams.size(); ++i)
+                       orders.emplace_back(i, drawingContext.m_drawGlyphRunParams[i].fBaselineOriginX);
+               std::stable_sort(orders.begin(), orders.end(),
+                       [](const std::pair<size_t, float>& a, const std::pair<size_t, float>& b)
+                       { return a.second < b.second; });
+               float fBaselineOriginX = static_cast<float>(x);
+               float fBaselineOriginY = y + m_fontAscent;
+               for (size_t i = 0; i < orders.size(); ++i)
+               {
+                       DrawGlyphRunParams& param = drawingContext.m_drawGlyphRunParams[orders[i].first];
+                       CustomGlyphRun customGlyphRun2(param.glyphRun, m_charSize.width, m_charSize.height);
+                       DrawGlyphRun(&drawingContext,
+                               (customGlyphRun2.bidiLevel & 1) ? (fBaselineOriginX + customGlyphRun2.sumCharWidth) : fBaselineOriginX,
+                               fBaselineOriginY,
+                               param.measuringMode, &customGlyphRun2, nullptr, nullptr);
+                       fBaselineOriginX += customGlyphRun2.sumCharWidth;
+               }
+       }
+       m_renderTarget.PopAxisAlignedClip();
+}
+
+STDMETHODIMP CCrystalRendererDirectWrite::DrawGlyphRun(void* pClientDrawingContext,
+       FLOAT fBaselineOriginX, FLOAT fBaselineOriginY, DWRITE_MEASURING_MODE measuringMode,
+       const DWRITE_GLYPH_RUN* pGlyphRun, const DWRITE_GLYPH_RUN_DESCRIPTION* pGlyphRunDescription,
+       IUnknown* pClientDrawingEffect)
+{
+       IDWriteFactory *pWriteFactory = AfxGetD2DState()->GetWriteFactory();
+       CComQIPtr<IDWriteFactory4> pWriteFactory4(pWriteFactory);
+       CComQIPtr<ID2D1DeviceContext4> pD2dDeviceContext(m_renderTarget);
+       CComPtr<IDWriteColorGlyphRunEnumerator1> glyphRunEnumerator;
+
+       DWRITE_GLYPH_IMAGE_FORMATS supportedFormats = static_cast<DWRITE_GLYPH_IMAGE_FORMATS>(
+               static_cast<int>(DWRITE_GLYPH_IMAGE_FORMATS_TRUETYPE) |
+               static_cast<int>(DWRITE_GLYPH_IMAGE_FORMATS_CFF) |
+               static_cast<int>(DWRITE_GLYPH_IMAGE_FORMATS_COLR) |
+               static_cast<int>(DWRITE_GLYPH_IMAGE_FORMATS_SVG) |
+               static_cast<int>(DWRITE_GLYPH_IMAGE_FORMATS_PNG) |
+               static_cast<int>(DWRITE_GLYPH_IMAGE_FORMATS_JPEG)|
+               static_cast<int>(DWRITE_GLYPH_IMAGE_FORMATS_TIFF) |
+               static_cast<int>(DWRITE_GLYPH_IMAGE_FORMATS_PREMULTIPLIED_B8G8R8A8)
+       );
+
+       if (!pWriteFactory4)
+       {
+               m_renderTarget.DrawGlyphRun(
+                       {fBaselineOriginX, fBaselineOriginY},
+                       *pGlyphRun, m_pTextBrush.get(), measuringMode);
+               return S_OK;
+       }
+
+       HRESULT hr = pWriteFactory4->TranslateColorGlyphRun(
+               {fBaselineOriginX, fBaselineOriginY},
+               pGlyphRun, pGlyphRunDescription, supportedFormats,
+               measuringMode, nullptr, 0, &glyphRunEnumerator);
+       if (hr == DWRITE_E_NOCOLOR)
+       {
+               m_renderTarget.DrawGlyphRun(
+                       {fBaselineOriginX, fBaselineOriginY},
+                       *pGlyphRun, m_pTextBrush.get(), measuringMode);
+               return S_OK;
+       }
+
+       for (;;)
+       {
+               BOOL haveRun;
+               glyphRunEnumerator->MoveNext(&haveRun);
+               if (!haveRun)
+                       break;
+
+               DWRITE_COLOR_GLYPH_RUN1 const* colorRun;
+               glyphRunEnumerator->GetCurrentRun(&colorRun);
+
+               D2D1_POINT_2F currentBaselineOrigin = D2D1::Point2F(
+                       colorRun->baselineOriginX,
+                       colorRun->baselineOriginY
+               );
+
+               switch (colorRun->glyphImageFormat)
+               {
+               case DWRITE_GLYPH_IMAGE_FORMATS_PNG:
+               case DWRITE_GLYPH_IMAGE_FORMATS_JPEG:
+               case DWRITE_GLYPH_IMAGE_FORMATS_TIFF:
+               case DWRITE_GLYPH_IMAGE_FORMATS_PREMULTIPLIED_B8G8R8A8:
+               {
+                       // This run is bitmap glyphs. Use Direct2D to draw them.
+                       pD2dDeviceContext->DrawColorBitmapGlyphRun(
+                               colorRun->glyphImageFormat, currentBaselineOrigin,
+                               &colorRun->glyphRun, measuringMode);
+               }
+               break;
+
+               case DWRITE_GLYPH_IMAGE_FORMATS_SVG:
+               {
+                       // This run is SVG glyphs. Use Direct2D to draw them.
+                       pD2dDeviceContext->DrawSvgGlyphRun(
+                               currentBaselineOrigin, &colorRun->glyphRun,
+                               m_pTextBrush->Get(),
+                               nullptr, 0, measuringMode);
+               }
+               break;
+
+               case DWRITE_GLYPH_IMAGE_FORMATS_TRUETYPE:
+               case DWRITE_GLYPH_IMAGE_FORMATS_CFF:
+               case DWRITE_GLYPH_IMAGE_FORMATS_COLR:
+               default:
+               {
+                       // This run is solid-color outlines, either from non-color
+                       // glyphs or from COLR glyph layers. Use Direct2D to draw them.
+
+                       ID2D1Brush* layerBrush;
+                       if (colorRun->paletteIndex == 0xFFFF)
+                       {
+                               // This run uses the current text color.
+                               layerBrush = m_pTextBrush->Get();
+                       }
+                       else
+                       {
+                               // This run specifies its own color.
+                               m_pTempBrush->SetColor(colorRun->runColor);
+                               layerBrush = m_pTempBrush->Get();
+                       }
+
+                       // Draw the run with the selected color.
+                       pD2dDeviceContext->DrawGlyphRun(currentBaselineOrigin, &colorRun->glyphRun,
+                               colorRun->glyphRunDescription, layerBrush, measuringMode);
+               }
+               break;
+               }
+       }
+       return S_OK;
+}
+
+#endif
diff --git a/Externals/crystaledit/editlib/ccrystalrendererdirectwrite.h b/Externals/crystaledit/editlib/ccrystalrendererdirectwrite.h
new file mode 100644 (file)
index 0000000..b1e7e9c
--- /dev/null
@@ -0,0 +1,69 @@
+/** 
+ * @file  ccrystalrendererdirectdraw.h
+ *
+ * @brief Declaration file for CCrystalRendererDirectWrite
+ */
+#include "ccrystalrenderer.h"
+#include <memory>
+#include <array>
+#include <afxwin.h>
+
+#pragma once
+
+////////////////////////////////////////////////////////////////////////////
+// Forward class declarations
+class CCustomTextRenderer;
+
+////////////////////////////////////////////////////////////////////////////
+// CCrystalRendererDirectWrite class declaration
+
+class CCrystalRendererDirectWrite : public CCrystalRenderer
+{
+public:
+       CCrystalRendererDirectWrite(int nRenderingMode = 1);
+       virtual ~CCrystalRendererDirectWrite();
+
+       virtual void BindDC(const CDC& dc, const CRect& rc);
+       virtual void BeginDraw();
+       virtual bool EndDraw();
+       virtual void SetFont(const LOGFONT &lf);
+       virtual void SwitchFont(bool italic, bool bold);
+       virtual CSize GetCharWidthHeight();
+       virtual bool GetCharWidth(unsigned start, unsigned end, int *nWidthArray);
+       virtual void SetTextColor(COLORREF clr);
+       virtual void SetBkColor(COLORREF clr);
+       virtual void DrawText(int x, int y, const CRect &rc, const TCHAR *text, size_t len, const int nWidths[]);
+       virtual void FillRectangle(const CRect &rc);
+       virtual void FillSolidRectangle(const CRect &rc, COLORREF color);
+       virtual void DrawRoundRectangle(int left, int top , int right, int bottom, int width, int height);
+       virtual void PushAxisAlignedClip(const CRect &rc);
+       virtual void PopAxisAlignedClip();
+       virtual void DrawMarginIcon(int x, int y, int iconIndex);
+       virtual void DrawMarginLineNumber(int x, int y, int number);
+       virtual void DrawBoundaryLine(int left, int right, int y);
+       virtual void DrawLineCursor(int left, int right, int y, int height);
+
+private:
+       STDMETHODIMP DrawGlyphRun(void* pClientDrawingContext,
+               FLOAT fBaselineOriginX, FLOAT fBaselineOriginY, DWRITE_MEASURING_MODE measuringMode,
+               const DWRITE_GLYPH_RUN* pGlyphRun, const DWRITE_GLYPH_RUN_DESCRIPTION* pGlyphRunDescription,
+               IUnknown* pClientDrawingEffect);
+
+       D2D1::ColorF ColorRefToColorF(COLORREF cr) const
+       {
+               return D2D1::ColorF(GetRValue(cr) / 255.0f, GetGValue(cr) / 255.0f, GetBValue(cr) / 255.0f);
+       };
+
+       CDCRenderTarget m_renderTarget;
+       std::array<std::unique_ptr<CD2DTextFormat>, 4> m_pTextFormat;
+       CD2DTextFormat *m_pCurrentTextFormat;
+       std::unique_ptr<CD2DSolidColorBrush> m_pTextBrush;
+       std::unique_ptr<CD2DSolidColorBrush> m_pTempBrush;
+       std::unique_ptr<CD2DSolidColorBrush> m_pBackgroundBrush;
+       std::unique_ptr<CCustomTextRenderer> m_pTextRenderer;
+       std::unique_ptr<CD2DBitmap> m_pIconBitmap;
+       LOGFONT m_lfBaseFont;
+       std::unique_ptr<CFont> m_pFont;
+       D2D1_SIZE_F m_charSize;
+       float m_fontAscent;
+};
diff --git a/Externals/crystaledit/editlib/ccrystalrenderergdi.cpp b/Externals/crystaledit/editlib/ccrystalrenderergdi.cpp
new file mode 100644 (file)
index 0000000..7b6cb27
--- /dev/null
@@ -0,0 +1,192 @@
+/**
+ * @file  ccrystalrenderergdi.cpp
+ *
+ * @brief Implementation of the CCrystalRendererGDI class
+ */
+
+#include "StdAfx.h"
+#include "ccrystalrenderergdi.h"
+
+CImageList* CCrystalRendererGDI::s_pIcons = nullptr;
+
+/////////////////////////////////////////////////////////////////////////////
+// CCrystalRendererGDI construction/destruction
+
+CCrystalRendererGDI::CCrystalRendererGDI() : m_pDC(nullptr), m_lfBaseFont{}
+{
+}
+
+CCrystalRendererGDI::~CCrystalRendererGDI ()
+{
+}
+
+void CCrystalRendererGDI::BindDC(const CDC& dc, const CRect& rc)
+{
+       m_pDC = const_cast<CDC *>(&dc);
+}
+
+void CCrystalRendererGDI::BeginDraw()
+{
+}
+
+bool CCrystalRendererGDI::EndDraw()
+{
+       return true;
+}
+
+void CCrystalRendererGDI::SetFont(const LOGFONT &lf)
+{
+       m_lfBaseFont = lf;
+       for (int nIndex = 0; nIndex < 4; ++nIndex)
+       {
+               bool bold = (nIndex & 1) != 0;
+               bool italic = (nIndex & 2) != 0;
+               m_apFonts[nIndex].reset(new CFont());
+               if (!m_lfBaseFont.lfHeight)
+               {
+                       CClientDC dc (CWnd::GetDesktopWindow());
+                       m_lfBaseFont.lfHeight = -MulDiv (11, dc.GetDeviceCaps (LOGPIXELSY), 72);
+               }
+               m_lfBaseFont.lfWeight = bold ? FW_BOLD : FW_NORMAL;
+               m_lfBaseFont.lfItalic = (BYTE) italic;
+               if (!m_apFonts[nIndex]->CreateFontIndirect(&m_lfBaseFont))
+                       m_apFonts[nIndex].reset(nullptr);
+       }
+}
+
+void CCrystalRendererGDI::SwitchFont(bool italic, bool bold)
+{
+       int nIndex = 0;
+       if (bold)
+               nIndex |= 1;
+       if (italic)
+               nIndex |= 2;
+       m_pDC->SelectObject(m_apFonts[nIndex].get());
+}
+
+CSize CCrystalRendererGDI::GetCharWidthHeight()
+{
+       if (!m_apFonts[3])
+               SetFont(m_lfBaseFont);
+       CClientDC dc (CWnd::GetDesktopWindow());
+       CFont *pOldFont = dc.SelectObject(m_apFonts[3].get());
+       CSize sizeItalicBold = dc.GetTextExtent(_T("X"));
+       dc.SelectObject(m_apFonts[0].get());
+       CSize sizeNormal = dc.GetTextExtent(_T("X"));
+       dc.SelectObject(pOldFont);
+       return CSize{ (std::max)(sizeNormal.cx, sizeItalicBold.cx), (std::max)(sizeNormal.cy, sizeItalicBold.cy)};
+}
+
+bool CCrystalRendererGDI::GetCharWidth(unsigned start, unsigned end, int * nWidthArray)
+{
+       if (!m_apFonts[3])
+               SetFont(m_lfBaseFont);
+       CClientDC dc (CWnd::GetDesktopWindow());
+       CFont *pOldFont = dc.SelectObject(m_apFonts[3].get());
+       bool succeeded = !!GetCharWidth32(dc.m_hDC, start, end, nWidthArray);
+       dc.SelectObject(pOldFont);
+       return succeeded;
+}
+
+void CCrystalRendererGDI::SetTextColor(COLORREF clr)
+{
+       m_pDC->SetTextColor(clr);
+}
+
+void CCrystalRendererGDI::SetBkColor(COLORREF clr)
+{
+       m_pDC->SetBkColor(clr);
+}
+
+void CCrystalRendererGDI::FillRectangle(const CRect &rc)
+{
+       m_pDC->FillSolidRect(&rc, m_pDC->GetBkColor());
+}
+
+void CCrystalRendererGDI::FillSolidRectangle(const CRect &rc, COLORREF color)
+{
+       m_pDC->FillSolidRect(&rc, color);
+}
+
+void CCrystalRendererGDI::DrawRoundRectangle(int left, int top, int right, int bottom, int width, int height)
+{
+       HGDIOBJ hBrush = ::GetStockObject(NULL_BRUSH);
+       hBrush = ::SelectObject(m_pDC->m_hDC, hBrush);
+       HGDIOBJ hPen = ::CreatePen(PS_SOLID, 1, ::GetTextColor(m_pDC->m_hDC));
+       hPen = ::SelectObject(m_pDC->m_hDC, hPen);
+
+       m_pDC->RoundRect(left, top, right, bottom, width, height);
+
+       hPen = ::SelectObject(m_pDC->m_hDC, hPen);
+       ::DeleteObject(hPen);
+       hBrush = ::SelectObject(m_pDC->m_hDC, hBrush);
+}
+
+void CCrystalRendererGDI::PushAxisAlignedClip(const CRect & rc)
+{
+       m_pDC->SaveDC();
+       m_pDC->IntersectClipRect(&rc);
+}
+
+void CCrystalRendererGDI::PopAxisAlignedClip()
+{
+       m_pDC->RestoreDC(-1);
+}
+
+void CCrystalRendererGDI::DrawMarginIcon(int x, int y, int iconIndex)
+{
+       if (s_pIcons == nullptr)
+       {
+               s_pIcons = new CImageList;
+               VERIFY(s_pIcons->Create(MARGIN_ICON_WIDTH, MARGIN_ICON_HEIGHT,
+                       ILC_COLOR32 | ILC_MASK, 0, 1));
+               CBitmap bmp;
+               bmp.LoadBitmap(IDR_MARGIN_ICONS);
+               s_pIcons->Add(&bmp, RGB(255, 255, 255));
+       }
+       if (iconIndex >= 0)
+       {
+               CPoint pt(x, y);
+               VERIFY(s_pIcons->Draw(m_pDC, iconIndex, pt, ILD_TRANSPARENT));
+       }
+}
+
+void CCrystalRendererGDI::DrawMarginLineNumber(int x, int y, int number)
+{
+       CFont *pOldFont = m_pDC->SelectObject(m_apFonts[0].get());
+       TCHAR szNumbers[32];
+       int len = wsprintf(szNumbers, _T("%d"), number);
+       UINT uiOldAlign = m_pDC->SetTextAlign(TA_RIGHT);
+       m_pDC->TextOut(x - (m_pDC->IsPrinting() ? 0 : 4), y, szNumbers, len);
+       m_pDC->SetTextAlign(uiOldAlign);
+       m_pDC->SelectObject(pOldFont);
+}
+
+void CCrystalRendererGDI::DrawBoundaryLine(int left, int right, int y)
+{
+       CPen *pOldPen = (CPen *)m_pDC->SelectStockObject(BLACK_PEN);
+       m_pDC->MoveTo(left, y);
+       m_pDC->LineTo(right, y);
+       m_pDC->SelectObject(pOldPen);
+}
+
+void CCrystalRendererGDI::DrawLineCursor(int left, int right, int y, int height)
+{
+       CDC  dcMem;
+       dcMem.CreateCompatibleDC(m_pDC);
+       CBitmap bitmap;
+       bitmap.CreateCompatibleBitmap(m_pDC, right - left, height);
+       CBitmap *pOldBitmap = dcMem.SelectObject(&bitmap);
+       dcMem.SetBkColor(RGB(0, 255, 0));
+       BLENDFUNCTION blend = { 0 };
+       blend.BlendOp = AC_SRC_OVER;
+       blend.SourceConstantAlpha = 24;
+       m_pDC->AlphaBlend(left, y, right - left, height, &dcMem, 0, 0, right - left, height, blend);
+       dcMem.SelectObject(pOldBitmap);
+}
+
+void CCrystalRendererGDI::DrawText(int x, int y, const CRect &rc, const TCHAR *text, size_t len, const int nWidths[])
+{
+       m_pDC->ExtTextOut(x, y, ETO_CLIPPED | ETO_OPAQUE, &rc, text, static_cast<UINT>(len), const_cast<int *>(nWidths));
+}
+
diff --git a/Externals/crystaledit/editlib/ccrystalrenderergdi.h b/Externals/crystaledit/editlib/ccrystalrenderergdi.h
new file mode 100644 (file)
index 0000000..f3ee5f1
--- /dev/null
@@ -0,0 +1,50 @@
+/** 
+ * @file  ccrystalrenderergdi.h
+ *
+ * @brief Declaration file for CCrystalRendererGDI
+ */
+#include "ccrystalrenderer.h"
+#include <memory>
+
+#pragma once
+
+////////////////////////////////////////////////////////////////////////////
+// Forward class declarations
+
+
+////////////////////////////////////////////////////////////////////////////
+// CCrystalRendererGDI class declaration
+
+
+class CCrystalRendererGDI : public CCrystalRenderer
+{
+public:
+       CCrystalRendererGDI();
+       virtual ~CCrystalRendererGDI();
+
+       virtual void BindDC(const CDC& dc, const CRect& rc);
+       virtual void BeginDraw();
+       virtual bool EndDraw();
+       virtual void SetFont(const LOGFONT &lf);
+       virtual void SwitchFont(bool italic, bool bold);
+       virtual CSize GetCharWidthHeight();
+       virtual bool GetCharWidth(unsigned start, unsigned end, int *nWidthArray);
+       virtual void SetTextColor(COLORREF clr);
+       virtual void SetBkColor(COLORREF clr);
+       virtual void DrawText(int x, int y, const CRect &rc, const TCHAR *text, size_t len, const int nWidths[]);
+       virtual void FillRectangle(const CRect &rc);
+       virtual void FillSolidRectangle(const CRect &rc, COLORREF color);
+       virtual void DrawRoundRectangle(int left, int top , int right, int bottom, int width, int height);
+       virtual void PushAxisAlignedClip(const CRect &rc);
+       virtual void PopAxisAlignedClip();
+       virtual void DrawMarginIcon(int x, int y, int iconIndex);
+       virtual void DrawMarginLineNumber(int x, int y, int number);
+       virtual void DrawBoundaryLine(int left, int right, int y);
+       virtual void DrawLineCursor(int left, int right, int y, int height);
+
+private:
+       CDC *m_pDC;
+       LOGFONT m_lfBaseFont;
+    std::array<std::unique_ptr<CFont>, 4> m_apFonts;
+       static CImageList *s_pIcons;
+};
index be9f38c..1de4378 100644 (file)
 #include "string_util.h"
 #include "wcwidth.h"
 #include "icu.hpp"
+#include "ccrystalrendererdirectwrite.h"
+#include "ccrystalrenderergdi.h"
 
 using std::vector;
 using CrystalLineParser::TEXTBLOCK;
@@ -165,6 +167,7 @@ LOGFONT CCrystalTextView::m_LogFont;
 IMPLEMENT_DYNCREATE (CCrystalTextView, CView)
 
 HINSTANCE CCrystalTextView::s_hResourceInst = nullptr;
+CCrystalTextView::RENDERING_MODE CCrystalTextView::s_nRenderingModeDefault = RENDERING_MODE_GDI;
 
 static ptrdiff_t FindStringHelper(LPCTSTR pszLineBegin, LPCTSTR pszFindWhere, LPCTSTR pszFindWhat, DWORD dwFlags, int &nLen, RxNode *&rxnode, RxMatchRes *rxmatch);
 
@@ -535,8 +538,6 @@ CCrystalTextView::CCrystalTextView ()
 , m_bRememberLastPos(false)
 , m_pColors(nullptr)
 , m_nLastLineIndexCalculatedSubLineIndex(-1)
-, m_pIcons(nullptr)
-, m_apFonts{}
 , m_hAccel(nullptr)
 , m_pTextBuffer(nullptr)
 , m_pCacheBitmap(nullptr)
@@ -592,7 +593,17 @@ CCrystalTextView::CCrystalTextView ()
 , m_bIncrementalSearchBackward(false)
 , m_bIncrementalFound(false)
 , m_rxmatch{}
+, m_nRenderingMode(s_nRenderingModeDefault)
 {
+#ifdef _WIN64
+  if (m_nRenderingMode == RENDERING_MODE_GDI)
+         m_pCrystalRenderer.reset(new CCrystalRendererGDI());
+  else
+         m_pCrystalRenderer.reset(new CCrystalRendererDirectWrite(m_nRenderingMode));
+#else
+  m_pCrystalRenderer.reset(new CCrystalRendererGDI());
+#endif
+
   m_panSubLines->SetSize( 0, 4096 );
   m_panSubLineIndexCache->SetSize( 0, 4096 );
 
@@ -652,7 +663,6 @@ CCrystalTextView::~CCrystalTextView ()
   ASSERT(m_pnActualLineLength != nullptr);
   delete m_pnActualLineLength;
   m_pnActualLineLength = nullptr;
-  delete m_pIcons;
   if (m_pMarkers != nullptr)
       m_pMarkers->DeleteView(this);
 }
@@ -1059,8 +1069,9 @@ ExpandChars (LPCTSTR pszChars, int nOffset, int nCount, CString & line, int nAct
  * @note In ANSI build, this routine is buggy for multibytes or double-width characters
  */
 void CCrystalTextView::
-DrawLineHelperImpl (CDC * pdc, CPoint & ptOrigin, const CRect & rcClip,
-                    int nColorIndex, int nBgColorIndex, COLORREF crText, COLORREF crBkgnd, LPCTSTR pszChars, int nOffset, int nCount, int &nActualOffset)
+DrawLineHelperImpl (CPoint & ptOrigin, const CRect & rcClip,
+ int nColorIndex,
+                    int nBgColorIndex, COLORREF crText, COLORREF crBkgnd, LPCTSTR pszChars, int nOffset, int nCount, int &nActualOffset)
 {
   ASSERT (nCount >= 0);
   if (nCount > 0)
@@ -1153,48 +1164,37 @@ DrawLineHelperImpl (CDC * pdc, CPoint & ptOrigin, const CRect & rcClip,
               if (ptOrigin.x + nSumWidth > rcClip.left)
                 {
                   if (crText == CLR_NONE || nColorIndex & COLORINDEX_APPLYFORCE)
-                    pdc->SetTextColor(GetColor(nColorIndex));
+                    m_pCrystalRenderer->SetTextColor(GetColor(nColorIndex));
                   else
-                    pdc->SetTextColor(crText);
+                    m_pCrystalRenderer->SetTextColor(crText);
                   if (crBkgnd == CLR_NONE || nBgColorIndex & COLORINDEX_APPLYFORCE)
-                    pdc->SetBkColor(GetColor(nBgColorIndex));
+                    m_pCrystalRenderer->SetBkColor(GetColor(nBgColorIndex));
                   else
-                    pdc->SetBkColor(crBkgnd);
+                    m_pCrystalRenderer->SetBkColor(crBkgnd);
 
-                  pdc->SelectObject(GetFont(GetItalic(nColorIndex),
-                      GetBold(nColorIndex)));
+                  m_pCrystalRenderer->SwitchFont(GetItalic(nColorIndex), GetBold(nColorIndex));
                   // we are sure to have less than 4095 characters because all the chars are visible
                   RECT rcIntersect;
                   RECT rcTextBlock = {ptOrigin.x, ptOrigin.y, ptOrigin.x + nSumWidth + 2, ptOrigin.y + nLineHeight};
                   IntersectRect(&rcIntersect, &rcClip, &rcTextBlock);
-                  VERIFY(pdc->ExtTextOut(ptOrigin.x, ptOrigin.y, ETO_CLIPPED | ETO_OPAQUE,
-                      &rcIntersect, LPCTSTR(line) + ibegin, nCount1, &nWidths[0]));
+                                 m_pCrystalRenderer->DrawText(ptOrigin.x, ptOrigin.y, rcIntersect, LPCTSTR(line) + ibegin, nCount1, &nWidths[0]);
                   if (bdisphex)
                     {
                      // Draw rounded rectangles around control characters
-                     pdc->SaveDC();
-                     pdc->IntersectClipRect(&rcClip);
-                     HDC hDC = pdc->m_hDC;
-                     HGDIOBJ hBrush = ::GetStockObject(NULL_BRUSH);
-                     hBrush = ::SelectObject(hDC, hBrush);
-                     HGDIOBJ hPen = ::CreatePen(PS_SOLID, 1, ::GetTextColor(hDC));
-                     hPen = ::SelectObject(hDC, hPen);
+                     m_pCrystalRenderer->PushAxisAlignedClip(rcClip);
                      int x = ptOrigin.x;
                      for (int j = 0 ; j < nCount1 ; ++j)
                      {
                        // Assume narrowed space is converted escape sequence leadin.
                        if (line[ibegin + j] == ' ' && nWidths[j] < nCharWidth)
                        {
-                         ::RoundRect(hDC, x + 2, ptOrigin.y + 1,
+                         m_pCrystalRenderer->DrawRoundRectangle(x + 2, ptOrigin.y + 1,
                            x + 3 * nCharWidth - 2, ptOrigin.y + nLineHeight - 1,
                            nCharWidth / 2, nLineHeight / 2);
                        }
                        x += nWidths[j];
                      }
-                     hPen = ::SelectObject(hDC, hPen);
-                     ::DeleteObject(hPen);
-                     hBrush = ::SelectObject(hDC, hBrush);
-                     pdc->RestoreDC(-1);
+                     m_pCrystalRenderer->PopAxisAlignedClip();
                    }
                 }
 
@@ -1212,7 +1212,7 @@ DrawLineHelperImpl (CDC * pdc, CPoint & ptOrigin, const CRect & rcClip,
 }
 
 void CCrystalTextView::
-DrawLineHelper (CDC * pdc, CPoint & ptOrigin, const CRect & rcClip, int nColorIndex, int nBgColorIndex, 
+DrawLineHelper (CPoint & ptOrigin, const CRect & rcClip, int nColorIndex, int nBgColorIndex, 
                 COLORREF crText, COLORREF crBkgnd, LPCTSTR pszChars, int nOffset, int nCount, int &nActualOffset, CPoint ptTextPos)
 {
   if (nCount > 0)
@@ -1266,24 +1266,28 @@ DrawLineHelper (CDC * pdc, CPoint & ptOrigin, const CRect & rcClip, int nColorIn
           //  Draw part of the text before selection
           if (nSelBegin > 0)
             {
-              DrawLineHelperImpl (pdc, ptOrigin, rcClip, nColorIndex, nBgColorIndex, crText, crBkgnd, pszChars, nOffset, nSelBegin, nActualOffset);
+              DrawLineHelperImpl (ptOrigin, rcClip, nColorIndex, nBgColorIndex, crText, crBkgnd, pszChars, nOffset, nSelBegin, nActualOffset);
             }
           if (nSelBegin < nSelEnd)
             {
-              DrawLineHelperImpl (pdc, ptOrigin, rcClip,
-                  nColorIndex & ~COLORINDEX_APPLYFORCE, nBgColorIndex & ~COLORINDEX_APPLYFORCE, 
-                  GetColor (COLORINDEX_SELTEXT),
+              DrawLineHelperImpl (ptOrigin, rcClip,
+ nColorIndex & ~COLORINDEX_APPLYFORCE,
+                  nBgColorIndex & ~COLORINDEX_APPLYFORCE,
+ GetColor (COLORINDEX_SELTEXT),
                   GetColor (COLORINDEX_SELBKGND),
-                  pszChars, nOffset + nSelBegin, nSelEnd - nSelBegin, nActualOffset);
+
+                  pszChars,
+                  nOffset + nSelBegin, nSelEnd - nSelBegin, nActualOffset);
             }
           if (nSelEnd < nCount)
             {
-              DrawLineHelperImpl (pdc, ptOrigin, rcClip, nColorIndex, nBgColorIndex, crText, crBkgnd, pszChars, nOffset + nSelEnd, nCount - nSelEnd, nActualOffset);
+              DrawLineHelperImpl (ptOrigin, rcClip, nColorIndex, nBgColorIndex, crText, crBkgnd, pszChars, nOffset + nSelEnd, nCount - nSelEnd, nActualOffset);
             }
         }
       else
         {
-          DrawLineHelperImpl (pdc, ptOrigin, rcClip, nColorIndex, nBgColorIndex, crText, crBkgnd, pszChars, nOffset, nCount, nActualOffset);
+          DrawLineHelperImpl (ptOrigin, rcClip, nColorIndex, nBgColorIndex, crText, crBkgnd, pszChars, nOffset, nCount, nActualOffset);
         }
     }
 }
@@ -1466,7 +1470,7 @@ void CCrystalTextView::InvalidateScreenRect(bool bInvalidateView)
     }
 }
 
-void CCrystalTextView::DrawScreenLine( CDC *pdc, CPoint &ptOrigin, const CRect &rcClip,
+void CCrystalTextView::DrawScreenLine( CPoint &ptOrigin, const CRect &rcClip,
          const std::vector<TEXTBLOCK>& blocks, int &nActualItem, 
          COLORREF crText, COLORREF crBkgnd, bool bDrawWhitespace,
          LPCTSTR pszChars, int nOffset, int nCount, int &nActualOffset, CPoint ptTextPos )
@@ -1505,14 +1509,14 @@ void CCrystalTextView::DrawScreenLine( CDC *pdc, CPoint &ptOrigin, const CRect &
           if (blocks[I + 1].m_nCharPos - nOffsetToUse > 0)
             {
               int nOldActualOffset = nActualOffset;
-              DrawLineHelper(pdc, ptOrigin, rcClip, blk.m_nColorIndex, blk.m_nBgColorIndex, crText, crBkgnd, pszChars,
+              DrawLineHelper(ptOrigin, rcClip, blk.m_nColorIndex, blk.m_nBgColorIndex, crText, crBkgnd, pszChars,
                 (nOffset > blk.m_nCharPos)? nOffset : blk.m_nCharPos, 
                 blocks[I + 1].m_nCharPos - nOffsetToUse,
                 nActualOffset, CPoint( nOffsetToUse, ptTextPos.y ));
               if (bPrevZeroWidthBlock)
                 {
                   CRect rcClipZeroWidthBlock(ptOriginZeroWidthBlock.x, rcClip.top, ptOriginZeroWidthBlock.x + ZEROWIDTHBLOCK_WIDTH, rcClip.bottom);
-                  DrawLineHelper(pdc, ptOriginZeroWidthBlock, rcClipZeroWidthBlock, blk.m_nColorIndex, nBgColorIndexZeorWidthBlock, crText, crBkgnd, pszChars,
+                  DrawLineHelper(ptOriginZeroWidthBlock, rcClipZeroWidthBlock, blk.m_nColorIndex, nBgColorIndexZeorWidthBlock, crText, crBkgnd, pszChars,
                       (nOffset > blk.m_nCharPos)? nOffset : blk.m_nCharPos, 
                       blocks[I + 1].m_nCharPos - nOffsetToUse,
                       nOldActualOffset, CPoint( nOffsetToUse, ptTextPos.y ));
@@ -1529,7 +1533,9 @@ void CCrystalTextView::DrawScreenLine( CDC *pdc, CPoint &ptOrigin, const CRect &
                     clrBkColor = GetColor(nBgColorIndex);
                   else
                     clrBkColor = crBkgnd;
-                  pdc->FillSolidRect(ptOrigin.x, ptOrigin.y, ZEROWIDTHBLOCK_WIDTH, GetLineHeight(), clrBkColor);
+                  CRect rc(ptOrigin.x, ptOrigin.y, ptOrigin.x + ZEROWIDTHBLOCK_WIDTH, ptOrigin.y + GetLineHeight());
+                                 m_pCrystalRenderer->SetBkColor(clrBkColor);
+                                 m_pCrystalRenderer->FillRectangle(rc);
                   ptOriginZeroWidthBlock = ptOrigin;
                   nBgColorIndexZeorWidthBlock = blk.m_nBgColorIndex;
                   bPrevZeroWidthBlock = true;
@@ -1547,14 +1553,14 @@ void CCrystalTextView::DrawScreenLine( CDC *pdc, CPoint &ptOrigin, const CRect &
       if (nOffset + nCount - blocks[nActualItem].m_nCharPos > 0)
         {
           int nOldActualOffset = nActualOffset;
-          DrawLineHelper(pdc, ptOrigin, rcClip, blocks[nActualItem].m_nColorIndex, blocks[nActualItem].m_nBgColorIndex,
+          DrawLineHelper(ptOrigin, rcClip, blocks[nActualItem].m_nColorIndex, blocks[nActualItem].m_nBgColorIndex,
                   crText, crBkgnd, pszChars, blocks[nActualItem].m_nCharPos,
                   nOffset + nCount - blocks[nActualItem].m_nCharPos,
                   nActualOffset, CPoint(blocks[nActualItem].m_nCharPos, ptTextPos.y));
           if (bPrevZeroWidthBlock)
             {
               CRect rcClipZeroWidthBlock(ptOriginZeroWidthBlock.x, rcClip.top, ptOriginZeroWidthBlock.x + ZEROWIDTHBLOCK_WIDTH, rcClip.bottom);
-              DrawLineHelper(pdc, ptOriginZeroWidthBlock, rcClipZeroWidthBlock, blocks[nActualItem].m_nColorIndex, nBgColorIndexZeorWidthBlock,
+              DrawLineHelper(ptOriginZeroWidthBlock, rcClipZeroWidthBlock, blocks[nActualItem].m_nColorIndex, nBgColorIndexZeorWidthBlock,
                   crText, crBkgnd, pszChars, blocks[nActualItem].m_nCharPos,
                   nOffset + nCount - blocks[nActualItem].m_nCharPos,
                   nOldActualOffset, CPoint(blocks[nActualItem].m_nCharPos, ptTextPos.y));
@@ -1571,7 +1577,9 @@ void CCrystalTextView::DrawScreenLine( CDC *pdc, CPoint &ptOrigin, const CRect &
                 clrBkColor = GetColor(nBgColorIndex);
               else
                 clrBkColor = crBkgnd;
-              pdc->FillSolidRect(ptOrigin.x, ptOrigin.y, ZEROWIDTHBLOCK_WIDTH, GetLineHeight(), clrBkColor);
+              CRect rc(ptOrigin.x, ptOrigin.y, ptOrigin.x + ZEROWIDTHBLOCK_WIDTH, ptOrigin.y + GetLineHeight());
+                         m_pCrystalRenderer->SetBkColor(clrBkColor);
+                         m_pCrystalRenderer->FillRectangle(rc);
               bPrevZeroWidthBlock = true;
             }
         }
@@ -1579,7 +1587,7 @@ void CCrystalTextView::DrawScreenLine( CDC *pdc, CPoint &ptOrigin, const CRect &
   else
     {
       DrawLineHelper(
-              pdc, ptOrigin, rcClip, blocks[nActualItem].m_nColorIndex, blocks[nActualItem].m_nBgColorIndex,
+              ptOrigin, rcClip, blocks[nActualItem].m_nColorIndex, blocks[nActualItem].m_nBgColorIndex,
               crText, crBkgnd, pszChars, nOffset, nCount, nActualOffset, ptTextPos);
     }
 
@@ -1595,8 +1603,9 @@ void CCrystalTextView::DrawScreenLine( CDC *pdc, CPoint &ptOrigin, const CRect &
       if (frect.left >= rcClip.left)
         {
           const int nCharWidth = GetCharWidth();
-          pdc->FillSolidRect(frect.left, frect.top, nCharWidth, frect.Height(),
-              GetColor(COLORINDEX_SELBKGND));
+          CRect rc(frect.left, frect.top, frect.left + nCharWidth, frect.bottom);
+          m_pCrystalRenderer->SetBkColor(GetColor(COLORINDEX_SELBKGND));
+          m_pCrystalRenderer->FillRectangle(rc);
           frect.left += nCharWidth;
         }
     }
@@ -1604,8 +1613,10 @@ void CCrystalTextView::DrawScreenLine( CDC *pdc, CPoint &ptOrigin, const CRect &
     frect.left = rcClip.left;
 
   if (frect.right > frect.left)
-    pdc->FillSolidRect(frect, bDrawWhitespace ?
-      crBkgnd : GetColor(COLORINDEX_WHITESPACE));
+    {
+      m_pCrystalRenderer->SetBkColor(bDrawWhitespace ? crBkgnd : GetColor(COLORINDEX_WHITESPACE));
+      m_pCrystalRenderer->FillRectangle(frect);
+    }
 
   // set origin to beginning of next screen line
   ptOrigin.x = originalOrigin.x;
@@ -1770,7 +1781,7 @@ CCrystalTextView::GetTextBlocks(int nLineIndex)
 }
 
 void CCrystalTextView::
-DrawSingleLine (CDC * pdc, const CRect & rc, int nLineIndex)
+DrawSingleLine (const CRect & rc, int nLineIndex)
 {
   const int nCharWidth = GetCharWidth();
   ASSERT (nLineIndex >= -1 && nLineIndex < GetLineCount ());
@@ -1778,7 +1789,7 @@ DrawSingleLine (CDC * pdc, const CRect & rc, int nLineIndex)
   if (nLineIndex == -1)
     {
       //  Draw line beyond the text
-      pdc->FillSolidRect (rc, GetColor (COLORINDEX_WHITESPACE));
+      m_pCrystalRenderer->FillSolidRectangle (rc, GetColor (COLORINDEX_WHITESPACE));
       return;
     }
 
@@ -1803,9 +1814,9 @@ DrawSingleLine (CDC * pdc, const CRect & rc, int nLineIndex)
   //  Draw the line text
   CPoint origin (rc.left - m_nOffsetChar * nCharWidth, rc.top);
   if (crBkgnd != CLR_NONE)
-    pdc->SetBkColor (crBkgnd);
+    m_pCrystalRenderer->SetBkColor (crBkgnd);
   if (crText != CLR_NONE)
-    pdc->SetTextColor (crText);
+    m_pCrystalRenderer->SetTextColor (crText);
 
   if( nBreaks > 0 )
     {
@@ -1814,7 +1825,7 @@ DrawSingleLine (CDC * pdc, const CRect & rc, int nLineIndex)
 
       // draw start of line to first break
       DrawScreenLine(
-        pdc, origin, rc,
+        origin, rc,
         blocks, nActualItem,
         crText, crBkgnd, bDrawWhitespace,
         pszChars, 0, anBreaks[0], nActualOffset, CPoint( 0, nLineIndex ) );
@@ -1825,7 +1836,7 @@ DrawSingleLine (CDC * pdc, const CRect & rc, int nLineIndex)
         {
           ASSERT( anBreaks[i] >= 0 && anBreaks[i] < nLength );
           DrawScreenLine(
-            pdc, origin, rc,
+            origin, rc,
             blocks, nActualItem,
             crText, crBkgnd, bDrawWhitespace,
             pszChars, anBreaks[i], anBreaks[i + 1] - anBreaks[i],
@@ -1834,7 +1845,7 @@ DrawSingleLine (CDC * pdc, const CRect & rc, int nLineIndex)
 
       // draw from last break till end of line
       DrawScreenLine(
-        pdc, origin, rc,
+        origin, rc,
         blocks, nActualItem,
         crText, crBkgnd, bDrawWhitespace,
         pszChars, anBreaks[i], nLength - anBreaks[i],
@@ -1842,7 +1853,7 @@ DrawSingleLine (CDC * pdc, const CRect & rc, int nLineIndex)
     }
   else
       DrawScreenLine(
-        pdc, origin, rc,
+        origin, rc,
         blocks, nActualItem,
         crText, crBkgnd, bDrawWhitespace,
         pszChars, 0, nLength, nActualOffset, CPoint(0, nLineIndex));
@@ -1853,7 +1864,7 @@ DrawSingleLine (CDC * pdc, const CRect & rc, int nLineIndex)
     {
       CRect frect = rc;
       frect.top = frect.bottom - nEmptySubLines * GetLineHeight();
-      pdc->FillSolidRect(frect, crBkgnd == CLR_NONE ? GetColor(COLORINDEX_WHITESPACE) : crBkgnd);
+      m_pCrystalRenderer->FillSolidRectangle(frect, crBkgnd == CLR_NONE ? GetColor(COLORINDEX_WHITESPACE) : crBkgnd);
     }
 }
 
@@ -2130,24 +2141,18 @@ GetLineFlags (int nLineIndex) const
  * @param [in] nLineNumber Line number to display. if -1, it's not displayed.
  */
 void CCrystalTextView::
-DrawMargin (CDC * pdc, const CRect & rect, int nLineIndex, int nLineNumber)
+DrawMargin (const CRect & rect, int nLineIndex, int nLineNumber)
 {
   if (!m_bSelMargin && !m_bViewLineNumbers)
-    pdc->FillSolidRect (rect, GetColor (COLORINDEX_BKGND));
+    m_pCrystalRenderer->SetBkColor(GetColor (COLORINDEX_BKGND));
   else
-    pdc->FillSolidRect (rect, GetColor (COLORINDEX_SELMARGIN));
+    m_pCrystalRenderer->SetBkColor(GetColor (COLORINDEX_SELMARGIN));
+  m_pCrystalRenderer->FillRectangle(rect);
 
   if (m_bViewLineNumbers && nLineNumber > 0)
     {
-      TCHAR szNumbers[32];
-      wsprintf(szNumbers, _T("%d"), nLineNumber);
-      CFont *pOldFont = pdc->SelectObject(GetFont());
-      COLORREF clrOldColor = pdc->SetTextColor(GetColor(COLORINDEX_NORMALTEXT));
-      UINT uiOldAlign = pdc->SetTextAlign(TA_RIGHT);
-      pdc->TextOut(rect.right - (pdc->IsPrinting() ? 0 : 4), rect.top, szNumbers, lstrlen(szNumbers));
-      pdc->SetTextAlign(uiOldAlign);
-      pdc->SelectObject(pOldFont);
-      pdc->SetTextColor(clrOldColor);
+      m_pCrystalRenderer->SetTextColor(GetColor(COLORINDEX_NORMALTEXT));
+         m_pCrystalRenderer->DrawMarginLineNumber(rect.right, rect.top, nLineNumber);
     }
 
   // Draw line revision mark (or background) whenever we have valid lineindex
@@ -2166,10 +2171,10 @@ DrawMargin (CDC * pdc, const CRect & rect, int nLineIndex, int nLineNumber)
     }
 
   // draw line revision marks
-  CRect rc(rect.right - (pdc->IsPrinting () ? 0 : MARGIN_REV_WIDTH), rect.top, rect.right, rect.bottom);
-  pdc->FillSolidRect (rc, clrRevisionMark);
+  CRect rc(rect.right - MARGIN_REV_WIDTH, rect.top, rect.right, rect.bottom);
+  m_pCrystalRenderer->FillSolidRectangle (rc, clrRevisionMark);
 
-  if (!m_bSelMargin || pdc->IsPrinting ())
+  if (!m_bSelMargin)
     return;
 
   int nImageIndex = -1;
@@ -2203,20 +2208,10 @@ DrawMargin (CDC * pdc, const CRect & rect, int nLineIndex, int nLineNumber)
             }
         }
     }
-  if (m_pIcons == nullptr)
-    {
-      m_pIcons = new CImageList;
-      VERIFY (m_pIcons->Create(MARGIN_ICON_WIDTH, MARGIN_ICON_HEIGHT,
-          ILC_COLOR32 | ILC_MASK, 0, 1));
-      CBitmap bmp;
-      bmp.LoadBitmap(IDR_MARGIN_ICONS);
-      m_pIcons->Add(&bmp, RGB(255, 255, 255));
-    }
   if (nImageIndex >= 0)
     {
-      CPoint pt(rect.left + 2, rect.top + (GetLineHeight() - MARGIN_ICON_HEIGHT) / 2);
-      VERIFY(m_pIcons->Draw(pdc, nImageIndex, pt, ILD_TRANSPARENT));
-      VERIFY (m_pIcons->Draw (pdc, nImageIndex, pt, ILD_TRANSPARENT));
+         m_pCrystalRenderer->DrawMarginIcon(
+        rect.left + 2, rect.top + (GetLineHeight() - CCrystalRenderer::MARGIN_ICON_HEIGHT) / 2, nImageIndex);
     }
 
   // draw wrapped-line-icon
@@ -2226,38 +2221,13 @@ DrawMargin (CDC * pdc, const CRect & rect, int nLineIndex, int nLineNumber)
       WrapLineCached( nLineIndex, GetScreenChars(), nullptr, nBreaks );
       for (int i = 0; i < nBreaks; i++)
         {
-          CPoint pt(rect.right - MARGIN_ICON_WIDTH, rect.top + (GetLineHeight()
-              - MARGIN_ICON_WIDTH) / 2 + (i+1) * GetLineHeight());
-          m_pIcons->Draw (pdc, ICON_INDEX_WRAPLINE, pt, ILD_TRANSPARENT);
+             m_pCrystalRenderer->DrawMarginIcon(
+              rect.right - CCrystalRenderer::MARGIN_ICON_WIDTH, rect.top + (GetLineHeight()
+              - CCrystalRenderer::MARGIN_ICON_WIDTH) / 2 + (i+1) * GetLineHeight(), ICON_INDEX_WRAPLINE);
         }
     }
 }
 
-void CCrystalTextView::
-DrawBoundaryLine (CDC * pdc, int nLeft, int nRight, int y)
-{
-  CPen *pOldPen = (CPen *)pdc->SelectStockObject (BLACK_PEN);
-  pdc->MoveTo (nLeft, y);
-  pdc->LineTo (nRight, y);
-  pdc->SelectObject (pOldPen);
-}
-
-void CCrystalTextView::
-DrawLineCursor (CDC * pdc, int nLeft, int nRight, int y, int nHeight)
-{
-  CDC  dcMem;
-  dcMem.CreateCompatibleDC (pdc);
-  CBitmap bitmap;
-  bitmap.CreateCompatibleBitmap (pdc, nRight - nLeft, nHeight);
-  CBitmap *pOldBitmap = dcMem.SelectObject (&bitmap);
-  dcMem.SetBkColor(RGB(0, 255, 0));
-  BLENDFUNCTION blend = {0};
-  blend.BlendOp = AC_SRC_OVER;
-  blend.SourceConstantAlpha = 24;
-  pdc->AlphaBlend (nLeft, y, nRight - nLeft, nHeight, &dcMem, 0, 0, nRight - nLeft, nHeight, blend);
-  dcMem.SelectObject (pOldBitmap);
-}
-
 bool CCrystalTextView::
 IsInsideSelBlock (CPoint ptTextPos)
 {
@@ -2322,7 +2292,11 @@ OnDraw (CDC * pdc)
 
   if (m_pTextBuffer == nullptr)
     {
-      pdc->FillSolidRect(&rcClient, GetSysColor(COLOR_WINDOW));
+         m_pCrystalRenderer->BindDC(*pdc, rcClient);
+         m_pCrystalRenderer->BeginDraw();
+         m_pCrystalRenderer->SetBkColor(GetSysColor(COLOR_WINDOW));
+      m_pCrystalRenderer->FillRectangle(rcClient);
+         m_pCrystalRenderer->EndDraw();
       return;
     }
 
@@ -2346,72 +2320,59 @@ OnDraw (CDC * pdc)
     }
   CBitmap *pOldBitmap = cacheDC.SelectObject (m_pCacheBitmap);
 
-  CRect rcLine;
-  rcLine = rcClient;
-  rcLine.bottom = rcLine.top + nLineHeight;
-  CRect rcCacheMargin (0, 0, GetMarginWidth (), nLineHeight);
-  CRect rcCacheLine (GetMarginWidth (), 0, rcLine.Width (), nLineHeight);
-  //BEGIN SW
   // initialize rects
-  int          nSubLineOffset = GetSubLineIndex( m_nTopLine ) - m_nTopSubLine;
-  if( nSubLineOffset < 0 )
-  {
-    rcCacheMargin.OffsetRect( 0, nSubLineOffset * nLineHeight );
-    rcCacheLine.OffsetRect( 0, nSubLineOffset * nLineHeight );
-  }
-
+  int nSubLineOffset = GetSubLineIndex( m_nTopLine ) - m_nTopSubLine;
   int nCursorY = TextToClient (m_ptCursorPos).y;
 
-  //END SW
+  CRect rcLine;
+  rcLine = rcClient;
+  rcLine.top += nSubLineOffset * nLineHeight;
+  CRect rcMargin (rcLine.left, rcLine.top, rcLine.left + GetMarginWidth (), rcLine.top + nLineHeight);
+  rcLine.left = rcMargin.right;
+
+  m_pCrystalRenderer->BindDC(cacheDC, rcClient);
+  m_pCrystalRenderer->BeginDraw();
 
   int nCurrentLine = m_nTopLine;
   while (rcLine.top < rcClient.bottom)
     {
-      //BEGIN SW
       int nSubLines = 1;
       if( nCurrentLine < nLineCount /*&& GetLineLength( nCurrentLine ) > nMaxLineChars*/ )
          nSubLines = GetSubLines(nCurrentLine);
 
       rcLine.bottom = rcLine.top + nSubLines * nLineHeight;
-      rcCacheLine.bottom = rcCacheLine.top + rcLine.Height();
-      rcCacheMargin.bottom = rcCacheMargin.top + rcLine.Height();
+         rcMargin.bottom = rcLine.bottom;
 
-      if( rcCacheLine.top < 0 )
-        rcLine.bottom+= rcCacheLine.top;
-      //END SW
-      if (pdc->RectVisible(rcLine))
+         CRect rcMarginAndLine(rcClient.left, rcLine.top, rcClient.right, rcLine.bottom);
+      if (pdc->RectVisible(rcMarginAndLine))
         {
           if (nCurrentLine < nLineCount && GetLineVisible (nCurrentLine))
             {
-              DrawMargin (&cacheDC, rcCacheMargin, nCurrentLine, nCurrentLine + 1);
-              DrawSingleLine (&cacheDC, rcCacheLine, nCurrentLine);
+              DrawMargin (rcMargin, nCurrentLine, nCurrentLine + 1);
+              DrawSingleLine (rcLine, nCurrentLine);
               if (nCurrentLine+1 < nLineCount && !GetLineVisible (nCurrentLine + 1))
-                DrawBoundaryLine (&cacheDC, rcCacheMargin.left, rcCacheLine.right, rcCacheMargin.bottom-1);
+                m_pCrystalRenderer->DrawBoundaryLine (rcMargin.left, rcLine.right, rcMargin.bottom-1);
               if (nCurrentLine == m_ptCursorPos.y)
-                DrawLineCursor (&cacheDC, rcCacheMargin.left, rcCacheLine.right, 
-                  nCursorY - rcLine.top + nLineHeight - 1, 1);
+                m_pCrystalRenderer->DrawLineCursor (rcMargin.left, rcLine.right, 
+                  nCursorY + nLineHeight - 1, 1);
             }
           else
             {
-              DrawMargin (&cacheDC, rcCacheMargin, -1, -1);
-              DrawSingleLine (&cacheDC, rcCacheLine, -1);
+              DrawMargin (rcMargin, -1, -1);
+              DrawSingleLine (rcLine, -1);
             }
-
-          VERIFY (pdc->BitBlt (rcLine.left, rcLine.top, rcLine.Width (),
-              rcLine.Height (), &cacheDC, 0, 0, SRCCOPY));
         }
 
       nCurrentLine++;
-      //BEGIN SW
       rcLine.top = rcLine.bottom;
-      rcCacheLine.top = 0;
-      rcCacheMargin.top = 0;
-      /*ORIGINAL
-      rcLine.OffsetRect(0, nLineHeight);
-      */
-      //END SW
+      rcMargin.top = rcLine.top;
     }
 
+  m_pCrystalRenderer->EndDraw();
+
+  VERIFY (pdc->BitBlt (rcClient.left, rcClient.top, rcClient.Width (),
+                 rcClient.Height (), &cacheDC, 0, 0, SRCCOPY));
+
   cacheDC.SelectObject (pOldBitmap);
   cacheDC.DeleteDC ();
 }
@@ -2430,19 +2391,6 @@ ResetView ()
   m_nIdealCharPos = -1;
   m_ptAnchor.x = 0;
   m_ptAnchor.y = 0;
-  if (m_pIcons != nullptr)
-    {
-      delete m_pIcons;
-      m_pIcons = nullptr;
-    }
-  for (int I = 0; I < 4; I++)
-    {
-      if (m_apFonts[I] != nullptr)
-        {
-          delete m_apFonts[I];
-          m_apFonts[I] = nullptr;
-        }
-    }
   InvalidateLineCache( 0, -1 );
   m_ParseCookies->clear();
   m_pnActualLineLength->clear();
@@ -2543,56 +2491,14 @@ SetTabSize (int nTabSize)
     }
 }
 
-CFont *CCrystalTextView::
-GetFont (bool bItalic /*= false*/ , bool bBold /*= false*/ )
-{
-  int nIndex = 0;
-  if (bBold)
-    nIndex |= 1;
-  if (bItalic)
-    nIndex |= 2;
-
-  if (m_apFonts[nIndex] == nullptr)
-    {
-      m_apFonts[nIndex] = new CFont;
-      if (!m_lfBaseFont.lfHeight)
-        {
-          CClientDC dc (GetDesktopWindow ());
-          m_lfBaseFont.lfHeight = -MulDiv (11, dc.GetDeviceCaps (LOGPIXELSY), 72);
-        }
-      m_lfBaseFont.lfWeight = bBold ? FW_BOLD : FW_NORMAL;
-      m_lfBaseFont.lfItalic = (BYTE) bItalic;
-      if (!m_apFonts[nIndex]->CreateFontIndirect (&m_lfBaseFont))
-        {
-          delete m_apFonts[nIndex];
-          m_apFonts[nIndex] = nullptr;
-          return CView::GetFont ();
-        }
-    }
-  return m_apFonts[nIndex];
-}
-
 void CCrystalTextView::
 CalcLineCharDim ()
 {
-  CDC *pdc = GetDC ();
-  CFont *pOldFont = pdc->SelectObject (GetFont ());
-  CSize szCharExt = pdc->GetTextExtent (_T ("X"));
+  CSize szCharExt = m_pCrystalRenderer->GetCharWidthHeight();
   m_nLineHeight = szCharExt.cy;
   if (m_nLineHeight < 1)
     m_nLineHeight = 1;
   m_nCharWidth = szCharExt.cx;
-  /*
-     TEXTMETRIC tm;
-     if (pdc->GetTextMetrics(&tm))
-     m_nCharWidth -= tm.tmOverhang;
-   */
-  pdc->SelectObject (GetFont (false, true));
-  szCharExt = pdc->GetTextExtent (_T ("X"));
-  if (m_nLineHeight < szCharExt.cy)
-    m_nLineHeight = szCharExt.cy;
-  pdc->SelectObject (pOldFont);
-  ReleaseDC (pdc);
 }
 
 int CCrystalTextView::
@@ -3063,11 +2969,8 @@ void CCrystalTextView::
 OnBeginPrinting (CDC * pdc, CPrintInfo * pInfo)
 {
   ASSERT (m_pPrintFont == nullptr);
-  CFont *pDisplayFont = GetFont ();
-
-  LOGFONT lf;
+  LOGFONT lf = m_lfBaseFont;
   CDC *pDisplayDC = GetDC ();
-  pDisplayFont->GetLogFont (&lf);
   lf.lfHeight = MulDiv (lf.lfHeight, pdc->GetDeviceCaps (LOGPIXELSY), pDisplayDC->GetDeviceCaps (LOGPIXELSY));
   lf.lfWidth = MulDiv (lf.lfWidth, pdc->GetDeviceCaps (LOGPIXELSX), pDisplayDC->GetDeviceCaps (LOGPIXELSX));
   ReleaseDC (pDisplayDC);
@@ -3176,6 +3079,9 @@ OnPrint (CDC * pdc, CPrintInfo * pInfo)
     rcLine.OffsetRect( 0, nSubLineOffset * nLineHeight );
   }
 
+  m_pCrystalRenderer->BindDC(*pdc, m_rcPrintArea);
+  m_pCrystalRenderer->BeginDraw();
+
   int nLineCount = GetLineCount();
   int nCurrentLine;
   for (nCurrentLine = nTopLine; nCurrentLine <= nEndLine; nCurrentLine++)
@@ -3185,16 +3091,18 @@ OnPrint (CDC * pdc, CPrintInfo * pInfo)
 
       if (nCurrentLine < nLineCount && GetLineVisible (nCurrentLine))
         {
-          DrawMargin (pdc, rcMargin, nCurrentLine, nCurrentLine + 1);
-          DrawSingleLine (pdc, rcLine, nCurrentLine);
+          DrawMargin (rcMargin, nCurrentLine, nCurrentLine + 1);
+          DrawSingleLine (rcLine, nCurrentLine);
           if (nCurrentLine+1 < nLineCount && !GetLineVisible (nCurrentLine + 1))
-            DrawBoundaryLine (pdc, rcMargin.left, rcLine.right, rcMargin.bottom-1);
+            m_pCrystalRenderer->DrawBoundaryLine (rcMargin.left, rcLine.right, rcMargin.bottom-1);
         }
 
       rcLine.top = rcLine.bottom;
       rcMargin.top = rcLine.bottom;
     }
 
+  m_pCrystalRenderer->EndDraw();
+
   pdc->SelectClipRgn (nullptr);
 }
 
@@ -3471,20 +3379,11 @@ GetScreenChars ()
 void CCrystalTextView::
 OnDestroy ()
 {
-  GetFont ()->GetLogFont (&m_lfBaseFont);
   DetachFromBuffer ();
   m_hAccel = nullptr;
 
   CView::OnDestroy ();
 
-  for (int I = 0; I < 4; I++)
-    {
-      if (m_apFonts[I] != nullptr)
-        {
-          delete m_apFonts[I];
-          m_apFonts[I] = nullptr;
-        }
-    }
   if (m_pCacheBitmap != nullptr)
     {
       delete m_pCacheBitmap;
@@ -4557,10 +4456,8 @@ void CCrystalTextView::
 UpdateCompositionWindowFont() /* IME */
 {
   HIMC hIMC = ImmGetContext(m_hWnd);
-  LOGFONT logfont;
 
-  GetFont()->GetLogFont(&logfont);
-  ImmSetCompositionFont(hIMC, &logfont);
+  ImmSetCompositionFont(hIMC, &m_lfBaseFont);
 
   ImmReleaseContext(m_hWnd, hIMC);
 }
@@ -4609,14 +4506,7 @@ SetFont (const LOGFONT & lf)
   m_lfBaseFont = lf;
   m_nCharWidth = -1;
   m_nLineHeight = -1;
-  for (int I = 0; I < 4; I++)
-    {
-      if (m_apFonts[I] != nullptr)
-        {
-          delete m_apFonts[I];
-          m_apFonts[I] = nullptr;
-        }
-    }
+  m_pCrystalRenderer->SetFont(lf);
   if (::IsWindow (m_hWnd))
     {
       InvalidateScreenRect();
@@ -6092,6 +5982,18 @@ OnToggleColumnSelection ()
   Invalidate ();
 }
 
+void CCrystalTextView::SetRenderingMode(RENDERING_MODE nRenderingMode)
+{
+#ifdef _WIN64
+  if (nRenderingMode == RENDERING_MODE_GDI)
+    m_pCrystalRenderer.reset(new CCrystalRendererGDI());
+  else
+    m_pCrystalRenderer.reset(new CCrystalRendererDirectWrite(nRenderingMode));
+  m_pCrystalRenderer->SetFont(m_lfBaseFont);
+#endif
+  m_nRenderingMode = nRenderingMode;
+}
+
 //BEGIN SW
 bool CCrystalTextView::GetWordWrapping() const
 {
@@ -6426,9 +6328,7 @@ int CCrystalTextView::GetCharCellCountUnicodeChar(const wchar_t *pch)
           int nWidthArray[256];
           wchar_t nStart = ch/256*256;
           wchar_t nEnd = nStart + 255;
-          CDC *pdc = GetDC();
-          CFont *pOldFont = pdc->SelectObject(GetFont());
-          GetCharWidth32(pdc->m_hDC, nStart, nEnd, nWidthArray);
+          m_pCrystalRenderer->GetCharWidth(nStart, nEnd, nWidthArray);
           int nCharWidth = GetCharWidth();
           for (int i = 0; i < 256; i++) 
             {
@@ -6442,7 +6342,6 @@ int CCrystalTextView::GetCharCellCountUnicodeChar(const wchar_t *pch)
                 }
             }
           m_bChWidthsCalculated[ch / 256] = true;
-          pdc->SelectObject(pOldFont);
         }
     }
   if (m_iChDoubleWidthFlags[ch / 32] & (1 << (ch % 32)))
index a391a35..3865506 100644 (file)
@@ -37,6 +37,7 @@
 #include "cregexp.h"
 #include "crystalparser.h"
 #include "crystallineparser.h"
+#include "ccrystalrenderer.h"
 #include "icu.hpp"
 
 ////////////////////////////////////////////////////////////////////////////
@@ -143,7 +144,6 @@ protected:
 private:
     LOGFONT m_lfBaseFont;
     LOGFONT m_lfSavedBaseFont;
-    CFont *m_apFonts[4];
 
     //  Parsing stuff
 
@@ -188,14 +188,26 @@ protected:
 
     int ApproxActualOffset (int nLineIndex, int nOffset);
     void AdjustTextPoint (CPoint & point);
-    void DrawLineHelperImpl (CDC * pdc, CPoint & ptOrigin, const CRect & rcClip,
-                             int nColorIndex, int nBgColorIndex, COLORREF crText, COLORREF crBkgnd, LPCTSTR pszChars, int nOffset, int nCount, int &nActualOffset);
+    void DrawLineHelperImpl (CPoint & ptOrigin, const CRect & rcClip,
+ int nColorIndex,
+                             int nBgColorIndex, COLORREF crText, COLORREF crBkgnd, LPCTSTR pszChars, int nOffset, int nCount, int &nActualOffset);
     bool IsInsideSelBlock (CPoint ptTextPos);
 
     bool m_bBookmarkExist;        // More bookmarks
     void ToggleBookmark(int nLine);
 
 public :
+    enum RENDERING_MODE
+    {
+         RENDERING_MODE_GDI = -1,
+         RENDERING_MODE_DWRITE_DFEAULT = 0,
+         RENDERING_MODE_DWRITE_ALIASED = 1,
+         RENDERING_MODE_DWRITE_GDI_CLASSIC = 2,
+         RENDERING_MODE_DWRITE_GDI_NATURAL = 3,
+         RENDERING_MODE_DWRITE_NATURAL = 4,
+         RENDERING_MODE_DWRITE_NATURAL_SYMMETRIC = 5,
+       };
+
     virtual void ResetView ();
     virtual int GetLineCount ();
     virtual void OnUpdateCaret ();
@@ -214,7 +226,6 @@ protected :
     bool           m_bOverrideCaret;
 
     bool m_bSingle;
-    CImageList * m_pIcons;
     CCrystalTextBuffer *m_pTextBuffer;
     HACCEL m_hAccel;
     bool m_bVertScrollBarLocked, m_bHorzScrollBarLocked;
@@ -383,7 +394,6 @@ protected :
     int GetMaxLineLength (int nTopLine, int nLines);
     int GetScreenLines ();
     int GetScreenChars ();
-    CFont *GetFont (bool bItalic = false, bool bBold = false);
 
     void RecalcVertScrollBar (bool bPositionOnly = false, bool bRedraw = true);
     virtual void RecalcHorzScrollBar (bool bPositionOnly = false, bool bRedraw = true);
@@ -465,12 +475,10 @@ protected:
     virtual bool GetItalic (int nColorIndex);
     virtual bool GetBold (int nColorIndex);
 
-    void DrawLineHelper (CDC * pdc, CPoint & ptOrigin, const CRect & rcClip, int nColorIndex, int nBgColorIndex,
+    void DrawLineHelper (CPoint & ptOrigin, const CRect & rcClip, int nColorIndex, int nBgColorIndex,
                          COLORREF crText, COLORREF crBkgnd, LPCTSTR pszChars, int nOffset, int nCount, int &nActualOffset, CPoint ptTextPos);
-    virtual void DrawSingleLine (CDC * pdc, const CRect & rect, int nLineIndex);
-    virtual void DrawMargin (CDC * pdc, const CRect & rect, int nLineIndex, int nLineNumber);
-    virtual void DrawBoundaryLine (CDC * pdc, int nLeft, int nRight, int y);
-    virtual void DrawLineCursor (CDC * pdc, int nLeft, int nRight, int y, int nHeight);
+    virtual void DrawSingleLine (const CRect & rect, int nLineIndex);
+    virtual void DrawMargin (const CRect & rect, int nLineIndex, int nLineNumber);
 
     inline int GetCharCellCountFromChar(const TCHAR *pch)
     {
@@ -580,11 +588,15 @@ protected:
     //BEGIN SW
     // function to draw a single screen line
     // (a wrapped line can consist of many screen lines
-    virtual void DrawScreenLine( CDC *pdc, CPoint &ptOrigin, const CRect &rcClip,
-        const std::vector<CrystalLineParser::TEXTBLOCK>& blocks, int &nActualItem,
-        COLORREF crText, COLORREF crBkgnd, bool bDrawWhitespace,
-        LPCTSTR pszChars,
-        int nOffset, int nCount, int &nActualOffset, CPoint ptTextPos );
+    virtual void DrawScreenLine( CPoint &ptOrigin, const CRect &rcClip,
+ const std::vector<CrystalLineParser::TEXTBLOCK>& blocks,
+        int &nActualItem,
+ COLORREF crText,
+        COLORREF crBkgnd, bool bDrawWhitespace,
+ LPCTSTR pszChars,
+
+        int nOffset,
+        int nCount, int &nActualOffset, CPoint ptTextPos );
     //END SW
 
     std::vector<CrystalLineParser::TEXTBLOCK> MergeTextBlocks(const std::vector<CrystalLineParser::TEXTBLOCK>& blocks1, const std::vector<CrystalLineParser::TEXTBLOCK>& blocks2) const;
@@ -680,6 +692,11 @@ public :
     bool GetDisableDragAndDrop () const;
     void SetDisableDragAndDrop (bool bDDAD);
 
+       static RENDERING_MODE GetRenderingModeDefault() { return s_nRenderingModeDefault;  }
+       static void SetRenderingModeDefault(RENDERING_MODE nRenderingMode) { s_nRenderingModeDefault = nRenderingMode;  }
+       RENDERING_MODE GetRenderingMode() const { return m_nRenderingMode;  }
+       void SetRenderingMode(RENDERING_MODE nRenderingMode);
+
     //BEGIN SW
     bool GetWordWrapping() const;
     virtual void SetWordWrapping( bool bWordWrap );
@@ -708,9 +725,12 @@ public :
     RxMatchRes m_rxmatch;
     LPTSTR m_pszMatched;
     static LOGFONT m_LogFont;
+       static RENDERING_MODE s_nRenderingModeDefault;
+       RENDERING_MODE m_nRenderingMode;
 
     ICUBreakIterator m_iterChar;
     ICUBreakIterator m_iterWord;
+       std::unique_ptr<CCrystalRenderer> m_pCrystalRenderer;
 
     typedef enum
     {
index 41d7146..bbadde0 100644 (file)
@@ -278,12 +278,12 @@ HGLOBAL CGhostTextView::PrepareDragData ()
  * @param [in] nLineIndex  Index of line in view.
  * @param [in] nLineNumber Line number to display. if -1, it's not displayed.
  */
-void CGhostTextView::DrawMargin (CDC * pdc, const CRect & rect, int nLineIndex, int nLineNumber)
+void CGhostTextView::DrawMargin (const CRect & rect, int nLineIndex, int nLineNumber)
 {
        int nRealLineNumber;
        if (nLineIndex < 0 || GetLineFlags(nLineIndex) & LF_GHOST)
                nRealLineNumber = -1;
        else
                nRealLineNumber = ComputeRealLine(nLineIndex) + 1;
-       CCrystalTextView::DrawMargin(pdc, rect, nLineIndex, nRealLineNumber);
+       CCrystalTextView::DrawMargin(rect, nLineIndex, nRealLineNumber);
 }
index 278b5d4..b5b2092 100644 (file)
@@ -115,6 +115,6 @@ public:
 
        int ComputeApparentLine (int nRealLine) const;
        int ComputeRealLine (int nApparentLine) const;
-       virtual void DrawMargin (CDC * pdc, const CRect & rect, int nLineIndex, int nLineNumber) override;
+       virtual void DrawMargin (const CRect & rect, int nLineIndex, int nLineNumber) override;
 
 };
index 99a0a3f..e5a0bb2 100644 (file)
@@ -816,6 +816,9 @@ void CMainFrame::OnOptions()
                String filterPath = GetOptionsMgr()->GetString(OPT_FILTER_USERPATH);
                theApp.m_pGlobalFileFilter->SetUserFilterPath(filterPath);
 
+               CCrystalTextView::RENDERING_MODE nRenderingMode = static_cast<CCrystalTextView::RENDERING_MODE>(GetOptionsMgr()->GetInt(OPT_RENDERING_MODE));
+               CCrystalTextView::SetRenderingModeDefault(nRenderingMode);
+
                theApp.UpdateCodepageModule();
 
                strdiff::SetBreakChars(GetOptionsMgr()->GetString(OPT_BREAK_SEPARATORS).c_str());
index d38f86b..f80b3cb 100644 (file)
@@ -302,6 +302,8 @@ BOOL CMergeApp::InitInstance()
        if (m_pMarkers != nullptr)
                m_pMarkers->LoadFromRegistry();
 
+       CCrystalTextView::SetRenderingModeDefault(static_cast<CCrystalTextView::RENDERING_MODE>(GetOptionsMgr()->GetInt(OPT_RENDERING_MODE)));
+
        if (m_pLineFilters != nullptr)
                m_pLineFilters->Initialize(GetOptionsMgr());
 
index 6b89ba2..fdcc81f 100644 (file)
@@ -1342,6 +1342,8 @@ BEGIN
     COMBOBOX        IDC_BREAK_TYPE,38,162,183,34,CBS_DROPDOWNLIST | WS_VSCROLL | WS_GROUP | WS_TABSTOP\r
     LTEXT           "W&ord break characters:",IDC_STATIC,24,180,194,10\r
     EDITTEXT        IDC_BREAK_CHARS,24,192,198,14,ES_AUTOHSCROLL\r
+    LTEXT           "&Rendering Mode:",IDC_STATIC,7,220,90,10\r
+    COMBOBOX        IDC_RENDERING_MODE,100,220,148,34,CBS_DROPDOWNLIST | WS_VSCROLL | WS_GROUP | WS_TABSTOP\r
 END\r
 \r
 IDD_MESSAGE_BOX DIALOGEX 0, 0, 186, 95\r
index 19d11d1..07912f3 100644 (file)
@@ -31,7 +31,7 @@
     <ProjectGuid>{9FDA4AF0-CCFD-4812-BDB9-53EFEDB32BDE}</ProjectGuid>\r
     <RootNamespace>Merge</RootNamespace>\r
     <Keyword>MFCProj</Keyword>\r
-    <WindowsTargetPlatformVersion>10.0.17134.0</WindowsTargetPlatformVersion>\r
+    <WindowsTargetPlatformVersion>10.0.18362.0</WindowsTargetPlatformVersion>\r
   </PropertyGroup>\r
   <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />\r
   <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">\r
@@ -45,7 +45,7 @@
     <ConfigurationType>Application</ConfigurationType>\r
     <UseOfMfc>Static</UseOfMfc>\r
     <CharacterSet>Unicode</CharacterSet>\r
-    <PlatformToolset>v141</PlatformToolset>\r
+    <PlatformToolset>v141_xp</PlatformToolset>\r
     <XPDeprecationWarning>false</XPDeprecationWarning>\r
   </PropertyGroup>\r
   <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">\r
@@ -59,7 +59,7 @@
     <ConfigurationType>Application</ConfigurationType>\r
     <UseOfMfc>Static</UseOfMfc>\r
     <CharacterSet>Unicode</CharacterSet>\r
-    <PlatformToolset>v141_xp</PlatformToolset>\r
+    <PlatformToolset>v141</PlatformToolset>\r
     <XPDeprecationWarning>false</XPDeprecationWarning>\r
   </PropertyGroup>\r
   <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Test|x64'" Label="Configuration">\r
@@ -73,7 +73,7 @@
     <ConfigurationType>Application</ConfigurationType>\r
     <UseOfMfc>Static</UseOfMfc>\r
     <CharacterSet>Unicode</CharacterSet>\r
-    <PlatformToolset>v141_xp</PlatformToolset>\r
+    <PlatformToolset>v141</PlatformToolset>\r
     <XPDeprecationWarning>false</XPDeprecationWarning>\r
   </PropertyGroup>\r
   <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />\r
     <ClCompile Include="..\Externals\crystaledit\editlib\basic.cpp" />\r
     <ClCompile Include="..\Externals\crystaledit\editlib\batch.cpp" />\r
     <ClCompile Include="..\Externals\crystaledit\editlib\ccrystaleditview.cpp" />\r
+    <ClCompile Include="..\Externals\crystaledit\editlib\ccrystalrendererdirectwrite.cpp">\r
+      <PrecompiledHeader>NotUsing</PrecompiledHeader>\r
+    </ClCompile>\r
+    <ClCompile Include="..\Externals\crystaledit\editlib\ccrystalrenderergdi.cpp" />\r
     <ClCompile Include="..\Externals\crystaledit\editlib\ccrystaltextbuffer.cpp" />\r
     <ClCompile Include="..\Externals\crystaledit\editlib\ccrystaltextmarkers.cpp" />\r
     <ClCompile Include="..\Externals\crystaledit\editlib\ccrystaltextview.cpp" />\r
     <ClInclude Include="..\Externals\boost\boost\config\compiler\visualc.hpp" />\r
     <ClInclude Include="..\Externals\boost\boost\config\select_compiler_config.hpp" />\r
     <ClInclude Include="..\Externals\crystaledit\editlib\ccrystaleditview.h" />\r
+    <ClInclude Include="..\Externals\crystaledit\editlib\ccrystalrenderer.h" />\r
+    <ClInclude Include="..\Externals\crystaledit\editlib\ccrystalrendererdirectwrite.h" />\r
+    <ClInclude Include="..\Externals\crystaledit\editlib\ccrystalrenderergdi.h" />\r
     <ClInclude Include="..\Externals\crystaledit\editlib\ccrystaltextbuffer.h" />\r
     <ClInclude Include="..\Externals\crystaledit\editlib\ccrystaltextmarkers.h" />\r
     <ClInclude Include="..\Externals\crystaledit\editlib\ccrystaltextview.h" />\r
index 45bf236..6c05554 100644 (file)
     <ClCompile Include="..\Externals\crystaledit\editlib\icu.cpp">\r
       <Filter>EditLib\Source Files</Filter>\r
     </ClCompile>\r
+    <ClCompile Include="..\Externals\crystaledit\editlib\ccrystalrenderergdi.cpp">\r
+      <Filter>EditLib\Source Files</Filter>\r
+    </ClCompile>\r
+    <ClCompile Include="..\Externals\crystaledit\editlib\ccrystalrendererdirectwrite.cpp">\r
+      <Filter>EditLib\Source Files</Filter>\r
+    </ClCompile>\r
     <ClCompile Include="DirSelectFilesDlg.cpp">\r
       <Filter>MFCGui\Dialogs\Source Files</Filter>\r
     </ClCompile>\r
index 283514d..dea8272 100644 (file)
     <ClCompile Include="..\Externals\crystaledit\editlib\basic.cpp" />\r
     <ClCompile Include="..\Externals\crystaledit\editlib\batch.cpp" />\r
     <ClCompile Include="..\Externals\crystaledit\editlib\ccrystaleditview.cpp" />\r
+    <ClCompile Include="..\Externals\crystaledit\editlib\ccrystalrendererdirectwrite.cpp">\r
+      <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">NotUsing</PrecompiledHeader>\r
+      <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Test|Win32'">NotUsing</PrecompiledHeader>\r
+      <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">NotUsing</PrecompiledHeader>\r
+      <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">NotUsing</PrecompiledHeader>\r
+      <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Test|x64'">NotUsing</PrecompiledHeader>\r
+      <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>\r
+    </ClCompile>\r
+    <ClCompile Include="..\Externals\crystaledit\editlib\ccrystalrenderergdi.cpp" />\r
     <ClCompile Include="..\Externals\crystaledit\editlib\ccrystaltextbuffer.cpp" />\r
     <ClCompile Include="..\Externals\crystaledit\editlib\ccrystaltextmarkers.cpp" />\r
     <ClCompile Include="..\Externals\crystaledit\editlib\ccrystaltextview.cpp" />\r
     <ClInclude Include="..\Externals\boost\boost\config\compiler\visualc.hpp" />\r
     <ClInclude Include="..\Externals\boost\boost\config\select_compiler_config.hpp" />\r
     <ClInclude Include="..\Externals\crystaledit\editlib\ccrystaleditview.h" />\r
+    <ClInclude Include="..\Externals\crystaledit\editlib\ccrystalrenderer.h" />\r
+    <ClInclude Include="..\Externals\crystaledit\editlib\ccrystalrendererdirectwrite.h" />\r
+    <ClInclude Include="..\Externals\crystaledit\editlib\ccrystalrenderergdi.h" />\r
     <ClInclude Include="..\Externals\crystaledit\editlib\ccrystaltextbuffer.h" />\r
     <ClInclude Include="..\Externals\crystaledit\editlib\ccrystaltextmarkers.h" />\r
     <ClInclude Include="..\Externals\crystaledit\editlib\ccrystaltextview.h" />\r
index 2d6f359..56473a2 100644 (file)
     <ClCompile Include="..\Externals\crystaledit\editlib\icu.cpp">\r
       <Filter>EditLib\Source Files</Filter>\r
     </ClCompile>\r
+    <ClCompile Include="..\Externals\crystaledit\editlib\ccrystalrenderergdi.cpp">\r
+      <Filter>EditLib\Source Files</Filter>\r
+    </ClCompile>\r
+    <ClCompile Include="..\Externals\crystaledit\editlib\ccrystalrendererdirectwrite.cpp">\r
+      <Filter>EditLib\Source Files</Filter>\r
+    </ClCompile>\r
     <ClCompile Include="DirSelectFilesDlg.cpp">\r
       <Filter>MFCGui\Dialogs\Source Files</Filter>\r
     </ClCompile>\r
index 283b266..b52eb49 100644 (file)
@@ -104,6 +104,7 @@ END
 
 IDR_SPLASH              IMAGE                   "res\\splash.jpg"
 IDR_LOGO                IMAGE                   "res\\logo.jpg"
+IDR_MARGIN_ICONS_PNG    IMAGE                   "res\\mg_icons.png"
 
 
 /////////////////////////////////////////////////////////////////////////////
index 230b68d..2fcd2da 100644 (file)
@@ -3047,6 +3047,9 @@ void CMergeEditView::OnUpdateShellMenu(CCmdUI* pCmdUI)
  */
 void CMergeEditView::RefreshOptions()
 { 
+       RENDERING_MODE nRenderingMode = static_cast<RENDERING_MODE>(GetOptionsMgr()->GetInt(OPT_RENDERING_MODE));
+       SetRenderingMode(nRenderingMode);
+
        m_bAutomaticRescan = GetOptionsMgr()->GetBool(OPT_AUTOMATIC_RESCAN);
 
        if (GetOptionsMgr()->GetInt(OPT_TAB_TYPE) == 0)
index ec7046e..22d9b8f 100644 (file)
@@ -41,6 +41,7 @@ extern const String OPT_SYNTAX_HIGHLIGHT OP("Settings/HiliteSyntax");
 extern const String OPT_VIEW_WHITESPACE OP("Settings/ViewWhitespace");
 extern const String OPT_CONNECT_MOVED_BLOCKS OP("Settings/ConnectMovedBlocks");
 extern const String OPT_SCROLL_TO_FIRST OP("Settings/ScrollToFirst");
+extern const String OPT_RENDERING_MODE OP("Settings/RenderingMode");
 
 // Difference (in-line) highlight
 extern const String OPT_WORDDIFF_HIGHLIGHT OP("Settings/HiliteWordDiff");
index c44dc2c..5e60bd6 100644 (file)
@@ -78,6 +78,7 @@ void Init(COptionsMgr *pOptions)
        pOptions->InitOption(OPT_VIEW_FILEMARGIN, false);
        pOptions->InitOption(OPT_DIFF_CONTEXT, (int)-1);
        pOptions->InitOption(OPT_SPLIT_HORIZONTALLY, false);
+       pOptions->InitOption(OPT_RENDERING_MODE, -1);
 
        pOptions->InitOption(OPT_WORDDIFF_HIGHLIGHT, true);
        pOptions->InitOption(OPT_BREAK_SEPARATORS, _T(".,:;?[](){}<>`'!\"#$%&^~\\|@+-*/"));
index c38c279..054bcdf 100644 (file)
@@ -31,6 +31,7 @@ PropEditor::PropEditor(COptionsMgr *optionsMgr)
 , m_bViewLineDifferences(false)
 , m_bBreakOnWords(false)
 , m_nBreakType(0)
+, m_nRenderingMode(0)
 {
 }
 
@@ -51,6 +52,7 @@ void PropEditor::DoDataExchange(CDataExchange* pDX)
        DDX_Radio(pDX, IDC_EDITOR_CHARLEVEL, m_bBreakOnWords);
        DDX_CBIndex(pDX, IDC_BREAK_TYPE, m_nBreakType);
        DDX_Text(pDX, IDC_BREAK_CHARS, m_breakChars);
+       DDX_CBIndex(pDX, IDC_RENDERING_MODE, m_nRenderingMode);
        //}}AFX_DATA_MAP
 }
 
@@ -78,6 +80,7 @@ void PropEditor::ReadOptions()
        m_bBreakOnWords = GetOptionsMgr()->GetBool(OPT_BREAK_ON_WORDS);
        m_nBreakType = GetOptionsMgr()->GetInt(OPT_BREAK_TYPE);
        m_breakChars = GetOptionsMgr()->GetString(OPT_BREAK_SEPARATORS);
+       m_nRenderingMode = GetOptionsMgr()->GetInt(OPT_RENDERING_MODE) + 1;
 }
 
 /** 
@@ -99,6 +102,7 @@ void PropEditor::WriteOptions()
        GetOptionsMgr()->SaveOption(OPT_BREAK_ON_WORDS, m_bBreakOnWords);
        GetOptionsMgr()->SaveOption(OPT_BREAK_TYPE, m_nBreakType);
        GetOptionsMgr()->SaveOption(OPT_BREAK_SEPARATORS, String(m_breakChars));
+       GetOptionsMgr()->SaveOption(OPT_RENDERING_MODE, m_nRenderingMode - 1);
 }
 
 /** 
@@ -108,7 +112,7 @@ BOOL PropEditor::OnInitDialog()
 {
        OptionsPanel::OnInitDialog();
 
-       LoadBreakTypeStrings();
+       LoadComboBoxStrings();
        UpdateDataToWindow();
        UpdateLineDiffControls();
 
@@ -119,11 +123,19 @@ BOOL PropEditor::OnInitDialog()
 /**
  * @brief Load strings (from resource) into combobox for break type
  */
-void PropEditor::LoadBreakTypeStrings()
+void PropEditor::LoadComboBoxStrings()
 {
        CComboBox * cbo = (CComboBox *)GetDlgItem(IDC_BREAK_TYPE);
        cbo->AddString(_("Break at whitespace").c_str());
        cbo->AddString(_("Break at whitespace or punctuation").c_str());
+       cbo = (CComboBox *)GetDlgItem(IDC_RENDERING_MODE);
+       cbo->AddString(_("GDI").c_str());
+       cbo->AddString(_("DirectWrite Default").c_str());
+       cbo->AddString(_("DirectWrite Aliased").c_str());
+       cbo->AddString(_("DirectWrite GDI Classic").c_str());
+       cbo->AddString(_("DirectWrite GDI Natural").c_str());
+       cbo->AddString(_("DirectWrite Natural").c_str());
+       cbo->AddString(_("DirectWrite Natural Symmetric").c_str());
 }
 
 /**
index 27c5049..4a0723a 100644 (file)
@@ -39,11 +39,12 @@ public:
        bool    m_bBreakOnWords;
        int     m_nBreakType;
        String m_breakChars;
+       int     m_nRenderingMode;
        //}}AFX_DATA
 
 private:
 // Implementation methods
-       void LoadBreakTypeStrings();
+       void LoadComboBoxStrings();
        void UpdateDataToWindow() { UpdateData(FALSE); }
        void UpdateDataFromWindow() { UpdateData(TRUE); }
        void UpdateLineDiffControls();
diff --git a/Src/res/mg_icons.png b/Src/res/mg_icons.png
new file mode 100644 (file)
index 0000000..50405ae
Binary files /dev/null and b/Src/res/mg_icons.png differ
index eef141c..3989077 100644 (file)
@@ -62,6 +62,7 @@
 #define IDR_LOGO                        307\r
 #define IDR_SPLASH                      308\r
 #define IDB_WINMERGE                    309\r
+#define IDR_MARGIN_ICONS_PNG            310\r
 #define IDB_EDIT_COPY                   316\r
 #define IDB_EDIT_CUT                    317\r
 #define IDB_EDIT_PASTE                  318\r
 #define IDC_USE_DIR_COMPARE_COLORS      1364\r
 #define IDC_PLUGIN_FILEFILTERS          1365\r
 #define IDC_PLUGIN_FILEFILTERS_DEFAULTS 1366\r
+#define IDC_RENDERING_MODE              1367\r
 #define IDC_DIFF_IGNORECP               1377\r
 #define IDC_RESET                       1378\r
 #define IDC_LEFT1                       1379\r
index 4105ede..49cb3b3 100644 (file)
@@ -1745,6 +1745,9 @@ msgstr "Hit&z maila:"
 msgid "W&ord break characters:"
 msgstr ""
 
+msgid "&Rendering Mode:"
+msgstr ""
+
 #, c-format
 msgid "Filefilters"
 msgstr "Agiri-iragazkiak"
index 70cbf17..b33ac71 100644 (file)
@@ -1745,6 +1745,9 @@ msgstr "&Nível das palavras:"
 msgid "W&ord break characters:"
 msgstr "C&aracters da quebra de linha:"
 
+msgid "&Rendering Mode:"
+msgstr ""
+
 #, c-format
 msgid "Filefilters"
 msgstr "Filtros dos arquivos"
index bdc9705..278cd53 100644 (file)
@@ -1346,6 +1346,9 @@ msgstr "На ниво &дума:"
 msgid "W&ord break characters:"
 msgstr "Символ за пренасяне на &дума:"
 
+msgid "&Rendering Mode:"
+msgstr ""
+
 msgid "Filefilters"
 msgstr "Филтри за файлове"
 
index cefc931..e863d79 100644 (file)
@@ -1741,6 +1741,9 @@ msgstr "Nivell de &paraula:"
 msgid "W&ord break characters:"
 msgstr ""
 
+msgid "&Rendering Mode:"
+msgstr ""
+
 #, c-format
 msgid "Filefilters"
 msgstr "Filtres de fitxer"
index b99f6bb..647771d 100644 (file)
@@ -1744,6 +1744,9 @@ msgstr "单词级别(&W):"
 msgid "W&ord break characters:"
 msgstr "单词分隔字符:"
 
+msgid "&Rendering Mode:"
+msgstr ""
+
 #, c-format
 msgid "Filefilters"
 msgstr "文件过滤器"
index f9301fb..c67866b 100644 (file)
@@ -1752,6 +1752,9 @@ msgstr "字階層(&W):"
 msgid "W&ord break characters:"
 msgstr "斷句字元(&O):"
 
+msgid "&Rendering Mode:"
+msgstr ""
+
 #, c-format
 msgid "Filefilters"
 msgstr "檔案篩選器"
index f0f1016..0e31be1 100644 (file)
@@ -1742,6 +1742,9 @@ msgstr "&Rijeć:"
 msgid "W&ord break characters:"
 msgstr ""
 
+msgid "&Rendering Mode:"
+msgstr ""
+
 #, c-format
 msgid "Filefilters"
 msgstr "Filtar redaka"
index ecbce21..b16f065 100644 (file)
@@ -1744,6 +1744,9 @@ msgstr "Na úrovni &slov:"
 msgid "W&ord break characters:"
 msgstr "Zn&aky oddělující slova:"
 
+msgid "&Rendering Mode:"
+msgstr ""
+
 #, c-format
 msgid "Filefilters"
 msgstr "Filtrování souborů"
index 5442ff2..03dcfe5 100644 (file)
@@ -1747,6 +1747,9 @@ msgstr "&Ord niveau:"
 msgid "W&ord break characters:"
 msgstr ""
 
+msgid "&Rendering Mode:"
+msgstr ""
+
 #, c-format
 msgid "Filefilters"
 msgstr "Filfiltre"
index 6ef2dcd..c3dcc3b 100644 (file)
@@ -1352,6 +1352,9 @@ msgstr "Woordniveau:"
 msgid "W&ord break characters:"
 msgstr "Woordsplitsingstekens:"
 
+msgid "&Rendering Mode:"
+msgstr ""
+
 msgid "Filefilters"
 msgstr "Bestandsfilters"
 
index aa3b568..9b71f41 100644 (file)
@@ -1340,6 +1340,9 @@ msgstr ""
 msgid "W&ord break characters:"
 msgstr ""
 
+msgid "&Rendering Mode:"
+msgstr ""
+
 msgid "Filefilters"
 msgstr ""
 
index 3f586ba..b14d6b7 100644 (file)
@@ -1739,6 +1739,9 @@ msgstr "Sanataso:"
 msgid "W&ord break characters:"
 msgstr ""
 
+msgid "&Rendering Mode:"
+msgstr ""
+
 #, c-format
 msgid "Filefilters"
 msgstr "Tiedostosuodattimet"
index 902c7aa..95d9d1f 100644 (file)
@@ -1753,6 +1753,9 @@ msgstr "Précision au &mot :"
 msgid "W&ord break characters:"
 msgstr "Caractères pour distinction de mot :"
 
+msgid "&Rendering Mode:"
+msgstr ""
+
 #, c-format
 msgid "Filefilters"
 msgstr "Filtre des fichiers"
index 91a8774..6590df9 100644 (file)
@@ -1742,6 +1742,9 @@ msgstr "&A nivel da palabra:"
 msgid "W&ord break characters:"
 msgstr ""
 
+msgid "&Rendering Mode:"
+msgstr ""
+
 #, c-format
 msgid "Filefilters"
 msgstr "Filtros de arquivos"
index c3b8bac..66d54b6 100644 (file)
@@ -1744,6 +1744,9 @@ msgstr "&Wort-Ebene:"
 msgid "W&ord break characters:"
 msgstr "W&ortumbruchzeichen:"
 
+msgid "&Rendering Mode:"
+msgstr ""
+
 #, c-format
 msgid "Filefilters"
 msgstr "Dateifilter"
index f7a6334..e5c4a57 100644 (file)
@@ -1741,6 +1741,9 @@ msgstr "Επίπεδο &Λέξεων"
 msgid "W&ord break characters:"
 msgstr ""
 
+msgid "&Rendering Mode:"
+msgstr ""
+
 #, c-format
 msgid "Filefilters"
 msgstr "Αρχειοφίλτρα"
index 87c0904..656a857 100644 (file)
@@ -1742,6 +1742,9 @@ msgstr ""
 msgid "W&ord break characters:"
 msgstr ""
 
+msgid "&Rendering Mode:"
+msgstr ""
+
 #, c-format
 msgid "Filefilters"
 msgstr "FájlSzűrők"
index 55db8f6..7bd110a 100644 (file)
@@ -1350,6 +1350,9 @@ msgstr "Livello &parole:"
 msgid "W&ord break characters:"
 msgstr "Caratteri terminatori &parola:"
 
+msgid "&Rendering Mode:"
+msgstr ""
+
 msgid "Filefilters"
 msgstr "Filtri file"
 
index da4ce52..5c0e188 100644 (file)
@@ -1355,6 +1355,9 @@ msgstr "単語単位(&W):"
 msgid "W&ord break characters:"
 msgstr "単語区切り文字(&O)"
 
+msgid "&Rendering Mode:"
+msgstr "レンダリングモード(&R):"
+
 msgid "Filefilters"
 msgstr "ファイル フィルタ"
 
index 8d968ab..21ff0f1 100644 (file)
@@ -1746,6 +1746,9 @@ msgstr "단어 단위(&W):"
 msgid "W&ord break characters:"
 msgstr "단어 분리 문자(&O):"
 
+msgid "&Rendering Mode:"
+msgstr ""
+
 #, c-format
 msgid "Filefilters"
 msgstr "파일 필터"
index dd11ff0..4ed41db 100644 (file)
@@ -1349,6 +1349,9 @@ msgstr "Žo&džio lygyje:"
 msgid "W&ord break characters:"
 msgstr "Ž&odžių skirtukų simboliai:"
 
+msgid "&Rendering Mode:"
+msgstr ""
+
 msgid "Filefilters"
 msgstr "Failo filtrai"
 
index ad34df2..0dab80b 100644 (file)
@@ -1742,6 +1742,9 @@ msgstr "&Ord-nivå:"
 msgid "W&ord break characters:"
 msgstr ""
 
+msgid "&Rendering Mode:"
+msgstr ""
+
 #, c-format
 msgid "Filefilters"
 msgstr "Filfiltere"
index 15e8a66..4c1b244 100644 (file)
@@ -1749,6 +1749,9 @@ msgstr "&W در سطح کلمه : "
 msgid "W&ord break characters:"
 msgstr ""
 
+msgid "&Rendering Mode:"
+msgstr ""
+
 #, c-format
 msgid "Filefilters"
 msgstr " پرونده صافيها "
index 1635d41..1dcb78c 100644 (file)
@@ -1346,6 +1346,10 @@ msgstr "Poziom słów:"
 msgid "W&ord break characters:"
 msgstr "Znaki łamania wyrazów:"
 
+msgid "&Rendering Mode:"
+msgstr ""
+
+#, c-format
 msgid "Filefilters"
 msgstr "Filtry plików"
 
index 4ff6d28..062e1ee 100644 (file)
@@ -1744,6 +1744,9 @@ msgstr "A nível da palavra:"
 msgid "W&ord break characters:"
 msgstr "Caracteres da palavra:"
 
+msgid "&Rendering Mode:"
+msgstr ""
+
 #, c-format
 msgid "Filefilters"
 msgstr "Filtros de ficheiro"
index d96d19a..53d9fb7 100644 (file)
@@ -1742,6 +1742,9 @@ msgstr "La nivel de cu&vânt:"
 msgid "W&ord break characters:"
 msgstr ""
 
+msgid "&Rendering Mode:"
+msgstr ""
+
 #, c-format
 msgid "Filefilters"
 msgstr "Filtre fişiere"
index 87503e9..e38db32 100644 (file)
@@ -1744,6 +1744,9 @@ msgstr "По словам:"
 msgid "W&ord break characters:"
 msgstr "Символы разрыва слова:"
 
+msgid "&Rendering Mode:"
+msgstr ""
+
 #, c-format
 msgid "Filefilters"
 msgstr "Фильтры файлов"
index 97b9f45..3d90ec5 100644 (file)
@@ -1725,6 +1725,9 @@ msgstr "Ранг ре&чи:"
 msgid "W&ord break characters:"
 msgstr ""
 
+msgid "&Rendering Mode:"
+msgstr ""
+
 #, c-format
 msgid "Filefilters"
 msgstr "Филтер датотека"
index 5205c85..80020e0 100644 (file)
@@ -1739,6 +1739,9 @@ msgstr "& වචනයෙහි පිහිටුම"
 msgid "W&ord break characters:"
 msgstr ""
 
+msgid "&Rendering Mode:"
+msgstr ""
+
 #, c-format
 msgid "Filefilters"
 msgstr "ගොනුපෙරහන්"
index f80f8b2..b760708 100644 (file)
@@ -1742,6 +1742,9 @@ msgstr "Úroveň &slova:"
 msgid "W&ord break characters:"
 msgstr "Zalam&ovať slová:"
 
+msgid "&Rendering Mode:"
+msgstr ""
+
 #, c-format
 msgid "Filefilters"
 msgstr "Filtre súborov"
index 48b314f..5264f5d 100644 (file)
@@ -1745,6 +1745,9 @@ msgstr "&besednem nivoju"
 msgid "W&ord break characters:"
 msgstr "&Znak za konec besede"
 
+msgid "&Rendering Mode:"
+msgstr ""
+
 #, c-format
 msgid "Filefilters"
 msgstr "Datotečni filtri"
index 34c6607..57252d0 100644 (file)
@@ -1744,6 +1744,9 @@ msgstr "A nivel de &palabra:"
 msgid "W&ord break characters:"
 msgstr ""
 
+msgid "&Rendering Mode:"
+msgstr ""
+
 #, c-format
 msgid "Filefilters"
 msgstr "Filtros de archivo"
index fedea7a..62b5b2a 100644 (file)
@@ -1742,6 +1742,9 @@ msgstr "Ordnivå:"
 msgid "W&ord break characters:"
 msgstr "Ordbrytningstecken:"
 
+msgid "&Rendering Mode:"
+msgstr ""
+
 #, c-format
 msgid "Filefilters"
 msgstr "Filfilter"
index f464b63..4335d63 100644 (file)
@@ -1745,6 +1745,9 @@ msgstr "&Sözcük Düzeyinde:"
 msgid "W&ord break characters:"
 msgstr "&Sözcük Kesme Karakterleri:"
 
+msgid "&Rendering Mode:"
+msgstr ""
+
 #, c-format
 msgid "Filefilters"
 msgstr "Dosya Süzgeçleri"
index bbd2126..41c0d98 100644 (file)
@@ -1743,6 +1743,9 @@ msgstr "За словами:"
 msgid "W&ord break characters:"
 msgstr "Символи, якимми розбиваються слова"
 
+msgid "&Rendering Mode:"
+msgstr ""
+
 #, c-format
 msgid "Filefilters"
 msgstr "Фільтри файлів"