static gboolean
gimp_operation_tile_source_process (GeglOperation       *operation,
                                    GeglBuffer          *output,
                                    const GeglRectangle *result)
{
  GimpOperationTileSource *self = GIMP_OPERATION_TILE_SOURCE (operation);
  const Babl              *format;
  PixelRegion              srcPR;
  gpointer                 pr;

  if (! self->tile_manager)
    return FALSE;

  format = gegl_operation_get_format (operation, "output");

  pixel_region_init (&srcPR, self->tile_manager,
                     result->x,     result->y,
                     result->width, result->height,
                     FALSE);

  for (pr = pixel_regions_register (1, &srcPR);
       pr;
       pr = pixel_regions_process (pr))
    {
      GeglRectangle rect = { srcPR.x, srcPR.y, srcPR.w, srcPR.h };

      gegl_buffer_set (output, &rect, 1, format, srcPR.data, srcPR.rowstride);
    }

  return TRUE;
}
static void
gimp_operation_tile_source_set_property (GObject      *object,
                                         guint         property_id,
                                         const GValue *value,
                                         GParamSpec   *pspec)
{
  GimpOperationTileSource *self = GIMP_OPERATION_TILE_SOURCE (object);

  switch (property_id)
    {
    case PROP_TILE_MANAGER:
      if (self->tile_manager)
        tile_manager_unref (self->tile_manager);
      self->tile_manager = g_value_dup_boxed (value);
      break;

    case PROP_LINEAR:
      self->linear = g_value_get_boolean (value);
      break;

    default:
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
      break;
    }
}
static void
gimp_operation_tile_source_prepare (GeglOperation *operation)
{
  GimpOperationTileSource *self = GIMP_OPERATION_TILE_SOURCE (operation);

  if (self->tile_manager)
    {
      gegl_operation_set_format (operation, "output",
                                 babl_format ("RaGaBaA float"));
    }
}
static void
gimp_operation_tile_source_finalize (GObject *object)
{
  GimpOperationTileSource *self = GIMP_OPERATION_TILE_SOURCE (object);

  if (self->tile_manager)
    {
      tile_manager_unref (self->tile_manager);
      self->tile_manager = NULL;
    }

  G_OBJECT_CLASS (parent_class)->finalize (object);
}
static GeglRectangle
gimp_operation_tile_source_get_bounding_box (GeglOperation *operation)
{
  GimpOperationTileSource *self   = GIMP_OPERATION_TILE_SOURCE (operation);
  GeglRectangle            result = { 0, };

  if (self->tile_manager)
    {
      result.x      = 0;
      result.y      = 0;
      result.width  = tile_manager_width (self->tile_manager);
      result.height = tile_manager_height (self->tile_manager);
    }

  return result;
}
static void
gimp_operation_tile_source_prepare (GeglOperation *operation)
{
  GimpOperationTileSource *self = GIMP_OPERATION_TILE_SOURCE (operation);

  if (self->tile_manager)
    {
      const Babl *format;
      guint       bpp = tile_manager_bpp (self->tile_manager);

      if (self->linear)
        format = gimp_bpp_to_babl_format_linear (bpp);
      else
        format = gimp_bpp_to_babl_format (bpp);

      gegl_operation_set_format (operation, "output", format);
    }
}