Chameleon

Chameleon Svn Source Tree

Root/tags/2.0/i386/boot2/gui.c

Source at commit 1808 created 12 years 3 months ago.
By blackosx, Revise layout of package installer 'Welcome' file so it looks cleaner. Change the copyright notice to begin from 2009 as seen in the Chameleon 2.0 r431 installer. Should this date be set earlier?
1/*
2 * gui.c
3 *
4 *
5 * Created by Jasmin Fazlic on 18.12.08.
6 * Copyright 2008/09 Jasmin Fazlic All rights reserved.
7 * Copyright 2008/09 iNDi All rights reserved.
8 *
9 */
10
11#include "gui.h"
12#include "appleboot.h"
13#include "vers.h"
14
15#define IMG_REQUIRED -1
16#define THEME_NAME_DEFAULT"Default"
17static const char *theme_name = THEME_NAME_DEFAULT;
18
19#ifdef CONFIG_EMBED_THEME
20#include "art.h"
21#endif
22
23#define LOADPNG(img, alt_img) if (loadThemeImage(#img, alt_img) != 0) { return 1; }
24
25#define VIDEO(x) (bootArgs->Video.v_ ## x)
26
27#define vram VIDEO(baseAddr)
28
29int lasttime = 0; // we need this for animating maybe
30
31
32/*
33 * ATTENTION: the enum and the following array images[] MUST match !!!
34 */
35enum {
36 iBackground = 0,
37 iLogo,
38
39 iDeviceGeneric,
40 iDeviceGeneric_o,
41 iDeviceHFS,
42 iDeviceHFS_o,
43 iDeviceHFSRAID,
44 iDeviceHFSRAID_o,
45 iDeviceEXT3,
46 iDeviceEXT3_o,
47 iDeviceFAT,
48 iDeviceFAT_o,
49 iDeviceFAT16,
50 iDeviceFAT16_o,
51 iDeviceFAT32,
52 iDeviceFAT32_o,
53 iDeviceNTFS,
54 iDeviceNTFS_o,
55 iDeviceCDROM,
56 iDeviceCDROM_o,
57
58 iSelection,
59 iDeviceScrollPrev,
60 iDeviceScrollNext,
61
62 iMenuBoot,
63 iMenuVerbose,
64 iMenuIgnoreCaches,
65 iMenuSingleUser,
66 iMenuMemoryInfo,
67 iMenuVideoInfo,
68 iMenuHelp,
69 iMenuVerboseDisabled,
70 iMenuIgnoreCachesDisabled,
71 iMenuSingleUserDisabled,
72 iMenuSelection,
73
74 iProgressBar,
75 iProgressBarBackground,
76
77 iTextScrollPrev,
78 iTextScrollNext,
79
80 iFontConsole,
81 iFontSmall,
82};
83
84image_t images[] = {
85 {.name = "background", .image = NULL},
86 {.name = "logo", .image = NULL},
87
88 {.name = "device_generic", .image = NULL},
89 {.name = "device_generic_o", .image = NULL},
90 {.name = "device_hfsplus", .image = NULL},
91 {.name = "device_hfsplus_o", .image = NULL},
92 {.name = "device_hfsraid", .image = NULL},
93 {.name = "device_hfsraid_o", .image = NULL},
94 {.name = "device_ext3", .image = NULL},
95 {.name = "device_ext3_o", .image = NULL},
96 {.name = "device_fat", .image = NULL},
97 {.name = "device_fat_o", .image = NULL},
98 {.name = "device_fat16", .image = NULL},
99 {.name = "device_fat16_o", .image = NULL},
100 {.name = "device_fat32", .image = NULL},
101 {.name = "device_fat32_o", .image = NULL},
102 {.name = "device_ntfs", .image = NULL},
103 {.name = "device_ntfs_o", .image = NULL},
104 {.name = "device_cdrom", .image = NULL},
105 {.name = "device_cdrom_o", .image = NULL},
106
107 {.name = "device_selection", .image = NULL},
108 {.name = "device_scroll_prev", .image = NULL},
109 {.name = "device_scroll_next", .image = NULL},
110
111 {.name = "menu_boot", .image = NULL},
112 {.name = "menu_verbose", .image = NULL},
113 {.name = "menu_ignore_caches", .image = NULL},
114 {.name = "menu_single_user", .image = NULL},
115 {.name = "menu_memory_info", .image = NULL},
116 {.name = "menu_video_info", .image = NULL},
117 {.name = "menu_help", .image = NULL},
118 {.name = "menu_verbose_disabled", .image = NULL},
119 {.name = "menu_ignore_caches_disabled", .image = NULL},
120 {.name = "menu_single_user_disabled", .image = NULL},
121 {.name = "menu_selection", .image = NULL},
122
123 {.name = "progress_bar", .image = NULL},
124 {.name = "progress_bar_background", .image = NULL},
125
126 {.name = "text_scroll_prev", .image = NULL},
127 {.name = "text_scroll_next", .image = NULL},
128
129 {.name = "font_console", .image = NULL},
130 {.name = "font_small", .image = NULL},
131};
132
133int imageCnt = 0;
134
135extern intgDeviceCount;
136extern intselectIndex;
137
138extern MenuItem *menuItems;
139
140//char prompt[BOOT_STRING_LEN];
141extern char gBootArgs[BOOT_STRING_LEN];
142
143char prompt_text[] = "boot: ";
144
145menuitem_t infoMenuItems[] =
146{
147{ .text = "Boot" },
148{ .text = "Boot Verbose" },
149{ .text = "Boot Ignore Caches" },
150{ .text = "Boot Single User" },
151{ .text = "Memory Info" },
152{ .text = "Video Info" },
153{ .text = "Help" }
154};
155
156int initFont(font_t *font, image_t *image);
157void colorFont(font_t *font, uint32_t color);
158void makeRoundedCorners(pixmap_t *p);
159
160static int infoMenuSelection = 0;
161static int infoMenuItemsCount = sizeof(infoMenuItems)/sizeof(infoMenuItems[0]);
162
163static bool infoMenuNativeBoot = false;
164
165// here we store the used screen resolution
166static unsigned long screen_params[4] = {DEFAULT_SCREEN_WIDTH, DEFAULT_SCREEN_HEIGHT, 32, 0};
167
168static int getImageIndexByName(const char *name)
169{
170 int i;
171for (i = 0; i < sizeof(images) / sizeof(images[0]); i++)
172{
173 if (strcmp(name, images[i].name) == 0)
174 return i; // found the name
175}
176return -1;
177}
178
179#ifdef CONFIG_EMBED_THEME
180static int getEmbeddedImageIndexByName(const char *name)
181{
182int upperLimit = sizeof(embeddedImages) / sizeof(embeddedImages[0]) - 1;
183int lowerLimit = 0;
184int compareIndex = (upperLimit - lowerLimit) >> 1; // Midpoint
185int result;
186
187// NOTE: This algorithm assumes that the embedded images are sorted.
188// This is currently done using the make file. If the array is
189// generated manualy, this *will* fail to work properly.
190while((result = strcmp(name, embeddedImages[compareIndex].name)) != 0)
191{
192if (result > 0)// We need to search a HIGHER index
193{
194if (compareIndex != lowerLimit)
195{
196lowerLimit = compareIndex;
197}
198else
199{
200return -1;
201}
202compareIndex = (upperLimit + lowerLimit + 1) >> 1;// Midpoint, round up
203}
204else // We Need to search a LOWER index
205{
206if (compareIndex != upperLimit)
207{
208upperLimit = compareIndex;
209}
210else
211{
212return -1;
213}
214compareIndex = (upperLimit + lowerLimit) >> 1;// Midpoint, round down
215}
216}
217return compareIndex;
218}
219#endif
220
221static int loadThemeImage(const char *image, int alt_image)
222{
223chardirspec[256];
224int i;
225#ifdef CONFIG_EMBED_THEME
226int e;
227#endif
228uint16_twidth;
229uint16_theight;
230uint8_t*imagedata;
231
232if ((strlen(image) + strlen(theme_name) + 20 ) > sizeof(dirspec)) {
233return 1;
234}
235
236 if ((i = getImageIndexByName(image)) >= 0)
237 {
238 if (images[i].image == NULL) {
239 images[i].image = malloc(sizeof(pixmap_t));
240 }
241 sprintf(dirspec, "/Extra/Themes/%s/%s.png", theme_name, image);
242 width = 0;
243 height = 0;
244 imagedata = NULL;
245 if ((loadPngImage(dirspec, &width, &height, &imagedata)) == 0)
246 {
247 images[i].image->width = width;
248 images[i].image->height = height;
249 images[i].image->pixels = (pixel_t *)imagedata;
250 flipRB(images[i].image);
251 return 0;
252 }
253#ifdef CONFIG_EMBED_THEME
254 else if ((e = getEmbeddedImageIndexByName(image)) >= 0)
255 {
256 unsigned char *embed_data;
257 unsigned int embed_size;
258 embed_data = embeddedImages[e].pngdata;
259 embed_size = *embeddedImages[e].length;
260
261 if (loadEmbeddedPngImage(embed_data, embed_size, &width, &height, &imagedata) == 0)
262 {
263 images[i].image->width = width;
264 images[i].image->height = height;
265 images[i].image->pixels = (pixel_t *)imagedata;
266 flipRB(images[i].image);
267 return 0;
268 }
269
270 return 0;
271 }
272#endif
273 else if (alt_image != IMG_REQUIRED && images[alt_image].image->pixels != NULL)
274 {
275 // Using the passed alternate image for non-mandatory images.
276 // We don't clone the already existing pixmap, but using its properties instead!
277 images[i].image->width = images[alt_image].image->width;
278 images[i].image->height = images[alt_image].image->height;
279 images[i].image->pixels = images[alt_image].image->pixels;
280 return 0;
281 }
282 else
283 {
284#ifndef CONFIG_EMBED_THEME
285 printf("ERROR: GUI: could not open '%s/%s.png'!\n", theme_name, image);
286sleep(2);
287#endif
288 return 1;
289 }
290 }
291return 1;
292}
293
294static int loadGraphics(void)
295{
296LOADPNG(background, IMG_REQUIRED);
297LOADPNG(logo, IMG_REQUIRED);
298
299LOADPNG(device_generic, IMG_REQUIRED);
300LOADPNG(device_generic_o, iDeviceGeneric);
301LOADPNG(device_hfsplus, iDeviceGeneric);
302LOADPNG(device_hfsplus_o, iDeviceHFS);
303LOADPNG(device_hfsraid, iDeviceGeneric);
304LOADPNG(device_hfsraid_o, iDeviceHFSRAID);
305LOADPNG(device_ext3, iDeviceGeneric);
306LOADPNG(device_ext3_o, iDeviceEXT3);
307LOADPNG(device_fat, iDeviceGeneric);
308LOADPNG(device_fat_o, iDeviceFAT);
309LOADPNG(device_fat16, iDeviceFAT);
310LOADPNG(device_fat16_o, iDeviceFAT_o);
311LOADPNG(device_fat32, iDeviceFAT);
312LOADPNG(device_fat32_o, iDeviceFAT_o);
313LOADPNG(device_ntfs, iDeviceGeneric);
314LOADPNG(device_ntfs_o, iDeviceNTFS);
315LOADPNG(device_cdrom, iDeviceGeneric);
316LOADPNG(device_cdrom_o, iDeviceCDROM);
317
318LOADPNG(device_selection, IMG_REQUIRED);
319LOADPNG(device_scroll_prev, IMG_REQUIRED);
320LOADPNG(device_scroll_next, IMG_REQUIRED);
321
322LOADPNG(menu_boot, IMG_REQUIRED);
323LOADPNG(menu_verbose, IMG_REQUIRED);
324LOADPNG(menu_ignore_caches, IMG_REQUIRED);
325LOADPNG(menu_single_user, IMG_REQUIRED);
326LOADPNG(menu_memory_info, IMG_REQUIRED);
327LOADPNG(menu_video_info, IMG_REQUIRED);
328LOADPNG(menu_help, IMG_REQUIRED);
329LOADPNG(menu_verbose_disabled, IMG_REQUIRED);
330LOADPNG(menu_ignore_caches_disabled, IMG_REQUIRED);
331LOADPNG(menu_single_user_disabled, IMG_REQUIRED);
332LOADPNG(menu_selection, IMG_REQUIRED);
333
334LOADPNG(progress_bar, IMG_REQUIRED);
335LOADPNG(progress_bar_background, IMG_REQUIRED);
336
337LOADPNG(text_scroll_prev, IMG_REQUIRED);
338LOADPNG(text_scroll_next, IMG_REQUIRED);
339
340LOADPNG(font_console, IMG_REQUIRED);
341LOADPNG(font_small, IMG_REQUIRED);
342
343initFont( &font_console, &images[iFontConsole]);
344initFont( &font_small, &images[iFontSmall]);
345
346return 0;
347}
348
349pixmap_t *getCroppedPixmapAtPosition( pixmap_t *from, position_t pos, uint16_t width, uint16_t height )
350{
351
352pixmap_t *cropped = malloc( sizeof( pixmap_t ) );
353if( !cropped )
354return 0;
355cropped->pixels = malloc( width * height * 4 );
356if ( !cropped->pixels )
357return 0;
358
359cropped->width = width;
360cropped->height = height;
361
362int destx = 0, desty = 0;
363int srcx = pos.x, srcy = pos.y;
364
365for( ; desty < height; desty++, srcy++)
366{
367for( destx = 0, srcx = pos.x; destx < width; destx++, srcx++ )
368{
369pixel( cropped, destx, desty ).value = pixel( from, srcx, srcy ).value;
370}
371}
372return cropped;
373}
374
375int createBackBuffer( window_t *window )
376{
377gui.backbuffer = malloc(sizeof(pixmap_t));
378if(!gui.backbuffer)
379return 1;
380
381gui.backbuffer->pixels = malloc( window->width * window->height * 4 );
382if(!gui.backbuffer->pixels)
383{
384free(gui.backbuffer);
385gui.backbuffer = 0;
386return 1;
387}
388
389gui.backbuffer->width = gui.screen.width;
390gui.backbuffer->height = gui.screen.height;
391
392return 0;
393}
394
395int createWindowBuffer( window_t *window )
396{
397window->pixmap = malloc(sizeof(pixmap_t));
398if(!window->pixmap)
399return 1;
400
401window->pixmap->pixels = malloc( window->width * window->height * 4 );
402if(!window->pixmap->pixels)
403{
404free(window->pixmap);
405window->pixmap = 0;
406return 1;
407}
408
409window->pixmap->width = window->width;
410window->pixmap->height = window->height;
411
412return 0;
413}
414
415int freeWindowBuffer( window_t *window )
416{
417if (window->pixmap && window->pixmap->pixels)
418 {
419free(window->pixmap->pixels);
420free(window->pixmap);
421return 0;
422}
423
424return 1;
425}
426
427void fillPixmapWithColor(pixmap_t *pm, uint32_t color)
428{
429int x,y;
430
431// fill with given color AARRGGBB
432for( x=0; x < pm->width; x++ )
433for( y=0; y< pm->height; y++)
434pixel(pm,x,y).value = color;
435}
436
437void drawBackground()
438{
439// reset text cursor
440gui.screen.cursor.x = gui.screen.hborder;
441gui.screen.cursor.y = gui.screen.vborder;
442
443fillPixmapWithColor( gui.screen.pixmap, gui.screen.bgcolor);
444
445// draw background.png into background buffer
446blend( images[iBackground].image, gui.screen.pixmap, gui.background.pos );
447
448// draw logo.png into background buffer
449if (gui.logo.draw)
450{
451 blend( images[iLogo].image, gui.screen.pixmap, gui.logo.pos);
452}
453
454memcpy( gui.backbuffer->pixels, gui.screen.pixmap->pixels, gui.backbuffer->width * gui.backbuffer->height * 4 );
455}
456
457void setupDeviceList(config_file_t *theme)
458{
459unsigned int pixel;
460intalpha;// transparency level 0 (obligue) - 255 (transparent)
461uint32_t color;// color value formatted RRGGBB
462int val, len;
463const char *string;
464
465if(getIntForKey("devices_max_visible", &val, theme ))
466gui.maxdevices = MIN( val, gDeviceCount );
467
468if(getIntForKey("devices_iconspacing", &val, theme ))
469gui.devicelist.iconspacing = val;
470
471// check layout for horizontal or vertical
472gui.layout = HorizontalLayout;
473if(getValueForKey( "devices_layout", &string, &len, theme)) {
474if (!strcmp (string, "vertical")) {
475gui.layout = VerticalLayout;
476}
477}
478
479switch (gui.layout) {
480case VerticalLayout:
481gui.devicelist.height = ((images[iSelection].image->height + font_console.chars[0]->height + gui.devicelist.iconspacing) * MIN(gui.maxdevices, gDeviceCount) + (images[iDeviceScrollPrev].image->height + images[iDeviceScrollNext].image->height) + gui.devicelist.iconspacing);
482gui.devicelist.width = (images[iSelection].image->width + gui.devicelist.iconspacing);
483
484if(getDimensionForKey("devices_pos_x", &pixel, theme, gui.screen.width , images[iSelection].image->width ) )
485gui.devicelist.pos.x = pixel;
486
487if(getDimensionForKey("devices_pos_y", &pixel, theme, gui.screen.height , gui.devicelist.height ) )
488gui.devicelist.pos.y = pixel;
489break;
490
491case HorizontalLayout:
492default:
493gui.devicelist.width = ((images[iSelection].image->width + gui.devicelist.iconspacing) * MIN(gui.maxdevices, gDeviceCount) + (images[iDeviceScrollPrev].image->width + images[iDeviceScrollNext].image->width) + gui.devicelist.iconspacing);
494gui.devicelist.height = (images[iSelection].image->height + font_console.chars[0]->height + gui.devicelist.iconspacing);
495
496if(getDimensionForKey("devices_pos_x", &pixel, theme, gui.screen.width , gui.devicelist.width ) )
497gui.devicelist.pos.x = pixel;
498else
499gui.devicelist.pos.x = ( gui.screen.width - gui.devicelist.width ) / 2;
500
501if(getDimensionForKey("devices_pos_y", &pixel, theme, gui.screen.height , images[iSelection].image->height ) )
502gui.devicelist.pos.y = pixel;
503else
504gui.devicelist.pos.y = ( gui.screen.height - gui.devicelist.height ) / 2;
505break;
506}
507
508if(getColorForKey("devices_bgcolor", &color, theme))
509gui.devicelist.bgcolor = (color & 0x00FFFFFF);
510
511if(getIntForKey("devices_transparency", &alpha, theme))
512gui.devicelist.bgcolor = gui.devicelist.bgcolor | (( 255 - ( alpha & 0xFF) ) << 24);
513
514if (gui.devicelist.pixmap)
515{
516 freeWindowBuffer(&gui.devicelist);
517 createWindowBuffer(&gui.devicelist);
518 }
519}
520
521void loadThemeValues(config_file_t *theme)
522{
523unsigned int screen_width = gui.screen.width;
524unsigned int screen_height = gui.screen.height;
525unsigned int pixel;
526intalpha;// transparency level 0 (obligue) - 255 (transparent)
527uint32_t color;// color value formatted RRGGBB
528int val;
529
530/*
531 * Parse screen parameters
532 */
533if(getColorForKey("screen_bgcolor", &color, theme ))
534gui.screen.bgcolor = (color & 0x00FFFFFF);
535
536if(getIntForKey("screen_textmargin_h", &val, theme))
537gui.screen.hborder = MIN( gui.screen.width , val );
538
539if(getIntForKey("screen_textmargin_v", &val, theme))
540gui.screen.vborder = MIN( gui.screen.height , val );
541
542/*
543 * Parse background parameters
544 */
545if(getDimensionForKey("background_pos_x", &pixel, theme, screen_width , images[iBackground].image->width ) )
546gui.background.pos.x = pixel;
547
548if(getDimensionForKey("background_pos_y", &pixel, theme, screen_height , images[iBackground].image->height ) )
549gui.background.pos.y = pixel;
550
551/*
552 * Parse logo parameters
553 */
554if(getDimensionForKey("logo_pos_x", &pixel, theme, screen_width , images[iLogo].image->width ) )
555gui.logo.pos.x = pixel;
556
557if(getDimensionForKey("logo_pos_y", &pixel, theme, screen_height , images[iLogo].image->height ) )
558gui.logo.pos.y = pixel;
559
560/*
561 * Parse progress bar parameters
562 */
563if(getDimensionForKey("progressbar_pos_x", &pixel, theme, screen_width , 0 ) )
564gui.progressbar.pos.x = pixel;
565
566if(getDimensionForKey("progressbar_pos_y", &pixel, theme, screen_height , 0 ) )
567gui.progressbar.pos.y = pixel;
568
569/*
570 * Parse countdown text parameters
571 */
572if(getDimensionForKey("countdown_pos_x", &pixel, theme, screen_width , 0 ) )
573gui.countdown.pos.x = pixel;
574
575if(getDimensionForKey("countdown_pos_y", &pixel, theme, screen_height , 0 ) )
576gui.countdown.pos.y = pixel;
577
578 /*
579 * Parse devicelist parameters
580 */
581setupDeviceList(theme);
582
583/*
584 * Parse infobox parameters
585 */
586if(getIntForKey("infobox_width", &val, theme))
587gui.infobox.width = MIN( screen_width , val );
588
589if(getIntForKey("infobox_height", &val, theme))
590gui.infobox.height = MIN( screen_height , val );
591
592if(getDimensionForKey("infobox_pos_x", &pixel, theme, screen_width , gui.infobox.width ) )
593gui.infobox.pos.x = pixel;
594
595if(getDimensionForKey("infobox_pos_y", &pixel, theme, screen_height , gui.infobox.height ) )
596gui.infobox.pos.y = pixel;
597
598if(getIntForKey("infobox_textmargin_h", &val, theme))
599gui.infobox.hborder = MIN( gui.infobox.width , val );
600
601if(getIntForKey("infobox_textmargin_v", &val, theme))
602gui.infobox.vborder = MIN( gui.infobox.height , val );
603
604if(getColorForKey("infobox_bgcolor", &color, theme))
605gui.infobox.bgcolor = (color & 0x00FFFFFF);
606
607if(getIntForKey("infobox_transparency", &alpha, theme))
608gui.infobox.bgcolor = gui.infobox.bgcolor | (( 255 - ( alpha & 0xFF) ) << 24);
609
610/*
611 * Parse menu parameters
612 */
613if(getDimensionForKey("menu_width", &pixel, theme, gui.screen.width , 0 ) )
614gui.menu.width = pixel;
615else
616gui.menu.width = images[iMenuSelection].image->width;
617
618if(getDimensionForKey("menu_height", &pixel, theme, gui.screen.height , 0 ) )
619gui.menu.height = pixel;
620else
621gui.menu.height = (infoMenuItemsCount) * images[iMenuSelection].image->height;
622
623if(getDimensionForKey("menu_pos_x", &pixel, theme, screen_width , gui.menu.width ) )
624gui.menu.pos.x = pixel;
625
626if(getDimensionForKey("menu_pos_y", &pixel, theme, screen_height , gui.menu.height ) )
627gui.menu.pos.y = pixel;
628
629if(getIntForKey("menu_textmargin_h", &val, theme))
630gui.menu.hborder = MIN( gui.menu.width , val );
631
632if(getIntForKey("menu_textmargin_v", &val, theme))
633gui.menu.vborder = MIN( gui.menu.height , val );
634
635if(getColorForKey("menu_bgcolor", &color, theme))
636gui.menu.bgcolor = (color & 0x00FFFFFF);
637
638if(getIntForKey("menu_transparency", &alpha, theme))
639gui.menu.bgcolor = gui.menu.bgcolor | (( 255 - ( alpha & 0xFF) ) << 24);
640
641/*
642 * Parse bootprompt parameters
643 */
644if(getDimensionForKey("bootprompt_width", &pixel, theme, screen_width , 0 ) )
645gui.bootprompt.width = pixel;
646
647if(getIntForKey("bootprompt_height", &val, theme))
648gui.bootprompt.height = MIN( screen_height , val );
649
650if(getDimensionForKey("bootprompt_pos_x", &pixel, theme, screen_width , gui.bootprompt.width ) )
651gui.bootprompt.pos.x = pixel;
652
653if(getDimensionForKey("bootprompt_pos_y", &pixel, theme, screen_height , gui.bootprompt.height ) )
654gui.bootprompt.pos.y = pixel;
655
656if(getIntForKey("bootprompt_textmargin_h", &val, theme))
657gui.bootprompt.hborder = MIN( gui.bootprompt.width , val );
658
659if(getIntForKey("bootprompt_textmargin_v", &val, theme))
660gui.bootprompt.vborder = MIN( gui.bootprompt.height , val );
661
662if(getColorForKey("bootprompt_bgcolor", &color, theme))
663gui.bootprompt.bgcolor = (color & 0x00FFFFFF);
664
665if(getIntForKey("bootprompt_transparency", &alpha, theme))
666gui.bootprompt.bgcolor = gui.bootprompt.bgcolor | (( 255 - ( alpha & 0xFF) ) << 24);
667
668if(getColorForKey("font_small_color", &color, theme))
669gui.screen.font_small_color = (color & 0x00FFFFFF);
670
671if(getColorForKey("font_console_color", &color, theme))
672gui.screen.font_console_color = (color & 0x00FFFFFF);
673}
674
675int initGUI(void)
676{
677intval;
678intlen;
679chardirspec[256];
680
681getValueForKey( "Theme", &theme_name, &len, &bootInfo->chameleonConfig );
682if ((strlen(theme_name) + 27) > sizeof(dirspec)) {
683return 1;
684}
685sprintf(dirspec, "/Extra/Themes/%s/theme.plist", theme_name);
686if (loadConfigFile(dirspec, &bootInfo->themeConfig) != 0) {
687#ifdef CONFIG_EMBED_THEME
688 config_file_t*config;
689
690 config = &bootInfo->themeConfig;
691 if (ParseXMLFile((char *)__theme_plist, &config->dictionary) != 0) {
692 return 1;
693 }
694#else
695return 1;
696#endif
697}
698// parse display size parameters
699if (getIntForKey("screen_width", &val, &bootInfo->themeConfig) && val > 0) {
700screen_params[0] = val;
701}
702if (getIntForKey("screen_height", &val, &bootInfo->themeConfig) && val > 0) {
703screen_params[1] = val;
704}
705
706// Initalizing GUI strucutre.
707bzero(&gui, sizeof(gui_t));
708
709// find best matching vesa mode for our requested width & height
710getGraphicModeParams(screen_params);
711
712// set our screen structure with the mode width & height
713gui.screen.width = screen_params[0];
714gui.screen.height = screen_params[1];
715
716// load graphics otherwise fail and return
717if (loadGraphics() == 0) {
718loadThemeValues(&bootInfo->themeConfig);
719colorFont(&font_small, gui.screen.font_small_color);
720colorFont(&font_console, gui.screen.font_console_color);
721
722// create the screen & window buffers
723if (createBackBuffer(&gui.screen) == 0) {
724if (createWindowBuffer(&gui.screen) == 0) {
725if (createWindowBuffer(&gui.devicelist) == 0) {
726if (createWindowBuffer(&gui.bootprompt) == 0) {
727if (createWindowBuffer(&gui.infobox) == 0) {
728if (createWindowBuffer(&gui.menu) == 0) {
729 gui.logo.draw = true;
730drawBackground();
731// lets copy the screen into the back buffer
732memcpy( gui.backbuffer->pixels, gui.screen.pixmap->pixels, gui.backbuffer->width * gui.backbuffer->height * 4 );
733setVideoMode( GRAPHICS_MODE, 0 );
734gui.initialised = true;
735return 0;
736}
737}
738}
739}
740}
741}
742}
743return 1;
744}
745
746void drawDeviceIcon(BVRef device, pixmap_t *buffer, position_t p, bool isSelected)
747{
748int devicetype;
749
750if( diskIsCDROM(device) )
751devicetype = iDeviceCDROM;// Use CDROM icon
752else
753{
754switch (device->part_type)
755{
756case kPartitionTypeHFS:
757
758// Use HFS or HFSRAID icon depending on bvr flags.
759devicetype = (device->flags & kBVFlagBooter) ? iDeviceHFSRAID : iDeviceHFS;
760break;
761
762case kPartitionTypeHPFS:
763devicetype = iDeviceNTFS;// Use HPFS / NTFS icon
764break;
765
766case kPartitionTypeFAT16:
767devicetype = iDeviceFAT16;// Use FAT16 icon
768break;
769
770case kPartitionTypeFAT32:
771devicetype = iDeviceFAT32;// Use FAT32 icon
772break;
773
774case kPartitionTypeEXT3:
775devicetype = iDeviceEXT3;// Use EXT2/3 icon
776break;
777
778default:
779devicetype = iDeviceGeneric;// Use Generic icon
780break;
781}
782}
783
784// Draw the selection image and use the next (device_*_o) image for the selected item.
785 if (isSelected)
786{
787blend(images[iSelection].image, buffer, centeredAt(images[iSelection].image, p));
788devicetype++;
789}
790
791// draw icon
792blend( images[devicetype].image, buffer, centeredAt( images[devicetype].image, p ));
793
794p.y += (images[iSelection].image->height / 2) + font_console.chars[0]->height;
795
796// draw volume label
797drawStrCenteredAt( device->label, &font_small, buffer, p);
798
799}
800
801void drawDeviceList (int start, int end, int selection)
802{
803inti;
804boolshoWinfo = true; //Azi:showinfo
805extern bool showBootBanner; //
806position_tp, p_prev, p_next;
807
808//uint8_tmaxDevices = MIN( gui.maxdevices, menucount );
809
810fillPixmapWithColor( gui.devicelist.pixmap, gui.devicelist.bgcolor);
811
812makeRoundedCorners( gui.devicelist.pixmap);
813
814switch (gui.layout)
815{
816
817case VerticalLayout:
818p.x = (gui.devicelist.width /2);
819p.y = ( ( images[iSelection].image->height / 2 ) + images[iDeviceScrollPrev].image->height + gui.devicelist.iconspacing );
820
821// place scroll indicators at top & bottom edges
822p_prev = pos ( gui.devicelist.width / 2 , gui.devicelist.iconspacing );
823p_next = pos ( p_prev.x, gui.devicelist.height - gui.devicelist.iconspacing );
824
825break;
826
827default:// use Horizontal layout as the default
828
829case HorizontalLayout:
830p.x = (gui.devicelist.width - ( gui.devicelist.width / gui.maxdevices ) * gui.maxdevices ) / 2 + ( images[iSelection].image->width / 2) + images[iDeviceScrollPrev].image->width + gui.devicelist.iconspacing;
831p.y = ((gui.devicelist.height - font_console.chars[0]->height ) - images[iSelection].image->height) / 2 + ( images[iSelection].image->height / 2 );
832
833// place scroll indicators at left & right edges
834p_prev = pos ( images[iDeviceScrollPrev].image->width / 2 + gui.devicelist.iconspacing / 2, gui.devicelist.height / 2 );
835p_next = pos ( gui.devicelist.width - ( images[iDeviceScrollNext].image->width / 2 + gui.devicelist.iconspacing / 2), gui.devicelist.height / 2 );
836
837break;
838
839}
840
841// draw visible device icons
842for (i = 0; i < gui.maxdevices; i++)
843{
844BVRef param = menuItems[start + i].param;
845
846 bool isSelected = ((start + i) == selection) ? true : false;
847if (isSelected)
848{
849 if (param->flags & kBVFlagNativeBoot)
850 {
851 infoMenuNativeBoot = true;
852 }
853 else
854 {
855 infoMenuNativeBoot = false;
856 if(infoMenuSelection >= INFOMENU_NATIVEBOOT_START && infoMenuSelection <= INFOMENU_NATIVEBOOT_END)
857 infoMenuSelection = 0;
858 }
859
860if (gui.menu.draw)
861drawInfoMenuItems();
862
863getBoolForKey(kShowInfoKey, &shoWinfo, &bootInfo->chameleonConfig);
864
865if (shoWinfo && showBootBanner) // no boot banner, no showinfo.
866{
867// keep formatted with spaces instead of tabs
868gui.debug.cursor = pos( 10, 100);
869dprintf( &gui.screen, "label: %s\n", param->label );
870dprintf( &gui.screen, "biosdev: 0x%x\n", param->biosdev );
871dprintf( &gui.screen, "type: 0x%x\n", param->type );
872dprintf( &gui.screen, "flags: 0x%x\n", param->flags );
873dprintf( &gui.screen, "part_no: %d\n", param->part_no );
874dprintf( &gui.screen, "part_boff: 0x%x\n", param->part_boff );
875dprintf( &gui.screen, "part_type: 0x%x\n", param->part_type );
876dprintf( &gui.screen, "bps: 0x%x\n", param->bps );
877dprintf( &gui.screen, "name: %s\n", param->name );
878dprintf( &gui.screen, "type_name: %s\n", param->type_name );
879dprintf( &gui.screen, "modtime: %d\n", param->modTime );
880dprintf( &gui.screen, "width: %d\n", gui.screen.width );
881dprintf( &gui.screen, "height: %d\n", gui.screen.height );
882//dprintf( &gui.screen, "attr: 0x%x\n", gui.screen.attr ); //Azi: reminder
883//dprintf( &gui.screen, "mm: %d\n", gui.screen.mm );
884}
885}
886
887drawDeviceIcon( param, gui.devicelist.pixmap, p, isSelected);
888
889if (gui.layout == HorizontalLayout)
890{
891p.x += images[iSelection].image->width + gui.devicelist.iconspacing;
892}
893if (gui.layout == VerticalLayout)
894{
895p.y += ( images[iSelection].image->height + font_console.chars[0]->height + gui.devicelist.iconspacing );
896}
897}
898
899// draw prev indicator
900if (start)
901blend( images[iDeviceScrollPrev].image, gui.devicelist.pixmap, centeredAt( images[iDeviceScrollPrev].image, p_prev ) );
902
903// draw next indicator
904if ( end < gDeviceCount - 1 )
905blend( images[iDeviceScrollNext].image, gui.devicelist.pixmap, centeredAt( images[iDeviceScrollNext].image, p_next ) );
906
907gui.redraw = true;
908
909updateVRAM();
910
911}
912
913void clearGraphicBootPrompt()
914{
915// clear text buffer
916//prompt[0] = '\0';
917//prompt_pos=0;
918
919
920if(gui.bootprompt.draw == true )
921{
922gui.bootprompt.draw = false;
923gui.redraw = true;
924// this causes extra frames to be drawn
925//updateVRAM();
926}
927
928return;
929}
930
931void updateGraphicBootPrompt()
932{
933fillPixmapWithColor( gui.bootprompt.pixmap, gui.bootprompt.bgcolor);
934
935makeRoundedCorners( gui.bootprompt.pixmap);
936
937position_t p_text = pos( gui.bootprompt.hborder , ( ( gui.bootprompt.height - font_console.chars[0]->height) ) / 2 );
938
939// print the boot prompt text
940drawStr(prompt_text, &font_console, gui.bootprompt.pixmap, p_text);
941
942// get the position of the end of the boot prompt text to display user input
943position_t p_prompt = pos( p_text.x + ( ( strlen(prompt_text) ) * font_console.chars[0]->width ), p_text.y );
944
945drawStr( gBootArgs, &font_console, gui.bootprompt.pixmap, p_prompt);
946
947gui.menu.draw = false;
948gui.bootprompt.draw = true;
949gui.redraw = true;
950
951updateVRAM();
952
953return;
954}
955
956inline
957void vramwrite (void *data, int width, int height)
958{
959if (VIDEO (depth) == 32 && VIDEO (rowBytes) == gui.backbuffer->width * 4)
960memcpy((uint8_t *)vram, gui.backbuffer->pixels, VIDEO (rowBytes)*VIDEO (height));
961else
962{
963uint32_t r, g, b;
964int i, j;
965for (i = 0; i < VIDEO (height); i++)
966for (j = 0; j < VIDEO (width); j++)
967{
968b = ((uint8_t *) data)[4*i*width + 4*j];
969g = ((uint8_t *) data)[4*i*width + 4*j + 1];
970r = ((uint8_t *) data)[4*i*width + 4*j + 2];
971switch (VIDEO (depth))
972{
973case 32:
974*(uint32_t *)(((uint8_t *)vram)+i*VIDEO (rowBytes) + j*4) = (b&0xff) | ((g&0xff)<<8) | ((r&0xff)<<16);
975break;
976case 24:
977*(uint32_t *)(((uint8_t *)vram)+i*VIDEO (rowBytes) + j*3) = ((*(uint32_t *)(((uint8_t *)vram)+i*VIDEO (rowBytes) + j*3))&0xff000000)
978| (b&0xff) | ((g&0xff)<<8) | ((r&0xff)<<16);
979break;
980case 16:
981// Somehow 16-bit is always 15-bits really
982//*(uint16_t *)(((uint8_t *)vram)+i*VIDEO (rowBytes) + j*2) = ((b&0xf8)>>3) | ((g&0xfc)<<3) | ((r&0xf8)<<8);
983//break;
984case 15:
985*(uint16_t *)(((uint8_t *)vram)+i*VIDEO (rowBytes) + j*2) = ((b&0xf8)>>3) | ((g&0xf8)<<2) | ((r&0xf8)<<7);
986break;
987}
988}
989}
990}
991
992void updateVRAM()
993{
994if (gui.redraw)
995{
996if (gui.devicelist.draw)
997blend( gui.devicelist.pixmap, gui.backbuffer, gui.devicelist.pos );
998
999if (gui.bootprompt.draw)
1000blend( gui.bootprompt.pixmap, gui.backbuffer, gui.bootprompt.pos );
1001
1002if (gui.menu.draw)
1003blend( gui.menu.pixmap, gui.backbuffer, gui.menu.pos );
1004
1005if (gui.infobox.draw)
1006blend( gui.infobox.pixmap, gui.backbuffer, gui.infobox.pos );
1007}
1008
1009vramwrite ( gui.backbuffer->pixels, gui.backbuffer->width, gui.backbuffer->height );
1010
1011if (gui.redraw)
1012{
1013memcpy( gui.backbuffer->pixels, gui.screen.pixmap->pixels, gui.backbuffer->width * gui.backbuffer->height * 4 );
1014gui.redraw = false;
1015}
1016}
1017
1018struct putc_info //Azi: exists on console.c & printf.c
1019{
1020 char * str;
1021 char * last_str;
1022};
1023
1024static int
1025sputc(int c, struct putc_info * pi) //Azi: same as above
1026{
1027 if (pi->last_str)
1028 if (pi->str == pi->last_str) {
1029 *(pi->str) = '\0';
1030 return 0;
1031 }
1032 *(pi->str)++ = c;
1033 return c;
1034}
1035
1036int gprintf( window_t * window, const char * fmt, ...)
1037{
1038char *formattedtext;
1039
1040va_list ap;
1041
1042struct putc_info pi;
1043
1044if ((formattedtext = malloc(1024)) != NULL) {
1045// format the text
1046va_start(ap, fmt);
1047pi.str = formattedtext;
1048pi.last_str = 0;
1049prf(fmt, ap, sputc, &pi);
1050*pi.str = '\0';
1051va_end(ap);
1052
1053position_torigin, cursor, bounds;
1054
1055int i;
1056int character;
1057
1058origin.x = MAX( window->cursor.x, window->hborder );
1059origin.y = MAX( window->cursor.y, window->vborder );
1060
1061bounds.x = ( window->width - window->hborder );
1062bounds.y = ( window->height - window->vborder );
1063
1064cursor = origin;
1065
1066font_t *font = &font_console;
1067
1068for( i=0; i< strlen(formattedtext); i++ )
1069{
1070character = formattedtext[i];
1071
1072character -= 32;
1073
1074// newline ?
1075if( formattedtext[i] == '\n' )
1076{
1077cursor.x = window->hborder;
1078cursor.y += font->height;
1079
1080if ( cursor.y > bounds.y )
1081cursor.y = origin.y;
1082
1083continue;
1084}
1085
1086// tab ?
1087if( formattedtext[i] == '\t' )
1088cursor.x += ( font->chars[0]->width * 5 );
1089
1090// draw the character
1091if( font->chars[character])
1092blend(font->chars[character], window->pixmap, cursor);
1093
1094cursor.x += font->chars[character]->width;
1095
1096// check x pos and do newline
1097if ( cursor.x > bounds.x )
1098{
1099cursor.x = origin.x;
1100cursor.y += font->height;
1101}
1102
1103// check y pos and reset to origin.y
1104if ( cursor.y > bounds.y )
1105cursor.y = origin.y;
1106}
1107
1108// update cursor postition
1109window->cursor = cursor;
1110
1111free(formattedtext);
1112
1113return 0;
1114
1115}
1116return 1;
1117}
1118
1119int dprintf( window_t * window, const char * fmt, ...)
1120{
1121char *formattedtext;
1122
1123va_list ap;
1124
1125//window = &gui.debug;
1126
1127struct putc_info pi;
1128
1129if ((formattedtext = malloc(1024)) != NULL) {
1130// format the text
1131va_start(ap, fmt);
1132pi.str = formattedtext;
1133pi.last_str = 0;
1134prf(fmt, ap, sputc, &pi);
1135*pi.str = '\0';
1136va_end(ap);
1137
1138position_torigin, cursor, bounds;
1139
1140int i;
1141int character;
1142
1143origin.x = MAX( gui.debug.cursor.x, window->hborder );
1144origin.y = MAX( gui.debug.cursor.y, window->vborder );
1145
1146bounds.x = ( window->width - window->hborder );
1147bounds.y = ( window->height - window->vborder );
1148
1149cursor = origin;
1150
1151font_t *font = &font_console;
1152
1153for( i=0; i< strlen(formattedtext); i++ )
1154{
1155character = formattedtext[i];
1156
1157character -= 32;
1158
1159// newline ?
1160if( formattedtext[i] == '\n' )
1161{
1162cursor.x = window->hborder;
1163cursor.y += font->height;
1164
1165if ( cursor.y > bounds.y )
1166cursor.y = origin.y;
1167
1168continue;
1169}
1170
1171// tab ?
1172if( formattedtext[i] == '\t' )
1173cursor.x += ( font->chars[0]->width * 5 );
1174
1175// draw the character
1176if( font->chars[character])
1177blend(font->chars[character], gui.backbuffer, cursor);
1178
1179cursor.x += font->chars[character]->width;
1180
1181// check x pos and do newline
1182if ( cursor.x > bounds.x )
1183{
1184cursor.x = origin.x;
1185cursor.y += font->height;
1186}
1187
1188// check y pos and reset to origin.y
1189if ( cursor.y > bounds.y )
1190cursor.y = origin.y;
1191}
1192
1193// update cursor postition
1194gui.debug.cursor = cursor;
1195
1196free(formattedtext);
1197
1198return 0;
1199
1200}
1201return 1;
1202}
1203
1204int vprf(const char * fmt, va_list ap)
1205{
1206int i;
1207int character;
1208
1209char *formattedtext;
1210window_t *window = &gui.screen;
1211struct putc_info pi;
1212
1213position_torigin, cursor, bounds;
1214font_t *font = &font_console;
1215
1216if ((formattedtext = malloc(1024)) != NULL) {
1217// format the text
1218pi.str = formattedtext;
1219pi.last_str = 0;
1220prf(fmt, ap, sputc, &pi);
1221*pi.str = '\0';
1222
1223origin.x = MAX( window->cursor.x, window->hborder );
1224origin.y = MAX( window->cursor.y, window->vborder );
1225bounds.x = ( window->width - ( window->hborder * 2 ) );
1226bounds.y = ( window->height - ( window->vborder * 2 ) );
1227cursor = origin;
1228
1229for( i=0; i< strlen(formattedtext); i++ )
1230{
1231character = formattedtext[i];
1232character -= 32;
1233
1234// newline ?
1235if( formattedtext[i] == '\n' )
1236{
1237cursor.x = window->hborder;
1238cursor.y += font->height;
1239if ( cursor.y > bounds.y )
1240{
1241gui.redraw = true;
1242updateVRAM();
1243cursor.y = window->vborder;
1244}
1245window->cursor.y = cursor.y;
1246continue;
1247}
1248
1249// tab ?
1250if( formattedtext[i] == '\t' )
1251{
1252cursor.x = ( cursor.x / ( font->chars[0]->width * 8 ) + 1 ) * ( font->chars[0]->width * 8 );
1253continue;
1254}
1255cursor.x += font->chars[character]->width;
1256
1257// check x pos and do newline
1258if ( cursor.x > bounds.x )
1259{
1260cursor.x = origin.x;
1261cursor.y += font->height;
1262}
1263
1264// check y pos and reset to origin.y
1265if ( cursor.y > ( bounds.y + font->chars[0]->height) )
1266{
1267gui.redraw = true;
1268updateVRAM();
1269cursor.y = window->vborder;
1270}
1271// draw the character
1272if( font->chars[character])
1273blend(font->chars[character], gui.backbuffer, cursor);
1274}
1275// save cursor postition
1276window->cursor.x = cursor.x;
1277updateVRAM();
1278free(formattedtext);
1279return 0;
1280}
1281return 1;
1282}
1283
1284void drawStr(char *ch, font_t *font, pixmap_t *blendInto, position_t p)
1285{
1286int i=0;
1287int y=0; // we need this to support multilines '\n'
1288int x=0;
1289
1290for(i=0;i<strlen(ch);i++)
1291{
1292int cha=(int)ch[i];
1293
1294cha-=32;
1295
1296// newline ?
1297if( ch[i] == '\n' )
1298{
1299x = 0;
1300y += font->height;
1301continue;
1302}
1303
1304// tab ?
1305if( ch[i] == '\t' )
1306x+=(font->chars[0]->width*5);
1307
1308if(font->chars[cha])
1309blend(font->chars[cha], blendInto, pos(p.x+x, p.y+y));
1310
1311x += font->chars[cha]->width;
1312}
1313}
1314
1315void drawStrCenteredAt(char *text, font_t *font, pixmap_t *blendInto, position_t p)
1316{
1317int i = 0;
1318int width = 0;
1319
1320// calculate the width in pixels
1321for(i=0;i<strlen(text);i++)
1322width += font->chars[text[i]-32]->width;
1323
1324p.x = ( p.x - ( width / 2 ) );
1325p.y = ( p.y - ( font->height / 2 ) );
1326
1327if ( p.x == -6 )
1328{
1329p.x = 0;
1330}
1331
1332for(i=0;i<strlen(text);i++)
1333{
1334int cha=(int)text[i];
1335
1336cha-=32;
1337
1338if(font->chars[cha])
1339{
1340blend(font->chars[cha], blendInto, p);
1341p.x += font->chars[cha]->width;
1342}
1343}
1344
1345}
1346
1347int initFont(font_t *font, image_t *data)
1348{
1349unsigned int x = 0, y = 0, x2 = 0, x3 = 0;
1350
1351int start = 0, end = 0, count = 0, space = 0;
1352
1353bool monospaced = false;
1354
1355font->height = data->image->height;
1356
1357for( x = 0; x < data->image->width; x++)
1358{
1359start = end;
1360
1361// if the pixel is red we've reached the end of the char
1362if( pixel( data->image, x, 0 ).value == 0xFFFF0000)
1363{
1364end = x + 1;
1365
1366if( (font->chars[count] = malloc(sizeof(pixmap_t)) ) )
1367{
1368font->chars[count]->width = ( end - start) - 1;
1369font->chars[count]->height = font->height;
1370
1371if ( ( font->chars[count]->pixels = malloc( font->chars[count]->width * data->image->height * 4) ) )
1372{
1373space += ( font->chars[count]->width * data->image->height * 4 );
1374// we skip the first line because there are just the red pixels for the char width
1375for( y = 1; y< (font->height); y++)
1376{
1377for( x2 = start, x3 = 0; x2 < end; x2++, x3++)
1378{
1379pixel( font->chars[count], x3, y ) = pixel( data->image, x2, y );
1380}
1381}
1382
1383// check if font is monospaced
1384if( ( count > 0 ) && ( font->width != font->chars[count]->width ) )
1385monospaced = true;
1386
1387font->width = font->chars[count]->width;
1388
1389count++;
1390}
1391}
1392}
1393}
1394
1395if(monospaced)
1396font->width = 0;
1397
1398return 0;
1399}
1400
1401void colorFont(font_t *font, uint32_t color)
1402{
1403if( !color )
1404return;
1405
1406int x, y, width, height;
1407int count = 0;
1408pixel_t *buff;
1409
1410while( font->chars[count++] )
1411{
1412width = font->chars[count-1]->width;
1413height = font->chars[count-1]->height;
1414for( y = 0; y < height; y++ )
1415{
1416for( x = 0; x < width; x++ )
1417{
1418buff = &(pixel( font->chars[count-1], x, y ));
1419if( buff->ch.a )
1420{
1421buff->ch.r = (color & 0xFFFF0000) >> 16;
1422buff->ch.g = (color & 0xFF00FF00) >> 8;
1423buff->ch.b = (color & 0xFF0000FF);
1424}
1425}
1426}
1427}
1428}
1429
1430void makeRoundedCorners(pixmap_t *p)
1431{
1432int x,y;
1433int width=p->width-1;
1434int height=p->height-1;
1435
1436// 10px rounded corner alpha values
1437uint8_t roundedCorner[10][10] =
1438{
1439{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x80, 0xC0, 0xFF},
1440{ 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0xFF, 0xFF, 0xFF, 0xFF},
1441{ 0x00, 0x00, 0x00, 0x40, 0xEF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF},
1442{ 0x00, 0x00, 0x40, 0xEF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF},
1443{ 0x00, 0x40, 0xEF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF},
1444{ 0x00, 0xEF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF},
1445{ 0x40, 0xEF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF},
1446{ 0x80, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF},
1447{ 0xC0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF},
1448{ 0xEF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}
1449};
1450
1451uint8_t alpha=0;
1452
1453for( y=0; y<10; y++)
1454{
1455for( x=0; x<10; x++)
1456{
1457// skip if the pixel should be visible
1458if(roundedCorner[y][x] != 0xFF)
1459{
1460alpha = ( roundedCorner[y][x] ? (uint8_t) (roundedCorner[y][x] * pixel(p, x, y).ch.a) / 255 : 0 );
1461// Upper left corner
1462pixel(p, x, y).ch.a = alpha;
1463
1464// upper right corner
1465pixel(p, width-x,y).ch.a = alpha;
1466
1467// lower left corner
1468pixel(p, x, height-y).ch.a = alpha;
1469
1470// lower right corner
1471pixel(p, width-x, height-y).ch.a = alpha;
1472}
1473}
1474}
1475}
1476
1477void showInfoBox(char *title, char *text)
1478{
1479int i, key, lines, visiblelines;
1480
1481int currentline=0;
1482int cnt=0;
1483int offset=0;
1484
1485if( !title || !text )
1486return;
1487
1488position_t pos_title = pos ( gui.infobox.vborder, gui.infobox.vborder );
1489
1490// calculate number of lines in the title
1491for ( i = 0, lines = 1; i<strlen(title); i++ )
1492if( title[i] == '\n')
1493lines++;
1494
1495// y position of text is lines in title * height of font
1496position_t pos_text = pos( pos_title.x , pos_title.y + ( font_console.height * lines ));
1497
1498// calculate number of lines in the text
1499for ( i=0, lines = 1; i<strlen(text); i++ )
1500if( text[i] == '\n')
1501lines++;
1502
1503// if text ends with \n strip off
1504if( text[i] == '\n' || text[i] == '\0')
1505lines--;
1506
1507visiblelines = ( ( gui.infobox.height - ( gui.infobox.vborder * 2 ) ) / font_console.height ) - 1;
1508
1509// lets display the text and allow scroll thru using up down / arrows
1510while(1)
1511{
1512// move to current line in text
1513for( offset = 0, i = 0; offset < strlen(text); offset++ )
1514{
1515if( currentline == i)
1516break;
1517if( text[offset] =='\n')
1518i++;
1519}
1520
1521// find last visible line in text and place \0
1522for( i = offset, cnt = 0; i < strlen(text); i++)
1523{
1524if(text[i]=='\n')
1525cnt++;
1526if ( cnt == visiblelines )
1527{
1528text[i]='\0';
1529break;
1530}
1531}
1532
1533fillPixmapWithColor( gui.infobox.pixmap, gui.infobox.bgcolor);
1534
1535makeRoundedCorners( gui.infobox.pixmap);
1536
1537// print the title if present
1538if( title )
1539drawStr(title, &font_console, gui.infobox.pixmap, pos_title);
1540
1541// print the text
1542drawStr( text + offset, &font_console, gui.infobox.pixmap, pos_text);
1543
1544// restore \n in text
1545if ( cnt == visiblelines )
1546text[i] = '\n';
1547
1548position_t pos_indicator = pos( gui.infobox.width - ( images[iTextScrollPrev].image->width - ( gui.infobox.vborder / 2) ), pos_text.y );
1549
1550// draw prev indicator
1551if(offset)
1552{
1553blend( images[iTextScrollPrev].image, gui.infobox.pixmap, centeredAt( images[iTextScrollPrev].image, pos_indicator ));
1554}
1555
1556// draw next indicator
1557if( lines > ( currentline + visiblelines ) )
1558{
1559pos_indicator.y = ( gui.infobox.height - ( ( images[iTextScrollNext].image->width + gui.infobox.vborder ) / 2 ) );
1560blend( images[iTextScrollNext].image, gui.infobox.pixmap, centeredAt( images[iTextScrollNext].image, pos_indicator ) );
1561}
1562
1563gui.bootprompt.draw = false;
1564gui.infobox.draw = true;
1565gui.redraw = true;
1566
1567updateVRAM();
1568
1569key = getchar();
1570
1571if( key == kUpArrowkey )
1572if( currentline > 0 )
1573currentline--;
1574
1575if( key == kDownArrowkey )
1576if( lines > ( currentline + visiblelines ) )
1577currentline++;
1578
1579if( key == kEscapeKey || key == 'q' || key == 'Q')
1580{
1581gui.infobox.draw = false;
1582gui.redraw = true;
1583updateVRAM();
1584break;
1585}
1586}
1587}
1588
1589void animateProgressBar()
1590{
1591int y;
1592
1593if( time18() > lasttime)
1594{
1595lasttime = time18();
1596
1597pixmap_t *buffBar = images[iProgressBar].image;
1598
1599uint32_t buff = buffBar->pixels[0].value;
1600
1601memcpy( buffBar->pixels, buffBar->pixels + 1, ( (buffBar->width*buffBar->height) - 1 ) * 4 );
1602
1603for( y = buffBar->height - 1; y > 0; y--)
1604pixel(buffBar, buffBar->width - 1, y) = pixel(buffBar, buffBar->width - 1, y - 1);
1605
1606pixel(buffBar, buffBar->width-1, 0).value = buff;
1607}
1608}
1609
1610void drawProgressBar(pixmap_t *blendInto, uint16_t width, position_t p, uint8_t progress)
1611{
1612if(progress>100)
1613return;
1614
1615p.x = ( p.x - ( width / 2 ) );
1616
1617int todraw = (width * progress) / 100;
1618
1619pixmap_t *buff = images[iProgressBar].image;
1620pixmap_t *buffBG = images[iProgressBarBackground].image;
1621if(!buff || !buffBG)
1622return;
1623
1624pixmap_t progressbar;
1625progressbar.pixels=malloc(width * 4 * buff->height);
1626if(!progressbar.pixels)
1627return;
1628
1629progressbar.width = width;
1630progressbar.height = buff->height;
1631
1632int x=0,x2=0,y=0;
1633
1634for(y=0; y<buff->height; y++)
1635{
1636for(x=0; x<todraw; x++, x2++)
1637{
1638if(x2 == (buff->width-1)) x2=0;
1639pixel(&progressbar, x,y).value = pixel(buff, x2,y).value;
1640}
1641x2=0;
1642}
1643
1644for(y=0; y<buff->height; y++)
1645{
1646for(x=todraw, x2 = 0; x < width - 1; x++, x2++)
1647{
1648if(x2 == (buffBG->width -2 )) x2 = 0;
1649pixel(&progressbar, x,y).value = pixel(buffBG, x2,y).value;
1650}
1651if(progress < 100)
1652pixel(&progressbar, width - 1, y).value = pixel(buffBG, buffBG->width - 1, y).value;
1653if(progress == 0)
1654pixel(&progressbar, 0, y).value = pixel(buffBG, buffBG->width - 1, y).value;
1655x2=0;
1656}
1657
1658blend(&progressbar, blendInto, p);
1659animateProgressBar();
1660free(progressbar.pixels);
1661}
1662
1663void drawInfoMenuItems()
1664{
1665int i,n;
1666
1667position_t position;
1668
1669pixmap_t *selection = images[iMenuSelection].image;
1670
1671pixmap_t *pbuff;
1672
1673fillPixmapWithColor(gui.menu.pixmap, gui.menu.bgcolor);
1674
1675makeRoundedCorners(gui.menu.pixmap);
1676
1677uint8_t offset = infoMenuNativeBoot ? 0 : infoMenuItemsCount - 1;
1678
1679position = pos(0,0);
1680
1681for ( i = 0, n = iMenuBoot; i < infoMenuItemsCount; i++, n++)
1682{
1683if (i == infoMenuSelection)
1684blend(selection, gui.menu.pixmap, position);
1685
1686pbuff = images[n].image;
1687if (offset && i >= INFOMENU_NATIVEBOOT_START && i <= INFOMENU_NATIVEBOOT_END)
1688blend( images[n + (iMenuHelp - iMenuBoot)].image , gui.menu.pixmap,
1689pos((position.x + (gui.menu.hborder / 2)), position.y + ((selection->height - pbuff->height) / 2)));
1690else
1691blend( pbuff, gui.menu.pixmap,
1692pos((position.x + (gui.menu.hborder / 2)), position.y + ((selection->height - pbuff->height) / 2)));
1693
1694drawStr(infoMenuItems[i].text, &font_console, gui.menu.pixmap,
1695pos(position.x + (pbuff->width + gui.menu.hborder),
1696position.y + ((selection->height - font_console.height) / 2)));
1697position.y += images[iMenuSelection].image->height;
1698
1699}
1700
1701gui.redraw = true;
1702}
1703
1704int drawInfoMenu()
1705{
1706drawInfoMenuItems();
1707
1708gui.menu.draw = true;
1709
1710updateVRAM();
1711
1712return 1;
1713}
1714
1715int updateInfoMenu(int key)
1716{
1717switch (key)
1718{
1719
1720case kUpArrowkey:// up arrow
1721if (infoMenuSelection > 0)
1722{
1723if(!infoMenuNativeBoot && infoMenuSelection == INFOMENU_NATIVEBOOT_END + 1)
1724infoMenuSelection -= 4;
1725
1726else
1727infoMenuSelection--;
1728drawInfoMenuItems();
1729updateVRAM();
1730
1731} else {
1732
1733gui.menu.draw = false;
1734gui.redraw = true;
1735
1736updateVRAM();
1737
1738return CLOSE_INFO_MENU;
1739}
1740break;
1741
1742case kDownArrowkey:// down arrow
1743if (infoMenuSelection < infoMenuItemsCount - 1)
1744{
1745if(!infoMenuNativeBoot && infoMenuSelection == INFOMENU_NATIVEBOOT_START - 1)
1746infoMenuSelection += 4;
1747else
1748infoMenuSelection++;
1749drawInfoMenuItems();
1750updateVRAM();
1751}
1752break;
1753
1754case kReturnKey:
1755key = 0;
1756if( infoMenuSelection == MENU_SHOW_MEMORY_INFO )
1757showInfoBox( "Memory Info. Press q to quit.\n", getMemoryInfoString());
1758
1759else if( infoMenuSelection == MENU_SHOW_VIDEO_INFO )
1760showInfoBox( getVBEInfoString(), getVBEModeInfoString() );
1761
1762else if( infoMenuSelection == MENU_SHOW_HELP )
1763showHelp();
1764
1765else
1766{
1767int buff = infoMenuSelection;
1768infoMenuSelection = 0;
1769return buff;
1770}
1771break;
1772}
1773return DO_NOT_BOOT;
1774}
1775
1776uint16_t bootImageWidth = 0;
1777uint16_t bootImageHeight = 0;
1778uint8_t *bootImageData = NULL;
1779static bool usePngImage = true;
1780
1781//==========================================================================
1782// loadBootGraphics
1783static void loadBootGraphics(void)
1784{
1785if (bootImageData != NULL) {
1786return;
1787}
1788
1789char dirspec[256];
1790
1791if ((strlen(theme_name) + 24) > sizeof(dirspec)) {
1792usePngImage = false;
1793return;
1794}
1795sprintf(dirspec, "/Extra/Themes/%s/boot.png", theme_name);
1796if (loadPngImage(dirspec, &bootImageWidth, &bootImageHeight, &bootImageData) != 0) {
1797#ifdef CONFIG_EMBED_THEME
1798 if ((loadEmbeddedPngImage(__boot_png, __boot_png_len, &bootImageWidth, &bootImageHeight, &bootImageData)) != 0)
1799#endif
1800usePngImage = false;
1801}
1802}
1803
1804//==========================================================================
1805// drawBootGraphics
1806void drawBootGraphics(void)
1807{
1808int pos;
1809int length;
1810const char *dummyVal;
1811int oldScreenWidth, oldScreenHeight;
1812bool legacy_logo;
1813uint16_t x, y;
1814
1815if (getBoolForKey("Legacy Logo", &legacy_logo, &bootInfo->chameleonConfig) && legacy_logo) {
1816usePngImage = false;
1817} else if (bootImageData == NULL) {
1818loadBootGraphics();
1819}
1820
1821// parse screen size parameters
1822if (getIntForKey("boot_width", &pos, &bootInfo->themeConfig) && pos > 0) {
1823screen_params[0] = pos;
1824} else {
1825screen_params[0] = DEFAULT_SCREEN_WIDTH;
1826}
1827if (getIntForKey("boot_height", &pos, &bootInfo->themeConfig) && pos > 0) {
1828screen_params[1] = pos;
1829} else {
1830screen_params[1] = DEFAULT_SCREEN_HEIGHT;
1831}
1832
1833 // Save current screen resolution.
1834oldScreenWidth = gui.screen.width;
1835oldScreenHeight = gui.screen.height;
1836
1837gui.screen.width = screen_params[0];
1838gui.screen.height = screen_params[1];
1839
1840// find best matching vesa mode for our requested width & height
1841getGraphicModeParams(screen_params);
1842
1843 // Set graphics mode if the booter was in text mode or the screen resolution has changed.
1844if (bootArgs->Video.v_display == VGA_TEXT_MODE
1845|| (screen_params[0] != oldScreenWidth && screen_params[1] != oldScreenHeight) )
1846{
1847setVideoMode(GRAPHICS_MODE, 0);
1848}
1849
1850if (getValueForKey("-checkers", &dummyVal, &length, &bootInfo->chameleonConfig)) {
1851drawCheckerBoard();
1852} else {
1853// Fill the background to 75% grey (same as BootX).
1854drawColorRectangle(0, 0, screen_params[0], screen_params[1], 0x01);
1855}
1856if ((bootImageData) && (usePngImage)) {
1857x = (screen_params[0] - MIN(bootImageWidth, screen_params[0])) / 2;
1858y = (screen_params[1] - MIN(bootImageHeight, screen_params[1])) / 2;
1859
1860// Draw the image in the center of the display.
1861blendImage(x, y, bootImageWidth, bootImageHeight, bootImageData);
1862} else {
1863uint8_t *appleBootPict;
1864bootImageData = NULL;
1865bootImageWidth = kAppleBootWidth;
1866bootImageHeight = kAppleBootHeight;
1867
1868// Prepare the data for the default Apple boot image.
1869appleBootPict = (uint8_t *) decodeRLE(gAppleBootPictRLE, kAppleBootRLEBlocks, bootImageWidth * bootImageHeight);
1870if (appleBootPict) {
1871convertImage(bootImageWidth, bootImageHeight, appleBootPict, &bootImageData);
1872if (bootImageData) {
1873x = (screen_params[0] - MIN(kAppleBootWidth, screen_params[0])) / 2;
1874y = (screen_params[1] - MIN(kAppleBootHeight, screen_params[1])) / 2;
1875drawDataRectangle(x, y, kAppleBootWidth, kAppleBootHeight, bootImageData);
1876free(bootImageData);
1877}
1878free(appleBootPict);
1879}
1880}
1881}
1882

Archive Download this file

Revision: 1808