diff options
-rw-r--r-- | TODO | 6 | ||||
-rw-r--r-- | gui/about.cpp | 32 | ||||
-rw-r--r-- | gui/about.h | 4 | ||||
-rw-r--r-- | gui/newgui.cpp | 48 | ||||
-rw-r--r-- | gui/newgui.h | 13 |
5 files changed, 92 insertions, 11 deletions
@@ -196,12 +196,6 @@ GUI * Maybe add the ScummVM logo (+typeface?) to the about dialog * Unify DirBrowserDialog and FileBrowserDialog. * MacOS X version of FileBrowserDialog, since there is one of DirBrowserDialog. -* The credits scroll is too CPU intensive. This is because for each time the - text is redrawn it has to do a full redraw, which causes blendRect() to be - called twice. Perhaps AboutDialog could keep a private copy of the blended - background so that it wouldn't have to be re-generated each time? Of course - we'd probably have to take screen changes into account, but there already is - a mechanism for that, I believe. Launcher ======== diff --git a/gui/about.cpp b/gui/about.cpp index 8ee240b9ed..d23ce9c0a4 100644 --- a/gui/about.cpp +++ b/gui/about.cpp @@ -120,16 +120,33 @@ void AboutDialog::open() { _scrollPos = 0; _modifiers = 0; _willClose = false; + _canvas.pixels = NULL; Dialog::open(); } +void AboutDialog::close() { + free(_canvas.pixels); + Dialog::close(); +} + void AboutDialog::drawDialog() { - // Blend over the background - g_gui.blendRect(_x, _y, _w, _h, g_gui._bgcolor); + if (!_canvas.pixels) { + // Blend over the background. Since we can't afford to do that + // every time the text is updated (it's horribly CPU intensive) + // we do it just once and then use a copy of the result as our + // static background for the remainder of the credits. + g_gui.blendRect(_x, _y, _w, _h, g_gui._bgcolor); + g_gui.copyToSurface(&_canvas, _x, _y, _w, _h); + } + + g_gui.drawSurface(_canvas, _x, _y); // Draw text // TODO: Add a "fade" effect for the top/bottom text lines + // TODO: Maybe prerender all of the text into another surface, + // and then simply compose that over the screen surface + // in the right way. Should be even faster... const int firstLine = _scrollPos / _lineHeight; const int lastLine = MIN((_scrollPos + _h) / _lineHeight + 1, (uint32)_lines.size()); int y = _y + kYOff - (_scrollPos % _lineHeight); @@ -212,13 +229,18 @@ void AboutDialog::handleTickle() { } else if ((uint32)_scrollPos > _lines.size() * _lineHeight) { _scrollPos = 0; _scrollTime += kScrollStartDelay; - } else { - g_gui.addDirtyRect(_x, _y, _w, _h); } - draw(); // Issue a full redraw + drawDialog(); } } +void AboutDialog::handleScreenChanged() { + // The screen has changed. Reset the canvas, to ensure it gets + // refreshed next time a redraw takes place. + free(_canvas.pixels); + _canvas.pixels = NULL; +} + void AboutDialog::handleMouseUp(int x, int y, int button, int clickCount) { // Close upon any mouse click close(); diff --git a/gui/about.h b/gui/about.h index 6507511f94..65dbb49f40 100644 --- a/gui/about.h +++ b/gui/about.h @@ -23,6 +23,7 @@ #include "gui/dialog.h" #include "common/str.h" +#include "graphics/surface.h" namespace GUI { @@ -35,13 +36,16 @@ protected: uint32 _lineHeight; byte _modifiers; bool _willClose; + Graphics::Surface _canvas; public: AboutDialog(); void open(); + void close(); void drawDialog(); void handleTickle(); + void handleScreenChanged(); void handleMouseUp(int x, int y, int button, int clickCount); void handleKeyDown(uint16 ascii, int keycode, int modifiers); void handleKeyUp(uint16 ascii, int keycode, int modifiers); diff --git a/gui/newgui.cpp b/gui/newgui.cpp index 232b4f8344..59f7149123 100644 --- a/gui/newgui.cpp +++ b/gui/newgui.cpp @@ -301,6 +301,54 @@ void NewGui::vLine(int x, int y, int y2, OverlayColor color) { _screen.vLine(x * _scaleFactor, y * _scaleFactor, y2 * _scaleFactor, color); } +void NewGui::copyToSurface(Graphics::Surface *s, int x, int y, int w, int h) { + Common::Rect rect(x * _scaleFactor, y * _scaleFactor, (x + w) * _scaleFactor, (y + h) * _scaleFactor); + rect.clip(_screen.w, _screen.h); + + if (!rect.isValidRect()) + return; + + s->w = rect.width(); + s->h = rect.height(); + s->bytesPerPixel = sizeof(OverlayColor); + s->pitch = s->w * s->bytesPerPixel; + s->pixels = (OverlayColor *)malloc(s->pitch * s->h); + + w = s->w; + h = s->h; + + OverlayColor *dst = (OverlayColor *)s->pixels; + OverlayColor *src = getBasePtr(rect.left, rect.top); + + while (h--) { + memcpy(dst, src, s->pitch); + src += _screenPitch; + dst += s->w; + } +} + +void NewGui::drawSurface(const Graphics::Surface &s, int x, int y) { + Common::Rect rect(x * _scaleFactor, y * _scaleFactor, x * _scaleFactor + s.w, y * _scaleFactor + s.h); + rect.clip(_screen.w, _screen.h); + + if (!rect.isValidRect()) + return; + + assert(s.bytesPerPixel == sizeof(OverlayColor)); + + OverlayColor *src = (OverlayColor *)s.pixels; + OverlayColor *dst = getBasePtr(rect.left, rect.top); + + int w = rect.width(); + int h = rect.height(); + + while (h--) { + memcpy(dst, src, s.pitch); + src += w; + dst += _screenPitch; + } +} + void NewGui::blendRect(int x, int y, int w, int h, OverlayColor color, int level) { #ifdef NEWGUI_256 fillRect(x, y, w, h, color); diff --git a/gui/newgui.h b/gui/newgui.h index 4acce206f7..78e166e6cf 100644 --- a/gui/newgui.h +++ b/gui/newgui.h @@ -134,6 +134,19 @@ public: void box(int x, int y, int width, int height, OverlayColor colorA, OverlayColor colorB); void hLine(int x, int y, int x2, OverlayColor color); void vLine(int x, int y, int y2, OverlayColor color); + + /** + * Copy the specified screen rectangle into a new graphics surfaces. + * New memory for the GFX data is allocated via malloc; it is the + * callers responsibilty to free that data. + */ + void copyToSurface(Graphics::Surface *s, int x, int y, int w, int h); + + /** + * Draw the graphics contained in the given surface at the specified coordinates. + */ + void drawSurface(const Graphics::Surface &s, int x, int y); + void blendRect(int x, int y, int w, int h, OverlayColor color, int level = 3); void fillRect(int x, int y, int w, int h, OverlayColor color); void frameRect(int x, int y, int w, int h, OverlayColor color); |