rockbox/apps/gui/splash.c
Linus Nielsen Feltzing 7da9477bc3 Initial multi screen support by Kévin Ferrare (Patch #1318081)
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@7666 a1c6a512-1295-4272-9138-f99709370657
2005-10-28 00:00:00 +00:00

216 lines
6 KiB
C

/***************************************************************************
* __________ __ ___.
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
* \/ \/ \/ \/ \/
* $Id$
*
* Copyright (C) Daniel Stenberg (2002), Kévin FERRARE (2005)
*
* All files in this archive are subject to the GNU General Public License.
* See the file COPYING in the source tree root for full license agreement.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
****************************************************************************/
#include "stdarg.h"
#include "string.h"
#include "stdio.h"
#include "kernel.h"
#include "screen_access.h"
#ifdef HAVE_LCD_BITMAP
#define SPACE 3 /* pixels between words */
#define MAXLETTERS 128 /* 16*8 */
#define MAXLINES 10
#else
#define SPACE 1 /* one letter space */
#define MAXLETTERS 22 /* 11 * 2 */
#define MAXLINES 2
#endif
void internal_splash(struct screen * screen,
bool center, const char *fmt, va_list ap)
{
char *next;
char *store=NULL;
int x=0;
int y=0;
int w, h;
unsigned char splash_buf[MAXLETTERS];
unsigned char widths[MAXLINES];
int line=0;
bool first=true;
#ifdef HAVE_LCD_BITMAP
int maxw=0;
#endif
#ifdef HAVE_LCD_CHARCELLS
screen->double_height (false);
#endif
vsnprintf( splash_buf, sizeof(splash_buf), fmt, ap );
if(center) {
/* first a pass to measure sizes */
next = strtok_r(splash_buf, " ", &store);
while (next) {
#ifdef HAVE_LCD_BITMAP
screen->getstringsize(next, &w, &h);
#else
w = strlen(next);
h = 1; /* store height in characters */
#endif
if(!first) {
if(x+w> screen->width) {
/* Too wide, wrap */
y+=h;
line++;
if((y > (screen->height-h)) || (line > screen->nb_lines))
/* STOP */
break;
x=0;
first=true;
}
}
else
first = false;
/* think of it as if the text was written here at position x,y
being w pixels/chars wide and h high */
x += w+SPACE;
widths[line]=x-SPACE; /* don't count the trailing space */
#ifdef HAVE_LCD_BITMAP
/* store the widest line */
if(widths[line]>maxw)
maxw = widths[line];
#endif
next = strtok_r(NULL, " ", &store);
}
#ifdef HAVE_LCD_BITMAP
/* Start displaying the message at position y. The reason for the
added h here is that it isn't added until the end of lines in the
loop above and we always break the loop in the middle of a line. */
y = (screen->height - (y+h) )/2;
#else
y = 0; /* vertical center on 2 lines would be silly */
#endif
first=true;
/* Now recreate the string again since the strtok_r() above has ruined
the one we already have! Here's room for improvements! */
vsnprintf( splash_buf, sizeof(splash_buf), fmt, ap );
}
va_end( ap );
if(center)
{
x = (screen->width-widths[0])/2;
if(x < 0)
x = 0;
}
#ifdef HAVE_LCD_BITMAP
/* If we center the display, then just clear the box we need and put
a nice little frame and put the text in there! */
if(center && (y > 2)) {
int xx = (screen->width-maxw)/2 - 2;
/* The new graphics routines handle clipping, so no need to check */
#if LCD_DEPTH > 1
#ifdef HAVE_LCD_COLOR
screen->set_background((struct rgb){LCD_MAX_RED-1, LCD_MAX_GREEN-1,
LCD_MAX_BLUE-1});
#else
if(screen->depth>1)
screen->set_background(LCD_MAX_LEVEL-1);
#endif
#endif
screen->set_drawmode(DRMODE_SOLID|DRMODE_INVERSEVID);
screen->fillrect(xx, y-2, maxw+4, screen->height-y*2+4);
screen->set_drawmode(DRMODE_SOLID);
screen->drawrect(xx, y-2, maxw+4, screen->height-y*2+4);
}
else
#endif
screen->clear_display();
line=0;
next = strtok_r(splash_buf, " ", &store);
while (next) {
#ifdef HAVE_LCD_BITMAP
screen->getstringsize(next, &w, &h);
#else
w = strlen(next);
h = 1;
#endif
if(!first) {
if(x+w> screen->width) {
/* too wide */
y+=h;
line++; /* goto next line */
first=true;
if(y > (screen->height-h))
/* STOP */
break;
if(center) {
x = (screen->width-widths[line])/2;
if(x < 0)
x = 0;
}
else
x=0;
}
}
else
first=false;
#ifdef HAVE_LCD_BITMAP
screen->putsxy(x, y, next);
#else
screen->puts(x, y, next);
#endif
x += w+SPACE; /* pixels space! */
next = strtok_r(NULL, " ", &store);
}
#if defined(HAVE_LCD_BITMAP) && (LCD_DEPTH > 1)
if(screen->depth > 1)
screen->set_background(LCD_WHITE);
#endif
#if defined(HAVE_LCD_BITMAP) || defined(SIMULATOR)
screen->update();
#endif
}
void gui_splash(struct screen * screen, int ticks,
bool center, const char *fmt, ...)
{
va_list ap;
va_start( ap, fmt );
internal_splash(screen, center, fmt, ap);
va_end( ap );
if(ticks)
sleep(ticks);
}
void gui_syncsplash(int ticks, bool center, const char *fmt, ...)
{
va_list ap;
int i;
va_start( ap, fmt );
for(i=0;i<NB_SCREENS;++i)
internal_splash(&(screens[i]), center, fmt, ap);
va_end( ap );
if(ticks)
sleep(ticks);
}