Arabic shaping support
This commit is contained in:
parent
0761327dd0
commit
e6d428c1b8
4 changed files with 400 additions and 52 deletions
22
font/font.c
22
font/font.c
|
@ -151,6 +151,7 @@ ascii_glyph_lookup (grub_uint32_t code)
|
||||||
ascii_font_glyph[current]->offset_x = 0;
|
ascii_font_glyph[current]->offset_x = 0;
|
||||||
ascii_font_glyph[current]->offset_y = -2;
|
ascii_font_glyph[current]->offset_y = -2;
|
||||||
ascii_font_glyph[current]->device_width = 8;
|
ascii_font_glyph[current]->device_width = 8;
|
||||||
|
ascii_font_glyph[current]->font = NULL;
|
||||||
|
|
||||||
grub_memcpy (ascii_font_glyph[current]->bitmap,
|
grub_memcpy (ascii_font_glyph[current]->bitmap,
|
||||||
&ascii_bitmaps[(0x7f - current) * ASCII_BITMAP_SIZE],
|
&ascii_bitmaps[(0x7f - current) * ASCII_BITMAP_SIZE],
|
||||||
|
@ -1181,11 +1182,12 @@ blit_comb (const struct grub_unicode_glyph *glyph_id,
|
||||||
{
|
{
|
||||||
grub_int16_t space = 0;
|
grub_int16_t space = 0;
|
||||||
/* Center by default. */
|
/* Center by default. */
|
||||||
grub_int16_t targetx = (bounds.width - combining_glyphs[i]->width) / 2
|
grub_int16_t targetx;
|
||||||
+ bounds.x;
|
|
||||||
|
|
||||||
if (!combining_glyphs[i])
|
if (!combining_glyphs[i])
|
||||||
continue;
|
continue;
|
||||||
|
targetx = (bounds.width - combining_glyphs[i]->width) / 2
|
||||||
|
+ bounds.x;
|
||||||
/* CGJ is to avoid diacritics reordering. */
|
/* CGJ is to avoid diacritics reordering. */
|
||||||
if (glyph_id->combining[i].code == GRUB_UNICODE_COMBINING_GRAPHEME_JOINER)
|
if (glyph_id->combining[i].code == GRUB_UNICODE_COMBINING_GRAPHEME_JOINER)
|
||||||
continue;
|
continue;
|
||||||
|
@ -1325,13 +1327,25 @@ grub_font_construct_dry_run (grub_font_t hinted_font,
|
||||||
struct grub_font_glyph ***combining_glyphs_out,
|
struct grub_font_glyph ***combining_glyphs_out,
|
||||||
int *device_width)
|
int *device_width)
|
||||||
{
|
{
|
||||||
struct grub_font_glyph *main_glyph;
|
struct grub_font_glyph *main_glyph = NULL;
|
||||||
struct grub_font_glyph **combining_glyphs;
|
struct grub_font_glyph **combining_glyphs;
|
||||||
|
grub_uint32_t desired_attributes = 0;
|
||||||
|
|
||||||
if (combining_glyphs_out)
|
if (combining_glyphs_out)
|
||||||
*combining_glyphs_out = NULL;
|
*combining_glyphs_out = NULL;
|
||||||
|
|
||||||
main_glyph = grub_font_get_glyph_with_fallback (hinted_font, glyph_id->base);
|
if (glyph_id->attributes & GRUB_UNICODE_GLYPH_ATTRIBUTE_RIGHT_JOINED)
|
||||||
|
desired_attributes |= GRUB_FONT_CODE_RIGHT_JOINED;
|
||||||
|
|
||||||
|
if (glyph_id->attributes & GRUB_UNICODE_GLYPH_ATTRIBUTE_LEFT_JOINED)
|
||||||
|
desired_attributes |= GRUB_FONT_CODE_LEFT_JOINED;
|
||||||
|
|
||||||
|
main_glyph = grub_font_get_glyph_with_fallback (hinted_font, glyph_id->base
|
||||||
|
| desired_attributes);
|
||||||
|
|
||||||
|
if (!main_glyph)
|
||||||
|
main_glyph = grub_font_get_glyph_with_fallback (hinted_font,
|
||||||
|
glyph_id->base);
|
||||||
|
|
||||||
/* Glyph not available in any font. Use ASCII fallback. */
|
/* Glyph not available in any font. Use ASCII fallback. */
|
||||||
if (!main_glyph)
|
if (!main_glyph)
|
||||||
|
|
|
@ -70,6 +70,11 @@ struct grub_font_glyph
|
||||||
grub_uint8_t bitmap[0];
|
grub_uint8_t bitmap[0];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* Part of code field which is really used as such. */
|
||||||
|
#define GRUB_FONT_CODE_CHAR_MASK 0x001fffff
|
||||||
|
#define GRUB_FONT_CODE_RIGHT_JOINED 0x80000000
|
||||||
|
#define GRUB_FONT_CODE_LEFT_JOINED 0x40000000
|
||||||
|
|
||||||
/* Initialize the font loader.
|
/* Initialize the font loader.
|
||||||
Must be called before any fonts are loaded or used. */
|
Must be called before any fonts are loaded or used. */
|
||||||
void grub_font_loader_init (void);
|
void grub_font_loader_init (void);
|
||||||
|
|
|
@ -26,7 +26,6 @@
|
||||||
- Cc type characters (ignored)
|
- Cc type characters (ignored)
|
||||||
- Line-breaking rules (e.g. Zs type characters)
|
- Line-breaking rules (e.g. Zs type characters)
|
||||||
- Indic languages
|
- Indic languages
|
||||||
- Arabic shaping
|
|
||||||
- non-Semitic shaping (rarely used)
|
- non-Semitic shaping (rarely used)
|
||||||
- Zl and Zp characters
|
- Zl and Zp characters
|
||||||
- Combining characters of types 7, 8, 9, 21, 27, 28, 29, 30, 31,
|
- Combining characters of types 7, 8, 9, 21, 27, 28, 29, 30, 31,
|
||||||
|
@ -40,6 +39,7 @@
|
||||||
- Justification data
|
- Justification data
|
||||||
- Glyph posititioning
|
- Glyph posititioning
|
||||||
- Baseline data
|
- Baseline data
|
||||||
|
TODO: Use form characters of Unicode as last resort Arabic shaping.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* Convert a (possibly null-terminated) UTF-8 string of at most SRCSIZE
|
/* Convert a (possibly null-terminated) UTF-8 string of at most SRCSIZE
|
||||||
|
|
|
@ -19,8 +19,10 @@
|
||||||
#include <config.h>
|
#include <config.h>
|
||||||
#include <grub/types.h>
|
#include <grub/types.h>
|
||||||
#include <grub/util/misc.h>
|
#include <grub/util/misc.h>
|
||||||
|
#include <grub/misc.h>
|
||||||
#include <grub/i18n.h>
|
#include <grub/i18n.h>
|
||||||
#include <grub/fontformat.h>
|
#include <grub/fontformat.h>
|
||||||
|
#include <grub/font.h>
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
@ -29,6 +31,8 @@
|
||||||
|
|
||||||
#include <ft2build.h>
|
#include <ft2build.h>
|
||||||
#include FT_FREETYPE_H
|
#include FT_FREETYPE_H
|
||||||
|
#include FT_TRUETYPE_TAGS_H
|
||||||
|
#include FT_TRUETYPE_TABLES_H
|
||||||
#include <freetype/ftsynth.h>
|
#include <freetype/ftsynth.h>
|
||||||
|
|
||||||
#include "progname.h"
|
#include "progname.h"
|
||||||
|
@ -47,7 +51,7 @@ struct grub_glyph_info
|
||||||
int y_ofs;
|
int y_ofs;
|
||||||
int device_width;
|
int device_width;
|
||||||
int bitmap_size;
|
int bitmap_size;
|
||||||
grub_uint8_t bitmap[0];
|
grub_uint8_t *bitmap;
|
||||||
};
|
};
|
||||||
|
|
||||||
enum file_formats
|
enum file_formats
|
||||||
|
@ -76,7 +80,9 @@ struct grub_font_info
|
||||||
int flags;
|
int flags;
|
||||||
int num_range;
|
int num_range;
|
||||||
grub_uint32_t *ranges;
|
grub_uint32_t *ranges;
|
||||||
struct grub_glyph_info *glyph;
|
struct grub_glyph_info *glyphs_unsorted;
|
||||||
|
struct grub_glyph_info *glyphs_sorted;
|
||||||
|
int num_glyphs;
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct option options[] =
|
static struct option options[] =
|
||||||
|
@ -149,11 +155,11 @@ add_pixel (grub_uint8_t **data, int *mask, int not_blank)
|
||||||
*mask >>= 1;
|
*mask >>= 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
static void
|
||||||
add_char (struct grub_font_info *font_info, FT_Face face,
|
add_glyph (struct grub_font_info *font_info, FT_UInt glyph_idx, FT_Face face,
|
||||||
grub_uint32_t char_code)
|
grub_uint32_t char_code)
|
||||||
{
|
{
|
||||||
struct grub_glyph_info *glyph_info, **p_glyph;
|
struct grub_glyph_info *glyph_info;
|
||||||
int width, height;
|
int width, height;
|
||||||
grub_uint8_t *data;
|
grub_uint8_t *data;
|
||||||
int mask, i, j, bitmap_size;
|
int mask, i, j, bitmap_size;
|
||||||
|
@ -168,24 +174,17 @@ add_char (struct grub_font_info *font_info, FT_Face face,
|
||||||
else if (font_info->flags & GRUB_FONT_FLAG_FORCEHINT)
|
else if (font_info->flags & GRUB_FONT_FLAG_FORCEHINT)
|
||||||
flag |= FT_LOAD_FORCE_AUTOHINT;
|
flag |= FT_LOAD_FORCE_AUTOHINT;
|
||||||
|
|
||||||
if (FT_Load_Char (face, char_code, flag))
|
if (FT_Load_Glyph (face, glyph_idx, flag))
|
||||||
|
{
|
||||||
|
printf ("WARNING: Couldn't load glyph %x\n", glyph_idx);
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
glyph = face->glyph;
|
glyph = face->glyph;
|
||||||
|
|
||||||
if (font_info->flags & GRUB_FONT_FLAG_BOLD)
|
if (font_info->flags & GRUB_FONT_FLAG_BOLD)
|
||||||
FT_GlyphSlot_Embolden (glyph);
|
FT_GlyphSlot_Embolden (glyph);
|
||||||
|
|
||||||
p_glyph = &font_info->glyph;
|
|
||||||
while ((*p_glyph) && ((*p_glyph)->char_code > char_code))
|
|
||||||
{
|
|
||||||
p_glyph = &(*p_glyph)->next;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Ignore duplicated glyph. */
|
|
||||||
if ((*p_glyph) && ((*p_glyph)->char_code == char_code))
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (glyph->next)
|
if (glyph->next)
|
||||||
printf ("%x\n", char_code);
|
printf ("%x\n", char_code);
|
||||||
|
|
||||||
|
@ -193,11 +192,13 @@ add_char (struct grub_font_info *font_info, FT_Face face,
|
||||||
height = glyph->bitmap.rows;
|
height = glyph->bitmap.rows;
|
||||||
|
|
||||||
bitmap_size = ((width * height + 7) / 8);
|
bitmap_size = ((width * height + 7) / 8);
|
||||||
glyph_info = xmalloc (sizeof (struct grub_glyph_info) + bitmap_size);
|
glyph_info = xmalloc (sizeof (struct grub_glyph_info));
|
||||||
|
glyph_info->bitmap = xmalloc (bitmap_size);
|
||||||
glyph_info->bitmap_size = bitmap_size;
|
glyph_info->bitmap_size = bitmap_size;
|
||||||
|
|
||||||
glyph_info->next = *p_glyph;
|
glyph_info->next = font_info->glyphs_unsorted;
|
||||||
*p_glyph = glyph_info;
|
font_info->glyphs_unsorted = glyph_info;
|
||||||
|
font_info->num_glyphs++;
|
||||||
|
|
||||||
glyph_info->char_code = char_code;
|
glyph_info->char_code = char_code;
|
||||||
glyph_info->width = width;
|
glyph_info->width = width;
|
||||||
|
@ -227,9 +228,318 @@ add_char (struct grub_font_info *font_info, FT_Face face,
|
||||||
(1 << (7 - (i & 7))));
|
(1 << (7 - (i & 7))));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct glyph_replace *subst_rightjoin, *subst_leftjoin, *subst_medijoin;
|
||||||
|
|
||||||
|
struct glyph_replace
|
||||||
|
{
|
||||||
|
struct glyph_replace *next;
|
||||||
|
grub_uint32_t from, to;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* TODO: sort glyph_replace and use binary search if necessary. */
|
||||||
|
static void
|
||||||
|
add_char (struct grub_font_info *font_info, FT_Face face,
|
||||||
|
grub_uint32_t char_code)
|
||||||
|
{
|
||||||
|
FT_UInt glyph_idx;
|
||||||
|
struct glyph_replace *cur;
|
||||||
|
|
||||||
|
glyph_idx = FT_Get_Char_Index (face, char_code);
|
||||||
|
if (!glyph_idx)
|
||||||
|
return;
|
||||||
|
add_glyph (font_info, glyph_idx, face, char_code);
|
||||||
|
for (cur = subst_rightjoin; cur; cur = cur->next)
|
||||||
|
if (cur->from == glyph_idx)
|
||||||
|
{
|
||||||
|
add_glyph (font_info, cur->to, face,
|
||||||
|
char_code | GRUB_FONT_CODE_RIGHT_JOINED);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
for (cur = subst_leftjoin; cur; cur = cur->next)
|
||||||
|
if (cur->from == glyph_idx)
|
||||||
|
{
|
||||||
|
add_glyph (font_info, cur->to, face,
|
||||||
|
char_code | GRUB_FONT_CODE_LEFT_JOINED);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
for (cur = subst_medijoin; cur; cur = cur->next)
|
||||||
|
if (cur->from == glyph_idx)
|
||||||
|
{
|
||||||
|
add_glyph (font_info, cur->to, face,
|
||||||
|
char_code | GRUB_FONT_CODE_LEFT_JOINED
|
||||||
|
| GRUB_FONT_CODE_RIGHT_JOINED);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct gsub_header
|
||||||
|
{
|
||||||
|
grub_uint32_t version;
|
||||||
|
grub_uint16_t scripts_off;
|
||||||
|
grub_uint16_t features_off;
|
||||||
|
grub_uint16_t lookups_off;
|
||||||
|
} __attribute__ ((packed));
|
||||||
|
|
||||||
|
struct gsub_features
|
||||||
|
{
|
||||||
|
grub_uint16_t count;
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
#define FEATURE_FINA 0x66696e61
|
||||||
|
#define FEATURE_INIT 0x696e6974
|
||||||
|
#define FEATURE_MEDI 0x6d656469
|
||||||
|
#define FEATURE_AALT 0x61616c74
|
||||||
|
grub_uint32_t feature_tag;
|
||||||
|
grub_uint16_t offset;
|
||||||
|
} __attribute__ ((packed)) features[0];
|
||||||
|
} __attribute__ ((packed));
|
||||||
|
|
||||||
|
struct gsub_feature
|
||||||
|
{
|
||||||
|
grub_uint16_t params;
|
||||||
|
grub_uint16_t lookupcount;
|
||||||
|
grub_uint16_t lookupindices[0];
|
||||||
|
} __attribute__ ((packed));
|
||||||
|
|
||||||
|
struct gsub_lookup_list
|
||||||
|
{
|
||||||
|
grub_uint16_t count;
|
||||||
|
grub_uint16_t offsets[0];
|
||||||
|
} __attribute__ ((packed));
|
||||||
|
|
||||||
|
struct gsub_lookup
|
||||||
|
{
|
||||||
|
grub_uint16_t type;
|
||||||
|
grub_uint16_t flag;
|
||||||
|
grub_uint16_t subtablecount;
|
||||||
|
grub_uint16_t subtables[0];
|
||||||
|
} __attribute__ ((packed));
|
||||||
|
|
||||||
|
struct gsub_substitution
|
||||||
|
{
|
||||||
|
grub_uint16_t type;
|
||||||
|
grub_uint16_t coverage_off;
|
||||||
|
union
|
||||||
|
{
|
||||||
|
grub_int16_t delta;
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
grub_int16_t count;
|
||||||
|
grub_uint16_t repl[0];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
} __attribute__ ((packed));
|
||||||
|
|
||||||
|
struct gsub_coverage_list
|
||||||
|
{
|
||||||
|
grub_uint16_t type;
|
||||||
|
grub_uint16_t count;
|
||||||
|
grub_uint16_t glyphs[0];
|
||||||
|
} __attribute__ ((packed));
|
||||||
|
|
||||||
|
struct gsub_coverage_ranges
|
||||||
|
{
|
||||||
|
grub_uint16_t type;
|
||||||
|
grub_uint16_t count;
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
grub_uint16_t start;
|
||||||
|
grub_uint16_t end;
|
||||||
|
grub_uint16_t start_index;
|
||||||
|
} __attribute__ ((packed)) ranges[0];
|
||||||
|
} __attribute__ ((packed));
|
||||||
|
|
||||||
|
#define GSUB_SINGLE_SUBSTITUTION 1
|
||||||
|
|
||||||
|
#define GSUB_SUBSTITUTION_DELTA 1
|
||||||
|
#define GSUB_SUBSTITUTION_MAP 2
|
||||||
|
|
||||||
|
#define GSUB_COVERAGE_LIST 1
|
||||||
|
#define GSUB_COVERAGE_RANGE 2
|
||||||
|
|
||||||
|
#define GSUB_RTL_CHAR 1
|
||||||
|
|
||||||
|
static void
|
||||||
|
add_subst (grub_uint32_t from, grub_uint32_t to, struct glyph_replace **target)
|
||||||
|
{
|
||||||
|
struct glyph_replace *new = xmalloc (sizeof (*new));
|
||||||
|
new->next = *target;
|
||||||
|
new->from = from;
|
||||||
|
new->to = to;
|
||||||
|
*target = new;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
process_cursive (struct gsub_feature *feature,
|
||||||
|
struct gsub_lookup_list *lookups,
|
||||||
|
grub_uint32_t feattag)
|
||||||
|
{
|
||||||
|
int j, k;
|
||||||
|
int i;
|
||||||
|
struct glyph_replace **target;
|
||||||
|
struct gsub_substitution *sub;
|
||||||
|
|
||||||
|
auto inline void subst (grub_uint32_t glyph);
|
||||||
|
void subst (grub_uint32_t glyph)
|
||||||
|
{
|
||||||
|
grub_uint16_t substtype;
|
||||||
|
substtype = grub_be_to_cpu16 (sub->type);
|
||||||
|
|
||||||
|
if (substtype == GSUB_SUBSTITUTION_DELTA)
|
||||||
|
add_subst (glyph, glyph + grub_be_to_cpu16 (sub->delta), target);
|
||||||
|
else if (i >= grub_be_to_cpu16 (sub->count))
|
||||||
|
printf ("Out of range substitution (%d, %d)\n", i,
|
||||||
|
grub_be_to_cpu16 (sub->count));
|
||||||
|
else
|
||||||
|
add_subst (glyph, grub_be_to_cpu16 (sub->repl[i++]), target);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (j = 0; j < grub_be_to_cpu16 (feature->lookupcount); j++)
|
||||||
|
{
|
||||||
|
int lookup_index = grub_be_to_cpu16 (feature->lookupindices[j]);
|
||||||
|
struct gsub_lookup *lookup;
|
||||||
|
if (lookup_index >= grub_be_to_cpu16 (lookups->count))
|
||||||
|
{
|
||||||
|
printf ("Out of range lookup: %d\n", lookup_index);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
lookup = (struct gsub_lookup *)
|
||||||
|
((grub_uint8_t *) lookups
|
||||||
|
+ grub_be_to_cpu16 (lookups->offsets[lookup_index]));
|
||||||
|
if (grub_be_to_cpu16 (lookup->type) != GSUB_SINGLE_SUBSTITUTION)
|
||||||
|
{
|
||||||
|
printf ("Unsupported substitution type: %d\n",
|
||||||
|
grub_be_to_cpu16 (lookup->type));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (grub_be_to_cpu16 (lookup->flag) & ~GSUB_RTL_CHAR)
|
||||||
|
{
|
||||||
|
printf ("Unsupported substitution flag: 0x%x\n",
|
||||||
|
grub_be_to_cpu16 (lookup->flag));
|
||||||
|
}
|
||||||
|
switch (feattag)
|
||||||
|
{
|
||||||
|
case FEATURE_INIT:
|
||||||
|
if (grub_be_to_cpu16 (lookup->flag) & GSUB_RTL_CHAR)
|
||||||
|
target = &subst_leftjoin;
|
||||||
|
else
|
||||||
|
target = &subst_rightjoin;
|
||||||
|
break;
|
||||||
|
case FEATURE_FINA:
|
||||||
|
if (grub_be_to_cpu16 (lookup->flag) & GSUB_RTL_CHAR)
|
||||||
|
target = &subst_rightjoin;
|
||||||
|
else
|
||||||
|
target = &subst_leftjoin;
|
||||||
|
break;
|
||||||
|
case FEATURE_MEDI:
|
||||||
|
target = &subst_medijoin;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
for (k = 0; k < grub_be_to_cpu16 (lookup->subtablecount); k++)
|
||||||
|
{
|
||||||
|
sub = (struct gsub_substitution *)
|
||||||
|
((grub_uint8_t *) lookup + grub_be_to_cpu16 (lookup->subtables[k]));
|
||||||
|
grub_uint16_t substtype;
|
||||||
|
substtype = grub_be_to_cpu16 (sub->type);
|
||||||
|
if (substtype != GSUB_SUBSTITUTION_MAP
|
||||||
|
&& substtype != GSUB_SUBSTITUTION_DELTA)
|
||||||
|
{
|
||||||
|
printf ("Unsupported substitution specification: %d\n",
|
||||||
|
substtype);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
void *coverage = (grub_uint8_t *) sub
|
||||||
|
+ grub_be_to_cpu16 (sub->coverage_off);
|
||||||
|
grub_uint32_t covertype;
|
||||||
|
covertype = grub_be_to_cpu16 (*(grub_uint16_t * __attribute__ ((packed))) coverage);
|
||||||
|
i = 0;
|
||||||
|
if (covertype == GSUB_COVERAGE_LIST)
|
||||||
|
{
|
||||||
|
struct gsub_coverage_list *cover = coverage;
|
||||||
|
int l;
|
||||||
|
for (l = 0; l < grub_be_to_cpu16 (cover->count); l++)
|
||||||
|
subst (grub_be_to_cpu16 (cover->glyphs[l]));
|
||||||
|
}
|
||||||
|
else if (covertype == GSUB_COVERAGE_RANGE)
|
||||||
|
{
|
||||||
|
struct gsub_coverage_ranges *cover = coverage;
|
||||||
|
int l, m;
|
||||||
|
for (l = 0; l < grub_be_to_cpu16 (cover->count); l++)
|
||||||
|
for (m = grub_be_to_cpu16 (cover->ranges[l].start);
|
||||||
|
m <= grub_be_to_cpu16 (cover->ranges[l].end); m++)
|
||||||
|
subst (m);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
printf ("Unsupported coverage specification: %d\n", covertype);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
add_font (struct grub_font_info *font_info, FT_Face face)
|
add_font (struct grub_font_info *font_info, FT_Face face)
|
||||||
{
|
{
|
||||||
|
struct gsub_header *gsub = NULL;
|
||||||
|
FT_ULong gsub_len = 0;
|
||||||
|
|
||||||
|
if (!FT_Load_Sfnt_Table (face, TTAG_GSUB, 0, NULL, &gsub_len))
|
||||||
|
{
|
||||||
|
gsub = xmalloc (gsub_len);
|
||||||
|
if (FT_Load_Sfnt_Table (face, TTAG_GSUB, 0, (void *) gsub, &gsub_len))
|
||||||
|
{
|
||||||
|
free (gsub);
|
||||||
|
gsub = NULL;
|
||||||
|
gsub_len = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (gsub)
|
||||||
|
{
|
||||||
|
struct gsub_features *features
|
||||||
|
= (struct gsub_features *) (((grub_uint8_t *) gsub)
|
||||||
|
+ grub_be_to_cpu16 (gsub->features_off));
|
||||||
|
struct gsub_lookup_list *lookups
|
||||||
|
= (struct gsub_lookup_list *) (((grub_uint8_t *) gsub)
|
||||||
|
+ grub_be_to_cpu16 (gsub->lookups_off));
|
||||||
|
int i;
|
||||||
|
int nfeatures = grub_be_to_cpu16 (features->count);
|
||||||
|
for (i = 0; i < nfeatures; i++)
|
||||||
|
{
|
||||||
|
struct gsub_feature *feature = (struct gsub_feature *)
|
||||||
|
((grub_uint8_t *) features
|
||||||
|
+ grub_be_to_cpu16 (features->features[i].offset));
|
||||||
|
grub_uint32_t feattag
|
||||||
|
= grub_be_to_cpu32 (features->features[i].feature_tag);
|
||||||
|
if (feature->params)
|
||||||
|
printf ("WARNING: unsupported feature parameters: %x\n",
|
||||||
|
grub_be_to_cpu16 (feature->params));
|
||||||
|
switch (feattag)
|
||||||
|
{
|
||||||
|
/* Used for retrieving all possible variants. Useless in grub. */
|
||||||
|
case FEATURE_AALT:
|
||||||
|
break;
|
||||||
|
|
||||||
|
/* Cursive form variants. */
|
||||||
|
case FEATURE_FINA:
|
||||||
|
case FEATURE_INIT:
|
||||||
|
case FEATURE_MEDI:
|
||||||
|
process_cursive (feature, lookups, feattag);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
char str[5];
|
||||||
|
int j;
|
||||||
|
memcpy (str, &features->features[i].feature_tag,
|
||||||
|
sizeof (features->features[i].feature_tag));
|
||||||
|
str[4] = 0;
|
||||||
|
for (j = 0; j < 4; j++)
|
||||||
|
if (!grub_isgraph (str[j]))
|
||||||
|
str[j] = '?';
|
||||||
|
printf ("Unknown gsub feature 0x%x (%s)\n", feattag, str);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (font_info->num_range)
|
if (font_info->num_range)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
@ -287,7 +597,8 @@ print_glyphs (struct grub_font_info *font_info)
|
||||||
struct grub_glyph_info *glyph;
|
struct grub_glyph_info *glyph;
|
||||||
char line[512];
|
char line[512];
|
||||||
|
|
||||||
for (glyph = font_info->glyph, num = 0; glyph; glyph = glyph->next, num++)
|
for (glyph = font_info->glyphs_sorted, num = 0; num < font_info->num_glyphs;
|
||||||
|
glyph++, num++)
|
||||||
{
|
{
|
||||||
int x, y, xmax, xmin, ymax, ymin;
|
int x, y, xmax, xmin, ymax, ymin;
|
||||||
grub_uint8_t *bitmap, mask;
|
grub_uint8_t *bitmap, mask;
|
||||||
|
@ -363,7 +674,8 @@ write_font_ascii_bitmap (struct grub_font_info *font_info, char *output_file)
|
||||||
grub_util_error ("Can\'t write to file %s.", output_file);
|
grub_util_error ("Can\'t write to file %s.", output_file);
|
||||||
|
|
||||||
int correct_size;
|
int correct_size;
|
||||||
for (glyph = font_info->glyph, num = 0; glyph; glyph = glyph->next, num++)
|
for (glyph = font_info->glyphs_sorted, num = 0; num < font_info->num_glyphs;
|
||||||
|
glyph++, num++)
|
||||||
{
|
{
|
||||||
correct_size = 1;
|
correct_size = 1;
|
||||||
if (glyph->width != 8 || glyph->height != 16)
|
if (glyph->width != 8 || glyph->height != 16)
|
||||||
|
@ -397,7 +709,8 @@ write_font_width_spec (struct grub_font_info *font_info, char *output_file)
|
||||||
if (! file)
|
if (! file)
|
||||||
grub_util_error ("Can\'t write to file %s.", output_file);
|
grub_util_error ("Can\'t write to file %s.", output_file);
|
||||||
|
|
||||||
for (glyph = font_info->glyph; glyph; glyph = glyph->next)
|
for (glyph = font_info->glyphs_sorted;
|
||||||
|
glyph < font_info->glyphs_sorted + font_info->num_glyphs; glyph++)
|
||||||
if (glyph->width > 12)
|
if (glyph->width > 12)
|
||||||
out[glyph->char_code >> 3] |= (1 << (glyph->char_code & 7));
|
out[glyph->char_code >> 3] |= (1 << (glyph->char_code & 7));
|
||||||
|
|
||||||
|
@ -412,8 +725,8 @@ write_font_pf2 (struct grub_font_info *font_info, char *output_file)
|
||||||
FILE *file;
|
FILE *file;
|
||||||
grub_uint32_t leng, data;
|
grub_uint32_t leng, data;
|
||||||
char style_name[20], *font_name;
|
char style_name[20], *font_name;
|
||||||
struct grub_glyph_info *cur, *pre;
|
int offset;
|
||||||
int num, offset;
|
struct grub_glyph_info *cur;
|
||||||
|
|
||||||
file = fopen (output_file, "wb");
|
file = fopen (output_file, "wb");
|
||||||
if (! file)
|
if (! file)
|
||||||
|
@ -497,33 +810,18 @@ write_font_pf2 (struct grub_font_info *font_info, char *output_file)
|
||||||
printf ("Font descent: %d\n", font_info->desc);
|
printf ("Font descent: %d\n", font_info->desc);
|
||||||
}
|
}
|
||||||
|
|
||||||
num = 0;
|
|
||||||
pre = 0;
|
|
||||||
cur = font_info->glyph;
|
|
||||||
while (cur)
|
|
||||||
{
|
|
||||||
struct grub_glyph_info *nxt;
|
|
||||||
|
|
||||||
nxt = cur->next;
|
|
||||||
cur->next = pre;
|
|
||||||
pre = cur;
|
|
||||||
cur = nxt;
|
|
||||||
num++;
|
|
||||||
}
|
|
||||||
|
|
||||||
font_info->glyph = pre;
|
|
||||||
|
|
||||||
if (font_verbosity > 0)
|
if (font_verbosity > 0)
|
||||||
printf ("Number of glyph: %d\n", num);
|
printf ("Number of glyph: %d\n", font_info->num_glyphs);
|
||||||
|
|
||||||
leng = grub_cpu_to_be32 (num * 9);
|
leng = grub_cpu_to_be32 (font_info->num_glyphs * 9);
|
||||||
grub_util_write_image (FONT_FORMAT_SECTION_NAMES_CHAR_INDEX,
|
grub_util_write_image (FONT_FORMAT_SECTION_NAMES_CHAR_INDEX,
|
||||||
sizeof(FONT_FORMAT_SECTION_NAMES_CHAR_INDEX) - 1,
|
sizeof(FONT_FORMAT_SECTION_NAMES_CHAR_INDEX) - 1,
|
||||||
file);
|
file);
|
||||||
grub_util_write_image ((char *) &leng, 4, file);
|
grub_util_write_image ((char *) &leng, 4, file);
|
||||||
offset += 8 + num * 9 + 8;
|
offset += 8 + font_info->num_glyphs * 9 + 8;
|
||||||
|
|
||||||
for (cur = font_info->glyph; cur; cur = cur->next)
|
for (cur = font_info->glyphs_sorted;
|
||||||
|
cur < font_info->glyphs_sorted + font_info->num_glyphs; cur++)
|
||||||
{
|
{
|
||||||
data = grub_cpu_to_be32 (cur->char_code);
|
data = grub_cpu_to_be32 (cur->char_code);
|
||||||
grub_util_write_image ((char *) &data, 4, file);
|
grub_util_write_image ((char *) &data, 4, file);
|
||||||
|
@ -539,7 +837,8 @@ write_font_pf2 (struct grub_font_info *font_info, char *output_file)
|
||||||
sizeof(FONT_FORMAT_SECTION_NAMES_DATA) - 1, file);
|
sizeof(FONT_FORMAT_SECTION_NAMES_DATA) - 1, file);
|
||||||
grub_util_write_image ((char *) &leng, 4, file);
|
grub_util_write_image ((char *) &leng, 4, file);
|
||||||
|
|
||||||
for (cur = font_info->glyph; cur; cur = cur->next)
|
for (cur = font_info->glyphs_sorted;
|
||||||
|
cur < font_info->glyphs_sorted + font_info->num_glyphs; cur++)
|
||||||
{
|
{
|
||||||
data = grub_cpu_to_be16 (cur->width);
|
data = grub_cpu_to_be16 (cur->width);
|
||||||
grub_util_write_image ((char *) &data, 2, file);
|
grub_util_write_image ((char *) &data, 2, file);
|
||||||
|
@ -742,6 +1041,36 @@ main (int argc, char *argv[])
|
||||||
|
|
||||||
FT_Done_FreeType (ft_lib);
|
FT_Done_FreeType (ft_lib);
|
||||||
|
|
||||||
|
{
|
||||||
|
int counter[65537];
|
||||||
|
struct grub_glyph_info *tmp, *cur;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
memset (counter, 0, sizeof (counter));
|
||||||
|
|
||||||
|
for (cur = font_info.glyphs_unsorted; cur; cur = cur->next)
|
||||||
|
counter[(cur->char_code & 0xffff) + 1]++;
|
||||||
|
for (i = 0; i < 0x10000; i++)
|
||||||
|
counter[i+1] += counter[i];
|
||||||
|
tmp = xmalloc (font_info.num_glyphs
|
||||||
|
* sizeof (tmp[0]));
|
||||||
|
for (cur = font_info.glyphs_unsorted; cur; cur = cur->next)
|
||||||
|
tmp[counter[(cur->char_code & 0xffff)]++] = *cur;
|
||||||
|
|
||||||
|
memset (counter, 0, sizeof (counter));
|
||||||
|
|
||||||
|
for (cur = tmp; cur < tmp + font_info.num_glyphs; cur++)
|
||||||
|
counter[((cur->char_code & 0xffff0000) >> 16) + 1]++;
|
||||||
|
for (i = 0; i < 0x10000; i++)
|
||||||
|
counter[i+1] += counter[i];
|
||||||
|
font_info.glyphs_sorted = xmalloc (font_info.num_glyphs
|
||||||
|
* sizeof (font_info.glyphs_sorted[0]));
|
||||||
|
for (cur = tmp; cur < tmp + font_info.num_glyphs; cur++)
|
||||||
|
font_info.glyphs_sorted[counter[(cur->char_code & 0xffff0000) >> 16]++]
|
||||||
|
= *cur;
|
||||||
|
free (tmp);
|
||||||
|
}
|
||||||
|
|
||||||
switch (file_format)
|
switch (file_format)
|
||||||
{
|
{
|
||||||
case PF2:
|
case PF2:
|
||||||
|
|
Loading…
Reference in a new issue