~ubuntu-branches/debian/stretch/grub2/stretch

« back to all changes in this revision

Viewing changes to util/grub-mkfont.c

Tags: upstream-1.98+20100705
ImportĀ upstreamĀ versionĀ 1.98+20100705

Show diffs side-by-side

added added

removed removed

Lines of Context:
19
19
#include <config.h>
20
20
#include <grub/types.h>
21
21
#include <grub/util/misc.h>
 
22
#include <grub/misc.h>
22
23
#include <grub/i18n.h>
23
24
#include <grub/fontformat.h>
 
25
#include <grub/font.h>
 
26
#include <grub/unicode.h>
24
27
 
25
28
#include <stdio.h>
26
29
#include <stdlib.h>
29
32
 
30
33
#include <ft2build.h>
31
34
#include FT_FREETYPE_H
 
35
#include FT_TRUETYPE_TAGS_H
 
36
#include FT_TRUETYPE_TABLES_H
32
37
#include <freetype/ftsynth.h>
33
38
 
 
39
#undef __FTERRORS_H__
 
40
#define FT_ERROR_START_LIST   const char *ft_errmsgs[] = { 
 
41
#define FT_ERRORDEF(e, v, s)  [e] = s,
 
42
#define FT_ERROR_END_LIST     };
 
43
#include FT_ERRORS_H   
 
44
 
34
45
#include "progname.h"
35
46
 
36
47
#define GRUB_FONT_DEFAULT_SIZE          16
47
58
  int y_ofs;
48
59
  int device_width;
49
60
  int bitmap_size;
50
 
  grub_uint8_t bitmap[0];
 
61
  grub_uint8_t *bitmap;
51
62
};
52
63
 
53
64
enum file_formats
54
65
{
55
66
  PF2,
56
 
  ASCII_BITMAPS 
 
67
  ASCII_BITMAPS,
 
68
  WIDTH_SPEC
57
69
};
58
70
 
59
71
#define GRUB_FONT_FLAG_BOLD             1
75
87
  int flags;
76
88
  int num_range;
77
89
  grub_uint32_t *ranges;
78
 
  struct grub_glyph_info *glyph;
 
90
  struct grub_glyph_info *glyphs_unsorted;
 
91
  struct grub_glyph_info *glyphs_sorted;
 
92
  int num_glyphs;
79
93
};
80
94
 
81
95
static struct option options[] =
95
109
  {"version", no_argument, 0, 'V'},
96
110
  {"verbose", no_argument, 0, 'v'},
97
111
  {"ascii-bitmaps", no_argument, 0, 0x102},
 
112
  {"width-spec", no_argument, 0, 0x103},
98
113
  {0, 0, 0, 0}
99
114
};
100
115
 
111
126
\nOptions:\n\
112
127
  -o, --output=FILE_NAME    set output file name\n\
113
128
  --ascii-bitmaps           save only the ASCII bitmaps\n\
 
129
  --width-spec              create width summary file\n\
114
130
  -i, --index=N             set face index\n\
115
131
  -r, --range=A-B[,C-D]     set font range\n\
116
132
  -n, --name=S              set font family name\n\
146
162
  *mask >>= 1;
147
163
}
148
164
 
149
 
void
150
 
add_char (struct grub_font_info *font_info, FT_Face face,
151
 
          grub_uint32_t char_code)
 
165
static void
 
166
add_glyph (struct grub_font_info *font_info, FT_UInt glyph_idx, FT_Face face,
 
167
           grub_uint32_t char_code, int nocut)
152
168
{
153
 
  struct grub_glyph_info *glyph_info, **p_glyph;
 
169
  struct grub_glyph_info *glyph_info;
154
170
  int width, height;
 
171
  int cuttop, cutbottom, cutleft, cutright;
155
172
  grub_uint8_t *data;
156
173
  int mask, i, j, bitmap_size;
157
174
  FT_GlyphSlot glyph;
158
175
  int flag = FT_LOAD_RENDER | FT_LOAD_MONOCHROME;
 
176
  FT_Error err;
159
177
 
160
178
  if (font_info->flags & GRUB_FONT_FLAG_NOBITMAP)
161
179
    flag |= FT_LOAD_NO_BITMAP;
165
183
  else if (font_info->flags & GRUB_FONT_FLAG_FORCEHINT)
166
184
    flag |= FT_LOAD_FORCE_AUTOHINT;
167
185
 
168
 
  if (FT_Load_Char (face, char_code, flag))
169
 
    return;
 
186
  err = FT_Load_Glyph (face, glyph_idx, flag);
 
187
  if (err)
 
188
    {
 
189
      printf ("Freetype Error %d loading glyph 0x%x for U+0x%x%s",
 
190
              err, glyph_idx, char_code & GRUB_FONT_CODE_CHAR_MASK,
 
191
              char_code & GRUB_FONT_CODE_RIGHT_JOINED
 
192
              ? ((char_code & GRUB_FONT_CODE_LEFT_JOINED) ? " (medial)":
 
193
                 " (leftmost)")
 
194
              : ((char_code & GRUB_FONT_CODE_LEFT_JOINED) ? " (rightmost)":
 
195
                 ""));
 
196
 
 
197
      if (err > 0 && err < (signed) ARRAY_SIZE (ft_errmsgs))
 
198
        printf (": %s\n", ft_errmsgs[err]);
 
199
      else
 
200
        printf ("\n");
 
201
      return;
 
202
    }
170
203
 
171
204
  glyph = face->glyph;
172
205
 
173
206
  if (font_info->flags & GRUB_FONT_FLAG_BOLD)
174
207
    FT_GlyphSlot_Embolden (glyph);
175
208
 
176
 
  p_glyph = &font_info->glyph;
177
 
  while ((*p_glyph) && ((*p_glyph)->char_code > char_code))
 
209
  if (glyph->next)
 
210
    printf ("%x\n", char_code);
 
211
 
 
212
  if (nocut)
 
213
    cuttop = cutbottom = cutleft = cutright = 0;
 
214
  else
178
215
    {
179
 
      p_glyph = &(*p_glyph)->next;
 
216
      for (cuttop = 0; cuttop < glyph->bitmap.rows; cuttop++)
 
217
        {
 
218
          for (j = 0; j < glyph->bitmap.width; j++)
 
219
            if (glyph->bitmap.buffer[j / 8 + cuttop * glyph->bitmap.pitch]
 
220
                & (1 << (7 - (j & 7))))
 
221
              break;
 
222
          if (j != glyph->bitmap.width)
 
223
            break;
 
224
        }
 
225
 
 
226
      for (cutbottom = glyph->bitmap.rows - 1; cutbottom >= 0; cutbottom--)
 
227
        {
 
228
          for (j = 0; j < glyph->bitmap.width; j++)
 
229
            if (glyph->bitmap.buffer[j / 8 + cutbottom * glyph->bitmap.pitch]
 
230
                & (1 << (7 - (j & 7))))
 
231
              break;
 
232
          if (j != glyph->bitmap.width)
 
233
            break;
 
234
        }
 
235
      cutbottom = glyph->bitmap.rows - 1 - cutbottom;
 
236
      if (cutbottom + cuttop >= glyph->bitmap.rows)
 
237
        cutbottom = 0;
 
238
 
 
239
      for (cutleft = 0; cutleft < glyph->bitmap.width; cutleft++)
 
240
        {
 
241
          for (j = 0; j < glyph->bitmap.rows; j++)
 
242
            if (glyph->bitmap.buffer[cutleft / 8 + j * glyph->bitmap.pitch]
 
243
                & (1 << (7 - (cutleft & 7))))
 
244
              break;
 
245
          if (j != glyph->bitmap.rows)
 
246
            break;
 
247
        }
 
248
      for (cutright = glyph->bitmap.width - 1; cutright >= 0; cutright--)
 
249
        {
 
250
          for (j = 0; j < glyph->bitmap.rows; j++)
 
251
            if (glyph->bitmap.buffer[cutright / 8 + j * glyph->bitmap.pitch]
 
252
                & (1 << (7 - (cutright & 7))))
 
253
              break;
 
254
          if (j != glyph->bitmap.rows)
 
255
            break;
 
256
        }
 
257
      cutright = glyph->bitmap.width - 1 - cutright;
 
258
      if (cutright + cutleft >= glyph->bitmap.width)
 
259
        cutright = 0;
180
260
    }
181
261
 
182
 
  /* Ignore duplicated glyph.  */
183
 
  if ((*p_glyph) && ((*p_glyph)->char_code == char_code))
184
 
    return;
185
 
 
186
 
  width = glyph->bitmap.width;
187
 
  height = glyph->bitmap.rows;
 
262
  width = glyph->bitmap.width - cutleft - cutright;
 
263
  height = glyph->bitmap.rows - cutbottom - cuttop;
188
264
 
189
265
  bitmap_size = ((width * height + 7) / 8);
190
 
  glyph_info = xmalloc (sizeof (struct grub_glyph_info) + bitmap_size);
 
266
  glyph_info = xmalloc (sizeof (struct grub_glyph_info));
 
267
  glyph_info->bitmap = xmalloc (bitmap_size);
191
268
  glyph_info->bitmap_size = bitmap_size;
192
269
 
193
 
  glyph_info->next = *p_glyph;
194
 
  *p_glyph = glyph_info;
 
270
  glyph_info->next = font_info->glyphs_unsorted;
 
271
  font_info->glyphs_unsorted = glyph_info;
 
272
  font_info->num_glyphs++;
195
273
 
196
274
  glyph_info->char_code = char_code;
197
275
  glyph_info->width = width;
198
276
  glyph_info->height = height;
199
 
  glyph_info->x_ofs = glyph->bitmap_left;
200
 
  glyph_info->y_ofs = glyph->bitmap_top - height;
 
277
  glyph_info->x_ofs = glyph->bitmap_left + cutleft;
 
278
  glyph_info->y_ofs = glyph->bitmap_top - height - cuttop;
201
279
  glyph_info->device_width = glyph->metrics.horiAdvance / 64;
202
280
 
203
281
  if (width > font_info->max_width)
214
292
 
215
293
  mask = 0;
216
294
  data = &glyph_info->bitmap[0] - 1;
217
 
  for (j = 0; j < height; j++)
218
 
    for (i = 0; i < width; i++)
 
295
  for (j = cuttop; j < height + cuttop; j++)
 
296
    for (i = cutleft; i < width + cutleft; i++)
219
297
      add_pixel (&data, &mask,
220
298
                 glyph->bitmap.buffer[i / 8 + j * glyph->bitmap.pitch] &
221
299
                 (1 << (7 - (i & 7))));
222
300
}
223
301
 
 
302
struct glyph_replace *subst_rightjoin, *subst_leftjoin, *subst_medijoin;
 
303
 
 
304
struct glyph_replace
 
305
{
 
306
  struct glyph_replace *next;
 
307
  grub_uint32_t from, to;
 
308
};
 
309
 
 
310
/* TODO: sort glyph_replace and use binary search if necessary.  */
 
311
static void
 
312
add_char (struct grub_font_info *font_info, FT_Face face,
 
313
          grub_uint32_t char_code, int nocut)
 
314
{
 
315
  FT_UInt glyph_idx;
 
316
  struct glyph_replace *cur;
 
317
 
 
318
  glyph_idx = FT_Get_Char_Index (face, char_code);
 
319
  if (!glyph_idx)
 
320
    return;
 
321
  add_glyph (font_info, glyph_idx, face, char_code, nocut);
 
322
  for (cur = subst_rightjoin; cur; cur = cur->next)
 
323
    if (cur->from == glyph_idx)
 
324
      {
 
325
        add_glyph (font_info, cur->to, face,
 
326
                   char_code | GRUB_FONT_CODE_RIGHT_JOINED, nocut);
 
327
        break;
 
328
      }
 
329
  if (!cur && char_code >= GRUB_UNICODE_ARABIC_START
 
330
      && char_code < GRUB_UNICODE_ARABIC_END)
 
331
    {
 
332
      int i;
 
333
      for (i = 0; grub_unicode_arabic_shapes[i].code; i++)
 
334
        if (grub_unicode_arabic_shapes[i].code == char_code
 
335
            && grub_unicode_arabic_shapes[i].right_linked)
 
336
          {
 
337
            FT_UInt idx2;
 
338
            idx2 = FT_Get_Char_Index (face, grub_unicode_arabic_shapes[i]
 
339
                                      .right_linked);
 
340
            if (idx2)
 
341
              add_glyph (font_info, idx2, face,
 
342
                         char_code | GRUB_FONT_CODE_RIGHT_JOINED, nocut);
 
343
            break;
 
344
          }
 
345
              
 
346
    }
 
347
 
 
348
  for (cur = subst_leftjoin; cur; cur = cur->next)
 
349
    if (cur->from == glyph_idx)
 
350
      {
 
351
        add_glyph (font_info, cur->to, face,
 
352
                   char_code | GRUB_FONT_CODE_LEFT_JOINED, nocut);
 
353
        break;
 
354
      }
 
355
  if (!cur && char_code >= GRUB_UNICODE_ARABIC_START
 
356
      && char_code < GRUB_UNICODE_ARABIC_END)
 
357
    {
 
358
      int i;
 
359
      for (i = 0; grub_unicode_arabic_shapes[i].code; i++)
 
360
        if (grub_unicode_arabic_shapes[i].code == char_code
 
361
            && grub_unicode_arabic_shapes[i].left_linked)
 
362
          {
 
363
            FT_UInt idx2;
 
364
            idx2 = FT_Get_Char_Index (face, grub_unicode_arabic_shapes[i]
 
365
                                      .left_linked);
 
366
            if (idx2)
 
367
              add_glyph (font_info, idx2, face,
 
368
                         char_code | GRUB_FONT_CODE_LEFT_JOINED, nocut);
 
369
            break;
 
370
          }
 
371
              
 
372
    }
 
373
  for (cur = subst_medijoin; cur; cur = cur->next)
 
374
    if (cur->from == glyph_idx)
 
375
      {
 
376
        add_glyph (font_info, cur->to, face,
 
377
                   char_code | GRUB_FONT_CODE_LEFT_JOINED
 
378
                   | GRUB_FONT_CODE_RIGHT_JOINED, nocut);
 
379
        break;
 
380
      }
 
381
  if (!cur && char_code >= GRUB_UNICODE_ARABIC_START
 
382
      && char_code < GRUB_UNICODE_ARABIC_END)
 
383
    {
 
384
      int i;
 
385
      for (i = 0; grub_unicode_arabic_shapes[i].code; i++)
 
386
        if (grub_unicode_arabic_shapes[i].code == char_code
 
387
            && grub_unicode_arabic_shapes[i].both_linked)
 
388
          {
 
389
            FT_UInt idx2;
 
390
            idx2 = FT_Get_Char_Index (face, grub_unicode_arabic_shapes[i]
 
391
                                      .both_linked);
 
392
            if (idx2)
 
393
              add_glyph (font_info, idx2, face,
 
394
                         char_code | GRUB_FONT_CODE_LEFT_JOINED
 
395
                         | GRUB_FONT_CODE_RIGHT_JOINED, nocut);
 
396
            break;
 
397
          }
 
398
              
 
399
    }
 
400
}
 
401
 
 
402
struct gsub_header
 
403
{
 
404
  grub_uint32_t version;
 
405
  grub_uint16_t scripts_off;
 
406
  grub_uint16_t features_off;
 
407
  grub_uint16_t lookups_off;
 
408
} __attribute__ ((packed));
 
409
 
 
410
struct gsub_features
 
411
{
 
412
  grub_uint16_t count;
 
413
  struct
 
414
  {
 
415
#define FEATURE_FINA 0x66696e61
 
416
#define FEATURE_INIT 0x696e6974
 
417
#define FEATURE_MEDI 0x6d656469
 
418
#define FEATURE_AALT 0x61616c74
 
419
#define FEATURE_LIGA 0x6c696761
 
420
#define FEATURE_RLIG 0x726c6967
 
421
    grub_uint32_t feature_tag;
 
422
    grub_uint16_t offset;
 
423
  } __attribute__ ((packed)) features[0];
 
424
} __attribute__ ((packed));
 
425
 
 
426
struct gsub_feature
 
427
{
 
428
  grub_uint16_t params;
 
429
  grub_uint16_t lookupcount;
 
430
  grub_uint16_t lookupindices[0];
 
431
} __attribute__ ((packed));
 
432
 
 
433
struct gsub_lookup_list
 
434
{
 
435
  grub_uint16_t count;
 
436
  grub_uint16_t offsets[0];
 
437
} __attribute__ ((packed));
 
438
 
 
439
struct gsub_lookup
 
440
{
 
441
  grub_uint16_t type;
 
442
  grub_uint16_t flag;
 
443
  grub_uint16_t subtablecount;
 
444
  grub_uint16_t subtables[0];
 
445
} __attribute__ ((packed));
 
446
 
 
447
struct gsub_substitution
 
448
{
 
449
  grub_uint16_t type;
 
450
  grub_uint16_t coverage_off;
 
451
  union
 
452
  {
 
453
    grub_int16_t delta;
 
454
    struct
 
455
    {
 
456
      grub_int16_t count;
 
457
      grub_uint16_t repl[0];
 
458
    };
 
459
  };
 
460
} __attribute__ ((packed));
 
461
 
 
462
struct gsub_coverage_list
 
463
{
 
464
  grub_uint16_t type;
 
465
  grub_uint16_t count;
 
466
  grub_uint16_t glyphs[0];
 
467
} __attribute__ ((packed));
 
468
 
 
469
struct gsub_coverage_ranges
 
470
{
 
471
  grub_uint16_t type;
 
472
  grub_uint16_t count;
 
473
  struct 
 
474
  {
 
475
    grub_uint16_t start;
 
476
    grub_uint16_t end;
 
477
    grub_uint16_t start_index;
 
478
  } __attribute__ ((packed)) ranges[0];
 
479
} __attribute__ ((packed));
 
480
 
 
481
#define GSUB_SINGLE_SUBSTITUTION 1
 
482
 
 
483
#define GSUB_SUBSTITUTION_DELTA 1
 
484
#define GSUB_SUBSTITUTION_MAP 2
 
485
 
 
486
#define GSUB_COVERAGE_LIST 1
 
487
#define GSUB_COVERAGE_RANGE 2
 
488
 
 
489
#define GSUB_RTL_CHAR 1
 
490
 
 
491
static void
 
492
add_subst (grub_uint32_t from, grub_uint32_t to, struct glyph_replace **target)
 
493
{
 
494
  struct glyph_replace *new = xmalloc (sizeof (*new));
 
495
  new->next = *target;
 
496
  new->from = from;
 
497
  new->to = to;
 
498
  *target = new;
 
499
}
 
500
 
 
501
static void
 
502
process_cursive (struct gsub_feature *feature,
 
503
                 struct gsub_lookup_list *lookups,
 
504
                 grub_uint32_t feattag)
 
505
{
 
506
  int j, k;
 
507
  int i;
 
508
  struct glyph_replace **target;
 
509
  struct gsub_substitution *sub;
 
510
 
 
511
  auto inline void subst (grub_uint32_t glyph);
 
512
  void subst (grub_uint32_t glyph)
 
513
  {
 
514
    grub_uint16_t substtype;
 
515
    substtype = grub_be_to_cpu16 (sub->type);
 
516
 
 
517
    if (substtype == GSUB_SUBSTITUTION_DELTA)
 
518
      add_subst (glyph, glyph + grub_be_to_cpu16 (sub->delta), target);
 
519
    else if (i >= grub_be_to_cpu16 (sub->count))
 
520
      printf ("Out of range substitution (%d, %d)\n", i,
 
521
              grub_be_to_cpu16 (sub->count));
 
522
    else
 
523
      add_subst (glyph, grub_be_to_cpu16 (sub->repl[i++]), target);
 
524
  }
 
525
 
 
526
  for (j = 0; j < grub_be_to_cpu16 (feature->lookupcount); j++)
 
527
    {
 
528
      int lookup_index = grub_be_to_cpu16 (feature->lookupindices[j]);
 
529
      struct gsub_lookup *lookup;
 
530
      if (lookup_index >= grub_be_to_cpu16 (lookups->count))
 
531
        {
 
532
          printf ("Out of range lookup: %d\n", lookup_index);
 
533
          continue;
 
534
        }
 
535
      lookup = (struct gsub_lookup *)
 
536
        ((grub_uint8_t *) lookups 
 
537
         + grub_be_to_cpu16 (lookups->offsets[lookup_index]));
 
538
      if (grub_be_to_cpu16 (lookup->type) != GSUB_SINGLE_SUBSTITUTION)
 
539
        {
 
540
          printf ("Unsupported substitution type: %d\n",
 
541
                  grub_be_to_cpu16 (lookup->type));
 
542
          continue;
 
543
        }                     
 
544
      if (grub_be_to_cpu16 (lookup->flag) & ~GSUB_RTL_CHAR)
 
545
        {
 
546
          printf ("Unsupported substitution flag: 0x%x\n",
 
547
                  grub_be_to_cpu16 (lookup->flag));
 
548
        }
 
549
      switch (feattag)
 
550
        {
 
551
        case FEATURE_INIT:
 
552
          if (grub_be_to_cpu16 (lookup->flag) & GSUB_RTL_CHAR)
 
553
            target = &subst_leftjoin;
 
554
          else
 
555
            target = &subst_rightjoin;
 
556
          break;
 
557
        case FEATURE_FINA:
 
558
          if (grub_be_to_cpu16 (lookup->flag) & GSUB_RTL_CHAR)
 
559
            target = &subst_rightjoin;
 
560
          else
 
561
            target = &subst_leftjoin;
 
562
          break;
 
563
        case FEATURE_MEDI:
 
564
          target = &subst_medijoin;
 
565
          break;          
 
566
        }
 
567
      for (k = 0; k < grub_be_to_cpu16 (lookup->subtablecount); k++)
 
568
        {
 
569
          sub = (struct gsub_substitution *)
 
570
            ((grub_uint8_t *) lookup + grub_be_to_cpu16 (lookup->subtables[k]));
 
571
          grub_uint16_t substtype;
 
572
          substtype = grub_be_to_cpu16 (sub->type);
 
573
          if (substtype != GSUB_SUBSTITUTION_MAP
 
574
              && substtype != GSUB_SUBSTITUTION_DELTA)
 
575
            {
 
576
              printf ("Unsupported substitution specification: %d\n",
 
577
                      substtype);
 
578
              continue;
 
579
            }
 
580
          void *coverage = (grub_uint8_t *) sub
 
581
            + grub_be_to_cpu16 (sub->coverage_off);
 
582
          grub_uint32_t covertype;
 
583
          covertype = grub_be_to_cpu16 (*(grub_uint16_t * __attribute__ ((packed))) coverage);
 
584
          i = 0;
 
585
          if (covertype == GSUB_COVERAGE_LIST)
 
586
            {
 
587
              struct gsub_coverage_list *cover = coverage;
 
588
              int l;
 
589
              for (l = 0; l < grub_be_to_cpu16 (cover->count); l++)
 
590
                subst (grub_be_to_cpu16 (cover->glyphs[l]));
 
591
            }
 
592
          else if (covertype == GSUB_COVERAGE_RANGE)
 
593
            {
 
594
              struct gsub_coverage_ranges *cover = coverage;
 
595
              int l, m;
 
596
              for (l = 0; l < grub_be_to_cpu16 (cover->count); l++)
 
597
                for (m = grub_be_to_cpu16 (cover->ranges[l].start);
 
598
                     m <= grub_be_to_cpu16 (cover->ranges[l].end); m++)
 
599
                  subst (m);
 
600
            }
 
601
          else
 
602
            printf ("Unsupported coverage specification: %d\n", covertype);
 
603
        }
 
604
    }
 
605
}
 
606
 
224
607
void
225
 
add_font (struct grub_font_info *font_info, FT_Face face)
 
608
add_font (struct grub_font_info *font_info, FT_Face face, int nocut)
226
609
{
 
610
  struct gsub_header *gsub = NULL;
 
611
  FT_ULong gsub_len = 0;
 
612
 
 
613
  if (!FT_Load_Sfnt_Table (face, TTAG_GSUB, 0, NULL, &gsub_len))
 
614
    {
 
615
      gsub = xmalloc (gsub_len);
 
616
      if (FT_Load_Sfnt_Table (face, TTAG_GSUB, 0, (void *) gsub, &gsub_len))
 
617
        {
 
618
          free (gsub);
 
619
          gsub = NULL;
 
620
          gsub_len = 0;
 
621
        }
 
622
    }
 
623
  if (gsub)
 
624
    {
 
625
      struct gsub_features *features 
 
626
        = (struct gsub_features *) (((grub_uint8_t *) gsub)
 
627
                                    + grub_be_to_cpu16 (gsub->features_off));
 
628
      struct gsub_lookup_list *lookups
 
629
        = (struct gsub_lookup_list *) (((grub_uint8_t *) gsub)
 
630
                                       + grub_be_to_cpu16 (gsub->lookups_off));
 
631
      int i;
 
632
      int nfeatures = grub_be_to_cpu16 (features->count);
 
633
      for (i = 0; i < nfeatures; i++)
 
634
        {
 
635
          struct gsub_feature *feature = (struct gsub_feature *)
 
636
            ((grub_uint8_t *) features
 
637
             + grub_be_to_cpu16 (features->features[i].offset));
 
638
          grub_uint32_t feattag
 
639
            = grub_be_to_cpu32 (features->features[i].feature_tag);
 
640
          if (feature->params)
 
641
            printf ("WARNING: unsupported feature parameters: %x\n",
 
642
                    grub_be_to_cpu16 (feature->params));
 
643
          switch (feattag)
 
644
            {
 
645
              /* Used for retrieving all possible variants. Useless in grub.  */
 
646
            case FEATURE_AALT:
 
647
              break;
 
648
 
 
649
              /* FIXME: Add ligature support.  */
 
650
            case FEATURE_LIGA:
 
651
            case FEATURE_RLIG:
 
652
              break;
 
653
 
 
654
              /* Cursive form variants.  */
 
655
            case FEATURE_FINA:
 
656
            case FEATURE_INIT:
 
657
            case FEATURE_MEDI:
 
658
              process_cursive (feature, lookups, feattag);
 
659
              break;
 
660
 
 
661
            default:
 
662
              {
 
663
                char str[5];
 
664
                int j;
 
665
                memcpy (str, &features->features[i].feature_tag,
 
666
                        sizeof (features->features[i].feature_tag));
 
667
                str[4] = 0;
 
668
                for (j = 0; j < 4; j++)
 
669
                  if (!grub_isgraph (str[j]))
 
670
                    str[j] = '?';
 
671
                printf ("Unknown gsub feature 0x%x (%s)\n", feattag, str);
 
672
              }
 
673
            }
 
674
        }
 
675
    }
 
676
 
227
677
  if (font_info->num_range)
228
678
    {
229
679
      int i;
232
682
      for (i = 0; i < font_info->num_range; i++)
233
683
        for (j = font_info->ranges[i * 2]; j <= font_info->ranges[i * 2 + 1];
234
684
             j++)
235
 
          add_char (font_info, face, j);
 
685
          add_char (font_info, face, j, nocut);
236
686
    }
237
687
  else
238
688
    {
241
691
      for (char_code = FT_Get_First_Char (face, &glyph_index);
242
692
           glyph_index;
243
693
           char_code = FT_Get_Next_Char (face, char_code, &glyph_index))
244
 
        add_char (font_info, face, char_code);
 
694
        add_char (font_info, face, char_code, nocut);
245
695
    }
246
696
}
247
697
 
281
731
  struct grub_glyph_info *glyph;
282
732
  char line[512];
283
733
 
284
 
  for (glyph = font_info->glyph, num = 0; glyph; glyph = glyph->next, num++)
 
734
  for (glyph = font_info->glyphs_sorted, num = 0; num < font_info->num_glyphs;
 
735
       glyph++, num++)
285
736
    {
286
737
      int x, y, xmax, xmin, ymax, ymin;
287
738
      grub_uint8_t *bitmap, mask;
357
808
    grub_util_error ("Can\'t write to file %s.", output_file);
358
809
 
359
810
  int correct_size;
360
 
  for (glyph = font_info->glyph, num = 0; glyph; glyph = glyph->next, num++)
 
811
  for (glyph = font_info->glyphs_sorted, num = 0; num < font_info->num_glyphs;
 
812
       glyph++, num++)
361
813
    {
362
814
      correct_size = 1;
363
815
      if (glyph->width != 8 || glyph->height != 16)
378
830
}
379
831
 
380
832
void
 
833
write_font_width_spec (struct grub_font_info *font_info, char *output_file)
 
834
{
 
835
  FILE *file;
 
836
  struct grub_glyph_info *glyph;
 
837
  grub_uint8_t *out;
 
838
 
 
839
  out = xmalloc (8192);
 
840
  memset (out, 0, 8192);
 
841
  
 
842
  file = fopen (output_file, "wb");
 
843
  if (! file)
 
844
    grub_util_error ("Can\'t write to file %s.", output_file);
 
845
 
 
846
  for (glyph = font_info->glyphs_sorted;
 
847
       glyph < font_info->glyphs_sorted + font_info->num_glyphs; glyph++)
 
848
    if (glyph->width > 12)
 
849
      out[glyph->char_code >> 3] |= (1 << (glyph->char_code & 7));
 
850
 
 
851
  fwrite (out, 8192, 1, file);
 
852
  fclose (file);
 
853
  free (out);
 
854
}
 
855
 
 
856
void
381
857
write_font_pf2 (struct grub_font_info *font_info, char *output_file)
382
858
{
383
859
  FILE *file;
384
860
  grub_uint32_t leng, data;
385
861
  char style_name[20], *font_name;
386
 
  struct grub_glyph_info *cur, *pre;
387
 
  int num, offset;
 
862
  int offset;
 
863
  struct grub_glyph_info *cur;
388
864
 
389
865
  file = fopen (output_file, "wb");
390
866
  if (! file)
468
944
      printf ("Font descent: %d\n", font_info->desc);
469
945
    }
470
946
 
471
 
  num = 0;
472
 
  pre = 0;
473
 
  cur = font_info->glyph;
474
 
  while (cur)
475
 
    {
476
 
      struct grub_glyph_info *nxt;
477
 
 
478
 
      nxt = cur->next;
479
 
      cur->next = pre;
480
 
      pre = cur;
481
 
      cur = nxt;
482
 
      num++;
483
 
    }
484
 
 
485
 
  font_info->glyph = pre;
486
 
 
487
947
  if (font_verbosity > 0)
488
 
    printf ("Number of glyph: %d\n", num);
 
948
    printf ("Number of glyph: %d\n", font_info->num_glyphs);
489
949
 
490
 
  leng = grub_cpu_to_be32 (num * 9);
 
950
  leng = grub_cpu_to_be32 (font_info->num_glyphs * 9);
491
951
  grub_util_write_image (FONT_FORMAT_SECTION_NAMES_CHAR_INDEX,
492
952
                         sizeof(FONT_FORMAT_SECTION_NAMES_CHAR_INDEX) - 1,
493
953
                         file);
494
954
  grub_util_write_image ((char *) &leng, 4, file);
495
 
  offset += 8 + num * 9 + 8;
 
955
  offset += 8 + font_info->num_glyphs * 9 + 8;
496
956
 
497
 
  for (cur = font_info->glyph; cur; cur = cur->next)
 
957
  for (cur = font_info->glyphs_sorted;
 
958
       cur < font_info->glyphs_sorted + font_info->num_glyphs; cur++)
498
959
    {
499
960
      data = grub_cpu_to_be32 (cur->char_code);
500
961
      grub_util_write_image ((char *) &data, 4, file);
510
971
                         sizeof(FONT_FORMAT_SECTION_NAMES_DATA) - 1, file);
511
972
  grub_util_write_image ((char *) &leng, 4, file);
512
973
 
513
 
  for (cur = font_info->glyph; cur; cur = cur->next)
 
974
  for (cur = font_info->glyphs_sorted;
 
975
       cur < font_info->glyphs_sorted + font_info->num_glyphs; cur++)
514
976
    {
515
977
      data = grub_cpu_to_be16 (cur->width);
516
978
      grub_util_write_image ((char *) &data, 2, file);
645
1107
             file_format = ASCII_BITMAPS;
646
1108
             break;
647
1109
 
 
1110
          case 0x103:
 
1111
             file_format = WIDTH_SPEC;
 
1112
             break;
 
1113
 
648
1114
          default:
649
1115
            usage (1);
650
1116
            break;
703
1169
      font_info.size = size;
704
1170
 
705
1171
      FT_Set_Pixel_Sizes (ft_face, size, size);
706
 
      add_font (&font_info, ft_face);
 
1172
      add_font (&font_info, ft_face, file_format != PF2);
707
1173
      FT_Done_Face (ft_face);
708
1174
    }
709
1175
 
710
1176
  FT_Done_FreeType (ft_lib);
711
1177
 
712
 
  if (file_format == PF2)
713
 
    write_font_pf2 (&font_info, output_file);
714
 
  else if (file_format == ASCII_BITMAPS)
715
 
    write_font_ascii_bitmap (&font_info, output_file);
 
1178
  {
 
1179
    int counter[65537];
 
1180
    struct grub_glyph_info *tmp, *cur;
 
1181
    int i;
 
1182
 
 
1183
    memset (counter, 0, sizeof (counter));
 
1184
 
 
1185
    for (cur = font_info.glyphs_unsorted; cur; cur = cur->next)
 
1186
      counter[(cur->char_code & 0xffff) + 1]++;
 
1187
    for (i = 0; i < 0x10000; i++)
 
1188
      counter[i+1] += counter[i];
 
1189
    tmp = xmalloc (font_info.num_glyphs
 
1190
                   * sizeof (tmp[0]));
 
1191
    for (cur = font_info.glyphs_unsorted; cur; cur = cur->next)
 
1192
      tmp[counter[(cur->char_code & 0xffff)]++] = *cur;
 
1193
 
 
1194
    memset (counter, 0, sizeof (counter));
 
1195
 
 
1196
    for (cur = tmp; cur < tmp + font_info.num_glyphs; cur++)
 
1197
      counter[((cur->char_code & 0xffff0000) >> 16) + 1]++;
 
1198
    for (i = 0; i < 0x10000; i++)
 
1199
      counter[i+1] += counter[i];
 
1200
    font_info.glyphs_sorted = xmalloc (font_info.num_glyphs
 
1201
                                        * sizeof (font_info.glyphs_sorted[0]));
 
1202
    for (cur = tmp; cur < tmp + font_info.num_glyphs; cur++)
 
1203
      font_info.glyphs_sorted[counter[(cur->char_code & 0xffff0000) >> 16]++]
 
1204
        = *cur;
 
1205
    free (tmp);
 
1206
  }
 
1207
 
 
1208
  switch (file_format)
 
1209
    {
 
1210
    case PF2:
 
1211
      write_font_pf2 (&font_info, output_file);
 
1212
      break;
 
1213
 
 
1214
    case ASCII_BITMAPS:
 
1215
      write_font_ascii_bitmap (&font_info, output_file);
 
1216
      break;
 
1217
 
 
1218
    case WIDTH_SPEC:
 
1219
      write_font_width_spec (&font_info, output_file);
 
1220
      break;
 
1221
    }
716
1222
 
717
1223
  if (font_verbosity > 1)
718
1224
    print_glyphs (&font_info);