Fix slices' user data serialization on .ase format

This commit is contained in:
David Capello 2017-04-12 08:57:02 -03:00
parent 2c0d0d3682
commit 02b225868d
2 changed files with 150 additions and 129 deletions

View File

@ -287,26 +287,23 @@ Insert this user data in the last read chunk. E.g. If we've read a
layer, this user data belongs to that layer, if we've read a cel, it layer, this user data belongs to that layer, if we've read a cel, it
belongs to that cel, etc. belongs to that cel, etc.
``` Field | Details |
DWORD Flags ----------- | -------------------------------- |
1 = Has text DWORD | Flags
2 = Has color | 1 - Has text
+ If flags have bit 1: | 2 - Has color
STRING Text If flags have bit 1 |
+ If flags have bit 2: STRING | Text
BYTE Color Red (0-255) If flags have bit 2 |
BYTE Color Green (0-255) BYTE | Color Red (0-255)
BYTE Color Blue (0-255) BYTE | Color Green (0-255)
BYTE Color Alpha (0-255) BYTE | Color Blue (0-255)
``` BYTE | Color Alpha (0-255)
### Slices Chunk (0x2021) ### Slice Chunk (0x2022)
Field | Details | Field | Details |
----------- | -------------------------------- | ----------- | -------------------------------- |
DWORD | Number of slices
BYTE[8] | Reserved
For each slice... |
DWORD | Number of "slice keys" DWORD | Number of "slice keys"
DWORD | Flags DWORD | Flags
| 1 - It's a 9-patches slice | 1 - It's a 9-patches slice

View File

@ -13,6 +13,7 @@
#include "app/file/file.h" #include "app/file/file.h"
#include "app/file/file_format.h" #include "app/file/file_format.h"
#include "app/file/format_options.h" #include "app/file/format_options.h"
#include "app/pref/preferences.h"
#include "base/cfile.h" #include "base/cfile.h"
#include "base/exception.h" #include "base/exception.h"
#include "base/file_handle.h" #include "base/file_handle.h"
@ -39,7 +40,8 @@
#define ASE_FILE_CHUNK_FRAME_TAGS 0x2018 #define ASE_FILE_CHUNK_FRAME_TAGS 0x2018
#define ASE_FILE_CHUNK_PALETTE 0x2019 #define ASE_FILE_CHUNK_PALETTE 0x2019
#define ASE_FILE_CHUNK_USER_DATA 0x2020 #define ASE_FILE_CHUNK_USER_DATA 0x2020
#define ASE_FILE_CHUNK_SLICES 0x2021 #define ASE_FILE_CHUNK_SLICES 0x2021 // Deprecated chunk (used on dev versions only between v1.2-beta7 and v1.2-beta8)
#define ASE_FILE_CHUNK_SLICE 0x2022
#define ASE_FILE_LAYER_IMAGE 0 #define ASE_FILE_LAYER_IMAGE 0
#define ASE_FILE_LAYER_GROUP 1 #define ASE_FILE_LAYER_GROUP 1
@ -143,8 +145,11 @@ static void ase_file_write_mask_chunk(FILE* f, ASE_FrameHeader* frame_header, Ma
static void ase_file_read_frame_tags_chunk(FILE* f, FrameTags* frameTags); static void ase_file_read_frame_tags_chunk(FILE* f, FrameTags* frameTags);
static void ase_file_write_frame_tags_chunk(FILE* f, ASE_FrameHeader* frame_header, const FrameTags* frameTags, static void ase_file_write_frame_tags_chunk(FILE* f, ASE_FrameHeader* frame_header, const FrameTags* frameTags,
const frame_t fromFrame, const frame_t toFrame); const frame_t fromFrame, const frame_t toFrame);
static void ase_file_read_slices_chunk(FILE* f, Slices* slices); static void ase_file_read_slices_chunk(FILE* f, Slices& slices);
static void ase_file_write_slices_chunk(FILE* f, ASE_FrameHeader* frame_header, const Slices* slices, static Slice* ase_file_read_slice_chunk(FILE* f, Slices& slices);
static void ase_file_write_slice_chunks(FILE* f, ASE_FrameHeader* frame_header, const Slices& slices,
const frame_t fromFrame, const frame_t toFrame);
static void ase_file_write_slice_chunk(FILE* f, ASE_FrameHeader* frame_header, Slice* slice,
const frame_t fromFrame, const frame_t toFrame); const frame_t fromFrame, const frame_t toFrame);
static void ase_file_read_user_data_chunk(FILE* f, UserData* userData); static void ase_file_read_user_data_chunk(FILE* f, UserData* userData);
static void ase_file_write_user_data_chunk(FILE* f, ASE_FrameHeader* frame_header, const UserData* userData); static void ase_file_write_user_data_chunk(FILE* f, ASE_FrameHeader* frame_header, const UserData* userData);
@ -332,9 +337,17 @@ bool AseFormat::onLoad(FileOp* fop)
ase_file_read_frame_tags_chunk(f, &sprite->frameTags()); ase_file_read_frame_tags_chunk(f, &sprite->frameTags());
break; break;
case ASE_FILE_CHUNK_SLICES: case ASE_FILE_CHUNK_SLICES: {
ase_file_read_slices_chunk(f, &sprite->slices()); ase_file_read_slices_chunk(f, sprite->slices());
break; break;
}
case ASE_FILE_CHUNK_SLICE: {
Slice* slice = ase_file_read_slice_chunk(f, sprite->slices());
if (slice)
last_object_with_user_data = slice;
break;
}
case ASE_FILE_CHUNK_USER_DATA: { case ASE_FILE_CHUNK_USER_DATA: {
UserData userData; UserData userData;
@ -468,9 +481,8 @@ bool AseFormat::onSave(FileOp* fop)
fop->roi().toFrame()); fop->roi().toFrame());
// Writer slice chunks // Writer slice chunks
if (sprite->slices().size() > 0) ase_file_write_slice_chunks(f, &frame_header,
ase_file_write_slices_chunk(f, &frame_header, sprite->slices(),
&sprite->slices(),
fop->roi().fromFrame(), fop->roi().fromFrame(),
fop->roi().toFrame()); fop->roi().toFrame());
} }
@ -1687,13 +1699,29 @@ static void ase_file_write_user_data_chunk(FILE* f, ASE_FrameHeader* frame_heade
} }
} }
static void ase_file_read_slices_chunk(FILE* f, Slices* slices) static void ase_file_read_slices_chunk(FILE* f, Slices& slices)
{ {
size_t nslices = fgetl(f); // Number of slices size_t nslices = fgetl(f); // Number of slices
fgetl(f); // 8 bytes reserved fgetl(f); // 8 bytes reserved
fgetl(f); fgetl(f);
for (size_t i=0; i<nslices; ++i) { for (size_t i=0; i<nslices; ++i) {
Slice* slice = ase_file_read_slice_chunk(f, slices);
// Set the user data
if (slice) {
// Default slice color
auto color = Preferences::instance().slices.defaultColor();
slice->userData().setColor(
doc::rgba(color.getRed(),
color.getGreen(),
color.getBlue(),
color.getAlpha()));
}
}
}
static Slice* ase_file_read_slice_chunk(FILE* f, Slices& slices)
{
size_t nkeys = fgetl(f); // Number of keys size_t nkeys = fgetl(f); // Number of keys
int flags = fgetl(f); // Flags int flags = fgetl(f); // Flags
fgetl(f); // 4 bytes reserved fgetl(f); // 4 bytes reserved
@ -1727,36 +1755,37 @@ static void ase_file_read_slices_chunk(FILE* f, Slices* slices)
slice->insert(frame, SliceKey(bounds, center, pivot)); slice->insert(frame, SliceKey(bounds, center, pivot));
} }
slices->add(slice); slices.add(slice);
slice.release(); return slice.release();
}
} }
static void ase_file_write_slices_chunk(FILE* f, ASE_FrameHeader* frame_header, static void ase_file_write_slice_chunks(FILE* f, ASE_FrameHeader* frame_header,
const Slices* slices, const Slices& slices,
const frame_t fromFrame, const frame_t fromFrame,
const frame_t toFrame) const frame_t toFrame)
{ {
ChunkWriter chunk(f, frame_header, ASE_FILE_CHUNK_SLICES); for (Slice* slice : slices) {
size_t nslices = 0;
for (Slice* slice : *slices) {
// Skip slices that are outside of the given ROI // Skip slices that are outside of the given ROI
if (slice->range(fromFrame, toFrame).empty()) if (slice->range(fromFrame, toFrame).empty())
continue; continue;
++nslices; ase_file_write_slice_chunk(f, frame_header, slice,
fromFrame, toFrame);
if (!slice->userData().isEmpty())
ase_file_write_user_data_chunk(f, frame_header, &slice->userData());
} }
}
fputl(nslices, f); static void ase_file_write_slice_chunk(FILE* f, ASE_FrameHeader* frame_header,
fputl(0, f); // 8 reserved bytes Slice* slice,
fputl(0, f); const frame_t fromFrame,
const frame_t toFrame)
{
ChunkWriter chunk(f, frame_header, ASE_FILE_CHUNK_SLICE);
for (Slice* slice : *slices) {
// Skip slices that are outside of the given ROI
auto range = slice->range(fromFrame, toFrame); auto range = slice->range(fromFrame, toFrame);
if (range.empty()) ASSERT(!range.empty());
continue;
int flags = 0; int flags = 0;
for (auto key : range) { for (auto key : range) {
@ -1811,11 +1840,6 @@ static void ase_file_write_slices_chunk(FILE* f, ASE_FrameHeader* frame_header,
} }
++frame; ++frame;
} }
--nslices;
}
ASSERT(nslices == 0);
} }
static bool ase_has_groups(LayerGroup* group) static bool ase_has_groups(LayerGroup* group)