[comp.windows.x] how to XDrawLines > MaxRequestSize

tomt@maui.coral.COM (Tom Tulinsky) (06/13/91)

I hadn't realized that there was a limit to the size of the lists that
the X poly requests like XDrawLines can handle until recently, when I
read Kenton Lee's article 'Behind Curtain X' in June's Unix Review.
Here's some code which will draw lines with an arbitrary length array
of points.  

A couple of pointed questions:
- If it's so simple, why can't the Xlib do it for you?
- Xlib should at least tell you the exact number of points you can
  give to each request, instead of making you divide by the size of the
  array element and subtract the header size...

/* allow for X protocol request header; 3 is supposed to be enough for now, 
 * but there's no guarantee this will not change...this is pretty sleazy 
 * anyhow
 */
#define FUDGE 10

int chunksize, ii, reqsize;

chunksize = XMaxRequestSize(gDisplay) - FUDGE;

for (ii=0; ii<numpts; ii+=chunksize-1)
{
   /* last chunk is short */
   reqsize = min(chunksize, numpts-ii);

   XDrawLines (dis, win, gc, Xpts[ii], reqsize, mode);

   printf("drawing points %d to %d\n", ii,ii+reqsize-1);
}

rws@expo.lcs.mit.EDU (Bob Scheifler) (06/13/91)

    - If it's so simple, why can't the Xlib do it for you?

R4 and later Xlib implementations do do it for you.

mouse@lightning.mcrcim.mcgill.EDU (der Mouse) (06/13/91)

> I hadn't realized that there was a limit to the size of the lists
> that the X poly requests like XDrawLines can handle until recently,
> when I read Kenton Lee's article 'Behind Curtain X' in June's Unix
> Review.  Here's some code which will draw lines with an arbitrary
> length array of points.

[code omitted; simply breaks up the list of points, calling XDrawLines
 multiple times.]

> A couple of pointed questions:
> - If it's so simple, why can't the Xlib do it for you?

Because it's *not* so simple.  Read the protocol spec for the PolyLine
request.  In particular, pay close attention to joins and the semantics
of overlapping lines.  Your "solution" produces at least the following
violations:

- Between batches of lines, the line cap is applied twice instead of
  the line join being applied once.  The protocol document says:

	The lines join correctly at all intermediate points, and if the
	first and last points coincide, the first and last lines also
	join correctly.

- When wide lines intersect, the overlapping pixesl are drawn either
  once, if all overlapping pieces fall in the same batch, or multiple
  times, if not.  The protocol document says:

	For any given line, no pixel is drawn more than once.  If thin
	(zero line-width) lines intersect, the intersecting pixels are
	drawn multiple times.  If wide lines intersect, the
	intersecting pixels are drawn only once, as though the entire
	PolyLine were a single filled shape.

The Xlib document contains similar language in both cases.

> - Xlib should at least tell you the exact number of points you can
>   give to each request, instead of making you divide by the size of
>   the array element and subtract the header size...

Arguably so, but you'd have to have a separate value for each
draw-multiple-things routine.  While this is not particularly onerous,
because there are only a few things which generate huge requests which
can't be split up (lines, rectangles, arcs, and filled polygons are all
I can see offhand), it is somewhat ugly.

> /* allow for X protocol request header; 3 is supposed to be enough
>  * for now, but there's no guarantee this will not change...
>  */
> #define FUDGE 10

It won't change without a pretty major protocol revision; the size of
the PolyLine overhead relative to the size of each line is fixed by the
encoding.

					der Mouse

			old: mcgill-vision!mouse
			new: mouse@larry.mcrcim.mcgill.edu

rws@expo.lcs.mit.EDU (Bob Scheifler) (06/13/91)

    > - If it's so simple, why can't the Xlib do it for you?
    Because it's *not* so simple.

Oops, yes, you're quite right, I mistranslated to XDrawSegments,
which Xlib does handle.

klee@wsl.dec.com (Ken Lee) (06/13/91)

In article <9106121938.AA23986@maui.coral.com>, tomt@maui.coral.COM (Tom Tulinsky) writes:
|> A couple of pointed questions:
|> - If it's so simple, why can't the Xlib do it for you?

Most (but not all) current Xlib implementations do break up the easy
cases.  You're on your own for the hard ones (e.g., XFillPolygon),
however.

-- 
Ken Lee
DEC Western Software Laboratory, Palo Alto, Calif.
Internet: klee@wsl.dec.com
uucp: uunet!decwrl!klee

pmartz@undies.dsd.es.com (Paul Martz) (06/13/91)

In article <9106121938.AA23986@maui.coral.com>, tomt@maui.coral.COM (Tom Tulinsky) writes:
> I hadn't realized that there was a limit to the size of the lists that
> the X poly requests like XDrawLines can handle until recently, when I
> read Kenton Lee's article 'Behind Curtain X' in June's Unix Review.

There are currently some mumblings in the X community about an
extension which will provide access to much larger request sizes, so
that neither the application nor the API need break apart large
requests. The extension is in the pre-proto-stages of development,
from what I've heard so far.
-- 

   -paul	pmartz@dsd.es.com
		Evans & Sutherland

tomt@maui.coral.COM (Tom Tulinsky) (06/15/91)

) 
) > I hadn't realized that there was a limit to the size of the lists
) > that the X poly requests like XDrawLines can handle until recently,
) > when I read Kenton Lee's article 'Behind Curtain X' in June's Unix
) > Review.  Here's some code which will draw lines with an arbitrary
) > length array of points.
) 
) [code omitted; simply breaks up the list of points, calling XDrawLines
)  multiple times.]
) 
) > A couple of pointed questions:
) > - If it's so simple, why can't the Xlib do it for you?
) 
) Because it's *not* so simple.  Read the protocol spec for the PolyLine
) request.  In particular, pay close attention to joins and the semantics
) of overlapping lines.  Your "solution" produces at least the following
) violations:
) . . .

Good point, correction accepted.  I believe that my for loop will
satisfy the protocol when the GC function is GXCopy because multiple
drawing of pixels does not matter in this common case.


 Coral
     * **	Tom Tulinsky                508 460-6010
  *  **		Coral Network Corporation   fax 508 481-6258
*  ** 		734 Forest St               net: tomt@coral.com
 ***		   Marlboro, MA 01752		
  **		   U S A
*********	   
NETWORKS	      

mouse@lightning.mcrcim.mcgill.EDU (der Mouse) (06/15/91)

>>> I hadn't realized that there was a limit to the size of the lists
>>> that the X poly requests like XDrawLines can handle until [...]

>>> A couple of pointed questions:
>>> - If it's so simple, why can't the Xlib do it for you?
>> Because it's *not* so simple.  Read the protocol spec for the
>> PolyLine request.  In particular, pay close attention to joins and
>> the semantics of overlapping lines.  [...]

> Good point, correction accepted.  I believe that my for loop will
> satisfy the protocol when the GC function is GXCopy because multiple
> drawing of pixels does not matter in this common case.

That's neither sufficient nor, strictly, necessary.  It's true that
overlap doesn't matter for graphics functions that don't depend on the
destination (which means GXclear, GXcopy, GXcopyInverted, and GXset;
GXcopy isn't the only one), but you also need to pay attention to the
difference between line caps and line joins.  Sometimes this doesn't
matter; in particular if the cap is CapRound and the join is JoinRound
it doesn't.  But if, say, the cap is CapButt and the join is JoinMiter,
it definitely does.

					der Mouse

			old: mcgill-vision!mouse
			new: mouse@larry.mcrcim.mcgill.edu

pinkas@almond.intel.com (Israel Pinkas) (06/18/91)

In article <9106142040.AA25972@maui.coral.com> tomt@maui.coral.COM (Tom Tulinsky) writes:

> ) > I hadn't realized that there was a limit to the size of the lists
> ) > that the X poly requests like XDrawLines can handle until recently,
> ) > when I read Kenton Lee's article 'Behind Curtain X' in June's Unix
> ) > Review.  Here's some code which will draw lines with an arbitrary
> ) > length array of points.
> ) 
> ) [code omitted; simply breaks up the list of points, calling XDrawLines
> )  multiple times.]
> ) 
> ) > A couple of pointed questions:
> ) > - If it's so simple, why can't the Xlib do it for you?
> ) 
> ) Because it's *not* so simple.  Read the protocol spec for the PolyLine
> ) request.  In particular, pay close attention to joins and the semantics
> ) of overlapping lines.  Your "solution" produces at least the following
> ) violations:
> ) . . .

> Good point, correction accepted.  I believe that my for loop will
> satisfy the protocol when the GC function is GXCopy because multiple
> drawing of pixels does not matter in this common case.

Nope.  Line joins are not the same as the line ends.  The only time your
code will work is if the line join and the line end are both round
(JoinRound and CapRound).  There is no way to get the line caps to emulate
JoinBevel or JoinMiter.  In addition, CapProjecting and CapRound modify
pixels that the various joins might not modify.  This makes things very
painful for wide lines.

Try breaking the following up:

	CapProjecting
	JoinRound
	LineWidth=10

	50,50 - 100,50 - 100,100

If you know that the lines are wide, you might be able to cheat in the
GXCopy case be drawing each segment of the line twice, creating a closed
loop.  MultiLine requests that form a closed loop are treated as a polygon,
which means that there are no caps, only joins.

Please note that breaking requests apart will not work if the line is
segmented.  The segments are supposed to start at the beginning of the line
and go to the end.  Breaking the request will cause each part to start the
pattern over.

-Israel Pinkas
 Intel Corp
--
--------------------------------------
Disclaimer: The above are my personal opinions, and in no way represent
the opinions of Intel Corporation.  In no way should the above be taken
to be a statement of Intel.

UUCP:	{amdcad,decwrl,hplabs,oliveb,pur-ee,qantel}!intelca!mipos3!st860!pinkas
ARPA:	pinkas%st860.intel.com@relay.cs.net
CSNET:	pinkas@st860.intel.com