ReactOS 0.4.15-dev-7681-g776c3a3
selectionmodel.cpp
Go to the documentation of this file.
1/*
2 * PROJECT: PAINT for ReactOS
3 * LICENSE: LGPL-2.0-or-later (https://spdx.org/licenses/LGPL-2.0-or-later)
4 * PURPOSE: Keep track of selection parameters, notify listeners
5 * COPYRIGHT: Copyright 2015 Benedikt Freisen <b.freisen@gmx.net>
6 * Copyright 2019 Katayama Hirofumi MZ <katayama.hirofumi.mz@gmail.com>
7 */
8
9#include "precomp.h"
10
12
13/* FUNCTIONS ********************************************************/
14
16 : m_hbmColor(NULL)
17 , m_hbmMask(NULL)
18 , m_rgbBack(RGB(255, 255, 255))
19 , m_bShow(FALSE)
20 , m_bContentChanged(FALSE)
21{
24 m_ptHit = { -1, -1 };
25}
26
28{
31}
32
34{
35 if (m_rcOld.IsRectEmpty())
36 return;
37
38 HGDIOBJ hbrOld = ::SelectObject(hDCImage, ::GetStockObject(DC_BRUSH));
39 ::SetDCBrushColor(hDCImage, crBg);
42 ::SelectObject(hDCImage, hbrOld);
43}
44
46{
47 if (m_rcOld.IsRectEmpty())
48 return;
49
50 Rect(hDCImage, m_rcOld.left, m_rcOld.top, m_rcOld.right, m_rcOld.bottom, crBg, crBg, 0, 1);
51}
52
54{
56 DrawBackgroundPoly(hDCImage, crBg);
57 else
58 DrawBackgroundRect(hDCImage, crBg);
59}
60
61void SelectionModel::DrawSelection(HDC hDCImage, COLORREF crBg, BOOL bBgTransparent)
62{
63 CRect rc = m_rc;
64 if (rc.IsRectEmpty())
65 return;
66
67 BITMAP bm;
68 if (!GetObjectW(m_hbmColor, sizeof(BITMAP), &bm))
69 return;
70
71 COLORREF keyColor = (bBgTransparent ? crBg : CLR_INVALID);
72
73 HDC hMemDC = CreateCompatibleDC(hDCImage);
74 HGDIOBJ hbmOld = SelectObject(hMemDC, m_hbmColor);
75 ColorKeyedMaskBlt(hDCImage, rc.left, rc.top, rc.Width(), rc.Height(),
76 hMemDC, 0, 0, bm.bmWidth, bm.bmHeight, m_hbmMask, keyColor);
77 SelectObject(hMemDC, hbmOld);
78 DeleteDC(hMemDC);
79}
80
81void SelectionModel::setMask(const CRect& rc, HBITMAP hbmMask)
82{
83 if (m_hbmMask)
85
86 m_hbmMask = hbmMask;
87 m_rc = m_rcOld = rc;
88}
89
91{
92 if (m_hbmColor)
94
95 HBITMAP hbmWhole = imageModel.LockBitmap();
96 HBITMAP hbmPart = getSubImage(hbmWhole, m_rc);
97 imageModel.UnlockBitmap(hbmWhole);
98 return hbmPart;
99}
100
102{
103 return !m_hbmColor;
104}
105
107{
108 if (!IsLanded() || m_rc.IsRectEmpty())
109 return FALSE;
110
111 // The background color is needed for transparency of selection
113
114 // Get the contents of the selection area
117
118 // RectSel doesn't need the mask image
121
122 // Save the selection area
123 m_rcOld = m_rc;
124
126 return TRUE;
127}
128
130{
131 if (IsLanded() && !m_bShow)
132 {
134 return;
135 }
136
137 if (m_bContentChanged ||
139 {
140 CRect rc;
143
146 }
147
149}
150
152{
154 m_hbmColor = hbmColor;
155
156 m_rc.left = x;
157 m_rc.top = y;
158 m_rc.right = x + GetDIBWidth(hbmColor);
159 m_rc.bottom = y + GetDIBHeight(hbmColor);
160
161 if (hbmMask)
162 {
164 m_hbmMask = hbmMask;
165 }
166 else
167 {
169 }
170
172}
173
175{
176 TakeOff();
177
179 if (m_hbmMask)
180 {
183 hdcMem, 0, 0, m_rc.Width(), m_rc.Height(), SRCCOPY);
184 }
185 if (m_hbmColor)
186 {
189 hdcMem, 0, 0, m_rc.Width(), m_rc.Height(), SRCCOPY);
190 }
192
194}
195
197{
198 TakeOff();
199
201 if (m_hbmMask)
202 {
205 hdcMem, 0, 0, m_rc.Width(), m_rc.Height(), SRCCOPY);
206 }
207 if (m_hbmColor)
208 {
211 hdcMem, 0, 0, m_rc.Width(), m_rc.Height(), SRCCOPY);
212 }
214
216}
217
219{
220 HBITMAP hbm;
221 HGDIOBJ hbmOld;
223
224 switch (iN)
225 {
226 case 1: /* rotate 90 degrees */
227 case 3: /* rotate 270 degrees */
228 TakeOff();
229
230 if (m_hbmColor)
231 {
234 ::SelectObject(hdcMem, hbmOld);
236 m_hbmColor = hbm;
237 }
238 if (m_hbmMask)
239 {
242 ::SelectObject(hdcMem, hbmOld);
244 m_hbmMask = hbm;
245 }
246
248 break;
249
250 case 2: /* rotate 180 degrees */
251 TakeOff();
252
253 if (m_hbmColor)
254 {
257 hdcMem, 0, 0, m_rc.Width(), m_rc.Height(), SRCCOPY);
258 ::SelectObject(hdcMem, hbmOld);
259 }
260 if (m_hbmMask)
261 {
264 hdcMem, 0, 0, m_rc.Width(), m_rc.Height(), SRCCOPY);
265 ::SelectObject(hdcMem, hbmOld);
266 }
267 break;
268 }
269
272}
273
274static void AttachHBITMAP(HBITMAP *phbm, HBITMAP hbmNew)
275{
276 if (hbmNew == NULL)
277 return;
278 ::DeleteObject(*phbm);
279 *phbm = hbmNew;
280}
281
282void SelectionModel::StretchSkew(int nStretchPercentX, int nStretchPercentY, int nSkewDegX, int nSkewDegY)
283{
284 if (nStretchPercentX == 100 && nStretchPercentY == 100 && nSkewDegX == 0 && nSkewDegY == 0)
285 return;
286
287 TakeOff();
288
289 INT oldWidth = m_rc.Width(), oldHeight = m_rc.Height();
290 INT newWidth = oldWidth * nStretchPercentX / 100;
291 INT newHeight = oldHeight * nStretchPercentY / 100;
292
293 HBITMAP hbmColor = m_hbmColor, hbmMask = m_hbmMask;
294
295 if (hbmMask == NULL)
296 hbmMask = CreateMonoBitmap(oldWidth, oldHeight, TRUE);
297
298 if (oldWidth != newWidth || oldHeight != newHeight)
299 {
300 AttachHBITMAP(&hbmColor, CopyDIBImage(hbmColor, newWidth, newHeight));
301 AttachHBITMAP(&hbmMask, CopyMonoImage(hbmMask, newWidth, newHeight));
302 }
303
304 HGDIOBJ hbmOld;
306
307 if (nSkewDegX)
308 {
309 hbmOld = ::SelectObject(hDC, hbmColor);
310 AttachHBITMAP(&hbmColor, SkewDIB(hDC, hbmColor, nSkewDegX, FALSE));
311 ::SelectObject(hDC, hbmMask);
312 AttachHBITMAP(&hbmMask, SkewDIB(hDC, hbmMask, nSkewDegX, FALSE, TRUE));
313 ::SelectObject(hDC, hbmOld);
314 }
315
316 if (nSkewDegY)
317 {
318 hbmOld = ::SelectObject(hDC, hbmColor);
319 AttachHBITMAP(&hbmColor, SkewDIB(hDC, hbmColor, nSkewDegY, TRUE));
320 ::SelectObject(hDC, hbmMask);
321 AttachHBITMAP(&hbmMask, SkewDIB(hDC, hbmMask, nSkewDegY, TRUE, TRUE));
322 ::SelectObject(hDC, hbmOld);
323 }
324
326
327 InsertFromHBITMAP(hbmColor, m_rc.left, m_rc.top, hbmMask);
328
329 m_bShow = TRUE;
331}
332
333void SelectionModel::SetRectFromPoints(const POINT& ptFrom, const POINT& ptTo)
334{
335 m_rc = CRect(ptFrom, ptTo);
337}
338
340{
341 switch (hit)
342 {
343 case HIT_NONE:
344 break;
345 case HIT_UPPER_LEFT:
346 m_rc.left += pt.x - m_ptHit.x;
347 m_rc.top += pt.y - m_ptHit.y;
348 break;
349 case HIT_UPPER_CENTER:
350 m_rc.top += pt.y - m_ptHit.y;
351 break;
352 case HIT_UPPER_RIGHT:
353 m_rc.right += pt.x - m_ptHit.x;
354 m_rc.top += pt.y - m_ptHit.y;
355 break;
356 case HIT_MIDDLE_LEFT:
357 m_rc.left += pt.x - m_ptHit.x;
358 break;
359 case HIT_MIDDLE_RIGHT:
360 m_rc.right += pt.x - m_ptHit.x;
361 break;
362 case HIT_LOWER_LEFT:
363 m_rc.left += pt.x - m_ptHit.x;
364 m_rc.bottom += pt.y - m_ptHit.y;
365 break;
366 case HIT_LOWER_CENTER:
367 m_rc.bottom += pt.y - m_ptHit.y;
368 break;
369 case HIT_LOWER_RIGHT:
370 m_rc.right += pt.x - m_ptHit.x;
371 m_rc.bottom += pt.y - m_ptHit.y;
372 break;
373 case HIT_BORDER:
374 case HIT_INNER:
375 m_rc.OffsetRect(pt.x - m_ptHit.x, pt.y - m_ptHit.y);
376 break;
377 }
378 m_ptHit = pt;
379}
380
382{
383 if (m_hbmMask)
384 {
386 m_hbmMask = NULL;
387 }
388}
389
391{
392 if (m_hbmColor)
393 {
396 }
397}
398
400{
407}
408
410{
411 if (!m_bShow)
412 return;
413
414 TakeOff();
417
419}
420
422{
423 TakeOff();
424
425 BITMAP bm;
426 ::GetObjectW(m_hbmColor, sizeof(bm), &bm);
427
430 RECT rc = { 0, 0, bm.bmWidth, bm.bmHeight };
431 ::InvertRect(hdc, &rc);
432 ::SelectObject(hdc, hbmOld);
434
436}
437
439{
442}
443
445{
446 INT cx = m_rc.Width(), cy = m_rc.Height();
447 m_rc.right = m_rc.left + cy;
448 m_rc.bottom = m_rc.top + cx;
449}
450
452{
453 if (!m_bShow)
454 return HIT_NONE;
455
456 CRect rcSelection = m_rc;
457 canvasWindow.ImageToCanvas(rcSelection);
458 rcSelection.InflateRect(GRIP_SIZE, GRIP_SIZE);
459 return getSizeBoxHitTest(ptCanvas, &rcSelection);
460}
461
463{
464 if (!m_bShow)
465 return;
466
467 CRect rcSelection = m_rc;
468 canvasWindow.ImageToCanvas(rcSelection);
469 rcSelection.InflateRect(GRIP_SIZE, GRIP_SIZE);
470 drawSizeBoxes(hCanvasDC, &rcSelection, TRUE);
471}
472
474{
475 if (!m_bShow)
476 return;
477
478 TakeOff();
479 m_rc.OffsetRect(xDelta, yDelta);
480 canvasWindow.Invalidate();
481}
482
484{
485 if (!m_bShow)
486 return;
487
488 TakeOff();
489
490 INT cx = m_rc.Width(), cy = m_rc.Height();
491
492 if (bShrink)
493 m_rc.InflateRect(-cx / 4, -cy / 4);
494 else
495 m_rc.InflateRect(+cx / 2, +cy / 2);
496
497 // The selection area must exist there
498 if (m_rc.Width() <= 0)
499 m_rc.right = m_rc.left + 1;
500 if (m_rc.Height() <= 0)
501 m_rc.bottom = m_rc.top + 1;
502
504}
static HDC hDC
Definition: 3dtext.c:33
static HBITMAP CopyDIBImage(HBITMAP hbm, INT cx=0, INT cy=0)
Definition: dib.h:19
ToolsModel toolsModel
Definition: toolsmodel.cpp:10
#define GRIP_SIZE
Definition: precomp.h:43
HITTEST
Definition: precomp.h:55
@ HIT_NONE
Definition: precomp.h:56
@ HIT_BORDER
Definition: precomp.h:65
@ HIT_LOWER_RIGHT
Definition: precomp.h:64
@ HIT_LOWER_CENTER
Definition: precomp.h:63
@ HIT_UPPER_LEFT
Definition: precomp.h:57
@ HIT_INNER
Definition: precomp.h:66
@ HIT_LOWER_LEFT
Definition: precomp.h:62
@ HIT_UPPER_CENTER
Definition: precomp.h:58
@ HIT_UPPER_RIGHT
Definition: precomp.h:59
@ HIT_MIDDLE_RIGHT
Definition: precomp.h:61
@ HIT_MIDDLE_LEFT
Definition: precomp.h:60
CCanvasWindow canvasWindow
Definition: canvas.cpp:10
BOOL m_drawing
Definition: canvas.h:43
VOID ImageToCanvas(POINT &pt)
Definition: canvas.cpp:40
void SetRectEmpty() noexcept
Definition: atltypes.h:431
void InflateRect(int x, int y) noexcept
Definition: atltypes.h:323
void OffsetRect(int x, int y) noexcept
Definition: atltypes.h:403
void NormalizeRect() noexcept
Definition: atltypes.h:387
BOOL UnionRect(LPCRECT lpRect1, LPCRECT lpRect2) noexcept
Definition: atltypes.h:456
int Width() const noexcept
Definition: atltypes.h:461
int Height() const noexcept
Definition: atltypes.h:318
BOOL IsRectEmpty() const noexcept
Definition: atltypes.h:351
BOOL EqualRect(LPCRECT lpRect) const noexcept
Definition: atltypes.h:312
HBITMAP LockBitmap()
Definition: history.cpp:345
void PushImageForUndo()
Definition: history.cpp:127
void NotifyImageChanged()
Definition: history.cpp:23
void UnlockBitmap(HBITMAP hbmLocked)
Definition: history.cpp:354
HDC GetDC()
Definition: history.cpp:271
COLORREF GetBgColor() const
HBITMAP m_hbmColor
void DrawBackground(HDC hDCImage, COLORREF crBg)
void DrawBackgroundPoly(HDC hDCImage, COLORREF crBg)
void RotateNTimes90Degrees(int iN)
void StretchSkew(int nStretchPercentX, int nStretchPercentY, int nSkewDegX, int nSkewDegY)
HBITMAP GetSelectionContents()
void InsertFromHBITMAP(HBITMAP hbmColor, INT x=0, INT y=0, HBITMAP hbmMask=NULL)
COLORREF m_rgbBack
void NotifyContentChanged()
void moveSelection(INT xDelta, INT yDelta)
void drawFrameOnCanvas(HDC hCanvasDC)
void Dragging(HITTEST hit, POINT pt)
void setMask(const CRect &rc, HBITMAP hbmMask)
HITTEST hitTest(POINT ptCanvas)
BOOL IsLanded() const
void DrawSelection(HDC hDCImage, COLORREF crBg=0, BOOL bBgTransparent=FALSE)
void SetRectFromPoints(const POINT &ptFrom, const POINT &ptTo)
void DrawBackgroundRect(HDC hDCImage, COLORREF crBg)
void StretchSelection(BOOL bShrink)
void OnDrawOverlayOnImage(HDC hdc)
Definition: mouse.cpp:1186
TOOLTYPE GetActiveTool() const
Definition: toolsmodel.cpp:134
HBITMAP getSubImage(HBITMAP hbmWhole, const RECT &rcPartial)
Definition: dib.cpp:409
HBITMAP SkewDIB(HDC hDC1, HBITMAP hbm, INT nDegree, BOOL bVertical, BOOL bMono)
Definition: dib.cpp:351
HBITMAP Rotate90DegreeBlt(HDC hDC1, INT cx, INT cy, BOOL bRight, BOOL bMono)
Definition: dib.cpp:312
HBITMAP CopyMonoImage(HBITMAP hbm, INT cx, INT cy)
Definition: dib.cpp:87
int GetDIBHeight(HBITMAP hBitmap)
Definition: dib.cpp:144
HBITMAP CreateMonoBitmap(int width, int height, BOOL bWhite)
Definition: dib.cpp:45
int GetDIBWidth(HBITMAP hBitmap)
Definition: dib.cpp:136
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
#define pt(x, y)
Definition: drawing.c:79
BOOL ColorKeyedMaskBlt(HDC hdcDest, int nXDest, int nYDest, int nWidth, int nHeight, HDC hdcSrc, int nXSrc, int nYSrc, int nSrcWidth, int nSrcHeight, HBITMAP hbmMask, COLORREF keyColor)
Definition: drawing.cpp:287
#define RGB(r, g, b)
Definition: precomp.h:62
unsigned int BOOL
Definition: ntddk_ex.h:94
pKey DeleteObject()
GLint GLint GLint GLint GLint x
Definition: gl.h:1548
GLint GLint GLint GLint GLint GLint y
Definition: gl.h:1548
ImageModel imageModel
Definition: history.cpp:11
HDC hdc
Definition: main.c:9
static HBITMAP
Definition: button.c:44
static HDC
Definition: imagelist.c:92
_In_ HBITMAP hbm
Definition: ntgdi.h:2776
PaletteModel paletteModel
_Out_opt_ int _Out_opt_ int * cy
Definition: commctrl.h:586
_Out_opt_ int * cx
Definition: commctrl.h:585
SelectionModel selectionModel
static void AttachHBITMAP(HBITMAP *phbm, HBITMAP hbmNew)
VOID drawSizeBoxes(HDC hdc, LPCRECT prcBase, BOOL bDrawFrame, LPCRECT prcPaint)
Definition: sizebox.cpp:103
HITTEST getSizeBoxHitTest(POINT pt, LPCRECT prcBase)
Definition: sizebox.cpp:80
Definition: bl.h:1331
long y
Definition: polytest.cpp:48
long x
Definition: polytest.cpp:48
LONG right
Definition: windef.h:308
LONG bottom
Definition: windef.h:309
LONG top
Definition: windef.h:307
LONG left
Definition: windef.h:306
@ TOOL_FREESEL
Definition: toolsmodel.h:12
@ TOOL_RECTSEL
Definition: toolsmodel.h:13
int32_t INT
Definition: typedefs.h:58
HDC hdcMem
Definition: welcome.c:104
COLORREF WINAPI SetDCBrushColor(_In_ HDC hdc, _In_ COLORREF crColor)
Definition: dc.c:905
DWORD COLORREF
Definition: windef.h:300
HGDIOBJ WINAPI GetStockObject(_In_ int)
int WINAPI GetObjectW(_In_ HANDLE h, _In_ int c, _Out_writes_bytes_opt_(c) LPVOID pv)
HGDIOBJ WINAPI SelectObject(_In_ HDC, _In_ HGDIOBJ)
Definition: dc.c:1539
BOOL WINAPI MaskBlt(_In_ HDC, _In_ int, _In_ int, _In_ int, _In_ int, _In_ HDC, _In_ int, _In_ int, _In_ HBITMAP, _In_ int, _In_ int, _In_ DWORD)
HDC WINAPI CreateCompatibleDC(_In_opt_ HDC hdc)
BOOL WINAPI StretchBlt(_In_ HDC, _In_ int, _In_ int, _In_ int, _In_ int, _In_opt_ HDC, _In_ int, _In_ int, _In_ int, _In_ int, _In_ DWORD)
#define CLR_INVALID
Definition: wingdi.h:883
#define SRCCOPY
Definition: wingdi.h:333
#define PATCOPY
Definition: wingdi.h:335
BOOL WINAPI DeleteDC(_In_ HDC)
#define MAKEROP4(f, b)
Definition: wingdi.h:2946
BOOL WINAPI InvertRect(_In_ HDC, _In_ LPCRECT)