Fix some clang warnings with -Wmissing-braces in pdfium.
[pdfium.git] / core / src / fxcrt / fx_basic_coords.cpp
1 // Copyright 2014 PDFium Authors. All rights reserved.
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 <limits.h>
8
9 #include "../../include/fxcrt/fx_coordinates.h"
10 #include "../../include/fxcrt/fx_ext.h"
11
12 void FX_RECT::Normalize()
13 {
14     if (left > right) {
15         int temp = left;
16         left = right;
17         right = temp;
18     }
19     if (top > bottom) {
20         int temp = top;
21         top = bottom;
22         bottom = temp;
23     }
24 }
25 void FX_RECT::Intersect(const FX_RECT& src)
26 {
27     FX_RECT src_n = src;
28     src_n.Normalize();
29     Normalize();
30     left = left > src_n.left ? left : src_n.left;
31     top = top > src_n.top ? top : src_n.top;
32     right = right < src_n.right ? right : src_n.right;
33     bottom = bottom < src_n.bottom ? bottom : src_n.bottom;
34     if (left > right || top > bottom) {
35         left = top = right = bottom = 0;
36     }
37 }
38 void FX_RECT::Union(const FX_RECT& other_rect)
39 {
40     Normalize();
41     FX_RECT other = other_rect;
42     other.Normalize();
43     left = left < other.left ? left : other.left;
44     right = right > other.right ? right : other.right;
45     bottom = bottom > other.bottom ? bottom : other.bottom;
46     top = top < other.top ? top : other.top;
47 }
48 FX_BOOL GetIntersection(FX_FLOAT low1, FX_FLOAT high1, FX_FLOAT low2, FX_FLOAT high2,
49                         FX_FLOAT& interlow, FX_FLOAT& interhigh)
50 {
51     if (low1 >= high2 || low2 >= high1) {
52         return FALSE;
53     }
54     interlow = low1 > low2 ? low1 : low2;
55     interhigh = high1 > high2 ? high2 : high1;
56     return TRUE;
57 }
58 extern "C" int FXSYS_round(FX_FLOAT d)
59 {
60     if (d < (FX_FLOAT)INT_MIN) {
61         return INT_MIN;
62     }
63     if (d > (FX_FLOAT)INT_MAX) {
64         return INT_MAX;
65     }
66
67     return (int)round(d);
68 }
69 CFX_FloatRect::CFX_FloatRect(const FX_RECT& rect)
70 {
71     left = (FX_FLOAT)(rect.left);
72     right = (FX_FLOAT)(rect.right);
73     bottom = (FX_FLOAT)(rect.top);
74     top = (FX_FLOAT)(rect.bottom);
75 }
76 void CFX_FloatRect::Normalize()
77 {
78     FX_FLOAT temp;
79     if (left > right) {
80         temp = left;
81         left = right;
82         right = temp;
83     }
84     if (bottom > top) {
85         temp = top;
86         top = bottom;
87         bottom = temp;
88     }
89 }
90 void CFX_FloatRect::Intersect(const CFX_FloatRect& other_rect)
91 {
92     Normalize();
93     CFX_FloatRect other = other_rect;
94     other.Normalize();
95     left = left > other.left ? left : other.left;
96     right = right < other.right ? right : other.right;
97     bottom = bottom > other.bottom ? bottom : other.bottom;
98     top = top < other.top ? top : other.top;
99     if (left > right || bottom > top) {
100         left = right = bottom = top = 0;
101     }
102 }
103 void CFX_FloatRect::Union(const CFX_FloatRect& other_rect)
104 {
105     Normalize();
106     CFX_FloatRect other = other_rect;
107     other.Normalize();
108     left = left < other.left ? left : other.left;
109     right = right > other.right ? right : other.right;
110     bottom = bottom < other.bottom ? bottom : other.bottom;
111     top = top > other.top ? top : other.top;
112 }
113 void CFX_FloatRect::Transform(const CFX_Matrix* pMatrix)
114 {
115     pMatrix->TransformRect(left, right, top, bottom);
116 }
117 int CFX_FloatRect::Substract4(CFX_FloatRect& s, CFX_FloatRect* pRects)
118 {
119     Normalize();
120     s.Normalize();
121     int nRects = 0;
122     CFX_FloatRect rects[4];
123     if (left < s.left) {
124         rects[nRects].left = left;
125         rects[nRects].right = s.left;
126         rects[nRects].bottom = bottom;
127         rects[nRects].top = top;
128         nRects ++;
129     }
130     if (s.left < right && s.top < top) {
131         rects[nRects].left = s.left;
132         rects[nRects].right = right;
133         rects[nRects].bottom = s.top;
134         rects[nRects].top = top;
135         nRects ++;
136     }
137     if (s.top > bottom && s.right < right) {
138         rects[nRects].left = s.right;
139         rects[nRects].right = right;
140         rects[nRects].bottom = bottom;
141         rects[nRects].top = s.top;
142         nRects ++;
143     }
144     if (s.bottom > bottom) {
145         rects[nRects].left = s.left;
146         rects[nRects].right = s.right;
147         rects[nRects].bottom = bottom;
148         rects[nRects].top = s.bottom;
149         nRects ++;
150     }
151     if (nRects == 0) {
152         return 0;
153     }
154     for (int i = 0; i < nRects; i ++) {
155         pRects[i] = rects[i];
156         pRects[i].Intersect(*this);
157     }
158     return nRects;
159 }
160 FX_RECT CFX_FloatRect::GetOutterRect() const
161 {
162     CFX_FloatRect rect1 = *this;
163     FX_RECT rect;
164     rect.left = (int)FXSYS_floor(rect1.left);
165     rect.right = (int)FXSYS_ceil(rect1.right);
166     rect.top = (int)FXSYS_floor(rect1.bottom);
167     rect.bottom = (int)FXSYS_ceil(rect1.top);
168     rect.Normalize();
169     return rect;
170 }
171 FX_RECT CFX_FloatRect::GetInnerRect() const
172 {
173     CFX_FloatRect rect1 = *this;
174     FX_RECT rect;
175     rect.left = (int)FXSYS_ceil(rect1.left);
176     rect.right = (int)FXSYS_floor(rect1.right);
177     rect.top = (int)FXSYS_ceil(rect1.bottom);
178     rect.bottom = (int)FXSYS_floor(rect1.top);
179     rect.Normalize();
180     return rect;
181 }
182 static void _MatchFloatRange(FX_FLOAT f1, FX_FLOAT f2, int& i1, int& i2)
183 {
184     int length = (int)FXSYS_ceil(f2 - f1);
185     int i1_1 = (int)FXSYS_floor(f1);
186     int i1_2 = (int)FXSYS_ceil(f1);
187     FX_FLOAT error1 = f1 - i1_1 + (FX_FLOAT)FXSYS_fabs(f2 - i1_1 - length);
188     FX_FLOAT error2 = i1_2 - f1 + (FX_FLOAT)FXSYS_fabs(f2 - i1_2 - length);
189     i1 = (error1 > error2) ? i1_2 : i1_1;
190     i2 = i1 + length;
191 }
192 FX_RECT CFX_FloatRect::GetClosestRect() const
193 {
194     CFX_FloatRect rect1 = *this;
195     FX_RECT rect;
196     _MatchFloatRange(rect1.left, rect1.right, rect.left, rect.right);
197     _MatchFloatRange(rect1.bottom, rect1.top, rect.top, rect.bottom);
198     rect.Normalize();
199     return rect;
200 }
201 FX_BOOL CFX_FloatRect::Contains(const CFX_FloatRect& other_rect) const
202 {
203     CFX_FloatRect n1 = *this;
204     n1.Normalize();
205     CFX_FloatRect n2 = other_rect;
206     n2.Normalize();
207     if (n2.left >= n1.left && n2.right <= n1.right && n2.bottom >= n1.bottom && n2.top <= n1.top) {
208         return TRUE;
209     }
210     return FALSE;
211 }
212 FX_BOOL CFX_FloatRect::Contains(FX_FLOAT x, FX_FLOAT y) const
213 {
214     CFX_FloatRect n1 = *this;
215     n1.Normalize();
216     return x <= n1.right && x >= n1.left && y <= n1.top && y >= n1.bottom;
217 }
218 void CFX_FloatRect::UpdateRect(FX_FLOAT x, FX_FLOAT y)
219 {
220     if (left > x) {
221         left = x;
222     }
223     if (right < x) {
224         right = x;
225     }
226     if (bottom > y) {
227         bottom = y;
228     }
229     if (top < y) {
230         top = y;
231     }
232 }
233 CFX_FloatRect CFX_FloatRect::GetBBox(const CFX_FloatPoint* pPoints, int nPoints)
234 {
235     if (nPoints == 0) {
236         return CFX_FloatRect();
237     }
238     FX_FLOAT min_x = pPoints->x, max_x = pPoints->x, min_y = pPoints->y, max_y = pPoints->y;
239     for (int i = 1; i < nPoints; i ++) {
240         if (min_x > pPoints[i].x) {
241             min_x = pPoints[i].x;
242         }
243         if (max_x < pPoints[i].x) {
244             max_x = pPoints[i].x;
245         }
246         if (min_y > pPoints[i].y) {
247             min_y = pPoints[i].y;
248         }
249         if (max_y < pPoints[i].y) {
250             max_y = pPoints[i].y;
251         }
252     }
253     return CFX_FloatRect(min_x, min_y, max_x, max_y);
254 }
255 void CFX_Matrix::Set(FX_FLOAT other_a,
256                      FX_FLOAT other_b,
257                      FX_FLOAT other_c,
258                      FX_FLOAT other_d,
259                      FX_FLOAT other_e,
260                      FX_FLOAT other_f)
261 {
262     a = other_a;
263     b = other_b;
264     c = other_c;
265     d = other_d;
266     e = other_e;
267     f = other_f;
268 }
269 void CFX_Matrix::Set(const FX_FLOAT n[6])
270 {
271     a = n[0];
272     b = n[1];
273     c = n[2];
274     d = n[3];
275     e = n[4];
276     f = n[5];
277 }
278 void CFX_Matrix::SetReverse(const CFX_Matrix &m)
279 {
280     FX_FLOAT i = m.a * m.d - m.b * m.c;
281     if (FXSYS_fabs(i) == 0) {
282         return;
283     }
284     FX_FLOAT j = -i;
285     a = m.d / i;
286     b = m.b / j;
287     c = m.c / j;
288     d = m.a / i;
289     e = (m.c * m.f - m.d * m.e) / i;
290     f = (m.a * m.f - m.b * m.e) / j;
291 }
292 static void FXCRT_Matrix_Concat(CFX_Matrix &m, const CFX_Matrix &m1, const CFX_Matrix &m2)
293 {
294     FX_FLOAT aa = m1.a * m2.a + m1.b * m2.c;
295     FX_FLOAT bb = m1.a * m2.b + m1.b * m2.d;
296     FX_FLOAT cc = m1.c * m2.a + m1.d * m2.c;
297     FX_FLOAT dd = m1.c * m2.b + m1.d * m2.d;
298     FX_FLOAT ee = m1.e * m2.a + m1.f * m2.c + m2.e;
299     FX_FLOAT ff = m1.e * m2.b + m1.f * m2.d + m2.f;
300     m.a = aa, m.b = bb, m.c = cc, m.d = dd, m.e = ee, m.f = ff;
301 }
302 void CFX_Matrix::Concat(FX_FLOAT a, FX_FLOAT b, FX_FLOAT c, FX_FLOAT d, FX_FLOAT e, FX_FLOAT f, FX_BOOL bPrepended)
303 {
304     CFX_Matrix m;
305     m.Set(a, b, c, d, e, f);
306     Concat(m, bPrepended);
307 }
308 void CFX_Matrix::Concat(const CFX_Matrix &m, FX_BOOL bPrepended)
309 {
310     if (bPrepended) {
311         FXCRT_Matrix_Concat(*this, m, *this);
312     } else {
313         FXCRT_Matrix_Concat(*this, *this, m);
314     }
315 }
316 void CFX_Matrix::ConcatInverse(const CFX_Matrix& src, FX_BOOL bPrepended)
317 {
318     CFX_Matrix m;
319     m.SetReverse(src);
320     Concat(m, bPrepended);
321 }
322 FX_BOOL CFX_Matrix::IsInvertible() const
323 {
324     return FXSYS_fabs(a * d - b * c) >= 0.0001f;
325 }
326 FX_BOOL CFX_Matrix::Is90Rotated() const
327 {
328     return FXSYS_fabs(a * 1000) < FXSYS_fabs(b) && FXSYS_fabs(d * 1000) < FXSYS_fabs(c);
329 }
330 FX_BOOL CFX_Matrix::IsScaled() const
331 {
332     return FXSYS_fabs(b * 1000) < FXSYS_fabs(a) && FXSYS_fabs(c * 1000) < FXSYS_fabs(d);
333 }
334 void CFX_Matrix::Translate(FX_FLOAT x, FX_FLOAT y, FX_BOOL bPrepended)
335 {
336     if (bPrepended) {
337         e += x * a + y * c;
338         f += y * d + x * b;
339     } else {
340         e += x, f += y;
341     }
342 }
343 void CFX_Matrix::Scale(FX_FLOAT sx, FX_FLOAT sy, FX_BOOL bPrepended)
344 {
345     a *= sx, d *= sy;
346     if (bPrepended) {
347         b *= sx;
348         c *= sy;
349     } else {
350         b *= sy;
351         c *= sx;
352         e *= sx;
353         f *= sy;
354     }
355 }
356 void CFX_Matrix::Rotate(FX_FLOAT fRadian, FX_BOOL bPrepended)
357 {
358     FX_FLOAT cosValue = FXSYS_cos(fRadian);
359     FX_FLOAT sinValue = FXSYS_sin(fRadian);
360     CFX_Matrix m;
361     m.Set(cosValue, sinValue, -sinValue, cosValue, 0, 0);
362     if (bPrepended) {
363         FXCRT_Matrix_Concat(*this, m, *this);
364     } else {
365         FXCRT_Matrix_Concat(*this, *this, m);
366     }
367 }
368 void CFX_Matrix::RotateAt(FX_FLOAT fRadian, FX_FLOAT dx, FX_FLOAT dy, FX_BOOL bPrepended)
369 {
370     Translate(dx, dy, bPrepended);
371     Rotate(fRadian, bPrepended);
372     Translate(-dx, -dy, bPrepended);
373 }
374 void CFX_Matrix::Shear(FX_FLOAT fAlphaRadian, FX_FLOAT fBetaRadian, FX_BOOL bPrepended)
375 {
376     CFX_Matrix m;
377     m.Set(1, FXSYS_tan(fAlphaRadian), FXSYS_tan(fBetaRadian), 1, 0, 0);
378     if (bPrepended) {
379         FXCRT_Matrix_Concat(*this, m, *this);
380     } else {
381         FXCRT_Matrix_Concat(*this, *this, m);
382     }
383 }
384 void CFX_Matrix::MatchRect(const CFX_FloatRect& dest, const CFX_FloatRect& src)
385 {
386     FX_FLOAT fDiff = src.left - src.right;
387     a = FXSYS_fabs(fDiff) < 0.001f ? 1 : (dest.left - dest.right) / fDiff;
388     fDiff = src.bottom - src.top;
389     d = FXSYS_fabs(fDiff) < 0.001f ? 1 : (dest.bottom - dest.top) / fDiff;
390     e = dest.left - src.left * a;
391     f = dest.bottom - src.bottom * d;
392     b = 0;
393     c = 0;
394 }
395 FX_FLOAT CFX_Matrix::GetXUnit() const
396 {
397     if (b == 0) {
398         return (a > 0 ? a : -a);
399     }
400     if (a == 0) {
401         return (b > 0 ? b : -b);
402     }
403     return FXSYS_sqrt(a * a + b * b);
404 }
405 FX_FLOAT CFX_Matrix::GetYUnit() const
406 {
407     if (c == 0) {
408         return (d > 0 ? d : -d);
409     }
410     if (d == 0) {
411         return (c > 0 ? c : -c);
412     }
413     return FXSYS_sqrt(c * c + d * d);
414 }
415 void CFX_Matrix::GetUnitRect(CFX_RectF &rect) const
416 {
417     rect.left = rect.top = 0;
418     rect.width = rect.height = 1;
419     TransformRect(rect);
420 }
421 CFX_FloatRect CFX_Matrix::GetUnitRect() const
422 {
423     CFX_FloatRect rect(0, 0, 1, 1);
424     rect.Transform((const CFX_Matrix*)this);
425     return rect;
426 }
427 FX_FLOAT CFX_Matrix::GetUnitArea() const
428 {
429     FX_FLOAT A = FXSYS_sqrt(a * a + b * b);
430     FX_FLOAT B = FXSYS_sqrt(c * c + d * d);
431     FX_FLOAT ac = a + c, bd = b + d;
432     FX_FLOAT C = FXSYS_sqrt(ac * ac + bd * bd);
433     FX_FLOAT P = (A + B + C ) / 2;
434     return FXSYS_sqrt(P * (P - A) * (P - B) * (P - C)) * 2;
435 }
436 FX_FLOAT CFX_Matrix::TransformXDistance(FX_FLOAT dx) const
437 {
438     FX_FLOAT fx = a * dx, fy = b * dx;
439     return FXSYS_sqrt(fx * fx + fy * fy);
440 }
441 int32_t CFX_Matrix::TransformXDistance(int32_t dx) const
442 {
443     FX_FLOAT fx = a * dx, fy = b * dx;
444     return FXSYS_round(FXSYS_sqrt(fx * fx + fy * fy));
445 }
446 FX_FLOAT CFX_Matrix::TransformYDistance(FX_FLOAT dy) const
447 {
448     FX_FLOAT fx = c * dy, fy = d * dy;
449     return FXSYS_sqrt(fx * fx + fy * fy);
450 }
451 int32_t CFX_Matrix::TransformYDistance(int32_t dy) const
452 {
453     FX_FLOAT fx = c * dy, fy = d * dy;
454     return FXSYS_round(FXSYS_sqrt(fx * fx + fy * fy));
455 }
456 FX_FLOAT CFX_Matrix::TransformDistance(FX_FLOAT dx, FX_FLOAT dy) const
457 {
458     FX_FLOAT fx = a * dx + c * dy, fy = b * dx + d * dy;
459     return FXSYS_sqrt(fx * fx + fy * fy);
460 }
461 int32_t CFX_Matrix::TransformDistance(int32_t dx, int32_t dy) const
462 {
463     FX_FLOAT fx = a * dx + c * dy, fy = b * dx + d * dy;
464     return FXSYS_round(FXSYS_sqrt(fx * fx + fy * fy));
465 }
466 FX_FLOAT CFX_Matrix::TransformDistance(FX_FLOAT distance) const
467 {
468     return distance * (GetXUnit() + GetYUnit()) / 2;
469 }
470 void CFX_Matrix::TransformVector(CFX_VectorF &v) const
471 {
472     FX_FLOAT fx = a * v.x + c * v.y;
473     FX_FLOAT fy = b * v.x + d * v.y;
474     v.x = fx, v.y = fy;
475 }
476 void CFX_Matrix::TransformVector(CFX_Vector &v) const
477 {
478     FX_FLOAT fx = a * v.x + c * v.y;
479     FX_FLOAT fy = b * v.x + d * v.y;
480     v.x = FXSYS_round(fx);
481     v.y = FXSYS_round(fy);
482 }
483 void CFX_Matrix::TransformPoints(CFX_Point *points, int32_t iCount) const
484 {
485     FXSYS_assert(iCount > 0);
486     FX_FLOAT fx, fy;
487     for (int32_t i = 0; i < iCount; i ++) {
488         fx = a * points->x + c * points->y + e;
489         fy = b * points->x + d * points->y + f;
490         points->x = FXSYS_round(fx);
491         points->y = FXSYS_round(fy);
492         points ++;
493     }
494 }
495 void CFX_Matrix::TransformPoints(CFX_PointF *points, int32_t iCount) const
496 {
497     FXSYS_assert(iCount > 0);
498     FX_FLOAT fx, fy;
499     for (int32_t i = 0; i < iCount; i ++) {
500         fx = a * points->x + c * points->y + e;
501         fy = b * points->x + d * points->y + f;
502         points->x = fx, points->y = fy;
503         points ++;
504     }
505 }
506 void CFX_Matrix::TransformPoint(FX_FLOAT &x, FX_FLOAT &y) const
507 {
508     FX_FLOAT fx = a * x + c * y + e;
509     FX_FLOAT fy = b * x + d * y + f;
510     x = fx, y = fy;
511 }
512 void CFX_Matrix::TransformPoint(int32_t &x, int32_t &y) const
513 {
514     FX_FLOAT fx = a * x + c * y + e;
515     FX_FLOAT fy = b * x + d * y + f;
516     x = FXSYS_round(fx);
517     y = FXSYS_round(fy);
518 }
519 void CFX_Matrix::TransformRect(CFX_RectF &rect) const
520 {
521     FX_FLOAT right = rect.right(), bottom = rect.bottom();
522     TransformRect(rect.left, right, bottom, rect.top);
523     rect.width = right - rect.left;
524     rect.height = bottom - rect.top;
525 }
526 void CFX_Matrix::TransformRect(CFX_Rect &rect) const
527 {
528     FX_FLOAT left = (FX_FLOAT)rect.left;
529     FX_FLOAT top = (FX_FLOAT)rect.bottom();
530     FX_FLOAT right = (FX_FLOAT)rect.right();
531     FX_FLOAT bottom = (FX_FLOAT)rect.top;
532     TransformRect(left, right, top, bottom);
533     rect.left = FXSYS_round(left);
534     rect.top = FXSYS_round(bottom);
535     rect.width = FXSYS_round(right - left);
536     rect.height = FXSYS_round(top - bottom);
537 }
538 void CFX_Matrix::TransformRect(FX_FLOAT& left, FX_FLOAT& right, FX_FLOAT& top, FX_FLOAT& bottom) const
539 {
540     FX_FLOAT x[4], y[4];
541     x[0] = left;
542     y[0] = top;
543     x[1] = left;
544     y[1] = bottom;
545     x[2] = right;
546     y[2] = top;
547     x[3] = right;
548     y[3] = bottom;
549     int i;
550     for (i = 0; i < 4; i ++) {
551         Transform(x[i], y[i], x[i], y[i]);
552     }
553     right = left = x[0];
554     top = bottom = y[0];
555     for (i = 1; i < 4; i ++) {
556         if (right < x[i]) {
557             right = x[i];
558         }
559         if (left > x[i]) {
560             left = x[i];
561         }
562         if (top < y[i]) {
563             top = y[i];
564         }
565         if (bottom > y[i]) {
566             bottom = y[i];
567         }
568     }
569 }