Commit 2fb344c1 authored by Aric Stewart's avatar Aric Stewart Committed by Alexandre Julliard

usp10: Generalize out applying Opentype features and define default features for…

usp10: Generalize out applying Opentype features and define default features for currently known scripts.
parent b6f2f10b
...@@ -242,15 +242,54 @@ static const char* contextual_features[] = ...@@ -242,15 +242,54 @@ static const char* contextual_features[] =
"medi" "medi"
}; };
static const char* arabic_GSUB_features[] = static OPENTYPE_FEATURE_RECORD standard_features[] =
{ {
"rlig", { 0x6167696c /*liga*/, 1},
"calt", { 0x67696c63 /*clig*/, 1},
"liga", };
"dlig",
"cswh", static OPENTYPE_FEATURE_RECORD arabic_features[] =
"mset", {
NULL { 0x67696c72 /*rlig*/, 1},
{ 0x746c6163 /*calt*/, 1},
{ 0x6167696c /*liga*/, 1},
{ 0x67696c64 /*dlig*/, 1},
{ 0x68777363 /*cswh*/, 1},
{ 0x7465736d /*mset*/, 1},
};
static OPENTYPE_FEATURE_RECORD hebrew_features[] =
{
{ 0x67696c64 /*dlig*/, 1},
};
static OPENTYPE_FEATURE_RECORD syriac_features[] =
{
{ 0x67696c72 /*rlig*/, 1},
{ 0x746c6163 /*calt*/, 1},
{ 0x6167696c /*liga*/, 1},
{ 0x67696c64 /*dlig*/, 1},
};
typedef struct ScriptShapeDataTag {
TEXTRANGE_PROPERTIES defaultTextRange;
CHAR otTag[5];
} ScriptShapeData;
/* in order of scripts */
static const ScriptShapeData ShapingData[] =
{
{{ standard_features, 2}, ""},
{{ standard_features, 2}, "latn"},
{{ standard_features, 2}, "latn"},
{{ standard_features, 2}, "latn"},
{{ standard_features, 2}, ""},
{{ standard_features, 2}, "latn"},
{{ arabic_features, 6}, "arab"},
{{ arabic_features, 6}, "arab"},
{{ hebrew_features, 1}, "hebr"},
{{ syriac_features, 4}, "syrc"},
{{ arabic_features, 6}, "arab"},
}; };
static INT GSUB_is_glyph_covered(LPCVOID table , UINT glyph) static INT GSUB_is_glyph_covered(LPCVOID table , UINT glyph)
...@@ -652,21 +691,8 @@ static const char* get_opentype_script(HDC hdc, SCRIPT_ANALYSIS *psa) ...@@ -652,21 +691,8 @@ static const char* get_opentype_script(HDC hdc, SCRIPT_ANALYSIS *psa)
{ {
UINT charset; UINT charset;
switch (psa->eScript) if (ShapingData[psa->eScript].otTag[0] != 0)
{ return ShapingData[psa->eScript].otTag;
case Script_Arabic:
case Script_Persian:
case Script_Arabic_Numeric:
return "arab";
case Script_Syriac:
return "syrc";
case Script_Hebrew:
return "hebr";
case Script_Latin:
case Script_Numeric:
case Script_CR:
return "latn";
}
/* /*
* fall back to the font charset * fall back to the font charset
...@@ -693,38 +719,67 @@ static const char* get_opentype_script(HDC hdc, SCRIPT_ANALYSIS *psa) ...@@ -693,38 +719,67 @@ static const char* get_opentype_script(HDC hdc, SCRIPT_ANALYSIS *psa)
} }
} }
static INT apply_GSUB_feature_to_glyph(HDC hdc, SCRIPT_ANALYSIS *psa, void* GSUB_Table, WORD *glyphs, INT index, INT write_dir, INT* glyph_count, const char* feat) static LPCVOID load_GSUB_feature(HDC hdc, SCRIPT_ANALYSIS *psa, ScriptCache *psc, const char* feat)
{ {
const GSUB_Header *header;
const GSUB_Script *script;
const GSUB_LangSys *language;
const GSUB_Feature *feature; const GSUB_Feature *feature;
int i;
if (!GSUB_Table) for (i = 0; i < psc->feature_count; i++)
return GSUB_E_NOFEATURE; if (strncmp(psc->features[i].tag,feat,4)==0)
return psc->features[i].feature;
header = GSUB_Table; feature = NULL;
script = GSUB_get_script_table(header, get_opentype_script(hdc,psa)); if (psc->GSUB_Table)
if (!script)
{ {
TRACE("Script not found\n"); const GSUB_Script *script;
return GSUB_E_NOFEATURE; const GSUB_LangSys *language;
}
language = GSUB_get_lang_table(script, "xxxx"); /* Need to get Lang tag */ script = GSUB_get_script_table(psc->GSUB_Table, get_opentype_script(hdc,psa));
if (!language) if (script)
{ {
TRACE("Language not found\n"); language = GSUB_get_lang_table(script, "xxxx"); /* Need to get Lang tag */
return GSUB_E_NOFEATURE; if (language)
feature = GSUB_get_feature(psc->GSUB_Table, language, feat);
}
/* try in the default (latin) table */
if (!feature)
{
script = GSUB_get_script_table(psc->GSUB_Table, "latn");
if (script)
{
language = GSUB_get_lang_table(script, "xxxx"); /* Need to get Lang tag */
if (language)
feature = GSUB_get_feature(psc->GSUB_Table, language, feat);
}
}
} }
feature = GSUB_get_feature(header, language, feat);
TRACE("Feature %s located at %p\n",debugstr_an(feat,4),feature);
psc->feature_count++;
if (psc->features)
psc->features = HeapReAlloc(GetProcessHeap(), 0, psc->features, psc->feature_count * sizeof(LoadedFeature));
else
psc->features = HeapAlloc(GetProcessHeap(), 0, psc->feature_count * sizeof(LoadedFeature));
lstrcpynA(psc->features[psc->feature_count - 1].tag,feat,4);
psc->features[psc->feature_count - 1].feature = feature;
return feature;
}
static INT apply_GSUB_feature_to_glyph(HDC hdc, SCRIPT_ANALYSIS *psa, ScriptCache* psc, WORD *glyphs, INT index, INT write_dir, INT* glyph_count, const char* feat)
{
const GSUB_Feature *feature;
feature = load_GSUB_feature(hdc, psa, psc, feat);
if (!feature) if (!feature)
{
TRACE("%s feature not found\n",feat);
return GSUB_E_NOFEATURE; return GSUB_E_NOFEATURE;
}
TRACE("applying feature %s\n",feat); TRACE("applying feature %s\n",feat);
return GSUB_apply_feature(header, feature, glyphs, index, write_dir, glyph_count); return GSUB_apply_feature(psc->GSUB_Table, feature, glyphs, index, write_dir, glyph_count);
} }
static VOID *load_gsub_table(HDC hdc) static VOID *load_gsub_table(HDC hdc)
...@@ -740,47 +795,24 @@ static VOID *load_gsub_table(HDC hdc) ...@@ -740,47 +795,24 @@ static VOID *load_gsub_table(HDC hdc)
return GSUB_Table; return GSUB_Table;
} }
static int apply_GSUB_feature(HDC hdc, SCRIPT_ANALYSIS *psa, void* GSUB_Table, WORD *pwOutGlyphs, int write_dir, INT* pcGlyphs, const char* feat) static int apply_GSUB_feature(HDC hdc, SCRIPT_ANALYSIS *psa, ScriptCache* psc, WORD *pwOutGlyphs, int write_dir, INT* pcGlyphs, const char* feat)
{ {
int i; int i;
if (GSUB_Table) if (psc->GSUB_Table)
{ {
const GSUB_Header *header;
const GSUB_Script *script;
const GSUB_LangSys *language;
const GSUB_Feature *feature; const GSUB_Feature *feature;
if (!GSUB_Table) feature = load_GSUB_feature(hdc, psa, psc, feat);
return GSUB_E_NOFEATURE;
header = GSUB_Table;
script = GSUB_get_script_table(header, get_opentype_script(hdc,psa));
if (!script)
{
TRACE("Script not found\n");
return GSUB_E_NOFEATURE;
}
language = GSUB_get_lang_table(script, "xxxx");
if (!language)
{
TRACE("Language not found\n");
return GSUB_E_NOFEATURE;
}
feature = GSUB_get_feature(header, language, feat);
if (!feature) if (!feature)
{
TRACE("%s feature not found\n",feat);
return GSUB_E_NOFEATURE; return GSUB_E_NOFEATURE;
}
i = 0; i = 0;
TRACE("applying feature %s\n",feat); TRACE("applying feature %s\n",debugstr_an(feat,4));
while(i < *pcGlyphs) while(i < *pcGlyphs)
{ {
INT nextIndex; INT nextIndex;
nextIndex = GSUB_apply_feature(header, feature, pwOutGlyphs, i, write_dir, pcGlyphs); nextIndex = GSUB_apply_feature(psc->GSUB_Table, feature, pwOutGlyphs, i, write_dir, pcGlyphs);
if (nextIndex > GSUB_E_NOGLYPH) if (nextIndex > GSUB_E_NOGLYPH)
i = nextIndex; i = nextIndex;
else else
...@@ -892,7 +924,7 @@ void SHAPE_ShapeArabicGlyphs(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa, WC ...@@ -892,7 +924,7 @@ void SHAPE_ShapeArabicGlyphs(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa, WC
if (psc->GSUB_Table) if (psc->GSUB_Table)
{ {
INT nextIndex; INT nextIndex;
nextIndex = apply_GSUB_feature_to_glyph(hdc, psa, psc->GSUB_Table, pwOutGlyphs, i, dirL, pcGlyphs, contextual_features[context_shape[i]]); nextIndex = apply_GSUB_feature_to_glyph(hdc, psa, psc, pwOutGlyphs, i, dirL, pcGlyphs, contextual_features[context_shape[i]]);
if (nextIndex > GSUB_E_NOGLYPH) if (nextIndex > GSUB_E_NOGLYPH)
i = nextIndex; i = nextIndex;
shaped = (nextIndex > GSUB_E_NOGLYPH); shaped = (nextIndex > GSUB_E_NOGLYPH);
...@@ -912,13 +944,40 @@ void SHAPE_ShapeArabicGlyphs(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa, WC ...@@ -912,13 +944,40 @@ void SHAPE_ShapeArabicGlyphs(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa, WC
} }
} }
i = 0; HeapFree(GetProcessHeap(),0,context_shape);
while (arabic_GSUB_features[i] != NULL) HeapFree(GetProcessHeap(),0,context_type);
}
void SHAPE_ApplyOpenTypeFeatures(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa, WORD* pwOutGlyphs, INT* pcGlyphs, INT cMaxGlyphs, const TEXTRANGE_PROPERTIES *rpRangeProperties)
{
int i;
INT dirL;
if (!rpRangeProperties)
return;
if (!psc->GSUB_Table)
psc->GSUB_Table = load_gsub_table(hdc);
if (!psc->GSUB_Table)
return;
if (!psa->fLogicalOrder && psa->fRTL)
dirL = -1;
else
dirL = 1;
for (i = 0; i < rpRangeProperties->cotfRecords; i++)
{ {
apply_GSUB_feature(hdc, psa, psc->GSUB_Table, pwOutGlyphs, dirL, pcGlyphs, arabic_GSUB_features[i]); if (rpRangeProperties->potfRecords[i].lParameter > 0)
i++; apply_GSUB_feature(hdc, psa, psc, pwOutGlyphs, dirL, pcGlyphs, (const char*)&rpRangeProperties->potfRecords[i].tagFeature);
} }
}
HeapFree(GetProcessHeap(),0,context_shape); void SHAPE_ApplyDefaultOpentypeFeatures(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa, WORD* pwOutGlyphs, INT* pcGlyphs, INT cMaxGlyphs)
HeapFree(GetProcessHeap(),0,context_type); {
const TEXTRANGE_PROPERTIES *rpRangeProperties;
rpRangeProperties = &ShapingData[psa->eScript].defaultTextRange;
SHAPE_ApplyOpenTypeFeatures(hdc, psc, psa, pwOutGlyphs, pcGlyphs, cMaxGlyphs, rpRangeProperties);
} }
...@@ -334,6 +334,7 @@ HRESULT WINAPI ScriptFreeCache(SCRIPT_CACHE *psc) ...@@ -334,6 +334,7 @@ HRESULT WINAPI ScriptFreeCache(SCRIPT_CACHE *psc)
heap_free(((ScriptCache *)*psc)->widths[i]); heap_free(((ScriptCache *)*psc)->widths[i]);
} }
heap_free(((ScriptCache *)*psc)->GSUB_Table); heap_free(((ScriptCache *)*psc)->GSUB_Table);
heap_free(((ScriptCache *)*psc)->features);
heap_free(*psc); heap_free(*psc);
*psc = NULL; *psc = NULL;
} }
...@@ -1198,6 +1199,7 @@ HRESULT WINAPI ScriptShape(HDC hdc, SCRIPT_CACHE *psc, const WCHAR *pwcChars, ...@@ -1198,6 +1199,7 @@ HRESULT WINAPI ScriptShape(HDC hdc, SCRIPT_CACHE *psc, const WCHAR *pwcChars,
rChars[i] = chInput; rChars[i] = chInput;
} }
SHAPE_ShapeArabicGlyphs(hdc, (ScriptCache *)*psc, psa, rChars, cChars, pwOutGlyphs, pcGlyphs, cMaxGlyphs); SHAPE_ShapeArabicGlyphs(hdc, (ScriptCache *)*psc, psa, rChars, cChars, pwOutGlyphs, pcGlyphs, cMaxGlyphs);
SHAPE_ApplyDefaultOpentypeFeatures(hdc, (ScriptCache *)*psc, psa, pwOutGlyphs, pcGlyphs, cMaxGlyphs);
heap_free(rChars); heap_free(rChars);
} }
else else
......
...@@ -36,11 +36,18 @@ ...@@ -36,11 +36,18 @@
#define GLYPH_MAX 65536 #define GLYPH_MAX 65536
typedef struct { typedef struct {
char tag[4];
LPCVOID feature;
} LoadedFeature;
typedef struct {
LOGFONTW lf; LOGFONTW lf;
TEXTMETRICW tm; TEXTMETRICW tm;
WORD *glyphs[GLYPH_MAX / GLYPH_BLOCK_SIZE]; WORD *glyphs[GLYPH_MAX / GLYPH_BLOCK_SIZE];
ABC *widths[GLYPH_MAX / GLYPH_BLOCK_SIZE]; ABC *widths[GLYPH_MAX / GLYPH_BLOCK_SIZE];
LPVOID *GSUB_Table; LPVOID GSUB_Table;
INT feature_count;
LoadedFeature *features;
} ScriptCache; } ScriptCache;
#define odd(x) ((x) & 1) #define odd(x) ((x) & 1)
...@@ -51,3 +58,4 @@ BOOL BIDI_DetermineLevels( LPCWSTR lpString, INT uCount, const SCRIPT_STATE *s, ...@@ -51,3 +58,4 @@ BOOL BIDI_DetermineLevels( LPCWSTR lpString, INT uCount, const SCRIPT_STATE *s,
INT BIDI_ReorderV2lLevel(int level, int *pIndexs, const BYTE* plevel, int cch, BOOL fReverse); INT BIDI_ReorderV2lLevel(int level, int *pIndexs, const BYTE* plevel, int cch, BOOL fReverse);
INT BIDI_ReorderL2vLevel(int level, int *pIndexs, const BYTE* plevel, int cch, BOOL fReverse); INT BIDI_ReorderL2vLevel(int level, int *pIndexs, const BYTE* plevel, int cch, BOOL fReverse);
void SHAPE_ShapeArabicGlyphs(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa, WCHAR* pwcChars, INT cChars, WORD* pwOutGlyphs, INT* pcGlyphs, INT cMaxGlyphs); void SHAPE_ShapeArabicGlyphs(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa, WCHAR* pwcChars, INT cChars, WORD* pwOutGlyphs, INT* pcGlyphs, INT cMaxGlyphs);
void SHAPE_ApplyDefaultOpentypeFeatures(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa, WORD* pwOutGlyphs, INT* pcGlyphs, INT cMaxGlyphs);
...@@ -202,6 +202,20 @@ typedef struct tagGOFFSET { ...@@ -202,6 +202,20 @@ typedef struct tagGOFFSET {
} GOFFSET; } GOFFSET;
#endif #endif
typedef ULONG OPENTYPE_TAG;
typedef struct tagOPENTYPE_FEATURE_RECORD
{
OPENTYPE_TAG tagFeature;
LONG lParameter;
} OPENTYPE_FEATURE_RECORD;
typedef struct tagTEXTRANGE_PROPERTIES
{
OPENTYPE_FEATURE_RECORD *potfRecords;
INT cotfRecords;
} TEXTRANGE_PROPERTIES;
/* Function Declarations */ /* Function Declarations */
HRESULT WINAPI ScriptApplyDigitSubstitution(const SCRIPT_DIGITSUBSTITUTE* psds, HRESULT WINAPI ScriptApplyDigitSubstitution(const SCRIPT_DIGITSUBSTITUTE* psds,
......
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