diff options
| author | Tavmjong Bah <tavmjong@free.fr> | 2015-09-20 13:54:59 +0000 |
|---|---|---|
| committer | tavmjong-free <tavmjong@free.fr> | 2015-09-20 13:54:59 +0000 |
| commit | 27ca90885f3f4dde9886780ff0cc0f40a34f4e7e (patch) | |
| tree | 8370fb902df688ad98bcd091aa40f0192d9a3437 /src | |
| parent | packaging/macosx: fix for bug #1497020 (Inkscape.app (0.91) crashes when atte... (diff) | |
| download | inkscape-27ca90885f3f4dde9886780ff0cc0f40a34f4e7e.tar.gz inkscape-27ca90885f3f4dde9886780ff0cc0f40a34f4e7e.zip | |
Crude partial implementation of feTile filter primitive.
(bzr r14377)
Diffstat (limited to 'src')
| -rw-r--r-- | src/display/nr-filter-image.cpp | 2 | ||||
| -rw-r--r-- | src/display/nr-filter-offset.cpp | 4 | ||||
| -rw-r--r-- | src/display/nr-filter-slot.cpp | 21 | ||||
| -rw-r--r-- | src/display/nr-filter-slot.h | 8 | ||||
| -rw-r--r-- | src/display/nr-filter-tile.cpp | 99 | ||||
| -rw-r--r-- | src/display/nr-filter-tile.h | 1 |
6 files changed, 130 insertions, 5 deletions
diff --git a/src/display/nr-filter-image.cpp b/src/display/nr-filter-image.cpp index 179ba0e0a..af89d98e0 100644 --- a/src/display/nr-filter-image.cpp +++ b/src/display/nr-filter-image.cpp @@ -56,6 +56,8 @@ void FilterImage::render_cairo(FilterSlot &slot) // Note: viewport calculation in non-trivial. Do not rely // on get_matrix_primitiveunits2pb(). Geom::Rect vp = filter_primitive_area( slot.get_units() ); + slot.set_primitive_area(_output, vp); // Needed for tiling + double feImageX = vp.min()[Geom::X]; double feImageY = vp.min()[Geom::Y]; double feImageWidth = vp.width(); diff --git a/src/display/nr-filter-offset.cpp b/src/display/nr-filter-offset.cpp index af1081abe..93bab7d39 100644 --- a/src/display/nr-filter-offset.cpp +++ b/src/display/nr-filter-offset.cpp @@ -37,9 +37,11 @@ void FilterOffset::render_cairo(FilterSlot &slot) cairo_surface_t *out = ink_cairo_surface_create_identical(in); // color_interpolation_filters for out same as in. See spec (DisplacementMap). copy_cairo_surface_ci(in, out); - cairo_t *ct = cairo_create(out); + Geom::Rect vp = filter_primitive_area( slot.get_units() ); + slot.set_primitive_area(_output, vp); // Needed for tiling + // Handle bounding box case double x = dx; double y = dy; diff --git a/src/display/nr-filter-slot.cpp b/src/display/nr-filter-slot.cpp index e4c2f048e..a6e0c5c4e 100644 --- a/src/display/nr-filter-slot.cpp +++ b/src/display/nr-filter-slot.cpp @@ -232,6 +232,27 @@ void FilterSlot::set(int slot_nr, cairo_surface_t *surface) _last_out = slot_nr; } +void FilterSlot::set_primitive_area(int slot_nr, Geom::Rect &area) +{ + if (slot_nr == NR_FILTER_SLOT_NOT_SET) + slot_nr = NR_FILTER_UNNAMED_SLOT; + + _primitiveAreas[slot_nr] = area; +} + +Geom::Rect FilterSlot::get_primitive_area(int slot_nr) +{ + if (slot_nr == NR_FILTER_SLOT_NOT_SET) + slot_nr = _last_out; + + PrimitiveAreaMap::iterator s = _primitiveAreas.find(slot_nr); + + if (s == _primitiveAreas.end()) { + return *(_units.get_filter_area()); + } + return s->second; +} + int FilterSlot::get_slot_count() { return _slots.size(); diff --git a/src/display/nr-filter-slot.h b/src/display/nr-filter-slot.h index 987dedfd1..166b2e718 100644 --- a/src/display/nr-filter-slot.h +++ b/src/display/nr-filter-slot.h @@ -54,6 +54,9 @@ public: cairo_surface_t *get_result(int slot_nr); + void set_primitive_area(int slot, Geom::Rect &area); + Geom::Rect get_primitive_area(int slot); + /** Returns the number of slots in use. */ int get_slot_count(); @@ -75,6 +78,11 @@ public: private: typedef std::map<int, cairo_surface_t *> SlotMap; SlotMap _slots; + + // We need to keep track of the primitive area as this is needed in feTile + typedef std::map<int, Geom::Rect> PrimitiveAreaMap; + PrimitiveAreaMap _primitiveAreas; + DrawingItem *_item; //Geom::Rect _source_bbox; ///< bounding box of source graphic surface diff --git a/src/display/nr-filter-tile.cpp b/src/display/nr-filter-tile.cpp index 93ca50210..913812828 100644 --- a/src/display/nr-filter-tile.cpp +++ b/src/display/nr-filter-tile.cpp @@ -10,6 +10,8 @@ */ #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" @@ -30,16 +32,105 @@ FilterTile::~FilterTile() void FilterTile::render_cairo(FilterSlot &slot) { + // FIX ME! static bool tile_warning = false; - -//IMPLEMENT ME! if (!tile_warning) { - g_warning("Renderer for feTile is not implemented."); + g_warning("Renderer for feTile has non-optimal implementation, expect slowness and bugs."); tile_warning = true; } + // Fixing isn't so easy as the Inkscape renderer breaks the canvas into "rendering" tiles for + // faster rendering. (The "rendering" tiles are not the same as the tiles in this primitive.) + // Only if the the feTile tile source falls inside the current "rendering" tile will the tile + // image be available. + + // This input source contains only the "rendering" tile. cairo_surface_t *in = slot.getcairo(_input); - slot.set(_output, in); + + // 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) +{ + // We need to enlarge enough to get tile source... we don't the area of the source tile in this + // function so we guess. This is VERY inefficient. + Geom::Point enlarge(200, 200); + enlarge *= trans; + area.expandBy( enlarge[Geom::X] < 100 ? 100: enlarge[Geom::X] ); } double FilterTile::complexity(Geom::Affine const &) diff --git a/src/display/nr-filter-tile.h b/src/display/nr-filter-tile.h index 29087f2d6..239ecff4b 100644 --- a/src/display/nr-filter-tile.h +++ b/src/display/nr-filter-tile.h @@ -26,6 +26,7 @@ public: virtual ~FilterTile(); virtual void render_cairo(FilterSlot &slot); + virtual void area_enlarge(Geom::IntRect &area, Geom::Affine const &trans); virtual double complexity(Geom::Affine const &ctm); }; |
