Bidi B1 - ICU's GetCharacterPlacement hook

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

 



This patch needs to be applied with "patch -p1".
The code here is not cleaned up yet. There are still some duplications with the system GetCharacterPlacement. Also, order is not implemented yet.


Changelog
Shachar Shemesh <winecode@shemesh.biz>
objects/text.c

   * Call internal version of GetCharacterPlacement, that knows how to
     handle paragraph direction properly (ExtTextOutW)
   * Add parsing to ExtTextOutW of flags to find out whether this is a
     right or left paragraph.

dlls/gdi/bidi.c

   * Copied definition of the original GetCharacterPlacement. Replaced
     the BiDi code with a call to the ICU library.
   * Added extra argument to the internal GCP, to determine paragraph
     direction.

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

diff -u -r wine.ref/dlls/gdi/bidi.c wine.patch/dlls/gdi/bidi.c
--- wine.ref/dlls/gdi/bidi.c	2003-05-30 01:21:31.000000000 +0300
+++ wine.patch/dlls/gdi/bidi.c	2003-05-30 01:22:35.000000000 +0300
@@ -19,6 +19,7 @@
  * 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>
@@ -34,7 +35,7 @@
 
 WINE_DEFAULT_DEBUG_CHANNEL(bidi);
 
-BOOL BidiAvail=FALSE;
+BOOL BidiAvail = FALSE;
 
 /*************************************************************
  *    WineEngInit
@@ -43,7 +44,124 @@
  */
 BOOL WineBidiInit(void)
 {
-    return TRUE;
+    BidiAvail=TRUE;
+    return BidiAvail;
 }
 
-#endif /* HAVE_BIDI */
+DWORD Wine_GCPW(HDC hdc,        /* [in] Device context for which the rendering is to be done */
+                LPCWSTR lpString,       /* [in] The string for which information is to be returned */
+                INT uCount,     /* [in] Number of WORDS in string. */
+                INT nMaxExtent, /* [in] Maximum extent the string is to take (in HDC logical units) */
+                GCP_RESULTSW * lpResults,       /* [in/out] A pointer to a GCP_RESULTSW struct */
+                DWORD dwFlags,  /* [in] Flags specifying how to process the string */
+                DWORD dwWineGCP_Flags       /* [in] Wine internal flags - Force paragraph direction */
+    )
+{
+    DWORD ret = 0;
+    SIZE size;
+    UINT i, nSet;
+
+    TRACE("%s, %d, %d, 0x%08lx\n",
+          debugstr_wn(lpString, uCount), uCount, nMaxExtent, dwFlags);
+
+    TRACE
+        ("lStructSize=%ld, lpOutString=%p, lpOrder=%p, lpDx=%p, lpCaretPos=%p\n"
+         "lpClass=%p, lpGlyphs=%p, nGlyphs=%u, nMaxFit=%d\n",
+         lpResults->lStructSize, lpResults->lpOutString,
+         lpResults->lpOrder, lpResults->lpDx, lpResults->lpCaretPos,
+         lpResults->lpClass, lpResults->lpGlyphs, lpResults->nGlyphs,
+         lpResults->nMaxFit);
+
+    if (dwFlags & (~GCP_REORDER))
+        FIXME("flags 0x%08lx ignored\n", dwFlags);
+    if (lpResults->lpCaretPos)
+        FIXME("caret positions not implemented\n");
+    if (lpResults->lpClass)
+        FIXME("classes not implemented\n");
+
+    nSet = (UINT) uCount;
+    if (nSet > lpResults->nGlyphs)
+        nSet = lpResults->nGlyphs;
+
+    /* return number of initialized fields */
+    lpResults->nGlyphs = nSet;
+
+    if (dwFlags == 0) {
+        /* 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];
+
+        if (lpResults->lpOrder) {
+            for (i = 0; i < nSet; i++)
+                lpResults->lpOrder[i] = i;
+        }
+    }
+
+    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 0;
+        }
+
+        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( lpResults->lpOutString!=NULL ) {
+            ubidi_writeReordered( bidi, lpResults->lpOutString, uCount,
+                    (dwFlags&GCP_SYMSWAPOFF)?0:UBIDI_DO_MIRRORING, &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 0;
+        }
+    }
+
+    /* FIXME: Will use the placement chars */
+    if (lpResults->lpDx) {
+        int c;
+        for (i = 0; i < nSet; i++) {
+            if (GetCharWidth32W(hdc, lpString[i], lpString[i], &c))
+                lpResults->lpDx[i] = c;
+        }
+    }
+
+    if (lpResults->lpGlyphs)
+        GetGlyphIndicesW(hdc, lpString, nSet, lpResults->lpGlyphs, 0);
+
+    if (GetTextExtentPoint32W(hdc, lpString, uCount, &size))
+        ret = MAKELONG(size.cx, size.cy);
+
+    return ret;
+}
+
+#endif                          /* HAVE_BIDI */
+
diff -u -r wine.ref/dlls/gdi/gdibidi.h wine.patch/dlls/gdi/gdibidi.h
--- wine.ref/dlls/gdi/gdibidi.h	2003-05-30 01:21:31.000000000 +0300
+++ wine.patch/dlls/gdi/gdibidi.h	2003-05-30 01:22:41.000000000 +0300
@@ -28,15 +28,38 @@
 
 BOOL WineBidiInit(void);
 
+DWORD Wine_GCPW(HDC hdc,        /* [in] Device context for which the rendering is to be done */
+                LPCWSTR lpString,       /* [in] The string for which information is to be returned */
+                INT uCount,     /* [in] Number of WORDS in string. */
+                INT nMaxExtent, /* [in] Maximum extent the string is to take (in HDC logical units) */
+                GCP_RESULTSW * lpResults,       /* [in/out] A pointer to a GCP_RESULTSW struct */
+                DWORD dwFlags,  /* [in] Flags specifying how to process the string */
+                DWORD dwWineFlags       /* [in] Wine internal flags - Force paragraph direction */
+    );
+
 #define HAVE_BIDI 1
 
 #else /* HAVE_ICU */
 
-#define BidiAvail FALSE
-#define WineBidiInit() FALSE
+/* Replace all the functions with their return code on error */
+#define BidiAvail (FALSE)
+#define WineBidiInit() (FALSE)
+
+#define Wine_GCPW(p1,p2,p3,p4,p5,p6,p7) (0)
 
 #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 */
diff -u -r wine.ref/objects/text.c wine.patch/objects/text.c
--- wine.ref/objects/text.c	2003-03-24 21:27:53.000000000 +0200
+++ wine.patch/objects/text.c	2003-05-30 01:22:20.000000000 +0300
@@ -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,10 +160,9 @@
             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;
 
@@ -174,7 +176,9 @@
 				gcp.nGlyphs=0;
 				gcp.nMaxFit=0;
 
-				GetCharacterPlacementW(hdc, str, count, 0, &gcp, GCP_REORDER );
+				Wine_GCPW(hdc, str, count, 0, &gcp, GCP_REORDER,
+                                        ((flags&ETO_RTLREADING)!=0 || (GetTextAlign(hdc)&TA_RTLREADING)!=0)?
+                                        WINE_GCPW_FORCE_RTL:WINE_GCPW_FORCE_LTR );
 
 				ret = dc->funcs->pExtTextOut(dc->physDev,x,y,flags|ETO_IGNORELANGUAGE,
 					lprect,gcp.lpOutString,count,lpDx);

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

  Powered by Linux