diff options
author | Teruaki Kawashima <teru@rockbox.org> | 2010-11-19 12:54:03 +0000 |
---|---|---|
committer | Teruaki Kawashima <teru@rockbox.org> | 2010-11-19 12:54:03 +0000 |
commit | ee6b0dae96617a5cfed3d155db9e5dda0b42f2ab (patch) | |
tree | 1204aa58a73dddd0b6c1235fe7b696b6c4315b50 /apps | |
parent | 579a7ebcf9df631496a2ffd592f3cd40150b0bfd (diff) | |
download | rockbox-ee6b0dae96617a5cfed3d155db9e5dda0b42f2ab.tar.gz rockbox-ee6b0dae96617a5cfed3d155db9e5dda0b42f2ab.zip |
rockpaint: cache font preview when browsing fonts.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@28623 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'apps')
-rw-r--r-- | apps/plugins/rockpaint.c | 225 |
1 files changed, 156 insertions, 69 deletions
diff --git a/apps/plugins/rockpaint.c b/apps/plugins/rockpaint.c index 00ac286167..4ef139a526 100644 --- a/apps/plugins/rockpaint.c +++ b/apps/plugins/rockpaint.c @@ -25,7 +25,6 @@ * - implement 2 layers with alpha colors * - take brush width into account when drawing shapes * - handle bigger than screen bitmaps - * - cache fonts when building the font preview (else it only works well on simulators because they have "fast" disk read) */ #include "plugin.h" @@ -455,9 +454,14 @@ union buf { char text[MAX_TEXT]; char font[MAX_PATH]; - char old_font[MAX_PATH]; - int fh_buf[80]; - int fw_buf[80]; + bool initialized; + size_t cache_used; + /* fonts from cache_first to cache_last are stored. */ + int cache_first; + int cache_last; + /* save these so that cache can be re-used next time. */ + int fvi; + int si; } text; }; @@ -488,11 +492,6 @@ static bool incdec_value(int *pval, struct incdec_ctx *ctx, bool inc, bool bigst return of; } -/* Font preview buffer */ -//#define FONT_PREVIEW_WIDTH ((LCD_WIDTH-30)/8) -//#define FONT_PREVIEW_HEIGHT 1000 -//static unsigned char fontpreview[FONT_PREVIEW_WIDTH*FONT_PREVIEW_HEIGHT]; - /*********************************************************************** * Offscreen buffer/Text/Fonts handling * @@ -797,7 +796,7 @@ static bool browse( char *dst, int dst_size, const char *start ) return true; } len = rb->strlen(e->name); - if (bbuf_len + len + 2 < (int)sizeof(bbuf)) + if( bbuf_len + len + 2 < (int)sizeof(bbuf) ) { bbuf_s[0] = '\0'; rb->strcpy( bbuf+bbuf_len, e->name ); @@ -823,35 +822,52 @@ static bool browse( char *dst, int dst_size, const char *start ) * on the simulators, disk spins too much on real targets -> rendered * font buffer needed. ***********************************************************************/ +/* + * cache font preview handling assumes: + * - fvi doesn't decrease by more than 1. + * In other words, cache_first-1 must be cached before cache_first-2 is cached. + * - there is enough space to store all preview currently displayed. + */ static bool browse_fonts( char *dst, int dst_size ) { #define LINE_SPACE 2 -#define fh_buf buffer->text.fh_buf -#define fw_buf buffer->text.fw_buf +#define PREVIEW_SIZE(x) ((x)->size) +#define PREVIEW_NEXT(x) (struct font_preview *)((char*)(x) + PREVIEW_SIZE(x)) struct tree_context backup; struct entry *dc, *e; int dirfilter = SHOW_FONT; + struct font_preview { + unsigned short width; + unsigned short height; + size_t size; /* to avoid calculating size each time. */ + fb_data preview[0]; + } *font_preview = NULL; + int top = 0; int fvi = 0; /* first visible item */ int lvi = 0; /* last visible item */ int si = 0; /* selected item */ - int osi = 0; /* old selected item */ int li = 0; /* last item */ int nvih = 0; /* next visible item height */ int i; - int b_need_redraw = 1; /* Do we need to redraw ? */ + bool need_redraw = true; /* Do we need to redraw ? */ + bool reset_font = false; + bool ret = false; int cp = 0; /* current position */ int sp = 0; /* selected position */ int fh, fw; /* font height, width */ + unsigned char *cache = (unsigned char *) buffer + sizeof(buffer->text); + size_t cache_size = sizeof(*buffer) - sizeof(buffer->text); + size_t cache_used = 0; + int cache_first = 0, cache_last = -1; char *a; - rb->snprintf( buffer->text.old_font, MAX_PATH, - FONT_DIR "/%s.fnt", + rb->snprintf( bbuf_s, MAX_PATH, FONT_DIR "/%s.fnt", rb->global_settings->font_file ); tree = rb->tree_get_context(); @@ -867,20 +883,30 @@ static bool browse_fonts( char *dst, int dst_size ) rb->strcpy( bbuf, FONT_DIR "/" ); rb->set_current_file( bbuf ); + if( buffer->text.initialized ) + { + cache_used = buffer->text.cache_used; + cache_first = buffer->text.cache_first; + cache_last = buffer->text.cache_last; + fvi = buffer->text.fvi; + si = buffer->text.si; + } + buffer->text.initialized = true; + while( 1 ) { - if( !b_need_redraw ) + if( !need_redraw ) { /* we don't need to redraw ... but we need to unselect * the previously selected item */ rb->lcd_set_drawmode(DRMODE_COMPLEMENT); - rb->lcd_fillrect( 10, sp, LCD_WIDTH-10, fh_buf[osi-fvi] ); + rb->lcd_fillrect( 10, sp, LCD_WIDTH-10, font_preview->height ); rb->lcd_set_drawmode(DRMODE_SOLID); } - if( b_need_redraw ) + if( need_redraw ) { - b_need_redraw = 0; + need_redraw = false; rb->lcd_set_foreground(COLOR_BLACK); rb->lcd_set_background(COLOR_LIGHTGRAY); @@ -890,69 +916,121 @@ static bool browse_fonts( char *dst, int dst_size ) rb->lcd_putsxy( 2, 2, "Fonts" ); top = fh + 4 + LINE_SPACE; - for( i = 0; fvi < lvi && nvih > 0; i++, fvi++ ) + font_preview = (struct font_preview *) cache; + /* get first font preview to be displayed. */ + for( i = cache_first; i < cache_last && i < fvi; i++ ) { - nvih -= fh_buf[i] + LINE_SPACE; + font_preview = PREVIEW_NEXT(font_preview); + } + for( ; fvi < lvi && nvih > 0; fvi++ ) + { + nvih -= font_preview->height + LINE_SPACE; + font_preview = PREVIEW_NEXT(font_preview); } nvih = 0; i = fvi; - li = -1; cp = top; - while( cp < LCD_HEIGHT && i < tree->filesindir ) + while( cp <= LCD_HEIGHT+LINE_SPACE && i < tree->filesindir ) { e = &dc[i]; - rb->snprintf( bbuf, MAX_PATH, FONT_DIR "/%s", e->name ); - rb->font_load(NULL, bbuf ); - rb->font_getstringsize( e->name, &fw, &fh, FONT_UI ); + if( i < cache_first || i > cache_last ) + { + size_t siz; + reset_font = true; + rb->snprintf( bbuf, MAX_PATH, FONT_DIR "/%s", e->name ); + rb->font_load(NULL, bbuf ); + rb->font_getstringsize( e->name, &fw, &fh, FONT_UI ); + if( fw > LCD_WIDTH ) fw = LCD_WIDTH; + siz = (sizeof(struct font_preview) + fw*fh*FB_DATA_SZ+3) & ~3; + if( i < cache_first ) + { + /* insert font preview to the top. */ + cache_used = 0; + for( ; cache_first <= cache_last; cache_first++ ) + { + font_preview = (struct font_preview *) (cache + cache_used); + size_t size = PREVIEW_SIZE(font_preview); + if( cache_used + size >= cache_size - siz ) + break; + cache_used += size; + } + cache_last = cache_first-1; + cache_first = i; + rb->memmove( cache+siz, cache, cache_used ); + font_preview = (struct font_preview *) cache; + } + else /* i > cache_last */ + { + /* add font preview to the bottom. */ + font_preview = (struct font_preview *) cache; + while( cache_used >= cache_size - siz ) + { + cache_used -= PREVIEW_SIZE(font_preview); + font_preview = PREVIEW_NEXT(font_preview); + cache_first++; + } + cache_last = i; + rb->memmove( cache, font_preview, cache_used ); + font_preview = (struct font_preview *) (cache + cache_used); + } + cache_used += siz; + /* create preview cache. */ + font_preview->width = fw; + font_preview->height = fh; + font_preview->size = siz; + /* clear with background. */ + for( siz = fw*fh; siz > 0; ) + { + font_preview->preview[--siz] = COLOR_LIGHTGRAY; + } + buffer_putsxyofs( font_preview->preview, + fw, fh, 0, 0, 0, e->name ); + } + else + { + fw = font_preview->width; + fh = font_preview->height; + } if( cp + fh >= LCD_HEIGHT ) { nvih = fh; break; } - rb->lcd_putsxy( 10, cp, e->name ); - fh_buf[i-fvi] = fh; - fw_buf[i-fvi] = fw; + rb->lcd_bitmap( font_preview->preview, 10, cp, fw, fh ); cp += fh + LINE_SPACE; i++; + font_preview = PREVIEW_NEXT(font_preview); } lvi = i-1; - if( i >= tree->filesindir ) - { - li = i-1; - } - if( li == -1 ) + li = tree->filesindir-1; + if( reset_font ) { - if( !nvih ) - { - e = &dc[i]; - rb->snprintf( bbuf, MAX_PATH, FONT_DIR "/%s", e->name ); - rb->font_load(NULL, bbuf ); - rb->font_getstringsize( e->name, NULL, &fh, FONT_UI ); - nvih = fh; - } + rb->font_load(NULL, bbuf_s ); + reset_font = false; } - rb->font_load(NULL, buffer->text.old_font ); - if( lvi-fvi < tree->filesindir-1 ) + if( lvi-fvi+1 < tree->filesindir ) { rb->gui_scrollbar_draw( rb->screens[SCREEN_MAIN], 0, top, - 9, cp-LINE_SPACE-top, - tree->filesindir-1, fvi, lvi, VERTICAL); + 9, LCD_HEIGHT-top, + tree->filesindir, fvi, lvi+1, VERTICAL ); } } rb->lcd_set_drawmode(DRMODE_COMPLEMENT); sp = top; - for( i = 0; i+fvi < si; i++ ) + font_preview = (struct font_preview *) cache; + for( i = cache_first; i < si; i++ ) { - sp += fh_buf[i] + LINE_SPACE; + if( i >= fvi ) + sp += font_preview->height + LINE_SPACE; + font_preview = PREVIEW_NEXT(font_preview); } - rb->lcd_fillrect( 10, sp, LCD_WIDTH-10, fh_buf[si-fvi] ); + rb->lcd_fillrect( 10, sp, LCD_WIDTH-10, font_preview->height ); rb->lcd_set_drawmode(DRMODE_SOLID); rb->lcd_update(); - osi = si; switch( rb->button_get(true) ) { case ROCKPAINT_UP: @@ -964,42 +1042,43 @@ static bool browse_fonts( char *dst, int dst_size ) { fvi = si; nvih = 0; - b_need_redraw = 1; + need_redraw = true; } } break; case ROCKPAINT_DOWN: case ROCKPAINT_DOWN|BUTTON_REPEAT: - if( li == -1 || si < li ) + if( si < li ) { si++; if( si > lvi ) { - b_need_redraw = 1; + need_redraw = true; } } break; - case ROCKPAINT_LEFT: - case ROCKPAINT_QUIT: - *tree = backup; - rb->set_current_file( backup.currdir ); - return false; - case ROCKPAINT_RIGHT: case ROCKPAINT_DRAW: + ret = true; rb->snprintf( dst, dst_size, FONT_DIR "/%s", dc[si].name ); + /* fall through */ + case ROCKPAINT_LEFT: + case ROCKPAINT_QUIT: + buffer->text.cache_used = cache_used; + buffer->text.cache_first = cache_first; + buffer->text.cache_last = cache_last; + buffer->text.fvi = fvi; + buffer->text.si = si; *tree = backup; rb->set_current_file( backup.currdir ); - return true; + return ret; } } -#undef fh_buf -#undef fw_buf -#undef WIDTH -#undef HEIGHT #undef LINE_SPACE +#undef PREVIEW_SIZE +#undef PREVIEW_NEXT } /*********************************************************************** @@ -1481,9 +1560,7 @@ static void draw_text( int x, int y ) { int selected = 0; buffer->text.text[0] = '\0'; - rb->snprintf( buffer->text.old_font, MAX_PATH, - FONT_DIR "/%s.fnt", - rb->global_settings->font_file ); + buffer->text.font[0] = '\0'; while( 1 ) { switch( rb->do_menu( &text_menu, &selected, NULL, NULL ) ) @@ -1545,7 +1622,13 @@ static void draw_text( int x, int y ) case TEXT_MENU_CANCEL: default: restore_screen(); - rb->font_load(NULL, buffer->text.old_font ); + if( buffer->text.font[0] ) + { + rb->snprintf( buffer->text.font, MAX_PATH, + FONT_DIR "/%s.fnt", + rb->global_settings->font_file ); + rb->font_load(NULL, buffer->text.font ); + } return; } } @@ -2357,6 +2440,10 @@ static void toolbar( void ) j = ( y - (TOP+TB_TL_TOP) )/(TB_TL_SIZE+TB_TL_SPACING); tool = i*2+j; reset_tool(); + if( tool == Text ) + { + buffer->text.initialized = false; + } } else if( x >= TB_MENU_LEFT && y >= TOP+TB_MENU_TOP-2) { |