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

Bug#181815: xlibs: Problem with XRenderCompositeText16 in Render extension



Package: xlibs
Version: 4.2.1-5
Severity: important
Tags: patch upstream sid

Hello Branden,

Mozilla Xft users (including myself) have been experiencing strange
disappearing text problem, as explained in Mozilla Bugzilla "Bug
#187377: Characters disappear with xft if fallback triggered twice on
the same line" and related bug reports.  See:

    http://bugzilla.mozilla.org/show_bug.cgi?id=187377

Most bug reporters use Debian or FreeBSD.  This problem does not happen
on Red Hat 8.0.  I guess not many people know the fix yet.

The details of this bug came up on the XFree86 fonts mailing list just
two days ago:

  ITO Tsuyoshi says:

    While performing some test about Mozilla Bugzilla Bug #187377 [1], I
    found that XRenderCompositeText16 function in Render extension does
    not draw text as intended when multiple glyphsets are involved in one
    call.

    According to the code of the Render extension on X server side,
    XRenderCompositeText16 should send a "glyphset-switch sign" (a glyph
    element with len = 0xff) to the X server when it encounters a glyph
    element whose glyphset is different from the one of the previous glyph
    element.  However, it actually sends the glyphset-switch sign when it
    encounters a glyph element whose glyphset is different from the one of
    the _first_ glyph element.  XRenderCompositeText{8,32} probably have
    the same problem.

  and provided a patch.  Keith Packard replied:

    Your analysis is quite correct.  A fix solving this issue was placed in
    XFree86 CVS on 2002-8-31.

That patch was also included in Red Hat 8.0, probably days before it
was final:

  * Sun Sep 01 2002 Mike A. Harris <mharris@redhat.com> 4.2.0-70
  ...
  - Added XFree86-4.2.0-libXrender-bugfix.patch to fix showstopper (#73243)

That patch (still identical to the one in current XFree86-4.3 CVS) is
attached.  Please include this in your next upload.  (Feel free to change
the "094_" number.  :-)

Thanks!

Anthony

-- System Information:
Debian Release: testing/unstable
Architecture: i386
Kernel: Linux anthony 2.4.21-pre4-ac1 #1 Mon Feb 3 03:11:48 HKT 2003 i686

Versions of packages xlibs depends on:
ii  libc6                         2.3.1-12   GNU C Library: Shared libraries an
ii  libfreetype6                  2.1.3-10   FreeType 2 font engine, shared lib
ii  xfree86-common                4.2.1-5    X Window System (XFree86) infrastr

-- no debconf information

Index: lib/Xrender/Glyph.c
===================================================================
RCS file: /cvs/xc/lib/Xrender/Glyph.c,v
retrieving revision 1.7
retrieving revision 1.10
diff -u -p -r1.7 -r1.10
--- xc/lib/Xrender/Glyph.c	2001/12/27 01:16:00	1.7
+++ xc/lib/Xrender/Glyph.c	2002/08/31 18:15:45	1.10
@@ -125,6 +125,7 @@ XRenderFreeGlyphs (Display   *dpy,
     GetReq(RenderFreeGlyphs, req);
     req->reqType = info->codes->major_opcode;
     req->renderReqType = X_RenderFreeGlyphs;
+    req->glyphset = glyphset;
     len = nglyphs;
     SetReqLen(req, len, len);
     len <<= 2;
@@ -390,6 +391,7 @@ XRenderCompositeText8 (Display			    *dp
 {
     XExtDisplayInfo		*info = XRenderFindDisplay (dpy);
     xRenderCompositeGlyphs8Req	*req;
+    GlyphSet			glyphset;
     long			len;
     long			elen;
     xGlyphElt			*elt;
@@ -419,10 +421,17 @@ XRenderCompositeText8 (Display			    *dp
      */
     len = 0;
     
+    glyphset = elts[0].glyphset;
     for (i = 0; i < nelt; i++)
     {
-	if (elts[i].glyphset != req->glyphset)
+	/*
+	 * Check for glyphset change
+	 */
+	if (elts[i].glyphset != glyphset)
+	{
+	    glyphset = elts[i].glyphset;
 	    len += (SIZEOF (xGlyphElt) + 4) >> 2;
+	}
 	nchars = elts[i].nchars;
 	/*
 	 * xGlyphElt must be aligned on a 32-bit boundary; this is
@@ -434,26 +443,24 @@ XRenderCompositeText8 (Display			    *dp
     }
     
     req->length += len;
-    /* 
-     * If the entire request does not fit into the remaining space in the
-     * buffer, flush the buffer first.
-     */
 
-    if (dpy->bufptr + (len << 2) > dpy->bufmax)
-    	_XFlush (dpy);
-
+    /*
+     * Send the glyphs
+     */
+    glyphset = elts[0].glyphset;
     for (i = 0; i < nelt; i++)
     {
 	/*
 	 * Switch glyphsets
 	 */
-	if (elts[i].glyphset != req->glyphset)
+	if (elts[i].glyphset != glyphset)
 	{
+	    glyphset = elts[i].glyphset;
 	    BufAlloc (xGlyphElt *, elt, SIZEOF (xGlyphElt));
 	    elt->len = 0xff;
 	    elt->deltax = 0;
 	    elt->deltay = 0;
-	    Data32(dpy, &elts[i].glyphset, 4);
+	    Data32(dpy, &glyphset, 4);
 	}
 	nchars = elts[i].nchars;
 	xDst = elts[i].xOff;
@@ -461,15 +468,17 @@ XRenderCompositeText8 (Display			    *dp
 	chars = elts[i].chars;
 	while (nchars)
 	{
+	    int this_chars = nchars > MAX_8 ? MAX_8 : nchars;
+
 	    BufAlloc (xGlyphElt *, elt, SIZEOF(xGlyphElt))
-	    elt->len = nchars > MAX_8 ? MAX_8 : nchars;
+	    elt->len = this_chars;
 	    elt->deltax = xDst;
 	    elt->deltay = yDst;
 	    xDst = 0;
 	    yDst = 0;
-	    Data (dpy, chars, elt->len);
-	    nchars -= elt->len;
-	    chars += elt->len;
+	    Data (dpy, chars, this_chars);
+	    nchars -= this_chars;
+	    chars += this_chars;
 	}
     }
     
@@ -492,6 +501,7 @@ XRenderCompositeText16 (Display			    *d
 {
     XExtDisplayInfo		*info = XRenderFindDisplay (dpy);
     xRenderCompositeGlyphs16Req	*req;
+    GlyphSet			glyphset;
     long			len;
     long			elen;
     xGlyphElt			*elt;
@@ -521,10 +531,17 @@ XRenderCompositeText16 (Display			    *d
      */
     len = 0;
     
+    glyphset = elts[0].glyphset;
     for (i = 0; i < nelt; i++)
     {
-	if (elts[i].glyphset != req->glyphset)
+	/*
+	 * Check for glyphset change
+	 */
+	if (elts[i].glyphset != glyphset)
+	{
+	    glyphset = elts[i].glyphset;
 	    len += (SIZEOF (xGlyphElt) + 4) >> 2;
+	}
 	nchars = elts[i].nchars;
 	/*
 	 * xGlyphElt must be aligned on a 32-bit boundary; this is
@@ -536,26 +553,21 @@ XRenderCompositeText16 (Display			    *d
     }
     
     req->length += len;
-    /* 
-     * If the entire request does not fit into the remaining space in the
-     * buffer, flush the buffer first.
-     */
 
-    if (dpy->bufptr + (len << 2) > dpy->bufmax)
-    	_XFlush (dpy);
-
+    glyphset = elts[0].glyphset;
     for (i = 0; i < nelt; i++)
     {
 	/*
 	 * Switch glyphsets
 	 */
-	if (elts[i].glyphset != req->glyphset)
+	if (elts[i].glyphset != glyphset)
 	{
+	    glyphset = elts[i].glyphset;
 	    BufAlloc (xGlyphElt *, elt, SIZEOF (xGlyphElt));
 	    elt->len = 0xff;
 	    elt->deltax = 0;
 	    elt->deltay = 0;
-	    Data32(dpy, &elts[i].glyphset, 4);
+	    Data32(dpy, &glyphset, 4);
 	}
 	nchars = elts[i].nchars;
 	xDst = elts[i].xOff;
@@ -563,15 +575,18 @@ XRenderCompositeText16 (Display			    *d
 	chars = elts[i].chars;
 	while (nchars)
 	{
+	    int this_chars = nchars > MAX_16 ? MAX_16 : nchars;
+	    int this_bytes = this_chars * 2;
+    
 	    BufAlloc (xGlyphElt *, elt, SIZEOF(xGlyphElt))
-	    elt->len = nchars > MAX_16 ? MAX_16 : nchars;
+	    elt->len = this_chars;
 	    elt->deltax = xDst;
 	    elt->deltay = yDst;
 	    xDst = 0;
 	    yDst = 0;
-	    Data16 (dpy, chars, elt->len * 2);
-	    nchars -= elt->len;
-	    chars += elt->len;
+	    Data16 (dpy, chars, this_bytes);
+	    nchars -= this_chars;
+	    chars += this_chars;
 	}
     }
     
@@ -594,6 +609,7 @@ XRenderCompositeText32 (Display			    *d
 {
     XExtDisplayInfo		*info = XRenderFindDisplay (dpy);
     xRenderCompositeGlyphs32Req	*req;
+    GlyphSet			glyphset;
     long			len;
     long			elen;
     xGlyphElt			*elt;
@@ -607,6 +623,7 @@ XRenderCompositeText32 (Display			    *d
     RenderSimpleCheckExtension (dpy, info);
     LockDisplay(dpy);
 
+    
     GetReq(RenderCompositeGlyphs32, req);
     req->reqType = info->codes->major_opcode;
     req->renderReqType = X_RenderCompositeGlyphs32;
@@ -623,36 +640,38 @@ XRenderCompositeText32 (Display			    *d
      */
     len = 0;
     
+    glyphset = elts[0].glyphset;
     for (i = 0; i < nelt; i++)
     {
-	if (elts[i].glyphset != req->glyphset)
+	/*
+	 * Check for glyphset change
+	 */
+	if (elts[i].glyphset != glyphset)
+	{
+	    glyphset = elts[i].glyphset;
 	    len += (SIZEOF (xGlyphElt) + 4) >> 2;
+	}
 	nchars = elts[i].nchars;
 	elen = SIZEOF(xGlyphElt) * ((nchars + MAX_32) / MAX_32) + nchars *4;
 	len += (elen + 3) >> 2;
     }
     
     req->length += len;
-    /* 
-     * If the entire request does not fit into the remaining space in the
-     * buffer, flush the buffer first.
-     */
-
-    if (dpy->bufptr + (len << 2) > dpy->bufmax)
-    	_XFlush (dpy);
 
+    glyphset = elts[0].glyphset;
     for (i = 0; i < nelt; i++)
     {
 	/*
 	 * Switch glyphsets
 	 */
-	if (elts[i].glyphset != req->glyphset)
+	if (elts[i].glyphset != glyphset)
 	{
+	    glyphset = elts[i].glyphset;
 	    BufAlloc (xGlyphElt *, elt, SIZEOF (xGlyphElt));
 	    elt->len = 0xff;
 	    elt->deltax = 0;
 	    elt->deltay = 0;
-	    Data32(dpy, &elts[i].glyphset, 4);
+	    Data32(dpy, &glyphset, 4);
 	}
 	nchars = elts[i].nchars;
 	xDst = elts[i].xOff;
@@ -660,15 +679,17 @@ XRenderCompositeText32 (Display			    *d
 	chars = elts[i].chars;
 	while (nchars)
 	{
+	    int this_chars = nchars > MAX_32 ? MAX_32 : nchars;
+	    int this_bytes = this_chars * 4;
 	    BufAlloc (xGlyphElt *, elt, SIZEOF(xGlyphElt))
-	    elt->len = nchars > MAX_32 ? MAX_32 : nchars;
+	    elt->len = this_chars;
 	    elt->deltax = xDst;
 	    elt->deltay = yDst;
 	    xDst = 0;
 	    yDst = 0;
-	    Data32 (dpy, chars, elt->len * 4);
-	    nchars -= elt->len;
-	    chars += elt->len;
+	    Data32 (dpy, chars, this_bytes);
+	    nchars -= this_chars;
+	    chars += this_chars;
 	}
     }
     

Reply to: