-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathUtil.cpp
More file actions
140 lines (126 loc) · 4.76 KB
/
Copy pathUtil.cpp
File metadata and controls
140 lines (126 loc) · 4.76 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
#include "Util.h"
#include "Wnd.h"
#include <cmath>
namespace FD2D::Util
{
unsigned long long NowMs()
{
return static_cast<unsigned long long>(GetTickCount64());
}
float Clamp01(float v)
{
if (v < 0.0f)
{
return 0.0f;
}
if (v > 1.0f)
{
return 1.0f;
}
return v;
}
bool RectContainsPoint(const D2D1_RECT_F& r, const POINT& pt)
{
return pt.x >= r.left &&
pt.x <= r.right &&
pt.y >= r.top &&
pt.y <= r.bottom;
}
bool IsMouseInputEventType(InputEventType type)
{
switch (type)
{
case InputEventType::MouseMove:
case InputEventType::MouseDown:
case InputEventType::MouseUp:
case InputEventType::MouseDoubleClick:
case InputEventType::MouseWheel:
case InputEventType::MouseHWheel:
case InputEventType::MouseLeave:
case InputEventType::CaptureChanged:
case InputEventType::SetCursor:
return true;
default:
return false;
}
}
D2D1_RECT_F ComputeAspectFitRect(
const D2D1_RECT_F& layoutRect,
const D2D1_SIZE_F& imageSize,
int rotationQuarters)
{
const float layoutWidth = layoutRect.right - layoutRect.left;
const float layoutHeight = layoutRect.bottom - layoutRect.top;
if (!(layoutWidth > 0.0f && layoutHeight > 0.0f &&
imageSize.width > 0.0f && imageSize.height > 0.0f))
{
return layoutRect;
}
// The returned rect is used as the *pre-rotation* draw/destination rect: the caller
// draws the (unrotated) bitmap into it and then rotates the whole rect on screen.
// For 90°/270° that on-screen (post-rotation) bounding box has swapped width/height
// compared to the draw rect, so we must aspect-fit using the swapped dimensions and
// then swap the resulting size back to get the actual pre-rotation draw rect.
// Getting this backwards (fitting with the draw rect's own aspect ratio) would leave
// the post-rotation bounding box mismatched from the image's true aspect ratio and
// visibly stretch/squash the image.
const bool swapDims = (rotationQuarters == 1 || rotationQuarters == 3);
const float effectiveW = swapDims ? imageSize.height : imageSize.width;
const float effectiveH = swapDims ? imageSize.width : imageSize.height;
const float rotatedAspect = effectiveW / effectiveH;
const float layoutAspect = layoutWidth / layoutHeight;
// Size of the on-screen (post-rotation) bounding box, aspect-fit within layoutRect.
float rotatedBoxW;
float rotatedBoxH;
if (rotatedAspect > layoutAspect)
{
rotatedBoxW = layoutWidth;
rotatedBoxH = layoutWidth / rotatedAspect;
}
else
{
rotatedBoxH = layoutHeight;
rotatedBoxW = layoutHeight * rotatedAspect;
}
// Swap back to get the pre-rotation draw rect size (matches the image's true aspect ratio).
const float drawW = swapDims ? rotatedBoxH : rotatedBoxW;
const float drawH = swapDims ? rotatedBoxW : rotatedBoxH;
const float centerX = (layoutRect.left + layoutRect.right) * 0.5f;
const float centerY = (layoutRect.top + layoutRect.bottom) * 0.5f;
return D2D1_RECT_F
{
centerX - drawW * 0.5f,
centerY - drawH * 0.5f,
centerX + drawW * 0.5f,
centerY + drawH * 0.5f
};
}
D2D1_RECT_F ApplyZoomPanToRect(
const D2D1_RECT_F& base,
float zoomScale,
float panX,
float panY)
{
D2D1_RECT_F rect = base;
if (zoomScale != 1.0f)
{
const float centerX = (base.left + base.right) * 0.5f;
const float centerY = (base.top + base.bottom) * 0.5f;
const float scaledWidth = (base.right - base.left) * zoomScale;
const float scaledHeight = (base.bottom - base.top) * zoomScale;
rect.left = centerX - scaledWidth * 0.5f + panX;
rect.right = rect.left + scaledWidth;
rect.top = centerY - scaledHeight * 0.5f + panY;
rect.bottom = rect.top + scaledHeight;
}
else if (std::abs(panX) > 0.001f || std::abs(panY) > 0.001f)
{
// Apply pan even when not zoomed (though this shouldn't normally happen).
rect.left += panX;
rect.right += panX;
rect.top += panY;
rect.bottom += panY;
}
return rect;
}
}