> My guess is, that the dirty region tracking code gets messed up by 
> the Hline.

Confirmed the GGI_X_CLEAN-Macro contains a bug (I think, it is pretty
had to understand) Diff attached, please validate before I commit.

Rationale for the changes:

Old code was:

#define GGI_X_CLEAN(vis, _x, _y, _w, _h) do { \
if (priv->dirtytl.x >= _x && priv->dirtybr.x <= _x + _w-1) {            \
### If the to be cleaned region is at least as wide as the dirty region,
### it can possibly be used to clip the region down.

  if (priv->dirtytl.y >= _y && priv->dirtybr.y <= _y + _h-1) {          \
### If it completely conceals the dirty region, turn off the dirty region.
### further processing can be stopped here.
    priv->dirtytl.x = 1; priv->dirtybr.x = 0; break; }                  \

  if ((priv->dirtybr.y < _y) || (priv->dirtytl.y > _y + _h-1)) break;   \
### If the region is completely outside of the dirty region (i.e. starts
### below it or stops above it, nothing happens. Stop processing.

  if ((priv->dirtybr.y < _y + _h-1) && (priv->dirtytl.y > _y)) break;   \
### Now here is the first bug. I think this is supposed to check, if
### the cleaned reagion is completely within the dirty region, in which
### case nothing can be done (it would split the region in two
### However it does check, that the cleaned region contains the dirty
### one. Correct code would IMHO be:
++if ((priv->dirtybr.y > _y + _h-1) && (priv->dirtytl.y < _y)) break;   \
### Mind the reversed comparisions.

  if (priv->dirtytl.y < _y) priv->dirtybr.y = _y;                       \
### Now we want o check, if it overlaps at the top or the bottom.
### This is inaccurate IMHO. The line y is cleared, so we can set y-1.
++if (priv->dirtytl.y < _y) priv->dirtybr.y = _y-1;

  if (priv->dirtybr.y > _y + _h-1) priv->dirtytl.y = _y + _h-1;         \
### Same here. y+h-1 is the last line that is cleaned, so we can start
### one line below, i.e.
++if (priv->dirtybr.y > _y + _h-1) priv->dirtytl.y = _y + _h;

  break;                                                                \
### is redundant here. We are in while(0), so we will autobreak anyway.

} else if (priv->dirtytl.x >= _x && priv->dirtybr.x <= _x + _w-1) {     \
### Uh - ouch. Next bug I think. I suppose this section is supposed 
### to check the same but snipping off at left and right. For that to
### work, we should check the y parameters. I.e.
++ } else if (priv->dirtytl.y >= _y && priv->dirtybr.y <= _y + _h-1) {     \

  if (priv->dirtytl.x >= _x && priv->dirtybr.x <= _x + _w-1) {          \
    priv->dirtytl.x = 1; priv->dirtybr.x = 0; break; }                  \
### This is redundant, as the check in the area above would have catched it.

  if ((priv->dirtybr.x < _x) || (priv->dirtytl.x > _x + _w-1)) break;   \
### Check cleans left/right of dirty region.

  if ((priv->dirtybr.x < _x + _w-1) && (priv->dirtytl.x > _x)) break;   \
# Check for completely contained region. Wrong like above.
++if ((priv->dirtybr.x > _x + _w-1) && (priv->dirtytl.x < _x)) break;

  if (priv->dirtytl.x < _x) priv->dirtybr.x = _x;                       \
  if (priv->dirtybr.x > _x + _w-1) priv->dirtytl.x = _x + _w-1;         \
# Comments like above leading to
++if (priv->dirtytl.x < _x) priv->dirtybr.x = _x-1;                     \
++if (priv->dirtybr.x > _x + _w-1) priv->dirtytl.x = _x + _w;           \

  break;                                                                \
# redundant.
}} while (0)


I spent quite a while thinking this code through, and suppose I got it
right. I am not quite sure about the last two ifs in each chain. I think one
could use greater/less-or-equal in the comparisions as well, thus correctly
handling regions that just touch the borders.


I have tested these changes with my application, and it fixes the problems
I reported.

Could you please go over the code and my comments and have a look, if the
fix is right? That stuff is pretty complex to think into, so I am not
absolutely positive I didn't mis anything.

If a few people confirm my thought, I will commit.


CU, Andy

-- 
= Andreas Beck                    |  Email :  <[EMAIL PROTECTED]>             =
? bla
Index: include/ggi/display/x.h
===================================================================
RCS file: /cvsroot/ggi/ggi-core/libggi/include/ggi/display/x.h,v
retrieving revision 1.3
diff -u -r1.3 x.h
--- include/ggi/display/x.h     12 Jun 2002 03:53:59 -0000      1.3
+++ include/ggi/display/x.h     14 Dec 2002 15:01:25 -0000
@@ -208,18 +208,14 @@
   if (priv->dirtytl.y >= _y && priv->dirtybr.y <= _y + _h-1) {         \
     priv->dirtytl.x = 1; priv->dirtybr.x = 0; break; }                 \
   if ((priv->dirtybr.y < _y) || (priv->dirtytl.y > _y + _h-1)) break;  \
-  if ((priv->dirtybr.y < _y + _h-1) && (priv->dirtytl.y > _y)) break;  \
-  if (priv->dirtytl.y < _y) priv->dirtybr.y = _y;                      \
-  if (priv->dirtybr.y > _y + _h-1) priv->dirtytl.y = _y + _h-1;                \
-  break;                                                               \
-} else if (priv->dirtytl.x >= _x && priv->dirtybr.x <= _x + _w-1) {    \
-  if (priv->dirtytl.x >= _x && priv->dirtybr.x <= _x + _w-1) {         \
-    priv->dirtytl.x = 1; priv->dirtybr.x = 0; break; }                 \
+  if ((priv->dirtybr.y > _y + _h-1) && (priv->dirtytl.y < _y)) break;  \
+  if (priv->dirtytl.y < _y) priv->dirtybr.y = _y-1;                    \
+  if (priv->dirtybr.y > _y + _h-1) priv->dirtytl.y = _y + _h;          \
+} else if (priv->dirtytl.y >= _y && priv->dirtybr.y <= _y + _h-1) {    \
   if ((priv->dirtybr.x < _x) || (priv->dirtytl.x > _x + _w-1)) break;  \
-  if ((priv->dirtybr.x < _x + _w-1) && (priv->dirtytl.x > _x)) break;  \
-  if (priv->dirtytl.x < _x) priv->dirtybr.x = _x;                      \
-  if (priv->dirtybr.x > _x + _w-1) priv->dirtytl.x = _x + _w-1;                \
-  break;                                                               \
+  if ((priv->dirtybr.x > _x + _w-1) && (priv->dirtytl.x < _x)) break;  \
+  if (priv->dirtytl.x < _x) priv->dirtybr.x = _x-1;                    \
+  if (priv->dirtybr.x > _x + _w-1) priv->dirtytl.x = _x + _w;          \
 }} while (0)
 #define GGI_X_SYNC(_vis) XFlush(GGIX_PRIV(_vis)->disp);
 #define GGI_X_MAYBE_SYNC(_vis) \

Reply via email to