No more pimpl idiom for Sprite class (because the biggest dependencies

are now part of Document class).
This commit is contained in:
David Capello 2011-03-24 13:06:40 -03:00
parent 82476db988
commit a2e0f32987
3 changed files with 204 additions and 460 deletions

View File

@ -389,25 +389,6 @@ SpriteImpl* SpriteImpl::copyBase(Sprite* new_sprite, const SpriteImpl* src_sprit
if (src_sprite->m_mask)
dst_sprite->m_mask = mask_new_copy(src_sprite->m_mask);
/* copy repositories */
{
PathsList::const_iterator end = src_sprite->m_repository.paths.end();
PathsList::const_iterator it = src_sprite->m_repository.paths.begin();
for (; it != end; ++it) {
Path* path_copy = new Path(*(*it));
dst_sprite->addPath(path_copy);
}
}
{
MasksList::const_iterator end = src_sprite->m_repository.masks.end();
MasksList::const_iterator it = src_sprite->m_repository.masks.begin();
for (; it != end; ++it) {
Mask* mask_copy = new Mask(*(*it));
dst_sprite->addMask(mask_copy);
}
}
return dst_sprite;
}

View File

@ -18,238 +18,23 @@
#include "config.h"
#include "raster/sprite.h"
#include "base/memory.h"
#include "base/remove_from_container.h"
#include "file/format_options.h"
#include "raster/raster.h"
#include <cstring>
#include <vector>
#ifdef _MSC_VER
#pragma warning(disable: 4355)
#endif
static Layer* index2layer(const Layer* layer, int index, int* index_count);
static int layer2index(const Layer* layer, const Layer* find_layer, int* index_count);
//////////////////////////////////////////////////////////////////////
// SpriteImpl
// Constructors/Destructor
class SpriteImpl
{
public:
SpriteImpl(Sprite* sprite, int imgtype, int width, int height, int ncolors);
~SpriteImpl();
int getImgType() const {
return m_imgtype;
}
void setImgType(int imgtype) {
m_imgtype = imgtype;
}
int getWidth() const {
return m_width;
}
int getHeight() const {
return m_height;
}
void setSize(int width, int height) {
ASSERT(width > 0);
ASSERT(height > 0);
m_width = width;
m_height = height;
}
bool needAlpha() const {
switch (m_imgtype) {
case IMAGE_RGB:
case IMAGE_GRAYSCALE:
return (getBackgroundLayer() == NULL);
}
return false;
}
ase_uint32 getTransparentColor() const {
return m_transparentColor;
}
void setTransparentColor(ase_uint32 color) {
m_transparentColor = color;
}
int getMemSize() const;
LayerFolder* getFolder() const {
return m_folder;
}
LayerImage* getBackgroundLayer() const;
Layer* getCurrentLayer() const {
return m_layer;
}
void setCurrentLayer(Layer* layer) {
m_layer = layer;
}
int countLayers() const {
return getFolder()->get_layers_count();
}
Layer* indexToLayer(int index) const {
int index_count = -1;
return index2layer(getFolder(), index, &index_count);
}
int layerToIndex(const Layer* layer) const {
int index_count = -1;
return layer2index(getFolder(), layer, &index_count);
}
Palette* getPalette(int frame) const;
PalettesList getPalettes() const {
return m_palettes;
}
void setPalette(Palette* pal, bool truncate);
void resetPalettes();
void deletePalette(Palette* pal);
Palette* getCurrentPalette() const {
return getPalette(getCurrentFrame());
}
RgbMap* getRgbMap(int frame) {
if (m_rgbMap == NULL) {
m_rgbMap = new RgbMap();
m_rgbMap->regenerate(getPalette(frame));
}
else if (!m_rgbMap->match(getPalette(frame))) {
m_rgbMap->regenerate(getPalette(frame));
}
return m_rgbMap;
}
int getTotalFrames() const {
return m_frames;
}
void setTotalFrames(int frames);
int getFrameDuration(int frame) const {
if (frame >= 0 && frame < m_frames)
return m_frlens[frame];
else
return 0;
}
void setFrameDuration(int frame, int msecs) {
if (frame >= 0 && frame < m_frames)
m_frlens[frame] = MID(1, msecs, 65535);
}
void setDurationForAllFrames(int msecs) {
std::fill(m_frlens.begin(), m_frlens.end(), MID(1, msecs, 65535));
}
int getCurrentFrame() const {
return m_frame;
}
void setCurrentFrame(int frame) {
m_frame = frame;
}
Stock* getStock() const {
return m_stock;
}
Image* getCurrentImage(int* x, int* y, int* opacity) const {
Image* image = NULL;
if (getCurrentLayer() != NULL &&
getCurrentLayer()->is_image()) {
const Cel* cel = static_cast<const LayerImage*>(getCurrentLayer())->getCel(getCurrentFrame());
if (cel) {
ASSERT((cel->image >= 0) &&
(cel->image < getStock()->size()));
image = getStock()->getImage(cel->image);
if (x) *x = cel->x;
if (y) *y = cel->y;
if (opacity) *opacity = MID(0, cel->opacity, 255);
}
}
return image;
}
void getCels(CelList& cels) {
getFolder()->getCels(cels);
}
void remapImages(int frame_from, int frame_to, const std::vector<int>& mapping) {
ASSERT(m_imgtype == IMAGE_INDEXED);
ASSERT(mapping.size() == 256);
CelList cels;
getCels(cels);
for (CelIterator it = cels.begin(); it != cels.end(); ++it) {
Cel* cel = *it;
// Remap this Cel because is inside the specified range
if (cel->frame >= frame_from &&
cel->frame <= frame_to) {
Image* image = getStock()->getImage(cel->image);
for (int y=0; y<image->h; ++y) {
IndexedTraits::address_t ptr = image_address_fast<IndexedTraits>(image, 0, y);
for (int x=0; x<image->w; ++x, ++ptr)
*ptr = mapping[*ptr];
}
}
}
}
void render(Image* image, int x, int y) const {
image_rectfill(image, x, y, x+m_width-1, y+m_height-1, 0);
layer_render(getFolder(), image, x, y, getCurrentFrame());
}
int getPixel(int x, int y) const;
private:
Sprite* m_self; // pointer to the Sprite
int m_imgtype; // image type
int m_width; // image width (in pixels)
int m_height; // image height (in pixels)
int m_frames; // how many frames has this sprite
std::vector<int> m_frlens; // duration per frame
int m_frame; // current frame, range [0,frames)
PalettesList m_palettes; // list of palettes
Stock* m_stock; // stock to get images
LayerFolder* m_folder; // main folder of layers
Layer* m_layer; // current layer
// Current rgb map
RgbMap* m_rgbMap;
// Transparent color used in indexed images
ase_uint32 m_transparentColor;
};
SpriteImpl::SpriteImpl(Sprite* sprite, int imgtype, int width, int height, int ncolors)
: m_self(sprite)
Sprite::Sprite(int imgtype, int width, int height, int ncolors)
: GfxObj(GFXOBJ_SPRITE)
, m_imgtype(imgtype)
, m_width(width)
, m_height(height)
@ -260,7 +45,7 @@ SpriteImpl::SpriteImpl(Sprite* sprite, int imgtype, int width, int height, int n
m_frlens.push_back(100); // First frame with 100 msecs of duration
m_frame = 0;
m_stock = new Stock(imgtype);
m_folder = new LayerFolder(m_self);
m_folder = new LayerFolder(this);
m_layer = NULL;
// Generate palette
@ -294,7 +79,7 @@ SpriteImpl::SpriteImpl(Sprite* sprite, int imgtype, int width, int height, int n
setPalette(&pal, true);
}
SpriteImpl::~SpriteImpl()
Sprite::~Sprite()
{
// Destroy layers
delete m_folder;
@ -315,7 +100,39 @@ SpriteImpl::~SpriteImpl()
delete m_rgbMap;
}
int SpriteImpl::getMemSize() const
//////////////////////////////////////////////////////////////////////
// Main properties
void Sprite::setImgType(int imgtype)
{
m_imgtype = imgtype;
}
void Sprite::setSize(int width, int height)
{
ASSERT(width > 0);
ASSERT(height > 0);
m_width = width;
m_height = height;
}
bool Sprite::needAlpha() const
{
switch (m_imgtype) {
case IMAGE_RGB:
case IMAGE_GRAYSCALE:
return (getBackgroundLayer() == NULL);
}
return false;
}
void Sprite::setTransparentColor(ase_uint32 color)
{
m_transparentColor = color;
}
int Sprite::getMemSize() const
{
Image *image;
int i, size = 0;
@ -329,7 +146,15 @@ int SpriteImpl::getMemSize() const
return size;
}
LayerImage* SpriteImpl::getBackgroundLayer() const
//////////////////////////////////////////////////////////////////////
// Layers
LayerFolder* Sprite::getFolder() const
{
return m_folder;
}
LayerImage* Sprite::getBackgroundLayer() const
{
if (getFolder()->get_layers_count() > 0) {
Layer* bglayer = *getFolder()->get_layer_begin();
@ -342,36 +167,37 @@ LayerImage* SpriteImpl::getBackgroundLayer() const
return NULL;
}
void SpriteImpl::setTotalFrames(int frames)
Layer* Sprite::getCurrentLayer() const
{
frames = MAX(1, frames);
m_frlens.resize(frames);
if (frames > m_frames) {
int c;
for (c=m_frames; c<frames; c++)
m_frlens[c] = m_frlens[m_frames-1];
}
m_frames = frames;
return m_layer;
}
int SpriteImpl::getPixel(int x, int y) const
void Sprite::setCurrentLayer(Layer* layer)
{
int color = 0;
if ((x >= 0) && (y >= 0) && (x < m_width) && (y < m_height)) {
Image* image = image_new(m_imgtype, 1, 1);
image_clear(image, 0);
this->render(image, -x, -y);
color = image_getpixel(image, 0, 0);
image_free(image);
}
return color;
m_layer = layer;
}
Palette* SpriteImpl::getPalette(int frame) const
int Sprite::countLayers() const
{
return getFolder()->get_layers_count();
}
Layer* Sprite::indexToLayer(int index) const
{
int index_count = -1;
return index2layer(getFolder(), index, &index_count);
}
int Sprite::layerToIndex(const Layer* layer) const
{
int index_count = -1;
return layer2index(getFolder(), layer, &index_count);
}
//////////////////////////////////////////////////////////////////////
// Palettes
Palette* Sprite::getPalette(int frame) const
{
ASSERT(frame >= 0);
@ -393,7 +219,12 @@ Palette* SpriteImpl::getPalette(int frame) const
return found;
}
void SpriteImpl::setPalette(Palette* pal, bool truncate)
PalettesList Sprite::getPalettes() const
{
return m_palettes;
}
void Sprite::setPalette(Palette* pal, bool truncate)
{
ASSERT(pal != NULL);
@ -421,7 +252,7 @@ void SpriteImpl::setPalette(Palette* pal, bool truncate)
}
}
void SpriteImpl::resetPalettes()
void Sprite::resetPalettes()
{
PalettesList::iterator end = m_palettes.end();
PalettesList::iterator it = m_palettes.begin();
@ -436,7 +267,7 @@ void SpriteImpl::resetPalettes()
}
}
void SpriteImpl::deletePalette(Palette* pal)
void Sprite::deletePalette(Palette* pal)
{
ASSERT(pal != NULL);
@ -444,208 +275,67 @@ void SpriteImpl::deletePalette(Palette* pal)
delete pal; // palette
}
//////////////////////////////////////////////////////////////////////
// Constructors/Destructor
Sprite::Sprite()
: GfxObj(GFXOBJ_SPRITE)
, m_impl(NULL)
{
}
Sprite::Sprite(int imgtype, int width, int height, int ncolors)
: GfxObj(GFXOBJ_SPRITE)
, m_impl(new SpriteImpl(this, imgtype, width, height, ncolors))
{
}
Sprite::~Sprite()
{
delete m_impl;
}
//////////////////////////////////////////////////////////////////////
// Main properties
int Sprite::getImgType() const
{
return m_impl->getImgType();
}
void Sprite::setImgType(int imgtype)
{
m_impl->setImgType(imgtype);
}
int Sprite::getWidth() const
{
return m_impl->getWidth();
}
int Sprite::getHeight() const
{
return m_impl->getHeight();
}
void Sprite::setSize(int width, int height)
{
m_impl->setSize(width, height);
}
/**
Returns true if the rendered images will contain alpha values less than 255.
@note Only RGB and Grayscale images without background needs alpha channel in the render.
*/
bool Sprite::needAlpha() const
{
return m_impl->needAlpha();
}
ase_uint32 Sprite::getTransparentColor() const
{
return m_impl->getTransparentColor();
}
void Sprite::setTransparentColor(ase_uint32 color)
{
m_impl->setTransparentColor(color);
}
int Sprite::getMemSize() const
{
return m_impl->getMemSize();
}
//////////////////////////////////////////////////////////////////////
// Layers
LayerFolder* Sprite::getFolder() const
{
return m_impl->getFolder();
}
LayerImage* Sprite::getBackgroundLayer() const
{
return m_impl->getBackgroundLayer();
}
Layer* Sprite::getCurrentLayer() const
{
return m_impl->getCurrentLayer();
}
/**
* Changes the current layer
*/
void Sprite::setCurrentLayer(Layer* layer)
{
m_impl->setCurrentLayer(layer);
}
int Sprite::countLayers() const
{
return m_impl->countLayers();
}
Layer* Sprite::indexToLayer(int index) const
{
return m_impl->indexToLayer(index);
}
int Sprite::layerToIndex(const Layer* layer) const
{
return m_impl->layerToIndex(layer);
}
//////////////////////////////////////////////////////////////////////
// Palettes
Palette* Sprite::getPalette(int frame) const
{
return m_impl->getPalette(frame);
}
PalettesList Sprite::getPalettes() const
{
return m_impl->getPalettes();
}
void Sprite::setPalette(Palette* pal, bool truncate)
{
m_impl->setPalette(pal, truncate);
}
/**
* Removes all palettes from the sprites except the first one.
*/
void Sprite::resetPalettes()
{
m_impl->resetPalettes();
}
void Sprite::deletePalette(Palette* pal)
{
m_impl->deletePalette(pal);
}
Palette* Sprite::getCurrentPalette() const
{
return m_impl->getCurrentPalette();
return getPalette(getCurrentFrame());
}
RgbMap* Sprite::getRgbMap()
{
return m_impl->getRgbMap(getCurrentFrame());
return getRgbMap(getCurrentFrame());
}
RgbMap* Sprite::getRgbMap(int frame)
{
return m_impl->getRgbMap(frame);
if (m_rgbMap == NULL) {
m_rgbMap = new RgbMap();
m_rgbMap->regenerate(getPalette(frame));
}
else if (!m_rgbMap->match(getPalette(frame))) {
m_rgbMap->regenerate(getPalette(frame));
}
return m_rgbMap;
}
//////////////////////////////////////////////////////////////////////
// Frames
int Sprite::getTotalFrames() const
{
return m_impl->getTotalFrames();
}
/**
* Changes the quantity of frames
*/
void Sprite::setTotalFrames(int frames)
{
m_impl->setTotalFrames(frames);
frames = MAX(1, frames);
m_frlens.resize(frames);
if (frames > m_frames) {
int c;
for (c=m_frames; c<frames; c++)
m_frlens[c] = m_frlens[m_frames-1];
}
m_frames = frames;
}
int Sprite::getFrameDuration(int frame) const
{
return m_impl->getFrameDuration(frame);
if (frame >= 0 && frame < m_frames)
return m_frlens[frame];
else
return 0;
}
void Sprite::setFrameDuration(int frame, int msecs)
{
m_impl->setFrameDuration(frame, msecs);
if (frame >= 0 && frame < m_frames)
m_frlens[frame] = MID(1, msecs, 65535);
}
/**
* Sets a constant frame-rate.
*/
void Sprite::setDurationForAllFrames(int msecs)
{
m_impl->setDurationForAllFrames(msecs);
}
int Sprite::getCurrentFrame() const
{
return m_impl->getCurrentFrame();
std::fill(m_frlens.begin(), m_frlens.end(), MID(1, msecs, 65535));
}
void Sprite::setCurrentFrame(int frame)
{
m_impl->setCurrentFrame(frame);
m_frame = frame;
}
//////////////////////////////////////////////////////////////////////
@ -653,22 +343,59 @@ void Sprite::setCurrentFrame(int frame)
Stock* Sprite::getStock() const
{
return m_impl->getStock();
return m_stock;
}
Image* Sprite::getCurrentImage(int* x, int* y, int* opacity) const
{
return m_impl->getCurrentImage(x, y, opacity);
Image* image = NULL;
if (getCurrentLayer() != NULL &&
getCurrentLayer()->is_image()) {
const Cel* cel = static_cast<const LayerImage*>(getCurrentLayer())->getCel(getCurrentFrame());
if (cel) {
ASSERT((cel->image >= 0) &&
(cel->image < getStock()->size()));
image = getStock()->getImage(cel->image);
if (x) *x = cel->x;
if (y) *y = cel->y;
if (opacity) *opacity = MID(0, cel->opacity, 255);
}
}
return image;
}
void Sprite::getCels(CelList& cels)
{
m_impl->getCels(cels);
getFolder()->getCels(cels);
}
void Sprite::remapImages(int frame_from, int frame_to, const std::vector<int>& mapping)
{
m_impl->remapImages(frame_from, frame_to, mapping);
ASSERT(m_imgtype == IMAGE_INDEXED);
ASSERT(mapping.size() == 256);
CelList cels;
getCels(cels);
for (CelIterator it = cels.begin(); it != cels.end(); ++it) {
Cel* cel = *it;
// Remap this Cel because is inside the specified range
if (cel->frame >= frame_from &&
cel->frame <= frame_to) {
Image* image = getStock()->getImage(cel->image);
for (int y=0; y<image->h; ++y) {
IndexedTraits::address_t ptr = image_address_fast<IndexedTraits>(image, 0, y);
for (int x=0; x<image->w; ++x, ++ptr)
*ptr = mapping[*ptr];
}
}
}
}
//////////////////////////////////////////////////////////////////////
@ -676,17 +403,23 @@ void Sprite::remapImages(int frame_from, int frame_to, const std::vector<int>& m
void Sprite::render(Image* image, int x, int y) const
{
m_impl->render(image, x, y);
image_rectfill(image, x, y, x+m_width-1, y+m_height-1, 0);
layer_render(getFolder(), image, x, y, getCurrentFrame());
}
/**
* Gets a pixel from the sprite in the specified position. If in the
* specified coordinates there're background this routine will return
* the 0 color (the mask-color).
*/
int Sprite::getPixel(int x, int y) const
{
return m_impl->getPixel(x, y);
int color = 0;
if ((x >= 0) && (y >= 0) && (x < m_width) && (y < m_height)) {
Image* image = image_new(m_imgtype, 1, 1);
image_clear(image, 0);
this->render(image, -x, -y);
color = image_getpixel(image, 0, 0);
image_free(image);
}
return color;
}
//////////////////////////////////////////////////////////////////////

View File

@ -21,6 +21,7 @@
#include "base/disable_copying.h"
#include "raster/gfxobj.h"
#include <vector>
class Image;
@ -35,8 +36,6 @@ class Sprite;
class RgbMap;
typedef std::vector<Palette*> PalettesList;
typedef std::vector<Mask*> MasksList;
typedef std::vector<Path*> PathsList;
// The main structure used in the whole program to handle a sprite.
class Sprite : public GfxObj
@ -52,16 +51,19 @@ public:
////////////////////////////////////////
// Main properties
int getImgType() const;
int getImgType() const { return m_imgtype; }
void setImgType(int imgtype);
int getWidth() const;
int getHeight() const;
int getWidth() const { return m_width; }
int getHeight() const { return m_height; }
void setSize(int width, int height);
// Returns true if the rendered images will contain alpha values less
// than 255. Only RGBA and Grayscale images without background needs
// alpha channel in the render.
bool needAlpha() const;
ase_uint32 getTransparentColor() const;
ase_uint32 getTransparentColor() const { return m_transparentColor; }
void setTransparentColor(ase_uint32 color);
int getMemSize() const;
@ -86,7 +88,10 @@ public:
PalettesList getPalettes() const;
void setPalette(Palette* pal, bool truncate);
// Removes all palettes from the sprites except the first one.
void resetPalettes();
void deletePalette(Palette* pal);
Palette* getCurrentPalette() const;
@ -97,14 +102,18 @@ public:
////////////////////////////////////////
// Frames
int getTotalFrames() const;
int getTotalFrames() const { return m_frames; }
// Changes the quantity of frames
void setTotalFrames(int frames);
int getFrameDuration(int frame) const;
void setFrameDuration(int frame, int msecs);
// Sets a constant frame-rate.
void setDurationForAllFrames(int msecs);
int getCurrentFrame() const;
int getCurrentFrame() const { return m_frame; }
void setCurrentFrame(int frame);
////////////////////////////////////////
@ -122,12 +131,33 @@ public:
// Drawing
void render(Image* image, int x, int y) const;
// Gets a pixel from the sprite in the specified position. If in the
// specified coordinates there're background this routine will
// return the 0 color (the mask-color).
int getPixel(int x, int y) const;
private:
Sprite();
class SpriteImpl* m_impl;
Sprite* m_self; // pointer to the Sprite
int m_imgtype; // image type
int m_width; // image width (in pixels)
int m_height; // image height (in pixels)
int m_frames; // how many frames has this sprite
std::vector<int> m_frlens; // duration per frame
int m_frame; // current frame, range [0,frames)
PalettesList m_palettes; // list of palettes
Stock* m_stock; // stock to get images
LayerFolder* m_folder; // main folder of layers
Layer* m_layer; // current layer
// Current rgb map
RgbMap* m_rgbMap;
// Transparent color used in indexed images
ase_uint32 m_transparentColor;
// Disable default constructor and copying
Sprite();
DISABLE_COPYING(Sprite);
};