|
|
A Proposal for how Viewports could be implemented(by DaveChapman. A patch is available at FS#8385)Viewports DesignA Viewport is simply a C struct containing the LCD state. It is defined as follows:struct viewport { int x; int y; int width; int height; int font; int drawmode; #if LCD_DEPTH > 1 unsigned fg_pattern; unsigned bg_pattern; #endif }The basic principle is that the Rockbox apps/ code will statically declare the various viewports it needs, and set the current viewport used by the LCD driver functions with the function: void lcd_set_viewport(struct viewport* vp);
All the existing LCD functions will change their behaviour so that
they only draw within the boundary of the viewport, and will use the
current font, drawmode and colours defined in that viewport. (x,y)
co-ordinates passed to the LCD functions will always be relative to
the current viewport.
Functions such as lcd_set_drawmode, lcd_set_background will set values
in the current viewport.
We will want to define a transparency color to be used as foreground or background color so that the common backdrop can show through / is not obscured by the viewport -- PeterDHoye - 18 Dec 2007
Default viewportA default viewport covering the entire screen will be declared in the LCD driver. A call to lcd_set_viewport(NULL) will set this default viewport to be current.Scrolling linesScrolling lines in Rockbox currently use the LCD state (line style, margin) current at the time that lcd_puts_scroll() was called. The x position is specified by the lcd_puts_scroll() function (and is stored, added to the current left margin). Which lines are currently scrolling is stored as a bit-pattern in screen_scroll_info.lines (the maximum number of scrolling lines any target can have is 32). There is an array of up to 32 scrolling lines, and these lines represent the first 32 lines (based on current font height) on the screen - so the y positioning is implied by the index into the lines[] array. This won't work with viewports, as viewports can be positioned at arbitrary positions on the screen. It is also hoped that at some point in the future, Rockbox will have support for multiple fonts, so lines can vary in height depending on the font used. We can clear the scrolling lines for the current viewport when lcd_clear_display is called, but if the apps/ code switches to a new set of viewports, lcd_clear_display will never be called on the old viewports, so the lines will remain active... Maybe an "void lcd_stop_scrolling(struct viewport* vp);" function which would destroy all scrolling lines related to that viewport? This function would also be called by lcd_clear_display();struct scrollinfo { char line[SCROLL_LINE_SIZE]; int len; /* length of line in chars */ int offset; int startx; #ifdef HAVE_LCD_BITMAP int width; /* length of line in pixels */ int style; /* line style */ #endif/* HAVE_LCD_BITMAP */ bool backward; /* scroll presently forward or backward? */ bool bidir; long start_tick; };to being: struct scrollinfo { char line[SCROLL_LINE_SIZE]; int len; /* length of line in chars */ int offset; #ifdef HAVE_LCD_BITMAP int width; /* length of line in pixels */ int style; /* line style */ #endif/* HAVE_LCD_BITMAP */ bool backward; /* scroll presently forward or backward? */ bool bidir; long start_tick; struct viewport* vp; /* pointer to parent viewport */ };The tick function that performs the scrolling will save the pointer to the current viewport, set the scrolling line's viewport as current, draw the line, then restore the old viewport. Problems:
Backdrop handlingBackdrops will continue to be global and cover the entire LCD. However, there may be a desire for the ability to specify more backdrops than currently available - maybe use buffer_alloc() to store them on the audio buffer at boot time?viewports in apps/ codeMulti-screen APIHow can viewports be used with the multi-screen API? [to-do]List widgetThe majority of the screens in Rockbox are based on the list widget, which has the following layout, with most elements being optional.
SplashesSplashes could initially just use the global "whole-screen" viewport, but it might be desirable to allow scrolling text within the splash, and a splash viewport would allow that.QuickScreenWould be redesigned to exploit viewports.Radio screenInitially could use a whole-screen (minus status-bar) viewport, but could be reimplemented to make use of viewports.Recording screenInitially could use a whole-screen (minus status-bar) viewport, but could be reimplemented to make use of viewports.USB screenJust use default viewport?Yes/no dialogThis could be rewritten to use viewports and become a "pop-up" dialog. Either using a small list widget in the centre of the screen, or a new UI.Button barviewport for each button? Do we want scrolling text in the button bar?WPSWPS syntax will need to be extended to allow the user to declare viewports, with the full set of attributes, and then to specify the content of each viewport. A viewport declaration may look like this:%v[A-Z]|x|y|width|height|fgcolor|bgcolor|
(can be extended with other attributes in the future, such as font
size/face (if multiple font support is added)
A limit on the number of viewports will be needed, as these will be
declared statically in the WPS code.
Currently, each line in the WPS can have one of the following attributes:
#define WPS_REFRESH_STATIC 1 /* line doesn't change over time */ #define WPS_REFRESH_DYNAMIC 2 /* line may change (e.g. time flag) */ #define WPS_REFRESH_SCROLL 4 /* line scrolls */ #define WPS_REFRESH_PLAYER_PROGRESS 8 /* line contains a progress bar */ #define WPS_REFRESH_PEAK_METER 16 /* line contains a peak meter */When the WPS is parsed, it is stored in the wps_data struct as follows: int num_lines; struct wps_line lines[WPS_MAX_LINES] int num_sublines struct wps_subline sublines[WPS_MAX_LINES]The wps_line struct just has pointers into the sublines array, along with curr_subline and num_sublines variables (signed chars). The wps_subline struct contains a pointer to the first token in the WPS token array, the line_type variable (bit or'ed WPS_REFRESH_* values). The main WPS drawing function (gui_wps_refresh) iterates through all lines in the WPS, refreshing them according to the type of refresh passed as a parameter to this function. A new "viewport level" could be added to wps_data, so a WPS would then consist of a number of viewports, each containing a number of lines. The gui_wps_refresh() function would then have a new outer-loop iterating over the viewports, calling lcd_set_viewport() on each viewport in turn. This would make the viewport refresh order known to the WPS writer (viewports are refreshed in the order declared, and then there would simply be a new %V[A-Z] tag in the WPS which means that "all lines up to the next %V tag belong to this viewport". An implicit viewport would be defined to cover the entire screen, and all lines up to the first %V tag would be drawn in this viewport. This would maintain backwards-compatibility with WPSs not using viewports - apart from those using the %m tag, which will be removed. There may be a desire for viewports to be conditional - e.g. if album-art is present, lay out the screen in one way, otherwise lay it out in another way. This could be dealt with by allowing a conditional tag on its own line which includes %V tags and nothing else. e.g. to switch viewports based on the presence of album-art the WPS would contain: ?%C<%VA|%VB>
[code for both viewports]
OR:
?%C<%VA|>
[Code only for album art present]
?%C<|%VB>
[Code only for no album art present]
Is this straightforward to implement? Do we need the
second ability, or can that be dealt with by further use of %C within
the content code of the viewport?
Status barThere will be a status bar viewport used throughout core Rockbox. If the status bar is disabled, then the other viewports need to expand to fill the screen. Should we integrate the status bar as a special viewport within the WPS (use numbers 0-9 to specify system viewports, letters for user viewports?), allowing the full WPS syntax in the status bar. The status bar drawing code would be replaced with a call to the WPS code, telling it to refresh the content of the statusbar viewport only. Conditionals based on a "current screen" tag could perhaps be used to customise the status bar for different screens. A "current screen" string could also be defined to be displayed in the status bar viewport - Main menu, Now Playing etc Maybe the status bar would need to be multiple viewports - to allow scrolling text, as well as icons. This could be done by giving a "type" to viewports defined in the WPS. So we would have TYPE_STATUSBAR, TYPE_WPS (others?) and a call to the wps_refresh() function would update all viewports with the specified type. This would allow statusbar information to be located anywhere on the screen. Would we want to be able to merge the list title and status bar?r7 - 02 Apr 2021 - 20:46:07 - UnknownUser
Copyright © by the contributing authors.
|