Пример #1
0
void
gimp_paint_core_validate_canvas_tiles (GimpPaintCore *core,
                                       gint           x,
                                       gint           y,
                                       gint           w,
                                       gint           h)
{
  gint i, j;

  g_return_if_fail (GIMP_IS_PAINT_CORE (core));
  g_return_if_fail (core->canvas_tiles != NULL);

  for (i = y; i < (y + h); i += (TILE_HEIGHT - (i % TILE_HEIGHT)))
    {
      for (j = x; j < (x + w); j += (TILE_WIDTH - (j % TILE_WIDTH)))
        {
          Tile *tile = tile_manager_get_tile (core->canvas_tiles, j, i,
                                              FALSE, FALSE);

          if (! tile_is_valid (tile))
            {
              tile = tile_manager_get_tile (core->canvas_tiles, j, i,
                                            TRUE, TRUE);
              memset (tile_data_pointer (tile, 0, 0), 0, tile_size (tile));
              tile_release (tile, TRUE);
            }
        }
    }
}
Пример #2
0
void
tile_update_rowhints (Tile *tile,
                      gint  start,
                      gint  rows)
{
  const guchar *ptr;
  gint          bpp, ewidth;
  gint          x, y;

#ifdef HINTS_SANITY
  g_assert (tile != NULL);
#endif

  tile_allocate_rowhints (tile);

  bpp = tile_bpp (tile);
  ewidth = tile_ewidth (tile);

  switch (bpp)
    {
    case 1:
    case 3:
      for (y = start; y < start + rows; y++)
        tile_set_rowhint (tile, y, TILEROWHINT_OPAQUE);
      break;

    case 4:
#ifdef HINTS_SANITY
      g_assert (tile != NULL);
#endif

      ptr = tile_data_pointer (tile, 0, start);

#ifdef HINTS_SANITY
      g_assert (ptr != NULL);
#endif

      for (y = start; y < start + rows; y++)
        {
          TileRowHint hint = tile_get_rowhint (tile, y);

#ifdef HINTS_SANITY
          if (hint == TILEROWHINT_BROKEN)
            g_error ("BROKEN y=%d", y);
          if (hint == TILEROWHINT_OUTOFRANGE)
            g_error ("OOR y=%d", y);
          if (hint == TILEROWHINT_UNDEFINED)
            g_error ("UNDEFINED y=%d - bpp=%d ew=%d eh=%d",
                     y, bpp, ewidth, eheight);
#endif

#ifdef HINTS_SANITY
          if (hint == TILEROWHINT_TRANSPARENT ||
              hint == TILEROWHINT_MIXED ||
              hint == TILEROWHINT_OPAQUE)
            {
              goto next_row4;
            }

          if (hint != TILEROWHINT_UNKNOWN)
            {
              g_error ("MEGABOGUS y=%d - bpp=%d ew=%d eh=%d",
                       y, bpp, ewidth, eheight);
            }
#endif

          if (hint == TILEROWHINT_UNKNOWN)
            {
              const guchar alpha = ptr[3];

              /* row is all-opaque or all-transparent? */
              if (alpha == 0 || alpha == 255)
                {
                  if (ewidth > 1)
                    {
                      for (x = 1; x < ewidth; x++)
                        {
                          if (ptr[x * 4 + 3] != alpha)
                            {
                              tile_set_rowhint (tile, y, TILEROWHINT_MIXED);
                              goto next_row4;
                            }
                        }
                    }

                  tile_set_rowhint (tile, y,
                                    (alpha == 0) ?
                                    TILEROWHINT_TRANSPARENT :
                                    TILEROWHINT_OPAQUE);
                }
              else
                {
                  tile_set_rowhint (tile, y, TILEROWHINT_MIXED);
                }
            }

        next_row4:
          ptr += 4 * ewidth;
        }
      break;

    case 2:
#ifdef HINTS_SANITY
      g_assert (tile != NULL);
#endif

      ptr = tile_data_pointer (tile, 0, start);

#ifdef HINTS_SANITY
      g_assert (ptr != NULL);
#endif

      for (y = start; y < start + rows; y++)
        {
          TileRowHint hint = tile_get_rowhint (tile, y);

#ifdef HINTS_SANITY
          if (hint == TILEROWHINT_BROKEN)
            g_error ("BROKEN y=%d",y);
          if (hint == TILEROWHINT_OUTOFRANGE)
            g_error ("OOR y=%d",y);
          if (hint == TILEROWHINT_UNDEFINED)
            g_error ("UNDEFINED y=%d - bpp=%d ew=%d eh=%d",
                     y, bpp, ewidth, eheight);
#endif

#ifdef HINTS_SANITY
          if (hint == TILEROWHINT_TRANSPARENT ||
              hint == TILEROWHINT_MIXED ||
              hint == TILEROWHINT_OPAQUE)
            {
              goto next_row2;
            }

          if (hint != TILEROWHINT_UNKNOWN)
            {
              g_error ("MEGABOGUS y=%d - bpp=%d ew=%d eh=%d",
                       y, bpp, ewidth, eheight);
            }
#endif

          if (hint == TILEROWHINT_UNKNOWN)
            {
              const guchar alpha = ptr[1];

              /* row is all-opaque or all-transparent? */
              if (alpha == 0 || alpha == 255)
                {
                  if (ewidth > 1)
                    {
                      for (x = 1; x < ewidth; x++)
                        {
                          if (ptr[x * 2 + 1] != alpha)
                            {
                              tile_set_rowhint (tile, y, TILEROWHINT_MIXED);
                              goto next_row2;
                            }
                        }
                    }

                  tile_set_rowhint (tile, y,
                                    (alpha == 0) ?
                                    TILEROWHINT_TRANSPARENT :
                                    TILEROWHINT_OPAQUE);
                }
              else
                {
                  tile_set_rowhint (tile, y, TILEROWHINT_MIXED);
                }
            }

        next_row2:
          ptr += 2 * ewidth;
        }
      break;

    default:
      g_return_if_reached ();
      break;
    }
}
Пример #3
0
static void
find_empty_segs (PixelRegion  *maskPR,
                 gint          scanline,
                 gint          empty_segs[],
                 gint          max_empty,
                 gint         *num_empty,
                 BoundaryType  type,
                 gint          x1,
                 gint          y1,
                 gint          x2,
                 gint          y2,
                 guchar        threshold)
{
    const guchar *data  = NULL;
    Tile         *tile  = NULL;
    gint          start = 0;
    gint          end   = 0;
    gint          endx  = 0;
    gint          bpp   = 0;
    gint          tilex = -1;
    gint          last  = -1;
    gint          l_num_empty;
    gint          x;

    *num_empty = 0;

    if (scanline < maskPR->y || scanline >= (maskPR->y + maskPR->h))
    {
        empty_segs[(*num_empty)++] = 0;
        empty_segs[(*num_empty)++] = G_MAXINT;
        return;
    }

    if (type == BOUNDARY_WITHIN_BOUNDS)
    {
        if (scanline < y1 || scanline >= y2)
        {
            empty_segs[(*num_empty)++] = 0;
            empty_segs[(*num_empty)++] = G_MAXINT;
            return;
        }

        start = x1;
        end   = x2;
    }
    else if (type == BOUNDARY_IGNORE_BOUNDS)
    {
        start = maskPR->x;
        end   = maskPR->x + maskPR->w;
        if (scanline < y1 || scanline >= y2)
            x2 = -1;
    }

    empty_segs[(*num_empty)++] = 0;

    l_num_empty = *num_empty;

    bpp = maskPR->bytes;

    if (! maskPR->tiles)
    {
        data  = maskPR->data + scanline * maskPR->rowstride;
        endx = end;
    }

    for (x = start; x < end;)
    {
        /*  Check to see if we must advance to next tile  */
        if (maskPR->tiles)
        {
            if ((x / TILE_WIDTH) != tilex)
            {
                if (tile)
                    tile_release (tile, FALSE);

                tile = tile_manager_get_tile (maskPR->tiles,
                                              x, scanline, TRUE, FALSE);
                data = ((const guchar *) tile_data_pointer (tile, x, scanline) +
                        bpp - 1);

                tilex = x / TILE_WIDTH;
            }

            endx = x + (TILE_WIDTH - (x % TILE_WIDTH));
            endx = MIN (end, endx);
        }

        if (type == BOUNDARY_IGNORE_BOUNDS && (endx > x1 || x < x2))
        {
            for (; x < endx; x++)
            {
                gint val;

                if (*data > threshold)
                {
                    if (x >= x1 && x < x2)
                        val = -1;
                    else
                        val = 1;
                }
                else
                {
                    val = -1;
                }

                data += bpp;

                if (last != val)
                    empty_segs[l_num_empty++] = x;

                last = val;
            }
        }
        else
        {
            for (; x < endx; x++)
            {
                gint val;

                if (*data > threshold)
                    val = 1;
                else
                    val = -1;

                data += bpp;

                if (last != val)
                    empty_segs[l_num_empty++] = x;

                last = val;
            }
        }
    }

    *num_empty = l_num_empty;

    if (last > 0)
        empty_segs[(*num_empty)++] = x;

    empty_segs[(*num_empty)++] = G_MAXINT;

    if (tile)
        tile_release (tile, FALSE);
}
Пример #4
0
TempBuf *
gimp_paint_core_get_orig_proj (GimpPaintCore *core,
                               GimpPickable  *pickable,
                               gint           x,
                               gint           y,
                               gint           width,
                               gint           height)
{
  TileManager  *src_tiles;
  PixelRegion   srcPR;
  PixelRegion   destPR;
  Tile         *saved_tile;
  gboolean      release_tile;
  gint          h;
  gint          pixelwidth;
  gint          pickable_width;
  gint          pickable_height;
  const guchar *s;
  guchar       *d;
  gpointer      pr;

  g_return_val_if_fail (GIMP_IS_PAINT_CORE (core), NULL);
  g_return_val_if_fail (GIMP_IS_PICKABLE (pickable), NULL);
  g_return_val_if_fail (core->saved_proj_tiles != NULL, NULL);

  core->orig_proj_buf = temp_buf_resize (core->orig_proj_buf,
                                         gimp_pickable_get_bytes (pickable),
                                         x, y, width, height);

  src_tiles = gimp_pickable_get_tiles (pickable);

  pickable_width  = tile_manager_width  (src_tiles);
  pickable_height = tile_manager_height (src_tiles);

  gimp_rectangle_intersect (x, y,
                            width, height,
                            0, 0,
                            pickable_width, pickable_height,
                            &x, &y,
                            &width, &height);

  /*  configure the pixel regions  */
  pixel_region_init (&srcPR, src_tiles,
                     x, y, width, height,
                     FALSE);

  pixel_region_init_temp_buf (&destPR, core->orig_proj_buf,
                              x - core->orig_proj_buf->x,
                              y - core->orig_proj_buf->y,
                              width, height);

  for (pr = pixel_regions_register (2, &srcPR, &destPR);
       pr != NULL;
       pr = pixel_regions_process (pr))
    {
      /*  If the saved tile corresponding to this location is valid, use it  */
      saved_tile = tile_manager_get_tile (core->saved_proj_tiles,
                                          srcPR.x, srcPR.y,
                                          FALSE, FALSE);

      if (tile_is_valid (saved_tile))
        {
          release_tile = TRUE;

          saved_tile = tile_manager_get_tile (core->saved_proj_tiles,
                                              srcPR.x, srcPR.y,
                                              TRUE, FALSE);
          s = tile_data_pointer (saved_tile, srcPR.x, srcPR.y);
        }
      else
        {
          release_tile = FALSE;

          s = srcPR.data;
        }

      d = destPR.data;

      pixelwidth = srcPR.w * srcPR.bytes;

      h = srcPR.h;
      while (h --)
        {
          memcpy (d, s, pixelwidth);

          s += srcPR.rowstride;
          d += destPR.rowstride;
        }

      if (release_tile)
        tile_release (saved_tile, FALSE);
    }

  return core->orig_proj_buf;
}
Пример #5
0
static void
tile_pyramid_write_quarter (Tile *dest,
                            Tile *src,
                            gint  i,
                            gint  j)
{
  const guchar *src_data    = tile_data_pointer (src, 0, 0);
  guchar       *dest_data   = tile_data_pointer (dest, 0, 0);
  const gint    src_ewidth  = tile_ewidth  (src);
  const gint    src_eheight = tile_eheight (src);
  const gint    dest_ewidth = tile_ewidth  (dest);
  const gint    bpp         = tile_bpp     (dest);
  gint          y;

  /* Adjust dest pointer to the right quadrant. */
  dest_data += i * bpp * (TILE_WIDTH / 2) +
               j * bpp * dest_ewidth * (TILE_HEIGHT / 2);

  for (y = 0; y < src_eheight / 2; y++)
    {
      const guchar *src0 = src_data;
      const guchar *src1 = src_data + bpp;
      const guchar *src2 = src0 + bpp * src_ewidth;
      const guchar *src3 = src1 + bpp * src_ewidth;
      guchar       *dst  = dest_data;
      gint          x;

      switch (bpp)
        {
        case 1:
          for (x = 0; x < src_ewidth / 2; x++)
            {
              dst[0] = (src0[0] + src1[0] + src2[0] + src3[0]) >> 2;

              dst += 1;

              src0 += 2;
              src1 += 2;
              src2 += 2;
              src3 += 2;
            }
          break;

        case 2:
          for (x = 0; x < src_ewidth / 2; x++)
            {
              guint a = src0[1] + src1[1] + src2[1] + src3[1];

              switch (a)
                {
                case 0:    /* all transparent */
                  dst[0] = dst[1] = 0;
                  break;

                case 1020: /* all opaque */
                  dst[0] = (src0[0]  + src1[0] + src2[0] + src3[0]) >> 2;
                  dst[1] = 255;
                  break;

                default:
                  dst[0] = ((src0[0] * src0[1] +
                             src1[0] * src1[1] +
                             src2[0] * src2[1] +
                             src3[0] * src3[1]) / a);
                  dst[1] = (a + 2) >> 2;
                  break;
                }

              dst += 2;

              src0 += 4;
              src1 += 4;
              src2 += 4;
              src3 += 4;
            }
          break;

        case 3:
          for (x = 0; x < src_ewidth / 2; x++)
            {
              dst[0] = (src0[0] + src1[0] + src2[0] + src3[0]) >> 2;
              dst[1] = (src0[1] + src1[1] + src2[1] + src3[1]) >> 2;
              dst[2] = (src0[2] + src1[2] + src2[2] + src3[2]) >> 2;

              dst += 3;

              src0 += 6;
              src1 += 6;
              src2 += 6;
              src3 += 6;
            }
          break;

        case 4:
          for (x = 0; x < src_ewidth / 2; x++)
            {
              guint a = src0[3] + src1[3] + src2[3] + src3[3];

              switch (a)
                {
                case 0:    /* all transparent */
                  dst[0] = dst[1] = dst[2] = dst[3] = 0;
                  break;

                case 1020: /* all opaque */
                  dst[0] = (src0[0] + src1[0] + src2[0] + src3[0]) >> 2;
                  dst[1] = (src0[1] + src1[1] + src2[1] + src3[1]) >> 2;
                  dst[2] = (src0[2] + src1[2] + src2[2] + src3[2]) >> 2;
                  dst[3] = 255;
                  break;

                default:
                  dst[0] = ((src0[0] * src0[3] +
                             src1[0] * src1[3] +
                             src2[0] * src2[3] +
                             src3[0] * src3[3]) / a);
                  dst[1] = ((src0[1] * src0[3] +
                             src1[1] * src1[3] +
                             src2[1] * src2[3] +
                             src3[1] * src3[3]) / a);
                  dst[2] = ((src0[2] * src0[3] +
                             src1[2] * src1[3] +
                             src2[2] * src2[3] +
                             src3[2] * src3[3]) / a);
                  dst[3] = (a + 2) >> 2;
                  break;
                }

              dst += 4;

              src0 += 8;
              src1 += 8;
              src2 += 8;
              src3 += 8;
            }
          break;
        }

      dest_data += dest_ewidth * bpp;
      src_data += src_ewidth * bpp * 2;
    }
}