home *** CD-ROM | disk | FTP | other *** search
/ PC Pro 2002 April / pcpro0402.iso / essentials / graphics / Gimp / gimp-src-20001226.exe / src / gimp / libgimp / gimppixelrgn.c < prev    next >
Encoding:
C/C++ Source or Header  |  2000-06-06  |  17.2 KB  |  745 lines

  1. /* LIBGIMP - The GIMP Library
  2.  * Copyright (C) 1995-1997 Peter Mattis and Spencer Kimball
  3.  *
  4.  * gimppixelrgn.c
  5.  *
  6.  * This library is free software; you can redistribute it and/or
  7.  * modify it under the terms of the GNU Lesser General Public
  8.  * License as published by the Free Software Foundation; either
  9.  * version 2 of the License, or (at your option) any later version.
  10.  *
  11.  * This library is distributed in the hope that it will be useful,
  12.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  14.  * Library General Public License for more details.
  15.  *
  16.  * You should have received a copy of the GNU Lesser General Public
  17.  * License along with this library; if not, write to the
  18.  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
  19.  * Boston, MA 02111-1307, USA.
  20.  */
  21.  
  22. /* Experimental: comment-out the following #define if a memcpy() call is
  23.    slower than compiler-optimized memory copies for transfers of approx.
  24.    64-256 bytes.
  25.  
  26.    FYI this #define is a win on Linux486/libc5.  Unbenchmarked on other
  27.    architectures.  --adam
  28. */
  29.  
  30. #define MEMCPY_IS_NICE
  31.  
  32. #ifdef MEMCPY_IS_NICE
  33. #include <string.h>
  34. #endif
  35.  
  36. #include <stdarg.h>
  37. #include "gimp.h"
  38.  
  39.  
  40. #define TILE_WIDTH     _gimp_tile_width
  41. #define TILE_HEIGHT    _gimp_tile_height
  42. #define BOUNDS(a,x,y)  ((a < x) ? x : ((a > y) ? y : a))
  43.  
  44.  
  45. typedef struct _GimpPixelRgnHolder    GimpPixelRgnHolder;
  46. typedef struct _GimpPixelRgnIterator  GimpPixelRgnIterator;
  47.  
  48. struct _GimpPixelRgnHolder
  49. {
  50.   GimpPixelRgn *pr;
  51.   guchar       *original_data;
  52.   gint          startx;
  53.   gint          starty;
  54.   gint          count;
  55. };
  56.  
  57. struct _GimpPixelRgnIterator
  58. {
  59.   GSList *pixel_regions;
  60.   gint    region_width;
  61.   gint    region_height;
  62.   gint    portion_width;
  63.   gint    portion_height;
  64.   gint    process_count;
  65. };
  66.  
  67.  
  68. static gint     gimp_get_portion_width    (GimpPixelRgnIterator *pri);
  69. static gint     gimp_get_portion_height   (GimpPixelRgnIterator *pri);
  70. static gpointer gimp_pixel_rgns_configure (GimpPixelRgnIterator *pri);
  71. static void     gimp_pixel_rgn_configure  (GimpPixelRgnHolder   *prh,
  72.                        GimpPixelRgnIterator *pri);
  73.  
  74.  
  75. extern gint _gimp_tile_width;
  76. extern gint _gimp_tile_height;
  77.  
  78.  
  79. void
  80. gimp_pixel_rgn_init (GimpPixelRgn *pr,
  81.              GimpDrawable *drawable,
  82.              gint          x,
  83.              gint          y,
  84.              gint          width,
  85.              gint          height,
  86.              gboolean      dirty,
  87.              gboolean      shadow)
  88. {
  89.   pr->data      = NULL;
  90.   pr->drawable  = drawable;
  91.   pr->bpp       = drawable->bpp;
  92.   pr->rowstride = pr->bpp * TILE_WIDTH;
  93.   pr->x         = x;
  94.   pr->y         = y;
  95.   pr->w         = width;
  96.   pr->h         = height;
  97.   pr->dirty     = dirty;
  98.   pr->shadow    = shadow;
  99. }
  100.  
  101. void
  102. gimp_pixel_rgn_resize (GimpPixelRgn *pr,
  103.                gint          x,
  104.                gint          y,
  105.                gint          width,
  106.                gint          height)
  107. {
  108.   if (pr->data != NULL)
  109.     pr->data += ((y - pr->y) * pr->rowstride +
  110.          (x - pr->x) * pr->bpp);
  111.  
  112.   pr->x = x;
  113.   pr->y = y;
  114.   pr->w = width;
  115.   pr->h = height;
  116. }
  117.  
  118. void
  119. gimp_pixel_rgn_get_pixel (GimpPixelRgn *pr,
  120.               guchar      *buf,
  121.               gint         x,
  122.               gint         y)
  123. {
  124.   GimpTile *tile;
  125.   guchar   *tile_data;
  126.   gint      b;
  127.  
  128.   tile = gimp_drawable_get_tile2 (pr->drawable, pr->shadow, x, y);
  129.   gimp_tile_ref (tile);
  130.  
  131.   tile_data = tile->data + tile->bpp * (tile->ewidth * (y % TILE_HEIGHT) + (x % TILE_WIDTH));
  132.  
  133.   for (b = 0; b < tile->bpp; b++)
  134.     *buf++ = *tile_data++;
  135.  
  136.   gimp_tile_unref (tile, FALSE);
  137. }
  138.  
  139. void
  140. gimp_pixel_rgn_get_row (GimpPixelRgn *pr,
  141.             guchar       *buf,
  142.             gint          x,
  143.             gint          y,
  144.             gint          width)
  145. {
  146.   GimpTile *tile;
  147.   guchar   *tile_data;
  148.   gint bpp, inc, min;
  149.   gint end;
  150.   gint boundary;
  151. #ifndef MEMCPY_IS_NICE
  152.   gint b;
  153. #endif
  154.  
  155.   end = x + width;
  156.  
  157.   while (x < end)
  158.     {
  159.       tile = gimp_drawable_get_tile2 (pr->drawable, pr->shadow, x, y);
  160.       gimp_tile_ref (tile);
  161.  
  162.       tile_data = tile->data + (int)tile->bpp * (int)(tile->ewidth * (int)(y % TILE_HEIGHT) + (x % TILE_WIDTH));
  163.       boundary = x + (tile->ewidth - (x % TILE_WIDTH));
  164.       bpp = tile->bpp;
  165.  
  166. #ifdef MEMCPY_IS_NICE
  167.       memcpy ((void *)buf,
  168.           (const void *)tile_data,
  169.           inc = (bpp * 
  170.              ( (min = MIN (end, boundary)) -x) ) );
  171.       x = min;;
  172.       buf += inc;
  173. #else
  174.       for ( ; x < end && x < boundary; x++)
  175.     {
  176.       for (b = 0; b < tile->bpp; b++)
  177.         *buf++ = tile_data[b];
  178.       tile_data += bpp;
  179.     }
  180. #endif /* MEMCPY_IS_NICE */
  181.  
  182.       gimp_tile_unref (tile, FALSE);
  183.     }
  184. }
  185.  
  186. void
  187. gimp_pixel_rgn_get_col (GimpPixelRgn *pr,
  188.             guchar       *buf,
  189.             gint          x,
  190.             gint          y,
  191.             gint          height)
  192. {
  193.   GimpTile *tile;
  194.   guchar   *tile_data;
  195.   gint inc;
  196.   gint end;
  197.   gint boundary;
  198.   gint b;
  199.  
  200.   end = y + height;
  201.  
  202.   while (y < end)
  203.     {
  204.       tile = gimp_drawable_get_tile2 (pr->drawable, pr->shadow, x, y);
  205.       gimp_tile_ref (tile);
  206.  
  207.       tile_data = tile->data + tile->bpp * (tile->ewidth * (y % TILE_HEIGHT) + (x % TILE_WIDTH));
  208.       boundary = y + (tile->eheight - (y % TILE_HEIGHT));
  209.       inc = tile->bpp * tile->ewidth;
  210.  
  211.       for ( ; y < end && y < boundary; y++)
  212.     {
  213.       for (b = 0; b < tile->bpp; b++)
  214.         *buf++ = tile_data[b];
  215.       tile_data += inc;
  216.     }
  217.  
  218.       gimp_tile_unref (tile, FALSE);
  219.     }
  220. }
  221.  
  222. void
  223. gimp_pixel_rgn_get_rect (GimpPixelRgn *pr,
  224.              guchar       *buf,
  225.              gint          x,
  226.              gint          y,
  227.              gint          width,
  228.              gint          height)
  229. {
  230.   GimpTile *tile;
  231.   guchar   *src;
  232.   guchar   *dest;
  233.   gulong    bufstride;
  234.   gint xstart, ystart;
  235.   gint xend, yend;
  236.   gint xboundary;
  237.   gint yboundary;
  238.   gint xstep, ystep;
  239.   gint ty, bpp;
  240. #ifndef MEMCPY_IS_NICE
  241.   gint b, tx;
  242. #endif
  243.  
  244.   bpp = pr->bpp;
  245.   bufstride = bpp * width;
  246.  
  247.   xstart = x;
  248.   ystart = y;
  249.   xend = x + width;
  250.   yend = y + height;
  251.   ystep = 0;
  252.  
  253.   while (y < yend)
  254.     {
  255.       x = xstart;
  256.       while (x < xend)
  257.     {
  258.       tile = gimp_drawable_get_tile2 (pr->drawable, pr->shadow, x, y);
  259.       gimp_tile_ref (tile);
  260.  
  261.       xstep = tile->ewidth - (x % TILE_WIDTH);
  262.       ystep = tile->eheight - (y % TILE_HEIGHT);
  263.       xboundary = x + xstep;
  264.       yboundary = y + ystep;
  265.       xboundary = MIN (xboundary, xend);
  266.       yboundary = MIN (yboundary, yend);
  267.  
  268.       for (ty = y; ty < yboundary; ty++)
  269.         {
  270.           src = tile->data + tile->bpp * (tile->ewidth * (ty % TILE_HEIGHT) + (x % TILE_WIDTH));
  271.           dest = buf + bufstride * (ty - ystart) + bpp * (x - xstart);
  272.  
  273. #ifdef MEMCPY_IS_NICE
  274.           memcpy ((void *)dest, (const void *)src, (xboundary-x)*bpp);  
  275. #else   
  276.           for (tx = x; tx < xboundary; tx++)
  277.         {
  278.           for (b = 0; b < bpp; b++)
  279.             *dest++ = *src++;
  280.         }
  281. #endif /* MEMCPY_IS_NICE */
  282.  
  283.         }
  284.  
  285.       gimp_tile_unref (tile, FALSE);
  286.       x += xstep;
  287.     }
  288.  
  289.       y += ystep;
  290.     }
  291. }
  292.  
  293. void
  294. gimp_pixel_rgn_set_pixel (GimpPixelRgn *pr,
  295.               guchar       *buf,
  296.               gint          x,
  297.               gint          y)
  298. {
  299.   GimpTile *tile;
  300.   guchar   *tile_data;
  301.   gint b;
  302.  
  303.   tile = gimp_drawable_get_tile2 (pr->drawable, pr->shadow, x, y);
  304.   gimp_tile_ref (tile);
  305.  
  306.   tile_data = tile->data + tile->bpp * (tile->ewidth * (y % TILE_HEIGHT) + (x % TILE_WIDTH));
  307.  
  308.   for (b = 0; b < tile->bpp; b++)
  309.     *tile_data++ = *buf++;
  310.  
  311.   gimp_tile_unref (tile, TRUE);
  312. }
  313.  
  314. void
  315. gimp_pixel_rgn_set_row (GimpPixelRgn *pr,
  316.             guchar       *buf,
  317.             gint          x,
  318.             gint          y,
  319.             gint          width)
  320. {
  321.   GimpTile *tile;
  322.   guchar   *tile_data;
  323.   gint inc, min;
  324.   gint end;
  325.   gint boundary;
  326. #ifndef MEMCPY_IS_NICE
  327.   gint b;
  328. #endif
  329.  
  330.   end = x + width;
  331.  
  332.   while (x < end)
  333.     {
  334.       tile = gimp_drawable_get_tile2 (pr->drawable, pr->shadow, x, y);
  335.       gimp_tile_ref (tile);
  336.  
  337.       tile_data = tile->data + tile->bpp * (tile->ewidth * (y % TILE_HEIGHT) + (x % TILE_WIDTH));
  338.       boundary = x + (tile->ewidth - (x % TILE_WIDTH));
  339.  
  340. #ifdef MEMCPY_IS_NICE
  341.       memcpy ((void *)tile_data,
  342.           (const void *)buf,
  343.           inc = (tile->bpp *
  344.              ( (min = MIN(end,boundary)) -x) ) );
  345.       x = min;
  346.       buf += inc;
  347. #else
  348.       for ( ; x < end && x < boundary; x++)
  349.     {
  350.       for (b = 0; b < tile->bpp; b++)
  351.         *tile_data++ = *buf++;
  352.     }
  353. #endif /* MEMCPY_IS_NICE */
  354.  
  355.       gimp_tile_unref (tile, TRUE);
  356.     }
  357. }
  358.  
  359. void
  360. gimp_pixel_rgn_set_col (GimpPixelRgn *pr,
  361.             guchar       *buf,
  362.             gint          x,
  363.             gint          y,
  364.             gint          height)
  365. {
  366.   GimpTile *tile;
  367.   guchar   *tile_data;
  368.   gint inc;
  369.   gint end;
  370.   gint boundary;
  371.   gint b;
  372.  
  373.   end = y + height;
  374.  
  375.   while (y < end)
  376.     {
  377.       tile = gimp_drawable_get_tile2 (pr->drawable, pr->shadow, x, y);
  378.       gimp_tile_ref (tile);
  379.  
  380.       tile_data = tile->data + tile->bpp * (tile->ewidth * (y % TILE_HEIGHT) + (x % TILE_WIDTH));
  381.       boundary = y + (tile->eheight - (y % TILE_HEIGHT));
  382.       inc = tile->bpp * tile->ewidth;
  383.  
  384.       for ( ; y < end && y < boundary; y++)
  385.     {
  386.       for (b = 0; b < tile->bpp; b++)
  387.         tile_data[b] = *buf++;
  388.       tile_data += inc;
  389.     }
  390.  
  391.       gimp_tile_unref (tile, TRUE);
  392.     }
  393. }
  394.  
  395. void
  396. gimp_pixel_rgn_set_rect (GimpPixelRgn *pr,
  397.              guchar       *buf,
  398.              gint          x,
  399.              gint          y,
  400.              gint          width,
  401.              gint          height)
  402. {
  403.   GimpTile *tile;
  404.   guchar   *src;
  405.   guchar   *dest;
  406.   gulong    bufstride;
  407.   gint xstart, ystart;
  408.   gint xend, yend;
  409.   gint xboundary;
  410.   gint yboundary;
  411.   gint xstep, ystep;
  412.   gint ty, bpp;
  413. #ifndef MEMCPY_IS_NICE
  414.   gint b, tx;
  415. #endif
  416.  
  417.   bpp = pr->bpp;
  418.   bufstride = bpp * width;
  419.  
  420.   xstart = x;
  421.   ystart = y;
  422.   xend = x + width;
  423.   yend = y + height;
  424.   ystep = 0;
  425.  
  426.   while (y < yend)
  427.     {
  428.       x = xstart;
  429.       while (x < xend)
  430.     {
  431.       tile = gimp_drawable_get_tile2 (pr->drawable, pr->shadow, x, y);
  432.       gimp_tile_ref (tile);
  433.  
  434.       xstep = tile->ewidth - (x % TILE_WIDTH);
  435.       ystep = tile->eheight - (y % TILE_HEIGHT);
  436.       xboundary = x + xstep;
  437.       yboundary = y + ystep;
  438.       xboundary = MIN (xboundary, xend);
  439.       yboundary = MIN (yboundary, yend);
  440.  
  441.       for (ty = y; ty < yboundary; ty++)
  442.         {
  443.           src = buf + bufstride * (ty - ystart) + bpp * (x - xstart);
  444.           dest = tile->data + tile->bpp * (tile->ewidth * (ty % TILE_HEIGHT) + (x % TILE_WIDTH));
  445.  
  446. #ifdef MEMCPY_IS_NICE
  447.           memcpy ((void *)dest, (const void *)src, (xboundary-x)*bpp); 
  448. #else
  449.           for (tx = x; tx < xboundary; tx++)
  450.         {
  451.           for (b = 0; b < bpp; b++)
  452.             *dest++ = *src++;
  453.         }
  454. #endif /* MEMCPY_IS_NICE */
  455.         }
  456.  
  457.       gimp_tile_unref (tile, TRUE);
  458.       x += xstep;
  459.     }
  460.  
  461.       y += ystep;
  462.     }
  463. }
  464.  
  465. gpointer
  466. gimp_pixel_rgns_register2 (gint           nrgns,
  467.                GimpPixelRgn **prs)
  468. {
  469.   GimpPixelRgn         *pr;
  470.   GimpPixelRgnHolder   *prh;
  471.   GimpPixelRgnIterator *pri;
  472.   gboolean found;
  473.  
  474.   pri = g_new (GimpPixelRgnIterator, 1);
  475.   pri->pixel_regions = NULL;
  476.   pri->process_count = 0;
  477.  
  478.   if (nrgns < 1)
  479.     return NULL;
  480.  
  481.   found = FALSE;
  482.   while (nrgns --)
  483.     {
  484.       pr = prs[nrgns];
  485.       prh = g_new (GimpPixelRgnHolder, 1);
  486.       prh->pr = pr;
  487.  
  488.       if (pr != NULL)
  489.     {
  490.       /*  If there is a defined value for data, make sure tiles is NULL  */
  491.       if (pr->data)
  492.         pr->drawable = NULL;
  493.       prh->original_data     = pr->data;
  494.       prh->startx            = pr->x;
  495.       prh->starty            = pr->y;
  496.       prh->pr->process_count = 0;
  497.  
  498.       if (!found)
  499.         {
  500.           found = TRUE;
  501.           pri->region_width  = pr->w;
  502.           pri->region_height = pr->h;
  503.         }
  504.     }
  505.  
  506.       /*  Add the pixel Rgn holder to the list  */
  507.       pri->pixel_regions = g_slist_prepend (pri->pixel_regions, prh);
  508.     }
  509.  
  510.   return gimp_pixel_rgns_configure (pri);
  511. }
  512.  
  513. gpointer
  514. gimp_pixel_rgns_register (gint nrgns,
  515.               ...)
  516. {
  517.   GimpPixelRgn **prs;
  518.   gpointer pri;
  519.   gint n;
  520.   va_list ap;
  521.  
  522.   prs = g_new (GimpPixelRgn *, nrgns);
  523.  
  524.   va_start (ap, nrgns);
  525.  
  526.   for (n = nrgns; n--; )
  527.     prs[n] = va_arg (ap, GimpPixelRgn *);
  528.  
  529.   va_end (ap);
  530.  
  531.   pri = gimp_pixel_rgns_register2 (nrgns, prs);
  532.  
  533.   g_free (prs);
  534.  
  535.   return pri;
  536. }
  537.  
  538. gpointer
  539. gimp_pixel_rgns_process (gpointer pri_ptr)
  540. {
  541.   GSList *list;
  542.   GimpPixelRgnHolder   *prh;
  543.   GimpPixelRgnIterator *pri;
  544.  
  545.   pri = (GimpPixelRgnIterator*) pri_ptr;
  546.   pri->process_count++;
  547.  
  548.   /*  Unref all referenced tiles and increment the offsets  */
  549.  
  550.   list = pri->pixel_regions;
  551.   while (list)
  552.     {
  553.       prh = (GimpPixelRgnHolder *) list->data;
  554.       list = list->next;
  555.  
  556.       if ((prh->pr != NULL) && (prh->pr->process_count != pri->process_count))
  557.     {
  558.       /*  This eliminates the possibility of incrementing the
  559.        *  same region twice
  560.        */
  561.       prh->pr->process_count++;
  562.  
  563.       /*  Unref the last referenced tile if the underlying region is a tile manager  */
  564.       if (prh->pr->drawable)
  565.         {
  566.           GimpTile *tile = gimp_drawable_get_tile2 (prh->pr->drawable, prh->pr->shadow,
  567.                             prh->pr->x, prh->pr->y);
  568.           gimp_tile_unref (tile, prh->pr->dirty);
  569.         }
  570.  
  571.       prh->pr->x += pri->portion_width;
  572.  
  573.       if ((prh->pr->x - prh->startx) >= pri->region_width)
  574.         {
  575.           prh->pr->x = prh->startx;
  576.           prh->pr->y += pri->portion_height;
  577.         }
  578.     }
  579.     }
  580.  
  581.   return gimp_pixel_rgns_configure (pri);
  582. }
  583.  
  584.  
  585. static gint
  586. gimp_get_portion_width (GimpPixelRgnIterator *pri)
  587. {
  588.   GimpPixelRgnHolder *prh;
  589.   GSList *list;
  590.   gint    min_width = G_MAXINT;
  591.   gint    width;
  592.  
  593.   /* Find the minimum width to the next vertical tile (in the case of a tile manager)
  594.    * or to the end of the pixel region (in the case of no tile manager)
  595.    */
  596.  
  597.   list = pri->pixel_regions;
  598.   while (list)
  599.     {
  600.       prh = (GimpPixelRgnHolder *) list->data;
  601.  
  602.       if (prh->pr)
  603.         {
  604.           /* Check if we're past the point of no return  */
  605.           if ((prh->pr->x - prh->startx) >= pri->region_width)
  606.             return 0;
  607.  
  608.           if (prh->pr->drawable)
  609.             {
  610.               width = TILE_WIDTH - (prh->pr->x % TILE_WIDTH);
  611.               width = BOUNDS (width, 0, (pri->region_width - (prh->pr->x - prh->startx)));
  612.             }
  613.           else
  614.             width = (pri->region_width - (prh->pr->x - prh->startx));
  615.  
  616.           if (width < min_width)
  617.             min_width = width;
  618.         }
  619.  
  620.       list = list->next;
  621.     }
  622.  
  623.   return min_width;
  624. }
  625.  
  626. static int
  627. gimp_get_portion_height (GimpPixelRgnIterator *pri)
  628. {
  629.   GimpPixelRgnHolder *prh;
  630.   GSList *list;
  631.   gint    min_height = G_MAXINT;
  632.   gint    height;
  633.  
  634.   /* Find the minimum height to the next vertical tile (in the case of a tile manager)
  635.    * or to the end of the pixel region (in the case of no tile manager)
  636.    */
  637.  
  638.   list = pri->pixel_regions;
  639.   while (list)
  640.     {
  641.       prh = (GimpPixelRgnHolder *) list->data;
  642.  
  643.       if (prh->pr)
  644.         {
  645.           /* Check if we're past the point of no return  */
  646.           if ((prh->pr->y - prh->starty) >= pri->region_height)
  647.             return 0;
  648.  
  649.           if (prh->pr->drawable)
  650.             {
  651.               height = TILE_HEIGHT - (prh->pr->y % TILE_HEIGHT);
  652.               height = BOUNDS (height, 0, (pri->region_height - (prh->pr->y - prh->starty)));
  653.             }
  654.           else
  655.             height = (pri->region_height - (prh->pr->y - prh->starty));
  656.  
  657.           if (height < min_height)
  658.             min_height = height;
  659.         }
  660.  
  661.       list = list->next;
  662.     }
  663.  
  664.   return min_height;
  665. }
  666.  
  667. static gpointer
  668. gimp_pixel_rgns_configure (GimpPixelRgnIterator *pri)
  669. {
  670.   GimpPixelRgnHolder *prh;
  671.   GSList             *list;
  672.  
  673.   /*  Determine the portion width and height  */
  674.   pri->portion_width = gimp_get_portion_width (pri);
  675.   pri->portion_height = gimp_get_portion_height (pri);
  676.  
  677.   if ((pri->portion_width == 0) ||
  678.       (pri->portion_height == 0))
  679.     {
  680.       /*  free the pixel regions list  */
  681.       if (pri->pixel_regions)
  682.         {
  683.           list = pri->pixel_regions;
  684.           while (list)
  685.             {
  686.               g_free (list->data);
  687.               list = list->next;
  688.             }
  689.           g_slist_free (pri->pixel_regions);
  690.           g_free (pri);
  691.         }
  692.  
  693.       return NULL;
  694.     }
  695.  
  696.   pri->process_count++;
  697.  
  698.   for (list = pri->pixel_regions; list; list = g_slist_next (list))
  699.     {
  700.       prh = (GimpPixelRgnHolder *) list->data;
  701.  
  702.       if ((prh->pr != NULL) && (prh->pr->process_count != pri->process_count))
  703.         {
  704.           prh->pr->process_count++;
  705.           gimp_pixel_rgn_configure (prh, pri);
  706.         }
  707.     }
  708.  
  709.   return pri;
  710. }
  711.  
  712. static void
  713. gimp_pixel_rgn_configure (GimpPixelRgnHolder   *prh,
  714.               GimpPixelRgnIterator *pri)
  715. {
  716.   /* Configure the rowstride and data pointer for the pixel region
  717.    * based on the current offsets into the region and whether the
  718.    * region is represented by a tile manager or not
  719.    */
  720.   if (prh->pr->drawable)
  721.     {
  722.       GimpTile *tile;
  723.       gint      offx;
  724.       gint      offy;
  725.  
  726.       tile = gimp_drawable_get_tile2 (prh->pr->drawable, prh->pr->shadow, prh->pr->x, prh->pr->y);
  727.       gimp_tile_ref (tile);
  728.  
  729.       offx = prh->pr->x % TILE_WIDTH;
  730.       offy = prh->pr->y % TILE_HEIGHT;
  731.  
  732.       prh->pr->rowstride = tile->ewidth * prh->pr->bpp;
  733.       prh->pr->data = tile->data + offy * prh->pr->rowstride + offx * prh->pr->bpp;
  734.     }
  735.   else
  736.     {
  737.       prh->pr->data = (prh->original_data +
  738.                (prh->pr->y - prh->starty) * prh->pr->rowstride +
  739.                (prh->pr->x - prh->startx) * prh->pr->bpp);
  740.     }
  741.  
  742.   prh->pr->w = pri->portion_width;
  743.   prh->pr->h = pri->portion_height;
  744. }
  745.