mirror of
https://github.com/reactos/wine.git
synced 2025-04-01 07:31:34 +00:00
Implementation of the reordering algorithm by calling ICU's reordering
functions.
This commit is contained in:
parent
25bf82ba64
commit
409374d914
@ -41,6 +41,7 @@ C_SRCS = \
|
||||
$(TOPOBJDIR)/objects/pen.c \
|
||||
$(TOPOBJDIR)/objects/region.c \
|
||||
$(TOPOBJDIR)/objects/text.c \
|
||||
bidi.c \
|
||||
driver.c \
|
||||
enhmfdrv/bitblt.c \
|
||||
enhmfdrv/dc.c \
|
||||
|
114
dlls/gdi/bidi.c
Normal file
114
dlls/gdi/bidi.c
Normal file
@ -0,0 +1,114 @@
|
||||
|
||||
/*
|
||||
* GDI BiDirectional handling
|
||||
*
|
||||
* Copyright 2003 Shachar Shemesh
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#ifdef HAVE_UNICODE_UBIDI_H
|
||||
#include <unicode/ubidi.h>
|
||||
#endif
|
||||
|
||||
#include "winbase.h"
|
||||
#include "wingdi.h"
|
||||
#include "wine/debug.h"
|
||||
#include "gdi.h"
|
||||
|
||||
WINE_DEFAULT_DEBUG_CHANNEL(bidi);
|
||||
|
||||
#if HAVE_ICU
|
||||
BOOL BidiAvail = TRUE;
|
||||
#else
|
||||
BOOL BidiAvail = FALSE;
|
||||
#endif
|
||||
|
||||
|
||||
/*************************************************************
|
||||
* BIDI_Reorder
|
||||
*/
|
||||
BOOL BIDI_Reorder(
|
||||
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 */
|
||||
)
|
||||
{
|
||||
#ifdef HAVE_ICU
|
||||
TRACE("%s, %d, 0x%08lx\n",
|
||||
debugstr_wn(lpString, uCount), uCount, dwFlags);
|
||||
|
||||
TRACE("lpOutString=%p, lpOrder=%p", lpOutString, lpOrder );
|
||||
|
||||
if ((dwFlags & GCP_REORDER) != 0) {
|
||||
UBiDi *bidi;
|
||||
UErrorCode err=0;
|
||||
UBiDiLevel level;
|
||||
|
||||
bidi=ubidi_open();
|
||||
if( bidi==NULL ) {
|
||||
WARN("Failed to allocate structure\n");
|
||||
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
switch( dwWineGCP_Flags&WINE_GCPW_DIR_MASK )
|
||||
{
|
||||
case WINE_GCPW_FORCE_LTR:
|
||||
level=0;
|
||||
break;
|
||||
case WINE_GCPW_FORCE_RTL:
|
||||
level=1;
|
||||
break;
|
||||
case WINE_GCPW_LOOSE_LTR:
|
||||
level=UBIDI_DEFAULT_LTR;
|
||||
break;
|
||||
case WINE_GCPW_LOOSE_RTL:
|
||||
level=UBIDI_DEFAULT_RTL;
|
||||
break;
|
||||
}
|
||||
|
||||
ubidi_setPara( bidi, lpString, uCount, level, NULL, &err );
|
||||
if( lpOutString!=NULL ) {
|
||||
ubidi_writeReordered( bidi, lpOutString, uCount,
|
||||
(dwFlags&GCP_SYMSWAPOFF)?0:UBIDI_DO_MIRRORING, &err );
|
||||
}
|
||||
|
||||
if( lpOrder!=NULL ) {
|
||||
ubidi_getLogicalMap( bidi, lpOrder, &err );
|
||||
}
|
||||
|
||||
ubidi_close( bidi );
|
||||
|
||||
if( U_FAILURE(err) ) {
|
||||
FIXME("ICU Library return error code %d.\n", err );
|
||||
FIXME("Please report this error to wine-devel@winehq.org so we can place "
|
||||
"descriptive Windows error codes here\n");
|
||||
SetLastError(ERROR_INVALID_LEVEL); /* This error is cryptic enough not to mean anything, I hope */
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
return TRUE;
|
||||
#else /* HAVE_ICU */
|
||||
return FALSE;
|
||||
#endif /* HAVE_ICU */
|
||||
}
|
@ -464,6 +464,22 @@ extern DC * DC_GetDCUpdate( HDC hdc );
|
||||
extern void DC_InitDC( DC * dc );
|
||||
extern void DC_UpdateXforms( DC * dc );
|
||||
|
||||
/* bidi.c */
|
||||
|
||||
/* Wine_GCPW Flags */
|
||||
/* Directionality -
|
||||
* LOOSE means that the paragraph dir is only set if there is no strong character.
|
||||
* FORCE means override the characters in the paragraph.
|
||||
*/
|
||||
#define WINE_GCPW_FORCE_LTR 0
|
||||
#define WINE_GCPW_FORCE_RTL 1
|
||||
#define WINE_GCPW_LOOSE_LTR 2
|
||||
#define WINE_GCPW_LOOSE_RTL 3
|
||||
#define WINE_GCPW_DIR_MASK 3
|
||||
extern BOOL BIDI_Reorder( LPCWSTR lpString, INT uCount, DWORD dwFlags, DWORD dwWineGCP_Flags,
|
||||
LPWSTR lpOutString, INT uCountOut, UINT *lpOrder );
|
||||
extern BOOL BidiAvail;
|
||||
|
||||
/* clipping.c */
|
||||
extern void CLIPPING_UpdateGCRegion( DC * dc );
|
||||
|
||||
|
@ -3,6 +3,7 @@
|
||||
*
|
||||
* Copyright 1993 Alexandre Julliard
|
||||
* 1997 Alex Korobka
|
||||
* Copyright 2002,2003 Shachar Shemesh
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
@ -1989,105 +1990,22 @@ GetCharacterPlacementW(
|
||||
/* return number of initialized fields */
|
||||
lpResults->nGlyphs = nSet;
|
||||
|
||||
if(dwFlags==0)
|
||||
if((dwFlags&GCP_REORDER)==0 || !BidiAvail)
|
||||
{
|
||||
/* Treat the case where no special handling was requested in a fastpath way */
|
||||
/* copy will do if the GCP_REORDER flag is not set */
|
||||
if(lpResults->lpOutString)
|
||||
for(i=0; i<nSet && lpString[i]!=0; ++i )
|
||||
lpResults->lpOutString[i]=lpString[i];
|
||||
strncpyW( lpResults->lpOutString, lpString, nSet );
|
||||
|
||||
if(lpResults->lpOrder)
|
||||
{
|
||||
for(i = 0; i < nSet; i++)
|
||||
lpResults->lpOrder[i] = i;
|
||||
}
|
||||
}
|
||||
|
||||
if((dwFlags&GCP_REORDER)!=0)
|
||||
} else
|
||||
{
|
||||
WORD *pwCharType;
|
||||
int run_end;
|
||||
/* Keep a static table that translates the C2 types to something meaningful */
|
||||
/* 1 - left to right
|
||||
* -1 - right to left
|
||||
* 0 - neutral
|
||||
*/
|
||||
static const int chardir[]={ 0, 1, -1, 1, 0, 0, -1, 0, 0, 0, 0, 0 };
|
||||
|
||||
WARN("The BiDi algorythm doesn't conform to Windows' yet\n");
|
||||
if( (pwCharType=HeapAlloc(GetProcessHeap(), 0, uCount * sizeof(WORD)))==NULL )
|
||||
{
|
||||
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Fill in the order array with directionality values */
|
||||
GetStringTypeW(CT_CTYPE2, lpString, uCount, pwCharType);
|
||||
|
||||
/* The complete and correct (at least according to MS) BiDi algorythm is not
|
||||
* yet implemented here. Instead, we just make sure that consecutive runs of
|
||||
* the same direction (or neutral) are ordered correctly. We also assign Neutrals
|
||||
* that are between runs of opposing directions the base (ok, always LTR) dir.
|
||||
* While this is a LONG way from a BiDi algorithm, it does produce more or less
|
||||
* readable results.
|
||||
*/
|
||||
for( i=0; i<uCount; i+=run_end )
|
||||
{
|
||||
for( run_end=1; i+run_end<uCount &&
|
||||
(chardir[pwCharType[i+run_end]]==chardir[pwCharType[i]] ||
|
||||
chardir[pwCharType[i+run_end]]==0); ++run_end )
|
||||
;
|
||||
|
||||
if( chardir[pwCharType[i]]==1 || chardir[pwCharType[i]]==0 )
|
||||
{
|
||||
/* A LTR run */
|
||||
if(lpResults->lpOutString)
|
||||
{
|
||||
int j;
|
||||
for( j=0; j<run_end; j++ )
|
||||
{
|
||||
lpResults->lpOutString[i+j]=lpString[i+j];
|
||||
}
|
||||
}
|
||||
|
||||
if(lpResults->lpOrder)
|
||||
{
|
||||
int j;
|
||||
for( j=0; j<run_end; j++ )
|
||||
lpResults->lpOrder[i+j] = i+j;
|
||||
}
|
||||
} else
|
||||
{
|
||||
/* A RTL run */
|
||||
|
||||
/* Since, at this stage, the paragraph context is always LTR,
|
||||
* remove any neutrals from the end of this run.
|
||||
*/
|
||||
if( chardir[pwCharType[i]]!=0 )
|
||||
while( chardir[pwCharType[i+run_end-1]]==0 )
|
||||
--run_end;
|
||||
|
||||
if(lpResults->lpOutString)
|
||||
{
|
||||
int j;
|
||||
for( j=0; j<run_end; j++ )
|
||||
{
|
||||
lpResults->lpOutString[i+j]=lpString[i+run_end-j-1];
|
||||
}
|
||||
}
|
||||
|
||||
if(lpResults->lpOrder)
|
||||
{
|
||||
int j;
|
||||
for( j=0; j<run_end; j++ )
|
||||
lpResults->lpOrder[i+j] = i+run_end-j-1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
HeapFree(GetProcessHeap(), 0, pwCharType);
|
||||
BIDI_Reorder( lpString, uCount, dwFlags, WINE_GCPW_FORCE_LTR, lpResults->lpOutString,
|
||||
nSet, lpResults->lpOrder );
|
||||
}
|
||||
|
||||
/* FIXME: Will use the placement chars */
|
||||
|
@ -2,6 +2,7 @@
|
||||
* text functions
|
||||
*
|
||||
* Copyright 1993, 1994 Alexandre Julliard
|
||||
* Copyright 2003 Shachar Shemesh
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
@ -155,34 +156,26 @@ BOOL WINAPI ExtTextOutW( HDC hdc, INT x, INT y, UINT flags,
|
||||
{
|
||||
if(PATH_IsPathOpen(dc->path))
|
||||
FIXME("called on an open path\n");
|
||||
else if(dc->funcs->pExtTextOut)
|
||||
{
|
||||
if( !(flags&(ETO_GLYPH_INDEX|ETO_IGNORELANGUAGE)) )
|
||||
{
|
||||
/* The caller did not specify that language processing was already done,
|
||||
* and the font idetifies iteself as requiring language processing.
|
||||
*/
|
||||
GCP_RESULTSW gcp;
|
||||
else if(dc->funcs->pExtTextOut)
|
||||
{
|
||||
if( !(flags&(ETO_GLYPH_INDEX|ETO_IGNORELANGUAGE)) && BidiAvail )
|
||||
{
|
||||
/* The caller did not specify that language processing was already done.
|
||||
*/
|
||||
LPWSTR lpReorderedString=HeapAlloc(GetProcessHeap(), 0, count*sizeof(WCHAR));
|
||||
|
||||
gcp.lStructSize=sizeof(gcp);
|
||||
gcp.lpOutString=HeapAlloc(GetProcessHeap(), 0, count*sizeof(WCHAR));
|
||||
gcp.lpOrder=NULL;
|
||||
gcp.lpDx=NULL;
|
||||
gcp.lpCaretPos=NULL;
|
||||
gcp.lpClass=NULL;
|
||||
gcp.lpGlyphs=NULL;
|
||||
gcp.nGlyphs=0;
|
||||
gcp.nMaxFit=0;
|
||||
BIDI_Reorder( str, count, GCP_REORDER,
|
||||
((flags&ETO_RTLREADING)!=0 || (GetTextAlign(hdc)&TA_RTLREADING)!=0)?
|
||||
WINE_GCPW_FORCE_RTL:WINE_GCPW_FORCE_LTR,
|
||||
lpReorderedString, count, NULL );
|
||||
|
||||
GetCharacterPlacementW(hdc, str, count, 0, &gcp, GCP_REORDER );
|
||||
|
||||
ret = dc->funcs->pExtTextOut(dc->physDev,x,y,flags|ETO_IGNORELANGUAGE,
|
||||
lprect,gcp.lpOutString,count,lpDx);
|
||||
HeapFree(GetProcessHeap(), 0, gcp.lpOutString);
|
||||
} else
|
||||
ret = dc->funcs->pExtTextOut(dc->physDev,x,y,flags,lprect,str,count,lpDx);
|
||||
}
|
||||
GDI_ReleaseObj( hdc );
|
||||
ret = dc->funcs->pExtTextOut(dc->physDev,x,y,flags|ETO_IGNORELANGUAGE,
|
||||
lprect,lpReorderedString,count,lpDx);
|
||||
HeapFree(GetProcessHeap(), 0, lpReorderedString);
|
||||
} else
|
||||
ret = dc->funcs->pExtTextOut(dc->physDev,x,y,flags,lprect,str,count,lpDx);
|
||||
}
|
||||
GDI_ReleaseObj( hdc );
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user