static GeglTile * get_tile (GeglTileSource *gegl_tile_source, gint x, gint y, gint z) { GeglTileSource *source = ((GeglTileHandler *) gegl_tile_source)->source; GeglTileHandlerZoom *zoom = (GeglTileHandlerZoom *) gegl_tile_source; GeglTile *tile = NULL; const Babl *format = gegl_tile_backend_get_format (zoom->backend); GeglTileStorage *tile_storage; gint tile_width; gint tile_height; gint tile_size; if (source) tile = gegl_tile_source_get_tile (source, x, y, z); if (tile) return tile; if (z == 0)/* at base level with no tile found->send null, and shared empty tile will be used instead */ { return NULL; } tile_storage = _gegl_tile_handler_get_tile_storage ((GeglTileHandler *) zoom); if (z > tile_storage->seen_zoom) tile_storage->seen_zoom = z; g_object_get (zoom->backend, "tile-width", &tile_width, "tile-height", &tile_height, "tile-size", &tile_size, NULL); { gint i, j; GeglTile *source_tile[2][2] = { { NULL, NULL }, { NULL, NULL } }; for (i = 0; i < 2; i++) for (j = 0; j < 2; j++) { /* we get the tile from ourselves, to make successive rescales work * correctly */ source_tile[i][j] = gegl_tile_source_get_tile (gegl_tile_source, x * 2 + i, y * 2 + j, z - 1); } if (source_tile[0][0] == NULL && source_tile[0][1] == NULL && source_tile[1][0] == NULL && source_tile[1][1] == NULL) { return NULL; /* no data from level below, return NULL and let GeglTileHandlerEmpty fill in the shared empty tile */ } g_assert (tile == NULL); tile = gegl_tile_handler_create_tile (GEGL_TILE_HANDLER (zoom), x, y, z); gegl_tile_lock (tile); for (i = 0; i < 2; i++) for (j = 0; j < 2; j++) { if (source_tile[i][j]) { set_half (tile, source_tile[i][j], tile_width, tile_height, format, i, j); gegl_tile_unref (source_tile[i][j]); } else { set_blank (tile, tile_width, tile_height, format, i, j); } } gegl_tile_unlock (tile); } return tile; }
static GeglTile * gimp_tile_handler_projection_validate (GeglTileSource *source, GeglTile *tile, gint x, gint y) { GimpTileHandlerProjection *projection; cairo_region_t *tile_region; cairo_rectangle_int_t tile_rect; projection = GIMP_TILE_HANDLER_PROJECTION (source); if (cairo_region_is_empty (projection->dirty_region)) return tile; tile_region = cairo_region_copy (projection->dirty_region); tile_rect.x = x * projection->tile_width; tile_rect.y = y * projection->tile_height; tile_rect.width = projection->tile_width; tile_rect.height = projection->tile_height; cairo_region_intersect_rectangle (tile_region, &tile_rect); if (! cairo_region_is_empty (tile_region)) { gint tile_bpp; gint tile_stride; gint n_rects; gint i; if (! tile) tile = gegl_tile_handler_create_tile (GEGL_TILE_HANDLER (source), x, y, 0); cairo_region_subtract_rectangle (projection->dirty_region, &tile_rect); tile_bpp = babl_format_get_bytes_per_pixel (projection->format); tile_stride = tile_bpp * projection->tile_width; gegl_tile_lock (tile); n_rects = cairo_region_num_rectangles (tile_region); #if 0 g_printerr ("%d ", n_rects); #endif for (i = 0; i < n_rects; i++) { cairo_rectangle_int_t blit_rect; cairo_region_get_rectangle (tile_region, i, &blit_rect); #if 0 g_printerr ("constructing projection at %d %d %d %d\n", blit_rect.x, blit_rect.y, blit_rect.width, blit_rect.height); #endif gegl_node_blit (projection->graph, 1.0, GEGL_RECTANGLE (blit_rect.x, blit_rect.y, blit_rect.width, blit_rect.height), projection->format, gegl_tile_get_data (tile) + (blit_rect.y % projection->tile_height) * tile_stride + (blit_rect.x % projection->tile_width) * tile_bpp, tile_stride, GEGL_ABYSS_NONE); } gegl_tile_unlock (tile); } cairo_region_destroy (tile_region); return tile; }