Load/save precise cel bounds for reference layers in .ase file

This commit is contained in:
David Capello 2016-10-12 12:48:11 -03:00
parent b83eb89ce4
commit 2a5ed858dc
2 changed files with 72 additions and 1 deletions

View File

@ -19,6 +19,7 @@ BYTE An 8-bit unsigned integer value
WORD A 16-bit unsigned integer value
SIGNED WORD A 16-bit signed integer value
DWORD A 32-bit unsigned integer value
FIXED A 32-bit fixed point (16.16) value
BYTE[n] "n" bytes.
STRING length=WORD (how many characters to read next)
string=BYTE[length]
@ -156,6 +157,7 @@ Layer Chunk (0x2004)
8 = Background
16 = Prefer linked cels
32 = The layer group should be displayed collapsed
64 = The layer is a reference layer
WORD Layer type
0 = Normal (image) layer
1 = Group
@ -218,6 +220,20 @@ Cel Chunk (0x2005)
http://www.ietf.org/rfc/rfc1951.txt
Cel Extra Chunk (0x2006)
----------------------------------------
Adds extra information to the latest read cel.
DWORD Flags (set to zero)
1 - precise bounds are set
FIXED Precise X position
FIXED Precise Y position
FIXED Width of the cel in the sprite (scaled in real-time)
FIXED Height of the cel in the sprite
BYTE[16] For future use (set to zero)
Mask Chunk (0x2016) DEPRECATED
----------------------------------------

View File

@ -18,6 +18,7 @@
#include "base/file_handle.h"
#include "base/path.h"
#include "doc/doc.h"
#include "fixmath/fixmath.h"
#include "ui/alert.h"
#include "zlib.h"
@ -26,12 +27,13 @@
#define ASE_FILE_MAGIC 0xA5E0
#define ASE_FILE_FRAME_MAGIC 0xF1FA
#define ASE_FILE_FLAG_LAYER_WITH_OPACITY 1
#define ASE_FILE_FLAG_LAYER_WITH_OPACITY 1
#define ASE_FILE_CHUNK_FLI_COLOR2 4
#define ASE_FILE_CHUNK_FLI_COLOR 11
#define ASE_FILE_CHUNK_LAYER 0x2004
#define ASE_FILE_CHUNK_CEL 0x2005
#define ASE_FILE_CHUNK_CEL_EXTRA 0x2006
#define ASE_FILE_CHUNK_MASK 0x2016
#define ASE_FILE_CHUNK_PATH 0x2017
#define ASE_FILE_CHUNK_FRAME_TAGS 0x2018
@ -50,6 +52,8 @@
#define ASE_USER_DATA_FLAG_HAS_TEXT 1
#define ASE_USER_DATA_FLAG_HAS_COLOR 2
#define ASE_CEL_EXTRA_FLAG_PRECISE_BOUNDS 1
namespace app {
using namespace base;
@ -119,12 +123,15 @@ static void ase_file_write_palette_chunk(FILE* f, ASE_FrameHeader* frame_header,
static Layer* ase_file_read_layer_chunk(FILE* f, ASE_Header* header, Sprite* sprite, Layer** previous_layer, int* current_level);
static void ase_file_write_layer_chunk(FILE* f, ASE_FrameHeader* frame_header, const Layer* layer, int child_level);
static Cel* ase_file_read_cel_chunk(FILE* f, Sprite* sprite, LayerList& allLayers, frame_t frame, PixelFormat pixelFormat, FileOp* fop, ASE_Header* header, size_t chunk_end);
static void ase_file_read_cel_extra_chunk(FILE* f, Cel* cel);
static void ase_file_write_cel_chunk(FILE* f, ASE_FrameHeader* frame_header,
const Cel* cel,
const LayerImage* layer,
const layer_t layer_index,
const Sprite* sprite,
const frame_t firstFrame);
static void ase_file_write_cel_extra_chunk(FILE* f, ASE_FrameHeader* frame_header,
const Cel* cel);
static Mask* ase_file_read_mask_chunk(FILE* f);
#if 0
static void ase_file_write_mask_chunk(FILE* f, ASE_FrameHeader* frame_header, Mask* mask);
@ -214,6 +221,7 @@ bool AseFormat::onLoad(FileOp* fop)
// Prepare variables for layer chunks
Layer* last_layer = sprite->root();
WithUserData* last_object_with_user_data = nullptr;
Cel* last_cel = nullptr;
int current_level = -1;
LayerList allLayers;
@ -287,11 +295,18 @@ bool AseFormat::onLoad(FileOp* fop)
sprite->pixelFormat(), fop, &header,
chunk_pos+chunk_size);
if (cel) {
last_cel = cel;
last_object_with_user_data = cel->data();
}
break;
}
case ASE_FILE_CHUNK_CEL_EXTRA: {
if (last_cel)
ase_file_read_cel_extra_chunk(f, last_cel);
break;
}
case ASE_FILE_CHUNK_MASK: {
Mask* mask = ase_file_read_mask_chunk(f);
if (mask)
@ -635,6 +650,9 @@ static layer_t ase_file_write_cels(FILE* f, ASE_FrameHeader* frame_header,
static_cast<const LayerImage*>(layer),
layer_index, sprite, firstFrame);
if (layer->isReference())
ase_file_write_cel_extra_chunk(f, frame_header, cel);
if (!cel->link() &&
!cel->data()->userData().isEmpty()) {
ase_file_write_user_data_chunk(f, frame_header,
@ -1320,6 +1338,25 @@ static Cel* ase_file_read_cel_chunk(FILE* f,
return cel.release();
}
static void ase_file_read_cel_extra_chunk(FILE* f, Cel* cel)
{
// Read chunk data
int flags = fgetl(f);
if (flags & ASE_CEL_EXTRA_FLAG_PRECISE_BOUNDS) {
fixmath::fixed x = fgetl(f);
fixmath::fixed y = fgetl(f);
fixmath::fixed w = fgetl(f);
fixmath::fixed h = fgetl(f);
if (w && h) {
gfx::RectF bounds(fixmath::fixtof(x),
fixmath::fixtof(y),
fixmath::fixtof(w),
fixmath::fixtof(h));
cel->setBoundsF(bounds);
}
}
}
static void ase_file_write_cel_chunk(FILE* f, ASE_FrameHeader* frame_header,
const Cel* cel,
const LayerImage* layer,
@ -1426,6 +1463,24 @@ static void ase_file_write_cel_chunk(FILE* f, ASE_FrameHeader* frame_header,
}
}
static void ase_file_write_cel_extra_chunk(FILE* f,
ASE_FrameHeader* frame_header,
const Cel* cel)
{
ChunkWriter chunk(f, frame_header, ASE_FILE_CHUNK_CEL_EXTRA);
ASSERT(cel->layer()->isReference());
gfx::RectF bounds = cel->boundsF();
fputl(ASE_CEL_EXTRA_FLAG_PRECISE_BOUNDS, f);
fputl(fixmath::ftofix(bounds.x), f);
fputl(fixmath::ftofix(bounds.y), f);
fputl(fixmath::ftofix(bounds.w), f);
fputl(fixmath::ftofix(bounds.h), f);
ase_file_write_padding(f, 16);
}
static Mask* ase_file_read_mask_chunk(FILE* f)
{
int c, u, v, byte;