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;
}
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)
{
if (color.getType() == app::Color::MaskType)

View File

@ -37,7 +37,6 @@ namespace app {
ui::Color blackandwhite_neg(ui::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_layer(const app::Color& color, raster::Layer* layer);
raster::color_t color_for_target(const app::Color& color, const ColorTarget& colorTarget);

View File

@ -1,5 +1,5 @@
/* 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
* it under the terms of the GNU General Public License as published by
@ -20,6 +20,8 @@
#include "config.h"
#endif
#include "app/ui/editor/editor.h"
#include "app/app.h"
#include "app/color.h"
#include "app/color_utils.h"
@ -28,10 +30,10 @@
#include "app/settings/settings.h"
#include "app/tools/ink.h"
#include "app/tools/tool.h"
#include "app/ui/editor/editor.h"
#include "app/ui_context.h"
#include "app/util/boundary.h"
#include "base/memory.h"
#include "raster/algo.h"
#include "raster/brush.h"
#include "raster/image.h"
#include "raster/layer.h"
@ -42,7 +44,6 @@
#include "ui/widget.h"
#include <algorithm>
#include <allegro.h>
#ifdef WIN32
#undef max
@ -53,18 +54,10 @@ namespace app {
using namespace ui;
/**********************************************************************/
/* drawing-cursor routines */
/**********************************************************************/
/**
* Returns true if the cursor of the editor needs subpixel movement.
*/
// Returns true if the cursor of the editor needs subpixel movement.
#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
static struct {
@ -72,19 +65,19 @@ static struct {
int brush_size;
int brush_angle;
int nseg;
BoundSeg *seg;
BoundSeg* seg;
} cursor_bound = { 0, 0, 0, 0, NULL };
enum {
CURSOR_BRUSH = 1, // New cursor style (with preview)
CURSOR_CROSS_ONE = 2, // Old cursor style (deprecated)
CURSOR_BOUNDS = 4 // Old cursor boundaries (deprecated)
CURSOR_THINCROSS = 1,
CURSOR_THICKCROSS = 2,
CURSOR_BRUSHBOUNDS = 4
};
static int cursor_type = CURSOR_BRUSH;
static int cursor_type = CURSOR_THINCROSS;
static int cursor_negative;
static int saved_pixel[MAX_SAVED];
static ui::Color saved_pixel[MAX_SAVED];
static int saved_pixel_n;
// 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 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 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 editor_cursor_bounds(Editor *editor, int x, int y, int color, 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 trace_thickcross_pixels(ui::Graphics* g, Editor* editor, int x, int y, ui::Color color, int thickness, Editor::PixelDelegate pixel);
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 drawpixel(BITMAP *bmp, int x, int y, int color);
static void cleanpixel(BITMAP *bmp, int x, int y, int color);
static void savepixel(ui::Graphics* g, int x, int y, ui::Color color);
static void drawpixel(ui::Graphics* g, int x, int y, ui::Color color);
static void clearpixel(ui::Graphics* g, int x, int y, ui::Color color);
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 int _cursor_color;
static bool _cursor_mask;
static ui::Color ui_cursor_color;
static bool is_cursor_mask;
static void update_cursor_color()
{
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
_cursor_color = 0;
ui_cursor_color = 0;
_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;
is_cursor_mask = (cursor_color.getType() == app::Color::MaskType);
}
app::Color Editor::get_cursor_color()
@ -228,19 +211,12 @@ void Editor::editor_cursor_exit()
current_brush = NULL;
}
/**
* Draws the brush cursor inside the specified editor.
*
* @warning You should clean the cursor before to use
* this routine with other editor.
*
* @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)
// 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(int x, int y, bool refresh)
{
ASSERT(m_cursor_thick == 0);
ASSERT(m_sprite != NULL);
@ -248,15 +224,14 @@ void Editor::editor_draw_cursor(int x, int y, bool refresh)
// Get drawable region
getDrawableRegion(clipping_region, kCutTopWindows);
/* get cursor color */
cursor_negative = is_cursor_mask();
int color = get_raw_cursor_color();
// Get cursor color
cursor_negative = is_cursor_mask;
/* cursor in the screen (view) */
// Cursor in the screen (view)
m_cursor_screen_x = x;
m_cursor_screen_y = y;
/* get cursor position in the editor */
// Get cursor position in the editor
screenToEditor(x, y, &x, &y);
// 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() ||
current_tool->getInk(0)->isSlice()) {
cursor_type = CURSOR_CROSS_ONE;
cursor_type = CURSOR_THICKCROSS;
}
else if (
// 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
(m_layer && !m_layer->isBackground() &&
brush_color == mask_color)) {
cursor_type = CURSOR_BOUNDS;
cursor_type = CURSOR_BRUSHBOUNDS;
}
else {
cursor_type = CURSOR_BRUSH;
cursor_type = CURSOR_THINCROSS;
}
// For cursor type 'bounds' we have to generate cursor boundaries
if (cursor_type & CURSOR_BOUNDS)
if (cursor_type & CURSOR_BRUSHBOUNDS)
generate_cursor_boundaries();
// draw pixel/brush preview
if (cursor_type & CURSOR_BRUSH && m_state->requireBrushPreview()) {
// Draw pixel/brush preview
if (cursor_type & CURSOR_THINCROSS && m_state->requireBrushPreview()) {
IToolSettings* tool_settings = UIContext::instance()
->getSettings()
->getToolSettings(current_tool);
@ -324,18 +299,17 @@ void Editor::editor_draw_cursor(int x, int y, bool refresh)
// Save area and draw the cursor
if (refresh) {
acquire_bitmap(ji_screen);
ji_screen->clip = false;
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);
ji_screen->clip = true;
release_bitmap(ji_screen);
ScreenGraphics g;
SetClip clip(&g, gfx::Rect(0, 0, g.width(), g.height()));
forEachBrushPixel(&g, m_cursor_screen_x, m_cursor_screen_y, x, y, ui_cursor_color, savepixel);
forEachBrushPixel(&g, m_cursor_screen_x, m_cursor_screen_y, x, y, ui_cursor_color, drawpixel);
}
// cursor thickness
m_cursor_thick = 1; // get_thickness_for_cursor();
// Cursor thickness
m_cursor_thick = 1;
// cursor in the editor (model)
// Cursor in the editor (model)
m_cursor_editor_x = x;
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;
}
void Editor::editor_move_cursor(int x, int y, bool refresh)
void Editor::moveBrushPreview(int x, int y, bool refresh)
{
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_y = m_cursor_editor_y;
editor_clean_cursor(false);
editor_draw_cursor(x, y, false);
clearBrushPreview(false);
drawBrushPreview(x, y, false);
int new_x = m_cursor_editor_x;
int new_y = m_cursor_editor_y;
if (refresh) {
/* restore points */
acquire_bitmap(ji_screen);
ji_screen->clip = FALSE;
forEachBrushPixel(old_screen_x, old_screen_y, old_x, old_y, 0, cleanpixel);
ji_screen->clip = TRUE;
release_bitmap(ji_screen);
// Restore pixels
{
ScreenGraphics g;
SetClip clip(&g, gfx::Rect(0, 0, g.width(), g.height()));
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();
gfx::Rect brushBounds = brush->getBounds();
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)));
}
/* save area and draw the cursor */
int color = get_raw_cursor_color();
acquire_bitmap(ji_screen);
ji_screen->clip = false;
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);
// Save area and draw the cursor
ScreenGraphics g;
forEachBrushPixel(&g, m_cursor_screen_x, m_cursor_screen_y, new_x, new_y, ui_cursor_color, savepixel);
forEachBrushPixel(&g, m_cursor_screen_x, m_cursor_screen_y, new_x, new_y, ui_cursor_color, drawpixel);
}
}
@ -390,16 +361,16 @@ void Editor::editor_move_cursor(int x, int y, bool refresh)
* Cleans the brush cursor from the specified editor.
*
* 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
* @c editor_draw_cursor before with the specified
* @c drawBrushPreview before with the specified
* editor @a 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;
@ -412,16 +383,15 @@ void Editor::editor_clean_cursor(bool refresh)
y = m_cursor_editor_y;
if (refresh) {
/* restore points */
acquire_bitmap(ji_screen);
ji_screen->clip = FALSE;
forEachBrushPixel(m_cursor_screen_x, m_cursor_screen_y, x, y, 0, cleanpixel);
ji_screen->clip = TRUE;
release_bitmap(ji_screen);
// Restore pixels
ScreenGraphics g;
SetClip clip(&g, gfx::Rect(0, 0, g.width(), g.height()));
forEachBrushPixel(&g, m_cursor_screen_x, m_cursor_screen_y, x, y, ui::ColorNone, clearpixel);
}
// clean pixel/brush preview
if (cursor_type & CURSOR_BRUSH && m_state->requireBrushPreview()) {
// Clean pixel/brush preview
if (cursor_type & CURSOR_THINCROSS && m_state->requireBrushPreview()) {
Brush* brush = editor_get_current_brush();
gfx::Rect brushBounds = brush->getBounds();
@ -444,12 +414,10 @@ void Editor::editor_clean_cursor(bool refresh)
old_clipping_region.clear();
}
/**
* Returns true if the cursor to draw in the editor has subpixel
* movement (a little pixel of the screen that indicates where is the
* mouse inside the pixel of the sprite).
*/
bool Editor::editor_cursor_is_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
// mouse inside the pixel of the sprite).
bool Editor::doesBrushPreviewNeedSubpixel()
{
return IS_SUBPIXEL(this);
}
@ -498,33 +466,33 @@ static void generate_cursor_boundaries()
}
void Editor::forEachBrushPixel(
ui::Graphics* g,
int screen_x, int screen_y,
int sprite_x, int sprite_y, int color,
void (*pixel)(BITMAP *bmp, int x, int y, int color))
int sprite_x, int sprite_y,
ui::Color color,
Editor::PixelDelegate pixelDelegate)
{
saved_pixel_n = 0;
if (cursor_type & CURSOR_BRUSH) {
editor_cursor_brush(this, screen_x, screen_y, color, 1, pixel);
}
if (cursor_type & CURSOR_THINCROSS)
trace_thincross_pixels(g, this, screen_x, screen_y, color, pixelDelegate);
if (cursor_type & CURSOR_CROSS_ONE) {
editor_cursor_cross(this, sprite_x, sprite_y, color, 1, pixel);
}
if (cursor_type & CURSOR_THICKCROSS)
trace_thickcross_pixels(g, this, sprite_x, sprite_y, color, 1, pixelDelegate);
if (cursor_type & CURSOR_BOUNDS) {
editor_cursor_bounds(this, sprite_x, sprite_y, color, pixel);
}
if (cursor_type & CURSOR_BRUSHBOUNDS)
trace_brush_bounds(g, this, sprite_x, sprite_y, color, pixelDelegate);
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] = {
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]) {
xout = x-3+u;
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,
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 pixelDelegate)
{
static int cursor_cross[6*6] = {
0, 0, 1, 1, 0, 0,
@ -578,19 +546,33 @@ 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+(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;
BoundSeg *seg;
BoundSeg* seg;
for (c=0; c<cursor_bound.nseg; c++) {
seg = cursor_bound.seg+c;
@ -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
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)))
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 (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);
g = getg(c);
b = getb(c);
putpixel(bmp, x, y, ui::to_system(color_utils::blackandwhite_neg(ui::rgba(r, g, b))));
graphics->putPixel(color_utils::blackandwhite_neg(ui::rgba(r, g, b)), x, y);
}
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 (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() &&
old_clipping_region.contains(gfx::Point(x, y)))
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;
if (thick)
editor_clean_cursor();
clearBrushPreview();
if (use_refresh_region) {
getDrawableRegion(region, kCutTopWindows);
@ -317,7 +317,7 @@ void Editor::setEditorScroll(int x, int y, int use_refresh_region)
}
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()
@ -587,7 +587,7 @@ void Editor::drawMaskSafe()
region.offset(-getBounds().getOrigin());
if (thick)
editor_clean_cursor();
clearBrushPreview();
else
jmouse_hide();
@ -602,7 +602,7 @@ void Editor::drawMaskSafe()
// Draw the cursor
if (thick)
editor_draw_cursor(m_cursor_screen_x, m_cursor_screen_y);
drawBrushPreview(m_cursor_screen_x, m_cursor_screen_y);
else
jmouse_show();
}
@ -776,7 +776,7 @@ void Editor::showDrawingCursor()
if (!m_cursor_thick && canDraw()) {
jmouse_hide();
editor_draw_cursor(jmouse_x(0), jmouse_y(0));
drawBrushPreview(jmouse_x(0), jmouse_y(0));
jmouse_show();
}
}
@ -785,7 +785,7 @@ void Editor::hideDrawingCursor()
{
if (m_cursor_thick) {
jmouse_hide();
editor_clean_cursor();
clearBrushPreview();
jmouse_show();
}
}
@ -803,7 +803,7 @@ void Editor::moveDrawingCursor()
// when the mouse moves only).
if ((m_cursor_screen_x != x) || (m_cursor_screen_y != y)) {
jmouse_hide();
editor_move_cursor(x, y);
moveBrushPreview(x, y);
jmouse_show();
}
}
@ -1025,7 +1025,7 @@ void Editor::onPaint(ui::PaintEvent& ev)
int old_cursor_thick = m_cursor_thick;
if (m_cursor_thick)
editor_clean_cursor();
clearBrushPreview();
// Editor without sprite
if (!m_sprite) {
@ -1051,7 +1051,7 @@ void Editor::onPaint(ui::PaintEvent& ev)
// Draw the cursor again
if (old_cursor_thick != 0) {
editor_draw_cursor(jmouse_x(0), jmouse_y(0));
drawBrushPreview(jmouse_x(0), jmouse_y(0));
}
}
catch (const LockedDocumentException&) {

View File

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

View File

@ -28,6 +28,10 @@ namespace {
return (she::Color)color;
}
inline ui::Color from_she(she::Color color) {
return (ui::Color)color;
}
}
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
{
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));
}
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)
{
she::ScopedSurfaceLock dst(m_surface);

View File

@ -34,6 +34,9 @@ namespace ui {
Graphics(she::Surface* surface, int dx, int dy);
~Graphics();
int width() const;
int height() const;
she::Surface* getInternalSurface() { return m_surface; }
int getInternalDeltaX() { return m_dx; }
int getInternalDeltaY() { return m_dy; }
@ -42,6 +45,9 @@ namespace ui {
void setClipBounds(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 drawVLine(ui::Color color, int x, int y, int h);
void drawLine(ui::Color color, const gfx::Point& a, const gfx::Point& b);
@ -91,6 +97,29 @@ namespace ui {
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
// (in the life-time of the IntersectClip instance).
class IntersectClip {