void FilterTurbulence::render_cairo(FilterSlot &slot) { cairo_surface_t *input = slot.getcairo(_input); cairo_surface_t *out = ink_cairo_surface_create_same_size(input, CAIRO_CONTENT_COLOR_ALPHA); if (!gen->ready()) { Geom::Point ta(fTileX, fTileY); Geom::Point tb(fTileX + fTileWidth, fTileY + fTileHeight); gen->init(seed, Geom::Rect(ta, tb), Geom::Point(XbaseFrequency, YbaseFrequency), stitchTiles, type == TURBULENCE_FRACTALNOISE, numOctaves); } Geom::Affine unit_trans = slot.get_units().get_matrix_primitiveunits2pb().inverse(); Geom::Rect slot_area = slot.get_slot_area(); double x0 = slot_area.min()[Geom::X]; double y0 = slot_area.min()[Geom::Y]; ink_cairo_surface_synthesize(out, Turbulence(*gen, unit_trans, x0, y0)); cairo_surface_mark_dirty(out); slot.set(_output, out); cairo_surface_destroy(out); }
void FilterFlood::render_cairo(FilterSlot &slot) { cairo_surface_t *input = slot.getcairo(_input); double r = SP_RGBA32_R_F(color); double g = SP_RGBA32_G_F(color); double b = SP_RGBA32_B_F(color); double a = opacity; #if defined(HAVE_LIBLCMS1) || defined(HAVE_LIBLCMS2) if (icc) { guchar ru, gu, bu; icc_color_to_sRGB(icc, &ru, &gu, &bu); r = SP_COLOR_U_TO_F(ru); g = SP_COLOR_U_TO_F(gu); b = SP_COLOR_U_TO_F(bu); } #endif cairo_surface_t *out = ink_cairo_surface_create_same_size(input, CAIRO_CONTENT_COLOR_ALPHA); // Get filter primitive area in user units Geom::Rect fp = filter_primitive_area( slot.get_units() ); // Convert to Cairo units Geom::Rect fp_cairo = fp * slot.get_units().get_matrix_user2pb(); // Get area in slot (tile to fill) Geom::Rect sa = slot.get_slot_area(); // Get overlap Geom::OptRect optoverlap = intersect( fp_cairo, sa ); if( optoverlap ) { Geom::Rect overlap = *optoverlap; double dx = fp_cairo.min()[Geom::X] - sa.min()[Geom::X]; double dy = fp_cairo.min()[Geom::Y] - sa.min()[Geom::Y]; if( dx < 0.0 ) dx = 0.0; if( dy < 0.0 ) dy = 0.0; cairo_t *ct = cairo_create(out); cairo_set_source_rgba(ct, r, g, b, a); cairo_set_operator(ct, CAIRO_OPERATOR_SOURCE); cairo_rectangle(ct, dx, dy, overlap.width(), overlap.height() ); cairo_fill(ct); cairo_destroy(ct); } slot.set(_output, out); cairo_surface_destroy(out); }
void FilterTile::render_cairo(FilterSlot &slot) { static bool tile_warning = false; //IMPLEMENT ME! if (!tile_warning) { g_warning("Renderer for feTile is not implemented."); tile_warning = true; } cairo_surface_t *in = slot.getcairo(_input); slot.set(_output, in); }
void FilterTile::render_cairo(FilterSlot &slot) { // FIX ME! static bool tile_warning = false; if (!tile_warning) { 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); // 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); } }