nr-filter.cpp revision 1b6b718bf7f0d5312e573dfb4b25281f5aee85ad
/*
* SVG filters rendering
*
* Author:
* Niko Kiirala <niko@kiirala.com>
*
* Copyright (C) 2006-2008 Niko Kiirala
*
* Released under GNU GPL, read the file 'COPYING' for more information
*/
#include <glib.h>
#include <cmath>
#include <cstring>
#include <string>
#include <cairo.h>
#include "display/nr-filter.h"
#include "display/nr-filter-primitive.h"
#include "display/nr-filter-slot.h"
#include "display/nr-filter-types.h"
#include "display/nr-filter-units.h"
#include "display/nr-filter-blend.h"
#include "display/nr-filter-composite.h"
#include "display/nr-filter-convolve-matrix.h"
#include "display/nr-filter-colormatrix.h"
#include "display/nr-filter-component-transfer.h"
#include "display/nr-filter-diffuselighting.h"
#include "display/nr-filter-displacement-map.h"
#include "display/nr-filter-flood.h"
#include "display/nr-filter-gaussian.h"
#include "display/nr-filter-image.h"
#include "display/nr-filter-merge.h"
#include "display/nr-filter-morphology.h"
#include "display/nr-filter-offset.h"
#include "display/nr-filter-specularlighting.h"
#include "display/nr-filter-tile.h"
#include "display/nr-filter-turbulence.h"
#include "display/nr-arena.h"
#include "display/nr-arena-item.h"
#include "svg/svg-length.h"
#include "sp-filter-units.h"
#include "preferences.h"
#include "round.h"
#endif
namespace Inkscape {
namespace Filters {
using Geom::X;
using Geom::Y;
{
_common_init();
}
{
if (n > 0) _primitive.reserve(n);
_common_init();
}
void Filter::_common_init() {
_slot_count = 1;
// Having "not set" here as value means the output of last filter
// primitive will be used as output of this filter
// These are the default values for filter region,
// as specified in SVG standard
// NB: SVGLength.set takes prescaled percent values: -.10 means -10%
// Filter resolution, negative value here stands for "automatic"
_x_pixels = -1.0;
_y_pixels = -1.0;
}
{
}
int Filter::render(NRArenaItem const *item, cairo_t *bgct, NRRectL const *bgarea, cairo_t *graphic, NRRectL const *area)
{
if (_primitive.empty()) {
// when no primitives are defined, clear source graphic
cairo_set_source_rgba(graphic, 0,0,0,0);
return 1;
}
{
if (maybe_bbox.isEmpty()) {
// Code below needs a bounding box
return 1;
}
item_bbox = *maybe_bbox;
}
if (item_bbox.hasZeroArea()) {
// It's no use to try and filter an empty object.
return 1;
}
// zero resolution - clear source graphic and return
cairo_set_source_rgba(graphic, 0,0,0,0);
return 1;
}
if (_x_pixels > 0) {
units.set_automatic_resolution(false);
}
else {
units.set_automatic_resolution(true);
}
units.set_paraller(false);
for (unsigned i = 0 ; i < _primitive.size() ; i++) {
units.set_paraller(true);
break;
}
}
FilterSlot slot(const_cast<NRArenaItem*>(item), bgct, bgarea, cairo_get_group_target(graphic), area, units);
for (unsigned i = 0 ; i < _primitive.size() ; i++) {
}
return 0;
}
}
}
for (unsigned i = 0 ; i < _primitive.size() ; i++) {
}
/*
TODO: something. See images at the bottom of filters.svg with medium-low
filtering quality.
Inkscape::Preferences *prefs = Inkscape::Preferences::get();
FilterQuality const filterquality = (FilterQuality)prefs->getInt("/options/filterquality/value");
if (_x_pixels <= 0 && (filterquality == FILTER_QUALITY_BEST ||
filterquality == FILTER_QUALITY_BETTER)) {
return;
}
Geom::Rect item_bbox;
Geom::OptRect maybe_bbox = item->item_bbox;
if (maybe_bbox.isEmpty()) {
// Code below needs a bounding box
return;
}
item_bbox = *maybe_bbox;
std::pair<double,double> res_low
= _filter_resolution(item_bbox, item->ctm, filterquality);
//std::pair<double,double> res_full
// = _filter_resolution(item_bbox, item->ctm, FILTER_QUALITY_BEST);
double pixels_per_block = fmax(item_bbox.width() / res_low.first,
item_bbox.height() / res_low.second);
bbox.x0 -= (int)pixels_per_block;
bbox.x1 += (int)pixels_per_block;
bbox.y0 -= (int)pixels_per_block;
bbox.y1 += (int)pixels_per_block;
*/
}
// Modifying empty bounding boxes confuses rest of the renderer, so
// let's not do that.
}
{
/* TODO: fetch somehow the object ex and em lengths */
} else {
}
} else {
}
} else {
}
} else {
}
} else if (_filter_units == SP_FILTER_UNITS_USERSPACEONUSE) {
/* TODO: make sure bbox and fe region are in same coordinate system */
} else {
g_warning("Error in Inkscape::Filters::Filter::filter_effect_area: unrecognized value of _filter_units");
}
return area;
}
/* Constructor table holds pointers to static methods returning filter
* primitives. This table is indexed with FilterPrimitiveType, so that
* for example method in _constructor[NR_FILTER_GAUSSIANBLUR]
* returns a filter object of type Inkscape::Filters::FilterGaussian.
*/
typedef FilterPrimitive*(*FilterConstructor)();
void Filter::_create_constructor_table()
{
// Constructor table won't change in run-time, so no need to recreate
static bool created = false;
if(created) return;
/* Some filter classes are not implemented yet.
Some of them still have only boilerplate code.*/
created = true;
}
{
// Check that we can create a new filter of specified type
return -1;
return handle;
}
{
// Check that target is valid primitive inside this filter
if (target < 0) return -1;
// Check that we can create a new filter of specified type
return -1;
delete _primitive[target];
return target;
}
return _primitive[handle];
}
void Filter::clear_primitives()
{
for (unsigned i = 0 ; i < _primitive.size() ; i++) {
delete _primitive[i];
}
_primitive.clear();
}
{
}
{
}
{
}
{
}
if (pixels > 0) {
}
}
}
}
void Filter::reset_resolution() {
_x_pixels = -1;
_y_pixels = -1;
}
int limit = -1;
switch (quality) {
case FILTER_QUALITY_WORST:
limit = 32;
break;
case FILTER_QUALITY_WORSE:
limit = 64;
break;
case FILTER_QUALITY_NORMAL:
limit = 256;
break;
case FILTER_QUALITY_BETTER:
case FILTER_QUALITY_BEST:
default:
break;
}
return limit;
}
FilterQuality const filterquality) const
{
if (_x_pixels > 0) {
double y_len;
if (_y_pixels > 0) {
} else {
}
} else {
}
else {
}
}
}
return resolution;
}
} /* 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 :