diff --git a/dlls/dwrite/dwrite_private.h b/dlls/dwrite/dwrite_private.h index 6eac1f4f338..3251e66dec4 100644 --- a/dlls/dwrite/dwrite_private.h +++ b/dlls/dwrite/dwrite_private.h @@ -245,8 +245,10 @@ struct dwrite_colorglyph { UINT16 palette_index; }; -extern HRESULT opentype_get_colr_glyph(const void*,UINT16,struct dwrite_colorglyph*) DECLSPEC_HIDDEN; -extern void opentype_colr_next_glyph(const void*,struct dwrite_colorglyph*) DECLSPEC_HIDDEN; +extern HRESULT opentype_get_colr_glyph(const struct dwrite_fonttable *table, UINT16 glyph, + struct dwrite_colorglyph *color_glyph) DECLSPEC_HIDDEN; +extern void opentype_colr_next_glyph(const struct dwrite_fonttable *table, + struct dwrite_colorglyph *color_glyph) DECLSPEC_HIDDEN; enum gasp_flags { GASP_GRIDFIT = 0x0001, diff --git a/dlls/dwrite/font.c b/dlls/dwrite/font.c index 2c51674b0a8..bb04df6bd28 100644 --- a/dlls/dwrite/font.c +++ b/dlls/dwrite/font.c @@ -5649,7 +5649,7 @@ static BOOL colorglyphenum_build_color_run(struct dwrite_colorglyphenum *glyphen /* offsets are relative to glyph origin, nothing to fix up */ if (glyphenum->color_offsets) glyphenum->color_offsets[index] = glyphenum->offsets[g]; - opentype_colr_next_glyph(glyphenum->colr.data, glyphenum->glyphs + g); + opentype_colr_next_glyph(&glyphenum->colr, glyphenum->glyphs + g); if (index) glyphenum->color_advances[index-1] += advance_adj; colorrun->glyphRun.glyphCount++; @@ -5755,7 +5755,7 @@ HRESULT create_colorglyphenum(float originX, float originY, const DWRITE_GLYPH_R has_colored_glyph = FALSE; colorglyphenum->has_regular_glyphs = FALSE; for (i = 0; i < run->glyphCount; i++) { - if (opentype_get_colr_glyph(colorglyphenum->colr.data, run->glyphIndices[i], colorglyphenum->glyphs + i) == S_OK) { + if (opentype_get_colr_glyph(&colorglyphenum->colr, run->glyphIndices[i], colorglyphenum->glyphs + i) == S_OK) { colorglyphenum->max_layer_num = max(colorglyphenum->max_layer_num, colorglyphenum->glyphs[i].num_layers); has_colored_glyph = TRUE; } diff --git a/dlls/dwrite/opentype.c b/dlls/dwrite/opentype.c index 647ac995978..82491dcc02e 100644 --- a/dlls/dwrite/opentype.c +++ b/dlls/dwrite/opentype.c @@ -862,26 +862,26 @@ struct cpal_color_record }; /* COLR table */ -struct COLR_Header +struct colr_header { USHORT version; - USHORT numBaseGlyphRecords; - ULONG offsetBaseGlyphRecord; - ULONG offsetLayerRecord; - USHORT numLayerRecords; + USHORT num_baseglyph_records; + ULONG offset_baseglyph_records; + ULONG offset_layer_records; + USHORT num_layer_records; }; -struct COLR_BaseGlyphRecord +struct colr_baseglyph_record { - USHORT GID; - USHORT firstLayerIndex; - USHORT numLayers; + USHORT glyph; + USHORT first_layer_index; + USHORT num_layers; }; -struct COLR_LayerRecord +struct colr_layer_record { - USHORT GID; - USHORT paletteIndex; + USHORT glyph; + USHORT palette_index; }; static const void *table_read_ensure(const struct dwrite_fonttable *table, unsigned int offset, unsigned int size) @@ -2050,8 +2050,8 @@ HRESULT opentype_get_cpal_entries(const struct dwrite_fonttable *cpal, unsigned static int colr_compare_gid(const void *g, const void *r) { - const struct COLR_BaseGlyphRecord *record = r; - UINT16 glyph = *(UINT16*)g, GID = GET_BE_WORD(record->GID); + const struct colr_baseglyph_record *record = r; + UINT16 glyph = *(UINT16*)g, GID = GET_BE_WORD(record->glyph); int ret = 0; if (glyph > GID) @@ -2062,51 +2062,68 @@ static int colr_compare_gid(const void *g, const void *r) return ret; } -HRESULT opentype_get_colr_glyph(const void *colr, UINT16 glyph, struct dwrite_colorglyph *ret) +HRESULT opentype_get_colr_glyph(const struct dwrite_fonttable *colr, UINT16 glyph, struct dwrite_colorglyph *ret) { - const struct COLR_BaseGlyphRecord *record; - const struct COLR_Header *header = colr; - const struct COLR_LayerRecord *layer; - DWORD layerrecordoffset = GET_BE_DWORD(header->offsetLayerRecord); - DWORD baserecordoffset = GET_BE_DWORD(header->offsetBaseGlyphRecord); - WORD numbaserecords = GET_BE_WORD(header->numBaseGlyphRecords); + unsigned int num_baseglyph_records, offset_baseglyph_records; + const struct colr_baseglyph_record *record; + const struct colr_layer_record *layer; + const struct colr_header *header; - record = bsearch(&glyph, (BYTE*)colr + baserecordoffset, numbaserecords, sizeof(struct COLR_BaseGlyphRecord), - colr_compare_gid); - if (!record) { - ret->layer = 0; - ret->first_layer = 0; - ret->num_layers = 0; - ret->glyph = glyph; - ret->palette_index = 0xffff; + memset(ret, 0, sizeof(*ret)); + ret->glyph = glyph; + ret->palette_index = 0xffff; + + header = table_read_ensure(colr, 0, sizeof(*header)); + if (!header) + return S_FALSE; + + num_baseglyph_records = GET_BE_WORD(header->num_baseglyph_records); + offset_baseglyph_records = GET_BE_DWORD(header->offset_baseglyph_records); + if (!table_read_ensure(colr, offset_baseglyph_records, num_baseglyph_records * sizeof(*record))) + { return S_FALSE; } - ret->layer = 0; - ret->first_layer = GET_BE_WORD(record->firstLayerIndex); - ret->num_layers = GET_BE_WORD(record->numLayers); + record = bsearch(&glyph, colr->data + offset_baseglyph_records, num_baseglyph_records, + sizeof(*record), colr_compare_gid); + if (!record) + return S_FALSE; - layer = (struct COLR_LayerRecord*)((BYTE*)colr + layerrecordoffset) + ret->first_layer + ret->layer; - ret->glyph = GET_BE_WORD(layer->GID); - ret->palette_index = GET_BE_WORD(layer->paletteIndex); + ret->first_layer = GET_BE_WORD(record->first_layer_index); + ret->num_layers = GET_BE_WORD(record->num_layers); + + if ((layer = table_read_ensure(colr, GET_BE_DWORD(header->offset_layer_records), + (ret->first_layer + ret->layer) * sizeof(*layer)))) + { + layer += ret->first_layer + ret->layer; + ret->glyph = GET_BE_WORD(layer->glyph); + ret->palette_index = GET_BE_WORD(layer->palette_index); + } return S_OK; } -void opentype_colr_next_glyph(const void *colr, struct dwrite_colorglyph *glyph) +void opentype_colr_next_glyph(const struct dwrite_fonttable *colr, struct dwrite_colorglyph *glyph) { - const struct COLR_Header *header = colr; - const struct COLR_LayerRecord *layer; - DWORD layerrecordoffset = GET_BE_DWORD(header->offsetLayerRecord); + const struct colr_layer_record *layer; + const struct colr_header *header; /* iterated all the way through */ if (glyph->layer == glyph->num_layers) return; + if (!(header = table_read_ensure(colr, 0, sizeof(*header)))) + return; + glyph->layer++; - layer = (struct COLR_LayerRecord*)((BYTE*)colr + layerrecordoffset) + glyph->first_layer + glyph->layer; - glyph->glyph = GET_BE_WORD(layer->GID); - glyph->palette_index = GET_BE_WORD(layer->paletteIndex); + + if ((layer = table_read_ensure(colr, GET_BE_DWORD(header->offset_layer_records), + (glyph->first_layer + glyph->layer) * sizeof(*layer)))) + { + layer += glyph->first_layer + glyph->layer; + glyph->glyph = GET_BE_WORD(layer->glyph); + glyph->palette_index = GET_BE_WORD(layer->palette_index); + } } BOOL opentype_has_vertical_variants(IDWriteFontFace4 *fontface)