Commit 10ec7dac authored by Aric Stewart's avatar Aric Stewart Committed by Alexandre Julliard

usp10: Code for the cmap format 12 table for unicode code points beyond the BMP.

parent 38f9ba00
......@@ -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;
}
......@@ -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;
......
......@@ -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;
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment