Fix crash merging a tilemap layer into a regular layer

This commit is contained in:
David Capello 2019-11-05 13:31:53 -03:00
parent a6302b91f7
commit 4d69106993
6 changed files with 168 additions and 33 deletions

View File

@ -1,5 +1,5 @@
// Aseprite
// Copyright (C) 2020 Igara Studio S.A.
// Copyright (C) 2019-2020 Igara Studio S.A.
// Copyright (C) 2001-2018 David Capello
//
// This program is distributed under the terms of
@ -26,7 +26,7 @@
#include "doc/layer.h"
#include "doc/primitives.h"
#include "doc/sprite.h"
#include "render/render.h"
#include "render/rasterize.h"
#include "ui/ui.h"
namespace app {
@ -103,7 +103,8 @@ void MergeDownLayerCommand::onExecute(Context* context)
// Copy this cel to the destination layer...
// Creating a copy of the image
dst_image.reset(Image::createCopy(src_image));
dst_image.reset(
render::rasterize_with_cel_bounds(src_cel));
// Creating a copy of the cell
dst_cel = new Cel(frpos, dst_image);
@ -133,14 +134,10 @@ void MergeDownLayerCommand::onExecute(Context* context)
bounds.y-dst_cel->y(),
bounds.w, bounds.h, bgcolor));
// Merge src_image in new_image
render::composite_image(
new_image.get(), src_image,
sprite->palette(src_cel->frame()),
src_cel->x()-bounds.x,
src_cel->y()-bounds.y,
opacity,
src_layer->blendMode());
// Draw src_cel on new_image
render::rasterize(
new_image.get(), src_cel,
-bounds.x, -bounds.y, false);
// First unlink the dst_cel
if (dst_cel->links())

View File

@ -53,6 +53,7 @@
#include "doc/sprite.h"
#include "fmt/format.h"
#include "render/dithering.h"
#include "render/rasterize.h"
#include "render/render.h"
#include "ui/ui.h"
@ -430,26 +431,8 @@ public:
}
else {
Cel* cel = m_layer->cel(m_frame);
if (cel && (cel->x() != 0 || cel->y() != 0)) {
m_floodfillSrcImage = Image::create(m_sprite->spec());
m_floodfillSrcImage->clear(m_sprite->transparentColor());
if (cel->image()->pixelFormat() == IMAGE_TILEMAP) {
render::Render render;
render.setNewBlend(Preferences::instance().experimental.newBlend());
render.renderCel(
m_floodfillSrcImage,
m_sprite,
cel->image(),
m_layer,
m_sprite->palette(m_frame),
gfx::RectF(cel->bounds()),
gfx::Clip(m_sprite->bounds()),
255, BlendMode::NORMAL);
}
else {
copy_image(m_floodfillSrcImage, cel->image(), cel->x(), cel->y());
}
}
if (cel && (cel->x() != 0 || cel->y() != 0))
m_floodfillSrcImage = render::rasterize_with_sprite_bounds(cel);
}
}

View File

@ -1,5 +1,6 @@
# Aseprite Render Library
# Copyright (C) 2001-2017 David Capello
# Copyright (C) 2019 Igara Studio S.A.
# Copyright (C) 2001-2018 David Capello
add_library(render-lib
error_diffusion.cpp
@ -7,6 +8,7 @@ add_library(render-lib
gradient.cpp
ordered_dither.cpp
quantization.cpp
rasterize.cpp
render.cpp
zoom.cpp)

View File

@ -1,4 +1,5 @@
# Aseprite Render Library
*Copyright (C) 2001-2017 David Capello*
> Distributed under [MIT license](LICENSE.txt)
Functions to render a [`doc::Sprite`](../doc/sprite.h).

111
src/render/rasterize.cpp Normal file
View File

@ -0,0 +1,111 @@
// Aseprite Render Library
// Copyright (C) 2019 Igara Studio S.A.
//
// This file is released under the terms of the MIT license.
// Read LICENSE.txt for more information.
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "render/rasterize.h"
#include "base/debug.h"
#include "doc/blend_internals.h"
#include "doc/cel.h"
#include "doc/sprite.h"
#include "render/render.h"
namespace render {
void rasterize(
doc::Image* dst,
const doc::Cel* cel,
const int x,
const int y,
const bool clear)
{
ASSERT(cel);
const doc::Sprite* sprite = cel->sprite();
ASSERT(sprite);
if (clear)
dst->clear(sprite->transparentColor());
int t;
int opacity;
opacity = MUL_UN8(cel->opacity(), cel->layer()->opacity(), t);
if (cel->image()->pixelFormat() == IMAGE_TILEMAP) {
render::Render render;
render.renderCel(
dst,
sprite,
cel->image(),
cel->layer(),
sprite->palette(cel->frame()),
gfx::RectF(cel->bounds()),
gfx::Clip(x, y, 0, 0, dst->width(), dst->height()),
clear ? 255: opacity,
clear ? BlendMode::NORMAL: cel->layer()->blendMode());
}
else {
if (clear)
copy_image(dst, cel->image(), x+cel->x(), y+cel->y());
else
composite_image(
dst, cel->image(),
sprite->palette(cel->frame()),
x+cel->x(),
y+cel->y(),
opacity,
cel->layer()->blendMode());
}
}
void rasterize_with_cel_bounds(
doc::Image* dst,
const doc::Cel* cel)
{
rasterize(dst, cel, -cel->x(), -cel->y(), true);
}
void rasterize_with_sprite_bounds(
doc::Image* dst,
const doc::Cel* cel)
{
rasterize(dst, cel, 0, 0, true);
}
doc::Image* rasterize_with_cel_bounds(
const doc::Cel* cel)
{
ASSERT(cel);
const doc::Sprite* sprite = cel->sprite();
ASSERT(sprite);
doc::ImageSpec spec = sprite->spec();
spec.setWidth(cel->bounds().w);
spec.setHeight(cel->bounds().h);
std::unique_ptr<doc::Image> dst(doc::Image::create(spec));
rasterize_with_cel_bounds(dst.get(), cel);
return dst.release();
}
doc::Image* rasterize_with_sprite_bounds(
const doc::Cel* cel)
{
ASSERT(cel);
const doc::Sprite* sprite = cel->sprite();
ASSERT(sprite);
std::unique_ptr<doc::Image> dst(doc::Image::create(sprite->spec()));
rasterize_with_sprite_bounds(dst.get(), cel);
return dst.release();
}
} // namespace render

41
src/render/rasterize.h Normal file
View File

@ -0,0 +1,41 @@
// Aseprite Render Library
// Copyright (C) 2019 Igara Studio S.A.
//
// This file is released under the terms of the MIT license.
// Read LICENSE.txt for more information.
#ifndef RENDER_RASTERIZE_H_INCLUDED
#define RENDER_RASTERIZE_H_INCLUDED
#pragma once
namespace doc {
class Cel;
class Image;
}
namespace render {
void rasterize(
doc::Image* dst,
const doc::Cel* cel,
const int x,
const int y,
const bool clear);
void rasterize_with_cel_bounds(
doc::Image* dst,
const doc::Cel* cel);
void rasterize_with_sprite_bounds(
doc::Image* dst,
const doc::Cel* cel);
doc::Image* rasterize_with_cel_bounds(
const doc::Cel* cel);
doc::Image* rasterize_with_sprite_bounds(
const doc::Cel* cel);
} // namespace render
#endif