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 #ifndef CORE_FXCRT_FX_COORDINATES_H_ 8 #define CORE_FXCRT_FX_COORDINATES_H_ 9 10 #include "core/fxcrt/fx_basic.h" 11 12 class CFX_Matrix; 13 14 template <class BaseType> 15 class CFX_PTemplate { 16 public: CFX_PTemplate()17 CFX_PTemplate() : x(0), y(0) {} CFX_PTemplate(BaseType new_x,BaseType new_y)18 CFX_PTemplate(BaseType new_x, BaseType new_y) : x(new_x), y(new_y) {} CFX_PTemplate(const CFX_PTemplate & other)19 CFX_PTemplate(const CFX_PTemplate& other) : x(other.x), y(other.y) {} clear()20 void clear() { 21 x = 0; 22 y = 0; 23 } 24 CFX_PTemplate operator=(const CFX_PTemplate& other) { 25 if (this != &other) { 26 x = other.x; 27 y = other.y; 28 } 29 return *this; 30 } 31 bool operator==(const CFX_PTemplate& other) const { 32 return x == other.x && y == other.y; 33 } 34 bool operator!=(const CFX_PTemplate& other) const { 35 return !(*this == other); 36 } 37 CFX_PTemplate& operator+=(const CFX_PTemplate<BaseType>& obj) { 38 x += obj.x; 39 y += obj.y; 40 return *this; 41 } 42 CFX_PTemplate& operator-=(const CFX_PTemplate<BaseType>& obj) { 43 x -= obj.x; 44 y -= obj.y; 45 return *this; 46 } 47 CFX_PTemplate& operator*=(BaseType factor) { 48 x *= factor; 49 y *= factor; 50 return *this; 51 } 52 CFX_PTemplate& operator/=(BaseType divisor) { 53 x /= divisor; 54 y /= divisor; 55 return *this; 56 } 57 CFX_PTemplate operator+(const CFX_PTemplate& other) const { 58 return CFX_PTemplate(x + other.x, y + other.y); 59 } 60 CFX_PTemplate operator-(const CFX_PTemplate& other) const { 61 return CFX_PTemplate(x - other.x, y - other.y); 62 } 63 CFX_PTemplate operator*(BaseType factor) const { 64 return CFX_PTemplate(x * factor, y * factor); 65 } 66 CFX_PTemplate operator/(BaseType divisor) const { 67 return CFX_PTemplate(x / divisor, y / divisor); 68 } 69 70 BaseType x; 71 BaseType y; 72 }; 73 using CFX_Point = CFX_PTemplate<int32_t>; 74 using CFX_PointF = CFX_PTemplate<FX_FLOAT>; 75 76 template <class BaseType> 77 class CFX_STemplate { 78 public: CFX_STemplate()79 CFX_STemplate() : width(0), height(0) {} 80 CFX_STemplate(BaseType new_width,BaseType new_height)81 CFX_STemplate(BaseType new_width, BaseType new_height) 82 : width(new_width), height(new_height) {} 83 CFX_STemplate(const CFX_STemplate & other)84 CFX_STemplate(const CFX_STemplate& other) 85 : width(other.width), height(other.height) {} 86 87 template <typename OtherType> As()88 CFX_STemplate<OtherType> As() const { 89 return CFX_STemplate<OtherType>(static_cast<OtherType>(width), 90 static_cast<OtherType>(height)); 91 } 92 clear()93 void clear() { 94 width = 0; 95 height = 0; 96 } 97 CFX_STemplate operator=(const CFX_STemplate& other) { 98 if (this != &other) { 99 width = other.width; 100 height = other.height; 101 } 102 return *this; 103 } 104 bool operator==(const CFX_STemplate& other) const { 105 return width == other.width && height == other.height; 106 } 107 bool operator!=(const CFX_STemplate& other) const { 108 return !(*this == other); 109 } 110 CFX_STemplate& operator+=(const CFX_STemplate<BaseType>& obj) { 111 width += obj.width; 112 height += obj.height; 113 return *this; 114 } 115 CFX_STemplate& operator-=(const CFX_STemplate<BaseType>& obj) { 116 width -= obj.width; 117 height -= obj.height; 118 return *this; 119 } 120 CFX_STemplate& operator*=(BaseType factor) { 121 width *= factor; 122 height *= factor; 123 return *this; 124 } 125 CFX_STemplate& operator/=(BaseType divisor) { 126 width /= divisor; 127 height /= divisor; 128 return *this; 129 } 130 CFX_STemplate operator+(const CFX_STemplate& other) const { 131 return CFX_STemplate(width + other.width, height + other.height); 132 } 133 CFX_STemplate operator-(const CFX_STemplate& other) const { 134 return CFX_STemplate(width - other.width, height - other.height); 135 } 136 CFX_STemplate operator*(BaseType factor) const { 137 return CFX_STemplate(width * factor, height * factor); 138 } 139 CFX_STemplate operator/(BaseType divisor) const { 140 return CFX_STemplate(width / divisor, height / divisor); 141 } 142 143 BaseType width; 144 BaseType height; 145 }; 146 using CFX_Size = CFX_STemplate<int32_t>; 147 using CFX_SizeF = CFX_STemplate<FX_FLOAT>; 148 149 template <class BaseType> 150 class CFX_VTemplate : public CFX_PTemplate<BaseType> { 151 public: 152 using CFX_PTemplate<BaseType>::x; 153 using CFX_PTemplate<BaseType>::y; 154 CFX_VTemplate()155 CFX_VTemplate() : CFX_PTemplate<BaseType>() {} CFX_VTemplate(BaseType new_x,BaseType new_y)156 CFX_VTemplate(BaseType new_x, BaseType new_y) 157 : CFX_PTemplate<BaseType>(new_x, new_y) {} 158 CFX_VTemplate(const CFX_VTemplate & other)159 CFX_VTemplate(const CFX_VTemplate& other) : CFX_PTemplate<BaseType>(other) {} 160 CFX_VTemplate(const CFX_PTemplate<BaseType> & point1,const CFX_PTemplate<BaseType> & point2)161 CFX_VTemplate(const CFX_PTemplate<BaseType>& point1, 162 const CFX_PTemplate<BaseType>& point2) 163 : CFX_PTemplate<BaseType>(point2.x - point1.x, point2.y - point1.y) {} 164 Length()165 FX_FLOAT Length() const { return FXSYS_sqrt(x * x + y * y); } Normalize()166 void Normalize() { 167 FX_FLOAT fLen = Length(); 168 if (fLen < 0.0001f) 169 return; 170 171 x /= fLen; 172 y /= fLen; 173 } Translate(BaseType dx,BaseType dy)174 void Translate(BaseType dx, BaseType dy) { 175 x += dx; 176 y += dy; 177 } Scale(BaseType sx,BaseType sy)178 void Scale(BaseType sx, BaseType sy) { 179 x *= sx; 180 y *= sy; 181 } Rotate(FX_FLOAT fRadian)182 void Rotate(FX_FLOAT fRadian) { 183 FX_FLOAT cosValue = FXSYS_cos(fRadian); 184 FX_FLOAT sinValue = FXSYS_sin(fRadian); 185 x = x * cosValue - y * sinValue; 186 y = x * sinValue + y * cosValue; 187 } 188 }; 189 using CFX_Vector = CFX_VTemplate<int32_t>; 190 using CFX_VectorF = CFX_VTemplate<FX_FLOAT>; 191 192 // Rectangles. 193 // TODO(tsepez): Consolidate all these different rectangle classes. 194 195 // LTWH rectangles (y-axis runs downwards). 196 template <class BaseType> 197 class CFX_RTemplate { 198 public: 199 using PointType = CFX_PTemplate<BaseType>; 200 using SizeType = CFX_STemplate<BaseType>; 201 using VectorType = CFX_VTemplate<BaseType>; 202 using RectType = CFX_RTemplate<BaseType>; 203 CFX_RTemplate()204 CFX_RTemplate() : left(0), top(0), width(0), height(0) {} CFX_RTemplate(BaseType dst_left,BaseType dst_top,BaseType dst_width,BaseType dst_height)205 CFX_RTemplate(BaseType dst_left, 206 BaseType dst_top, 207 BaseType dst_width, 208 BaseType dst_height) 209 : left(dst_left), top(dst_top), width(dst_width), height(dst_height) {} CFX_RTemplate(BaseType dst_left,BaseType dst_top,const SizeType & dst_size)210 CFX_RTemplate(BaseType dst_left, BaseType dst_top, const SizeType& dst_size) 211 : left(dst_left), 212 top(dst_top), 213 width(dst_size.width), 214 height(dst_size.height) {} CFX_RTemplate(const PointType & p,BaseType dst_width,BaseType dst_height)215 CFX_RTemplate(const PointType& p, BaseType dst_width, BaseType dst_height) 216 : left(p.x), top(p.y), width(dst_width), height(dst_height) {} CFX_RTemplate(const PointType & p1,const SizeType & s2)217 CFX_RTemplate(const PointType& p1, const SizeType& s2) 218 : left(p1.x), top(p1.y), width(s2.width), height(s2.height) {} CFX_RTemplate(const PointType & p1,const PointType & p2)219 CFX_RTemplate(const PointType& p1, const PointType& p2) 220 : left(p1.x), 221 top(p1.y), 222 width(p2.width - p1.width), 223 height(p2.height - p1.height) { 224 Normalize(); 225 } CFX_RTemplate(const PointType & p,const VectorType & v)226 CFX_RTemplate(const PointType& p, const VectorType& v) 227 : left(p.x), top(p.y), width(v.x), height(v.y) { 228 Normalize(); 229 } 230 231 // NOLINTNEXTLINE(runtime/explicit) CFX_RTemplate(const RectType & other)232 CFX_RTemplate(const RectType& other) 233 : left(other.left), 234 top(other.top), 235 width(other.width), 236 height(other.height) {} 237 238 template <typename OtherType> As()239 CFX_RTemplate<OtherType> As() const { 240 return CFX_RTemplate<OtherType>( 241 static_cast<OtherType>(left), static_cast<OtherType>(top), 242 static_cast<OtherType>(width), static_cast<OtherType>(height)); 243 } 244 Reset()245 void Reset() { 246 left = 0; 247 top = 0; 248 width = 0; 249 height = 0; 250 } 251 RectType& operator+=(const PointType& p) { 252 left += p.x; 253 top += p.y; 254 return *this; 255 } 256 RectType& operator-=(const PointType& p) { 257 left -= p.x; 258 top -= p.y; 259 return *this; 260 } right()261 BaseType right() const { return left + width; } bottom()262 BaseType bottom() const { return top + height; } Normalize()263 void Normalize() { 264 if (width < 0) { 265 left += width; 266 width = -width; 267 } 268 if (height < 0) { 269 top += height; 270 height = -height; 271 } 272 } Offset(BaseType dx,BaseType dy)273 void Offset(BaseType dx, BaseType dy) { 274 left += dx; 275 top += dy; 276 } Inflate(BaseType x,BaseType y)277 void Inflate(BaseType x, BaseType y) { 278 left -= x; 279 width += x * 2; 280 top -= y; 281 height += y * 2; 282 } Inflate(const PointType & p)283 void Inflate(const PointType& p) { Inflate(p.x, p.y); } Inflate(BaseType off_left,BaseType off_top,BaseType off_right,BaseType off_bottom)284 void Inflate(BaseType off_left, 285 BaseType off_top, 286 BaseType off_right, 287 BaseType off_bottom) { 288 left -= off_left; 289 top -= off_top; 290 width += off_left + off_right; 291 height += off_top + off_bottom; 292 } Inflate(const RectType & rt)293 void Inflate(const RectType& rt) { 294 Inflate(rt.left, rt.top, rt.left + rt.width, rt.top + rt.height); 295 } Deflate(BaseType x,BaseType y)296 void Deflate(BaseType x, BaseType y) { 297 left += x; 298 width -= x * 2; 299 top += y; 300 height -= y * 2; 301 } Deflate(const PointType & p)302 void Deflate(const PointType& p) { Deflate(p.x, p.y); } Deflate(BaseType off_left,BaseType off_top,BaseType off_right,BaseType off_bottom)303 void Deflate(BaseType off_left, 304 BaseType off_top, 305 BaseType off_right, 306 BaseType off_bottom) { 307 left += off_left; 308 top += off_top; 309 width -= off_left + off_right; 310 height -= off_top + off_bottom; 311 } Deflate(const RectType & rt)312 void Deflate(const RectType& rt) { 313 Deflate(rt.left, rt.top, rt.top + rt.width, rt.top + rt.height); 314 } IsEmpty()315 bool IsEmpty() const { return width <= 0 || height <= 0; } IsEmpty(FX_FLOAT fEpsilon)316 bool IsEmpty(FX_FLOAT fEpsilon) const { 317 return width <= fEpsilon || height <= fEpsilon; 318 } Empty()319 void Empty() { width = height = 0; } Contains(const PointType & p)320 bool Contains(const PointType& p) const { 321 return p.x >= left && p.x < left + width && p.y >= top && 322 p.y < top + height; 323 } Contains(const RectType & rt)324 bool Contains(const RectType& rt) const { 325 return rt.left >= left && rt.right() <= right() && rt.top >= top && 326 rt.bottom() <= bottom(); 327 } Width()328 BaseType Width() const { return width; } Height()329 BaseType Height() const { return height; } Size()330 SizeType Size() const { return SizeType(width, height); } TopLeft()331 PointType TopLeft() const { return PointType(left, top); } TopRight()332 PointType TopRight() const { return PointType(left + width, top); } BottomLeft()333 PointType BottomLeft() const { return PointType(left, top + height); } BottomRight()334 PointType BottomRight() const { 335 return PointType(left + width, top + height); 336 } Center()337 PointType Center() const { 338 return PointType(left + width / 2, top + height / 2); 339 } Union(BaseType x,BaseType y)340 void Union(BaseType x, BaseType y) { 341 BaseType r = right(); 342 BaseType b = bottom(); 343 if (left > x) 344 left = x; 345 if (r < x) 346 r = x; 347 if (top > y) 348 top = y; 349 if (b < y) 350 b = y; 351 width = r - left; 352 height = b - top; 353 } Union(const PointType & p)354 void Union(const PointType& p) { Union(p.x, p.y); } Union(const RectType & rt)355 void Union(const RectType& rt) { 356 BaseType r = right(); 357 BaseType b = bottom(); 358 if (left > rt.left) 359 left = rt.left; 360 if (r < rt.right()) 361 r = rt.right(); 362 if (top > rt.top) 363 top = rt.top; 364 if (b < rt.bottom()) 365 b = rt.bottom(); 366 width = r - left; 367 height = b - top; 368 } Intersect(const RectType & rt)369 void Intersect(const RectType& rt) { 370 BaseType r = right(); 371 BaseType b = bottom(); 372 if (left < rt.left) 373 left = rt.left; 374 if (r > rt.right()) 375 r = rt.right(); 376 if (top < rt.top) 377 top = rt.top; 378 if (b > rt.bottom()) 379 b = rt.bottom(); 380 width = r - left; 381 height = b - top; 382 } IntersectWith(const RectType & rt)383 bool IntersectWith(const RectType& rt) const { 384 RectType rect = rt; 385 rect.Intersect(*this); 386 return !rect.IsEmpty(); 387 } IntersectWith(const RectType & rt,FX_FLOAT fEpsilon)388 bool IntersectWith(const RectType& rt, FX_FLOAT fEpsilon) const { 389 RectType rect = rt; 390 rect.Intersect(*this); 391 return !rect.IsEmpty(fEpsilon); 392 } 393 friend bool operator==(const RectType& rc1, const RectType& rc2) { 394 return rc1.left == rc2.left && rc1.top == rc2.top && 395 rc1.width == rc2.width && rc1.height == rc2.height; 396 } 397 friend bool operator!=(const RectType& rc1, const RectType& rc2) { 398 return !(rc1 == rc2); 399 } 400 401 BaseType left; 402 BaseType top; 403 BaseType width; 404 BaseType height; 405 }; 406 using CFX_Rect = CFX_RTemplate<int32_t>; 407 using CFX_RectF = CFX_RTemplate<FX_FLOAT>; 408 409 // LTRB rectangles (y-axis runs downwards). 410 struct FX_RECT { FX_RECTFX_RECT411 FX_RECT() : left(0), top(0), right(0), bottom(0) {} FX_RECTFX_RECT412 FX_RECT(int l, int t, int r, int b) : left(l), top(t), right(r), bottom(b) {} 413 WidthFX_RECT414 int Width() const { return right - left; } HeightFX_RECT415 int Height() const { return bottom - top; } IsEmptyFX_RECT416 bool IsEmpty() const { return right <= left || bottom <= top; } 417 ValidFX_RECT418 bool Valid() const { 419 pdfium::base::CheckedNumeric<int> w = right; 420 pdfium::base::CheckedNumeric<int> h = bottom; 421 w -= left; 422 h -= top; 423 return w.IsValid() && h.IsValid(); 424 } 425 426 void Normalize(); 427 428 void Intersect(const FX_RECT& src); IntersectFX_RECT429 void Intersect(int l, int t, int r, int b) { Intersect(FX_RECT(l, t, r, b)); } 430 OffsetFX_RECT431 void Offset(int dx, int dy) { 432 left += dx; 433 right += dx; 434 top += dy; 435 bottom += dy; 436 } 437 438 bool operator==(const FX_RECT& src) const { 439 return left == src.left && right == src.right && top == src.top && 440 bottom == src.bottom; 441 } 442 ContainsFX_RECT443 bool Contains(int x, int y) const { 444 return x >= left && x < right && y >= top && y < bottom; 445 } 446 447 int32_t left; 448 int32_t top; 449 int32_t right; 450 int32_t bottom; 451 }; 452 453 // LTRB rectangles (y-axis runs upwards). 454 class CFX_FloatRect { 455 public: CFX_FloatRect()456 CFX_FloatRect() : CFX_FloatRect(0.0f, 0.0f, 0.0f, 0.0f) {} CFX_FloatRect(FX_FLOAT l,FX_FLOAT b,FX_FLOAT r,FX_FLOAT t)457 CFX_FloatRect(FX_FLOAT l, FX_FLOAT b, FX_FLOAT r, FX_FLOAT t) 458 : left(l), bottom(b), right(r), top(t) {} 459 CFX_FloatRect(const FX_FLOAT * pArray)460 explicit CFX_FloatRect(const FX_FLOAT* pArray) 461 : CFX_FloatRect(pArray[0], pArray[1], pArray[2], pArray[3]) {} 462 463 explicit CFX_FloatRect(const FX_RECT& rect); 464 465 void Normalize(); 466 Reset()467 void Reset() { 468 left = 0.0f; 469 right = 0.0f; 470 bottom = 0.0f; 471 top = 0.0f; 472 } 473 IsEmpty()474 bool IsEmpty() const { return left >= right || bottom >= top; } 475 476 bool Contains(const CFX_PointF& point) const; 477 bool Contains(const CFX_FloatRect& other_rect) const; 478 479 void Intersect(const CFX_FloatRect& other_rect); 480 void Union(const CFX_FloatRect& other_rect); 481 482 FX_RECT GetInnerRect() const; 483 FX_RECT GetOuterRect() const; 484 FX_RECT GetClosestRect() const; 485 486 int Substract4(CFX_FloatRect& substract_rect, CFX_FloatRect* pRects); 487 InitRect(FX_FLOAT x,FX_FLOAT y)488 void InitRect(FX_FLOAT x, FX_FLOAT y) { 489 left = x; 490 right = x; 491 bottom = y; 492 top = y; 493 } 494 void UpdateRect(FX_FLOAT x, FX_FLOAT y); 495 Width()496 FX_FLOAT Width() const { return right - left; } Height()497 FX_FLOAT Height() const { return top - bottom; } 498 Inflate(FX_FLOAT x,FX_FLOAT y)499 void Inflate(FX_FLOAT x, FX_FLOAT y) { 500 Normalize(); 501 left -= x; 502 right += x; 503 bottom -= y; 504 top += y; 505 } 506 Inflate(FX_FLOAT other_left,FX_FLOAT other_bottom,FX_FLOAT other_right,FX_FLOAT other_top)507 void Inflate(FX_FLOAT other_left, 508 FX_FLOAT other_bottom, 509 FX_FLOAT other_right, 510 FX_FLOAT other_top) { 511 Normalize(); 512 left -= other_left; 513 bottom -= other_bottom; 514 right += other_right; 515 top += other_top; 516 } 517 Inflate(const CFX_FloatRect & rt)518 void Inflate(const CFX_FloatRect& rt) { 519 Inflate(rt.left, rt.bottom, rt.right, rt.top); 520 } 521 Deflate(FX_FLOAT x,FX_FLOAT y)522 void Deflate(FX_FLOAT x, FX_FLOAT y) { 523 Normalize(); 524 left += x; 525 right -= x; 526 bottom += y; 527 top -= y; 528 } 529 Deflate(FX_FLOAT other_left,FX_FLOAT other_bottom,FX_FLOAT other_right,FX_FLOAT other_top)530 void Deflate(FX_FLOAT other_left, 531 FX_FLOAT other_bottom, 532 FX_FLOAT other_right, 533 FX_FLOAT other_top) { 534 Normalize(); 535 left += other_left; 536 bottom += other_bottom; 537 right -= other_right; 538 top -= other_top; 539 } 540 Deflate(const CFX_FloatRect & rt)541 void Deflate(const CFX_FloatRect& rt) { 542 Deflate(rt.left, rt.bottom, rt.right, rt.top); 543 } 544 Translate(FX_FLOAT e,FX_FLOAT f)545 void Translate(FX_FLOAT e, FX_FLOAT f) { 546 left += e; 547 right += e; 548 top += f; 549 bottom += f; 550 } 551 552 static CFX_FloatRect GetBBox(const CFX_PointF* pPoints, int nPoints); 553 ToFxRect()554 FX_RECT ToFxRect() const { 555 return FX_RECT(static_cast<int32_t>(left), static_cast<int32_t>(top), 556 static_cast<int32_t>(right), static_cast<int32_t>(bottom)); 557 } 558 FromCFXRectF(const CFX_RectF & rect)559 static CFX_FloatRect FromCFXRectF(const CFX_RectF& rect) { 560 return CFX_FloatRect(rect.left, rect.top, rect.right(), rect.bottom()); 561 } 562 563 FX_FLOAT left; 564 FX_FLOAT bottom; 565 FX_FLOAT right; 566 FX_FLOAT top; 567 }; 568 569 class CFX_Matrix { 570 public: CFX_Matrix()571 CFX_Matrix() { SetIdentity(); } 572 CFX_Matrix(const FX_FLOAT n[6])573 explicit CFX_Matrix(const FX_FLOAT n[6]) 574 : a(n[0]), b(n[1]), c(n[2]), d(n[3]), e(n[4]), f(n[5]) {} 575 CFX_Matrix(const CFX_Matrix & other)576 CFX_Matrix(const CFX_Matrix& other) 577 : a(other.a), 578 b(other.b), 579 c(other.c), 580 d(other.d), 581 e(other.e), 582 f(other.f) {} 583 CFX_Matrix(FX_FLOAT a1,FX_FLOAT b1,FX_FLOAT c1,FX_FLOAT d1,FX_FLOAT e1,FX_FLOAT f1)584 CFX_Matrix(FX_FLOAT a1, 585 FX_FLOAT b1, 586 FX_FLOAT c1, 587 FX_FLOAT d1, 588 FX_FLOAT e1, 589 FX_FLOAT f1) 590 : a(a1), b(b1), c(c1), d(d1), e(e1), f(f1) {} 591 592 void operator=(const CFX_Matrix& other) { 593 a = other.a; 594 b = other.b; 595 c = other.c; 596 d = other.d; 597 e = other.e; 598 f = other.f; 599 } 600 SetIdentity()601 void SetIdentity() { 602 a = 1; 603 b = 0; 604 c = 0; 605 d = 1; 606 e = 0; 607 f = 0; 608 } 609 610 void SetReverse(const CFX_Matrix& m); 611 612 void Concat(const CFX_Matrix& m, bool bPrepended = false); 613 void ConcatInverse(const CFX_Matrix& m, bool bPrepended = false); 614 IsIdentity()615 bool IsIdentity() const { 616 return a == 1 && b == 0 && c == 0 && d == 1 && e == 0 && f == 0; 617 } 618 619 bool Is90Rotated() const; 620 bool IsScaled() const; WillScale()621 bool WillScale() const { return a != 1.0f || b != 0 || c != 0 || d != 1.0f; } 622 623 void Translate(FX_FLOAT x, FX_FLOAT y, bool bPrepended = false); 624 void Translate(int32_t x, int32_t y, bool bPrepended = false) { 625 Translate(static_cast<FX_FLOAT>(x), static_cast<FX_FLOAT>(y), bPrepended); 626 } 627 628 void Scale(FX_FLOAT sx, FX_FLOAT sy, bool bPrepended = false); 629 void Rotate(FX_FLOAT fRadian, bool bPrepended = false); 630 void RotateAt(FX_FLOAT fRadian, 631 FX_FLOAT x, 632 FX_FLOAT y, 633 bool bPrepended = false); 634 635 void Shear(FX_FLOAT fAlphaRadian, 636 FX_FLOAT fBetaRadian, 637 bool bPrepended = false); 638 639 void MatchRect(const CFX_FloatRect& dest, const CFX_FloatRect& src); 640 641 FX_FLOAT GetXUnit() const; 642 FX_FLOAT GetYUnit() const; 643 CFX_FloatRect GetUnitRect() const; 644 645 FX_FLOAT TransformXDistance(FX_FLOAT dx) const; 646 FX_FLOAT TransformDistance(FX_FLOAT dx, FX_FLOAT dy) const; 647 FX_FLOAT TransformDistance(FX_FLOAT distance) const; 648 649 CFX_PointF Transform(const CFX_PointF& point) const; 650 651 void TransformRect(CFX_RectF& rect) const; 652 void TransformRect(FX_FLOAT& left, 653 FX_FLOAT& right, 654 FX_FLOAT& top, 655 FX_FLOAT& bottom) const; TransformRect(CFX_FloatRect & rect)656 void TransformRect(CFX_FloatRect& rect) const { 657 TransformRect(rect.left, rect.right, rect.top, rect.bottom); 658 } 659 660 FX_FLOAT a; 661 FX_FLOAT b; 662 FX_FLOAT c; 663 FX_FLOAT d; 664 FX_FLOAT e; 665 FX_FLOAT f; 666 667 private: 668 void ConcatInternal(const CFX_Matrix& other, bool prepend); 669 }; 670 671 #endif // CORE_FXCRT_FX_COORDINATES_H_ 672