void
ScreenRecoveryUI::Init()
{
gr_init();
gr_font_size(&char_width, &char_height);
text_col = text_row =
0
;
text_rows = gr_fb_height() / char_height;
if
(text_rows > kMaxRows) text_rows = kMaxRows;
text_top =
1
;
text_cols = gr_fb_width() / char_width;
if
(text_cols > kMaxCols -
1
) text_cols = kMaxCols -
1
;
LoadBitmap(
"icon_installing"
, &backgroundIcon[INSTALLING_UPDATE]);
backgroundIcon[ERASING] = backgroundIcon[INSTALLING_UPDATE];
LoadBitmap(
"icon_error"
, &backgroundIcon[ERROR]);
backgroundIcon[NO_COMMAND] = backgroundIcon[ERROR];
LoadBitmap(
"progress_empty"
, &progressBarEmpty);
LoadBitmap(
"progress_fill"
, &progressBarFill);
LoadLocalizedBitmap(
"installing_text"
, &backgroundText[INSTALLING_UPDATE]);
LoadLocalizedBitmap(
"erasing_text"
, &backgroundText[ERASING]);
LoadLocalizedBitmap(
"no_command_text"
, &backgroundText[NO_COMMAND]);
LoadLocalizedBitmap(
"error_text"
, &backgroundText[ERROR]);
int
i;
progressBarIndeterminate = (gr_surface*)malloc(indeterminate_frames *
sizeof(gr_surface));
for
(i =
0
; i
0
) {
installationOverlay = (gr_surface*)malloc(installing_frames *
sizeof(gr_surface));
for
(i =
0
; i
<p style=
"margin-top:0px; margin-bottom:0px; padding:5px"
>
</p>
<p style=
"margin-top:0px; margin-bottom:0px; padding:5px"
> </p>
<p style=
"margin-top:0px; margin-bottom:0px; padding:5px"
>
1
、gr_init() 初始化图形设备,分配Pixelflinger库渲染的内存</p>
<p style=
"margin-top:0px; margin-bottom:0px; padding:5px"
>
2
、gr_font_size() 将字体相应的surface长宽赋值给char_width和char_height</p>
3
、LoadBitmap() 将png生成surface, 每一个png图片相应一个surface, 全部surface存放在一个数组中
4
、LoadLocalizedBitmap() 将区域文字所在的图片中的text信息依据当前的locale提取出来,生成相应的surface, 所以
surface也存放在一个数组中
6
、pthread_create(&progress_t, NULL, progress_thread, NULL)
创建一个线程,该线程的任务是一个死循环。在该循环中不停
地检測currentIcon以及progressBarType来决定是不是要更新进度条。
7
、调用RecoveryUI的Init(),初始化输入事件处理。
<p style=
"margin-top:0px; margin-bottom:0px; padding:5px"
> </p>
<pre
class
=
"brush:java;"
>
void
ScreenRecoveryUI::SetLocale(
const
char
* locale) {
if
(locale) {
char
* lang = strdup(locale);
for
(
char
* p = lang; *p; ++p) {
if
(*p ==
'_'
) {
*p =
'\0'
;
break
;
}
}
if
(strcmp(lang,
"ar"
) ==
0
||
strcmp(lang,
"fa"
) ==
0
||
strcmp(lang,
"he"
) ==
0
||
strcmp(lang,
"iw"
) ==
0
||
strcmp(lang,
"ur"
) ==
0
) {
rtl_locale =
true
;
}
free(lang);
}
}
</pre><br> ScreenRecoveryUI类的SetLocale, 该函数依据locale推断所用的字体是否属于阿拉伯语系,阿拉伯语的书写习惯是从右到左,假设是阿拉伯语系的话,就设置一个标志。后面依据这个标志决定从右到左显示文字或进度条。SetLocale的參数locale赋值逻辑是这种,先从command文件里读取, command文件里设置locale的命令如
"--<em>locale</em>=zh_CN“,假设没有传入locale,初始化过程中会尝试从/cache/recovery/last_locale中读取locale, 假设该文件也没有,则locale不会被赋值,就默认用English. <pre class="
brush:java;">
void
ScreenRecoveryUI::SetBackground(Icon icon)
{
pthread_mutex_lock(&updateMutex);
if
(backgroundIcon[icon] != NULL) {
gr_surface bg = backgroundIcon[icon];
gr_surface text = backgroundText[icon];
overlay_offset_x = install_overlay_offset_x + (gr_fb_width() - gr_get_width(bg)) /
2
;
overlay_offset_y = install_overlay_offset_y +
(gr_fb_height() - (gr_get_height(bg) + gr_get_height(text) +
40
)) /
2
;
}
currentIcon = icon;
update_screen_locked();
pthread_mutex_unlock(&updateMutex);
}
</pre> SetBackground函数比較简洁,关键部分在update_screen_locked。以下我们重点分析一下。<p></p><p> update_screen_locked和update_progress_locked是recovery的UI部分的关键函数,update_screen_locked用来更新背景, update_progress_locked用来更新进度条。由于显示的画面会一直在更新,所以这两个函数会在不同的地方被重复调用<br></p><pre
class
=
"brush:java;"
>
void
ScreenRecoveryUI::update_screen_locked()
{
draw_screen_locked();
gr_flip();
}
</pre> update_screen_locked包括两个操作。一是更新screen, 二是切换前后buffer。 <pre
class
=
"brush:java;"
>
void
ScreenRecoveryUI::draw_screen_locked()
{
draw_background_locked(currentIcon);
draw_progress_locked();
if
(show_text) {
SetColor(TEXT_FILL);
gr_fill(
0
,
0
, gr_fb_width(), gr_fb_height());
int
y =
0
;
int
i =
0
;
if
(show_menu) {
SetColor(HEADER);
for
(; i y+
2
&& count
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上进行渲染。
<pre
class
=
"brush:java;"
>
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
;
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) {
if
(pos >
0
) {
gr_blit(progressBarFill, width-pos,
0
, pos, height, dx+width-pos, dy);
}
if
(pos
0
) {
gr_blit(progressBarFill,
0
,
0
, pos, height, dx, dy);
}
if
(pos
draw_progress_locked函数的原理与 update_screen_locked函数类似, 终于是将进度条的surface输出到渲染buffer,
recovery中各个场景的画面,就是由背景、文字、进度条的重叠,不同的是所用的surface 以及surface的坐标。<p></p><p>
recovery main函数中的UI代码基本上已经分析过了。最后一点主菜单的显示,就是通过上面介绍的这些接口将文字图片显示出来。因此就不再多讲。总的来说,recovery的UI显示部分难度不大,应用层调用minui库实现了图形的描绘以及固定大小的文字显示,minui库调用了Pixelflinger库来进行渲染。</p><p>
附上minui部分接口的说明。供參考
</p><pre
class
=
"brush:java;"
>
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);
</pre><div><br></div></pre></pre> 本文转自mfrbuaa博客园博客,原文链接:http://www.cnblogs.com/mfrbuaa/p/5371988.html,如需转载请自行联系原作者