Example #1
0
static void skin_render_viewport(struct skin_element* viewport, struct gui_wps *gwps,
                                 struct skin_viewport* skin_viewport, unsigned long refresh_type)
{
    struct screen *display = gwps->display;
    char linebuf[MAX_LINE];
    skin_render_func func = skin_render_line;
    struct skin_element* line = viewport;
    struct skin_draw_info info = {
        .gwps = gwps,
        .buf = linebuf,
        .buf_size = sizeof(linebuf),
        .line_number = 0,
        .no_line_break = false,
        .line_scrolls = false,
        .refresh_type = refresh_type,
        .skin_vp = skin_viewport,
        .offset = 0
    };
    
    struct align_pos * align = &info.align;
    bool needs_update;
#ifdef HAVE_LCD_BITMAP
    /* Set images to not to be displayed */
    struct skin_token_list *imglist = gwps->data->images;
    while (imglist)
    {
        struct gui_img *img = (struct gui_img *)imglist->token->value.data;
        img->display = -1;
        imglist = imglist->next;
    }
#endif
    
    while (line)
    {
        linebuf[0] = '\0';
        info.no_line_break = false;
        info.line_scrolls = false;
        info.force_redraw = false;
    
        info.cur_align_start = info.buf;
        align->left = info.buf;
        align->center = NULL;
        align->right = NULL;
        
        
        if (line->type == LINE_ALTERNATOR)
            func = skin_render_alternator;
        else if (line->type == LINE)
            func = skin_render_line;
        
        needs_update = func(line, &info);
#if (LCD_DEPTH > 1) || (defined(HAVE_REMOTE_LCD) && (LCD_REMOTE_DEPTH > 1))
        if (skin_viewport->vp.fg_pattern != skin_viewport->start_fgcolour ||
            skin_viewport->vp.bg_pattern != skin_viewport->start_bgcolour)
        {
            /* 2bit lcd drivers need lcd_set_viewport() to be called to change
             * the colour, 16bit doesnt. But doing this makes static text
             * get the new colour also */
            needs_update = true;
            display->set_viewport(&skin_viewport->vp);
        }
#endif
        /* only update if the line needs to be, and there is something to write */
        if (refresh_type && needs_update)
        {
            if (info.line_scrolls)
            {
                /* 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_type & SKIN_REFRESH_SCROLL) || info.force_redraw)
                    write_line(display, align, info.line_number, true);
            }
            else
                write_line(display, align, info.line_number, false);
        }
        if (!info.no_line_break)
            info.line_number++;
        line = line->next;
    }
#ifdef HAVE_LCD_BITMAP
    wps_display_images(gwps, &skin_viewport->vp);
#endif
}

void skin_render(struct gui_wps *gwps, unsigned refresh_mode)
{
    struct wps_data *data = gwps->data;
    struct screen *display = gwps->display;
    
    struct skin_element* viewport = data->tree;
    struct skin_viewport* skin_viewport;
    
    int old_refresh_mode = refresh_mode;
    
#ifdef HAVE_LCD_CHARCELLS
    int i;
    for (i = 0; i < 8; i++)
    {
        if (data->wps_progress_pat[i] == 0)
            data->wps_progress_pat[i] = display->get_locked_pattern();
    }
#endif
    viewport = data->tree;
    skin_viewport = (struct skin_viewport *)viewport->data;
    if (skin_viewport->label && viewport->next &&
        !strcmp(skin_viewport->label,VP_DEFAULT_LABEL))
        refresh_mode = 0;
    
    for (viewport = data->tree;
         viewport;
         viewport = viewport->next)
    {
        /* SETUP */
        skin_viewport = (struct skin_viewport*)viewport->data;
        unsigned vp_refresh_mode = refresh_mode;
#if (LCD_DEPTH > 1) || (defined(HAVE_REMOTE_LCD) && LCD_REMOTE_DEPTH > 1)
        skin_viewport->vp.fg_pattern = skin_viewport->start_fgcolour;
        skin_viewport->vp.bg_pattern = skin_viewport->start_bgcolour;
#endif
        
        /* dont redraw the viewport if its disabled */
        if (skin_viewport->hidden_flags&VP_NEVER_VISIBLE)
        {   /* don't draw anything into this one */
            vp_refresh_mode = 0;
        }
        else if ((skin_viewport->hidden_flags&VP_DRAW_HIDDEN))
        {
            skin_viewport->hidden_flags |= VP_DRAW_WASHIDDEN;
            continue;
        }
        else if (((skin_viewport->hidden_flags&
                   (VP_DRAW_WASHIDDEN|VP_DRAW_HIDEABLE))
                    == (VP_DRAW_WASHIDDEN|VP_DRAW_HIDEABLE)))
        {
            vp_refresh_mode = SKIN_REFRESH_ALL;
            skin_viewport->hidden_flags = VP_DRAW_HIDEABLE;
        }
        
        display->set_viewport(&skin_viewport->vp);
        if ((vp_refresh_mode&SKIN_REFRESH_ALL) == SKIN_REFRESH_ALL)
        {
            display->clear_viewport();
        }
        /* render */
        if (viewport->children_count)
            skin_render_viewport(viewport->children[0], gwps,
                                 skin_viewport, vp_refresh_mode);
        refresh_mode = old_refresh_mode;
    }
    
    /* Restore the default viewport */
    display->set_viewport(NULL);
    display->update();
}

#ifdef HAVE_LCD_BITMAP
static __attribute__((noinline)) void skin_render_playlistviewer(struct playlistviewer* viewer,
                                       struct gui_wps *gwps,
                                       struct skin_viewport* skin_viewport,
                                       unsigned long refresh_type)
{
    struct screen *display = gwps->display;
    char linebuf[MAX_LINE];
    skin_render_func func = skin_render_line;
    struct skin_element* line;
    struct skin_draw_info info = {
        .gwps = gwps,
        .buf = linebuf,
        .buf_size = sizeof(linebuf),
        .line_number = 0,
        .no_line_break = false,
        .line_scrolls = false,
        .refresh_type = refresh_type,
        .skin_vp = skin_viewport,
        .offset = viewer->start_offset
    };
    
    struct align_pos * align = &info.align;
    bool needs_update;
    int cur_pos, start_item, max;
    int nb_lines = viewport_get_nb_lines(viewer->vp);
#if CONFIG_TUNER
    if (current_screen() == GO_TO_FM)
    {
        cur_pos = radio_current_preset();
        start_item = cur_pos + viewer->start_offset;
        max = start_item+radio_preset_count();
    }
    else
#endif
    {
        struct cuesheet *cue = skin_get_global_state()->id3 ? 
                               skin_get_global_state()->id3->cuesheet : NULL;
        cur_pos = playlist_get_display_index();
        max = playlist_amount()+1;
        if (cue)
            max += cue->track_count;
        start_item = MAX(0, cur_pos + viewer->start_offset); 
    }
    if (max-start_item > nb_lines)
        max = start_item + nb_lines;
    
    line = viewer->line;
    while (start_item < max)
    {
        linebuf[0] = '\0';
        info.no_line_break = false;
        info.line_scrolls = false;
        info.force_redraw = false;
    
        info.cur_align_start = info.buf;
        align->left = info.buf;
        align->center = NULL;
        align->right = NULL;
        
        
        if (line->type == LINE_ALTERNATOR)
            func = skin_render_alternator;
        else if (line->type == LINE)
            func = skin_render_line;
        
        needs_update = func(line, &info);
        
        /* only update if the line needs to be, and there is something to write */
        if (refresh_type && needs_update)
        {
            if (info.line_scrolls)
            {
                /* 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_type & SKIN_REFRESH_SCROLL) || info.force_redraw)
                    write_line(display, align, info.line_number, true);
            }
            else
                write_line(display, align, info.line_number, false);
        }
        info.line_number++;
        info.offset++;
        start_item++;
    }
}
Example #2
0
bool skinlist_draw(struct screen *display, struct gui_synclist *list)
{
    int cur_line, display_lines;
    const int screen = display->screen_type;
    struct viewport *parent = (list->parent[screen]);
    char* label = NULL;
    const int list_start_item = list->start_item[screen];
    struct gui_wps wps;
    if (!skinlist_is_configured(screen, list))
        return false;

    current_list = list;
    wps.display = display;
    wps.data = listcfg[screen]->data;
    display_lines = skinlist_get_line_count(screen, list);
    label = (char *)SKINOFFSETTOPTR(get_skin_buffer(wps.data), listcfg[screen]->label);
    display->set_viewport(parent);
    display->clear_viewport();
    current_item = list->selected_item;
    current_nbitems = list->nb_items;
    needs_scrollbar[screen] = list->nb_items > display_lines;

    for (cur_line = 0; cur_line < display_lines; cur_line++)
    {
        struct skin_element* viewport;
        struct skin_viewport* skin_viewport = NULL;
        if (list_start_item+cur_line+1 > list->nb_items)
            break;
        current_drawing_line = list_start_item+cur_line;
        is_selected = list->show_selection_marker &&
                list_start_item+cur_line == list->selected_item;

        for (viewport = SKINOFFSETTOPTR(get_skin_buffer(wps.data), listcfg[screen]->data->tree);
             viewport;
             viewport = SKINOFFSETTOPTR(get_skin_buffer(wps.data), viewport->next))
        {
            int original_x, original_y;
            skin_viewport = SKINOFFSETTOPTR(get_skin_buffer(wps.data), viewport->data);
            char *viewport_label = SKINOFFSETTOPTR(get_skin_buffer(wps.data), skin_viewport->label);
            if (viewport->children == 0 || !viewport_label ||
                (skin_viewport->label && strcmp(label, viewport_label))
                )
                continue;
            if (is_selected)
            {
                memcpy(&listcfg[screen]->selected_item_vp, skin_viewport, sizeof(struct skin_viewport));
                skin_viewport = &listcfg[screen]->selected_item_vp;
            }
            original_x = skin_viewport->vp.x;
            original_y = skin_viewport->vp.y;
            if (listcfg[screen]->tile)
            {
                int cols = (parent->width / listcfg[screen]->width);
                current_column = (cur_line)%cols;
                current_row = (cur_line)/cols;
                
                skin_viewport->vp.x = parent->x + listcfg[screen]->width*current_column + original_x;
                skin_viewport->vp.y = parent->y + listcfg[screen]->height*current_row + original_y;
            }
            else
            {
                current_column = 1;
                current_row = cur_line;
                skin_viewport->vp.x = parent->x + original_x;
                skin_viewport->vp.y = parent->y + original_y +
                                   (listcfg[screen]->height*cur_line);
            }
            display->set_viewport(&skin_viewport->vp);
#ifdef HAVE_LCD_BITMAP
            /* Set images to not to be displayed */
            struct skin_token_list *imglist = SKINOFFSETTOPTR(get_skin_buffer(wps.data), wps.data->images);
            while (imglist)
            {
                struct wps_token *token = SKINOFFSETTOPTR(get_skin_buffer(wps.data), imglist->token);
                struct gui_img *img = SKINOFFSETTOPTR(get_skin_buffer(wps.data), token->value.data);
                img->display = -1;
                imglist = SKINOFFSETTOPTR(get_skin_buffer(wps.data), imglist->next);
            }
#endif
            struct skin_element** children = SKINOFFSETTOPTR(get_skin_buffer(wps.data), viewport->children);
            skin_render_viewport(SKINOFFSETTOPTR(get_skin_buffer(wps.data), (intptr_t)children[0]),
                                 &wps, skin_viewport, SKIN_REFRESH_ALL);
#ifdef HAVE_LCD_BITMAP
            wps_display_images(&wps, &skin_viewport->vp);
#endif
            /* force disableing scroll because it breaks later */
            if (!is_selected)
            {
                display->scroll_stop_viewport(&skin_viewport->vp);
                skin_viewport->vp.x = original_x;
                skin_viewport->vp.y = original_y;
            }
        }
    }
    current_column = -1;
    current_row = -1;
    display->set_viewport(parent);
    display->update_viewport();
    current_drawing_line = list->selected_item;
    return true;
}