diff --git a/src/app/commands/filters/filter_preview.cpp b/src/app/commands/filters/filter_preview.cpp index f7509aa51..40a767c81 100644 --- a/src/app/commands/filters/filter_preview.cpp +++ b/src/app/commands/filters/filter_preview.cpp @@ -75,8 +75,9 @@ bool FilterPreview::onProcessMessage(Message* msg) switch (msg->type()) { case kOpenMessage: - RenderEngine::setPreviewImage(m_filterMgr->layer(), - m_filterMgr->destinationImage()); + RenderEngine::setPreviewImage( + m_filterMgr->layer(), + m_filterMgr->destinationImage()); break; case kCloseMessage: diff --git a/src/app/document.cpp b/src/app/document.cpp index d5fecd099..26bd9bcdc 100644 --- a/src/app/document.cpp +++ b/src/app/document.cpp @@ -59,6 +59,7 @@ Document::Document(Sprite* sprite) // Extra cel , m_extraCel(NULL) , m_extraImage(NULL) + , m_extraCelBlendMode(BLEND_MODE_NORMAL) // Mask , m_mask(new Mask()) , m_maskVisible(true) diff --git a/src/app/document.h b/src/app/document.h index d57ed05b0..4fc63ab7e 100644 --- a/src/app/document.h +++ b/src/app/document.h @@ -129,6 +129,9 @@ namespace app { Cel* getExtraCel() const; Image* getExtraCelImage() const; + int getExtraCelBlendMode() const { return m_extraCelBlendMode; } + void setExtraCelBlendMode(int mode) { m_extraCelBlendMode = mode; } + ////////////////////////////////////////////////////////////////////// // Mask @@ -214,6 +217,7 @@ namespace app { // Image of the extra cel. Image* m_extraImage; + int m_extraCelBlendMode; // Current mask. base::UniquePtr m_mask; diff --git a/src/app/tools/ink_processing.h b/src/app/tools/ink_processing.h index e6e1b8740..3671f1a22 100644 --- a/src/app/tools/ink_processing.h +++ b/src/app/tools/ink_processing.h @@ -648,6 +648,51 @@ private: bool m_left; }; +////////////////////////////////////////////////////////////////////// +// Xor Ink +////////////////////////////////////////////////////////////////////// + +template +class XorInkProcessing : public DoubleInkProcessing, ImageTraits> { +public: + XorInkProcessing(ToolLoop* loop) { } + void processPixel(int x, int y) { + // Do nothing + } +}; + +template<> +void XorInkProcessing::processPixel(int x, int y) { + *m_dstAddress = rgba_blend_blackandwhite(*m_srcAddress, 0, 255); +} + +template<> +void XorInkProcessing::processPixel(int x, int y) { + *m_dstAddress = graya_blend_blackandwhite(*m_srcAddress, 0, 255); +} + +template<> +class XorInkProcessing : public DoubleInkProcessing, IndexedTraits> { +public: + XorInkProcessing(ToolLoop* loop) : + m_palette(get_current_palette()), + m_rgbmap(loop->getRgbMap()), + m_color(m_palette->getEntry(loop->getPrimaryColor())) { + } + + void processPixel(int x, int y) { + color_t c = rgba_blend_blackandwhite(m_palette->getEntry(*m_srcAddress), m_color, 255); + *m_dstAddress = m_rgbmap->mapColor(rgba_getr(c), + rgba_getg(c), + rgba_getb(c)); + } + +private: + const Palette* m_palette; + const RgbMap* m_rgbmap; + color_t m_color; +}; + ////////////////////////////////////////////////////////////////////// enum { @@ -659,6 +704,7 @@ enum { INK_REPLACE, INK_JUMBLE, INK_SHADING, + INK_XOR, MAX_INKS }; @@ -672,7 +718,7 @@ void ink_processing_algo(int x1, int y, int x2, void* data) AlgoHLine ink_processing[][3] = { -#define DEFINE_INK(name) \ +#define DEFINE_INK(name) \ { ink_processing_algo >, \ ink_processing_algo >, \ ink_processing_algo > } @@ -684,7 +730,8 @@ AlgoHLine ink_processing[][3] = DEFINE_INK(BlurInkProcessing), DEFINE_INK(ReplaceInkProcessing), DEFINE_INK(JumbleInkProcessing), - DEFINE_INK(ShadingInkProcessing) + DEFINE_INK(ShadingInkProcessing), + DEFINE_INK(XorInkProcessing) }; } // anonymous namespace diff --git a/src/app/tools/inks.h b/src/app/tools/inks.h index 7f9726d2e..78ccec98d 100644 --- a/src/app/tools/inks.h +++ b/src/app/tools/inks.h @@ -278,7 +278,8 @@ public: } // TODO show the selection-preview with a XOR color or something like that else { - draw_hline(loop->getDstImage(), x1, y, x2, loop->getPrimaryColor()); + ink_processing[INK_XOR][MID(0, loop->sprite()->pixelFormat(), 2)] + (x1, y, x2, loop); } } diff --git a/src/app/tools/tool_loop_manager.cpp b/src/app/tools/tool_loop_manager.cpp index 535b59ff6..d2ef0f803 100644 --- a/src/app/tools/tool_loop_manager.cpp +++ b/src/app/tools/tool_loop_manager.cpp @@ -72,8 +72,9 @@ void ToolLoopManager::prepareLoop(const Pointer& pointer) // Prepare preview image (the destination image will be our preview // in the tool-loop time, so we can see what we are drawing) - RenderEngine::setPreviewImage(m_toolLoop->getLayer(), - m_toolLoop->getDstImage()); + RenderEngine::setPreviewImage( + m_toolLoop->getLayer(), + m_toolLoop->getDstImage()); } void ToolLoopManager::releaseLoop(const Pointer& pointer) diff --git a/src/app/ui/editor/drawing_state.cpp b/src/app/ui/editor/drawing_state.cpp index aca4b629b..bb1d955d1 100644 --- a/src/app/ui/editor/drawing_state.cpp +++ b/src/app/ui/editor/drawing_state.cpp @@ -32,6 +32,7 @@ #include "app/tools/tool_loop_manager.h" #include "app/ui/editor/editor.h" #include "app/ui_context.h" +#include "raster/blend.h" #include "ui/message.h" #include "ui/system.h" diff --git a/src/app/ui/editor/tool_loop_impl.cpp b/src/app/ui/editor/tool_loop_impl.cpp index 34cb289c9..e57b15b60 100644 --- a/src/app/ui/editor/tool_loop_impl.cpp +++ b/src/app/ui/editor/tool_loop_impl.cpp @@ -151,7 +151,10 @@ public: brush_settings->getSize(), brush_settings->getAngle()); - m_useMask = m_document->isMaskVisible(); + if (m_ink->isSelection()) + m_useMask = false; + else + m_useMask = m_document->isMaskVisible(); // Selection ink if (getInk()->isSelection() && diff --git a/src/app/util/render.cpp b/src/app/util/render.cpp index a1467466c..8b8b367d4 100644 --- a/src/app/util/render.cpp +++ b/src/app/util/render.cpp @@ -289,7 +289,8 @@ static app::Color checked_bg_color2; static int global_opacity = 255; static const Layer* selected_layer = NULL; -static Image* rastering_image = NULL; +static Image* preview_image = NULL; +static int preview_blendmode = BLEND_MODE_NORMAL; // static void RenderEngine::loadConfig() @@ -370,7 +371,7 @@ RenderEngine::RenderEngine(const Document* document, void RenderEngine::setPreviewImage(const Layer* layer, Image* image) { selected_layer = layer; - rastering_image = image; + preview_image = image; } /** @@ -585,11 +586,11 @@ void RenderEngine::renderLayer( if (cel != NULL) { Image* src_image; - // Is the 'rastering_image' set to be used with this layer? + // Is the 'preview_image' set to be used with this layer? if ((frame == m_currentFrame) && (selected_layer == layer) && - (rastering_image != NULL)) { - src_image = rastering_image; + (preview_image != NULL)) { + src_image = preview_image; } // If not, we use the original cel-image from the images' stock else { @@ -608,9 +609,9 @@ void RenderEngine::renderLayer( (cel->x() << zoom) - source_x, (cel->y() << zoom) - source_y, output_opacity, - blend_mode < 0 ? + (blend_mode < 0 ? static_cast(layer)->getBlendMode(): - blend_mode, + blend_mode), zoom); } } @@ -642,9 +643,10 @@ void RenderEngine::renderLayer( Image* extraImage = m_document->getExtraCelImage(); (*zoomed_func)(image, extraImage, m_sprite->getPalette(frame), - (extraCel->x() << zoom) - source_x, - (extraCel->y() << zoom) - source_y, - extraCel->opacity(), BLEND_MODE_NORMAL, zoom); + (extraCel->x() << zoom) - source_x, + (extraCel->y() << zoom) - source_y, + extraCel->opacity(), + m_document->getExtraCelBlendMode(), zoom); } } } diff --git a/src/raster/blend.cpp b/src/raster/blend.cpp index 5a1cf08c2..c80fc31b7 100644 --- a/src/raster/blend.cpp +++ b/src/raster/blend.cpp @@ -32,6 +32,7 @@ BLEND_COLOR rgba_blenders[] = rgba_blend_merge, rgba_blend_red_tint, rgba_blend_blue_tint, + rgba_blend_blackandwhite, }; BLEND_COLOR graya_blenders[] = @@ -41,6 +42,7 @@ BLEND_COLOR graya_blenders[] = graya_blend_copy, graya_blend_copy, graya_blend_copy, + graya_blend_blackandwhite, }; /**********************************************************************/ @@ -195,6 +197,24 @@ int rgba_blend_blue_tint(int back, int front, int opacity) return rgba_blend_color_tint(back, front, opacity, rgba(0, 0, 255, 128)); } +int rgba_blend_blackandwhite(int back, int front, int opacity) +{ + int B_r, B_g, B_b, B_a; + int D_v; + + B_r = rgba_getr(back); + B_g = rgba_getg(back); + B_b = rgba_getb(back); + B_a = rgba_geta(back); + + if ((B_r*30 + B_g*59 + B_b*11)/100 < 128) + D_v = 255; + else + D_v = 0; + + return rgba(D_v, D_v, D_v, B_a); +} + /**********************************************************************/ /* Grayscale blenders */ /**********************************************************************/ @@ -272,4 +292,20 @@ int graya_blend_merge(int back, int front, int opacity) return graya(D_k, D_a); } +int graya_blend_blackandwhite(int back, int front, int opacity) +{ + int B_k, B_a; + int D_k; + + B_k = graya_getv(back); + B_a = graya_geta(back); + + if (B_k < 128) + D_k = 255; + else + D_k = 0; + + return graya(D_k, B_a); +} + } // namespace raster diff --git a/src/raster/blend.h b/src/raster/blend.h index 358b328b8..83aa45944 100644 --- a/src/raster/blend.h +++ b/src/raster/blend.h @@ -31,6 +31,7 @@ namespace raster { BLEND_MODE_MERGE, BLEND_MODE_RED_TINT, BLEND_MODE_BLUE_TINT, + BLEND_MODE_BLACKANDWHITE, BLEND_MODE_MAX, }; @@ -45,11 +46,13 @@ namespace raster { int rgba_blend_merge(int back, int front, int opacity); int rgba_blend_red_tint(int back, int front, int opacity); int rgba_blend_blue_tint(int back, int front, int opacity); + int rgba_blend_blackandwhite(int back, int front, int opacity); int graya_blend_normal(int back, int front, int opacity); int graya_blend_copy(int back, int front, int opacity); int graya_blend_forpath(int back, int front, int opacity); int graya_blend_merge(int back, int front, int opacity); + int graya_blend_blackandwhite(int back, int front, int opacity); } // namespace raster