mirror of
https://github.com/aseprite/aseprite.git
synced 2025-03-01 10:13:22 +00:00
Fix several old issues with indexed images and transparent color
- If we use a RGB color in a background layer (indexed image), and the first palette entry (transparent color) matches that RGB color, we can use that entry, because this is the background (the transparent color isn't transparent at all in the background layer). - If we use the same RGB color in a transparent color, we've to avoid the transparent color, because the user want to paint with that specific solid color. - Palette::findBestfit() receives a mask_index now, so we can find what color best matches a specific RGB avoiding that specific mask color, or we can use -1 to use any color (e.g. for background layers). - Added app::ColorTarget() to simplify and fix color_utils::color_for_layer and app_get_color_to_clear_layer(), so now we can use the new findBestfit to return the transparent color for background layers (if a RGB color matches the transparent color RGB values). - Removed fixup_color_for_layer/background() functions in color_utils - Fix NewImageFromMask() to use the mask color to clear the image - Improve the Editor pen preview (cursor.cpp) to draw the bounds of the pen when it will paint with the transparent color.
This commit is contained in:
parent
5a45d1ec23
commit
a6d900fc2c
@ -377,12 +377,15 @@ void app_default_statusbar_message()
|
|||||||
|
|
||||||
int app_get_color_to_clear_layer(Layer* layer)
|
int app_get_color_to_clear_layer(Layer* layer)
|
||||||
{
|
{
|
||||||
/* all transparent layers are cleared with the mask color */
|
ASSERT(layer != NULL);
|
||||||
app::Color color = app::Color::fromMask();
|
|
||||||
|
|
||||||
/* the `Background' is erased with the `Background Color' */
|
app::Color color;
|
||||||
if (layer != NULL && layer->isBackground())
|
|
||||||
|
// The `Background' is erased with the `Background Color'
|
||||||
|
if (layer->isBackground())
|
||||||
color = ColorBar::instance()->getBgColor();
|
color = ColorBar::instance()->getBgColor();
|
||||||
|
else // All transparent layers are cleared with the mask color
|
||||||
|
color = app::Color::fromMask();
|
||||||
|
|
||||||
return color_utils::color_for_layer(color, layer);
|
return color_utils::color_for_layer(color, layer);
|
||||||
}
|
}
|
||||||
|
64
src/app/color_target.h
Normal file
64
src/app/color_target.h
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
/* Aseprite
|
||||||
|
* Copyright (C) 2001-2014 David Capello
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef APP_COLOR_TARGET_H_INCLUDED
|
||||||
|
#define APP_COLOR_TARGET_H_INCLUDED
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "raster/color.h"
|
||||||
|
#include "raster/layer.h"
|
||||||
|
#include "raster/pixel_format.h"
|
||||||
|
#include "raster/sprite.h"
|
||||||
|
|
||||||
|
namespace app {
|
||||||
|
|
||||||
|
// Represents the kind of surface where we'll use a color.
|
||||||
|
class ColorTarget {
|
||||||
|
public:
|
||||||
|
enum LayerType {
|
||||||
|
BackgroundLayer,
|
||||||
|
TransparentLayer
|
||||||
|
};
|
||||||
|
|
||||||
|
ColorTarget(LayerType layerType, raster::PixelFormat pixelFormat, raster::color_t maskColor) :
|
||||||
|
m_layerType(layerType),
|
||||||
|
m_pixelFormat(pixelFormat),
|
||||||
|
m_maskColor(maskColor) {
|
||||||
|
}
|
||||||
|
|
||||||
|
ColorTarget(raster::Layer* layer) :
|
||||||
|
m_layerType(layer->isBackground() ? BackgroundLayer: TransparentLayer),
|
||||||
|
m_pixelFormat(layer->getSprite()->getPixelFormat()),
|
||||||
|
m_maskColor(layer->getSprite()->getTransparentColor()) {
|
||||||
|
}
|
||||||
|
|
||||||
|
bool isBackground() const { return m_layerType == BackgroundLayer; }
|
||||||
|
bool isTransparent() const { return m_layerType == TransparentLayer; }
|
||||||
|
LayerType layerType() const { return m_layerType; }
|
||||||
|
raster::PixelFormat pixelFormat() const { return m_pixelFormat; }
|
||||||
|
raster::color_t maskColor() const { return m_maskColor; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
LayerType m_layerType;
|
||||||
|
raster::PixelFormat m_pixelFormat;
|
||||||
|
raster::color_t m_maskColor;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace app
|
||||||
|
|
||||||
|
#endif
|
@ -1,5 +1,5 @@
|
|||||||
/* Aseprite
|
/* Aseprite
|
||||||
* Copyright (C) 2001-2013 David Capello
|
* Copyright (C) 2001-2014 David Capello
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* This program is free software; you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
@ -180,44 +180,40 @@ raster::color_t color_utils::color_for_image(const app::Color& color, PixelForma
|
|||||||
|
|
||||||
raster::color_t color_utils::color_for_layer(const app::Color& color, Layer* layer)
|
raster::color_t color_utils::color_for_layer(const app::Color& color, Layer* layer)
|
||||||
{
|
{
|
||||||
raster::color_t pixel_color;
|
return color_for_target(color, ColorTarget(layer));
|
||||||
|
|
||||||
if (color.getType() == app::Color::MaskType) {
|
|
||||||
pixel_color = layer->getSprite()->getTransparentColor();
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
PixelFormat format = layer->getSprite()->getPixelFormat();
|
|
||||||
pixel_color = color_for_image(color, format);
|
|
||||||
}
|
|
||||||
|
|
||||||
return fixup_color_for_layer(layer, pixel_color);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
raster::color_t color_utils::fixup_color_for_layer(Layer *layer, raster::color_t color)
|
raster::color_t color_utils::color_for_target(const app::Color& color, const ColorTarget& colorTarget)
|
||||||
{
|
{
|
||||||
if (layer->isBackground())
|
if (color.getType() == app::Color::MaskType)
|
||||||
return fixup_color_for_background(layer->getSprite()->getPixelFormat(), color);
|
return colorTarget.maskColor();
|
||||||
else
|
|
||||||
return color;
|
|
||||||
}
|
|
||||||
|
|
||||||
raster::color_t color_utils::fixup_color_for_background(PixelFormat format, raster::color_t color)
|
raster::color_t c = -1;
|
||||||
{
|
|
||||||
switch (format) {
|
switch (colorTarget.pixelFormat()) {
|
||||||
case IMAGE_RGB:
|
case IMAGE_RGB:
|
||||||
if (rgba_geta(color) < 255) {
|
c = rgba(color.getRed(), color.getGreen(), color.getBlue(), 255);
|
||||||
return rgba(rgba_getr(color),
|
|
||||||
rgba_getg(color),
|
|
||||||
rgba_getb(color), 255);
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
case IMAGE_GRAYSCALE:
|
case IMAGE_GRAYSCALE:
|
||||||
if (graya_geta(color) < 255) {
|
c = graya(color.getGray(), 255);
|
||||||
return graya(graya_getv(color), 255);
|
break;
|
||||||
|
case IMAGE_INDEXED:
|
||||||
|
if (color.getType() == app::Color::IndexType) {
|
||||||
|
c = color.getIndex();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
c = get_current_palette()->findBestfit(
|
||||||
|
color.getRed(),
|
||||||
|
color.getGreen(),
|
||||||
|
color.getBlue(),
|
||||||
|
colorTarget.isTransparent() ?
|
||||||
|
colorTarget.maskColor(): // Don't return the mask color
|
||||||
|
-1); // Return any color, we are in a background layer.
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
return color;
|
|
||||||
|
return c;
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace app
|
} // namespace app
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/* Aseprite
|
/* Aseprite
|
||||||
* Copyright (C) 2001-2013 David Capello
|
* Copyright (C) 2001-2014 David Capello
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* This program is free software; you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
@ -21,6 +21,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "app/color.h"
|
#include "app/color.h"
|
||||||
|
#include "app/color_target.h"
|
||||||
#include "raster/color.h"
|
#include "raster/color.h"
|
||||||
#include "raster/pixel_format.h"
|
#include "raster/pixel_format.h"
|
||||||
#include "ui/color.h"
|
#include "ui/color.h"
|
||||||
@ -39,9 +40,7 @@ namespace app {
|
|||||||
int color_for_allegro(const app::Color& color, int depth);
|
int color_for_allegro(const app::Color& color, int depth);
|
||||||
raster::color_t color_for_image(const app::Color& color, raster::PixelFormat format);
|
raster::color_t color_for_image(const app::Color& color, raster::PixelFormat format);
|
||||||
raster::color_t color_for_layer(const app::Color& color, raster::Layer* layer);
|
raster::color_t color_for_layer(const app::Color& color, raster::Layer* layer);
|
||||||
|
raster::color_t color_for_target(const app::Color& color, const ColorTarget& colorTarget);
|
||||||
raster::color_t fixup_color_for_layer(raster::Layer* layer, raster::color_t color);
|
|
||||||
raster::color_t fixup_color_for_background(raster::PixelFormat format, raster::color_t color);
|
|
||||||
|
|
||||||
} // namespace color_utils
|
} // namespace color_utils
|
||||||
} // namespace app
|
} // namespace app
|
||||||
|
@ -68,16 +68,22 @@ void BackgroundFromLayerCommand::onExecute(Context* context)
|
|||||||
Document* document(writer.document());
|
Document* document(writer.document());
|
||||||
Sprite* sprite(writer.sprite());
|
Sprite* sprite(writer.sprite());
|
||||||
|
|
||||||
// each frame of the layer to be converted as `Background' must be
|
raster::color_t bgcolor =
|
||||||
// cleared using the selected background color in the color-bar
|
color_utils::color_for_target(
|
||||||
int bgcolor = color_utils::color_for_image(context->getSettings()->getBgColor(), sprite->getPixelFormat());
|
context->getSettings()->getBgColor(),
|
||||||
bgcolor = color_utils::fixup_color_for_background(sprite->getPixelFormat(), bgcolor);
|
ColorTarget(
|
||||||
|
ColorTarget::BackgroundLayer,
|
||||||
|
sprite->getPixelFormat(),
|
||||||
|
sprite->getTransparentColor()));
|
||||||
|
|
||||||
{
|
{
|
||||||
UndoTransaction undo_transaction(writer.context(), "Background from Layer");
|
UndoTransaction undo_transaction(writer.context(), "Background from Layer");
|
||||||
document->getApi().backgroundFromLayer(static_cast<LayerImage*>(writer.layer()), bgcolor);
|
document->getApi().backgroundFromLayer(
|
||||||
|
static_cast<LayerImage*>(writer.layer()),
|
||||||
|
bgcolor);
|
||||||
undo_transaction.commit();
|
undo_transaction.commit();
|
||||||
}
|
}
|
||||||
|
|
||||||
update_screen_for_document(document);
|
update_screen_for_document(document);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -212,8 +212,12 @@ void CanvasSizeCommand::onExecute(Context* context)
|
|||||||
Sprite* sprite = writer.sprite();
|
Sprite* sprite = writer.sprite();
|
||||||
UndoTransaction undoTransaction(writer.context(), "Canvas Size");
|
UndoTransaction undoTransaction(writer.context(), "Canvas Size");
|
||||||
DocumentApi api = document->getApi();
|
DocumentApi api = document->getApi();
|
||||||
int bgcolor = color_utils::color_for_image(context->getSettings()->getBgColor(), sprite->getPixelFormat());
|
raster::color_t bgcolor = color_utils::color_for_target(
|
||||||
bgcolor = color_utils::fixup_color_for_background(sprite->getPixelFormat(), bgcolor);
|
context->getSettings()->getBgColor(),
|
||||||
|
ColorTarget(
|
||||||
|
ColorTarget::BackgroundLayer,
|
||||||
|
sprite->getPixelFormat(),
|
||||||
|
sprite->getTransparentColor()));
|
||||||
|
|
||||||
api.cropSprite(sprite, gfx::Rect(x1, y1, x2-x1, y2-y1), bgcolor);
|
api.cropSprite(sprite, gfx::Rect(x1, y1, x2-x1, y2-y1), bgcolor);
|
||||||
undoTransaction.commit();
|
undoTransaction.commit();
|
||||||
|
@ -104,7 +104,7 @@ void FlipCommand::onExecute(Context* context)
|
|||||||
|
|
||||||
// If the mask isn't a rectangular area, we've to flip the mask too.
|
// If the mask isn't a rectangular area, we've to flip the mask too.
|
||||||
if (mask->getBitmap() != NULL && !mask->isRectangular()) {
|
if (mask->getBitmap() != NULL && !mask->isRectangular()) {
|
||||||
int bgcolor = app_get_color_to_clear_layer(writer.layer());
|
raster::color_t bgcolor = app_get_color_to_clear_layer(writer.layer());
|
||||||
|
|
||||||
// Flip the portion of image specified by the mask.
|
// Flip the portion of image specified by the mask.
|
||||||
mask->offsetOrigin(-x, -y);
|
mask->offsetOrigin(-x, -y);
|
||||||
|
@ -132,7 +132,7 @@ void MergeDownLayerCommand::onExecute(Context* context)
|
|||||||
}
|
}
|
||||||
// With destination
|
// With destination
|
||||||
else {
|
else {
|
||||||
int x1, y1, x2, y2, bgcolor;
|
int x1, y1, x2, y2;
|
||||||
Image *new_image;
|
Image *new_image;
|
||||||
|
|
||||||
// Merge down in the background layer
|
// Merge down in the background layer
|
||||||
@ -141,7 +141,6 @@ void MergeDownLayerCommand::onExecute(Context* context)
|
|||||||
y1 = 0;
|
y1 = 0;
|
||||||
x2 = sprite->getWidth();
|
x2 = sprite->getWidth();
|
||||||
y2 = sprite->getHeight();
|
y2 = sprite->getHeight();
|
||||||
bgcolor = app_get_color_to_clear_layer(dst_layer);
|
|
||||||
}
|
}
|
||||||
// Merge down in a transparent layer
|
// Merge down in a transparent layer
|
||||||
else {
|
else {
|
||||||
@ -149,9 +148,10 @@ void MergeDownLayerCommand::onExecute(Context* context)
|
|||||||
y1 = MIN(src_cel->getY(), dst_cel->getY());
|
y1 = MIN(src_cel->getY(), dst_cel->getY());
|
||||||
x2 = MAX(src_cel->getX()+src_image->getWidth()-1, dst_cel->getX()+dst_image->getWidth()-1);
|
x2 = MAX(src_cel->getX()+src_image->getWidth()-1, dst_cel->getX()+dst_image->getWidth()-1);
|
||||||
y2 = MAX(src_cel->getY()+src_image->getHeight()-1, dst_cel->getY()+dst_image->getHeight()-1);
|
y2 = MAX(src_cel->getY()+src_image->getHeight()-1, dst_cel->getY()+dst_image->getHeight()-1);
|
||||||
bgcolor = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
raster::color_t bgcolor = app_get_color_to_clear_layer(dst_layer);
|
||||||
|
|
||||||
new_image = raster::crop_image(dst_image,
|
new_image = raster::crop_image(dst_image,
|
||||||
x1-dst_cel->getX(),
|
x1-dst_cel->getX(),
|
||||||
y1-dst_cel->getY(),
|
y1-dst_cel->getY(),
|
||||||
|
@ -191,7 +191,11 @@ void NewFileCommand::onExecute(Context* context)
|
|||||||
|
|
||||||
Image* image = sprite->getStock()->getImage(layerImage->getCel(FrameNumber(0))->getImage());
|
Image* image = sprite->getStock()->getImage(layerImage->getCel(FrameNumber(0))->getImage());
|
||||||
raster::clear_image(image,
|
raster::clear_image(image,
|
||||||
color_utils::color_for_image(color, format, -1));
|
color_utils::color_for_target(color,
|
||||||
|
ColorTarget(
|
||||||
|
ColorTarget::BackgroundLayer,
|
||||||
|
sprite->getPixelFormat(),
|
||||||
|
sprite->getTransparentColor())));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -295,8 +295,6 @@ void Document::prepareExtraCel(int x, int y, int w, int h, int opacity)
|
|||||||
m_extraImage->getHeight() != h) {
|
m_extraImage->getHeight() != h) {
|
||||||
delete m_extraImage; // image
|
delete m_extraImage; // image
|
||||||
m_extraImage = Image::create(getSprite()->getPixelFormat(), w, h);
|
m_extraImage = Image::create(getSprite()->getPixelFormat(), w, h);
|
||||||
m_extraImage->setMaskColor(0);
|
|
||||||
clear_image(m_extraImage, m_extraImage->getMaskColor());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -263,15 +263,20 @@ void Editor::editor_draw_cursor(int x, int y, bool refresh)
|
|||||||
->getSettings()
|
->getSettings()
|
||||||
->getCurrentTool();
|
->getCurrentTool();
|
||||||
|
|
||||||
// Setup the cursor type depending the current tool
|
// Setup the cursor type depending of several factors (current tool,
|
||||||
|
// foreground color, and layer transparency).
|
||||||
|
color_t pen_color = get_pen_color(m_sprite, m_layer);
|
||||||
|
color_t mask_color = m_sprite->getTransparentColor();
|
||||||
|
|
||||||
if (current_tool->getInk(0)->isSelection()) {
|
if (current_tool->getInk(0)->isSelection()) {
|
||||||
cursor_type = CURSOR_CROSS_ONE;
|
cursor_type = CURSOR_CROSS_ONE;
|
||||||
}
|
}
|
||||||
else if (// Use cursor bounds for inks that are effects (eraser, blur, etc.)
|
else if (
|
||||||
current_tool->getInk(0)->isEffect() ||
|
// Use cursor bounds for inks that are effects (eraser, blur, etc.)
|
||||||
// or when the FG color is mask and we are not in the background layer
|
(current_tool->getInk(0)->isEffect()) ||
|
||||||
(UIContext::instance()->getSettings()->getFgColor().getType() == app::Color::MaskType &&
|
// or when the pen color is transparent and we are not in the background layer
|
||||||
(m_layer != NULL && !m_layer->isBackground()))) {
|
(m_layer && !m_layer->isBackground() &&
|
||||||
|
pen_color == mask_color)) {
|
||||||
cursor_type = CURSOR_BOUNDS;
|
cursor_type = CURSOR_BOUNDS;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@ -288,8 +293,6 @@ void Editor::editor_draw_cursor(int x, int y, bool refresh)
|
|||||||
->getSettings()
|
->getSettings()
|
||||||
->getToolSettings(current_tool);
|
->getToolSettings(current_tool);
|
||||||
|
|
||||||
color_t pen_color = get_pen_color(m_sprite, m_layer);
|
|
||||||
uint32_t new_mask_color;
|
|
||||||
Pen* pen = editor_get_current_pen();
|
Pen* pen = editor_get_current_pen();
|
||||||
gfx::Rect penBounds = pen->getBounds();
|
gfx::Rect penBounds = pen->getBounds();
|
||||||
|
|
||||||
@ -300,18 +303,11 @@ void Editor::editor_draw_cursor(int x, int y, bool refresh)
|
|||||||
|
|
||||||
// In 'indexed' images, if the current color is 0, we have to use
|
// In 'indexed' images, if the current color is 0, we have to use
|
||||||
// a different mask color (different from 0) to draw the extra layer
|
// a different mask color (different from 0) to draw the extra layer
|
||||||
if (m_sprite->getPixelFormat() == IMAGE_INDEXED && pen_color == 0) {
|
if (pen_color == mask_color)
|
||||||
new_mask_color = 1;
|
mask_color = (mask_color == 0 ? 1: 0);
|
||||||
}
|
|
||||||
else {
|
|
||||||
new_mask_color = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
Image* extraImage = m_document->getExtraCelImage();
|
Image* extraImage = m_document->getExtraCelImage();
|
||||||
if (extraImage->getMaskColor() != new_mask_color) {
|
extraImage->setMaskColor(mask_color);
|
||||||
extraImage->setMaskColor(new_mask_color);
|
|
||||||
clear_image(extraImage, new_mask_color);
|
|
||||||
}
|
|
||||||
put_pen(extraImage, pen, -penBounds.x, -penBounds.y,
|
put_pen(extraImage, pen, -penBounds.x, -penBounds.y,
|
||||||
pen_color, extraImage->getMaskColor());
|
pen_color, extraImage->getMaskColor());
|
||||||
|
|
||||||
@ -324,7 +320,7 @@ void Editor::editor_draw_cursor(int x, int y, bool refresh)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* save area and draw the cursor */
|
// Save area and draw the cursor
|
||||||
if (refresh) {
|
if (refresh) {
|
||||||
acquire_bitmap(ji_screen);
|
acquire_bitmap(ji_screen);
|
||||||
ji_screen->clip = false;
|
ji_screen->clip = false;
|
||||||
@ -337,7 +333,7 @@ void Editor::editor_draw_cursor(int x, int y, bool refresh)
|
|||||||
// cursor thickness
|
// cursor thickness
|
||||||
m_cursor_thick = 1; // get_thickness_for_cursor();
|
m_cursor_thick = 1; // get_thickness_for_cursor();
|
||||||
|
|
||||||
/* cursor in the editor (model) */
|
// cursor in the editor (model)
|
||||||
m_cursor_editor_x = x;
|
m_cursor_editor_x = x;
|
||||||
m_cursor_editor_y = y;
|
m_cursor_editor_y = y;
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/* Aseprite
|
/* Aseprite
|
||||||
* Copyright (C) 2001-2013 David Capello
|
* Copyright (C) 2001-2014 David Capello
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* This program is free software; you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
@ -61,6 +61,7 @@ PixelsMovement::PixelsMovement(Context* context,
|
|||||||
, m_adjustPivot(false)
|
, m_adjustPivot(false)
|
||||||
, m_handle(NoHandle)
|
, m_handle(NoHandle)
|
||||||
, m_originalImage(Image::createCopy(moveThis))
|
, m_originalImage(Image::createCopy(moveThis))
|
||||||
|
, m_maskColor(m_sprite->getTransparentColor())
|
||||||
{
|
{
|
||||||
m_initialData = gfx::Transformation(gfx::Rect(initialX, initialY, moveThis->getWidth(), moveThis->getHeight()));
|
m_initialData = gfx::Transformation(gfx::Rect(initialX, initialY, moveThis->getWidth(), moveThis->getHeight()));
|
||||||
m_currentData = m_initialData;
|
m_currentData = m_initialData;
|
||||||
@ -68,9 +69,7 @@ PixelsMovement::PixelsMovement(Context* context,
|
|||||||
ContextWriter writer(m_reader);
|
ContextWriter writer(m_reader);
|
||||||
m_document->prepareExtraCel(0, 0, m_sprite->getWidth(), m_sprite->getHeight(), opacity);
|
m_document->prepareExtraCel(0, 0, m_sprite->getWidth(), m_sprite->getHeight(), opacity);
|
||||||
|
|
||||||
Image* extraImage = m_document->getExtraCelImage();
|
redrawExtraImage();
|
||||||
clear_image(extraImage, extraImage->getMaskColor());
|
|
||||||
copy_image(extraImage, moveThis, initialX, initialY);
|
|
||||||
|
|
||||||
m_initialMask = new Mask(*m_document->getMask());
|
m_initialMask = new Mask(*m_document->getMask());
|
||||||
m_currentMask = new Mask(*m_document->getMask());
|
m_currentMask = new Mask(*m_document->getMask());
|
||||||
@ -438,8 +437,8 @@ Image* PixelsMovement::getDraggedImageCopy(gfx::Point& origin)
|
|||||||
int width = rightBottom.x - leftTop.x;
|
int width = rightBottom.x - leftTop.x;
|
||||||
int height = rightBottom.y - leftTop.y;
|
int height = rightBottom.y - leftTop.y;
|
||||||
base::UniquePtr<Image> image(Image::create(m_sprite->getPixelFormat(), width, height));
|
base::UniquePtr<Image> image(Image::create(m_sprite->getPixelFormat(), width, height));
|
||||||
clear_image(image, image->getMaskColor());
|
|
||||||
drawParallelogram(image, m_originalImage, corners, leftTop);
|
drawImage(image, leftTop);
|
||||||
|
|
||||||
origin = leftTop;
|
origin = leftTop;
|
||||||
|
|
||||||
@ -567,28 +566,21 @@ gfx::Size PixelsMovement::getInitialImageSize() const
|
|||||||
return m_initialData.bounds().getSize();
|
return m_initialData.bounds().getSize();
|
||||||
}
|
}
|
||||||
|
|
||||||
void PixelsMovement::setMaskColor(uint32_t mask_color)
|
void PixelsMovement::setMaskColor(color_t mask_color)
|
||||||
{
|
{
|
||||||
ContextWriter writer(m_reader);
|
ContextWriter writer(m_reader);
|
||||||
Image* extraImage = m_document->getExtraCelImage();
|
|
||||||
|
|
||||||
ASSERT(extraImage != NULL);
|
m_maskColor = mask_color;
|
||||||
|
|
||||||
extraImage->setMaskColor(mask_color);
|
|
||||||
redrawExtraImage();
|
redrawExtraImage();
|
||||||
update_screen_for_document(m_document);
|
update_screen_for_document(m_document);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void PixelsMovement::redrawExtraImage()
|
void PixelsMovement::redrawExtraImage()
|
||||||
{
|
{
|
||||||
gfx::Transformation::Corners corners;
|
// Draw the transformed pixels in the extra-cel which is the chunk
|
||||||
m_currentData.transformBox(corners);
|
// of pixels that the user is moving.
|
||||||
|
drawImage(m_document->getExtraCelImage(), gfx::Point(0, 0));
|
||||||
// Transform the extra-cel which is the chunk of pixels that the user is moving.
|
|
||||||
Image* extraImage = m_document->getExtraCelImage();
|
|
||||||
clear_image(extraImage, extraImage->getMaskColor());
|
|
||||||
drawParallelogram(extraImage, m_originalImage, corners, gfx::Point(0, 0));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void PixelsMovement::redrawCurrentMask()
|
void PixelsMovement::redrawCurrentMask()
|
||||||
@ -607,6 +599,18 @@ void PixelsMovement::redrawCurrentMask()
|
|||||||
m_currentMask->unfreeze();
|
m_currentMask->unfreeze();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void PixelsMovement::drawImage(raster::Image* dst, const gfx::Point& pt)
|
||||||
|
{
|
||||||
|
gfx::Transformation::Corners corners;
|
||||||
|
m_currentData.transformBox(corners);
|
||||||
|
|
||||||
|
dst->setMaskColor(m_sprite->getTransparentColor());
|
||||||
|
clear_image(dst, dst->getMaskColor());
|
||||||
|
|
||||||
|
m_originalImage->setMaskColor(m_maskColor);
|
||||||
|
drawParallelogram(dst, m_originalImage, corners, pt);
|
||||||
|
}
|
||||||
|
|
||||||
void PixelsMovement::drawParallelogram(raster::Image* dst, raster::Image* src,
|
void PixelsMovement::drawParallelogram(raster::Image* dst, raster::Image* src,
|
||||||
const gfx::Transformation::Corners& corners,
|
const gfx::Transformation::Corners& corners,
|
||||||
const gfx::Point& leftTop)
|
const gfx::Point& leftTop)
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/* Aseprite
|
/* Aseprite
|
||||||
* Copyright (C) 2001-2013 David Capello
|
* Copyright (C) 2001-2014 David Capello
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* This program is free software; you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
@ -88,7 +88,7 @@ namespace app {
|
|||||||
gfx::Rect getImageBounds();
|
gfx::Rect getImageBounds();
|
||||||
gfx::Size getInitialImageSize() const;
|
gfx::Size getInitialImageSize() const;
|
||||||
|
|
||||||
void setMaskColor(uint32_t mask_color);
|
void setMaskColor(color_t mask_color);
|
||||||
|
|
||||||
// Flips the image and mask in the given direction in "flipType".
|
// Flips the image and mask in the given direction in "flipType".
|
||||||
// Flip Horizontally/Vertically commands are replaced calling this
|
// Flip Horizontally/Vertically commands are replaced calling this
|
||||||
@ -104,6 +104,7 @@ namespace app {
|
|||||||
private:
|
private:
|
||||||
void redrawExtraImage();
|
void redrawExtraImage();
|
||||||
void redrawCurrentMask();
|
void redrawCurrentMask();
|
||||||
|
void drawImage(raster::Image* dst, const gfx::Point& pt);
|
||||||
void drawParallelogram(raster::Image* dst, raster::Image* src,
|
void drawParallelogram(raster::Image* dst, raster::Image* src,
|
||||||
const gfx::Transformation::Corners& corners,
|
const gfx::Transformation::Corners& corners,
|
||||||
const gfx::Point& leftTop);
|
const gfx::Point& leftTop);
|
||||||
@ -124,6 +125,7 @@ namespace app {
|
|||||||
gfx::Transformation m_currentData;
|
gfx::Transformation m_currentData;
|
||||||
Mask* m_initialMask;
|
Mask* m_initialMask;
|
||||||
Mask* m_currentMask;
|
Mask* m_currentMask;
|
||||||
|
color_t m_maskColor;
|
||||||
};
|
};
|
||||||
|
|
||||||
inline PixelsMovement::MoveModifier& operator|=(PixelsMovement::MoveModifier& a,
|
inline PixelsMovement::MoveModifier& operator|=(PixelsMovement::MoveModifier& a,
|
||||||
|
@ -62,7 +62,8 @@ Image* NewImageFromMask(const DocumentLocation& location)
|
|||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
// Clear the new image
|
// Clear the new image
|
||||||
clear_image(dst, 0);
|
dst->setMaskColor(src->getMaskColor());
|
||||||
|
clear_image(dst, dst->getMaskColor());
|
||||||
|
|
||||||
// Copy the masked zones
|
// Copy the masked zones
|
||||||
const LockImageBits<BitmapTraits> maskBits(srcMaskBitmap, gfx::Rect(0, 0, srcBounds.w, srcBounds.h));
|
const LockImageBits<BitmapTraits> maskBits(srcMaskBitmap, gfx::Rect(0, 0, srcBounds.w, srcBounds.h));
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/* Aseprite
|
/* Aseprite
|
||||||
* Copyright (C) 2001-2013 David Capello
|
* Copyright (C) 2001-2014 David Capello
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* This program is free software; you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
@ -77,7 +77,8 @@ Image* Image::create(PixelFormat format, int width, int height,
|
|||||||
Image* Image::createCopy(const Image* image, const ImageBufferPtr& buffer)
|
Image* Image::createCopy(const Image* image, const ImageBufferPtr& buffer)
|
||||||
{
|
{
|
||||||
ASSERT(image);
|
ASSERT(image);
|
||||||
return crop_image(image, 0, 0, image->getWidth(), image->getHeight(), 0, buffer);
|
return crop_image(image, 0, 0, image->getWidth(), image->getHeight(),
|
||||||
|
image->getMaskColor(), buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace raster
|
} // namespace raster
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/* Aseprite
|
/* Aseprite
|
||||||
* Copyright (C) 2001-2013 David Capello
|
* Copyright (C) 2001-2014 David Capello
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* This program is free software; you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
@ -489,7 +489,7 @@ static void bestfit_init()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int Palette::findBestfit(int r, int g, int b) const
|
int Palette::findBestfit(int r, int g, int b, int mask_index) const
|
||||||
{
|
{
|
||||||
#ifdef __GNUC__
|
#ifdef __GNUC__
|
||||||
register int bestfit asm("%eax");
|
register int bestfit asm("%eax");
|
||||||
@ -512,7 +512,7 @@ int Palette::findBestfit(int r, int g, int b) const
|
|||||||
g >>= 3;
|
g >>= 3;
|
||||||
b >>= 3;
|
b >>= 3;
|
||||||
|
|
||||||
i = 1;
|
i = 0;
|
||||||
while (i < size()) {
|
while (i < size()) {
|
||||||
color_t rgb = m_colors[i];
|
color_t rgb = m_colors[i];
|
||||||
|
|
||||||
@ -521,7 +521,7 @@ int Palette::findBestfit(int r, int g, int b) const
|
|||||||
coldiff += (col_diff + 128) [ ((rgba_getr(rgb)>>3) - r) & 0x7F ];
|
coldiff += (col_diff + 128) [ ((rgba_getr(rgb)>>3) - r) & 0x7F ];
|
||||||
if (coldiff < lowest) {
|
if (coldiff < lowest) {
|
||||||
coldiff += (col_diff + 256) [ ((rgba_getb(rgb)>>3) - b) & 0x7F ];
|
coldiff += (col_diff + 256) [ ((rgba_getb(rgb)>>3) - b) & 0x7F ];
|
||||||
if (coldiff < lowest) {
|
if (coldiff < lowest && i != mask_index) {
|
||||||
bestfit = i;
|
bestfit = i;
|
||||||
if (coldiff == 0)
|
if (coldiff == 0)
|
||||||
return bestfit;
|
return bestfit;
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/* Aseprite
|
/* Aseprite
|
||||||
* Copyright (C) 2001-2013 David Capello
|
* Copyright (C) 2001-2014 David Capello
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* This program is free software; you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
@ -101,7 +101,7 @@ namespace raster {
|
|||||||
static Palette* load(const char *filename);
|
static Palette* load(const char *filename);
|
||||||
bool save(const char *filename) const;
|
bool save(const char *filename) const;
|
||||||
|
|
||||||
int findBestfit(int r, int g, int b) const;
|
int findBestfit(int r, int g, int b, int mask_index = 0) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
FrameNumber m_frame;
|
FrameNumber m_frame;
|
||||||
|
@ -694,7 +694,7 @@ static void ase_parallelogram_map_standard(Image *bmp, Image *sprite,
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case IMAGE_INDEXED: {
|
case IMAGE_INDEXED: {
|
||||||
IndexedDelegate delegate(bmp->getMaskColor());
|
IndexedDelegate delegate(sprite->getMaskColor());
|
||||||
ase_parallelogram_map<IndexedTraits, IndexedDelegate>(bmp, sprite, xs, ys, false, delegate);
|
ase_parallelogram_map<IndexedTraits, IndexedDelegate>(bmp, sprite, xs, ys, false, delegate);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/* Aseprite
|
/* Aseprite
|
||||||
* Copyright (C) 2001-2013 David Capello
|
* Copyright (C) 2001-2014 David Capello
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* This program is free software; you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
@ -179,7 +179,7 @@ void image_rotsprite(Image* bmp, Image* spr,
|
|||||||
base::UniquePtr<Image> tmp_copy(Image::create(spr->getPixelFormat(), spr->getWidth()*scale, spr->getHeight()*scale, buf2));
|
base::UniquePtr<Image> tmp_copy(Image::create(spr->getPixelFormat(), spr->getWidth()*scale, spr->getHeight()*scale, buf2));
|
||||||
base::UniquePtr<Image> spr_copy(Image::create(spr->getPixelFormat(), spr->getWidth()*scale, spr->getHeight()*scale, buf3));
|
base::UniquePtr<Image> spr_copy(Image::create(spr->getPixelFormat(), spr->getWidth()*scale, spr->getHeight()*scale, buf3));
|
||||||
|
|
||||||
color_t maskColor = bmp->getMaskColor();
|
color_t maskColor = spr->getMaskColor();
|
||||||
|
|
||||||
bmp_copy->setMaskColor(maskColor);
|
bmp_copy->setMaskColor(maskColor);
|
||||||
tmp_copy->setMaskColor(maskColor);
|
tmp_copy->setMaskColor(maskColor);
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/* Aseprite
|
/* Aseprite
|
||||||
* Copyright (C) 2001-2013 David Capello
|
* Copyright (C) 2001-2014 David Capello
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* This program is free software; you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
@ -132,7 +132,7 @@ bool Sprite::needAlpha() const
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Sprite::setTransparentColor(uint32_t color)
|
void Sprite::setTransparentColor(color_t color)
|
||||||
{
|
{
|
||||||
m_transparentColor = color;
|
m_transparentColor = color;
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/* Aseprite
|
/* Aseprite
|
||||||
* Copyright (C) 2001-2013 David Capello
|
* Copyright (C) 2001-2014 David Capello
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* This program is free software; you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
@ -21,6 +21,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "base/disable_copying.h"
|
#include "base/disable_copying.h"
|
||||||
|
#include "raster/color.h"
|
||||||
#include "raster/frame_number.h"
|
#include "raster/frame_number.h"
|
||||||
#include "raster/layer_index.h"
|
#include "raster/layer_index.h"
|
||||||
#include "raster/object.h"
|
#include "raster/object.h"
|
||||||
@ -69,8 +70,8 @@ namespace raster {
|
|||||||
// alpha channel in the render.
|
// alpha channel in the render.
|
||||||
bool needAlpha() const;
|
bool needAlpha() const;
|
||||||
|
|
||||||
uint32_t getTransparentColor() const { return m_transparentColor; }
|
color_t getTransparentColor() const { return m_transparentColor; }
|
||||||
void setTransparentColor(uint32_t color);
|
void setTransparentColor(color_t color);
|
||||||
|
|
||||||
int getMemSize() const;
|
int getMemSize() const;
|
||||||
|
|
||||||
@ -153,7 +154,7 @@ namespace raster {
|
|||||||
RgbMap* m_rgbMap;
|
RgbMap* m_rgbMap;
|
||||||
|
|
||||||
// Transparent color used in indexed images
|
// Transparent color used in indexed images
|
||||||
uint32_t m_transparentColor;
|
color_t m_transparentColor;
|
||||||
|
|
||||||
// Disable default constructor and copying
|
// Disable default constructor and copying
|
||||||
Sprite();
|
Sprite();
|
||||||
|
Loading…
x
Reference in New Issue
Block a user