Index: apps/plugins/rockpaint.c =================================================================== --- apps/plugins/rockpaint.c (revision 22462) +++ apps/plugins/rockpaint.c (working copy) @@ -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" @@ -402,20 +401,17 @@ char text[MAX_TEXT]; char font[MAX_PATH]; char old_font[MAX_PATH]; - int fh_buf[30]; - int fw_buf[30]; - char fontname_buf[30][MAX_PATH]; + bool initialized; + int font_count; + int selected; + int preview[0]; } text; } buffer; +#define FONT_PREVIEW_SIZE (sizeof(buffer)-sizeof(buffer.text)) /* Current filename */ static char filename[MAX_PATH]; -/* 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 * @@ -747,159 +743,221 @@ ***********************************************************************/ static bool browse_fonts( char *dst, int dst_size ) { -#define WIDTH ( LCD_WIDTH - 20 ) -#define HEIGHT ( LCD_HEIGHT - 20 ) #define LINE_SPACE 2 - int top, top_inside = 0, left; +#define X_OFFSET 8 +#define PREVIEW_SIZE(x) ((sizeof(struct font_preview)+(x)->name_len \ + +(x)->width*(x)->height*sizeof(fb_data)+3) & ~3) +#define PREVIEW_NEXT(x) (struct font_preview *)((char*)(x) + PREVIEW_SIZE(x)) +#define PREVIEW_IMGDATA(x) (fb_data *)((x)->data+(x)->name_len) - DIR *d; - struct dirent *de; - 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 ? */ + struct font_preview { + unsigned short width, height; + unsigned char name_len; + char data[0]; + } *font_preview, *temp_preview; + char selected_file[MAX_PATH] = ""; + int total_height, i; + int first=0, last; + bool need_redraw = true; - int cp = 0; /* current position */ - int fh; /* font height */ + if(!buffer.text.initialized) + { + /* create preview */ + struct tree_context backup; + struct entry *dc; + int dirfilter = SHOW_FONT; + char *a; + unsigned long preview_used; - #define fh_buf buffer.text.fh_buf /* 30 might not be enough ... */ - #define fw_buf buffer.text.fw_buf - int fw; - #define fontname_buf buffer.text.fontname_buf + rb->splash(0, "Creating Preview..."); + rb->snprintf( buffer.text.old_font, MAX_PATH, + FONT_DIR "/%s.fnt", rb->global_settings->font_file ); - rb->snprintf( buffer.text.old_font, MAX_PATH, - FONT_DIR "/%s.fnt", - rb->global_settings->font_file ); + tree = rb->tree_get_context(); + backup = *tree; + dc = tree->dircache; + a = backup.currdir+rb->strlen(backup.currdir)-1; + if( *a != '/' ) + { + *++a = '/'; + *++a = '\0'; + } + rb->strcpy( a, dc[tree->selected_item].name ); + tree->dirfilter = &dirfilter; + rb->strcpy( bbuf, FONT_DIR "/" ); + rb->set_current_file( bbuf ); - while( 1 ) - { - if( !b_need_redraw ) + buffer.text.selected = 0; + buffer.text.font_count = 0; + preview_used = 0; + + font_preview = (struct font_preview *) buffer.text.preview; + for( i = 0; i < tree->filesindir ; i++) { - /* we don't need to redraw ... but we need to unselect - * the previously selected item */ - cp = top_inside + LINE_SPACE; - for( i = 0; i+fvi < osi; i++ ) + int w, h, siz; + char *name = dc[i].name; + /* only display font files */ + if( !check_extention( name, ".fnt" ) ) + continue; + + rb->snprintf( bbuf, MAX_PATH, FONT_DIR "/%s", name ); + if( !rb->font_load( bbuf ) ) + continue; + + /* check size of preview and store */ + siz = rb->strlen(name) - 4 + 1; /* file name without extension */ + rb->strlcpy( bbuf, name, siz ); + rb->font_getstringsize( bbuf, &w, &h, FONT_UI ); + if( w > LCD_WIDTH-X_OFFSET ) + w = LCD_WIDTH-X_OFFSET; + siz = ((((long) font_preview->data) + siz + 3) & ~3) - + ((long) font_preview->data); + font_preview->name_len = siz; + font_preview->width = w; + font_preview->height = h; + preview_used += PREVIEW_SIZE(font_preview); + if( preview_used > FONT_PREVIEW_SIZE ) + break; + rb->strcpy( font_preview->data, bbuf ); + fb_data *img_data = PREVIEW_IMGDATA(font_preview); + for( siz=0; sizlcd_set_drawmode(DRMODE_COMPLEMENT); - rb->lcd_fillrect( left+10, cp, fw_buf[i], fh_buf[i] ); - rb->lcd_set_drawmode(DRMODE_SOLID); + font_preview = PREVIEW_NEXT(font_preview); + buffer_putsxyofs( img_data, w, h, 0, 0, 0, bbuf ); + buffer.text.font_count++; } + buffer.text.initialized = true; + rb->font_load( buffer.text.old_font ); + *tree = backup; + rb->set_current_file( backup.currdir ); - if( b_need_redraw ) +#ifdef SIMULATOR /* just to test. should be removed. */ + DEBUGF("buffer usage: %d/%d\n", + (int)preview_used, (int)FONT_PREVIEW_SIZE); +#else + rb->splashf(HZ*2, "buffer usage: %d/%d", + (int)preview_used, (int)FONT_PREVIEW_SIZE); +#endif + if( preview_used > FONT_PREVIEW_SIZE ) + rb->splash(HZ, "Font buffer is full!"); + } + + total_height = 0; + font_preview = (struct font_preview *) buffer.text.preview; + for( i=0; iheight+LINE_SPACE; + font_preview = PREVIEW_NEXT(font_preview); + } + + rb->lcd_set_foreground(COLOR_BLACK); + rb->lcd_set_background(COLOR_LIGHTGRAY); + + int y0 = 0, y = 0, h0 = 0, h1 = 0; + while( 1 ) + { + if( need_redraw ) { - b_need_redraw = 0; - - d = rb->opendir( FONT_DIR "/" ); - if( !d ) + h0 = h1 = 0; + rb->lcd_getstringsize("Fonts", NULL, &y0); + y0 += LINE_SPACE; + last = 0; + /* increase index so that selected item is displayed */ + font_preview = (struct font_preview *) buffer.text.preview; + for( i=0; iheight+LINE_SPACE; + font_preview = PREVIEW_NEXT(font_preview); } - top_inside = draw_window( HEIGHT, WIDTH, &top, &left, "Fonts" ); - i = 0; - li = -1; - while( i < fvi ) + /* find index of last item */ + temp_preview = font_preview; + for( y=y0; ireaddir( d ); - i++; - } - cp = top_inside+LINE_SPACE; - - rb->lcd_set_foreground(COLOR_BLACK); - rb->lcd_set_background(COLOR_LIGHTGRAY); - - while( cp < top+HEIGHT ) - { - de = rb->readdir( d ); - if( !de ) - { - li = i-1; + if( y+temp_preview->height > LCD_HEIGHT ) break; - } - if( !check_extention( de->d_name, ".fnt" ) ) - continue; - rb->snprintf( bbuf, MAX_PATH, FONT_DIR "/%s", - de->d_name ); - rb->font_load( bbuf ); - rb->font_getstringsize( de->d_name, &fw, &fh, FONT_UI ); - if( nvih > 0 ) - { - nvih -= fh; - fvi++; - if( nvih < 0 ) nvih = 0; - i++; - continue; - } - if( cp + fh >= top+HEIGHT ) - { - nvih = fh; - break; - } - rb->lcd_putsxy( left+10, cp, de->d_name ); - fh_buf[i-fvi] = fh; - fw_buf[i-fvi] = fw; - cp += fh + LINE_SPACE; - rb->strcpy( fontname_buf[i-fvi], bbuf ); - i++; + y += temp_preview->height+LINE_SPACE; + temp_preview = PREVIEW_NEXT(temp_preview); + last = i; } - lvi = i-1; - if( li == -1 ) + /* increase index so that selected item is displayed */ + while( last < buffer.text.selected ) { - if( !(de = rb->readdir( d ) ) ) + first++; + h0 += font_preview->height+LINE_SPACE; + y -= font_preview->height+LINE_SPACE; + font_preview = PREVIEW_NEXT(font_preview); + + /* increse index for last item */ + while( last < buffer.text.font_count-1 ) { - li = lvi; + if( y+temp_preview->height > LCD_HEIGHT ) + break; + y += temp_preview->height+LINE_SPACE; + temp_preview = PREVIEW_NEXT(temp_preview); + last++; } - else if( !nvih && check_extention( de->d_name, ".fnt" ) ) - { - rb->snprintf( bbuf, MAX_PATH, FONT_DIR "/%s", - de->d_name ); - rb->font_load( bbuf ); - rb->font_getstringsize( de->d_name, NULL, &fh, FONT_UI ); - nvih = fh; - } } - rb->font_load( buffer.text.old_font ); - rb->closedir( d ); + //need_redraw = false; } - - rb->lcd_set_drawmode(DRMODE_COMPLEMENT); - cp = top_inside + LINE_SPACE; - for( i = 0; i+fvi < si; i++ ) + /* display */ + rb->lcd_clear_display(); + rb->lcd_putsxy(0, 0, "Fonts"); + temp_preview = font_preview; + for( y=y0, i=first; i<=last; i++ ) { - cp += fh_buf[i] + LINE_SPACE; + rb->lcd_bitmap( PREVIEW_IMGDATA(temp_preview), X_OFFSET, y, + (int)temp_preview->width, + (int)temp_preview->height ); + if( i==buffer.text.selected ) + { + rb->lcd_set_drawmode( DRMODE_COMPLEMENT ); + rb->lcd_fillrect( X_OFFSET, y, LCD_WIDTH, + (int)temp_preview->height ); + rb->lcd_set_drawmode( DRMODE_SOLID ); + rb->strlcpy( selected_file, temp_preview->data, MAX_PATH ); + } + y += temp_preview->height+LINE_SPACE; + temp_preview = PREVIEW_NEXT(temp_preview); } - rb->lcd_fillrect( left+10, cp, fw_buf[i], fh_buf[i] ); - rb->lcd_set_drawmode(DRMODE_SOLID); - - rb->lcd_update_rect( left, top, WIDTH, HEIGHT ); - - osi = si; - i = fvi; + y -= y0; + h1 = h0+y; + rb->gui_scrollbar_draw( rb->screens[SCREEN_MAIN], 0, y0, X_OFFSET-2, + y-LINE_SPACE, total_height, h0, h1, VERTICAL ); + rb->lcd_update(); + i = first; switch( rb->button_get(true) ) { case ROCKPAINT_UP: case ROCKPAINT_UP|BUTTON_REPEAT: - if( si > 0 ) + if( buffer.text.selected > 0 ) { - si--; - if( si last ) + first++; } + else + { + buffer.text.selected = 0; + first = 0; + } break; case ROCKPAINT_LEFT: @@ -907,25 +965,16 @@ case ROCKPAINT_RIGHT: case ROCKPAINT_DRAW: - rb->snprintf( dst, dst_size, "%s", fontname_buf[si-fvi] ); + rb->snprintf( dst, dst_size, FONT_DIR "/%s.fnt", selected_file ); return true; } - - if( i != fvi || si > lvi ) - { - b_need_redraw = 1; - } - - if( si<=lvi ) - { - nvih = 0; - } + if( i != first ) + need_redraw = true; } -#undef fh_buf -#undef fw_buf -#undef fontname_buf -#undef WIDTH -#undef HEIGHT +#undef PREVIEW_IMGDATA +#undef PREVIEW_NEXT +#undef PREVIEW_SIZE +#undef X_OFFSET #undef LINE_SPACE } @@ -2315,6 +2364,8 @@ static void toolbar( void ) { int button, i, j; + bool exit = false; + enum Tools old_tool = tool; restore_screen(); draw_toolbars( false ); y = LCD_HEIGHT-TB_HEIGHT/2; @@ -2410,7 +2461,8 @@ y-=bspeed * ( button & BUTTON_REPEAT ? 4 : 1 ); if (y=LCD_HEIGHT) { y = 0; - return; + exit = true; + break; } inv_cursor(true); break; case ROCKPAINT_TOOLBAR: case ROCKPAINT_TOOLBAR2: - return; + exit = true; + break; } if( quit ) return; + if( exit ) { + if( tool == Text && old_tool != Text) + { + buffer.text.initialized = false; + } + return; + } } }