1 // Aseprite
2 // Copyright (C) 2001-2018  David Capello
3 //
4 // This program is distributed under the terms of
5 // the End-User License Agreement for Aseprite.
6 
7 #ifdef HAVE_CONFIG_H
8 #include "config.h"
9 #endif
10 
11 #include "app/doc_range.h"
12 
13 #include "base/serialization.h"
14 #include "doc/cel.h"
15 #include "doc/image.h"
16 #include "doc/layer.h"
17 #include "doc/sprite.h"
18 
19 #include <iostream>
20 
21 namespace app {
22 
23 using namespace base::serialization;
24 using namespace base::serialization::little_endian;
25 using namespace doc;
26 
DocRange()27 DocRange::DocRange()
28   : m_type(kNone)
29   , m_flags(m_type)
30   , m_selectingFromLayer(nullptr)
31   , m_selectingFromFrame(-1)
32 {
33 }
34 
DocRange(Cel * cel)35 DocRange::DocRange(Cel* cel)
36   : m_type(kCels)
37   , m_flags(m_type)
38   , m_selectingFromLayer(nullptr)
39   , m_selectingFromFrame(-1)
40 {
41   m_selectedLayers.insert(cel->layer());
42   m_selectedFrames.insert(cel->frame());
43 }
44 
clearRange()45 void DocRange::clearRange()
46 {
47   m_type = kNone;
48   m_flags = kNone;
49   m_selectedLayers.clear();
50   m_selectedFrames.clear();
51 }
52 
startRange(Layer * fromLayer,frame_t fromFrame,Type type)53 void DocRange::startRange(Layer* fromLayer, frame_t fromFrame, Type type)
54 {
55   m_type = type;
56   m_flags |= type;
57   m_selectingFromLayer = fromLayer;
58   m_selectingFromFrame = fromFrame;
59 
60   if (fromLayer)
61     m_selectedLayers.insert(fromLayer);
62   if (fromFrame >= 0)
63     m_selectedFrames.insert(fromFrame);
64 }
65 
endRange(Layer * toLayer,frame_t toFrame)66 void DocRange::endRange(Layer* toLayer, frame_t toFrame)
67 {
68   ASSERT(enabled());
69 
70   if (m_selectingFromLayer && toLayer)
71     selectLayerRange(m_selectingFromLayer, toLayer);
72 
73   if (m_selectingFromFrame >= 0)
74     selectFrameRange(m_selectingFromFrame, toFrame);
75 }
76 
selectLayer(Layer * layer)77 void DocRange::selectLayer(Layer* layer)
78 {
79   if (m_type == kNone)
80     m_type = kLayers;
81   m_flags |= kLayers;
82 
83   m_selectedLayers.insert(layer);
84 }
85 
selectLayers(const SelectedLayers & selLayers)86 void DocRange::selectLayers(const SelectedLayers& selLayers)
87 {
88   if (m_type == kNone)
89     m_type = kLayers;
90   m_flags |= kLayers;
91 
92   for (auto layer : selLayers)
93     m_selectedLayers.insert(layer);
94 }
95 
contains(const Layer * layer) const96 bool DocRange::contains(const Layer* layer) const
97 {
98   if (enabled())
99     return m_selectedLayers.contains(const_cast<Layer*>(layer));
100   else
101     return false;
102 }
103 
contains(const Layer * layer,const frame_t frame) const104 bool DocRange::contains(const Layer* layer,
105                         const frame_t frame) const
106 {
107   switch (m_type) {
108     case DocRange::kNone:
109       return false;
110     case DocRange::kCels:
111       return contains(layer) && contains(frame);
112     case DocRange::kFrames:
113       if (contains(frame)) {
114         if ((m_flags & (kCels | kLayers)) != 0)
115           return contains(layer);
116         else
117           return true;
118       }
119       break;
120     case DocRange::kLayers:
121       if (contains(layer)) {
122         if ((m_flags & (kCels | kFrames)) != 0)
123           return contains(frame);
124         else
125           return true;
126       }
127       break;
128   }
129   return false;
130 }
131 
displace(layer_t layerDelta,frame_t frameDelta)132 void DocRange::displace(layer_t layerDelta, frame_t frameDelta)
133 {
134   m_selectedLayers.displace(layerDelta);
135   m_selectedFrames.displace(frameDelta);
136 }
137 
convertToCels(const Sprite * sprite)138 bool DocRange::convertToCels(const Sprite* sprite)
139 {
140   switch (m_type) {
141     case DocRange::kNone:
142       return false;
143     case DocRange::kCels:
144       break;
145     case DocRange::kFrames: {
146       if ((m_flags & (kCels | kLayers)) == 0) {
147         for (auto layer : sprite->allBrowsableLayers())
148           m_selectedLayers.insert(layer);
149       }
150       m_type = DocRange::kCels;
151       break;
152     }
153     case DocRange::kLayers:
154       if ((m_flags & (kCels | kFrames)) == 0)
155         selectFrameRange(0, sprite->lastFrame());
156       m_type = DocRange::kCels;
157       break;
158   }
159   return true;
160 }
161 
write(std::ostream & os) const162 bool DocRange::write(std::ostream& os) const
163 {
164   write32(os, m_type);
165   write32(os, m_flags);
166 
167   if (!m_selectedLayers.write(os)) return false;
168   if (!m_selectedFrames.write(os)) return false;
169 
170   write32(os, m_selectingFromLayer ? m_selectingFromLayer->id(): 0);
171   write32(os, m_selectingFromFrame);
172   return os.good();
173 }
174 
read(std::istream & is)175 bool DocRange::read(std::istream& is)
176 {
177   clearRange();
178 
179   m_type = (Type)read32(is);
180   m_flags = read32(is);
181 
182   if (!m_selectedLayers.read(is)) return false;
183   if (!m_selectedFrames.read(is)) return false;
184 
185   ObjectId id = read32(is);
186   m_selectingFromLayer = doc::get<Layer>(id);
187   m_selectingFromFrame = read32(is);
188   return is.good();
189 }
190 
selectLayerRange(Layer * fromLayer,Layer * toLayer)191 void DocRange::selectLayerRange(Layer* fromLayer, Layer* toLayer)
192 {
193   ASSERT(fromLayer);
194   ASSERT(toLayer);
195 
196   bool goNext = false;
197   bool goPrev = false;
198   Layer* it;
199 
200   if (fromLayer != toLayer) {
201     it = m_selectingFromLayer;
202     while (it) {
203       if (it == toLayer) {
204         goNext = true;
205         break;
206       }
207       it = it->getNextBrowsable();
208     }
209 
210     if (!goNext) {
211       it = m_selectingFromLayer;
212       while (it) {
213         if (it == toLayer) {
214           goPrev = true;
215           break;
216         }
217         it = it->getPreviousBrowsable();
218       }
219     }
220   }
221 
222   it = m_selectingFromLayer;
223   do {
224     m_selectedLayers.insert(it);
225     if (it == toLayer)
226       break;
227 
228     if (goNext)
229       it = it->getNextBrowsable();
230     else if (goPrev)
231       it = it->getPreviousBrowsable();
232     else
233       break;
234   } while (it);
235 }
236 
selectFrameRange(frame_t fromFrame,frame_t toFrame)237 void DocRange::selectFrameRange(frame_t fromFrame, frame_t toFrame)
238 {
239   m_selectedFrames.insert(fromFrame, toFrame);
240 }
241 
242 } // namespace app
243