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