Aric Stewart : usp10: Code for the cmap format 12 table for unicode code points beyond the BMP.
Alexandre Julliard
julliard at winehq.org
Mon Dec 19 13:39:22 CST 2011
Module: wine
Branch: master
Commit: 10ec7dacde5df4698f43feee97cb72e9a64a3025
URL: http://source.winehq.org/git/wine.git/?a=commit;h=10ec7dacde5df4698f43feee97cb72e9a64a3025
Author: Aric Stewart <aric at 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;
More information about the wine-cvs
mailing list