forked from Mirrors/wine-wine
gdi32: Use usp10 to optionally generate glyphs for bidi strings.
parent
745b5fe8f1
commit
2a8958ec18
|
@ -283,46 +283,12 @@ static void resolveWhitespace(int baselevel, const WORD *pcls, BYTE *plevel, int
|
||||||
SetDeferredRun(plevel, cchrun, ich, baselevel);
|
SetDeferredRun(plevel, cchrun, ich, baselevel);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* DISPLAY OPTIONS */
|
|
||||||
/*-----------------------------------------------------------------------
|
|
||||||
Function: mirror
|
|
||||||
|
|
||||||
Crudely implements rule L4 of the Unicode Bidirectional Algorithm
|
|
||||||
Demonstrate mirrored brackets, braces and parens
|
|
||||||
|
|
||||||
|
|
||||||
Input: Array of levels
|
|
||||||
Count of characters
|
|
||||||
|
|
||||||
In/Out: Array of characters (should be array of glyph ids)
|
|
||||||
|
|
||||||
Note;
|
|
||||||
A full implementation would need to substitute mirrored glyphs even
|
|
||||||
for characters that are not paired (e.g. integral sign).
|
|
||||||
-----------------------------------------------------------------------*/
|
|
||||||
static void mirror(LPWSTR pszInput, const BYTE* plevel, int cch)
|
|
||||||
{
|
|
||||||
static int warn_once;
|
|
||||||
int i;
|
|
||||||
|
|
||||||
for (i = 0; i < cch; ++i)
|
|
||||||
{
|
|
||||||
if (!odd(plevel[i]))
|
|
||||||
continue;
|
|
||||||
/* This needs the data from http://www.unicode.org/Public/UNIDATA/BidiMirroring.txt */
|
|
||||||
if (!warn_once++)
|
|
||||||
FIXME("stub: mirroring of characters not yet implemented\n");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*------------------------------------------------------------------------
|
/*------------------------------------------------------------------------
|
||||||
Function: BidiLines
|
Function: BidiLines
|
||||||
|
|
||||||
Implements the Line-by-Line phases of the Unicode Bidi Algorithm
|
Implements the Line-by-Line phases of the Unicode Bidi Algorithm
|
||||||
|
|
||||||
Input: Count of characters
|
Input: Count of characters
|
||||||
flag whether to mirror
|
|
||||||
|
|
||||||
Inp/Out: Input text
|
Inp/Out: Input text
|
||||||
Array of character directions
|
Array of character directions
|
||||||
|
@ -330,7 +296,7 @@ static void mirror(LPWSTR pszInput, const BYTE* plevel, int cch)
|
||||||
|
|
||||||
------------------------------------------------------------------------*/
|
------------------------------------------------------------------------*/
|
||||||
static void BidiLines(int baselevel, LPWSTR pszOutLine, LPCWSTR pszLine, WORD * pclsLine,
|
static void BidiLines(int baselevel, LPWSTR pszOutLine, LPCWSTR pszLine, WORD * pclsLine,
|
||||||
BYTE * plevelLine, int cchPara, int fMirror, BOOL * pbrk)
|
BYTE * plevelLine, int cchPara, BOOL * pbrk)
|
||||||
{
|
{
|
||||||
int cchLine = 0;
|
int cchLine = 0;
|
||||||
int done = 0;
|
int done = 0;
|
||||||
|
@ -354,9 +320,6 @@ static void BidiLines(int baselevel, LPWSTR pszOutLine, LPCWSTR pszLine, WORD *
|
||||||
if (pszOutLine)
|
if (pszOutLine)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
if (fMirror)
|
|
||||||
mirror(pszOutLine, plevelLine, cchLine);
|
|
||||||
|
|
||||||
/* reorder each line in place */
|
/* reorder each line in place */
|
||||||
ScriptLayout(cchLine, plevelLine, run, NULL);
|
ScriptLayout(cchLine, plevelLine, run, NULL);
|
||||||
for (i = 0; i < cchLine; i++)
|
for (i = 0; i < cchLine; i++)
|
||||||
|
@ -377,20 +340,24 @@ static void BidiLines(int baselevel, LPWSTR pszOutLine, LPCWSTR pszLine, WORD *
|
||||||
|
|
||||||
/*************************************************************
|
/*************************************************************
|
||||||
* BIDI_Reorder
|
* BIDI_Reorder
|
||||||
|
*
|
||||||
|
* Returns TRUE if reordering was required and done.
|
||||||
*/
|
*/
|
||||||
BOOL BIDI_Reorder(
|
BOOL BIDI_Reorder(
|
||||||
|
HDC hDC, /*[in] Display DC */
|
||||||
LPCWSTR lpString, /* [in] The string for which information is to be returned */
|
LPCWSTR lpString, /* [in] The string for which information is to be returned */
|
||||||
INT uCount, /* [in] Number of WCHARs in string. */
|
INT uCount, /* [in] Number of WCHARs in string. */
|
||||||
DWORD dwFlags, /* [in] GetCharacterPlacement compatible flags specifying how to process the string */
|
DWORD dwFlags, /* [in] GetCharacterPlacement compatible flags specifying how to process the string */
|
||||||
DWORD dwWineGCP_Flags, /* [in] Wine internal flags - Force paragraph direction */
|
DWORD dwWineGCP_Flags, /* [in] Wine internal flags - Force paragraph direction */
|
||||||
LPWSTR lpOutString, /* [out] Reordered string */
|
LPWSTR lpOutString, /* [out] Reordered string */
|
||||||
INT uCountOut, /* [in] Size of output buffer */
|
INT uCountOut, /* [in] Size of output buffer */
|
||||||
UINT *lpOrder /* [out] Logical -> Visual order map */
|
UINT *lpOrder, /* [out] Logical -> Visual order map */
|
||||||
|
WORD **lpGlyphs /* [out] reordered, mirrored, shaped glyphs to display */
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
WORD *chartype;
|
WORD *chartype;
|
||||||
BYTE *levels;
|
BYTE *levels;
|
||||||
unsigned i, done;
|
unsigned i, done, glyph_i;
|
||||||
|
|
||||||
int maxItems;
|
int maxItems;
|
||||||
int nItems;
|
int nItems;
|
||||||
|
@ -398,6 +365,12 @@ BOOL BIDI_Reorder(
|
||||||
SCRIPT_STATE State;
|
SCRIPT_STATE State;
|
||||||
SCRIPT_ITEM *pItems;
|
SCRIPT_ITEM *pItems;
|
||||||
HRESULT res;
|
HRESULT res;
|
||||||
|
SCRIPT_CACHE psc = NULL;
|
||||||
|
WORD *run_glyphs = NULL;
|
||||||
|
WORD *pwLogClust = NULL;
|
||||||
|
SCRIPT_VISATTR *psva = NULL;
|
||||||
|
DWORD cMaxGlyphs = 0;
|
||||||
|
BOOL doGlyphs = TRUE;
|
||||||
|
|
||||||
TRACE("%s, %d, 0x%08x lpOutString=%p, lpOrder=%p\n",
|
TRACE("%s, %d, 0x%08x lpOutString=%p, lpOrder=%p\n",
|
||||||
debugstr_wn(lpString, uCount), uCount, dwFlags,
|
debugstr_wn(lpString, uCount), uCount, dwFlags,
|
||||||
|
@ -405,6 +378,8 @@ BOOL BIDI_Reorder(
|
||||||
|
|
||||||
memset(&Control, 0, sizeof(Control));
|
memset(&Control, 0, sizeof(Control));
|
||||||
memset(&State, 0, sizeof(State));
|
memset(&State, 0, sizeof(State));
|
||||||
|
if (lpGlyphs)
|
||||||
|
*lpGlyphs = NULL;
|
||||||
|
|
||||||
if (!(dwFlags & GCP_REORDER))
|
if (!(dwFlags & GCP_REORDER))
|
||||||
{
|
{
|
||||||
|
@ -412,7 +387,7 @@ BOOL BIDI_Reorder(
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (uCountOut < uCount)
|
if (lpOutString && uCountOut < uCount)
|
||||||
{
|
{
|
||||||
FIXME("lpOutString too small\n");
|
FIXME("lpOutString too small\n");
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
@ -471,7 +446,43 @@ BOOL BIDI_Reorder(
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (lpGlyphs)
|
||||||
|
{
|
||||||
|
cMaxGlyphs = 1.5 * uCount + 16;
|
||||||
|
run_glyphs = HeapAlloc(GetProcessHeap(),0,sizeof(WORD) * cMaxGlyphs);
|
||||||
|
if (!run_glyphs)
|
||||||
|
{
|
||||||
|
WARN("Out of memory\n");
|
||||||
|
HeapFree(GetProcessHeap(), 0, chartype);
|
||||||
|
HeapFree(GetProcessHeap(), 0, levels);
|
||||||
|
HeapFree(GetProcessHeap(), 0, pItems);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
pwLogClust = HeapAlloc(GetProcessHeap(),0,sizeof(WORD) * uCount);
|
||||||
|
if (!pwLogClust)
|
||||||
|
{
|
||||||
|
WARN("Out of memory\n");
|
||||||
|
HeapFree(GetProcessHeap(), 0, chartype);
|
||||||
|
HeapFree(GetProcessHeap(), 0, levels);
|
||||||
|
HeapFree(GetProcessHeap(), 0, pItems);
|
||||||
|
HeapFree(GetProcessHeap(), 0, run_glyphs);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
psva = HeapAlloc(GetProcessHeap(),0,sizeof(SCRIPT_VISATTR) * uCount);
|
||||||
|
if (!psva)
|
||||||
|
{
|
||||||
|
WARN("Out of memory\n");
|
||||||
|
HeapFree(GetProcessHeap(), 0, chartype);
|
||||||
|
HeapFree(GetProcessHeap(), 0, levels);
|
||||||
|
HeapFree(GetProcessHeap(), 0, pItems);
|
||||||
|
HeapFree(GetProcessHeap(), 0, run_glyphs);
|
||||||
|
HeapFree(GetProcessHeap(), 0, pwLogClust);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
done = 0;
|
done = 0;
|
||||||
|
glyph_i = 0;
|
||||||
while (done < uCount)
|
while (done < uCount)
|
||||||
{
|
{
|
||||||
unsigned j;
|
unsigned j;
|
||||||
|
@ -523,20 +534,23 @@ BOOL BIDI_Reorder(
|
||||||
res = ScriptItemize(lpString + done, i, maxItems, &Control, &State, pItems, &nItems);
|
res = ScriptItemize(lpString + done, i, maxItems, &Control, &State, pItems, &nItems);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (j = 0; j < nItems; j++)
|
if (lpOutString || lpOrder)
|
||||||
|
for (j = 0; j < nItems; j++)
|
||||||
|
{
|
||||||
|
int k;
|
||||||
|
for (k = pItems[j].iCharPos; k < pItems[j+1].iCharPos; k++)
|
||||||
|
levels[k] = pItems[j].a.s.uBidiLevel;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (lpOutString)
|
||||||
{
|
{
|
||||||
int k;
|
/* assign directional types again, but for WS, S this time */
|
||||||
for (k = pItems[j].iCharPos; k < pItems[j+1].iCharPos; k++)
|
classify(lpString + done, chartype, i);
|
||||||
levels[k] = pItems[j].a.s.uBidiLevel;
|
|
||||||
|
BidiLines(State.uBidiLevel, lpOutString + done, lpString + done,
|
||||||
|
chartype, levels, i, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* assign directional types again, but for WS, S this time */
|
|
||||||
classify(lpString + done, chartype, i);
|
|
||||||
|
|
||||||
BidiLines(State.uBidiLevel, lpOutString ? lpOutString + done : NULL, lpString + done,
|
|
||||||
chartype, levels, i, !(dwFlags & GCP_SYMSWAPOFF), 0);
|
|
||||||
|
|
||||||
|
|
||||||
if (lpOrder)
|
if (lpOrder)
|
||||||
{
|
{
|
||||||
int k, lastgood;
|
int k, lastgood;
|
||||||
|
@ -559,11 +573,77 @@ BOOL BIDI_Reorder(
|
||||||
for (k = lastgood; k < j; ++k)
|
for (k = lastgood; k < j; ++k)
|
||||||
lpOrder[done + k] = done + k;
|
lpOrder[done + k] = done + k;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (lpGlyphs && doGlyphs)
|
||||||
|
{
|
||||||
|
int j;
|
||||||
|
BYTE runOrder[maxItems];
|
||||||
|
int visOrder[maxItems];
|
||||||
|
SCRIPT_ITEM *curItem;
|
||||||
|
|
||||||
|
for (j = 0; j < nItems; j++)
|
||||||
|
runOrder[j] = pItems[j].a.s.uBidiLevel;
|
||||||
|
|
||||||
|
ScriptLayout(nItems, runOrder, NULL, visOrder);
|
||||||
|
|
||||||
|
for (j = 0; j < nItems; j++)
|
||||||
|
{
|
||||||
|
int k;
|
||||||
|
int cChars,cOutGlyphs;
|
||||||
|
curItem = &pItems[visOrder[j]];
|
||||||
|
|
||||||
|
cChars = pItems[visOrder[j]+1].iCharPos - curItem->iCharPos;
|
||||||
|
|
||||||
|
res = ScriptShape(hDC, &psc, lpString + done + curItem->iCharPos, cChars, cMaxGlyphs, &curItem->a, run_glyphs, pwLogClust, psva, &cOutGlyphs);
|
||||||
|
while (res == E_OUTOFMEMORY)
|
||||||
|
{
|
||||||
|
cMaxGlyphs *= 2;
|
||||||
|
run_glyphs = HeapReAlloc(GetProcessHeap(), 0, run_glyphs, sizeof(WORD) * cMaxGlyphs);
|
||||||
|
if (!run_glyphs)
|
||||||
|
{
|
||||||
|
WARN("Out of memory\n");
|
||||||
|
HeapFree(GetProcessHeap(), 0, chartype);
|
||||||
|
HeapFree(GetProcessHeap(), 0, levels);
|
||||||
|
HeapFree(GetProcessHeap(), 0, pItems);
|
||||||
|
HeapFree(GetProcessHeap(), 0, psva);
|
||||||
|
HeapFree(GetProcessHeap(), 0, pwLogClust);
|
||||||
|
HeapFree(GetProcessHeap(), 0, *lpGlyphs);
|
||||||
|
ScriptFreeCache(&psc);
|
||||||
|
*lpGlyphs = NULL;
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
res = ScriptShape(hDC, &psc, lpString + done + curItem->iCharPos, cChars, cMaxGlyphs, &curItem->a, run_glyphs, pwLogClust, psva, &cOutGlyphs);
|
||||||
|
}
|
||||||
|
if (res && res != USP_E_SCRIPT_NOT_IN_FONT)
|
||||||
|
{
|
||||||
|
FIXME("Unable to shape string (%x)\n",res);
|
||||||
|
j = nItems;
|
||||||
|
doGlyphs = FALSE;
|
||||||
|
HeapFree(GetProcessHeap(), 0, *lpGlyphs);
|
||||||
|
*lpGlyphs = NULL;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (*lpGlyphs)
|
||||||
|
*lpGlyphs = HeapReAlloc(GetProcessHeap(), 0, *lpGlyphs, sizeof(WORD) * (glyph_i + cOutGlyphs));
|
||||||
|
else
|
||||||
|
*lpGlyphs = HeapAlloc(GetProcessHeap(), 0, sizeof(WORD) * (glyph_i + cOutGlyphs));
|
||||||
|
for (k = 0; k < cOutGlyphs; k++)
|
||||||
|
(*lpGlyphs)[glyph_i+k] = run_glyphs[k];
|
||||||
|
glyph_i += cOutGlyphs;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
done += i;
|
done += i;
|
||||||
}
|
}
|
||||||
|
|
||||||
HeapFree(GetProcessHeap(), 0, chartype);
|
HeapFree(GetProcessHeap(), 0, chartype);
|
||||||
HeapFree(GetProcessHeap(), 0, levels);
|
HeapFree(GetProcessHeap(), 0, levels);
|
||||||
HeapFree(GetProcessHeap(), 0, pItems);
|
HeapFree(GetProcessHeap(), 0, pItems);
|
||||||
|
HeapFree(GetProcessHeap(), 0, run_glyphs);
|
||||||
|
HeapFree(GetProcessHeap(), 0, pwLogClust);
|
||||||
|
HeapFree(GetProcessHeap(), 0, psva);
|
||||||
|
ScriptFreeCache(&psc);
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1704,20 +1704,21 @@ BOOL WINAPI ExtTextOutW( HDC hdc, INT x, INT y, UINT flags,
|
||||||
{
|
{
|
||||||
reordered_str = HeapAlloc(GetProcessHeap(), 0, count*sizeof(WCHAR));
|
reordered_str = HeapAlloc(GetProcessHeap(), 0, count*sizeof(WCHAR));
|
||||||
|
|
||||||
BIDI_Reorder( str, count, GCP_REORDER,
|
BIDI_Reorder( hdc, str, count, GCP_REORDER,
|
||||||
((flags&ETO_RTLREADING)!=0 || (GetTextAlign(hdc)&TA_RTLREADING)!=0)?
|
((flags&ETO_RTLREADING)!=0 || (GetTextAlign(hdc)&TA_RTLREADING)!=0)?
|
||||||
WINE_GCPW_FORCE_RTL:WINE_GCPW_FORCE_LTR,
|
WINE_GCPW_FORCE_RTL:WINE_GCPW_FORCE_LTR,
|
||||||
reordered_str, count, NULL );
|
reordered_str, count, NULL, &glyphs );
|
||||||
|
|
||||||
flags |= ETO_IGNORELANGUAGE;
|
flags |= ETO_IGNORELANGUAGE;
|
||||||
|
if (glyphs)
|
||||||
|
flags |= ETO_GLYPH_INDEX;
|
||||||
}
|
}
|
||||||
|
else if(flags & ETO_GLYPH_INDEX)
|
||||||
|
glyphs = reordered_str;
|
||||||
|
|
||||||
TRACE("%p, %d, %d, %08x, %p, %s, %d, %p)\n", hdc, x, y, flags,
|
TRACE("%p, %d, %d, %08x, %p, %s, %d, %p)\n", hdc, x, y, flags,
|
||||||
lprect, debugstr_wn(str, count), count, lpDx);
|
lprect, debugstr_wn(str, count), count, lpDx);
|
||||||
|
|
||||||
if(flags & ETO_GLYPH_INDEX)
|
|
||||||
glyphs = reordered_str;
|
|
||||||
|
|
||||||
if(lprect)
|
if(lprect)
|
||||||
TRACE("rect: %d,%d - %d,%d\n", lprect->left, lprect->top, lprect->right,
|
TRACE("rect: %d,%d - %d,%d\n", lprect->left, lprect->top, lprect->right,
|
||||||
lprect->bottom);
|
lprect->bottom);
|
||||||
|
@ -2872,8 +2873,8 @@ GetCharacterPlacementW(
|
||||||
}
|
}
|
||||||
} else
|
} else
|
||||||
{
|
{
|
||||||
BIDI_Reorder( lpString, uCount, dwFlags, WINE_GCPW_FORCE_LTR, lpResults->lpOutString,
|
BIDI_Reorder(NULL, lpString, uCount, dwFlags, WINE_GCPW_FORCE_LTR, lpResults->lpOutString,
|
||||||
nSet, lpResults->lpOrder );
|
nSet, lpResults->lpOrder, NULL );
|
||||||
}
|
}
|
||||||
|
|
||||||
/* FIXME: Will use the placement chars */
|
/* FIXME: Will use the placement chars */
|
||||||
|
|
|
@ -355,8 +355,8 @@ typedef struct tagBITMAPOBJ
|
||||||
#define WINE_GCPW_DIR_MASK 3
|
#define WINE_GCPW_DIR_MASK 3
|
||||||
#define WINE_GCPW_LOOSE_MASK 2
|
#define WINE_GCPW_LOOSE_MASK 2
|
||||||
|
|
||||||
extern BOOL BIDI_Reorder( LPCWSTR lpString, INT uCount, DWORD dwFlags, DWORD dwWineGCP_Flags,
|
extern BOOL BIDI_Reorder( HDC hDC, LPCWSTR lpString, INT uCount, DWORD dwFlags, DWORD dwWineGCP_Flags,
|
||||||
LPWSTR lpOutString, INT uCountOut, UINT *lpOrder ) DECLSPEC_HIDDEN;
|
LPWSTR lpOutString, INT uCountOut, UINT *lpOrder, WORD **lpGlyphs ) DECLSPEC_HIDDEN;
|
||||||
|
|
||||||
/* bitmap.c */
|
/* bitmap.c */
|
||||||
extern HBITMAP BITMAP_CopyBitmap( HBITMAP hbitmap ) DECLSPEC_HIDDEN;
|
extern HBITMAP BITMAP_CopyBitmap( HBITMAP hbitmap ) DECLSPEC_HIDDEN;
|
||||||
|
|
Loading…
Reference in New Issue