usp10: Update pwLogClust with glyph transformations.

This commit is contained in:
Aric Stewart 2010-08-12 14:59:04 -05:00 committed by Alexandre Julliard
parent 4ffd3e6af6
commit f4d142e277
3 changed files with 115 additions and 34 deletions

View file

@ -38,10 +38,10 @@ WINE_DEFAULT_DEBUG_CHANNEL(uniscribe);
#define LAST_ARABIC_CHAR 0x06ff
typedef VOID (*ContextualShapingProc)(HDC, ScriptCache*, SCRIPT_ANALYSIS*,
WCHAR*, INT, WORD*, INT*, INT);
WCHAR*, INT, WORD*, INT*, INT, WORD*);
static void ContextualShape_Arabic(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa, WCHAR* pwcChars, INT cChars, WORD* pwOutGlyphs, INT* pcGlyphs, INT cMaxGlyphs);
static void ContextualShape_Syriac(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa, WCHAR* pwcChars, INT cChars, WORD* pwOutGlyphs, INT* pcGlyphs, INT cMaxGlyphs);
static void ContextualShape_Arabic(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa, WCHAR* pwcChars, INT cChars, WORD* pwOutGlyphs, INT* pcGlyphs, INT cMaxGlyphs, WORD *pwLogClust);
static void ContextualShape_Syriac(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa, WCHAR* pwcChars, INT cChars, WORD* pwOutGlyphs, INT* pcGlyphs, INT cMaxGlyphs, WORD *pwLogClust);
extern const unsigned short wine_shaping_table[];
extern const unsigned short wine_shaping_forms[LAST_ARABIC_CHAR - FIRST_ARABIC_CHAR + 1][4];
@ -810,7 +810,75 @@ static VOID *load_gsub_table(HDC hdc)
return GSUB_Table;
}
static int apply_GSUB_feature(HDC hdc, SCRIPT_ANALYSIS *psa, ScriptCache* psc, WORD *pwOutGlyphs, int write_dir, INT* pcGlyphs, const char* feat)
static void UpdateClusters(int nextIndex, int changeCount, int write_dir, int chars, WORD* pwLogClust )
{
if (changeCount == 0)
return;
else
{
int i;
int target_glyph = nextIndex - 1;
int target_index = -1;
int replacing_glyph = -1;
int changed = 0;
if (write_dir > 0)
for (i = 0; i < chars; i++)
{
if (pwLogClust[i] == target_glyph)
{
target_index = i;
break;
}
}
else
for (i = chars - 1; i >= 0; i--)
{
if (pwLogClust[i] == target_glyph)
{
target_index = i;
break;
}
}
if (target_index == -1)
{
ERR("Unable to find target glyph\n");
return;
}
if (changeCount < 0)
{
/* merge glyphs */
for(i = target_index; i < chars && i >= 0; i+=write_dir)
{
if (pwLogClust[i] == target_glyph)
continue;
if(pwLogClust[i] == replacing_glyph)
pwLogClust[i] = target_glyph;
else
{
changed--;
if (changed >= changeCount)
{
replacing_glyph = pwLogClust[i];
pwLogClust[i] = target_glyph;
}
else
break;
}
}
}
/* renumber trailing indexes*/
for(i = target_index; i < chars && i >= 0; i+=write_dir)
{
if (pwLogClust[i] != target_glyph)
pwLogClust[i] += changeCount;
}
}
}
static int apply_GSUB_feature(HDC hdc, SCRIPT_ANALYSIS *psa, ScriptCache* psc, WORD *pwOutGlyphs, int write_dir, INT* pcGlyphs, INT cChars, const char* feat, WORD *pwLogClust )
{
int i;
@ -827,9 +895,13 @@ static int apply_GSUB_feature(HDC hdc, SCRIPT_ANALYSIS *psa, ScriptCache* psc, W
while(i < *pcGlyphs)
{
INT nextIndex;
INT prevCount = *pcGlyphs;
nextIndex = GSUB_apply_feature(psc->GSUB_Table, feature, pwOutGlyphs, i, write_dir, pcGlyphs);
if (nextIndex > GSUB_E_NOGLYPH)
{
UpdateClusters(nextIndex, *pcGlyphs - prevCount, write_dir, cChars, pwLogClust);
i = nextIndex;
}
else
i++;
}
@ -896,7 +968,7 @@ static inline BOOL word_break_causing(WCHAR chr)
/*
* ContextualShape_Arabic
*/
static void ContextualShape_Arabic(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa, WCHAR* pwcChars, INT cChars, WORD* pwOutGlyphs, INT* pcGlyphs, INT cMaxGlyphs)
static void ContextualShape_Arabic(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa, WCHAR* pwcChars, INT cChars, WORD* pwOutGlyphs, INT* pcGlyphs, INT cMaxGlyphs, WORD *pwLogClust)
{
CHAR *context_type;
INT *context_shape;
@ -954,9 +1026,13 @@ static void ContextualShape_Arabic(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *p
if (psc->GSUB_Table)
{
INT nextIndex;
INT prevCount = *pcGlyphs;
nextIndex = apply_GSUB_feature_to_glyph(hdc, psa, psc, pwOutGlyphs, i, dirL, pcGlyphs, contextual_features[context_shape[i]]);
if (nextIndex > GSUB_E_NOGLYPH)
{
i = nextIndex;
UpdateClusters(nextIndex, *pcGlyphs - prevCount, dirL, cChars, pwLogClust);
}
shaped = (nextIndex > GSUB_E_NOGLYPH);
}
@ -986,7 +1062,7 @@ static void ContextualShape_Arabic(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *p
#define DALATH 0x715
#define RISH 0x72A
static void ContextualShape_Syriac(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa, WCHAR* pwcChars, INT cChars, WORD* pwOutGlyphs, INT* pcGlyphs, INT cMaxGlyphs)
static void ContextualShape_Syriac(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa, WCHAR* pwcChars, INT cChars, WORD* pwOutGlyphs, INT* pcGlyphs, INT cMaxGlyphs, WORD *pwLogClust)
{
CHAR *context_type;
INT *context_shape;
@ -1057,22 +1133,26 @@ right_join_causing(neighbour_joining_type(i,dirR,context_type,cChars,psa)))
while(i < *pcGlyphs)
{
INT nextIndex;
nextIndex = apply_GSUB_feature_to_glyph(hdc, psa, psc->GSUB_Table, pwOutGlyphs, i, dirL, pcGlyphs, contextual_features[context_shape[i]]);
INT prevCount = *pcGlyphs;
nextIndex = apply_GSUB_feature_to_glyph(hdc, psa, psc, pwOutGlyphs, i, dirL, pcGlyphs, contextual_features[context_shape[i]]);
if (nextIndex > GSUB_E_NOGLYPH)
{
UpdateClusters(nextIndex, *pcGlyphs - prevCount, dirL, cChars, pwLogClust);
i = nextIndex;
}
}
HeapFree(GetProcessHeap(),0,context_shape);
HeapFree(GetProcessHeap(),0,context_type);
}
void SHAPE_ContextualShaping(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa, WCHAR* pwcChars, INT cChars, WORD* pwOutGlyphs, INT* pcGlyphs, INT cMaxGlyphs)
void SHAPE_ContextualShaping(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa, WCHAR* pwcChars, INT cChars, WORD* pwOutGlyphs, INT* pcGlyphs, INT cMaxGlyphs, WORD *pwLogClust)
{
if (ShapingData[psa->eScript].contextProc)
ShapingData[psa->eScript].contextProc(hdc, psc, psa, pwcChars, cChars, pwOutGlyphs, pcGlyphs, cMaxGlyphs);
ShapingData[psa->eScript].contextProc(hdc, psc, psa, pwcChars, cChars, pwOutGlyphs, pcGlyphs, cMaxGlyphs, pwLogClust);
}
void SHAPE_ApplyOpenTypeFeatures(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa, WORD* pwOutGlyphs, INT* pcGlyphs, INT cMaxGlyphs, const TEXTRANGE_PROPERTIES *rpRangeProperties)
void SHAPE_ApplyOpenTypeFeatures(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa, WORD* pwOutGlyphs, INT* pcGlyphs, INT cMaxGlyphs, INT cChars, const TEXTRANGE_PROPERTIES *rpRangeProperties, WORD *pwLogClust)
{
int i;
INT dirL;
@ -1094,14 +1174,14 @@ void SHAPE_ApplyOpenTypeFeatures(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa
for (i = 0; i < rpRangeProperties->cotfRecords; i++)
{
if (rpRangeProperties->potfRecords[i].lParameter > 0)
apply_GSUB_feature(hdc, psa, psc, pwOutGlyphs, dirL, pcGlyphs, (const char*)&rpRangeProperties->potfRecords[i].tagFeature);
apply_GSUB_feature(hdc, psa, psc, pwOutGlyphs, dirL, pcGlyphs, cChars, (const char*)&rpRangeProperties->potfRecords[i].tagFeature, pwLogClust);
}
}
void SHAPE_ApplyDefaultOpentypeFeatures(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa, WORD* pwOutGlyphs, INT* pcGlyphs, INT cMaxGlyphs)
void SHAPE_ApplyDefaultOpentypeFeatures(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa, WORD* pwOutGlyphs, INT* pcGlyphs, INT cMaxGlyphs, INT cChars, WORD *pwLogClust)
{
const TEXTRANGE_PROPERTIES *rpRangeProperties;
rpRangeProperties = &ShapingData[psa->eScript].defaultTextRange;
const TEXTRANGE_PROPERTIES *rpRangeProperties;
rpRangeProperties = &ShapingData[psa->eScript].defaultTextRange;
SHAPE_ApplyOpenTypeFeatures(hdc, psc, psa, pwOutGlyphs, pcGlyphs, cMaxGlyphs, rpRangeProperties);
SHAPE_ApplyOpenTypeFeatures(hdc, psc, psa, pwOutGlyphs, pcGlyphs, cMaxGlyphs, cChars, rpRangeProperties, pwLogClust);
}

View file

@ -1176,6 +1176,22 @@ HRESULT WINAPI ScriptShape(HDC hdc, SCRIPT_CACHE *psc, const WCHAR *pwcChars,
if ((hr = init_script_cache(hdc, psc)) != S_OK) return hr;
if (!pwLogClust) return E_FAIL;
/* Initialize a SCRIPT_VISATTR and LogClust for each char in this run */
for (i = 0; i < cChars; i++)
{
int idx = i;
if (rtl) idx = cChars - 1 - i;
/* FIXME: set to better values */
psva[i].uJustification = (pwcChars[idx] == ' ') ? SCRIPT_JUSTIFY_BLANK : SCRIPT_JUSTIFY_CHARACTER;
psva[i].fClusterStart = 1;
psva[i].fDiacritic = 0;
psva[i].fZeroWidth = 0;
psva[i].fReserved = 0;
psva[i].fShapeReserved = 0;
pwLogClust[i] = idx;
}
if ((get_cache_pitch_family(psc) & TMPF_TRUETYPE) && !psa->fNoGlyphIndex)
{
WCHAR *rChars = heap_alloc(sizeof(WCHAR) * cChars);
@ -1198,8 +1214,8 @@ HRESULT WINAPI ScriptShape(HDC hdc, SCRIPT_CACHE *psc, const WCHAR *pwcChars,
}
rChars[i] = chInput;
}
SHAPE_ContextualShaping(hdc, (ScriptCache *)*psc, psa, rChars, cChars, pwOutGlyphs, pcGlyphs, cMaxGlyphs);
SHAPE_ApplyDefaultOpentypeFeatures(hdc, (ScriptCache *)*psc, psa, pwOutGlyphs, pcGlyphs, cMaxGlyphs);
SHAPE_ContextualShaping(hdc, (ScriptCache *)*psc, psa, rChars, cChars, pwOutGlyphs, pcGlyphs, cMaxGlyphs, pwLogClust);
SHAPE_ApplyDefaultOpentypeFeatures(hdc, (ScriptCache *)*psc, psa, pwOutGlyphs, pcGlyphs, cMaxGlyphs, cChars, pwLogClust);
heap_free(rChars);
}
else
@ -1214,21 +1230,6 @@ HRESULT WINAPI ScriptShape(HDC hdc, SCRIPT_CACHE *psc, const WCHAR *pwcChars,
}
}
/* set up a valid SCRIPT_VISATTR and LogClust for each char in this run */
for (i = 0; i < cChars; i++)
{
int idx = i;
if (rtl) idx = cChars - 1 - i;
/* FIXME: set to better values */
psva[i].uJustification = (pwcChars[idx] == ' ') ? SCRIPT_JUSTIFY_BLANK : SCRIPT_JUSTIFY_CHARACTER;
psva[i].fClusterStart = 1;
psva[i].fDiacritic = 0;
psva[i].fZeroWidth = 0;
psva[i].fReserved = 0;
psva[i].fShapeReserved = 0;
pwLogClust[i] = idx;
}
return S_OK;
}

View file

@ -57,5 +57,5 @@ 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_ReorderL2vLevel(int level, int *pIndexs, const BYTE* plevel, int cch, BOOL fReverse);
void SHAPE_ContextualShaping(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);
void SHAPE_ContextualShaping(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa, WCHAR* pwcChars, INT cChars, WORD* pwOutGlyphs, INT* pcGlyphs, INT cMaxGlyphs, WORD *pwLogClust);
void SHAPE_ApplyDefaultOpentypeFeatures(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa, WORD* pwOutGlyphs, INT* pcGlyphs, INT cMaxGlyphs, INT cChars, WORD *pwLogClust);