1 | // Aseprite Document Library |
2 | // Copyright (c) 2020 Igara Studio S.A. |
3 | // Copyright (c) 2001-2018 David Capello |
4 | // |
5 | // This file is released under the terms of the MIT license. |
6 | // Read LICENSE.txt for more information. |
7 | |
8 | #ifndef DOC_MASK_H_INCLUDED |
9 | #define DOC_MASK_H_INCLUDED |
10 | #pragma once |
11 | |
12 | #include "doc/image.h" |
13 | #include "doc/image_buffer.h" |
14 | #include "doc/image_ref.h" |
15 | #include "doc/object.h" |
16 | #include "doc/primitives.h" |
17 | #include "gfx/rect.h" |
18 | |
19 | #include <string> |
20 | |
21 | namespace doc { |
22 | |
23 | // Represents the selection (selected pixels, 0/1, 0=non-selected, 1=selected) |
24 | // |
25 | // TODO rename Mask -> Selection |
26 | class Mask : public Object { |
27 | public: |
28 | Mask(); |
29 | Mask(const Mask& mask); |
30 | virtual ~Mask(); |
31 | |
32 | virtual int getMemSize() const override; |
33 | |
34 | void setName(const char *name); |
35 | const std::string& name() const { return m_name; } |
36 | |
37 | const Image* bitmap() const { return m_bitmap.get(); } |
38 | Image* bitmap() { return m_bitmap.get(); } |
39 | |
40 | // Returns true if the mask is completely empty (i.e. nothing |
41 | // selected) |
42 | bool isEmpty() const { |
43 | return (!m_bitmap ? true: false); |
44 | } |
45 | |
46 | // Returns true if the point is inside the mask |
47 | bool containsPoint(int u, int v) const { |
48 | return (m_bitmap.get() && |
49 | u >= m_bounds.x && u < m_bounds.x+m_bounds.w && |
50 | v >= m_bounds.y && v < m_bounds.y+m_bounds.h && |
51 | get_pixel(m_bitmap.get(), u-m_bounds.x, v-m_bounds.y)); |
52 | } |
53 | |
54 | gfx::Point origin() const { return m_bounds.origin(); } |
55 | const gfx::Rect& bounds() const { return m_bounds; } |
56 | |
57 | void setOrigin(int x, int y) { |
58 | m_bounds.x = x; |
59 | m_bounds.y = y; |
60 | } |
61 | |
62 | // These functions can be used to disable the automatic call to |
63 | // "shrink" method (so you can do a lot of modifications without |
64 | // lossing time shrinking the mask in each little operation). |
65 | void freeze(); |
66 | void unfreeze(); |
67 | |
68 | // Returns true if the mask is frozen (See freeze/unfreeze functions). |
69 | bool isFrozen() const { return m_freeze_count > 0; } |
70 | |
71 | // Returns true if the mask is a rectangular region. |
72 | bool isRectangular() const; |
73 | |
74 | // Clears the mask. |
75 | void clear(); |
76 | |
77 | // Copies the data from the given mask. |
78 | void copyFrom(const Mask* sourceMask); |
79 | |
80 | // Replace the whole mask with the given region. |
81 | void replace(const gfx::Rect& bounds); |
82 | void replace(const doc::Mask& sourceMask) { copyFrom(&sourceMask); } |
83 | |
84 | // Inverts the mask. |
85 | void invert(); |
86 | |
87 | void add(const doc::Mask& mask); |
88 | void subtract(const doc::Mask& mask); |
89 | void intersect(const doc::Mask& mask); |
90 | |
91 | void add(const gfx::Rect& bounds); |
92 | void subtract(const gfx::Rect& bounds); |
93 | void intersect(const gfx::Rect& bounds); |
94 | |
95 | void byColor(const Image* image, int color, int fuzziness); |
96 | void crop(const Image* image); |
97 | |
98 | // Reserves a rectangle to draw onto the bitmap (you should call |
99 | // shrink after you draw in the bitmap) |
100 | void reserve(const gfx::Rect& bounds); |
101 | |
102 | // Shrinks all sides of the mask to the minimum possible looking at |
103 | // empty pixels in the bitmap |
104 | void shrink(); |
105 | |
106 | // Displaces the mask bounds origin point. |
107 | void offsetOrigin(int dx, int dy); |
108 | |
109 | private: |
110 | void initialize(); |
111 | |
112 | int m_freeze_count; |
113 | std::string m_name; // Mask name |
114 | gfx::Rect m_bounds; // Region bounds |
115 | ImageRef m_bitmap; // Bitmapped image mask |
116 | ImageBufferPtr m_buffer; // Buffer used in m_bitmap |
117 | |
118 | Mask& operator=(const Mask& mask); |
119 | }; |
120 | |
121 | } // namespace doc |
122 | |
123 | #endif |
124 | |