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