1 // Aseprite 2 // Copyright (C) 2001-2016 David Capello 3 // 4 // This program is distributed under the terms of 5 // the End-User License Agreement for Aseprite. 6 7 #ifndef APP_TRANSFORMATION_H_INCLUDED 8 #define APP_TRANSFORMATION_H_INCLUDED 9 #pragma once 10 11 #include "gfx/point.h" 12 #include "gfx/rect.h" 13 #include <vector> 14 15 namespace app { 16 17 // Represents a transformation that can be done by the user in the 18 // document when he/she moves the mask using the selection handles. 19 class Transformation { 20 public: 21 class Corners { 22 public: 23 enum { 24 LEFT_TOP = 0, 25 RIGHT_TOP = 1, 26 RIGHT_BOTTOM = 2, 27 LEFT_BOTTOM = 3, 28 NUM_OF_CORNERS = 4 29 }; 30 Corners()31 Corners() : m_corners(NUM_OF_CORNERS) { } 32 size()33 std::size_t size() const { return m_corners.size(); } 34 35 gfx::PointF& operator[](int index) { return m_corners[index]; } 36 const gfx::PointF& operator[](int index) const { return m_corners[index]; } 37 leftTop()38 const gfx::PointF& leftTop() const { return m_corners[LEFT_TOP]; } rightTop()39 const gfx::PointF& rightTop() const { return m_corners[RIGHT_TOP]; } rightBottom()40 const gfx::PointF& rightBottom() const { return m_corners[RIGHT_BOTTOM]; } leftBottom()41 const gfx::PointF& leftBottom() const { return m_corners[LEFT_BOTTOM]; } 42 leftTop(const gfx::PointF & pt)43 void leftTop(const gfx::PointF& pt) { m_corners[LEFT_TOP] = pt; } rightTop(const gfx::PointF & pt)44 void rightTop(const gfx::PointF& pt) { m_corners[RIGHT_TOP] = pt; } rightBottom(const gfx::PointF & pt)45 void rightBottom(const gfx::PointF& pt) { m_corners[RIGHT_BOTTOM] = pt; } leftBottom(const gfx::PointF & pt)46 void leftBottom(const gfx::PointF& pt) { m_corners[LEFT_BOTTOM] = pt; } 47 48 Corners& operator=(const gfx::RectF bounds) { 49 m_corners[LEFT_TOP].x = bounds.x; 50 m_corners[LEFT_TOP].y = bounds.y; 51 m_corners[RIGHT_TOP].x = bounds.x + bounds.w; 52 m_corners[RIGHT_TOP].y = bounds.y; 53 m_corners[RIGHT_BOTTOM].x = bounds.x + bounds.w; 54 m_corners[RIGHT_BOTTOM].y = bounds.y + bounds.h; 55 m_corners[LEFT_BOTTOM].x = bounds.x; 56 m_corners[LEFT_BOTTOM].y = bounds.y + bounds.h; 57 return *this; 58 } 59 bounds()60 gfx::RectF bounds() const { 61 gfx::RectF bounds; 62 for (int i=0; i<Corners::NUM_OF_CORNERS; ++i) 63 bounds |= gfx::RectF(m_corners[i].x, m_corners[i].y, 1, 1); 64 return bounds; 65 } 66 67 private: 68 std::vector<gfx::PointF> m_corners; 69 }; 70 71 Transformation(); 72 Transformation(const gfx::RectF& bounds); 73 74 // Simple getters and setters. The angle is in radians. 75 bounds()76 const gfx::RectF& bounds() const { return m_bounds; } pivot()77 const gfx::PointF& pivot() const { return m_pivot; } angle()78 double angle() const { return m_angle; } 79 bounds(const gfx::RectF & bounds)80 void bounds(const gfx::RectF& bounds) { m_bounds = bounds; } pivot(const gfx::PointF & pivot)81 void pivot(const gfx::PointF& pivot) { m_pivot = pivot; } angle(double angle)82 void angle(double angle) { m_angle = angle; } 83 84 // Applies the transformation (rotation with angle/pivot) to the 85 // current bounds (m_bounds). 86 void transformBox(Corners& corners) const; 87 88 // Changes the pivot to another location, adjusting the bounds to 89 // keep the current rotated-corners in the same location. 90 void displacePivotTo(const gfx::PointF& newPivot); 91 92 gfx::RectF transformedBounds() const; 93 94 // Static helper method to rotate points. 95 static gfx::PointF rotatePoint(const gfx::PointF& point, 96 const gfx::PointF& pivot, 97 double angle); 98 99 private: 100 gfx::RectF m_bounds; 101 gfx::PointF m_pivot; 102 double m_angle; 103 }; 104 105 } // namespace app 106 107 #endif 108