Bidi B patch

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Originally sent in three seperate emails, now resent, united and happy.

Changelog:
Shachar Shemesh <winecode@shemesh.biz>

   * dlls/gdi/bidi.c, dlls/gdi/gdibidi.h and dlls/gdi/Makefile.in
         o Implementation of the reordering algorithm by calling ICU's
           reordering functions.
         o Adding the new files to the makefile
   * objects/gdiobj.c
         o Initializing the new subsystem.
   * objects/test.c and objects/font.c
         o Calling the Bidi infrastructure from bidi.c instead of
           implementing small, insufficient parts of the BiDi algorithm
           inline.
   * include/config.h.in
         o Added HAVE_ICU and HAVE_UNICODE_UBIDI_H to the config header
           file (configure is already checking for these, and will
           correctly generate them).

Enjoy!

--
Shachar Shemesh
Open Source integration consultant
Home page & resume - http://www.shemesh.biz/

Index: dlls/gdi/Makefile.in
===================================================================
RCS file: /home/sun/sources/cvs/wine/dlls/gdi/Makefile.in,v
retrieving revision 1.52
diff -u -r1.52 Makefile.in
--- dlls/gdi/Makefile.in	20 Jun 2003 21:38:10 -0000	1.52
+++ dlls/gdi/Makefile.in	21 Jun 2003 05:31:18 -0000
@@ -41,6 +41,7 @@
 	$(TOPOBJDIR)/objects/pen.c \
 	$(TOPOBJDIR)/objects/region.c \
 	$(TOPOBJDIR)/objects/text.c \
+	bidi.c \
 	driver.c \
 	enhmfdrv/bitblt.c \
 	enhmfdrv/dc.c \
Index: include/config.h.in
===================================================================
RCS file: /home/sun/sources/cvs/wine/include/config.h.in,v
retrieving revision 1.157
diff -u -r1.157 config.h.in
--- include/config.h.in	20 Jun 2003 23:26:56 -0000	1.157
+++ include/config.h.in	21 Jun 2003 05:24:57 -0000
@@ -77,6 +77,12 @@
 /* Define to 1 if you have the `fpclass' function. */
 #undef HAVE_FPCLASS
 
+/* Define if the ICU library is available for static linking */
+#undef HAVE_ICU
+
+/* Define if the bidi header is available for ICU */
+#undef HAVE_UNICODE_UBIDI_H
+
 /* Define if FreeType 2 is installed */
 #undef HAVE_FREETYPE
 
Index: objects/font.c
===================================================================
RCS file: /home/sun/sources/cvs/wine/objects/font.c,v
retrieving revision 1.100
diff -u -r1.100 font.c
--- objects/font.c	23 Jun 2003 20:51:06 -0000	1.100
+++ objects/font.c	24 Jun 2003 18:45:25 -0000
@@ -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
@@ -19,18 +20,19 @@
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  */
 
-#include "config.h"
-#include "wine/port.h"
+#include <config.h>
+#include <wine/port.h>
 
 #include <stdlib.h>
 #include <string.h>
 #include <assert.h>
-#include "winerror.h"
-#include "winnls.h"
-#include "wownt32.h"
-#include "gdi.h"
-#include "wine/unicode.h"
-#include "wine/debug.h"
+#include <winerror.h>
+#include <winnls.h>
+#include <wownt32.h>
+#include <gdi.h>
+#include <wine/unicode.h>
+#include <wine/debug.h>
+#include "gdibidi.h"
 
 WINE_DEFAULT_DEBUG_CHANNEL(font);
 WINE_DECLARE_DEBUG_CHANNEL(gdi);
@@ -1989,105 +1991,22 @@
 	/* 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);
+            Wine_BiDi_reorder( lpString, uCount, dwFlags, WINE_GCPW_FORCE_LTR, lpResults->lpOutString,
+                    nSet, lpResults->lpOrder );
 	}
 
 	/* FIXME: Will use the placement chars */
Index: objects/gdiobj.c
===================================================================
RCS file: /home/sun/sources/cvs/wine/objects/gdiobj.c,v
retrieving revision 1.87
diff -u -r1.87 gdiobj.c
--- objects/gdiobj.c	21 May 2003 18:28:49 -0000	1.87
+++ objects/gdiobj.c	14 Jun 2003 14:44:31 -0000
@@ -34,6 +34,7 @@
 #include "palette.h"
 #include "gdi.h"
 #include "wine/debug.h"
+#include "gdibidi.h"
 
 WINE_DEFAULT_DEBUG_CHANNEL(gdi);
 
@@ -627,6 +628,8 @@
     if (hkey) RegCloseKey( hkey );
 
     WineEngInit();
+
+    WineBidiInit();
 
     return TRUE;
 }
Index: objects/text.c
===================================================================
RCS file: /home/sun/sources/cvs/wine/objects/text.c,v
retrieving revision 1.52
diff -u -r1.52 text.c
--- objects/text.c	23 Jun 2003 20:51:06 -0000	1.52
+++ objects/text.c	24 Jun 2003 18:45:25 -0000
@@ -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
@@ -20,14 +21,16 @@
 
 #include <string.h>
 
-#include "windef.h"
-#include "wingdi.h"
-#include "wine/winuser16.h"
-#include "winbase.h"
-#include "winerror.h"
-#include "gdi.h"
-#include "wine/debug.h"
-#include "winnls.h"
+#include <windef.h>
+#include <wingdi.h>
+#include <wine/winuser16.h>
+#include <winbase.h>
+#include <winerror.h>
+#include <gdi.h>
+#include <wine/debug.h>
+#include <winnls.h>
+
+#include "gdibidi.h"
 
 WINE_DEFAULT_DEBUG_CHANNEL(text);
 
@@ -157,28 +160,20 @@
             FIXME("called on an open path\n");
 		else if(dc->funcs->pExtTextOut)
 		{
-			if( !(flags&(ETO_GLYPH_INDEX|ETO_IGNORELANGUAGE)) )
+			if( !(flags&(ETO_GLYPH_INDEX|ETO_IGNORELANGUAGE)) && BidiAvail )
 			{
-				/* The caller did not specify that language processing was already done,
-				 * and the font idetifies iteself as requiring language processing.
+				/* The caller did not specify that language processing was already done.
 				 */
-				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;
+                                LPWSTR lpReorderedString=HeapAlloc(GetProcessHeap(), 0, count*sizeof(WCHAR));
 
-				GetCharacterPlacementW(hdc, str, count, 0, &gcp, GCP_REORDER );
+				Wine_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,gcp.lpOutString,count,lpDx);
-				HeapFree(GetProcessHeap(), 0, gcp.lpOutString);
+					lprect,lpReorderedString,count,lpDx);
+				HeapFree(GetProcessHeap(), 0, lpReorderedString);
 			} else
 				ret = dc->funcs->pExtTextOut(dc->physDev,x,y,flags,lprect,str,count,lpDx);
 		}
--- /dev/null	2003-01-06 20:21:43.000000000 +0200
+++ dlls/gdi/bidi.c	2003-05-31 15:52:20.000000000 +0300
@@ -0,0 +1,120 @@
+
+/*
+ * 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 <winbase.h>
+#include <wingdi.h>
+#include <wine/debug.h>
+#include <wine/library.h>
+#include <dlfcn.h>
+
+/* As this is not an exported include, it's important not to turn it into a <>
+ * quotes 
+ */
+#include "gdibidi.h"
+
+#if HAVE_BIDI
+
+#include <unicode/ubidi.h>
+
+WINE_DEFAULT_DEBUG_CHANNEL(bidi);
+
+BOOL BidiAvail = FALSE;
+
+/*************************************************************
+ *    WineEngInit
+ *
+ * Initialize FreeType library and create a list of available faces
+ */
+BOOL WineBidiInit(void)
+{
+    BidiAvail=TRUE;
+    return BidiAvail;
+}
+
+BOOL Wine_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 */
+    )
+{
+    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;
+}
+
+#endif                          /* HAVE_BIDI */
+
--- /dev/null	2003-01-06 20:21:43.000000000 +0200
+++ dlls/gdi/gdibidi.h	2003-06-14 17:38:42.000000000 +0300
@@ -0,0 +1,65 @@
+/*
+ * GDI BiDi definitions
+ *
+ * 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
+ */
+#ifndef __WINE_GDI_BIDI_H
+#define __WINE_GDI_BIDI_H
+
+#include <config.h>
+
+#if HAVE_ICU
+
+extern BOOL BidiAvail;
+
+BOOL WineBidiInit(void);
+
+BOOL Wine_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 */
+    );
+
+#define HAVE_BIDI 1
+
+#else /* HAVE_ICU */
+
+/* Replace all the functions with their return code on error */
+#define BidiAvail (FALSE)
+#define WineBidiInit() (FALSE)
+#define Wine_BiDi_reorder(p1,p2,p3,p4,p5,p6,p7) (FALSE)
+
+#undef HAVE_BIDI
+
+#endif /* HAVE_ICU */
+
+/* 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
+
+#endif /* __WINE_GDI_BIDI_H */

[Index of Archives]     [Gimp for Windows]     [Red Hat]     [Samba]     [Yosemite Camping]     [Graphics Cards]     [Wine Home]

  Powered by Linux