2 * GRUB -- GRand Unified Bootloader
3 * Copyright (C) 2009,2010 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/misc.h>
22 #include <grub/emu/misc.h>
23 #include <grub/util/misc.h>
24 #include <grub/misc.h>
25 #include <grub/i18n.h>
26 #include <grub/fontformat.h>
27 #include <grub/font.h>
28 #include <grub/unicode.h>
39 #include FT_FREETYPE_H
40 #include FT_TRUETYPE_TAGS_H
41 #include FT_TRUETYPE_TABLES_H
42 #include <freetype/ftsynth.h>
45 #define FT_ERROR_START_LIST const char *ft_errmsgs[] = {
46 #define FT_ERRORDEF(e, v, s) [e] = s,
47 #define FT_ERROR_END_LIST };
52 #define GRUB_FONT_DEFAULT_SIZE 16
54 #define GRUB_FONT_RANGE_BLOCK 1024
56 struct grub_glyph_info
58 struct grub_glyph_info
*next
;
59 grub_uint32_t char_code
;
76 #define GRUB_FONT_FLAG_BOLD 1
77 #define GRUB_FONT_FLAG_NOBITMAP 2
78 #define GRUB_FONT_FLAG_NOHINTING 4
79 #define GRUB_FONT_FLAG_FORCEHINT 8
94 grub_uint32_t
*ranges
;
95 struct grub_glyph_info
*glyphs_unsorted
;
96 struct grub_glyph_info
*glyphs_sorted
;
100 static int font_verbosity
;
103 add_pixel (grub_uint8_t
**data
, int *mask
, int not_blank
)
119 add_glyph (struct grub_font_info
*font_info
, FT_UInt glyph_idx
, FT_Face face
,
120 grub_uint32_t char_code
, int nocut
)
122 struct grub_glyph_info
*glyph_info
;
124 int cuttop
, cutbottom
, cutleft
, cutright
;
126 int mask
, i
, j
, bitmap_size
;
128 int flag
= FT_LOAD_RENDER
| FT_LOAD_MONOCHROME
;
131 if (font_info
->flags
& GRUB_FONT_FLAG_NOBITMAP
)
132 flag
|= FT_LOAD_NO_BITMAP
;
134 if (font_info
->flags
& GRUB_FONT_FLAG_NOHINTING
)
135 flag
|= FT_LOAD_NO_HINTING
;
136 else if (font_info
->flags
& GRUB_FONT_FLAG_FORCEHINT
)
137 flag
|= FT_LOAD_FORCE_AUTOHINT
;
139 err
= FT_Load_Glyph (face
, glyph_idx
, flag
);
142 printf (_("Freetype Error %d loading glyph 0x%x for U+0x%x%s"),
143 err
, glyph_idx
, char_code
& GRUB_FONT_CODE_CHAR_MASK
,
144 char_code
& GRUB_FONT_CODE_RIGHT_JOINED
145 /* TRANSLATORS: These qualifiers are used for cursive typography,
146 mainly Arabic. Note that the terms refer to the visual position
147 and not logical order and if used in left-to-right script then
148 leftmost is initial but with right-to-left script like Arabic
149 rightmost is the initial. */
150 ? ((char_code
& GRUB_FONT_CODE_LEFT_JOINED
) ? _(" (medial)"):
152 : ((char_code
& GRUB_FONT_CODE_LEFT_JOINED
) ? _(" (rightmost)"):
155 if (err
> 0 && err
< (signed) ARRAY_SIZE (ft_errmsgs
))
156 printf (": %s\n", ft_errmsgs
[err
]);
164 if (font_info
->flags
& GRUB_FONT_FLAG_BOLD
)
165 FT_GlyphSlot_Embolden (glyph
);
168 printf ("%x\n", char_code
);
171 cuttop
= cutbottom
= cutleft
= cutright
= 0;
174 for (cuttop
= 0; cuttop
< glyph
->bitmap
.rows
; cuttop
++)
176 for (j
= 0; j
< glyph
->bitmap
.width
; j
++)
177 if (glyph
->bitmap
.buffer
[j
/ 8 + cuttop
* glyph
->bitmap
.pitch
]
178 & (1 << (7 - (j
& 7))))
180 if (j
!= glyph
->bitmap
.width
)
184 for (cutbottom
= glyph
->bitmap
.rows
- 1; cutbottom
>= 0; cutbottom
--)
186 for (j
= 0; j
< glyph
->bitmap
.width
; j
++)
187 if (glyph
->bitmap
.buffer
[j
/ 8 + cutbottom
* glyph
->bitmap
.pitch
]
188 & (1 << (7 - (j
& 7))))
190 if (j
!= glyph
->bitmap
.width
)
193 cutbottom
= glyph
->bitmap
.rows
- 1 - cutbottom
;
194 if (cutbottom
+ cuttop
>= glyph
->bitmap
.rows
)
197 for (cutleft
= 0; cutleft
< glyph
->bitmap
.width
; cutleft
++)
199 for (j
= 0; j
< glyph
->bitmap
.rows
; j
++)
200 if (glyph
->bitmap
.buffer
[cutleft
/ 8 + j
* glyph
->bitmap
.pitch
]
201 & (1 << (7 - (cutleft
& 7))))
203 if (j
!= glyph
->bitmap
.rows
)
206 for (cutright
= glyph
->bitmap
.width
- 1; cutright
>= 0; cutright
--)
208 for (j
= 0; j
< glyph
->bitmap
.rows
; j
++)
209 if (glyph
->bitmap
.buffer
[cutright
/ 8 + j
* glyph
->bitmap
.pitch
]
210 & (1 << (7 - (cutright
& 7))))
212 if (j
!= glyph
->bitmap
.rows
)
215 cutright
= glyph
->bitmap
.width
- 1 - cutright
;
216 if (cutright
+ cutleft
>= glyph
->bitmap
.width
)
220 width
= glyph
->bitmap
.width
- cutleft
- cutright
;
221 height
= glyph
->bitmap
.rows
- cutbottom
- cuttop
;
223 bitmap_size
= ((width
* height
+ 7) / 8);
224 glyph_info
= xmalloc (sizeof (struct grub_glyph_info
));
225 glyph_info
->bitmap
= xmalloc (bitmap_size
);
226 glyph_info
->bitmap_size
= bitmap_size
;
228 glyph_info
->next
= font_info
->glyphs_unsorted
;
229 font_info
->glyphs_unsorted
= glyph_info
;
230 font_info
->num_glyphs
++;
232 glyph_info
->char_code
= char_code
;
233 glyph_info
->width
= width
;
234 glyph_info
->height
= height
;
235 glyph_info
->x_ofs
= glyph
->bitmap_left
+ cutleft
;
236 glyph_info
->y_ofs
= glyph
->bitmap_top
- height
- cuttop
;
237 glyph_info
->device_width
= glyph
->metrics
.horiAdvance
/ 64;
239 if (width
> font_info
->max_width
)
240 font_info
->max_width
= width
;
242 if (height
> font_info
->max_height
)
243 font_info
->max_height
= height
;
245 if (glyph_info
->y_ofs
< font_info
->min_y
&& glyph_info
->y_ofs
> -font_info
->size
)
246 font_info
->min_y
= glyph_info
->y_ofs
;
248 if (glyph_info
->y_ofs
+ height
> font_info
->max_y
)
249 font_info
->max_y
= glyph_info
->y_ofs
+ height
;
252 data
= &glyph_info
->bitmap
[0] - 1;
253 for (j
= cuttop
; j
< height
+ cuttop
; j
++)
254 for (i
= cutleft
; i
< width
+ cutleft
; i
++)
255 add_pixel (&data
, &mask
,
256 glyph
->bitmap
.buffer
[i
/ 8 + j
* glyph
->bitmap
.pitch
] &
257 (1 << (7 - (i
& 7))));
260 struct glyph_replace
*subst_rightjoin
, *subst_leftjoin
, *subst_medijoin
;
264 struct glyph_replace
*next
;
265 grub_uint32_t from
, to
;
268 /* TODO: sort glyph_replace and use binary search if necessary. */
270 add_char (struct grub_font_info
*font_info
, FT_Face face
,
271 grub_uint32_t char_code
, int nocut
)
274 struct glyph_replace
*cur
;
276 glyph_idx
= FT_Get_Char_Index (face
, char_code
);
279 add_glyph (font_info
, glyph_idx
, face
, char_code
, nocut
);
280 for (cur
= subst_rightjoin
; cur
; cur
= cur
->next
)
281 if (cur
->from
== glyph_idx
)
283 add_glyph (font_info
, cur
->to
, face
,
284 char_code
| GRUB_FONT_CODE_RIGHT_JOINED
, nocut
);
287 if (!cur
&& char_code
>= GRUB_UNICODE_ARABIC_START
288 && char_code
< GRUB_UNICODE_ARABIC_END
)
291 for (i
= 0; grub_unicode_arabic_shapes
[i
].code
; i
++)
292 if (grub_unicode_arabic_shapes
[i
].code
== char_code
293 && grub_unicode_arabic_shapes
[i
].right_linked
)
296 idx2
= FT_Get_Char_Index (face
, grub_unicode_arabic_shapes
[i
]
299 add_glyph (font_info
, idx2
, face
,
300 char_code
| GRUB_FONT_CODE_RIGHT_JOINED
, nocut
);
306 for (cur
= subst_leftjoin
; cur
; cur
= cur
->next
)
307 if (cur
->from
== glyph_idx
)
309 add_glyph (font_info
, cur
->to
, face
,
310 char_code
| GRUB_FONT_CODE_LEFT_JOINED
, nocut
);
313 if (!cur
&& char_code
>= GRUB_UNICODE_ARABIC_START
314 && char_code
< GRUB_UNICODE_ARABIC_END
)
317 for (i
= 0; grub_unicode_arabic_shapes
[i
].code
; i
++)
318 if (grub_unicode_arabic_shapes
[i
].code
== char_code
319 && grub_unicode_arabic_shapes
[i
].left_linked
)
322 idx2
= FT_Get_Char_Index (face
, grub_unicode_arabic_shapes
[i
]
325 add_glyph (font_info
, idx2
, face
,
326 char_code
| GRUB_FONT_CODE_LEFT_JOINED
, nocut
);
331 for (cur
= subst_medijoin
; cur
; cur
= cur
->next
)
332 if (cur
->from
== glyph_idx
)
334 add_glyph (font_info
, cur
->to
, face
,
335 char_code
| GRUB_FONT_CODE_LEFT_JOINED
336 | GRUB_FONT_CODE_RIGHT_JOINED
, nocut
);
339 if (!cur
&& char_code
>= GRUB_UNICODE_ARABIC_START
340 && char_code
< GRUB_UNICODE_ARABIC_END
)
343 for (i
= 0; grub_unicode_arabic_shapes
[i
].code
; i
++)
344 if (grub_unicode_arabic_shapes
[i
].code
== char_code
345 && grub_unicode_arabic_shapes
[i
].both_linked
)
348 idx2
= FT_Get_Char_Index (face
, grub_unicode_arabic_shapes
[i
]
351 add_glyph (font_info
, idx2
, face
,
352 char_code
| GRUB_FONT_CODE_LEFT_JOINED
353 | GRUB_FONT_CODE_RIGHT_JOINED
, nocut
);
362 grub_uint32_t version
;
363 grub_uint16_t scripts_off
;
364 grub_uint16_t features_off
;
365 grub_uint16_t lookups_off
;
366 } __attribute__ ((packed
));
373 #define FEATURE_FINA 0x66696e61
374 #define FEATURE_INIT 0x696e6974
375 #define FEATURE_MEDI 0x6d656469
376 #define FEATURE_AALT 0x61616c74
377 #define FEATURE_LIGA 0x6c696761
378 #define FEATURE_RLIG 0x726c6967
379 grub_uint32_t feature_tag
;
380 grub_uint16_t offset
;
381 } __attribute__ ((packed
)) features
[0];
382 } __attribute__ ((packed
));
386 grub_uint16_t params
;
387 grub_uint16_t lookupcount
;
388 grub_uint16_t lookupindices
[0];
389 } __attribute__ ((packed
));
391 struct gsub_lookup_list
394 grub_uint16_t offsets
[0];
395 } __attribute__ ((packed
));
401 grub_uint16_t subtablecount
;
402 grub_uint16_t subtables
[0];
403 } __attribute__ ((packed
));
405 struct gsub_substitution
408 grub_uint16_t coverage_off
;
415 grub_uint16_t repl
[0];
418 } __attribute__ ((packed
));
420 struct gsub_coverage_list
424 grub_uint16_t glyphs
[0];
425 } __attribute__ ((packed
));
427 struct gsub_coverage_ranges
435 grub_uint16_t start_index
;
436 } __attribute__ ((packed
)) ranges
[0];
437 } __attribute__ ((packed
));
439 #define GSUB_SINGLE_SUBSTITUTION 1
441 #define GSUB_SUBSTITUTION_DELTA 1
442 #define GSUB_SUBSTITUTION_MAP 2
444 #define GSUB_COVERAGE_LIST 1
445 #define GSUB_COVERAGE_RANGE 2
447 #define GSUB_RTL_CHAR 1
450 add_subst (grub_uint32_t from
, grub_uint32_t to
, struct glyph_replace
**target
)
452 struct glyph_replace
*new = xmalloc (sizeof (*new));
460 process_cursive (struct gsub_feature
*feature
,
461 struct gsub_lookup_list
*lookups
,
462 grub_uint32_t feattag
)
466 struct glyph_replace
**target
;
467 struct gsub_substitution
*sub
;
469 auto inline void subst (grub_uint32_t glyph
);
470 void subst (grub_uint32_t glyph
)
472 grub_uint16_t substtype
;
473 substtype
= grub_be_to_cpu16 (sub
->type
);
475 if (substtype
== GSUB_SUBSTITUTION_DELTA
)
476 add_subst (glyph
, glyph
+ grub_be_to_cpu16 (sub
->delta
), target
);
477 else if (i
>= grub_be_to_cpu16 (sub
->count
))
478 printf (_("Out of range substitution (%d, %d)\n"), i
,
479 grub_be_to_cpu16 (sub
->count
));
481 add_subst (glyph
, grub_be_to_cpu16 (sub
->repl
[i
++]), target
);
484 for (j
= 0; j
< grub_be_to_cpu16 (feature
->lookupcount
); j
++)
486 int lookup_index
= grub_be_to_cpu16 (feature
->lookupindices
[j
]);
487 struct gsub_lookup
*lookup
;
488 if (lookup_index
>= grub_be_to_cpu16 (lookups
->count
))
490 /* TRANSLATORS: "lookup" is taken directly from font specifications
491 which are formulated as "Under condition X replace LOOKUP with
493 printf (_("Out of range lookup: %d\n"), lookup_index
);
496 lookup
= (struct gsub_lookup
*)
497 ((grub_uint8_t
*) lookups
498 + grub_be_to_cpu16 (lookups
->offsets
[lookup_index
]));
499 if (grub_be_to_cpu16 (lookup
->type
) != GSUB_SINGLE_SUBSTITUTION
)
501 printf (_("Unsupported substitution type: %d\n"),
502 grub_be_to_cpu16 (lookup
->type
));
505 if (grub_be_to_cpu16 (lookup
->flag
) & ~GSUB_RTL_CHAR
)
507 printf (_("Unsupported substitution flag: 0x%x\n"),
508 grub_be_to_cpu16 (lookup
->flag
));
513 if (grub_be_to_cpu16 (lookup
->flag
) & GSUB_RTL_CHAR
)
514 target
= &subst_leftjoin
;
516 target
= &subst_rightjoin
;
519 if (grub_be_to_cpu16 (lookup
->flag
) & GSUB_RTL_CHAR
)
520 target
= &subst_rightjoin
;
522 target
= &subst_leftjoin
;
525 target
= &subst_medijoin
;
528 for (k
= 0; k
< grub_be_to_cpu16 (lookup
->subtablecount
); k
++)
530 sub
= (struct gsub_substitution
*)
531 ((grub_uint8_t
*) lookup
+ grub_be_to_cpu16 (lookup
->subtables
[k
]));
532 grub_uint16_t substtype
;
533 substtype
= grub_be_to_cpu16 (sub
->type
);
534 if (substtype
!= GSUB_SUBSTITUTION_MAP
535 && substtype
!= GSUB_SUBSTITUTION_DELTA
)
537 printf (_("Unsupported substitution specification: %d\n"),
541 void *coverage
= (grub_uint8_t
*) sub
542 + grub_be_to_cpu16 (sub
->coverage_off
);
543 grub_uint32_t covertype
;
544 covertype
= grub_be_to_cpu16 (*(grub_uint16_t
* __attribute__ ((packed
))) coverage
);
546 if (covertype
== GSUB_COVERAGE_LIST
)
548 struct gsub_coverage_list
*cover
= coverage
;
550 for (l
= 0; l
< grub_be_to_cpu16 (cover
->count
); l
++)
551 subst (grub_be_to_cpu16 (cover
->glyphs
[l
]));
553 else if (covertype
== GSUB_COVERAGE_RANGE
)
555 struct gsub_coverage_ranges
*cover
= coverage
;
557 for (l
= 0; l
< grub_be_to_cpu16 (cover
->count
); l
++)
558 for (m
= grub_be_to_cpu16 (cover
->ranges
[l
].start
);
559 m
<= grub_be_to_cpu16 (cover
->ranges
[l
].end
); m
++)
563 /* TRANSLATORS: most font transformations apply only to
564 some glyphs. Those glyphs are described as "coverage".
565 There are 2 coverage specifications: list and range.
566 This warning is thrown when another coverage specification
568 printf (_("Unsupported coverage specification: %d\n"), covertype
);
574 add_font (struct grub_font_info
*font_info
, FT_Face face
, int nocut
)
576 struct gsub_header
*gsub
= NULL
;
577 FT_ULong gsub_len
= 0;
579 if (!FT_Load_Sfnt_Table (face
, TTAG_GSUB
, 0, NULL
, &gsub_len
))
581 gsub
= xmalloc (gsub_len
);
582 if (FT_Load_Sfnt_Table (face
, TTAG_GSUB
, 0, (void *) gsub
, &gsub_len
))
591 struct gsub_features
*features
592 = (struct gsub_features
*) (((grub_uint8_t
*) gsub
)
593 + grub_be_to_cpu16 (gsub
->features_off
));
594 struct gsub_lookup_list
*lookups
595 = (struct gsub_lookup_list
*) (((grub_uint8_t
*) gsub
)
596 + grub_be_to_cpu16 (gsub
->lookups_off
));
598 int nfeatures
= grub_be_to_cpu16 (features
->count
);
599 for (i
= 0; i
< nfeatures
; i
++)
601 struct gsub_feature
*feature
= (struct gsub_feature
*)
602 ((grub_uint8_t
*) features
603 + grub_be_to_cpu16 (features
->features
[i
].offset
));
604 grub_uint32_t feattag
605 = grub_be_to_cpu32 (features
->features
[i
].feature_tag
);
607 printf (_("WARNING: unsupported font feature parameters: %x\n"),
608 grub_be_to_cpu16 (feature
->params
));
611 /* Used for retrieving all possible variants. Useless in grub. */
615 /* FIXME: Add ligature support. */
620 /* Cursive form variants. */
624 process_cursive (feature
, lookups
, feattag
);
631 memcpy (str
, &features
->features
[i
].feature_tag
,
632 sizeof (features
->features
[i
].feature_tag
));
634 for (j
= 0; j
< 4; j
++)
635 if (!grub_isgraph (str
[j
]))
637 /* TRANSLATORS: It's gsub feature, not gsub font. */
638 printf (_("Unknown gsub font feature 0x%x (%s)\n"),
645 if (font_info
->num_range
)
650 for (i
= 0; i
< font_info
->num_range
; i
++)
651 for (j
= font_info
->ranges
[i
* 2]; j
<= font_info
->ranges
[i
* 2 + 1];
653 add_char (font_info
, face
, j
, nocut
);
657 grub_uint32_t char_code
, glyph_index
;
659 for (char_code
= FT_Get_First_Char (face
, &glyph_index
);
661 char_code
= FT_Get_Next_Char (face
, char_code
, &glyph_index
))
662 add_char (font_info
, face
, char_code
, nocut
);
667 write_string_section (const char *name
, const char *str
,
668 int *offset
, FILE *file
,
669 const char *filename
)
671 grub_uint32_t leng
, leng_be32
;
673 leng
= strlen (str
) + 1;
674 leng_be32
= grub_cpu_to_be32 (leng
);
676 grub_util_write_image (name
, 4, file
, filename
);
677 grub_util_write_image ((char *) &leng_be32
, 4, file
, filename
);
678 grub_util_write_image (str
, leng
, file
, filename
);
684 write_be16_section (const char *name
, grub_uint16_t data
, int* offset
,
685 FILE *file
, const char *filename
)
689 leng
= grub_cpu_to_be32 (2);
690 data
= grub_cpu_to_be16 (data
);
691 grub_util_write_image (name
, 4, file
, filename
);
692 grub_util_write_image ((char *) &leng
, 4, file
, filename
);
693 grub_util_write_image ((char *) &data
, 2, file
, filename
);
698 #pragma GCC diagnostic ignored "-Wunsafe-loop-optimizations"
701 print_glyphs (struct grub_font_info
*font_info
)
704 struct grub_glyph_info
*glyph
;
707 for (glyph
= font_info
->glyphs_sorted
, num
= 0; num
< font_info
->num_glyphs
;
710 int x
, y
, xmax
, xmin
, ymax
, ymin
;
711 grub_uint8_t
*bitmap
, mask
;
713 printf ("\nGlyph #%d, U+%04x\n", num
, glyph
->char_code
);
714 printf ("Width %d, Height %d, X offset %d, Y offset %d, Device width %d\n",
715 glyph
->width
, glyph
->height
, glyph
->x_ofs
, glyph
->y_ofs
,
716 glyph
->device_width
);
718 xmax
= glyph
->x_ofs
+ glyph
->width
;
719 if (xmax
< glyph
->device_width
)
720 xmax
= glyph
->device_width
;
726 ymax
= glyph
->y_ofs
+ glyph
->height
;
727 if (ymax
< font_info
->asce
)
728 ymax
= font_info
->asce
;
731 if (ymin
> - font_info
->desc
)
732 ymin
= - font_info
->desc
;
734 bitmap
= glyph
->bitmap
;
736 for (y
= ymax
- 1; y
> ymin
- 1; y
--)
741 for (x
= xmin
; x
< xmax
; x
++)
743 if ((x
>= glyph
->x_ofs
) &&
744 (x
< glyph
->x_ofs
+ glyph
->width
) &&
745 (y
>= glyph
->y_ofs
) &&
746 (y
< glyph
->y_ofs
+ glyph
->height
))
748 line
[line_pos
++] = (*bitmap
& mask
) ? '#' : '_';
757 (x
< glyph
->device_width
) &&
758 (y
>= - font_info
->desc
) &&
759 (y
< font_info
->asce
))
761 line
[line_pos
++] = ((x
== 0) || (y
== 0)) ? '+' : '.';
764 line
[line_pos
++] = '*';
767 printf ("%s\n", line
);
773 write_font_ascii_bitmap (struct grub_font_info
*font_info
, char *output_file
)
776 struct grub_glyph_info
*glyph
;
779 file
= fopen (output_file
, "wb");
781 grub_util_error (_("cannot write to `%s': %s"), output_file
,
785 for (glyph
= font_info
->glyphs_sorted
, num
= 0; num
< font_info
->num_glyphs
;
789 if (glyph
->width
!= 8 || glyph
->height
!= 16)
791 /* printf ("Width or height from glyph U+%04x not supported, skipping.\n", glyph->char_code); */
795 for (row
= 0; row
< glyph
->height
; row
++)
798 fwrite (&glyph
->bitmap
[row
], sizeof(glyph
->bitmap
[row
]), 1, file
);
800 fwrite (&correct_size
, 1, 1, file
);
807 write_font_width_spec (struct grub_font_info
*font_info
, char *output_file
)
810 struct grub_glyph_info
*glyph
;
813 out
= xmalloc (8192);
814 memset (out
, 0, 8192);
816 file
= fopen (output_file
, "wb");
818 grub_util_error (_("cannot write to `%s': %s"), output_file
,
821 for (glyph
= font_info
->glyphs_sorted
;
822 glyph
< font_info
->glyphs_sorted
+ font_info
->num_glyphs
; glyph
++)
823 if (glyph
->width
> 12)
824 out
[glyph
->char_code
>> 3] |= (1 << (glyph
->char_code
& 7));
826 fwrite (out
, 8192, 1, file
);
832 write_font_pf2 (struct grub_font_info
*font_info
, char *output_file
)
836 char style_name
[20], *font_name
;
838 struct grub_glyph_info
*cur
;
840 file
= fopen (output_file
, "wb");
842 grub_util_error (_("cannot write to `%s': %s"), output_file
,
847 leng
= grub_cpu_to_be32 (4);
848 grub_util_write_image (FONT_FORMAT_SECTION_NAMES_FILE
,
849 sizeof(FONT_FORMAT_SECTION_NAMES_FILE
) - 1, file
,
851 grub_util_write_image ((char *) &leng
, 4, file
, output_file
);
852 grub_util_write_image (FONT_FORMAT_PFF2_MAGIC
, 4, file
, output_file
);
855 if (! font_info
->name
)
856 font_info
->name
= "Unknown";
858 if (font_info
->flags
& GRUB_FONT_FLAG_BOLD
)
859 font_info
->style
|= FT_STYLE_FLAG_BOLD
;
862 if (font_info
->style
& FT_STYLE_FLAG_BOLD
)
863 strcpy (style_name
, " Bold");
865 if (font_info
->style
& FT_STYLE_FLAG_ITALIC
)
866 strcat (style_name
, " Italic");
869 strcpy (style_name
, " Regular");
871 font_name
= xasprintf ("%s %s %d", font_info
->name
, &style_name
[1],
874 write_string_section (FONT_FORMAT_SECTION_NAMES_FONT_NAME
,
875 font_name
, &offset
, file
, output_file
);
876 write_string_section (FONT_FORMAT_SECTION_NAMES_FAMILY
,
877 font_info
->name
, &offset
, file
, output_file
);
878 write_string_section (FONT_FORMAT_SECTION_NAMES_WEIGHT
,
879 (font_info
->style
& FT_STYLE_FLAG_BOLD
) ?
881 &offset
, file
, output_file
);
882 write_string_section (FONT_FORMAT_SECTION_NAMES_SLAN
,
883 (font_info
->style
& FT_STYLE_FLAG_ITALIC
) ?
885 &offset
, file
, output_file
);
887 write_be16_section (FONT_FORMAT_SECTION_NAMES_POINT_SIZE
,
888 font_info
->size
, &offset
, file
, output_file
);
889 write_be16_section (FONT_FORMAT_SECTION_NAMES_MAX_CHAR_WIDTH
,
890 font_info
->max_width
, &offset
, file
, output_file
);
891 write_be16_section (FONT_FORMAT_SECTION_NAMES_MAX_CHAR_HEIGHT
,
892 font_info
->max_height
, &offset
, file
, output_file
);
894 if (! font_info
->desc
)
896 if (font_info
->min_y
>= 0)
899 font_info
->desc
= - font_info
->min_y
;
902 if (! font_info
->asce
)
904 if (font_info
->max_y
<= 0)
907 font_info
->asce
= font_info
->max_y
;
910 write_be16_section (FONT_FORMAT_SECTION_NAMES_ASCENT
,
911 font_info
->asce
, &offset
, file
, output_file
);
912 write_be16_section (FONT_FORMAT_SECTION_NAMES_DESCENT
,
913 font_info
->desc
, &offset
, file
, output_file
);
915 if (font_verbosity
> 0)
917 printf ("Font name: %s\n", font_name
);
918 printf ("Max width: %d\n", font_info
->max_width
);
919 printf ("Max height: %d\n", font_info
->max_height
);
920 printf ("Font ascent: %d\n", font_info
->asce
);
921 printf ("Font descent: %d\n", font_info
->desc
);
924 if (font_verbosity
> 0)
925 printf ("Number of glyph: %d\n", font_info
->num_glyphs
);
927 leng
= grub_cpu_to_be32 (font_info
->num_glyphs
* 9);
928 grub_util_write_image (FONT_FORMAT_SECTION_NAMES_CHAR_INDEX
,
929 sizeof(FONT_FORMAT_SECTION_NAMES_CHAR_INDEX
) - 1,
931 grub_util_write_image ((char *) &leng
, 4, file
, output_file
);
932 offset
+= 8 + font_info
->num_glyphs
* 9 + 8;
934 for (cur
= font_info
->glyphs_sorted
;
935 cur
< font_info
->glyphs_sorted
+ font_info
->num_glyphs
; cur
++)
937 grub_uint32_t data32
;
939 data32
= grub_cpu_to_be32 (cur
->char_code
);
940 grub_util_write_image ((char *) &data32
, 4, file
, output_file
);
942 grub_util_write_image ((char *) &data8
, 1, file
, output_file
);
943 data32
= grub_cpu_to_be32 (offset
);
944 grub_util_write_image ((char *) &data32
, 4, file
, output_file
);
945 offset
+= 10 + cur
->bitmap_size
;
949 grub_util_write_image (FONT_FORMAT_SECTION_NAMES_DATA
,
950 sizeof(FONT_FORMAT_SECTION_NAMES_DATA
) - 1,
952 grub_util_write_image ((char *) &leng
, 4, file
, output_file
);
954 for (cur
= font_info
->glyphs_sorted
;
955 cur
< font_info
->glyphs_sorted
+ font_info
->num_glyphs
; cur
++)
958 data
= grub_cpu_to_be16 (cur
->width
);
959 grub_util_write_image ((char *) &data
, 2, file
, output_file
);
960 data
= grub_cpu_to_be16 (cur
->height
);
961 grub_util_write_image ((char *) &data
, 2, file
, output_file
);
962 data
= grub_cpu_to_be16 (cur
->x_ofs
);
963 grub_util_write_image ((char *) &data
, 2, file
, output_file
);
964 data
= grub_cpu_to_be16 (cur
->y_ofs
);
965 grub_util_write_image ((char *) &data
, 2, file
, output_file
);
966 data
= grub_cpu_to_be16 (cur
->device_width
);
967 grub_util_write_image ((char *) &data
, 2, file
, output_file
);
968 grub_util_write_image ((char *) &cur
->bitmap
[0], cur
->bitmap_size
,
975 static struct argp_option options
[] = {
976 {"output", 'o', N_("FILE"), 0, N_("save output in FILE [required]"), 0},
977 /* TRANSLATORS: bitmaps are images like e.g. in JPEG. */
978 {"ascii-bitmaps", 0x102, 0, 0, N_("save only the ASCII bitmaps"), 0},
979 {"width-spec", 0x103, 0, 0,
980 /* TRANSLATORS: this refers to creating a file containing the width of
981 every glyph but not the glyphs themselves. */
982 N_("create width summary file"), 0},
983 {"index", 'i', N_("NUM"), 0,
984 /* TRANSLATORS: some font files may have multiple faces (fonts).
985 This option is used to chose among them, the first face being '0'.
987 N_("select face index"), 0},
988 {"range", 'r', N_("FROM-TO[,FROM-TO]"), 0,
989 /* TRANSLATORS: It refers to the range of characters in font. */
990 N_("set font range"), 0},
991 {"name", 'n', N_("NAME"), 0,
992 /* TRANSLATORS: "family name" for font is just a generic name without suffix
994 N_("set font family name"), 0},
995 {"size", 's', N_("SIZE"), 0, N_("set font size"), 0},
996 {"desc", 'd', N_("NUM"), 0, N_("set font descent"), 0},
997 {"asce", 'c', N_("NUM"), 0, N_("set font ascent"), 0},
998 {"bold", 'b', 0, 0, N_("convert to bold font"), 0},
999 {"force-autohint", 'a', 0, 0, N_("force autohint"), 0},
1000 {"no-hinting", 0x101, 0, 0, N_("disable hinting"), 0},
1001 {"no-bitmap", 0x100, 0, 0,
1002 /* TRANSLATORS: some fonts contain bitmap rendering for
1003 some sizes. This option forces rerendering even if
1004 pre-rendered bitmap is available.
1006 N_("ignore bitmap strikes when loading"), 0},
1007 {"verbose", 'v', 0, 0, N_("print verbose messages."), 0},
1008 { 0, 0, 0, 0, 0, 0 }
1013 struct grub_font_info font_info
;
1020 enum file_formats file_format
;
1024 argp_parser (int key
, char *arg
, struct argp_state
*state
)
1026 /* Get the input argument from argp_parse, which we
1027 know is a pointer to our arguments structure. */
1028 struct arguments
*arguments
= state
->input
;
1033 arguments
->font_info
.flags
|= GRUB_FONT_FLAG_BOLD
;
1037 arguments
->font_info
.flags
|= GRUB_FONT_FLAG_NOBITMAP
;
1041 arguments
->font_info
.flags
|= GRUB_FONT_FLAG_NOHINTING
;
1045 arguments
->font_info
.flags
|= GRUB_FONT_FLAG_FORCEHINT
;
1049 arguments
->output_file
= xstrdup (arg
);
1053 arguments
->font_info
.name
= xstrdup (arg
);
1057 arguments
->font_index
= strtoul (arg
, NULL
, 0);
1061 arguments
->font_size
= strtoul (arg
, NULL
, 0);
1072 a
= strtoul (p
, &p
, 0);
1074 /* TRANSLATORS: It refers to the range of characters in font. */
1075 grub_util_error ("%s", _("invalid font range"));
1076 b
= strtoul (p
+ 1, &p
, 0);
1077 if ((arguments
->font_info
.num_range
1078 & (GRUB_FONT_RANGE_BLOCK
- 1)) == 0)
1079 arguments
->font_info
.ranges
= xrealloc (arguments
->font_info
.ranges
,
1080 (arguments
->font_info
.num_range
+
1081 GRUB_FONT_RANGE_BLOCK
) *
1082 sizeof (grub_uint32_t
) * 2);
1084 arguments
->font_info
.ranges
[arguments
->font_info
.num_range
* 2] = a
;
1085 arguments
->font_info
.ranges
[arguments
->font_info
.num_range
* 2 + 1] = b
;
1086 arguments
->font_info
.num_range
++;
1091 grub_util_error ("%s", _("invalid font range"));
1101 arguments
->font_info
.desc
= strtoul (arg
, NULL
, 0);
1105 arguments
->font_info
.asce
= strtoul (arg
, NULL
, 0);
1113 arguments
->file_format
= ASCII_BITMAPS
;
1117 arguments
->file_format
= WIDTH_SPEC
;
1121 assert (arguments
->nfiles
< arguments
->files_max
);
1122 arguments
->files
[arguments
->nfiles
++] = xstrdup(arg
);
1126 return ARGP_ERR_UNKNOWN
;
1131 static struct argp argp
= {
1132 options
, argp_parser
, N_("[OPTIONS] FONT_FILES"),
1133 N_("Convert common font file formats into PF2"),
1138 main (int argc
, char *argv
[])
1141 struct arguments arguments
;
1143 set_program_name (argv
[0]);
1145 grub_util_init_nls ();
1147 memset (&arguments
, 0, sizeof (struct arguments
));
1148 arguments
.file_format
= PF2
;
1149 arguments
.files_max
= argc
+ 1;
1150 arguments
.files
= xmalloc ((arguments
.files_max
+ 1)
1151 * sizeof (arguments
.files
[0]));
1152 memset (arguments
.files
, 0, (arguments
.files_max
+ 1)
1153 * sizeof (arguments
.files
[0]));
1155 if (argp_parse (&argp
, argc
, argv
, 0, 0, &arguments
) != 0)
1157 fprintf (stderr
, "%s", _("Error in parsing command line arguments\n"));
1161 if (arguments
.file_format
== ASCII_BITMAPS
1162 && arguments
.font_info
.num_range
> 0)
1164 grub_util_error ("%s", _("Option --ascii-bitmaps doesn't accept ranges (it always uses ASCII)."));
1167 else if (arguments
.file_format
== ASCII_BITMAPS
)
1169 arguments
.font_info
.ranges
= xrealloc (arguments
.font_info
.ranges
,
1170 GRUB_FONT_RANGE_BLOCK
*
1171 sizeof (grub_uint32_t
) * 2);
1173 arguments
.font_info
.ranges
[0] = (grub_uint32_t
) 0x00;
1174 arguments
.font_info
.ranges
[1] = (grub_uint32_t
) 0x7f;
1175 arguments
.font_info
.num_range
= 1;
1178 if (! arguments
.output_file
)
1179 grub_util_error ("%s", _("output file must be specified"));
1181 if (FT_Init_FreeType (&ft_lib
))
1182 grub_util_error ("%s", _("FT_Init_FreeType fails"));
1186 for (i
= 0; i
< arguments
.nfiles
; i
++)
1192 err
= FT_New_Face (ft_lib
, arguments
.files
[i
],
1193 arguments
.font_index
, &ft_face
);
1196 grub_printf (_("can't open file %s, index %d: error %d"),
1198 arguments
.font_index
, err
);
1199 if (err
> 0 && err
< (signed) ARRAY_SIZE (ft_errmsgs
))
1200 printf (": %s\n", ft_errmsgs
[err
]);
1207 if ((! arguments
.font_info
.name
) && (ft_face
->family_name
))
1208 arguments
.font_info
.name
= xstrdup (ft_face
->family_name
);
1210 size
= arguments
.font_size
;
1213 if ((ft_face
->face_flags
& FT_FACE_FLAG_SCALABLE
) ||
1214 (! ft_face
->num_fixed_sizes
))
1215 size
= GRUB_FONT_DEFAULT_SIZE
;
1217 size
= ft_face
->available_sizes
[0].height
;
1220 arguments
.font_info
.style
= ft_face
->style_flags
;
1221 arguments
.font_info
.size
= size
;
1223 if (FT_Set_Pixel_Sizes (ft_face
, size
, size
))
1224 grub_util_error (_("can't set %dx%d font size"),
1226 add_font (&arguments
.font_info
, ft_face
, arguments
.file_format
!= PF2
);
1227 FT_Done_Face (ft_face
);
1231 FT_Done_FreeType (ft_lib
);
1235 struct grub_glyph_info
*tmp
, *cur
;
1238 memset (counter
, 0, sizeof (counter
));
1240 for (cur
= arguments
.font_info
.glyphs_unsorted
; cur
; cur
= cur
->next
)
1241 counter
[(cur
->char_code
& 0xffff) + 1]++;
1242 for (i
= 0; i
< 0x10000; i
++)
1243 counter
[i
+1] += counter
[i
];
1244 tmp
= xmalloc (arguments
.font_info
.num_glyphs
1246 for (cur
= arguments
.font_info
.glyphs_unsorted
; cur
; cur
= cur
->next
)
1247 tmp
[counter
[(cur
->char_code
& 0xffff)]++] = *cur
;
1249 memset (counter
, 0, sizeof (counter
));
1251 for (cur
= tmp
; cur
< tmp
+ arguments
.font_info
.num_glyphs
; cur
++)
1252 counter
[((cur
->char_code
& 0xffff0000) >> 16) + 1]++;
1253 for (i
= 0; i
< 0x10000; i
++)
1254 counter
[i
+1] += counter
[i
];
1255 arguments
.font_info
.glyphs_sorted
= xmalloc (arguments
.font_info
.num_glyphs
1256 * sizeof (arguments
.font_info
.glyphs_sorted
[0]));
1257 for (cur
= tmp
; cur
< tmp
+ arguments
.font_info
.num_glyphs
; cur
++)
1258 arguments
.font_info
.glyphs_sorted
[counter
[(cur
->char_code
& 0xffff0000)
1263 switch (arguments
.file_format
)
1266 write_font_pf2 (&arguments
.font_info
, arguments
.output_file
);
1270 write_font_ascii_bitmap (&arguments
.font_info
, arguments
.output_file
);
1274 write_font_width_spec (&arguments
.font_info
, arguments
.output_file
);
1278 if (font_verbosity
> 1)
1279 print_glyphs (&arguments
.font_info
);
1283 for (i
= 0; i
< arguments
.nfiles
; i
++)
1284 free (arguments
.files
[i
]);