grub-mkfont.c 35 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338
  1. /*
  2. * GRUB -- GRand Unified Bootloader
  3. * Copyright (C) 2009,2010 Free Software Foundation, Inc.
  4. *
  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.
  9. *
  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.
  14. *
  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/>.
  17. */
  18. #include <config.h>
  19. #include <grub/types.h>
  20. #include <grub/misc.h>
  21. #include <grub/emu/misc.h>
  22. #include <grub/util/misc.h>
  23. #include <grub/misc.h>
  24. #include <grub/i18n.h>
  25. #include <grub/fontformat.h>
  26. #include <grub/font.h>
  27. #include <grub/unicode.h>
  28. #include <stdio.h>
  29. #include <stdlib.h>
  30. #include <string.h>
  31. #ifndef GRUB_BUILD
  32. #define _GNU_SOURCE 1
  33. #pragma GCC diagnostic ignored "-Wmissing-prototypes"
  34. #pragma GCC diagnostic ignored "-Wmissing-declarations"
  35. #include <argp.h>
  36. #pragma GCC diagnostic error "-Wmissing-prototypes"
  37. #pragma GCC diagnostic error "-Wmissing-declarations"
  38. #endif
  39. #include <assert.h>
  40. #include <errno.h>
  41. #include <ft2build.h>
  42. #include FT_FREETYPE_H
  43. #include FT_TRUETYPE_TAGS_H
  44. #include FT_TRUETYPE_TABLES_H
  45. #include FT_SYNTHESIS_H
  46. #undef __FTERRORS_H__
  47. #define FT_ERROR_START_LIST const char *ft_errmsgs[] = {
  48. #define FT_ERRORDEF(e, v, s) [e] = s,
  49. #define FT_ERROR_END_LIST };
  50. #include FT_ERRORS_H
  51. #ifndef GRUB_BUILD
  52. #include "progname.h"
  53. #endif
  54. #ifdef GRUB_BUILD
  55. #define grub_util_fopen fopen
  56. #endif
  57. #define GRUB_FONT_DEFAULT_SIZE 16
  58. #define GRUB_FONT_RANGE_BLOCK 1024
  59. #define GSUB_PTR_VALID(x, end) assert ((grub_uint8_t *) (x) <= (end))
  60. #define GSUB_ARRAY_SIZE_VALID(a, sz, end) \
  61. assert ((sz) >= 0 && ((sz) <= ((end) - (grub_uint8_t *) (a)) / sizeof (*(a))))
  62. struct grub_glyph_info
  63. {
  64. struct grub_glyph_info *next;
  65. grub_uint32_t char_code;
  66. int width;
  67. int height;
  68. int x_ofs;
  69. int y_ofs;
  70. int device_width;
  71. int bitmap_size;
  72. grub_uint8_t *bitmap;
  73. };
  74. enum file_formats
  75. {
  76. PF2
  77. };
  78. enum
  79. {
  80. GRUB_FONT_FLAG_BOLD = 1,
  81. GRUB_FONT_FLAG_NOBITMAP = 2,
  82. GRUB_FONT_FLAG_NOHINTING = 4,
  83. GRUB_FONT_FLAG_FORCEHINT = 8
  84. };
  85. struct grub_font_info
  86. {
  87. const char *name;
  88. int style;
  89. int desc;
  90. int asce;
  91. int size;
  92. int max_width;
  93. int max_height;
  94. int min_y;
  95. int max_y;
  96. int flags;
  97. int num_range;
  98. grub_uint32_t *ranges;
  99. struct grub_glyph_info *glyphs_unsorted;
  100. struct grub_glyph_info *glyphs_sorted;
  101. int num_glyphs;
  102. };
  103. static int font_verbosity;
  104. static void
  105. add_pixel (grub_uint8_t **data, int *mask, int not_blank)
  106. {
  107. if (*mask == 0)
  108. {
  109. (*data)++;
  110. **data = 0;
  111. *mask = 128;
  112. }
  113. if (not_blank)
  114. **data |= *mask;
  115. *mask >>= 1;
  116. }
  117. static void
  118. add_glyph (struct grub_font_info *font_info, FT_UInt glyph_idx, FT_Face face,
  119. grub_uint32_t char_code, int nocut)
  120. {
  121. struct grub_glyph_info *glyph_info;
  122. int width, height;
  123. int cuttop, cutbottom, cutleft, cutright;
  124. grub_uint8_t *data;
  125. int mask, i, j, bitmap_size;
  126. FT_GlyphSlot glyph;
  127. int flag = FT_LOAD_RENDER | FT_LOAD_MONOCHROME;
  128. FT_Error err;
  129. if (font_info->flags & GRUB_FONT_FLAG_NOBITMAP)
  130. flag |= FT_LOAD_NO_BITMAP;
  131. if (font_info->flags & GRUB_FONT_FLAG_NOHINTING)
  132. flag |= FT_LOAD_NO_HINTING;
  133. else if (font_info->flags & GRUB_FONT_FLAG_FORCEHINT)
  134. flag |= FT_LOAD_FORCE_AUTOHINT;
  135. err = FT_Load_Glyph (face, glyph_idx, flag);
  136. if (err)
  137. {
  138. printf (_("Freetype Error %d loading glyph 0x%x for U+0x%x%s"),
  139. err, glyph_idx, char_code & GRUB_FONT_CODE_CHAR_MASK,
  140. char_code & GRUB_FONT_CODE_RIGHT_JOINED
  141. /* TRANSLATORS: These qualifiers are used for cursive typography,
  142. mainly Arabic. Note that the terms refer to the visual position
  143. and not logical order and if used in left-to-right script then
  144. leftmost is initial but with right-to-left script like Arabic
  145. rightmost is the initial. */
  146. ? ((char_code & GRUB_FONT_CODE_LEFT_JOINED) ? _(" (medial)"):
  147. _(" (leftmost)"))
  148. : ((char_code & GRUB_FONT_CODE_LEFT_JOINED) ? _(" (rightmost)"):
  149. ""));
  150. if (err > 0 && err < (signed) ARRAY_SIZE (ft_errmsgs))
  151. printf (": %s\n", ft_errmsgs[err]);
  152. else
  153. printf ("\n");
  154. return;
  155. }
  156. glyph = face->glyph;
  157. if (font_info->flags & GRUB_FONT_FLAG_BOLD)
  158. FT_GlyphSlot_Embolden (glyph);
  159. if (nocut)
  160. cuttop = cutbottom = cutleft = cutright = 0;
  161. else
  162. {
  163. for (cuttop = 0; cuttop < glyph->bitmap.rows; cuttop++)
  164. {
  165. for (j = 0; j < glyph->bitmap.width; j++)
  166. if (glyph->bitmap.buffer[j / 8 + cuttop * glyph->bitmap.pitch]
  167. & (1 << (7 - (j & 7))))
  168. break;
  169. if (j != glyph->bitmap.width)
  170. break;
  171. }
  172. for (cutbottom = glyph->bitmap.rows - 1; cutbottom >= 0; cutbottom--)
  173. {
  174. for (j = 0; j < glyph->bitmap.width; j++)
  175. if (glyph->bitmap.buffer[j / 8 + cutbottom * glyph->bitmap.pitch]
  176. & (1 << (7 - (j & 7))))
  177. break;
  178. if (j != glyph->bitmap.width)
  179. break;
  180. }
  181. cutbottom = glyph->bitmap.rows - 1 - cutbottom;
  182. if (cutbottom + cuttop >= glyph->bitmap.rows)
  183. cutbottom = 0;
  184. for (cutleft = 0; cutleft < glyph->bitmap.width; cutleft++)
  185. {
  186. for (j = 0; j < glyph->bitmap.rows; j++)
  187. if (glyph->bitmap.buffer[cutleft / 8 + j * glyph->bitmap.pitch]
  188. & (1 << (7 - (cutleft & 7))))
  189. break;
  190. if (j != glyph->bitmap.rows)
  191. break;
  192. }
  193. for (cutright = glyph->bitmap.width - 1; cutright >= 0; cutright--)
  194. {
  195. for (j = 0; j < glyph->bitmap.rows; j++)
  196. if (glyph->bitmap.buffer[cutright / 8 + j * glyph->bitmap.pitch]
  197. & (1 << (7 - (cutright & 7))))
  198. break;
  199. if (j != glyph->bitmap.rows)
  200. break;
  201. }
  202. cutright = glyph->bitmap.width - 1 - cutright;
  203. if (cutright + cutleft >= glyph->bitmap.width)
  204. cutright = 0;
  205. }
  206. width = glyph->bitmap.width - cutleft - cutright;
  207. height = glyph->bitmap.rows - cutbottom - cuttop;
  208. bitmap_size = ((width * height + 7) / 8);
  209. glyph_info = xmalloc (sizeof (struct grub_glyph_info));
  210. glyph_info->bitmap = xmalloc (bitmap_size);
  211. glyph_info->bitmap_size = bitmap_size;
  212. glyph_info->next = font_info->glyphs_unsorted;
  213. font_info->glyphs_unsorted = glyph_info;
  214. font_info->num_glyphs++;
  215. glyph_info->char_code = char_code;
  216. glyph_info->width = width;
  217. glyph_info->height = height;
  218. glyph_info->x_ofs = glyph->bitmap_left + cutleft;
  219. glyph_info->y_ofs = glyph->bitmap_top - height - cuttop;
  220. glyph_info->device_width = glyph->metrics.horiAdvance / 64;
  221. if (width > font_info->max_width)
  222. font_info->max_width = width;
  223. if (height > font_info->max_height)
  224. font_info->max_height = height;
  225. if (glyph_info->y_ofs < font_info->min_y && glyph_info->y_ofs > -font_info->size)
  226. font_info->min_y = glyph_info->y_ofs;
  227. if (glyph_info->y_ofs + height > font_info->max_y)
  228. font_info->max_y = glyph_info->y_ofs + height;
  229. mask = 0;
  230. data = &glyph_info->bitmap[0] - 1;
  231. for (j = cuttop; j < height + cuttop; j++)
  232. for (i = cutleft; i < width + cutleft; i++)
  233. add_pixel (&data, &mask,
  234. glyph->bitmap.buffer[i / 8 + j * glyph->bitmap.pitch] &
  235. (1 << (7 - (i & 7))));
  236. }
  237. struct glyph_replace *subst_rightjoin, *subst_leftjoin, *subst_medijoin;
  238. struct glyph_replace
  239. {
  240. struct glyph_replace *next;
  241. grub_uint32_t from, to;
  242. };
  243. /* TODO: sort glyph_replace and use binary search if necessary. */
  244. static void
  245. add_char (struct grub_font_info *font_info, FT_Face face,
  246. grub_uint32_t char_code, int nocut)
  247. {
  248. FT_UInt glyph_idx;
  249. struct glyph_replace *cur;
  250. glyph_idx = FT_Get_Char_Index (face, char_code);
  251. if (!glyph_idx)
  252. return;
  253. add_glyph (font_info, glyph_idx, face, char_code, nocut);
  254. for (cur = subst_rightjoin; cur; cur = cur->next)
  255. if (cur->from == glyph_idx)
  256. {
  257. add_glyph (font_info, cur->to, face,
  258. char_code | GRUB_FONT_CODE_RIGHT_JOINED, nocut);
  259. break;
  260. }
  261. if (!cur && char_code >= GRUB_UNICODE_ARABIC_START
  262. && char_code < GRUB_UNICODE_ARABIC_END)
  263. {
  264. int i;
  265. for (i = 0; grub_unicode_arabic_shapes[i].code; i++)
  266. if (grub_unicode_arabic_shapes[i].code == char_code
  267. && grub_unicode_arabic_shapes[i].right_linked)
  268. {
  269. FT_UInt idx2;
  270. idx2 = FT_Get_Char_Index (face, grub_unicode_arabic_shapes[i]
  271. .right_linked);
  272. if (idx2)
  273. add_glyph (font_info, idx2, face,
  274. char_code | GRUB_FONT_CODE_RIGHT_JOINED, nocut);
  275. break;
  276. }
  277. }
  278. for (cur = subst_leftjoin; cur; cur = cur->next)
  279. if (cur->from == glyph_idx)
  280. {
  281. add_glyph (font_info, cur->to, face,
  282. char_code | GRUB_FONT_CODE_LEFT_JOINED, nocut);
  283. break;
  284. }
  285. if (!cur && char_code >= GRUB_UNICODE_ARABIC_START
  286. && char_code < GRUB_UNICODE_ARABIC_END)
  287. {
  288. int i;
  289. for (i = 0; grub_unicode_arabic_shapes[i].code; i++)
  290. if (grub_unicode_arabic_shapes[i].code == char_code
  291. && grub_unicode_arabic_shapes[i].left_linked)
  292. {
  293. FT_UInt idx2;
  294. idx2 = FT_Get_Char_Index (face, grub_unicode_arabic_shapes[i]
  295. .left_linked);
  296. if (idx2)
  297. add_glyph (font_info, idx2, face,
  298. char_code | GRUB_FONT_CODE_LEFT_JOINED, nocut);
  299. break;
  300. }
  301. }
  302. for (cur = subst_medijoin; cur; cur = cur->next)
  303. if (cur->from == glyph_idx)
  304. {
  305. add_glyph (font_info, cur->to, face,
  306. char_code | GRUB_FONT_CODE_LEFT_JOINED
  307. | GRUB_FONT_CODE_RIGHT_JOINED, nocut);
  308. break;
  309. }
  310. if (!cur && char_code >= GRUB_UNICODE_ARABIC_START
  311. && char_code < GRUB_UNICODE_ARABIC_END)
  312. {
  313. int i;
  314. for (i = 0; grub_unicode_arabic_shapes[i].code; i++)
  315. if (grub_unicode_arabic_shapes[i].code == char_code
  316. && grub_unicode_arabic_shapes[i].both_linked)
  317. {
  318. FT_UInt idx2;
  319. idx2 = FT_Get_Char_Index (face, grub_unicode_arabic_shapes[i]
  320. .both_linked);
  321. if (idx2)
  322. add_glyph (font_info, idx2, face,
  323. char_code | GRUB_FONT_CODE_LEFT_JOINED
  324. | GRUB_FONT_CODE_RIGHT_JOINED, nocut);
  325. break;
  326. }
  327. }
  328. }
  329. struct gsub_header
  330. {
  331. grub_uint32_t version;
  332. grub_uint16_t scripts_off;
  333. grub_uint16_t features_off;
  334. grub_uint16_t lookups_off;
  335. } GRUB_PACKED;
  336. struct gsub_features
  337. {
  338. grub_uint16_t count;
  339. struct
  340. {
  341. #define FEATURE_FINA 0x66696e61
  342. #define FEATURE_INIT 0x696e6974
  343. #define FEATURE_MEDI 0x6d656469
  344. #define FEATURE_AALT 0x61616c74
  345. #define FEATURE_LIGA 0x6c696761
  346. #define FEATURE_RLIG 0x726c6967
  347. grub_uint32_t feature_tag;
  348. grub_uint16_t offset;
  349. } GRUB_PACKED features[0];
  350. } GRUB_PACKED;
  351. struct gsub_feature
  352. {
  353. grub_uint16_t params;
  354. grub_uint16_t lookupcount;
  355. grub_uint16_t lookupindices[0];
  356. } GRUB_PACKED;
  357. struct gsub_lookup_list
  358. {
  359. grub_uint16_t count;
  360. grub_uint16_t offsets[0];
  361. } GRUB_PACKED;
  362. struct gsub_lookup
  363. {
  364. grub_uint16_t type;
  365. grub_uint16_t flag;
  366. grub_uint16_t subtablecount;
  367. grub_uint16_t subtables[0];
  368. } GRUB_PACKED;
  369. struct gsub_substitution
  370. {
  371. grub_uint16_t type;
  372. grub_uint16_t coverage_off;
  373. union
  374. {
  375. grub_int16_t delta;
  376. struct
  377. {
  378. grub_int16_t count;
  379. grub_uint16_t repl[0];
  380. };
  381. };
  382. } GRUB_PACKED;
  383. struct gsub_coverage_list
  384. {
  385. grub_uint16_t type;
  386. grub_uint16_t count;
  387. grub_uint16_t glyphs[0];
  388. } GRUB_PACKED;
  389. struct gsub_coverage_ranges
  390. {
  391. grub_uint16_t type;
  392. grub_uint16_t count;
  393. struct
  394. {
  395. grub_uint16_t start;
  396. grub_uint16_t end;
  397. grub_uint16_t start_index;
  398. } GRUB_PACKED ranges[0];
  399. } GRUB_PACKED;
  400. #define GSUB_SINGLE_SUBSTITUTION 1
  401. #define GSUB_SUBSTITUTION_DELTA 1
  402. #define GSUB_SUBSTITUTION_MAP 2
  403. #define GSUB_COVERAGE_LIST 1
  404. #define GSUB_COVERAGE_RANGE 2
  405. #define GSUB_RTL_CHAR 1
  406. static void
  407. add_subst (grub_uint32_t from, grub_uint32_t to, struct glyph_replace **target)
  408. {
  409. struct glyph_replace *new = xmalloc (sizeof (*new));
  410. new->next = *target;
  411. new->from = from;
  412. new->to = to;
  413. *target = new;
  414. }
  415. static void
  416. subst (const struct gsub_substitution *sub, grub_uint32_t glyph,
  417. struct glyph_replace **target, int *i)
  418. {
  419. grub_uint16_t substtype;
  420. substtype = grub_be_to_cpu16 (sub->type);
  421. if (substtype == GSUB_SUBSTITUTION_DELTA)
  422. add_subst (glyph, glyph + grub_be_to_cpu16 (sub->delta), target);
  423. else if (*i >= grub_be_to_cpu16 (sub->count))
  424. printf (_("Out of range substitution (%d, %u)\n"), *i,
  425. grub_be_to_cpu16 (sub->count));
  426. else
  427. add_subst (glyph, grub_be_to_cpu16 (sub->repl[(*i)++]), target);
  428. }
  429. static void
  430. process_cursive (struct gsub_feature *feature,
  431. struct gsub_lookup_list *lookups,
  432. grub_uint32_t feattag,
  433. grub_uint32_t num_glyphs,
  434. grub_uint8_t *gsub_end)
  435. {
  436. int j, k;
  437. int i;
  438. int lookup_count = grub_be_to_cpu16 (feature->lookupcount);
  439. struct glyph_replace **target = NULL;
  440. struct gsub_substitution *sub;
  441. GSUB_ARRAY_SIZE_VALID (feature->lookupindices, lookup_count, gsub_end);
  442. for (j = 0; j < lookup_count; j++)
  443. {
  444. int lookup_index = grub_be_to_cpu16 (feature->lookupindices[j]);
  445. int sub_count;
  446. struct gsub_lookup *lookup;
  447. if (lookup_index >= grub_be_to_cpu16 (lookups->count))
  448. {
  449. /* TRANSLATORS: "lookup" is taken directly from font specifications
  450. which are formulated as "Under condition X replace LOOKUP with
  451. SUBSTITUITION". "*/
  452. printf (_("Out of range lookup: %d\n"), lookup_index);
  453. continue;
  454. }
  455. lookup = (struct gsub_lookup *)
  456. ((grub_uint8_t *) lookups
  457. + grub_be_to_cpu16 (lookups->offsets[lookup_index]));
  458. if (grub_be_to_cpu16 (lookup->type) != GSUB_SINGLE_SUBSTITUTION)
  459. {
  460. printf (_("Unsupported substitution type: %d\n"),
  461. grub_be_to_cpu16 (lookup->type));
  462. continue;
  463. }
  464. if (grub_be_to_cpu16 (lookup->flag) & ~GSUB_RTL_CHAR)
  465. {
  466. grub_util_info ("unsupported substitution flag: 0x%x",
  467. grub_be_to_cpu16 (lookup->flag));
  468. }
  469. switch (feattag)
  470. {
  471. case FEATURE_INIT:
  472. if (grub_be_to_cpu16 (lookup->flag) & GSUB_RTL_CHAR)
  473. target = &subst_leftjoin;
  474. else
  475. target = &subst_rightjoin;
  476. break;
  477. case FEATURE_FINA:
  478. if (grub_be_to_cpu16 (lookup->flag) & GSUB_RTL_CHAR)
  479. target = &subst_rightjoin;
  480. else
  481. target = &subst_leftjoin;
  482. break;
  483. case FEATURE_MEDI:
  484. target = &subst_medijoin;
  485. break;
  486. }
  487. sub_count = grub_be_to_cpu16 (lookup->subtablecount);
  488. GSUB_ARRAY_SIZE_VALID (lookup->subtables, sub_count, gsub_end);
  489. for (k = 0; k < sub_count; k++)
  490. {
  491. sub = (struct gsub_substitution *)
  492. ((grub_uint8_t *) lookup + grub_be_to_cpu16 (lookup->subtables[k]));
  493. grub_uint16_t substtype;
  494. substtype = grub_be_to_cpu16 (sub->type);
  495. if (substtype != GSUB_SUBSTITUTION_MAP
  496. && substtype != GSUB_SUBSTITUTION_DELTA)
  497. {
  498. printf (_("Unsupported substitution specification: %u\n"),
  499. substtype);
  500. continue;
  501. }
  502. void *coverage = (grub_uint8_t *) sub
  503. + grub_be_to_cpu16 (sub->coverage_off);
  504. grub_uint32_t covertype;
  505. covertype = grub_be_to_cpu16 (grub_get_unaligned16 (coverage));
  506. i = 0;
  507. if (covertype == GSUB_COVERAGE_LIST)
  508. {
  509. struct gsub_coverage_list *cover = coverage;
  510. int count = grub_be_to_cpu16 (cover->count);
  511. int l;
  512. GSUB_ARRAY_SIZE_VALID (cover->glyphs, count, gsub_end);
  513. for (l = 0; l < count; l++)
  514. subst (sub, grub_be_to_cpu16 (cover->glyphs[l]), target, &i);
  515. }
  516. else if (covertype == GSUB_COVERAGE_RANGE)
  517. {
  518. struct gsub_coverage_ranges *cover = coverage;
  519. int count = grub_be_to_cpu16 (cover->count);
  520. int l, m;
  521. GSUB_ARRAY_SIZE_VALID (cover->ranges, count, gsub_end);
  522. for (l = 0; l < count; l++)
  523. {
  524. grub_uint16_t start = grub_be_to_cpu16 (cover->ranges[l].start);
  525. grub_uint16_t end = grub_be_to_cpu16 (cover->ranges[l].end);
  526. if (start > end || end > num_glyphs)
  527. grub_util_error ("%s", _("invalid font range"));
  528. for (m = start; m <= end; m++)
  529. subst (sub, m, target, &i);
  530. }
  531. }
  532. else
  533. /* TRANSLATORS: most font transformations apply only to
  534. some glyphs. Those glyphs are described as "coverage".
  535. There are 2 coverage specifications: list and range.
  536. This warning is thrown when another coverage specification
  537. is detected. */
  538. fprintf (stderr,
  539. _("Unsupported coverage specification: %u\n"), covertype);
  540. }
  541. }
  542. }
  543. static void
  544. add_font (struct grub_font_info *font_info, FT_Face face, int nocut)
  545. {
  546. struct gsub_header *gsub = NULL;
  547. FT_ULong gsub_len = 0;
  548. grub_uint8_t *gsub_end = NULL;
  549. if (!FT_Load_Sfnt_Table (face, TTAG_GSUB, 0, NULL, &gsub_len))
  550. {
  551. gsub = xmalloc (gsub_len);
  552. if (FT_Load_Sfnt_Table (face, TTAG_GSUB, 0, (void *) gsub, &gsub_len))
  553. {
  554. free (gsub);
  555. gsub = NULL;
  556. gsub_len = 0;
  557. }
  558. }
  559. gsub_end = (grub_uint8_t *) gsub + gsub_len;
  560. if (gsub)
  561. {
  562. struct gsub_features *features
  563. = (struct gsub_features *) (((grub_uint8_t *) gsub)
  564. + grub_be_to_cpu16 (gsub->features_off));
  565. struct gsub_lookup_list *lookups
  566. = (struct gsub_lookup_list *) (((grub_uint8_t *) gsub)
  567. + grub_be_to_cpu16 (gsub->lookups_off));
  568. int i;
  569. int nfeatures = grub_be_to_cpu16 (features->count);
  570. GSUB_PTR_VALID (features, gsub_end);
  571. GSUB_PTR_VALID (lookups, gsub_end);
  572. GSUB_ARRAY_SIZE_VALID (features->features, nfeatures, gsub_end);
  573. for (i = 0; i < nfeatures; i++)
  574. {
  575. struct gsub_feature *feature = (struct gsub_feature *)
  576. ((grub_uint8_t *) features
  577. + grub_be_to_cpu16 (features->features[i].offset));
  578. grub_uint32_t feattag
  579. = grub_be_to_cpu32 (features->features[i].feature_tag);
  580. GSUB_PTR_VALID (feature, gsub_end);
  581. if (feature->params)
  582. fprintf (stderr,
  583. _("WARNING: unsupported font feature parameters: %x\n"),
  584. grub_be_to_cpu16 (feature->params));
  585. switch (feattag)
  586. {
  587. /* Used for retrieving all possible variants. Useless in grub. */
  588. case FEATURE_AALT:
  589. break;
  590. /* FIXME: Add ligature support. */
  591. case FEATURE_LIGA:
  592. case FEATURE_RLIG:
  593. break;
  594. /* Cursive form variants. */
  595. case FEATURE_FINA:
  596. case FEATURE_INIT:
  597. case FEATURE_MEDI:
  598. process_cursive (feature, lookups, feattag,
  599. face->num_glyphs, gsub_end);
  600. break;
  601. default:
  602. {
  603. char str[5];
  604. int j;
  605. memcpy (str, &features->features[i].feature_tag,
  606. sizeof (features->features[i].feature_tag));
  607. str[4] = 0;
  608. for (j = 0; j < 4; j++)
  609. if (!grub_isgraph (str[j]))
  610. str[j] = '?';
  611. /* TRANSLATORS: It's gsub feature, not gsub font. */
  612. grub_util_info ("Unknown gsub font feature 0x%x (%s)",
  613. feattag, str);
  614. }
  615. }
  616. }
  617. free (gsub);
  618. }
  619. if (font_info->num_range)
  620. {
  621. int i;
  622. grub_uint32_t j;
  623. for (i = 0; i < font_info->num_range; i++)
  624. for (j = font_info->ranges[i * 2]; j <= font_info->ranges[i * 2 + 1];
  625. j++)
  626. add_char (font_info, face, j, nocut);
  627. }
  628. else
  629. {
  630. grub_uint32_t char_code, glyph_index;
  631. for (char_code = FT_Get_First_Char (face, &glyph_index);
  632. glyph_index;
  633. char_code = FT_Get_Next_Char (face, char_code, &glyph_index))
  634. add_char (font_info, face, char_code, nocut);
  635. }
  636. }
  637. static void
  638. write_string_section (const char *name, const char *str,
  639. int *offset, FILE *file,
  640. const char *filename)
  641. {
  642. grub_uint32_t leng, leng_be32;
  643. leng = strlen (str) + 1;
  644. leng_be32 = grub_cpu_to_be32 (leng);
  645. grub_util_write_image (name, 4, file, filename);
  646. grub_util_write_image ((char *) &leng_be32, 4, file, filename);
  647. grub_util_write_image (str, leng, file, filename);
  648. *offset += 8 + leng;
  649. }
  650. static void
  651. write_be16_section (const char *name, grub_uint16_t data, int* offset,
  652. FILE *file, const char *filename)
  653. {
  654. grub_uint32_t leng;
  655. leng = grub_cpu_to_be32_compile_time (2);
  656. data = grub_cpu_to_be16 (data);
  657. grub_util_write_image (name, 4, file, filename);
  658. grub_util_write_image ((char *) &leng, 4, file, filename);
  659. grub_util_write_image ((char *) &data, 2, file, filename);
  660. *offset += 10;
  661. }
  662. static void
  663. print_glyphs (struct grub_font_info *font_info)
  664. {
  665. int num;
  666. struct grub_glyph_info *glyph;
  667. char line[512];
  668. for (glyph = font_info->glyphs_sorted, num = 0; num < font_info->num_glyphs;
  669. glyph++, num++)
  670. {
  671. int x, y, xmax, xmin, ymax, ymin;
  672. grub_uint8_t *bitmap, mask;
  673. printf ("\nGlyph #%d, U+%04x\n", num, glyph->char_code);
  674. printf ("Width %d, Height %d, X offset %d, Y offset %d, Device width %d\n",
  675. glyph->width, glyph->height, glyph->x_ofs, glyph->y_ofs,
  676. glyph->device_width);
  677. xmax = glyph->x_ofs + glyph->width;
  678. if (xmax < glyph->device_width)
  679. xmax = glyph->device_width;
  680. xmin = glyph->x_ofs;
  681. if (xmin > 0)
  682. xmin = 0;
  683. ymax = glyph->y_ofs + glyph->height;
  684. if (ymax < font_info->asce)
  685. ymax = font_info->asce;
  686. ymin = glyph->y_ofs;
  687. if (ymin > - font_info->desc)
  688. ymin = - font_info->desc;
  689. bitmap = glyph->bitmap;
  690. mask = 0x80;
  691. for (y = ymax - 1; y > ymin - 1; y--)
  692. {
  693. int line_pos;
  694. line_pos = 0;
  695. for (x = xmin; x < xmax; x++)
  696. {
  697. if ((x >= glyph->x_ofs) &&
  698. (x < glyph->x_ofs + glyph->width) &&
  699. (y >= glyph->y_ofs) &&
  700. (y < glyph->y_ofs + glyph->height))
  701. {
  702. line[line_pos++] = (*bitmap & mask) ? '#' : '_';
  703. mask >>= 1;
  704. if (mask == 0)
  705. {
  706. mask = 0x80;
  707. bitmap++;
  708. }
  709. }
  710. else if ((x >= 0) &&
  711. (x < glyph->device_width) &&
  712. (y >= - font_info->desc) &&
  713. (y < font_info->asce))
  714. {
  715. line[line_pos++] = ((x == 0) || (y == 0)) ? '+' : '.';
  716. }
  717. else
  718. line[line_pos++] = '*';
  719. }
  720. line[line_pos] = 0;
  721. printf ("%s\n", line);
  722. }
  723. }
  724. }
  725. static void
  726. write_font_pf2 (struct grub_font_info *font_info, char *output_file)
  727. {
  728. FILE *file;
  729. grub_uint32_t leng;
  730. char style_name[20], *font_name, *ptr;
  731. int offset;
  732. struct grub_glyph_info *cur;
  733. file = grub_util_fopen (output_file, "wb");
  734. if (! file)
  735. grub_util_error (_("cannot write to `%s': %s"), output_file,
  736. strerror (errno));
  737. offset = 0;
  738. leng = grub_cpu_to_be32_compile_time (4);
  739. grub_util_write_image (FONT_FORMAT_SECTION_NAMES_FILE,
  740. sizeof(FONT_FORMAT_SECTION_NAMES_FILE) - 1, file,
  741. output_file);
  742. grub_util_write_image ((char *) &leng, 4, file, output_file);
  743. grub_util_write_image (FONT_FORMAT_PFF2_MAGIC, 4, file, output_file);
  744. offset += 12;
  745. if (! font_info->name)
  746. font_info->name = "Unknown";
  747. if (font_info->flags & GRUB_FONT_FLAG_BOLD)
  748. font_info->style |= FT_STYLE_FLAG_BOLD;
  749. style_name[0] = 0;
  750. if (font_info->style & FT_STYLE_FLAG_BOLD)
  751. strcpy (style_name, " Bold");
  752. if (font_info->style & FT_STYLE_FLAG_ITALIC)
  753. strcat (style_name, " Italic");
  754. if (! style_name[0])
  755. strcpy (style_name, " Regular");
  756. font_name = xmalloc (strlen (font_info->name) + strlen (&style_name[1])
  757. + 3 + 20);
  758. ptr = grub_stpcpy (font_name, font_info->name);
  759. *ptr++ = ' ';
  760. ptr = grub_stpcpy (ptr, &style_name[1]);
  761. *ptr++ = ' ';
  762. snprintf (ptr, 20, "%d", font_info->size);
  763. write_string_section (FONT_FORMAT_SECTION_NAMES_FONT_NAME,
  764. font_name, &offset, file, output_file);
  765. write_string_section (FONT_FORMAT_SECTION_NAMES_FAMILY,
  766. font_info->name, &offset, file, output_file);
  767. write_string_section (FONT_FORMAT_SECTION_NAMES_WEIGHT,
  768. (font_info->style & FT_STYLE_FLAG_BOLD) ?
  769. "bold" : "normal",
  770. &offset, file, output_file);
  771. write_string_section (FONT_FORMAT_SECTION_NAMES_SLAN,
  772. (font_info->style & FT_STYLE_FLAG_ITALIC) ?
  773. "italic" : "normal",
  774. &offset, file, output_file);
  775. write_be16_section (FONT_FORMAT_SECTION_NAMES_POINT_SIZE,
  776. font_info->size, &offset, file, output_file);
  777. write_be16_section (FONT_FORMAT_SECTION_NAMES_MAX_CHAR_WIDTH,
  778. font_info->max_width, &offset, file, output_file);
  779. write_be16_section (FONT_FORMAT_SECTION_NAMES_MAX_CHAR_HEIGHT,
  780. font_info->max_height, &offset, file, output_file);
  781. if (! font_info->desc)
  782. {
  783. if (font_info->min_y >= 0)
  784. font_info->desc = 1;
  785. else
  786. font_info->desc = - font_info->min_y;
  787. }
  788. if (! font_info->asce)
  789. {
  790. if (font_info->max_y <= 0)
  791. font_info->asce = 1;
  792. else
  793. font_info->asce = font_info->max_y;
  794. }
  795. write_be16_section (FONT_FORMAT_SECTION_NAMES_ASCENT,
  796. font_info->asce, &offset, file, output_file);
  797. write_be16_section (FONT_FORMAT_SECTION_NAMES_DESCENT,
  798. font_info->desc, &offset, file, output_file);
  799. if (font_verbosity > 0)
  800. {
  801. printf ("Font name: %s\n", font_name);
  802. printf ("Max width: %d\n", font_info->max_width);
  803. printf ("Max height: %d\n", font_info->max_height);
  804. printf ("Font ascent: %d\n", font_info->asce);
  805. printf ("Font descent: %d\n", font_info->desc);
  806. }
  807. if (font_verbosity > 0)
  808. printf ("Number of glyph: %d\n", font_info->num_glyphs);
  809. leng = grub_cpu_to_be32 (font_info->num_glyphs * 9);
  810. grub_util_write_image (FONT_FORMAT_SECTION_NAMES_CHAR_INDEX,
  811. sizeof(FONT_FORMAT_SECTION_NAMES_CHAR_INDEX) - 1,
  812. file, output_file);
  813. grub_util_write_image ((char *) &leng, 4, file, output_file);
  814. offset += 8 + font_info->num_glyphs * 9 + 8;
  815. for (cur = font_info->glyphs_sorted;
  816. cur < font_info->glyphs_sorted + font_info->num_glyphs; cur++)
  817. {
  818. grub_uint32_t data32;
  819. grub_uint8_t data8;
  820. data32 = grub_cpu_to_be32 (cur->char_code);
  821. grub_util_write_image ((char *) &data32, 4, file, output_file);
  822. data8 = 0;
  823. grub_util_write_image ((char *) &data8, 1, file, output_file);
  824. data32 = grub_cpu_to_be32 (offset);
  825. grub_util_write_image ((char *) &data32, 4, file, output_file);
  826. offset += 10 + cur->bitmap_size;
  827. }
  828. leng = 0xffffffff;
  829. grub_util_write_image (FONT_FORMAT_SECTION_NAMES_DATA,
  830. sizeof(FONT_FORMAT_SECTION_NAMES_DATA) - 1,
  831. file, output_file);
  832. grub_util_write_image ((char *) &leng, 4, file, output_file);
  833. for (cur = font_info->glyphs_sorted;
  834. cur < font_info->glyphs_sorted + font_info->num_glyphs; cur++)
  835. {
  836. grub_uint16_t data;
  837. data = grub_cpu_to_be16 (cur->width);
  838. grub_util_write_image ((char *) &data, 2, file, output_file);
  839. data = grub_cpu_to_be16 (cur->height);
  840. grub_util_write_image ((char *) &data, 2, file, output_file);
  841. data = grub_cpu_to_be16 (cur->x_ofs);
  842. grub_util_write_image ((char *) &data, 2, file, output_file);
  843. data = grub_cpu_to_be16 (cur->y_ofs);
  844. grub_util_write_image ((char *) &data, 2, file, output_file);
  845. data = grub_cpu_to_be16 (cur->device_width);
  846. grub_util_write_image ((char *) &data, 2, file, output_file);
  847. grub_util_write_image ((char *) &cur->bitmap[0], cur->bitmap_size,
  848. file, output_file);
  849. }
  850. free (font_name);
  851. fclose (file);
  852. }
  853. #ifndef GRUB_BUILD
  854. static struct argp_option options[] = {
  855. {"output", 'o', N_("FILE"), 0, N_("save output in FILE [required]"), 0},
  856. /* TRANSLATORS: bitmaps are images like e.g. in JPEG. */
  857. {"index", 'i', N_("NUM"), 0,
  858. /* TRANSLATORS: some font files may have multiple faces (fonts).
  859. This option is used to chose among them, the first face being '0'.
  860. Rarely used. */
  861. N_("select face index"), 0},
  862. {"range", 'r', N_("FROM-TO[,FROM-TO]"), 0,
  863. /* TRANSLATORS: It refers to the range of characters in font. */
  864. N_("set font range"), 0},
  865. {"name", 'n', N_("NAME"), 0,
  866. /* TRANSLATORS: "family name" for font is just a generic name without suffix
  867. like "Bold". */
  868. N_("set font family name"), 0},
  869. {"size", 's', N_("SIZE"), 0, N_("set font size"), 0},
  870. {"desc", 'd', N_("NUM"), 0, N_("set font descent"), 0},
  871. {"asce", 'c', N_("NUM"), 0, N_("set font ascent"), 0},
  872. {"bold", 'b', 0, 0, N_("convert to bold font"), 0},
  873. {"force-autohint", 'a', 0, 0, N_("force autohint"), 0},
  874. {"no-hinting", 0x101, 0, 0, N_("disable hinting"), 0},
  875. {"no-bitmap", 0x100, 0, 0,
  876. /* TRANSLATORS: some fonts contain bitmap rendering for
  877. some sizes. This option forces rerendering even if
  878. pre-rendered bitmap is available.
  879. */
  880. N_("ignore bitmap strikes when loading"), 0},
  881. {"verbose", 'v', 0, 0, N_("print verbose messages."), 0},
  882. { 0, 0, 0, 0, 0, 0 }
  883. };
  884. #define my_argp_parse argp_parse
  885. #define MY_ARGP_KEY_ARG ARGP_KEY_ARG
  886. #define my_error_t error_t
  887. #define MY_ARGP_ERR_UNKNOWN ARGP_ERR_UNKNOWN
  888. #define my_argp_state argp_state
  889. #else
  890. #define my_error_t int
  891. #define MY_ARGP_ERR_UNKNOWN -1
  892. #define MY_ARGP_KEY_ARG -1
  893. #define my_argp_parse(a, argc, argv, b, c, st) my_argp_parse_real(argc, argv, st)
  894. struct my_argp_state
  895. {
  896. void *input;
  897. };
  898. #endif
  899. struct arguments
  900. {
  901. struct grub_font_info font_info;
  902. size_t nfiles;
  903. size_t files_max;
  904. char **files;
  905. char *output_file;
  906. int font_index;
  907. int font_size;
  908. enum file_formats file_format;
  909. };
  910. #ifdef GRUB_BUILD
  911. static int
  912. has_argument (int v)
  913. {
  914. return v =='o' || v == 'i' || v == 'r' || v == 'n' || v == 's'
  915. || v == 'd' || v == 'c';
  916. }
  917. #endif
  918. static my_error_t
  919. argp_parser (int key, char *arg, struct my_argp_state *state)
  920. {
  921. /* Get the input argument from argp_parse, which we
  922. know is a pointer to our arguments structure. */
  923. struct arguments *arguments = state->input;
  924. switch (key)
  925. {
  926. case 'b':
  927. arguments->font_info.flags |= GRUB_FONT_FLAG_BOLD;
  928. break;
  929. case 0x100:
  930. arguments->font_info.flags |= GRUB_FONT_FLAG_NOBITMAP;
  931. break;
  932. case 0x101:
  933. arguments->font_info.flags |= GRUB_FONT_FLAG_NOHINTING;
  934. break;
  935. case 'a':
  936. arguments->font_info.flags |= GRUB_FONT_FLAG_FORCEHINT;
  937. break;
  938. case 'o':
  939. arguments->output_file = xstrdup (arg);
  940. break;
  941. case 'n':
  942. arguments->font_info.name = xstrdup (arg);
  943. break;
  944. case 'i':
  945. arguments->font_index = strtoul (arg, NULL, 0);
  946. break;
  947. case 's':
  948. arguments->font_size = strtoul (arg, NULL, 0);
  949. break;
  950. case 'r':
  951. {
  952. char *p = arg;
  953. while (1)
  954. {
  955. grub_uint32_t a, b;
  956. a = strtoul (p, &p, 0);
  957. if (*p != '-')
  958. /* TRANSLATORS: It refers to the range of characters in font. */
  959. grub_util_error ("%s", _("invalid font range"));
  960. b = strtoul (p + 1, &p, 0);
  961. if ((arguments->font_info.num_range
  962. & (GRUB_FONT_RANGE_BLOCK - 1)) == 0)
  963. arguments->font_info.ranges = xrealloc (arguments->font_info.ranges,
  964. (arguments->font_info.num_range +
  965. GRUB_FONT_RANGE_BLOCK) *
  966. sizeof (grub_uint32_t) * 2);
  967. arguments->font_info.ranges[arguments->font_info.num_range * 2] = a;
  968. arguments->font_info.ranges[arguments->font_info.num_range * 2 + 1] = b;
  969. arguments->font_info.num_range++;
  970. if (*p)
  971. {
  972. if (*p != ',')
  973. grub_util_error ("%s", _("invalid font range"));
  974. p++;
  975. }
  976. else
  977. break;
  978. }
  979. break;
  980. }
  981. case 'd':
  982. arguments->font_info.desc = strtoul (arg, NULL, 0);
  983. break;
  984. case 'c':
  985. arguments->font_info.asce = strtoul (arg, NULL, 0);
  986. break;
  987. case 'v':
  988. font_verbosity++;
  989. break;
  990. case MY_ARGP_KEY_ARG:
  991. assert (arguments->nfiles < arguments->files_max);
  992. arguments->files[arguments->nfiles++] = xstrdup(arg);
  993. break;
  994. default:
  995. return MY_ARGP_ERR_UNKNOWN;
  996. }
  997. return 0;
  998. }
  999. #ifdef GRUB_BUILD
  1000. /* We don't require host platform to have argp. In the same time configuring
  1001. gnulib for build would result in even worse mess. So we have our
  1002. minimalistic argp replacement just enough for build system. Most
  1003. argp features are omitted. */
  1004. static int
  1005. my_argp_parse_real (int argc, char **argv, void *st)
  1006. {
  1007. int curar;
  1008. struct my_argp_state p;
  1009. p.input = st;
  1010. for (curar = 1; curar < argc; )
  1011. {
  1012. if (argv[curar][0] == '-')
  1013. {
  1014. if (has_argument (argv[curar][1])
  1015. && curar + 1 >= argc)
  1016. return 1;
  1017. if (has_argument (argv[curar][1]))
  1018. {
  1019. if (argp_parser (argv[curar][1], argv[curar + 1], &p))
  1020. return 1;
  1021. curar += 2;
  1022. continue;
  1023. }
  1024. if (argp_parser (argv[curar][1], NULL, &p))
  1025. return 1;
  1026. curar++;
  1027. continue;
  1028. }
  1029. if (argp_parser (MY_ARGP_KEY_ARG, argv[curar], &p))
  1030. return 1;
  1031. curar++;
  1032. }
  1033. return 0;
  1034. }
  1035. #endif
  1036. #ifndef GRUB_BUILD
  1037. static struct argp argp = {
  1038. options, argp_parser, N_("[OPTIONS] FONT_FILES"),
  1039. N_("Convert common font file formats into PF2"),
  1040. NULL, NULL, NULL
  1041. };
  1042. #endif
  1043. int
  1044. main (int argc, char *argv[])
  1045. {
  1046. FT_Library ft_lib;
  1047. struct arguments arguments;
  1048. #ifndef GRUB_BUILD
  1049. grub_util_host_init (&argc, &argv);
  1050. #endif
  1051. memset (&arguments, 0, sizeof (struct arguments));
  1052. arguments.file_format = PF2;
  1053. arguments.files_max = argc + 1;
  1054. arguments.files = xmalloc ((arguments.files_max + 1)
  1055. * sizeof (arguments.files[0]));
  1056. memset (arguments.files, 0, (arguments.files_max + 1)
  1057. * sizeof (arguments.files[0]));
  1058. if (my_argp_parse (&argp, argc, argv, 0, 0, &arguments) != 0)
  1059. {
  1060. fprintf (stderr, "%s", _("Error in parsing command line arguments\n"));
  1061. exit(1);
  1062. }
  1063. if (! arguments.output_file)
  1064. grub_util_error ("%s", _("output file must be specified"));
  1065. if (FT_Init_FreeType (&ft_lib))
  1066. grub_util_error ("%s", _("FT_Init_FreeType fails"));
  1067. {
  1068. size_t i;
  1069. for (i = 0; i < arguments.nfiles; i++)
  1070. {
  1071. FT_Face ft_face;
  1072. int size;
  1073. FT_Error err;
  1074. err = FT_New_Face (ft_lib, arguments.files[i],
  1075. arguments.font_index, &ft_face);
  1076. if (err)
  1077. {
  1078. printf (_("can't open file %s, index %d: error %d"),
  1079. arguments.files[i],
  1080. arguments.font_index, err);
  1081. if (err > 0 && err < (signed) ARRAY_SIZE (ft_errmsgs))
  1082. printf (": %s\n", ft_errmsgs[err]);
  1083. else
  1084. printf ("\n");
  1085. continue;
  1086. }
  1087. if ((! arguments.font_info.name) && (ft_face->family_name))
  1088. arguments.font_info.name = xstrdup (ft_face->family_name);
  1089. size = arguments.font_size;
  1090. if (! size)
  1091. {
  1092. if ((ft_face->face_flags & FT_FACE_FLAG_SCALABLE) ||
  1093. (! ft_face->num_fixed_sizes))
  1094. size = GRUB_FONT_DEFAULT_SIZE;
  1095. else
  1096. size = ft_face->available_sizes[0].height;
  1097. }
  1098. arguments.font_info.style = ft_face->style_flags;
  1099. arguments.font_info.size = size;
  1100. err = FT_Set_Pixel_Sizes (ft_face, size, size);
  1101. if (err)
  1102. grub_util_error (_("can't set %dx%d font size: Freetype error %d: %s"),
  1103. size, size, err,
  1104. (err > 0 && err < (signed) ARRAY_SIZE (ft_errmsgs))
  1105. ? ft_errmsgs[err] : "");
  1106. add_font (&arguments.font_info, ft_face, arguments.file_format != PF2);
  1107. FT_Done_Face (ft_face);
  1108. }
  1109. }
  1110. FT_Done_FreeType (ft_lib);
  1111. {
  1112. int counter[65537];
  1113. struct grub_glyph_info *tmp, *cur;
  1114. int i;
  1115. memset (counter, 0, sizeof (counter));
  1116. for (cur = arguments.font_info.glyphs_unsorted; cur; cur = cur->next)
  1117. counter[(cur->char_code & 0xffff) + 1]++;
  1118. for (i = 0; i < 0x10000; i++)
  1119. counter[i+1] += counter[i];
  1120. tmp = xmalloc (arguments.font_info.num_glyphs
  1121. * sizeof (tmp[0]));
  1122. for (cur = arguments.font_info.glyphs_unsorted; cur; cur = cur->next)
  1123. tmp[counter[(cur->char_code & 0xffff)]++] = *cur;
  1124. memset (counter, 0, sizeof (counter));
  1125. for (cur = tmp; cur < tmp + arguments.font_info.num_glyphs; cur++)
  1126. counter[((cur->char_code & 0xffff0000) >> 16) + 1]++;
  1127. for (i = 0; i < 0x10000; i++)
  1128. counter[i+1] += counter[i];
  1129. arguments.font_info.glyphs_sorted = xmalloc (arguments.font_info.num_glyphs
  1130. * sizeof (arguments.font_info.glyphs_sorted[0]));
  1131. for (cur = tmp; cur < tmp + arguments.font_info.num_glyphs; cur++)
  1132. arguments.font_info.glyphs_sorted[counter[(cur->char_code & 0xffff0000)
  1133. >> 16]++] = *cur;
  1134. free (tmp);
  1135. }
  1136. switch (arguments.file_format)
  1137. {
  1138. case PF2:
  1139. write_font_pf2 (&arguments.font_info, arguments.output_file);
  1140. break;
  1141. }
  1142. if (font_verbosity > 1)
  1143. print_glyphs (&arguments.font_info);
  1144. free (arguments.font_info.glyphs_sorted);
  1145. {
  1146. size_t i;
  1147. for (i = 0; i < arguments.nfiles; i++)
  1148. free (arguments.files[i]);
  1149. }
  1150. free (arguments.files);
  1151. return 0;
  1152. }