165
183
else if (font_info->flags & GRUB_FONT_FLAG_FORCEHINT)
166
184
flag |= FT_LOAD_FORCE_AUTOHINT;
168
if (FT_Load_Char (face, char_code, flag))
186
err = FT_Load_Glyph (face, glyph_idx, flag);
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)":
194
: ((char_code & GRUB_FONT_CODE_LEFT_JOINED) ? " (rightmost)":
197
if (err > 0 && err < (signed) ARRAY_SIZE (ft_errmsgs))
198
printf (": %s\n", ft_errmsgs[err]);
171
204
glyph = face->glyph;
173
206
if (font_info->flags & GRUB_FONT_FLAG_BOLD)
174
207
FT_GlyphSlot_Embolden (glyph);
176
p_glyph = &font_info->glyph;
177
while ((*p_glyph) && ((*p_glyph)->char_code > char_code))
210
printf ("%x\n", char_code);
213
cuttop = cutbottom = cutleft = cutright = 0;
179
p_glyph = &(*p_glyph)->next;
216
for (cuttop = 0; cuttop < glyph->bitmap.rows; cuttop++)
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))))
222
if (j != glyph->bitmap.width)
226
for (cutbottom = glyph->bitmap.rows - 1; cutbottom >= 0; cutbottom--)
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))))
232
if (j != glyph->bitmap.width)
235
cutbottom = glyph->bitmap.rows - 1 - cutbottom;
236
if (cutbottom + cuttop >= glyph->bitmap.rows)
239
for (cutleft = 0; cutleft < glyph->bitmap.width; cutleft++)
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))))
245
if (j != glyph->bitmap.rows)
248
for (cutright = glyph->bitmap.width - 1; cutright >= 0; cutright--)
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))))
254
if (j != glyph->bitmap.rows)
257
cutright = glyph->bitmap.width - 1 - cutright;
258
if (cutright + cutleft >= glyph->bitmap.width)
182
/* Ignore duplicated glyph. */
183
if ((*p_glyph) && ((*p_glyph)->char_code == char_code))
186
width = glyph->bitmap.width;
187
height = glyph->bitmap.rows;
262
width = glyph->bitmap.width - cutleft - cutright;
263
height = glyph->bitmap.rows - cutbottom - cuttop;
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;
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++;
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;
203
281
if (width > font_info->max_width)
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))));
302
struct glyph_replace *subst_rightjoin, *subst_leftjoin, *subst_medijoin;
306
struct glyph_replace *next;
307
grub_uint32_t from, to;
310
/* TODO: sort glyph_replace and use binary search if necessary. */
312
add_char (struct grub_font_info *font_info, FT_Face face,
313
grub_uint32_t char_code, int nocut)
316
struct glyph_replace *cur;
318
glyph_idx = FT_Get_Char_Index (face, char_code);
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)
325
add_glyph (font_info, cur->to, face,
326
char_code | GRUB_FONT_CODE_RIGHT_JOINED, nocut);
329
if (!cur && char_code >= GRUB_UNICODE_ARABIC_START
330
&& char_code < GRUB_UNICODE_ARABIC_END)
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)
338
idx2 = FT_Get_Char_Index (face, grub_unicode_arabic_shapes[i]
341
add_glyph (font_info, idx2, face,
342
char_code | GRUB_FONT_CODE_RIGHT_JOINED, nocut);
348
for (cur = subst_leftjoin; cur; cur = cur->next)
349
if (cur->from == glyph_idx)
351
add_glyph (font_info, cur->to, face,
352
char_code | GRUB_FONT_CODE_LEFT_JOINED, nocut);
355
if (!cur && char_code >= GRUB_UNICODE_ARABIC_START
356
&& char_code < GRUB_UNICODE_ARABIC_END)
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)
364
idx2 = FT_Get_Char_Index (face, grub_unicode_arabic_shapes[i]
367
add_glyph (font_info, idx2, face,
368
char_code | GRUB_FONT_CODE_LEFT_JOINED, nocut);
373
for (cur = subst_medijoin; cur; cur = cur->next)
374
if (cur->from == glyph_idx)
376
add_glyph (font_info, cur->to, face,
377
char_code | GRUB_FONT_CODE_LEFT_JOINED
378
| GRUB_FONT_CODE_RIGHT_JOINED, nocut);
381
if (!cur && char_code >= GRUB_UNICODE_ARABIC_START
382
&& char_code < GRUB_UNICODE_ARABIC_END)
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)
390
idx2 = FT_Get_Char_Index (face, grub_unicode_arabic_shapes[i]
393
add_glyph (font_info, idx2, face,
394
char_code | GRUB_FONT_CODE_LEFT_JOINED
395
| GRUB_FONT_CODE_RIGHT_JOINED, nocut);
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));
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));
428
grub_uint16_t params;
429
grub_uint16_t lookupcount;
430
grub_uint16_t lookupindices[0];
431
} __attribute__ ((packed));
433
struct gsub_lookup_list
436
grub_uint16_t offsets[0];
437
} __attribute__ ((packed));
443
grub_uint16_t subtablecount;
444
grub_uint16_t subtables[0];
445
} __attribute__ ((packed));
447
struct gsub_substitution
450
grub_uint16_t coverage_off;
457
grub_uint16_t repl[0];
460
} __attribute__ ((packed));
462
struct gsub_coverage_list
466
grub_uint16_t glyphs[0];
467
} __attribute__ ((packed));
469
struct gsub_coverage_ranges
477
grub_uint16_t start_index;
478
} __attribute__ ((packed)) ranges[0];
479
} __attribute__ ((packed));
481
#define GSUB_SINGLE_SUBSTITUTION 1
483
#define GSUB_SUBSTITUTION_DELTA 1
484
#define GSUB_SUBSTITUTION_MAP 2
486
#define GSUB_COVERAGE_LIST 1
487
#define GSUB_COVERAGE_RANGE 2
489
#define GSUB_RTL_CHAR 1
492
add_subst (grub_uint32_t from, grub_uint32_t to, struct glyph_replace **target)
494
struct glyph_replace *new = xmalloc (sizeof (*new));
502
process_cursive (struct gsub_feature *feature,
503
struct gsub_lookup_list *lookups,
504
grub_uint32_t feattag)
508
struct glyph_replace **target;
509
struct gsub_substitution *sub;
511
auto inline void subst (grub_uint32_t glyph);
512
void subst (grub_uint32_t glyph)
514
grub_uint16_t substtype;
515
substtype = grub_be_to_cpu16 (sub->type);
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));
523
add_subst (glyph, grub_be_to_cpu16 (sub->repl[i++]), target);
526
for (j = 0; j < grub_be_to_cpu16 (feature->lookupcount); j++)
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))
532
printf ("Out of range lookup: %d\n", lookup_index);
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)
540
printf ("Unsupported substitution type: %d\n",
541
grub_be_to_cpu16 (lookup->type));
544
if (grub_be_to_cpu16 (lookup->flag) & ~GSUB_RTL_CHAR)
546
printf ("Unsupported substitution flag: 0x%x\n",
547
grub_be_to_cpu16 (lookup->flag));
552
if (grub_be_to_cpu16 (lookup->flag) & GSUB_RTL_CHAR)
553
target = &subst_leftjoin;
555
target = &subst_rightjoin;
558
if (grub_be_to_cpu16 (lookup->flag) & GSUB_RTL_CHAR)
559
target = &subst_rightjoin;
561
target = &subst_leftjoin;
564
target = &subst_medijoin;
567
for (k = 0; k < grub_be_to_cpu16 (lookup->subtablecount); k++)
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)
576
printf ("Unsupported substitution specification: %d\n",
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);
585
if (covertype == GSUB_COVERAGE_LIST)
587
struct gsub_coverage_list *cover = coverage;
589
for (l = 0; l < grub_be_to_cpu16 (cover->count); l++)
590
subst (grub_be_to_cpu16 (cover->glyphs[l]));
592
else if (covertype == GSUB_COVERAGE_RANGE)
594
struct gsub_coverage_ranges *cover = coverage;
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++)
602
printf ("Unsupported coverage specification: %d\n", covertype);
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)
610
struct gsub_header *gsub = NULL;
611
FT_ULong gsub_len = 0;
613
if (!FT_Load_Sfnt_Table (face, TTAG_GSUB, 0, NULL, &gsub_len))
615
gsub = xmalloc (gsub_len);
616
if (FT_Load_Sfnt_Table (face, TTAG_GSUB, 0, (void *) gsub, &gsub_len))
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));
632
int nfeatures = grub_be_to_cpu16 (features->count);
633
for (i = 0; i < nfeatures; i++)
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);
641
printf ("WARNING: unsupported feature parameters: %x\n",
642
grub_be_to_cpu16 (feature->params));
645
/* Used for retrieving all possible variants. Useless in grub. */
649
/* FIXME: Add ligature support. */
654
/* Cursive form variants. */
658
process_cursive (feature, lookups, feattag);
665
memcpy (str, &features->features[i].feature_tag,
666
sizeof (features->features[i].feature_tag));
668
for (j = 0; j < 4; j++)
669
if (!grub_isgraph (str[j]))
671
printf ("Unknown gsub feature 0x%x (%s)\n", feattag, str);
227
677
if (font_info->num_range)