Extremely preliminary BiDi patch

Shachar Shemesh wine-devel at sun.consumer.org.il
Wed Jun 12 15:00:45 CDT 2002


  Attached is an extremely preliminary BiDi patch. Here are the things 
this patch contains, and the points I would love to hear the list's 
comments about. This patch is under the LGPL only, at this stage.

Changes:

    * Fixed the heb.nls file so that LANG=he_IL will be accepted
    * Implemented a skeleton for GetFontLanguageInfo.
          o I have filled in the skeleton where I knew what to fill it
            with. I would guess that a lot of stuff is still missing.
          o I would apretiate input on the aprorpiatness of using
            GetTextCharsetInfo as the source of information.
          o I have removed the FIXME, but a lot of stuff is still
            unimplemented. I didn't quite know what to put there instead.
    * GetCharacterPlacementW - This is certanly one of the more
      overloaded functions in the Win32 set (Select object comes to mind
      as a competitor, and this one has way more execution flows
      throught it). So far, as far as I could tell, only the flow that
      matched Latin fonts was implemented. I have added some (very
      basic) reordering. I would like to hear your comments about the
      following points:
          o I followed the autodocumentation instructions. Is this at
            all still supported or required?
          o The algorythm I used is far from a good one. It still
            doesn't support right to left paragraphs, neutral boundry
            characters, and a bunch of other necessary stuff. All it
            does, at the moment, is make sure consecutive runs of one
            direction are, more or less, readable.
          o I have added a fastpath option when no work is necassary.
            When all that is supported is reordering, this may make
            sense. However, I am somewhat worried that when kerning,
            ligation, glyphing etc. are added, the fastpath will be
            meaningless. Opinions?
    * ExtTextOutW
          o I am calling GetFontLanguageInfo for each and every
            ExtTextOutW (which is a focus point for all Text rendering
            functions). What performance implications will that have?
            Don't forget that what I pay for in asking whether
            reordering is necessary, I get back in not calling
            GetCharacterPlacementW, and in not allocating a buffer. Then
            again, some Unicode fonts will suffer both allocation and no
            reordering.
          o I am calling the backend text printing function in two
            flows. One is using the allocated buffer used for
            GetCharacterPlacementW, and the other is the original (no
            point in allocating a buffer if no processing was done).
            Should I work hard to merge the two calls?
          o I am assuming that the backend driver will not perform any
            reordering. I am not sure how correct that assumption is
            under, say, KDE3 (Hetz?).

These are all the questions for the time being. I also need some 
explanation regarding procedures. Which of the following three are 
enough, on their own, to cause the patch to be integrated:

   1. Attaching it to a bug (assuming that I am the bug's owner)
   2. Sending the patch to wine-devel
   3. Sending the patch to wine-patches

Obviously, 3 is enough on it's own. Assuming I have questions, however, 
is 2 enough on its own? Is 1 at all necessary if I'm doing 2 or 3? Is 
this message off topic on wine-devel? on wine-patches?

                    Shachar

-------------- next part --------------
Index: dlls/kernel/nls/heb.nls
===================================================================
RCS file: /home/wine/wine/dlls/kernel/nls/heb.nls,v
retrieving revision 1.3
diff -u -r1.3 heb.nls
--- dlls/kernel/nls/heb.nls	19 May 2002 22:23:23 -0000	1.3
+++ dlls/kernel/nls/heb.nls	12 Jun 2002 19:34:02 -0000
@@ -128,6 +128,6 @@
 /* LOCVAL(LOCALE_FONTSIGNATURE, "") */
 
 LOCVAL(LOCALE_SISO639LANGNAME,"he")
-LOCVAL(LOCALE_SISO3166CTRYNAME,"HE")
+LOCVAL(LOCALE_SISO3166CTRYNAME,"IL")
 
 /* gregoriansk kalender */
Index: objects/font.c
===================================================================
RCS file: /home/wine/wine/objects/font.c,v
retrieving revision 1.74
diff -u -r1.74 font.c
--- objects/font.c	4 Jun 2002 01:02:52 -0000	1.74
+++ objects/font.c	12 Jun 2002 19:34:04 -0000
@@ -2098,10 +2098,48 @@
 /*************************************************************************
  *             GetFontLanguageInfo   (GDI32.@)
  */
-DWORD WINAPI GetFontLanguageInfo(HDC hdc) {
-	/* return value 0 is correct for most cases anyway */
-        FIXME("(%x):stub!\n", hdc);
-	return 0;
+DWORD WINAPI GetFontLanguageInfo(HDC hdc)
+{
+	FONTSIGNATURE fontsig;
+	static const DWORD GCP_DBCS_MASK=0x003F0000,
+		GCP_DIACRITIC_MASK=0x00000000,
+		FLI_GLYPHS_MASK=0x00000000,
+		GCP_GLYPHSHAPE_MASK=0x00000040,
+		GCP_KASHIDA_MASK=0x00000000,
+		GCP_LIGATE_MASK=0x00000000,
+		GCP_USEKERNING_MASK=0x00000000,
+		GCP_REORDER_MASK=0x00000060;
+	
+	DWORD result=0;
+	
+	GetTextCharsetInfo( hdc, &fontsig, 0 );
+	/* We detect each flag we return using a bitmask on the Codepage Bitfields */
+
+	if( (fontsig.fsCsb[0]&GCP_DBCS_MASK)!=0 )
+		result|=GCP_DBCS;
+	
+	if( (fontsig.fsCsb[0]&GCP_DIACRITIC_MASK)!=0 )
+		result|=GCP_DIACRITIC;
+	
+	if( (fontsig.fsCsb[0]&FLI_GLYPHS_MASK)!=0 )
+		result|=FLI_GLYPHS;
+	
+	if( (fontsig.fsCsb[0]&GCP_GLYPHSHAPE_MASK)!=0 )
+		result|=GCP_GLYPHSHAPE;
+	
+	if( (fontsig.fsCsb[0]&GCP_KASHIDA_MASK)!=0 )
+		result|=GCP_KASHIDA;
+	
+	if( (fontsig.fsCsb[0]&GCP_LIGATE_MASK)!=0 )
+		result|=GCP_LIGATE;
+
+	if( (fontsig.fsCsb[0]&GCP_USEKERNING_MASK)!=0 )
+		result|=GCP_USEKERNING;
+	
+	if( (fontsig.fsCsb[0]&GCP_REORDER_MASK)!=0 )
+		result|=GCP_REORDER;
+	
+	return result;
 }
 
 /*************************************************************************
@@ -2235,11 +2273,31 @@
 
 /*************************************************************************
  * GetCharacterPlacementW [GDI32.@]
+ *
+ *   Retrieve information about a string. This includes the width, reordering,
+ *   Glyphing and so on.
+ *
+ * RETURNS
+ *
+ *   The width and height of the string if succesful, 0 if failed.
+ *
+ * BUGS
+ *
+ *   All flags except GCP_REORDER are not yet implemented.
+ *   Reordering is not 100% complient to the Windows BiDi method.
+ *   Caret positioning is not yet implemented.
+ *   Classes are not yet implemented.
+ *
  */
 DWORD WINAPI
-GetCharacterPlacementW(HDC hdc, LPCWSTR lpString, INT uCount,
-			 INT nMaxExtent, GCP_RESULTSW *lpResults,
-			 DWORD dwFlags)
+GetCharacterPlacementW(
+		HDC hdc,	/* Device context for which the rendering is to be done */
+		LPCWSTR lpString,	/* The string for which information is to be returned */
+		INT uCount,	/* Number of WORDS in string. */
+		INT nMaxExtent,	/* Maximum extent the string is to take (in HDC logical units) */
+		GCP_RESULTSW *lpResults,	/* A pointer to a GCP_RESULTSW struct */
+		DWORD dwFlags	/* Flags specifying how to process the string */
+		)
 {
     DWORD ret=0;
     SIZE size;
@@ -2254,37 +2312,115 @@
 	    lpResults->lpDx, lpResults->lpCaretPos, lpResults->lpClass,
 	    lpResults->lpGlyphs, lpResults->nGlyphs, lpResults->nMaxFit);
 
-    if(dwFlags)			FIXME("flags 0x%08lx ignored\n", dwFlags);
+    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");
 
-    /* FIXME: reordering not implemented */
-    /* copy will do if the GCP_REORDER flag is not set */
-    if(lpResults->lpOutString)
-      lstrcpynW(lpResults->lpOutString, lpString, uCount);
-
-    nSet = (UINT)uCount;
-    if(nSet > lpResults->nGlyphs)
-	nSet = lpResults->nGlyphs;
-
-    /* return number of initialized fields */
-    lpResults->nGlyphs = nSet;
-
-    if(lpResults->lpOrder)
-    {
-	for(i = 0; i < nSet; i++)
-	    lpResults->lpOrder[i] = i;
-    }
-
-    if (lpResults->lpDx)
-    {
-      int c;
-      for (i = 0; i < nSet; i++)
-      {
-        if (GetCharWidth32W(hdc, lpString[i], lpString[i], &c))
-          lpResults->lpDx[i]= c;
-      }
-    }
+	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)
+			lstrcpynW(lpResults->lpOutString, lpString, uCount);
+
+		if(lpResults->lpOrder)
+		{
+			for(i = 0; i < nSet; i++)
+				lpResults->lpOrder[i] = i;
+		}
+		
+	} 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, 1, 1, -1, 1, 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 list 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
+		 */
+		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 */
+				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);
+	}
+
+	/* 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);
Index: objects/text.c
===================================================================
RCS file: /home/wine/wine/objects/text.c,v
retrieving revision 1.45
diff -u -r1.45 text.c
--- objects/text.c	31 May 2002 23:06:53 -0000	1.45
+++ objects/text.c	12 Jun 2002 19:34:04 -0000
@@ -170,9 +170,35 @@
     {
         if(PATH_IsPathOpen(dc->path))
             FIXME("called on an open path\n");
-        else if(dc->funcs->pExtTextOut)
-	    ret = dc->funcs->pExtTextOut(dc->physDev,x,y,flags,lprect,str,count,lpDx);
-	GDI_ReleaseObj( hdc );
+		else if(dc->funcs->pExtTextOut)
+		{
+			DWORD fontLangInfo=0;
+			if( !(flags&(ETO_GLYPH_INDEX|ETO_IGNORELANGUAGE)) &&
+			   ((fontLangInfo=GetFontLanguageInfo( hdc ))&(GCP_REORDER|GCP_GLYPHSHAPE)) )
+			{
+				/* 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);
+			} else
+				ret = dc->funcs->pExtTextOut(dc->physDev,x,y,flags,lprect,str,count,lpDx);
+		}
+		GDI_ReleaseObj( hdc );
     }
     return ret;
 }




More information about the wine-devel mailing list