diff --git a/data/gui/widget/button_default.cfg b/data/gui/widget/button_default.cfg index 3ac5fbe34a301..0e353ed1909e3 100644 --- a/data/gui/widget/button_default.cfg +++ b/data/gui/widget/button_default.cfg @@ -30,8 +30,8 @@ [image] x = 2 y = 2 - w = "(width)" - h = "(height)" + w = "(width - 2)" + h = "(height - 2)" name = "buttons/button_normal/{BACKGROUND_IMAGE}.png{IPF}" [/image] diff --git a/src/gui/core/canvas.cpp b/src/gui/core/canvas.cpp index fa04aaeb37b1c..bf9fc5d853fad 100644 --- a/src/gui/core/canvas.cpp +++ b/src/gui/core/canvas.cpp @@ -103,7 +103,8 @@ static void set_renderer_color(SDL_Renderer* renderer, color_t color) * @param x2 The end x coordinate of the line to draw. * @param y2 The end y coordinate of the line to draw. */ -static void draw_line(surface& canvas, +static void draw_line(const int canvas_w, + const int canvas_h, SDL_Renderer* renderer, color_t color, unsigned x1, @@ -111,16 +112,14 @@ static void draw_line(surface& canvas, const unsigned x2, unsigned y2) { - unsigned w = canvas->w; - DBG_GUI_D << "Shape: draw line from " << x1 << ',' << y1 << " to " << x2 - << ',' << y2 << " canvas width " << w << " canvas height " - << canvas->h << ".\n"; + << ',' << y2 << " canvas width " << canvas_w << " canvas height " + << canvas_h << ".\n"; - assert(static_cast(x1) < canvas->w); - assert(static_cast(x2) < canvas->w); - assert(static_cast(y1) < canvas->h); - assert(static_cast(y2) < canvas->h); + assert(static_cast(x1) < canvas_w); + assert(static_cast(x2) < canvas_w); + assert(static_cast(y1) < canvas_h); + assert(static_cast(y2) < canvas_h); set_renderer_color(renderer, color); @@ -147,22 +146,23 @@ static void draw_line(surface& canvas, * @tparam octants A bitfield indicating which octants to draw, starting at twelve o'clock and moving clockwise. */ template -static void draw_circle(surface& canvas, +static void draw_circle(const int canvas_w, + const int canvas_h, SDL_Renderer* renderer, color_t color, const int x_center, const int y_center, const int radius) { - unsigned w = canvas->w; + unsigned w = canvas_w; DBG_GUI_D << "Shape: draw circle at " << x_center << ',' << y_center << " with radius " << radius << " canvas width " << w - << " canvas height " << canvas->h << ".\n"; + << " canvas height " << canvas_h << ".\n"; - if(octants & 0x0f) assert((x_center + radius) < canvas->w); + if(octants & 0x0f) assert((x_center + radius) < canvas_w); if(octants & 0xf0) assert((x_center - radius) >= 0); - if(octants & 0x3c) assert((y_center + radius) < canvas->h); + if(octants & 0x3c) assert((y_center + radius) < canvas_h); if(octants & 0xc3) assert((y_center - radius) >= 0); set_renderer_color(renderer, color); @@ -213,22 +213,23 @@ static void draw_circle(surface& canvas, * @tparam octants A bitfield indicating which octants to draw, starting at twelve o'clock and moving clockwise. */ template -static void fill_circle(surface& canvas, +static void fill_circle(const int canvas_w, + const int canvas_h, SDL_Renderer* renderer, color_t color, const int x_center, const int y_center, const int radius) { - unsigned w = canvas->w; + unsigned w = canvas_w; DBG_GUI_D << "Shape: draw filled circle at " << x_center << ',' << y_center << " with radius " << radius << " canvas width " << w - << " canvas height " << canvas->h << ".\n"; + << " canvas height " << canvas_h << ".\n"; - if(octants & 0x0f) assert((x_center + radius) < canvas->w); + if(octants & 0x0f) assert((x_center + radius) < canvas_w); if(octants & 0xf0) assert((x_center - radius) >= 0); - if(octants & 0x3c) assert((y_center + radius) < canvas->h); + if(octants & 0x3c) assert((y_center + radius) < canvas_h); if(octants & 0xc3) assert((y_center - radius) >= 0); set_renderer_color(renderer, color); @@ -594,9 +595,11 @@ line_shape::line_shape(const config& cfg) } } -void line_shape::draw(surface& canvas, - SDL_Renderer* renderer, - wfl::map_formula_callable& variables) +void line_shape::draw( + const int canvas_w, + const int canvas_h, + SDL_Renderer* renderer, + wfl::map_formula_callable& variables) { /** * @todo formulas are now recalculated every draw cycle which is a bit silly @@ -610,21 +613,18 @@ void line_shape::draw(surface& canvas, const unsigned y2 = y2_(variables); DBG_GUI_D << "Line: draw from " << x1 << ',' << y1 << " to " << x2 << ',' - << y2 << " canvas size " << canvas->w << ',' << canvas->h + << y2 << " canvas size " << canvas_w << ',' << canvas_h << ".\n"; - VALIDATE(static_cast(x1) < canvas->w - && static_cast(x2) < canvas->w - && static_cast(y1) < canvas->h - && static_cast(y2) < canvas->h, + VALIDATE(static_cast(x1) < canvas_w + && static_cast(x2) < canvas_w + && static_cast(y1) < canvas_h + && static_cast(y2) < canvas_h, _("Line doesn't fit on canvas.")); // @todo FIXME respect the thickness. - // lock the surface - surface_lock locker(canvas); - - draw_line(canvas, renderer, color_(variables), x1, y1, x2, y2); + draw_line(canvas_w, canvas_h, renderer, color_(variables), x1, y1, x2, y2); } /***** ***** ***** ***** ***** Rectangle ***** ***** ***** ***** *****/ @@ -683,9 +683,11 @@ rectangle_shape::rectangle_shape(const config& cfg) } } -void rectangle_shape::draw(surface& canvas, - SDL_Renderer* renderer, - wfl::map_formula_callable& variables) +void rectangle_shape::draw( + const int canvas_w, + const int canvas_h, + SDL_Renderer* renderer, + wfl::map_formula_callable& variables) { /** * @todo formulas are now recalculated every draw cycle which is a bit @@ -698,13 +700,13 @@ void rectangle_shape::draw(surface& canvas, const int h = h_(variables); DBG_GUI_D << "Rectangle: draw from " << x << ',' << y << " width " << w - << " height " << h << " canvas size " << canvas->w << ',' - << canvas->h << ".\n"; + << " height " << h << " canvas size " << canvas_w << ',' + << canvas_h << ".\n"; - VALIDATE(x < canvas->w - && x + w <= canvas->w - && y < canvas->h - && y + h <= canvas->h, _("Rectangle doesn't fit on canvas.")); + VALIDATE(x < canvas_w + && x + w <= canvas_w + && y < canvas_h + && y + h <= canvas_h, _("Rectangle doesn't fit on canvas.")); surface_lock locker(canvas); @@ -797,9 +799,11 @@ round_rectangle_shape::round_rectangle_shape(const config& cfg) } } -void round_rectangle_shape::draw(surface& canvas, - SDL_Renderer* renderer, - wfl::map_formula_callable& variables) +void round_rectangle_shape::draw( + const int canvas_w, + const int canvas_h, + SDL_Renderer* renderer, + wfl::map_formula_callable& variables) { /** * @todo formulas are now recalculated every draw cycle which is a bit @@ -813,13 +817,13 @@ void round_rectangle_shape::draw(surface& canvas, const int r = r_(variables); DBG_GUI_D << "Rounded Rectangle: draw from " << x << ',' << y << " width " << w - << " height " << h << " canvas size " << canvas->w << ',' - << canvas->h << ".\n"; + << " height " << h << " canvas size " << canvas_w << ',' + << canvas_h << ".\n"; - VALIDATE(x < canvas->w - && x + w <= canvas->w - && y < canvas->h - && y + h <= canvas->h, _("Rounded Rectangle doesn't fit on canvas.")); + VALIDATE(x < canvas_w + && x + w <= canvas_w + && y < canvas_h + && y + h <= canvas_h, _("Rounded Rectangle doesn't fit on canvas.")); surface_lock locker(canvas); @@ -837,10 +841,10 @@ void round_rectangle_shape::draw(surface& canvas, SDL_RenderFillRects(renderer, area, count); - fill_circle<0xc0>(canvas, renderer, fill_color, x + r, y + r, r); - fill_circle<0x03>(canvas, renderer, fill_color, x + w - r, y + r, r); - fill_circle<0x30>(canvas, renderer, fill_color, x + r, y + h - r, r); - fill_circle<0x0c>(canvas, renderer, fill_color, x + w - r, y + h - r, r); + fill_circle<0xc0>(canvas_w, canvas_h, renderer, fill_color, x + r, y + r, r); + fill_circle<0x03>(canvas_w, canvas_h, renderer, fill_color, x + w - r, y + r, r); + fill_circle<0x30>(canvas_w, canvas_h, renderer, fill_color, x + r, y + h - r, r); + fill_circle<0x0c>(canvas_w, canvas_h, renderer, fill_color, x + w - r, y + h - r, r); } const color_t border_color = border_color_(variables); @@ -855,10 +859,10 @@ void round_rectangle_shape::draw(surface& canvas, SDL_RenderDrawLine(renderer, x + i, y + r, x + i, y + h - r); SDL_RenderDrawLine(renderer, x + w - i, y + r, x + w - i, y + h - r); - draw_circle<0xc0>(canvas, renderer, border_color, x + r, y + r, r - i); - draw_circle<0x03>(canvas, renderer, border_color, x + w - r, y + r, r - i); - draw_circle<0x30>(canvas, renderer, border_color, x + r, y + h - r, r - i); - draw_circle<0x0c>(canvas, renderer, border_color, x + w - r, y + h - r, r - i); + draw_circle<0xc0>(canvas_w, canvas_h, renderer, border_color, x + r, y + r, r - i); + draw_circle<0x03>(canvas_w, canvas_h, renderer, border_color, x + w - r, y + r, r - i); + draw_circle<0x30>(canvas_w, canvas_h, renderer, border_color, x + r, y + h - r, r - i); + draw_circle<0x0c>(canvas_w, canvas_h, renderer, border_color, x + w - r, y + h - r, r - i); } } @@ -909,9 +913,11 @@ circle_shape::circle_shape(const config& cfg) } } -void circle_shape::draw(surface& canvas, - SDL_Renderer* renderer, - wfl::map_formula_callable& variables) +void circle_shape::draw( + const int canvas_w, + const int canvas_h, + SDL_Renderer* renderer, + wfl::map_formula_callable& variables) { /** * @todo formulas are now recalculated every draw cycle which is a bit @@ -924,7 +930,7 @@ void circle_shape::draw(surface& canvas, const unsigned radius = radius_(variables); DBG_GUI_D << "Circle: drawn at " << x << ',' << y << " radius " << radius - << " canvas size " << canvas->w << ',' << canvas->h << ".\n"; + << " canvas size " << canvas_w << ',' << canvas_h << ".\n"; VALIDATE_WITH_DEV_MESSAGE( static_cast(x - radius) >= 0, @@ -937,28 +943,28 @@ void circle_shape::draw(surface& canvas, formatter() << "y = " << y << ", radius = " << radius); VALIDATE_WITH_DEV_MESSAGE( - static_cast(x + radius) < canvas->w, + static_cast(x + radius) < canvas_w, _("Circle doesn't fit on canvas."), formatter() << "x = " << x << ", radius = " << radius - << "', canvas width = " << canvas->w << "."); + << "', canvas width = " << canvas_w << "."); VALIDATE_WITH_DEV_MESSAGE( - static_cast(y + radius) < canvas->h, + static_cast(y + radius) < canvas_h, _("Circle doesn't fit on canvas."), formatter() << "y = " << y << ", radius = " << radius - << "', canvas height = " << canvas->h << "."); + << "', canvas height = " << canvas_h << "."); // lock the surface surface_lock locker(canvas); const color_t fill_color = fill_color_(variables); if(!fill_color.null() && radius) { - fill_circle(canvas, renderer, fill_color, x, y, radius); + fill_circle(canvas_w, canvas_h, renderer, fill_color, x, y, radius); } const color_t border_color = border_color_(variables); for(unsigned int i = 0; i < border_thickness_; i++) { - draw_circle(canvas, renderer, border_color, x, y, radius - i); + draw_circle(canvas_w, canvas_h, renderer, border_color, x, y, radius - i); } } @@ -1049,9 +1055,11 @@ void image_shape::dimension_validation(unsigned value, const std::string& name, ); } -void image_shape::draw(surface& canvas, - SDL_Renderer* /*renderer*/, - wfl::map_formula_callable& variables) +void image_shape::draw( + const int /*canvas_w*/, + const int /*canvas_h*/, + SDL_Renderer* renderer, + wfl::map_formula_callable& variables) { DBG_GUI_D << "Image: draw.\n"; @@ -1071,14 +1079,13 @@ void image_shape::draw(surface& canvas, * The locator might return a different surface for every call so we can't * cache the output, also not if no formula is used. */ - surface tmp(image::get_image(image::locator(name))); + image_.assign(make_neutral_surface(image::get_image(image::locator(name)))); - if(!tmp) { + if(!image_) { ERR_GUI_D << "Image: '" << name << "' not found and won't be drawn." << std::endl; return; } - image_.assign(make_neutral_surface(tmp)); assert(image_); src_clip_ = {0, 0, image_->w, image_->h}; @@ -1108,9 +1115,8 @@ void image_shape::draw(surface& canvas, wfl::variant(variables.fake_ptr()).execute_variant(actions_formula_.evaluate(local_variables)); // Copy the data to local variables to avoid overwriting the originals. - SDL_Rect src_clip = src_clip_; SDL_Rect dst_clip = sdl::create_rect(clip_x, clip_y, 0, 0); - surface surf; + surface surf(nullptr); // Test whether we need to scale and do the scaling if needed. if(w || h) { @@ -1121,6 +1127,7 @@ void image_shape::draw(surface& canvas, DBG_GUI_D << "Image: vertical stretch from " << image_->w << ',' << image_->h << " to a height of " << h << ".\n"; + // TODO: convert to texture handling. surf = stretch_surface_vertical(image_, h); done = true; } @@ -1133,6 +1140,7 @@ void image_shape::draw(surface& canvas, << ',' << image_->h << " to a width of " << w << ".\n"; + // TODO: convert to texture handling. surf = stretch_surface_horizontal(image_, w); done = true; } @@ -1145,11 +1153,13 @@ void image_shape::draw(surface& canvas, DBG_GUI_D << "Image: tiling from " << image_->w << ',' << image_->h << " to " << w << ',' << h << ".\n"; + // TODO: convert to texture handling. surf = tile_surface(image_, w, h, false); } else if(resize_mode_ == tile_center) { DBG_GUI_D << "Image: tiling centrally from " << image_->w << ',' << image_->h << " to " << w << ',' << h << ".\n"; + // TODO: convert to texture handling. surf = tile_surface(image_, w, h, true); } else { if(resize_mode_ == stretch) { @@ -1160,20 +1170,33 @@ void image_shape::draw(surface& canvas, DBG_GUI_D << "Image: scaling from " << image_->w << ',' << image_->h << " to " << w << ',' << h << ".\n"; - surf = scale_surface(image_, w, h); + // Textures are automatically scaled to size. } } - src_clip.w = w; - src_clip.h = h; - } else { + } + + if(!surf) { surf = image_; } + dst_clip.w = w ? w : surf->w; + dst_clip.h = h ? h : surf->h; + + /* NOTE: we cannot use SDL_UpdateTexture to copy the surface pixel data directly to the canvas texture + * since no alpha blending occurs; values (even pure alpha) totally overwrite the underlying pixel data. + * + * To work around that, we create a texture from the surface and copy it to the renderer. This cleanly + * copies the surface to the canvas texture with the appropriate alpha blending. + */ + SDL_Texture* txt = SDL_CreateTextureFromSurface(renderer, surf); + if(vertical_mirror_(local_variables)) { - surf = flip_surface(surf); + SDL_RenderCopyEx(renderer, txt, nullptr, &dst_clip, 0, nullptr, SDL_FLIP_VERTICAL); + } else { + SDL_RenderCopy(renderer, txt, nullptr, &dst_clip); } - blit_surface(surf, &src_clip, canvas, &dst_clip); + SDL_DestroyTexture(txt); } image_shape::resize_mode image_shape::get_resize_mode(const std::string& resize_mode) @@ -1274,9 +1297,11 @@ text_shape::text_shape(const config& cfg) } } -void text_shape::draw(surface& canvas, - SDL_Renderer* /*renderer*/, - wfl::map_formula_callable& variables) +void text_shape::draw( + const int canvas_w, + const int canvas_h, + SDL_Renderer* renderer, + wfl::map_formula_callable& variables) { assert(variables.has_key("text")); @@ -1337,9 +1362,9 @@ void text_shape::draw(surface& canvas, DBG_GUI_D << "Text: drawing text '" << text << "' drawn from " << x << ',' << y << " width " << w << " height " << h << " canvas size " - << canvas->w << ',' << canvas->h << ".\n"; + << canvas_w << ',' << canvas_h << ".\n"; - VALIDATE(static_cast(x) < canvas->w && static_cast(y) < canvas->h, + VALIDATE(static_cast(x) < canvas_w && static_cast(y) < canvas_h, _("Text doesn't start on canvas.")); // A text might be to long and will be clipped. @@ -1353,8 +1378,18 @@ void text_shape::draw(surface& canvas, "canvas and will be clipped.\n"; } - SDL_Rect dst = sdl::create_rect(x, y, canvas->w, canvas->h); - blit_surface(surf, nullptr, canvas, &dst); + SDL_Rect dst = sdl::create_rect(x, y, surf->w, surf->h); + + /* NOTE: we cannot use SDL_UpdateTexture to copy the surface pixel data directly to the canvas texture + * since no alpha blending occurs; values (even pure alpha) totally overwrite the underlying pixel data. + * + * To work around that, we create a texture from the surface and copy it to the renderer. This cleanly + * copies the surface to the canvas texture with the appropriate alpha blending. + */ + SDL_Texture* txt = SDL_CreateTextureFromSurface(renderer, surf); + SDL_RenderCopy(renderer, txt, nullptr, &dst); + + SDL_DestroyTexture(txt); } /***** ***** ***** ***** ***** CANVAS ***** ***** ***** ***** *****/ @@ -1364,8 +1399,8 @@ canvas::canvas() , blur_depth_(0) , w_(0) , h_(0) - , canvas_() - , renderer_(nullptr) + , texture_(nullptr) + , renderer_(*CVideo::get_singleton().get_window()) , variables_() , functions_() , is_dirty_(true) @@ -1374,7 +1409,8 @@ canvas::canvas() canvas::~canvas() { - SDL_DestroyRenderer(renderer_); + SDL_SetRenderTarget(renderer_, nullptr); + SDL_DestroyTexture(texture_); } void canvas::draw(const bool force) @@ -1391,31 +1427,44 @@ void canvas::draw(const bool force) variables_.add("height", wfl::variant(h_)); } - // create surface - DBG_GUI_D << "Canvas: create new empty canvas.\n"; - canvas_.assign(create_neutral_surface(w_, h_)); + DBG_GUI_D << "Canvas: resetting canvas.\n"; + + // Recreate the texture. + if(texture_) { + SDL_DestroyTexture(texture_); + } - SDL_DestroyRenderer(renderer_); + texture_ = SDL_CreateTexture(renderer_, SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_TARGET, w_, h_); + assert(texture_); - renderer_ = SDL_CreateSoftwareRenderer(canvas_); - SDL_SetRenderDrawBlendMode(renderer_, SDL_BLENDMODE_BLEND); + SDL_SetTextureBlendMode(texture_, SDL_BLENDMODE_BLEND); - // draw items + SDL_SetRenderTarget(renderer_, texture_); + + // Draw items. for(auto& shape : shapes_) { lg::scope_logger inner_scope_logging_object__(log_gui_draw, "Canvas: draw shape."); - shape->draw(canvas_, renderer_, variables_); + shape->draw(w_, h_, renderer_, variables_); } - SDL_RenderPresent(renderer_); + SDL_SetRenderTarget(renderer_, nullptr); is_dirty_ = false; } -void canvas::blit(surface& surf, SDL_Rect rect) +void canvas::blit(surface& /*surf*/, SDL_Rect rect) { + SDL_RenderSetViewport(renderer_, &rect); + draw(); + SDL_RenderCopy(renderer_, texture_, nullptr, nullptr); + + SDL_RenderSetViewport(renderer_, nullptr); + + // TODO: reenable +#if 0 if(blur_depth_) { /* * If the surf is the video surface the blurring seems to stack, this @@ -1432,8 +1481,7 @@ void canvas::blit(surface& surf, SDL_Rect rect) sdl_blit(s, nullptr, surf, &r); } } - - sdl_blit(canvas_, nullptr, surf, &rect); +#endif } void canvas::parse_cfg(const config& cfg) diff --git a/src/gui/core/canvas.hpp b/src/gui/core/canvas.hpp index e805eab81553e..0b9ab5bc63652 100644 --- a/src/gui/core/canvas.hpp +++ b/src/gui/core/canvas.hpp @@ -64,14 +64,15 @@ class canvas /** * Draws the canvas. * - * @param canvas The resulting image will be blitted upon this - * canvas. * @param variables The canvas can have formulas in it's * definition, this parameter contains the values * for these formulas. */ - virtual void draw(surface& canvas, SDL_Renderer* renderer, - wfl::map_formula_callable& variables) = 0; + virtual void draw( + const int canvas_w, + const int canvas_h, + SDL_Renderer* renderer, + wfl::map_formula_callable& variables) = 0; bool immutable() const { @@ -160,11 +161,6 @@ class canvas return h_; } - surface& surf() - { - return canvas_; - } - void set_variable(const std::string& key, const wfl::variant& value) { variables_.add(key, value); @@ -196,9 +192,10 @@ class canvas /** Height of the canvas. */ unsigned h_; - /** The surface we draw all items on. */ - surface canvas_; + /** The texture onto which items are drawn. */ + SDL_Texture* texture_; + /** A pointer to the window renderer. */ SDL_Renderer* renderer_; /** The variables of the canvas. */ diff --git a/src/gui/core/canvas_private.hpp b/src/gui/core/canvas_private.hpp index e5602f371b3b4..7cc82f49c9f4b 100644 --- a/src/gui/core/canvas_private.hpp +++ b/src/gui/core/canvas_private.hpp @@ -30,9 +30,11 @@ class line_shape : public canvas::shape { explicit line_shape(const config& cfg); /** Implement shape::draw(). */ - void draw(surface& canvas, - SDL_Renderer* renderer, - wfl::map_formula_callable& variables) override; + void draw( + const int canvas_w, + const int canvas_h, + SDL_Renderer* renderer, + wfl::map_formula_callable& variables) override; private: typed_formula x1_, /**< The start x coordinate of the line. */ @@ -66,9 +68,11 @@ class rectangle_shape : public canvas::shape { explicit rectangle_shape(const config& cfg); /** Implement shape::draw(). */ - void draw(surface& canvas, - SDL_Renderer* renderer, - wfl::map_formula_callable& variables) override; + void draw( + const int canvas_w, + const int canvas_h, + SDL_Renderer* renderer, + wfl::map_formula_callable& variables) override; private: typed_formula x_, /**< The x coordinate of the rectangle. */ @@ -111,10 +115,11 @@ class round_rectangle_shape : public canvas::shape { explicit round_rectangle_shape(const config& cfg); /** Implement shape::draw(). */ - void draw(surface& canvas, - SDL_Renderer* renderer, - wfl::map_formula_callable& variables) override; - + void draw( + const int canvas_w, + const int canvas_h, + SDL_Renderer* renderer, + wfl::map_formula_callable& variables) override; private: typed_formula x_, /**< The x coordinate of the rectangle. */ y_, /**< The y coordinate of the rectangle. */ @@ -157,9 +162,11 @@ class circle_shape : public canvas::shape { explicit circle_shape(const config& cfg); /** Implement shape::draw(). */ - void draw(surface& canvas, - SDL_Renderer* renderer, - wfl::map_formula_callable& variables) override; + void draw( + const int canvas_w, + const int canvas_h, + SDL_Renderer* renderer, + wfl::map_formula_callable& variables) override; private: typed_formula x_, /**< The center x coordinate of the circle. */ @@ -186,10 +193,11 @@ class image_shape : public canvas::shape { image_shape(const config& cfg, wfl::action_function_symbol_table& functions); /** Implement shape::draw(). */ - void draw(surface& canvas, - SDL_Renderer* renderer, - wfl::map_formula_callable& variables) override; - + void draw( + const int canvas_w, + const int canvas_h, + SDL_Renderer* renderer, + wfl::map_formula_callable& variables) override; private: typed_formula x_, /**< The x coordinate of the image. */ y_, /**< The y coordinate of the image. */ @@ -252,9 +260,11 @@ class text_shape : public canvas::shape { explicit text_shape(const config& cfg); /** Implement shape::draw(). */ - void draw(surface& canvas, - SDL_Renderer* renderer, - wfl::map_formula_callable& variables) override; + void draw( + const int canvas_w, + const int canvas_h, + SDL_Renderer* renderer, + wfl::map_formula_callable& variables) override; private: typed_formula x_, /**< The x coordinate of the text. */ diff --git a/src/gui/core/event/handler.cpp b/src/gui/core/event/handler.cpp index 5b90e64237b30..00bf4ae289593 100644 --- a/src/gui/core/event/handler.cpp +++ b/src/gui/core/event/handler.cpp @@ -30,6 +30,8 @@ #include +#include + /** * @todo The items below are not implemented yet. * @@ -518,6 +520,21 @@ void sdl_event_handler::draw(const bool force) // Don't display this event since it floods the screen // DBG_GUI_E << "Firing " << DRAW << ".\n"; + // Don't draw anything if we have no dispatcher. + if(dispatchers_.empty()) { + return; + } + + CVideo& video = dynamic_cast(*dispatchers_.back()).video(); + + /** + * Clear the renderer before beginning the draw cycle. + */ + SDL_Renderer* renderer = *video.get_window(); + + SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255); + SDL_RenderClear(renderer); + /* * In normal draw mode the first window in not forced to be drawn the * others are. So for forced mode we only need to force the first window to @@ -547,11 +564,8 @@ void sdl_event_handler::draw(const bool force) dispatcher->fire(DRAW, dynamic_cast(*dispatcher)); } - if(!dispatchers_.empty()) { - CVideo& video = dynamic_cast(*dispatchers_.back()).video(); - - video.flip(); - } + // Finally, render the screen. + video.flip(); } void sdl_event_handler::video_resize(const point& new_size) diff --git a/src/gui/widgets/widget.cpp b/src/gui/widgets/widget.cpp index 96d39b76c6548..8d7cf2af425be 100644 --- a/src/gui/widgets/widget.cpp +++ b/src/gui/widgets/widget.cpp @@ -431,12 +431,12 @@ void widget::populate_dirty_list(window& caller, } call_stack.push_back(this); - if(is_dirty_) { + //if(is_dirty_) { caller.add_to_dirty_list(call_stack); - } else { + //} else { // virtual function which only does something for container items. - child_populate_dirty_list(caller, call_stack); - } + // child_populate_dirty_list(caller, call_stack); + //} } void diff --git a/src/gui/widgets/window.cpp b/src/gui/widgets/window.cpp index 1c0f853da8975..8de8d806de469 100644 --- a/src/gui/widgets/window.cpp +++ b/src/gui/widgets/window.cpp @@ -670,34 +670,37 @@ int window::show(const bool restore, const unsigned auto_close_timeout) suspend_drawing_ = true; // restore area - if(restore_) { - SDL_Rect rect = get_rectangle(); - sdl_blit(restorer_, 0, video_.getSurface(), &rect); - font::undraw_floating_labels(video_.getSurface()); - } + // if(restore_) { + // SDL_Rect rect = get_rectangle(); + // sdl_blit(restorer_, 0, video_.getSurface(), &rect); + // font::undraw_floating_labels(video_.getSurface()); + // } throw; } suspend_drawing_ = true; // restore area - if(restore_) { - SDL_Rect rect = get_rectangle(); - sdl_blit(restorer_, 0, video_.getSurface(), &rect); - font::undraw_floating_labels(video_.getSurface()); - } + //if(restore_) { + // SDL_Rect rect = get_rectangle(); + // sdl_blit(restorer_, 0, video_.getSurface(), &rect); + // font::undraw_floating_labels(video_.getSurface()); + //} return retval_; } void window::draw() { + //const size_t start = SDL_GetTicks(); + /***** ***** ***** ***** Init ***** ***** ***** *****/ // Prohibited from drawing? if(suspend_drawing_) { return; } + // TODO: remove surface& frame_buffer = video_.getSurface(); /***** ***** Layout and get dirty list ***** *****/ @@ -705,33 +708,35 @@ void window::draw() // Restore old surface. In the future this phase will not be needed // since all will be redrawn when needed with dirty rects. Since that // doesn't work yet we need to undraw the window. - if(restore_ && restorer_) { - SDL_Rect rect = get_rectangle(); - sdl_blit(restorer_, 0, frame_buffer, &rect); - } + //if(restore_ && restorer_) { + // SDL_Rect rect = get_rectangle(); + // sdl_blit(restorer_, 0, frame_buffer, &rect); + //} layout(); // Get new surface for restoring - SDL_Rect rect = get_rectangle(); + //SDL_Rect rect = get_rectangle(); // We want the labels underneath the window so draw them and use them // as restore point. if(is_toplevel_) { - font::draw_floating_labels(frame_buffer); + //font::draw_floating_labels(frame_buffer); } if(restore_) { - restorer_ = get_surface_portion(frame_buffer, rect); + //restorer_ = get_surface_portion(frame_buffer, rect); } // Need full redraw so only set ourselves dirty. - dirty_list_.emplace_back(1, this); + //dirty_list_.emplace_back(1, this); + + need_layout_ = false; } else { // Let widgets update themselves, which might dirty some things. layout_children(); - +#if 0 // Now find the widgets that are dirty. std::vector call_stack; if(!new_widgets) { @@ -741,20 +746,24 @@ void window::draw() dirty_list_.clear(); dirty_list_.emplace_back(1, this); } +#endif } - if (dirty_list_.empty()) { - return; - } + //if (dirty_list_.empty()) { + // return; + //} + + dirty_list_.clear(); + dirty_list_.emplace_back(1, this); for(auto & item : dirty_list_) { assert(!item.empty()); - const SDL_Rect dirty_rect - = new_widgets ? screen_area() - : item.back()->get_dirty_rectangle(); + //const SDL_Rect dirty_rect + // = new_widgets ? screen_area() + // : item.back()->get_dirty_rectangle(); // For testing we disable the clipping rect and force the entire screen to // update. This way an item rendered at the wrong place is directly visible. @@ -762,7 +771,7 @@ void window::draw() dirty_list_.clear(); dirty_list_.emplace_back(1, this); #else - clip_rect_setter clip(frame_buffer, &dirty_rect); + //clip_rect_setter clip(frame_buffer, &dirty_rect); #endif /* @@ -808,8 +817,8 @@ void window::draw() // Restore. if(restore_) { - SDL_Rect rect = get_rectangle(); - sdl_blit(restorer_, 0, frame_buffer, &rect); + //SDL_Rect rect = get_rectangle(); + //sdl_blit(restorer_, 0, frame_buffer, &rect); } // Background. @@ -838,8 +847,10 @@ void window::draw() dirty_list_.clear(); std::vector call_stack; - populate_dirty_list(*this, call_stack); - assert(dirty_list_.empty()); + + //std::cerr << "draw took, " << (SDL_GetTicks() - start) << " ms" << std::endl; + //populate_dirty_list(*this, call_stack); + //assert(dirty_list_.empty()); if(callback_next_draw_ != nullptr) { callback_next_draw_(); @@ -849,12 +860,14 @@ void window::draw() void window::undraw() { +#if 0 if(restore_ && restorer_) { SDL_Rect rect = get_rectangle(); sdl_blit(restorer_, 0, video_.getSurface(), &rect); // Since the old area might be bigger as the new one, invalidate // it. } +#endif // 0 } window::invalidate_layout_blocker::invalidate_layout_blocker(window& window) @@ -949,6 +962,7 @@ void window::remove_linked_widget(const std::string& id, const widget* wgt) void window::layout() { + std::cerr << "calling layout" << std::endl; /***** Initialize. *****/ std::shared_ptr