Use ui::Graphics instead of Allegro in Editor's brush preview routines

* Remove color_utils::color_for_allegro()
* Rename editor_draw/move/clear_cursor() -> draw/move/clearBrushPreview()
* Rename Editor::get_raw_cursor_color() and Editor::is_cursor_mask()
* Add Graphics::get/putPixel() and Graphics::width/height()
* Add SetClip class
This commit is contained in:
David Capello 2014-06-28 10:33:58 -03:00
parent 0b8d88d6ee
commit 7ebc90678f
9 changed files with 219 additions and 204 deletions

View File

@ -111,48 +111,6 @@ ui::Color color_utils::color_for_ui(const app::Color& color)
return c; return c;
} }
int color_utils::color_for_allegro(const app::Color& color, int depth)
{
int c = -1;
switch (color.getType()) {
case app::Color::MaskType:
c = get_mask_for_bitmap(depth);
break;
case app::Color::RgbType:
case app::Color::HsvType:
c = makeacol_depth(depth,
color.getRed(),
color.getGreen(),
color.getBlue(), 255);
break;
case app::Color::GrayType:
c = color.getGray();
if (depth != 8)
c = makeacol_depth(depth, c, c, c, 255);
break;
case app::Color::IndexType:
c = color.getIndex();
if (depth != 8) {
ASSERT(c >= 0 && c < (int)get_current_palette()->size());
uint32_t _c = get_current_palette()->getEntry(c);
c = makeacol_depth(depth,
rgba_getr(_c),
rgba_getg(_c),
rgba_getb(_c), 255);
}
break;
}
return c;
}
raster::color_t color_utils::color_for_image(const app::Color& color, PixelFormat format) raster::color_t color_utils::color_for_image(const app::Color& color, PixelFormat format)
{ {
if (color.getType() == app::Color::MaskType) if (color.getType() == app::Color::MaskType)

View File

@ -37,7 +37,6 @@ namespace app {
ui::Color blackandwhite_neg(ui::Color color); ui::Color blackandwhite_neg(ui::Color color);
ui::Color color_for_ui(const app::Color& color); ui::Color color_for_ui(const app::Color& color);
int color_for_allegro(const app::Color& color, int depth);
raster::color_t color_for_image(const app::Color& color, raster::PixelFormat format); raster::color_t color_for_image(const app::Color& color, raster::PixelFormat format);
raster::color_t color_for_layer(const app::Color& color, raster::Layer* layer); raster::color_t color_for_layer(const app::Color& color, raster::Layer* layer);
raster::color_t color_for_target(const app::Color& color, const ColorTarget& colorTarget); raster::color_t color_for_target(const app::Color& color, const ColorTarget& colorTarget);

View File

@ -1,5 +1,5 @@
/* Aseprite /* Aseprite
* Copyright (C) 2001-2013 David Capello * Copyright (C) 2001-2014 David Capello
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
@ -20,6 +20,8 @@
#include "config.h" #include "config.h"
#endif #endif
#include "app/ui/editor/editor.h"
#include "app/app.h" #include "app/app.h"
#include "app/color.h" #include "app/color.h"
#include "app/color_utils.h" #include "app/color_utils.h"
@ -28,10 +30,10 @@
#include "app/settings/settings.h" #include "app/settings/settings.h"
#include "app/tools/ink.h" #include "app/tools/ink.h"
#include "app/tools/tool.h" #include "app/tools/tool.h"
#include "app/ui/editor/editor.h"
#include "app/ui_context.h" #include "app/ui_context.h"
#include "app/util/boundary.h" #include "app/util/boundary.h"
#include "base/memory.h" #include "base/memory.h"
#include "raster/algo.h"
#include "raster/brush.h" #include "raster/brush.h"
#include "raster/image.h" #include "raster/image.h"
#include "raster/layer.h" #include "raster/layer.h"
@ -42,7 +44,6 @@
#include "ui/widget.h" #include "ui/widget.h"
#include <algorithm> #include <algorithm>
#include <allegro.h>
#ifdef WIN32 #ifdef WIN32
#undef max #undef max
@ -53,18 +54,10 @@ namespace app {
using namespace ui; using namespace ui;
/**********************************************************************/ // Returns true if the cursor of the editor needs subpixel movement.
/* drawing-cursor routines */
/**********************************************************************/
/**
* Returns true if the cursor of the editor needs subpixel movement.
*/
#define IS_SUBPIXEL(editor) ((editor)->m_zoom >= 2) #define IS_SUBPIXEL(editor) ((editor)->m_zoom >= 2)
/** // Maximum quantity of colors to save pixels overlapped by the cursor.
* Maximum quantity of colors to save pixels overlapped by the cursor.
*/
#define MAX_SAVED 4096 #define MAX_SAVED 4096
static struct { static struct {
@ -76,15 +69,15 @@ static struct {
} cursor_bound = { 0, 0, 0, 0, NULL }; } cursor_bound = { 0, 0, 0, 0, NULL };
enum { enum {
CURSOR_BRUSH = 1, // New cursor style (with preview) CURSOR_THINCROSS = 1,
CURSOR_CROSS_ONE = 2, // Old cursor style (deprecated) CURSOR_THICKCROSS = 2,
CURSOR_BOUNDS = 4 // Old cursor boundaries (deprecated) CURSOR_BRUSHBOUNDS = 4
}; };
static int cursor_type = CURSOR_BRUSH; static int cursor_type = CURSOR_THINCROSS;
static int cursor_negative; static int cursor_negative;
static int saved_pixel[MAX_SAVED]; static ui::Color saved_pixel[MAX_SAVED];
static int saved_pixel_n; static int saved_pixel_n;
// These clipping regions are shared between all editors, so we cannot // These clipping regions are shared between all editors, so we cannot
@ -94,13 +87,13 @@ static gfx::Region old_clipping_region;
static void generate_cursor_boundaries(); static void generate_cursor_boundaries();
static void editor_cursor_brush(Editor *editor, int x, int y, int color, int thickness, void (*pixel)(BITMAP *bmp, int x, int y, int color)); static void trace_thincross_pixels(ui::Graphics* g, Editor* editor, int x, int y, ui::Color color, Editor::PixelDelegate pixel);
static void editor_cursor_cross(Editor *editor, int x, int y, int color, int thickness, void (*pixel)(BITMAP *bmp, int x, int y, int color)); static void trace_thickcross_pixels(ui::Graphics* g, Editor* editor, int x, int y, ui::Color color, int thickness, Editor::PixelDelegate pixel);
static void editor_cursor_bounds(Editor *editor, int x, int y, int color, void (*pixel)(BITMAP *bmp, int x, int y, int color)); static void trace_brush_bounds(ui::Graphics* g, Editor* editor, int x, int y, ui::Color color, Editor::PixelDelegate pixel);
static void savepixel(BITMAP *bmp, int x, int y, int color); static void savepixel(ui::Graphics* g, int x, int y, ui::Color color);
static void drawpixel(BITMAP *bmp, int x, int y, int color); static void drawpixel(ui::Graphics* g, int x, int y, ui::Color color);
static void cleanpixel(BITMAP *bmp, int x, int y, int color); static void clearpixel(ui::Graphics* g, int x, int y, ui::Color color);
static color_t get_brush_color(Sprite* sprite, Layer* layer); static color_t get_brush_color(Sprite* sprite, Layer* layer);
@ -109,27 +102,17 @@ static color_t get_brush_color(Sprite* sprite, Layer* layer);
////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////
static app::Color cursor_color; static app::Color cursor_color;
static int _cursor_color; static ui::Color ui_cursor_color;
static bool _cursor_mask; static bool is_cursor_mask;
static void update_cursor_color() static void update_cursor_color()
{ {
if (ji_screen) if (ji_screen)
_cursor_color = color_utils::color_for_allegro(cursor_color, bitmap_color_depth(ji_screen)); ui_cursor_color = color_utils::color_for_ui(cursor_color);
else else
_cursor_color = 0; ui_cursor_color = 0;
_cursor_mask = (cursor_color.getType() == app::Color::MaskType); is_cursor_mask = (cursor_color.getType() == app::Color::MaskType);
}
int Editor::get_raw_cursor_color()
{
return _cursor_color;
}
bool Editor::is_cursor_mask()
{
return _cursor_mask;
} }
app::Color Editor::get_cursor_color() app::Color Editor::get_cursor_color()
@ -228,19 +211,12 @@ void Editor::editor_cursor_exit()
current_brush = NULL; current_brush = NULL;
} }
/** // Draws the brush cursor inside the specified editor.
* Draws the brush cursor inside the specified editor. // Warning: You should clean the cursor before to use
* // this routine with other 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(int x, int y, bool refresh)
* @param widget The editor widget
* @param x Absolute position in X axis of the mouse.
* @param y Absolute position in Y axis of the mouse.
*
* @see editor_clean_cursor
*/
void Editor::editor_draw_cursor(int x, int y, bool refresh)
{ {
ASSERT(m_cursor_thick == 0); ASSERT(m_cursor_thick == 0);
ASSERT(m_sprite != NULL); ASSERT(m_sprite != NULL);
@ -248,15 +224,14 @@ void Editor::editor_draw_cursor(int x, int y, bool refresh)
// Get drawable region // Get drawable region
getDrawableRegion(clipping_region, kCutTopWindows); getDrawableRegion(clipping_region, kCutTopWindows);
/* get cursor color */ // Get cursor color
cursor_negative = is_cursor_mask(); cursor_negative = is_cursor_mask;
int color = get_raw_cursor_color();
/* cursor in the screen (view) */ // Cursor in the screen (view)
m_cursor_screen_x = x; m_cursor_screen_x = x;
m_cursor_screen_y = y; m_cursor_screen_y = y;
/* get cursor position in the editor */ // Get cursor position in the editor
screenToEditor(x, y, &x, &y); screenToEditor(x, y, &x, &y);
// Get the current tool // Get the current tool
@ -271,7 +246,7 @@ void Editor::editor_draw_cursor(int x, int y, bool refresh)
if (current_tool->getInk(0)->isSelection() || if (current_tool->getInk(0)->isSelection() ||
current_tool->getInk(0)->isSlice()) { current_tool->getInk(0)->isSlice()) {
cursor_type = CURSOR_CROSS_ONE; cursor_type = CURSOR_THICKCROSS;
} }
else if ( else if (
// Use cursor bounds for inks that are effects (eraser, blur, etc.) // Use cursor bounds for inks that are effects (eraser, blur, etc.)
@ -279,18 +254,18 @@ void Editor::editor_draw_cursor(int x, int y, bool refresh)
// or when the brush color is transparent and we are not in the background layer // or when the brush color is transparent and we are not in the background layer
(m_layer && !m_layer->isBackground() && (m_layer && !m_layer->isBackground() &&
brush_color == mask_color)) { brush_color == mask_color)) {
cursor_type = CURSOR_BOUNDS; cursor_type = CURSOR_BRUSHBOUNDS;
} }
else { else {
cursor_type = CURSOR_BRUSH; cursor_type = CURSOR_THINCROSS;
} }
// For cursor type 'bounds' we have to generate cursor boundaries // For cursor type 'bounds' we have to generate cursor boundaries
if (cursor_type & CURSOR_BOUNDS) if (cursor_type & CURSOR_BRUSHBOUNDS)
generate_cursor_boundaries(); generate_cursor_boundaries();
// draw pixel/brush preview // Draw pixel/brush preview
if (cursor_type & CURSOR_BRUSH && m_state->requireBrushPreview()) { if (cursor_type & CURSOR_THINCROSS && m_state->requireBrushPreview()) {
IToolSettings* tool_settings = UIContext::instance() IToolSettings* tool_settings = UIContext::instance()
->getSettings() ->getSettings()
->getToolSettings(current_tool); ->getToolSettings(current_tool);
@ -324,18 +299,17 @@ void Editor::editor_draw_cursor(int x, int y, bool refresh)
// Save area and draw the cursor // Save area and draw the cursor
if (refresh) { if (refresh) {
acquire_bitmap(ji_screen); ScreenGraphics g;
ji_screen->clip = false; SetClip clip(&g, gfx::Rect(0, 0, g.width(), g.height()));
forEachBrushPixel(m_cursor_screen_x, m_cursor_screen_y, x, y, color, savepixel);
forEachBrushPixel(m_cursor_screen_x, m_cursor_screen_y, x, y, color, drawpixel); forEachBrushPixel(&g, m_cursor_screen_x, m_cursor_screen_y, x, y, ui_cursor_color, savepixel);
ji_screen->clip = true; forEachBrushPixel(&g, m_cursor_screen_x, m_cursor_screen_y, x, y, ui_cursor_color, drawpixel);
release_bitmap(ji_screen);
} }
// cursor thickness // Cursor thickness
m_cursor_thick = 1; // get_thickness_for_cursor(); m_cursor_thick = 1;
// cursor in the editor (model) // Cursor in the editor (model)
m_cursor_editor_x = x; m_cursor_editor_x = x;
m_cursor_editor_y = y; m_cursor_editor_y = y;
@ -343,7 +317,7 @@ void Editor::editor_draw_cursor(int x, int y, bool refresh)
old_clipping_region = clipping_region; old_clipping_region = clipping_region;
} }
void Editor::editor_move_cursor(int x, int y, bool refresh) void Editor::moveBrushPreview(int x, int y, bool refresh)
{ {
ASSERT(m_sprite != NULL); ASSERT(m_sprite != NULL);
@ -352,21 +326,22 @@ void Editor::editor_move_cursor(int x, int y, bool refresh)
int old_x = m_cursor_editor_x; int old_x = m_cursor_editor_x;
int old_y = m_cursor_editor_y; int old_y = m_cursor_editor_y;
editor_clean_cursor(false); clearBrushPreview(false);
editor_draw_cursor(x, y, false); drawBrushPreview(x, y, false);
int new_x = m_cursor_editor_x; int new_x = m_cursor_editor_x;
int new_y = m_cursor_editor_y; int new_y = m_cursor_editor_y;
if (refresh) { if (refresh) {
/* restore points */ // Restore pixels
acquire_bitmap(ji_screen); {
ji_screen->clip = FALSE; ScreenGraphics g;
forEachBrushPixel(old_screen_x, old_screen_y, old_x, old_y, 0, cleanpixel); SetClip clip(&g, gfx::Rect(0, 0, g.width(), g.height()));
ji_screen->clip = TRUE;
release_bitmap(ji_screen);
if (cursor_type & CURSOR_BRUSH && m_state->requireBrushPreview()) { forEachBrushPixel(&g, old_screen_x, old_screen_y, old_x, old_y, ui::ColorNone, clearpixel);
}
if (cursor_type & CURSOR_THINCROSS && m_state->requireBrushPreview()) {
Brush* brush = editor_get_current_brush(); Brush* brush = editor_get_current_brush();
gfx::Rect brushBounds = brush->getBounds(); gfx::Rect brushBounds = brush->getBounds();
gfx::Rect rc1(old_x+brushBounds.x, old_y+brushBounds.y, brushBounds.w, brushBounds.h); gfx::Rect rc1(old_x+brushBounds.x, old_y+brushBounds.y, brushBounds.w, brushBounds.h);
@ -375,14 +350,10 @@ void Editor::editor_move_cursor(int x, int y, bool refresh)
(m_sprite, gfx::Region(rc1.createUnion(rc2))); (m_sprite, gfx::Region(rc1.createUnion(rc2)));
} }
/* save area and draw the cursor */ // Save area and draw the cursor
int color = get_raw_cursor_color(); ScreenGraphics g;
acquire_bitmap(ji_screen); forEachBrushPixel(&g, m_cursor_screen_x, m_cursor_screen_y, new_x, new_y, ui_cursor_color, savepixel);
ji_screen->clip = false; forEachBrushPixel(&g, m_cursor_screen_x, m_cursor_screen_y, new_x, new_y, ui_cursor_color, drawpixel);
forEachBrushPixel(m_cursor_screen_x, m_cursor_screen_y, new_x, new_y, color, savepixel);
forEachBrushPixel(m_cursor_screen_x, m_cursor_screen_y, new_x, new_y, color, drawpixel);
ji_screen->clip = true;
release_bitmap(ji_screen);
} }
} }
@ -390,16 +361,16 @@ void Editor::editor_move_cursor(int x, int y, bool refresh)
* Cleans the brush cursor from the specified editor. * Cleans the brush cursor from the specified editor.
* *
* The mouse position is got from the last * The mouse position is got from the last
* call to @c editor_draw_cursor. So you must * call to @c drawBrushPreview. So you must
* to use this routine only if you called * to use this routine only if you called
* @c editor_draw_cursor before with the specified * @c drawBrushPreview before with the specified
* editor @a widget. * editor @a widget.
* *
* @param widget The editor widget * @param widget The editor widget
* *
* @see editor_draw_cursor * @see drawBrushPreview
*/ */
void Editor::editor_clean_cursor(bool refresh) void Editor::clearBrushPreview(bool refresh)
{ {
int x, y; int x, y;
@ -412,16 +383,15 @@ void Editor::editor_clean_cursor(bool refresh)
y = m_cursor_editor_y; y = m_cursor_editor_y;
if (refresh) { if (refresh) {
/* restore points */ // Restore pixels
acquire_bitmap(ji_screen); ScreenGraphics g;
ji_screen->clip = FALSE; SetClip clip(&g, gfx::Rect(0, 0, g.width(), g.height()));
forEachBrushPixel(m_cursor_screen_x, m_cursor_screen_y, x, y, 0, cleanpixel);
ji_screen->clip = TRUE; forEachBrushPixel(&g, m_cursor_screen_x, m_cursor_screen_y, x, y, ui::ColorNone, clearpixel);
release_bitmap(ji_screen);
} }
// clean pixel/brush preview // Clean pixel/brush preview
if (cursor_type & CURSOR_BRUSH && m_state->requireBrushPreview()) { if (cursor_type & CURSOR_THINCROSS && m_state->requireBrushPreview()) {
Brush* brush = editor_get_current_brush(); Brush* brush = editor_get_current_brush();
gfx::Rect brushBounds = brush->getBounds(); gfx::Rect brushBounds = brush->getBounds();
@ -444,12 +414,10 @@ void Editor::editor_clean_cursor(bool refresh)
old_clipping_region.clear(); old_clipping_region.clear();
} }
/** // Returns true if the cursor to draw in the editor has subpixel
* Returns true if the cursor to draw in the editor has subpixel // movement (a little pixel of the screen that indicates where is the
* movement (a little pixel of the screen that indicates where is the // mouse inside the pixel of the sprite).
* mouse inside the pixel of the sprite). bool Editor::doesBrushPreviewNeedSubpixel()
*/
bool Editor::editor_cursor_is_subpixel()
{ {
return IS_SUBPIXEL(this); return IS_SUBPIXEL(this);
} }
@ -498,33 +466,33 @@ static void generate_cursor_boundaries()
} }
void Editor::forEachBrushPixel( void Editor::forEachBrushPixel(
ui::Graphics* g,
int screen_x, int screen_y, int screen_x, int screen_y,
int sprite_x, int sprite_y, int color, int sprite_x, int sprite_y,
void (*pixel)(BITMAP *bmp, int x, int y, int color)) ui::Color color,
Editor::PixelDelegate pixelDelegate)
{ {
saved_pixel_n = 0; saved_pixel_n = 0;
if (cursor_type & CURSOR_BRUSH) { if (cursor_type & CURSOR_THINCROSS)
editor_cursor_brush(this, screen_x, screen_y, color, 1, pixel); trace_thincross_pixels(g, this, screen_x, screen_y, color, pixelDelegate);
}
if (cursor_type & CURSOR_CROSS_ONE) { if (cursor_type & CURSOR_THICKCROSS)
editor_cursor_cross(this, sprite_x, sprite_y, color, 1, pixel); trace_thickcross_pixels(g, this, sprite_x, sprite_y, color, 1, pixelDelegate);
}
if (cursor_type & CURSOR_BOUNDS) { if (cursor_type & CURSOR_BRUSHBOUNDS)
editor_cursor_bounds(this, sprite_x, sprite_y, color, pixel); trace_brush_bounds(g, this, sprite_x, sprite_y, color, pixelDelegate);
}
if (IS_SUBPIXEL(this)) { if (IS_SUBPIXEL(this)) {
(*pixel)(ji_screen, screen_x, screen_y, color); pixelDelegate(g, screen_x, screen_y, color);
} }
} }
////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////
// New cross // New Thin Cross
static void editor_cursor_brush(Editor *editor, int x, int y, int color, int thickness, void (*pixel)(BITMAP *bmp, int x, int y, int color)) static void trace_thincross_pixels(ui::Graphics* g, Editor* editor,
int x, int y, ui::Color color, Editor::PixelDelegate pixelDelegate)
{ {
static int cursor_cross[7*7] = { static int cursor_cross[7*7] = {
0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0,
@ -542,17 +510,17 @@ static void editor_cursor_brush(Editor *editor, int x, int y, int color, int thi
if (cursor_cross[v*7+u]) { if (cursor_cross[v*7+u]) {
xout = x-3+u; xout = x-3+u;
yout = y-3+v; yout = y-3+v;
(*pixel)(ji_screen, xout, yout, color); pixelDelegate(g, xout, yout, color);
} }
} }
} }
} }
////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////
// Old cross // Old Thick Cross
static void editor_cursor_cross(Editor* editor, int x, int y, int color, int thickness, static void trace_thickcross_pixels(ui::Graphics* g, Editor* editor,
void (*pixel)(BITMAP *bmp, int x, int y, int color)) int x, int y, ui::Color color, int thickness, Editor::PixelDelegate pixelDelegate)
{ {
static int cursor_cross[6*6] = { static int cursor_cross[6*6] = {
0, 0, 1, 1, 0, 0, 0, 0, 1, 1, 0, 0,
@ -578,17 +546,31 @@ static void editor_cursor_cross(Editor* editor, int x, int y, int color, int thi
v-((thickness>>1)<<zoom)-3: v-((thickness>>1)<<zoom)-3:
v-((thickness>>1)<<zoom)-3+(thickness<<zoom)); v-((thickness>>1)<<zoom)-3+(thickness<<zoom));
(*pixel)(ji_screen, xout, yout, color); pixelDelegate(g, xout, yout, color);
} }
} }
} }
} }
////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////
// Cursor Bounds // Current Brush Bounds
static void editor_cursor_bounds(Editor *editor, int x, int y, int color, void (*pixel) (BITMAP *bmp, int x, int y, int color)) struct Data {
ui::Graphics* g;
ui::Color color;
Editor::PixelDelegate pixelDelegate;
};
static void algo_line_proxy(int x, int y, void* _data)
{ {
Data* data = (Data*)_data;
data->pixelDelegate(data->g, x, y, data->color);
}
static void trace_brush_bounds(ui::Graphics* g, Editor* editor,
int x, int y, ui::Color color, Editor::PixelDelegate pixelDelegate)
{
Data data = { g, color, pixelDelegate };
int c, x1, y1, x2, y2; int c, x1, y1, x2, y2;
BoundSeg* seg; BoundSeg* seg;
@ -624,42 +606,41 @@ static void editor_cursor_bounds(Editor *editor, int x, int y, int color, void (
} }
} }
do_line(ji_screen, x1, y1, x2, y2, color, pixel); raster::algo_line(x1, y1, x2, y2, (void*)&data, algo_line_proxy);
} }
} }
////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////
// Helpers // Helpers
static void savepixel(BITMAP *bmp, int x, int y, int color) static void savepixel(ui::Graphics* g, int x, int y, ui::Color color)
{ {
if (saved_pixel_n < MAX_SAVED && clipping_region.contains(gfx::Point(x, y))) if (saved_pixel_n < MAX_SAVED && clipping_region.contains(gfx::Point(x, y)))
saved_pixel[saved_pixel_n++] = getpixel(bmp, x, y); saved_pixel[saved_pixel_n++] = g->getPixel(x, y);
} }
static void drawpixel(BITMAP *bmp, int x, int y, int color) static void drawpixel(ui::Graphics* graphics, int x, int y, ui::Color color)
{ {
if (saved_pixel_n < MAX_SAVED && clipping_region.contains(gfx::Point(x, y))) { if (saved_pixel_n < MAX_SAVED && clipping_region.contains(gfx::Point(x, y))) {
if (cursor_negative) { if (cursor_negative) {
int r, g, b, c = saved_pixel[saved_pixel_n++]; int c = saved_pixel[saved_pixel_n++];
int r = getr(c);
int g = getg(c);
int b = getb(c);
r = getr(c); graphics->putPixel(color_utils::blackandwhite_neg(ui::rgba(r, g, b)), x, y);
g = getg(c);
b = getb(c);
putpixel(bmp, x, y, ui::to_system(color_utils::blackandwhite_neg(ui::rgba(r, g, b))));
} }
else { else {
putpixel(bmp, x, y, color); graphics->putPixel(color, x, y);
} }
} }
} }
static void cleanpixel(BITMAP *bmp, int x, int y, int color) static void clearpixel(ui::Graphics* g, int x, int y, ui::Color color)
{ {
if (saved_pixel_n < MAX_SAVED) { if (saved_pixel_n < MAX_SAVED) {
if (clipping_region.contains(gfx::Point(x, y))) if (clipping_region.contains(gfx::Point(x, y)))
putpixel(bmp, x, y, saved_pixel[saved_pixel_n++]); g->putPixel(saved_pixel[saved_pixel_n++], x, y);
else if (!old_clipping_region.isEmpty() && else if (!old_clipping_region.isEmpty() &&
old_clipping_region.contains(gfx::Point(x, y))) old_clipping_region.contains(gfx::Point(x, y)))
saved_pixel_n++; saved_pixel_n++;

View File

@ -299,7 +299,7 @@ void Editor::setEditorScroll(int x, int y, int use_refresh_region)
int thick = m_cursor_thick; int thick = m_cursor_thick;
if (thick) if (thick)
editor_clean_cursor(); clearBrushPreview();
if (use_refresh_region) { if (use_refresh_region) {
getDrawableRegion(region, kCutTopWindows); getDrawableRegion(region, kCutTopWindows);
@ -317,7 +317,7 @@ void Editor::setEditorScroll(int x, int y, int use_refresh_region)
} }
if (thick) if (thick)
editor_draw_cursor(m_cursor_screen_x, m_cursor_screen_y); drawBrushPreview(m_cursor_screen_x, m_cursor_screen_y);
} }
void Editor::updateEditor() void Editor::updateEditor()
@ -587,7 +587,7 @@ void Editor::drawMaskSafe()
region.offset(-getBounds().getOrigin()); region.offset(-getBounds().getOrigin());
if (thick) if (thick)
editor_clean_cursor(); clearBrushPreview();
else else
jmouse_hide(); jmouse_hide();
@ -602,7 +602,7 @@ void Editor::drawMaskSafe()
// Draw the cursor // Draw the cursor
if (thick) if (thick)
editor_draw_cursor(m_cursor_screen_x, m_cursor_screen_y); drawBrushPreview(m_cursor_screen_x, m_cursor_screen_y);
else else
jmouse_show(); jmouse_show();
} }
@ -776,7 +776,7 @@ void Editor::showDrawingCursor()
if (!m_cursor_thick && canDraw()) { if (!m_cursor_thick && canDraw()) {
jmouse_hide(); jmouse_hide();
editor_draw_cursor(jmouse_x(0), jmouse_y(0)); drawBrushPreview(jmouse_x(0), jmouse_y(0));
jmouse_show(); jmouse_show();
} }
} }
@ -785,7 +785,7 @@ void Editor::hideDrawingCursor()
{ {
if (m_cursor_thick) { if (m_cursor_thick) {
jmouse_hide(); jmouse_hide();
editor_clean_cursor(); clearBrushPreview();
jmouse_show(); jmouse_show();
} }
} }
@ -803,7 +803,7 @@ void Editor::moveDrawingCursor()
// when the mouse moves only). // when the mouse moves only).
if ((m_cursor_screen_x != x) || (m_cursor_screen_y != y)) { if ((m_cursor_screen_x != x) || (m_cursor_screen_y != y)) {
jmouse_hide(); jmouse_hide();
editor_move_cursor(x, y); moveBrushPreview(x, y);
jmouse_show(); jmouse_show();
} }
} }
@ -1025,7 +1025,7 @@ void Editor::onPaint(ui::PaintEvent& ev)
int old_cursor_thick = m_cursor_thick; int old_cursor_thick = m_cursor_thick;
if (m_cursor_thick) if (m_cursor_thick)
editor_clean_cursor(); clearBrushPreview();
// Editor without sprite // Editor without sprite
if (!m_sprite) { if (!m_sprite) {
@ -1051,7 +1051,7 @@ void Editor::onPaint(ui::PaintEvent& ev)
// Draw the cursor again // Draw the cursor again
if (old_cursor_thick != 0) { if (old_cursor_thick != 0) {
editor_draw_cursor(jmouse_x(0), jmouse_y(0)); drawBrushPreview(jmouse_x(0), jmouse_y(0));
} }
} }
catch (const LockedDocumentException&) { catch (const LockedDocumentException&) {

View File

@ -65,6 +65,8 @@ namespace app {
class Editor : public ui::Widget, class Editor : public ui::Widget,
public DocumentSettingsObserver { public DocumentSettingsObserver {
public: public:
typedef void (*PixelDelegate)(ui::Graphics* g, int x, int y, ui::Color color);
enum EditorFlags { enum EditorFlags {
kNoneFlag = 0, kNoneFlag = 0,
kShowGridFlag = 1, kShowGridFlag = 1,
@ -178,8 +180,6 @@ namespace app {
// in cursor.cpp // in cursor.cpp
static int get_raw_cursor_color();
static bool is_cursor_mask();
static app::Color get_cursor_color(); static app::Color get_cursor_color();
static void set_cursor_color(const app::Color& color); static void set_cursor_color(const app::Color& color);
@ -201,10 +201,10 @@ namespace app {
private: private:
void setStateInternal(const EditorStatePtr& newState); void setStateInternal(const EditorStatePtr& newState);
void editor_update_quicktool(); void editor_update_quicktool();
void editor_draw_cursor(int x, int y, bool refresh = true); void drawBrushPreview(int x, int y, bool refresh = true);
void editor_move_cursor(int x, int y, bool refresh = true); void moveBrushPreview(int x, int y, bool refresh = true);
void editor_clean_cursor(bool refresh = true); void clearBrushPreview(bool refresh = true);
bool editor_cursor_is_subpixel(); bool doesBrushPreviewNeedSubpixel();
void drawMaskSafe(); void drawMaskSafe();
void drawMask(ui::Graphics* g); void drawMask(ui::Graphics* g);
@ -213,9 +213,11 @@ namespace app {
void editor_setcursor(); void editor_setcursor();
void forEachBrushPixel( void forEachBrushPixel(
ui::Graphics* g,
int screen_x, int screen_y, int screen_x, int screen_y,
int sprite_x, int sprite_y, int color, int sprite_x, int sprite_y,
void (*pixel)(BITMAP* bmp, int x, int y, int color)); ui::Color color,
PixelDelegate pixelDelegate);
// Draws the specified portion of sprite in the editor. Warning: // Draws the specified portion of sprite in the editor. Warning:
// You should setup the clip of the screen before calling this // You should setup the clip of the screen before calling this

View File

@ -27,6 +27,13 @@ namespace she {
return makecol(getr(color), getg(color), getb(color)); return makecol(getr(color), getg(color), getb(color));
} }
inline Color from_allegro(int color_depth, int color) {
return she::rgba(
getr_depth(color_depth, color),
getg_depth(color_depth, color),
getb_depth(color_depth, color));
}
class Alleg4Surface : public Surface class Alleg4Surface : public Surface
, public LockedSurface { , public LockedSurface {
public: public:
@ -212,6 +219,16 @@ namespace she {
} }
} }
she::Color getPixel(int x, int y) OVERRIDE {
return from_allegro(
bitmap_color_depth(m_bmp),
getpixel(m_bmp, x, y));
}
void putPixel(she::Color color, int x, int y) OVERRIDE {
putpixel(m_bmp, x, y, to_allegro(color));
}
void drawHLine(she::Color color, int x, int y, int w) OVERRIDE { void drawHLine(she::Color color, int x, int y, int w) OVERRIDE {
hline(m_bmp, x, y, x+w-1, to_allegro(color)); hline(m_bmp, x, y, x+w-1, to_allegro(color));
} }

View File

@ -27,6 +27,9 @@ namespace she {
virtual uint8_t* getData(int x, int y) = 0; virtual uint8_t* getData(int x, int y) = 0;
virtual void getFormat(SurfaceFormatData* formatData) = 0; virtual void getFormat(SurfaceFormatData* formatData) = 0;
virtual she::Color getPixel(int x, int y) = 0;
virtual void putPixel(she::Color color, int x, int y) = 0;
virtual void drawHLine(she::Color color, int x, int y, int w) = 0; virtual void drawHLine(she::Color color, int x, int y, int w) = 0;
virtual void drawVLine(she::Color color, int x, int y, int h) = 0; virtual void drawVLine(she::Color color, int x, int y, int h) = 0;
virtual void drawLine(she::Color color, const gfx::Point& a, const gfx::Point& b) = 0; virtual void drawLine(she::Color color, const gfx::Point& a, const gfx::Point& b) = 0;

View File

@ -28,6 +28,10 @@ namespace {
return (she::Color)color; return (she::Color)color;
} }
inline ui::Color from_she(she::Color color) {
return (ui::Color)color;
}
} }
namespace ui { namespace ui {
@ -43,6 +47,16 @@ Graphics::~Graphics()
{ {
} }
int Graphics::width() const
{
return m_surface->width();
}
int Graphics::height() const
{
return m_surface->height();
}
gfx::Rect Graphics::getClipBounds() const gfx::Rect Graphics::getClipBounds() const
{ {
return m_surface->getClipBounds().offset(-m_dx, -m_dy); return m_surface->getClipBounds().offset(-m_dx, -m_dy);
@ -58,6 +72,18 @@ bool Graphics::intersectClipRect(const gfx::Rect& rc)
return m_surface->intersectClipRect(gfx::Rect(rc).offset(m_dx, m_dy)); return m_surface->intersectClipRect(gfx::Rect(rc).offset(m_dx, m_dy));
} }
ui::Color Graphics::getPixel(int x, int y)
{
she::ScopedSurfaceLock dst(m_surface);
return from_she(dst->getPixel(m_dx+x, m_dy+y));
}
void Graphics::putPixel(ui::Color color, int x, int y)
{
she::ScopedSurfaceLock dst(m_surface);
dst->putPixel(to_she(color), m_dx+x, m_dy+y);
}
void Graphics::drawHLine(ui::Color color, int x, int y, int w) void Graphics::drawHLine(ui::Color color, int x, int y, int w)
{ {
she::ScopedSurfaceLock dst(m_surface); she::ScopedSurfaceLock dst(m_surface);

View File

@ -34,6 +34,9 @@ namespace ui {
Graphics(she::Surface* surface, int dx, int dy); Graphics(she::Surface* surface, int dx, int dy);
~Graphics(); ~Graphics();
int width() const;
int height() const;
she::Surface* getInternalSurface() { return m_surface; } she::Surface* getInternalSurface() { return m_surface; }
int getInternalDeltaX() { return m_dx; } int getInternalDeltaX() { return m_dx; }
int getInternalDeltaY() { return m_dy; } int getInternalDeltaY() { return m_dy; }
@ -42,6 +45,9 @@ namespace ui {
void setClipBounds(const gfx::Rect& rc); void setClipBounds(const gfx::Rect& rc);
bool intersectClipRect(const gfx::Rect& rc); bool intersectClipRect(const gfx::Rect& rc);
ui::Color getPixel(int x, int y);
void putPixel(ui::Color color, int x, int y);
void drawHLine(ui::Color color, int x, int y, int w); void drawHLine(ui::Color color, int x, int y, int w);
void drawVLine(ui::Color color, int x, int y, int h); void drawVLine(ui::Color color, int x, int y, int h);
void drawLine(ui::Color color, const gfx::Point& a, const gfx::Point& b); void drawLine(ui::Color color, const gfx::Point& a, const gfx::Point& b);
@ -91,6 +97,29 @@ namespace ui {
virtual ~ScreenGraphics(); virtual ~ScreenGraphics();
}; };
// Class to temporary set the Graphics' clip region (in the
// life-time of the SetClip instance).
class SetClip {
public:
SetClip(Graphics* g, const gfx::Rect& rc)
: m_graphics(g)
, m_oldClip(g->getClipBounds())
{
m_graphics->setClipBounds(rc);
}
~SetClip()
{
m_graphics->setClipBounds(m_oldClip);
}
private:
Graphics* m_graphics;
gfx::Rect m_oldClip;
DISABLE_COPYING(SetClip);
};
// Class to temporary set the Graphics' clip region to a sub-rectangle // Class to temporary set the Graphics' clip region to a sub-rectangle
// (in the life-time of the IntersectClip instance). // (in the life-time of the IntersectClip instance).
class IntersectClip { class IntersectClip {