mirror of
https://github.com/aseprite/aseprite.git
synced 2025-03-30 04:20:23 +00:00
Fix custom brush is available with the eraser tool (fix #1408)
This commit is contained in:
parent
d99e642c55
commit
2b1be4f288
@ -9,6 +9,7 @@
|
||||
#include "app/util/wrap_point.h"
|
||||
#include "app/util/wrap_value.h"
|
||||
#include "doc/blend_funcs.h"
|
||||
#include "doc/blend_internals.h"
|
||||
#include "doc/image_impl.h"
|
||||
#include "doc/layer.h"
|
||||
#include "doc/palette.h"
|
||||
@ -1125,7 +1126,7 @@ public:
|
||||
|
||||
color_t getTransparentColor() { return m_transparentColor; }
|
||||
|
||||
private:
|
||||
protected:
|
||||
void alignPixelPoint(int& x, int& y) {
|
||||
x = (x - m_u) % m_width;
|
||||
y = (y - m_v) % m_height;
|
||||
@ -1363,6 +1364,174 @@ void BrushLockAlphaInkProcessing<GrayscaleTraits>::processPixel(int x, int y) {
|
||||
*m_dstAddress = graya(graya_getv(c), graya_geta(*m_srcAddress));
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// Brush Ink - Eraser Tool
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
template<typename ImageTraits>
|
||||
class BrushEraserInkProcessing : public BrushInkProcessingBase<ImageTraits> {
|
||||
public:
|
||||
BrushEraserInkProcessing(ToolLoop* loop) : BrushInkProcessingBase<ImageTraits>(loop) {
|
||||
}
|
||||
|
||||
void processPixel(int x, int y) override {
|
||||
// Do nothing
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
void BrushEraserInkProcessing<RgbTraits>::processPixel(int x, int y) {
|
||||
alignPixelPoint(x, y);
|
||||
if (m_brushMask && !get_pixel_fast<BitmapTraits>(m_brushMask, x, y))
|
||||
return;
|
||||
|
||||
color_t c;
|
||||
switch (m_brushImage->pixelFormat()) {
|
||||
case IMAGE_RGB: {
|
||||
c = get_pixel_fast<RgbTraits>(m_brushImage, x, y);
|
||||
int t;
|
||||
c = rgba(rgba_getr(*m_srcAddress),
|
||||
rgba_getg(*m_srcAddress),
|
||||
rgba_getb(*m_srcAddress),
|
||||
MUL_UN8(rgba_geta(*m_dstAddress), 255 - rgba_geta(c), t));
|
||||
break;
|
||||
}
|
||||
case IMAGE_INDEXED: {
|
||||
c = get_pixel_fast<IndexedTraits>(m_brushImage, x, y);
|
||||
if (m_transparentColor == c)
|
||||
c = 0;
|
||||
else
|
||||
// TODO m_palette->getEntry(c) does not work because the
|
||||
// m_palette member is loaded the Rgba Palette, NOT the
|
||||
// original Indexed Palette from where m_brushImage belongs.
|
||||
// This conversion can be possible if we load the palette
|
||||
// pointer in m_brush when is created the custom brush in the
|
||||
// Indexed Sprite.
|
||||
c = m_palette->getEntry(c);
|
||||
int t;
|
||||
c = rgba(rgba_getr(*m_srcAddress),
|
||||
rgba_getg(*m_srcAddress),
|
||||
rgba_getb(*m_srcAddress),
|
||||
MUL_UN8(rgba_geta(*m_dstAddress), 255 - rgba_geta(c), t));
|
||||
break;
|
||||
}
|
||||
case IMAGE_GRAYSCALE: {
|
||||
c = get_pixel_fast<GrayscaleTraits>(m_brushImage, x, y);
|
||||
int t;
|
||||
c = rgba(rgba_getr(*m_srcAddress),
|
||||
rgba_getg(*m_srcAddress),
|
||||
rgba_getb(*m_srcAddress),
|
||||
MUL_UN8(rgba_geta(*m_dstAddress), 255 - graya_geta(c), t));
|
||||
break;
|
||||
}
|
||||
case IMAGE_BITMAP: {
|
||||
// TODO In which circuntance is possible this case?
|
||||
c = get_pixel_fast<BitmapTraits>(m_brushImage, x, y);
|
||||
c = c ? m_bgColor : *m_srcAddress;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
ASSERT(false);
|
||||
return;
|
||||
}
|
||||
*m_dstAddress = c;;
|
||||
}
|
||||
|
||||
template<>
|
||||
void BrushEraserInkProcessing<GrayscaleTraits>::processPixel(int x, int y) {
|
||||
alignPixelPoint(x, y);
|
||||
if (m_brushMask && !get_pixel_fast<BitmapTraits>(m_brushMask, x, y))
|
||||
return;
|
||||
|
||||
color_t c;
|
||||
switch (m_brushImage->pixelFormat()) {
|
||||
case IMAGE_RGB: {
|
||||
c = get_pixel_fast<RgbTraits>(m_brushImage, x, y);
|
||||
int t;
|
||||
c = graya(graya_getv(*m_srcAddress),
|
||||
MUL_UN8(graya_geta(*m_dstAddress), 255 - rgba_geta(c), t));
|
||||
break;
|
||||
}
|
||||
case IMAGE_INDEXED: {
|
||||
c = get_pixel_fast<IndexedTraits>(m_brushImage, x, y);
|
||||
if (m_transparentColor == c)
|
||||
c = 0;
|
||||
else
|
||||
// TODO m_palette->getEntry(c) does not work because the
|
||||
// m_palette member is loaded the Graya Palette, NOT the
|
||||
// original Indexed Palette from where m_brushImage belongs.
|
||||
// This conversion can be possible if we load the palette
|
||||
// pointer in m_brush when is created the custom brush in the
|
||||
// Indexed Sprite.
|
||||
c = m_palette->getEntry(c);
|
||||
int t;
|
||||
c = graya(graya_getv(*m_srcAddress),
|
||||
MUL_UN8(graya_geta(*m_dstAddress), 255 - rgba_geta(c), t));
|
||||
break;
|
||||
}
|
||||
case IMAGE_GRAYSCALE: {
|
||||
c = get_pixel_fast<GrayscaleTraits>(m_brushImage, x, y);
|
||||
int t;
|
||||
c = graya(graya_getv(*m_srcAddress),
|
||||
MUL_UN8(graya_geta(*m_dstAddress), 255 - graya_geta(c), t));
|
||||
break;
|
||||
}
|
||||
case IMAGE_BITMAP: {
|
||||
// TODO In which circuntance is possible this case?
|
||||
c = get_pixel_fast<BitmapTraits>(m_brushImage, x, y);
|
||||
c = c ? m_bgColor : *m_srcAddress;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
ASSERT(false);
|
||||
return;
|
||||
}
|
||||
*m_dstAddress = c;
|
||||
}
|
||||
|
||||
template<>
|
||||
void BrushEraserInkProcessing<IndexedTraits>::processPixel(int x, int y) {
|
||||
alignPixelPoint(x, y);
|
||||
if (m_brushMask && !get_pixel_fast<BitmapTraits>(m_brushMask, x, y))
|
||||
return;
|
||||
|
||||
color_t c;
|
||||
switch (m_brushImage->pixelFormat()) {
|
||||
case IMAGE_RGB: {
|
||||
c = get_pixel_fast<RgbTraits>(m_brushImage, x, y);
|
||||
c = m_palette->findBestfit(rgba_getr(c),
|
||||
rgba_getg(c),
|
||||
rgba_getb(c),
|
||||
rgba_geta(c), m_transparentColor);
|
||||
break;
|
||||
}
|
||||
case IMAGE_INDEXED: {
|
||||
c = get_pixel_fast<IndexedTraits>(m_brushImage, x, y);
|
||||
break;
|
||||
}
|
||||
case IMAGE_GRAYSCALE: {
|
||||
c = get_pixel_fast<GrayscaleTraits>(m_brushImage, x, y);
|
||||
c = m_palette->findBestfit(graya_getv(c),
|
||||
graya_getv(c),
|
||||
graya_getv(c),
|
||||
graya_geta(c), 0);
|
||||
break;
|
||||
}
|
||||
case IMAGE_BITMAP: {
|
||||
// TODO In which circuntance is possible this case?
|
||||
c = get_pixel_fast<BitmapTraits>(m_brushImage, x, y);
|
||||
c = c ? m_fgColor: m_bgColor;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
ASSERT(false);
|
||||
return;
|
||||
}
|
||||
if (c != m_transparentColor) {
|
||||
*m_dstAddress = m_transparentColor;
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
template<template<typename> class T>
|
||||
|
@ -284,32 +284,35 @@ public:
|
||||
|
||||
void prepareInk(ToolLoop* loop) override {
|
||||
switch (m_type) {
|
||||
|
||||
case Eraser: {
|
||||
// TODO app_get_color_to_clear_layer should receive the context as parameter
|
||||
color_t clearColor = app_get_color_to_clear_layer(loop->getLayer());
|
||||
loop->setPrimaryColor(clearColor);
|
||||
loop->setSecondaryColor(clearColor);
|
||||
|
||||
if (loop->getOpacity() == 255) {
|
||||
setProc(get_ink_proc<CopyInkProcessing>(loop));
|
||||
if (loop->getBrush()->type() == doc::kImageBrushType) {
|
||||
setProc(get_ink_proc<BrushEraserInkProcessing>(loop));
|
||||
}
|
||||
else {
|
||||
// For opaque layers
|
||||
if (loop->getLayer()->isBackground()) {
|
||||
setProc(get_ink_proc<TransparentInkProcessing>(loop));
|
||||
}
|
||||
// For transparent layers
|
||||
else {
|
||||
if (loop->sprite()->pixelFormat() == IMAGE_INDEXED)
|
||||
loop->setPrimaryColor(loop->sprite()->transparentColor());
|
||||
// TODO app_get_color_to_clear_layer should receive the context as parameter
|
||||
color_t clearColor = app_get_color_to_clear_layer(loop->getLayer());
|
||||
loop->setPrimaryColor(clearColor);
|
||||
loop->setSecondaryColor(clearColor);
|
||||
|
||||
setProc(get_ink_proc<MergeInkProcessing>(loop));
|
||||
if (loop->getOpacity() == 255) {
|
||||
setProc(get_ink_proc<CopyInkProcessing>(loop));
|
||||
}
|
||||
else {
|
||||
// For opaque layers
|
||||
if (loop->getLayer()->isBackground()) {
|
||||
setProc(get_ink_proc<TransparentInkProcessing>(loop));
|
||||
}
|
||||
// For transparent layers
|
||||
else {
|
||||
if (loop->sprite()->pixelFormat() == IMAGE_INDEXED)
|
||||
loop->setPrimaryColor(loop->sprite()->transparentColor());
|
||||
|
||||
setProc(get_ink_proc<MergeInkProcessing>(loop));
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case ReplaceFgWithBg:
|
||||
loop->setPrimaryColor(loop->getFgColor());
|
||||
loop->setSecondaryColor(loop->getBgColor());
|
||||
|
@ -183,7 +183,8 @@ void BrushPreview::show(const gfx::Point& screenPos)
|
||||
|
||||
// For cursor type 'bounds' we have to generate cursor boundaries
|
||||
if (m_type & BRUSH_BOUNDARIES) {
|
||||
showPreview = false;
|
||||
if (brush->type() != kImageBrushType)
|
||||
showPreview = false;
|
||||
generateBoundaries();
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user