From 267299811df952d08324a39008f52c19641de9e0 Mon Sep 17 00:00:00 2001 From: Tavmjong Bah Date: Tue, 30 Jan 2018 09:33:01 +0100 Subject: Move classes derived from SPObject to own directory. A lot of header clean-up. --- src/sp-hatch.cpp | 739 ------------------------------------------------------- 1 file changed, 739 deletions(-) delete mode 100644 src/sp-hatch.cpp (limited to 'src/sp-hatch.cpp') diff --git a/src/sp-hatch.cpp b/src/sp-hatch.cpp deleted file mode 100644 index f1958a53b..000000000 --- a/src/sp-hatch.cpp +++ /dev/null @@ -1,739 +0,0 @@ -/** - * @file - * SVG implementation - */ -/* - * Authors: - * Tomasz Boczkowski - * Jon A. Cruz - * - * Copyright (C) 2014 Tomasz Boczkowski - * - * Released under GNU GPL, read the file 'COPYING' for more information - */ - -#include "sp-hatch.h" - -#include -#include - -#include <2geom/transforms.h> -#include - -#include "bad-uri-exception.h" -#include "svg/svg.h" -#include "display/cairo-utils.h" -#include "display/drawing-context.h" -#include "display/drawing-surface.h" -#include "display/drawing.h" -#include "display/drawing-pattern.h" -#include "attributes.h" -#include "document-private.h" -#include "sp-hatch-path.h" - -SPHatch::SPHatch() - : SPPaintServer(), - href(), - ref(NULL), // avoiding 'this' in initializer list - _hatchUnits(UNITS_OBJECTBOUNDINGBOX), - _hatchUnits_set(false), - _hatchContentUnits(UNITS_USERSPACEONUSE), - _hatchContentUnits_set(false), - _hatchTransform(Geom::identity()), - _hatchTransform_set(false), - _x(), - _y(), - _pitch(), - _rotate(), - _modified_connection(), - _display() -{ - ref = new SPHatchReference(this); - ref->changedSignal().connect(sigc::mem_fun(this, &SPHatch::_onRefChanged)); - - // TODO check that these should start already as unset: - _x.unset(); - _y.unset(); - _pitch.unset(); - _rotate.unset(); -} - -SPHatch::~SPHatch() { -} - -void SPHatch::build(SPDocument* doc, Inkscape::XML::Node* repr) -{ - SPPaintServer::build(doc, repr); - - readAttr("hatchUnits"); - readAttr("hatchContentUnits"); - readAttr("hatchTransform"); - readAttr("x"); - readAttr("y"); - readAttr("pitch"); - readAttr("rotate"); - readAttr("xlink:href"); - readAttr( "style" ); - - // Register ourselves - doc->addResource("hatch", this); -} - -void SPHatch::release() -{ - if (document) { - // Unregister ourselves - document->removeResource("hatch", this); - } - - std::vector children(hatchPaths()); - for (ViewIterator view_iter = _display.begin(); view_iter != _display.end(); ++view_iter) { - for (ChildIterator child_iter = children.begin(); child_iter != children.end(); ++child_iter) { - SPHatchPath *child = *child_iter; - child->hide(view_iter->key); - } - delete view_iter->arenaitem; - view_iter->arenaitem = NULL; - } - - if (ref) { - _modified_connection.disconnect(); - ref->detach(); - delete ref; - ref = NULL; - } - - SPPaintServer::release(); -} - -void SPHatch::child_added(Inkscape::XML::Node* child, Inkscape::XML::Node* ref) -{ - SPObject::child_added(child, ref); - - SPHatchPath *path_child = dynamic_cast(document->getObjectByRepr(child)); - - if (path_child) { - for (ViewIterator iter = _display.begin(); iter != _display.end(); ++iter) { - Geom::OptInterval extents = _calculateStripExtents(iter->bbox); - Inkscape::DrawingItem *ac = path_child->show(iter->arenaitem->drawing(), iter->key, extents); - - path_child->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG); - if (ac) { - iter->arenaitem->prependChild(ac); - } - } - } - //FIXME: notify all hatches that refer to this child set -} - -void SPHatch::set(unsigned int key, const gchar* value) -{ - switch (key) { - case SP_ATTR_HATCHUNITS: - if (value) { - if (!strcmp(value, "userSpaceOnUse")) { - _hatchUnits = UNITS_USERSPACEONUSE; - } else { - _hatchUnits = UNITS_OBJECTBOUNDINGBOX; - } - - _hatchUnits_set = true; - } else { - _hatchUnits_set = false; - } - - requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG); - break; - - case SP_ATTR_HATCHCONTENTUNITS: - if (value) { - if (!strcmp(value, "userSpaceOnUse")) { - _hatchContentUnits = UNITS_USERSPACEONUSE; - } else { - _hatchContentUnits = UNITS_OBJECTBOUNDINGBOX; - } - - _hatchContentUnits_set = true; - } else { - _hatchContentUnits_set = false; - } - - requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG); - break; - - case SP_ATTR_HATCHTRANSFORM: { - Geom::Affine t; - - if (value && sp_svg_transform_read(value, &t)) { - _hatchTransform = t; - _hatchTransform_set = true; - } else { - _hatchTransform = Geom::identity(); - _hatchTransform_set = false; - } - - requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG); - break; - } - case SP_ATTR_X: - _x.readOrUnset(value); - requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG); - break; - - case SP_ATTR_Y: - _y.readOrUnset(value); - requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG); - break; - - case SP_ATTR_PITCH: - _pitch.readOrUnset(value); - requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG); - break; - - case SP_ATTR_ROTATE: - _rotate.readOrUnset(value); - requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG); - break; - - case SP_ATTR_XLINK_HREF: - if (value && href == value) { - // Href unchanged, do nothing. - } else { - href.clear(); - - if (value) { - // First, set the href field; it's only used in the "unchanged" check above. - href = value; - // Now do the attaching, which emits the changed signal. - if (value) { - try { - ref->attach(Inkscape::URI(value)); - } catch (Inkscape::BadURIException &e) { - g_warning("%s", e.what()); - ref->detach(); - } - } else { - ref->detach(); - } - } - } - requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG); - break; - - default: - if (SP_ATTRIBUTE_IS_CSS(key)) { - style->readFromObject( this ); - requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG | SP_OBJECT_STYLE_MODIFIED_FLAG); - } else { - SPPaintServer::set(key, value); - } - break; - } -} - -bool SPHatch::_hasHatchPatchChildren(SPHatch const *hatch) -{ - for (auto& child: hatch->children) { - SPHatchPath const *hatchPath = dynamic_cast(&child); - if (hatchPath) { - return true; - } - } - return false; -} - -std::vector SPHatch::hatchPaths() -{ - std::vector list; - SPHatch *src = chase_hrefs(this, sigc::ptr_fun(&_hasHatchPatchChildren)); - - if (src) { - for (auto& child: src->children) { - SPHatchPath *hatchPath = dynamic_cast(&child); - if (hatchPath) { - list.push_back(hatchPath); - } - } - } - return list; -} - -std::vector SPHatch::hatchPaths() const -{ - std::vector list; - SPHatch const *src = chase_hrefs(this, sigc::ptr_fun(&_hasHatchPatchChildren)); - - if (src) { - for (auto& child: src->children) { - SPHatchPath const *hatchPath = dynamic_cast(&child); - if (hatchPath) { - list.push_back(hatchPath); - } - } - } - return list; -} - -// TODO: ::remove_child and ::order_changed handles - see SPPattern - - -void SPHatch::update(SPCtx* ctx, unsigned int flags) -{ - typedef std::list::iterator ViewIterator; - - if (flags & SP_OBJECT_MODIFIED_FLAG) { - flags |= SP_OBJECT_PARENT_MODIFIED_FLAG; - } - - flags &= SP_OBJECT_MODIFIED_CASCADE; - - std::vector children(hatchPaths()); - - for (ChildIterator iter = children.begin(); iter != children.end(); ++iter) { - SPHatchPath* child = *iter; - - sp_object_ref(child, NULL); - - for (ViewIterator view_iter = _display.begin(); view_iter != _display.end(); ++view_iter) { - Geom::OptInterval strip_extents = _calculateStripExtents(view_iter->bbox); - child->setStripExtents(view_iter->key, strip_extents); - } - - if (flags || (child->mflags & (SP_OBJECT_MODIFIED_FLAG | SP_OBJECT_CHILD_MODIFIED_FLAG))) { - - child->updateDisplay(ctx, flags); - } - - sp_object_unref(child, NULL); - } - - for (ViewIterator iter = _display.begin(); iter != _display.end(); ++iter) { - _updateView(*iter); - } -} - -void SPHatch::modified(unsigned int flags) -{ - if (flags & SP_OBJECT_MODIFIED_FLAG) { - flags |= SP_OBJECT_PARENT_MODIFIED_FLAG; - } - - flags &= SP_OBJECT_MODIFIED_CASCADE; - - std::vector children(hatchPaths()); - - for (ChildIterator iter = children.begin(); iter != children.end(); ++iter) { - SPObject *child = *iter; - - sp_object_ref(child, NULL); - - if (flags || (child->mflags & (SP_OBJECT_MODIFIED_FLAG | SP_OBJECT_CHILD_MODIFIED_FLAG))) { - child->emitModified(flags); - } - - sp_object_unref(child, NULL); - } -} - -void SPHatch::_onRefChanged(SPObject *old_ref, SPObject *ref) -{ - typedef std::list::iterator ViewIterator; - - if (old_ref) { - _modified_connection.disconnect(); - } - - SPHatch *hatch = dynamic_cast(ref); - if (hatch) { - _modified_connection = ref->connectModified(sigc::mem_fun(this, &SPHatch::_onRefModified)); - } - - if (!_hasHatchPatchChildren(this)) { - SPHatch *old_shown = NULL; - SPHatch *new_shown = NULL; - std::vector oldhatchPaths; - std::vector newhatchPaths; - - SPHatch *old_hatch = dynamic_cast(old_ref); - if (old_hatch) { - old_shown = old_hatch->rootHatch(); - oldhatchPaths = old_shown->hatchPaths(); - } - if (hatch) { - new_shown = hatch->rootHatch(); - newhatchPaths = new_shown->hatchPaths(); - } - if (old_shown != new_shown) { - - for (ViewIterator iter = _display.begin(); iter != _display.end(); ++iter) { - Geom::OptInterval extents = _calculateStripExtents(iter->bbox); - - for (ChildIterator child_iter = oldhatchPaths.begin(); child_iter != oldhatchPaths.end(); ++child_iter) { - SPHatchPath *child = *child_iter; - child->hide(iter->key); - } - for (ChildIterator child_iter = newhatchPaths.begin(); child_iter != newhatchPaths.end(); ++child_iter) { - SPHatchPath *child = *child_iter; - Inkscape::DrawingItem *cai = child->show(iter->arenaitem->drawing(), iter->key, extents); - child->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG); - if (cai) { - iter->arenaitem->appendChild(cai); - } - - } - } - } - } - - _onRefModified(ref, 0); -} - -void SPHatch::_onRefModified(SPObject */*ref*/, guint /*flags*/) -{ - requestModified(SP_OBJECT_MODIFIED_FLAG); - // Conditional to avoid causing infinite loop if there's a cycle in the href chain. -} - - -SPHatch *SPHatch::rootHatch() -{ - SPHatch *src = chase_hrefs(this, sigc::ptr_fun(&_hasHatchPatchChildren)); - return src ? src : this; // document is broken, we can't get to root; but at least we can return pat which is supposedly a valid hatch -} - -// Access functions that look up fields up the chain of referenced hatchs and return the first one which is set -// FIXME: all of them must use chase_hrefs as children() and rootHatch() - -SPHatch::HatchUnits SPHatch::hatchUnits() const -{ - HatchUnits units = _hatchUnits; - for (SPHatch const *pat_i = this; pat_i; pat_i = (pat_i->ref) ? pat_i->ref->getObject() : NULL) { - if (pat_i->_hatchUnits_set) { - units = pat_i->_hatchUnits; - break; - } - } - return units; -} - -SPHatch::HatchUnits SPHatch::hatchContentUnits() const -{ - HatchUnits units = _hatchContentUnits; - for (SPHatch const *pat_i = this; pat_i; pat_i = (pat_i->ref) ? pat_i->ref->getObject() : NULL) { - if (pat_i->_hatchContentUnits_set) { - units = pat_i->_hatchContentUnits; - break; - } - } - return units; -} - -Geom::Affine const &SPHatch::hatchTransform() const -{ - for (SPHatch const *pat_i = this; pat_i; pat_i = (pat_i->ref) ? pat_i->ref->getObject() : NULL) { - if (pat_i->_hatchTransform_set) { - return pat_i->_hatchTransform; - } - } - return _hatchTransform; -} - -gdouble SPHatch::x() const -{ - gdouble val = 0; - for (SPHatch const *pat_i = this; pat_i; pat_i = (pat_i->ref) ? pat_i->ref->getObject() : NULL) { - if (pat_i->_x._set) { - val = pat_i->_x.computed; - break; - } - } - return val; -} - -gdouble SPHatch::y() const -{ - gdouble val = 0; - for (SPHatch const *pat_i = this; pat_i; pat_i = (pat_i->ref) ? pat_i->ref->getObject() : NULL) { - if (pat_i->_y._set) { - val = pat_i->_y.computed; - break; - } - } - return val; -} - -gdouble SPHatch::pitch() const -{ - gdouble val = 0; - for (SPHatch const *pat_i = this; pat_i; pat_i = (pat_i->ref) ? pat_i->ref->getObject() : NULL) { - if (pat_i->_pitch._set) { - val = pat_i->_pitch.computed; - break; - } - } - return val; -} - -gdouble SPHatch::rotate() const -{ - gdouble val = 0; - for (SPHatch const *pat_i = this; pat_i; pat_i = (pat_i->ref) ? pat_i->ref->getObject() : NULL) { - if (pat_i->_rotate._set) { - val = pat_i->_rotate.computed; - break; - } - } - return val; -} - -bool SPHatch::isValid() const -{ - bool valid = false; - - if (pitch() > 0) { - std::vector children(hatchPaths()); - if (!children.empty()) { - valid = true; - for (ConstChildIterator iter = children.begin(); (iter != children.end()) && valid; ++iter) { - SPHatchPath const *child = *iter; - valid = child->isValid(); - } - } - } - - return valid; -} - -Inkscape::DrawingPattern *SPHatch::show(Inkscape::Drawing &drawing, unsigned int key, Geom::OptRect bbox) -{ - Inkscape::DrawingPattern *ai = new Inkscape::DrawingPattern(drawing); - //TODO: set some debug flag to see DrawingPattern - _display.push_front(View(ai, key)); - _display.front().bbox = bbox; - - std::vector children(hatchPaths()); - - Geom::OptInterval extents = _calculateStripExtents(bbox); - for (ChildIterator iter = children.begin(); iter != children.end(); ++iter) { - SPHatchPath *child = *iter; - Inkscape::DrawingItem *cai = child->show(drawing, key, extents); - if (cai) { - ai->appendChild(cai); - } - } - - View& view = _display.front(); - _updateView(view); - - return ai; -} - -void SPHatch::hide(unsigned int key) -{ - std::vector children(hatchPaths()); - - for (ChildIterator iter = children.begin(); iter != children.end(); ++iter) { - SPHatchPath *child = *iter; - child->hide(key); - } - - for (ViewIterator iter = _display.begin(); iter != _display.end(); ++iter) { - if (iter->key == key) { - delete iter->arenaitem; - _display.erase(iter); - return; - } - } - - g_assert_not_reached(); -} - - -Geom::Interval SPHatch::bounds() const -{ - Geom::Interval result; - std::vector children(hatchPaths()); - - for (ConstChildIterator iter = children.begin(); iter != children.end(); ++iter) { - SPHatchPath const *child = *iter; - if (result.extent() == 0) { - result = child->bounds(); - } else { - result |= child->bounds(); - } - } - return result; -} - -SPHatch::RenderInfo SPHatch::calculateRenderInfo(unsigned key) const -{ - RenderInfo info; - for (ConstViewIterator iter = _display.begin(); iter != _display.end(); ++iter) { - if (iter->key == key) { - return _calculateRenderInfo(*iter); - } - } - g_assert_not_reached(); - return info; -} - -void SPHatch::_updateView(View &view) -{ - RenderInfo info = _calculateRenderInfo(view); - //The rendering of hatch overflow is implemented by repeated drawing - //of hatch paths over one strip. Within each iteration paths are moved by pitch value. - //The movement progresses from right to left. This gives the same result - //as drawing whole strips in left-to-right order. - - - view.arenaitem->setChildTransform(info.child_transform); - view.arenaitem->setPatternToUserTransform(info.pattern_to_user_transform); - view.arenaitem->setTileRect(info.tile_rect); - view.arenaitem->setStyle(style); - view.arenaitem->setOverflow(info.overflow_initial_transform, info.overflow_steps, - info.overflow_step_transform); -} - -SPHatch::RenderInfo SPHatch::_calculateRenderInfo(View const &view) const -{ - RenderInfo info; - - Geom::OptInterval extents = _calculateStripExtents(view.bbox); - if (extents) { - double tile_x = x(); - double tile_y = y(); - double tile_width = pitch(); - double tile_height = extents->max() - extents->min(); - double tile_rotate = rotate(); - double tile_render_y = extents->min(); - - if (view.bbox && (hatchUnits() == UNITS_OBJECTBOUNDINGBOX)) { - tile_x *= view.bbox->width(); - tile_y *= view.bbox->height(); - tile_width *= view.bbox->width(); - tile_height *= view.bbox->height(); - tile_render_y *= view.bbox->height(); - } - - // Pattern size in hatch space - Geom::Rect hatch_tile = Geom::Rect::from_xywh(0, tile_render_y, tile_width, tile_height); - - // Content to bbox - Geom::Affine content2ps; - if (view.bbox && (hatchContentUnits() == UNITS_OBJECTBOUNDINGBOX)) { - content2ps = Geom::Affine(view.bbox->width(), 0.0, 0.0, view.bbox->height(), 0, 0); - } - - // Tile (hatch space) to user. - Geom::Affine ps2user = Geom::Translate(tile_x, tile_y) * Geom::Rotate::from_degrees(tile_rotate) * hatchTransform(); - - info.child_transform = content2ps; - info.pattern_to_user_transform = ps2user; - info.tile_rect = hatch_tile; - - if (style->overflow.computed == SP_CSS_OVERFLOW_VISIBLE) { - Geom::Interval bounds = this->bounds(); - gdouble pitch = this->pitch(); - gdouble overflow_right_strip = floor(bounds.max() / pitch) * pitch; - info.overflow_steps = ceil((overflow_right_strip - bounds.min()) / pitch) + 1; - info.overflow_step_transform = Geom::Translate(pitch, 0.0); - info.overflow_initial_transform = Geom::Translate(-overflow_right_strip, 0.0); - } else { - info.overflow_steps = 1; - } - } - - return info; -} - -//calculates strip extents in content space -Geom::OptInterval SPHatch::_calculateStripExtents(Geom::OptRect const &bbox) const -{ - if (!bbox || (bbox->area() == 0)) { - return Geom::OptInterval(); - } else { - double tile_x = x(); - double tile_y = y(); - double tile_rotate = rotate(); - - Geom::Affine ps2user = Geom::Translate(tile_x, tile_y) * Geom::Rotate::from_degrees(tile_rotate) * hatchTransform(); - Geom::Affine user2ps = ps2user.inverse(); - - Geom::Interval extents; - for (int i = 0; i < 4; ++i) { - Geom::Point corner = bbox->corner(i); - Geom::Point corner_ps = corner * user2ps; - if (i == 0 || corner_ps.y() < extents.min()) { - extents.setMin(corner_ps.y()); - } - if (i == 0 || corner_ps.y() > extents.max()) { - extents.setMax(corner_ps.y()); - } - } - - if (hatchUnits() == UNITS_OBJECTBOUNDINGBOX) { - extents /= bbox->height(); - } - - return extents; - } -} - -cairo_pattern_t* SPHatch::pattern_new(cairo_t * /*base_ct*/, Geom::OptRect const &/*bbox*/, double /*opacity*/) -{ - //this code should not be used - //it is however required by the fact that SPPaintServer::hatch_new is pure virtual - return cairo_pattern_create_rgb(0.5, 0.5, 1.0); -} - -void SPHatch::setBBox(unsigned int key, Geom::OptRect const &bbox) -{ - for (ViewIterator iter = _display.begin(); iter != _display.end(); ++iter) { - if (iter->key == key) { - iter->bbox = bbox; - break; - } - } -} - -// - -SPHatch::RenderInfo::RenderInfo() - : child_transform(), - pattern_to_user_transform(), - tile_rect(), - overflow_steps(0), - overflow_step_transform(), - overflow_initial_transform() -{ -} - -SPHatch::RenderInfo::~RenderInfo() -{ -} - -// - -SPHatch::View::View(Inkscape::DrawingPattern *arenaitem, int key) - : arenaitem(arenaitem), - bbox(), - key(key) -{ -} - -SPHatch::View::~View() -{ - // remember, do not delete arenaitem here - arenaitem = NULL; -} - -/* - 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 : -- cgit v1.2.3