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