diff -u -r rockbox_svn.orig/apps/gui/gwps-common.c rockbox_svn/apps/gui/gwps-common.c --- rockbox_svn.orig/apps/gui/gwps-common.c 2007-11-12 23:57:33.310500000 -0600 +++ rockbox_svn/apps/gui/gwps-common.c 2007-11-12 23:56:31.310500000 -0600 @@ -1354,13 +1354,64 @@ #endif case WPS_TOKEN_ALIGN_SCROLLMARGIN_LEFT: - gwps->display->setmargins( token->value.i, gwps->display->getrightmargin(), gwps->display->getymargin() ); + if(!gwps->data->customline) + gwps->display->setmargins( token->value.i, gwps->display->getrightmargin(), gwps->display->getymargin() ); return NULL; case WPS_TOKEN_ALIGN_SCROLLMARGIN_RIGHT: - gwps->display->setmargins( gwps->display->getleftmargin(), token->value.i, gwps->display->getymargin() ); + if(!gwps->data->customline) + gwps->display->setmargins( gwps->display->getleftmargin(), token->value.i, gwps->display->getymargin() ); return NULL; - + + case WPS_TOKEN_CUSTOMLINE_XPOS: + gwps->data->line_xpos=token->value.i; + return NULL; + case WPS_TOKEN_CUSTOMLINE_YPOS: + gwps->data->line_ypos=token->value.i; + return NULL; + case WPS_TOKEN_CUSTOMLINE_WIDTH: + gwps->data->line_width=token->value.i; + return NULL; + case WPS_TOKEN_CUSTOMLINE_FONT: + gwps->data->line_font=token->value.i; + return NULL; + case WPS_TOKEN_CUSTOMLINE_COLOR: + gwps->data->line_fgcolor=token->value.i; + gwps->data->customline = true; +#ifdef HAVE_LCD_COLOR + if(gwps->display->depth>2){ + gwps->display->set_foreground(gwps->data->line_fgcolor); + } +#endif + + gwps->display->setmargins( gwps->data->line_xpos, gwps->data->line_xpos+gwps->data->line_width, gwps->data->line_ypos ); + + switch (gwps->data->line_font) { + case 1: + gwps->display->setfont(FONT_USER1); + break; + case 2: + gwps->display->setfont(FONT_USER2); + break; + case 3: + gwps->display->setfont(FONT_USER3); + break; + case 4: + gwps->display->setfont(FONT_USER4); + break; + case 5: + gwps->display->setfont(FONT_USER5); + break; + case 6: + gwps->display->setfont(FONT_USER6); + break; + case 7: + gwps->display->setfont(FONT_USER7); + break; + } + + return NULL; + default: return NULL; } @@ -1681,7 +1732,8 @@ line is the index of the line on the screen. scroll indicates whether the line is a scrolling one or not. */ -static void write_line(struct screen *display, +static void write_line(struct wps_data *data, + struct screen *display, struct align_pos *format_align, int line, bool scroll) @@ -1694,26 +1746,42 @@ int space_width; int string_height; const int scroll_width = display->getrightmargin()-display->getleftmargin(); - + bool customline=data->customline; + /* calculate different string sizes and positions */ display->getstringsize((unsigned char *)" ", &space_width, &string_height); if (format_align->left != 0) { display->getstringsize((unsigned char *)format_align->left, &left_width, &string_height); } - left_xpos = display->getleftmargin(); + if(customline){ + left_xpos = data->line_xpos; + } + else { + left_xpos = display->getleftmargin(); + } if (format_align->center != 0) { display->getstringsize((unsigned char *)format_align->center, ¢er_width, &string_height); } - center_xpos=(display->getrightmargin() + display->getleftmargin() - center_width)/2; - + if(customline){ + center_xpos=(data->line_width - center_width) / 2 + data->line_xpos; + } + else { + center_xpos=(display->getrightmargin() + display->getleftmargin() - center_width)/2; + } + if (format_align->right != 0) { display->getstringsize((unsigned char *)format_align->right, &right_width, &string_height); } - right_xpos = (display->getrightmargin() - right_width); + if(customline){ + right_xpos = (data->line_xpos+data->line_width - right_width); + } + else { + right_xpos = (display->getrightmargin() - right_width); + } /* Checks for overlapping strings. If needed the overlapping strings will be merged, separated by a @@ -1795,14 +1863,79 @@ } ypos = (line * string_height) + display->getymargin(); - - if (scroll && ( left_width > scroll_width || center_width > scroll_width || right_width > scroll_width ) ) - { - display->puts_scroll(0, line, - (unsigned char *)format_align->left); - } - else - { + + if(customline){ +#if (!defined(IRIVER_H100)) && (!defined(IRIVER_H120)) && (!defined(IRIVER_H300)) && (!defined(IAUDIO_X5)) && (!defined(IAUDIO_M5)) + switch (data->line_font) { + case 1: + display->setfont(FONT_USER1); + break; + case 2: + display->setfont(FONT_USER2); + break; + case 3: + display->setfont(FONT_USER3); + break; + case 4: + display->setfont(FONT_USER4); + break; + case 5: + display->setfont(FONT_USER5); + break; + case 6: + display->setfont(FONT_USER6); + break; + case 7: + display->setfont(FONT_USER7); + break; + } + if(display->depth > 2) + lcd_set_foreground(data->line_fgcolor); +#endif + if (scroll && ( left_width > scroll_width || center_width > scroll_width || right_width > scroll_width ) ) + { + display->puts_customline_scroll(line, + (unsigned char *)format_align->left); + } + else + { +#ifdef HAVE_LCD_BITMAP + /* Clear the area first if there is something to display */ + if (left_width || center_width || right_width) { + display->set_drawmode(DRMODE_SOLID|DRMODE_INVERSEVID); + display->fillrect(data->line_xpos, data->line_ypos, data->line_width, string_height); + display->set_drawmode(DRMODE_SOLID); + } +#endif + /* Nasty hack: we output an empty scrolling string, + which will reset the scroller for that line */ + display->puts_customline_scroll(line, (unsigned char *)""); + + /* print aligned strings */ + if (left_width != 0) + { + display->putsxy(left_xpos, data->line_ypos, + (unsigned char *)format_align->left); + } + if (center_width != 0) + { + display->putsxy(center_xpos, data->line_ypos, + (unsigned char *)format_align->center); + } + if (right_width != 0) + { + display->putsxy(right_xpos, data->line_ypos, + (unsigned char *)format_align->right); + } + } + } else { + if (scroll && ( left_width > scroll_width || center_width > scroll_width || right_width > scroll_width ) ) + { + display->puts_scroll(0, line, + (unsigned char *)format_align->left); + } + else + { #ifdef HAVE_LCD_BITMAP /* clear the line first */ display->set_drawmode(DRMODE_SOLID|DRMODE_INVERSEVID); @@ -1810,25 +1943,26 @@ display->set_drawmode(DRMODE_SOLID); #endif - /* Nasty hack: we output an empty scrolling string, - which will reset the scroller for that line */ - display->puts_scroll(0, line, (unsigned char *)""); - - /* print aligned strings */ - if (left_width != 0) - { - display->putsxy(left_xpos, ypos, - (unsigned char *)format_align->left); - } - if (center_width != 0) - { - display->putsxy(center_xpos, ypos, - (unsigned char *)format_align->center); - } - if (right_width != 0) - { - display->putsxy(right_xpos, ypos, - (unsigned char *)format_align->right); + /* Nasty hack: we output an empty scrolling string, + which will reset the scroller for that line */ + display->puts_scroll(0, line, (unsigned char *)""); + + /* print aligned strings */ + if (left_width != 0) + { + display->putsxy(left_xpos, ypos, + (unsigned char *)format_align->left); + } + if (center_width != 0) + { + display->putsxy(center_xpos, ypos, + (unsigned char *)format_align->center); + } + if (right_width != 0) + { + display->putsxy(right_xpos, ypos, + (unsigned char *)format_align->right); + } } } } @@ -1856,6 +1990,16 @@ bool update_line, new_subline_refresh; +#ifdef HAVE_LCD_COLOR + int fgcolor_save; + if(display->depth>2){ + fgcolor_save=display->get_foreground(); + } +#endif + int leftmargin_save=display->getleftmargin(); + int rightmargin_save=display->getrightmargin(); + int ymargin_save=display->getymargin(); + #ifdef HAVE_LCD_BITMAP display->setfont(FONT_WPS); gui_wps_statusbar_draw(gwps, true); @@ -1963,7 +2107,6 @@ draw_player_progress(gwps); } #endif - if (update_line) { if (flags & WPS_REFRESH_SCROLL) @@ -1971,10 +2114,10 @@ /* if the line is a scrolling one we don't want to update too often, so that it has the time to scroll */ if ((refresh_mode & WPS_REFRESH_SCROLL) || new_subline_refresh) - write_line(display, &align, line, true); + write_line(data, display, &align, line, true); } else - write_line(display, &align, line, false); + write_line(data, display, &align, line, false); } } @@ -2021,6 +2164,12 @@ } #endif +#ifdef HAVE_LCD_COLOR + if(display->depth>2){ + display->set_foreground(fgcolor_save); + } +#endif + display->setmargins( leftmargin_save, rightmargin_save, ymargin_save ); return true; } diff -u -r rockbox_svn.orig/apps/gui/gwps.h rockbox_svn/apps/gui/gwps.h --- rockbox_svn.orig/apps/gui/gwps.h 2007-11-12 23:57:24.623000000 -0600 +++ rockbox_svn/apps/gui/gwps.h 2007-11-12 23:55:25.154250000 -0600 @@ -210,6 +210,13 @@ /* Albumart */ WPS_TOKEN_ALBUMART_DISPLAY, WPS_TOKEN_ALBUMART_FOUND, + + /* customline */ + WPS_TOKEN_CUSTOMLINE_XPOS, + WPS_TOKEN_CUSTOMLINE_YPOS, + WPS_TOKEN_CUSTOMLINE_WIDTH, + WPS_TOKEN_CUSTOMLINE_FONT, + WPS_TOKEN_CUSTOMLINE_COLOR, #endif /* Metadata */ @@ -379,6 +386,12 @@ int num_strings; bool wps_loaded; + + /* customline */ + int line_xpos, line_ypos, line_width; + int line_font; + int line_fgcolor; + bool customline; }; /* initial setup of wps_data */ diff -u -r rockbox_svn.orig/apps/gui/wps_parser.c rockbox_svn/apps/gui/wps_parser.c --- rockbox_svn.orig/apps/gui/wps_parser.c 2007-11-12 23:59:56.013625000 -0600 +++ rockbox_svn/apps/gui/wps_parser.c 2007-11-12 23:55:25.169875000 -0600 @@ -129,6 +129,8 @@ struct wps_token *token, struct wps_data *wps_data); static int parse_image_load(const char *wps_bufptr, struct wps_token *token, struct wps_data *wps_data); +static int parse_customline(const char *wps_bufptr, + struct wps_token *token, struct wps_data *wps_data); #endif /*HAVE_LCD_BITMAP */ #ifdef HAVE_ALBUMART @@ -301,6 +303,7 @@ { WPS_TOKEN_ALBUMART_DISPLAY, "C", WPS_REFRESH_STATIC, parse_albumart_conditional }, #endif + { WPS_NO_TOKEN, "e", 0, parse_customline }, #if (LCD_DEPTH > 1) || (defined(HAVE_LCD_REMOTE) && (LCD_REMOTE_DEPTH > 1)) { WPS_TOKEN_IMAGE_BACKDROP, "X", 0, parse_image_special }, #endif @@ -894,6 +897,68 @@ } #endif +static int parse_customline(const char *wps_bufptr, + struct wps_token *token, + struct wps_data *wps_data) +{ + /* format: %e|x|y|w|font|color */ + const char* _pos; + + if(*wps_bufptr!='|') + return(0); /* malformed token: */ + + _pos=wps_bufptr+1; + if(!isdigit(*_pos)) + return(0); /* malformed token: */ + + wps_data->num_tokens +=5; + token->type = WPS_TOKEN_CUSTOMLINE_XPOS; + token->value.i = atoi(_pos); + token++; + + _pos=strchr(_pos,'|'); + if(!_pos || !isdigit(*(++_pos))) + return(0); /* malformed token: */ + + token->type = WPS_TOKEN_CUSTOMLINE_YPOS; + token->value.i = atoi(_pos); + token++; + + _pos=strchr(_pos,'|'); + if(!_pos || !isdigit(*(++_pos))) + return(0); /* malformed token: */ + + token->type = WPS_TOKEN_CUSTOMLINE_WIDTH; + token->value.i = atoi(_pos); + token++; + + _pos=strchr(_pos,'|'); + if(!_pos || !isdigit(*(++_pos))) + return(0); /* malformed token: */ + + token->type = WPS_TOKEN_CUSTOMLINE_FONT; + token->value.i = atoi(_pos); + token++; + + _pos=strchr(_pos,'|'); + if(!_pos) + return(0); /* malformed token: */ + + ++_pos; + char fg_color[7]; + snprintf(fg_color, 7, "%s", _pos); + + token->type = WPS_TOKEN_CUSTOMLINE_COLOR; +#ifdef HAVE_LCD_COLOR + token->value.i = hex_to_rgb(fg_color); +#else + token->value.i=0; +#endif + + _pos+=6; + return( _pos - wps_bufptr + 1 ); +} + /* Parse a generic token from the given string. Return the length read */ static int parse_token(const char *wps_bufptr, struct wps_data *wps_data) { @@ -1205,6 +1270,13 @@ wps_data->full_line_progressbar = false; #endif wps_data->wps_loaded = false; + + wps_data->customline = false; + wps_data->line_xpos = -1; + wps_data->line_ypos = 1; + wps_data->line_width = -1; + wps_data->line_fgcolor = -1; + wps_data->line_font = -1; } static void wps_reset(struct wps_data *data) diff -u -r rockbox_svn.orig/apps/screen_access.c rockbox_svn/apps/screen_access.c --- rockbox_svn.orig/apps/screen_access.c 2007-11-12 23:57:33.888625000 -0600 +++ rockbox_svn/apps/screen_access.c 2007-11-12 23:55:25.201125000 -0600 @@ -54,6 +54,7 @@ .getymargin=&lcd_getymargin, .getleftmargin=&lcd_getleftmargin, .getrightmargin=&lcd_getrightmargin, + .getmarginwidth=&lcd_getmarginwidth, .getstringsize=&lcd_getstringsize, #ifdef HAVE_LCD_BITMAP .setfont=&lcd_setfont, @@ -111,7 +112,9 @@ .puts=&lcd_puts, .puts_offset=&lcd_puts_offset, .puts_scroll=&lcd_puts_scroll, + .puts_customline_scroll=&lcd_puts_customline_scroll, .puts_scroll_offset=&lcd_puts_scroll_offset, + .puts_customline_scroll_offset=&lcd_puts_customline_scroll_offset, .scroll_speed=&lcd_scroll_speed, .scroll_delay=&lcd_scroll_delay, .stop_scroll=&lcd_stop_scroll, @@ -138,6 +141,7 @@ .getymargin=&lcd_remote_getymargin, .getleftmargin=&lcd_remote_getleftmargin, .getrightmargin=&lcd_remote_getrightmargin, + .getmarginwidth=&lcd_remote_getmarginwidth, .getstringsize=&lcd_remote_getstringsize, #if 1 /* all remote LCDs are bitmapped so far */ .setfont=&lcd_remote_setfont, @@ -186,7 +190,9 @@ .puts=&lcd_remote_puts, .puts_offset=&lcd_remote_puts_offset, .puts_scroll=&lcd_remote_puts_scroll, + .puts_customline_scroll=&lcd_remote_puts_customline_scroll, .puts_scroll_offset=&lcd_remote_puts_scroll_offset, + .puts_customline_scroll_offset=&lcd_remote_puts_customline_scroll_offset, .scroll_speed=&lcd_remote_scroll_speed, .scroll_delay=&lcd_remote_scroll_delay, .stop_scroll=&lcd_remote_stop_scroll, diff -u -r rockbox_svn.orig/apps/screen_access.h rockbox_svn/apps/screen_access.h --- rockbox_svn.orig/apps/screen_access.h 2007-11-12 23:57:33.904250000 -0600 +++ rockbox_svn/apps/screen_access.h 2007-11-12 23:55:25.216750000 -0600 @@ -75,6 +75,7 @@ int (*getleftmargin)(void); int (*getrightmargin)(void); int (*getymargin)(void); + int (*getmarginwidth)(void); int (*getstringsize)(const unsigned char *str, int *w, int *h); #if defined(HAVE_LCD_BITMAP) || defined(HAVE_REMOTE_LCD) /* always bitmap */ void (*setfont)(int newfont); @@ -137,6 +138,10 @@ void (*puts_scroll)(int x, int y, const unsigned char *string); void (*puts_scroll_offset)(int x, int y, const unsigned char *string, int offset); + void (*puts_customline_scroll)(int i, const unsigned char *string); + void (*puts_customline_scroll_offset)(int i, const unsigned char *string, + int offset); + void (*scroll_speed)(int speed); void (*scroll_delay)(int ms); void (*stop_scroll)(void); diff -u -r rockbox_svn.orig/firmware/drivers/lcd-16bit.c rockbox_svn/firmware/drivers/lcd-16bit.c --- rockbox_svn.orig/firmware/drivers/lcd-16bit.c 2007-11-12 23:57:34.029250000 -0600 +++ rockbox_svn/firmware/drivers/lcd-16bit.c 2007-11-12 23:55:25.232375000 -0600 @@ -155,6 +155,11 @@ return ymargin; } +int lcd_getmarginwidth(void) +{ + return lcd_getrightmargin()-lcd_getleftmargin(); +} + void lcd_setfont(int newfont) { curfont = newfont; @@ -899,7 +904,148 @@ bg_pattern = oldbgcolor; } +/* put a string at a given pixel position, skipping first ofs pixel columns + if rmargin==0 the global rightmargin is used */ +static void lcd_putsxyofs_custom(int x, int y, int ofs, const unsigned char *str, int rmargin) +{ + unsigned short ch; + unsigned short *ucs; + struct font* pf = font_get(curfont); + int used_rightmargin=rmargin?rmargin:rightmargin; + + ucs = bidi_l2v(str, 1); + + while ((ch = *ucs++) != 0 && x < used_rightmargin) + { + int width; + const unsigned char *bits; + + /* get proportional width and glyph bits */ + width = font_get_width(pf,ch,curfont); + + if (ofs > width) + { + ofs -= width; + continue; + } + + bits = font_get_bits(pf, ch, curfont); + + lcd_mono_bitmap_part(bits, ofs, 0, width, x, y, (x+width > used_rightmargin?used_rightmargin-x:width) - ofs, pf->height); + + x += width - ofs; + ofs = 0; + } +} + +void lcd_puts_customline_style_offset(int i, const unsigned char *str, int style, + int offset) +{ + int xpos,ypos,w,h,xrect; + int lastmode = drawmode; + + /* make sure scrolling is turned off on the line we are updating */ + lcd_scroll_info.lines &= ~(1 << i); + + if(!str || !str[0]) + return; + + lcd_getstringsize(str, &w, &h); + xpos = leftmargin; + ypos = ymargin; + drawmode = (style & STYLE_INVERT) ? + (DRMODE_SOLID|DRMODE_INVERSEVID) : DRMODE_SOLID; + lcd_putsxyofs_custom(xpos, ypos, offset, str, 0); + drawmode ^= DRMODE_INVERSEVID; + xrect = xpos + MAX(w - offset, 0); + lcd_fillrect(xpos + w, ypos, rightmargin - (xpos + w), h); + drawmode = lastmode; +} + +void lcd_puts_customline_offset(int i, const unsigned char *str, int offset) +{ + lcd_puts_customline_style_offset(i, str, STYLE_DEFAULT, offset); +} + /*** scrolling ***/ +void lcd_puts_customline_scroll_style(int i, const unsigned char *string, int style) +{ + lcd_puts_customline_scroll_style_offset(i, string, style, 0); +} + +void lcd_puts_customline_scroll_offset(int i, const unsigned char *string, int offset) +{ + lcd_puts_customline_scroll_style_offset(i, string, STYLE_DEFAULT, offset); +} + +void lcd_puts_customline_scroll(int i, const unsigned char *string) +{ + lcd_puts_customline_scroll_style_offset(i, string, + STYLE_DEFAULT, 0); +} + +void lcd_puts_customline_scroll_style_offset(int i, + const unsigned char *string, int style, int offset) +{ + struct scrollinfo* s; + int w, h; + + s = &lcd_scroll_info.scroll[i]; + + s->customline = true; + s->line_font = curfont; + s->line_xpos = lcd_getleftmargin(); + s->line_ypos = lcd_getymargin(); + s->fgcolor = lcd_get_foreground(); + s->line_width = lcd_getrightmargin()-lcd_getleftmargin(); + + s->start_tick = current_tick + lcd_scroll_info.delay; + s->style = style; + lcd_puts_customline_style_offset(i,string,style,offset); + lcd_getstringsize(string, &w, &h); + + if (s->line_width < w) { + /* prepare scroll line */ + char *end; + + memset(s->line, 0, sizeof s->line); + strcpy(s->line, string); + + /* get width */ + s->width = lcd_getstringsize(s->line, &w, &h); + + /* scroll bidirectional or forward only depending on the string + width */ + if ( lcd_scroll_info.bidir_limit ) { + s->bidir = s->width < (s->line_width) * + (100 + lcd_scroll_info.bidir_limit) / 100; + } + else + s->bidir = false; + + if (!s->bidir) { /* add spaces if scrolling in the round */ + strcat(s->line, " "); + /* get new width incl. spaces */ + s->width = lcd_getstringsize(s->line, &w, &h); + } + + end = strchr(s->line, '\0'); + strncpy(end, string, s->line_width/2); + + s->len = utf8length(string); + s->offset = offset; + s->startx = leftmargin + leftmargin * s->width / s->len; + s->backward = false; + s->left_margin=s->line_xpos; + s->right_margin=s->line_xpos+s->line_width; + s->y_margin=ymargin; + lcd_scroll_info.lines |= (1<customline = false; + s->line_font = curfont; + s->line_xpos = 0; + s->line_ypos = 0; + s->line_width=0; + s->fgcolor = lcd_get_foreground(); s->start_tick = current_tick + lcd_scroll_info.delay; s->style = style; lcd_puts_style_offset(x,y,string,style,offset); @@ -982,6 +1135,7 @@ int lastmode; unsigned old_fgcolor = fg_pattern; unsigned old_bgcolor = bg_pattern; + int fgcolor_save; for ( index = 0; index < LCD_SCROLLABLE_LINES; index++ ) { /* really scroll? */ @@ -1010,9 +1164,18 @@ else s->offset += lcd_scroll_info.step; + if (s->customline) { + lcd_setfont(s->line_font); + } + pf = font_get(curfont); - xpos = s->startx; - ypos = s->y_margin + index * pf->height; + if (s->customline) { + xpos = s->line_xpos; + ypos = s->line_ypos; + } else { + xpos = s->startx; + ypos = s->y_margin + index * pf->height; + } if (s->bidir) { /* scroll bidirectional */ if (s->offset <= 0) { @@ -1033,7 +1196,10 @@ if (s->offset >= s->width) s->offset %= s->width; } - + + fgcolor_save = lcd_get_foreground(); + lcd_set_foreground(s->fgcolor); + lastmode = drawmode; switch (s->style&STYLE_MODE_MASK) { case STYLE_INVERT: @@ -1056,13 +1222,14 @@ drawmode = DRMODE_SOLID; break; } - lcd_putsxyofs(xpos, ypos, s->offset, s->line); + lcd_putsxyofs_custom(xpos, ypos, s->offset, s->line, s->right_margin); if (LCD_WIDTH>s->right_margin) { drawmode ^= DRMODE_INVERSEVID; lcd_fillrect(s->right_margin, ypos, LCD_WIDTH - s->right_margin, pf->height); } drawmode = lastmode; lcd_update_rect(xpos, ypos, s->right_margin - xpos, pf->height); + lcd_set_foreground(fgcolor_save); } fg_pattern = old_fgcolor; diff -u -r rockbox_svn.orig/firmware/drivers/lcd-2bit-vert.c rockbox_svn/firmware/drivers/lcd-2bit-vert.c --- rockbox_svn.orig/firmware/drivers/lcd-2bit-vert.c 2007-11-12 23:57:34.060500000 -0600 +++ rockbox_svn/firmware/drivers/lcd-2bit-vert.c 2007-11-12 23:55:25.263625000 -0600 @@ -128,6 +128,11 @@ return ymargin; } +int lcd_getmarginwidth(void) +{ + return lcd_getrightmargin()-lcd_getleftmargin(); +} + void lcd_setfont(int newfont) { curfont = newfont; @@ -1011,6 +1016,68 @@ drawmode = lastmode; } +/* put a string at a given pixel position, skipping first ofs pixel columns + if rmargin==0 the global rightmargin is used */ +static void lcd_putsxyofs_custom(int x, int y, int ofs, const unsigned char *str, int rmargin) +{ + unsigned short ch; + unsigned short *ucs; + struct font* pf = font_get(curfont); + int used_rightmargin=rmargin?rmargin:rightmargin; + + ucs = bidi_l2v(str, 1); + + while ((ch = *ucs++) != 0 && x < used_rightmargin) + { + int width; + const unsigned char *bits; + + /* get proportional width and glyph bits */ + width = font_get_width(pf,ch,curfont); + + if (ofs > width) + { + ofs -= width; + continue; + } + + bits = font_get_bits(pf, ch, curfont); + + lcd_mono_bitmap_part(bits, ofs, 0, width, x, y, (x+width > used_rightmargin?used_rightmargin-x:width) - ofs, pf->height); + + x += width - ofs; + ofs = 0; + } +} + +void lcd_puts_customline_style_offset(int i, const unsigned char *str, int style, + int offset) +{ + int xpos,ypos,w,h,xrect; + int lastmode = drawmode; + + /* make sure scrolling is turned off on the line we are updating */ + lcd_scroll_info.lines &= ~(1 << i); + + if(!str || !str[0]) + return; + + lcd_getstringsize(str, &w, &h); + xpos = leftmargin; + ypos = ymargin; + drawmode = (style & STYLE_INVERT) ? + (DRMODE_SOLID|DRMODE_INVERSEVID) : DRMODE_SOLID; + lcd_putsxyofs_custom(xpos, ypos, offset, str, 0); + drawmode ^= DRMODE_INVERSEVID; + xrect = xpos + MAX(w - offset, 0); + lcd_fillrect(xpos + w, ypos, rightmargin - (xpos + w), h); + drawmode = lastmode; +} + +void lcd_puts_customline_offset(int i, const unsigned char *str, int offset) +{ + lcd_puts_customline_style_offset(i, str, STYLE_DEFAULT, offset); +} /*** scrolling ***/ void lcd_puts_scroll(int x, int y, const unsigned char *string) @@ -1038,13 +1105,21 @@ s = &lcd_scroll_info.scroll[y]; + // MWE reset customline attributes + s->customline = false; + s->line_font = curfont; + s->line_xpos = 0; + s->line_ypos = 0; + s->line_width=0; + s->fgcolor = lcd_get_foreground(); + s->start_tick = current_tick + lcd_scroll_info.delay; s->style = style; if (style & STYLE_INVERT) { - lcd_puts_style_offset(x,y,string,STYLE_INVERT,offset); + lcd_puts_style_offset(0,0,string,STYLE_INVERT,offset); } else - lcd_puts_offset(x,y,string,offset); + lcd_puts_offset(0,0,string,offset); lcd_getstringsize(string, &w, &h); @@ -1109,14 +1184,23 @@ if (TIME_BEFORE(current_tick, s->start_tick)) continue; + if (s->customline) { + lcd_setfont(s->line_font); + } + if (s->backward) s->offset -= lcd_scroll_info.step; else s->offset += lcd_scroll_info.step; pf = font_get(curfont); - xpos = s->startx; - ypos = s->y_margin + index * pf->height; + if (s->customline) { + xpos = s->line_xpos; + ypos = s->line_ypos; + } else { + xpos = s->startx; + ypos = s->y_margin + index * pf->height; + } if (s->bidir) { /* scroll bidirectional */ if (s->offset <= 0) { @@ -1141,12 +1225,90 @@ lastmode = drawmode; drawmode = (s->style&STYLE_INVERT) ? (DRMODE_SOLID|DRMODE_INVERSEVID) : DRMODE_SOLID; - lcd_putsxyofs(xpos, ypos, s->offset, s->line); - if (LCD_WIDTH>s->right_margin) { - drawmode ^= DRMODE_INVERSEVID; - lcd_fillrect(s->right_margin, ypos, LCD_WIDTH - s->right_margin, pf->height); - } + lcd_putsxyofs_custom(xpos, ypos, s->offset, s->line, s->right_margin); drawmode = lastmode; lcd_update_rect(xpos, ypos, s->right_margin - xpos, pf->height); } } + +void lcd_puts_customline_scroll_style(int i, const unsigned char *string, int style) +{ + lcd_puts_customline_scroll_style_offset(i, string, style, 0); +} + +void lcd_puts_customline_scroll_offset(int i, const unsigned char *string, int offset) +{ + lcd_puts_customline_scroll_style_offset(i, string, STYLE_DEFAULT, offset); +} + +void lcd_puts_customline_scroll(int i, const unsigned char *string) +{ + lcd_puts_customline_scroll_style_offset(i, string, + STYLE_DEFAULT, 0); +} + +void lcd_puts_customline_scroll_style_offset(int i, + const unsigned char *string, int style, int offset) +{ + struct scrollinfo* s; + int w, h; + + s = &lcd_scroll_info.scroll[i]; + + s->customline = true; + s->line_font = curfont; + s->line_xpos = lcd_getleftmargin(); + s->line_ypos = lcd_getymargin(); + s->line_width = lcd_getrightmargin()-lcd_getleftmargin(); + + s->start_tick = current_tick + lcd_scroll_info.delay; + s->style = style; + if (style & STYLE_INVERT) { + lcd_puts_customline_style_offset(i,string,STYLE_INVERT,offset); + } + else + lcd_puts_customline_offset(i,string,offset); + + lcd_getstringsize(string, &w, &h); + + if (s->line_width < w) { + /* prepare scroll line */ + char *end; + + memset(s->line, 0, sizeof s->line); + strcpy(s->line, string); + + /* get width */ + s->width = lcd_getstringsize(s->line, &w, &h); + + /* scroll bidirectional or forward only depending on the string + width */ + if ( lcd_scroll_info.bidir_limit ) { + s->bidir = s->width < (s->line_width) * + (100 + lcd_scroll_info.bidir_limit) / 100; + } + else + s->bidir = false; + + if (!s->bidir) { /* add spaces if scrolling in the round */ + strcat(s->line, " "); + /* get new width incl. spaces */ + s->width = lcd_getstringsize(s->line, &w, &h); + } + + end = strchr(s->line, '\0'); + strncpy(end, string, s->line_width/2); + + s->len = utf8length(string); + s->offset = offset; + s->startx = leftmargin + leftmargin * s->width / s->len; + s->backward = false; + s->left_margin=s->line_xpos; + s->right_margin=s->line_xpos+s->line_width; + s->y_margin=ymargin; + lcd_scroll_info.lines |= (1< width) + { + ofs -= width; + continue; + } + + bits = font_get_bits(pf, ch, curfont); + + lcd_remote_mono_bitmap_part(bits, ofs, 0, width, x, y, (x+width > used_rightmargin?used_rightmargin-x:width) - ofs, + pf->height); + + x += width - ofs; + ofs = 0; + } +} + +void lcd_remote_puts_customline_style_offset(int i, const unsigned char *str, int style, + int offset) +{ + int xpos,ypos,w,h,xrect; + int lastmode = drawmode; + + /* make sure scrolling is turned off on the line we are updating */ + lcd_scroll_info.lines &= ~(1 << i); + + if(!str || !str[0]) + return; + + lcd_remote_getstringsize(str, &w, &h); + xpos = leftmargin; + ypos = ymargin; + drawmode = (style & STYLE_INVERT) ? + (DRMODE_SOLID|DRMODE_INVERSEVID) : DRMODE_SOLID; + lcd_remote_putsxyofs_custom(xpos, ypos, offset, str, 0); + drawmode ^= DRMODE_INVERSEVID; + xrect = xpos + MAX(w - offset, 0); + lcd_remote_fillrect(xpos + w, ypos, rightmargin - (xpos + w), h); + drawmode = lastmode; +} + +void lcd_remote_puts_customline_offset(int i, const unsigned char *str, int offset) +{ + lcd_remote_puts_customline_style_offset(i, str, STYLE_DEFAULT, offset); +} + /*** scrolling ***/ void lcd_remote_puts_scroll(int x, int y, const unsigned char *string) @@ -769,14 +838,23 @@ if (TIME_BEFORE(current_tick, s->start_tick)) continue; + if (s->customline) { + lcd_remote_setfont(s->line_font); + } + if (s->backward) s->offset -= lcd_remote_scroll_info.step; else s->offset += lcd_remote_scroll_info.step; pf = font_get(curfont); - xpos = s->startx; - ypos = s->y_margin + index * pf->height; + if (s->customline) { + xpos = s->line_xpos; + ypos = s->line_ypos; + } else { + xpos = s->startx; + ypos = s->y_margin + index * pf->height; + } if (s->bidir) { /* scroll bidirectional */ if (s->offset <= 0) { @@ -801,11 +879,7 @@ lastmode = drawmode; drawmode = (s->style&STYLE_INVERT) ? (DRMODE_SOLID|DRMODE_INVERSEVID) : DRMODE_SOLID; - lcd_remote_putsxyofs(xpos, ypos, s->offset, s->line); - if (LCD_REMOTE_WIDTH > s->right_margin) { - drawmode ^= DRMODE_INVERSEVID; - lcd_remote_fillrect(s->right_margin, ypos, LCD_REMOTE_WIDTH - s->right_margin, pf->height); - } + lcd_remote_putsxyofs_custom(xpos, ypos, s->offset, s->line, s->right_margin); drawmode = lastmode; lcd_remote_update_rect(xpos, ypos, s->right_margin - xpos, pf->height); } @@ -819,3 +893,85 @@ lcd_remote_init_device(); #endif } + +void lcd_remote_puts_customline_scroll_style(int i, const unsigned char *string, int style) +{ + lcd_remote_puts_customline_scroll_style_offset(i, string, style, 0); +} + +void lcd_remote_puts_customline_scroll_offset(int i, const unsigned char *string, int offset) +{ + lcd_remote_puts_customline_scroll_style_offset(i, string, STYLE_DEFAULT, offset); +} + +void lcd_remote_puts_customline_scroll(int i, const unsigned char *string) +{ + lcd_remote_puts_customline_scroll_style_offset(i, string, + STYLE_DEFAULT, 0); +} + +void lcd_remote_puts_customline_scroll_style_offset(int i, const unsigned char *string, + int style, int offset) +{ + struct scrollinfo* s; + int w, h; + + s = &lcd_scroll_info.scroll[i]; + + s->customline = true; + s->line_font = curfont; + s->line_xpos = lcd_remote_getleftmargin(); + s->line_ypos = lcd_remote_getymargin(); + s->line_width = lcd_remote_getrightmargin()-lcd_remote_getleftmargin(); + + s->start_tick = current_tick + lcd_scroll_info.delay; + s->style = style; + if (style & STYLE_INVERT) { + lcd_remote_puts_customline_style_offset(i,string,STYLE_INVERT,offset); + } + else + lcd_remote_puts_customline_offset(i,string,offset); + + lcd_remote_getstringsize(string, &w, &h); + + if (s->line_width < w) { + /* prepare scroll line */ + char *end; + + memset(s->line, 0, sizeof s->line); + strcpy(s->line, string); + + /* get width */ + s->width = lcd_remote_getstringsize(s->line, &w, &h); + + /* scroll bidirectional or forward only depending on the string + width */ + if ( lcd_scroll_info.bidir_limit ) { + s->bidir = s->width < (s->line_width) * + (100 + lcd_scroll_info.bidir_limit) / 100; + } + else + s->bidir = false; + + if (!s->bidir) { /* add spaces if scrolling in the round */ + strcat(s->line, " "); + /* get new width incl. spaces */ + s->width = lcd_remote_getstringsize(s->line, &w, &h); + } + + end = strchr(s->line, '\0'); + strncpy(end, string, s->line_width/2); + + s->len = utf8length(string); + s->offset = offset; + s->startx = leftmargin + leftmargin * s->width / s->len; + s->backward = false; + s->left_margin=s->line_xpos; + s->right_margin=s->line_xpos+s->line_width; + s->y_margin=ymargin; + lcd_scroll_info.lines |= (1< used_rightmargin?used_rightmargin-x:width) - ofs, pf->height); x += width - ofs; @@ -960,7 +967,7 @@ /* put a string at a given pixel position */ void lcd_remote_putsxy(int x, int y, const unsigned char *str) { - lcd_remote_putsxyofs(x, y, 0, str); + lcd_remote_putsxyofs(x, y, 0, str, 0); } /*** line oriented text output ***/ @@ -981,6 +988,41 @@ lcd_remote_puts_style_offset(x, y, str, STYLE_DEFAULT, offset); } +/* put a string at a given pixel position, skipping first ofs pixel columns + if rmargin==0 the global rightmargin is used */ +void lcd_remote_putsxyofs_custom(int x, int y, int ofs, const unsigned char *str, int rmargin) +{ + unsigned short ch; + unsigned short *ucs; + struct font* pf = font_get(curfont); + int used_rightmargin=rmargin?rmargin:rightmargin; + + ucs = bidi_l2v(str, 1); + + while ((ch = *ucs++) != 0 && x < used_rightmargin) + { + int width; + const unsigned char *bits; + + /* get proportional width and glyph bits */ + width = font_get_width(pf, ch, curfont); + + if (ofs > width) + { + ofs -= width; + continue; + } + + bits = font_get_bits(pf, ch, curfont); + + lcd_remote_mono_bitmap_part(bits, ofs, 0, width, x, y, (x+width > used_rightmargin?used_rightmargin-x:width) - ofs, + pf->height); + + x += width - ofs; + ofs = 0; + } +} + /* put a string at a given char position, style, and pixel position, * skipping first offset pixel columns */ void lcd_remote_puts_style_offset(int x, int y, const unsigned char *str, @@ -1000,13 +1042,42 @@ ypos = ymargin + y*h; drawmode = (style & STYLE_INVERT) ? (DRMODE_SOLID|DRMODE_INVERSEVID) : DRMODE_SOLID; - lcd_remote_putsxyofs(xpos, ypos, offset, str); + lcd_remote_putsxyofs(xpos, ypos, offset, str, 0); drawmode ^= DRMODE_INVERSEVID; xrect = xpos + MAX(w - offset, 0); - lcd_remote_fillrect(xrect, ypos, LCD_REMOTE_WIDTH - xrect, h); + lcd_remote_fillrect(xpos + w, ypos, rightmargin - (xpos + w), h); drawmode = lastmode; } +void lcd_remote_puts_customline_style_offset(int i, const unsigned char *str, int style, + int offset) +{ + int xpos,ypos,w,h,xrect; + int lastmode = drawmode; + + /* make sure scrolling is turned off on the line we are updating */ + lcd_remote_scroll_info.lines &= ~(1 << i); + + if(!str || !str[0]) + return; + + lcd_remote_getstringsize(str, &w, &h); + xpos = leftmargin; + ypos = ymargin; + drawmode = (style & STYLE_INVERT) ? + (DRMODE_SOLID|DRMODE_INVERSEVID) : DRMODE_SOLID; + lcd_remote_putsxyofs_custom(xpos, ypos, offset, str, 0); + drawmode ^= DRMODE_INVERSEVID; + xrect = xpos + MAX(w - offset, 0); + lcd_remote_fillrect(xpos + w, ypos, rightmargin - (xpos + w), h); + drawmode = lastmode; +} + +void lcd_remote_puts_customline_offset(int i, const unsigned char *str, int offset) +{ + lcd_remote_puts_customline_style_offset(i, str, STYLE_DEFAULT, offset); +} + /*** scrolling ***/ void lcd_remote_puts_scroll(int x, int y, const unsigned char *string) { @@ -1033,6 +1104,13 @@ s = &lcd_remote_scroll_info.scroll[y]; + // MWE reset customline attributes + s->customline = false; + s->line_font = curfont; + s->line_xpos = 0; + s->line_ypos = 0; + s->line_width=0; + s->start_tick = current_tick + lcd_remote_scroll_info.delay; s->style = style; if (style & STYLE_INVERT) { @@ -1040,7 +1118,6 @@ } else lcd_remote_puts_offset(x,y,string,offset); - lcd_remote_getstringsize(string, &w, &h); if (LCD_REMOTE_WIDTH - x * 8 - leftmargin < w) { @@ -1069,12 +1146,14 @@ } end = strchr(s->line, '\0'); - strncpy(end, (char *)string, LCD_REMOTE_WIDTH/2); + strncpy(end, (char *)string, rightmargin/2); s->len = utf8length((char *)string); s->offset = offset; s->startx = leftmargin + x * s->width / s->len;; s->backward = false; + s->left_margin=leftmargin; + s->right_margin=rightmargin; lcd_remote_scroll_info.lines |= (1<y_margin=ymargin; } @@ -1090,7 +1169,7 @@ int index; int xpos, ypos; int lastmode; - + for ( index = 0; index < LCD_REMOTE_SCROLLABLE_LINES; index++ ) { /* really scroll? */ if ((lcd_remote_scroll_info.lines & (1 << index)) == 0) @@ -1102,14 +1181,23 @@ if (TIME_BEFORE(current_tick, s->start_tick)) continue; + if (s->customline) { + lcd_remote_setfont(s->line_font); + } + if (s->backward) s->offset -= lcd_remote_scroll_info.step; else s->offset += lcd_remote_scroll_info.step; pf = font_get(curfont); - xpos = s->startx; - ypos = s->y_margin + index * pf->height; + if (s->customline) { + xpos = s->line_xpos; + ypos = s->line_ypos; + } else { + xpos = s->startx; + ypos = s->y_margin + index * pf->height; + } if (s->bidir) { /* scroll bidirectional */ if (s->offset <= 0) { @@ -1118,9 +1206,9 @@ s->backward = false; s->start_tick = current_tick + lcd_remote_scroll_info.delay*2; } - if (s->offset >= s->width - (LCD_REMOTE_WIDTH - xpos)) { + if (s->offset >= s->width - (s->right_margin - xpos)) { /* at end of line */ - s->offset = s->width - (LCD_REMOTE_WIDTH - xpos); + s->offset = s->width - (s->right_margin - xpos); s->backward = true; s->start_tick = current_tick + lcd_remote_scroll_info.delay*2; } @@ -1134,9 +1222,9 @@ lastmode = drawmode; drawmode = (s->style&STYLE_INVERT) ? (DRMODE_SOLID|DRMODE_INVERSEVID) : DRMODE_SOLID; - lcd_remote_putsxyofs(xpos, ypos, s->offset, s->line); + lcd_remote_putsxyofs_custom(xpos, ypos, s->offset, s->line, s->right_margin); drawmode = lastmode; - lcd_remote_update_rect(xpos, ypos, LCD_REMOTE_WIDTH - xpos, pf->height); + lcd_remote_update_rect(xpos, ypos, s->right_margin - xpos, pf->height); } } @@ -1148,3 +1236,85 @@ lcd_remote_init_device(); #endif } + +void lcd_remote_puts_customline_scroll_style(int i, const unsigned char *string, int style) +{ + lcd_remote_puts_customline_scroll_style_offset(i, string, style, 0); +} + +void lcd_remote_puts_customline_scroll_offset(int i, const unsigned char *string, int offset) +{ + lcd_remote_puts_customline_scroll_style_offset(i, string, STYLE_DEFAULT, offset); +} + +void lcd_remote_puts_customline_scroll(int i, const unsigned char *string) +{ + lcd_remote_puts_customline_scroll_style_offset(i, string, + STYLE_DEFAULT, 0); +} + +void lcd_remote_puts_customline_scroll_style_offset(int i, const unsigned char *string, + int style, int offset) +{ + struct scrollinfo* s; + int w, h; + + s = &lcd_remote_scroll_info.scroll[i]; + + s->customline = true; + s->line_font = curfont; + s->line_xpos = lcd_remote_getleftmargin(); + s->line_ypos = lcd_remote_getymargin(); + s->line_width = lcd_remote_getrightmargin()-lcd_remote_getleftmargin(); + + s->start_tick = current_tick + lcd_remote_scroll_info.delay; + s->style = style; + if (style & STYLE_INVERT) { + lcd_remote_puts_customline_style_offset(i,string,STYLE_INVERT,offset); + } + else + lcd_remote_puts_customline_offset(i,string,offset); + lcd_remote_getstringsize(string, &w, &h); + + if (s->line_width < w) { + /* prepare scroll line */ + char *end; + + memset(s->line, 0, sizeof s->line); + strcpy(s->line, (char *)string); + + /* get width */ + s->width = lcd_remote_getstringsize(s->line, &w, &h); + + /* scroll bidirectional or forward only depending on the string + width */ + if ( lcd_remote_scroll_info.bidir_limit ) { + s->bidir = s->width < (s->line_width) * + (100 + lcd_remote_scroll_info.bidir_limit) / 100; + } + else + s->bidir = false; + + if (!s->bidir) { /* add spaces if scrolling in the round */ + strcat(s->line, " "); + /* get new width incl. spaces */ + s->width = lcd_remote_getstringsize((unsigned char *)s->line, &w, &h); + } + + end = strchr(s->line, '\0'); + strncpy(end, (char *)string, s->line_width/2); + + s->len = utf8length((char *)string); + s->offset = offset; + s->startx = leftmargin + leftmargin * s->width / s->len; + s->backward = false; + s->left_margin=s->line_xpos; + s->right_margin=s->line_xpos+s->line_width; + s->y_margin=ymargin; + lcd_remote_scroll_info.lines |= (1<= 8 extern lcd_fastpixelfunc_type* const *lcd_fastpixelfuncs; diff -u -r rockbox_svn.orig/firmware/export/scroll_engine.h rockbox_svn/firmware/export/scroll_engine.h --- rockbox_svn.orig/firmware/export/scroll_engine.h 2007-11-12 23:57:25.060500000 -0600 +++ rockbox_svn/firmware/export/scroll_engine.h 2007-11-12 23:55:25.357375000 -0600 @@ -51,6 +51,13 @@ int y_margin; int left_margin; int right_margin; + /* Customline arguments */ + bool customline; + int line_font; + int line_xpos; + int line_ypos; + int line_width; + int fgcolor; }; struct scroll_screen_info