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 <algorithm> 10 11 #include "core/fxcrt/fx_coordinates.h" 12 #include "core/fxcrt/fx_ext.h" 13 14 namespace { 15 16 void MatchFloatRange(FX_FLOAT f1, FX_FLOAT f2, int* i1, int* i2) { 17 int length = static_cast<int>(FXSYS_ceil(f2 - f1)); 18 int i1_1 = static_cast<int>(FXSYS_floor(f1)); 19 int i1_2 = static_cast<int>(FXSYS_ceil(f1)); 20 FX_FLOAT error1 = f1 - i1_1 + (FX_FLOAT)FXSYS_fabs(f2 - i1_1 - length); 21 FX_FLOAT error2 = i1_2 - f1 + (FX_FLOAT)FXSYS_fabs(f2 - i1_2 - length); 22 23 *i1 = (error1 > error2) ? i1_2 : i1_1; 24 *i2 = *i1 + length; 25 } 26 27 } // namespace 28 29 void FX_RECT::Normalize() { 30 if (left > right) { 31 int temp = left; 32 left = right; 33 right = temp; 34 } 35 if (top > bottom) { 36 int temp = top; 37 top = bottom; 38 bottom = temp; 39 } 40 } 41 void FX_RECT::Intersect(const FX_RECT& src) { 42 FX_RECT src_n = src; 43 src_n.Normalize(); 44 Normalize(); 45 left = left > src_n.left ? left : src_n.left; 46 top = top > src_n.top ? top : src_n.top; 47 right = right < src_n.right ? right : src_n.right; 48 bottom = bottom < src_n.bottom ? bottom : src_n.bottom; 49 if (left > right || top > bottom) { 50 left = top = right = bottom = 0; 51 } 52 } 53 54 bool GetIntersection(FX_FLOAT low1, 55 FX_FLOAT high1, 56 FX_FLOAT low2, 57 FX_FLOAT high2, 58 FX_FLOAT& interlow, 59 FX_FLOAT& interhigh) { 60 if (low1 >= high2 || low2 >= high1) { 61 return false; 62 } 63 interlow = low1 > low2 ? low1 : low2; 64 interhigh = high1 > high2 ? high2 : high1; 65 return true; 66 } 67 extern "C" int FXSYS_round(FX_FLOAT d) { 68 if (d < (FX_FLOAT)INT_MIN) { 69 return INT_MIN; 70 } 71 if (d > (FX_FLOAT)INT_MAX) { 72 return INT_MAX; 73 } 74 75 return (int)round(d); 76 } 77 CFX_FloatRect::CFX_FloatRect(const FX_RECT& rect) { 78 left = (FX_FLOAT)(rect.left); 79 right = (FX_FLOAT)(rect.right); 80 bottom = (FX_FLOAT)(rect.top); 81 top = (FX_FLOAT)(rect.bottom); 82 } 83 void CFX_FloatRect::Normalize() { 84 FX_FLOAT temp; 85 if (left > right) { 86 temp = left; 87 left = right; 88 right = temp; 89 } 90 if (bottom > top) { 91 temp = top; 92 top = bottom; 93 bottom = temp; 94 } 95 } 96 void CFX_FloatRect::Intersect(const CFX_FloatRect& other_rect) { 97 Normalize(); 98 CFX_FloatRect other = other_rect; 99 other.Normalize(); 100 left = left > other.left ? left : other.left; 101 right = right < other.right ? right : other.right; 102 bottom = bottom > other.bottom ? bottom : other.bottom; 103 top = top < other.top ? top : other.top; 104 if (left > right || bottom > top) { 105 left = right = bottom = top = 0; 106 } 107 } 108 void CFX_FloatRect::Union(const CFX_FloatRect& other_rect) { 109 Normalize(); 110 CFX_FloatRect other = other_rect; 111 other.Normalize(); 112 left = left < other.left ? left : other.left; 113 right = right > other.right ? right : other.right; 114 bottom = bottom < other.bottom ? bottom : other.bottom; 115 top = top > other.top ? top : other.top; 116 } 117 118 int CFX_FloatRect::Substract4(CFX_FloatRect& s, CFX_FloatRect* pRects) { 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 161 FX_RECT CFX_FloatRect::GetOuterRect() const { 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 172 FX_RECT CFX_FloatRect::GetInnerRect() const { 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 183 FX_RECT CFX_FloatRect::GetClosestRect() const { 184 CFX_FloatRect rect1 = *this; 185 FX_RECT rect; 186 MatchFloatRange(rect1.left, rect1.right, &rect.left, &rect.right); 187 MatchFloatRange(rect1.bottom, rect1.top, &rect.top, &rect.bottom); 188 rect.Normalize(); 189 return rect; 190 } 191 192 bool CFX_FloatRect::Contains(const CFX_PointF& point) const { 193 CFX_FloatRect n1(*this); 194 n1.Normalize(); 195 return point.x <= n1.right && point.x >= n1.left && point.y <= n1.top && 196 point.y >= n1.bottom; 197 } 198 199 bool CFX_FloatRect::Contains(const CFX_FloatRect& other_rect) const { 200 CFX_FloatRect n1(*this); 201 CFX_FloatRect n2(other_rect); 202 n1.Normalize(); 203 n2.Normalize(); 204 return n2.left >= n1.left && n2.right <= n1.right && n2.bottom >= n1.bottom && 205 n2.top <= n1.top; 206 } 207 208 void CFX_FloatRect::UpdateRect(FX_FLOAT x, FX_FLOAT y) { 209 left = std::min(left, x); 210 right = std::max(right, x); 211 bottom = std::min(bottom, y); 212 top = std::max(top, y); 213 } 214 215 CFX_FloatRect CFX_FloatRect::GetBBox(const CFX_PointF* pPoints, int nPoints) { 216 if (nPoints == 0) 217 return CFX_FloatRect(); 218 219 FX_FLOAT min_x = pPoints->x; 220 FX_FLOAT max_x = pPoints->x; 221 FX_FLOAT min_y = pPoints->y; 222 FX_FLOAT max_y = pPoints->y; 223 for (int i = 1; i < nPoints; i++) { 224 min_x = std::min(min_x, pPoints[i].x); 225 max_x = std::max(max_x, pPoints[i].x); 226 min_y = std::min(min_y, pPoints[i].y); 227 max_y = std::max(max_y, pPoints[i].y); 228 } 229 return CFX_FloatRect(min_x, min_y, max_x, max_y); 230 } 231 232 void CFX_Matrix::SetReverse(const CFX_Matrix& m) { 233 FX_FLOAT i = m.a * m.d - m.b * m.c; 234 if (FXSYS_fabs(i) == 0) 235 return; 236 237 FX_FLOAT j = -i; 238 a = m.d / i; 239 b = m.b / j; 240 c = m.c / j; 241 d = m.a / i; 242 e = (m.c * m.f - m.d * m.e) / i; 243 f = (m.a * m.f - m.b * m.e) / j; 244 } 245 246 void CFX_Matrix::Concat(const CFX_Matrix& m, bool bPrepended) { 247 ConcatInternal(m, bPrepended); 248 } 249 250 void CFX_Matrix::ConcatInverse(const CFX_Matrix& src, bool bPrepended) { 251 CFX_Matrix m; 252 m.SetReverse(src); 253 Concat(m, bPrepended); 254 } 255 256 bool CFX_Matrix::Is90Rotated() const { 257 return FXSYS_fabs(a * 1000) < FXSYS_fabs(b) && 258 FXSYS_fabs(d * 1000) < FXSYS_fabs(c); 259 } 260 261 bool CFX_Matrix::IsScaled() const { 262 return FXSYS_fabs(b * 1000) < FXSYS_fabs(a) && 263 FXSYS_fabs(c * 1000) < FXSYS_fabs(d); 264 } 265 266 void CFX_Matrix::Translate(FX_FLOAT x, FX_FLOAT y, bool bPrepended) { 267 if (bPrepended) { 268 e += x * a + y * c; 269 f += y * d + x * b; 270 return; 271 } 272 e += x; 273 f += y; 274 } 275 276 void CFX_Matrix::Scale(FX_FLOAT sx, FX_FLOAT sy, bool bPrepended) { 277 a *= sx; 278 d *= sy; 279 if (bPrepended) { 280 b *= sx; 281 c *= sy; 282 return; 283 } 284 285 b *= sy; 286 c *= sx; 287 e *= sx; 288 f *= sy; 289 } 290 291 void CFX_Matrix::Rotate(FX_FLOAT fRadian, bool bPrepended) { 292 FX_FLOAT cosValue = FXSYS_cos(fRadian); 293 FX_FLOAT sinValue = FXSYS_sin(fRadian); 294 ConcatInternal(CFX_Matrix(cosValue, sinValue, -sinValue, cosValue, 0, 0), 295 bPrepended); 296 } 297 298 void CFX_Matrix::RotateAt(FX_FLOAT fRadian, 299 FX_FLOAT dx, 300 FX_FLOAT dy, 301 bool bPrepended) { 302 Translate(dx, dy, bPrepended); 303 Rotate(fRadian, bPrepended); 304 Translate(-dx, -dy, bPrepended); 305 } 306 307 void CFX_Matrix::Shear(FX_FLOAT fAlphaRadian, 308 FX_FLOAT fBetaRadian, 309 bool bPrepended) { 310 ConcatInternal( 311 CFX_Matrix(1, FXSYS_tan(fAlphaRadian), FXSYS_tan(fBetaRadian), 1, 0, 0), 312 bPrepended); 313 } 314 315 void CFX_Matrix::MatchRect(const CFX_FloatRect& dest, 316 const CFX_FloatRect& src) { 317 FX_FLOAT fDiff = src.left - src.right; 318 a = FXSYS_fabs(fDiff) < 0.001f ? 1 : (dest.left - dest.right) / fDiff; 319 320 fDiff = src.bottom - src.top; 321 d = FXSYS_fabs(fDiff) < 0.001f ? 1 : (dest.bottom - dest.top) / fDiff; 322 e = dest.left - src.left * a; 323 f = dest.bottom - src.bottom * d; 324 b = 0; 325 c = 0; 326 } 327 328 FX_FLOAT CFX_Matrix::GetXUnit() const { 329 if (b == 0) 330 return (a > 0 ? a : -a); 331 if (a == 0) 332 return (b > 0 ? b : -b); 333 return FXSYS_sqrt(a * a + b * b); 334 } 335 336 FX_FLOAT CFX_Matrix::GetYUnit() const { 337 if (c == 0) 338 return (d > 0 ? d : -d); 339 if (d == 0) 340 return (c > 0 ? c : -c); 341 return FXSYS_sqrt(c * c + d * d); 342 } 343 344 CFX_FloatRect CFX_Matrix::GetUnitRect() const { 345 CFX_FloatRect rect(0, 0, 1, 1); 346 TransformRect(rect); 347 return rect; 348 } 349 350 FX_FLOAT CFX_Matrix::TransformXDistance(FX_FLOAT dx) const { 351 FX_FLOAT fx = a * dx; 352 FX_FLOAT fy = b * dx; 353 return FXSYS_sqrt(fx * fx + fy * fy); 354 } 355 356 FX_FLOAT CFX_Matrix::TransformDistance(FX_FLOAT dx, FX_FLOAT dy) const { 357 FX_FLOAT fx = a * dx + c * dy; 358 FX_FLOAT fy = b * dx + d * dy; 359 return FXSYS_sqrt(fx * fx + fy * fy); 360 } 361 362 FX_FLOAT CFX_Matrix::TransformDistance(FX_FLOAT distance) const { 363 return distance * (GetXUnit() + GetYUnit()) / 2; 364 } 365 366 CFX_PointF CFX_Matrix::Transform(const CFX_PointF& point) const { 367 return CFX_PointF(a * point.x + c * point.y + e, 368 b * point.x + d * point.y + f); 369 } 370 371 void CFX_Matrix::TransformRect(CFX_RectF& rect) const { 372 FX_FLOAT right = rect.right(), bottom = rect.bottom(); 373 TransformRect(rect.left, right, bottom, rect.top); 374 rect.width = right - rect.left; 375 rect.height = bottom - rect.top; 376 } 377 378 void CFX_Matrix::TransformRect(FX_FLOAT& left, 379 FX_FLOAT& right, 380 FX_FLOAT& top, 381 FX_FLOAT& bottom) const { 382 CFX_PointF points[] = { 383 {left, top}, {left, bottom}, {right, top}, {right, bottom}}; 384 for (int i = 0; i < 4; i++) 385 points[i] = Transform(points[i]); 386 387 right = points[0].x; 388 left = points[0].x; 389 top = points[0].y; 390 bottom = points[0].y; 391 for (int i = 1; i < 4; i++) { 392 right = std::max(right, points[i].x); 393 left = std::min(left, points[i].x); 394 top = std::max(top, points[i].y); 395 bottom = std::min(bottom, points[i].y); 396 } 397 } 398 399 void CFX_Matrix::ConcatInternal(const CFX_Matrix& other, bool prepend) { 400 CFX_Matrix left; 401 CFX_Matrix right; 402 if (prepend) { 403 left = other; 404 right = *this; 405 } else { 406 left = *this; 407 right = other; 408 } 409 410 a = left.a * right.a + left.b * right.c; 411 b = left.a * right.b + left.b * right.d; 412 c = left.c * right.a + left.d * right.c; 413 d = left.c * right.b + left.d * right.d; 414 e = left.e * right.a + left.f * right.c + right.e; 415 f = left.e * right.b + left.f * right.d + right.f; 416 } 417