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>
43 #include FT_FREETYPE_H
44 #include FT_TRUETYPE_TAGS_H
45 #include FT_TRUETYPE_TABLES_H
46 #include FT_SYNTHESIS_H
49 #define FT_ERROR_START_LIST const char *ft_errmsgs[] = {
50 #define FT_ERRORDEF(e, v, s) [e] = s,
51 #define FT_ERROR_END_LIST };
59 #define grub_util_fopen fopen
62 #define GRUB_FONT_DEFAULT_SIZE 16
64 #define GRUB_FONT_RANGE_BLOCK 1024
66 struct grub_glyph_info
68 struct grub_glyph_info
*next
;
69 grub_uint32_t char_code
;
86 GRUB_FONT_FLAG_BOLD
= 1,
87 GRUB_FONT_FLAG_NOBITMAP
= 2,
88 GRUB_FONT_FLAG_NOHINTING
= 4,
89 GRUB_FONT_FLAG_FORCEHINT
= 8
105 grub_uint32_t
*ranges
;
106 struct grub_glyph_info
*glyphs_unsorted
;
107 struct grub_glyph_info
*glyphs_sorted
;
111 static int font_verbosity
;
114 add_pixel (grub_uint8_t
**data
, int *mask
, int not_blank
)
130 add_glyph (struct grub_font_info
*font_info
, FT_UInt glyph_idx
, FT_Face face
,
131 grub_uint32_t char_code
, int nocut
)
133 struct grub_glyph_info
*glyph_info
;
135 int cuttop
, cutbottom
, cutleft
, cutright
;
137 int mask
, i
, j
, bitmap_size
;
139 int flag
= FT_LOAD_RENDER
| FT_LOAD_MONOCHROME
;
142 if (font_info
->flags
& GRUB_FONT_FLAG_NOBITMAP
)
143 flag
|= FT_LOAD_NO_BITMAP
;
145 if (font_info
->flags
& GRUB_FONT_FLAG_NOHINTING
)
146 flag
|= FT_LOAD_NO_HINTING
;
147 else if (font_info
->flags
& GRUB_FONT_FLAG_FORCEHINT
)
148 flag
|= FT_LOAD_FORCE_AUTOHINT
;
150 err
= FT_Load_Glyph (face
, glyph_idx
, flag
);
153 printf (_("Freetype Error %d loading glyph 0x%x for U+0x%x%s"),
154 err
, glyph_idx
, char_code
& GRUB_FONT_CODE_CHAR_MASK
,
155 char_code
& GRUB_FONT_CODE_RIGHT_JOINED
156 /* TRANSLATORS: These qualifiers are used for cursive typography,
157 mainly Arabic. Note that the terms refer to the visual position
158 and not logical order and if used in left-to-right script then
159 leftmost is initial but with right-to-left script like Arabic
160 rightmost is the initial. */
161 ? ((char_code
& GRUB_FONT_CODE_LEFT_JOINED
) ? _(" (medial)"):
163 : ((char_code
& GRUB_FONT_CODE_LEFT_JOINED
) ? _(" (rightmost)"):
166 if (err
> 0 && err
< (signed) ARRAY_SIZE (ft_errmsgs
))
167 printf (": %s\n", ft_errmsgs
[err
]);
175 if (font_info
->flags
& GRUB_FONT_FLAG_BOLD
)
176 FT_GlyphSlot_Embolden (glyph
);
179 printf ("%x\n", char_code
);
182 cuttop
= cutbottom
= cutleft
= cutright
= 0;
185 for (cuttop
= 0; cuttop
< glyph
->bitmap
.rows
; cuttop
++)
187 for (j
= 0; j
< glyph
->bitmap
.width
; j
++)
188 if (glyph
->bitmap
.buffer
[j
/ 8 + cuttop
* glyph
->bitmap
.pitch
]
189 & (1 << (7 - (j
& 7))))
191 if (j
!= glyph
->bitmap
.width
)
195 for (cutbottom
= glyph
->bitmap
.rows
- 1; cutbottom
>= 0; cutbottom
--)
197 for (j
= 0; j
< glyph
->bitmap
.width
; j
++)
198 if (glyph
->bitmap
.buffer
[j
/ 8 + cutbottom
* glyph
->bitmap
.pitch
]
199 & (1 << (7 - (j
& 7))))
201 if (j
!= glyph
->bitmap
.width
)
204 cutbottom
= glyph
->bitmap
.rows
- 1 - cutbottom
;
205 if (cutbottom
+ cuttop
>= glyph
->bitmap
.rows
)
208 for (cutleft
= 0; cutleft
< glyph
->bitmap
.width
; cutleft
++)
210 for (j
= 0; j
< glyph
->bitmap
.rows
; j
++)
211 if (glyph
->bitmap
.buffer
[cutleft
/ 8 + j
* glyph
->bitmap
.pitch
]
212 & (1 << (7 - (cutleft
& 7))))
214 if (j
!= glyph
->bitmap
.rows
)
217 for (cutright
= glyph
->bitmap
.width
- 1; cutright
>= 0; cutright
--)
219 for (j
= 0; j
< glyph
->bitmap
.rows
; j
++)
220 if (glyph
->bitmap
.buffer
[cutright
/ 8 + j
* glyph
->bitmap
.pitch
]
221 & (1 << (7 - (cutright
& 7))))
223 if (j
!= glyph
->bitmap
.rows
)
226 cutright
= glyph
->bitmap
.width
- 1 - cutright
;
227 if (cutright
+ cutleft
>= glyph
->bitmap
.width
)
231 width
= glyph
->bitmap
.width
- cutleft
- cutright
;
232 height
= glyph
->bitmap
.rows
- cutbottom
- cuttop
;
234 bitmap_size
= ((width
* height
+ 7) / 8);
235 glyph_info
= xmalloc (sizeof (struct grub_glyph_info
));
236 glyph_info
->bitmap
= xmalloc (bitmap_size
);
237 glyph_info
->bitmap_size
= bitmap_size
;
239 glyph_info
->next
= font_info
->glyphs_unsorted
;
240 font_info
->glyphs_unsorted
= glyph_info
;
241 font_info
->num_glyphs
++;
243 glyph_info
->char_code
= char_code
;
244 glyph_info
->width
= width
;
245 glyph_info
->height
= height
;
246 glyph_info
->x_ofs
= glyph
->bitmap_left
+ cutleft
;
247 glyph_info
->y_ofs
= glyph
->bitmap_top
- height
- cuttop
;
248 glyph_info
->device_width
= glyph
->metrics
.horiAdvance
/ 64;
250 if (width
> font_info
->max_width
)
251 font_info
->max_width
= width
;
253 if (height
> font_info
->max_height
)
254 font_info
->max_height
= height
;
256 if (glyph_info
->y_ofs
< font_info
->min_y
&& glyph_info
->y_ofs
> -font_info
->size
)
257 font_info
->min_y
= glyph_info
->y_ofs
;
259 if (glyph_info
->y_ofs
+ height
> font_info
->max_y
)
260 font_info
->max_y
= glyph_info
->y_ofs
+ height
;
263 data
= &glyph_info
->bitmap
[0] - 1;
264 for (j
= cuttop
; j
< height
+ cuttop
; j
++)
265 for (i
= cutleft
; i
< width
+ cutleft
; i
++)
266 add_pixel (&data
, &mask
,
267 glyph
->bitmap
.buffer
[i
/ 8 + j
* glyph
->bitmap
.pitch
] &
268 (1 << (7 - (i
& 7))));
271 struct glyph_replace
*subst_rightjoin
, *subst_leftjoin
, *subst_medijoin
;
275 struct glyph_replace
*next
;
276 grub_uint32_t from
, to
;
279 /* TODO: sort glyph_replace and use binary search if necessary. */
281 add_char (struct grub_font_info
*font_info
, FT_Face face
,
282 grub_uint32_t char_code
, int nocut
)
285 struct glyph_replace
*cur
;
287 glyph_idx
= FT_Get_Char_Index (face
, char_code
);
290 add_glyph (font_info
, glyph_idx
, face
, char_code
, nocut
);
291 for (cur
= subst_rightjoin
; cur
; cur
= cur
->next
)
292 if (cur
->from
== glyph_idx
)
294 add_glyph (font_info
, cur
->to
, face
,
295 char_code
| GRUB_FONT_CODE_RIGHT_JOINED
, nocut
);
298 if (!cur
&& char_code
>= GRUB_UNICODE_ARABIC_START
299 && char_code
< GRUB_UNICODE_ARABIC_END
)
302 for (i
= 0; grub_unicode_arabic_shapes
[i
].code
; i
++)
303 if (grub_unicode_arabic_shapes
[i
].code
== char_code
304 && grub_unicode_arabic_shapes
[i
].right_linked
)
307 idx2
= FT_Get_Char_Index (face
, grub_unicode_arabic_shapes
[i
]
310 add_glyph (font_info
, idx2
, face
,
311 char_code
| GRUB_FONT_CODE_RIGHT_JOINED
, nocut
);
317 for (cur
= subst_leftjoin
; cur
; cur
= cur
->next
)
318 if (cur
->from
== glyph_idx
)
320 add_glyph (font_info
, cur
->to
, face
,
321 char_code
| GRUB_FONT_CODE_LEFT_JOINED
, nocut
);
324 if (!cur
&& char_code
>= GRUB_UNICODE_ARABIC_START
325 && char_code
< GRUB_UNICODE_ARABIC_END
)
328 for (i
= 0; grub_unicode_arabic_shapes
[i
].code
; i
++)
329 if (grub_unicode_arabic_shapes
[i
].code
== char_code
330 && grub_unicode_arabic_shapes
[i
].left_linked
)
333 idx2
= FT_Get_Char_Index (face
, grub_unicode_arabic_shapes
[i
]
336 add_glyph (font_info
, idx2
, face
,
337 char_code
| GRUB_FONT_CODE_LEFT_JOINED
, nocut
);
342 for (cur
= subst_medijoin
; cur
; cur
= cur
->next
)
343 if (cur
->from
== glyph_idx
)
345 add_glyph (font_info
, cur
->to
, face
,
346 char_code
| GRUB_FONT_CODE_LEFT_JOINED
347 | GRUB_FONT_CODE_RIGHT_JOINED
, nocut
);
350 if (!cur
&& char_code
>= GRUB_UNICODE_ARABIC_START
351 && char_code
< GRUB_UNICODE_ARABIC_END
)
354 for (i
= 0; grub_unicode_arabic_shapes
[i
].code
; i
++)
355 if (grub_unicode_arabic_shapes
[i
].code
== char_code
356 && grub_unicode_arabic_shapes
[i
].both_linked
)
359 idx2
= FT_Get_Char_Index (face
, grub_unicode_arabic_shapes
[i
]
362 add_glyph (font_info
, idx2
, face
,
363 char_code
| GRUB_FONT_CODE_LEFT_JOINED
364 | GRUB_FONT_CODE_RIGHT_JOINED
, nocut
);
373 grub_uint32_t version
;
374 grub_uint16_t scripts_off
;
375 grub_uint16_t features_off
;
376 grub_uint16_t lookups_off
;
384 #define FEATURE_FINA 0x66696e61
385 #define FEATURE_INIT 0x696e6974
386 #define FEATURE_MEDI 0x6d656469
387 #define FEATURE_AALT 0x61616c74
388 #define FEATURE_LIGA 0x6c696761
389 #define FEATURE_RLIG 0x726c6967
390 grub_uint32_t feature_tag
;
391 grub_uint16_t offset
;
392 } GRUB_PACKED features
[0];
397 grub_uint16_t params
;
398 grub_uint16_t lookupcount
;
399 grub_uint16_t lookupindices
[0];
402 struct gsub_lookup_list
405 grub_uint16_t offsets
[0];
412 grub_uint16_t subtablecount
;
413 grub_uint16_t subtables
[0];
416 struct gsub_substitution
419 grub_uint16_t coverage_off
;
426 grub_uint16_t repl
[0];
431 struct gsub_coverage_list
435 grub_uint16_t glyphs
[0];
438 struct gsub_coverage_ranges
446 grub_uint16_t start_index
;
447 } GRUB_PACKED ranges
[0];
450 #define GSUB_SINGLE_SUBSTITUTION 1
452 #define GSUB_SUBSTITUTION_DELTA 1
453 #define GSUB_SUBSTITUTION_MAP 2
455 #define GSUB_COVERAGE_LIST 1
456 #define GSUB_COVERAGE_RANGE 2
458 #define GSUB_RTL_CHAR 1
461 add_subst (grub_uint32_t from
, grub_uint32_t to
, struct glyph_replace
**target
)
463 struct glyph_replace
*new = xmalloc (sizeof (*new));
471 subst (const struct gsub_substitution
*sub
, grub_uint32_t glyph
,
472 struct glyph_replace
**target
, int *i
)
474 grub_uint16_t substtype
;
475 substtype
= grub_be_to_cpu16 (sub
->type
);
477 if (substtype
== GSUB_SUBSTITUTION_DELTA
)
478 add_subst (glyph
, glyph
+ grub_be_to_cpu16 (sub
->delta
), target
);
479 else if (*i
>= grub_be_to_cpu16 (sub
->count
))
480 printf (_("Out of range substitution (%d, %d)\n"), *i
,
481 grub_be_to_cpu16 (sub
->count
));
483 add_subst (glyph
, grub_be_to_cpu16 (sub
->repl
[(*i
)++]), target
);
487 process_cursive (struct gsub_feature
*feature
,
488 struct gsub_lookup_list
*lookups
,
489 grub_uint32_t feattag
)
493 struct glyph_replace
**target
= NULL
;
494 struct gsub_substitution
*sub
;
496 for (j
= 0; j
< grub_be_to_cpu16 (feature
->lookupcount
); j
++)
498 int lookup_index
= grub_be_to_cpu16 (feature
->lookupindices
[j
]);
499 struct gsub_lookup
*lookup
;
500 if (lookup_index
>= grub_be_to_cpu16 (lookups
->count
))
502 /* TRANSLATORS: "lookup" is taken directly from font specifications
503 which are formulated as "Under condition X replace LOOKUP with
505 printf (_("Out of range lookup: %d\n"), lookup_index
);
508 lookup
= (struct gsub_lookup
*)
509 ((grub_uint8_t
*) lookups
510 + grub_be_to_cpu16 (lookups
->offsets
[lookup_index
]));
511 if (grub_be_to_cpu16 (lookup
->type
) != GSUB_SINGLE_SUBSTITUTION
)
513 printf (_("Unsupported substitution type: %d\n"),
514 grub_be_to_cpu16 (lookup
->type
));
517 if (grub_be_to_cpu16 (lookup
->flag
) & ~GSUB_RTL_CHAR
)
519 printf (_("Unsupported substitution flag: 0x%x\n"),
520 grub_be_to_cpu16 (lookup
->flag
));
525 if (grub_be_to_cpu16 (lookup
->flag
) & GSUB_RTL_CHAR
)
526 target
= &subst_leftjoin
;
528 target
= &subst_rightjoin
;
531 if (grub_be_to_cpu16 (lookup
->flag
) & GSUB_RTL_CHAR
)
532 target
= &subst_rightjoin
;
534 target
= &subst_leftjoin
;
537 target
= &subst_medijoin
;
540 for (k
= 0; k
< grub_be_to_cpu16 (lookup
->subtablecount
); k
++)
542 sub
= (struct gsub_substitution
*)
543 ((grub_uint8_t
*) lookup
+ grub_be_to_cpu16 (lookup
->subtables
[k
]));
544 grub_uint16_t substtype
;
545 substtype
= grub_be_to_cpu16 (sub
->type
);
546 if (substtype
!= GSUB_SUBSTITUTION_MAP
547 && substtype
!= GSUB_SUBSTITUTION_DELTA
)
549 printf (_("Unsupported substitution specification: %d\n"),
553 void *coverage
= (grub_uint8_t
*) sub
554 + grub_be_to_cpu16 (sub
->coverage_off
);
555 grub_uint32_t covertype
;
556 covertype
= grub_be_to_cpu16 (grub_get_unaligned16 (coverage
));
558 if (covertype
== GSUB_COVERAGE_LIST
)
560 struct gsub_coverage_list
*cover
= coverage
;
562 for (l
= 0; l
< grub_be_to_cpu16 (cover
->count
); l
++)
563 subst (sub
, grub_be_to_cpu16 (cover
->glyphs
[l
]), target
, &i
);
565 else if (covertype
== GSUB_COVERAGE_RANGE
)
567 struct gsub_coverage_ranges
*cover
= coverage
;
569 for (l
= 0; l
< grub_be_to_cpu16 (cover
->count
); l
++)
570 for (m
= grub_be_to_cpu16 (cover
->ranges
[l
].start
);
571 m
<= grub_be_to_cpu16 (cover
->ranges
[l
].end
); m
++)
572 subst (sub
, m
, target
, &i
);
575 /* TRANSLATORS: most font transformations apply only to
576 some glyphs. Those glyphs are described as "coverage".
577 There are 2 coverage specifications: list and range.
578 This warning is thrown when another coverage specification
580 printf (_("Unsupported coverage specification: %d\n"), covertype
);
586 add_font (struct grub_font_info
*font_info
, FT_Face face
, int nocut
)
588 struct gsub_header
*gsub
= NULL
;
589 FT_ULong gsub_len
= 0;
591 if (!FT_Load_Sfnt_Table (face
, TTAG_GSUB
, 0, NULL
, &gsub_len
))
593 gsub
= xmalloc (gsub_len
);
594 if (FT_Load_Sfnt_Table (face
, TTAG_GSUB
, 0, (void *) gsub
, &gsub_len
))
603 struct gsub_features
*features
604 = (struct gsub_features
*) (((grub_uint8_t
*) gsub
)
605 + grub_be_to_cpu16 (gsub
->features_off
));
606 struct gsub_lookup_list
*lookups
607 = (struct gsub_lookup_list
*) (((grub_uint8_t
*) gsub
)
608 + grub_be_to_cpu16 (gsub
->lookups_off
));
610 int nfeatures
= grub_be_to_cpu16 (features
->count
);
611 for (i
= 0; i
< nfeatures
; i
++)
613 struct gsub_feature
*feature
= (struct gsub_feature
*)
614 ((grub_uint8_t
*) features
615 + grub_be_to_cpu16 (features
->features
[i
].offset
));
616 grub_uint32_t feattag
617 = grub_be_to_cpu32 (features
->features
[i
].feature_tag
);
619 printf (_("WARNING: unsupported font feature parameters: %x\n"),
620 grub_be_to_cpu16 (feature
->params
));
623 /* Used for retrieving all possible variants. Useless in grub. */
627 /* FIXME: Add ligature support. */
632 /* Cursive form variants. */
636 process_cursive (feature
, lookups
, feattag
);
643 memcpy (str
, &features
->features
[i
].feature_tag
,
644 sizeof (features
->features
[i
].feature_tag
));
646 for (j
= 0; j
< 4; j
++)
647 if (!grub_isgraph (str
[j
]))
649 /* TRANSLATORS: It's gsub feature, not gsub font. */
650 printf (_("Unknown gsub font feature 0x%x (%s)\n"),
657 if (font_info
->num_range
)
662 for (i
= 0; i
< font_info
->num_range
; i
++)
663 for (j
= font_info
->ranges
[i
* 2]; j
<= font_info
->ranges
[i
* 2 + 1];
665 add_char (font_info
, face
, j
, nocut
);
669 grub_uint32_t char_code
, glyph_index
;
671 for (char_code
= FT_Get_First_Char (face
, &glyph_index
);
673 char_code
= FT_Get_Next_Char (face
, char_code
, &glyph_index
))
674 add_char (font_info
, face
, char_code
, nocut
);
679 write_string_section (const char *name
, const char *str
,
680 int *offset
, FILE *file
,
681 const char *filename
)
683 grub_uint32_t leng
, leng_be32
;
685 leng
= strlen (str
) + 1;
686 leng_be32
= grub_cpu_to_be32 (leng
);
688 grub_util_write_image (name
, 4, file
, filename
);
689 grub_util_write_image ((char *) &leng_be32
, 4, file
, filename
);
690 grub_util_write_image (str
, leng
, file
, filename
);
696 write_be16_section (const char *name
, grub_uint16_t data
, int* offset
,
697 FILE *file
, const char *filename
)
701 leng
= grub_cpu_to_be32 (2);
702 data
= grub_cpu_to_be16 (data
);
703 grub_util_write_image (name
, 4, file
, filename
);
704 grub_util_write_image ((char *) &leng
, 4, file
, filename
);
705 grub_util_write_image ((char *) &data
, 2, file
, filename
);
711 print_glyphs (struct grub_font_info
*font_info
)
714 struct grub_glyph_info
*glyph
;
717 for (glyph
= font_info
->glyphs_sorted
, num
= 0; num
< font_info
->num_glyphs
;
720 int x
, y
, xmax
, xmin
, ymax
, ymin
;
721 grub_uint8_t
*bitmap
, mask
;
723 printf ("\nGlyph #%d, U+%04x\n", num
, glyph
->char_code
);
724 printf ("Width %d, Height %d, X offset %d, Y offset %d, Device width %d\n",
725 glyph
->width
, glyph
->height
, glyph
->x_ofs
, glyph
->y_ofs
,
726 glyph
->device_width
);
728 xmax
= glyph
->x_ofs
+ glyph
->width
;
729 if (xmax
< glyph
->device_width
)
730 xmax
= glyph
->device_width
;
736 ymax
= glyph
->y_ofs
+ glyph
->height
;
737 if (ymax
< font_info
->asce
)
738 ymax
= font_info
->asce
;
741 if (ymin
> - font_info
->desc
)
742 ymin
= - font_info
->desc
;
744 bitmap
= glyph
->bitmap
;
746 for (y
= ymax
- 1; y
> ymin
- 1; y
--)
751 for (x
= xmin
; x
< xmax
; x
++)
753 if ((x
>= glyph
->x_ofs
) &&
754 (x
< glyph
->x_ofs
+ glyph
->width
) &&
755 (y
>= glyph
->y_ofs
) &&
756 (y
< glyph
->y_ofs
+ glyph
->height
))
758 line
[line_pos
++] = (*bitmap
& mask
) ? '#' : '_';
767 (x
< glyph
->device_width
) &&
768 (y
>= - font_info
->desc
) &&
769 (y
< font_info
->asce
))
771 line
[line_pos
++] = ((x
== 0) || (y
== 0)) ? '+' : '.';
774 line
[line_pos
++] = '*';
777 printf ("%s\n", line
);
783 write_font_pf2 (struct grub_font_info
*font_info
, char *output_file
)
787 char style_name
[20], *font_name
, *ptr
;
789 struct grub_glyph_info
*cur
;
791 file
= grub_util_fopen (output_file
, "wb");
793 grub_util_error (_("cannot write to `%s': %s"), output_file
,
798 leng
= grub_cpu_to_be32 (4);
799 grub_util_write_image (FONT_FORMAT_SECTION_NAMES_FILE
,
800 sizeof(FONT_FORMAT_SECTION_NAMES_FILE
) - 1, file
,
802 grub_util_write_image ((char *) &leng
, 4, file
, output_file
);
803 grub_util_write_image (FONT_FORMAT_PFF2_MAGIC
, 4, file
, output_file
);
806 if (! font_info
->name
)
807 font_info
->name
= "Unknown";
809 if (font_info
->flags
& GRUB_FONT_FLAG_BOLD
)
810 font_info
->style
|= FT_STYLE_FLAG_BOLD
;
813 if (font_info
->style
& FT_STYLE_FLAG_BOLD
)
814 strcpy (style_name
, " Bold");
816 if (font_info
->style
& FT_STYLE_FLAG_ITALIC
)
817 strcat (style_name
, " Italic");
820 strcpy (style_name
, " Regular");
822 font_name
= xmalloc (strlen (font_info
->name
) + strlen (&style_name
[1])
824 ptr
= grub_stpcpy (font_name
, font_info
->name
);
826 ptr
= grub_stpcpy (ptr
, &style_name
[1]);
828 snprintf (ptr
, 20, "%d", font_info
->size
);
830 write_string_section (FONT_FORMAT_SECTION_NAMES_FONT_NAME
,
831 font_name
, &offset
, file
, output_file
);
832 write_string_section (FONT_FORMAT_SECTION_NAMES_FAMILY
,
833 font_info
->name
, &offset
, file
, output_file
);
834 write_string_section (FONT_FORMAT_SECTION_NAMES_WEIGHT
,
835 (font_info
->style
& FT_STYLE_FLAG_BOLD
) ?
837 &offset
, file
, output_file
);
838 write_string_section (FONT_FORMAT_SECTION_NAMES_SLAN
,
839 (font_info
->style
& FT_STYLE_FLAG_ITALIC
) ?
841 &offset
, file
, output_file
);
843 write_be16_section (FONT_FORMAT_SECTION_NAMES_POINT_SIZE
,
844 font_info
->size
, &offset
, file
, output_file
);
845 write_be16_section (FONT_FORMAT_SECTION_NAMES_MAX_CHAR_WIDTH
,
846 font_info
->max_width
, &offset
, file
, output_file
);
847 write_be16_section (FONT_FORMAT_SECTION_NAMES_MAX_CHAR_HEIGHT
,
848 font_info
->max_height
, &offset
, file
, output_file
);
850 if (! font_info
->desc
)
852 if (font_info
->min_y
>= 0)
855 font_info
->desc
= - font_info
->min_y
;
858 if (! font_info
->asce
)
860 if (font_info
->max_y
<= 0)
863 font_info
->asce
= font_info
->max_y
;
866 write_be16_section (FONT_FORMAT_SECTION_NAMES_ASCENT
,
867 font_info
->asce
, &offset
, file
, output_file
);
868 write_be16_section (FONT_FORMAT_SECTION_NAMES_DESCENT
,
869 font_info
->desc
, &offset
, file
, output_file
);
871 if (font_verbosity
> 0)
873 printf ("Font name: %s\n", font_name
);
874 printf ("Max width: %d\n", font_info
->max_width
);
875 printf ("Max height: %d\n", font_info
->max_height
);
876 printf ("Font ascent: %d\n", font_info
->asce
);
877 printf ("Font descent: %d\n", font_info
->desc
);
880 if (font_verbosity
> 0)
881 printf ("Number of glyph: %d\n", font_info
->num_glyphs
);
883 leng
= grub_cpu_to_be32 (font_info
->num_glyphs
* 9);
884 grub_util_write_image (FONT_FORMAT_SECTION_NAMES_CHAR_INDEX
,
885 sizeof(FONT_FORMAT_SECTION_NAMES_CHAR_INDEX
) - 1,
887 grub_util_write_image ((char *) &leng
, 4, file
, output_file
);
888 offset
+= 8 + font_info
->num_glyphs
* 9 + 8;
890 for (cur
= font_info
->glyphs_sorted
;
891 cur
< font_info
->glyphs_sorted
+ font_info
->num_glyphs
; cur
++)
893 grub_uint32_t data32
;
895 data32
= grub_cpu_to_be32 (cur
->char_code
);
896 grub_util_write_image ((char *) &data32
, 4, file
, output_file
);
898 grub_util_write_image ((char *) &data8
, 1, file
, output_file
);
899 data32
= grub_cpu_to_be32 (offset
);
900 grub_util_write_image ((char *) &data32
, 4, file
, output_file
);
901 offset
+= 10 + cur
->bitmap_size
;
905 grub_util_write_image (FONT_FORMAT_SECTION_NAMES_DATA
,
906 sizeof(FONT_FORMAT_SECTION_NAMES_DATA
) - 1,
908 grub_util_write_image ((char *) &leng
, 4, file
, output_file
);
910 for (cur
= font_info
->glyphs_sorted
;
911 cur
< font_info
->glyphs_sorted
+ font_info
->num_glyphs
; cur
++)
914 data
= grub_cpu_to_be16 (cur
->width
);
915 grub_util_write_image ((char *) &data
, 2, file
, output_file
);
916 data
= grub_cpu_to_be16 (cur
->height
);
917 grub_util_write_image ((char *) &data
, 2, file
, output_file
);
918 data
= grub_cpu_to_be16 (cur
->x_ofs
);
919 grub_util_write_image ((char *) &data
, 2, file
, output_file
);
920 data
= grub_cpu_to_be16 (cur
->y_ofs
);
921 grub_util_write_image ((char *) &data
, 2, file
, output_file
);
922 data
= grub_cpu_to_be16 (cur
->device_width
);
923 grub_util_write_image ((char *) &data
, 2, file
, output_file
);
924 grub_util_write_image ((char *) &cur
->bitmap
[0], cur
->bitmap_size
,
932 static struct argp_option options
[] = {
933 {"output", 'o', N_("FILE"), 0, N_("save output in FILE [required]"), 0},
934 /* TRANSLATORS: bitmaps are images like e.g. in JPEG. */
935 {"index", 'i', N_("NUM"), 0,
936 /* TRANSLATORS: some font files may have multiple faces (fonts).
937 This option is used to chose among them, the first face being '0'.
939 N_("select face index"), 0},
940 {"range", 'r', N_("FROM-TO[,FROM-TO]"), 0,
941 /* TRANSLATORS: It refers to the range of characters in font. */
942 N_("set font range"), 0},
943 {"name", 'n', N_("NAME"), 0,
944 /* TRANSLATORS: "family name" for font is just a generic name without suffix
946 N_("set font family name"), 0},
947 {"size", 's', N_("SIZE"), 0, N_("set font size"), 0},
948 {"desc", 'd', N_("NUM"), 0, N_("set font descent"), 0},
949 {"asce", 'c', N_("NUM"), 0, N_("set font ascent"), 0},
950 {"bold", 'b', 0, 0, N_("convert to bold font"), 0},
951 {"force-autohint", 'a', 0, 0, N_("force autohint"), 0},
952 {"no-hinting", 0x101, 0, 0, N_("disable hinting"), 0},
953 {"no-bitmap", 0x100, 0, 0,
954 /* TRANSLATORS: some fonts contain bitmap rendering for
955 some sizes. This option forces rerendering even if
956 pre-rendered bitmap is available.
958 N_("ignore bitmap strikes when loading"), 0},
959 {"verbose", 'v', 0, 0, N_("print verbose messages."), 0},
962 #define my_argp_parse argp_parse
963 #define MY_ARGP_KEY_ARG ARGP_KEY_ARG
964 #define my_error_t error_t
965 #define MY_ARGP_ERR_UNKNOWN ARGP_ERR_UNKNOWN
966 #define my_argp_state argp_state
970 #define my_error_t int
971 #define MY_ARGP_ERR_UNKNOWN -1
972 #define MY_ARGP_KEY_ARG -1
973 #define my_argp_parse(a, argc, argv, b, c, st) my_argp_parse_real(argc, argv, st)
983 struct grub_font_info font_info
;
990 enum file_formats file_format
;
998 return v
=='o' || v
== 'i' || v
== 'r' || v
== 'n' || v
== 's'
999 || v
== 'd' || v
== 'c';
1005 argp_parser (int key
, char *arg
, struct my_argp_state
*state
)
1007 /* Get the input argument from argp_parse, which we
1008 know is a pointer to our arguments structure. */
1009 struct arguments
*arguments
= state
->input
;
1014 arguments
->font_info
.flags
|= GRUB_FONT_FLAG_BOLD
;
1018 arguments
->font_info
.flags
|= GRUB_FONT_FLAG_NOBITMAP
;
1022 arguments
->font_info
.flags
|= GRUB_FONT_FLAG_NOHINTING
;
1026 arguments
->font_info
.flags
|= GRUB_FONT_FLAG_FORCEHINT
;
1030 arguments
->output_file
= xstrdup (arg
);
1034 arguments
->font_info
.name
= xstrdup (arg
);
1038 arguments
->font_index
= strtoul (arg
, NULL
, 0);
1042 arguments
->font_size
= strtoul (arg
, NULL
, 0);
1053 a
= strtoul (p
, &p
, 0);
1055 /* TRANSLATORS: It refers to the range of characters in font. */
1056 grub_util_error ("%s", _("invalid font range"));
1057 b
= strtoul (p
+ 1, &p
, 0);
1058 if ((arguments
->font_info
.num_range
1059 & (GRUB_FONT_RANGE_BLOCK
- 1)) == 0)
1060 arguments
->font_info
.ranges
= xrealloc (arguments
->font_info
.ranges
,
1061 (arguments
->font_info
.num_range
+
1062 GRUB_FONT_RANGE_BLOCK
) *
1063 sizeof (grub_uint32_t
) * 2);
1065 arguments
->font_info
.ranges
[arguments
->font_info
.num_range
* 2] = a
;
1066 arguments
->font_info
.ranges
[arguments
->font_info
.num_range
* 2 + 1] = b
;
1067 arguments
->font_info
.num_range
++;
1072 grub_util_error ("%s", _("invalid font range"));
1082 arguments
->font_info
.desc
= strtoul (arg
, NULL
, 0);
1086 arguments
->font_info
.asce
= strtoul (arg
, NULL
, 0);
1093 case MY_ARGP_KEY_ARG
:
1094 assert (arguments
->nfiles
< arguments
->files_max
);
1095 arguments
->files
[arguments
->nfiles
++] = xstrdup(arg
);
1099 return MY_ARGP_ERR_UNKNOWN
;
1106 /* We don't require host platform to have argp. In the same time configuring
1107 gnulib for build would result in even worse mess. So we have our
1108 minimalistic argp replacement just enough for build system. Most
1109 argp features are omitted. */
1112 my_argp_parse_real (int argc
, char **argv
, void *st
)
1115 struct my_argp_state p
;
1119 for (curar
= 1; curar
< argc
; )
1121 if (argv
[curar
][0] == '-')
1123 if (has_argument (argv
[curar
][1])
1124 && curar
+ 1 >= argc
)
1126 if (has_argument (argv
[curar
][1]))
1128 if (argp_parser (argv
[curar
][1], argv
[curar
+ 1], &p
))
1133 if (argp_parser (argv
[curar
][1], NULL
, &p
))
1138 if (argp_parser (MY_ARGP_KEY_ARG
, argv
[curar
], &p
))
1147 static struct argp argp
= {
1148 options
, argp_parser
, N_("[OPTIONS] FONT_FILES"),
1149 N_("Convert common font file formats into PF2"),
1155 main (int argc
, char *argv
[])
1158 struct arguments arguments
;
1161 grub_util_host_init (&argc
, &argv
);
1164 memset (&arguments
, 0, sizeof (struct arguments
));
1165 arguments
.file_format
= PF2
;
1166 arguments
.files_max
= argc
+ 1;
1167 arguments
.files
= xmalloc ((arguments
.files_max
+ 1)
1168 * sizeof (arguments
.files
[0]));
1169 memset (arguments
.files
, 0, (arguments
.files_max
+ 1)
1170 * sizeof (arguments
.files
[0]));
1172 if (my_argp_parse (&argp
, argc
, argv
, 0, 0, &arguments
) != 0)
1174 fprintf (stderr
, "%s", _("Error in parsing command line arguments\n"));
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 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 err
= FT_Set_Pixel_Sizes (ft_face
, size
, size
);
1226 grub_util_error (_("can't set %dx%d font size: Freetype error %d: %s"),
1228 (err
> 0 && err
< (signed) ARRAY_SIZE (ft_errmsgs
))
1229 ? ft_errmsgs
[err
] : "");
1230 add_font (&arguments
.font_info
, ft_face
, arguments
.file_format
!= PF2
);
1231 FT_Done_Face (ft_face
);
1235 FT_Done_FreeType (ft_lib
);
1239 struct grub_glyph_info
*tmp
, *cur
;
1242 memset (counter
, 0, sizeof (counter
));
1244 for (cur
= arguments
.font_info
.glyphs_unsorted
; cur
; cur
= cur
->next
)
1245 counter
[(cur
->char_code
& 0xffff) + 1]++;
1246 for (i
= 0; i
< 0x10000; i
++)
1247 counter
[i
+1] += counter
[i
];
1248 tmp
= xmalloc (arguments
.font_info
.num_glyphs
1250 for (cur
= arguments
.font_info
.glyphs_unsorted
; cur
; cur
= cur
->next
)
1251 tmp
[counter
[(cur
->char_code
& 0xffff)]++] = *cur
;
1253 memset (counter
, 0, sizeof (counter
));
1255 for (cur
= tmp
; cur
< tmp
+ arguments
.font_info
.num_glyphs
; cur
++)
1256 counter
[((cur
->char_code
& 0xffff0000) >> 16) + 1]++;
1257 for (i
= 0; i
< 0x10000; i
++)
1258 counter
[i
+1] += counter
[i
];
1259 arguments
.font_info
.glyphs_sorted
= xmalloc (arguments
.font_info
.num_glyphs
1260 * sizeof (arguments
.font_info
.glyphs_sorted
[0]));
1261 for (cur
= tmp
; cur
< tmp
+ arguments
.font_info
.num_glyphs
; cur
++)
1262 arguments
.font_info
.glyphs_sorted
[counter
[(cur
->char_code
& 0xffff0000)
1267 switch (arguments
.file_format
)
1270 write_font_pf2 (&arguments
.font_info
, arguments
.output_file
);
1274 if (font_verbosity
> 1)
1275 print_glyphs (&arguments
.font_info
);
1279 for (i
= 0; i
< arguments
.nfiles
; i
++)
1280 free (arguments
.files
[i
]);