1// Aseprite
2// Copyright (C) 2018-2022 Igara Studio S.A.
3// Copyright (C) 2001-2018 David Capello
4//
5// This program is distributed under the terms of
6// the End-User License Agreement for Aseprite.
7
8#ifdef HAVE_CONFIG_H
9#include "config.h"
10#endif
11
12#include "app/crash/read_document.h"
13
14#include "app/console.h"
15#include "app/crash/doc_format.h"
16#include "app/crash/internals.h"
17#include "app/doc.h"
18#include "base/convert_to.h"
19#include "base/exception.h"
20#include "base/fs.h"
21#include "base/fstream_path.h"
22#include "base/serialization.h"
23#include "base/string.h"
24#include "doc/cel.h"
25#include "doc/cel_data_io.h"
26#include "doc/cel_io.h"
27#include "doc/cels_range.h"
28#include "doc/frame.h"
29#include "doc/image_io.h"
30#include "doc/layer.h"
31#include "doc/layer_tilemap.h"
32#include "doc/palette.h"
33#include "doc/palette_io.h"
34#include "doc/slice.h"
35#include "doc/slice_io.h"
36#include "doc/sprite.h"
37#include "doc/string_io.h"
38#include "doc/subobjects_io.h"
39#include "doc/tag.h"
40#include "doc/tag_io.h"
41#include "doc/tileset.h"
42#include "doc/tileset_io.h"
43#include "doc/tilesets.h"
44#include "doc/user_data_io.h"
45#include "doc/util.h"
46#include "fixmath/fixmath.h"
47
48#include <fstream>
49#include <map>
50
51namespace app {
52namespace crash {
53
54using namespace base::serialization;
55using namespace base::serialization::little_endian;
56using namespace doc;
57
58namespace {
59
60class Reader : public SubObjectsIO {
61public:
62 Reader(const std::string& dir,
63 base::task_token* t)
64 : m_docFormatVer(DOC_FORMAT_VERSION_0)
65 , m_sprite(nullptr)
66 , m_dir(dir)
67 , m_docId(0)
68 , m_docVersions(nullptr)
69 , m_loadInfo(nullptr)
70 , m_taskToken(t) {
71 for (const auto& fn : base::list_files(dir)) {
72 auto i = fn.find('-');
73 if (i == std::string::npos)
74 continue; // Has no ID
75
76 auto j = fn.find('.', ++i);
77 if (j == std::string::npos)
78 continue; // Has no version
79
80 ObjectId id = base::convert_to<int>(fn.substr(i, j - i));
81 ObjectVersion ver = base::convert_to<int>(fn.substr(j+1));
82 if (!id || !ver)
83 continue; // Error converting strings to ID/ver
84
85 ObjVersions& versions = m_objVersions[id];
86 versions.add(ver);
87
88 if (fn.compare(0, 3, "doc") == 0) {
89 if (!m_docId)
90 m_docId = id;
91 else {
92 ASSERT(m_docId == id);
93 }
94
95 m_docVersions = &versions;
96 }
97 }
98 }
99
100 Doc* loadDocument() {
101 Doc* doc = loadObject<Doc*>("doc", m_docId, &Reader::readDocument);
102 if (doc)
103 fixUndetectedDocumentIssues(doc);
104 else
105 Console().printf("Error recovering the document\n");
106 return doc;
107 }
108
109 bool loadDocumentInfo(DocumentInfo& info) {
110 m_loadInfo = &info;
111 return
112 loadObject<Doc*>("doc", m_docId, &Reader::readDocument)
113 == (Doc*)1;
114 }
115
116private:
117
118 const ObjectVersion docId() const {
119 return m_docId;
120 }
121
122 const ObjVersions* docVersions() const {
123 return m_docVersions;
124 }
125
126 Sprite* loadSprite(ObjectId sprId) {
127 return loadObject<Sprite*>("spr", sprId, &Reader::readSprite);
128 }
129
130 ImageRef getImageRef(ObjectId imageId) {
131 if (m_images.find(imageId) != m_images.end())
132 return m_images[imageId];
133
134 ImageRef image(loadObject<Image*>("img", imageId, &Reader::readImage));
135 return m_images[imageId] = image;
136 }
137
138 CelDataRef getCelDataRef(ObjectId celdataId) {
139 if (m_celdatas.find(celdataId) != m_celdatas.end())
140 return m_celdatas[celdataId];
141
142 CelDataRef celData(loadObject<CelData*>("celdata", celdataId, &Reader::readCelData));
143 return m_celdatas[celdataId] = celData;
144 }
145
146 template<typename T>
147 T loadObject(const char* prefix, ObjectId id, T (Reader::*readMember)(std::ifstream&)) {
148 const ObjVersions& versions = m_objVersions[id];
149
150 for (size_t i=0; i<versions.size(); ++i) {
151 ObjectVersion ver = versions[i];
152 if (!ver)
153 continue;
154
155 TRACE("RECO: Restoring %s #%d v%d\n", prefix, id, ver);
156
157 std::string fn = prefix;
158 fn.push_back('-');
159 fn += base::convert_to<std::string>(id);
160 fn.push_back('.');
161 fn += base::convert_to<std::string>(ver);
162
163 std::ifstream s(FSTREAM_PATH(base::join_path(m_dir, fn)), std::ifstream::binary);
164 T obj = nullptr;
165 if (read32(s) == MAGIC_NUMBER)
166 obj = (this->*readMember)(s);
167
168 if (obj) {
169 TRACE("RECO: %s #%d v%d restored successfully\n", prefix, id, ver);
170 return obj;
171 }
172 else {
173 TRACE("RECO: %s #%d v%d was not restored\n", prefix, id, ver);
174 }
175 }
176
177 // Show error only if we've failed to load all versions
178 if (!m_loadInfo)
179 Console().printf("Error loading object %s #%d\n", prefix, id);
180
181 return nullptr;
182 }
183
184 Doc* readDocument(std::ifstream& s) {
185 ObjectId sprId = read32(s);
186 std::string filename = read_string(s);
187 m_docFormatVer = read16(s);
188 if (s.eof()) m_docFormatVer = DOC_FORMAT_VERSION_0;
189
190 TRACE("RECO: internal format version=%d\n", m_docFormatVer);
191
192 // Load DocumentInfo only
193 if (m_loadInfo) {
194 m_loadInfo->filename = filename;
195 return (Doc*)loadSprite(sprId);
196 }
197
198 Sprite* spr = loadSprite(sprId);
199 if (spr) {
200 Doc* doc = new Doc(spr);
201 doc->setFilename(filename);
202 doc->impossibleToBackToSavedState();
203 return doc;
204 }
205 else {
206 Console().printf("Unable to load sprite #%d\n", sprId);
207 return nullptr;
208 }
209 }
210
211 Sprite* readSprite(std::ifstream& s) {
212 // Header
213 ColorMode mode = (ColorMode)read8(s);
214 int w = read16(s);
215 int h = read16(s);
216 color_t transparentColor = read32(s);
217 frame_t nframes = read32(s);
218
219 if (mode != ColorMode::RGB &&
220 mode != ColorMode::INDEXED &&
221 mode != ColorMode::GRAYSCALE) {
222 if (!m_loadInfo)
223 Console().printf("Invalid sprite color mode #%d\n", (int)mode);
224 return nullptr;
225 }
226
227 if (w < 1 || h < 1 || w > 0xfffff || h > 0xfffff) {
228 if (!m_loadInfo)
229 Console().printf("Invalid sprite dimension %dx%d\n", w, h);
230 return nullptr;
231 }
232
233 if (m_loadInfo) {
234 m_loadInfo->mode = mode;
235 m_loadInfo->width = w;
236 m_loadInfo->height = h;
237 m_loadInfo->frames = nframes;
238 return (Sprite*)1; // TODO improve this
239 }
240
241 std::unique_ptr<Sprite> spr(new Sprite(ImageSpec(mode, w, h), 256));
242 m_sprite = spr.get();
243 spr->setTransparentColor(transparentColor);
244
245 if (nframes >= 1) {
246 spr->setTotalFrames(nframes);
247 for (frame_t fr=0; fr<nframes; ++fr) {
248 int msecs = read32(s);
249 spr->setFrameDuration(fr, msecs);
250 }
251 }
252 else {
253 Console().printf("Invalid number of frames #%d\n", nframes);
254 }
255
256 // IDs of all tilesets
257 if (m_docFormatVer >= DOC_FORMAT_VERSION_1) {
258 int ntilesets = read32(s);
259 if (ntilesets > 0 && ntilesets < 0xffffff) {
260 for (int i=0; i<ntilesets; ++i) {
261 ObjectId tilesetId = read32(s);
262 Tileset* tileset = loadObject<Tileset*>("tset", tilesetId, &Reader::readTileset);
263 if (tileset)
264 spr->tilesets()->add(tileset);
265 }
266 }
267 }
268
269 // Read layers
270 int nlayers = read32(s);
271 if (nlayers >= 1 && nlayers < 0xfffff) {
272 std::map<ObjectId, LayerGroup*> layersMap;
273 layersMap[0] = spr->root(); // parentId = 0 is the root level
274
275 for (int i=0; i<nlayers; ++i) {
276 if (canceled())
277 return nullptr;
278
279 ObjectId layId = read32(s);
280 ObjectId parentId = read32(s);
281
282 if (!layersMap[parentId]) {
283 Console().printf("Inexistent parent #%d for layer #%d", parentId, layId);
284 // Put this layer at the root level
285 parentId = 0;
286 }
287
288 Layer* lay = loadObject<Layer*>("lay", layId, &Reader::readLayer);
289 if (lay) {
290 if (lay->isGroup())
291 layersMap[layId] = static_cast<LayerGroup*>(lay);
292
293 layersMap[parentId]->addLayer(lay);
294 }
295 }
296 }
297 else {
298 Console().printf("Invalid number of layers #%d\n", nlayers);
299 }
300
301 // Read all cels
302 for (size_t i=0; i<m_celsToLoad.size(); ++i) {
303 if (canceled())
304 return nullptr;
305
306 const auto& pair = m_celsToLoad[i];
307 LayerImage* lay = doc::get<LayerImage>(pair.first);
308 if (!lay)
309 continue;
310
311 ObjectId celId = pair.second;
312
313 Cel* cel = loadObject<Cel*>("cel", celId, &Reader::readCel);
314 if (cel) {
315 // Expand sprite size
316 if (cel->frame() > m_sprite->lastFrame())
317 m_sprite->setTotalFrames(cel->frame()+1);
318
319 lay->addCel(cel);
320 }
321
322 if (m_taskToken) {
323 m_taskToken->set_progress(float(i) / float(m_celsToLoad.size()));
324 }
325 }
326
327 // Read palettes
328 int npalettes = read32(s);
329 if (npalettes >= 1 && npalettes < 0xfffff) {
330 for (int i = 0; i < npalettes; ++i) {
331 if (canceled())
332 return nullptr;
333
334 ObjectId palId = read32(s);
335 std::unique_ptr<Palette> pal(
336 loadObject<Palette*>("pal", palId, &Reader::readPalette));
337 if (pal)
338 spr->setPalette(pal.get(), true);
339 }
340 }
341
342 // Read frame tags
343 int nfrtags = read32(s);
344 if (nfrtags >= 1 && nfrtags < 0xfffff) {
345 for (int i = 0; i < nfrtags; ++i) {
346 if (canceled())
347 return nullptr;
348
349 ObjectId tagId = read32(s);
350 Tag* tag = loadObject<Tag*>("frtag", tagId, &Reader::readTag);
351 if (tag)
352 spr->tags().add(tag);
353 }
354 }
355
356 // Read slices
357 int nslices = read32(s);
358 if (nslices >= 1 && nslices < 0xffffff) {
359 for (int i = 0; i < nslices; ++i) {
360 if (canceled())
361 return nullptr;
362
363 ObjectId sliceId = read32(s);
364 Slice* slice = loadObject<Slice*>("slice", sliceId, &Reader::readSlice);
365 if (slice)
366 spr->slices().add(slice);
367 }
368 }
369
370 // Read color space
371 if (!s.eof()) {
372 gfx::ColorSpaceRef colorSpace = readColorSpace(s);
373 if (colorSpace)
374 spr->setColorSpace(colorSpace);
375 }
376
377 // Read grid bounds
378 if (!s.eof()) {
379 gfx::Rect gridBounds = readGridBounds(s);
380 if (!gridBounds.isEmpty())
381 spr->setGridBounds(gridBounds);
382 }
383
384 // Read Sprite User Data
385 if (!s.eof()) {
386 UserData userData = readUserData(s);
387 if (!userData.isEmpty())
388 spr->setUserData(userData);
389 }
390
391 return spr.release();
392 }
393
394 UserData readUserData(std::ifstream& s) {
395 UserData userData;
396 userData.setText(read_string(s));
397 // This check is here because we've been restoring sprites from
398 // old sessions where the color is restored incorrectly if we
399 // don't check if there is enough space to read from the file
400 // (e.g. reading a random color or just white, maybe -1 which is
401 // 0xffffffff in 32-bit).
402 if (!s.eof()) {
403 userData.setColor(read32(s));
404 }
405 return userData;
406 }
407
408 gfx::ColorSpaceRef readColorSpace(std::ifstream& s) {
409 const gfx::ColorSpace::Type type = (gfx::ColorSpace::Type)read16(s);
410 const gfx::ColorSpace::Flag flags = (gfx::ColorSpace::Flag)read16(s);
411 const double gamma = fixmath::fixtof(read32(s));
412 const size_t n = read32(s);
413
414 // If the color space file is to big, it's because the sprite file
415 // is invalid or or from an old session without color spcae.
416 if (n > 1024*1024*64) // 64 MB is too much for an ICC file
417 return nullptr;
418
419 std::vector<uint8_t> buf(n);
420 if (n)
421 s.read((char*)&buf[0], n);
422 std::string name = read_string(s);
423
424 auto colorSpace = base::make_ref<gfx::ColorSpace>(
425 type, flags, gamma, std::move(buf));
426 colorSpace->setName(name);
427 return colorSpace;
428 }
429
430 gfx::Rect readGridBounds(std::ifstream& s) {
431 gfx::Rect grid;
432 grid.x = (int16_t)read16(s);
433 grid.y = (int16_t)read16(s);
434 grid.w = read16(s);
435 grid.h = read16(s);
436 return grid;
437 }
438
439 // TODO could we use doc::read_layer() here?
440 Layer* readLayer(std::ifstream& s) {
441 LayerFlags flags = (LayerFlags)read32(s);
442 ObjectType type = (ObjectType)read16(s);
443 ASSERT(type == ObjectType::LayerImage ||
444 type == ObjectType::LayerGroup ||
445 type == ObjectType::LayerTilemap);
446
447 std::string name = read_string(s);
448 std::unique_ptr<Layer> lay;
449
450 switch (type) {
451
452 case ObjectType::LayerImage:
453 case ObjectType::LayerTilemap: {
454 switch (type) {
455 case ObjectType::LayerImage:
456 lay.reset(new LayerImage(m_sprite));
457 break;
458 case ObjectType::LayerTilemap: {
459 tileset_index tilesetIndex = read32(s);
460 lay.reset(new LayerTilemap(m_sprite, tilesetIndex));
461 break;
462 }
463 }
464
465 lay->setName(name);
466 lay->setFlags(flags);
467
468 // Blend mode & opacity
469 static_cast<LayerImage*>(lay.get())->setBlendMode((BlendMode)read16(s));
470 static_cast<LayerImage*>(lay.get())->setOpacity(read8(s));
471
472 // Cels
473 int ncels = read32(s);
474 for (int i=0; i<ncels; ++i) {
475 if (canceled())
476 return nullptr;
477
478 // Add a new cel to load in the future after we load all layers
479 ObjectId celId = read32(s);
480 m_celsToLoad.push_back(std::make_pair(lay->id(), celId));
481 }
482 break;
483 }
484
485 case ObjectType::LayerGroup:
486 lay.reset(new LayerGroup(m_sprite));
487 lay->setName(name);
488 lay->setFlags(flags);
489 break;
490
491 default:
492 Console().printf("Unable to load layer named '%s', type #%d\n",
493 name.c_str(), (int)type);
494 break;
495 }
496
497 if (lay) {
498 UserData userData = read_user_data(s);
499 lay->setUserData(userData);
500 return lay.release();
501 }
502 else
503 return nullptr;
504 }
505
506 Cel* readCel(std::ifstream& s) {
507 return read_cel(s, this, false);
508 }
509
510 CelData* readCelData(std::ifstream& s) {
511 return read_celdata(s, this, false);
512 }
513
514 Image* readImage(std::ifstream& s) {
515 return read_image(s, false);
516 }
517
518 Palette* readPalette(std::ifstream& s) {
519 return read_palette(s);
520 }
521
522 Tileset* readTileset(std::ifstream& s) {
523 bool isOldVersion = false;
524 Tileset* tileset = read_tileset(s, m_sprite, false, &isOldVersion);
525 if (tileset && isOldVersion)
526 m_updateOldTilemapWithTileset.insert(tileset->id());
527 return tileset;
528 }
529
530 Tag* readTag(std::ifstream& s) {
531 const bool oldVersion = (m_docFormatVer < DOC_FORMAT_VERSION_1);
532 return read_tag(s, false, oldVersion);
533 }
534
535 Slice* readSlice(std::ifstream& s) {
536 return read_slice(s, false);
537 }
538
539 // Fix issues that the restoration process could produce.
540 void fixUndetectedDocumentIssues(Doc* doc) {
541 Sprite* spr = doc->sprite();
542 ASSERT(spr);
543 if (!spr)
544 return; // TODO create an empty sprite
545
546 // Fill the background layer with empty cels if they are missing
547 if (LayerImage* bg = spr->backgroundLayer()) {
548 for (frame_t fr=0; fr<spr->totalFrames(); ++fr) {
549 Cel* cel = bg->cel(fr);
550 if (!cel) {
551 ImageRef image(Image::create(spr->pixelFormat(),
552 spr->width(),
553 spr->height()));
554 image->clear(spr->transparentColor());
555 cel = new Cel(fr, image);
556 bg->addCel(cel);
557 }
558 }
559 }
560
561 // Fix tilemaps using old tilesets
562 if (!m_updateOldTilemapWithTileset.empty()) {
563 for (Tileset* tileset : *spr->tilesets()) {
564 if (m_updateOldTilemapWithTileset.find(tileset->id()) == m_updateOldTilemapWithTileset.end())
565 continue;
566
567 for (Cel* cel : spr->uniqueCels()) {
568 if (cel->image()->pixelFormat() == IMAGE_TILEMAP &&
569 static_cast<LayerTilemap*>(cel->layer())->tileset() == tileset) {
570 doc::fix_old_tilemap(cel->image(), tileset,
571 tile_i_mask, tile_f_mask);
572 }
573 }
574 }
575 }
576 }
577
578 bool canceled() const {
579 if (m_taskToken)
580 return m_taskToken->canceled();
581 else
582 return false;
583 }
584
585 int m_docFormatVer;
586 Sprite* m_sprite; // Used to pass the sprite in LayerImage() ctor
587 std::string m_dir;
588 ObjectVersion m_docId;
589 ObjVersionsMap m_objVersions;
590 ObjVersions* m_docVersions;
591 DocumentInfo* m_loadInfo;
592 std::vector<std::pair<ObjectId, ObjectId> > m_celsToLoad;
593 std::map<ObjectId, ImageRef> m_images;
594 std::map<ObjectId, CelDataRef> m_celdatas;
595 // Each ObjectId is a tileset ID that didn't contain the empty tile
596 // as the first tile (this was an old format used in internal betas)
597 std::set<ObjectId> m_updateOldTilemapWithTileset;
598 base::task_token* m_taskToken;
599};
600
601} // anonymous namespace
602
603//////////////////////////////////////////////////////////////////////
604// Public API
605
606bool read_document_info(const std::string& dir, DocumentInfo& info)
607{
608 return Reader(dir, nullptr).loadDocumentInfo(info);
609}
610
611Doc* read_document(const std::string& dir,
612 base::task_token* t)
613{
614 return Reader(dir, t).loadDocument();
615}
616
617Doc* read_document_with_raw_images(const std::string& dir,
618 RawImagesAs as,
619 base::task_token* t)
620{
621 Reader reader(dir, t);
622
623 DocumentInfo info;
624 if (!reader.loadDocumentInfo(info)) {
625 info.mode = ColorMode::RGB;
626 info.width = 256;
627 info.height = 256;
628 info.filename = "Unknown";
629 }
630 info.width = std::clamp(info.width, 1, 99999);
631 info.height = std::clamp(info.height, 1, 99999);
632 Sprite* spr = new Sprite(ImageSpec(info.mode, info.width, info.height), 256);
633
634 // Load each image as a new frame
635 auto lay = new LayerImage(spr);
636 spr->root()->addLayer(lay);
637
638 int i = 0;
639 frame_t frame = 0;
640 auto fns = base::list_files(dir);
641 for (const auto& fn : fns) {
642 if (t)
643 t->set_progress((i++) / fns.size());
644
645 if (fn.compare(0, 3, "img") != 0)
646 continue;
647
648 std::ifstream s(FSTREAM_PATH(base::join_path(dir, fn)), std::ifstream::binary);
649 if (!s)
650 continue;
651
652 ImageRef img;
653 if (read32(s) == MAGIC_NUMBER)
654 img.reset(read_image(s, false));
655
656 if (img) {
657 lay->addCel(new Cel(frame, img));
658 }
659
660 switch (as) {
661 case RawImagesAs::kFrames:
662 ++frame;
663 break;
664 case RawImagesAs::kLayers:
665 lay = new LayerImage(spr);
666 spr->root()->addLayer(lay);
667 break;
668 }
669 }
670 if (as == RawImagesAs::kFrames) {
671 if (frame > 1)
672 spr->setTotalFrames(frame);
673 }
674
675 Doc* doc = new Doc(spr);
676 doc->setFilename(info.filename);
677 doc->impossibleToBackToSavedState();
678 return doc;
679}
680
681} // namespace crash
682} // namespace app
683