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 "../../include/fxcrt/fx_ext.h" 8 void FX_RECT::Normalize() 9 { 10 if (left > right) { 11 int temp = left; 12 left = right; 13 right = temp; 14 } 15 if (top > bottom) { 16 int temp = top; 17 top = bottom; 18 bottom = temp; 19 } 20 } 21 void FX_RECT::Intersect(const FX_RECT& src) 22 { 23 FX_RECT src_n = src; 24 src_n.Normalize(); 25 Normalize(); 26 left = left > src_n.left ? left : src_n.left; 27 top = top > src_n.top ? top : src_n.top; 28 right = right < src_n.right ? right : src_n.right; 29 bottom = bottom < src_n.bottom ? bottom : src_n.bottom; 30 if (left > right || top > bottom) { 31 left = top = right = bottom = 0; 32 } 33 } 34 void FX_RECT::Union(const FX_RECT& other_rect) 35 { 36 Normalize(); 37 FX_RECT other = other_rect; 38 other.Normalize(); 39 left = left < other.left ? left : other.left; 40 right = right > other.right ? right : other.right; 41 bottom = bottom > other.bottom ? bottom : other.bottom; 42 top = top < other.top ? top : other.top; 43 } 44 FX_BOOL GetIntersection(FX_FLOAT low1, FX_FLOAT high1, FX_FLOAT low2, FX_FLOAT high2, 45 FX_FLOAT& interlow, FX_FLOAT& interhigh) 46 { 47 if (low1 >= high2 || low2 >= high1) { 48 return FALSE; 49 } 50 interlow = low1 > low2 ? low1 : low2; 51 interhigh = high1 > high2 ? high2 : high1; 52 return TRUE; 53 } 54 extern "C" int FXSYS_round(FX_FLOAT d) 55 { 56 int iRet = 0; 57 if (d >= 0.0f) { 58 iRet = (int)(d + 0.5f); 59 if (iRet >= 0) { 60 return iRet; 61 } 62 return -iRet; 63 } 64 return (int)(d - 0.5f); 65 } 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 } 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 } 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 } 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 } 110 void CFX_FloatRect::Transform(const CFX_Matrix* pMatrix) 111 { 112 pMatrix->TransformRect(left, right, top, bottom); 113 } 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 } 157 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 } 168 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 } 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 } 189 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 } 198 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 } 209 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 } 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 } 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 } 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 } 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 } 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 } 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 } 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 } 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 } 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 } 314 FX_BOOL CFX_Matrix::IsInvertible() const 315 { 316 return FXSYS_fabs(a * d - b * c) >= 0.0001f; 317 } 318 FX_BOOL CFX_Matrix::Is90Rotated() const 319 { 320 return FXSYS_fabs(a * 1000) < FXSYS_fabs(b) && FXSYS_fabs(d * 1000) < FXSYS_fabs(c); 321 } 322 FX_BOOL CFX_Matrix::IsScaled() const 323 { 324 return FXSYS_fabs(b * 1000) < FXSYS_fabs(a) && FXSYS_fabs(c * 1000) < FXSYS_fabs(d); 325 } 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 } 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 } 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 } 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 } 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 } 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 } 387 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 } 397 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 } 407 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 } 413 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 } 419 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 } 428 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 } 433 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 } 438 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 } 443 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 } 448 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 } 453 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 } 458 FX_FLOAT CFX_Matrix::TransformDistance(FX_FLOAT distance) const 459 { 460 return distance * (GetXUnit() + GetYUnit()) / 2; 461 } 462 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 } 468 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 } 475 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 } 487 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 } 498 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 } 504 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 } 511 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 } 518 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 } 530 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