From 8a81837c04175c7ee463fb16cc1fa90372b3d614 Mon Sep 17 00:00:00 2001 From: Maarten ter Huurne Date: Fri, 3 Jun 2011 11:46:36 +0200 Subject: [PATCH] Surface: Make pixel format conversion explicit. Instead of having the copy constructor convert to display format, the new copy constructor preserves the pixel format and a separate method was introduced to convert surfaces to display format. The code was made more robust as well: it should no longer crash if the wallpaper cannot be loaded. --- src/gmenu2x.cpp | 30 +++++++++++++++--------------- src/linkapp.cpp | 11 ++++++++--- src/messagebox.cpp | 1 + src/selector.cpp | 2 ++ src/settingsdialog.cpp | 2 +- src/surface.cpp | 21 ++++++++++++++++++++- src/surface.h | 7 +++++++ src/textdialog.cpp | 2 ++ src/textmanualdialog.cpp | 2 ++ 9 files changed, 58 insertions(+), 20 deletions(-) diff --git a/src/gmenu2x.cpp b/src/gmenu2x.cpp index 6a9df84..0510bef 100644 --- a/src/gmenu2x.cpp +++ b/src/gmenu2x.cpp @@ -344,14 +344,11 @@ void GMenu2X::quit() { void GMenu2X::initBG() { sc.del("bgmain"); - if (bg != NULL) free(bg); - - if (!fileExists(confStr["wallpaper"])) { - bg = new Surface(s); - bg->box(0,0,resX,resY,0,0,0); - } else { - // Note: Copy constructor converts to display format. - bg = new Surface(Surface::loadImage(confStr["wallpaper"])); + // Load wallpaper. + free(bg); + bg = Surface::loadImage(confStr["wallpaper"]); + if (!bg) { + bg = Surface::emptySurface(resX, resY); } drawTopBar(bg); @@ -361,20 +358,20 @@ void GMenu2X::initBG() { sc.add(bgmain,"bgmain"); Surface *sd = Surface::loadImage("imgs/sd.png", confStr["skin"]); - if (sd) sd->blit(sc["bgmain"], 3, bottomBarIconY); + if (sd) sd->blit(bgmain, 3, bottomBarIconY); string df = getDiskFree(); - sc["bgmain"]->write(font, df, 22, bottomBarTextY, ASFont::HAlignLeft, ASFont::VAlignMiddle); + bgmain->write(font, df, 22, bottomBarTextY, ASFont::HAlignLeft, ASFont::VAlignMiddle); free(sd); Surface *volume = Surface::loadImage("imgs/volume.png", confStr["skin"]); volumeX = 27+font->getTextWidth(df); - if (volume) volume->blit(sc["bgmain"], volumeX, bottomBarIconY); + if (volume) volume->blit(bgmain, volumeX, bottomBarIconY); volumeX += 19; free(volume); Surface *cpu = Surface::loadImage("imgs/cpu.png", confStr["skin"]); cpuX = volumeX+font->getTextWidth("100")+5; - if (cpu) cpu->blit(sc["bgmain"], cpuX, bottomBarIconY); + if (cpu) cpu->blit(bgmain, cpuX, bottomBarIconY); cpuX += 19; manualX = cpuX+font->getTextWidth("300Mhz")+5; free(cpu); @@ -384,24 +381,26 @@ void GMenu2X::initBG() { if (web) { Surface *webserver = Surface::loadImage( "imgs/webserver.png", confStr["skin"]); - if (webserver) webserver->blit(sc["bgmain"], serviceX, bottomBarIconY); + if (webserver) webserver->blit(bgmain, serviceX, bottomBarIconY); serviceX -= 19; free(webserver); } if (samba) { Surface *sambaS = Surface::loadImage( "imgs/samba.png", confStr["skin"]); - if (sambaS) sambaS->blit(sc["bgmain"], serviceX, bottomBarIconY); + if (sambaS) sambaS->blit(bgmain, serviceX, bottomBarIconY); serviceX -= 19; free(sambaS); } if (inet) { Surface *inetS = Surface::loadImage("imgs/inet.png", confStr["skin"]); - if (inetS) inetS->blit(sc["bgmain"], serviceX, bottomBarIconY); + if (inetS) inetS->blit(bgmain, serviceX, bottomBarIconY); serviceX -= 19; free(inetS); } } + + bgmain->convertToDisplayFormat(); } void GMenu2X::initFont() { @@ -1632,6 +1631,7 @@ void GMenu2X::scanner() { drawButton(&scanbg, "x", tr["Exit"], drawButton(&scanbg, "b", "", 5)-10); scanbg.write(font,tr["Link Scanner"],halfX,7,ASFont::HAlignCenter,ASFont::VAlignMiddle); + scanbg.convertToDisplayFormat(); uint lineY = 42; diff --git a/src/linkapp.cpp b/src/linkapp.cpp index 278dc47..c12179e 100644 --- a/src/linkapp.cpp +++ b/src/linkapp.cpp @@ -304,8 +304,12 @@ void LinkApp::showManual() { if (!pngman) { return; } - // Note: Copy constructor converts to display format. - Surface bg(Surface::loadImage(gmenu2x->confStr["wallpaper"])); + Surface *bg = Surface::loadImage(gmenu2x->confStr["wallpaper"]); + if (!bg) { + bg = Surface::emptySurface(gmenu2x->s->width(), gmenu2x->s->height()); + } + bg->convertToDisplayFormat(); + stringstream ss; string pageStatus; @@ -321,7 +325,7 @@ void LinkApp::showManual() { while (!close) { if (repaint) { - bg.blit(gmenu2x->s, 0, 0); + bg->blit(gmenu2x->s, 0, 0); pngman->blit(gmenu2x->s, -page*320, 0); gmenu2x->drawBottomBar(); @@ -361,6 +365,7 @@ void LinkApp::showManual() { break; } } + free(bg); return; } diff --git a/src/messagebox.cpp b/src/messagebox.cpp index d6e15a4..46bc28d 100644 --- a/src/messagebox.cpp +++ b/src/messagebox.cpp @@ -99,6 +99,7 @@ int MessageBox::exec() { } } + bg.convertToDisplayFormat(); bg.blit(gmenu2x->s,0,0); gmenu2x->s->flip(); diff --git a/src/selector.cpp b/src/selector.cpp index acf082f..d73a9bc 100644 --- a/src/selector.cpp +++ b/src/selector.cpp @@ -71,6 +71,8 @@ int Selector::exec(int startSelection) { gmenu2x->drawButton(&bg, "b", gmenu2x->tr["Select a file"], 5)); } + bg.convertToDisplayFormat(); + Uint32 selTick = SDL_GetTicks(), curTick; uint i, firstElement = 0, iY; diff --git a/src/settingsdialog.cpp b/src/settingsdialog.cpp index 5a0ac9c..e4b0bb3 100644 --- a/src/settingsdialog.cpp +++ b/src/settingsdialog.cpp @@ -45,8 +45,8 @@ SettingsDialog::~SettingsDialog() { } bool SettingsDialog::exec() { - //Surface bg (gmenu2x->confStr["wallpaper"],false); Surface bg(gmenu2x->bg); + bg.convertToDisplayFormat(); bool close = false, ts_pressed = false; uint i, sel = 0, iY, firstElement = 0, action; diff --git a/src/surface.cpp b/src/surface.cpp index a0a49b5..5293617 100644 --- a/src/surface.cpp +++ b/src/surface.cpp @@ -44,6 +44,14 @@ Surface *Surface::openOutputSurface(int width, int height, int bitsperpixel) { return raw ? new Surface(raw, false) : NULL; } +Surface *Surface::emptySurface(int width, int height) { + SDL_Surface *raw = SDL_CreateRGBSurface( + SDL_SWSURFACE, width, height, 32, 0, 0, 0, 0); + if (!raw) return NULL; + SDL_FillRect(raw, NULL, SDL_MapRGB(raw->format, 0, 0, 0)); + return new Surface(raw, true); +} + Surface *Surface::loadImage(const string &img, const string &skin) { string skinpath; if (!skin.empty() && !img.empty() && img[0]!='/') { @@ -72,7 +80,7 @@ Surface::Surface(SDL_Surface *raw_, bool freeWhenDone_) } Surface::Surface(Surface *s) { - raw = SDL_DisplayFormat(s->raw); + raw = SDL_ConvertSurface(s->raw, s->raw->format, SDL_SWSURFACE); freeWhenDone = true; halfW = raw->w/2; halfH = raw->h/2; @@ -84,6 +92,17 @@ Surface::~Surface() { } } +void Surface::convertToDisplayFormat() { + SDL_Surface *newSurface = SDL_DisplayFormat(raw); + if (newSurface) { + if (freeWhenDone) { + SDL_FreeSurface(raw); + } + raw = newSurface; + freeWhenDone = true; + } +} + void Surface::flip() { SDL_Flip(raw); } diff --git a/src/surface.h b/src/surface.h index 0386429..7f0070a 100644 --- a/src/surface.h +++ b/src/surface.h @@ -40,11 +40,18 @@ RGBAColor strtorgba(const string &strColor); class Surface { public: static Surface *openOutputSurface(int width, int height, int bitsperpixel); + static Surface *emptySurface(int width, int height); static Surface *loadImage(const string &img, const string &skin=""); Surface(Surface *s); ~Surface(); + /** Converts the underlying surface to the same pixel format as the frame + * buffer, for faster blitting. This removes the alpha channel if the + * image has done. + */ + void convertToDisplayFormat(); + int width() { return raw->w; } int height() { return raw->h; } diff --git a/src/textdialog.cpp b/src/textdialog.cpp index 4d12134..ef809c1 100644 --- a/src/textdialog.cpp +++ b/src/textdialog.cpp @@ -110,6 +110,8 @@ void TextDialog::exec() { gmenu2x->drawButton(&bg, "down", gmenu2x->tr["Scroll"], gmenu2x->drawButton(&bg, "up", "", 5)-10)); + bg.convertToDisplayFormat(); + uint firstRow = 0, rowsPerPage = (gmenu2x->resY-60)/gmenu2x->font->getHeight(); while (!close) { bg.blit(gmenu2x->s,0,0); diff --git a/src/textmanualdialog.cpp b/src/textmanualdialog.cpp index 4fb4a3f..6c2207f 100644 --- a/src/textmanualdialog.cpp +++ b/src/textmanualdialog.cpp @@ -80,6 +80,8 @@ void TextManualDialog::exec() { gmenu2x->drawButton(&bg, "down", gmenu2x->tr["Scroll"], gmenu2x->drawButton(&bg, "up", "", 5)-10))-10)); + bg.convertToDisplayFormat(); + uint firstRow = 0, rowsPerPage = 180/gmenu2x->font->getHeight(); stringstream ss; ss << pages.size();