drawing-shape.cpp revision de843c4e0b086a164491232bcf99a51cb5f7dd68
f07bfd5a05d43a6d11f7cd442f085149092dea88pjrm * Shape (styled path) belonging to an SVG drawing.
f07bfd5a05d43a6d11f7cd442f085149092dea88pjrm * Authors:
f07bfd5a05d43a6d11f7cd442f085149092dea88pjrm * Krzysztof KosiĆski <tweenk.pl@gmail.com>
f07bfd5a05d43a6d11f7cd442f085149092dea88pjrm * Copyright (C) 2011 Authors
ddc251b3cf95b0097b6a5ee39ea132bd4d7d5cbcjohanengelen * Released under GNU GPL, read the file 'COPYING' for more information
f07bfd5a05d43a6d11f7cd442f085149092dea88pjrmDrawingShape::_updateItem(Geom::IntRect const &area, UpdateContext const &ctx, unsigned flags, unsigned reset)
f07bfd5a05d43a6d11f7cd442f085149092dea88pjrm // update markers
072916d0ef7dccd696b59381f50bcf776abccefbjohanengelen for (ChildrenList::iterator i = _children.begin(); i != _children.end(); ++i) {
dc98accfae7a38326b92d74fa4330ac8ccb5b778jfbarraud /* We do not have to create rendering structures */
dc98accfae7a38326b92d74fa4330ac8ccb5b778jfbarraud boundingbox = bounds_exact_transformed(_curve->get_pathvector(), ctx.ctm);
f07bfd5a05d43a6d11f7cd442f085149092dea88pjrm for (ChildrenList::iterator i = _children.begin(); i != _children.end(); ++i) {
92fe3142613d000eff89db8a983b3b18b14eee79johanengelen // clear Cairo data to force update
70eb1fc448cb08acf3468f80fa2296c03b32afd2cilix boundingbox = bounds_exact_transformed(_curve->get_pathvector(), ctx.ctm);
f07bfd5a05d43a6d11f7cd442f085149092dea88pjrm if (boundingbox && (_nrstyle.stroke.type != NRStyle::PAINT_NONE || outline)) {
f07bfd5a05d43a6d11f7cd442f085149092dea88pjrm width = std::max(0.125f, _nrstyle.stroke_width * scale);
f07bfd5a05d43a6d11f7cd442f085149092dea88pjrm if ( fabs(_nrstyle.stroke_width * scale) > 0.01 ) { // FIXME: this is always true
f07bfd5a05d43a6d11f7cd442f085149092dea88pjrm // those pesky miters, now
f07bfd5a05d43a6d11f7cd442f085149092dea88pjrm // grunt mode. we should compute the various miters instead
f07bfd5a05d43a6d11f7cd442f085149092dea88pjrm // (one for each point on the curve)
f07bfd5a05d43a6d11f7cd442f085149092dea88pjrm _bbox = boundingbox ? boundingbox->roundOutwards() : Geom::OptIntRect();
eaa9bdc7bf7b73397e536edd47490d84e4420bd8bryce ( _nrstyle.stroke.type != NRStyle::PAINT_NONE && !outline) ))
f07bfd5a05d43a6d11f7cd442f085149092dea88pjrm for (ChildrenList::iterator i = _children.begin(); i != _children.end(); ++i) {
f07bfd5a05d43a6d11f7cd442f085149092dea88pjrm bool has_fill = _nrstyle.prepareFill(dc, _item_bbox, _fill_pattern);
f07bfd5a05d43a6d11f7cd442f085149092dea88pjrm bool has_stroke = _nrstyle.prepareStroke(dc, _item_bbox, _stroke_pattern);
f07bfd5a05d43a6d11f7cd442f085149092dea88pjrm // TODO: remove segments outside of bbox when no dashes present
f07bfd5a05d43a6d11f7cd442f085149092dea88pjrmDrawingShape::_renderMarkers(DrawingContext &dc, Geom::IntRect const &area, unsigned flags, DrawingItem *stop_at)
f07bfd5a05d43a6d11f7cd442f085149092dea88pjrm // marker rendering
f07bfd5a05d43a6d11f7cd442f085149092dea88pjrm for (ChildrenList::iterator i = _children.begin(); i != _children.end(); ++i) {
f07bfd5a05d43a6d11f7cd442f085149092dea88pjrmDrawingShape::_renderItem(DrawingContext &dc, Geom::IntRect const &area, unsigned flags, DrawingItem *stop_at)
f07bfd5a05d43a6d11f7cd442f085149092dea88pjrm if (!area.intersects(_bbox)) return RENDER_OK; // skip if not within bounding box
46c4893a7458eda6edcd064121bc000634af7a09johanengelen // paint-order doesn't matter
46c4893a7458eda6edcd064121bc000634af7a09johanengelen if( _nrstyle.paint_order_layer[0] == NRStyle::PAINT_ORDER_NORMAL ) {
46c4893a7458eda6edcd064121bc000634af7a09johanengelen // This is the most common case, special case so we don't call get_pathvector(), etc. twice
f07bfd5a05d43a6d11f7cd442f085149092dea88pjrm // we assume the context has no path
5675f17bbbc00f2c970b4d4966ce55d86775f7a6johanengelen // update fill and stroke paints.
f07bfd5a05d43a6d11f7cd442f085149092dea88pjrm // this cannot be done during nr_arena_shape_update, because we need a Cairo context
f07bfd5a05d43a6d11f7cd442f085149092dea88pjrm // to render svg:pattern
f07bfd5a05d43a6d11f7cd442f085149092dea88pjrm bool has_fill = _nrstyle.prepareFill(dc, _item_bbox, _fill_pattern);
f07bfd5a05d43a6d11f7cd442f085149092dea88pjrm bool has_stroke = _nrstyle.prepareStroke(dc, _item_bbox, _stroke_pattern);
f07bfd5a05d43a6d11f7cd442f085149092dea88pjrm // TODO: remove segments outside of bbox when no dashes present
93bb287e28a818fd5ba61b99d012e0500a49ccf6johanengelen } // has fill or stroke pattern
f07bfd5a05d43a6d11f7cd442f085149092dea88pjrm // Handle different paint orders
f07bfd5a05d43a6d11f7cd442f085149092dea88pjrm for (unsigned i = 0; i < NRStyle::PAINT_ORDER_LAYERS; ++i) {
f07bfd5a05d43a6d11f7cd442f085149092dea88pjrm // PAINT_ORDER_AUTO Should not happen
f07bfd5a05d43a6d11f7cd442f085149092dea88pjrmvoid DrawingShape::_clipItem(DrawingContext &dc, Geom::IntRect const & /*area*/)
f07bfd5a05d43a6d11f7cd442f085149092dea88pjrm if (!_curve) return;
f07bfd5a05d43a6d11f7cd442f085149092dea88pjrm // handle clip-rule
c0cd5511d3b975ebe07d019c1f5528108725e438johanengelen if (_style->clip_rule.computed == SP_WIND_RULE_EVENODD) {
c0cd5511d3b975ebe07d019c1f5528108725e438johanengelenDrawingShape::_pickItem(Geom::Point const &p, double delta, unsigned flags)
c0cd5511d3b975ebe07d019c1f5528108725e438johanengelen if (_repick_after > 0) // we are a slow, huge path
c0cd5511d3b975ebe07d019c1f5528108725e438johanengelen return _last_pick; // skip this pick, returning what was returned last time
f07bfd5a05d43a6d11f7cd442f085149092dea88pjrm if (SP_SCALE24_TO_FLOAT(_style->opacity.value) == 0 && !outline && !pick_as_clip)
f07bfd5a05d43a6d11f7cd442f085149092dea88pjrm // fully transparent, no pick unless outline mode
56542e2b97ec8826cc692153b0e2d4f5ac8ef913johanengelen width = 0; // no width should be applied to clip picking
f07bfd5a05d43a6d11f7cd442f085149092dea88pjrm // this overrides display mode and stroke style considerations
f07bfd5a05d43a6d11f7cd442f085149092dea88pjrm } else if (outline) {
f07bfd5a05d43a6d11f7cd442f085149092dea88pjrm width = 0.5; // in outline mode, everything is stroked with the same 0.5px line width
f07bfd5a05d43a6d11f7cd442f085149092dea88pjrm } else if (_nrstyle.stroke.type != NRStyle::PAINT_NONE && _nrstyle.stroke.opacity > 1e-3) {
f07bfd5a05d43a6d11f7cd442f085149092dea88pjrm // for normal picking calculate the distance corresponding top the stroke width
f07bfd5a05d43a6d11f7cd442f085149092dea88pjrm // FIXME BUG: this is incorrect for transformed strokes
56542e2b97ec8826cc692153b0e2d4f5ac8ef913johanengelen width = std::max(0.125f, _nrstyle.stroke_width * scale) / 2;
93bb287e28a818fd5ba61b99d012e0500a49ccf6johanengelen bool needfill = pick_as_clip || (_nrstyle.fill.type != NRStyle::PAINT_NONE &&
93bb287e28a818fd5ba61b99d012e0500a49ccf6johanengelen bool wind_evenodd = pick_as_clip ? (_style->clip_rule.computed == SP_WIND_RULE_EVENODD) :
93bb287e28a818fd5ba61b99d012e0500a49ccf6johanengelen (_style->fill_rule.computed == SP_WIND_RULE_EVENODD);
56542e2b97ec8826cc692153b0e2d4f5ac8ef913johanengelen // actual shape picking
93bb287e28a818fd5ba61b99d012e0500a49ccf6johanengelen Geom::Rect viewbox = _drawing.arena()->item.canvas->getViewbox();
56542e2b97ec8826cc692153b0e2d4f5ac8ef913johanengelen pathv_matrix_point_bbox_wind_distance(_curve->get_pathvector(), _ctm, p, NULL, needfill? &wind : NULL, &dist, 0.5, &viewbox);
fb5a72174252e0e79107dcad3bf5a2bbd73e349cjohanengelen pathv_matrix_point_bbox_wind_distance(_curve->get_pathvector(), _ctm, p, NULL, needfill? &wind : NULL, &dist, 0.5, NULL);
a0334366488989ef25fb812d7030d298c0917c96johanengelen glong this_pick = (tfinish.tv_sec - tstart.tv_sec) * 1000000 + (tfinish.tv_usec - tstart.tv_usec);
fb5a72174252e0e79107dcad3bf5a2bbd73e349cjohanengelen //g_print ("pick time %lu\n", this_pick);
fb5a72174252e0e79107dcad3bf5a2bbd73e349cjohanengelen if (this_pick > 10000) { // slow picking, remember to skip several new picks
fb5a72174252e0e79107dcad3bf5a2bbd73e349cjohanengelen // covered by fill?
fb5a72174252e0e79107dcad3bf5a2bbd73e349cjohanengelen return this;
fb5a72174252e0e79107dcad3bf5a2bbd73e349cjohanengelen return this;
fb5a72174252e0e79107dcad3bf5a2bbd73e349cjohanengelen // close to the edge, as defined by strokewidth and delta?
fb5a72174252e0e79107dcad3bf5a2bbd73e349cjohanengelen // this ignores dashing (as if the stroke is solid) and always works as if caps are round
fb5a72174252e0e79107dcad3bf5a2bbd73e349cjohanengelen if (needfill || width > 0) { // if either fill or stroke visible,
fb5a72174252e0e79107dcad3bf5a2bbd73e349cjohanengelen return this;
fb5a72174252e0e79107dcad3bf5a2bbd73e349cjohanengelen // if not picked on the shape itself, try its markers
fb5a72174252e0e79107dcad3bf5a2bbd73e349cjohanengelen for (ChildrenList::iterator i = _children.begin(); i != _children.end(); ++i) {
fb5a72174252e0e79107dcad3bf5a2bbd73e349cjohanengelen DrawingItem *ret = i->pick(p, delta, flags & ~PICK_STICKY);
42e99769805c14a5cc01c805faa3c3b03f9dd1c0johanengelen return this;
56542e2b97ec8826cc692153b0e2d4f5ac8ef913johanengelen return true;
56542e2b97ec8826cc692153b0e2d4f5ac8ef913johanengelen} // end namespace Inkscape
ddc251b3cf95b0097b6a5ee39ea132bd4d7d5cbcjohanengelen Local Variables:
ddc251b3cf95b0097b6a5ee39ea132bd4d7d5cbcjohanengelen c-file-style:"stroustrup"
ddc251b3cf95b0097b6a5ee39ea132bd4d7d5cbcjohanengelen c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
ddc251b3cf95b0097b6a5ee39ea132bd4d7d5cbcjohanengelen indent-tabs-mode:nil
ddc251b3cf95b0097b6a5ee39ea132bd4d7d5cbcjohanengelen fill-column:99
ddc251b3cf95b0097b6a5ee39ea132bd4d7d5cbcjohanengelen// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :