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
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;
}