예제 #1
0
void ExpandCelCanvas::commit()
{
  ASSERT(!m_closed);
  ASSERT(!m_committed);

  // Was the cel created in the start of the tool-loop?
  if (m_celCreated) {
    ASSERT(m_cel);
    ASSERT(!m_celImage);

    // Validate the whole m_dstImage (invalid areas are cleared, as we
    // don't have a m_celImage)
    validateDestCanvas(gfx::Region(m_bounds));

    // We can temporary remove the cel.
    static_cast<LayerImage*>(m_layer)->removeCel(m_cel);

    // Add a copy of m_dstImage in the sprite's image stock
    ImageRef newImage(Image::createCopy(m_dstImage.get()));
    m_cel->data()->setImage(newImage);

    // And finally we add the cel again in the layer.
    m_transaction.execute(new cmd::AddCel(m_layer, m_cel));
  }
  else if (m_celImage) {
    // If the size of each image is the same, we can create an undo
    // with only the differences between both images.
    if (m_cel->position() == m_origCelPos &&
        m_bounds.origin() == m_origCelPos &&
        m_celImage->width() == m_dstImage->width() &&
        m_celImage->height() == m_dstImage->height()) {
      int dx = -m_bounds.x + m_origCelPos.x;
      int dy = -m_bounds.y + m_origCelPos.y;

      if ((m_flags & UseModifiedRegionAsUndoInfo) != UseModifiedRegionAsUndoInfo) {
        // TODO Reduce m_validDstRegion to modified areas between
        //      m_celImage and m_dstImage
      }

      // Copy the destination to the cel image.
      m_transaction.execute(new cmd::CopyRegion(
          m_celImage.get(), m_dstImage.get(), m_validDstRegion, dx, dy));
    }
    // If the size of both images are different, we have to
    // replace the entire image.
    else {
      if (m_cel->position() != m_origCelPos) {
        gfx::Point newPos = m_cel->position();
        m_cel->setPosition(m_origCelPos);
        m_transaction.execute(new cmd::SetCelPosition(m_cel, newPos.x, newPos.y));
      }

      // Validate the whole m_dstImage copying invalid areas from m_celImage
      validateDestCanvas(gfx::Region(m_bounds));

      // Replace the image in the stock. We need to create a copy of
      // image because m_dstImage's ImageBuffer cannot be shared.
      ImageRef newImage(Image::createCopy(m_dstImage.get()));
      m_transaction.execute(new cmd::ReplaceImage(
          m_sprite, m_celImage, newImage));
    }
  }
  else {
    ASSERT(false);
  }

  m_committed = true;
}
예제 #2
0
void ExpandCelCanvas::commit()
{
  ASSERT(!m_closed);
  ASSERT(!m_committed);

  // Was the cel created in the start of the tool-loop?
  if (m_celCreated) {
    ASSERT(m_cel);
    ASSERT(!m_celImage);

    // Validate the whole m_dstImage (invalid areas are cleared, as we
    // don't have a m_celImage)
    validateDestCanvas(gfx::Region(m_bounds));

    // Add a copy of m_dstImage in the sprite's image stock
    m_cel->setImage(m_sprite->stock()->addImage(
        Image::createCopy(m_dstImage)));

    // Is the undo enabled?.
    if (m_undo.isEnabled()) {
      // We can temporary remove the cel.
      static_cast<LayerImage*>(m_layer)->removeCel(m_cel);

      // We create the undo information (for the new m_celImage
      // in the stock and the new cel in the layer)...
      m_undo.pushUndoer(new undoers::AddImage(m_undo.getObjects(),
          m_sprite->stock(), m_cel->imageIndex()));
      m_undo.pushUndoer(new undoers::AddCel(m_undo.getObjects(),
          m_layer, m_cel));

      // And finally we add the cel again in the layer.
      static_cast<LayerImage*>(m_layer)->addCel(m_cel);
    }
  }
  else if (m_celImage) {
    // If the size of each image is the same, we can create an undo
    // with only the differences between both images.
    if (m_cel->position() == m_origCelPos &&
        m_bounds.getOrigin() == m_origCelPos &&
        m_celImage->width() == m_dstImage->width() &&
        m_celImage->height() == m_dstImage->height()) {
      // Add to the undo history the differences between m_celImage and m_dstImage
      if (m_undo.isEnabled()) {
        if ((m_flags & UseModifiedRegionAsUndoInfo) == UseModifiedRegionAsUndoInfo) {
          m_undo.pushUndoer(new undoers::ModifiedRegion(
              m_undo.getObjects(), m_celImage, m_validDstRegion));
        }
        else {
          Dirty dirty(m_celImage, m_dstImage, m_validDstRegion);
          dirty.saveImagePixels(m_celImage);
          m_undo.pushUndoer(new undoers::DirtyArea(
              m_undo.getObjects(), m_celImage, &dirty));
        }
      }

      // Copy the destination to the cel image.
      copyValidDestToOriginalCel();
    }
    // If the size of both images are different, we have to
    // replace the entire image.
    else {
      if (m_undo.isEnabled()) {
        if (m_cel->position() != m_origCelPos) {
          gfx::Point newPos = m_cel->position();
          m_cel->setPosition(m_origCelPos);
          m_undo.pushUndoer(new undoers::SetCelPosition(m_undo.getObjects(), m_cel));
          m_cel->setPosition(newPos);
        }

        m_undo.pushUndoer(new undoers::ReplaceImage(m_undo.getObjects(),
            m_sprite->stock(), m_cel->imageIndex()));
      }

      // Validate the whole m_dstImage copying invalid areas from m_celImage
      validateDestCanvas(gfx::Region(m_bounds));

      // Replace the image in the stock. We need to create a copy of
      // image because m_dstImage's ImageBuffer cannot be shared.
      m_sprite->stock()->replaceImage(m_cel->imageIndex(),
        Image::createCopy(m_dstImage));

      // Destroy the old cel image.
      delete m_celImage;
    }
  }
  else {
    ASSERT(false);
  }

  m_committed = true;
}
예제 #3
0
void ExpandCelCanvas::commit()
{
  ASSERT(!m_closed);
  ASSERT(!m_committed);

  if (!m_layer) {
    m_committed = true;
    return;
  }

  // Was the cel created in the start of the tool-loop?
  if (m_celCreated) {
    ASSERT(m_cel);
    ASSERT(!m_celImage);

    // Validate the whole m_dstImage (invalid areas are cleared, as we
    // don't have a m_celImage)
    validateDestCanvas(gfx::Region(m_bounds));

    // We can temporary remove the cel.
    if (m_layer->isImage()) {
      static_cast<LayerImage*>(m_layer)->removeCel(m_cel);

      // Add a copy of m_dstImage in the sprite's image stock
      gfx::Rect trimBounds = getTrimDstImageBounds();
      if (!trimBounds.isEmpty()) {
        ImageRef newImage(trimDstImage(trimBounds));
        ASSERT(newImage);

        m_cel->data()->setImage(newImage);
        m_cel->setPosition(m_cel->position() + trimBounds.origin());

        // And finally we add the cel again in the layer.
        m_transaction.execute(new cmd::AddCel(m_layer, m_cel));
      }
    }
    // We are selecting inside a layer group...
    else {
      // Just delete the created layer
      delete m_cel;
      m_cel = nullptr;
    }
  }
  else if (m_celImage) {
    // Restore cel position to its original position
    m_cel->setPosition(m_origCelPos);

    ASSERT(m_cel->image() == m_celImage.get());

    gfx::Region* regionToPatch = &m_validDstRegion;
    gfx::Region reduced;

    if (m_canCompareSrcVsDst) {
      ASSERT(gfx::Region().createSubtraction(m_validDstRegion, m_validSrcRegion).isEmpty());

      for (gfx::Rect rc : m_validDstRegion) {
        if (algorithm::shrink_bounds2(getSourceCanvas(),
                                      getDestCanvas(), rc, rc)) {
          reduced |= gfx::Region(rc);
        }
      }

      regionToPatch = &reduced;
    }

    if (m_layer->isBackground()) {
      m_transaction.execute(
        new cmd::CopyRegion(
          m_cel->image(),
          m_dstImage.get(),
          *regionToPatch,
          m_bounds.origin()));
    }
    else {
      m_transaction.execute(
        new cmd::PatchCel(
          m_cel,
          m_dstImage.get(),
          *regionToPatch,
          m_bounds.origin()));
    }
  }
  else {
    ASSERT(false);
  }

  m_committed = true;
}