dwrite: Validate font data when retrieving supported unicode ranges data.
Signed-off-by: Nikolay Sivov <nsivov@codeweavers.com> Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
3795100bf7
commit
2dcb3c7451
|
@ -208,9 +208,18 @@ struct file_stream_desc {
|
||||||
UINT32 face_index;
|
UINT32 face_index;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct dwrite_fonttable
|
||||||
|
{
|
||||||
|
const BYTE *data;
|
||||||
|
void *context;
|
||||||
|
UINT32 size;
|
||||||
|
BOOL exists;
|
||||||
|
};
|
||||||
|
|
||||||
extern HRESULT opentype_analyze_font(IDWriteFontFileStream*,BOOL*,DWRITE_FONT_FILE_TYPE*,DWRITE_FONT_FACE_TYPE*,UINT32*) DECLSPEC_HIDDEN;
|
extern HRESULT opentype_analyze_font(IDWriteFontFileStream*,BOOL*,DWRITE_FONT_FILE_TYPE*,DWRITE_FONT_FACE_TYPE*,UINT32*) DECLSPEC_HIDDEN;
|
||||||
extern HRESULT opentype_get_font_table(struct file_stream_desc*,UINT32,const void**,void**,UINT32*,BOOL*) DECLSPEC_HIDDEN;
|
extern HRESULT opentype_get_font_table(struct file_stream_desc*,UINT32,const void**,void**,UINT32*,BOOL*) DECLSPEC_HIDDEN;
|
||||||
extern HRESULT opentype_cmap_get_unicode_ranges(void*,UINT32,DWRITE_UNICODE_RANGE*,UINT32*) DECLSPEC_HIDDEN;
|
extern HRESULT opentype_cmap_get_unicode_ranges(const struct dwrite_fonttable *table, unsigned int max_count,
|
||||||
|
DWRITE_UNICODE_RANGE *ranges, unsigned int *count) DECLSPEC_HIDDEN;
|
||||||
extern void opentype_get_font_properties(struct file_stream_desc*,struct dwrite_font_props*) DECLSPEC_HIDDEN;
|
extern void opentype_get_font_properties(struct file_stream_desc*,struct dwrite_font_props*) DECLSPEC_HIDDEN;
|
||||||
extern void opentype_get_font_metrics(struct file_stream_desc*,DWRITE_FONT_METRICS1*,DWRITE_CARET_METRICS*) DECLSPEC_HIDDEN;
|
extern void opentype_get_font_metrics(struct file_stream_desc*,DWRITE_FONT_METRICS1*,DWRITE_CARET_METRICS*) DECLSPEC_HIDDEN;
|
||||||
extern HRESULT opentype_get_font_info_strings(const void*,DWRITE_INFORMATIONAL_STRING_ID,IDWriteLocalizedStrings**) DECLSPEC_HIDDEN;
|
extern HRESULT opentype_get_font_info_strings(const void*,DWRITE_INFORMATIONAL_STRING_ID,IDWriteLocalizedStrings**) DECLSPEC_HIDDEN;
|
||||||
|
|
|
@ -149,13 +149,6 @@ struct dwrite_font {
|
||||||
struct dwrite_fontfamily *family;
|
struct dwrite_fontfamily *family;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct dwrite_fonttable {
|
|
||||||
void *data;
|
|
||||||
void *context;
|
|
||||||
UINT32 size;
|
|
||||||
BOOL exists;
|
|
||||||
};
|
|
||||||
|
|
||||||
enum runanalysis_flags {
|
enum runanalysis_flags {
|
||||||
RUNANALYSIS_BOUNDS_READY = 1 << 0,
|
RUNANALYSIS_BOUNDS_READY = 1 << 0,
|
||||||
RUNANALYSIS_BITMAP_READY = 1 << 1,
|
RUNANALYSIS_BITMAP_READY = 1 << 1,
|
||||||
|
@ -345,7 +338,7 @@ static HRESULT set_cached_glyph_metrics(struct dwrite_fontface *fontface, UINT16
|
||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void* get_fontface_table(IDWriteFontFace4 *fontface, UINT32 tag, struct dwrite_fonttable *table)
|
static const void* get_fontface_table(IDWriteFontFace4 *fontface, UINT32 tag, struct dwrite_fonttable *table)
|
||||||
{
|
{
|
||||||
HRESULT hr;
|
HRESULT hr;
|
||||||
|
|
||||||
|
@ -381,29 +374,24 @@ static FLOAT get_font_prop_vec_dotproduct(const struct dwrite_font_propvec *left
|
||||||
return left->stretch * right->stretch + left->style * right->style + left->weight * right->weight;
|
return left->stretch * right->stretch + left->style * right->style + left->weight * right->weight;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void* get_fontface_cmap(struct dwrite_fontface *fontface)
|
static const void* get_fontface_vdmx(struct dwrite_fontface *fontface)
|
||||||
{
|
|
||||||
return get_fontface_table(&fontface->IDWriteFontFace4_iface, MS_CMAP_TAG, &fontface->cmap);
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void* get_fontface_vdmx(struct dwrite_fontface *fontface)
|
|
||||||
{
|
{
|
||||||
return get_fontface_table(&fontface->IDWriteFontFace4_iface, MS_VDMX_TAG, &fontface->vdmx);
|
return get_fontface_table(&fontface->IDWriteFontFace4_iface, MS_VDMX_TAG, &fontface->vdmx);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void* get_fontface_gasp(struct dwrite_fontface *fontface, UINT32 *size)
|
static const void* get_fontface_gasp(struct dwrite_fontface *fontface, UINT32 *size)
|
||||||
{
|
{
|
||||||
void *ptr = get_fontface_table(&fontface->IDWriteFontFace4_iface, MS_GASP_TAG, &fontface->gasp);
|
const void *ptr = get_fontface_table(&fontface->IDWriteFontFace4_iface, MS_GASP_TAG, &fontface->gasp);
|
||||||
*size = fontface->gasp.size;
|
*size = fontface->gasp.size;
|
||||||
return ptr;
|
return ptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void* get_fontface_cpal(struct dwrite_fontface *fontface)
|
static const void* get_fontface_cpal(struct dwrite_fontface *fontface)
|
||||||
{
|
{
|
||||||
return get_fontface_table(&fontface->IDWriteFontFace4_iface, MS_CPAL_TAG, &fontface->cpal);
|
return get_fontface_table(&fontface->IDWriteFontFace4_iface, MS_CPAL_TAG, &fontface->cpal);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void* get_fontface_colr(struct dwrite_fontface *fontface)
|
static const void* get_fontface_colr(struct dwrite_fontface *fontface)
|
||||||
{
|
{
|
||||||
return get_fontface_table(&fontface->IDWriteFontFace4_iface, MS_COLR_TAG, &fontface->colr);
|
return get_fontface_table(&fontface->IDWriteFontFace4_iface, MS_COLR_TAG, &fontface->colr);
|
||||||
}
|
}
|
||||||
|
@ -730,9 +718,10 @@ static HRESULT WINAPI dwritefontface_GetRecommendedRenderingMode(IDWriteFontFace
|
||||||
FLOAT ppdip, DWRITE_MEASURING_MODE measuring, IDWriteRenderingParams *params, DWRITE_RENDERING_MODE *mode)
|
FLOAT ppdip, DWRITE_MEASURING_MODE measuring, IDWriteRenderingParams *params, DWRITE_RENDERING_MODE *mode)
|
||||||
{
|
{
|
||||||
struct dwrite_fontface *This = impl_from_IDWriteFontFace4(iface);
|
struct dwrite_fontface *This = impl_from_IDWriteFontFace4(iface);
|
||||||
WORD gasp, *ptr;
|
const WORD *ptr;
|
||||||
UINT32 size;
|
UINT32 size;
|
||||||
FLOAT ppem;
|
FLOAT ppem;
|
||||||
|
WORD gasp;
|
||||||
|
|
||||||
TRACE("(%p)->(%.2f %.2f %d %p %p)\n", This, emSize, ppdip, measuring, params, mode);
|
TRACE("(%p)->(%.2f %.2f %d %p %p)\n", This, emSize, ppdip, measuring, params, mode);
|
||||||
|
|
||||||
|
@ -910,7 +899,8 @@ static HRESULT WINAPI dwritefontface1_GetUnicodeRanges(IDWriteFontFace4 *iface,
|
||||||
if (max_count && !ranges)
|
if (max_count && !ranges)
|
||||||
return E_INVALIDARG;
|
return E_INVALIDARG;
|
||||||
|
|
||||||
return opentype_cmap_get_unicode_ranges(get_fontface_cmap(This), max_count, ranges, count);
|
get_fontface_table(iface, MS_CMAP_TAG, &This->cmap);
|
||||||
|
return opentype_cmap_get_unicode_ranges(&This->cmap, max_count, ranges, count);
|
||||||
}
|
}
|
||||||
|
|
||||||
static BOOL WINAPI dwritefontface1_IsMonospacedFont(IDWriteFontFace4 *iface)
|
static BOOL WINAPI dwritefontface1_IsMonospacedFont(IDWriteFontFace4 *iface)
|
||||||
|
@ -1108,8 +1098,9 @@ static HRESULT WINAPI dwritefontface2_GetRecommendedRenderingMode(IDWriteFontFac
|
||||||
{
|
{
|
||||||
struct dwrite_fontface *This = impl_from_IDWriteFontFace4(iface);
|
struct dwrite_fontface *This = impl_from_IDWriteFontFace4(iface);
|
||||||
FLOAT emthreshold;
|
FLOAT emthreshold;
|
||||||
WORD gasp, *ptr;
|
const WORD *ptr;
|
||||||
UINT32 size;
|
UINT32 size;
|
||||||
|
WORD gasp;
|
||||||
|
|
||||||
TRACE("(%p)->(%.2f %.2f %.2f %p %d %d %d %p %p %p)\n", This, emSize, dpiX, dpiY, m, is_sideways, threshold,
|
TRACE("(%p)->(%.2f %.2f %.2f %p %d %d %d %p %p %p)\n", This, emSize, dpiX, dpiY, m, is_sideways, threshold,
|
||||||
measuringmode, params, renderingmode, gridfitmode);
|
measuringmode, params, renderingmode, gridfitmode);
|
||||||
|
@ -1239,8 +1230,9 @@ static HRESULT WINAPI dwritefontface3_GetRecommendedRenderingMode(IDWriteFontFac
|
||||||
{
|
{
|
||||||
struct dwrite_fontface *This = impl_from_IDWriteFontFace4(iface);
|
struct dwrite_fontface *This = impl_from_IDWriteFontFace4(iface);
|
||||||
FLOAT emthreshold;
|
FLOAT emthreshold;
|
||||||
WORD gasp, *ptr;
|
const WORD *ptr;
|
||||||
UINT32 size;
|
UINT32 size;
|
||||||
|
WORD gasp;
|
||||||
|
|
||||||
TRACE("(%p)->(%.2f %.2f %.2f %p %d %d %d %p %p %p)\n", This, emSize, dpiX, dpiY, m, is_sideways, threshold,
|
TRACE("(%p)->(%.2f %.2f %.2f %p %d %d %d %p %p %p)\n", This, emSize, dpiX, dpiY, m, is_sideways, threshold,
|
||||||
measuring_mode, params, rendering_mode, gridfit_mode);
|
measuring_mode, params, rendering_mode, gridfit_mode);
|
||||||
|
|
|
@ -82,16 +82,18 @@ typedef struct {
|
||||||
DWORD length;
|
DWORD length;
|
||||||
} TT_TableRecord;
|
} TT_TableRecord;
|
||||||
|
|
||||||
typedef struct {
|
struct cmap_encoding_record
|
||||||
|
{
|
||||||
WORD platformID;
|
WORD platformID;
|
||||||
WORD encodingID;
|
WORD encodingID;
|
||||||
DWORD offset;
|
DWORD offset;
|
||||||
} CMAP_EncodingRecord;
|
};
|
||||||
|
|
||||||
typedef struct {
|
struct cmap_header
|
||||||
|
{
|
||||||
WORD version;
|
WORD version;
|
||||||
WORD numTables;
|
WORD num_tables;
|
||||||
CMAP_EncodingRecord tables[1];
|
struct cmap_encoding_record tables[1];
|
||||||
} CMAP_Header;
|
} CMAP_Header;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
|
@ -100,25 +102,27 @@ typedef struct {
|
||||||
DWORD startGlyphID;
|
DWORD startGlyphID;
|
||||||
} CMAP_SegmentedCoverage_group;
|
} CMAP_SegmentedCoverage_group;
|
||||||
|
|
||||||
typedef struct {
|
struct cmap_segmented_coverage
|
||||||
|
{
|
||||||
WORD format;
|
WORD format;
|
||||||
WORD reserved;
|
WORD reserved;
|
||||||
DWORD length;
|
DWORD length;
|
||||||
DWORD language;
|
DWORD language;
|
||||||
DWORD nGroups;
|
DWORD num_groups;
|
||||||
CMAP_SegmentedCoverage_group groups[1];
|
CMAP_SegmentedCoverage_group groups[1];
|
||||||
} CMAP_SegmentedCoverage;
|
};
|
||||||
|
|
||||||
typedef struct {
|
struct cmap_segment_mapping
|
||||||
|
{
|
||||||
WORD format;
|
WORD format;
|
||||||
WORD length;
|
WORD length;
|
||||||
WORD language;
|
WORD language;
|
||||||
WORD segCountX2;
|
WORD seg_count_x2;
|
||||||
WORD searchRange;
|
WORD search_range;
|
||||||
WORD entrySelector;
|
WORD entry_selector;
|
||||||
WORD rangeShift;
|
WORD range_shift;
|
||||||
WORD endCode[1];
|
WORD end_code[1];
|
||||||
} CMAP_SegmentMapping_0;
|
};
|
||||||
|
|
||||||
enum OPENTYPE_CMAP_TABLE_FORMAT
|
enum OPENTYPE_CMAP_TABLE_FORMAT
|
||||||
{
|
{
|
||||||
|
@ -874,6 +878,26 @@ struct COLR_LayerRecord
|
||||||
USHORT paletteIndex;
|
USHORT paletteIndex;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static const void *table_read_ensure(const struct dwrite_fonttable *table, unsigned int offset, unsigned int size)
|
||||||
|
{
|
||||||
|
if (size > table->size || offset > table->size - size)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
return table->data + offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
static WORD table_read_be_word(const struct dwrite_fonttable *table, unsigned int offset)
|
||||||
|
{
|
||||||
|
const WORD *ptr = table_read_ensure(table, offset, sizeof(*ptr));
|
||||||
|
return ptr ? GET_BE_WORD(*ptr) : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static DWORD table_read_be_dword(const struct dwrite_fonttable *table, unsigned int offset)
|
||||||
|
{
|
||||||
|
const DWORD *ptr = table_read_ensure(table, offset, sizeof(*ptr));
|
||||||
|
return ptr ? GET_BE_DWORD(*ptr) : 0;
|
||||||
|
}
|
||||||
|
|
||||||
BOOL is_face_type_supported(DWRITE_FONT_FACE_TYPE type)
|
BOOL is_face_type_supported(DWRITE_FONT_FACE_TYPE type)
|
||||||
{
|
{
|
||||||
return (type == DWRITE_FONT_FACE_TYPE_CFF) ||
|
return (type == DWRITE_FONT_FACE_TYPE_CFF) ||
|
||||||
|
@ -1137,92 +1161,115 @@ HRESULT opentype_get_font_table(struct file_stream_desc *stream_desc, UINT32 tag
|
||||||
* CMAP
|
* CMAP
|
||||||
**********/
|
**********/
|
||||||
|
|
||||||
static UINT32 opentype_cmap_get_unicode_ranges_count(const CMAP_Header *CMAP_Table)
|
static unsigned int opentype_cmap_get_unicode_ranges_count(const struct dwrite_fonttable *cmap)
|
||||||
{
|
{
|
||||||
UINT32 count = 0;
|
unsigned int i, num_tables, count = 0;
|
||||||
int i;
|
const struct cmap_header *header;
|
||||||
|
|
||||||
for (i = 0; i < GET_BE_WORD(CMAP_Table->numTables); i++) {
|
num_tables = table_read_be_word(cmap, FIELD_OFFSET(struct cmap_header, num_tables));
|
||||||
WORD type;
|
header = table_read_ensure(cmap, 0, FIELD_OFFSET(struct cmap_header, tables[num_tables]));
|
||||||
WORD *table;
|
|
||||||
|
|
||||||
if (GET_BE_WORD(CMAP_Table->tables[i].platformID) != 3)
|
if (!header)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
for (i = 0; i < num_tables; ++i)
|
||||||
|
{
|
||||||
|
unsigned int format, offset;
|
||||||
|
|
||||||
|
if (GET_BE_WORD(header->tables[i].platformID) != 3)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
table = (WORD*)(((BYTE*)CMAP_Table) + GET_BE_DWORD(CMAP_Table->tables[i].offset));
|
offset = GET_BE_DWORD(header->tables[i].offset);
|
||||||
type = GET_BE_WORD(*table);
|
format = table_read_be_word(cmap, offset);
|
||||||
TRACE("table type %i\n", type);
|
|
||||||
|
|
||||||
switch (type)
|
switch (format)
|
||||||
{
|
{
|
||||||
case OPENTYPE_CMAP_TABLE_SEGMENT_MAPPING:
|
case OPENTYPE_CMAP_TABLE_SEGMENT_MAPPING:
|
||||||
{
|
{
|
||||||
CMAP_SegmentMapping_0 *format = (CMAP_SegmentMapping_0*)table;
|
count += table_read_be_word(cmap, offset + FIELD_OFFSET(struct cmap_segment_mapping, seg_count_x2)) / 2;
|
||||||
count += GET_BE_WORD(format->segCountX2)/2;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case OPENTYPE_CMAP_TABLE_SEGMENTED_COVERAGE:
|
case OPENTYPE_CMAP_TABLE_SEGMENTED_COVERAGE:
|
||||||
{
|
{
|
||||||
CMAP_SegmentedCoverage *format = (CMAP_SegmentedCoverage*)table;
|
count += table_read_be_dword(cmap, offset + FIELD_OFFSET(struct cmap_segmented_coverage, num_groups));
|
||||||
count += GET_BE_DWORD(format->nGroups);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
FIXME("table type %i unhandled.\n", type);
|
FIXME("table format %u is not supported.\n", format);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
|
|
||||||
HRESULT opentype_cmap_get_unicode_ranges(void *data, UINT32 max_count, DWRITE_UNICODE_RANGE *ranges, UINT32 *count)
|
HRESULT opentype_cmap_get_unicode_ranges(const struct dwrite_fonttable *cmap, unsigned int max_count,
|
||||||
|
DWRITE_UNICODE_RANGE *ranges, unsigned int *count)
|
||||||
{
|
{
|
||||||
CMAP_Header *CMAP_Table = data;
|
unsigned int i, num_tables, k = 0;
|
||||||
int i, k = 0;
|
const struct cmap_header *header;
|
||||||
|
|
||||||
if (!CMAP_Table)
|
if (!cmap->exists)
|
||||||
return E_FAIL;
|
return E_FAIL;
|
||||||
|
|
||||||
*count = opentype_cmap_get_unicode_ranges_count(CMAP_Table);
|
*count = opentype_cmap_get_unicode_ranges_count(cmap);
|
||||||
|
|
||||||
for (i = 0; i < GET_BE_WORD(CMAP_Table->numTables) && k < max_count; i++)
|
num_tables = table_read_be_word(cmap, FIELD_OFFSET(struct cmap_header, num_tables));
|
||||||
|
header = table_read_ensure(cmap, 0, FIELD_OFFSET(struct cmap_header, tables[num_tables]));
|
||||||
|
|
||||||
|
if (!header)
|
||||||
|
return S_OK;
|
||||||
|
|
||||||
|
for (i = 0; i < num_tables && k < max_count; ++i)
|
||||||
{
|
{
|
||||||
WORD type;
|
unsigned int j, offset, format;
|
||||||
WORD *table;
|
|
||||||
int j;
|
|
||||||
|
|
||||||
if (GET_BE_WORD(CMAP_Table->tables[i].platformID) != 3)
|
if (GET_BE_WORD(header->tables[i].platformID) != 3)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
table = (WORD*)(((BYTE*)CMAP_Table) + GET_BE_DWORD(CMAP_Table->tables[i].offset));
|
offset = GET_BE_DWORD(header->tables[i].offset);
|
||||||
type = GET_BE_WORD(*table);
|
|
||||||
TRACE("table type %i\n", type);
|
|
||||||
|
|
||||||
switch (type)
|
format = table_read_be_word(cmap, offset);
|
||||||
|
switch (format)
|
||||||
{
|
{
|
||||||
case OPENTYPE_CMAP_TABLE_SEGMENT_MAPPING:
|
case OPENTYPE_CMAP_TABLE_SEGMENT_MAPPING:
|
||||||
{
|
{
|
||||||
CMAP_SegmentMapping_0 *format = (CMAP_SegmentMapping_0*)table;
|
unsigned int segment_count = table_read_be_word(cmap, offset +
|
||||||
UINT16 segment_count = GET_BE_WORD(format->segCountX2)/2;
|
FIELD_OFFSET(struct cmap_segment_mapping, seg_count_x2)) / 2;
|
||||||
UINT16 *startCode = (WORD*)((BYTE*)format + sizeof(CMAP_SegmentMapping_0) + (sizeof(WORD) * segment_count));
|
const UINT16 *start_code = table_read_ensure(cmap, offset,
|
||||||
|
FIELD_OFFSET(struct cmap_segment_mapping, end_code[segment_count]) +
|
||||||
|
2 /* reservedPad */ +
|
||||||
|
2 * segment_count /* start code array */);
|
||||||
|
const UINT16 *end_code = table_read_ensure(cmap, offset,
|
||||||
|
FIELD_OFFSET(struct cmap_segment_mapping, end_code[segment_count]));
|
||||||
|
|
||||||
for (j = 0; j < segment_count && GET_BE_WORD(format->endCode[j]) < 0xffff && k < max_count; j++, k++) {
|
if (!start_code || !end_code)
|
||||||
ranges[k].first = GET_BE_WORD(startCode[j]);
|
continue;
|
||||||
ranges[k].last = GET_BE_WORD(format->endCode[j]);
|
|
||||||
|
for (j = 0; j < segment_count && GET_BE_WORD(end_code[j]) != 0xffff && k < max_count; ++j, ++k)
|
||||||
|
{
|
||||||
|
ranges[k].first = GET_BE_WORD(start_code[j]);
|
||||||
|
ranges[k].last = GET_BE_WORD(end_code[j]);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case OPENTYPE_CMAP_TABLE_SEGMENTED_COVERAGE:
|
case OPENTYPE_CMAP_TABLE_SEGMENTED_COVERAGE:
|
||||||
{
|
{
|
||||||
CMAP_SegmentedCoverage *format = (CMAP_SegmentedCoverage*)table;
|
unsigned int num_groups = table_read_be_dword(cmap, offset +
|
||||||
for (j = 0; j < GET_BE_DWORD(format->nGroups) && k < max_count; j++, k++) {
|
FIELD_OFFSET(struct cmap_segmented_coverage, num_groups));
|
||||||
ranges[k].first = GET_BE_DWORD(format->groups[j].startCharCode);
|
const struct cmap_segmented_coverage *coverage;
|
||||||
ranges[k].last = GET_BE_DWORD(format->groups[j].endCharCode);
|
|
||||||
|
coverage = table_read_ensure(cmap, offset,
|
||||||
|
FIELD_OFFSET(struct cmap_segmented_coverage, groups[num_groups]));
|
||||||
|
|
||||||
|
for (j = 0; j < num_groups && k < max_count; j++, k++)
|
||||||
|
{
|
||||||
|
ranges[k].first = GET_BE_DWORD(coverage->groups[j].startCharCode);
|
||||||
|
ranges[k].last = GET_BE_DWORD(coverage->groups[j].endCharCode);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
FIXME("table type %i unhandled.\n", type);
|
FIXME("table format %u unhandled.\n", format);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue