diff --git a/src/app/color_utils.cpp b/src/app/color_utils.cpp index 47f3c5fbf..408aa910c 100644 --- a/src/app/color_utils.cpp +++ b/src/app/color_utils.cpp @@ -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) diff --git a/src/app/color_utils.h b/src/app/color_utils.h index 564f54bfa..1e49fdcc9 100644 --- a/src/app/color_utils.h +++ b/src/app/color_utils.h @@ -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); diff --git a/src/app/ui/editor/cursor.cpp b/src/app/ui/editor/cursor.cpp index 3d9977a6b..02e69597b 100644 --- a/src/app/ui/editor/cursor.cpp +++ b/src/app/ui/editor/cursor.cpp @@ -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 -#include #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)<>1)<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; cgetPixel(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++; diff --git a/src/app/ui/editor/editor.cpp b/src/app/ui/editor/editor.cpp index 466b8ef1f..23da8b848 100644 --- a/src/app/ui/editor/editor.cpp +++ b/src/app/ui/editor/editor.cpp @@ -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&) { diff --git a/src/app/ui/editor/editor.h b/src/app/ui/editor/editor.h index e1ed2253f..7bd73c405 100644 --- a/src/app/ui/editor/editor.h +++ b/src/app/ui/editor/editor.h @@ -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 diff --git a/src/she/alleg4/alleg4_surface.h b/src/she/alleg4/alleg4_surface.h index f862ff847..5b8078b46 100644 --- a/src/she/alleg4/alleg4_surface.h +++ b/src/she/alleg4/alleg4_surface.h @@ -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)); } diff --git a/src/she/locked_surface.h b/src/she/locked_surface.h index 4b21acc72..b873543d8 100644 --- a/src/she/locked_surface.h +++ b/src/she/locked_surface.h @@ -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; diff --git a/src/ui/graphics.cpp b/src/ui/graphics.cpp index e92b5afe3..10075139e 100644 --- a/src/ui/graphics.cpp +++ b/src/ui/graphics.cpp @@ -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); diff --git a/src/ui/graphics.h b/src/ui/graphics.h index 46286a9e6..9f78b0b31 100644 --- a/src/ui/graphics.h +++ b/src/ui/graphics.h @@ -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 {