OSDN Git Service

Made it possible to display the contents of CSV and TSV files like spreadsheet softwa...
[winmerge-jp/winmerge-jp.git] / Externals / crystaledit / editlib / renderers / ccrystalrenderergdi.cpp
1 /**
2  * @file  ccrystalrenderergdi.cpp
3  *
4  * @brief Implementation of the CCrystalRendererGDI class
5  */
6
7 #include "StdAfx.h"
8 #include "ccrystalrenderergdi.h"
9 #include "resource.h"
10
11 CImageList* CCrystalRendererGDI::s_pIcons = nullptr;
12
13 /////////////////////////////////////////////////////////////////////////////
14 // CCrystalRendererGDI construction/destruction
15
16 CCrystalRendererGDI::CCrystalRendererGDI() :
17   m_pDC(nullptr)
18 , m_lfBaseFont{}
19 , m_gridPen(PS_SOLID, 0, RGB(0xC0, 0xC0, 0xC0))
20 {
21 }
22
23 CCrystalRendererGDI::~CCrystalRendererGDI ()
24 {
25 }
26
27 void CCrystalRendererGDI::BindDC(const CDC& dc, const CRect& rc)
28 {
29         m_pDC = const_cast<CDC *>(&dc);
30 }
31
32 void CCrystalRendererGDI::BeginDraw()
33 {
34         m_pDC->SaveDC();
35 }
36
37 bool CCrystalRendererGDI::EndDraw()
38 {
39         m_pDC->RestoreDC(-1);
40         return true;
41 }
42
43 void CCrystalRendererGDI::SetFont(const LOGFONT &lf)
44 {
45         m_lfBaseFont = lf;
46         for (int nIndex = 0; nIndex < 4; ++nIndex)
47         {
48                 bool bold = (nIndex & 1) != 0;
49                 bool italic = (nIndex & 2) != 0;
50                 m_apFonts[nIndex].reset(new CFont());
51                 if (!m_lfBaseFont.lfHeight)
52                 {
53                         CClientDC dc (CWnd::GetDesktopWindow());
54                         m_lfBaseFont.lfHeight = -MulDiv (11, dc.GetDeviceCaps (LOGPIXELSY), 72);
55                 }
56                 m_lfBaseFont.lfWeight = bold ? FW_BOLD : FW_NORMAL;
57                 m_lfBaseFont.lfItalic = (BYTE) italic;
58                 if (!m_apFonts[nIndex]->CreateFontIndirect(&m_lfBaseFont))
59                         m_apFonts[nIndex].reset(nullptr);
60         }
61 }
62
63 void CCrystalRendererGDI::SwitchFont(bool italic, bool bold)
64 {
65         int nIndex = 0;
66         if (bold)
67                 nIndex |= 1;
68         if (italic)
69                 nIndex |= 2;
70         m_pDC->SelectObject(m_apFonts[nIndex].get());
71 }
72
73 CSize CCrystalRendererGDI::GetCharWidthHeight()
74 {
75         if (!m_apFonts[3])
76                 SetFont(m_lfBaseFont);
77         CClientDC dc (CWnd::GetDesktopWindow());
78         CFont *pOldFont = dc.SelectObject(m_apFonts[3].get());
79         CSize sizeItalicBold = dc.GetTextExtent(_T("X"));
80         dc.SelectObject(m_apFonts[0].get());
81         CSize sizeNormal = dc.GetTextExtent(_T("X"));
82         dc.SelectObject(pOldFont);
83         return CSize{ sizeNormal.cx, (std::max)(sizeNormal.cy, sizeItalicBold.cy) };
84 }
85
86 bool CCrystalRendererGDI::GetCharWidth(unsigned start, unsigned end, int * nWidthArray)
87 {
88         if (!m_apFonts[3])
89                 SetFont(m_lfBaseFont);
90         CClientDC dc (CWnd::GetDesktopWindow());
91         CFont *pOldFont = dc.SelectObject(m_apFonts[3].get());
92         bool succeeded = !!GetCharWidth32(dc.m_hDC, start, end, nWidthArray);
93         dc.SelectObject(pOldFont);
94         return succeeded;
95 }
96
97 void CCrystalRendererGDI::SetTextColor(COLORREF clr)
98 {
99         m_pDC->SetTextColor(clr);
100 }
101
102 void CCrystalRendererGDI::SetBkColor(COLORREF clr)
103 {
104         m_pDC->SetBkColor(clr);
105 }
106
107 void CCrystalRendererGDI::FillRectangle(const CRect &rc)
108 {
109         m_pDC->FillSolidRect(&rc, m_pDC->GetBkColor());
110 }
111
112 void CCrystalRendererGDI::FillSolidRectangle(const CRect &rc, COLORREF color)
113 {
114         m_pDC->FillSolidRect(&rc, color);
115 }
116
117 void CCrystalRendererGDI::DrawRoundRectangle(int left, int top, int right, int bottom, int width, int height)
118 {
119         CBrush brush;
120         brush.CreateStockObject(NULL_BRUSH);
121         CBrush* pOldBrush = m_pDC->SelectObject(&brush);
122         CPen pen(PS_SOLID, 1, m_pDC->GetTextColor());
123         CPen *pOldPen = m_pDC->SelectObject(&pen);
124
125         m_pDC->RoundRect(left, top, right, bottom, width, height);
126
127         m_pDC->SelectObject(pOldPen);
128         m_pDC->SelectObject(pOldBrush);
129 }
130
131 void CCrystalRendererGDI::PushAxisAlignedClip(const CRect & rc)
132 {
133         m_pDC->SaveDC();
134         m_pDC->IntersectClipRect(&rc);
135 }
136
137 void CCrystalRendererGDI::PopAxisAlignedClip()
138 {
139         m_pDC->RestoreDC(-1);
140 }
141
142 void CCrystalRendererGDI::DrawMarginIcon(int x, int y, int iconIndex)
143 {
144         if (s_pIcons == nullptr)
145         {
146                 s_pIcons = new CImageList;
147                 VERIFY(s_pIcons->Create(MARGIN_ICON_WIDTH, MARGIN_ICON_HEIGHT,
148                         ILC_COLOR32 | ILC_MASK, 0, 1));
149                 CBitmap bmp;
150                 bmp.LoadBitmap(IDR_MARGIN_ICONS);
151                 s_pIcons->Add(&bmp, RGB(255, 255, 255));
152         }
153         if (iconIndex >= 0)
154         {
155                 CPoint pt(x, y);
156                 VERIFY(s_pIcons->Draw(m_pDC, iconIndex, pt, ILD_TRANSPARENT));
157         }
158 }
159
160 void CCrystalRendererGDI::DrawMarginLineNumber(int x, int y, int number)
161 {
162         CFont *pOldFont = m_pDC->SelectObject(m_apFonts[0].get());
163         TCHAR szNumbers[32];
164         int len = wsprintf(szNumbers, _T("%d"), number);
165         UINT uiOldAlign = m_pDC->SetTextAlign(TA_RIGHT);
166         m_pDC->TextOut(x - (m_pDC->IsPrinting() ? 0 : 4), y, szNumbers, len);
167         m_pDC->SetTextAlign(uiOldAlign);
168         m_pDC->SelectObject(pOldFont);
169 }
170
171 void CCrystalRendererGDI::DrawBoundaryLine(int left, int right, int y)
172 {
173         CPen *pOldPen = (CPen *)m_pDC->SelectStockObject(BLACK_PEN);
174         m_pDC->MoveTo(left, y);
175         m_pDC->LineTo(right, y);
176         m_pDC->SelectObject(pOldPen);
177 }
178
179 void CCrystalRendererGDI::DrawGridLine(int x1, int y1, int x2, int y2)
180 {
181         if (x1 == x2 || y1 == y2)
182         {
183                 CDC  dcMem;
184                 dcMem.CreateCompatibleDC(m_pDC);
185                 CBitmap bitmap;
186                 if (x1 == x2)
187                         bitmap.CreateCompatibleBitmap(m_pDC, 1, y2 - y1);
188                 else
189                         bitmap.CreateCompatibleBitmap(m_pDC, x2 - x1, 1);
190                 CBitmap *pOldBitmap = dcMem.SelectObject(&bitmap);
191                 dcMem.SetBkColor(RGB(0, 255, 0));
192                 BLENDFUNCTION blend = { 0 };
193                 blend.BlendOp = AC_SRC_OVER;
194                 blend.SourceConstantAlpha = 24;
195                 if (x1 == x2)
196                         m_pDC->AlphaBlend(x1, y1, 1, y2 - y1, &dcMem, 0, 0, 1, y2 - y1, blend);
197                 else
198                         m_pDC->AlphaBlend(x1, y1, x2 - x1, 1, &dcMem, 0, 0, x2 - x1, 1, blend);
199                 dcMem.SelectObject(pOldBitmap);
200         }
201         else
202         {
203                 CPen* pOldPen = (CPen*)m_pDC->SelectObject(&m_gridPen);
204                 m_pDC->MoveTo(x1, y1);
205                 m_pDC->LineTo(x2, y2);
206                 m_pDC->SelectObject(pOldPen);
207         }
208 }
209
210 void CCrystalRendererGDI::DrawLineCursor(int left, int right, int y, int height)
211 {
212         CDC  dcMem;
213         dcMem.CreateCompatibleDC(m_pDC);
214         CBitmap bitmap;
215         bitmap.CreateCompatibleBitmap(m_pDC, right - left, height);
216         CBitmap *pOldBitmap = dcMem.SelectObject(&bitmap);
217         dcMem.SetBkColor(RGB(0, 255, 0));
218         BLENDFUNCTION blend = { 0 };
219         blend.BlendOp = AC_SRC_OVER;
220         blend.SourceConstantAlpha = 24;
221         m_pDC->AlphaBlend(left, y, right - left, height, &dcMem, 0, 0, right - left, height, blend);
222         dcMem.SelectObject(pOldBitmap);
223 }
224
225 void CCrystalRendererGDI::DrawText(int x, int y, const CRect &rc, const TCHAR *text, size_t len, const int nWidths[])
226 {
227         m_pDC->ExtTextOut(x, y, ETO_CLIPPED | ETO_OPAQUE, &rc, text, static_cast<UINT>(len), const_cast<int *>(nWidths));
228 }
229
230 void CCrystalRendererGDI::DrawRuler(int left, int top, int width, int height, int charwidth, int offset)
231 {
232         CFont *pOldFont = m_pDC->SelectObject(m_apFonts[0].get());
233         UINT uiOldAlign = m_pDC->SetTextAlign(TA_LEFT);
234         CPen *pOldPen = (CPen *)m_pDC->SelectStockObject(BLACK_PEN);
235         int bottom = top + height - 1;
236         int prev10 = (offset / 10) * 10;
237         TCHAR szNumbers[32];
238         int len = wsprintf(szNumbers, _T("%d"), prev10);
239         if ((offset % 10) != 0 && offset - prev10 < len)
240                 m_pDC->TextOut(left, bottom - height, szNumbers + (offset - prev10), len - (offset - prev10));
241         for (int i = 0; i < width / charwidth; ++i)
242         {
243                 int x = left + i * charwidth;
244                 if (((i + offset) % 10) == 0)
245                 {
246                         len = wsprintf(szNumbers, _T("%d"), offset + i);
247                         m_pDC->TextOut(x, bottom - height + 1, szNumbers, len);
248                 }
249                 float tickscale = [](int i, int offset) {
250                         if (((i + offset) % 10) == 0)
251                                 return 0.6f;
252                         else if (((i + offset) % 5) == 0)
253                                 return 0.4f;
254                         else
255                                 return 0.2f;
256                 }(i, offset);
257                 m_pDC->MoveTo(x, bottom - static_cast<int>(height * tickscale));
258                 m_pDC->LineTo(x, bottom);
259         }
260         m_pDC->MoveTo(left, bottom);
261         m_pDC->LineTo(left + width, bottom);
262         m_pDC->SelectObject(pOldPen);
263         m_pDC->SetTextAlign(uiOldAlign);
264         m_pDC->SelectObject(pOldFont);
265 }
266