Index: apps/gui/gwps-common.c =================================================================== --- apps/gui/gwps-common.c.orig +++ apps/gui/gwps-common.c @@ -1453,7 +1453,55 @@ static char *get_token_value(struct gui_ case WPS_TOKEN_ALIGN_SCROLLMARGIN_RIGHT: 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; } @@ -1768,7 +1816,8 @@ static bool update_curr_subline(struct g 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) @@ -1781,7 +1830,8 @@ static void write_line(struct screen *di 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) { @@ -1791,7 +1841,12 @@ static void write_line(struct screen *di else { left_width = 0; } - 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, @@ -1800,8 +1855,13 @@ static void write_line(struct screen *di else { center_width = 0; } - 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); @@ -1809,7 +1869,12 @@ static void write_line(struct screen *di else { right_width = 0; } - 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 @@ -1897,40 +1962,82 @@ static void write_line(struct screen *di 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 (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 line first */ - display->set_drawmode(DRMODE_SOLID|DRMODE_INVERSEVID); - display->fillrect(0, ypos, display->width, string_height); - display->set_drawmode(DRMODE_SOLID); + /* 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_scroll(0, line, (unsigned char *)""); + /* 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 area first if there is something to display */ + if (left_width || center_width || right_width) { + display->set_drawmode(DRMODE_SOLID|DRMODE_INVERSEVID); + display->fillrect(0, ypos, display->width, string_height); + display->set_drawmode(DRMODE_SOLID); + } +#endif - /* 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); + } + } } } @@ -1957,6 +2064,16 @@ bool gui_wps_refresh(struct gui_wps *gwp 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 gui_wps_statusbar_draw(gwps, true); @@ -2071,10 +2188,10 @@ bool gui_wps_refresh(struct gui_wps *gwp /* 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); } } @@ -2121,6 +2238,12 @@ bool gui_wps_refresh(struct gui_wps *gwp } #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; } Index: apps/gui/gwps.h =================================================================== --- apps/gui/gwps.h.orig +++ apps/gui/gwps.h @@ -211,6 +211,13 @@ enum wps_token_type { /* 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 */ @@ -375,6 +382,12 @@ struct wps_data 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 */ Index: apps/screen_access.h =================================================================== --- apps/screen_access.h.orig +++ apps/screen_access.h @@ -69,7 +69,7 @@ struct screen 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); @@ -128,6 +128,10 @@ struct screen 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); Index: apps/screen_access.c =================================================================== --- apps/screen_access.c.orig +++ apps/screen_access.c @@ -47,6 +47,7 @@ void screen_init(struct screen * screen, screen->getymargin=&lcd_remote_getymargin; screen->getleftmargin=&lcd_remote_getleftmargin; screen->getrightmargin=&lcd_remote_getrightmargin; + screen->getmarginwidth=&lcd_remote_getmarginwidth; screen->getstringsize=&lcd_remote_getstringsize; #if 1 /* all remote LCDs are bitmapped so far */ screen->setfont=&lcd_remote_setfont; @@ -98,7 +99,9 @@ void screen_init(struct screen * screen, screen->puts=&lcd_remote_puts; screen->puts_offset=&lcd_remote_puts_offset; screen->puts_scroll=&lcd_remote_puts_scroll; + screen->puts_customline_scroll=&lcd_remote_puts_customline_scroll; screen->puts_scroll_offset=&lcd_remote_puts_scroll_offset; + screen->puts_customline_scroll_offset=&lcd_remote_puts_customline_scroll_offset; screen->scroll_speed=&lcd_remote_scroll_speed; screen->scroll_delay=&lcd_remote_scroll_delay; screen->stop_scroll=&lcd_remote_stop_scroll; @@ -125,6 +128,7 @@ void screen_init(struct screen * screen, screen->getymargin=&lcd_getymargin; screen->getleftmargin=&lcd_getleftmargin; screen->getrightmargin=&lcd_getrightmargin; + screen->getmarginwidth=&lcd_getmarginwidth; screen->getstringsize=&lcd_getstringsize; #ifdef HAVE_LCD_BITMAP screen->setfont=&lcd_setfont; @@ -178,7 +182,9 @@ void screen_init(struct screen * screen, screen->puts=&lcd_puts; screen->puts_offset=&lcd_puts_offset; screen->puts_scroll=&lcd_puts_scroll; + screen->puts_customline_scroll=&lcd_puts_customline_scroll; screen->puts_scroll_offset=&lcd_puts_scroll_offset; + screen->puts_customline_scroll_offset=&lcd_puts_customline_scroll_offset; screen->scroll_speed=&lcd_scroll_speed; screen->scroll_delay=&lcd_scroll_delay; screen->stop_scroll=&lcd_stop_scroll; Index: firmware/export/lcd.h =================================================================== --- firmware/export/lcd.h.orig +++ firmware/export/lcd.h @@ -64,6 +64,7 @@ extern void lcd_setmargins(int leftmargi extern int lcd_getleftmargin(void); extern int lcd_getrightmargin(void); extern int lcd_getymargin(void); +extern int lcd_getmarginwidth(void); extern int lcd_getstringsize(const unsigned char *str, int *w, int *h); extern void lcd_update(void); @@ -83,6 +84,14 @@ extern void lcd_puts_scroll(int x, int y extern void lcd_puts_scroll_style(int x, int y, const unsigned char* string, int style); +extern void lcd_puts_customline_scroll(int i, const unsigned char *string); +extern void lcd_puts_customline_scroll_style(int i, const unsigned char *str, + int style); +extern void lcd_puts_customline_scroll_offset(int i, const unsigned char *string, + int offset); +extern void lcd_puts_customline_scroll_style_offset(int i, const unsigned char *string, + int style, int offset); + #if defined(HAVE_LCD_COLOR) && !defined(SIMULATOR) extern void lcd_yuv_blit(unsigned char * const src[3], int src_x, int src_y, int stride, @@ -316,6 +325,11 @@ extern void lcd_puts_style_offset(int x, extern void lcd_puts_scroll_style_offset(int x, int y, const unsigned char *string, int style, int offset); +extern void lcd_puts_customline_scroll_offset(int i, const unsigned char *string, + int offset); +extern void lcd_puts_customline_scroll_style_offset(int i, const unsigned char *string, + int style, int offset); + /* low level drawing function pointer arrays */ #if LCD_DEPTH >= 8 extern lcd_fastpixelfunc_type* const *lcd_fastpixelfuncs; @@ -400,6 +414,13 @@ struct scrollinfo { int y_margin; int left_margin; int right_margin; + /* Custome line arguments */ + bool customline; + int line_font; + int line_xpos; + int line_ypos; + int line_width; + int fgcolor; }; #endif /* __LCD_H__ */ Index: firmware/drivers/lcd-16bit.c =================================================================== --- firmware/drivers/lcd-16bit.c.orig +++ firmware/drivers/lcd-16bit.c @@ -150,6 +150,11 @@ int lcd_getymargin(void) return ymargin; } +int lcd_getmarginwidth(void) +{ + return lcd_getrightmargin()-lcd_getleftmargin(); +} + void lcd_setfont(int newfont) { curfont = newfont; @@ -850,6 +855,69 @@ void lcd_puts_style_offset(int x, int y, 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 */ + scrolling_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 ***/ /* Reverse the invert setting of the scrolling line (if any) at given char @@ -891,6 +959,90 @@ void lcd_bidir_scroll(int percent) bidir_limit = percent; } +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 = &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 + scroll_delay; + s->invert = false; + if (style & STYLE_INVERT) { + s->invert = true; + 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 ( bidir_limit ) { + s->bidir = s->width < (s->line_width) * + (100 + 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; + scrolling_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 + scroll_delay; s->invert = false; + s->invert = false; + if (style & STYLE_INVERT) { s->invert = true; } @@ -977,6 +1138,7 @@ static void scroll_thread(void) int xpos, ypos; int lastmode; unsigned old_bgcolour, old_fgcolour; + int fgcolor_save; /* initialize scroll struct array */ scrolling_lines = 0; @@ -1016,9 +1178,18 @@ static void scroll_thread(void) else s->offset += scroll_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) { @@ -1040,12 +1211,17 @@ static void scroll_thread(void) s->offset %= s->width; } + fgcolor_save = lcd_get_foreground(); + lcd_set_foreground(s->fgcolor); + lastmode = drawmode; drawmode = s->invert ? (DRMODE_SOLID|DRMODE_INVERSEVID) : DRMODE_SOLID; - lcd_putsxyofs(xpos, ypos, s->offset, s->line, s->right_margin); + 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); + + lcd_set_foreground(fgcolor_save); } lcd_set_foreground(old_fgcolour); lcd_set_background(old_bgcolour); Index: firmware/drivers/lcd-remote-2bit-vi.c =================================================================== --- firmware/drivers/lcd-remote-2bit-vi.c.orig +++ firmware/drivers/lcd-remote-2bit-vi.c @@ -151,6 +151,11 @@ int lcd_remote_getymargin(void) return ymargin; } +int lcd_remote_getmarginwidth(void) +{ + return lcd_remote_getrightmargin()-lcd_remote_getleftmargin(); +} + void lcd_remote_setfont(int newfont) { curfont = newfont; @@ -1005,6 +1010,41 @@ void lcd_remote_puts_offset(int x, int y 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 */ +static 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, @@ -1024,13 +1064,42 @@ void lcd_remote_puts_style_offset(int x, ypos = ymargin + y*h; drawmode = (style & STYLE_INVERT) ? (DRMODE_SOLID|DRMODE_INVERSEVID) : DRMODE_SOLID; - lcd_remote_putsxyofs(xpos, ypos, offset, str, 0); + 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_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 */ + scrolling_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(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 ***/ /* Reverse the invert setting of the scrolling line (if any) at given char @@ -1096,7 +1165,14 @@ void lcd_remote_puts_scroll_style_offset if(y>=SCROLLABLE_LINES) return; s = &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 + scroll_delay; s->invert = false; if (style & STYLE_INVERT) { @@ -1204,14 +1280,24 @@ static void scroll_thread(void) if (TIME_BEFORE(current_tick, s->start_tick)) continue; + if (s->customline) { + lcd_remote_setfont(s->line_font); + } + if (s->backward) s->offset -= scroll_step; else s->offset += scroll_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) { @@ -1236,11 +1322,10 @@ static void scroll_thread(void) lastmode = drawmode; drawmode = s->invert ? (DRMODE_SOLID|DRMODE_INVERSEVID) : DRMODE_SOLID; - lcd_remote_putsxyofs(xpos, ypos, s->offset, s->line, s->right_margin); + 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); - } - + lcd_remote_update_rect(xpos, ypos, s->right_margin - xpos, pf->height); + } next_tick += scroll_ticks; delay = next_tick - current_tick - 1; @@ -1252,6 +1337,7 @@ static void scroll_thread(void) } } + /* LCD init */ void lcd_remote_init(void) { @@ -1265,3 +1351,87 @@ void lcd_remote_init(void) sizeof(scroll_stack), scroll_name IF_PRIO(, PRIORITY_USER_INTERFACE) IF_COP(, CPU, false)); } + +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 = &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 + scroll_delay; + s->invert = false; + if (style & STYLE_INVERT) { + s->invert = true; + 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 ( bidir_limit ) { + s->bidir = s->width < (s->line_width) * + (100 + 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; + scrolling_lines |= (1< 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 */ + scrolling_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 ***/ /* Reverse the invert setting of the scrolling line (if any) at given char @@ -1098,14 +1165,22 @@ void lcd_puts_scroll_style_offset(int x, s = &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 + scroll_delay; s->invert = false; - if (style & STYLE_INVERT) { - s->invert = true; - lcd_puts_style_offset(x,y,string,STYLE_INVERT,offset); - } - else - lcd_puts_offset(x,y,string,offset); + if (style & STYLE_INVERT) { + s->invert = true; + lcd_puts_style_offset(0,0,string,STYLE_INVERT,offset); + } + else + lcd_puts_offset(0,0,string,offset); lcd_getstringsize(string, &w, &h); @@ -1158,7 +1233,7 @@ static void scroll_thread(void) int index; int xpos, ypos; int lastmode; - + /* initialize scroll struct array */ scrolling_lines = 0; @@ -1174,14 +1249,24 @@ static void scroll_thread(void) if (TIME_BEFORE(current_tick, s->start_tick)) continue; + if (s->customline) { + lcd_setfont(s->line_font); + } + if (s->backward) s->offset -= scroll_step; else s->offset += scroll_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) { @@ -1206,11 +1291,7 @@ static void scroll_thread(void) lastmode = drawmode; drawmode = s->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); } @@ -1218,3 +1299,86 @@ static void scroll_thread(void) sleep(scroll_ticks); } } + +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 = &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 + scroll_delay; + s->invert = false; + if (style & STYLE_INVERT) { + s->invert = true; + 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 ( bidir_limit ) { + s->bidir = s->width < (s->line_width) * + (100 + 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; + scrolling_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 */ + scrolling_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 ***/ /* Reverse the invert setting of the scrolling line (if any) at given char @@ -867,15 +935,24 @@ static void scroll_thread(void) if (TIME_BEFORE(current_tick, s->start_tick)) continue; + if (s->customline) { + lcd_remote_setfont(s->line_font); + } + if (s->backward) s->offset -= scroll_step; else s->offset += scroll_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) { /* at beginning of line */ @@ -899,11 +976,7 @@ static void scroll_thread(void) lastmode = drawmode; drawmode = s->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_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); } @@ -931,3 +1004,86 @@ void lcd_remote_init(void) sizeof(scroll_stack), scroll_name IF_PRIO(, PRIORITY_USER_INTERFACE) IF_COP(, CPU, false)); } + +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 = &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 + scroll_delay; + s->invert = false; + if (style & STYLE_INVERT) { + s->invert = true; + 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 ( bidir_limit ) { + s->bidir = s->width < (s->line_width) * + (100 + 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; + scrolling_lines |= (1<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 ); +} + static int parse_albumart_load(const char *wps_bufptr, struct wps_token *token, struct wps_data *wps_data) @@ -1137,6 +1203,13 @@ void wps_data_init(struct wps_data *wps_ 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)