Cleaning up gegl_buffer_void

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

 



Hello. I have been reading through gegl-buffer.c and have caught a few
minor bugs that I intend to patch once I have completed my
modifications to the file.

I noticed that there is a method in gegl-buffer.c called
gegl_buffer_void () that contains a comment /* FIXME: handle z==0
correctly */. The code seemed rather messy, so I cleaned it up without
modifying the behaviour (I'm fairly certain).

Below, I provide the original code and my modified version, along with
an explanation of the changes I have made.

What I am wondering is if anyone could provide some guidance as to the
desired behaviour of this method so the FIXME can be properly
addressed.

ORIGINAL CODE:
--------------------------
static void
gegl_buffer_void (GeglBuffer *buffer)
{
 gint width       = buffer->extent.width;
 gint height      = buffer->extent.height;
 gint tile_width  = buffer->tile_storage->tile_width;
 gint tile_height = buffer->tile_storage->tile_height;
 gint bufy        = 0;

 {
   gint z;
   gint factor = 1;
   for (z = 0; z <= buffer->max_z; z++)
     {
       bufy = 0;
       while (bufy < height)
         {
           gint tiledy  = buffer->extent.y + buffer->shift_y + bufy;
           gint offsety = gegl_tile_offset (tiledy, tile_height);
           gint bufx    = 0;
           gint ty = gegl_tile_indice (tiledy / factor, tile_height);

           if (z != 0 ||  /* FIXME: handle z==0 correctly */
               ty >= buffer->min_y)
             while (bufx < width)
               {
                 gint tiledx  = buffer->extent.x + buffer->shift_x + bufx;
                 gint offsetx = gegl_tile_offset (tiledx, tile_width);

                 gint tx = gegl_tile_indice (tiledx / factor, tile_width);

                 if (z != 0 ||
                     tx >= buffer->min_x)
                 gegl_tile_source_command (GEGL_TILE_SOURCE (buffer),
                                        GEGL_TILE_VOID, tx, ty, z, NULL);

                 if (z != 0 ||
                     tx > buffer->max_x)
                   goto done_with_row;

                 bufx += (tile_width - offsetx) * factor;
               }
done_with_row:
           bufy += (tile_height - offsety) * factor;

                 if (z != 0 ||
                     ty > buffer->max_y)
                   break;
         }
       factor *= 2;
     }
 }
}
--------------------------

MODIFIED CODE:
--------------------------
static void
gegl_buffer_void (GeglBuffer *buffer)
{
  const gint width       = buffer->extent.width;
  const gint height      = buffer->extent.height;
  const gint tile_width  = buffer->tile_storage->tile_width;
  const gint tile_height = buffer->tile_storage->tile_height;
  const gint extent_plus_shift_x = buffer->extent.x + buffer->shift_x;
  const gint extent_plus_shift_y = buffer->extent.y + buffer->shift_y;

  {
    gint z;
    gint bufy   = 0;
    gint factor = 2;

    /* z == 0 */
    while (bufy < height)
      {
        gint tiledy  = extent_plus_shift_y + bufy;
        gint offsety = gegl_tile_offset (tiledy, tile_height);
        gint bufx    = 0;
        gint ty = gegl_tile_indice (tiledy, tile_height);

        if (ty >= buffer->min_y)
          while (bufx < width)
            {
              gint tiledx  = extent_plus_shift_y + bufx;
              gint offsetx = gegl_tile_offset (tiledx, tile_width);

              gint tx = gegl_tile_indice (tiledx, tile_width);

              if (tx >= buffer->min_x)
                gegl_tile_source_command (GEGL_TILE_SOURCE (buffer),
                                       GEGL_TILE_VOID, tx, ty, z, NULL);

              if (tx > buffer->max_x)
                break;

              bufx += tile_width - offsetx;
            }

            if (ty > buffer->max_y)
              break;

            bufy += tile_height - offsety;
      }

    /* z > 0 */
    if (height > 0 && width > 0) /* can height and width be negative? */
      for (z = 1; z <= buffer->max_z; z++)
        {
          gint ty = gegl_tile_indice (extent_plus_shift_y / factor,
tile_height);
          gint tx = gegl_tile_indice (extent_plus_shift_x / factor, tile_width);

          gegl_tile_source_command (GEGL_TILE_SOURCE (buffer),
                                 GEGL_TILE_VOID, tx, ty, z, NULL);

          factor *= 2;
        }
  }
}

REASONING
-------------------
I'll try to talk you through my reasoning. Several variables seemed to
go unchanged throughout the method, so they became const. In
particular, adding the extent and the shift for every loop iteration
seemed wasteful, so I created new variables for them. I unrolled the
for-loop and addressed the z ==0 case separately, since that is
apparently the case to fix. Here is how I handle the two cases:

z == 0
---------
- I removed the variable "factor" from the equations because it's
simply equal to 1. This is why I instead initialize "factor" to 2, to
get it ready for the z>0 cases.

- I also removed all the z!=0 checks, since we already know that z==0.

- The GOTO seems to do the exact same thing as BREAK would, so I
replaced it. Also, there was no reason to increment "bufy" if the
break happens, as it is reset to 0 at the beginning of the for-loop,
so I swapped the order.


z > 0
-------
- All the if-statements are automatically TRUE, so I removed them.

- The last two if-statements lead to BREAKs, meaning that the
while-loops NEVER actually loop, so I replaced the while-loops with
if-statements.

- Since the while-loops are now if-statements, bufx and bufy are never
incremented, so they are ALWAYS 0 and have therefore been removed.
Since they are 0, we only ever compare width and height to 0. Also,
since they are the only reason we compute offsety and offsetx, those
variables have been removed.

- The only line that actually seems to perform an action is
gegl_tile_source_command. So if width <= 0 it never executes, and if
height <=0, it REALLY never executes because it never even checks if
width > 0. Because of this, the entire for-loop is useless unless
they're both positive, so this check has been moved around the for-loop.




Adam Turcotte
_______________________________________________
Gegl-developer mailing list
Gegl-developer@xxxxxxxxxxxxxxxxxxxxxx
https://lists.XCF.Berkeley.EDU/mailman/listinfo/gegl-developer

[Index of Archives]     [Yosemite News]     [Yosemite Photos]     [gtk]     [GIMP Users]     [KDE]     [Gimp's Home]     [Gimp on Windows]     [Steve's Art]

  Powered by Linux