mirror of
https://github.com/reactos/wine.git
synced 2024-11-28 22:20:26 +00:00
gdi32: Use usp10 to optionally generate glyphs for bidi strings.
This commit is contained in:
parent
745b5fe8f1
commit
2a8958ec18
@ -283,46 +283,12 @@ static void resolveWhitespace(int baselevel, const WORD *pcls, BYTE *plevel, int
|
||||
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
|
||||
|
||||
Implements the Line-by-Line phases of the Unicode Bidi Algorithm
|
||||
|
||||
Input: Count of characters
|
||||
flag whether to mirror
|
||||
|
||||
Inp/Out: Input text
|
||||
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,
|
||||
BYTE * plevelLine, int cchPara, int fMirror, BOOL * pbrk)
|
||||
BYTE * plevelLine, int cchPara, BOOL * pbrk)
|
||||
{
|
||||
int cchLine = 0;
|
||||
int done = 0;
|
||||
@ -354,9 +320,6 @@ static void BidiLines(int baselevel, LPWSTR pszOutLine, LPCWSTR pszLine, WORD *
|
||||
if (pszOutLine)
|
||||
{
|
||||
int i;
|
||||
if (fMirror)
|
||||
mirror(pszOutLine, plevelLine, cchLine);
|
||||
|
||||
/* reorder each line in place */
|
||||
ScriptLayout(cchLine, plevelLine, run, NULL);
|
||||
for (i = 0; i < cchLine; i++)
|
||||
@ -377,20 +340,24 @@ static void BidiLines(int baselevel, LPWSTR pszOutLine, LPCWSTR pszLine, WORD *
|
||||
|
||||
/*************************************************************
|
||||
* BIDI_Reorder
|
||||
*
|
||||
* Returns TRUE if reordering was required and done.
|
||||
*/
|
||||
BOOL BIDI_Reorder(
|
||||
HDC hDC, /*[in] Display DC */
|
||||
LPCWSTR lpString, /* [in] The string for which information is to be returned */
|
||||
INT uCount, /* [in] Number of WCHARs in string. */
|
||||
DWORD dwFlags, /* [in] GetCharacterPlacement compatible flags specifying how to process the string */
|
||||
DWORD dwWineGCP_Flags, /* [in] Wine internal flags - Force paragraph direction */
|
||||
LPWSTR lpOutString, /* [out] Reordered string */
|
||||
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;
|
||||
BYTE *levels;
|
||||
unsigned i, done;
|
||||
unsigned i, done, glyph_i;
|
||||
|
||||
int maxItems;
|
||||
int nItems;
|
||||
@ -398,6 +365,12 @@ BOOL BIDI_Reorder(
|
||||
SCRIPT_STATE State;
|
||||
SCRIPT_ITEM *pItems;
|
||||
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",
|
||||
debugstr_wn(lpString, uCount), uCount, dwFlags,
|
||||
@ -405,6 +378,8 @@ BOOL BIDI_Reorder(
|
||||
|
||||
memset(&Control, 0, sizeof(Control));
|
||||
memset(&State, 0, sizeof(State));
|
||||
if (lpGlyphs)
|
||||
*lpGlyphs = NULL;
|
||||
|
||||
if (!(dwFlags & GCP_REORDER))
|
||||
{
|
||||
@ -412,7 +387,7 @@ BOOL BIDI_Reorder(
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (uCountOut < uCount)
|
||||
if (lpOutString && uCountOut < uCount)
|
||||
{
|
||||
FIXME("lpOutString too small\n");
|
||||
return FALSE;
|
||||
@ -471,7 +446,43 @@ BOOL BIDI_Reorder(
|
||||
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;
|
||||
glyph_i = 0;
|
||||
while (done < uCount)
|
||||
{
|
||||
unsigned j;
|
||||
@ -523,20 +534,23 @@ BOOL BIDI_Reorder(
|
||||
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;
|
||||
for (k = pItems[j].iCharPos; k < pItems[j+1].iCharPos; k++)
|
||||
levels[k] = pItems[j].a.s.uBidiLevel;
|
||||
/* assign directional types again, but for WS, S this time */
|
||||
classify(lpString + done, chartype, i);
|
||||
|
||||
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)
|
||||
{
|
||||
int k, lastgood;
|
||||
@ -559,11 +573,77 @@ BOOL BIDI_Reorder(
|
||||
for (k = lastgood; k < j; ++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;
|
||||
}
|
||||
|
||||
HeapFree(GetProcessHeap(), 0, chartype);
|
||||
HeapFree(GetProcessHeap(), 0, levels);
|
||||
HeapFree(GetProcessHeap(), 0, pItems);
|
||||
HeapFree(GetProcessHeap(), 0, run_glyphs);
|
||||
HeapFree(GetProcessHeap(), 0, pwLogClust);
|
||||
HeapFree(GetProcessHeap(), 0, psva);
|
||||
ScriptFreeCache(&psc);
|
||||
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));
|
||||
|
||||
BIDI_Reorder( str, count, GCP_REORDER,
|
||||
BIDI_Reorder( hdc, str, count, GCP_REORDER,
|
||||
((flags&ETO_RTLREADING)!=0 || (GetTextAlign(hdc)&TA_RTLREADING)!=0)?
|
||||
WINE_GCPW_FORCE_RTL:WINE_GCPW_FORCE_LTR,
|
||||
reordered_str, count, NULL );
|
||||
reordered_str, count, NULL, &glyphs );
|
||||
|
||||
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,
|
||||
lprect, debugstr_wn(str, count), count, lpDx);
|
||||
|
||||
if(flags & ETO_GLYPH_INDEX)
|
||||
glyphs = reordered_str;
|
||||
|
||||
if(lprect)
|
||||
TRACE("rect: %d,%d - %d,%d\n", lprect->left, lprect->top, lprect->right,
|
||||
lprect->bottom);
|
||||
@ -2872,8 +2873,8 @@ GetCharacterPlacementW(
|
||||
}
|
||||
} else
|
||||
{
|
||||
BIDI_Reorder( lpString, uCount, dwFlags, WINE_GCPW_FORCE_LTR, lpResults->lpOutString,
|
||||
nSet, lpResults->lpOrder );
|
||||
BIDI_Reorder(NULL, lpString, uCount, dwFlags, WINE_GCPW_FORCE_LTR, lpResults->lpOutString,
|
||||
nSet, lpResults->lpOrder, NULL );
|
||||
}
|
||||
|
||||
/* FIXME: Will use the placement chars */
|
||||
|
@ -355,8 +355,8 @@ typedef struct tagBITMAPOBJ
|
||||
#define WINE_GCPW_DIR_MASK 3
|
||||
#define WINE_GCPW_LOOSE_MASK 2
|
||||
|
||||
extern BOOL BIDI_Reorder( LPCWSTR lpString, INT uCount, DWORD dwFlags, DWORD dwWineGCP_Flags,
|
||||
LPWSTR lpOutString, INT uCountOut, UINT *lpOrder ) DECLSPEC_HIDDEN;
|
||||
extern BOOL BIDI_Reorder( HDC hDC, LPCWSTR lpString, INT uCount, DWORD dwFlags, DWORD dwWineGCP_Flags,
|
||||
LPWSTR lpOutString, INT uCountOut, UINT *lpOrder, WORD **lpGlyphs ) DECLSPEC_HIDDEN;
|
||||
|
||||
/* bitmap.c */
|
||||
extern HBITMAP BITMAP_CopyBitmap( HBITMAP hbitmap ) DECLSPEC_HIDDEN;
|
||||
|
Loading…
Reference in New Issue
Block a user