Only in xdvipdfmx-0.4-new/data: Makefile diff -aur xdvipdfmx-0.4/src/dvi.c xdvipdfmx-0.4-new/src/dvi.c --- xdvipdfmx-0.4/src/dvi.c 2007-02-07 10:30:58.000000000 +0100 +++ xdvipdfmx-0.4-new/src/dvi.c 2007-07-18 15:06:32.774945893 +0200 @@ -64,6 +64,7 @@ #include "ft2build.h" #include FT_FREETYPE_H #include FT_TRUETYPE_TABLES_H +#include FT_TRUETYPE_TAGS_H #endif #define DVI_STACK_DEPTH_MAX 256u @@ -1897,6 +1898,29 @@ pdf_dev_setcolor(&color, 0); /* stroke color */ pdf_dev_setcolor(&color, 1); /* fill color */ } + + TT_HoriHeader *dir_hea; /* vhea structure is identical */ + FT_Error *error; + FT_Byte *buffer; + FT_ULong table_size = 0, offset; + if (FT_IS_SFNT(font->ft_face)) { + /* CFF driver of freetype does not set vertical metrics correctly, + so we'll read the metrics directly */ + dir_hea = FT_Get_Sfnt_Table(font->ft_face, (font->layout_dir == 0) + ? ft_sfnt_hhea + : ft_sfnt_vhea); + error = FT_Load_Sfnt_Table(font->ft_face, + (font->layout_dir == 0) ? TTAG_hmtx : TTAG_vmtx, + 0, NULL, &table_size); + if (!error) { + buffer = (FT_Byte *)calloc(table_size, 1); + /* Load the [hv]mtx table into buffer */ + FT_Load_Sfnt_Table(font->ft_face, + (font->layout_dir == 0) ? TTAG_hmtx : TTAG_vmtx, + 0, buffer, &table_size); + } + } + for (i = 0; i < slen; i++) { glyph_id = get_buffered_unsigned_pair(); /* freetype glyph index */ if (glyph_id < font->ft_face->num_glyphs) { @@ -1904,17 +1928,17 @@ if (FT_IS_SFNT(font->ft_face)) { /* CFF driver of freetype does not set vertical metrics correctly, so we'll read the metrics directly */ - TT_HoriHeader *dir_hea; /* vhea structure is identical */ - dir_hea = FT_Get_Sfnt_Table(font->ft_face, (font->layout_dir == 0) - ? ft_sfnt_hhea - : ft_sfnt_vhea); - if (dir_hea) { - FT_UShort *metrics = (FT_UShort*) dir_hea->long_metrics; - /* each metrics record is two shorts, advance and sidebearing */ - if (glyph_id < dir_hea->number_Of_HMetrics) - font->glyph_widths[glyph_id] = metrics[glyph_id * 2]; - else - font->glyph_widths[glyph_id] = metrics[2 * (dir_hea->number_Of_HMetrics - 1)]; + if (dir_hea && !error) { + /* each metrics record is two shorts, advance and sidebearing + * thus is 4-byte sized */ + offset = (glyph_id < dir_hea->number_Of_HMetrics) ? + 4 * glyph_id : 4 * (dir_hea->number_Of_HMetrics - 1); + if (offset + 4 > table_size) { + font->glyph_widths[glyph_id] = 0; + } else { + font->glyph_widths[glyph_id] = + (FT_UShort)(buffer[offset] << 8 | buffer[offset + 1]); + } } else font->glyph_widths[glyph_id] = 0; } @@ -1944,6 +1968,7 @@ } RELEASE(xloc); RELEASE(yloc); + free(buffer); if (!dvi_state.d) { dvi_state.h += width;