Module: wine Branch: master Commit: 10ec7dacde5df4698f43feee97cb72e9a64a3025 URL: http://source.winehq.org/git/wine.git/?a=commit;h=10ec7dacde5df4698f43feee97...
Author: Aric Stewart aric@codeweavers.com Date: Mon Dec 19 07:25:00 2011 -0600
usp10: Code for the cmap format 12 table for unicode code points beyond the BMP.
---
dlls/usp10/shape.c | 117 +++++++++++++++++++++++++++++++++++++++++++ dlls/usp10/usp10.c | 1 + dlls/usp10/usp10_internal.h | 4 ++ 3 files changed, 122 insertions(+), 0 deletions(-)
diff --git a/dlls/usp10/shape.c b/dlls/usp10/shape.c index d0ab0b2..e889ba8 100644 --- a/dlls/usp10/shape.c +++ b/dlls/usp10/shape.c @@ -19,6 +19,7 @@ * */ #include <stdarg.h> +#include <stdlib.h>
#include "windef.h" #include "winbase.h" @@ -101,8 +102,10 @@ enum joined_forms {
#ifdef WORDS_BIGENDIAN #define GET_BE_WORD(x) (x) +#define GET_BE_DWORD(x) (x) #else #define GET_BE_WORD(x) RtlUshortByteSwap(x) +#define GET_BE_DWORD(x) RtlUlongByteSwap(x) #endif
/* These are all structures needed for the GSUB table */ @@ -312,6 +315,37 @@ typedef struct { GDEF_ClassRangeRecord ClassRangeRecord[1]; } GDEF_ClassDefFormat2;
+ +/* These are all structures needed for the cmap format 12 table */ +#define CMAP_TAG MS_MAKE_TAG('c', 'm', 'a', 'p') + +typedef struct { + WORD platformID; + WORD encodingID; + DWORD offset; +} CMAP_EncodingRecord; + +typedef struct { + WORD version; + WORD numTables; + CMAP_EncodingRecord tables[1]; +} CMAP_Header; + +typedef struct { + DWORD startCharCode; + DWORD endCharCode; + DWORD startGlyphID; +} CMAP_SegmentedCoverage_group; + +typedef struct { + WORD format; + WORD reserved; + DWORD length; + DWORD language; + DWORD nGroups; + CMAP_SegmentedCoverage_group groups[1]; +} CMAP_SegmentedCoverage; + static INT GSUB_apply_lookup(const GSUB_LookupList* lookup, INT lookup_index, WORD *glyphs, INT glyph_index, INT write_dir, INT *glyph_count);
typedef struct tagVowelComponents @@ -3654,3 +3688,86 @@ HRESULT SHAPE_CheckFontForRequiredFeatures(HDC hdc, ScriptCache *psc, SCRIPT_ANA
return USP_E_SCRIPT_NOT_IN_FONT; } + +static VOID *load_CMAP_format12_table(HDC hdc, ScriptCache *psc) +{ + CMAP_Header *CMAP_Table = NULL; + int length; + int i; + + if (!psc->CMAP_Table) + { + length = GetFontData(hdc, CMAP_TAG , 0, NULL, 0); + if (length != GDI_ERROR) + { + psc->CMAP_Table = HeapAlloc(GetProcessHeap(),0,length); + GetFontData(hdc, CMAP_TAG , 0, psc->CMAP_Table, length); + TRACE("Loaded cmap table of %i bytes\n",length); + } + else + return NULL; + } + + CMAP_Table = psc->CMAP_Table; + + for (i = 0; i < GET_BE_WORD(CMAP_Table->numTables); i++) + { + if ( (GET_BE_WORD(CMAP_Table->tables[i].platformID) == 3) && + (GET_BE_WORD(CMAP_Table->tables[i].encodingID) == 10) ) + { + CMAP_SegmentedCoverage *format = (CMAP_SegmentedCoverage*)(((BYTE*)CMAP_Table) + GET_BE_DWORD(CMAP_Table->tables[i].offset)); + if (GET_BE_WORD(format->format) == 12) + return format; + } + } + return NULL; +} + +static int compare_group(const void *a, const void* b) +{ + const DWORD *chr = a; + const CMAP_SegmentedCoverage_group *group = b; + + if (*chr < GET_BE_DWORD(group->startCharCode)) + return -1; + if (*chr > GET_BE_DWORD(group->endCharCode)) + return 1; + return 0; +} + +DWORD CMAP_GetGlyphIndex(HDC hdc, ScriptCache *psc, DWORD utf32c, LPWORD pgi, DWORD flags) +{ + /* BMP: use gdi32 for ease */ + if (utf32c < 0x10000) + { + WCHAR ch = utf32c; + return GetGlyphIndicesW(hdc,&ch, 1, pgi, flags); + } + + if (!psc->CMAP_format12_Table) + psc->CMAP_format12_Table = load_CMAP_format12_table(hdc, psc); + + if (flags & GGI_MARK_NONEXISTING_GLYPHS) + *pgi = 0xffff; + else + *pgi = 0; + + if (psc->CMAP_format12_Table) + { + CMAP_SegmentedCoverage *format = NULL; + CMAP_SegmentedCoverage_group *group = NULL; + + format = (CMAP_SegmentedCoverage *)psc->CMAP_format12_Table; + + group = bsearch(&utf32c, format->groups, GET_BE_DWORD(format->nGroups), + sizeof(CMAP_SegmentedCoverage_group), compare_group); + + if (group) + { + DWORD offset = utf32c - GET_BE_DWORD(group->startCharCode); + *pgi = GET_BE_DWORD(group->startGlyphID) + offset; + return 0; + } + } + return 0; +} diff --git a/dlls/usp10/usp10.c b/dlls/usp10/usp10.c index ad1764a..a0e143e 100644 --- a/dlls/usp10/usp10.c +++ b/dlls/usp10/usp10.c @@ -862,6 +862,7 @@ HRESULT WINAPI ScriptFreeCache(SCRIPT_CACHE *psc) } heap_free(((ScriptCache *)*psc)->GSUB_Table); heap_free(((ScriptCache *)*psc)->GDEF_Table); + heap_free(((ScriptCache *)*psc)->CMAP_Table); heap_free(((ScriptCache *)*psc)->features); heap_free(*psc); *psc = NULL; diff --git a/dlls/usp10/usp10_internal.h b/dlls/usp10/usp10_internal.h index 1692b60..f310011 100644 --- a/dlls/usp10/usp10_internal.h +++ b/dlls/usp10/usp10_internal.h @@ -129,6 +129,8 @@ typedef struct { ABC *widths[GLYPH_MAX / GLYPH_BLOCK_SIZE]; LPVOID GSUB_Table; LPVOID GDEF_Table; + LPVOID CMAP_Table; + LPVOID CMAP_format12_Table; INT feature_count; LoadedFeature *features;
@@ -181,3 +183,5 @@ void Indic_ReorderCharacters( HDC hdc, SCRIPT_ANALYSIS *psa, ScriptCache* psc, L void Indic_ParseSyllables( HDC hdc, SCRIPT_ANALYSIS *psa, ScriptCache* psc, LPCWSTR input, const int cChar, IndicSyllable **syllables, int *syllable_count, lexical_function lex, BOOL modern);
void BREAK_line(const WCHAR *chars, int count, const SCRIPT_ANALYSIS *sa, SCRIPT_LOGATTR *la) DECLSPEC_HIDDEN; + +DWORD CMAP_GetGlyphIndex(HDC hdc, ScriptCache *psc, DWORD utf32c, LPWORD pgi, DWORD flags) DECLSPEC_HIDDEN;