Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
fx_coordinates.cpp
Go to the documentation of this file.
1// Copyright 2014 The PDFium Authors
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
6
7#include "core/fxcrt/fx_coordinates.h"
8
9#include <math.h>
10
11#include <algorithm>
12#include <array>
13#include <iterator>
14#include <utility>
15
16#include "build/build_config.h"
17#include "core/fxcrt/fx_extension.h"
18#include "core/fxcrt/fx_safe_types.h"
19#include "core/fxcrt/fx_system.h"
20
21namespace {
22
23void MatchFloatRange(float f1, float f2, int* i1, int* i2) {
24 float length = ceilf(f2 - f1);
25 float f1_floor = floorf(f1);
26 float f1_ceil = ceilf(f1);
27 float error1 = f1 - f1_floor + fabsf(f2 - f1_floor - length);
28 float error2 = f1_ceil - f1 + fabsf(f2 - f1_ceil - length);
29 float start = error1 > error2 ? f1_ceil : f1_floor;
30 FX_SAFE_INT32 safe1 = start;
31 FX_SAFE_INT32 safe2 = start + length;
32 if (safe1.IsValid() && safe2.IsValid()) {
33 *i1 = safe1.ValueOrDie();
34 *i2 = safe2.ValueOrDie();
35 } else {
36 *i1 = 0;
37 *i2 = 0;
38 }
39}
40
41#if BUILDFLAG(IS_WIN)
42static_assert(sizeof(FX_RECT) == sizeof(RECT), "FX_RECT vs. RECT mismatch");
43static_assert(offsetof(FX_RECT, left) == offsetof(RECT, left),
44 "FX_RECT vs. RECT mismatch");
45static_assert(offsetof(FX_RECT, top) == offsetof(RECT, top),
46 "FX_RECT vs. RECT mismatch");
47static_assert(offsetof(FX_RECT, right) == offsetof(RECT, right),
48 "FX_RECT vs. RECT mismatch");
49static_assert(offsetof(FX_RECT, bottom) == offsetof(RECT, bottom),
50 "FX_RECT vs. RECT mismatch");
51static_assert(sizeof(FX_RECT::left) == sizeof(RECT::left),
52 "FX_RECT vs. RECT mismatch");
53static_assert(sizeof(FX_RECT::top) == sizeof(RECT::top),
54 "FX_RECT vs. RECT mismatch");
55static_assert(sizeof(FX_RECT::right) == sizeof(RECT::right),
56 "FX_RECT vs. RECT mismatch");
57static_assert(sizeof(FX_RECT::bottom) == sizeof(RECT::bottom),
58 "FX_RECT vs. RECT mismatch");
59#endif
60
61} // namespace
62
63template <>
64float CFX_VTemplate<float>::Length() const {
65 return hypotf(x, y);
66}
67
68template <>
69void CFX_VTemplate<float>::Normalize() {
70 float fLen = Length();
71 if (fLen < 0.0001f)
72 return;
73
74 x /= fLen;
75 y /= fLen;
76}
77
78bool FX_RECT::Valid() const {
79 FX_SAFE_INT32 w = right;
80 FX_SAFE_INT32 h = bottom;
81 w -= left;
82 h -= top;
83 return w.IsValid() && h.IsValid();
84}
85
87 if (left > right)
88 std::swap(left, right);
89 if (top > bottom)
90 std::swap(top, bottom);
91}
92
93void FX_RECT::Intersect(const FX_RECT& src) {
94 FX_RECT src_n = src;
95 src_n.Normalize();
97 left = std::max(left, src_n.left);
98 top = std::max(top, src_n.top);
99 right = std::min(right, src_n.right);
100 bottom = std::min(bottom, src_n.bottom);
101 if (left > right || top > bottom) {
102 left = top = right = bottom = 0;
103 }
104}
105
107 int height,
108 bool bFlipX,
109 bool bFlipY) const {
110 FX_RECT rect;
111 if (bFlipY) {
112 rect.left = height - top;
113 rect.right = height - bottom;
114 } else {
115 rect.left = top;
116 rect.right = bottom;
117 }
118 if (bFlipX) {
119 rect.top = width - left;
120 rect.bottom = width - right;
121 } else {
122 rect.top = left;
123 rect.bottom = right;
124 }
125 rect.Normalize();
126 return rect;
127}
128
129// Y-axis runs the opposite way in FX_RECT.
131 : left(rect.left), bottom(rect.top), right(rect.right), top(rect.bottom) {}
132
134 : left(point.x), bottom(point.y), right(point.x), top(point.y) {}
135
136// static
137CFX_FloatRect CFX_FloatRect::GetBBox(pdfium::span<const CFX_PointF> pPoints) {
138 if (pPoints.empty())
139 return CFX_FloatRect();
140
141 float min_x = pPoints.front().x;
142 float max_x = pPoints.front().x;
143 float min_y = pPoints.front().y;
144 float max_y = pPoints.front().y;
145 for (const auto& point : pPoints.subspan(1)) {
146 min_x = std::min(min_x, point.x);
147 max_x = std::max(max_x, point.x);
148 min_y = std::min(min_y, point.y);
149 max_y = std::max(max_y, point.y);
150 }
151 return CFX_FloatRect(min_x, min_y, max_x, max_y);
152}
153
155 if (left > right)
156 std::swap(left, right);
157 if (bottom > top)
158 std::swap(top, bottom);
159}
160
161void CFX_FloatRect::Intersect(const CFX_FloatRect& other_rect) {
163 CFX_FloatRect other = other_rect;
164 other.Normalize();
165 left = std::max(left, other.left);
166 bottom = std::max(bottom, other.bottom);
167 right = std::min(right, other.right);
168 top = std::min(top, other.top);
169 if (left > right || bottom > top)
170 *this = CFX_FloatRect();
171}
172
173void CFX_FloatRect::Union(const CFX_FloatRect& other_rect) {
175 CFX_FloatRect other = other_rect;
176 other.Normalize();
177 left = std::min(left, other.left);
178 bottom = std::min(bottom, other.bottom);
179 right = std::max(right, other.right);
180 top = std::max(top, other.top);
181}
182
184 FX_RECT rect;
185 rect.left = pdfium::saturated_cast<int>(floor(left));
186 rect.bottom = pdfium::saturated_cast<int>(ceil(top));
187 rect.right = pdfium::saturated_cast<int>(ceil(right));
188 rect.top = pdfium::saturated_cast<int>(floor(bottom));
189 rect.Normalize();
190 return rect;
191}
192
194 FX_RECT rect;
195 rect.left = pdfium::saturated_cast<int>(ceil(left));
196 rect.bottom = pdfium::saturated_cast<int>(floor(top));
197 rect.right = pdfium::saturated_cast<int>(floor(right));
198 rect.top = pdfium::saturated_cast<int>(ceil(bottom));
199 rect.Normalize();
200 return rect;
201}
202
204 FX_RECT rect;
205 MatchFloatRange(left, right, &rect.left, &rect.right);
206 MatchFloatRange(bottom, top, &rect.top, &rect.bottom);
207 rect.Normalize();
208 return rect;
209}
210
212 float fWidth = Width();
213 float fHeight = Height();
214 float fHalfWidth = (fWidth > fHeight) ? fHeight / 2 : fWidth / 2;
215
216 float fCenterX = (left + right) / 2.0f;
217 float fCenterY = (top + bottom) / 2.0f;
218 return CFX_FloatRect(fCenterX - fHalfWidth, fCenterY - fHalfWidth,
219 fCenterX + fHalfWidth, fCenterY + fHalfWidth);
220}
221
222bool CFX_FloatRect::Contains(const CFX_PointF& point) const {
223 CFX_FloatRect n1(*this);
224 n1.Normalize();
225 return point.x <= n1.right && point.x >= n1.left && point.y <= n1.top &&
226 point.y >= n1.bottom;
227}
228
229bool CFX_FloatRect::Contains(const CFX_FloatRect& other_rect) const {
230 CFX_FloatRect n1(*this);
231 CFX_FloatRect n2(other_rect);
232 n1.Normalize();
233 n2.Normalize();
234 return n2.left >= n1.left && n2.right <= n1.right && n2.bottom >= n1.bottom &&
235 n2.top <= n1.top;
236}
237
239 left = std::min(left, point.x);
240 bottom = std::min(bottom, point.y);
241 right = std::max(right, point.x);
242 top = std::max(top, point.y);
243}
244
245void CFX_FloatRect::Inflate(float x, float y) {
246 Inflate(x, y, x, y);
247}
248
249void CFX_FloatRect::Inflate(float other_left,
250 float other_bottom,
251 float other_right,
252 float other_top) {
254 left -= other_left;
255 bottom -= other_bottom;
256 right += other_right;
257 top += other_top;
258}
259
263
264void CFX_FloatRect::Deflate(float x, float y) {
265 Deflate(x, y, x, y);
266}
267
268void CFX_FloatRect::Deflate(float other_left,
269 float other_bottom,
270 float other_right,
271 float other_top) {
272 Inflate(-other_left, -other_bottom, -other_right, -other_top);
273}
274
278
279CFX_FloatRect CFX_FloatRect::GetDeflated(float x, float y) const {
280 if (IsEmpty())
281 return CFX_FloatRect();
282
283 CFX_FloatRect that = *this;
284 that.Deflate(x, y);
285 that.Normalize();
286 return that;
287}
288
289void CFX_FloatRect::Translate(float e, float f) {
290 left += e;
291 right += e;
292 top += f;
293 bottom += f;
294}
295
296void CFX_FloatRect::Scale(float fScale) {
297 left *= fScale;
298 bottom *= fScale;
299 right *= fScale;
300 top *= fScale;
301}
302
304 float fHalfWidth = (right - left) / 2.0f;
305 float fHalfHeight = (top - bottom) / 2.0f;
306
307 float center_x = (left + right) / 2;
308 float center_y = (top + bottom) / 2;
309
310 left = center_x - fHalfWidth * fScale;
311 bottom = center_y - fHalfHeight * fScale;
312 right = center_x + fHalfWidth * fScale;
313 top = center_y + fHalfHeight * fScale;
314}
315
317 return FX_RECT(static_cast<int>(left), static_cast<int>(top),
318 static_cast<int>(right), static_cast<int>(bottom));
319}
320
325
326void CFX_RectF::Union(float x, float y) {
327 float r = right();
328 float b = bottom();
329
330 left = std::min(left, x);
331 top = std::min(top, y);
332 r = std::max(r, x);
333 b = std::max(b, y);
334
335 width = r - left;
336 height = b - top;
337}
338
339void CFX_RectF::Union(const CFX_RectF& rt) {
340 float r = right();
341 float b = bottom();
342
343 left = std::min(left, rt.left);
344 top = std::min(top, rt.top);
345 r = std::max(r, rt.right());
346 b = std::max(b, rt.bottom());
347
348 width = r - left;
349 height = b - top;
350}
351
352void CFX_RectF::Intersect(const CFX_RectF& rt) {
353 float r = right();
354 float b = bottom();
355
356 left = std::max(left, rt.left);
357 top = std::max(top, rt.top);
358 r = std::min(r, rt.right());
359 b = std::min(b, rt.bottom());
360
361 width = r - left;
362 height = b - top;
363}
364
366 return FX_RECT(static_cast<int32_t>(floor(left)),
367 static_cast<int32_t>(floor(top)),
368 static_cast<int32_t>(ceil(right())),
369 static_cast<int32_t>(ceil(bottom())));
370}
371
373 CFX_Matrix inverse;
374 float i = a * d - b * c;
375 if (fabs(i) == 0)
376 return inverse;
377
378 float j = -i;
379 inverse.a = d / i;
380 inverse.b = b / j;
381 inverse.c = c / j;
382 inverse.d = a / i;
383 inverse.e = (c * f - d * e) / i;
384 inverse.f = (a * f - b * e) / j;
385 return inverse;
386}
387
388bool CFX_Matrix::Is90Rotated() const {
389 return fabs(a * 1000) < fabs(b) && fabs(d * 1000) < fabs(c);
390}
391
392bool CFX_Matrix::IsScaled() const {
393 return fabs(b * 1000) < fabs(a) && fabs(c * 1000) < fabs(d);
394}
395
396void CFX_Matrix::Translate(float x, float y) {
397 e += x;
398 f += y;
399}
400
401void CFX_Matrix::TranslatePrepend(float x, float y) {
402 e += x * a + y * c;
403 f += y * d + x * b;
404}
405
406void CFX_Matrix::Scale(float sx, float sy) {
407 a *= sx;
408 b *= sy;
409 c *= sx;
410 d *= sy;
411 e *= sx;
412 f *= sy;
413}
414
415void CFX_Matrix::Rotate(float fRadian) {
416 float cosValue = cos(fRadian);
417 float sinValue = sin(fRadian);
418 Concat(CFX_Matrix(cosValue, sinValue, -sinValue, cosValue, 0, 0));
419}
420
422 const CFX_FloatRect& src) {
423 float fDiff = src.left - src.right;
424 a = fabs(fDiff) < 0.001f ? 1 : (dest.left - dest.right) / fDiff;
425
426 fDiff = src.bottom - src.top;
427 d = fabs(fDiff) < 0.001f ? 1 : (dest.bottom - dest.top) / fDiff;
428 e = dest.left - src.left * a;
429 f = dest.bottom - src.bottom * d;
430 b = 0;
431 c = 0;
432}
433
434float CFX_Matrix::GetXUnit() const {
435 if (b == 0)
436 return (a > 0 ? a : -a);
437 if (a == 0)
438 return (b > 0 ? b : -b);
439 return hypotf(a, b);
440}
441
442float CFX_Matrix::GetYUnit() const {
443 if (c == 0)
444 return (d > 0 ? d : -d);
445 if (d == 0)
446 return (c > 0 ? c : -c);
447 return hypotf(c, d);
448}
449
453
454float CFX_Matrix::TransformXDistance(float dx) const {
455 float fx = a * dx;
456 float fy = b * dx;
457 return hypotf(fx, fy);
458}
459
460float CFX_Matrix::TransformDistance(float distance) const {
461 return distance * (GetXUnit() + GetYUnit()) / 2;
462}
463
465 return CFX_PointF(a * point.x + c * point.y + e,
466 b * point.x + d * point.y + f);
467}
468
471 return CFX_RectF(result_rect.left, result_rect.bottom, result_rect.Width(),
472 result_rect.Height());
473}
474
476 std::array<CFX_PointF, 4> points = {{{rect.left, rect.top},
477 {rect.left, rect.bottom},
478 {rect.right, rect.top},
479 {rect.right, rect.bottom}}};
480 for (CFX_PointF& point : points) {
481 point = Transform(point);
482 }
483 float new_right = points[0].x;
484 float new_left = points[0].x;
485 float new_top = points[0].y;
486 float new_bottom = points[0].y;
487 for (size_t i = 1; i < points.size(); i++) {
488 new_right = std::max(new_right, points[i].x);
489 new_left = std::min(new_left, points[i].x);
490 new_top = std::max(new_top, points[i].y);
491 new_bottom = std::min(new_bottom, points[i].y);
492 }
493
494 return CFX_FloatRect(new_left, new_bottom, new_right, new_top);
495}
void Deflate(const CFX_FloatRect &rt)
void Deflate(float other_left, float other_bottom, float other_right, float other_top)
FX_RECT ToRoundedFxRect() const
bool Contains(const CFX_PointF &point) const
CFX_FloatRect(const CFX_FloatRect &that)=default
CFX_FloatRect GetCenterSquare() const
constexpr CFX_FloatRect(float l, float b, float r, float t)
constexpr CFX_FloatRect()=default
float Width() const
FX_RECT GetClosestRect() const
bool IsEmpty() const
CFX_FloatRect(const FX_RECT &rect)
void UpdateRect(const CFX_PointF &point)
void Intersect(const CFX_FloatRect &other_rect)
void ScaleFromCenterPoint(float fScale)
void Inflate(float x, float y)
FX_RECT GetInnerRect() const
CFX_FloatRect & operator=(const CFX_FloatRect &that)=default
void Deflate(float x, float y)
bool Contains(const CFX_FloatRect &other_rect) const
float Height() const
FX_RECT GetOuterRect() const
FX_RECT ToFxRect() const
void Inflate(const CFX_FloatRect &rt)
void Translate(float e, float f)
CFX_FloatRect GetDeflated(float x, float y) const
void Inflate(float other_left, float other_bottom, float other_right, float other_top)
void Union(const CFX_FloatRect &other_rect)
void Scale(float fScale)
CFX_FloatRect(const CFX_PointF &point)
bool IsScaled() const
CFX_FloatRect TransformRect(const CFX_FloatRect &rect) const
float TransformDistance(float distance) const
CFX_RectF TransformRect(const CFX_RectF &rect) const
void MatchRect(const CFX_FloatRect &dest, const CFX_FloatRect &src)
CFX_PointF Transform(const CFX_PointF &point) const
float GetXUnit() const
CFX_FloatRect GetUnitRect() const
CFX_Matrix GetInverse() const
bool Is90Rotated() const
float GetYUnit() const
void TranslatePrepend(float x, float y)
void Rotate(float fRadian)
constexpr CFX_Matrix(float a1, float b1, float c1, float d1, float e1, float f1)
void Scale(float sx, float sy)
void Translate(float x, float y)
void Concat(const CFX_Matrix &right)
float TransformXDistance(float dx) const
CFX_FloatRect ToFloatRect() const
void Intersect(const CFX_RectF &rt)
FX_RECT GetOuterRect() const
float bottom() const
float right() const
void Union(float x, float y)
constexpr CFX_RectF(float dst_left, float dst_top, float dst_width, float dst_height)
void Union(const CFX_RectF &rt)
CFX_PTemplate< float > CFX_PointF
pdfium::CheckedNumeric< int32_t > FX_SAFE_INT32
int FXSYS_roundf(float f)
int32_t bottom
bool Valid() const
int32_t right
void Normalize()
int32_t top
FX_RECT SwappedClipBox(int width, int height, bool bFlipX, bool bFlipY) const
int32_t left
void Intersect(const FX_RECT &src)
constexpr FX_RECT(int l, int t, int r, int b)