2 * GRUB -- GRand Unified Bootloader
3 * Copyright (C) 2009 Free Software Foundation, Inc.
5 * GRUB 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.
10 * GRUB 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.
15 * You should have received a copy of the GNU General Public License
16 * along with GRUB. If not, see <http://www.gnu.org/licenses/>.
20 #include <grub/types.h>
21 #include <grub/util/misc.h>
29 #include FT_FREETYPE_H
30 #include <freetype/ftsynth.h>
32 #define GRUB_FONT_DEFAULT_SIZE 16
34 #define GRUB_FONT_RANGE_BLOCK 1024
36 struct grub_glyph_info
38 struct grub_glyph_info
*next
;
39 grub_uint32_t char_code
;
46 grub_uint8_t bitmap
[0];
49 #define GRUB_FONT_FLAG_BOLD 1
50 #define GRUB_FONT_FLAG_NOBITMAP 2
51 #define GRUB_FONT_FLAG_NOHINTING 4
52 #define GRUB_FONT_FLAG_FORCEHINT 8
65 grub_uint32_t
*ranges
;
66 struct grub_glyph_info
*glyph
;
69 static struct option options
[] =
71 {"output", required_argument
, 0, 'o'},
72 {"name", required_argument
, 0, 'n'},
73 {"index", required_argument
, 0, 'i'},
74 {"range", required_argument
, 0, 'r'},
75 {"size", required_argument
, 0, 's'},
76 {"desc", required_argument
, 0, 'd'},
77 {"bold", no_argument
, 0, 'b'},
78 {"no-bitmap", no_argument
, 0, 0x100},
79 {"no-hinting", no_argument
, 0, 0x101},
80 {"force-autohint", no_argument
, 0, 'a'},
81 {"help", no_argument
, 0, 'h'},
82 {"version", no_argument
, 0, 'V'},
83 {"verbose", no_argument
, 0, 'v'},
93 fprintf (stderr
, "Try ``grub-mkfont --help'' for more information.\n");
96 Usage: grub-mkfont [OPTIONS] FONT_FILES\n\
98 -o, --output=FILE_NAME set output file name\n\
99 -i, --index=N set face index\n\
100 -r, --range=A-B[,C-D] set font range\n\
101 -n, --name=S set font family name\n\
102 -s, --size=N set font size\n\
103 -d, --desc=N set font descent\n\
104 -b, --bold convert to bold font\n\
105 -a, --force-autohint force autohint\n\
106 --no-hinting disable hinting\n\
107 --no-bitmap ignore bitmap strikes when loading\n\
108 -h, --help display this message and exit\n\
109 -V, --version print version information and exit\n\
110 -v, --verbose print verbose messages\n\
112 Report bugs to <%s>.\n", PACKAGE_BUGREPORT
);
118 add_pixel (grub_uint8_t
**data
, int *mask
, int not_blank
)
134 add_char (struct grub_font_info
*font_info
, FT_Face face
,
135 grub_uint32_t char_code
)
137 struct grub_glyph_info
*glyph_info
, **p_glyph
;
140 int mask
, i
, j
, bitmap_size
;
142 int flag
= FT_LOAD_RENDER
| FT_LOAD_MONOCHROME
;
144 if (font_info
->flags
& GRUB_FONT_FLAG_NOBITMAP
)
145 flag
|= FT_LOAD_NO_BITMAP
;
147 if (font_info
->flags
& GRUB_FONT_FLAG_NOHINTING
)
148 flag
|= FT_LOAD_NO_HINTING
;
149 else if (font_info
->flags
& GRUB_FONT_FLAG_FORCEHINT
)
150 flag
|= FT_LOAD_FORCE_AUTOHINT
;
152 if (FT_Load_Char (face
, char_code
, flag
))
157 if (font_info
->flags
& GRUB_FONT_FLAG_BOLD
)
158 FT_GlyphSlot_Embolden (glyph
);
160 p_glyph
= &font_info
->glyph
;
161 while ((*p_glyph
) && ((*p_glyph
)->char_code
> char_code
))
163 p_glyph
= &(*p_glyph
)->next
;
166 /* Ignore duplicated glyph. */
167 if ((*p_glyph
) && ((*p_glyph
)->char_code
== char_code
))
170 width
= glyph
->bitmap
.width
;
171 height
= glyph
->bitmap
.rows
;
173 bitmap_size
= ((width
* height
+ 7) / 8);
174 glyph_info
= xmalloc (sizeof (struct grub_glyph_info
) + bitmap_size
);
175 glyph_info
->bitmap_size
= bitmap_size
;
177 glyph_info
->next
= *p_glyph
;
178 *p_glyph
= glyph_info
;
180 glyph_info
->char_code
= char_code
;
181 glyph_info
->width
= width
;
182 glyph_info
->height
= height
;
183 glyph_info
->x_ofs
= glyph
->bitmap_left
;
184 glyph_info
->y_ofs
= glyph
->bitmap_top
- height
;
185 glyph_info
->device_width
= glyph
->metrics
.horiAdvance
/ 64;
187 if (width
> font_info
->max_width
)
188 font_info
->max_width
= width
;
190 if (height
> font_info
->max_height
)
191 font_info
->max_height
= height
;
193 if (glyph_info
->y_ofs
< font_info
->min_y
)
194 font_info
->min_y
= glyph_info
->y_ofs
;
197 data
= &glyph_info
->bitmap
[0] - 1;
198 for (j
= 0; j
< height
; j
++)
199 for (i
= 0; i
< width
; i
++)
200 add_pixel (&data
, &mask
,
201 glyph
->bitmap
.buffer
[i
/ 8 + j
* glyph
->bitmap
.pitch
] &
202 (1 << (7 - (i
& 7))));
206 add_font (struct grub_font_info
*font_info
, FT_Face face
)
208 if (font_info
->num_range
)
213 for (i
= 0; i
< font_info
->num_range
; i
++)
214 for (j
= font_info
->ranges
[i
* 2]; j
<= font_info
->ranges
[i
* 2 + 1];
216 add_char (font_info
, face
, j
);
220 grub_uint32_t char_code
, glyph_index
;
222 for (char_code
= FT_Get_First_Char (face
, &glyph_index
);
224 char_code
= FT_Get_Next_Char (face
, char_code
, &glyph_index
))
225 add_char (font_info
, face
, char_code
);
230 write_string_section (char *name
, char *str
, int* offset
, FILE* file
)
232 grub_uint32_t leng
, leng_be32
;
234 leng
= strlen (str
) + 1;
235 leng_be32
= grub_cpu_to_be32 (leng
);
237 grub_util_write_image (name
, 4, file
);
238 grub_util_write_image ((char *) &leng_be32
, 4, file
);
239 grub_util_write_image (str
, leng
, file
);
245 write_be16_section (char *name
, grub_uint16_t data
, int* offset
, FILE* file
)
249 leng
= grub_cpu_to_be32 (2);
250 data
= grub_cpu_to_be16 (data
);
251 grub_util_write_image (name
, 4, file
);
252 grub_util_write_image ((char *) &leng
, 4, file
);
253 grub_util_write_image ((char *) &data
, 2, file
);
259 print_glyphs (struct grub_font_info
*font_info
)
262 struct grub_glyph_info
*glyph
;
265 for (glyph
= font_info
->glyph
, num
= 0; glyph
; glyph
= glyph
->next
, num
++)
267 int x
, y
, xmax
, xmin
, ymax
, ymin
;
268 grub_uint8_t
*bitmap
, mask
;
270 printf ("\nGlyph #%d, U+%04x\n", num
, glyph
->char_code
);
271 printf ("Width %d, Height %d, X offset %d, Y offset %d, Device width %d\n",
272 glyph
->width
, glyph
->height
, glyph
->x_ofs
, glyph
->y_ofs
,
273 glyph
->device_width
);
275 xmax
= glyph
->x_ofs
+ glyph
->width
;
276 if (xmax
< glyph
->device_width
)
277 xmax
= glyph
->device_width
;
283 ymax
= glyph
->y_ofs
+ glyph
->height
;
284 if (ymax
< font_info
->size
- font_info
->desc
)
285 ymax
= font_info
->size
- font_info
->desc
;
288 if (ymin
> - font_info
->desc
)
289 ymin
= - font_info
->desc
;
291 bitmap
= glyph
->bitmap
;
293 for (y
= ymax
- 1; y
>= ymin
; y
--)
298 for (x
= xmin
; x
< xmax
; x
++)
300 if ((x
>= glyph
->x_ofs
) &&
301 (x
< glyph
->x_ofs
+ glyph
->width
) &&
302 (y
>= glyph
->y_ofs
) &&
303 (y
< glyph
->y_ofs
+ glyph
->height
))
305 line
[line_pos
++] = (*bitmap
& mask
) ? '#' : '_';
314 (x
< glyph
->device_width
) &&
315 (y
>= - font_info
->desc
) &&
316 (y
< font_info
->size
- font_info
->desc
))
318 line
[line_pos
++] = ((x
== 0) || (y
== 0)) ? '+' : '.';
321 line
[line_pos
++] = '*';
324 printf ("%s\n", line
);
330 write_font (struct grub_font_info
*font_info
, char *output_file
)
333 grub_uint32_t leng
, data
;
334 char style_name
[20], *font_name
;
335 struct grub_glyph_info
*cur
, *pre
;
338 file
= fopen (output_file
, "wb");
340 grub_util_error ("Can\'t write to file %s.", output_file
);
344 leng
= grub_cpu_to_be32 (4);
345 grub_util_write_image ("FILE", 4, file
);
346 grub_util_write_image ((char *) &leng
, 4, file
);
347 grub_util_write_image ("PFF2", 4, file
);
350 if (! font_info
->name
)
351 font_info
->name
= "Unknown";
353 if (font_info
->flags
& GRUB_FONT_FLAG_BOLD
)
354 font_info
->style
|= FT_STYLE_FLAG_BOLD
;
357 if (font_info
->style
& FT_STYLE_FLAG_BOLD
)
358 strcpy (style_name
, " Bold");
360 if (font_info
->style
& FT_STYLE_FLAG_ITALIC
)
361 strcat (style_name
, " Italic");
364 strcpy (style_name
, " Regular");
366 asprintf (&font_name
, "%s %s %d", font_info
->name
, &style_name
[1],
369 write_string_section ("NAME", font_name
, &offset
, file
);
370 write_string_section ("FAMI", font_info
->name
, &offset
, file
);
371 write_string_section ("WEIG",
372 (font_info
->style
& FT_STYLE_FLAG_BOLD
) ?
375 write_string_section ("SLAN",
376 (font_info
->style
& FT_STYLE_FLAG_ITALIC
) ?
380 write_be16_section ("PTSZ", font_info
->size
, &offset
, file
);
381 write_be16_section ("MAXW", font_info
->max_width
, &offset
, file
);
382 write_be16_section ("MAXH", font_info
->max_height
, &offset
, file
);
384 if (! font_info
->desc
)
386 if (font_info
->min_y
>= 0)
389 font_info
->desc
= - font_info
->min_y
;
392 write_be16_section ("ASCE", font_info
->size
- font_info
->desc
, &offset
, file
);
393 write_be16_section ("DESC", font_info
->desc
, &offset
, file
);
395 if (font_verbosity
> 0)
397 printf ("Font name: %s\n", font_name
);
398 printf ("Max width: %d\n", font_info
->max_width
);
399 printf ("Max height: %d\n", font_info
->max_height
);
400 printf ("Font ascent: %d\n", font_info
->size
- font_info
->desc
);
401 printf ("Font descent: %d\n", font_info
->desc
);
406 cur
= font_info
->glyph
;
409 struct grub_glyph_info
*nxt
;
418 font_info
->glyph
= pre
;
420 if (font_verbosity
> 0)
421 printf ("Number of glyph: %d\n", num
);
423 leng
= grub_cpu_to_be32 (num
* 9);
424 grub_util_write_image ("CHIX", 4, file
);
425 grub_util_write_image ((char *) &leng
, 4, file
);
426 offset
+= 8 + num
* 9 + 8;
428 for (cur
= font_info
->glyph
; cur
; cur
= cur
->next
)
430 data
= grub_cpu_to_be32 (cur
->char_code
);
431 grub_util_write_image ((char *) &data
, 4, file
);
433 grub_util_write_image ((char *) &data
, 1, file
);
434 data
= grub_cpu_to_be32 (offset
);
435 grub_util_write_image ((char *) &data
, 4, file
);
436 offset
+= 10 + cur
->bitmap_size
;
440 grub_util_write_image ("DATA", 4, file
);
441 grub_util_write_image ((char *) &leng
, 4, file
);
443 for (cur
= font_info
->glyph
; cur
; cur
= cur
->next
)
445 data
= grub_cpu_to_be16 (cur
->width
);
446 grub_util_write_image ((char *) &data
, 2, file
);
447 data
= grub_cpu_to_be16 (cur
->height
);
448 grub_util_write_image ((char *) &data
, 2, file
);
449 data
= grub_cpu_to_be16 (cur
->x_ofs
);
450 grub_util_write_image ((char *) &data
, 2, file
);
451 data
= grub_cpu_to_be16 (cur
->y_ofs
);
452 grub_util_write_image ((char *) &data
, 2, file
);
453 data
= grub_cpu_to_be16 (cur
->device_width
);
454 grub_util_write_image ((char *) &data
, 2, file
);
455 grub_util_write_image ((char *) &cur
->bitmap
[0], cur
->bitmap_size
, file
);
458 if (font_verbosity
> 1)
459 print_glyphs (font_info
);
465 main (int argc
, char *argv
[])
467 struct grub_font_info font_info
;
471 char *output_file
= NULL
;
473 memset (&font_info
, 0, sizeof (font_info
));
475 progname
= "grub-mkfont";
477 /* Check for options. */
480 int c
= getopt_long (argc
, argv
, "bao:n:i:s:d:r:hVv", options
, 0);
488 font_info
.flags
|= GRUB_FONT_FLAG_BOLD
;
492 font_info
.flags
|= GRUB_FONT_FLAG_NOBITMAP
;
496 font_info
.flags
|= GRUB_FONT_FLAG_NOHINTING
;
500 font_info
.flags
|= GRUB_FONT_FLAG_FORCEHINT
;
504 output_file
= optarg
;
508 font_info
.name
= optarg
;
512 font_index
= strtoul (optarg
, NULL
, 0);
516 font_size
= strtoul (optarg
, NULL
, 0);
527 a
= strtoul (p
, &p
, 0);
529 grub_util_error ("Invalid font range");
530 b
= strtoul (p
+ 1, &p
, 0);
531 if ((font_info
.num_range
& (GRUB_FONT_RANGE_BLOCK
- 1)) == 0)
532 font_info
.ranges
= xrealloc (font_info
.ranges
,
533 (font_info
.num_range
+
534 GRUB_FONT_RANGE_BLOCK
) *
537 font_info
.ranges
[font_info
.num_range
* 2] = a
;
538 font_info
.ranges
[font_info
.num_range
* 2 + 1] = b
;
539 font_info
.num_range
++;
544 grub_util_error ("Invalid font range");
555 font_info
.desc
= strtoul (optarg
, NULL
, 0);
563 printf ("%s (%s) %s\n", progname
, PACKAGE_NAME
, PACKAGE_VERSION
);
577 grub_util_error ("No output file is specified.");
579 if (FT_Init_FreeType (&ft_lib
))
580 grub_util_error ("FT_Init_FreeType fails");
582 for (; optind
< argc
; optind
++)
587 if (FT_New_Face (ft_lib
, argv
[optind
], font_index
, &ft_face
))
589 grub_util_info ("Can't open file %s, index %d\n", argv
[optind
],
594 if ((! font_info
.name
) && (ft_face
->family_name
))
595 font_info
.name
= xstrdup (ft_face
->family_name
);
600 if ((ft_face
->face_flags
& FT_FACE_FLAG_SCALABLE
) ||
601 (! ft_face
->num_fixed_sizes
))
602 size
= GRUB_FONT_DEFAULT_SIZE
;
604 size
= ft_face
->available_sizes
[0].height
;
607 font_info
.style
= ft_face
->style_flags
;
608 font_info
.size
= size
;
610 FT_Set_Pixel_Sizes (ft_face
, size
, size
);
611 add_font (&font_info
, ft_face
);
612 FT_Done_Face (ft_face
);
615 FT_Done_FreeType (ft_lib
);
617 write_font (&font_info
, output_file
);