mirror of
https://github.com/aseprite/aseprite.git
synced 2025-03-29 01:20:17 +00:00
Change ink processing impl
This commit is contained in:
parent
3e3b0d8a35
commit
8de967dd37
@ -5,6 +5,7 @@
|
|||||||
// the End-User License Agreement for Aseprite.
|
// the End-User License Agreement for Aseprite.
|
||||||
|
|
||||||
#include "app/modules/palettes.h"
|
#include "app/modules/palettes.h"
|
||||||
|
#include "base/unique_ptr.h"
|
||||||
#include "doc/blend_funcs.h"
|
#include "doc/blend_funcs.h"
|
||||||
#include "doc/image_impl.h"
|
#include "doc/image_impl.h"
|
||||||
#include "doc/layer.h"
|
#include "doc/layer.h"
|
||||||
@ -28,10 +29,16 @@ namespace {
|
|||||||
// Ink Processing
|
// Ink Processing
|
||||||
//////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
template<typename Derived>
|
class BaseInkProcessing {
|
||||||
class InkProcessing {
|
|
||||||
public:
|
public:
|
||||||
void operator()(int x1, int y, int x2, ToolLoop* loop) {
|
virtual ~BaseInkProcessing() { }
|
||||||
|
virtual void hline(int x1, int y, int x2, ToolLoop* loop) = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename Derived>
|
||||||
|
class InkProcessing : public BaseInkProcessing {
|
||||||
|
public:
|
||||||
|
void hline(int x1, int y, int x2, ToolLoop* loop) override {
|
||||||
int x;
|
int x;
|
||||||
|
|
||||||
// Use mask
|
// Use mask
|
||||||
@ -1066,22 +1073,15 @@ void BrushInkProcessing<IndexedTraits>::processPixel(int x, int y) {
|
|||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
template<template<typename> class InkProcessing,
|
typedef base::UniquePtr<BaseInkProcessing> InkProcessingPtr;
|
||||||
typename ImageTraits>
|
|
||||||
void ink_proc(int x1, int y, int x2, void* data)
|
|
||||||
{
|
|
||||||
ToolLoop* loop = reinterpret_cast<ToolLoop*>(data);
|
|
||||||
InkProcessing<ImageTraits> ink(loop);
|
|
||||||
ink(x1, y, x2, loop);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<template<typename> class InkProcessing>
|
template<template<typename> class T>
|
||||||
AlgoHLine get_ink_proc(PixelFormat pixelFormat)
|
BaseInkProcessing* get_ink_proc(ToolLoop* loop)
|
||||||
{
|
{
|
||||||
switch (pixelFormat) {
|
switch (loop->sprite()->pixelFormat()) {
|
||||||
case IMAGE_RGB: return ink_proc<InkProcessing, RgbTraits>;
|
case IMAGE_RGB: return new T<RgbTraits>(loop);
|
||||||
case IMAGE_GRAYSCALE: return ink_proc<InkProcessing, GrayscaleTraits>;
|
case IMAGE_GRAYSCALE: return new T<GrayscaleTraits>(loop);
|
||||||
case IMAGE_INDEXED: return ink_proc<InkProcessing, IndexedTraits>;
|
case IMAGE_INDEXED: return new T<IndexedTraits>(loop);
|
||||||
}
|
}
|
||||||
ASSERT(false);
|
ASSERT(false);
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
@ -19,18 +19,36 @@
|
|||||||
namespace app {
|
namespace app {
|
||||||
namespace tools {
|
namespace tools {
|
||||||
|
|
||||||
|
class BaseInk : public Ink {
|
||||||
|
public:
|
||||||
|
BaseInk() { }
|
||||||
|
BaseInk(const BaseInk& other) { }
|
||||||
|
|
||||||
|
void inkHline(int x1, int y, int x2, ToolLoop* loop) override {
|
||||||
|
ASSERT(m_proc);
|
||||||
|
m_proc->hline(x1, y, x2, loop);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void setProc(BaseInkProcessing* proc) {
|
||||||
|
m_proc.reset(proc);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
InkProcessingPtr m_proc;
|
||||||
|
};
|
||||||
|
|
||||||
// Ink used for tools which paint with primary/secondary
|
// Ink used for tools which paint with primary/secondary
|
||||||
// (or foreground/background colors)
|
// (or foreground/background colors)
|
||||||
class PaintInk : public Ink {
|
class PaintInk : public BaseInk {
|
||||||
public:
|
public:
|
||||||
enum Type { Simple, WithFg, WithBg, Copy, LockAlpha };
|
enum Type { Simple, WithFg, WithBg, Copy, LockAlpha };
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Type m_type;
|
Type m_type;
|
||||||
AlgoHLine m_proc;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
PaintInk(Type type) : m_type(type), m_proc(nullptr) { }
|
PaintInk(Type type) : m_type(type) { }
|
||||||
|
|
||||||
Ink* clone() override { return new PaintInk(*this); }
|
Ink* clone() override { return new PaintInk(*this); }
|
||||||
|
|
||||||
@ -54,10 +72,8 @@ public:
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto pixelFormat = loop->sprite()->pixelFormat();
|
|
||||||
|
|
||||||
if (loop->getBrush()->type() == doc::kImageBrushType)
|
if (loop->getBrush()->type() == doc::kImageBrushType)
|
||||||
m_proc = get_ink_proc<BrushInkProcessing>(pixelFormat);
|
setProc(get_ink_proc<BrushInkProcessing>(loop));
|
||||||
else {
|
else {
|
||||||
switch (m_type) {
|
switch (m_type) {
|
||||||
case Simple: {
|
case Simple: {
|
||||||
@ -82,50 +98,36 @@ public:
|
|||||||
|
|
||||||
// Use a faster ink, direct copy
|
// Use a faster ink, direct copy
|
||||||
if (opaque)
|
if (opaque)
|
||||||
m_proc = get_ink_proc<CopyInkProcessing>(pixelFormat);
|
setProc(get_ink_proc<CopyInkProcessing>(loop));
|
||||||
else
|
else
|
||||||
m_proc = get_ink_proc<TransparentInkProcessing>(pixelFormat);
|
setProc(get_ink_proc<TransparentInkProcessing>(loop));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case Copy:
|
case Copy:
|
||||||
m_proc = get_ink_proc<CopyInkProcessing>(pixelFormat);
|
setProc(get_ink_proc<CopyInkProcessing>(loop));
|
||||||
break;
|
break;
|
||||||
case LockAlpha:
|
case LockAlpha:
|
||||||
m_proc = get_ink_proc<LockAlphaInkProcessing>(pixelFormat);
|
setProc(get_ink_proc<LockAlphaInkProcessing>(loop));
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
m_proc = get_ink_proc<TransparentInkProcessing>(pixelFormat);
|
setProc(get_ink_proc<TransparentInkProcessing>(loop));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void inkHline(int x1, int y, int x2, ToolLoop* loop) override {
|
|
||||||
ASSERT(m_proc);
|
|
||||||
(*m_proc)(x1, y, x2, loop);
|
|
||||||
}
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
class ShadingInk : public Ink {
|
class ShadingInk : public BaseInk {
|
||||||
private:
|
|
||||||
AlgoHLine m_proc;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
ShadingInk() { }
|
|
||||||
|
|
||||||
Ink* clone() override { return new ShadingInk(*this); }
|
Ink* clone() override { return new ShadingInk(*this); }
|
||||||
|
|
||||||
bool isPaint() const override { return true; }
|
bool isPaint() const override { return true; }
|
||||||
bool isShading() const override { return true; }
|
bool isShading() const override { return true; }
|
||||||
|
|
||||||
void prepareInk(ToolLoop* loop) override {
|
void prepareInk(ToolLoop* loop) override {
|
||||||
m_proc = get_ink_proc<ShadingInkProcessing>(loop->sprite()->pixelFormat());
|
setProc(get_ink_proc<ShadingInkProcessing>(loop));
|
||||||
}
|
|
||||||
|
|
||||||
void inkHline(int x1, int y, int x2, ToolLoop* loop) override {
|
|
||||||
(*m_proc)(x1, y, x2, loop);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
@ -168,15 +170,12 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
class SliceInk : public Ink {
|
class SliceInk : public BaseInk {
|
||||||
AlgoHLine m_proc;
|
|
||||||
bool m_createSlice;
|
bool m_createSlice;
|
||||||
gfx::Rect m_maxBounds;
|
gfx::Rect m_maxBounds;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
SliceInk() {
|
SliceInk() : m_createSlice(false) { }
|
||||||
m_createSlice = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
Ink* clone() override { return new SliceInk(*this); }
|
Ink* clone() override { return new SliceInk(*this); }
|
||||||
|
|
||||||
@ -186,14 +185,14 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
void prepareInk(ToolLoop* loop) override {
|
void prepareInk(ToolLoop* loop) override {
|
||||||
m_proc = get_ink_proc<XorInkProcessing>(loop->sprite()->pixelFormat());
|
setProc(get_ink_proc<XorInkProcessing>(loop));
|
||||||
}
|
}
|
||||||
|
|
||||||
void inkHline(int x1, int y, int x2, ToolLoop* loop) override {
|
void inkHline(int x1, int y, int x2, ToolLoop* loop) override {
|
||||||
if (m_createSlice)
|
if (m_createSlice)
|
||||||
m_maxBounds |= gfx::Rect(x1, y, x2-x1+1, 1);
|
m_maxBounds |= gfx::Rect(x1, y, x2-x1+1, 1);
|
||||||
else
|
else
|
||||||
(*m_proc)(x1, y, x2, loop);
|
BaseInk::inkHline(x1, y, x2, loop);
|
||||||
}
|
}
|
||||||
|
|
||||||
void setFinalStep(ToolLoop* loop, bool state) override {
|
void setFinalStep(ToolLoop* loop, bool state) override {
|
||||||
@ -211,12 +210,11 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
class EraserInk : public Ink {
|
class EraserInk : public BaseInk {
|
||||||
public:
|
public:
|
||||||
enum Type { Eraser, ReplaceFgWithBg, ReplaceBgWithFg };
|
enum Type { Eraser, ReplaceFgWithBg, ReplaceBgWithFg };
|
||||||
|
|
||||||
private:
|
private:
|
||||||
AlgoHLine m_proc;
|
|
||||||
Type m_type;
|
Type m_type;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
@ -232,58 +230,48 @@ public:
|
|||||||
switch (m_type) {
|
switch (m_type) {
|
||||||
|
|
||||||
case Eraser: {
|
case Eraser: {
|
||||||
color_t primary = app_get_color_to_clear_layer(loop->getLayer());
|
// TODO app_get_color_to_clear_layer should receive the context as parameter
|
||||||
color_t secondary = app_get_color_to_clear_layer(loop->getLayer());
|
color_t clearColor = app_get_color_to_clear_layer(loop->getLayer());
|
||||||
|
loop->setPrimaryColor(clearColor);
|
||||||
|
loop->setSecondaryColor(clearColor);
|
||||||
|
|
||||||
if (loop->getOpacity() == 255) {
|
if (loop->getOpacity() == 255) {
|
||||||
m_proc = get_ink_proc<CopyInkProcessing>(loop->sprite()->pixelFormat());
|
setProc(get_ink_proc<CopyInkProcessing>(loop));
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// For opaque layers
|
// For opaque layers
|
||||||
if (loop->getLayer()->isBackground()) {
|
if (loop->getLayer()->isBackground()) {
|
||||||
m_proc = get_ink_proc<TransparentInkProcessing>(loop->sprite()->pixelFormat());
|
setProc(get_ink_proc<TransparentInkProcessing>(loop));
|
||||||
}
|
}
|
||||||
// For transparent layers
|
// For transparent layers
|
||||||
else {
|
else {
|
||||||
m_proc = get_ink_proc<MergeInkProcessing>(loop->sprite()->pixelFormat());
|
if (loop->sprite()->pixelFormat() == IMAGE_INDEXED)
|
||||||
|
loop->setPrimaryColor(loop->sprite()->transparentColor());
|
||||||
|
|
||||||
if (loop->sprite()->pixelFormat() == IMAGE_INDEXED) {
|
setProc(get_ink_proc<MergeInkProcessing>(loop));
|
||||||
primary = loop->sprite()->transparentColor();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO app_get_color_to_clear_layer should receive the context as parameter
|
|
||||||
loop->setPrimaryColor(primary);
|
|
||||||
loop->setSecondaryColor(secondary);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case ReplaceFgWithBg:
|
case ReplaceFgWithBg:
|
||||||
m_proc = get_ink_proc<ReplaceInkProcessing>(loop->sprite()->pixelFormat());
|
|
||||||
|
|
||||||
loop->setPrimaryColor(loop->getFgColor());
|
loop->setPrimaryColor(loop->getFgColor());
|
||||||
loop->setSecondaryColor(loop->getBgColor());
|
loop->setSecondaryColor(loop->getBgColor());
|
||||||
|
setProc(get_ink_proc<ReplaceInkProcessing>(loop));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ReplaceBgWithFg:
|
case ReplaceBgWithFg:
|
||||||
m_proc = get_ink_proc<ReplaceInkProcessing>(loop->sprite()->pixelFormat());
|
|
||||||
|
|
||||||
loop->setPrimaryColor(loop->getBgColor());
|
loop->setPrimaryColor(loop->getBgColor());
|
||||||
loop->setSecondaryColor(loop->getFgColor());
|
loop->setSecondaryColor(loop->getFgColor());
|
||||||
|
setProc(get_ink_proc<ReplaceInkProcessing>(loop));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void inkHline(int x1, int y, int x2, ToolLoop* loop) override {
|
|
||||||
(*m_proc)(x1, y, x2, loop);
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
class BlurInk : public Ink {
|
class BlurInk : public BaseInk {
|
||||||
AlgoHLine m_proc;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Ink* clone() override { return new BlurInk(*this); }
|
Ink* clone() override { return new BlurInk(*this); }
|
||||||
|
|
||||||
@ -292,11 +280,7 @@ public:
|
|||||||
bool needsSpecialSourceArea() const override { return true; }
|
bool needsSpecialSourceArea() const override { return true; }
|
||||||
|
|
||||||
void prepareInk(ToolLoop* loop) override {
|
void prepareInk(ToolLoop* loop) override {
|
||||||
m_proc = get_ink_proc<BlurInkProcessing>(loop->sprite()->pixelFormat());
|
setProc(get_ink_proc<BlurInkProcessing>(loop));
|
||||||
}
|
|
||||||
|
|
||||||
void inkHline(int x1, int y, int x2, ToolLoop* loop) override {
|
|
||||||
(*m_proc)(x1, y, x2, loop);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void createSpecialSourceArea(const gfx::Region& dirtyArea, gfx::Region& sourceArea) const override {
|
void createSpecialSourceArea(const gfx::Region& dirtyArea, gfx::Region& sourceArea) const override {
|
||||||
@ -309,9 +293,7 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
class JumbleInk : public Ink {
|
class JumbleInk : public BaseInk {
|
||||||
AlgoHLine m_proc;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Ink* clone() override { return new JumbleInk(*this); }
|
Ink* clone() override { return new JumbleInk(*this); }
|
||||||
|
|
||||||
@ -320,11 +302,7 @@ public:
|
|||||||
bool needsSpecialSourceArea() const override { return true; }
|
bool needsSpecialSourceArea() const override { return true; }
|
||||||
|
|
||||||
void prepareInk(ToolLoop* loop) override {
|
void prepareInk(ToolLoop* loop) override {
|
||||||
m_proc = get_ink_proc<JumbleInkProcessing>(loop->sprite()->pixelFormat());
|
setProc(get_ink_proc<JumbleInkProcessing>(loop));
|
||||||
}
|
|
||||||
|
|
||||||
void inkHline(int x1, int y, int x2, ToolLoop* loop) override {
|
|
||||||
(*m_proc)(x1, y, x2, loop);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void createSpecialSourceArea(const gfx::Region& dirtyArea, gfx::Region& sourceArea) const override {
|
void createSpecialSourceArea(const gfx::Region& dirtyArea, gfx::Region& sourceArea) const override {
|
||||||
@ -338,21 +316,19 @@ public:
|
|||||||
|
|
||||||
|
|
||||||
// Ink used for selection tools (like Rectangle Marquee, Lasso, Magic Wand, etc.)
|
// Ink used for selection tools (like Rectangle Marquee, Lasso, Magic Wand, etc.)
|
||||||
class SelectionInk : public Ink {
|
class SelectionInk : public BaseInk {
|
||||||
bool m_modify_selection;
|
bool m_modify_selection;
|
||||||
Mask m_mask;
|
Mask m_mask;
|
||||||
Rect m_maxBounds;
|
Rect m_maxBounds;
|
||||||
AlgoHLine m_proc;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
SelectionInk() {
|
SelectionInk()
|
||||||
m_modify_selection = false;
|
: m_modify_selection(false) { }
|
||||||
}
|
|
||||||
|
|
||||||
Ink* clone() override { return new SelectionInk(*this); }
|
Ink* clone() override { return new SelectionInk(*this); }
|
||||||
|
|
||||||
void prepareInk(ToolLoop* loop) override {
|
void prepareInk(ToolLoop* loop) override {
|
||||||
m_proc = get_ink_proc<XorInkProcessing>(loop->sprite()->pixelFormat());
|
setProc(get_ink_proc<XorInkProcessing>(loop));
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isSelection() const override { return true; }
|
bool isSelection() const override { return true; }
|
||||||
@ -375,7 +351,7 @@ public:
|
|||||||
m_maxBounds |= gfx::Rect(x1, y, x2-x1+1, 1);
|
m_maxBounds |= gfx::Rect(x1, y, x2-x1+1, 1);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
(*m_proc)(x1, y, x2, loop);
|
BaseInk::inkHline(x1, y, x2, loop);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user