|
Packit Service |
2781ba |
/* This file is part of GEGL.
|
|
Packit Service |
2781ba |
*
|
|
Packit Service |
2781ba |
* This library is free software; you can redistribute it and/or
|
|
Packit Service |
2781ba |
* modify it under the terms of the GNU Lesser General Public
|
|
Packit Service |
2781ba |
* License as published by the Free Software Foundation; either
|
|
Packit Service |
2781ba |
* version 3 of the License, or (at your option) any later version.
|
|
Packit Service |
2781ba |
*
|
|
Packit Service |
2781ba |
* This library is distributed in the hope that it will be useful,
|
|
Packit Service |
2781ba |
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
Packit Service |
2781ba |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
Packit Service |
2781ba |
* Lesser General Public License for more details.
|
|
Packit Service |
2781ba |
*
|
|
Packit Service |
2781ba |
* You should have received a copy of the GNU Lesser General Public
|
|
Packit Service |
2781ba |
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
|
|
Packit Service |
2781ba |
*
|
|
Packit Service |
2781ba |
* Copyright 2006, 2007 Øyvind Kolås <pippin@gimp.org>
|
|
Packit Service |
2781ba |
*/
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
#include "config.h"
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
#include <string.h>
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
#include <sys/types.h>
|
|
Packit Service |
2781ba |
#include <sys/stat.h>
|
|
Packit Service |
2781ba |
#include <fcntl.h>
|
|
Packit Service |
2781ba |
#include <unistd.h>
|
|
Packit Service |
2781ba |
#include <errno.h>
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
#include <glib-object.h>
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
#include "gegl-types-internal.h"
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
#include "gegl.h"
|
|
Packit Service |
2781ba |
#include "gegl-buffer-types.h"
|
|
Packit Service |
2781ba |
#include "gegl-buffer.h"
|
|
Packit Service |
2781ba |
#include "gegl-buffer-private.h"
|
|
Packit Service |
2781ba |
#include "gegl-debug.h"
|
|
Packit Service |
2781ba |
#include "gegl-tile-storage.h"
|
|
Packit Service |
2781ba |
#include "gegl-tile-backend.h"
|
|
Packit Service |
2781ba |
#include "gegl-tile-handler.h"
|
|
Packit Service |
2781ba |
#include "gegl-tile.h"
|
|
Packit Service |
2781ba |
#include "gegl-tile-handler-cache.h"
|
|
Packit Service |
2781ba |
#include "gegl-tile-handler-log.h"
|
|
Packit Service |
2781ba |
#include "gegl-tile-handler-empty.h"
|
|
Packit Service |
2781ba |
#include "gegl-types-internal.h"
|
|
Packit Service |
2781ba |
#include "gegl-utils.h"
|
|
Packit Service |
2781ba |
#include "gegl-buffer-save.h"
|
|
Packit Service |
2781ba |
#include "gegl-buffer-index.h"
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
typedef struct
|
|
Packit Service |
2781ba |
{
|
|
Packit Service |
2781ba |
GeglBufferHeader header;
|
|
Packit Service |
2781ba |
GList *tiles;
|
|
Packit Service |
2781ba |
gchar *path;
|
|
Packit Service |
2781ba |
int o;
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
gint tile_size;
|
|
Packit Service |
2781ba |
gint offset;
|
|
Packit Service |
2781ba |
gint entry_count;
|
|
Packit Service |
2781ba |
GeglBufferBlock *in_holding; /* we need to write one block added behind
|
|
Packit Service |
2781ba |
* to be able to recompute the forward pointing
|
|
Packit Service |
2781ba |
* link from one entry to the next.
|
|
Packit Service |
2781ba |
*/
|
|
Packit Service |
2781ba |
} SaveInfo;
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
GeglBufferTile *
|
|
Packit Service |
2781ba |
gegl_tile_entry_new (gint x,
|
|
Packit Service |
2781ba |
gint y,
|
|
Packit Service |
2781ba |
gint z)
|
|
Packit Service |
2781ba |
{
|
|
Packit Service |
2781ba |
GeglBufferTile *entry = g_malloc0 (sizeof(GeglBufferTile));
|
|
Packit Service |
2781ba |
entry->block.flags = GEGL_FLAG_TILE;
|
|
Packit Service |
2781ba |
entry->block.length = sizeof (GeglBufferTile);
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
entry->x = x;
|
|
Packit Service |
2781ba |
entry->y = y;
|
|
Packit Service |
2781ba |
entry->z = z;
|
|
Packit Service |
2781ba |
return entry;
|
|
Packit Service |
2781ba |
}
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
void
|
|
Packit Service |
2781ba |
gegl_tile_entry_destroy (GeglBufferTile *entry)
|
|
Packit Service |
2781ba |
{
|
|
Packit Service |
2781ba |
g_free (entry);
|
|
Packit Service |
2781ba |
}
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
static gsize write_block (SaveInfo *info,
|
|
Packit Service |
2781ba |
GeglBufferBlock *block)
|
|
Packit Service |
2781ba |
{
|
|
Packit Service |
2781ba |
gssize ret = 0;
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
if (info->in_holding)
|
|
Packit Service |
2781ba |
{
|
|
Packit Service |
2781ba |
glong allocated_pos = info->offset + info->in_holding->length;
|
|
Packit Service |
2781ba |
info->in_holding->next = allocated_pos;
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
if (block == NULL)
|
|
Packit Service |
2781ba |
info->in_holding->next = 0;
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
ret = write (info->o, info->in_holding, info->in_holding->length);
|
|
Packit Service |
2781ba |
if (ret == -1)
|
|
Packit Service |
2781ba |
ret = 0;
|
|
Packit Service |
2781ba |
info->offset += ret;
|
|
Packit Service |
2781ba |
g_assert (allocated_pos == info->offset);
|
|
Packit Service |
2781ba |
}
|
|
Packit Service |
2781ba |
/* write block should also allocate the block and update the
|
|
Packit Service |
2781ba |
* previously added blocks next pointer
|
|
Packit Service |
2781ba |
*/
|
|
Packit Service |
2781ba |
info->in_holding = block;
|
|
Packit Service |
2781ba |
return ret;
|
|
Packit Service |
2781ba |
}
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
static void
|
|
Packit Service |
2781ba |
save_info_destroy (SaveInfo *info)
|
|
Packit Service |
2781ba |
{
|
|
Packit Service |
2781ba |
if (!info)
|
|
Packit Service |
2781ba |
return;
|
|
Packit Service |
2781ba |
if (info->path)
|
|
Packit Service |
2781ba |
g_free (info->path);
|
|
Packit Service |
2781ba |
if (info->o != -1)
|
|
Packit Service |
2781ba |
close (info->o);
|
|
Packit Service |
2781ba |
if (info->tiles != NULL)
|
|
Packit Service |
2781ba |
{
|
|
Packit Service |
2781ba |
GList *iter;
|
|
Packit Service |
2781ba |
for (iter = info->tiles; iter; iter = iter->next)
|
|
Packit Service |
2781ba |
gegl_tile_entry_destroy (iter->data);
|
|
Packit Service |
2781ba |
g_list_free (info->tiles);
|
|
Packit Service |
2781ba |
info->tiles = NULL;
|
|
Packit Service |
2781ba |
}
|
|
Packit Service |
2781ba |
g_slice_free (SaveInfo, info);
|
|
Packit Service |
2781ba |
}
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
static glong z_order (const GeglBufferTile *entry)
|
|
Packit Service |
2781ba |
{
|
|
Packit Service |
2781ba |
glong value;
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
gint i;
|
|
Packit Service |
2781ba |
gint srcA = entry->x;
|
|
Packit Service |
2781ba |
gint srcB = entry->y;
|
|
Packit Service |
2781ba |
gint srcC = entry->z;
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
/* interleave the 10 least significant bits of all coordinates,
|
|
Packit Service |
2781ba |
* this gives us Z-order / morton order of the space and should
|
|
Packit Service |
2781ba |
* work well as a hash
|
|
Packit Service |
2781ba |
*/
|
|
Packit Service |
2781ba |
value = 0;
|
|
Packit Service |
2781ba |
for (i = 20; i >= 0; i--)
|
|
Packit Service |
2781ba |
{
|
|
Packit Service |
2781ba |
#define ADD_BIT(bit) do { value |= (((bit) != 0) ? 1 : 0); value <<= 1; \
|
|
Packit Service |
2781ba |
} \
|
|
Packit Service |
2781ba |
while (0)
|
|
Packit Service |
2781ba |
ADD_BIT (srcA & (1 << i));
|
|
Packit Service |
2781ba |
ADD_BIT (srcB & (1 << i));
|
|
Packit Service |
2781ba |
ADD_BIT (srcC & (1 << i));
|
|
Packit Service |
2781ba |
#undef ADD_BIT
|
|
Packit Service |
2781ba |
}
|
|
Packit Service |
2781ba |
return value;
|
|
Packit Service |
2781ba |
}
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
static gint z_order_compare (gconstpointer a,
|
|
Packit Service |
2781ba |
gconstpointer b)
|
|
Packit Service |
2781ba |
{
|
|
Packit Service |
2781ba |
const GeglBufferTile *entryA = a;
|
|
Packit Service |
2781ba |
const GeglBufferTile *entryB = b;
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
return z_order (entryB) - z_order (entryA);
|
|
Packit Service |
2781ba |
}
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
void
|
|
Packit Service |
2781ba |
gegl_buffer_header_init (GeglBufferHeader *header,
|
|
Packit Service |
2781ba |
gint tile_width,
|
|
Packit Service |
2781ba |
gint tile_height,
|
|
Packit Service |
2781ba |
gint bpp,
|
|
Packit Service |
2781ba |
const Babl* format)
|
|
Packit Service |
2781ba |
{
|
|
Packit Service |
2781ba |
memcpy (header->magic, "GEGL", 4);
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
header->flags = GEGL_FLAG_HEADER;
|
|
Packit Service |
2781ba |
header->tile_width = tile_width;
|
|
Packit Service |
2781ba |
header->tile_height = tile_height;
|
|
Packit Service |
2781ba |
header->bytes_per_pixel = bpp;
|
|
Packit Service |
2781ba |
{
|
|
Packit Service |
2781ba |
gchar buf[64] = { 0, };
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
g_snprintf (buf, 64, "%s%c\n%i×%i %ibpp\n%ix%i\n\n\n\n\n\n\n\n\n",
|
|
Packit Service |
2781ba |
babl_get_name (format), 0,
|
|
Packit Service |
2781ba |
header->tile_width,
|
|
Packit Service |
2781ba |
header->tile_height,
|
|
Packit Service |
2781ba |
header->bytes_per_pixel,
|
|
Packit Service |
2781ba |
(gint)header->width,
|
|
Packit Service |
2781ba |
(gint)header->height);
|
|
Packit Service |
2781ba |
memcpy ((header->description), buf, 64);
|
|
Packit Service |
2781ba |
}
|
|
Packit Service |
2781ba |
}
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
void
|
|
Packit Service |
2781ba |
gegl_buffer_save (GeglBuffer *buffer,
|
|
Packit Service |
2781ba |
const gchar *path,
|
|
Packit Service |
2781ba |
const GeglRectangle *roi)
|
|
Packit Service |
2781ba |
{
|
|
Packit Service |
2781ba |
SaveInfo *info = g_slice_new0 (SaveInfo);
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
glong prediction = 0;
|
|
Packit Service |
2781ba |
gint bpp;
|
|
Packit Service |
2781ba |
gint tile_width;
|
|
Packit Service |
2781ba |
gint tile_height;
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
GEGL_BUFFER_SANITY;
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
if (! roi)
|
|
Packit Service |
2781ba |
roi = &buffer->extent;
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
GEGL_NOTE (GEGL_DEBUG_BUFFER_SAVE,
|
|
Packit Service |
2781ba |
"starting to save buffer %s, roi: %d,%d %dx%d",
|
|
Packit Service |
2781ba |
path, roi->x, roi->y, roi->width, roi->height);
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
/* a header should follow the same structure as a blockdef with
|
|
Packit Service |
2781ba |
* respect to the flags and next offsets, thus this is a valid
|
|
Packit Service |
2781ba |
* cast shortcut.
|
|
Packit Service |
2781ba |
*/
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
info->path = g_strdup (path);
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
#ifndef G_OS_WIN32
|
|
Packit Service |
2781ba |
info->o = open (info->path, O_RDWR|O_CREAT|O_TRUNC, S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH);
|
|
Packit Service |
2781ba |
#else
|
|
Packit Service |
2781ba |
info->o = open (info->path, O_RDWR|O_CREAT|O_TRUNC, S_IRUSR|S_IWUSR);
|
|
Packit Service |
2781ba |
#endif
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
if (info->o == -1)
|
|
Packit Service |
2781ba |
g_warning ("%s: Could not open '%s': %s", G_STRFUNC, info->path, g_strerror(errno));
|
|
Packit Service |
2781ba |
tile_width = buffer->tile_storage->tile_width;
|
|
Packit Service |
2781ba |
tile_height = buffer->tile_storage->tile_height;
|
|
Packit Service |
2781ba |
g_object_get (buffer, "px-size", &bpp, NULL);
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
info->header.x = roi->x;
|
|
Packit Service |
2781ba |
info->header.y = roi->y;
|
|
Packit Service |
2781ba |
info->header.width = roi->width;
|
|
Packit Service |
2781ba |
info->header.height = roi->height;
|
|
Packit Service |
2781ba |
gegl_buffer_header_init (&info->header,
|
|
Packit Service |
2781ba |
tile_width,
|
|
Packit Service |
2781ba |
tile_height,
|
|
Packit Service |
2781ba |
bpp,
|
|
Packit Service |
2781ba |
buffer->tile_storage->format
|
|
Packit Service |
2781ba |
);
|
|
Packit Service |
2781ba |
info->header.next = (prediction += sizeof (GeglBufferHeader));
|
|
Packit Service |
2781ba |
info->tile_size = tile_width * tile_height * bpp;
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
g_assert (info->tile_size % 16 == 0);
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
GEGL_NOTE (GEGL_DEBUG_BUFFER_SAVE,
|
|
Packit Service |
2781ba |
"collecting list of tiles to be written");
|
|
Packit Service |
2781ba |
{
|
|
Packit Service |
2781ba |
gint z;
|
|
Packit Service |
2781ba |
gint factor = 1;
|
|
Packit Service |
2781ba |
int bufy = roi->y;
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
for (z = 0; z < 1; z++)
|
|
Packit Service |
2781ba |
{
|
|
Packit Service |
2781ba |
bufy = roi->y;
|
|
Packit Service |
2781ba |
while (bufy < roi->y + roi->height)
|
|
Packit Service |
2781ba |
{
|
|
Packit Service |
2781ba |
gint tiledy = roi->y + bufy;
|
|
Packit Service |
2781ba |
gint offsety = gegl_tile_offset (tiledy, tile_height);
|
|
Packit Service |
2781ba |
gint bufx = roi->x;
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
while (bufx < roi->x + roi->width)
|
|
Packit Service |
2781ba |
{
|
|
Packit Service |
2781ba |
gint tiledx = roi->x + bufx;
|
|
Packit Service |
2781ba |
gint offsetx = gegl_tile_offset (tiledx, tile_width);
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
gint tx = gegl_tile_indice (tiledx / factor, tile_width);
|
|
Packit Service |
2781ba |
gint ty = gegl_tile_indice (tiledy / factor, tile_height);
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
if (gegl_tile_source_exist (GEGL_TILE_SOURCE (buffer), tx, ty, z))
|
|
Packit Service |
2781ba |
{
|
|
Packit Service |
2781ba |
GeglBufferTile *entry;
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
GEGL_NOTE (GEGL_DEBUG_BUFFER_SAVE,
|
|
Packit Service |
2781ba |
"Found tile to save, tx, ty, z = %d, %d, %d",
|
|
Packit Service |
2781ba |
tx, ty, z);
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
entry = gegl_tile_entry_new (tx, ty, z);
|
|
Packit Service |
2781ba |
info->tiles = g_list_prepend (info->tiles, entry);
|
|
Packit Service |
2781ba |
info->entry_count++;
|
|
Packit Service |
2781ba |
}
|
|
Packit Service |
2781ba |
bufx += (tile_width - offsetx) * factor;
|
|
Packit Service |
2781ba |
}
|
|
Packit Service |
2781ba |
bufy += (tile_height - offsety) * factor;
|
|
Packit Service |
2781ba |
}
|
|
Packit Service |
2781ba |
factor *= 2;
|
|
Packit Service |
2781ba |
}
|
|
Packit Service |
2781ba |
GEGL_NOTE (GEGL_DEBUG_BUFFER_SAVE,
|
|
Packit Service |
2781ba |
"size of list of tiles to be written: %d",
|
|
Packit Service |
2781ba |
g_list_length (info->tiles));
|
|
Packit Service |
2781ba |
}
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
/* sort the list of tiles into zorder */
|
|
Packit Service |
2781ba |
info->tiles = g_list_sort (info->tiles, z_order_compare);
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
/* set the offset in the file each tile will be stored on */
|
|
Packit Service |
2781ba |
{
|
|
Packit Service |
2781ba |
GList *iter;
|
|
Packit Service |
2781ba |
gint predicted_offset = sizeof (GeglBufferHeader) +
|
|
Packit Service |
2781ba |
sizeof (GeglBufferTile) * (info->entry_count);
|
|
Packit Service |
2781ba |
for (iter = info->tiles; iter; iter = iter->next)
|
|
Packit Service |
2781ba |
{
|
|
Packit Service |
2781ba |
GeglBufferTile *entry = iter->data;
|
|
Packit Service |
2781ba |
entry->block.next = iter->next?
|
|
Packit Service |
2781ba |
(prediction += sizeof (GeglBufferTile)):0;
|
|
Packit Service |
2781ba |
entry->offset = predicted_offset;
|
|
Packit Service |
2781ba |
predicted_offset += info->tile_size;
|
|
Packit Service |
2781ba |
}
|
|
Packit Service |
2781ba |
}
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
/* save the header */
|
|
Packit Service |
2781ba |
{
|
|
Packit Service |
2781ba |
ssize_t ret = write (info->o, &info->header, sizeof (GeglBufferHeader));
|
|
Packit Service |
2781ba |
if (ret != -1)
|
|
Packit Service |
2781ba |
info->offset += ret;
|
|
Packit Service |
2781ba |
}
|
|
Packit Service |
2781ba |
g_assert (info->offset == info->header.next);
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
/* save the index */
|
|
Packit Service |
2781ba |
{
|
|
Packit Service |
2781ba |
GList *iter;
|
|
Packit Service |
2781ba |
for (iter = info->tiles; iter; iter = iter->next)
|
|
Packit Service |
2781ba |
{
|
|
Packit Service |
2781ba |
GeglBufferItem *item = iter->data;
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
write_block (info, &item->block);
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
}
|
|
Packit Service |
2781ba |
}
|
|
Packit Service |
2781ba |
write_block (info, NULL); /* terminate the index */
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
/* update header to point to start of new index (already done for
|
|
Packit Service |
2781ba |
* this serial saver, and the header is already written.
|
|
Packit Service |
2781ba |
*/
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
/* save each tile */
|
|
Packit Service |
2781ba |
{
|
|
Packit Service |
2781ba |
GList *iter;
|
|
Packit Service |
2781ba |
gint i = 0;
|
|
Packit Service |
2781ba |
for (iter = info->tiles; iter; iter = iter->next)
|
|
Packit Service |
2781ba |
{
|
|
Packit Service |
2781ba |
GeglBufferTile *entry = iter->data;
|
|
Packit Service |
2781ba |
guchar *data;
|
|
Packit Service |
2781ba |
GeglTile *tile;
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
tile = gegl_tile_source_get_tile (GEGL_TILE_SOURCE (buffer),
|
|
Packit Service |
2781ba |
entry->x,
|
|
Packit Service |
2781ba |
entry->y,
|
|
Packit Service |
2781ba |
entry->z);
|
|
Packit Service |
2781ba |
g_assert (tile);
|
|
Packit Service |
2781ba |
data = gegl_tile_get_data (tile);
|
|
Packit Service |
2781ba |
g_assert (data);
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
g_assert (info->offset == entry->offset);
|
|
Packit Service |
2781ba |
{
|
|
Packit Service |
2781ba |
ssize_t ret = write (info->o, data, info->tile_size);
|
|
Packit Service |
2781ba |
if (ret != -1)
|
|
Packit Service |
2781ba |
info->offset += ret;
|
|
Packit Service |
2781ba |
}
|
|
Packit Service |
2781ba |
gegl_tile_unref (tile);
|
|
Packit Service |
2781ba |
i++;
|
|
Packit Service |
2781ba |
}
|
|
Packit Service |
2781ba |
}
|
|
Packit Service |
2781ba |
save_info_destroy (info);
|
|
Packit Service |
2781ba |
}
|