diff --git a/src/app/file/ase_format.cpp b/src/app/file/ase_format.cpp index 2e5b5e508..708fa8b27 100644 --- a/src/app/file/ase_format.cpp +++ b/src/app/file/ase_format.cpp @@ -1278,16 +1278,19 @@ static void ase_file_write_external_files_chunk( dio::AsepriteExternalFiles& ext_files, const Sprite* sprite) { - auto putExtentionIds = [](const UserData::PropertiesMaps& propertiesMaps, dio::AsepriteExternalFiles& ext_files) { + auto putExtentionIds = [](const UserData::PropertiesMaps& propertiesMaps, + dio::AsepriteExternalFiles& ext_files) { for (auto propertiesMap : propertiesMaps) { if (!propertiesMap.first.empty()) - ext_files.put(propertiesMap.first, ASE_EXTERNAL_FILE_EXTENSION); + ext_files.insert(ASE_EXTERNAL_FILE_EXTENSION, + propertiesMap.first); } }; for (const Tileset* tileset : *sprite->tilesets()) { if (!tileset->externalFilename().empty()) { - ext_files.put(tileset->externalFilename(), ASE_EXTERNAL_FILE_TILESET); + ext_files.insert(ASE_EXTERNAL_FILE_TILESET, + tileset->externalFilename()); } putExtentionIds(tileset->userData().propertiesMaps(), ext_files); @@ -1334,13 +1337,13 @@ static void ase_file_write_external_files_chunk( } // No external files to write - if (ext_files.lastid == 0) + if (ext_files.items().empty()) return; ChunkWriter chunk(f, frame_header, ASE_FILE_CHUNK_EXTERNAL_FILE); - fputl(ext_files.items.size(), f); // Number of entries + fputl(ext_files.items().size(), f); // Number of entries ase_file_write_padding(f, 8); - for (const auto& it : ext_files.items) { + for (const auto& it : ext_files.items()) { fputl(it.first, f); // ID fputc(it.second.type, f); // Type ase_file_write_padding(f, 7); @@ -1395,9 +1398,9 @@ static void ase_file_write_tileset_chunk(FILE* f, FileOp* fop, // Flag 1 = external tileset if (flags & ASE_TILESET_FLAG_EXTERNAL_FILE) { - auto it = ext_files.to_id.find(tileset->externalFilename()); - if (it != ext_files.to_id.end()) { - auto file_id = it->second; + uint32_t file_id = 0; + if (ext_files.getIDByFilename(ASE_EXTERNAL_FILE_TILESET, + tileset->externalFilename(), file_id)) { fputl(file_id, f); fputl(tileset->externalTileset(), f); } @@ -1532,7 +1535,8 @@ static void ase_file_write_properties_maps(FILE* f, FileOp* fop, const std::string& extensionKey = propertiesMap.first; uint32_t extensionId = 0; if (!extensionKey.empty() && - !ext_files.getIDByFilename(extensionKey, extensionId)) { + !ext_files.getIDByFilename(ASE_EXTERNAL_FILE_EXTENSION, + extensionKey, extensionId)) { // This shouldn't ever happen, but if it does... most likely // it is because we forgot to add the extensionID to the // ext_files object. And this could happen if someone adds the diff --git a/src/dio/aseprite_common.h b/src/dio/aseprite_common.h index 10ccdb1b9..c8d1847d4 100644 --- a/src/dio/aseprite_common.h +++ b/src/dio/aseprite_common.h @@ -66,6 +66,7 @@ #define ASE_EXTERNAL_FILE_PALETTE 0 #define ASE_EXTERNAL_FILE_TILESET 1 #define ASE_EXTERNAL_FILE_EXTENSION 2 +#define ASE_EXTERNAL_FILE_TYPES 3 namespace dio { @@ -105,44 +106,67 @@ struct AsepriteChunk { int start; }; -struct AsepriteExternalFiles { +class AsepriteExternalFiles { +public: struct Item { std::string fn; // filename uint8_t type; // type has one of the ASE_EXTERNAL_FILE_* values }; - std::map items; - std::map to_id; // filename -> ID - uint32_t lastid = 0; + using Items = std::map; + + const Items& items() const { + return m_items; + } // Adds the external filename with the next autogenerated ID and specified type. - void put(const std::string& filename, uint8_t type) { - put(++lastid, filename, type); + uint32_t insert(const uint8_t type, + const std::string& filename) { + auto it = m_toID[type].find(filename); + if (it != m_toID[type].end()) + return it->second; + else { + insert(++m_lastid, type, filename); + return m_lastid; + } } // Adds the external filename using the specified ID and type. - void put(uint32_t id, const std::string& filename, uint8_t type) { - items[id] = Item{ filename, type }; - to_id[filename] = id; + void insert(uint32_t id, + const uint8_t type, + const std::string& filename) { + ASSERT(type >= 0 && type < ASE_EXTERNAL_FILE_TYPES); + + m_items[id] = Item{ filename, type }; + m_toID[type][filename] = id; } // Returns true if the given filename exists in the external files // chunk, and assign its ID in "id" - bool getIDByFilename(const std::string& fn, uint32_t& id) const { - auto it = to_id.find(fn); - if (it == to_id.end()) + bool getIDByFilename(const uint8_t type, + const std::string& fn, + uint32_t& id) const { + ASSERT(type >= 0 && type < ASE_EXTERNAL_FILE_TYPES); + + auto it = m_toID[type].find(fn); + if (it == m_toID[type].end()) return false; id = it->second; return true; } bool getFilenameByID(uint32_t id, std::string& fn) const { - auto it = items.find(id); - if (it == items.end()) + auto it = m_items.find(id); + if (it == m_items.end()) return false; fn = it->second.fn; return true; } + +private: + uint32_t m_lastid = 0; // ID used to add new items + Items m_items; + std::map m_toID[ASE_EXTERNAL_FILE_TYPES]; }; } // namespace dio diff --git a/src/dio/aseprite_decoder.cpp b/src/dio/aseprite_decoder.cpp index aaeb8d5b2..7d27c15d2 100644 --- a/src/dio/aseprite_decoder.cpp +++ b/src/dio/aseprite_decoder.cpp @@ -1014,7 +1014,7 @@ void AsepriteDecoder::readExternalFiles(AsepriteExternalFiles& extFiles) uint8_t type = read8(); readPadding(7); std::string fn = readString(); - extFiles.put(id, fn, type); + extFiles.insert(id, type, fn); } }