gfx_region.c 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319
  1. /*
  2. * BURG - Brand-new Universal loadeR from GRUB
  3. * Copyright 2009 Bean Lee - All Rights Reserved
  4. *
  5. * BURG is free software: you can redistribute it and/or modify
  6. * it under the terms of the GNU General Public License as published by
  7. * the Free Software Foundation, either version 3 of the License, or
  8. * (at your option) any later version.
  9. *
  10. * BURG is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. * GNU General Public License for more details.
  14. *
  15. * You should have received a copy of the GNU General Public License
  16. * along with BURG. If not, see <http://www.gnu.org/licenses/>.
  17. */
  18. #include <grub/dl.h>
  19. #include <grub/mm.h>
  20. #include <grub/env.h>
  21. #include <grub/misc.h>
  22. #include <grub/video.h>
  23. #include <grub/bitmap.h>
  24. #include <grub/bitmap_scale.h>
  25. #include <grub/menu_region.h>
  26. #include <grub/fbutil.h>
  27. #include <grub/fbblit.h>
  28. #define DEFAULT_VIDEO_MODE "auto"
  29. static int screen_width;
  30. static int screen_height;
  31. static grub_font_t default_font;
  32. static struct grub_menu_region grub_gfx_region;
  33. #define REFERENCE_STRING "m"
  34. static grub_err_t
  35. grub_gfx_region_init (void)
  36. {
  37. const char *modevar;
  38. struct grub_video_mode_info mode_info;
  39. grub_err_t err;
  40. char *fn;
  41. modevar = grub_env_get ("gfxmode");
  42. if (! modevar || *modevar == 0)
  43. err = grub_video_set_mode (DEFAULT_VIDEO_MODE,
  44. GRUB_VIDEO_MODE_TYPE_PURE_TEXT |
  45. GRUB_VIDEO_MODE_TYPE_DOUBLE_BUFFERED, 0);
  46. else
  47. {
  48. char *tmp;
  49. tmp = grub_xasprintf ("%s;" DEFAULT_VIDEO_MODE, modevar);
  50. if (!tmp)
  51. return grub_errno;
  52. err = grub_video_set_mode (tmp,
  53. GRUB_VIDEO_MODE_TYPE_PURE_TEXT |
  54. GRUB_VIDEO_MODE_TYPE_DOUBLE_BUFFERED, 0);
  55. grub_free (tmp);
  56. }
  57. if (err)
  58. return err;
  59. err = grub_video_get_info (&mode_info);
  60. if (err)
  61. return err;
  62. screen_width = mode_info.width;
  63. screen_height = mode_info.height;
  64. fn = grub_env_get ("gfxfont");
  65. if (! fn)
  66. fn = "";
  67. default_font = grub_font_get (fn);
  68. grub_gfx_region.char_width = grub_font_get_string_width (default_font,
  69. REFERENCE_STRING);
  70. grub_gfx_region.char_height = grub_font_get_ascent (default_font) +
  71. grub_font_get_descent (default_font);
  72. if ((! grub_gfx_region.char_width) || (! grub_gfx_region.char_height))
  73. return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "invalid font");
  74. return grub_errno;
  75. }
  76. static grub_err_t
  77. grub_gfx_region_fini (void)
  78. {
  79. grub_video_restore ();
  80. return (grub_errno = GRUB_ERR_NONE);
  81. }
  82. static void
  83. grub_gfx_region_get_screen_size (int *width, int *height)
  84. {
  85. *width = screen_width;
  86. *height = screen_height;
  87. }
  88. static grub_font_t
  89. grub_gfx_region_get_font (const char *name)
  90. {
  91. return (name) ? grub_font_get (name) : default_font;
  92. }
  93. static int
  94. grub_gfx_region_get_text_width (grub_font_t font, const char *str,
  95. int count, int *chars)
  96. {
  97. int width, w;
  98. const char *p;
  99. if (! count)
  100. {
  101. if (chars)
  102. *chars = grub_strlen (str);
  103. return grub_font_get_string_width (font, str);
  104. }
  105. width = 0;
  106. p = str;
  107. while ((count) && (*p) &&
  108. ((w = grub_font_get_code_width (font, p, &p)) > 0))
  109. {
  110. width += w;
  111. count--;
  112. }
  113. if (chars)
  114. *chars = p - str;
  115. return width;
  116. }
  117. static int
  118. grub_gfx_region_get_text_height (grub_font_t font)
  119. {
  120. return grub_font_get_height (font);
  121. }
  122. static struct grub_video_bitmap *
  123. grub_gfx_region_get_bitmap (const char *name)
  124. {
  125. struct grub_video_bitmap *bitmap;
  126. if (grub_video_bitmap_load (&bitmap, name))
  127. {
  128. grub_errno = 0;
  129. return 0;
  130. }
  131. return bitmap;
  132. }
  133. static void
  134. grub_gfx_region_free_bitmap (struct grub_video_bitmap *bitmap)
  135. {
  136. grub_video_bitmap_destroy (bitmap);
  137. }
  138. static void
  139. grub_gfx_region_scale_bitmap (struct grub_menu_region_bitmap *bitmap)
  140. {
  141. if ((bitmap->bitmap != bitmap->cache->bitmap) &&
  142. (bitmap->bitmap != bitmap->cache->scaled_bitmap))
  143. grub_video_bitmap_destroy (bitmap->bitmap);
  144. bitmap->bitmap = 0;
  145. grub_video_bitmap_create_scaled (&bitmap->bitmap, bitmap->common.width,
  146. bitmap->common.height,
  147. bitmap->cache->bitmap,
  148. bitmap->scale, bitmap->color);
  149. }
  150. static struct grub_video_bitmap *
  151. grub_gfx_region_new_bitmap (int width, int height)
  152. {
  153. struct grub_video_bitmap *dst = 0;
  154. grub_video_bitmap_create (&dst, width, height,
  155. GRUB_VIDEO_BLIT_FORMAT_RGBA_8888);
  156. return dst;
  157. }
  158. static void
  159. grub_gfx_region_blit_bitmap (struct grub_video_bitmap *dst,
  160. struct grub_video_bitmap *src,
  161. enum grub_video_blit_operators oper,
  162. int dst_x, int dst_y, int width, int height,
  163. int src_x, int src_y)
  164. {
  165. struct grub_video_fbblit_info dst_info;
  166. struct grub_video_fbblit_info src_info;
  167. dst_info.mode_info = &dst->mode_info;
  168. dst_info.data = dst->data;
  169. src_info.mode_info = &src->mode_info;
  170. src_info.data = src->data;
  171. grub_video_fbblit (&dst_info, &src_info, oper,
  172. dst_x, dst_y, width, height, src_x, src_y);
  173. }
  174. static grub_video_color_t
  175. grub_gfx_region_map_color (int fg_color, int bg_color __attribute__ ((unused)))
  176. {
  177. return grub_video_map_color (fg_color);
  178. }
  179. static grub_video_color_t
  180. grub_gfx_region_map_rgb (grub_uint8_t red, grub_uint8_t green, grub_uint8_t blue)
  181. {
  182. return grub_video_map_rgb (red, green, blue);
  183. }
  184. static void
  185. grub_gfx_region_update_rect (struct grub_menu_region_rect *rect,
  186. int x, int y, int width, int height,
  187. int scn_x, int scn_y)
  188. {
  189. if (rect->fill)
  190. {
  191. struct grub_font_glyph *glyph;
  192. int w, h, font_ascent, font_width;
  193. grub_video_set_viewport (scn_x, scn_y, width, height);
  194. glyph = grub_font_get_glyph_with_fallback (default_font, rect->fill);
  195. font_ascent = grub_font_get_ascent (default_font);
  196. font_width = glyph->device_width;
  197. for (h = -y ; h < height; h += grub_gfx_region.char_height)
  198. {
  199. for (w = -x; w < width; w += font_width)
  200. grub_font_draw_glyph (glyph, rect->color, w, h + font_ascent);
  201. }
  202. grub_video_set_viewport (0, 0, screen_width, screen_height);
  203. }
  204. else
  205. grub_video_fill_rect (rect->color, scn_x, scn_y, width, height);
  206. grub_video_update_rect (scn_x, scn_y, width, height);
  207. }
  208. static void
  209. grub_gfx_region_update_text (struct grub_menu_region_text *text,
  210. int x, int y, int width, int height,
  211. int scn_x, int scn_y)
  212. {
  213. grub_video_set_viewport (scn_x, scn_y, width, height);
  214. grub_font_draw_string (text->text, text->font, text->color, - x,
  215. - y + grub_font_get_ascent (text->font));
  216. grub_video_set_viewport (0, 0, screen_width, screen_height);
  217. grub_video_update_rect (scn_x, scn_y, width, height);
  218. }
  219. static void
  220. grub_gfx_region_update_bitmap (struct grub_menu_region_bitmap *bitmap,
  221. int x, int y, int width, int height,
  222. int scn_x, int scn_y)
  223. {
  224. grub_video_blit_bitmap (bitmap->bitmap, GRUB_VIDEO_BLIT_BLEND,
  225. scn_x, scn_y, x, y, width, height);
  226. grub_video_update_rect (scn_x, scn_y, width, height);
  227. }
  228. #define CURSOR_HEIGHT 2
  229. static void
  230. grub_gfx_region_draw_cursor (struct grub_menu_region_text *text,
  231. int width, int height, int scn_x, int scn_y)
  232. {
  233. int y;
  234. y = grub_font_get_ascent (text->font);
  235. if (y >= height)
  236. return;
  237. height -= y;
  238. if (height > CURSOR_HEIGHT)
  239. height = CURSOR_HEIGHT;
  240. grub_video_fill_rect (text->color, scn_x, scn_y + y, width, height);
  241. grub_video_update_rect (scn_x, scn_y + y, width, height);
  242. }
  243. static struct grub_menu_region grub_gfx_region =
  244. {
  245. .name = "gfx",
  246. .init = grub_gfx_region_init,
  247. .fini = grub_gfx_region_fini,
  248. .get_screen_size = grub_gfx_region_get_screen_size,
  249. .get_font = grub_gfx_region_get_font,
  250. .get_text_width = grub_gfx_region_get_text_width,
  251. .get_text_height = grub_gfx_region_get_text_height,
  252. .get_bitmap = grub_gfx_region_get_bitmap,
  253. .free_bitmap = grub_gfx_region_free_bitmap,
  254. .scale_bitmap = grub_gfx_region_scale_bitmap,
  255. .map_color = grub_gfx_region_map_color,
  256. .map_rgb = grub_gfx_region_map_rgb,
  257. .update_rect = grub_gfx_region_update_rect,
  258. .update_text = grub_gfx_region_update_text,
  259. .update_bitmap = grub_gfx_region_update_bitmap,
  260. .draw_cursor = grub_gfx_region_draw_cursor,
  261. .new_bitmap = grub_gfx_region_new_bitmap,
  262. .blit_bitmap = grub_gfx_region_blit_bitmap
  263. };
  264. GRUB_MOD_INIT(gfxrgn)
  265. {
  266. grub_menu_region_register ("gfx", &grub_gfx_region);
  267. }
  268. GRUB_MOD_FINI(gfxrgn)
  269. {
  270. grub_menu_region_unregister (&grub_gfx_region);
  271. }