aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--TODO6
-rw-r--r--gui/about.cpp32
-rw-r--r--gui/about.h4
-rw-r--r--gui/newgui.cpp48
-rw-r--r--gui/newgui.h13
5 files changed, 92 insertions, 11 deletions
diff --git a/TODO b/TODO
index 1e5bfd5994..fe68887071 100644
--- a/TODO
+++ b/TODO
@@ -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);