Chameleon Applications

Chameleon Applications Svn Source Tree

Root/branches/iFabio/i386/boot2/gui.c

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

Archive Download this file

Revision: 214