summaryrefslogtreecommitdiffstats
path: root/src/display/drawing.cpp
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/display/drawing.cpp262
1 files changed, 262 insertions, 0 deletions
diff --git a/src/display/drawing.cpp b/src/display/drawing.cpp
new file mode 100644
index 0000000..c306095
--- /dev/null
+++ b/src/display/drawing.cpp
@@ -0,0 +1,262 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/**
+ * @file
+ * SVG drawing for display.
+ *//*
+ * Authors:
+ * Krzysztof KosiƄski <tweenk.pl@gmail.com>
+ * Johan Engelen <j.b.c.engelen@alumnus.utwente.nl>
+ *
+ * Copyright (C) 2011-2012 Authors
+ * Released under GNU GPL v2+, read the file 'COPYING' for more information.
+ */
+
+#include "display/drawing.h"
+#include "display/control/canvas-item-drawing.h"
+#include "nr-filter-gaussian.h"
+#include "nr-filter-types.h"
+
+//grayscale colormode:
+#include "cairo-templates.h"
+#include "drawing-context.h"
+
+
+namespace Inkscape {
+
+// hardcoded grayscale color matrix values as default
+static const gdouble grayscale_value_matrix[20] = {
+ 0.21, 0.72, 0.072, 0, 0,
+ 0.21, 0.72, 0.072, 0, 0,
+ 0.21, 0.72, 0.072, 0, 0,
+ 0 , 0 , 0 , 1, 0
+};
+
+Drawing::Drawing(Inkscape::CanvasItemDrawing *canvas_item_drawing)
+ : _canvas_item_drawing(canvas_item_drawing)
+ , _grayscale_colormatrix(std::vector<gdouble>(grayscale_value_matrix, grayscale_value_matrix + 20))
+{
+ // _canvas_item_drawing can be null. Used this way by Eraser tool.
+}
+
+Drawing::~Drawing()
+{
+ delete _root;
+}
+
+void
+Drawing::setRoot(DrawingItem *item)
+{
+ delete _root;
+ _root = item;
+ if (item) {
+ assert(item->_child_type == DrawingItem::CHILD_ORPHAN);
+ item->_child_type = DrawingItem::CHILD_ROOT;
+ }
+}
+
+RenderMode
+Drawing::renderMode() const
+{
+ return _exact ? RenderMode::NORMAL : _rendermode;
+}
+ColorMode
+Drawing::colorMode() const
+{
+ return (outline() || _exact) ? ColorMode::NORMAL : _colormode;
+}
+bool
+Drawing::outline() const
+{
+ return renderMode() == RenderMode::OUTLINE;
+}
+bool
+Drawing::visibleHairlines() const
+{
+ return renderMode() == RenderMode::VISIBLE_HAIRLINES;
+}
+bool
+Drawing::outlineOverlay() const
+{
+ return renderMode() == RenderMode::OUTLINE_OVERLAY;
+}
+bool
+Drawing::renderFilters() const
+{
+ return renderMode() == RenderMode::NORMAL || renderMode() == RenderMode::VISIBLE_HAIRLINES || renderMode() == RenderMode::OUTLINE_OVERLAY;
+}
+int
+Drawing::blurQuality() const
+{
+ if (renderMode() == RenderMode::NORMAL) {
+ return _exact ? BLUR_QUALITY_BEST : _blur_quality;
+ } else {
+ return BLUR_QUALITY_WORST;
+ }
+}
+int
+Drawing::filterQuality() const
+{
+ if (renderMode() == RenderMode::NORMAL) {
+ return _exact ? Filters::FILTER_QUALITY_BEST : _filter_quality;
+ } else {
+ return Filters::FILTER_QUALITY_WORST;
+ }
+}
+
+void
+Drawing::setRenderMode(RenderMode mode)
+{
+ _rendermode = mode;
+}
+void
+Drawing::setColorMode(ColorMode mode)
+{
+ _colormode = mode;
+}
+void
+Drawing::setBlurQuality(int q)
+{
+ _blur_quality = q;
+}
+void
+Drawing::setFilterQuality(int q)
+{
+ _filter_quality = q;
+}
+void
+Drawing::setExact(bool e)
+{
+ _exact = e;
+}
+
+void Drawing::setOutlineSensitive(bool e) { _outline_sensitive = e; };
+
+Geom::OptIntRect const &
+Drawing::cacheLimit() const
+{
+ return _cache_limit;
+}
+void
+Drawing::setCacheLimit(Geom::OptIntRect const &r)
+{
+ _cache_limit = r;
+ for (auto _cached_item : _cached_items) {
+ _cached_item->_markForUpdate(DrawingItem::STATE_CACHE, false);
+ }
+}
+void
+Drawing::setCacheBudget(size_t bytes)
+{
+ _cache_budget = bytes;
+ _pickItemsForCaching();
+}
+
+void
+Drawing::setGrayscaleMatrix(gdouble value_matrix[20]) {
+ _grayscale_colormatrix = Filters::FilterColorMatrix::ColorMatrixMatrix(
+ std::vector<gdouble> (value_matrix, value_matrix + 20) );
+}
+
+void
+Drawing::update(Geom::IntRect const &area, unsigned flags, unsigned reset)
+{
+ if (_root) {
+ auto ctx = _canvas_item_drawing ? _canvas_item_drawing->get_context() : UpdateContext();
+ _root->update(area, ctx, flags, reset);
+ }
+ if ((flags & DrawingItem::STATE_CACHE) || (flags & DrawingItem::STATE_ALL)) {
+ // process the updated cache scores
+ _pickItemsForCaching();
+ }
+}
+
+void
+Drawing::render(DrawingContext &dc, Geom::IntRect const &area, unsigned flags, int antialiasing)
+{
+ if (_root) {
+ int prev_a = _root->_antialias;
+ if(antialiasing >= 0)
+ _root->setAntialiasing(antialiasing);
+ _root->render(dc, area, flags);
+ _root->setAntialiasing(prev_a);
+ }
+
+ if (colorMode() == ColorMode::GRAYSCALE) {
+ // apply grayscale filter on top of everything
+ cairo_surface_t *input = dc.rawTarget();
+ cairo_surface_t *out = ink_cairo_surface_create_identical(input);
+ ink_cairo_surface_filter(input, out, _grayscale_colormatrix);
+ Geom::Point origin = dc.targetLogicalBounds().min();
+ dc.setSource(out, origin[Geom::X], origin[Geom::Y]);
+ dc.setOperator(CAIRO_OPERATOR_SOURCE);
+ dc.paint();
+ dc.setOperator(CAIRO_OPERATOR_OVER);
+
+ cairo_surface_destroy(out);
+ }
+}
+
+DrawingItem *
+Drawing::pick(Geom::Point const &p, double delta, unsigned flags)
+{
+ if (_root) {
+ return _root->pick(p, delta, flags);
+ } else {
+ std::cerr << "Drawing::pick: _root is null!" << std::endl;
+ }
+ return nullptr;
+}
+
+void
+Drawing::_pickItemsForCaching()
+{
+ size_t used = 0;
+ CandidateList::iterator i;
+ for (i = _candidate_items.begin(); i != _candidate_items.end(); ++i) {
+ if (used + i->cache_size > _cache_budget) break;
+ used += i->cache_size;
+ }
+
+ std::set<DrawingItem*> to_cache;
+ for (CandidateList::iterator j = _candidate_items.begin(); j != i; ++j) {
+ j->item->setCached(true);
+ to_cache.insert(j->item);
+ }
+ // Everything which is now in _cached_items but not in to_cache must be uncached
+ // Note that calling setCached on an item modifies _cached_items
+ // TODO: find a way to avoid the set copy
+ std::set<DrawingItem*> to_uncache;
+ std::set_difference(_cached_items.begin(), _cached_items.end(),
+ to_cache.begin(), to_cache.end(),
+ std::inserter(to_uncache, to_uncache.end()));
+ for (auto j : to_uncache) {
+ j->setCached(false);
+ }
+}
+
+/*
+ * Return average color over area. Used by Calligraphic, Dropper, and Spray tools.
+ */
+void
+Drawing::average_color(Geom::IntRect const &area, double &R, double &G, double &B, double &A)
+{
+ auto surface = Cairo::ImageSurface::create(Cairo::FORMAT_ARGB32, area.width(), area.height());
+ Inkscape::DrawingContext dc(surface->cobj(), area.min());
+ render(dc, area);
+
+ ink_cairo_surface_average_color_premul(surface->cobj(), R, G, B, A);
+}
+
+
+} // end 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 :