draw_background_locked函數的實作代碼中又出現了幾個以gr_開頭的函數,以gr_開頭的函數來自minui庫, minui庫的代碼在recovery源碼下的minui目錄下,minui提供的接口實作了圖形的描繪以及固定大小的文字顯示。
gr_color(unsigned char r, unsigned char g, unsigned char b, unsigned char a);
gr_fill(int x, int y, int w, int h);
gr_blit(gr_surface source, int sx, int sy, int w, int h, int dx, int dy);
draw_background_locked函數先将整個渲染buffer填充為黑色,然後計算背景surface的長寬,文字surface的長寬, 再結合fb的長寬計算出背景surface以及文字surface顯示的坐标,有長寬和坐标就可以調用Pixelflinger的接口在渲染buffer上進行渲染。
void ScreenRecoveryUI::draw_progress_locked()
{ if (currentIcon == ERROR) return; if (currentIcon == INSTALLING_UPDATE || currentIcon == ERASING) { draw_install_overlay_locked(installingFrame); } if (progressBarType != EMPTY) { int iconHeight = gr_get_height(backgroundIcon[INSTALLING_UPDATE]); int width = gr_get_width(progressBarEmpty); int height = gr_get_height(progressBarEmpty); int dx = (gr_fb_width() - width)/2; int dy = (3*gr_fb_height() + iconHeight - 2*height)/4; // Erase behind the progress bar (in case this was a progress-only update) gr_color(0, 0, 0, 255); gr_fill(dx, dy, width, height); if (progressBarType == DETERMINATE) { float p = progressScopeStart + progress * progressScopeSize; int pos = (int) (p * width); if (rtl_locale) { // Fill the progress bar from right to left. if (pos > 0) { gr_blit(progressBarFill, width-pos, 0, pos, height, dx+width-pos, dy); } if (pos < width-1) { gr_blit(progressBarEmpty, 0, 0, width-pos, height, dx, dy); } } else { // Fill the progress bar from left to right. if (pos > 0) { gr_blit(progressBarFill, 0, 0, pos, height, dx, dy); } if (pos < width-1) { gr_blit(progressBarEmpty, pos, 0, width-pos, height, dx+pos, dy); } } } if (progressBarType == INDETERMINATE) { static int frame = 0; gr_blit(progressBarIndeterminate[frame], 0, 0, width, height, dx, dy); // in RTL locales, we run the animation backwards, which // makes the spinner spin the other way. if (rtl_locale) { frame = (frame + indeterminate_frames - 1) % indeterminate_frames; } else { frame = (frame + 1) % indeterminate_frames; } } }
}
draw_progress_locked函數的原理與 update_screen_locked函數類似, 最終是将進度條的surface輸出到渲染buffer,
recovery中各個場景的畫面,就是由背景、文字、進度條的重疊,不同的是所用的surface 以及surface的坐标。
recovery main函數中的UI代碼基本上已經分析過了,最後一點主菜單的顯示,就是通過上面介紹的這些接口将文字圖檔顯示出來,是以就不再多講。 總的來說,recovery的UI顯示部分難度不大,應用層調用minui庫實作了圖形的描繪以及固定大小的文字顯示,minui庫調用了Pixelflinger庫來進行渲染。
附上minui部分接口的說明,供參考
int gr_init(void); void gr_exit(void); int gr_fb_width(void); int gr_fb_height(void); gr_pixel *gr_fb_data(void); void gr_flip(void); void gr_fb_blank(bool blank); void gr_color(unsigned char r, unsigned char g, unsigned char b, unsigned char a); void gr_fill(int x, int y, int w, int h); int gr_text(int x, int y, const char *s); int gr_measure(const char *s); void gr_font_size(int *x, int *y); void gr_blit(gr_surface source, int sx, int sy, int w, int h, int dx, int dy); unsigned int gr_get_width(gr_surface surface); unsigned int gr_get_height(gr_surface surface); int res_create_surface(const char* name, gr_surface* pSurface); void res_free_surface(gr_surface surface);