Commit 409374d9 authored by Shachar Shemesh's avatar Shachar Shemesh Committed by Alexandre Julliard

Implementation of the reordering algorithm by calling ICU's reordering

functions.
parent 25bf82ba
......@@ -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 \
......
/*
* 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;
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;
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 );
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));
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 );
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;
}
......
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