Patch #1183808 (GUI: Less CPU-intensive credits scroll), with some tweaks by me

svn-id: r17620
This commit is contained in:
Max Horn 2005-04-16 11:40:15 +00:00
parent e9be61a465
commit 7aebedcc14
5 changed files with 92 additions and 11 deletions

6
TODO
View File

@ -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
========

View File

@ -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();

View File

@ -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);

View File

@ -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);

View File

@ -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);