Fix problem redrawing eraser cursor when the brush size changes (fix #671)

This commit is contained in:
David Capello 2015-05-18 15:02:02 -03:00
parent 6c882e43d5
commit 70dd6806a9
4 changed files with 43 additions and 100 deletions

View File

@ -56,7 +56,9 @@ static struct {
int nseg;
BoundSeg* seg;
Image* brush_image;
} cursor_bound = { 0, nullptr, nullptr };
int brush_width;
int brush_height;
} cursor_bound = { 0, nullptr, nullptr, 0, 0 };
enum {
CURSOR_THINCROSS = 1,
@ -65,7 +67,7 @@ enum {
};
static int cursor_type = CURSOR_THINCROSS;
static int cursor_negative;
static bool cursor_negative;
static std::vector<gfx::Color> saved_pixel;
static int saved_pixel_n;
@ -171,12 +173,10 @@ void Editor::editor_cursor_exit()
base_free(cursor_bound.seg);
}
// Draws the brush cursor inside the specified editor.
// Warning: You should clean the cursor before to use
// this routine with other editor.
//
// Note: x and y params are absolute positions of the mouse.
void Editor::drawBrushPreview(const gfx::Point& pos, bool refresh)
// Draws the brush cursor in the specified absolute mouse position
// given in 'pos' param. Warning: You should clean the cursor before
// to use this routine with other editor.
void Editor::drawBrushPreview(const gfx::Point& pos)
{
ASSERT(!m_cursorOnScreen);
ASSERT(m_sprite);
@ -271,14 +271,13 @@ void Editor::drawBrushPreview(const gfx::Point& pos, bool refresh)
delete loop;
}
if (refresh) {
m_document->notifySpritePixelsModified
(m_sprite, gfx::Region(lastBrushBounds = brushBounds));
}
m_document->notifySpritePixelsModified(
m_sprite,
gfx::Region(lastBrushBounds = brushBounds));
}
// Save area and draw the cursor
if (refresh) {
{
ScreenGraphics g;
SetClip clip(&g, gfx::Rect(0, 0, g.width(), g.height()));
@ -294,59 +293,12 @@ void Editor::drawBrushPreview(const gfx::Point& pos, bool refresh)
old_clipping_region = clipping_region;
}
void Editor::moveBrushPreview(const gfx::Point& pos, bool refresh)
{
ASSERT(m_sprite != NULL);
gfx::Point oldScreenPos = m_cursorScreen;
gfx::Point oldEditorPos = m_cursorEditor;
clearBrushPreview(false);
drawBrushPreview(pos, false);
gfx::Point newEditorPos = m_cursorEditor;
if (refresh) {
// Restore pixels
{
ScreenGraphics g;
SetClip clip(&g, gfx::Rect(0, 0, g.width(), g.height()));
forEachBrushPixel(&g, oldScreenPos, oldEditorPos, gfx::ColorNone, clearpixel);
}
if (cursor_type & CURSOR_THINCROSS && m_state->requireBrushPreview()) {
Brush* brush = get_current_brush();
gfx::Rect newBrushBounds = brush->bounds();
newBrushBounds.offset(newEditorPos);
m_document->notifySpritePixelsModified
(m_sprite, gfx::Region(lastBrushBounds.createUnion(newBrushBounds)));
lastBrushBounds = newBrushBounds;
}
// Save area and draw the cursor
ScreenGraphics g;
forEachBrushPixel(&g, m_cursorScreen, newEditorPos, ui_cursor_color, savepixel);
forEachBrushPixel(&g, m_cursorScreen, newEditorPos, ui_cursor_color, drawpixel);
}
}
/**
* Cleans the brush cursor from the specified editor.
*
* The mouse position is got from the last
* call to @c drawBrushPreview. So you must
* to use this routine only if you called
* @c drawBrushPreview before with the specified
* editor @a widget.
*
* @param widget The editor widget
*
* @see drawBrushPreview
*/
void Editor::clearBrushPreview(bool refresh)
// Cleans the brush cursor from the specified editor.
//
// The mouse position is got from the last call to drawBrushPreview()
// (m_cursorEditor). So you must to use this routine only if you
// called drawBrushPreview() before.
void Editor::clearBrushPreview()
{
ASSERT(m_cursorOnScreen);
ASSERT(m_sprite);
@ -355,7 +307,7 @@ void Editor::clearBrushPreview(bool refresh)
gfx::Point pos = m_cursorEditor;
if (refresh) {
{
// Restore pixels
ScreenGraphics g;
SetClip clip(&g, gfx::Rect(0, 0, g.width(), g.height()));
@ -366,10 +318,8 @@ void Editor::clearBrushPreview(bool refresh)
// Clean pixel/brush preview
if (cursor_type & CURSOR_THINCROSS && m_state->requireBrushPreview()) {
m_document->destroyExtraCel();
if (refresh) {
m_document->notifySpritePixelsModified
(m_sprite, gfx::Region(lastBrushBounds));
}
m_document->notifySpritePixelsModified(
m_sprite, gfx::Region(lastBrushBounds));
}
m_cursorOnScreen = false;
@ -394,17 +344,18 @@ static void generate_cursor_boundaries(Editor* editor)
if (!cursor_bound.seg || cursor_bound.brush_image != brush->image()) {
Image* brush_image = brush->image();
int w = brush_image->width();
int h = brush_image->height();
cursor_bound.brush_image = brush_image;
cursor_bound.brush_width = w;
cursor_bound.brush_height = h;
if (cursor_bound.seg)
base_free(cursor_bound.seg);
ImageRef mask;
if (brush_image->pixelFormat() != IMAGE_BITMAP) {
int w = brush_image->width();
int h = brush_image->height();
mask.reset(Image::create(IMAGE_BITMAP, w, h));
LockImageBits<BitmapTraits> bits(mask.get());
@ -533,8 +484,8 @@ static void trace_brush_bounds(ui::Graphics* g, Editor* editor,
BoundSeg* seg;
int c;
pos.x -= cursor_bound.brush_image->width()/2;
pos.y -= cursor_bound.brush_image->height()/2;
pos.x -= cursor_bound.brush_width/2;
pos.y -= cursor_bound.brush_height/2;
for (c=0; c<cursor_bound.nseg; c++) {
seg = cursor_bound.seg+c;

View File

@ -1028,11 +1028,12 @@ void Editor::moveDrawingCursor()
if (m_cursorOnScreen) {
gfx::Point mousePos = ui::get_mouse_position();
// Redraw it only when the mouse change to other pixel (not
// when the mouse moves only).
// Redraw it only when the mouse change to other pixel (not when
// the mouse just moves).
if (m_cursorScreen != mousePos) {
ui::hide_mouse_cursor();
moveBrushPreview(mousePos);
clearBrushPreview();
drawBrushPreview(mousePos);
ui::show_mouse_cursor();
}
}
@ -1448,8 +1449,7 @@ void Editor::setZoomAndCenterInMouse(Zoom zoom,
{
View* view = View::getView(this);
Rect vp = view->getViewportBounds();
hideDrawingCursor();
HideShowDrawingCursor hideShow(this);
gfx::Point screenPos;
gfx::Point spritePos;
@ -1488,7 +1488,6 @@ void Editor::setZoomAndCenterInMouse(Zoom zoom,
updateEditor();
setEditorScroll(scrollPos, blit_valid_rgn);
}
showDrawingCursor();
}
void Editor::pasteImage(const Image* image, const gfx::Point& pos)

View File

@ -227,9 +227,8 @@ namespace app {
void setStateInternal(const EditorStatePtr& newState);
void updateQuicktool();
void updateContextBarFromModifiers();
void drawBrushPreview(const gfx::Point& pos, bool refresh = true);
void moveBrushPreview(const gfx::Point& pos, bool refresh = true);
void clearBrushPreview(bool refresh = true);
void drawBrushPreview(const gfx::Point& pos);
void clearBrushPreview();
bool doesBrushPreviewNeedSubpixel();
bool isCurrentToolAffectedByRightClickMode();

View File

@ -11,28 +11,22 @@
namespace app {
class ShowHideDrawingCursor {
public:
ShowHideDrawingCursor(Editor* editor) : m_editor(editor) {
m_editor->showDrawingCursor();
}
~ShowHideDrawingCursor() {
m_editor->hideDrawingCursor();
}
private:
Editor* m_editor;
};
class HideShowDrawingCursor {
public:
HideShowDrawingCursor(Editor* editor) : m_editor(editor) {
m_editor->hideDrawingCursor();
HideShowDrawingCursor(Editor* editor)
: m_editor(editor)
, m_cursorOnScreen(m_editor->cursorOnScreen())
{
if (m_cursorOnScreen)
m_editor->hideDrawingCursor();
}
~HideShowDrawingCursor() {
m_editor->showDrawingCursor();
if (m_cursorOnScreen)
m_editor->showDrawingCursor();
}
private:
Editor* m_editor;
bool m_cursorOnScreen;
};
} // namespace app