예제 #1
0
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);
}
예제 #2
0
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);
}
예제 #3
0
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);
    }
}