~ubuntu-branches/ubuntu/trusty/grub2/trusty-updates

« back to all changes in this revision

Viewing changes to util/grub-mkfont.c

Tags: upstream-1.99~20101122
ImportĀ upstreamĀ versionĀ 1.99~20101122

Show diffs side-by-side

added added

removed removed

Lines of Context:
18
18
 
19
19
#include <config.h>
20
20
#include <grub/types.h>
 
21
#include <grub/misc.h>
 
22
#include <grub/emu/misc.h>
21
23
#include <grub/util/misc.h>
 
24
#include <grub/misc.h>
22
25
#include <grub/i18n.h>
 
26
#include <grub/fontformat.h>
 
27
#include <grub/font.h>
 
28
#include <grub/unicode.h>
23
29
 
24
30
#include <stdio.h>
25
31
#include <stdlib.h>
28
34
 
29
35
#include <ft2build.h>
30
36
#include FT_FREETYPE_H
 
37
#include FT_TRUETYPE_TAGS_H
 
38
#include FT_TRUETYPE_TABLES_H
31
39
#include <freetype/ftsynth.h>
32
40
 
 
41
#undef __FTERRORS_H__
 
42
#define FT_ERROR_START_LIST   const char *ft_errmsgs[] = { 
 
43
#define FT_ERRORDEF(e, v, s)  [e] = s,
 
44
#define FT_ERROR_END_LIST     };
 
45
#include FT_ERRORS_H   
 
46
 
33
47
#include "progname.h"
34
48
 
35
49
#define GRUB_FONT_DEFAULT_SIZE          16
46
60
  int y_ofs;
47
61
  int device_width;
48
62
  int bitmap_size;
49
 
  grub_uint8_t bitmap[0];
 
63
  grub_uint8_t *bitmap;
 
64
};
 
65
 
 
66
enum file_formats
 
67
{
 
68
  PF2,
 
69
  ASCII_BITMAPS,
 
70
  WIDTH_SPEC
50
71
};
51
72
 
52
73
#define GRUB_FONT_FLAG_BOLD             1
68
89
  int flags;
69
90
  int num_range;
70
91
  grub_uint32_t *ranges;
71
 
  struct grub_glyph_info *glyph;
 
92
  struct grub_glyph_info *glyphs_unsorted;
 
93
  struct grub_glyph_info *glyphs_sorted;
 
94
  int num_glyphs;
72
95
};
73
96
 
74
97
static struct option options[] =
87
110
  {"help", no_argument, 0, 'h'},
88
111
  {"version", no_argument, 0, 'V'},
89
112
  {"verbose", no_argument, 0, 'v'},
 
113
  {"ascii-bitmaps", no_argument, 0, 0x102},
 
114
  {"width-spec", no_argument, 0, 0x103},
90
115
  {0, 0, 0, 0}
91
116
};
92
117
 
96
121
usage (int status)
97
122
{
98
123
  if (status)
99
 
    fprintf (stderr, "Try ``%s --help'' for more information.\n", program_name);
 
124
    fprintf (stderr, "Try `%s --help' for more information.\n", program_name);
100
125
  else
101
126
    printf ("\
102
127
Usage: %s [OPTIONS] FONT_FILES\n\
103
128
\nOptions:\n\
104
129
  -o, --output=FILE_NAME    set output file name\n\
 
130
  --ascii-bitmaps           save only the ASCII bitmaps\n\
 
131
  --width-spec              create width summary file\n\
105
132
  -i, --index=N             set face index\n\
106
133
  -r, --range=A-B[,C-D]     set font range\n\
107
134
  -n, --name=S              set font family name\n\
137
164
  *mask >>= 1;
138
165
}
139
166
 
140
 
void
141
 
add_char (struct grub_font_info *font_info, FT_Face face,
142
 
          grub_uint32_t char_code)
 
167
static void
 
168
add_glyph (struct grub_font_info *font_info, FT_UInt glyph_idx, FT_Face face,
 
169
           grub_uint32_t char_code, int nocut)
143
170
{
144
 
  struct grub_glyph_info *glyph_info, **p_glyph;
 
171
  struct grub_glyph_info *glyph_info;
145
172
  int width, height;
 
173
  int cuttop, cutbottom, cutleft, cutright;
146
174
  grub_uint8_t *data;
147
175
  int mask, i, j, bitmap_size;
148
176
  FT_GlyphSlot glyph;
149
177
  int flag = FT_LOAD_RENDER | FT_LOAD_MONOCHROME;
 
178
  FT_Error err;
150
179
 
151
180
  if (font_info->flags & GRUB_FONT_FLAG_NOBITMAP)
152
181
    flag |= FT_LOAD_NO_BITMAP;
156
185
  else if (font_info->flags & GRUB_FONT_FLAG_FORCEHINT)
157
186
    flag |= FT_LOAD_FORCE_AUTOHINT;
158
187
 
159
 
  if (FT_Load_Char (face, char_code, flag))
160
 
    return;
 
188
  err = FT_Load_Glyph (face, glyph_idx, flag);
 
189
  if (err)
 
190
    {
 
191
      printf ("Freetype Error %d loading glyph 0x%x for U+0x%x%s",
 
192
              err, glyph_idx, char_code & GRUB_FONT_CODE_CHAR_MASK,
 
193
              char_code & GRUB_FONT_CODE_RIGHT_JOINED
 
194
              ? ((char_code & GRUB_FONT_CODE_LEFT_JOINED) ? " (medial)":
 
195
                 " (leftmost)")
 
196
              : ((char_code & GRUB_FONT_CODE_LEFT_JOINED) ? " (rightmost)":
 
197
                 ""));
 
198
 
 
199
      if (err > 0 && err < (signed) ARRAY_SIZE (ft_errmsgs))
 
200
        printf (": %s\n", ft_errmsgs[err]);
 
201
      else
 
202
        printf ("\n");
 
203
      return;
 
204
    }
161
205
 
162
206
  glyph = face->glyph;
163
207
 
164
208
  if (font_info->flags & GRUB_FONT_FLAG_BOLD)
165
209
    FT_GlyphSlot_Embolden (glyph);
166
210
 
167
 
  p_glyph = &font_info->glyph;
168
 
  while ((*p_glyph) && ((*p_glyph)->char_code > char_code))
 
211
  if (glyph->next)
 
212
    printf ("%x\n", char_code);
 
213
 
 
214
  if (nocut)
 
215
    cuttop = cutbottom = cutleft = cutright = 0;
 
216
  else
169
217
    {
170
 
      p_glyph = &(*p_glyph)->next;
 
218
      for (cuttop = 0; cuttop < glyph->bitmap.rows; cuttop++)
 
219
        {
 
220
          for (j = 0; j < glyph->bitmap.width; j++)
 
221
            if (glyph->bitmap.buffer[j / 8 + cuttop * glyph->bitmap.pitch]
 
222
                & (1 << (7 - (j & 7))))
 
223
              break;
 
224
          if (j != glyph->bitmap.width)
 
225
            break;
 
226
        }
 
227
 
 
228
      for (cutbottom = glyph->bitmap.rows - 1; cutbottom >= 0; cutbottom--)
 
229
        {
 
230
          for (j = 0; j < glyph->bitmap.width; j++)
 
231
            if (glyph->bitmap.buffer[j / 8 + cutbottom * glyph->bitmap.pitch]
 
232
                & (1 << (7 - (j & 7))))
 
233
              break;
 
234
          if (j != glyph->bitmap.width)
 
235
            break;
 
236
        }
 
237
      cutbottom = glyph->bitmap.rows - 1 - cutbottom;
 
238
      if (cutbottom + cuttop >= glyph->bitmap.rows)
 
239
        cutbottom = 0;
 
240
 
 
241
      for (cutleft = 0; cutleft < glyph->bitmap.width; cutleft++)
 
242
        {
 
243
          for (j = 0; j < glyph->bitmap.rows; j++)
 
244
            if (glyph->bitmap.buffer[cutleft / 8 + j * glyph->bitmap.pitch]
 
245
                & (1 << (7 - (cutleft & 7))))
 
246
              break;
 
247
          if (j != glyph->bitmap.rows)
 
248
            break;
 
249
        }
 
250
      for (cutright = glyph->bitmap.width - 1; cutright >= 0; cutright--)
 
251
        {
 
252
          for (j = 0; j < glyph->bitmap.rows; j++)
 
253
            if (glyph->bitmap.buffer[cutright / 8 + j * glyph->bitmap.pitch]
 
254
                & (1 << (7 - (cutright & 7))))
 
255
              break;
 
256
          if (j != glyph->bitmap.rows)
 
257
            break;
 
258
        }
 
259
      cutright = glyph->bitmap.width - 1 - cutright;
 
260
      if (cutright + cutleft >= glyph->bitmap.width)
 
261
        cutright = 0;
171
262
    }
172
263
 
173
 
  /* Ignore duplicated glyph.  */
174
 
  if ((*p_glyph) && ((*p_glyph)->char_code == char_code))
175
 
    return;
176
 
 
177
 
  width = glyph->bitmap.width;
178
 
  height = glyph->bitmap.rows;
 
264
  width = glyph->bitmap.width - cutleft - cutright;
 
265
  height = glyph->bitmap.rows - cutbottom - cuttop;
179
266
 
180
267
  bitmap_size = ((width * height + 7) / 8);
181
 
  glyph_info = xmalloc (sizeof (struct grub_glyph_info) + bitmap_size);
 
268
  glyph_info = xmalloc (sizeof (struct grub_glyph_info));
 
269
  glyph_info->bitmap = xmalloc (bitmap_size);
182
270
  glyph_info->bitmap_size = bitmap_size;
183
271
 
184
 
  glyph_info->next = *p_glyph;
185
 
  *p_glyph = glyph_info;
 
272
  glyph_info->next = font_info->glyphs_unsorted;
 
273
  font_info->glyphs_unsorted = glyph_info;
 
274
  font_info->num_glyphs++;
186
275
 
187
276
  glyph_info->char_code = char_code;
188
277
  glyph_info->width = width;
189
278
  glyph_info->height = height;
190
 
  glyph_info->x_ofs = glyph->bitmap_left;
191
 
  glyph_info->y_ofs = glyph->bitmap_top - height;
 
279
  glyph_info->x_ofs = glyph->bitmap_left + cutleft;
 
280
  glyph_info->y_ofs = glyph->bitmap_top - height - cuttop;
192
281
  glyph_info->device_width = glyph->metrics.horiAdvance / 64;
193
282
 
194
283
  if (width > font_info->max_width)
205
294
 
206
295
  mask = 0;
207
296
  data = &glyph_info->bitmap[0] - 1;
208
 
  for (j = 0; j < height; j++)
209
 
    for (i = 0; i < width; i++)
 
297
  for (j = cuttop; j < height + cuttop; j++)
 
298
    for (i = cutleft; i < width + cutleft; i++)
210
299
      add_pixel (&data, &mask,
211
300
                 glyph->bitmap.buffer[i / 8 + j * glyph->bitmap.pitch] &
212
301
                 (1 << (7 - (i & 7))));
213
302
}
214
303
 
 
304
struct glyph_replace *subst_rightjoin, *subst_leftjoin, *subst_medijoin;
 
305
 
 
306
struct glyph_replace
 
307
{
 
308
  struct glyph_replace *next;
 
309
  grub_uint32_t from, to;
 
310
};
 
311
 
 
312
/* TODO: sort glyph_replace and use binary search if necessary.  */
 
313
static void
 
314
add_char (struct grub_font_info *font_info, FT_Face face,
 
315
          grub_uint32_t char_code, int nocut)
 
316
{
 
317
  FT_UInt glyph_idx;
 
318
  struct glyph_replace *cur;
 
319
 
 
320
  glyph_idx = FT_Get_Char_Index (face, char_code);
 
321
  if (!glyph_idx)
 
322
    return;
 
323
  add_glyph (font_info, glyph_idx, face, char_code, nocut);
 
324
  for (cur = subst_rightjoin; cur; cur = cur->next)
 
325
    if (cur->from == glyph_idx)
 
326
      {
 
327
        add_glyph (font_info, cur->to, face,
 
328
                   char_code | GRUB_FONT_CODE_RIGHT_JOINED, nocut);
 
329
        break;
 
330
      }
 
331
  if (!cur && char_code >= GRUB_UNICODE_ARABIC_START
 
332
      && char_code < GRUB_UNICODE_ARABIC_END)
 
333
    {
 
334
      int i;
 
335
      for (i = 0; grub_unicode_arabic_shapes[i].code; i++)
 
336
        if (grub_unicode_arabic_shapes[i].code == char_code
 
337
            && grub_unicode_arabic_shapes[i].right_linked)
 
338
          {
 
339
            FT_UInt idx2;
 
340
            idx2 = FT_Get_Char_Index (face, grub_unicode_arabic_shapes[i]
 
341
                                      .right_linked);
 
342
            if (idx2)
 
343
              add_glyph (font_info, idx2, face,
 
344
                         char_code | GRUB_FONT_CODE_RIGHT_JOINED, nocut);
 
345
            break;
 
346
          }
 
347
              
 
348
    }
 
349
 
 
350
  for (cur = subst_leftjoin; cur; cur = cur->next)
 
351
    if (cur->from == glyph_idx)
 
352
      {
 
353
        add_glyph (font_info, cur->to, face,
 
354
                   char_code | GRUB_FONT_CODE_LEFT_JOINED, nocut);
 
355
        break;
 
356
      }
 
357
  if (!cur && char_code >= GRUB_UNICODE_ARABIC_START
 
358
      && char_code < GRUB_UNICODE_ARABIC_END)
 
359
    {
 
360
      int i;
 
361
      for (i = 0; grub_unicode_arabic_shapes[i].code; i++)
 
362
        if (grub_unicode_arabic_shapes[i].code == char_code
 
363
            && grub_unicode_arabic_shapes[i].left_linked)
 
364
          {
 
365
            FT_UInt idx2;
 
366
            idx2 = FT_Get_Char_Index (face, grub_unicode_arabic_shapes[i]
 
367
                                      .left_linked);
 
368
            if (idx2)
 
369
              add_glyph (font_info, idx2, face,
 
370
                         char_code | GRUB_FONT_CODE_LEFT_JOINED, nocut);
 
371
            break;
 
372
          }
 
373
              
 
374
    }
 
375
  for (cur = subst_medijoin; cur; cur = cur->next)
 
376
    if (cur->from == glyph_idx)
 
377
      {
 
378
        add_glyph (font_info, cur->to, face,
 
379
                   char_code | GRUB_FONT_CODE_LEFT_JOINED
 
380
                   | GRUB_FONT_CODE_RIGHT_JOINED, nocut);
 
381
        break;
 
382
      }
 
383
  if (!cur && char_code >= GRUB_UNICODE_ARABIC_START
 
384
      && char_code < GRUB_UNICODE_ARABIC_END)
 
385
    {
 
386
      int i;
 
387
      for (i = 0; grub_unicode_arabic_shapes[i].code; i++)
 
388
        if (grub_unicode_arabic_shapes[i].code == char_code
 
389
            && grub_unicode_arabic_shapes[i].both_linked)
 
390
          {
 
391
            FT_UInt idx2;
 
392
            idx2 = FT_Get_Char_Index (face, grub_unicode_arabic_shapes[i]
 
393
                                      .both_linked);
 
394
            if (idx2)
 
395
              add_glyph (font_info, idx2, face,
 
396
                         char_code | GRUB_FONT_CODE_LEFT_JOINED
 
397
                         | GRUB_FONT_CODE_RIGHT_JOINED, nocut);
 
398
            break;
 
399
          }
 
400
              
 
401
    }
 
402
}
 
403
 
 
404
struct gsub_header
 
405
{
 
406
  grub_uint32_t version;
 
407
  grub_uint16_t scripts_off;
 
408
  grub_uint16_t features_off;
 
409
  grub_uint16_t lookups_off;
 
410
} __attribute__ ((packed));
 
411
 
 
412
struct gsub_features
 
413
{
 
414
  grub_uint16_t count;
 
415
  struct
 
416
  {
 
417
#define FEATURE_FINA 0x66696e61
 
418
#define FEATURE_INIT 0x696e6974
 
419
#define FEATURE_MEDI 0x6d656469
 
420
#define FEATURE_AALT 0x61616c74
 
421
#define FEATURE_LIGA 0x6c696761
 
422
#define FEATURE_RLIG 0x726c6967
 
423
    grub_uint32_t feature_tag;
 
424
    grub_uint16_t offset;
 
425
  } __attribute__ ((packed)) features[0];
 
426
} __attribute__ ((packed));
 
427
 
 
428
struct gsub_feature
 
429
{
 
430
  grub_uint16_t params;
 
431
  grub_uint16_t lookupcount;
 
432
  grub_uint16_t lookupindices[0];
 
433
} __attribute__ ((packed));
 
434
 
 
435
struct gsub_lookup_list
 
436
{
 
437
  grub_uint16_t count;
 
438
  grub_uint16_t offsets[0];
 
439
} __attribute__ ((packed));
 
440
 
 
441
struct gsub_lookup
 
442
{
 
443
  grub_uint16_t type;
 
444
  grub_uint16_t flag;
 
445
  grub_uint16_t subtablecount;
 
446
  grub_uint16_t subtables[0];
 
447
} __attribute__ ((packed));
 
448
 
 
449
struct gsub_substitution
 
450
{
 
451
  grub_uint16_t type;
 
452
  grub_uint16_t coverage_off;
 
453
  union
 
454
  {
 
455
    grub_int16_t delta;
 
456
    struct
 
457
    {
 
458
      grub_int16_t count;
 
459
      grub_uint16_t repl[0];
 
460
    };
 
461
  };
 
462
} __attribute__ ((packed));
 
463
 
 
464
struct gsub_coverage_list
 
465
{
 
466
  grub_uint16_t type;
 
467
  grub_uint16_t count;
 
468
  grub_uint16_t glyphs[0];
 
469
} __attribute__ ((packed));
 
470
 
 
471
struct gsub_coverage_ranges
 
472
{
 
473
  grub_uint16_t type;
 
474
  grub_uint16_t count;
 
475
  struct 
 
476
  {
 
477
    grub_uint16_t start;
 
478
    grub_uint16_t end;
 
479
    grub_uint16_t start_index;
 
480
  } __attribute__ ((packed)) ranges[0];
 
481
} __attribute__ ((packed));
 
482
 
 
483
#define GSUB_SINGLE_SUBSTITUTION 1
 
484
 
 
485
#define GSUB_SUBSTITUTION_DELTA 1
 
486
#define GSUB_SUBSTITUTION_MAP 2
 
487
 
 
488
#define GSUB_COVERAGE_LIST 1
 
489
#define GSUB_COVERAGE_RANGE 2
 
490
 
 
491
#define GSUB_RTL_CHAR 1
 
492
 
 
493
static void
 
494
add_subst (grub_uint32_t from, grub_uint32_t to, struct glyph_replace **target)
 
495
{
 
496
  struct glyph_replace *new = xmalloc (sizeof (*new));
 
497
  new->next = *target;
 
498
  new->from = from;
 
499
  new->to = to;
 
500
  *target = new;
 
501
}
 
502
 
 
503
static void
 
504
process_cursive (struct gsub_feature *feature,
 
505
                 struct gsub_lookup_list *lookups,
 
506
                 grub_uint32_t feattag)
 
507
{
 
508
  int j, k;
 
509
  int i;
 
510
  struct glyph_replace **target;
 
511
  struct gsub_substitution *sub;
 
512
 
 
513
  auto inline void subst (grub_uint32_t glyph);
 
514
  void subst (grub_uint32_t glyph)
 
515
  {
 
516
    grub_uint16_t substtype;
 
517
    substtype = grub_be_to_cpu16 (sub->type);
 
518
 
 
519
    if (substtype == GSUB_SUBSTITUTION_DELTA)
 
520
      add_subst (glyph, glyph + grub_be_to_cpu16 (sub->delta), target);
 
521
    else if (i >= grub_be_to_cpu16 (sub->count))
 
522
      printf ("Out of range substitution (%d, %d)\n", i,
 
523
              grub_be_to_cpu16 (sub->count));
 
524
    else
 
525
      add_subst (glyph, grub_be_to_cpu16 (sub->repl[i++]), target);
 
526
  }
 
527
 
 
528
  for (j = 0; j < grub_be_to_cpu16 (feature->lookupcount); j++)
 
529
    {
 
530
      int lookup_index = grub_be_to_cpu16 (feature->lookupindices[j]);
 
531
      struct gsub_lookup *lookup;
 
532
      if (lookup_index >= grub_be_to_cpu16 (lookups->count))
 
533
        {
 
534
          printf ("Out of range lookup: %d\n", lookup_index);
 
535
          continue;
 
536
        }
 
537
      lookup = (struct gsub_lookup *)
 
538
        ((grub_uint8_t *) lookups 
 
539
         + grub_be_to_cpu16 (lookups->offsets[lookup_index]));
 
540
      if (grub_be_to_cpu16 (lookup->type) != GSUB_SINGLE_SUBSTITUTION)
 
541
        {
 
542
          printf ("Unsupported substitution type: %d\n",
 
543
                  grub_be_to_cpu16 (lookup->type));
 
544
          continue;
 
545
        }                     
 
546
      if (grub_be_to_cpu16 (lookup->flag) & ~GSUB_RTL_CHAR)
 
547
        {
 
548
          printf ("Unsupported substitution flag: 0x%x\n",
 
549
                  grub_be_to_cpu16 (lookup->flag));
 
550
        }
 
551
      switch (feattag)
 
552
        {
 
553
        case FEATURE_INIT:
 
554
          if (grub_be_to_cpu16 (lookup->flag) & GSUB_RTL_CHAR)
 
555
            target = &subst_leftjoin;
 
556
          else
 
557
            target = &subst_rightjoin;
 
558
          break;
 
559
        case FEATURE_FINA:
 
560
          if (grub_be_to_cpu16 (lookup->flag) & GSUB_RTL_CHAR)
 
561
            target = &subst_rightjoin;
 
562
          else
 
563
            target = &subst_leftjoin;
 
564
          break;
 
565
        case FEATURE_MEDI:
 
566
          target = &subst_medijoin;
 
567
          break;          
 
568
        }
 
569
      for (k = 0; k < grub_be_to_cpu16 (lookup->subtablecount); k++)
 
570
        {
 
571
          sub = (struct gsub_substitution *)
 
572
            ((grub_uint8_t *) lookup + grub_be_to_cpu16 (lookup->subtables[k]));
 
573
          grub_uint16_t substtype;
 
574
          substtype = grub_be_to_cpu16 (sub->type);
 
575
          if (substtype != GSUB_SUBSTITUTION_MAP
 
576
              && substtype != GSUB_SUBSTITUTION_DELTA)
 
577
            {
 
578
              printf ("Unsupported substitution specification: %d\n",
 
579
                      substtype);
 
580
              continue;
 
581
            }
 
582
          void *coverage = (grub_uint8_t *) sub
 
583
            + grub_be_to_cpu16 (sub->coverage_off);
 
584
          grub_uint32_t covertype;
 
585
          covertype = grub_be_to_cpu16 (*(grub_uint16_t * __attribute__ ((packed))) coverage);
 
586
          i = 0;
 
587
          if (covertype == GSUB_COVERAGE_LIST)
 
588
            {
 
589
              struct gsub_coverage_list *cover = coverage;
 
590
              int l;
 
591
              for (l = 0; l < grub_be_to_cpu16 (cover->count); l++)
 
592
                subst (grub_be_to_cpu16 (cover->glyphs[l]));
 
593
            }
 
594
          else if (covertype == GSUB_COVERAGE_RANGE)
 
595
            {
 
596
              struct gsub_coverage_ranges *cover = coverage;
 
597
              int l, m;
 
598
              for (l = 0; l < grub_be_to_cpu16 (cover->count); l++)
 
599
                for (m = grub_be_to_cpu16 (cover->ranges[l].start);
 
600
                     m <= grub_be_to_cpu16 (cover->ranges[l].end); m++)
 
601
                  subst (m);
 
602
            }
 
603
          else
 
604
            printf ("Unsupported coverage specification: %d\n", covertype);
 
605
        }
 
606
    }
 
607
}
 
608
 
215
609
void
216
 
add_font (struct grub_font_info *font_info, FT_Face face)
 
610
add_font (struct grub_font_info *font_info, FT_Face face, int nocut)
217
611
{
 
612
  struct gsub_header *gsub = NULL;
 
613
  FT_ULong gsub_len = 0;
 
614
 
 
615
  if (!FT_Load_Sfnt_Table (face, TTAG_GSUB, 0, NULL, &gsub_len))
 
616
    {
 
617
      gsub = xmalloc (gsub_len);
 
618
      if (FT_Load_Sfnt_Table (face, TTAG_GSUB, 0, (void *) gsub, &gsub_len))
 
619
        {
 
620
          free (gsub);
 
621
          gsub = NULL;
 
622
          gsub_len = 0;
 
623
        }
 
624
    }
 
625
  if (gsub)
 
626
    {
 
627
      struct gsub_features *features 
 
628
        = (struct gsub_features *) (((grub_uint8_t *) gsub)
 
629
                                    + grub_be_to_cpu16 (gsub->features_off));
 
630
      struct gsub_lookup_list *lookups
 
631
        = (struct gsub_lookup_list *) (((grub_uint8_t *) gsub)
 
632
                                       + grub_be_to_cpu16 (gsub->lookups_off));
 
633
      int i;
 
634
      int nfeatures = grub_be_to_cpu16 (features->count);
 
635
      for (i = 0; i < nfeatures; i++)
 
636
        {
 
637
          struct gsub_feature *feature = (struct gsub_feature *)
 
638
            ((grub_uint8_t *) features
 
639
             + grub_be_to_cpu16 (features->features[i].offset));
 
640
          grub_uint32_t feattag
 
641
            = grub_be_to_cpu32 (features->features[i].feature_tag);
 
642
          if (feature->params)
 
643
            printf ("WARNING: unsupported feature parameters: %x\n",
 
644
                    grub_be_to_cpu16 (feature->params));
 
645
          switch (feattag)
 
646
            {
 
647
              /* Used for retrieving all possible variants. Useless in grub.  */
 
648
            case FEATURE_AALT:
 
649
              break;
 
650
 
 
651
              /* FIXME: Add ligature support.  */
 
652
            case FEATURE_LIGA:
 
653
            case FEATURE_RLIG:
 
654
              break;
 
655
 
 
656
              /* Cursive form variants.  */
 
657
            case FEATURE_FINA:
 
658
            case FEATURE_INIT:
 
659
            case FEATURE_MEDI:
 
660
              process_cursive (feature, lookups, feattag);
 
661
              break;
 
662
 
 
663
            default:
 
664
              {
 
665
                char str[5];
 
666
                int j;
 
667
                memcpy (str, &features->features[i].feature_tag,
 
668
                        sizeof (features->features[i].feature_tag));
 
669
                str[4] = 0;
 
670
                for (j = 0; j < 4; j++)
 
671
                  if (!grub_isgraph (str[j]))
 
672
                    str[j] = '?';
 
673
                printf ("Unknown gsub feature 0x%x (%s)\n", feattag, str);
 
674
              }
 
675
            }
 
676
        }
 
677
    }
 
678
 
218
679
  if (font_info->num_range)
219
680
    {
220
681
      int i;
223
684
      for (i = 0; i < font_info->num_range; i++)
224
685
        for (j = font_info->ranges[i * 2]; j <= font_info->ranges[i * 2 + 1];
225
686
             j++)
226
 
          add_char (font_info, face, j);
 
687
          add_char (font_info, face, j, nocut);
227
688
    }
228
689
  else
229
690
    {
232
693
      for (char_code = FT_Get_First_Char (face, &glyph_index);
233
694
           glyph_index;
234
695
           char_code = FT_Get_Next_Char (face, char_code, &glyph_index))
235
 
        add_char (font_info, face, char_code);
 
696
        add_char (font_info, face, char_code, nocut);
236
697
    }
237
698
}
238
699
 
272
733
  struct grub_glyph_info *glyph;
273
734
  char line[512];
274
735
 
275
 
  for (glyph = font_info->glyph, num = 0; glyph; glyph = glyph->next, num++)
 
736
  for (glyph = font_info->glyphs_sorted, num = 0; num < font_info->num_glyphs;
 
737
       glyph++, num++)
276
738
    {
277
739
      int x, y, xmax, xmin, ymax, ymin;
278
740
      grub_uint8_t *bitmap, mask;
337
799
}
338
800
 
339
801
void
340
 
write_font (struct grub_font_info *font_info, char *output_file)
 
802
write_font_ascii_bitmap (struct grub_font_info *font_info, char *output_file)
 
803
{
 
804
  FILE *file;
 
805
  struct grub_glyph_info *glyph;
 
806
  int num; 
 
807
  
 
808
  file = fopen (output_file, "wb");
 
809
  if (! file)
 
810
    grub_util_error ("Can\'t write to file %s.", output_file);
 
811
 
 
812
  int correct_size;
 
813
  for (glyph = font_info->glyphs_sorted, num = 0; num < font_info->num_glyphs;
 
814
       glyph++, num++)
 
815
    {
 
816
      correct_size = 1;
 
817
      if (glyph->width != 8 || glyph->height != 16)
 
818
      {
 
819
        /* printf ("Width or height from glyph U+%04x not supported, skipping.\n", glyph->char_code);  */
 
820
        correct_size = 0;
 
821
      }
 
822
      int row;
 
823
      for (row = 0; row < glyph->height; row++)
 
824
        {
 
825
          if (correct_size)
 
826
            fwrite (&glyph->bitmap[row], sizeof(glyph->bitmap[row]), 1, file);
 
827
          else
 
828
            fwrite (&correct_size, 1, 1, file);
 
829
        }
 
830
    }
 
831
    fclose (file);
 
832
}
 
833
 
 
834
void
 
835
write_font_width_spec (struct grub_font_info *font_info, char *output_file)
 
836
{
 
837
  FILE *file;
 
838
  struct grub_glyph_info *glyph;
 
839
  grub_uint8_t *out;
 
840
 
 
841
  out = xmalloc (8192);
 
842
  memset (out, 0, 8192);
 
843
  
 
844
  file = fopen (output_file, "wb");
 
845
  if (! file)
 
846
    grub_util_error ("Can\'t write to file %s.", output_file);
 
847
 
 
848
  for (glyph = font_info->glyphs_sorted;
 
849
       glyph < font_info->glyphs_sorted + font_info->num_glyphs; glyph++)
 
850
    if (glyph->width > 12)
 
851
      out[glyph->char_code >> 3] |= (1 << (glyph->char_code & 7));
 
852
 
 
853
  fwrite (out, 8192, 1, file);
 
854
  fclose (file);
 
855
  free (out);
 
856
}
 
857
 
 
858
void
 
859
write_font_pf2 (struct grub_font_info *font_info, char *output_file)
341
860
{
342
861
  FILE *file;
343
862
  grub_uint32_t leng, data;
344
863
  char style_name[20], *font_name;
345
 
  struct grub_glyph_info *cur, *pre;
346
 
  int num, offset;
 
864
  int offset;
 
865
  struct grub_glyph_info *cur;
347
866
 
348
867
  file = fopen (output_file, "wb");
349
868
  if (! file)
350
 
    grub_util_error ("Can\'t write to file %s.", output_file);
 
869
    grub_util_error ("can\'t write to file %s.", output_file);
351
870
 
352
871
  offset = 0;
353
872
 
354
873
  leng = grub_cpu_to_be32 (4);
355
 
  grub_util_write_image ("FILE", 4, file);
 
874
  grub_util_write_image (FONT_FORMAT_SECTION_NAMES_FILE,
 
875
                         sizeof(FONT_FORMAT_SECTION_NAMES_FILE) - 1, file);
356
876
  grub_util_write_image ((char *) &leng, 4, file);
357
 
  grub_util_write_image ("PFF2", 4, file);
 
877
  grub_util_write_image (FONT_FORMAT_PFF2_MAGIC, 4, file);
358
878
  offset += 12;
359
879
 
360
880
  if (! font_info->name)
376
896
  font_name = xasprintf ("%s %s %d", font_info->name, &style_name[1],
377
897
                         font_info->size);
378
898
 
379
 
  write_string_section ("NAME", font_name, &offset, file);
380
 
  write_string_section ("FAMI", font_info->name, &offset, file);
381
 
  write_string_section ("WEIG",
 
899
  write_string_section (FONT_FORMAT_SECTION_NAMES_FONT_NAME,
 
900
                        font_name, &offset, file);
 
901
  write_string_section (FONT_FORMAT_SECTION_NAMES_FAMILY,
 
902
                        font_info->name, &offset, file);
 
903
  write_string_section (FONT_FORMAT_SECTION_NAMES_WEIGHT,
382
904
                        (font_info->style & FT_STYLE_FLAG_BOLD) ?
383
905
                        "bold" : "normal",
384
906
                        &offset, file);
385
 
  write_string_section ("SLAN",
 
907
  write_string_section (FONT_FORMAT_SECTION_NAMES_SLAN,
386
908
                        (font_info->style & FT_STYLE_FLAG_ITALIC) ?
387
909
                        "italic" : "normal",
388
910
                        &offset, file);
389
911
 
390
 
  write_be16_section ("PTSZ", font_info->size, &offset, file);
391
 
  write_be16_section ("MAXW", font_info->max_width, &offset, file);
392
 
  write_be16_section ("MAXH", font_info->max_height, &offset, file);
 
912
  write_be16_section (FONT_FORMAT_SECTION_NAMES_POINT_SIZE,
 
913
                      font_info->size, &offset, file);
 
914
  write_be16_section (FONT_FORMAT_SECTION_NAMES_MAX_CHAR_WIDTH,
 
915
                      font_info->max_width, &offset, file);
 
916
  write_be16_section (FONT_FORMAT_SECTION_NAMES_MAX_CHAR_HEIGHT,
 
917
                      font_info->max_height, &offset, file);
393
918
 
394
919
  if (! font_info->desc)
395
920
    {
407
932
        font_info->asce = font_info->max_y;
408
933
    }
409
934
 
410
 
  write_be16_section ("ASCE", font_info->asce, &offset, file);
411
 
  write_be16_section ("DESC", font_info->desc, &offset, file);
 
935
  write_be16_section (FONT_FORMAT_SECTION_NAMES_ASCENT,
 
936
                      font_info->asce, &offset, file);
 
937
  write_be16_section (FONT_FORMAT_SECTION_NAMES_DESCENT,
 
938
                      font_info->desc, &offset, file);
412
939
 
413
940
  if (font_verbosity > 0)
414
941
    {
419
946
      printf ("Font descent: %d\n", font_info->desc);
420
947
    }
421
948
 
422
 
  num = 0;
423
 
  pre = 0;
424
 
  cur = font_info->glyph;
425
 
  while (cur)
426
 
    {
427
 
      struct grub_glyph_info *nxt;
428
 
 
429
 
      nxt = cur->next;
430
 
      cur->next = pre;
431
 
      pre = cur;
432
 
      cur = nxt;
433
 
      num++;
434
 
    }
435
 
 
436
 
  font_info->glyph = pre;
437
 
 
438
949
  if (font_verbosity > 0)
439
 
    printf ("Number of glyph: %d\n", num);
 
950
    printf ("Number of glyph: %d\n", font_info->num_glyphs);
440
951
 
441
 
  leng = grub_cpu_to_be32 (num * 9);
442
 
  grub_util_write_image ("CHIX", 4, file);
 
952
  leng = grub_cpu_to_be32 (font_info->num_glyphs * 9);
 
953
  grub_util_write_image (FONT_FORMAT_SECTION_NAMES_CHAR_INDEX,
 
954
                         sizeof(FONT_FORMAT_SECTION_NAMES_CHAR_INDEX) - 1,
 
955
                         file);
443
956
  grub_util_write_image ((char *) &leng, 4, file);
444
 
  offset += 8 + num * 9 + 8;
 
957
  offset += 8 + font_info->num_glyphs * 9 + 8;
445
958
 
446
 
  for (cur = font_info->glyph; cur; cur = cur->next)
 
959
  for (cur = font_info->glyphs_sorted;
 
960
       cur < font_info->glyphs_sorted + font_info->num_glyphs; cur++)
447
961
    {
448
962
      data = grub_cpu_to_be32 (cur->char_code);
449
963
      grub_util_write_image ((char *) &data, 4, file);
455
969
    }
456
970
 
457
971
  leng = 0xffffffff;
458
 
  grub_util_write_image ("DATA", 4, file);
 
972
  grub_util_write_image (FONT_FORMAT_SECTION_NAMES_DATA,
 
973
                         sizeof(FONT_FORMAT_SECTION_NAMES_DATA) - 1, file);
459
974
  grub_util_write_image ((char *) &leng, 4, file);
460
975
 
461
 
  for (cur = font_info->glyph; cur; cur = cur->next)
 
976
  for (cur = font_info->glyphs_sorted;
 
977
       cur < font_info->glyphs_sorted + font_info->num_glyphs; cur++)
462
978
    {
463
979
      data = grub_cpu_to_be16 (cur->width);
464
980
      grub_util_write_image ((char *) &data, 2, file);
473
989
      grub_util_write_image ((char *) &cur->bitmap[0], cur->bitmap_size, file);
474
990
    }
475
991
 
476
 
  if (font_verbosity > 1)
477
 
    print_glyphs (font_info);
478
 
 
479
992
  fclose (file);
480
993
}
481
994
 
487
1000
  int font_index = 0;
488
1001
  int font_size = 0;
489
1002
  char *output_file = NULL;
 
1003
  enum file_formats file_format = PF2;
490
1004
 
491
1005
  memset (&font_info, 0, sizeof (font_info));
492
1006
 
546
1060
 
547
1061
                  a = strtoul (p, &p, 0);
548
1062
                  if (*p != '-')
549
 
                    grub_util_error ("Invalid font range");
 
1063
                    grub_util_error ("invalid font range");
550
1064
                  b = strtoul (p + 1, &p, 0);
551
1065
                  if ((font_info.num_range & (GRUB_FONT_RANGE_BLOCK - 1)) == 0)
552
1066
                    font_info.ranges = xrealloc (font_info.ranges,
553
1067
                                                 (font_info.num_range +
554
1068
                                                  GRUB_FONT_RANGE_BLOCK) *
555
 
                                                 sizeof (int) * 2);
 
1069
                                                 sizeof (grub_uint32_t) * 2);
556
1070
 
557
1071
                  font_info.ranges[font_info.num_range * 2] = a;
558
1072
                  font_info.ranges[font_info.num_range * 2 + 1] = b;
561
1075
                  if (*p)
562
1076
                    {
563
1077
                      if (*p != ',')
564
 
                        grub_util_error ("Invalid font range");
 
1078
                        grub_util_error ("invalid font range");
565
1079
                      else
566
1080
                        p++;
567
1081
                    }
591
1105
            font_verbosity++;
592
1106
            break;
593
1107
 
 
1108
          case 0x102:
 
1109
             file_format = ASCII_BITMAPS;
 
1110
             break;
 
1111
 
 
1112
          case 0x103:
 
1113
             file_format = WIDTH_SPEC;
 
1114
             break;
 
1115
 
594
1116
          default:
595
1117
            usage (1);
596
1118
            break;
597
1119
          }
598
1120
    }
599
1121
 
 
1122
  if (file_format == ASCII_BITMAPS && font_info.num_range > 0)
 
1123
    {
 
1124
      grub_util_error ("Option --ascii-bitmaps doesn't accept ranges (use ASCII).");
 
1125
      return 1;
 
1126
    }
 
1127
 
 
1128
  else if (file_format == ASCII_BITMAPS)
 
1129
    {
 
1130
      font_info.ranges = xrealloc (font_info.ranges,
 
1131
                                   GRUB_FONT_RANGE_BLOCK *
 
1132
                                   sizeof (grub_uint32_t) * 2);
 
1133
 
 
1134
      font_info.ranges[0] = (grub_uint32_t) 0x00;
 
1135
      font_info.ranges[1] = (grub_uint32_t) 0x7f;
 
1136
      font_info.num_range = 1;
 
1137
    }
 
1138
 
600
1139
  if (! output_file)
601
 
    grub_util_error ("No output file is specified.");
 
1140
    grub_util_error ("no output file is specified");
602
1141
 
603
1142
  if (FT_Init_FreeType (&ft_lib))
604
1143
    grub_util_error ("FT_Init_FreeType fails");
610
1149
 
611
1150
      if (FT_New_Face (ft_lib, argv[optind], font_index, &ft_face))
612
1151
        {
613
 
          grub_util_info ("Can't open file %s, index %d\n", argv[optind],
 
1152
          grub_util_info ("can't open file %s, index %d", argv[optind],
614
1153
                          font_index);
615
1154
          continue;
616
1155
        }
632
1171
      font_info.size = size;
633
1172
 
634
1173
      FT_Set_Pixel_Sizes (ft_face, size, size);
635
 
      add_font (&font_info, ft_face);
 
1174
      add_font (&font_info, ft_face, file_format != PF2);
636
1175
      FT_Done_Face (ft_face);
637
1176
    }
638
1177
 
639
1178
  FT_Done_FreeType (ft_lib);
640
1179
 
641
 
  write_font (&font_info, output_file);
 
1180
  {
 
1181
    int counter[65537];
 
1182
    struct grub_glyph_info *tmp, *cur;
 
1183
    int i;
 
1184
 
 
1185
    memset (counter, 0, sizeof (counter));
 
1186
 
 
1187
    for (cur = font_info.glyphs_unsorted; cur; cur = cur->next)
 
1188
      counter[(cur->char_code & 0xffff) + 1]++;
 
1189
    for (i = 0; i < 0x10000; i++)
 
1190
      counter[i+1] += counter[i];
 
1191
    tmp = xmalloc (font_info.num_glyphs
 
1192
                   * sizeof (tmp[0]));
 
1193
    for (cur = font_info.glyphs_unsorted; cur; cur = cur->next)
 
1194
      tmp[counter[(cur->char_code & 0xffff)]++] = *cur;
 
1195
 
 
1196
    memset (counter, 0, sizeof (counter));
 
1197
 
 
1198
    for (cur = tmp; cur < tmp + font_info.num_glyphs; cur++)
 
1199
      counter[((cur->char_code & 0xffff0000) >> 16) + 1]++;
 
1200
    for (i = 0; i < 0x10000; i++)
 
1201
      counter[i+1] += counter[i];
 
1202
    font_info.glyphs_sorted = xmalloc (font_info.num_glyphs
 
1203
                                        * sizeof (font_info.glyphs_sorted[0]));
 
1204
    for (cur = tmp; cur < tmp + font_info.num_glyphs; cur++)
 
1205
      font_info.glyphs_sorted[counter[(cur->char_code & 0xffff0000) >> 16]++]
 
1206
        = *cur;
 
1207
    free (tmp);
 
1208
  }
 
1209
 
 
1210
  switch (file_format)
 
1211
    {
 
1212
    case PF2:
 
1213
      write_font_pf2 (&font_info, output_file);
 
1214
      break;
 
1215
 
 
1216
    case ASCII_BITMAPS:
 
1217
      write_font_ascii_bitmap (&font_info, output_file);
 
1218
      break;
 
1219
 
 
1220
    case WIDTH_SPEC:
 
1221
      write_font_width_spec (&font_info, output_file);
 
1222
      break;
 
1223
    }
 
1224
 
 
1225
  if (font_verbosity > 1)
 
1226
    print_glyphs (&font_info);
642
1227
 
643
1228
  return 0;
644
1229
}