diff options
Diffstat (limited to '')
-rw-r--r-- | src/display/nr-filter-tile.cpp | 141 |
1 files changed, 141 insertions, 0 deletions
diff --git a/src/display/nr-filter-tile.cpp b/src/display/nr-filter-tile.cpp new file mode 100644 index 0000000..4605dde --- /dev/null +++ b/src/display/nr-filter-tile.cpp @@ -0,0 +1,141 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * feTile filter primitive renderer + * + * Authors: + * Felipe CorrĂȘa da Silva Sanches <juca@members.fsf.org> + * + * Copyright (C) 2007 authors + * + * Released under GNU GPL v2+, read the file 'COPYING' for more information. + */ + +#include <glib.h> + +#include "display/cairo-utils.h" +#include "display/nr-filter-tile.h" +#include "display/nr-filter-slot.h" +#include "display/nr-filter-units.h" + +namespace Inkscape { +namespace Filters { + +FilterTile::FilterTile() += default; + +FilterPrimitive * FilterTile::create() { + return new FilterTile(); +} + +FilterTile::~FilterTile() += default; + +void FilterTile::render_cairo(FilterSlot &slot) +{ + // This input source contains only the "rendering" tile. + cairo_surface_t *in = slot.getcairo(_input); + + // For debugging + // static int i = 0; + // ++i; + // std::stringstream filename; + // filename << "dump." << i << ".png"; + // cairo_surface_write_to_png( in, filename.str().c_str() ); + + // This is the feTile source area as determined by the input primitive area (see SVG spec). + Geom::Rect tile_area = slot.get_primitive_area(_input); + + if( tile_area.width() == 0.0 || tile_area.height() == 0.0 ) { + + slot.set(_output, in); + std::cerr << "FileTile::render_cairo: tile has zero width or height" << std::endl; + + } else { + + cairo_surface_t *out = ink_cairo_surface_create_identical(in); + // color_interpolation_filters for out same as in. + copy_cairo_surface_ci(in, out); + cairo_t *ct = cairo_create(out); + + // The rectangle of the "rendering" tile. + Geom::Rect sa = slot.get_slot_area(); + + Geom::Affine trans = slot.get_units().get_matrix_user2pb(); + + // Create feTile tile ---------------- + + // Get tile area in pixbuf units (tile transformed). + Geom::Rect tt = tile_area * trans; + + // Shift between "rendering" tile and feTile tile + Geom::Point shift = sa.min() - tt.min(); + + // Create feTile tile surface + cairo_surface_t *tile = cairo_surface_create_similar(in, cairo_surface_get_content(in), + tt.width(), tt.height()); + cairo_t *ct_tile = cairo_create(tile); + cairo_set_source_surface(ct_tile, in, shift[Geom::X], shift[Geom::Y]); + cairo_paint(ct_tile); + + // Paint tiles ------------------ + + // For debugging + // std::stringstream filename; + // filename << "tile." << i << ".png"; + // cairo_surface_write_to_png( tile, filename.str().c_str() ); + + // Determine number of feTile rows and columns + Geom::Rect pr = filter_primitive_area( slot.get_units() ); + int tile_cols = ceil( pr.width() / tile_area.width() ); + int tile_rows = ceil( pr.height() / tile_area.height() ); + + // Do tiling (TO DO: restrict to slot area.) + for( int col=0; col < tile_cols; ++col ) { + for( int row=0; row < tile_rows; ++row ) { + + Geom::Point offset( col*tile_area.width(), row*tile_area.height() ); + offset *= trans; + offset[Geom::X] -= trans[4]; + offset[Geom::Y] -= trans[5]; + + cairo_set_source_surface(ct, tile, offset[Geom::X], offset[Geom::Y]); + cairo_paint(ct); + } + } + slot.set(_output, out); + + // Clean up + cairo_destroy(ct); + cairo_surface_destroy(out); + cairo_destroy(ct_tile); + cairo_surface_destroy(tile); + } +} + +void FilterTile::area_enlarge(Geom::IntRect &area, Geom::Affine const &trans) +{ + // Set to very large rectangle so we get tile source. It will be clipped later. + + // Note, setting to infinite using Geom::IntRect::infinite() causes overflow/underflow problems. + Geom::IntCoord max = std::numeric_limits<Geom::IntCoord>::max()/4; + area = Geom::IntRect(-max,-max,max,max); +} + +double FilterTile::complexity(Geom::Affine const &) +{ + return 1.0; +} + +} /* namespace Filters */ +} /* namespace Inkscape */ + +/* + Local Variables: + mode:c++ + c-file-style:"stroustrup" + c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +)) + indent-tabs-mode:nil + fill-column:99 + End: +*/ +// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 : |