From cdea6004bd5a6b8ccc89d8ba8889f679027a1daa Mon Sep 17 00:00:00 2001 From: David Capello Date: Tue, 25 Jun 2024 22:42:42 -0300 Subject: [PATCH] Refactor app::DocFormat to doc::SerialFormat This fixes a violation of module layers (circular dependency) introduced in e6cd13d7e13775de2a687e55e59819cb7f19e7e9 where doc-lib started to depend on app-lib (which cannot happen, as app-lib depends on doc-lib). This DocFormat/SerialFormat was used only from app-lib previously, but when properties were introduced in user data, the serialization format version was needed to read user properties too. So now it makes sense to move this type/its values to the doc-lib. A couple of extra issues were found in this refactor: 1) The recursive call inside read_layer() didn't receive this "serial" argument 2) read_grid() doesn't need the setId parameter --- src/app/crash/doc_format.h | 16 ---------------- src/app/crash/read_document.cpp | 27 ++++++++++++++------------- src/app/crash/write_document.cpp | 6 +++--- src/doc/cel_data_io.cpp | 10 +++++++--- src/doc/cel_data_io.h | 12 +++++++++--- src/doc/grid_io.cpp | 2 +- src/doc/grid_io.h | 2 +- src/doc/image_io.cpp | 2 +- src/doc/layer_io.cpp | 10 ++++++---- src/doc/layer_io.h | 10 +++++++--- src/doc/serial_format.h | 27 +++++++++++++++++++++++++++ src/doc/slice_io.cpp | 6 ++++-- src/doc/slice_io.h | 13 +++++++++---- src/doc/tag_io.cpp | 10 +++++----- src/doc/tag_io.h | 12 +++++++----- src/doc/tileset_io.cpp | 16 ++++++++-------- src/doc/tileset_io.h | 6 +++--- src/doc/user_data_io.cpp | 5 +++-- src/doc/user_data_io.h | 10 +++++++--- 19 files changed, 122 insertions(+), 80 deletions(-) delete mode 100644 src/app/crash/doc_format.h create mode 100644 src/doc/serial_format.h diff --git a/src/app/crash/doc_format.h b/src/app/crash/doc_format.h deleted file mode 100644 index be47ce1f1..000000000 --- a/src/app/crash/doc_format.h +++ /dev/null @@ -1,16 +0,0 @@ -// Aseprite -// Copyright (c) 2020 Igara Studio S.A. -// -// This program is distributed under the terms of -// the End-User License Agreement for Aseprite. - -#ifndef APP_CRASH_DOC_FORMAT_H_INCLUDED -#define APP_CRASH_DOC_FORMAT_H_INCLUDED -#pragma once - -#define DOC_FORMAT_VERSION_0 0 // Old version -#define DOC_FORMAT_VERSION_1 1 // New version with tilesets -#define DOC_FORMAT_VERSION_2 2 // Version 2 adds custom properties to user data -#define DOC_FORMAT_VERSION_LAST 2 - -#endif diff --git a/src/app/crash/read_document.cpp b/src/app/crash/read_document.cpp index 73a79e637..eff10357c 100644 --- a/src/app/crash/read_document.cpp +++ b/src/app/crash/read_document.cpp @@ -12,7 +12,6 @@ #include "app/crash/read_document.h" #include "app/console.h" -#include "app/crash/doc_format.h" #include "app/crash/internals.h" #include "app/crash/log.h" #include "app/doc.h" @@ -32,6 +31,7 @@ #include "doc/layer_tilemap.h" #include "doc/palette.h" #include "doc/palette_io.h" +#include "doc/serial_format.h" #include "doc/slice.h" #include "doc/slice_io.h" #include "doc/sprite.h" @@ -70,7 +70,7 @@ class Reader : public SubObjectsIO { public: Reader(const std::string& dir, base::task_token* t) - : m_docFormatVer(DOC_FORMAT_VERSION_0) + : m_serial(SerialFormat::Ver0) , m_sprite(nullptr) , m_dir(dir) , m_docId(0) @@ -198,10 +198,11 @@ private: Doc* readDocument(std::ifstream& s) { ObjectId sprId = read32(s); std::string filename = read_string(s); - m_docFormatVer = read16(s); - if (s.eof()) m_docFormatVer = DOC_FORMAT_VERSION_0; + m_serial = SerialFormat(read16(s)); + if (s.eof()) + m_serial = SerialFormat::Ver0; - RECO_TRACE("RECO: internal format version=%d\n", m_docFormatVer); + RECO_TRACE("RECO: internal format version=%d\n", int(m_serial)); // Load DocumentInfo only if (m_loadInfo) { @@ -268,7 +269,7 @@ private: } // IDs of all tilesets - if (m_docFormatVer >= DOC_FORMAT_VERSION_1) { + if (m_serial >= SerialFormat::Ver1) { int ntilesets = read32(s); if (ntilesets > 0 && ntilesets < 0xffffff) { for (int i=0; isetUserData(userData); } @@ -497,7 +498,7 @@ private: } if (lay) { - UserData userData = read_user_data(s, m_docFormatVer); + UserData userData = read_user_data(s, m_serial); lay->setUserData(userData); return lay.release(); } @@ -510,7 +511,7 @@ private: } CelData* readCelData(std::ifstream& s) { - return read_celdata(s, this, false, m_docFormatVer); + return read_celdata(s, this, false, m_serial); } Image* readImage(std::ifstream& s) { @@ -523,18 +524,18 @@ private: Tileset* readTileset(std::ifstream& s) { uint32_t tilesetVer; - Tileset* tileset = read_tileset(s, m_sprite, false, &tilesetVer, m_docFormatVer); + Tileset* tileset = read_tileset(s, m_sprite, false, &tilesetVer, m_serial); if (tileset && tilesetVer < TILESET_VER1) m_updateOldTilemapWithTileset.insert(tileset->id()); return tileset; } Tag* readTag(std::ifstream& s) { - return read_tag(s, false, m_docFormatVer); + return read_tag(s, false, m_serial); } Slice* readSlice(std::ifstream& s) { - return read_slice(s, false, m_docFormatVer); + return read_slice(s, false, m_serial); } // Fix issues that the restoration process could produce. @@ -586,7 +587,7 @@ private: return false; } - int m_docFormatVer; + SerialFormat m_serial; Sprite* m_sprite; // Used to pass the sprite in LayerImage() ctor std::string m_dir; ObjectVersion m_docId; diff --git a/src/app/crash/write_document.cpp b/src/app/crash/write_document.cpp index a6e8a5b31..ada5eb3e6 100644 --- a/src/app/crash/write_document.cpp +++ b/src/app/crash/write_document.cpp @@ -1,5 +1,5 @@ // Aseprite -// Copyright (C) 2018-2023 Igara Studio S.A. +// Copyright (C) 2018-2024 Igara Studio S.A. // Copyright (C) 2001-2018 David Capello // // This program is distributed under the terms of @@ -11,7 +11,6 @@ #include "app/crash/write_document.h" -#include "app/crash/doc_format.h" #include "app/crash/internals.h" #include "app/crash/log.h" #include "app/doc.h" @@ -31,6 +30,7 @@ #include "doc/layer_tilemap.h" #include "doc/palette.h" #include "doc/palette_io.h" +#include "doc/serial_format.h" #include "doc/slice.h" #include "doc/slice_io.h" #include "doc/sprite.h" @@ -152,7 +152,7 @@ private: bool writeDocumentFile(std::ofstream& s, Doc* doc) { write32(s, doc->sprite()->id()); write_string(s, doc->filename()); - write16(s, DOC_FORMAT_VERSION_LAST); + write16(s, uint16_t(doc::SerialFormat::LastVer)); return true; } diff --git a/src/doc/cel_data_io.cpp b/src/doc/cel_data_io.cpp index 13551035e..04d6cdb6e 100644 --- a/src/doc/cel_data_io.cpp +++ b/src/doc/cel_data_io.cpp @@ -27,7 +27,8 @@ namespace doc { using namespace base::serialization; using namespace base::serialization::little_endian; -void write_celdata(std::ostream& os, const CelData* celdata) +void write_celdata(std::ostream& os, + const CelData* celdata) { write32(os, celdata->id()); write32(os, celdata->bounds().x); @@ -50,7 +51,10 @@ void write_celdata(std::ostream& os, const CelData* celdata) } } -CelData* read_celdata(std::istream& is, SubObjectsIO* subObjects, const bool setId, const int docFormatVer) +CelData* read_celdata(std::istream& is, + SubObjectsIO* subObjects, + const bool setId, + const SerialFormat serial) { ObjectId id = read32(is); int x = read32(is); @@ -59,7 +63,7 @@ CelData* read_celdata(std::istream& is, SubObjectsIO* subObjects, const bool set int h = read32(is); int opacity = read8(is); ObjectId imageId = read32(is); - UserData userData = read_user_data(is, docFormatVer); + const UserData userData = read_user_data(is, serial); gfx::RectF boundsF; // Extra fields diff --git a/src/doc/cel_data_io.h b/src/doc/cel_data_io.h index 102f38819..6817623e8 100644 --- a/src/doc/cel_data_io.h +++ b/src/doc/cel_data_io.h @@ -1,4 +1,5 @@ // Aseprite Document Library +// Copyright (c) 2024 Igara Studio S.A. // Copyright (c) 2001-2015 David Capello // // This file is released under the terms of the MIT license. @@ -8,7 +9,7 @@ #define DOC_CEL_DATA_IO_H_INCLUDED #pragma once -#include "app/crash/doc_format.h" +#include "doc/serial_format.h" #include @@ -17,8 +18,13 @@ namespace doc { class CelData; class SubObjectsIO; - void write_celdata(std::ostream& os, const CelData* cel); - CelData* read_celdata(std::istream& is, SubObjectsIO* subObjects, const bool setId = true, const int read_celdata = DOC_FORMAT_VERSION_LAST); + void write_celdata(std::ostream& os, + const CelData* cel); + + CelData* read_celdata(std::istream& is, + SubObjectsIO* subObjects, + bool setId = true, + SerialFormat serial = SerialFormat::LastVer); } // namespace doc diff --git a/src/doc/grid_io.cpp b/src/doc/grid_io.cpp index 8c2cca6f9..179ad87b5 100644 --- a/src/doc/grid_io.cpp +++ b/src/doc/grid_io.cpp @@ -43,7 +43,7 @@ bool write_grid(std::ostream& os, const Grid& grid) return true; } -Grid read_grid(std::istream& is, bool setId) +Grid read_grid(std::istream& is) { gfx::Size tileSize; gfx::Point origin; diff --git a/src/doc/grid_io.h b/src/doc/grid_io.h index 93aa1edd1..61d8538e1 100644 --- a/src/doc/grid_io.h +++ b/src/doc/grid_io.h @@ -15,7 +15,7 @@ namespace doc { class Grid; bool write_grid(std::ostream& os, const Grid& grid); - Grid read_grid(std::istream& is, bool setId = true); + Grid read_grid(std::istream& is); } // namespace doc diff --git a/src/doc/image_io.cpp b/src/doc/image_io.cpp index 38ef9388a..01084f7fd 100644 --- a/src/doc/image_io.cpp +++ b/src/doc/image_io.cpp @@ -102,7 +102,7 @@ bool write_image(std::ostream& os, const Image* image, CancelIO* cancel) return true; } -Image* read_image(std::istream& is, bool setId) +Image* read_image(std::istream& is, const bool setId) { ObjectId id = read32(is); int pixelFormat = read8(is); // Pixel format diff --git a/src/doc/layer_io.cpp b/src/doc/layer_io.cpp index 4a18e4a80..1bef82787 100644 --- a/src/doc/layer_io.cpp +++ b/src/doc/layer_io.cpp @@ -110,7 +110,9 @@ void write_layer(std::ostream& os, const Layer* layer) write_user_data(os, layer->userData()); } -Layer* read_layer(std::istream& is, SubObjectsFromSprite* subObjects, const int docFormatVer) +Layer* read_layer(std::istream& is, + SubObjectsFromSprite* subObjects, + const SerialFormat serial) { ObjectId id = read32(is); std::string name = read_string(is); @@ -147,7 +149,7 @@ Layer* read_layer(std::istream& is, SubObjectsFromSprite* subObjects, const int // Read celdatas int celdatas = read16(is); for (int c=0; caddCelDataRef(celdata); } @@ -176,7 +178,7 @@ Layer* read_layer(std::istream& is, SubObjectsFromSprite* subObjects, const int // Number of sub-layers int layers = read16(is); for (int c=0; c(layer.get())->addLayer(child); else @@ -190,7 +192,7 @@ Layer* read_layer(std::istream& is, SubObjectsFromSprite* subObjects, const int } - UserData userData = read_user_data(is, docFormatVer); + const UserData userData = read_user_data(is, serial); if (layer) { layer->setName(name); diff --git a/src/doc/layer_io.h b/src/doc/layer_io.h index 64a0699bf..edf2d7e3e 100644 --- a/src/doc/layer_io.h +++ b/src/doc/layer_io.h @@ -1,4 +1,5 @@ // Aseprite Document Library +// Copyright (c) 2024 Igara Studio S.A. // Copyright (c) 2001-2015 David Capello // // This file is released under the terms of the MIT license. @@ -8,8 +9,8 @@ #define DOC_LAYER_IO_H_INCLUDED #pragma once -#include "app/crash/doc_format.h" #include "base/exception.h" +#include "doc/serial_format.h" #include @@ -23,8 +24,11 @@ namespace doc { InvalidLayerType(const char* msg) throw() : base::Exception(msg) { } }; - void write_layer(std::ostream& os, const Layer* layer); - Layer* read_layer(std::istream& is, SubObjectsFromSprite* subObjects, const int docFormatVer = DOC_FORMAT_VERSION_LAST); + void write_layer(std::ostream& os, + const Layer* layer); + Layer* read_layer(std::istream& is, + SubObjectsFromSprite* subObjects, + SerialFormat serial = SerialFormat::LastVer); } // namespace doc diff --git a/src/doc/serial_format.h b/src/doc/serial_format.h new file mode 100644 index 000000000..192e62f88 --- /dev/null +++ b/src/doc/serial_format.h @@ -0,0 +1,27 @@ +// Aseprite +// Copyright (c) 2020-2024 Igara Studio S.A. +// +// This file is released under the terms of the MIT license. +// Read LICENSE.txt for more information. + +#ifndef DOC_SERIAL_FORMAT_H_INCLUDED +#define DOC_SERIAL_FORMAT_H_INCLUDED +#pragma once + +#include "base/ints.h" + +namespace doc { + +// Format version of raw document/sprite data when it's serialized in +// IO operations for undo/redo or in recovery data to allow backward +// compatibility with old session backups. +enum class SerialFormat : uint16_t { + Ver0 = 0, // Old version + Ver1 = 1, // New version with tilesets + Ver2 = 2, // Version 2 adds custom properties to user data + LastVer = Ver2 +}; + +} // namespace doc + +#endif diff --git a/src/doc/slice_io.cpp b/src/doc/slice_io.cpp index c86ac8bce..a4f3cd3fc 100644 --- a/src/doc/slice_io.cpp +++ b/src/doc/slice_io.cpp @@ -37,11 +37,13 @@ void write_slice(std::ostream& os, const Slice* slice) } } -Slice* read_slice(std::istream& is, const bool setId, const int docFormatVer) +Slice* read_slice(std::istream& is, + const bool setId, + const SerialFormat serial) { ObjectId id = read32(is); std::string name = read_string(is); - UserData userData = read_user_data(is, docFormatVer); + const UserData userData = read_user_data(is, serial); size_t nkeys = read32(is); std::unique_ptr slice(new Slice); diff --git a/src/doc/slice_io.h b/src/doc/slice_io.h index 14487e96a..50c0e2f25 100644 --- a/src/doc/slice_io.h +++ b/src/doc/slice_io.h @@ -1,4 +1,5 @@ // Aseprite Document Library +// Copyright (c) 2024 Igara Studio S.A. // Copyright (c) 2017 David Capello // // This file is released under the terms of the MIT license. @@ -8,7 +9,7 @@ #define DOC_SLICE_IO_H_INCLUDED #pragma once -#include "app/crash/doc_format.h" +#include "doc/serial_format.h" #include @@ -17,10 +18,14 @@ namespace doc { class Slice; class SliceKey; - void write_slice(std::ostream& os, const Slice* slice); - Slice* read_slice(std::istream& is, const bool setId = true, const int docFormatVer = DOC_FORMAT_VERSION_LAST); + void write_slice(std::ostream& os, + const Slice* slice); + Slice* read_slice(std::istream& is, + bool setId = true, + SerialFormat serial = SerialFormat::LastVer); - void write_slicekey(std::ostream& os, const SliceKey& sliceKey); + void write_slicekey(std::ostream& os, + const SliceKey& sliceKey); SliceKey read_slicekey(std::istream& is); } // namespace doc diff --git a/src/doc/tag_io.cpp b/src/doc/tag_io.cpp index 56fadb7b6..e04151f30 100644 --- a/src/doc/tag_io.cpp +++ b/src/doc/tag_io.cpp @@ -39,7 +39,7 @@ void write_tag(std::ostream& os, const Tag* tag) Tag* read_tag(std::istream& is, const bool setId, - const int docFormatVer) + const SerialFormat serial) { ObjectId id = read32(is); frame_t from = read32(is); @@ -47,7 +47,7 @@ Tag* read_tag(std::istream& is, // If we are reading a session from v1.2.x, there is a color field color_t color; - if (docFormatVer < DOC_FORMAT_VERSION_1) + if (serial < SerialFormat::Ver1) color = read32(is); AniDir aniDir = (AniDir)read8(is); @@ -56,15 +56,15 @@ Tag* read_tag(std::istream& is, // If we are reading the new v1.3.x version, there is a user data with the color + text int repeat = 0; - if (docFormatVer >= DOC_FORMAT_VERSION_1) { - userData = read_user_data(is, docFormatVer); + if (serial >= SerialFormat::Ver1) { + userData = read_user_data(is, serial); repeat = read32(is); } auto tag = std::make_unique(from, to); tag->setAniDir(aniDir); tag->setName(name); - if (docFormatVer < DOC_FORMAT_VERSION_1) + if (serial < SerialFormat::Ver1) tag->setColor(color); else { tag->setUserData(userData); diff --git a/src/doc/tag_io.h b/src/doc/tag_io.h index 887fb847b..e35950dae 100644 --- a/src/doc/tag_io.h +++ b/src/doc/tag_io.h @@ -1,5 +1,5 @@ // Aseprite Document Library -// Copyright (C) 2019-2020 Igara Studio S.A. +// Copyright (C) 2019-2024 Igara Studio S.A. // Copyright (C) 2001-2015 David Capello // // This file is released under the terms of the MIT license. @@ -9,7 +9,7 @@ #define DOC_TAG_IO_H_INCLUDED #pragma once -#include "app/crash/doc_format.h" +#include "doc/serial_format.h" #include @@ -17,10 +17,12 @@ namespace doc { class Tag; - void write_tag(std::ostream& os, const Tag* tag); + void write_tag(std::ostream& os, + const Tag* tag); + Tag* read_tag(std::istream& is, - const bool setId = true, - const int docFormatVer = DOC_FORMAT_VERSION_LAST); + bool setId = true, + SerialFormat serial = SerialFormat::LastVer); } // namespace doc diff --git a/src/doc/tileset_io.cpp b/src/doc/tileset_io.cpp index 0f5987267..4e4269a8d 100644 --- a/src/doc/tileset_io.cpp +++ b/src/doc/tileset_io.cpp @@ -57,13 +57,13 @@ bool write_tileset(std::ostream& os, Tileset* read_tileset(std::istream& is, Sprite* sprite, - bool setId, + const bool setId, uint32_t* tilesetVer, - const int docFormatVer) + const SerialFormat serial) { - ObjectId id = read32(is); - tileset_index ntiles = read32(is); - Grid grid = read_grid(is, setId); + const ObjectId id = read32(is); + const tileset_index ntiles = read32(is); + const Grid grid = read_grid(is); auto tileset = new Tileset(sprite, grid, ntiles); if (setId) tileset->setId(id); @@ -74,21 +74,21 @@ Tileset* read_tileset(std::istream& is, } // Read extra version byte after tiles - uint32_t ver = read8(is); + const uint32_t ver = read8(is); if (tilesetVer) *tilesetVer = ver; if (ver >= TILESET_VER1) { tileset->setBaseIndex(1); if (ver >= TILESET_VER2) { - UserData userData = read_user_data(is, docFormatVer); + const UserData userData = read_user_data(is, serial); tileset->setUserData(userData); if (ver >= TILESET_VER3) { tileset->setName(read_string(is)); for (tileset_index ti=0; tisetTileData(ti, read_user_data(is, docFormatVer)); + tileset->setTileData(ti, read_user_data(is, serial)); } } } diff --git a/src/doc/tileset_io.h b/src/doc/tileset_io.h index 7787363e0..936733e58 100644 --- a/src/doc/tileset_io.h +++ b/src/doc/tileset_io.h @@ -1,5 +1,5 @@ // Aseprite Document Library -// Copyright (C) 2019-2020 Igara Studio S.A. +// Copyright (C) 2019-2024 Igara Studio S.A. // // This file is released under the terms of the MIT license. // Read LICENSE.txt for more information. @@ -8,8 +8,8 @@ #define DOC_TILESET_IO_H_INCLUDED #pragma once -#include "app/crash/doc_format.h" #include "base/ints.h" +#include "doc/serial_format.h" #include @@ -38,7 +38,7 @@ namespace doc { Sprite* sprite, bool setId = true, uint32_t* tilesetVer = nullptr, - const int docFormatVer = DOC_FORMAT_VERSION_LAST); + SerialFormat serial = SerialFormat::LastVer); } // namespace doc diff --git a/src/doc/user_data_io.cpp b/src/doc/user_data_io.cpp index 575b71465..be5746e9e 100644 --- a/src/doc/user_data_io.cpp +++ b/src/doc/user_data_io.cpp @@ -259,7 +259,8 @@ static UserData::PropertiesMaps read_properties_maps(std::istream& is) return propertiesMaps; } -UserData read_user_data(std::istream& is, const int docFormatVer) +UserData read_user_data(std::istream& is, + const SerialFormat serial) { UserData userData; userData.setText(read_string(is)); @@ -273,7 +274,7 @@ UserData read_user_data(std::istream& is, const int docFormatVer) // When recovering a session from an old Aseprite version, we need // to skip reading the parts that it doesn't contains. Otherwise // it is very likely to fail. - if (docFormatVer >= DOC_FORMAT_VERSION_2) { + if (serial >= SerialFormat::Ver2) { userData.propertiesMaps() = read_properties_maps(is); } } diff --git a/src/doc/user_data_io.h b/src/doc/user_data_io.h index f5abcfd3f..9ab641250 100644 --- a/src/doc/user_data_io.h +++ b/src/doc/user_data_io.h @@ -1,4 +1,5 @@ // Aseprite Document Library +// Copyright (c) 2024 Igara Studio S.A. // Copyright (c) 2001-2015 David Capello // // This file is released under the terms of the MIT license. @@ -8,7 +9,7 @@ #define DOC_USER_DATA_IO_H_INCLUDED #pragma once -#include "app/crash/doc_format.h" +#include "doc/serial_format.h" #include @@ -16,8 +17,11 @@ namespace doc { class UserData; - void write_user_data(std::ostream& os, const UserData& userData); - UserData read_user_data(std::istream& is, const int docFormatVer = DOC_FORMAT_VERSION_LAST); + void write_user_data(std::ostream& os, + const UserData& userData); + + UserData read_user_data(std::istream& is, + SerialFormat serial = SerialFormat::LastVer); } // namespace doc