mirror of https://github.com/aseprite/aseprite.git
Merge branch 'master' into beta
This commit is contained in:
commit
e46d453356
|
|
@ -75,6 +75,7 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
Key* key() { return m_key; }
|
Key* key() { return m_key; }
|
||||||
|
AppMenuItem* menuitem() const { return m_menuitem; }
|
||||||
|
|
||||||
void restoreKeys() {
|
void restoreKeys() {
|
||||||
if (m_key && m_keyOrig)
|
if (m_key && m_keyOrig)
|
||||||
|
|
@ -502,7 +503,8 @@ private:
|
||||||
|
|
||||||
KeyItem* copyItem =
|
KeyItem* copyItem =
|
||||||
new KeyItem(itemText,
|
new KeyItem(itemText,
|
||||||
keyItem->key(), nullptr, 0);
|
keyItem->key(),
|
||||||
|
keyItem->menuitem(), 0);
|
||||||
searchList()->addChild(copyItem);
|
searchList()->addChild(copyItem);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1066,46 +1066,26 @@ void BrushInkProcessing<IndexedTraits>::processPixel(int x, int y) {
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
enum {
|
template<template<typename> class InkProcessing,
|
||||||
INK_COPY,
|
typename ImageTraits>
|
||||||
INK_LOCKALPHA,
|
void ink_proc(int x1, int y, int x2, void* data)
|
||||||
INK_TRANSPARENT,
|
|
||||||
INK_MERGE,
|
|
||||||
INK_BLUR,
|
|
||||||
INK_REPLACE,
|
|
||||||
INK_JUMBLE,
|
|
||||||
INK_SHADING,
|
|
||||||
INK_XOR,
|
|
||||||
INK_BRUSH,
|
|
||||||
MAX_INKS
|
|
||||||
};
|
|
||||||
|
|
||||||
template<typename InkProcessing>
|
|
||||||
void ink_processing_algo(int x1, int y, int x2, void* data)
|
|
||||||
{
|
{
|
||||||
ToolLoop* loop = reinterpret_cast<ToolLoop*>(data);
|
ToolLoop* loop = reinterpret_cast<ToolLoop*>(data);
|
||||||
InkProcessing ink(loop);
|
InkProcessing<ImageTraits> ink(loop);
|
||||||
ink(x1, y, x2, loop);
|
ink(x1, y, x2, loop);
|
||||||
}
|
}
|
||||||
|
|
||||||
AlgoHLine ink_processing[][3] =
|
template<template<typename> class InkProcessing>
|
||||||
|
AlgoHLine get_ink_proc(PixelFormat pixelFormat)
|
||||||
{
|
{
|
||||||
#define DEFINE_INK(name) \
|
switch (pixelFormat) {
|
||||||
{ ink_processing_algo<name<RgbTraits> >, \
|
case IMAGE_RGB: return ink_proc<InkProcessing, RgbTraits>;
|
||||||
ink_processing_algo<name<GrayscaleTraits> >, \
|
case IMAGE_GRAYSCALE: return ink_proc<InkProcessing, GrayscaleTraits>;
|
||||||
ink_processing_algo<name<IndexedTraits> > }
|
case IMAGE_INDEXED: return ink_proc<InkProcessing, IndexedTraits>;
|
||||||
|
}
|
||||||
DEFINE_INK(CopyInkProcessing),
|
ASSERT(false);
|
||||||
DEFINE_INK(LockAlphaInkProcessing),
|
return nullptr;
|
||||||
DEFINE_INK(TransparentInkProcessing),
|
}
|
||||||
DEFINE_INK(MergeInkProcessing),
|
|
||||||
DEFINE_INK(BlurInkProcessing),
|
|
||||||
DEFINE_INK(ReplaceInkProcessing),
|
|
||||||
DEFINE_INK(JumbleInkProcessing),
|
|
||||||
DEFINE_INK(ShadingInkProcessing),
|
|
||||||
DEFINE_INK(XorInkProcessing),
|
|
||||||
DEFINE_INK(BrushInkProcessing)
|
|
||||||
};
|
|
||||||
|
|
||||||
} // anonymous namespace
|
} // anonymous namespace
|
||||||
} // namespace tools
|
} // namespace tools
|
||||||
|
|
|
||||||
|
|
@ -53,10 +53,10 @@ public:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
int depth = MID(0, loop->sprite()->pixelFormat(), 2);
|
auto pixelFormat = loop->sprite()->pixelFormat();
|
||||||
|
|
||||||
if (loop->getBrush()->type() == doc::kImageBrushType)
|
if (loop->getBrush()->type() == doc::kImageBrushType)
|
||||||
m_proc = ink_processing[INK_BRUSH][depth];
|
m_proc = get_ink_proc<BrushInkProcessing>(pixelFormat);
|
||||||
else {
|
else {
|
||||||
switch (m_type) {
|
switch (m_type) {
|
||||||
case Simple: {
|
case Simple: {
|
||||||
|
|
@ -81,19 +81,19 @@ public:
|
||||||
|
|
||||||
// Use a faster ink, direct copy
|
// Use a faster ink, direct copy
|
||||||
if (opaque)
|
if (opaque)
|
||||||
m_proc = ink_processing[INK_COPY][depth];
|
m_proc = get_ink_proc<CopyInkProcessing>(pixelFormat);
|
||||||
else
|
else
|
||||||
m_proc = ink_processing[INK_TRANSPARENT][depth];
|
m_proc = get_ink_proc<TransparentInkProcessing>(pixelFormat);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case Copy:
|
case Copy:
|
||||||
m_proc = ink_processing[INK_COPY][depth];
|
m_proc = get_ink_proc<CopyInkProcessing>(pixelFormat);
|
||||||
break;
|
break;
|
||||||
case LockAlpha:
|
case LockAlpha:
|
||||||
m_proc = ink_processing[INK_LOCKALPHA][depth];
|
m_proc = get_ink_proc<LockAlphaInkProcessing>(pixelFormat);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
m_proc = ink_processing[INK_TRANSPARENT][depth];
|
m_proc = get_ink_proc<TransparentInkProcessing>(pixelFormat);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -120,7 +120,7 @@ public:
|
||||||
bool isShading() const override { return true; }
|
bool isShading() const override { return true; }
|
||||||
|
|
||||||
void prepareInk(ToolLoop* loop) override {
|
void prepareInk(ToolLoop* loop) override {
|
||||||
m_proc = ink_processing[INK_SHADING][MID(0, loop->sprite()->pixelFormat(), 2)];
|
m_proc = get_ink_proc<ShadingInkProcessing>(loop->sprite()->pixelFormat());
|
||||||
}
|
}
|
||||||
|
|
||||||
void inkHline(int x1, int y, int x2, ToolLoop* loop) override {
|
void inkHline(int x1, int y, int x2, ToolLoop* loop) override {
|
||||||
|
|
@ -207,16 +207,16 @@ public:
|
||||||
color_t secondary = app_get_color_to_clear_layer(loop->getLayer());
|
color_t secondary = app_get_color_to_clear_layer(loop->getLayer());
|
||||||
|
|
||||||
if (loop->getOpacity() == 255) {
|
if (loop->getOpacity() == 255) {
|
||||||
m_proc = ink_processing[INK_COPY][MID(0, loop->sprite()->pixelFormat(), 2)];
|
m_proc = get_ink_proc<CopyInkProcessing>(loop->sprite()->pixelFormat());
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// For opaque layers
|
// For opaque layers
|
||||||
if (loop->getLayer()->isBackground()) {
|
if (loop->getLayer()->isBackground()) {
|
||||||
m_proc = ink_processing[INK_TRANSPARENT][MID(0, loop->sprite()->pixelFormat(), 2)];
|
m_proc = get_ink_proc<TransparentInkProcessing>(loop->sprite()->pixelFormat());
|
||||||
}
|
}
|
||||||
// For transparent layers
|
// For transparent layers
|
||||||
else {
|
else {
|
||||||
m_proc = ink_processing[INK_MERGE][MID(0, loop->sprite()->pixelFormat(), 2)];
|
m_proc = get_ink_proc<MergeInkProcessing>(loop->sprite()->pixelFormat());
|
||||||
|
|
||||||
if (loop->sprite()->pixelFormat() == IMAGE_INDEXED) {
|
if (loop->sprite()->pixelFormat() == IMAGE_INDEXED) {
|
||||||
primary = loop->sprite()->transparentColor();
|
primary = loop->sprite()->transparentColor();
|
||||||
|
|
@ -231,14 +231,14 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
case ReplaceFgWithBg:
|
case ReplaceFgWithBg:
|
||||||
m_proc = ink_processing[INK_REPLACE][MID(0, loop->sprite()->pixelFormat(), 2)];
|
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());
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ReplaceBgWithFg:
|
case ReplaceBgWithFg:
|
||||||
m_proc = ink_processing[INK_REPLACE][MID(0, loop->sprite()->pixelFormat(), 2)];
|
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());
|
||||||
|
|
@ -263,7 +263,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 = ink_processing[INK_BLUR][MID(0, loop->sprite()->pixelFormat(), 2)];
|
m_proc = get_ink_proc<BlurInkProcessing>(loop->sprite()->pixelFormat());
|
||||||
}
|
}
|
||||||
|
|
||||||
void inkHline(int x1, int y, int x2, ToolLoop* loop) override {
|
void inkHline(int x1, int y, int x2, ToolLoop* loop) override {
|
||||||
|
|
@ -291,7 +291,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 = ink_processing[INK_JUMBLE][MID(0, loop->sprite()->pixelFormat(), 2)];
|
m_proc = get_ink_proc<JumbleInkProcessing>(loop->sprite()->pixelFormat());
|
||||||
}
|
}
|
||||||
|
|
||||||
void inkHline(int x1, int y, int x2, ToolLoop* loop) override {
|
void inkHline(int x1, int y, int x2, ToolLoop* loop) override {
|
||||||
|
|
@ -313,12 +313,19 @@ class SelectionInk : public Ink {
|
||||||
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() { m_modify_selection = false; }
|
SelectionInk() {
|
||||||
|
m_modify_selection = false;
|
||||||
|
}
|
||||||
|
|
||||||
Ink* clone() override { return new SelectionInk(*this); }
|
Ink* clone() override { return new SelectionInk(*this); }
|
||||||
|
|
||||||
|
void prepareInk(ToolLoop* loop) override {
|
||||||
|
m_proc = get_ink_proc<XorInkProcessing>(loop->sprite()->pixelFormat());
|
||||||
|
}
|
||||||
|
|
||||||
bool isSelection() const override { return true; }
|
bool isSelection() const override { return true; }
|
||||||
bool needsCelCoordinates() const override {
|
bool needsCelCoordinates() const override {
|
||||||
return (m_modify_selection ? false: true);
|
return (m_modify_selection ? false: true);
|
||||||
|
|
@ -340,8 +347,7 @@ public:
|
||||||
}
|
}
|
||||||
// TODO show the selection-preview with a XOR color or something like that
|
// TODO show the selection-preview with a XOR color or something like that
|
||||||
else {
|
else {
|
||||||
ink_processing[INK_XOR][MID(0, loop->sprite()->pixelFormat(), 2)]
|
(*m_proc)(x1, y, x2, loop);
|
||||||
(x1, y, x2, loop);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -52,10 +52,6 @@ DrawingState::~DrawingState()
|
||||||
|
|
||||||
void DrawingState::initToolLoop(Editor* editor, MouseMessage* msg)
|
void DrawingState::initToolLoop(Editor* editor, MouseMessage* msg)
|
||||||
{
|
{
|
||||||
// It's needed to clear and redraw the brush boundaries after the
|
|
||||||
// first mouse pressed/point shape if drawn.
|
|
||||||
HideBrushPreview hide(editor->brushPreview());
|
|
||||||
|
|
||||||
// Prepare preview image (the destination image will be our preview
|
// Prepare preview image (the destination image will be our preview
|
||||||
// in the tool-loop time, so we can see what we are drawing)
|
// in the tool-loop time, so we can see what we are drawing)
|
||||||
editor->renderEngine().setPreviewImage(
|
editor->renderEngine().setPreviewImage(
|
||||||
|
|
|
||||||
|
|
@ -305,6 +305,12 @@ bool StandbyState::onMouseDown(Editor* editor, MouseMessage* msg)
|
||||||
if (layerEdges)
|
if (layerEdges)
|
||||||
layerEdgesOption(false);
|
layerEdgesOption(false);
|
||||||
|
|
||||||
|
// We need to clear and redraw the brush boundaries after the
|
||||||
|
// first mouse pressed/point shape if drawn. This is to avoid
|
||||||
|
// graphical glitches (invalid areas in the ToolLoop's src/dst
|
||||||
|
// images).
|
||||||
|
HideBrushPreview hide(editor->brushPreview());
|
||||||
|
|
||||||
tools::ToolLoop* toolLoop = create_tool_loop(editor, context);
|
tools::ToolLoop* toolLoop = create_tool_loop(editor, context);
|
||||||
if (toolLoop) {
|
if (toolLoop) {
|
||||||
EditorStatePtr newState(new DrawingState(toolLoop));
|
EditorStatePtr newState(new DrawingState(toolLoop));
|
||||||
|
|
|
||||||
|
|
@ -241,10 +241,15 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
void updateDirtyArea() override {
|
void updateDirtyArea() override {
|
||||||
// TODO find a way to avoid calling hide/show brush preview here
|
// This is necessary here so the "on sprite crosshair" is hidden,
|
||||||
|
// we update screen pixels with the new sprite, and then we show
|
||||||
|
// the crosshair saving the updated pixels. It fixes problems with
|
||||||
|
// filled shape tools when we release the button, or paint-bucket
|
||||||
|
// when we press the button.
|
||||||
HideBrushPreview hide(m_editor->brushPreview());
|
HideBrushPreview hide(m_editor->brushPreview());
|
||||||
m_document->notifySpritePixelsModified(m_sprite, m_dirtyArea,
|
|
||||||
m_frame);
|
m_document->notifySpritePixelsModified(
|
||||||
|
m_sprite, m_dirtyArea, m_frame);
|
||||||
}
|
}
|
||||||
|
|
||||||
void updateStatusBar(const char* text) override {
|
void updateStatusBar(const char* text) override {
|
||||||
|
|
|
||||||
|
|
@ -42,19 +42,20 @@ CompressedImage::CompressedImage(const Image* image,
|
||||||
scanline.x = x;
|
scanline.x = x;
|
||||||
|
|
||||||
for (++x; x<image->width(); ++x) {
|
for (++x; x<image->width(); ++x) {
|
||||||
|
if (maskBitmap && !get_pixel_fast<BitmapTraits>(maskBitmap, x, y))
|
||||||
|
break;
|
||||||
|
|
||||||
c2 = get_pixel(image, x, y);
|
c2 = get_pixel(image, x, y);
|
||||||
|
|
||||||
if (diffColors && c1 != c2)
|
if (diffColors && c1 != c2)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
if (maskBitmap && !get_pixel_fast<BitmapTraits>(maskBitmap, x, y))
|
|
||||||
break;
|
|
||||||
|
|
||||||
if (!diffColors && !maskBitmap && c2 == mask)
|
if (!diffColors && !maskBitmap && c2 == mask)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
scanline.w = x - scanline.x;
|
scanline.w = x - scanline.x;
|
||||||
|
if (scanline.w > 0)
|
||||||
m_scanlines.push_back(scanline);
|
m_scanlines.push_back(scanline);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue