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