[aseprite] 36/51: Fix several bugs applying filters to cels smaller than the sprite bounds

Tobias Hansen thansen at moszumanska.debian.org
Mon Jul 11 21:35:18 UTC 2016


This is an automated email from the git hooks/post-receive script.

thansen pushed a commit to branch master
in repository aseprite.

commit d56660420515a49a966361a1c8671ef35818b9b2
Author: David Capello <davidcapello at gmail.com>
Date:   Fri Jul 1 18:49:58 2016 -0300

    Fix several bugs applying filters to cels smaller than the sprite bounds
    
    Now if we apply a 3x3 (or bigger) convolution matrix to a cel, the cel
    will be expanded to so new pixels are included in the new cel content.
---
 src/app/commands/filters/filter_manager_impl.cpp | 112 ++++++++++-------------
 src/app/commands/filters/filter_manager_impl.h   |  16 ++--
 src/app/commands/filters/filter_preview.cpp      |   1 +
 src/app/ui/editor/drawing_state.cpp              |   1 +
 src/render/render.cpp                            |  46 ++++++----
 src/render/render.h                              |  14 ++-
 6 files changed, 95 insertions(+), 95 deletions(-)

diff --git a/src/app/commands/filters/filter_manager_impl.cpp b/src/app/commands/filters/filter_manager_impl.cpp
index 61a2fc5..9ad408e 100644
--- a/src/app/commands/filters/filter_manager_impl.cpp
+++ b/src/app/commands/filters/filter_manager_impl.cpp
@@ -20,6 +20,7 @@
 #include "app/modules/editors.h"
 #include "app/transaction.h"
 #include "app/ui/editor/editor.h"
+#include "doc/algorithm/shrink_bounds.h"
 #include "doc/cel.h"
 #include "doc/image.h"
 #include "doc/images_collector.h"
@@ -45,15 +46,14 @@ FilterManagerImpl::FilterManagerImpl(Context* context, Filter* filter)
   : m_context(context)
   , m_site(context->activeSite())
   , m_filter(filter)
+  , m_cel(nullptr)
   , m_src(nullptr)
   , m_dst(nullptr)
+  , m_mask(nullptr)
   , m_previewMask(nullptr)
   , m_progressDelegate(NULL)
 {
   m_row = 0;
-  m_celX = 0;
-  m_celY = 0;
-  m_mask = NULL;
   m_targetOrig = TARGET_ALL_CHANNELS;
   m_target = TARGET_ALL_CHANNELS;
 
@@ -62,11 +62,7 @@ FilterManagerImpl::FilterManagerImpl(Context* context, Filter* filter)
   if (!image)
     throw NoImageException();
 
-  init(m_site.layer(), image, x, y);
-}
-
-FilterManagerImpl::~FilterManagerImpl()
-{
+  init(m_site.cel());
 }
 
 app::Document* FilterManagerImpl::document()
@@ -100,9 +96,8 @@ void FilterManagerImpl::begin()
   Document* document = static_cast<app::Document*>(m_site.document());
 
   m_row = 0;
-  m_mask = (document->isMaskVisible() ? document->mask(): NULL);
-
-  updateBounds(m_mask, m_src);
+  m_mask = (document->isMaskVisible() ? document->mask(): nullptr);
+  updateBounds(m_mask);
 }
 
 void FilterManagerImpl::beginForPreview()
@@ -113,11 +108,7 @@ void FilterManagerImpl::beginForPreview()
     m_previewMask.reset(new Mask(*document->mask()));
   else {
     m_previewMask.reset(new Mask());
-    m_previewMask->replace(
-      gfx::Rect(
-        m_celX, m_celY,
-        m_src->width(),
-        m_src->height()));
+    m_previewMask->replace(m_site.sprite()->bounds());
   }
 
   m_row = 0;
@@ -139,7 +130,7 @@ void FilterManagerImpl::beginForPreview()
     m_previewMask->intersect(vp);
   }
 
-  if (!updateBounds(m_mask, m_src)) {
+  if (!updateBounds(m_mask)) {
     m_previewMask.reset(nullptr);
     m_row = -1;
     return;
@@ -156,12 +147,11 @@ bool FilterManagerImpl::applyStep()
   if (m_row < 0 || m_row >= m_bounds.h)
     return false;
 
-  if ((m_mask) && (m_mask->bitmap())) {
-    int x = m_bounds.x - m_mask->bounds().x + m_celX;
-    int y = m_bounds.y - m_mask->bounds().y + m_celY + m_row;
-
-    if ((m_bounds.w - x < 1) ||
-        (m_bounds.h - y < 1))
+  if (m_mask && m_mask->bitmap()) {
+    int x = m_bounds.x - m_mask->bounds().x;
+    int y = m_bounds.y - m_mask->bounds().y + m_row;
+    if ((x >= m_bounds.w) ||
+        (y >= m_bounds.h))
       return false;
 
     m_maskBits = m_mask->bitmap()
@@ -197,13 +187,16 @@ void FilterManagerImpl::apply(Transaction& transaction)
   }
 
   if (!cancelled) {
-    // Copy "dst" to "src"
-    transaction.execute(
-      new cmd::CopyRect(
-        m_src, m_dst.get(),
-        gfx::Clip(m_bounds.x, m_bounds.y,
-                  m_bounds.x, m_bounds.y,
-                  m_bounds.w, m_bounds.h)));
+    gfx::Rect output;
+    if (algorithm::shrink_bounds2(m_src.get(), m_dst.get(),
+                                  m_bounds, output)) {
+      // Patch "m_cel"
+      transaction.execute(
+        new cmd::PatchCel(
+          m_cel, m_dst.get(),
+          gfx::Region(output),
+          position()));
+    }
   }
 }
 
@@ -239,9 +232,7 @@ void FilterManagerImpl::applyToTarget()
     // Avoid applying the filter two times to the same image
     if (visited.find(image->id()) == visited.end()) {
       visited.insert(image->id());
-      applyToImage(
-        transaction, it->layer(),
-        image, it->cel()->x(), it->cel()->y());
+      applyToCel(transaction, it->cel());
     }
 
     // Is there a delegate to know if the process was cancelled by the user?
@@ -262,8 +253,8 @@ void FilterManagerImpl::flush()
     gfx::Rect rect(
       editor->editorToScreen(
         gfx::Point(
-          m_bounds.x+m_celX,
-          m_bounds.y+m_celY+m_row-1)),
+          m_bounds.x,
+          m_bounds.y+m_row-1)),
       gfx::Size(
         editor->zoom().apply(m_bounds.w),
         (editor->zoom().scale() >= 1 ? editor->zoom().apply(1):
@@ -280,12 +271,12 @@ void FilterManagerImpl::flush()
 
 const void* FilterManagerImpl::getSourceAddress()
 {
-  return m_src->getPixelAddress(m_bounds.x, m_row+m_bounds.y);
+  return m_src->getPixelAddress(m_bounds.x, m_bounds.y+m_row);
 }
 
 void* FilterManagerImpl::getDestinationAddress()
 {
-  return m_dst->getPixelAddress(m_bounds.x, m_row+m_bounds.y);
+  return m_dst->getPixelAddress(m_bounds.x, m_bounds.y+m_row);
 }
 
 bool FilterManagerImpl::skipPixel()
@@ -312,55 +303,48 @@ RgbMap* FilterManagerImpl::getRgbMap()
   return m_site.sprite()->rgbMap(m_site.frame());
 }
 
-void FilterManagerImpl::init(const Layer* layer, Image* image, int x, int y)
+void FilterManagerImpl::init(Cel* cel)
 {
-  m_celX = x;
-  m_celY = y;
-
-  if (!updateBounds(static_cast<app::Document*>(m_site.document())->mask(), image))
+  ASSERT(cel);
+  if (!updateBounds(static_cast<app::Document*>(m_site.document())->mask()))
     throw InvalidAreaException();
 
-  m_src = image;
-  m_dst.reset(Image::createCopy(m_src));
+  m_cel = cel;
+  m_src.reset(
+    crop_image(
+      cel->image(),
+      gfx::Rect(m_site.sprite()->bounds()).offset(-cel->position()), 0));
+  m_dst.reset(Image::createCopy(m_src.get()));
 
   m_row = -1;
-  m_mask = NULL;
+  m_mask = nullptr;
   m_previewMask.reset(nullptr);
 
   m_target = m_targetOrig;
 
-  /* the alpha channel of the background layer can't be modified */
-  if (layer->isBackground())
+  // The alpha channel of the background layer can't be modified
+  if (cel->layer()->isBackground())
     m_target &= ~TARGET_ALPHA_CHANNEL;
 }
 
-void FilterManagerImpl::applyToImage(Transaction& transaction, Layer* layer, Image* image, int x, int y)
+void FilterManagerImpl::applyToCel(Transaction& transaction, Cel* cel)
 {
-  init(layer, image, x, y);
+  init(cel);
   apply(transaction);
 }
 
-bool FilterManagerImpl::updateBounds(Mask* mask, const Image* image)
+bool FilterManagerImpl::updateBounds(doc::Mask* mask)
 {
   gfx::Rect bounds;
-
-  if (mask && mask->bitmap()) {
+  if (mask && mask->bitmap() && !mask->bounds().isEmpty()) {
     bounds = mask->bounds();
-    bounds.offset(-m_celX, -m_celY);
-    bounds &= image->bounds();
-  }
-  else {
-    bounds = image->bounds();
-  }
-
-  if (bounds.isEmpty()) {
-    m_bounds = gfx::Rect(0, 0, 0, 0);
-    return false;
+    bounds &= m_site.sprite()->bounds();
   }
   else {
-    m_bounds = bounds;
-    return true;
+    bounds = m_site.sprite()->bounds();
   }
+  m_bounds = bounds;
+  return !m_bounds.isEmpty();
 }
 
 } // namespace app
diff --git a/src/app/commands/filters/filter_manager_impl.h b/src/app/commands/filters/filter_manager_impl.h
index 3bf3685..47e4d31 100644
--- a/src/app/commands/filters/filter_manager_impl.h
+++ b/src/app/commands/filters/filter_manager_impl.h
@@ -17,10 +17,12 @@
 #include "doc/site.h"
 #include "filters/filter_indexed_data.h"
 #include "filters/filter_manager.h"
+#include "gfx/rect.h"
 
 #include <cstring>
 
 namespace doc {
+  class Cel;
   class Image;
   class Layer;
   class Mask;
@@ -68,7 +70,6 @@ namespace app {
     };
 
     FilterManagerImpl(Context* context, Filter* filter);
-    ~FilterManagerImpl();
 
     void setProgressDelegate(IProgressDelegate* progressDelegate);
 
@@ -87,6 +88,7 @@ namespace app {
     doc::Layer* layer() { return m_site.layer(); }
     doc::frame_t frame() { return m_site.frame(); }
     doc::Image* destinationImage() const { return m_dst.get(); }
+    gfx::Point position() const { return gfx::Point(0, 0); }
 
     // Updates the current editor to show the progress of the preview.
     void flush();
@@ -98,7 +100,7 @@ namespace app {
     Target getTarget() override { return m_target; }
     FilterIndexedData* getIndexedData() override { return this; }
     bool skipPixel() override;
-    const doc::Image* getSourceImage() override { return m_src; }
+    const doc::Image* getSourceImage() override { return m_src.get(); }
     int x() override { return m_bounds.x; }
     int y() override { return m_bounds.y+m_row; }
 
@@ -107,19 +109,19 @@ namespace app {
     doc::RgbMap* getRgbMap() override;
 
   private:
-    void init(const doc::Layer* layer, doc::Image* image, int x, int y);
+    void init(doc::Cel* cel);
     void apply(Transaction& transaction);
-    void applyToImage(Transaction& transaction, doc::Layer* layer, doc::Image* image, int x, int y);
-    bool updateBounds(doc::Mask* mask, const doc::Image* image);
+    void applyToCel(Transaction& transaction, doc::Cel* cel);
+    bool updateBounds(doc::Mask* mask);
 
     Context* m_context;
     doc::Site m_site;
     Filter* m_filter;
-    doc::Image* m_src;
+    doc::Cel* m_cel;
+    doc::ImageRef m_src;
     doc::ImageRef m_dst;
     int m_row;
     gfx::Rect m_bounds;
-    int m_celX, m_celY;
     doc::Mask* m_mask;
     base::UniquePtr<doc::Mask> m_previewMask;
     doc::ImageBits<doc::BitmapTraits> m_maskBits;
diff --git a/src/app/commands/filters/filter_preview.cpp b/src/app/commands/filters/filter_preview.cpp
index 41fc463..2e6e8ad 100644
--- a/src/app/commands/filters/filter_preview.cpp
+++ b/src/app/commands/filters/filter_preview.cpp
@@ -70,6 +70,7 @@ bool FilterPreview::onProcessMessage(Message* msg)
         m_filterMgr->layer(),
         m_filterMgr->frame(),
         m_filterMgr->destinationImage(),
+        m_filterMgr->position(),
         static_cast<doc::LayerImage*>(m_filterMgr->layer())->blendMode());
       break;
 
diff --git a/src/app/ui/editor/drawing_state.cpp b/src/app/ui/editor/drawing_state.cpp
index d8a75dd..775079e 100644
--- a/src/app/ui/editor/drawing_state.cpp
+++ b/src/app/ui/editor/drawing_state.cpp
@@ -63,6 +63,7 @@ void DrawingState::initToolLoop(Editor* editor, MouseMessage* msg)
     m_toolLoop->getLayer(),
     m_toolLoop->getFrame(),
     m_toolLoop->getDstImage(),
+    m_toolLoop->getCelOrigin(),
     (m_toolLoop->getLayer() &&
      m_toolLoop->getLayer()->isImage() ?
      static_cast<LayerImage*>(m_toolLoop->getLayer())->blendMode():
diff --git a/src/render/render.cpp b/src/render/render.cpp
index 0b98198..6ec6d7d 100644
--- a/src/render/render.cpp
+++ b/src/render/render.cpp
@@ -478,12 +478,16 @@ void Render::setBgCheckedSize(const gfx::Size& size)
   m_bgCheckedSize = size;
 }
 
-void Render::setPreviewImage(const Layer* layer, frame_t frame,
-                             Image* image, BlendMode blendMode)
+void Render::setPreviewImage(const Layer* layer,
+                             const frame_t frame,
+                             const Image* image,
+                             const gfx::Point& pos,
+                             const BlendMode blendMode)
 {
   m_selectedLayer = layer;
   m_selectedFrame = frame;
   m_previewImage = image;
+  m_previewPos = pos;
   m_previewBlendMode = blendMode;
 }
 
@@ -660,7 +664,8 @@ void Render::renderSprite(
       dstImage,
       m_previewImage,
       m_sprite->palette(frame),
-      0, 0,
+      m_previewPos.x,
+      m_previewPos.y,
       area,
       compositeImage,
       255,
@@ -843,24 +848,27 @@ void Render::renderLayer(
       const Cel* cel = layer->cel(frame);
       if (cel) {
         Palette* pal = m_sprite->palette(frame);
-        Image* src_image;
+        const Image* celImage;
+        gfx::Point celPos;
 
         // Is the 'm_previewImage' set to be used with this layer?
         if ((m_previewImage) &&
             (m_selectedLayer == layer) &&
             (m_selectedFrame == frame)) {
-          src_image = m_previewImage;
+          celImage = m_previewImage;
+          celPos = m_previewPos;
 
-          ASSERT(src_image->pixelFormat() == cel->image()->pixelFormat());
+          ASSERT(celImage->pixelFormat() == cel->image()->pixelFormat());
         }
         // If not, we use the original cel-image from the images' stock
         else {
-          src_image = cel->image();
+          celImage = cel->image();
+          celPos = cel->position();
         }
 
-        if (src_image) {
+        if (celImage) {
           const LayerImage* imgLayer = static_cast<const LayerImage*>(layer);
-          BlendMode layerBlendMode =
+          const BlendMode layerBlendMode =
             (blendMode == BlendMode::UNSPECIFIED ?
              imgLayer->blendMode():
              blendMode);
@@ -876,7 +884,7 @@ void Render::renderLayer(
           opacity = MUL_UN8(opacity, imgLayer->opacity(), t);
           opacity = MUL_UN8(opacity, m_globalOpacity, t);
 
-          ASSERT(src_image->maskColor() == m_sprite->transparentColor());
+          ASSERT(celImage->maskColor() == m_sprite->transparentColor());
 
           // Draw parts outside the "m_extraCel" area
           if (drawExtra && m_extraType == ExtraType::PATCH) {
@@ -886,17 +894,17 @@ void Render::renderLayer(
 
             for (auto rc : originalAreas) {
               renderCel(
-                image, src_image, pal,
-                cel, gfx::Clip(area.dst.x+rc.x-area.src.x,
-                               area.dst.y+rc.y-area.src.y, rc), compositeImage,
+                image, celImage, pal, celPos,
+                gfx::Clip(area.dst.x+rc.x-area.src.x,
+                          area.dst.y+rc.y-area.src.y, rc), compositeImage,
                 opacity, layerBlendMode, zoom);
             }
           }
           // Draw the whole cel
           else {
             renderCel(
-              image, src_image, pal,
-              cel, area, compositeImage,
+              image, celImage, pal,
+              celPos, area, compositeImage,
               opacity, layerBlendMode, zoom);
           }
         }
@@ -926,7 +934,7 @@ void Render::renderLayer(
       renderCel(
         image, m_extraImage,
         m_sprite->palette(frame),
-        m_extraCel,
+        m_extraCel->position(),
         gfx::Clip(area.dst.x+extraArea.x-area.src.x,
                   area.dst.y+extraArea.y-area.src.y,
                   extraArea),
@@ -941,7 +949,7 @@ void Render::renderCel(
   Image* dst_image,
   const Image* cel_image,
   const Palette* pal,
-  const Cel* cel,
+  const gfx::Point& celPos,
   const gfx::Clip& area,
   CompositeImageFunc compositeImage,
   int opacity, BlendMode blendMode, Zoom zoom)
@@ -949,8 +957,8 @@ void Render::renderCel(
   renderImage(dst_image,
               cel_image,
               pal,
-              cel->x(),
-              cel->y(),
+              celPos.x,
+              celPos.y,
               area,
               compositeImage,
               opacity,
diff --git a/src/render/render.h b/src/render/render.h
index 9c57447..936de70 100644
--- a/src/render/render.h
+++ b/src/render/render.h
@@ -13,7 +13,7 @@
 #include "doc/color.h"
 #include "doc/frame.h"
 #include "doc/pixel_format.h"
-#include "gfx/fwd.h"
+#include "gfx/point.h"
 #include "gfx/size.h"
 #include "render/extra_type.h"
 #include "render/onionskin_position.h"
@@ -111,8 +111,11 @@ namespace render {
 
     // Sets the preview image. This preview image is an alternative
     // image to be used for the given layer/frame.
-    void setPreviewImage(const Layer* layer, frame_t frame,
-                         Image* image, BlendMode blendMode);
+    void setPreviewImage(const Layer* layer,
+                         const frame_t frame,
+                         const Image* image,
+                         const gfx::Point& pos,
+                         const BlendMode blendMode);
     void removePreviewImage();
 
     // Sets an extra cel/image to be drawn after the current
@@ -190,7 +193,7 @@ namespace render {
       Image* dst_image,
       const Image* cel_image,
       const Palette* pal,
-      const Cel* cel,
+      const gfx::Point& celPos,
       const gfx::Clip& area,
       CompositeImageFunc compositeImage,
       int opacity, BlendMode blendMode, Zoom zoom);
@@ -221,7 +224,8 @@ namespace render {
     int m_globalOpacity;
     const Layer* m_selectedLayer;
     frame_t m_selectedFrame;
-    Image* m_previewImage;
+    const Image* m_previewImage;
+    gfx::Point m_previewPos;
     BlendMode m_previewBlendMode;
     OnionskinOptions m_onionskin;
   };

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-games/aseprite.git



More information about the Pkg-games-commits mailing list