[aseprite] 100/128: Fix problems using paint bucket referring to all layers and cels origin != 0, 0

Tobias Hansen thansen at moszumanska.debian.org
Mon May 9 21:24:28 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 0f3dea233b4520b63ac7d58a4ec3a204cc5d2243
Author: David Capello <davidcapello at gmail.com>
Date:   Wed May 4 00:02:56 2016 -0300

    Fix problems using paint bucket referring to all layers and cels origin != 0,0
    
    With this change we've simplified several portions of the ToolLoop code
    where the "cel origin" is added and then subtracted needlessly.
---
 src/app/tools/ink.h                  |   5 ++
 src/app/tools/inks.h                 |  12 ++--
 src/app/tools/intertwine.cpp         |   8 +--
 src/app/tools/point_shape.cpp        |  11 +++-
 src/app/tools/point_shapes.h         |  17 ++----
 src/app/tools/tool_loop_manager.cpp  |  16 ++----
 src/app/ui/editor/brush_preview.cpp  |   4 +-
 src/app/ui/editor/tool_loop_impl.cpp | 107 ++++++++++++++++++++---------------
 8 files changed, 99 insertions(+), 81 deletions(-)

diff --git a/src/app/tools/ink.h b/src/app/tools/ink.h
index c2325d3..91b46d4 100644
--- a/src/app/tools/ink.h
+++ b/src/app/tools/ink.h
@@ -66,6 +66,11 @@ namespace app {
       // Returns true if this ink is used to mark slices
       virtual bool isSlice() const { return false; }
 
+      // Returns true if inkHline() needs source cel coordinates
+      // instead of sprite coordinates (i.e. relative to
+      // ToolLoop::getCelOrigin()).
+      virtual bool needsCelCoordinates() const { return true; }
+
       // Returns true if this ink needs a special source area.  For
       // example, blur tool needs one extra pixel to all sides of the
       // modified area, so it can use a 3x3 convolution matrix.
diff --git a/src/app/tools/inks.h b/src/app/tools/inks.h
index 4d1d61d..8c0a1e9 100644
--- a/src/app/tools/inks.h
+++ b/src/app/tools/inks.h
@@ -173,6 +173,8 @@ public:
   Ink* clone() override { return new SliceInk(*this); }
 
   bool isSlice() const override { return true; }
+  bool needsCelCoordinates() const override { return false; }
+
   void prepareInk(ToolLoop* loop) override { }
   void inkHline(int x1, int y, int x2, ToolLoop* loop) override {
     // TODO show the selection-preview with a XOR color or something like that
@@ -319,21 +321,23 @@ public:
   Ink* clone() override { return new SelectionInk(*this); }
 
   bool isSelection() const override { return true; }
+  bool needsCelCoordinates() const override {
+    return (m_modify_selection ? false: true);
+  }
 
   void inkHline(int x1, int y, int x2, ToolLoop* loop) override {
     if (m_modify_selection) {
       int modifiers = int(loop->getModifiers());
-      Point origin = loop->getCelOrigin();
 
       if ((modifiers & (int(ToolLoopModifiers::kReplaceSelection) |
                         int(ToolLoopModifiers::kAddSelection))) != 0) {
-        m_mask.add(gfx::Rect(x1+origin.x, y+origin.y, x2-x1+1, 1));
+        m_mask.add(gfx::Rect(x1, y, x2-x1+1, 1));
       }
       else if ((modifiers & int(ToolLoopModifiers::kSubtractSelection)) != 0) {
-        m_mask.subtract(gfx::Rect(x1+origin.x, y+origin.y, x2-x1+1, 1));
+        m_mask.subtract(gfx::Rect(x1, y, x2-x1+1, 1));
       }
 
-      m_maxBounds |= gfx::Rect(x1+origin.x, y+origin.y, x2-x1+1, 1);
+      m_maxBounds |= gfx::Rect(x1, y, x2-x1+1, 1);
     }
     // TODO show the selection-preview with a XOR color or something like that
     else {
diff --git a/src/app/tools/intertwine.cpp b/src/app/tools/intertwine.cpp
index ce918b3..75bec16 100644
--- a/src/app/tools/intertwine.cpp
+++ b/src/app/tools/intertwine.cpp
@@ -27,12 +27,10 @@ void Intertwine::doPointshapePoint(int x, int y, ToolLoop* loop)
 {
   Symmetry* symmetry = loop->getSymmetry();
   if (symmetry) {
-    Point origin(loop->getCelOrigin());
-
     // Convert the point to the sprite position so we can apply the
     // symmetry transformation.
     Stroke main_stroke;
-    main_stroke.addPoint(Point(x, y) + origin);
+    main_stroke.addPoint(Point(x, y));
 
     Strokes strokes;
     symmetry->generateStrokes(main_stroke, strokes, loop);
@@ -40,9 +38,7 @@ void Intertwine::doPointshapePoint(int x, int y, ToolLoop* loop)
       // We call transformPoint() moving back each point to the cel
       // origin.
       loop->getPointShape()->transformPoint(
-        loop,
-        stroke[0].x - origin.x,
-        stroke[0].y - origin.y);
+        loop, stroke[0].x, stroke[0].y);
     }
   }
   else {
diff --git a/src/app/tools/point_shape.cpp b/src/app/tools/point_shape.cpp
index a7326c0..ab49291 100644
--- a/src/app/tools/point_shape.cpp
+++ b/src/app/tools/point_shape.cpp
@@ -27,13 +27,22 @@ void PointShape::doInkHline(int x1, int y, int x2, ToolLoop* loop)
   TiledMode tiledMode = loop->getTiledMode();
   int x, w, size; // width or height
 
+  // In case the ink needs original cel coordinates, we have to
+  // translate the x1/y/x2 coordinate.
+  if (loop->getInk()->needsCelCoordinates()) {
+    gfx::Point origin = loop->getCelOrigin();
+    x1 -= origin.x;
+    x2 -= origin.x;
+    y -= origin.y;
+  }
+
   // Tiled in Y axis
   if (int(tiledMode) & int(TiledMode::Y_AXIS)) {
     size = loop->getDstImage()->height();      // size = image height
     y = wrap_value(y, size);
   }
   else if (y < 0 || y >= loop->getDstImage()->height())
-      return;
+    return;
 
   // Tiled in X axis
   if (int(tiledMode) & int(TiledMode::X_AXIS)) {
diff --git a/src/app/tools/point_shapes.h b/src/app/tools/point_shapes.h
index 61bf874..6398cec 100644
--- a/src/app/tools/point_shapes.h
+++ b/src/app/tools/point_shapes.h
@@ -52,14 +52,14 @@ public:
       if (m_brush->type() == kImageBrushType) {
         if (m_brush->pattern() == BrushPattern::ALIGNED_TO_DST ||
             m_brush->pattern() == BrushPattern::PAINT_BRUSH) {
-          m_brush->setPatternOrigin(gfx::Point(x, y)+loop->getCelOrigin());
+          m_brush->setPatternOrigin(gfx::Point(x, y));
         }
       }
     }
     else {
       if (m_brush->type() == kImageBrushType &&
           m_brush->pattern() == BrushPattern::PAINT_BRUSH) {
-        m_brush->setPatternOrigin(gfx::Point(x, y)+loop->getCelOrigin());
+        m_brush->setPatternOrigin(gfx::Point(x, y));
       }
     }
 
@@ -98,13 +98,8 @@ public:
 
 private:
   gfx::Rect floodfillBounds(ToolLoop* loop, int x, int y) const {
-    gfx::Point origin = loop->getCelOrigin();
-    gfx::Rect bounds(-origin.x, -origin.y,
-                     loop->sprite()->width(),
-                     loop->sprite()->height());
-
-    bounds = bounds.createIntersection(
-      loop->getFloodFillSrcImage()->bounds());
+    gfx::Rect bounds = loop->sprite()->bounds();
+    bounds &= loop->getFloodFillSrcImage()->bounds();
 
     // Limit the flood-fill to the current tile if the grid is visible.
     if (loop->getStopAtGrid()) {
@@ -112,8 +107,8 @@ private:
       if (!grid.isEmpty()) {
         div_t d, dx, dy;
 
-        dx = div(grid.x-origin.x, grid.w);
-        dy = div(grid.y-origin.y, grid.h);
+        dx = div(grid.x, grid.w);
+        dy = div(grid.y, grid.h);
 
         if (dx.rem > 0) dx.rem -= grid.w;
         if (dy.rem > 0) dy.rem -= grid.h;
diff --git a/src/app/tools/tool_loop_manager.cpp b/src/app/tools/tool_loop_manager.cpp
index 06f2da7..f05ed4d 100644
--- a/src/app/tools/tool_loop_manager.cpp
+++ b/src/app/tools/tool_loop_manager.cpp
@@ -188,9 +188,6 @@ void ToolLoopManager::doLoopStep(bool last_step)
 
   m_toolLoop->validateDstImage(m_dirtyArea);
 
-  // Move the stroke to be relative to the cel origin.
-  main_stroke.offset(-m_toolLoop->getCelOrigin());
-
   // Join or fill user points
   if (!m_toolLoop->getFilled() || (!last_step && !m_toolLoop->getPreviewFilled()))
     m_toolLoop->getIntertwine()->joinStroke(m_toolLoop, main_stroke);
@@ -229,8 +226,6 @@ void ToolLoopManager::calculateDirtyArea(const Strokes& strokes)
   // Start with a fresh dirty area
   m_dirtyArea.clear();
 
-  const Point celOrigin = m_toolLoop->getCelOrigin();
-
   for (auto& stroke : strokes) {
     gfx::Rect strokeBounds = stroke.bounds();
     if (strokeBounds.isEmpty())
@@ -241,20 +236,17 @@ void ToolLoopManager::calculateDirtyArea(const Strokes& strokes)
 
     m_toolLoop->getPointShape()->getModifiedArea(
       m_toolLoop,
-      strokeBounds.x - celOrigin.x,
-      strokeBounds.y - celOrigin.y, r1);
+      strokeBounds.x,
+      strokeBounds.y, r1);
 
     m_toolLoop->getPointShape()->getModifiedArea(
       m_toolLoop,
-      strokeBounds.x+strokeBounds.w-1 - celOrigin.x,
-      strokeBounds.y+strokeBounds.h-1 - celOrigin.y, r2);
+      strokeBounds.x+strokeBounds.w-1,
+      strokeBounds.y+strokeBounds.h-1, r2);
 
     m_dirtyArea.createUnion(m_dirtyArea, Region(r1.createUnion(r2)));
   }
 
-  // Make the dirty area relative to the sprite.
-  m_dirtyArea.offset(celOrigin);
-
   // Merge new dirty area with the previous one (for tools like line
   // or rectangle it's needed to redraw the previous position and
   // the new one)
diff --git a/src/app/ui/editor/brush_preview.cpp b/src/app/ui/editor/brush_preview.cpp
index 92f9663..02b6955 100644
--- a/src/app/ui/editor/brush_preview.cpp
+++ b/src/app/ui/editor/brush_preview.cpp
@@ -209,7 +209,9 @@ void BrushPreview::show(const gfx::Point& screenPos)
         loop->getIntertwine()->prepareIntertwine();
         loop->getPointShape()->preparePointShape(loop);
         loop->getPointShape()->transformPoint(
-          loop, -origBrushBounds.x, -origBrushBounds.y);
+          loop,
+          brushBounds.x-origBrushBounds.x,
+          brushBounds.y-origBrushBounds.y);
       }
     }
 
diff --git a/src/app/ui/editor/tool_loop_impl.cpp b/src/app/ui/editor/tool_loop_impl.cpp
index 9ebd43f..0843149 100644
--- a/src/app/ui/editor/tool_loop_impl.cpp
+++ b/src/app/ui/editor/tool_loop_impl.cpp
@@ -269,7 +269,7 @@ class ToolLoopImpl : public ToolLoopBase {
   gfx::Point m_maskOrigin;
   bool m_canceled;
   Transaction m_transaction;
-  ExpandCelCanvas m_expandCelCanvas;
+  ExpandCelCanvas* m_expandCelCanvas;
   Image* m_floodfillSrcImage;
 
 public:
@@ -294,23 +294,58 @@ public:
                       getInk()->isSlice() ||
                       getInk()->isZoom()) ? DoesntModifyDocument:
                                             ModifyDocument))
-    , m_expandCelCanvas(
-        editor->getSite(),
-        layer,
-        m_docPref.tiled.mode(),
-        m_transaction,
-        ExpandCelCanvas::Flags(
-          ExpandCelCanvas::NeedsSource |
-          // If the tool is freehand-like, we can use the modified
-          // region directly as undo information to save the modified
-          // pixels (it's faster than creating a Dirty object).
-          // See ExpandCelCanvas::commit() for details about this flag.
-          (getController()->isFreehand() ?
-            ExpandCelCanvas::UseModifiedRegionAsUndoInfo:
-            ExpandCelCanvas::None)))
+    , m_expandCelCanvas(nullptr)
+    , m_floodfillSrcImage(nullptr)
   {
     ASSERT(m_context->activeDocument() == m_editor->document());
 
+    if (m_pointShape->isFloodFill()) {
+      // Prepare a special image for floodfill when it's configured to
+      // stop using all visible layers.
+      if (m_toolPref.floodfill.referTo() == gen::FillReferTo::ALL_LAYERS) {
+        m_floodfillSrcImage = Image::create(m_sprite->pixelFormat(),
+                                            m_sprite->width(),
+                                            m_sprite->height());
+
+        m_floodfillSrcImage->clear(m_sprite->transparentColor());
+
+        render::Render().renderSprite(
+          m_floodfillSrcImage,
+          m_sprite,
+          m_frame,
+          gfx::Clip(m_sprite->bounds()),
+          render::Zoom(1, 1));
+      }
+      else {
+        Cel* cel = m_layer->cel(m_frame);
+        if (cel && (cel->x() != 0 || cel->y() != 0)) {
+          m_floodfillSrcImage = Image::create(m_sprite->pixelFormat(),
+                                              m_sprite->width(),
+                                              m_sprite->height());
+          m_floodfillSrcImage->clear(m_sprite->transparentColor());
+          copy_image(m_floodfillSrcImage, cel->image(), cel->x(), cel->y());
+        }
+      }
+    }
+
+    m_expandCelCanvas = new ExpandCelCanvas(
+      editor->getSite(),
+      layer,
+      m_docPref.tiled.mode(),
+      m_transaction,
+      ExpandCelCanvas::Flags(
+        ExpandCelCanvas::NeedsSource |
+        // If the tool is freehand-like, we can use the modified
+        // region directly as undo information to save the modified
+        // pixels (it's faster than creating a Dirty object).
+        // See ExpandCelCanvas::commit() for details about this flag.
+        (getController()->isFreehand() ?
+         ExpandCelCanvas::UseModifiedRegionAsUndoInfo:
+         ExpandCelCanvas::None)));
+
+    if (!m_floodfillSrcImage)
+      m_floodfillSrcImage = const_cast<Image*>(getSrcImage());
+
     // Settings
     switch (tool->getFill(m_button)) {
       case tools::FillNone:
@@ -341,37 +376,17 @@ public:
       m_transaction.execute(new cmd::SetMask(m_document, &emptyMask));
     }
 
-    m_celOrigin = m_expandCelCanvas.getCel()->position();
+    m_celOrigin = m_expandCelCanvas->getCel()->position();
     m_mask = m_document->mask();
     m_maskOrigin = (!m_mask->isEmpty() ? gfx::Point(m_mask->bounds().x-m_celOrigin.x,
                                                     m_mask->bounds().y-m_celOrigin.y):
                                          gfx::Point(0, 0));
-
-    // Prepare a special image for floodfill when it's configured to
-    // stop using all visible layers.
-    if (m_pointShape->isFloodFill() &&
-        m_toolPref.floodfill.referTo() == gen::FillReferTo::ALL_LAYERS) {
-      m_floodfillSrcImage = Image::create(m_sprite->pixelFormat(),
-                                          m_sprite->width(),
-                                          m_sprite->height());
-
-      m_floodfillSrcImage->clear(m_sprite->transparentColor());
-
-      render::Render().renderSprite(
-        m_floodfillSrcImage,
-        m_sprite,
-        m_frame,
-        gfx::Clip(m_sprite->bounds()),
-        render::Zoom(1, 1));
-    }
-    else {
-      m_floodfillSrcImage = const_cast<Image*>(getSrcImage());
-    }
   }
 
   ~ToolLoopImpl() {
     if (m_floodfillSrcImage != getSrcImage())
       delete m_floodfillSrcImage;
+    delete m_expandCelCanvas;
   }
 
   // IToolLoop interface
@@ -385,7 +400,7 @@ public:
         try {
           ContextReader reader(m_context, 500);
           ContextWriter writer(reader, 500);
-          m_expandCelCanvas.commit();
+          m_expandCelCanvas->commit();
         }
         catch (const LockedDocumentException& ex) {
           Console::showException(ex);
@@ -410,7 +425,7 @@ public:
       try {
         ContextReader reader(m_context, 500);
         ContextWriter writer(reader, 500);
-        m_expandCelCanvas.rollback();
+        m_expandCelCanvas->rollback();
       }
       catch (const LockedDocumentException& ex) {
         Console::showException(ex);
@@ -421,23 +436,23 @@ public:
       update_screen_for_document(m_document);
   }
 
-  const Image* getSrcImage() override { return m_expandCelCanvas.getSourceCanvas(); }
+  const Image* getSrcImage() override { return m_expandCelCanvas->getSourceCanvas(); }
   const Image* getFloodFillSrcImage() override { return m_floodfillSrcImage; }
-  Image* getDstImage() override { return m_expandCelCanvas.getDestCanvas(); }
+  Image* getDstImage() override { return m_expandCelCanvas->getDestCanvas(); }
   void validateSrcImage(const gfx::Region& rgn) override {
-    m_expandCelCanvas.validateSourceCanvas(rgn);
+    m_expandCelCanvas->validateSourceCanvas(rgn);
   }
   void validateDstImage(const gfx::Region& rgn) override {
-    m_expandCelCanvas.validateDestCanvas(rgn);
+    m_expandCelCanvas->validateDestCanvas(rgn);
   }
   void invalidateDstImage() override {
-    m_expandCelCanvas.invalidateDestCanvas();
+    m_expandCelCanvas->invalidateDestCanvas();
   }
   void invalidateDstImage(const gfx::Region& rgn) override {
-    m_expandCelCanvas.invalidateDestCanvas(rgn);
+    m_expandCelCanvas->invalidateDestCanvas(rgn);
   }
   void copyValidDstToSrcImage(const gfx::Region& rgn) override {
-    m_expandCelCanvas.copyValidDestToSourceCanvas(rgn);
+    m_expandCelCanvas->copyValidDestToSourceCanvas(rgn);
   }
 
   bool useMask() override { return m_useMask; }

-- 
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