1 // Aseprite
2 // Copyright (C) 2001-2017  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/crash/read_document.h"
12 
13 #include "app/console.h"
14 #include "app/crash/internals.h"
15 #include "app/doc.h"
16 #include "base/convert_to.h"
17 #include "base/exception.h"
18 #include "base/fs.h"
19 #include "base/fstream_path.h"
20 #include "base/serialization.h"
21 #include "base/string.h"
22 #include "base/unique_ptr.h"
23 #include "doc/cel.h"
24 #include "doc/cel_data_io.h"
25 #include "doc/cel_io.h"
26 #include "doc/cels_range.h"
27 #include "doc/frame.h"
28 #include "doc/frame_tag.h"
29 #include "doc/frame_tag_io.h"
30 #include "doc/image_io.h"
31 #include "doc/layer.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 
40 #include <fstream>
41 #include <map>
42 
43 namespace app {
44 namespace crash {
45 
46 using namespace base::serialization;
47 using namespace base::serialization::little_endian;
48 using namespace doc;
49 
50 namespace {
51 
52 class Reader : public SubObjectsIO {
53 public:
Reader(const std::string & dir)54   Reader(const std::string& dir)
55     : m_sprite(nullptr)
56     , m_dir(dir)
57     , m_docId(0)
58     , m_docVersions(nullptr)
59     , m_loadInfo(nullptr) {
60     for (const auto& fn : base::list_files(dir)) {
61       auto i = fn.find('-');
62       if (i == std::string::npos)
63         continue;               // Has no ID
64 
65       auto j = fn.find('.', ++i);
66       if (j == std::string::npos)
67         continue;               // Has no version
68 
69       ObjectId id = base::convert_to<int>(fn.substr(i, j - i));
70       ObjectVersion ver = base::convert_to<int>(fn.substr(j+1));
71       if (!id || !ver)
72         continue;               // Error converting strings to ID/ver
73 
74       ObjVersions& versions = m_objVersions[id];
75       versions.add(ver);
76 
77       if (fn.compare(0, 3, "doc") == 0) {
78         if (!m_docId)
79           m_docId = id;
80         else {
81           ASSERT(m_docId == id);
82         }
83 
84         m_docVersions = &versions;
85       }
86     }
87   }
88 
loadDocument()89   Doc* loadDocument() {
90     Doc* doc = loadObject<Doc*>("doc", m_docId, &Reader::readDocument);
91     if (doc)
92       fixUndetectedDocumentIssues(doc);
93     else
94       Console().printf("Error recovering the document\n");
95     return doc;
96   }
97 
loadDocumentInfo(DocumentInfo & info)98   bool loadDocumentInfo(DocumentInfo& info) {
99     m_loadInfo = &info;
100     return
101       loadObject<Doc*>("doc", m_docId, &Reader::readDocument)
102         == (Doc*)1;
103   }
104 
105 private:
106 
docId() const107   const ObjectVersion docId() const {
108     return m_docId;
109   }
110 
docVersions() const111   const ObjVersions* docVersions() const {
112     return m_docVersions;
113   }
114 
loadSprite(ObjectId sprId)115   Sprite* loadSprite(ObjectId sprId) {
116     return loadObject<Sprite*>("spr", sprId, &Reader::readSprite);
117   }
118 
getImageRef(ObjectId imageId)119   ImageRef getImageRef(ObjectId imageId) {
120     if (m_images.find(imageId) != m_images.end())
121       return m_images[imageId];
122 
123     ImageRef image(loadObject<Image*>("img", imageId, &Reader::readImage));
124     return m_images[imageId] = image;
125   }
126 
getCelDataRef(ObjectId celdataId)127   CelDataRef getCelDataRef(ObjectId celdataId) {
128     if (m_celdatas.find(celdataId) != m_celdatas.end())
129       return m_celdatas[celdataId];
130 
131     CelDataRef celData(loadObject<CelData*>("celdata", celdataId, &Reader::readCelData));
132     return m_celdatas[celdataId] = celData;
133   }
134 
135   template<typename T>
loadObject(const char * prefix,ObjectId id,T (Reader::* readMember)(std::ifstream &))136   T loadObject(const char* prefix, ObjectId id, T (Reader::*readMember)(std::ifstream&)) {
137     const ObjVersions& versions = m_objVersions[id];
138 
139     for (size_t i=0; i<versions.size(); ++i) {
140       ObjectVersion ver = versions[i];
141       if (!ver)
142         continue;
143 
144       TRACE("RECO: Restoring %s #%d v%d\n", prefix, id, ver);
145 
146       std::string fn = prefix;
147       fn.push_back('-');
148       fn += base::convert_to<std::string>(id);
149       fn.push_back('.');
150       fn += base::convert_to<std::string>(ver);
151 
152       std::ifstream s(FSTREAM_PATH(base::join_path(m_dir, fn)), std::ifstream::binary);
153       T obj = nullptr;
154       if (read32(s) == MAGIC_NUMBER)
155         obj = (this->*readMember)(s);
156 
157       if (obj) {
158         TRACE("RECO: %s #%d v%d restored successfully\n", prefix, id, ver);
159         return obj;
160       }
161       else {
162         TRACE("RECO: %s #%d v%d was not restored\n", prefix, id, ver);
163       }
164     }
165 
166     // Show error only if we've failed to load all versions
167     if (!m_loadInfo)
168       Console().printf("Error loading object %s #%d\n", prefix, id);
169 
170     return nullptr;
171   }
172 
readDocument(std::ifstream & s)173   Doc* readDocument(std::ifstream& s) {
174     ObjectId sprId = read32(s);
175     std::string filename = read_string(s);
176 
177     // Load DocumentInfo only
178     if (m_loadInfo) {
179       m_loadInfo->filename = filename;
180       return (Doc*)loadSprite(sprId);
181     }
182 
183     Sprite* spr = loadSprite(sprId);
184     if (spr) {
185       Doc* doc = new Doc(spr);
186       doc->setFilename(filename);
187       doc->impossibleToBackToSavedState();
188       return doc;
189     }
190     else {
191       Console().printf("Unable to load sprite #%d\n", sprId);
192       return nullptr;
193     }
194   }
195 
readSprite(std::ifstream & s)196   Sprite* readSprite(std::ifstream& s) {
197     PixelFormat format = (PixelFormat)read8(s);
198     int w = read16(s);
199     int h = read16(s);
200     color_t transparentColor = read32(s);
201     frame_t nframes = read32(s);
202 
203     if (format != IMAGE_RGB &&
204         format != IMAGE_INDEXED &&
205         format != IMAGE_GRAYSCALE) {
206       if (!m_loadInfo)
207         Console().printf("Invalid sprite format #%d\n", (int)format);
208       return nullptr;
209     }
210 
211     if (w < 1 || h < 1 || w > 0xfffff || h > 0xfffff) {
212       if (!m_loadInfo)
213         Console().printf("Invalid sprite dimension %dx%d\n", w, h);
214       return nullptr;
215     }
216 
217     if (m_loadInfo) {
218       m_loadInfo->format = format;
219       m_loadInfo->width = w;
220       m_loadInfo->height = h;
221       m_loadInfo->frames = nframes;
222       return (Sprite*)1;
223     }
224 
225     base::UniquePtr<Sprite> spr(new Sprite(format, w, h, 256));
226     m_sprite = spr.get();
227     spr->setTransparentColor(transparentColor);
228 
229     if (nframes >= 1) {
230       spr->setTotalFrames(nframes);
231       for (frame_t fr=0; fr<nframes; ++fr) {
232         int msecs = read32(s);
233         spr->setFrameDuration(fr, msecs);
234       }
235     }
236     else {
237       Console().printf("Invalid number of frames #%d\n", nframes);
238     }
239 
240     // Read layers
241     int nlayers = read32(s);
242     if (nlayers >= 1 && nlayers < 0xfffff) {
243       std::map<ObjectId, LayerGroup*> layersMap;
244       layersMap[0] = spr->root(); // parentId = 0 is the root level
245 
246       for (int i = 0; i < nlayers; ++i) {
247         ObjectId layId = read32(s);
248         ObjectId parentId = read32(s);
249 
250         if (!layersMap[parentId]) {
251           Console().printf("Inexistent parent #%d for layer #%d", parentId, layId);
252           // Put this layer at the root level
253           parentId = 0;
254         }
255 
256         Layer* lay = loadObject<Layer*>("lay", layId, &Reader::readLayer);
257         if (lay) {
258           if (lay->isGroup())
259             layersMap[layId] = static_cast<LayerGroup*>(lay);
260 
261           layersMap[parentId]->addLayer(lay);
262         }
263       }
264     }
265     else {
266       Console().printf("Invalid number of layers #%d\n", nlayers);
267     }
268 
269     // Read palettes
270     int npalettes = read32(s);
271     if (npalettes >= 1 && npalettes < 0xfffff) {
272       for (int i = 0; i < npalettes; ++i) {
273         ObjectId palId = read32(s);
274         Palette* pal = loadObject<Palette*>("pal", palId, &Reader::readPalette);
275         if (pal)
276           spr->setPalette(pal, true);
277       }
278     }
279 
280     // Read frame tags
281     int nfrtags = read32(s);
282     if (nfrtags >= 1 && nfrtags < 0xfffff) {
283       for (int i = 0; i < nfrtags; ++i) {
284         ObjectId tagId = read32(s);
285         FrameTag* tag = loadObject<FrameTag*>("frtag", tagId, &Reader::readFrameTag);
286         if (tag)
287           spr->frameTags().add(tag);
288       }
289     }
290 
291     // Read slices
292     int nslices = read32(s);
293     if (nslices >= 1 && nslices < 0xffffff) {
294       for (int i = 0; i < nslices; ++i) {
295         ObjectId sliceId = read32(s);
296         Slice* slice = loadObject<Slice*>("slice", sliceId, &Reader::readSlice);
297         if (slice)
298           spr->slices().add(slice);
299       }
300     }
301 
302     return spr.release();
303   }
304 
305   // TODO could we use doc::read_layer() here?
readLayer(std::ifstream & s)306   Layer* readLayer(std::ifstream& s) {
307     LayerFlags flags = (LayerFlags)read32(s);
308     ObjectType type = (ObjectType)read16(s);
309     ASSERT(type == ObjectType::LayerImage ||
310            type == ObjectType::LayerGroup);
311 
312     std::string name = read_string(s);
313 
314     if (type == ObjectType::LayerImage) {
315       base::UniquePtr<LayerImage> lay(new LayerImage(m_sprite));
316       lay->setName(name);
317       lay->setFlags(flags);
318 
319       // Blend mode & opacity
320       lay->setBlendMode((BlendMode)read16(s));
321       lay->setOpacity(read8(s));
322 
323       // Cels
324       int ncels = read32(s);
325       for (int i=0; i<ncels; ++i) {
326         ObjectId celId = read32(s);
327         Cel* cel = loadObject<Cel*>("cel", celId, &Reader::readCel);
328         if (cel) {
329           // Expand sprite size
330           if (cel->frame() > m_sprite->lastFrame())
331             m_sprite->setTotalFrames(cel->frame()+1);
332 
333           lay->addCel(cel);
334         }
335       }
336       return lay.release();
337     }
338     else if (type == ObjectType::LayerGroup) {
339       base::UniquePtr<LayerGroup> lay(new LayerGroup(m_sprite));
340       lay->setName(name);
341       lay->setFlags(flags);
342       return lay.release();
343     }
344     else {
345       Console().printf("Unable to load layer named '%s', type #%d\n",
346         name.c_str(), (int)type);
347       return nullptr;
348     }
349   }
350 
readCel(std::ifstream & s)351   Cel* readCel(std::ifstream& s) {
352     return read_cel(s, this, false);
353   }
354 
readCelData(std::ifstream & s)355   CelData* readCelData(std::ifstream& s) {
356     return read_celdata(s, this, false);
357   }
358 
readImage(std::ifstream & s)359   Image* readImage(std::ifstream& s) {
360     return read_image(s, false);
361   }
362 
readPalette(std::ifstream & s)363   Palette* readPalette(std::ifstream& s) {
364     return read_palette(s);
365   }
366 
readFrameTag(std::ifstream & s)367   FrameTag* readFrameTag(std::ifstream& s) {
368     return read_frame_tag(s, false);
369   }
370 
readSlice(std::ifstream & s)371   Slice* readSlice(std::ifstream& s) {
372     return read_slice(s, false);
373   }
374 
375   // Fix issues that the restoration process could produce.
fixUndetectedDocumentIssues(Doc * doc)376   void fixUndetectedDocumentIssues(Doc* doc) {
377     Sprite* spr = doc->sprite();
378     ASSERT(spr);
379     if (!spr)
380       return;                   // TODO create an empty sprite
381 
382     // Fill the background layer with empty cels if they are missing
383     if (LayerImage* bg = spr->backgroundLayer()) {
384       for (frame_t fr=0; fr<spr->totalFrames(); ++fr) {
385         Cel* cel = bg->cel(fr);
386         if (!cel) {
387           ImageRef image(Image::create(spr->pixelFormat(),
388                                        spr->width(),
389                                        spr->height()));
390           image->clear(spr->transparentColor());
391           cel = new Cel(fr, image);
392           bg->addCel(cel);
393         }
394       }
395     }
396   }
397 
398   Sprite* m_sprite;    // Used to pass the sprite in LayerImage() ctor
399   std::string m_dir;
400   ObjectVersion m_docId;
401   ObjVersionsMap m_objVersions;
402   ObjVersions* m_docVersions;
403   DocumentInfo* m_loadInfo;
404   std::map<ObjectId, ImageRef> m_images;
405   std::map<ObjectId, CelDataRef> m_celdatas;
406 };
407 
408 } // anonymous namespace
409 
410 //////////////////////////////////////////////////////////////////////
411 // Public API
412 
read_document_info(const std::string & dir,DocumentInfo & info)413 bool read_document_info(const std::string& dir, DocumentInfo& info)
414 {
415   return Reader(dir).loadDocumentInfo(info);
416 }
417 
read_document(const std::string & dir)418 Doc* read_document(const std::string& dir)
419 {
420   return Reader(dir).loadDocument();
421 }
422 
read_document_with_raw_images(const std::string & dir,RawImagesAs as)423 Doc* read_document_with_raw_images(const std::string& dir,
424                                    RawImagesAs as)
425 {
426   Reader reader(dir);
427 
428   DocumentInfo info;
429   if (!reader.loadDocumentInfo(info)) {
430     info.format = IMAGE_RGB;
431     info.width = 256;
432     info.height = 256;
433     info.filename = "Unknown";
434   }
435   info.width = MID(1, info.width, 99999);
436   info.height = MID(1, info.height, 99999);
437   Sprite* spr = new Sprite(info.format, info.width, info.height, 256);
438 
439   // Load each image as a new frame
440   auto lay = new LayerImage(spr);
441   spr->root()->addLayer(lay);
442 
443   frame_t frame = 0;
444   for (const auto& fn : base::list_files(dir)) {
445     if (fn.compare(0, 3, "img") != 0)
446       continue;
447 
448     std::ifstream s(FSTREAM_PATH(base::join_path(dir, fn)), std::ifstream::binary);
449     if (!s)
450       continue;
451 
452     ImageRef img;
453     if (read32(s) == MAGIC_NUMBER)
454       img.reset(read_image(s, false));
455 
456     if (img) {
457       lay->addCel(new Cel(frame, img));
458     }
459 
460     switch (as) {
461       case RawImagesAs::kFrames:
462         ++frame;
463         break;
464       case RawImagesAs::kLayers:
465         lay = new LayerImage(spr);
466         spr->root()->addLayer(lay);
467         break;
468     }
469   }
470   if (as == RawImagesAs::kFrames) {
471     if (frame > 1)
472       spr->setTotalFrames(frame);
473   }
474 
475   Doc* doc = new Doc(spr);
476   doc->setFilename(info.filename);
477   doc->impossibleToBackToSavedState();
478   return doc;
479 }
480 
481 } // namespace crash
482 } // namespace app
483