TTF/TTC to CIDFontType2 patch
- From: Ling Li <liling learn bit edu cn>
- To: gnome-print-list gnome org
- Subject: TTF/TTC to CIDFontType2 patch
- Date: Wed Apr 14 00:22:58 2004
Hi all,
I found that in gnome-print, large TTF/TTC fonts for CJK characters is
converted to Type1 font by ttf2pt1. This method has changed the font and it
looks not exactly the same as original TTF/TTC ones.
In order to subset large TTF/TTC font into PostScript, Adobe has developed
Type 2 CIDFont, it's a extension to Type 42 font.
I have write a patch to make gnome-print use CIDFontType2 when its too large
for Type 42 font. I have tested it using Chinese SimSun font and gs-gpl 8.0.
(In gs-esp 7, theirs some bug to deal metrics data saved in GlyphDirectory.)
The patch is in attachment and it should be applied to files in libgnomeprint
directory. File gp-tt-cid2.c and gp-tt-cid2.h should be put in that directory
too.
Index: gnome-font-face.c
===================================================================
RCS file: /cvs/gnome/libgnomeprint/libgnomeprint/gnome-font-face.c,v
retrieving revision 1.75
diff -r1.75 gnome-font-face.c
44a45
> #include <libgnomeprint/gp-tt-cid2.h>
849,852c850,853
< {
< found = charmap;
< break;
< }
---
> {
> found = charmap;
> break;
> }
1128d1128
<
1335a1336,1338
> void sfnts_write_byte_array (GnomeFontPsObject *pso, GByteArray* array);
> void sfnts_write_tt_table (GnomeFontPsObject *pso, const guchar *buf, guint buf_len, struct tt_table *table);
>
1344a1348,1349
> GHashTable *tables;
> GByteArray *head;
1350a1356,1357
> guchar *required[] = {"head", "prep", "cvt ", "hhea", "fpgm", "maxp", "vhea", "gdir", NULL};
> gint metrics_count, num_glyphs;
1427,1443d1433
< } else {
< guchar *afm;
< /* This is somewhat experimental - convert TTF to Type1 */
< afm = ttf2pfa (pso->face->ft_face, embeddedname, pso->glyphs);
< if (!afm) {
< gnome_print_buffer_munmap (&b);
< g_warning ("file %s: line %d: Cannot convert TTF %s to Type1", __FILE__, __LINE__, file_name);
< gnome_font_face_ps_embed_empty (pso);
< return;
< }
< /* We take over ownership of afm here (be careful) */
< pso->buf = afm;
< pso->bufsize = strlen (afm);
< pso->length = pso->bufsize;
< }
<
< gnome_print_buffer_munmap (&b);
1445,1491c1435,1449
< /*
< * We have font downloaded (hopefully)
< *
< * With CharStrings: .nodef _1 _2 _3
< *
< * Now we have to build usable 2-byte encoded font from it
< *
< */
<
< /* fixme: That is crap. We should use CID */
< /* Bitch 'o' bitches (Lauris) ! */
< if (pso->face->num_glyphs < 256) {
< gint glyph;
< /* 8-bit vector */
< pso->encodedbytes = 1;
< gf_pso_sprintf (pso, "(%s) cvn findfont dup length dict begin\n", embeddedname);
< gf_pso_sprintf (pso, "{1 index /FID ne {def} {pop pop} ifelse} forall\n");
< gf_pso_sprintf (pso, "/Encoding [\n");
< for (glyph = 0; glyph < 256; glyph++) {
< guint g;
< g = (glyph < pso->face->num_glyphs) ? glyph : 0;
< if ((g == 0) || !PSO_GLYPH_MARKED (pso, glyph)) {
< gf_pso_sprintf (pso, ((glyph & 0xf) == 0xf) ? "/.notdef\n" : "/.notdef ", g);
< } else {
< gf_pso_sprintf (pso, ((glyph & 0xf) == 0xf) ? "/_%d\n" : "/_%d ", g);
< }
< }
< gf_pso_sprintf (pso, "] def currentdict end\n");
< gf_pso_sprintf (pso, "(%s) cvn exch definefont pop\n", pso->encodedname);
< } else {
< gint nfonts, nglyphs, i, j;
< /* 16-bit vector */
< pso->encodedbytes = 2;
< nglyphs = pso->face->num_glyphs;
< nfonts = (nglyphs + 255) >> 8;
<
< gf_pso_sprintf (pso, "32 dict begin\n");
< /* Common entries */
< gf_pso_sprintf (pso, "/FontType 0 def\n");
< gf_pso_sprintf (pso, "/FontMatrix [1 0 0 1 0 0] def\n");
< gf_pso_sprintf (pso, "/FontName (%s-Glyph-Composite) cvn def\n", embeddedname);
< gf_pso_sprintf (pso, "/LanguageLevel 2 def\n");
< /* Type 0 entries */
< gf_pso_sprintf (pso, "/FMapType 2 def\n");
< /* Bitch 'o' bitches */
< gf_pso_sprintf (pso, "/FDepVector [\n");
< for (i = 0; i < nfonts; i++) {
---
> /*
> * We have font downloaded (hopefully)
> *
> * With CharStrings: .nodef _1 _2 _3
> *
> * Now we have to build usable 2-byte encoded font from it
> *
> */
>
> /* fixme: That is crap. We should use CID */
> /* Bitch 'o' bitches (Lauris) ! */
> if (pso->face->num_glyphs < 256) {
> gint glyph;
> /* 8-bit vector */
> pso->encodedbytes = 1;
1495,1501c1453,1457
< for (j = 0; j < 256; j++) {
< gint glyph;
< glyph = 256 * i + j;
< if (glyph >= nglyphs)
< glyph = 0;
< if ((glyph == 0) || !PSO_GLYPH_MARKED (pso, glyph)) {
< gf_pso_sprintf (pso, ((j & 0xf) == 0xf) ? "/.notdef\n" : "/.notdef ");
---
> for (glyph = 0; glyph < 256; glyph++) {
> guint g;
> g = (glyph < pso->face->num_glyphs) ? glyph : 0;
> if ((g == 0) || !PSO_GLYPH_MARKED (pso, glyph)) {
> gf_pso_sprintf (pso, ((glyph & 0xf) == 0xf) ? "/.notdef\n" : "/.notdef ", g);
1503c1459,1494
< gf_pso_sprintf (pso, ((j & 0xf) == 0xf) ? "/_%d\n" : "/_%d ", glyph);
---
> gf_pso_sprintf (pso, ((glyph & 0xf) == 0xf) ? "/_%d\n" : "/_%d ", g);
> }
> }
> gf_pso_sprintf (pso, "] def currentdict end\n");
> gf_pso_sprintf (pso, "(%s) cvn exch definefont pop\n", pso->encodedname);
> } else {
> gint nfonts, nglyphs, i, j;
> /* 16-bit vector */
> pso->encodedbytes = 2;
> nglyphs = pso->face->num_glyphs;
> nfonts = (nglyphs + 255) >> 8;
>
> gf_pso_sprintf (pso, "32 dict begin\n");
> /* Common entries */
> gf_pso_sprintf (pso, "/FontType 0 def\n");
> gf_pso_sprintf (pso, "/FontMatrix [1 0 0 1 0 0] def\n");
> gf_pso_sprintf (pso, "/FontName (%s-Glyph-Composite) cvn def\n", embeddedname);
> gf_pso_sprintf (pso, "/LanguageLevel 2 def\n");
> /* Type 0 entries */
> gf_pso_sprintf (pso, "/FMapType 2 def\n");
> /* Bitch 'o' bitches */
> gf_pso_sprintf (pso, "/FDepVector [\n");
> for (i = 0; i < nfonts; i++) {
> gf_pso_sprintf (pso, "(%s) cvn findfont dup length dict begin\n", embeddedname);
> gf_pso_sprintf (pso, "{1 index /FID ne {def} {pop pop} ifelse} forall\n");
> gf_pso_sprintf (pso, "/Encoding [\n");
> for (j = 0; j < 256; j++) {
> gint glyph;
> glyph = 256 * i + j;
> if (glyph >= nglyphs)
> glyph = 0;
> if ((glyph == 0) || !PSO_GLYPH_MARKED (pso, glyph)) {
> gf_pso_sprintf (pso, ((j & 0xf) == 0xf) ? "/.notdef\n" : "/.notdef ");
> } else {
> gf_pso_sprintf (pso, ((j & 0xf) == 0xf) ? "/_%d\n" : "/_%d ", glyph);
> }
1504a1496,1497
> gf_pso_sprintf (pso, "] def\n");
> gf_pso_sprintf (pso, "currentdict end (%s-Glyph-Page-%d) cvn exch definefont\n", embeddedname, i);
1507c1500,1508
< gf_pso_sprintf (pso, "currentdict end (%s-Glyph-Page-%d) cvn exch definefont\n", embeddedname, i);
---
> gf_pso_sprintf (pso, "/Encoding [\n");
> for (i = 0; i < 256; i++) {
> gint fn;
> fn = (i < nfonts) ? i : 0;
> gf_pso_sprintf (pso, ((i & 0xf) == 0xf) ? "%d\n" : "%d ", fn);
> }
> gf_pso_sprintf (pso, "] def\n");
> gf_pso_sprintf (pso, "currentdict end\n");
> gf_pso_sprintf (pso, "(%s) cvn exch definefont pop\n", pso->encodedname);
1508a1510,1547
>
> } else {
> tables = gp_tt_get_tables (fbuf, b.buf_size, pso->face->entry->index);
> /* Relatively easy - just embed TTF into PS stream */
> /* Download master font */
> TTVersion = 1.0;
> MfrRevision = 1.0;
> gf_pso_sprintf (pso, "%%!PS-TrueTypeFont-");
> gf_pso_print_double (pso, "%g", TTVersion);
> gf_pso_sprintf (pso, "-");
> gf_pso_print_double (pso, "%g", MfrRevision);
> gf_pso_sprintf (pso, "\n");
>
> gf_pso_sprintf (pso, "/CIDInit /ProcSet findresource begin\n\n");
> gf_pso_sprintf (pso, "20 dict begin\n");
> gf_pso_sprintf (pso, "/CIDFontName (%s) cvn def\n", embeddedname);
> gf_pso_sprintf (pso, "/CIDFontVersion 1 def\n");
> gf_pso_sprintf (pso, "/CIDFontType 2 def\n");
> gf_pso_sprintf (pso, "/FontType 42 def\n");
> gf_pso_sprintf (pso, "/CIDSystemInfo 3 dict dup begin\n");
> gf_pso_sprintf (pso, " /Registry (Adobe) def\n");
> gf_pso_sprintf (pso, " /Ordering (Identity) def\n");
> gf_pso_sprintf (pso, " /Supplement 0 def\n");
> gf_pso_sprintf (pso, " end def\n");
> gf_pso_sprintf (pso, "/CIDCount %d def\n", pso->face->num_glyphs);
> gf_pso_sprintf (pso, "/GDBytes 2 def\n");
> gf_pso_sprintf (pso, "/CIDMap 0 def\n");
> gf_pso_sprintf (pso, "/PaintType 0 def\n");
> gf_pso_sprintf (pso, "/FontMatrix [1 0 0 1 0 0] def\n");
> bbox = gnome_font_face_get_stdbbox (pso->face);
> gf_pso_sprintf (pso, "/FontBBox [");
> gf_pso_print_double (pso, "%g", bbox->x0);
> gf_pso_sprintf (pso, " ");
> gf_pso_print_double (pso, "%g", bbox->y0);
> gf_pso_sprintf (pso, " ");
> gf_pso_print_double (pso, "%g", bbox->x1);
> gf_pso_sprintf (pso, " ");
> gf_pso_print_double (pso, "%g", bbox->y1);
1510,1514c1549,1562
< gf_pso_sprintf (pso, "/Encoding [\n");
< for (i = 0; i < 256; i++) {
< gint fn;
< fn = (i < nfonts) ? i : 0;
< gf_pso_sprintf (pso, ((i & 0xf) == 0xf) ? "%d\n" : "%d ", fn);
---
> gf_pso_sprintf (pso, "/Encoding [] readonly def\n");
> gf_pso_sprintf (pso, "/CharStrings 1 dict dup begin\n");
> gf_pso_sprintf (pso, " /.notdef 0 def\n");
> gf_pso_sprintf (pso, " end readonly def\n");
> gf_pso_sprintf (pso, "/sfnts [\n");
> head = gp_tt_build_header (fbuf, b.buf_size, tables, required);
> sfnts_write_byte_array (pso, head);
> g_byte_array_free (head, TRUE);
> i = 0;
> for (i = 0; required[i] != NULL; i++) {
> struct tt_table *table;
> table = (struct tt_table *) g_hash_table_lookup (tables, (gpointer) required[i]);
> if (table == NULL) continue;
> sfnts_write_tt_table (pso, fbuf, b.buf_size, table);
1517,1518c1565,1629
< gf_pso_sprintf (pso, "currentdict end\n");
< gf_pso_sprintf (pso, "(%s) cvn exch definefont pop\n", pso->encodedname);
---
>
> metrics_count = 0;
> if (g_hash_table_lookup (tables, "hmtx")) {
> metrics_count += 2;
> if (g_hash_table_lookup (tables, "vmtx")) {
> metrics_count += 2;
> }
> }
> gf_pso_sprintf (pso, "/MetricsCount %d def\n", metrics_count);
> num_glyphs = 1;
> for (i = 0; i < pso->face->num_glyphs; i++) {
> if (PSO_GLYPH_MARKED(pso, i)) num_glyphs++;
> }
> gf_pso_sprintf (pso, "/GlyphDirectory %d dict dup begin\n", num_glyphs);
> for (i = 0; i < pso->face->num_glyphs; i++) {
> GByteArray *glyph_desc;
> if (i != 0 && ! PSO_GLYPH_MARKED(pso, i)) continue;
> gf_pso_sprintf (pso, " %d ", i);
> glyph_desc = gp_tt_get_glyph_desc(fbuf, b.buf_size, tables, i, metrics_count);
> sfnts_write_byte_array(pso, glyph_desc);
> g_byte_array_free (glyph_desc, TRUE);
> gf_pso_sprintf (pso, " def\n");
> }
> gf_pso_sprintf (pso, " end def\n");
> gf_pso_sprintf (pso, "CIDFontName currentdict end /CIDFont defineresource pop\n\n");
>
> gf_pso_sprintf (pso, "(%s) cvn /Identity-H /CMap findresource[(%s) cvn /CIDFont findresource] composefont pop\n", pso->encodedname, embeddedname);
> g_hash_table_destroy (tables);
> }
>
> gnome_print_buffer_munmap (&b);
> }
>
> void
> sfnts_write_byte_array (GnomeFontPsObject *pso, GByteArray* array)
> {
> guint i, j;
> guint8 *b;
>
> gf_pso_sprintf (pso, "<");
> for (b = array->data, i = 0; i < array->len; i += 32) {
> for (j = 0; j < 32 && (i + j) < array->len; j++)
> gf_pso_sprintf(pso, "%02x", *b++);
> if (j == 32)
> gf_pso_sprintf(pso, "\n");
> }
> gf_pso_sprintf (pso, "00>\n");
> }
>
> void
> sfnts_write_tt_table (GnomeFontPsObject *pso, const guchar *buf, guint buf_len, struct tt_table *table)
> {
> const guchar *b;
> guint32 i, j;
>
> gf_pso_sprintf (pso, "<");
> for (b = buf + table->offset, i = 0; i < table->length; i+=32) {
> for (j = 0; j < 32 && (i + j) < table->length; j++)
> gf_pso_sprintf(pso, "%02x", *b++);
> if (j == 32)
> gf_pso_sprintf(pso, "\n");
> }
> if (table->length % 4 != 0) {
> for (i = 0; i < (4 - table->length % 4); i++)
> gf_pso_sprintf(pso, "00");
1519a1631
> gf_pso_sprintf (pso, "00>\n");
Index: gnome-print-ps2.c
===================================================================
RCS file: /cvs/gnome/libgnomeprint/libgnomeprint/gnome-print-ps2.c,v
retrieving revision 1.79
diff -r1.79 gnome-print-ps2.c
47a48
> #define CMAP_IDENTITY "/CIDInit /ProcSet findresource begin\n10 dict begin\n begincmap\n /CMapType 1 def\n /CMapName /Identity-H def\n /CIDSystemInfo 3 dict dup begin\n /Registry (Adobe) def\n /Ordering (Identity) def\n /Supplement 0 def\n end def\n 1 begincodespacerange\n <0000> <ffff>\n endcodespacerange\n 0 usefont\n 1 begincidrange\n <0000> <ffff> 0\n endcidrange\n endcmap\n currentdict CMapName exch /CMap defineresource pop\nend\n10 dict begin\n begincmap\n /CMapType 1 def\n /CMapName /Identity-V def\n /CIDSystemInfo 3 dict dup begin\n /Registry (Adobe) def\n /Ordering (Identity) def\n /Supplement 0 def\n end def\n /WMode 1 def\n 1 begincodespacerange\n <0000> <ffff>\n endcodespacerange\n 0 usefont\n 1 begincidrange\n <0000> <ffff> 0\n endcidrange\n endcmap\n currentdict CMapName exch /CMap defineresource pop\nend\nend\n"
768a770
> gboolean need_cmap_identity;
850a853,861
> need_cmap_identity = FALSE;
> for (font = ps2->fonts; font != NULL; font = font->next) {
> if (font->pso->face->entry->type == GP_FONT_ENTRY_TRUETYPE) {
> need_cmap_identity = TRUE;
> break;
> }
> }
> if (need_cmap_identity)
> gnome_print_transport_printf (pc->transport, CMAP_IDENTITY);
Index: Makefile.am
===================================================================
RCS file: /cvs/gnome/libgnomeprint/libgnomeprint/Makefile.am,v
retrieving revision 1.100
diff -r1.100 Makefile.am
17c17,18
< gp-tt-t1.c gp-tt-t1.h
---
> gp-tt-t1.c gp-tt-t1.h \
> gp-tt-cid2.c gp-tt-cid2.h
#include "gp-tt-cid2.h"
#include <glib.h>
#include <string.h>
#define GUINT32FROMPTR(p) ((*(guchar*)((p))<<24)|(*((guchar*)(p)+1)<<16)|(*((guchar*)(p)+2)<<8)|(*((guchar*)(p)+3)))
#define GUINT16FROMPTR(p) ((*(guchar*)((p))<<8)|(*((guchar*)(p)+1)))
#define GP_TT_IS_TTC(b) (!strncmp (b, "ttcf", 4))
#define GUINT16TOPTR(p,i) (*((guint8*)p)=(i>>8)&0xFF,*((guint8*)p+1)=i&0xFF)
#define GUINT32TOPTR(p,i) (*((guint8*)p)=(i>>24)&0xFF,*((guint8*)p+1)=(i>>16)&0xFF,*((guint8*)p+2)=(i>>8)&0xFF,*((guint8*)p+3)=i&0xFF)
struct tt_glyph_loca* gp_tt_loca_get (const guchar *buf, guint buf_len, GHashTable *tables, guint glyph);
GByteArray* gp_tt_glyf_get (const guchar *buf, guint buf_len, GHashTable *tables, guint glyph);
guint32 gp_tt_vmtx_get (const guchar *buf, guint buf_len, GHashTable *tables, guint glyph);
guint32 gp_tt_hmtx_get (const guchar *buf, guint buf_len, GHashTable *tables, guint glyph);
guint gp_tt_head_get_index_to_loc_format (const guchar *buf, guint buf_len, GHashTable *tables);
GHashTable *
gp_tt_get_tables (const guchar *buf, guint buf_len, guint face)
{
const guchar *b;
guint32 scaler_type;
guint i, offset = 0, numTables;
GHashTable *tt_tables;
b = buf;
if (GP_TT_IS_TTC (b)) {
guint32 version, num_fonts;
/* this file is TrueType Collection file */
version = GUINT32FROMPTR (b + 4);
if (version >= 0x00010000) {
num_fonts = GUINT32FROMPTR (b + 8);
if (face > num_fonts) {
g_warning ("font doesn't have a face %d. number of face is %d.", face, num_fonts);
return NULL;
}
offset = GUINT32FROMPTR (b + 12 + face * 4);
} else {
g_warning ("unknown TTC version %X", version);
return NULL;
}
}
scaler_type = GUINT32FROMPTR (b + offset);
numTables = GUINT16FROMPTR (b + offset + 4);
if ((scaler_type != 0x74727565) && (scaler_type != 0x00010000))
return NULL;
b = buf + offset + 12;
tt_tables = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, g_free);
for (i = 0; i < numTables; i++) {
guint j;
struct tt_table *table;
table = (struct tt_table *) g_malloc (sizeof(struct tt_table));
table->tag[4] = 0;
for (j = 0; j < 4; j++)
table->tag[j] = *(b + j);
table->checksum = GUINT32FROMPTR (b + 4);
table->offset = GUINT32FROMPTR (b + 8);
table->length = GUINT32FROMPTR (b + 12);
g_hash_table_insert (tt_tables, table->tag, table);
b += 16;
}
return tt_tables;
}
GByteArray*
gp_tt_build_header (const guchar *buf, guint buf_len, GHashTable *tables, guchar **required)
{
GByteArray *head;
guchar *headbuf;
guint8 *b;
guchar **tag;
guint num_tables, search_range, entry_selector, range_shift;
guint i;
guint32 len, offset;
num_tables = 0;
for (tag = required; *tag != NULL; tag++) {
struct tt_table *table;
table = g_hash_table_lookup (tables, *tag);
if (table != NULL || !strcmp(*tag, "gdir"))
num_tables++;
}
/* needs check */
entry_selector = 1;
while ((entry_selector << 1) <= num_tables)
entry_selector <<= 1;
search_range = entry_selector * 16;
range_shift = num_tables * 16 - search_range;
len = offset = 12 + 16 * num_tables;
headbuf = g_malloc (sizeof(guchar[len]));
headbuf[0] = 0;
headbuf[1] = 1;
headbuf[2] = 0;
headbuf[3] = 0;
GUINT16TOPTR (headbuf + 4, num_tables);
GUINT16TOPTR (headbuf + 6, search_range);
GUINT16TOPTR (headbuf + 8, entry_selector);
GUINT16TOPTR (headbuf + 10, range_shift);
for (b = headbuf + 12, tag = required; *tag != NULL; tag++) {
struct tt_table *table;
table = g_hash_table_lookup (tables, *tag);
if (table == NULL && strcmp (*tag, "gdir"))
continue;
if (strcmp(*tag, "gdir") != 0) {
for (i = 0; i < 4; i++) *(b+i) = *(table->tag+i);
GUINT32TOPTR (b + 4, table->checksum);
GUINT32TOPTR (b + 8, offset);
GUINT32TOPTR (b + 12, table->length);
offset += table->length;
} else {
*b = 'g', *(b+1) = 'd', *(b+2) = 'i', *(b+3) = 'r';
GUINT32TOPTR (b + 4, 0);
GUINT32TOPTR (b + 8, 0);
GUINT32TOPTR (b + 12, 0);
}
if (offset % 4 != 0)
offset += 4 - offset % 4;
b += 16;
}
head = g_byte_array_sized_new (len);
g_byte_array_append (head, headbuf, len);
g_free (headbuf);
return head;
}
GByteArray*
gp_tt_get_glyph_desc (const guchar * buf, guint buf_len, GHashTable *tables, guint glyph, guint metrics_count)
{
GByteArray *glyf, *desc;
guint32 hmtx, vmtx;
glyf = gp_tt_glyf_get (buf, buf_len, tables, glyph);
switch (metrics_count) {
case 0:
desc = glyf;
break;
case 2:
desc = g_byte_array_sized_new (glyf->len + (metrics_count << 1));
hmtx = gp_tt_hmtx_get (buf, buf_len, tables, glyph);
GUINT32TOPTR (desc->data, hmtx);
desc->len = 4;
g_byte_array_append (desc, glyf->data, glyf->len);
g_byte_array_free (glyf, TRUE);
break;
case 4:
desc = g_byte_array_sized_new (glyf->len + (metrics_count << 1));
hmtx = gp_tt_hmtx_get (buf, buf_len, tables, glyph);
vmtx = gp_tt_vmtx_get (buf, buf_len, tables, glyph);
GUINT32TOPTR (desc->data, vmtx);
GUINT32TOPTR (desc->data + 4, hmtx);
desc->len = 8;
g_byte_array_append (desc, glyf->data, glyf->len);
g_byte_array_free (glyf, TRUE);
break;
default:
desc = NULL;
}
return desc;
}
GByteArray*
gp_tt_glyf_get (const guchar *buf, guint buf_len, GHashTable *tables, guint glyph)
{
struct tt_glyph_loca *loca;
struct tt_table *glyf;
GByteArray *desc;
glyf = g_hash_table_lookup (tables, "glyf");
loca = gp_tt_loca_get (buf, buf_len, tables, glyph);
desc = g_byte_array_sized_new (loca->length);
g_byte_array_append (desc, buf + glyf->offset + loca->offset, loca->length);
g_free (loca);
return desc;
}
struct tt_glyph_loca*
gp_tt_loca_get (const guchar *buf, guint buf_len, GHashTable *tables, guint index)
{
guint format;
struct tt_table *loca;
struct tt_glyph_loca *result;
const guchar * b;
loca = g_hash_table_lookup (tables, "loca");
format = gp_tt_head_get_index_to_loc_format (buf, buf_len, tables);
result = (struct tt_glyph_loca *) g_malloc (sizeof(struct tt_glyph_loca));
if (format == 0) {
b = buf + loca->offset + index * 2;
result->offset = GUINT16FROMPTR (b);
result->length = GUINT16FROMPTR (b + 2) - result->offset;
result->offset <<= 1;
result->length <<= 1;
} else if (format == 1) {
b = buf + loca->offset + index * 4;
result->offset = GUINT32FROMPTR (b);
result->length = GUINT32FROMPTR (b + 4) - result->offset;
} else {
g_free (result);
return NULL;
}
return result;
}
guint32
gp_tt_hmtx_get (const guchar *buf, guint buf_len, GHashTable *tables, guint glyph)
{
struct tt_table *hmtx;
hmtx = g_hash_table_lookup (tables, "hmtx");
return GUINT32FROMPTR (buf + hmtx->offset + glyph * 4);
}
guint32
gp_tt_vmtx_get (const guchar *buf, guint buf_len, GHashTable *tables, guint glyph)
{
struct tt_table *vmtx;
vmtx = g_hash_table_lookup (tables, "vmtx");
return GUINT32FROMPTR (buf + vmtx->offset + glyph * 4);
}
guint
gp_tt_head_get_index_to_loc_format (const guchar *buf, guint buf_len, GHashTable *tables)
{
struct tt_table *head;
head = (struct tt_table *) g_hash_table_lookup (tables, "head");
return GUINT16FROMPTR (buf + head->offset + 50);
}
#ifndef __GP_TT_CID2_H__
#define __GP_TT_CID2_H__
#include <glib.h>
G_BEGIN_DECLS
struct tt_table {
guchar tag[5];
guint32 checksum;
guint32 offset;
guint32 length;
};
struct tt_glyph_loca {
guint32 offset;
guint32 length;
};
GHashTable* gp_tt_get_tables (const guchar *buf, guint buf_len, guint face);
GByteArray* gp_tt_build_header (const guchar *buf, guint buf_len, GHashTable *tables, guchar **required);
GByteArray* gp_tt_get_glyph_desc (const guchar *buf, guint buf_len, GHashTable *tables, guint glyph, guint metrics_count);
G_END_DECLS
#endif
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]