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