1 // Aseprite Document Library
2 // Copyright (c) 2001-2018 David Capello
3 //
4 // This file is released under the terms of the MIT license.
5 // Read LICENSE.txt for more information.
6 
7 #ifdef HAVE_CONFIG_H
8 #include "config.h"
9 #endif
10 
11 #include "doc/sprite.h"
12 
13 #include "base/base.h"
14 #include "base/memory.h"
15 #include "base/remove_from_container.h"
16 #include "base/unique_ptr.h"
17 #include "doc/cel.h"
18 #include "doc/cels_range.h"
19 #include "doc/frame_tag.h"
20 #include "doc/image_impl.h"
21 #include "doc/layer.h"
22 #include "doc/palette.h"
23 #include "doc/primitives.h"
24 #include "doc/remap.h"
25 #include "doc/rgbmap.h"
26 
27 #include <cstring>
28 #include <vector>
29 
30 namespace doc {
31 
32 //////////////////////////////////////////////////////////////////////
33 // Constructors/Destructor
34 
Sprite(PixelFormat format,int width,int height,int ncolors)35 Sprite::Sprite(PixelFormat format, int width, int height, int ncolors)
36   : Object(ObjectType::Sprite)
37   , m_document(NULL)
38   , m_spec((ColorMode)format, width, height, 0)
39   , m_pixelRatio(1, 1)
40   , m_frames(1)
41   , m_frameTags(this)
42   , m_slices(this)
43 {
44   ASSERT(width > 0 && height > 0);
45 
46   m_frlens.push_back(100);      // First frame with 100 msecs of duration
47   m_root = new LayerGroup(this);
48 
49   // Generate palette
50   switch (format) {
51     case IMAGE_GRAYSCALE: ncolors = 256; break;
52     case IMAGE_BITMAP: ncolors = 2; break;
53   }
54 
55   Palette pal(frame_t(0), ncolors);
56 
57   switch (format) {
58 
59     // For black and white images
60     case IMAGE_GRAYSCALE:
61     case IMAGE_BITMAP:
62       for (int c=0; c<ncolors; c++) {
63         int g = 255 * c / (ncolors-1);
64         g = MID(0, g, 255);
65         pal.setEntry(c, rgba(g, g, g, 255));
66       }
67       break;
68   }
69 
70   // Initial RGB map
71   m_rgbMap = NULL;
72 
73   setPalette(&pal, true);
74 }
75 
Sprite(const ImageSpec & spec,int ncolors)76 Sprite::Sprite(const ImageSpec& spec, int ncolors)
77   : Sprite((PixelFormat)spec.colorMode(), spec.width(), spec.height(), ncolors)
78 {
79 }
80 
~Sprite()81 Sprite::~Sprite()
82 {
83   // Destroy layers
84   delete m_root;
85 
86   // Destroy palettes
87   {
88     PalettesList::iterator end = m_palettes.end();
89     PalettesList::iterator it = m_palettes.begin();
90     for (; it != end; ++it)
91       delete *it;               // palette
92   }
93 
94   // Destroy RGB map
95   delete m_rgbMap;
96 }
97 
98 // static
createBasicSprite(doc::PixelFormat format,int width,int height,int ncolors)99 Sprite* Sprite::createBasicSprite(doc::PixelFormat format, int width, int height, int ncolors)
100 {
101   // Create the sprite.
102   base::UniquePtr<doc::Sprite> sprite(new doc::Sprite(format, width, height, ncolors));
103   sprite->setTotalFrames(doc::frame_t(1));
104 
105   // Create the main image.
106   doc::ImageRef image(doc::Image::create(format, width, height));
107   doc::clear_image(image.get(), 0);
108 
109   // Create the first transparent layer.
110   {
111     base::UniquePtr<doc::LayerImage> layer(new doc::LayerImage(sprite));
112     layer->setName("Layer 1");
113 
114     // Create the cel.
115     {
116       base::UniquePtr<doc::Cel> cel(new doc::Cel(doc::frame_t(0), image));
117       cel->setPosition(0, 0);
118 
119       // Add the cel in the layer.
120       layer->addCel(cel);
121       cel.release();            // Release the cel because it is in the layer
122     }
123 
124     // Add the layer in the sprite.
125     sprite->root()->addLayer(layer.release()); // Release the layer because it's owned by the sprite
126   }
127 
128   return sprite.release();
129 }
130 
131 //////////////////////////////////////////////////////////////////////
132 // Main properties
133 
setPixelFormat(PixelFormat format)134 void Sprite::setPixelFormat(PixelFormat format)
135 {
136   m_spec.setColorMode((ColorMode)format);
137 }
138 
setPixelRatio(const PixelRatio & pixelRatio)139 void Sprite::setPixelRatio(const PixelRatio& pixelRatio)
140 {
141   m_pixelRatio = pixelRatio;
142 }
143 
setSize(int width,int height)144 void Sprite::setSize(int width, int height)
145 {
146   ASSERT(width > 0);
147   ASSERT(height > 0);
148 
149   m_spec.setSize(width, height);
150 }
151 
needAlpha() const152 bool Sprite::needAlpha() const
153 {
154   switch (pixelFormat()) {
155     case IMAGE_RGB:
156     case IMAGE_GRAYSCALE: {
157       Layer* bg = backgroundLayer();
158       return (!bg || !bg->isVisible());
159     }
160   }
161   return false;
162 }
163 
supportAlpha() const164 bool Sprite::supportAlpha() const
165 {
166   switch (pixelFormat()) {
167     case IMAGE_RGB:
168     case IMAGE_GRAYSCALE:
169       return true;
170   }
171   return false;
172 }
173 
setTransparentColor(color_t color)174 void Sprite::setTransparentColor(color_t color)
175 {
176   m_spec.setMaskColor(color);
177 
178   // Change the mask color of all images.
179   std::vector<Image*> images;
180   getImages(images);
181   for (Image* image : images)
182     image->setMaskColor(color);
183 }
184 
getMemSize() const185 int Sprite::getMemSize() const
186 {
187   int size = 0;
188 
189   std::vector<Image*> images;
190   getImages(images);
191   for (Image* image : images)
192     size += image->getRowStrideSize() * image->height();
193 
194   return size;
195 }
196 
197 //////////////////////////////////////////////////////////////////////
198 // Layers
199 
backgroundLayer() const200 LayerImage* Sprite::backgroundLayer() const
201 {
202   if (root()->layersCount() > 0) {
203     Layer* bglayer = root()->layers().front();
204 
205     if (bglayer->isBackground()) {
206       ASSERT(bglayer->isImage());
207       return static_cast<LayerImage*>(bglayer);
208     }
209   }
210   return NULL;
211 }
212 
firstBrowsableLayer() const213 Layer* Sprite::firstBrowsableLayer() const
214 {
215   Layer* layer = root()->firstLayer();
216   while (layer->isBrowsable())
217     layer = static_cast<LayerGroup*>(layer)->firstLayer();
218   return layer;
219 }
220 
allLayersCount() const221 layer_t Sprite::allLayersCount() const
222 {
223   return root()->allLayersCount();
224 }
225 
hasVisibleReferenceLayers() const226 bool Sprite::hasVisibleReferenceLayers() const
227 {
228   return root()->hasVisibleReferenceLayers();
229 }
230 
231 //////////////////////////////////////////////////////////////////////
232 // Palettes
233 
palette(frame_t frame) const234 Palette* Sprite::palette(frame_t frame) const
235 {
236   ASSERT(frame >= 0);
237 
238   Palette* found = NULL;
239 
240   PalettesList::const_iterator end = m_palettes.end();
241   PalettesList::const_iterator it = m_palettes.begin();
242   for (; it != end; ++it) {
243     Palette* pal = *it;
244     if (frame < pal->frame())
245       break;
246 
247     found = pal;
248     if (frame == pal->frame())
249       break;
250   }
251 
252   ASSERT(found != NULL);
253   return found;
254 }
255 
getPalettes() const256 const PalettesList& Sprite::getPalettes() const
257 {
258   return m_palettes;
259 }
260 
setPalette(const Palette * pal,bool truncate)261 void Sprite::setPalette(const Palette* pal, bool truncate)
262 {
263   ASSERT(pal != NULL);
264 
265   if (!truncate) {
266     Palette* sprite_pal = palette(pal->frame());
267     pal->copyColorsTo(sprite_pal);
268   }
269   else {
270     Palette* other;
271 
272     PalettesList::iterator end = m_palettes.end();
273     PalettesList::iterator it = m_palettes.begin();
274     for (; it != end; ++it) {
275       other = *it;
276 
277       if (pal->frame() == other->frame()) {
278         pal->copyColorsTo(other);
279         return;
280       }
281       else if (pal->frame() < other->frame())
282         break;
283     }
284 
285     m_palettes.insert(it, new Palette(*pal));
286   }
287 }
288 
resetPalettes()289 void Sprite::resetPalettes()
290 {
291   PalettesList::iterator end = m_palettes.end();
292   PalettesList::iterator it = m_palettes.begin();
293 
294   if (it != end) {
295     ++it;                       // Leave the first palette only.
296     while (it != end) {
297       delete *it;               // palette
298       it = m_palettes.erase(it);
299       end = m_palettes.end();
300     }
301   }
302 }
303 
deletePalette(frame_t frame)304 void Sprite::deletePalette(frame_t frame)
305 {
306   auto it = m_palettes.begin(), end = m_palettes.end();
307   for (; it != end; ++it) {
308     Palette* pal = *it;
309 
310     if (pal->frame() == frame) {
311       delete pal;                   // delete palette
312       m_palettes.erase(it);
313       break;
314     }
315   }
316 }
317 
rgbMap(frame_t frame) const318 RgbMap* Sprite::rgbMap(frame_t frame) const
319 {
320   return rgbMap(frame, backgroundLayer() ? RgbMapFor::OpaqueLayer:
321                                            RgbMapFor::TransparentLayer);
322 }
323 
rgbMap(frame_t frame,RgbMapFor forLayer) const324 RgbMap* Sprite::rgbMap(frame_t frame, RgbMapFor forLayer) const
325 {
326   int maskIndex = (forLayer == RgbMapFor::OpaqueLayer ?
327                    -1: transparentColor());
328 
329   if (m_rgbMap == NULL) {
330     m_rgbMap = new RgbMap();
331     m_rgbMap->regenerate(palette(frame), maskIndex);
332   }
333   else if (!m_rgbMap->match(palette(frame)) ||
334            m_rgbMap->maskIndex() != maskIndex) {
335     m_rgbMap->regenerate(palette(frame), maskIndex);
336   }
337 
338   return m_rgbMap;
339 }
340 
341 //////////////////////////////////////////////////////////////////////
342 // Frames
343 
addFrame(frame_t newFrame)344 void Sprite::addFrame(frame_t newFrame)
345 {
346   setTotalFrames(m_frames+1);
347   for (frame_t i=m_frames-1; i>=newFrame; --i)
348     setFrameDuration(i, frameDuration(i-1));
349 
350   root()->displaceFrames(newFrame, +1);
351 }
352 
removeFrame(frame_t frame)353 void Sprite::removeFrame(frame_t frame)
354 {
355   root()->displaceFrames(frame, -1);
356 
357   frame_t newTotal = m_frames-1;
358   for (frame_t i=frame; i<newTotal; ++i)
359     setFrameDuration(i, frameDuration(i+1));
360   setTotalFrames(newTotal);
361 }
362 
setTotalFrames(frame_t frames)363 void Sprite::setTotalFrames(frame_t frames)
364 {
365   frames = MAX(frame_t(1), frames);
366   m_frlens.resize(frames);
367 
368   if (frames > m_frames) {
369     for (frame_t c=m_frames; c<frames; ++c)
370       m_frlens[c] = m_frlens[m_frames-1];
371   }
372 
373   m_frames = frames;
374 }
375 
frameDuration(frame_t frame) const376 int Sprite::frameDuration(frame_t frame) const
377 {
378   if (frame >= 0 && frame < m_frames)
379     return m_frlens[frame];
380   else
381     return 0;
382 }
383 
totalAnimationDuration() const384 int Sprite::totalAnimationDuration() const
385 {
386   int duration = 0;
387   for (frame_t frame=0; frame<m_frames; ++frame)
388     duration += frameDuration(frame);
389   return duration; // TODO cache this value
390 }
391 
setFrameDuration(frame_t frame,int msecs)392 void Sprite::setFrameDuration(frame_t frame, int msecs)
393 {
394   if (frame >= 0 && frame < m_frames)
395     m_frlens[frame] = MID(1, msecs, 65535);
396 }
397 
setFrameRangeDuration(frame_t from,frame_t to,int msecs)398 void Sprite::setFrameRangeDuration(frame_t from, frame_t to, int msecs)
399 {
400   std::fill(
401     m_frlens.begin()+(std::size_t)from,
402     m_frlens.begin()+(std::size_t)to+1, MID(1, msecs, 65535));
403 }
404 
setDurationForAllFrames(int msecs)405 void Sprite::setDurationForAllFrames(int msecs)
406 {
407   std::fill(m_frlens.begin(), m_frlens.end(), MID(1, msecs, 65535));
408 }
409 
410 //////////////////////////////////////////////////////////////////////
411 // Shared Images and CelData (for linked Cels)
412 
getImageRef(ObjectId imageId)413 ImageRef Sprite::getImageRef(ObjectId imageId)
414 {
415   for (Cel* cel : cels()) {
416     if (cel->image()->id() == imageId)
417       return cel->imageRef();
418   }
419   return ImageRef(nullptr);
420 }
421 
getCelDataRef(ObjectId celDataId)422 CelDataRef Sprite::getCelDataRef(ObjectId celDataId)
423 {
424   for (Cel* cel : cels()) {
425     if (cel->dataRef()->id() == celDataId)
426       return cel->dataRef();
427   }
428   return CelDataRef(nullptr);
429 }
430 
431 //////////////////////////////////////////////////////////////////////
432 // Images
433 
replaceImage(ObjectId curImageId,const ImageRef & newImage)434 void Sprite::replaceImage(ObjectId curImageId, const ImageRef& newImage)
435 {
436   for (Cel* cel : cels()) {
437     if (cel->image()->id() == curImageId)
438       cel->data()->setImage(newImage);
439   }
440 }
441 
442 // TODO replace it with a images iterator
getImages(std::vector<Image * > & images) const443 void Sprite::getImages(std::vector<Image*>& images) const
444 {
445   for (const auto& cel : uniqueCels())
446     images.push_back(cel->image());
447 }
448 
remapImages(frame_t frameFrom,frame_t frameTo,const Remap & remap)449 void Sprite::remapImages(frame_t frameFrom, frame_t frameTo, const Remap& remap)
450 {
451   ASSERT(pixelFormat() == IMAGE_INDEXED);
452   //ASSERT(remap.size() == 256);
453 
454   for (const Cel* cel : uniqueCels()) {
455     // Remap this Cel because is inside the specified range
456     if (cel->frame() >= frameFrom &&
457         cel->frame() <= frameTo) {
458       remap_image(cel->image(), remap);
459     }
460   }
461 }
462 
463 //////////////////////////////////////////////////////////////////////
464 // Drawing
465 
pickCels(const double x,const double y,const frame_t frame,const int opacityThreshold,const LayerList & layers,CelList & cels) const466 void Sprite::pickCels(const double x,
467                       const double y,
468                       const frame_t frame,
469                       const int opacityThreshold,
470                       const LayerList& layers,
471                       CelList& cels) const
472 {
473   gfx::PointF pos(x, y);
474 
475   for (int i=(int)layers.size()-1; i>=0; --i) {
476     const Layer* layer = layers[i];
477     if (!layer->isImage())
478       continue;
479 
480     Cel* cel = layer->cel(frame);
481     if (!cel)
482       continue;
483 
484     const Image* image = cel->image();
485     if (!image)
486       continue;
487 
488     gfx::RectF celBounds;
489     if (cel->layer()->isReference())
490       celBounds = cel->boundsF();
491     else
492       celBounds = cel->bounds();
493 
494     if (!celBounds.contains(pos))
495       continue;
496 
497     const gfx::Point ipos(
498       int((pos.x-celBounds.x)*image->width()/celBounds.w),
499       int((pos.y-celBounds.y)*image->height()/celBounds.h));
500     if (!image->bounds().contains(ipos))
501       continue;
502 
503     const color_t color = get_pixel(image, ipos.x, ipos.y);
504     bool isOpaque = true;
505 
506     switch (image->pixelFormat()) {
507       case IMAGE_RGB:
508         isOpaque = (rgba_geta(color) >= opacityThreshold);
509         break;
510       case IMAGE_INDEXED:
511         isOpaque = (color != image->maskColor());
512         break;
513       case IMAGE_GRAYSCALE:
514         isOpaque = (graya_geta(color) >= opacityThreshold);
515         break;
516     }
517 
518     if (!isOpaque)
519       continue;
520 
521     cels.push_back(cel);
522   }
523 }
524 
525 //////////////////////////////////////////////////////////////////////
526 // Iterators
527 
allLayers() const528 LayerList Sprite::allLayers() const
529 {
530   LayerList list;
531   m_root->allLayers(list);
532   return list;
533 }
534 
allVisibleLayers() const535 LayerList Sprite::allVisibleLayers() const
536 {
537   LayerList list;
538   m_root->allVisibleLayers(list);
539   return list;
540 }
541 
allVisibleReferenceLayers() const542 LayerList Sprite::allVisibleReferenceLayers() const
543 {
544   LayerList list;
545   m_root->allVisibleReferenceLayers(list);
546   return list;
547 }
548 
allBrowsableLayers() const549 LayerList Sprite::allBrowsableLayers() const
550 {
551   LayerList list;
552   m_root->allBrowsableLayers(list);
553   return list;
554 }
555 
cels() const556 CelsRange Sprite::cels() const
557 {
558   SelectedFrames selFrames;
559   selFrames.insert(0, lastFrame());
560   return CelsRange(this, selFrames);
561 }
562 
cels(frame_t frame) const563 CelsRange Sprite::cels(frame_t frame) const
564 {
565   SelectedFrames selFrames;
566   selFrames.insert(frame);
567   return CelsRange(this, selFrames);
568 }
569 
uniqueCels() const570 CelsRange Sprite::uniqueCels() const
571 {
572   SelectedFrames selFrames;
573   selFrames.insert(0, lastFrame());
574   return CelsRange(this, selFrames, CelsRange::UNIQUE);
575 }
576 
uniqueCels(const SelectedFrames & selFrames) const577 CelsRange Sprite::uniqueCels(const SelectedFrames& selFrames) const
578 {
579   return CelsRange(this, selFrames, CelsRange::UNIQUE);
580 }
581 
582 } // namespace doc
583