Fix ase format write/read for tags user data (backward compatible)

This commit is contained in:
Gaspar Capello 2020-08-20 14:46:22 -03:00 committed by David Capello
parent 55a37d0e6b
commit 1cd584413d
2 changed files with 31 additions and 8 deletions

View File

@ -382,15 +382,23 @@ bool AseFormat::onSave(FileOp* fop)
ase_file_write_tileset_chunks(f, fop, &frame_header, ext_files,
sprite->tilesets());
// Write layer chunks
for (Layer* child : sprite->root()->layers())
ase_file_write_layers(f, &frame_header, child, 0);
// Writer frame tags
if (sprite->tags().size() > 0)
if (sprite->tags().size() > 0) {
ase_file_write_tags_chunk(f, &frame_header, &sprite->tags(),
fop->roi().fromFrame(),
fop->roi().toFrame());
// Write user data for tags
for (doc::Tag* tag : sprite->tags()) {
ase_file_write_user_data_chunk(f, &frame_header, &(tag->userData()));
}
}
// Write layer chunks.
// In older versions layers were before tags, but now we put tags
// before layers so older version don't get confused by the new
// user data chunks for tags.
for (Layer* child : sprite->root()->layers())
ase_file_write_layers(f, &frame_header, child, 0);
// Write slice chunks
ase_file_write_slice_chunks(f, &frame_header,
@ -1106,8 +1114,6 @@ static void ase_file_write_tags_chunk(FILE* f,
fputc(0, f);
ase_file_write_string(f, tag->name());
if (!tag->userData().isEmpty())
ase_file_write_user_data_chunk(f, frame_header, &tag->userData());
}
}

View File

@ -21,6 +21,7 @@
#include "dio/file_interface.h"
#include "dio/pixel_io.h"
#include "doc/doc.h"
#include "doc/user_data.h"
#include "fixmath/fixmath.h"
#include "fmt/format.h"
#include "zlib.h"
@ -82,6 +83,9 @@ bool AsepriteDecoder::decode()
doc::Layer* last_layer = sprite->root();
doc::WithUserData* last_object_with_user_data = nullptr;
doc::Cel* last_cel = nullptr;
auto tag_it = sprite->tags().begin();
auto tag_end = sprite->tags().end();
bool tagsInProcess = false;
int current_level = -1;
doc::LayerList allLayers;
AsepriteExternalFiles extFiles;
@ -198,7 +202,10 @@ bool AsepriteDecoder::decode()
break;
case ASE_FILE_CHUNK_TAGS:
tagsInProcess = true;
readTagsChunk(&sprite->tags());
tag_it = sprite->tags().begin();
tag_end = sprite->tags().end();
break;
case ASE_FILE_CHUNK_SLICES: {
@ -216,7 +223,17 @@ bool AsepriteDecoder::decode()
case ASE_FILE_CHUNK_USER_DATA: {
doc::UserData userData;
readUserDataChunk(&userData);
if (last_object_with_user_data)
// The next condition implies user data is from tags
if (tagsInProcess) {
// Tag user data:
doc::Tag* tag = *tag_it;
tag->setUserData(userData);
tag_it++;
if (tag_it == tag_end)
tagsInProcess = false;
break;
}
else if (last_object_with_user_data)
last_object_with_user_data->setUserData(userData);
break;
}