bool CropSpriteCommand::onEnabled(Context* context) { return context->checkFlags( ContextFlags::ActiveDocumentIsWritable | (m_bounds.isEmpty() ? ContextFlags::HasVisibleMask: 0)); }
ClearRect::ClearRect(Cel* cel, const gfx::Rect& bounds) { app::Document* doc = static_cast<app::Document*>(cel->document()); Image* image = (cel ? cel->image(): NULL); if (!image) return; m_offsetX = bounds.x - cel->x(); m_offsetY = bounds.y - cel->y(); gfx::Rect bounds2 = image->bounds().createIntersection( gfx::Rect( m_offsetX, m_offsetY, bounds.w, bounds.h)); if (bounds.isEmpty()) return; m_dstImage.reset(new WithImage(image)); m_bgcolor = doc->bgColor(cel->layer()); m_copy.reset(crop_image(image, bounds2.x, bounds2.y, bounds2.w, bounds2.h, m_bgcolor)); }
void CropSpriteCommand::onExecute(Context* context) { ContextWriter writer(context); Document* document(writer.document()); Sprite* sprite(writer.sprite()); gfx::Rect bounds; if (m_bounds.isEmpty()) bounds = document->mask()->bounds(); else bounds = m_bounds; { Transaction transaction(writer.context(), "Sprite Crop"); document->getApi(transaction).cropSprite(sprite, bounds); transaction.commit(); } document->generateMaskBoundaries(); update_screen_for_document(document); }
void CropSpriteCommand::onExecute(Context* context) { ContextWriter writer(context); Doc* document(writer.document()); Sprite* sprite(writer.sprite()); gfx::Rect bounds; if (m_bounds.isEmpty()) bounds = document->mask()->bounds(); else bounds = m_bounds; { Tx tx(writer.context(), "Sprite Crop"); document->getApi(tx).cropSprite(sprite, bounds); tx.commit(); } #ifdef ENABLE_UI if (context->isUIAvailable()) update_screen_for_document(document); #endif }
bool shrink_bounds(Image *image, gfx::Rect& bounds, color_t refpixel) { bool shrink; int u, v; bounds = image->bounds(); // Shrink left side for (u=bounds.x; u<bounds.x+bounds.w; ++u) { shrink = true; for (v=bounds.y; v<bounds.y+bounds.h; ++v) { if (!is_same_pixel(image->pixelFormat(), image->getPixel(u, v), refpixel)) { shrink = false; break; } } if (!shrink) break; ++bounds.x; --bounds.w; } // Shrink right side for (u=bounds.x+bounds.w-1; u>=bounds.x; --u) { shrink = true; for (v=bounds.y; v<bounds.y+bounds.h; ++v) { if (!is_same_pixel(image->pixelFormat(), image->getPixel(u, v), refpixel)) { shrink = false; break; } } if (!shrink) break; --bounds.w; } // Shrink top side for (v=bounds.y; v<bounds.y+bounds.h; ++v) { shrink = true; for (u=bounds.x; u<bounds.x+bounds.w; ++u) { if (!is_same_pixel(image->pixelFormat(), image->getPixel(u, v), refpixel)) { shrink = false; break; } } if (!shrink) break; ++bounds.y; --bounds.h; } // Shrink bottom side for (v=bounds.y+bounds.h-1; v>=bounds.y; --v) { shrink = true; for (u=bounds.x; u<bounds.x+bounds.w; ++u) { if (!is_same_pixel(image->pixelFormat(), image->getPixel(u, v), refpixel)) { shrink = false; break; } } if (!shrink) break; --bounds.h; } return (!bounds.isEmpty()); }
void ExpandCelCanvas::commit(const gfx::Rect& bounds) { ASSERT(!m_closed); ASSERT(!m_committed); // If the size of each image is the same, we can create an undo // with only the differences between both images. if (m_cel->getX() == m_originalCelX && m_cel->getY() == m_originalCelY && m_celImage->getWidth() == m_dstImage->getWidth() && m_celImage->getHeight() == m_dstImage->getHeight()) { // Was m_celImage created in the start of the tool-loop?. if (m_celCreated) { // We can keep the m_celImage // We copy the destination image to the m_celImage copy_image(m_celImage, m_dstImage, 0, 0); // Add the m_celImage in the images stock of the sprite. m_cel->setImage(m_sprite->getStock()->addImage(m_celImage)); // 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->getStock(), m_cel->getImage())); 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); } } // If the m_celImage was already created before the whole process... else { // Add to the undo history the differences between m_celImage and m_dstImage if (m_undo.isEnabled()) { gfx::Rect dirtyBounds; if (bounds.isEmpty()) dirtyBounds = m_celImage->getBounds(); else dirtyBounds = m_celImage->getBounds().createIntersect(bounds); base::UniquePtr<Dirty> dirty(new Dirty(m_celImage, m_dstImage, dirtyBounds)); dirty->saveImagePixels(m_celImage); if (dirty != NULL) m_undo.pushUndoer(new undoers::DirtyArea(m_undo.getObjects(), m_celImage, dirty)); } // Copy the destination to the cel image. copy_image(m_celImage, m_dstImage, 0, 0); } } // If the size of both images are different, we have to // replace the entire image. else { if (m_undo.isEnabled()) { if (m_cel->getX() != m_originalCelX || m_cel->getY() != m_originalCelY) { int x = m_cel->getX(); int y = m_cel->getY(); m_cel->setPosition(m_originalCelX, m_originalCelY); m_undo.pushUndoer(new undoers::SetCelPosition(m_undo.getObjects(), m_cel)); m_cel->setPosition(x, y); } m_undo.pushUndoer(new undoers::ReplaceImage(m_undo.getObjects(), m_sprite->getStock(), m_cel->getImage())); } // Replace the image in the stock. m_sprite->getStock()->replaceImage(m_cel->getImage(), m_dstImage); // Destroy the old cel image. delete m_celImage; // Now the m_dstImage is used, so we haven't to destroy it. m_dstImage = NULL; } m_committed = true; }
void ToolLoopManager::calculateDirtyArea(const gfx::Rect& strokeBounds) { // Save the current dirty area if it's needed Region prevDirtyArea; if (m_toolLoop->getTracePolicy() == TracePolicy::Last) prevDirtyArea = m_dirtyArea; // Start with a fresh dirty area m_dirtyArea.clear(); if (!strokeBounds.isEmpty()) { // Expand the dirty-area with the pen width Rect r1, r2; m_toolLoop->getPointShape()->getModifiedArea( m_toolLoop, strokeBounds.x, strokeBounds.y, r1); m_toolLoop->getPointShape()->getModifiedArea( m_toolLoop, strokeBounds.x+strokeBounds.w-1, strokeBounds.y+strokeBounds.h-1, r2); m_dirtyArea.createUnion(m_dirtyArea, Region(r1.createUnion(r2))); } // Apply offset mode Point offset(m_toolLoop->getOffset()); m_dirtyArea.offset(-offset); // 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) if (m_toolLoop->getTracePolicy() == TracePolicy::Last) m_dirtyArea.createUnion(m_dirtyArea, prevDirtyArea); // Apply tiled mode TiledMode tiledMode = m_toolLoop->getTiledMode(); if (tiledMode != TiledMode::NONE) { int w = m_toolLoop->sprite()->width(); int h = m_toolLoop->sprite()->height(); Region sprite_area(Rect(0, 0, w, h)); Region outside; outside.createSubtraction(m_dirtyArea, sprite_area); switch (tiledMode) { case TiledMode::X_AXIS: outside.createIntersection(outside, Region(Rect(-w*10000, 0, w*20000, h))); break; case TiledMode::Y_AXIS: outside.createIntersection(outside, Region(Rect(0, -h*10000, w, h*20000))); break; } Rect outsideBounds = outside.bounds(); if (outsideBounds.x < 0) outside.offset(w * (1+((-outsideBounds.x) / w)), 0); if (outsideBounds.y < 0) outside.offset(0, h * (1+((-outsideBounds.y) / h))); int x1 = outside.bounds().x; while (true) { Region in_sprite; in_sprite.createIntersection(outside, sprite_area); outside.createSubtraction(outside, in_sprite); m_dirtyArea.createUnion(m_dirtyArea, in_sprite); outsideBounds = outside.bounds(); if (outsideBounds.isEmpty()) break; else if (outsideBounds.x+outsideBounds.w > w) outside.offset(-w, 0); else if (outsideBounds.y+outsideBounds.h > h) outside.offset(x1-outsideBounds.x, -h); else break; } } }