From 1d854ff519b9c0867bfa4ecaf2f6329ca256f06a Mon Sep 17 00:00:00 2001 From: "Liam P. White" Date: Sun, 2 Mar 2014 10:29:06 -0500 Subject: Experimental merge of Ponyscape features into trunk (will not compile) (bzr r13090.1.1) --- src/live_effects/CMakeLists.txt | 13 + src/live_effects/Makefile_insert | 14 +- src/live_effects/effect-enum.h | 6 + src/live_effects/effect.cpp | 39 +- src/live_effects/lpe-attach-path.cpp | 203 ++ src/live_effects/lpe-attach-path.h | 54 + src/live_effects/lpe-bounding-box.cpp | 67 + src/live_effects/lpe-bounding-box.h | 37 + src/live_effects/lpe-ellipse_5pts.cpp | 214 ++ src/live_effects/lpe-ellipse_5pts.h | 50 + src/live_effects/lpe-fill-between-many.cpp | 77 + src/live_effects/lpe-fill-between-many.h | 36 + src/live_effects/lpe-fill-between-strokes.cpp | 116 ++ src/live_effects/lpe-fill-between-strokes.h | 38 + src/live_effects/lpe-jointype.cpp | 203 ++ src/live_effects/lpe-jointype.h | 43 + src/live_effects/lpe-powerstroke-interpolators.h | 42 +- src/live_effects/lpe-powerstroke.cpp | 97 +- src/live_effects/lpe-powerstroke.h | 2 + src/live_effects/parameter/Makefile_insert | 4 + src/live_effects/parameter/originalpatharray.cpp | 486 +++++ src/live_effects/parameter/originalpatharray.h | 123 ++ .../parameter/powerstrokepointarray.cpp | 39 +- src/live_effects/parameter/powerstrokepointarray.h | 23 +- src/live_effects/parameter/transformedpoint.cpp | 182 ++ src/live_effects/parameter/transformedpoint.h | 87 + src/live_effects/pathoutlineprovider.h | 766 ++++++++ src/sp-item.cpp | 20 + src/sp-item.h | 10 + src/sp-object.h | 1 + src/ui/dialog/Makefile_insert | 4 + src/ui/dialog/lpe-powerstroke-properties.cpp | 203 ++ src/ui/dialog/lpe-powerstroke-properties.h | 99 + src/ui/dialog/objects.cpp | 2048 ++++++++++++++++++++ src/ui/dialog/objects.h | 255 +++ src/ui/dialog/tags.cpp | 1182 +++++++++++ src/ui/dialog/tags.h | 181 ++ src/ui/widget/clipmaskicon.cpp | 177 ++ src/ui/widget/clipmaskicon.h | 102 + src/ui/widget/highlight-picker.cpp | 176 ++ src/ui/widget/highlight-picker.h | 90 + src/ui/widget/insertordericon.cpp | 166 ++ src/ui/widget/insertordericon.h | 100 + src/ui/widget/layertypeicon.cpp | 167 ++ src/ui/widget/layertypeicon.h | 108 ++ 45 files changed, 8126 insertions(+), 24 deletions(-) create mode 100644 src/live_effects/lpe-attach-path.cpp create mode 100644 src/live_effects/lpe-attach-path.h create mode 100644 src/live_effects/lpe-bounding-box.cpp create mode 100644 src/live_effects/lpe-bounding-box.h create mode 100644 src/live_effects/lpe-ellipse_5pts.cpp create mode 100644 src/live_effects/lpe-ellipse_5pts.h create mode 100644 src/live_effects/lpe-fill-between-many.cpp create mode 100644 src/live_effects/lpe-fill-between-many.h create mode 100644 src/live_effects/lpe-fill-between-strokes.cpp create mode 100644 src/live_effects/lpe-fill-between-strokes.h create mode 100644 src/live_effects/lpe-jointype.cpp create mode 100755 src/live_effects/lpe-jointype.h create mode 100644 src/live_effects/parameter/originalpatharray.cpp create mode 100644 src/live_effects/parameter/originalpatharray.h create mode 100644 src/live_effects/parameter/transformedpoint.cpp create mode 100644 src/live_effects/parameter/transformedpoint.h create mode 100755 src/live_effects/pathoutlineprovider.h create mode 100644 src/ui/dialog/lpe-powerstroke-properties.cpp create mode 100644 src/ui/dialog/lpe-powerstroke-properties.h create mode 100644 src/ui/dialog/objects.cpp create mode 100644 src/ui/dialog/objects.h create mode 100644 src/ui/dialog/tags.cpp create mode 100644 src/ui/dialog/tags.h create mode 100644 src/ui/widget/clipmaskicon.cpp create mode 100644 src/ui/widget/clipmaskicon.h create mode 100644 src/ui/widget/highlight-picker.cpp create mode 100644 src/ui/widget/highlight-picker.h create mode 100644 src/ui/widget/insertordericon.cpp create mode 100644 src/ui/widget/insertordericon.h create mode 100644 src/ui/widget/layertypeicon.cpp create mode 100644 src/ui/widget/layertypeicon.h (limited to 'src') diff --git a/src/live_effects/CMakeLists.txt b/src/live_effects/CMakeLists.txt index a5f50a69d..8ad1ccf9b 100644 --- a/src/live_effects/CMakeLists.txt +++ b/src/live_effects/CMakeLists.txt @@ -2,8 +2,10 @@ set(live_effects_SRC effect.cpp lpe-angle_bisector.cpp + lpe-attach-path.cpp lpe-bendpath.cpp lpe-boolops.cpp + lpe-bounding-box.cpp lpe-circle_3pts.cpp lpe-circle_with_radius.cpp lpe-clone-original.cpp @@ -11,8 +13,11 @@ set(live_effects_SRC lpe-copy_rotate.cpp lpe-curvestitch.cpp lpe-dynastroke.cpp + lpe-ellipse-5pts.cpp lpe-envelope.cpp lpe-extrude.cpp + lpe-fill-between-many.cpp + lpe-fill-between-strokes.cpp lpe-gears.cpp lpe-interpolate.cpp lpe-knot.cpp @@ -47,11 +52,13 @@ set(live_effects_SRC parameter/parameter.cpp parameter/path.cpp parameter/originalpath.cpp + parameter/originalpatharray.cpp parameter/path-reference.cpp parameter/point.cpp parameter/powerstrokepointarray.cpp parameter/random.cpp parameter/text.cpp + paramter/transformedpoint.cpp parameter/unit.cpp parameter/vector.cpp @@ -61,8 +68,10 @@ set(live_effects_SRC effect-enum.h effect.h lpe-angle_bisector.h + lpe-attach-path.h lpe-bendpath.h lpe-boolops.h + lpe-bounding-box.h lpe-circle_3pts.h lpe-circle_with_radius.h lpe-clone-original.h @@ -70,8 +79,11 @@ set(live_effects_SRC lpe-copy_rotate.h lpe-curvestitch.h lpe-dynastroke.h + lpe-ellipse-5pts.h lpe-envelope.h lpe-extrude.h + lpe-fill-between-many.h + lpe-fill-between-strokes.h lpe-gears.h lpe-interpolate.h lpe-knot.h @@ -109,6 +121,7 @@ set(live_effects_SRC parameter/path-reference.h parameter/path.h parameter/originalpath.h + parameter/originalpatharray.h parameter/point.h parameter/powerstrokepointarray.h parameter/random.h diff --git a/src/live_effects/Makefile_insert b/src/live_effects/Makefile_insert index 9c3c171f2..76d7b418f 100644 --- a/src/live_effects/Makefile_insert +++ b/src/live_effects/Makefile_insert @@ -82,4 +82,16 @@ ink_common_sources += \ live_effects/lpe-path_length.cpp \ live_effects/lpe-path_length.h \ live_effects/lpe-line_segment.cpp \ - live_effects/lpe-line_segment.h + live_effects/lpe-line_segment.h \ + live_effects/lpe-bounding-box.cpp \ + live_effects/lpe-bounding-box.h \ + live_effects/lpe-attach-path.cpp \ + live_effects/lpe-attach-path.h \ + live_effects/lpe-fill-between-strokes.cpp \ + live_effects/lpe-fill-between-stroke.h \ + live_effects/lpe-fill-between-many.cpp \ + live_effects/lpe-fill-between-many.h \ + live_effects/lpe-ellipse_5pts.cpp \ + live_effects/lpe-ellipse_5pts.h \ + live_effects/lpe-jointype.cpp \ + live_effects/lpe-jointype.h diff --git a/src/live_effects/effect-enum.h b/src/live_effects/effect-enum.h index 43af33b53..46bc56a81 100644 --- a/src/live_effects/effect-enum.h +++ b/src/live_effects/effect-enum.h @@ -50,6 +50,12 @@ enum EffectType { EXTRUDE, POWERSTROKE, CLONE_ORIGINAL, + ATTACH_PATH, + FILL_BETWEEN_STROKES, + FILL_BETWEEN_MANY, + ELLIPSE_5PTS, + BOUNDING_BOX, + JOIN_TYPE, INVALID_LPE // This must be last (I made it such that it is not needed anymore I think..., Don't trust on it being last. - johan) }; diff --git a/src/live_effects/effect.cpp b/src/live_effects/effect.cpp index 12990ee24..17b229352 100644 --- a/src/live_effects/effect.cpp +++ b/src/live_effects/effect.cpp @@ -5,7 +5,7 @@ * Released under GNU GPL, read the file 'COPYING' for more information */ -//#define LPE_ENABLE_TEST_EFFECTS +#define LPE_ENABLE_TEST_EFFECTS #ifdef HAVE_CONFIG_H # include "config.h" @@ -47,6 +47,12 @@ #include "live_effects/lpe-extrude.h" #include "live_effects/lpe-powerstroke.h" #include "live_effects/lpe-clone-original.h" +#include "live_effects/lpe-attach-path.h" +#include "live_effects/lpe-fill-between-strokes.h" +#include "live_effects/lpe-fill-between-many.h" +#include "live_effects/lpe-ellipse_5pts.h" +#include "live_effects/lpe-bounding-box.h" +#include "live_effects/lpe-jointype.h" #include "xml/node-event-vector.h" #include "sp-object.h" @@ -103,9 +109,10 @@ const Util::EnumData LPETypeData[] = { {RECURSIVE_SKELETON, N_("Recursive skeleton"), "recursive_skeleton"}, {TANGENT_TO_CURVE, N_("Tangent to curve"), "tangent_to_curve"}, {TEXT_LABEL, N_("Text label"), "text_label"}, + {JOIN_TYPE, N_("Join type"), "join_type"}, #endif /* 0.46 */ - {BEND_PATH, N_("Bend"), "bend_path"}, + {BEND_PATH, N_("Bend"), "bend_path"}, {GEARS, N_("Gears"), "gears"}, {PATTERN_ALONG_PATH, N_("Pattern Along Path"), "skeletal"}, // for historic reasons, this effect is called skeletal(strokes) in Inkscape:SVG {CURVE_STITCH, N_("Stitch Sub-Paths"), "curvestitching"}, @@ -120,8 +127,14 @@ const Util::EnumData LPETypeData[] = { {SKETCH, N_("Sketch"), "sketch"}, {RULER, N_("Ruler"), "ruler"}, /* 0.49 */ - {POWERSTROKE, N_("Power stroke"), "powerstroke"}, - {CLONE_ORIGINAL, N_("Clone original path"), "clone_original"}, + {POWERSTROKE, N_("Power stroke"), "powerstroke"}, + {CLONE_ORIGINAL, N_("Clone original path"), "clone_original"}, +/* Ponyscape */ + {ATTACH_PATH, N_("Attach path"), "attach_path"}, + {FILL_BETWEEN_STROKES, N_("Fill between strokes"), "fill_between_strokes"}, + {FILL_BETWEEN_MANY, N_("Fill between many"), "fill_between_many"}, + {ELLIPSE_5PTS, N_("Ellipse by 5 points"), "ellipse_5pts"}, + {BOUNDING_BOX, N_("Bounding Box"), "bounding_box"}, }; const Util::EnumDataConverter LPETypeConverter(LPETypeData, sizeof(LPETypeData)/sizeof(*LPETypeData)); @@ -245,6 +258,24 @@ Effect::New(EffectType lpenr, LivePathEffectObject *lpeobj) case CLONE_ORIGINAL: neweffect = static_cast ( new LPECloneOriginal(lpeobj) ); break; + case ATTACH_PATH: + neweffect = static_cast ( new LPEAttachPath(lpeobj) ); + break; + case FILL_BETWEEN_STROKES: + neweffect = static_cast ( new LPEFillBetweenStrokes(lpeobj) ); + break; + case FILL_BETWEEN_MANY: + neweffect = static_cast ( new LPEFillBetweenMany(lpeobj) ); + break; + case ELLIPSE_5PTS: + neweffect = static_cast ( new LPEEllipse5Pts(lpeobj) ); + break; + case BOUNDING_BOX: + neweffect = static_cast ( new LPEBoundingBox(lpeobj) ); + break; + case JOIN_TYPE: + neweffect = static_cast ( new LPEJoinType(lpeobj) ); + break; default: g_warning("LivePathEffect::Effect::New called with invalid patheffect type (%d)", lpenr); neweffect = NULL; diff --git a/src/live_effects/lpe-attach-path.cpp b/src/live_effects/lpe-attach-path.cpp new file mode 100644 index 000000000..b3d5ed9b7 --- /dev/null +++ b/src/live_effects/lpe-attach-path.cpp @@ -0,0 +1,203 @@ +/* + * Copyright (C) Johan Engelen 2012 + * + * Released under GNU GPL, read the file 'COPYING' for more information + */ + +#include +#include + +#include "live_effects/lpe-attach-path.h" + +#include "display/curve.h" +#include "sp-item.h" +#include "2geom/path.h" +#include "sp-shape.h" +#include "sp-text.h" +#include "2geom/bezier-curve.h" +#include "2geom/path-sink.h" +#include "parameter/parameter.h" +#include "live_effects/parameter/point.h" +#include "parameter/originalpath.h" +#include "2geom/affine.h" + +namespace Inkscape { +namespace LivePathEffect { + +LPEAttachPath::LPEAttachPath(LivePathEffectObject *lpeobject) : + Effect(lpeobject), + start_path(_("Start path:"), _("Path to attach to the start of this path"), "startpath", &wr, this), + start_path_position(_("Start path position:"), _("Position to attach path start to"), "startposition", &wr, this, 0.0), + start_path_curve_start(_("Start path curve start:"), _("Starting curve"), "startcurvestart", &wr, this, Geom::Point(20,0)/*, true*/), + start_path_curve_end(_("Start path curve end:"), _("Ending curve"), "startcurveend", &wr, this, Geom::Point(20,0)/*, true*/), + end_path(_("End path:"), _("Path to attach to the end of this path"), "endpath", &wr, this), + end_path_position(_("End path position:"), _("Position to attach path end to"), "endposition", &wr, this, 0.0), + end_path_curve_start(_("End path curve start:"), _("Starting curve"), "endcurvestart", &wr, this, Geom::Point(20,0)/*, true*/), + end_path_curve_end(_("End path curve end:"), _("Ending curve"), "endcurveend", &wr, this, Geom::Point(20,0)/*, true*/) +{ + registerParameter( dynamic_cast(&start_path) ); + registerParameter( dynamic_cast(&start_path_position) ); + registerParameter( dynamic_cast(&start_path_curve_start) ); + registerParameter( dynamic_cast(&start_path_curve_end) ); + + registerParameter( dynamic_cast(&end_path) ); + registerParameter( dynamic_cast(&end_path_position) ); + registerParameter( dynamic_cast(&end_path_curve_start) ); + registerParameter( dynamic_cast(&end_path_curve_end) ); + + //perceived_path = true; + show_orig_path = true; + curve_start_previous_origin = start_path_curve_end.getOrigin(); + curve_end_previous_origin = end_path_curve_end.getOrigin(); +} + +LPEAttachPath::~LPEAttachPath() +{ + +} + +void LPEAttachPath::resetDefaults(SPItem const * item) +{ + curve_start_previous_origin = start_path_curve_end.getOrigin(); + curve_end_previous_origin = end_path_curve_end.getOrigin(); +} + +void LPEAttachPath::doBeforeEffect(const SPLPEItem *lpeitem) +{ + lpe_effect = lpeitem; +} + +void LPEAttachPath::doEffect (SPCurve * curve) +{ + std::vector this_pathv = curve->get_pathvector(); + if (lpe_effect && !this_pathv.empty()) { + Geom::Path p = Geom::Path(this_pathv.front().initialPoint()); + + bool set_start_end = start_path_curve_end.getOrigin() != curve_start_previous_origin; + bool set_end_end = end_path_curve_end.getOrigin() != curve_end_previous_origin; + + if (start_path.linksToPath()) { + + std::vector linked_pathv = start_path.get_pathvector(); + Geom::Affine linkedtransform = start_path.getObject()->getRelativeTransform(lpe_effect); + + if ( !linked_pathv.empty() ) + { + Geom::Path transformedpath = linked_pathv.front() * linkedtransform; + start_path_curve_start.setOrigin(this_pathv.front().initialPoint()); + + std::vector derivs = this_pathv.front().front().pointAndDerivatives(0, 3); + + for (unsigned deriv_n = 1; deriv_n < derivs.size(); deriv_n++) { + Geom::Coord length = derivs[deriv_n].length(); + if ( ! Geom::are_near(length, 0) ) { + if (set_start_end) { + start_path_position.param_set_value(transformedpath.nearestPoint(start_path_curve_end.getOrigin())); + } + + if (start_path_position > transformedpath.size()) { + start_path_position.param_set_value(transformedpath.size()); + } else if (start_path_position < 0) { + start_path_position.param_set_value(0); + } + const Geom::Curve *c = start_path_position >= transformedpath.size() ? &transformedpath.back() : &transformedpath.at_index((int)start_path_position); + + std::vector derivs_2 = c->pointAndDerivatives(start_path_position >= transformedpath.size() ? 1 : (start_path_position - (int)start_path_position), 3); + for (unsigned deriv_n_2 = 1; deriv_n_2 < derivs_2.size(); deriv_n_2++) { + Geom::Coord length_2 = derivs[deriv_n_2].length(); + if ( ! Geom::are_near(length_2, 0) ) { + start_path_curve_end.setOrigin(derivs_2[0]); + curve_start_previous_origin = start_path_curve_end.getOrigin(); + + double startangle = atan2(start_path_curve_start.getVector().y(), start_path_curve_start.getVector().x()); + double endangle = atan2(start_path_curve_end.getVector().y(), start_path_curve_end.getVector().x()); + double startderiv = atan2(derivs[deriv_n].y(), derivs[deriv_n].x()); + double endderiv = atan2(derivs_2[deriv_n_2].y(), derivs_2[deriv_n_2].x()); + Geom::Point pt1 = Geom::Point(start_path_curve_start.getVector().length() * cos(startangle + startderiv), start_path_curve_start.getVector().length() * sin(startangle + startderiv)); + Geom::Point pt2 = Geom::Point(start_path_curve_end.getVector().length() * cos(endangle + endderiv), start_path_curve_end.getVector().length() * sin(endangle + endderiv)); + p = Geom::Path(derivs_2[0]); + p.appendNew(-pt2 + derivs_2[0], -pt1 + this_pathv.front().initialPoint(), this_pathv.front().initialPoint()); + break; + + } + } + break; + } + } + } + } + + p.append(this_pathv.front()); + + if (end_path.linksToPath()) { + + std::vector linked_pathv = end_path.get_pathvector(); + Geom::Affine linkedtransform = end_path.getObject()->getRelativeTransform(lpe_effect); + + if ( !linked_pathv.empty() ) + { + Geom::Path transformedpath = linked_pathv.front() * linkedtransform; + Geom::Curve * last_seg_reverse = this_pathv.front().back().reverse(); + + end_path_curve_start.setOrigin(last_seg_reverse->initialPoint()); + + std::vector derivs = last_seg_reverse->pointAndDerivatives(0, 3); + for (unsigned deriv_n = 1; deriv_n < derivs.size(); deriv_n++) { + Geom::Coord length = derivs[deriv_n].length(); + if ( ! Geom::are_near(length, 0) ) { + if (set_end_end) { + end_path_position.param_set_value(transformedpath.nearestPoint(end_path_curve_end.getOrigin())); + } + + if (end_path_position > transformedpath.size()) { + end_path_position.param_set_value(transformedpath.size()); + } else if (end_path_position < 0) { + end_path_position.param_set_value(0); + } + const Geom::Curve *c = end_path_position >= transformedpath.size() ? &transformedpath.back() : &transformedpath.at_index((int)end_path_position); + + std::vector derivs_2 = c->pointAndDerivatives(end_path_position >= transformedpath.size() ? 1 : (end_path_position - (int)end_path_position), 3); + for (unsigned deriv_n_2 = 1; deriv_n_2 < derivs_2.size(); deriv_n_2++) { + Geom::Coord length_2 = derivs[deriv_n_2].length(); + if ( ! Geom::are_near(length_2, 0) ) { + + end_path_curve_end.setOrigin(derivs_2[0]); + curve_end_previous_origin = end_path_curve_end.getOrigin(); + + double startangle = atan2(end_path_curve_start.getVector().y(), end_path_curve_start.getVector().x()); + double endangle = atan2(end_path_curve_end.getVector().y(), end_path_curve_end.getVector().x()); + double startderiv = atan2(derivs[deriv_n].y(), derivs[deriv_n].x()); + double endderiv = atan2(derivs_2[deriv_n_2].y(), derivs_2[deriv_n_2].x()); + Geom::Point pt1 = Geom::Point(end_path_curve_start.getVector().length() * cos(startangle + startderiv), end_path_curve_start.getVector().length() * sin(startangle + startderiv)); + Geom::Point pt2 = Geom::Point(end_path_curve_end.getVector().length() * cos(endangle + endderiv), end_path_curve_end.getVector().length() * sin(endangle + endderiv)); + p.appendNew(-pt1 + this_pathv.front().finalPoint(), -pt2 + derivs_2[0], derivs_2[0]); + + break; + + } + } + break; + } + } + delete last_seg_reverse; + } + } + Geom::PathVector outvector; + outvector.push_back(p); + curve->set_pathvector(outvector); + } +} + +} // namespace LivePathEffect +} /* 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 : diff --git a/src/live_effects/lpe-attach-path.h b/src/live_effects/lpe-attach-path.h new file mode 100644 index 000000000..3dda189d6 --- /dev/null +++ b/src/live_effects/lpe-attach-path.h @@ -0,0 +1,54 @@ +#ifndef INKSCAPE_LPE_ATTACH_PATH_H +#define INKSCAPE_LPE_ATTACH_PATH_H + +/* + * Inkscape::LPEAttachPath + * + * Copyright (C) Ted Janeczko 2012 + * + * Released under GNU GPL, read the file 'COPYING' for more information + */ + +#include "live_effects/effect.h" +#include "live_effects/parameter/parameter.h" +#include "live_effects/parameter/point.h" +#include "live_effects/parameter/originalpath.h" +#include "live_effects/parameter/vector.h" +#include "live_effects/parameter/bool.h" +#include "live_effects/parameter/transformedpoint.h" + +namespace Inkscape { +namespace LivePathEffect { + +class LPEAttachPath : public Effect { +public: + LPEAttachPath(LivePathEffectObject *lpeobject); + virtual ~LPEAttachPath(); + + virtual void doBeforeEffect(const SPLPEItem *lpeitem); + virtual void doEffect (SPCurve * curve); + virtual void resetDefaults(SPItem const * item); + +private: + LPEAttachPath(const LPEAttachPath&); + LPEAttachPath& operator=(const LPEAttachPath&); + + Geom::Point curve_start_previous_origin; + Geom::Point curve_end_previous_origin; + + OriginalPathParam start_path; + ScalarParam start_path_position; + TransformedPointParam start_path_curve_start; + VectorParam start_path_curve_end; + + OriginalPathParam end_path; + ScalarParam end_path_position; + TransformedPointParam end_path_curve_start; + VectorParam end_path_curve_end; + const SPLPEItem * lpe_effect; +}; + +}; //namespace LivePathEffect +}; //namespace Inkscape + +#endif diff --git a/src/live_effects/lpe-bounding-box.cpp b/src/live_effects/lpe-bounding-box.cpp new file mode 100644 index 000000000..bafd5e70e --- /dev/null +++ b/src/live_effects/lpe-bounding-box.cpp @@ -0,0 +1,67 @@ +/* + * Copyright (C) Theodore Janeczko 2012 + * + * Released under GNU GPL, read the file 'COPYING' for more information + */ + +#include + +#include "live_effects/lpe-bounding-box.h" + +#include "display/curve.h" +#include "sp-item.h" +#include "2geom/path.h" +#include "sp-shape.h" +#include "sp-text.h" +#include "2geom/bezier-curve.h" +#include "lpe-bounding-box.h" + +namespace Inkscape { +namespace LivePathEffect { + +LPEBoundingBox::LPEBoundingBox(LivePathEffectObject *lpeobject) : + Effect(lpeobject), + linked_path(_("Linked path:"), _("Path from which to take the original path data"), "linkedpath", &wr, this), + visual_bounds(_("Visual Bounds"), _("Uses the visual bounding box"), "visualbounds", &wr, this) +{ + registerParameter( dynamic_cast(&linked_path) ); + registerParameter( dynamic_cast(&visual_bounds) ); + //perceived_path = true; +} + +LPEBoundingBox::~LPEBoundingBox() +{ + +} + +void LPEBoundingBox::doEffect (SPCurve * curve) +{ + if (curve) { + if ( linked_path.linksToPath() && linked_path.getObject() ) { + SPItem * item = linked_path.getObject(); + Geom::OptRect bbox = visual_bounds.get_value() ? item->visualBounds() : item->geometricBounds(); + Geom::Path p(Geom::Point(bbox->left(), bbox->top())); + p.appendNew(Geom::Point(bbox->right(), bbox->top())); + p.appendNew(Geom::Point(bbox->right(), bbox->bottom())); + p.appendNew(Geom::Point(bbox->left(), bbox->bottom())); + p.appendNew(Geom::Point(bbox->left(), bbox->top())); + std::vector out; + out.push_back(p); + curve->set_pathvector(out); + } + } +} + +} // namespace LivePathEffect +} /* 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 : diff --git a/src/live_effects/lpe-bounding-box.h b/src/live_effects/lpe-bounding-box.h new file mode 100644 index 000000000..d028a20ac --- /dev/null +++ b/src/live_effects/lpe-bounding-box.h @@ -0,0 +1,37 @@ +#ifndef INKSCAPE_LPE_BOUNDING_BOX_H +#define INKSCAPE_LPE_BOUNDING_BOX_H + +/* + * Inkscape::LPEFillBetweenStrokes + * + * Copyright (C) Theodore Janeczko 2012 + * + * Released under GNU GPL, read the file 'COPYING' for more information + */ + +#include "live_effects/effect.h" +#include "live_effects/parameter/originalpath.h" + +namespace Inkscape { +namespace LivePathEffect { + +class LPEBoundingBox : public Effect { +public: + LPEBoundingBox(LivePathEffectObject *lpeobject); + virtual ~LPEBoundingBox(); + + virtual void doEffect (SPCurve * curve); + +private: + OriginalPathParam linked_path; + BoolParam visual_bounds; + +private: + LPEBoundingBox(const LPEBoundingBox&); + LPEBoundingBox& operator=(const LPEBoundingBox&); +}; + +}; //namespace LivePathEffect +}; //namespace Inkscape + +#endif diff --git a/src/live_effects/lpe-ellipse_5pts.cpp b/src/live_effects/lpe-ellipse_5pts.cpp new file mode 100644 index 000000000..b0a5919fe --- /dev/null +++ b/src/live_effects/lpe-ellipse_5pts.cpp @@ -0,0 +1,214 @@ +/** \file + * LPE "Ellipse through 5 points" implementation + */ + +/* + * Authors: + * Theodore Janeczko + * + * Copyright (C) Theodore Janeczko 2012 + * + * Released under GNU GPL, read the file 'COPYING' for more information + */ + +#include "live_effects/lpe-ellipse_5pts.h" + +// You might need to include other 2geom files. You can add them here: +#include +#include <2geom/path.h> +#include <2geom/circle.h> +#include <2geom/ellipse.h> +#include <2geom/path-sink.h> +#include "inkscape.h" +#include "desktop.h" +#include "message-stack.h" + +namespace Inkscape { +namespace LivePathEffect { + +LPEEllipse5Pts::LPEEllipse5Pts(LivePathEffectObject *lpeobject) : + Effect(lpeobject) +{ + //perceived_path = true; +} + +LPEEllipse5Pts::~LPEEllipse5Pts() +{ +} + +static double _det3(double (*mat)[3]) +{ + for (int i = 0; i < 2; i++) + { + for (int j = i + 1; j < 3; j++) + { + for (int k = i + 1; k < 3; k++) + { + mat[j][k] = (mat[j][k] * mat[i][i] - mat[j][i] * mat[i][k]); + if (i) mat[j][k] /= mat[i-1][i-1]; + } + } + } + return mat[2][2]; +} +static double _det5(double (*mat)[5]) +{ + for (int i = 0; i < 4; i++) + { + for (int j = i + 1; j < 5; j++) + { + for (int k = i + 1; k < 5; k++) + { + mat[j][k] = (mat[j][k] * mat[i][i] - mat[j][i] * mat[i][k]); + if (i) mat[j][k] /= mat[i-1][i-1]; + } + } + } + return mat[4][4]; +} + +std::vector +LPEEllipse5Pts::doEffect_path (std::vector const & path_in) +{ + std::vector path_out = std::vector(); + + if (path_in[0].size() < 4) { + + SP_ACTIVE_DESKTOP->messageStack()->flash(Inkscape::WARNING_MESSAGE, _("Five points required for constructing an ellipse")); + return path_in; + } + // we assume that the path has >= 3 nodes + Geom::Point A = path_in[0].initialPoint(); + Geom::Point B = path_in[0].pointAt(1); + Geom::Point C = path_in[0].pointAt(2); + Geom::Point D = path_in[0].pointAt(3); + Geom::Point E = path_in[0].pointAt(4); + + using namespace Geom; + + double rowmajor_matrix[5][6] = + { + {A.x()*A.x(), A.x()*A.y(), A.y()*A.y(), A.x(), A.y(), 1}, + {B.x()*B.x(), B.x()*B.y(), B.y()*B.y(), B.x(), B.y(), 1}, + {C.x()*C.x(), C.x()*C.y(), C.y()*C.y(), C.x(), C.y(), 1}, + {D.x()*D.x(), D.x()*D.y(), D.y()*D.y(), D.x(), D.y(), 1}, + {E.x()*E.x(), E.x()*E.y(), E.y()*E.y(), E.x(), E.y(), 1} + }; + + double mat_a[5][5] = + { + {rowmajor_matrix[0][1], rowmajor_matrix[1][1], rowmajor_matrix[2][1], rowmajor_matrix[3][1], rowmajor_matrix[4][1]}, + {rowmajor_matrix[0][2], rowmajor_matrix[1][2], rowmajor_matrix[2][2], rowmajor_matrix[3][2], rowmajor_matrix[4][2]}, + {rowmajor_matrix[0][3], rowmajor_matrix[1][3], rowmajor_matrix[2][3], rowmajor_matrix[3][3], rowmajor_matrix[4][3]}, + {rowmajor_matrix[0][4], rowmajor_matrix[1][4], rowmajor_matrix[2][4], rowmajor_matrix[3][4], rowmajor_matrix[4][4]}, + {rowmajor_matrix[0][5], rowmajor_matrix[1][5], rowmajor_matrix[2][5], rowmajor_matrix[3][5], rowmajor_matrix[4][5]} + }; + double mat_b[5][5] = + { + {rowmajor_matrix[0][0], rowmajor_matrix[1][0], rowmajor_matrix[2][0], rowmajor_matrix[3][0], rowmajor_matrix[4][0]}, + {rowmajor_matrix[0][2], rowmajor_matrix[1][2], rowmajor_matrix[2][2], rowmajor_matrix[3][2], rowmajor_matrix[4][2]}, + {rowmajor_matrix[0][3], rowmajor_matrix[1][3], rowmajor_matrix[2][3], rowmajor_matrix[3][3], rowmajor_matrix[4][3]}, + {rowmajor_matrix[0][4], rowmajor_matrix[1][4], rowmajor_matrix[2][4], rowmajor_matrix[3][4], rowmajor_matrix[4][4]}, + {rowmajor_matrix[0][5], rowmajor_matrix[1][5], rowmajor_matrix[2][5], rowmajor_matrix[3][5], rowmajor_matrix[4][5]} + }; + double mat_c[5][5] = + { + {rowmajor_matrix[0][0], rowmajor_matrix[1][0], rowmajor_matrix[2][0], rowmajor_matrix[3][0], rowmajor_matrix[4][0]}, + {rowmajor_matrix[0][1], rowmajor_matrix[1][1], rowmajor_matrix[2][1], rowmajor_matrix[3][1], rowmajor_matrix[4][1]}, + {rowmajor_matrix[0][3], rowmajor_matrix[1][3], rowmajor_matrix[2][3], rowmajor_matrix[3][3], rowmajor_matrix[4][3]}, + {rowmajor_matrix[0][4], rowmajor_matrix[1][4], rowmajor_matrix[2][4], rowmajor_matrix[3][4], rowmajor_matrix[4][4]}, + {rowmajor_matrix[0][5], rowmajor_matrix[1][5], rowmajor_matrix[2][5], rowmajor_matrix[3][5], rowmajor_matrix[4][5]} + }; + double mat_d[5][5] = + { + {rowmajor_matrix[0][0], rowmajor_matrix[1][0], rowmajor_matrix[2][0], rowmajor_matrix[3][0], rowmajor_matrix[4][0]}, + {rowmajor_matrix[0][1], rowmajor_matrix[1][1], rowmajor_matrix[2][1], rowmajor_matrix[3][1], rowmajor_matrix[4][1]}, + {rowmajor_matrix[0][2], rowmajor_matrix[1][2], rowmajor_matrix[2][2], rowmajor_matrix[3][2], rowmajor_matrix[4][2]}, + {rowmajor_matrix[0][4], rowmajor_matrix[1][4], rowmajor_matrix[2][4], rowmajor_matrix[3][4], rowmajor_matrix[4][4]}, + {rowmajor_matrix[0][5], rowmajor_matrix[1][5], rowmajor_matrix[2][5], rowmajor_matrix[3][5], rowmajor_matrix[4][5]} + }; + double mat_e[5][5] = + { + {rowmajor_matrix[0][0], rowmajor_matrix[1][0], rowmajor_matrix[2][0], rowmajor_matrix[3][0], rowmajor_matrix[4][0]}, + {rowmajor_matrix[0][1], rowmajor_matrix[1][1], rowmajor_matrix[2][1], rowmajor_matrix[3][1], rowmajor_matrix[4][1]}, + {rowmajor_matrix[0][2], rowmajor_matrix[1][2], rowmajor_matrix[2][2], rowmajor_matrix[3][2], rowmajor_matrix[4][2]}, + {rowmajor_matrix[0][3], rowmajor_matrix[1][3], rowmajor_matrix[2][3], rowmajor_matrix[3][3], rowmajor_matrix[4][3]}, + {rowmajor_matrix[0][5], rowmajor_matrix[1][5], rowmajor_matrix[2][5], rowmajor_matrix[3][5], rowmajor_matrix[4][5]} + }; + double mat_f[5][5] = + { + {rowmajor_matrix[0][0], rowmajor_matrix[1][0], rowmajor_matrix[2][0], rowmajor_matrix[3][0], rowmajor_matrix[4][0]}, + {rowmajor_matrix[0][1], rowmajor_matrix[1][1], rowmajor_matrix[2][1], rowmajor_matrix[3][1], rowmajor_matrix[4][1]}, + {rowmajor_matrix[0][2], rowmajor_matrix[1][2], rowmajor_matrix[2][2], rowmajor_matrix[3][2], rowmajor_matrix[4][2]}, + {rowmajor_matrix[0][3], rowmajor_matrix[1][3], rowmajor_matrix[2][3], rowmajor_matrix[3][3], rowmajor_matrix[4][3]}, + {rowmajor_matrix[0][4], rowmajor_matrix[1][4], rowmajor_matrix[2][4], rowmajor_matrix[3][4], rowmajor_matrix[4][4]} + }; + + double a1 = _det5(mat_a); + double b1 = -_det5(mat_b); + double c1 = _det5(mat_c); + double d1 = -_det5(mat_d); + double e1 = _det5(mat_e); + double f1 = -_det5(mat_f); + + double mat_check[][3] = + { + {a1, b1/2, d1/2}, + {b1/2, c1, e1/2}, + {d1/2, e1/2, f1} + }; + + if (_det3(mat_check) == 0 || a1*c1 - b1*b1/4 <= 0) { + SP_ACTIVE_DESKTOP->messageStack()->flash(Inkscape::WARNING_MESSAGE, _("No ellipse found for specified points")); + return path_in; + } + + Geom::Ellipse el(a1, b1, c1, d1, e1, f1); + + double s, e; + double x0, y0, x1, y1, x2, y2, x3, y3; + double len; + + // figure out if we have a slice, guarding against rounding errors + + Path p(Geom::Point(cos(0), sin(0))); + + double end = 2 * M_PI; + for (s = 0; s < end; s += M_PI_2) { + e = s + M_PI_2; + if (e > end) + e = end; + len = 4*tan((e - s)/4)/3; + x0 = cos(s); + y0 = sin(s); + x1 = x0 + len * cos(s + M_PI_2); + y1 = y0 + len * sin(s + M_PI_2); + x3 = cos(e); + y3 = sin(e); + x2 = x3 + len * cos(e - M_PI_2); + y2 = y3 + len * sin(e - M_PI_2); + p.appendNew(Geom::Point(x1,y1), Geom::Point(x2,y2), Geom::Point(x3,y3)); + } + + Geom::Affine aff = Geom::Scale(el.ray(Geom::X), el.ray(Geom::Y)) * Geom::Rotate(el.rot_angle()) * Geom::Translate(el.center()); + + path_out.push_back(p * aff); + + return path_out; +} + +/* ######################## */ + +} //namespace LivePathEffect +} /* 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 : diff --git a/src/live_effects/lpe-ellipse_5pts.h b/src/live_effects/lpe-ellipse_5pts.h new file mode 100644 index 000000000..d3b1fccfa --- /dev/null +++ b/src/live_effects/lpe-ellipse_5pts.h @@ -0,0 +1,50 @@ +#ifndef INKSCAPE_LPE_ELLIPSE_5PTS_H +#define INKSCAPE_LPE_ELLIPSE_5PTS_H + +/** \file + * LPE "Ellipse through 5 points" implementation + */ + +/* + * Authors: + * Theodore Janeczko + * + * Copyright (C) Theodore Janeczko 2012 + * + * Released under GNU GPL, read the file 'COPYING' for more information + */ + +#include "live_effects/effect.h" +#include "live_effects/parameter/parameter.h" +#include "live_effects/parameter/point.h" + +namespace Inkscape { +namespace LivePathEffect { + +class LPEEllipse5Pts : public Effect { +public: + LPEEllipse5Pts(LivePathEffectObject *lpeobject); + virtual ~LPEEllipse5Pts(); + + virtual std::vector doEffect_path (std::vector const & path_in); + +private: + LPEEllipse5Pts(const LPEEllipse5Pts&); + LPEEllipse5Pts& operator=(const LPEEllipse5Pts&); +}; + +} //namespace LivePathEffect +} //namespace Inkscape + +#endif + +/* + 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 : diff --git a/src/live_effects/lpe-fill-between-many.cpp b/src/live_effects/lpe-fill-between-many.cpp new file mode 100644 index 000000000..00cc1fed5 --- /dev/null +++ b/src/live_effects/lpe-fill-between-many.cpp @@ -0,0 +1,77 @@ +/* + * Copyright (C) Theodore Janeczko 2012 + * + * Released under GNU GPL, read the file 'COPYING' for more information + */ + +#include +#include + +#include "live_effects/lpe-fill-between-many.h" + +#include "display/curve.h" +#include "sp-item.h" +#include "2geom/path.h" +#include "sp-shape.h" +#include "sp-text.h" +#include "2geom/bezier-curve.h" + +namespace Inkscape { +namespace LivePathEffect { + +LPEFillBetweenMany::LPEFillBetweenMany(LivePathEffectObject *lpeobject) : + Effect(lpeobject), + linked_paths(_("Linked path:"), _("Paths from which to take the original path data"), "linkedpaths", &wr, this) +{ + registerParameter( dynamic_cast(&linked_paths) ); + //perceived_path = true; +} + +LPEFillBetweenMany::~LPEFillBetweenMany() +{ + +} + +void LPEFillBetweenMany::doEffect (SPCurve * curve) +{ + std::vector res_pathv; + SPItem * firstObj = NULL; + for (std::vector::iterator iter = linked_paths._vector.begin(); iter != linked_paths._vector.end(); iter++) { + SPObject *obj; + if ((*iter)->ref.isAttached() && (obj = (*iter)->ref.getObject()) && SP_IS_ITEM(obj) && !(*iter)->_pathvector.empty()) { + Geom::Path linked_path; + if ((*iter)->reversed) { + linked_path = (*iter)->_pathvector.front().reverse(); + } else { + linked_path = (*iter)->_pathvector.front(); + } + + if (!res_pathv.empty()) { + linked_path = linked_path * SP_ITEM(obj)->getRelativeTransform(firstObj); + res_pathv.front().appendNew(linked_path.initialPoint()); + res_pathv.front().append(linked_path); + } else { + firstObj = SP_ITEM(obj); + res_pathv.push_back(linked_path); + } + } + } + if (!res_pathv.empty()) { + res_pathv.front().close(); + } + curve->set_pathvector(res_pathv); +} + +} // namespace LivePathEffect +} /* 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 : diff --git a/src/live_effects/lpe-fill-between-many.h b/src/live_effects/lpe-fill-between-many.h new file mode 100644 index 000000000..99ee8b15f --- /dev/null +++ b/src/live_effects/lpe-fill-between-many.h @@ -0,0 +1,36 @@ +#ifndef INKSCAPE_LPE_FILL_BETWEEN_MANY_H +#define INKSCAPE_LPE_FILL_BETWEEN_MANY_H + +/* + * Inkscape::LPEFillBetweenStrokes + * + * Copyright (C) Theodore Janeczko 2012 + * + * Released under GNU GPL, read the file 'COPYING' for more information + */ + +#include "live_effects/effect.h" +#include "live_effects/parameter/originalpatharray.h" + +namespace Inkscape { +namespace LivePathEffect { + +class LPEFillBetweenMany : public Effect { +public: + LPEFillBetweenMany(LivePathEffectObject *lpeobject); + virtual ~LPEFillBetweenMany(); + + virtual void doEffect (SPCurve * curve); + +private: + OriginalPathArrayParam linked_paths; + +private: + LPEFillBetweenMany(const LPEFillBetweenMany&); + LPEFillBetweenMany& operator=(const LPEFillBetweenMany&); +}; + +}; //namespace LivePathEffect +}; //namespace Inkscape + +#endif diff --git a/src/live_effects/lpe-fill-between-strokes.cpp b/src/live_effects/lpe-fill-between-strokes.cpp new file mode 100644 index 000000000..e72979ed0 --- /dev/null +++ b/src/live_effects/lpe-fill-between-strokes.cpp @@ -0,0 +1,116 @@ +/* + * Copyright (C) Theodore Janeczko 2012 + * + * Released under GNU GPL, read the file 'COPYING' for more information + */ + +#include + +#include "live_effects/lpe-fill-between-strokes.h" + +#include "display/curve.h" +#include "sp-item.h" +#include "2geom/path.h" +#include "sp-shape.h" +#include "sp-text.h" +#include "2geom/bezier-curve.h" + +namespace Inkscape { +namespace LivePathEffect { + +LPEFillBetweenStrokes::LPEFillBetweenStrokes(LivePathEffectObject *lpeobject) : + Effect(lpeobject), + linked_path(_("Linked path:"), _("Path from which to take the original path data"), "linkedpath", &wr, this), + second_path(_("Second path:"), _("Second path from which to take the original path data"), "secondpath", &wr, this), + reverse_second(_("Reverse Second"), _("Reverses the second path order"), "reversesecond", &wr, this) +{ + registerParameter( dynamic_cast(&linked_path) ); + registerParameter( dynamic_cast(&second_path) ); + registerParameter( dynamic_cast(&reverse_second) ); + //perceived_path = true; +} + +LPEFillBetweenStrokes::~LPEFillBetweenStrokes() +{ + +} + +void LPEFillBetweenStrokes::doEffect (SPCurve * curve) +{ + if (curve) { + if ( linked_path.linksToPath() && second_path.linksToPath() && linked_path.getObject() && second_path.getObject() ) { + std::vector linked_pathv = linked_path.get_pathvector(); + std::vector second_pathv = second_path.get_pathvector(); + std::vector result_linked_pathv; + std::vector result_second_pathv; + Geom::Affine second_transform = second_path.getObject()->getRelativeTransform(linked_path.getObject()); + + for (std::vector::iterator iter = linked_pathv.begin(); iter != linked_pathv.end(); ++iter) + { + result_linked_pathv.push_back((*iter)); + } + for (std::vector::iterator iter = second_pathv.begin(); iter != second_pathv.end(); ++iter) + { + result_second_pathv.push_back((*iter) * second_transform); + } + + if ( !result_linked_pathv.empty() && !result_second_pathv.empty() && !result_linked_pathv.front().closed() ) { + if (reverse_second.get_value()) + { + result_linked_pathv.front().appendNew(result_second_pathv.front().finalPoint()); + result_linked_pathv.front().append(result_second_pathv.front().reverse()); + } + else + { + result_linked_pathv.front().appendNew(result_second_pathv.front().initialPoint()); + result_linked_pathv.front().append(result_second_pathv.front()); + } + curve->set_pathvector(result_linked_pathv); + } + else if ( !result_linked_pathv.empty() ) { + curve->set_pathvector(result_linked_pathv); + } + else if ( !result_second_pathv.empty() ) { + curve->set_pathvector(result_second_pathv); + } + } + else if ( linked_path.linksToPath() && linked_path.getObject() ) { + std::vector linked_pathv = linked_path.get_pathvector(); + std::vector result_pathv; + + for (std::vector::iterator iter = linked_pathv.begin(); iter != linked_pathv.end(); ++iter) + { + result_pathv.push_back((*iter)); + } + if ( !result_pathv.empty() ) { + curve->set_pathvector(result_pathv); + } + } + else if ( second_path.linksToPath() && second_path.getObject() ) { + std::vector second_pathv = second_path.get_pathvector(); + std::vector result_pathv; + + for (std::vector::iterator iter = second_pathv.begin(); iter != second_pathv.end(); ++iter) + { + result_pathv.push_back((*iter)); + } + if ( !result_pathv.empty() ) { + curve->set_pathvector(result_pathv); + } + } + } +} + +} // namespace LivePathEffect +} /* 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 : diff --git a/src/live_effects/lpe-fill-between-strokes.h b/src/live_effects/lpe-fill-between-strokes.h new file mode 100644 index 000000000..ec57b1852 --- /dev/null +++ b/src/live_effects/lpe-fill-between-strokes.h @@ -0,0 +1,38 @@ +#ifndef INKSCAPE_LPE_FILL_BETWEEN_STROKES_H +#define INKSCAPE_LPE_FILL_BETWEEN_STROKES_H + +/* + * Inkscape::LPEFillBetweenStrokes + * + * Copyright (C) Theodore Janeczko 2012 + * + * Released under GNU GPL, read the file 'COPYING' for more information + */ + +#include "live_effects/effect.h" +#include "live_effects/parameter/originalpath.h" + +namespace Inkscape { +namespace LivePathEffect { + +class LPEFillBetweenStrokes : public Effect { +public: + LPEFillBetweenStrokes(LivePathEffectObject *lpeobject); + virtual ~LPEFillBetweenStrokes(); + + virtual void doEffect (SPCurve * curve); + +private: + OriginalPathParam linked_path; + OriginalPathParam second_path; + BoolParam reverse_second; + +private: + LPEFillBetweenStrokes(const LPEFillBetweenStrokes&); + LPEFillBetweenStrokes& operator=(const LPEFillBetweenStrokes&); +}; + +}; //namespace LivePathEffect +}; //namespace Inkscape + +#endif diff --git a/src/live_effects/lpe-jointype.cpp b/src/live_effects/lpe-jointype.cpp new file mode 100644 index 000000000..97c0a1b8a --- /dev/null +++ b/src/live_effects/lpe-jointype.cpp @@ -0,0 +1,203 @@ +/** \file + * LPE "Join Type" implementation + */ + /* Authors: + * + * Liam P White + * + * Copyright (C) 2014 Authors + * + * Released under GNU GPL v2, read the file 'COPYING' for more information + */ + +#include + +#include "sp-shape.h" +#include "style.h" +#include "xml/repr.h" +#include "sp-paint-server.h" +#include "svg/svg-color.h" +#include "desktop-style.h" +#include "svg/css-ostringstream.h" +#include "display/curve.h" +#include "live_effects/parameter/enum.h" + +#include <2geom/path.h> +#include <2geom/svg-elliptical-arc.h> +#include "live_effects/pathoutlineprovider.h" + +#include "lpe-jointype.h" + +namespace Inkscape { +namespace LivePathEffect { + +static const Util::EnumData JoinTypeData[] = { + {LINEJOIN_STRAIGHT, N_("Beveled"), "bevel"}, + {LINEJOIN_ROUND, N_("Rounded"), "round"}, + {LINEJOIN_POINTY, N_("Miter"), "miter"}, + {LINEJOIN_REFLECTED, N_("Reflected"), "extrapolated"}, + {LINEJOIN_EXTRAPOLATED, N_("Extrapolated arc"), "extrp_arc"} +}; + +static const Util::EnumData CapTypeData[] = { + {butt_straight, N_("Butt"), "butt"}, + {butt_round, N_("Rounded"), "round"}, + {butt_square, N_("Square"), "square"}, + {butt_pointy, N_("Peak"), "peak"} +}; + +static const Util::EnumDataConverter CapTypeConverter(CapTypeData, sizeof(CapTypeData)/sizeof(*CapTypeData)); +static const Util::EnumDataConverter JoinTypeConverter(JoinTypeData, sizeof(JoinTypeData)/sizeof(*JoinTypeData)); + +LPEJoinType::LPEJoinType(LivePathEffectObject *lpeobject) : + Effect(lpeobject), + line_width(_("Line width"), _("Thickness of the stroke"), "line_width", &wr, this, 10.), + linecap_type(_("Line cap"), _("The end shape of the stroke"), "linecap_type", CapTypeConverter, &wr, this, butt_straight), + linejoin_type(_("Join:"), _("Determines the shape of the path's corners"), "linejoin_type", JoinTypeConverter, &wr, this, join_pointy), + miter_limit(_("Miter limit:"), _("Maximum length of the miter join (in units of stroke width)"), "miter_limit", &wr, this, 100.), + attempt_force_join(_("Force miter"), _("Overrides the miter limit and forces a join."), "attempt_force_join", &wr, this, true) +{ + show_orig_path = true; + registerParameter( dynamic_cast(&linecap_type) ); + registerParameter( dynamic_cast(&line_width) ); + registerParameter( dynamic_cast(&linejoin_type) ); + registerParameter( dynamic_cast(&miter_limit) ); + registerParameter( dynamic_cast(&attempt_force_join) ); + was_initialized = false; +} + +LPEJoinType::~LPEJoinType() +{ +} + +//from LPEPowerStroke -- sets fill if stroke color because we will +//be converting to a fill to make the new join. + +void LPEJoinType::doOnApply(SPLPEItem const* lpeitem) +{ + if (SP_IS_SHAPE(lpeitem)) { + SPLPEItem* item = const_cast(lpeitem); + double width = (lpeitem && lpeitem->style) ? lpeitem->style->stroke_width.computed : 1.; + + SPCSSAttr *css = sp_repr_css_attr_new (); + if (lpeitem->style->stroke.isSet()) { + if (lpeitem->style->stroke.isPaintserver()) { + SPPaintServer * server = lpeitem->style->getStrokePaintServer(); + if (server) { + Glib::ustring str; + str += "url(#"; + str += server->getId(); + str += ")"; + sp_repr_css_set_property (css, "fill", str.c_str()); + } + } else if (lpeitem->style->stroke.isColor()) { + gchar c[64]; + sp_svg_write_color (c, sizeof(c), lpeitem->style->stroke.value.color.toRGBA32(SP_SCALE24_TO_FLOAT(lpeitem->style->stroke_opacity.value))); + sp_repr_css_set_property (css, "fill", c); + } else { + sp_repr_css_set_property (css, "fill", "none"); + } + } else { + sp_repr_css_unset_property (css, "fill"); + } + + sp_repr_css_set_property(css, "stroke", "none"); + + sp_desktop_apply_css_recursive(item, css, true); + sp_repr_css_attr_unref (css); + if (!was_initialized) + { + was_initialized = true; + line_width.param_set_value(width); + } + } else { + g_warning("LPE Join Type can only be applied to paths (not groups)."); + } +} + +//from LPEPowerStroke -- sets stroke color from existing fill color + +void LPEJoinType::doOnRemove(SPLPEItem const* lpeitem) +{ + + if (SP_IS_SHAPE(lpeitem)) { + SPLPEItem *item = const_cast(lpeitem); + + SPCSSAttr *css = sp_repr_css_attr_new (); + if (lpeitem->style->fill.isSet()) { + if (lpeitem->style->fill.isPaintserver()) { + SPPaintServer * server = lpeitem->style->getFillPaintServer(); + if (server) { + Glib::ustring str; + str += "url(#"; + str += server->getId(); + str += ")"; + sp_repr_css_set_property (css, "stroke", str.c_str()); + } + } else if (lpeitem->style->fill.isColor()) { + gchar c[64]; + sp_svg_write_color (c, sizeof(c), lpeitem->style->stroke.value.color.toRGBA32(SP_SCALE24_TO_FLOAT(lpeitem->style->stroke_opacity.value))); + sp_repr_css_set_property (css, "stroke", c); + } else { + sp_repr_css_set_property (css, "stroke", "none"); + } + } else { + sp_repr_css_unset_property (css, "stroke"); + } + + Inkscape::CSSOStringStream os; + os << fabs(line_width); + sp_repr_css_set_property (css, "stroke-width", os.str().c_str()); + + sp_repr_css_set_property(css, "fill", "none"); + + sp_desktop_apply_css_recursive(item, css, true); + sp_repr_css_attr_unref (css); + item->updateRepr(); + } +} + + +std::vector LPEJoinType::doEffect_path(std::vector const & path_in) +{ + std::vector path_out = std::vector(); + if (path_in.empty()) + { + return path_out; + } + Path p = Path(); + Path outlinepath = Path(); + for (unsigned i = 0; i < path_in.size(); i++) + { + p.LoadPath(path_in[i], Geom::Affine(), false, ( (i==0) ? false : true)); + } + + #define miter_lim ( (attempt_force_join) ? std::numeric_limits::max() : fabs(line_width * miter_limit)) + + //magic! + if (linejoin_type.get_value() <= 2) + { + p.Outline(&outlinepath, line_width / 2, static_cast( linejoin_type.get_value() ), + static_cast( linecap_type.get_value() ), miter_lim); + //fix memory leak + std::vector *pv_p = outlinepath.MakePathVector(); + path_out = *pv_p; + delete pv_p; + + } else if (linejoin_type.get_value() == 3) { + //reflected arc join + path_out = Outline::outlinePath(path_in, line_width, static_cast( linejoin_type.get_value() ), + static_cast( linecap_type.get_value() ), miter_lim); + + } else if (linejoin_type.get_value() == 4) { + //extrapolated arc join + path_out = Outline::outlinePath_extr(path_in, line_width, LINEJOIN_STRAIGHT, static_cast(linecap_type.get_value()), miter_lim); + + } + + #undef miter_lim + return path_out; +} + +} //namespace LivePathEffect +} //namespace Inkscape diff --git a/src/live_effects/lpe-jointype.h b/src/live_effects/lpe-jointype.h new file mode 100755 index 000000000..db113c66a --- /dev/null +++ b/src/live_effects/lpe-jointype.h @@ -0,0 +1,43 @@ +/* Authors: + * Liam P White + * + * Copyright (C) 2014 Authors + * + * Released under GNU GPL v2, read the file COPYING for more information + */ +#ifndef INKSCAPE_LPE_JOINTYPE_H +#define INKSCAPE_LPE_JOINTYPE_H + +#include "live_effects/effect.h" +#include "live_effects/parameter/parameter.h" +#include "live_effects/parameter/point.h" +#include "live_effects/parameter/enum.h" + +namespace Inkscape { +namespace LivePathEffect { + +class LPEJoinType : public Effect { +public: + LPEJoinType(LivePathEffectObject *lpeobject); + virtual ~LPEJoinType(); + + virtual void doOnApply(SPLPEItem const* lpeitem); + virtual void doOnRemove(SPLPEItem const* lpeitem); + virtual std::vector doEffect_path (std::vector const & path_in); + +private: + LPEJoinType(const LPEJoinType&); + LPEJoinType& operator=(const LPEJoinType&); + + ScalarParam line_width; + EnumParam linecap_type; + EnumParam linejoin_type; + ScalarParam miter_limit; + BoolParam attempt_force_join; + bool was_initialized; +}; + +} //namespace LivePathEffect +} //namespace Inkscape + +#endif diff --git a/src/live_effects/lpe-powerstroke-interpolators.h b/src/live_effects/lpe-powerstroke-interpolators.h index 6f5b75af8..f080b06e6 100644 --- a/src/live_effects/lpe-powerstroke-interpolators.h +++ b/src/live_effects/lpe-powerstroke-interpolators.h @@ -27,7 +27,8 @@ enum InterpolatorType { INTERP_LINEAR, INTERP_CUBICBEZIER, INTERP_CUBICBEZIER_JOHAN, - INTERP_SPIRO + INTERP_SPIRO, + INTERP_CUBICBEZIER_SMOOTH }; class Interpolator { @@ -133,6 +134,43 @@ private: CubicBezierJohan& operator=(const CubicBezierJohan&); }; +/// @todo invent name for this class +class CubicBezierSmooth : public Interpolator { +public: + CubicBezierSmooth(double beta = 0.2) { + _beta = beta; + }; + virtual ~CubicBezierSmooth() {}; + + virtual Path interpolateToPath(std::vector const &points) const { + Path fit; + fit.start(points.at(0)); + unsigned int num_points = points.size(); + for (unsigned int i = 1; i < num_points; ++i) { + Point p0 = points.at(i-1); + Point p1 = points.at(i); + Point dx = Point(p1[X] - p0[X], 0); + if (i == 1) { + fit.appendNew(p0, p1-0.75*dx, p1); + } else if (i == points.size() - 1) { + fit.appendNew(p0+0.75*dx, p1, p1); + } else { + fit.appendNew(p0+_beta*dx, p1-_beta*dx, p1); + } + } + return fit; + }; + + void setBeta(double beta) { + _beta = beta; + } + + double _beta; + +private: + CubicBezierSmooth(const CubicBezierSmooth&); + CubicBezierSmooth& operator=(const CubicBezierSmooth&); +}; class SpiroInterpolator : public Interpolator { public: @@ -179,6 +217,8 @@ Interpolator::create(InterpolatorType type) { return new Geom::Interpolate::CubicBezierJohan(); case INTERP_SPIRO: return new Geom::Interpolate::SpiroInterpolator(); + case INTERP_CUBICBEZIER_SMOOTH: + return new Geom::Interpolate::CubicBezierSmooth(); default: return new Geom::Interpolate::Linear(); } diff --git a/src/live_effects/lpe-powerstroke.cpp b/src/live_effects/lpe-powerstroke.cpp index acf8ab6a5..f6bc1de65 100644 --- a/src/live_effects/lpe-powerstroke.cpp +++ b/src/live_effects/lpe-powerstroke.cpp @@ -15,6 +15,11 @@ #include "sp-shape.h" #include "style.h" +#include "xml/repr.h" +#include "sp-paint-server.h" +#include "svg/svg-color.h" +#include "desktop-style.h" +#include "svg/css-ostringstream.h" #include "display/curve.h" #include <2geom/path.h> @@ -185,6 +190,7 @@ namespace Inkscape { namespace LivePathEffect { static const Util::EnumData InterpolatorTypeData[] = { + {Geom::Interpolate::INTERP_CUBICBEZIER_SMOOTH, N_("CubicBezierSmooth"), "CubicBezierSmooth"}, {Geom::Interpolate::INTERP_LINEAR , N_("Linear"), "Linear"}, {Geom::Interpolate::INTERP_CUBICBEZIER , N_("CubicBezierFit"), "CubicBezierFit"}, {Geom::Interpolate::INTERP_CUBICBEZIER_JOHAN , N_("CubicBezierJohan"), "CubicBezierJohan"}, @@ -222,9 +228,7 @@ static const Util::EnumData LineJoinTypeData[] = { {LINEJOIN_EXTRP_MITER, N_("Extrapolated"), "extrapolated"}, {LINEJOIN_MITER, N_("Miter"), "miter"}, {LINEJOIN_SPIRO, N_("Spiro"), "spiro"}, -#ifdef LPE_ENABLE_TEST_EFFECTS {LINEJOIN_EXTRP_MITER_ARC, N_("Extrapolated arc"), "extrp_arc"}, -#endif }; static const Util::EnumDataConverter LineJoinTypeConverter(LineJoinTypeData, sizeof(LineJoinTypeData)/sizeof(*LineJoinTypeData)); @@ -232,12 +236,12 @@ LPEPowerStroke::LPEPowerStroke(LivePathEffectObject *lpeobject) : Effect(lpeobject), offset_points(_("Offset points"), _("Offset points"), "offset_points", &wr, this), sort_points(_("Sort points"), _("Sort offset points according to their time value along the curve"), "sort_points", &wr, this, true), - interpolator_type(_("Interpolator type:"), _("Determines which kind of interpolator will be used to interpolate between stroke width along the path"), "interpolator_type", InterpolatorTypeConverter, &wr, this, Geom::Interpolate::INTERP_CUBICBEZIER_JOHAN), + interpolator_type(_("Interpolator type:"), _("Determines which kind of interpolator will be used to interpolate between stroke width along the path"), "interpolator_type", InterpolatorTypeConverter, &wr, this, Geom::Interpolate::INTERP_CUBICBEZIER), interpolator_beta(_("Smoothness:"), _("Sets the smoothness for the CubicBezierJohan interpolator; 0 = linear interpolation, 1 = smooth"), "interpolator_beta", &wr, this, 0.2), - start_linecap_type(_("Start cap:"), _("Determines the shape of the path's start"), "start_linecap_type", LineCapTypeConverter, &wr, this, LINECAP_ROUND), - linejoin_type(_("Join:"), _("Determines the shape of the path's corners"), "linejoin_type", LineJoinTypeConverter, &wr, this, LINEJOIN_ROUND), + start_linecap_type(_("Start cap:"), _("Determines the shape of the path's start"), "start_linecap_type", LineCapTypeConverter, &wr, this, LINECAP_BUTT), + linejoin_type(_("Join:"), _("Determines the shape of the path's corners"), "linejoin_type", LineJoinTypeConverter, &wr, this, LINEJOIN_EXTRP_MITER_ARC), miter_limit(_("Miter limit:"), _("Maximum length of the miter (in units of stroke width)"), "miter_limit", &wr, this, 4.), - end_linecap_type(_("End cap:"), _("Determines the shape of the path's end"), "end_linecap_type", LineCapTypeConverter, &wr, this, LINECAP_ROUND) + end_linecap_type(_("End cap:"), _("Determines the shape of the path's end"), "end_linecap_type", LineCapTypeConverter, &wr, this, LINECAP_BUTT) { show_orig_path = true; @@ -266,20 +270,52 @@ void LPEPowerStroke::doOnApply(SPLPEItem const* lpeitem) { if (SP_IS_SHAPE(lpeitem)) { + SPLPEItem* item = const_cast(lpeitem); std::vector points; Geom::PathVector const &pathv = SP_SHAPE(lpeitem)->_curve->get_pathvector(); - double width = (lpeitem && lpeitem->style) ? lpeitem->style->stroke_width.computed : 1.; + double width = (lpeitem && lpeitem->style) ? lpeitem->style->stroke_width.computed / 2 : 1.; + + SPCSSAttr *css = sp_repr_css_attr_new (); + if (lpeitem->style->stroke.isSet()) { + if (lpeitem->style->stroke.isPaintserver()) { + SPPaintServer * server = lpeitem->style->getStrokePaintServer(); + if (server) { + Glib::ustring str; + str += "url(#"; + str += server->getId(); + str += ")"; + sp_repr_css_set_property (css, "fill", str.c_str()); + } + } else if (lpeitem->style->stroke.isColor()) { + gchar c[64]; + sp_svg_write_color (c, sizeof(c), lpeitem->style->stroke.value.color.toRGBA32(SP_SCALE24_TO_FLOAT(lpeitem->style->stroke_opacity.value))); + sp_repr_css_set_property (css, "fill", c); + } else { + sp_repr_css_set_property (css, "fill", "none"); + } + } else { + sp_repr_css_unset_property (css, "fill"); + } + + sp_repr_css_set_property(css, "stroke", "none"); + + sp_desktop_apply_css_recursive(item, css, true); + sp_repr_css_attr_unref (css); + + item->updateRepr(); if (pathv.empty()) { - points.push_back( Geom::Point(0.,width) ); + points.push_back( Geom::Point(0.2,width) ); points.push_back( Geom::Point(0.5,width) ); - points.push_back( Geom::Point(1.,width) ); + points.push_back( Geom::Point(0.8,width) ); } else { Geom::Path const &path = pathv.front(); Geom::Path::size_type const size = path.size_default(); - points.push_back( Geom::Point(0.,width) ); + if (!path.closed()) { + points.push_back( Geom::Point(0.2,width) ); + } points.push_back( Geom::Point(0.5*size,width) ); if (!path.closed()) { - points.push_back( Geom::Point(size,width) ); + points.push_back( Geom::Point(size - 0.2,width) ); } } offset_points.param_set_and_write_new_value(points); @@ -288,6 +324,45 @@ LPEPowerStroke::doOnApply(SPLPEItem const* lpeitem) } } +void LPEPowerStroke::doOnRemove(SPLPEItem const* lpeitem) +{ + if (SP_IS_SHAPE(lpeitem)) { + SPLPEItem *item = const_cast(lpeitem); + SPCSSAttr *css = sp_repr_css_attr_new (); + if (lpeitem->style->fill.isSet()) { + if (lpeitem->style->fill.isPaintserver()) { + SPPaintServer * server = lpeitem->style->getFillPaintServer(); + if (server) { + Glib::ustring str; + str += "url(#"; + str += server->getId(); + str += ")"; + sp_repr_css_set_property (css, "stroke", str.c_str()); + } + } else if (lpeitem->style->fill.isColor()) { + gchar c[64]; + sp_svg_write_color (c, sizeof(c), lpeitem->style->stroke.value.color.toRGBA32(SP_SCALE24_TO_FLOAT(lpeitem->style->stroke_opacity.value))); + sp_repr_css_set_property (css, "stroke", c); + } else { + sp_repr_css_set_property (css, "stroke", "none"); + } + } else { + sp_repr_css_unset_property (css, "stroke"); + } + + Inkscape::CSSOStringStream os; + os << offset_points.median_width() * 2; + sp_repr_css_set_property (css, "stroke-width", os.str().c_str()); + + sp_repr_css_set_property(css, "fill", "none"); + + sp_desktop_apply_css_recursive(item, css, true); + sp_repr_css_attr_unref (css); + + item->updateRepr(); + } +} + void LPEPowerStroke::adjustForNewPath(std::vector const & path_in) { diff --git a/src/live_effects/lpe-powerstroke.h b/src/live_effects/lpe-powerstroke.h index 7bc736820..a773434aa 100644 --- a/src/live_effects/lpe-powerstroke.h +++ b/src/live_effects/lpe-powerstroke.h @@ -25,9 +25,11 @@ public: LPEPowerStroke(LivePathEffectObject *lpeobject); virtual ~LPEPowerStroke(); + virtual std::vector doEffect_path (std::vector const & path_in); virtual void doOnApply(SPLPEItem const* lpeitem); + virtual void doOnRemove(SPLPEItem const* lpeitem); // methods called by path-manipulator upon edits void adjustForNewPath(std::vector const & path_in); diff --git a/src/live_effects/parameter/Makefile_insert b/src/live_effects/parameter/Makefile_insert index efdda686a..37cc3dc62 100644 --- a/src/live_effects/parameter/Makefile_insert +++ b/src/live_effects/parameter/Makefile_insert @@ -18,10 +18,14 @@ ink_common_sources += \ live_effects/parameter/path.h \ live_effects/parameter/originalpath.cpp \ live_effects/parameter/originalpath.h \ + live_effects/parameter/originalpatharray.cpp \ + live_effects/parameter/originalpatharray.h \ live_effects/parameter/powerstrokepointarray.cpp \ live_effects/parameter/powerstrokepointarray.h \ live_effects/parameter/text.cpp \ live_effects/parameter/text.h \ + live_effects/parameter/transformedpoint.cpp \ + live_effects/parameter/transformedpoint.h \ live_effects/parameter/unit.cpp \ live_effects/parameter/unit.h \ live_effects/parameter/vector.cpp \ diff --git a/src/live_effects/parameter/originalpatharray.cpp b/src/live_effects/parameter/originalpatharray.cpp new file mode 100644 index 000000000..29e4c409c --- /dev/null +++ b/src/live_effects/parameter/originalpatharray.cpp @@ -0,0 +1,486 @@ +/* + * Copyright (C) Johan Engelen 2008 + * + * Released under GNU GPL, read the file 'COPYING' for more information + */ + +#include "live_effects/parameter/originalpatharray.h" + +#include +#include +#include +#include + +#include + +#include "inkscape.h" +#include "icon-size.h" +#include "widgets/icon.h" +#include "ui/clipboard.h" +#include "svg/svg.h" +#include "svg/stringstream.h" +#include "originalpath.h" +#include "uri.h" +#include "display/curve.h" + +#include +#include <2geom/coord.h> +#include <2geom/point.h> +#include "sp-shape.h" +#include "sp-text.h" +#include "live_effects/effect.h" + +#include "verbs.h" +#include "document-undo.h" +#include "document.h" + +namespace Inkscape { + +namespace LivePathEffect { + +class OriginalPathArrayParam::ModelColumns : public Gtk::TreeModel::ColumnRecord +{ +public: + + ModelColumns() + { + add(_colObject); + add(_colLabel); + add(_colReverse); + } + virtual ~ModelColumns() {} + + Gtk::TreeModelColumn _colObject; + Gtk::TreeModelColumn _colLabel; + Gtk::TreeModelColumn _colReverse; +}; + +OriginalPathArrayParam::OriginalPathArrayParam( const Glib::ustring& label, + const Glib::ustring& tip, + const Glib::ustring& key, + Inkscape::UI::Widget::Registry* wr, + Effect* effect ) +: Parameter(label, tip, key, wr, effect), + _vector(), + _tree(), + _text_renderer(), + _toggle_renderer(), + _scroller() +{ + _model = new ModelColumns(); + _store = Gtk::TreeStore::create(*_model); + _tree.set_model(_store); + + _tree.set_reorderable(true); + _tree.enable_model_drag_dest (Gdk::ACTION_MOVE); + + _text_renderer = manage(new Gtk::CellRendererText()); + int nameColNum = _tree.append_column(_("Name"), *_text_renderer) - 1; + _name_column = _tree.get_column(nameColNum); + _name_column->add_attribute(_text_renderer->property_text(), _model->_colLabel); + + _tree.set_expander_column( *_tree.get_column(nameColNum) ); + _tree.set_search_column(_model->_colLabel); + + Gtk::CellRendererToggle * _toggle_renderer = manage(new Gtk::CellRendererToggle()); + int toggleColNum = _tree.append_column(_("Reverse"), *_toggle_renderer) - 1; + Gtk::TreeViewColumn* col = _tree.get_column(toggleColNum); + _toggle_renderer->set_activatable(true); + _toggle_renderer->signal_toggled().connect(sigc::mem_fun(*this, &OriginalPathArrayParam::on_reverse_toggled)); + col->add_attribute(_toggle_renderer->property_active(), _model->_colReverse); + + _scroller.add(_tree); + _scroller.set_policy( Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC ); + _scroller.set_shadow_type(Gtk::SHADOW_IN); + + oncanvas_editable = true; + +} + +OriginalPathArrayParam::~OriginalPathArrayParam() +{ + while (!_vector.empty()) { + PathAndDirection *w = _vector.back(); + _vector.pop_back(); + unlink(w); + delete w; + } + delete _model; +} + +void OriginalPathArrayParam::on_reverse_toggled(const Glib::ustring& path) +{ + Gtk::TreeModel::iterator iter = _store->get_iter(path); + Gtk::TreeModel::Row row = *iter; + PathAndDirection *w = row[_model->_colObject]; + row[_model->_colReverse] = !row[_model->_colReverse]; + w->reversed = row[_model->_colReverse]; + + gchar * full = param_getSVGValue(); + param_write_to_repr(full); + g_free(full); + DocumentUndo::done(param_effect->getSPDoc(), SP_VERB_DIALOG_LIVE_PATH_EFFECT, + _("Link path parameter to path")); +} + +void OriginalPathArrayParam::param_set_default() +{ + +} + +Gtk::Widget* OriginalPathArrayParam::param_newWidget() +{ + Gtk::VBox* vbox = Gtk::manage(new Gtk::VBox()); + Gtk::HBox* hbox = Gtk::manage(new Gtk::HBox()); + + vbox->pack_start(_scroller, Gtk::PACK_EXPAND_WIDGET); + + + { // Paste path to link button + Gtk::Widget *pIcon = Gtk::manage( sp_icon_get_icon( GTK_STOCK_PASTE, Inkscape::ICON_SIZE_BUTTON) ); + Gtk::Button *pButton = Gtk::manage(new Gtk::Button()); + pButton->set_relief(Gtk::RELIEF_NONE); + pIcon->show(); + pButton->add(*pIcon); + pButton->show(); + pButton->signal_clicked().connect(sigc::mem_fun(*this, &OriginalPathArrayParam::on_link_button_click)); + hbox->pack_start(*pButton, Gtk::PACK_SHRINK); + pButton->set_tooltip_text(_("Link to path")); + } + + { // Remove linked path + Gtk::Widget *pIcon = Gtk::manage( sp_icon_get_icon( GTK_STOCK_REMOVE, Inkscape::ICON_SIZE_BUTTON) ); + Gtk::Button *pButton = Gtk::manage(new Gtk::Button()); + pButton->set_relief(Gtk::RELIEF_NONE); + pIcon->show(); + pButton->add(*pIcon); + pButton->show(); + pButton->signal_clicked().connect(sigc::mem_fun(*this, &OriginalPathArrayParam::on_remove_button_click)); + hbox->pack_start(*pButton, Gtk::PACK_SHRINK); + pButton->set_tooltip_text(_("Remove Path")); + } + + { // Move Down + Gtk::Widget *pIcon = Gtk::manage( sp_icon_get_icon( GTK_STOCK_GO_DOWN, Inkscape::ICON_SIZE_BUTTON) ); + Gtk::Button *pButton = Gtk::manage(new Gtk::Button()); + pButton->set_relief(Gtk::RELIEF_NONE); + pIcon->show(); + pButton->add(*pIcon); + pButton->show(); + pButton->signal_clicked().connect(sigc::mem_fun(*this, &OriginalPathArrayParam::on_down_button_click)); + hbox->pack_end(*pButton, Gtk::PACK_SHRINK); + pButton->set_tooltip_text(_("Move Down")); + } + + { // Move Down + Gtk::Widget *pIcon = Gtk::manage( sp_icon_get_icon( GTK_STOCK_GO_UP, Inkscape::ICON_SIZE_BUTTON) ); + Gtk::Button *pButton = Gtk::manage(new Gtk::Button()); + pButton->set_relief(Gtk::RELIEF_NONE); + pIcon->show(); + pButton->add(*pIcon); + pButton->show(); + pButton->signal_clicked().connect(sigc::mem_fun(*this, &OriginalPathArrayParam::on_up_button_click)); + hbox->pack_end(*pButton, Gtk::PACK_SHRINK); + pButton->set_tooltip_text(_("Move Up")); + } + + vbox->pack_end(*hbox, Gtk::PACK_SHRINK); + + vbox->show_all_children(true); + + return vbox; +} + +bool OriginalPathArrayParam::_selectIndex(const Gtk::TreeIter& iter, int* i) +{ + if ((*i)-- <= 0) { + _tree.get_selection()->select(iter); + return true; + } + return false; +} + +void OriginalPathArrayParam::on_up_button_click() +{ + Gtk::TreeModel::iterator iter = _tree.get_selection()->get_selected(); + if (iter) { + Gtk::TreeModel::Row row = *iter; + + int i = -1; + std::vector::iterator piter = _vector.begin(); + for (std::vector::iterator iter = _vector.begin(); iter != _vector.end(); piter = iter, i++, iter++) { + if (*iter == row[_model->_colObject]) { + _vector.erase(iter); + _vector.insert(piter, row[_model->_colObject]); + break; + } + } + + gchar * full = param_getSVGValue(); + param_write_to_repr(full); + g_free(full); + + DocumentUndo::done(param_effect->getSPDoc(), SP_VERB_DIALOG_LIVE_PATH_EFFECT, + _("Move path up")); + + _store->foreach_iter(sigc::bind(sigc::mem_fun(*this, &OriginalPathArrayParam::_selectIndex), &i)); + } +} + +void OriginalPathArrayParam::on_down_button_click() +{ + Gtk::TreeModel::iterator iter = _tree.get_selection()->get_selected(); + if (iter) { + Gtk::TreeModel::Row row = *iter; + + int i = 0; + for (std::vector::iterator iter = _vector.begin(); iter != _vector.end(); i++, iter++) { + if (*iter == row[_model->_colObject]) { + std::vector::iterator niter = _vector.erase(iter); + if (niter != _vector.end()) { + niter++; + i++; + } + _vector.insert(niter, row[_model->_colObject]); + break; + } + } + + gchar * full = param_getSVGValue(); + param_write_to_repr(full); + g_free(full); + + DocumentUndo::done(param_effect->getSPDoc(), SP_VERB_DIALOG_LIVE_PATH_EFFECT, + _("Move path down")); + + _store->foreach_iter(sigc::bind(sigc::mem_fun(*this, &OriginalPathArrayParam::_selectIndex), &i)); + } +} + +void OriginalPathArrayParam::on_remove_button_click() +{ + Gtk::TreeModel::iterator iter = _tree.get_selection()->get_selected(); + if (iter) { + Gtk::TreeModel::Row row = *iter; + remove_link(row[_model->_colObject]); + + gchar * full = param_getSVGValue(); + param_write_to_repr(full); + g_free(full); + + DocumentUndo::done(param_effect->getSPDoc(), SP_VERB_DIALOG_LIVE_PATH_EFFECT, + _("Remove path")); + } + +} + +void +OriginalPathArrayParam::on_link_button_click() +{ + Inkscape::UI::ClipboardManager *cm = Inkscape::UI::ClipboardManager::get(); + Glib::ustring pathid = cm->getShapeOrTextObjectId(SP_ACTIVE_DESKTOP); + + if (pathid == "") { + return; + } + // add '#' at start to make it an uri. + pathid.insert(pathid.begin(), '#'); + + Inkscape::SVGOStringStream os; + bool foundOne = false; + for (std::vector::const_iterator iter = _vector.begin(); iter != _vector.end(); iter++) { + if (foundOne) { + os << "|"; + } else { + foundOne = true; + } + os << (*iter)->href << "," << ((*iter)->reversed ? "1" : "0"); + } + + if (foundOne) { + os << "|"; + } + + os << pathid.c_str() << ",0"; + + param_write_to_repr(os.str().c_str()); + DocumentUndo::done(param_effect->getSPDoc(), SP_VERB_DIALOG_LIVE_PATH_EFFECT, + _("Link path parameter to path")); +} + +void OriginalPathArrayParam::unlink(PathAndDirection* to) +{ + to->linked_modified_connection.disconnect(); + to->linked_delete_connection.disconnect(); + to->ref.detach(); + to->_pathvector = Geom::PathVector(); + if (to->href) { + g_free(to->href); + to->href = NULL; + } +} + +void OriginalPathArrayParam::remove_link(PathAndDirection* to) +{ + unlink(to); + for (std::vector::iterator iter = _vector.begin(); iter != _vector.end(); iter++) { + if (*iter == to) { + PathAndDirection *w = *iter; + _vector.erase(iter); + delete w; + return; + } + } +} + +void OriginalPathArrayParam::linked_delete(SPObject */*deleted*/, PathAndDirection* to) +{ + //remove_link(to); + + gchar * full = param_getSVGValue(); + param_write_to_repr(full); + g_free(full); +} + +bool OriginalPathArrayParam::_updateLink(const Gtk::TreeIter& iter, PathAndDirection* pd) +{ + Gtk::TreeModel::Row row = *iter; + if (row[_model->_colObject] == pd) { + SPObject *obj = pd->ref.getObject(); + row[_model->_colLabel] = obj && obj->getId() ? ( obj->label() ? obj->label() : obj->getId() ) : pd->href; + return true; + } + return false; +} + +void OriginalPathArrayParam::linked_changed(SPObject */*old_obj*/, SPObject *new_obj, PathAndDirection* to) +{ + to->linked_delete_connection.disconnect(); + to->linked_modified_connection.disconnect(); + to->linked_transformed_connection.disconnect(); + + if (new_obj && SP_IS_ITEM(new_obj)) { + to->linked_delete_connection = new_obj->connectDelete(sigc::bind(sigc::mem_fun(*this, &OriginalPathArrayParam::linked_delete), to)); + to->linked_modified_connection = new_obj->connectModified(sigc::bind(sigc::mem_fun(*this, &OriginalPathArrayParam::linked_modified), to)); + to->linked_transformed_connection = SP_ITEM(new_obj)->connectTransformed(sigc::bind(sigc::mem_fun(*this, &OriginalPathArrayParam::linked_transformed), to)); + + linked_modified(new_obj, SP_OBJECT_MODIFIED_FLAG, to); + } else { + to->_pathvector = Geom::PathVector(); + SP_OBJECT(param_effect->getLPEObj())->requestModified(SP_OBJECT_MODIFIED_FLAG); + _store->foreach_iter(sigc::bind(sigc::mem_fun(*this, &OriginalPathArrayParam::_updateLink), to)); + } +} + +void OriginalPathArrayParam::linked_transformed(Geom::Affine const *mp, SPItem* original, PathAndDirection* to) +{ + +} + +void OriginalPathArrayParam::setPathVector(SPObject *linked_obj, guint flags, PathAndDirection* to) +{ + if (!to) { + return; + } + SPCurve *curve = NULL; + if (SP_IS_SHAPE(linked_obj)) { + curve = SP_SHAPE(linked_obj)->getCurveBeforeLPE(); + } + if (SP_IS_TEXT(linked_obj)) { + curve = SP_TEXT(linked_obj)->getNormalizedBpath(); + } + + if (curve == NULL) { + // curve invalid, set empty pathvector + to->_pathvector = Geom::PathVector(); + } else { + to->_pathvector = curve->get_pathvector(); + curve->unref(); + } +} + +void OriginalPathArrayParam::linked_modified(SPObject *linked_obj, guint flags, PathAndDirection* to) +{ + if (!to) { + return; + } + setPathVector(linked_obj, flags, to); + SP_OBJECT(param_effect->getLPEObj())->requestModified(SP_OBJECT_MODIFIED_FLAG); + _store->foreach_iter(sigc::bind(sigc::mem_fun(*this, &OriginalPathArrayParam::_updateLink), to)); +} + +//void PathParam::linked_transformed(Geom::Affine const *rel_transf, SPItem *moved_item) +//{ +// linked_transformed_callback(rel_transf, moved_item); +//} + +bool OriginalPathArrayParam::param_readSVGValue(const gchar* strvalue) +{ + if (strvalue) { + while (!_vector.empty()) { + PathAndDirection *w = _vector.back(); + unlink(w); + _vector.pop_back(); + delete w; + } + _store->clear(); + + gchar ** strarray = g_strsplit(strvalue, "|", 0); + for (gchar ** iter = strarray; *iter != NULL; iter++) { + if ((*iter)[0] == '#') { + gchar ** substrarray = g_strsplit(*iter, ",", 0); + PathAndDirection* w = new PathAndDirection((SPObject *)param_effect->getLPEObj()); + w->href = g_strdup(*substrarray); + w->reversed = *(substrarray+1) != NULL && (*(substrarray+1))[0] == '1'; + + w->linked_changed_connection = w->ref.changedSignal().connect(sigc::bind(sigc::mem_fun(*this, &OriginalPathArrayParam::linked_changed), w)); + w->ref.attach(URI(w->href)); + + _vector.push_back(w); + + Gtk::TreeModel::iterator iter = _store->append(); + Gtk::TreeModel::Row row = *iter; + SPObject *obj = w->ref.getObject(); + + row[_model->_colObject] = w; + row[_model->_colLabel] = obj ? ( obj->label() ? obj->label() : obj->getId() ) : w->href; + row[_model->_colReverse] = w->reversed; + g_strfreev (substrarray); + } + } + g_strfreev (strarray); + return true; + } + return false; +} + +gchar * OriginalPathArrayParam::param_getSVGValue() const +{ + Inkscape::SVGOStringStream os; + bool foundOne = false; + for (std::vector::const_iterator iter = _vector.begin(); iter != _vector.end(); iter++) { + if (foundOne) { + os << "|"; + } else { + foundOne = true; + } + os << (*iter)->href << "," << ((*iter)->reversed ? "1" : "0"); + } + gchar * str = g_strdup(os.str().c_str()); + return str; +} + +} /* namespace LivePathEffect */ + +} /* 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 : diff --git a/src/live_effects/parameter/originalpatharray.h b/src/live_effects/parameter/originalpatharray.h new file mode 100644 index 000000000..865a3f8e5 --- /dev/null +++ b/src/live_effects/parameter/originalpatharray.h @@ -0,0 +1,123 @@ +#ifndef INKSCAPE_LIVEPATHEFFECT_PARAMETER_ORIGINALPATHARRAY_H +#define INKSCAPE_LIVEPATHEFFECT_PARAMETER_ORIGINALPATHARRAY_H + +/* + * Inkscape::LivePathEffectParameters + * +* Copyright (C) Johan Engelen 2008 + * + * Released under GNU GPL, read the file 'COPYING' for more information + */ + +#include + +#include +#include +#include +#include + +#include "live_effects/parameter/parameter.h" +#include "live_effects/parameter/path-reference.h" + +#include "svg/svg.h" +#include "svg/stringstream.h" +#include "path-reference.h" +#include "sp-object.h" + +namespace Inkscape { + +namespace LivePathEffect { + +class PathAndDirection { +public: + PathAndDirection(SPObject *owner) + : href(NULL), + ref(owner), + _pathvector(Geom::PathVector()), + reversed(false) + { + + } + gchar *href; + URIReference ref; + //SPItem *obj; + std::vector _pathvector; + bool reversed; + + sigc::connection linked_changed_connection; + sigc::connection linked_delete_connection; + sigc::connection linked_modified_connection; + sigc::connection linked_transformed_connection; +}; + +class OriginalPathArrayParam : public Parameter { +public: + class ModelColumns; + + OriginalPathArrayParam( const Glib::ustring& label, + const Glib::ustring& tip, + const Glib::ustring& key, + Inkscape::UI::Widget::Registry* wr, + Effect* effect); + + virtual ~OriginalPathArrayParam(); + + virtual Gtk::Widget * param_newWidget(); + virtual bool param_readSVGValue(const gchar * strvalue); + virtual gchar * param_getSVGValue() const; + virtual void param_set_default(); + + /** Disable the canvas indicators of parent class by overriding this method */ + virtual void param_editOncanvas(SPItem * /*item*/, SPDesktop * /*dt*/) {}; + /** Disable the canvas indicators of parent class by overriding this method */ + virtual void addCanvasIndicators(SPLPEItem const* /*lpeitem*/, std::vector & /*hp_vec*/) {}; + + std::vector _vector; + +protected: + bool _updateLink(const Gtk::TreeIter& iter, PathAndDirection* pd); + bool _selectIndex(const Gtk::TreeIter& iter, int* i); + void unlink(PathAndDirection* to); + void remove_link(PathAndDirection* to); + void setPathVector(SPObject *linked_obj, guint flags, PathAndDirection* to); + + void linked_changed(SPObject *old_obj, SPObject *new_obj, PathAndDirection* to); + void linked_modified(SPObject *linked_obj, guint flags, PathAndDirection* to); + void linked_transformed(Geom::Affine const *mp, SPItem *original, PathAndDirection* to); + void linked_delete(SPObject *deleted, PathAndDirection* to); + + ModelColumns *_model; + Glib::RefPtr _store; + Gtk::TreeView _tree; + Gtk::CellRendererText *_text_renderer; + Gtk::CellRendererToggle *_toggle_renderer; + Gtk::TreeView::Column *_name_column; + Gtk::ScrolledWindow _scroller; + + void on_link_button_click(); + void on_remove_button_click(); + void on_up_button_click(); + void on_down_button_click(); + void on_reverse_toggled(const Glib::ustring& path); + +private: + OriginalPathArrayParam(const OriginalPathArrayParam&); + OriginalPathArrayParam& operator=(const OriginalPathArrayParam&); +}; + +} //namespace LivePathEffect + +} //namespace Inkscape + +#endif + +/* + 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 : diff --git a/src/live_effects/parameter/powerstrokepointarray.cpp b/src/live_effects/parameter/powerstrokepointarray.cpp index fecdfeda8..ac0000b1a 100644 --- a/src/live_effects/parameter/powerstrokepointarray.cpp +++ b/src/live_effects/parameter/powerstrokepointarray.cpp @@ -6,6 +6,7 @@ #include +#include "ui/dialog/lpe-powerstroke-properties.h" #include "live_effects/parameter/powerstrokepointarray.h" #include "live_effects/effect.h" @@ -102,6 +103,23 @@ PowerStrokePointArrayParam::recalculate_controlpoints_for_new_pwd2(Geom::Piecewi } } +float PowerStrokePointArrayParam::median_width() +{ + size_t size = _vector.size(); + if (size > 0) + { + if (size % 2 == 0) + { + return (_vector[size / 2 - 1].y() + _vector[size / 2].y()) / 2; + } + else + { + return _vector[size / 2].y(); + } + } + return 1; +} + void PowerStrokePointArrayParam::set_pwd2(Geom::Piecewise > const & pwd2_in, Geom::Piecewise > const & pwd2_normal_in) { @@ -117,7 +135,7 @@ PowerStrokePointArrayParam::set_oncanvas_looks(SPKnotShapeType shape, SPKnotMode knot_mode = mode; knot_color = color; } - +/* class PowerStrokePointArrayParamKnotHolderEntity : public KnotHolderEntity { public: PowerStrokePointArrayParamKnotHolderEntity(PowerStrokePointArrayParam *p, unsigned int index); @@ -127,7 +145,7 @@ public: virtual Geom::Point knot_get() const; virtual void knot_click(guint state); - /** Checks whether the index falls within the size of the parameter's vector */ + /** Checks whether the index falls within the size of the parameter's vector / bool valid_index(unsigned int index) const { return (_pparam->_vector.size() > index); }; @@ -135,7 +153,7 @@ public: private: PowerStrokePointArrayParam *_pparam; unsigned int _index; -}; +};*/ PowerStrokePointArrayParamKnotHolderEntity::PowerStrokePointArrayParamKnotHolderEntity(PowerStrokePointArrayParam *p, unsigned int index) : _pparam(p), @@ -181,6 +199,12 @@ PowerStrokePointArrayParamKnotHolderEntity::knot_get() const return canvas_point; } +void PowerStrokePointArrayParamKnotHolderEntity::knot_set_offset(Geom::Point offset) +{ + _pparam->_vector.at(_index) = Geom::Point(offset.x(), offset.y() / 2); + this->parent_holder->knot_ungrabbed_handler(this->knot); +} + void PowerStrokePointArrayParamKnotHolderEntity::knot_click(guint state) { @@ -223,10 +247,15 @@ PowerStrokePointArrayParamKnotHolderEntity::knot_click(guint state) // add knot to knotholder PowerStrokePointArrayParamKnotHolderEntity *e = new PowerStrokePointArrayParamKnotHolderEntity(_pparam, _index+1); e->create( this->desktop, this->item, parent_holder, Inkscape::CTRL_TYPE_UNKNOWN, - _("Stroke width control point: drag to alter the stroke width. Ctrl+click adds a control point, Ctrl+Alt+click deletes it."), + _("Stroke width control point: drag to alter the stroke width. Ctrl+click adds a control point, Ctrl+Alt+click deletes it, Shift+click launches width dialog."), _pparam->knot_shape, _pparam->knot_mode, _pparam->knot_color); parent_holder->add(e); } + } + else if ((state & GDK_MOD1_MASK) || (state & GDK_SHIFT_MASK)) + { + Geom::Point offset = Geom::Point(_pparam->_vector.at(_index).x(), _pparam->_vector.at(_index).y() * 2); + Inkscape::UI::Dialogs::PowerstrokePropertiesDialog::showDialog(this->desktop, offset, this); } } @@ -235,7 +264,7 @@ void PowerStrokePointArrayParam::addKnotHolderEntities(KnotHolder *knotholder, S for (unsigned int i = 0; i < _vector.size(); ++i) { PowerStrokePointArrayParamKnotHolderEntity *e = new PowerStrokePointArrayParamKnotHolderEntity(this, i); e->create( desktop, item, knotholder, Inkscape::CTRL_TYPE_UNKNOWN, - _("Stroke width control point: drag to alter the stroke width. Ctrl+click adds a control point, Ctrl+Alt+click deletes it."), + _("Stroke width control point: drag to alter the stroke width. Ctrl+click adds a control point, Ctrl+Alt+click deletes it, Shift+click launches width dialog."), knot_shape, knot_mode, knot_color); knotholder->add(e); } diff --git a/src/live_effects/parameter/powerstrokepointarray.h b/src/live_effects/parameter/powerstrokepointarray.h index e1fa440f2..911bbc82d 100644 --- a/src/live_effects/parameter/powerstrokepointarray.h +++ b/src/live_effects/parameter/powerstrokepointarray.h @@ -20,8 +20,6 @@ namespace Inkscape { namespace LivePathEffect { -class PowerStrokePointArrayParamKnotHolderEntity; - class PowerStrokePointArrayParam : public ArrayParam { public: PowerStrokePointArrayParam( const Glib::ustring& label, @@ -37,6 +35,8 @@ public: void set_oncanvas_looks(SPKnotShapeType shape, SPKnotModeType mode, guint32 color); + float median_width(); + virtual bool providesKnotHolderEntities() const { return true; } virtual void addKnotHolderEntities(KnotHolder *knotholder, SPDesktop *desktop, SPItem *item); @@ -60,6 +60,25 @@ private: Geom::Piecewise > last_pwd2_normal; }; +class PowerStrokePointArrayParamKnotHolderEntity : public KnotHolderEntity { +public: + PowerStrokePointArrayParamKnotHolderEntity(PowerStrokePointArrayParam *p, unsigned int index); + virtual ~PowerStrokePointArrayParamKnotHolderEntity() {} + + virtual void knot_set(Geom::Point const &p, Geom::Point const &origin, guint state); + virtual Geom::Point knot_get() const; + virtual void knot_set_offset(Geom::Point offset); + virtual void knot_click(guint state); + + /** Checks whether the index falls within the size of the parameter's vector */ + bool valid_index(unsigned int index) const { + return (_pparam->_vector.size() > index); + }; + +private: + PowerStrokePointArrayParam *_pparam; + unsigned int _index; +}; } //namespace LivePathEffect diff --git a/src/live_effects/parameter/transformedpoint.cpp b/src/live_effects/parameter/transformedpoint.cpp new file mode 100644 index 000000000..f5b01e267 --- /dev/null +++ b/src/live_effects/parameter/transformedpoint.cpp @@ -0,0 +1,182 @@ +/* + * Copyright (C) Theodore Janeczko 2012 + * + * Released under GNU GPL, read the file 'COPYING' for more information + */ + +#include + +#include "ui/widget/registered-widget.h" +#include "live_effects/parameter/transformedpoint.h" +#include "sp-lpe-item.h" +#include "knotholder.h" +#include "svg/svg.h" +#include "svg/stringstream.h" + +#include "live_effects/effect.h" +#include "desktop.h" +#include "verbs.h" + +namespace Inkscape { + +namespace LivePathEffect { + +TransformedPointParam::TransformedPointParam( const Glib::ustring& label, const Glib::ustring& tip, + const Glib::ustring& key, Inkscape::UI::Widget::Registry* wr, + Effect* effect, Geom::Point default_vector, + bool dontTransform) + : Parameter(label, tip, key, wr, effect), + defvalue(default_vector), + origin(0.,0.), + vector(default_vector), + noTransform(dontTransform) +{ + vec_knot_shape = SP_KNOT_SHAPE_DIAMOND; + vec_knot_mode = SP_KNOT_MODE_XOR; + vec_knot_color = 0xffffb500; +} + +TransformedPointParam::~TransformedPointParam() +{ + +} + +void +TransformedPointParam::param_set_default() +{ + setOrigin(Geom::Point(0.,0.)); + setVector(defvalue); +} + +bool +TransformedPointParam::param_readSVGValue(const gchar * strvalue) +{ + gchar ** strarray = g_strsplit(strvalue, ",", 4); + if (!strarray) { + return false; + } + double val[4]; + unsigned int i = 0; + while (i < 4 && strarray[i]) { + if (sp_svg_number_read_d(strarray[i], &val[i]) != 0) { + i++; + } else { + break; + } + } + g_strfreev (strarray); + if (i == 4) { + setOrigin( Geom::Point(val[0], val[1]) ); + setVector( Geom::Point(val[2], val[3]) ); + return true; + } + return false; +} + +gchar * +TransformedPointParam::param_getSVGValue() const +{ + Inkscape::SVGOStringStream os; + os << origin << " , " << vector; + gchar * str = g_strdup(os.str().c_str()); + return str; +} + +Gtk::Widget * +TransformedPointParam::param_newWidget() +{ + Inkscape::UI::Widget::RegisteredVector * pointwdg = Gtk::manage( + new Inkscape::UI::Widget::RegisteredVector( param_label, + param_tooltip, + param_key, + *param_wr, + param_effect->getRepr(), + param_effect->getSPDoc() ) ); + pointwdg->setPolarCoords(); + pointwdg->setValue( vector, origin ); + pointwdg->clearProgrammatically(); + pointwdg->set_undo_parameters(SP_VERB_DIALOG_LIVE_PATH_EFFECT, _("Change vector parameter")); + + Gtk::HBox * hbox = Gtk::manage( new Gtk::HBox() ); + static_cast(hbox)->pack_start(*pointwdg, true, true); + static_cast(hbox)->show_all_children(); + + return dynamic_cast (hbox); +} + +void +TransformedPointParam::set_and_write_new_values(Geom::Point const &new_origin, Geom::Point const &new_vector) +{ + setValues(new_origin, new_vector); + gchar * str = param_getSVGValue(); + param_write_to_repr(str); + g_free(str); +} + +void +TransformedPointParam::param_transform_multiply(Geom::Affine const& postmul, bool /*set*/) +{ + if (!noTransform) { + set_and_write_new_values( origin * postmul, vector * postmul.withoutTranslation() ); + } +} + + +void +TransformedPointParam::set_vector_oncanvas_looks(SPKnotShapeType shape, SPKnotModeType mode, guint32 color) +{ + vec_knot_shape = shape; + vec_knot_mode = mode; + vec_knot_color = color; +} + +void +TransformedPointParam::set_oncanvas_color(guint32 color) +{ + vec_knot_color = color; +} + +class TransformedPointParamKnotHolderEntity_Vector : public KnotHolderEntity { +public: + TransformedPointParamKnotHolderEntity_Vector(TransformedPointParam *p) : param(p) { } + virtual ~TransformedPointParamKnotHolderEntity_Vector() {} + + virtual void knot_set(Geom::Point const &p, Geom::Point const &/*origin*/, guint /*state*/) { + Geom::Point const s = p - param->origin; + /// @todo implement angle snapping when holding CTRL + param->setVector(s); + sp_lpe_item_update_patheffect(SP_LPE_ITEM(item), false, false); + }; + virtual Geom::Point knot_get() const{ + return param->origin + param->vector; + }; + virtual void knot_click(guint /*state*/){ + g_print ("This is the vector handle associated to parameter '%s'\n", param->param_key.c_str()); + }; + +private: + TransformedPointParam *param; +}; + +void +TransformedPointParam::addKnotHolderEntities(KnotHolder *knotholder, SPDesktop *desktop, SPItem *item) +{ + TransformedPointParamKnotHolderEntity_Vector *vector_e = new TransformedPointParamKnotHolderEntity_Vector(this); + vector_e->create(desktop, item, knotholder, Inkscape::CTRL_TYPE_UNKNOWN, handleTip(), vec_knot_shape, vec_knot_mode, vec_knot_color); + knotholder->add(vector_e); +} + +} /* namespace LivePathEffect */ + +} /* 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 : diff --git a/src/live_effects/parameter/transformedpoint.h b/src/live_effects/parameter/transformedpoint.h new file mode 100644 index 000000000..37af8b98f --- /dev/null +++ b/src/live_effects/parameter/transformedpoint.h @@ -0,0 +1,87 @@ +#ifndef INKSCAPE_LIVEPATHEFFECT_PARAMETER_TRANSFORMED_POINT_H +#define INKSCAPE_LIVEPATHEFFECT_PARAMETER_TRANSFORMED_POINT_H + +/* + * Inkscape::LivePathEffectParameters + * + * Copyright (C) Theodore Janeczko 2012 + * + * Released under GNU GPL, read the file 'COPYING' for more information + */ + +#include +#include <2geom/point.h> + +#include "live_effects/parameter/parameter.h" + +#include "knot-holder-entity.h" + +namespace Inkscape { + +namespace LivePathEffect { + + +class TransformedPointParam : public Parameter { +public: + TransformedPointParam( const Glib::ustring& label, + const Glib::ustring& tip, + const Glib::ustring& key, + Inkscape::UI::Widget::Registry* wr, + Effect* effect, + Geom::Point default_vector = Geom::Point(1,0), + bool dontTransform = false); + virtual ~TransformedPointParam(); + + virtual Gtk::Widget * param_newWidget(); + inline const gchar *handleTip() const { return param_tooltip.c_str(); } + + virtual bool param_readSVGValue(const gchar * strvalue); + virtual gchar * param_getSVGValue() const; + + Geom::Point getVector() const { return vector; }; + Geom::Point getOrigin() const { return origin; }; + void setValues(Geom::Point const &new_origin, Geom::Point const &new_vector) { setVector(new_vector); setOrigin(new_origin); }; + void setVector(Geom::Point const &new_vector) { vector = new_vector; }; + void setOrigin(Geom::Point const &new_origin) { origin = new_origin; }; + virtual void param_set_default(); + + void set_and_write_new_values(Geom::Point const &new_origin, Geom::Point const &new_vector); + + virtual void param_transform_multiply(Geom::Affine const &postmul, bool set); + + void set_vector_oncanvas_looks(SPKnotShapeType shape, SPKnotModeType mode, guint32 color); + //void set_origin_oncanvas_looks(SPKnotShapeType shape, SPKnotModeType mode, guint32 color); + void set_oncanvas_color(guint32 color); + + virtual bool providesKnotHolderEntities() const { return true; } + virtual void addKnotHolderEntities(KnotHolder *knotholder, SPDesktop *desktop, SPItem *item); + +private: + TransformedPointParam(const TransformedPointParam&); + TransformedPointParam& operator=(const TransformedPointParam&); + + Geom::Point defvalue; + + Geom::Point origin; + Geom::Point vector; + + bool noTransform; + + /// The looks of the vector and origin knots oncanvas + SPKnotShapeType vec_knot_shape; + SPKnotModeType vec_knot_mode; + guint32 vec_knot_color; +// SPKnotShapeType ori_knot_shape; +// SPKnotModeType ori_knot_mode; +// guint32 ori_knot_color; + +// friend class VectorParamKnotHolderEntity_Origin; + friend class TransformedPointParamKnotHolderEntity_Vector; +}; + + +} //namespace LivePathEffect + +} //namespace Inkscape + +#endif diff --git a/src/live_effects/pathoutlineprovider.h b/src/live_effects/pathoutlineprovider.h new file mode 100755 index 000000000..8aa2e38ad --- /dev/null +++ b/src/live_effects/pathoutlineprovider.h @@ -0,0 +1,766 @@ +#pragma once + +#include <2geom/path.h> +#include <2geom/circle.h> +#include <2geom/sbasis-to-bezier.h> +#include <2geom/shape.h> +#include <2geom/transforms.h> +#include <2geom/path-sink.h> + +#include +#include + +enum LineJoinType { + LINEJOIN_STRAIGHT, + LINEJOIN_ROUND, + LINEJOIN_POINTY, + LINEJOIN_REFLECTED, + LINEJOIN_EXTRAPOLATED +}; + +namespace Geom +{ + /** + * Refer to: Weisstein, Eric W. "Circle-Circle Intersection." + From MathWorld--A Wolfram Web Resource. + http://mathworld.wolfram.com/Circle-CircleIntersection.html + * + * @return 0 if no intersection + * @return 1 if one circle is contained in the other + * @return 2 if intersections are found (they are written to p0 and p1) + */ + static int circle_circle_intersection(Circle const &circle0, Circle const &circle1, + Point & p0, Point & p1) + { + Point X0 = circle0.center(); + double r0 = circle0.ray(); + Point X1 = circle1.center(); + double r1 = circle1.ray(); + + /* dx and dy are the vertical and horizontal distances between + * the circle centers. + */ + Point D = X1 - X0; + + /* Determine the straight-line distance between the centers. */ + double d = L2(D); + + /* Check for solvability. */ + if (d > (r0 + r1)) + { + /* no solution. circles do not intersect. */ + return 0; + } + if (d <= fabs(r0 - r1)) + { + /* no solution. one circle is contained in the other */ + return 1; + } + + /* 'point 2' is the point where the line through the circle + * intersection points crosses the line between the circle + * centers. + */ + + /* Determine the distance from point 0 to point 2. */ + double a = ((r0*r0) - (r1*r1) + (d*d)) / (2.0 * d) ; + + /* Determine the coordinates of point 2. */ + Point p2 = X0 + D * (a/d); + + /* Determine the distance from point 2 to either of the + * intersection points. + */ + double h = std::sqrt((r0*r0) - (a*a)); + + /* Now determine the offsets of the intersection points from + * point 2. + */ + Point r = (h/d)*rot90(D); + + /* Determine the absolute intersection points. */ + p0 = p2 + r; + p1 = p2 - r; + + return 2; + } + /** + * Find circle that touches inside of the curve, with radius matching the curvature, at time value \c t. + * Because this method internally uses unitTangentAt, t should be smaller than 1.0 (see unitTangentAt). + */ + static Circle touching_circle( D2 const &curve, double t, double tol=0.01 ) + { + D2 dM=derivative(curve); + if ( are_near(L2sq(dM(t)),0.) ) { + dM=derivative(dM); + } + if ( are_near(L2sq(dM(t)),0.) ) { // try second time + dM=derivative(dM); + } + Piecewise > unitv = unitVector(dM,tol); + Piecewise dMlength = dot(Piecewise >(dM),unitv); + Piecewise k = cross(derivative(unitv),unitv); + k = divide(k,dMlength,tol,3); + double curv = k(t); // note that this value is signed + + Geom::Point normal = unitTangentAt(curve, t).cw(); + double radius = 1/curv; + Geom::Point center = curve(t) + radius*normal; + return Geom::Circle(center, fabs(radius)); + } + + static std::vector split_at_cusps(const Geom::Path& in) + { + Geom::PathVector out = Geom::PathVector(); + Geom::Path temp = Geom::Path(); + + for (unsigned path_descr = 0; path_descr < in.size(); path_descr++) + { + temp = Geom::Path(); + temp.append(in[path_descr]); + out.push_back(temp); + } + + return out; + } + + static Geom::CubicBezier sbasis_to_cubicbezier(Geom::D2 const & sbasis_in) + { + std::vector temp; + sbasis_to_bezier(temp, sbasis_in, 4); + return Geom::CubicBezier( temp ); + } + + static boost::optional intersection_point( Geom::Point const & origin_a, Geom::Point const & vector_a, + Geom::Point const & origin_b, Geom::Point const & vector_b) + { + Geom::Coord denom = cross(vector_b, vector_a); + if (!Geom::are_near(denom,0.)){ + Geom::Coord t = (cross(origin_a,vector_b) + cross(vector_b,origin_b)) / denom; + return origin_a + t * vector_a; + } + return boost::none; + } +} + +namespace Outline +{ + + typedef Geom::D2 D2SB; + typedef Geom::Piecewise PWD2; + + static void extrapolate_curves(Geom::Path& path_builder, Geom::Curve* cbc1, Geom::Curve*cbc2, Geom::Point endPt, double miter_limit) +{ + Geom::Crossings cross = Geom::crossings(*cbc1, *cbc2); + if (cross.empty()) + { + Geom::Path pth; + pth.append(*cbc1); + + Geom::Point tang1 = Geom::unitTangentAt(pth.toPwSb()[0], 1); + + pth = Geom::Path(); + pth.append( *cbc2 ); + Geom::Point tang2 = Geom::unitTangentAt(pth.toPwSb()[0], 0); + + + Geom::Circle circle1 = Geom::touching_circle(Geom::reverse(cbc1->toSBasis()), 0.); + Geom::Circle circle2 = Geom::touching_circle(cbc2->toSBasis(), 0); + + Geom::Point points[2]; + int solutions = Geom::circle_circle_intersection(circle1, circle2, points[0], points[1]); + if (solutions == 2) + { + Geom::Point sol(0,0); + if ( dot(tang2,points[0]-endPt) > 0 ) + { + // points[0] is bad, choose points[1] + sol = points[1]; + } + else if ( dot(tang2,points[1]-endPt) > 0 ) { // points[0] could be good, now check points[1] + // points[1] is bad, choose points[0] + sol = points[0]; + } + else + { + // both points are good, choose nearest + sol = ( distanceSq(endPt, points[0]) < distanceSq(endPt, points[1]) ) ? + points[0] : points[1]; + } + Geom::EllipticalArc *arc0 = circle1.arc(cbc1->finalPoint(), 0.5*(cbc1->finalPoint()+sol), sol, true); + Geom::EllipticalArc *arc1 = circle2.arc(sol, 0.5*(sol+endPt), endPt, true); + + if (arc0) + { + path_builder.append (arc0->toSBasis()); + delete arc0; + arc0 = NULL; + } + + if (arc1) + { + path_builder.append (arc1->toSBasis()); + delete arc1; + arc1 = NULL; + } + } + else + { + path_builder.appendNew (endPt); + } + } + else + { + path_builder.appendNew (endPt); + } +} + static Geom::Path half_outline_extrp(const Geom::Path& path_in, double line_width, ButtType linecap_type, double miter_limit) + { + Geom::PathVector pv = split_at_cusps(path_in); + unsigned m; + Path path_outline = Path(); + Path path_tangent = Path(); + + Geom::Point initialPoint; + Geom::Point endPoint; + + Geom::Path path_builder = Geom::Path(); + Geom::PathVector * pathvec; + + //load the first portion in before the loop starts + { + path_outline = Path(); + path_outline.LoadPath(pv[0], Geom::Affine(), false, false); + path_outline.OutsideOutline(&path_tangent, line_width / 2, join_straight, linecap_type, 10); + //now half of first cusp has been loaded + + pathvec = path_tangent.MakePathVector(); + path_tangent = Path(); + + //instead of array accessing twice, dereferencing used for clarity + initialPoint = (*pathvec)[0].initialPoint(); + + path_builder.start(initialPoint); + path_builder.append( (*pathvec)[0] ); + + path_outline = Path(); + path_outline.LoadPath(pv[1], Geom::Affine(), false, false); + path_outline.OutsideOutline(&path_tangent, line_width / 2, join_straight, linecap_type, 10); + + delete pathvec; pathvec = NULL; + pathvec = path_tangent.MakePathVector(); + path_tangent = Path(); + + Geom::Curve *cbc1 = path_builder[path_builder.size() - 1].duplicate(); + Geom::Curve *cbc2 = (*pathvec)[0][0].duplicate(); + + extrapolate_curves(path_builder, cbc1, cbc2, (*pathvec)[0].initialPoint(), miter_limit ); + + path_builder.append( (*pathvec)[0] ); + + //always set pointers null after deleting + delete pathvec; pathvec = NULL; + delete cbc1; delete cbc2; cbc1 = cbc2 = NULL; + } + + for (m = 2; m < pv.size(); m++) + { + path_outline = Path(); + path_outline.LoadPath(pv[m], Geom::Affine(), false, false); + path_outline.OutsideOutline(&path_tangent, line_width / 2, join_straight, linecap_type, 10); + + delete pathvec; pathvec = NULL; + pathvec = path_tangent.MakePathVector(); + + Geom::Curve *cbc1 = path_builder[path_builder.size() - 1].duplicate(); + Geom::Curve *cbc2 = (*pathvec)[0][0].duplicate(); + + extrapolate_curves(path_builder, cbc1, cbc2, (*pathvec)[0].initialPoint(), miter_limit ); + path_builder.append( (*pathvec)[0] ); + + delete pathvec; pathvec = NULL; + delete cbc1; delete cbc2; cbc1 = cbc2 = NULL; + } + + return path_builder; + } + + //Create a reflected outline join. + //Note: it is generally recommended to let half_outline do this for you! + //path_builder: the path to append the curves to + //cbc1: the curve before the join + //cbc2: the curve after the join + //endPt: the point to end at + //miter_limit: the miter parameter + static void reflect_curves(Geom::Path& path_builder, Geom::Curve* cbc1, Geom::Curve* cbc2, Geom::Point endPt, double miter_limit) + { + //the most important work for the reflected join is done here + + //determine where we are in the path. If we're on the inside, ignore + //and just lineTo. On the outside, we'll do a little reflection magic :) + Geom::Crossings cross = Geom::crossings(*cbc1, *cbc2); + if (cross.empty()) + { + //probably on the outside of the corner + Geom::Path pth; + pth.append(*cbc1); + + Geom::Point tang1 = Geom::unitTangentAt(pth.toPwSb()[0], 1); + + //reflect curves along the bevel + D2SB newcurve1 = pth.toPwSb()[0] * + Geom::reflection ( -Geom::rot90(tang1) , + cbc1->finalPoint() ); + + Geom::CubicBezier bzr1 = sbasis_to_cubicbezier(Geom::reverse(newcurve1)); + + pth = Geom::Path(); + pth.append( *cbc2 ); + Geom::Point tang2 = Geom::unitTangentAt(pth.toPwSb()[0], 0); + + D2SB newcurve2 = pth.toPwSb()[0] * + Geom::reflection ( -Geom::rot90(tang2) , + cbc2->initialPoint() ); + Geom::CubicBezier bzr2 = sbasis_to_cubicbezier(Geom::reverse(newcurve2)); + + cross = Geom::crossings(bzr1, bzr2); + if ( cross.empty() ) + { + //std::cout << "Oops, no crossings!" << std::endl; + //curves didn't cross; default to miter + /*boost::optional p = intersection_point (cbc1->finalPoint(), tang1, + cbc2->initialPoint(), tang2); + if (p) + { + path_builder.appendNew (*p); + }*/ + //bevel + path_builder.appendNew( endPt ); + } + else + { + //join + std::pair sub1 = bzr1.subdivide(cross[0].ta); + std::pair sub2 = bzr2.subdivide(cross[0].tb); + + //@TODO joins have a strange tendency to cross themselves twice. Check this. + + //sections commented out are for general stability + path_builder.appendNew (sub1.first[1], sub1.first[2], /*sub1.first[3]*/ sub2.second[0] ); + path_builder.appendNew (sub2.second[1], sub2.second[2], /*sub2.second[3]*/ endPt ); + } + } + else // cross.empty() + { + //probably on the inside of the corner + path_builder.appendNew ( endPt ); + } + } + + /** @brief Converts a path to one half of an outline. + * path_in: The input path to use. (To create the other side use path_in.reverse() ) + * line_width: the line width to use (usually you want to divide this by 2) + * linecap_type: (not used here) the cap to apply. Passed to libvarot. + * miter_limit: the miter parameter + */ + static Geom::Path half_outline(const Geom::Path& path_in, double line_width, ButtType linecap_type, double miter_limit) + { + Geom::PathVector pv = split_at_cusps(path_in); + unsigned m; + Path path_outline = Path(); + Path path_tangent = Path(); + //needed for closing the path + Geom::Point initialPoint; + Geom::Point endPoint; + + //some issues prevented me from using a PathBuilder here + //it seems like PathBuilder::peek() gave me a null reference exception + //and I was unable to get a stack trace on Windows, so had to switch to Linux + //to see what the hell was wrong. :( + //I wasted five hours opening it in IDAPro, VS2012, and GDB Windows + + /*Program received signal SIGSEGV, Segmentation fault. + 0x00000000006539ac in get_curves (this=0x0) + at /usr/include/c++/4.6/bits/locale_facets.h:1077 + 1077 { return __c; } + */ + + Geom::Path path_builder = Geom::Path(); + Geom::PathVector * pathvec; + + //load the first portion in before the loop starts + { + path_outline = Path(); + path_outline.LoadPath(pv[0], Geom::Affine(), false, false); + path_outline.OutsideOutline(&path_tangent, line_width / 2, join_straight, linecap_type, 10); + //now half of first cusp has been loaded + + pathvec = path_tangent.MakePathVector(); + path_tangent = Path(); + + //instead of array accessing twice, dereferencing used for clarity + initialPoint = (*pathvec)[0].initialPoint(); + + path_builder.start(initialPoint); + path_builder.append( (*pathvec)[0] ); + + path_outline = Path(); + path_outline.LoadPath(pv[1], Geom::Affine(), false, false); + path_outline.OutsideOutline(&path_tangent, line_width / 2, join_straight, linecap_type, 10); + + delete pathvec; pathvec = NULL; + pathvec = path_tangent.MakePathVector(); + path_tangent = Path(); + + Geom::Curve *cbc1 = path_builder[path_builder.size() - 1].duplicate(); + Geom::Curve *cbc2 = (*pathvec)[0][0].duplicate(); + + reflect_curves(path_builder, cbc1, cbc2, (*pathvec)[0].initialPoint(), miter_limit ); + + path_builder.append( (*pathvec)[0] ); + + //always set pointers null after deleting + delete pathvec; pathvec = NULL; + delete cbc1; delete cbc2; cbc1 = cbc2 = NULL; + } + + for (m = 2; m < pv.size(); m++) + { + path_outline = Path(); + path_outline.LoadPath(pv[m], Geom::Affine(), false, false); + path_outline.OutsideOutline(&path_tangent, line_width / 2, join_straight, linecap_type, 10); + + delete pathvec; pathvec = NULL; + pathvec = path_tangent.MakePathVector(); + + Geom::Curve *cbc1 = path_builder[path_builder.size() - 1].duplicate(); + Geom::Curve *cbc2 = (*pathvec)[0][0].duplicate(); + + reflect_curves(path_builder, cbc1, cbc2, (*pathvec)[0].initialPoint(), miter_limit ); + path_builder.append( (*pathvec)[0] ); + + delete pathvec; pathvec = NULL; + delete cbc1; delete cbc2; cbc1 = cbc2 = NULL; + } + + return path_builder; + } + + static Geom::PathVector outlinePath(const Geom::PathVector& path_in, double line_width, JoinType join, ButtType butt, double miter_lim) + { + Path p = Path(); + Path outlinepath = Path(); + for (unsigned i = 0; i < path_in.size(); i++) + { + p.LoadPath(path_in[i], Geom::Affine(), false, ( (i==0) ? false : true)); + } + + Geom::PathVector path_out; + for (unsigned lmnop = 0; lmnop < path_in.size(); lmnop++) + { + if (path_in[lmnop].size() > 1) + { + Geom::Path p_init; + Geom::Path p_rev; + Geom::PathBuilder pb = Geom::PathBuilder(); + + if ( !path_in[lmnop].closed() ) + { + p_init = Outline::half_outline( path_in[lmnop], -line_width, butt, + miter_lim ); + p_rev = Outline::half_outline( path_in[lmnop].reverse(), -line_width, butt, + miter_lim ); + + pb.moveTo(p_init.initialPoint() ); + pb.append(p_init); + + //cap + if (butt == butt_straight) { + pb.lineTo(p_rev.initialPoint() ); + } else if (butt == butt_round) { + pb.arcTo((-line_width) / 2, (-line_width) / 2, 0., true, true, p_rev.initialPoint() ); + } else if (butt == butt_square) { + //don't know what to do + pb.lineTo(p_rev.initialPoint() ); + } else if (butt == butt_pointy) { + //don't know what to do + pb.lineTo(p_rev.initialPoint() ); + } + + pb.append(p_rev); + + if (butt == butt_straight) { + pb.lineTo(p_init.initialPoint() ); + } else if (butt == butt_round) { + pb.arcTo((-line_width) / 2, (-line_width) / 2, 0., true, true, p_init.initialPoint() ); + } else if (butt == butt_square) { + //don't know what to do + pb.lineTo(p_init.initialPoint() ); + } else if (butt == butt_pointy) { + //don't know what to do + //Geom::Point end_deriv = Geom::unitTangentAt( Geom::reverse(path_in[lmnop].toPwSb()[path_in[lmnop].size()]), 0); + //double radius = 0.5 * Geom::distance(path_in[lmnop].finalPoint(), p_rev.initialPoint()); + + pb.lineTo(p_init.initialPoint() ); + } + } + else + { + //final join + //refer to half_outline for documentation + Geom::Path p_almost = path_in[lmnop]; + p_almost.appendNew ( path_in[lmnop].initialPoint() ); + p_init = Outline::half_outline( p_almost, -line_width, butt, + miter_lim ); + p_rev = Outline::half_outline( p_almost.reverse(), -line_width, butt, + miter_lim ); + p.LoadPath(path_in[lmnop], Geom::Affine(), false, false); + + //this is a kludge, because I can't find how to make this work properly + bool lastIsLinear = ( (Geom::distance(path_in[lmnop].finalPoint(), + path_in[lmnop] [path_in[lmnop].size() - 1].finalPoint())) == + (path_in[lmnop] [path_in[lmnop].size()].length())); + + p_almost = p_init; + if (lastIsLinear) + { + p_almost.erase_last(); p_almost.erase_last(); + } + + //outside test + Geom::Curve* cbc1 = p_almost[p_almost.size() - 1].duplicate(); + Geom::Curve* cbc2 = p_almost[0].duplicate(); + + Geom::Crossings cross = Geom::crossings(*cbc1, *cbc2); + + if (cross.empty()) + { + //this is the outside path + + //reuse the old one + p_init = p_almost; + Outline::reflect_curves(p_init, cbc1, cbc2, p_almost.initialPoint(), miter_lim ); + pb.moveTo(p_init.initialPoint()); pb.append(p_init); + } + else + { + //inside, carry on :-) + pb.moveTo(p_almost.initialPoint()); pb.append(p_almost); + } + + p_almost = p_rev; + if (lastIsLinear) + { + p_almost.erase(p_almost.begin() ); + p_almost.erase(p_almost.begin() ); + } + + delete cbc1; delete cbc2; cbc1 = cbc2 = NULL; + + cbc1 = p_almost[p_almost.size() - 1].duplicate(); + cbc2 = p_almost[0].duplicate(); + + cross = Geom::crossings(*cbc1, *cbc2); + + if (cross.empty()) + { + //outside path + + p_init = p_almost; + reflect_curves(p_init, cbc1, cbc2, p_almost.initialPoint(), miter_lim ); + pb.moveTo(p_init.initialPoint()); pb.append(p_init); + } + else + { + //inside + pb.moveTo(p_almost.initialPoint()); pb.append(p_almost); + } + delete cbc1; delete cbc2; cbc1 = cbc2 = NULL; + } + //pb.closePath(); + pb.flush(); + Geom::PathVector pv_np = pb.peek(); + //hack + for (unsigned abcd = 0; abcd < pv_np.size(); abcd++) + { + path_out.push_back( pv_np[abcd] ); + } + } + else + { + p.LoadPath(path_in[lmnop], Geom::Affine(), false, false); + p.Outline(&outlinepath, line_width / 2, join, butt, miter_lim); + std::vector *pv_p = outlinepath.MakePathVector(); + //hack + path_out.push_back( (*pv_p)[0].reverse() ); + delete pv_p; + } + } + return path_out; + } + static Geom::PathVector outlinePath_extr(const Geom::PathVector& path_in, double line_width, LineJoinType join, ButtType butt, double miter_lim) + { + Path p = Path(); + Path outlinepath = Path(); + for (unsigned i = 0; i < path_in.size(); i++) + { + p.LoadPath(path_in[i], Geom::Affine(), false, ( (i==0) ? false : true)); + } + + Geom::PathVector path_out; + for (unsigned lmnop = 0; lmnop < path_in.size(); lmnop++) + { + if (path_in[lmnop].size() > 1) + { + Geom::Path p_init; + Geom::Path p_rev; + Geom::PathBuilder pb = Geom::PathBuilder(); + + if ( !path_in[lmnop].closed() ) + { + p_init = Outline::half_outline_extrp( path_in[lmnop], -line_width, butt, + miter_lim ); + p_rev = Outline::half_outline_extrp( path_in[lmnop].reverse(), -line_width, butt, + miter_lim ); + + pb.moveTo(p_init.initialPoint() ); + pb.append(p_init); + + //cap + if (butt == butt_straight) { + pb.lineTo(p_rev.initialPoint() ); + } else if (butt == butt_round) { + pb.arcTo((-line_width) / 2, (-line_width) / 2, 0., true, true, p_rev.initialPoint() ); + } else if (butt == butt_square) { + //don't know what to do + pb.lineTo(p_rev.initialPoint() ); + } else if (butt == butt_pointy) { + //don't know what to do + pb.lineTo(p_rev.initialPoint() ); + } + + pb.append(p_rev); + + if (butt == butt_straight) { + pb.lineTo(p_init.initialPoint() ); + } else if (butt == butt_round) { + pb.arcTo((-line_width) / 2, (-line_width) / 2, 0., true, true, p_init.initialPoint() ); + } else if (butt == butt_square) { + //don't know what to do + pb.lineTo(p_init.initialPoint() ); + } else if (butt == butt_pointy) { + //don't know what to do + //Geom::Point end_deriv = Geom::unitTangentAt( Geom::reverse(path_in[lmnop].toPwSb()[path_in[lmnop].size()]), 0); + //double radius = 0.5 * Geom::distance(path_in[lmnop].finalPoint(), p_rev.initialPoint()); + + pb.lineTo(p_init.initialPoint() ); + } + } + else + { + //final join + //refer to half_outline for documentation + Geom::Path p_almost = path_in[lmnop]; + p_almost.appendNew ( path_in[lmnop].initialPoint() ); + p_init = Outline::half_outline_extrp( p_almost, -line_width, butt, + miter_lim ); + p_rev = Outline::half_outline_extrp( p_almost.reverse(), -line_width, butt, + miter_lim ); + p.LoadPath(path_in[lmnop], Geom::Affine(), false, false); + + //this is a kludge, because I can't find how to make this work properly + bool lastIsLinear = ( (Geom::distance(path_in[lmnop].finalPoint(), + path_in[lmnop] [path_in[lmnop].size() - 1].finalPoint())) == + (path_in[lmnop] [path_in[lmnop].size()].length())); + + p_almost = p_init; + if (lastIsLinear) + { + p_almost.erase_last(); p_almost.erase_last(); + } + + //outside test + Geom::Curve* cbc1 = p_almost[p_almost.size() - 1].duplicate(); + Geom::Curve* cbc2 = p_almost[0].duplicate(); + + Geom::Crossings cross = Geom::crossings(*cbc1, *cbc2); + + if (cross.empty()) + { + //this is the outside path + + //reuse the old one + p_init = p_almost; + Outline::extrapolate_curves(p_init, cbc1, cbc2, p_almost.initialPoint(), miter_lim ); + pb.moveTo(p_init.initialPoint()); pb.append(p_init); + } + else + { + //inside, carry on :-) + pb.moveTo(p_almost.initialPoint()); pb.append(p_almost); + } + + p_almost = p_rev; + if (lastIsLinear) + { + p_almost.erase(p_almost.begin() ); + p_almost.erase(p_almost.begin() ); + } + + delete cbc1; delete cbc2; cbc1 = cbc2 = NULL; + + cbc1 = p_almost[p_almost.size() - 1].duplicate(); + cbc2 = p_almost[0].duplicate(); + + cross = Geom::crossings(*cbc1, *cbc2); + + if (cross.empty()) + { + //outside path + + p_init = p_almost; + extrapolate_curves(p_init, cbc1, cbc2, p_almost.initialPoint(), miter_lim ); + pb.moveTo(p_init.initialPoint()); pb.append(p_init); + } + else + { + //inside + pb.moveTo(p_almost.initialPoint()); pb.append(p_almost); + } + delete cbc1; delete cbc2; cbc1 = cbc2 = NULL; + } + //pb.closePath(); + pb.flush(); + Geom::PathVector pv_np = pb.peek(); + //hack + for (unsigned abcd = 0; abcd < pv_np.size(); abcd++) + { + path_out.push_back( pv_np[abcd] ); + } + } + else + { + p.LoadPath(path_in[lmnop], Geom::Affine(), false, false); + p.Outline(&outlinepath, line_width / 2, join_pointy, butt, miter_lim); + std::vector *pv_p = outlinepath.MakePathVector(); + //hack + path_out.push_back( (*pv_p)[0].reverse() ); + delete pv_p; + } + } + return path_out; + } + + +} // namespace Outline + +/* + 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:encoding=utf-8:textwidth=99 : diff --git a/src/sp-item.cpp b/src/sp-item.cpp index 5e126f486..aec749929 100644 --- a/src/sp-item.cpp +++ b/src/sp-item.cpp @@ -183,6 +183,26 @@ bool SPItem::isHidden(unsigned display_key) const { return true; } +bool SPItem::isHighlightSet() const { + return _highlightColor != NULL; +} + +guint32 SPItem::highlight_color() const { + if (_highlightColor) + { + return atoi(_highlightColor) | 0x000000ff; + } + else if (parent && parent != this && SP_IS_ITEM(parent)) + { + return SP_ITEM(parent)->highlight_color(); + } + else + { + static Inkscape::Preferences *prefs = Inkscape::Preferences::get(); + return prefs->getInt("/tools/nodes/highlight_color", 0xff0000ff) | 0x000000ff; + } +} + void SPItem::setEvaluated(bool evaluated) { _is_evaluated = evaluated; _evaluated_status = StatusSet; diff --git a/src/sp-item.h b/src/sp-item.h index d605c99b9..dc0c54a80 100644 --- a/src/sp-item.h +++ b/src/sp-item.h @@ -145,6 +145,15 @@ public: bool isHidden() const; void setHidden(bool hidden); + /* Objects dialogue */ + bool isHighlightSet() const; + guint32 highlight_color() const; + + void setHighlightColor(guint32 color); + + void unsetHighlightColor(); + /********************/ + bool isEvaluated() const; void setEvaluated(bool visible); void resetEvaluated(); @@ -215,6 +224,7 @@ public: void set_i2d_affine(Geom::Affine const &transform); Geom::Affine dt2i_affine() const; + gchar *_highlightColor; private: enum EvaluatedStatus { diff --git a/src/sp-object.h b/src/sp-object.h index 3faadb404..4f7ef3f4c 100644 --- a/src/sp-object.h +++ b/src/sp-object.h @@ -45,6 +45,7 @@ class SPObject; #define SP_OBJECT_WRITE_BUILD (1 << 0) #define SP_OBJECT_WRITE_EXT (1 << 1) #define SP_OBJECT_WRITE_ALL (1 << 2) +#define SP_OBJECT_WRITE_NO_CHILDREN (1 << 3) #include #include diff --git a/src/ui/dialog/Makefile_insert b/src/ui/dialog/Makefile_insert index c37767a08..1cf667f2a 100644 --- a/src/ui/dialog/Makefile_insert +++ b/src/ui/dialog/Makefile_insert @@ -109,4 +109,8 @@ ink_common_sources += \ ui/dialog/undo-history.h \ ui/dialog/xml-tree.cpp \ ui/dialog/xml-tree.h \ + ui/dialog/lpe-powerstroke-properties.cpp \ + ui/dialog/lpe-powerstroke-properties.h \ + ui/dialog/objects.cpp \ + ui/dialog/objects.h \ $(inkboard_dialogs) diff --git a/src/ui/dialog/lpe-powerstroke-properties.cpp b/src/ui/dialog/lpe-powerstroke-properties.cpp new file mode 100644 index 000000000..cef6f494e --- /dev/null +++ b/src/ui/dialog/lpe-powerstroke-properties.cpp @@ -0,0 +1,203 @@ +/** + * @file + * Dialog for renaming layers. + */ +/* Author: + * Bryce W. Harrington + * Andrius R. + * Abhishek Sharma + * + * Copyright (C) 2004 Bryce Harrington + * Copyright (C) 2006 Andrius R. + * + * Released under GNU GPL. Read the file 'COPYING' for more information + */ + +#include "lpe-powerstroke-properties.h" +#include +#include +#include +#include +#include "inkscape.h" +#include "desktop.h" +#include "document.h" +#include "document-undo.h" +#include "layer-manager.h" +#include "message-stack.h" +#include "desktop-handles.h" +#include "sp-object.h" +#include "sp-item.h" +#include "verbs.h" +#include "selection.h" +#include "selection-chemistry.h" +#include "ui/icon-names.h" +#include "ui/widget/imagetoggler.h" +//#include "event-context.h" + +namespace Inkscape { +namespace UI { +namespace Dialogs { + +PowerstrokePropertiesDialog::PowerstrokePropertiesDialog() +: _desktop(NULL), _knotpoint(NULL), _position_visible(false) +{ + Gtk::Box *mainVBox = get_vbox(); + + _layout_table.set_spacings(4); + _layout_table.resize (2, 2); + + // Layer name widgets + _powerstroke_position_entry.set_activates_default(true); + _powerstroke_position_label.set_label(_("Position:")); + _powerstroke_position_label.set_alignment(1.0, 0.5); + + _powerstroke_width_entry.set_activates_default(true); + _powerstroke_width_label.set_label(_("Width:")); + _powerstroke_width_label.set_alignment(1.0, 0.5); + + _layout_table.attach(_powerstroke_position_label, + 0, 1, 0, 1, Gtk::FILL, Gtk::FILL); + _layout_table.attach(_powerstroke_position_entry, + 1, 2, 0, 1, Gtk::FILL | Gtk::EXPAND, Gtk::FILL); + + _layout_table.attach(_powerstroke_width_label, 0, 1, 1, 2, Gtk::FILL, Gtk::FILL); + _layout_table.attach(_powerstroke_width_entry, 1, 2, 1, 2, Gtk::FILL | Gtk::EXPAND, Gtk::FILL); + + mainVBox->pack_start(_layout_table, true, true, 4); + + // Buttons + _close_button.set_use_stock(true); + _close_button.set_label(Gtk::Stock::CANCEL.id); + _close_button.set_can_default(); + + _apply_button.set_use_underline(true); + _apply_button.set_can_default(); + + _close_button.signal_clicked() + .connect(sigc::mem_fun(*this, &PowerstrokePropertiesDialog::_close)); + _apply_button.signal_clicked() + .connect(sigc::mem_fun(*this, &PowerstrokePropertiesDialog::_apply)); + + signal_delete_event().connect( + sigc::bind_return( + sigc::hide(sigc::mem_fun(*this, &PowerstrokePropertiesDialog::_close)), + true + ) + ); + + add_action_widget(_close_button, Gtk::RESPONSE_CLOSE); + add_action_widget(_apply_button, Gtk::RESPONSE_APPLY); + + _apply_button.grab_default(); + + show_all_children(); + + set_focus(_powerstroke_width_entry); +} + +PowerstrokePropertiesDialog::~PowerstrokePropertiesDialog() { + + _setDesktop(NULL); +} + +void PowerstrokePropertiesDialog::showDialog(SPDesktop *desktop, Geom::Point knotpoint, const Inkscape::LivePathEffect::PowerStrokePointArrayParamKnotHolderEntity *pt) +{ + PowerstrokePropertiesDialog *dialog = new PowerstrokePropertiesDialog(); + + dialog->_setDesktop(desktop); + dialog->_setKnotPoint(knotpoint); + dialog->_setPt(pt); + + dialog->set_title(_("Modify Node Position")); + dialog->_apply_button.set_label(_("_Move")); + + dialog->set_modal(true); + desktop->setWindowTransient (dialog->gobj()); + dialog->property_destroy_with_parent() = true; + + dialog->show(); + dialog->present(); +} + +void +PowerstrokePropertiesDialog::_apply() +{ + std::istringstream i_pos(_powerstroke_position_entry.get_text()); + std::istringstream i_width(_powerstroke_width_entry.get_text()); + double d_pos, d_width; + if ((i_pos >> d_pos) && i_width >> d_width) { + _knotpoint->knot_set_offset(Geom::Point(d_pos, d_width)); + } + _close(); +} + +void +PowerstrokePropertiesDialog::_close() +{ + _setDesktop(NULL); + destroy_(); + Glib::signal_idle().connect( + sigc::bind_return( + sigc::bind(sigc::ptr_fun(&::operator delete), this), + false + ) + ); +} + +bool PowerstrokePropertiesDialog::_handleKeyEvent(GdkEventKey *event) +{ + + /*switch (get_group0_keyval(event)) { + case GDK_KEY_Return: + case GDK_KEY_KP_Enter: { + _apply(); + return true; + } + break; + }*/ + return false; +} + +void PowerstrokePropertiesDialog::_handleButtonEvent(GdkEventButton* event) +{ + if ( (event->type == GDK_2BUTTON_PRESS) && (event->button == 1) ) { + _apply(); + } +} + +void PowerstrokePropertiesDialog::_setKnotPoint(Geom::Point knotpoint) +{ + _powerstroke_position_entry.set_text(boost::lexical_cast(knotpoint.x())); + _powerstroke_width_entry.set_text(boost::lexical_cast(knotpoint.y())); +} + +void PowerstrokePropertiesDialog::_setPt(const Inkscape::LivePathEffect::PowerStrokePointArrayParamKnotHolderEntity *pt) +{ + _knotpoint = const_cast(pt); +} + +void PowerstrokePropertiesDialog::_setDesktop(SPDesktop *desktop) { + if (desktop) { + Inkscape::GC::anchor (desktop); + } + if (_desktop) { + Inkscape::GC::release (_desktop); + } + _desktop = desktop; +} + +} // namespace +} // namespace +} // namespace + + +/* + 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 : diff --git a/src/ui/dialog/lpe-powerstroke-properties.h b/src/ui/dialog/lpe-powerstroke-properties.h new file mode 100644 index 000000000..c53eac0d9 --- /dev/null +++ b/src/ui/dialog/lpe-powerstroke-properties.h @@ -0,0 +1,99 @@ +/** @file + * @brief Dialog for renaming layers + */ +/* Author: + * Bryce W. Harrington + * + * Copyright (C) 2004 Bryce Harrington + * + * Released under GNU GPL. Read the file 'COPYING' for more information + */ + +#ifndef INKSCAPE_DIALOG_POWERSTROKE_PROPERTIES_H +#define INKSCAPE_DIALOG_POWERSTROKE_PROPERTIES_H + +#include <2geom/point.h> +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "live_effects/parameter/powerstrokepointarray.h" + +class SPDesktop; + +namespace Inkscape { +namespace UI { +namespace Dialogs { + +class PowerstrokePropertiesDialog : public Gtk::Dialog { + public: + PowerstrokePropertiesDialog(); + virtual ~PowerstrokePropertiesDialog(); + + Glib::ustring getName() const { return "LayerPropertiesDialog"; } + + static void showDialog(SPDesktop *desktop, Geom::Point knotpoint, const Inkscape::LivePathEffect::PowerStrokePointArrayParamKnotHolderEntity *pt); + +protected: + + SPDesktop *_desktop; + Inkscape::LivePathEffect::PowerStrokePointArrayParamKnotHolderEntity *_knotpoint; + + Gtk::Label _powerstroke_position_label; + Gtk::Entry _powerstroke_position_entry; + Gtk::Label _powerstroke_width_label; + Gtk::Entry _powerstroke_width_entry; + Gtk::Table _layout_table; + bool _position_visible; + + Gtk::Button _close_button; + Gtk::Button _apply_button; + + sigc::connection _destroy_connection; + + static PowerstrokePropertiesDialog &_instance() { + static PowerstrokePropertiesDialog instance; + return instance; + } + + void _setDesktop(SPDesktop *desktop); + void _setPt(const Inkscape::LivePathEffect::PowerStrokePointArrayParamKnotHolderEntity *pt); + + void _apply(); + void _close(); + + void _setKnotPoint(Geom::Point knotpoint); + void _prepareLabelRenderer(Gtk::TreeModel::const_iterator const &row); + + bool _handleKeyEvent(GdkEventKey *event); + void _handleButtonEvent(GdkEventButton* event); + + friend class Inkscape::LivePathEffect::PowerStrokePointArrayParamKnotHolderEntity; + +private: + PowerstrokePropertiesDialog(PowerstrokePropertiesDialog const &); // no copy + PowerstrokePropertiesDialog &operator=(PowerstrokePropertiesDialog const &); // no assign +}; + +} // namespace +} // namespace +} // namespace + + +#endif //INKSCAPE_DIALOG_LAYER_PROPERTIES_H + +/* + 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 : diff --git a/src/ui/dialog/objects.cpp b/src/ui/dialog/objects.cpp new file mode 100644 index 000000000..31e73db29 --- /dev/null +++ b/src/ui/dialog/objects.cpp @@ -0,0 +1,2048 @@ +/* + * A simple panel for objects + * + * Authors: + * Theodore Janeczko + * + * Copyright (C) Theodore Janeczko 2012 + * + * Released under GNU GPL, read the file 'COPYING' for more information + */ +#ifdef HAVE_CONFIG_H +# include +#endif + +#include "objects.h" +#include +#include +#include +#include + +#include + +#include "desktop.h" +#include "desktop-style.h" +#include "document.h" +#include "document-undo.h" +#include "helper/action.h" +#include "inkscape.h" +#include "preferences.h" +#include "sp-item.h" +#include "sp-object.h" +#include "sp-shape.h" +#include "svg/css-ostringstream.h" +#include "ui/icon-names.h" +#include "ui/widget/imagetoggler.h" +#include "ui/widget/layertypeicon.h" +#include "ui/widget/insertordericon.h" +#include "ui/widget/clipmaskicon.h" +#include "ui/widget/highlight-picker.h" +#include "verbs.h" +#include "widgets/icon.h" +#include "xml/node.h" +#include "xml/node-observer.h" +#include "xml/repr.h" +#include "sp-root.h" +//#include "event-context.h" +#include "selection.h" +#include "dialogs/dialog-events.h" +#include "widgets/sp-color-notebook.h" +#include "style.h" +#include "filter-chemistry.h" +#include "filters/blend.h" +#include "filters/gaussian-blur.h" +#include "sp-clippath.h" +#include "sp-mask.h" +#include "layer-manager.h" + +//#define DUMP_LAYERS 1 + +namespace Inkscape { +namespace UI { +namespace Dialog { + +using Inkscape::XML::Node; + +/** + * Gets an instance of the Objects panel + */ +ObjectsPanel& ObjectsPanel::getInstance() +{ + return *new ObjectsPanel(); +} + +/** + * Column enumeration + */ +enum { + COL_VISIBLE = 1, + COL_LOCKED, + COL_TYPE, + COL_INSERTORDER, + COL_CLIPMASK, + COL_HIGHLIGHT +}; + +/** + * Button enumeration + */ +enum { + BUTTON_NEW = 0, + BUTTON_RENAME, + BUTTON_TOP, + BUTTON_BOTTOM, + BUTTON_UP, + BUTTON_DOWN, + BUTTON_DUPLICATE, + BUTTON_DELETE, + BUTTON_SOLO, + BUTTON_SHOW_ALL, + BUTTON_HIDE_ALL, + BUTTON_LOCK_OTHERS, + BUTTON_LOCK_ALL, + BUTTON_UNLOCK_ALL, + BUTTON_SETCLIP, + BUTTON_CLIPGROUP, + BUTTON_SETINVCLIP, + BUTTON_UNSETCLIP, + BUTTON_SETMASK, + BUTTON_UNSETMASK, + BUTTON_GROUP, + BUTTON_UNGROUP, + BUTTON_COLLAPSE_ALL, + DRAGNDROP +}; + +/** + * Xml node observer for observing objects in the document + */ +class ObjectsPanel::ObjectWatcher : public Inkscape::XML::NodeObserver { +public: + /** + * Creates a new object watcher + * @param pnl The panel to which the object watcher belongs + * @param obj The object to watch + */ + ObjectWatcher(ObjectsPanel* pnl, SPObject* obj) : + _pnl(pnl), + _obj(obj), + _repr(obj->getRepr()), + _highlightAttr(g_quark_from_string("inkscape:highlight-color")), + _lockedAttr(g_quark_from_string("sodipodi:insensitive")), + _labelAttr(g_quark_from_string("inkscape:label")), + _groupAttr(g_quark_from_string("inkscape:groupmode")), + _styleAttr(g_quark_from_string("style")), + _clipAttr(g_quark_from_string("clip-path")), + _maskAttr(g_quark_from_string("mask")) + {} + + virtual void notifyChildAdded( Node &/*node*/, Node &/*child*/, Node */*prev*/ ) + { + if ( _pnl && _obj ) { + _pnl->_objectsChanged( _obj ); + } + } + virtual void notifyChildRemoved( Node &/*node*/, Node &/*child*/, Node */*prev*/ ) + { + if ( _pnl && _obj ) { + _pnl->_objectsChanged( _obj ); + } + } + virtual void notifyChildOrderChanged( Node &/*node*/, Node &/*child*/, Node */*old_prev*/, Node */*new_prev*/ ) + { + if ( _pnl && _obj ) { + _pnl->_objectsChanged( _obj ); + } + } + virtual void notifyContentChanged( Node &/*node*/, Util::ptr_shared /*old_content*/, Util::ptr_shared /*new_content*/ ) {} + virtual void notifyAttributeChanged( Node &/*node*/, GQuark name, Util::ptr_shared /*old_value*/, Util::ptr_shared /*new_value*/ ) { + if ( _pnl && _obj ) { + if ( name == _lockedAttr || name == _labelAttr || name == _highlightAttr || name == _groupAttr || name == _styleAttr || name == _clipAttr || name == _maskAttr ) { + _pnl->_updateObject(_obj, name == _highlightAttr); + if ( name == _styleAttr ) { + _pnl->_updateComposite(); + } + } + } + } + + /** + * Objects panel to which this watcher belongs + */ + ObjectsPanel* _pnl; + + /** + * The object that is being observed + */ + SPObject* _obj; + + /** + * The xml representation of the object that is being observed + */ + Inkscape::XML::Node* _repr; + + /* These are quarks which define the attributes that we are observing */ + GQuark _highlightAttr; + GQuark _lockedAttr; + GQuark _labelAttr; + GQuark _groupAttr; + GQuark _styleAttr; + GQuark _clipAttr; + GQuark _maskAttr; +}; + +class ObjectsPanel::InternalUIBounce +{ +public: + int _actionCode; +}; + +class ObjectsPanel::ModelColumns : public Gtk::TreeModel::ColumnRecord +{ +public: + + ModelColumns() + { + add(_colObject); + add(_colVisible); + add(_colLocked); + add(_colLabel); + add(_colType); + add(_colHighlight); + add(_colClipMask); + add(_colInsertOrder); + } + virtual ~ModelColumns() {} + + Gtk::TreeModelColumn _colObject; + Gtk::TreeModelColumn _colLabel; + Gtk::TreeModelColumn _colVisible; + Gtk::TreeModelColumn _colLocked; + Gtk::TreeModelColumn _colType; + Gtk::TreeModelColumn _colHighlight; + Gtk::TreeModelColumn _colClipMask; + Gtk::TreeModelColumn _colInsertOrder; +}; + +/** + * Stylizes a button using the given icon name and tooltip + */ +void ObjectsPanel::_styleButton( Gtk::Button& btn, char const* iconName, char const* tooltip ) +{ + GtkWidget *child = sp_icon_new( Inkscape::ICON_SIZE_SMALL_TOOLBAR, iconName ); + gtk_widget_show( child ); + btn.add( *Gtk::manage(Glib::wrap(child)) ); + btn.set_relief(Gtk::RELIEF_NONE); + + btn.set_tooltip_text (tooltip); + +} + +/** + * Adds an item to the pop-up (right-click) menu + * @param desktop The active destktop + * @param code Action code + * @param iconName Icon name + * @param fallback Fallback text + * @param id Button id for callback function + * @return The generated menu item + */ +Gtk::MenuItem& ObjectsPanel::_addPopupItem( SPDesktop *desktop, unsigned int code, char const* iconName, char const* fallback, int id ) +{ + GtkWidget* iconWidget = 0; + const char* label = 0; + + if ( iconName ) { + iconWidget = sp_icon_new( Inkscape::ICON_SIZE_MENU, iconName ); + } + + if ( desktop ) { + Verb *verb = Verb::get( code ); + if ( verb ) { + SPAction *action = verb->get_action(desktop); + if ( !iconWidget && action && action->image ) { + iconWidget = sp_icon_new( Inkscape::ICON_SIZE_MENU, action->image ); + } + + if ( action ) { + label = action->name; + } + } + } + + if ( !label && fallback ) { + label = fallback; + } + + Gtk::Widget* wrapped = 0; + if ( iconWidget ) { + wrapped = Gtk::manage(Glib::wrap(iconWidget)); + wrapped->show(); + } + + + Gtk::MenuItem* item = 0; + + if (wrapped) { + item = Gtk::manage(new Gtk::ImageMenuItem(*wrapped, label, true)); + } else { + item = Gtk::manage(new Gtk::MenuItem(label, true)); + } + + item->signal_activate().connect(sigc::bind(sigc::mem_fun(*this, &ObjectsPanel::_takeAction), id)); + _popupMenu.append(*item); + + return *item; +} + +/** + * Callback function for when an object changes. Essentially refreshes the entire tree + * @param obj Object which was changed (currently not used as the entire tree is recreated) + */ +void ObjectsPanel::_objectsChanged(SPObject */*obj*/) +{ + //First, unattach the watchers + while (!_objectWatchers.empty()) + { + ObjectsPanel::ObjectWatcher *w = _objectWatchers.back(); + w->_repr->removeObserver(*w); + _objectWatchers.pop_back(); + delete w; + } + + if (_desktop) { + //Get the current document's root and use that to enumerate the tree + SPDocument* document = _desktop->doc(); + SPRoot* root = document->getRoot(); + if ( root ) { + _selectedConnection.block(); + //Clear the tree store + _store->clear(); + //Add all items recursively + _addObject( root, 0 ); + _selectedConnection.unblock(); + //Set the tree selection + _objectsSelected(_desktop->selection); + //Handle button sensitivity + _checkTreeSelection(); + } + } +} + +/** + * Recursively adds the children of the given item to the tree + * @param obj Root object to add to the tree + * @param parentRow Parent tree row (or NULL if adding to tree root) + */ +void ObjectsPanel::_addObject(SPObject* obj, Gtk::TreeModel::Row* parentRow) +{ + if ( _desktop && obj ) { + for ( SPObject *child = obj->children; child != NULL; child = child->next) { + + if (SP_IS_ITEM(child)) + { + SPItem * item = SP_ITEM(child); + SPGroup * group = SP_IS_GROUP(child) ? SP_GROUP(child) : 0; + + //Add the item to the tree and set the column information + Gtk::TreeModel::iterator iter = parentRow ? _store->prepend(parentRow->children()) : _store->prepend(); + Gtk::TreeModel::Row row = *iter; + row[_model->_colObject] = item; + row[_model->_colLabel] = item->label() ? item->label() : item->getId(); + row[_model->_colVisible] = !item->isHidden(); + row[_model->_colLocked] = !item->isSensitive(); + row[_model->_colType] = group ? (group->layerMode() == SPGroup::LAYER ? 2 : 1) : 0; + row[_model->_colHighlight] = item->isHighlightSet() ? item->highlight_color() : item->highlight_color() & 0xffffff00; + row[_model->_colClipMask] = item->clip_ref && item->clip_ref->getObject() ? 1 : (item->mask_ref && item->mask_ref->getObject() ? 2 : 0); + row[_model->_colInsertOrder] = group ? (group->insertBottom() ? 2 : 1) : 0; + + //If our parent object is a group and it's expanded, expand the tree + if (SP_IS_GROUP(obj) && SP_GROUP(obj)->expanded()) + { + _tree.expand_to_path( _store->get_path(iter) ); + } + + //Add an object watcher to the item + ObjectsPanel::ObjectWatcher *w = new ObjectsPanel::ObjectWatcher(this, child); + child->getRepr()->addObserver(*w); + _objectWatchers.push_back(w); + + //If the item is a group, recursively add its children + if (group) + { + _addObject( child, &row ); + } + } + } + } +} + +/** + * Updates an item in the tree and optionally recursively updates the item's children + * @param obj The item to update in the tree + * @param recurse Whether to recurse through the item's children + */ +void ObjectsPanel::_updateObject( SPObject *obj, bool recurse ) { + //Find the object in the tree store and update it + _store->foreach_iter( sigc::bind(sigc::mem_fun(*this, &ObjectsPanel::_checkForUpdated), obj) ); + if (recurse) + { + for (SPObject * iter = obj->children; iter != NULL; iter = iter->next) + { + _updateObject(iter, recurse); + } + } +} + +/** + * Checks items in the tree store and updates the given item + * @param iter Current item being looked at in the tree + * @param obj Object to update + * @return + */ +bool ObjectsPanel::_checkForUpdated(const Gtk::TreeIter& iter, SPObject* obj) +{ + Gtk::TreeModel::Row row = *iter; + if ( obj == row[_model->_colObject] ) + { + //We found our item in the tree!! Update it! + SPItem * item = SP_IS_ITEM(obj) ? SP_ITEM(obj) : 0; + SPGroup * group = SP_IS_GROUP(obj) ? SP_GROUP(obj) : 0; + + row[_model->_colLabel] = obj->label() ? obj->label() : obj->getId(); + row[_model->_colVisible] = item ? !item->isHidden() : false; + row[_model->_colLocked] = item ? !item->isSensitive() : false; + row[_model->_colType] = group ? (group->layerMode() == SPGroup::LAYER ? 2 : 1) : 0; + row[_model->_colHighlight] = item ? (item->isHighlightSet() ? item->highlight_color() : item->highlight_color() & 0xffffff00) : 0; + row[_model->_colClipMask] = item ? (item->clip_ref && item->clip_ref->getObject() ? (item->clip_ref->getObject()->inverse ? 3 : 1) : (item->mask_ref && item->mask_ref->getObject() ? 2 : 0)) : 0; + row[_model->_colInsertOrder] = group ? (group->insertBottom() ? 2 : 1) : 0; + + return true; + } + + return false; +} + +/** + * Updates the composite controls for the selected item + */ +void ObjectsPanel::_updateComposite() { + if (!_blockCompositeUpdate) + { + //Set the default values + bool setValues = true; + + //Get/set the values + _tree.get_selection()->selected_foreach_iter(sigc::bind(sigc::mem_fun(*this, &ObjectsPanel::_compositingChanged), &setValues)); + } +} + +/** + * Sets the compositing values for the first selected item in the tree + * @param iter Current tree item + * @param setValues Whether to set the compositing values + * @param blur Blur value to use + */ +void ObjectsPanel::_compositingChanged( const Gtk::TreeModel::iterator& iter, bool *setValues ) +{ + if (iter) { + Gtk::TreeModel::Row row = *iter; + SPItem *item = row[_model->_colObject]; + if (*setValues) + { + _setCompositingValues(item); + *setValues = false; + } + } +} + +/** + * Occurs when the current desktop selection changes + * @param sel The current selection + */ +void ObjectsPanel::_objectsSelected( Selection *sel ) { + + bool setOpacity = true; + _selectedConnection.block(); + _tree.get_selection()->unselect_all(); + SPItem *item = NULL; + for (const GSList * iter = sel->itemList(); iter != NULL; iter = iter->next) + { + item = reinterpret_cast(iter->data); + if (setOpacity) + { + _setCompositingValues(item); + setOpacity = false; + } + _store->foreach(sigc::bind( sigc::mem_fun(*this, &ObjectsPanel::_checkForSelected), item, iter->next == NULL)); + } + if (!item) { + if (_desktop->currentLayer() && SP_IS_ITEM(_desktop->currentLayer())) { + item = SP_ITEM(_desktop->currentLayer()); + _setCompositingValues(item); + _store->foreach(sigc::bind( sigc::mem_fun(*this, &ObjectsPanel::_checkForSelected), item, true)); + } + } + _selectedConnection.unblock(); + _checkTreeSelection(); +} + +/** + * Helper function for setting the compositing values + * @param item Item to use for setting the compositing values + */ +void ObjectsPanel::_setCompositingValues(SPItem *item) +{ + //Block the connections to avoid interference + _opacityConnection.block(); + _blendConnection.block(); + _blurConnection.block(); + + //Set the opacity + _opacity_adjustment.set_value((item->style->opacity.set ? SP_SCALE24_TO_FLOAT(item->style->opacity.value) : 1) * _opacity_adjustment.get_upper()); + SPFeBlend *spblend = NULL; + SPGaussianBlur *spblur = NULL; + if (item->style->getFilter()) + { + for(SPObject *primitive_obj = item->style->getFilter()->children; primitive_obj && SP_IS_FILTER_PRIMITIVE(primitive_obj); primitive_obj = primitive_obj->next) { + if(SP_IS_FEBLEND(primitive_obj) && !spblend) { + //Get the blend mode + spblend = SP_FEBLEND(primitive_obj); + } + + if(SP_IS_GAUSSIANBLUR(primitive_obj) && !spblur) { + //Get the blur value + spblur = SP_GAUSSIANBLUR(primitive_obj); + } + } + } + + //Set the blend mode + _fe_cb.set_blend_mode(spblend ? spblend->blend_mode : Inkscape::Filters::BLEND_NORMAL); + + //Set the blur value + Geom::OptRect bbox = item->bounds(SPItem::GEOMETRIC_BBOX); + if (bbox && spblur) { + double perimeter = bbox->dimensions()[Geom::X] + bbox->dimensions()[Geom::Y]; // fixme: this is only half the perimeter, is that correct? + _fe_blur.set_blur_value(spblur->stdDeviation.getNumber() * 400 / perimeter); + } else { + _fe_blur.set_blur_value(0); + } + + //Unblock connections + _blurConnection.unblock(); + _blendConnection.unblock(); + _opacityConnection.unblock(); +} + +/** + * Checks the tree and selects the specified item, optionally scrolling to the item + * @param path Current tree path + * @param iter Current tree item + * @param item Item to select in the tree + * @param scrollto Whether to scroll to the item + * @return Whether to continue searching the tree + */ +bool ObjectsPanel::_checkForSelected(const Gtk::TreePath &path, const Gtk::TreeIter& iter, SPItem* item, bool scrollto) +{ + bool stopGoing = false; + + Gtk::TreeModel::Row row = *iter; + if ( item == row[_model->_colObject] ) + { + //We found the item! Expand to the path and select it in the tree. + _tree.expand_to_path( path ); + + Glib::RefPtr select = _tree.get_selection(); + + select->select(iter); + if (scrollto) { + //Scroll to the item in the tree + _tree.scroll_to_row(path); + } + + stopGoing = true; + } + + return stopGoing; +} + +/** + * Pushes the current tree selection to the canvas + */ +void ObjectsPanel::_pushTreeSelectionToCurrent() +{ + if ( _desktop && _desktop->currentRoot() ) { + //block connections for selection and compositing values to prevent interference + _selectionChangedConnection.block(); + + //Clear the selection and then iterate over the tree selection, pushing each item to the desktop + _desktop->selection->clear(); + bool setOpacity = true; + _tree.get_selection()->selected_foreach_iter( sigc::bind(sigc::mem_fun(*this, &ObjectsPanel::_selected_row_callback), &setOpacity)); + //unblock connections + _selectionChangedConnection.unblock(); + + _checkTreeSelection(); + } +} + +/** + * Helper function for pushing the current tree selection to the current desktop + * @param iter Current tree item + * @param setCompositingValues Whether to set the compositing values + * @param blur + */ +void ObjectsPanel::_selected_row_callback( const Gtk::TreeModel::iterator& iter, bool *setCompositingValues ) +{ + if (iter) { + Gtk::TreeModel::Row row = *iter; + SPItem *item = row[_model->_colObject]; + if (!SP_IS_GROUP(item) || SP_GROUP(item)->layerMode() != SPGroup::LAYER) + { + //If the item is not a layer, then select it and set the current layer to its parent (if it's the first item) + if (_desktop->selection->isEmpty()) _desktop->setCurrentLayer(item->parent); + _desktop->selection->add(item); + } + else + { + //If the item is a layer, set the current layer + if (_desktop->selection->isEmpty()) _desktop->setCurrentLayer(item); + } + if (*setCompositingValues) + { + //Only set the compositing values for the first item + _setCompositingValues(item); + *setCompositingValues = false; + } + } +} + +/** + * Handles button sensitivity + */ +void ObjectsPanel::_checkTreeSelection() +{ + bool sensitive = _tree.get_selection()->count_selected_rows() > 0; + //TODO: top/bottom sensitivity + bool sensitiveNonTop = true; + bool sensitiveNonBottom = true; + + for ( std::vector::iterator it = _watching.begin(); it != _watching.end(); ++it ) { + (*it)->set_sensitive( sensitive ); + } + for ( std::vector::iterator it = _watchingNonTop.begin(); it != _watchingNonTop.end(); ++it ) { + (*it)->set_sensitive( sensitiveNonTop ); + } + for ( std::vector::iterator it = _watchingNonBottom.begin(); it != _watchingNonBottom.end(); ++it ) { + (*it)->set_sensitive( sensitiveNonBottom ); + } +} + +/** + * Sets visibility of items in the tree + * @param iter Current item in the tree + * @param visible Whether the item should be visible or not + */ +void ObjectsPanel::_setVisibleIter( const Gtk::TreeModel::iterator& iter, const bool visible ) +{ + Gtk::TreeModel::Row row = *iter; + SPItem* item = row[_model->_colObject]; + if (item) + { + item->setHidden( !visible ); + row[_model->_colVisible] = visible; + item->updateRepr(SP_OBJECT_WRITE_NO_CHILDREN | SP_OBJECT_WRITE_EXT); + } +} + +/** + * Sets sensitivity of items in the tree + * @param iter Current item in the tree + * @param locked Whether the item should be locked + */ +void ObjectsPanel::_setLockedIter( const Gtk::TreeModel::iterator& iter, const bool locked ) +{ + Gtk::TreeModel::Row row = *iter; + SPItem* item = row[_model->_colObject]; + if (item) + { + item->setLocked( locked ); + row[_model->_colLocked] = locked; + item->updateRepr(SP_OBJECT_WRITE_NO_CHILDREN | SP_OBJECT_WRITE_EXT); + } +} + +/** + * Handles keyboard events + * @param event Keyboard event passed in from GDK + * @return Whether the event should be eaten (om nom nom) + */ +bool ObjectsPanel::_handleKeyEvent(GdkEventKey *event) +{ + + switch (get_group0_keyval(event)) { + case GDK_KEY_Return: + case GDK_KEY_KP_Enter: + case GDK_KEY_F2: + { + Gtk::TreeModel::iterator iter = _tree.get_selection()->get_selected(); + if (iter && !_text_renderer->property_editable()) { + //Rename item + Gtk::TreeModel::Path *path = new Gtk::TreeModel::Path(iter); + _text_renderer->property_editable() = true; + _tree.set_cursor(*path, *_name_column, true); + grab_focus(); + return true; + } + } + break; + case GDK_Home: + { + //Move item(s) to top of containing group/layer + if (_desktop->selection->isEmpty()) + { + _fireAction( SP_VERB_LAYER_TO_TOP ); + } + else + { + _fireAction( SP_VERB_SELECTION_TO_FRONT ); + } + return true; + } + case GDK_End: + { + //Move item(s) to bottom of containing group/layer + if (_desktop->selection->isEmpty()) + { + _fireAction( SP_VERB_LAYER_TO_BOTTOM ); + } + else + { + _fireAction( SP_VERB_SELECTION_TO_BACK ); + } + return true; + } + case GDK_KEY_Page_Up: + { + //Move item(s) up in containing group/layer + if (_desktop->selection->isEmpty()) + { + _fireAction( SP_VERB_LAYER_RAISE ); + } + else + { + if (event->state & GDK_SHIFT_MASK) { + _fireAction( SP_VERB_LAYER_MOVE_TO_NEXT ); + } else { + _fireAction( SP_VERB_SELECTION_RAISE ); + } + } + return true; + } + case GDK_KEY_Page_Down: + { + //Move item(s) down in containing group/layer + if (_desktop->selection->isEmpty()) + { + _fireAction( SP_VERB_LAYER_LOWER ); + } + else + { + if (event->state & GDK_SHIFT_MASK) { + _fireAction( SP_VERB_LAYER_MOVE_TO_PREV ); + } else { + _fireAction( SP_VERB_SELECTION_LOWER ); + } + } + return true; + } + //TODO: Handle Ctrl-A, etc. + } + return false; +} + +/** + * Handles mouse events + * @param event Mouse event from GDK + * @return whether to eat the event (om nom nom) + */ +bool ObjectsPanel::_handleButtonEvent(GdkEventButton* event) +{ + static unsigned doubleclick = 0; + static bool overVisible = false; + + //Right mouse button was clicked, launch the pop-up menu + if ( (event->type == GDK_BUTTON_PRESS) && (event->button == 3) ) { + Gtk::TreeModel::Path path; + int x = static_cast(event->x); + int y = static_cast(event->y); + if ( _tree.get_path_at_pos( x, y, path ) ) { + _checkTreeSelection(); + _popupMenu.popup(event->button, event->time); + if (_tree.get_selection()->is_selected(path)) { + return true; + } + } + } + + //Left mouse button was pressed! In order to handle multiple item drag & drop, + //we need to defer selection by setting the select function so that the tree doesn't + //automatically select anything. In order to handle multiple item icon clicking, + //we need to eat the event. There might be a better way to do both of these... + if ( (event->type == GDK_BUTTON_PRESS) && (event->button == 1)) { + overVisible = false; + Gtk::TreeModel::Path path; + Gtk::TreeViewColumn* col = 0; + int x = static_cast(event->x); + int y = static_cast(event->y); + int x2 = 0; + int y2 = 0; + if ( _tree.get_path_at_pos( x, y, path, col, x2, y2 ) ) { + if (col == _tree.get_column(COL_VISIBLE-1)) { + //Click on visible column, eat this event to keep row selection + overVisible = true; + return true; + } else if (col == _tree.get_column(COL_LOCKED-1) || + col == _tree.get_column(COL_TYPE-1) || + col == _tree.get_column(COL_INSERTORDER - 1) || + col == _tree.get_column(COL_HIGHLIGHT-1)) { + //Click on an icon column, eat this event to keep row selection + return true; + } else if ( !(event->state & (GDK_SHIFT_MASK | GDK_CONTROL_MASK)) & _tree.get_selection()->is_selected(path) ) { + //Click on a selected item with no modifiers, defer selection to the mouse-up by + //setting the select function to _noSelection + _tree.get_selection()->set_select_function(sigc::mem_fun(*this, &ObjectsPanel::_noSelection)); + _defer_target = path; + } + } + } + + //Restore the selection function to allow tree selection on mouse button release + if ( event->type == GDK_BUTTON_RELEASE) { + _tree.get_selection()->set_select_function(sigc::mem_fun(*this, &ObjectsPanel::_rowSelectFunction)); + } + + //CellRenderers do not have good support for dealing with multiple items, so + //we handle all events on them here + if ( (event->type == GDK_BUTTON_RELEASE) && (event->button == 1)) { + + Gtk::TreeModel::Path path; + Gtk::TreeViewColumn* col = 0; + int x = static_cast(event->x); + int y = static_cast(event->y); + int x2 = 0; + int y2 = 0; + if ( _tree.get_path_at_pos( x, y, path, col, x2, y2 ) ) { + if (_defer_target) { + //We had deferred a selection target, select it here (assuming no drag & drop) + if (_defer_target == path && !(event->x == 0 && event->y == 0)) + { + _tree.set_cursor(path, *col, false); + } + _defer_target = Gtk::TreeModel::Path(); + } + else { + if (event->state & GDK_SHIFT_MASK) { + // Shift left click on the visible/lock columns toggles "solo" mode + if (col == _tree.get_column(COL_VISIBLE - 1)) { + _takeAction(BUTTON_SOLO); + } else if (col == _tree.get_column(COL_LOCKED - 1)) { + _takeAction(BUTTON_LOCK_OTHERS); + } + } else if (event->state & GDK_MOD1_MASK) { + // Alt+left click on the visible/lock columns toggles "solo" mode and preserves selection + Gtk::TreeModel::iterator iter = _store->get_iter(path); + if (_store->iter_is_valid(iter)) { + Gtk::TreeModel::Row row = *iter; + SPItem *item = row[_model->_colObject]; + if (col == _tree.get_column(COL_VISIBLE - 1)) { + _desktop->toggleLayerSolo( item ); + DocumentUndo::maybeDone(_desktop->doc(), "layer:solo", SP_VERB_LAYER_SOLO, _("Toggle layer solo")); + } else if (col == _tree.get_column(COL_LOCKED - 1)) { + _desktop->toggleLockOtherLayers( item ); + DocumentUndo::maybeDone(_desktop->doc(), "layer:lockothers", SP_VERB_LAYER_LOCK_OTHERS, _("Lock other layers")); + } + } + } else { + Gtk::TreeModel::Children::iterator iter = _tree.get_model()->get_iter(path); + Gtk::TreeModel::Row row = *iter; + + SPItem* item = row[_model->_colObject]; + + if (col == _tree.get_column(COL_VISIBLE - 1)) { + if (overVisible) { + //Toggle visibility + bool newValue = !row[_model->_colVisible]; + if (_tree.get_selection()->is_selected(path)) + { + //If the current row is selected, toggle the visibility + //for all selected items + _tree.get_selection()->selected_foreach_iter(sigc::bind(sigc::mem_fun(*this, &ObjectsPanel::_setVisibleIter), newValue)); + } + else + { + //If the current row is not selected, toggle just its visibility + row[_model->_colVisible] = newValue; + item->setHidden(!newValue); + item->updateRepr(SP_OBJECT_WRITE_NO_CHILDREN | SP_OBJECT_WRITE_EXT); + } + DocumentUndo::done( _desktop->doc() , SP_VERB_DIALOG_OBJECTS, + newValue? _("Unhide objects") : _("Hide objects")); + overVisible = false; + } + } else if (col == _tree.get_column(COL_LOCKED - 1)) { + //Toggle locking + bool newValue = !row[_model->_colLocked]; + if (_tree.get_selection()->is_selected(path)) + { + //If the current row is selected, toggle the sensitivity for + //all selected items + _tree.get_selection()->selected_foreach_iter(sigc::bind(sigc::mem_fun(*this, &ObjectsPanel::_setLockedIter), newValue)); + } + else + { + //If the current row is not selected, toggle just its sensitivity + row[_model->_colLocked] = newValue; + item->setLocked( newValue ); + item->updateRepr(SP_OBJECT_WRITE_NO_CHILDREN | SP_OBJECT_WRITE_EXT); + } + DocumentUndo::done( _desktop->doc() , SP_VERB_DIALOG_OBJECTS, + newValue? _("Lock objects") : _("Unlock objects")); + + } else if (col == _tree.get_column(COL_TYPE - 1)) { + if (SP_IS_GROUP(item)) + { + //Toggle the current item between a group and a layer + SPGroup * g = SP_GROUP(item); + bool newValue = g->layerMode() == SPGroup::LAYER; + row[_model->_colType] = newValue ? 1: 2; + g->setLayerMode(newValue ? SPGroup::GROUP : SPGroup::LAYER); + g->updateRepr(SP_OBJECT_WRITE_NO_CHILDREN | SP_OBJECT_WRITE_EXT); + DocumentUndo::done( _desktop->doc() , SP_VERB_DIALOG_OBJECTS, + newValue? _("Layer to group") : _("Group to layer")); + } + } else if (col == _tree.get_column(COL_INSERTORDER - 1)) { + if (SP_IS_GROUP(item)) + { + //Toggle the current item's insert order + SPGroup * g = SP_GROUP(item); + bool newValue = !g->insertBottom(); + row[_model->_colInsertOrder] = newValue ? 2: 1; + g->setInsertBottom(newValue); + g->updateRepr(SP_OBJECT_WRITE_NO_CHILDREN | SP_OBJECT_WRITE_EXT); + DocumentUndo::done( _desktop->doc() , SP_VERB_DIALOG_OBJECTS, + newValue? _("Set insert mode bottom") : _("Set insert mode top")); + } + } else if (col == _tree.get_column(COL_HIGHLIGHT - 1)) { + //Clear the highlight targets + _highlight_target.clear(); + if (_tree.get_selection()->is_selected(path)) + { + //If the current item is selected, store all selected items + //in the highlight source + _tree.get_selection()->selected_foreach_iter(sigc::mem_fun(*this, &ObjectsPanel::_storeHighlightTarget)); + } else { + //If the current item is not selected, store only it in the highlight source + _storeHighlightTarget(iter); + } + if (_colorSelector) + { + //Set up the color selector + SPColor color; + color.set( row[_model->_colHighlight] ); + _colorSelector->base->setColorAlpha(color, SP_RGBA32_A_F(row[_model->_colHighlight])); + } + //Show the color selector dialog + _colorSelectorDialog.show(); + } + } + } + } + } + + //Second mouse button press, set double click status for when the mouse is released + if ( (event->type == GDK_2BUTTON_PRESS) && (event->button == 1) ) { + doubleclick = 1; + } + + //Double click on mouse button release, if we're over the label column, edit + //the item name + if ( event->type == GDK_BUTTON_RELEASE && doubleclick) { + doubleclick = 0; + Gtk::TreeModel::Path path; + Gtk::TreeViewColumn* col = 0; + int x = static_cast(event->x); + int y = static_cast(event->y); + int x2 = 0; + int y2 = 0; + if ( _tree.get_path_at_pos( x, y, path, col, x2, y2 ) && col == _name_column) { + // Double click on the Layer name, enable editing + _text_renderer->property_editable() = true; + _tree.set_cursor (path, *_name_column, true); + grab_focus(); + } + } + + return false; +} + +/** + * Stores items in the highlight target vector to manipulate with the color selector + * @param iter Current tree item to store + */ +void ObjectsPanel::_storeHighlightTarget(const Gtk::TreeModel::iterator& iter) +{ + Gtk::TreeModel::Row row = *iter; + SPItem* item = row[_model->_colObject]; + if (item) + { + _highlight_target.push_back(item); + } +} + +/* + * Drap and drop within the tree + */ +bool ObjectsPanel::_handleDragDrop(const Glib::RefPtr& context, int x, int y, guint time) +{ + int cell_x = 0, cell_y = 0; + Gtk::TreeModel::Path target_path; + Gtk::TreeView::Column *target_column; + + //Set up our defaults and clear the source vector + _dnd_into = false; + _dnd_target = NULL; + _dnd_source.clear(); + + //Add all selected items to the source vector + _tree.get_selection()->selected_foreach_iter(sigc::mem_fun(*this, &ObjectsPanel::_storeDragSource)); + + if (_tree.get_path_at_pos (x, y, target_path, target_column, cell_x, cell_y)) { + // Are we before, inside or after the drop layer + Gdk::Rectangle rect; + _tree.get_background_area (target_path, *target_column, rect); + int cell_height = rect.get_height(); + _dnd_into = (cell_y > (int)(cell_height * 1/4) && cell_y <= (int)(cell_height * 3/4)); + if (cell_y > (int)(cell_height * 3/4)) { + Gtk::TreeModel::Path next_path = target_path; + next_path.next(); + if (_store->iter_is_valid(_store->get_iter(next_path))) { + target_path = next_path; + } else { + // Dragging to the "end" + Gtk::TreeModel::Path up_path = target_path; + up_path.up(); + if (_store->iter_is_valid(_store->get_iter(up_path))) { + // Drop into parent + target_path = up_path; + _dnd_into = true; + } else { + // Drop into the top level + _dnd_target = NULL; + } + } + } + Gtk::TreeModel::iterator iter = _store->get_iter(target_path); + if (_store->iter_is_valid(iter)) { + Gtk::TreeModel::Row row = *iter; + //Set the drop target. If we're not dropping into a group, we cannot + //drop into it, so set _dnd_into false. + _dnd_target = row[_model->_colObject]; + if (!(SP_IS_GROUP(_dnd_target))) _dnd_into = false; + } + } + + _takeAction(DRAGNDROP); + + return false; +} + +/** + * Stores all selected items as the drag source + * @param iter Current tree item + */ +void ObjectsPanel::_storeDragSource(const Gtk::TreeModel::iterator& iter) +{ + Gtk::TreeModel::Row row = *iter; + SPItem* item = row[_model->_colObject]; + if (item) + { + _dnd_source.push_back(item); + } +} + +/* + * Move a layer in response to a drag & drop action + */ +void ObjectsPanel::_doTreeMove( ) +{ + g_assert(_desktop != NULL); + g_assert(_document != NULL); + + std::vector idvector; + + //Clear the desktop selection + _desktop->selection->clear(); + while (!_dnd_source.empty()) + { + SPItem *obj = _dnd_source.back(); + _dnd_source.pop_back(); + + if (obj != _dnd_target) { + //Store the object id (for selection later) and move the object + idvector.push_back(g_strdup(obj->getId())); + obj->moveTo(_dnd_target, _dnd_into); + } + } + + //Select items + while (!idvector.empty()) { + //Grab the id from the vector, get the item in the document and select it + gchar * id = idvector.back(); + idvector.pop_back(); + SPObject *obj = _document->getObjectById(id); + g_free(id); + if (obj && SP_IS_ITEM(obj)) { + SPItem *item = SP_ITEM(obj); + if (!SP_IS_GROUP(item) || SP_GROUP(item)->layerMode() != SPGroup::LAYER) + { + if (_desktop->selection->isEmpty()) _desktop->setCurrentLayer(item->parent); + _desktop->selection->add(item); + } + else + { + if (_desktop->selection->isEmpty()) _desktop->setCurrentLayer(item); + } + } + } + + DocumentUndo::done( _desktop->doc() , SP_VERB_NONE, + _("Moved objects")); +} + +/** + * Fires the action verb + */ +void ObjectsPanel::_fireAction( unsigned int code ) +{ + if ( _desktop ) { + Verb *verb = Verb::get( code ); + if ( verb ) { + SPAction *action = verb->get_action(_desktop); + if ( action ) { + sp_action_perform( action, NULL ); + } + } + } +} + +/** + * Executes the given button action during the idle time + */ +void ObjectsPanel::_takeAction( int val ) +{ + if ( !_pending ) { + _pending = new InternalUIBounce(); + _pending->_actionCode = val; + Glib::signal_timeout().connect( sigc::mem_fun(*this, &ObjectsPanel::_executeAction), 0 ); + } +} + +/** + * Executes the pending button action + */ +bool ObjectsPanel::_executeAction() +{ + // Make sure selected layer hasn't changed since the action was triggered + if ( _document && _pending) + { + int val = _pending->_actionCode; +// SPObject* target = _pending->_target; + + switch ( val ) { + case BUTTON_NEW: + { + _fireAction( SP_VERB_LAYER_NEW ); + } + break; + case BUTTON_RENAME: + { + _fireAction( SP_VERB_LAYER_RENAME ); + } + break; + case BUTTON_TOP: + { + if (_desktop->selection->isEmpty()) + { + _fireAction( SP_VERB_LAYER_TO_TOP ); + } + else + { + _fireAction( SP_VERB_SELECTION_TO_FRONT); + } + } + break; + case BUTTON_BOTTOM: + { + if (_desktop->selection->isEmpty()) + { + _fireAction( SP_VERB_LAYER_TO_BOTTOM ); + } + else + { + _fireAction( SP_VERB_SELECTION_TO_BACK); + } + } + break; + case BUTTON_UP: + { + if (_desktop->selection->isEmpty()) + { + _fireAction( SP_VERB_LAYER_RAISE ); + } + else + { + _fireAction( SP_VERB_SELECTION_RAISE ); + } + } + break; + case BUTTON_DOWN: + { + if (_desktop->selection->isEmpty()) + { + _fireAction( SP_VERB_LAYER_LOWER ); + } + else + { + _fireAction( SP_VERB_SELECTION_LOWER ); + } + } + break; + case BUTTON_DUPLICATE: + { + if (_desktop->selection->isEmpty()) + { + _fireAction( SP_VERB_LAYER_DUPLICATE ); + } + else + { + _fireAction( SP_VERB_EDIT_DUPLICATE ); + } + } + break; + case BUTTON_DELETE: + { + if (_desktop->selection->isEmpty()) + { + _fireAction( SP_VERB_LAYER_DELETE ); + } + else + { + _fireAction( SP_VERB_EDIT_DELETE ); + } + } + break; + case BUTTON_SOLO: + { + _fireAction( SP_VERB_LAYER_SOLO ); + } + break; + case BUTTON_SHOW_ALL: + { + _fireAction( SP_VERB_LAYER_SHOW_ALL ); + } + break; + case BUTTON_HIDE_ALL: + { + _fireAction( SP_VERB_LAYER_HIDE_ALL ); + } + break; + case BUTTON_LOCK_OTHERS: + { + _fireAction( SP_VERB_LAYER_LOCK_OTHERS ); + } + break; + case BUTTON_LOCK_ALL: + { + _fireAction( SP_VERB_LAYER_LOCK_ALL ); + } + break; + case BUTTON_UNLOCK_ALL: + { + _fireAction( SP_VERB_LAYER_UNLOCK_ALL ); + } + break; + case BUTTON_SETCLIP: + { + _fireAction( SP_VERB_OBJECT_SET_CLIPPATH ); + } + break; + case BUTTON_UNSETCLIP: + { + _fireAction( SP_VERB_OBJECT_UNSET_CLIPPATH ); + } + break; + case BUTTON_SETMASK: + { + _fireAction( SP_VERB_OBJECT_SET_MASK ); + } + break; + case BUTTON_UNSETMASK: + { + _fireAction( SP_VERB_OBJECT_UNSET_MASK ); + } + break; + case BUTTON_GROUP: + { + _fireAction( SP_VERB_SELECTION_GROUP ); + } + break; + case BUTTON_UNGROUP: + { + _fireAction( SP_VERB_SELECTION_UNGROUP ); + } + break; + case BUTTON_COLLAPSE_ALL: + { + for (SPObject* obj = _document->getRoot()->firstChild(); obj != NULL; obj = obj->next) { + if (SP_IS_GROUP(obj)) { + _setCollapsed(SP_GROUP(obj)); + } + } + _objectsChanged(_document->getRoot()); + } + break; + case DRAGNDROP: + { + _doTreeMove( ); + } + break; + } + + delete _pending; + _pending = 0; + } + + return false; +} + +/** + * Handles an unsuccessful item label edit (escape pressed, etc.) + */ +void ObjectsPanel::_handleEditingCancelled() +{ + _text_renderer->property_editable() = false; +} + +/** + * Handle a successful item label edit + * @param path Tree path of the item currently being edited + * @param new_text New label text + */ +void ObjectsPanel::_handleEdited(const Glib::ustring& path, const Glib::ustring& new_text) +{ + Gtk::TreeModel::iterator iter = _tree.get_model()->get_iter(path); + Gtk::TreeModel::Row row = *iter; + + _renameObject(row, new_text); + _text_renderer->property_editable() = false; +} + +/** + * Renames an item in the tree + * @param row Tree row + * @param name New label to give to the item + */ +void ObjectsPanel::_renameObject(Gtk::TreeModel::Row row, const Glib::ustring& name) +{ + if ( row && _desktop) { + SPItem* item = row[_model->_colObject]; + if ( item ) { + gchar const* oldLabel = item->label(); + if ( !name.empty() && (!oldLabel || name != oldLabel) ) { + item->setLabel(name.c_str()); + DocumentUndo::done( _desktop->doc() , SP_VERB_NONE, + _("Rename object")); + } + } + } +} + +/** + * A row selection function used by the tree that doesn't allow any new items to be selected. + * Currently, this is used to allow multi-item drag & drop. + */ +bool ObjectsPanel::_noSelection( Glib::RefPtr const & /*model*/, Gtk::TreeModel::Path const & /*path*/, bool /*currentlySelected*/ ) +{ + return false; +} + +/** + * Default row selection function taken from the layers dialog + */ +bool ObjectsPanel::_rowSelectFunction( Glib::RefPtr const & /*model*/, Gtk::TreeModel::Path const & /*path*/, bool currentlySelected ) +{ + bool val = true; + if ( !currentlySelected && _toggleEvent ) + { + GdkEvent* event = gtk_get_current_event(); + if ( event ) { + // (keep these checks separate, so we know when to call gdk_event_free() + if ( event->type == GDK_BUTTON_PRESS ) { + GdkEventButton const* target = reinterpret_cast(_toggleEvent); + GdkEventButton const* evtb = reinterpret_cast(event); + + if ( (evtb->window == target->window) + && (evtb->send_event == target->send_event) + && (evtb->time == target->time) + && (evtb->state == target->state) + ) + { + // Ooooh! It's a magic one + val = false; + } + } + gdk_event_free(event); + } + } + return val; +} + +/** + * Sets a group to be collapsed and recursively collapses its children + * @param group The group to collapse + */ +void ObjectsPanel::_setCollapsed(SPGroup * group) +{ + group->setExpanded(false); + group->updateRepr(SP_OBJECT_WRITE_NO_CHILDREN | SP_OBJECT_WRITE_EXT); + for (SPObject *iter = group->children; iter != NULL; iter = iter->next) + { + if (SP_IS_GROUP(iter)) _setCollapsed(SP_GROUP(iter)); + } +} + +/** + * Sets a group to be expanded or collapsed + * @param iter Current tree item + * @param isexpanded Whether to expand or collapse + */ +void ObjectsPanel::_setExpanded(const Gtk::TreeModel::iterator& iter, const Gtk::TreeModel::Path& /*path*/, bool isexpanded) +{ + Gtk::TreeModel::Row row = *iter; + + SPItem* item = row[_model->_colObject]; + if (item && SP_IS_GROUP(item)) + { + if (isexpanded) + { + //If we're expanding, simply perform the expansion + SP_GROUP(item)->setExpanded(isexpanded); + item->updateRepr(SP_OBJECT_WRITE_NO_CHILDREN | SP_OBJECT_WRITE_EXT); + } + else + { + //If we're collapsing, we need to recursively collapse, so call our helper function + _setCollapsed(SP_GROUP(item)); + } + } +} + +/** + * Callback for when the highlight color is changed + * @param csel Color selector + * @param cp Objects panel + */ +void sp_highlight_picker_color_mod(SPColorSelector *csel, GObject * cp) +{ + SPColor color; + float alpha = 0; + csel->base->getColorAlpha(color, alpha); + guint32 rgba = color.toRGBA32( alpha ); + + ObjectsPanel *ptr = reinterpret_cast(cp); + + //Set the highlight color for all items in the _highlight_target (all selected items) + for (std::vector::iterator iter = ptr->_highlight_target.begin(); iter != ptr->_highlight_target.end(); ++iter) + { + SPItem * target = *iter; + target->setHighlightColor(rgba); + target->updateRepr(SP_OBJECT_WRITE_NO_CHILDREN | SP_OBJECT_WRITE_EXT); + } + DocumentUndo::done(SP_ACTIVE_DOCUMENT, SP_VERB_DIALOG_OBJECTS, _("Set object highlight color")); +} + +/** + * Callback for when the opacity value is changed + */ +void ObjectsPanel::_opacityValueChanged() +{ + _blockCompositeUpdate = true; + _tree.get_selection()->selected_foreach_iter(sigc::mem_fun(*this, &ObjectsPanel::_opacityChangedIter)); + DocumentUndo::maybeDone(_document, "opacity", SP_VERB_DIALOG_OBJECTS, _("Set object opacity")); + _blockCompositeUpdate = false; +} + +/** + * Change the opacity of the selected items in the tree + * @param iter Current tree item + */ +void ObjectsPanel::_opacityChangedIter(const Gtk::TreeIter& iter) +{ + Gtk::TreeModel::Row row = *iter; + SPItem* item = row[_model->_colObject]; + if (item) + { + item->style->opacity.set = TRUE; + item->style->opacity.value = SP_SCALE24_FROM_FLOAT(_opacity_adjustment.get_value() / _opacity_adjustment.get_upper()); + item->updateRepr(SP_OBJECT_WRITE_NO_CHILDREN | SP_OBJECT_WRITE_EXT); + } +} + +/** + * Callback for when the blend mode is changed + */ +void ObjectsPanel::_blendValueChanged() +{ + _blockCompositeUpdate = true; + const Glib::ustring blendmode = _fe_cb.get_blend_mode(); + + _tree.get_selection()->selected_foreach_iter(sigc::bind(sigc::mem_fun(*this, &ObjectsPanel::_blendChangedIter), blendmode)); + DocumentUndo::done(_document, SP_VERB_DIALOG_OBJECTS, _("Set object blend mode")); + _blockCompositeUpdate = false; +} + +/** + * Sets the blend mode of the selected tree items + * @param iter Current tree item + * @param blendmode Blend mode to set + */ +void ObjectsPanel::_blendChangedIter(const Gtk::TreeIter& iter, Glib::ustring blendmode) +{ + Gtk::TreeModel::Row row = *iter; + SPItem* item = row[_model->_colObject]; + if (item) + { + //Since blur and blend are both filters, we need to set both at the same time + SPStyle *style = item->style; + g_assert(style != NULL); + + if (blendmode != "normal") { + gdouble radius = 0; + if (item->style->getFilter()) { + for (SPObject *primitive = item->style->getFilter()->children; primitive && SP_IS_FILTER_PRIMITIVE(primitive); primitive = primitive->next) { + if (SP_IS_GAUSSIANBLUR(primitive)) { + Geom::OptRect bbox = item->bounds(SPItem::GEOMETRIC_BBOX); + if (bbox) { + radius = SP_GAUSSIANBLUR(primitive)->stdDeviation.getNumber(); + } + } + } + } + SPFilter *filter = new_filter_simple_from_item(_document, item, blendmode.c_str(), radius); + sp_style_set_property_url(item, "filter", filter, false); + } else { + for (SPObject *primitive = item->style->getFilter()->children; primitive && SP_IS_FILTER_PRIMITIVE(primitive); primitive = primitive->next) { + if (SP_IS_FEBLEND(primitive)) { + primitive->deleteObject(); + break; + } + } + if (!item->style->getFilter()->children) { + remove_filter(item, false); + } + } + + item->updateRepr(SP_OBJECT_WRITE_NO_CHILDREN | SP_OBJECT_WRITE_EXT); + } +} + +/** + * Callback for when the blur value has changed + */ +void ObjectsPanel::_blurValueChanged() +{ + _blockCompositeUpdate = true; + _tree.get_selection()->selected_foreach_iter(sigc::bind(sigc::mem_fun(*this, &ObjectsPanel::_blurChangedIter), _fe_blur.get_blur_value())); + DocumentUndo::maybeDone(_document, "blur", SP_VERB_DIALOG_OBJECTS, _("Set object blur")); + _blockCompositeUpdate = false; +} + +/** + * Sets the blur value for the selected items in the tree + * @param iter Current tree item + * @param blur Blur value to set + */ +void ObjectsPanel::_blurChangedIter(const Gtk::TreeIter& iter, double blur) +{ + Gtk::TreeModel::Row row = *iter; + SPItem* item = row[_model->_colObject]; + if (item) + { + //Since blur and blend are both filters, we need to set both at the same time + SPStyle *style = item->style; + if (style) { + Geom::OptRect bbox = item->bounds(SPItem::GEOMETRIC_BBOX); + double radius; + if (bbox) { + double perimeter = bbox->dimensions()[Geom::X] + bbox->dimensions()[Geom::Y]; // fixme: this is only half the perimeter, is that correct? + radius = blur * perimeter / 400; + } else { + radius = 0; + } + + if (radius != 0) { + SPFilter *filter = modify_filter_gaussian_blur_from_item(_document, item, radius); + sp_style_set_property_url(item, "filter", filter, false); + } else if (item->style->filter.set && item->style->getFilter()) { + for (SPObject *primitive = item->style->getFilter()->children; primitive && SP_IS_FILTER_PRIMITIVE(primitive); primitive = primitive->next) { + if (SP_IS_GAUSSIANBLUR(primitive)) { + primitive->deleteObject(); + break; + } + } + if (!item->style->getFilter()->children) { + remove_filter(item, false); + } + } + item->updateRepr(SP_OBJECT_WRITE_NO_CHILDREN | SP_OBJECT_WRITE_EXT); + } + } +} + +/** + * Constructor + */ +ObjectsPanel::ObjectsPanel() : + UI::Widget::Panel("", "/dialogs/objects", SP_VERB_DIALOG_OBJECTS), + _rootWatcher(0), + _deskTrack(), + _desktop(0), + _document(0), + _model(0), + _pending(0), + _toggleEvent(0), + _defer_target(), + _composite_vbox(false, 0), + _opacity_vbox(false, 0), + _opacity_label(_("Opacity:")), + _opacity_label_unit(_("%")), +#if WITH_GTKMM_3_0 + _opacity_adjustment(Gtk::Adjustment::create(100.0, 0.0, 100.0, 1.0, 1.0, 0.0)), +#else + _opacity_adjustment(100.0, 0.0, 100.0, 1.0, 1.0, 0.0), +#endif + _opacity_hscale(_opacity_adjustment), + _opacity_spin_button(_opacity_adjustment, 0.01, 1), + _fe_cb(UI::Widget::SimpleFilterModifier::BLEND), + _fe_vbox(false, 0), + _fe_alignment(1, 1, 1, 1), + _fe_blur(UI::Widget::SimpleFilterModifier::BLUR), + _blur_vbox(false, 0), + _blur_alignment(1, 1, 1, 1), + _colorSelectorDialog("dialogs.colorpickerwindow") +{ + //Create the tree model and store + ModelColumns *zoop = new ModelColumns(); + _model = zoop; + + _store = Gtk::TreeStore::create( *zoop ); + + //Set up the tree + _tree.set_model( _store ); + _tree.set_headers_visible(false); + _tree.set_reorderable(true); + _tree.enable_model_drag_dest (Gdk::ACTION_MOVE); + + //Create the column CellRenderers + //Visible + Inkscape::UI::Widget::ImageToggler *eyeRenderer = Gtk::manage( new Inkscape::UI::Widget::ImageToggler( + INKSCAPE_ICON("object-visible"), INKSCAPE_ICON("object-hidden")) ); + int visibleColNum = _tree.append_column("vis", *eyeRenderer) - 1; + eyeRenderer->property_activatable() = true; + Gtk::TreeViewColumn* col = _tree.get_column(visibleColNum); + if ( col ) { + col->add_attribute( eyeRenderer->property_active(), _model->_colVisible ); + } + + //Locked + Inkscape::UI::Widget::ImageToggler * renderer = Gtk::manage( new Inkscape::UI::Widget::ImageToggler( + INKSCAPE_ICON("object-locked"), INKSCAPE_ICON("object-unlocked")) ); + int lockedColNum = _tree.append_column("lock", *renderer) - 1; + renderer->property_activatable() = true; + col = _tree.get_column(lockedColNum); + if ( col ) { + col->add_attribute( renderer->property_active(), _model->_colLocked ); + } + + //Type + Inkscape::UI::Widget::LayerTypeIcon * typeRenderer = Gtk::manage( new Inkscape::UI::Widget::LayerTypeIcon()); + int typeColNum = _tree.append_column("type", *typeRenderer) - 1; + typeRenderer->property_activatable() = true; + col = _tree.get_column(typeColNum); + if ( col ) { + col->add_attribute( typeRenderer->property_active(), _model->_colType ); + } + + //Insert order + Inkscape::UI::Widget::InsertOrderIcon * insertRenderer = Gtk::manage( new Inkscape::UI::Widget::InsertOrderIcon()); + int insertColNum = _tree.append_column("type", *insertRenderer) - 1; + col = _tree.get_column(insertColNum); + if ( col ) { + col->add_attribute( insertRenderer->property_active(), _model->_colInsertOrder ); + } + + //Clip/mask + Inkscape::UI::Widget::ClipMaskIcon * clipRenderer = Gtk::manage( new Inkscape::UI::Widget::ClipMaskIcon()); + int clipColNum = _tree.append_column("clipmask", *clipRenderer) - 1; + col = _tree.get_column(clipColNum); + if ( col ) { + col->add_attribute( clipRenderer->property_active(), _model->_colClipMask ); + } + + //Highlight + Inkscape::UI::Widget::HighlightPicker * highlightRenderer = Gtk::manage( new Inkscape::UI::Widget::HighlightPicker()); + int highlightColNum = _tree.append_column("highlight", *highlightRenderer) - 1; + col = _tree.get_column(highlightColNum); + if ( col ) { + col->add_attribute( highlightRenderer->property_active(), _model->_colHighlight ); + } + + //Label + _text_renderer = Gtk::manage(new Gtk::CellRendererText()); + int nameColNum = _tree.append_column("Name", *_text_renderer) - 1; + _name_column = _tree.get_column(nameColNum); + _name_column->add_attribute(_text_renderer->property_text(), _model->_colLabel); + + //Set the expander and search columns + _tree.set_expander_column( *_tree.get_column(nameColNum) ); + _tree.set_search_column(_model->_colLabel); + + //Set up the tree selection + _tree.get_selection()->set_mode(Gtk::SELECTION_MULTIPLE); + _selectedConnection = _tree.get_selection()->signal_changed().connect( sigc::mem_fun(*this, &ObjectsPanel::_pushTreeSelectionToCurrent) ); + _tree.get_selection()->set_select_function( sigc::mem_fun(*this, &ObjectsPanel::_rowSelectFunction) ); + + //Set up tree signals + _tree.signal_button_press_event().connect( sigc::mem_fun(*this, &ObjectsPanel::_handleButtonEvent), false ); + _tree.signal_button_release_event().connect( sigc::mem_fun(*this, &ObjectsPanel::_handleButtonEvent), false ); + _tree.signal_key_press_event().connect( sigc::mem_fun(*this, &ObjectsPanel::_handleKeyEvent), false ); + _tree.signal_drag_drop().connect( sigc::mem_fun(*this, &ObjectsPanel::_handleDragDrop), false); + _tree.signal_row_collapsed().connect( sigc::bind(sigc::mem_fun(*this, &ObjectsPanel::_setExpanded), false)); + _tree.signal_row_expanded().connect( sigc::bind(sigc::mem_fun(*this, &ObjectsPanel::_setExpanded), true)); + + //Set up the label editing signals + _text_renderer->signal_edited().connect( sigc::mem_fun(*this, &ObjectsPanel::_handleEdited) ); + _text_renderer->signal_editing_canceled().connect( sigc::mem_fun(*this, &ObjectsPanel::_handleEditingCancelled) ); + + //Set up the scroller window and pack the page + _scroller.add( _tree ); + _scroller.set_policy( Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC ); + _scroller.set_shadow_type(Gtk::SHADOW_IN); + Gtk::Requisition sreq; +#if WITH_GTKMM_3_0 + Gtk::Requisition sreq_natural; + _scroller.get_preferred_size(sreq_natural, sreq); +#else + sreq = _scroller.size_request(); +#endif + int minHeight = 70; + if (sreq.height < minHeight) { + // Set a min height to see the layers when used with Ubuntu liboverlay-scrollbar + _scroller.set_size_request(sreq.width, minHeight); + } + + _page.pack_start( _scroller, Gtk::PACK_EXPAND_WIDGET ); + + //Set up the compositing items + //Blend mode filter effect + _composite_vbox.pack_start(_fe_vbox, false, false, 2); + _fe_alignment.set_padding(0, 0, 4, 0); + _fe_alignment.add(_fe_cb); + _fe_vbox.pack_start(_fe_alignment, false, false, 0); + _blendConnection = _fe_cb.signal_blend_blur_changed().connect(sigc::mem_fun(*this, &ObjectsPanel::_blendValueChanged)); + + //Blur filter effect + _composite_vbox.pack_start(_blur_vbox, false, false, 2); + _blur_alignment.set_padding(0, 0, 4, 0); + _blur_alignment.add(_fe_blur); + _blur_vbox.pack_start(_blur_alignment, false, false, 0); + _blurConnection = _fe_blur.signal_blend_blur_changed().connect(sigc::mem_fun(*this, &ObjectsPanel::_blurValueChanged)); + + //Opacity + _composite_vbox.pack_start(_opacity_vbox, false, false, 2); + _opacity_label.set_alignment(Gtk::ALIGN_END, Gtk::ALIGN_CENTER); + _opacity_hbox.pack_start(_opacity_label, false, false, 3); + _opacity_vbox.pack_start(_opacity_hbox, false, false, 0); + _opacity_hbox.pack_start(_opacity_hscale, true, true, 0); + _opacity_hbox.pack_start(_opacity_spin_button, false, false, 0); + _opacity_hbox.pack_start(_opacity_label_unit, false, false, 3); + _opacity_hscale.set_draw_value(false); +#if WITH_GTKMM_3_0 + _opacityConnection = _opacity_adjustment->signal_value_changed().connect(sigc::mem_fun(*this, &ObjectCompositeSettings::_opacityValueChanged)); + _opacity_label.set_mnemonic_widget(_opacity_hscale); +#else + _opacityConnection = _opacity_adjustment.signal_value_changed().connect(sigc::mem_fun(*this, &ObjectsPanel::_opacityValueChanged)); + _opacity_label.set_mnemonic_widget(_opacity_hscale); +#endif + + //Keep the labels aligned + GtkSizeGroup *labels = gtk_size_group_new(GTK_SIZE_GROUP_HORIZONTAL); + gtk_size_group_add_widget(labels, GTK_WIDGET(_opacity_label.gobj())); + gtk_size_group_add_widget(labels, GTK_WIDGET(_fe_cb.get_blur_label()->gobj())); + gtk_size_group_add_widget(labels, GTK_WIDGET(_fe_blur.get_blur_label()->gobj())); + + //Pack the compositing functions and the button row + _page.pack_end(_composite_vbox, Gtk::PACK_SHRINK); + _page.pack_end(_buttonsRow, Gtk::PACK_SHRINK); + + //Pack into the panel contents + _getContents()->pack_start(_page, Gtk::PACK_EXPAND_WIDGET); + + SPDesktop* targetDesktop = getDesktop(); + + //Set up the button row + Gtk::Button* btn = Gtk::manage( new Gtk::Button() ); + _styleButton( *btn, GTK_STOCK_ADD, _("New Layer") ); + btn->signal_clicked().connect( sigc::bind( sigc::mem_fun(*this, &ObjectsPanel::_takeAction), (int)BUTTON_NEW) ); + _buttonsSecondary.pack_start(*btn, Gtk::PACK_SHRINK); + + btn = Gtk::manage( new Gtk::Button() ); + _styleButton( *btn, GTK_STOCK_REMOVE, _("Remove") ); + btn->signal_clicked().connect( sigc::bind( sigc::mem_fun(*this, &ObjectsPanel::_takeAction), (int)BUTTON_DELETE) ); + _watching.push_back( btn ); + _buttonsSecondary.pack_start(*btn, Gtk::PACK_SHRINK); + + btn = Gtk::manage( new Gtk::Button() ); + _styleButton( *btn, GTK_STOCK_GOTO_BOTTOM, _("Move To Bottom") ); + btn->signal_clicked().connect( sigc::bind( sigc::mem_fun(*this, &ObjectsPanel::_takeAction), (int)BUTTON_BOTTOM) ); + _watchingNonBottom.push_back( btn ); + _buttonsPrimary.pack_end(*btn, Gtk::PACK_SHRINK); + + btn = Gtk::manage( new Gtk::Button() ); + _styleButton( *btn, GTK_STOCK_GO_DOWN, _("Move Down") ); + btn->signal_clicked().connect( sigc::bind( sigc::mem_fun(*this, &ObjectsPanel::_takeAction), (int)BUTTON_DOWN) ); + _watchingNonBottom.push_back( btn ); + _buttonsPrimary.pack_end(*btn, Gtk::PACK_SHRINK); + + btn = Gtk::manage( new Gtk::Button() ); + _styleButton( *btn, GTK_STOCK_GO_UP, _("Move Up") ); + btn->signal_clicked().connect( sigc::bind( sigc::mem_fun(*this, &ObjectsPanel::_takeAction), (int)BUTTON_UP) ); + _watchingNonTop.push_back( btn ); + _buttonsPrimary.pack_end(*btn, Gtk::PACK_SHRINK); + + btn = Gtk::manage( new Gtk::Button() ); + _styleButton( *btn, GTK_STOCK_GOTO_TOP, _("Move To Top") ); + btn->signal_clicked().connect( sigc::bind( sigc::mem_fun(*this, &ObjectsPanel::_takeAction), (int)BUTTON_TOP) ); + _watchingNonTop.push_back( btn ); + _buttonsPrimary.pack_end(*btn, Gtk::PACK_SHRINK); + + btn = Gtk::manage( new Gtk::Button() ); + _styleButton( *btn, GTK_STOCK_UNINDENT, _("Collapse All") ); + btn->signal_clicked().connect( sigc::bind( sigc::mem_fun(*this, &ObjectsPanel::_takeAction), (int)BUTTON_COLLAPSE_ALL) ); + _watchingNonBottom.push_back( btn ); + _buttonsPrimary.pack_end(*btn, Gtk::PACK_SHRINK); + + _buttonsRow.pack_start(_buttonsSecondary, Gtk::PACK_EXPAND_WIDGET); + _buttonsRow.pack_end(_buttonsPrimary, Gtk::PACK_EXPAND_WIDGET); + + _watching.push_back(&_composite_vbox); + + //Set up the pop-up menu + // ------------------------------------------------------- + { + _watching.push_back( &_addPopupItem( targetDesktop, SP_VERB_LAYER_RENAME, 0, "Rename", (int)BUTTON_RENAME ) ); + _watching.push_back( &_addPopupItem( targetDesktop, SP_VERB_EDIT_DUPLICATE, 0, "Duplicate", (int)BUTTON_DUPLICATE ) ); + _watching.push_back( &_addPopupItem( targetDesktop, SP_VERB_LAYER_NEW, 0, "New", (int)BUTTON_NEW ) ); + + _popupMenu.append(*Gtk::manage(new Gtk::SeparatorMenuItem())); + + _watching.push_back( &_addPopupItem( targetDesktop, SP_VERB_LAYER_SOLO, 0, "Solo", (int)BUTTON_SOLO ) ); + _watching.push_back( &_addPopupItem( targetDesktop, SP_VERB_LAYER_SHOW_ALL, 0, "Show All", (int)BUTTON_SHOW_ALL ) ); + _watching.push_back( &_addPopupItem( targetDesktop, SP_VERB_LAYER_HIDE_ALL, 0, "Hide All", (int)BUTTON_HIDE_ALL ) ); + + _popupMenu.append(*Gtk::manage(new Gtk::SeparatorMenuItem())); + + _watching.push_back( &_addPopupItem( targetDesktop, SP_VERB_LAYER_LOCK_OTHERS, 0, "Lock Others", (int)BUTTON_LOCK_OTHERS ) ); + _watching.push_back( &_addPopupItem( targetDesktop, SP_VERB_LAYER_LOCK_ALL, 0, "Lock All", (int)BUTTON_LOCK_ALL ) ); + _watching.push_back( &_addPopupItem( targetDesktop, SP_VERB_LAYER_UNLOCK_ALL, 0, "Unlock All", (int)BUTTON_UNLOCK_ALL ) ); + + _popupMenu.append(*Gtk::manage(new Gtk::SeparatorMenuItem())); + + _watchingNonTop.push_back( &_addPopupItem( targetDesktop, SP_VERB_SELECTION_RAISE, GTK_STOCK_GO_UP, "Up", (int)BUTTON_UP ) ); + _watchingNonBottom.push_back( &_addPopupItem( targetDesktop, SP_VERB_SELECTION_LOWER, GTK_STOCK_GO_DOWN, "Down", (int)BUTTON_DOWN ) ); + + _popupMenu.append(*Gtk::manage(new Gtk::SeparatorMenuItem())); + + _watching.push_back( &_addPopupItem( targetDesktop, SP_VERB_SELECTION_GROUP, 0, "Group", (int)BUTTON_GROUP ) ); + _watching.push_back( &_addPopupItem( targetDesktop, SP_VERB_SELECTION_UNGROUP, 0, "Ungroup", (int)BUTTON_UNGROUP ) ); + + _popupMenu.append(*Gtk::manage(new Gtk::SeparatorMenuItem())); + + _watching.push_back( &_addPopupItem( targetDesktop, SP_VERB_OBJECT_SET_CLIPPATH, 0, "Set Clip", (int)BUTTON_SETCLIP ) ); + //not implemented + //_watching.push_back( &_addPopupItem( targetDesktop, SP_VERB_OBJECT_CREATE_CLIP_GROUP, 0, "Create Clip Group", (int)BUTTON_CLIPGROUP ) ); + + //will never be implemented + //_watching.push_back( &_addPopupItem( targetDesktop, SP_VERB_OBJECT_SET_INVERSE_CLIPPATH, 0, "Set Inverse Clip", (int)BUTTON_SETINVCLIP ) ); + _watching.push_back( &_addPopupItem( targetDesktop, SP_VERB_OBJECT_UNSET_CLIPPATH, 0, "Unset Clip", (int)BUTTON_UNSETCLIP ) ); + + _popupMenu.append(*Gtk::manage(new Gtk::SeparatorMenuItem())); + + _watching.push_back( &_addPopupItem( targetDesktop, SP_VERB_OBJECT_SET_MASK, 0, "Set Mask", (int)BUTTON_SETMASK ) ); + _watching.push_back( &_addPopupItem( targetDesktop, SP_VERB_OBJECT_UNSET_MASK, 0, "Unset Mask", (int)BUTTON_UNSETMASK ) ); + + _popupMenu.show_all_children(); + } + // ------------------------------------------------------- + + //Set initial sensitivity of buttons + for ( std::vector::iterator it = _watching.begin(); it != _watching.end(); ++it ) { + (*it)->set_sensitive( false ); + } + for ( std::vector::iterator it = _watchingNonTop.begin(); it != _watchingNonTop.end(); ++it ) { + (*it)->set_sensitive( false ); + } + for ( std::vector::iterator it = _watchingNonBottom.begin(); it != _watchingNonBottom.end(); ++it ) { + (*it)->set_sensitive( false ); + } + + //Set up the color selection dialog + GtkWidget *dlg = GTK_WIDGET(_colorSelectorDialog.gobj()); + sp_transientize(dlg); + + _colorSelectorDialog.hide(); + _colorSelectorDialog.set_title (_("Select Highlight Color")); + _colorSelectorDialog.set_border_width (4); + _colorSelectorDialog.property_modal() = true; + _colorSelector = SP_COLOR_SELECTOR(sp_color_selector_new(SP_TYPE_COLOR_NOTEBOOK)); + _colorSelectorDialog.get_vbox()->pack_start ( + *Glib::wrap(&_colorSelector->vbox), true, true, 0); + + g_signal_connect(G_OBJECT(_colorSelector), "dragged", + G_CALLBACK(sp_highlight_picker_color_mod), (void *)this); + g_signal_connect(G_OBJECT(_colorSelector), "released", + G_CALLBACK(sp_highlight_picker_color_mod), (void *)this); + g_signal_connect(G_OBJECT(_colorSelector), "changed", + G_CALLBACK(sp_highlight_picker_color_mod), (void *)this); + + gtk_widget_show(GTK_WIDGET(_colorSelector)); + + setDesktop( targetDesktop ); + + show_all_children(); + + //Connect the desktop changed connection + desktopChangeConn = _deskTrack.connectDesktopChanged( sigc::mem_fun(*this, &ObjectsPanel::setDesktop) ); + _deskTrack.connect(GTK_WIDGET(gobj())); +} + +/** + * Destructor + */ +ObjectsPanel::~ObjectsPanel() +{ + //Close the highlight selection dialog + _colorSelectorDialog.hide(); + _colorSelector = NULL; + + //Set the desktop to null, which will disconnect all object watchers + setDesktop(NULL); + + if ( _model ) + { + delete _model; + _model = 0; + } + + if (_pending) { + delete _pending; + _pending = 0; + } + + if ( _toggleEvent ) + { + gdk_event_free( _toggleEvent ); + _toggleEvent = 0; + } + + desktopChangeConn.disconnect(); + _deskTrack.disconnect(); +} + +/** + * Sets the current document + */ +void ObjectsPanel::setDocument(SPDesktop* /*desktop*/, SPDocument* document) +{ + //Clear all object watchers + while (!_objectWatchers.empty()) + { + ObjectsPanel::ObjectWatcher *w = _objectWatchers.back(); + w->_repr->removeObserver(*w); + _objectWatchers.pop_back(); + delete w; + } + + //Delete the root watcher + if (_rootWatcher) + { + _rootWatcher->_repr->removeObserver(*_rootWatcher); + delete _rootWatcher; + _rootWatcher = NULL; + } + + _document = document; + + if (document && document->getRoot() && document->getRoot()->getRepr()) + { + //Create a new root watcher for the document and then call _objectsChanged to fill the tree + _rootWatcher = new ObjectsPanel::ObjectWatcher(this, document->getRoot()); + document->getRoot()->getRepr()->addObserver(*_rootWatcher); + _objectsChanged(document->getRoot()); + } +} + +/** + * Set the current panel desktop + */ +void ObjectsPanel::setDesktop( SPDesktop* desktop ) +{ + Panel::setDesktop(desktop); + + if ( desktop != _desktop ) { + _documentChangedConnection.disconnect(); + _selectionChangedConnection.disconnect(); + if ( _desktop ) { + _desktop = 0; + } + + _desktop = Panel::getDesktop(); + if ( _desktop ) { + //Connect desktop signals + _documentChangedConnection = _desktop->connectDocumentReplaced( sigc::mem_fun(*this, &ObjectsPanel::setDocument)); + _selectionChangedConnection = _desktop->selection->connectChanged( sigc::mem_fun(*this, &ObjectsPanel::_objectsSelected)); + + setDocument(_desktop, _desktop->doc()); + } else { + setDocument(NULL, NULL); + } + } + _deskTrack.setBase(desktop); +} +} //namespace Dialogs +} //namespace UI +} //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 : diff --git a/src/ui/dialog/objects.h b/src/ui/dialog/objects.h new file mode 100644 index 000000000..7b07afd63 --- /dev/null +++ b/src/ui/dialog/objects.h @@ -0,0 +1,255 @@ +/* + * A simple dialog for objects UI. + * + * Authors: + * Theodore Janeczko + * + * Copyright (C) Theodore Janeczko 2012 + * + * Released under GNU GPL, read the file 'COPYING' for more information + */ + +#ifndef SEEN_OBJECTS_PANEL_H +#define SEEN_OBJECTS_PANEL_H + +#include +#include +#include +#include +#include +#include "ui/widget/spinbutton.h" +#include "ui/widget/panel.h" +#include "ui/widget/object-composite-settings.h" +#include "desktop-tracker.h" +#include "ui/widget/style-subject.h" +#include "selection.h" +#include "ui/widget/filter-effect-chooser.h" + +class SPObject; +class SPGroup; +struct SPColorSelector; + +namespace Inkscape { + +namespace UI { +namespace Dialog { + + +/** + * A panel that displays objects. + */ +class ObjectsPanel : public UI::Widget::Panel +{ +public: + ObjectsPanel(); + virtual ~ObjectsPanel(); + + static ObjectsPanel& getInstance(); + + void setDesktop( SPDesktop* desktop ); + void setDocument( SPDesktop* desktop, SPDocument* document); + +private: + //Internal Classes: + class ModelColumns; + class InternalUIBounce; + class ObjectWatcher; + + //Connections, Watchers, Trackers: + + //Document root watcher + ObjectsPanel::ObjectWatcher* _rootWatcher; + + //All object watchers + std::vector _objectWatchers; + + //Connection for when the desktop changes + sigc::connection desktopChangeConn; + + //Connection for when the document changes + sigc::connection _documentChangedConnection; + + //Connection for when the active selection in the document changes + sigc::connection _selectionChangedConnection; + + //Connection for when the selection in the dialog changes + sigc::connection _selectedConnection; + + //Connections for when the opacity/blend/blur of the active selection in the document changes + sigc::connection _opacityConnection; + sigc::connection _blendConnection; + sigc::connection _blurConnection; + + //Desktop tracker for grabbing the desktop changed connection + DesktopTracker _deskTrack; + + //Members: + + //The current desktop + SPDesktop* _desktop; + + //The current document + SPDocument* _document; + + //Tree data model + ModelColumns* _model; + + //Prevents the composite controls from updating + bool _blockCompositeUpdate; + + // + InternalUIBounce* _pending; + + //Whether the drag & drop was dragged into an item + gboolean _dnd_into; + + //List of drag & drop source items + std::vector _dnd_source; + + //Drag & drop target item + SPItem* _dnd_target; + + //List of items to change the highlight on + std::vector _highlight_target; + + //GUI Members: + + GdkEvent* _toggleEvent; + + Gtk::TreeModel::Path _defer_target; + + Glib::RefPtr _store; + std::vector _watching; + std::vector _watchingNonTop; + std::vector _watchingNonBottom; + + Gtk::TreeView _tree; + Gtk::CellRendererText *_text_renderer; + Gtk::TreeView::Column *_name_column; +#if WITH_GTKMM_3_0 + Gtk::Box _buttonsRow; + Gtk::Box _buttonsPrimary; + Gtk::Box _buttonsSecondary; +#else + Gtk::HBox _buttonsRow; + Gtk::HBox _buttonsPrimary; + Gtk::HBox _buttonsSecondary; +#endif + Gtk::ScrolledWindow _scroller; + Gtk::Menu _popupMenu; + Inkscape::UI::Widget::SpinButton _spinBtn; + Gtk::VBox _page; + + /* Composite Settings */ + Gtk::VBox _composite_vbox; + Gtk::VBox _opacity_vbox; + Gtk::HBox _opacity_hbox; + Gtk::Label _opacity_label; + Gtk::Label _opacity_label_unit; +#if WITH_GTKMM_3_0 + Glib::RefPtr _opacity_adjustment; +#else + Gtk::Adjustment _opacity_adjustment; +#endif + Gtk::HScale _opacity_hscale; + Inkscape::UI::Widget::SpinButton _opacity_spin_button; + + Inkscape::UI::Widget::SimpleFilterModifier _fe_cb; + Gtk::VBox _fe_vbox; + Gtk::Alignment _fe_alignment; + Inkscape::UI::Widget::SimpleFilterModifier _fe_blur; + Gtk::VBox _blur_vbox; + Gtk::Alignment _blur_alignment; + + Gtk::Dialog _colorSelectorDialog; + SPColorSelector *_colorSelector; + + + //Methods: + + ObjectsPanel(ObjectsPanel const &); // no copy + ObjectsPanel &operator=(ObjectsPanel const &); // no assign + + void _styleButton( Gtk::Button& btn, char const* iconName, char const* tooltip ); + void _fireAction( unsigned int code ); + + Gtk::MenuItem& _addPopupItem( SPDesktop *desktop, unsigned int code, char const* iconName, char const* fallback, int id ); + + void _setVisibleIter( const Gtk::TreeModel::iterator& iter, const bool visible ); + void _setLockedIter( const Gtk::TreeModel::iterator& iter, const bool locked ); + + bool _handleButtonEvent(GdkEventButton *event); + bool _handleKeyEvent(GdkEventKey *event); + + void _storeHighlightTarget(const Gtk::TreeModel::iterator& iter); + void _storeDragSource(const Gtk::TreeModel::iterator& iter); + bool _handleDragDrop(const Glib::RefPtr& context, int x, int y, guint time); + void _handleEdited(const Glib::ustring& path, const Glib::ustring& new_text); + void _handleEditingCancelled(); + + void _doTreeMove(); + void _renameObject(Gtk::TreeModel::Row row, const Glib::ustring& name); + + void _pushTreeSelectionToCurrent(); + void _selected_row_callback( const Gtk::TreeModel::iterator& iter, bool *setOpacity ); + + void _checkTreeSelection(); + + void _takeAction( int val ); + bool _executeAction(); + + void _setExpanded( const Gtk::TreeModel::iterator& iter, const Gtk::TreeModel::Path& path, bool isexpanded ); + void _setCollapsed(SPGroup * group); + + bool _noSelection( Glib::RefPtr const & model, Gtk::TreeModel::Path const & path, bool b ); + bool _rowSelectFunction( Glib::RefPtr const & model, Gtk::TreeModel::Path const & path, bool b ); + + void _compositingChanged( const Gtk::TreeModel::iterator& iter, bool *setValues ); + void _updateComposite(); + void _setCompositingValues(SPItem *item); + + void _updateObject(SPObject *obj, bool recurse); + bool _checkForUpdated(const Gtk::TreeIter& iter, SPObject* obj); + + void _objectsSelected(Selection *sel); + bool _checkForSelected(const Gtk::TreePath& path, const Gtk::TreeIter& iter, SPItem* item, bool scrollto); + + void _objectsChanged(SPObject *obj); + void _addObject( SPObject* obj, Gtk::TreeModel::Row* parentRow ); + + void _opacityChangedIter(const Gtk::TreeIter& iter); + void _opacityValueChanged(); + + void _blendChangedIter(const Gtk::TreeIter& iter, Glib::ustring blendmode); + void _blendValueChanged(); + + void _blurChangedIter(const Gtk::TreeIter& iter, double blur); + void _blurValueChanged(); + + + void setupDialog(const Glib::ustring &title); + + friend void sp_highlight_picker_color_mod(SPColorSelector *csel, GObject *cp); + +}; + + + +} //namespace Dialogs +} //namespace UI +} //namespace Inkscape + + + +#endif // SEEN_OBJECTS_PANEL_H + +/* + 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 : diff --git a/src/ui/dialog/tags.cpp b/src/ui/dialog/tags.cpp new file mode 100644 index 000000000..f994b571f --- /dev/null +++ b/src/ui/dialog/tags.cpp @@ -0,0 +1,1182 @@ +/* + * A simple panel for tags + * + * Authors: + * Theodore Janeczko + * + * Copyright (C) Theodore Janeczko 2012 + * + * Released under GNU GPL, read the file 'COPYING' for more information + */ +#ifdef HAVE_CONFIG_H +# include +#endif + +#include "tags.h" +#include +#include +#include +#include + +#include + +#include "desktop.h" +#include "desktop-style.h" +#include "document.h" +#include "document-undo.h" +#include "helper/action.h" +#include "inkscape.h" +#include "layer-fns.h" +#include "layer-manager.h" +#include "preferences.h" +#include "sp-item.h" +#include "sp-object.h" +#include "sp-shape.h" +#include "svg/css-ostringstream.h" +#include "ui/icon-names.h" +#include "ui/widget/layertypeicon.h" +#include "ui/widget/addtoicon.h" +#include "verbs.h" +#include "widgets/icon.h" +#include "xml/node.h" +#include "xml/node-observer.h" +#include "xml/repr.h" +#include "sp-root.h" +#include "event-context.h" +#include "selection.h" +#include "dialogs/dialog-events.h" +#include "widgets/sp-color-notebook.h" +#include "style.h" +#include "filter-chemistry.h" +#include "filters/blend.h" +#include "filters/gaussian-blur.h" +#include "sp-clippath.h" +#include "sp-mask.h" +#include "sp-tag.h" +#include "sp-defs.h" +#include "sp-tag-use.h" +#include "sp-tag-use-reference.h" + +//#define DUMP_LAYERS 1 + +namespace Inkscape { +namespace UI { +namespace Dialog { + +using Inkscape::XML::Node; + +TagsPanel& TagsPanel::getInstance() +{ + return *new TagsPanel(); +} + +enum { + COL_ADD = 1 +}; + +enum { + BUTTON_NEW = 0, + BUTTON_TOP, + BUTTON_BOTTOM, + BUTTON_UP, + BUTTON_DOWN, + BUTTON_DELETE, + DRAGNDROP +}; + +class TagsPanel::ObjectWatcher : public Inkscape::XML::NodeObserver { +public: + ObjectWatcher(TagsPanel* pnl, SPObject* obj, Inkscape::XML::Node * repr) : + _pnl(pnl), + _obj(obj), + _repr(repr), + _labelAttr(g_quark_from_string("inkscape:label")) + {} + + ObjectWatcher(TagsPanel* pnl, SPObject* obj) : + _pnl(pnl), + _obj(obj), + _repr(obj->getRepr()), + _labelAttr(g_quark_from_string("inkscape:label")) + {} + + virtual void notifyChildAdded( Node &/*node*/, Node &/*child*/, Node */*prev*/ ) + { + if ( _pnl && _obj ) { + _pnl->_objectsChanged( _obj ); + } + } + virtual void notifyChildRemoved( Node &/*node*/, Node &/*child*/, Node */*prev*/ ) + { + if ( _pnl && _obj ) { + _pnl->_objectsChanged( _obj ); + } + } + virtual void notifyChildOrderChanged( Node &/*node*/, Node &/*child*/, Node */*old_prev*/, Node */*new_prev*/ ) + { + if ( _pnl && _obj ) { + _pnl->_objectsChanged( _obj ); + } + } + virtual void notifyContentChanged( Node &/*node*/, Util::ptr_shared /*old_content*/, Util::ptr_shared /*new_content*/ ) {} + virtual void notifyAttributeChanged( Node &/*node*/, GQuark name, Util::ptr_shared /*old_value*/, Util::ptr_shared /*new_value*/ ) { + if ( _pnl && _obj ) { + if ( name == _labelAttr ) { + _pnl->_updateObject( _obj); + } + } + } + + TagsPanel* _pnl; + SPObject* _obj; + Inkscape::XML::Node* _repr; + GQuark _labelAttr; +}; + +class TagsPanel::InternalUIBounce +{ +public: + int _actionCode; +}; + +void TagsPanel::_styleButton( Gtk::Button& btn, SPDesktop *desktop, unsigned int code, char const* iconName, char const* tooltip ) +{ + bool set = false; + + if ( iconName ) { + GtkWidget *child = sp_icon_new( Inkscape::ICON_SIZE_SMALL_TOOLBAR, iconName ); + gtk_widget_show( child ); + btn.add( *manage(Glib::wrap(child)) ); + btn.set_relief(Gtk::RELIEF_NONE); + set = true; + } + + if ( desktop ) { + Verb *verb = Verb::get( code ); + if ( verb ) { + SPAction *action = verb->get_action(desktop); + if ( !set && action && action->image ) { + GtkWidget *child = sp_icon_new( Inkscape::ICON_SIZE_SMALL_TOOLBAR, action->image ); + gtk_widget_show( child ); + btn.add( *manage(Glib::wrap(child)) ); + set = true; + } + } + } + + btn.set_tooltip_text (tooltip); +} + + +Gtk::MenuItem& TagsPanel::_addPopupItem( SPDesktop *desktop, unsigned int code, char const* iconName, char const* fallback, int id ) +{ + GtkWidget* iconWidget = 0; + const char* label = 0; + + if ( iconName ) { + iconWidget = sp_icon_new( Inkscape::ICON_SIZE_MENU, iconName ); + } + + if ( desktop ) { + Verb *verb = Verb::get( code ); + if ( verb ) { + SPAction *action = verb->get_action(desktop); + if ( !iconWidget && action && action->image ) { + iconWidget = sp_icon_new( Inkscape::ICON_SIZE_MENU, action->image ); + } + + if ( action ) { + label = action->name; + } + } + } + + if ( !label && fallback ) { + label = fallback; + } + + Gtk::Widget* wrapped = 0; + if ( iconWidget ) { + wrapped = manage(Glib::wrap(iconWidget)); + wrapped->show(); + } + + + Gtk::MenuItem* item = 0; + + if (wrapped) { + item = Gtk::manage(new Gtk::ImageMenuItem(*wrapped, label, true)); + } else { + item = Gtk::manage(new Gtk::MenuItem(label, true)); + } + + item->signal_activate().connect(sigc::bind(sigc::mem_fun(*this, &TagsPanel::_takeAction), id)); + _popupMenu.append(*item); + + return *item; +} + +void TagsPanel::_fireAction( unsigned int code ) +{ + if ( _desktop ) { + Verb *verb = Verb::get( code ); + if ( verb ) { + SPAction *action = verb->get_action(_desktop); + if ( action ) { + sp_action_perform( action, NULL ); + } + } + } +} + +void TagsPanel::_takeAction( int val ) +{ + if ( !_pending ) { + _pending = new InternalUIBounce(); + _pending->_actionCode = val; + Glib::signal_timeout().connect( sigc::mem_fun(*this, &TagsPanel::_executeAction), 0 ); + } +} + +bool TagsPanel::_executeAction() +{ + // Make sure selected layer hasn't changed since the action was triggered + if ( _pending) + { + int val = _pending->_actionCode; +// SPObject* target = _pending->_target; + + switch ( val ) { + case BUTTON_NEW: + { + _fireAction( SP_VERB_TAG_NEW ); + } + break; + case BUTTON_TOP: + { + if (_desktop->selection->isEmpty()) + { + _fireAction( SP_VERB_LAYER_TO_TOP ); + } + else + { + _fireAction( SP_VERB_SELECTION_TO_FRONT); + } + } + break; + case BUTTON_BOTTOM: + { + if (_desktop->selection->isEmpty()) + { + _fireAction( SP_VERB_LAYER_TO_BOTTOM ); + } + else + { + _fireAction( SP_VERB_SELECTION_TO_BACK); + } + } + break; + case BUTTON_UP: + { + if (_desktop->selection->isEmpty()) + { + _fireAction( SP_VERB_LAYER_RAISE ); + } + else + { + _fireAction( SP_VERB_SELECTION_RAISE ); + } + } + break; + case BUTTON_DOWN: + { + if (_desktop->selection->isEmpty()) + { + _fireAction( SP_VERB_LAYER_LOWER ); + } + else + { + _fireAction( SP_VERB_SELECTION_LOWER ); + } + } + break; + case BUTTON_DELETE: + { + std::vector todelete; + _tree.get_selection()->selected_foreach_iter(sigc::bind*>(sigc::mem_fun(*this, &TagsPanel::_checkForDeleted), &todelete)); + for (std::vector::iterator iter = todelete.begin(); iter != todelete.end(); ++iter) { + SPObject * obj = *iter; + if (obj && obj->parent && obj->getRepr() && obj->parent->getRepr()) { + obj->parent->getRepr()->removeChild(obj->getRepr()); + } + } + DocumentUndo::done(_document, SP_VERB_DIALOG_TAGS, _("Remove from tags")); + } + break; + case DRAGNDROP: + { + _doTreeMove( ); + } + break; + } + + delete _pending; + _pending = 0; + } + + return false; +} + + +class TagsPanel::ModelColumns : public Gtk::TreeModel::ColumnRecord +{ +public: + + ModelColumns() + { + add(_colParentObject); + add(_colObject); + add(_colLabel); + add(_colAddRemove); + add(_colAllowAddRemove); + } + virtual ~ModelColumns() {} + + Gtk::TreeModelColumn _colParentObject; + Gtk::TreeModelColumn _colObject; + Gtk::TreeModelColumn _colLabel; + Gtk::TreeModelColumn _colAddRemove; + Gtk::TreeModelColumn _colAllowAddRemove; +}; + +void TagsPanel::_checkForDeleted(const Gtk::TreeIter& iter, std::vector* todelete) +{ + Gtk::TreeRow row = *iter; + SPObject * obj = row[_model->_colObject]; + if (obj && obj->parent) { + todelete->push_back(obj); + } +} + +void TagsPanel::_updateObject( SPObject *obj ) { + _store->foreach( sigc::bind(sigc::mem_fun(*this, &TagsPanel::_checkForUpdated), obj) ); +} + +bool TagsPanel::_checkForUpdated(const Gtk::TreePath &/*path*/, const Gtk::TreeIter& iter, SPObject* obj) +{ + Gtk::TreeModel::Row row = *iter; + if ( obj == row[_model->_colObject] ) + { + /* + * We get notified of layer update here (from layer->setLabel()) before layer->label() is set + * with the correct value (sp-object bug?). So use the inkscape:label attribute instead which + * has the correct value (bug #168351) + */ + //row[_model->_colLabel] = layer->label() ? layer->label() : layer->getId(); + gchar const *label; + SPTagUse * use = SP_IS_TAG_USE(obj) ? SP_TAG_USE(obj) : 0; + if (use && use->ref->isAttached()) { + label = use->ref->getObject()->getAttribute("inkscape:label"); + } else { + label = obj->getAttribute("inkscape:label"); + } + row[_model->_colLabel] = label ? label : obj->getId(); + row[_model->_colAddRemove] = SP_IS_TAG(obj); + } + + return false; +} + +void TagsPanel::_objectsSelected( Selection *sel ) { + + _selectedConnection.block(); + _tree.get_selection()->unselect_all(); + for (const GSList * iter = sel->list(); iter != NULL; iter = iter->next) + { + SPObject *obj = reinterpret_cast(iter->data); + _store->foreach(sigc::bind( sigc::mem_fun(*this, &TagsPanel::_checkForSelected), obj)); + } + _selectedConnection.unblock(); + _checkTreeSelection(); +} + +bool TagsPanel::_checkForSelected(const Gtk::TreePath &path, const Gtk::TreeIter& iter, SPObject* obj) +{ + Gtk::TreeModel::Row row = *iter; + SPObject * it = row[_model->_colObject]; + if ( it && SP_IS_TAG_USE(it) && SP_TAG_USE(it)->ref->getObject() == obj ) + { + Glib::RefPtr select = _tree.get_selection(); + + select->select(iter); + } + return false; +} + +void TagsPanel::_objectsChanged(SPObject* root) +{ + while (!_objectWatchers.empty()) + { + TagsPanel::ObjectWatcher *w = _objectWatchers.back(); + w->_repr->removeObserver(*w); + _objectWatchers.pop_back(); + delete w; + } + + if (_desktop) { + SPDocument* document = _desktop->doc(); + SPDefs* root = document->getDefs(); + if ( root ) { + _selectedConnection.block(); + _store->clear(); + _addObject( document, root, 0 ); + _selectedConnection.unblock(); + _objectsSelected(_desktop->selection); + _checkTreeSelection(); + } + } +} + +void TagsPanel::_addObject( SPDocument* doc, SPObject* obj, Gtk::TreeModel::Row* parentRow ) +{ + if ( _desktop && obj ) { + for ( SPObject *child = obj->children; child != NULL; child = child->next) { + if (SP_IS_TAG(child)) + { + Gtk::TreeModel::iterator iter = parentRow ? _store->prepend(parentRow->children()) : _store->prepend(); + Gtk::TreeModel::Row row = *iter; + row[_model->_colObject] = child; + row[_model->_colParentObject] = NULL; + row[_model->_colLabel] = child->label() ? child->label() : child->getId(); + row[_model->_colAddRemove] = true; + row[_model->_colAllowAddRemove] = true; + + _tree.expand_to_path( _store->get_path(iter) ); + + TagsPanel::ObjectWatcher *w = new TagsPanel::ObjectWatcher(this, child); + child->getRepr()->addObserver(*w); + _objectWatchers.push_back(w); + _addObject( doc, child, &row ); + } + } + if (SP_IS_TAG(obj) && obj->children) + { + Gtk::TreeModel::iterator iteritems = parentRow ? _store->append(parentRow->children()) : _store->prepend(); + Gtk::TreeModel::Row rowitems = *iteritems; + rowitems[_model->_colObject] = NULL; + rowitems[_model->_colParentObject] = obj; + rowitems[_model->_colLabel] = _("Items"); + rowitems[_model->_colAddRemove] = false; + rowitems[_model->_colAllowAddRemove] = false; + + _tree.expand_to_path( _store->get_path(iteritems) ); + + for ( SPObject *child = obj->children; child != NULL; child = child->next) { + if (SP_IS_TAG_USE(child)) + { + SPItem *item = SP_TAG_USE(child)->ref->getObject(); + Gtk::TreeModel::iterator iter = _store->prepend(rowitems->children()); + Gtk::TreeModel::Row row = *iter; + row[_model->_colObject] = child; + row[_model->_colParentObject] = NULL; + row[_model->_colLabel] = item ? (item->label() ? item->label() : item->getId()) : SP_TAG_USE(child)->href; + row[_model->_colAddRemove] = false; + row[_model->_colAllowAddRemove] = true; + + if (SP_TAG(obj)->expanded()) { + _tree.expand_to_path( _store->get_path(iter) ); + } + + if (item) { + TagsPanel::ObjectWatcher *w = new TagsPanel::ObjectWatcher(this, child, item->getRepr()); + item->getRepr()->addObserver(*w); + _objectWatchers.push_back(w); + } + } + } + } + } +} + +void TagsPanel::_select_tag( SPTag * tag ) +{ + for (SPObject * child = tag->children; child != NULL; child = child->next) + { + if (SP_IS_TAG(child)) { + _select_tag(SP_TAG(child)); + } else if (SP_IS_TAG_USE(child)) { + SPObject * obj = SP_TAG_USE(child)->ref->getObject(); + if (obj) { + if (_desktop->selection->isEmpty()) _desktop->setCurrentLayer(obj->parent); + _desktop->selection->add(obj); + } + } + } +} + +void TagsPanel::_selected_row_callback( const Gtk::TreeModel::iterator& iter ) +{ + if (iter) { + Gtk::TreeModel::Row row = *iter; + SPObject *obj = row[_model->_colObject]; + if (obj) { + if (SP_IS_TAG(obj)) { + _select_tag(SP_TAG(obj)); + } else if (SP_IS_TAG_USE(obj)) { + SPObject * item = SP_TAG_USE(obj)->ref->getObject(); + if (item) { + if (_desktop->selection->isEmpty()) _desktop->setCurrentLayer(item->parent); + _desktop->selection->add(item); + } + } + } + } +} + +void TagsPanel::_pushTreeSelectionToCurrent() +{ + _selectionChangedConnection.block(); + // TODO hunt down the possible API abuse in getting NULL + if ( _desktop && _desktop->currentRoot() ) { + _desktop->selection->clear(); + _tree.get_selection()->selected_foreach_iter( sigc::mem_fun(*this, &TagsPanel::_selected_row_callback)); + } + _selectionChangedConnection.unblock(); + + _checkTreeSelection(); +} + +void TagsPanel::_checkTreeSelection() +{ + bool sensitive = _tree.get_selection()->count_selected_rows() > 0; + bool sensitiveNonTop = true; + bool sensitiveNonBottom = true; +// if ( _tree.get_selection()->count_selected_rows() > 0 ) { +// sensitive = true; +// +// SPObject* inTree = _selectedLayer(); +// if ( inTree ) { +// +// sensitiveNonTop = (Inkscape::Nex(inTree->parent, inTree) != 0); +// sensitiveNonBottom = (Inkscape::previous_layer(inTree->parent, inTree) != 0); +// +// } +// } + + + for ( std::vector::iterator it = _watching.begin(); it != _watching.end(); ++it ) { + (*it)->set_sensitive( sensitive ); + } + for ( std::vector::iterator it = _watchingNonTop.begin(); it != _watchingNonTop.end(); ++it ) { + (*it)->set_sensitive( sensitiveNonTop ); + } + for ( std::vector::iterator it = _watchingNonBottom.begin(); it != _watchingNonBottom.end(); ++it ) { + (*it)->set_sensitive( sensitiveNonBottom ); + } +} + +bool TagsPanel::_handleKeyEvent(GdkEventKey *event) +{ + + switch (get_group0_keyval(event)) { + case GDK_KEY_Return: + case GDK_KEY_KP_Enter: + case GDK_KEY_F2: { + Gtk::TreeModel::iterator iter = _tree.get_selection()->get_selected(); + if (iter && !_text_renderer->property_editable()) { + Gtk::TreeRow row = *iter; + SPObject * obj = row[_model->_colObject]; + if (obj && SP_IS_TAG(obj)) { + Gtk::TreeModel::Path *path = new Gtk::TreeModel::Path(iter); + // Edit the layer label + _text_renderer->property_editable() = true; + _tree.set_cursor(*path, *_name_column, true); + grab_focus(); + return true; + } + } + } + case GDK_KEY_Delete: { + std::vector todelete; + _tree.get_selection()->selected_foreach_iter(sigc::bind*>(sigc::mem_fun(*this, &TagsPanel::_checkForDeleted), &todelete)); + if (!todelete.empty()) { + for (std::vector::iterator iter = todelete.begin(); iter != todelete.end(); ++iter) { + SPObject * obj = *iter; + if (obj && obj->parent && obj->getRepr() && obj->parent->getRepr()) { + obj->parent->getRepr()->removeChild(obj->getRepr()); + } + } + DocumentUndo::done(_document, SP_VERB_DIALOG_TAGS, _("Remove from tags")); + } + return true; + } + break; + } + return false; +} + +bool TagsPanel::_handleButtonEvent(GdkEventButton* event) +{ + static unsigned doubleclick = 0; + + if ( (event->type == GDK_BUTTON_PRESS) && (event->button == 3) ) { + // TODO - fix to a better is-popup function + Gtk::TreeModel::Path path; + int x = static_cast(event->x); + int y = static_cast(event->y); + if ( _tree.get_path_at_pos( x, y, path ) ) { + _checkTreeSelection(); + _popupMenu.popup(event->button, event->time); + if (_tree.get_selection()->is_selected(path)) { + return true; + } + } + } + + if ( (event->type == GDK_BUTTON_PRESS) && (event->button == 1)) { + // Alt left click on the visible/lock columns - eat this event to keep row selection + Gtk::TreeModel::Path path; + Gtk::TreeViewColumn* col = 0; + int x = static_cast(event->x); + int y = static_cast(event->y); + int x2 = 0; + int y2 = 0; + if ( _tree.get_path_at_pos( x, y, path, col, x2, y2 ) ) { + if (col == _tree.get_column(COL_ADD-1)) { + down_at_add = true; + return true; + } else if ( !(event->state & (GDK_SHIFT_MASK | GDK_CONTROL_MASK)) & _tree.get_selection()->is_selected(path) ) { + _tree.get_selection()->set_select_function(sigc::mem_fun(*this, &TagsPanel::_noSelection)); + _defer_target = path; + } else { + down_at_add = false; + } + } else { + down_at_add = false; + } + } + + if ( event->type == GDK_BUTTON_RELEASE) { + _tree.get_selection()->set_select_function(sigc::mem_fun(*this, &TagsPanel::_rowSelectFunction)); + } + + // TODO - ImageToggler doesn't seem to handle Shift/Alt clicks - so we deal with them here. + if ( (event->type == GDK_BUTTON_RELEASE) && (event->button == 1)) { + + Gtk::TreeModel::Path path; + Gtk::TreeViewColumn* col = 0; + int x = static_cast(event->x); + int y = static_cast(event->y); + int x2 = 0; + int y2 = 0; + if ( _tree.get_path_at_pos( x, y, path, col, x2, y2 ) ) { + if (_defer_target) { + if (_defer_target == path && !(event->x == 0 && event->y == 0)) + { + _tree.set_cursor(path, *col, false); + } + _defer_target = Gtk::TreeModel::Path(); + } else { + Gtk::TreeModel::Children::iterator iter = _tree.get_model()->get_iter(path); + Gtk::TreeModel::Row row = *iter; + + SPObject* obj = row[_model->_colObject]; + + if (obj) { + if (col == _tree.get_column(COL_ADD - 1) && down_at_add) { + if (SP_IS_TAG(obj)) { + bool wasadded = false; + for (const GSList * iter = _desktop->selection->itemList(); iter != NULL; iter = iter->next) + { + SPObject *newobj = reinterpret_cast(iter->data); + bool addchild = true; + for ( SPObject *child = obj->children; child != NULL; child = child->next) { + if (SP_IS_TAG_USE(child) && SP_TAG_USE(child)->ref->getObject() == newobj) { + addchild = false; + } + } + if (addchild) { + Inkscape::XML::Node *clone = _document->getReprDoc()->createElement("inkscape:tagref"); + clone->setAttribute("xlink:href", g_strdup_printf("#%s", newobj->getRepr()->attribute("id")), false); + obj->appendChild(clone); + wasadded = true; + } + } + if (wasadded) { + DocumentUndo::done(_document, SP_VERB_DIALOG_TAGS, _("Add selection to tag")); + } + } else { + std::vector todelete; + _tree.get_selection()->selected_foreach_iter(sigc::bind*>(sigc::mem_fun(*this, &TagsPanel::_checkForDeleted), &todelete)); + if (!todelete.empty()) { + for (std::vector::iterator iter = todelete.begin(); iter != todelete.end(); ++iter) { + SPObject * tobj = *iter; + if (tobj && tobj->parent && tobj->getRepr() && tobj->parent->getRepr()) { + tobj->parent->getRepr()->removeChild(tobj->getRepr()); + } + } + } else if (obj && obj->parent && obj->getRepr() && obj->parent->getRepr()) { + obj->parent->getRepr()->removeChild(obj->getRepr()); + } + DocumentUndo::done(_document, SP_VERB_DIALOG_TAGS, _("Remove from tags")); + } + } + } + } + } + } + + + if ( (event->type == GDK_2BUTTON_PRESS) && (event->button == 1) ) { + doubleclick = 1; + } + + if ( event->type == GDK_BUTTON_RELEASE && doubleclick) { + doubleclick = 0; + Gtk::TreeModel::Path path; + Gtk::TreeViewColumn* col = 0; + int x = static_cast(event->x); + int y = static_cast(event->y); + int x2 = 0; + int y2 = 0; + if ( _tree.get_path_at_pos( x, y, path, col, x2, y2 ) && col == _name_column) { + Gtk::TreeModel::Children::iterator iter = _tree.get_model()->get_iter(path); + Gtk::TreeModel::Row row = *iter; + + SPObject* obj = row[_model->_colObject]; + if (obj && (SP_IS_TAG(obj) || (SP_IS_TAG_USE(obj) && SP_TAG_USE(obj)->ref->getObject()))) { + // Double click on the Layer name, enable editing + _text_renderer->property_editable() = true; + _tree.set_cursor (path, *_name_column, true); + grab_focus(); + } + } + } + + return false; +} + +void TagsPanel::_storeDragSource(const Gtk::TreeModel::iterator& iter) +{ + Gtk::TreeModel::Row row = *iter; + SPObject* obj = row[_model->_colObject]; + SPTag* item = ( obj && SP_IS_TAG(obj) ) ? SP_TAG(obj) : 0; + if (item) + { + _dnd_source.push_back(item); + } +} + +/* + * Drap and drop within the tree + * Save the drag source and drop target SPObjects and if its a drag between layers or into (sublayer) a layer + */ +bool TagsPanel::_handleDragDrop(const Glib::RefPtr& context, int x, int y, guint time) +{ + int cell_x = 0, cell_y = 0; + Gtk::TreeModel::Path target_path; + Gtk::TreeView::Column *target_column; + + _dnd_into = true; + _dnd_target = _document->getDefs(); + _dnd_source.clear(); + _tree.get_selection()->selected_foreach_iter(sigc::mem_fun(*this, &TagsPanel::_storeDragSource)); + + if (_dnd_source.empty()) { + return true; + } + + if (_tree.get_path_at_pos (x, y, target_path, target_column, cell_x, cell_y)) { + // Are we before, inside or after the drop layer + Gdk::Rectangle rect; + _tree.get_background_area (target_path, *target_column, rect); + int cell_height = rect.get_height(); + _dnd_into = (cell_y > (int)(cell_height * 1/3) && cell_y <= (int)(cell_height * 2/3)); + if (cell_y > (int)(cell_height * 2/3)) { + Gtk::TreeModel::Path next_path = target_path; + next_path.next(); + if (_store->iter_is_valid(_store->get_iter(next_path))) { + target_path = next_path; + } else { + // Dragging to the "end" + Gtk::TreeModel::Path up_path = target_path; + up_path.up(); + if (_store->iter_is_valid(_store->get_iter(up_path))) { + // Drop into parent + target_path = up_path; + _dnd_into = true; + } else { + // Drop into the top level + _dnd_target = _document->getDefs(); + _dnd_into = true; + } + } + } + Gtk::TreeModel::iterator iter = _store->get_iter(target_path); + if (_store->iter_is_valid(iter)) { + Gtk::TreeModel::Row row = *iter; + SPObject *obj = row[_model->_colObject]; + SPObject *pobj = row[_model->_colParentObject]; + if (obj) { + if (SP_IS_TAG(obj)) { + _dnd_target = SP_TAG(obj); + } else if (SP_IS_TAG(obj->parent)) { + _dnd_target = SP_TAG(obj->parent); + _dnd_into = true; + } + } else if (pobj && SP_IS_TAG(pobj)) { + _dnd_target = SP_TAG(pobj); + _dnd_into = true; + } else { + return true; + } + } + } + + _takeAction(DRAGNDROP); + + return false; +} + +/* + * Move a layer in response to a drag & drop action + */ +void TagsPanel::_doTreeMove( ) +{ + if (_dnd_target) { + for (std::vector::iterator iter = _dnd_source.begin(); iter != _dnd_source.end(); ++iter) + { + SPTag *src = *iter; + if (src != _dnd_target) { + src->moveTo(_dnd_target, _dnd_into); + } + } + _desktop->selection->clear(); + while (!_dnd_source.empty()) + { + SPTag *src = _dnd_source.back(); + _select_tag(src); + _dnd_source.pop_back(); + } + DocumentUndo::done( _desktop->doc() , SP_VERB_DIALOG_TAGS, + _("Moved tags")); + } +} + + +void TagsPanel::_handleEdited(const Glib::ustring& path, const Glib::ustring& new_text) +{ + Gtk::TreeModel::iterator iter = _tree.get_model()->get_iter(path); + Gtk::TreeModel::Row row = *iter; + + _renameObject(row, new_text); + _text_renderer->property_editable() = false; +} + +void TagsPanel::_handleEditingCancelled() +{ + _text_renderer->property_editable() = false; +} + +void TagsPanel::_renameObject(Gtk::TreeModel::Row row, const Glib::ustring& name) +{ + if ( row && _desktop) { + SPObject* obj = row[_model->_colObject]; + if ( obj ) { + if (SP_IS_TAG(obj)) { + gchar const* oldLabel = obj->label(); + if ( !name.empty() && (!oldLabel || name != oldLabel) ) { + obj->setLabel(name.c_str()); + DocumentUndo::done( _desktop->doc() , SP_VERB_NONE, + _("Rename object")); + } + } else if (SP_IS_TAG_USE(obj) && (obj = SP_TAG_USE(obj)->ref->getObject())) { + gchar const* oldLabel = obj->label(); + if ( !name.empty() && (!oldLabel || name != oldLabel) ) { + obj->setLabel(name.c_str()); + DocumentUndo::done( _desktop->doc() , SP_VERB_NONE, + _("Rename object")); + } + } + } + } +} + +bool TagsPanel::_noSelection( Glib::RefPtr const & /*model*/, Gtk::TreeModel::Path const & /*path*/, bool currentlySelected ) +{ + return false; +} + +bool TagsPanel::_rowSelectFunction( Glib::RefPtr const & /*model*/, Gtk::TreeModel::Path const & /*path*/, bool currentlySelected ) +{ + bool val = true; + if ( !currentlySelected && _toggleEvent ) + { + GdkEvent* event = gtk_get_current_event(); + if ( event ) { + // (keep these checks separate, so we know when to call gdk_event_free() + if ( event->type == GDK_BUTTON_PRESS ) { + GdkEventButton const* target = reinterpret_cast(_toggleEvent); + GdkEventButton const* evtb = reinterpret_cast(event); + + if ( (evtb->window == target->window) + && (evtb->send_event == target->send_event) + && (evtb->time == target->time) + && (evtb->state == target->state) + ) + { + // Ooooh! It's a magic one + val = false; + } + } + gdk_event_free(event); + } + } + return val; +} + +void TagsPanel::_setExpanded(const Gtk::TreeModel::iterator& iter, const Gtk::TreeModel::Path& /*path*/, bool isexpanded) +{ + Gtk::TreeModel::Row row = *iter; + + SPObject* obj = row[_model->_colParentObject]; + if (obj && SP_IS_TAG(obj)) + { + SP_TAG(obj)->setExpanded(isexpanded); + obj->updateRepr(SP_OBJECT_WRITE_NO_CHILDREN | SP_OBJECT_WRITE_EXT); + } +} + +/** + * Constructor + */ +TagsPanel::TagsPanel() : + UI::Widget::Panel("", "/dialogs/tags", SP_VERB_DIALOG_TAGS), + _rootWatcher(0), + deskTrack(), + _desktop(0), + _document(0), + _model(0), + _pending(0), + _toggleEvent(0), + _defer_target(), + desktopChangeConn() +{ + //Inkscape::Preferences *prefs = Inkscape::Preferences::get(); + + ModelColumns *zoop = new ModelColumns(); + _model = zoop; + + _store = Gtk::TreeStore::create( *zoop ); + + _tree.set_model( _store ); + _tree.set_headers_visible(false); + _tree.set_reorderable(true); + _tree.enable_model_drag_dest (Gdk::ACTION_MOVE); + + Inkscape::UI::Widget::AddToIcon * addRenderer = manage( new Inkscape::UI::Widget::AddToIcon()); + int addColNum = _tree.append_column("type", *addRenderer) - 1; + Gtk::TreeViewColumn *col = _tree.get_column(addColNum); + if ( col ) { + col->add_attribute( addRenderer->property_active(), _model->_colAddRemove ); + col->add_attribute( addRenderer->property_visible(), _model->_colAllowAddRemove ); + } + + _text_renderer = manage(new Gtk::CellRendererText()); + int nameColNum = _tree.append_column("Name", *_text_renderer) - 1; + _name_column = _tree.get_column(nameColNum); + _name_column->add_attribute(_text_renderer->property_text(), _model->_colLabel); + + _tree.set_expander_column( *_tree.get_column(nameColNum) ); + + _tree.get_selection()->set_mode(Gtk::SELECTION_MULTIPLE); + _selectedConnection = _tree.get_selection()->signal_changed().connect( sigc::mem_fun(*this, &TagsPanel::_pushTreeSelectionToCurrent) ); + _tree.get_selection()->set_select_function( sigc::mem_fun(*this, &TagsPanel::_rowSelectFunction) ); + + _tree.signal_drag_drop().connect( sigc::mem_fun(*this, &TagsPanel::_handleDragDrop), false); + _collapsedConnection = _tree.signal_row_collapsed().connect( sigc::bind(sigc::mem_fun(*this, &TagsPanel::_setExpanded), false)); + _expandedConnection = _tree.signal_row_expanded().connect( sigc::bind(sigc::mem_fun(*this, &TagsPanel::_setExpanded), true)); + + _text_renderer->signal_edited().connect( sigc::mem_fun(*this, &TagsPanel::_handleEdited) ); + _text_renderer->signal_editing_canceled().connect( sigc::mem_fun(*this, &TagsPanel::_handleEditingCancelled) ); + + _tree.signal_button_press_event().connect( sigc::mem_fun(*this, &TagsPanel::_handleButtonEvent), false ); + _tree.signal_button_release_event().connect( sigc::mem_fun(*this, &TagsPanel::_handleButtonEvent), false ); + _tree.signal_key_press_event().connect( sigc::mem_fun(*this, &TagsPanel::_handleKeyEvent), false ); + + _scroller.add( _tree ); + _scroller.set_policy( Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC ); + _scroller.set_shadow_type(Gtk::SHADOW_IN); + Gtk::Requisition sreq; +#if WITH_GTKMM_3_0 + Gtk::Requisition sreq_natural; + _scroller.get_preferred_size(sreq_natural, sreq); +#else + sreq = _scroller.size_request(); +#endif + int minHeight = 70; + if (sreq.height < minHeight) { + // Set a min height to see the layers when used with Ubuntu liboverlay-scrollbar + _scroller.set_size_request(sreq.width, minHeight); + } + + _layersPage.pack_start( _scroller, Gtk::PACK_EXPAND_WIDGET ); + + _layersPage.pack_end(_buttonsRow, Gtk::PACK_SHRINK); + + _getContents()->pack_start(_layersPage, Gtk::PACK_EXPAND_WIDGET); + + SPDesktop* targetDesktop = getDesktop(); + + Gtk::Button* btn = manage( new Gtk::Button() ); + _styleButton( *btn, targetDesktop, SP_VERB_TAG_NEW, GTK_STOCK_ADD, _("Add a new tag") ); + btn->signal_clicked().connect( sigc::bind( sigc::mem_fun(*this, &TagsPanel::_takeAction), (int)BUTTON_NEW) ); + _buttonsSecondary.pack_start(*btn, Gtk::PACK_SHRINK); + +// btn = manage( new Gtk::Button("Dup") ); +// btn->signal_clicked().connect( sigc::bind( sigc::mem_fun(*this, &LayersPanel::_takeAction), (int)BUTTON_DUPLICATE) ); +// _buttonsRow.add( *btn ); + + btn = manage( new Gtk::Button() ); + _styleButton( *btn, targetDesktop, SP_VERB_LAYER_DELETE, GTK_STOCK_REMOVE, _("Remove Item/Tag") ); + btn->signal_clicked().connect( sigc::bind( sigc::mem_fun(*this, &TagsPanel::_takeAction), (int)BUTTON_DELETE) ); + _watching.push_back( btn ); + _buttonsSecondary.pack_start(*btn, Gtk::PACK_SHRINK); + + _buttonsRow.pack_start(_buttonsSecondary, Gtk::PACK_EXPAND_WIDGET); + _buttonsRow.pack_end(_buttonsPrimary, Gtk::PACK_EXPAND_WIDGET); + + // ------------------------------------------------------- + { + _watching.push_back( &_addPopupItem( targetDesktop, SP_VERB_TAG_NEW, 0, "New", (int)BUTTON_NEW ) ); + + _popupMenu.show_all_children(); + } + // ------------------------------------------------------- + + + + for ( std::vector::iterator it = _watching.begin(); it != _watching.end(); ++it ) { + (*it)->set_sensitive( false ); + } + for ( std::vector::iterator it = _watchingNonTop.begin(); it != _watchingNonTop.end(); ++it ) { + (*it)->set_sensitive( false ); + } + for ( std::vector::iterator it = _watchingNonBottom.begin(); it != _watchingNonBottom.end(); ++it ) { + (*it)->set_sensitive( false ); + } + + setDesktop( targetDesktop ); + + show_all_children(); + + // restorePanelPrefs(); + + // Connect this up last + desktopChangeConn = deskTrack.connectDesktopChanged( sigc::mem_fun(*this, &TagsPanel::setDesktop) ); + deskTrack.connect(GTK_WIDGET(gobj())); +} + +TagsPanel::~TagsPanel() +{ + + setDesktop(NULL); + + if ( _model ) + { + delete _model; + _model = 0; + } + + if (_pending) { + delete _pending; + _pending = 0; + } + + if ( _toggleEvent ) + { + gdk_event_free( _toggleEvent ); + _toggleEvent = 0; + } + + desktopChangeConn.disconnect(); + deskTrack.disconnect(); +} + +void TagsPanel::setDocument(SPDesktop* /*desktop*/, SPDocument* document) +{ + while (!_objectWatchers.empty()) + { + TagsPanel::ObjectWatcher *w = _objectWatchers.back(); + w->_repr->removeObserver(*w); + _objectWatchers.pop_back(); + delete w; + } + + if (_rootWatcher) + { + _rootWatcher->_repr->removeObserver(*_rootWatcher); + delete _rootWatcher; + _rootWatcher = NULL; + } + + _document = document; + + if (document && document->getDefs() && document->getDefs()->getRepr()) + { + _rootWatcher = new TagsPanel::ObjectWatcher(this, document->getDefs()); + document->getDefs()->getRepr()->addObserver(*_rootWatcher); + _objectsChanged(document->getDefs()); + } +} + +void TagsPanel::setDesktop( SPDesktop* desktop ) +{ + Panel::setDesktop(desktop); + + if ( desktop != _desktop ) { + _documentChangedConnection.disconnect(); + _selectionChangedConnection.disconnect(); + if ( _desktop ) { + _desktop = 0; + } + + _desktop = Panel::getDesktop(); + if ( _desktop ) { + //setLabel( _desktop->doc()->name ); + _documentChangedConnection = _desktop->connectDocumentReplaced( sigc::mem_fun(*this, &TagsPanel::setDocument)); + _selectionChangedConnection = _desktop->selection->connectChanged( sigc::mem_fun(*this, &TagsPanel::_objectsSelected)); + + setDocument(_desktop, _desktop->doc()); + } + } +/* + GSList const *layers = _desktop->doc()->getResourceList( "layer" ); + g_message( "layers list starts at %p", layers ); + for ( GSList const *iter=layers ; iter ; iter = iter->next ) { + SPObject *layer=static_cast(iter->data); + g_message(" {%s} [%s]", layer->id, layer->label() ); + } +*/ + deskTrack.setBase(desktop); +} + + + + + +} //namespace Dialogs +} //namespace UI +} //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 : diff --git a/src/ui/dialog/tags.h b/src/ui/dialog/tags.h new file mode 100644 index 000000000..d35dfba01 --- /dev/null +++ b/src/ui/dialog/tags.h @@ -0,0 +1,181 @@ +/* + * A simple dialog for tags UI. + * + * Authors: + * Theodore Janeczko + * + * Copyright (C) Theodore Janeczko 2012 + * + * Released under GNU GPL, read the file 'COPYING' for more information + */ + +#ifndef SEEN_TAGS_PANEL_H +#define SEEN_TAGS_PANEL_H + +#include +#include +#include +#include +#include +#include "ui/widget/spinbutton.h" +#include "ui/widget/panel.h" +#include "ui/widget/object-composite-settings.h" +#include "desktop-tracker.h" +#include "ui/widget/style-subject.h" +#include "selection.h" +#include "ui/widget/filter-effect-chooser.h" + +class SPObject; +class SPTag; +struct SPColorSelector; + +namespace Inkscape { + +namespace UI { +namespace Dialog { + + +/** + * A panel that displays layers. + */ +class TagsPanel : public UI::Widget::Panel +{ +public: + TagsPanel(); + virtual ~TagsPanel(); + + //virtual void setOrientation( Gtk::AnchorType how ); + + static TagsPanel& getInstance(); + + void setDesktop( SPDesktop* desktop ); + void setDocument( SPDesktop* desktop, SPDocument* document); + +protected: + //virtual void _handleAction( int setId, int itemId ); + friend void sp_highlight_picker_color_mod(SPColorSelector *csel, GObject *cp); +private: + class ModelColumns; + class InternalUIBounce; + class ObjectWatcher; + + TagsPanel(TagsPanel const &); // no copy + TagsPanel &operator=(TagsPanel const &); // no assign + + void _styleButton( Gtk::Button& btn, SPDesktop *desktop, unsigned int code, char const* iconName, char const* tooltip ); + void _fireAction( unsigned int code ); + Gtk::MenuItem& _addPopupItem( SPDesktop *desktop, unsigned int code, char const* iconName, char const* fallback, int id ); + + bool _handleButtonEvent(GdkEventButton *event); + bool _handleKeyEvent(GdkEventKey *event); + + void _storeDragSource(const Gtk::TreeModel::iterator& iter); + bool _handleDragDrop(const Glib::RefPtr& context, int x, int y, guint time); + void _handleEdited(const Glib::ustring& path, const Glib::ustring& new_text); + void _handleEditingCancelled(); + + void _doTreeMove(); + void _renameObject(Gtk::TreeModel::Row row, const Glib::ustring& name); + + void _pushTreeSelectionToCurrent(); + void _selected_row_callback( const Gtk::TreeModel::iterator& iter ); + void _select_tag( SPTag * tag ); + + void _checkTreeSelection(); + + void _takeAction( int val ); + bool _executeAction(); + + void _setExpanded( const Gtk::TreeModel::iterator& iter, const Gtk::TreeModel::Path& path, bool isexpanded ); + + bool _noSelection( Glib::RefPtr const & model, Gtk::TreeModel::Path const & path, bool b ); + bool _rowSelectFunction( Glib::RefPtr const & model, Gtk::TreeModel::Path const & path, bool b ); + + void _updateObject(SPObject *obj); + bool _checkForUpdated(const Gtk::TreePath &path, const Gtk::TreeIter& iter, SPObject* obj); + + void _objectsSelected(Selection *sel); + bool _checkForSelected(const Gtk::TreePath& path, const Gtk::TreeIter& iter, SPObject* layer); + + void _objectsChanged(SPObject *root); + void _addObject( SPDocument* doc, SPObject* obj, Gtk::TreeModel::Row* parentRow ); + + void _checkForDeleted(const Gtk::TreeIter& iter, std::vector* todelete); + +// std::vector groupConnections; + TagsPanel::ObjectWatcher* _rootWatcher; + std::vector _objectWatchers; + + // Hooked to the layer manager: + sigc::connection _documentChangedConnection; + sigc::connection _selectionChangedConnection; + + sigc::connection _changedConnection; + sigc::connection _addedConnection; + sigc::connection _removedConnection; + + // Internal + sigc::connection _selectedConnection; + sigc::connection _expandedConnection; + sigc::connection _collapsedConnection; + + DesktopTracker deskTrack; + SPDesktop* _desktop; + SPDocument* _document; + ModelColumns* _model; + InternalUIBounce* _pending; + gboolean _dnd_into; + std::vector _dnd_source; + SPObject* _dnd_target; + + GdkEvent* _toggleEvent; + bool down_at_add; + + Gtk::TreeModel::Path _defer_target; + + Glib::RefPtr _store; + std::vector _watching; + std::vector _watchingNonTop; + std::vector _watchingNonBottom; + + Gtk::TreeView _tree; + Gtk::CellRendererText *_text_renderer; + Gtk::TreeView::Column *_name_column; +#if WITH_GTKMM_3_0 + Gtk::Box _buttonsRow; + Gtk::Box _buttonsPrimary; + Gtk::Box _buttonsSecondary; +#else + Gtk::HBox _buttonsRow; + Gtk::HBox _buttonsPrimary; + Gtk::HBox _buttonsSecondary; +#endif + Gtk::ScrolledWindow _scroller; + Gtk::Menu _popupMenu; + Inkscape::UI::Widget::SpinButton _spinBtn; + Gtk::VBox _layersPage; + + sigc::connection desktopChangeConn; + +}; + + + +} //namespace Dialogs +} //namespace UI +} //namespace Inkscape + + + +#endif // SEEN_OBJECTS_PANEL_H + +/* + 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 : diff --git a/src/ui/widget/clipmaskicon.cpp b/src/ui/widget/clipmaskicon.cpp new file mode 100644 index 000000000..de7638bfe --- /dev/null +++ b/src/ui/widget/clipmaskicon.cpp @@ -0,0 +1,177 @@ +/* + * Authors: + * Theodore Janeczko + * + * Copyright (C) Theodore Janeczko 2012 + * + * Released under GNU GPL, read the file 'COPYING' for more information + */ + + +#include "ui/widget/clipmaskicon.h" + +#include + +#include "widgets/icon.h" +#include "widgets/toolbox.h" +#include "ui/icon-names.h" +#include "layertypeicon.h" + +namespace Inkscape { +namespace UI { +namespace Widget { + +ClipMaskIcon::ClipMaskIcon() : + Glib::ObjectBase(typeid(ClipMaskIcon)), + Gtk::CellRendererPixbuf(), + _pixClipName(INKSCAPE_ICON("path-intersection")), + _pixInverseName(INKSCAPE_ICON("path-difference")), + _pixMaskName(INKSCAPE_ICON("mask-intersection")), + _property_active(*this, "active", 0), + _property_pixbuf_clip(*this, "pixbuf_on", Glib::RefPtr(0)), + _property_pixbuf_inverse(*this, "pixbuf_on", Glib::RefPtr(0)), + _property_pixbuf_mask(*this, "pixbuf_off", Glib::RefPtr(0)) +{ + + property_mode() = Gtk::CELL_RENDERER_MODE_ACTIVATABLE; + phys = sp_icon_get_phys_size((int)Inkscape::ICON_SIZE_DECORATION); + Glib::RefPtr icon_theme = Gtk::IconTheme::get_default(); + + if (!icon_theme->has_icon(_pixClipName)) { + Inkscape::queueIconPrerender( INKSCAPE_ICON(_pixClipName.data()), Inkscape::ICON_SIZE_DECORATION ); + } + if (!icon_theme->has_icon(_pixInverseName)) { + Inkscape::queueIconPrerender( INKSCAPE_ICON(_pixInverseName.data()), Inkscape::ICON_SIZE_DECORATION ); + } + if (!icon_theme->has_icon(_pixMaskName)) { + Inkscape::queueIconPrerender( INKSCAPE_ICON(_pixMaskName.data()), Inkscape::ICON_SIZE_DECORATION ); + } + + if (icon_theme->has_icon(_pixClipName)) { + _property_pixbuf_clip = icon_theme->load_icon(_pixClipName, phys, (Gtk::IconLookupFlags)0); + } + if (icon_theme->has_icon(_pixInverseName)) { + _property_pixbuf_inverse = icon_theme->load_icon(_pixInverseName, phys, (Gtk::IconLookupFlags)0); + } + if (icon_theme->has_icon(_pixMaskName)) { + _property_pixbuf_mask = icon_theme->load_icon(_pixMaskName, phys, (Gtk::IconLookupFlags)0); + } + + property_pixbuf() = Glib::RefPtr(0); +} + + +#if WITH_GTKMM_3_0 +void ClipMaskIcon::get_preferred_height_vfunc(Gtk::Widget& widget, + int& min_h, + int& nat_h) const +{ + Gtk::CellRendererPixbuf::get_preferred_height_vfunc(widget, min_h, nat_h); + + if (min_h) { + min_h += (min_h) >> 1; + } + + if (nat_h) { + nat_h += (nat_h) >> 1; + } +} + +void ClipMaskIcon::get_preferred_width_vfunc(Gtk::Widget& widget, + int& min_w, + int& nat_w) const +{ + Gtk::CellRendererPixbuf::get_preferred_width_vfunc(widget, min_w, nat_w); + + if (min_w) { + min_w += (min_w) >> 1; + } + + if (nat_w) { + nat_w += (nat_w) >> 1; + } +} +#else +void ClipMaskIcon::get_size_vfunc(Gtk::Widget& widget, + const Gdk::Rectangle* cell_area, + int* x_offset, + int* y_offset, + int* width, + int* height ) const +{ + Gtk::CellRendererPixbuf::get_size_vfunc( widget, cell_area, x_offset, y_offset, width, height ); + + if ( width ) { + *width = phys;//+= (*width) >> 1; + } + if ( height ) { + *height =phys;//+= (*height) >> 1; + } +} +#endif + +#if WITH_GTKMM_3_0 +void ClipMaskIcon::render_vfunc( const Cairo::RefPtr& cr, + Gtk::Widget& widget, + const Gdk::Rectangle& background_area, + const Gdk::Rectangle& cell_area, + Gtk::CellRendererState flags ) +#else +void ClipMaskIcon::render_vfunc( const Glib::RefPtr& window, + Gtk::Widget& widget, + const Gdk::Rectangle& background_area, + const Gdk::Rectangle& cell_area, + const Gdk::Rectangle& expose_area, + Gtk::CellRendererState flags ) +#endif +{ + switch (_property_active.get_value()) + { + case 1: + property_pixbuf() = _property_pixbuf_clip; + break; + case 2: + property_pixbuf() = _property_pixbuf_mask; + break; + case 3: + property_pixbuf() = _property_pixbuf_inverse; + break; + default: + property_pixbuf() = Glib::RefPtr(0); + break; + } +#if WITH_GTKMM_3_0 + Gtk::CellRendererPixbuf::render_vfunc( cr, widget, background_area, cell_area, flags ); +#else + Gtk::CellRendererPixbuf::render_vfunc( window, widget, background_area, cell_area, expose_area, flags ); +#endif +} + +bool +ClipMaskIcon::activate_vfunc(GdkEvent* event, + Gtk::Widget& /*widget*/, + const Glib::ustring& path, + const Gdk::Rectangle& /*background_area*/, + const Gdk::Rectangle& /*cell_area*/, + Gtk::CellRendererState /*flags*/) +{ + return false; +} + + +} // namespace Widget +} // namespace UI +} // 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 : + + diff --git a/src/ui/widget/clipmaskicon.h b/src/ui/widget/clipmaskicon.h new file mode 100644 index 000000000..f1c1e7628 --- /dev/null +++ b/src/ui/widget/clipmaskicon.h @@ -0,0 +1,102 @@ +#ifndef __UI_DIALOG_CLIPMASKICON_H__ +#define __UI_DIALOG_CLIPMASKICON_H__ +/* + * Authors: + * Theodore Janeczko + * + * Copyright (C) Theodore Janeczko 2012 + * + * Released under GNU GPL, read the file 'COPYING' for more information + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include + +namespace Inkscape { +namespace UI { +namespace Widget { + +class ClipMaskIcon : public Gtk::CellRendererPixbuf { +public: + ClipMaskIcon(); + virtual ~ClipMaskIcon() {}; + + Glib::PropertyProxy property_active() { return _property_active.get_proxy(); } + Glib::PropertyProxy< Glib::RefPtr > property_pixbuf_on(); + Glib::PropertyProxy< Glib::RefPtr > property_pixbuf_off(); + +protected: + +#if WITH_GTKMM_3_0 + virtual void render_vfunc( const Cairo::RefPtr& cr, + Gtk::Widget& widget, + const Gdk::Rectangle& background_area, + const Gdk::Rectangle& cell_area, + Gtk::CellRendererState flags ); + + virtual void get_preferred_width_vfunc(Gtk::Widget& widget, + int& min_w, + int& nat_w) const; + + virtual void get_preferred_height_vfunc(Gtk::Widget& widget, + int& min_h, + int& nat_h) const; +#else + virtual void render_vfunc( const Glib::RefPtr& window, + Gtk::Widget& widget, + const Gdk::Rectangle& background_area, + const Gdk::Rectangle& cell_area, + const Gdk::Rectangle& expose_area, + Gtk::CellRendererState flags ); + + virtual void get_size_vfunc( Gtk::Widget &widget, + Gdk::Rectangle const *cell_area, + int *x_offset, int *y_offset, int *width, int *height ) const; +#endif + + virtual bool activate_vfunc(GdkEvent *event, + Gtk::Widget &widget, + const Glib::ustring &path, + const Gdk::Rectangle &background_area, + const Gdk::Rectangle &cell_area, + Gtk::CellRendererState flags); + + +private: + int phys; + + Glib::ustring _pixClipName; + Glib::ustring _pixInverseName; + Glib::ustring _pixMaskName; + + Glib::Property _property_active; + Glib::Property< Glib::RefPtr > _property_pixbuf_clip; + Glib::Property< Glib::RefPtr > _property_pixbuf_inverse; + Glib::Property< Glib::RefPtr > _property_pixbuf_mask; + +}; + + + +} // namespace Widget +} // namespace UI +} // namespace Inkscape + + +#endif /* __UI_DIALOG_IMAGETOGGLER_H__ */ + +/* + 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 : diff --git a/src/ui/widget/highlight-picker.cpp b/src/ui/widget/highlight-picker.cpp new file mode 100644 index 000000000..b799b5e29 --- /dev/null +++ b/src/ui/widget/highlight-picker.cpp @@ -0,0 +1,176 @@ +/* + * Authors: + * Theodore Janeczko + * + * Copyright (C) Theodore Janeczko 2012 + * + * Released under GNU GPL, read the file 'COPYING' for more information + */ + +#include +#include "display/cairo-utils.h" + +#include + +#include "highlight-picker.h" +#include "widgets/icon.h" +#include "widgets/toolbox.h" +#include "ui/icon-names.h" + +namespace Inkscape { +namespace UI { +namespace Widget { + +HighlightPicker::HighlightPicker() : + Glib::ObjectBase(typeid(HighlightPicker)), + Gtk::CellRendererPixbuf(), + _property_active(*this, "active", 0) +{ + + property_mode() = Gtk::CELL_RENDERER_MODE_ACTIVATABLE; +} + +HighlightPicker::~HighlightPicker() +{ +} + + +#if WITH_GTKMM_3_0 +void HighlightPicker::get_preferred_height_vfunc(Gtk::Widget& widget, + int& min_h, + int& nat_h) const +{ + Gtk::CellRendererPixbuf::get_preferred_height_vfunc(widget, min_h, nat_h); + + if (min_h) { + min_h += (min_h) >> 1; + } + + if (nat_h) { + nat_h += (nat_h) >> 1; + } +} + +void HighlightPicker::get_preferred_width_vfunc(Gtk::Widget& widget, + int& min_w, + int& nat_w) const +{ + Gtk::CellRendererPixbuf::get_preferred_width_vfunc(widget, min_w, nat_w); + + if (min_w) { + min_w += (min_w) >> 1; + } + + if (nat_w) { + nat_w += (nat_w) >> 1; + } +} +#else +void HighlightPicker::get_size_vfunc(Gtk::Widget& widget, + const Gdk::Rectangle* cell_area, + int* x_offset, + int* y_offset, + int* width, + int* height ) const +{ + Gtk::CellRendererPixbuf::get_size_vfunc( widget, cell_area, x_offset, y_offset, width, height ); + + if ( width ) { + *width = 10;//+= (*width) >> 1; + } + if ( height ) { + *height = 20; //cell_area ? cell_area->get_height() / 2 : 50; //+= (*height) >> 1; + } +} +#endif + +#if WITH_GTKMM_3_0 +void HighlightPicker::render_vfunc( const Cairo::RefPtr& cr, + Gtk::Widget& widget, + const Gdk::Rectangle& background_area, + const Gdk::Rectangle& cell_area, + Gtk::CellRendererState flags ) +#else +void HighlightPicker::render_vfunc( const Glib::RefPtr& window, + Gtk::Widget& widget, + const Gdk::Rectangle& background_area, + const Gdk::Rectangle& cell_area, + const Gdk::Rectangle& expose_area, + Gtk::CellRendererState flags ) +#endif +{ + GdkRectangle carea; + + cairo_surface_t *s = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, 10, 20); + cairo_t *ct = cairo_create(s); + + /* Transparent area */ + carea.x = 0; + carea.y = 0; + carea.width = 10; + carea.height = 20; + + cairo_pattern_t *checkers = ink_cairo_pattern_create_checkerboard(); + + cairo_rectangle(ct, carea.x, carea.y, carea.width, carea.height / 2); + cairo_set_source(ct, checkers); + cairo_fill_preserve(ct); + ink_cairo_set_source_rgba32(ct, _property_active.get_value()); + cairo_fill(ct); + + cairo_pattern_destroy(checkers); + + cairo_rectangle(ct, carea.x, carea.y + carea.height / 2, carea.width, carea.height / 2); + ink_cairo_set_source_rgba32(ct, _property_active.get_value() | 0x000000ff); + cairo_fill(ct); + + cairo_rectangle(ct, carea.x, carea.y, carea.width, carea.height); + ink_cairo_set_source_rgba32(ct, 0x333333ff); + cairo_set_line_width(ct, 2); + cairo_stroke(ct); + + cairo_destroy(ct); + cairo_surface_flush(s); + + GdkPixbuf* pixbuf = gdk_pixbuf_new_from_data( cairo_image_surface_get_data(s), + GDK_COLORSPACE_RGB, TRUE, 8, + 10, 20, cairo_image_surface_get_stride(s), + ink_cairo_pixbuf_cleanup, s); + convert_pixbuf_argb32_to_normal(pixbuf); + + property_pixbuf() = Glib::wrap(pixbuf); +#if WITH_GTKMM_3_0 + Gtk::CellRendererPixbuf::render_vfunc( cr, widget, background_area, cell_area, flags ); +#else + Gtk::CellRendererPixbuf::render_vfunc( window, widget, background_area, cell_area, expose_area, flags ); +#endif +} + +bool +HighlightPicker::activate_vfunc(GdkEvent* event, + Gtk::Widget& /*widget*/, + const Glib::ustring& path, + const Gdk::Rectangle& /*background_area*/, + const Gdk::Rectangle& /*cell_area*/, + Gtk::CellRendererState /*flags*/) +{ + return false; +} + + +} // namespace Widget +} // namespace UI +} // 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 : + + diff --git a/src/ui/widget/highlight-picker.h b/src/ui/widget/highlight-picker.h new file mode 100644 index 000000000..2d7dbc14e --- /dev/null +++ b/src/ui/widget/highlight-picker.h @@ -0,0 +1,90 @@ +#ifndef __UI_DIALOG_HIGHLIGHT_PICKER_H__ +#define __UI_DIALOG_HIGHLIGHT_PICKER_H__ +/* + * Authors: + * Theodore Janeczko + * + * Copyright (C) Theodore Janeczko 2012 + * + * Released under GNU GPL, read the file 'COPYING' for more information + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include + +namespace Inkscape { +namespace UI { +namespace Widget { + +class HighlightPicker : public Gtk::CellRendererPixbuf { +public: + HighlightPicker(); + virtual ~HighlightPicker(); + + Glib::PropertyProxy property_active() { return _property_active.get_proxy(); } + +protected: + +#if WITH_GTKMM_3_0 + virtual void render_vfunc( const Cairo::RefPtr& cr, + Gtk::Widget& widget, + const Gdk::Rectangle& background_area, + const Gdk::Rectangle& cell_area, + Gtk::CellRendererState flags ); + + virtual void get_preferred_width_vfunc(Gtk::Widget& widget, + int& min_w, + int& nat_w) const; + + virtual void get_preferred_height_vfunc(Gtk::Widget& widget, + int& min_h, + int& nat_h) const; +#else + virtual void render_vfunc( const Glib::RefPtr& window, + Gtk::Widget& widget, + const Gdk::Rectangle& background_area, + const Gdk::Rectangle& cell_area, + const Gdk::Rectangle& expose_area, + Gtk::CellRendererState flags ); + + virtual void get_size_vfunc( Gtk::Widget &widget, + Gdk::Rectangle const *cell_area, + int *x_offset, int *y_offset, int *width, int *height ) const; +#endif + + virtual bool activate_vfunc(GdkEvent *event, + Gtk::Widget &widget, + const Glib::ustring &path, + const Gdk::Rectangle &background_area, + const Gdk::Rectangle &cell_area, + Gtk::CellRendererState flags); + +private: + + Glib::Property _property_active; +}; + + + +} // namespace Widget +} // namespace UI +} // namespace Inkscape + + +#endif /* __UI_DIALOG_IMAGETOGGLER_H__ */ + +/* + 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 : diff --git a/src/ui/widget/insertordericon.cpp b/src/ui/widget/insertordericon.cpp new file mode 100644 index 000000000..9002a99c2 --- /dev/null +++ b/src/ui/widget/insertordericon.cpp @@ -0,0 +1,166 @@ +/* + * Authors: + * Theodore Janeczko + * + * Copyright (C) Theodore Janeczko 2012 + * + * Released under GNU GPL, read the file 'COPYING' for more information + */ + + +#include "ui/widget/insertordericon.h" + +#include + +#include "widgets/icon.h" +#include "widgets/toolbox.h" +#include "ui/icon-names.h" +#include "layertypeicon.h" + +namespace Inkscape { +namespace UI { +namespace Widget { + +InsertOrderIcon::InsertOrderIcon() : + Glib::ObjectBase(typeid(InsertOrderIcon)), + Gtk::CellRendererPixbuf(), + _pixTopName(INKSCAPE_ICON("insert-top")), + _pixBottomName(INKSCAPE_ICON("insert-bottom")), + _property_active(*this, "active", 0), + _property_pixbuf_top(*this, "pixbuf_on", Glib::RefPtr(0)), + _property_pixbuf_bottom(*this, "pixbuf_on", Glib::RefPtr(0)) +{ + + property_mode() = Gtk::CELL_RENDERER_MODE_ACTIVATABLE; + phys = sp_icon_get_phys_size((int)Inkscape::ICON_SIZE_DECORATION); + Glib::RefPtr icon_theme = Gtk::IconTheme::get_default(); + + if (!icon_theme->has_icon(_pixTopName)) { + Inkscape::queueIconPrerender( INKSCAPE_ICON(_pixTopName.data()), Inkscape::ICON_SIZE_DECORATION ); + } + if (!icon_theme->has_icon(_pixBottomName)) { + Inkscape::queueIconPrerender( INKSCAPE_ICON(_pixBottomName.data()), Inkscape::ICON_SIZE_DECORATION ); + } + + if (icon_theme->has_icon(_pixTopName)) { + _property_pixbuf_top = icon_theme->load_icon(_pixTopName, phys, (Gtk::IconLookupFlags)0); + } + if (icon_theme->has_icon(_pixBottomName)) { + _property_pixbuf_bottom = icon_theme->load_icon(_pixBottomName, phys, (Gtk::IconLookupFlags)0); + } + + property_pixbuf() = Glib::RefPtr(0); +} + + +#if WITH_GTKMM_3_0 +void InsertOrderIcon::get_preferred_height_vfunc(Gtk::Widget& widget, + int& min_h, + int& nat_h) const +{ + Gtk::CellRendererPixbuf::get_preferred_height_vfunc(widget, min_h, nat_h); + + if (min_h) { + min_h += (min_h) >> 1; + } + + if (nat_h) { + nat_h += (nat_h) >> 1; + } +} + +void InsertOrderIcon::get_preferred_width_vfunc(Gtk::Widget& widget, + int& min_w, + int& nat_w) const +{ + Gtk::CellRendererPixbuf::get_preferred_width_vfunc(widget, min_w, nat_w); + + if (min_w) { + min_w += (min_w) >> 1; + } + + if (nat_w) { + nat_w += (nat_w) >> 1; + } +} +#else +void InsertOrderIcon::get_size_vfunc(Gtk::Widget& widget, + const Gdk::Rectangle* cell_area, + int* x_offset, + int* y_offset, + int* width, + int* height ) const +{ + Gtk::CellRendererPixbuf::get_size_vfunc( widget, cell_area, x_offset, y_offset, width, height ); + + if ( width ) { + *width = phys;//+= (*width) >> 1; + } + if ( height ) { + *height =phys;//+= (*height) >> 1; + } +} +#endif + +#if WITH_GTKMM_3_0 +void InsertOrderIcon::render_vfunc( const Cairo::RefPtr& cr, + Gtk::Widget& widget, + const Gdk::Rectangle& background_area, + const Gdk::Rectangle& cell_area, + Gtk::CellRendererState flags ) +#else +void InsertOrderIcon::render_vfunc( const Glib::RefPtr& window, + Gtk::Widget& widget, + const Gdk::Rectangle& background_area, + const Gdk::Rectangle& cell_area, + const Gdk::Rectangle& expose_area, + Gtk::CellRendererState flags ) +#endif +{ + switch (_property_active.get_value()) + { + case 1: + property_pixbuf() = _property_pixbuf_top; + break; + case 2: + property_pixbuf() = _property_pixbuf_bottom; + break; + default: + property_pixbuf() = Glib::RefPtr(0); + break; + } +#if WITH_GTKMM_3_0 + Gtk::CellRendererPixbuf::render_vfunc( cr, widget, background_area, cell_area, flags ); +#else + Gtk::CellRendererPixbuf::render_vfunc( window, widget, background_area, cell_area, expose_area, flags ); +#endif +} + +bool +InsertOrderIcon::activate_vfunc(GdkEvent* event, + Gtk::Widget& /*widget*/, + const Glib::ustring& path, + const Gdk::Rectangle& /*background_area*/, + const Gdk::Rectangle& /*cell_area*/, + Gtk::CellRendererState /*flags*/) +{ + return false; +} + + +} // namespace Widget +} // namespace UI +} // 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 : + + diff --git a/src/ui/widget/insertordericon.h b/src/ui/widget/insertordericon.h new file mode 100644 index 000000000..4b4b51de2 --- /dev/null +++ b/src/ui/widget/insertordericon.h @@ -0,0 +1,100 @@ +#ifndef __UI_DIALOG_INSERTORDERICON_H__ +#define __UI_DIALOG_INSERTORDERICON_H__ +/* + * Authors: + * Theodore Janeczko + * + * Copyright (C) Theodore Janeczko 2012 + * + * Released under GNU GPL, read the file 'COPYING' for more information + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include + +namespace Inkscape { +namespace UI { +namespace Widget { + +class InsertOrderIcon : public Gtk::CellRendererPixbuf { +public: + InsertOrderIcon(); + virtual ~InsertOrderIcon() {}; + + Glib::PropertyProxy property_active() { return _property_active.get_proxy(); } + Glib::PropertyProxy< Glib::RefPtr > property_pixbuf_on(); + Glib::PropertyProxy< Glib::RefPtr > property_pixbuf_off(); + +protected: + +#if WITH_GTKMM_3_0 + virtual void render_vfunc( const Cairo::RefPtr& cr, + Gtk::Widget& widget, + const Gdk::Rectangle& background_area, + const Gdk::Rectangle& cell_area, + Gtk::CellRendererState flags ); + + virtual void get_preferred_width_vfunc(Gtk::Widget& widget, + int& min_w, + int& nat_w) const; + + virtual void get_preferred_height_vfunc(Gtk::Widget& widget, + int& min_h, + int& nat_h) const; +#else + virtual void render_vfunc( const Glib::RefPtr& window, + Gtk::Widget& widget, + const Gdk::Rectangle& background_area, + const Gdk::Rectangle& cell_area, + const Gdk::Rectangle& expose_area, + Gtk::CellRendererState flags ); + + virtual void get_size_vfunc( Gtk::Widget &widget, + Gdk::Rectangle const *cell_area, + int *x_offset, int *y_offset, int *width, int *height ) const; +#endif + + virtual bool activate_vfunc(GdkEvent *event, + Gtk::Widget &widget, + const Glib::ustring &path, + const Gdk::Rectangle &background_area, + const Gdk::Rectangle &cell_area, + Gtk::CellRendererState flags); + + +private: + int phys; + + Glib::ustring _pixTopName; + Glib::ustring _pixBottomName; + + Glib::Property _property_active; + Glib::Property< Glib::RefPtr > _property_pixbuf_top; + Glib::Property< Glib::RefPtr > _property_pixbuf_bottom; + +}; + + + +} // namespace Widget +} // namespace UI +} // namespace Inkscape + + +#endif /* __UI_DIALOG_IMAGETOGGLER_H__ */ + +/* + 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 : diff --git a/src/ui/widget/layertypeicon.cpp b/src/ui/widget/layertypeicon.cpp new file mode 100644 index 000000000..bfe855b28 --- /dev/null +++ b/src/ui/widget/layertypeicon.cpp @@ -0,0 +1,167 @@ +/* + * Authors: + * Theodore Janeczko + * + * Copyright (C) Theodore Janeczko 2012 + * + * Released under GNU GPL, read the file 'COPYING' for more information + */ + + +#include "ui/widget/layertypeicon.h" + +#include + +#include "widgets/icon.h" +#include "widgets/toolbox.h" +#include "ui/icon-names.h" +#include "layertypeicon.h" + +namespace Inkscape { +namespace UI { +namespace Widget { + +LayerTypeIcon::LayerTypeIcon() : + Glib::ObjectBase(typeid(LayerTypeIcon)), + Gtk::CellRendererPixbuf(), + _pixLayerName(INKSCAPE_ICON("dialog-layers")), + _pixGroupName(INKSCAPE_ICON("layer-duplicate")), + _pixPathName(INKSCAPE_ICON("layer-rename")), + _property_active(*this, "active", false), + _property_activatable(*this, "activatable", true), + _property_pixbuf_layer(*this, "pixbuf_on", Glib::RefPtr(0)), + _property_pixbuf_group(*this, "pixbuf_off", Glib::RefPtr(0)), + _property_pixbuf_path(*this, "pixbuf_off", Glib::RefPtr(0)) +{ + + property_mode() = Gtk::CELL_RENDERER_MODE_ACTIVATABLE; + int phys = sp_icon_get_phys_size((int)Inkscape::ICON_SIZE_DECORATION); + Glib::RefPtr icon_theme = Gtk::IconTheme::get_default(); + + if (!icon_theme->has_icon(_pixLayerName)) { + Inkscape::queueIconPrerender( INKSCAPE_ICON(_pixLayerName.data()), Inkscape::ICON_SIZE_DECORATION ); + } + if (!icon_theme->has_icon(_pixGroupName)) { + Inkscape::queueIconPrerender( INKSCAPE_ICON(_pixGroupName.data()), Inkscape::ICON_SIZE_DECORATION ); + } + if (!icon_theme->has_icon(_pixPathName)) { + Inkscape::queueIconPrerender( INKSCAPE_ICON(_pixPathName.data()), Inkscape::ICON_SIZE_DECORATION ); + } + + if (icon_theme->has_icon(_pixLayerName)) { + _property_pixbuf_layer = icon_theme->load_icon(_pixLayerName, phys, (Gtk::IconLookupFlags)0); + } + if (icon_theme->has_icon(_pixGroupName)) { + _property_pixbuf_group = icon_theme->load_icon(_pixGroupName, phys, (Gtk::IconLookupFlags)0); + } + if (icon_theme->has_icon(_pixPathName)) { + _property_pixbuf_path = icon_theme->load_icon(_pixPathName, phys, (Gtk::IconLookupFlags)0); + } + + property_pixbuf() = _property_pixbuf_path.get_value(); +} + + +#if WITH_GTKMM_3_0 +void LayerTypeIcon::get_preferred_height_vfunc(Gtk::Widget& widget, + int& min_h, + int& nat_h) const +{ + Gtk::CellRendererPixbuf::get_preferred_height_vfunc(widget, min_h, nat_h); + + if (min_h) { + min_h += (min_h) >> 1; + } + + if (nat_h) { + nat_h += (nat_h) >> 1; + } +} + +void LayerTypeIcon::get_preferred_width_vfunc(Gtk::Widget& widget, + int& min_w, + int& nat_w) const +{ + Gtk::CellRendererPixbuf::get_preferred_width_vfunc(widget, min_w, nat_w); + + if (min_w) { + min_w += (min_w) >> 1; + } + + if (nat_w) { + nat_w += (nat_w) >> 1; + } +} +#else +void LayerTypeIcon::get_size_vfunc(Gtk::Widget& widget, + const Gdk::Rectangle* cell_area, + int* x_offset, + int* y_offset, + int* width, + int* height ) const +{ + Gtk::CellRendererPixbuf::get_size_vfunc( widget, cell_area, x_offset, y_offset, width, height ); + + if ( width ) { + *width += (*width) >> 1; + } + if ( height ) { + *height += (*height) >> 1; + } +} +#endif + +#if WITH_GTKMM_3_0 +void LayerTypeIcon::render_vfunc( const Cairo::RefPtr& cr, + Gtk::Widget& widget, + const Gdk::Rectangle& background_area, + const Gdk::Rectangle& cell_area, + Gtk::CellRendererState flags ) +#else +void LayerTypeIcon::render_vfunc( const Glib::RefPtr& window, + Gtk::Widget& widget, + const Gdk::Rectangle& background_area, + const Gdk::Rectangle& cell_area, + const Gdk::Rectangle& expose_area, + Gtk::CellRendererState flags ) +#endif +{ + property_pixbuf() = _property_active.get_value() == 1 ? _property_pixbuf_group : (_property_active.get_value() == 2 ? _property_pixbuf_layer : _property_pixbuf_path); +#if WITH_GTKMM_3_0 + Gtk::CellRendererPixbuf::render_vfunc( cr, widget, background_area, cell_area, flags ); +#else + Gtk::CellRendererPixbuf::render_vfunc( window, widget, background_area, cell_area, expose_area, flags ); +#endif +} + +bool +LayerTypeIcon::activate_vfunc(GdkEvent* event, + Gtk::Widget& /*widget*/, + const Glib::ustring& path, + const Gdk::Rectangle& /*background_area*/, + const Gdk::Rectangle& /*cell_area*/, + Gtk::CellRendererState /*flags*/) +{ + _signal_pre_toggle.emit(event); + _signal_toggled.emit(path); + + return false; +} + + +} // namespace Widget +} // namespace UI +} // 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 : + + diff --git a/src/ui/widget/layertypeicon.h b/src/ui/widget/layertypeicon.h new file mode 100644 index 000000000..4ad3f16fb --- /dev/null +++ b/src/ui/widget/layertypeicon.h @@ -0,0 +1,108 @@ +#ifndef __UI_DIALOG_LAYERTYPEICON_H__ +#define __UI_DIALOG_LAYERTYPEICON_H__ +/* + * Authors: + * Theodore Janeczko + * + * Copyright (C) Theodore Janeczko 2012 + * + * Released under GNU GPL, read the file 'COPYING' for more information + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include + +namespace Inkscape { +namespace UI { +namespace Widget { + +class LayerTypeIcon : public Gtk::CellRendererPixbuf { +public: + LayerTypeIcon(); + virtual ~LayerTypeIcon() {}; + + sigc::signal signal_toggled() { return _signal_toggled;} + sigc::signal signal_pre_toggle() { return _signal_pre_toggle; } + + Glib::PropertyProxy property_active() { return _property_active.get_proxy(); } + Glib::PropertyProxy property_activatable() { return _property_activatable.get_proxy(); } + Glib::PropertyProxy< Glib::RefPtr > property_pixbuf_on(); + Glib::PropertyProxy< Glib::RefPtr > property_pixbuf_off(); + +protected: + +#if WITH_GTKMM_3_0 + virtual void render_vfunc( const Cairo::RefPtr& cr, + Gtk::Widget& widget, + const Gdk::Rectangle& background_area, + const Gdk::Rectangle& cell_area, + Gtk::CellRendererState flags ); + + virtual void get_preferred_width_vfunc(Gtk::Widget& widget, + int& min_w, + int& nat_w) const; + + virtual void get_preferred_height_vfunc(Gtk::Widget& widget, + int& min_h, + int& nat_h) const; +#else + virtual void render_vfunc( const Glib::RefPtr& window, + Gtk::Widget& widget, + const Gdk::Rectangle& background_area, + const Gdk::Rectangle& cell_area, + const Gdk::Rectangle& expose_area, + Gtk::CellRendererState flags ); + + virtual void get_size_vfunc( Gtk::Widget &widget, + Gdk::Rectangle const *cell_area, + int *x_offset, int *y_offset, int *width, int *height ) const; +#endif + + virtual bool activate_vfunc(GdkEvent *event, + Gtk::Widget &widget, + const Glib::ustring &path, + const Gdk::Rectangle &background_area, + const Gdk::Rectangle &cell_area, + Gtk::CellRendererState flags); + + +private: + Glib::ustring _pixLayerName; + Glib::ustring _pixGroupName; + Glib::ustring _pixPathName; + + Glib::Property _property_active; + Glib::Property _property_activatable; + Glib::Property< Glib::RefPtr > _property_pixbuf_layer; + Glib::Property< Glib::RefPtr > _property_pixbuf_group; + Glib::Property< Glib::RefPtr > _property_pixbuf_path; + + sigc::signal _signal_toggled; + sigc::signal _signal_pre_toggle; + +}; + + + +} // namespace Widget +} // namespace UI +} // namespace Inkscape + + +#endif /* __UI_DIALOG_IMAGETOGGLER_H__ */ + +/* + 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 From 9bfba5c24a89f0d2ae75fc78a0aa21743a29e978 Mon Sep 17 00:00:00 2001 From: "Liam P. White" Date: Sun, 2 Mar 2014 11:56:51 -0500 Subject: Experimental merge of Ponyscape features into trunk (will not compile) (bzr r13090.1.2) --- src/sp-item-group.cpp | 12 ++++++++++++ src/sp-item-group.h | 8 ++++++++ src/ui/dialog/objects.cpp | 12 +++++++++++- src/verbs.h | 2 ++ 4 files changed, 33 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/sp-item-group.cpp b/src/sp-item-group.cpp index 2cfe97db8..fbd9a6538 100644 --- a/src/sp-item-group.cpp +++ b/src/sp-item-group.cpp @@ -616,6 +616,18 @@ SPGroup::LayerMode SPGroup::layerDisplayMode(unsigned int dkey) const { } } +void SPGroup::setExpanded(bool isexpanded) { + if ( _expanded != isexpanded ){ + _expanded = isexpanded; + } +} + +void SPGroup::setInsertBottom(bool insertbottom) { + if ( _insertBottom != insertbottom) { + _insertBottom = insertbottom; + } +} + void SPGroup::setLayerDisplayMode(unsigned int dkey, SPGroup::LayerMode mode) { if ( layerDisplayMode(dkey) != mode ) { _display_modes[dkey] = mode; diff --git a/src/sp-item-group.h b/src/sp-item-group.h index 2004a72b8..68bbd083a 100644 --- a/src/sp-item-group.h +++ b/src/sp-item-group.h @@ -35,12 +35,20 @@ public: enum LayerMode { GROUP, LAYER, MASK_HELPER }; + bool _expanded; + bool _insertBottom; LayerMode _layer_mode; std::map _display_modes; LayerMode layerMode() const { return _layer_mode; } void setLayerMode(LayerMode mode); + bool expanded() const { return _expanded; } + void setExpanded(bool isexpanded); + + bool insertBottom() const { return _insertBottom; } + void setInsertBottom(bool insertbottom); + LayerMode effectiveLayerMode(unsigned int display_key) const { if ( _layer_mode == LAYER ) { return LAYER; diff --git a/src/ui/dialog/objects.cpp b/src/ui/dialog/objects.cpp index 31e73db29..5023a8813 100644 --- a/src/ui/dialog/objects.cpp +++ b/src/ui/dialog/objects.cpp @@ -57,6 +57,8 @@ //#define DUMP_LAYERS 1 +guint get_group0_keyval(GdkEventKey *event); + namespace Inkscape { namespace UI { namespace Dialog { @@ -414,7 +416,7 @@ bool ObjectsPanel::_checkForUpdated(const Gtk::TreeIter& iter, SPObject* obj) row[_model->_colLocked] = item ? !item->isSensitive() : false; row[_model->_colType] = group ? (group->layerMode() == SPGroup::LAYER ? 2 : 1) : 0; row[_model->_colHighlight] = item ? (item->isHighlightSet() ? item->highlight_color() : item->highlight_color() & 0xffffff00) : 0; - row[_model->_colClipMask] = item ? (item->clip_ref && item->clip_ref->getObject() ? (item->clip_ref->getObject()->inverse ? 3 : 1) : (item->mask_ref && item->mask_ref->getObject() ? 2 : 0)) : 0; + row[_model->_colClipMask] = item ? (item->clip_ref && item->clip_ref->getObject() ? 1 : (item->mask_ref && item->mask_ref->getObject() ? 2 : 0)) : 0; row[_model->_colInsertOrder] = group ? (group->insertBottom() ? 2 : 1) : 0; return true; @@ -2035,6 +2037,14 @@ void ObjectsPanel::setDesktop( SPDesktop* desktop ) } //namespace UI } //namespace Inkscape +guint get_group0_keyval(GdkEventKey *event) { + guint keyval = 0; + gdk_keymap_translate_keyboard_state(gdk_keymap_get_for_display( + gdk_display_get_default()), event->hardware_keycode, + (GdkModifierType) event->state, 0 /*event->key.group*/, &keyval, + NULL, NULL, NULL); + return keyval; +} /* Local Variables: diff --git a/src/verbs.h b/src/verbs.h index 0f764eb29..b8a0b1fd5 100644 --- a/src/verbs.h +++ b/src/verbs.h @@ -289,6 +289,8 @@ enum { SP_VERB_DIALOG_INPUT, SP_VERB_DIALOG_EXTENSIONEDITOR, SP_VERB_DIALOG_LAYERS, + SP_VERB_DIALOG_OBJECTS, + SP_VERB_DIALOG_TAGS, SP_VERB_DIALOG_LIVE_PATH_EFFECT, SP_VERB_DIALOG_FILTER_EFFECTS, SP_VERB_DIALOG_SVG_FONTS, -- cgit v1.2.3 From 05f60fa645caeda752fe6bffb33993f6485cadb6 Mon Sep 17 00:00:00 2001 From: "Liam P. White" Date: Sun, 2 Mar 2014 12:48:51 -0500 Subject: Experimental merge of Ponyscape to Inkscape trunk (does not compile) (bzr r13090.1.3) --- src/ui/widget/filter-effect-chooser.cpp | 2 ++ src/ui/widget/filter-effect-chooser.h | 4 +++- 2 files changed, 5 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/ui/widget/filter-effect-chooser.cpp b/src/ui/widget/filter-effect-chooser.cpp index 65706a9dc..3932bdfd4 100644 --- a/src/ui/widget/filter-effect-chooser.cpp +++ b/src/ui/widget/filter-effect-chooser.cpp @@ -23,6 +23,8 @@ namespace Widget { SimpleFilterModifier::SimpleFilterModifier(int flags) : _lb_blend(_("Blend mode:")), + _lb_blur(_("_Blur:")), + _lb_blur_unit(_("%")), _blend(BlendModeConverter, SP_ATTR_INVALID, false), _blur(_("Blur (%)"), 0, 0, 100, 1, 0.01, 1) { diff --git a/src/ui/widget/filter-effect-chooser.h b/src/ui/widget/filter-effect-chooser.h index 6f0c2f26e..a467adcb1 100644 --- a/src/ui/widget/filter-effect-chooser.h +++ b/src/ui/widget/filter-effect-chooser.h @@ -54,11 +54,13 @@ public: double get_blur_value() const; void set_blur_value(const double); void set_blur_sensitive(const bool); + Gtk::Label *get_blur_label() { return &_lb_blur; }; private: int _flags; Gtk::HBox _hb_blend; - Gtk::Label _lb_blend; + Gtk::HBox _hb_blur; + Gtk::Label _lb_blend, _lb_blur, _lb_blur_unit; ComboBoxEnum _blend; SpinScale _blur; -- cgit v1.2.3 From ac167afb76ab4c730ac9dc945dc5dcd8efb8f5cf Mon Sep 17 00:00:00 2001 From: "Liam P. White" Date: Sun, 2 Mar 2014 12:59:13 -0500 Subject: Experimental Ponyscape to Inkscape merge (does not compile) (bzr r13090.1.4) --- src/display/cairo-utils.cpp | 4 +--- src/display/cairo-utils.h | 2 ++ src/ui/widget/Makefile_insert | 9 +++++++-- 3 files changed, 10 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/display/cairo-utils.cpp b/src/display/cairo-utils.cpp index 5b358ade7..c0a17bcdd 100644 --- a/src/display/cairo-utils.cpp +++ b/src/display/cairo-utils.cpp @@ -30,8 +30,6 @@ #include "helper/geom-curves.h" #include "display/cairo-templates.h" -static void ink_cairo_pixbuf_cleanup(guchar *, void *); - /** * Key for cairo_surface_t to keep track of current color interpolation value * Only the address of the structure is used, it is never initialized. See: @@ -1119,7 +1117,7 @@ GdkPixbuf *ink_pixbuf_create_from_cairo_surface(cairo_surface_t *s) * to gdk_pixbuf_new_from_data when creating a GdkPixbuf backed by * a Cairo surface. */ -static void ink_cairo_pixbuf_cleanup(guchar * /*pixels*/, void *data) +void ink_cairo_pixbuf_cleanup(guchar * /*pixels*/, void *data) { cairo_surface_t *surface = static_cast(data); cairo_surface_destroy(surface); diff --git a/src/display/cairo-utils.h b/src/display/cairo-utils.h index 505e2ca77..fa0ee8853 100644 --- a/src/display/cairo-utils.h +++ b/src/display/cairo-utils.h @@ -21,6 +21,8 @@ #include "style.h" struct SPColor; +void ink_cairo_pixbuf_cleanup(guchar *, void *); +void convert_pixbuf_argb32_to_normal(GdkPixbuf *pb); namespace Inkscape { diff --git a/src/ui/widget/Makefile_insert b/src/ui/widget/Makefile_insert index 710b95c2b..e388b27f5 100644 --- a/src/ui/widget/Makefile_insert +++ b/src/ui/widget/Makefile_insert @@ -81,5 +81,10 @@ ink_common_sources += \ ui/widget/unit-menu.cpp \ ui/widget/unit-menu.h \ ui/widget/unit-tracker.h \ - ui/widget/unit-tracker.cpp - + ui/widget/unit-tracker.cpp \ + ui/widget/clipmaskicon.cpp \ + ui/widget/clipmaskicon.h \ + ui/widget/highlight-picker.cpp \ + ui/widget/highlight-picker.h \ + ui/widget/layertypeicon.cpp \ + ui/widget/layertypeicon.h -- cgit v1.2.3 From 1f7732ba927a31166d834a206bdfc7d20128d483 Mon Sep 17 00:00:00 2001 From: "Liam P. White" Date: Sun, 2 Mar 2014 14:15:38 -0500 Subject: Attempt at merging certaing features of Ponyscape to trunk (will not link) (bzr r13090.1.5) --- src/sp-item.cpp | 1 + src/sp-item.h | 4 ++++ 2 files changed, 5 insertions(+) (limited to 'src') diff --git a/src/sp-item.cpp b/src/sp-item.cpp index aec749929..279606481 100644 --- a/src/sp-item.cpp +++ b/src/sp-item.cpp @@ -416,6 +416,7 @@ void SPItem::build(SPDocument *document, Inkscape::XML::Node *repr) { object->readAttr( "inkscape:transform-center-y" ); object->readAttr( "inkscape:connector-avoid" ); object->readAttr( "inkscape:connection-points" ); + object->readAttr( "inkscape:highlight-color" ); SPObject::build(document, repr); } diff --git a/src/sp-item.h b/src/sp-item.h index dc0c54a80..0c0edae2a 100644 --- a/src/sp-item.h +++ b/src/sp-item.h @@ -146,6 +146,10 @@ public: void setHidden(bool hidden); /* Objects dialogue */ + bool isSensitive() const { + return sensitive; + }; + bool isHighlightSet() const; guint32 highlight_color() const; -- cgit v1.2.3 From 8830d1ad5ab0693313d760cc99e2df0f35c9f6d9 Mon Sep 17 00:00:00 2001 From: "Liam P. White" Date: Sun, 2 Mar 2014 16:29:52 -0500 Subject: Updated to include (non-functional) Objects dialogue (bzr r13090.1.6) --- src/menus-skeleton.h | 1 + src/ui/dialog/objects.cpp | 41 ++++++++++++++++++++++++++++++++++++++ src/ui/widget/Makefile_insert | 4 +++- src/ui/widget/highlight-picker.cpp | 32 ++++++++++++++++++++++++++++- 4 files changed, 76 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/menus-skeleton.h b/src/menus-skeleton.h index 3fcb77207..855b7774b 100644 --- a/src/menus-skeleton.h +++ b/src/menus-skeleton.h @@ -179,6 +179,7 @@ static char const menus_skeleton[] = " \n" " \n" " \n" +" \n" " \n" " \n" " \n" diff --git a/src/ui/dialog/objects.cpp b/src/ui/dialog/objects.cpp index 5023a8813..ebfa16f02 100644 --- a/src/ui/dialog/objects.cpp +++ b/src/ui/dialog/objects.cpp @@ -37,6 +37,7 @@ #include "ui/widget/insertordericon.h" #include "ui/widget/clipmaskicon.h" #include "ui/widget/highlight-picker.h" +#include "ui/tools/node-tool.h" #include "verbs.h" #include "widgets/icon.h" #include "xml/node.h" @@ -54,6 +55,7 @@ #include "sp-clippath.h" #include "sp-mask.h" #include "layer-manager.h" +#include "tools-switch.h" //#define DUMP_LAYERS 1 @@ -2037,6 +2039,9 @@ void ObjectsPanel::setDesktop( SPDesktop* desktop ) } //namespace UI } //namespace Inkscape +//should be okay to put these here because they are never referenced anywhere else +using namespace Inkscape::UI::Tools; + guint get_group0_keyval(GdkEventKey *event) { guint keyval = 0; gdk_keymap_translate_keyboard_state(gdk_keymap_get_for_display( @@ -2046,6 +2051,42 @@ guint get_group0_keyval(GdkEventKey *event) { return keyval; } +void SPItem::setHighlightColor(guint32 const color) +{ + g_free(_highlightColor); + if (color & 0x000000ff) + { + _highlightColor = g_strdup_printf("%u", color); + } + else + { + _highlightColor = NULL; + } + + NodeTool *tool = 0; + if (SP_ACTIVE_DESKTOP ) { + ToolBase *ec = SP_ACTIVE_DESKTOP->event_context; + if (INK_IS_NODE_TOOL(ec)) { + tool = static_cast(ec); + tools_switch(tool->desktop, TOOLS_NODES); + } + } +} + +void SPItem::unsetHighlightColor() +{ + g_free(_highlightColor); + _highlightColor = NULL; + NodeTool *tool = 0; + if (SP_ACTIVE_DESKTOP ) { + ToolBase *ec = SP_ACTIVE_DESKTOP->event_context; + if (INK_IS_NODE_TOOL(ec)) { + tool = static_cast(ec); + tools_switch(tool->desktop, TOOLS_NODES); + } + } +} + /* Local Variables: mode:c++ diff --git a/src/ui/widget/Makefile_insert b/src/ui/widget/Makefile_insert index e388b27f5..2c543c5cc 100644 --- a/src/ui/widget/Makefile_insert +++ b/src/ui/widget/Makefile_insert @@ -87,4 +87,6 @@ ink_common_sources += \ ui/widget/highlight-picker.cpp \ ui/widget/highlight-picker.h \ ui/widget/layertypeicon.cpp \ - ui/widget/layertypeicon.h + ui/widget/layertypeicon.h \ + ui/widget/insertordericon.cpp \ + ui/widget/insertordericon.h diff --git a/src/ui/widget/highlight-picker.cpp b/src/ui/widget/highlight-picker.cpp index b799b5e29..bf93fa960 100644 --- a/src/ui/widget/highlight-picker.cpp +++ b/src/ui/widget/highlight-picker.cpp @@ -157,11 +157,41 @@ HighlightPicker::activate_vfunc(GdkEvent* event, return false; } - } // namespace Widget } // namespace UI } // namespace Inkscape +//should be okay to put this here +/** + * Converts GdkPixbuf's data to premultiplied ARGB. + * This function will convert a GdkPixbuf in place into Cairo's native pixel format. + * Note that this is a hack intended to save memory. When the pixbuf is in Cairo's format, + * using it with GTK will result in corrupted drawings. + */ +void +convert_pixbuf_normal_to_argb32(GdkPixbuf *pb) +{ + convert_pixels_pixbuf_to_argb32( + gdk_pixbuf_get_pixels(pb), + gdk_pixbuf_get_width(pb), + gdk_pixbuf_get_height(pb), + gdk_pixbuf_get_rowstride(pb)); +} + +/** + * Converts GdkPixbuf's data back to its native format. + * Once this is done, the pixbuf can be used with GTK again. + */ +void +convert_pixbuf_argb32_to_normal(GdkPixbuf *pb) +{ + convert_pixels_argb32_to_pixbuf( + gdk_pixbuf_get_pixels(pb), + gdk_pixbuf_get_width(pb), + gdk_pixbuf_get_height(pb), + gdk_pixbuf_get_rowstride(pb)); +} + /* Local Variables: mode:c++ -- cgit v1.2.3 From 169c4551d14f4403f01724b93740c23e841f5fb0 Mon Sep 17 00:00:00 2001 From: "Liam P. White" Date: Sun, 2 Mar 2014 17:00:28 -0500 Subject: Fix verbs.cpp (bzr r13090.1.7) --- src/verbs.cpp | 3 +++ 1 file changed, 3 insertions(+) (limited to 'src') diff --git a/src/verbs.cpp b/src/verbs.cpp index 653d5f892..4ac5fdc41 100644 --- a/src/verbs.cpp +++ b/src/verbs.cpp @@ -2040,6 +2040,9 @@ void DialogVerb::perform(SPAction *action, void *data) case SP_VERB_DIALOG_LAYERS: dt->_dlg_mgr->showDialog("LayersPanel"); break; + case SP_VERB_DIALOG_OBJECTS: + dt->_dlg_mgr->showDialog("ObjectsPanel"); + break; case SP_VERB_DIALOG_LIVE_PATH_EFFECT: dt->_dlg_mgr->showDialog("LivePathEffect"); break; -- cgit v1.2.3 From b8fb6e46b8e96c90a2182061d3a6c4fab1e7f784 Mon Sep 17 00:00:00 2001 From: "Liam P. White" Date: Sun, 2 Mar 2014 17:23:47 -0500 Subject: Attempt 2 at getting objects dialogue (bzr r13090.1.8) --- src/verbs.cpp | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src') diff --git a/src/verbs.cpp b/src/verbs.cpp index 4ac5fdc41..b5c5abe13 100644 --- a/src/verbs.cpp +++ b/src/verbs.cpp @@ -2861,6 +2861,8 @@ Verb *Verb::_base_verbs[] = { N_("Query information about extensions"), NULL), new DialogVerb(SP_VERB_DIALOG_LAYERS, "DialogLayers", N_("Layer_s..."), N_("View Layers"), INKSCAPE_ICON("dialog-layers")), + new DialogVerb(SP_VERB_DIALOG_OBJECTS, "DialogObjects", N_("Object_s..."), + N_("View Objects"), INKSCAPE_ICON("dialog-layers")), new DialogVerb(SP_VERB_DIALOG_LIVE_PATH_EFFECT, "DialogLivePathEffect", N_("Path E_ffects ..."), N_("Manage, edit, and apply path effects"), NULL), new DialogVerb(SP_VERB_DIALOG_FILTER_EFFECTS, "DialogFilterEffects", N_("Filter _Editor..."), -- cgit v1.2.3 From fc643d9de8b5b3faf6d43559a43308fbce56e592 Mon Sep 17 00:00:00 2001 From: "Liam P. White" Date: Sun, 2 Mar 2014 17:39:47 -0500 Subject: Fix objects dialogue (bzr r13090.1.9) --- src/ui/dialog/dialog-manager.cpp | 3 +++ 1 file changed, 3 insertions(+) (limited to 'src') diff --git a/src/ui/dialog/dialog-manager.cpp b/src/ui/dialog/dialog-manager.cpp index 6d32e3aa8..bbb55ceee 100644 --- a/src/ui/dialog/dialog-manager.cpp +++ b/src/ui/dialog/dialog-manager.cpp @@ -54,6 +54,7 @@ #include "ui/dialog/xml-tree.h" #include "ui/dialog/clonetiler.h" #include "ui/dialog/svg-fonts-dialog.h" +#include "ui/dialog/objects.h" namespace Inkscape { namespace UI { @@ -108,6 +109,7 @@ DialogManager::DialogManager() { registerFactory("IconPreviewPanel", &create); registerFactory("InkscapePreferences", &create); registerFactory("LayersPanel", &create); + registerFactory("ObjectsPanel", &create); registerFactory("LivePathEffect", &create); registerFactory("Memory", &create); registerFactory("Messages", &create); @@ -142,6 +144,7 @@ DialogManager::DialogManager() { registerFactory("IconPreviewPanel", &create); registerFactory("InkscapePreferences", &create); registerFactory("LayersPanel", &create); + registerFactory("ObjectsPanel", &create); registerFactory("LivePathEffect", &create); registerFactory("Memory", &create); registerFactory("Messages", &create); -- cgit v1.2.3 From 93e2eef0d931bc2250b0328ddc24dac76c7c3e03 Mon Sep 17 00:00:00 2001 From: "Liam P. White" Date: Sun, 2 Mar 2014 18:18:32 -0500 Subject: Modified Objects dialogue to stop crashing on change of highlight color (bzr r13090.1.10) --- src/sp-item.cpp | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src') diff --git a/src/sp-item.cpp b/src/sp-item.cpp index 279606481..79d8cc37d 100644 --- a/src/sp-item.cpp +++ b/src/sp-item.cpp @@ -99,6 +99,8 @@ SPItem::SPItem() : SPObject() { sensitive = TRUE; bbox_valid = FALSE; + _highlightColor = NULL; + transform_center_x = 0; transform_center_y = 0; -- cgit v1.2.3 From 4eed716131afa00f3590b7d60600ef0c476c78e3 Mon Sep 17 00:00:00 2001 From: "Liam P. White" Date: Sun, 2 Mar 2014 20:24:50 -0500 Subject: Fixed path color when changed by Objects Dialog (bzr r13090.1.11) --- src/attributes.cpp | 1 + src/attributes.h | 1 + src/sp-item.cpp | 17 +++++++++++++++++ src/ui/tool/multi-path-manipulator.cpp | 6 +++--- src/ui/tool/multi-path-manipulator.h | 2 +- src/ui/tools/node-tool.cpp | 3 ++- 6 files changed, 25 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/attributes.cpp b/src/attributes.cpp index ee2a80fd3..4e39b648e 100644 --- a/src/attributes.cpp +++ b/src/attributes.cpp @@ -41,6 +41,7 @@ static SPStyleProp const props[] = { {SP_ATTR_TRANSFORM_CENTER_X, "inkscape:transform-center-x"}, {SP_ATTR_TRANSFORM_CENTER_Y, "inkscape:transform-center-y"}, {SP_ATTR_INKSCAPE_PATH_EFFECT, "inkscape:path-effect"}, + {SP_ATTR_INKSCAPE_HIGHLIGHT_COLOR, "inkscape:highlight-color"}, /* SPAnchor */ {SP_ATTR_XLINK_HREF, "xlink:href"}, {SP_ATTR_XLINK_TYPE, "xlink:type"}, diff --git a/src/attributes.h b/src/attributes.h index b8843fcb7..d1c93b819 100644 --- a/src/attributes.h +++ b/src/attributes.h @@ -40,6 +40,7 @@ enum SPAttributeEnum { SP_ATTR_TRANSFORM_CENTER_X, SP_ATTR_TRANSFORM_CENTER_Y, SP_ATTR_INKSCAPE_PATH_EFFECT, + SP_ATTR_INKSCAPE_HIGHLIGHT_COLOR, /* SPAnchor */ SP_ATTR_XLINK_HREF, SP_ATTR_XLINK_TYPE, diff --git a/src/sp-item.cpp b/src/sp-item.cpp index 79d8cc37d..ff3e3a31c 100644 --- a/src/sp-item.cpp +++ b/src/sp-item.cpp @@ -493,11 +493,23 @@ void SPItem::set(unsigned int key, gchar const* value) { break; } case SP_ATTR_SODIPODI_INSENSITIVE: + { item->sensitive = !value; for (SPItemView *v = item->display; v != NULL; v = v->next) { v->arenaitem->setSensitive(item->sensitive); } break; + } + case SP_ATTR_INKSCAPE_HIGHLIGHT_COLOR: + { + g_free(item->_highlightColor); + if (value) { + item->_highlightColor = g_strdup(value); + } else { + item->_highlightColor = NULL; + } + break; + } case SP_ATTR_CONNECTOR_AVOID: item->avoidRef->setAvoid(value); break; @@ -706,6 +718,11 @@ Inkscape::XML::Node* SPItem::write(Inkscape::XML::Document *xml_doc, Inkscape::X g_free ((void *) uri); } } + if (item->_highlightColor){ + repr->setAttribute("inkscape:highlight-color", item->_highlightColor); + } else { + repr->setAttribute("inkscape:highlight-color", NULL); + } SPObject::write(xml_doc, repr, flags); diff --git a/src/ui/tool/multi-path-manipulator.cpp b/src/ui/tool/multi-path-manipulator.cpp index 65987ad52..b54b5ad07 100644 --- a/src/ui/tool/multi-path-manipulator.cpp +++ b/src/ui/tool/multi-path-manipulator.cpp @@ -182,7 +182,7 @@ void MultiPathManipulator::setItems(std::set const &s) ShapeRecord const &r = *i; if (!SP_IS_PATH(r.item) && !IS_LIVEPATHEFFECT(r.item)) continue; boost::shared_ptr newpm(new PathManipulator(*this, (SPPath*) r.item, - r.edit_transform, _getOutlineColor(r.role), r.lpe_key)); + r.edit_transform, _getOutlineColor(r.role, r.item), r.lpe_key)); newpm->showHandles(_show_handles); // always show outlines for clips and masks newpm->showOutline(_show_outline || r.role != SHAPE_ROLE_NORMAL); @@ -833,7 +833,7 @@ void MultiPathManipulator::_doneWithCleanup(gchar const *reason, bool alert_LPE) } /** Get an outline color based on the shape's role (normal, mask, LPE parameter, etc.). */ -guint32 MultiPathManipulator::_getOutlineColor(ShapeRole role) +guint32 MultiPathManipulator::_getOutlineColor(ShapeRole role, SPItem *item) { Inkscape::Preferences *prefs = Inkscape::Preferences::get(); switch(role) { @@ -845,7 +845,7 @@ guint32 MultiPathManipulator::_getOutlineColor(ShapeRole role) return prefs->getColor("/tools/nodes/lpe_param_color", 0x009000ff); case SHAPE_ROLE_NORMAL: default: - return prefs->getColor("/tools/nodes/outline_color", 0xff0000ff); + return item->highlight_color(); } } diff --git a/src/ui/tool/multi-path-manipulator.h b/src/ui/tool/multi-path-manipulator.h index 1328372c6..d3746b878 100644 --- a/src/ui/tool/multi-path-manipulator.h +++ b/src/ui/tool/multi-path-manipulator.h @@ -106,7 +106,7 @@ private: void _commit(CommitEvent cps); void _done(gchar const *reason, bool alert_LPE = false); void _doneWithCleanup(gchar const *reason, bool alert_LPE = false); - guint32 _getOutlineColor(ShapeRole role); + guint32 _getOutlineColor(ShapeRole role, SPItem *item); MapType _mmap; public: diff --git a/src/ui/tools/node-tool.cpp b/src/ui/tools/node-tool.cpp index b1e11bd66..719b67108 100644 --- a/src/ui/tools/node-tool.cpp +++ b/src/ui/tools/node-tool.cpp @@ -473,7 +473,8 @@ bool NodeTool::root_handler(GdkEvent* event) { SPCanvasItem *flash = sp_canvas_bpath_new(sp_desktop_tempgroup(desktop), c); sp_canvas_bpath_set_stroke(SP_CANVAS_BPATH(flash), - prefs->getInt("/tools/nodes/highlight_color", 0xff0000ff), 1.0, + //prefs->getInt("/tools/nodes/highlight_color", 0xff0000ff), 1.0, + over_item->highlight_color(), 1.0, SP_STROKE_LINEJOIN_MITER, SP_STROKE_LINECAP_BUTT); sp_canvas_bpath_set_fill(SP_CANVAS_BPATH(flash), 0, SP_WIND_RULE_NONZERO); -- cgit v1.2.3 From dc1f7ce719d703d8dd4d7747d1967a3e8a1bfb18 Mon Sep 17 00:00:00 2001 From: "Liam P. White" Date: Tue, 4 Mar 2014 16:53:56 -0500 Subject: Remove tag dialog temporarily (bzr r13090.1.13) --- src/ui/dialog/Makefile_insert | 2 -- src/ui/dialog/dialog-manager.cpp | 6 +++--- src/ui/dialog/swatches.cpp | 18 ++++++++++++++++++ 3 files changed, 21 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/ui/dialog/Makefile_insert b/src/ui/dialog/Makefile_insert index bdb1abcda..1cf667f2a 100644 --- a/src/ui/dialog/Makefile_insert +++ b/src/ui/dialog/Makefile_insert @@ -113,6 +113,4 @@ ink_common_sources += \ ui/dialog/lpe-powerstroke-properties.h \ ui/dialog/objects.cpp \ ui/dialog/objects.h \ - ui/dialog/tags.cpp \ - ui/dialog/tags.h \ $(inkboard_dialogs) diff --git a/src/ui/dialog/dialog-manager.cpp b/src/ui/dialog/dialog-manager.cpp index bbfea8cf0..1fddbf007 100644 --- a/src/ui/dialog/dialog-manager.cpp +++ b/src/ui/dialog/dialog-manager.cpp @@ -55,7 +55,7 @@ #include "ui/dialog/clonetiler.h" #include "ui/dialog/svg-fonts-dialog.h" #include "ui/dialog/objects.h" -#include "ui/dialog/tags.h" +//#include "ui/dialog/tags.h" namespace Inkscape { namespace UI { @@ -111,7 +111,7 @@ DialogManager::DialogManager() { registerFactory("InkscapePreferences", &create); registerFactory("LayersPanel", &create); registerFactory("ObjectsPanel", &create); - registerFactory("TagsPanel", &create); + //registerFactory("TagsPanel", &create); registerFactory("LivePathEffect", &create); registerFactory("Memory", &create); registerFactory("Messages", &create); @@ -147,7 +147,7 @@ DialogManager::DialogManager() { registerFactory("InkscapePreferences", &create); registerFactory("LayersPanel", &create); registerFactory("ObjectsPanel", &create); - registerFactory("TagsPanel", &create); + //registerFactory("TagsPanel", &create); registerFactory("LivePathEffect", &create); registerFactory("Memory", &create); registerFactory("Messages", &create); diff --git a/src/ui/dialog/swatches.cpp b/src/ui/dialog/swatches.cpp index 5e77a28ab..711bcfe2d 100644 --- a/src/ui/dialog/swatches.cpp +++ b/src/ui/dialog/swatches.cpp @@ -20,6 +20,7 @@ #include "swatches.h" #include +#include #include #include @@ -57,6 +58,22 @@ #include "gradient-chemistry.h" #include "helper/action.h" #include "helper/action-context.h" +#include "xml/node-observer.h" +#include "xml/repr.h" +#include "sp-pattern.h" +#include "icon-size.h" +#include "widgets/icon.h" +#include "filedialog.h" +#include "sp-stop.h" +#include "svg/svg-color.h" +#include "sp-radial-gradient.h" +#include "color-rgba.h" +#include "event-context.h" +#include +//sorry! +#ifdef WIN32 +#include +#endif namespace Inkscape { namespace UI { @@ -64,6 +81,7 @@ namespace Dialogs { #define VBLOCK 16 #define PREVIEW_PIXBUF_WIDTH 128 +#define SWATCHES_FILE_NAME "swatches.svg" void _loadPaletteFile( gchar const *filename, gboolean user=FALSE ); -- cgit v1.2.3 From 12971e975dae83c23e89cdbff99e990d3916b6ff Mon Sep 17 00:00:00 2001 From: "Liam P. White" Date: Tue, 4 Mar 2014 18:05:52 -0500 Subject: Added some basic swatch stuff (does not compile) (bzr r13090.1.14) --- src/ui/dialog/swatches.cpp | 2940 ++++++++++++++++++++++++++++++-------------- src/ui/dialog/swatches.h | 155 ++- 2 files changed, 2157 insertions(+), 938 deletions(-) (limited to 'src') diff --git a/src/ui/dialog/swatches.cpp b/src/ui/dialog/swatches.cpp index 711bcfe2d..a0c79b8ac 100644 --- a/src/ui/dialog/swatches.cpp +++ b/src/ui/dialog/swatches.cpp @@ -43,10 +43,10 @@ #include "path-prefix.h" #include "preferences.h" #include "sp-item.h" +#include "sp-gradient-fns.h" #include "sp-gradient.h" #include "sp-gradient-vector.h" #include "style.h" -#include "ui/previewholder.h" #include "widgets/desktop-widget.h" #include "widgets/gradient-vector.h" #include "widgets/eek-preview.h" @@ -57,7 +57,6 @@ #include "verbs.h" #include "gradient-chemistry.h" #include "helper/action.h" -#include "helper/action-context.h" #include "xml/node-observer.h" #include "xml/repr.h" #include "sp-pattern.h" @@ -68,1172 +67,2255 @@ #include "svg/svg-color.h" #include "sp-radial-gradient.h" #include "color-rgba.h" -#include "event-context.h" +#include "svg/css-ostringstream.h" +//#include "event-context.h" //no longer exists #include -//sorry! #ifdef WIN32 #include #endif +guint get_group0_keyval(GdkEventKey *event); +void sp_desktop_set_gradient(SPDesktop *desktop, SPGradient* gradient, bool fill); + namespace Inkscape { namespace UI { namespace Dialogs { -#define VBLOCK 16 -#define PREVIEW_PIXBUF_WIDTH 128 #define SWATCHES_FILE_NAME "swatches.svg" -void _loadPaletteFile( gchar const *filename, gboolean user=FALSE ); - -std::list userSwatchPages; -std::list systemSwatchPages; -static std::map docPalettes; -static std::vector docTrackings; -static std::map docPerPanel; - - -class SwatchesPanelHook : public SwatchesPanel -{ -public: - static void convertGradient( GtkMenuItem *menuitem, gpointer userData ); - static void deleteGradient( GtkMenuItem *menuitem, gpointer userData ); -}; +static char* trim( char* str ) { + char* ret = str; + while ( *str && (*str == ' ' || *str == '\t') ) { + str++; + } + ret = str; + while ( *str ) { + str++; + } + str--; + while ( str > ret && (( *str == ' ' || *str == '\t' ) || *str == '\r' || *str == '\n') ) { + *str-- = 0; + } + return ret; +} -static void handleClick( GtkWidget* /*widget*/, gpointer callback_data ) { - ColorItem* item = reinterpret_cast(callback_data); - if ( item ) { - item->buttonClicked(false); +static void skipWhitespace( char*& str ) { + while ( *str == ' ' || *str == '\t' ) { + str++; } } -static void handleSecondaryClick( GtkWidget* /*widget*/, gint /*arg1*/, gpointer callback_data ) { - ColorItem* item = reinterpret_cast(callback_data); - if ( item ) { - item->buttonClicked(true); +static bool parseNum( char*& str, int& val ) { + val = 0; + while ( '0' <= *str && *str <= '9' ) { + val = val * 10 + (*str - '0'); + str++; } + bool retval = !(*str == 0 || *str == ' ' || *str == '\t' || *str == '\r' || *str == '\n'); + return retval; } -static GtkWidget* popupMenu = 0; -static GtkWidget *popupSubHolder = 0; -static GtkWidget *popupSub = 0; -static std::vector popupItems; -static std::vector popupExtras; -static ColorItem* bounceTarget = 0; -static SwatchesPanel* bouncePanel = 0; +static char * SwatchFile; +static SPDocument * SwatchDocument; +static unsigned int page_suffix; -static void redirClick( GtkMenuItem *menuitem, gpointer /*user_data*/ ) +static void loadPalletFile() { - if ( bounceTarget ) { - handleClick( GTK_WIDGET(menuitem), bounceTarget ); + if (!SwatchDocument) { + SwatchFile=g_build_filename(INKSCAPE_PALETTESDIR, _("swatches.svg"), NULL); + SwatchDocument=SPDocument::createNewDoc (SwatchFile, TRUE); + if (!SwatchDocument) { + SwatchDocument = SPDocument::createNewDoc(NULL, TRUE, true); + sp_repr_save_file(SwatchDocument->getReprDoc(), SwatchFile, SP_SVG_NS_URI); + } } } -static void redirSecondaryClick( GtkMenuItem *menuitem, gpointer /*user_data*/ ) +static void addStop( Inkscape::XML::Node *parent, Glib::ustring const &color, gfloat opacity, gchar const *offset ) { - if ( bounceTarget ) { - handleSecondaryClick( GTK_WIDGET(menuitem), 0, bounceTarget ); +#ifdef SP_GR_VERBOSE + g_message("addStop(%p, %s, %d, %s)", parent, color.c_str(), opacity, offset); +#endif + Inkscape::XML::Node *stop = parent->document()->createElement("svg:stop"); + { + gchar *tmp = g_strdup_printf( "stop-color:%s;stop-opacity:%f;", color.c_str(), opacity < 0.0 ? 0.0 : (opacity > 1.0 ? 1.0 : opacity) ); + stop->setAttribute( "style", tmp ); + g_free(tmp); } + + stop->setAttribute( "offset", offset ); + + parent->appendChild(stop); + Inkscape::GC::release(stop); } -static void editGradientImpl( SPDesktop* desktop, SPGradient* gr ) +static SPGroup* importGPL(SPDocument* doc, const gchar* full) { - if ( gr ) { - bool shown = false; - if ( desktop && desktop->doc() ) { - Inkscape::Selection *selection = sp_desktop_selection( desktop ); - GSList const *items = selection->itemList(); - if (items) { - SPStyle *query = sp_style_new( desktop->doc() ); - int result = objects_query_fillstroke(const_cast(items), query, true); - if ( (result == QUERY_STYLE_MULTIPLE_SAME) || (result == QUERY_STYLE_SINGLE) ) { - // could be pertinent - if (query->fill.isPaintserver()) { - SPPaintServer* server = query->getFillPaintServer(); - if ( SP_IS_GRADIENT(server) ) { - SPGradient* grad = SP_GRADIENT(server); - if ( grad->isSwatch() && grad->getId() == gr->getId()) { - desktop->_dlg_mgr->showDialog("FillAndStroke"); - shown = true; + SPGroup* ret = NULL; + if ( !Inkscape::IO::file_test( full, G_FILE_TEST_IS_DIR ) ) { + + /*Load the pallet file here*/ + char block[1024]; + FILE *f = Inkscape::IO::fopen_utf8name( full, "r" ); + if ( f ) { + char* result = fgets( block, sizeof(block), f ); + if ( result ) { + if ( strncmp( "GIMP Palette", block, 12 ) == 0 ) { + bool inHeader = true; + bool hasErr = false; + + Inkscape::XML::Node * page = doc->getReprDoc()->createElement("svg:g"); + gchar *id=NULL; + do { + g_free(id); + id = g_strdup_printf("page%d", page_suffix++); + } while (doc->getObjectById(id)); + + page->setAttribute("id", id); + + do { + result = fgets( block, sizeof(block), f ); + block[sizeof(block) - 1] = 0; + if ( result ) { + if ( block[0] == '#' ) { + // ignore comment + } else { + char *ptr = block; + // very simple check for header versus entry + while ( *ptr == ' ' || *ptr == '\t' ) { + ptr++; + } + if ( (*ptr == 0) || (*ptr == '\r') || (*ptr == '\n') ) { + // blank line. skip it. + } else if ( '0' <= *ptr && *ptr <= '9' ) { + // should be an entry link + inHeader = false; + ptr = block; + Glib::ustring name(""); + skipWhitespace(ptr); + if ( *ptr ) { + int r = 0; + int g = 0; + int b = 0; + hasErr = parseNum(ptr, r); + if ( !hasErr ) { + skipWhitespace(ptr); + hasErr = parseNum(ptr, g); + } + if ( !hasErr ) { + skipWhitespace(ptr); + hasErr = parseNum(ptr, b); + } + if ( !hasErr && *ptr ) { + char* n = trim(ptr); + if (n != NULL) { + name = g_dpgettext2(NULL, "Palette", n); + } + } + if ( !hasErr ) { + // Add the entry now + + Inkscape::XML::Node *grad = doc->getReprDoc()->createElement("svg:linearGradient"); + grad->setAttribute("inkscape:label", name.c_str()); + grad->setAttribute( "osb:paint", "solid", 0 ); + SPColor color((float)r / 255, (float)g / 255, (float)b / 255); + addStop(grad, color.toString(), 1, "0"); + page->appendChild(grad); + Inkscape::GC::release(grad); + } + } else { + hasErr = true; + } + } else { + if ( !inHeader ) { + // Hmmm... probably bad. Not quite the format we want? + hasErr = true; + } else { + char* sep = strchr(result, ':'); + if ( sep ) { + *sep = 0; + char* val = trim(sep + 1); + char* name = trim(result); + if ( *name ) { + if ( strcmp( "Name", name ) == 0 ) + { + page->setAttribute("inkscape:label", val); + } + } else { + // error + hasErr = true; + } + } else { + // error + hasErr = true; + } + } + } } } + } while ( result && !hasErr ); + if ( !hasErr ) { + doc->getDefs()->appendChild(page); + Inkscape::GC::release(page); + SPObject* obj = doc->getObjectByRepr(page); + if (SP_IS_GROUP(obj)) { + ret = SP_GROUP(obj); + } + #if ENABLE_MAGIC_COLORS + ColorItem::_wireMagicColors( onceMore ); + #endif // ENABLE_MAGIC_COLORS + } else { + delete page; } } - sp_style_unref(query); } - } - if (!shown) { - Inkscape::Preferences *prefs = Inkscape::Preferences::get(); - if (prefs->getBool("/dialogs/gradienteditor/showlegacy", false)) { - // Legacy gradient dialog - GtkWidget *dialog = sp_gradient_vector_editor_new( gr ); - gtk_widget_show( dialog ); - } else { - // Invoke the gradient tool - Inkscape::Verb *verb = Inkscape::Verb::get( SP_VERB_CONTEXT_GRADIENT ); - if ( verb ) { - SPAction *action = verb->get_action( Inkscape::ActionContext( ( Inkscape::UI::View::View * ) SP_ACTIVE_DESKTOP ) ); - if ( action ) { - sp_action_perform( action, NULL ); - } - } - } + fclose(f); } + /* end loading the pallet file*/ } + return ret; } -static void editGradient( GtkMenuItem */*menuitem*/, gpointer /*user_data*/ ) +SwatchesPanel& SwatchesPanel::getInstance() { - if ( bounceTarget ) { - SwatchesPanel* swp = bouncePanel; - SPDesktop* desktop = swp ? swp->getDesktop() : 0; - SPDocument *doc = desktop ? desktop->doc() : 0; - if (doc) { - std::string targetName(bounceTarget->def.descr); - const GSList *gradients = doc->getResourceList("gradient"); - for (const GSList *item = gradients; item; item = item->next) { - SPGradient* grad = SP_GRADIENT(item->data); - if ( targetName == grad->getId() ) { - editGradientImpl( desktop, grad ); - break; + return *new SwatchesPanel(); +} + +class SwatchesPanel::StopWatcher : public Inkscape::XML::NodeObserver { +public: + StopWatcher(SwatchesPanel* pnl, SPStop* obj) : + _pnl(pnl), + _obj(obj), + _repr(obj->getRepr()) + { + _repr->addObserver(*this); + } + + ~StopWatcher() { + _repr->removeObserver(*this); + } + + virtual void notifyChildAdded( Inkscape::XML::Node &/*node*/, Inkscape::XML::Node &/*child*/, Inkscape::XML::Node */*prev*/ ){} + virtual void notifyChildRemoved( Inkscape::XML::Node &/*node*/, Inkscape::XML::Node &/*child*/, Inkscape::XML::Node */*prev*/ ){} + virtual void notifyChildOrderChanged( Inkscape::XML::Node &/*node*/, Inkscape::XML::Node &/*child*/, Inkscape::XML::Node */*old_prev*/, Inkscape::XML::Node */*new_prev*/ ){} + virtual void notifyContentChanged( Inkscape::XML::Node &/*node*/, Util::ptr_shared /*old_content*/, Util::ptr_shared /*new_content*/ ) {} + + virtual void notifyAttributeChanged( Inkscape::XML::Node &/*node*/, GQuark name, Util::ptr_shared /*old_value*/, Util::ptr_shared /*new_value*/ ) { + if (_pnl && _obj) { + _pnl->_defsChanged( ); + } + } + + SwatchesPanel* _pnl; + SPStop* _obj; + Inkscape::XML::Node* _repr; +}; + +class SwatchesPanel::GradientWatcher : public Inkscape::XML::NodeObserver { +public: + GradientWatcher(SwatchesPanel* pnl, SPGradient* obj) : + _pnl(pnl), + _obj(obj), + _repr(obj->getRepr()), + _labelAttr(g_quark_from_string("inkscape:label")), + _swatchAttr(g_quark_from_string("osb:paint")) + { + _repr->addObserver(*this); + } + + ~GradientWatcher() { + _repr->removeObserver(*this); + } + + virtual void notifyChildAdded( Inkscape::XML::Node &/*node*/, Inkscape::XML::Node &/*child*/, Inkscape::XML::Node */*prev*/ ) + { + if ( _pnl && _obj && _obj->isSwatch()) { + _pnl->_defsChanged( ); + } + } + virtual void notifyChildRemoved( Inkscape::XML::Node &/*node*/, Inkscape::XML::Node &/*child*/, Inkscape::XML::Node */*prev*/ ) + { + if ( _pnl && _obj && _obj->isSwatch() ) { + _pnl->_defsChanged( ); + } + } + virtual void notifyChildOrderChanged( Inkscape::XML::Node &/*node*/, Inkscape::XML::Node &/*child*/, Inkscape::XML::Node */*old_prev*/, Inkscape::XML::Node */*new_prev*/ ) + { + if ( _pnl && _obj && _obj->isSwatch() ) { + _pnl->_defsChanged( ); + } + } + virtual void notifyContentChanged( Inkscape::XML::Node &/*node*/, Util::ptr_shared /*old_content*/, Util::ptr_shared /*new_content*/ ) {} + virtual void notifyAttributeChanged( Inkscape::XML::Node &/*node*/, GQuark name, Util::ptr_shared /*old_value*/, Util::ptr_shared /*new_value*/ ) { + if (_pnl && _obj && ((_obj->isSwatch() && name == _labelAttr) || name == _swatchAttr)) { + _pnl->_defsChanged( ); + } + } + + SwatchesPanel* _pnl; + SPGradient* _obj; + Inkscape::XML::Node* _repr; + GQuark _labelAttr; + GQuark _swatchAttr; +}; + +class SwatchesPanel::SwatchWatcher : public Inkscape::XML::NodeObserver { +public: + SwatchWatcher(SwatchesPanel* pnl, SPObject* obj, bool builtIn) : + _pnl(pnl), + _obj(obj), + _builtIn(builtIn), + _repr(obj->getRepr()), + _labelAttr(g_quark_from_string("inkscape:label")), + _swatchAttr(g_quark_from_string("osb:paint")) + { + _repr->addObserver(*this); + } + + ~SwatchWatcher() { + _repr->removeObserver(*this); + } + + virtual void notifyChildAdded( Inkscape::XML::Node &/*node*/, Inkscape::XML::Node &child, Inkscape::XML::Node */*prev*/ ) + { + if ( _pnl && _obj) { + SPObject *childobj = _builtIn ? SwatchDocument->getObjectByRepr(&child) : (_pnl->_currentDocument ? _pnl->_currentDocument->getObjectByRepr(&child) : 0); + if (childobj && ((SP_IS_GRADIENT(childobj) && SP_GRADIENT(childobj)->hasStops()) || SP_IS_GROUP(childobj))) { + if (_builtIn) { + _pnl->_swatchesChanged( ); + } else { + _pnl->_defsChanged( ); } } } } -} - -void SwatchesPanelHook::convertGradient( GtkMenuItem * /*menuitem*/, gpointer userData ) -{ - if ( bounceTarget ) { - SwatchesPanel* swp = bouncePanel; - SPDesktop* desktop = swp ? swp->getDesktop() : 0; - SPDocument *doc = desktop ? desktop->doc() : 0; - gint index = GPOINTER_TO_INT(userData); - if ( doc && (index >= 0) && (static_cast(index) < popupItems.size()) ) { - Glib::ustring targetName = popupItems[index]; - - const GSList *gradients = doc->getResourceList("gradient"); - for (const GSList *item = gradients; item; item = item->next) { - SPGradient* grad = SP_GRADIENT(item->data); - if ( targetName == grad->getId() ) { - grad->setSwatch(); - DocumentUndo::done(doc, SP_VERB_CONTEXT_GRADIENT, - _("Add gradient stop")); - break; + virtual void notifyChildRemoved( Inkscape::XML::Node &/*node*/, Inkscape::XML::Node &child, Inkscape::XML::Node */*prev*/ ) + { + if ( _pnl && _obj) { + if (_builtIn) { + _pnl->_swatchesChanged( ); + } else { + _pnl->_defsChanged( ); + } + } + } + virtual void notifyChildOrderChanged( Inkscape::XML::Node &/*node*/, Inkscape::XML::Node &child, Inkscape::XML::Node */*old_prev*/, Inkscape::XML::Node */*new_prev*/ ) + { + if ( _pnl && _obj) { + SPObject *childobj = _builtIn ? SwatchDocument->getObjectByRepr(&child) : (_pnl->_currentDocument ? _pnl->_currentDocument->getObjectByRepr(&child) : 0); + if (childobj && ((SP_IS_GRADIENT(childobj) && SP_GRADIENT(childobj)->hasStops()) || SP_IS_GROUP(childobj))) { + if (_builtIn) { + _pnl->_swatchesChanged( ); + } else { + _pnl->_defsChanged( ); } } } } -} + virtual void notifyContentChanged( Inkscape::XML::Node &/*node*/, Util::ptr_shared /*old_content*/, Util::ptr_shared /*new_content*/ ) {} + virtual void notifyAttributeChanged( Inkscape::XML::Node &/*node*/, GQuark name, Util::ptr_shared /*old_value*/, Util::ptr_shared /*new_value*/ ) { + if (_pnl && _obj && name == _labelAttr) { + if (_builtIn) { + _pnl->_swatchesChanged( ); + } else { + _pnl->_defsChanged( ); + } + } + } -void SwatchesPanelHook::deleteGradient( GtkMenuItem */*menuitem*/, gpointer /*userData*/ ) + SwatchesPanel* _pnl; + SPObject* _obj; + bool _builtIn; + Inkscape::XML::Node* _repr; + GQuark _labelAttr; + GQuark _swatchAttr; +}; + +class SwatchesPanel::ModelColumns : public Gtk::TreeModel::ColumnRecord { - if ( bounceTarget ) { - SwatchesPanel* swp = bouncePanel; - SPDesktop* desktop = swp ? swp->getDesktop() : 0; - sp_gradient_unset_swatch(desktop, bounceTarget->def.descr); +public: + + ModelColumns() + { + add(_colObject); + add(_colLabel); } -} + virtual ~ModelColumns() {} + + Gtk::TreeModelColumn _colObject; + Gtk::TreeModelColumn _colLabel; +}; -static SwatchesPanel* findContainingPanel( GtkWidget *widget ) +class SwatchesPanel::ModelColumnsDoc : public Gtk::TreeModel::ColumnRecord { - SwatchesPanel *swp = 0; +public: - std::map rawObjects; - for (std::map::iterator it = docPerPanel.begin(); it != docPerPanel.end(); ++it) { - rawObjects[GTK_WIDGET(it->first->gobj())] = it->first; + ModelColumnsDoc() + { + add(_colObject); + add(_colLabel); + add(_colPixbuf); } + virtual ~ModelColumnsDoc() {} - for (GtkWidget* curr = widget; curr && !swp; curr = gtk_widget_get_parent(curr)) { - if (rawObjects.find(curr) != rawObjects.end()) { - swp = rawObjects[curr]; + Gtk::TreeModelColumn _colObject; + Gtk::TreeModelColumn _colLabel; + Gtk::TreeModelColumn > _colPixbuf; +}; + +static void StripChildGroups(Inkscape::XML::Node * node, SPObject* addTo) +{ + for (Inkscape::XML::Node * it = node->firstChild(); it != NULL;) { + if (!strcmp(it->name(), "svg:g")) { + Inkscape::XML::Node * todel = it; + it = it->next(); + node->removeChild(todel); + } else { + it = it->next(); } } - - return swp; + addTo->appendChildRepr(node); } -static void removeit( GtkWidget *widget, gpointer data ) +static void BubbleChildGroups(Inkscape::XML::Node * node, SPObject* addTo) { - gtk_container_remove( GTK_CONTAINER(data), widget ); + std::queue groups; + for (Inkscape::XML::Node * it = node->firstChild(); it != NULL; ) { + if (!strcmp(it->name(), "svg:g")) { + groups.push(it->duplicate(addTo->document->getReprDoc())); + Inkscape::XML::Node * todel = it; + it = it->next(); + node->removeChild(todel); + } else { + it = it->next(); + } + } + addTo->appendChildRepr(node); + while (!groups.empty()) { + Inkscape::XML::Node * it = groups.front(); + groups.pop(); + BubbleChildGroups(it, addTo); + Inkscape::GC::release(it); + } } -/* extern'ed from colot-item.cpp */ -gboolean colorItemHandleButtonPress( GtkWidget* widget, GdkEventButton* event, gpointer user_data ); +void SwatchesPanel::_addSwatchButtonClicked(SPGroup* swatch, bool recurse) +{ + if (_currentDocument) { + if (swatch && SP_IS_GROUP(swatch) ) { + Inkscape::XML::Node * copy = swatch->getRepr()->duplicate(_currentDocument->getReprDoc()); + if (recurse) { + BubbleChildGroups(copy, _currentDocument->getDefs()); + } else { + StripChildGroups(copy, _currentDocument->getDefs()); + } + Inkscape::GC::release(copy); + DocumentUndo::done(_currentDocument, SP_VERB_DIALOG_SWATCHES, _("Add swatches to document")); + } + } +} -gboolean colorItemHandleButtonPress( GtkWidget* widget, GdkEventButton* event, gpointer user_data ) +void SwatchesPanel::_importButtonClicked(bool addToDoc, bool addToBI) { - gboolean handled = FALSE; - - if ( event && (event->button == 3) && (event->type == GDK_BUTTON_PRESS) ) { - SwatchesPanel* swp = findContainingPanel( widget ); - - if ( !popupMenu ) { - popupMenu = gtk_menu_new(); - GtkWidget* child = 0; - - //TRANSLATORS: An item in context menu on a colour in the swatches - child = gtk_menu_item_new_with_label(_("Set fill")); - g_signal_connect( G_OBJECT(child), - "activate", - G_CALLBACK(redirClick), - user_data); - gtk_menu_shell_append(GTK_MENU_SHELL(popupMenu), child); - - //TRANSLATORS: An item in context menu on a colour in the swatches - child = gtk_menu_item_new_with_label(_("Set stroke")); - - g_signal_connect( G_OBJECT(child), - "activate", - G_CALLBACK(redirSecondaryClick), - user_data); - gtk_menu_shell_append(GTK_MENU_SHELL(popupMenu), child); - - child = gtk_separator_menu_item_new(); - gtk_menu_shell_append(GTK_MENU_SHELL(popupMenu), child); - popupExtras.push_back(child); - - child = gtk_menu_item_new_with_label(_("Delete")); - g_signal_connect( G_OBJECT(child), - "activate", - G_CALLBACK(SwatchesPanelHook::deleteGradient), - user_data ); - gtk_menu_shell_append(GTK_MENU_SHELL(popupMenu), child); - popupExtras.push_back(child); - gtk_widget_set_sensitive( child, FALSE ); - - child = gtk_menu_item_new_with_label(_("Edit...")); - g_signal_connect( G_OBJECT(child), - "activate", - G_CALLBACK(editGradient), - user_data ); - gtk_menu_shell_append(GTK_MENU_SHELL(popupMenu), child); - popupExtras.push_back(child); - - child = gtk_separator_menu_item_new(); - gtk_menu_shell_append(GTK_MENU_SHELL(popupMenu), child); - popupExtras.push_back(child); - - child = gtk_menu_item_new_with_label(_("Convert")); - gtk_menu_shell_append(GTK_MENU_SHELL(popupMenu), child); - //popupExtras.push_back(child); - //gtk_widget_set_sensitive( child, FALSE ); + if (addToDoc || addToBI) { + //# Get the current directory for finding files + static Glib::ustring open_path; + Inkscape::Preferences *prefs = Inkscape::Preferences::get(); + + if(open_path.empty()) + { + Glib::ustring attr = prefs->getString("/dialogs/open/path"); + if (!attr.empty()) open_path = attr; + } + + //# Test if the open_path directory exists + if (!Inkscape::IO::file_test(open_path.c_str(), + (GFileTest)(G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR))) + open_path = ""; + + #ifdef WIN32 + //# If no open path, default to our win32 documents folder + if (open_path.empty()) + { + // The path to the My Documents folder is read from the + // value "HKEY_CURRENT_USER\Software\Windows\CurrentVersion\Explorer\Shell Folders\Personal" + HKEY key = NULL; + if(RegOpenKeyExA(HKEY_CURRENT_USER, + "Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders", + 0, KEY_QUERY_VALUE, &key) == ERROR_SUCCESS) { - popupSubHolder = child; - popupSub = gtk_menu_new(); - gtk_menu_item_set_submenu( GTK_MENU_ITEM(child), popupSub ); + WCHAR utf16path[_MAX_PATH]; + DWORD value_type; + DWORD data_size = sizeof(utf16path); + if(RegQueryValueExW(key, L"Personal", NULL, &value_type, + (BYTE*)utf16path, &data_size) == ERROR_SUCCESS) + { + g_assert(value_type == REG_SZ); + gchar *utf8path = g_utf16_to_utf8( + (const gunichar2*)utf16path, -1, NULL, NULL, NULL); + if(utf8path) + { + open_path = Glib::ustring(utf8path); + g_free(utf8path); + } + } } + } + #endif - gtk_widget_show_all(popupMenu); + //# If no open path, default to our home directory + if (open_path.empty()) + { + open_path = g_get_home_dir(); + open_path.append(G_DIR_SEPARATOR_S); } - if ( user_data ) { - ColorItem* item = reinterpret_cast(user_data); - bool show = swp && (swp->getSelectedIndex() == 0); - for ( std::vector::iterator it = popupExtras.begin(); it != popupExtras.end(); ++ it) { - gtk_widget_set_sensitive(*it, show); - } + Gtk::Window * parent = SP_ACTIVE_DESKTOP->getToplevel(); + //# Create a dialog + Inkscape::UI::Dialog::FileOpenDialog *openDialogInstance = + Inkscape::UI::Dialog::FileOpenDialog::create( + *parent, open_path, + Inkscape::UI::Dialog::SWATCH_TYPES, + _("Select file to open")); - bounceTarget = item; - bouncePanel = swp; - popupItems.clear(); - if ( popupMenu ) { - gtk_container_foreach(GTK_CONTAINER(popupSub), removeit, popupSub); - bool processed = false; - GtkWidget *wdgt = gtk_widget_get_ancestor(widget, SP_TYPE_DESKTOP_WIDGET); - if ( wdgt ) { - SPDesktopWidget *dtw = SP_DESKTOP_WIDGET(wdgt); - if ( dtw && dtw->desktop ) { - // Pick up all gradients with vectors - const GSList *gradients = (dtw->desktop->doc())->getResourceList("gradient"); - gint index = 0; - for (const GSList *curr = gradients; curr; curr = curr->next) { - SPGradient* grad = SP_GRADIENT(curr->data); - if ( grad->hasStops() && !grad->isSwatch() ) { - //gl = g_slist_prepend(gl, curr->data); - processed = true; - GtkWidget *child = gtk_menu_item_new_with_label(grad->getId()); - gtk_menu_shell_append(GTK_MENU_SHELL(popupSub), child); - - popupItems.push_back(grad->getId()); - g_signal_connect( G_OBJECT(child), - "activate", - G_CALLBACK(SwatchesPanelHook::convertGradient), - GINT_TO_POINTER(index) ); - index++; - } - } + //# Show the dialog + bool const success = openDialogInstance->show(); - gtk_widget_show_all(popupSub); - } - } - gtk_widget_set_sensitive( popupSubHolder, processed ); + //# Save the folder the user selected for later + open_path = openDialogInstance->getCurrentDirectory(); - gtk_menu_popup(GTK_MENU(popupMenu), NULL, NULL, NULL, NULL, event->button, event->time); - handled = TRUE; - } + if (!success) + { + delete openDialogInstance; + return; } - } - return handled; -} + //# User selected something. Get name and type + Glib::ustring fileName = openDialogInstance->getFilename(); + //# We no longer need the file dialog object - delete it + delete openDialogInstance; + openDialogInstance = NULL; -static char* trim( char* str ) { - char* ret = str; - while ( *str && (*str == ' ' || *str == '\t') ) { - str++; - } - ret = str; - while ( *str ) { - str++; - } - str--; - while ( str > ret && (( *str == ' ' || *str == '\t' ) || *str == '\r' || *str == '\n') ) { - *str-- = 0; - } - return ret; -} -static void skipWhitespace( char*& str ) { - while ( *str == ' ' || *str == '\t' ) { - str++; + if (!fileName.empty()) + { + Glib::ustring newFileName = Glib::filename_to_utf8(fileName); + + if ( newFileName.size() > 0) + fileName = newFileName; + else + g_warning( "ERROR CONVERTING OPEN FILENAME TO UTF-8" ); + + open_path = Glib::path_get_dirname (fileName); + open_path.append(G_DIR_SEPARATOR_S); + prefs->setString("/dialogs/open/path", open_path); + + SPDocument* importdoc = SPDocument::createNewDoc(fileName.c_str(), true); + Inkscape::XML::Node * page = NULL; + if (importdoc && importdoc->getDefs()) { + if (addToBI) { + page = SwatchDocument->getReprDoc()->createElement("svg:g"); + gchar *id=NULL; + do { + g_free(id); + id = g_strdup_printf("page%d", page_suffix++); + } while (SwatchDocument->getObjectById(id)); + + page->setAttribute("id", id); + gchar* name = g_path_get_basename(importdoc->getName()); + page->setAttribute("inkscape:label", name); + g_free(name); + } + + for (SPObject* it = importdoc->getDefs()->firstChild(); it != NULL; it = it->next) { + if (SP_IS_GROUP(it)) { + if (page) { + Inkscape::XML::Node * copy = it->getRepr()->duplicate(SwatchDocument->getReprDoc()); + page->appendChild(copy); + } + if (addToDoc) { + _addSwatchButtonClicked(SP_GROUP(it), false); + } + } + } + if (page) { + SwatchDocument->getDefs()->appendChildRepr(page); + sp_repr_save_file(SwatchDocument->getReprDoc(), SwatchFile, SP_SVG_NS_URI); + } + + importdoc->doUnref(); + } else { + SPGroup* g = importGPL(addToBI ? SwatchDocument : _currentDocument, fileName.c_str()); + if (addToBI) { + if (addToDoc) { + _addSwatchButtonClicked(g, false); + } + sp_repr_save_file(SwatchDocument->getReprDoc(), SwatchFile, SP_SVG_NS_URI); + } else { + DocumentUndo::done(_currentDocument, SP_VERB_DIALOG_SWATCHES, _("Add swatches to document")); + } + } + } } } -static bool parseNum( char*& str, int& val ) { - val = 0; - while ( '0' <= *str && *str <= '9' ) { - val = val * 10 + (*str - '0'); - str++; +void SwatchesPanel::SetSelectedFill(SPGradient* swatch) +{ + if (_currentDesktop && _currentDocument) { + SPItem* it = _currentDesktop->selection->singleItem(); + if (it) { + if (it->style->fill.isSet()) { + if (it->style->fill.isPaintserver()) { + SPPaintServer * server = it->style->getFillPaintServer(); + if (SP_IS_GRADIENT(server)) { + SPGradient *grad = SP_GRADIENT(server)->getVector(); + Inkscape::XML::Node * repr = grad->getRepr(); + Inkscape::XML::Node * drepr = swatch->getRepr(); + if (repr != drepr && grad != swatch) { + while (SPStop* olds = swatch->getFirstStop()) { + olds->deleteObject(); + } + for (SPStop* news = grad->getVector()->getFirstStop(); news != NULL; news = news->getNextStop()) { + Inkscape::XML::Node* clone = news->getRepr()->duplicate(_currentDocument->getReprDoc()); + swatch->appendChildRepr(clone); + Inkscape::GC::release(clone); + } + swatch->setSwatch(); + if (!_noLink.get_active()) { + sp_item_set_gradient(it, sp_gradient_ensure_vector_normalized(swatch), SP_IS_RADIALGRADIENT(swatch) ? SP_GRADIENT_TYPE_RADIAL : SP_GRADIENT_TYPE_LINEAR, Inkscape::FOR_FILL); + } + DocumentUndo::done(_currentDocument, SP_VERB_DIALOG_SWATCHES, _("Set Gradient Swatch")); + } + } + } else if (it->style->fill.isColor()) { + while (SPStop* olds = swatch->getFirstStop()) { + olds->deleteObject(); + } + addStop(swatch->getRepr(), it->style->fill.value.color.toString(), SP_SCALE24_TO_FLOAT(it->style->fill_opacity.value), "0"); + swatch->setSwatch(); + if (!_noLink.get_active()) { + SPGradient* normalized = sp_gradient_ensure_vector_normalized(swatch); + sp_item_set_gradient(it, normalized, SP_GRADIENT_TYPE_LINEAR, Inkscape::FOR_FILL); + } + DocumentUndo::done(_currentDocument, SP_VERB_DIALOG_SWATCHES, _("Set Color Swatch")); + } + } + } } - bool retval = !(*str == 0 || *str == ' ' || *str == '\t' || *str == '\r' || *str == '\n'); - return retval; } - -void _loadPaletteFile( gchar const *filename, gboolean user/*=FALSE*/ ) +void SwatchesPanel::SetSelectedStroke(SPGradient* swatch) { - char block[1024]; - FILE *f = Inkscape::IO::fopen_utf8name( filename, "r" ); - if ( f ) { - char* result = fgets( block, sizeof(block), f ); - if ( result ) { - if ( strncmp( "GIMP Palette", block, 12 ) == 0 ) { - bool inHeader = true; - bool hasErr = false; - - SwatchPage *onceMore = new SwatchPage(); - - do { - result = fgets( block, sizeof(block), f ); - block[sizeof(block) - 1] = 0; - if ( result ) { - if ( block[0] == '#' ) { - // ignore comment - } else { - char *ptr = block; - // very simple check for header versus entry - while ( *ptr == ' ' || *ptr == '\t' ) { - ptr++; + if (_currentDesktop && _currentDocument) { + SPItem* it = _currentDesktop->selection->singleItem(); + if (it) { + if (it->style->stroke.isSet()) { + if (it->style->stroke.isPaintserver()) { + SPPaintServer * server = it->style->getStrokePaintServer(); + if (SP_IS_GRADIENT(server)) { + SPGradient *grad = SP_GRADIENT(server)->getVector(); + Inkscape::XML::Node * repr = grad->getRepr(); + Inkscape::XML::Node * drepr = swatch->getRepr(); + if (repr != drepr && grad != swatch) { + while (SPStop* olds = swatch->getFirstStop()) { + olds->deleteObject(); } - if ( (*ptr == 0) || (*ptr == '\r') || (*ptr == '\n') ) { - // blank line. skip it. - } else if ( '0' <= *ptr && *ptr <= '9' ) { - // should be an entry link - inHeader = false; - ptr = block; - Glib::ustring name(""); - skipWhitespace(ptr); - if ( *ptr ) { - int r = 0; - int g = 0; - int b = 0; - hasErr = parseNum(ptr, r); - if ( !hasErr ) { - skipWhitespace(ptr); - hasErr = parseNum(ptr, g); - } - if ( !hasErr ) { - skipWhitespace(ptr); - hasErr = parseNum(ptr, b); - } - if ( !hasErr && *ptr ) { - char* n = trim(ptr); - if (n != NULL) { - name = g_dpgettext2(NULL, "Palette", n); - } - } - if ( !hasErr ) { - // Add the entry now - Glib::ustring nameStr(name); - ColorItem* item = new ColorItem( r, g, b, nameStr ); - onceMore->_colors.push_back(item); - } - } else { - hasErr = true; - } - } else { - if ( !inHeader ) { - // Hmmm... probably bad. Not quite the format we want? - hasErr = true; - } else { - char* sep = strchr(result, ':'); - if ( sep ) { - *sep = 0; - char* val = trim(sep + 1); - char* name = trim(result); - if ( *name ) { - if ( strcmp( "Name", name ) == 0 ) - { - onceMore->_name = val; - } - else if ( strcmp( "Columns", name ) == 0 ) - { - gchar* endPtr = 0; - guint64 numVal = g_ascii_strtoull( val, &endPtr, 10 ); - if ( (numVal == G_MAXUINT64) && (ERANGE == errno) ) { - // overflow - } else if ( (numVal == 0) && (endPtr == val) ) { - // failed conversion - } else { - onceMore->_prefWidth = numVal; - } - } - } else { - // error - hasErr = true; - } - } else { - // error - hasErr = true; - } - } + for (SPStop* news = grad->getVector()->getFirstStop(); news != NULL; news = news->getNextStop()) { + Inkscape::XML::Node* clone = news->getRepr()->duplicate(_currentDocument->getReprDoc()); + swatch->appendChildRepr(clone); + Inkscape::GC::release(clone); + } + swatch->setSwatch(); + if (!_noLink.get_active()) { + sp_item_set_gradient(it, sp_gradient_ensure_vector_normalized(swatch), SP_IS_RADIALGRADIENT(swatch) ? SP_GRADIENT_TYPE_RADIAL : SP_GRADIENT_TYPE_LINEAR, Inkscape::FOR_STROKE); } + DocumentUndo::done(_currentDocument, SP_VERB_DIALOG_SWATCHES, _("Set Gradient Swatch")); } } - } while ( result && !hasErr ); - if ( !hasErr ) { - if (user) - userSwatchPages.push_back(onceMore); - else - systemSwatchPages.push_back(onceMore); -#if ENABLE_MAGIC_COLORS - ColorItem::_wireMagicColors( onceMore ); -#endif // ENABLE_MAGIC_COLORS - } else { - delete onceMore; + } else if (it->style->stroke.isColor()) { + while (SPStop* olds = swatch->getFirstStop()) { + olds->deleteObject(); + } + addStop(swatch->getRepr(), it->style->stroke.value.color.toString(), SP_SCALE24_TO_FLOAT(it->style->stroke_opacity.value), "0"); + swatch->setSwatch(); + if (!_noLink.get_active()) { + SPGradient* normalized = sp_gradient_ensure_vector_normalized(swatch); + sp_item_set_gradient(it, normalized, SP_GRADIENT_TYPE_LINEAR, Inkscape::FOR_STROKE); + } + DocumentUndo::done(_currentDocument, SP_VERB_DIALOG_SWATCHES, _("Set Color Swatch")); } } } + } +} - fclose(f); +void SwatchesPanel::MoveSwatchDown(SPGradient* swatch) +{ + if (_currentDocument && swatch) { + SPObject* next = swatch->next; + while (next && (!SP_IS_GRADIENT(next) || !(SP_GRADIENT(next)->isSwatch()))) { + next = next->next; + } + if (next) { + Inkscape::XML::Node* repr = swatch->getRepr(); + repr->parent()->changeOrder(repr, next->getRepr()); + DocumentUndo::done(_currentDocument, SP_VERB_DIALOG_SWATCHES, _("Move Swatch Right")); + } } } -static bool -compare_swatch_names(SwatchPage const *a, SwatchPage const *b) { +void SwatchesPanel::MoveSwatchUp(SPGradient* swatch) +{ + if (_currentDocument && swatch) { + SPObject* g = NULL; + SPObject* next = swatch->parent->firstChild(); + while (next && next != swatch) { + if (SP_IS_GRADIENT(next) && SP_GRADIENT(next)->isSwatch()) { + g = next; + } + next = next->next; + } + if (g) { + g = g->getPrev(); + Inkscape::XML::Node* repr = swatch->getRepr(); + repr->parent()->changeOrder(repr, g ? g->getRepr() : NULL); + DocumentUndo::done(_currentDocument, SP_VERB_DIALOG_SWATCHES, _("Move Swatch Left")); + } + } +} - return g_utf8_collate(a->_name.c_str(), b->_name.c_str()) < 0; +void SwatchesPanel::RemoveSwatch(SPGradient* swatch) +{ + if (_currentDocument) { + if (swatch->isReferenced()) { + Inkscape::XML::Node * repr = swatch->getRepr(); + repr->parent()->removeChild(repr); + _currentDocument->getDefs()->getRepr()->appendChild(repr); + SP_GRADIENT(_currentDocument->getObjectByRepr(repr))->setSwatch(false); + } else { + swatch->deleteObject(false); + } + } } -static void loadEmUp() +void SwatchesPanel::_setSelectionSwatch(SPGradient* swatch, bool isStroke) { - static bool beenHere = false; - gboolean userPalete = true; - if ( !beenHere ) { - beenHere = true; - - std::list sources; - sources.push_back( profile_path("palettes") ); - sources.push_back( g_strdup(INKSCAPE_PALETTESDIR) ); - sources.push_back( g_strdup(CREATE_PALETTESDIR) ); - - // Use this loop to iterate through a list of possible document locations. - while (!sources.empty()) { - gchar *dirname = sources.front(); - if ( Inkscape::IO::file_test( dirname, G_FILE_TEST_EXISTS ) - && Inkscape::IO::file_test( dirname, G_FILE_TEST_IS_DIR )) { - GError *err = 0; - GDir *directory = g_dir_open(dirname, 0, &err); - if (!directory) { - gchar *safeDir = Inkscape::IO::sanitizeString(dirname); - g_warning(_("Palettes directory (%s) is unavailable."), safeDir); - g_free(safeDir); + if (_currentDocument) { + if (swatch) { + if (_noLink.get_active()) { + if (swatch->isSolid()) { + ColorRGBA rgba(swatch->getFirstStop()->getEffectiveColor().toRGBA32(swatch->getFirstStop()->opacity)); + sp_desktop_set_color(_currentDesktop, rgba, false, !isStroke); } else { - gchar *filename = 0; - while ((filename = (gchar *)g_dir_read_name(directory)) != NULL) { - gchar* lower = g_ascii_strdown( filename, -1 ); -// if ( g_str_has_suffix(lower, ".gpl") ) { - if ( !g_str_has_suffix(lower, "~") ) { - gchar* full = g_build_filename(dirname, filename, NULL); - if ( !Inkscape::IO::file_test( full, G_FILE_TEST_IS_DIR ) ) { - _loadPaletteFile(full, userPalete); - } - g_free(full); - } -// } - g_free(lower); - } - g_dir_close(directory); + SPCSSAttr *css = sp_repr_css_attr_new(); + sp_repr_css_set_property(css, isStroke ? "stroke-opacity" : "fill-opacity", "1.0"); + + Inkscape::XML::Node * clone = swatch->getRepr()->duplicate(_currentDocument->getReprDoc()); + _currentDocument->getDefs()->appendChildRepr(clone); + SPGradient* grad = SP_GRADIENT(_currentDocument->getObjectByRepr(clone)); + Inkscape::GC::release(clone); + grad->setSwatch(false); + SPGradient* normalized = sp_gradient_ensure_vector_normalized(grad); +// for (GSList const * it = _currentDesktop->selection->itemList(); it != NULL; it = it->next) { +// sp_desktop_apply_css_recursive(SP_ITEM(it->data), css, true); +// sp_item_set_gradient(SP_ITEM(it->data), normalized, SP_IS_RADIALGRADIENT(normalized) ? SP_GRADIENT_TYPE_RADIAL : SP_GRADIENT_TYPE_LINEAR, isStroke ? Inkscape::FOR_STROKE : Inkscape::FOR_FILL); +// } + sp_desktop_set_style(_currentDesktop, css); + sp_desktop_set_gradient(_currentDesktop, normalized, !isStroke); + sp_repr_css_attr_unref (css); } + } else { + SPCSSAttr *css = sp_repr_css_attr_new(); + sp_repr_css_set_property(css, isStroke ? "stroke-opacity" : "fill-opacity", "1.0"); + + SPGradient* normalized = sp_gradient_ensure_vector_normalized(swatch); +// for (GSList const * it = _currentDesktop->selection->itemList(); it != NULL; it = it->next) { +// sp_desktop_apply_css_recursive(SP_ITEM(it->data), css, true); +// sp_item_set_gradient(SP_ITEM(it->data), normalized, SP_IS_RADIALGRADIENT(normalized) ? SP_GRADIENT_TYPE_RADIAL : SP_GRADIENT_TYPE_LINEAR, isStroke ? Inkscape::FOR_STROKE : Inkscape::FOR_FILL); +// } + sp_desktop_set_style(_currentDesktop, css); + sp_desktop_set_gradient(_currentDesktop, normalized, !isStroke); + sp_repr_css_attr_unref (css); } - - // toss the dirname - g_free(dirname); - sources.pop_front(); - userPalete = false; + } else { + SPCSSAttr *css = sp_repr_css_attr_new (); + sp_repr_css_set_property (css, isStroke ? "stroke" : "fill", "none"); + sp_desktop_set_style(_currentDesktop, css); + } + if (isStroke) { + DocumentUndo::done(_currentDocument, SP_VERB_DIALOG_SWATCHES, _("Set item stroke swatch")); + } else { + DocumentUndo::done(_currentDocument, SP_VERB_DIALOG_SWATCHES, _("Set item fill swatch")); } } +} - // Sort the list of swatches by name, grouped by user/system - userSwatchPages.sort(compare_swatch_names); - systemSwatchPages.sort(compare_swatch_names); +void SwatchesPanel::_swatchClicked(GdkEventButton* event, SPGradient* swatch) +{ + if (_currentDesktop) { + if (event->button == 3) { + Gtk::Menu * menu = Gtk::manage(new Gtk::Menu()); + + Gtk::MenuItem* mi; + + Glib::ustring us = Glib::ustring::compose("%1", swatch ? (swatch->label() ? swatch->label() : swatch->getId()) : _("[None]")); + mi = Gtk::manage(new Gtk::MenuItem(swatch ? (swatch->label() ? swatch->label() : swatch->getId()) : _("[None]"))); + Gtk::Label* namelbl = dynamic_cast(mi->get_child()); + if (namelbl) { + namelbl->set_markup(us); + } + mi->show(); + mi->set_sensitive(false); + menu->append(*mi); + + Gtk::SeparatorMenuItem* sep; + sep = manage(new Gtk::SeparatorMenuItem()); + sep->show(); + menu->append(*sep); + + mi = Gtk::manage(new Gtk::MenuItem(_("Set Fill"))); + mi->signal_activate().connect_notify(sigc::bind(sigc::mem_fun(*this, &SwatchesPanel::_setSelectionSwatch), swatch, false)); + mi->show(); + mi->set_sensitive(_currentDesktop && !_currentDesktop->selection->isEmpty()); + menu->append(*mi); + + mi = Gtk::manage(new Gtk::MenuItem(_("Set Stroke"))); + mi->signal_activate().connect_notify(sigc::bind(sigc::mem_fun(*this, &SwatchesPanel::_setSelectionSwatch), swatch, true)); + mi->show(); + mi->set_sensitive(_currentDesktop && !_currentDesktop->selection->isEmpty()); + menu->append(*mi); + + if (swatch) { + sep = manage(new Gtk::SeparatorMenuItem()); + sep->show(); + menu->append(*sep); + + mi = Gtk::manage(new Gtk::MenuItem(_("Set to Selected Fill"))); + mi->signal_activate().connect_notify(sigc::bind(sigc::mem_fun(*this, &SwatchesPanel::SetSelectedFill), swatch)); + mi->show(); + mi->set_sensitive(_currentDesktop && _currentDesktop->selection->singleItem()); + menu->append(*mi); + + mi = Gtk::manage(new Gtk::MenuItem(_("Set to Selected Stroke"))); + mi->signal_activate().connect_notify(sigc::bind(sigc::mem_fun(*this, &SwatchesPanel::SetSelectedStroke), swatch)); + mi->show(); + mi->set_sensitive(_currentDesktop && _currentDesktop->selection->singleItem()); + menu->append(*mi); + + + sep = manage(new Gtk::SeparatorMenuItem()); + sep->show(); + menu->append(*sep); + + mi = Gtk::manage(new Gtk::MenuItem(_("Move Left"))); + mi->signal_activate().connect_notify(sigc::bind(sigc::mem_fun(*this, &SwatchesPanel::MoveSwatchUp), swatch)); + mi->show(); + menu->append(*mi); + + mi = Gtk::manage(new Gtk::MenuItem(_("Move Right"))); + mi->signal_activate().connect_notify(sigc::bind(sigc::mem_fun(*this, &SwatchesPanel::MoveSwatchDown), swatch)); + mi->show(); + menu->append(*mi); + + sep = manage(new Gtk::SeparatorMenuItem()); + sep->show(); + menu->append(*sep); + + mi = Gtk::manage(new Gtk::MenuItem(_("Remove"))); + mi->signal_activate().connect_notify(sigc::bind(sigc::mem_fun(*this, &SwatchesPanel::RemoveSwatch), swatch)); + mi->show(); + menu->append(*mi); + } + menu->popup(event->button, event->time); + } else if (!_currentDesktop->selection->isEmpty()) { + _setSelectionSwatch(swatch, event->state & GDK_SHIFT_MASK); + } + } } +void SwatchesPanel::MoveDown(SPGroup* page) +{ + if (_currentDocument && page) { + SPObject* next = page->next; + while (next && !SP_IS_GROUP(next)) { + next = next->next; + } + if (next) { + Inkscape::XML::Node* repr = page->getRepr(); + repr->parent()->changeOrder(repr, next->getRepr()); + DocumentUndo::done(_currentDocument, SP_VERB_DIALOG_SWATCHES, _("Move Swatch Down")); + } + } +} - -SwatchesPanel& SwatchesPanel::getInstance() +void SwatchesPanel::MoveUp(SPGroup* page) { - return *new SwatchesPanel(); + if (_currentDocument && page) { + SPObject* g = NULL; + SPObject* next = page->parent->firstChild(); + while (next && next != page) { + if (SP_IS_GROUP(next)) { + g = next; + } + next = next->next; + } + if (g) { + g = g->getPrev(); + Inkscape::XML::Node* repr = page->getRepr(); + repr->parent()->changeOrder(repr, g ? g->getRepr() : NULL); + DocumentUndo::done(_currentDocument, SP_VERB_DIALOG_SWATCHES, _("Move Swatch Up")); + } + } } +void SwatchesPanel::Remove(SPGroup* page) +{ + if (_currentDocument && page) { + std::vector toMove; + for(SPObject* obj = page->firstChild(); obj != NULL; obj = obj->next) { + if (SP_IS_GRADIENT(obj)) { + SPGradient* grad = SP_GRADIENT(obj); + if (grad->isReferenced()) { + toMove.push_back(grad->getRepr()); + } + } + } + while (!toMove.empty()) { + Inkscape::XML::Node * repr = toMove.back(); + toMove.pop_back(); + repr->parent()->removeChild(repr); + _currentDocument->getDefs()->getRepr()->appendChild(repr); + SP_GRADIENT(_currentDocument->getObjectByRepr(repr))->setSwatch(false); + } + page->deleteObject(false); + DocumentUndo::done(_currentDocument, SP_VERB_DIALOG_SWATCHES, _("Remove Swatch Group")); + } +} -/** - * Constructor - */ -SwatchesPanel::SwatchesPanel(gchar const* prefsPath) : - Inkscape::UI::Widget::Panel("", prefsPath, SP_VERB_DIALOG_SWATCHES, "", true), - _holder(0), - _clear(0), - _remove(0), - _currentIndex(0), - _currentDesktop(0), - _currentDocument(0) +void SwatchesPanel::AddSelectedFill(SPGroup* page) { - Gtk::RadioMenuItem* hotItem = 0; - _holder = new PreviewHolder(); - _clear = new ColorItem( ege::PaintDef::CLEAR ); - _remove = new ColorItem( ege::PaintDef::NONE ); - if (docPalettes.empty()) { - SwatchPage *docPalette = new SwatchPage(); - - docPalette->_name = "Auto"; - docPalettes[0] = docPalette; - } - - loadEmUp(); - if ( !systemSwatchPages.empty() ) { - SwatchPage* first = 0; - int index = 0; - Glib::ustring targetName; - if ( !_prefs_path.empty() ) { - Inkscape::Preferences *prefs = Inkscape::Preferences::get(); - targetName = prefs->getString(_prefs_path + "/palette"); - if (!targetName.empty()) { - if (targetName == "Auto") { - first = docPalettes[0]; - } else { - //index++; - std::vector pages = _getSwatchSets(); - for ( std::vector::iterator iter = pages.begin(); iter != pages.end(); ++iter ) { - if ( (*iter)->_name == targetName ) { - first = *iter; - break; + if (_currentDesktop && _currentDocument) { + SPItem* it = _currentDesktop->selection->singleItem(); + if (it) { + if (it->style->fill.isSet()) { + if (it->style->fill.isPaintserver()) { + SPPaintServer * server = it->style->getFillPaintServer(); + if (SP_IS_GRADIENT(server)) { + SPGradient *grad = SP_GRADIENT(server)->getVector(); + if (_noLink.get_active()) { + Inkscape::XML::Node * clone = grad->getRepr()->duplicate(_currentDocument->getReprDoc()); + clone->setAttribute( "osb:paint", "gradient", 0 ); + if (page) { + page->appendChildRepr(clone); + } else { + _currentDocument->getDefs()->appendChildRepr(clone); + } + Inkscape::GC::release(clone); + DocumentUndo::done(_currentDocument, SP_VERB_DIALOG_SWATCHES, _("Add Gradient Swatch")); + } else if (grad->isSwatch()) { + Inkscape::XML::Node * repr = grad->getRepr(); + Inkscape::XML::Node * clone = repr->duplicate(_currentDocument->getReprDoc()); + if (page) { + page->appendChildRepr(clone); + } else { + _currentDocument->getDefs()->appendChildRepr(clone); + } + SPGradient *newgrad = SP_GRADIENT(_currentDocument->getObjectByRepr(clone)); + + sp_item_set_gradient(it, sp_gradient_ensure_vector_normalized(newgrad), SP_IS_RADIALGRADIENT(newgrad) ? SP_GRADIENT_TYPE_RADIAL : SP_GRADIENT_TYPE_LINEAR, Inkscape::FOR_FILL); + Inkscape::GC::release(clone); + DocumentUndo::done(_currentDocument, SP_VERB_DIALOG_SWATCHES, _("Add Gradient Swatch")); + } else { + Inkscape::XML::Node * repr = grad->getRepr(); + Inkscape::XML::Node * drepr = page ? page->getRepr() : _currentDocument->getDefs()->getRepr(); + if (repr->parent() != drepr) { + repr->parent()->removeChild(repr); + drepr->appendChild(repr); + } + SP_GRADIENT(_currentDocument->getObjectByRepr(repr))->setSwatch(); + DocumentUndo::done(_currentDocument, SP_VERB_DIALOG_SWATCHES, _("Add Gradient Swatch")); } - index++; } + } else if (it->style->fill.isColor()) { + Inkscape::XML::Node *grad = _currentDocument->getReprDoc()->createElement("svg:linearGradient"); + grad->setAttribute( "osb:paint", "solid", 0 ); + addStop(grad, it->style->fill.value.color.toString(), SP_SCALE24_TO_FLOAT(it->style->fill_opacity.value), "0"); + if (page) { + page->appendChild(grad); + } else { + _currentDocument->getDefs()->appendChild(grad); + } + SPGradient* normalized = sp_gradient_ensure_vector_normalized(SP_GRADIENT(_currentDocument->getObjectByRepr(grad))); + Inkscape::GC::release(grad); + if (!_noLink.get_active()) { + sp_item_set_gradient(it, normalized, SP_GRADIENT_TYPE_LINEAR, Inkscape::FOR_FILL); + } + DocumentUndo::done(_currentDocument, SP_VERB_DIALOG_SWATCHES, _("Add Color Swatch")); } } } + } +} - if ( !first ) { - first = docPalettes[0]; - _currentIndex = 0; - } else { - _currentIndex = index; - } - - _rebuild(); - - Gtk::RadioMenuItem::Group groupOne; - - int i = 0; - std::vector swatchSets = _getSwatchSets(); - for ( std::vector::iterator it = swatchSets.begin(); it != swatchSets.end(); ++it) { - SwatchPage* curr = *it; - Gtk::RadioMenuItem* single = manage(new Gtk::RadioMenuItem(groupOne, curr->_name)); - if ( curr == first ) { - hotItem = single; +void SwatchesPanel::AddSelectedStroke(SPGroup* page) +{ + if (_currentDesktop && _currentDocument) { + SPItem* it = _currentDesktop->selection->singleItem(); + if (it) { + if (it->style->stroke.isSet()) { + if (it->style->stroke.isPaintserver()) { + SPPaintServer * server = it->style->getStrokePaintServer(); + if (SP_IS_GRADIENT(server)) { + SPGradient *grad = SP_GRADIENT(server)->getVector(); + if (_noLink.get_active()) { + Inkscape::XML::Node * clone = grad->getRepr()->duplicate(_currentDocument->getReprDoc()); + clone->setAttribute( "osb:paint", "gradient", 0 ); + if (page) { + page->appendChildRepr(clone); + } else { + _currentDocument->getDefs()->appendChildRepr(clone); + } + Inkscape::GC::release(clone); + DocumentUndo::done(_currentDocument, SP_VERB_DIALOG_SWATCHES, _("Add Gradient Swatch")); + } else if (grad->isSwatch()) { + Inkscape::XML::Node * repr = grad->getRepr(); + Inkscape::XML::Node * clone = repr->duplicate(_currentDocument->getReprDoc()); + if (page) { + page->appendChildRepr(clone); + } else { + _currentDocument->getDefs()->appendChildRepr(clone); + } + SPGradient *newgrad = SP_GRADIENT(_currentDocument->getObjectByRepr(clone)); + + sp_item_set_gradient(it, sp_gradient_ensure_vector_normalized(newgrad), SP_IS_RADIALGRADIENT(newgrad) ? SP_GRADIENT_TYPE_RADIAL : SP_GRADIENT_TYPE_LINEAR, Inkscape::FOR_STROKE); + Inkscape::GC::release(clone); + DocumentUndo::done(_currentDocument, SP_VERB_DIALOG_SWATCHES, _("Add Gradient Swatch")); + } else { + Inkscape::XML::Node * repr = grad->getRepr(); + Inkscape::XML::Node * drepr = page ? page->getRepr() : _currentDocument->getDefs()->getRepr(); + if (repr->parent() != drepr) { + repr->parent()->removeChild(repr); + drepr->appendChild(repr); + } + SP_GRADIENT(_currentDocument->getObjectByRepr(repr))->setSwatch(); + DocumentUndo::done(_currentDocument, SP_VERB_DIALOG_SWATCHES, _("Add Gradient Swatch")); + } + } + } else if (it->style->stroke.isColor()) { + Inkscape::XML::Node *grad = _currentDocument->getReprDoc()->createElement("svg:linearGradient"); + grad->setAttribute( "osb:paint", "solid", 0 ); + addStop(grad, it->style->stroke.value.color.toString(), SP_SCALE24_TO_FLOAT(it->style->stroke_opacity.value), "0"); + if (page) { + page->appendChild(grad); + } else { + _currentDocument->getDefs()->appendChild(grad); + } + SPGradient* normalized = sp_gradient_ensure_vector_normalized(SP_GRADIENT(_currentDocument->getObjectByRepr(grad))); + Inkscape::GC::release(grad); + if (!_noLink.get_active()) { + sp_item_set_gradient(it, normalized, SP_GRADIENT_TYPE_LINEAR, Inkscape::FOR_STROKE); + } + DocumentUndo::done(_currentDocument, SP_VERB_DIALOG_SWATCHES, _("Add Color Swatch")); + } } - _regItem( single, 3, i ); - - i++; } } +} - if (Glib::ustring(prefsPath) == "/dialogs/swatches") { - Gtk::Requisition sreq; -#if WITH_GTKMM_3_0 - Gtk::Requisition sreq_natural; - get_preferred_size(sreq_natural, sreq); -#else - sreq = size_request(); -#endif - int minHeight = 60; - if (sreq.height < minHeight) { - set_size_request(70, minHeight); - } +void SwatchesPanel::_addBIButtonClicked(GdkEventButton* event) +{ + if (popUpImportMenu) { + popUpImportMenu->popup(event->button, event->time); } +} - _getContents()->pack_start(*_holder, Gtk::PACK_EXPAND_WIDGET); - _setTargetFillable(_holder); - - show_all_children(); - - restorePanelPrefs(); - if ( hotItem ) { - hotItem->set_active(); +void SwatchesPanel::NewGroupBI() +{ + if (_currentDocument) { + Inkscape::XML::Node * page = SwatchDocument->getReprDoc()->createElement("svg:g"); + gchar *id=NULL; + do { + g_free(id); + id = g_strdup_printf("page%d", page_suffix++); + } while (SwatchDocument->getObjectById(id)); + + page->setAttribute("id", id); + + SwatchDocument->getDefs()->appendChild(page); + sp_repr_save_file(SwatchDocument->getReprDoc(), SwatchFile, SP_SVG_NS_URI); } } -SwatchesPanel::~SwatchesPanel() +void SwatchesPanel::NewGroup() { - _trackDocument( this, 0 ); - - _documentConnection.disconnect(); - _selChanged.disconnect(); - - if ( _clear ) { - delete _clear; - } - if ( _remove ) { - delete _remove; - } - if ( _holder ) { - delete _holder; + if (_currentDocument) { + Inkscape::XML::Node * page = _currentDocument->getReprDoc()->createElement("svg:g"); + gchar *id=NULL; + do { + g_free(id); + id = g_strdup_printf("page%d", page_suffix++); + } while (_currentDocument->getObjectById(id)); + + page->setAttribute("id", id); + + _currentDocument->getDefs()->appendChild(page); + DocumentUndo::done(_currentDocument, SP_VERB_DIALOG_SWATCHES, _("New Swatch Group")); } } -void SwatchesPanel::setOrientation(SPAnchorType how) +void SwatchesPanel::SaveAs() { - // Must call the parent class or bad things might happen - Inkscape::UI::Widget::Panel::setOrientation( how ); - - if ( _holder ) - { - _holder->setOrientation(SP_ANCHOR_SOUTH); + if (_currentDocument) { + Inkscape::XML::Node * page = _currentDocument->getReprDoc()->createElement("svg:g"); + gchar *id=NULL; + do { + g_free(id); + id = g_strdup_printf("page%d", page_suffix++); + } while (_currentDocument->getObjectById(id)); + + page->setAttribute("id", id); + + std::vector toMove; + for (SPObject *it = _currentDocument->getDefs()->firstChild(); it != NULL; it = it->next) { + if (SP_IS_GRADIENT(it)) { + SPGradient* grad = SP_GRADIENT(it); + if (grad->isSwatch()) { + toMove.push_back(grad->getRepr()); + } + } + } + while (!toMove.empty()) { + Inkscape::XML::Node* repr = toMove.back(); + toMove.pop_back(); + repr->parent()->removeChild(repr); + page->appendChild(repr); + } + _currentDocument->getDefs()->appendChild(page); + DocumentUndo::done(_currentDocument, SP_VERB_DIALOG_SWATCHES, _("Save Swatch Group")); } } -void SwatchesPanel::setDesktop( SPDesktop* desktop ) +void SwatchesPanel::Duplicate(SPGroup* oldpage) { - if ( desktop != _currentDesktop ) { - if ( _currentDesktop ) { - _documentConnection.disconnect(); - _selChanged.disconnect(); + if (_currentDocument) { + Inkscape::XML::Node * page = _currentDocument->getReprDoc()->createElement("svg:g"); + gchar *id=NULL; + do { + g_free(id); + id = g_strdup_printf("page%d", page_suffix++); + } while (_currentDocument->getObjectById(id)); + + page->setAttribute("id", id); + if (oldpage->label()) page->setAttribute("inkscape:label", oldpage->label()); + + for (SPObject *it = oldpage->firstChild(); it != NULL; it = it->next) { + if (SP_IS_GRADIENT(it)) { + SPGradient* grad = SP_GRADIENT(it); + if (grad->isSwatch()) { + Inkscape::XML::Node * copy = grad->getRepr()->duplicate(_currentDocument->getReprDoc()); + page->appendChild(copy); + Inkscape::GC::release(copy); + } + } } + _currentDocument->getDefs()->appendChild(page); + DocumentUndo::done(_currentDocument, SP_VERB_DIALOG_SWATCHES, _("Duplicate Swatch Group")); + } +} - _currentDesktop = desktop; +void SwatchesPanel::_lblClick(GdkEventButton* event, SPGroup* page) +{ + Gtk::Menu * menu = Gtk::manage(new Gtk::Menu()); + + Gtk::MenuItem* mi; + Glib::ustring us = Glib::ustring::compose("%1", page ? (page->label() ? page->label() : page->getId()) : _("[Base]")); + mi = Gtk::manage(new Gtk::MenuItem(page ? (page->label() ? page->label() : page->getId()) : _("[Base]"))); + Gtk::Label* namelbl = dynamic_cast(mi->get_child()); + if (namelbl) { + namelbl->set_markup(us); + } + mi->show(); + mi->set_sensitive(false); + menu->append(*mi); + + Gtk::SeparatorMenuItem* sep; + sep = manage(new Gtk::SeparatorMenuItem()); + sep->show(); + menu->append(*sep); + + mi = Gtk::manage(new Gtk::MenuItem(_("Add Selected Fill"))); + mi->signal_activate().connect_notify(sigc::bind(sigc::mem_fun(*this, &SwatchesPanel::AddSelectedFill), page)); + mi->show(); + mi->set_sensitive(_currentDesktop && _currentDesktop->selection->singleItem()); + menu->append(*mi); + + mi = Gtk::manage(new Gtk::MenuItem(_("Add Selected Stroke"))); + mi->signal_activate().connect_notify(sigc::bind(sigc::mem_fun(*this, &SwatchesPanel::AddSelectedStroke), page)); + mi->show(); + mi->set_sensitive(_currentDesktop && _currentDesktop->selection->singleItem()); + menu->append(*mi); + + sep = manage(new Gtk::SeparatorMenuItem()); + sep->show(); + menu->append(*sep); + + if (page) { + + mi = Gtk::manage(new Gtk::MenuItem(_("Move Up"))); + mi->signal_activate().connect_notify(sigc::bind(sigc::mem_fun(*this, &SwatchesPanel::MoveUp), page)); + mi->show(); + menu->append(*mi); + + mi = Gtk::manage(new Gtk::MenuItem(_("Move Down"))); + mi->signal_activate().connect_notify(sigc::bind(sigc::mem_fun(*this, &SwatchesPanel::MoveDown), page)); + mi->show(); + menu->append(*mi); + + sep = manage(new Gtk::SeparatorMenuItem()); + sep->show(); + menu->append(*sep); + + mi = Gtk::manage(new Gtk::MenuItem(_("Duplicate"))); + mi->signal_activate().connect_notify(sigc::bind(sigc::mem_fun(*this, &SwatchesPanel::Duplicate), page)); + mi->show(); + menu->append(*mi); + + sep = manage(new Gtk::SeparatorMenuItem()); + sep->show(); + menu->append(*sep); + + mi = Gtk::manage(new Gtk::MenuItem(_("Remove"))); + mi->signal_activate().connect_notify(sigc::bind(sigc::mem_fun(*this, &SwatchesPanel::Remove), page)); + mi->show(); + menu->append(*mi); + } else { + mi = Gtk::manage(new Gtk::MenuItem(_("Create New Group"))); + mi->signal_activate().connect_notify(sigc::mem_fun(*this, &SwatchesPanel::NewGroup)); + mi->show(); + menu->append(*mi); + + mi = Gtk::manage(new Gtk::MenuItem(_("Save As New Group"))); + mi->signal_activate().connect_notify(sigc::mem_fun(*this, &SwatchesPanel::SaveAs)); + mi->show(); + menu->append(*mi); + } + + menu->popup(event->button, event->time); +} - if ( desktop ) { - _currentDesktop->selection->connectChanged( - sigc::hide(sigc::mem_fun(*this, &SwatchesPanel::_updateFromSelection))); +void SwatchesPanel::_defsChanged() +{ + if (_storeDoc) { + _storeDoc->clear(); + } + + while (!docWatchers.empty()) { + Inkscape::XML::NodeObserver* w = docWatchers.back(); + docWatchers.pop_back(); + delete w; + } + + std::vector tableChildren = _insideTable.get_children(); + for (std::vector::iterator c = tableChildren.begin(); c != tableChildren.end(); ++c) { + _insideTable.remove(**c); + } + + if (_currentDocument) { + Gtk::EventBox* eb; + Gtk::Label* lbl; + if (_showlabels) { + eb = Gtk::manage(new Gtk::EventBox()); + eb->add_events(Gdk::BUTTON_PRESS_MASK); + eb->signal_button_press_event().connect_notify(sigc::bind(sigc::mem_fun(*this, &SwatchesPanel::_lblClick), NULL)); + + lbl = Gtk::manage(new Gtk::Label(_("[Base]"))); + eb->add(*lbl); + _insideTable.attach( *eb, 0, 1, 0, 1, Gtk::FILL|Gtk::EXPAND, Gtk::FILL|Gtk::EXPAND , 5, 0); + } + Glib::ustring str1 = Glib::ustring(_("[None]")); + ColorItem* item = Gtk::manage(new ColorItem(NULL, NULL, NULL, str1)); + //item->signal_button_press_event().connect_notify(sigc::bind(sigc::mem_fun(*this, &SwatchesPanel::_swatchClicked), NULL)); + item->setName(_("[None]")); + _insideTable.attach( *item, _showlabels ? 1 : 0, _showlabels ? 2 : 1, 0, 1, Gtk::FILL|Gtk::EXPAND, Gtk::FILL|Gtk::EXPAND ); + + unsigned int i = 1; + for (SPObject *it = _currentDocument->getDefs()->firstChild(); it != NULL; it = it->next) { + if (SP_IS_GRADIENT(it)) { + SPGradient* grad = SP_GRADIENT(it); + if (grad->hasStops()) { + + GradientWatcher* w = new GradientWatcher(this, grad); + docWatchers.push_back(w); + + if (grad->isSwatch()) { + + for (SPStop* s = grad->getFirstStop(); s != NULL; s = s->getNextStop()) { + StopWatcher* sw = new StopWatcher(this, s); + docWatchers.push_back(sw); + } - _currentDesktop->selection->connectModified( - sigc::hide(sigc::hide(sigc::mem_fun(*this, &SwatchesPanel::_updateFromSelection)))); + if (_storeDoc) { + Gtk::TreeModel::iterator iter = _storeDoc->append(); + Gtk::TreeModel::Row row = *iter; + row[_modelDoc->_colObject] = grad; + row[_modelDoc->_colLabel] = grad->label() ? grad->label() : grad->getId(); + GdkPixbuf* pixb = sp_gradient_to_pixbuf (grad, 64, 18); + row[_modelDoc->_colPixbuf] = Glib::wrap(pixb); + } + Glib::ustring str2 = Glib::ustring(it->label() ? it->label() : it->getId()); + item = Gtk::manage(new ColorItem(NULL, NULL, NULL, str2)); + item->setGradient(grad); + //item->colorItemHandleButtonPress().connect_notify(sigc::bind(sigc::mem_fun(*this, &SwatchesPanel::_swatchClicked), grad)); + item->setName(it->label() ? it->label() : it->getId()); + if (_showlabels) { + _insideTable.attach( *item, 1 + (i % 20), 2 + (i % 20), i / 20, i / 20 + 1, Gtk::FILL|Gtk::EXPAND, Gtk::FILL|Gtk::EXPAND ); + } else { + _insideTable.attach( *item, i, i + 1, 0, 1, Gtk::FILL|Gtk::EXPAND, Gtk::FILL|Gtk::EXPAND ); + } - _currentDesktop->connectToolSubselectionChanged( - sigc::hide(sigc::mem_fun(*this, &SwatchesPanel::_updateFromSelection))); + i++; + } + } + } + } + + for (SPObject *it = _currentDocument->getDefs()->firstChild(); it != NULL; it = it->next) { + if (SP_IS_GROUP(it)) { + SwatchWatcher* w = new SwatchWatcher(this, it, false); + docWatchers.push_back(w); + + if (_showlabels) { + i += 20 - (i % 20); + eb = Gtk::manage(new Gtk::EventBox()); + eb->add_events(Gdk::BUTTON_PRESS_MASK); + eb->signal_button_press_event().connect_notify(sigc::bind(sigc::mem_fun(*this, &SwatchesPanel::_lblClick), SP_GROUP(it))); + lbl = Gtk::manage(new Gtk::Label(it->label() ? it->label() : it->getId())); + eb->add(*lbl); + _insideTable.attach( *eb, 0, 1, i / 20, i / 20 + 1, Gtk::FILL|Gtk::EXPAND, Gtk::FILL|Gtk::EXPAND , 5, 0); + } + + Gtk::TreeModel::iterator rowiter; + + if (_storeDoc) { + rowiter = _storeDoc->append(); + Gtk::TreeModel::Row row = *rowiter; + row[_modelDoc->_colObject] = it; + row[_modelDoc->_colLabel] = it->label() ? it->label() : it->getId(); + } + + for (SPObject *cit = it->firstChild(); cit != NULL; cit = cit->next) { + if (SP_IS_GRADIENT(cit)) { + SPGradient* grad = SP_GRADIENT(cit); + + if (grad->hasStops()) { + + GradientWatcher* w = new GradientWatcher(this, grad); + docWatchers.push_back(w); + + if (grad->isSwatch()) { + + for (SPStop* s = grad->getFirstStop(); s != NULL; s = s->getNextStop()) { + StopWatcher* sw = new StopWatcher(this, s); + docWatchers.push_back(sw); + } - sigc::bound_mem_functor1 first = sigc::mem_fun(*this, &SwatchesPanel::_setDocument); - sigc::slot base2 = first; - sigc::slot slot2 = sigc::hide<0>( base2 ); - _documentConnection = desktop->connectDocumentReplaced( slot2 ); + if (_storeDoc && rowiter) { + Gtk::TreeModel::iterator iter = _storeDoc->append(rowiter->children()); + Gtk::TreeModel::Row row = *iter; + row[_modelDoc->_colObject] = grad; + row[_modelDoc->_colLabel] = grad->label() ? grad->label() : grad->getId(); + GdkPixbuf* pixb = sp_gradient_to_pixbuf (grad, 64, 18); + row[_modelDoc->_colPixbuf] = Glib::wrap(pixb); - _setDocument( desktop->doc() ); - } else { - _setDocument(0); + _editDoc.expand_to_path(_storeDoc->get_path(iter)); + } + Glib::ustring str3= Glib::ustring(cit->label() ? cit->label() : cit->getId()); + item = Gtk::manage(new ColorItem(NULL, NULL, NULL, str3)); + item->setGradient(grad); + //item->signal_button_press_event().connect_notify(sigc::bind(sigc::mem_fun(*this, &SwatchesPanel::_swatchClicked), grad)); + item->setName(cit->label() ? cit->label() : cit->getId()); + if (_showlabels) { + _insideTable.attach( *item, 1 + (i % 20), 2 + (i % 20), i / 20, i / 20 + 1, Gtk::FILL|Gtk::EXPAND, Gtk::FILL|Gtk::EXPAND ); + } else { + _insideTable.attach( *item, i, i + 1, 0, 1, Gtk::FILL|Gtk::EXPAND, Gtk::FILL|Gtk::EXPAND ); + } + i++; + } + } + } + } + } } } + + _scroller.show_all_children(); + _scroller.queue_draw(); } - -class DocTrack +Gtk::MenuItem* SwatchesPanel::_addSwatchGroup(SPGroup* group, Gtk::TreeModel::Row* parentRow) { -public: - DocTrack(SPDocument *doc, sigc::connection &docDestroy, sigc::connection &gradientRsrcChanged, sigc::connection &defsChanged, sigc::connection &defsModified) : - doc(doc), - updatePending(false), - lastGradientUpdate(0.0), - docDestroy(docDestroy), - gradientRsrcChanged(gradientRsrcChanged), - defsChanged(defsChanged), - defsModified(defsModified) - { - if ( !timer ) { - timer = new Glib::Timer(); - refreshTimer = Glib::signal_timeout().connect( sigc::ptr_fun(handleTimerCB), 33 ); + Gtk::MenuItem* mi = manage(new Gtk::MenuItem(group->label() ? group->label() : group->getId(),1)); + Gtk::Menu* m = NULL; + + Gtk::TreeModel::Row* r; + if (_store) { + Gtk::TreeModel::iterator iter = parentRow ? _store->append(parentRow->children()) : _store->append(); + Gtk::TreeModel::Row row = *iter; + row[_model->_colObject] = group; + row[_model->_colLabel] = group->label() ? group->label() : group->getId(); + + if (SP_IS_GROUP(group->parent) && SP_GROUP(group->parent)->expanded()) { + _editBI.expand_to_path(_store->get_path(iter)); } - timerRefCount++; + r = &row; + } else { + r = NULL; } - - ~DocTrack() + + bool hasswatches = false; + for (SPObject * obj = group->firstChild(); obj != NULL; obj = obj->next) { - timerRefCount--; - if ( timerRefCount <= 0 ) { - refreshTimer.disconnect(); - timerRefCount = 0; - if ( timer ) { - timer->stop(); - delete timer; - timer = 0; + if (SP_IS_GROUP(obj)) { + if (!m) { + m = manage(new Gtk::Menu()); + m->show_all(); + mi->set_submenu(*m); + + Gtk::MenuItem* basemi = manage(new Gtk::MenuItem(_("[All]"))); + basemi->show(); + Gtk::Label* namelbl = dynamic_cast(basemi->get_child()); + if (namelbl) { + namelbl->set_markup(_("[All]")); + } + basemi->signal_activate().connect(sigc::bind(sigc::mem_fun(*this, &SwatchesPanel::_addSwatchButtonClicked), group, true)); + m->append(*basemi); + + Gtk::SeparatorMenuItem* sep = manage(new Gtk::SeparatorMenuItem()); + sep->show(); + m->append(*sep); } + SwatchWatcher* w = new SwatchWatcher(this, obj, true); + rootWatchers.push_back(w); + m->append(*_addSwatchGroup(SP_GROUP(obj), r)); + } else if (SP_IS_GRADIENT(obj)) { + hasswatches = true; } - if (doc) { - docDestroy.disconnect(); - gradientRsrcChanged.disconnect(); - defsChanged.disconnect(); - defsModified.disconnect(); - doc = NULL; + } + if (!m) { + mi->signal_activate().connect(sigc::bind(sigc::mem_fun(*this, &SwatchesPanel::_addSwatchButtonClicked), group, false)); + } else if (hasswatches) { + Glib::ustring us = Glib::ustring::compose("%1", group->label() ? group->label() : group->getId()); + Gtk::MenuItem* basemi = manage(new Gtk::MenuItem(group->label() ? group->label() : group->getId())); + basemi->show(); + Gtk::Label* namelbl = dynamic_cast(basemi->get_child()); + if (namelbl) { + namelbl->set_markup(us); } + basemi->signal_activate().connect(sigc::bind(sigc::mem_fun(*this, &SwatchesPanel::_addSwatchButtonClicked), group, false)); + m->prepend(*basemi); } + mi->show(); + return mi; +} - static bool handleTimerCB(); - - /** - * Checks if update should be queued or executed immediately. - * - * @return true if the update was queued and should not be immediately executed. - */ - static bool queueUpdateIfNeeded(SPDocument *doc); - - static Glib::Timer *timer; - static int timerRefCount; - static sigc::connection refreshTimer; - - SPDocument *doc; - bool updatePending; - double lastGradientUpdate; - sigc::connection docDestroy; - sigc::connection gradientRsrcChanged; - sigc::connection defsChanged; - sigc::connection defsModified; - -private: - DocTrack(DocTrack const &); // no copy - DocTrack &operator=(DocTrack const &); // no assign -}; - -Glib::Timer *DocTrack::timer = 0; -int DocTrack::timerRefCount = 0; -sigc::connection DocTrack::refreshTimer; +void SwatchesPanel::_swatchesChanged() +{ + while (!rootWatchers.empty()) { + Inkscape::XML::NodeObserver* w = rootWatchers.back(); + rootWatchers.pop_back(); + delete w; + } -static const double DOC_UPDATE_THREASHOLD = 0.090; + std::vector menuChildren = popUpMenu->get_children(); + for (std::vector::iterator c = menuChildren.begin(); c != menuChildren.end(); ++c) { + popUpMenu->remove(**c); + } + + if (_store) { + _store->clear(); + } + + Gtk::MenuItem* mi; + + for (SPObject * obj = SwatchDocument->getDefs()->firstChild(); obj != NULL; obj = obj->next) + { + if (SP_IS_GROUP(obj)) { + SwatchWatcher* w = new SwatchWatcher(this, obj, true); + rootWatchers.push_back(w); + popUpMenu->append(*_addSwatchGroup(SP_GROUP(obj), NULL)); + + } + } + Gtk::SeparatorMenuItem* sep = manage(new Gtk::SeparatorMenuItem()); + sep->show(); + popUpMenu->append(*sep); + + mi = manage(new Gtk::MenuItem(_("New Swatch Group..."),1)); + mi->signal_activate().connect(sigc::mem_fun(*this, &SwatchesPanel::NewGroup)); + mi->show(); + popUpMenu->append(*mi); + + mi = manage(new Gtk::MenuItem(_("Add Swatch File..."),1)); + mi->signal_activate().connect(sigc::bind(sigc::mem_fun(*this, &SwatchesPanel::_importButtonClicked), true, false)); + mi->show(); + popUpMenu->append(*mi); + + mi = manage(new Gtk::MenuItem(_("Import Swatch File..."),1)); + mi->signal_activate().connect(sigc::bind(sigc::mem_fun(*this, &SwatchesPanel::_importButtonClicked), true, true)); + mi->show(); + popUpMenu->append(*mi); +} -bool DocTrack::handleTimerCB() +void SwatchesPanel::_styleButton( Gtk::Button& btn, SPDesktop *desktop, unsigned int code, char const* iconName, char const* fallback ) { - double now = timer->elapsed(); + bool set = false; + + if ( iconName ) { + GtkWidget *child = sp_icon_new( Inkscape::ICON_SIZE_SMALL_TOOLBAR, iconName ); + gtk_widget_show( child ); + btn.add( *manage(Glib::wrap(child)) ); + btn.set_relief(Gtk::RELIEF_NONE); + set = true; + } - std::vector needCallback; - for (std::vector::iterator it = docTrackings.begin(); it != docTrackings.end(); ++it) { - DocTrack *track = *it; - if ( track->updatePending && ( (now - track->lastGradientUpdate) >= DOC_UPDATE_THREASHOLD) ) { - needCallback.push_back(track); + if ( desktop ) { + Verb *verb = Verb::get( code ); + if ( verb ) { + SPAction *action = verb->get_action(desktop); + if ( !set && action && action->image ) { + GtkWidget *child = sp_icon_new( Inkscape::ICON_SIZE_SMALL_TOOLBAR, action->image ); + gtk_widget_show( child ); + btn.add( *manage(Glib::wrap(child)) ); + set = true; + } } } + + btn.set_tooltip_text (fallback); + + if ( !set ) { + btn.set_label( fallback ); + } +} - for (std::vector::iterator it = needCallback.begin(); it != needCallback.end(); ++it) { - DocTrack *track = *it; - if ( std::find(docTrackings.begin(), docTrackings.end(), track) != docTrackings.end() ) { // Just in case one gets deleted while we are looping - // Note: calling handleDefsModified will call queueUpdateIfNeeded and thus update the time and flag. - SwatchesPanel::handleDefsModified(track->doc); +void SwatchesPanel::_addButtonClicked(GdkEventButton* event) { + if ( (event->type == GDK_BUTTON_PRESS) && (event->button == 3 || event->button == 1) ) { + if (popUpMenu) { + popUpMenu->popup(event->button, event->time); } } +} - return true; +void SwatchesPanel::NoLinkToggled() { + static Inkscape::Preferences *prefs = Inkscape::Preferences::get(); + Glib::ustring nolink = Glib::ustring::compose("%1/nolink", _prefs_path); + prefs->setBool(nolink, _noLink.get_active()); } -bool DocTrack::queueUpdateIfNeeded( SPDocument *doc ) +bool SwatchesPanel::_handleButtonEvent(GdkEventButton *event) { - bool deferProcessing = false; - for (std::vector::iterator it = docTrackings.begin(); it != docTrackings.end(); ++it) { - DocTrack *track = *it; - if ( track->doc == doc ) { - double now = timer->elapsed(); - double elapsed = now - track->lastGradientUpdate; - - if ( elapsed < DOC_UPDATE_THREASHOLD ) { - deferProcessing = true; - track->updatePending = true; - } else { - track->lastGradientUpdate = now; - track->updatePending = false; - } + static unsigned doubleclick = 0; + if ( (event->type == GDK_2BUTTON_PRESS) && (event->button == 1) ) { + doubleclick = 1; + } - break; + if ( event->type == GDK_BUTTON_RELEASE && doubleclick) { + doubleclick = 0; + Gtk::TreeModel::Path path; + Gtk::TreeViewColumn* col = 0; + int x = static_cast(event->x); + int y = static_cast(event->y); + int x2 = 0; + int y2 = 0; + if ( _editBI.get_path_at_pos( x, y, path, col, x2, y2 ) && col == _name_columnBI) { + // Double click on the Layer name, enable editing + _text_rendererBI->property_editable() = true; + _editBI.set_cursor (path, *_name_columnBI, true); + grab_focus(); } } - return deferProcessing; + + return false; } -void SwatchesPanel::_trackDocument( SwatchesPanel *panel, SPDocument *document ) +bool SwatchesPanel::_handleKeyEvent(GdkEventKey *event) { - SPDocument *oldDoc = NULL; - if (docPerPanel.find(panel) != docPerPanel.end()) { - oldDoc = docPerPanel[panel]; - if (!oldDoc) { - docPerPanel.erase(panel); // Should not be needed, but clean up just in case. - } - } - if (oldDoc != document) { - if (oldDoc) { - docPerPanel[panel] = NULL; - bool found = false; - for (std::map::iterator it = docPerPanel.begin(); (it != docPerPanel.end()) && !found; ++it) { - found = (it->second == document); - } - if (!found) { - for (std::vector::iterator it = docTrackings.begin(); it != docTrackings.end(); ++it){ - if ((*it)->doc == oldDoc) { - delete *it; - docTrackings.erase(it); - break; - } + switch (get_group0_keyval(event)) { + case GDK_KEY_Return: + case GDK_KEY_KP_Enter: + case GDK_KEY_F2: { + Gtk::TreeModel::iterator iter = _editBI.get_selection()->get_selected(); + if (iter && !_text_rendererBI->property_editable()) { + Gtk::TreeRow row = *iter; + SPObject * obj = row[_model->_colObject]; + if (obj) { + Gtk::TreeModel::Path *path = new Gtk::TreeModel::Path(iter); + // Edit the layer label + _text_rendererBI->property_editable() = true; + _editBI.set_cursor(*path, *_name_columnBI, true); + grab_focus(); + return true; } } } - - if (document) { - bool found = false; - for (std::map::iterator it = docPerPanel.begin(); (it != docPerPanel.end()) && !found; ++it) { - found = (it->second == document); - } - docPerPanel[panel] = document; - if (!found) { - sigc::connection conn0 = document->connectDestroy(sigc::bind(sigc::ptr_fun(&SwatchesPanel::handleDocumentDestroy), document)); - sigc::connection conn1 = document->connectResourcesChanged( "gradient", sigc::bind(sigc::ptr_fun(&SwatchesPanel::handleGradientsChange), document) ); - sigc::connection conn2 = document->getDefs()->connectRelease( sigc::hide(sigc::bind(sigc::ptr_fun(&SwatchesPanel::handleDefsModified), document)) ); - sigc::connection conn3 = document->getDefs()->connectModified( sigc::hide(sigc::hide(sigc::bind(sigc::ptr_fun(&SwatchesPanel::handleDefsModified), document))) ); - - DocTrack *dt = new DocTrack(document, conn0, conn1, conn2, conn3); - docTrackings.push_back(dt); - - if (docPalettes.find(document) == docPalettes.end()) { - SwatchPage *docPalette = new SwatchPage(); - docPalette->_name = "Auto"; - docPalettes[document] = docPalette; + case GDK_KEY_Delete: { + + Gtk::TreeModel::iterator iter = _editBI.get_selection()->get_selected(); + if (iter) { + Gtk::TreeRow row = *iter; + SPObject * obj = row[_model->_colObject]; + if (obj) { + obj->deleteObject(false); + sp_repr_save_file(SwatchDocument->getReprDoc(), SwatchFile, SP_SVG_NS_URI); } } + return true; } + break; } + return false; } -void SwatchesPanel::_setDocument( SPDocument *document ) +void SwatchesPanel::_handleEdited(const Glib::ustring& path, const Glib::ustring& new_text) { - if ( document != _currentDocument ) { - _trackDocument(this, document); - _currentDocument = document; - handleGradientsChange( document ); - } + Gtk::TreeModel::iterator iter = _editBI.get_model()->get_iter(path); + Gtk::TreeModel::Row row = *iter; + + _renameObject(row, new_text); + _text_rendererBI->property_editable() = false; } -static void recalcSwatchContents(SPDocument* doc, - boost::ptr_vector &tmpColors, - std::map &previewMappings, - std::map &gradMappings) +void SwatchesPanel::_handleEditingCancelled() { - std::vector newList; - - if (doc) { - const GSList *gradients = doc->getResourceList("gradient"); - for (const GSList *item = gradients; item; item = item->next) { - SPGradient* grad = SP_GRADIENT(item->data); - if ( grad->isSwatch() ) { - newList.push_back(SP_GRADIENT(item->data)); + _text_rendererBI->property_editable() = false; +} + +void SwatchesPanel::_renameObject(Gtk::TreeModel::Row row, const Glib::ustring& name) +{ + if ( row && SwatchDocument) { + SPObject* obj = row[_model->_colObject]; + if ( obj ) { + gchar const* oldLabel = obj->label(); + if ( !name.empty() && (!oldLabel || name != oldLabel) ) { + obj->setLabel(name.c_str()); + sp_repr_save_file(SwatchDocument->getReprDoc(), SwatchFile, SP_SVG_NS_URI); } } } +} - if ( !newList.empty() ) { - std::reverse(newList.begin(), newList.end()); - for ( std::vector::iterator it = newList.begin(); it != newList.end(); ++it ) - { - SPGradient* grad = *it; - - cairo_surface_t *preview = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, - PREVIEW_PIXBUF_WIDTH, VBLOCK); - cairo_t *ct = cairo_create(preview); - - Glib::ustring name( grad->getId() ); - ColorItem* item = new ColorItem( 0, 0, 0, name ); - - cairo_pattern_t *check = ink_cairo_pattern_create_checkerboard(); - cairo_pattern_t *gradient = sp_gradient_create_preview_pattern(grad, PREVIEW_PIXBUF_WIDTH); - cairo_set_source(ct, check); - cairo_paint(ct); - cairo_set_source(ct, gradient); - cairo_paint(ct); - - cairo_destroy(ct); - cairo_pattern_destroy(gradient); - cairo_pattern_destroy(check); - - cairo_pattern_t *prevpat = cairo_pattern_create_for_surface(preview); - cairo_surface_destroy(preview); +void SwatchesPanel::_setCollapsed(SPGroup * group) +{ + group->setExpanded(false); + group->updateRepr(SP_OBJECT_WRITE_NO_CHILDREN | SP_OBJECT_WRITE_EXT); + for (SPObject *iter = group->children; iter != NULL; iter = iter->next) + { + if (SP_IS_GROUP(iter)) _setCollapsed(SP_GROUP(iter)); + } +} - previewMappings[item] = prevpat; +void SwatchesPanel::_setExpanded(const Gtk::TreeModel::iterator& iter, const Gtk::TreeModel::Path& /*path*/, bool isexpanded) +{ + Gtk::TreeModel::Row row = *iter; - tmpColors.push_back(item); - gradMappings[item] = grad; + SPObject* obj = row[_model->_colObject]; + if (obj && SP_IS_GROUP(obj)) + { + if (isexpanded) + { + SP_GROUP(obj)->setExpanded(isexpanded); + obj->updateRepr(SP_OBJECT_WRITE_NO_CHILDREN | SP_OBJECT_WRITE_EXT); + } + else + { + _setCollapsed(SP_GROUP(obj)); } } + sp_repr_save_file(SwatchDocument->getReprDoc(), SwatchFile, SP_SVG_NS_URI); } -void SwatchesPanel::handleDocumentDestroy(SPDocument *document) +void SwatchesPanel::_deleteButtonClicked() { - if (document) { - for (std::vector::iterator it = docTrackings.begin(); it != docTrackings.end(); ++it){ - if ((*it)->doc == document) { - delete *it; - docTrackings.erase(it); - break; - } + Gtk::TreeModel::iterator iter = _editBI.get_selection()->get_selected(); + if (iter) { + Gtk::TreeModel::Row row = *iter; + SPObject* obj = row[_model->_colObject]; + if (obj) { + obj->deleteObject(false); + sp_repr_save_file(SwatchDocument->getReprDoc(), SwatchFile, SP_SVG_NS_URI); } + } +} - if (docPalettes.find(document) != docPalettes.end()) { - docPalettes.erase(document); +bool SwatchesPanel::_handleButtonEventDoc(GdkEventButton* event) +{ + static unsigned doubleclick = 0; + + if ( (event->type == GDK_BUTTON_PRESS) && (event->button == 3) ) { + // TODO - fix to a better is-popup function + Gtk::TreeModel::Path path; + int x = static_cast(event->x); + int y = static_cast(event->y); + if ( _editDoc.get_path_at_pos( x, y, path ) ) { + Gtk::TreeModel::Children::iterator iter = _editDoc.get_model()->get_iter(path); + Gtk::TreeModel::Row row = *iter; + + SPObject* obj = row[_modelDoc->_colObject]; + if (SP_IS_GRADIENT(obj)) { + _swatchClicked(event, SP_GRADIENT(obj)); + } else if (SP_IS_GROUP(obj)) { + _lblClick(event, SP_GROUP(obj)); + } else { + _lblClick(event, NULL); + } + } else { + _lblClick(event, NULL); } + } + + if ( (event->type == GDK_2BUTTON_PRESS) && (event->button == 1) ) { + doubleclick = 1; + } - for (std::map::iterator it = docPerPanel.begin(); it != docPerPanel.end(); ++it) { - if (it->second == document) { - SwatchesPanel* swp = it->first; - std::vector pages = swp->_getSwatchSets(); - if ((swp->_currentIndex >= static_cast(pages.size())) && (pages.size() > 0)) - { - swp->_setSelectedIndex(swp->_getSwatchSets().size() - 1); - } - swp->_rebuild(); - docPerPanel.erase(it); - break; - } + if ( event->type == GDK_BUTTON_RELEASE && doubleclick) { + doubleclick = 0; + Gtk::TreeModel::Path path; + Gtk::TreeViewColumn* col = 0; + int x = static_cast(event->x); + int y = static_cast(event->y); + int x2 = 0; + int y2 = 0; + if ( _editDoc.get_path_at_pos( x, y, path, col, x2, y2 ) && col == _name_columnDoc) { + // Double click on the Layer name, enable editing + _text_rendererDoc->property_editable() = true; + _editDoc.set_cursor (path, *_name_columnDoc, true); + grab_focus(); } } + + return false; } -void SwatchesPanel::handleGradientsChange(SPDocument *document) +void SwatchesPanel::_deleteButtonClickedDoc() { - SwatchPage *docPalette = (docPalettes.find(document) != docPalettes.end()) ? docPalettes[document] : 0; - if (docPalette) { - boost::ptr_vector tmpColors; - std::map tmpPrevs; - std::map tmpGrads; - recalcSwatchContents(document, tmpColors, tmpPrevs, tmpGrads); - - for (std::map::iterator it = tmpPrevs.begin(); it != tmpPrevs.end(); ++it) { - it->first->setPattern(it->second); - cairo_pattern_destroy(it->second); + Gtk::TreeModel::iterator iter = _editDoc.get_selection()->get_selected(); + if (iter) { + Gtk::TreeRow row = *iter; + SPObject * obj = row[_modelDoc->_colObject]; + if (SP_IS_GRADIENT(obj)) { + RemoveSwatch(SP_GRADIENT(obj)); + } else if (SP_IS_GROUP(obj)) { + Remove(SP_GROUP(obj)); } + } +} - for (std::map::iterator it = tmpGrads.begin(); it != tmpGrads.end(); ++it) { - it->first->setGradient(it->second); - } - - docPalette->_colors.swap(tmpColors); - - // Figure out which SwatchesPanel instances are affected and update them. - - for (std::map::iterator it = docPerPanel.begin(); it != docPerPanel.end(); ++it) { - if (it->second == document) { - SwatchesPanel* swp = it->first; - std::vector pages = swp->_getSwatchSets(); - SwatchPage* curr = pages[swp->_currentIndex]; - if (curr == docPalette) { - swp->_rebuild(); +bool SwatchesPanel::_handleKeyEventDoc(GdkEventKey *event) +{ + switch (get_group0_keyval(event)) { + case GDK_KEY_Return: + case GDK_KEY_KP_Enter: + case GDK_KEY_F2: { + Gtk::TreeModel::iterator iter = _editDoc.get_selection()->get_selected(); + if (iter && !_text_rendererDoc->property_editable()) { + Gtk::TreeRow row = *iter; + SPObject * obj = row[_modelDoc->_colObject]; + if (obj) { + Gtk::TreeModel::Path *path = new Gtk::TreeModel::Path(iter); + // Edit the layer label + _text_rendererDoc->property_editable() = true; + _editDoc.set_cursor(*path, *_name_columnDoc, true); + grab_focus(); + return true; } } } + case GDK_KEY_Delete: { + + _deleteButtonClickedDoc(); + return true; + } + break; } + return false; } -void SwatchesPanel::handleDefsModified(SPDocument *document) +void SwatchesPanel::_renameObjectDoc(Gtk::TreeModel::Row row, const Glib::ustring& name) { - SwatchPage *docPalette = (docPalettes.find(document) != docPalettes.end()) ? docPalettes[document] : 0; - if (docPalette && !DocTrack::queueUpdateIfNeeded(document) ) { - boost::ptr_vector tmpColors; - std::map tmpPrevs; - std::map tmpGrads; - recalcSwatchContents(document, tmpColors, tmpPrevs, tmpGrads); - - if ( tmpColors.size() != docPalette->_colors.size() ) { - handleGradientsChange(document); - } else { - int cap = std::min(docPalette->_colors.size(), tmpColors.size()); - for (int i = 0; i < cap; i++) { - ColorItem *newColor = &tmpColors[i]; - ColorItem *oldColor = &docPalette->_colors[i]; - if ( (newColor->def.getType() != oldColor->def.getType()) || - (newColor->def.getR() != oldColor->def.getR()) || - (newColor->def.getG() != oldColor->def.getG()) || - (newColor->def.getB() != oldColor->def.getB()) ) { - oldColor->def.setRGB(newColor->def.getR(), newColor->def.getG(), newColor->def.getB()); - } - if (tmpGrads.find(newColor) != tmpGrads.end()) { - oldColor->setGradient(tmpGrads[newColor]); - } - if ( tmpPrevs.find(newColor) != tmpPrevs.end() ) { - oldColor->setPattern(tmpPrevs[newColor]); - } + if ( row && SwatchDocument) { + SPObject* obj = row[_modelDoc->_colObject]; + if ( obj ) { + gchar const* oldLabel = obj->label(); + if ( !name.empty() && (!oldLabel || name != oldLabel) ) { + obj->setLabel(name.c_str()); } } - - for (std::map::iterator it = tmpPrevs.begin(); it != tmpPrevs.end(); ++it) { - cairo_pattern_destroy(it->second); - } } } +void SwatchesPanel::_handleEditedDoc(const Glib::ustring& path, const Glib::ustring& new_text) +{ + Gtk::TreeModel::iterator iter = _editDoc.get_model()->get_iter(path); + Gtk::TreeModel::Row row = *iter; + + _renameObjectDoc(row, new_text); + _text_rendererDoc->property_editable() = false; +} + +void SwatchesPanel::_handleEditingCancelledDoc() +{ + _text_rendererDoc->property_editable() = false; +} -std::vector SwatchesPanel::_getSwatchSets() const +/* + * Drap and drop within the tree + * Save the drag source and drop target SPObjects and if its a drag between layers or into (sublayer) a layer + */ +bool SwatchesPanel::_handleDragDrop(const Glib::RefPtr& context, int x, int y, guint time) { - std::vector tmp; - if (docPalettes.find(_currentDocument) != docPalettes.end()) { - tmp.push_back(docPalettes[_currentDocument]); + int cell_x = 0, cell_y = 0; + Gtk::TreeModel::Path target_path; + Gtk::TreeView::Column *target_column; + + bool _dnd_top = false; + _dnd_into = false; + _dnd_target = SwatchDocument->getDefs()->lastChild(); + Gtk::TreeModel::iterator itersel = _editBI.get_selection()->get_selected(); + if (!itersel) { + return true; } + Gtk::TreeModel::Row rowsel = *itersel; + _dnd_source = rowsel[_model->_colObject]; - tmp.insert(tmp.end(), userSwatchPages.begin(), userSwatchPages.end()); - tmp.insert(tmp.end(), systemSwatchPages.begin(), systemSwatchPages.end()); + if (!_dnd_source) { + return true; + } + + if (_editBI.get_path_at_pos (x, y, target_path, target_column, cell_x, cell_y)) { + // Are we before, inside or after the drop layer + Gdk::Rectangle rect; + _editBI.get_background_area (target_path, *target_column, rect); + int cell_height = rect.get_height(); + _dnd_into = (cell_y > (int)(cell_height * 1/3) && cell_y <= (int)(cell_height * 2/3)); + if (cell_y < (int)(cell_height * 1/3)) { + Gtk::TreeModel::Path next_path = target_path; + if (next_path.prev()) { + target_path = next_path; + } else { + // Dragging to the "end" + Gtk::TreeModel::Path up_path = target_path; + up_path.up(); + if (_store->iter_is_valid(_store->get_iter(up_path))) { + // Drop into parent + target_path = up_path; + _dnd_into = true; + } else { + _dnd_top = true; + // Drop into the top level + _dnd_target = NULL; + } + } + } + if (!_dnd_top) { + Gtk::TreeModel::iterator iter = _store->get_iter(target_path); + if (_store->iter_is_valid(iter)) { + Gtk::TreeModel::Row row = *iter; + SPObject *obj = row[_model->_colObject]; + if (obj) { + _dnd_target = obj; + } + } + } + } + + if (_dnd_source != _dnd_target) { + + Inkscape::XML::Node *target_ref = _dnd_target ? _dnd_target->getRepr() : NULL; + Inkscape::XML::Node *our_ref = _dnd_source->getRepr(); + + if (target_ref != our_ref) { + if (!target_ref) { + target_ref = SwatchDocument->getDefs()->getRepr(); + if (target_ref != our_ref->parent()) { + our_ref->parent()->removeChild(our_ref); + target_ref->addChild(our_ref, NULL); + } else { + our_ref->parent()->changeOrder(our_ref, NULL); + } + } else if (_dnd_into) { + // Move this inside of the target at the end + our_ref->parent()->removeChild(our_ref); + target_ref->addChild(our_ref, NULL); + } else if (target_ref->parent() != our_ref->parent()) { + // Change in parent, need to remove and add + our_ref->parent()->removeChild(our_ref); + target_ref->parent()->addChild(our_ref, target_ref); + } else { + // Same parent, just move + our_ref->parent()->changeOrder(our_ref, target_ref); + } + } + sp_repr_save_file(SwatchDocument->getReprDoc(), SwatchFile, SP_SVG_NS_URI); + } - return tmp; + return true; } -void SwatchesPanel::_updateFromSelection() +/* + * Drap and drop within the tree + * Save the drag source and drop target SPObjects and if its a drag between layers or into (sublayer) a layer + */ +bool SwatchesPanel::_handleDragDropDoc(const Glib::RefPtr& context, int x, int y, guint time) { - SwatchPage *docPalette = (docPalettes.find(_currentDocument) != docPalettes.end()) ? docPalettes[_currentDocument] : 0; - if ( docPalette ) { - Glib::ustring fillId; - Glib::ustring strokeId; - - SPStyle *tmpStyle = sp_style_new( sp_desktop_document(_currentDesktop) ); - int result = sp_desktop_query_style( _currentDesktop, tmpStyle, QUERY_STYLE_PROPERTY_FILL ); - switch (result) { - case QUERY_STYLE_SINGLE: - case QUERY_STYLE_MULTIPLE_AVERAGED: - case QUERY_STYLE_MULTIPLE_SAME: - { - if (tmpStyle->fill.set && tmpStyle->fill.isPaintserver()) { - SPPaintServer* server = tmpStyle->getFillPaintServer(); - if ( SP_IS_GRADIENT(server) ) { - SPGradient* target = 0; - SPGradient* grad = SP_GRADIENT(server); - - if ( grad->isSwatch() ) { - target = grad; - } else if ( grad->ref ) { - SPGradient *tmp = grad->ref->getObject(); - if ( tmp && tmp->isSwatch() ) { - target = tmp; - } - } - if ( target ) { - //XML Tree being used directly here while it shouldn't be - gchar const* id = target->getRepr()->attribute("id"); - if ( id ) { - fillId = id; - } - } - } + int cell_x = 0, cell_y = 0; + Gtk::TreeModel::Path target_path; + Gtk::TreeView::Column *target_column; + + bool _dnd_top = false; + _dnd_into = false; + _dnd_target = _currentDocument->getDefs()->lastChild(); + Gtk::TreeModel::iterator itersel = _editDoc.get_selection()->get_selected(); + if (!itersel) { + return true; + } + Gtk::TreeModel::Row rowsel = *itersel; + _dnd_source = rowsel[_modelDoc->_colObject]; + + if (!_dnd_source) { + return true; + } + + if (_editDoc.get_path_at_pos (x, y, target_path, target_column, cell_x, cell_y)) { + // Are we before, inside or after the drop layer + Gdk::Rectangle rect; + _editDoc.get_background_area (target_path, *target_column, rect); + int cell_height = rect.get_height(); + _dnd_into = (cell_y > (int)(cell_height * 1/3) && cell_y <= (int)(cell_height * 2/3)); + if (cell_y < (int)(cell_height * 1/3)) { + Gtk::TreeModel::Path next_path = target_path; + if (next_path.prev()) { + target_path = next_path; + } else { + // Dragging to the "end" + Gtk::TreeModel::Path up_path = target_path; + up_path.up(); + if (_storeDoc->iter_is_valid(_storeDoc->get_iter(up_path))) { + // Drop into parent + target_path = up_path; + _dnd_into = true; + } else { + _dnd_top = true; + // Drop into the top level + _dnd_target = NULL; } - break; } } - - result = sp_desktop_query_style( _currentDesktop, tmpStyle, QUERY_STYLE_PROPERTY_STROKE ); - switch (result) { - case QUERY_STYLE_SINGLE: - case QUERY_STYLE_MULTIPLE_AVERAGED: - case QUERY_STYLE_MULTIPLE_SAME: - { - if (tmpStyle->stroke.set && tmpStyle->stroke.isPaintserver()) { - SPPaintServer* server = tmpStyle->getStrokePaintServer(); - if ( SP_IS_GRADIENT(server) ) { - SPGradient* target = 0; - SPGradient* grad = SP_GRADIENT(server); - if ( grad->isSwatch() ) { - target = grad; - } else if ( grad->ref ) { - SPGradient *tmp = grad->ref->getObject(); - if ( tmp && tmp->isSwatch() ) { - target = tmp; - } - } - if ( target ) { - //XML Tree being used directly here while it shouldn't be - gchar const* id = target->getRepr()->attribute("id"); - if ( id ) { - strokeId = id; - } + if (!_dnd_top) { + Gtk::TreeModel::iterator iter = _storeDoc->get_iter(target_path); + if (_storeDoc->iter_is_valid(iter)) { + Gtk::TreeModel::Row row = *iter; + SPObject *obj = row[_modelDoc->_colObject]; + if (obj) { + _dnd_target = obj; + if (SP_IS_GRADIENT(obj)) { + _dnd_into = false; + if (SP_IS_GROUP(_dnd_source)) { + _dnd_target = obj->parent; } + } else if (SP_IS_GROUP(_dnd_source)) { + _dnd_into = false; } } - break; } } - sp_style_unref(tmpStyle); - - for ( boost::ptr_vector::iterator it = docPalette->_colors.begin(); it != docPalette->_colors.end(); ++it ) { - ColorItem* item = &*it; - bool isFill = (fillId == item->def.descr); - bool isStroke = (strokeId == item->def.descr); - item->setState( isFill, isStroke ); + } + + if (_dnd_source != _dnd_target) { + + Inkscape::XML::Node *target_ref = _dnd_target ? _dnd_target->getRepr() : NULL; + Inkscape::XML::Node *our_ref = _dnd_source->getRepr(); + + if (target_ref != our_ref) { + if (!target_ref) { + target_ref = _currentDocument->getDefs()->getRepr(); + if (target_ref != our_ref->parent()) { + our_ref->parent()->removeChild(our_ref); + target_ref->addChild(our_ref, NULL); + } else { + our_ref->parent()->changeOrder(our_ref, NULL); + } + } else if (_dnd_into) { + // Move this inside of the target at the end + our_ref->parent()->removeChild(our_ref); + target_ref->addChild(our_ref, NULL); + } else if (target_ref->parent() != our_ref->parent()) { + // Change in parent, need to remove and add + our_ref->parent()->removeChild(our_ref); + target_ref->parent()->addChild(our_ref, target_ref); + } else { + // Same parent, just move + our_ref->parent()->changeOrder(our_ref, target_ref); + } } + DocumentUndo::done( _currentDocument , SP_VERB_DIALOG_SWATCHES, + _("Moved Swatches")); } + + return true; } -void SwatchesPanel::_handleAction( int setId, int itemId ) + +/** + * Constructor + */ +SwatchesPanel::SwatchesPanel(gchar const* prefsPath, bool showLabels) : + Inkscape::UI::Widget::Panel("", prefsPath, SP_VERB_DIALOG_SWATCHES, ""), + _scroller(), + _insideTable(1, 2), + _insideV(), + _insideH(), + _buttonsRow(), + _outsideV(), + _noLink(_("Don't Link")), + _showlabels(showLabels), + _store(0), + _scrollerBI(), + _editBI(), + _buttonsRowBI(), + _editBIV(), + _storeDoc(0), + _scrollerDoc(), + _editDoc(), + _buttonsRowDoc(), + _editDocV(), + _notebook(), + rootWatcher(0), + docWatcher(0), + _currentDesktop(0), + _currentDocument(0) { - switch( setId ) { - case 3: + _insideH.pack_start(_insideTable, Gtk::PACK_SHRINK); + if (_showlabels) { + _insideV.pack_start(_insideH, Gtk::PACK_SHRINK); + _scroller.add(_insideV); + } else { + _scroller.property_height_request() = 45; + _scroller.add(_insideH); + } + + popUpMenu = manage( new Gtk::Menu() ); + popUpMenu->show_all_children(); + + Gtk::Button* btn = manage( new Gtk::Button() ); + _styleButton( *btn, SP_ACTIVE_DESKTOP, SP_VERB_LAYER_NEW, GTK_STOCK_ADD, _("Add Swatch") ); + btn->signal_button_press_event().connect_notify( sigc::mem_fun(*this, &SwatchesPanel::_addButtonClicked) ); + _buttonsRow.pack_start(*btn, Gtk::PACK_SHRINK); + +// btn = manage( new Gtk::Button() ); +// _styleButton( *btn, SP_ACTIVE_DESKTOP, SP_VERB_LAYER_NEW, GTK_STOCK_DISCONNECT, C_("Unlink", "New") ); +// _buttonsRow.pack_end(*btn, Gtk::PACK_SHRINK); + + static Inkscape::Preferences *prefs = Inkscape::Preferences::get(); + Glib::ustring nolink = Glib::ustring::compose("%1/nolink", prefsPath); + _noLink.set_tooltip_text(_("Don't link swatches")); + _noLink.set_active(prefs->getBool(nolink, false)); + _noLink.signal_toggled().connect_notify(sigc::mem_fun(*this, &SwatchesPanel::NoLinkToggled)); + _buttonsRow.pack_end(_noLink, Gtk::PACK_SHRINK); + + _scroller.set_policy( Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC ); + _scroller.set_shadow_type(Gtk::SHADOW_NONE); + + if (_showlabels) { + _outsideV.pack_end(_buttonsRow, Gtk::PACK_SHRINK); + _outsideV.pack_end(_scroller, Gtk::PACK_EXPAND_WIDGET); + + _notebook.append_page(_outsideV, "Use"); + + { + ModelColumnsDoc *zoop = new ModelColumnsDoc(); + _modelDoc = zoop; + + _storeDoc = Gtk::TreeStore::create( *zoop ); + + _editDoc.set_model( _storeDoc ); + _editDoc.set_headers_visible(false); + _editDoc.set_reorderable(true); + _editDoc.enable_model_drag_dest (Gdk::ACTION_MOVE); + + Gtk::Button* btn = manage( new Gtk::Button() ); + _styleButton( *btn, SP_ACTIVE_DESKTOP, SP_VERB_LAYER_NEW, GTK_STOCK_ADD, _("Import Swatch") ); + btn->signal_button_press_event().connect_notify( sigc::mem_fun(*this, &SwatchesPanel::_addButtonClicked)); + _buttonsRowDoc.pack_start(*btn, Gtk::PACK_SHRINK); + + btn = manage( new Gtk::Button() ); + _styleButton( *btn, SP_ACTIVE_DESKTOP, SP_VERB_LAYER_DELETE, GTK_STOCK_DELETE, _("Delete Swatch") ); + btn->signal_button_press_event().connect_notify( sigc::hide(sigc::mem_fun(*this, &SwatchesPanel::_deleteButtonClickedDoc))); + _buttonsRowDoc.pack_start(*btn, Gtk::PACK_SHRINK); + + _pixbuf_rendererDoc = manage(new Gtk::CellRendererPixbuf()); + int pixbufColNum = _editDoc.append_column("Pixbuf", *_pixbuf_rendererDoc) - 1; + _pixbuf_columnDoc = _editDoc.get_column(pixbufColNum); + _pixbuf_columnDoc->add_attribute(_pixbuf_rendererDoc->property_pixbuf(), _modelDoc->_colPixbuf); + + _text_rendererDoc = manage(new Gtk::CellRendererText()); + int nameColNum = _editDoc.append_column("Name", *_text_rendererDoc) - 1; + _name_columnDoc = _editDoc.get_column(nameColNum); + _name_columnDoc->add_attribute(_text_rendererDoc->property_text(), _modelDoc->_colLabel); + + _text_rendererDoc->signal_edited().connect( sigc::mem_fun(*this, &SwatchesPanel::_handleEditedDoc) ); + _text_rendererDoc->signal_editing_canceled().connect( sigc::mem_fun(*this, &SwatchesPanel::_handleEditingCancelledDoc) ); + + _editDoc.set_expander_column( *_editDoc.get_column(nameColNum) ); + + _editDoc.signal_button_press_event().connect( sigc::mem_fun(*this, &SwatchesPanel::_handleButtonEventDoc), false ); + _editDoc.signal_button_release_event().connect( sigc::mem_fun(*this, &SwatchesPanel::_handleButtonEventDoc), false ); + _editDoc.signal_key_press_event().connect( sigc::mem_fun(*this, &SwatchesPanel::_handleKeyEventDoc), false ); + + _editDoc.signal_drag_drop().connect( sigc::mem_fun(*this, &SwatchesPanel::_handleDragDropDoc), false); + + _scrollerDoc.set_policy( Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC ); + _scrollerDoc.set_shadow_type(Gtk::SHADOW_IN); + _scrollerDoc.add(_editDoc); + + _editDocV.pack_start(_scrollerDoc, Gtk::PACK_EXPAND_WIDGET); + _editDocV.pack_end(_buttonsRowDoc, Gtk::PACK_SHRINK); + + _notebook.append_page(_editDocV, "Edit"); + } + { - _setSelectedIndex(itemId); + popUpImportMenu = Gtk::manage(new Gtk::Menu()); + + Gtk::MenuItem* mi = Gtk::manage(new Gtk::MenuItem(_("New Swatch Group..."))); + mi->signal_activate().connect_notify(sigc::mem_fun(*this, &SwatchesPanel::NewGroupBI)); + mi->show(); + popUpImportMenu->append(*mi); + + mi = Gtk::manage(new Gtk::MenuItem(_("Import Swatch File..."))); + mi->signal_activate().connect_notify(sigc::bind(sigc::mem_fun(*this, &SwatchesPanel::_importButtonClicked), false, true)); + mi->show(); + popUpImportMenu->append(*mi); + + ModelColumns *zoop = new ModelColumns(); + _model = zoop; + + _store = Gtk::TreeStore::create( *zoop ); + + _editBI.set_model( _store ); + _editBI.set_headers_visible(false); + _editBI.set_reorderable(true); + _editBI.enable_model_drag_dest (Gdk::ACTION_MOVE); + + Gtk::Button* btn = manage( new Gtk::Button() ); + _styleButton( *btn, SP_ACTIVE_DESKTOP, SP_VERB_LAYER_NEW, GTK_STOCK_ADD, _("Import Swatch") ); + btn->signal_button_press_event().connect_notify(sigc::mem_fun(*this, &SwatchesPanel::_addBIButtonClicked)); + _buttonsRowBI.pack_start(*btn, Gtk::PACK_SHRINK); + + btn = manage( new Gtk::Button() ); + _styleButton( *btn, SP_ACTIVE_DESKTOP, SP_VERB_LAYER_DELETE, GTK_STOCK_DELETE, _("Delete Swatch") ); + btn->signal_button_press_event().connect_notify( sigc::hide(sigc::mem_fun(*this, &SwatchesPanel::_deleteButtonClicked))); + _buttonsRowBI.pack_start(*btn, Gtk::PACK_SHRINK); + + _text_rendererBI = manage(new Gtk::CellRendererText()); + int nameColNum = _editBI.append_column("Name", *_text_rendererBI) - 1; + _name_columnBI = _editBI.get_column(nameColNum); + _name_columnBI->add_attribute(_text_rendererBI->property_text(), _model->_colLabel); + + _text_rendererBI->signal_edited().connect( sigc::mem_fun(*this, &SwatchesPanel::_handleEdited) ); + _text_rendererBI->signal_editing_canceled().connect( sigc::mem_fun(*this, &SwatchesPanel::_handleEditingCancelled) ); + + _editBI.set_expander_column( *_editBI.get_column(nameColNum) ); + + _editBI.signal_button_press_event().connect( sigc::mem_fun(*this, &SwatchesPanel::_handleButtonEvent), false ); + _editBI.signal_button_release_event().connect( sigc::mem_fun(*this, &SwatchesPanel::_handleButtonEvent), false ); + _editBI.signal_key_press_event().connect( sigc::mem_fun(*this, &SwatchesPanel::_handleKeyEvent), false ); + + _editBI.signal_drag_drop().connect( sigc::mem_fun(*this, &SwatchesPanel::_handleDragDrop), false); + _editBI.signal_row_collapsed().connect( sigc::bind(sigc::mem_fun(*this, &SwatchesPanel::_setExpanded), false)); + _editBI.signal_row_expanded().connect( sigc::bind(sigc::mem_fun(*this, &SwatchesPanel::_setExpanded), true)); + + _scrollerBI.set_policy( Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC ); + _scrollerBI.set_shadow_type(Gtk::SHADOW_IN); + _scrollerBI.add(_editBI); + + _editBIV.pack_start(_scrollerBI, Gtk::PACK_EXPAND_WIDGET); + _editBIV.pack_end(_buttonsRowBI, Gtk::PACK_SHRINK); + + _notebook.append_page(_editBIV, "Edit Built-In"); } - break; + + _getContents()->pack_end(_notebook, Gtk::PACK_EXPAND_WIDGET); + } else { + //_outsideV.pack_end(_scroller, Gtk::PACK_SHRINK); + _buttonsRow.pack_end(_scroller, Gtk::PACK_EXPAND_WIDGET); + //_getContents()->pack_end(_outsideV, Gtk::PACK_SHRINK); + _getContents()->pack_end(_buttonsRow, Gtk::PACK_SHRINK); } + + loadPalletFile(); + + rootWatcher = new SwatchWatcher(this, SwatchDocument->getDefs(), true); + SwatchDocument->getDefs()->getRepr()->addObserver(*rootWatcher); + _swatchesChanged(); } -void SwatchesPanel::_setSelectedIndex( int index ) +SwatchesPanel::~SwatchesPanel() { - std::vector pages = _getSwatchSets(); - if ( index >= 0 && index < static_cast(pages.size()) ) { - _currentIndex = index; + if (rootWatcher) { + rootWatcher->_repr->removeObserver(*rootWatcher); + delete rootWatcher; + } + + if (docWatcher) { + docWatcher->_repr->removeObserver(*docWatcher); + delete docWatcher; + } + + _documentConnection.disconnect(); + _selChanged.disconnect(); +} - if ( !_prefs_path.empty() ) { - Inkscape::Preferences *prefs = Inkscape::Preferences::get(); - prefs->setString(_prefs_path + "/palette", pages[_currentIndex]->_name); +void SwatchesPanel::setDesktop( SPDesktop* desktop ) +{ + Inkscape::UI::Widget::Panel::setDesktop(desktop); + if ( desktop != _currentDesktop ) { + if ( _currentDesktop ) { + _documentConnection.disconnect(); + _selChanged.disconnect(); } - _rebuild(); + _currentDesktop = desktop; + + if ( desktop ) { + //_currentDesktop->selection->connectChanged(sigc::hide(sigc::mem_fun(*this, &SwatchesPanel::_updateFromSelection))); + + _documentConnection = desktop->connectDocumentReplaced(sigc::mem_fun(*this, &SwatchesPanel::_setDocument)); + + _setDocument( desktop, desktop->doc() ); + } else { + _setDocument(0, 0); + } } } -void SwatchesPanel::_rebuild() +void SwatchesPanel::_setDocument( SPDesktop* desktop, SPDocument *document ) { - std::vector pages = _getSwatchSets(); - if (_currentIndex < static_cast(pages.size())) { - SwatchPage* curr = pages[_currentIndex]; - _holder->clear(); - - if ( curr->_prefWidth > 0 ) { - _holder->setColumnPref( curr->_prefWidth ); + if ( document != _currentDocument ) { + if (docWatcher) { + docWatcher->_repr->removeObserver(*docWatcher); + delete docWatcher; + docWatcher = NULL; } - _holder->freezeUpdates(); - // TODO restore once 'clear' works _holder->addPreview(_clear); - _holder->addPreview(_remove); - for ( boost::ptr_vector::iterator it = curr->_colors.begin(); it != curr->_colors.end(); ++it) { - _holder->addPreview(&*it); + _currentDocument = document; + + if (_currentDocument) { + docWatcher = new SwatchWatcher(this, _currentDocument->getDefs(), false); + _currentDocument->getDefs()->getRepr()->addObserver(*docWatcher); } - _holder->thawUpdates(); + _defsChanged(); } } @@ -1241,6 +2323,48 @@ void SwatchesPanel::_rebuild() } //namespace UI } //namespace Inkscape +//should be okay to add this here +guint get_group0_keyval(GdkEventKey *event) { + guint keyval = 0; + gdk_keymap_translate_keyboard_state(gdk_keymap_get_for_display( + gdk_display_get_default()), event->hardware_keycode, + (GdkModifierType) event->state, 0 /*event->key.group*/, &keyval, + NULL, NULL, NULL); + return keyval; +} + +void +sp_desktop_set_gradient(SPDesktop *desktop, SPGradient* gradient, bool fill) +{ + + bool intercepted = false; + + if (gradient->isSolid()) { + ColorRGBA color(gradient->getFirstStop()->getEffectiveColor().toRGBA32(gradient->getFirstStop()->opacity)); + guint32 rgba = SP_RGBA32_F_COMPOSE(color[0], color[1], color[2], color[3]); + gchar b[64]; + sp_svg_write_color(b, sizeof(b), rgba); + SPCSSAttr *css = sp_repr_css_attr_new(); + if (fill) { + sp_repr_css_set_property(css, "fill", b); + Inkscape::CSSOStringStream osalpha; + osalpha << color[3]; + sp_repr_css_set_property(css, "fill-opacity", osalpha.str().c_str()); + } else { + sp_repr_css_set_property(css, "stroke", b); + Inkscape::CSSOStringStream osalpha; + osalpha << color[3]; + sp_repr_css_set_property(css, "stroke-opacity", osalpha.str().c_str()); + } + intercepted = desktop->_set_style_signal.emit(css); + } + + if (!intercepted) { + for (const GSList *it = desktop->selection->itemList(); it != NULL; it = it->next) { + sp_item_set_gradient(SP_ITEM(it->data), gradient, SP_IS_RADIALGRADIENT(gradient) ? SP_GRADIENT_TYPE_RADIAL : SP_GRADIENT_TYPE_LINEAR, !fill ? Inkscape::FOR_STROKE : Inkscape::FOR_FILL); + } + } +} /* Local Variables: diff --git a/src/ui/dialog/swatches.h b/src/ui/dialog/swatches.h index 3abb81d98..cb8f87962 100644 --- a/src/ui/dialog/swatches.h +++ b/src/ui/dialog/swatches.h @@ -12,66 +12,161 @@ #include "ui/widget/panel.h" #include "enums.h" +#include "sp-object.h" +#include "sp-item-group.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "sp-gradient.h" +#include "xml/node-observer.h" namespace Inkscape { namespace UI { -class PreviewHolder; - namespace Dialogs { -class ColorItem; -class SwatchPage; -class DocTrack; - /** * A panel that displays paint swatches. */ class SwatchesPanel : public Inkscape::UI::Widget::Panel { public: - SwatchesPanel(gchar const* prefsPath = "/dialogs/swatches"); + SwatchesPanel(gchar const* prefsPath = "/dialogs/swatches", bool showLabels = true); virtual ~SwatchesPanel(); - + static SwatchesPanel& getInstance(); - virtual void setOrientation(SPAnchorType how); - virtual void setDesktop( SPDesktop* desktop ); virtual SPDesktop* getDesktop() {return _currentDesktop;} - virtual int getSelectedIndex() {return _currentIndex;} // temporary - protected: - static void handleDocumentDestroy(SPDocument *document); - static void handleGradientsChange(SPDocument *document); - - virtual void _updateFromSelection(); - virtual void _handleAction( int setId, int itemId ); - virtual void _setDocument( SPDocument *document ); - virtual void _setSelectedIndex( int index ); - virtual void _rebuild(); - virtual std::vector _getSwatchSets() const; + virtual void _setDocument( SPDesktop* desktop, SPDocument *document ); private: + class ModelColumns; + class ModelColumnsDoc; + + class StopWatcher; + class GradientWatcher; + class SwatchWatcher; + SwatchesPanel(SwatchesPanel const &); // no copy SwatchesPanel &operator=(SwatchesPanel const &); // no assign + + void _styleButton( Gtk::Button& btn, SPDesktop *desktop, unsigned int code, char const* iconName, char const* fallback ); + + void _setSelectionSwatch(SPGradient* swatchItem, bool isStroke); + + void NoLinkToggled(); + void NewGroup(); + void NewGroupBI(); + void _addBIButtonClicked(GdkEventButton* event); + void Duplicate(SPGroup* page); + void SaveAs(); + void AddSelectedFill(SPGroup* page); + void AddSelectedStroke(SPGroup* page); + void MoveUp(SPGroup* page); + void MoveDown(SPGroup* page); + void Remove(SPGroup* page); + + void SetSelectedFill(SPGradient* swatch); + void SetSelectedStroke(SPGradient* swatch); + void MoveSwatchUp(SPGradient* swatch); + void MoveSwatchDown(SPGradient* swatch); + void RemoveSwatch(SPGradient* swatch); + + void _lblClick(GdkEventButton* event, SPGroup* page); + void _addSwatchButtonClicked(SPGroup* swatch, bool recurse); + void _defsChanged(); + void _importButtonClicked(bool addToDoc, bool addToBI); + void _deleteButtonClicked(); + void _addButtonClicked(GdkEventButton* event); + void _swatchClicked(GdkEventButton* event, SPGradient* swatchItem); + + Gtk::MenuItem* _addSwatchGroup(SPGroup* group, Gtk::TreeModel::Row* parentRow); + void _swatchesChanged(); + + bool _handleButtonEvent(GdkEventButton *event); + bool _handleKeyEvent(GdkEventKey *event); + + void _handleEdited(const Glib::ustring& path, const Glib::ustring& new_text); + void _handleEditingCancelled(); + void _renameObject(Gtk::TreeModel::Row row, const Glib::ustring& name); + + void _setCollapsed(SPGroup * group); + void _setExpanded(const Gtk::TreeModel::iterator& iter, const Gtk::TreeModel::Path& /*path*/, bool isexpanded); + + void _deleteButtonClickedDoc(); + bool _handleButtonEventDoc(GdkEventButton* event); + bool _handleKeyEventDoc(GdkEventKey *event); + + void _handleEditedDoc(const Glib::ustring& path, const Glib::ustring& new_text); + void _handleEditingCancelledDoc(); + void _renameObjectDoc(Gtk::TreeModel::Row row, const Glib::ustring& name); + + bool _handleDragDropDoc(const Glib::RefPtr& context, int x, int y, guint time); + bool _handleDragDrop(const Glib::RefPtr& context, int x, int y, guint time); + + Gtk::Menu *popUpMenu; + Gtk::Menu *popUpImportMenu; + + Gtk::ScrolledWindow _scroller; + Gtk::Table _insideTable; + Gtk::VBox _insideV; + Gtk::HBox _insideH; + Gtk::HBox _buttonsRow; + Gtk::VBox _outsideV; + Gtk::CheckButton _noLink; + bool _showlabels; + + SwatchesPanel::ModelColumns* _model; + Glib::RefPtr _store; + + Gtk::CellRendererText *_text_rendererBI; + Gtk::TreeView::Column *_name_columnBI; + Gtk::ScrolledWindow _scrollerBI; + Gtk::TreeView _editBI; + Gtk::HBox _buttonsRowBI; + Gtk::VBox _editBIV; + + SwatchesPanel::ModelColumnsDoc* _modelDoc; + Glib::RefPtr _storeDoc; + + Gtk::CellRendererText *_text_rendererDoc; + Gtk::CellRendererPixbuf *_pixbuf_rendererDoc; + Gtk::TreeView::Column *_name_columnDoc; + Gtk::TreeView::Column *_pixbuf_columnDoc; + Gtk::ScrolledWindow _scrollerDoc; + Gtk::TreeView _editDoc; + Gtk::HBox _buttonsRowDoc; + Gtk::VBox _editDocV; + + Gtk::Notebook _notebook; + + SwatchWatcher* rootWatcher; + std::vector rootWatchers; + + std::vector docWatchers; + SwatchWatcher* docWatcher; - static void _trackDocument( SwatchesPanel *panel, SPDocument *document ); - static void handleDefsModified(SPDocument *document); - - PreviewHolder* _holder; - ColorItem* _clear; - ColorItem* _remove; - int _currentIndex; SPDesktop* _currentDesktop; SPDocument* _currentDocument; + + bool _dnd_into; + SPObject* _dnd_source; + SPObject* _dnd_target; sigc::connection _documentConnection; sigc::connection _selChanged; - - friend class DocTrack; }; } //namespace Dialogs -- cgit v1.2.3 From 3093434e177d4bb7ccc57c1339fad00d47431c17 Mon Sep 17 00:00:00 2001 From: "Liam P. White" Date: Tue, 4 Mar 2014 21:24:03 -0500 Subject: Added a few swatch related functions (does not compile) (bzr r13090.1.15) --- src/sp-gradient-fns.h | 47 ++++++++ src/sp-tag-use-reference.cpp | 147 ++++++++++++++++++++++ src/sp-tag-use-reference.h | 77 ++++++++++++ src/sp-tag-use.cpp | 281 +++++++++++++++++++++++++++++++++++++++++++ src/sp-tag-use.h | 53 ++++++++ src/sp-tag.cpp | 240 ++++++++++++++++++++++++++++++++++++ src/sp-tag.h | 55 +++++++++ src/ui/dialog/swatches.cpp | 2 +- src/ui/widget/addtoicon.cpp | 149 +++++++++++++++++++++++ src/ui/widget/addtoicon.h | 98 +++++++++++++++ 10 files changed, 1148 insertions(+), 1 deletion(-) create mode 100644 src/sp-gradient-fns.h create mode 100644 src/sp-tag-use-reference.cpp create mode 100644 src/sp-tag-use-reference.h create mode 100644 src/sp-tag-use.cpp create mode 100644 src/sp-tag-use.h create mode 100644 src/sp-tag.cpp create mode 100644 src/sp-tag.h create mode 100644 src/ui/widget/addtoicon.cpp create mode 100644 src/ui/widget/addtoicon.h (limited to 'src') diff --git a/src/sp-gradient-fns.h b/src/sp-gradient-fns.h new file mode 100644 index 000000000..e57877256 --- /dev/null +++ b/src/sp-gradient-fns.h @@ -0,0 +1,47 @@ +#ifndef SEEN_SP_GRADIENT_FNS_H +#define SEEN_SP_GRADIENT_FNS_H + +/** \file + * Macros and fn declarations related to gradients. + */ + +#include +#include +#include <2geom/forward.h> +#include "sp-gradient-spread.h" +#include "sp-gradient-units.h" + +class SPGradient; +class SPMeshGradient; + +SPGradientSpread sp_gradient_get_spread (SPGradient *gradient); + +/* Gradient repr methods */ +void sp_gradient_repr_write_vector(SPGradient *gr); +void sp_gradient_repr_clear_vector(SPGradient *gr); + +void sp_meshgradient_repr_write(SPMeshGradient *mg); + +cairo_pattern_t *sp_gradient_create_preview_pattern(SPGradient *gradient, double width); + +/** Transforms to/from gradient position space in given environment */ +Geom::Affine sp_gradient_get_g2d_matrix(SPGradient const *gr, Geom::Affine const &ctm, + Geom::Rect const &bbox); +Geom::Affine sp_gradient_get_gs2d_matrix(SPGradient const *gr, Geom::Affine const &ctm, + Geom::Rect const &bbox); +void sp_gradient_set_gs2d_matrix(SPGradient *gr, Geom::Affine const &ctm, Geom::Rect const &bbox, + Geom::Affine const &gs2d); + + +#endif /* !SEEN_SP_GRADIENT_FNS_H */ + +/* + 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 : diff --git a/src/sp-tag-use-reference.cpp b/src/sp-tag-use-reference.cpp new file mode 100644 index 000000000..8e48c0285 --- /dev/null +++ b/src/sp-tag-use-reference.cpp @@ -0,0 +1,147 @@ +/* + * The reference corresponding to href of element. + * + * Copyright (C) Theodore Janeczko 2012 + * + * Released under GNU GPL, read the file 'COPYING' for more information. + */ + +#include +#include +#include + +#include "enums.h" +#include "sp-tag-use-reference.h" + +#include "display/curve.h" +#include "livarot/Path.h" +#include "preferences.h" +#include "sp-shape.h" +#include "sp-text.h" +#include "uri.h" + + + +bool SPTagUseReference::_acceptObject(SPObject * const obj) const +{ + if (SP_IS_ITEM(obj)) { + SPObject * const owner = getOwner(); + // Refuse references to us or to an ancestor. + for ( SPObject *iter = owner ; iter ; iter = iter->parent ) { + if ( iter == obj ) { + return false; + } + } + return true; + } else { + return false; + } +} + + +static void sp_usepath_href_changed(SPObject *old_ref, SPObject *ref, SPTagUsePath *offset); +static void sp_usepath_delete_self(SPObject *deleted, SPTagUsePath *offset); + +SPTagUsePath::SPTagUsePath(SPObject* i_owner):SPTagUseReference(i_owner) +{ + owner=i_owner; + originalPath = NULL; + sourceDirty=false; + sourceHref = NULL; + sourceRepr = NULL; + sourceObject = NULL; + _changed_connection = changedSignal().connect(sigc::bind(sigc::ptr_fun(sp_usepath_href_changed), this)); // listening to myself, this should be virtual instead + + user_unlink = NULL; +} + +SPTagUsePath::~SPTagUsePath(void) +{ + delete originalPath; + originalPath = NULL; + + _changed_connection.disconnect(); // to do before unlinking + + quit_listening(); + unlink(); +} + +void +SPTagUsePath::link(char *to) +{ + if ( to == NULL ) { + quit_listening(); + unlink(); + } else { + if ( !sourceHref || ( strcmp(to, sourceHref) != 0 ) ) { + g_free(sourceHref); + sourceHref = g_strdup(to); + try { + attach(Inkscape::URI(to)); + } catch (Inkscape::BadURIException &e) { + /* TODO: Proper error handling as per + * http://www.w3.org/TR/SVG11/implnote.html#ErrorProcessing. + */ + g_warning("%s", e.what()); + detach(); + } + } + } +} + +void +SPTagUsePath::unlink(void) +{ + g_free(sourceHref); + sourceHref = NULL; + detach(); +} + +void +SPTagUsePath::start_listening(SPObject* to) +{ + if ( to == NULL ) { + return; + } + sourceObject = to; + sourceRepr = to->getRepr(); + _delete_connection = to->connectDelete(sigc::bind(sigc::ptr_fun(&sp_usepath_delete_self), this)); +} + +void +SPTagUsePath::quit_listening(void) +{ + if ( sourceObject == NULL ) { + return; + } + _delete_connection.disconnect(); + sourceRepr = NULL; + sourceObject = NULL; +} + +static void +sp_usepath_href_changed(SPObject */*old_ref*/, SPObject */*ref*/, SPTagUsePath *offset) +{ + offset->quit_listening(); + SPItem *refobj = offset->getObject(); + if ( refobj ) { + offset->start_listening(refobj); + } +} + +static void +sp_usepath_delete_self(SPObject */*deleted*/, SPTagUsePath *offset) +{ + offset->owner->deleteObject(); +} + +/* + 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 : diff --git a/src/sp-tag-use-reference.h b/src/sp-tag-use-reference.h new file mode 100644 index 000000000..039d2fd7d --- /dev/null +++ b/src/sp-tag-use-reference.h @@ -0,0 +1,77 @@ +#ifndef SEEN_SP_TAG_USE_REFERENCE_H +#define SEEN_SP_TAG_USE_REFERENCE_H + +/* + * The reference corresponding to href of element. + * + * Copyright (C) Theodore Janeczko 2012 + * + * Released under GNU GPL, read the file 'COPYING' for more information. + */ + +#include "sp-object.h" +#include "sp-item.h" +#include +#include +#include + +class Path; + +namespace Inkscape { +namespace XML { + struct Node; +} +} + + +class SPTagUseReference : public Inkscape::URIReference { +public: + SPTagUseReference(SPObject *owner) : URIReference(owner) {} + + SPItem *getObject() const { + return static_cast(URIReference::getObject()); + } + +protected: + virtual bool _acceptObject(SPObject * const obj) const; + +}; + + +class SPTagUsePath : public SPTagUseReference { +public: + Path *originalPath; + bool sourceDirty; + + SPObject *owner; + gchar *sourceHref; + Inkscape::XML::Node *sourceRepr; + SPObject *sourceObject; + + sigc::connection _delete_connection; + sigc::connection _changed_connection; + + SPTagUsePath(SPObject* i_owner); + ~SPTagUsePath(void); + + void link(char* to); + void unlink(void); + void start_listening(SPObject* to); + void quit_listening(void); + void refresh_source(void); + + void (*user_unlink) (SPObject *user); +}; + +#endif /* !SEEN_SP_USE_REFERENCE_H */ + +/* + 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 : diff --git a/src/sp-tag-use.cpp b/src/sp-tag-use.cpp new file mode 100644 index 000000000..4c5171bbb --- /dev/null +++ b/src/sp-tag-use.cpp @@ -0,0 +1,281 @@ +/* + * SVG implementation + * + * Authors: + * Theodore Janeczko + * + * Copyright (C) Theodore Janeczko 2012 + * + * Released under GNU GPL, read the file 'COPYING' for more information + */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include +#include + +#include +#include "display/drawing-group.h" +#include "attributes.h" +#include "document.h" +#include "sp-object-repr.h" +#include "uri.h" +#include "xml/repr.h" +#include "preferences.h" +#include "style.h" +#include "sp-symbol.h" +#include "sp-tag-use.h" +#include "sp-tag-use-reference.h" + +/* fixme: */ + +static void sp_tag_use_class_init(SPTagUseClass *classname); +static void sp_tag_use_init(SPTagUse *use); +static void sp_tag_use_finalize(GObject *obj); + +static void sp_tag_use_build(SPObject *object, SPDocument *document, Inkscape::XML::Node *repr); +static void sp_tag_use_release(SPObject *object); +static void sp_tag_use_set(SPObject *object, unsigned key, gchar const *value); +static Inkscape::XML::Node *sp_tag_use_write(SPObject *object, Inkscape::XML::Document *doc, Inkscape::XML::Node *repr, guint flags); +static void sp_tag_use_update(SPObject *object, SPCtx *ctx, guint flags); + +static void sp_tag_use_href_changed(SPObject *old_ref, SPObject *ref, SPTagUse *use); + +static SPObjectClass *parent_class; + + +GType +sp_tag_use_get_type(void) +{ + static GType use_type = 0; + if (!use_type) { + GTypeInfo use_info = { + sizeof(SPTagUseClass), + NULL, /* base_init */ + NULL, /* base_finalize */ + (GClassInitFunc) sp_tag_use_class_init, + NULL, /* class_finalize */ + NULL, /* class_data */ + sizeof(SPTagUse), + 16, /* n_preallocs */ + (GInstanceInitFunc) sp_tag_use_init, + NULL, /* value_table */ + }; + use_type = g_type_register_static(SP_TYPE_OBJECT, "SPTagUse", &use_info, (GTypeFlags)0); + } + return use_type; +} + +static void +sp_tag_use_class_init(SPTagUseClass *classname) +{ + GObjectClass *gobject_class = (GObjectClass *) classname; + SPObjectClass *sp_object_class = (SPObjectClass *) classname; + + parent_class = (SPObjectClass*)g_type_class_peek_parent(classname); + + gobject_class->finalize = sp_tag_use_finalize; + + sp_object_class->build = sp_tag_use_build; + sp_object_class->release = sp_tag_use_release; + sp_object_class->set = sp_tag_use_set; + sp_object_class->write = sp_tag_use_write; + sp_object_class->update = sp_tag_use_update; +} + +static void +sp_tag_use_init(SPTagUse *use) +{ + use->href = NULL; + + new (&use->_changed_connection) sigc::connection(); + + use->ref = new SPTagUseReference(use); + + use->_changed_connection = use->ref->changedSignal().connect(sigc::bind(sigc::ptr_fun(sp_tag_use_href_changed), use)); +} + +static void +sp_tag_use_finalize(GObject *obj) +{ + SPTagUse *use = reinterpret_cast(obj); + + if (use->child) { + use->detach(use->child); + use->child = NULL; + } + + use->ref->detach(); + delete use->ref; + use->ref = 0; + + use->_changed_connection.~connection(); + +} + +static void +sp_tag_use_build(SPObject *object, SPDocument *document, Inkscape::XML::Node *repr) +{ + if (((SPObjectClass *) parent_class)->build) { + (* ((SPObjectClass *) parent_class)->build)(object, document, repr); + } + + object->readAttr( "xlink:href" ); + + // We don't need to create child here: + // reading xlink:href will attach ref, and that will cause the changed signal to be emitted, + // which will call sp_tag_use_href_changed, and that will take care of the child +} + +static void +sp_tag_use_release(SPObject *object) +{ + SPTagUse *use = SP_TAG_USE(object); + + if (use->child) { + object->detach(use->child); + use->child = NULL; + } + + use->_changed_connection.disconnect(); + + g_free(use->href); + use->href = NULL; + + use->ref->detach(); + + if (((SPObjectClass *) parent_class)->release) { + ((SPObjectClass *) parent_class)->release(object); + } +} + +static void +sp_tag_use_set(SPObject *object, unsigned key, gchar const *value) +{ + SPTagUse *use = SP_TAG_USE(object); + + switch (key) { + case SP_ATTR_XLINK_HREF: { + if ( value && use->href && ( strcmp(value, use->href) == 0 ) ) { + /* No change, do nothing. */ + } else { + g_free(use->href); + use->href = NULL; + if (value) { + // First, set the href field, because sp_tag_use_href_changed will need it. + use->href = g_strdup(value); + + // Now do the attaching, which emits the changed signal. + try { + use->ref->attach(Inkscape::URI(value)); + } catch (Inkscape::BadURIException &e) { + g_warning("%s", e.what()); + use->ref->detach(); + } + } else { + use->ref->detach(); + } + } + break; + } + + default: + if (((SPObjectClass *) parent_class)->set) { + ((SPObjectClass *) parent_class)->set(object, key, value); + } + break; + } +} + +static Inkscape::XML::Node * +sp_tag_use_write(SPObject *object, Inkscape::XML::Document *xml_doc, Inkscape::XML::Node *repr, guint flags) +{ + SPTagUse *use = SP_TAG_USE(object); + + if ((flags & SP_OBJECT_WRITE_BUILD) && !repr) { + repr = xml_doc->createElement("inkscape:tagref"); + } + + if (((SPObjectClass *) (parent_class))->write) { + ((SPObjectClass *) (parent_class))->write(object, xml_doc, repr, flags); + } + + if (use->ref->getURI()) { + gchar *uri_string = use->ref->getURI()->toString(); + repr->setAttribute("xlink:href", uri_string); + g_free(uri_string); + } + + return repr; +} + +/** + * Returns the ultimate original of a SPTagUse (i.e. the first object in the chain of its originals + * which is not an SPTagUse). If no original is found, NULL is returned (it is the responsibility + * of the caller to make sure that this is handled correctly). + * + * Note that the returned is the clone object, i.e. the child of an SPTagUse (of the argument one for + * the trivial case) and not the "true original". + */ +SPItem * +sp_tag_use_root(SPTagUse *use) +{ + SPObject *orig = use->child; + while (orig && SP_IS_TAG_USE(orig)) { + orig = SP_TAG_USE(orig)->child; + } + if (!orig || !SP_IS_ITEM(orig)) + return NULL; + return SP_ITEM(orig); +} + +static void +sp_tag_use_href_changed(SPObject */*old_ref*/, SPObject */*ref*/, SPTagUse *use) +{ + if (use->href) { + SPItem *refobj = use->ref->getObject(); + if (refobj) { + Inkscape::XML::Node *childrepr = refobj->getRepr(); + GType type = sp_repr_type_lookup(childrepr); + g_return_if_fail(type > G_TYPE_NONE); + if (g_type_is_a(type, SP_TYPE_ITEM)) { + use->child = (SPObject*) g_object_new(type, 0); + use->attach(use->child, use->lastChild()); + sp_object_unref(use->child, use); + (use->child)->invoke_build(use->document, childrepr, TRUE); + + } + } + } +} + +static void +sp_tag_use_update(SPObject *object, SPCtx *ctx, unsigned flags) +{ + if (((SPObjectClass *) (parent_class))->update) + ((SPObjectClass *) (parent_class))->update(object, ctx, flags); +} + +SPItem *sp_tag_use_get_original(SPTagUse *use) +{ + SPItem *ref = NULL; + if (use){ + if (use->ref){ + ref = use->ref->getObject(); + } + } + return ref; +} + +/* + 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 : diff --git a/src/sp-tag-use.h b/src/sp-tag-use.h new file mode 100644 index 000000000..6e068fc21 --- /dev/null +++ b/src/sp-tag-use.h @@ -0,0 +1,53 @@ +#ifndef __SP_TAG_USE_H__ +#define __SP_TAG_USE_H__ + +/* + * SVG implementation + * + * Authors: + * Theodore Janeczko + * + * Copyright (C) Theodore Janeczko 2012 + * + * Released under GNU GPL, read the file 'COPYING' for more information + */ + +#include +#include +#include "svg/svg-length.h" +#include "sp-object.h" + + +#define SP_TYPE_TAG_USE (sp_tag_use_get_type ()) +#define SP_TAG_USE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), SP_TYPE_TAG_USE, SPTagUse)) +#define SP_TAG_USE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), SP_TYPE_TAG_USE, SPTagUseClass)) +#define SP_IS_TAG_USE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), SP_TYPE_TAG_USE)) +#define SP_IS_TAG_USE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), SP_TYPE_TAG_USE)) + +class SPTagUse; +class SPTagUseClass; +class SPTagUseReference; + +struct SPTagUse : public SPObject { + // item built from the original's repr (the visible clone) + // relative to the SPUse itself, it is treated as a child, similar to a grouped item relative to its group + SPObject *child; + + gchar *href; + + // the reference to the original object + SPTagUseReference *ref; + sigc::connection _changed_connection; +}; + +struct SPTagUseClass { + SPObjectClass parent_class; +}; + +GType sp_tag_use_get_type (void); + +SPItem *sp_tag_use_unlink (SPTagUse *use); +SPItem *sp_tag_use_get_original (SPTagUse *use); + +SPItem *sp_tag_use_root(SPTagUse *use); +#endif diff --git a/src/sp-tag.cpp b/src/sp-tag.cpp new file mode 100644 index 000000000..eef55d628 --- /dev/null +++ b/src/sp-tag.cpp @@ -0,0 +1,240 @@ +/** \file + * SVG implementation + * + * Authors: + * Theodore Janeczko + * + * Copyright (C) Theodore Janeczko 2012 + * + * Released under GNU GPL, read the file 'COPYING' for more information + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include "attributes.h" +#include "sp-tag.h" +#include "xml/repr.h" +#include + +#define DEBUG_TAG +#ifdef DEBUG_TAG +# define debug(f, a...) { g_print("%s(%d) %s:", \ + __FILE__,__LINE__,__FUNCTION__); \ + g_print(f, ## a); \ + g_print("\n"); \ + } +#else +# define debug(f, a...) /**/ +#endif + +/* Tag base class */ + +static void sp_tag_class_init(SPTagClass *klass); +static void sp_tag_init(SPTag *tag); + +static void sp_tag_build(SPObject *object, SPDocument *document, Inkscape::XML::Node *repr); +static void sp_tag_release(SPObject *object); +static void sp_tag_set(SPObject *object, unsigned int key, gchar const *value); +static void sp_tag_update(SPObject *object, SPCtx *ctx, guint flags); +static Inkscape::XML::Node *sp_tag_write(SPObject *object, Inkscape::XML::Document *doc, Inkscape::XML::Node *repr, guint flags); + +static SPObjectClass *tag_parent_class; + +GType +sp_tag_get_type() +{ + static GType tag_type = 0; + + if (!tag_type) { + GTypeInfo tag_info = { + sizeof(SPTagClass), + NULL, NULL, + (GClassInitFunc) sp_tag_class_init, + NULL, NULL, + sizeof(SPTag), + 16, + (GInstanceInitFunc) sp_tag_init, + NULL, /* value_table */ + }; + tag_type = g_type_register_static(SP_TYPE_OBJECT, "SPTag", &tag_info, (GTypeFlags)0); + } + return tag_type; +} + +static void +sp_tag_class_init(SPTagClass *klass) +{ + //GObjectClass *gobject_class = (GObjectClass *)klass; + SPObjectClass *sp_object_class = (SPObjectClass *)klass; + + tag_parent_class = (SPObjectClass*)g_type_class_peek_parent(klass); + + sp_object_class->build = sp_tag_build; + sp_object_class->release = sp_tag_release; + sp_object_class->write = sp_tag_write; + sp_object_class->set = sp_tag_set; + sp_object_class->update = sp_tag_update; +} + +static void +sp_tag_init(SPTag *tag) +{ +} + +/* + * Move this SPItem into or after another SPItem in the doc + * \param target - the SPItem to move into or after + * \param intoafter - move to after the target (false), move inside (sublayer) of the target (true) + */ +void SPTag::moveTo(SPObject *target, gboolean intoafter) { + + Inkscape::XML::Node *target_ref = ( target ? target->getRepr() : NULL ); + Inkscape::XML::Node *our_ref = getRepr(); + gboolean first = FALSE; + + if (target_ref == our_ref) { + // Move to ourself ignore + return; + } + + if (!target_ref) { + // Assume move to the "first" in the top node, find the top node + target_ref = our_ref; + while (target_ref->parent() != target_ref->root()) { + target_ref = target_ref->parent(); + } + first = TRUE; + } + + if (intoafter) { + // Move this inside of the target at the end + our_ref->parent()->removeChild(our_ref); + target_ref->addChild(our_ref, NULL); + } else if (target_ref->parent() != our_ref->parent()) { + // Change in parent, need to remove and add + our_ref->parent()->removeChild(our_ref); + target_ref->parent()->addChild(our_ref, target_ref); + } else if (!first) { + // Same parent, just move + our_ref->parent()->changeOrder(our_ref, target_ref); + } +} + +/** + * Reads the Inkscape::XML::Node, and initializes SPTag variables. For this to get called, + * our name must be associated with a repr via "sp_object_type_register". Best done through + * sp-object-repr.cpp's repr_name_entries array. + */ +static void +sp_tag_build(SPObject *object, SPDocument *document, Inkscape::XML::Node *repr) +{ + object->readAttr( "inkscape:expanded" ); + + if (((SPObjectClass *) tag_parent_class)->build) { + ((SPObjectClass *) tag_parent_class)->build(object, document, repr); + } +} + +/** + * Drops any allocated memory. + */ +static void +sp_tag_release(SPObject *object) +{ + /* deal with our children and our selves here */ + + if (((SPObjectClass *) tag_parent_class)->release) + ((SPObjectClass *) tag_parent_class)->release(object); +} + +/** + * Sets a specific value in the SPTag. + */ +static void +sp_tag_set(SPObject *object, unsigned int key, gchar const *value) +{ + SPTag *tag = SP_TAG(object); + + switch (key) + { + case SP_ATTR_INKSCAPE_EXPANDED: + if ( value && !strcmp(value, "true") ) { + tag->setExpanded(true); + } + break; + default: + if (((SPObjectClass *) tag_parent_class)->set) { + ((SPObjectClass *) tag_parent_class)->set(object, key, value); + } + break; + } +} + +void SPTag::setExpanded(bool isexpanded) { + if ( _expanded != isexpanded ){ + _expanded = isexpanded; + } +} + +/** + * Receives update notifications. + */ +static void +sp_tag_update(SPObject *object, SPCtx *ctx, guint flags) +{ + //SPTag *tag = SP_TAG(object); + + if (flags & (SP_OBJECT_MODIFIED_FLAG | SP_OBJECT_STYLE_MODIFIED_FLAG | + SP_OBJECT_VIEWPORT_MODIFIED_FLAG)) { + + /* do something to trigger redisplay, updates? */ + + } + + if (((SPObjectClass *) tag_parent_class)->update) { + ((SPObjectClass *) tag_parent_class)->update(object, ctx, flags); + } +} + +/** + * Writes its settings to an incoming repr object, if any. + */ +static Inkscape::XML::Node * +sp_tag_write(SPObject *object, Inkscape::XML::Document *doc, Inkscape::XML::Node *repr, guint flags) +{ + SPTag *tag = SP_TAG(object); + + if ((flags & SP_OBJECT_WRITE_BUILD) && !repr) { + repr = doc->createElement("inkscape:tag"); + } + + // Inkscape-only object, not copied during an "plain SVG" dump: + if (flags & SP_OBJECT_WRITE_EXT) { + + if (tag->_expanded) { + repr->setAttribute("inkscape:expanded", "true"); + } else { + repr->setAttribute("inkscape:expanded", NULL); + } + } + + if (((SPObjectClass *) tag_parent_class)->write) { + ((SPObjectClass *) tag_parent_class)->write(object, doc, repr, flags); + } + + return repr; +} + + +/* + 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 : diff --git a/src/sp-tag.h b/src/sp-tag.h new file mode 100644 index 000000000..c5eec785a --- /dev/null +++ b/src/sp-tag.h @@ -0,0 +1,55 @@ +#ifndef SP_TAG_H_SEEN +#define SP_TAG_H_SEEN + +/** \file + * SVG implementation + * + * Authors: + * Theodore Janeczko + * + * Copyright (C) Theodore Janeczko 2012 + * + * Released under GNU GPL, read the file 'COPYING' for more information + */ + +#include "sp-object.h" + +/* Skeleton base class */ + +#define SP_TYPE_TAG (sp_tag_get_type()) +#define SP_TAG(o) (G_TYPE_CHECK_INSTANCE_CAST((o), SP_TYPE_TAG, SPTag)) +#define SP_IS_TAG(o) (G_TYPE_CHECK_INSTANCE_TYPE((o), SP_TYPE_TAG)) + +class SPTag; +class SPTagClass; + +class SPTag : public SPObject { +public: + bool _expanded; + + bool expanded() const { return _expanded; } + void setExpanded(bool isexpanded); + + void moveTo(SPObject *target, gboolean intoafter); + +}; + +struct SPTagClass { + SPObjectClass parent_class; +}; + +GType sp_tag_get_type(); + + +#endif /* !SP_SKELETON_H_SEEN */ + +/* + 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 : diff --git a/src/ui/dialog/swatches.cpp b/src/ui/dialog/swatches.cpp index a0c79b8ac..2956c6d17 100644 --- a/src/ui/dialog/swatches.cpp +++ b/src/ui/dialog/swatches.cpp @@ -68,7 +68,7 @@ #include "sp-radial-gradient.h" #include "color-rgba.h" #include "svg/css-ostringstream.h" -//#include "event-context.h" //no longer exists +#include "ui/tools/tool-base.h" //event-context.h #include #ifdef WIN32 #include diff --git a/src/ui/widget/addtoicon.cpp b/src/ui/widget/addtoicon.cpp new file mode 100644 index 000000000..3d6091f70 --- /dev/null +++ b/src/ui/widget/addtoicon.cpp @@ -0,0 +1,149 @@ +/* + * Authors: + * Theodore Janeczko + * + * Copyright (C) Theodore Janeczko 2012 + * + * Released under GNU GPL, read the file 'COPYING' for more information + */ + + +#include "ui/widget/addtoicon.h" + +#include + +#include "widgets/icon.h" +#include "widgets/toolbox.h" +#include "ui/icon-names.h" +#include "layertypeicon.h" +#include "addtoicon.h" + +namespace Inkscape { +namespace UI { +namespace Widget { + +AddToIcon::AddToIcon() : + Glib::ObjectBase(typeid(AddToIcon)), + Gtk::CellRendererPixbuf(), +// _pixAddName(INKSCAPE_ICON("layer-new")), + _property_active(*this, "active", false) +// _property_pixbuf_add(*this, "pixbuf_on", Glib::RefPtr(0)) +{ + property_mode() = Gtk::CELL_RENDERER_MODE_ACTIVATABLE; + phys = sp_icon_get_phys_size((int)Inkscape::ICON_SIZE_BUTTON); +// Glib::RefPtr icon_theme = Gtk::IconTheme::get_default(); +// +// if (!icon_theme->has_icon(_pixAddName)) { +// Inkscape::queueIconPrerender( INKSCAPE_ICON(_pixAddName.data()), Inkscape::ICON_SIZE_DECORATION ); +// } +// if (icon_theme->has_icon(_pixAddName)) { +// _property_pixbuf_add = icon_theme->load_icon(_pixAddName, phys, (Gtk::IconLookupFlags)0); +// } +// +// _property_pixbuf_add = Gtk::Widget:: + + property_stock_id() = GTK_STOCK_ADD; +} + + +#if WITH_GTKMM_3_0 +void AddToIcon::get_preferred_height_vfunc(Gtk::Widget& widget, + int& min_h, + int& nat_h) const +{ + Gtk::CellRendererPixbuf::get_preferred_height_vfunc(widget, min_h, nat_h); + + if (min_h) { + min_h += (min_h) >> 1; + } + + if (nat_h) { + nat_h += (nat_h) >> 1; + } +} + +void AddToIcon::get_preferred_width_vfunc(Gtk::Widget& widget, + int& min_w, + int& nat_w) const +{ + Gtk::CellRendererPixbuf::get_preferred_width_vfunc(widget, min_w, nat_w); + + if (min_w) { + min_w += (min_w) >> 1; + } + + if (nat_w) { + nat_w += (nat_w) >> 1; + } +} +#else +void AddToIcon::get_size_vfunc(Gtk::Widget& widget, + const Gdk::Rectangle* cell_area, + int* x_offset, + int* y_offset, + int* width, + int* height ) const +{ + Gtk::CellRendererPixbuf::get_size_vfunc( widget, cell_area, x_offset, y_offset, width, height ); + + if ( width ) { + *width = phys;//+= (*width) >> 1; + } + if ( height ) { + *height =phys;//+= (*height) >> 1; + } +} +#endif + +#if WITH_GTKMM_3_0 +void AddToIcon::render_vfunc( const Cairo::RefPtr& cr, + Gtk::Widget& widget, + const Gdk::Rectangle& background_area, + const Gdk::Rectangle& cell_area, + Gtk::CellRendererState flags ) +#else +void AddToIcon::render_vfunc( const Glib::RefPtr& window, + Gtk::Widget& widget, + const Gdk::Rectangle& background_area, + const Gdk::Rectangle& cell_area, + const Gdk::Rectangle& expose_area, + Gtk::CellRendererState flags ) +#endif +{ + property_stock_id() = property_active().get_value() ? GTK_STOCK_ADD : GTK_STOCK_DELETE; + +#if WITH_GTKMM_3_0 + Gtk::CellRendererPixbuf::render_vfunc( cr, widget, background_area, cell_area, flags ); +#else + Gtk::CellRendererPixbuf::render_vfunc( window, widget, background_area, cell_area, expose_area, flags ); +#endif +} + +bool +AddToIcon::activate_vfunc(GdkEvent* event, + Gtk::Widget& /*widget*/, + const Glib::ustring& path, + const Gdk::Rectangle& /*background_area*/, + const Gdk::Rectangle& /*cell_area*/, + Gtk::CellRendererState /*flags*/) +{ + return false; +} + + +} // namespace Widget +} // namespace UI +} // 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 : + + diff --git a/src/ui/widget/addtoicon.h b/src/ui/widget/addtoicon.h new file mode 100644 index 000000000..aa8b4148e --- /dev/null +++ b/src/ui/widget/addtoicon.h @@ -0,0 +1,98 @@ +#ifndef __UI_DIALOG_ADDTOICON_H__ +#define __UI_DIALOG_ADDTOICON_H__ +/* + * Authors: + * Theodore Janeczko + * + * Copyright (C) Theodore Janeczko 2012 + * + * Released under GNU GPL, read the file 'COPYING' for more information + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include + +namespace Inkscape { +namespace UI { +namespace Widget { + +class AddToIcon : public Gtk::CellRendererPixbuf { +public: + AddToIcon(); + virtual ~AddToIcon() {}; + + Glib::PropertyProxy property_active() { return _property_active.get_proxy(); } + Glib::PropertyProxy< Glib::RefPtr > property_pixbuf_on(); + Glib::PropertyProxy< Glib::RefPtr > property_pixbuf_off(); + +protected: + +#if WITH_GTKMM_3_0 + virtual void render_vfunc( const Cairo::RefPtr& cr, + Gtk::Widget& widget, + const Gdk::Rectangle& background_area, + const Gdk::Rectangle& cell_area, + Gtk::CellRendererState flags ); + + virtual void get_preferred_width_vfunc(Gtk::Widget& widget, + int& min_w, + int& nat_w) const; + + virtual void get_preferred_height_vfunc(Gtk::Widget& widget, + int& min_h, + int& nat_h) const; +#else + virtual void render_vfunc( const Glib::RefPtr& window, + Gtk::Widget& widget, + const Gdk::Rectangle& background_area, + const Gdk::Rectangle& cell_area, + const Gdk::Rectangle& expose_area, + Gtk::CellRendererState flags ); + + virtual void get_size_vfunc( Gtk::Widget &widget, + Gdk::Rectangle const *cell_area, + int *x_offset, int *y_offset, int *width, int *height ) const; +#endif + + virtual bool activate_vfunc(GdkEvent *event, + Gtk::Widget &widget, + const Glib::ustring &path, + const Gdk::Rectangle &background_area, + const Gdk::Rectangle &cell_area, + Gtk::CellRendererState flags); + + +private: + int phys; + +// Glib::ustring _pixAddName; + + Glib::Property _property_active; +// Glib::Property< Glib::RefPtr > _property_pixbuf_add; + +}; + + + +} // namespace Widget +} // namespace UI +} // namespace Inkscape + + +#endif /* __UI_DIALOG_IMAGETOGGLER_H__ */ + +/* + 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 From fcffbecabedd7c6bca1312918c918d57fee3cf8c Mon Sep 17 00:00:00 2001 From: "Liam P. White" Date: Wed, 5 Mar 2014 15:24:04 -0500 Subject: Added new swatches dialog (bzr r13090.1.16) --- src/ui/dialog/color-item.cpp | 860 ++++++++--------------------------------- src/ui/dialog/color-item.h | 108 ++---- src/ui/dialog/filedialog.h | 1 + src/ui/dialog/swatches.cpp | 48 +-- src/widgets/desktop-widget.cpp | 2 +- 5 files changed, 204 insertions(+), 815 deletions(-) (limited to 'src') diff --git a/src/ui/dialog/color-item.cpp b/src/ui/dialog/color-item.cpp index 7940c28ae..6eece0c17 100644 --- a/src/ui/dialog/color-item.cpp +++ b/src/ui/dialog/color-item.cpp @@ -11,18 +11,9 @@ * Released under GNU GPL, read the file 'COPYING' for more information */ -#ifdef HAVE_CONFIG_H -# include "config.h" -#endif - #include - -#if GLIBMM_DISABLE_DEPRECATED && HAVE_GLIBMM_THREADS_H -#include -#endif - -#include #include +#include #include #include @@ -45,6 +36,7 @@ #include "xml/repr.h" #include "verbs.h" #include "widgets/gradient-vector.h" +#include "sp-paint-server.h" #include "color.h" // for SP_RGBA32_U_COMPOSE @@ -53,756 +45,206 @@ namespace Inkscape { namespace UI { namespace Dialogs { -static std::vector mimeStrings; -static std::map mimeToInt; - -#if ENABLE_MAGIC_COLORS -// TODO remove this soon: -extern std::vector possible; -#endif // ENABLE_MAGIC_COLORS - - -#if ENABLE_MAGIC_COLORS -static bool bruteForce( SPDocument* document, Inkscape::XML::Node* node, Glib::ustring const& match, int r, int g, int b ) +bool ColorItem::on_enter_notify_event(GdkEventCrossing* event) { - bool changed = false; - - if ( node ) { - gchar const * val = node->attribute("inkscape:x-fill-tag"); - if ( val && (match == val) ) { - SPObject *obj = document->getObjectByRepr( node ); - - gchar c[64] = {0}; - sp_svg_write_color( c, sizeof(c), SP_RGBA32_U_COMPOSE( r, g, b, 0xff ) ); - SPCSSAttr *css = sp_repr_css_attr_new(); - sp_repr_css_set_property( css, "fill", c ); - - sp_desktop_apply_css_recursive( obj, css, true ); - static_cast(obj)->updateRepr(); - - changed = true; - } - - val = node->attribute("inkscape:x-stroke-tag"); - if ( val && (match == val) ) { - SPObject *obj = document->getObjectByRepr( node ); - - gchar c[64] = {0}; - sp_svg_write_color( c, sizeof(c), SP_RGBA32_U_COMPOSE( r, g, b, 0xff ) ); - SPCSSAttr *css = sp_repr_css_attr_new(); - sp_repr_css_set_property( css, "stroke", c ); - - sp_desktop_apply_css_recursive( (SPItem*)obj, css, true ); - ((SPItem*)obj)->updateRepr(); - - changed = true; - } - - Inkscape::XML::Node* first = node->firstChild(); - changed |= bruteForce( document, first, match, r, g, b ); - - changed |= bruteForce( document, node->next(), match, r, g, b ); - } - - return changed; -} -#endif // ENABLE_MAGIC_COLORS - -static void handleClick( GtkWidget* /*widget*/, gpointer callback_data ) { - ColorItem* item = reinterpret_cast(callback_data); - if ( item ) { - item->buttonClicked(false); - } -} - -static void handleSecondaryClick( GtkWidget* /*widget*/, gint /*arg1*/, gpointer callback_data ) { - ColorItem* item = reinterpret_cast(callback_data); - if ( item ) { - item->buttonClicked(true); - } -} - -static gboolean handleEnterNotify( GtkWidget* /*widget*/, GdkEventCrossing* /*event*/, gpointer callback_data ) { - ColorItem* item = reinterpret_cast(callback_data); - if ( item ) { - SPDesktop *desktop = SP_ACTIVE_DESKTOP; - if ( desktop ) { - gchar* msg = g_strdup_printf(_("Color: %s; Click to set fill, Shift+click to set stroke"), - item->def.descr.c_str()); - desktop->tipsMessageContext()->set(Inkscape::INFORMATION_MESSAGE, msg); - g_free(msg); - } - } - return FALSE; -} - -static gboolean handleLeaveNotify( GtkWidget* /*widget*/, GdkEventCrossing* /*event*/, gpointer callback_data ) { - ColorItem* item = reinterpret_cast(callback_data); - if ( item ) { - SPDesktop *desktop = SP_ACTIVE_DESKTOP; - if ( desktop ) { - desktop->tipsMessageContext()->clear(); - } + SPDesktop *desktop = SP_ACTIVE_DESKTOP; + if ( desktop ) { + gchar* msg = g_strdup_printf(_("Color: %s; Click to set fill, Shift+click to set stroke"),def); + desktop->tipsMessageContext()->set(Inkscape::INFORMATION_MESSAGE, msg); + g_free(msg); } - return FALSE; + return Gtk::Widget::on_enter_notify_event(event); } -static void dieDieDie( GObject *obj, gpointer user_data ) +bool ColorItem::on_leave_notify_event(GdkEventCrossing* event) { - g_message("die die die %p %p", obj, user_data ); -} - -static bool getBlock( std::string& dst, guchar ch, std::string const & str ) -{ - bool good = false; - std::string::size_type pos = str.find(ch); - if ( pos != std::string::npos ) - { - std::string::size_type pos2 = str.find( '(', pos ); - if ( pos2 != std::string::npos ) { - std::string::size_type endPos = str.find( ')', pos2 ); - if ( endPos != std::string::npos ) { - dst = str.substr( pos2 + 1, (endPos - pos2 - 1) ); - good = true; - } - } + SPDesktop *desktop = SP_ACTIVE_DESKTOP; + if ( desktop ) { + desktop->tipsMessageContext()->clear(); } - return good; + return Gtk::Widget::on_leave_notify_event(event); } -static bool popVal( guint64& numVal, std::string& str ) +void ColorItem::selection_modified(Selection* selection, guint flags) { - bool good = false; - std::string::size_type endPos = str.find(','); - if ( endPos == std::string::npos ) { - endPos = str.length(); - } - - if ( endPos != std::string::npos && endPos > 0 ) { - std::string xxx = str.substr( 0, endPos ); - const gchar* ptr = xxx.c_str(); - gchar* endPtr = 0; - numVal = g_ascii_strtoull( ptr, &endPtr, 10 ); - if ( (numVal == G_MAXUINT64) && (ERANGE == errno) ) { - // overflow - } else if ( (numVal == 0) && (endPtr == ptr) ) { - // failed conversion - } else { - good = true; - str.erase( 0, endPos + 1 ); - } - } - - return good; + selection_changed(selection); } -// TODO resolve this more cleanly: -extern gboolean colorItemHandleButtonPress( GtkWidget* /*widget*/, GdkEventButton* event, gpointer user_data); - -static void colorItemDragBegin( GtkWidget */*widget*/, GdkDragContext* dc, gpointer data ) +void ColorItem::selection_changed(Selection* selection) { - ColorItem* item = reinterpret_cast(data); - if ( item ) + SPItem* item = selection->singleItem(); + SPPaintServer* grad; + if (item && + ( + (item->style->fill.isPaintserver() && + SP_IS_GRADIENT( (grad = item->style->getFillPaintServer()) ) + && SP_GRADIENT(grad)->getVector() == gradient) || + + (item->style->stroke.isPaintserver() && + SP_IS_GRADIENT( (grad = item->style->getStrokePaintServer()) ) && + SP_GRADIENT(grad)->getVector() == gradient) + ) + ) { - using Inkscape::IO::Resource::get_path; - using Inkscape::IO::Resource::ICONS; - using Inkscape::IO::Resource::SYSTEM; - int width = 32; - int height = 24; - - if (item->def.getType() != ege::PaintDef::RGB){ - GError *error = NULL; - gsize bytesRead = 0; - gsize bytesWritten = 0; - gchar *localFilename = g_filename_from_utf8( get_path(SYSTEM, ICONS, "remove-color.png"), - -1, - &bytesRead, - &bytesWritten, - &error); - GdkPixbuf* pixbuf = gdk_pixbuf_new_from_file_at_scale(localFilename, width, height, FALSE, &error); - g_free(localFilename); - gtk_drag_set_icon_pixbuf( dc, pixbuf, 0, 0 ); - } else { - GdkPixbuf* pixbuf = 0; - if ( item->getGradient() ){ - cairo_surface_t *s = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, width, height); - cairo_pattern_t *gradient = sp_gradient_create_preview_pattern(item->getGradient(), width); - cairo_t *ct = cairo_create(s); - cairo_set_source(ct, gradient); - cairo_paint(ct); - cairo_destroy(ct); - cairo_pattern_destroy(gradient); - cairo_surface_flush(s); - - pixbuf = ink_pixbuf_create_from_cairo_surface(s); - } else { - Glib::RefPtr thumb = Gdk::Pixbuf::create( Gdk::COLORSPACE_RGB, false, 8, width, height ); - guint32 fillWith = (0xff000000 & (item->def.getR() << 24)) - | (0x00ff0000 & (item->def.getG() << 16)) - | (0x0000ff00 & (item->def.getB() << 8)); - thumb->fill( fillWith ); - pixbuf = thumb->gobj(); - g_object_ref(G_OBJECT(pixbuf)); - } - gtk_drag_set_icon_pixbuf( dc, pixbuf, 0, 0 ); + if (!_isSelected) { + _isSelected = true; + queue_draw(); } + } else if (_isSelected) { + _isSelected = false; + queue_draw(); } - -} - -//"drag-drop" -// gboolean dragDropColorData( GtkWidget *widget, -// GdkDragContext *drag_context, -// gint x, -// gint y, -// guint time, -// gpointer user_data) -// { -// // TODO finish - -// return TRUE; -// } - - -SwatchPage::SwatchPage() - : _prefWidth(0) -{ -} - -SwatchPage::~SwatchPage() -{ -} - - -ColorItem::ColorItem(ege::PaintDef::ColorType type) : - def(type), - _isFill(false), - _isStroke(false), - _isLive(false), - _linkIsTone(false), - _linkPercent(0), - _linkGray(0), - _linkSrc(0), - _grad(0), - _pattern(0) -{ -} - -ColorItem::ColorItem( unsigned int r, unsigned int g, unsigned int b, Glib::ustring& name ) : - def( r, g, b, name ), - _isFill(false), - _isStroke(false), - _isLive(false), - _linkIsTone(false), - _linkPercent(0), - _linkGray(0), - _linkSrc(0), - _grad(0), - _pattern(0) -{ -} - -ColorItem::~ColorItem() -{ - if (_pattern != NULL) { - cairo_pattern_destroy(_pattern); - } -} - -ColorItem::ColorItem(ColorItem const &other) : - Inkscape::UI::Previewable() -{ - if ( this != &other ) { - *this = other; - } -} - -ColorItem &ColorItem::operator=(ColorItem const &other) -{ - if ( this != &other ) { - def = other.def; - - // TODO - correct linkage - _linkSrc = other._linkSrc; - g_message("Erk!"); - } - return *this; } -void ColorItem::setState( bool fill, bool stroke ) +ColorItem::ColorItem( SPGradient* grad, const gchar* name, SPDesktop* desktop ) : + Glib::ObjectBase("coloritem"), + Gtk::Widget(), + def( name ), + gradient(grad), + _isSelected(false) { - if ( (_isFill != fill) || (_isStroke != stroke) ) { - _isFill = fill; - _isStroke = stroke; - - for ( std::vector::iterator it = _previews.begin(); it != _previews.end(); ++it ) { - Gtk::Widget* widget = *it; - if ( IS_EEK_PREVIEW(widget->gobj()) ) { - EekPreview * preview = EEK_PREVIEW(widget->gobj()); - - int val = eek_preview_get_linked( preview ); - val &= ~(PREVIEW_FILL | PREVIEW_STROKE); - if ( _isFill ) { - val |= PREVIEW_FILL; - } - if ( _isStroke ) { - val |= PREVIEW_STROKE; - } - eek_preview_set_linked( preview, static_cast(val) ); - } - } - } + set_has_window(true); + add_events(Gdk::BUTTON_PRESS_MASK); + add_events(Gdk::ENTER_NOTIFY_MASK | Gdk::LEAVE_NOTIFY_MASK); + sel_connection = desktop->selection->connectChanged(sigc::mem_fun(*this, &ColorItem::selection_changed)); + mod_connection = desktop->selection->connectModified(sigc::mem_fun(*this, &ColorItem::selection_modified)); + selection_changed(desktop->selection); } -void ColorItem::setGradient(SPGradient *grad) +void ColorItem::on_size_request(Gtk::Requisition* requisition) { - if (_grad != grad) { - _grad = grad; - // TODO regen and push to listeners - } - - setName( gr_prepare_label(_grad) ); + requisition->height = 20; + requisition->width = 20; } -void ColorItem::setName(const Glib::ustring name) +void ColorItem::on_size_allocate(Gtk::Allocation& allocation) { - //def.descr = name; - - for ( std::vector::iterator it = _previews.begin(); it != _previews.end(); ++it ) { - Gtk::Widget* widget = *it; - if ( IS_EEK_PREVIEW(widget->gobj()) ) { - gtk_widget_set_tooltip_text(GTK_WIDGET(widget->gobj()), name.c_str()); - } - else if ( GTK_IS_LABEL(widget->gobj()) ) { - gtk_label_set_text(GTK_LABEL(widget->gobj()), name.c_str()); - } + set_allocation(allocation); + if (m_refGdkWindow) + { + m_refGdkWindow->move_resize( allocation.get_x(), allocation.get_y(), allocation.get_width(), allocation.get_height() ); } } -void ColorItem::setPattern(cairo_pattern_t *pattern) +void ColorItem::on_map() { - if (pattern) { - cairo_pattern_reference(pattern); - } - if (_pattern) { - cairo_pattern_destroy(_pattern); - } - _pattern = pattern; - - _updatePreviews(); + Gtk::Widget::on_map(); } -void ColorItem::_dragGetColorData( GtkWidget */*widget*/, - GdkDragContext */*drag_context*/, - GtkSelectionData *data, - guint info, - guint /*time*/, - gpointer user_data) +void ColorItem::on_unmap() { - ColorItem* item = reinterpret_cast(user_data); - std::string key; - if ( info < mimeStrings.size() ) { - key = mimeStrings[info]; - } else { - g_warning("ERROR: unknown value (%d)", info); - } - - if ( !key.empty() ) { - char* tmp = 0; - int len = 0; - int format = 0; - item->def.getMIMEData(key, tmp, len, format); - if ( tmp ) { - GdkAtom dataAtom = gdk_atom_intern( key.c_str(), FALSE ); - gtk_selection_data_set( data, dataAtom, format, (guchar*)tmp, len ); - delete[] tmp; - } - } + Gtk::Widget::on_unmap(); } -void ColorItem::_dropDataIn( GtkWidget */*widget*/, - GdkDragContext */*drag_context*/, - gint /*x*/, gint /*y*/, - GtkSelectionData */*data*/, - guint /*info*/, - guint /*event_time*/, - gpointer /*user_data*/) +void ColorItem::on_realize() { + set_realized(); + ensure_style(); + + if(!m_refGdkWindow) + { + //Create the GdkWindow: + + GdkWindowAttr attributes; + memset(&attributes, 0, sizeof(attributes)); + + Gtk::Allocation allocation = get_allocation(); + + //Set initial position and size of the Gdk::Window: + attributes.x = allocation.get_x(); + attributes.y = allocation.get_y(); + attributes.width = allocation.get_width(); + attributes.height = allocation.get_height(); + + attributes.event_mask = get_events () | Gdk::EXPOSURE_MASK; + attributes.window_type = GDK_WINDOW_CHILD; + attributes.wclass = GDK_INPUT_OUTPUT; + + m_refGdkWindow = Gdk::Window::create(get_parent_window(), &attributes, + GDK_WA_X | GDK_WA_Y); + set_window(m_refGdkWindow); + + //Attach this widget's style to its Gdk::Window. + style_attach(); + + //make the widget receive expose events + m_refGdkWindow->set_user_data(gobj()); + } } -void ColorItem::_colorDefChanged(void* data) +void ColorItem::on_unrealize() { - ColorItem* item = reinterpret_cast(data); - if ( item ) { - item->_updatePreviews(); - } + m_refGdkWindow.reset(); + + Gtk::Widget::on_unrealize(); } -void ColorItem::_updatePreviews() +bool ColorItem::on_expose_event(GdkEventExpose* event) { - for ( std::vector::iterator it = _previews.begin(); it != _previews.end(); ++it ) { - Gtk::Widget* widget = *it; - if ( IS_EEK_PREVIEW(widget->gobj()) ) { - EekPreview * preview = EEK_PREVIEW(widget->gobj()); - - _regenPreview(preview); - - widget->queue_draw(); - } - } - - for ( std::vector::iterator it = _listeners.begin(); it != _listeners.end(); ++it ) { - guint r = def.getR(); - guint g = def.getG(); - guint b = def.getB(); - - if ( (*it)->_linkIsTone ) { - r = ( ((*it)->_linkPercent * (*it)->_linkGray) + ((100 - (*it)->_linkPercent) * r) ) / 100; - g = ( ((*it)->_linkPercent * (*it)->_linkGray) + ((100 - (*it)->_linkPercent) * g) ) / 100; - b = ( ((*it)->_linkPercent * (*it)->_linkGray) + ((100 - (*it)->_linkPercent) * b) ) / 100; - } else { - r = ( ((*it)->_linkPercent * 255) + ((100 - (*it)->_linkPercent) * r) ) / 100; - g = ( ((*it)->_linkPercent * 255) + ((100 - (*it)->_linkPercent) * g) ) / 100; - b = ( ((*it)->_linkPercent * 255) + ((100 - (*it)->_linkPercent) * b) ) / 100; - } - - (*it)->def.setRGB( r, g, b ); - } - - -#if ENABLE_MAGIC_COLORS - // Look for objects using this color + if(m_refGdkWindow) { - SPDesktop *desktop = SP_ACTIVE_DESKTOP; - if ( desktop ) { - SPDocument* document = sp_desktop_document( desktop ); - Inkscape::XML::Node *rroot = document->getReprRoot(); - if ( rroot ) { - - // Find where this thing came from - Glib::ustring paletteName; - bool found = false; - int index = 0; - for ( std::vector::iterator it2 = possible.begin(); it2 != possible.end() && !found; ++it2 ) { - SwatchPage* curr = *it2; - index = 0; - for ( boost::ptr_vector::iterator zz = curr->_colors.begin(); zz != curr->_colors.end(); ++zz ) { - if ( this == &*zz ) { - found = true; - paletteName = curr->_name; - break; - } else { - index++; - } - } - } - - if ( !paletteName.empty() ) { - gchar* str = g_strdup_printf("%d|", index); - paletteName.insert( 0, str ); - g_free(str); - str = 0; - - if ( bruteForce( document, rroot, paletteName, def.getR(), def.getG(), def.getB() ) ) { - SPDocumentUndo::done( document , SP_VERB_DIALOG_SWATCHES, - _("Change color definition")); - } - } - } - } - } -#endif // ENABLE_MAGIC_COLORS - -} - -void ColorItem::_regenPreview(EekPreview * preview) -{ - if ( def.getType() != ege::PaintDef::RGB ) { - using Inkscape::IO::Resource::get_path; - using Inkscape::IO::Resource::ICONS; - using Inkscape::IO::Resource::SYSTEM; - GError *error = NULL; - gsize bytesRead = 0; - gsize bytesWritten = 0; - gchar *localFilename = g_filename_from_utf8( get_path(SYSTEM, ICONS, "remove-color.png"), - -1, - &bytesRead, - &bytesWritten, - &error); - GdkPixbuf* pixbuf = gdk_pixbuf_new_from_file(localFilename, &error); - if (!pixbuf) { - g_warning("Null pixbuf for %p [%s]", localFilename, localFilename ); - } - g_free(localFilename); - - eek_preview_set_pixbuf( preview, pixbuf ); - } - else if ( !_pattern ){ - eek_preview_set_color( preview, - (def.getR() << 8) | def.getR(), - (def.getG() << 8) | def.getG(), - (def.getB() << 8) | def.getB() ); - } else { - // These correspond to PREVIEW_PIXBUF_WIDTH and VBLOCK from swatches.cpp - // TODO: the pattern to draw should be in the widget that draws the preview, - // so the preview can be scalable - int w = 128; - int h = 16; - - cairo_surface_t *s = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, w, h); - cairo_t *ct = cairo_create(s); - cairo_set_source(ct, _pattern); - cairo_paint(ct); - cairo_destroy(ct); - cairo_surface_flush(s); - - GdkPixbuf* pixbuf = ink_pixbuf_create_from_cairo_surface(s); - eek_preview_set_pixbuf( preview, pixbuf ); - } - - eek_preview_set_linked( preview, (LinkType)((_linkSrc ? PREVIEW_LINK_IN:0) - | (_listeners.empty() ? 0:PREVIEW_LINK_OUT) - | (_isLive ? PREVIEW_LINK_OTHER:0)) ); -} - -Gtk::Widget* ColorItem::getPreview(PreviewStyle style, ViewType view, ::PreviewSize size, guint ratio, guint border) -{ - Gtk::Widget* widget = 0; - if ( style == PREVIEW_STYLE_BLURB) { - Gtk::Label *lbl = new Gtk::Label(def.descr); - lbl->set_alignment(Gtk::ALIGN_START, Gtk::ALIGN_CENTER); - widget = lbl; - } else { - GtkWidget* eekWidget = eek_preview_new(); - EekPreview * preview = EEK_PREVIEW(eekWidget); - Gtk::Widget* newBlot = Glib::wrap(eekWidget); - _regenPreview(preview); - - eek_preview_set_details( preview, - (::ViewType)view, - (::PreviewSize)size, - ratio, - border ); - - def.addCallback( _colorDefChanged, this ); - eek_preview_set_focus_on_click(preview, FALSE); - newBlot->set_tooltip_text(def.descr); - - g_signal_connect( G_OBJECT(newBlot->gobj()), - "clicked", - G_CALLBACK(handleClick), - this); - - g_signal_connect( G_OBJECT(newBlot->gobj()), - "alt-clicked", - G_CALLBACK(handleSecondaryClick), - this); - - g_signal_connect( G_OBJECT(newBlot->gobj()), - "button-press-event", - G_CALLBACK(colorItemHandleButtonPress), - this); - + Cairo::RefPtr cr = m_refGdkWindow->create_cairo_context(); + if(event) { - std::vector listing = def.getMIMETypes(); - int entryCount = listing.size(); - GtkTargetEntry* entries = new GtkTargetEntry[entryCount]; - GtkTargetEntry* curr = entries; - for ( std::vector::iterator it = listing.begin(); it != listing.end(); ++it ) { - curr->target = g_strdup(it->c_str()); - curr->flags = 0; - if ( mimeToInt.find(*it) == mimeToInt.end() ){ - // these next lines are order-dependent: - mimeToInt[*it] = mimeStrings.size(); - mimeStrings.push_back(*it); - } - curr->info = mimeToInt[curr->target]; - curr++; - } - gtk_drag_source_set( GTK_WIDGET(newBlot->gobj()), - GDK_BUTTON1_MASK, - entries, entryCount, - GdkDragAction(GDK_ACTION_MOVE | GDK_ACTION_COPY) ); - for ( int i = 0; i < entryCount; i++ ) { - g_free(entries[i].target); - } - delete[] entries; + // clip to the area that needs to be re-exposed so we don't draw any + // more than we need to. + cr->rectangle(event->area.x, event->area.y, event->area.width, event->area.height); + cr->clip(); } - g_signal_connect( G_OBJECT(newBlot->gobj()), - "drag-data-get", - G_CALLBACK(ColorItem::_dragGetColorData), - this); - - g_signal_connect( G_OBJECT(newBlot->gobj()), - "drag-begin", - G_CALLBACK(colorItemDragBegin), - this ); - - g_signal_connect( G_OBJECT(newBlot->gobj()), - "enter-notify-event", - G_CALLBACK(handleEnterNotify), - this); - - g_signal_connect( G_OBJECT(newBlot->gobj()), - "leave-notify-event", - G_CALLBACK(handleLeaveNotify), - this); - - g_signal_connect( G_OBJECT(newBlot->gobj()), - "destroy", - G_CALLBACK(dieDieDie), - this); - - - widget = newBlot; - } - - _previews.push_back( widget ); - - return widget; -} - -void ColorItem::buttonClicked(bool secondary) -{ - SPDesktop *desktop = SP_ACTIVE_DESKTOP; - if (desktop) { - char const * attrName = secondary ? "stroke" : "fill"; - - SPCSSAttr *css = sp_repr_css_attr_new(); - Glib::ustring descr; - switch (def.getType()) { - case ege::PaintDef::CLEAR: { - // TODO actually make this clear - sp_repr_css_set_property( css, attrName, "none" ); - descr = secondary? _("Remove stroke color") : _("Remove fill color"); - break; - } - case ege::PaintDef::NONE: { - sp_repr_css_set_property( css, attrName, "none" ); - descr = secondary? _("Set stroke color to none") : _("Set fill color to none"); - break; - } - case ege::PaintDef::RGB: { - Glib::ustring colorspec; - if ( _grad ){ - colorspec = "url(#"; - colorspec += _grad->getId(); - colorspec += ")"; - } else { - gchar c[64]; - guint32 rgba = (def.getR() << 24) | (def.getG() << 16) | (def.getB() << 8) | 0xff; - sp_svg_write_color(c, sizeof(c), rgba); - colorspec = c; - } - sp_repr_css_set_property( css, attrName, colorspec.c_str() ); - descr = secondary? _("Set stroke color from swatch") : _("Set fill color from swatch"); - break; - } - } - sp_desktop_set_style(desktop, css); - sp_repr_css_attr_unref(css); - - DocumentUndo::done( sp_desktop_document(desktop), SP_VERB_DIALOG_SWATCHES, descr.c_str() ); - } -} - -void ColorItem::_wireMagicColors( SwatchPage *colorSet ) -{ - if ( colorSet ) - { - for ( boost::ptr_vector::iterator it = colorSet->_colors.begin(); it != colorSet->_colors.end(); ++it ) - { - std::string::size_type pos = it->def.descr.find("*{"); - if ( pos != std::string::npos ) - { - std::string subby = it->def.descr.substr( pos + 2 ); - std::string::size_type endPos = subby.find("}*"); - if ( endPos != std::string::npos ) - { - subby.erase( endPos ); - //g_message("FOUND MAGIC at '%s'", (*it)->def.descr.c_str()); - //g_message(" '%s'", subby.c_str()); - - if ( subby.find('E') != std::string::npos ) - { - it->def.setEditable( true ); - } - - if ( subby.find('L') != std::string::npos ) - { - it->_isLive = true; - } - - std::string part; - // Tint. index + 1 more val. - if ( getBlock( part, 'T', subby ) ) { - guint64 colorIndex = 0; - if ( popVal( colorIndex, part ) ) { - guint64 percent = 0; - if ( popVal( percent, part ) ) { - it->_linkTint( colorSet->_colors[colorIndex], percent ); - } - } - } - - // Shade/tone. index + 1 or 2 more val. - if ( getBlock( part, 'S', subby ) ) { - guint64 colorIndex = 0; - if ( popVal( colorIndex, part ) ) { - guint64 percent = 0; - if ( popVal( percent, part ) ) { - guint64 grayLevel = 0; - if ( !popVal( grayLevel, part ) ) { - grayLevel = 0; - } - it->_linkTone( colorSet->_colors[colorIndex], percent, grayLevel ); - } - } - } - - } + if (gradient) { + cairo_pattern_t *check = ink_cairo_pattern_create_checkerboard(); + + Cairo::RefPtr checkpat(new Cairo::Pattern(check)); + + cr->set_source(checkpat); + cr->paint(); + + cairo_pattern_t *g = sp_gradient_create_preview_pattern(gradient, get_allocation().get_width()); + Cairo::RefPtr gpat(new Cairo::Pattern(g)); + cr->set_source(gpat); + cr->paint(); + gpat.clear(); + cairo_pattern_destroy(g); + + checkpat.clear(); + + cairo_pattern_destroy(check); + + if (_isSelected) { + cr->set_source_rgb(0, 0, 0); + cr->set_line_width(3); + cr->move_to(0, get_allocation().get_height()); + cr->line_to(0,0); + cr->line_to(get_allocation().get_width(), 0); + cr->stroke(); + cr->move_to(get_allocation().get_width(), 0); + cr->set_source_rgb(1, 1, 1); + cr->line_to(get_allocation().get_width(), get_allocation().get_height()); + cr->line_to(0, get_allocation().get_height()); + //cr->rectangle(0, 0, get_allocation().get_width(), get_allocation().get_height()); + cr->stroke(); } + } else { + cr->set_source_rgb(1, 1, 1); + cr->paint(); + cr->set_source_rgb(1, 0, 0); + cr->set_line_width(3); + cr->move_to(0,0); + cr->line_to(get_allocation().get_width(), get_allocation().get_height()); + cr->move_to(get_allocation().get_width(), 0); + cr->line_to(0, get_allocation().get_height()); + cr->stroke(); } } + return true; } - -void ColorItem::_linkTint( ColorItem& other, int percent ) -{ - if ( !_linkSrc ) - { - other._listeners.push_back(this); - _linkIsTone = false; - _linkPercent = percent; - if ( _linkPercent > 100 ) - _linkPercent = 100; - if ( _linkPercent < 0 ) - _linkPercent = 0; - _linkGray = 0; - _linkSrc = &other; - - ColorItem::_colorDefChanged(&other); - } -} - -void ColorItem::_linkTone( ColorItem& other, int percent, int grayLevel ) +ColorItem::~ColorItem() { - if ( !_linkSrc ) - { - other._listeners.push_back(this); - _linkIsTone = true; - _linkPercent = percent; - if ( _linkPercent > 100 ) - _linkPercent = 100; - if ( _linkPercent < 0 ) - _linkPercent = 0; - _linkGray = grayLevel; - _linkSrc = &other; - - ColorItem::_colorDefChanged(&other); - } + sel_connection.disconnect(); + mod_connection.disconnect(); } } // namespace Dialogs diff --git a/src/ui/dialog/color-item.h b/src/ui/dialog/color-item.h index 3a0b33193..5d97d8803 100644 --- a/src/ui/dialog/color-item.h +++ b/src/ui/dialog/color-item.h @@ -15,7 +15,11 @@ #include #include "widgets/ege-paint-def.h" -#include "ui/previewable.h" +#include "widgets/eek-preview.h" +#include +#include +#include "desktop.h" +#include "selection.h" class SPGradient; @@ -23,89 +27,43 @@ namespace Inkscape { namespace UI { namespace Dialogs { -class ColorItem; - -class SwatchPage -{ -public: - SwatchPage(); - ~SwatchPage(); - - Glib::ustring _name; - int _prefWidth; - boost::ptr_vector _colors; -}; - /** * The color swatch you see on screen as a clickable box. */ -class ColorItem : public Inkscape::UI::Previewable +class ColorItem : public Gtk::Widget { - friend void _loadPaletteFile( gchar const *filename ); public: - ColorItem( ege::PaintDef::ColorType type ); - ColorItem( unsigned int r, unsigned int g, unsigned int b, - Glib::ustring& name ); + ColorItem( SPGradient * grad, const gchar* name, SPDesktop* desktop ); virtual ~ColorItem(); - ColorItem(ColorItem const &other); - virtual ColorItem &operator=(ColorItem const &other); - virtual Gtk::Widget* getPreview(PreviewStyle style, - ViewType view, - ::PreviewSize size, - guint ratio, - guint border); - void buttonClicked(bool secondary = false); - - void setGradient(SPGradient *grad); - SPGradient * getGradient() const { return _grad; } - void setPattern(cairo_pattern_t *pattern); - void setName(const Glib::ustring name); - - void setState( bool fill, bool stroke ); - bool isFill() { return _isFill; } - bool isStroke() { return _isStroke; } - - ege::PaintDef def; - + + SPGradient * getGradient() { return gradient; } + +protected: + + const gchar* def; + SPGradient * gradient; + virtual bool on_enter_notify_event(GdkEventCrossing* event); + virtual bool on_leave_notify_event(GdkEventCrossing* event); + + virtual void on_size_request(Gtk::Requisition* requisition); + virtual void on_size_allocate(Gtk::Allocation& allocation); + virtual void on_map(); + virtual void on_unmap(); + virtual void on_realize(); + virtual void on_unrealize(); + virtual bool on_expose_event(GdkEventExpose* event); + + Glib::RefPtr m_refGdkWindow; + + private: + void selection_changed(Selection* selection); + void selection_modified(Selection* selection, guint flags); - static void _dropDataIn( GtkWidget *widget, - GdkDragContext *drag_context, - gint x, gint y, - GtkSelectionData *data, - guint info, - guint event_time, - gpointer user_data); - - static void _dragGetColorData( GtkWidget *widget, - GdkDragContext *drag_context, - GtkSelectionData *data, - guint info, - guint time, - gpointer user_data); - - static void _wireMagicColors( SwatchPage *colorSet ); - static void _colorDefChanged(void* data); - - void _updatePreviews(); - void _regenPreview(EekPreview * preview); - - void _linkTint( ColorItem& other, int percent ); - void _linkTone( ColorItem& other, int percent, int grayLevel ); - - std::vector _previews; - - bool _isFill; - bool _isStroke; - bool _isLive; - bool _linkIsTone; - int _linkPercent; - int _linkGray; - ColorItem* _linkSrc; - SPGradient* _grad; - cairo_pattern_t *_pattern; - std::vector _listeners; + sigc::connection sel_connection; + sigc::connection mod_connection; + bool _isSelected; }; } // namespace Dialogs diff --git a/src/ui/dialog/filedialog.h b/src/ui/dialog/filedialog.h index 8dfcf5dce..175031bcf 100644 --- a/src/ui/dialog/filedialog.h +++ b/src/ui/dialog/filedialog.h @@ -48,6 +48,7 @@ typedef enum { IMPORT_TYPES, EXPORT_TYPES, EXE_TYPES, + SWATCH_TYPES, CUSTOM_TYPE } FileDialogType; diff --git a/src/ui/dialog/swatches.cpp b/src/ui/dialog/swatches.cpp index 2956c6d17..efea4b869 100644 --- a/src/ui/dialog/swatches.cpp +++ b/src/ui/dialog/swatches.cpp @@ -67,14 +67,14 @@ #include "svg/svg-color.h" #include "sp-radial-gradient.h" #include "color-rgba.h" +#include "ui/tools/tool-base.h" #include "svg/css-ostringstream.h" -#include "ui/tools/tool-base.h" //event-context.h #include #ifdef WIN32 #include #endif -guint get_group0_keyval(GdkEventKey *event); +//lazy! void sp_desktop_set_gradient(SPDesktop *desktop, SPGradient* gradient, bool fill); namespace Inkscape { @@ -1335,10 +1335,10 @@ void SwatchesPanel::_defsChanged() eb->add(*lbl); _insideTable.attach( *eb, 0, 1, 0, 1, Gtk::FILL|Gtk::EXPAND, Gtk::FILL|Gtk::EXPAND , 5, 0); } - Glib::ustring str1 = Glib::ustring(_("[None]")); - ColorItem* item = Gtk::manage(new ColorItem(NULL, NULL, NULL, str1)); - //item->signal_button_press_event().connect_notify(sigc::bind(sigc::mem_fun(*this, &SwatchesPanel::_swatchClicked), NULL)); - item->setName(_("[None]")); + + ColorItem* item = Gtk::manage(new ColorItem(NULL, _("[None]"), _currentDesktop)); + item->signal_button_press_event().connect_notify(sigc::bind(sigc::mem_fun(*this, &SwatchesPanel::_swatchClicked), NULL)); + item->set_tooltip_text(_("[None]")); _insideTable.attach( *item, _showlabels ? 1 : 0, _showlabels ? 2 : 1, 0, 1, Gtk::FILL|Gtk::EXPAND, Gtk::FILL|Gtk::EXPAND ); unsigned int i = 1; @@ -1365,11 +1365,10 @@ void SwatchesPanel::_defsChanged() GdkPixbuf* pixb = sp_gradient_to_pixbuf (grad, 64, 18); row[_modelDoc->_colPixbuf] = Glib::wrap(pixb); } - Glib::ustring str2 = Glib::ustring(it->label() ? it->label() : it->getId()); - item = Gtk::manage(new ColorItem(NULL, NULL, NULL, str2)); - item->setGradient(grad); - //item->colorItemHandleButtonPress().connect_notify(sigc::bind(sigc::mem_fun(*this, &SwatchesPanel::_swatchClicked), grad)); - item->setName(it->label() ? it->label() : it->getId()); + + item = Gtk::manage(new ColorItem(grad, it->label() ? it->label() : it->getId(), _currentDesktop)); + item->signal_button_press_event().connect_notify(sigc::bind(sigc::mem_fun(*this, &SwatchesPanel::_swatchClicked), grad)); + item->set_tooltip_text(it->label() ? it->label() : it->getId()); if (_showlabels) { _insideTable.attach( *item, 1 + (i % 20), 2 + (i % 20), i / 20, i / 20 + 1, Gtk::FILL|Gtk::EXPAND, Gtk::FILL|Gtk::EXPAND ); } else { @@ -1432,11 +1431,10 @@ void SwatchesPanel::_defsChanged() _editDoc.expand_to_path(_storeDoc->get_path(iter)); } - Glib::ustring str3= Glib::ustring(cit->label() ? cit->label() : cit->getId()); - item = Gtk::manage(new ColorItem(NULL, NULL, NULL, str3)); - item->setGradient(grad); - //item->signal_button_press_event().connect_notify(sigc::bind(sigc::mem_fun(*this, &SwatchesPanel::_swatchClicked), grad)); - item->setName(cit->label() ? cit->label() : cit->getId()); + + item = Gtk::manage(new ColorItem(grad, cit->label() ? cit->label() : cit->getId(), _currentDesktop)); + item->signal_button_press_event().connect_notify(sigc::bind(sigc::mem_fun(*this, &SwatchesPanel::_swatchClicked), grad)); + item->set_tooltip_text(cit->label() ? cit->label() : cit->getId()); if (_showlabels) { _insideTable.attach( *item, 1 + (i % 20), 2 + (i % 20), i / 20, i / 20 + 1, Gtk::FILL|Gtk::EXPAND, Gtk::FILL|Gtk::EXPAND ); } else { @@ -1643,7 +1641,7 @@ bool SwatchesPanel::_handleButtonEvent(GdkEventButton *event) bool SwatchesPanel::_handleKeyEvent(GdkEventKey *event) { - switch (get_group0_keyval(event)) { + switch (Inkscape::UI::Tools::get_group0_keyval(event)) { case GDK_KEY_Return: case GDK_KEY_KP_Enter: case GDK_KEY_F2: { @@ -1815,7 +1813,7 @@ void SwatchesPanel::_deleteButtonClickedDoc() bool SwatchesPanel::_handleKeyEventDoc(GdkEventKey *event) { - switch (get_group0_keyval(event)) { + switch (Inkscape::UI::Tools::get_group0_keyval(event)) { case GDK_KEY_Return: case GDK_KEY_KP_Enter: case GDK_KEY_F2: { @@ -2323,18 +2321,8 @@ void SwatchesPanel::_setDocument( SPDesktop* desktop, SPDocument *document ) } //namespace UI } //namespace Inkscape -//should be okay to add this here -guint get_group0_keyval(GdkEventKey *event) { - guint keyval = 0; - gdk_keymap_translate_keyboard_state(gdk_keymap_get_for_display( - gdk_display_get_default()), event->hardware_keycode, - (GdkModifierType) event->state, 0 /*event->key.group*/, &keyval, - NULL, NULL, NULL); - return keyval; -} - -void -sp_desktop_set_gradient(SPDesktop *desktop, SPGradient* gradient, bool fill) +//really lazy! +void sp_desktop_set_gradient(SPDesktop *desktop, SPGradient* gradient, bool fill) { bool intercepted = false; diff --git a/src/widgets/desktop-widget.cpp b/src/widgets/desktop-widget.cpp index 583dbec85..2eba8bb8c 100644 --- a/src/widgets/desktop-widget.cpp +++ b/src/widgets/desktop-widget.cpp @@ -358,7 +358,7 @@ void SPDesktopWidget::init( SPDesktopWidget *dtw ) { using Inkscape::UI::Dialogs::SwatchesPanel; - dtw->panels = new SwatchesPanel("/embedded/swatches"); + dtw->panels = new SwatchesPanel("/embedded/swatches", false); dtw->panels->setOrientation(SP_ANCHOR_SOUTH); #if GTK_CHECK_VERSION(3,0,0) -- cgit v1.2.3 From a13fdaaa6335ad69b59750a3a9c6b978b921881b Mon Sep 17 00:00:00 2001 From: "Liam P. White" Date: Wed, 5 Mar 2014 16:21:29 -0500 Subject: Fixed some swatch sizes (what about the table?) (bzr r13090.1.17) --- src/ui/dialog/swatches.cpp | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'src') diff --git a/src/ui/dialog/swatches.cpp b/src/ui/dialog/swatches.cpp index efea4b869..91d859f90 100644 --- a/src/ui/dialog/swatches.cpp +++ b/src/ui/dialog/swatches.cpp @@ -1333,13 +1333,13 @@ void SwatchesPanel::_defsChanged() lbl = Gtk::manage(new Gtk::Label(_("[Base]"))); eb->add(*lbl); - _insideTable.attach( *eb, 0, 1, 0, 1, Gtk::FILL|Gtk::EXPAND, Gtk::FILL|Gtk::EXPAND , 5, 0); + _insideTable.attach( *eb, 0, 1, 0, 1, Gtk::FILL/*|Gtk::EXPAND*/, Gtk::FILL/*|Gtk::EXPAND*/ , 5, 0); } ColorItem* item = Gtk::manage(new ColorItem(NULL, _("[None]"), _currentDesktop)); item->signal_button_press_event().connect_notify(sigc::bind(sigc::mem_fun(*this, &SwatchesPanel::_swatchClicked), NULL)); item->set_tooltip_text(_("[None]")); - _insideTable.attach( *item, _showlabels ? 1 : 0, _showlabels ? 2 : 1, 0, 1, Gtk::FILL|Gtk::EXPAND, Gtk::FILL|Gtk::EXPAND ); + _insideTable.attach( *item, _showlabels ? 1 : 0, _showlabels ? 2 : 1, 0, 1, Gtk::FILL/*|Gtk::EXPAND*/, Gtk::FILL/*|Gtk::EXPAND*/ ); unsigned int i = 1; for (SPObject *it = _currentDocument->getDefs()->firstChild(); it != NULL; it = it->next) { @@ -1370,9 +1370,9 @@ void SwatchesPanel::_defsChanged() item->signal_button_press_event().connect_notify(sigc::bind(sigc::mem_fun(*this, &SwatchesPanel::_swatchClicked), grad)); item->set_tooltip_text(it->label() ? it->label() : it->getId()); if (_showlabels) { - _insideTable.attach( *item, 1 + (i % 20), 2 + (i % 20), i / 20, i / 20 + 1, Gtk::FILL|Gtk::EXPAND, Gtk::FILL|Gtk::EXPAND ); + _insideTable.attach( *item, 1 + (i % 20), 2 + (i % 20), i / 20, i / 20 + 1, Gtk::FILL/*|Gtk::EXPAND*/, Gtk::FILL/*|Gtk::EXPAND*/ ); } else { - _insideTable.attach( *item, i, i + 1, 0, 1, Gtk::FILL|Gtk::EXPAND, Gtk::FILL|Gtk::EXPAND ); + _insideTable.attach( *item, i, i + 1, 0, 1, Gtk::FILL/*|Gtk::EXPAND*/, Gtk::FILL/*|Gtk::EXPAND*/ ); } i++; @@ -1393,7 +1393,7 @@ void SwatchesPanel::_defsChanged() eb->signal_button_press_event().connect_notify(sigc::bind(sigc::mem_fun(*this, &SwatchesPanel::_lblClick), SP_GROUP(it))); lbl = Gtk::manage(new Gtk::Label(it->label() ? it->label() : it->getId())); eb->add(*lbl); - _insideTable.attach( *eb, 0, 1, i / 20, i / 20 + 1, Gtk::FILL|Gtk::EXPAND, Gtk::FILL|Gtk::EXPAND , 5, 0); + _insideTable.attach( *eb, 0, 1, i / 20, i / 20 + 1, Gtk::FILL/*|Gtk::EXPAND*/, Gtk::FILL/*|Gtk::EXPAND*/ , 5, 0); } Gtk::TreeModel::iterator rowiter; @@ -1436,9 +1436,9 @@ void SwatchesPanel::_defsChanged() item->signal_button_press_event().connect_notify(sigc::bind(sigc::mem_fun(*this, &SwatchesPanel::_swatchClicked), grad)); item->set_tooltip_text(cit->label() ? cit->label() : cit->getId()); if (_showlabels) { - _insideTable.attach( *item, 1 + (i % 20), 2 + (i % 20), i / 20, i / 20 + 1, Gtk::FILL|Gtk::EXPAND, Gtk::FILL|Gtk::EXPAND ); + _insideTable.attach( *item, 1 + (i % 20), 2 + (i % 20), i / 20, i / 20 + 1, Gtk::FILL/*|Gtk::EXPAND*/, Gtk::FILL/*|Gtk::EXPAND*/ ); } else { - _insideTable.attach( *item, i, i + 1, 0, 1, Gtk::FILL|Gtk::EXPAND, Gtk::FILL|Gtk::EXPAND ); + _insideTable.attach( *item, i, i + 1, 0, 1, Gtk::FILL/*|Gtk::EXPAND*/, Gtk::FILL/*|Gtk::EXPAND*/ ); } i++; } @@ -2072,7 +2072,7 @@ bool SwatchesPanel::_handleDragDropDoc(const Glib::RefPtr& con SwatchesPanel::SwatchesPanel(gchar const* prefsPath, bool showLabels) : Inkscape::UI::Widget::Panel("", prefsPath, SP_VERB_DIALOG_SWATCHES, ""), _scroller(), - _insideTable(1, 2), + _insideTable(1, 1), _insideV(), _insideH(), _buttonsRow(), -- cgit v1.2.3 From 8db893813e5974793db85bad0eb6b32468d29c45 Mon Sep 17 00:00:00 2001 From: "Liam P. White" Date: Wed, 5 Mar 2014 19:31:15 -0500 Subject: Makefile fix (bzr r13090.1.18) --- src/ui/dialog/swatches.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/ui/dialog/swatches.cpp b/src/ui/dialog/swatches.cpp index 91d859f90..ceda27885 100644 --- a/src/ui/dialog/swatches.cpp +++ b/src/ui/dialog/swatches.cpp @@ -1448,9 +1448,11 @@ void SwatchesPanel::_defsChanged() } } } - + //_scroller.resize(1,1); + _insideTable.resize(1,1); _scroller.show_all_children(); _scroller.queue_draw(); + } Gtk::MenuItem* SwatchesPanel::_addSwatchGroup(SPGroup* group, Gtk::TreeModel::Row* parentRow) @@ -2258,6 +2260,7 @@ SwatchesPanel::SwatchesPanel(gchar const* prefsPath, bool showLabels) : rootWatcher = new SwatchWatcher(this, SwatchDocument->getDefs(), true); SwatchDocument->getDefs()->getRepr()->addObserver(*rootWatcher); _swatchesChanged(); + _insideTable.resize(1,1); } SwatchesPanel::~SwatchesPanel() -- cgit v1.2.3 From 50a5b62b327c55b8038b5031d35bf6ae48705485 Mon Sep 17 00:00:00 2001 From: "Liam P. White" Date: Wed, 5 Mar 2014 21:08:09 -0500 Subject: Fixed size of swatches widget (bzr r13090.1.19) --- src/ui/dialog/swatches.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/ui/dialog/swatches.cpp b/src/ui/dialog/swatches.cpp index ceda27885..c3889db46 100644 --- a/src/ui/dialog/swatches.cpp +++ b/src/ui/dialog/swatches.cpp @@ -2102,7 +2102,7 @@ SwatchesPanel::SwatchesPanel(gchar const* prefsPath, bool showLabels) : _insideV.pack_start(_insideH, Gtk::PACK_SHRINK); _scroller.add(_insideV); } else { - _scroller.property_height_request() = 45; + _scroller.property_height_request() = 20; _scroller.add(_insideH); } -- cgit v1.2.3 From c3edf2beebfdf0cbb505d2accbddc4fec17dff7d Mon Sep 17 00:00:00 2001 From: "Liam P. White" Date: Thu, 6 Mar 2014 21:05:19 -0500 Subject: Start cleanup for merge into trunk (bzr r13090.1.20) --- src/live_effects/effect.cpp | 8 +- src/live_effects/lpe-fill-between-many.cpp | 3 +- src/live_effects/lpe-jointype.cpp | 5 +- src/live_effects/parameter/originalpatharray.cpp | 12 +- .../parameter/powerstrokepointarray.cpp | 6 +- src/live_effects/parameter/transformedpoint.cpp | 4 +- src/sp-gradient-fns.h | 47 - src/sp-tag-use-reference.cpp | 147 --- src/sp-tag-use-reference.h | 77 -- src/sp-tag-use.cpp | 281 ----- src/sp-tag-use.h | 53 - src/sp-tag.cpp | 240 ---- src/sp-tag.h | 55 - src/ui/dialog/color-item.cpp | 2 +- src/ui/dialog/dialog-manager.cpp | 4 +- src/ui/dialog/lpe-powerstroke-properties.cpp | 8 + src/ui/dialog/swatches.cpp | 1 - src/ui/dialog/tags.cpp | 1182 -------------------- src/ui/dialog/tags.h | 181 --- src/ui/widget/addtoicon.h | 2 +- src/ui/widget/clipmaskicon.h | 2 +- src/ui/widget/highlight-picker.cpp | 10 +- src/ui/widget/highlight-picker.h | 2 +- src/ui/widget/insertordericon.cpp | 7 + src/ui/widget/layertypeicon.h | 2 +- src/verbs.cpp | 8 +- src/verbs.h | 2 +- 27 files changed, 61 insertions(+), 2290 deletions(-) delete mode 100644 src/sp-gradient-fns.h delete mode 100644 src/sp-tag-use-reference.cpp delete mode 100644 src/sp-tag-use-reference.h delete mode 100644 src/sp-tag-use.cpp delete mode 100644 src/sp-tag-use.h delete mode 100644 src/sp-tag.cpp delete mode 100644 src/sp-tag.h delete mode 100644 src/ui/dialog/tags.cpp delete mode 100644 src/ui/dialog/tags.h (limited to 'src') diff --git a/src/live_effects/effect.cpp b/src/live_effects/effect.cpp index 17b229352..2ffff153c 100644 --- a/src/live_effects/effect.cpp +++ b/src/live_effects/effect.cpp @@ -47,7 +47,7 @@ #include "live_effects/lpe-extrude.h" #include "live_effects/lpe-powerstroke.h" #include "live_effects/lpe-clone-original.h" -#include "live_effects/lpe-attach-path.h" +//#include "live_effects/lpe-attach-path.h" #include "live_effects/lpe-fill-between-strokes.h" #include "live_effects/lpe-fill-between-many.h" #include "live_effects/lpe-ellipse_5pts.h" @@ -130,7 +130,7 @@ const Util::EnumData LPETypeData[] = { {POWERSTROKE, N_("Power stroke"), "powerstroke"}, {CLONE_ORIGINAL, N_("Clone original path"), "clone_original"}, /* Ponyscape */ - {ATTACH_PATH, N_("Attach path"), "attach_path"}, +// {ATTACH_PATH, N_("Attach path"), "attach_path"}, {FILL_BETWEEN_STROKES, N_("Fill between strokes"), "fill_between_strokes"}, {FILL_BETWEEN_MANY, N_("Fill between many"), "fill_between_many"}, {ELLIPSE_5PTS, N_("Ellipse by 5 points"), "ellipse_5pts"}, @@ -258,9 +258,9 @@ Effect::New(EffectType lpenr, LivePathEffectObject *lpeobj) case CLONE_ORIGINAL: neweffect = static_cast ( new LPECloneOriginal(lpeobj) ); break; - case ATTACH_PATH: + /*case ATTACH_PATH: neweffect = static_cast ( new LPEAttachPath(lpeobj) ); - break; + break;*/ case FILL_BETWEEN_STROKES: neweffect = static_cast ( new LPEFillBetweenStrokes(lpeobj) ); break; diff --git a/src/live_effects/lpe-fill-between-many.cpp b/src/live_effects/lpe-fill-between-many.cpp index 00cc1fed5..7cf354044 100644 --- a/src/live_effects/lpe-fill-between-many.cpp +++ b/src/live_effects/lpe-fill-between-many.cpp @@ -4,7 +4,6 @@ * Released under GNU GPL, read the file 'COPYING' for more information */ -#include #include #include "live_effects/lpe-fill-between-many.h" @@ -16,6 +15,8 @@ #include "sp-text.h" #include "2geom/bezier-curve.h" +#include + namespace Inkscape { namespace LivePathEffect { diff --git a/src/live_effects/lpe-jointype.cpp b/src/live_effects/lpe-jointype.cpp index 97c0a1b8a..93e645783 100644 --- a/src/live_effects/lpe-jointype.cpp +++ b/src/live_effects/lpe-jointype.cpp @@ -12,6 +12,9 @@ #include +#include "live_effects/parameter/enum.h" +#include "live_effects/pathoutlineprovider.h" + #include "sp-shape.h" #include "style.h" #include "xml/repr.h" @@ -20,11 +23,9 @@ #include "desktop-style.h" #include "svg/css-ostringstream.h" #include "display/curve.h" -#include "live_effects/parameter/enum.h" #include <2geom/path.h> #include <2geom/svg-elliptical-arc.h> -#include "live_effects/pathoutlineprovider.h" #include "lpe-jointype.h" diff --git a/src/live_effects/parameter/originalpatharray.cpp b/src/live_effects/parameter/originalpatharray.cpp index 29e4c409c..ed47db28d 100644 --- a/src/live_effects/parameter/originalpatharray.cpp +++ b/src/live_effects/parameter/originalpatharray.cpp @@ -4,6 +4,14 @@ * Released under GNU GPL, read the file 'COPYING' for more information */ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#if GLIBMM_DISABLE_DEPRECATED && HAVE_GLIBMM_THREADS_H +#include +#endif + #include "live_effects/parameter/originalpatharray.h" #include @@ -89,9 +97,11 @@ OriginalPathArrayParam::OriginalPathArrayParam( const Glib::ustring& label, _toggle_renderer->signal_toggled().connect(sigc::mem_fun(*this, &OriginalPathArrayParam::on_reverse_toggled)); col->add_attribute(_toggle_renderer->property_active(), _model->_colReverse); + //quick little hack -- new versions of gtk did not give the item enough space + _scroller.property_height_request() = 120; _scroller.add(_tree); _scroller.set_policy( Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC ); - _scroller.set_shadow_type(Gtk::SHADOW_IN); + //_scroller.set_shadow_type(Gtk::SHADOW_IN); oncanvas_editable = true; diff --git a/src/live_effects/parameter/powerstrokepointarray.cpp b/src/live_effects/parameter/powerstrokepointarray.cpp index ac0000b1a..7fa837689 100644 --- a/src/live_effects/parameter/powerstrokepointarray.cpp +++ b/src/live_effects/parameter/powerstrokepointarray.cpp @@ -4,8 +4,6 @@ * Released under GNU GPL, read the file 'COPYING' for more information */ -#include - #include "ui/dialog/lpe-powerstroke-properties.h" #include "live_effects/parameter/powerstrokepointarray.h" @@ -22,6 +20,8 @@ #include "desktop.h" #include "live_effects/lpeobject.h" +#include + namespace Inkscape { namespace LivePathEffect { @@ -145,7 +145,7 @@ public: virtual Geom::Point knot_get() const; virtual void knot_click(guint state); - /** Checks whether the index falls within the size of the parameter's vector / + // Checks whether the index falls within the size of the parameter's vector bool valid_index(unsigned int index) const { return (_pparam->_vector.size() > index); }; diff --git a/src/live_effects/parameter/transformedpoint.cpp b/src/live_effects/parameter/transformedpoint.cpp index f5b01e267..0d03432c3 100644 --- a/src/live_effects/parameter/transformedpoint.cpp +++ b/src/live_effects/parameter/transformedpoint.cpp @@ -4,8 +4,6 @@ * Released under GNU GPL, read the file 'COPYING' for more information */ -#include - #include "ui/widget/registered-widget.h" #include "live_effects/parameter/transformedpoint.h" #include "sp-lpe-item.h" @@ -17,6 +15,8 @@ #include "desktop.h" #include "verbs.h" +#include + namespace Inkscape { namespace LivePathEffect { diff --git a/src/sp-gradient-fns.h b/src/sp-gradient-fns.h deleted file mode 100644 index e57877256..000000000 --- a/src/sp-gradient-fns.h +++ /dev/null @@ -1,47 +0,0 @@ -#ifndef SEEN_SP_GRADIENT_FNS_H -#define SEEN_SP_GRADIENT_FNS_H - -/** \file - * Macros and fn declarations related to gradients. - */ - -#include -#include -#include <2geom/forward.h> -#include "sp-gradient-spread.h" -#include "sp-gradient-units.h" - -class SPGradient; -class SPMeshGradient; - -SPGradientSpread sp_gradient_get_spread (SPGradient *gradient); - -/* Gradient repr methods */ -void sp_gradient_repr_write_vector(SPGradient *gr); -void sp_gradient_repr_clear_vector(SPGradient *gr); - -void sp_meshgradient_repr_write(SPMeshGradient *mg); - -cairo_pattern_t *sp_gradient_create_preview_pattern(SPGradient *gradient, double width); - -/** Transforms to/from gradient position space in given environment */ -Geom::Affine sp_gradient_get_g2d_matrix(SPGradient const *gr, Geom::Affine const &ctm, - Geom::Rect const &bbox); -Geom::Affine sp_gradient_get_gs2d_matrix(SPGradient const *gr, Geom::Affine const &ctm, - Geom::Rect const &bbox); -void sp_gradient_set_gs2d_matrix(SPGradient *gr, Geom::Affine const &ctm, Geom::Rect const &bbox, - Geom::Affine const &gs2d); - - -#endif /* !SEEN_SP_GRADIENT_FNS_H */ - -/* - 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 : diff --git a/src/sp-tag-use-reference.cpp b/src/sp-tag-use-reference.cpp deleted file mode 100644 index 8e48c0285..000000000 --- a/src/sp-tag-use-reference.cpp +++ /dev/null @@ -1,147 +0,0 @@ -/* - * The reference corresponding to href of element. - * - * Copyright (C) Theodore Janeczko 2012 - * - * Released under GNU GPL, read the file 'COPYING' for more information. - */ - -#include -#include -#include - -#include "enums.h" -#include "sp-tag-use-reference.h" - -#include "display/curve.h" -#include "livarot/Path.h" -#include "preferences.h" -#include "sp-shape.h" -#include "sp-text.h" -#include "uri.h" - - - -bool SPTagUseReference::_acceptObject(SPObject * const obj) const -{ - if (SP_IS_ITEM(obj)) { - SPObject * const owner = getOwner(); - // Refuse references to us or to an ancestor. - for ( SPObject *iter = owner ; iter ; iter = iter->parent ) { - if ( iter == obj ) { - return false; - } - } - return true; - } else { - return false; - } -} - - -static void sp_usepath_href_changed(SPObject *old_ref, SPObject *ref, SPTagUsePath *offset); -static void sp_usepath_delete_self(SPObject *deleted, SPTagUsePath *offset); - -SPTagUsePath::SPTagUsePath(SPObject* i_owner):SPTagUseReference(i_owner) -{ - owner=i_owner; - originalPath = NULL; - sourceDirty=false; - sourceHref = NULL; - sourceRepr = NULL; - sourceObject = NULL; - _changed_connection = changedSignal().connect(sigc::bind(sigc::ptr_fun(sp_usepath_href_changed), this)); // listening to myself, this should be virtual instead - - user_unlink = NULL; -} - -SPTagUsePath::~SPTagUsePath(void) -{ - delete originalPath; - originalPath = NULL; - - _changed_connection.disconnect(); // to do before unlinking - - quit_listening(); - unlink(); -} - -void -SPTagUsePath::link(char *to) -{ - if ( to == NULL ) { - quit_listening(); - unlink(); - } else { - if ( !sourceHref || ( strcmp(to, sourceHref) != 0 ) ) { - g_free(sourceHref); - sourceHref = g_strdup(to); - try { - attach(Inkscape::URI(to)); - } catch (Inkscape::BadURIException &e) { - /* TODO: Proper error handling as per - * http://www.w3.org/TR/SVG11/implnote.html#ErrorProcessing. - */ - g_warning("%s", e.what()); - detach(); - } - } - } -} - -void -SPTagUsePath::unlink(void) -{ - g_free(sourceHref); - sourceHref = NULL; - detach(); -} - -void -SPTagUsePath::start_listening(SPObject* to) -{ - if ( to == NULL ) { - return; - } - sourceObject = to; - sourceRepr = to->getRepr(); - _delete_connection = to->connectDelete(sigc::bind(sigc::ptr_fun(&sp_usepath_delete_self), this)); -} - -void -SPTagUsePath::quit_listening(void) -{ - if ( sourceObject == NULL ) { - return; - } - _delete_connection.disconnect(); - sourceRepr = NULL; - sourceObject = NULL; -} - -static void -sp_usepath_href_changed(SPObject */*old_ref*/, SPObject */*ref*/, SPTagUsePath *offset) -{ - offset->quit_listening(); - SPItem *refobj = offset->getObject(); - if ( refobj ) { - offset->start_listening(refobj); - } -} - -static void -sp_usepath_delete_self(SPObject */*deleted*/, SPTagUsePath *offset) -{ - offset->owner->deleteObject(); -} - -/* - 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 : diff --git a/src/sp-tag-use-reference.h b/src/sp-tag-use-reference.h deleted file mode 100644 index 039d2fd7d..000000000 --- a/src/sp-tag-use-reference.h +++ /dev/null @@ -1,77 +0,0 @@ -#ifndef SEEN_SP_TAG_USE_REFERENCE_H -#define SEEN_SP_TAG_USE_REFERENCE_H - -/* - * The reference corresponding to href of element. - * - * Copyright (C) Theodore Janeczko 2012 - * - * Released under GNU GPL, read the file 'COPYING' for more information. - */ - -#include "sp-object.h" -#include "sp-item.h" -#include -#include -#include - -class Path; - -namespace Inkscape { -namespace XML { - struct Node; -} -} - - -class SPTagUseReference : public Inkscape::URIReference { -public: - SPTagUseReference(SPObject *owner) : URIReference(owner) {} - - SPItem *getObject() const { - return static_cast(URIReference::getObject()); - } - -protected: - virtual bool _acceptObject(SPObject * const obj) const; - -}; - - -class SPTagUsePath : public SPTagUseReference { -public: - Path *originalPath; - bool sourceDirty; - - SPObject *owner; - gchar *sourceHref; - Inkscape::XML::Node *sourceRepr; - SPObject *sourceObject; - - sigc::connection _delete_connection; - sigc::connection _changed_connection; - - SPTagUsePath(SPObject* i_owner); - ~SPTagUsePath(void); - - void link(char* to); - void unlink(void); - void start_listening(SPObject* to); - void quit_listening(void); - void refresh_source(void); - - void (*user_unlink) (SPObject *user); -}; - -#endif /* !SEEN_SP_USE_REFERENCE_H */ - -/* - 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 : diff --git a/src/sp-tag-use.cpp b/src/sp-tag-use.cpp deleted file mode 100644 index 4c5171bbb..000000000 --- a/src/sp-tag-use.cpp +++ /dev/null @@ -1,281 +0,0 @@ -/* - * SVG implementation - * - * Authors: - * Theodore Janeczko - * - * Copyright (C) Theodore Janeczko 2012 - * - * Released under GNU GPL, read the file 'COPYING' for more information - */ - -#ifdef HAVE_CONFIG_H -# include -#endif - -#include -#include - -#include -#include "display/drawing-group.h" -#include "attributes.h" -#include "document.h" -#include "sp-object-repr.h" -#include "uri.h" -#include "xml/repr.h" -#include "preferences.h" -#include "style.h" -#include "sp-symbol.h" -#include "sp-tag-use.h" -#include "sp-tag-use-reference.h" - -/* fixme: */ - -static void sp_tag_use_class_init(SPTagUseClass *classname); -static void sp_tag_use_init(SPTagUse *use); -static void sp_tag_use_finalize(GObject *obj); - -static void sp_tag_use_build(SPObject *object, SPDocument *document, Inkscape::XML::Node *repr); -static void sp_tag_use_release(SPObject *object); -static void sp_tag_use_set(SPObject *object, unsigned key, gchar const *value); -static Inkscape::XML::Node *sp_tag_use_write(SPObject *object, Inkscape::XML::Document *doc, Inkscape::XML::Node *repr, guint flags); -static void sp_tag_use_update(SPObject *object, SPCtx *ctx, guint flags); - -static void sp_tag_use_href_changed(SPObject *old_ref, SPObject *ref, SPTagUse *use); - -static SPObjectClass *parent_class; - - -GType -sp_tag_use_get_type(void) -{ - static GType use_type = 0; - if (!use_type) { - GTypeInfo use_info = { - sizeof(SPTagUseClass), - NULL, /* base_init */ - NULL, /* base_finalize */ - (GClassInitFunc) sp_tag_use_class_init, - NULL, /* class_finalize */ - NULL, /* class_data */ - sizeof(SPTagUse), - 16, /* n_preallocs */ - (GInstanceInitFunc) sp_tag_use_init, - NULL, /* value_table */ - }; - use_type = g_type_register_static(SP_TYPE_OBJECT, "SPTagUse", &use_info, (GTypeFlags)0); - } - return use_type; -} - -static void -sp_tag_use_class_init(SPTagUseClass *classname) -{ - GObjectClass *gobject_class = (GObjectClass *) classname; - SPObjectClass *sp_object_class = (SPObjectClass *) classname; - - parent_class = (SPObjectClass*)g_type_class_peek_parent(classname); - - gobject_class->finalize = sp_tag_use_finalize; - - sp_object_class->build = sp_tag_use_build; - sp_object_class->release = sp_tag_use_release; - sp_object_class->set = sp_tag_use_set; - sp_object_class->write = sp_tag_use_write; - sp_object_class->update = sp_tag_use_update; -} - -static void -sp_tag_use_init(SPTagUse *use) -{ - use->href = NULL; - - new (&use->_changed_connection) sigc::connection(); - - use->ref = new SPTagUseReference(use); - - use->_changed_connection = use->ref->changedSignal().connect(sigc::bind(sigc::ptr_fun(sp_tag_use_href_changed), use)); -} - -static void -sp_tag_use_finalize(GObject *obj) -{ - SPTagUse *use = reinterpret_cast(obj); - - if (use->child) { - use->detach(use->child); - use->child = NULL; - } - - use->ref->detach(); - delete use->ref; - use->ref = 0; - - use->_changed_connection.~connection(); - -} - -static void -sp_tag_use_build(SPObject *object, SPDocument *document, Inkscape::XML::Node *repr) -{ - if (((SPObjectClass *) parent_class)->build) { - (* ((SPObjectClass *) parent_class)->build)(object, document, repr); - } - - object->readAttr( "xlink:href" ); - - // We don't need to create child here: - // reading xlink:href will attach ref, and that will cause the changed signal to be emitted, - // which will call sp_tag_use_href_changed, and that will take care of the child -} - -static void -sp_tag_use_release(SPObject *object) -{ - SPTagUse *use = SP_TAG_USE(object); - - if (use->child) { - object->detach(use->child); - use->child = NULL; - } - - use->_changed_connection.disconnect(); - - g_free(use->href); - use->href = NULL; - - use->ref->detach(); - - if (((SPObjectClass *) parent_class)->release) { - ((SPObjectClass *) parent_class)->release(object); - } -} - -static void -sp_tag_use_set(SPObject *object, unsigned key, gchar const *value) -{ - SPTagUse *use = SP_TAG_USE(object); - - switch (key) { - case SP_ATTR_XLINK_HREF: { - if ( value && use->href && ( strcmp(value, use->href) == 0 ) ) { - /* No change, do nothing. */ - } else { - g_free(use->href); - use->href = NULL; - if (value) { - // First, set the href field, because sp_tag_use_href_changed will need it. - use->href = g_strdup(value); - - // Now do the attaching, which emits the changed signal. - try { - use->ref->attach(Inkscape::URI(value)); - } catch (Inkscape::BadURIException &e) { - g_warning("%s", e.what()); - use->ref->detach(); - } - } else { - use->ref->detach(); - } - } - break; - } - - default: - if (((SPObjectClass *) parent_class)->set) { - ((SPObjectClass *) parent_class)->set(object, key, value); - } - break; - } -} - -static Inkscape::XML::Node * -sp_tag_use_write(SPObject *object, Inkscape::XML::Document *xml_doc, Inkscape::XML::Node *repr, guint flags) -{ - SPTagUse *use = SP_TAG_USE(object); - - if ((flags & SP_OBJECT_WRITE_BUILD) && !repr) { - repr = xml_doc->createElement("inkscape:tagref"); - } - - if (((SPObjectClass *) (parent_class))->write) { - ((SPObjectClass *) (parent_class))->write(object, xml_doc, repr, flags); - } - - if (use->ref->getURI()) { - gchar *uri_string = use->ref->getURI()->toString(); - repr->setAttribute("xlink:href", uri_string); - g_free(uri_string); - } - - return repr; -} - -/** - * Returns the ultimate original of a SPTagUse (i.e. the first object in the chain of its originals - * which is not an SPTagUse). If no original is found, NULL is returned (it is the responsibility - * of the caller to make sure that this is handled correctly). - * - * Note that the returned is the clone object, i.e. the child of an SPTagUse (of the argument one for - * the trivial case) and not the "true original". - */ -SPItem * -sp_tag_use_root(SPTagUse *use) -{ - SPObject *orig = use->child; - while (orig && SP_IS_TAG_USE(orig)) { - orig = SP_TAG_USE(orig)->child; - } - if (!orig || !SP_IS_ITEM(orig)) - return NULL; - return SP_ITEM(orig); -} - -static void -sp_tag_use_href_changed(SPObject */*old_ref*/, SPObject */*ref*/, SPTagUse *use) -{ - if (use->href) { - SPItem *refobj = use->ref->getObject(); - if (refobj) { - Inkscape::XML::Node *childrepr = refobj->getRepr(); - GType type = sp_repr_type_lookup(childrepr); - g_return_if_fail(type > G_TYPE_NONE); - if (g_type_is_a(type, SP_TYPE_ITEM)) { - use->child = (SPObject*) g_object_new(type, 0); - use->attach(use->child, use->lastChild()); - sp_object_unref(use->child, use); - (use->child)->invoke_build(use->document, childrepr, TRUE); - - } - } - } -} - -static void -sp_tag_use_update(SPObject *object, SPCtx *ctx, unsigned flags) -{ - if (((SPObjectClass *) (parent_class))->update) - ((SPObjectClass *) (parent_class))->update(object, ctx, flags); -} - -SPItem *sp_tag_use_get_original(SPTagUse *use) -{ - SPItem *ref = NULL; - if (use){ - if (use->ref){ - ref = use->ref->getObject(); - } - } - return ref; -} - -/* - 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 : diff --git a/src/sp-tag-use.h b/src/sp-tag-use.h deleted file mode 100644 index 6e068fc21..000000000 --- a/src/sp-tag-use.h +++ /dev/null @@ -1,53 +0,0 @@ -#ifndef __SP_TAG_USE_H__ -#define __SP_TAG_USE_H__ - -/* - * SVG implementation - * - * Authors: - * Theodore Janeczko - * - * Copyright (C) Theodore Janeczko 2012 - * - * Released under GNU GPL, read the file 'COPYING' for more information - */ - -#include -#include -#include "svg/svg-length.h" -#include "sp-object.h" - - -#define SP_TYPE_TAG_USE (sp_tag_use_get_type ()) -#define SP_TAG_USE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), SP_TYPE_TAG_USE, SPTagUse)) -#define SP_TAG_USE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), SP_TYPE_TAG_USE, SPTagUseClass)) -#define SP_IS_TAG_USE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), SP_TYPE_TAG_USE)) -#define SP_IS_TAG_USE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), SP_TYPE_TAG_USE)) - -class SPTagUse; -class SPTagUseClass; -class SPTagUseReference; - -struct SPTagUse : public SPObject { - // item built from the original's repr (the visible clone) - // relative to the SPUse itself, it is treated as a child, similar to a grouped item relative to its group - SPObject *child; - - gchar *href; - - // the reference to the original object - SPTagUseReference *ref; - sigc::connection _changed_connection; -}; - -struct SPTagUseClass { - SPObjectClass parent_class; -}; - -GType sp_tag_use_get_type (void); - -SPItem *sp_tag_use_unlink (SPTagUse *use); -SPItem *sp_tag_use_get_original (SPTagUse *use); - -SPItem *sp_tag_use_root(SPTagUse *use); -#endif diff --git a/src/sp-tag.cpp b/src/sp-tag.cpp deleted file mode 100644 index eef55d628..000000000 --- a/src/sp-tag.cpp +++ /dev/null @@ -1,240 +0,0 @@ -/** \file - * SVG implementation - * - * Authors: - * Theodore Janeczko - * - * Copyright (C) Theodore Janeczko 2012 - * - * Released under GNU GPL, read the file 'COPYING' for more information - */ - -#ifdef HAVE_CONFIG_H -# include "config.h" -#endif - -#include "attributes.h" -#include "sp-tag.h" -#include "xml/repr.h" -#include - -#define DEBUG_TAG -#ifdef DEBUG_TAG -# define debug(f, a...) { g_print("%s(%d) %s:", \ - __FILE__,__LINE__,__FUNCTION__); \ - g_print(f, ## a); \ - g_print("\n"); \ - } -#else -# define debug(f, a...) /**/ -#endif - -/* Tag base class */ - -static void sp_tag_class_init(SPTagClass *klass); -static void sp_tag_init(SPTag *tag); - -static void sp_tag_build(SPObject *object, SPDocument *document, Inkscape::XML::Node *repr); -static void sp_tag_release(SPObject *object); -static void sp_tag_set(SPObject *object, unsigned int key, gchar const *value); -static void sp_tag_update(SPObject *object, SPCtx *ctx, guint flags); -static Inkscape::XML::Node *sp_tag_write(SPObject *object, Inkscape::XML::Document *doc, Inkscape::XML::Node *repr, guint flags); - -static SPObjectClass *tag_parent_class; - -GType -sp_tag_get_type() -{ - static GType tag_type = 0; - - if (!tag_type) { - GTypeInfo tag_info = { - sizeof(SPTagClass), - NULL, NULL, - (GClassInitFunc) sp_tag_class_init, - NULL, NULL, - sizeof(SPTag), - 16, - (GInstanceInitFunc) sp_tag_init, - NULL, /* value_table */ - }; - tag_type = g_type_register_static(SP_TYPE_OBJECT, "SPTag", &tag_info, (GTypeFlags)0); - } - return tag_type; -} - -static void -sp_tag_class_init(SPTagClass *klass) -{ - //GObjectClass *gobject_class = (GObjectClass *)klass; - SPObjectClass *sp_object_class = (SPObjectClass *)klass; - - tag_parent_class = (SPObjectClass*)g_type_class_peek_parent(klass); - - sp_object_class->build = sp_tag_build; - sp_object_class->release = sp_tag_release; - sp_object_class->write = sp_tag_write; - sp_object_class->set = sp_tag_set; - sp_object_class->update = sp_tag_update; -} - -static void -sp_tag_init(SPTag *tag) -{ -} - -/* - * Move this SPItem into or after another SPItem in the doc - * \param target - the SPItem to move into or after - * \param intoafter - move to after the target (false), move inside (sublayer) of the target (true) - */ -void SPTag::moveTo(SPObject *target, gboolean intoafter) { - - Inkscape::XML::Node *target_ref = ( target ? target->getRepr() : NULL ); - Inkscape::XML::Node *our_ref = getRepr(); - gboolean first = FALSE; - - if (target_ref == our_ref) { - // Move to ourself ignore - return; - } - - if (!target_ref) { - // Assume move to the "first" in the top node, find the top node - target_ref = our_ref; - while (target_ref->parent() != target_ref->root()) { - target_ref = target_ref->parent(); - } - first = TRUE; - } - - if (intoafter) { - // Move this inside of the target at the end - our_ref->parent()->removeChild(our_ref); - target_ref->addChild(our_ref, NULL); - } else if (target_ref->parent() != our_ref->parent()) { - // Change in parent, need to remove and add - our_ref->parent()->removeChild(our_ref); - target_ref->parent()->addChild(our_ref, target_ref); - } else if (!first) { - // Same parent, just move - our_ref->parent()->changeOrder(our_ref, target_ref); - } -} - -/** - * Reads the Inkscape::XML::Node, and initializes SPTag variables. For this to get called, - * our name must be associated with a repr via "sp_object_type_register". Best done through - * sp-object-repr.cpp's repr_name_entries array. - */ -static void -sp_tag_build(SPObject *object, SPDocument *document, Inkscape::XML::Node *repr) -{ - object->readAttr( "inkscape:expanded" ); - - if (((SPObjectClass *) tag_parent_class)->build) { - ((SPObjectClass *) tag_parent_class)->build(object, document, repr); - } -} - -/** - * Drops any allocated memory. - */ -static void -sp_tag_release(SPObject *object) -{ - /* deal with our children and our selves here */ - - if (((SPObjectClass *) tag_parent_class)->release) - ((SPObjectClass *) tag_parent_class)->release(object); -} - -/** - * Sets a specific value in the SPTag. - */ -static void -sp_tag_set(SPObject *object, unsigned int key, gchar const *value) -{ - SPTag *tag = SP_TAG(object); - - switch (key) - { - case SP_ATTR_INKSCAPE_EXPANDED: - if ( value && !strcmp(value, "true") ) { - tag->setExpanded(true); - } - break; - default: - if (((SPObjectClass *) tag_parent_class)->set) { - ((SPObjectClass *) tag_parent_class)->set(object, key, value); - } - break; - } -} - -void SPTag::setExpanded(bool isexpanded) { - if ( _expanded != isexpanded ){ - _expanded = isexpanded; - } -} - -/** - * Receives update notifications. - */ -static void -sp_tag_update(SPObject *object, SPCtx *ctx, guint flags) -{ - //SPTag *tag = SP_TAG(object); - - if (flags & (SP_OBJECT_MODIFIED_FLAG | SP_OBJECT_STYLE_MODIFIED_FLAG | - SP_OBJECT_VIEWPORT_MODIFIED_FLAG)) { - - /* do something to trigger redisplay, updates? */ - - } - - if (((SPObjectClass *) tag_parent_class)->update) { - ((SPObjectClass *) tag_parent_class)->update(object, ctx, flags); - } -} - -/** - * Writes its settings to an incoming repr object, if any. - */ -static Inkscape::XML::Node * -sp_tag_write(SPObject *object, Inkscape::XML::Document *doc, Inkscape::XML::Node *repr, guint flags) -{ - SPTag *tag = SP_TAG(object); - - if ((flags & SP_OBJECT_WRITE_BUILD) && !repr) { - repr = doc->createElement("inkscape:tag"); - } - - // Inkscape-only object, not copied during an "plain SVG" dump: - if (flags & SP_OBJECT_WRITE_EXT) { - - if (tag->_expanded) { - repr->setAttribute("inkscape:expanded", "true"); - } else { - repr->setAttribute("inkscape:expanded", NULL); - } - } - - if (((SPObjectClass *) tag_parent_class)->write) { - ((SPObjectClass *) tag_parent_class)->write(object, doc, repr, flags); - } - - return repr; -} - - -/* - 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 : diff --git a/src/sp-tag.h b/src/sp-tag.h deleted file mode 100644 index c5eec785a..000000000 --- a/src/sp-tag.h +++ /dev/null @@ -1,55 +0,0 @@ -#ifndef SP_TAG_H_SEEN -#define SP_TAG_H_SEEN - -/** \file - * SVG implementation - * - * Authors: - * Theodore Janeczko - * - * Copyright (C) Theodore Janeczko 2012 - * - * Released under GNU GPL, read the file 'COPYING' for more information - */ - -#include "sp-object.h" - -/* Skeleton base class */ - -#define SP_TYPE_TAG (sp_tag_get_type()) -#define SP_TAG(o) (G_TYPE_CHECK_INSTANCE_CAST((o), SP_TYPE_TAG, SPTag)) -#define SP_IS_TAG(o) (G_TYPE_CHECK_INSTANCE_TYPE((o), SP_TYPE_TAG)) - -class SPTag; -class SPTagClass; - -class SPTag : public SPObject { -public: - bool _expanded; - - bool expanded() const { return _expanded; } - void setExpanded(bool isexpanded); - - void moveTo(SPObject *target, gboolean intoafter); - -}; - -struct SPTagClass { - SPObjectClass parent_class; -}; - -GType sp_tag_get_type(); - - -#endif /* !SP_SKELETON_H_SEEN */ - -/* - 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 : diff --git a/src/ui/dialog/color-item.cpp b/src/ui/dialog/color-item.cpp index 6eece0c17..a1951ec48 100644 --- a/src/ui/dialog/color-item.cpp +++ b/src/ui/dialog/color-item.cpp @@ -12,7 +12,6 @@ */ #include -#include #include #include #include @@ -40,6 +39,7 @@ #include "color.h" // for SP_RGBA32_U_COMPOSE +#include namespace Inkscape { namespace UI { diff --git a/src/ui/dialog/dialog-manager.cpp b/src/ui/dialog/dialog-manager.cpp index 1fddbf007..ddf41e0c8 100644 --- a/src/ui/dialog/dialog-manager.cpp +++ b/src/ui/dialog/dialog-manager.cpp @@ -111,7 +111,7 @@ DialogManager::DialogManager() { registerFactory("InkscapePreferences", &create); registerFactory("LayersPanel", &create); registerFactory("ObjectsPanel", &create); - //registerFactory("TagsPanel", &create); +// registerFactory("TagsPanel", &create); registerFactory("LivePathEffect", &create); registerFactory("Memory", &create); registerFactory("Messages", &create); @@ -147,7 +147,7 @@ DialogManager::DialogManager() { registerFactory("InkscapePreferences", &create); registerFactory("LayersPanel", &create); registerFactory("ObjectsPanel", &create); - //registerFactory("TagsPanel", &create); +// registerFactory("TagsPanel", &create); registerFactory("LivePathEffect", &create); registerFactory("Memory", &create); registerFactory("Messages", &create); diff --git a/src/ui/dialog/lpe-powerstroke-properties.cpp b/src/ui/dialog/lpe-powerstroke-properties.cpp index cef6f494e..c34351511 100644 --- a/src/ui/dialog/lpe-powerstroke-properties.cpp +++ b/src/ui/dialog/lpe-powerstroke-properties.cpp @@ -13,6 +13,14 @@ * Released under GNU GPL. Read the file 'COPYING' for more information */ +#ifdef HAVE_CONFIG_H +# include +#endif + +#if GLIBMM_DISABLE_DEPRECATED && HAVE_GLIBMM_THREADS_H +#include +#endif + #include "lpe-powerstroke-properties.h" #include #include diff --git a/src/ui/dialog/swatches.cpp b/src/ui/dialog/swatches.cpp index c3889db46..34885a971 100644 --- a/src/ui/dialog/swatches.cpp +++ b/src/ui/dialog/swatches.cpp @@ -43,7 +43,6 @@ #include "path-prefix.h" #include "preferences.h" #include "sp-item.h" -#include "sp-gradient-fns.h" #include "sp-gradient.h" #include "sp-gradient-vector.h" #include "style.h" diff --git a/src/ui/dialog/tags.cpp b/src/ui/dialog/tags.cpp deleted file mode 100644 index 116f9eb0b..000000000 --- a/src/ui/dialog/tags.cpp +++ /dev/null @@ -1,1182 +0,0 @@ -/* - * A simple panel for tags - * - * Authors: - * Theodore Janeczko - * - * Copyright (C) Theodore Janeczko 2012 - * - * Released under GNU GPL, read the file 'COPYING' for more information - */ -#ifdef HAVE_CONFIG_H -# include -#endif - -#include "tags.h" -#include -#include -#include -#include - -#include - -#include "desktop.h" -#include "desktop-style.h" -#include "document.h" -#include "document-undo.h" -#include "helper/action.h" -#include "inkscape.h" -#include "layer-fns.h" -#include "layer-manager.h" -#include "preferences.h" -#include "sp-item.h" -#include "sp-object.h" -#include "sp-shape.h" -#include "svg/css-ostringstream.h" -#include "ui/icon-names.h" -#include "ui/widget/layertypeicon.h" -#include "ui/widget/addtoicon.h" -#include "verbs.h" -#include "widgets/icon.h" -#include "xml/node.h" -#include "xml/node-observer.h" -#include "xml/repr.h" -#include "sp-root.h" -//#include "event-context.h" -#include "selection.h" -#include "dialogs/dialog-events.h" -#include "widgets/sp-color-notebook.h" -#include "style.h" -#include "filter-chemistry.h" -#include "filters/blend.h" -#include "filters/gaussian-blur.h" -#include "sp-clippath.h" -#include "sp-mask.h" -#include "sp-tag.h" -#include "sp-defs.h" -#include "sp-tag-use.h" -#include "sp-tag-use-reference.h" - -//#define DUMP_LAYERS 1 - -namespace Inkscape { -namespace UI { -namespace Dialog { - -using Inkscape::XML::Node; - -TagsPanel& TagsPanel::getInstance() -{ - return *new TagsPanel(); -} - -enum { - COL_ADD = 1 -}; - -enum { - BUTTON_NEW = 0, - BUTTON_TOP, - BUTTON_BOTTOM, - BUTTON_UP, - BUTTON_DOWN, - BUTTON_DELETE, - DRAGNDROP -}; - -class TagsPanel::ObjectWatcher : public Inkscape::XML::NodeObserver { -public: - ObjectWatcher(TagsPanel* pnl, SPObject* obj, Inkscape::XML::Node * repr) : - _pnl(pnl), - _obj(obj), - _repr(repr), - _labelAttr(g_quark_from_string("inkscape:label")) - {} - - ObjectWatcher(TagsPanel* pnl, SPObject* obj) : - _pnl(pnl), - _obj(obj), - _repr(obj->getRepr()), - _labelAttr(g_quark_from_string("inkscape:label")) - {} - - virtual void notifyChildAdded( Node &/*node*/, Node &/*child*/, Node */*prev*/ ) - { - if ( _pnl && _obj ) { - _pnl->_objectsChanged( _obj ); - } - } - virtual void notifyChildRemoved( Node &/*node*/, Node &/*child*/, Node */*prev*/ ) - { - if ( _pnl && _obj ) { - _pnl->_objectsChanged( _obj ); - } - } - virtual void notifyChildOrderChanged( Node &/*node*/, Node &/*child*/, Node */*old_prev*/, Node */*new_prev*/ ) - { - if ( _pnl && _obj ) { - _pnl->_objectsChanged( _obj ); - } - } - virtual void notifyContentChanged( Node &/*node*/, Util::ptr_shared /*old_content*/, Util::ptr_shared /*new_content*/ ) {} - virtual void notifyAttributeChanged( Node &/*node*/, GQuark name, Util::ptr_shared /*old_value*/, Util::ptr_shared /*new_value*/ ) { - if ( _pnl && _obj ) { - if ( name == _labelAttr ) { - _pnl->_updateObject( _obj); - } - } - } - - TagsPanel* _pnl; - SPObject* _obj; - Inkscape::XML::Node* _repr; - GQuark _labelAttr; -}; - -class TagsPanel::InternalUIBounce -{ -public: - int _actionCode; -}; - -void TagsPanel::_styleButton( Gtk::Button& btn, SPDesktop *desktop, unsigned int code, char const* iconName, char const* tooltip ) -{ - bool set = false; - - if ( iconName ) { - GtkWidget *child = sp_icon_new( Inkscape::ICON_SIZE_SMALL_TOOLBAR, iconName ); - gtk_widget_show( child ); - btn.add( *manage(Glib::wrap(child)) ); - btn.set_relief(Gtk::RELIEF_NONE); - set = true; - } - - if ( desktop ) { - Verb *verb = Verb::get( code ); - if ( verb ) { - SPAction *action = verb->get_action(desktop); - if ( !set && action && action->image ) { - GtkWidget *child = sp_icon_new( Inkscape::ICON_SIZE_SMALL_TOOLBAR, action->image ); - gtk_widget_show( child ); - btn.add( *manage(Glib::wrap(child)) ); - set = true; - } - } - } - - btn.set_tooltip_text (tooltip); -} - - -Gtk::MenuItem& TagsPanel::_addPopupItem( SPDesktop *desktop, unsigned int code, char const* iconName, char const* fallback, int id ) -{ - GtkWidget* iconWidget = 0; - const char* label = 0; - - if ( iconName ) { - iconWidget = sp_icon_new( Inkscape::ICON_SIZE_MENU, iconName ); - } - - if ( desktop ) { - Verb *verb = Verb::get( code ); - if ( verb ) { - SPAction *action = verb->get_action(desktop); - if ( !iconWidget && action && action->image ) { - iconWidget = sp_icon_new( Inkscape::ICON_SIZE_MENU, action->image ); - } - - if ( action ) { - label = action->name; - } - } - } - - if ( !label && fallback ) { - label = fallback; - } - - Gtk::Widget* wrapped = 0; - if ( iconWidget ) { - wrapped = manage(Glib::wrap(iconWidget)); - wrapped->show(); - } - - - Gtk::MenuItem* item = 0; - - if (wrapped) { - item = Gtk::manage(new Gtk::ImageMenuItem(*wrapped, label, true)); - } else { - item = Gtk::manage(new Gtk::MenuItem(label, true)); - } - - item->signal_activate().connect(sigc::bind(sigc::mem_fun(*this, &TagsPanel::_takeAction), id)); - _popupMenu.append(*item); - - return *item; -} - -void TagsPanel::_fireAction( unsigned int code ) -{ - if ( _desktop ) { - Verb *verb = Verb::get( code ); - if ( verb ) { - SPAction *action = verb->get_action(_desktop); - if ( action ) { - sp_action_perform( action, NULL ); - } - } - } -} - -void TagsPanel::_takeAction( int val ) -{ - if ( !_pending ) { - _pending = new InternalUIBounce(); - _pending->_actionCode = val; - Glib::signal_timeout().connect( sigc::mem_fun(*this, &TagsPanel::_executeAction), 0 ); - } -} - -bool TagsPanel::_executeAction() -{ - // Make sure selected layer hasn't changed since the action was triggered - if ( _pending) - { - int val = _pending->_actionCode; -// SPObject* target = _pending->_target; - - switch ( val ) { - case BUTTON_NEW: - { - _fireAction( SP_VERB_TAG_NEW ); - } - break; - case BUTTON_TOP: - { - if (_desktop->selection->isEmpty()) - { - _fireAction( SP_VERB_LAYER_TO_TOP ); - } - else - { - _fireAction( SP_VERB_SELECTION_TO_FRONT); - } - } - break; - case BUTTON_BOTTOM: - { - if (_desktop->selection->isEmpty()) - { - _fireAction( SP_VERB_LAYER_TO_BOTTOM ); - } - else - { - _fireAction( SP_VERB_SELECTION_TO_BACK); - } - } - break; - case BUTTON_UP: - { - if (_desktop->selection->isEmpty()) - { - _fireAction( SP_VERB_LAYER_RAISE ); - } - else - { - _fireAction( SP_VERB_SELECTION_RAISE ); - } - } - break; - case BUTTON_DOWN: - { - if (_desktop->selection->isEmpty()) - { - _fireAction( SP_VERB_LAYER_LOWER ); - } - else - { - _fireAction( SP_VERB_SELECTION_LOWER ); - } - } - break; - case BUTTON_DELETE: - { - std::vector todelete; - _tree.get_selection()->selected_foreach_iter(sigc::bind*>(sigc::mem_fun(*this, &TagsPanel::_checkForDeleted), &todelete)); - for (std::vector::iterator iter = todelete.begin(); iter != todelete.end(); ++iter) { - SPObject * obj = *iter; - if (obj && obj->parent && obj->getRepr() && obj->parent->getRepr()) { - obj->parent->getRepr()->removeChild(obj->getRepr()); - } - } - DocumentUndo::done(_document, SP_VERB_DIALOG_TAGS, _("Remove from tags")); - } - break; - case DRAGNDROP: - { - _doTreeMove( ); - } - break; - } - - delete _pending; - _pending = 0; - } - - return false; -} - - -class TagsPanel::ModelColumns : public Gtk::TreeModel::ColumnRecord -{ -public: - - ModelColumns() - { - add(_colParentObject); - add(_colObject); - add(_colLabel); - add(_colAddRemove); - add(_colAllowAddRemove); - } - virtual ~ModelColumns() {} - - Gtk::TreeModelColumn _colParentObject; - Gtk::TreeModelColumn _colObject; - Gtk::TreeModelColumn _colLabel; - Gtk::TreeModelColumn _colAddRemove; - Gtk::TreeModelColumn _colAllowAddRemove; -}; - -void TagsPanel::_checkForDeleted(const Gtk::TreeIter& iter, std::vector* todelete) -{ - Gtk::TreeRow row = *iter; - SPObject * obj = row[_model->_colObject]; - if (obj && obj->parent) { - todelete->push_back(obj); - } -} - -void TagsPanel::_updateObject( SPObject *obj ) { - _store->foreach( sigc::bind(sigc::mem_fun(*this, &TagsPanel::_checkForUpdated), obj) ); -} - -bool TagsPanel::_checkForUpdated(const Gtk::TreePath &/*path*/, const Gtk::TreeIter& iter, SPObject* obj) -{ - Gtk::TreeModel::Row row = *iter; - if ( obj == row[_model->_colObject] ) - { - /* - * We get notified of layer update here (from layer->setLabel()) before layer->label() is set - * with the correct value (sp-object bug?). So use the inkscape:label attribute instead which - * has the correct value (bug #168351) - */ - //row[_model->_colLabel] = layer->label() ? layer->label() : layer->getId(); - gchar const *label; - SPTagUse * use = SP_IS_TAG_USE(obj) ? SP_TAG_USE(obj) : 0; - if (use && use->ref->isAttached()) { - label = use->ref->getObject()->getAttribute("inkscape:label"); - } else { - label = obj->getAttribute("inkscape:label"); - } - row[_model->_colLabel] = label ? label : obj->getId(); - row[_model->_colAddRemove] = SP_IS_TAG(obj); - } - - return false; -} - -void TagsPanel::_objectsSelected( Selection *sel ) { - - _selectedConnection.block(); - _tree.get_selection()->unselect_all(); - for (const GSList * iter = sel->list(); iter != NULL; iter = iter->next) - { - SPObject *obj = reinterpret_cast(iter->data); - _store->foreach(sigc::bind( sigc::mem_fun(*this, &TagsPanel::_checkForSelected), obj)); - } - _selectedConnection.unblock(); - _checkTreeSelection(); -} - -bool TagsPanel::_checkForSelected(const Gtk::TreePath &path, const Gtk::TreeIter& iter, SPObject* obj) -{ - Gtk::TreeModel::Row row = *iter; - SPObject * it = row[_model->_colObject]; - if ( it && SP_IS_TAG_USE(it) && SP_TAG_USE(it)->ref->getObject() == obj ) - { - Glib::RefPtr select = _tree.get_selection(); - - select->select(iter); - } - return false; -} - -void TagsPanel::_objectsChanged(SPObject* root) -{ - while (!_objectWatchers.empty()) - { - TagsPanel::ObjectWatcher *w = _objectWatchers.back(); - w->_repr->removeObserver(*w); - _objectWatchers.pop_back(); - delete w; - } - - if (_desktop) { - SPDocument* document = _desktop->doc(); - SPDefs* root = document->getDefs(); - if ( root ) { - _selectedConnection.block(); - _store->clear(); - _addObject( document, root, 0 ); - _selectedConnection.unblock(); - _objectsSelected(_desktop->selection); - _checkTreeSelection(); - } - } -} - -void TagsPanel::_addObject( SPDocument* doc, SPObject* obj, Gtk::TreeModel::Row* parentRow ) -{ - if ( _desktop && obj ) { - for ( SPObject *child = obj->children; child != NULL; child = child->next) { - if (SP_IS_TAG(child)) - { - Gtk::TreeModel::iterator iter = parentRow ? _store->prepend(parentRow->children()) : _store->prepend(); - Gtk::TreeModel::Row row = *iter; - row[_model->_colObject] = child; - row[_model->_colParentObject] = NULL; - row[_model->_colLabel] = child->label() ? child->label() : child->getId(); - row[_model->_colAddRemove] = true; - row[_model->_colAllowAddRemove] = true; - - _tree.expand_to_path( _store->get_path(iter) ); - - TagsPanel::ObjectWatcher *w = new TagsPanel::ObjectWatcher(this, child); - child->getRepr()->addObserver(*w); - _objectWatchers.push_back(w); - _addObject( doc, child, &row ); - } - } - if (SP_IS_TAG(obj) && obj->children) - { - Gtk::TreeModel::iterator iteritems = parentRow ? _store->append(parentRow->children()) : _store->prepend(); - Gtk::TreeModel::Row rowitems = *iteritems; - rowitems[_model->_colObject] = NULL; - rowitems[_model->_colParentObject] = obj; - rowitems[_model->_colLabel] = _("Items"); - rowitems[_model->_colAddRemove] = false; - rowitems[_model->_colAllowAddRemove] = false; - - _tree.expand_to_path( _store->get_path(iteritems) ); - - for ( SPObject *child = obj->children; child != NULL; child = child->next) { - if (SP_IS_TAG_USE(child)) - { - SPItem *item = SP_TAG_USE(child)->ref->getObject(); - Gtk::TreeModel::iterator iter = _store->prepend(rowitems->children()); - Gtk::TreeModel::Row row = *iter; - row[_model->_colObject] = child; - row[_model->_colParentObject] = NULL; - row[_model->_colLabel] = item ? (item->label() ? item->label() : item->getId()) : SP_TAG_USE(child)->href; - row[_model->_colAddRemove] = false; - row[_model->_colAllowAddRemove] = true; - - if (SP_TAG(obj)->expanded()) { - _tree.expand_to_path( _store->get_path(iter) ); - } - - if (item) { - TagsPanel::ObjectWatcher *w = new TagsPanel::ObjectWatcher(this, child, item->getRepr()); - item->getRepr()->addObserver(*w); - _objectWatchers.push_back(w); - } - } - } - } - } -} - -void TagsPanel::_select_tag( SPTag * tag ) -{ - for (SPObject * child = tag->children; child != NULL; child = child->next) - { - if (SP_IS_TAG(child)) { - _select_tag(SP_TAG(child)); - } else if (SP_IS_TAG_USE(child)) { - SPObject * obj = SP_TAG_USE(child)->ref->getObject(); - if (obj) { - if (_desktop->selection->isEmpty()) _desktop->setCurrentLayer(obj->parent); - _desktop->selection->add(obj); - } - } - } -} - -void TagsPanel::_selected_row_callback( const Gtk::TreeModel::iterator& iter ) -{ - if (iter) { - Gtk::TreeModel::Row row = *iter; - SPObject *obj = row[_model->_colObject]; - if (obj) { - if (SP_IS_TAG(obj)) { - _select_tag(SP_TAG(obj)); - } else if (SP_IS_TAG_USE(obj)) { - SPObject * item = SP_TAG_USE(obj)->ref->getObject(); - if (item) { - if (_desktop->selection->isEmpty()) _desktop->setCurrentLayer(item->parent); - _desktop->selection->add(item); - } - } - } - } -} - -void TagsPanel::_pushTreeSelectionToCurrent() -{ - _selectionChangedConnection.block(); - // TODO hunt down the possible API abuse in getting NULL - if ( _desktop && _desktop->currentRoot() ) { - _desktop->selection->clear(); - _tree.get_selection()->selected_foreach_iter( sigc::mem_fun(*this, &TagsPanel::_selected_row_callback)); - } - _selectionChangedConnection.unblock(); - - _checkTreeSelection(); -} - -void TagsPanel::_checkTreeSelection() -{ - bool sensitive = _tree.get_selection()->count_selected_rows() > 0; - bool sensitiveNonTop = true; - bool sensitiveNonBottom = true; -// if ( _tree.get_selection()->count_selected_rows() > 0 ) { -// sensitive = true; -// -// SPObject* inTree = _selectedLayer(); -// if ( inTree ) { -// -// sensitiveNonTop = (Inkscape::Nex(inTree->parent, inTree) != 0); -// sensitiveNonBottom = (Inkscape::previous_layer(inTree->parent, inTree) != 0); -// -// } -// } - - - for ( std::vector::iterator it = _watching.begin(); it != _watching.end(); ++it ) { - (*it)->set_sensitive( sensitive ); - } - for ( std::vector::iterator it = _watchingNonTop.begin(); it != _watchingNonTop.end(); ++it ) { - (*it)->set_sensitive( sensitiveNonTop ); - } - for ( std::vector::iterator it = _watchingNonBottom.begin(); it != _watchingNonBottom.end(); ++it ) { - (*it)->set_sensitive( sensitiveNonBottom ); - } -} - -bool TagsPanel::_handleKeyEvent(GdkEventKey *event) -{ - - switch (get_group0_keyval(event)) { - case GDK_KEY_Return: - case GDK_KEY_KP_Enter: - case GDK_KEY_F2: { - Gtk::TreeModel::iterator iter = _tree.get_selection()->get_selected(); - if (iter && !_text_renderer->property_editable()) { - Gtk::TreeRow row = *iter; - SPObject * obj = row[_model->_colObject]; - if (obj && SP_IS_TAG(obj)) { - Gtk::TreeModel::Path *path = new Gtk::TreeModel::Path(iter); - // Edit the layer label - _text_renderer->property_editable() = true; - _tree.set_cursor(*path, *_name_column, true); - grab_focus(); - return true; - } - } - } - case GDK_KEY_Delete: { - std::vector todelete; - _tree.get_selection()->selected_foreach_iter(sigc::bind*>(sigc::mem_fun(*this, &TagsPanel::_checkForDeleted), &todelete)); - if (!todelete.empty()) { - for (std::vector::iterator iter = todelete.begin(); iter != todelete.end(); ++iter) { - SPObject * obj = *iter; - if (obj && obj->parent && obj->getRepr() && obj->parent->getRepr()) { - obj->parent->getRepr()->removeChild(obj->getRepr()); - } - } - DocumentUndo::done(_document, SP_VERB_DIALOG_TAGS, _("Remove from tags")); - } - return true; - } - break; - } - return false; -} - -bool TagsPanel::_handleButtonEvent(GdkEventButton* event) -{ - static unsigned doubleclick = 0; - - if ( (event->type == GDK_BUTTON_PRESS) && (event->button == 3) ) { - // TODO - fix to a better is-popup function - Gtk::TreeModel::Path path; - int x = static_cast(event->x); - int y = static_cast(event->y); - if ( _tree.get_path_at_pos( x, y, path ) ) { - _checkTreeSelection(); - _popupMenu.popup(event->button, event->time); - if (_tree.get_selection()->is_selected(path)) { - return true; - } - } - } - - if ( (event->type == GDK_BUTTON_PRESS) && (event->button == 1)) { - // Alt left click on the visible/lock columns - eat this event to keep row selection - Gtk::TreeModel::Path path; - Gtk::TreeViewColumn* col = 0; - int x = static_cast(event->x); - int y = static_cast(event->y); - int x2 = 0; - int y2 = 0; - if ( _tree.get_path_at_pos( x, y, path, col, x2, y2 ) ) { - if (col == _tree.get_column(COL_ADD-1)) { - down_at_add = true; - return true; - } else if ( !(event->state & (GDK_SHIFT_MASK | GDK_CONTROL_MASK)) & _tree.get_selection()->is_selected(path) ) { - _tree.get_selection()->set_select_function(sigc::mem_fun(*this, &TagsPanel::_noSelection)); - _defer_target = path; - } else { - down_at_add = false; - } - } else { - down_at_add = false; - } - } - - if ( event->type == GDK_BUTTON_RELEASE) { - _tree.get_selection()->set_select_function(sigc::mem_fun(*this, &TagsPanel::_rowSelectFunction)); - } - - // TODO - ImageToggler doesn't seem to handle Shift/Alt clicks - so we deal with them here. - if ( (event->type == GDK_BUTTON_RELEASE) && (event->button == 1)) { - - Gtk::TreeModel::Path path; - Gtk::TreeViewColumn* col = 0; - int x = static_cast(event->x); - int y = static_cast(event->y); - int x2 = 0; - int y2 = 0; - if ( _tree.get_path_at_pos( x, y, path, col, x2, y2 ) ) { - if (_defer_target) { - if (_defer_target == path && !(event->x == 0 && event->y == 0)) - { - _tree.set_cursor(path, *col, false); - } - _defer_target = Gtk::TreeModel::Path(); - } else { - Gtk::TreeModel::Children::iterator iter = _tree.get_model()->get_iter(path); - Gtk::TreeModel::Row row = *iter; - - SPObject* obj = row[_model->_colObject]; - - if (obj) { - if (col == _tree.get_column(COL_ADD - 1) && down_at_add) { - if (SP_IS_TAG(obj)) { - bool wasadded = false; - for (const GSList * iter = _desktop->selection->itemList(); iter != NULL; iter = iter->next) - { - SPObject *newobj = reinterpret_cast(iter->data); - bool addchild = true; - for ( SPObject *child = obj->children; child != NULL; child = child->next) { - if (SP_IS_TAG_USE(child) && SP_TAG_USE(child)->ref->getObject() == newobj) { - addchild = false; - } - } - if (addchild) { - Inkscape::XML::Node *clone = _document->getReprDoc()->createElement("inkscape:tagref"); - clone->setAttribute("xlink:href", g_strdup_printf("#%s", newobj->getRepr()->attribute("id")), false); - obj->appendChild(clone); - wasadded = true; - } - } - if (wasadded) { - DocumentUndo::done(_document, SP_VERB_DIALOG_TAGS, _("Add selection to tag")); - } - } else { - std::vector todelete; - _tree.get_selection()->selected_foreach_iter(sigc::bind*>(sigc::mem_fun(*this, &TagsPanel::_checkForDeleted), &todelete)); - if (!todelete.empty()) { - for (std::vector::iterator iter = todelete.begin(); iter != todelete.end(); ++iter) { - SPObject * tobj = *iter; - if (tobj && tobj->parent && tobj->getRepr() && tobj->parent->getRepr()) { - tobj->parent->getRepr()->removeChild(tobj->getRepr()); - } - } - } else if (obj && obj->parent && obj->getRepr() && obj->parent->getRepr()) { - obj->parent->getRepr()->removeChild(obj->getRepr()); - } - DocumentUndo::done(_document, SP_VERB_DIALOG_TAGS, _("Remove from tags")); - } - } - } - } - } - } - - - if ( (event->type == GDK_2BUTTON_PRESS) && (event->button == 1) ) { - doubleclick = 1; - } - - if ( event->type == GDK_BUTTON_RELEASE && doubleclick) { - doubleclick = 0; - Gtk::TreeModel::Path path; - Gtk::TreeViewColumn* col = 0; - int x = static_cast(event->x); - int y = static_cast(event->y); - int x2 = 0; - int y2 = 0; - if ( _tree.get_path_at_pos( x, y, path, col, x2, y2 ) && col == _name_column) { - Gtk::TreeModel::Children::iterator iter = _tree.get_model()->get_iter(path); - Gtk::TreeModel::Row row = *iter; - - SPObject* obj = row[_model->_colObject]; - if (obj && (SP_IS_TAG(obj) || (SP_IS_TAG_USE(obj) && SP_TAG_USE(obj)->ref->getObject()))) { - // Double click on the Layer name, enable editing - _text_renderer->property_editable() = true; - _tree.set_cursor (path, *_name_column, true); - grab_focus(); - } - } - } - - return false; -} - -void TagsPanel::_storeDragSource(const Gtk::TreeModel::iterator& iter) -{ - Gtk::TreeModel::Row row = *iter; - SPObject* obj = row[_model->_colObject]; - SPTag* item = ( obj && SP_IS_TAG(obj) ) ? SP_TAG(obj) : 0; - if (item) - { - _dnd_source.push_back(item); - } -} - -/* - * Drap and drop within the tree - * Save the drag source and drop target SPObjects and if its a drag between layers or into (sublayer) a layer - */ -bool TagsPanel::_handleDragDrop(const Glib::RefPtr& context, int x, int y, guint time) -{ - int cell_x = 0, cell_y = 0; - Gtk::TreeModel::Path target_path; - Gtk::TreeView::Column *target_column; - - _dnd_into = true; - _dnd_target = _document->getDefs(); - _dnd_source.clear(); - _tree.get_selection()->selected_foreach_iter(sigc::mem_fun(*this, &TagsPanel::_storeDragSource)); - - if (_dnd_source.empty()) { - return true; - } - - if (_tree.get_path_at_pos (x, y, target_path, target_column, cell_x, cell_y)) { - // Are we before, inside or after the drop layer - Gdk::Rectangle rect; - _tree.get_background_area (target_path, *target_column, rect); - int cell_height = rect.get_height(); - _dnd_into = (cell_y > (int)(cell_height * 1/3) && cell_y <= (int)(cell_height * 2/3)); - if (cell_y > (int)(cell_height * 2/3)) { - Gtk::TreeModel::Path next_path = target_path; - next_path.next(); - if (_store->iter_is_valid(_store->get_iter(next_path))) { - target_path = next_path; - } else { - // Dragging to the "end" - Gtk::TreeModel::Path up_path = target_path; - up_path.up(); - if (_store->iter_is_valid(_store->get_iter(up_path))) { - // Drop into parent - target_path = up_path; - _dnd_into = true; - } else { - // Drop into the top level - _dnd_target = _document->getDefs(); - _dnd_into = true; - } - } - } - Gtk::TreeModel::iterator iter = _store->get_iter(target_path); - if (_store->iter_is_valid(iter)) { - Gtk::TreeModel::Row row = *iter; - SPObject *obj = row[_model->_colObject]; - SPObject *pobj = row[_model->_colParentObject]; - if (obj) { - if (SP_IS_TAG(obj)) { - _dnd_target = SP_TAG(obj); - } else if (SP_IS_TAG(obj->parent)) { - _dnd_target = SP_TAG(obj->parent); - _dnd_into = true; - } - } else if (pobj && SP_IS_TAG(pobj)) { - _dnd_target = SP_TAG(pobj); - _dnd_into = true; - } else { - return true; - } - } - } - - _takeAction(DRAGNDROP); - - return false; -} - -/* - * Move a layer in response to a drag & drop action - */ -void TagsPanel::_doTreeMove( ) -{ - if (_dnd_target) { - for (std::vector::iterator iter = _dnd_source.begin(); iter != _dnd_source.end(); ++iter) - { - SPTag *src = *iter; - if (src != _dnd_target) { - src->moveTo(_dnd_target, _dnd_into); - } - } - _desktop->selection->clear(); - while (!_dnd_source.empty()) - { - SPTag *src = _dnd_source.back(); - _select_tag(src); - _dnd_source.pop_back(); - } - DocumentUndo::done( _desktop->doc() , SP_VERB_DIALOG_TAGS, - _("Moved tags")); - } -} - - -void TagsPanel::_handleEdited(const Glib::ustring& path, const Glib::ustring& new_text) -{ - Gtk::TreeModel::iterator iter = _tree.get_model()->get_iter(path); - Gtk::TreeModel::Row row = *iter; - - _renameObject(row, new_text); - _text_renderer->property_editable() = false; -} - -void TagsPanel::_handleEditingCancelled() -{ - _text_renderer->property_editable() = false; -} - -void TagsPanel::_renameObject(Gtk::TreeModel::Row row, const Glib::ustring& name) -{ - if ( row && _desktop) { - SPObject* obj = row[_model->_colObject]; - if ( obj ) { - if (SP_IS_TAG(obj)) { - gchar const* oldLabel = obj->label(); - if ( !name.empty() && (!oldLabel || name != oldLabel) ) { - obj->setLabel(name.c_str()); - DocumentUndo::done( _desktop->doc() , SP_VERB_NONE, - _("Rename object")); - } - } else if (SP_IS_TAG_USE(obj) && (obj = SP_TAG_USE(obj)->ref->getObject())) { - gchar const* oldLabel = obj->label(); - if ( !name.empty() && (!oldLabel || name != oldLabel) ) { - obj->setLabel(name.c_str()); - DocumentUndo::done( _desktop->doc() , SP_VERB_NONE, - _("Rename object")); - } - } - } - } -} - -bool TagsPanel::_noSelection( Glib::RefPtr const & /*model*/, Gtk::TreeModel::Path const & /*path*/, bool currentlySelected ) -{ - return false; -} - -bool TagsPanel::_rowSelectFunction( Glib::RefPtr const & /*model*/, Gtk::TreeModel::Path const & /*path*/, bool currentlySelected ) -{ - bool val = true; - if ( !currentlySelected && _toggleEvent ) - { - GdkEvent* event = gtk_get_current_event(); - if ( event ) { - // (keep these checks separate, so we know when to call gdk_event_free() - if ( event->type == GDK_BUTTON_PRESS ) { - GdkEventButton const* target = reinterpret_cast(_toggleEvent); - GdkEventButton const* evtb = reinterpret_cast(event); - - if ( (evtb->window == target->window) - && (evtb->send_event == target->send_event) - && (evtb->time == target->time) - && (evtb->state == target->state) - ) - { - // Ooooh! It's a magic one - val = false; - } - } - gdk_event_free(event); - } - } - return val; -} - -void TagsPanel::_setExpanded(const Gtk::TreeModel::iterator& iter, const Gtk::TreeModel::Path& /*path*/, bool isexpanded) -{ - Gtk::TreeModel::Row row = *iter; - - SPObject* obj = row[_model->_colParentObject]; - if (obj && SP_IS_TAG(obj)) - { - SP_TAG(obj)->setExpanded(isexpanded); - obj->updateRepr(SP_OBJECT_WRITE_NO_CHILDREN | SP_OBJECT_WRITE_EXT); - } -} - -/** - * Constructor - */ -TagsPanel::TagsPanel() : - UI::Widget::Panel("", "/dialogs/tags", SP_VERB_DIALOG_TAGS), - _rootWatcher(0), - deskTrack(), - _desktop(0), - _document(0), - _model(0), - _pending(0), - _toggleEvent(0), - _defer_target(), - desktopChangeConn() -{ - //Inkscape::Preferences *prefs = Inkscape::Preferences::get(); - - ModelColumns *zoop = new ModelColumns(); - _model = zoop; - - _store = Gtk::TreeStore::create( *zoop ); - - _tree.set_model( _store ); - _tree.set_headers_visible(false); - _tree.set_reorderable(true); - _tree.enable_model_drag_dest (Gdk::ACTION_MOVE); - - Inkscape::UI::Widget::AddToIcon * addRenderer = manage( new Inkscape::UI::Widget::AddToIcon()); - int addColNum = _tree.append_column("type", *addRenderer) - 1; - Gtk::TreeViewColumn *col = _tree.get_column(addColNum); - if ( col ) { - col->add_attribute( addRenderer->property_active(), _model->_colAddRemove ); - col->add_attribute( addRenderer->property_visible(), _model->_colAllowAddRemove ); - } - - _text_renderer = manage(new Gtk::CellRendererText()); - int nameColNum = _tree.append_column("Name", *_text_renderer) - 1; - _name_column = _tree.get_column(nameColNum); - _name_column->add_attribute(_text_renderer->property_text(), _model->_colLabel); - - _tree.set_expander_column( *_tree.get_column(nameColNum) ); - - _tree.get_selection()->set_mode(Gtk::SELECTION_MULTIPLE); - _selectedConnection = _tree.get_selection()->signal_changed().connect( sigc::mem_fun(*this, &TagsPanel::_pushTreeSelectionToCurrent) ); - _tree.get_selection()->set_select_function( sigc::mem_fun(*this, &TagsPanel::_rowSelectFunction) ); - - _tree.signal_drag_drop().connect( sigc::mem_fun(*this, &TagsPanel::_handleDragDrop), false); - _collapsedConnection = _tree.signal_row_collapsed().connect( sigc::bind(sigc::mem_fun(*this, &TagsPanel::_setExpanded), false)); - _expandedConnection = _tree.signal_row_expanded().connect( sigc::bind(sigc::mem_fun(*this, &TagsPanel::_setExpanded), true)); - - _text_renderer->signal_edited().connect( sigc::mem_fun(*this, &TagsPanel::_handleEdited) ); - _text_renderer->signal_editing_canceled().connect( sigc::mem_fun(*this, &TagsPanel::_handleEditingCancelled) ); - - _tree.signal_button_press_event().connect( sigc::mem_fun(*this, &TagsPanel::_handleButtonEvent), false ); - _tree.signal_button_release_event().connect( sigc::mem_fun(*this, &TagsPanel::_handleButtonEvent), false ); - _tree.signal_key_press_event().connect( sigc::mem_fun(*this, &TagsPanel::_handleKeyEvent), false ); - - _scroller.add( _tree ); - _scroller.set_policy( Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC ); - _scroller.set_shadow_type(Gtk::SHADOW_IN); - Gtk::Requisition sreq; -#if WITH_GTKMM_3_0 - Gtk::Requisition sreq_natural; - _scroller.get_preferred_size(sreq_natural, sreq); -#else - sreq = _scroller.size_request(); -#endif - int minHeight = 70; - if (sreq.height < minHeight) { - // Set a min height to see the layers when used with Ubuntu liboverlay-scrollbar - _scroller.set_size_request(sreq.width, minHeight); - } - - _layersPage.pack_start( _scroller, Gtk::PACK_EXPAND_WIDGET ); - - _layersPage.pack_end(_buttonsRow, Gtk::PACK_SHRINK); - - _getContents()->pack_start(_layersPage, Gtk::PACK_EXPAND_WIDGET); - - SPDesktop* targetDesktop = getDesktop(); - - Gtk::Button* btn = manage( new Gtk::Button() ); - _styleButton( *btn, targetDesktop, SP_VERB_TAG_NEW, GTK_STOCK_ADD, _("Add a new tag") ); - btn->signal_clicked().connect( sigc::bind( sigc::mem_fun(*this, &TagsPanel::_takeAction), (int)BUTTON_NEW) ); - _buttonsSecondary.pack_start(*btn, Gtk::PACK_SHRINK); - -// btn = manage( new Gtk::Button("Dup") ); -// btn->signal_clicked().connect( sigc::bind( sigc::mem_fun(*this, &LayersPanel::_takeAction), (int)BUTTON_DUPLICATE) ); -// _buttonsRow.add( *btn ); - - btn = manage( new Gtk::Button() ); - _styleButton( *btn, targetDesktop, SP_VERB_LAYER_DELETE, GTK_STOCK_REMOVE, _("Remove Item/Tag") ); - btn->signal_clicked().connect( sigc::bind( sigc::mem_fun(*this, &TagsPanel::_takeAction), (int)BUTTON_DELETE) ); - _watching.push_back( btn ); - _buttonsSecondary.pack_start(*btn, Gtk::PACK_SHRINK); - - _buttonsRow.pack_start(_buttonsSecondary, Gtk::PACK_EXPAND_WIDGET); - _buttonsRow.pack_end(_buttonsPrimary, Gtk::PACK_EXPAND_WIDGET); - - // ------------------------------------------------------- - { - _watching.push_back( &_addPopupItem( targetDesktop, SP_VERB_TAG_NEW, 0, "New", (int)BUTTON_NEW ) ); - - _popupMenu.show_all_children(); - } - // ------------------------------------------------------- - - - - for ( std::vector::iterator it = _watching.begin(); it != _watching.end(); ++it ) { - (*it)->set_sensitive( false ); - } - for ( std::vector::iterator it = _watchingNonTop.begin(); it != _watchingNonTop.end(); ++it ) { - (*it)->set_sensitive( false ); - } - for ( std::vector::iterator it = _watchingNonBottom.begin(); it != _watchingNonBottom.end(); ++it ) { - (*it)->set_sensitive( false ); - } - - setDesktop( targetDesktop ); - - show_all_children(); - - // restorePanelPrefs(); - - // Connect this up last - desktopChangeConn = deskTrack.connectDesktopChanged( sigc::mem_fun(*this, &TagsPanel::setDesktop) ); - deskTrack.connect(GTK_WIDGET(gobj())); -} - -TagsPanel::~TagsPanel() -{ - - setDesktop(NULL); - - if ( _model ) - { - delete _model; - _model = 0; - } - - if (_pending) { - delete _pending; - _pending = 0; - } - - if ( _toggleEvent ) - { - gdk_event_free( _toggleEvent ); - _toggleEvent = 0; - } - - desktopChangeConn.disconnect(); - deskTrack.disconnect(); -} - -void TagsPanel::setDocument(SPDesktop* /*desktop*/, SPDocument* document) -{ - while (!_objectWatchers.empty()) - { - TagsPanel::ObjectWatcher *w = _objectWatchers.back(); - w->_repr->removeObserver(*w); - _objectWatchers.pop_back(); - delete w; - } - - if (_rootWatcher) - { - _rootWatcher->_repr->removeObserver(*_rootWatcher); - delete _rootWatcher; - _rootWatcher = NULL; - } - - _document = document; - - if (document && document->getDefs() && document->getDefs()->getRepr()) - { - _rootWatcher = new TagsPanel::ObjectWatcher(this, document->getDefs()); - document->getDefs()->getRepr()->addObserver(*_rootWatcher); - _objectsChanged(document->getDefs()); - } -} - -void TagsPanel::setDesktop( SPDesktop* desktop ) -{ - Panel::setDesktop(desktop); - - if ( desktop != _desktop ) { - _documentChangedConnection.disconnect(); - _selectionChangedConnection.disconnect(); - if ( _desktop ) { - _desktop = 0; - } - - _desktop = Panel::getDesktop(); - if ( _desktop ) { - //setLabel( _desktop->doc()->name ); - _documentChangedConnection = _desktop->connectDocumentReplaced( sigc::mem_fun(*this, &TagsPanel::setDocument)); - _selectionChangedConnection = _desktop->selection->connectChanged( sigc::mem_fun(*this, &TagsPanel::_objectsSelected)); - - setDocument(_desktop, _desktop->doc()); - } - } -/* - GSList const *layers = _desktop->doc()->getResourceList( "layer" ); - g_message( "layers list starts at %p", layers ); - for ( GSList const *iter=layers ; iter ; iter = iter->next ) { - SPObject *layer=static_cast(iter->data); - g_message(" {%s} [%s]", layer->id, layer->label() ); - } -*/ - deskTrack.setBase(desktop); -} - - - - - -} //namespace Dialogs -} //namespace UI -} //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 : diff --git a/src/ui/dialog/tags.h b/src/ui/dialog/tags.h deleted file mode 100644 index d35dfba01..000000000 --- a/src/ui/dialog/tags.h +++ /dev/null @@ -1,181 +0,0 @@ -/* - * A simple dialog for tags UI. - * - * Authors: - * Theodore Janeczko - * - * Copyright (C) Theodore Janeczko 2012 - * - * Released under GNU GPL, read the file 'COPYING' for more information - */ - -#ifndef SEEN_TAGS_PANEL_H -#define SEEN_TAGS_PANEL_H - -#include -#include -#include -#include -#include -#include "ui/widget/spinbutton.h" -#include "ui/widget/panel.h" -#include "ui/widget/object-composite-settings.h" -#include "desktop-tracker.h" -#include "ui/widget/style-subject.h" -#include "selection.h" -#include "ui/widget/filter-effect-chooser.h" - -class SPObject; -class SPTag; -struct SPColorSelector; - -namespace Inkscape { - -namespace UI { -namespace Dialog { - - -/** - * A panel that displays layers. - */ -class TagsPanel : public UI::Widget::Panel -{ -public: - TagsPanel(); - virtual ~TagsPanel(); - - //virtual void setOrientation( Gtk::AnchorType how ); - - static TagsPanel& getInstance(); - - void setDesktop( SPDesktop* desktop ); - void setDocument( SPDesktop* desktop, SPDocument* document); - -protected: - //virtual void _handleAction( int setId, int itemId ); - friend void sp_highlight_picker_color_mod(SPColorSelector *csel, GObject *cp); -private: - class ModelColumns; - class InternalUIBounce; - class ObjectWatcher; - - TagsPanel(TagsPanel const &); // no copy - TagsPanel &operator=(TagsPanel const &); // no assign - - void _styleButton( Gtk::Button& btn, SPDesktop *desktop, unsigned int code, char const* iconName, char const* tooltip ); - void _fireAction( unsigned int code ); - Gtk::MenuItem& _addPopupItem( SPDesktop *desktop, unsigned int code, char const* iconName, char const* fallback, int id ); - - bool _handleButtonEvent(GdkEventButton *event); - bool _handleKeyEvent(GdkEventKey *event); - - void _storeDragSource(const Gtk::TreeModel::iterator& iter); - bool _handleDragDrop(const Glib::RefPtr& context, int x, int y, guint time); - void _handleEdited(const Glib::ustring& path, const Glib::ustring& new_text); - void _handleEditingCancelled(); - - void _doTreeMove(); - void _renameObject(Gtk::TreeModel::Row row, const Glib::ustring& name); - - void _pushTreeSelectionToCurrent(); - void _selected_row_callback( const Gtk::TreeModel::iterator& iter ); - void _select_tag( SPTag * tag ); - - void _checkTreeSelection(); - - void _takeAction( int val ); - bool _executeAction(); - - void _setExpanded( const Gtk::TreeModel::iterator& iter, const Gtk::TreeModel::Path& path, bool isexpanded ); - - bool _noSelection( Glib::RefPtr const & model, Gtk::TreeModel::Path const & path, bool b ); - bool _rowSelectFunction( Glib::RefPtr const & model, Gtk::TreeModel::Path const & path, bool b ); - - void _updateObject(SPObject *obj); - bool _checkForUpdated(const Gtk::TreePath &path, const Gtk::TreeIter& iter, SPObject* obj); - - void _objectsSelected(Selection *sel); - bool _checkForSelected(const Gtk::TreePath& path, const Gtk::TreeIter& iter, SPObject* layer); - - void _objectsChanged(SPObject *root); - void _addObject( SPDocument* doc, SPObject* obj, Gtk::TreeModel::Row* parentRow ); - - void _checkForDeleted(const Gtk::TreeIter& iter, std::vector* todelete); - -// std::vector groupConnections; - TagsPanel::ObjectWatcher* _rootWatcher; - std::vector _objectWatchers; - - // Hooked to the layer manager: - sigc::connection _documentChangedConnection; - sigc::connection _selectionChangedConnection; - - sigc::connection _changedConnection; - sigc::connection _addedConnection; - sigc::connection _removedConnection; - - // Internal - sigc::connection _selectedConnection; - sigc::connection _expandedConnection; - sigc::connection _collapsedConnection; - - DesktopTracker deskTrack; - SPDesktop* _desktop; - SPDocument* _document; - ModelColumns* _model; - InternalUIBounce* _pending; - gboolean _dnd_into; - std::vector _dnd_source; - SPObject* _dnd_target; - - GdkEvent* _toggleEvent; - bool down_at_add; - - Gtk::TreeModel::Path _defer_target; - - Glib::RefPtr _store; - std::vector _watching; - std::vector _watchingNonTop; - std::vector _watchingNonBottom; - - Gtk::TreeView _tree; - Gtk::CellRendererText *_text_renderer; - Gtk::TreeView::Column *_name_column; -#if WITH_GTKMM_3_0 - Gtk::Box _buttonsRow; - Gtk::Box _buttonsPrimary; - Gtk::Box _buttonsSecondary; -#else - Gtk::HBox _buttonsRow; - Gtk::HBox _buttonsPrimary; - Gtk::HBox _buttonsSecondary; -#endif - Gtk::ScrolledWindow _scroller; - Gtk::Menu _popupMenu; - Inkscape::UI::Widget::SpinButton _spinBtn; - Gtk::VBox _layersPage; - - sigc::connection desktopChangeConn; - -}; - - - -} //namespace Dialogs -} //namespace UI -} //namespace Inkscape - - - -#endif // SEEN_OBJECTS_PANEL_H - -/* - 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 : diff --git a/src/ui/widget/addtoicon.h b/src/ui/widget/addtoicon.h index aa8b4148e..9c134d231 100644 --- a/src/ui/widget/addtoicon.h +++ b/src/ui/widget/addtoicon.h @@ -13,9 +13,9 @@ #include "config.h" #endif -#include #include #include +#include namespace Inkscape { namespace UI { diff --git a/src/ui/widget/clipmaskicon.h b/src/ui/widget/clipmaskicon.h index f1c1e7628..eca852a83 100644 --- a/src/ui/widget/clipmaskicon.h +++ b/src/ui/widget/clipmaskicon.h @@ -13,9 +13,9 @@ #include "config.h" #endif -#include #include #include +#include namespace Inkscape { namespace UI { diff --git a/src/ui/widget/highlight-picker.cpp b/src/ui/widget/highlight-picker.cpp index bf93fa960..2afdc02a6 100644 --- a/src/ui/widget/highlight-picker.cpp +++ b/src/ui/widget/highlight-picker.cpp @@ -7,7 +7,14 @@ * Released under GNU GPL, read the file 'COPYING' for more information */ -#include +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#if GLIBMM_DISABLE_DEPRECATED && HAVE_GLIBMM_THREADS_H +#include +#endif + #include "display/cairo-utils.h" #include @@ -16,6 +23,7 @@ #include "widgets/icon.h" #include "widgets/toolbox.h" #include "ui/icon-names.h" +#include namespace Inkscape { namespace UI { diff --git a/src/ui/widget/highlight-picker.h b/src/ui/widget/highlight-picker.h index 2d7dbc14e..c5fe4c02c 100644 --- a/src/ui/widget/highlight-picker.h +++ b/src/ui/widget/highlight-picker.h @@ -13,9 +13,9 @@ #include "config.h" #endif -#include #include #include +#include namespace Inkscape { namespace UI { diff --git a/src/ui/widget/insertordericon.cpp b/src/ui/widget/insertordericon.cpp index 9002a99c2..2f06225bc 100644 --- a/src/ui/widget/insertordericon.cpp +++ b/src/ui/widget/insertordericon.cpp @@ -7,6 +7,13 @@ * Released under GNU GPL, read the file 'COPYING' for more information */ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#if GLIBMM_DISABLE_DEPRECATED && HAVE_GLIBMM_THREADS_H +#include +#endif #include "ui/widget/insertordericon.h" diff --git a/src/ui/widget/layertypeicon.h b/src/ui/widget/layertypeicon.h index 4ad3f16fb..6c71ce361 100644 --- a/src/ui/widget/layertypeicon.h +++ b/src/ui/widget/layertypeicon.h @@ -13,9 +13,9 @@ #include "config.h" #endif -#include #include #include +#include namespace Inkscape { namespace UI { diff --git a/src/verbs.cpp b/src/verbs.cpp index 9c0908e93..26e5ce531 100644 --- a/src/verbs.cpp +++ b/src/verbs.cpp @@ -2043,9 +2043,9 @@ void DialogVerb::perform(SPAction *action, void *data) case SP_VERB_DIALOG_OBJECTS: dt->_dlg_mgr->showDialog("ObjectsPanel"); break; - case SP_VERB_DIALOG_TAGS: + /*case SP_VERB_DIALOG_TAGS: dt->_dlg_mgr->showDialog("TagsPanel"); - break; + break;*/ //in a moment my dear case SP_VERB_DIALOG_LIVE_PATH_EFFECT: dt->_dlg_mgr->showDialog("LivePathEffect"); break; @@ -2866,8 +2866,8 @@ Verb *Verb::_base_verbs[] = { N_("View Layers"), INKSCAPE_ICON("dialog-layers")), new DialogVerb(SP_VERB_DIALOG_OBJECTS, "DialogObjects", N_("Object_s..."), N_("View Objects"), INKSCAPE_ICON("dialog-layers")), - new DialogVerb(SP_VERB_DIALOG_TAGS, "DialogObjects", N_("Ta_gs..."), - N_("View Tags"), INKSCAPE_ICON("edit-select-all-layers")), + /*new DialogVerb(SP_VERB_DIALOG_TAGS, "DialogObjects", N_("Ta_gs..."), + N_("View Tags"), INKSCAPE_ICON("edit-select-all-layers")),*/ new DialogVerb(SP_VERB_DIALOG_LIVE_PATH_EFFECT, "DialogLivePathEffect", N_("Path E_ffects ..."), N_("Manage, edit, and apply path effects"), NULL), new DialogVerb(SP_VERB_DIALOG_FILTER_EFFECTS, "DialogFilterEffects", N_("Filter _Editor..."), diff --git a/src/verbs.h b/src/verbs.h index b8a0b1fd5..1533bbd50 100644 --- a/src/verbs.h +++ b/src/verbs.h @@ -290,7 +290,7 @@ enum { SP_VERB_DIALOG_EXTENSIONEDITOR, SP_VERB_DIALOG_LAYERS, SP_VERB_DIALOG_OBJECTS, - SP_VERB_DIALOG_TAGS, +// SP_VERB_DIALOG_TAGS, SP_VERB_DIALOG_LIVE_PATH_EFFECT, SP_VERB_DIALOG_FILTER_EFFECTS, SP_VERB_DIALOG_SVG_FONTS, -- cgit v1.2.3 From fd36e8d406b5ca3bfdc575a949351c6ae4a45c57 Mon Sep 17 00:00:00 2001 From: "Liam P. White" Date: Sat, 8 Mar 2014 20:52:27 -0500 Subject: Remove all trace of the Tags dialog Fixed Attach Path and Fill Between Many LPEs Enabled Gradient Meshes (bzr r13090.1.21) --- src/live_effects/effect.cpp | 8 ++++---- src/live_effects/lpe-attach-path.cpp | 4 ++-- src/live_effects/lpe-attach-path.h | 2 +- src/menus-skeleton.h | 1 - src/ui/dialog/swatches.cpp | 1 + 5 files changed, 8 insertions(+), 8 deletions(-) (limited to 'src') diff --git a/src/live_effects/effect.cpp b/src/live_effects/effect.cpp index 2ffff153c..17b229352 100644 --- a/src/live_effects/effect.cpp +++ b/src/live_effects/effect.cpp @@ -47,7 +47,7 @@ #include "live_effects/lpe-extrude.h" #include "live_effects/lpe-powerstroke.h" #include "live_effects/lpe-clone-original.h" -//#include "live_effects/lpe-attach-path.h" +#include "live_effects/lpe-attach-path.h" #include "live_effects/lpe-fill-between-strokes.h" #include "live_effects/lpe-fill-between-many.h" #include "live_effects/lpe-ellipse_5pts.h" @@ -130,7 +130,7 @@ const Util::EnumData LPETypeData[] = { {POWERSTROKE, N_("Power stroke"), "powerstroke"}, {CLONE_ORIGINAL, N_("Clone original path"), "clone_original"}, /* Ponyscape */ -// {ATTACH_PATH, N_("Attach path"), "attach_path"}, + {ATTACH_PATH, N_("Attach path"), "attach_path"}, {FILL_BETWEEN_STROKES, N_("Fill between strokes"), "fill_between_strokes"}, {FILL_BETWEEN_MANY, N_("Fill between many"), "fill_between_many"}, {ELLIPSE_5PTS, N_("Ellipse by 5 points"), "ellipse_5pts"}, @@ -258,9 +258,9 @@ Effect::New(EffectType lpenr, LivePathEffectObject *lpeobj) case CLONE_ORIGINAL: neweffect = static_cast ( new LPECloneOriginal(lpeobj) ); break; - /*case ATTACH_PATH: + case ATTACH_PATH: neweffect = static_cast ( new LPEAttachPath(lpeobj) ); - break;*/ + break; case FILL_BETWEEN_STROKES: neweffect = static_cast ( new LPEFillBetweenStrokes(lpeobj) ); break; diff --git a/src/live_effects/lpe-attach-path.cpp b/src/live_effects/lpe-attach-path.cpp index b3d5ed9b7..0cceb1cb7 100644 --- a/src/live_effects/lpe-attach-path.cpp +++ b/src/live_effects/lpe-attach-path.cpp @@ -62,9 +62,9 @@ void LPEAttachPath::resetDefaults(SPItem const * item) curve_end_previous_origin = end_path_curve_end.getOrigin(); } -void LPEAttachPath::doBeforeEffect(const SPLPEItem *lpeitem) +void LPEAttachPath::doBeforeEffect(SPLPEItem const *lpeitem) { - lpe_effect = lpeitem; + lpe_effect = const_cast (lpeitem); } void LPEAttachPath::doEffect (SPCurve * curve) diff --git a/src/live_effects/lpe-attach-path.h b/src/live_effects/lpe-attach-path.h index 3dda189d6..390282f90 100644 --- a/src/live_effects/lpe-attach-path.h +++ b/src/live_effects/lpe-attach-path.h @@ -45,7 +45,7 @@ private: ScalarParam end_path_position; TransformedPointParam end_path_curve_start; VectorParam end_path_curve_end; - const SPLPEItem * lpe_effect; + SPLPEItem * lpe_effect; }; }; //namespace LivePathEffect diff --git a/src/menus-skeleton.h b/src/menus-skeleton.h index 422609390..f1a88cd2d 100644 --- a/src/menus-skeleton.h +++ b/src/menus-skeleton.h @@ -180,7 +180,6 @@ static char const menus_skeleton[] = " \n" " \n" " \n" -" \n" " \n" " \n" " \n" diff --git a/src/ui/dialog/swatches.cpp b/src/ui/dialog/swatches.cpp index 34885a971..2a8471b55 100644 --- a/src/ui/dialog/swatches.cpp +++ b/src/ui/dialog/swatches.cpp @@ -6,6 +6,7 @@ * Jon A. Cruz * John Bintz * Abhishek Sharma + * Theodore Janezcko * * Copyright (C) 2005 Jon A. Cruz * Copyright (C) 2008 John Bintz -- cgit v1.2.3 From 13c192e2fa564c0a743e13e30b1cf6de9b1a39a6 Mon Sep 17 00:00:00 2001 From: "Liam P. White" Date: Wed, 12 Mar 2014 08:56:04 -0400 Subject: Reverted swatches Removed a toy effect (not ready yet) Fixed a bug with Livarot General cleanup (bzr r13090.1.23) --- src/display/drawing-item.cpp | 5 +- src/live_effects/Makefile_insert | 4 +- src/live_effects/effect-enum.h | 2 +- src/live_effects/effect.cpp | 10 +- src/live_effects/lpe-jointype.h | 43 - src/live_effects/parameter/originalpatharray.cpp | 7 +- src/live_effects/pathoutlineprovider.h | 766 ------ src/path-chemistry.cpp | 8 + src/splivarot.cpp | 28 +- src/ui/dialog/color-item.cpp | 862 +++++-- src/ui/dialog/color-item.h | 108 +- src/ui/dialog/object-properties.cpp | 1 + src/ui/dialog/objects.cpp | 227 +- src/ui/dialog/swatches.cpp | 2944 +++++++--------------- src/ui/dialog/swatches.h | 153 +- src/widgets/desktop-widget.cpp | 2 +- 16 files changed, 1870 insertions(+), 3300 deletions(-) delete mode 100755 src/live_effects/lpe-jointype.h delete mode 100755 src/live_effects/pathoutlineprovider.h (limited to 'src') diff --git a/src/display/drawing-item.cpp b/src/display/drawing-item.cpp index 13e7b61eb..6c7f99d42 100644 --- a/src/display/drawing-item.cpp +++ b/src/display/drawing-item.cpp @@ -808,9 +808,10 @@ DrawingItem::pick(Geom::Point const &p, double delta, unsigned flags) { // Sometimes there's no BBOX in state, reason unknown (bug 992817) // I made this not an assert to remove the warning + // This warning clutters the console output, so commented out if (!(_state & STATE_BBOX) || !(_state & STATE_PICK)) { - g_warning("Invalid state when picking: STATE_BBOX = %d, STATE_PICK = %d", - _state & STATE_BBOX, _state & STATE_PICK); + /*g_warning("Invalid state when picking: STATE_BBOX = %d, STATE_PICK = %d", + _state & STATE_BBOX, _state & STATE_PICK);*/ return NULL; } // ignore invisible and insensitive items unless sticky diff --git a/src/live_effects/Makefile_insert b/src/live_effects/Makefile_insert index 76d7b418f..35a85b4aa 100644 --- a/src/live_effects/Makefile_insert +++ b/src/live_effects/Makefile_insert @@ -92,6 +92,4 @@ ink_common_sources += \ live_effects/lpe-fill-between-many.cpp \ live_effects/lpe-fill-between-many.h \ live_effects/lpe-ellipse_5pts.cpp \ - live_effects/lpe-ellipse_5pts.h \ - live_effects/lpe-jointype.cpp \ - live_effects/lpe-jointype.h + live_effects/lpe-ellipse_5pts.h diff --git a/src/live_effects/effect-enum.h b/src/live_effects/effect-enum.h index 46bc56a81..9c76875e9 100644 --- a/src/live_effects/effect-enum.h +++ b/src/live_effects/effect-enum.h @@ -55,7 +55,7 @@ enum EffectType { FILL_BETWEEN_MANY, ELLIPSE_5PTS, BOUNDING_BOX, - JOIN_TYPE, +// JOIN_TYPE, INVALID_LPE // This must be last (I made it such that it is not needed anymore I think..., Don't trust on it being last. - johan) }; diff --git a/src/live_effects/effect.cpp b/src/live_effects/effect.cpp index 17b229352..eac0f79f4 100644 --- a/src/live_effects/effect.cpp +++ b/src/live_effects/effect.cpp @@ -5,7 +5,7 @@ * Released under GNU GPL, read the file 'COPYING' for more information */ -#define LPE_ENABLE_TEST_EFFECTS +//#define LPE_ENABLE_TEST_EFFECTS //uncomment for toy effects #ifdef HAVE_CONFIG_H # include "config.h" @@ -52,7 +52,7 @@ #include "live_effects/lpe-fill-between-many.h" #include "live_effects/lpe-ellipse_5pts.h" #include "live_effects/lpe-bounding-box.h" -#include "live_effects/lpe-jointype.h" +//#include "live_effects/lpe-jointype.h" #include "xml/node-event-vector.h" #include "sp-object.h" @@ -109,7 +109,7 @@ const Util::EnumData LPETypeData[] = { {RECURSIVE_SKELETON, N_("Recursive skeleton"), "recursive_skeleton"}, {TANGENT_TO_CURVE, N_("Tangent to curve"), "tangent_to_curve"}, {TEXT_LABEL, N_("Text label"), "text_label"}, - {JOIN_TYPE, N_("Join type"), "join_type"}, +// {JOIN_TYPE, N_("Join type"), "join_type"}, #endif /* 0.46 */ {BEND_PATH, N_("Bend"), "bend_path"}, @@ -273,9 +273,9 @@ Effect::New(EffectType lpenr, LivePathEffectObject *lpeobj) case BOUNDING_BOX: neweffect = static_cast ( new LPEBoundingBox(lpeobj) ); break; - case JOIN_TYPE: + /*case JOIN_TYPE: neweffect = static_cast ( new LPEJoinType(lpeobj) ); - break; + break;*/ default: g_warning("LivePathEffect::Effect::New called with invalid patheffect type (%d)", lpenr); neweffect = NULL; diff --git a/src/live_effects/lpe-jointype.h b/src/live_effects/lpe-jointype.h deleted file mode 100755 index db113c66a..000000000 --- a/src/live_effects/lpe-jointype.h +++ /dev/null @@ -1,43 +0,0 @@ -/* Authors: - * Liam P White - * - * Copyright (C) 2014 Authors - * - * Released under GNU GPL v2, read the file COPYING for more information - */ -#ifndef INKSCAPE_LPE_JOINTYPE_H -#define INKSCAPE_LPE_JOINTYPE_H - -#include "live_effects/effect.h" -#include "live_effects/parameter/parameter.h" -#include "live_effects/parameter/point.h" -#include "live_effects/parameter/enum.h" - -namespace Inkscape { -namespace LivePathEffect { - -class LPEJoinType : public Effect { -public: - LPEJoinType(LivePathEffectObject *lpeobject); - virtual ~LPEJoinType(); - - virtual void doOnApply(SPLPEItem const* lpeitem); - virtual void doOnRemove(SPLPEItem const* lpeitem); - virtual std::vector doEffect_path (std::vector const & path_in); - -private: - LPEJoinType(const LPEJoinType&); - LPEJoinType& operator=(const LPEJoinType&); - - ScalarParam line_width; - EnumParam linecap_type; - EnumParam linejoin_type; - ScalarParam miter_limit; - BoolParam attempt_force_join; - bool was_initialized; -}; - -} //namespace LivePathEffect -} //namespace Inkscape - -#endif diff --git a/src/live_effects/parameter/originalpatharray.cpp b/src/live_effects/parameter/originalpatharray.cpp index ed47db28d..514c9e23e 100644 --- a/src/live_effects/parameter/originalpatharray.cpp +++ b/src/live_effects/parameter/originalpatharray.cpp @@ -18,6 +18,7 @@ #include #include #include +#include #include @@ -31,7 +32,6 @@ #include "uri.h" #include "display/curve.h" -#include #include <2geom/coord.h> #include <2geom/point.h> #include "sp-shape.h" @@ -97,8 +97,9 @@ OriginalPathArrayParam::OriginalPathArrayParam( const Glib::ustring& label, _toggle_renderer->signal_toggled().connect(sigc::mem_fun(*this, &OriginalPathArrayParam::on_reverse_toggled)); col->add_attribute(_toggle_renderer->property_active(), _model->_colReverse); - //quick little hack -- new versions of gtk did not give the item enough space - _scroller.property_height_request() = 120; + //quick little hack -- newer versions of gtk gave the item zero space allotment + _scroller.set_size_request(-1, 120); + _scroller.add(_tree); _scroller.set_policy( Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC ); //_scroller.set_shadow_type(Gtk::SHADOW_IN); diff --git a/src/live_effects/pathoutlineprovider.h b/src/live_effects/pathoutlineprovider.h deleted file mode 100755 index 8aa2e38ad..000000000 --- a/src/live_effects/pathoutlineprovider.h +++ /dev/null @@ -1,766 +0,0 @@ -#pragma once - -#include <2geom/path.h> -#include <2geom/circle.h> -#include <2geom/sbasis-to-bezier.h> -#include <2geom/shape.h> -#include <2geom/transforms.h> -#include <2geom/path-sink.h> - -#include -#include - -enum LineJoinType { - LINEJOIN_STRAIGHT, - LINEJOIN_ROUND, - LINEJOIN_POINTY, - LINEJOIN_REFLECTED, - LINEJOIN_EXTRAPOLATED -}; - -namespace Geom -{ - /** - * Refer to: Weisstein, Eric W. "Circle-Circle Intersection." - From MathWorld--A Wolfram Web Resource. - http://mathworld.wolfram.com/Circle-CircleIntersection.html - * - * @return 0 if no intersection - * @return 1 if one circle is contained in the other - * @return 2 if intersections are found (they are written to p0 and p1) - */ - static int circle_circle_intersection(Circle const &circle0, Circle const &circle1, - Point & p0, Point & p1) - { - Point X0 = circle0.center(); - double r0 = circle0.ray(); - Point X1 = circle1.center(); - double r1 = circle1.ray(); - - /* dx and dy are the vertical and horizontal distances between - * the circle centers. - */ - Point D = X1 - X0; - - /* Determine the straight-line distance between the centers. */ - double d = L2(D); - - /* Check for solvability. */ - if (d > (r0 + r1)) - { - /* no solution. circles do not intersect. */ - return 0; - } - if (d <= fabs(r0 - r1)) - { - /* no solution. one circle is contained in the other */ - return 1; - } - - /* 'point 2' is the point where the line through the circle - * intersection points crosses the line between the circle - * centers. - */ - - /* Determine the distance from point 0 to point 2. */ - double a = ((r0*r0) - (r1*r1) + (d*d)) / (2.0 * d) ; - - /* Determine the coordinates of point 2. */ - Point p2 = X0 + D * (a/d); - - /* Determine the distance from point 2 to either of the - * intersection points. - */ - double h = std::sqrt((r0*r0) - (a*a)); - - /* Now determine the offsets of the intersection points from - * point 2. - */ - Point r = (h/d)*rot90(D); - - /* Determine the absolute intersection points. */ - p0 = p2 + r; - p1 = p2 - r; - - return 2; - } - /** - * Find circle that touches inside of the curve, with radius matching the curvature, at time value \c t. - * Because this method internally uses unitTangentAt, t should be smaller than 1.0 (see unitTangentAt). - */ - static Circle touching_circle( D2 const &curve, double t, double tol=0.01 ) - { - D2 dM=derivative(curve); - if ( are_near(L2sq(dM(t)),0.) ) { - dM=derivative(dM); - } - if ( are_near(L2sq(dM(t)),0.) ) { // try second time - dM=derivative(dM); - } - Piecewise > unitv = unitVector(dM,tol); - Piecewise dMlength = dot(Piecewise >(dM),unitv); - Piecewise k = cross(derivative(unitv),unitv); - k = divide(k,dMlength,tol,3); - double curv = k(t); // note that this value is signed - - Geom::Point normal = unitTangentAt(curve, t).cw(); - double radius = 1/curv; - Geom::Point center = curve(t) + radius*normal; - return Geom::Circle(center, fabs(radius)); - } - - static std::vector split_at_cusps(const Geom::Path& in) - { - Geom::PathVector out = Geom::PathVector(); - Geom::Path temp = Geom::Path(); - - for (unsigned path_descr = 0; path_descr < in.size(); path_descr++) - { - temp = Geom::Path(); - temp.append(in[path_descr]); - out.push_back(temp); - } - - return out; - } - - static Geom::CubicBezier sbasis_to_cubicbezier(Geom::D2 const & sbasis_in) - { - std::vector temp; - sbasis_to_bezier(temp, sbasis_in, 4); - return Geom::CubicBezier( temp ); - } - - static boost::optional intersection_point( Geom::Point const & origin_a, Geom::Point const & vector_a, - Geom::Point const & origin_b, Geom::Point const & vector_b) - { - Geom::Coord denom = cross(vector_b, vector_a); - if (!Geom::are_near(denom,0.)){ - Geom::Coord t = (cross(origin_a,vector_b) + cross(vector_b,origin_b)) / denom; - return origin_a + t * vector_a; - } - return boost::none; - } -} - -namespace Outline -{ - - typedef Geom::D2 D2SB; - typedef Geom::Piecewise PWD2; - - static void extrapolate_curves(Geom::Path& path_builder, Geom::Curve* cbc1, Geom::Curve*cbc2, Geom::Point endPt, double miter_limit) -{ - Geom::Crossings cross = Geom::crossings(*cbc1, *cbc2); - if (cross.empty()) - { - Geom::Path pth; - pth.append(*cbc1); - - Geom::Point tang1 = Geom::unitTangentAt(pth.toPwSb()[0], 1); - - pth = Geom::Path(); - pth.append( *cbc2 ); - Geom::Point tang2 = Geom::unitTangentAt(pth.toPwSb()[0], 0); - - - Geom::Circle circle1 = Geom::touching_circle(Geom::reverse(cbc1->toSBasis()), 0.); - Geom::Circle circle2 = Geom::touching_circle(cbc2->toSBasis(), 0); - - Geom::Point points[2]; - int solutions = Geom::circle_circle_intersection(circle1, circle2, points[0], points[1]); - if (solutions == 2) - { - Geom::Point sol(0,0); - if ( dot(tang2,points[0]-endPt) > 0 ) - { - // points[0] is bad, choose points[1] - sol = points[1]; - } - else if ( dot(tang2,points[1]-endPt) > 0 ) { // points[0] could be good, now check points[1] - // points[1] is bad, choose points[0] - sol = points[0]; - } - else - { - // both points are good, choose nearest - sol = ( distanceSq(endPt, points[0]) < distanceSq(endPt, points[1]) ) ? - points[0] : points[1]; - } - Geom::EllipticalArc *arc0 = circle1.arc(cbc1->finalPoint(), 0.5*(cbc1->finalPoint()+sol), sol, true); - Geom::EllipticalArc *arc1 = circle2.arc(sol, 0.5*(sol+endPt), endPt, true); - - if (arc0) - { - path_builder.append (arc0->toSBasis()); - delete arc0; - arc0 = NULL; - } - - if (arc1) - { - path_builder.append (arc1->toSBasis()); - delete arc1; - arc1 = NULL; - } - } - else - { - path_builder.appendNew (endPt); - } - } - else - { - path_builder.appendNew (endPt); - } -} - static Geom::Path half_outline_extrp(const Geom::Path& path_in, double line_width, ButtType linecap_type, double miter_limit) - { - Geom::PathVector pv = split_at_cusps(path_in); - unsigned m; - Path path_outline = Path(); - Path path_tangent = Path(); - - Geom::Point initialPoint; - Geom::Point endPoint; - - Geom::Path path_builder = Geom::Path(); - Geom::PathVector * pathvec; - - //load the first portion in before the loop starts - { - path_outline = Path(); - path_outline.LoadPath(pv[0], Geom::Affine(), false, false); - path_outline.OutsideOutline(&path_tangent, line_width / 2, join_straight, linecap_type, 10); - //now half of first cusp has been loaded - - pathvec = path_tangent.MakePathVector(); - path_tangent = Path(); - - //instead of array accessing twice, dereferencing used for clarity - initialPoint = (*pathvec)[0].initialPoint(); - - path_builder.start(initialPoint); - path_builder.append( (*pathvec)[0] ); - - path_outline = Path(); - path_outline.LoadPath(pv[1], Geom::Affine(), false, false); - path_outline.OutsideOutline(&path_tangent, line_width / 2, join_straight, linecap_type, 10); - - delete pathvec; pathvec = NULL; - pathvec = path_tangent.MakePathVector(); - path_tangent = Path(); - - Geom::Curve *cbc1 = path_builder[path_builder.size() - 1].duplicate(); - Geom::Curve *cbc2 = (*pathvec)[0][0].duplicate(); - - extrapolate_curves(path_builder, cbc1, cbc2, (*pathvec)[0].initialPoint(), miter_limit ); - - path_builder.append( (*pathvec)[0] ); - - //always set pointers null after deleting - delete pathvec; pathvec = NULL; - delete cbc1; delete cbc2; cbc1 = cbc2 = NULL; - } - - for (m = 2; m < pv.size(); m++) - { - path_outline = Path(); - path_outline.LoadPath(pv[m], Geom::Affine(), false, false); - path_outline.OutsideOutline(&path_tangent, line_width / 2, join_straight, linecap_type, 10); - - delete pathvec; pathvec = NULL; - pathvec = path_tangent.MakePathVector(); - - Geom::Curve *cbc1 = path_builder[path_builder.size() - 1].duplicate(); - Geom::Curve *cbc2 = (*pathvec)[0][0].duplicate(); - - extrapolate_curves(path_builder, cbc1, cbc2, (*pathvec)[0].initialPoint(), miter_limit ); - path_builder.append( (*pathvec)[0] ); - - delete pathvec; pathvec = NULL; - delete cbc1; delete cbc2; cbc1 = cbc2 = NULL; - } - - return path_builder; - } - - //Create a reflected outline join. - //Note: it is generally recommended to let half_outline do this for you! - //path_builder: the path to append the curves to - //cbc1: the curve before the join - //cbc2: the curve after the join - //endPt: the point to end at - //miter_limit: the miter parameter - static void reflect_curves(Geom::Path& path_builder, Geom::Curve* cbc1, Geom::Curve* cbc2, Geom::Point endPt, double miter_limit) - { - //the most important work for the reflected join is done here - - //determine where we are in the path. If we're on the inside, ignore - //and just lineTo. On the outside, we'll do a little reflection magic :) - Geom::Crossings cross = Geom::crossings(*cbc1, *cbc2); - if (cross.empty()) - { - //probably on the outside of the corner - Geom::Path pth; - pth.append(*cbc1); - - Geom::Point tang1 = Geom::unitTangentAt(pth.toPwSb()[0], 1); - - //reflect curves along the bevel - D2SB newcurve1 = pth.toPwSb()[0] * - Geom::reflection ( -Geom::rot90(tang1) , - cbc1->finalPoint() ); - - Geom::CubicBezier bzr1 = sbasis_to_cubicbezier(Geom::reverse(newcurve1)); - - pth = Geom::Path(); - pth.append( *cbc2 ); - Geom::Point tang2 = Geom::unitTangentAt(pth.toPwSb()[0], 0); - - D2SB newcurve2 = pth.toPwSb()[0] * - Geom::reflection ( -Geom::rot90(tang2) , - cbc2->initialPoint() ); - Geom::CubicBezier bzr2 = sbasis_to_cubicbezier(Geom::reverse(newcurve2)); - - cross = Geom::crossings(bzr1, bzr2); - if ( cross.empty() ) - { - //std::cout << "Oops, no crossings!" << std::endl; - //curves didn't cross; default to miter - /*boost::optional p = intersection_point (cbc1->finalPoint(), tang1, - cbc2->initialPoint(), tang2); - if (p) - { - path_builder.appendNew (*p); - }*/ - //bevel - path_builder.appendNew( endPt ); - } - else - { - //join - std::pair sub1 = bzr1.subdivide(cross[0].ta); - std::pair sub2 = bzr2.subdivide(cross[0].tb); - - //@TODO joins have a strange tendency to cross themselves twice. Check this. - - //sections commented out are for general stability - path_builder.appendNew (sub1.first[1], sub1.first[2], /*sub1.first[3]*/ sub2.second[0] ); - path_builder.appendNew (sub2.second[1], sub2.second[2], /*sub2.second[3]*/ endPt ); - } - } - else // cross.empty() - { - //probably on the inside of the corner - path_builder.appendNew ( endPt ); - } - } - - /** @brief Converts a path to one half of an outline. - * path_in: The input path to use. (To create the other side use path_in.reverse() ) - * line_width: the line width to use (usually you want to divide this by 2) - * linecap_type: (not used here) the cap to apply. Passed to libvarot. - * miter_limit: the miter parameter - */ - static Geom::Path half_outline(const Geom::Path& path_in, double line_width, ButtType linecap_type, double miter_limit) - { - Geom::PathVector pv = split_at_cusps(path_in); - unsigned m; - Path path_outline = Path(); - Path path_tangent = Path(); - //needed for closing the path - Geom::Point initialPoint; - Geom::Point endPoint; - - //some issues prevented me from using a PathBuilder here - //it seems like PathBuilder::peek() gave me a null reference exception - //and I was unable to get a stack trace on Windows, so had to switch to Linux - //to see what the hell was wrong. :( - //I wasted five hours opening it in IDAPro, VS2012, and GDB Windows - - /*Program received signal SIGSEGV, Segmentation fault. - 0x00000000006539ac in get_curves (this=0x0) - at /usr/include/c++/4.6/bits/locale_facets.h:1077 - 1077 { return __c; } - */ - - Geom::Path path_builder = Geom::Path(); - Geom::PathVector * pathvec; - - //load the first portion in before the loop starts - { - path_outline = Path(); - path_outline.LoadPath(pv[0], Geom::Affine(), false, false); - path_outline.OutsideOutline(&path_tangent, line_width / 2, join_straight, linecap_type, 10); - //now half of first cusp has been loaded - - pathvec = path_tangent.MakePathVector(); - path_tangent = Path(); - - //instead of array accessing twice, dereferencing used for clarity - initialPoint = (*pathvec)[0].initialPoint(); - - path_builder.start(initialPoint); - path_builder.append( (*pathvec)[0] ); - - path_outline = Path(); - path_outline.LoadPath(pv[1], Geom::Affine(), false, false); - path_outline.OutsideOutline(&path_tangent, line_width / 2, join_straight, linecap_type, 10); - - delete pathvec; pathvec = NULL; - pathvec = path_tangent.MakePathVector(); - path_tangent = Path(); - - Geom::Curve *cbc1 = path_builder[path_builder.size() - 1].duplicate(); - Geom::Curve *cbc2 = (*pathvec)[0][0].duplicate(); - - reflect_curves(path_builder, cbc1, cbc2, (*pathvec)[0].initialPoint(), miter_limit ); - - path_builder.append( (*pathvec)[0] ); - - //always set pointers null after deleting - delete pathvec; pathvec = NULL; - delete cbc1; delete cbc2; cbc1 = cbc2 = NULL; - } - - for (m = 2; m < pv.size(); m++) - { - path_outline = Path(); - path_outline.LoadPath(pv[m], Geom::Affine(), false, false); - path_outline.OutsideOutline(&path_tangent, line_width / 2, join_straight, linecap_type, 10); - - delete pathvec; pathvec = NULL; - pathvec = path_tangent.MakePathVector(); - - Geom::Curve *cbc1 = path_builder[path_builder.size() - 1].duplicate(); - Geom::Curve *cbc2 = (*pathvec)[0][0].duplicate(); - - reflect_curves(path_builder, cbc1, cbc2, (*pathvec)[0].initialPoint(), miter_limit ); - path_builder.append( (*pathvec)[0] ); - - delete pathvec; pathvec = NULL; - delete cbc1; delete cbc2; cbc1 = cbc2 = NULL; - } - - return path_builder; - } - - static Geom::PathVector outlinePath(const Geom::PathVector& path_in, double line_width, JoinType join, ButtType butt, double miter_lim) - { - Path p = Path(); - Path outlinepath = Path(); - for (unsigned i = 0; i < path_in.size(); i++) - { - p.LoadPath(path_in[i], Geom::Affine(), false, ( (i==0) ? false : true)); - } - - Geom::PathVector path_out; - for (unsigned lmnop = 0; lmnop < path_in.size(); lmnop++) - { - if (path_in[lmnop].size() > 1) - { - Geom::Path p_init; - Geom::Path p_rev; - Geom::PathBuilder pb = Geom::PathBuilder(); - - if ( !path_in[lmnop].closed() ) - { - p_init = Outline::half_outline( path_in[lmnop], -line_width, butt, - miter_lim ); - p_rev = Outline::half_outline( path_in[lmnop].reverse(), -line_width, butt, - miter_lim ); - - pb.moveTo(p_init.initialPoint() ); - pb.append(p_init); - - //cap - if (butt == butt_straight) { - pb.lineTo(p_rev.initialPoint() ); - } else if (butt == butt_round) { - pb.arcTo((-line_width) / 2, (-line_width) / 2, 0., true, true, p_rev.initialPoint() ); - } else if (butt == butt_square) { - //don't know what to do - pb.lineTo(p_rev.initialPoint() ); - } else if (butt == butt_pointy) { - //don't know what to do - pb.lineTo(p_rev.initialPoint() ); - } - - pb.append(p_rev); - - if (butt == butt_straight) { - pb.lineTo(p_init.initialPoint() ); - } else if (butt == butt_round) { - pb.arcTo((-line_width) / 2, (-line_width) / 2, 0., true, true, p_init.initialPoint() ); - } else if (butt == butt_square) { - //don't know what to do - pb.lineTo(p_init.initialPoint() ); - } else if (butt == butt_pointy) { - //don't know what to do - //Geom::Point end_deriv = Geom::unitTangentAt( Geom::reverse(path_in[lmnop].toPwSb()[path_in[lmnop].size()]), 0); - //double radius = 0.5 * Geom::distance(path_in[lmnop].finalPoint(), p_rev.initialPoint()); - - pb.lineTo(p_init.initialPoint() ); - } - } - else - { - //final join - //refer to half_outline for documentation - Geom::Path p_almost = path_in[lmnop]; - p_almost.appendNew ( path_in[lmnop].initialPoint() ); - p_init = Outline::half_outline( p_almost, -line_width, butt, - miter_lim ); - p_rev = Outline::half_outline( p_almost.reverse(), -line_width, butt, - miter_lim ); - p.LoadPath(path_in[lmnop], Geom::Affine(), false, false); - - //this is a kludge, because I can't find how to make this work properly - bool lastIsLinear = ( (Geom::distance(path_in[lmnop].finalPoint(), - path_in[lmnop] [path_in[lmnop].size() - 1].finalPoint())) == - (path_in[lmnop] [path_in[lmnop].size()].length())); - - p_almost = p_init; - if (lastIsLinear) - { - p_almost.erase_last(); p_almost.erase_last(); - } - - //outside test - Geom::Curve* cbc1 = p_almost[p_almost.size() - 1].duplicate(); - Geom::Curve* cbc2 = p_almost[0].duplicate(); - - Geom::Crossings cross = Geom::crossings(*cbc1, *cbc2); - - if (cross.empty()) - { - //this is the outside path - - //reuse the old one - p_init = p_almost; - Outline::reflect_curves(p_init, cbc1, cbc2, p_almost.initialPoint(), miter_lim ); - pb.moveTo(p_init.initialPoint()); pb.append(p_init); - } - else - { - //inside, carry on :-) - pb.moveTo(p_almost.initialPoint()); pb.append(p_almost); - } - - p_almost = p_rev; - if (lastIsLinear) - { - p_almost.erase(p_almost.begin() ); - p_almost.erase(p_almost.begin() ); - } - - delete cbc1; delete cbc2; cbc1 = cbc2 = NULL; - - cbc1 = p_almost[p_almost.size() - 1].duplicate(); - cbc2 = p_almost[0].duplicate(); - - cross = Geom::crossings(*cbc1, *cbc2); - - if (cross.empty()) - { - //outside path - - p_init = p_almost; - reflect_curves(p_init, cbc1, cbc2, p_almost.initialPoint(), miter_lim ); - pb.moveTo(p_init.initialPoint()); pb.append(p_init); - } - else - { - //inside - pb.moveTo(p_almost.initialPoint()); pb.append(p_almost); - } - delete cbc1; delete cbc2; cbc1 = cbc2 = NULL; - } - //pb.closePath(); - pb.flush(); - Geom::PathVector pv_np = pb.peek(); - //hack - for (unsigned abcd = 0; abcd < pv_np.size(); abcd++) - { - path_out.push_back( pv_np[abcd] ); - } - } - else - { - p.LoadPath(path_in[lmnop], Geom::Affine(), false, false); - p.Outline(&outlinepath, line_width / 2, join, butt, miter_lim); - std::vector *pv_p = outlinepath.MakePathVector(); - //hack - path_out.push_back( (*pv_p)[0].reverse() ); - delete pv_p; - } - } - return path_out; - } - static Geom::PathVector outlinePath_extr(const Geom::PathVector& path_in, double line_width, LineJoinType join, ButtType butt, double miter_lim) - { - Path p = Path(); - Path outlinepath = Path(); - for (unsigned i = 0; i < path_in.size(); i++) - { - p.LoadPath(path_in[i], Geom::Affine(), false, ( (i==0) ? false : true)); - } - - Geom::PathVector path_out; - for (unsigned lmnop = 0; lmnop < path_in.size(); lmnop++) - { - if (path_in[lmnop].size() > 1) - { - Geom::Path p_init; - Geom::Path p_rev; - Geom::PathBuilder pb = Geom::PathBuilder(); - - if ( !path_in[lmnop].closed() ) - { - p_init = Outline::half_outline_extrp( path_in[lmnop], -line_width, butt, - miter_lim ); - p_rev = Outline::half_outline_extrp( path_in[lmnop].reverse(), -line_width, butt, - miter_lim ); - - pb.moveTo(p_init.initialPoint() ); - pb.append(p_init); - - //cap - if (butt == butt_straight) { - pb.lineTo(p_rev.initialPoint() ); - } else if (butt == butt_round) { - pb.arcTo((-line_width) / 2, (-line_width) / 2, 0., true, true, p_rev.initialPoint() ); - } else if (butt == butt_square) { - //don't know what to do - pb.lineTo(p_rev.initialPoint() ); - } else if (butt == butt_pointy) { - //don't know what to do - pb.lineTo(p_rev.initialPoint() ); - } - - pb.append(p_rev); - - if (butt == butt_straight) { - pb.lineTo(p_init.initialPoint() ); - } else if (butt == butt_round) { - pb.arcTo((-line_width) / 2, (-line_width) / 2, 0., true, true, p_init.initialPoint() ); - } else if (butt == butt_square) { - //don't know what to do - pb.lineTo(p_init.initialPoint() ); - } else if (butt == butt_pointy) { - //don't know what to do - //Geom::Point end_deriv = Geom::unitTangentAt( Geom::reverse(path_in[lmnop].toPwSb()[path_in[lmnop].size()]), 0); - //double radius = 0.5 * Geom::distance(path_in[lmnop].finalPoint(), p_rev.initialPoint()); - - pb.lineTo(p_init.initialPoint() ); - } - } - else - { - //final join - //refer to half_outline for documentation - Geom::Path p_almost = path_in[lmnop]; - p_almost.appendNew ( path_in[lmnop].initialPoint() ); - p_init = Outline::half_outline_extrp( p_almost, -line_width, butt, - miter_lim ); - p_rev = Outline::half_outline_extrp( p_almost.reverse(), -line_width, butt, - miter_lim ); - p.LoadPath(path_in[lmnop], Geom::Affine(), false, false); - - //this is a kludge, because I can't find how to make this work properly - bool lastIsLinear = ( (Geom::distance(path_in[lmnop].finalPoint(), - path_in[lmnop] [path_in[lmnop].size() - 1].finalPoint())) == - (path_in[lmnop] [path_in[lmnop].size()].length())); - - p_almost = p_init; - if (lastIsLinear) - { - p_almost.erase_last(); p_almost.erase_last(); - } - - //outside test - Geom::Curve* cbc1 = p_almost[p_almost.size() - 1].duplicate(); - Geom::Curve* cbc2 = p_almost[0].duplicate(); - - Geom::Crossings cross = Geom::crossings(*cbc1, *cbc2); - - if (cross.empty()) - { - //this is the outside path - - //reuse the old one - p_init = p_almost; - Outline::extrapolate_curves(p_init, cbc1, cbc2, p_almost.initialPoint(), miter_lim ); - pb.moveTo(p_init.initialPoint()); pb.append(p_init); - } - else - { - //inside, carry on :-) - pb.moveTo(p_almost.initialPoint()); pb.append(p_almost); - } - - p_almost = p_rev; - if (lastIsLinear) - { - p_almost.erase(p_almost.begin() ); - p_almost.erase(p_almost.begin() ); - } - - delete cbc1; delete cbc2; cbc1 = cbc2 = NULL; - - cbc1 = p_almost[p_almost.size() - 1].duplicate(); - cbc2 = p_almost[0].duplicate(); - - cross = Geom::crossings(*cbc1, *cbc2); - - if (cross.empty()) - { - //outside path - - p_init = p_almost; - extrapolate_curves(p_init, cbc1, cbc2, p_almost.initialPoint(), miter_lim ); - pb.moveTo(p_init.initialPoint()); pb.append(p_init); - } - else - { - //inside - pb.moveTo(p_almost.initialPoint()); pb.append(p_almost); - } - delete cbc1; delete cbc2; cbc1 = cbc2 = NULL; - } - //pb.closePath(); - pb.flush(); - Geom::PathVector pv_np = pb.peek(); - //hack - for (unsigned abcd = 0; abcd < pv_np.size(); abcd++) - { - path_out.push_back( pv_np[abcd] ); - } - } - else - { - p.LoadPath(path_in[lmnop], Geom::Affine(), false, false); - p.Outline(&outlinepath, line_width / 2, join_pointy, butt, miter_lim); - std::vector *pv_p = outlinepath.MakePathVector(); - //hack - path_out.push_back( (*pv_p)[0].reverse() ); - delete pv_p; - } - } - return path_out; - } - - -} // namespace Outline - -/* - 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:encoding=utf-8:textwidth=99 : diff --git a/src/path-chemistry.cpp b/src/path-chemistry.cpp index 5f478435d..456af3731 100644 --- a/src/path-chemistry.cpp +++ b/src/path-chemistry.cpp @@ -22,6 +22,7 @@ #include "xml/repr.h" #include "svg/svg.h" #include "display/curve.h" +#include "color.h" #include #include #include "sp-path.h" @@ -438,6 +439,10 @@ sp_item_list_to_curves(const GSList *items, GSList **selected, GSList **to_selec gchar *title = item->title(); // remember description gchar *desc = item->desc(); + // remember highlight color + guint32 highlight_color = 0; + if (item->isHighlightSet()) + highlight_color = item->highlight_color(); // It's going to resurrect, so we delete without notifying listeners. item->deleteObject(false); @@ -455,6 +460,9 @@ sp_item_list_to_curves(const GSList *items, GSList **selected, GSList **to_selec newObj->setDesc(desc); g_free(desc); } + if (highlight_color && newObj) { + SP_ITEM(newObj)->setHighlightColor( highlight_color ); + } // move to the saved position repr->setPosition(pos > 0 ? pos : 0); diff --git a/src/splivarot.cpp b/src/splivarot.cpp index 5c7b389ff..1eab73b62 100644 --- a/src/splivarot.cpp +++ b/src/splivarot.cpp @@ -1339,6 +1339,10 @@ sp_selected_path_outline(SPDesktop *desktop) gchar *title = item->title(); // remember description gchar *desc = item->desc(); + // remember highlight color + guint32 highlight_color = 0; + if (item->isHighlightSet()) + highlight_color = item->highlight_color(); if (res->descr_cmd.size() > 1) { // if there's 0 or 1 node left, drop this path altogether @@ -1381,6 +1385,9 @@ sp_selected_path_outline(SPDesktop *desktop) if (desc) { newitem->setDesc(desc); } + if (highlight_color && newitem) { + newitem->setHighlightColor( highlight_color ); + } SPShape *shape = SP_SHAPE(item); @@ -1456,13 +1463,23 @@ sp_selected_path_outline(SPDesktop *desktop) g_repr, xml_doc, doc ); } } + //bug 1290573: completely destroy the old object first to prevent + //an ID clash, which has issues on undo + curve->unref(); + selection->remove(item); + item->deleteObject(false); selection->add(g_repr); Inkscape::GC::release(g_repr); - - } else { + } else + { + //bug 1290573: completely destroy the old object first to prevent + //an ID clash, which has issues on undo + curve->unref(); + selection->remove(item); + item->deleteObject(false); // add the new repr to the parent parent->appendChild(repr); @@ -1481,6 +1498,9 @@ sp_selected_path_outline(SPDesktop *desktop) if (desc) { newitem->setDesc(desc); } + if (highlight_color && newitem) { + newitem->setHighlightColor( highlight_color ); + } selection->add(repr); @@ -1488,10 +1508,6 @@ sp_selected_path_outline(SPDesktop *desktop) Inkscape::GC::release(repr); - curve->unref(); - selection->remove(item); - item->deleteObject(false); - } if (title) { g_free(title); diff --git a/src/ui/dialog/color-item.cpp b/src/ui/dialog/color-item.cpp index a1951ec48..bab7e18e1 100644 --- a/src/ui/dialog/color-item.cpp +++ b/src/ui/dialog/color-item.cpp @@ -11,8 +11,18 @@ * Released under GNU GPL, read the file 'COPYING' for more information */ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + #include + +#if GLIBMM_DISABLE_DEPRECATED && HAVE_GLIBMM_THREADS_H +#include +#endif + #include +#include #include #include @@ -35,216 +45,766 @@ #include "xml/repr.h" #include "verbs.h" #include "widgets/gradient-vector.h" -#include "sp-paint-server.h" #include "color.h" // for SP_RGBA32_U_COMPOSE -#include namespace Inkscape { namespace UI { namespace Dialogs { +static std::vector mimeStrings; +static std::map mimeToInt; + -bool ColorItem::on_enter_notify_event(GdkEventCrossing* event) +#if ENABLE_MAGIC_COLORS +// TODO remove this soon: +extern std::vector possible; +#endif // ENABLE_MAGIC_COLORS + + +#if ENABLE_MAGIC_COLORS +static bool bruteForce( SPDocument* document, Inkscape::XML::Node* node, Glib::ustring const& match, int r, int g, int b ) { - SPDesktop *desktop = SP_ACTIVE_DESKTOP; - if ( desktop ) { - gchar* msg = g_strdup_printf(_("Color: %s; Click to set fill, Shift+click to set stroke"),def); - desktop->tipsMessageContext()->set(Inkscape::INFORMATION_MESSAGE, msg); - g_free(msg); + bool changed = false; + + if ( node ) { + gchar const * val = node->attribute("inkscape:x-fill-tag"); + if ( val && (match == val) ) { + SPObject *obj = document->getObjectByRepr( node ); + + gchar c[64] = {0}; + sp_svg_write_color( c, sizeof(c), SP_RGBA32_U_COMPOSE( r, g, b, 0xff ) ); + SPCSSAttr *css = sp_repr_css_attr_new(); + sp_repr_css_set_property( css, "fill", c ); + + sp_desktop_apply_css_recursive( obj, css, true ); + static_cast(obj)->updateRepr(); + + changed = true; + } + + val = node->attribute("inkscape:x-stroke-tag"); + if ( val && (match == val) ) { + SPObject *obj = document->getObjectByRepr( node ); + + gchar c[64] = {0}; + sp_svg_write_color( c, sizeof(c), SP_RGBA32_U_COMPOSE( r, g, b, 0xff ) ); + SPCSSAttr *css = sp_repr_css_attr_new(); + sp_repr_css_set_property( css, "stroke", c ); + + sp_desktop_apply_css_recursive( (SPItem*)obj, css, true ); + ((SPItem*)obj)->updateRepr(); + + changed = true; + } + + Inkscape::XML::Node* first = node->firstChild(); + changed |= bruteForce( document, first, match, r, g, b ); + + changed |= bruteForce( document, node->next(), match, r, g, b ); } - return Gtk::Widget::on_enter_notify_event(event); + + return changed; +} +#endif // ENABLE_MAGIC_COLORS + +static void handleClick( GtkWidget* /*widget*/, gpointer callback_data ) { + ColorItem* item = reinterpret_cast(callback_data); + if ( item ) { + item->buttonClicked(false); + } +} + +static void handleSecondaryClick( GtkWidget* /*widget*/, gint /*arg1*/, gpointer callback_data ) { + ColorItem* item = reinterpret_cast(callback_data); + if ( item ) { + item->buttonClicked(true); + } +} + +static gboolean handleEnterNotify( GtkWidget* /*widget*/, GdkEventCrossing* /*event*/, gpointer callback_data ) { + ColorItem* item = reinterpret_cast(callback_data); + if ( item ) { + SPDesktop *desktop = SP_ACTIVE_DESKTOP; + if ( desktop ) { + gchar* msg = g_strdup_printf(_("Color: %s; Click to set fill, Shift+click to set stroke"), + item->def.descr.c_str()); + desktop->tipsMessageContext()->set(Inkscape::INFORMATION_MESSAGE, msg); + g_free(msg); + } + } + return FALSE; +} + +static gboolean handleLeaveNotify( GtkWidget* /*widget*/, GdkEventCrossing* /*event*/, gpointer callback_data ) { + ColorItem* item = reinterpret_cast(callback_data); + if ( item ) { + SPDesktop *desktop = SP_ACTIVE_DESKTOP; + if ( desktop ) { + desktop->tipsMessageContext()->clear(); + } + } + return FALSE; } -bool ColorItem::on_leave_notify_event(GdkEventCrossing* event) +static void dieDieDie( GObject *obj, gpointer user_data ) { - SPDesktop *desktop = SP_ACTIVE_DESKTOP; - if ( desktop ) { - desktop->tipsMessageContext()->clear(); + g_message("die die die %p %p", obj, user_data ); +} + +static bool getBlock( std::string& dst, guchar ch, std::string const & str ) +{ + bool good = false; + std::string::size_type pos = str.find(ch); + if ( pos != std::string::npos ) + { + std::string::size_type pos2 = str.find( '(', pos ); + if ( pos2 != std::string::npos ) { + std::string::size_type endPos = str.find( ')', pos2 ); + if ( endPos != std::string::npos ) { + dst = str.substr( pos2 + 1, (endPos - pos2 - 1) ); + good = true; + } + } } - return Gtk::Widget::on_leave_notify_event(event); + return good; } -void ColorItem::selection_modified(Selection* selection, guint flags) +static bool popVal( guint64& numVal, std::string& str ) { - selection_changed(selection); + bool good = false; + std::string::size_type endPos = str.find(','); + if ( endPos == std::string::npos ) { + endPos = str.length(); + } + + if ( endPos != std::string::npos && endPos > 0 ) { + std::string xxx = str.substr( 0, endPos ); + const gchar* ptr = xxx.c_str(); + gchar* endPtr = 0; + numVal = g_ascii_strtoull( ptr, &endPtr, 10 ); + if ( (numVal == G_MAXUINT64) && (ERANGE == errno) ) { + // overflow + } else if ( (numVal == 0) && (endPtr == ptr) ) { + // failed conversion + } else { + good = true; + str.erase( 0, endPos + 1 ); + } + } + + return good; } -void ColorItem::selection_changed(Selection* selection) +// TODO resolve this more cleanly: +extern gboolean colorItemHandleButtonPress( GtkWidget* /*widget*/, GdkEventButton* event, gpointer user_data); + +static void colorItemDragBegin( GtkWidget */*widget*/, GdkDragContext* dc, gpointer data ) { - SPItem* item = selection->singleItem(); - SPPaintServer* grad; - if (item && - ( - (item->style->fill.isPaintserver() && - SP_IS_GRADIENT( (grad = item->style->getFillPaintServer()) ) - && SP_GRADIENT(grad)->getVector() == gradient) || - - (item->style->stroke.isPaintserver() && - SP_IS_GRADIENT( (grad = item->style->getStrokePaintServer()) ) && - SP_GRADIENT(grad)->getVector() == gradient) - ) - ) + ColorItem* item = reinterpret_cast(data); + if ( item ) { - if (!_isSelected) { - _isSelected = true; - queue_draw(); + using Inkscape::IO::Resource::get_path; + using Inkscape::IO::Resource::ICONS; + using Inkscape::IO::Resource::SYSTEM; + int width = 32; + int height = 24; + + if (item->def.getType() != ege::PaintDef::RGB){ + GError *error = NULL; + gsize bytesRead = 0; + gsize bytesWritten = 0; + gchar *localFilename = g_filename_from_utf8( get_path(SYSTEM, ICONS, "remove-color.png"), + -1, + &bytesRead, + &bytesWritten, + &error); + GdkPixbuf* pixbuf = gdk_pixbuf_new_from_file_at_scale(localFilename, width, height, FALSE, &error); + g_free(localFilename); + gtk_drag_set_icon_pixbuf( dc, pixbuf, 0, 0 ); + } else { + GdkPixbuf* pixbuf = 0; + if ( item->getGradient() ){ + cairo_surface_t *s = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, width, height); + cairo_pattern_t *gradient = sp_gradient_create_preview_pattern(item->getGradient(), width); + cairo_t *ct = cairo_create(s); + cairo_set_source(ct, gradient); + cairo_paint(ct); + cairo_destroy(ct); + cairo_pattern_destroy(gradient); + cairo_surface_flush(s); + + pixbuf = ink_pixbuf_create_from_cairo_surface(s); + } else { + Glib::RefPtr thumb = Gdk::Pixbuf::create( Gdk::COLORSPACE_RGB, false, 8, width, height ); + guint32 fillWith = (0xff000000 & (item->def.getR() << 24)) + | (0x00ff0000 & (item->def.getG() << 16)) + | (0x0000ff00 & (item->def.getB() << 8)); + thumb->fill( fillWith ); + pixbuf = thumb->gobj(); + g_object_ref(G_OBJECT(pixbuf)); + } + gtk_drag_set_icon_pixbuf( dc, pixbuf, 0, 0 ); } - } else if (_isSelected) { - _isSelected = false; - queue_draw(); } + +} + +//"drag-drop" +// gboolean dragDropColorData( GtkWidget *widget, +// GdkDragContext *drag_context, +// gint x, +// gint y, +// guint time, +// gpointer user_data) +// { +// // TODO finish + +// return TRUE; +// } + + +SwatchPage::SwatchPage() + : _prefWidth(0) +{ } -ColorItem::ColorItem( SPGradient* grad, const gchar* name, SPDesktop* desktop ) : - Glib::ObjectBase("coloritem"), - Gtk::Widget(), - def( name ), - gradient(grad), - _isSelected(false) +SwatchPage::~SwatchPage() { - set_has_window(true); - add_events(Gdk::BUTTON_PRESS_MASK); - add_events(Gdk::ENTER_NOTIFY_MASK | Gdk::LEAVE_NOTIFY_MASK); - sel_connection = desktop->selection->connectChanged(sigc::mem_fun(*this, &ColorItem::selection_changed)); - mod_connection = desktop->selection->connectModified(sigc::mem_fun(*this, &ColorItem::selection_modified)); - selection_changed(desktop->selection); } -void ColorItem::on_size_request(Gtk::Requisition* requisition) + +ColorItem::ColorItem(ege::PaintDef::ColorType type) : + def(type), + _isFill(false), + _isStroke(false), + _isLive(false), + _linkIsTone(false), + _linkPercent(0), + _linkGray(0), + _linkSrc(0), + _grad(0), + _pattern(0) { - requisition->height = 20; - requisition->width = 20; } -void ColorItem::on_size_allocate(Gtk::Allocation& allocation) +ColorItem::ColorItem( unsigned int r, unsigned int g, unsigned int b, Glib::ustring& name ) : + def( r, g, b, name ), + _isFill(false), + _isStroke(false), + _isLive(false), + _linkIsTone(false), + _linkPercent(0), + _linkGray(0), + _linkSrc(0), + _grad(0), + _pattern(0) { - set_allocation(allocation); - if (m_refGdkWindow) - { - m_refGdkWindow->move_resize( allocation.get_x(), allocation.get_y(), allocation.get_width(), allocation.get_height() ); +} + +ColorItem::~ColorItem() +{ + if (_pattern != NULL) { + cairo_pattern_destroy(_pattern); + } +} + +ColorItem::ColorItem(ColorItem const &other) : + Inkscape::UI::Previewable() +{ + if ( this != &other ) { + *this = other; + } +} + +ColorItem &ColorItem::operator=(ColorItem const &other) +{ + if ( this != &other ) { + def = other.def; + + // TODO - correct linkage + _linkSrc = other._linkSrc; + g_message("Erk!"); + } + return *this; +} + +void ColorItem::setState( bool fill, bool stroke ) +{ + if ( (_isFill != fill) || (_isStroke != stroke) ) { + _isFill = fill; + _isStroke = stroke; + + for ( std::vector::iterator it = _previews.begin(); it != _previews.end(); ++it ) { + Gtk::Widget* widget = *it; + if ( IS_EEK_PREVIEW(widget->gobj()) ) { + EekPreview * preview = EEK_PREVIEW(widget->gobj()); + + int val = eek_preview_get_linked( preview ); + val &= ~(PREVIEW_FILL | PREVIEW_STROKE); + if ( _isFill ) { + val |= PREVIEW_FILL; + } + if ( _isStroke ) { + val |= PREVIEW_STROKE; + } + eek_preview_set_linked( preview, static_cast(val) ); + } + } + } +} + +void ColorItem::setGradient(SPGradient *grad) +{ + if (_grad != grad) { + _grad = grad; + // TODO regen and push to listeners } + + setName( gr_prepare_label(_grad) ); } -void ColorItem::on_map() +void ColorItem::setName(const Glib::ustring name) { - Gtk::Widget::on_map(); + //def.descr = name; + + for ( std::vector::iterator it = _previews.begin(); it != _previews.end(); ++it ) { + Gtk::Widget* widget = *it; + if ( IS_EEK_PREVIEW(widget->gobj()) ) { + gtk_widget_set_tooltip_text(GTK_WIDGET(widget->gobj()), name.c_str()); + } + else if ( GTK_IS_LABEL(widget->gobj()) ) { + gtk_label_set_text(GTK_LABEL(widget->gobj()), name.c_str()); + } + } } -void ColorItem::on_unmap() +void ColorItem::setPattern(cairo_pattern_t *pattern) { - Gtk::Widget::on_unmap(); + if (pattern) { + cairo_pattern_reference(pattern); + } + if (_pattern) { + cairo_pattern_destroy(_pattern); + } + _pattern = pattern; + + _updatePreviews(); } -void ColorItem::on_realize() +void ColorItem::_dragGetColorData( GtkWidget */*widget*/, + GdkDragContext */*drag_context*/, + GtkSelectionData *data, + guint info, + guint /*time*/, + gpointer user_data) +{ + ColorItem* item = reinterpret_cast(user_data); + std::string key; + if ( info < mimeStrings.size() ) { + key = mimeStrings[info]; + } else { + g_warning("ERROR: unknown value (%d)", info); + } + + if ( !key.empty() ) { + char* tmp = 0; + int len = 0; + int format = 0; + item->def.getMIMEData(key, tmp, len, format); + if ( tmp ) { + GdkAtom dataAtom = gdk_atom_intern( key.c_str(), FALSE ); + gtk_selection_data_set( data, dataAtom, format, (guchar*)tmp, len ); + delete[] tmp; + } + } +} + +void ColorItem::_dropDataIn( GtkWidget */*widget*/, + GdkDragContext */*drag_context*/, + gint /*x*/, gint /*y*/, + GtkSelectionData */*data*/, + guint /*info*/, + guint /*event_time*/, + gpointer /*user_data*/) { - set_realized(); - ensure_style(); - - if(!m_refGdkWindow) - { - //Create the GdkWindow: - - GdkWindowAttr attributes; - memset(&attributes, 0, sizeof(attributes)); - - Gtk::Allocation allocation = get_allocation(); - - //Set initial position and size of the Gdk::Window: - attributes.x = allocation.get_x(); - attributes.y = allocation.get_y(); - attributes.width = allocation.get_width(); - attributes.height = allocation.get_height(); - - attributes.event_mask = get_events () | Gdk::EXPOSURE_MASK; - attributes.window_type = GDK_WINDOW_CHILD; - attributes.wclass = GDK_INPUT_OUTPUT; - - m_refGdkWindow = Gdk::Window::create(get_parent_window(), &attributes, - GDK_WA_X | GDK_WA_Y); - set_window(m_refGdkWindow); - - //Attach this widget's style to its Gdk::Window. - style_attach(); - - //make the widget receive expose events - m_refGdkWindow->set_user_data(gobj()); - } } -void ColorItem::on_unrealize() +void ColorItem::_colorDefChanged(void* data) { - m_refGdkWindow.reset(); - - Gtk::Widget::on_unrealize(); + ColorItem* item = reinterpret_cast(data); + if ( item ) { + item->_updatePreviews(); + } } -bool ColorItem::on_expose_event(GdkEventExpose* event) +void ColorItem::_updatePreviews() { - if(m_refGdkWindow) + for ( std::vector::iterator it = _previews.begin(); it != _previews.end(); ++it ) { + Gtk::Widget* widget = *it; + if ( IS_EEK_PREVIEW(widget->gobj()) ) { + EekPreview * preview = EEK_PREVIEW(widget->gobj()); + + _regenPreview(preview); + + widget->queue_draw(); + } + } + + for ( std::vector::iterator it = _listeners.begin(); it != _listeners.end(); ++it ) { + guint r = def.getR(); + guint g = def.getG(); + guint b = def.getB(); + + if ( (*it)->_linkIsTone ) { + r = ( ((*it)->_linkPercent * (*it)->_linkGray) + ((100 - (*it)->_linkPercent) * r) ) / 100; + g = ( ((*it)->_linkPercent * (*it)->_linkGray) + ((100 - (*it)->_linkPercent) * g) ) / 100; + b = ( ((*it)->_linkPercent * (*it)->_linkGray) + ((100 - (*it)->_linkPercent) * b) ) / 100; + } else { + r = ( ((*it)->_linkPercent * 255) + ((100 - (*it)->_linkPercent) * r) ) / 100; + g = ( ((*it)->_linkPercent * 255) + ((100 - (*it)->_linkPercent) * g) ) / 100; + b = ( ((*it)->_linkPercent * 255) + ((100 - (*it)->_linkPercent) * b) ) / 100; + } + + (*it)->def.setRGB( r, g, b ); + } + + +#if ENABLE_MAGIC_COLORS + // Look for objects using this color { - Cairo::RefPtr cr = m_refGdkWindow->create_cairo_context(); - if(event) + SPDesktop *desktop = SP_ACTIVE_DESKTOP; + if ( desktop ) { + SPDocument* document = sp_desktop_document( desktop ); + Inkscape::XML::Node *rroot = document->getReprRoot(); + if ( rroot ) { + + // Find where this thing came from + Glib::ustring paletteName; + bool found = false; + int index = 0; + for ( std::vector::iterator it2 = possible.begin(); it2 != possible.end() && !found; ++it2 ) { + SwatchPage* curr = *it2; + index = 0; + for ( boost::ptr_vector::iterator zz = curr->_colors.begin(); zz != curr->_colors.end(); ++zz ) { + if ( this == &*zz ) { + found = true; + paletteName = curr->_name; + break; + } else { + index++; + } + } + } + + if ( !paletteName.empty() ) { + gchar* str = g_strdup_printf("%d|", index); + paletteName.insert( 0, str ); + g_free(str); + str = 0; + + if ( bruteForce( document, rroot, paletteName, def.getR(), def.getG(), def.getB() ) ) { + SPDocumentUndo::done( document , SP_VERB_DIALOG_SWATCHES, + _("Change color definition")); + } + } + } + } + } +#endif // ENABLE_MAGIC_COLORS + +} + +void ColorItem::_regenPreview(EekPreview * preview) +{ + if ( def.getType() != ege::PaintDef::RGB ) { + using Inkscape::IO::Resource::get_path; + using Inkscape::IO::Resource::ICONS; + using Inkscape::IO::Resource::SYSTEM; + GError *error = NULL; + gsize bytesRead = 0; + gsize bytesWritten = 0; + gchar *localFilename = g_filename_from_utf8( get_path(SYSTEM, ICONS, "remove-color.png"), + -1, + &bytesRead, + &bytesWritten, + &error); + GdkPixbuf* pixbuf = gdk_pixbuf_new_from_file(localFilename, &error); + if (!pixbuf) { + g_warning("Null pixbuf for %p [%s]", localFilename, localFilename ); + } + g_free(localFilename); + + eek_preview_set_pixbuf( preview, pixbuf ); + } + else if ( !_pattern ){ + eek_preview_set_color( preview, + (def.getR() << 8) | def.getR(), + (def.getG() << 8) | def.getG(), + (def.getB() << 8) | def.getB() ); + } else { + // These correspond to PREVIEW_PIXBUF_WIDTH and VBLOCK from swatches.cpp + // TODO: the pattern to draw should be in the widget that draws the preview, + // so the preview can be scalable + int w = 128; + int h = 16; + + cairo_surface_t *s = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, w, h); + cairo_t *ct = cairo_create(s); + cairo_set_source(ct, _pattern); + cairo_paint(ct); + cairo_destroy(ct); + cairo_surface_flush(s); + + GdkPixbuf* pixbuf = ink_pixbuf_create_from_cairo_surface(s); + eek_preview_set_pixbuf( preview, pixbuf ); + } + + eek_preview_set_linked( preview, (LinkType)((_linkSrc ? PREVIEW_LINK_IN:0) + | (_listeners.empty() ? 0:PREVIEW_LINK_OUT) + | (_isLive ? PREVIEW_LINK_OTHER:0)) ); +} + +Gtk::Widget* ColorItem::getPreview(PreviewStyle style, ViewType view, ::PreviewSize size, guint ratio, guint border) +{ + Gtk::Widget* widget = 0; + if ( style == PREVIEW_STYLE_BLURB) { + Gtk::Label *lbl = new Gtk::Label(def.descr); + lbl->set_alignment(Gtk::ALIGN_START, Gtk::ALIGN_CENTER); + widget = lbl; + } else { + GtkWidget* eekWidget = eek_preview_new(); + EekPreview * preview = EEK_PREVIEW(eekWidget); + Gtk::Widget* newBlot = Glib::wrap(eekWidget); + _regenPreview(preview); + + eek_preview_set_details( preview, + (::ViewType)view, + (::PreviewSize)size, + ratio, + border ); + + def.addCallback( _colorDefChanged, this ); + eek_preview_set_focus_on_click(preview, FALSE); + newBlot->set_tooltip_text(def.descr); + + g_signal_connect( G_OBJECT(newBlot->gobj()), + "clicked", + G_CALLBACK(handleClick), + this); + + g_signal_connect( G_OBJECT(newBlot->gobj()), + "alt-clicked", + G_CALLBACK(handleSecondaryClick), + this); + + g_signal_connect( G_OBJECT(newBlot->gobj()), + "button-press-event", + G_CALLBACK(colorItemHandleButtonPress), + this); + { - // clip to the area that needs to be re-exposed so we don't draw any - // more than we need to. - cr->rectangle(event->area.x, event->area.y, event->area.width, event->area.height); - cr->clip(); + std::vector listing = def.getMIMETypes(); + int entryCount = listing.size(); + GtkTargetEntry* entries = new GtkTargetEntry[entryCount]; + GtkTargetEntry* curr = entries; + for ( std::vector::iterator it = listing.begin(); it != listing.end(); ++it ) { + curr->target = g_strdup(it->c_str()); + curr->flags = 0; + if ( mimeToInt.find(*it) == mimeToInt.end() ){ + // these next lines are order-dependent: + mimeToInt[*it] = mimeStrings.size(); + mimeStrings.push_back(*it); + } + curr->info = mimeToInt[curr->target]; + curr++; + } + gtk_drag_source_set( GTK_WIDGET(newBlot->gobj()), + GDK_BUTTON1_MASK, + entries, entryCount, + GdkDragAction(GDK_ACTION_MOVE | GDK_ACTION_COPY) ); + for ( int i = 0; i < entryCount; i++ ) { + g_free(entries[i].target); + } + delete[] entries; } - if (gradient) { - cairo_pattern_t *check = ink_cairo_pattern_create_checkerboard(); - - Cairo::RefPtr checkpat(new Cairo::Pattern(check)); - - cr->set_source(checkpat); - cr->paint(); - - cairo_pattern_t *g = sp_gradient_create_preview_pattern(gradient, get_allocation().get_width()); - Cairo::RefPtr gpat(new Cairo::Pattern(g)); - cr->set_source(gpat); - cr->paint(); - gpat.clear(); - cairo_pattern_destroy(g); - - checkpat.clear(); - - cairo_pattern_destroy(check); - - if (_isSelected) { - cr->set_source_rgb(0, 0, 0); - cr->set_line_width(3); - cr->move_to(0, get_allocation().get_height()); - cr->line_to(0,0); - cr->line_to(get_allocation().get_width(), 0); - cr->stroke(); - cr->move_to(get_allocation().get_width(), 0); - cr->set_source_rgb(1, 1, 1); - cr->line_to(get_allocation().get_width(), get_allocation().get_height()); - cr->line_to(0, get_allocation().get_height()); - //cr->rectangle(0, 0, get_allocation().get_width(), get_allocation().get_height()); - cr->stroke(); + g_signal_connect( G_OBJECT(newBlot->gobj()), + "drag-data-get", + G_CALLBACK(ColorItem::_dragGetColorData), + this); + + g_signal_connect( G_OBJECT(newBlot->gobj()), + "drag-begin", + G_CALLBACK(colorItemDragBegin), + this ); + + g_signal_connect( G_OBJECT(newBlot->gobj()), + "enter-notify-event", + G_CALLBACK(handleEnterNotify), + this); + + g_signal_connect( G_OBJECT(newBlot->gobj()), + "leave-notify-event", + G_CALLBACK(handleLeaveNotify), + this); + + g_signal_connect( G_OBJECT(newBlot->gobj()), + "destroy", + G_CALLBACK(dieDieDie), + this); + + + widget = newBlot; + } + + _previews.push_back( widget ); + + return widget; +} + +void ColorItem::buttonClicked(bool secondary) +{ + SPDesktop *desktop = SP_ACTIVE_DESKTOP; + if (desktop) { + char const * attrName = secondary ? "stroke" : "fill"; + + SPCSSAttr *css = sp_repr_css_attr_new(); + Glib::ustring descr; + switch (def.getType()) { + case ege::PaintDef::CLEAR: { + // TODO actually make this clear + sp_repr_css_set_property( css, attrName, "none" ); + descr = secondary? _("Remove stroke color") : _("Remove fill color"); + break; + } + case ege::PaintDef::NONE: { + sp_repr_css_set_property( css, attrName, "none" ); + descr = secondary? _("Set stroke color to none") : _("Set fill color to none"); + break; + } +//mark + case ege::PaintDef::RGB: { + Glib::ustring colorspec; + if ( _grad ){ + colorspec = "url(#"; + colorspec += _grad->getId(); + colorspec += ")"; + } else { + gchar c[64]; + guint32 rgba = (def.getR() << 24) | (def.getG() << 16) | (def.getB() << 8) | 0xff; + sp_svg_write_color(c, sizeof(c), rgba); + colorspec = c; + } +//end mark + sp_repr_css_set_property( css, attrName, colorspec.c_str() ); + descr = secondary? _("Set stroke color from swatch") : _("Set fill color from swatch"); + break; } - } else { - cr->set_source_rgb(1, 1, 1); - cr->paint(); - cr->set_source_rgb(1, 0, 0); - cr->set_line_width(3); - cr->move_to(0,0); - cr->line_to(get_allocation().get_width(), get_allocation().get_height()); - cr->move_to(get_allocation().get_width(), 0); - cr->line_to(0, get_allocation().get_height()); - cr->stroke(); } + sp_desktop_set_style(desktop, css); + sp_repr_css_attr_unref(css); + + DocumentUndo::done( sp_desktop_document(desktop), SP_VERB_DIALOG_SWATCHES, descr.c_str() ); } - return true; } -ColorItem::~ColorItem() +void ColorItem::_wireMagicColors( SwatchPage *colorSet ) +{ + if ( colorSet ) + { + for ( boost::ptr_vector::iterator it = colorSet->_colors.begin(); it != colorSet->_colors.end(); ++it ) + { + std::string::size_type pos = it->def.descr.find("*{"); + if ( pos != std::string::npos ) + { + std::string subby = it->def.descr.substr( pos + 2 ); + std::string::size_type endPos = subby.find("}*"); + if ( endPos != std::string::npos ) + { + subby.erase( endPos ); + //g_message("FOUND MAGIC at '%s'", (*it)->def.descr.c_str()); + //g_message(" '%s'", subby.c_str()); + + if ( subby.find('E') != std::string::npos ) + { + it->def.setEditable( true ); + } + + if ( subby.find('L') != std::string::npos ) + { + it->_isLive = true; + } + + std::string part; + // Tint. index + 1 more val. + if ( getBlock( part, 'T', subby ) ) { + guint64 colorIndex = 0; + if ( popVal( colorIndex, part ) ) { + guint64 percent = 0; + if ( popVal( percent, part ) ) { + it->_linkTint( colorSet->_colors[colorIndex], percent ); + } + } + } + + // Shade/tone. index + 1 or 2 more val. + if ( getBlock( part, 'S', subby ) ) { + guint64 colorIndex = 0; + if ( popVal( colorIndex, part ) ) { + guint64 percent = 0; + if ( popVal( percent, part ) ) { + guint64 grayLevel = 0; + if ( !popVal( grayLevel, part ) ) { + grayLevel = 0; + } + it->_linkTone( colorSet->_colors[colorIndex], percent, grayLevel ); + } + } + } + + } + } + } + } +} + + +void ColorItem::_linkTint( ColorItem& other, int percent ) +{ + if ( !_linkSrc ) + { + other._listeners.push_back(this); + _linkIsTone = false; + _linkPercent = percent; + if ( _linkPercent > 100 ) + _linkPercent = 100; + if ( _linkPercent < 0 ) + _linkPercent = 0; + _linkGray = 0; + _linkSrc = &other; + + ColorItem::_colorDefChanged(&other); + } +} + +void ColorItem::_linkTone( ColorItem& other, int percent, int grayLevel ) { - sel_connection.disconnect(); - mod_connection.disconnect(); + if ( !_linkSrc ) + { + other._listeners.push_back(this); + _linkIsTone = true; + _linkPercent = percent; + if ( _linkPercent > 100 ) + _linkPercent = 100; + if ( _linkPercent < 0 ) + _linkPercent = 0; + _linkGray = grayLevel; + _linkSrc = &other; + + ColorItem::_colorDefChanged(&other); + } } } // namespace Dialogs diff --git a/src/ui/dialog/color-item.h b/src/ui/dialog/color-item.h index 5d97d8803..3a0b33193 100644 --- a/src/ui/dialog/color-item.h +++ b/src/ui/dialog/color-item.h @@ -15,11 +15,7 @@ #include #include "widgets/ege-paint-def.h" -#include "widgets/eek-preview.h" -#include -#include -#include "desktop.h" -#include "selection.h" +#include "ui/previewable.h" class SPGradient; @@ -27,43 +23,89 @@ namespace Inkscape { namespace UI { namespace Dialogs { +class ColorItem; + +class SwatchPage +{ +public: + SwatchPage(); + ~SwatchPage(); + + Glib::ustring _name; + int _prefWidth; + boost::ptr_vector _colors; +}; + /** * The color swatch you see on screen as a clickable box. */ -class ColorItem : public Gtk::Widget +class ColorItem : public Inkscape::UI::Previewable { + friend void _loadPaletteFile( gchar const *filename ); public: - ColorItem( SPGradient * grad, const gchar* name, SPDesktop* desktop ); + ColorItem( ege::PaintDef::ColorType type ); + ColorItem( unsigned int r, unsigned int g, unsigned int b, + Glib::ustring& name ); virtual ~ColorItem(); - - SPGradient * getGradient() { return gradient; } - -protected: - - const gchar* def; - SPGradient * gradient; - virtual bool on_enter_notify_event(GdkEventCrossing* event); - virtual bool on_leave_notify_event(GdkEventCrossing* event); - - virtual void on_size_request(Gtk::Requisition* requisition); - virtual void on_size_allocate(Gtk::Allocation& allocation); - virtual void on_map(); - virtual void on_unmap(); - virtual void on_realize(); - virtual void on_unrealize(); - virtual bool on_expose_event(GdkEventExpose* event); - - Glib::RefPtr m_refGdkWindow; - - + ColorItem(ColorItem const &other); + virtual ColorItem &operator=(ColorItem const &other); + virtual Gtk::Widget* getPreview(PreviewStyle style, + ViewType view, + ::PreviewSize size, + guint ratio, + guint border); + void buttonClicked(bool secondary = false); + + void setGradient(SPGradient *grad); + SPGradient * getGradient() const { return _grad; } + void setPattern(cairo_pattern_t *pattern); + void setName(const Glib::ustring name); + + void setState( bool fill, bool stroke ); + bool isFill() { return _isFill; } + bool isStroke() { return _isStroke; } + + ege::PaintDef def; + private: - void selection_changed(Selection* selection); - void selection_modified(Selection* selection, guint flags); - sigc::connection sel_connection; - sigc::connection mod_connection; - bool _isSelected; + static void _dropDataIn( GtkWidget *widget, + GdkDragContext *drag_context, + gint x, gint y, + GtkSelectionData *data, + guint info, + guint event_time, + gpointer user_data); + + static void _dragGetColorData( GtkWidget *widget, + GdkDragContext *drag_context, + GtkSelectionData *data, + guint info, + guint time, + gpointer user_data); + + static void _wireMagicColors( SwatchPage *colorSet ); + static void _colorDefChanged(void* data); + + void _updatePreviews(); + void _regenPreview(EekPreview * preview); + + void _linkTint( ColorItem& other, int percent ); + void _linkTone( ColorItem& other, int percent, int grayLevel ); + + std::vector _previews; + + bool _isFill; + bool _isStroke; + bool _isLive; + bool _linkIsTone; + int _linkPercent; + int _linkGray; + ColorItem* _linkSrc; + SPGradient* _grad; + cairo_pattern_t *_pattern; + std::vector _listeners; }; } // namespace Dialogs diff --git a/src/ui/dialog/object-properties.cpp b/src/ui/dialog/object-properties.cpp index 82b2cf6b1..8f36cba43 100644 --- a/src/ui/dialog/object-properties.cpp +++ b/src/ui/dialog/object-properties.cpp @@ -467,6 +467,7 @@ void ObjectProperties::label_changed(void) blocked = true; /* Retrieve the label widget for the object's id */ + //bug 1290573: getId() crashes after undo (cannot create string from NULL ptr) gchar *id = g_strdup(EntryID.get_text().c_str()); g_strcanon (id, "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_.:", '_'); if (!strcmp (id, item->getId())) { diff --git a/src/ui/dialog/objects.cpp b/src/ui/dialog/objects.cpp index ebfa16f02..2095546fb 100644 --- a/src/ui/dialog/objects.cpp +++ b/src/ui/dialog/objects.cpp @@ -3,6 +3,7 @@ * * Authors: * Theodore Janeczko + * Tweaked by Liam P White for use in Inkscape * * Copyright (C) Theodore Janeczko 2012 * @@ -17,20 +18,31 @@ #include #include #include +#include #include #include "desktop.h" #include "desktop-style.h" +#include "dialogs/dialog-events.h" #include "document.h" #include "document-undo.h" +#include "filter-chemistry.h" +#include "filters/blend.h" +#include "filters/gaussian-blur.h" #include "helper/action.h" #include "inkscape.h" +#include "layer-manager.h" #include "preferences.h" +#include "selection.h" +#include "sp-clippath.h" +#include "sp-mask.h" #include "sp-item.h" #include "sp-object.h" +#include "sp-root.h" #include "sp-shape.h" -#include "svg/css-ostringstream.h" +#include "style.h" +#include "tools-switch.h" #include "ui/icon-names.h" #include "ui/widget/imagetoggler.h" #include "ui/widget/layertypeicon.h" @@ -38,29 +50,16 @@ #include "ui/widget/clipmaskicon.h" #include "ui/widget/highlight-picker.h" #include "ui/tools/node-tool.h" +#include "ui/tools/tool-base.h" #include "verbs.h" +#include "widgets/sp-color-notebook.h" #include "widgets/icon.h" #include "xml/node.h" #include "xml/node-observer.h" #include "xml/repr.h" -#include "sp-root.h" -//#include "event-context.h" -#include "selection.h" -#include "dialogs/dialog-events.h" -#include "widgets/sp-color-notebook.h" -#include "style.h" -#include "filter-chemistry.h" -#include "filters/blend.h" -#include "filters/gaussian-blur.h" -#include "sp-clippath.h" -#include "sp-mask.h" -#include "layer-manager.h" -#include "tools-switch.h" //#define DUMP_LAYERS 1 -guint get_group0_keyval(GdkEventKey *event); - namespace Inkscape { namespace UI { namespace Dialog { @@ -82,7 +81,7 @@ enum { COL_VISIBLE = 1, COL_LOCKED, COL_TYPE, - COL_INSERTORDER, +// COL_INSERTORDER, COL_CLIPMASK, COL_HIGHLIGHT }; @@ -106,8 +105,8 @@ enum { BUTTON_LOCK_ALL, BUTTON_UNLOCK_ALL, BUTTON_SETCLIP, - BUTTON_CLIPGROUP, - BUTTON_SETINVCLIP, +// BUTTON_CLIPGROUP, +// BUTTON_SETINVCLIP, BUTTON_UNSETCLIP, BUTTON_SETMASK, BUTTON_UNSETMASK, @@ -214,7 +213,7 @@ public: add(_colType); add(_colHighlight); add(_colClipMask); - add(_colInsertOrder); + //add(_colInsertOrder); } virtual ~ModelColumns() {} @@ -225,7 +224,7 @@ public: Gtk::TreeModelColumn _colType; Gtk::TreeModelColumn _colHighlight; Gtk::TreeModelColumn _colClipMask; - Gtk::TreeModelColumn _colInsertOrder; + //Gtk::TreeModelColumn _colInsertOrder; }; /** @@ -352,13 +351,19 @@ void ObjectsPanel::_addObject(SPObject* obj, Gtk::TreeModel::Row* parentRow) Gtk::TreeModel::iterator iter = parentRow ? _store->prepend(parentRow->children()) : _store->prepend(); Gtk::TreeModel::Row row = *iter; row[_model->_colObject] = item; - row[_model->_colLabel] = item->label() ? item->label() : item->getId(); + //this seems to crash on convert stroke to path then undo (probably no ID?) + try { + row[_model->_colLabel] = item->label() ? item->label() : item->getId(); + } catch (...) { + row[_model->_colLabel] = Glib::ustring("getId_failure"); + g_critical("item->getId() failed, using \"getId_failure\""); + } row[_model->_colVisible] = !item->isHidden(); row[_model->_colLocked] = !item->isSensitive(); row[_model->_colType] = group ? (group->layerMode() == SPGroup::LAYER ? 2 : 1) : 0; row[_model->_colHighlight] = item->isHighlightSet() ? item->highlight_color() : item->highlight_color() & 0xffffff00; row[_model->_colClipMask] = item->clip_ref && item->clip_ref->getObject() ? 1 : (item->mask_ref && item->mask_ref->getObject() ? 2 : 0); - row[_model->_colInsertOrder] = group ? (group->insertBottom() ? 2 : 1) : 0; + //row[_model->_colInsertOrder] = group ? (group->insertBottom() ? 2 : 1) : 0; //If our parent object is a group and it's expanded, expand the tree if (SP_IS_GROUP(obj) && SP_GROUP(obj)->expanded()) @@ -388,7 +393,10 @@ void ObjectsPanel::_addObject(SPObject* obj, Gtk::TreeModel::Row* parentRow) */ void ObjectsPanel::_updateObject( SPObject *obj, bool recurse ) { //Find the object in the tree store and update it + + //mark _store->foreach_iter( sigc::bind(sigc::mem_fun(*this, &ObjectsPanel::_checkForUpdated), obj) ); + //end mark if (recurse) { for (SPObject * iter = obj->children; iter != NULL; iter = iter->next) @@ -419,7 +427,7 @@ bool ObjectsPanel::_checkForUpdated(const Gtk::TreeIter& iter, SPObject* obj) row[_model->_colType] = group ? (group->layerMode() == SPGroup::LAYER ? 2 : 1) : 0; row[_model->_colHighlight] = item ? (item->isHighlightSet() ? item->highlight_color() : item->highlight_color() & 0xffffff00) : 0; row[_model->_colClipMask] = item ? (item->clip_ref && item->clip_ref->getObject() ? 1 : (item->mask_ref && item->mask_ref->getObject() ? 2 : 0)) : 0; - row[_model->_colInsertOrder] = group ? (group->insertBottom() ? 2 : 1) : 0; + //row[_model->_colInsertOrder] = group ? (group->insertBottom() ? 2 : 1) : 0; return true; } @@ -685,7 +693,9 @@ void ObjectsPanel::_setLockedIter( const Gtk::TreeModel::iterator& iter, const b bool ObjectsPanel::_handleKeyEvent(GdkEventKey *event) { - switch (get_group0_keyval(event)) { + bool empty = _desktop->selection->isEmpty(); + + switch (Inkscape::UI::Tools::get_group0_keyval(event)) { case GDK_KEY_Return: case GDK_KEY_KP_Enter: case GDK_KEY_F2: @@ -702,68 +712,33 @@ bool ObjectsPanel::_handleKeyEvent(GdkEventKey *event) } break; case GDK_Home: - { //Move item(s) to top of containing group/layer - if (_desktop->selection->isEmpty()) - { - _fireAction( SP_VERB_LAYER_TO_TOP ); - } - else - { - _fireAction( SP_VERB_SELECTION_TO_FRONT ); - } - return true; - } + _fireAction( empty ? SP_VERB_LAYER_TO_TOP : SP_VERB_SELECTION_TO_FRONT ); + break; case GDK_End: - { //Move item(s) to bottom of containing group/layer - if (_desktop->selection->isEmpty()) - { - _fireAction( SP_VERB_LAYER_TO_BOTTOM ); - } - else - { - _fireAction( SP_VERB_SELECTION_TO_BACK ); - } - return true; - } + _fireAction( empty ? SP_VERB_LAYER_TO_BOTTOM : SP_VERB_SELECTION_TO_BACK ); + break; case GDK_KEY_Page_Up: { //Move item(s) up in containing group/layer - if (_desktop->selection->isEmpty()) - { - _fireAction( SP_VERB_LAYER_RAISE ); - } - else - { - if (event->state & GDK_SHIFT_MASK) { - _fireAction( SP_VERB_LAYER_MOVE_TO_NEXT ); - } else { - _fireAction( SP_VERB_SELECTION_RAISE ); - } - } - return true; + int ch = event->state & GDK_SHIFT_MASK ? SP_VERB_LAYER_MOVE_TO_NEXT : SP_VERB_SELECTION_RAISE; + _fireAction( empty ? SP_VERB_LAYER_RAISE : ch ); + break; } case GDK_KEY_Page_Down: { //Move item(s) down in containing group/layer - if (_desktop->selection->isEmpty()) - { - _fireAction( SP_VERB_LAYER_LOWER ); - } - else - { - if (event->state & GDK_SHIFT_MASK) { - _fireAction( SP_VERB_LAYER_MOVE_TO_PREV ); - } else { - _fireAction( SP_VERB_SELECTION_LOWER ); - } - } - return true; + int ch = event->state & GDK_SHIFT_MASK ? SP_VERB_LAYER_MOVE_TO_PREV : SP_VERB_SELECTION_LOWER; + _fireAction( empty ? SP_VERB_LAYER_LOWER : ch ); + break; } + //TODO: Handle Ctrl-A, etc. + default: + return false; } - return false; + return true; } /** @@ -809,7 +784,7 @@ bool ObjectsPanel::_handleButtonEvent(GdkEventButton* event) return true; } else if (col == _tree.get_column(COL_LOCKED-1) || col == _tree.get_column(COL_TYPE-1) || - col == _tree.get_column(COL_INSERTORDER - 1) || + //col == _tree.get_column(COL_INSERTORDER - 1) || col == _tree.get_column(COL_HIGHLIGHT-1)) { //Click on an icon column, eat this event to keep row selection return true; @@ -926,7 +901,7 @@ bool ObjectsPanel::_handleButtonEvent(GdkEventButton* event) DocumentUndo::done( _desktop->doc() , SP_VERB_DIALOG_OBJECTS, newValue? _("Layer to group") : _("Group to layer")); } - } else if (col == _tree.get_column(COL_INSERTORDER - 1)) { + } /*else if (col == _tree.get_column(COL_INSERTORDER - 1)) { if (SP_IS_GROUP(item)) { //Toggle the current item's insert order @@ -938,7 +913,7 @@ bool ObjectsPanel::_handleButtonEvent(GdkEventButton* event) DocumentUndo::done( _desktop->doc() , SP_VERB_DIALOG_OBJECTS, newValue? _("Set insert mode bottom") : _("Set insert mode top")); } - } else if (col == _tree.get_column(COL_HIGHLIGHT - 1)) { + }*/ else if (col == _tree.get_column(COL_HIGHLIGHT - 1)) { //Clear the highlight targets _highlight_target.clear(); if (_tree.get_selection()->is_selected(path)) @@ -1474,7 +1449,7 @@ void sp_highlight_picker_color_mod(SPColorSelector *csel, GObject * cp) target->setHighlightColor(rgba); target->updateRepr(SP_OBJECT_WRITE_NO_CHILDREN | SP_OBJECT_WRITE_EXT); } - DocumentUndo::done(SP_ACTIVE_DOCUMENT, SP_VERB_DIALOG_OBJECTS, _("Set object highlight color")); + DocumentUndo::maybeDone(SP_ACTIVE_DOCUMENT, "highlight", SP_VERB_DIALOG_OBJECTS, _("Set object highlight color")); } /** @@ -1689,13 +1664,13 @@ ObjectsPanel::ObjectsPanel() : col->add_attribute( typeRenderer->property_active(), _model->_colType ); } - //Insert order - Inkscape::UI::Widget::InsertOrderIcon * insertRenderer = Gtk::manage( new Inkscape::UI::Widget::InsertOrderIcon()); + //Insert order (LiamW: unused) + /*Inkscape::UI::Widget::InsertOrderIcon * insertRenderer = Gtk::manage( new Inkscape::UI::Widget::InsertOrderIcon()); int insertColNum = _tree.append_column("type", *insertRenderer) - 1; col = _tree.get_column(insertColNum); if ( col ) { col->add_attribute( insertRenderer->property_active(), _model->_colInsertOrder ); - } + }*/ //Clip/mask Inkscape::UI::Widget::ClipMaskIcon * clipRenderer = Gtk::manage( new Inkscape::UI::Widget::ClipMaskIcon()); @@ -1807,43 +1782,102 @@ ObjectsPanel::ObjectsPanel() : SPDesktop* targetDesktop = getDesktop(); //Set up the button row + + + //Add object/layer Gtk::Button* btn = Gtk::manage( new Gtk::Button() ); - _styleButton( *btn, GTK_STOCK_ADD, _("New Layer") ); + btn->set_tooltip_text(_("Add layer...")); +#if GTK_CHECK_VERSION(3,10,0) + btn->set_image_from_icon_name(INKSCAPE_ICON("list-add"), Gtk::ICON_SIZE_SMALL_TOOLBAR); +#else + Gtk::Image *image_add = Gtk::manage(new Gtk::Image()); + image_add->set_from_icon_name(INKSCAPE_ICON("list-add"), Gtk::ICON_SIZE_SMALL_TOOLBAR); + btn->set_image(*image_add); +#endif + btn->set_relief(Gtk::RELIEF_NONE); btn->signal_clicked().connect( sigc::bind( sigc::mem_fun(*this, &ObjectsPanel::_takeAction), (int)BUTTON_NEW) ); _buttonsSecondary.pack_start(*btn, Gtk::PACK_SHRINK); + + //Remove object btn = Gtk::manage( new Gtk::Button() ); - _styleButton( *btn, GTK_STOCK_REMOVE, _("Remove") ); + btn->set_tooltip_text(_("Remove object")); +#if GTK_CHECK_VERSION(3,10,0) + btn->set_image_from_icon_name(INKSCAPE_ICON("list-remove"), Gtk::ICON_SIZE_SMALL_TOOLBAR); +#else + Gtk::Image *image_remove = Gtk::manage(new Gtk::Image()); + image_remove->set_from_icon_name(INKSCAPE_ICON("list-remove"), Gtk::ICON_SIZE_SMALL_TOOLBAR); + btn->set_image(*image_remove); +#endif + btn->set_relief(Gtk::RELIEF_NONE); btn->signal_clicked().connect( sigc::bind( sigc::mem_fun(*this, &ObjectsPanel::_takeAction), (int)BUTTON_DELETE) ); _watching.push_back( btn ); _buttonsSecondary.pack_start(*btn, Gtk::PACK_SHRINK); + //Move to bottom btn = Gtk::manage( new Gtk::Button() ); - _styleButton( *btn, GTK_STOCK_GOTO_BOTTOM, _("Move To Bottom") ); + btn->set_tooltip_text(_("Move To Bottom")); +#if GTK_CHECK_VERSION(3,10,0) + btn->set_image_from_icon_name(INKSCAPE_ICON("go-bottom"), Gtk::ICON_SIZE_SMALL_TOOLBAR); +#else + image_remove = Gtk::manage(new Gtk::Image()); + image_remove->set_from_icon_name(INKSCAPE_ICON("go-bottom"), Gtk::ICON_SIZE_SMALL_TOOLBAR); + btn->set_image(*image_remove); +#endif + btn->set_relief(Gtk::RELIEF_NONE); btn->signal_clicked().connect( sigc::bind( sigc::mem_fun(*this, &ObjectsPanel::_takeAction), (int)BUTTON_BOTTOM) ); _watchingNonBottom.push_back( btn ); _buttonsPrimary.pack_end(*btn, Gtk::PACK_SHRINK); - + + //Move down btn = Gtk::manage( new Gtk::Button() ); - _styleButton( *btn, GTK_STOCK_GO_DOWN, _("Move Down") ); + btn->set_tooltip_text(_("Move Down")); +#if GTK_CHECK_VERSION(3,10,0) + btn->set_image_from_icon_name(INKSCAPE_ICON("go-down"), Gtk::ICON_SIZE_SMALL_TOOLBAR); +#else + image_remove = Gtk::manage(new Gtk::Image()); + image_remove->set_from_icon_name(INKSCAPE_ICON("go-down"), Gtk::ICON_SIZE_SMALL_TOOLBAR); + btn->set_image(*image_remove); +#endif + btn->set_relief(Gtk::RELIEF_NONE); btn->signal_clicked().connect( sigc::bind( sigc::mem_fun(*this, &ObjectsPanel::_takeAction), (int)BUTTON_DOWN) ); _watchingNonBottom.push_back( btn ); _buttonsPrimary.pack_end(*btn, Gtk::PACK_SHRINK); + //Move up btn = Gtk::manage( new Gtk::Button() ); - _styleButton( *btn, GTK_STOCK_GO_UP, _("Move Up") ); + btn->set_tooltip_text(_("Move Up")); +#if GTK_CHECK_VERSION(3,10,0) + btn->set_image_from_icon_name(INKSCAPE_ICON("go-up"), Gtk::ICON_SIZE_SMALL_TOOLBAR); +#else + image_remove = Gtk::manage(new Gtk::Image()); + image_remove->set_from_icon_name(INKSCAPE_ICON("go-up"), Gtk::ICON_SIZE_SMALL_TOOLBAR); + btn->set_image(*image_remove); +#endif + btn->set_relief(Gtk::RELIEF_NONE); btn->signal_clicked().connect( sigc::bind( sigc::mem_fun(*this, &ObjectsPanel::_takeAction), (int)BUTTON_UP) ); _watchingNonTop.push_back( btn ); _buttonsPrimary.pack_end(*btn, Gtk::PACK_SHRINK); + //Move to top btn = Gtk::manage( new Gtk::Button() ); - _styleButton( *btn, GTK_STOCK_GOTO_TOP, _("Move To Top") ); + btn->set_tooltip_text(_("Move To Top")); +#if GTK_CHECK_VERSION(3,10,0) + btn->set_image_from_icon_name(INKSCAPE_ICON("go-top"), Gtk::ICON_SIZE_SMALL_TOOLBAR); +#else + image_remove = Gtk::manage(new Gtk::Image()); + image_remove->set_from_icon_name(INKSCAPE_ICON("go-top"), Gtk::ICON_SIZE_SMALL_TOOLBAR); + btn->set_image(*image_remove); +#endif + btn->set_relief(Gtk::RELIEF_NONE); btn->signal_clicked().connect( sigc::bind( sigc::mem_fun(*this, &ObjectsPanel::_takeAction), (int)BUTTON_TOP) ); _watchingNonTop.push_back( btn ); _buttonsPrimary.pack_end(*btn, Gtk::PACK_SHRINK); - btn = Gtk::manage( new Gtk::Button() ); - _styleButton( *btn, GTK_STOCK_UNINDENT, _("Collapse All") ); + //Collapse all + btn = Gtk::manage( new Gtk::Button(Gtk::Stock::UNINDENT) ); + btn->set_tooltip_text(_("Collapse All")); + btn->set_relief(Gtk::RELIEF_NONE); btn->signal_clicked().connect( sigc::bind( sigc::mem_fun(*this, &ObjectsPanel::_takeAction), (int)BUTTON_COLLAPSE_ALL) ); _watchingNonBottom.push_back( btn ); _buttonsPrimary.pack_end(*btn, Gtk::PACK_SHRINK); @@ -2042,15 +2076,6 @@ void ObjectsPanel::setDesktop( SPDesktop* desktop ) //should be okay to put these here because they are never referenced anywhere else using namespace Inkscape::UI::Tools; -guint get_group0_keyval(GdkEventKey *event) { - guint keyval = 0; - gdk_keymap_translate_keyboard_state(gdk_keymap_get_for_display( - gdk_display_get_default()), event->hardware_keycode, - (GdkModifierType) event->state, 0 /*event->key.group*/, &keyval, - NULL, NULL, NULL); - return keyval; -} - void SPItem::setHighlightColor(guint32 const color) { g_free(_highlightColor); @@ -2065,7 +2090,7 @@ void SPItem::setHighlightColor(guint32 const color) NodeTool *tool = 0; if (SP_ACTIVE_DESKTOP ) { - ToolBase *ec = SP_ACTIVE_DESKTOP->event_context; + Inkscape::UI::Tools::ToolBase *ec = SP_ACTIVE_DESKTOP->event_context; if (INK_IS_NODE_TOOL(ec)) { tool = static_cast(ec); tools_switch(tool->desktop, TOOLS_NODES); @@ -2079,7 +2104,7 @@ void SPItem::unsetHighlightColor() _highlightColor = NULL; NodeTool *tool = 0; if (SP_ACTIVE_DESKTOP ) { - ToolBase *ec = SP_ACTIVE_DESKTOP->event_context; + Inkscape::UI::Tools::ToolBase *ec = SP_ACTIVE_DESKTOP->event_context; if (INK_IS_NODE_TOOL(ec)) { tool = static_cast(ec); tools_switch(tool->desktop, TOOLS_NODES); diff --git a/src/ui/dialog/swatches.cpp b/src/ui/dialog/swatches.cpp index 2a8471b55..807618b4d 100644 --- a/src/ui/dialog/swatches.cpp +++ b/src/ui/dialog/swatches.cpp @@ -6,7 +6,6 @@ * Jon A. Cruz * John Bintz * Abhishek Sharma - * Theodore Janezcko * * Copyright (C) 2005 Jon A. Cruz * Copyright (C) 2008 John Bintz @@ -21,7 +20,6 @@ #include "swatches.h" #include -#include #include #include @@ -47,6 +45,7 @@ #include "sp-gradient.h" #include "sp-gradient-vector.h" #include "style.h" +#include "ui/previewholder.h" #include "widgets/desktop-widget.h" #include "widgets/gradient-vector.h" #include "widgets/eek-preview.h" @@ -57,2305 +56,1130 @@ #include "verbs.h" #include "gradient-chemistry.h" #include "helper/action.h" -#include "xml/node-observer.h" -#include "xml/repr.h" -#include "sp-pattern.h" -#include "icon-size.h" -#include "widgets/icon.h" -#include "filedialog.h" -#include "sp-stop.h" -#include "svg/svg-color.h" -#include "sp-radial-gradient.h" -#include "color-rgba.h" -#include "ui/tools/tool-base.h" -#include "svg/css-ostringstream.h" -#include -#ifdef WIN32 -#include -#endif - -//lazy! -void sp_desktop_set_gradient(SPDesktop *desktop, SPGradient* gradient, bool fill); +#include "helper/action-context.h" namespace Inkscape { namespace UI { namespace Dialogs { -#define SWATCHES_FILE_NAME "swatches.svg" - -static char* trim( char* str ) { - char* ret = str; - while ( *str && (*str == ' ' || *str == '\t') ) { - str++; - } - ret = str; - while ( *str ) { - str++; - } - str--; - while ( str > ret && (( *str == ' ' || *str == '\t' ) || *str == '\r' || *str == '\n') ) { - *str-- = 0; - } - return ret; -} - -static void skipWhitespace( char*& str ) { - while ( *str == ' ' || *str == '\t' ) { - str++; - } -} - -static bool parseNum( char*& str, int& val ) { - val = 0; - while ( '0' <= *str && *str <= '9' ) { - val = val * 10 + (*str - '0'); - str++; - } - bool retval = !(*str == 0 || *str == ' ' || *str == '\t' || *str == '\r' || *str == '\n'); - return retval; -} - -static char * SwatchFile; -static SPDocument * SwatchDocument; -static unsigned int page_suffix; - -static void loadPalletFile() -{ - if (!SwatchDocument) { - SwatchFile=g_build_filename(INKSCAPE_PALETTESDIR, _("swatches.svg"), NULL); - SwatchDocument=SPDocument::createNewDoc (SwatchFile, TRUE); - if (!SwatchDocument) { - SwatchDocument = SPDocument::createNewDoc(NULL, TRUE, true); - sp_repr_save_file(SwatchDocument->getReprDoc(), SwatchFile, SP_SVG_NS_URI); - } - } -} - -static void addStop( Inkscape::XML::Node *parent, Glib::ustring const &color, gfloat opacity, gchar const *offset ) -{ -#ifdef SP_GR_VERBOSE - g_message("addStop(%p, %s, %d, %s)", parent, color.c_str(), opacity, offset); -#endif - Inkscape::XML::Node *stop = parent->document()->createElement("svg:stop"); - { - gchar *tmp = g_strdup_printf( "stop-color:%s;stop-opacity:%f;", color.c_str(), opacity < 0.0 ? 0.0 : (opacity > 1.0 ? 1.0 : opacity) ); - stop->setAttribute( "style", tmp ); - g_free(tmp); - } - - stop->setAttribute( "offset", offset ); - - parent->appendChild(stop); - Inkscape::GC::release(stop); -} - -static SPGroup* importGPL(SPDocument* doc, const gchar* full) -{ - SPGroup* ret = NULL; - if ( !Inkscape::IO::file_test( full, G_FILE_TEST_IS_DIR ) ) { - - /*Load the pallet file here*/ - char block[1024]; - FILE *f = Inkscape::IO::fopen_utf8name( full, "r" ); - if ( f ) { - char* result = fgets( block, sizeof(block), f ); - if ( result ) { - if ( strncmp( "GIMP Palette", block, 12 ) == 0 ) { - bool inHeader = true; - bool hasErr = false; - - Inkscape::XML::Node * page = doc->getReprDoc()->createElement("svg:g"); - gchar *id=NULL; - do { - g_free(id); - id = g_strdup_printf("page%d", page_suffix++); - } while (doc->getObjectById(id)); - - page->setAttribute("id", id); - - do { - result = fgets( block, sizeof(block), f ); - block[sizeof(block) - 1] = 0; - if ( result ) { - if ( block[0] == '#' ) { - // ignore comment - } else { - char *ptr = block; - // very simple check for header versus entry - while ( *ptr == ' ' || *ptr == '\t' ) { - ptr++; - } - if ( (*ptr == 0) || (*ptr == '\r') || (*ptr == '\n') ) { - // blank line. skip it. - } else if ( '0' <= *ptr && *ptr <= '9' ) { - // should be an entry link - inHeader = false; - ptr = block; - Glib::ustring name(""); - skipWhitespace(ptr); - if ( *ptr ) { - int r = 0; - int g = 0; - int b = 0; - hasErr = parseNum(ptr, r); - if ( !hasErr ) { - skipWhitespace(ptr); - hasErr = parseNum(ptr, g); - } - if ( !hasErr ) { - skipWhitespace(ptr); - hasErr = parseNum(ptr, b); - } - if ( !hasErr && *ptr ) { - char* n = trim(ptr); - if (n != NULL) { - name = g_dpgettext2(NULL, "Palette", n); - } - } - if ( !hasErr ) { - // Add the entry now - - Inkscape::XML::Node *grad = doc->getReprDoc()->createElement("svg:linearGradient"); - grad->setAttribute("inkscape:label", name.c_str()); - grad->setAttribute( "osb:paint", "solid", 0 ); - SPColor color((float)r / 255, (float)g / 255, (float)b / 255); - addStop(grad, color.toString(), 1, "0"); - page->appendChild(grad); - Inkscape::GC::release(grad); - } - } else { - hasErr = true; - } - } else { - if ( !inHeader ) { - // Hmmm... probably bad. Not quite the format we want? - hasErr = true; - } else { - char* sep = strchr(result, ':'); - if ( sep ) { - *sep = 0; - char* val = trim(sep + 1); - char* name = trim(result); - if ( *name ) { - if ( strcmp( "Name", name ) == 0 ) - { - page->setAttribute("inkscape:label", val); - } - } else { - // error - hasErr = true; - } - } else { - // error - hasErr = true; - } - } - } - } - } - } while ( result && !hasErr ); - if ( !hasErr ) { - doc->getDefs()->appendChild(page); - Inkscape::GC::release(page); - SPObject* obj = doc->getObjectByRepr(page); - if (SP_IS_GROUP(obj)) { - ret = SP_GROUP(obj); - } - #if ENABLE_MAGIC_COLORS - ColorItem::_wireMagicColors( onceMore ); - #endif // ENABLE_MAGIC_COLORS - } else { - delete page; - } - } - } - - fclose(f); - } - /* end loading the pallet file*/ - } - return ret; -} - -SwatchesPanel& SwatchesPanel::getInstance() -{ - return *new SwatchesPanel(); -} - -class SwatchesPanel::StopWatcher : public Inkscape::XML::NodeObserver { -public: - StopWatcher(SwatchesPanel* pnl, SPStop* obj) : - _pnl(pnl), - _obj(obj), - _repr(obj->getRepr()) - { - _repr->addObserver(*this); - } - - ~StopWatcher() { - _repr->removeObserver(*this); - } - - virtual void notifyChildAdded( Inkscape::XML::Node &/*node*/, Inkscape::XML::Node &/*child*/, Inkscape::XML::Node */*prev*/ ){} - virtual void notifyChildRemoved( Inkscape::XML::Node &/*node*/, Inkscape::XML::Node &/*child*/, Inkscape::XML::Node */*prev*/ ){} - virtual void notifyChildOrderChanged( Inkscape::XML::Node &/*node*/, Inkscape::XML::Node &/*child*/, Inkscape::XML::Node */*old_prev*/, Inkscape::XML::Node */*new_prev*/ ){} - virtual void notifyContentChanged( Inkscape::XML::Node &/*node*/, Util::ptr_shared /*old_content*/, Util::ptr_shared /*new_content*/ ) {} - - virtual void notifyAttributeChanged( Inkscape::XML::Node &/*node*/, GQuark name, Util::ptr_shared /*old_value*/, Util::ptr_shared /*new_value*/ ) { - if (_pnl && _obj) { - _pnl->_defsChanged( ); - } - } +#define VBLOCK 16 +#define PREVIEW_PIXBUF_WIDTH 128 - SwatchesPanel* _pnl; - SPStop* _obj; - Inkscape::XML::Node* _repr; -}; +void _loadPaletteFile( gchar const *filename, gboolean user=FALSE ); -class SwatchesPanel::GradientWatcher : public Inkscape::XML::NodeObserver { -public: - GradientWatcher(SwatchesPanel* pnl, SPGradient* obj) : - _pnl(pnl), - _obj(obj), - _repr(obj->getRepr()), - _labelAttr(g_quark_from_string("inkscape:label")), - _swatchAttr(g_quark_from_string("osb:paint")) - { - _repr->addObserver(*this); - } - - ~GradientWatcher() { - _repr->removeObserver(*this); - } - - virtual void notifyChildAdded( Inkscape::XML::Node &/*node*/, Inkscape::XML::Node &/*child*/, Inkscape::XML::Node */*prev*/ ) - { - if ( _pnl && _obj && _obj->isSwatch()) { - _pnl->_defsChanged( ); - } - } - virtual void notifyChildRemoved( Inkscape::XML::Node &/*node*/, Inkscape::XML::Node &/*child*/, Inkscape::XML::Node */*prev*/ ) - { - if ( _pnl && _obj && _obj->isSwatch() ) { - _pnl->_defsChanged( ); - } - } - virtual void notifyChildOrderChanged( Inkscape::XML::Node &/*node*/, Inkscape::XML::Node &/*child*/, Inkscape::XML::Node */*old_prev*/, Inkscape::XML::Node */*new_prev*/ ) - { - if ( _pnl && _obj && _obj->isSwatch() ) { - _pnl->_defsChanged( ); - } - } - virtual void notifyContentChanged( Inkscape::XML::Node &/*node*/, Util::ptr_shared /*old_content*/, Util::ptr_shared /*new_content*/ ) {} - virtual void notifyAttributeChanged( Inkscape::XML::Node &/*node*/, GQuark name, Util::ptr_shared /*old_value*/, Util::ptr_shared /*new_value*/ ) { - if (_pnl && _obj && ((_obj->isSwatch() && name == _labelAttr) || name == _swatchAttr)) { - _pnl->_defsChanged( ); - } - } - - SwatchesPanel* _pnl; - SPGradient* _obj; - Inkscape::XML::Node* _repr; - GQuark _labelAttr; - GQuark _swatchAttr; -}; - -class SwatchesPanel::SwatchWatcher : public Inkscape::XML::NodeObserver { -public: - SwatchWatcher(SwatchesPanel* pnl, SPObject* obj, bool builtIn) : - _pnl(pnl), - _obj(obj), - _builtIn(builtIn), - _repr(obj->getRepr()), - _labelAttr(g_quark_from_string("inkscape:label")), - _swatchAttr(g_quark_from_string("osb:paint")) - { - _repr->addObserver(*this); - } - - ~SwatchWatcher() { - _repr->removeObserver(*this); - } - - virtual void notifyChildAdded( Inkscape::XML::Node &/*node*/, Inkscape::XML::Node &child, Inkscape::XML::Node */*prev*/ ) - { - if ( _pnl && _obj) { - SPObject *childobj = _builtIn ? SwatchDocument->getObjectByRepr(&child) : (_pnl->_currentDocument ? _pnl->_currentDocument->getObjectByRepr(&child) : 0); - if (childobj && ((SP_IS_GRADIENT(childobj) && SP_GRADIENT(childobj)->hasStops()) || SP_IS_GROUP(childobj))) { - if (_builtIn) { - _pnl->_swatchesChanged( ); - } else { - _pnl->_defsChanged( ); - } - } - } - } - virtual void notifyChildRemoved( Inkscape::XML::Node &/*node*/, Inkscape::XML::Node &child, Inkscape::XML::Node */*prev*/ ) - { - if ( _pnl && _obj) { - if (_builtIn) { - _pnl->_swatchesChanged( ); - } else { - _pnl->_defsChanged( ); - } - } - } - virtual void notifyChildOrderChanged( Inkscape::XML::Node &/*node*/, Inkscape::XML::Node &child, Inkscape::XML::Node */*old_prev*/, Inkscape::XML::Node */*new_prev*/ ) - { - if ( _pnl && _obj) { - SPObject *childobj = _builtIn ? SwatchDocument->getObjectByRepr(&child) : (_pnl->_currentDocument ? _pnl->_currentDocument->getObjectByRepr(&child) : 0); - if (childobj && ((SP_IS_GRADIENT(childobj) && SP_GRADIENT(childobj)->hasStops()) || SP_IS_GROUP(childobj))) { - if (_builtIn) { - _pnl->_swatchesChanged( ); - } else { - _pnl->_defsChanged( ); - } - } - } - } - virtual void notifyContentChanged( Inkscape::XML::Node &/*node*/, Util::ptr_shared /*old_content*/, Util::ptr_shared /*new_content*/ ) {} - virtual void notifyAttributeChanged( Inkscape::XML::Node &/*node*/, GQuark name, Util::ptr_shared /*old_value*/, Util::ptr_shared /*new_value*/ ) { - if (_pnl && _obj && name == _labelAttr) { - if (_builtIn) { - _pnl->_swatchesChanged( ); - } else { - _pnl->_defsChanged( ); - } - } - } +std::list userSwatchPages; +std::list systemSwatchPages; +static std::map docPalettes; +static std::vector docTrackings; +static std::map docPerPanel; - SwatchesPanel* _pnl; - SPObject* _obj; - bool _builtIn; - Inkscape::XML::Node* _repr; - GQuark _labelAttr; - GQuark _swatchAttr; -}; -class SwatchesPanel::ModelColumns : public Gtk::TreeModel::ColumnRecord +class SwatchesPanelHook : public SwatchesPanel { public: - - ModelColumns() - { - add(_colObject); - add(_colLabel); - } - virtual ~ModelColumns() {} - - Gtk::TreeModelColumn _colObject; - Gtk::TreeModelColumn _colLabel; + static void convertGradient( GtkMenuItem *menuitem, gpointer userData ); + static void deleteGradient( GtkMenuItem *menuitem, gpointer userData ); }; -class SwatchesPanel::ModelColumnsDoc : public Gtk::TreeModel::ColumnRecord -{ -public: - - ModelColumnsDoc() - { - add(_colObject); - add(_colLabel); - add(_colPixbuf); +static void handleClick( GtkWidget* /*widget*/, gpointer callback_data ) { + ColorItem* item = reinterpret_cast(callback_data); + if ( item ) { + item->buttonClicked(false); } - virtual ~ModelColumnsDoc() {} - - Gtk::TreeModelColumn _colObject; - Gtk::TreeModelColumn _colLabel; - Gtk::TreeModelColumn > _colPixbuf; -}; +} -static void StripChildGroups(Inkscape::XML::Node * node, SPObject* addTo) -{ - for (Inkscape::XML::Node * it = node->firstChild(); it != NULL;) { - if (!strcmp(it->name(), "svg:g")) { - Inkscape::XML::Node * todel = it; - it = it->next(); - node->removeChild(todel); - } else { - it = it->next(); - } +static void handleSecondaryClick( GtkWidget* /*widget*/, gint /*arg1*/, gpointer callback_data ) { + ColorItem* item = reinterpret_cast(callback_data); + if ( item ) { + item->buttonClicked(true); } - addTo->appendChildRepr(node); } -static void BubbleChildGroups(Inkscape::XML::Node * node, SPObject* addTo) +static GtkWidget* popupMenu = 0; +static GtkWidget *popupSubHolder = 0; +static GtkWidget *popupSub = 0; +static std::vector popupItems; +static std::vector popupExtras; +static ColorItem* bounceTarget = 0; +static SwatchesPanel* bouncePanel = 0; + +static void redirClick( GtkMenuItem *menuitem, gpointer /*user_data*/ ) { - std::queue groups; - for (Inkscape::XML::Node * it = node->firstChild(); it != NULL; ) { - if (!strcmp(it->name(), "svg:g")) { - groups.push(it->duplicate(addTo->document->getReprDoc())); - Inkscape::XML::Node * todel = it; - it = it->next(); - node->removeChild(todel); - } else { - it = it->next(); - } - } - addTo->appendChildRepr(node); - while (!groups.empty()) { - Inkscape::XML::Node * it = groups.front(); - groups.pop(); - BubbleChildGroups(it, addTo); - Inkscape::GC::release(it); + if ( bounceTarget ) { + handleClick( GTK_WIDGET(menuitem), bounceTarget ); } } -void SwatchesPanel::_addSwatchButtonClicked(SPGroup* swatch, bool recurse) +static void redirSecondaryClick( GtkMenuItem *menuitem, gpointer /*user_data*/ ) { - if (_currentDocument) { - if (swatch && SP_IS_GROUP(swatch) ) { - Inkscape::XML::Node * copy = swatch->getRepr()->duplicate(_currentDocument->getReprDoc()); - if (recurse) { - BubbleChildGroups(copy, _currentDocument->getDefs()); - } else { - StripChildGroups(copy, _currentDocument->getDefs()); - } - Inkscape::GC::release(copy); - DocumentUndo::done(_currentDocument, SP_VERB_DIALOG_SWATCHES, _("Add swatches to document")); - } + if ( bounceTarget ) { + handleSecondaryClick( GTK_WIDGET(menuitem), 0, bounceTarget ); } } -void SwatchesPanel::_importButtonClicked(bool addToDoc, bool addToBI) +static void editGradientImpl( SPDesktop* desktop, SPGradient* gr ) { - if (addToDoc || addToBI) { - //# Get the current directory for finding files - static Glib::ustring open_path; - Inkscape::Preferences *prefs = Inkscape::Preferences::get(); - - if(open_path.empty()) - { - Glib::ustring attr = prefs->getString("/dialogs/open/path"); - if (!attr.empty()) open_path = attr; - } - - //# Test if the open_path directory exists - if (!Inkscape::IO::file_test(open_path.c_str(), - (GFileTest)(G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR))) - open_path = ""; - - #ifdef WIN32 - //# If no open path, default to our win32 documents folder - if (open_path.empty()) - { - // The path to the My Documents folder is read from the - // value "HKEY_CURRENT_USER\Software\Windows\CurrentVersion\Explorer\Shell Folders\Personal" - HKEY key = NULL; - if(RegOpenKeyExA(HKEY_CURRENT_USER, - "Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders", - 0, KEY_QUERY_VALUE, &key) == ERROR_SUCCESS) - { - WCHAR utf16path[_MAX_PATH]; - DWORD value_type; - DWORD data_size = sizeof(utf16path); - if(RegQueryValueExW(key, L"Personal", NULL, &value_type, - (BYTE*)utf16path, &data_size) == ERROR_SUCCESS) - { - g_assert(value_type == REG_SZ); - gchar *utf8path = g_utf16_to_utf8( - (const gunichar2*)utf16path, -1, NULL, NULL, NULL); - if(utf8path) - { - open_path = Glib::ustring(utf8path); - g_free(utf8path); + if ( gr ) { + bool shown = false; + if ( desktop && desktop->doc() ) { + Inkscape::Selection *selection = sp_desktop_selection( desktop ); + GSList const *items = selection->itemList(); + if (items) { + SPStyle *query = sp_style_new( desktop->doc() ); + int result = objects_query_fillstroke(const_cast(items), query, true); + if ( (result == QUERY_STYLE_MULTIPLE_SAME) || (result == QUERY_STYLE_SINGLE) ) { + // could be pertinent + if (query->fill.isPaintserver()) { + SPPaintServer* server = query->getFillPaintServer(); + if ( SP_IS_GRADIENT(server) ) { + SPGradient* grad = SP_GRADIENT(server); + if ( grad->isSwatch() && grad->getId() == gr->getId()) { + desktop->_dlg_mgr->showDialog("FillAndStroke"); + shown = true; + } + } } } + sp_style_unref(query); } } - #endif - - //# If no open path, default to our home directory - if (open_path.empty()) - { - open_path = g_get_home_dir(); - open_path.append(G_DIR_SEPARATOR_S); - } - Gtk::Window * parent = SP_ACTIVE_DESKTOP->getToplevel(); - //# Create a dialog - Inkscape::UI::Dialog::FileOpenDialog *openDialogInstance = - Inkscape::UI::Dialog::FileOpenDialog::create( - *parent, open_path, - Inkscape::UI::Dialog::SWATCH_TYPES, - _("Select file to open")); - - //# Show the dialog - bool const success = openDialogInstance->show(); - - //# Save the folder the user selected for later - open_path = openDialogInstance->getCurrentDirectory(); - - if (!success) - { - delete openDialogInstance; - return; - } - - //# User selected something. Get name and type - Glib::ustring fileName = openDialogInstance->getFilename(); - - //# We no longer need the file dialog object - delete it - delete openDialogInstance; - openDialogInstance = NULL; - - - if (!fileName.empty()) - { - Glib::ustring newFileName = Glib::filename_to_utf8(fileName); - - if ( newFileName.size() > 0) - fileName = newFileName; - else - g_warning( "ERROR CONVERTING OPEN FILENAME TO UTF-8" ); - - open_path = Glib::path_get_dirname (fileName); - open_path.append(G_DIR_SEPARATOR_S); - prefs->setString("/dialogs/open/path", open_path); - - SPDocument* importdoc = SPDocument::createNewDoc(fileName.c_str(), true); - Inkscape::XML::Node * page = NULL; - if (importdoc && importdoc->getDefs()) { - if (addToBI) { - page = SwatchDocument->getReprDoc()->createElement("svg:g"); - gchar *id=NULL; - do { - g_free(id); - id = g_strdup_printf("page%d", page_suffix++); - } while (SwatchDocument->getObjectById(id)); - - page->setAttribute("id", id); - gchar* name = g_path_get_basename(importdoc->getName()); - page->setAttribute("inkscape:label", name); - g_free(name); - } - - for (SPObject* it = importdoc->getDefs()->firstChild(); it != NULL; it = it->next) { - if (SP_IS_GROUP(it)) { - if (page) { - Inkscape::XML::Node * copy = it->getRepr()->duplicate(SwatchDocument->getReprDoc()); - page->appendChild(copy); - } - if (addToDoc) { - _addSwatchButtonClicked(SP_GROUP(it), false); - } - } - } - if (page) { - SwatchDocument->getDefs()->appendChildRepr(page); - sp_repr_save_file(SwatchDocument->getReprDoc(), SwatchFile, SP_SVG_NS_URI); - } - - importdoc->doUnref(); + if (!shown) { + Inkscape::Preferences *prefs = Inkscape::Preferences::get(); + if (prefs->getBool("/dialogs/gradienteditor/showlegacy", false)) { + // Legacy gradient dialog + GtkWidget *dialog = sp_gradient_vector_editor_new( gr ); + gtk_widget_show( dialog ); } else { - SPGroup* g = importGPL(addToBI ? SwatchDocument : _currentDocument, fileName.c_str()); - if (addToBI) { - if (addToDoc) { - _addSwatchButtonClicked(g, false); + // Invoke the gradient tool + Inkscape::Verb *verb = Inkscape::Verb::get( SP_VERB_CONTEXT_GRADIENT ); + if ( verb ) { + SPAction *action = verb->get_action( Inkscape::ActionContext( ( Inkscape::UI::View::View * ) SP_ACTIVE_DESKTOP ) ); + if ( action ) { + sp_action_perform( action, NULL ); } - sp_repr_save_file(SwatchDocument->getReprDoc(), SwatchFile, SP_SVG_NS_URI); - } else { - DocumentUndo::done(_currentDocument, SP_VERB_DIALOG_SWATCHES, _("Add swatches to document")); } } } } } -void SwatchesPanel::SetSelectedFill(SPGradient* swatch) +static void editGradient( GtkMenuItem */*menuitem*/, gpointer /*user_data*/ ) { - if (_currentDesktop && _currentDocument) { - SPItem* it = _currentDesktop->selection->singleItem(); - if (it) { - if (it->style->fill.isSet()) { - if (it->style->fill.isPaintserver()) { - SPPaintServer * server = it->style->getFillPaintServer(); - if (SP_IS_GRADIENT(server)) { - SPGradient *grad = SP_GRADIENT(server)->getVector(); - Inkscape::XML::Node * repr = grad->getRepr(); - Inkscape::XML::Node * drepr = swatch->getRepr(); - if (repr != drepr && grad != swatch) { - while (SPStop* olds = swatch->getFirstStop()) { - olds->deleteObject(); - } - for (SPStop* news = grad->getVector()->getFirstStop(); news != NULL; news = news->getNextStop()) { - Inkscape::XML::Node* clone = news->getRepr()->duplicate(_currentDocument->getReprDoc()); - swatch->appendChildRepr(clone); - Inkscape::GC::release(clone); - } - swatch->setSwatch(); - if (!_noLink.get_active()) { - sp_item_set_gradient(it, sp_gradient_ensure_vector_normalized(swatch), SP_IS_RADIALGRADIENT(swatch) ? SP_GRADIENT_TYPE_RADIAL : SP_GRADIENT_TYPE_LINEAR, Inkscape::FOR_FILL); - } - DocumentUndo::done(_currentDocument, SP_VERB_DIALOG_SWATCHES, _("Set Gradient Swatch")); - } - } - } else if (it->style->fill.isColor()) { - while (SPStop* olds = swatch->getFirstStop()) { - olds->deleteObject(); - } - addStop(swatch->getRepr(), it->style->fill.value.color.toString(), SP_SCALE24_TO_FLOAT(it->style->fill_opacity.value), "0"); - swatch->setSwatch(); - if (!_noLink.get_active()) { - SPGradient* normalized = sp_gradient_ensure_vector_normalized(swatch); - sp_item_set_gradient(it, normalized, SP_GRADIENT_TYPE_LINEAR, Inkscape::FOR_FILL); - } - DocumentUndo::done(_currentDocument, SP_VERB_DIALOG_SWATCHES, _("Set Color Swatch")); + if ( bounceTarget ) { + SwatchesPanel* swp = bouncePanel; + SPDesktop* desktop = swp ? swp->getDesktop() : 0; + SPDocument *doc = desktop ? desktop->doc() : 0; + if (doc) { + std::string targetName(bounceTarget->def.descr); + const GSList *gradients = doc->getResourceList("gradient"); + for (const GSList *item = gradients; item; item = item->next) { + SPGradient* grad = SP_GRADIENT(item->data); + if ( targetName == grad->getId() ) { + editGradientImpl( desktop, grad ); + break; } } } } } -void SwatchesPanel::SetSelectedStroke(SPGradient* swatch) +void SwatchesPanelHook::convertGradient( GtkMenuItem * /*menuitem*/, gpointer userData ) { - if (_currentDesktop && _currentDocument) { - SPItem* it = _currentDesktop->selection->singleItem(); - if (it) { - if (it->style->stroke.isSet()) { - if (it->style->stroke.isPaintserver()) { - SPPaintServer * server = it->style->getStrokePaintServer(); - if (SP_IS_GRADIENT(server)) { - SPGradient *grad = SP_GRADIENT(server)->getVector(); - Inkscape::XML::Node * repr = grad->getRepr(); - Inkscape::XML::Node * drepr = swatch->getRepr(); - if (repr != drepr && grad != swatch) { - while (SPStop* olds = swatch->getFirstStop()) { - olds->deleteObject(); - } - for (SPStop* news = grad->getVector()->getFirstStop(); news != NULL; news = news->getNextStop()) { - Inkscape::XML::Node* clone = news->getRepr()->duplicate(_currentDocument->getReprDoc()); - swatch->appendChildRepr(clone); - Inkscape::GC::release(clone); - } - swatch->setSwatch(); - if (!_noLink.get_active()) { - sp_item_set_gradient(it, sp_gradient_ensure_vector_normalized(swatch), SP_IS_RADIALGRADIENT(swatch) ? SP_GRADIENT_TYPE_RADIAL : SP_GRADIENT_TYPE_LINEAR, Inkscape::FOR_STROKE); - } - DocumentUndo::done(_currentDocument, SP_VERB_DIALOG_SWATCHES, _("Set Gradient Swatch")); - } - } - } else if (it->style->stroke.isColor()) { - while (SPStop* olds = swatch->getFirstStop()) { - olds->deleteObject(); - } - addStop(swatch->getRepr(), it->style->stroke.value.color.toString(), SP_SCALE24_TO_FLOAT(it->style->stroke_opacity.value), "0"); - swatch->setSwatch(); - if (!_noLink.get_active()) { - SPGradient* normalized = sp_gradient_ensure_vector_normalized(swatch); - sp_item_set_gradient(it, normalized, SP_GRADIENT_TYPE_LINEAR, Inkscape::FOR_STROKE); - } - DocumentUndo::done(_currentDocument, SP_VERB_DIALOG_SWATCHES, _("Set Color Swatch")); + if ( bounceTarget ) { + SwatchesPanel* swp = bouncePanel; + SPDesktop* desktop = swp ? swp->getDesktop() : 0; + SPDocument *doc = desktop ? desktop->doc() : 0; + gint index = GPOINTER_TO_INT(userData); + if ( doc && (index >= 0) && (static_cast(index) < popupItems.size()) ) { + Glib::ustring targetName = popupItems[index]; + + const GSList *gradients = doc->getResourceList("gradient"); + for (const GSList *item = gradients; item; item = item->next) { + SPGradient* grad = SP_GRADIENT(item->data); + if ( targetName == grad->getId() ) { + grad->setSwatch(); + DocumentUndo::done(doc, SP_VERB_CONTEXT_GRADIENT, + _("Add gradient stop")); + break; } } } } } -void SwatchesPanel::MoveSwatchDown(SPGradient* swatch) +void SwatchesPanelHook::deleteGradient( GtkMenuItem */*menuitem*/, gpointer /*userData*/ ) { - if (_currentDocument && swatch) { - SPObject* next = swatch->next; - while (next && (!SP_IS_GRADIENT(next) || !(SP_GRADIENT(next)->isSwatch()))) { - next = next->next; - } - if (next) { - Inkscape::XML::Node* repr = swatch->getRepr(); - repr->parent()->changeOrder(repr, next->getRepr()); - DocumentUndo::done(_currentDocument, SP_VERB_DIALOG_SWATCHES, _("Move Swatch Right")); - } + if ( bounceTarget ) { + SwatchesPanel* swp = bouncePanel; + SPDesktop* desktop = swp ? swp->getDesktop() : 0; + sp_gradient_unset_swatch(desktop, bounceTarget->def.descr); } } -void SwatchesPanel::MoveSwatchUp(SPGradient* swatch) +static SwatchesPanel* findContainingPanel( GtkWidget *widget ) { - if (_currentDocument && swatch) { - SPObject* g = NULL; - SPObject* next = swatch->parent->firstChild(); - while (next && next != swatch) { - if (SP_IS_GRADIENT(next) && SP_GRADIENT(next)->isSwatch()) { - g = next; - } - next = next->next; - } - if (g) { - g = g->getPrev(); - Inkscape::XML::Node* repr = swatch->getRepr(); - repr->parent()->changeOrder(repr, g ? g->getRepr() : NULL); - DocumentUndo::done(_currentDocument, SP_VERB_DIALOG_SWATCHES, _("Move Swatch Left")); - } - } -} + SwatchesPanel *swp = 0; -void SwatchesPanel::RemoveSwatch(SPGradient* swatch) -{ - if (_currentDocument) { - if (swatch->isReferenced()) { - Inkscape::XML::Node * repr = swatch->getRepr(); - repr->parent()->removeChild(repr); - _currentDocument->getDefs()->getRepr()->appendChild(repr); - SP_GRADIENT(_currentDocument->getObjectByRepr(repr))->setSwatch(false); - } else { - swatch->deleteObject(false); - } + std::map rawObjects; + for (std::map::iterator it = docPerPanel.begin(); it != docPerPanel.end(); ++it) { + rawObjects[GTK_WIDGET(it->first->gobj())] = it->first; } -} -void SwatchesPanel::_setSelectionSwatch(SPGradient* swatch, bool isStroke) -{ - if (_currentDocument) { - if (swatch) { - if (_noLink.get_active()) { - if (swatch->isSolid()) { - ColorRGBA rgba(swatch->getFirstStop()->getEffectiveColor().toRGBA32(swatch->getFirstStop()->opacity)); - sp_desktop_set_color(_currentDesktop, rgba, false, !isStroke); - } else { - SPCSSAttr *css = sp_repr_css_attr_new(); - sp_repr_css_set_property(css, isStroke ? "stroke-opacity" : "fill-opacity", "1.0"); - - Inkscape::XML::Node * clone = swatch->getRepr()->duplicate(_currentDocument->getReprDoc()); - _currentDocument->getDefs()->appendChildRepr(clone); - SPGradient* grad = SP_GRADIENT(_currentDocument->getObjectByRepr(clone)); - Inkscape::GC::release(clone); - grad->setSwatch(false); - SPGradient* normalized = sp_gradient_ensure_vector_normalized(grad); -// for (GSList const * it = _currentDesktop->selection->itemList(); it != NULL; it = it->next) { -// sp_desktop_apply_css_recursive(SP_ITEM(it->data), css, true); -// sp_item_set_gradient(SP_ITEM(it->data), normalized, SP_IS_RADIALGRADIENT(normalized) ? SP_GRADIENT_TYPE_RADIAL : SP_GRADIENT_TYPE_LINEAR, isStroke ? Inkscape::FOR_STROKE : Inkscape::FOR_FILL); -// } - sp_desktop_set_style(_currentDesktop, css); - sp_desktop_set_gradient(_currentDesktop, normalized, !isStroke); - sp_repr_css_attr_unref (css); - } - } else { - SPCSSAttr *css = sp_repr_css_attr_new(); - sp_repr_css_set_property(css, isStroke ? "stroke-opacity" : "fill-opacity", "1.0"); - - SPGradient* normalized = sp_gradient_ensure_vector_normalized(swatch); -// for (GSList const * it = _currentDesktop->selection->itemList(); it != NULL; it = it->next) { -// sp_desktop_apply_css_recursive(SP_ITEM(it->data), css, true); -// sp_item_set_gradient(SP_ITEM(it->data), normalized, SP_IS_RADIALGRADIENT(normalized) ? SP_GRADIENT_TYPE_RADIAL : SP_GRADIENT_TYPE_LINEAR, isStroke ? Inkscape::FOR_STROKE : Inkscape::FOR_FILL); -// } - sp_desktop_set_style(_currentDesktop, css); - sp_desktop_set_gradient(_currentDesktop, normalized, !isStroke); - sp_repr_css_attr_unref (css); - } - } else { - SPCSSAttr *css = sp_repr_css_attr_new (); - sp_repr_css_set_property (css, isStroke ? "stroke" : "fill", "none"); - sp_desktop_set_style(_currentDesktop, css); - } - if (isStroke) { - DocumentUndo::done(_currentDocument, SP_VERB_DIALOG_SWATCHES, _("Set item stroke swatch")); - } else { - DocumentUndo::done(_currentDocument, SP_VERB_DIALOG_SWATCHES, _("Set item fill swatch")); + for (GtkWidget* curr = widget; curr && !swp; curr = gtk_widget_get_parent(curr)) { + if (rawObjects.find(curr) != rawObjects.end()) { + swp = rawObjects[curr]; } } -} - -void SwatchesPanel::_swatchClicked(GdkEventButton* event, SPGradient* swatch) -{ - if (_currentDesktop) { - if (event->button == 3) { - Gtk::Menu * menu = Gtk::manage(new Gtk::Menu()); - - Gtk::MenuItem* mi; - - Glib::ustring us = Glib::ustring::compose("%1", swatch ? (swatch->label() ? swatch->label() : swatch->getId()) : _("[None]")); - mi = Gtk::manage(new Gtk::MenuItem(swatch ? (swatch->label() ? swatch->label() : swatch->getId()) : _("[None]"))); - Gtk::Label* namelbl = dynamic_cast(mi->get_child()); - if (namelbl) { - namelbl->set_markup(us); - } - mi->show(); - mi->set_sensitive(false); - menu->append(*mi); - - Gtk::SeparatorMenuItem* sep; - sep = manage(new Gtk::SeparatorMenuItem()); - sep->show(); - menu->append(*sep); - - mi = Gtk::manage(new Gtk::MenuItem(_("Set Fill"))); - mi->signal_activate().connect_notify(sigc::bind(sigc::mem_fun(*this, &SwatchesPanel::_setSelectionSwatch), swatch, false)); - mi->show(); - mi->set_sensitive(_currentDesktop && !_currentDesktop->selection->isEmpty()); - menu->append(*mi); - - mi = Gtk::manage(new Gtk::MenuItem(_("Set Stroke"))); - mi->signal_activate().connect_notify(sigc::bind(sigc::mem_fun(*this, &SwatchesPanel::_setSelectionSwatch), swatch, true)); - mi->show(); - mi->set_sensitive(_currentDesktop && !_currentDesktop->selection->isEmpty()); - menu->append(*mi); - - if (swatch) { - sep = manage(new Gtk::SeparatorMenuItem()); - sep->show(); - menu->append(*sep); - - mi = Gtk::manage(new Gtk::MenuItem(_("Set to Selected Fill"))); - mi->signal_activate().connect_notify(sigc::bind(sigc::mem_fun(*this, &SwatchesPanel::SetSelectedFill), swatch)); - mi->show(); - mi->set_sensitive(_currentDesktop && _currentDesktop->selection->singleItem()); - menu->append(*mi); - - mi = Gtk::manage(new Gtk::MenuItem(_("Set to Selected Stroke"))); - mi->signal_activate().connect_notify(sigc::bind(sigc::mem_fun(*this, &SwatchesPanel::SetSelectedStroke), swatch)); - mi->show(); - mi->set_sensitive(_currentDesktop && _currentDesktop->selection->singleItem()); - menu->append(*mi); - - - sep = manage(new Gtk::SeparatorMenuItem()); - sep->show(); - menu->append(*sep); - - mi = Gtk::manage(new Gtk::MenuItem(_("Move Left"))); - mi->signal_activate().connect_notify(sigc::bind(sigc::mem_fun(*this, &SwatchesPanel::MoveSwatchUp), swatch)); - mi->show(); - menu->append(*mi); - - mi = Gtk::manage(new Gtk::MenuItem(_("Move Right"))); - mi->signal_activate().connect_notify(sigc::bind(sigc::mem_fun(*this, &SwatchesPanel::MoveSwatchDown), swatch)); - mi->show(); - menu->append(*mi); - - sep = manage(new Gtk::SeparatorMenuItem()); - sep->show(); - menu->append(*sep); - - mi = Gtk::manage(new Gtk::MenuItem(_("Remove"))); - mi->signal_activate().connect_notify(sigc::bind(sigc::mem_fun(*this, &SwatchesPanel::RemoveSwatch), swatch)); - mi->show(); - menu->append(*mi); - } - menu->popup(event->button, event->time); - } else if (!_currentDesktop->selection->isEmpty()) { - _setSelectionSwatch(swatch, event->state & GDK_SHIFT_MASK); - } - } + return swp; } -void SwatchesPanel::MoveDown(SPGroup* page) +static void removeit( GtkWidget *widget, gpointer data ) { - if (_currentDocument && page) { - SPObject* next = page->next; - while (next && !SP_IS_GROUP(next)) { - next = next->next; - } - if (next) { - Inkscape::XML::Node* repr = page->getRepr(); - repr->parent()->changeOrder(repr, next->getRepr()); - DocumentUndo::done(_currentDocument, SP_VERB_DIALOG_SWATCHES, _("Move Swatch Down")); - } - } + gtk_container_remove( GTK_CONTAINER(data), widget ); } -void SwatchesPanel::MoveUp(SPGroup* page) -{ - if (_currentDocument && page) { - SPObject* g = NULL; - SPObject* next = page->parent->firstChild(); - while (next && next != page) { - if (SP_IS_GROUP(next)) { - g = next; - } - next = next->next; - } - if (g) { - g = g->getPrev(); - Inkscape::XML::Node* repr = page->getRepr(); - repr->parent()->changeOrder(repr, g ? g->getRepr() : NULL); - DocumentUndo::done(_currentDocument, SP_VERB_DIALOG_SWATCHES, _("Move Swatch Up")); - } - } -} +/* extern'ed from colot-item.cpp */ +gboolean colorItemHandleButtonPress( GtkWidget* widget, GdkEventButton* event, gpointer user_data ); -void SwatchesPanel::Remove(SPGroup* page) +gboolean colorItemHandleButtonPress( GtkWidget* widget, GdkEventButton* event, gpointer user_data ) { - if (_currentDocument && page) { - std::vector toMove; - for(SPObject* obj = page->firstChild(); obj != NULL; obj = obj->next) { - if (SP_IS_GRADIENT(obj)) { - SPGradient* grad = SP_GRADIENT(obj); - if (grad->isReferenced()) { - toMove.push_back(grad->getRepr()); - } + gboolean handled = FALSE; + + if ( event && (event->button == 3) && (event->type == GDK_BUTTON_PRESS) ) { + SwatchesPanel* swp = findContainingPanel( widget ); + + if ( !popupMenu ) { + popupMenu = gtk_menu_new(); + GtkWidget* child = 0; + + //TRANSLATORS: An item in context menu on a colour in the swatches + child = gtk_menu_item_new_with_label(_("Set fill")); + g_signal_connect( G_OBJECT(child), + "activate", + G_CALLBACK(redirClick), + user_data); + gtk_menu_shell_append(GTK_MENU_SHELL(popupMenu), child); + + //TRANSLATORS: An item in context menu on a colour in the swatches + child = gtk_menu_item_new_with_label(_("Set stroke")); + + g_signal_connect( G_OBJECT(child), + "activate", + G_CALLBACK(redirSecondaryClick), + user_data); + gtk_menu_shell_append(GTK_MENU_SHELL(popupMenu), child); + + child = gtk_separator_menu_item_new(); + gtk_menu_shell_append(GTK_MENU_SHELL(popupMenu), child); + popupExtras.push_back(child); + + child = gtk_menu_item_new_with_label(_("Delete")); + g_signal_connect( G_OBJECT(child), + "activate", + G_CALLBACK(SwatchesPanelHook::deleteGradient), + user_data ); + gtk_menu_shell_append(GTK_MENU_SHELL(popupMenu), child); + popupExtras.push_back(child); + gtk_widget_set_sensitive( child, FALSE ); + + child = gtk_menu_item_new_with_label(_("Edit...")); + g_signal_connect( G_OBJECT(child), + "activate", + G_CALLBACK(editGradient), + user_data ); + gtk_menu_shell_append(GTK_MENU_SHELL(popupMenu), child); + popupExtras.push_back(child); + + child = gtk_separator_menu_item_new(); + gtk_menu_shell_append(GTK_MENU_SHELL(popupMenu), child); + popupExtras.push_back(child); + + child = gtk_menu_item_new_with_label(_("Convert")); + gtk_menu_shell_append(GTK_MENU_SHELL(popupMenu), child); + //popupExtras.push_back(child); + //gtk_widget_set_sensitive( child, FALSE ); + { + popupSubHolder = child; + popupSub = gtk_menu_new(); + gtk_menu_item_set_submenu( GTK_MENU_ITEM(child), popupSub ); } + + gtk_widget_show_all(popupMenu); } - while (!toMove.empty()) { - Inkscape::XML::Node * repr = toMove.back(); - toMove.pop_back(); - repr->parent()->removeChild(repr); - _currentDocument->getDefs()->getRepr()->appendChild(repr); - SP_GRADIENT(_currentDocument->getObjectByRepr(repr))->setSwatch(false); - } - page->deleteObject(false); - DocumentUndo::done(_currentDocument, SP_VERB_DIALOG_SWATCHES, _("Remove Swatch Group")); - } -} -void SwatchesPanel::AddSelectedFill(SPGroup* page) -{ - if (_currentDesktop && _currentDocument) { - SPItem* it = _currentDesktop->selection->singleItem(); - if (it) { - if (it->style->fill.isSet()) { - if (it->style->fill.isPaintserver()) { - SPPaintServer * server = it->style->getFillPaintServer(); - if (SP_IS_GRADIENT(server)) { - SPGradient *grad = SP_GRADIENT(server)->getVector(); - if (_noLink.get_active()) { - Inkscape::XML::Node * clone = grad->getRepr()->duplicate(_currentDocument->getReprDoc()); - clone->setAttribute( "osb:paint", "gradient", 0 ); - if (page) { - page->appendChildRepr(clone); - } else { - _currentDocument->getDefs()->appendChildRepr(clone); - } - Inkscape::GC::release(clone); - DocumentUndo::done(_currentDocument, SP_VERB_DIALOG_SWATCHES, _("Add Gradient Swatch")); - } else if (grad->isSwatch()) { - Inkscape::XML::Node * repr = grad->getRepr(); - Inkscape::XML::Node * clone = repr->duplicate(_currentDocument->getReprDoc()); - if (page) { - page->appendChildRepr(clone); - } else { - _currentDocument->getDefs()->appendChildRepr(clone); - } - SPGradient *newgrad = SP_GRADIENT(_currentDocument->getObjectByRepr(clone)); - - sp_item_set_gradient(it, sp_gradient_ensure_vector_normalized(newgrad), SP_IS_RADIALGRADIENT(newgrad) ? SP_GRADIENT_TYPE_RADIAL : SP_GRADIENT_TYPE_LINEAR, Inkscape::FOR_FILL); - Inkscape::GC::release(clone); - DocumentUndo::done(_currentDocument, SP_VERB_DIALOG_SWATCHES, _("Add Gradient Swatch")); - } else { - Inkscape::XML::Node * repr = grad->getRepr(); - Inkscape::XML::Node * drepr = page ? page->getRepr() : _currentDocument->getDefs()->getRepr(); - if (repr->parent() != drepr) { - repr->parent()->removeChild(repr); - drepr->appendChild(repr); - } - SP_GRADIENT(_currentDocument->getObjectByRepr(repr))->setSwatch(); - DocumentUndo::done(_currentDocument, SP_VERB_DIALOG_SWATCHES, _("Add Gradient Swatch")); - } - } - } else if (it->style->fill.isColor()) { - Inkscape::XML::Node *grad = _currentDocument->getReprDoc()->createElement("svg:linearGradient"); - grad->setAttribute( "osb:paint", "solid", 0 ); - addStop(grad, it->style->fill.value.color.toString(), SP_SCALE24_TO_FLOAT(it->style->fill_opacity.value), "0"); - if (page) { - page->appendChild(grad); - } else { - _currentDocument->getDefs()->appendChild(grad); - } - SPGradient* normalized = sp_gradient_ensure_vector_normalized(SP_GRADIENT(_currentDocument->getObjectByRepr(grad))); - Inkscape::GC::release(grad); - if (!_noLink.get_active()) { - sp_item_set_gradient(it, normalized, SP_GRADIENT_TYPE_LINEAR, Inkscape::FOR_FILL); - } - DocumentUndo::done(_currentDocument, SP_VERB_DIALOG_SWATCHES, _("Add Color Swatch")); - } + if ( user_data ) { + ColorItem* item = reinterpret_cast(user_data); + bool show = swp && (swp->getSelectedIndex() == 0); + for ( std::vector::iterator it = popupExtras.begin(); it != popupExtras.end(); ++ it) { + gtk_widget_set_sensitive(*it, show); } - } - } -} -void SwatchesPanel::AddSelectedStroke(SPGroup* page) -{ - if (_currentDesktop && _currentDocument) { - SPItem* it = _currentDesktop->selection->singleItem(); - if (it) { - if (it->style->stroke.isSet()) { - if (it->style->stroke.isPaintserver()) { - SPPaintServer * server = it->style->getStrokePaintServer(); - if (SP_IS_GRADIENT(server)) { - SPGradient *grad = SP_GRADIENT(server)->getVector(); - if (_noLink.get_active()) { - Inkscape::XML::Node * clone = grad->getRepr()->duplicate(_currentDocument->getReprDoc()); - clone->setAttribute( "osb:paint", "gradient", 0 ); - if (page) { - page->appendChildRepr(clone); - } else { - _currentDocument->getDefs()->appendChildRepr(clone); + bounceTarget = item; + bouncePanel = swp; + popupItems.clear(); + if ( popupMenu ) { + gtk_container_foreach(GTK_CONTAINER(popupSub), removeit, popupSub); + bool processed = false; + GtkWidget *wdgt = gtk_widget_get_ancestor(widget, SP_TYPE_DESKTOP_WIDGET); + if ( wdgt ) { + SPDesktopWidget *dtw = SP_DESKTOP_WIDGET(wdgt); + if ( dtw && dtw->desktop ) { + // Pick up all gradients with vectors + const GSList *gradients = (dtw->desktop->doc())->getResourceList("gradient"); + gint index = 0; + for (const GSList *curr = gradients; curr; curr = curr->next) { + SPGradient* grad = SP_GRADIENT(curr->data); + if ( grad->hasStops() && !grad->isSwatch() ) { + //gl = g_slist_prepend(gl, curr->data); + processed = true; + GtkWidget *child = gtk_menu_item_new_with_label(grad->getId()); + gtk_menu_shell_append(GTK_MENU_SHELL(popupSub), child); + + popupItems.push_back(grad->getId()); + g_signal_connect( G_OBJECT(child), + "activate", + G_CALLBACK(SwatchesPanelHook::convertGradient), + GINT_TO_POINTER(index) ); + index++; } - Inkscape::GC::release(clone); - DocumentUndo::done(_currentDocument, SP_VERB_DIALOG_SWATCHES, _("Add Gradient Swatch")); - } else if (grad->isSwatch()) { - Inkscape::XML::Node * repr = grad->getRepr(); - Inkscape::XML::Node * clone = repr->duplicate(_currentDocument->getReprDoc()); - if (page) { - page->appendChildRepr(clone); - } else { - _currentDocument->getDefs()->appendChildRepr(clone); - } - SPGradient *newgrad = SP_GRADIENT(_currentDocument->getObjectByRepr(clone)); - - sp_item_set_gradient(it, sp_gradient_ensure_vector_normalized(newgrad), SP_IS_RADIALGRADIENT(newgrad) ? SP_GRADIENT_TYPE_RADIAL : SP_GRADIENT_TYPE_LINEAR, Inkscape::FOR_STROKE); - Inkscape::GC::release(clone); - DocumentUndo::done(_currentDocument, SP_VERB_DIALOG_SWATCHES, _("Add Gradient Swatch")); - } else { - Inkscape::XML::Node * repr = grad->getRepr(); - Inkscape::XML::Node * drepr = page ? page->getRepr() : _currentDocument->getDefs()->getRepr(); - if (repr->parent() != drepr) { - repr->parent()->removeChild(repr); - drepr->appendChild(repr); - } - SP_GRADIENT(_currentDocument->getObjectByRepr(repr))->setSwatch(); - DocumentUndo::done(_currentDocument, SP_VERB_DIALOG_SWATCHES, _("Add Gradient Swatch")); } + + gtk_widget_show_all(popupSub); } - } else if (it->style->stroke.isColor()) { - Inkscape::XML::Node *grad = _currentDocument->getReprDoc()->createElement("svg:linearGradient"); - grad->setAttribute( "osb:paint", "solid", 0 ); - addStop(grad, it->style->stroke.value.color.toString(), SP_SCALE24_TO_FLOAT(it->style->stroke_opacity.value), "0"); - if (page) { - page->appendChild(grad); - } else { - _currentDocument->getDefs()->appendChild(grad); - } - SPGradient* normalized = sp_gradient_ensure_vector_normalized(SP_GRADIENT(_currentDocument->getObjectByRepr(grad))); - Inkscape::GC::release(grad); - if (!_noLink.get_active()) { - sp_item_set_gradient(it, normalized, SP_GRADIENT_TYPE_LINEAR, Inkscape::FOR_STROKE); - } - DocumentUndo::done(_currentDocument, SP_VERB_DIALOG_SWATCHES, _("Add Color Swatch")); } + gtk_widget_set_sensitive( popupSubHolder, processed ); + + gtk_menu_popup(GTK_MENU(popupMenu), NULL, NULL, NULL, NULL, event->button, event->time); + handled = TRUE; } } } -} -void SwatchesPanel::_addBIButtonClicked(GdkEventButton* event) -{ - if (popUpImportMenu) { - popUpImportMenu->popup(event->button, event->time); - } + return handled; } -void SwatchesPanel::NewGroupBI() -{ - if (_currentDocument) { - Inkscape::XML::Node * page = SwatchDocument->getReprDoc()->createElement("svg:g"); - gchar *id=NULL; - do { - g_free(id); - id = g_strdup_printf("page%d", page_suffix++); - } while (SwatchDocument->getObjectById(id)); - - page->setAttribute("id", id); - - SwatchDocument->getDefs()->appendChild(page); - sp_repr_save_file(SwatchDocument->getReprDoc(), SwatchFile, SP_SVG_NS_URI); - } -} -void SwatchesPanel::NewGroup() -{ - if (_currentDocument) { - Inkscape::XML::Node * page = _currentDocument->getReprDoc()->createElement("svg:g"); - gchar *id=NULL; - do { - g_free(id); - id = g_strdup_printf("page%d", page_suffix++); - } while (_currentDocument->getObjectById(id)); - - page->setAttribute("id", id); - - _currentDocument->getDefs()->appendChild(page); - DocumentUndo::done(_currentDocument, SP_VERB_DIALOG_SWATCHES, _("New Swatch Group")); +static char* trim( char* str ) { + char* ret = str; + while ( *str && (*str == ' ' || *str == '\t') ) { + str++; } -} - -void SwatchesPanel::SaveAs() -{ - if (_currentDocument) { - Inkscape::XML::Node * page = _currentDocument->getReprDoc()->createElement("svg:g"); - gchar *id=NULL; - do { - g_free(id); - id = g_strdup_printf("page%d", page_suffix++); - } while (_currentDocument->getObjectById(id)); - - page->setAttribute("id", id); - - std::vector toMove; - for (SPObject *it = _currentDocument->getDefs()->firstChild(); it != NULL; it = it->next) { - if (SP_IS_GRADIENT(it)) { - SPGradient* grad = SP_GRADIENT(it); - if (grad->isSwatch()) { - toMove.push_back(grad->getRepr()); - } - } - } - while (!toMove.empty()) { - Inkscape::XML::Node* repr = toMove.back(); - toMove.pop_back(); - repr->parent()->removeChild(repr); - page->appendChild(repr); - } - _currentDocument->getDefs()->appendChild(page); - DocumentUndo::done(_currentDocument, SP_VERB_DIALOG_SWATCHES, _("Save Swatch Group")); + ret = str; + while ( *str ) { + str++; } -} - -void SwatchesPanel::Duplicate(SPGroup* oldpage) -{ - if (_currentDocument) { - Inkscape::XML::Node * page = _currentDocument->getReprDoc()->createElement("svg:g"); - gchar *id=NULL; - do { - g_free(id); - id = g_strdup_printf("page%d", page_suffix++); - } while (_currentDocument->getObjectById(id)); - - page->setAttribute("id", id); - if (oldpage->label()) page->setAttribute("inkscape:label", oldpage->label()); - - for (SPObject *it = oldpage->firstChild(); it != NULL; it = it->next) { - if (SP_IS_GRADIENT(it)) { - SPGradient* grad = SP_GRADIENT(it); - if (grad->isSwatch()) { - Inkscape::XML::Node * copy = grad->getRepr()->duplicate(_currentDocument->getReprDoc()); - page->appendChild(copy); - Inkscape::GC::release(copy); - } - } - } - _currentDocument->getDefs()->appendChild(page); - DocumentUndo::done(_currentDocument, SP_VERB_DIALOG_SWATCHES, _("Duplicate Swatch Group")); + str--; + while ( str > ret && (( *str == ' ' || *str == '\t' ) || *str == '\r' || *str == '\n') ) { + *str-- = 0; } + return ret; } -void SwatchesPanel::_lblClick(GdkEventButton* event, SPGroup* page) -{ - Gtk::Menu * menu = Gtk::manage(new Gtk::Menu()); - - Gtk::MenuItem* mi; - Glib::ustring us = Glib::ustring::compose("%1", page ? (page->label() ? page->label() : page->getId()) : _("[Base]")); - mi = Gtk::manage(new Gtk::MenuItem(page ? (page->label() ? page->label() : page->getId()) : _("[Base]"))); - Gtk::Label* namelbl = dynamic_cast(mi->get_child()); - if (namelbl) { - namelbl->set_markup(us); - } - mi->show(); - mi->set_sensitive(false); - menu->append(*mi); - - Gtk::SeparatorMenuItem* sep; - sep = manage(new Gtk::SeparatorMenuItem()); - sep->show(); - menu->append(*sep); - - mi = Gtk::manage(new Gtk::MenuItem(_("Add Selected Fill"))); - mi->signal_activate().connect_notify(sigc::bind(sigc::mem_fun(*this, &SwatchesPanel::AddSelectedFill), page)); - mi->show(); - mi->set_sensitive(_currentDesktop && _currentDesktop->selection->singleItem()); - menu->append(*mi); - - mi = Gtk::manage(new Gtk::MenuItem(_("Add Selected Stroke"))); - mi->signal_activate().connect_notify(sigc::bind(sigc::mem_fun(*this, &SwatchesPanel::AddSelectedStroke), page)); - mi->show(); - mi->set_sensitive(_currentDesktop && _currentDesktop->selection->singleItem()); - menu->append(*mi); - - sep = manage(new Gtk::SeparatorMenuItem()); - sep->show(); - menu->append(*sep); - - if (page) { - - mi = Gtk::manage(new Gtk::MenuItem(_("Move Up"))); - mi->signal_activate().connect_notify(sigc::bind(sigc::mem_fun(*this, &SwatchesPanel::MoveUp), page)); - mi->show(); - menu->append(*mi); - - mi = Gtk::manage(new Gtk::MenuItem(_("Move Down"))); - mi->signal_activate().connect_notify(sigc::bind(sigc::mem_fun(*this, &SwatchesPanel::MoveDown), page)); - mi->show(); - menu->append(*mi); - - sep = manage(new Gtk::SeparatorMenuItem()); - sep->show(); - menu->append(*sep); - - mi = Gtk::manage(new Gtk::MenuItem(_("Duplicate"))); - mi->signal_activate().connect_notify(sigc::bind(sigc::mem_fun(*this, &SwatchesPanel::Duplicate), page)); - mi->show(); - menu->append(*mi); - - sep = manage(new Gtk::SeparatorMenuItem()); - sep->show(); - menu->append(*sep); - - mi = Gtk::manage(new Gtk::MenuItem(_("Remove"))); - mi->signal_activate().connect_notify(sigc::bind(sigc::mem_fun(*this, &SwatchesPanel::Remove), page)); - mi->show(); - menu->append(*mi); - } else { - mi = Gtk::manage(new Gtk::MenuItem(_("Create New Group"))); - mi->signal_activate().connect_notify(sigc::mem_fun(*this, &SwatchesPanel::NewGroup)); - mi->show(); - menu->append(*mi); - - mi = Gtk::manage(new Gtk::MenuItem(_("Save As New Group"))); - mi->signal_activate().connect_notify(sigc::mem_fun(*this, &SwatchesPanel::SaveAs)); - mi->show(); - menu->append(*mi); +static void skipWhitespace( char*& str ) { + while ( *str == ' ' || *str == '\t' ) { + str++; } - - menu->popup(event->button, event->time); } -void SwatchesPanel::_defsChanged() -{ - if (_storeDoc) { - _storeDoc->clear(); - } - - while (!docWatchers.empty()) { - Inkscape::XML::NodeObserver* w = docWatchers.back(); - docWatchers.pop_back(); - delete w; - } - - std::vector tableChildren = _insideTable.get_children(); - for (std::vector::iterator c = tableChildren.begin(); c != tableChildren.end(); ++c) { - _insideTable.remove(**c); +static bool parseNum( char*& str, int& val ) { + val = 0; + while ( '0' <= *str && *str <= '9' ) { + val = val * 10 + (*str - '0'); + str++; } - - if (_currentDocument) { - Gtk::EventBox* eb; - Gtk::Label* lbl; - if (_showlabels) { - eb = Gtk::manage(new Gtk::EventBox()); - eb->add_events(Gdk::BUTTON_PRESS_MASK); - eb->signal_button_press_event().connect_notify(sigc::bind(sigc::mem_fun(*this, &SwatchesPanel::_lblClick), NULL)); - - lbl = Gtk::manage(new Gtk::Label(_("[Base]"))); - eb->add(*lbl); - _insideTable.attach( *eb, 0, 1, 0, 1, Gtk::FILL/*|Gtk::EXPAND*/, Gtk::FILL/*|Gtk::EXPAND*/ , 5, 0); - } - - ColorItem* item = Gtk::manage(new ColorItem(NULL, _("[None]"), _currentDesktop)); - item->signal_button_press_event().connect_notify(sigc::bind(sigc::mem_fun(*this, &SwatchesPanel::_swatchClicked), NULL)); - item->set_tooltip_text(_("[None]")); - _insideTable.attach( *item, _showlabels ? 1 : 0, _showlabels ? 2 : 1, 0, 1, Gtk::FILL/*|Gtk::EXPAND*/, Gtk::FILL/*|Gtk::EXPAND*/ ); - - unsigned int i = 1; - for (SPObject *it = _currentDocument->getDefs()->firstChild(); it != NULL; it = it->next) { - if (SP_IS_GRADIENT(it)) { - SPGradient* grad = SP_GRADIENT(it); - if (grad->hasStops()) { - - GradientWatcher* w = new GradientWatcher(this, grad); - docWatchers.push_back(w); - - if (grad->isSwatch()) { - - for (SPStop* s = grad->getFirstStop(); s != NULL; s = s->getNextStop()) { - StopWatcher* sw = new StopWatcher(this, s); - docWatchers.push_back(sw); - } + bool retval = !(*str == 0 || *str == ' ' || *str == '\t' || *str == '\r' || *str == '\n'); + return retval; +} - if (_storeDoc) { - Gtk::TreeModel::iterator iter = _storeDoc->append(); - Gtk::TreeModel::Row row = *iter; - row[_modelDoc->_colObject] = grad; - row[_modelDoc->_colLabel] = grad->label() ? grad->label() : grad->getId(); - GdkPixbuf* pixb = sp_gradient_to_pixbuf (grad, 64, 18); - row[_modelDoc->_colPixbuf] = Glib::wrap(pixb); - } - item = Gtk::manage(new ColorItem(grad, it->label() ? it->label() : it->getId(), _currentDesktop)); - item->signal_button_press_event().connect_notify(sigc::bind(sigc::mem_fun(*this, &SwatchesPanel::_swatchClicked), grad)); - item->set_tooltip_text(it->label() ? it->label() : it->getId()); - if (_showlabels) { - _insideTable.attach( *item, 1 + (i % 20), 2 + (i % 20), i / 20, i / 20 + 1, Gtk::FILL/*|Gtk::EXPAND*/, Gtk::FILL/*|Gtk::EXPAND*/ ); +void _loadPaletteFile( gchar const *filename, gboolean user/*=FALSE*/ ) +{ + char block[1024]; + FILE *f = Inkscape::IO::fopen_utf8name( filename, "r" ); + if ( f ) { + char* result = fgets( block, sizeof(block), f ); + if ( result ) { + if ( strncmp( "GIMP Palette", block, 12 ) == 0 ) { + bool inHeader = true; + bool hasErr = false; + + SwatchPage *onceMore = new SwatchPage(); + + do { + result = fgets( block, sizeof(block), f ); + block[sizeof(block) - 1] = 0; + if ( result ) { + if ( block[0] == '#' ) { + // ignore comment } else { - _insideTable.attach( *item, i, i + 1, 0, 1, Gtk::FILL/*|Gtk::EXPAND*/, Gtk::FILL/*|Gtk::EXPAND*/ ); - } - - i++; - } - } - } - } - - for (SPObject *it = _currentDocument->getDefs()->firstChild(); it != NULL; it = it->next) { - if (SP_IS_GROUP(it)) { - SwatchWatcher* w = new SwatchWatcher(this, it, false); - docWatchers.push_back(w); - - if (_showlabels) { - i += 20 - (i % 20); - eb = Gtk::manage(new Gtk::EventBox()); - eb->add_events(Gdk::BUTTON_PRESS_MASK); - eb->signal_button_press_event().connect_notify(sigc::bind(sigc::mem_fun(*this, &SwatchesPanel::_lblClick), SP_GROUP(it))); - lbl = Gtk::manage(new Gtk::Label(it->label() ? it->label() : it->getId())); - eb->add(*lbl); - _insideTable.attach( *eb, 0, 1, i / 20, i / 20 + 1, Gtk::FILL/*|Gtk::EXPAND*/, Gtk::FILL/*|Gtk::EXPAND*/ , 5, 0); - } - - Gtk::TreeModel::iterator rowiter; - - if (_storeDoc) { - rowiter = _storeDoc->append(); - Gtk::TreeModel::Row row = *rowiter; - row[_modelDoc->_colObject] = it; - row[_modelDoc->_colLabel] = it->label() ? it->label() : it->getId(); - } - - for (SPObject *cit = it->firstChild(); cit != NULL; cit = cit->next) { - if (SP_IS_GRADIENT(cit)) { - SPGradient* grad = SP_GRADIENT(cit); - - if (grad->hasStops()) { - - GradientWatcher* w = new GradientWatcher(this, grad); - docWatchers.push_back(w); - - if (grad->isSwatch()) { - - for (SPStop* s = grad->getFirstStop(); s != NULL; s = s->getNextStop()) { - StopWatcher* sw = new StopWatcher(this, s); - docWatchers.push_back(sw); - } - - if (_storeDoc && rowiter) { - Gtk::TreeModel::iterator iter = _storeDoc->append(rowiter->children()); - Gtk::TreeModel::Row row = *iter; - row[_modelDoc->_colObject] = grad; - row[_modelDoc->_colLabel] = grad->label() ? grad->label() : grad->getId(); - GdkPixbuf* pixb = sp_gradient_to_pixbuf (grad, 64, 18); - row[_modelDoc->_colPixbuf] = Glib::wrap(pixb); - - _editDoc.expand_to_path(_storeDoc->get_path(iter)); + char *ptr = block; + // very simple check for header versus entry + while ( *ptr == ' ' || *ptr == '\t' ) { + ptr++; + } + if ( (*ptr == 0) || (*ptr == '\r') || (*ptr == '\n') ) { + // blank line. skip it. + } else if ( '0' <= *ptr && *ptr <= '9' ) { + // should be an entry link + inHeader = false; + ptr = block; + Glib::ustring name(""); + skipWhitespace(ptr); + if ( *ptr ) { + int r = 0; + int g = 0; + int b = 0; + hasErr = parseNum(ptr, r); + if ( !hasErr ) { + skipWhitespace(ptr); + hasErr = parseNum(ptr, g); + } + if ( !hasErr ) { + skipWhitespace(ptr); + hasErr = parseNum(ptr, b); + } + if ( !hasErr && *ptr ) { + char* n = trim(ptr); + if (n != NULL) { + name = g_dpgettext2(NULL, "Palette", n); + } + } + if ( !hasErr ) { + // Add the entry now + Glib::ustring nameStr(name); + ColorItem* item = new ColorItem( r, g, b, nameStr ); + onceMore->_colors.push_back(item); + } + } else { + hasErr = true; } - - item = Gtk::manage(new ColorItem(grad, cit->label() ? cit->label() : cit->getId(), _currentDesktop)); - item->signal_button_press_event().connect_notify(sigc::bind(sigc::mem_fun(*this, &SwatchesPanel::_swatchClicked), grad)); - item->set_tooltip_text(cit->label() ? cit->label() : cit->getId()); - if (_showlabels) { - _insideTable.attach( *item, 1 + (i % 20), 2 + (i % 20), i / 20, i / 20 + 1, Gtk::FILL/*|Gtk::EXPAND*/, Gtk::FILL/*|Gtk::EXPAND*/ ); + } else { + if ( !inHeader ) { + // Hmmm... probably bad. Not quite the format we want? + hasErr = true; } else { - _insideTable.attach( *item, i, i + 1, 0, 1, Gtk::FILL/*|Gtk::EXPAND*/, Gtk::FILL/*|Gtk::EXPAND*/ ); + char* sep = strchr(result, ':'); + if ( sep ) { + *sep = 0; + char* val = trim(sep + 1); + char* name = trim(result); + if ( *name ) { + if ( strcmp( "Name", name ) == 0 ) + { + onceMore->_name = val; + } + else if ( strcmp( "Columns", name ) == 0 ) + { + gchar* endPtr = 0; + guint64 numVal = g_ascii_strtoull( val, &endPtr, 10 ); + if ( (numVal == G_MAXUINT64) && (ERANGE == errno) ) { + // overflow + } else if ( (numVal == 0) && (endPtr == val) ) { + // failed conversion + } else { + onceMore->_prefWidth = numVal; + } + } + } else { + // error + hasErr = true; + } + } else { + // error + hasErr = true; + } } - i++; } } } + } while ( result && !hasErr ); + if ( !hasErr ) { + if (user) + userSwatchPages.push_back(onceMore); + else + systemSwatchPages.push_back(onceMore); +#if ENABLE_MAGIC_COLORS + ColorItem::_wireMagicColors( onceMore ); +#endif // ENABLE_MAGIC_COLORS + } else { + delete onceMore; } } } - } - //_scroller.resize(1,1); - _insideTable.resize(1,1); - _scroller.show_all_children(); - _scroller.queue_draw(); - -} -Gtk::MenuItem* SwatchesPanel::_addSwatchGroup(SPGroup* group, Gtk::TreeModel::Row* parentRow) -{ - Gtk::MenuItem* mi = manage(new Gtk::MenuItem(group->label() ? group->label() : group->getId(),1)); - Gtk::Menu* m = NULL; - - Gtk::TreeModel::Row* r; - if (_store) { - Gtk::TreeModel::iterator iter = parentRow ? _store->append(parentRow->children()) : _store->append(); - Gtk::TreeModel::Row row = *iter; - row[_model->_colObject] = group; - row[_model->_colLabel] = group->label() ? group->label() : group->getId(); - - if (SP_IS_GROUP(group->parent) && SP_GROUP(group->parent)->expanded()) { - _editBI.expand_to_path(_store->get_path(iter)); - } - r = &row; - } else { - r = NULL; - } - - bool hasswatches = false; - for (SPObject * obj = group->firstChild(); obj != NULL; obj = obj->next) - { - if (SP_IS_GROUP(obj)) { - if (!m) { - m = manage(new Gtk::Menu()); - m->show_all(); - mi->set_submenu(*m); - - Gtk::MenuItem* basemi = manage(new Gtk::MenuItem(_("[All]"))); - basemi->show(); - Gtk::Label* namelbl = dynamic_cast(basemi->get_child()); - if (namelbl) { - namelbl->set_markup(_("[All]")); - } - basemi->signal_activate().connect(sigc::bind(sigc::mem_fun(*this, &SwatchesPanel::_addSwatchButtonClicked), group, true)); - m->append(*basemi); - - Gtk::SeparatorMenuItem* sep = manage(new Gtk::SeparatorMenuItem()); - sep->show(); - m->append(*sep); - } - SwatchWatcher* w = new SwatchWatcher(this, obj, true); - rootWatchers.push_back(w); - m->append(*_addSwatchGroup(SP_GROUP(obj), r)); - } else if (SP_IS_GRADIENT(obj)) { - hasswatches = true; - } + fclose(f); } - if (!m) { - mi->signal_activate().connect(sigc::bind(sigc::mem_fun(*this, &SwatchesPanel::_addSwatchButtonClicked), group, false)); - } else if (hasswatches) { - Glib::ustring us = Glib::ustring::compose("%1", group->label() ? group->label() : group->getId()); - Gtk::MenuItem* basemi = manage(new Gtk::MenuItem(group->label() ? group->label() : group->getId())); - basemi->show(); - Gtk::Label* namelbl = dynamic_cast(basemi->get_child()); - if (namelbl) { - namelbl->set_markup(us); - } - basemi->signal_activate().connect(sigc::bind(sigc::mem_fun(*this, &SwatchesPanel::_addSwatchButtonClicked), group, false)); - m->prepend(*basemi); - } - mi->show(); - return mi; } -void SwatchesPanel::_swatchesChanged() -{ - while (!rootWatchers.empty()) { - Inkscape::XML::NodeObserver* w = rootWatchers.back(); - rootWatchers.pop_back(); - delete w; - } +static bool +compare_swatch_names(SwatchPage const *a, SwatchPage const *b) { - std::vector menuChildren = popUpMenu->get_children(); - for (std::vector::iterator c = menuChildren.begin(); c != menuChildren.end(); ++c) { - popUpMenu->remove(**c); - } - - if (_store) { - _store->clear(); - } - - Gtk::MenuItem* mi; - - for (SPObject * obj = SwatchDocument->getDefs()->firstChild(); obj != NULL; obj = obj->next) - { - if (SP_IS_GROUP(obj)) { - SwatchWatcher* w = new SwatchWatcher(this, obj, true); - rootWatchers.push_back(w); - popUpMenu->append(*_addSwatchGroup(SP_GROUP(obj), NULL)); - - } - } - Gtk::SeparatorMenuItem* sep = manage(new Gtk::SeparatorMenuItem()); - sep->show(); - popUpMenu->append(*sep); - - mi = manage(new Gtk::MenuItem(_("New Swatch Group..."),1)); - mi->signal_activate().connect(sigc::mem_fun(*this, &SwatchesPanel::NewGroup)); - mi->show(); - popUpMenu->append(*mi); - - mi = manage(new Gtk::MenuItem(_("Add Swatch File..."),1)); - mi->signal_activate().connect(sigc::bind(sigc::mem_fun(*this, &SwatchesPanel::_importButtonClicked), true, false)); - mi->show(); - popUpMenu->append(*mi); - - mi = manage(new Gtk::MenuItem(_("Import Swatch File..."),1)); - mi->signal_activate().connect(sigc::bind(sigc::mem_fun(*this, &SwatchesPanel::_importButtonClicked), true, true)); - mi->show(); - popUpMenu->append(*mi); + return g_utf8_collate(a->_name.c_str(), b->_name.c_str()) < 0; } -void SwatchesPanel::_styleButton( Gtk::Button& btn, SPDesktop *desktop, unsigned int code, char const* iconName, char const* fallback ) +static void loadEmUp() { - bool set = false; - - if ( iconName ) { - GtkWidget *child = sp_icon_new( Inkscape::ICON_SIZE_SMALL_TOOLBAR, iconName ); - gtk_widget_show( child ); - btn.add( *manage(Glib::wrap(child)) ); - btn.set_relief(Gtk::RELIEF_NONE); - set = true; - } - - if ( desktop ) { - Verb *verb = Verb::get( code ); - if ( verb ) { - SPAction *action = verb->get_action(desktop); - if ( !set && action && action->image ) { - GtkWidget *child = sp_icon_new( Inkscape::ICON_SIZE_SMALL_TOOLBAR, action->image ); - gtk_widget_show( child ); - btn.add( *manage(Glib::wrap(child)) ); - set = true; + static bool beenHere = false; + gboolean userPalete = true; + if ( !beenHere ) { + beenHere = true; + + std::list sources; + sources.push_back( profile_path("palettes") ); + sources.push_back( g_strdup(INKSCAPE_PALETTESDIR) ); + sources.push_back( g_strdup(CREATE_PALETTESDIR) ); + + // Use this loop to iterate through a list of possible document locations. + while (!sources.empty()) { + gchar *dirname = sources.front(); + if ( Inkscape::IO::file_test( dirname, G_FILE_TEST_EXISTS ) + && Inkscape::IO::file_test( dirname, G_FILE_TEST_IS_DIR )) { + GError *err = 0; + GDir *directory = g_dir_open(dirname, 0, &err); + if (!directory) { + gchar *safeDir = Inkscape::IO::sanitizeString(dirname); + g_warning(_("Palettes directory (%s) is unavailable."), safeDir); + g_free(safeDir); + } else { + gchar *filename = 0; + while ((filename = (gchar *)g_dir_read_name(directory)) != NULL) { + gchar* lower = g_ascii_strdown( filename, -1 ); +// if ( g_str_has_suffix(lower, ".gpl") ) { + if ( !g_str_has_suffix(lower, "~") ) { + gchar* full = g_build_filename(dirname, filename, NULL); + if ( !Inkscape::IO::file_test( full, G_FILE_TEST_IS_DIR ) ) { + _loadPaletteFile(full, userPalete); + } + g_free(full); + } +// } + g_free(lower); + } + g_dir_close(directory); + } } + + // toss the dirname + g_free(dirname); + sources.pop_front(); + userPalete = false; } } - - btn.set_tooltip_text (fallback); - if ( !set ) { - btn.set_label( fallback ); - } -} + // Sort the list of swatches by name, grouped by user/system + userSwatchPages.sort(compare_swatch_names); + systemSwatchPages.sort(compare_swatch_names); -void SwatchesPanel::_addButtonClicked(GdkEventButton* event) { - if ( (event->type == GDK_BUTTON_PRESS) && (event->button == 3 || event->button == 1) ) { - if (popUpMenu) { - popUpMenu->popup(event->button, event->time); - } - } } -void SwatchesPanel::NoLinkToggled() { - static Inkscape::Preferences *prefs = Inkscape::Preferences::get(); - Glib::ustring nolink = Glib::ustring::compose("%1/nolink", _prefs_path); - prefs->setBool(nolink, _noLink.get_active()); -} -bool SwatchesPanel::_handleButtonEvent(GdkEventButton *event) -{ - static unsigned doubleclick = 0; - if ( (event->type == GDK_2BUTTON_PRESS) && (event->button == 1) ) { - doubleclick = 1; - } - if ( event->type == GDK_BUTTON_RELEASE && doubleclick) { - doubleclick = 0; - Gtk::TreeModel::Path path; - Gtk::TreeViewColumn* col = 0; - int x = static_cast(event->x); - int y = static_cast(event->y); - int x2 = 0; - int y2 = 0; - if ( _editBI.get_path_at_pos( x, y, path, col, x2, y2 ) && col == _name_columnBI) { - // Double click on the Layer name, enable editing - _text_rendererBI->property_editable() = true; - _editBI.set_cursor (path, *_name_columnBI, true); - grab_focus(); - } - } - - return false; +SwatchesPanel& SwatchesPanel::getInstance() +{ + return *new SwatchesPanel(); } -bool SwatchesPanel::_handleKeyEvent(GdkEventKey *event) + +/** + * Constructor + */ +SwatchesPanel::SwatchesPanel(gchar const* prefsPath) : + Inkscape::UI::Widget::Panel("", prefsPath, SP_VERB_DIALOG_SWATCHES, "", true), + _holder(0), + _clear(0), + _remove(0), + _currentIndex(0), + _currentDesktop(0), + _currentDocument(0) { - switch (Inkscape::UI::Tools::get_group0_keyval(event)) { - case GDK_KEY_Return: - case GDK_KEY_KP_Enter: - case GDK_KEY_F2: { - Gtk::TreeModel::iterator iter = _editBI.get_selection()->get_selected(); - if (iter && !_text_rendererBI->property_editable()) { - Gtk::TreeRow row = *iter; - SPObject * obj = row[_model->_colObject]; - if (obj) { - Gtk::TreeModel::Path *path = new Gtk::TreeModel::Path(iter); - // Edit the layer label - _text_rendererBI->property_editable() = true; - _editBI.set_cursor(*path, *_name_columnBI, true); - grab_focus(); - return true; + Gtk::RadioMenuItem* hotItem = 0; + _holder = new PreviewHolder(); + _clear = new ColorItem( ege::PaintDef::CLEAR ); + _remove = new ColorItem( ege::PaintDef::NONE ); + if (docPalettes.empty()) { + SwatchPage *docPalette = new SwatchPage(); + + docPalette->_name = "Auto"; + docPalettes[0] = docPalette; + } + + loadEmUp(); + if ( !systemSwatchPages.empty() ) { + SwatchPage* first = 0; + int index = 0; + Glib::ustring targetName; + if ( !_prefs_path.empty() ) { + Inkscape::Preferences *prefs = Inkscape::Preferences::get(); + targetName = prefs->getString(_prefs_path + "/palette"); + if (!targetName.empty()) { + if (targetName == "Auto") { + first = docPalettes[0]; + } else { + //index++; + std::vector pages = _getSwatchSets(); + for ( std::vector::iterator iter = pages.begin(); iter != pages.end(); ++iter ) { + if ( (*iter)->_name == targetName ) { + first = *iter; + break; + } + index++; + } } } } - case GDK_KEY_Delete: { - - Gtk::TreeModel::iterator iter = _editBI.get_selection()->get_selected(); - if (iter) { - Gtk::TreeRow row = *iter; - SPObject * obj = row[_model->_colObject]; - if (obj) { - obj->deleteObject(false); - sp_repr_save_file(SwatchDocument->getReprDoc(), SwatchFile, SP_SVG_NS_URI); - } + + if ( !first ) { + first = docPalettes[0]; + _currentIndex = 0; + } else { + _currentIndex = index; + } + + _rebuild(); + + Gtk::RadioMenuItem::Group groupOne; + + int i = 0; + std::vector swatchSets = _getSwatchSets(); + for ( std::vector::iterator it = swatchSets.begin(); it != swatchSets.end(); ++it) { + SwatchPage* curr = *it; + Gtk::RadioMenuItem* single = manage(new Gtk::RadioMenuItem(groupOne, curr->_name)); + if ( curr == first ) { + hotItem = single; } - return true; + _regItem( single, 3, i ); + + i++; } - break; } - return false; -} -void SwatchesPanel::_handleEdited(const Glib::ustring& path, const Glib::ustring& new_text) -{ - Gtk::TreeModel::iterator iter = _editBI.get_model()->get_iter(path); - Gtk::TreeModel::Row row = *iter; + if (Glib::ustring(prefsPath) == "/dialogs/swatches") { + Gtk::Requisition sreq; +#if WITH_GTKMM_3_0 + Gtk::Requisition sreq_natural; + get_preferred_size(sreq_natural, sreq); +#else + sreq = size_request(); +#endif + int minHeight = 60; + if (sreq.height < minHeight) { + set_size_request(70, minHeight); + } + } - _renameObject(row, new_text); - _text_rendererBI->property_editable() = false; -} + _getContents()->pack_start(*_holder, Gtk::PACK_EXPAND_WIDGET); + _setTargetFillable(_holder); -void SwatchesPanel::_handleEditingCancelled() -{ - _text_rendererBI->property_editable() = false; -} + show_all_children(); -void SwatchesPanel::_renameObject(Gtk::TreeModel::Row row, const Glib::ustring& name) -{ - if ( row && SwatchDocument) { - SPObject* obj = row[_model->_colObject]; - if ( obj ) { - gchar const* oldLabel = obj->label(); - if ( !name.empty() && (!oldLabel || name != oldLabel) ) { - obj->setLabel(name.c_str()); - sp_repr_save_file(SwatchDocument->getReprDoc(), SwatchFile, SP_SVG_NS_URI); - } - } + restorePanelPrefs(); + if ( hotItem ) { + hotItem->set_active(); } } -void SwatchesPanel::_setCollapsed(SPGroup * group) +SwatchesPanel::~SwatchesPanel() { - group->setExpanded(false); - group->updateRepr(SP_OBJECT_WRITE_NO_CHILDREN | SP_OBJECT_WRITE_EXT); - for (SPObject *iter = group->children; iter != NULL; iter = iter->next) - { - if (SP_IS_GROUP(iter)) _setCollapsed(SP_GROUP(iter)); + _trackDocument( this, 0 ); + + _documentConnection.disconnect(); + _selChanged.disconnect(); + + if ( _clear ) { + delete _clear; + } + if ( _remove ) { + delete _remove; + } + if ( _holder ) { + delete _holder; } } -void SwatchesPanel::_setExpanded(const Gtk::TreeModel::iterator& iter, const Gtk::TreeModel::Path& /*path*/, bool isexpanded) +void SwatchesPanel::setOrientation(SPAnchorType how) { - Gtk::TreeModel::Row row = *iter; + // Must call the parent class or bad things might happen + Inkscape::UI::Widget::Panel::setOrientation( how ); - SPObject* obj = row[_model->_colObject]; - if (obj && SP_IS_GROUP(obj)) + if ( _holder ) { - if (isexpanded) - { - SP_GROUP(obj)->setExpanded(isexpanded); - obj->updateRepr(SP_OBJECT_WRITE_NO_CHILDREN | SP_OBJECT_WRITE_EXT); - } - else - { - _setCollapsed(SP_GROUP(obj)); - } + _holder->setOrientation(SP_ANCHOR_SOUTH); } - sp_repr_save_file(SwatchDocument->getReprDoc(), SwatchFile, SP_SVG_NS_URI); } -void SwatchesPanel::_deleteButtonClicked() +void SwatchesPanel::setDesktop( SPDesktop* desktop ) { - Gtk::TreeModel::iterator iter = _editBI.get_selection()->get_selected(); - if (iter) { - Gtk::TreeModel::Row row = *iter; - SPObject* obj = row[_model->_colObject]; - if (obj) { - obj->deleteObject(false); - sp_repr_save_file(SwatchDocument->getReprDoc(), SwatchFile, SP_SVG_NS_URI); + if ( desktop != _currentDesktop ) { + if ( _currentDesktop ) { + _documentConnection.disconnect(); + _selChanged.disconnect(); } - } -} -bool SwatchesPanel::_handleButtonEventDoc(GdkEventButton* event) -{ - static unsigned doubleclick = 0; - - if ( (event->type == GDK_BUTTON_PRESS) && (event->button == 3) ) { - // TODO - fix to a better is-popup function - Gtk::TreeModel::Path path; - int x = static_cast(event->x); - int y = static_cast(event->y); - if ( _editDoc.get_path_at_pos( x, y, path ) ) { - Gtk::TreeModel::Children::iterator iter = _editDoc.get_model()->get_iter(path); - Gtk::TreeModel::Row row = *iter; - - SPObject* obj = row[_modelDoc->_colObject]; - if (SP_IS_GRADIENT(obj)) { - _swatchClicked(event, SP_GRADIENT(obj)); - } else if (SP_IS_GROUP(obj)) { - _lblClick(event, SP_GROUP(obj)); - } else { - _lblClick(event, NULL); - } - } else { - _lblClick(event, NULL); - } - } - - if ( (event->type == GDK_2BUTTON_PRESS) && (event->button == 1) ) { - doubleclick = 1; - } + _currentDesktop = desktop; - if ( event->type == GDK_BUTTON_RELEASE && doubleclick) { - doubleclick = 0; - Gtk::TreeModel::Path path; - Gtk::TreeViewColumn* col = 0; - int x = static_cast(event->x); - int y = static_cast(event->y); - int x2 = 0; - int y2 = 0; - if ( _editDoc.get_path_at_pos( x, y, path, col, x2, y2 ) && col == _name_columnDoc) { - // Double click on the Layer name, enable editing - _text_rendererDoc->property_editable() = true; - _editDoc.set_cursor (path, *_name_columnDoc, true); - grab_focus(); + if ( desktop ) { + _currentDesktop->selection->connectChanged( + sigc::hide(sigc::mem_fun(*this, &SwatchesPanel::_updateFromSelection))); + + _currentDesktop->selection->connectModified( + sigc::hide(sigc::hide(sigc::mem_fun(*this, &SwatchesPanel::_updateFromSelection)))); + + _currentDesktop->connectToolSubselectionChanged( + sigc::hide(sigc::mem_fun(*this, &SwatchesPanel::_updateFromSelection))); + + sigc::bound_mem_functor1 first = sigc::mem_fun(*this, &SwatchesPanel::_setDocument); + sigc::slot base2 = first; + sigc::slot slot2 = sigc::hide<0>( base2 ); + _documentConnection = desktop->connectDocumentReplaced( slot2 ); + + _setDocument( desktop->doc() ); + } else { + _setDocument(0); } } - - return false; } -void SwatchesPanel::_deleteButtonClickedDoc() + +class DocTrack { - Gtk::TreeModel::iterator iter = _editDoc.get_selection()->get_selected(); - if (iter) { - Gtk::TreeRow row = *iter; - SPObject * obj = row[_modelDoc->_colObject]; - if (SP_IS_GRADIENT(obj)) { - RemoveSwatch(SP_GRADIENT(obj)); - } else if (SP_IS_GROUP(obj)) { - Remove(SP_GROUP(obj)); +public: + DocTrack(SPDocument *doc, sigc::connection &gradientRsrcChanged, sigc::connection &defsChanged, sigc::connection &defsModified) : + doc(doc->doRef()), + updatePending(false), + lastGradientUpdate(0.0), + gradientRsrcChanged(gradientRsrcChanged), + defsChanged(defsChanged), + defsModified(defsModified) + { + if ( !timer ) { + timer = new Glib::Timer(); + refreshTimer = Glib::signal_timeout().connect( sigc::ptr_fun(handleTimerCB), 33 ); } + timerRefCount++; } -} -bool SwatchesPanel::_handleKeyEventDoc(GdkEventKey *event) -{ - switch (Inkscape::UI::Tools::get_group0_keyval(event)) { - case GDK_KEY_Return: - case GDK_KEY_KP_Enter: - case GDK_KEY_F2: { - Gtk::TreeModel::iterator iter = _editDoc.get_selection()->get_selected(); - if (iter && !_text_rendererDoc->property_editable()) { - Gtk::TreeRow row = *iter; - SPObject * obj = row[_modelDoc->_colObject]; - if (obj) { - Gtk::TreeModel::Path *path = new Gtk::TreeModel::Path(iter); - // Edit the layer label - _text_rendererDoc->property_editable() = true; - _editDoc.set_cursor(*path, *_name_columnDoc, true); - grab_focus(); - return true; - } + ~DocTrack() + { + timerRefCount--; + if ( timerRefCount <= 0 ) { + refreshTimer.disconnect(); + timerRefCount = 0; + if ( timer ) { + timer->stop(); + delete timer; + timer = 0; } } - case GDK_KEY_Delete: { - - _deleteButtonClickedDoc(); - return true; + if (doc) { + gradientRsrcChanged.disconnect(); + defsChanged.disconnect(); + defsModified.disconnect(); + doc->doUnref(); + doc = NULL; } - break; } - return false; -} -void SwatchesPanel::_renameObjectDoc(Gtk::TreeModel::Row row, const Glib::ustring& name) -{ - if ( row && SwatchDocument) { - SPObject* obj = row[_modelDoc->_colObject]; - if ( obj ) { - gchar const* oldLabel = obj->label(); - if ( !name.empty() && (!oldLabel || name != oldLabel) ) { - obj->setLabel(name.c_str()); - } - } - } -} + static bool handleTimerCB(); -void SwatchesPanel::_handleEditedDoc(const Glib::ustring& path, const Glib::ustring& new_text) -{ - Gtk::TreeModel::iterator iter = _editDoc.get_model()->get_iter(path); - Gtk::TreeModel::Row row = *iter; + /** + * Checks if update should be queued or executed immediately. + * + * @return true if the update was queued and should not be immediately executed. + */ + static bool queueUpdateIfNeeded(SPDocument *doc); - _renameObjectDoc(row, new_text); - _text_rendererDoc->property_editable() = false; -} + static Glib::Timer *timer; + static int timerRefCount; + static sigc::connection refreshTimer; -void SwatchesPanel::_handleEditingCancelledDoc() -{ - _text_rendererDoc->property_editable() = false; -} + SPDocument *doc; + bool updatePending; + double lastGradientUpdate; + sigc::connection gradientRsrcChanged; + sigc::connection defsChanged; + sigc::connection defsModified; -/* - * Drap and drop within the tree - * Save the drag source and drop target SPObjects and if its a drag between layers or into (sublayer) a layer - */ -bool SwatchesPanel::_handleDragDrop(const Glib::RefPtr& context, int x, int y, guint time) +private: + DocTrack(DocTrack const &); // no copy + DocTrack &operator=(DocTrack const &); // no assign +}; + +Glib::Timer *DocTrack::timer = 0; +int DocTrack::timerRefCount = 0; +sigc::connection DocTrack::refreshTimer; + +static const double DOC_UPDATE_THREASHOLD = 0.090; + +bool DocTrack::handleTimerCB() { - int cell_x = 0, cell_y = 0; - Gtk::TreeModel::Path target_path; - Gtk::TreeView::Column *target_column; - - bool _dnd_top = false; - _dnd_into = false; - _dnd_target = SwatchDocument->getDefs()->lastChild(); - Gtk::TreeModel::iterator itersel = _editBI.get_selection()->get_selected(); - if (!itersel) { - return true; - } - Gtk::TreeModel::Row rowsel = *itersel; - _dnd_source = rowsel[_model->_colObject]; + double now = timer->elapsed(); - if (!_dnd_source) { - return true; - } - - if (_editBI.get_path_at_pos (x, y, target_path, target_column, cell_x, cell_y)) { - // Are we before, inside or after the drop layer - Gdk::Rectangle rect; - _editBI.get_background_area (target_path, *target_column, rect); - int cell_height = rect.get_height(); - _dnd_into = (cell_y > (int)(cell_height * 1/3) && cell_y <= (int)(cell_height * 2/3)); - if (cell_y < (int)(cell_height * 1/3)) { - Gtk::TreeModel::Path next_path = target_path; - if (next_path.prev()) { - target_path = next_path; - } else { - // Dragging to the "end" - Gtk::TreeModel::Path up_path = target_path; - up_path.up(); - if (_store->iter_is_valid(_store->get_iter(up_path))) { - // Drop into parent - target_path = up_path; - _dnd_into = true; - } else { - _dnd_top = true; - // Drop into the top level - _dnd_target = NULL; - } - } - } - if (!_dnd_top) { - Gtk::TreeModel::iterator iter = _store->get_iter(target_path); - if (_store->iter_is_valid(iter)) { - Gtk::TreeModel::Row row = *iter; - SPObject *obj = row[_model->_colObject]; - if (obj) { - _dnd_target = obj; - } - } + std::vector needCallback; + for (std::vector::iterator it = docTrackings.begin(); it != docTrackings.end(); ++it) { + DocTrack *track = *it; + if ( track->updatePending && ( (now - track->lastGradientUpdate) >= DOC_UPDATE_THREASHOLD) ) { + needCallback.push_back(track); } } - - if (_dnd_source != _dnd_target) { - - Inkscape::XML::Node *target_ref = _dnd_target ? _dnd_target->getRepr() : NULL; - Inkscape::XML::Node *our_ref = _dnd_source->getRepr(); - - if (target_ref != our_ref) { - if (!target_ref) { - target_ref = SwatchDocument->getDefs()->getRepr(); - if (target_ref != our_ref->parent()) { - our_ref->parent()->removeChild(our_ref); - target_ref->addChild(our_ref, NULL); - } else { - our_ref->parent()->changeOrder(our_ref, NULL); - } - } else if (_dnd_into) { - // Move this inside of the target at the end - our_ref->parent()->removeChild(our_ref); - target_ref->addChild(our_ref, NULL); - } else if (target_ref->parent() != our_ref->parent()) { - // Change in parent, need to remove and add - our_ref->parent()->removeChild(our_ref); - target_ref->parent()->addChild(our_ref, target_ref); - } else { - // Same parent, just move - our_ref->parent()->changeOrder(our_ref, target_ref); - } + + for (std::vector::iterator it = needCallback.begin(); it != needCallback.end(); ++it) { + DocTrack *track = *it; + if ( std::find(docTrackings.begin(), docTrackings.end(), track) != docTrackings.end() ) { // Just in case one gets deleted while we are looping + // Note: calling handleDefsModified will call queueUpdateIfNeeded and thus update the time and flag. + SwatchesPanel::handleDefsModified(track->doc); } - sp_repr_save_file(SwatchDocument->getReprDoc(), SwatchFile, SP_SVG_NS_URI); } return true; } -/* - * Drap and drop within the tree - * Save the drag source and drop target SPObjects and if its a drag between layers or into (sublayer) a layer - */ -bool SwatchesPanel::_handleDragDropDoc(const Glib::RefPtr& context, int x, int y, guint time) +bool DocTrack::queueUpdateIfNeeded( SPDocument *doc ) { - int cell_x = 0, cell_y = 0; - Gtk::TreeModel::Path target_path; - Gtk::TreeView::Column *target_column; - - bool _dnd_top = false; - _dnd_into = false; - _dnd_target = _currentDocument->getDefs()->lastChild(); - Gtk::TreeModel::iterator itersel = _editDoc.get_selection()->get_selected(); - if (!itersel) { - return true; - } - Gtk::TreeModel::Row rowsel = *itersel; - _dnd_source = rowsel[_modelDoc->_colObject]; - - if (!_dnd_source) { - return true; - } - - if (_editDoc.get_path_at_pos (x, y, target_path, target_column, cell_x, cell_y)) { - // Are we before, inside or after the drop layer - Gdk::Rectangle rect; - _editDoc.get_background_area (target_path, *target_column, rect); - int cell_height = rect.get_height(); - _dnd_into = (cell_y > (int)(cell_height * 1/3) && cell_y <= (int)(cell_height * 2/3)); - if (cell_y < (int)(cell_height * 1/3)) { - Gtk::TreeModel::Path next_path = target_path; - if (next_path.prev()) { - target_path = next_path; + bool deferProcessing = false; + for (std::vector::iterator it = docTrackings.begin(); it != docTrackings.end(); ++it) { + DocTrack *track = *it; + if ( track->doc == doc ) { + double now = timer->elapsed(); + double elapsed = now - track->lastGradientUpdate; + + if ( elapsed < DOC_UPDATE_THREASHOLD ) { + deferProcessing = true; + track->updatePending = true; } else { - // Dragging to the "end" - Gtk::TreeModel::Path up_path = target_path; - up_path.up(); - if (_storeDoc->iter_is_valid(_storeDoc->get_iter(up_path))) { - // Drop into parent - target_path = up_path; - _dnd_into = true; - } else { - _dnd_top = true; - // Drop into the top level - _dnd_target = NULL; - } + track->lastGradientUpdate = now; + track->updatePending = false; } + + break; } - if (!_dnd_top) { - Gtk::TreeModel::iterator iter = _storeDoc->get_iter(target_path); - if (_storeDoc->iter_is_valid(iter)) { - Gtk::TreeModel::Row row = *iter; - SPObject *obj = row[_modelDoc->_colObject]; - if (obj) { - _dnd_target = obj; - if (SP_IS_GRADIENT(obj)) { - _dnd_into = false; - if (SP_IS_GROUP(_dnd_source)) { - _dnd_target = obj->parent; - } - } else if (SP_IS_GROUP(_dnd_source)) { - _dnd_into = false; + } + return deferProcessing; +} + +void SwatchesPanel::_trackDocument( SwatchesPanel *panel, SPDocument *document ) +{ + SPDocument *oldDoc = NULL; + if (docPerPanel.find(panel) != docPerPanel.end()) { + oldDoc = docPerPanel[panel]; + if (!oldDoc) { + docPerPanel.erase(panel); // Should not be needed, but clean up just in case. + } + } + if (oldDoc != document) { + if (oldDoc) { + docPerPanel[panel] = NULL; + bool found = false; + for (std::map::iterator it = docPerPanel.begin(); (it != docPerPanel.end()) && !found; ++it) { + found = (it->second == document); + } + if (!found) { + for (std::vector::iterator it = docTrackings.begin(); it != docTrackings.end(); ++it){ + if ((*it)->doc == oldDoc) { + delete *it; + docTrackings.erase(it); + break; } } } } - } - - if (_dnd_source != _dnd_target) { - - Inkscape::XML::Node *target_ref = _dnd_target ? _dnd_target->getRepr() : NULL; - Inkscape::XML::Node *our_ref = _dnd_source->getRepr(); - - if (target_ref != our_ref) { - if (!target_ref) { - target_ref = _currentDocument->getDefs()->getRepr(); - if (target_ref != our_ref->parent()) { - our_ref->parent()->removeChild(our_ref); - target_ref->addChild(our_ref, NULL); - } else { - our_ref->parent()->changeOrder(our_ref, NULL); + + if (document) { + bool found = false; + for (std::map::iterator it = docPerPanel.begin(); (it != docPerPanel.end()) && !found; ++it) { + found = (it->second == document); + } + docPerPanel[panel] = document; + if (!found) { + sigc::connection conn1 = document->connectResourcesChanged( "gradient", sigc::bind(sigc::ptr_fun(&SwatchesPanel::handleGradientsChange), document) ); + sigc::connection conn2 = document->getDefs()->connectRelease( sigc::hide(sigc::bind(sigc::ptr_fun(&SwatchesPanel::handleDefsModified), document)) ); + sigc::connection conn3 = document->getDefs()->connectModified( sigc::hide(sigc::hide(sigc::bind(sigc::ptr_fun(&SwatchesPanel::handleDefsModified), document))) ); + + DocTrack *dt = new DocTrack(document, conn1, conn2, conn3); + docTrackings.push_back(dt); + + if (docPalettes.find(document) == docPalettes.end()) { + SwatchPage *docPalette = new SwatchPage(); + docPalette->_name = "Auto"; + docPalettes[document] = docPalette; } - } else if (_dnd_into) { - // Move this inside of the target at the end - our_ref->parent()->removeChild(our_ref); - target_ref->addChild(our_ref, NULL); - } else if (target_ref->parent() != our_ref->parent()) { - // Change in parent, need to remove and add - our_ref->parent()->removeChild(our_ref); - target_ref->parent()->addChild(our_ref, target_ref); - } else { - // Same parent, just move - our_ref->parent()->changeOrder(our_ref, target_ref); } } - DocumentUndo::done( _currentDocument , SP_VERB_DIALOG_SWATCHES, - _("Moved Swatches")); } - - return true; } +void SwatchesPanel::_setDocument( SPDocument *document ) +{ + if ( document != _currentDocument ) { + _trackDocument(this, document); + _currentDocument = document; + handleGradientsChange( document ); + } +} -/** - * Constructor - */ -SwatchesPanel::SwatchesPanel(gchar const* prefsPath, bool showLabels) : - Inkscape::UI::Widget::Panel("", prefsPath, SP_VERB_DIALOG_SWATCHES, ""), - _scroller(), - _insideTable(1, 1), - _insideV(), - _insideH(), - _buttonsRow(), - _outsideV(), - _noLink(_("Don't Link")), - _showlabels(showLabels), - _store(0), - _scrollerBI(), - _editBI(), - _buttonsRowBI(), - _editBIV(), - _storeDoc(0), - _scrollerDoc(), - _editDoc(), - _buttonsRowDoc(), - _editDocV(), - _notebook(), - rootWatcher(0), - docWatcher(0), - _currentDesktop(0), - _currentDocument(0) +static void recalcSwatchContents(SPDocument* doc, + boost::ptr_vector &tmpColors, + std::map &previewMappings, + std::map &gradMappings) { - _insideH.pack_start(_insideTable, Gtk::PACK_SHRINK); - if (_showlabels) { - _insideV.pack_start(_insideH, Gtk::PACK_SHRINK); - _scroller.add(_insideV); - } else { - _scroller.property_height_request() = 20; - _scroller.add(_insideH); + std::vector newList; + + const GSList *gradients = doc->getResourceList("gradient"); + for (const GSList *item = gradients; item; item = item->next) { + SPGradient* grad = SP_GRADIENT(item->data); + if ( grad->isSwatch() ) { + newList.push_back(SP_GRADIENT(item->data)); + } } - - popUpMenu = manage( new Gtk::Menu() ); - popUpMenu->show_all_children(); - - Gtk::Button* btn = manage( new Gtk::Button() ); - _styleButton( *btn, SP_ACTIVE_DESKTOP, SP_VERB_LAYER_NEW, GTK_STOCK_ADD, _("Add Swatch") ); - btn->signal_button_press_event().connect_notify( sigc::mem_fun(*this, &SwatchesPanel::_addButtonClicked) ); - _buttonsRow.pack_start(*btn, Gtk::PACK_SHRINK); - -// btn = manage( new Gtk::Button() ); -// _styleButton( *btn, SP_ACTIVE_DESKTOP, SP_VERB_LAYER_NEW, GTK_STOCK_DISCONNECT, C_("Unlink", "New") ); -// _buttonsRow.pack_end(*btn, Gtk::PACK_SHRINK); - - static Inkscape::Preferences *prefs = Inkscape::Preferences::get(); - Glib::ustring nolink = Glib::ustring::compose("%1/nolink", prefsPath); - _noLink.set_tooltip_text(_("Don't link swatches")); - _noLink.set_active(prefs->getBool(nolink, false)); - _noLink.signal_toggled().connect_notify(sigc::mem_fun(*this, &SwatchesPanel::NoLinkToggled)); - _buttonsRow.pack_end(_noLink, Gtk::PACK_SHRINK); - - _scroller.set_policy( Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC ); - _scroller.set_shadow_type(Gtk::SHADOW_NONE); - - if (_showlabels) { - _outsideV.pack_end(_buttonsRow, Gtk::PACK_SHRINK); - _outsideV.pack_end(_scroller, Gtk::PACK_EXPAND_WIDGET); - - _notebook.append_page(_outsideV, "Use"); - + + if ( !newList.empty() ) { + std::reverse(newList.begin(), newList.end()); + for ( std::vector::iterator it = newList.begin(); it != newList.end(); ++it ) { - ModelColumnsDoc *zoop = new ModelColumnsDoc(); - _modelDoc = zoop; + SPGradient* grad = *it; - _storeDoc = Gtk::TreeStore::create( *zoop ); + cairo_surface_t *preview = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, + PREVIEW_PIXBUF_WIDTH, VBLOCK); + cairo_t *ct = cairo_create(preview); - _editDoc.set_model( _storeDoc ); - _editDoc.set_headers_visible(false); - _editDoc.set_reorderable(true); - _editDoc.enable_model_drag_dest (Gdk::ACTION_MOVE); + Glib::ustring name( grad->getId() ); + ColorItem* item = new ColorItem( 0, 0, 0, name ); - Gtk::Button* btn = manage( new Gtk::Button() ); - _styleButton( *btn, SP_ACTIVE_DESKTOP, SP_VERB_LAYER_NEW, GTK_STOCK_ADD, _("Import Swatch") ); - btn->signal_button_press_event().connect_notify( sigc::mem_fun(*this, &SwatchesPanel::_addButtonClicked)); - _buttonsRowDoc.pack_start(*btn, Gtk::PACK_SHRINK); + cairo_pattern_t *check = ink_cairo_pattern_create_checkerboard(); + cairo_pattern_t *gradient = sp_gradient_create_preview_pattern(grad, PREVIEW_PIXBUF_WIDTH); + cairo_set_source(ct, check); + cairo_paint(ct); + cairo_set_source(ct, gradient); + cairo_paint(ct); - btn = manage( new Gtk::Button() ); - _styleButton( *btn, SP_ACTIVE_DESKTOP, SP_VERB_LAYER_DELETE, GTK_STOCK_DELETE, _("Delete Swatch") ); - btn->signal_button_press_event().connect_notify( sigc::hide(sigc::mem_fun(*this, &SwatchesPanel::_deleteButtonClickedDoc))); - _buttonsRowDoc.pack_start(*btn, Gtk::PACK_SHRINK); + cairo_destroy(ct); + cairo_pattern_destroy(gradient); + cairo_pattern_destroy(check); - _pixbuf_rendererDoc = manage(new Gtk::CellRendererPixbuf()); - int pixbufColNum = _editDoc.append_column("Pixbuf", *_pixbuf_rendererDoc) - 1; - _pixbuf_columnDoc = _editDoc.get_column(pixbufColNum); - _pixbuf_columnDoc->add_attribute(_pixbuf_rendererDoc->property_pixbuf(), _modelDoc->_colPixbuf); - - _text_rendererDoc = manage(new Gtk::CellRendererText()); - int nameColNum = _editDoc.append_column("Name", *_text_rendererDoc) - 1; - _name_columnDoc = _editDoc.get_column(nameColNum); - _name_columnDoc->add_attribute(_text_rendererDoc->property_text(), _modelDoc->_colLabel); + cairo_pattern_t *prevpat = cairo_pattern_create_for_surface(preview); + cairo_surface_destroy(preview); - _text_rendererDoc->signal_edited().connect( sigc::mem_fun(*this, &SwatchesPanel::_handleEditedDoc) ); - _text_rendererDoc->signal_editing_canceled().connect( sigc::mem_fun(*this, &SwatchesPanel::_handleEditingCancelledDoc) ); + previewMappings[item] = prevpat; + + tmpColors.push_back(item); + gradMappings[item] = grad; + } + } +} - _editDoc.set_expander_column( *_editDoc.get_column(nameColNum) ); +void SwatchesPanel::handleGradientsChange(SPDocument *document) +{ + SwatchPage *docPalette = (docPalettes.find(document) != docPalettes.end()) ? docPalettes[document] : 0; + if (docPalette) { + boost::ptr_vector tmpColors; + std::map tmpPrevs; + std::map tmpGrads; + recalcSwatchContents(document, tmpColors, tmpPrevs, tmpGrads); - _editDoc.signal_button_press_event().connect( sigc::mem_fun(*this, &SwatchesPanel::_handleButtonEventDoc), false ); - _editDoc.signal_button_release_event().connect( sigc::mem_fun(*this, &SwatchesPanel::_handleButtonEventDoc), false ); - _editDoc.signal_key_press_event().connect( sigc::mem_fun(*this, &SwatchesPanel::_handleKeyEventDoc), false ); + for (std::map::iterator it = tmpPrevs.begin(); it != tmpPrevs.end(); ++it) { + it->first->setPattern(it->second); + cairo_pattern_destroy(it->second); + } - _editDoc.signal_drag_drop().connect( sigc::mem_fun(*this, &SwatchesPanel::_handleDragDropDoc), false); + for (std::map::iterator it = tmpGrads.begin(); it != tmpGrads.end(); ++it) { + it->first->setGradient(it->second); + } - _scrollerDoc.set_policy( Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC ); - _scrollerDoc.set_shadow_type(Gtk::SHADOW_IN); - _scrollerDoc.add(_editDoc); + docPalette->_colors.swap(tmpColors); - _editDocV.pack_start(_scrollerDoc, Gtk::PACK_EXPAND_WIDGET); - _editDocV.pack_end(_buttonsRowDoc, Gtk::PACK_SHRINK); + // Figure out which SwatchesPanel instances are affected and update them. - _notebook.append_page(_editDocV, "Edit"); - } - - { - popUpImportMenu = Gtk::manage(new Gtk::Menu()); - - Gtk::MenuItem* mi = Gtk::manage(new Gtk::MenuItem(_("New Swatch Group..."))); - mi->signal_activate().connect_notify(sigc::mem_fun(*this, &SwatchesPanel::NewGroupBI)); - mi->show(); - popUpImportMenu->append(*mi); - - mi = Gtk::manage(new Gtk::MenuItem(_("Import Swatch File..."))); - mi->signal_activate().connect_notify(sigc::bind(sigc::mem_fun(*this, &SwatchesPanel::_importButtonClicked), false, true)); - mi->show(); - popUpImportMenu->append(*mi); - - ModelColumns *zoop = new ModelColumns(); - _model = zoop; - - _store = Gtk::TreeStore::create( *zoop ); - - _editBI.set_model( _store ); - _editBI.set_headers_visible(false); - _editBI.set_reorderable(true); - _editBI.enable_model_drag_dest (Gdk::ACTION_MOVE); - - Gtk::Button* btn = manage( new Gtk::Button() ); - _styleButton( *btn, SP_ACTIVE_DESKTOP, SP_VERB_LAYER_NEW, GTK_STOCK_ADD, _("Import Swatch") ); - btn->signal_button_press_event().connect_notify(sigc::mem_fun(*this, &SwatchesPanel::_addBIButtonClicked)); - _buttonsRowBI.pack_start(*btn, Gtk::PACK_SHRINK); - - btn = manage( new Gtk::Button() ); - _styleButton( *btn, SP_ACTIVE_DESKTOP, SP_VERB_LAYER_DELETE, GTK_STOCK_DELETE, _("Delete Swatch") ); - btn->signal_button_press_event().connect_notify( sigc::hide(sigc::mem_fun(*this, &SwatchesPanel::_deleteButtonClicked))); - _buttonsRowBI.pack_start(*btn, Gtk::PACK_SHRINK); - - _text_rendererBI = manage(new Gtk::CellRendererText()); - int nameColNum = _editBI.append_column("Name", *_text_rendererBI) - 1; - _name_columnBI = _editBI.get_column(nameColNum); - _name_columnBI->add_attribute(_text_rendererBI->property_text(), _model->_colLabel); - - _text_rendererBI->signal_edited().connect( sigc::mem_fun(*this, &SwatchesPanel::_handleEdited) ); - _text_rendererBI->signal_editing_canceled().connect( sigc::mem_fun(*this, &SwatchesPanel::_handleEditingCancelled) ); - - _editBI.set_expander_column( *_editBI.get_column(nameColNum) ); - - _editBI.signal_button_press_event().connect( sigc::mem_fun(*this, &SwatchesPanel::_handleButtonEvent), false ); - _editBI.signal_button_release_event().connect( sigc::mem_fun(*this, &SwatchesPanel::_handleButtonEvent), false ); - _editBI.signal_key_press_event().connect( sigc::mem_fun(*this, &SwatchesPanel::_handleKeyEvent), false ); - - _editBI.signal_drag_drop().connect( sigc::mem_fun(*this, &SwatchesPanel::_handleDragDrop), false); - _editBI.signal_row_collapsed().connect( sigc::bind(sigc::mem_fun(*this, &SwatchesPanel::_setExpanded), false)); - _editBI.signal_row_expanded().connect( sigc::bind(sigc::mem_fun(*this, &SwatchesPanel::_setExpanded), true)); - - _scrollerBI.set_policy( Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC ); - _scrollerBI.set_shadow_type(Gtk::SHADOW_IN); - _scrollerBI.add(_editBI); - - _editBIV.pack_start(_scrollerBI, Gtk::PACK_EXPAND_WIDGET); - _editBIV.pack_end(_buttonsRowBI, Gtk::PACK_SHRINK); - - _notebook.append_page(_editBIV, "Edit Built-In"); + for (std::map::iterator it = docPerPanel.begin(); it != docPerPanel.end(); ++it) { + if (it->second == document) { + SwatchesPanel* swp = it->first; + std::vector pages = swp->_getSwatchSets(); + SwatchPage* curr = pages[swp->_currentIndex]; + if (curr == docPalette) { + swp->_rebuild(); + } + } } - - _getContents()->pack_end(_notebook, Gtk::PACK_EXPAND_WIDGET); - } else { - //_outsideV.pack_end(_scroller, Gtk::PACK_SHRINK); - _buttonsRow.pack_end(_scroller, Gtk::PACK_EXPAND_WIDGET); - //_getContents()->pack_end(_outsideV, Gtk::PACK_SHRINK); - _getContents()->pack_end(_buttonsRow, Gtk::PACK_SHRINK); } - - loadPalletFile(); - - rootWatcher = new SwatchWatcher(this, SwatchDocument->getDefs(), true); - SwatchDocument->getDefs()->getRepr()->addObserver(*rootWatcher); - _swatchesChanged(); - _insideTable.resize(1,1); } -SwatchesPanel::~SwatchesPanel() +void SwatchesPanel::handleDefsModified(SPDocument *document) { - if (rootWatcher) { - rootWatcher->_repr->removeObserver(*rootWatcher); - delete rootWatcher; + SwatchPage *docPalette = (docPalettes.find(document) != docPalettes.end()) ? docPalettes[document] : 0; + if (docPalette && !DocTrack::queueUpdateIfNeeded(document) ) { + boost::ptr_vector tmpColors; + std::map tmpPrevs; + std::map tmpGrads; + recalcSwatchContents(document, tmpColors, tmpPrevs, tmpGrads); + + if ( tmpColors.size() != docPalette->_colors.size() ) { + handleGradientsChange(document); + } else { + int cap = std::min(docPalette->_colors.size(), tmpColors.size()); + for (int i = 0; i < cap; i++) { + ColorItem *newColor = &tmpColors[i]; + ColorItem *oldColor = &docPalette->_colors[i]; + if ( (newColor->def.getType() != oldColor->def.getType()) || + (newColor->def.getR() != oldColor->def.getR()) || + (newColor->def.getG() != oldColor->def.getG()) || + (newColor->def.getB() != oldColor->def.getB()) ) { + oldColor->def.setRGB(newColor->def.getR(), newColor->def.getG(), newColor->def.getB()); + } + if (tmpGrads.find(newColor) != tmpGrads.end()) { + oldColor->setGradient(tmpGrads[newColor]); + } + if ( tmpPrevs.find(newColor) != tmpPrevs.end() ) { + oldColor->setPattern(tmpPrevs[newColor]); + } + } + } + + for (std::map::iterator it = tmpPrevs.begin(); it != tmpPrevs.end(); ++it) { + cairo_pattern_destroy(it->second); + } } - - if (docWatcher) { - docWatcher->_repr->removeObserver(*docWatcher); - delete docWatcher; +} + + +std::vector SwatchesPanel::_getSwatchSets() const +{ + std::vector tmp; + if (docPalettes.find(_currentDocument) != docPalettes.end()) { + tmp.push_back(docPalettes[_currentDocument]); } - _documentConnection.disconnect(); - _selChanged.disconnect(); + tmp.insert(tmp.end(), userSwatchPages.begin(), userSwatchPages.end()); + tmp.insert(tmp.end(), systemSwatchPages.begin(), systemSwatchPages.end()); + + return tmp; } -void SwatchesPanel::setDesktop( SPDesktop* desktop ) +void SwatchesPanel::_updateFromSelection() { - Inkscape::UI::Widget::Panel::setDesktop(desktop); - if ( desktop != _currentDesktop ) { - if ( _currentDesktop ) { - _documentConnection.disconnect(); - _selChanged.disconnect(); + SwatchPage *docPalette = (docPalettes.find(_currentDocument) != docPalettes.end()) ? docPalettes[_currentDocument] : 0; + if ( docPalette ) { + Glib::ustring fillId; + Glib::ustring strokeId; + + SPStyle *tmpStyle = sp_style_new( sp_desktop_document(_currentDesktop) ); + int result = sp_desktop_query_style( _currentDesktop, tmpStyle, QUERY_STYLE_PROPERTY_FILL ); + switch (result) { + case QUERY_STYLE_SINGLE: + case QUERY_STYLE_MULTIPLE_AVERAGED: + case QUERY_STYLE_MULTIPLE_SAME: + { + if (tmpStyle->fill.set && tmpStyle->fill.isPaintserver()) { + SPPaintServer* server = tmpStyle->getFillPaintServer(); + if ( SP_IS_GRADIENT(server) ) { + SPGradient* target = 0; + SPGradient* grad = SP_GRADIENT(server); + + if ( grad->isSwatch() ) { + target = grad; + } else if ( grad->ref ) { + SPGradient *tmp = grad->ref->getObject(); + if ( tmp && tmp->isSwatch() ) { + target = tmp; + } + } + if ( target ) { + //XML Tree being used directly here while it shouldn't be + gchar const* id = target->getRepr()->attribute("id"); + if ( id ) { + fillId = id; + } + } + } + } + break; + } } - _currentDesktop = desktop; + result = sp_desktop_query_style( _currentDesktop, tmpStyle, QUERY_STYLE_PROPERTY_STROKE ); + switch (result) { + case QUERY_STYLE_SINGLE: + case QUERY_STYLE_MULTIPLE_AVERAGED: + case QUERY_STYLE_MULTIPLE_SAME: + { + if (tmpStyle->stroke.set && tmpStyle->stroke.isPaintserver()) { + SPPaintServer* server = tmpStyle->getStrokePaintServer(); + if ( SP_IS_GRADIENT(server) ) { + SPGradient* target = 0; + SPGradient* grad = SP_GRADIENT(server); + if ( grad->isSwatch() ) { + target = grad; + } else if ( grad->ref ) { + SPGradient *tmp = grad->ref->getObject(); + if ( tmp && tmp->isSwatch() ) { + target = tmp; + } + } + if ( target ) { + //XML Tree being used directly here while it shouldn't be + gchar const* id = target->getRepr()->attribute("id"); + if ( id ) { + strokeId = id; + } + } + } + } + break; + } + } + sp_style_unref(tmpStyle); - if ( desktop ) { - //_currentDesktop->selection->connectChanged(sigc::hide(sigc::mem_fun(*this, &SwatchesPanel::_updateFromSelection))); + for ( boost::ptr_vector::iterator it = docPalette->_colors.begin(); it != docPalette->_colors.end(); ++it ) { + ColorItem* item = &*it; + bool isFill = (fillId == item->def.descr); + bool isStroke = (strokeId == item->def.descr); + item->setState( isFill, isStroke ); + } + } +} - _documentConnection = desktop->connectDocumentReplaced(sigc::mem_fun(*this, &SwatchesPanel::_setDocument)); +void SwatchesPanel::_handleAction( int setId, int itemId ) +{ + switch( setId ) { + case 3: + { + std::vector pages = _getSwatchSets(); + if ( itemId >= 0 && itemId < static_cast(pages.size()) ) { + _currentIndex = itemId; - _setDocument( desktop, desktop->doc() ); - } else { - _setDocument(0, 0); + if ( !_prefs_path.empty() ) { + Inkscape::Preferences *prefs = Inkscape::Preferences::get(); + prefs->setString(_prefs_path + "/palette", pages[_currentIndex]->_name); + } + + _rebuild(); + } } + break; } } -void SwatchesPanel::_setDocument( SPDesktop* desktop, SPDocument *document ) +void SwatchesPanel::_rebuild() { - if ( document != _currentDocument ) { - if (docWatcher) { - docWatcher->_repr->removeObserver(*docWatcher); - delete docWatcher; - docWatcher = NULL; - } - _currentDocument = document; - - if (_currentDocument) { - docWatcher = new SwatchWatcher(this, _currentDocument->getDefs(), false); - _currentDocument->getDefs()->getRepr()->addObserver(*docWatcher); - } - _defsChanged(); + std::vector pages = _getSwatchSets(); + SwatchPage* curr = pages[_currentIndex]; + _holder->clear(); + + if ( curr->_prefWidth > 0 ) { + _holder->setColumnPref( curr->_prefWidth ); } + _holder->freezeUpdates(); + // TODO restore once 'clear' works _holder->addPreview(_clear); + _holder->addPreview(_remove); + for ( boost::ptr_vector::iterator it = curr->_colors.begin(); it != curr->_colors.end(); ++it) { + _holder->addPreview(&*it); + } + _holder->thawUpdates(); } } //namespace Dialogs } //namespace UI } //namespace Inkscape -//really lazy! -void sp_desktop_set_gradient(SPDesktop *desktop, SPGradient* gradient, bool fill) -{ - - bool intercepted = false; - - if (gradient->isSolid()) { - ColorRGBA color(gradient->getFirstStop()->getEffectiveColor().toRGBA32(gradient->getFirstStop()->opacity)); - guint32 rgba = SP_RGBA32_F_COMPOSE(color[0], color[1], color[2], color[3]); - gchar b[64]; - sp_svg_write_color(b, sizeof(b), rgba); - SPCSSAttr *css = sp_repr_css_attr_new(); - if (fill) { - sp_repr_css_set_property(css, "fill", b); - Inkscape::CSSOStringStream osalpha; - osalpha << color[3]; - sp_repr_css_set_property(css, "fill-opacity", osalpha.str().c_str()); - } else { - sp_repr_css_set_property(css, "stroke", b); - Inkscape::CSSOStringStream osalpha; - osalpha << color[3]; - sp_repr_css_set_property(css, "stroke-opacity", osalpha.str().c_str()); - } - intercepted = desktop->_set_style_signal.emit(css); - } - - if (!intercepted) { - for (const GSList *it = desktop->selection->itemList(); it != NULL; it = it->next) { - sp_item_set_gradient(SP_ITEM(it->data), gradient, SP_IS_RADIALGRADIENT(gradient) ? SP_GRADIENT_TYPE_RADIAL : SP_GRADIENT_TYPE_LINEAR, !fill ? Inkscape::FOR_STROKE : Inkscape::FOR_FILL); - } - } -} /* Local Variables: diff --git a/src/ui/dialog/swatches.h b/src/ui/dialog/swatches.h index cb8f87962..ca4c1687d 100644 --- a/src/ui/dialog/swatches.h +++ b/src/ui/dialog/swatches.h @@ -12,161 +12,64 @@ #include "ui/widget/panel.h" #include "enums.h" -#include "sp-object.h" -#include "sp-item-group.h" -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "sp-gradient.h" -#include "xml/node-observer.h" namespace Inkscape { namespace UI { +class PreviewHolder; + namespace Dialogs { +class ColorItem; +class SwatchPage; +class DocTrack; + /** * A panel that displays paint swatches. */ class SwatchesPanel : public Inkscape::UI::Widget::Panel { public: - SwatchesPanel(gchar const* prefsPath = "/dialogs/swatches", bool showLabels = true); + SwatchesPanel(gchar const* prefsPath = "/dialogs/swatches"); virtual ~SwatchesPanel(); - + static SwatchesPanel& getInstance(); + virtual void setOrientation(SPAnchorType how); + virtual void setDesktop( SPDesktop* desktop ); virtual SPDesktop* getDesktop() {return _currentDesktop;} + virtual int getSelectedIndex() {return _currentIndex;} // temporary + protected: + static void handleGradientsChange(SPDocument *document); + + virtual void _updateFromSelection(); + virtual void _handleAction( int setId, int itemId ); + virtual void _setDocument( SPDocument *document ); + virtual void _rebuild(); - virtual void _setDocument( SPDesktop* desktop, SPDocument *document ); + virtual std::vector _getSwatchSets() const; private: - class ModelColumns; - class ModelColumnsDoc; - - class StopWatcher; - class GradientWatcher; - class SwatchWatcher; - SwatchesPanel(SwatchesPanel const &); // no copy SwatchesPanel &operator=(SwatchesPanel const &); // no assign - - void _styleButton( Gtk::Button& btn, SPDesktop *desktop, unsigned int code, char const* iconName, char const* fallback ); - - void _setSelectionSwatch(SPGradient* swatchItem, bool isStroke); - - void NoLinkToggled(); - void NewGroup(); - void NewGroupBI(); - void _addBIButtonClicked(GdkEventButton* event); - void Duplicate(SPGroup* page); - void SaveAs(); - void AddSelectedFill(SPGroup* page); - void AddSelectedStroke(SPGroup* page); - void MoveUp(SPGroup* page); - void MoveDown(SPGroup* page); - void Remove(SPGroup* page); - - void SetSelectedFill(SPGradient* swatch); - void SetSelectedStroke(SPGradient* swatch); - void MoveSwatchUp(SPGradient* swatch); - void MoveSwatchDown(SPGradient* swatch); - void RemoveSwatch(SPGradient* swatch); - - void _lblClick(GdkEventButton* event, SPGroup* page); - void _addSwatchButtonClicked(SPGroup* swatch, bool recurse); - void _defsChanged(); - void _importButtonClicked(bool addToDoc, bool addToBI); - void _deleteButtonClicked(); - void _addButtonClicked(GdkEventButton* event); - void _swatchClicked(GdkEventButton* event, SPGradient* swatchItem); - - Gtk::MenuItem* _addSwatchGroup(SPGroup* group, Gtk::TreeModel::Row* parentRow); - void _swatchesChanged(); - - bool _handleButtonEvent(GdkEventButton *event); - bool _handleKeyEvent(GdkEventKey *event); - - void _handleEdited(const Glib::ustring& path, const Glib::ustring& new_text); - void _handleEditingCancelled(); - void _renameObject(Gtk::TreeModel::Row row, const Glib::ustring& name); - - void _setCollapsed(SPGroup * group); - void _setExpanded(const Gtk::TreeModel::iterator& iter, const Gtk::TreeModel::Path& /*path*/, bool isexpanded); - - void _deleteButtonClickedDoc(); - bool _handleButtonEventDoc(GdkEventButton* event); - bool _handleKeyEventDoc(GdkEventKey *event); - - void _handleEditedDoc(const Glib::ustring& path, const Glib::ustring& new_text); - void _handleEditingCancelledDoc(); - void _renameObjectDoc(Gtk::TreeModel::Row row, const Glib::ustring& name); - - bool _handleDragDropDoc(const Glib::RefPtr& context, int x, int y, guint time); - bool _handleDragDrop(const Glib::RefPtr& context, int x, int y, guint time); - - Gtk::Menu *popUpMenu; - Gtk::Menu *popUpImportMenu; - - Gtk::ScrolledWindow _scroller; - Gtk::Table _insideTable; - Gtk::VBox _insideV; - Gtk::HBox _insideH; - Gtk::HBox _buttonsRow; - Gtk::VBox _outsideV; - Gtk::CheckButton _noLink; - bool _showlabels; - - SwatchesPanel::ModelColumns* _model; - Glib::RefPtr _store; - - Gtk::CellRendererText *_text_rendererBI; - Gtk::TreeView::Column *_name_columnBI; - Gtk::ScrolledWindow _scrollerBI; - Gtk::TreeView _editBI; - Gtk::HBox _buttonsRowBI; - Gtk::VBox _editBIV; - - SwatchesPanel::ModelColumnsDoc* _modelDoc; - Glib::RefPtr _storeDoc; - - Gtk::CellRendererText *_text_rendererDoc; - Gtk::CellRendererPixbuf *_pixbuf_rendererDoc; - Gtk::TreeView::Column *_name_columnDoc; - Gtk::TreeView::Column *_pixbuf_columnDoc; - Gtk::ScrolledWindow _scrollerDoc; - Gtk::TreeView _editDoc; - Gtk::HBox _buttonsRowDoc; - Gtk::VBox _editDocV; - - Gtk::Notebook _notebook; - - SwatchWatcher* rootWatcher; - std::vector rootWatchers; - - std::vector docWatchers; - SwatchWatcher* docWatcher; + static void _trackDocument( SwatchesPanel *panel, SPDocument *document ); + static void handleDefsModified(SPDocument *document); + + PreviewHolder* _holder; + ColorItem* _clear; + ColorItem* _remove; + int _currentIndex; SPDesktop* _currentDesktop; SPDocument* _currentDocument; - - bool _dnd_into; - SPObject* _dnd_source; - SPObject* _dnd_target; sigc::connection _documentConnection; sigc::connection _selChanged; + + friend class DocTrack; }; } //namespace Dialogs diff --git a/src/widgets/desktop-widget.cpp b/src/widgets/desktop-widget.cpp index 2eba8bb8c..361a54a90 100644 --- a/src/widgets/desktop-widget.cpp +++ b/src/widgets/desktop-widget.cpp @@ -358,7 +358,7 @@ void SPDesktopWidget::init( SPDesktopWidget *dtw ) { using Inkscape::UI::Dialogs::SwatchesPanel; - dtw->panels = new SwatchesPanel("/embedded/swatches", false); + dtw->panels = new SwatchesPanel("/embedded/swatches" /*false*/); dtw->panels->setOrientation(SP_ANCHOR_SOUTH); #if GTK_CHECK_VERSION(3,0,0) -- cgit v1.2.3 From 95b10e0707ee0e16055d5e514e1d05c929d49b5a Mon Sep 17 00:00:00 2001 From: "Liam P. White" Date: Tue, 18 Mar 2014 17:34:31 -0600 Subject: Added in new toy effect "Taper Strokes," readded a missing header file, bugfixes (bzr r13090.1.25) --- src/live_effects/Makefile_insert | 6 +- src/live_effects/effect-enum.h | 3 +- src/live_effects/effect.cpp | 13 +- src/live_effects/lpe-jointype.h | 43 ++ src/live_effects/lpe-taperstroke.cpp | 536 +++++++++++++++++++++++ src/live_effects/lpe-taperstroke.h | 73 ++++ src/live_effects/pathoutlineprovider.h | 766 +++++++++++++++++++++++++++++++++ src/ui/clipboard.cpp | 9 + 8 files changed, 1443 insertions(+), 6 deletions(-) create mode 100755 src/live_effects/lpe-jointype.h create mode 100644 src/live_effects/lpe-taperstroke.cpp create mode 100644 src/live_effects/lpe-taperstroke.h create mode 100755 src/live_effects/pathoutlineprovider.h (limited to 'src') diff --git a/src/live_effects/Makefile_insert b/src/live_effects/Makefile_insert index 35a85b4aa..b19f417ae 100644 --- a/src/live_effects/Makefile_insert +++ b/src/live_effects/Makefile_insert @@ -92,4 +92,8 @@ ink_common_sources += \ live_effects/lpe-fill-between-many.cpp \ live_effects/lpe-fill-between-many.h \ live_effects/lpe-ellipse_5pts.cpp \ - live_effects/lpe-ellipse_5pts.h + live_effects/lpe-ellipse_5pts.h \ + live_effects/lpe-jointype.cpp \ + live_effects/lpe-jointype.h \ + live_effects/lpe-taperstroke.cpp \ + live_effects/lpe-taperstroke.h diff --git a/src/live_effects/effect-enum.h b/src/live_effects/effect-enum.h index 9c76875e9..c53d64699 100644 --- a/src/live_effects/effect-enum.h +++ b/src/live_effects/effect-enum.h @@ -55,7 +55,8 @@ enum EffectType { FILL_BETWEEN_MANY, ELLIPSE_5PTS, BOUNDING_BOX, -// JOIN_TYPE, + JOIN_TYPE, + TAPER_STROKE, INVALID_LPE // This must be last (I made it such that it is not needed anymore I think..., Don't trust on it being last. - johan) }; diff --git a/src/live_effects/effect.cpp b/src/live_effects/effect.cpp index eac0f79f4..d6840e5b8 100644 --- a/src/live_effects/effect.cpp +++ b/src/live_effects/effect.cpp @@ -52,7 +52,8 @@ #include "live_effects/lpe-fill-between-many.h" #include "live_effects/lpe-ellipse_5pts.h" #include "live_effects/lpe-bounding-box.h" -//#include "live_effects/lpe-jointype.h" +#include "live_effects/lpe-jointype.h" +#include "live_effects/lpe-taperstroke.h" #include "xml/node-event-vector.h" #include "sp-object.h" @@ -109,7 +110,8 @@ const Util::EnumData LPETypeData[] = { {RECURSIVE_SKELETON, N_("Recursive skeleton"), "recursive_skeleton"}, {TANGENT_TO_CURVE, N_("Tangent to curve"), "tangent_to_curve"}, {TEXT_LABEL, N_("Text label"), "text_label"}, -// {JOIN_TYPE, N_("Join type"), "join_type"}, + {JOIN_TYPE, N_("Join type"), "join_type"}, + {TAPER_STROKE, N_("Taper stroke"), "taper_stroke"}, #endif /* 0.46 */ {BEND_PATH, N_("Bend"), "bend_path"}, @@ -273,9 +275,12 @@ Effect::New(EffectType lpenr, LivePathEffectObject *lpeobj) case BOUNDING_BOX: neweffect = static_cast ( new LPEBoundingBox(lpeobj) ); break; - /*case JOIN_TYPE: + case JOIN_TYPE: neweffect = static_cast ( new LPEJoinType(lpeobj) ); - break;*/ + break; + case TAPER_STROKE: + neweffect = static_cast ( new LPETaperStroke(lpeobj) ); + break; default: g_warning("LivePathEffect::Effect::New called with invalid patheffect type (%d)", lpenr); neweffect = NULL; diff --git a/src/live_effects/lpe-jointype.h b/src/live_effects/lpe-jointype.h new file mode 100755 index 000000000..db113c66a --- /dev/null +++ b/src/live_effects/lpe-jointype.h @@ -0,0 +1,43 @@ +/* Authors: + * Liam P White + * + * Copyright (C) 2014 Authors + * + * Released under GNU GPL v2, read the file COPYING for more information + */ +#ifndef INKSCAPE_LPE_JOINTYPE_H +#define INKSCAPE_LPE_JOINTYPE_H + +#include "live_effects/effect.h" +#include "live_effects/parameter/parameter.h" +#include "live_effects/parameter/point.h" +#include "live_effects/parameter/enum.h" + +namespace Inkscape { +namespace LivePathEffect { + +class LPEJoinType : public Effect { +public: + LPEJoinType(LivePathEffectObject *lpeobject); + virtual ~LPEJoinType(); + + virtual void doOnApply(SPLPEItem const* lpeitem); + virtual void doOnRemove(SPLPEItem const* lpeitem); + virtual std::vector doEffect_path (std::vector const & path_in); + +private: + LPEJoinType(const LPEJoinType&); + LPEJoinType& operator=(const LPEJoinType&); + + ScalarParam line_width; + EnumParam linecap_type; + EnumParam linejoin_type; + ScalarParam miter_limit; + BoolParam attempt_force_join; + bool was_initialized; +}; + +} //namespace LivePathEffect +} //namespace Inkscape + +#endif diff --git a/src/live_effects/lpe-taperstroke.cpp b/src/live_effects/lpe-taperstroke.cpp new file mode 100644 index 000000000..e6eed3abe --- /dev/null +++ b/src/live_effects/lpe-taperstroke.cpp @@ -0,0 +1,536 @@ +/** + * @file + * Taper Stroke path effect, provided as an alternative to Power Strokes + * for otherwise constant-width paths. + * + * Authors: + * Liam P White + * + * Copyright (C) 2014 Authors + * + * Released under GNU GPL, read the file 'COPYING' for more information + */ + +#include "live_effects/lpe-taperstroke.h" + +// You might need to include other 2geom files. You can add them here: +#include <2geom/path.h> +#include <2geom/shape.h> +#include "pathoutlineprovider.h" +#include "display/curve.h" +#include "svg/svg.h" + +//#include + +#include "knot-holder-entity.h" +#include "knotholder.h" + +namespace Inkscape { +namespace LivePathEffect { + +namespace TpS { + class KnotHolderEntityAttachBegin : public LPEKnotHolderEntity { + public: + KnotHolderEntityAttachBegin(LPETaperStroke * effect) : LPEKnotHolderEntity(effect) {} + virtual void knot_set(Geom::Point const &p, Geom::Point const &origin, guint state); + virtual Geom::Point knot_get() const; + }; + class KnotHolderEntityAttachEnd : public LPEKnotHolderEntity { + public: + KnotHolderEntityAttachEnd(LPETaperStroke * effect) : LPEKnotHolderEntity(effect) {} + virtual void knot_set(Geom::Point const &p, Geom::Point const &origin, guint state); + virtual Geom::Point knot_get() const; + }; +} // TpS + +static const Util::EnumData JoinType[] = { + {LINEJOIN_STRAIGHT, N_("Beveled"), "bevel"}, + {LINEJOIN_ROUND, N_("Rounded"), "round"}, + {LINEJOIN_REFLECTED, N_("Reflected"), "reflected"}, + {LINEJOIN_POINTY, N_("Miter"), "miter"}, + {LINEJOIN_EXTRAPOLATED, N_("Extrapolated"), "extrapolated"} +}; + +static const Util::EnumDataConverter JoinTypeConverter(JoinType, sizeof (JoinType)/sizeof(*JoinType)); + +LPETaperStroke::LPETaperStroke(LivePathEffectObject *lpeobject) : + Effect(lpeobject), + attach_start(_("Start offset"), _("Taper distance from path start"), "attach_start", &wr, this, 0.2), + attach_end(_("End offset"), _("The ending position of the taper"), "end_offset", &wr, this, 0.2), + smoothing(_("Taper smoothing"), _("Amount of smoothing to apply to the tapers"), "smoothing", &wr, this, 0.2), + join_type(_("Join type"), _("Join type for non-smooth nodes"), "jointype", JoinTypeConverter, &wr, this, LINEJOIN_EXTRAPOLATED), + miter_limit(_("Miter limit"), _("Limit for miter joins"), "miter_limit", &wr, this, 30.) +{ + /* uncomment the following line to have the original path displayed while the item is selected */ + show_orig_path = true; + _provides_knotholder_entities = true; + + attach_start.param_set_digits(3); + attach_end.param_set_digits(3); + + registerParameter( dynamic_cast(&attach_start) ); + registerParameter( dynamic_cast(&attach_end) ); + registerParameter( dynamic_cast(&smoothing) ); + registerParameter( dynamic_cast(&join_type) ); + registerParameter( dynamic_cast(&miter_limit) ); +} + +LPETaperStroke::~LPETaperStroke() +{ + +} + +unsigned curveOrder (const Geom::Curve* curve_in) +{ + using namespace Geom; + //cast it + const CubicBezier *cbc = dynamic_cast(curve_in); + if (cbc) return 3; + const QuadraticBezier * qbc = dynamic_cast(curve_in); + if (qbc) return 2; + const BezierCurveN<1U> * lbc = dynamic_cast *>(curve_in); + if (lbc) return 1; + //BezierCurveN<0> * dbc = dynamic_cast *> (curve_in); + return 0; +} + +Geom::Path return_at_first_cusp (Geom::Path const & path_in, double smooth_tolerance = 0.01) +{ + Geom::Path path_out = Geom::Path(); + + for (unsigned i = 0; i < path_in.size(); i++) + { + path_out.append(path_in[i]); + if (path_in.size() == 1) + break; + + //determine order of curve + int order = curveOrder(&path_in[i]); + + Geom::Point start_point; + Geom::Point cross_point = path_in[i].finalPoint(); + Geom::Point end_point; + + g_assert(path_in[i].finalPoint() == path_in[i+1].initialPoint()); + + //can you tell that the following expressions have been shaped by + //repeated compiler errors? ;) + switch (order) + { + case 3: + start_point = (dynamic_cast(&path_in[i]))->operator[] (2); + break; + case 2: + start_point = (dynamic_cast(&path_in[i]))->operator[] (1); + break; + case 1: + default: + start_point = path_in[i].initialPoint(); + } + + order = curveOrder(&path_in[i+1]); + + switch (order) + { + case 3: + end_point = (dynamic_cast(&path_in[i+1]))->operator[] (1); + break; + case 2: + end_point = (dynamic_cast(&path_in[i+1]))->operator[] (1); + break; + case 1: + default: + end_point = path_in[i+1].finalPoint(); + } + if (!are_collinear(start_point, cross_point, end_point, smooth_tolerance)) + break; + } + return path_out; +} + +Geom::Curve * subdivide_at(const Geom::Curve* curve_in, Geom::Coord time, bool first) +{ + //the only reason for this function is the lack of a subdivide function in the Curve class. + //you have to cast to Beziers to be able to use subdivide(t) + unsigned order = curveOrder(curve_in); + Geom::Curve* curve_out = curve_in->duplicate(); + switch (order) + { + //these need to be scoped because of the variable 'c' + case 3: + { + Geom::CubicBezier c = first ? (dynamic_cast (curve_out))->subdivide(time).first : + (dynamic_cast (curve_out))->subdivide(time).second; + if (curve_out) delete curve_out; + curve_out = c.duplicate(); + break; + } + case 2: + { + Geom::QuadraticBezier c = first ? (dynamic_cast(curve_out))->subdivide(time).first : + (dynamic_cast(curve_out))->subdivide(time).second; + if (curve_out) delete curve_out; + curve_out = c.duplicate(); + break; + } + case 1: + { + Geom::BezierCurveN<1> c = first ? (dynamic_cast* >(curve_out))->subdivide(time).first : + (dynamic_cast* >(curve_out))->subdivide(time).second; + if (curve_out) delete curve_out; + curve_out = c.duplicate(); + break; + } + } + return curve_out; +} + +Geom::Piecewise > stretch_along(Geom::Piecewise > pwd2_in, Geom::Path pattern, double width); + +Geom::PathVector LPETaperStroke::doEffect_path(Geom::PathVector const& path_in) +{ + //there is a pretty good chance that people will try to drag the knots + //on top of each other, so block it + + unsigned size = path_in[0].size(); + if (size == return_at_first_cusp(path_in[0]).size()) { + //check to see if the knots were dragged over each other + //if so, reset the end offset + if ( attach_start >= (size - attach_end) ) { + attach_end.param_set_value( size - attach_start ); + } + } + + //don't ever let it be zero + if (attach_start <= 0) { + attach_start.param_set_value( 0.0001 ); + } + if (attach_end <= 0) { + attach_end.param_set_value( 0.0001 ); + } + + /*if (size != return_at_first_cusp(path_in[0]).size()) { //will get to this in a bit + //check to see if either knot was dragged past their allowed amount + volatile unsigned size_p_start = (unsigned)attach_start; + volatile unsigned size_p_end = (unsigned)attach_end; + + //maximum allowed value in either direction is return_at_first_cusp(path_in[0]).size + volatile unsigned allowed_p_start = return_at_first_cusp(path_in[0]).size(); + volatile unsigned allowed_p_end = return_at_first_cusp(path_in[0].reverse()).size(); + + if (size_p_start > allowed_p_start) { + attach_start.param_set_value(allowed_p_start - 0.0001); + } else if (size_p_end > allowed_p_end) { + attach_end.param_set_value(allowed_p_end - 0.0001); + } + }*/ + + //Path::operator () means get point at time t + start_attach_point = return_at_first_cusp(path_in[0])(attach_start); + end_attach_point = return_at_first_cusp(path_in[0].reverse())(attach_end); + Geom::PathVector pathv_out; + + pathv_out = doEffect_simplePath(path_in); + + + //now for the fun stuff. Right? RIGHT? + + //decide on case + + //first case: taper on both sides + if (true/*pathv_out[0].length() != 0.001 && pathv_out[2].length() != 0.001*/) { + Geom::PathVector real_pathv; + + //Construct the pattern + + Geom::PathVector pat_vec = sp_svg_read_pathv("M 1,0 1,1 C 0.5,1 0,0.5 0,0.5 0,0.5 0.5,0 1,0 Z"); + + Geom::Piecewise > pwd2; + pwd2.concat(stretch_along(pathv_out[0].toPwSb(), pat_vec[0], 40)); + + real_pathv.push_back(path_from_piecewise(pwd2, 0.001)[0]); + + Geom::PathVector sht_path; + sht_path.push_back(pathv_out[1]); + sht_path = Outline::outlinePath_extr(sht_path, 40, LINEJOIN_STRAIGHT, butt_straight, 30); + + real_pathv.push_back(sht_path[0]); + + pat_vec = sp_svg_read_pathv("M 0,0 0,1 C 0.5,1 1,0.5 1,0.5 1,0.5 0.5,0 0,0 Z"); + + pwd2 = Geom::Piecewise > (); + pwd2.concat(stretch_along(pathv_out[2].toPwSb(), pat_vec[0], 40)); + real_pathv.push_back(path_from_piecewise(pwd2, 0.001)[0].reverse()); + + //clever union + //Geom::Shape shape1 = Geom::sanitize(Geom::PathVector(1, real_pathv[0])); + //Geom::Shape shape2 = Geom::sanitize(Geom::PathVector(1, real_pathv[1])); + //Geom::Shape shape3 = Geom::boolop(shape1, shape2, Geom::BOOLOP_UNION); + + //shape2 = Geom::sanitize(Geom::PathVector(1, real_pathv[2])); + //shape1 = Geom::boolop(shape3, shape2, Geom::BOOLOP_UNION); + + //real_pathv = Geom::desanitize(shape1); + return real_pathv; + } + + return pathv_out; +} + +//in all cases, this should return a PathVector with three elements. +Geom::PathVector LPETaperStroke::doEffect_simplePath(Geom::PathVector const & path_in) +{ + unsigned size = path_in[0].size(); + + //do subdivision and get out + unsigned loc = (unsigned)attach_start; + Geom::Curve * curve_start = path_in[0] [loc].duplicate(); + + std::vector pathv_out; + Geom::Path path_out = Geom::Path(); + + Geom::Path trimmed_start = Geom::Path(); + Geom::Path trimmed_end = Geom::Path(); + + for (unsigned i = 0; i < loc; i++) { + trimmed_start.append(path_in[0] [i]); + } + + #define OVERLAP 0.001 + + trimmed_start.append(*subdivide_at(curve_start, (attach_start - loc) + OVERLAP, true)); + curve_start = subdivide_at(curve_start, attach_start - loc, false); + + //special case: path is one segment long + //special case: what if the two knots occupy the same segment? + if ((size == 1) || ( size - unsigned(attach_end) - 1 == loc )) + { + Geom::Coord t = Geom::nearest_point(end_attach_point, *curve_start); + //it is just a dumb segment + //we have to do some shifting here because the value changed when we reduced the length + //of the previous segment. + trimmed_end.append(*subdivide_at(curve_start, t - OVERLAP, false)); + for (unsigned j = (size - attach_end) + 1; j < size; j++) { + trimmed_end.append(path_in[0] [j]); + } + + curve_start = subdivide_at(curve_start, t, true); + path_out.append(*curve_start); + pathv_out.push_back(trimmed_start); + pathv_out.push_back(path_out); + pathv_out.push_back(trimmed_end); + return pathv_out; + } + + pathv_out.push_back(trimmed_start); + + //append almost all of the rest of the path, ignore the curves that the knot is past (we'll get to it in a minute) + path_out.append(*curve_start); + + for (unsigned k = loc + 1; k < (size - unsigned(attach_end)) - 1; k++) { + path_out.append(path_in[0] [k]); + } + + //deal with the last segment in a very similar fashion to the first + loc = size - attach_end; + + Geom::Curve * curve_end = path_in[0] [loc].duplicate(); + + Geom::Coord t = Geom::nearest_point(end_attach_point, *curve_end); + + trimmed_end.append(*subdivide_at(curve_end, t - OVERLAP, false)); + curve_end = subdivide_at(curve_end, t, true); + + for (unsigned j = (size - attach_end) + 1; j < size; j++) { + trimmed_end.append(path_in[0] [j]); + } + + path_out.append(*curve_end); + pathv_out.push_back(path_out); + + pathv_out.push_back(trimmed_end); + + if (curve_end) delete curve_end; + if (curve_start) delete curve_start; + return pathv_out; +} + + +//most of the below code is verbatim from Pattern Along Path. However, it needed a little +//tweaking to get it to work right in this case. +Geom::Piecewise > stretch_along(Geom::Piecewise > pwd2_in, Geom::Path pattern, double prop_scale) +{ + using namespace Geom; + + // Don't allow empty path parameter: + if ( pattern.empty() ) { + return pwd2_in; + } + +/* Much credit should go to jfb and mgsloan of lib2geom development for the code below! */ + Piecewise > output; + std::vector > > pre_output; + + D2 > patternd2 = make_cuts_independent(pattern.toPwSb()); + Piecewise x0 = Piecewise(patternd2[0]); + Piecewise y0 = Piecewise(patternd2[1]); + OptInterval pattBndsX = bounds_exact(x0); + OptInterval pattBndsY = bounds_exact(y0); + if (pattBndsX && pattBndsY) { + x0 -= pattBndsX->min(); + y0 -= pattBndsY->middle(); + + double xspace = 0; + double noffset = 0; + double toffset = 0; + /*if (prop_units.get_value() && pattBndsY){ + xspace *= pattBndsX->extent(); + noffset *= pattBndsY->extent(); + toffset *= pattBndsX->extent(); + }*/ + + //Prevent more than 90% overlap... + if (xspace < -pattBndsX->extent()*.9) { + xspace = -pattBndsX->extent()*.9; + } + + y0+=noffset; + + std::vector > > paths_in; + paths_in = split_at_discontinuities(pwd2_in); + + for (unsigned idx = 0; idx < paths_in.size(); idx++){ + Geom::Piecewise > path_i = paths_in[idx]; + Piecewise x = x0; + Piecewise y = y0; + Piecewise > uskeleton = arc_length_parametrization(path_i,2,.1); + uskeleton = remove_short_cuts(uskeleton,.01); + Piecewise > n = rot90(derivative(uskeleton)); + n = force_continuity(remove_short_cuts(n,.1)); + + int nbCopies = 0; + double scaling = 1; + nbCopies = 1; + scaling = (uskeleton.domain().extent() - toffset)/pattBndsX->extent(); + + double pattWidth = pattBndsX->extent() * scaling; + + if (scaling != 1.0) { + x*=scaling; + } + if ( false ) { + y*=(scaling*prop_scale); + } else { + if (prop_scale != 1.0) y *= prop_scale; + } + x += toffset; + + double offs = 0; + for (int i=0; i > output_piece = compose(uskeleton,x+offs)+y*compose(n,x+offs); + std::vector > > splited_output_piece = split_at_discontinuities(output_piece); + pre_output.insert(pre_output.end(), splited_output_piece.begin(), splited_output_piece.end() ); + }else{ + output.concat(compose(uskeleton,x+offs)+y*compose(n,x+offs)); + } + offs+=pattWidth; + } + } + /*if (false){ + pre_output = fuse_nearby_ends(pre_output, fuse_tolerance); + for (unsigned i=0; icreate( desktop, item, knotholder, Inkscape::CTRL_TYPE_UNKNOWN, + _("Start point of the taper"), SP_KNOT_SHAPE_CIRCLE ); + knotholder->add(e); + } + { + KnotHolderEntity *e = new TpS::KnotHolderEntityAttachEnd(this); + e->create( desktop, item, knotholder, Inkscape::CTRL_TYPE_UNKNOWN, + _("End point of the taper"), SP_KNOT_SHAPE_CIRCLE ); + knotholder->add(e); + } +} + +namespace TpS { + void KnotHolderEntityAttachBegin::knot_set(Geom::Point const &p, Geom::Point const &/*origin*/, guint state) + { + using namespace Geom; + + LPETaperStroke* lpe = dynamic_cast(_effect); + + Geom::Point const s = snap_knot_position(p, state); + + SPCurve *curve = SP_PATH(item)->get_curve_for_edit(); + Geom::PathVector pathv = curve->get_pathvector(); + Piecewise > pwd2; + Geom::Path p_in = return_at_first_cusp(pathv[0]); + pwd2.concat(p_in.toPwSb()); + + double t0 = nearest_point(s, pwd2); + lpe->attach_start.param_set_value(t0); + + // FIXME: this should not directly ask for updating the item. It should write to SVG, which triggers updating. + sp_lpe_item_update_patheffect (SP_LPE_ITEM(item), false, true); + } + void KnotHolderEntityAttachEnd::knot_set(Geom::Point const &p, Geom::Point const& /*origin*/, guint state) + { + using namespace Geom; + + LPETaperStroke* lpe = dynamic_cast(_effect); + + Geom::Point const s = snap_knot_position(p, state); + + SPCurve *curve = SP_PATH(item)->get_curve_for_edit(); + Geom::PathVector pathv = curve->get_pathvector(); + Piecewise > pwd2; + Geom::Path p_in = return_at_first_cusp(pathv[0].reverse()); + pwd2.concat(p_in.toPwSb()); + + double t0 = nearest_point(s, pwd2); + lpe->attach_end.param_set_value(t0); + + // FIXME: this should not directly ask for updating the item. It should write to SVG, which triggers updating. + sp_lpe_item_update_patheffect (SP_LPE_ITEM(item), false, true); + } + Geom::Point KnotHolderEntityAttachBegin::knot_get() const + { + LPETaperStroke const * lpe = dynamic_cast (_effect); + return lpe->start_attach_point; + } + Geom::Point KnotHolderEntityAttachEnd::knot_get() const + { + LPETaperStroke const * lpe = dynamic_cast (_effect); + return lpe->end_attach_point; + } +} + + +/* ######################## */ + +} //namespace LivePathEffect +} /* 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 : diff --git a/src/live_effects/lpe-taperstroke.h b/src/live_effects/lpe-taperstroke.h new file mode 100644 index 000000000..f2fe03533 --- /dev/null +++ b/src/live_effects/lpe-taperstroke.h @@ -0,0 +1,73 @@ +/** @file + * @brief Taper Stroke path effect (meant as a replacement for using Power Strokes for tapering) + */ +/* Authors: + * Liam P White + * Copyright (C) 2014 Authors + * + * Released under GNU GPL, read the file 'COPYING' for more information + */ + +#ifndef INKSCAPE_LPE_SKELETON_H +#define INKSCAPE_LPE_SKELETON_H + +#include "live_effects/effect.h" +#include "live_effects/parameter/parameter.h" +#include "live_effects/parameter/enum.h" +#include "live_effects/parameter/vector.h" + +namespace Inkscape { +namespace LivePathEffect { + +namespace TpS { + // we need a separate namespace to avoid clashes with other LPEs + class KnotHolderEntityAttachBegin; + class KnotHolderEntityAttachEnd; +} + +class LPETaperStroke : public Effect { +public: + LPETaperStroke(LivePathEffectObject *lpeobject); + virtual ~LPETaperStroke(); + + virtual Geom::PathVector doEffect_path (Geom::PathVector const& path_in); + Geom::PathVector doEffect_simplePath(Geom::PathVector const& path_in); + + virtual void addKnotHolderEntities(KnotHolder * knotholder, SPDesktop * desktop, SPItem * item); + + friend class TpS::KnotHolderEntityAttachBegin; + friend class TpS::KnotHolderEntityAttachEnd; +private: + ScalarParam attach_start; + ScalarParam attach_end; + ScalarParam smoothing; + EnumParam join_type; + ScalarParam miter_limit; + + Geom::Point start_attach_point; + Geom::Point end_attach_point; + + LPETaperStroke(const LPETaperStroke&); + LPETaperStroke& operator=(const LPETaperStroke&); +}; + +} //namespace LivePathEffect +} //namespace Inkscape + +//because Windoze is stupid +# ifdef WIN32 +# include "lpe-taperstroke.cpp" +# endif + +#endif + +/* + 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 : diff --git a/src/live_effects/pathoutlineprovider.h b/src/live_effects/pathoutlineprovider.h new file mode 100755 index 000000000..8aa2e38ad --- /dev/null +++ b/src/live_effects/pathoutlineprovider.h @@ -0,0 +1,766 @@ +#pragma once + +#include <2geom/path.h> +#include <2geom/circle.h> +#include <2geom/sbasis-to-bezier.h> +#include <2geom/shape.h> +#include <2geom/transforms.h> +#include <2geom/path-sink.h> + +#include +#include + +enum LineJoinType { + LINEJOIN_STRAIGHT, + LINEJOIN_ROUND, + LINEJOIN_POINTY, + LINEJOIN_REFLECTED, + LINEJOIN_EXTRAPOLATED +}; + +namespace Geom +{ + /** + * Refer to: Weisstein, Eric W. "Circle-Circle Intersection." + From MathWorld--A Wolfram Web Resource. + http://mathworld.wolfram.com/Circle-CircleIntersection.html + * + * @return 0 if no intersection + * @return 1 if one circle is contained in the other + * @return 2 if intersections are found (they are written to p0 and p1) + */ + static int circle_circle_intersection(Circle const &circle0, Circle const &circle1, + Point & p0, Point & p1) + { + Point X0 = circle0.center(); + double r0 = circle0.ray(); + Point X1 = circle1.center(); + double r1 = circle1.ray(); + + /* dx and dy are the vertical and horizontal distances between + * the circle centers. + */ + Point D = X1 - X0; + + /* Determine the straight-line distance between the centers. */ + double d = L2(D); + + /* Check for solvability. */ + if (d > (r0 + r1)) + { + /* no solution. circles do not intersect. */ + return 0; + } + if (d <= fabs(r0 - r1)) + { + /* no solution. one circle is contained in the other */ + return 1; + } + + /* 'point 2' is the point where the line through the circle + * intersection points crosses the line between the circle + * centers. + */ + + /* Determine the distance from point 0 to point 2. */ + double a = ((r0*r0) - (r1*r1) + (d*d)) / (2.0 * d) ; + + /* Determine the coordinates of point 2. */ + Point p2 = X0 + D * (a/d); + + /* Determine the distance from point 2 to either of the + * intersection points. + */ + double h = std::sqrt((r0*r0) - (a*a)); + + /* Now determine the offsets of the intersection points from + * point 2. + */ + Point r = (h/d)*rot90(D); + + /* Determine the absolute intersection points. */ + p0 = p2 + r; + p1 = p2 - r; + + return 2; + } + /** + * Find circle that touches inside of the curve, with radius matching the curvature, at time value \c t. + * Because this method internally uses unitTangentAt, t should be smaller than 1.0 (see unitTangentAt). + */ + static Circle touching_circle( D2 const &curve, double t, double tol=0.01 ) + { + D2 dM=derivative(curve); + if ( are_near(L2sq(dM(t)),0.) ) { + dM=derivative(dM); + } + if ( are_near(L2sq(dM(t)),0.) ) { // try second time + dM=derivative(dM); + } + Piecewise > unitv = unitVector(dM,tol); + Piecewise dMlength = dot(Piecewise >(dM),unitv); + Piecewise k = cross(derivative(unitv),unitv); + k = divide(k,dMlength,tol,3); + double curv = k(t); // note that this value is signed + + Geom::Point normal = unitTangentAt(curve, t).cw(); + double radius = 1/curv; + Geom::Point center = curve(t) + radius*normal; + return Geom::Circle(center, fabs(radius)); + } + + static std::vector split_at_cusps(const Geom::Path& in) + { + Geom::PathVector out = Geom::PathVector(); + Geom::Path temp = Geom::Path(); + + for (unsigned path_descr = 0; path_descr < in.size(); path_descr++) + { + temp = Geom::Path(); + temp.append(in[path_descr]); + out.push_back(temp); + } + + return out; + } + + static Geom::CubicBezier sbasis_to_cubicbezier(Geom::D2 const & sbasis_in) + { + std::vector temp; + sbasis_to_bezier(temp, sbasis_in, 4); + return Geom::CubicBezier( temp ); + } + + static boost::optional intersection_point( Geom::Point const & origin_a, Geom::Point const & vector_a, + Geom::Point const & origin_b, Geom::Point const & vector_b) + { + Geom::Coord denom = cross(vector_b, vector_a); + if (!Geom::are_near(denom,0.)){ + Geom::Coord t = (cross(origin_a,vector_b) + cross(vector_b,origin_b)) / denom; + return origin_a + t * vector_a; + } + return boost::none; + } +} + +namespace Outline +{ + + typedef Geom::D2 D2SB; + typedef Geom::Piecewise PWD2; + + static void extrapolate_curves(Geom::Path& path_builder, Geom::Curve* cbc1, Geom::Curve*cbc2, Geom::Point endPt, double miter_limit) +{ + Geom::Crossings cross = Geom::crossings(*cbc1, *cbc2); + if (cross.empty()) + { + Geom::Path pth; + pth.append(*cbc1); + + Geom::Point tang1 = Geom::unitTangentAt(pth.toPwSb()[0], 1); + + pth = Geom::Path(); + pth.append( *cbc2 ); + Geom::Point tang2 = Geom::unitTangentAt(pth.toPwSb()[0], 0); + + + Geom::Circle circle1 = Geom::touching_circle(Geom::reverse(cbc1->toSBasis()), 0.); + Geom::Circle circle2 = Geom::touching_circle(cbc2->toSBasis(), 0); + + Geom::Point points[2]; + int solutions = Geom::circle_circle_intersection(circle1, circle2, points[0], points[1]); + if (solutions == 2) + { + Geom::Point sol(0,0); + if ( dot(tang2,points[0]-endPt) > 0 ) + { + // points[0] is bad, choose points[1] + sol = points[1]; + } + else if ( dot(tang2,points[1]-endPt) > 0 ) { // points[0] could be good, now check points[1] + // points[1] is bad, choose points[0] + sol = points[0]; + } + else + { + // both points are good, choose nearest + sol = ( distanceSq(endPt, points[0]) < distanceSq(endPt, points[1]) ) ? + points[0] : points[1]; + } + Geom::EllipticalArc *arc0 = circle1.arc(cbc1->finalPoint(), 0.5*(cbc1->finalPoint()+sol), sol, true); + Geom::EllipticalArc *arc1 = circle2.arc(sol, 0.5*(sol+endPt), endPt, true); + + if (arc0) + { + path_builder.append (arc0->toSBasis()); + delete arc0; + arc0 = NULL; + } + + if (arc1) + { + path_builder.append (arc1->toSBasis()); + delete arc1; + arc1 = NULL; + } + } + else + { + path_builder.appendNew (endPt); + } + } + else + { + path_builder.appendNew (endPt); + } +} + static Geom::Path half_outline_extrp(const Geom::Path& path_in, double line_width, ButtType linecap_type, double miter_limit) + { + Geom::PathVector pv = split_at_cusps(path_in); + unsigned m; + Path path_outline = Path(); + Path path_tangent = Path(); + + Geom::Point initialPoint; + Geom::Point endPoint; + + Geom::Path path_builder = Geom::Path(); + Geom::PathVector * pathvec; + + //load the first portion in before the loop starts + { + path_outline = Path(); + path_outline.LoadPath(pv[0], Geom::Affine(), false, false); + path_outline.OutsideOutline(&path_tangent, line_width / 2, join_straight, linecap_type, 10); + //now half of first cusp has been loaded + + pathvec = path_tangent.MakePathVector(); + path_tangent = Path(); + + //instead of array accessing twice, dereferencing used for clarity + initialPoint = (*pathvec)[0].initialPoint(); + + path_builder.start(initialPoint); + path_builder.append( (*pathvec)[0] ); + + path_outline = Path(); + path_outline.LoadPath(pv[1], Geom::Affine(), false, false); + path_outline.OutsideOutline(&path_tangent, line_width / 2, join_straight, linecap_type, 10); + + delete pathvec; pathvec = NULL; + pathvec = path_tangent.MakePathVector(); + path_tangent = Path(); + + Geom::Curve *cbc1 = path_builder[path_builder.size() - 1].duplicate(); + Geom::Curve *cbc2 = (*pathvec)[0][0].duplicate(); + + extrapolate_curves(path_builder, cbc1, cbc2, (*pathvec)[0].initialPoint(), miter_limit ); + + path_builder.append( (*pathvec)[0] ); + + //always set pointers null after deleting + delete pathvec; pathvec = NULL; + delete cbc1; delete cbc2; cbc1 = cbc2 = NULL; + } + + for (m = 2; m < pv.size(); m++) + { + path_outline = Path(); + path_outline.LoadPath(pv[m], Geom::Affine(), false, false); + path_outline.OutsideOutline(&path_tangent, line_width / 2, join_straight, linecap_type, 10); + + delete pathvec; pathvec = NULL; + pathvec = path_tangent.MakePathVector(); + + Geom::Curve *cbc1 = path_builder[path_builder.size() - 1].duplicate(); + Geom::Curve *cbc2 = (*pathvec)[0][0].duplicate(); + + extrapolate_curves(path_builder, cbc1, cbc2, (*pathvec)[0].initialPoint(), miter_limit ); + path_builder.append( (*pathvec)[0] ); + + delete pathvec; pathvec = NULL; + delete cbc1; delete cbc2; cbc1 = cbc2 = NULL; + } + + return path_builder; + } + + //Create a reflected outline join. + //Note: it is generally recommended to let half_outline do this for you! + //path_builder: the path to append the curves to + //cbc1: the curve before the join + //cbc2: the curve after the join + //endPt: the point to end at + //miter_limit: the miter parameter + static void reflect_curves(Geom::Path& path_builder, Geom::Curve* cbc1, Geom::Curve* cbc2, Geom::Point endPt, double miter_limit) + { + //the most important work for the reflected join is done here + + //determine where we are in the path. If we're on the inside, ignore + //and just lineTo. On the outside, we'll do a little reflection magic :) + Geom::Crossings cross = Geom::crossings(*cbc1, *cbc2); + if (cross.empty()) + { + //probably on the outside of the corner + Geom::Path pth; + pth.append(*cbc1); + + Geom::Point tang1 = Geom::unitTangentAt(pth.toPwSb()[0], 1); + + //reflect curves along the bevel + D2SB newcurve1 = pth.toPwSb()[0] * + Geom::reflection ( -Geom::rot90(tang1) , + cbc1->finalPoint() ); + + Geom::CubicBezier bzr1 = sbasis_to_cubicbezier(Geom::reverse(newcurve1)); + + pth = Geom::Path(); + pth.append( *cbc2 ); + Geom::Point tang2 = Geom::unitTangentAt(pth.toPwSb()[0], 0); + + D2SB newcurve2 = pth.toPwSb()[0] * + Geom::reflection ( -Geom::rot90(tang2) , + cbc2->initialPoint() ); + Geom::CubicBezier bzr2 = sbasis_to_cubicbezier(Geom::reverse(newcurve2)); + + cross = Geom::crossings(bzr1, bzr2); + if ( cross.empty() ) + { + //std::cout << "Oops, no crossings!" << std::endl; + //curves didn't cross; default to miter + /*boost::optional p = intersection_point (cbc1->finalPoint(), tang1, + cbc2->initialPoint(), tang2); + if (p) + { + path_builder.appendNew (*p); + }*/ + //bevel + path_builder.appendNew( endPt ); + } + else + { + //join + std::pair sub1 = bzr1.subdivide(cross[0].ta); + std::pair sub2 = bzr2.subdivide(cross[0].tb); + + //@TODO joins have a strange tendency to cross themselves twice. Check this. + + //sections commented out are for general stability + path_builder.appendNew (sub1.first[1], sub1.first[2], /*sub1.first[3]*/ sub2.second[0] ); + path_builder.appendNew (sub2.second[1], sub2.second[2], /*sub2.second[3]*/ endPt ); + } + } + else // cross.empty() + { + //probably on the inside of the corner + path_builder.appendNew ( endPt ); + } + } + + /** @brief Converts a path to one half of an outline. + * path_in: The input path to use. (To create the other side use path_in.reverse() ) + * line_width: the line width to use (usually you want to divide this by 2) + * linecap_type: (not used here) the cap to apply. Passed to libvarot. + * miter_limit: the miter parameter + */ + static Geom::Path half_outline(const Geom::Path& path_in, double line_width, ButtType linecap_type, double miter_limit) + { + Geom::PathVector pv = split_at_cusps(path_in); + unsigned m; + Path path_outline = Path(); + Path path_tangent = Path(); + //needed for closing the path + Geom::Point initialPoint; + Geom::Point endPoint; + + //some issues prevented me from using a PathBuilder here + //it seems like PathBuilder::peek() gave me a null reference exception + //and I was unable to get a stack trace on Windows, so had to switch to Linux + //to see what the hell was wrong. :( + //I wasted five hours opening it in IDAPro, VS2012, and GDB Windows + + /*Program received signal SIGSEGV, Segmentation fault. + 0x00000000006539ac in get_curves (this=0x0) + at /usr/include/c++/4.6/bits/locale_facets.h:1077 + 1077 { return __c; } + */ + + Geom::Path path_builder = Geom::Path(); + Geom::PathVector * pathvec; + + //load the first portion in before the loop starts + { + path_outline = Path(); + path_outline.LoadPath(pv[0], Geom::Affine(), false, false); + path_outline.OutsideOutline(&path_tangent, line_width / 2, join_straight, linecap_type, 10); + //now half of first cusp has been loaded + + pathvec = path_tangent.MakePathVector(); + path_tangent = Path(); + + //instead of array accessing twice, dereferencing used for clarity + initialPoint = (*pathvec)[0].initialPoint(); + + path_builder.start(initialPoint); + path_builder.append( (*pathvec)[0] ); + + path_outline = Path(); + path_outline.LoadPath(pv[1], Geom::Affine(), false, false); + path_outline.OutsideOutline(&path_tangent, line_width / 2, join_straight, linecap_type, 10); + + delete pathvec; pathvec = NULL; + pathvec = path_tangent.MakePathVector(); + path_tangent = Path(); + + Geom::Curve *cbc1 = path_builder[path_builder.size() - 1].duplicate(); + Geom::Curve *cbc2 = (*pathvec)[0][0].duplicate(); + + reflect_curves(path_builder, cbc1, cbc2, (*pathvec)[0].initialPoint(), miter_limit ); + + path_builder.append( (*pathvec)[0] ); + + //always set pointers null after deleting + delete pathvec; pathvec = NULL; + delete cbc1; delete cbc2; cbc1 = cbc2 = NULL; + } + + for (m = 2; m < pv.size(); m++) + { + path_outline = Path(); + path_outline.LoadPath(pv[m], Geom::Affine(), false, false); + path_outline.OutsideOutline(&path_tangent, line_width / 2, join_straight, linecap_type, 10); + + delete pathvec; pathvec = NULL; + pathvec = path_tangent.MakePathVector(); + + Geom::Curve *cbc1 = path_builder[path_builder.size() - 1].duplicate(); + Geom::Curve *cbc2 = (*pathvec)[0][0].duplicate(); + + reflect_curves(path_builder, cbc1, cbc2, (*pathvec)[0].initialPoint(), miter_limit ); + path_builder.append( (*pathvec)[0] ); + + delete pathvec; pathvec = NULL; + delete cbc1; delete cbc2; cbc1 = cbc2 = NULL; + } + + return path_builder; + } + + static Geom::PathVector outlinePath(const Geom::PathVector& path_in, double line_width, JoinType join, ButtType butt, double miter_lim) + { + Path p = Path(); + Path outlinepath = Path(); + for (unsigned i = 0; i < path_in.size(); i++) + { + p.LoadPath(path_in[i], Geom::Affine(), false, ( (i==0) ? false : true)); + } + + Geom::PathVector path_out; + for (unsigned lmnop = 0; lmnop < path_in.size(); lmnop++) + { + if (path_in[lmnop].size() > 1) + { + Geom::Path p_init; + Geom::Path p_rev; + Geom::PathBuilder pb = Geom::PathBuilder(); + + if ( !path_in[lmnop].closed() ) + { + p_init = Outline::half_outline( path_in[lmnop], -line_width, butt, + miter_lim ); + p_rev = Outline::half_outline( path_in[lmnop].reverse(), -line_width, butt, + miter_lim ); + + pb.moveTo(p_init.initialPoint() ); + pb.append(p_init); + + //cap + if (butt == butt_straight) { + pb.lineTo(p_rev.initialPoint() ); + } else if (butt == butt_round) { + pb.arcTo((-line_width) / 2, (-line_width) / 2, 0., true, true, p_rev.initialPoint() ); + } else if (butt == butt_square) { + //don't know what to do + pb.lineTo(p_rev.initialPoint() ); + } else if (butt == butt_pointy) { + //don't know what to do + pb.lineTo(p_rev.initialPoint() ); + } + + pb.append(p_rev); + + if (butt == butt_straight) { + pb.lineTo(p_init.initialPoint() ); + } else if (butt == butt_round) { + pb.arcTo((-line_width) / 2, (-line_width) / 2, 0., true, true, p_init.initialPoint() ); + } else if (butt == butt_square) { + //don't know what to do + pb.lineTo(p_init.initialPoint() ); + } else if (butt == butt_pointy) { + //don't know what to do + //Geom::Point end_deriv = Geom::unitTangentAt( Geom::reverse(path_in[lmnop].toPwSb()[path_in[lmnop].size()]), 0); + //double radius = 0.5 * Geom::distance(path_in[lmnop].finalPoint(), p_rev.initialPoint()); + + pb.lineTo(p_init.initialPoint() ); + } + } + else + { + //final join + //refer to half_outline for documentation + Geom::Path p_almost = path_in[lmnop]; + p_almost.appendNew ( path_in[lmnop].initialPoint() ); + p_init = Outline::half_outline( p_almost, -line_width, butt, + miter_lim ); + p_rev = Outline::half_outline( p_almost.reverse(), -line_width, butt, + miter_lim ); + p.LoadPath(path_in[lmnop], Geom::Affine(), false, false); + + //this is a kludge, because I can't find how to make this work properly + bool lastIsLinear = ( (Geom::distance(path_in[lmnop].finalPoint(), + path_in[lmnop] [path_in[lmnop].size() - 1].finalPoint())) == + (path_in[lmnop] [path_in[lmnop].size()].length())); + + p_almost = p_init; + if (lastIsLinear) + { + p_almost.erase_last(); p_almost.erase_last(); + } + + //outside test + Geom::Curve* cbc1 = p_almost[p_almost.size() - 1].duplicate(); + Geom::Curve* cbc2 = p_almost[0].duplicate(); + + Geom::Crossings cross = Geom::crossings(*cbc1, *cbc2); + + if (cross.empty()) + { + //this is the outside path + + //reuse the old one + p_init = p_almost; + Outline::reflect_curves(p_init, cbc1, cbc2, p_almost.initialPoint(), miter_lim ); + pb.moveTo(p_init.initialPoint()); pb.append(p_init); + } + else + { + //inside, carry on :-) + pb.moveTo(p_almost.initialPoint()); pb.append(p_almost); + } + + p_almost = p_rev; + if (lastIsLinear) + { + p_almost.erase(p_almost.begin() ); + p_almost.erase(p_almost.begin() ); + } + + delete cbc1; delete cbc2; cbc1 = cbc2 = NULL; + + cbc1 = p_almost[p_almost.size() - 1].duplicate(); + cbc2 = p_almost[0].duplicate(); + + cross = Geom::crossings(*cbc1, *cbc2); + + if (cross.empty()) + { + //outside path + + p_init = p_almost; + reflect_curves(p_init, cbc1, cbc2, p_almost.initialPoint(), miter_lim ); + pb.moveTo(p_init.initialPoint()); pb.append(p_init); + } + else + { + //inside + pb.moveTo(p_almost.initialPoint()); pb.append(p_almost); + } + delete cbc1; delete cbc2; cbc1 = cbc2 = NULL; + } + //pb.closePath(); + pb.flush(); + Geom::PathVector pv_np = pb.peek(); + //hack + for (unsigned abcd = 0; abcd < pv_np.size(); abcd++) + { + path_out.push_back( pv_np[abcd] ); + } + } + else + { + p.LoadPath(path_in[lmnop], Geom::Affine(), false, false); + p.Outline(&outlinepath, line_width / 2, join, butt, miter_lim); + std::vector *pv_p = outlinepath.MakePathVector(); + //hack + path_out.push_back( (*pv_p)[0].reverse() ); + delete pv_p; + } + } + return path_out; + } + static Geom::PathVector outlinePath_extr(const Geom::PathVector& path_in, double line_width, LineJoinType join, ButtType butt, double miter_lim) + { + Path p = Path(); + Path outlinepath = Path(); + for (unsigned i = 0; i < path_in.size(); i++) + { + p.LoadPath(path_in[i], Geom::Affine(), false, ( (i==0) ? false : true)); + } + + Geom::PathVector path_out; + for (unsigned lmnop = 0; lmnop < path_in.size(); lmnop++) + { + if (path_in[lmnop].size() > 1) + { + Geom::Path p_init; + Geom::Path p_rev; + Geom::PathBuilder pb = Geom::PathBuilder(); + + if ( !path_in[lmnop].closed() ) + { + p_init = Outline::half_outline_extrp( path_in[lmnop], -line_width, butt, + miter_lim ); + p_rev = Outline::half_outline_extrp( path_in[lmnop].reverse(), -line_width, butt, + miter_lim ); + + pb.moveTo(p_init.initialPoint() ); + pb.append(p_init); + + //cap + if (butt == butt_straight) { + pb.lineTo(p_rev.initialPoint() ); + } else if (butt == butt_round) { + pb.arcTo((-line_width) / 2, (-line_width) / 2, 0., true, true, p_rev.initialPoint() ); + } else if (butt == butt_square) { + //don't know what to do + pb.lineTo(p_rev.initialPoint() ); + } else if (butt == butt_pointy) { + //don't know what to do + pb.lineTo(p_rev.initialPoint() ); + } + + pb.append(p_rev); + + if (butt == butt_straight) { + pb.lineTo(p_init.initialPoint() ); + } else if (butt == butt_round) { + pb.arcTo((-line_width) / 2, (-line_width) / 2, 0., true, true, p_init.initialPoint() ); + } else if (butt == butt_square) { + //don't know what to do + pb.lineTo(p_init.initialPoint() ); + } else if (butt == butt_pointy) { + //don't know what to do + //Geom::Point end_deriv = Geom::unitTangentAt( Geom::reverse(path_in[lmnop].toPwSb()[path_in[lmnop].size()]), 0); + //double radius = 0.5 * Geom::distance(path_in[lmnop].finalPoint(), p_rev.initialPoint()); + + pb.lineTo(p_init.initialPoint() ); + } + } + else + { + //final join + //refer to half_outline for documentation + Geom::Path p_almost = path_in[lmnop]; + p_almost.appendNew ( path_in[lmnop].initialPoint() ); + p_init = Outline::half_outline_extrp( p_almost, -line_width, butt, + miter_lim ); + p_rev = Outline::half_outline_extrp( p_almost.reverse(), -line_width, butt, + miter_lim ); + p.LoadPath(path_in[lmnop], Geom::Affine(), false, false); + + //this is a kludge, because I can't find how to make this work properly + bool lastIsLinear = ( (Geom::distance(path_in[lmnop].finalPoint(), + path_in[lmnop] [path_in[lmnop].size() - 1].finalPoint())) == + (path_in[lmnop] [path_in[lmnop].size()].length())); + + p_almost = p_init; + if (lastIsLinear) + { + p_almost.erase_last(); p_almost.erase_last(); + } + + //outside test + Geom::Curve* cbc1 = p_almost[p_almost.size() - 1].duplicate(); + Geom::Curve* cbc2 = p_almost[0].duplicate(); + + Geom::Crossings cross = Geom::crossings(*cbc1, *cbc2); + + if (cross.empty()) + { + //this is the outside path + + //reuse the old one + p_init = p_almost; + Outline::extrapolate_curves(p_init, cbc1, cbc2, p_almost.initialPoint(), miter_lim ); + pb.moveTo(p_init.initialPoint()); pb.append(p_init); + } + else + { + //inside, carry on :-) + pb.moveTo(p_almost.initialPoint()); pb.append(p_almost); + } + + p_almost = p_rev; + if (lastIsLinear) + { + p_almost.erase(p_almost.begin() ); + p_almost.erase(p_almost.begin() ); + } + + delete cbc1; delete cbc2; cbc1 = cbc2 = NULL; + + cbc1 = p_almost[p_almost.size() - 1].duplicate(); + cbc2 = p_almost[0].duplicate(); + + cross = Geom::crossings(*cbc1, *cbc2); + + if (cross.empty()) + { + //outside path + + p_init = p_almost; + extrapolate_curves(p_init, cbc1, cbc2, p_almost.initialPoint(), miter_lim ); + pb.moveTo(p_init.initialPoint()); pb.append(p_init); + } + else + { + //inside + pb.moveTo(p_almost.initialPoint()); pb.append(p_almost); + } + delete cbc1; delete cbc2; cbc1 = cbc2 = NULL; + } + //pb.closePath(); + pb.flush(); + Geom::PathVector pv_np = pb.peek(); + //hack + for (unsigned abcd = 0; abcd < pv_np.size(); abcd++) + { + path_out.push_back( pv_np[abcd] ); + } + } + else + { + p.LoadPath(path_in[lmnop], Geom::Affine(), false, false); + p.Outline(&outlinepath, line_width / 2, join_pointy, butt, miter_lim); + std::vector *pv_p = outlinepath.MakePathVector(); + //hack + path_out.push_back( (*pv_p)[0].reverse() ); + delete pv_p; + } + } + return path_out; + } + + +} // namespace Outline + +/* + 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:encoding=utf-8:textwidth=99 : diff --git a/src/ui/clipboard.cpp b/src/ui/clipboard.cpp index 8e2502545..2dabf1884 100644 --- a/src/ui/clipboard.cpp +++ b/src/ui/clipboard.cpp @@ -601,6 +601,12 @@ Glib::ustring ClipboardManagerImpl::getPathParameter(SPDesktop* desktop) */ Glib::ustring ClipboardManagerImpl::getShapeOrTextObjectId(SPDesktop *desktop) { + //https://bugs.launchpad.net/inkscape/+bug/1293979 + //basically, when we do a depth-first search, we're stopping + //at the first object to be or . + //but that could then return the id of the object's + //clip path or mask, not the original path! + SPDocument *tempdoc = _retrieveClipboard(); // any target will do here if ( tempdoc == NULL ) { _userWarn(desktop, _("Nothing on the clipboard.")); @@ -608,6 +614,9 @@ Glib::ustring ClipboardManagerImpl::getShapeOrTextObjectId(SPDesktop *desktop) } Inkscape::XML::Node *root = tempdoc->getReprRoot(); + //1293979: strip out the defs of the document + root->removeChild(tempdoc->getDefs()->getRepr()); + Inkscape::XML::Node *repr = sp_repr_lookup_name(root, "svg:path", -1); // unlimited search depth if ( repr == NULL ) { repr = sp_repr_lookup_name(root, "svg:text", -1); -- cgit v1.2.3 From ba99347e1308e6d183aaaf6e8d5f65cce4f4b74b Mon Sep 17 00:00:00 2001 From: "Liam P. White" Date: Tue, 18 Mar 2014 21:00:36 -0600 Subject: Fix a compiler error on Windows (bzr r13090.1.27) --- src/live_effects/effect.cpp | 2 +- src/live_effects/lpe-taperstroke.cpp | 26 ++++++++++++++------------ src/live_effects/lpe-taperstroke.h | 6 +----- 3 files changed, 16 insertions(+), 18 deletions(-) (limited to 'src') diff --git a/src/live_effects/effect.cpp b/src/live_effects/effect.cpp index d6840e5b8..337fe631f 100644 --- a/src/live_effects/effect.cpp +++ b/src/live_effects/effect.cpp @@ -5,7 +5,7 @@ * Released under GNU GPL, read the file 'COPYING' for more information */ -//#define LPE_ENABLE_TEST_EFFECTS //uncomment for toy effects +#define LPE_ENABLE_TEST_EFFECTS //uncomment for toy effects #ifdef HAVE_CONFIG_H # include "config.h" diff --git a/src/live_effects/lpe-taperstroke.cpp b/src/live_effects/lpe-taperstroke.cpp index e6eed3abe..2cdc09376 100644 --- a/src/live_effects/lpe-taperstroke.cpp +++ b/src/live_effects/lpe-taperstroke.cpp @@ -55,6 +55,7 @@ static const Util::EnumDataConverter JoinTypeConverter(JoinType, sizeo LPETaperStroke::LPETaperStroke(LivePathEffectObject *lpeobject) : Effect(lpeobject), + line_width(_("Stroke width"), _("The (non-tapered) width of the path"), "stroke_width", &wr, this, 3), attach_start(_("Start offset"), _("Taper distance from path start"), "attach_start", &wr, this, 0.2), attach_end(_("End offset"), _("The ending position of the taper"), "end_offset", &wr, this, 0.2), smoothing(_("Taper smoothing"), _("Amount of smoothing to apply to the tapers"), "smoothing", &wr, this, 0.2), @@ -67,7 +68,9 @@ LPETaperStroke::LPETaperStroke(LivePathEffectObject *lpeobject) : attach_start.param_set_digits(3); attach_end.param_set_digits(3); - + + + registerParameter( dynamic_cast(&line_width) ); registerParameter( dynamic_cast(&attach_start) ); registerParameter( dynamic_cast(&attach_end) ); registerParameter( dynamic_cast(&smoothing) ); @@ -235,31 +238,30 @@ Geom::PathVector LPETaperStroke::doEffect_path(Geom::PathVector const& path_in) //now for the fun stuff. Right? RIGHT? - //decide on case - - //first case: taper on both sides - if (true/*pathv_out[0].length() != 0.001 && pathv_out[2].length() != 0.001*/) { + if (true) { Geom::PathVector real_pathv; - //Construct the pattern - - Geom::PathVector pat_vec = sp_svg_read_pathv("M 1,0 1,1 C 0.5,1 0,0.5 0,0.5 0,0.5 0.5,0 1,0 Z"); + //Construct the pattern (pat_str stands for pattern string) + char* pat_str = new char[200]; + sprintf(pat_str, "M 1,0 1,1 C %5.5f,1 0,0.5 0,0.5 0,0.5 %5.5f,0 1,0 Z", (double)smoothing, (double)smoothing); + Geom::PathVector pat_vec = sp_svg_read_pathv(pat_str); Geom::Piecewise > pwd2; - pwd2.concat(stretch_along(pathv_out[0].toPwSb(), pat_vec[0], 40)); + pwd2.concat(stretch_along(pathv_out[0].toPwSb(), pat_vec[0], line_width)); real_pathv.push_back(path_from_piecewise(pwd2, 0.001)[0]); Geom::PathVector sht_path; sht_path.push_back(pathv_out[1]); - sht_path = Outline::outlinePath_extr(sht_path, 40, LINEJOIN_STRAIGHT, butt_straight, 30); + sht_path = Outline::outlinePath_extr(sht_path, line_width, LINEJOIN_STRAIGHT, butt_straight, miter_limit); real_pathv.push_back(sht_path[0]); - pat_vec = sp_svg_read_pathv("M 0,0 0,1 C 0.5,1 1,0.5 1,0.5 1,0.5 0.5,0 0,0 Z"); + sprintf(pat_str, "M 0,0 0,1 C %5.5f,1 1,0.5 1,0.5 1,0.5 %5.5f,0 0,0 Z", (double)smoothing, (double)smoothing); + pat_vec = sp_svg_read_pathv(pat_str); pwd2 = Geom::Piecewise > (); - pwd2.concat(stretch_along(pathv_out[2].toPwSb(), pat_vec[0], 40)); + pwd2.concat(stretch_along(pathv_out[2].toPwSb(), pat_vec[0], line_width)); real_pathv.push_back(path_from_piecewise(pwd2, 0.001)[0].reverse()); //clever union diff --git a/src/live_effects/lpe-taperstroke.h b/src/live_effects/lpe-taperstroke.h index f2fe03533..7cb8bc85e 100644 --- a/src/live_effects/lpe-taperstroke.h +++ b/src/live_effects/lpe-taperstroke.h @@ -38,6 +38,7 @@ public: friend class TpS::KnotHolderEntityAttachBegin; friend class TpS::KnotHolderEntityAttachEnd; private: + ScalarParam line_width; ScalarParam attach_start; ScalarParam attach_end; ScalarParam smoothing; @@ -54,11 +55,6 @@ private: } //namespace LivePathEffect } //namespace Inkscape -//because Windoze is stupid -# ifdef WIN32 -# include "lpe-taperstroke.cpp" -# endif - #endif /* -- cgit v1.2.3 From 9a04c985ec628dc749a8a82d94bcf47d482a4f63 Mon Sep 17 00:00:00 2001 From: "Liam P. White" Date: Thu, 20 Mar 2014 17:09:57 -0400 Subject: Fix a linker error ("static") (hopefully) Resolve compiler errors with GTK3+ (bzr r13090.1.28) --- src/live_effects/Makefile_insert | 1 + src/live_effects/effect.cpp | 2 +- src/live_effects/lpe-taperstroke.cpp | 162 ++++-- src/live_effects/lpe-taperstroke.h | 9 +- src/live_effects/pathoutlineprovider.cpp | 840 +++++++++++++++++++++++++++++++ src/live_effects/pathoutlineprovider.h | 791 +---------------------------- src/ui/dialog/objects.cpp | 3 +- 7 files changed, 999 insertions(+), 809 deletions(-) create mode 100755 src/live_effects/pathoutlineprovider.cpp mode change 100755 => 100644 src/live_effects/pathoutlineprovider.h (limited to 'src') diff --git a/src/live_effects/Makefile_insert b/src/live_effects/Makefile_insert index b19f417ae..ac7c33e2f 100644 --- a/src/live_effects/Makefile_insert +++ b/src/live_effects/Makefile_insert @@ -93,6 +93,7 @@ ink_common_sources += \ live_effects/lpe-fill-between-many.h \ live_effects/lpe-ellipse_5pts.cpp \ live_effects/lpe-ellipse_5pts.h \ + live_effects/pathoutlineprovider.cpp \ live_effects/lpe-jointype.cpp \ live_effects/lpe-jointype.h \ live_effects/lpe-taperstroke.cpp \ diff --git a/src/live_effects/effect.cpp b/src/live_effects/effect.cpp index 337fe631f..d6840e5b8 100644 --- a/src/live_effects/effect.cpp +++ b/src/live_effects/effect.cpp @@ -5,7 +5,7 @@ * Released under GNU GPL, read the file 'COPYING' for more information */ -#define LPE_ENABLE_TEST_EFFECTS //uncomment for toy effects +//#define LPE_ENABLE_TEST_EFFECTS //uncomment for toy effects #ifdef HAVE_CONFIG_H # include "config.h" diff --git a/src/live_effects/lpe-taperstroke.cpp b/src/live_effects/lpe-taperstroke.cpp index 2cdc09376..a862417d7 100644 --- a/src/live_effects/lpe-taperstroke.cpp +++ b/src/live_effects/lpe-taperstroke.cpp @@ -13,11 +13,20 @@ #include "live_effects/lpe-taperstroke.h" -// You might need to include other 2geom files. You can add them here: #include <2geom/path.h> #include <2geom/shape.h> +#include <2geom/path.h> +#include <2geom/circle.h> +#include <2geom/sbasis-to-bezier.h> #include "pathoutlineprovider.h" #include "display/curve.h" +#include "sp-shape.h" +#include "style.h" +#include "xml/repr.h" +#include "sp-paint-server.h" +#include "svg/svg-color.h" +#include "desktop-style.h" +#include "svg/css-ostringstream.h" #include "svg/svg.h" //#include @@ -58,7 +67,7 @@ LPETaperStroke::LPETaperStroke(LivePathEffectObject *lpeobject) : line_width(_("Stroke width"), _("The (non-tapered) width of the path"), "stroke_width", &wr, this, 3), attach_start(_("Start offset"), _("Taper distance from path start"), "attach_start", &wr, this, 0.2), attach_end(_("End offset"), _("The ending position of the taper"), "end_offset", &wr, this, 0.2), - smoothing(_("Taper smoothing"), _("Amount of smoothing to apply to the tapers"), "smoothing", &wr, this, 0.2), + smoothing(_("Taper smoothing"), _("Amount of smoothing to apply to the tapers"), "smoothing", &wr, this, 0.5), join_type(_("Join type"), _("Join type for non-smooth nodes"), "jointype", JoinTypeConverter, &wr, this, LINEJOIN_EXTRAPOLATED), miter_limit(_("Miter limit"), _("Limit for miter joins"), "miter_limit", &wr, this, 30.) { @@ -83,21 +92,93 @@ LPETaperStroke::~LPETaperStroke() } -unsigned curveOrder (const Geom::Curve* curve_in) +//from LPEPowerStroke -- sets fill if stroke color because we will +//be converting to a fill to make the new join. + +void LPETaperStroke::doOnApply(SPLPEItem const* lpeitem) { - using namespace Geom; - //cast it - const CubicBezier *cbc = dynamic_cast(curve_in); - if (cbc) return 3; - const QuadraticBezier * qbc = dynamic_cast(curve_in); - if (qbc) return 2; - const BezierCurveN<1U> * lbc = dynamic_cast *>(curve_in); - if (lbc) return 1; - //BezierCurveN<0> * dbc = dynamic_cast *> (curve_in); - return 0; + if (SP_IS_SHAPE(lpeitem)) { + SPLPEItem* item = const_cast(lpeitem); + double width = (lpeitem && lpeitem->style) ? lpeitem->style->stroke_width.computed : 1.; + + SPCSSAttr *css = sp_repr_css_attr_new (); + if (lpeitem->style->stroke.isSet()) { + if (lpeitem->style->stroke.isPaintserver()) { + SPPaintServer * server = lpeitem->style->getStrokePaintServer(); + if (server) { + Glib::ustring str; + str += "url(#"; + str += server->getId(); + str += ")"; + sp_repr_css_set_property (css, "fill", str.c_str()); + } + } else if (lpeitem->style->stroke.isColor()) { + gchar c[64]; + sp_svg_write_color (c, sizeof(c), lpeitem->style->stroke.value.color.toRGBA32(SP_SCALE24_TO_FLOAT(lpeitem->style->stroke_opacity.value))); + sp_repr_css_set_property (css, "fill", c); + } else { + sp_repr_css_set_property (css, "fill", "none"); + } + } else { + sp_repr_css_unset_property (css, "fill"); + } + + sp_repr_css_set_property(css, "stroke", "none"); + + sp_desktop_apply_css_recursive(item, css, true); + sp_repr_css_attr_unref (css); + + line_width.param_set_value(width); + } else { + g_warning("LPE Join Type can only be applied to paths (not groups)."); + } } -Geom::Path return_at_first_cusp (Geom::Path const & path_in, double smooth_tolerance = 0.01) +//from LPEPowerStroke -- sets stroke color from existing fill color + +void LPETaperStroke::doOnRemove(SPLPEItem const* lpeitem) +{ + + if (SP_IS_SHAPE(lpeitem)) { + SPLPEItem *item = const_cast(lpeitem); + + SPCSSAttr *css = sp_repr_css_attr_new (); + if (lpeitem->style->fill.isSet()) { + if (lpeitem->style->fill.isPaintserver()) { + SPPaintServer * server = lpeitem->style->getFillPaintServer(); + if (server) { + Glib::ustring str; + str += "url(#"; + str += server->getId(); + str += ")"; + sp_repr_css_set_property (css, "stroke", str.c_str()); + } + } else if (lpeitem->style->fill.isColor()) { + gchar c[64]; + sp_svg_write_color (c, sizeof(c), lpeitem->style->stroke.value.color.toRGBA32(SP_SCALE24_TO_FLOAT(lpeitem->style->stroke_opacity.value))); + sp_repr_css_set_property (css, "stroke", c); + } else { + sp_repr_css_set_property (css, "stroke", "none"); + } + } else { + sp_repr_css_unset_property (css, "stroke"); + } + + Inkscape::CSSOStringStream os; + os << fabs(line_width); + sp_repr_css_set_property (css, "stroke-width", os.str().c_str()); + + sp_repr_css_set_property(css, "fill", "none"); + + sp_desktop_apply_css_recursive(item, css, true); + sp_repr_css_attr_unref (css); + item->updateRepr(); + } +} + +//actual effect impl here + +Geom::Path return_at_first_cusp (Geom::Path const & path_in, double smooth_tolerance = 0.05) { Geom::Path path_out = Geom::Path(); @@ -108,7 +189,7 @@ Geom::Path return_at_first_cusp (Geom::Path const & path_in, double smooth_toler break; //determine order of curve - int order = curveOrder(&path_in[i]); + int order = Outline::bezierOrder(&path_in[i]); Geom::Point start_point; Geom::Point cross_point = path_in[i].finalPoint(); @@ -131,7 +212,7 @@ Geom::Path return_at_first_cusp (Geom::Path const & path_in, double smooth_toler start_point = path_in[i].initialPoint(); } - order = curveOrder(&path_in[i+1]); + order = Outline::bezierOrder(&path_in[i+1]); switch (order) { @@ -155,7 +236,7 @@ Geom::Curve * subdivide_at(const Geom::Curve* curve_in, Geom::Coord time, bool f { //the only reason for this function is the lack of a subdivide function in the Curve class. //you have to cast to Beziers to be able to use subdivide(t) - unsigned order = curveOrder(curve_in); + unsigned order = Outline::bezierOrder(curve_in); Geom::Curve* curve_out = curve_in->duplicate(); switch (order) { @@ -211,22 +292,25 @@ Geom::PathVector LPETaperStroke::doEffect_path(Geom::PathVector const& path_in) if (attach_end <= 0) { attach_end.param_set_value( 0.0001 ); } + + //don't let it be integer + if (double(unsigned(attach_start)) == attach_start) { + attach_start.param_set_value(attach_start - 0.0001); + } + if (double(unsigned(attach_end)) == attach_end) { + attach_end.param_set_value(attach_end - 0.0001); + } - /*if (size != return_at_first_cusp(path_in[0]).size()) { //will get to this in a bit - //check to see if either knot was dragged past their allowed amount - volatile unsigned size_p_start = (unsigned)attach_start; - volatile unsigned size_p_end = (unsigned)attach_end; - - //maximum allowed value in either direction is return_at_first_cusp(path_in[0]).size - volatile unsigned allowed_p_start = return_at_first_cusp(path_in[0]).size(); - volatile unsigned allowed_p_end = return_at_first_cusp(path_in[0].reverse()).size(); - - if (size_p_start > allowed_p_start) { - attach_start.param_set_value(allowed_p_start - 0.0001); - } else if (size_p_end > allowed_p_end) { - attach_end.param_set_value(allowed_p_end - 0.0001); - } - }*/ + unsigned allowed_start = return_at_first_cusp(path_in[0]).size(); + + unsigned allowed_end = return_at_first_cusp(path_in[0].reverse()).size(); + + if ((unsigned)attach_start >= allowed_start) { + attach_start.param_set_value((double)allowed_start - 0.0001); + } + if ((unsigned)attach_end >= allowed_end) { + attach_end.param_set_value((double)allowed_end - 0.0001); + } //Path::operator () means get point at time t start_attach_point = return_at_first_cusp(path_in[0])(attach_start); @@ -242,8 +326,8 @@ Geom::PathVector LPETaperStroke::doEffect_path(Geom::PathVector const& path_in) Geom::PathVector real_pathv; //Construct the pattern (pat_str stands for pattern string) - char* pat_str = new char[200]; - sprintf(pat_str, "M 1,0 1,1 C %5.5f,1 0,0.5 0,0.5 0,0.5 %5.5f,0 1,0 Z", (double)smoothing, (double)smoothing); + char pat_str[200]; + sprintf(pat_str, "M 1,0 1,1 C %5.5f,1 0,0.5 0,0.5 0,0.5 %5.5f,0 1,0 Z", 1 - (double)smoothing, 1 - (double)smoothing); Geom::PathVector pat_vec = sp_svg_read_pathv(pat_str); Geom::Piecewise > pwd2; @@ -253,12 +337,13 @@ Geom::PathVector LPETaperStroke::doEffect_path(Geom::PathVector const& path_in) Geom::PathVector sht_path; sht_path.push_back(pathv_out[1]); - sht_path = Outline::outlinePath_extr(sht_path, line_width, LINEJOIN_STRAIGHT, butt_straight, miter_limit); + sht_path = Outline::PathVectorOutline(sht_path, line_width, butt_straight, static_cast(join_type.get_value()) , miter_limit); real_pathv.push_back(sht_path[0]); - sprintf(pat_str, "M 0,0 0,1 C %5.5f,1 1,0.5 1,0.5 1,0.5 %5.5f,0 0,0 Z", (double)smoothing, (double)smoothing); - pat_vec = sp_svg_read_pathv(pat_str); + char pat_str_1[200]; + sprintf(pat_str_1, "M 0,0 0,1 C %5.5f,1 1,0.5 1,0.5 1,0.5 %5.5f,0 0,0 Z", (double)smoothing, (double)smoothing); + pat_vec = sp_svg_read_pathv(pat_str_1); pwd2 = Geom::Piecewise > (); pwd2.concat(stretch_along(pathv_out[2].toPwSb(), pat_vec[0], line_width)); @@ -298,7 +383,7 @@ Geom::PathVector LPETaperStroke::doEffect_simplePath(Geom::PathVector const & pa trimmed_start.append(path_in[0] [i]); } - #define OVERLAP 0.001 + #define OVERLAP (0.001 / (line_width < 1 ? 1 : line_width)) trimmed_start.append(*subdivide_at(curve_start, (attach_start - loc) + OVERLAP, true)); curve_start = subdivide_at(curve_start, attach_start - loc, false); @@ -451,6 +536,7 @@ Geom::Piecewise > stretch_along(Geom::Piecewise +#include <2geom/path.h> +#include <2geom/circle.h> +#include <2geom/sbasis-to-bezier.h> +#include <2geom/shape.h> +#include <2geom/transforms.h> +#include <2geom/path-sink.h> + +namespace Geom +{ + /** + * Refer to: Weisstein, Eric W. "Circle-Circle Intersection." + From MathWorld--A Wolfram Web Resource. + http://mathworld.wolfram.com/Circle-CircleIntersection.html + * + * @return 0 if no intersection + * @return 1 if one circle is contained in the other + * @return 2 if intersections are found (they are written to p0 and p1) + */ + static int circle_circle_intersection(Circle const &circle0, Circle const &circle1, + Point & p0, Point & p1) + { + Point X0 = circle0.center(); + double r0 = circle0.ray(); + Point X1 = circle1.center(); + double r1 = circle1.ray(); + + /* dx and dy are the vertical and horizontal distances between + * the circle centers. + */ + Point D = X1 - X0; + + /* Determine the straight-line distance between the centers. */ + double d = L2(D); + + /* Check for solvability. */ + if (d > (r0 + r1)) + { + /* no solution. circles do not intersect. */ + return 0; + } + if (d <= fabs(r0 - r1)) + { + /* no solution. one circle is contained in the other */ + return 1; + } + + /* 'point 2' is the point where the line through the circle + * intersection points crosses the line between the circle + * centers. + */ + + /* Determine the distance from point 0 to point 2. */ + double a = ((r0*r0) - (r1*r1) + (d*d)) / (2.0 * d) ; + + /* Determine the coordinates of point 2. */ + Point p2 = X0 + D * (a/d); + + /* Determine the distance from point 2 to either of the + * intersection points. + */ + double h = std::sqrt((r0*r0) - (a*a)); + + /* Now determine the offsets of the intersection points from + * point 2. + */ + Point r = (h/d)*rot90(D); + + /* Determine the absolute intersection points. */ + p0 = p2 + r; + p1 = p2 - r; + + return 2; + } + /** + * Find circle that touches inside of the curve, with radius matching the curvature, at time value \c t. + * Because this method internally uses unitTangentAt, t should be smaller than 1.0 (see unitTangentAt). + */ + static Circle touching_circle( D2 const &curve, double t, double tol=0.01 ) + { + D2 dM=derivative(curve); + if ( are_near(L2sq(dM(t)),0.) ) { + dM=derivative(dM); + } + if ( are_near(L2sq(dM(t)),0.) ) { // try second time + dM=derivative(dM); + } + Piecewise > unitv = unitVector(dM,tol); + Piecewise dMlength = dot(Piecewise >(dM),unitv); + Piecewise k = cross(derivative(unitv),unitv); + k = divide(k,dMlength,tol,3); + double curv = k(t); // note that this value is signed + + Geom::Point normal = unitTangentAt(curve, t).cw(); + double radius = 1/curv; + Geom::Point center = curve(t) + radius*normal; + return Geom::Circle(center, fabs(radius)); + } + + static std::vector split_at_cusps(const Geom::Path& in) + { + Geom::PathVector out = Geom::PathVector(); + Geom::Path temp = Geom::Path(); + + for (unsigned path_descr = 0; path_descr < in.size(); path_descr++) + { + temp = Geom::Path(); + temp.append(in[path_descr]); + out.push_back(temp); + } + + return out; + } + + static Geom::CubicBezier sbasis_to_cubicbezier(Geom::D2 const & sbasis_in) + { + std::vector temp; + sbasis_to_bezier(temp, sbasis_in, 4); + return Geom::CubicBezier( temp ); + } + + static boost::optional intersection_point( Geom::Point const & origin_a, Geom::Point const & vector_a, + Geom::Point const & origin_b, Geom::Point const & vector_b) + { + Geom::Coord denom = cross(vector_b, vector_a); + if (!Geom::are_near(denom,0.)){ + Geom::Coord t = (cross(origin_a,vector_b) + cross(vector_b,origin_b)) / denom; + return origin_a + t * vector_a; + } + return boost::none; + } +} + +namespace Outline +{ + +typedef Geom::D2 D2SB; +typedef Geom::Piecewise PWD2; + +unsigned bezierOrder (const Geom::Curve* curve_in) +{ + using namespace Geom; + //cast it + const CubicBezier *cbc = dynamic_cast(curve_in); + if (cbc) return 3; + const QuadraticBezier * qbc = dynamic_cast(curve_in); + if (qbc) return 2; + const BezierCurveN<1U> * lbc = dynamic_cast *>(curve_in); + if (lbc) return 1; + return 0; +} + +//returns true if the angle formed by the curves and their handles +//is >180 clockwise, otherwise false. +bool outside_angle (const Geom::Curve* cbc1, const Geom::Curve* cbc2) +{ + Geom::Point start_point = cbc1->initialPoint(); + Geom::Point end_point = cbc2->finalPoint(); + unsigned order = bezierOrder(cbc1); + switch (order) + { + case 3: + start_point = ( dynamic_cast(cbc1) )->operator [] (2); + break; + case 2: + start_point = ( dynamic_cast(cbc1) )->operator [] (1); + break; + } + order = bezierOrder(cbc2); + switch (order) + { + case 3: + end_point = ( dynamic_cast(cbc2) )->operator [] (1); + break; + case 2: + end_point = ( dynamic_cast(cbc2) )->operator[] (1); + break; + } + return false; +} + +void extrapolate_curves(Geom::Path& path_builder, Geom::Curve* cbc1, Geom::Curve*cbc2, Geom::Point endPt, double miter_limit) +{ + + Geom::Crossings cross = Geom::crossings(*cbc1, *cbc2); + if (cross.empty()) + { + Geom::Path pth; + pth.append(*cbc1); + + //Geom::Point tang1 = Geom::unitTangentAt(pth.toPwSb()[0], 1); + + pth = Geom::Path(); + pth.append( *cbc2 ); + Geom::Point tang2 = Geom::unitTangentAt(pth.toPwSb()[0], 0); + + + Geom::Circle circle1 = Geom::touching_circle(Geom::reverse(cbc1->toSBasis()), 0.); + Geom::Circle circle2 = Geom::touching_circle(cbc2->toSBasis(), 0); + + Geom::Point points[2]; + int solutions = Geom::circle_circle_intersection(circle1, circle2, points[0], points[1]); + if (solutions == 2) + { + Geom::Point sol(0,0); + if ( dot(tang2,points[0]-endPt) > 0 ) + { + // points[0] is bad, choose points[1] + sol = points[1]; + } + else if ( dot(tang2,points[1]-endPt) > 0 ) { // points[0] could be good, now check points[1] + // points[1] is bad, choose points[0] + sol = points[0]; + } + else + { + // both points are good, choose nearest + sol = ( distanceSq(endPt, points[0]) < distanceSq(endPt, points[1]) ) ? + points[0] : points[1]; + } + Geom::EllipticalArc *arc0 = circle1.arc(cbc1->finalPoint(), 0.5*(cbc1->finalPoint()+sol), sol, true); + Geom::EllipticalArc *arc1 = circle2.arc(sol, 0.5*(sol+endPt), endPt, true); + + if (arc0) + { + path_builder.append (arc0->toSBasis()); + delete arc0; + arc0 = NULL; + } + + if (arc1) + { + path_builder.append (arc1->toSBasis()); + delete arc1; + arc1 = NULL; + } + } + else + { + path_builder.appendNew (endPt); + } + } + else + { + path_builder.appendNew (endPt); + } +} + Geom::Path half_outline_extrp(const Geom::Path& path_in, double line_width, ButtType linecap_type, double miter_limit) + { + Geom::PathVector pv = split_at_cusps(path_in); + unsigned m; + Path path_outline = Path(); + Path path_tangent = Path(); + + Geom::Point initialPoint; + Geom::Point endPoint; + + Geom::Path path_builder = Geom::Path(); + Geom::PathVector * pathvec; + + //load the first portion in before the loop starts + { + path_outline = Path(); + path_outline.LoadPath(pv[0], Geom::Affine(), false, false); + path_outline.OutsideOutline(&path_tangent, line_width / 2, join_straight, linecap_type, 10); + //now half of first cusp has been loaded + + pathvec = path_tangent.MakePathVector(); + path_tangent = Path(); + + //instead of array accessing twice, dereferencing used for clarity + initialPoint = (*pathvec)[0].initialPoint(); + + path_builder.start(initialPoint); + path_builder.append( (*pathvec)[0] ); + + path_outline = Path(); + path_outline.LoadPath(pv[1], Geom::Affine(), false, false); + path_outline.OutsideOutline(&path_tangent, line_width / 2, join_straight, linecap_type, 10); + + delete pathvec; pathvec = NULL; + pathvec = path_tangent.MakePathVector(); + path_tangent = Path(); + + Geom::Curve *cbc1 = path_builder[path_builder.size() - 1].duplicate(); + Geom::Curve *cbc2 = (*pathvec)[0][0].duplicate(); + + extrapolate_curves(path_builder, cbc1, cbc2, (*pathvec)[0].initialPoint(), miter_limit ); + + path_builder.append( (*pathvec)[0] ); + + //always set pointers null after deleting + delete pathvec; pathvec = NULL; + delete cbc1; delete cbc2; cbc1 = cbc2 = NULL; + } + + for (m = 2; m < pv.size(); m++) + { + path_outline = Path(); + path_outline.LoadPath(pv[m], Geom::Affine(), false, false); + path_outline.OutsideOutline(&path_tangent, line_width / 2, join_straight, linecap_type, 10); + + delete pathvec; pathvec = NULL; + pathvec = path_tangent.MakePathVector(); + + Geom::Curve *cbc1 = path_builder[path_builder.size() - 1].duplicate(); + Geom::Curve *cbc2 = (*pathvec)[0][0].duplicate(); + + extrapolate_curves(path_builder, cbc1, cbc2, (*pathvec)[0].initialPoint(), miter_limit ); + path_builder.append( (*pathvec)[0] ); + + delete pathvec; pathvec = NULL; + delete cbc1; delete cbc2; cbc1 = cbc2 = NULL; + } + + return path_builder; + } + + //Create a reflected outline join. + //Note: it is generally recommended to let half_outline do this for you! + //path_builder: the path to append the curves to + //cbc1: the curve before the join + //cbc2: the curve after the join + //endPt: the point to end at + //miter_limit: the miter parameter + void reflect_curves(Geom::Path& path_builder, Geom::Curve* cbc1, Geom::Curve* cbc2, Geom::Point endPt, double miter_limit) + { + //the most important work for the reflected join is done here + + //determine where we are in the path. If we're on the inside, ignore + //and just lineTo. On the outside, we'll do a little reflection magic :) + Geom::Crossings cross = Geom::crossings(*cbc1, *cbc2); + if (cross.empty()) + { + //probably on the outside of the corner + Geom::Path pth; + pth.append(*cbc1); + + Geom::Point tang1 = Geom::unitTangentAt(pth.toPwSb()[0], 1); + + //reflect curves along the bevel + D2SB newcurve1 = pth.toPwSb()[0] * + Geom::reflection ( -Geom::rot90(tang1) , + cbc1->finalPoint() ); + + Geom::CubicBezier bzr1 = sbasis_to_cubicbezier(Geom::reverse(newcurve1)); + + pth = Geom::Path(); + pth.append( *cbc2 ); + Geom::Point tang2 = Geom::unitTangentAt(pth.toPwSb()[0], 0); + + D2SB newcurve2 = pth.toPwSb()[0] * + Geom::reflection ( -Geom::rot90(tang2) , + cbc2->initialPoint() ); + Geom::CubicBezier bzr2 = sbasis_to_cubicbezier(Geom::reverse(newcurve2)); + + cross = Geom::crossings(bzr1, bzr2); + if ( cross.empty() ) + { + //std::cout << "Oops, no crossings!" << std::endl; + //curves didn't cross; default to miter + /*boost::optional p = intersection_point (cbc1->finalPoint(), tang1, + cbc2->initialPoint(), tang2); + if (p) + { + path_builder.appendNew (*p); + }*/ + //bevel + path_builder.appendNew( endPt ); + } + else + { + //join + std::pair sub1 = bzr1.subdivide(cross[0].ta); + std::pair sub2 = bzr2.subdivide(cross[0].tb); + + //@TODO joins have a strange tendency to cross themselves twice. Check this. + + //sections commented out are for general stability + path_builder.appendNew (sub1.first[1], sub1.first[2], /*sub1.first[3]*/ sub2.second[0] ); + path_builder.appendNew (sub2.second[1], sub2.second[2], /*sub2.second[3]*/ endPt ); + } + } + else // cross.empty() + { + //probably on the inside of the corner + path_builder.appendNew ( endPt ); + } + } + + /** @brief Converts a path to one half of an outline. + * path_in: The input path to use. (To create the other side use path_in.reverse() ) + * line_width: the line width to use (usually you want to divide this by 2) + * linecap_type: (not used here) the cap to apply. Passed to libvarot. + * miter_limit: the miter parameter + */ + Geom::Path half_outline(const Geom::Path& path_in, double line_width, ButtType linecap_type, double miter_limit) + { + Geom::PathVector pv = split_at_cusps(path_in); + unsigned m; + Path path_outline = Path(); + Path path_tangent = Path(); + //needed for closing the path + Geom::Point initialPoint; + Geom::Point endPoint; + + //some issues prevented me from using a PathBuilder here + //it seems like PathBuilder::peek() gave me a null reference exception + //and I was unable to get a stack trace on Windows, so had to switch to Linux + //to see what the hell was wrong. :( + //I wasted five hours opening it in IDAPro, VS2012, and GDB Windows + + /*Program received signal SIGSEGV, Segmentation fault. + 0x00000000006539ac in get_curves (this=0x0) + at /usr/include/c++/4.6/bits/locale_facets.h:1077 + 1077 { return __c; } + */ + + Geom::Path path_builder = Geom::Path(); + Geom::PathVector * pathvec; + + //load the first portion in before the loop starts + { + path_outline = Path(); + path_outline.LoadPath(pv[0], Geom::Affine(), false, false); + path_outline.OutsideOutline(&path_tangent, line_width / 2, join_straight, linecap_type, 10); + //now half of first cusp has been loaded + + pathvec = path_tangent.MakePathVector(); + path_tangent = Path(); + + //instead of array accessing twice, dereferencing used for clarity + initialPoint = (*pathvec)[0].initialPoint(); + + path_builder.start(initialPoint); + path_builder.append( (*pathvec)[0] ); + + path_outline = Path(); + path_outline.LoadPath(pv[1], Geom::Affine(), false, false); + path_outline.OutsideOutline(&path_tangent, line_width / 2, join_straight, linecap_type, 10); + + delete pathvec; pathvec = NULL; + pathvec = path_tangent.MakePathVector(); + path_tangent = Path(); + + Geom::Curve *cbc1 = path_builder[path_builder.size() - 1].duplicate(); + Geom::Curve *cbc2 = (*pathvec)[0][0].duplicate(); + + reflect_curves(path_builder, cbc1, cbc2, (*pathvec)[0].initialPoint(), miter_limit ); + + path_builder.append( (*pathvec)[0] ); + + //always set pointers null after deleting + delete pathvec; pathvec = NULL; + delete cbc1; delete cbc2; cbc1 = cbc2 = NULL; + } + + for (m = 2; m < pv.size(); m++) + { + path_outline = Path(); + path_outline.LoadPath(pv[m], Geom::Affine(), false, false); + path_outline.OutsideOutline(&path_tangent, line_width / 2, join_straight, linecap_type, 10); + + delete pathvec; pathvec = NULL; + pathvec = path_tangent.MakePathVector(); + + Geom::Curve *cbc1 = path_builder[path_builder.size() - 1].duplicate(); + Geom::Curve *cbc2 = (*pathvec)[0][0].duplicate(); + + reflect_curves(path_builder, cbc1, cbc2, (*pathvec)[0].initialPoint(), miter_limit ); + path_builder.append( (*pathvec)[0] ); + + delete pathvec; pathvec = NULL; + delete cbc1; delete cbc2; cbc1 = cbc2 = NULL; + } + + return path_builder; + } + + Geom::PathVector outlinePath(const Geom::PathVector& path_in, double line_width, JoinType join, ButtType butt, double miter_lim) + { + Path p = Path(); + Path outlinepath = Path(); + for (unsigned i = 0; i < path_in.size(); i++) + { + p.LoadPath(path_in[i], Geom::Affine(), false, ( (i==0) ? false : true)); + } + + Geom::PathVector path_out; + for (unsigned lmnop = 0; lmnop < path_in.size(); lmnop++) + { + if (path_in[lmnop].size() > 1) + { + Geom::Path p_init; + Geom::Path p_rev; + Geom::PathBuilder pb = Geom::PathBuilder(); + + if ( !path_in[lmnop].closed() ) + { + p_init = Outline::half_outline( path_in[lmnop], -line_width, butt, + miter_lim ); + p_rev = Outline::half_outline( path_in[lmnop].reverse(), -line_width, butt, + miter_lim ); + + pb.moveTo(p_init.initialPoint() ); + pb.append(p_init); + + //cap + if (butt == butt_straight) { + pb.lineTo(p_rev.initialPoint() ); + } else if (butt == butt_round) { + pb.arcTo((-line_width) / 2, (-line_width) / 2, 0., true, true, p_rev.initialPoint() ); + } else if (butt == butt_square) { + //don't know what to do + pb.lineTo(p_rev.initialPoint() ); + } else if (butt == butt_pointy) { + //don't know what to do + pb.lineTo(p_rev.initialPoint() ); + } + + pb.append(p_rev); + + if (butt == butt_straight) { + pb.lineTo(p_init.initialPoint() ); + } else if (butt == butt_round) { + pb.arcTo((-line_width) / 2, (-line_width) / 2, 0., true, true, p_init.initialPoint() ); + } else if (butt == butt_square) { + //don't know what to do + pb.lineTo(p_init.initialPoint() ); + } else if (butt == butt_pointy) { + //don't know what to do + //Geom::Point end_deriv = Geom::unitTangentAt( Geom::reverse(path_in[lmnop].toPwSb()[path_in[lmnop].size()]), 0); + //double radius = 0.5 * Geom::distance(path_in[lmnop].finalPoint(), p_rev.initialPoint()); + + pb.lineTo(p_init.initialPoint() ); + } + } + else + { + //final join + //refer to half_outline for documentation + Geom::Path p_almost = path_in[lmnop]; + p_almost.appendNew ( path_in[lmnop].initialPoint() ); + p_init = Outline::half_outline( p_almost, -line_width, butt, + miter_lim ); + p_rev = Outline::half_outline( p_almost.reverse(), -line_width, butt, + miter_lim ); + p.LoadPath(path_in[lmnop], Geom::Affine(), false, false); + + //this is a kludge, because I can't find how to make this work properly + bool lastIsLinear = ( (Geom::distance(path_in[lmnop].finalPoint(), + path_in[lmnop] [path_in[lmnop].size() - 1].finalPoint())) == + (path_in[lmnop] [path_in[lmnop].size()].length())); + + p_almost = p_init; + if (lastIsLinear) + { + p_almost.erase_last(); p_almost.erase_last(); + } + + //outside test + Geom::Curve* cbc1 = p_almost[p_almost.size() - 1].duplicate(); + Geom::Curve* cbc2 = p_almost[0].duplicate(); + + Geom::Crossings cross = Geom::crossings(*cbc1, *cbc2); + + if (cross.empty()) + { + //this is the outside path + + //reuse the old one + p_init = p_almost; + Outline::reflect_curves(p_init, cbc1, cbc2, p_almost.initialPoint(), miter_lim ); + pb.moveTo(p_init.initialPoint()); pb.append(p_init); + } + else + { + //inside, carry on :-) + pb.moveTo(p_almost.initialPoint()); pb.append(p_almost); + } + + p_almost = p_rev; + if (lastIsLinear) + { + p_almost.erase(p_almost.begin() ); + p_almost.erase(p_almost.begin() ); + } + + delete cbc1; delete cbc2; cbc1 = cbc2 = NULL; + + cbc1 = p_almost[p_almost.size() - 1].duplicate(); + cbc2 = p_almost[0].duplicate(); + + cross = Geom::crossings(*cbc1, *cbc2); + + if (cross.empty()) + { + //outside path + + p_init = p_almost; + reflect_curves(p_init, cbc1, cbc2, p_almost.initialPoint(), miter_lim ); + pb.moveTo(p_init.initialPoint()); pb.append(p_init); + } + else + { + //inside + pb.moveTo(p_almost.initialPoint()); pb.append(p_almost); + } + delete cbc1; delete cbc2; cbc1 = cbc2 = NULL; + } + //pb.closePath(); + pb.flush(); + Geom::PathVector pv_np = pb.peek(); + //hack + for (unsigned abcd = 0; abcd < pv_np.size(); abcd++) + { + path_out.push_back( pv_np[abcd] ); + } + } + else + { + p.LoadPath(path_in[lmnop], Geom::Affine(), false, false); + p.Outline(&outlinepath, line_width / 2, join, butt, miter_lim); + std::vector *pv_p = outlinepath.MakePathVector(); + //hack + path_out.push_back( (*pv_p)[0].reverse() ); + delete pv_p; + } + } + return path_out; + } + Geom::PathVector outlinePath_extr(const Geom::PathVector& path_in, double line_width, LineJoinType join, ButtType butt, double miter_lim) + { + Path p = Path(); + Path outlinepath = Path(); + for (unsigned i = 0; i < path_in.size(); i++) + { + p.LoadPath(path_in[i], Geom::Affine(), false, ( (i==0) ? false : true)); + } + + Geom::PathVector path_out; + for (unsigned lmnop = 0; lmnop < path_in.size(); lmnop++) + { + if (path_in[lmnop].size() > 1) + { + Geom::Path p_init; + Geom::Path p_rev; + Geom::PathBuilder pb = Geom::PathBuilder(); + + if ( !path_in[lmnop].closed() ) + { + p_init = Outline::half_outline_extrp( path_in[lmnop], -line_width, butt, + miter_lim ); + p_rev = Outline::half_outline_extrp( path_in[lmnop].reverse(), -line_width, butt, + miter_lim ); + + pb.moveTo(p_init.initialPoint() ); + pb.append(p_init); + + //cap + if (butt == butt_straight) { + pb.lineTo(p_rev.initialPoint() ); + } else if (butt == butt_round) { + pb.arcTo((-line_width) / 2, (-line_width) / 2, 0., true, true, p_rev.initialPoint() ); + } else if (butt == butt_square) { + //don't know what to do + pb.lineTo(p_rev.initialPoint() ); + } else if (butt == butt_pointy) { + //don't know what to do + pb.lineTo(p_rev.initialPoint() ); + } + + pb.append(p_rev); + + if (butt == butt_straight) { + pb.lineTo(p_init.initialPoint() ); + } else if (butt == butt_round) { + pb.arcTo((-line_width) / 2, (-line_width) / 2, 0., true, true, p_init.initialPoint() ); + } else if (butt == butt_square) { + //don't know what to do + pb.lineTo(p_init.initialPoint() ); + } else if (butt == butt_pointy) { + //don't know what to do + //Geom::Point end_deriv = Geom::unitTangentAt( Geom::reverse(path_in[lmnop].toPwSb()[path_in[lmnop].size()]), 0); + //double radius = 0.5 * Geom::distance(path_in[lmnop].finalPoint(), p_rev.initialPoint()); + + pb.lineTo(p_init.initialPoint() ); + } + } + else + { + //final join + //refer to half_outline for documentation + Geom::Path p_almost = path_in[lmnop]; + p_almost.appendNew ( path_in[lmnop].initialPoint() ); + p_init = Outline::half_outline_extrp( p_almost, -line_width, butt, + miter_lim ); + p_rev = Outline::half_outline_extrp( p_almost.reverse(), -line_width, butt, + miter_lim ); + p.LoadPath(path_in[lmnop], Geom::Affine(), false, false); + + //this is a kludge, because I can't find how to make this work properly + bool lastIsLinear = ( (Geom::distance(path_in[lmnop].finalPoint(), + path_in[lmnop] [path_in[lmnop].size() - 1].finalPoint())) == + (path_in[lmnop] [path_in[lmnop].size()].length())); + + p_almost = p_init; + if (lastIsLinear) + { + p_almost.erase_last(); p_almost.erase_last(); + } + + //outside test + Geom::Curve* cbc1 = p_almost[p_almost.size() - 1].duplicate(); + Geom::Curve* cbc2 = p_almost[0].duplicate(); + + Geom::Crossings cross = Geom::crossings(*cbc1, *cbc2); + + if (cross.empty()) + { + //this is the outside path + + //reuse the old one + p_init = p_almost; + Outline::extrapolate_curves(p_init, cbc1, cbc2, p_almost.initialPoint(), miter_lim ); + pb.moveTo(p_init.initialPoint()); pb.append(p_init); + } + else + { + //inside, carry on :-) + pb.moveTo(p_almost.initialPoint()); pb.append(p_almost); + } + + p_almost = p_rev; + if (lastIsLinear) + { + p_almost.erase(p_almost.begin() ); + p_almost.erase(p_almost.begin() ); + } + + delete cbc1; delete cbc2; cbc1 = cbc2 = NULL; + + cbc1 = p_almost[p_almost.size() - 1].duplicate(); + cbc2 = p_almost[0].duplicate(); + + cross = Geom::crossings(*cbc1, *cbc2); + + if (cross.empty()) + { + //outside path + + p_init = p_almost; + extrapolate_curves(p_init, cbc1, cbc2, p_almost.initialPoint(), miter_lim ); + pb.moveTo(p_init.initialPoint()); pb.append(p_init); + } + else + { + //inside + pb.moveTo(p_almost.initialPoint()); pb.append(p_almost); + } + delete cbc1; delete cbc2; cbc1 = cbc2 = NULL; + } + //pb.closePath(); + pb.flush(); + Geom::PathVector pv_np = pb.peek(); + //hack + for (unsigned abcd = 0; abcd < pv_np.size(); abcd++) + { + path_out.push_back( pv_np[abcd] ); + } + } + else + { + p.LoadPath(path_in[lmnop], Geom::Affine(), false, false); + p.Outline(&outlinepath, line_width / 2, join_pointy, butt, miter_lim); + std::vector *pv_p = outlinepath.MakePathVector(); + //hack + path_out.push_back( (*pv_p)[0].reverse() ); + delete pv_p; + } + } + return path_out; + } + +Geom::PathVector PathVectorOutline(Geom::PathVector const & path_in, double line_width, ButtType linecap_type, + join_typ linejoin_type, double miter_limit) +{ + std::vector path_out = std::vector(); + if (path_in.empty()) + { + return path_out; + } + Path p = Path(); + Path outlinepath = Path(); + for (unsigned i = 0; i < path_in.size(); i++) + { + p.LoadPath(path_in[i], Geom::Affine(), false, ( (i==0) ? false : true)); + } + + #define miter_lim fabs(line_width * miter_limit) + + //magic! + if (linejoin_type <= 2) + { + p.Outline(&outlinepath, line_width / 2, linejoin_type, + linecap_type, miter_lim); + //fix memory leak + std::vector *pv_p = outlinepath.MakePathVector(); + path_out = *pv_p; + delete pv_p; + + } else if (linejoin_type == 3) { + //reflected arc join + path_out = outlinePath(path_in, line_width, linejoin_type, + linecap_type , miter_lim); + + } else if (linejoin_type == 4) { + //extrapolated arc join + path_out = outlinePath_extr(path_in, line_width, LINEJOIN_STRAIGHT, linecap_type, miter_lim); + + } + + #undef miter_lim + return path_out; +} + +} // namespace Outline + +/* + 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:encoding=utf-8:textwidth=99 : diff --git a/src/live_effects/pathoutlineprovider.h b/src/live_effects/pathoutlineprovider.h old mode 100755 new mode 100644 index 8aa2e38ad..1a363c35b --- a/src/live_effects/pathoutlineprovider.h +++ b/src/live_effects/pathoutlineprovider.h @@ -1,766 +1,25 @@ -#pragma once - -#include <2geom/path.h> -#include <2geom/circle.h> -#include <2geom/sbasis-to-bezier.h> -#include <2geom/shape.h> -#include <2geom/transforms.h> -#include <2geom/path-sink.h> - -#include -#include - -enum LineJoinType { - LINEJOIN_STRAIGHT, - LINEJOIN_ROUND, - LINEJOIN_POINTY, - LINEJOIN_REFLECTED, - LINEJOIN_EXTRAPOLATED -}; - -namespace Geom -{ - /** - * Refer to: Weisstein, Eric W. "Circle-Circle Intersection." - From MathWorld--A Wolfram Web Resource. - http://mathworld.wolfram.com/Circle-CircleIntersection.html - * - * @return 0 if no intersection - * @return 1 if one circle is contained in the other - * @return 2 if intersections are found (they are written to p0 and p1) - */ - static int circle_circle_intersection(Circle const &circle0, Circle const &circle1, - Point & p0, Point & p1) - { - Point X0 = circle0.center(); - double r0 = circle0.ray(); - Point X1 = circle1.center(); - double r1 = circle1.ray(); - - /* dx and dy are the vertical and horizontal distances between - * the circle centers. - */ - Point D = X1 - X0; - - /* Determine the straight-line distance between the centers. */ - double d = L2(D); - - /* Check for solvability. */ - if (d > (r0 + r1)) - { - /* no solution. circles do not intersect. */ - return 0; - } - if (d <= fabs(r0 - r1)) - { - /* no solution. one circle is contained in the other */ - return 1; - } - - /* 'point 2' is the point where the line through the circle - * intersection points crosses the line between the circle - * centers. - */ - - /* Determine the distance from point 0 to point 2. */ - double a = ((r0*r0) - (r1*r1) + (d*d)) / (2.0 * d) ; - - /* Determine the coordinates of point 2. */ - Point p2 = X0 + D * (a/d); - - /* Determine the distance from point 2 to either of the - * intersection points. - */ - double h = std::sqrt((r0*r0) - (a*a)); - - /* Now determine the offsets of the intersection points from - * point 2. - */ - Point r = (h/d)*rot90(D); - - /* Determine the absolute intersection points. */ - p0 = p2 + r; - p1 = p2 - r; - - return 2; - } - /** - * Find circle that touches inside of the curve, with radius matching the curvature, at time value \c t. - * Because this method internally uses unitTangentAt, t should be smaller than 1.0 (see unitTangentAt). - */ - static Circle touching_circle( D2 const &curve, double t, double tol=0.01 ) - { - D2 dM=derivative(curve); - if ( are_near(L2sq(dM(t)),0.) ) { - dM=derivative(dM); - } - if ( are_near(L2sq(dM(t)),0.) ) { // try second time - dM=derivative(dM); - } - Piecewise > unitv = unitVector(dM,tol); - Piecewise dMlength = dot(Piecewise >(dM),unitv); - Piecewise k = cross(derivative(unitv),unitv); - k = divide(k,dMlength,tol,3); - double curv = k(t); // note that this value is signed - - Geom::Point normal = unitTangentAt(curve, t).cw(); - double radius = 1/curv; - Geom::Point center = curve(t) + radius*normal; - return Geom::Circle(center, fabs(radius)); - } - - static std::vector split_at_cusps(const Geom::Path& in) - { - Geom::PathVector out = Geom::PathVector(); - Geom::Path temp = Geom::Path(); - - for (unsigned path_descr = 0; path_descr < in.size(); path_descr++) - { - temp = Geom::Path(); - temp.append(in[path_descr]); - out.push_back(temp); - } - - return out; - } - - static Geom::CubicBezier sbasis_to_cubicbezier(Geom::D2 const & sbasis_in) - { - std::vector temp; - sbasis_to_bezier(temp, sbasis_in, 4); - return Geom::CubicBezier( temp ); - } - - static boost::optional intersection_point( Geom::Point const & origin_a, Geom::Point const & vector_a, - Geom::Point const & origin_b, Geom::Point const & vector_b) - { - Geom::Coord denom = cross(vector_b, vector_a); - if (!Geom::are_near(denom,0.)){ - Geom::Coord t = (cross(origin_a,vector_b) + cross(vector_b,origin_b)) / denom; - return origin_a + t * vector_a; - } - return boost::none; - } -} - -namespace Outline -{ - - typedef Geom::D2 D2SB; - typedef Geom::Piecewise PWD2; - - static void extrapolate_curves(Geom::Path& path_builder, Geom::Curve* cbc1, Geom::Curve*cbc2, Geom::Point endPt, double miter_limit) -{ - Geom::Crossings cross = Geom::crossings(*cbc1, *cbc2); - if (cross.empty()) - { - Geom::Path pth; - pth.append(*cbc1); - - Geom::Point tang1 = Geom::unitTangentAt(pth.toPwSb()[0], 1); - - pth = Geom::Path(); - pth.append( *cbc2 ); - Geom::Point tang2 = Geom::unitTangentAt(pth.toPwSb()[0], 0); - - - Geom::Circle circle1 = Geom::touching_circle(Geom::reverse(cbc1->toSBasis()), 0.); - Geom::Circle circle2 = Geom::touching_circle(cbc2->toSBasis(), 0); - - Geom::Point points[2]; - int solutions = Geom::circle_circle_intersection(circle1, circle2, points[0], points[1]); - if (solutions == 2) - { - Geom::Point sol(0,0); - if ( dot(tang2,points[0]-endPt) > 0 ) - { - // points[0] is bad, choose points[1] - sol = points[1]; - } - else if ( dot(tang2,points[1]-endPt) > 0 ) { // points[0] could be good, now check points[1] - // points[1] is bad, choose points[0] - sol = points[0]; - } - else - { - // both points are good, choose nearest - sol = ( distanceSq(endPt, points[0]) < distanceSq(endPt, points[1]) ) ? - points[0] : points[1]; - } - Geom::EllipticalArc *arc0 = circle1.arc(cbc1->finalPoint(), 0.5*(cbc1->finalPoint()+sol), sol, true); - Geom::EllipticalArc *arc1 = circle2.arc(sol, 0.5*(sol+endPt), endPt, true); - - if (arc0) - { - path_builder.append (arc0->toSBasis()); - delete arc0; - arc0 = NULL; - } - - if (arc1) - { - path_builder.append (arc1->toSBasis()); - delete arc1; - arc1 = NULL; - } - } - else - { - path_builder.appendNew (endPt); - } - } - else - { - path_builder.appendNew (endPt); - } -} - static Geom::Path half_outline_extrp(const Geom::Path& path_in, double line_width, ButtType linecap_type, double miter_limit) - { - Geom::PathVector pv = split_at_cusps(path_in); - unsigned m; - Path path_outline = Path(); - Path path_tangent = Path(); - - Geom::Point initialPoint; - Geom::Point endPoint; - - Geom::Path path_builder = Geom::Path(); - Geom::PathVector * pathvec; - - //load the first portion in before the loop starts - { - path_outline = Path(); - path_outline.LoadPath(pv[0], Geom::Affine(), false, false); - path_outline.OutsideOutline(&path_tangent, line_width / 2, join_straight, linecap_type, 10); - //now half of first cusp has been loaded - - pathvec = path_tangent.MakePathVector(); - path_tangent = Path(); - - //instead of array accessing twice, dereferencing used for clarity - initialPoint = (*pathvec)[0].initialPoint(); - - path_builder.start(initialPoint); - path_builder.append( (*pathvec)[0] ); - - path_outline = Path(); - path_outline.LoadPath(pv[1], Geom::Affine(), false, false); - path_outline.OutsideOutline(&path_tangent, line_width / 2, join_straight, linecap_type, 10); - - delete pathvec; pathvec = NULL; - pathvec = path_tangent.MakePathVector(); - path_tangent = Path(); - - Geom::Curve *cbc1 = path_builder[path_builder.size() - 1].duplicate(); - Geom::Curve *cbc2 = (*pathvec)[0][0].duplicate(); - - extrapolate_curves(path_builder, cbc1, cbc2, (*pathvec)[0].initialPoint(), miter_limit ); - - path_builder.append( (*pathvec)[0] ); - - //always set pointers null after deleting - delete pathvec; pathvec = NULL; - delete cbc1; delete cbc2; cbc1 = cbc2 = NULL; - } - - for (m = 2; m < pv.size(); m++) - { - path_outline = Path(); - path_outline.LoadPath(pv[m], Geom::Affine(), false, false); - path_outline.OutsideOutline(&path_tangent, line_width / 2, join_straight, linecap_type, 10); - - delete pathvec; pathvec = NULL; - pathvec = path_tangent.MakePathVector(); - - Geom::Curve *cbc1 = path_builder[path_builder.size() - 1].duplicate(); - Geom::Curve *cbc2 = (*pathvec)[0][0].duplicate(); - - extrapolate_curves(path_builder, cbc1, cbc2, (*pathvec)[0].initialPoint(), miter_limit ); - path_builder.append( (*pathvec)[0] ); - - delete pathvec; pathvec = NULL; - delete cbc1; delete cbc2; cbc1 = cbc2 = NULL; - } - - return path_builder; - } - - //Create a reflected outline join. - //Note: it is generally recommended to let half_outline do this for you! - //path_builder: the path to append the curves to - //cbc1: the curve before the join - //cbc2: the curve after the join - //endPt: the point to end at - //miter_limit: the miter parameter - static void reflect_curves(Geom::Path& path_builder, Geom::Curve* cbc1, Geom::Curve* cbc2, Geom::Point endPt, double miter_limit) - { - //the most important work for the reflected join is done here - - //determine where we are in the path. If we're on the inside, ignore - //and just lineTo. On the outside, we'll do a little reflection magic :) - Geom::Crossings cross = Geom::crossings(*cbc1, *cbc2); - if (cross.empty()) - { - //probably on the outside of the corner - Geom::Path pth; - pth.append(*cbc1); - - Geom::Point tang1 = Geom::unitTangentAt(pth.toPwSb()[0], 1); - - //reflect curves along the bevel - D2SB newcurve1 = pth.toPwSb()[0] * - Geom::reflection ( -Geom::rot90(tang1) , - cbc1->finalPoint() ); - - Geom::CubicBezier bzr1 = sbasis_to_cubicbezier(Geom::reverse(newcurve1)); - - pth = Geom::Path(); - pth.append( *cbc2 ); - Geom::Point tang2 = Geom::unitTangentAt(pth.toPwSb()[0], 0); - - D2SB newcurve2 = pth.toPwSb()[0] * - Geom::reflection ( -Geom::rot90(tang2) , - cbc2->initialPoint() ); - Geom::CubicBezier bzr2 = sbasis_to_cubicbezier(Geom::reverse(newcurve2)); - - cross = Geom::crossings(bzr1, bzr2); - if ( cross.empty() ) - { - //std::cout << "Oops, no crossings!" << std::endl; - //curves didn't cross; default to miter - /*boost::optional p = intersection_point (cbc1->finalPoint(), tang1, - cbc2->initialPoint(), tang2); - if (p) - { - path_builder.appendNew (*p); - }*/ - //bevel - path_builder.appendNew( endPt ); - } - else - { - //join - std::pair sub1 = bzr1.subdivide(cross[0].ta); - std::pair sub2 = bzr2.subdivide(cross[0].tb); - - //@TODO joins have a strange tendency to cross themselves twice. Check this. - - //sections commented out are for general stability - path_builder.appendNew (sub1.first[1], sub1.first[2], /*sub1.first[3]*/ sub2.second[0] ); - path_builder.appendNew (sub2.second[1], sub2.second[2], /*sub2.second[3]*/ endPt ); - } - } - else // cross.empty() - { - //probably on the inside of the corner - path_builder.appendNew ( endPt ); - } - } - - /** @brief Converts a path to one half of an outline. - * path_in: The input path to use. (To create the other side use path_in.reverse() ) - * line_width: the line width to use (usually you want to divide this by 2) - * linecap_type: (not used here) the cap to apply. Passed to libvarot. - * miter_limit: the miter parameter - */ - static Geom::Path half_outline(const Geom::Path& path_in, double line_width, ButtType linecap_type, double miter_limit) - { - Geom::PathVector pv = split_at_cusps(path_in); - unsigned m; - Path path_outline = Path(); - Path path_tangent = Path(); - //needed for closing the path - Geom::Point initialPoint; - Geom::Point endPoint; - - //some issues prevented me from using a PathBuilder here - //it seems like PathBuilder::peek() gave me a null reference exception - //and I was unable to get a stack trace on Windows, so had to switch to Linux - //to see what the hell was wrong. :( - //I wasted five hours opening it in IDAPro, VS2012, and GDB Windows - - /*Program received signal SIGSEGV, Segmentation fault. - 0x00000000006539ac in get_curves (this=0x0) - at /usr/include/c++/4.6/bits/locale_facets.h:1077 - 1077 { return __c; } - */ - - Geom::Path path_builder = Geom::Path(); - Geom::PathVector * pathvec; - - //load the first portion in before the loop starts - { - path_outline = Path(); - path_outline.LoadPath(pv[0], Geom::Affine(), false, false); - path_outline.OutsideOutline(&path_tangent, line_width / 2, join_straight, linecap_type, 10); - //now half of first cusp has been loaded - - pathvec = path_tangent.MakePathVector(); - path_tangent = Path(); - - //instead of array accessing twice, dereferencing used for clarity - initialPoint = (*pathvec)[0].initialPoint(); - - path_builder.start(initialPoint); - path_builder.append( (*pathvec)[0] ); - - path_outline = Path(); - path_outline.LoadPath(pv[1], Geom::Affine(), false, false); - path_outline.OutsideOutline(&path_tangent, line_width / 2, join_straight, linecap_type, 10); - - delete pathvec; pathvec = NULL; - pathvec = path_tangent.MakePathVector(); - path_tangent = Path(); - - Geom::Curve *cbc1 = path_builder[path_builder.size() - 1].duplicate(); - Geom::Curve *cbc2 = (*pathvec)[0][0].duplicate(); - - reflect_curves(path_builder, cbc1, cbc2, (*pathvec)[0].initialPoint(), miter_limit ); - - path_builder.append( (*pathvec)[0] ); - - //always set pointers null after deleting - delete pathvec; pathvec = NULL; - delete cbc1; delete cbc2; cbc1 = cbc2 = NULL; - } - - for (m = 2; m < pv.size(); m++) - { - path_outline = Path(); - path_outline.LoadPath(pv[m], Geom::Affine(), false, false); - path_outline.OutsideOutline(&path_tangent, line_width / 2, join_straight, linecap_type, 10); - - delete pathvec; pathvec = NULL; - pathvec = path_tangent.MakePathVector(); - - Geom::Curve *cbc1 = path_builder[path_builder.size() - 1].duplicate(); - Geom::Curve *cbc2 = (*pathvec)[0][0].duplicate(); - - reflect_curves(path_builder, cbc1, cbc2, (*pathvec)[0].initialPoint(), miter_limit ); - path_builder.append( (*pathvec)[0] ); - - delete pathvec; pathvec = NULL; - delete cbc1; delete cbc2; cbc1 = cbc2 = NULL; - } - - return path_builder; - } - - static Geom::PathVector outlinePath(const Geom::PathVector& path_in, double line_width, JoinType join, ButtType butt, double miter_lim) - { - Path p = Path(); - Path outlinepath = Path(); - for (unsigned i = 0; i < path_in.size(); i++) - { - p.LoadPath(path_in[i], Geom::Affine(), false, ( (i==0) ? false : true)); - } - - Geom::PathVector path_out; - for (unsigned lmnop = 0; lmnop < path_in.size(); lmnop++) - { - if (path_in[lmnop].size() > 1) - { - Geom::Path p_init; - Geom::Path p_rev; - Geom::PathBuilder pb = Geom::PathBuilder(); - - if ( !path_in[lmnop].closed() ) - { - p_init = Outline::half_outline( path_in[lmnop], -line_width, butt, - miter_lim ); - p_rev = Outline::half_outline( path_in[lmnop].reverse(), -line_width, butt, - miter_lim ); - - pb.moveTo(p_init.initialPoint() ); - pb.append(p_init); - - //cap - if (butt == butt_straight) { - pb.lineTo(p_rev.initialPoint() ); - } else if (butt == butt_round) { - pb.arcTo((-line_width) / 2, (-line_width) / 2, 0., true, true, p_rev.initialPoint() ); - } else if (butt == butt_square) { - //don't know what to do - pb.lineTo(p_rev.initialPoint() ); - } else if (butt == butt_pointy) { - //don't know what to do - pb.lineTo(p_rev.initialPoint() ); - } - - pb.append(p_rev); - - if (butt == butt_straight) { - pb.lineTo(p_init.initialPoint() ); - } else if (butt == butt_round) { - pb.arcTo((-line_width) / 2, (-line_width) / 2, 0., true, true, p_init.initialPoint() ); - } else if (butt == butt_square) { - //don't know what to do - pb.lineTo(p_init.initialPoint() ); - } else if (butt == butt_pointy) { - //don't know what to do - //Geom::Point end_deriv = Geom::unitTangentAt( Geom::reverse(path_in[lmnop].toPwSb()[path_in[lmnop].size()]), 0); - //double radius = 0.5 * Geom::distance(path_in[lmnop].finalPoint(), p_rev.initialPoint()); - - pb.lineTo(p_init.initialPoint() ); - } - } - else - { - //final join - //refer to half_outline for documentation - Geom::Path p_almost = path_in[lmnop]; - p_almost.appendNew ( path_in[lmnop].initialPoint() ); - p_init = Outline::half_outline( p_almost, -line_width, butt, - miter_lim ); - p_rev = Outline::half_outline( p_almost.reverse(), -line_width, butt, - miter_lim ); - p.LoadPath(path_in[lmnop], Geom::Affine(), false, false); - - //this is a kludge, because I can't find how to make this work properly - bool lastIsLinear = ( (Geom::distance(path_in[lmnop].finalPoint(), - path_in[lmnop] [path_in[lmnop].size() - 1].finalPoint())) == - (path_in[lmnop] [path_in[lmnop].size()].length())); - - p_almost = p_init; - if (lastIsLinear) - { - p_almost.erase_last(); p_almost.erase_last(); - } - - //outside test - Geom::Curve* cbc1 = p_almost[p_almost.size() - 1].duplicate(); - Geom::Curve* cbc2 = p_almost[0].duplicate(); - - Geom::Crossings cross = Geom::crossings(*cbc1, *cbc2); - - if (cross.empty()) - { - //this is the outside path - - //reuse the old one - p_init = p_almost; - Outline::reflect_curves(p_init, cbc1, cbc2, p_almost.initialPoint(), miter_lim ); - pb.moveTo(p_init.initialPoint()); pb.append(p_init); - } - else - { - //inside, carry on :-) - pb.moveTo(p_almost.initialPoint()); pb.append(p_almost); - } - - p_almost = p_rev; - if (lastIsLinear) - { - p_almost.erase(p_almost.begin() ); - p_almost.erase(p_almost.begin() ); - } - - delete cbc1; delete cbc2; cbc1 = cbc2 = NULL; - - cbc1 = p_almost[p_almost.size() - 1].duplicate(); - cbc2 = p_almost[0].duplicate(); - - cross = Geom::crossings(*cbc1, *cbc2); - - if (cross.empty()) - { - //outside path - - p_init = p_almost; - reflect_curves(p_init, cbc1, cbc2, p_almost.initialPoint(), miter_lim ); - pb.moveTo(p_init.initialPoint()); pb.append(p_init); - } - else - { - //inside - pb.moveTo(p_almost.initialPoint()); pb.append(p_almost); - } - delete cbc1; delete cbc2; cbc1 = cbc2 = NULL; - } - //pb.closePath(); - pb.flush(); - Geom::PathVector pv_np = pb.peek(); - //hack - for (unsigned abcd = 0; abcd < pv_np.size(); abcd++) - { - path_out.push_back( pv_np[abcd] ); - } - } - else - { - p.LoadPath(path_in[lmnop], Geom::Affine(), false, false); - p.Outline(&outlinepath, line_width / 2, join, butt, miter_lim); - std::vector *pv_p = outlinepath.MakePathVector(); - //hack - path_out.push_back( (*pv_p)[0].reverse() ); - delete pv_p; - } - } - return path_out; - } - static Geom::PathVector outlinePath_extr(const Geom::PathVector& path_in, double line_width, LineJoinType join, ButtType butt, double miter_lim) - { - Path p = Path(); - Path outlinepath = Path(); - for (unsigned i = 0; i < path_in.size(); i++) - { - p.LoadPath(path_in[i], Geom::Affine(), false, ( (i==0) ? false : true)); - } - - Geom::PathVector path_out; - for (unsigned lmnop = 0; lmnop < path_in.size(); lmnop++) - { - if (path_in[lmnop].size() > 1) - { - Geom::Path p_init; - Geom::Path p_rev; - Geom::PathBuilder pb = Geom::PathBuilder(); - - if ( !path_in[lmnop].closed() ) - { - p_init = Outline::half_outline_extrp( path_in[lmnop], -line_width, butt, - miter_lim ); - p_rev = Outline::half_outline_extrp( path_in[lmnop].reverse(), -line_width, butt, - miter_lim ); - - pb.moveTo(p_init.initialPoint() ); - pb.append(p_init); - - //cap - if (butt == butt_straight) { - pb.lineTo(p_rev.initialPoint() ); - } else if (butt == butt_round) { - pb.arcTo((-line_width) / 2, (-line_width) / 2, 0., true, true, p_rev.initialPoint() ); - } else if (butt == butt_square) { - //don't know what to do - pb.lineTo(p_rev.initialPoint() ); - } else if (butt == butt_pointy) { - //don't know what to do - pb.lineTo(p_rev.initialPoint() ); - } - - pb.append(p_rev); - - if (butt == butt_straight) { - pb.lineTo(p_init.initialPoint() ); - } else if (butt == butt_round) { - pb.arcTo((-line_width) / 2, (-line_width) / 2, 0., true, true, p_init.initialPoint() ); - } else if (butt == butt_square) { - //don't know what to do - pb.lineTo(p_init.initialPoint() ); - } else if (butt == butt_pointy) { - //don't know what to do - //Geom::Point end_deriv = Geom::unitTangentAt( Geom::reverse(path_in[lmnop].toPwSb()[path_in[lmnop].size()]), 0); - //double radius = 0.5 * Geom::distance(path_in[lmnop].finalPoint(), p_rev.initialPoint()); - - pb.lineTo(p_init.initialPoint() ); - } - } - else - { - //final join - //refer to half_outline for documentation - Geom::Path p_almost = path_in[lmnop]; - p_almost.appendNew ( path_in[lmnop].initialPoint() ); - p_init = Outline::half_outline_extrp( p_almost, -line_width, butt, - miter_lim ); - p_rev = Outline::half_outline_extrp( p_almost.reverse(), -line_width, butt, - miter_lim ); - p.LoadPath(path_in[lmnop], Geom::Affine(), false, false); - - //this is a kludge, because I can't find how to make this work properly - bool lastIsLinear = ( (Geom::distance(path_in[lmnop].finalPoint(), - path_in[lmnop] [path_in[lmnop].size() - 1].finalPoint())) == - (path_in[lmnop] [path_in[lmnop].size()].length())); - - p_almost = p_init; - if (lastIsLinear) - { - p_almost.erase_last(); p_almost.erase_last(); - } - - //outside test - Geom::Curve* cbc1 = p_almost[p_almost.size() - 1].duplicate(); - Geom::Curve* cbc2 = p_almost[0].duplicate(); - - Geom::Crossings cross = Geom::crossings(*cbc1, *cbc2); - - if (cross.empty()) - { - //this is the outside path - - //reuse the old one - p_init = p_almost; - Outline::extrapolate_curves(p_init, cbc1, cbc2, p_almost.initialPoint(), miter_lim ); - pb.moveTo(p_init.initialPoint()); pb.append(p_init); - } - else - { - //inside, carry on :-) - pb.moveTo(p_almost.initialPoint()); pb.append(p_almost); - } - - p_almost = p_rev; - if (lastIsLinear) - { - p_almost.erase(p_almost.begin() ); - p_almost.erase(p_almost.begin() ); - } - - delete cbc1; delete cbc2; cbc1 = cbc2 = NULL; - - cbc1 = p_almost[p_almost.size() - 1].duplicate(); - cbc2 = p_almost[0].duplicate(); - - cross = Geom::crossings(*cbc1, *cbc2); - - if (cross.empty()) - { - //outside path - - p_init = p_almost; - extrapolate_curves(p_init, cbc1, cbc2, p_almost.initialPoint(), miter_lim ); - pb.moveTo(p_init.initialPoint()); pb.append(p_init); - } - else - { - //inside - pb.moveTo(p_almost.initialPoint()); pb.append(p_almost); - } - delete cbc1; delete cbc2; cbc1 = cbc2 = NULL; - } - //pb.closePath(); - pb.flush(); - Geom::PathVector pv_np = pb.peek(); - //hack - for (unsigned abcd = 0; abcd < pv_np.size(); abcd++) - { - path_out.push_back( pv_np[abcd] ); - } - } - else - { - p.LoadPath(path_in[lmnop], Geom::Affine(), false, false); - p.Outline(&outlinepath, line_width / 2, join_pointy, butt, miter_lim); - std::vector *pv_p = outlinepath.MakePathVector(); - //hack - path_out.push_back( (*pv_p)[0].reverse() ); - delete pv_p; - } - } - return path_out; - } - - -} // namespace Outline - -/* - 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:encoding=utf-8:textwidth=99 : +#ifndef _SEEN_PATH_OUTLINE_H +#define _SEEN_PATH_OUTLINE_H + +#include +#include + +enum LineJoinType { + LINEJOIN_STRAIGHT, + LINEJOIN_ROUND, + LINEJOIN_POINTY, + LINEJOIN_REFLECTED, + LINEJOIN_EXTRAPOLATED +}; + +namespace Outline +{ + unsigned bezierOrder (const Geom::Curve* curve_in); + std::vector PathVectorOutline(std::vector const & path_in, double line_width, ButtType linecap_type, + join_typ linejoin_type, double miter_limit); + + Geom::PathVector outlinePath(const Geom::PathVector& path_in, double line_width, JoinType join, ButtType butt, double miter_lim); + Geom::PathVector outlinePath_extr(const Geom::PathVector& path_in, double line_width, LineJoinType join, ButtType butt, double miter_lim); +} + +#endif // _SEEN_PATH_OUTLINE_H diff --git a/src/ui/dialog/objects.cpp b/src/ui/dialog/objects.cpp index 338233042..85583a0e7 100644 --- a/src/ui/dialog/objects.cpp +++ b/src/ui/dialog/objects.cpp @@ -1887,8 +1887,9 @@ ObjectsPanel::ObjectsPanel() : btn = Gtk::manage( new Gtk::Button() ); btn->set_tooltip_text(_("Collapse All")); #if GTK_CHECK_VERSION(3,10,0) - btn->set_from_icon_name(INKSCAPE_ICON("gtk-unindent-ltr"), Gtk::ICON_SIZE_SMALL_TOOLBAR); + btn->set_image_from_icon_name(INKSCAPE_ICON("gtk-unindent-ltr"), Gtk::ICON_SIZE_SMALL_TOOLBAR); #else + image_remove = Gtk::manage(new Gtk::Image()); image_remove->set_from_icon_name(INKSCAPE_ICON("gtk-unindent-ltr"), Gtk::ICON_SIZE_SMALL_TOOLBAR); btn->set_image(*image_remove); #endif -- cgit v1.2.3 From 7d6a2eac770b159a51183add6917eaec36729d80 Mon Sep 17 00:00:00 2001 From: "Liam P. White" Date: Sun, 23 Mar 2014 17:25:49 -0400 Subject: tiny bugfix for Taper Strokes (bzr r13090.1.30) --- src/live_effects/lpe-taperstroke.cpp | 54 ++++++++++++++++++++------------ src/live_effects/pathoutlineprovider.cpp | 33 +++++++++++++++++++ src/live_effects/pathoutlineprovider.h | 1 + 3 files changed, 68 insertions(+), 20 deletions(-) (limited to 'src') diff --git a/src/live_effects/lpe-taperstroke.cpp b/src/live_effects/lpe-taperstroke.cpp index a862417d7..0e709f3ac 100644 --- a/src/live_effects/lpe-taperstroke.cpp +++ b/src/live_effects/lpe-taperstroke.cpp @@ -324,40 +324,54 @@ Geom::PathVector LPETaperStroke::doEffect_path(Geom::PathVector const& path_in) if (true) { Geom::PathVector real_pathv; + Geom::Path real_path; //Construct the pattern (pat_str stands for pattern string) - char pat_str[200]; - sprintf(pat_str, "M 1,0 1,1 C %5.5f,1 0,0.5 0,0.5 0,0.5 %5.5f,0 1,0 Z", 1 - (double)smoothing, 1 - (double)smoothing); - Geom::PathVector pat_vec = sp_svg_read_pathv(pat_str); + std::stringstream pat_str; + pat_str << "M 1,0 1,1 C " << 1 - (double)smoothing << ",1 0,0.5 0,0.5 0,0.5 " << 1 - double(smoothing) << ",0 1,0"; + + Geom::PathVector pat_vec = sp_svg_read_pathv(pat_str.str().c_str()); Geom::Piecewise > pwd2; pwd2.concat(stretch_along(pathv_out[0].toPwSb(), pat_vec[0], line_width)); - real_pathv.push_back(path_from_piecewise(pwd2, 0.001)[0]); + Geom::Path throwaway_path = path_from_piecewise(pwd2, 0.001)[0].reverse(); + throwaway_path.erase_last(); - Geom::PathVector sht_path; - sht_path.push_back(pathv_out[1]); - sht_path = Outline::PathVectorOutline(sht_path, line_width, butt_straight, static_cast(join_type.get_value()) , miter_limit); + real_path.append(throwaway_path); //wtf - real_pathv.push_back(sht_path[0]); + throwaway_path = Outline::PathOutsideOutline(pathv_out[1], + line_width, static_cast(join_type.get_value()), miter_limit); + + throwaway_path.setInitial(real_path.finalPoint()); + real_path.append(throwaway_path); - char pat_str_1[200]; - sprintf(pat_str_1, "M 0,0 0,1 C %5.5f,1 1,0.5 1,0.5 1,0.5 %5.5f,0 0,0 Z", (double)smoothing, (double)smoothing); - pat_vec = sp_svg_read_pathv(pat_str_1); + std::stringstream pat_str_1; + pat_str_1 << "M 0,0 0,1 C " << (double)smoothing << ",1 1,0.5 1,0.5 1,0.5 " << double(smoothing) << ",0 0,0"; + pat_vec = sp_svg_read_pathv(pat_str_1.str().c_str()); pwd2 = Geom::Piecewise > (); pwd2.concat(stretch_along(pathv_out[2].toPwSb(), pat_vec[0], line_width)); - real_pathv.push_back(path_from_piecewise(pwd2, 0.001)[0].reverse()); - //clever union - //Geom::Shape shape1 = Geom::sanitize(Geom::PathVector(1, real_pathv[0])); - //Geom::Shape shape2 = Geom::sanitize(Geom::PathVector(1, real_pathv[1])); - //Geom::Shape shape3 = Geom::boolop(shape1, shape2, Geom::BOOLOP_UNION); + throwaway_path = Geom::Path(); + throwaway_path = path_from_piecewise(pwd2, 0.001)[0]; + throwaway_path.setInitial(real_path.finalPoint()); + real_path.append(throwaway_path); + + throwaway_path = Geom::Path(); + throwaway_path = Outline::PathOutsideOutline(pathv_out[1].reverse(), + line_width, static_cast(join_type.get_value()), miter_limit); + + //throwaway_path = throwaway_path.reverse(); + throwaway_path.setInitial(real_path.finalPoint()); + + real_path.append(throwaway_path); + //real_path.close(); + + real_pathv.push_back(real_path); - //shape2 = Geom::sanitize(Geom::PathVector(1, real_pathv[2])); - //shape1 = Geom::boolop(shape3, shape2, Geom::BOOLOP_UNION); + //real_pathv.push_back(path_from_piecewise(pwd2, 0.001)[0].reverse()); - //real_pathv = Geom::desanitize(shape1); return real_pathv; } @@ -383,7 +397,7 @@ Geom::PathVector LPETaperStroke::doEffect_simplePath(Geom::PathVector const & pa trimmed_start.append(path_in[0] [i]); } - #define OVERLAP (0.001 / (line_width < 1 ? 1 : line_width)) + #define OVERLAP 0 /*(0.001 / (line_width < 1 ? 1 : line_width))*/ trimmed_start.append(*subdivide_at(curve_start, (attach_start - loc) + OVERLAP, true)); curve_start = subdivide_at(curve_start, attach_start - loc, false); diff --git a/src/live_effects/pathoutlineprovider.cpp b/src/live_effects/pathoutlineprovider.cpp index e62f516c9..302756c7c 100755 --- a/src/live_effects/pathoutlineprovider.cpp +++ b/src/live_effects/pathoutlineprovider.cpp @@ -825,6 +825,39 @@ Geom::PathVector PathVectorOutline(Geom::PathVector const & path_in, double line #undef miter_lim return path_out; } +Geom::Path PathOutsideOutline(Geom::Path const & path_in, double line_width, LineJoinType linejoin_type, double miter_limit) +{ + + #define miter_lim fabs(line_width * miter_limit) + + Geom::Path path_out; + + if (linejoin_type <= LINEJOIN_POINTY || path_in.size() <= 1) { + + Geom::PathVector * pathvec; + + Path path_tangent = Path(); + Path path_outline = Path(); + path_outline.LoadPath(path_in, Geom::Affine(), false, false); + path_outline.OutsideOutline(&path_tangent, line_width / 2, static_cast(linejoin_type), butt_straight, miter_lim); + + pathvec = path_tangent.MakePathVector(); + path_out = pathvec[0]/* deref pointer */[0]/*actual object ref*/; + delete pathvec; + return path_out; + } + else if (linejoin_type == LINEJOIN_REFLECTED) { + //reflected half outline + Geom::PathVector pathvec; pathvec.push_back(path_in); + path_out = half_outline(path_in, line_width, butt_straight, miter_lim); + return path_out; + } + else if (linejoin_type == LINEJOIN_EXTRAPOLATED) { + path_out = half_outline_extrp(path_in, line_width, butt_straight, miter_lim); + return path_out; + } + return path_out; +} } // namespace Outline diff --git a/src/live_effects/pathoutlineprovider.h b/src/live_effects/pathoutlineprovider.h index 1a363c35b..4133f47c2 100644 --- a/src/live_effects/pathoutlineprovider.h +++ b/src/live_effects/pathoutlineprovider.h @@ -20,6 +20,7 @@ namespace Outline Geom::PathVector outlinePath(const Geom::PathVector& path_in, double line_width, JoinType join, ButtType butt, double miter_lim); Geom::PathVector outlinePath_extr(const Geom::PathVector& path_in, double line_width, LineJoinType join, ButtType butt, double miter_lim); + Geom::Path PathOutsideOutline(Geom::Path const & path_in, double line_width, LineJoinType linejoin_type, double miter_limit); } #endif // _SEEN_PATH_OUTLINE_H -- cgit v1.2.3 From f928fc556c8d7824dd920171b5de534cee4fe4ad Mon Sep 17 00:00:00 2001 From: "Liam P. White" Date: Wed, 26 Mar 2014 21:32:07 -0400 Subject: Small performance and bug fixes (bzr r13090.1.33) --- src/live_effects/effect.cpp | 2 +- src/live_effects/lpe-taperstroke.cpp | 169 +++++++++++++++++++++-------------- 2 files changed, 101 insertions(+), 70 deletions(-) (limited to 'src') diff --git a/src/live_effects/effect.cpp b/src/live_effects/effect.cpp index d6840e5b8..337fe631f 100644 --- a/src/live_effects/effect.cpp +++ b/src/live_effects/effect.cpp @@ -5,7 +5,7 @@ * Released under GNU GPL, read the file 'COPYING' for more information */ -//#define LPE_ENABLE_TEST_EFFECTS //uncomment for toy effects +#define LPE_ENABLE_TEST_EFFECTS //uncomment for toy effects #ifdef HAVE_CONFIG_H # include "config.h" diff --git a/src/live_effects/lpe-taperstroke.cpp b/src/live_effects/lpe-taperstroke.cpp index 91b8fd7bc..4ae1de923 100644 --- a/src/live_effects/lpe-taperstroke.cpp +++ b/src/live_effects/lpe-taperstroke.cpp @@ -232,9 +232,9 @@ Geom::Path return_at_first_cusp (Geom::Path const & path_in, double smooth_toler return path_out; } -Geom::Curve * subdivide_at(const Geom::Curve* curve_in, Geom::Coord time, bool first); Geom::Piecewise > stretch_along(Geom::Piecewise > pwd2_in, Geom::Path pattern, double width); + Geom::PathVector LPETaperStroke::doEffect_path(Geom::PathVector const& path_in) { Geom::Path first_cusp = return_at_first_cusp(path_in[0]); @@ -255,21 +255,21 @@ Geom::PathVector LPETaperStroke::doEffect_path(Geom::PathVector const& path_in) } //don't ever let it be zero - if (attach_start <= 0) { + if (attach_start <= 0.00000001) { attach_start.param_set_value( 0.00000001 ); + zeroStart = true; } - if (attach_end <= 0) { + if (attach_end <= 0.00000001) { attach_end.param_set_value( 0.00000001 ); + zeroEnd = true; } //don't let it be integer if (double(unsigned(attach_start)) == attach_start) { attach_start.param_set_value(attach_start - 0.00000001); - zeroStart = true; } if (double(unsigned(attach_end)) == attach_end) { - attach_end.param_set_value(attach_end - 0.00000001); - zeroStart = true; + attach_end.param_set_value(attach_end - 0.00000001); } unsigned allowed_start = first_cusp.size(); @@ -302,14 +302,11 @@ Geom::PathVector LPETaperStroke::doEffect_path(Geom::PathVector const& path_in) if (!zeroStart) { //Construct the pattern (pat_str stands for pattern string) (yes, this is easier, trust me) std::stringstream pat_str; - pat_str << "M 1,0 1,1 C " << 1 - (double)smoothing << ",1 0,0.5 0,0.5 0,0.5 " << 1 - double(smoothing) << ",0 1,0"; + pat_str << "M 1,0 C " << 1 - (double)smoothing << ",0 0,0.5 0,0.5 0,0.5 " << 1 - (double)smoothing << ",1 1,1"; - pat_vec = sp_svg_read_pathv(pat_str.str().c_str()); - - pwd2.concat(stretch_along(pathv_out[0].toPwSb(), pat_vec[0], line_width)); - - throwaway_path = Geom::path_from_piecewise(pwd2, 0.001)[0].reverse(); - throwaway_path.erase_last(); //wtf + pat_vec = sp_svg_read_pathv(pat_str.str().c_str()); + pwd2.concat(stretch_along(pathv_out[0].toPwSb(), pat_vec[0], line_width)); + throwaway_path = Geom::path_from_piecewise(pwd2, 0.001)[0]; real_path.append(throwaway_path); } @@ -317,8 +314,12 @@ Geom::PathVector LPETaperStroke::doEffect_path(Geom::PathVector const& path_in) throwaway_path = Outline::PathOutsideOutline(pathv_out[1], line_width, static_cast(join_type.get_value()), miter_limit); - throwaway_path.setInitial(real_path.finalPoint()); - real_path.append(throwaway_path); + if (!zeroStart) { + throwaway_path.setInitial(real_path.finalPoint()); + real_path.append(throwaway_path); + } else { + real_path.append(throwaway_path, Geom::Path::STITCH_DISCONTINUOUS); + } if (!zeroEnd) { //append the ending taper @@ -336,10 +337,13 @@ Geom::PathVector LPETaperStroke::doEffect_path(Geom::PathVector const& path_in) //append the inside outline of the path (against direction) throwaway_path = Outline::PathOutsideOutline(pathv_out[1].reverse(), line_width, static_cast(join_type.get_value()), miter_limit); - - throwaway_path.setInitial(real_path.finalPoint()); - - real_path.append(throwaway_path); + + if (!zeroEnd) { + throwaway_path.setInitial(real_path.finalPoint()); + real_path.append(throwaway_path); + } else { + real_path.append(throwaway_path, Geom::Path::STITCH_DISCONTINUOUS); + } real_path.close(); real_pathv.push_back(real_path); @@ -355,7 +359,7 @@ Geom::PathVector LPETaperStroke::doEffect_simplePath(Geom::PathVector const & pa //do subdivision and get out unsigned loc = (unsigned)attach_start; Geom::Curve * curve_start = path_in[0] [loc].duplicate(); - + std::vector pathv_out; Geom::Path path_out = Geom::Path(); @@ -365,25 +369,69 @@ Geom::PathVector LPETaperStroke::doEffect_simplePath(Geom::PathVector const & pa for (unsigned i = 0; i < loc; i++) { trimmed_start.append(path_in[0] [i]); } - - - trimmed_start.append(*subdivide_at(curve_start, (attach_start - loc), true)); - curve_start = subdivide_at(curve_start, attach_start - loc, false); + + + //this is pretty annoying + //previously I wrote a function for this but it wasted a lot of time + //so I optimized it back into here. + unsigned order = Outline::bezierOrder(curve_start); + switch (order) { + case 3: { + Geom::CubicBezier *cb = static_cast(curve_start); + std::pair cb_pair = cb->subdivide((attach_start - loc)); + trimmed_start.append(cb_pair.first); curve_start = cb_pair.second.duplicate(); //goes out of scope + break; + } + case 2: { + Geom::QuadraticBezier *qb = static_cast(curve_start); + std::pair qb_pair = qb->subdivide((attach_start - loc)); + trimmed_start.append(qb_pair.first); curve_start = qb_pair.second.duplicate(); + break; + } + case 1: { + Geom::BezierCurveN<1> *lb = static_cast * >(curve_start); + std::pair, Geom::BezierCurveN<1> > lb_pair = lb->subdivide((attach_start - loc)); + trimmed_start.append(lb_pair.first); curve_start = lb_pair.second.duplicate(); + break; + } + } //special case: path is one segment long //special case: what if the two knots occupy the same segment? if ((size == 1) || ( size - unsigned(attach_end) - 1 == loc )) { Geom::Coord t = Geom::nearest_point(end_attach_point, *curve_start); + //it is just a dumb segment //we have to do some shifting here because the value changed when we reduced the length //of the previous segment. - trimmed_end.append(*subdivide_at(curve_start, t, false)); + + order = Outline::bezierOrder(curve_start); + switch (order) { + case 3: { + Geom::CubicBezier *cb = static_cast(curve_start); + std::pair cb_pair = cb->subdivide(t); + trimmed_end.append(cb_pair.second); curve_start = cb_pair.first.duplicate(); + break; + } + case 2: { + Geom::QuadraticBezier *qb = static_cast(curve_start); + std::pair qb_pair = qb->subdivide(t); + trimmed_end.append(qb_pair.second); curve_start = qb_pair.first.duplicate(); + break; + } + case 1: { + Geom::BezierCurveN<1> *lb = static_cast * >(curve_start); + std::pair, Geom::BezierCurveN<1> > lb_pair = lb->subdivide(t); + trimmed_end.append(lb_pair.second); curve_start = lb_pair.first.duplicate(); + break; + } + } + for (unsigned j = (size - attach_end) + 1; j < size; j++) { trimmed_end.append(path_in[0] [j]); } - curve_start = subdivide_at(curve_start, t, true); path_out.append(*curve_start); pathv_out.push_back(trimmed_start); pathv_out.push_back(path_out); @@ -406,9 +454,28 @@ Geom::PathVector LPETaperStroke::doEffect_simplePath(Geom::PathVector const & pa Geom::Curve * curve_end = path_in[0] [loc].duplicate(); Geom::Coord t = Geom::nearest_point(end_attach_point, *curve_end); - - trimmed_end.append(*subdivide_at(curve_end, t, false)); - curve_end = subdivide_at(curve_end, t, true); + + order = Outline::bezierOrder(curve_end); + switch (order) { + case 3: { + Geom::CubicBezier *cb = static_cast(curve_end); + std::pair cb_pair = cb->subdivide(t); + trimmed_end.append(cb_pair.second); curve_end = cb_pair.first.duplicate(); + break; + } + case 2: { + Geom::QuadraticBezier *qb = static_cast(curve_end); + std::pair qb_pair = qb->subdivide(t); + trimmed_end.append(qb_pair.second); curve_end = qb_pair.first.duplicate(); + break; + } + case 1: { + Geom::BezierCurveN<1> *lb = static_cast * >(curve_end); + std::pair, Geom::BezierCurveN<1> > lb_pair = lb->subdivide(t); + trimmed_end.append(lb_pair.second); curve_end = lb_pair.first.duplicate(); + break; + } + } for (unsigned j = (size - attach_end) + 1; j < size; j++) { trimmed_end.append(path_in[0] [j]); @@ -424,44 +491,6 @@ Geom::PathVector LPETaperStroke::doEffect_simplePath(Geom::PathVector const & pa return pathv_out; } -Geom::Curve * subdivide_at(const Geom::Curve* curve_in, Geom::Coord time, bool first) -{ - //the only reason for this function is the lack of a subdivide function in the Curve class. - //you have to cast to Beziers to be able to use subdivide(t) - unsigned order = Outline::bezierOrder(curve_in); - Geom::Curve* curve_out = curve_in->duplicate(); - switch (order) - { - //these need to be scoped because of the variable 'c' - case 3: - { - Geom::CubicBezier c = first ? (dynamic_cast (curve_out))->subdivide(time).first : - (dynamic_cast (curve_out))->subdivide(time).second; - if (curve_out) delete curve_out; - curve_out = c.duplicate(); - break; - } - case 2: - { - Geom::QuadraticBezier c = first ? (dynamic_cast(curve_out))->subdivide(time).first : - (dynamic_cast(curve_out))->subdivide(time).second; - if (curve_out) delete curve_out; - curve_out = c.duplicate(); - break; - } - case 1: - { - Geom::BezierCurveN<1> c = first ? (dynamic_cast* >(curve_out))->subdivide(time).first : - (dynamic_cast* >(curve_out))->subdivide(time).second; - if (curve_out) delete curve_out; - curve_out = c.duplicate(); - break; - } - } - return curve_out; -} - - //most of the below code is verbatim from Pattern Along Path. However, it needed a little //tweaking to get it to work right in this case. @@ -587,8 +616,9 @@ namespace TpS { Piecewise > pwd2; Geom::Path p_in = return_at_first_cusp(pathv[0]); pwd2.concat(p_in.toPwSb()); + std::vector > > pwd_vec = split_at_discontinuities(pwd2); - double t0 = nearest_point(s, pwd2); + double t0 = nearest_point(s, pwd_vec[0]); lpe->attach_start.param_set_value(t0); // FIXME: this should not directly ask for updating the item. It should write to SVG, which triggers updating. @@ -607,8 +637,9 @@ namespace TpS { Piecewise > pwd2; Geom::Path p_in = return_at_first_cusp(pathv[0].reverse()); pwd2.concat(p_in.toPwSb()); + std::vector > > pwd_vec = split_at_discontinuities(pwd2); - double t0 = nearest_point(s, pwd2); + double t0 = nearest_point(s, pwd_vec[0]); lpe->attach_end.param_set_value(t0); // FIXME: this should not directly ask for updating the item. It should write to SVG, which triggers updating. -- cgit v1.2.3 From 8a082e274bc322596c217bbe7770904a3cb50cc2 Mon Sep 17 00:00:00 2001 From: "Liam P. White" Date: Sat, 29 Mar 2014 15:28:44 -0400 Subject: Fix build errors and a few small bugs (bzr r13090.1.36) --- src/live_effects/lpe-taperstroke.cpp | 4 ++-- .../parameter/powerstrokepointarray.cpp | 2 +- src/live_effects/pathoutlineprovider.cpp | 25 ++++++++++++++++++---- 3 files changed, 24 insertions(+), 7 deletions(-) mode change 100644 => 100755 src/live_effects/lpe-taperstroke.cpp (limited to 'src') diff --git a/src/live_effects/lpe-taperstroke.cpp b/src/live_effects/lpe-taperstroke.cpp old mode 100644 new mode 100755 index 8e6edfa2f..0e9752d31 --- a/src/live_effects/lpe-taperstroke.cpp +++ b/src/live_effects/lpe-taperstroke.cpp @@ -279,10 +279,10 @@ Geom::PathVector LPETaperStroke::doEffect_path(Geom::PathVector const& path_in) //don't let it be integer if (double(unsigned(attach_start)) == attach_start) { - attach_start.param_set_value(attach_start - 0.00000001); + attach_start.param_set_value(attach_start - 0.00001); } if (double(unsigned(attach_end)) == attach_end) { - attach_end.param_set_value(attach_end - 0.00000001); + attach_end.param_set_value(attach_end - 0.00001); } unsigned allowed_start = first_cusp.size(); diff --git a/src/live_effects/parameter/powerstrokepointarray.cpp b/src/live_effects/parameter/powerstrokepointarray.cpp index 7fa837689..4ed8998fa 100644 --- a/src/live_effects/parameter/powerstrokepointarray.cpp +++ b/src/live_effects/parameter/powerstrokepointarray.cpp @@ -202,7 +202,7 @@ PowerStrokePointArrayParamKnotHolderEntity::knot_get() const void PowerStrokePointArrayParamKnotHolderEntity::knot_set_offset(Geom::Point offset) { _pparam->_vector.at(_index) = Geom::Point(offset.x(), offset.y() / 2); - this->parent_holder->knot_ungrabbed_handler(this->knot); + this->parent_holder->knot_ungrabbed_handler(this->knot, 0); } void diff --git a/src/live_effects/pathoutlineprovider.cpp b/src/live_effects/pathoutlineprovider.cpp index a5a7a044f..2a0da05b4 100755 --- a/src/live_effects/pathoutlineprovider.cpp +++ b/src/live_effects/pathoutlineprovider.cpp @@ -220,8 +220,8 @@ bool outside_angle (const Geom::Curve& cbc1, const Geom::Curve& cbc2) void extrapolate_curves(Geom::Path& path_builder, Geom::Curve* cbc1, Geom::Curve* cbc2, Geom::Point endPt, double miter_limit, bool outside = false) { - - if ( outside ) { + bool lineProblem = (dynamic_cast *>(cbc1)) || (dynamic_cast *>(cbc2)); + if ( outside && !lineProblem ) { Geom::Path pth; pth.append(*cbc1); @@ -273,9 +273,26 @@ void extrapolate_curves(Geom::Path& path_builder, Geom::Curve* cbc1, Geom::Curve } path_builder.appendNew (endPt); } - } else { + } + if ( outside && lineProblem ) { + Geom::Path pth; + pth.append(*cbc1); + Geom::Point tang1 = Geom::unitTangentAt(Geom::reverse(pth.toPwSb()[0]), 0.); + pth = Geom::Path(); + pth.append( *cbc2 ); + Geom::Point tang2 = Geom::unitTangentAt(pth.toPwSb()[0], 0); + + boost::optional p = intersection_point (cbc1->finalPoint(), tang1, + cbc2->initialPoint(), tang2); + if (p) + { + path_builder.appendNew (*p); + } path_builder.appendNew (endPt); - } + } + if ( !outside ) { + path_builder.appendNew (endPt); + } } void reflect_curves(Geom::Path& path_builder, Geom::Curve* cbc1, Geom::Curve* cbc2, Geom::Point endPt, double miter_limit, bool outside = false) -- cgit v1.2.3 From e667170b1473faccbeabece0cef7d24ebf15bef9 Mon Sep 17 00:00:00 2001 From: "Liam P. White" Date: Sat, 29 Mar 2014 20:33:36 -0400 Subject: Minor fixes (bzr r13090.1.37) --- src/live_effects/lpe-taperstroke.cpp | 4 +- src/live_effects/pathoutlineprovider.cpp | 79 +++++++++++++++++++++++++------- 2 files changed, 65 insertions(+), 18 deletions(-) (limited to 'src') diff --git a/src/live_effects/lpe-taperstroke.cpp b/src/live_effects/lpe-taperstroke.cpp index 0e9752d31..b4e43209d 100755 --- a/src/live_effects/lpe-taperstroke.cpp +++ b/src/live_effects/lpe-taperstroke.cpp @@ -352,8 +352,8 @@ Geom::PathVector LPETaperStroke::doEffect_path(Geom::PathVector const& path_in) -fabs(line_width), static_cast(join_type.get_value()), miter_limit); if (!zeroEnd) { - throwaway_path.setInitial(real_path.finalPoint()); - real_path.append(throwaway_path); + //throwaway_path.setInitial(real_path.finalPoint()); + real_path.append(throwaway_path, Geom::Path::STITCH_DISCONTINUOUS); } else { real_path.append(throwaway_path, Geom::Path::STITCH_DISCONTINUOUS); } diff --git a/src/live_effects/pathoutlineprovider.cpp b/src/live_effects/pathoutlineprovider.cpp index 2a0da05b4..6a47285a0 100755 --- a/src/live_effects/pathoutlineprovider.cpp +++ b/src/live_effects/pathoutlineprovider.cpp @@ -1,5 +1,5 @@ #include "pathoutlineprovider.h" - +#include "livarot/path-description.h" #include <2geom/angle.h> #include <2geom/path.h> #include <2geom/circle.h> @@ -7,6 +7,7 @@ #include <2geom/shape.h> #include <2geom/transforms.h> #include <2geom/path-sink.h> +#include namespace Geom { @@ -163,7 +164,10 @@ bool outside_angle (const Geom::Curve& cbc1, const Geom::Curve& cbc2) Geom::Point end_point; //assert(cbc1.finalPoint() == cbc2.initialPoint()); + //short circuiting? if (cbc1.finalPoint() != cbc2.initialPoint()) { + printf("There was an issue when asserting that one curve's end is the start of the other. Line %d, File %s\n" + "By default we are going to say that this is an inside join, so we cannot make a line join for it.\n", __LINE__, __FILE__); return false; } switch (order) @@ -218,7 +222,8 @@ bool outside_angle (const Geom::Curve& cbc1, const Geom::Curve& cbc2) return false; } -void extrapolate_curves(Geom::Path& path_builder, Geom::Curve* cbc1, Geom::Curve* cbc2, Geom::Point endPt, double miter_limit, bool outside = false) +void extrapolate_curves(Geom::Path& path_builder, Geom::Curve* cbc1, Geom::Curve* cbc2, Geom::Point endPt, + double miter_limit, double line_width, bool outside = false) { bool lineProblem = (dynamic_cast *>(cbc1)) || (dynamic_cast *>(cbc2)); if ( outside && !lineProblem ) { @@ -269,7 +274,13 @@ void extrapolate_curves(Geom::Path& path_builder, Geom::Curve* cbc1, Geom::Curve cbc2->initialPoint(), tang2); if (p) { - path_builder.appendNew (*p); + //check size of miter + Geom::Point point_on_path = cbc1->finalPoint() - rot90(tang1) * line_width; + Geom::Coord len = distance(*p, point_on_path); + if (len <= miter_limit) { + // miter OK + path_builder.appendNew (*p); + } } path_builder.appendNew (endPt); } @@ -286,7 +297,13 @@ void extrapolate_curves(Geom::Path& path_builder, Geom::Curve* cbc1, Geom::Curve cbc2->initialPoint(), tang2); if (p) { - path_builder.appendNew (*p); + //check size of miter + Geom::Point point_on_path = cbc1->finalPoint() - rot90(tang1) * line_width; + Geom::Coord len = distance(*p, point_on_path); + if (len <= miter_limit) { + // miter OK + path_builder.appendNew (*p); + } } path_builder.appendNew (endPt); } @@ -295,7 +312,8 @@ void extrapolate_curves(Geom::Path& path_builder, Geom::Curve* cbc1, Geom::Curve } } -void reflect_curves(Geom::Path& path_builder, Geom::Curve* cbc1, Geom::Curve* cbc2, Geom::Point endPt, double miter_limit, bool outside = false) +void reflect_curves(Geom::Path& path_builder, Geom::Curve* cbc1, Geom::Curve* cbc2, Geom::Point endPt, + double miter_limit, double line_width, bool outside = false) { //the most important work for the reflected join is done here @@ -332,7 +350,13 @@ void reflect_curves(Geom::Path& path_builder, Geom::Curve* cbc1, Geom::Curve* cb cbc2->initialPoint(), tang2); if (p) { - path_builder.appendNew (*p); + //check size of miter + Geom::Point point_on_path = cbc1->finalPoint() - rot90(tang1) * line_width; + Geom::Coord len = distance(*p, point_on_path); + if (len <= miter_limit) { + // miter OK + path_builder.appendNew (*p); + } } //bevel path_builder.appendNew( endPt ); @@ -395,10 +419,10 @@ Geom::Path doAdvHalfOutline(const Geom::Path& path_in, double line_width, double Geom::Curve * cbc2 = (*path_vec)[0] [0].duplicate(); //do the reflection/extrapolation: - if (extrapolate) { extrapolate_curves(path_builder, cbc1, cbc2, (*path_vec)[0].initialPoint(), miter_limit, - outside_angle ( pv[u - 1] [pv[u - 1].size()], pv[u] [0] )); } - else { reflect_curves (path_builder, cbc1, cbc2, (*path_vec)[0].initialPoint(), miter_limit, - outside_angle ( pv[u - 1] [pv[u - 1].size()], pv[u] [0] )); } + if (extrapolate) { extrapolate_curves(path_builder, cbc1, cbc2, (*path_vec)[0].initialPoint(), miter_limit, line_width, + outside_angle ( pv[u - 1] [pv[u - 1].size() - 1], pv[u] [0] )); } + else { reflect_curves (path_builder, cbc1, cbc2, (*path_vec)[0].initialPoint(), miter_limit, line_width, + outside_angle ( pv[u - 1] [pv[u - 1].size() - 1], pv[u] [0] )); } } path_builder.append( (*path_vec)[0] ); @@ -420,9 +444,9 @@ Geom::Path doAdvHalfOutline(const Geom::Path& path_in, double line_width, double Geom::Curve * cbc2 = (*path_vec)[0] [0].duplicate(); //do the reflection/extrapolation: - if (extrapolate) { extrapolate_curves(path_builder, cbc1, cbc2, (*path_vec)[0].initialPoint(), miter_limit, + if (extrapolate) { extrapolate_curves(path_builder, cbc1, cbc2, (*path_vec)[0].initialPoint(), miter_limit, line_width, outside_angle ( pv[u] [pv[u].size()-1], pv[u+1] [0] )); } - else { reflect_curves (path_builder, cbc1, cbc2, (*path_vec)[0].initialPoint(), miter_limit, + else { reflect_curves (path_builder, cbc1, cbc2, (*path_vec)[0].initialPoint(), miter_limit, line_width, outside_angle ( pv[u] [pv[u].size()-1], pv[u+1] [0] )); } //Now we can store it. @@ -449,10 +473,33 @@ Geom::PathVector outlinePath(const Geom::PathVector& path_in, double line_width, //since you've made it this far, hopefully all this is obvious :P Geom::Path with_direction; Geom::Path against_direction; - - with_direction = Outline::doAdvHalfOutline( path_in[i], -line_width, miter_lim, extrapolate ); - against_direction = Outline::doAdvHalfOutline( path_in[i].reverse(), -line_width, extrapolate ); - + if ( !path_in[i].closed() ) { + with_direction = Outline::doAdvHalfOutline( path_in[i], -line_width, miter_lim, extrapolate ); + against_direction = Outline::doAdvHalfOutline( path_in[i].reverse(), -line_width, miter_lim, extrapolate ); + } else { + //Geom::Path absolutely refuses to do what I want with these + Geom::Path newPath = path_in[i]; + newPath.close(false); + Geom::Piecewise > pwd2 = newPath.toPwSb(); + newPath = Geom::path_from_piecewise(pwd2, 0.01)[0]; + //fuk this + with_direction = Outline::doAdvHalfOutline( newPath, -line_width, miter_lim, extrapolate ); + against_direction = Outline::doAdvHalfOutline( newPath.reverse(), -line_width, miter_lim, extrapolate ); + + /*if (dynamic_cast *>(&newPath[newPath.size()])) { + //delete the 'Z' + newPath.erase_last(); + newPath.append(path_in[i][path_in[i].size() - 1]); + newPath.appendNew(newPath.initialPoint()); + newPath.erase_last(); + } else { + //delete the 'Z' + newPath.erase_last(); + newPath.append(path_in[i][path_in[i].size() - 1]); + newPath.appendNew(newPath.initialPoint()); + newPath.erase_last(); + }*/ + } Geom::PathBuilder pb; //add in the...do I really need to say this? -- cgit v1.2.3 From 355bfa5bf4d51f9d8c3fddf910a73ec7958d9a8a Mon Sep 17 00:00:00 2001 From: "Liam P. White" Date: Tue, 1 Apr 2014 18:38:26 -0400 Subject: Fix bug 1219324 (bzr r13090.1.40) --- src/sp-lpe-item.cpp | 15 +++++++++++++++ 1 file changed, 15 insertions(+) (limited to 'src') diff --git a/src/sp-lpe-item.cpp b/src/sp-lpe-item.cpp index 666c79e49..6324af147 100644 --- a/src/sp-lpe-item.cpp +++ b/src/sp-lpe-item.cpp @@ -36,6 +36,10 @@ #include "desktop.h" #include "shape-editor.h" #include "sp-ellipse.h" +#include "tools-switch.h" +#include "ui/tools/node-tool.h" +#include "ui/tools/tool-base.h" +#include "ui/tool/multi-path-manipulator.h" #include @@ -416,6 +420,17 @@ void SPLPEItem::addPathEffect(gchar *value, bool reset) // Apply the path effect sp_lpe_item_update_patheffect(this, true, true); + + //fix bug 1219324 + Inkscape::UI::Tools::NodeTool *tool = 0; + if (SP_ACTIVE_DESKTOP ) { + Inkscape::UI::Tools::ToolBase *ec = SP_ACTIVE_DESKTOP->event_context; + if (INK_IS_NODE_TOOL(ec)) { + tool = static_cast(ec); + tools_switch(SP_ACTIVE_DESKTOP, TOOLS_LPETOOL); //mhh + tools_switch(SP_ACTIVE_DESKTOP, TOOLS_NODES); + } + } } } -- cgit v1.2.3 From f3e0966f95dc4284b1fd191fb4c187c92c24aeed Mon Sep 17 00:00:00 2001 From: "Liam P. White" Date: Tue, 1 Apr 2014 20:40:15 -0400 Subject: Fix some stuff (bzr r13090.1.41) --- src/live_effects/effect.cpp | 10 +++++++++- src/live_effects/effect.h | 3 +++ src/sp-lpe-item.cpp | 13 +++++++++++-- 3 files changed, 23 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/live_effects/effect.cpp b/src/live_effects/effect.cpp index 337fe631f..8bf210270 100644 --- a/src/live_effects/effect.cpp +++ b/src/live_effects/effect.cpp @@ -5,7 +5,7 @@ * Released under GNU GPL, read the file 'COPYING' for more information */ -#define LPE_ENABLE_TEST_EFFECTS //uncomment for toy effects +//#define LPE_ENABLE_TEST_EFFECTS //uncomment for toy effects #ifdef HAVE_CONFIG_H # include "config.h" @@ -365,6 +365,14 @@ Effect::doBeforeEffect (SPLPEItem const*/*lpeitem*/) //Do nothing for simple effects } +void Effect::doAfterEffect (SPLPEItem const* lpeitem) +{ +} + +void Effect::doOnRemove (SPLPEItem const* lpeitem) +{ +} + /** * Effects can have a parameter path set before they are applied by accepting a nonzero number of * mouse clicks. This method activates the pen context, which waits for the specified number of diff --git a/src/live_effects/effect.h b/src/live_effects/effect.h index 1da9b4cc9..85c930def 100644 --- a/src/live_effects/effect.h +++ b/src/live_effects/effect.h @@ -55,6 +55,9 @@ public: virtual void doOnApply (SPLPEItem const* lpeitem); virtual void doBeforeEffect (SPLPEItem const* lpeitem); + + virtual void doAfterEffect (SPLPEItem const* lpeitem); + virtual void doOnRemove (SPLPEItem const* lpeitem); void writeParamsToSVG(); diff --git a/src/sp-lpe-item.cpp b/src/sp-lpe-item.cpp index 6324af147..71aa9545a 100644 --- a/src/sp-lpe-item.cpp +++ b/src/sp-lpe-item.cpp @@ -16,6 +16,9 @@ # include "config.h" #endif +//the gtk devs are really not smart about backwards compatibility +#include "ui/tool/multi-path-manipulator.h" + #include #include "live_effects/effect.h" @@ -39,7 +42,6 @@ #include "tools-switch.h" #include "ui/tools/node-tool.h" #include "ui/tools/tool-base.h" -#include "ui/tool/multi-path-manipulator.h" #include @@ -254,6 +256,9 @@ bool SPLPEItem::performPathEffect(SPCurve *curve) { } return false; } + if (!SP_IS_GROUP(this)) { + lpe->doAfterEffect(this); + } } } } @@ -447,11 +452,15 @@ void SPLPEItem::removeCurrentPathEffect(bool keep_paths) Inkscape::LivePathEffect::LPEObjectReference* lperef = this->getCurrentLPEReference(); if (!lperef) return; - + + Inkscape::LivePathEffect::Effect * lpe = this->getCurrentLPE(); + lpe->doOnRemove(this); + PathEffectList new_list = *this->path_effect_list; new_list.remove(lperef); //current lpe ref is always our 'own' pointer from the path_effect_list std::string r = patheffectlist_write_svg(new_list); + if (!r.empty()) { this->getRepr()->setAttribute("inkscape:path-effect", r.c_str()); } else { -- cgit v1.2.3 From d20b73d611b6de99e0e0697ee47a760de437ee97 Mon Sep 17 00:00:00 2001 From: "Liam P. White" Date: Wed, 2 Apr 2014 17:18:40 -0400 Subject: Clean up code (bzr r13090.1.42) --- src/live_effects/lpe-taperstroke.cpp | 905 ++++++++++++++++--------------- src/live_effects/lpe-taperstroke.h | 48 +- src/live_effects/pathoutlineprovider.cpp | 521 +++++++++--------- src/live_effects/pathoutlineprovider.h | 16 +- 4 files changed, 765 insertions(+), 725 deletions(-) mode change 100755 => 100644 src/live_effects/lpe-taperstroke.cpp mode change 100755 => 100644 src/live_effects/pathoutlineprovider.cpp (limited to 'src') diff --git a/src/live_effects/lpe-taperstroke.cpp b/src/live_effects/lpe-taperstroke.cpp old mode 100755 new mode 100644 index b4e43209d..97ae02e3b --- a/src/live_effects/lpe-taperstroke.cpp +++ b/src/live_effects/lpe-taperstroke.cpp @@ -38,26 +38,27 @@ namespace Inkscape { namespace LivePathEffect { namespace TpS { - class KnotHolderEntityAttachBegin : public LPEKnotHolderEntity { - public: - KnotHolderEntityAttachBegin(LPETaperStroke * effect) : LPEKnotHolderEntity(effect) {} - virtual void knot_set(Geom::Point const &p, Geom::Point const &origin, guint state); - virtual Geom::Point knot_get() const; - }; - class KnotHolderEntityAttachEnd : public LPEKnotHolderEntity { - public: - KnotHolderEntityAttachEnd(LPETaperStroke * effect) : LPEKnotHolderEntity(effect) {} - virtual void knot_set(Geom::Point const &p, Geom::Point const &origin, guint state); - virtual Geom::Point knot_get() const; - }; + class KnotHolderEntityAttachBegin : public LPEKnotHolderEntity { + public: + KnotHolderEntityAttachBegin(LPETaperStroke * effect) : LPEKnotHolderEntity(effect) {} + virtual void knot_set(Geom::Point const &p, Geom::Point const &origin, guint state); + virtual Geom::Point knot_get() const; + }; + + class KnotHolderEntityAttachEnd : public LPEKnotHolderEntity { + public: + KnotHolderEntityAttachEnd(LPETaperStroke * effect) : LPEKnotHolderEntity(effect) {} + virtual void knot_set(Geom::Point const &p, Geom::Point const &origin, guint state); + virtual Geom::Point knot_get() const; + }; } // TpS static const Util::EnumData JoinType[] = { - {LINEJOIN_STRAIGHT, N_("Beveled"), "bevel"}, - {LINEJOIN_ROUND, N_("Rounded"), "round"}, - {LINEJOIN_REFLECTED, N_("Reflected"), "reflected"}, - {LINEJOIN_POINTY, N_("Miter"), "miter"}, - {LINEJOIN_EXTRAPOLATED, N_("Extrapolated"), "extrapolated"} + {LINEJOIN_STRAIGHT, N_("Beveled"), "bevel"}, + {LINEJOIN_ROUND, N_("Rounded"), "round"}, + {LINEJOIN_REFLECTED, N_("Reflected"), "reflected"}, + {LINEJOIN_POINTY, N_("Miter"), "miter"}, + {LINEJOIN_EXTRAPOLATED, N_("Extrapolated"), "extrapolated"} }; static const Util::EnumDataConverter JoinTypeConverter(JoinType, sizeof (JoinType)/sizeof(*JoinType)); @@ -65,31 +66,30 @@ static const Util::EnumDataConverter JoinTypeConverter(JoinType, sizeo LPETaperStroke::LPETaperStroke(LivePathEffectObject *lpeobject) : Effect(lpeobject), line_width(_("Stroke width"), _("The (non-tapered) width of the path"), "stroke_width", &wr, this, 3), - attach_start(_("Start offset"), _("Taper distance from path start"), "attach_start", &wr, this, 0.2), - attach_end(_("End offset"), _("The ending position of the taper"), "end_offset", &wr, this, 0.2), - smoothing(_("Taper smoothing"), _("Amount of smoothing to apply to the tapers"), "smoothing", &wr, this, 0.5), - join_type(_("Join type"), _("Join type for non-smooth nodes"), "jointype", JoinTypeConverter, &wr, this, LINEJOIN_EXTRAPOLATED), - miter_limit(_("Miter limit"), _("Limit for miter joins"), "miter_limit", &wr, this, 30.) + attach_start(_("Start offset"), _("Taper distance from path start"), "attach_start", &wr, this, 0.2), + attach_end(_("End offset"), _("The ending position of the taper"), "end_offset", &wr, this, 0.2), + smoothing(_("Taper smoothing"), _("Amount of smoothing to apply to the tapers"), "smoothing", &wr, this, 0.5), + join_type(_("Join type"), _("Join type for non-smooth nodes"), "jointype", JoinTypeConverter, &wr, this, LINEJOIN_EXTRAPOLATED), + miter_limit(_("Miter limit"), _("Limit for miter joins"), "miter_limit", &wr, this, 30.) { - /* uncomment the following line to have the original path displayed while the item is selected */ show_orig_path = true; - _provides_knotholder_entities = true; - - attach_start.param_set_digits(3); - attach_end.param_set_digits(3); - - - registerParameter( dynamic_cast(&line_width) ); - registerParameter( dynamic_cast(&attach_start) ); - registerParameter( dynamic_cast(&attach_end) ); - registerParameter( dynamic_cast(&smoothing) ); - registerParameter( dynamic_cast(&join_type) ); - registerParameter( dynamic_cast(&miter_limit) ); + _provides_knotholder_entities = true; + + attach_start.param_set_digits(3); + attach_end.param_set_digits(3); + + + registerParameter( dynamic_cast(&line_width) ); + registerParameter( dynamic_cast(&attach_start) ); + registerParameter( dynamic_cast(&attach_end) ); + registerParameter( dynamic_cast(&smoothing) ); + registerParameter( dynamic_cast(&join_type) ); + registerParameter( dynamic_cast(&miter_limit) ); } LPETaperStroke::~LPETaperStroke() { - + } //from LPEPowerStroke -- sets fill if stroke color because we will @@ -97,10 +97,10 @@ LPETaperStroke::~LPETaperStroke() void LPETaperStroke::doOnApply(SPLPEItem const* lpeitem) { - if (SP_IS_SHAPE(lpeitem)) { + if (SP_IS_SHAPE(lpeitem)) { SPLPEItem* item = const_cast(lpeitem); double width = (lpeitem && lpeitem->style) ? lpeitem->style->stroke_width.computed : 1.; - + SPCSSAttr *css = sp_repr_css_attr_new (); if (lpeitem->style->stroke.isSet()) { if (lpeitem->style->stroke.isPaintserver()) { @@ -122,13 +122,13 @@ void LPETaperStroke::doOnApply(SPLPEItem const* lpeitem) } else { sp_repr_css_unset_property (css, "fill"); } - + sp_repr_css_set_property(css, "stroke", "none"); - + sp_desktop_apply_css_recursive(item, css, true); sp_repr_css_attr_unref (css); - line_width.param_set_value(width); + line_width.param_set_value(width); } else { g_warning("LPE Join Type can only be applied to paths (not groups)."); } @@ -138,8 +138,10 @@ void LPETaperStroke::doOnApply(SPLPEItem const* lpeitem) void LPETaperStroke::doOnRemove(SPLPEItem const* lpeitem) { - - if (SP_IS_SHAPE(lpeitem)) { + + if (SP_IS_SHAPE(lpeitem)) { + //TODO: make it getobjbyrepr instead of const_cast because this can cause + //undefined behavior SPLPEItem *item = const_cast(lpeitem); SPCSSAttr *css = sp_repr_css_attr_new (); @@ -164,7 +166,7 @@ void LPETaperStroke::doOnRemove(SPLPEItem const* lpeitem) sp_repr_css_unset_property (css, "stroke"); } - Inkscape::CSSOStringStream os; + Inkscape::CSSOStringStream os; os << fabs(line_width); sp_repr_css_set_property (css, "stroke-width", os.str().c_str()); @@ -173,335 +175,347 @@ void LPETaperStroke::doOnRemove(SPLPEItem const* lpeitem) sp_desktop_apply_css_recursive(item, css, true); sp_repr_css_attr_unref (css); item->updateRepr(); - } + } } //actual effect impl here Geom::Path return_at_first_cusp (Geom::Path const & path_in, double smooth_tolerance = 0.05) { - Geom::Path path_out = Geom::Path(); - - for (unsigned i = 0; i < path_in.size(); i++) - { - path_out.append(path_in[i]); - if (path_in.size() == 1) - break; - - //determine order of curve - int order = Outline::bezierOrder(&path_in[i]); - - Geom::Point start_point; - Geom::Point cross_point = path_in[i].finalPoint(); - Geom::Point end_point; - - g_assert(path_in[i].finalPoint() == path_in[i+1].initialPoint()); - - //can you tell that the following expressions have been shaped by - //repeated compiler errors? ;) - switch (order) - { - case 3: - start_point = (static_cast(&path_in[i]))->operator[] (2); - //major league b***f***ing - if (are_near(start_point, cross_point, 0.0000001)) { - start_point = (static_cast(&path_in[i]))->operator[] (1); - } - break; - case 2: - //this never happens - start_point = (static_cast(&path_in[i]))->operator[] (1); - break; - case 1: - default: - start_point = path_in[i].initialPoint(); - } - - order = Outline::bezierOrder(&path_in[i+1]); - - switch (order) - { - case 3: - end_point = (static_cast(&path_in[i+1]))->operator[] (1); - if (are_near(end_point, cross_point, 0.0000001)) { - end_point = (static_cast(&path_in[i+1]))->operator[] (2); - } - break; - case 2: - end_point = (static_cast(&path_in[i+1]))->operator[] (1); - break; - case 1: - default: - end_point = path_in[i+1].finalPoint(); - } - - g_assert(!are_near(start_point, cross_point, 0.0000001)); //take that motherf*ckers - g_assert(!are_near(cross_point, end_point, 0.0000001)); - g_assert(!are_near(start_point, end_point, 0.0000001)); - - if (!are_collinear(start_point, cross_point, end_point, smooth_tolerance)) - break; - } - return path_out; + Geom::Path path_out = Geom::Path(); + + for (unsigned i = 0; i < path_in.size(); i++) { + path_out.append(path_in[i]); + if (path_in.size() == 1) + break; + + //determine order of curve + int order = Outline::bezierOrder(&path_in[i]); + + Geom::Point start_point; + Geom::Point cross_point = path_in[i].finalPoint(); + Geom::Point end_point; + + g_assert(path_in[i].finalPoint() == path_in[i+1].initialPoint()); + + //can you tell that the following expressions have been shaped by + //repeated compiler errors? ;) + switch (order) { + case 3: + start_point = (static_cast(&path_in[i]))->operator[] (2); + //major league b***f***ing + if (are_near(start_point, cross_point, 0.0000001)) { + start_point = (static_cast(&path_in[i]))->operator[] (1); + } + break; + case 2: + //this never happens + start_point = (static_cast(&path_in[i]))->operator[] (1); + break; + case 1: + default: + start_point = path_in[i].initialPoint(); + } + + order = Outline::bezierOrder(&path_in[i+1]); + + switch (order) { + case 3: + end_point = (static_cast(&path_in[i+1]))->operator[] (1); + if (are_near(end_point, cross_point, 0.0000001)) { + end_point = (static_cast(&path_in[i+1]))->operator[] (2); + } + break; + case 2: + end_point = (static_cast(&path_in[i+1]))->operator[] (1); + break; + case 1: + default: + end_point = path_in[i+1].finalPoint(); + } + + //clearly it's collinear if two occupy the same point + g_assert(!are_near(start_point, cross_point, 0.0000001)); + g_assert(!are_near(cross_point, end_point, 0.0000001)); + g_assert(!are_near(start_point, end_point, 0.0000001)); + + if (!are_collinear(start_point, cross_point, end_point, smooth_tolerance)) + break; + } + return path_out; } Geom::Piecewise > stretch_along(Geom::Piecewise > pwd2_in, Geom::Path pattern, double width); +//references to pointers, because magic +void subdivideCurve(Geom::Curve * curve_in, Geom::Coord t, Geom::Curve *& val_first, Geom::Curve *& val_second); Geom::PathVector LPETaperStroke::doEffect_path(Geom::PathVector const& path_in) { - Geom::Path first_cusp = return_at_first_cusp(path_in[0]); - Geom::Path last_cusp = return_at_first_cusp(path_in[0].reverse()); - - bool zeroStart = false; - bool zeroEnd = false; - //there is a pretty good chance that people will try to drag the knots - //on top of each other, so block it - - unsigned size = path_in[0].size(); - if (size == first_cusp.size()) { - //check to see if the knots were dragged over each other - //if so, reset the end offset - if ( attach_start >= (size - attach_end) ) { - attach_end.param_set_value( size - attach_start ); - } - } - - //don't ever let it be zero - if (attach_start <= 0.00000001) { - attach_start.param_set_value( 0.00000001 ); - zeroStart = true; - } - if (attach_end <= 0.00000001) { - attach_end.param_set_value( 0.00000001 ); - zeroEnd = true; - } - - //don't let it be integer - if (double(unsigned(attach_start)) == attach_start) { - attach_start.param_set_value(attach_start - 0.00001); - } - if (double(unsigned(attach_end)) == attach_end) { - attach_end.param_set_value(attach_end - 0.00001); - } - - unsigned allowed_start = first_cusp.size(); - unsigned allowed_end = last_cusp.size(); - - //don't let the knots be farther than they are allowed to be - if ((unsigned)attach_start >= allowed_start) { - attach_start.param_set_value((double)allowed_start - 0.00000001); - } - if ((unsigned)attach_end >= allowed_end) { - attach_end.param_set_value((double)allowed_end - 0.00000001); - } - - //remember, Path::operator () means get point at time t - start_attach_point = first_cusp(attach_start); - end_attach_point = last_cusp(attach_end); - Geom::PathVector pathv_out; - - //the following function just splits it up into three pieces. - pathv_out = doEffect_simplePath(path_in); - - //now for the actual tapering. We use a Pattern Along Path method to get this done. - - Geom::PathVector real_pathv; - Geom::Path real_path; - Geom::PathVector pat_vec; - Geom::Piecewise > pwd2; - Geom::Path throwaway_path; - - if (!zeroStart) { - //Construct the pattern (pat_str stands for pattern string) (yes, this is easier, trust me) - std::stringstream pat_str; - pat_str << "M 1,0 C " << 1 - (double)smoothing << ",0 0,0.5 0,0.5 0,0.5 " << 1 - (double)smoothing << ",1 1,1"; - - pat_vec = sp_svg_read_pathv(pat_str.str().c_str()); - pwd2.concat(stretch_along(pathv_out[0].toPwSb(), pat_vec[0], -fabs(line_width))); - throwaway_path = Geom::path_from_piecewise(pwd2, 0.001)[0]; - - real_path.append(throwaway_path); - } - //append the outside outline of the path (with direction) - throwaway_path = Outline::PathOutsideOutline(pathv_out[1], - -fabs(line_width), static_cast(join_type.get_value()), miter_limit); - - if (!zeroStart) { - throwaway_path.setInitial(real_path.finalPoint()); - real_path.append(throwaway_path); - } else { - real_path.append(throwaway_path, Geom::Path::STITCH_DISCONTINUOUS); - } - - if (!zeroEnd) { - //append the ending taper - std::stringstream pat_str_1; - pat_str_1 << "M 0,0 0,1 C " << (double)smoothing << ",1 1,0.5 1,0.5 1,0.5 " << double(smoothing) << ",0 0,0"; - pat_vec = sp_svg_read_pathv(pat_str_1.str().c_str()); - - pwd2 = Geom::Piecewise > (); - pwd2.concat(stretch_along(pathv_out[2].toPwSb(), pat_vec[0], -fabs(line_width))); - - throwaway_path = Geom::path_from_piecewise(pwd2, 0.001)[0]; - throwaway_path.setInitial(real_path.finalPoint()); - real_path.append(throwaway_path); - } - //append the inside outline of the path (against direction) - throwaway_path = Outline::PathOutsideOutline(pathv_out[1].reverse(), - -fabs(line_width), static_cast(join_type.get_value()), miter_limit); - - if (!zeroEnd) { - //throwaway_path.setInitial(real_path.finalPoint()); - real_path.append(throwaway_path, Geom::Path::STITCH_DISCONTINUOUS); - } else { - real_path.append(throwaway_path, Geom::Path::STITCH_DISCONTINUOUS); - } - real_path.close(); - - real_pathv.push_back(real_path); - - return real_pathv; + Geom::Path first_cusp = return_at_first_cusp(path_in[0]); + Geom::Path last_cusp = return_at_first_cusp(path_in[0].reverse()); + + bool zeroStart = false; + bool zeroEnd = false; + //there is a pretty good chance that people will try to drag the knots + //on top of each other, so block it + + unsigned size = path_in[0].size(); + if (size == first_cusp.size()) { + //check to see if the knots were dragged over each other + //if so, reset the end offset + if ( attach_start >= (size - attach_end) ) { + attach_end.param_set_value( size - attach_start ); + } + } + + //don't ever let it be zero + if (attach_start <= 0.00000001) { + attach_start.param_set_value( 0.00000001 ); + zeroStart = true; + } + if (attach_end <= 0.00000001) { + attach_end.param_set_value( 0.00000001 ); + zeroEnd = true; + } + + //don't let it be integer + if (double(unsigned(attach_start)) == attach_start) { + attach_start.param_set_value(attach_start - 0.00001); + } + if (double(unsigned(attach_end)) == attach_end) { + attach_end.param_set_value(attach_end - 0.00001); + } + + unsigned allowed_start = first_cusp.size(); + unsigned allowed_end = last_cusp.size(); + + //don't let the knots be farther than they are allowed to be + if ((unsigned)attach_start >= allowed_start) { + attach_start.param_set_value((double)allowed_start - 0.00000001); + } + if ((unsigned)attach_end >= allowed_end) { + attach_end.param_set_value((double)allowed_end - 0.00000001); + } + + //remember, Path::operator () means get point at time t + start_attach_point = first_cusp(attach_start); + end_attach_point = last_cusp(attach_end); + Geom::PathVector pathv_out; + + //the following function just splits it up into three pieces. + pathv_out = doEffect_simplePath(path_in); + + //now for the actual tapering. We use a Pattern Along Path method to get this done. + + Geom::PathVector real_pathv; + Geom::Path real_path; + Geom::PathVector pat_vec; + Geom::Piecewise > pwd2; + Geom::Path throwaway_path; + + if (!zeroStart) { + //Construct the pattern (pat_str stands for pattern string) (yes, this is easier, trust me) + std::stringstream pat_str; + pat_str << "M 1,0 C " << 1 - (double)smoothing << ",0 0,0.5 0,0.5 0,0.5 " << 1 - (double)smoothing << ",1 1,1"; + + pat_vec = sp_svg_read_pathv(pat_str.str().c_str()); + pwd2.concat(stretch_along(pathv_out[0].toPwSb(), pat_vec[0], -fabs(line_width))); + throwaway_path = Geom::path_from_piecewise(pwd2, 0.001)[0]; + + real_path.append(throwaway_path); + } + //append the outside outline of the path (with direction) + throwaway_path = Outline::PathOutsideOutline(pathv_out[1], + -fabs(line_width), static_cast(join_type.get_value()), miter_limit); + + if (!zeroStart) { + throwaway_path.setInitial(real_path.finalPoint()); + real_path.append(throwaway_path); + } else { + real_path.append(throwaway_path, Geom::Path::STITCH_DISCONTINUOUS); + } + + if (!zeroEnd) { + //append the ending taper + std::stringstream pat_str_1; + pat_str_1 << "M 0,0 0,1 C " << (double)smoothing << ",1 1,0.5 1,0.5 1,0.5 " << double(smoothing) << ",0 0,0"; + pat_vec = sp_svg_read_pathv(pat_str_1.str().c_str()); + + pwd2 = Geom::Piecewise > (); + pwd2.concat(stretch_along(pathv_out[2].toPwSb(), pat_vec[0], -fabs(line_width))); + + throwaway_path = Geom::path_from_piecewise(pwd2, 0.001)[0]; + throwaway_path.setInitial(real_path.finalPoint()); + real_path.append(throwaway_path); + } + //append the inside outline of the path (against direction) + throwaway_path = Outline::PathOutsideOutline(pathv_out[1].reverse(), + -fabs(line_width), static_cast(join_type.get_value()), miter_limit); + + if (!zeroEnd) { + //throwaway_path.setInitial(real_path.finalPoint()); + real_path.append(throwaway_path, Geom::Path::STITCH_DISCONTINUOUS); + } else { + real_path.append(throwaway_path, Geom::Path::STITCH_DISCONTINUOUS); + } + + //hmm + real_path.setFinal(real_path.initialPoint()); + + real_path.close(); + + real_pathv.push_back(real_path); + + return real_pathv; } //in all cases, this should return a PathVector with three elements. Geom::PathVector LPETaperStroke::doEffect_simplePath(Geom::PathVector const & path_in) { - unsigned size = path_in[0].size(); - - //do subdivision and get out - unsigned loc = (unsigned)attach_start; - Geom::Curve * curve_start = path_in[0] [loc].duplicate(); - - std::vector pathv_out; - Geom::Path path_out = Geom::Path(); - - Geom::Path trimmed_start = Geom::Path(); - Geom::Path trimmed_end = Geom::Path(); - - for (unsigned i = 0; i < loc; i++) { - trimmed_start.append(path_in[0] [i]); - } - - - //this is pretty annoying - //previously I wrote a function for this but it wasted a lot of time - //so I optimized it back into here. - unsigned order = Outline::bezierOrder(curve_start); - switch (order) { - case 3: { - Geom::CubicBezier *cb = static_cast(curve_start); - std::pair cb_pair = cb->subdivide((attach_start - loc)); - trimmed_start.append(cb_pair.first); curve_start = cb_pair.second.duplicate(); //goes out of scope - break; - } - case 2: { - Geom::QuadraticBezier *qb = static_cast(curve_start); - std::pair qb_pair = qb->subdivide((attach_start - loc)); - trimmed_start.append(qb_pair.first); curve_start = qb_pair.second.duplicate(); - break; - } - case 1: { - Geom::BezierCurveN<1> *lb = static_cast * >(curve_start); - std::pair, Geom::BezierCurveN<1> > lb_pair = lb->subdivide((attach_start - loc)); - trimmed_start.append(lb_pair.first); curve_start = lb_pair.second.duplicate(); - break; - } - } - - //special case: path is one segment long - //special case: what if the two knots occupy the same segment? - if ((size == 1) || ( size - unsigned(attach_end) - 1 == loc )) - { - Geom::Coord t = Geom::nearest_point(end_attach_point, *curve_start); - - //it is just a dumb segment - //we have to do some shifting here because the value changed when we reduced the length - //of the previous segment. - - order = Outline::bezierOrder(curve_start); - switch (order) { - case 3: { - Geom::CubicBezier *cb = static_cast(curve_start); - std::pair cb_pair = cb->subdivide(t); - trimmed_end.append(cb_pair.second); curve_start = cb_pair.first.duplicate(); - break; - } - case 2: { - Geom::QuadraticBezier *qb = static_cast(curve_start); - std::pair qb_pair = qb->subdivide(t); - trimmed_end.append(qb_pair.second); curve_start = qb_pair.first.duplicate(); - break; - } - case 1: { - Geom::BezierCurveN<1> *lb = static_cast * >(curve_start); - std::pair, Geom::BezierCurveN<1> > lb_pair = lb->subdivide(t); - trimmed_end.append(lb_pair.second); curve_start = lb_pair.first.duplicate(); - break; - } - } - - for (unsigned j = (size - attach_end) + 1; j < size; j++) { - trimmed_end.append(path_in[0] [j]); - } - - path_out.append(*curve_start); - pathv_out.push_back(trimmed_start); - pathv_out.push_back(path_out); - pathv_out.push_back(trimmed_end); - return pathv_out; - } - - pathv_out.push_back(trimmed_start); - - //append almost all of the rest of the path, ignore the curves that the knot is past (we'll get to it in a minute) - path_out.append(*curve_start); - - for (unsigned k = loc + 1; k < (size - unsigned(attach_end)) - 1; k++) { - path_out.append(path_in[0] [k]); - } - - //deal with the last segment in a very similar fashion to the first - loc = size - attach_end; - - Geom::Curve * curve_end = path_in[0] [loc].duplicate(); - - Geom::Coord t = Geom::nearest_point(end_attach_point, *curve_end); - - order = Outline::bezierOrder(curve_end); - switch (order) { - case 3: { - Geom::CubicBezier *cb = static_cast(curve_end); - std::pair cb_pair = cb->subdivide(t); - trimmed_end.append(cb_pair.second); curve_end = cb_pair.first.duplicate(); - break; - } - case 2: { - Geom::QuadraticBezier *qb = static_cast(curve_end); - std::pair qb_pair = qb->subdivide(t); - trimmed_end.append(qb_pair.second); curve_end = qb_pair.first.duplicate(); - break; - } - case 1: { - Geom::BezierCurveN<1> *lb = static_cast * >(curve_end); - std::pair, Geom::BezierCurveN<1> > lb_pair = lb->subdivide(t); - trimmed_end.append(lb_pair.second); curve_end = lb_pair.first.duplicate(); - break; - } - } - - for (unsigned j = (size - attach_end) + 1; j < size; j++) { - trimmed_end.append(path_in[0] [j]); - } - - path_out.append(*curve_end); - pathv_out.push_back(path_out); - - pathv_out.push_back(trimmed_end); - - if (curve_end) delete curve_end; - if (curve_start) delete curve_start; - return pathv_out; + unsigned size = path_in[0].size(); + + //do subdivision and get out + unsigned loc = (unsigned)attach_start; + Geom::Curve * curve_start = path_in[0] [loc].duplicate(); + + std::vector pathv_out; + Geom::Path path_out = Geom::Path(); + + Geom::Path trimmed_start = Geom::Path(); + Geom::Path trimmed_end = Geom::Path(); + + for (unsigned i = 0; i < loc; i++) { + trimmed_start.append(path_in[0] [i]); + } + + + //this is pretty annoying + //previously I wrote a function for this but it wasted a lot of time + //so I optimized it back into here. + unsigned order = Outline::bezierOrder(curve_start); + switch (order) { + case 3: { + Geom::CubicBezier *cb = static_cast(curve_start); + std::pair cb_pair = cb->subdivide((attach_start - loc)); + trimmed_start.append(cb_pair.first); + curve_start = cb_pair.second.duplicate(); //goes out of scope + break; + } + case 2: { + Geom::QuadraticBezier *qb = static_cast(curve_start); + std::pair qb_pair = qb->subdivide((attach_start - loc)); + trimmed_start.append(qb_pair.first); + curve_start = qb_pair.second.duplicate(); + break; + } + case 1: { + Geom::BezierCurveN<1> *lb = static_cast * >(curve_start); + std::pair, Geom::BezierCurveN<1> > lb_pair = lb->subdivide((attach_start - loc)); + trimmed_start.append(lb_pair.first); + curve_start = lb_pair.second.duplicate(); + break; + } + } + + //special case: path is one segment long + //special case: what if the two knots occupy the same segment? + if ((size == 1) || ( size - unsigned(attach_end) - 1 == loc )) { + Geom::Coord t = Geom::nearest_point(end_attach_point, *curve_start); + + //it is just a dumb segment + //we have to do some shifting here because the value changed when we reduced the length + //of the previous segment. + + order = Outline::bezierOrder(curve_start); + switch (order) { + case 3: { + Geom::CubicBezier *cb = static_cast(curve_start); + std::pair cb_pair = cb->subdivide(t); + trimmed_end.append(cb_pair.second); + curve_start = cb_pair.first.duplicate(); + break; + } + case 2: { + Geom::QuadraticBezier *qb = static_cast(curve_start); + std::pair qb_pair = qb->subdivide(t); + trimmed_end.append(qb_pair.second); + curve_start = qb_pair.first.duplicate(); + break; + } + case 1: { + Geom::BezierCurveN<1> *lb = static_cast * >(curve_start); + std::pair, Geom::BezierCurveN<1> > lb_pair = lb->subdivide(t); + trimmed_end.append(lb_pair.second); + curve_start = lb_pair.first.duplicate(); + break; + } + } + + for (unsigned j = (size - attach_end) + 1; j < size; j++) { + trimmed_end.append(path_in[0] [j]); + } + + path_out.append(*curve_start); + pathv_out.push_back(trimmed_start); + pathv_out.push_back(path_out); + pathv_out.push_back(trimmed_end); + return pathv_out; + } + + pathv_out.push_back(trimmed_start); + + //append almost all of the rest of the path, ignore the curves that the knot is past (we'll get to it in a minute) + path_out.append(*curve_start); + + for (unsigned k = loc + 1; k < (size - unsigned(attach_end)) - 1; k++) { + path_out.append(path_in[0] [k]); + } + + //deal with the last segment in a very similar fashion to the first + loc = size - attach_end; + + Geom::Curve * curve_end = path_in[0] [loc].duplicate(); + + Geom::Coord t = Geom::nearest_point(end_attach_point, *curve_end); + + order = Outline::bezierOrder(curve_end); + switch (order) { + case 3: { + Geom::CubicBezier *cb = static_cast(curve_end); + std::pair cb_pair = cb->subdivide(t); + trimmed_end.append(cb_pair.second); + curve_end = cb_pair.first.duplicate(); + break; + } + case 2: { + Geom::QuadraticBezier *qb = static_cast(curve_end); + std::pair qb_pair = qb->subdivide(t); + trimmed_end.append(qb_pair.second); + curve_end = qb_pair.first.duplicate(); + break; + } + case 1: { + Geom::BezierCurveN<1> *lb = static_cast * >(curve_end); + std::pair, Geom::BezierCurveN<1> > lb_pair = lb->subdivide(t); + trimmed_end.append(lb_pair.second); + curve_end = lb_pair.first.duplicate(); + break; + } + } + + for (unsigned j = (size - attach_end) + 1; j < size; j++) { + trimmed_end.append(path_in[0] [j]); + } + + path_out.append(*curve_end); + pathv_out.push_back(path_out); + + pathv_out.push_back(trimmed_end); + + if (curve_end) delete curve_end; + if (curve_start) delete curve_start; + return pathv_out; } @@ -509,14 +523,14 @@ Geom::PathVector LPETaperStroke::doEffect_simplePath(Geom::PathVector const & pa //tweaking to get it to work right in this case. Geom::Piecewise > stretch_along(Geom::Piecewise > pwd2_in, Geom::Path pattern, double prop_scale) { - using namespace Geom; + using namespace Geom; // Don't allow empty path parameter: if ( pattern.empty() ) { return pwd2_in; } -/* Much credit should go to jfb and mgsloan of lib2geom development for the code below! */ + /* Much credit should go to jfb and mgsloan of lib2geom development for the code below! */ Piecewise > output; std::vector > > pre_output; @@ -548,7 +562,7 @@ Geom::Piecewise > stretch_along(Geom::Piecewise > > paths_in; paths_in = split_at_discontinuities(pwd2_in); - for (unsigned idx = 0; idx < paths_in.size(); idx++){ + for (unsigned idx = 0; idx < paths_in.size(); idx++) { Geom::Piecewise > path_i = paths_in[idx]; Piecewise x = x0; Piecewise y = y0; @@ -556,14 +570,14 @@ Geom::Piecewise > stretch_along(Geom::Piecewise > n = rot90(derivative(uskeleton)); n = force_continuity(remove_short_cuts(n,.1)); - + int nbCopies = 0; double scaling = 1; nbCopies = 1; scaling = (uskeleton.domain().extent() - toffset)/pattBndsX->extent(); double pattWidth = pattBndsX->extent() * scaling; - + if (scaling != 1.0) { x*=scaling; } @@ -573,20 +587,20 @@ Geom::Piecewise > stretch_along(Geom::Piecewise > output_piece = compose(uskeleton,x+offs)+y*compose(n,x+offs); std::vector > > splited_output_piece = split_at_discontinuities(output_piece); pre_output.insert(pre_output.end(), splited_output_piece.begin(), splited_output_piece.end() ); - }else{ + } else { output.concat(compose(uskeleton,x+offs)+y*compose(n,x+offs)); } offs+=pattWidth; } } - /*if (false){ + /*if (false){ pre_output = fuse_nearby_ends(pre_output, fuse_tolerance); for (unsigned i=0; i > stretch_along(Geom::Piecewise(curve_in); + std::pair cb_pair = cb->subdivide(t); + //trimmed_start.append(cb_pair.first); + val_first = cb_pair.first.duplicate(); + val_second = cb_pair.second.duplicate(); + break; + } + case 2: { + Geom::QuadraticBezier *qb = static_cast(curve_in); + std::pair qb_pair = qb->subdivide(t); + //trimmed_start.append(qb_pair.first); + val_first = qb_pair.first.duplicate(); + val_second = qb_pair.second.duplicate(); + break; + } + case 1: { + Geom::BezierCurveN<1> *lb = static_cast * >(curve_in); + std::pair, Geom::BezierCurveN<1> > lb_pair = lb->subdivide(t); + //trimmed_start.append(lb_pair.first); + val_first = lb_pair.first.duplicate(); + val_second = lb_pair.second.duplicate(); + break; + } + } +} -void LPETaperStroke::addKnotHolderEntities(KnotHolder *knotholder, SPDesktop *desktop, SPItem *item) + +void LPETaperStroke::addKnotHolderEntities(KnotHolder *knotholder, SPDesktop *desktop, SPItem *item) { - { - KnotHolderEntity *e = new TpS::KnotHolderEntityAttachBegin(this); - e->create( desktop, item, knotholder, Inkscape::CTRL_TYPE_UNKNOWN, - _("Start point of the taper"), SP_KNOT_SHAPE_CIRCLE ); - knotholder->add(e); - } - { - KnotHolderEntity *e = new TpS::KnotHolderEntityAttachEnd(this); - e->create( desktop, item, knotholder, Inkscape::CTRL_TYPE_UNKNOWN, - _("End point of the taper"), SP_KNOT_SHAPE_CIRCLE ); - knotholder->add(e); - } + { + KnotHolderEntity *e = new TpS::KnotHolderEntityAttachBegin(this); + e->create( desktop, item, knotholder, Inkscape::CTRL_TYPE_UNKNOWN, + _("Start point of the taper"), SP_KNOT_SHAPE_CIRCLE ); + knotholder->add(e); + } + { + KnotHolderEntity *e = new TpS::KnotHolderEntityAttachEnd(this); + e->create( desktop, item, knotholder, Inkscape::CTRL_TYPE_UNKNOWN, + _("End point of the taper"), SP_KNOT_SHAPE_CIRCLE ); + knotholder->add(e); + } } namespace TpS { - void KnotHolderEntityAttachBegin::knot_set(Geom::Point const &p, Geom::Point const &/*origin*/, guint state) - { - using namespace Geom; - - LPETaperStroke* lpe = dynamic_cast(_effect); - - Geom::Point const s = snap_knot_position(p, state); - - SPCurve *curve = SP_PATH(item)->get_curve_for_edit(); - Geom::PathVector pathv = curve->get_pathvector(); - Piecewise > pwd2; - Geom::Path p_in = return_at_first_cusp(pathv[0]); - pwd2.concat(p_in.toPwSb()); - std::vector > > pwd_vec = split_at_discontinuities(pwd2); - - double t0 = nearest_point(s, pwd_vec[0]); - lpe->attach_start.param_set_value(t0); - - // FIXME: this should not directly ask for updating the item. It should write to SVG, which triggers updating. - sp_lpe_item_update_patheffect (SP_LPE_ITEM(item), false, true); - } - void KnotHolderEntityAttachEnd::knot_set(Geom::Point const &p, Geom::Point const& /*origin*/, guint state) - { - using namespace Geom; - - LPETaperStroke* lpe = dynamic_cast(_effect); - - Geom::Point const s = snap_knot_position(p, state); - - SPCurve *curve = SP_PATH(item)->get_curve_for_edit(); - Geom::PathVector pathv = curve->get_pathvector(); - Piecewise > pwd2; - Geom::Path p_in = return_at_first_cusp(pathv[0].reverse()); - pwd2.concat(p_in.toPwSb()); - std::vector > > pwd_vec = split_at_discontinuities(pwd2); - - double t0 = nearest_point(s, pwd_vec[0]); - lpe->attach_end.param_set_value(t0); - - // FIXME: this should not directly ask for updating the item. It should write to SVG, which triggers updating. - sp_lpe_item_update_patheffect (SP_LPE_ITEM(item), false, true); - } - Geom::Point KnotHolderEntityAttachBegin::knot_get() const - { - LPETaperStroke const * lpe = dynamic_cast (_effect); - return lpe->start_attach_point; - } - Geom::Point KnotHolderEntityAttachEnd::knot_get() const - { - LPETaperStroke const * lpe = dynamic_cast (_effect); - return lpe->end_attach_point; - } +void KnotHolderEntityAttachBegin::knot_set(Geom::Point const &p, Geom::Point const &/*origin*/, guint state) +{ + using namespace Geom; + + LPETaperStroke* lpe = dynamic_cast(_effect); + + Geom::Point const s = snap_knot_position(p, state); + + SPCurve *curve = SP_PATH(item)->get_curve_for_edit(); + Geom::PathVector pathv = curve->get_pathvector(); + Piecewise > pwd2; + Geom::Path p_in = return_at_first_cusp(pathv[0]); + pwd2.concat(p_in.toPwSb()); + std::vector > > pwd_vec = split_at_discontinuities(pwd2); + + double t0 = nearest_point(s, pwd_vec[0]); + lpe->attach_start.param_set_value(t0); + + // FIXME: this should not directly ask for updating the item. It should write to SVG, which triggers updating. + sp_lpe_item_update_patheffect (SP_LPE_ITEM(item), false, true); +} +void KnotHolderEntityAttachEnd::knot_set(Geom::Point const &p, Geom::Point const& /*origin*/, guint state) +{ + using namespace Geom; + + LPETaperStroke* lpe = dynamic_cast(_effect); + + Geom::Point const s = snap_knot_position(p, state); + + SPCurve *curve = SP_PATH(item)->get_curve_for_edit(); + Geom::PathVector pathv = curve->get_pathvector(); + Piecewise > pwd2; + Geom::Path p_in = return_at_first_cusp(pathv[0].reverse()); + pwd2.concat(p_in.toPwSb()); + std::vector > > pwd_vec = split_at_discontinuities(pwd2); + + double t0 = nearest_point(s, pwd_vec[0]); + lpe->attach_end.param_set_value(t0); + + // FIXME: this should not directly ask for updating the item. It should write to SVG, which triggers updating. + sp_lpe_item_update_patheffect (SP_LPE_ITEM(item), false, true); +} +Geom::Point KnotHolderEntityAttachBegin::knot_get() const +{ + LPETaperStroke const * lpe = dynamic_cast (_effect); + return lpe->start_attach_point; +} +Geom::Point KnotHolderEntityAttachEnd::knot_get() const +{ + LPETaperStroke const * lpe = dynamic_cast (_effect); + return lpe->end_attach_point; +} } diff --git a/src/live_effects/lpe-taperstroke.h b/src/live_effects/lpe-taperstroke.h index 29a56f77c..997209543 100644 --- a/src/live_effects/lpe-taperstroke.h +++ b/src/live_effects/lpe-taperstroke.h @@ -20,39 +20,39 @@ namespace Inkscape { namespace LivePathEffect { namespace TpS { - // we need a separate namespace to avoid clashes with other LPEs - class KnotHolderEntityAttachBegin; - class KnotHolderEntityAttachEnd; +// we need a separate namespace to avoid clashes with other LPEs +class KnotHolderEntityAttachBegin; +class KnotHolderEntityAttachEnd; } class LPETaperStroke : public Effect { public: - LPETaperStroke(LivePathEffectObject *lpeobject); - virtual ~LPETaperStroke(); - - virtual void doOnApply(SPLPEItem const* lpeitem); - virtual void doOnRemove(SPLPEItem const* lpeitem); + LPETaperStroke(LivePathEffectObject *lpeobject); + virtual ~LPETaperStroke(); - virtual Geom::PathVector doEffect_path (Geom::PathVector const& path_in); - Geom::PathVector doEffect_simplePath(Geom::PathVector const& path_in); - - virtual void addKnotHolderEntities(KnotHolder * knotholder, SPDesktop * desktop, SPItem * item); + virtual void doOnApply(SPLPEItem const* lpeitem); + virtual void doOnRemove(SPLPEItem const* lpeitem); - friend class TpS::KnotHolderEntityAttachBegin; - friend class TpS::KnotHolderEntityAttachEnd; + virtual Geom::PathVector doEffect_path (Geom::PathVector const& path_in); + Geom::PathVector doEffect_simplePath(Geom::PathVector const& path_in); + + virtual void addKnotHolderEntities(KnotHolder * knotholder, SPDesktop * desktop, SPItem * item); + + friend class TpS::KnotHolderEntityAttachBegin; + friend class TpS::KnotHolderEntityAttachEnd; private: - ScalarParam line_width; - ScalarParam attach_start; - ScalarParam attach_end; - ScalarParam smoothing; - EnumParam join_type; - ScalarParam miter_limit; + ScalarParam line_width; + ScalarParam attach_start; + ScalarParam attach_end; + ScalarParam smoothing; + EnumParam join_type; + ScalarParam miter_limit; - Geom::Point start_attach_point; - Geom::Point end_attach_point; + Geom::Point start_attach_point; + Geom::Point end_attach_point; - LPETaperStroke(const LPETaperStroke&); - LPETaperStroke& operator=(const LPETaperStroke&); + LPETaperStroke(const LPETaperStroke&); + LPETaperStroke& operator=(const LPETaperStroke&); }; } //namespace LivePathEffect diff --git a/src/live_effects/pathoutlineprovider.cpp b/src/live_effects/pathoutlineprovider.cpp old mode 100755 new mode 100644 index 6a47285a0..ad39a7416 --- a/src/live_effects/pathoutlineprovider.cpp +++ b/src/live_effects/pathoutlineprovider.cpp @@ -9,133 +9,128 @@ #include <2geom/path-sink.h> #include -namespace Geom +namespace Geom { +/** +* Refer to: Weisstein, Eric W. "Circle-Circle Intersection." + From MathWorld--A Wolfram Web Resource. + http://mathworld.wolfram.com/Circle-CircleIntersection.html +* +* @return 0 if no intersection +* @return 1 if one circle is contained in the other +* @return 2 if intersections are found (they are written to p0 and p1) +*/ +static int circle_circle_intersection(Circle const &circle0, Circle const &circle1, + Point & p0, Point & p1) +{ + Point X0 = circle0.center(); + double r0 = circle0.ray(); + Point X1 = circle1.center(); + double r1 = circle1.ray(); + + /* dx and dy are the vertical and horizontal distances between + * the circle centers. + */ + Point D = X1 - X0; + + /* Determine the straight-line distance between the centers. */ + double d = L2(D); + + /* Check for solvability. */ + if (d > (r0 + r1)) { + /* no solution. circles do not intersect. */ + return 0; + } + if (d <= fabs(r0 - r1)) { + /* no solution. one circle is contained in the other */ + return 1; + } + + /* 'point 2' is the point where the line through the circle + * intersection points crosses the line between the circle + * centers. + */ + + /* Determine the distance from point 0 to point 2. */ + double a = ((r0*r0) - (r1*r1) + (d*d)) / (2.0 * d) ; + + /* Determine the coordinates of point 2. */ + Point p2 = X0 + D * (a/d); + + /* Determine the distance from point 2 to either of the + * intersection points. + */ + double h = std::sqrt((r0*r0) - (a*a)); + + /* Now determine the offsets of the intersection points from + * point 2. + */ + Point r = (h/d)*rot90(D); + + /* Determine the absolute intersection points. */ + p0 = p2 + r; + p1 = p2 - r; + + return 2; +} +/** +* Find circle that touches inside of the curve, with radius matching the curvature, at time value \c t. +* Because this method internally uses unitTangentAt, t should be smaller than 1.0 (see unitTangentAt). +*/ +static Circle touching_circle( D2 const &curve, double t, double tol=0.01 ) { - /** - * Refer to: Weisstein, Eric W. "Circle-Circle Intersection." - From MathWorld--A Wolfram Web Resource. - http://mathworld.wolfram.com/Circle-CircleIntersection.html - * - * @return 0 if no intersection - * @return 1 if one circle is contained in the other - * @return 2 if intersections are found (they are written to p0 and p1) - */ - static int circle_circle_intersection(Circle const &circle0, Circle const &circle1, - Point & p0, Point & p1) - { - Point X0 = circle0.center(); - double r0 = circle0.ray(); - Point X1 = circle1.center(); - double r1 = circle1.ray(); - - /* dx and dy are the vertical and horizontal distances between - * the circle centers. - */ - Point D = X1 - X0; - - /* Determine the straight-line distance between the centers. */ - double d = L2(D); - - /* Check for solvability. */ - if (d > (r0 + r1)) - { - /* no solution. circles do not intersect. */ - return 0; - } - if (d <= fabs(r0 - r1)) - { - /* no solution. one circle is contained in the other */ - return 1; - } - - /* 'point 2' is the point where the line through the circle - * intersection points crosses the line between the circle - * centers. - */ - - /* Determine the distance from point 0 to point 2. */ - double a = ((r0*r0) - (r1*r1) + (d*d)) / (2.0 * d) ; - - /* Determine the coordinates of point 2. */ - Point p2 = X0 + D * (a/d); - - /* Determine the distance from point 2 to either of the - * intersection points. - */ - double h = std::sqrt((r0*r0) - (a*a)); - - /* Now determine the offsets of the intersection points from - * point 2. - */ - Point r = (h/d)*rot90(D); - - /* Determine the absolute intersection points. */ - p0 = p2 + r; - p1 = p2 - r; - - return 2; - } - /** - * Find circle that touches inside of the curve, with radius matching the curvature, at time value \c t. - * Because this method internally uses unitTangentAt, t should be smaller than 1.0 (see unitTangentAt). - */ - static Circle touching_circle( D2 const &curve, double t, double tol=0.01 ) - { - D2 dM=derivative(curve); - if ( are_near(L2sq(dM(t)),0.) ) { - dM=derivative(dM); - } - if ( are_near(L2sq(dM(t)),0.) ) { // try second time - dM=derivative(dM); - } - Piecewise > unitv = unitVector(dM,tol); - Piecewise dMlength = dot(Piecewise >(dM),unitv); - Piecewise k = cross(derivative(unitv),unitv); - k = divide(k,dMlength,tol,3); - double curv = k(t); // note that this value is signed - - Geom::Point normal = unitTangentAt(curve, t).cw(); - double radius = 1/curv; - Geom::Point center = curve(t) + radius*normal; - return Geom::Circle(center, fabs(radius)); - } - - static std::vector split_at_cusps(const Geom::Path& in) - { - Geom::PathVector out = Geom::PathVector(); - Geom::Path temp = Geom::Path(); - - for (unsigned path_descr = 0; path_descr < in.size(); path_descr++) - { - temp = Geom::Path(); - temp.append(in[path_descr]); - out.push_back(temp); - } - - return out; - } - - static Geom::CubicBezier sbasis_to_cubicbezier(Geom::D2 const & sbasis_in) - { - std::vector temp; - sbasis_to_bezier(temp, sbasis_in, 4); - return Geom::CubicBezier( temp ); - } - - static boost::optional intersection_point( Geom::Point const & origin_a, Geom::Point const & vector_a, - Geom::Point const & origin_b, Geom::Point const & vector_b) - { - Geom::Coord denom = cross(vector_b, vector_a); - if (!Geom::are_near(denom,0.)){ - Geom::Coord t = (cross(origin_a,vector_b) + cross(vector_b,origin_b)) / denom; - return origin_a + t * vector_a; - } - return boost::none; - } + D2 dM=derivative(curve); + if ( are_near(L2sq(dM(t)),0.) ) { + dM=derivative(dM); + } + if ( are_near(L2sq(dM(t)),0.) ) { // try second time + dM=derivative(dM); + } + Piecewise > unitv = unitVector(dM,tol); + Piecewise dMlength = dot(Piecewise >(dM),unitv); + Piecewise k = cross(derivative(unitv),unitv); + k = divide(k,dMlength,tol,3); + double curv = k(t); // note that this value is signed + + Geom::Point normal = unitTangentAt(curve, t).cw(); + double radius = 1/curv; + Geom::Point center = curve(t) + radius*normal; + return Geom::Circle(center, fabs(radius)); } -namespace Outline +static std::vector split_at_cusps(const Geom::Path& in) { + Geom::PathVector out = Geom::PathVector(); + Geom::Path temp = Geom::Path(); + + for (unsigned path_descr = 0; path_descr < in.size(); path_descr++) { + temp = Geom::Path(); + temp.append(in[path_descr]); + out.push_back(temp); + } + + return out; +} + +static Geom::CubicBezier sbasis_to_cubicbezier(Geom::D2 const & sbasis_in) +{ + std::vector temp; + sbasis_to_bezier(temp, sbasis_in, 4); + return Geom::CubicBezier( temp ); +} + +static boost::optional intersection_point( Geom::Point const & origin_a, Geom::Point const & vector_a, + Geom::Point const & origin_b, Geom::Point const & vector_b) +{ + Geom::Coord denom = cross(vector_b, vector_a); + if (!Geom::are_near(denom,0.)) { + Geom::Coord t = (cross(origin_a,vector_b) + cross(vector_b,origin_b)) / denom; + return origin_a + t * vector_a; + } + return boost::none; +} +} + +namespace Outline { typedef Geom::D2 D2SB; typedef Geom::Piecewise PWD2; @@ -160,72 +155,70 @@ bool outside_angle (const Geom::Curve& cbc1, const Geom::Curve& cbc2) unsigned order = bezierOrder(&cbc1); Geom::Point start_point; - Geom::Point cross_point = cbc1.finalPoint(); - Geom::Point end_point; - - //assert(cbc1.finalPoint() == cbc2.initialPoint()); - //short circuiting? - if (cbc1.finalPoint() != cbc2.initialPoint()) { - printf("There was an issue when asserting that one curve's end is the start of the other. Line %d, File %s\n" - "By default we are going to say that this is an inside join, so we cannot make a line join for it.\n", __LINE__, __FILE__); - return false; + Geom::Point cross_point = cbc1.finalPoint(); + Geom::Point end_point; + + //assert(cbc1.finalPoint() == cbc2.initialPoint()); + //short circuiting? + if (cbc1.finalPoint() != cbc2.initialPoint()) { + printf("There was an issue when asserting that one curve's end is the start of the other. Line %d, File %s\n" + "By default we are going to say that this is an inside join, so we cannot make a line join for it.\n", __LINE__, __FILE__); + return false; + } + switch (order) { + case 3: + start_point = (static_cast(&cbc1))->operator[] (2); + //major league b***f***ing + if (are_near(start_point, cross_point, 0.0000001)) { + start_point = (static_cast(&cbc1))->operator[] (1); } - switch (order) - { - case 3: - start_point = (static_cast(&cbc1))->operator[] (2); - //major league b***f***ing - if (are_near(start_point, cross_point, 0.0000001)) { - start_point = (static_cast(&cbc1))->operator[] (1); - } - break; - case 2: - //this never happens - start_point = (static_cast(&cbc1))->operator[] (1); - break; - case 1: - default: - start_point = cbc1.initialPoint(); - } - - order = Outline::bezierOrder(&cbc2); - - switch (order) - { - case 3: - end_point = (static_cast(&cbc2))->operator[] (1); - if (are_near(end_point, cross_point, 0.0000001)) { - end_point = (static_cast(&cbc2))->operator[] (2); - } - break; - case 2: - end_point = (static_cast(&cbc2))->operator[] (1); - break; - case 1: - default: - end_point = cbc2.finalPoint(); - } - //got our three points, now let's see what their clockwise angle is - - //Much credit to Wikipedia for the following ( http://en.wikipedia.org/wiki/Graham_scan ) - /******************************************************************** + break; + case 2: + //this never happens + start_point = (static_cast(&cbc1))->operator[] (1); + break; + case 1: + default: + start_point = cbc1.initialPoint(); + } + + order = Outline::bezierOrder(&cbc2); + + switch (order) { + case 3: + end_point = (static_cast(&cbc2))->operator[] (1); + if (are_near(end_point, cross_point, 0.0000001)) { + end_point = (static_cast(&cbc2))->operator[] (2); + } + break; + case 2: + end_point = (static_cast(&cbc2))->operator[] (1); + break; + case 1: + default: + end_point = cbc2.finalPoint(); + } + //got our three points, now let's see what their clockwise angle is + + //Much credit to Wikipedia for the following ( http://en.wikipedia.org/wiki/Graham_scan ) + /******************************************************************** # Three points are a counter-clockwise turn if ccw > 0, clockwise if # ccw < 0, and collinear if ccw = 0 because ccw is a determinant that # gives the signed area of the triangle formed by p1, p2 and p3. function ccw(p1, p2, p3): - return (p2.x - p1.x)*(p3.y - p1.y) - (p2.y - p1.y)*(p3.x - p1.x) + return (p2.x - p1.x)*(p3.y - p1.y) - (p2.y - p1.y)*(p3.x - p1.x) *********************************************************************/ - + double ccw = ( (cross_point.x() - start_point.x()) * (end_point.y() - start_point.y()) ) - ( (cross_point.y() - start_point.y()) * (end_point.x() - start_point.x()) ); if (ccw > 0) return true; return false; } -void extrapolate_curves(Geom::Path& path_builder, Geom::Curve* cbc1, Geom::Curve* cbc2, Geom::Point endPt, +void extrapolate_curves(Geom::Path& path_builder, Geom::Curve* cbc1, Geom::Curve* cbc2, Geom::Point endPt, double miter_limit, double line_width, bool outside = false) { - bool lineProblem = (dynamic_cast *>(cbc1)) || (dynamic_cast *>(cbc2)); + bool lineProblem = (dynamic_cast *>(cbc1)) || (dynamic_cast *>(cbc2)); if ( outside && !lineProblem ) { Geom::Path pth; pth.append(*cbc1); @@ -271,9 +264,8 @@ void extrapolate_curves(Geom::Path& path_builder, Geom::Curve* cbc1, Geom::Curve } } else { boost::optional p = intersection_point (cbc1->finalPoint(), tang1, - cbc2->initialPoint(), tang2); - if (p) - { + cbc2->initialPoint(), tang2); + if (p) { //check size of miter Geom::Point point_on_path = cbc1->finalPoint() - rot90(tang1) * line_width; Geom::Coord len = distance(*p, point_on_path); @@ -284,19 +276,18 @@ void extrapolate_curves(Geom::Path& path_builder, Geom::Curve* cbc1, Geom::Curve } path_builder.appendNew (endPt); } - } - if ( outside && lineProblem ) { - Geom::Path pth; + } + if ( outside && lineProblem ) { + Geom::Path pth; pth.append(*cbc1); - Geom::Point tang1 = Geom::unitTangentAt(Geom::reverse(pth.toPwSb()[0]), 0.); + Geom::Point tang1 = Geom::unitTangentAt(Geom::reverse(pth.toPwSb()[0]), 0.); pth = Geom::Path(); - pth.append( *cbc2 ); - Geom::Point tang2 = Geom::unitTangentAt(pth.toPwSb()[0], 0); - - boost::optional p = intersection_point (cbc1->finalPoint(), tang1, - cbc2->initialPoint(), tang2); - if (p) - { + pth.append( *cbc2 ); + Geom::Point tang2 = Geom::unitTangentAt(pth.toPwSb()[0], 0); + + boost::optional p = intersection_point (cbc1->finalPoint(), tang1, + cbc2->initialPoint(), tang2); + if (p) { //check size of miter Geom::Point point_on_path = cbc1->finalPoint() - rot90(tang1) * line_width; Geom::Coord len = distance(*p, point_on_path); @@ -306,13 +297,13 @@ void extrapolate_curves(Geom::Path& path_builder, Geom::Curve* cbc1, Geom::Curve } } path_builder.appendNew (endPt); - } - if ( !outside ) { - path_builder.appendNew (endPt); - } + } + if ( !outside ) { + path_builder.appendNew (endPt); + } } -void reflect_curves(Geom::Path& path_builder, Geom::Curve* cbc1, Geom::Curve* cbc2, Geom::Point endPt, +void reflect_curves(Geom::Path& path_builder, Geom::Curve* cbc1, Geom::Curve* cbc2, Geom::Point endPt, double miter_limit, double line_width, bool outside = false) { //the most important work for the reflected join is done here @@ -320,7 +311,7 @@ void reflect_curves(Geom::Path& path_builder, Geom::Curve* cbc1, Geom::Curve* cb //determine where we are in the path. If we're on the inside, ignore //and just lineTo. On the outside, we'll do a little reflection magic :) Geom::Crossings cross; - + if (outside) { Geom::Path pth; pth.append(*cbc1); @@ -347,9 +338,8 @@ void reflect_curves(Geom::Path& path_builder, Geom::Curve* cbc1, Geom::Curve* cb if ( cross.empty() ) { //curves didn't cross; default to miter boost::optional p = intersection_point (cbc1->finalPoint(), tang1, - cbc2->initialPoint(), tang2); - if (p) - { + cbc2->initialPoint(), tang2); + if (p) { //check size of miter Geom::Point point_on_path = cbc1->finalPoint() - rot90(tang1) * line_width; Geom::Coord len = distance(*p, point_on_path); @@ -388,27 +378,26 @@ Geom::Path doAdvHalfOutline(const Geom::Path& path_in, double line_width, double // NOTE: it is important to notice the distinction between a Geom::Path and a livarot Path here! // if you do not see "Geom::" there is a different function set! Geom::PathVector pv = split_at_cusps(path_in); - + Path to_outline; Path outlined_result; - + Geom::Path path_builder = Geom::Path(); //the path to store the result in Geom::PathVector * path_vec; //needed because livarot returns a goddamn pointer - + const unsigned k = path_in.size(); - - for (unsigned u = 0; u < k; u+=2) - { + + for (unsigned u = 0; u < k; u+=2) { to_outline = Path(); outlined_result = Path(); - + to_outline.LoadPath(pv[u], Geom::Affine(), false, false); to_outline.OutsideOutline(&outlined_result, line_width / 2, join_straight, butt_straight, 10); //now a curve has been outside outlined and loaded into outlined_result - + //get the Geom::Path path_vec = outlined_result.MakePathVector(); - + //thing to do on the first run through if (u == 0) { //I could use the pv->operator[] (0) notation but that looks terrible @@ -417,58 +406,64 @@ Geom::Path doAdvHalfOutline(const Geom::Path& path_in, double line_width, double //get the curves ready for the operation Geom::Curve * cbc1 = path_builder[path_builder.size() - 1].duplicate(); Geom::Curve * cbc2 = (*path_vec)[0] [0].duplicate(); - + //do the reflection/extrapolation: - if (extrapolate) { extrapolate_curves(path_builder, cbc1, cbc2, (*path_vec)[0].initialPoint(), miter_limit, line_width, - outside_angle ( pv[u - 1] [pv[u - 1].size() - 1], pv[u] [0] )); } - else { reflect_curves (path_builder, cbc1, cbc2, (*path_vec)[0].initialPoint(), miter_limit, line_width, - outside_angle ( pv[u - 1] [pv[u - 1].size() - 1], pv[u] [0] )); } + if (extrapolate) { + extrapolate_curves(path_builder, cbc1, cbc2, (*path_vec)[0].initialPoint(), miter_limit, line_width, + outside_angle ( pv[u - 1] [pv[u - 1].size() - 1], pv[u] [0] )); + } else { + reflect_curves (path_builder, cbc1, cbc2, (*path_vec)[0].initialPoint(), miter_limit, line_width, + outside_angle ( pv[u - 1] [pv[u - 1].size() - 1], pv[u] [0] )); + } } - + path_builder.append( (*path_vec)[0] ); - + //outline the next segment, but don't store it yet if (path_vec) delete path_vec; - + if (u < k - 1) { outlined_result = Path(); to_outline = Path(); - + to_outline.LoadPath(pv[u+1], Geom::Affine(), false, false); to_outline.OutsideOutline(&outlined_result, line_width / 2, join_straight, butt_straight, 10); - + path_vec = outlined_result.MakePathVector(); - + //get the curves ready for the operation Geom::Curve * cbc1 = path_builder[path_builder.size() - 1].duplicate(); Geom::Curve * cbc2 = (*path_vec)[0] [0].duplicate(); - + //do the reflection/extrapolation: - if (extrapolate) { extrapolate_curves(path_builder, cbc1, cbc2, (*path_vec)[0].initialPoint(), miter_limit, line_width, - outside_angle ( pv[u] [pv[u].size()-1], pv[u+1] [0] )); } - else { reflect_curves (path_builder, cbc1, cbc2, (*path_vec)[0].initialPoint(), miter_limit, line_width, - outside_angle ( pv[u] [pv[u].size()-1], pv[u+1] [0] )); } - + if (extrapolate) { + extrapolate_curves(path_builder, cbc1, cbc2, (*path_vec)[0].initialPoint(), miter_limit, line_width, + outside_angle ( pv[u] [pv[u].size()-1], pv[u+1] [0] )); + } else { + reflect_curves (path_builder, cbc1, cbc2, (*path_vec)[0].initialPoint(), miter_limit, line_width, + outside_angle ( pv[u] [pv[u].size()-1], pv[u+1] [0] )); + } + //Now we can store it. path_builder.append( (*path_vec)[0] ); - + if (cbc1) delete cbc1; if (cbc2) delete cbc2; if (path_vec) delete path_vec; } } - + return path_builder; } -Geom::PathVector outlinePath(const Geom::PathVector& path_in, double line_width, LineJoinType join, +Geom::PathVector outlinePath(const Geom::PathVector& path_in, double line_width, LineJoinType join, ButtType butt, double miter_lim, bool extrapolate) { Geom::PathVector path_out; - + unsigned pv_size = path_in.size(); for (unsigned i = 0; i < pv_size; i++) { - + if (path_in[i].size() > 1) { //since you've made it this far, hopefully all this is obvious :P Geom::Path with_direction; @@ -484,8 +479,8 @@ Geom::PathVector outlinePath(const Geom::PathVector& path_in, double line_width, newPath = Geom::path_from_piecewise(pwd2, 0.01)[0]; //fuk this with_direction = Outline::doAdvHalfOutline( newPath, -line_width, miter_lim, extrapolate ); - against_direction = Outline::doAdvHalfOutline( newPath.reverse(), -line_width, miter_lim, extrapolate ); - + against_direction = Outline::doAdvHalfOutline( newPath.reverse(), -line_width, miter_lim, extrapolate ); + /*if (dynamic_cast *>(&newPath[newPath.size()])) { //delete the 'Z' newPath.erase_last(); @@ -497,54 +492,54 @@ Geom::PathVector outlinePath(const Geom::PathVector& path_in, double line_width, newPath.erase_last(); newPath.append(path_in[i][path_in[i].size() - 1]); newPath.appendNew(newPath.initialPoint()); - newPath.erase_last(); + newPath.erase_last(); }*/ } Geom::PathBuilder pb; - + //add in the...do I really need to say this? pb.moveTo(with_direction.initialPoint()); pb.append(with_direction); - + //add in our line caps if (!path_in[i].closed()) { switch (butt) { - case butt_straight: - pb.lineTo(against_direction.initialPoint()); - break; - case butt_round: - pb.arcTo((-line_width) / 2, (-line_width) / 2, 0., true, true, against_direction.initialPoint() ); - break; - case butt_pointy: - //I have ZERO idea what to do here. - pb.lineTo(against_direction.initialPoint()); - break; - case butt_square: - pb.lineTo(against_direction.initialPoint()); - break; + case butt_straight: + pb.lineTo(against_direction.initialPoint()); + break; + case butt_round: + pb.arcTo((-line_width) / 2, (-line_width) / 2, 0., true, true, against_direction.initialPoint() ); + break; + case butt_pointy: + //I have ZERO idea what to do here. + pb.lineTo(against_direction.initialPoint()); + break; + case butt_square: + pb.lineTo(against_direction.initialPoint()); + break; } } else { pb.moveTo(against_direction.initialPoint()); } - + pb.append(against_direction); - + //cap (if necessary) if (!path_in[i].closed()) { switch (butt) { - case butt_straight: - pb.lineTo(with_direction.initialPoint()); - break; - case butt_round: - pb.arcTo((-line_width) / 2, (-line_width) / 2, 0., true, true, with_direction.initialPoint() ); - break; - case butt_pointy: - //I have ZERO idea what to do here. - pb.lineTo(with_direction.initialPoint()); - break; - case butt_square: - pb.lineTo(with_direction.initialPoint()); - break; + case butt_straight: + pb.lineTo(with_direction.initialPoint()); + break; + case butt_round: + pb.arcTo((-line_width) / 2, (-line_width) / 2, 0., true, true, with_direction.initialPoint() ); + break; + case butt_pointy: + //I have ZERO idea what to do here. + pb.lineTo(with_direction.initialPoint()); + break; + case butt_square: + pb.lineTo(with_direction.initialPoint()); + break; } } pb.flush(); @@ -554,7 +549,7 @@ Geom::PathVector outlinePath(const Geom::PathVector& path_in, double line_width, } else { Path p = Path(); Path outlinepath = Path(); - + p.LoadPath(path_in[i], Geom::Affine(), false, false); p.Outline(&outlinepath, line_width / 2, static_cast(join), butt, miter_lim); Geom::PathVector *pv_p = outlinepath.MakePathVector(); diff --git a/src/live_effects/pathoutlineprovider.h b/src/live_effects/pathoutlineprovider.h index 23cc7e2c4..27bc62d45 100644 --- a/src/live_effects/pathoutlineprovider.h +++ b/src/live_effects/pathoutlineprovider.h @@ -12,15 +12,15 @@ enum LineJoinType { LINEJOIN_EXTRAPOLATED }; -namespace Outline +namespace Outline { - unsigned bezierOrder (const Geom::Curve* curve_in); - std::vector PathVectorOutline(std::vector const & path_in, double line_width, ButtType linecap_type, - LineJoinType linejoin_type, double miter_limit); - - Geom::PathVector outlinePath(const Geom::PathVector& path_in, double line_width, LineJoinType join, - ButtType butt, double miter_lim, bool extrapolate = false); - Geom::Path PathOutsideOutline(Geom::Path const & path_in, double line_width, LineJoinType linejoin_type, double miter_limit); + unsigned bezierOrder (const Geom::Curve* curve_in); + std::vector PathVectorOutline(std::vector const & path_in, double line_width, ButtType linecap_type, + LineJoinType linejoin_type, double miter_limit); + + /*Geom::PathVector outlinePath(const Geom::PathVector& path_in, double line_width, LineJoinType join, + ButtType butt, double miter_lim, bool extrapolate = false);*/ + Geom::Path PathOutsideOutline(Geom::Path const & path_in, double line_width, LineJoinType linejoin_type, double miter_limit); } #endif // _SEEN_PATH_OUTLINE_H -- cgit v1.2.3 From b7c026006efcc5461dcef0f3c9a5e1b87d162d3d Mon Sep 17 00:00:00 2001 From: "Liam P. White" Date: Wed, 2 Apr 2014 17:33:37 -0400 Subject: Hopefully remove the last of the exception throwing with certain path effects (bzr r13090.1.43) --- src/live_effects/pathoutlineprovider.cpp | 24 ++++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-) (limited to 'src') diff --git a/src/live_effects/pathoutlineprovider.cpp b/src/live_effects/pathoutlineprovider.cpp index ad39a7416..56f741417 100644 --- a/src/live_effects/pathoutlineprovider.cpp +++ b/src/live_effects/pathoutlineprovider.cpp @@ -250,17 +250,21 @@ void extrapolate_curves(Geom::Path& path_builder, Geom::Curve* cbc1, Geom::Curve } Geom::EllipticalArc *arc0 = circle1.arc(cbc1->finalPoint(), 0.5*(cbc1->finalPoint()+sol), sol, true); Geom::EllipticalArc *arc1 = circle2.arc(sol, 0.5*(sol+endPt), endPt, true); + try { + if (arc0) { + path_builder.append (arc0->toSBasis()); + delete arc0; + arc0 = NULL; + } - if (arc0) { - path_builder.append (arc0->toSBasis()); - delete arc0; - arc0 = NULL; - } - - if (arc1) { - path_builder.append (arc1->toSBasis()); - delete arc1; - arc1 = NULL; + if (arc1) { + path_builder.append (arc1->toSBasis()); + delete arc1; + arc1 = NULL; + } + } catch (std::exception ex) { + printf("Exception occured, probably NaN or infinite valued points: %s\n", ex.what()); + path_builder.appendNew(endPt); } } else { boost::optional p = intersection_point (cbc1->finalPoint(), tang1, -- cgit v1.2.3 From b2f138290a5dedf907fe3e67d12ab93adfd5fd50 Mon Sep 17 00:00:00 2001 From: "Liam P. White" Date: Wed, 2 Apr 2014 21:49:11 -0400 Subject: Fix some minor issues (bzr r13090.1.44) --- src/live_effects/lpe-taperstroke.cpp | 29 ++++++++--------------------- 1 file changed, 8 insertions(+), 21 deletions(-) (limited to 'src') diff --git a/src/live_effects/lpe-taperstroke.cpp b/src/live_effects/lpe-taperstroke.cpp index 97ae02e3b..c452c825c 100644 --- a/src/live_effects/lpe-taperstroke.cpp +++ b/src/live_effects/lpe-taperstroke.cpp @@ -248,7 +248,7 @@ Geom::Path return_at_first_cusp (Geom::Path const & path_in, double smooth_toler Geom::Piecewise > stretch_along(Geom::Piecewise > pwd2_in, Geom::Path pattern, double width); //references to pointers, because magic -void subdivideCurve(Geom::Curve * curve_in, Geom::Coord t, Geom::Curve *& val_first, Geom::Curve *& val_second); +void subdivideCurve(const Geom::Curve * curve_in, Geom::Coord t, Geom::Curve *& val_first, Geom::Curve *& val_second); Geom::PathVector LPETaperStroke::doEffect_path(Geom::PathVector const& path_in) { @@ -269,7 +269,7 @@ Geom::PathVector LPETaperStroke::doEffect_path(Geom::PathVector const& path_in) } } - //don't ever let it be zero + //don't let it be zero if (attach_start <= 0.00000001) { attach_start.param_set_value( 0.00000001 ); zeroStart = true; @@ -329,12 +329,7 @@ Geom::PathVector LPETaperStroke::doEffect_path(Geom::PathVector const& path_in) throwaway_path = Outline::PathOutsideOutline(pathv_out[1], -fabs(line_width), static_cast(join_type.get_value()), miter_limit); - if (!zeroStart) { - throwaway_path.setInitial(real_path.finalPoint()); - real_path.append(throwaway_path); - } else { - real_path.append(throwaway_path, Geom::Path::STITCH_DISCONTINUOUS); - } + real_path.append(throwaway_path, Geom::Path::STITCH_DISCONTINUOUS); if (!zeroEnd) { //append the ending taper @@ -346,25 +341,17 @@ Geom::PathVector LPETaperStroke::doEffect_path(Geom::PathVector const& path_in) pwd2.concat(stretch_along(pathv_out[2].toPwSb(), pat_vec[0], -fabs(line_width))); throwaway_path = Geom::path_from_piecewise(pwd2, 0.001)[0]; - throwaway_path.setInitial(real_path.finalPoint()); - real_path.append(throwaway_path); + real_path.append(throwaway_path, Geom::Path::STITCH_DISCONTINUOUS); } //append the inside outline of the path (against direction) throwaway_path = Outline::PathOutsideOutline(pathv_out[1].reverse(), -fabs(line_width), static_cast(join_type.get_value()), miter_limit); - if (!zeroEnd) { - //throwaway_path.setInitial(real_path.finalPoint()); - real_path.append(throwaway_path, Geom::Path::STITCH_DISCONTINUOUS); - } else { - real_path.append(throwaway_path, Geom::Path::STITCH_DISCONTINUOUS); - } - - //hmm - real_path.setFinal(real_path.initialPoint()); - - real_path.close(); + real_path.append(throwaway_path, Geom::Path::STITCH_DISCONTINUOUS); + real_path.appendNew(real_path.initialPoint()); + real_path.close(); + real_pathv.push_back(real_path); return real_pathv; -- cgit v1.2.3 From 4007abe02509fc1e312a007fb26f31c5a595df26 Mon Sep 17 00:00:00 2001 From: "Liam P. White" Date: Thu, 3 Apr 2014 21:04:51 -0400 Subject: Begin first stage of resolving issue with duplicate knots (bzr r13090.1.46) --- src/knotholder.cpp | 14 ++++++++------ src/live_effects/lpe-taperstroke.cpp | 10 ++++++++++ src/live_effects/pathoutlineprovider.cpp | 4 +++- src/sp-lpe-item.cpp | 5 +++++ 4 files changed, 26 insertions(+), 7 deletions(-) (limited to 'src') diff --git a/src/knotholder.cpp b/src/knotholder.cpp index cf87423d4..94a041385 100644 --- a/src/knotholder.cpp +++ b/src/knotholder.cpp @@ -203,14 +203,16 @@ KnotHolder::knot_ungrabbed_handler(SPKnot */*knot*/, guint) /* do cleanup tasks (e.g., for LPE items write the parameter values * that were changed by dragging the handle to SVG) */ - if (SP_IS_LPE_ITEM(object)) { + if (dynamic_cast (object)) { // This writes all parameters to SVG. Is this sufficiently efficient or should we only // write the ones that were changed? - - Inkscape::LivePathEffect::Effect *lpe = SP_LPE_ITEM(object)->getCurrentLPE(); - if (lpe) { - LivePathEffectObject *lpeobj = lpe->getLPEObj(); - lpeobj->updateRepr(); + SPLPEItem * lpeitem = SP_LPE_ITEM(this->item); + if (lpeitem) { + Inkscape::LivePathEffect::Effect *lpe = lpeitem->getCurrentLPE(); + if (lpe) { + LivePathEffectObject *lpeobj = lpe->getLPEObj(); + lpeobj->updateRepr(); + } } } diff --git a/src/live_effects/lpe-taperstroke.cpp b/src/live_effects/lpe-taperstroke.cpp index c452c825c..dc70782c4 100644 --- a/src/live_effects/lpe-taperstroke.cpp +++ b/src/live_effects/lpe-taperstroke.cpp @@ -657,6 +657,11 @@ void KnotHolderEntityAttachBegin::knot_set(Geom::Point const &p, Geom::Point con Geom::Point const s = snap_knot_position(p, state); SPCurve *curve = SP_PATH(item)->get_curve_for_edit(); + if (!curve) { + //oops + lpe->attach_start.param_set_value(0); + return; + } Geom::PathVector pathv = curve->get_pathvector(); Piecewise > pwd2; Geom::Path p_in = return_at_first_cusp(pathv[0]); @@ -678,6 +683,11 @@ void KnotHolderEntityAttachEnd::knot_set(Geom::Point const &p, Geom::Point const Geom::Point const s = snap_knot_position(p, state); SPCurve *curve = SP_PATH(item)->get_curve_for_edit(); + if (!curve) { + //oops + lpe->attach_end.param_set_value(0); + return; + } Geom::PathVector pathv = curve->get_pathvector(); Piecewise > pwd2; Geom::Path p_in = return_at_first_cusp(pathv[0].reverse()); diff --git a/src/live_effects/pathoutlineprovider.cpp b/src/live_effects/pathoutlineprovider.cpp index 56f741417..a696728d6 100644 --- a/src/live_effects/pathoutlineprovider.cpp +++ b/src/live_effects/pathoutlineprovider.cpp @@ -1,3 +1,5 @@ +#include //g_critical + #include "pathoutlineprovider.h" #include "livarot/path-description.h" #include <2geom/angle.h> @@ -262,7 +264,7 @@ void extrapolate_curves(Geom::Path& path_builder, Geom::Curve* cbc1, Geom::Curve delete arc1; arc1 = NULL; } - } catch (std::exception ex) { + } catch (std::exception & ex) { printf("Exception occured, probably NaN or infinite valued points: %s\n", ex.what()); path_builder.appendNew(endPt); } diff --git a/src/sp-lpe-item.cpp b/src/sp-lpe-item.cpp index 71aa9545a..eda34a0b5 100644 --- a/src/sp-lpe-item.cpp +++ b/src/sp-lpe-item.cpp @@ -553,6 +553,7 @@ bool SPLPEItem::hasBrokenPathEffect() const bool SPLPEItem::hasPathEffect() const { + if (!path_effect_list) return false; //nullptr sucks if (path_effect_list->empty()) { return false; } @@ -698,6 +699,7 @@ PathEffectList const SPLPEItem::getEffectList() const Inkscape::LivePathEffect::LPEObjectReference* SPLPEItem::getCurrentLPEReference() { + if (!this->hasPathEffect()) return NULL; if (!this->current_path_effect && !this->path_effect_list->empty()) { setCurrentPathEffect(this->path_effect_list->back()); } @@ -707,6 +709,9 @@ Inkscape::LivePathEffect::LPEObjectReference* SPLPEItem::getCurrentLPEReference( Inkscape::LivePathEffect::Effect* SPLPEItem::getCurrentLPE() { + if (path_effect_list == NULL) { + return NULL; + } Inkscape::LivePathEffect::LPEObjectReference* lperef = getCurrentLPEReference(); if (lperef && lperef->lpeobject) -- cgit v1.2.3 From 09ab1cca2d7fb8cdbb252feb4d1ef7945249c051 Mon Sep 17 00:00:00 2001 From: "Liam P. White" Date: Fri, 4 Apr 2014 15:37:48 -0400 Subject: Prevent crash on "three knot" issue (bzr r13090.1.47) --- src/knotholder.cpp | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/knotholder.cpp b/src/knotholder.cpp index 94a041385..30a7e58d5 100644 --- a/src/knotholder.cpp +++ b/src/knotholder.cpp @@ -234,9 +234,14 @@ KnotHolder::knot_ungrabbed_handler(SPKnot */*knot*/, guint) else object_verb = SP_VERB_SELECTION_DYNAMIC_OFFSET; } - - DocumentUndo::done(object->document, object_verb, - _("Move handle")); + if (object) { //increasingly aggressive sanity checks + if (object->document) { + if (object_verb <= SP_VERB_LAST && object_verb >= SP_VERB_INVALID) { + DocumentUndo::done(object->document, object_verb, + _("Move handle")); + } + } + } //else { abort(); } } } -- cgit v1.2.3 From 6f10c7f675fae8c20f24f01b7cffb861f3726e9d Mon Sep 17 00:00:00 2001 From: "Liam P. White" Date: Sun, 6 Apr 2014 17:38:30 -0400 Subject: Properly allow effect stacking with knotholders (and add extra LPE functionality) (bzr r13090.1.48) --- src/live_effects/effect.cpp | 18 +++++++++ src/live_effects/effect.h | 8 ++++ src/live_effects/lpe-attach-path.cpp | 11 ++---- src/live_effects/lpe-attach-path.h | 2 - src/live_effects/lpe-knot.cpp | 4 ++ src/live_effects/lpe-knot.h | 3 +- src/live_effects/lpe-tangent_to_curve.cpp | 19 ++++------ src/live_effects/lpe-tangent_to_curve.h | 1 - src/live_effects/lpe-taperstroke.cpp | 62 +++++++++++++++---------------- src/snap.cpp | 2 +- src/sp-lpe-item.cpp | 4 +- 11 files changed, 77 insertions(+), 57 deletions(-) (limited to 'src') diff --git a/src/live_effects/effect.cpp b/src/live_effects/effect.cpp index 8bf210270..99282a312 100644 --- a/src/live_effects/effect.cpp +++ b/src/live_effects/effect.cpp @@ -373,6 +373,24 @@ void Effect::doOnRemove (SPLPEItem const* lpeitem) { } +//secret impl methods (shhhh!) +void Effect::doOnApply_impl(SPLPEItem const* lpeitem) +{ + sp_lpe_item = const_cast(lpeitem); + sp_curve = SP_SHAPE(sp_lpe_item)->getCurve(); + pathvector_before_effect = sp_curve->get_pathvector(); + doOnApply(lpeitem); +} + +void Effect::doBeforeEffect_impl(SPLPEItem const* lpeitem) +{ + sp_lpe_item = const_cast(lpeitem); + sp_curve = SP_SHAPE(sp_lpe_item)->getCurve(); + pathvector_before_effect = sp_curve->get_pathvector(); + + doBeforeEffect(lpeitem); +} + /** * Effects can have a parameter path set before they are applied by accepting a nonzero number of * mouse clicks. This method activates the pen context, which waits for the specified number of diff --git a/src/live_effects/effect.h b/src/live_effects/effect.h index 85c930def..d2d9f3b63 100644 --- a/src/live_effects/effect.h +++ b/src/live_effects/effect.h @@ -53,6 +53,11 @@ public: EffectType effectType() const; + //basically, to get this method called before the derived classes, a bit + //of indirection is needed. We first call these methods, then the below. + void doOnApply_impl(SPLPEItem const* lpeitem); + void doBeforeEffect_impl(SPLPEItem const* lpeitem); + virtual void doOnApply (SPLPEItem const* lpeitem); virtual void doBeforeEffect (SPLPEItem const* lpeitem); @@ -149,6 +154,9 @@ protected: // instead of normally 'splitting' the path into continuous pwd2 paths and calling doEffect_pwd2 for each. bool concatenate_before_pwd2; + SPLPEItem * sp_lpe_item; // these get stored in doBeforeEffect_impl, and derived classes may do as they please with them. + SPCurve * sp_curve; + std::vector pathvector_before_effect; private: bool provides_own_flash_paths; // if true, the standard flash path is suppressed diff --git a/src/live_effects/lpe-attach-path.cpp b/src/live_effects/lpe-attach-path.cpp index 0cceb1cb7..96372892e 100644 --- a/src/live_effects/lpe-attach-path.cpp +++ b/src/live_effects/lpe-attach-path.cpp @@ -62,15 +62,10 @@ void LPEAttachPath::resetDefaults(SPItem const * item) curve_end_previous_origin = end_path_curve_end.getOrigin(); } -void LPEAttachPath::doBeforeEffect(SPLPEItem const *lpeitem) -{ - lpe_effect = const_cast (lpeitem); -} - void LPEAttachPath::doEffect (SPCurve * curve) { std::vector this_pathv = curve->get_pathvector(); - if (lpe_effect && !this_pathv.empty()) { + if (sp_lpe_item && !this_pathv.empty()) { Geom::Path p = Geom::Path(this_pathv.front().initialPoint()); bool set_start_end = start_path_curve_end.getOrigin() != curve_start_previous_origin; @@ -79,7 +74,7 @@ void LPEAttachPath::doEffect (SPCurve * curve) if (start_path.linksToPath()) { std::vector linked_pathv = start_path.get_pathvector(); - Geom::Affine linkedtransform = start_path.getObject()->getRelativeTransform(lpe_effect); + Geom::Affine linkedtransform = start_path.getObject()->getRelativeTransform(sp_lpe_item); if ( !linked_pathv.empty() ) { @@ -132,7 +127,7 @@ void LPEAttachPath::doEffect (SPCurve * curve) if (end_path.linksToPath()) { std::vector linked_pathv = end_path.get_pathvector(); - Geom::Affine linkedtransform = end_path.getObject()->getRelativeTransform(lpe_effect); + Geom::Affine linkedtransform = end_path.getObject()->getRelativeTransform(sp_lpe_item); if ( !linked_pathv.empty() ) { diff --git a/src/live_effects/lpe-attach-path.h b/src/live_effects/lpe-attach-path.h index 390282f90..1d6c590d1 100644 --- a/src/live_effects/lpe-attach-path.h +++ b/src/live_effects/lpe-attach-path.h @@ -25,7 +25,6 @@ public: LPEAttachPath(LivePathEffectObject *lpeobject); virtual ~LPEAttachPath(); - virtual void doBeforeEffect(const SPLPEItem *lpeitem); virtual void doEffect (SPCurve * curve); virtual void resetDefaults(SPItem const * item); @@ -45,7 +44,6 @@ private: ScalarParam end_path_position; TransformedPointParam end_path_curve_start; VectorParam end_path_curve_end; - SPLPEItem * lpe_effect; }; }; //namespace LivePathEffect diff --git a/src/live_effects/lpe-knot.cpp b/src/live_effects/lpe-knot.cpp index 581c632f5..05b6ed795 100644 --- a/src/live_effects/lpe-knot.cpp +++ b/src/live_effects/lpe-knot.cpp @@ -538,6 +538,10 @@ LPEKnot::doBeforeEffect (SPLPEItem const* lpeitem) { using namespace Geom; original_bbox(lpeitem); + + if (SP_IS_PATH(lpeitem)) { + supplied_path = SP_PATH(lpeitem)->getCurve()->get_pathvector(); + } gpaths = std::vector(); gstroke_widths = std::vector(); diff --git a/src/live_effects/lpe-knot.h b/src/live_effects/lpe-knot.h index b937f9021..12ab32e5b 100644 --- a/src/live_effects/lpe-knot.h +++ b/src/live_effects/lpe-knot.h @@ -64,7 +64,8 @@ public: void addKnotHolderEntities(KnotHolder *knotholder, SPDesktop *desktop, SPItem *item); protected: - virtual void addCanvasIndicators(SPLPEItem const *lpeitem, std::vector &hp_vec); + virtual void addCanvasIndicators(SPLPEItem const *lpeitem, std::vector &hp_vec); + std::vector supplied_path; //for knotholder business private: void updateSwitcher(); diff --git a/src/live_effects/lpe-tangent_to_curve.cpp b/src/live_effects/lpe-tangent_to_curve.cpp index dbebdf7fb..bce4876af 100644 --- a/src/live_effects/lpe-tangent_to_curve.cpp +++ b/src/live_effects/lpe-tangent_to_curve.cpp @@ -16,8 +16,6 @@ #include #include "live_effects/lpe-tangent_to_curve.h" -// FIXME: The following are only needed to convert the path's SPCurve* to pwd2. -// There must be a more convenient way to achieve this. #include "sp-path.h" #include "display/curve.h" @@ -108,13 +106,13 @@ LPETangentToCurve::addKnotHolderEntities(KnotHolder *knotholder, SPDesktop *desk { KnotHolderEntity *e = new TtC::KnotHolderEntityLeftEnd(this); e->create( desktop, item, knotholder, Inkscape::CTRL_TYPE_UNKNOWN, - _("Adjust the \"left\" end of the tangent") ); + _("Adjust the left end of the tangent") ); knotholder->add(e); } { KnotHolderEntity *e = new TtC::KnotHolderEntityRightEnd(this); e->create( desktop, item, knotholder, Inkscape::CTRL_TYPE_UNKNOWN, - _("Adjust the \"right\" end of the tangent") ); + _("Adjust the right end of the tangent") ); knotholder->add(e); } }; @@ -130,14 +128,13 @@ KnotHolderEntityAttachPt::knot_set(Geom::Point const &p, Geom::Point const &/*or Geom::Point const s = snap_knot_position(p, state); - // FIXME: There must be a better way of converting the path's SPCurve* to pwd2. - SPCurve *curve = SP_PATH(item)->get_curve_for_edit(); - Geom::PathVector pathv = curve->get_pathvector(); - Piecewise > pwd2; - for (unsigned int i=0; i < pathv.size(); i++) { - pwd2.concat(pathv[i].toPwSb()); + if ( !SP_IS_SHAPE(lpe->sp_lpe_item) ) { + //lpe->t_attach.param_set_value(0); + g_warning("LPEItem is not a path! %s:%d\n", __FILE__, __LINE__); + return; } - + Piecewise > pwd2 = paths_to_pw( lpe->pathvector_before_effect ); + double t0 = nearest_point(s, pwd2); lpe->t_attach.param_set_value(t0); diff --git a/src/live_effects/lpe-tangent_to_curve.h b/src/live_effects/lpe-tangent_to_curve.h index 309afc14b..8e44c01d1 100644 --- a/src/live_effects/lpe-tangent_to_curve.h +++ b/src/live_effects/lpe-tangent_to_curve.h @@ -34,7 +34,6 @@ class LPETangentToCurve : public Effect { public: LPETangentToCurve(LivePathEffectObject *lpeobject); virtual ~LPETangentToCurve(); - virtual Geom::Piecewise > doEffect_pwd2 (Geom::Piecewise > const & pwd2_in); diff --git a/src/live_effects/lpe-taperstroke.cpp b/src/live_effects/lpe-taperstroke.cpp index dc70782c4..901abff70 100644 --- a/src/live_effects/lpe-taperstroke.cpp +++ b/src/live_effects/lpe-taperstroke.cpp @@ -235,9 +235,11 @@ Geom::Path return_at_first_cusp (Geom::Path const & path_in, double smooth_toler } //clearly it's collinear if two occupy the same point - g_assert(!are_near(start_point, cross_point, 0.0000001)); - g_assert(!are_near(cross_point, end_point, 0.0000001)); - g_assert(!are_near(start_point, end_point, 0.0000001)); + if (are_near(start_point, cross_point, 0.0000001) || + are_near(cross_point, end_point, 0.0000001) || + are_near(start_point, end_point, 0.0000001) ) { + g_critical("Holy crap, something went wrong! %s:%d\n", __FILE__, __LINE__); + } if (!are_collinear(start_point, cross_point, end_point, smooth_tolerance)) break; @@ -533,12 +535,6 @@ Geom::Piecewise > stretch_along(Geom::Piecewiseextent(); - noffset *= pattBndsY->extent(); - toffset *= pattBndsX->extent(); - }*/ - //Prevent more than 90% overlap... if (xspace < -pattBndsX->extent()*.9) { xspace = -pattBndsX->extent()*.9; @@ -587,12 +583,6 @@ Geom::Piecewise > stretch_along(Geom::Piecewiseget_curve_for_edit(); - if (!curve) { + if (!SP_IS_SHAPE(lpe->sp_lpe_item) ) { + g_warning("LPEItem is not a path! %s:%d\n", __FILE__, __LINE__); + return; + } + + SPCurve* curve; + if ( !(curve = SP_SHAPE(lpe->sp_lpe_item)->getCurve()) ) { //oops - lpe->attach_start.param_set_value(0); + //lpe->attach_start.param_set_value(0); return; } - Geom::PathVector pathv = curve->get_pathvector(); + //in case you are wondering, the above are simply sanity checks. we never want to actually + //use that object. + + Geom::PathVector pathv = lpe->pathvector_before_effect; + Piecewise > pwd2; Geom::Path p_in = return_at_first_cusp(pathv[0]); pwd2.concat(p_in.toPwSb()); - std::vector > > pwd_vec = split_at_discontinuities(pwd2); - double t0 = nearest_point(s, pwd_vec[0]); + double t0 = nearest_point(s, pwd2); lpe->attach_start.param_set_value(t0); // FIXME: this should not directly ask for updating the item. It should write to SVG, which triggers updating. @@ -682,22 +680,24 @@ void KnotHolderEntityAttachEnd::knot_set(Geom::Point const &p, Geom::Point const Geom::Point const s = snap_knot_position(p, state); - SPCurve *curve = SP_PATH(item)->get_curve_for_edit(); - if (!curve) { + if (!SP_IS_SHAPE(lpe->sp_lpe_item) ) { + g_warning("LPEItem is not a path! %s:%d\n", __FILE__, __LINE__); + return; + } + + SPCurve* curve; + if ( !(curve = SP_SHAPE(lpe->sp_lpe_item)->getCurve()) ) { //oops - lpe->attach_end.param_set_value(0); + //lpe->attach_end.param_set_value(0); return; } - Geom::PathVector pathv = curve->get_pathvector(); - Piecewise > pwd2; + Geom::PathVector pathv = lpe->pathvector_before_effect; Geom::Path p_in = return_at_first_cusp(pathv[0].reverse()); - pwd2.concat(p_in.toPwSb()); - std::vector > > pwd_vec = split_at_discontinuities(pwd2); - - double t0 = nearest_point(s, pwd_vec[0]); + Piecewise > pwd2 = p_in.toPwSb(); + + double t0 = nearest_point(s, pwd2); lpe->attach_end.param_set_value(t0); - // FIXME: this should not directly ask for updating the item. It should write to SVG, which triggers updating. sp_lpe_item_update_patheffect (SP_LPE_ITEM(item), false, true); } Geom::Point KnotHolderEntityAttachBegin::knot_get() const diff --git a/src/snap.cpp b/src/snap.cpp index ecf799cdc..c3891baea 100644 --- a/src/snap.cpp +++ b/src/snap.cpp @@ -116,7 +116,7 @@ void SnapManager::freeSnapReturnByRef(Geom::Point &p, Inkscape::SnapSourceType const source_type, Geom::OptRect const &bbox_to_snap) const { - Inkscape::SnappedPoint const s = freeSnap(Inkscape::SnapCandidatePoint(p, source_type), bbox_to_snap); + Inkscape::SnappedPoint const s = freeSnap(Inkscape::SnapCandidatePoint(p, source_type, Inkscape::SNAPTARGET_PATH), bbox_to_snap); s.getPointIfSnapped(p); } diff --git a/src/sp-lpe-item.cpp b/src/sp-lpe-item.cpp index eda34a0b5..712a0d579 100644 --- a/src/sp-lpe-item.cpp +++ b/src/sp-lpe-item.cpp @@ -242,7 +242,7 @@ bool SPLPEItem::performPathEffect(SPCurve *curve) { // Groups have their doBeforeEffect called elsewhere if (!SP_IS_GROUP(this)) { - lpe->doBeforeEffect(this); + lpe->doBeforeEffect_impl(this); } try { @@ -414,7 +414,7 @@ void SPLPEItem::addPathEffect(gchar *value, bool reset) } // perform this once when the effect is applied - lpe->doOnApply(this); + lpe->doOnApply_impl(this); // indicate that all necessary preparations are done and the effect can be performed lpe->setReady(); -- cgit v1.2.3 From a354238633c206078acc11a60d02382cee572740 Mon Sep 17 00:00:00 2001 From: "Liam P. White" Date: Sat, 12 Apr 2014 00:52:48 -0400 Subject: Wonderful code optimizations (bzr r13090.1.50) --- src/live_effects/lpe-taperstroke.cpp | 153 +++---------------------------- src/live_effects/pathoutlineprovider.cpp | 79 ++++++---------- src/live_effects/pathoutlineprovider.h | 6 ++ 3 files changed, 46 insertions(+), 192 deletions(-) (limited to 'src') diff --git a/src/live_effects/lpe-taperstroke.cpp b/src/live_effects/lpe-taperstroke.cpp index 901abff70..ce07ed962 100644 --- a/src/live_effects/lpe-taperstroke.cpp +++ b/src/live_effects/lpe-taperstroke.cpp @@ -180,77 +180,15 @@ void LPETaperStroke::doOnRemove(SPLPEItem const* lpeitem) //actual effect impl here -Geom::Path return_at_first_cusp (Geom::Path const & path_in, double smooth_tolerance = 0.05) +Geom::Path return_at_first_cusp (Geom::Path const & path_in, double /*smooth_tolerance*/ = 0.05) { - Geom::Path path_out = Geom::Path(); - - for (unsigned i = 0; i < path_in.size(); i++) { - path_out.append(path_in[i]); - if (path_in.size() == 1) - break; - - //determine order of curve - int order = Outline::bezierOrder(&path_in[i]); - - Geom::Point start_point; - Geom::Point cross_point = path_in[i].finalPoint(); - Geom::Point end_point; - - g_assert(path_in[i].finalPoint() == path_in[i+1].initialPoint()); - - //can you tell that the following expressions have been shaped by - //repeated compiler errors? ;) - switch (order) { - case 3: - start_point = (static_cast(&path_in[i]))->operator[] (2); - //major league b***f***ing - if (are_near(start_point, cross_point, 0.0000001)) { - start_point = (static_cast(&path_in[i]))->operator[] (1); - } - break; - case 2: - //this never happens - start_point = (static_cast(&path_in[i]))->operator[] (1); - break; - case 1: - default: - start_point = path_in[i].initialPoint(); - } - - order = Outline::bezierOrder(&path_in[i+1]); - - switch (order) { - case 3: - end_point = (static_cast(&path_in[i+1]))->operator[] (1); - if (are_near(end_point, cross_point, 0.0000001)) { - end_point = (static_cast(&path_in[i+1]))->operator[] (2); - } - break; - case 2: - end_point = (static_cast(&path_in[i+1]))->operator[] (1); - break; - case 1: - default: - end_point = path_in[i+1].finalPoint(); - } - - //clearly it's collinear if two occupy the same point - if (are_near(start_point, cross_point, 0.0000001) || - are_near(cross_point, end_point, 0.0000001) || - are_near(start_point, end_point, 0.0000001) ) { - g_critical("Holy crap, something went wrong! %s:%d\n", __FILE__, __LINE__); - } - - if (!are_collinear(start_point, cross_point, end_point, smooth_tolerance)) - break; - } - return path_out; + return Geom::split_at_cusps(path_in)[0]; } Geom::Piecewise > stretch_along(Geom::Piecewise > pwd2_in, Geom::Path pattern, double width); //references to pointers, because magic -void subdivideCurve(const Geom::Curve * curve_in, Geom::Coord t, Geom::Curve *& val_first, Geom::Curve *& val_second); +void subdivideCurve(Geom::Curve * curve_in, Geom::Coord t, Geom::Curve *& val_first, Geom::Curve *& val_second); Geom::PathVector LPETaperStroke::doEffect_path(Geom::PathVector const& path_in) { @@ -378,34 +316,9 @@ Geom::PathVector LPETaperStroke::doEffect_simplePath(Geom::PathVector const & pa trimmed_start.append(path_in[0] [i]); } - - //this is pretty annoying - //previously I wrote a function for this but it wasted a lot of time - //so I optimized it back into here. - unsigned order = Outline::bezierOrder(curve_start); - switch (order) { - case 3: { - Geom::CubicBezier *cb = static_cast(curve_start); - std::pair cb_pair = cb->subdivide((attach_start - loc)); - trimmed_start.append(cb_pair.first); - curve_start = cb_pair.second.duplicate(); //goes out of scope - break; - } - case 2: { - Geom::QuadraticBezier *qb = static_cast(curve_start); - std::pair qb_pair = qb->subdivide((attach_start - loc)); - trimmed_start.append(qb_pair.first); - curve_start = qb_pair.second.duplicate(); - break; - } - case 1: { - Geom::BezierCurveN<1> *lb = static_cast * >(curve_start); - std::pair, Geom::BezierCurveN<1> > lb_pair = lb->subdivide((attach_start - loc)); - trimmed_start.append(lb_pair.first); - curve_start = lb_pair.second.duplicate(); - break; - } - } + Geom::Curve * temp; + subdivideCurve(curve_start, attach_start - loc, temp, curve_start); + trimmed_start.append(*temp); //special case: path is one segment long //special case: what if the two knots occupy the same segment? @@ -416,31 +329,9 @@ Geom::PathVector LPETaperStroke::doEffect_simplePath(Geom::PathVector const & pa //we have to do some shifting here because the value changed when we reduced the length //of the previous segment. - order = Outline::bezierOrder(curve_start); - switch (order) { - case 3: { - Geom::CubicBezier *cb = static_cast(curve_start); - std::pair cb_pair = cb->subdivide(t); - trimmed_end.append(cb_pair.second); - curve_start = cb_pair.first.duplicate(); - break; - } - case 2: { - Geom::QuadraticBezier *qb = static_cast(curve_start); - std::pair qb_pair = qb->subdivide(t); - trimmed_end.append(qb_pair.second); - curve_start = qb_pair.first.duplicate(); - break; - } - case 1: { - Geom::BezierCurveN<1> *lb = static_cast * >(curve_start); - std::pair, Geom::BezierCurveN<1> > lb_pair = lb->subdivide(t); - trimmed_end.append(lb_pair.second); - curve_start = lb_pair.first.duplicate(); - break; - } - } - + subdivideCurve(curve_start, t, curve_start, temp); + trimmed_end.append(*temp); + for (unsigned j = (size - attach_end) + 1; j < size; j++) { trimmed_end.append(path_in[0] [j]); } @@ -468,30 +359,8 @@ Geom::PathVector LPETaperStroke::doEffect_simplePath(Geom::PathVector const & pa Geom::Coord t = Geom::nearest_point(end_attach_point, *curve_end); - order = Outline::bezierOrder(curve_end); - switch (order) { - case 3: { - Geom::CubicBezier *cb = static_cast(curve_end); - std::pair cb_pair = cb->subdivide(t); - trimmed_end.append(cb_pair.second); - curve_end = cb_pair.first.duplicate(); - break; - } - case 2: { - Geom::QuadraticBezier *qb = static_cast(curve_end); - std::pair qb_pair = qb->subdivide(t); - trimmed_end.append(qb_pair.second); - curve_end = qb_pair.first.duplicate(); - break; - } - case 1: { - Geom::BezierCurveN<1> *lb = static_cast * >(curve_end); - std::pair, Geom::BezierCurveN<1> > lb_pair = lb->subdivide(t); - trimmed_end.append(lb_pair.second); - curve_end = lb_pair.first.duplicate(); - break; - } - } + subdivideCurve(curve_end, t, curve_end, temp); + trimmed_end.append(*temp); for (unsigned j = (size - attach_end) + 1; j < size; j++) { trimmed_end.append(path_in[0] [j]); diff --git a/src/live_effects/pathoutlineprovider.cpp b/src/live_effects/pathoutlineprovider.cpp index a696728d6..5a95da75d 100644 --- a/src/live_effects/pathoutlineprovider.cpp +++ b/src/live_effects/pathoutlineprovider.cpp @@ -9,6 +9,7 @@ #include <2geom/shape.h> #include <2geom/transforms.h> #include <2geom/path-sink.h> +#include "helper/geom-nodetype.h" #include namespace Geom { @@ -99,21 +100,25 @@ static Circle touching_circle( D2 const &curve, double t, double tol=0.0 return Geom::Circle(center, fabs(radius)); } -static std::vector split_at_cusps(const Geom::Path& in) +std::vector split_at_cusps(const Geom::Path& in) { - Geom::PathVector out = Geom::PathVector(); - Geom::Path temp = Geom::Path(); - - for (unsigned path_descr = 0; path_descr < in.size(); path_descr++) { - temp = Geom::Path(); - temp.append(in[path_descr]); + PathVector out = PathVector(); + Path temp = Path(); + + for (unsigned i = 0; i < in.size(); i++) { + temp.append(in[i]); + if ( get_nodetype(in[i], in[i + 1]) != Geom::NODE_SMOOTH ) { + out.push_back(temp); + temp = Path(); + } + } + if (temp.size() > 0) { out.push_back(temp); } - return out; } -static Geom::CubicBezier sbasis_to_cubicbezier(Geom::D2 const & sbasis_in) +Geom::CubicBezier sbasis_to_cubicbezier(Geom::D2 const & sbasis_in) { std::vector temp; sbasis_to_bezier(temp, sbasis_in, 4); @@ -140,13 +145,9 @@ typedef Geom::Piecewise PWD2; unsigned bezierOrder (const Geom::Curve* curve_in) { using namespace Geom; - //cast it - const CubicBezier *cbc = dynamic_cast(curve_in); - if (cbc) return 3; - const QuadraticBezier * qbc = dynamic_cast(curve_in); - if (qbc) return 2; - const BezierCurveN<1U> * lbc = dynamic_cast *>(curve_in); - if (lbc) return 1; + if ( const BezierCurve* bz = dynamic_cast(curve_in) ) { + return bz->order(); + } return 0; } @@ -154,8 +155,6 @@ unsigned bezierOrder (const Geom::Curve* curve_in) //is >180 clockwise, otherwise false. bool outside_angle (const Geom::Curve& cbc1, const Geom::Curve& cbc2) { - unsigned order = bezierOrder(&cbc1); - Geom::Point start_point; Geom::Point cross_point = cbc1.finalPoint(); Geom::Point end_point; @@ -167,38 +166,18 @@ bool outside_angle (const Geom::Curve& cbc1, const Geom::Curve& cbc2) "By default we are going to say that this is an inside join, so we cannot make a line join for it.\n", __LINE__, __FILE__); return false; } - switch (order) { - case 3: - start_point = (static_cast(&cbc1))->operator[] (2); - //major league b***f***ing - if (are_near(start_point, cross_point, 0.0000001)) { - start_point = (static_cast(&cbc1))->operator[] (1); - } - break; - case 2: - //this never happens - start_point = (static_cast(&cbc1))->operator[] (1); - break; - case 1: - default: - start_point = cbc1.initialPoint(); + + //let's try: + Geom::CubicBezier cubicBezier = Geom::sbasis_to_cubicbezier(cbc1.toSBasis()); + start_point = cubicBezier [2]; + //stupid thing Inkscape does: + if (are_near(start_point, cross_point, 0.0000001)) { + start_point = cubicBezier [1]; } - - order = Outline::bezierOrder(&cbc2); - - switch (order) { - case 3: - end_point = (static_cast(&cbc2))->operator[] (1); - if (are_near(end_point, cross_point, 0.0000001)) { - end_point = (static_cast(&cbc2))->operator[] (2); - } - break; - case 2: - end_point = (static_cast(&cbc2))->operator[] (1); - break; - case 1: - default: - end_point = cbc2.finalPoint(); + cubicBezier = Geom::sbasis_to_cubicbezier(cbc2.toSBasis()); + end_point = cubicBezier [1]; + if (are_near(end_point, cross_point, 0.0000001)) { + end_point = cubicBezier [2]; } //got our three points, now let's see what their clockwise angle is @@ -391,7 +370,7 @@ Geom::Path doAdvHalfOutline(const Geom::Path& path_in, double line_width, double Geom::Path path_builder = Geom::Path(); //the path to store the result in Geom::PathVector * path_vec; //needed because livarot returns a goddamn pointer - const unsigned k = path_in.size(); + const unsigned k = pv.size(); for (unsigned u = 0; u < k; u+=2) { to_outline = Path(); diff --git a/src/live_effects/pathoutlineprovider.h b/src/live_effects/pathoutlineprovider.h index 27bc62d45..0ee0f261e 100644 --- a/src/live_effects/pathoutlineprovider.h +++ b/src/live_effects/pathoutlineprovider.h @@ -12,6 +12,12 @@ enum LineJoinType { LINEJOIN_EXTRAPOLATED }; +namespace Geom +{ + Geom::CubicBezier sbasis_to_cubicbezier(Geom::D2 const & sbasis_in); + std::vector split_at_cusps(const Geom::Path& in); +} + namespace Outline { unsigned bezierOrder (const Geom::Curve* curve_in); -- cgit v1.2.3 From 727826e1fdd2c4142b1687e50c174ed14c178427 Mon Sep 17 00:00:00 2001 From: "Liam P. White" Date: Sat, 12 Apr 2014 14:18:31 -0400 Subject: Fix triangles in joins (bzr r13090.1.52) --- src/live_effects/lpe-taperstroke.cpp | 58 ++++++++++++++------------------ src/live_effects/pathoutlineprovider.cpp | 45 +++++++++++++++++++++---- 2 files changed, 65 insertions(+), 38 deletions(-) (limited to 'src') diff --git a/src/live_effects/lpe-taperstroke.cpp b/src/live_effects/lpe-taperstroke.cpp index ce07ed962..2400b3e37 100644 --- a/src/live_effects/lpe-taperstroke.cpp +++ b/src/live_effects/lpe-taperstroke.cpp @@ -197,6 +197,8 @@ Geom::PathVector LPETaperStroke::doEffect_path(Geom::PathVector const& path_in) bool zeroStart = false; bool zeroEnd = false; + bool metInMiddle = false; + //there is a pretty good chance that people will try to drag the knots //on top of each other, so block it @@ -208,6 +210,10 @@ Geom::PathVector LPETaperStroke::doEffect_path(Geom::PathVector const& path_in) attach_end.param_set_value( size - attach_start ); } } + + if (attach_start == size - attach_end) { + metInMiddle = true; + } //don't let it be zero if (attach_start <= 0.00000001) { @@ -232,10 +238,10 @@ Geom::PathVector LPETaperStroke::doEffect_path(Geom::PathVector const& path_in) //don't let the knots be farther than they are allowed to be if ((unsigned)attach_start >= allowed_start) { - attach_start.param_set_value((double)allowed_start - 0.00000001); + attach_start.param_set_value((double)allowed_start - 0.00001); } if ((unsigned)attach_end >= allowed_end) { - attach_end.param_set_value((double)allowed_end - 0.00000001); + attach_end.param_set_value((double)allowed_end - 0.00001); } //remember, Path::operator () means get point at time t @@ -265,11 +271,14 @@ Geom::PathVector LPETaperStroke::doEffect_path(Geom::PathVector const& path_in) real_path.append(throwaway_path); } - //append the outside outline of the path (with direction) - throwaway_path = Outline::PathOutsideOutline(pathv_out[1], - -fabs(line_width), static_cast(join_type.get_value()), miter_limit); + + if (!metInMiddle) { + //append the outside outline of the path (with direction) + throwaway_path = Outline::PathOutsideOutline(pathv_out[1], + -fabs(line_width), static_cast(join_type.get_value()), miter_limit); - real_path.append(throwaway_path, Geom::Path::STITCH_DISCONTINUOUS); + real_path.append(throwaway_path, Geom::Path::STITCH_DISCONTINUOUS); + } if (!zeroEnd) { //append the ending taper @@ -460,32 +469,17 @@ Geom::Piecewise > stretch_along(Geom::Piecewise(curve_in); - std::pair cb_pair = cb->subdivide(t); - //trimmed_start.append(cb_pair.first); - val_first = cb_pair.first.duplicate(); - val_second = cb_pair.second.duplicate(); - break; - } - case 2: { - Geom::QuadraticBezier *qb = static_cast(curve_in); - std::pair qb_pair = qb->subdivide(t); - //trimmed_start.append(qb_pair.first); - val_first = qb_pair.first.duplicate(); - val_second = qb_pair.second.duplicate(); - break; - } - case 1: { - Geom::BezierCurveN<1> *lb = static_cast * >(curve_in); - std::pair, Geom::BezierCurveN<1> > lb_pair = lb->subdivide(t); - //trimmed_start.append(lb_pair.first); - val_first = lb_pair.first.duplicate(); - val_second = lb_pair.second.duplicate(); - break; - } + if (Geom::LineSegment* linear = dynamic_cast(curve_in)) { + //special case for line segments + std::pair seg_pair = linear->subdivide(t); + val_first = seg_pair.first.duplicate(); + val_second = seg_pair.second.duplicate(); + } else { + //all other cases: + Geom::CubicBezier cubic = Geom::sbasis_to_cubicbezier(curve_in->toSBasis()); + std::pair cubic_pair = cubic.subdivide(t); + val_first = cubic_pair.first.duplicate(); + val_second = cubic_pair.second.duplicate(); } } diff --git a/src/live_effects/pathoutlineprovider.cpp b/src/live_effects/pathoutlineprovider.cpp index 5a95da75d..080f42c08 100644 --- a/src/live_effects/pathoutlineprovider.cpp +++ b/src/live_effects/pathoutlineprovider.cpp @@ -261,6 +261,7 @@ void extrapolate_curves(Geom::Path& path_builder, Geom::Curve* cbc1, Geom::Curve } path_builder.appendNew (endPt); } + path_builder.append(*cbc2, Geom::Path::STITCH_DISCONTINUOUS); } if ( outside && lineProblem ) { Geom::Path pth; @@ -282,9 +283,22 @@ void extrapolate_curves(Geom::Path& path_builder, Geom::Curve* cbc1, Geom::Curve } } path_builder.appendNew (endPt); + path_builder.append(*cbc2, Geom::Path::STITCH_DISCONTINUOUS); } if ( !outside ) { - path_builder.appendNew (endPt); + /*path_builder.appendNew (endPt);*/ + Geom::Crossings cross = Geom::crossings(*cbc1, *cbc2); + if (!cross.empty()) { + path_builder.erase_last(); + Geom::CubicBezier cubic = Geom::sbasis_to_cubicbezier(cbc1->toSBasis()); + cubic = cubic.subdivide(cross[0].ta).first; + path_builder.append(cubic, Geom::Path::STITCH_DISCONTINUOUS); + cubic = Geom::sbasis_to_cubicbezier(cbc2->toSBasis()); + cubic = cubic.subdivide(cross[0].tb).second; + path_builder.append(cubic, Geom::Path::STITCH_DISCONTINUOUS); + } else { + path_builder.append(*cbc2, Geom::Path::STITCH_DISCONTINUOUS); + } } } @@ -346,9 +360,22 @@ void reflect_curves(Geom::Path& path_builder, Geom::Curve* cbc1, Geom::Curve* cb path_builder.appendNew (sub1.first[1], sub1.first[2], /*sub1.first[3]*/ sub2.second[0] ); path_builder.appendNew (sub2.second[1], sub2.second[2], /*sub2.second[3]*/ endPt ); } - } else { // cross.empty() + path_builder.append(*cbc2); + } else { //probably on the inside of the corner - path_builder.appendNew ( endPt ); + /*path_builder.appendNew ( endPt );*/ + cross = Geom::crossings(*cbc1, *cbc2); + if (!cross.empty()) { + path_builder.erase_last(); + Geom::CubicBezier cubic = Geom::sbasis_to_cubicbezier(cbc1->toSBasis()); + cubic = cubic.subdivide(cross[0].ta).first; + path_builder.append(cubic, Geom::Path::STITCH_DISCONTINUOUS); + cubic = Geom::sbasis_to_cubicbezier(cbc2->toSBasis()); + cubic = cubic.subdivide(cross[0].tb).second; + path_builder.append(cubic, Geom::Path::STITCH_DISCONTINUOUS); + } else { + path_builder.append(*cbc2, Geom::Path::STITCH_DISCONTINUOUS); + } } } @@ -387,6 +414,7 @@ Geom::Path doAdvHalfOutline(const Geom::Path& path_in, double line_width, double if (u == 0) { //I could use the pv->operator[] (0) notation but that looks terrible path_builder.start( (*path_vec)[0].initialPoint() ); + path_builder.append( (*path_vec)[0] ); } else { //get the curves ready for the operation Geom::Curve * cbc1 = path_builder[path_builder.size() - 1].duplicate(); @@ -400,10 +428,12 @@ Geom::Path doAdvHalfOutline(const Geom::Path& path_in, double line_width, double reflect_curves (path_builder, cbc1, cbc2, (*path_vec)[0].initialPoint(), miter_limit, line_width, outside_angle ( pv[u - 1] [pv[u - 1].size() - 1], pv[u] [0] )); } + Geom::Path temp_path = (*path_vec)[0]; + temp_path.erase(temp_path.begin()); + + path_builder.append( temp_path ); } - path_builder.append( (*path_vec)[0] ); - //outline the next segment, but don't store it yet if (path_vec) delete path_vec; @@ -430,7 +460,10 @@ Geom::Path doAdvHalfOutline(const Geom::Path& path_in, double line_width, double } //Now we can store it. - path_builder.append( (*path_vec)[0] ); + Geom::Path temp_path = (*path_vec)[0]; + temp_path.erase(temp_path.begin()); + + path_builder.append( temp_path ); if (cbc1) delete cbc1; if (cbc2) delete cbc2; -- cgit v1.2.3 From e36987cea4199ec3e51becad59b88e36c75e0955 Mon Sep 17 00:00:00 2001 From: "Liam P. White" Date: Sat, 12 Apr 2014 14:38:11 -0400 Subject: Fix memory leak (bzr r13090.1.53) --- src/live_effects/lpe-taperstroke.cpp | 3 +++ 1 file changed, 3 insertions(+) (limited to 'src') diff --git a/src/live_effects/lpe-taperstroke.cpp b/src/live_effects/lpe-taperstroke.cpp index 2400b3e37..8316daf71 100644 --- a/src/live_effects/lpe-taperstroke.cpp +++ b/src/live_effects/lpe-taperstroke.cpp @@ -328,6 +328,7 @@ Geom::PathVector LPETaperStroke::doEffect_simplePath(Geom::PathVector const & pa Geom::Curve * temp; subdivideCurve(curve_start, attach_start - loc, temp, curve_start); trimmed_start.append(*temp); + if (temp) delete temp; temp = 0; //special case: path is one segment long //special case: what if the two knots occupy the same segment? @@ -340,6 +341,7 @@ Geom::PathVector LPETaperStroke::doEffect_simplePath(Geom::PathVector const & pa subdivideCurve(curve_start, t, curve_start, temp); trimmed_end.append(*temp); + if (temp) delete temp; temp = 0; for (unsigned j = (size - attach_end) + 1; j < size; j++) { trimmed_end.append(path_in[0] [j]); @@ -370,6 +372,7 @@ Geom::PathVector LPETaperStroke::doEffect_simplePath(Geom::PathVector const & pa subdivideCurve(curve_end, t, curve_end, temp); trimmed_end.append(*temp); + if (temp) delete temp; temp = 0; for (unsigned j = (size - attach_end) + 1; j < size; j++) { trimmed_end.append(path_in[0] [j]); -- cgit v1.2.3 From 3a4844ef32ce02cbcb9f1102f61d60914bb48d72 Mon Sep 17 00:00:00 2001 From: "Liam P. White" Date: Sat, 12 Apr 2014 18:58:48 -0400 Subject: Enable line caps (bzr r13090.1.54) --- src/live_effects/pathoutlineprovider.cpp | 30 ++++++++++++++++++++++++------ 1 file changed, 24 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/live_effects/pathoutlineprovider.cpp b/src/live_effects/pathoutlineprovider.cpp index 080f42c08..d7f5362aa 100644 --- a/src/live_effects/pathoutlineprovider.cpp +++ b/src/live_effects/pathoutlineprovider.cpp @@ -528,14 +528,23 @@ Geom::PathVector outlinePath(const Geom::PathVector& path_in, double line_width, case butt_round: pb.arcTo((-line_width) / 2, (-line_width) / 2, 0., true, true, against_direction.initialPoint() ); break; - case butt_pointy: - //I have ZERO idea what to do here. + case butt_pointy: { + Geom::Point end_deriv = -Geom::unitTangentAt(Geom::reverse(path_in[i].back().toSBasis()), 0.); + double radius = 0.5 * Geom::distance(with_direction.finalPoint(), against_direction.initialPoint()); + Geom::Point midpoint = 0.5 * (with_direction.finalPoint() + against_direction.initialPoint()) + radius*end_deriv; + pb.lineTo(midpoint); pb.lineTo(against_direction.initialPoint()); break; - case butt_square: + } + case butt_square: { + Geom::Point end_deriv = -Geom::unitTangentAt(Geom::reverse(path_in[i].back().toSBasis()), 0.); + double radius = 0.5 * Geom::distance(with_direction.finalPoint(), against_direction.initialPoint()); + pb.lineTo(with_direction.finalPoint() + radius*end_deriv); + pb.lineTo(against_direction.initialPoint() + radius*end_deriv); pb.lineTo(against_direction.initialPoint()); break; } + } } else { pb.moveTo(against_direction.initialPoint()); } @@ -551,14 +560,23 @@ Geom::PathVector outlinePath(const Geom::PathVector& path_in, double line_width, case butt_round: pb.arcTo((-line_width) / 2, (-line_width) / 2, 0., true, true, with_direction.initialPoint() ); break; - case butt_pointy: - //I have ZERO idea what to do here. + case butt_pointy: { + Geom::Point end_deriv = -Geom::unitTangentAt(path_in[i].front().toSBasis(), 0.); + double radius = 0.5 * Geom::distance(against_direction.finalPoint(), with_direction.initialPoint()); + Geom::Point midpoint = 0.5 * (against_direction.finalPoint() + with_direction.initialPoint()) + radius*end_deriv; + pb.lineTo(midpoint); pb.lineTo(with_direction.initialPoint()); break; - case butt_square: + } + case butt_square: { + Geom::Point end_deriv = -Geom::unitTangentAt(path_in[i].front().toSBasis(), 0.); + double radius = 0.5 * Geom::distance(against_direction.finalPoint(), with_direction.initialPoint()); + pb.lineTo(against_direction.finalPoint() + radius*end_deriv); + pb.lineTo(with_direction.initialPoint() + radius*end_deriv); pb.lineTo(with_direction.initialPoint()); break; } + } } pb.flush(); for (unsigned m = 0; i < pb.peek().size(); i++) { -- cgit v1.2.3 From fd29d6366fe47e17b732ec4cc40d40ae1f272e35 Mon Sep 17 00:00:00 2001 From: "Liam P. White" Date: Sun, 13 Apr 2014 12:49:05 -0400 Subject: Nothing special (bzr r13090.1.55) --- src/live_effects/pathoutlineprovider.cpp | 49 ++++++++++++++++++-------------- 1 file changed, 27 insertions(+), 22 deletions(-) (limited to 'src') diff --git a/src/live_effects/pathoutlineprovider.cpp b/src/live_effects/pathoutlineprovider.cpp index d7f5362aa..d8e416fea 100644 --- a/src/live_effects/pathoutlineprovider.cpp +++ b/src/live_effects/pathoutlineprovider.cpp @@ -389,7 +389,13 @@ Geom::Path doAdvHalfOutline(const Geom::Path& path_in, double line_width, double { // NOTE: it is important to notice the distinction between a Geom::Path and a livarot Path here! // if you do not see "Geom::" there is a different function set! - Geom::PathVector pv = split_at_cusps(path_in); + Geom::Path temporary(path_in); + if (path_in.closed()) { + //this is a terrible solution + temporary.erase_last(); + temporary.close(false); + } + Geom::PathVector pv = split_at_cusps(temporary); Path to_outline; Path outlined_result; @@ -469,6 +475,12 @@ Geom::Path doAdvHalfOutline(const Geom::Path& path_in, double line_width, double if (cbc2) delete cbc2; if (path_vec) delete path_vec; } + if (path_in.closed()) { + temporary = Geom::Path(); + temporary.append(*path_in.end()); + Geom::Path temporary2 = doAdvHalfOutline(temporary, line_width, miter_limit, extrapolate); + path_builder.append(temporary2/*, Geom::Path::STITCH_DISCONTINUOUS*/); + } } return path_builder; @@ -492,25 +504,19 @@ Geom::PathVector outlinePath(const Geom::PathVector& path_in, double line_width, } else { //Geom::Path absolutely refuses to do what I want with these Geom::Path newPath = path_in[i]; - newPath.close(false); - Geom::Piecewise > pwd2 = newPath.toPwSb(); - newPath = Geom::path_from_piecewise(pwd2, 0.01)[0]; - //fuk this + if (Geom::distance(newPath.finalPoint(), newPath.initialPoint()) == newPath[newPath.size()].length()) { + Geom::LineSegment linear(newPath.finalPoint(), newPath.initialPoint()); + Geom::CubicBezier cubic = Geom::sbasis_to_cubicbezier(linear.toSBasis()); + newPath.appendNew(cubic[1], cubic[2], cubic[3]); + } + //newPath.close(false); with_direction = Outline::doAdvHalfOutline( newPath, -line_width, miter_lim, extrapolate ); against_direction = Outline::doAdvHalfOutline( newPath.reverse(), -line_width, miter_lim, extrapolate ); - - /*if (dynamic_cast *>(&newPath[newPath.size()])) { - //delete the 'Z' - newPath.erase_last(); - newPath.append(path_in[i][path_in[i].size() - 1]); - newPath.appendNew(newPath.initialPoint()); - newPath.erase_last(); - } else { - //delete the 'Z' - newPath.erase_last(); - newPath.append(path_in[i][path_in[i].size() - 1]); - newPath.appendNew(newPath.initialPoint()); - newPath.erase_last(); + /*if (Geom::distance(newPath.finalPoint(), newPath.initialPoint()) != newPath[newPath.size()].length()) { + with_direction.erase_last(); + with_direction.erase_last(); + against_direction.erase(against_direction.begin()); + against_direction.erase(against_direction.begin()); }*/ } Geom::PathBuilder pb; @@ -579,8 +585,9 @@ Geom::PathVector outlinePath(const Geom::PathVector& path_in, double line_width, } } pb.flush(); - for (unsigned m = 0; i < pb.peek().size(); i++) { - path_out.push_back(pb.peek()[m]); + path_out.push_back(pb.peek()[0]); + if (path_in[i].closed()) { + path_out.push_back(pb.peek()[1]); } } else { Path p = Path(); @@ -658,8 +665,6 @@ Geom::Path PathOutsideOutline(Geom::Path const & path_in, double line_width, Lin return path_out; } else if (linejoin_type == LINEJOIN_REFLECTED) { //reflected half outline - Geom::PathVector pathvec; - pathvec.push_back(path_in); path_out = doAdvHalfOutline(path_in, line_width, miter_lim, false); return path_out; } else if (linejoin_type == LINEJOIN_EXTRAPOLATED) { -- cgit v1.2.3 From 6f508cfcaa161695711309d3413b90d2b3f44ea0 Mon Sep 17 00:00:00 2001 From: "Liam P. White" Date: Mon, 14 Apr 2014 21:50:06 -0400 Subject: Minor things (bzr r13090.1.58) --- src/knotholder.cpp | 11 +++++++++-- src/live_effects/Makefile_insert | 3 ++- src/sp-lpe-item.cpp | 8 ++++++++ 3 files changed, 19 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/knotholder.cpp b/src/knotholder.cpp index 30a7e58d5..aea983cbb 100644 --- a/src/knotholder.cpp +++ b/src/knotholder.cpp @@ -154,8 +154,15 @@ KnotHolder::knot_clicked_handler(SPKnot *knot, guint state) } // for drag, this is done by ungrabbed_handler, but for click we must do it here - DocumentUndo::done(saved_item->document, object_verb, - _("Change handle")); + + if (saved_item) { //increasingly aggressive sanity checks + if (saved_item->document) { + if (object_verb <= SP_VERB_LAST && object_verb >= SP_VERB_INVALID) { + DocumentUndo::done(saved_item->document, object_verb, + _("Change handle")); + } + } + } // else { abort(); } } void diff --git a/src/live_effects/Makefile_insert b/src/live_effects/Makefile_insert index ac7c33e2f..e2c35c3bd 100644 --- a/src/live_effects/Makefile_insert +++ b/src/live_effects/Makefile_insert @@ -88,12 +88,13 @@ ink_common_sources += \ live_effects/lpe-attach-path.cpp \ live_effects/lpe-attach-path.h \ live_effects/lpe-fill-between-strokes.cpp \ - live_effects/lpe-fill-between-stroke.h \ + live_effects/lpe-fill-between-strokes.h \ live_effects/lpe-fill-between-many.cpp \ live_effects/lpe-fill-between-many.h \ live_effects/lpe-ellipse_5pts.cpp \ live_effects/lpe-ellipse_5pts.h \ live_effects/pathoutlineprovider.cpp \ + live_effects/pathoutlineprovider.h \ live_effects/lpe-jointype.cpp \ live_effects/lpe-jointype.h \ live_effects/lpe-taperstroke.cpp \ diff --git a/src/sp-lpe-item.cpp b/src/sp-lpe-item.cpp index 07fa6147b..ae5763e67 100644 --- a/src/sp-lpe-item.cpp +++ b/src/sp-lpe-item.cpp @@ -689,12 +689,20 @@ static std::string hreflist_write_svg(HRefList const & list) // Return a copy of the effect list PathEffectList SPLPEItem::getEffectList() { + if (!path_effect_list) { + g_critical("Broken path effect list in %s\n", __FILE__); + return PathEffectList(); + } return *path_effect_list; } // Return a copy of the effect list PathEffectList const SPLPEItem::getEffectList() const { + if (!path_effect_list) { + g_critical("Broken path effect list in %s\n", __FILE__); + return PathEffectList(); + } return *path_effect_list; } -- cgit v1.2.3 From 313863173f0d2f406dd3c36aea90099f22a04531 Mon Sep 17 00:00:00 2001 From: "Liam P. White" Date: Thu, 17 Apr 2014 13:58:57 -0400 Subject: Semi-fix for Join type on closed paths (bzr r13090.1.59) --- src/live_effects/pathoutlineprovider.cpp | 78 ++++++++++++++++++-------------- 1 file changed, 45 insertions(+), 33 deletions(-) (limited to 'src') diff --git a/src/live_effects/pathoutlineprovider.cpp b/src/live_effects/pathoutlineprovider.cpp index d8e416fea..4836b0d98 100644 --- a/src/live_effects/pathoutlineprovider.cpp +++ b/src/live_effects/pathoutlineprovider.cpp @@ -389,13 +389,8 @@ Geom::Path doAdvHalfOutline(const Geom::Path& path_in, double line_width, double { // NOTE: it is important to notice the distinction between a Geom::Path and a livarot Path here! // if you do not see "Geom::" there is a different function set! - Geom::Path temporary(path_in); - if (path_in.closed()) { - //this is a terrible solution - temporary.erase_last(); - temporary.close(false); - } - Geom::PathVector pv = split_at_cusps(temporary); + + Geom::PathVector pv = split_at_cusps(path_in); Path to_outline; Path outlined_result; @@ -434,6 +429,7 @@ Geom::Path doAdvHalfOutline(const Geom::Path& path_in, double line_width, double reflect_curves (path_builder, cbc1, cbc2, (*path_vec)[0].initialPoint(), miter_limit, line_width, outside_angle ( pv[u - 1] [pv[u - 1].size() - 1], pv[u] [0] )); } + //store it Geom::Path temp_path = (*path_vec)[0]; temp_path.erase(temp_path.begin()); @@ -475,11 +471,44 @@ Geom::Path doAdvHalfOutline(const Geom::Path& path_in, double line_width, double if (cbc2) delete cbc2; if (path_vec) delete path_vec; } - if (path_in.closed()) { - temporary = Geom::Path(); - temporary.append(*path_in.end()); - Geom::Path temporary2 = doAdvHalfOutline(temporary, line_width, miter_limit, extrapolate); - path_builder.append(temporary2/*, Geom::Path::STITCH_DISCONTINUOUS*/); + } + + if (path_in.closed()) { + if ( path_in[path_in.size() - 1].length() != Geom::distance(path_in[path_in.size() - 1].finalPoint(), path_in.initialPoint())) { + //handle case for last segment curved + outlined_result = Path(); + to_outline = Path(); + + Geom::Path oneCurve; oneCurve.append(path_in[0]); + + to_outline.LoadPath(oneCurve, Geom::Affine(), false, false); + to_outline.OutsideOutline(&outlined_result, line_width / 2, join_straight, butt_straight, 10); + + path_vec = outlined_result.MakePathVector(); + + Geom::Curve * cbc1 = path_builder[path_builder.size() - 1].duplicate();//(*path_vec)[0] [0].duplicate(); + Geom::Curve * cbc2 = (*path_vec)[0] [0].duplicate();//path_builder[path_builder.size() - 1].duplicate(); + + Geom::Path temporary; //why do we need this? you'll see in a bit + temporary.append(*cbc1); + + if (extrapolate) { + extrapolate_curves(temporary, cbc1, cbc2, cbc2->initialPoint(), miter_limit, line_width, + outside_angle ( path_in[path_in.size() - 1], path_in [0] )); + } else { + reflect_curves (temporary, cbc1, cbc2, cbc2->initialPoint(), miter_limit, line_width, + outside_angle ( path_in[path_in.size() - 1], path_in [0] )); + } + //extract the appended curves + if (temporary[0].finalPoint() != path_builder[path_builder.size() - 1].finalPoint()) { + path_builder.erase(path_builder.begin()); + } else { + temporary.erase_last(); + } + path_builder.erase_last(); + + path_builder.append(temporary, Geom::Path::STITCH_DISCONTINUOUS); + path_builder.close(); } } @@ -498,27 +527,10 @@ Geom::PathVector outlinePath(const Geom::PathVector& path_in, double line_width, //since you've made it this far, hopefully all this is obvious :P Geom::Path with_direction; Geom::Path against_direction; - if ( !path_in[i].closed() ) { - with_direction = Outline::doAdvHalfOutline( path_in[i], -line_width, miter_lim, extrapolate ); - against_direction = Outline::doAdvHalfOutline( path_in[i].reverse(), -line_width, miter_lim, extrapolate ); - } else { - //Geom::Path absolutely refuses to do what I want with these - Geom::Path newPath = path_in[i]; - if (Geom::distance(newPath.finalPoint(), newPath.initialPoint()) == newPath[newPath.size()].length()) { - Geom::LineSegment linear(newPath.finalPoint(), newPath.initialPoint()); - Geom::CubicBezier cubic = Geom::sbasis_to_cubicbezier(linear.toSBasis()); - newPath.appendNew(cubic[1], cubic[2], cubic[3]); - } - //newPath.close(false); - with_direction = Outline::doAdvHalfOutline( newPath, -line_width, miter_lim, extrapolate ); - against_direction = Outline::doAdvHalfOutline( newPath.reverse(), -line_width, miter_lim, extrapolate ); - /*if (Geom::distance(newPath.finalPoint(), newPath.initialPoint()) != newPath[newPath.size()].length()) { - with_direction.erase_last(); - with_direction.erase_last(); - against_direction.erase(against_direction.begin()); - against_direction.erase(against_direction.begin()); - }*/ - } + + with_direction = Outline::doAdvHalfOutline( path_in[i], -line_width, miter_lim, extrapolate ); + against_direction = Outline::doAdvHalfOutline( path_in[i].reverse(), -line_width, miter_lim, extrapolate ); + Geom::PathBuilder pb; //add in the...do I really need to say this? -- cgit v1.2.3 From d7d371a372254ac945dac7f5f6ac17ff1d96298f Mon Sep 17 00:00:00 2001 From: "Liam P. White" Date: Fri, 18 Apr 2014 14:36:25 -0400 Subject: Move my path effects outside test effects (stable) (bzr r13090.1.61) --- src/live_effects/effect.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/live_effects/effect.cpp b/src/live_effects/effect.cpp index 99282a312..3787dd849 100644 --- a/src/live_effects/effect.cpp +++ b/src/live_effects/effect.cpp @@ -110,8 +110,6 @@ const Util::EnumData LPETypeData[] = { {RECURSIVE_SKELETON, N_("Recursive skeleton"), "recursive_skeleton"}, {TANGENT_TO_CURVE, N_("Tangent to curve"), "tangent_to_curve"}, {TEXT_LABEL, N_("Text label"), "text_label"}, - {JOIN_TYPE, N_("Join type"), "join_type"}, - {TAPER_STROKE, N_("Taper stroke"), "taper_stroke"}, #endif /* 0.46 */ {BEND_PATH, N_("Bend"), "bend_path"}, @@ -137,6 +135,9 @@ const Util::EnumData LPETypeData[] = { {FILL_BETWEEN_MANY, N_("Fill between many"), "fill_between_many"}, {ELLIPSE_5PTS, N_("Ellipse by 5 points"), "ellipse_5pts"}, {BOUNDING_BOX, N_("Bounding Box"), "bounding_box"}, +/* lp:~inkscapebrony/inkscape/inkscape */ + {JOIN_TYPE, N_("Join type"), "join_type"}, + {TAPER_STROKE, N_("Taper stroke"), "taper_stroke"}, }; const Util::EnumDataConverter LPETypeConverter(LPETypeData, sizeof(LPETypeData)/sizeof(*LPETypeData)); -- cgit v1.2.3 From 6cf3f3c4fa0309fbe2af3849cbb0c1f3e9d2b2e7 Mon Sep 17 00:00:00 2001 From: "Liam P. White" Date: Sat, 19 Apr 2014 21:14:39 -0400 Subject: remove easter eggs (bzr r13090.1.62) --- src/live_effects/lpe-jointype.cpp | 7 +- src/live_effects/lpe-powerstroke.cpp | 3 + src/live_effects/lpe-taperstroke.cpp | 108 ++++++++++++++++++++----------- src/live_effects/pathoutlineprovider.cpp | 58 ++++++++++++----- 4 files changed, 119 insertions(+), 57 deletions(-) (limited to 'src') diff --git a/src/live_effects/lpe-jointype.cpp b/src/live_effects/lpe-jointype.cpp index 3b2887bb5..f3ec02530 100644 --- a/src/live_effects/lpe-jointype.cpp +++ b/src/live_effects/lpe-jointype.cpp @@ -52,9 +52,9 @@ static const Util::EnumDataConverter JoinTypeConverter(JoinTypeData, s LPEJoinType::LPEJoinType(LivePathEffectObject *lpeobject) : Effect(lpeobject), - line_width(_("Line width"), _("Thickness of the stroke"), "line_width", &wr, this, 10.), + line_width(_("Line width"), _("Thickness of the stroke"), "line_width", &wr, this, 1.), linecap_type(_("Line cap"), _("The end shape of the stroke"), "linecap_type", CapTypeConverter, &wr, this, butt_straight), - linejoin_type(_("Join:"), _("Determines the shape of the path's corners"), "linejoin_type", JoinTypeConverter, &wr, this, join_pointy), + linejoin_type(_("Join:"), _("Determines the shape of the path's corners"), "linejoin_type", JoinTypeConverter, &wr, this, LINEJOIN_EXTRAPOLATED), miter_limit(_("Miter limit:"), _("Maximum length of the miter join (in units of stroke width)"), "miter_limit", &wr, this, 100.), attempt_force_join(_("Force miter"), _("Overrides the miter limit and forces a join."), "attempt_force_join", &wr, this, true) { @@ -164,7 +164,8 @@ void LPEJoinType::doOnRemove(SPLPEItem const* lpeitem) std::vector LPEJoinType::doEffect_path(std::vector const & path_in) { return Outline::PathVectorOutline(path_in, line_width, static_cast(linecap_type.get_value()), - static_cast(linejoin_type.get_value()), miter_limit); + static_cast(linejoin_type.get_value()), + (attempt_force_join ? std::numeric_limits::max() : miter_limit)); } } //namespace LivePathEffect diff --git a/src/live_effects/lpe-powerstroke.cpp b/src/live_effects/lpe-powerstroke.cpp index d17def471..b63a2bf01 100644 --- a/src/live_effects/lpe-powerstroke.cpp +++ b/src/live_effects/lpe-powerstroke.cpp @@ -662,6 +662,9 @@ LPEPowerStroke::doEffect_path (std::vector const & path_in) if (Geom::Interpolate::CubicBezierJohan *johan = dynamic_cast(interpolator)) { johan->setBeta(interpolator_beta); } + if (Geom::Interpolate::CubicBezierSmooth *smooth = dynamic_cast(interpolator)) { + smooth->setBeta(interpolator_beta); + } Geom::Path strokepath = interpolator->interpolateToPath(ts); delete interpolator; diff --git a/src/live_effects/lpe-taperstroke.cpp b/src/live_effects/lpe-taperstroke.cpp index 8316daf71..c29690d4f 100644 --- a/src/live_effects/lpe-taperstroke.cpp +++ b/src/live_effects/lpe-taperstroke.cpp @@ -34,6 +34,11 @@ #include "knot-holder-entity.h" #include "knotholder.h" +template +inline bool withinRange(T value, T low, T high) { + return (value > low && value < high); +} + namespace Inkscape { namespace LivePathEffect { @@ -65,12 +70,12 @@ static const Util::EnumDataConverter JoinTypeConverter(JoinType, sizeo LPETaperStroke::LPETaperStroke(LivePathEffectObject *lpeobject) : Effect(lpeobject), - line_width(_("Stroke width"), _("The (non-tapered) width of the path"), "stroke_width", &wr, this, 3), + line_width(_("Stroke width"), _("The (non-tapered) width of the path"), "stroke_width", &wr, this, 1.), attach_start(_("Start offset"), _("Taper distance from path start"), "attach_start", &wr, this, 0.2), attach_end(_("End offset"), _("The ending position of the taper"), "end_offset", &wr, this, 0.2), smoothing(_("Taper smoothing"), _("Amount of smoothing to apply to the tapers"), "smoothing", &wr, this, 0.5), join_type(_("Join type"), _("Join type for non-smooth nodes"), "jointype", JoinTypeConverter, &wr, this, LINEJOIN_EXTRAPOLATED), - miter_limit(_("Miter limit"), _("Limit for miter joins"), "miter_limit", &wr, this, 30.) + miter_limit(_("Miter limit"), _("Limit for miter joins"), "miter_limit", &wr, this, 100.) { show_orig_path = true; _provides_knotholder_entities = true; @@ -205,43 +210,47 @@ Geom::PathVector LPETaperStroke::doEffect_path(Geom::PathVector const& path_in) unsigned size = path_in[0].size(); if (size == first_cusp.size()) { //check to see if the knots were dragged over each other - //if so, reset the end offset + //if so, reset the end offset, but still allow the start offset. if ( attach_start >= (size - attach_end) ) { attach_end.param_set_value( size - attach_start ); } } - if (attach_start == size - attach_end) { + if (attach_end == size - attach_start) { metInMiddle = true; } - //don't let it be zero - if (attach_start <= 0.00000001) { - attach_start.param_set_value( 0.00000001 ); - zeroStart = true; - } - if (attach_end <= 0.00000001) { - attach_end.param_set_value( 0.00000001 ); - zeroEnd = true; - } - //don't let it be integer - if (double(unsigned(attach_start)) == attach_start) { - attach_start.param_set_value(attach_start - 0.00001); - } - if (double(unsigned(attach_end)) == attach_end) { - attach_end.param_set_value(attach_end - 0.00001); + { + if (double(unsigned(attach_start)) == attach_start) { + attach_start.param_set_value(attach_start - 0.00001); + } + if (double(unsigned(attach_end)) == attach_end) { + attach_end.param_set_value(attach_end - 0.00001); + } } unsigned allowed_start = first_cusp.size(); unsigned allowed_end = last_cusp.size(); //don't let the knots be farther than they are allowed to be - if ((unsigned)attach_start >= allowed_start) { - attach_start.param_set_value((double)allowed_start - 0.00001); + { + if ((unsigned)attach_start >= allowed_start) { + attach_start.param_set_value((double)allowed_start - 0.00001); + } + if ((unsigned)attach_end >= allowed_end) { + attach_end.param_set_value((double)allowed_end - 0.00001); + } + } + + //don't let it be zero + if (attach_start < 0.0000001 || withinRange(double(attach_start), 0.00000001, 0.000001)) { + attach_start.param_set_value( 0.0000001 ); + zeroStart = true; } - if ((unsigned)attach_end >= allowed_end) { - attach_end.param_set_value((double)allowed_end - 0.00001); + if (attach_end < 0.0000001 || withinRange(double(attach_end), 0.00000001, 0.000001)) { + attach_end.param_set_value( 0.0000001 ); + zeroEnd = true; } //remember, Path::operator () means get point at time t @@ -252,7 +261,7 @@ Geom::PathVector LPETaperStroke::doEffect_path(Geom::PathVector const& path_in) //the following function just splits it up into three pieces. pathv_out = doEffect_simplePath(path_in); - //now for the actual tapering. We use a Pattern Along Path method to get this done. + //now for the actual tapering. We use the stretch_along method to get this done. Geom::PathVector real_pathv; Geom::Path real_path; @@ -261,13 +270,13 @@ Geom::PathVector LPETaperStroke::doEffect_path(Geom::PathVector const& path_in) Geom::Path throwaway_path; if (!zeroStart) { - //Construct the pattern (pat_str stands for pattern string) (yes, this is easier, trust me) + //Construct the pattern (pat_str stands for pattern string) (and yes, this is easier, trust me) std::stringstream pat_str; pat_str << "M 1,0 C " << 1 - (double)smoothing << ",0 0,0.5 0,0.5 0,0.5 " << 1 - (double)smoothing << ",1 1,1"; pat_vec = sp_svg_read_pathv(pat_str.str().c_str()); pwd2.concat(stretch_along(pathv_out[0].toPwSb(), pat_vec[0], -fabs(line_width))); - throwaway_path = Geom::path_from_piecewise(pwd2, 0.001)[0]; + throwaway_path = Geom::path_from_piecewise(pwd2, LPE_CONVERSION_TOLERANCE)[0]; real_path.append(throwaway_path); } @@ -276,29 +285,52 @@ Geom::PathVector LPETaperStroke::doEffect_path(Geom::PathVector const& path_in) //append the outside outline of the path (with direction) throwaway_path = Outline::PathOutsideOutline(pathv_out[1], -fabs(line_width), static_cast(join_type.get_value()), miter_limit); - - real_path.append(throwaway_path, Geom::Path::STITCH_DISCONTINUOUS); + if (!zeroStart) { + if (Geom::distance(real_path.finalPoint(), throwaway_path.initialPoint()) > 0.0000001) { + real_path.appendNew(throwaway_path.initialPoint()); + } else { + real_path.setFinal(throwaway_path.initialPoint()); + } + } + real_path.append(throwaway_path); } if (!zeroEnd) { //append the ending taper std::stringstream pat_str_1; - pat_str_1 << "M 0,0 0,1 C " << (double)smoothing << ",1 1,0.5 1,0.5 1,0.5 " << double(smoothing) << ",0 0,0"; + pat_str_1 << "M 0,1 C " << (double)smoothing << ",1 1,0.5 1,0.5 1,0.5 " << double(smoothing) << ",0 0,0"; pat_vec = sp_svg_read_pathv(pat_str_1.str().c_str()); pwd2 = Geom::Piecewise > (); pwd2.concat(stretch_along(pathv_out[2].toPwSb(), pat_vec[0], -fabs(line_width))); - throwaway_path = Geom::path_from_piecewise(pwd2, 0.001)[0]; - real_path.append(throwaway_path, Geom::Path::STITCH_DISCONTINUOUS); + throwaway_path = Geom::path_from_piecewise(pwd2, LPE_CONVERSION_TOLERANCE)[0]; + if (Geom::distance(real_path.finalPoint(), throwaway_path.initialPoint()) > 0.0000001) { + real_path.appendNew(throwaway_path.initialPoint()); + } else { + real_path.setFinal(throwaway_path.initialPoint()); + } + real_path.append(throwaway_path); + } + + if (!metInMiddle) { + //append the inside outline of the path (against direction) + throwaway_path = Outline::PathOutsideOutline(pathv_out[1].reverse(), + -fabs(line_width), static_cast(join_type.get_value()), miter_limit); + + if (Geom::distance(real_path.finalPoint(), throwaway_path.initialPoint()) > 0.0000001) { + real_path.appendNew(throwaway_path.initialPoint()); + } else { + real_path.setFinal(throwaway_path.initialPoint()); + } + real_path.append(throwaway_path); + } + + if (Geom::distance(real_path.finalPoint(), real_path.initialPoint()) > 0.0000001) { + real_path.appendNew(real_path.initialPoint()); + } else { + real_path.setFinal(real_path.initialPoint()); } - //append the inside outline of the path (against direction) - throwaway_path = Outline::PathOutsideOutline(pathv_out[1].reverse(), - -fabs(line_width), static_cast(join_type.get_value()), miter_limit); - - real_path.append(throwaway_path, Geom::Path::STITCH_DISCONTINUOUS); - real_path.appendNew(real_path.initialPoint()); - real_path.close(); real_pathv.push_back(real_path); diff --git a/src/live_effects/pathoutlineprovider.cpp b/src/live_effects/pathoutlineprovider.cpp index b5a3258fa..9ff896f84 100644 --- a/src/live_effects/pathoutlineprovider.cpp +++ b/src/live_effects/pathoutlineprovider.cpp @@ -162,8 +162,7 @@ bool outside_angle (const Geom::Curve& cbc1, const Geom::Curve& cbc2) //assert(cbc1.finalPoint() == cbc2.initialPoint()); //short circuiting? if (cbc1.finalPoint() != cbc2.initialPoint()) { - printf("There was an issue when asserting that one curve's end is the start of the other. Line %d, File %s\n" - "By default we are going to say that this is an inside join, so we cannot make a line join for it.\n", __LINE__, __FILE__); + printf("erk! Line %d, File %s\n", __LINE__, __FILE__); return false; } @@ -261,7 +260,10 @@ void extrapolate_curves(Geom::Path& path_builder, Geom::Curve* cbc1, Geom::Curve } path_builder.appendNew (endPt); } - path_builder.append(*cbc2, Geom::Path::STITCH_DISCONTINUOUS); + if (cbc1->finalPoint() != cbc2->initialPoint()) { + path_builder.appendNew(cbc2->initialPoint()); + } + path_builder.append(*cbc2); } if ( outside && lineProblem ) { Geom::Path pth; @@ -283,7 +285,10 @@ void extrapolate_curves(Geom::Path& path_builder, Geom::Curve* cbc1, Geom::Curve } } path_builder.appendNew (endPt); - path_builder.append(*cbc2, Geom::Path::STITCH_DISCONTINUOUS); + if (cbc1->finalPoint() != cbc2->initialPoint()) { + path_builder.appendNew(cbc2->initialPoint()); + } + path_builder.append(*cbc2); } if ( !outside ) { /*path_builder.appendNew (endPt);*/ @@ -297,7 +302,12 @@ void extrapolate_curves(Geom::Path& path_builder, Geom::Curve* cbc1, Geom::Curve cubic = cubic.subdivide(cross[0].tb).second; path_builder.append(cubic, Geom::Path::STITCH_DISCONTINUOUS); } else { - path_builder.append(*cbc2, Geom::Path::STITCH_DISCONTINUOUS); + if (Geom::distance(path_builder.finalPoint(), cbc2->initialPoint()) > 0.0000001) { + path_builder.appendNew(cbc2->initialPoint()); + } else { + path_builder.setFinal(cbc2->initialPoint()); + } + path_builder.append(*cbc2); } } } @@ -360,6 +370,9 @@ void reflect_curves(Geom::Path& path_builder, Geom::Curve* cbc1, Geom::Curve* cb path_builder.appendNew (sub1.first[1], sub1.first[2], /*sub1.first[3]*/ sub2.second[0] ); path_builder.appendNew (sub2.second[1], sub2.second[2], /*sub2.second[3]*/ endPt ); } + if (cbc1->finalPoint() != cbc2->initialPoint()) { + path_builder.appendNew(cbc2->initialPoint()); + } path_builder.append(*cbc2); } else { //probably on the inside of the corner @@ -374,7 +387,12 @@ void reflect_curves(Geom::Path& path_builder, Geom::Curve* cbc1, Geom::Curve* cb cubic = cubic.subdivide(cross[0].tb).second; path_builder.append(cubic, Geom::Path::STITCH_DISCONTINUOUS); } else { - path_builder.append(*cbc2, Geom::Path::STITCH_DISCONTINUOUS); + if (Geom::distance(path_builder.finalPoint(), cbc2->initialPoint()) > 0.0000001) { + path_builder.appendNew(cbc2->initialPoint()); + } else { + path_builder.setFinal(cbc2->initialPoint()); + } + path_builder.append(*cbc2); } } } @@ -431,6 +449,7 @@ Geom::Path doAdvHalfOutline(const Geom::Path& path_in, double line_width, double } //store it Geom::Path temp_path = (*path_vec)[0]; + //erase the first segment since the join code already appended it temp_path.erase(temp_path.begin()); path_builder.append( temp_path ); @@ -477,7 +496,7 @@ Geom::Path doAdvHalfOutline(const Geom::Path& path_in, double line_width, double Geom::Curve * cbc1; Geom::Curve * cbc2; - if ( path_in[path_in.size() - 1].length() != Geom::distance(path_in[path_in.size() - 1].finalPoint(), path_in.initialPoint())) { + if ( path_in[path_in.size()].isDegenerate() ) { //handle case for last segment curved outlined_result = Path(); to_outline = Path(); @@ -512,10 +531,10 @@ Geom::Path doAdvHalfOutline(const Geom::Path& path_in, double line_width, double if (extrapolate) { extrapolate_curves(path_builder, cbc1, cbc2, cbc2->initialPoint(), miter_limit, line_width, - outside_angle ( path_in[path_in.size() - 1], path_in [0] )); + outside_angle ( path_in[path_in.size() - 1], oneCurve [0] )); } else { reflect_curves (path_builder, cbc1, cbc2, cbc2->initialPoint(), miter_limit, line_width, - outside_angle ( path_in[path_in.size() - 1], path_in [0] )); + outside_angle ( path_in[path_in.size() - 1], oneCurve [0] )); } delete cbc1; cbc1 = cbc2->duplicate(); @@ -534,22 +553,29 @@ Geom::Path doAdvHalfOutline(const Geom::Path& path_in, double line_width, double Geom::Path temporary; //just an accessory path, we won't need it for long temporary.append(*cbc1); + const Geom::Curve& prev_curve = path_in[path_in.size()].isDegenerate() ? path_in[path_in.size() - 1] : + path_in[path_in.size()]; + if (extrapolate) { extrapolate_curves(temporary, cbc1, cbc2, cbc2->initialPoint(), miter_limit, line_width, - outside_angle ( path_in[path_in.size() - 1], path_in [0] )); + outside_angle ( prev_curve, path_in [0] )); } else { reflect_curves (temporary, cbc1, cbc2, cbc2->initialPoint(), miter_limit, line_width, - outside_angle ( path_in[path_in.size() - 1], path_in [0] )); + outside_angle ( prev_curve, path_in [0] )); } //extract the appended curves - if (temporary[0].finalPoint() != path_builder[path_builder.size() - 1].finalPoint()) { + //if (temporary[temporary.size()].initialPoint() != path_builder[0].initialPoint()) { path_builder.erase(path_builder.begin()); - } else { + /*} else { temporary.erase_last(); - } + }*/ path_builder.erase_last(); - - path_builder.append(temporary, Geom::Path::STITCH_DISCONTINUOUS); + if (Geom::distance(path_builder.finalPoint(), temporary.initialPoint()) > 0.0000001) { + path_builder.appendNew(temporary.initialPoint()); + } else { + path_builder.setFinal(temporary.initialPoint()); + } + path_builder.append(temporary); path_builder.close(); if (cbc1) delete cbc1; -- cgit v1.2.3 From 44dbc123e17a639c9a8dc7c2a2bd3d36a444823c Mon Sep 17 00:00:00 2001 From: "Liam P. White" Date: Sat, 19 Apr 2014 23:12:30 -0400 Subject: Bug fixes (bzr r13090.1.63) --- src/live_effects/effect.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/live_effects/effect.cpp b/src/live_effects/effect.cpp index 3787dd849..4b48ce68c 100644 --- a/src/live_effects/effect.cpp +++ b/src/live_effects/effect.cpp @@ -378,8 +378,8 @@ void Effect::doOnRemove (SPLPEItem const* lpeitem) void Effect::doOnApply_impl(SPLPEItem const* lpeitem) { sp_lpe_item = const_cast(lpeitem); - sp_curve = SP_SHAPE(sp_lpe_item)->getCurve(); - pathvector_before_effect = sp_curve->get_pathvector(); + /*sp_curve = SP_SHAPE(sp_lpe_item)->getCurve(); + pathvector_before_effect = sp_curve->get_pathvector();*/ doOnApply(lpeitem); } -- cgit v1.2.3 From 2f628e571a3817765392479766418add4bbdaa20 Mon Sep 17 00:00:00 2001 From: "Liam P. White" Date: Sun, 20 Apr 2014 11:03:23 -0400 Subject: minor bugfix (bzr r13090.1.64) --- src/live_effects/lpe-taperstroke.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/live_effects/lpe-taperstroke.cpp b/src/live_effects/lpe-taperstroke.cpp index c29690d4f..7aa896ade 100644 --- a/src/live_effects/lpe-taperstroke.cpp +++ b/src/live_effects/lpe-taperstroke.cpp @@ -216,7 +216,7 @@ Geom::PathVector LPETaperStroke::doEffect_path(Geom::PathVector const& path_in) } } - if (attach_end == size - attach_start) { + if (attach_start == size - attach_end) { metInMiddle = true; } -- cgit v1.2.3 From 3c99062c5bc3c28b9c2b05de0ee3e9c2725a55b6 Mon Sep 17 00:00:00 2001 From: "Liam P. White" Date: Sun, 20 Apr 2014 13:05:53 -0400 Subject: correcting previous revision (bzr r13090.1.65) --- src/live_effects/lpe-taperstroke.cpp | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/live_effects/lpe-taperstroke.cpp b/src/live_effects/lpe-taperstroke.cpp index 7aa896ade..8ddaa4087 100644 --- a/src/live_effects/lpe-taperstroke.cpp +++ b/src/live_effects/lpe-taperstroke.cpp @@ -213,12 +213,16 @@ Geom::PathVector LPETaperStroke::doEffect_path(Geom::PathVector const& path_in) //if so, reset the end offset, but still allow the start offset. if ( attach_start >= (size - attach_end) ) { attach_end.param_set_value( size - attach_start ); + metInMiddle = true; } } if (attach_start == size - attach_end) { metInMiddle = true; } + if (attach_end == size - attach_start) { + metInMiddle = true; + } //don't let it be integer { @@ -285,7 +289,7 @@ Geom::PathVector LPETaperStroke::doEffect_path(Geom::PathVector const& path_in) //append the outside outline of the path (with direction) throwaway_path = Outline::PathOutsideOutline(pathv_out[1], -fabs(line_width), static_cast(join_type.get_value()), miter_limit); - if (!zeroStart) { + if (!zeroStart && real_path.size() >= 1 && throwaway_path.size() >= 1) { if (Geom::distance(real_path.finalPoint(), throwaway_path.initialPoint()) > 0.0000001) { real_path.appendNew(throwaway_path.initialPoint()); } else { @@ -305,7 +309,7 @@ Geom::PathVector LPETaperStroke::doEffect_path(Geom::PathVector const& path_in) pwd2.concat(stretch_along(pathv_out[2].toPwSb(), pat_vec[0], -fabs(line_width))); throwaway_path = Geom::path_from_piecewise(pwd2, LPE_CONVERSION_TOLERANCE)[0]; - if (Geom::distance(real_path.finalPoint(), throwaway_path.initialPoint()) > 0.0000001) { + if (Geom::distance(real_path.finalPoint(), throwaway_path.initialPoint()) > 0.0000001 && real_path.size() >= 1) { real_path.appendNew(throwaway_path.initialPoint()); } else { real_path.setFinal(throwaway_path.initialPoint()); @@ -318,7 +322,7 @@ Geom::PathVector LPETaperStroke::doEffect_path(Geom::PathVector const& path_in) throwaway_path = Outline::PathOutsideOutline(pathv_out[1].reverse(), -fabs(line_width), static_cast(join_type.get_value()), miter_limit); - if (Geom::distance(real_path.finalPoint(), throwaway_path.initialPoint()) > 0.0000001) { + if (Geom::distance(real_path.finalPoint(), throwaway_path.initialPoint()) > 0.0000001 && real_path.size() >= 1) { real_path.appendNew(throwaway_path.initialPoint()); } else { real_path.setFinal(throwaway_path.initialPoint()); -- cgit v1.2.3 From 2a5ab3d65249a8a7dde08097c87562d5bca598f2 Mon Sep 17 00:00:00 2001 From: "Liam P. White" Date: Tue, 29 Apr 2014 19:55:14 -0400 Subject: Fix a small issue with Attach Path (bzr r13090.1.69) --- src/live_effects/effect.cpp | 1 + src/sp-lpe-item.cpp | 5 ++++- 2 files changed, 5 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/live_effects/effect.cpp b/src/live_effects/effect.cpp index 4b48ce68c..d8e057ab7 100644 --- a/src/live_effects/effect.cpp +++ b/src/live_effects/effect.cpp @@ -386,6 +386,7 @@ void Effect::doOnApply_impl(SPLPEItem const* lpeitem) void Effect::doBeforeEffect_impl(SPLPEItem const* lpeitem) { sp_lpe_item = const_cast(lpeitem); + //printf("(SPLPEITEM*) %p\n", sp_lpe_item); sp_curve = SP_SHAPE(sp_lpe_item)->getCurve(); pathvector_before_effect = sp_curve->get_pathvector(); diff --git a/src/sp-lpe-item.cpp b/src/sp-lpe-item.cpp index b5dd74fc6..19a688ca5 100644 --- a/src/sp-lpe-item.cpp +++ b/src/sp-lpe-item.cpp @@ -242,7 +242,7 @@ bool SPLPEItem::performPathEffect(SPCurve *curve) { // Groups have their doBeforeEffect called elsewhere if (!SP_IS_GROUP(this)) { - lpe->doBeforeEffect(this); + lpe->doBeforeEffect_impl(this); } try { @@ -256,6 +256,9 @@ bool SPLPEItem::performPathEffect(SPCurve *curve) { } return false; } + if (!SP_IS_GROUP(this)) { + lpe->doAfterEffect(this); + } } } } -- cgit v1.2.3 From 0a3de4794a6fa71b4c6b4217d42115001503013e Mon Sep 17 00:00:00 2001 From: "Liam P. White" Date: Sat, 10 May 2014 09:47:56 -0400 Subject: Fix stubborn bug 1299948 Fixed bugs: - https://launchpad.net/bugs/1299948 (bzr r13090.1.74) --- src/live_effects/parameter/path.cpp | 5 +++++ src/sp-path.cpp | 18 ++++++++++++++++-- 2 files changed, 21 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/live_effects/parameter/path.cpp b/src/live_effects/parameter/path.cpp index cdbbef1db..44d414942 100644 --- a/src/live_effects/parameter/path.cpp +++ b/src/live_effects/parameter/path.cpp @@ -118,6 +118,11 @@ PathParam::param_readSVGValue(const gchar * strvalue) // Now do the attaching, which emits the changed signal. try { ref.attach(Inkscape::URI(href)); + //lp:1299948 + SPItem* i = ref.getObject(); + if (i) { + linked_modified_callback(i, SP_OBJECT_MODIFIED_FLAG); + } // else: document still processing new events. Repr of the linked object not created yet. } catch (Inkscape::BadURIException &e) { g_warning("%s", e.what()); ref.detach(); diff --git a/src/sp-path.cpp b/src/sp-path.cpp index cbb61b0f6..d1fb850e1 100644 --- a/src/sp-path.cpp +++ b/src/sp-path.cpp @@ -140,7 +140,22 @@ void SPPath::build(SPDocument *document, Inkscape::XML::Node *repr) { SPShape::build(document, repr); - this->readAttr( "inkscape:original-d" ); + //this->readAttr( "inkscape:original-d" ); //lp1299948 + if (gchar const* s = this->getRepr()->attribute("inkscape:original-d")) + { + //write it to XML, and to my curve, but don't update patheffects + Geom::PathVector pv = sp_svg_read_pathv(s); + SPCurve *curve = new SPCurve(pv); + + if (_curve_before_lpe) { + _curve_before_lpe = _curve_before_lpe->unref(); + } + + if (curve) { + _curve_before_lpe = curve->ref(); + } + //this->getRepr()->setAttribute("inkscape:original-d", s); + } this->readAttr( "d" ); /* d is a required attribute */ @@ -314,7 +329,6 @@ g_message("sp_path_update_patheffect"); #ifdef PATH_VERBOSE g_message("sp_path_update_patheffect writes 'd' attribute"); #endif - if (_curve) { gchar *str = sp_svg_write_path(this->_curve->get_pathvector()); repr->setAttribute("d", str); -- cgit v1.2.3 From 4038de8b4763974c97aa8fcb9d87b83c1a5daac7 Mon Sep 17 00:00:00 2001 From: "Liam P. White" Date: Sat, 10 May 2014 15:16:24 -0400 Subject: Add selection sets (bzr r13090.1.75) --- src/Makefile_insert | 3 + src/attributes.cpp | 1 + src/attributes.h | 1 + src/menus-skeleton.h | 1 + src/sp-tag-use-reference.cpp | 156 +++++ src/sp-tag-use-reference.h | 77 +++ src/sp-tag-use.cpp | 205 +++++++ src/sp-tag-use.h | 54 ++ src/sp-tag.cpp | 154 +++++ src/sp-tag.h | 57 ++ src/ui/dialog/Makefile_insert | 2 + src/ui/dialog/dialog-manager.cpp | 6 +- src/ui/dialog/tags.cpp | 1155 ++++++++++++++++++++++++++++++++++++++ src/ui/dialog/tags.h | 181 ++++++ src/verbs.cpp | 86 ++- src/verbs.h | 4 +- 16 files changed, 2134 insertions(+), 9 deletions(-) create mode 100644 src/sp-tag-use-reference.cpp create mode 100644 src/sp-tag-use-reference.h create mode 100644 src/sp-tag-use.cpp create mode 100644 src/sp-tag-use.h create mode 100644 src/sp-tag.cpp create mode 100644 src/sp-tag.h create mode 100644 src/ui/dialog/tags.cpp create mode 100644 src/ui/dialog/tags.h (limited to 'src') diff --git a/src/Makefile_insert b/src/Makefile_insert index 6d0d6b08c..810f706ac 100644 --- a/src/Makefile_insert +++ b/src/Makefile_insert @@ -199,6 +199,9 @@ ink_common_sources += \ sp-style-elem.cpp sp-style-elem.h \ sp-switch.cpp sp-switch.h \ sp-symbol.cpp sp-symbol.h \ + sp-tag.cpp sp-tag.h \ + sp-tag-use.cpp sp-tag-use.h \ + sp-tag-use-reference.cpp sp-tag-use-reference.h \ sp-text.cpp sp-text.h \ sp-textpath.h \ sp-title.cpp sp-title.h \ diff --git a/src/attributes.cpp b/src/attributes.cpp index 4e39b648e..2dc0d8071 100644 --- a/src/attributes.cpp +++ b/src/attributes.cpp @@ -52,6 +52,7 @@ static SPStyleProp const props[] = { {SP_ATTR_XLINK_ACTUATE, "xlink:actuate"}, {SP_ATTR_TARGET, "target"}, {SP_ATTR_INKSCAPE_GROUPMODE, "inkscape:groupmode"}, + {SP_ATTR_INKSCAPE_EXPANDED, "inkscape:expanded"}, /* SPRoot */ {SP_ATTR_VERSION, "version"}, {SP_ATTR_WIDTH, "width"}, diff --git a/src/attributes.h b/src/attributes.h index d1c93b819..270296c9a 100644 --- a/src/attributes.h +++ b/src/attributes.h @@ -52,6 +52,7 @@ enum SPAttributeEnum { SP_ATTR_TARGET, /* SPGroup */ SP_ATTR_INKSCAPE_GROUPMODE, + SP_ATTR_INKSCAPE_EXPANDED, /* SPRoot */ SP_ATTR_VERSION, SP_ATTR_WIDTH, diff --git a/src/menus-skeleton.h b/src/menus-skeleton.h index 67e600edf..18a26d82c 100644 --- a/src/menus-skeleton.h +++ b/src/menus-skeleton.h @@ -179,6 +179,7 @@ static char const menus_skeleton[] = " \n" " \n" " \n" +" \n" " \n" " \n" " \n" diff --git a/src/sp-tag-use-reference.cpp b/src/sp-tag-use-reference.cpp new file mode 100644 index 000000000..50c011812 --- /dev/null +++ b/src/sp-tag-use-reference.cpp @@ -0,0 +1,156 @@ +/* + * The reference corresponding to href of element. + * + * Copyright (C) Theodore Janeczko 2012-2014 + * + * Released under GNU GPL, read the file 'COPYING' for more information. + */ + +#include +#include +#include + +#include "enums.h" +#include "sp-tag-use-reference.h" + +#include "display/curve.h" +#include "livarot/Path.h" +#include "preferences.h" +#include "sp-shape.h" +#include "sp-text.h" +#include "uri.h" + +#if 0 +namespace { + SPObject* createTagUseReference() { + return new SPTag(); + } + bool tagUseReferencesRegistered = SPFactory::instance().registerObject("inkscape:tag", createTag); +} +// this SPObject doesn't need to be registered +#endif + + +bool SPTagUseReference::_acceptObject(SPObject * const obj) const +{ + if (SP_IS_ITEM(obj)) { + SPObject * const owner = getOwner(); + // Refuse references to us or to an ancestor. + for ( SPObject *iter = owner ; iter ; iter = iter->parent ) { + if ( iter == obj ) { + return false; + } + } + return true; + } else { + return false; + } +} + + +static void sp_usepath_href_changed(SPObject *old_ref, SPObject *ref, SPTagUsePath *offset); +static void sp_usepath_delete_self(SPObject *deleted, SPTagUsePath *offset); + +SPTagUsePath::SPTagUsePath(SPObject* i_owner):SPTagUseReference(i_owner) +{ + owner=i_owner; + originalPath = NULL; + sourceDirty=false; + sourceHref = NULL; + sourceRepr = NULL; + sourceObject = NULL; + _changed_connection = changedSignal().connect(sigc::bind(sigc::ptr_fun(sp_usepath_href_changed), this)); // listening to myself, this should be virtual instead + + user_unlink = NULL; +} + +SPTagUsePath::~SPTagUsePath(void) +{ + delete originalPath; + originalPath = NULL; + + _changed_connection.disconnect(); // to do before unlinking + + quit_listening(); + unlink(); +} + +void +SPTagUsePath::link(char *to) +{ + if ( to == NULL ) { + quit_listening(); + unlink(); + } else { + if ( !sourceHref || ( strcmp(to, sourceHref) != 0 ) ) { + g_free(sourceHref); + sourceHref = g_strdup(to); + try { + attach(Inkscape::URI(to)); + } catch (Inkscape::BadURIException &e) { + /* TODO: Proper error handling as per + * http://www.w3.org/TR/SVG11/implnote.html#ErrorProcessing. + */ + g_warning("%s", e.what()); + detach(); + } + } + } +} + +void +SPTagUsePath::unlink(void) +{ + g_free(sourceHref); + sourceHref = NULL; + detach(); +} + +void +SPTagUsePath::start_listening(SPObject* to) +{ + if ( to == NULL ) { + return; + } + sourceObject = to; + sourceRepr = to->getRepr(); + _delete_connection = to->connectDelete(sigc::bind(sigc::ptr_fun(&sp_usepath_delete_self), this)); +} + +void +SPTagUsePath::quit_listening(void) +{ + if ( sourceObject == NULL ) { + return; + } + _delete_connection.disconnect(); + sourceRepr = NULL; + sourceObject = NULL; +} + +static void +sp_usepath_href_changed(SPObject */*old_ref*/, SPObject */*ref*/, SPTagUsePath *offset) +{ + offset->quit_listening(); + SPItem *refobj = offset->getObject(); + if ( refobj ) { + offset->start_listening(refobj); + } +} + +static void +sp_usepath_delete_self(SPObject */*deleted*/, SPTagUsePath *offset) +{ + offset->owner->deleteObject(); +} + +/* + 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 : diff --git a/src/sp-tag-use-reference.h b/src/sp-tag-use-reference.h new file mode 100644 index 000000000..b38e45837 --- /dev/null +++ b/src/sp-tag-use-reference.h @@ -0,0 +1,77 @@ +#ifndef SEEN_SP_TAG_USE_REFERENCE_H +#define SEEN_SP_TAG_USE_REFERENCE_H + +/* + * The reference corresponding to href of element. + * + * Copyright (C) Theodore Janeczko 2012-2014 + * + * Released under GNU GPL, read the file 'COPYING' for more information. + */ + +#include "sp-object.h" +#include "sp-item.h" +#include +#include +#include + +class Path; + +namespace Inkscape { +namespace XML { + struct Node; +} +} + + +class SPTagUseReference : public Inkscape::URIReference { +public: + SPTagUseReference(SPObject *owner) : URIReference(owner) {} + + SPItem *getObject() const { + return static_cast(URIReference::getObject()); + } + +protected: + virtual bool _acceptObject(SPObject * const obj) const; + +}; + + +class SPTagUsePath : public SPTagUseReference { +public: + Path *originalPath; + bool sourceDirty; + + SPObject *owner; + gchar *sourceHref; + Inkscape::XML::Node *sourceRepr; + SPObject *sourceObject; + + sigc::connection _delete_connection; + sigc::connection _changed_connection; + + SPTagUsePath(SPObject* i_owner); + ~SPTagUsePath(void); + + void link(char* to); + void unlink(void); + void start_listening(SPObject* to); + void quit_listening(void); + void refresh_source(void); + + void (*user_unlink) (SPObject *user); +}; + +#endif /* !SEEN_SP_USE_REFERENCE_H */ + +/* + 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 : diff --git a/src/sp-tag-use.cpp b/src/sp-tag-use.cpp new file mode 100644 index 000000000..ffcfcee3e --- /dev/null +++ b/src/sp-tag-use.cpp @@ -0,0 +1,205 @@ +/* + * SVG implementation + * + * Authors: + * Theodore Janeczko + * Liam P White + * + * Copyright (C) Theodore Janeczko 2012-2014 + * + * Released under GNU GPL, read the file 'COPYING' for more information + */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include +#include + +#include +#include "display/drawing-group.h" +#include "attributes.h" +#include "document.h" +#include "uri.h" +#include "xml/repr.h" +#include "preferences.h" +#include "style.h" +#include "sp-factory.h" +#include "sp-symbol.h" +#include "sp-tag-use.h" +#include "sp-tag-use-reference.h" + +namespace { + SPObject* createTagUse() { + return new SPTagUse(); + } + bool tagUseRegistered = SPFactory::instance().registerObject("inkscape:tagref", createTagUse); +} + +SPTagUse::SPTagUse() +{ + href = NULL; + //new (_changed_connection) sigc::connection; + ref = new SPTagUseReference(this); + + _changed_connection = ref->changedSignal().connect(sigc::mem_fun(*this, &SPTagUse::href_changed)); +} + +SPTagUse::~SPTagUse() +{ + + if (child) { + detach(child); + child = NULL; + } + + ref->detach(); + delete ref; + ref = 0; + + _changed_connection.~connection(); //FIXME why? +} + +void +SPTagUse::build(SPDocument *document, Inkscape::XML::Node *repr) +{ + SPObject::build(document, repr); + readAttr( "xlink:href" ); + + // We don't need to create child here: + // reading xlink:href will attach ref, and that will cause the changed signal to be emitted, + // which will call sp_tag_use_href_changed, and that will take care of the child +} + +void +SPTagUse::release() +{ + + if (child) { + detach(child); + child = NULL; + } + + _changed_connection.disconnect(); + + g_free(href); + href = NULL; + + ref->detach(); + + SPObject::release(); +} + +void +SPTagUse::set(unsigned key, gchar const *value) +{ + + switch (key) { + case SP_ATTR_XLINK_HREF: { + if ( value && href && ( strcmp(value, href) == 0 ) ) { + /* No change, do nothing. */ + } else { + g_free(href); + href = NULL; + if (value) { + // First, set the href field, because sp_tag_use_href_changed will need it. + href = g_strdup(value); + + // Now do the attaching, which emits the changed signal. + try { + ref->attach(Inkscape::URI(value)); + } catch (Inkscape::BadURIException &e) { + g_warning("%s", e.what()); + ref->detach(); + } + } else { + ref->detach(); + } + } + break; + } + + default: + SPObject::set(key, value); + break; + } +} + +Inkscape::XML::Node * +SPTagUse::write(Inkscape::XML::Document *xml_doc, Inkscape::XML::Node *repr, guint flags) +{ + if ((flags & SP_OBJECT_WRITE_BUILD) && !repr) { + repr = xml_doc->createElement("inkscape:tagref"); + } + + SPObject::write(xml_doc, repr, flags); + + if (ref->getURI()) { + gchar *uri_string = ref->getURI()->toString(); + repr->setAttribute("xlink:href", uri_string); + g_free(uri_string); + } + + return repr; +} + +/** + * Returns the ultimate original of a SPTagUse (i.e. the first object in the chain of its originals + * which is not an SPTagUse). If no original is found, NULL is returned (it is the responsibility + * of the caller to make sure that this is handled correctly). + * + * Note that the returned is the clone object, i.e. the child of an SPTagUse (of the argument one for + * the trivial case) and not the "true original". + */ + +SPItem * SPTagUse::root() +{ + SPObject *orig = child; + while (orig && SP_IS_TAG_USE(orig)) { + orig = SP_TAG_USE(orig)->child; + } + if (!orig || !SP_IS_ITEM(orig)) + return NULL; + return SP_ITEM(orig); +} + +void +SPTagUse::href_changed(SPObject */*old_ref*/, SPObject */*ref*/) +{ + if (href) { + SPItem *refobj = ref->getObject(); + if (refobj) { + Inkscape::XML::Node *childrepr = refobj->getRepr(); + const std::string typeString = NodeTraits::get_type_string(*childrepr); + + SPObject* child_ = SPFactory::instance().createObject(typeString); + if (child_) { + attach(child_, lastChild()); + sp_object_unref(child_, 0); + child_->invoke_build(this->document, childrepr, TRUE); + + } + } + } +} + +SPItem * SPTagUse::get_original() +{ + SPItem *ref_ = NULL; + if (ref) { + ref_ = ref->getObject(); + } + return ref_; +} + +/* + 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 : diff --git a/src/sp-tag-use.h b/src/sp-tag-use.h new file mode 100644 index 000000000..8a0c3e7fb --- /dev/null +++ b/src/sp-tag-use.h @@ -0,0 +1,54 @@ +#ifndef __SP_TAG_USE_H__ +#define __SP_TAG_USE_H__ + +/* + * SVG implementation + * + * Authors: + * Theodore Janeczko + * + * Copyright (C) Theodore Janeczko 2012 + * + * Released under GNU GPL, read the file 'COPYING' for more information + */ + +#include +#include +#include "svg/svg-length.h" +#include "sp-object.h" + + +#define SP_TAG_USE(obj) (dynamic_cast (obj)) +#define SP_IS_TAG_USE(obj) (dynamic_cast (obj) != NULL) + +class SPTagUse; +class SPTagUseReference; + +class SPTagUse : public SPObject { + +public: + // item built from the original's repr (the visible clone) + // relative to the SPUse itself, it is treated as a child, similar to a grouped item relative to its group + SPObject *child; + gchar *href; +public: + SPTagUse(); + virtual ~SPTagUse(); + + virtual void build(SPDocument *doc, Inkscape::XML::Node *repr); + virtual void set(unsigned key, gchar const *value); + virtual Inkscape::XML::Node* write(Inkscape::XML::Document* doc, Inkscape::XML::Node* repr, guint flags); + virtual void release(); + + virtual void href_changed(SPObject* old_ref, SPObject* ref); + + //virtual SPItem* unlink(); + virtual SPItem* get_original(); + virtual SPItem* root(); + + // the reference to the original object + SPTagUseReference *ref; + sigc::connection _changed_connection; +}; + +#endif diff --git a/src/sp-tag.cpp b/src/sp-tag.cpp new file mode 100644 index 000000000..c4b40417f --- /dev/null +++ b/src/sp-tag.cpp @@ -0,0 +1,154 @@ +/** \file + * SVG implementation + * + * Authors: + * Theodore Janeczko + * Liam P. White + * + * Copyright (C) Theodore Janeczko 2012-2014 + * + * Released under GNU GPL, read the file 'COPYING' for more information + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include "attributes.h" +#include "sp-factory.h" +#include "sp-tag.h" +#include "xml/repr.h" +#include + +namespace { + SPObject* createTag() { + return new SPTag(); + } + bool tagsRegistered = SPFactory::instance().registerObject("inkscape:tag", createTag); +} + +/* + * Move this SPItem into or after another SPItem in the doc + * \param target - the SPItem to move into or after + * \param intoafter - move to after the target (false), move inside (sublayer) of the target (true) + */ +void SPTag::moveTo(SPObject *target, gboolean intoafter) { + + Inkscape::XML::Node *target_ref = ( target ? target->getRepr() : NULL ); + Inkscape::XML::Node *our_ref = getRepr(); + gboolean first = FALSE; + + if (target_ref == our_ref) { + // Move to ourself ignore + return; + } + + if (!target_ref) { + // Assume move to the "first" in the top node, find the top node + target_ref = our_ref; + while (target_ref->parent() != target_ref->root()) { + target_ref = target_ref->parent(); + } + first = TRUE; + } + + if (intoafter) { + // Move this inside of the target at the end + our_ref->parent()->removeChild(our_ref); + target_ref->addChild(our_ref, NULL); + } else if (target_ref->parent() != our_ref->parent()) { + // Change in parent, need to remove and add + our_ref->parent()->removeChild(our_ref); + target_ref->parent()->addChild(our_ref, target_ref); + } else if (!first) { + // Same parent, just move + our_ref->parent()->changeOrder(our_ref, target_ref); + } +} + +/** + * Reads the Inkscape::XML::Node, and initializes SPTag variables. For this to get called, + * our name must be associated with a repr via "sp_object_type_register". Best done through + * sp-object-repr.cpp's repr_name_entries array. + */ +void +SPTag::build(SPDocument *document, Inkscape::XML::Node *repr) +{ + readAttr( "inkscape:expanded" ); + SPObject::build(document, repr); +} + +/** + * Sets a specific value in the SPTag. + */ +void +SPTag::set(unsigned int key, gchar const *value) +{ + + switch (key) + { + case SP_ATTR_INKSCAPE_EXPANDED: + if ( value && !strcmp(value, "true") ) { + setExpanded(true); + } + break; + default: + SPObject::set(key, value); + break; + } +} + +void SPTag::setExpanded(bool isexpanded) { + //if ( _expanded != isexpanded ){ + _expanded = isexpanded; + //} +} + +/** + * Receives update notifications. + */ +void +SPTag::update(SPCtx *ctx, guint flags) +{ + if (flags & (SP_OBJECT_MODIFIED_FLAG | SP_OBJECT_STYLE_MODIFIED_FLAG | + SP_OBJECT_VIEWPORT_MODIFIED_FLAG)) { + + /* do something to trigger redisplay, updates? */ + + } + SPObject::update(ctx, flags); +} + +/** + * Writes its settings to an incoming repr object, if any. + */ +Inkscape::XML::Node * +SPTag::write(Inkscape::XML::Document *doc, Inkscape::XML::Node *repr, guint flags) +{ + if ((flags & SP_OBJECT_WRITE_BUILD) && !repr) { + repr = doc->createElement("inkscape:tag"); + } + + // Inkscape-only object, not copied during an "plain SVG" dump: + if (flags & SP_OBJECT_WRITE_EXT) { + if (_expanded) { + repr->setAttribute("inkscape:expanded", "true"); + } else { + repr->setAttribute("inkscape:expanded", NULL); + } + } + SPObject::write(doc, repr, flags); + return repr; +} + + +/* + 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 : diff --git a/src/sp-tag.h b/src/sp-tag.h new file mode 100644 index 000000000..927bb45d1 --- /dev/null +++ b/src/sp-tag.h @@ -0,0 +1,57 @@ +#ifndef SP_TAG_H_SEEN +#define SP_TAG_H_SEEN + +/** \file + * SVG implementation + * + * Authors: + * Theodore Janeczko + * + * Copyright (C) Theodore Janeczko 2012 + * + * Released under GNU GPL, read the file 'COPYING' for more information + */ + +#include "sp-object.h" + +/* Skeleton base class */ + +#define SP_TAG(o) (dynamic_cast(o)) +#define SP_IS_TAG(o) (dynamic_cast(o) != NULL) + +class SPTag; + +class SPTag : public SPObject { +public: + SPTag() {} + virtual ~SPTag() {} + + virtual void build(SPDocument * doc, Inkscape::XML::Node *repr); + //virtual void release(); + virtual void set(unsigned key, const gchar* value); + virtual void update(SPCtx * ctx, unsigned flags); + + virtual Inkscape::XML::Node* write(Inkscape::XML::Document* doc, Inkscape::XML::Node* repr, guint flags); + + bool expanded() const { return _expanded; } + void setExpanded(bool isexpanded); + + void moveTo(SPObject *target, gboolean intoafter); + +private: + bool _expanded; +}; + + +#endif /* !SP_SKELETON_H_SEEN */ + +/* + 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 : diff --git a/src/ui/dialog/Makefile_insert b/src/ui/dialog/Makefile_insert index 8a7a4a5dd..1aa73dc5b 100644 --- a/src/ui/dialog/Makefile_insert +++ b/src/ui/dialog/Makefile_insert @@ -100,6 +100,8 @@ ink_common_sources += \ ui/dialog/template-load-tab.h \ ui/dialog/template-widget.cpp \ ui/dialog/template-widget.h \ + ui/dialog/tags.cpp \ + ui/dialpg/tags.h \ ui/dialog/text-edit.cpp \ ui/dialog/text-edit.h \ ui/dialog/tile.cpp \ diff --git a/src/ui/dialog/dialog-manager.cpp b/src/ui/dialog/dialog-manager.cpp index 22c41d75e..bd2f1eb12 100644 --- a/src/ui/dialog/dialog-manager.cpp +++ b/src/ui/dialog/dialog-manager.cpp @@ -55,7 +55,7 @@ #include "ui/dialog/clonetiler.h" #include "ui/dialog/svg-fonts-dialog.h" #include "ui/dialog/objects.h" -//#include "ui/dialog/tags.h" +#include "ui/dialog/tags.h" namespace Inkscape { namespace UI { @@ -113,7 +113,7 @@ DialogManager::DialogManager() { registerFactory("IconPreviewPanel", &create); registerFactory("LayersPanel", &create); registerFactory("ObjectsPanel", &create); -// registerFactory("TagsPanel", &create); + registerFactory("TagsPanel", &create); registerFactory("LivePathEffect", &create); registerFactory("Memory", &create); registerFactory("Messages", &create); @@ -148,7 +148,7 @@ DialogManager::DialogManager() { registerFactory("IconPreviewPanel", &create); registerFactory("LayersPanel", &create); registerFactory("ObjectsPanel", &create); -// registerFactory("TagsPanel", &create); + registerFactory("TagsPanel", &create); registerFactory("LivePathEffect", &create); registerFactory("Memory", &create); registerFactory("Messages", &create); diff --git a/src/ui/dialog/tags.cpp b/src/ui/dialog/tags.cpp new file mode 100644 index 000000000..7fdd2e906 --- /dev/null +++ b/src/ui/dialog/tags.cpp @@ -0,0 +1,1155 @@ +/* + * A simple panel for tags + * + * Authors: + * Theodore Janeczko + * + * Copyright (C) Theodore Janeczko 2012 + * + * Released under GNU GPL, read the file 'COPYING' for more information + */ +#ifdef HAVE_CONFIG_H +# include +#endif + +#include "tags.h" +#include +#include +#include +#include + +#include + +#include "desktop.h" +#include "desktop-style.h" +#include "document.h" +#include "document-undo.h" +#include "helper/action.h" +#include "inkscape.h" +#include "layer-fns.h" +#include "layer-manager.h" +#include "preferences.h" +#include "sp-item.h" +#include "sp-object.h" +#include "sp-shape.h" +#include "svg/css-ostringstream.h" +#include "ui/icon-names.h" +#include "ui/widget/layertypeicon.h" +#include "ui/widget/addtoicon.h" +#include "verbs.h" +#include "widgets/icon.h" +#include "xml/node.h" +#include "xml/node-observer.h" +#include "xml/repr.h" +#include "sp-root.h" +#include "ui/tools/tool-base.h" //"event-context.h" +#include "selection.h" +#include "dialogs/dialog-events.h" +#include "widgets/sp-color-notebook.h" +#include "style.h" +#include "filter-chemistry.h" +#include "filters/blend.h" +#include "filters/gaussian-blur.h" +#include "sp-clippath.h" +#include "sp-mask.h" +#include "sp-tag.h" +#include "sp-defs.h" +#include "sp-tag-use.h" +#include "sp-tag-use-reference.h" + +//#define DUMP_LAYERS 1 + +namespace Inkscape { +namespace UI { +namespace Dialog { + +using Inkscape::XML::Node; + +TagsPanel& TagsPanel::getInstance() +{ + return *new TagsPanel(); +} + +enum { + COL_ADD = 1 +}; + +enum { + BUTTON_NEW = 0, + BUTTON_TOP, + BUTTON_BOTTOM, + BUTTON_UP, + BUTTON_DOWN, + BUTTON_DELETE, + DRAGNDROP +}; + +class TagsPanel::ObjectWatcher : public Inkscape::XML::NodeObserver { +public: + ObjectWatcher(TagsPanel* pnl, SPObject* obj, Inkscape::XML::Node * repr) : + _pnl(pnl), + _obj(obj), + _repr(repr), + _labelAttr(g_quark_from_string("inkscape:label")) + {} + + ObjectWatcher(TagsPanel* pnl, SPObject* obj) : + _pnl(pnl), + _obj(obj), + _repr(obj->getRepr()), + _labelAttr(g_quark_from_string("inkscape:label")) + {} + + virtual void notifyChildAdded( Node &/*node*/, Node &/*child*/, Node */*prev*/ ) + { + if ( _pnl && _obj ) { + _pnl->_objectsChanged( _obj ); + } + } + virtual void notifyChildRemoved( Node &/*node*/, Node &/*child*/, Node */*prev*/ ) + { + if ( _pnl && _obj ) { + _pnl->_objectsChanged( _obj ); + } + } + virtual void notifyChildOrderChanged( Node &/*node*/, Node &/*child*/, Node */*old_prev*/, Node */*new_prev*/ ) + { + if ( _pnl && _obj ) { + _pnl->_objectsChanged( _obj ); + } + } + virtual void notifyContentChanged( Node &/*node*/, Util::ptr_shared /*old_content*/, Util::ptr_shared /*new_content*/ ) {} + virtual void notifyAttributeChanged( Node &/*node*/, GQuark name, Util::ptr_shared /*old_value*/, Util::ptr_shared /*new_value*/ ) { + if ( _pnl && _obj ) { + if ( name == _labelAttr ) { + _pnl->_updateObject( _obj); + } + } + } + + TagsPanel* _pnl; + SPObject* _obj; + Inkscape::XML::Node* _repr; + GQuark _labelAttr; +}; + +class TagsPanel::InternalUIBounce +{ +public: + int _actionCode; +}; + +void TagsPanel::_styleButton( Gtk::Button& btn, SPDesktop *desktop, unsigned int code, char const* iconName, char const* tooltip ) +{ + bool set = false; + + if ( iconName ) { + GtkWidget *child = sp_icon_new( Inkscape::ICON_SIZE_SMALL_TOOLBAR, iconName ); + gtk_widget_show( child ); + btn.add( *manage(Glib::wrap(child)) ); + btn.set_relief(Gtk::RELIEF_NONE); + set = true; + } + + if ( desktop ) { + Verb *verb = Verb::get( code ); + if ( verb ) { + SPAction *action = verb->get_action(desktop); + if ( !set && action && action->image ) { + GtkWidget *child = sp_icon_new( Inkscape::ICON_SIZE_SMALL_TOOLBAR, action->image ); + gtk_widget_show( child ); + btn.add( *manage(Glib::wrap(child)) ); + set = true; + } + } + } + + btn.set_tooltip_text (tooltip); +} + + +Gtk::MenuItem& TagsPanel::_addPopupItem( SPDesktop *desktop, unsigned int code, char const* iconName, char const* fallback, int id ) +{ + GtkWidget* iconWidget = 0; + const char* label = 0; + + if ( iconName ) { + iconWidget = sp_icon_new( Inkscape::ICON_SIZE_MENU, iconName ); + } + + if ( desktop ) { + Verb *verb = Verb::get( code ); + if ( verb ) { + SPAction *action = verb->get_action(desktop); + if ( !iconWidget && action && action->image ) { + iconWidget = sp_icon_new( Inkscape::ICON_SIZE_MENU, action->image ); + } + + if ( action ) { + label = action->name; + } + } + } + + if ( !label && fallback ) { + label = fallback; + } + + Gtk::Widget* wrapped = 0; + if ( iconWidget ) { + wrapped = manage(Glib::wrap(iconWidget)); + wrapped->show(); + } + + + Gtk::MenuItem* item = 0; + + if (wrapped) { + item = Gtk::manage(new Gtk::ImageMenuItem(*wrapped, label, true)); + } else { + item = Gtk::manage(new Gtk::MenuItem(label, true)); + } + + item->signal_activate().connect(sigc::bind(sigc::mem_fun(*this, &TagsPanel::_takeAction), id)); + _popupMenu.append(*item); + + return *item; +} + +void TagsPanel::_fireAction( unsigned int code ) +{ + if ( _desktop ) { + Verb *verb = Verb::get( code ); + if ( verb ) { + SPAction *action = verb->get_action(_desktop); + if ( action ) { + sp_action_perform( action, NULL ); + } + } + } +} + +void TagsPanel::_takeAction( int val ) +{ + if ( !_pending ) { + _pending = new InternalUIBounce(); + _pending->_actionCode = val; + Glib::signal_timeout().connect( sigc::mem_fun(*this, &TagsPanel::_executeAction), 0 ); + } +} + +bool TagsPanel::_executeAction() +{ + // Make sure selected layer hasn't changed since the action was triggered + if ( _pending) + { + int val = _pending->_actionCode; +// SPObject* target = _pending->_target; + bool empty = _desktop->selection->isEmpty(); + + switch ( val ) { + case BUTTON_NEW: + { + _fireAction( SP_VERB_TAG_NEW ); + } + break; + case BUTTON_TOP: + { + _fireAction( empty ? SP_VERB_LAYER_TO_TOP : SP_VERB_SELECTION_TO_FRONT); + } + break; + case BUTTON_BOTTOM: + { + _fireAction( empty ? SP_VERB_LAYER_TO_BOTTOM : SP_VERB_SELECTION_TO_BACK ); + } + break; + case BUTTON_UP: + { + _fireAction( empty ? SP_VERB_LAYER_RAISE : SP_VERB_SELECTION_RAISE ); + } + break; + case BUTTON_DOWN: + { + _fireAction( empty ? SP_VERB_LAYER_LOWER : SP_VERB_SELECTION_LOWER ); + } + break; + case BUTTON_DELETE: + { + std::vector todelete; + _tree.get_selection()->selected_foreach_iter(sigc::bind*>(sigc::mem_fun(*this, &TagsPanel::_checkForDeleted), &todelete)); + for (std::vector::iterator iter = todelete.begin(); iter != todelete.end(); ++iter) { + SPObject * obj = *iter; + if (obj && obj->parent && obj->getRepr() && obj->parent->getRepr()) { + obj->parent->getRepr()->removeChild(obj->getRepr()); + } + } + DocumentUndo::done(_document, SP_VERB_DIALOG_TAGS, _("Remove from selection set")); + } + break; + case DRAGNDROP: + { + _doTreeMove( ); + } + break; + } + + delete _pending; + _pending = 0; + } + + return false; +} + + +class TagsPanel::ModelColumns : public Gtk::TreeModel::ColumnRecord +{ +public: + + ModelColumns() + { + add(_colParentObject); + add(_colObject); + add(_colLabel); + add(_colAddRemove); + add(_colAllowAddRemove); + } + virtual ~ModelColumns() {} + + Gtk::TreeModelColumn _colParentObject; + Gtk::TreeModelColumn _colObject; + Gtk::TreeModelColumn _colLabel; + Gtk::TreeModelColumn _colAddRemove; + Gtk::TreeModelColumn _colAllowAddRemove; +}; + +void TagsPanel::_checkForDeleted(const Gtk::TreeIter& iter, std::vector* todelete) +{ + Gtk::TreeRow row = *iter; + SPObject * obj = row[_model->_colObject]; + if (obj && obj->parent) { + todelete->push_back(obj); + } +} + +void TagsPanel::_updateObject( SPObject *obj ) { + _store->foreach( sigc::bind(sigc::mem_fun(*this, &TagsPanel::_checkForUpdated), obj) ); +} + +bool TagsPanel::_checkForUpdated(const Gtk::TreePath &/*path*/, const Gtk::TreeIter& iter, SPObject* obj) +{ + Gtk::TreeModel::Row row = *iter; + if ( obj == row[_model->_colObject] ) + { + /* + * We get notified of layer update here (from layer->setLabel()) before layer->label() is set + * with the correct value (sp-object bug?). So use the inkscape:label attribute instead which + * has the correct value (bug #168351) + */ + //row[_model->_colLabel] = layer->label() ? layer->label() : layer->getId(); + gchar const *label; + SPTagUse * use = SP_IS_TAG_USE(obj) ? SP_TAG_USE(obj) : 0; + if (use && use->ref->isAttached()) { + label = use->ref->getObject()->getAttribute("inkscape:label"); + } else { + label = obj->getAttribute("inkscape:label"); + } + row[_model->_colLabel] = label ? label : obj->getId(); + row[_model->_colAddRemove] = SP_IS_TAG(obj); + } + + return false; +} + +void TagsPanel::_objectsSelected( Selection *sel ) { + + _selectedConnection.block(); + _tree.get_selection()->unselect_all(); + for (const GSList * iter = sel->list(); iter != NULL; iter = iter->next) + { + SPObject *obj = reinterpret_cast(iter->data); + _store->foreach(sigc::bind( sigc::mem_fun(*this, &TagsPanel::_checkForSelected), obj)); + } + _selectedConnection.unblock(); + _checkTreeSelection(); +} + +bool TagsPanel::_checkForSelected(const Gtk::TreePath &path, const Gtk::TreeIter& iter, SPObject* obj) +{ + Gtk::TreeModel::Row row = *iter; + SPObject * it = row[_model->_colObject]; + if ( it && SP_IS_TAG_USE(it) && SP_TAG_USE(it)->ref->getObject() == obj ) + { + Glib::RefPtr select = _tree.get_selection(); + + select->select(iter); + } + return false; +} + +void TagsPanel::_objectsChanged(SPObject* root) +{ + while (!_objectWatchers.empty()) + { + TagsPanel::ObjectWatcher *w = _objectWatchers.back(); + w->_repr->removeObserver(*w); + _objectWatchers.pop_back(); + delete w; + } + + if (_desktop) { + SPDocument* document = _desktop->doc(); + SPDefs* root = document->getDefs(); + if ( root ) { + _selectedConnection.block(); + _store->clear(); + _addObject( document, root, 0 ); + _selectedConnection.unblock(); + _objectsSelected(_desktop->selection); + _checkTreeSelection(); + } + } +} + +void TagsPanel::_addObject( SPDocument* doc, SPObject* obj, Gtk::TreeModel::Row* parentRow ) +{ + if ( _desktop && obj ) { + for ( SPObject *child = obj->children; child != NULL; child = child->next) { + if (SP_IS_TAG(child)) + { + Gtk::TreeModel::iterator iter = parentRow ? _store->prepend(parentRow->children()) : _store->prepend(); + Gtk::TreeModel::Row row = *iter; + row[_model->_colObject] = child; + row[_model->_colParentObject] = NULL; + row[_model->_colLabel] = child->label() ? child->label() : child->getId(); + row[_model->_colAddRemove] = true; + row[_model->_colAllowAddRemove] = true; + + _tree.expand_to_path( _store->get_path(iter) ); + + TagsPanel::ObjectWatcher *w = new TagsPanel::ObjectWatcher(this, child); + child->getRepr()->addObserver(*w); + _objectWatchers.push_back(w); + _addObject( doc, child, &row ); + } + } + if (SP_IS_TAG(obj) && obj->children) + { + Gtk::TreeModel::iterator iteritems = parentRow ? _store->append(parentRow->children()) : _store->prepend(); + Gtk::TreeModel::Row rowitems = *iteritems; + rowitems[_model->_colObject] = NULL; + rowitems[_model->_colParentObject] = obj; + rowitems[_model->_colLabel] = _("Items"); + rowitems[_model->_colAddRemove] = false; + rowitems[_model->_colAllowAddRemove] = false; + + _tree.expand_to_path( _store->get_path(iteritems) ); + + for ( SPObject *child = obj->children; child != NULL; child = child->next) { + if (SP_IS_TAG_USE(child)) + { + SPItem *item = SP_TAG_USE(child)->ref->getObject(); + Gtk::TreeModel::iterator iter = _store->prepend(rowitems->children()); + Gtk::TreeModel::Row row = *iter; + row[_model->_colObject] = child; + row[_model->_colParentObject] = NULL; + row[_model->_colLabel] = item ? (item->label() ? item->label() : item->getId()) : SP_TAG_USE(child)->href; + row[_model->_colAddRemove] = false; + row[_model->_colAllowAddRemove] = true; + + if (SP_TAG(obj)->expanded()) { + _tree.expand_to_path( _store->get_path(iter) ); + } + + if (item) { + TagsPanel::ObjectWatcher *w = new TagsPanel::ObjectWatcher(this, child, item->getRepr()); + item->getRepr()->addObserver(*w); + _objectWatchers.push_back(w); + } + } + } + } + } +} + +void TagsPanel::_select_tag( SPTag * tag ) +{ + for (SPObject * child = tag->children; child != NULL; child = child->next) + { + if (SP_IS_TAG(child)) { + _select_tag(SP_TAG(child)); + } else if (SP_IS_TAG_USE(child)) { + SPObject * obj = SP_TAG_USE(child)->ref->getObject(); + if (obj) { + if (_desktop->selection->isEmpty()) _desktop->setCurrentLayer(obj->parent); + _desktop->selection->add(obj); + } + } + } +} + +void TagsPanel::_selected_row_callback( const Gtk::TreeModel::iterator& iter ) +{ + if (iter) { + Gtk::TreeModel::Row row = *iter; + SPObject *obj = row[_model->_colObject]; + if (obj) { + if (SP_IS_TAG(obj)) { + _select_tag(SP_TAG(obj)); + } else if (SP_IS_TAG_USE(obj)) { + SPObject * item = SP_TAG_USE(obj)->ref->getObject(); + if (item) { + if (_desktop->selection->isEmpty()) _desktop->setCurrentLayer(item->parent); + _desktop->selection->add(item); + } + } + } + } +} + +void TagsPanel::_pushTreeSelectionToCurrent() +{ + _selectionChangedConnection.block(); + // TODO hunt down the possible API abuse in getting NULL + if ( _desktop && _desktop->currentRoot() ) { + _desktop->selection->clear(); + _tree.get_selection()->selected_foreach_iter( sigc::mem_fun(*this, &TagsPanel::_selected_row_callback)); + } + _selectionChangedConnection.unblock(); + + _checkTreeSelection(); +} + +void TagsPanel::_checkTreeSelection() +{ + bool sensitive = _tree.get_selection()->count_selected_rows() > 0; + bool sensitiveNonTop = true; + bool sensitiveNonBottom = true; +// if ( _tree.get_selection()->count_selected_rows() > 0 ) { +// sensitive = true; +// +// SPObject* inTree = _selectedLayer(); +// if ( inTree ) { +// +// sensitiveNonTop = (Inkscape::Nex(inTree->parent, inTree) != 0); +// sensitiveNonBottom = (Inkscape::previous_layer(inTree->parent, inTree) != 0); +// +// } +// } + + + for ( std::vector::iterator it = _watching.begin(); it != _watching.end(); ++it ) { + (*it)->set_sensitive( sensitive ); + } + for ( std::vector::iterator it = _watchingNonTop.begin(); it != _watchingNonTop.end(); ++it ) { + (*it)->set_sensitive( sensitiveNonTop ); + } + for ( std::vector::iterator it = _watchingNonBottom.begin(); it != _watchingNonBottom.end(); ++it ) { + (*it)->set_sensitive( sensitiveNonBottom ); + } +} + +bool TagsPanel::_handleKeyEvent(GdkEventKey *event) +{ + + switch (Inkscape::UI::Tools::get_group0_keyval(event)) { + case GDK_KEY_Return: + case GDK_KEY_KP_Enter: + case GDK_KEY_F2: { + Gtk::TreeModel::iterator iter = _tree.get_selection()->get_selected(); + if (iter && !_text_renderer->property_editable()) { + Gtk::TreeRow row = *iter; + SPObject * obj = row[_model->_colObject]; + if (obj && SP_IS_TAG(obj)) { + Gtk::TreeModel::Path *path = new Gtk::TreeModel::Path(iter); + // Edit the layer label + _text_renderer->property_editable() = true; + _tree.set_cursor(*path, *_name_column, true); + grab_focus(); + return true; + } + } + } + case GDK_KEY_Delete: { + std::vector todelete; + _tree.get_selection()->selected_foreach_iter(sigc::bind*>(sigc::mem_fun(*this, &TagsPanel::_checkForDeleted), &todelete)); + if (!todelete.empty()) { + for (std::vector::iterator iter = todelete.begin(); iter != todelete.end(); ++iter) { + SPObject * obj = *iter; + if (obj && obj->parent && obj->getRepr() && obj->parent->getRepr()) { + obj->parent->getRepr()->removeChild(obj->getRepr()); + } + } + DocumentUndo::done(_document, SP_VERB_DIALOG_TAGS, _("Remove from selection set")); + } + return true; + } + break; + } + return false; +} + +bool TagsPanel::_handleButtonEvent(GdkEventButton* event) +{ + static unsigned doubleclick = 0; + + if ( (event->type == GDK_BUTTON_PRESS) && (event->button == 3) ) { + // TODO - fix to a better is-popup function + Gtk::TreeModel::Path path; + int x = static_cast(event->x); + int y = static_cast(event->y); + if ( _tree.get_path_at_pos( x, y, path ) ) { + _checkTreeSelection(); + _popupMenu.popup(event->button, event->time); + if (_tree.get_selection()->is_selected(path)) { + return true; + } + } + } + + if ( (event->type == GDK_BUTTON_PRESS) && (event->button == 1)) { + // Alt left click on the visible/lock columns - eat this event to keep row selection + Gtk::TreeModel::Path path; + Gtk::TreeViewColumn* col = 0; + int x = static_cast(event->x); + int y = static_cast(event->y); + int x2 = 0; + int y2 = 0; + if ( _tree.get_path_at_pos( x, y, path, col, x2, y2 ) ) { + if (col == _tree.get_column(COL_ADD-1)) { + down_at_add = true; + return true; + } else if ( !(event->state & (GDK_SHIFT_MASK | GDK_CONTROL_MASK)) & _tree.get_selection()->is_selected(path) ) { + _tree.get_selection()->set_select_function(sigc::mem_fun(*this, &TagsPanel::_noSelection)); + _defer_target = path; + } else { + down_at_add = false; + } + } else { + down_at_add = false; + } + } + + if ( event->type == GDK_BUTTON_RELEASE) { + _tree.get_selection()->set_select_function(sigc::mem_fun(*this, &TagsPanel::_rowSelectFunction)); + } + + // TODO - ImageToggler doesn't seem to handle Shift/Alt clicks - so we deal with them here. + if ( (event->type == GDK_BUTTON_RELEASE) && (event->button == 1)) { + + Gtk::TreeModel::Path path; + Gtk::TreeViewColumn* col = 0; + int x = static_cast(event->x); + int y = static_cast(event->y); + int x2 = 0; + int y2 = 0; + if ( _tree.get_path_at_pos( x, y, path, col, x2, y2 ) ) { + if (_defer_target) { + if (_defer_target == path && !(event->x == 0 && event->y == 0)) + { + _tree.set_cursor(path, *col, false); + } + _defer_target = Gtk::TreeModel::Path(); + } else { + Gtk::TreeModel::Children::iterator iter = _tree.get_model()->get_iter(path); + Gtk::TreeModel::Row row = *iter; + + SPObject* obj = row[_model->_colObject]; + + if (obj) { + if (col == _tree.get_column(COL_ADD - 1) && down_at_add) { + if (SP_IS_TAG(obj)) { + bool wasadded = false; + for (const GSList * iter = _desktop->selection->itemList(); iter != NULL; iter = iter->next) + { + SPObject *newobj = reinterpret_cast(iter->data); + bool addchild = true; + for ( SPObject *child = obj->children; child != NULL; child = child->next) { + if (SP_IS_TAG_USE(child) && SP_TAG_USE(child)->ref->getObject() == newobj) { + addchild = false; + } + } + if (addchild) { + Inkscape::XML::Node *clone = _document->getReprDoc()->createElement("inkscape:tagref"); + clone->setAttribute("xlink:href", g_strdup_printf("#%s", newobj->getRepr()->attribute("id")), false); + obj->appendChild(clone); + wasadded = true; + } + } + if (wasadded) { + DocumentUndo::done(_document, SP_VERB_DIALOG_TAGS, _("Add selection to set")); + } + } else { + std::vector todelete; + _tree.get_selection()->selected_foreach_iter(sigc::bind*>(sigc::mem_fun(*this, &TagsPanel::_checkForDeleted), &todelete)); + if (!todelete.empty()) { + for (std::vector::iterator iter = todelete.begin(); iter != todelete.end(); ++iter) { + SPObject * tobj = *iter; + if (tobj && tobj->parent && tobj->getRepr() && tobj->parent->getRepr()) { + tobj->parent->getRepr()->removeChild(tobj->getRepr()); + } + } + } else if (obj && obj->parent && obj->getRepr() && obj->parent->getRepr()) { + obj->parent->getRepr()->removeChild(obj->getRepr()); + } + DocumentUndo::done(_document, SP_VERB_DIALOG_TAGS, _("Remove from selection set")); + } + } + } + } + } + } + + + if ( (event->type == GDK_2BUTTON_PRESS) && (event->button == 1) ) { + doubleclick = 1; + } + + if ( event->type == GDK_BUTTON_RELEASE && doubleclick) { + doubleclick = 0; + Gtk::TreeModel::Path path; + Gtk::TreeViewColumn* col = 0; + int x = static_cast(event->x); + int y = static_cast(event->y); + int x2 = 0; + int y2 = 0; + if ( _tree.get_path_at_pos( x, y, path, col, x2, y2 ) && col == _name_column) { + Gtk::TreeModel::Children::iterator iter = _tree.get_model()->get_iter(path); + Gtk::TreeModel::Row row = *iter; + + SPObject* obj = row[_model->_colObject]; + if (obj && (SP_IS_TAG(obj) || (SP_IS_TAG_USE(obj) && SP_TAG_USE(obj)->ref->getObject()))) { + // Double click on the Layer name, enable editing + _text_renderer->property_editable() = true; + _tree.set_cursor (path, *_name_column, true); + grab_focus(); + } + } + } + + return false; +} + +void TagsPanel::_storeDragSource(const Gtk::TreeModel::iterator& iter) +{ + Gtk::TreeModel::Row row = *iter; + SPObject* obj = row[_model->_colObject]; + SPTag* item = ( obj && SP_IS_TAG(obj) ) ? SP_TAG(obj) : 0; + if (item) + { + _dnd_source.push_back(item); + } +} + +/* + * Drap and drop within the tree + * Save the drag source and drop target SPObjects and if its a drag between layers or into (sublayer) a layer + */ +bool TagsPanel::_handleDragDrop(const Glib::RefPtr& context, int x, int y, guint time) +{ + int cell_x = 0, cell_y = 0; + Gtk::TreeModel::Path target_path; + Gtk::TreeView::Column *target_column; + + _dnd_into = true; + _dnd_target = _document->getDefs(); + _dnd_source.clear(); + _tree.get_selection()->selected_foreach_iter(sigc::mem_fun(*this, &TagsPanel::_storeDragSource)); + + if (_dnd_source.empty()) { + return true; + } + + if (_tree.get_path_at_pos (x, y, target_path, target_column, cell_x, cell_y)) { + // Are we before, inside or after the drop layer + Gdk::Rectangle rect; + _tree.get_background_area (target_path, *target_column, rect); + int cell_height = rect.get_height(); + _dnd_into = (cell_y > (int)(cell_height * 1/3) && cell_y <= (int)(cell_height * 2/3)); + if (cell_y > (int)(cell_height * 2/3)) { + Gtk::TreeModel::Path next_path = target_path; + next_path.next(); + if (_store->iter_is_valid(_store->get_iter(next_path))) { + target_path = next_path; + } else { + // Dragging to the "end" + Gtk::TreeModel::Path up_path = target_path; + up_path.up(); + if (_store->iter_is_valid(_store->get_iter(up_path))) { + // Drop into parent + target_path = up_path; + _dnd_into = true; + } else { + // Drop into the top level + _dnd_target = _document->getDefs(); + _dnd_into = true; + } + } + } + Gtk::TreeModel::iterator iter = _store->get_iter(target_path); + if (_store->iter_is_valid(iter)) { + Gtk::TreeModel::Row row = *iter; + SPObject *obj = row[_model->_colObject]; + SPObject *pobj = row[_model->_colParentObject]; + if (obj) { + if (SP_IS_TAG(obj)) { + _dnd_target = SP_TAG(obj); + } else if (SP_IS_TAG(obj->parent)) { + _dnd_target = SP_TAG(obj->parent); + _dnd_into = true; + } + } else if (pobj && SP_IS_TAG(pobj)) { + _dnd_target = SP_TAG(pobj); + _dnd_into = true; + } else { + return true; + } + } + } + + _takeAction(DRAGNDROP); + + return false; +} + +/* + * Move a layer in response to a drag & drop action + */ +void TagsPanel::_doTreeMove( ) +{ + if (_dnd_target) { + for (std::vector::iterator iter = _dnd_source.begin(); iter != _dnd_source.end(); ++iter) + { + SPTag *src = *iter; + if (src != _dnd_target) { + src->moveTo(_dnd_target, _dnd_into); + } + } + _desktop->selection->clear(); + while (!_dnd_source.empty()) + { + SPTag *src = _dnd_source.back(); + _select_tag(src); + _dnd_source.pop_back(); + } + DocumentUndo::done( _desktop->doc() , SP_VERB_DIALOG_TAGS, + _("Moved sets")); + } +} + + +void TagsPanel::_handleEdited(const Glib::ustring& path, const Glib::ustring& new_text) +{ + Gtk::TreeModel::iterator iter = _tree.get_model()->get_iter(path); + Gtk::TreeModel::Row row = *iter; + + _renameObject(row, new_text); + _text_renderer->property_editable() = false; +} + +void TagsPanel::_handleEditingCancelled() +{ + _text_renderer->property_editable() = false; +} + +void TagsPanel::_renameObject(Gtk::TreeModel::Row row, const Glib::ustring& name) +{ + if ( row && _desktop) { + SPObject* obj = row[_model->_colObject]; + if ( obj ) { + if (SP_IS_TAG(obj)) { + gchar const* oldLabel = obj->label(); + if ( !name.empty() && (!oldLabel || name != oldLabel) ) { + obj->setLabel(name.c_str()); + DocumentUndo::done( _desktop->doc() , SP_VERB_NONE, + _("Rename object")); + } + } else if (SP_IS_TAG_USE(obj) && (obj = SP_TAG_USE(obj)->ref->getObject())) { + gchar const* oldLabel = obj->label(); + if ( !name.empty() && (!oldLabel || name != oldLabel) ) { + obj->setLabel(name.c_str()); + DocumentUndo::done( _desktop->doc() , SP_VERB_NONE, + _("Rename object")); + } + } + } + } +} + +bool TagsPanel::_noSelection( Glib::RefPtr const & /*model*/, Gtk::TreeModel::Path const & /*path*/, bool currentlySelected ) +{ + return false; +} + +bool TagsPanel::_rowSelectFunction( Glib::RefPtr const & /*model*/, Gtk::TreeModel::Path const & /*path*/, bool currentlySelected ) +{ + bool val = true; + if ( !currentlySelected && _toggleEvent ) + { + GdkEvent* event = gtk_get_current_event(); + if ( event ) { + // (keep these checks separate, so we know when to call gdk_event_free() + if ( event->type == GDK_BUTTON_PRESS ) { + GdkEventButton const* target = reinterpret_cast(_toggleEvent); + GdkEventButton const* evtb = reinterpret_cast(event); + + if ( (evtb->window == target->window) + && (evtb->send_event == target->send_event) + && (evtb->time == target->time) + && (evtb->state == target->state) + ) + { + // Ooooh! It's a magic one + val = false; + } + } + gdk_event_free(event); + } + } + return val; +} + +void TagsPanel::_setExpanded(const Gtk::TreeModel::iterator& iter, const Gtk::TreeModel::Path& /*path*/, bool isexpanded) +{ + Gtk::TreeModel::Row row = *iter; + + SPObject* obj = row[_model->_colParentObject]; + if (obj && SP_IS_TAG(obj)) + { + SP_TAG(obj)->setExpanded(isexpanded); + obj->updateRepr(SP_OBJECT_WRITE_NO_CHILDREN | SP_OBJECT_WRITE_EXT); + } +} + +/** + * Constructor + */ +TagsPanel::TagsPanel() : + UI::Widget::Panel("", "/dialogs/tags", SP_VERB_DIALOG_TAGS), + _rootWatcher(0), + deskTrack(), + _desktop(0), + _document(0), + _model(0), + _pending(0), + _toggleEvent(0), + _defer_target(), + desktopChangeConn() +{ + //Inkscape::Preferences *prefs = Inkscape::Preferences::get(); + + ModelColumns *zoop = new ModelColumns(); + _model = zoop; + + _store = Gtk::TreeStore::create( *zoop ); + + _tree.set_model( _store ); + _tree.set_headers_visible(false); + _tree.set_reorderable(true); + _tree.enable_model_drag_dest (Gdk::ACTION_MOVE); + + Inkscape::UI::Widget::AddToIcon * addRenderer = manage( new Inkscape::UI::Widget::AddToIcon()); + int addColNum = _tree.append_column("type", *addRenderer) - 1; + Gtk::TreeViewColumn *col = _tree.get_column(addColNum); + if ( col ) { + col->add_attribute( addRenderer->property_active(), _model->_colAddRemove ); + col->add_attribute( addRenderer->property_visible(), _model->_colAllowAddRemove ); + } + + _text_renderer = manage(new Gtk::CellRendererText()); + int nameColNum = _tree.append_column("Name", *_text_renderer) - 1; + _name_column = _tree.get_column(nameColNum); + _name_column->add_attribute(_text_renderer->property_text(), _model->_colLabel); + + _tree.set_expander_column( *_tree.get_column(nameColNum) ); + + _tree.get_selection()->set_mode(Gtk::SELECTION_MULTIPLE); + _selectedConnection = _tree.get_selection()->signal_changed().connect( sigc::mem_fun(*this, &TagsPanel::_pushTreeSelectionToCurrent) ); + _tree.get_selection()->set_select_function( sigc::mem_fun(*this, &TagsPanel::_rowSelectFunction) ); + + _tree.signal_drag_drop().connect( sigc::mem_fun(*this, &TagsPanel::_handleDragDrop), false); + _collapsedConnection = _tree.signal_row_collapsed().connect( sigc::bind(sigc::mem_fun(*this, &TagsPanel::_setExpanded), false)); + _expandedConnection = _tree.signal_row_expanded().connect( sigc::bind(sigc::mem_fun(*this, &TagsPanel::_setExpanded), true)); + + _text_renderer->signal_edited().connect( sigc::mem_fun(*this, &TagsPanel::_handleEdited) ); + _text_renderer->signal_editing_canceled().connect( sigc::mem_fun(*this, &TagsPanel::_handleEditingCancelled) ); + + _tree.signal_button_press_event().connect( sigc::mem_fun(*this, &TagsPanel::_handleButtonEvent), false ); + _tree.signal_button_release_event().connect( sigc::mem_fun(*this, &TagsPanel::_handleButtonEvent), false ); + _tree.signal_key_press_event().connect( sigc::mem_fun(*this, &TagsPanel::_handleKeyEvent), false ); + + _scroller.add( _tree ); + _scroller.set_policy( Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC ); + _scroller.set_shadow_type(Gtk::SHADOW_IN); + Gtk::Requisition sreq; +#if WITH_GTKMM_3_0 + Gtk::Requisition sreq_natural; + _scroller.get_preferred_size(sreq_natural, sreq); +#else + sreq = _scroller.size_request(); +#endif + int minHeight = 70; + if (sreq.height < minHeight) { + // Set a min height to see the layers when used with Ubuntu liboverlay-scrollbar + _scroller.set_size_request(sreq.width, minHeight); + } + + _layersPage.pack_start( _scroller, Gtk::PACK_EXPAND_WIDGET ); + + _layersPage.pack_end(_buttonsRow, Gtk::PACK_SHRINK); + + _getContents()->pack_start(_layersPage, Gtk::PACK_EXPAND_WIDGET); + + SPDesktop* targetDesktop = getDesktop(); + + Gtk::Button* btn = manage( new Gtk::Button() ); + _styleButton( *btn, targetDesktop, SP_VERB_TAG_NEW, GTK_STOCK_ADD, _("Add a new selection set") ); + btn->signal_clicked().connect( sigc::bind( sigc::mem_fun(*this, &TagsPanel::_takeAction), (int)BUTTON_NEW) ); + _buttonsSecondary.pack_start(*btn, Gtk::PACK_SHRINK); + +// btn = manage( new Gtk::Button("Dup") ); +// btn->signal_clicked().connect( sigc::bind( sigc::mem_fun(*this, &LayersPanel::_takeAction), (int)BUTTON_DUPLICATE) ); +// _buttonsRow.add( *btn ); + + btn = manage( new Gtk::Button() ); + _styleButton( *btn, targetDesktop, SP_VERB_LAYER_DELETE, GTK_STOCK_REMOVE, _("Remove Item/Set") ); + btn->signal_clicked().connect( sigc::bind( sigc::mem_fun(*this, &TagsPanel::_takeAction), (int)BUTTON_DELETE) ); + _watching.push_back( btn ); + _buttonsSecondary.pack_start(*btn, Gtk::PACK_SHRINK); + + _buttonsRow.pack_start(_buttonsSecondary, Gtk::PACK_EXPAND_WIDGET); + _buttonsRow.pack_end(_buttonsPrimary, Gtk::PACK_EXPAND_WIDGET); + + // ------------------------------------------------------- + { + _watching.push_back( &_addPopupItem( targetDesktop, SP_VERB_TAG_NEW, 0, "New", (int)BUTTON_NEW ) ); + + _popupMenu.show_all_children(); + } + // ------------------------------------------------------- + + + + for ( std::vector::iterator it = _watching.begin(); it != _watching.end(); ++it ) { + (*it)->set_sensitive( false ); + } + for ( std::vector::iterator it = _watchingNonTop.begin(); it != _watchingNonTop.end(); ++it ) { + (*it)->set_sensitive( false ); + } + for ( std::vector::iterator it = _watchingNonBottom.begin(); it != _watchingNonBottom.end(); ++it ) { + (*it)->set_sensitive( false ); + } + + setDesktop( targetDesktop ); + + show_all_children(); + + // restorePanelPrefs(); + + // Connect this up last + desktopChangeConn = deskTrack.connectDesktopChanged( sigc::mem_fun(*this, &TagsPanel::setDesktop) ); + deskTrack.connect(GTK_WIDGET(gobj())); +} + +TagsPanel::~TagsPanel() +{ + + setDesktop(NULL); + + if ( _model ) + { + delete _model; + _model = 0; + } + + if (_pending) { + delete _pending; + _pending = 0; + } + + if ( _toggleEvent ) + { + gdk_event_free( _toggleEvent ); + _toggleEvent = 0; + } + + desktopChangeConn.disconnect(); + deskTrack.disconnect(); +} + +void TagsPanel::setDocument(SPDesktop* /*desktop*/, SPDocument* document) +{ + while (!_objectWatchers.empty()) + { + TagsPanel::ObjectWatcher *w = _objectWatchers.back(); + w->_repr->removeObserver(*w); + _objectWatchers.pop_back(); + delete w; + } + + if (_rootWatcher) + { + _rootWatcher->_repr->removeObserver(*_rootWatcher); + delete _rootWatcher; + _rootWatcher = NULL; + } + + _document = document; + + if (document && document->getDefs() && document->getDefs()->getRepr()) + { + _rootWatcher = new TagsPanel::ObjectWatcher(this, document->getDefs()); + document->getDefs()->getRepr()->addObserver(*_rootWatcher); + _objectsChanged(document->getDefs()); + } +} + +void TagsPanel::setDesktop( SPDesktop* desktop ) +{ + Panel::setDesktop(desktop); + + if ( desktop != _desktop ) { + _documentChangedConnection.disconnect(); + _selectionChangedConnection.disconnect(); + if ( _desktop ) { + _desktop = 0; + } + + _desktop = Panel::getDesktop(); + if ( _desktop ) { + //setLabel( _desktop->doc()->name ); + _documentChangedConnection = _desktop->connectDocumentReplaced( sigc::mem_fun(*this, &TagsPanel::setDocument)); + _selectionChangedConnection = _desktop->selection->connectChanged( sigc::mem_fun(*this, &TagsPanel::_objectsSelected)); + + setDocument(_desktop, _desktop->doc()); + } + } +/* + GSList const *layers = _desktop->doc()->getResourceList( "layer" ); + g_message( "layers list starts at %p", layers ); + for ( GSList const *iter=layers ; iter ; iter = iter->next ) { + SPObject *layer=static_cast(iter->data); + g_message(" {%s} [%s]", layer->id, layer->label() ); + } +*/ + deskTrack.setBase(desktop); +} + + + + + +} //namespace Dialogs +} //namespace UI +} //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 : diff --git a/src/ui/dialog/tags.h b/src/ui/dialog/tags.h new file mode 100644 index 000000000..d35dfba01 --- /dev/null +++ b/src/ui/dialog/tags.h @@ -0,0 +1,181 @@ +/* + * A simple dialog for tags UI. + * + * Authors: + * Theodore Janeczko + * + * Copyright (C) Theodore Janeczko 2012 + * + * Released under GNU GPL, read the file 'COPYING' for more information + */ + +#ifndef SEEN_TAGS_PANEL_H +#define SEEN_TAGS_PANEL_H + +#include +#include +#include +#include +#include +#include "ui/widget/spinbutton.h" +#include "ui/widget/panel.h" +#include "ui/widget/object-composite-settings.h" +#include "desktop-tracker.h" +#include "ui/widget/style-subject.h" +#include "selection.h" +#include "ui/widget/filter-effect-chooser.h" + +class SPObject; +class SPTag; +struct SPColorSelector; + +namespace Inkscape { + +namespace UI { +namespace Dialog { + + +/** + * A panel that displays layers. + */ +class TagsPanel : public UI::Widget::Panel +{ +public: + TagsPanel(); + virtual ~TagsPanel(); + + //virtual void setOrientation( Gtk::AnchorType how ); + + static TagsPanel& getInstance(); + + void setDesktop( SPDesktop* desktop ); + void setDocument( SPDesktop* desktop, SPDocument* document); + +protected: + //virtual void _handleAction( int setId, int itemId ); + friend void sp_highlight_picker_color_mod(SPColorSelector *csel, GObject *cp); +private: + class ModelColumns; + class InternalUIBounce; + class ObjectWatcher; + + TagsPanel(TagsPanel const &); // no copy + TagsPanel &operator=(TagsPanel const &); // no assign + + void _styleButton( Gtk::Button& btn, SPDesktop *desktop, unsigned int code, char const* iconName, char const* tooltip ); + void _fireAction( unsigned int code ); + Gtk::MenuItem& _addPopupItem( SPDesktop *desktop, unsigned int code, char const* iconName, char const* fallback, int id ); + + bool _handleButtonEvent(GdkEventButton *event); + bool _handleKeyEvent(GdkEventKey *event); + + void _storeDragSource(const Gtk::TreeModel::iterator& iter); + bool _handleDragDrop(const Glib::RefPtr& context, int x, int y, guint time); + void _handleEdited(const Glib::ustring& path, const Glib::ustring& new_text); + void _handleEditingCancelled(); + + void _doTreeMove(); + void _renameObject(Gtk::TreeModel::Row row, const Glib::ustring& name); + + void _pushTreeSelectionToCurrent(); + void _selected_row_callback( const Gtk::TreeModel::iterator& iter ); + void _select_tag( SPTag * tag ); + + void _checkTreeSelection(); + + void _takeAction( int val ); + bool _executeAction(); + + void _setExpanded( const Gtk::TreeModel::iterator& iter, const Gtk::TreeModel::Path& path, bool isexpanded ); + + bool _noSelection( Glib::RefPtr const & model, Gtk::TreeModel::Path const & path, bool b ); + bool _rowSelectFunction( Glib::RefPtr const & model, Gtk::TreeModel::Path const & path, bool b ); + + void _updateObject(SPObject *obj); + bool _checkForUpdated(const Gtk::TreePath &path, const Gtk::TreeIter& iter, SPObject* obj); + + void _objectsSelected(Selection *sel); + bool _checkForSelected(const Gtk::TreePath& path, const Gtk::TreeIter& iter, SPObject* layer); + + void _objectsChanged(SPObject *root); + void _addObject( SPDocument* doc, SPObject* obj, Gtk::TreeModel::Row* parentRow ); + + void _checkForDeleted(const Gtk::TreeIter& iter, std::vector* todelete); + +// std::vector groupConnections; + TagsPanel::ObjectWatcher* _rootWatcher; + std::vector _objectWatchers; + + // Hooked to the layer manager: + sigc::connection _documentChangedConnection; + sigc::connection _selectionChangedConnection; + + sigc::connection _changedConnection; + sigc::connection _addedConnection; + sigc::connection _removedConnection; + + // Internal + sigc::connection _selectedConnection; + sigc::connection _expandedConnection; + sigc::connection _collapsedConnection; + + DesktopTracker deskTrack; + SPDesktop* _desktop; + SPDocument* _document; + ModelColumns* _model; + InternalUIBounce* _pending; + gboolean _dnd_into; + std::vector _dnd_source; + SPObject* _dnd_target; + + GdkEvent* _toggleEvent; + bool down_at_add; + + Gtk::TreeModel::Path _defer_target; + + Glib::RefPtr _store; + std::vector _watching; + std::vector _watchingNonTop; + std::vector _watchingNonBottom; + + Gtk::TreeView _tree; + Gtk::CellRendererText *_text_renderer; + Gtk::TreeView::Column *_name_column; +#if WITH_GTKMM_3_0 + Gtk::Box _buttonsRow; + Gtk::Box _buttonsPrimary; + Gtk::Box _buttonsSecondary; +#else + Gtk::HBox _buttonsRow; + Gtk::HBox _buttonsPrimary; + Gtk::HBox _buttonsSecondary; +#endif + Gtk::ScrolledWindow _scroller; + Gtk::Menu _popupMenu; + Inkscape::UI::Widget::SpinButton _spinBtn; + Gtk::VBox _layersPage; + + sigc::connection desktopChangeConn; + +}; + + + +} //namespace Dialogs +} //namespace UI +} //namespace Inkscape + + + +#endif // SEEN_OBJECTS_PANEL_H + +/* + 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 : diff --git a/src/verbs.cpp b/src/verbs.cpp index c20f48e65..e1d6c0583 100644 --- a/src/verbs.cpp +++ b/src/verbs.cpp @@ -64,6 +64,7 @@ #include "seltrans.h" #include "shape-editor.h" #include "shortcuts.h" +#include "sp-defs.h" #include "sp-flowtext.h" #include "sp-guide.h" #include "splivarot.h" @@ -214,6 +215,25 @@ public: { } }; // ObjectVerb class +/** + * A class to encompass all of the verbs which deal with operations related to tags. + */ +class TagVerb : public Verb { +private: + static void perform(SPAction *action, void *mydata); +protected: + virtual SPAction *make_action(Inkscape::ActionContext const & context); +public: + /** Use the Verb initializer with the same parameters. */ + TagVerb(unsigned int const code, + gchar const *id, + gchar const *name, + gchar const *tip, + gchar const *image) : + Verb(code, id, name, tip, image, _("Tag")) + { } +}; // TagVerb class + /** * A class to encompass all of the verbs which deal with operations relative to context. */ @@ -459,6 +479,19 @@ SPAction *ObjectVerb::make_action(Inkscape::ActionContext const & context) return make_action_helper(context, &perform); } +/** + * Create an action for a \c TagVerb. + * + * Calls \c make_action_helper with the \c vector. + * + * @param view Which view the action should be created for. + * @return The built action. + */ +SPAction *TagVerb::make_action(Inkscape::ActionContext const & context) +{ + return make_action_helper(context, &perform); +} + /** * Create an action for a \c ContextVerb. * @@ -1547,6 +1580,47 @@ void ObjectVerb::perform( SPAction *action, void *data) } // end of sp_verb_action_object_perform() +/** + * Decode the verb code and take appropriate action. + */ +void TagVerb::perform( SPAction *action, void *data) +{ + SPDesktop *dt = static_cast(sp_action_get_view(action)); + if (!dt) + return; + + //Inkscape::UI::Tools::ToolBase *ec = dt->event_context; + + Inkscape::Selection *sel = sp_desktop_selection(dt); + + Inkscape::XML::Document * doc; + Inkscape::XML::Node * repr; + gchar *id; + + switch (reinterpret_cast(data)) { + case SP_VERB_TAG_NEW: + static int tag_suffix=1; + id=NULL; + do { + g_free(id); + id = g_strdup_printf("tag%d", tag_suffix++); + } while (dt->doc()->getObjectById(id)); + + doc = dt->doc()->getReprDoc(); + repr = doc->createElement("inkscape:tag"); + repr->setAttribute("id", id); + g_free(id); + + dt->doc()->getDefs()->addChild(repr, NULL); + Inkscape::DocumentUndo::done(dt->doc(), SP_VERB_DIALOG_TAGS, _("Create new selection set")); + break; + default: + break; + } + +} // end of sp_verb_action_tag_perform() + + /** * Decode the verb code and take appropriate action. */ @@ -2040,9 +2114,9 @@ void DialogVerb::perform(SPAction *action, void *data) case SP_VERB_DIALOG_OBJECTS: dt->_dlg_mgr->showDialog("ObjectsPanel"); break; - /*case SP_VERB_DIALOG_TAGS: + case SP_VERB_DIALOG_TAGS: dt->_dlg_mgr->showDialog("TagsPanel"); - break;*/ //in a moment my dear + break; case SP_VERB_DIALOG_LIVE_PATH_EFFECT: dt->_dlg_mgr->showDialog("LivePathEffect"); break; @@ -2647,7 +2721,9 @@ Verb *Verb::_base_verbs[] = { N_("Edit clipping path"), INKSCAPE_ICON("path-clip-edit")), new ObjectVerb(SP_VERB_OBJECT_UNSET_CLIPPATH, "ObjectUnSetClipPath", N_("_Release"), N_("Remove clipping path from selection"), NULL), - + // Tag + new TagVerb(SP_VERB_TAG_NEW, "TagNew", N_("_New"), + N_("Create new selection set"), NULL), // Tools new ContextVerb(SP_VERB_CONTEXT_SELECT, "ToolSelector", NC_("ContextVerb", "Select"), N_("Select and transform objects"), INKSCAPE_ICON("tool-pointer")), @@ -2862,8 +2938,8 @@ Verb *Verb::_base_verbs[] = { N_("View Layers"), INKSCAPE_ICON("dialog-layers")), new DialogVerb(SP_VERB_DIALOG_OBJECTS, "DialogObjects", N_("Object_s..."), N_("View Objects"), INKSCAPE_ICON("dialog-layers")), - /*new DialogVerb(SP_VERB_DIALOG_TAGS, "DialogObjects", N_("Ta_gs..."), - N_("View Tags"), INKSCAPE_ICON("edit-select-all-layers")),*/ + new DialogVerb(SP_VERB_DIALOG_TAGS, "DialogTags", N_("Ta_gs..."), + N_("View Tags"), INKSCAPE_ICON("edit-select-all-layers")), new DialogVerb(SP_VERB_DIALOG_LIVE_PATH_EFFECT, "DialogLivePathEffect", N_("Path E_ffects ..."), N_("Manage, edit, and apply path effects"), NULL), new DialogVerb(SP_VERB_DIALOG_FILTER_EFFECTS, "DialogFilterEffects", N_("Filter _Editor..."), diff --git a/src/verbs.h b/src/verbs.h index 141a9c7e9..821c9ee82 100644 --- a/src/verbs.h +++ b/src/verbs.h @@ -177,6 +177,8 @@ enum { SP_VERB_OBJECT_SET_CLIPPATH, SP_VERB_OBJECT_EDIT_CLIPPATH, SP_VERB_OBJECT_UNSET_CLIPPATH, + /* Tag */ + SP_VERB_TAG_NEW, /* Tools */ SP_VERB_CONTEXT_SELECT, SP_VERB_CONTEXT_NODE, @@ -290,7 +292,7 @@ enum { SP_VERB_DIALOG_EXTENSIONEDITOR, SP_VERB_DIALOG_LAYERS, SP_VERB_DIALOG_OBJECTS, -// SP_VERB_DIALOG_TAGS, + SP_VERB_DIALOG_TAGS, SP_VERB_DIALOG_LIVE_PATH_EFFECT, SP_VERB_DIALOG_FILTER_EFFECTS, SP_VERB_DIALOG_SVG_FONTS, -- cgit v1.2.3 From 1f1932ae4592c8f316e3a68ac86874bf87f321c4 Mon Sep 17 00:00:00 2001 From: "Liam P. White" Date: Sun, 11 May 2014 14:23:10 -0400 Subject: Stabilize the selection set system a bit (bzr r13090.1.76) --- src/sp-tag-use.cpp | 1 + src/ui/dialog/tags.cpp | 10 +++++++--- 2 files changed, 8 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/sp-tag-use.cpp b/src/sp-tag-use.cpp index ffcfcee3e..5851598f2 100644 --- a/src/sp-tag-use.cpp +++ b/src/sp-tag-use.cpp @@ -175,6 +175,7 @@ SPTagUse::href_changed(SPObject */*old_ref*/, SPObject */*ref*/) SPObject* child_ = SPFactory::instance().createObject(typeString); if (child_) { + child = child_; attach(child_, lastChild()); sp_object_unref(child_, 0); child_->invoke_build(this->document, childrepr, TRUE); diff --git a/src/ui/dialog/tags.cpp b/src/ui/dialog/tags.cpp index 7fdd2e906..14ad5b8cc 100644 --- a/src/ui/dialog/tags.cpp +++ b/src/ui/dialog/tags.cpp @@ -280,7 +280,8 @@ bool TagsPanel::_executeAction() for (std::vector::iterator iter = todelete.begin(); iter != todelete.end(); ++iter) { SPObject * obj = *iter; if (obj && obj->parent && obj->getRepr() && obj->parent->getRepr()) { - obj->parent->getRepr()->removeChild(obj->getRepr()); + //obj->parent->getRepr()->removeChild(obj->getRepr()); + obj->deleteObject(true, true); } } DocumentUndo::done(_document, SP_VERB_DIALOG_TAGS, _("Remove from selection set")); @@ -576,7 +577,8 @@ bool TagsPanel::_handleKeyEvent(GdkEventKey *event) for (std::vector::iterator iter = todelete.begin(); iter != todelete.end(); ++iter) { SPObject * obj = *iter; if (obj && obj->parent && obj->getRepr() && obj->parent->getRepr()) { - obj->parent->getRepr()->removeChild(obj->getRepr()); + //obj->parent->getRepr()->removeChild(obj->getRepr()); + obj->deleteObject(true, true); } } DocumentUndo::done(_document, SP_VERB_DIALOG_TAGS, _("Remove from selection set")); @@ -680,12 +682,14 @@ bool TagsPanel::_handleButtonEvent(GdkEventButton* event) } } else { std::vector todelete; + // FIXME unnecessary use of XML tree _tree.get_selection()->selected_foreach_iter(sigc::bind*>(sigc::mem_fun(*this, &TagsPanel::_checkForDeleted), &todelete)); if (!todelete.empty()) { for (std::vector::iterator iter = todelete.begin(); iter != todelete.end(); ++iter) { SPObject * tobj = *iter; if (tobj && tobj->parent && tobj->getRepr() && tobj->parent->getRepr()) { - tobj->parent->getRepr()->removeChild(tobj->getRepr()); + //tobj->parent->getRepr()->removeChild(tobj->getRepr()); + tobj->deleteObject(true, true); } } } else if (obj && obj->parent && obj->getRepr() && obj->parent->getRepr()) { -- cgit v1.2.3 From 0dc8b506fe92a6f4a57d6412db69c3fea420d67a Mon Sep 17 00:00:00 2001 From: "Liam P. White" Date: Sun, 11 May 2014 15:08:59 -0400 Subject: Rename "Tags" to "Selection sets" to avoid confusion with a global tagging system (bzr r13090.1.77) --- src/ui/dialog/tags.cpp | 2 +- src/verbs.cpp | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/ui/dialog/tags.cpp b/src/ui/dialog/tags.cpp index 14ad5b8cc..1b5dd9400 100644 --- a/src/ui/dialog/tags.cpp +++ b/src/ui/dialog/tags.cpp @@ -1025,7 +1025,7 @@ TagsPanel::TagsPanel() : // ------------------------------------------------------- { - _watching.push_back( &_addPopupItem( targetDesktop, SP_VERB_TAG_NEW, 0, "New", (int)BUTTON_NEW ) ); + _watching.push_back( &_addPopupItem( targetDesktop, SP_VERB_TAG_NEW, 0, "Add a new selection set", (int)BUTTON_NEW ) ); _popupMenu.show_all_children(); } diff --git a/src/verbs.cpp b/src/verbs.cpp index e1d6c0583..73613ab9e 100644 --- a/src/verbs.cpp +++ b/src/verbs.cpp @@ -1603,7 +1603,7 @@ void TagVerb::perform( SPAction *action, void *data) id=NULL; do { g_free(id); - id = g_strdup_printf("tag%d", tag_suffix++); + id = g_strdup_printf("Set %d", tag_suffix++); } while (dt->doc()->getObjectById(id)); doc = dt->doc()->getReprDoc(); @@ -2938,7 +2938,7 @@ Verb *Verb::_base_verbs[] = { N_("View Layers"), INKSCAPE_ICON("dialog-layers")), new DialogVerb(SP_VERB_DIALOG_OBJECTS, "DialogObjects", N_("Object_s..."), N_("View Objects"), INKSCAPE_ICON("dialog-layers")), - new DialogVerb(SP_VERB_DIALOG_TAGS, "DialogTags", N_("Ta_gs..."), + new DialogVerb(SP_VERB_DIALOG_TAGS, "DialogTags", N_("Selection se_ts..."), N_("View Tags"), INKSCAPE_ICON("edit-select-all-layers")), new DialogVerb(SP_VERB_DIALOG_LIVE_PATH_EFFECT, "DialogLivePathEffect", N_("Path E_ffects ..."), N_("Manage, edit, and apply path effects"), NULL), -- cgit v1.2.3 From 8e303a547b23758ec6c1accee912185f25718c03 Mon Sep 17 00:00:00 2001 From: "Liam P. White" Date: Mon, 12 May 2014 19:59:28 -0400 Subject: Commit patch for "leaned" cap. Thanks Jabiertxof! (bzr r13090.1.78) --- src/live_effects/lpe-jointype.cpp | 24 ++++++--- src/live_effects/lpe-jointype.h | 2 + src/live_effects/pathoutlineprovider.cpp | 92 ++++++++++++++++++++++++++------ src/live_effects/pathoutlineprovider.h | 14 +++-- 4 files changed, 105 insertions(+), 27 deletions(-) (limited to 'src') diff --git a/src/live_effects/lpe-jointype.cpp b/src/live_effects/lpe-jointype.cpp index 0c1813970..b0a6e845b 100644 --- a/src/live_effects/lpe-jointype.cpp +++ b/src/live_effects/lpe-jointype.cpp @@ -41,10 +41,11 @@ static const Util::EnumData JoinTypeData[] = { }; static const Util::EnumData CapTypeData[] = { - {butt_straight, N_("Butt"), "butt"}, - {butt_round, N_("Rounded"), "round"}, - {butt_square, N_("Square"), "square"}, - {butt_pointy, N_("Peak"), "peak"} + {BUTT_STRAIGHT, N_("Butt"), "butt"}, + {BUTT_ROUND, N_("Rounded"), "round"}, + {BUTT_SQUARE, N_("Square"), "square"}, + {BUTT_POINTY, N_("Peak"), "peak"}, + {BUTT_LEANED, N_("Leaned"), "leaned"} }; static const Util::EnumDataConverter CapTypeConverter(CapTypeData, sizeof(CapTypeData)/sizeof(*CapTypeData)); @@ -55,6 +56,8 @@ LPEJoinType::LPEJoinType(LivePathEffectObject *lpeobject) : line_width(_("Line width"), _("Thickness of the stroke"), "line_width", &wr, this, 1.), linecap_type(_("Line cap"), _("The end shape of the stroke"), "linecap_type", CapTypeConverter, &wr, this, butt_straight), linejoin_type(_("Join:"), _("Determines the shape of the path's corners"), "linejoin_type", JoinTypeConverter, &wr, this, LINEJOIN_EXTRAPOLATED), + start_lean(_("Start path lean"), _("Start path lean"), "start_lean", &wr, this, 0.), + end_lean(_("End path lean"), _("End path lean"), "end_lean", &wr, this, 0.), miter_limit(_("Miter limit:"), _("Maximum length of the miter join (in units of stroke width)"), "miter_limit", &wr, this, 100.), attempt_force_join(_("Force miter"), _("Overrides the miter limit and forces a join."), "attempt_force_join", &wr, this, true) { @@ -62,9 +65,17 @@ LPEJoinType::LPEJoinType(LivePathEffectObject *lpeobject) : registerParameter( dynamic_cast(&linecap_type) ); registerParameter( dynamic_cast(&line_width) ); registerParameter( dynamic_cast(&linejoin_type) ); + registerParameter( dynamic_cast(&start_lean) ); + registerParameter( dynamic_cast(&end_lean) ); registerParameter( dynamic_cast(&miter_limit) ); registerParameter( dynamic_cast(&attempt_force_join) ); was_initialized = false; + start_lean.param_set_range(-1,1); + start_lean.param_set_increments(0.1, 0.1); + start_lean.param_set_digits(4); + end_lean.param_set_range(-1,1); + end_lean.param_set_increments(0.1, 0.1); + end_lean.param_set_digits(4); } LPEJoinType::~LPEJoinType() @@ -163,9 +174,10 @@ void LPEJoinType::doOnRemove(SPLPEItem const* lpeitem) //wrapper around it. std::vector LPEJoinType::doEffect_path(std::vector const & path_in) { - return Outline::PathVectorOutline(path_in, line_width, static_cast(linecap_type.get_value()), + return Outline::PathVectorOutline(path_in, line_width, static_cast(linecap_type.get_value()), static_cast(linejoin_type.get_value()), - (attempt_force_join ? std::numeric_limits::max() : miter_limit)); + (attempt_force_join ? std::numeric_limits::max() : miter_limit), + start_lean/2 ,end_lean/2); } } //namespace LivePathEffect diff --git a/src/live_effects/lpe-jointype.h b/src/live_effects/lpe-jointype.h index db113c66a..7ebce1c7e 100755 --- a/src/live_effects/lpe-jointype.h +++ b/src/live_effects/lpe-jointype.h @@ -32,6 +32,8 @@ private: ScalarParam line_width; EnumParam linecap_type; EnumParam linejoin_type; + ScalarParam start_lean; + ScalarParam end_lean; ScalarParam miter_limit; BoolParam attempt_force_join; bool was_initialized; diff --git a/src/live_effects/pathoutlineprovider.cpp b/src/live_effects/pathoutlineprovider.cpp index 9ff896f84..d6e0ce7ea 100644 --- a/src/live_effects/pathoutlineprovider.cpp +++ b/src/live_effects/pathoutlineprovider.cpp @@ -586,7 +586,7 @@ Geom::Path doAdvHalfOutline(const Geom::Path& path_in, double line_width, double } Geom::PathVector outlinePath(const Geom::PathVector& path_in, double line_width, LineJoinType join, - ButtType butt, double miter_lim, bool extrapolate) + ButtTypeMod butt, double miter_lim, bool extrapolate, double start_lean, double end_lean) { Geom::PathVector path_out; @@ -610,13 +610,13 @@ Geom::PathVector outlinePath(const Geom::PathVector& path_in, double line_width, //add in our line caps if (!path_in[i].closed()) { switch (butt) { - case butt_straight: + case BUTT_STRAIGHT: pb.lineTo(against_direction.initialPoint()); break; - case butt_round: + case BUTT_ROUND: pb.arcTo((-line_width) / 2, (-line_width) / 2, 0., true, true, against_direction.initialPoint() ); break; - case butt_pointy: { + case BUTT_POINTY: { Geom::Point end_deriv = -Geom::unitTangentAt(Geom::reverse(path_in[i].back().toSBasis()), 0.); double radius = 0.5 * Geom::distance(with_direction.finalPoint(), against_direction.initialPoint()); Geom::Point midpoint = 0.5 * (with_direction.finalPoint() + against_direction.initialPoint()) + radius*end_deriv; @@ -624,7 +624,7 @@ Geom::PathVector outlinePath(const Geom::PathVector& path_in, double line_width, pb.lineTo(against_direction.initialPoint()); break; } - case butt_square: { + case BUTT_SQUARE: { Geom::Point end_deriv = -Geom::unitTangentAt(Geom::reverse(path_in[i].back().toSBasis()), 0.); double radius = 0.5 * Geom::distance(with_direction.finalPoint(), against_direction.initialPoint()); pb.lineTo(with_direction.finalPoint() + radius*end_deriv); @@ -632,6 +632,15 @@ Geom::PathVector outlinePath(const Geom::PathVector& path_in, double line_width, pb.lineTo(against_direction.initialPoint()); break; } + case BUTT_LEANED: { + Geom::Point end_deriv = -Geom::unitTangentAt(Geom::reverse(path_in[i].back().toSBasis()), 0.); + double maxRadius = (end_lean+0.5) * Geom::distance(with_direction.finalPoint(), against_direction.initialPoint()); + double minRadius = ((end_lean*-1)+0.5) * Geom::distance(with_direction.finalPoint(), against_direction.initialPoint()); + pb.lineTo(with_direction.finalPoint() + maxRadius*end_deriv); + pb.lineTo(against_direction.initialPoint() + minRadius*end_deriv); + pb.lineTo(against_direction.initialPoint()); + break; + } } } else { pb.moveTo(against_direction.initialPoint()); @@ -642,13 +651,13 @@ Geom::PathVector outlinePath(const Geom::PathVector& path_in, double line_width, //cap (if necessary) if (!path_in[i].closed()) { switch (butt) { - case butt_straight: + case BUTT_STRAIGHT: pb.lineTo(with_direction.initialPoint()); break; - case butt_round: + case BUTT_ROUND: pb.arcTo((-line_width) / 2, (-line_width) / 2, 0., true, true, with_direction.initialPoint() ); break; - case butt_pointy: { + case BUTT_POINTY: { Geom::Point end_deriv = -Geom::unitTangentAt(path_in[i].front().toSBasis(), 0.); double radius = 0.5 * Geom::distance(against_direction.finalPoint(), with_direction.initialPoint()); Geom::Point midpoint = 0.5 * (against_direction.finalPoint() + with_direction.initialPoint()) + radius*end_deriv; @@ -656,7 +665,7 @@ Geom::PathVector outlinePath(const Geom::PathVector& path_in, double line_width, pb.lineTo(with_direction.initialPoint()); break; } - case butt_square: { + case BUTT_SQUARE: { Geom::Point end_deriv = -Geom::unitTangentAt(path_in[i].front().toSBasis(), 0.); double radius = 0.5 * Geom::distance(against_direction.finalPoint(), with_direction.initialPoint()); pb.lineTo(against_direction.finalPoint() + radius*end_deriv); @@ -664,6 +673,15 @@ Geom::PathVector outlinePath(const Geom::PathVector& path_in, double line_width, pb.lineTo(with_direction.initialPoint()); break; } + case BUTT_LEANED: { + Geom::Point end_deriv = -Geom::unitTangentAt(path_in[i].front().toSBasis(), 0.); + double maxRadius = (start_lean+0.5) * Geom::distance(against_direction.finalPoint(), with_direction.initialPoint()); + double minRadius = ((start_lean*-1)+0.5) * Geom::distance(against_direction.finalPoint(), with_direction.initialPoint()); + pb.lineTo(against_direction.finalPoint() + minRadius*end_deriv); + pb.lineTo(with_direction.initialPoint() + maxRadius*end_deriv); + pb.lineTo(with_direction.initialPoint()); + break; + } } } pb.flush(); @@ -674,9 +692,29 @@ Geom::PathVector outlinePath(const Geom::PathVector& path_in, double line_width, } else { Path p = Path(); Path outlinepath = Path(); - + ButtType original_butt; + switch (butt) { + case BUTT_STRAIGHT: + original_butt = butt_straight; + break; + case BUTT_ROUND: + original_butt = butt_round; + break; + case butt_pointy: { + original_butt = butt_pointy; + break; + } + case BUTT_SQUARE: { + original_butt = butt_square; + break; + } + case BUTT_LEANED: { + original_butt = butt_straight; + break; + } + } p.LoadPath(path_in[i], Geom::Affine(), false, false); - p.Outline(&outlinepath, line_width / 2, static_cast(join), butt, miter_lim); + p.Outline(&outlinepath, line_width / 2, static_cast(join), original_butt, miter_lim); Geom::PathVector *pv_p = outlinepath.MakePathVector(); //somewhat hack-ish path_out.push_back( (*pv_p)[0].reverse() ); @@ -686,8 +724,8 @@ Geom::PathVector outlinePath(const Geom::PathVector& path_in, double line_width, return path_out; } -Geom::PathVector PathVectorOutline(Geom::PathVector const & path_in, double line_width, ButtType linecap_type, - LineJoinType linejoin_type, double miter_limit) +Geom::PathVector PathVectorOutline(Geom::PathVector const & path_in, double line_width, ButtTypeMod linecap_type, + LineJoinType linejoin_type, double miter_limit, double start_lean, double end_lean) { std::vector path_out = std::vector(); if (path_in.empty()) { @@ -702,9 +740,30 @@ Geom::PathVector PathVectorOutline(Geom::PathVector const & path_in, double line #define miter_lim fabs(line_width * miter_limit) //magic! + ButtType original_butt; + switch (linecap_type) { + case BUTT_STRAIGHT: + original_butt = butt_straight; + break; + case BUTT_ROUND: + original_butt = butt_round; + break; + case butt_pointy: { + original_butt = butt_pointy; + break; + } + case BUTT_SQUARE: { + original_butt = butt_square; + break; + } + case BUTT_LEANED: { + original_butt = butt_straight; + break; + } + } if (linejoin_type <= 2) { p.Outline(&outlinepath, line_width / 2, static_cast(linejoin_type), - linecap_type, miter_lim); + original_butt, miter_lim); //fix memory leak std::vector *pv_p = outlinepath.MakePathVector(); path_out = *pv_p; @@ -713,12 +772,11 @@ Geom::PathVector PathVectorOutline(Geom::PathVector const & path_in, double line } else if (linejoin_type == 3) { //reflected arc join path_out = outlinePath(path_in, line_width, static_cast(linejoin_type), - linecap_type , miter_lim, false); + linecap_type , miter_lim, false, start_lean, end_lean); } else if (linejoin_type == 4) { //extrapolated arc join - path_out = outlinePath(path_in, line_width, LINEJOIN_STRAIGHT, linecap_type, miter_lim, true); - + path_out = outlinePath(path_in, line_width, LINEJOIN_STRAIGHT, linecap_type, miter_lim, true, start_lean, end_lean); } #undef miter_lim diff --git a/src/live_effects/pathoutlineprovider.h b/src/live_effects/pathoutlineprovider.h index 0ee0f261e..272c93a49 100644 --- a/src/live_effects/pathoutlineprovider.h +++ b/src/live_effects/pathoutlineprovider.h @@ -11,7 +11,13 @@ enum LineJoinType { LINEJOIN_REFLECTED, LINEJOIN_EXTRAPOLATED }; - +enum ButtTypeMod { + BUTT_STRAIGHT, + BUTT_ROUND, + BUTT_SQUARE, + BUTT_POINTY, + BUTT_LEANED +}; namespace Geom { Geom::CubicBezier sbasis_to_cubicbezier(Geom::D2 const & sbasis_in); @@ -21,11 +27,11 @@ namespace Geom namespace Outline { unsigned bezierOrder (const Geom::Curve* curve_in); - std::vector PathVectorOutline(std::vector const & path_in, double line_width, ButtType linecap_type, - LineJoinType linejoin_type, double miter_limit); + std::vector PathVectorOutline(std::vector const & path_in, double line_width, ButtTypeMod linecap_type, + LineJoinType linejoin_type, double miter_limit, double start_lean = 0, double end_lean = 0); /*Geom::PathVector outlinePath(const Geom::PathVector& path_in, double line_width, LineJoinType join, - ButtType butt, double miter_lim, bool extrapolate = false);*/ + ButtTypeMod butt, double miter_lim, bool extrapolate = false);*/ Geom::Path PathOutsideOutline(Geom::Path const & path_in, double line_width, LineJoinType linejoin_type, double miter_limit); } -- cgit v1.2.3 From eb4d7e1225a2e1e5a5d1da8d0ab784632bc77291 Mon Sep 17 00:00:00 2001 From: "Liam P. White" Date: Sat, 14 Jun 2014 14:51:11 -0400 Subject: Add clip group option from Ponyscape (bzr r13090.1.83) --- src/interface.cpp | 11 +++++ src/interface.h | 1 + src/selection-chemistry.cpp | 112 ++++++++++++++++++++++++++++++++++++++++++++ src/selection-chemistry.h | 1 + src/ui/dialog/objects.cpp | 12 +++-- src/verbs.cpp | 5 ++ src/verbs.h | 1 + 7 files changed, 139 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/interface.cpp b/src/interface.cpp index 1cbeb44a3..e47cff598 100644 --- a/src/interface.cpp +++ b/src/interface.cpp @@ -1756,6 +1756,13 @@ void ContextMenu::MakeItemMenu (void) } mi->show(); append(*mi); + + /*SSet Clip Group */ + mi = Gtk::manage(new Gtk::MenuItem(_("Create Clip G_roup"),1)); + mi->signal_activate().connect(sigc::mem_fun(*this, &ContextMenu::CreateGroupClip)); + mi->set_sensitive(TRUE); + mi->show(); + append(*mi); /* Set Clip */ mi = Gtk::manage(new Gtk::MenuItem(_("Set Cl_ip"), 1)); @@ -1867,6 +1874,10 @@ void ContextMenu::ReleaseMask(void) sp_selection_unset_mask(_desktop, false); } +void ContextMenu::CreateGroupClip(void) +{ + sp_selection_set_clipgroup(_desktop); +} void ContextMenu::SetClip(void) { diff --git a/src/interface.h b/src/interface.h index 215a3bfc9..a4eedf9db 100644 --- a/src/interface.h +++ b/src/interface.h @@ -187,6 +187,7 @@ class ContextMenu : public Gtk::Menu void SelectSameStrokeStyle(void); void SelectSameObjectType(void); void ItemCreateLink(void); + void CreateGroupClip(void); void SetMask(void); void ReleaseMask(void); void SetClip(void); diff --git a/src/selection-chemistry.cpp b/src/selection-chemistry.cpp index a350dd7a7..d2f6d692a 100644 --- a/src/selection-chemistry.cpp +++ b/src/selection-chemistry.cpp @@ -3661,6 +3661,118 @@ void sp_selection_create_bitmap_copy(SPDesktop *desktop) g_free(filepath); } +/* Creates a mask or clipPath from selection. + * What is a clip group? + * A clip group is a tangled mess of XML that allows an object inside a group + * to clip the entire group using a few s and generally irritating me. + */ + +void sp_selection_set_clipgroup(SPDesktop *desktop) +{ + if (desktop == NULL) { + return; + } + SPDocument* doc = sp_desktop_document(desktop); + Inkscape::XML::Document *xml_doc = doc->getReprDoc(); + + Inkscape::Selection *selection = sp_desktop_selection(desktop); + if (selection->isEmpty()) { + desktop->messageStack()->flash(Inkscape::WARNING_MESSAGE, _("Select object(s) to create clippath or mask from.")); + return; + } + + GSList const *l = const_cast(selection->reprList()); + + GSList *p = g_slist_copy(const_cast(l)); + + p = g_slist_sort(p, (GCompareFunc) sp_repr_compare_position); + + selection->clear(); + + gint topmost = (static_cast(g_slist_last(p)->data))->position(); + Inkscape::XML::Node *topmost_parent = (static_cast(g_slist_last(p)->data))->parent(); + + Inkscape::XML::Node *inner = xml_doc->createElement("svg:g"); + inner->setAttribute("inkscape:label", "Clip"); + + while (p) { + Inkscape::XML::Node *current = static_cast(p->data); + + if (current->parent() == topmost_parent) { + Inkscape::XML::Node *spnew = current->duplicate(xml_doc); + sp_repr_unparent(current); + inner->appendChild(spnew); + Inkscape::GC::release(spnew); + topmost --; // only reduce count for those items deleted from topmost_parent + } else { // move it to topmost_parent first + GSList *temp_clip = NULL; + + // At this point, current may already have no item, due to its being a clone whose original is already moved away + // So we copy it artificially calculating the transform from its repr->attr("transform") and the parent transform + gchar const *t_str = current->attribute("transform"); + Geom::Affine item_t(Geom::identity()); + if (t_str) + sp_svg_transform_read(t_str, &item_t); + item_t *= SP_ITEM(doc->getObjectByRepr(current->parent()))->i2doc_affine(); + // FIXME: when moving both clone and original from a transformed group (either by + // grouping into another parent, or by cut/paste) the transform from the original's + // parent becomes embedded into original itself, and this affects its clones. Fix + // this by remembering the transform diffs we write to each item into an array and + // then, if this is clone, looking up its original in that array and pre-multiplying + // it by the inverse of that original's transform diff. + + sp_selection_copy_one(current, item_t, &temp_clip, xml_doc); + sp_repr_unparent(current); + + // paste into topmost_parent (temporarily) + GSList *copied = sp_selection_paste_impl(doc, doc->getObjectByRepr(topmost_parent), &temp_clip); + if (temp_clip) g_slist_free(temp_clip); + if (copied) { // if success, + // take pasted object (now in topmost_parent) + Inkscape::XML::Node *in_topmost = static_cast(copied->data); + // make a copy + Inkscape::XML::Node *spnew = in_topmost->duplicate(xml_doc); + // remove pasted + sp_repr_unparent(in_topmost); + // put its copy into group + inner->appendChild(spnew); + Inkscape::GC::release(spnew); + g_slist_free(copied); + } + } + p = g_slist_remove(p, current); + } + + Inkscape::XML::Node *outer = xml_doc->createElement("svg:g"); + outer->appendChild(inner); + topmost_parent->appendChild(outer); + outer->setPosition(topmost + 1); + + Inkscape::XML::Node *clone = xml_doc->createElement("svg:use"); + clone->setAttribute("x", "0", false); + clone->setAttribute("y", "0", false); + clone->setAttribute("xlink:href", g_strdup_printf("#%s", inner->attribute("id")), false); + + clone->setAttribute("inkscape:transform-center-x", inner->attribute("inkscape:transform-center-x"), false); + clone->setAttribute("inkscape:transform-center-y", inner->attribute("inkscape:transform-center-y"), false); + + const Geom::Affine maskTransform(Geom::Affine::identity()); + GSList *templist = NULL; + + templist = g_slist_append(templist, clone); + // add the new clone to the top of the original's parent + gchar const *mask_id = SPClipPath::create(templist, doc, &maskTransform); + + g_slist_free(templist); + + outer->setAttribute("clip-path", g_strdup_printf("url(#%s)", mask_id)); + + Inkscape::GC::release(clone); + + selection->set(outer); + DocumentUndo::done(doc, SP_VERB_OBJECT_SET_CLIPPATH, _("Create Clip Group")); +} + /** * Creates a mask or clipPath from selection. * Two different modes: diff --git a/src/selection-chemistry.h b/src/selection-chemistry.h index d76a67a9d..baa530806 100644 --- a/src/selection-chemistry.h +++ b/src/selection-chemistry.h @@ -156,6 +156,7 @@ void sp_document_get_export_hints (SPDocument * doc, Glib::ustring &filename, fl void sp_selection_create_bitmap_copy (SPDesktop *desktop); +void sp_selection_set_clipgroup(SPDesktop *desktop); void sp_selection_set_mask(SPDesktop *desktop, bool apply_clip_path, bool apply_to_layer); void sp_selection_unset_mask(SPDesktop *desktop, bool apply_clip_path); diff --git a/src/ui/dialog/objects.cpp b/src/ui/dialog/objects.cpp index 85583a0e7..2d558daae 100644 --- a/src/ui/dialog/objects.cpp +++ b/src/ui/dialog/objects.cpp @@ -106,7 +106,7 @@ enum { BUTTON_LOCK_ALL, BUTTON_UNLOCK_ALL, BUTTON_SETCLIP, -// BUTTON_CLIPGROUP, + BUTTON_CLIPGROUP, // BUTTON_SETINVCLIP, BUTTON_UNSETCLIP, BUTTON_SETMASK, @@ -269,7 +269,7 @@ Gtk::MenuItem& ObjectsPanel::_addPopupItem( SPDesktop *desktop, unsigned int cod } if ( action ) { - label = action->name; + // label = action->name; } } } @@ -1257,6 +1257,10 @@ bool ObjectsPanel::_executeAction() _fireAction( SP_VERB_LAYER_UNLOCK_ALL ); } break; + case BUTTON_CLIPGROUP: + { + _fireAction ( SP_VERB_OBJECT_CREATE_CLIP_GROUP ); + } case BUTTON_SETCLIP: { _fireAction( SP_VERB_OBJECT_SET_CLIPPATH ); @@ -1935,8 +1939,8 @@ ObjectsPanel::ObjectsPanel() : _popupMenu.append(*Gtk::manage(new Gtk::SeparatorMenuItem())); _watching.push_back( &_addPopupItem( targetDesktop, SP_VERB_OBJECT_SET_CLIPPATH, 0, "Set Clip", (int)BUTTON_SETCLIP ) ); - //not implemented - //_watching.push_back( &_addPopupItem( targetDesktop, SP_VERB_OBJECT_CREATE_CLIP_GROUP, 0, "Create Clip Group", (int)BUTTON_CLIPGROUP ) ); + + _watching.push_back( &_addPopupItem( targetDesktop, SP_VERB_OBJECT_CREATE_CLIP_GROUP, 0, "Create Clip Group", (int)BUTTON_CLIPGROUP ) ); //will never be implemented //_watching.push_back( &_addPopupItem( targetDesktop, SP_VERB_OBJECT_SET_INVERSE_CLIPPATH, 0, "Set Inverse Clip", (int)BUTTON_SETINVCLIP ) ); diff --git a/src/verbs.cpp b/src/verbs.cpp index 73613ab9e..f0a49a81a 100644 --- a/src/verbs.cpp +++ b/src/verbs.cpp @@ -1568,6 +1568,9 @@ void ObjectVerb::perform( SPAction *action, void *data) case SP_VERB_OBJECT_SET_CLIPPATH: sp_selection_set_mask(dt, true, false); break; + case SP_VERB_OBJECT_CREATE_CLIP_GROUP: + sp_selection_set_clipgroup(dt); + break; case SP_VERB_OBJECT_EDIT_CLIPPATH: sp_selection_edit_clip_or_mask(dt, true); break; @@ -2717,6 +2720,8 @@ Verb *Verb::_base_verbs[] = { N_("Remove mask from selection"), NULL), new ObjectVerb(SP_VERB_OBJECT_SET_CLIPPATH, "ObjectSetClipPath", N_("_Set"), N_("Apply clipping path to selection (using the topmost object as clipping path)"), NULL), + new ObjectVerb(SP_VERB_OBJECT_CREATE_CLIP_GROUP, "ObjectCreateClipGroup", N_("Create Cl_ip Group"), + N_("Creates a clip group using the selected objects as a base"), NULL), new ObjectVerb(SP_VERB_OBJECT_EDIT_CLIPPATH, "ObjectEditClipPath", N_("_Edit"), N_("Edit clipping path"), INKSCAPE_ICON("path-clip-edit")), new ObjectVerb(SP_VERB_OBJECT_UNSET_CLIPPATH, "ObjectUnSetClipPath", N_("_Release"), diff --git a/src/verbs.h b/src/verbs.h index 821c9ee82..84d31fe42 100644 --- a/src/verbs.h +++ b/src/verbs.h @@ -175,6 +175,7 @@ enum { SP_VERB_OBJECT_EDIT_MASK, SP_VERB_OBJECT_UNSET_MASK, SP_VERB_OBJECT_SET_CLIPPATH, + SP_VERB_OBJECT_CREATE_CLIP_GROUP, SP_VERB_OBJECT_EDIT_CLIPPATH, SP_VERB_OBJECT_UNSET_CLIPPATH, /* Tag */ -- cgit v1.2.3 From fe12278d612a0c52bcbff2736f18d4e590410b71 Mon Sep 17 00:00:00 2001 From: "Liam P. White" Date: Tue, 22 Jul 2014 22:35:50 -0400 Subject: Duplicate LPE entries (bzr r13090.1.91) --- src/live_effects/effect.cpp | 5 ----- 1 file changed, 5 deletions(-) (limited to 'src') diff --git a/src/live_effects/effect.cpp b/src/live_effects/effect.cpp index 179759ed6..777d500e9 100644 --- a/src/live_effects/effect.cpp +++ b/src/live_effects/effect.cpp @@ -147,11 +147,6 @@ const Util::EnumData LPETypeData[] = { {SIMPLIFY, N_("Simplify"), "simplify"}, {LATTICE2, N_("Lattice Deformation 2"), "lattice2"}, {ENVELOPE_PERSPECTIVE, N_("Envelope-Perspective"), "envelope-perspective"}, - {SIMPLIFY, N_("Simplify"), "simplify"}, - {LATTICE2, N_("Lattice Deformation 2"), "lattice2"}, - // TRANSLATORS: "Envelope Perspective" should be equivalent to "perspective transformation" - {ENVELOPE_PERSPECTIVE, N_("Envelope Perspective"), "envelope-perspective"}, - {FILLET_CHAMFER, N_("Fillet/Chamfer"), "fillet-chamfer"}, }; const Util::EnumDataConverter LPETypeConverter(LPETypeData, sizeof(LPETypeData)/sizeof(*LPETypeData)); -- cgit v1.2.3 From 76244246733cc1f1f3874aa498ad75977ebc6cd7 Mon Sep 17 00:00:00 2001 From: "Liam P. White" Date: Tue, 22 Jul 2014 22:39:21 -0400 Subject: This file does not need executable permissions (bzr r13090.1.93) --- src/live_effects/lpe-jointype.h | 0 1 file changed, 0 insertions(+), 0 deletions(-) mode change 100755 => 100644 src/live_effects/lpe-jointype.h (limited to 'src') diff --git a/src/live_effects/lpe-jointype.h b/src/live_effects/lpe-jointype.h old mode 100755 new mode 100644 -- cgit v1.2.3 From 3a6ed95f3fa5921c78b24f9ae73df7d442827571 Mon Sep 17 00:00:00 2001 From: "Liam P. White" Date: Wed, 23 Jul 2014 16:16:43 -0400 Subject: Refactoring of linejoin code (bzr r13090.1.94) --- src/live_effects/pathoutlineprovider.cpp | 551 +++++++++++++++---------------- src/live_effects/pathoutlineprovider.h | 33 +- 2 files changed, 283 insertions(+), 301 deletions(-) (limited to 'src') diff --git a/src/live_effects/pathoutlineprovider.cpp b/src/live_effects/pathoutlineprovider.cpp index d6e0ce7ea..482f1f5e0 100644 --- a/src/live_effects/pathoutlineprovider.cpp +++ b/src/live_effects/pathoutlineprovider.cpp @@ -125,8 +125,7 @@ Geom::CubicBezier sbasis_to_cubicbezier(Geom::D2 const & sbasis_in return Geom::CubicBezier( temp ); } -static boost::optional intersection_point( Geom::Point const & origin_a, Geom::Point const & vector_a, - Geom::Point const & origin_b, Geom::Point const & vector_b) +static boost::optional intersection_point(Geom::Point const & origin_a, Geom::Point const & vector_a, Geom::Point const & origin_b, Geom::Point const & vector_b) { Geom::Coord denom = cross(vector_b, vector_a); if (!Geom::are_near(denom,0.)) { @@ -135,13 +134,16 @@ static boost::optional intersection_point( Geom::Point const & orig } return boost::none; } -} + +} // namespace Geom namespace Outline { typedef Geom::D2 D2SB; typedef Geom::Piecewise PWD2; +// UTILITY + unsigned bezierOrder (const Geom::Curve* curve_in) { using namespace Geom; @@ -151,25 +153,28 @@ unsigned bezierOrder (const Geom::Curve* curve_in) return 0; } -//returns true if the angle formed by the curves and their handles -//is >180 clockwise, otherwise false. +/** + * @return true if the angle formed by the curves and their handles is greater than 180 degrees clockwise, otherwise false. + */ bool outside_angle (const Geom::Curve& cbc1, const Geom::Curve& cbc2) { Geom::Point start_point; Geom::Point cross_point = cbc1.finalPoint(); Geom::Point end_point; - //assert(cbc1.finalPoint() == cbc2.initialPoint()); - //short circuiting? - if (cbc1.finalPoint() != cbc2.initialPoint()) { - printf("erk! Line %d, File %s\n", __LINE__, __FILE__); + if (cross_point != cbc2.initialPoint()) { + g_warning("Non-contiguous path in Outline::outside_angle()"); return false; } - //let's try: Geom::CubicBezier cubicBezier = Geom::sbasis_to_cubicbezier(cbc1.toSBasis()); start_point = cubicBezier [2]; - //stupid thing Inkscape does: + + /* + * Because the node editor does not yet support true quadratics, paths are converted to + * cubic beziers in the node tool with degenerate handles on one side. + */ + if (are_near(start_point, cross_point, 0.0000001)) { start_point = cubicBezier [1]; } @@ -178,9 +183,11 @@ bool outside_angle (const Geom::Curve& cbc1, const Geom::Curve& cbc2) if (are_near(end_point, cross_point, 0.0000001)) { end_point = cubicBezier [2]; } - //got our three points, now let's see what their clockwise angle is - //Much credit to Wikipedia for the following ( http://en.wikipedia.org/wiki/Graham_scan ) + // got our three points, now let's see what their clockwise angle is + + // Definition of a Graham scan + /******************************************************************** # Three points are a counter-clockwise turn if ccw > 0, clockwise if # ccw < 0, and collinear if ccw = 0 because ccw is a determinant that @@ -191,27 +198,90 @@ bool outside_angle (const Geom::Curve& cbc1, const Geom::Curve& cbc2) double ccw = ( (cross_point.x() - start_point.x()) * (end_point.y() - start_point.y()) ) - ( (cross_point.y() - start_point.y()) * (end_point.x() - start_point.x()) ); - if (ccw > 0) return true; - return false; + return ccw > 0; } -void extrapolate_curves(Geom::Path& path_builder, Geom::Curve* cbc1, Geom::Curve* cbc2, Geom::Point endPt, - double miter_limit, double line_width, bool outside = false) -{ - bool lineProblem = (dynamic_cast *>(cbc1)) || (dynamic_cast *>(cbc2)); - if ( outside && !lineProblem ) { - Geom::Path pth; - pth.append(*cbc1); +// LINE JOINS - Geom::Point tang1 = Geom::unitTangentAt(Geom::reverse(pth.toPwSb()[0]), 0.); +typedef Geom::BezierCurveN<1u> BezierLine; - pth = Geom::Path(); - pth.append( *cbc2 ); - Geom::Point tang2 = Geom::unitTangentAt(pth.toPwSb()[0], 0); +/** + * Removes the crossings on an interior join. + * @param path_builder Contains the incoming segment; result is appended to this + * @param outgoing The outgoing segment + */ +void joinInside(Geom::Path& path_builder, Geom::Curve const& outgoing) { + Geom::Curve const& incoming = path_builder.back(); + + // Using Geom::crossings to find intersections between two curves + Geom::Crossings cross = Geom::crossings(incoming, outgoing); + if (!cross.empty()) { + // Crossings found, create the join + Geom::CubicBezier cubic = Geom::sbasis_to_cubicbezier(incoming.toSBasis()); + cubic = cubic.subdivide(cross[0].ta).first; + // erase the last segment, as we're going to overwrite it now + path_builder.erase_last(); + path_builder.append(cubic, Geom::Path::STITCH_DISCONTINUOUS); + cubic = Geom::sbasis_to_cubicbezier(outgoing.toSBasis()); + cubic = cubic.subdivide(cross[0].tb).second; + path_builder.append(cubic, Geom::Path::STITCH_DISCONTINUOUS); + } else { + // No crossings occurred, or Geom::crossings() failed; default to bevel + if (Geom::are_near(incoming.finalPoint(), outgoing.initialPoint())) { + path_builder.appendNew(outgoing.initialPoint()); + } else { + path_builder.setFinal(outgoing.initialPoint()); + } + } +} + +/** + * Try to create a miter join. Falls back to bevel if no miter can be created. + * @param path_builder Path to append curves to; back() is the incoming curve + * @param outgoing Outgoing curve. + * @param miter_limit When mitering, don't exceed this length + * @param line_width The thickness of the line. + */ +void miter_curves(Geom::Path& path_builder, Geom::Curve const& outgoing, double miter_limit, double line_width) { + using namespace Geom; + Curve const& incoming = path_builder.back(); + Point tang1 = unitTangentAt(Geom::reverse(incoming.toSBasis()), 0.); + Point tang2 = unitTangentAt(outgoing.toSBasis(), 0); + + boost::optional p = intersection_point (incoming.finalPoint(), tang1, outgoing.initialPoint(), tang2); + if (p) { + // check size of miter + Point point_on_path = incoming.finalPoint() - rot90(tang1) * line_width; + Coord len = distance(*p, point_on_path); + if (len <= miter_limit) { + // miter OK + path_builder.appendNew(*p); + } + } + path_builder.appendNew(outgoing.initialPoint()); +} - Geom::Circle circle1 = Geom::touching_circle(Geom::reverse(cbc1->toSBasis()), 0.); - Geom::Circle circle2 = Geom::touching_circle(cbc2->toSBasis(), 0); +/** + * Smoothly extrapolate curves along a circular route. Falls back to miter if necessary. + * @param path_builder Path to append curves to; back() is the incoming curve + * @param outgoing Outgoing curve. + * @param miter_limit When mitering, don't exceed this length + * @param line_width The thickness of the line. Used for miter fallback. + */ +void extrapolate_curves(Geom::Path& path_builder, Geom::Curve const& outgoing, double miter_limit, double line_width) { + Geom::Curve const& incoming = path_builder.back(); + Geom::Point endPt = outgoing.initialPoint(); + + // The method used when extrapolating curves fails to work when either side of the join to be extrapolated + // is a line segment. When this situation is encountered, fall back to a regular miter join. + bool lineProblem = (dynamic_cast(&incoming)) || (dynamic_cast(&outgoing)); + if (lineProblem == false) { + // Geom::Point tang1 = Geom::unitTangentAt(Geom::reverse(incoming.toSBasis()), 0.); + Geom::Point tang2 = Geom::unitTangentAt(outgoing.toSBasis(), 0); + + Geom::Circle circle1 = Geom::touching_circle(Geom::reverse(incoming.toSBasis()), 0.); + Geom::Circle circle2 = Geom::touching_circle(outgoing.toSBasis(), 0); Geom::Point points[2]; int solutions = Geom::circle_circle_intersection(circle1, circle2, points[0], points[1]); @@ -225,239 +295,161 @@ void extrapolate_curves(Geom::Path& path_builder, Geom::Curve* cbc1, Geom::Curve sol = points[0]; } else { // both points are good, choose nearest - sol = ( distanceSq(endPt, points[0]) < distanceSq(endPt, points[1]) ) ? - points[0] : points[1]; + sol = ( distanceSq(endPt, points[0]) < distanceSq(endPt, points[1]) ) ? points[0] : points[1]; } - Geom::EllipticalArc *arc0 = circle1.arc(cbc1->finalPoint(), 0.5*(cbc1->finalPoint()+sol), sol, true); + + Geom::EllipticalArc *arc0 = circle1.arc(incoming.finalPoint(), 0.5*(incoming.finalPoint()+sol), sol, true); Geom::EllipticalArc *arc1 = circle2.arc(sol, 0.5*(sol+endPt), endPt, true); try { if (arc0) { path_builder.append (arc0->toSBasis()); delete arc0; arc0 = NULL; + } else { + throw std::exception(); } if (arc1) { path_builder.append (arc1->toSBasis()); delete arc1; arc1 = NULL; + } else { + throw std::exception(); } - } catch (std::exception & ex) { - printf("Exception occured, probably NaN or infinite valued points: %s\n", ex.what()); + + } catch (std::exception const & ex) { + g_warning("Error extrapolating line join: %s\n", ex.what()); path_builder.appendNew(endPt); } } else { - boost::optional p = intersection_point (cbc1->finalPoint(), tang1, - cbc2->initialPoint(), tang2); - if (p) { - //check size of miter - Geom::Point point_on_path = cbc1->finalPoint() - rot90(tang1) * line_width; - Geom::Coord len = distance(*p, point_on_path); - if (len <= miter_limit) { - // miter OK - path_builder.appendNew (*p); - } - } - path_builder.appendNew (endPt); - } - if (cbc1->finalPoint() != cbc2->initialPoint()) { - path_builder.appendNew(cbc2->initialPoint()); - } - path_builder.append(*cbc2); - } - if ( outside && lineProblem ) { - Geom::Path pth; - pth.append(*cbc1); - Geom::Point tang1 = Geom::unitTangentAt(Geom::reverse(pth.toPwSb()[0]), 0.); - pth = Geom::Path(); - pth.append( *cbc2 ); - Geom::Point tang2 = Geom::unitTangentAt(pth.toPwSb()[0], 0); - - boost::optional p = intersection_point (cbc1->finalPoint(), tang1, - cbc2->initialPoint(), tang2); - if (p) { - //check size of miter - Geom::Point point_on_path = cbc1->finalPoint() - rot90(tang1) * line_width; - Geom::Coord len = distance(*p, point_on_path); - if (len <= miter_limit) { - // miter OK - path_builder.appendNew (*p); - } - } - path_builder.appendNew (endPt); - if (cbc1->finalPoint() != cbc2->initialPoint()) { - path_builder.appendNew(cbc2->initialPoint()); - } - path_builder.append(*cbc2); - } - if ( !outside ) { - /*path_builder.appendNew (endPt);*/ - Geom::Crossings cross = Geom::crossings(*cbc1, *cbc2); - if (!cross.empty()) { - path_builder.erase_last(); - Geom::CubicBezier cubic = Geom::sbasis_to_cubicbezier(cbc1->toSBasis()); - cubic = cubic.subdivide(cross[0].ta).first; - path_builder.append(cubic, Geom::Path::STITCH_DISCONTINUOUS); - cubic = Geom::sbasis_to_cubicbezier(cbc2->toSBasis()); - cubic = cubic.subdivide(cross[0].tb).second; - path_builder.append(cubic, Geom::Path::STITCH_DISCONTINUOUS); - } else { - if (Geom::distance(path_builder.finalPoint(), cbc2->initialPoint()) > 0.0000001) { - path_builder.appendNew(cbc2->initialPoint()); - } else { - path_builder.setFinal(cbc2->initialPoint()); - } - path_builder.append(*cbc2); + // 1 or no solutions found, default to miter + miter_curves(path_builder, outgoing, miter_limit, line_width); } + } else { + // Line segments exist + miter_curves(path_builder, outgoing, miter_limit, line_width); } } -void reflect_curves(Geom::Path& path_builder, Geom::Curve* cbc1, Geom::Curve* cbc2, Geom::Point endPt, - double miter_limit, double line_width, bool outside = false) +/** + * Extrapolate curves by reflecting them along the line that would be given by beveling the join. + * @param path_builder Path to append curves to; back() is the incoming curve + * @param outgoing Outgoing curve. + * @param miter_limit When mitering, don't exceed this length + * @param line_width The thickness of the line. Used for miter fallback. + */ +void reflect_curves(Geom::Path& path_builder, Geom::Curve const& outgoing, double miter_limit, double line_width) { - //the most important work for the reflected join is done here - - //determine where we are in the path. If we're on the inside, ignore - //and just lineTo. On the outside, we'll do a little reflection magic :) - Geom::Crossings cross; + using namespace Geom; + Curve const& incoming = path_builder.back(); + // On the outside, we'll take the incoming curve, the outgoing curve, and + // reflect them over the line formed by taking the unit tangent vector at times + // 0 and 1, respectively, rotated by 90 degrees. + Crossings cross; + + // reflect curves along the line that would be given by beveling the join + Point tang1 = unitTangentAt(reverse(incoming.toSBasis()), 0.); + D2SB newcurve1 = incoming.toSBasis() * reflection(-rot90(tang1), incoming.finalPoint()); + CubicBezier bzr1 = sbasis_to_cubicbezier(reverse(newcurve1)); + + Point tang2 = Geom::unitTangentAt(outgoing.toSBasis(), 0.); + D2SB newcurve2 = outgoing.toSBasis() * reflection(-rot90(tang2), outgoing.initialPoint()); + CubicBezier bzr2 = sbasis_to_cubicbezier(reverse(newcurve2)); + + cross = crossings(bzr1, bzr2); + if (cross.empty()) { + // paths don't cross, fall back to miter + miter_curves(path_builder, outgoing, miter_limit, line_width); + } else { + // reflected join + std::pair sub1 = bzr1.subdivide(cross[0].ta); + std::pair sub2 = bzr2.subdivide(cross[0].tb); + + // TODO it seems as if a bug in 2geom sometimes doesn't catch the first + // crossing of paths, but the second instead; but only sometimes. + path_builder.appendNew (sub1.first[1], sub1.first[2], sub2.second[0]); + path_builder.appendNew (sub2.second[1], sub2.second[2], outgoing.initialPoint()); + } +} - if (outside) { - Geom::Path pth; - pth.append(*cbc1); - - Geom::Point tang1 = Geom::unitTangentAt(Geom::reverse(pth.toPwSb()[0]), 0.); - - //reflect curves along the bevel - D2SB newcurve1 = pth.toPwSb()[0] * - Geom::reflection ( -Geom::rot90(tang1) , - cbc1->finalPoint() ); - - Geom::CubicBezier bzr1 = sbasis_to_cubicbezier(Geom::reverse(newcurve1)); - - pth = Geom::Path(); - pth.append( *cbc2 ); - Geom::Point tang2 = Geom::unitTangentAt(pth.toPwSb()[0], 0); - - D2SB newcurve2 = pth.toPwSb()[0] * - Geom::reflection ( -Geom::rot90(tang2) , - cbc2->initialPoint() ); - Geom::CubicBezier bzr2 = sbasis_to_cubicbezier(Geom::reverse(newcurve2)); - - cross = Geom::crossings(bzr1, bzr2); - if ( cross.empty() ) { - //curves didn't cross; default to miter - boost::optional p = intersection_point (cbc1->finalPoint(), tang1, - cbc2->initialPoint(), tang2); - if (p) { - //check size of miter - Geom::Point point_on_path = cbc1->finalPoint() - rot90(tang1) * line_width; - Geom::Coord len = distance(*p, point_on_path); - if (len <= miter_limit) { - // miter OK - path_builder.appendNew (*p); - } - } - //bevel - path_builder.appendNew( endPt ); - } else { - //join - std::pair sub1 = bzr1.subdivide(cross[0].ta); - std::pair sub2 = bzr2.subdivide(cross[0].tb); +// Ideal function pointer we want to pass +typedef void JoinFunc(Geom::Path& /*path_builder*/, Geom::Curve const& /*outgoing*/, double /*miter_limit*/, double /*line_width*/); - //@TODO joins have a strange tendency to cross themselves twice. Check this. +/** + * Helper function for repeated logic in outlineHalf. + */ +static void outlineHelper(Geom::Path& path_builder, Geom::PathVector* path_vec, bool outside, double width, double miter, JoinFunc func) { + Geom::Curve * cbc2 = path_vec->front()[0].duplicate(); - //sections commented out are for general stability - path_builder.appendNew (sub1.first[1], sub1.first[2], /*sub1.first[3]*/ sub2.second[0] ); - path_builder.appendNew (sub2.second[1], sub2.second[2], /*sub2.second[3]*/ endPt ); - } - if (cbc1->finalPoint() != cbc2->initialPoint()) { - path_builder.appendNew(cbc2->initialPoint()); - } - path_builder.append(*cbc2); + if (outside) { + func(path_builder, *cbc2, miter, width); } else { - //probably on the inside of the corner - /*path_builder.appendNew ( endPt );*/ - cross = Geom::crossings(*cbc1, *cbc2); - if (!cross.empty()) { - path_builder.erase_last(); - Geom::CubicBezier cubic = Geom::sbasis_to_cubicbezier(cbc1->toSBasis()); - cubic = cubic.subdivide(cross[0].ta).first; - path_builder.append(cubic, Geom::Path::STITCH_DISCONTINUOUS); - cubic = Geom::sbasis_to_cubicbezier(cbc2->toSBasis()); - cubic = cubic.subdivide(cross[0].tb).second; - path_builder.append(cubic, Geom::Path::STITCH_DISCONTINUOUS); - } else { - if (Geom::distance(path_builder.finalPoint(), cbc2->initialPoint()) > 0.0000001) { - path_builder.appendNew(cbc2->initialPoint()); - } else { - path_builder.setFinal(cbc2->initialPoint()); - } - path_builder.append(*cbc2); - } + joinInside(path_builder, *cbc2); + } + + // store it + Geom::Path temp_path = path_vec->front(); + if (!outside) { + // erase the first segment since the inside join code already appended it + temp_path.erase(temp_path.begin()); + } + + if (temp_path.initialPoint() != path_builder.finalPoint()) { + temp_path.setInitial(path_builder.finalPoint()); } + + path_builder.append(temp_path); + + delete cbc2; } -/** @brief Converts a path to one half of an outline. -* path_in: The input path to use. (To create the other side use path_in.reverse() ) -* line_width: the line width to use (usually you want to divide this by 2) -* miter_limit: the miter parameter -* extrapolate: whether the join should be extrapolated instead of reflected -*/ -Geom::Path doAdvHalfOutline(const Geom::Path& path_in, double line_width, double miter_limit, bool extrapolate = false) -{ - // NOTE: it is important to notice the distinction between a Geom::Path and a livarot Path here! +/** + * Offsets exactly one half of a bezier spline (path). + * @param path_in The input path to use. (To create the other side use path_in.reverse() ) + * @param line_width the line width to use (usually you want to divide this by 2) + * @param miter_limit the miter parameter + * @param func Join function to apply at each join. + */ + +Geom::Path outlineHalf(const Geom::Path& path_in, double line_width, double miter_limit, JoinFunc func) { + // NOTE: it is important to notice the distinction between a Geom::Path and a livarot ::Path here! // if you do not see "Geom::" there is a different function set! Geom::PathVector pv = split_at_cusps(path_in); - Path to_outline; - Path outlined_result; - - Geom::Path path_builder = Geom::Path(); //the path to store the result in - Geom::PathVector * path_vec; //needed because livarot returns a goddamn pointer + ::Path to_outline; + ::Path outlined_result; - const unsigned k = pv.size(); + Geom::Path path_builder = Geom::Path(); // the path to store the result in + Geom::PathVector* path_vec; // needed because livarot returns a pointer (TODO make this not a pointer) - for (unsigned u = 0; u < k; u+=2) { + // Do two curves at a time for efficiency, since the join function needs to know the outgoing curve as well + const size_t k = pv.size(); + for (size_t u = 0; u < k; u += 2) { to_outline = Path(); outlined_result = Path(); - to_outline.LoadPath(pv[u], Geom::Affine(), false, false); + to_outline.LoadPath(pv[u], Geom::identity(), false, false); to_outline.OutsideOutline(&outlined_result, line_width / 2, join_straight, butt_straight, 10); - //now a curve has been outside outlined and loaded into outlined_result + // now a curve has been outside outlined and loaded into outlined_result - //get the Geom::Path + // get the Geom::Path path_vec = outlined_result.MakePathVector(); - //thing to do on the first run through + // on the first run through, there is no join if (u == 0) { - //I could use the pv->operator[] (0) notation but that looks terrible - path_builder.start( (*path_vec)[0].initialPoint() ); - path_builder.append( (*path_vec)[0] ); + path_builder.start(path_vec->front().initialPoint()); + path_builder.append(path_vec->front()); } else { - //get the curves ready for the operation - Geom::Curve * cbc1 = path_builder[path_builder.size() - 1].duplicate(); - Geom::Curve * cbc2 = (*path_vec)[0] [0].duplicate(); - - //do the reflection/extrapolation: - if (extrapolate) { - extrapolate_curves(path_builder, cbc1, cbc2, (*path_vec)[0].initialPoint(), miter_limit, line_width, - outside_angle ( pv[u - 1] [pv[u - 1].size() - 1], pv[u] [0] )); - } else { - reflect_curves (path_builder, cbc1, cbc2, (*path_vec)[0].initialPoint(), miter_limit, line_width, - outside_angle ( pv[u - 1] [pv[u - 1].size() - 1], pv[u] [0] )); - } - //store it - Geom::Path temp_path = (*path_vec)[0]; - //erase the first segment since the join code already appended it - temp_path.erase(temp_path.begin()); - - path_builder.append( temp_path ); + outlineHelper(path_builder, path_vec, outside_angle(pv[u-1][pv[u-1].size()-1], pv[u][0]), line_width, miter_limit, func); } - //outline the next segment, but don't store it yet - if (path_vec) delete path_vec; + // outline the next segment, but don't store it yet + if (path_vec) + delete path_vec; + path_vec = NULL; + // odd number of paths if (u < k - 1) { outlined_result = Path(); to_outline = Path(); @@ -466,29 +458,11 @@ Geom::Path doAdvHalfOutline(const Geom::Path& path_in, double line_width, double to_outline.OutsideOutline(&outlined_result, line_width / 2, join_straight, butt_straight, 10); path_vec = outlined_result.MakePathVector(); + outlineHelper(path_builder, path_vec, outside_angle(pv[u][pv[u].size()-1], pv[u+1][0]), line_width, miter_limit, func); - //get the curves ready for the operation - Geom::Curve * cbc1 = path_builder[path_builder.size() - 1].duplicate(); - Geom::Curve * cbc2 = (*path_vec)[0] [0].duplicate(); - - //do the reflection/extrapolation: - if (extrapolate) { - extrapolate_curves(path_builder, cbc1, cbc2, (*path_vec)[0].initialPoint(), miter_limit, line_width, - outside_angle ( pv[u] [pv[u].size()-1], pv[u+1] [0] )); - } else { - reflect_curves (path_builder, cbc1, cbc2, (*path_vec)[0].initialPoint(), miter_limit, line_width, - outside_angle ( pv[u] [pv[u].size()-1], pv[u+1] [0] )); - } - - //Now we can store it. - Geom::Path temp_path = (*path_vec)[0]; - temp_path.erase(temp_path.begin()); - - path_builder.append( temp_path ); - - if (cbc1) delete cbc1; - if (cbc2) delete cbc2; - if (path_vec) delete path_vec; + if (path_vec) + delete path_vec; + path_vec = NULL; } } @@ -497,7 +471,7 @@ Geom::Path doAdvHalfOutline(const Geom::Path& path_in, double line_width, double Geom::Curve * cbc2; if ( path_in[path_in.size()].isDegenerate() ) { - //handle case for last segment curved + // handle case for last segment curved outlined_result = Path(); to_outline = Path(); @@ -509,11 +483,12 @@ Geom::Path doAdvHalfOutline(const Geom::Path& path_in, double line_width, double path_vec = outlined_result.MakePathVector(); cbc1 = path_builder[path_builder.size() - 1].duplicate(); - cbc2 = (*path_vec)[0] [0].duplicate(); + cbc2 = path_vec->front()[0].duplicate(); delete path_vec; } else { - //handle case for last segment straight (since the path doesn't actually give us access to it) + // handle case for last segment straight + // since the path doesn't actually give us access to it, we'll do it ourselves outlined_result = Path(); to_outline = Path(); @@ -527,17 +502,10 @@ Geom::Path doAdvHalfOutline(const Geom::Path& path_in, double line_width, double cbc1 = path_builder[path_builder.size() - 1].duplicate(); cbc2 = (*path_vec)[0] [0].duplicate(); - //append the closing segment - - if (extrapolate) { - extrapolate_curves(path_builder, cbc1, cbc2, cbc2->initialPoint(), miter_limit, line_width, - outside_angle ( path_in[path_in.size() - 1], oneCurve [0] )); - } else { - reflect_curves (path_builder, cbc1, cbc2, cbc2->initialPoint(), miter_limit, line_width, - outside_angle ( path_in[path_in.size() - 1], oneCurve [0] )); - } - - delete cbc1; cbc1 = cbc2->duplicate(); + outlineHelper(path_builder, path_vec, outside_angle(path_in[path_in.size()-1], oneCurve[0]), line_width, miter_limit, func); + + delete cbc1; + cbc1 = cbc2->duplicate(); delete path_vec; oneCurve = Geom::Path(); oneCurve.append(path_in[0]); @@ -550,32 +518,35 @@ Geom::Path doAdvHalfOutline(const Geom::Path& path_in, double line_width, double delete path_vec; } - Geom::Path temporary; //just an accessory path, we won't need it for long + Geom::Path temporary; temporary.append(*cbc1); - const Geom::Curve& prev_curve = path_in[path_in.size()].isDegenerate() ? path_in[path_in.size() - 1] : - path_in[path_in.size()]; - - if (extrapolate) { - extrapolate_curves(temporary, cbc1, cbc2, cbc2->initialPoint(), miter_limit, line_width, - outside_angle ( prev_curve, path_in [0] )); - } else { - reflect_curves (temporary, cbc1, cbc2, cbc2->initialPoint(), miter_limit, line_width, - outside_angle ( prev_curve, path_in [0] )); - } - //extract the appended curves - //if (temporary[temporary.size()].initialPoint() != path_builder[0].initialPoint()) { - path_builder.erase(path_builder.begin()); - /*} else { - temporary.erase_last(); - }*/ - path_builder.erase_last(); - if (Geom::distance(path_builder.finalPoint(), temporary.initialPoint()) > 0.0000001) { - path_builder.appendNew(temporary.initialPoint()); + Geom::Curve const & prev_curve = path_in[path_in.size()].isDegenerate() ? path_in[path_in.size() - 1] : path_in[path_in.size()]; + Geom::Path isStraight; + isStraight.append(prev_curve); + isStraight.append(path_in[0]); + // does closing path require a join? + if (Geom::split_at_cusps(isStraight).size() > 1) { + bool outside = outside_angle(prev_curve, path_in[0]); + if (outside) { + func(temporary, *cbc2, miter_limit, line_width); + } else { + joinInside(temporary, *cbc2); + path_builder.erase(path_builder.begin()); + } + + // extract the appended curves + path_builder.erase_last(); + if (Geom::are_near(path_builder.finalPoint(), temporary.initialPoint())) { + path_builder.setFinal(temporary.initialPoint()); + } else { + path_builder.appendNew(temporary.initialPoint()); + } + path_builder.append(temporary); } else { - path_builder.setFinal(temporary.initialPoint()); + // closing path does not require a join + path_builder.setFinal(path_builder.initialPoint()); } - path_builder.append(temporary); path_builder.close(); if (cbc1) delete cbc1; @@ -585,8 +556,7 @@ Geom::Path doAdvHalfOutline(const Geom::Path& path_in, double line_width, double return path_builder; } -Geom::PathVector outlinePath(const Geom::PathVector& path_in, double line_width, LineJoinType join, - ButtTypeMod butt, double miter_lim, bool extrapolate, double start_lean, double end_lean) +Geom::PathVector outlinePath(const Geom::PathVector& path_in, double line_width, LineJoinType join, ButtTypeMod butt, double miter_lim, bool extrapolate, double start_lean, double end_lean) { Geom::PathVector path_out; @@ -594,16 +564,14 @@ Geom::PathVector outlinePath(const Geom::PathVector& path_in, double line_width, for (unsigned i = 0; i < pv_size; i++) { if (path_in[i].size() > 1) { - //since you've made it this far, hopefully all this is obvious :P Geom::Path with_direction; Geom::Path against_direction; - - with_direction = Outline::doAdvHalfOutline( path_in[i], -line_width, miter_lim, extrapolate ); - against_direction = Outline::doAdvHalfOutline( path_in[i].reverse(), -line_width, miter_lim, extrapolate ); + + with_direction = Outline::outlineHalf(path_in[i], -line_width, miter_lim, extrapolate ? extrapolate_curves : reflect_curves); + against_direction = Outline::outlineHalf(path_in[i].reverse(), -line_width, miter_lim, extrapolate ? extrapolate_curves : reflect_curves); Geom::PathBuilder pb; - //add in the...do I really need to say this? pb.moveTo(with_direction.initialPoint()); pb.append(with_direction); @@ -724,8 +692,7 @@ Geom::PathVector outlinePath(const Geom::PathVector& path_in, double line_width, return path_out; } -Geom::PathVector PathVectorOutline(Geom::PathVector const & path_in, double line_width, ButtTypeMod linecap_type, - LineJoinType linejoin_type, double miter_limit, double start_lean, double end_lean) +Geom::PathVector PathVectorOutline(Geom::PathVector const & path_in, double line_width, ButtTypeMod linecap_type, LineJoinType linejoin_type, double miter_limit, double start_lean, double end_lean) { std::vector path_out = std::vector(); if (path_in.empty()) { @@ -761,21 +728,21 @@ Geom::PathVector PathVectorOutline(Geom::PathVector const & path_in, double line break; } } - if (linejoin_type <= 2) { + if (linejoin_type <= LINEJOIN_POINTY) { p.Outline(&outlinepath, line_width / 2, static_cast(linejoin_type), original_butt, miter_lim); - //fix memory leak + // fix memory leak std::vector *pv_p = outlinepath.MakePathVector(); path_out = *pv_p; delete pv_p; - } else if (linejoin_type == 3) { - //reflected arc join + } else if (linejoin_type == LINEJOIN_REFLECTED) { + // reflected arc join path_out = outlinePath(path_in, line_width, static_cast(linejoin_type), linecap_type , miter_lim, false, start_lean, end_lean); - } else if (linejoin_type == 4) { - //extrapolated arc join + } else if (linejoin_type == LINEJOIN_EXTRAPOLATED) { + // extrapolated arc join path_out = outlinePath(path_in, line_width, LINEJOIN_STRAIGHT, linecap_type, miter_lim, true, start_lean, end_lean); } @@ -800,16 +767,14 @@ Geom::Path PathOutsideOutline(Geom::Path const & path_in, double line_width, Lin path_outline.OutsideOutline(&path_tangent, line_width / 2, static_cast(linejoin_type), butt_straight, miter_lim); pathvec = path_tangent.MakePathVector(); - path_out = pathvec[0]/* deref pointer */[0]/*actual object ref*/; + path_out = pathvec->front(); delete pathvec; return path_out; } else if (linejoin_type == LINEJOIN_REFLECTED) { - //reflected half outline - path_out = doAdvHalfOutline(path_in, line_width, miter_lim, false); + path_out = outlineHalf(path_in, line_width, miter_lim, reflect_curves); return path_out; } else if (linejoin_type == LINEJOIN_EXTRAPOLATED) { - //what the hell do you think this is? :P - path_out = doAdvHalfOutline(path_in, line_width, miter_lim, true); + path_out = outlineHalf(path_in, line_width, miter_lim, extrapolate_curves); return path_out; } #undef miter_lim @@ -827,4 +792,4 @@ Geom::Path PathOutsideOutline(Geom::Path const & path_in, double line_width, Lin fill-column:99 End: */ -// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 : +// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8 : diff --git a/src/live_effects/pathoutlineprovider.h b/src/live_effects/pathoutlineprovider.h index 272c93a49..c17584be2 100644 --- a/src/live_effects/pathoutlineprovider.h +++ b/src/live_effects/pathoutlineprovider.h @@ -1,5 +1,13 @@ -#ifndef _SEEN_PATH_OUTLINE_H -#define _SEEN_PATH_OUTLINE_H +#ifndef SEEN_PATH_OUTLINE_H +#define SEEN_PATH_OUTLINE_H + +/* Author: + * Liam P. White + * + * Copyright (C) 2014 Author + * + * Released under GNU GPL, read the file 'COPYING' for more information + */ #include #include @@ -18,10 +26,11 @@ enum ButtTypeMod { BUTT_POINTY, BUTT_LEANED }; + namespace Geom { - Geom::CubicBezier sbasis_to_cubicbezier(Geom::D2 const & sbasis_in); - std::vector split_at_cusps(const Geom::Path& in); + Geom::CubicBezier sbasis_to_cubicbezier(Geom::D2 const & sbasis_in); + std::vector split_at_cusps(const Geom::Path& in); } namespace Outline @@ -29,10 +38,18 @@ namespace Outline unsigned bezierOrder (const Geom::Curve* curve_in); std::vector PathVectorOutline(std::vector const & path_in, double line_width, ButtTypeMod linecap_type, LineJoinType linejoin_type, double miter_limit, double start_lean = 0, double end_lean = 0); - - /*Geom::PathVector outlinePath(const Geom::PathVector& path_in, double line_width, LineJoinType join, - ButtTypeMod butt, double miter_lim, bool extrapolate = false);*/ Geom::Path PathOutsideOutline(Geom::Path const & path_in, double line_width, LineJoinType linejoin_type, double miter_limit); } -#endif // _SEEN_PATH_OUTLINE_H +#endif // SEEN_PATH_OUTLINE_H + +/* + 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 : -- cgit v1.2.3 From b9a8b72cd7bb5c6dbfe5118f15fa870cff8eb4c5 Mon Sep 17 00:00:00 2001 From: "Liam P. White" Date: Thu, 31 Jul 2014 14:53:10 -0400 Subject: I'm an idiot (bzr r13090.1.97) --- src/knotholder.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/knotholder.cpp b/src/knotholder.cpp index aea983cbb..9890647e1 100644 --- a/src/knotholder.cpp +++ b/src/knotholder.cpp @@ -213,7 +213,7 @@ KnotHolder::knot_ungrabbed_handler(SPKnot */*knot*/, guint) if (dynamic_cast (object)) { // This writes all parameters to SVG. Is this sufficiently efficient or should we only // write the ones that were changed? - SPLPEItem * lpeitem = SP_LPE_ITEM(this->item); + SPLPEItem * lpeitem = SP_LPE_ITEM(object); if (lpeitem) { Inkscape::LivePathEffect::Effect *lpe = lpeitem->getCurrentLPE(); if (lpe) { -- cgit v1.2.3 From d59ab0cc036239f5e2f6040b2f439ba7b55af4c3 Mon Sep 17 00:00:00 2001 From: "Liam P. White" Date: Fri, 8 Aug 2014 09:47:46 -0400 Subject: Ponyscape feature: finish pen drawing on context switch (bzr r13090.1.101) --- src/ui/tools/pen-tool.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/ui/tools/pen-tool.cpp b/src/ui/tools/pen-tool.cpp index 9a73d497f..318591df5 100644 --- a/src/ui/tools/pen-tool.cpp +++ b/src/ui/tools/pen-tool.cpp @@ -239,7 +239,9 @@ void PenTool::finish() { sp_event_context_discard_delayed_snap_event(this); if (this->npoints != 0) { - this->_cancel(); + // switching context - finish path + this->ea = NULL; // unset end anchor if set (otherwise crashes) + this->_finish(false); } FreehandBase::finish(); -- cgit v1.2.3 From 527aea8e906f12c1b5e6072321fa48f09d60bab5 Mon Sep 17 00:00:00 2001 From: "Liam P. White" Date: Thu, 14 Aug 2014 18:10:29 -0400 Subject: Clone Original -> Fill Between Many (bzr r13090.1.104) --- src/selection-chemistry.cpp | 85 ++++++++++++++++++++++----------------------- 1 file changed, 42 insertions(+), 43 deletions(-) (limited to 'src') diff --git a/src/selection-chemistry.cpp b/src/selection-chemistry.cpp index 1d7d76609..33279c0e7 100644 --- a/src/selection-chemistry.cpp +++ b/src/selection-chemistry.cpp @@ -2793,54 +2793,53 @@ void sp_selection_clone_original_path_lpe(SPDesktop *desktop) if (desktop == NULL) { return; } - - Inkscape::Selection *selection = sp_desktop_selection(desktop); - SPItem *item = selection->singleItem(); - if (g_slist_length(const_cast(selection->itemList())) != 1 || !item) { - desktop->messageStack()->flash(Inkscape::WARNING_MESSAGE, _("Select one path to clone.")); - return; - } - if ( !(SP_IS_SHAPE(item) || SP_IS_TEXT(item)) ) { - desktop->messageStack()->flash(Inkscape::WARNING_MESSAGE, _("Select one path to clone.")); - return; - } - - Inkscape::XML::Document *xml_doc = desktop->doc()->getReprDoc(); - Inkscape::XML::Node *parent = item->getRepr()->parent(); - - // create the LPE - Inkscape::XML::Node *lpe_repr = xml_doc->createElement("inkscape:path-effect"); - { - lpe_repr->setAttribute("effect", "clone_original"); - gchar *href = g_strdup_printf("#%s", item->getRepr()->attribute("id")); - lpe_repr->setAttribute("linkedpath", href); - g_free(href); - desktop->doc()->getDefs()->getRepr()->addChild(lpe_repr, NULL); // adds to and assigns the 'id' attribute - } - const gchar * lpe_id = lpe_repr->attribute("id"); - Inkscape::GC::release(lpe_repr); - - // create the new path - Inkscape::XML::Node *clone = xml_doc->createElement("svg:path"); - { - clone->setAttribute("d", "M 0 0", false); - // add the new clone to the top of the original's parent - parent->appendChild(clone); - SPObject *clone_obj = desktop->doc()->getObjectById(clone->attribute("id")); - if (SP_IS_LPE_ITEM(clone_obj)) { - gchar *href = g_strdup_printf("#%s", lpe_id); - SP_LPE_ITEM(clone_obj)->addPathEffect( href, false ); - g_free(href); + + Inkscape::SVGOStringStream os; + SPObject * firstItem = NULL; + for (const GSList * item = desktop->selection->itemList(); item != NULL; item = item->next) { + if (SP_IS_SHAPE(item->data) || SP_IS_TEXT(item->data)) { + if (firstItem) { + os << "|"; + } else { + firstItem = SP_ITEM(item->data); + } + os << "#" << SP_ITEM(item->data)->getId() << ",0"; } } + if (firstItem) { + Inkscape::XML::Document *xml_doc = desktop->doc()->getReprDoc(); + SPObject *parent = firstItem->parent; - DocumentUndo::done(sp_desktop_document(desktop), SP_VERB_EDIT_CLONE_ORIGINAL_PATH_LPE, - _("Clone original path")); + // create the LPE + Inkscape::XML::Node *lpe_repr = xml_doc->createElement("inkscape:path-effect"); + { + lpe_repr->setAttribute("effect", "fill_between_many"); + lpe_repr->setAttribute("linkedpaths", os.str().c_str()); + desktop->doc()->getDefs()->getRepr()->addChild(lpe_repr, NULL); // adds to and assigns the 'id' attribute + } + const gchar * lpe_id = lpe_repr->attribute("id"); + Inkscape::GC::release(lpe_repr); - // select the new object: - selection->set(clone); + // create the new path + Inkscape::XML::Node *clone = xml_doc->createElement("svg:path"); + { + clone->setAttribute("d", "M 0 0", false); + // add the new clone to the top of the original's parent + parent->appendChildRepr(clone); + SPObject *clone_obj = desktop->doc()->getObjectById(clone->attribute("id")); + if (SP_IS_LPE_ITEM(clone_obj)) { + gchar *href = g_strdup_printf("#%s", lpe_id); + //sp_lpe_item_add_path_effect( SP_LPE_ITEM(clone_obj), href, false ); + SP_LPE_ITEM(clone_obj)->addPathEffect(href, false); + g_free(href); + } + } - Inkscape::GC::release(clone); + DocumentUndo::done(sp_desktop_document(desktop), SP_VERB_EDIT_CLONE_ORIGINAL_PATH_LPE, + _("Fill between strokes")); + } else { + desktop->messageStack()->flash(Inkscape::WARNING_MESSAGE, _("Select path(s) to fill.")); + } } void sp_selection_to_marker(SPDesktop *desktop, bool apply) -- cgit v1.2.3 From e469f1f4eb04e7cc1401c6679a41c217287ae888 Mon Sep 17 00:00:00 2001 From: "Johan B. C. Engelen" Date: Sat, 23 Aug 2014 15:17:43 +0200 Subject: fix Windows 64-bit build (bzr r13531) --- src/ui/dialog/print.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/ui/dialog/print.cpp b/src/ui/dialog/print.cpp index ed39ebb32..a015d28f9 100644 --- a/src/ui/dialog/print.cpp +++ b/src/ui/dialog/print.cpp @@ -14,13 +14,13 @@ # include #endif +#include + #ifdef WIN32 #include #include #endif -#include - #include "preferences.h" #include "print.h" -- cgit v1.2.3 From 14d2f47bd95482e500524dccc1b40445f7f44701 Mon Sep 17 00:00:00 2001 From: Nicolas Dufour Date: Tue, 26 Aug 2014 09:43:41 +0200 Subject: UI. Fix for Bug #340723 "Interface inconsistency of tooltips". Translations. Translations template update. Fixed bugs: - https://launchpad.net/bugs/340723 (bzr r13532) --- src/extension/internal/bitmap/crop.cpp | 2 +- src/extension/internal/bitmap/opacity.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/extension/internal/bitmap/crop.cpp b/src/extension/internal/bitmap/crop.cpp index 0e633afd6..02d92668b 100644 --- a/src/extension/internal/bitmap/crop.cpp +++ b/src/extension/internal/bitmap/crop.cpp @@ -74,7 +74,7 @@ Crop::init(void) "\n" "\n" "\n" - "" N_("Crop selected bitmap(s).") "\n" + "" N_("Crop selected bitmap(s)") "\n" "\n" "\n", new Crop()); } diff --git a/src/extension/internal/bitmap/opacity.cpp b/src/extension/internal/bitmap/opacity.cpp index 742cb7019..f9b4bbc27 100644 --- a/src/extension/internal/bitmap/opacity.cpp +++ b/src/extension/internal/bitmap/opacity.cpp @@ -43,7 +43,7 @@ Opacity::init(void) "\n" "\n" "\n" - "" N_("Modify opacity channel(s) of selected bitmap(s).") "\n" + "" N_("Modify opacity channel(s) of selected bitmap(s)") "\n" "\n" "\n", new Opacity()); } -- cgit v1.2.3 From 2d1275f0337e3fe49ea493f58135c81d0e3af36d Mon Sep 17 00:00:00 2001 From: Alex Valavanis Date: Tue, 26 Aug 2014 11:55:28 +0100 Subject: Standardise InkscapeApplication GObject implementation (namespace not supported properly) (bzr r13341.1.179) --- src/desktop.h | 5 +- src/dialogs/dialog-events.cpp | 2 +- src/dialogs/dialog-events.h | 6 +- src/document-undo.cpp | 2 +- src/document-undo.h | 5 +- src/inkscape.cpp | 124 ++++++++++------------------ src/inkscape.h | 15 ++-- src/inkview.cpp | 6 +- src/ui/dialog/align-and-distribute.cpp | 4 +- src/ui/dialog/clonetiler.cpp | 4 +- src/ui/dialog/clonetiler.h | 4 +- src/ui/dialog/desktop-tracker.cpp | 2 +- src/ui/dialog/desktop-tracker.h | 5 +- src/ui/dialog/dialog-manager.cpp | 4 +- src/ui/dialog/dialog.cpp | 2 +- src/ui/dialog/dialog.h | 4 +- src/ui/dialog/document-metadata.cpp | 4 +- src/ui/dialog/document-metadata.h | 4 +- src/ui/dialog/document-properties.cpp | 4 +- src/ui/dialog/document-properties.h | 4 +- src/ui/dialog/fill-and-stroke.h | 2 +- src/ui/dialog/grid-arrange-tab.cpp | 2 +- src/ui/dialog/panel-dialog.h | 12 +-- src/ui/dialog/transformation.cpp | 4 +- src/ui/widget/object-composite-settings.cpp | 4 +- src/ui/widget/object-composite-settings.h | 6 +- src/ui/widget/panel.cpp | 4 +- src/ui/widget/panel.h | 12 +-- src/widgets/sp-widget.cpp | 6 +- src/widgets/sp-widget.h | 8 +- 30 files changed, 116 insertions(+), 154 deletions(-) (limited to 'src') diff --git a/src/desktop.h b/src/desktop.h index ec240dd40..509f8a396 100644 --- a/src/desktop.h +++ b/src/desktop.h @@ -72,8 +72,9 @@ typedef struct _GdkEventAny GdkEventAny; struct _GdkEventWindowState; typedef struct _GdkEventWindowState GdkEventWindowState; +struct InkscapeApplication; + namespace Inkscape { - struct Application; class LayerModel; class MessageContext; class Selection; @@ -423,7 +424,7 @@ public: private: Inkscape::UI::View::EditWidgetInterface *_widget; - Inkscape::Application *_inkscape; + InkscapeApplication *_inkscape; Inkscape::MessageContext *_guides_message_context; bool _active; Geom::Affine _w2d; diff --git a/src/dialogs/dialog-events.cpp b/src/dialogs/dialog-events.cpp index a12e3eafc..cf3497c9b 100644 --- a/src/dialogs/dialog-events.cpp +++ b/src/dialogs/dialog-events.cpp @@ -187,7 +187,7 @@ void on_transientize (SPDesktop *desktop, win_data *wd ) } void -sp_transientize_callback ( Inkscape::Application * /*inkscape*/, +sp_transientize_callback ( InkscapeApplication * /*inkscape*/, SPDesktop *desktop, win_data *wd ) { Inkscape::Preferences *prefs = Inkscape::Preferences::get(); diff --git a/src/dialogs/dialog-events.h b/src/dialogs/dialog-events.h index 623058282..b33eb3f38 100644 --- a/src/dialogs/dialog-events.h +++ b/src/dialogs/dialog-events.h @@ -29,9 +29,7 @@ class Entry; class SPDesktop; -namespace Inkscape { -struct Application; -} // namespace Inkscape +struct InkscapeApplication; typedef struct { GtkWidget *win; @@ -55,7 +53,7 @@ void sp_transientize ( GtkWidget *win ); void on_transientize ( SPDesktop *desktop, win_data *wd ); -void sp_transientize_callback ( Inkscape::Application *inkscape, +void sp_transientize_callback ( InkscapeApplication *inkscape, SPDesktop *desktop, win_data *wd ); diff --git a/src/document-undo.cpp b/src/document-undo.cpp index 53e701648..478266b7b 100644 --- a/src/document-undo.cpp +++ b/src/document-undo.cpp @@ -112,7 +112,7 @@ void Inkscape::DocumentUndo::done(SPDocument *doc, const unsigned int event_type maybeDone(doc, NULL, event_type, event_description); } -void Inkscape::DocumentUndo::resetKey( Inkscape::Application * /*inkscape*/, SPDesktop * /*desktop*/, GObject *base ) +void Inkscape::DocumentUndo::resetKey( InkscapeApplication * /*inkscape*/, SPDesktop * /*desktop*/, GObject *base ) { SPDocument *doc = reinterpret_cast(base); doc->actionkey.clear(); diff --git a/src/document-undo.h b/src/document-undo.h index 38e575a34..17b3de252 100644 --- a/src/document-undo.h +++ b/src/document-undo.h @@ -9,11 +9,10 @@ typedef struct _GObject GObject; class SPDesktop; class SPDocument; +struct InkscapeApplication; namespace Inkscape { -struct Application; - class DocumentUndo { public: @@ -42,7 +41,7 @@ public: static void maybeDone(SPDocument *document, const gchar *keyconst, unsigned int event_type, Glib::ustring const &event_description); - static void resetKey(Inkscape::Application *inkscape, SPDesktop *desktop, GObject *base); + static void resetKey(InkscapeApplication *inkscape, SPDesktop *desktop, GObject *base); static void cancel(SPDocument *document); diff --git a/src/inkscape.cpp b/src/inkscape.cpp index 4b4c8c678..8ac87dadd 100644 --- a/src/inkscape.cpp +++ b/src/inkscape.cpp @@ -71,7 +71,7 @@ #include "helper/action-context.h" #include "helper/sp-marshal.h" -static Inkscape::Application *inkscape = NULL; +static InkscapeApplication *inkscape = NULL; /* Backbones of configuration xml data */ #include "menus-skeleton.h" @@ -99,16 +99,10 @@ enum { # FORWARD DECLARATIONS ################################*/ -namespace Inkscape { -struct ApplicationClass; -} - -static void inkscape_class_init (Inkscape::ApplicationClass *klass); -static void inkscape_init (SPObject *object); static void inkscape_dispose (GObject *object); -static void inkscape_activate_desktop_private (Inkscape::Application *inkscape, SPDesktop *desktop); -static void inkscape_deactivate_desktop_private (Inkscape::Application *inkscape, SPDesktop *desktop); +static void inkscape_activate_desktop_private (InkscapeApplication *inkscape, SPDesktop *desktop); +static void inkscape_deactivate_desktop_private (InkscapeApplication *inkscape, SPDesktop *desktop); class AppSelectionModel { Inkscape::LayerModel _layer_model; @@ -126,7 +120,7 @@ public: Inkscape::Selection *getSelection() const { return _selection; } }; -struct Inkscape::Application { +struct InkscapeApplication { GObject object; Inkscape::XML::Document *menus; std::map document_set; @@ -140,26 +134,25 @@ struct Inkscape::Application { guint trackalt; }; -struct Inkscape::ApplicationClass { +struct InkscapeApplicationClass { GObjectClass object_class; /* Signals */ - void (* change_selection) (Inkscape::Application * inkscape, Inkscape::Selection * selection); - void (* change_subselection) (Inkscape::Application * inkscape, SPDesktop *desktop); - void (* modify_selection) (Inkscape::Application * inkscape, Inkscape::Selection * selection, guint flags); - void (* set_selection) (Inkscape::Application * inkscape, Inkscape::Selection * selection); - void (* set_eventcontext) (Inkscape::Application * inkscape, Inkscape::UI::Tools::ToolBase * eventcontext); - void (* activate_desktop) (Inkscape::Application * inkscape, SPDesktop * desktop); - void (* deactivate_desktop) (Inkscape::Application * inkscape, SPDesktop * desktop); - void (* destroy_document) (Inkscape::Application *inkscape, SPDocument *doc); - void (* color_set) (Inkscape::Application *inkscape, SPColor *color, double opacity); - void (* shut_down) (Inkscape::Application *inkscape); - void (* dialogs_hide) (Inkscape::Application *inkscape); - void (* dialogs_unhide) (Inkscape::Application *inkscape); - void (* external_change) (Inkscape::Application *inkscape); + void (* change_selection) (InkscapeApplication * inkscape, Inkscape::Selection * selection); + void (* change_subselection) (InkscapeApplication * inkscape, SPDesktop *desktop); + void (* modify_selection) (InkscapeApplication * inkscape, Inkscape::Selection * selection, guint flags); + void (* set_selection) (InkscapeApplication * inkscape, Inkscape::Selection * selection); + void (* set_eventcontext) (InkscapeApplication * inkscape, Inkscape::UI::Tools::ToolBase * eventcontext); + void (* activate_desktop) (InkscapeApplication * inkscape, SPDesktop * desktop); + void (* deactivate_desktop) (InkscapeApplication * inkscape, SPDesktop * desktop); + void (* destroy_document) (InkscapeApplication *inkscape, SPDocument *doc); + void (* color_set) (InkscapeApplication *inkscape, SPColor *color, double opacity); + void (* shut_down) (InkscapeApplication *inkscape); + void (* dialogs_hide) (InkscapeApplication *inkscape); + void (* dialogs_unhide) (InkscapeApplication *inkscape); + void (* external_change) (InkscapeApplication *inkscape); }; -static GObjectClass * parent_class; static guint inkscape_signals[LAST_SIGNAL] = {0}; static void (* segv_handler) (int) = SIG_DFL; @@ -175,48 +168,21 @@ static void (* bus_handler) (int) = SIG_DFL; #define INKSCAPE_LEGACY_PROFILE_DIR ".inkscape" #define MENUS_FILE "menus.xml" - -/** - * Retrieves the GType for the Inkscape Application object. - */ -GType -inkscape_get_type (void) -{ - static GType type = 0; - if (!type) { - GTypeInfo info = { - sizeof (Inkscape::ApplicationClass), - NULL, NULL, - (GClassInitFunc) inkscape_class_init, - NULL, NULL, - sizeof (Inkscape::Application), - 4, - (GInstanceInitFunc) inkscape_init, - NULL - }; - type = g_type_register_static (G_TYPE_OBJECT, "Inkscape_Application", &info, (GTypeFlags)0); - } - return type; -} - +G_DEFINE_TYPE(InkscapeApplication, inkscape, G_TYPE_OBJECT); /** * Initializes the inkscape class, registering all of its signal handlers * and virtual functions */ static void -inkscape_class_init (Inkscape::ApplicationClass * klass) +inkscape_class_init (InkscapeApplicationClass * klass) { - GObjectClass * object_class; - - object_class = (GObjectClass *) klass; - - parent_class = (GObjectClass *)g_type_class_peek_parent (klass); + GObjectClass * object_class = G_OBJECT_CLASS(klass); inkscape_signals[MODIFY_SELECTION] = g_signal_new ("modify_selection", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_FIRST, - G_STRUCT_OFFSET (Inkscape::ApplicationClass, modify_selection), + G_STRUCT_OFFSET (InkscapeApplicationClass, modify_selection), NULL, NULL, sp_marshal_VOID__POINTER_UINT, G_TYPE_NONE, 2, @@ -224,7 +190,7 @@ inkscape_class_init (Inkscape::ApplicationClass * klass) inkscape_signals[CHANGE_SELECTION] = g_signal_new ("change_selection", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_FIRST, - G_STRUCT_OFFSET (Inkscape::ApplicationClass, change_selection), + G_STRUCT_OFFSET (InkscapeApplicationClass, change_selection), NULL, NULL, g_cclosure_marshal_VOID__POINTER, G_TYPE_NONE, 1, @@ -232,7 +198,7 @@ inkscape_class_init (Inkscape::ApplicationClass * klass) inkscape_signals[CHANGE_SUBSELECTION] = g_signal_new ("change_subselection", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_FIRST, - G_STRUCT_OFFSET (Inkscape::ApplicationClass, change_subselection), + G_STRUCT_OFFSET (InkscapeApplicationClass, change_subselection), NULL, NULL, g_cclosure_marshal_VOID__POINTER, G_TYPE_NONE, 1, @@ -240,7 +206,7 @@ inkscape_class_init (Inkscape::ApplicationClass * klass) inkscape_signals[SET_SELECTION] = g_signal_new ("set_selection", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_FIRST, - G_STRUCT_OFFSET (Inkscape::ApplicationClass, set_selection), + G_STRUCT_OFFSET (InkscapeApplicationClass, set_selection), NULL, NULL, g_cclosure_marshal_VOID__POINTER, G_TYPE_NONE, 1, @@ -248,7 +214,7 @@ inkscape_class_init (Inkscape::ApplicationClass * klass) inkscape_signals[SET_EVENTCONTEXT] = g_signal_new ("set_eventcontext", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_FIRST, - G_STRUCT_OFFSET (Inkscape::ApplicationClass, set_eventcontext), + G_STRUCT_OFFSET (InkscapeApplicationClass, set_eventcontext), NULL, NULL, g_cclosure_marshal_VOID__POINTER, G_TYPE_NONE, 1, @@ -256,7 +222,7 @@ inkscape_class_init (Inkscape::ApplicationClass * klass) inkscape_signals[ACTIVATE_DESKTOP] = g_signal_new ("activate_desktop", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_FIRST, - G_STRUCT_OFFSET (Inkscape::ApplicationClass, activate_desktop), + G_STRUCT_OFFSET (InkscapeApplicationClass, activate_desktop), NULL, NULL, g_cclosure_marshal_VOID__POINTER, G_TYPE_NONE, 1, @@ -264,7 +230,7 @@ inkscape_class_init (Inkscape::ApplicationClass * klass) inkscape_signals[DEACTIVATE_DESKTOP] = g_signal_new ("deactivate_desktop", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_FIRST, - G_STRUCT_OFFSET (Inkscape::ApplicationClass, deactivate_desktop), + G_STRUCT_OFFSET (InkscapeApplicationClass, deactivate_desktop), NULL, NULL, g_cclosure_marshal_VOID__POINTER, G_TYPE_NONE, 1, @@ -272,28 +238,28 @@ inkscape_class_init (Inkscape::ApplicationClass * klass) inkscape_signals[SHUTDOWN_SIGNAL] = g_signal_new ("shut_down", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_FIRST, - G_STRUCT_OFFSET (Inkscape::ApplicationClass, shut_down), + G_STRUCT_OFFSET (InkscapeApplicationClass, shut_down), NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0); inkscape_signals[DIALOGS_HIDE] = g_signal_new ("dialogs_hide", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_FIRST, - G_STRUCT_OFFSET (Inkscape::ApplicationClass, dialogs_hide), + G_STRUCT_OFFSET (InkscapeApplicationClass, dialogs_hide), NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0); inkscape_signals[DIALOGS_UNHIDE] = g_signal_new ("dialogs_unhide", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_FIRST, - G_STRUCT_OFFSET (Inkscape::ApplicationClass, dialogs_unhide), + G_STRUCT_OFFSET (InkscapeApplicationClass, dialogs_unhide), NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0); inkscape_signals[EXTERNAL_CHANGE] = g_signal_new ("external_change", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_FIRST, - G_STRUCT_OFFSET (Inkscape::ApplicationClass, external_change), + G_STRUCT_OFFSET (InkscapeApplicationClass, external_change), NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0); @@ -494,10 +460,10 @@ void inkscape_autosave_init() static void -inkscape_init (SPObject * object) +inkscape_init (InkscapeApplication * object) { if (!inkscape) { - inkscape = (Inkscape::Application *) object; + inkscape = (InkscapeApplication *) object; } else { g_assert_not_reached (); } @@ -515,7 +481,7 @@ inkscape_init (SPObject * object) static void inkscape_dispose (GObject *object) { - Inkscape::Application *inkscape = (Inkscape::Application *) object; + InkscapeApplication *inkscape = (InkscapeApplication *) object; g_assert (!inkscape->desktops); @@ -530,7 +496,7 @@ inkscape_dispose (GObject *object) inkscape->selection_models.~map(); inkscape->document_set.~map(); - G_OBJECT_CLASS (parent_class)->dispose (object); + G_OBJECT_CLASS (inkscape_parent_class)->dispose (object); gtk_main_quit (); } @@ -580,14 +546,14 @@ void inkscape_trackalt(guint trackvalue) static void -inkscape_activate_desktop_private (Inkscape::Application */*inkscape*/, SPDesktop *desktop) +inkscape_activate_desktop_private (InkscapeApplication */*inkscape*/, SPDesktop *desktop) { desktop->set_active (true); } static void -inkscape_deactivate_desktop_private (Inkscape::Application */*inkscape*/, SPDesktop *desktop) +inkscape_deactivate_desktop_private (InkscapeApplication */*inkscape*/, SPDesktop *desktop) { desktop->set_active (false); } @@ -835,7 +801,7 @@ private: void inkscape_application_init (const gchar *argv0, gboolean use_gui) { - inkscape = (Inkscape::Application *)g_object_new (SP_TYPE_INKSCAPE, NULL); + inkscape = (InkscapeApplication *)g_object_new (SP_TYPE_INKSCAPE, NULL); /* fixme: load application defaults */ segv_handler = signal (SIGSEGV, inkscape_crash_handler); @@ -904,9 +870,9 @@ inkscape_application_init (const gchar *argv0, gboolean use_gui) } /** - * Returns the current Inkscape::Application global object + * Returns the current InkscapeApplication global object */ -Inkscape::Application * +InkscapeApplication * inkscape_get_instance() { return inkscape; @@ -921,7 +887,7 @@ gboolean inkscape_use_gui() * Menus management * */ -bool inkscape_load_menus( Inkscape::Application * inkscape ) +bool inkscape_load_menus( InkscapeApplication * inkscape ) { gchar *fn = profile_path(MENUS_FILE); gchar *menus_xml = 0; @@ -1391,7 +1357,7 @@ inkscape_action_context_for_document(SPDocument *doc) #####################*/ void -inkscape_refresh_display (Inkscape::Application *inkscape) +inkscape_refresh_display (InkscapeApplication *inkscape) { for (GSList *l = inkscape->desktops; l != NULL; l = l->next) { (static_cast(l->data))->requestRedraw(); @@ -1404,7 +1370,7 @@ inkscape_refresh_display (Inkscape::Application *inkscape) * saves the preferences if appropriate, and quits. */ void -inkscape_exit (Inkscape::Application */*inkscape*/) +inkscape_exit (InkscapeApplication */*inkscape*/) { g_assert (INKSCAPE); @@ -1546,7 +1512,7 @@ profile_path(const char *filename) } Inkscape::XML::Node * -inkscape_get_menus (Inkscape::Application * inkscape) +inkscape_get_menus (InkscapeApplication * inkscape) { Inkscape::XML::Node *repr = inkscape->menus->root(); g_assert (!(strcmp (repr->name(), "inkscape"))); diff --git a/src/inkscape.h b/src/inkscape.h index 823e7524f..3a9b85fc9 100644 --- a/src/inkscape.h +++ b/src/inkscape.h @@ -28,9 +28,10 @@ class ToolBase; } } +struct InkscapeApplication; + namespace Inkscape { class ActionContext; - struct Application; namespace XML { class Node; struct Document; @@ -46,11 +47,11 @@ void inkscape_application_init (const gchar *argv0, gboolean use_gui); bool inkscape_load_config (const gchar *filename, Inkscape::XML::Document *config, const gchar *skeleton, unsigned int skel_size, const gchar *e_notreg, const gchar *e_notxml, const gchar *e_notsp, const gchar *warn); /* Menus */ -bool inkscape_load_menus (Inkscape::Application * inkscape); -bool inkscape_save_menus (Inkscape::Application * inkscape); -Inkscape::XML::Node *inkscape_get_menus (Inkscape::Application * inkscape); +bool inkscape_load_menus (InkscapeApplication * inkscape); +bool inkscape_save_menus (InkscapeApplication * inkscape); +Inkscape::XML::Node *inkscape_get_menus (InkscapeApplication * inkscape); -Inkscape::Application *inkscape_get_instance(); +InkscapeApplication *inkscape_get_instance(); gboolean inkscape_use_gui(); bool inkscapeIsCrashing(); @@ -108,13 +109,13 @@ bool inkscape_remove_document (SPDocument *document); * fixme: This has to be rethought */ -void inkscape_refresh_display (Inkscape::Application *inkscape); +void inkscape_refresh_display (InkscapeApplication *inkscape); /* * fixme: This also */ -void inkscape_exit (Inkscape::Application *inkscape); +void inkscape_exit (InkscapeApplication *inkscape); #endif diff --git a/src/inkview.cpp b/src/inkview.cpp index 82bd08e34..4188c832f 100644 --- a/src/inkview.cpp +++ b/src/inkview.cpp @@ -62,7 +62,7 @@ #include "inkscape-private.h" -Inkscape::Application *inkscape; +InkscapeApplication *inkscape; #include @@ -232,7 +232,7 @@ main (int argc, const char **argv) ss.view = NULL; ss.fullscreen = false; - inkscape = (Inkscape::Application *)g_object_new (SP_TYPE_INKSCAPE, NULL); + inkscape = (InkscapeApplication *)g_object_new (SP_TYPE_INKSCAPE, NULL); // starting at where the commandline options stopped parsing because // we want all the files to be in the list @@ -572,7 +572,7 @@ static void usage() #ifdef XXX /* TODO !!! make this temporary stub unnecessary */ -Inkscape::Application *inkscape_get_instance() { return NULL; } +InkscapeApplication *inkscape_get_instance() { return NULL; } void inkscape_ref (void) {} void inkscape_unref (void) {} void inkscape_add_document (SPDocument *document) {} diff --git a/src/ui/dialog/align-and-distribute.cpp b/src/ui/dialog/align-and-distribute.cpp index e02ccd3f1..8352de1e3 100644 --- a/src/ui/dialog/align-and-distribute.cpp +++ b/src/ui/dialog/align-and-distribute.cpp @@ -829,14 +829,14 @@ private : -static void on_tool_changed(Inkscape::Application */*inkscape*/, Inkscape::UI::Tools::ToolBase */*context*/, AlignAndDistribute *daad) +static void on_tool_changed(InkscapeApplication */*inkscape*/, Inkscape::UI::Tools::ToolBase */*context*/, AlignAndDistribute *daad) { SPDesktop *desktop = SP_ACTIVE_DESKTOP; if (desktop && desktop->getEventContext()) daad->setMode(tools_active(desktop) == TOOLS_NODES); } -static void on_selection_changed(Inkscape::Application */*inkscape*/, Inkscape::Selection */*selection*/, AlignAndDistribute *daad) +static void on_selection_changed(InkscapeApplication */*inkscape*/, Inkscape::Selection */*selection*/, AlignAndDistribute *daad) { daad->randomize_bbox = Geom::OptRect(); } diff --git a/src/ui/dialog/clonetiler.cpp b/src/ui/dialog/clonetiler.cpp index e5f18216c..d9e2c03ba 100644 --- a/src/ui/dialog/clonetiler.cpp +++ b/src/ui/dialog/clonetiler.cpp @@ -1349,7 +1349,7 @@ void CloneTiler::on_picker_color_changed(guint rgba) is_updating = false; } -void CloneTiler::clonetiler_change_selection(Inkscape::Application * /*inkscape*/, Inkscape::Selection *selection, GtkWidget *dlg) +void CloneTiler::clonetiler_change_selection(InkscapeApplication * /*inkscape*/, Inkscape::Selection *selection, GtkWidget *dlg) { GtkWidget *buttons = GTK_WIDGET(g_object_get_data (G_OBJECT(dlg), "buttons_on_tiles")); GtkWidget *status = GTK_WIDGET(g_object_get_data (G_OBJECT(dlg), "status")); @@ -1378,7 +1378,7 @@ void CloneTiler::clonetiler_change_selection(Inkscape::Application * /*inkscape* } } -void CloneTiler::clonetiler_external_change(Inkscape::Application * /*inkscape*/, GtkWidget *dlg) +void CloneTiler::clonetiler_external_change(InkscapeApplication * /*inkscape*/, GtkWidget *dlg) { clonetiler_change_selection (NULL, sp_desktop_selection(SP_ACTIVE_DESKTOP), dlg); } diff --git a/src/ui/dialog/clonetiler.h b/src/ui/dialog/clonetiler.h index e2a0240ee..9bacc701d 100644 --- a/src/ui/dialog/clonetiler.h +++ b/src/ui/dialog/clonetiler.h @@ -58,8 +58,8 @@ protected: static void clonetiler_keep_bbox_toggled(GtkToggleButton *tb, gpointer /*data*/); static void clonetiler_apply(GtkWidget */*widget*/, GtkWidget *dlg); static void clonetiler_unclump(GtkWidget */*widget*/, void *); - static void clonetiler_change_selection(Inkscape::Application * /*inkscape*/, Inkscape::Selection *selection, GtkWidget *dlg); - static void clonetiler_external_change(Inkscape::Application * /*inkscape*/, GtkWidget *dlg); + static void clonetiler_change_selection(InkscapeApplication * /*inkscape*/, Inkscape::Selection *selection, GtkWidget *dlg); + static void clonetiler_external_change(InkscapeApplication * /*inkscape*/, GtkWidget *dlg); static void clonetiler_disconnect_gsignal(GObject *widget, gpointer source); static void clonetiler_reset(GtkWidget */*widget*/, GtkWidget *dlg); static guint clonetiler_number_of_clones(SPObject *obj); diff --git a/src/ui/dialog/desktop-tracker.cpp b/src/ui/dialog/desktop-tracker.cpp index 8a359dd2d..3ed998252 100644 --- a/src/ui/dialog/desktop-tracker.cpp +++ b/src/ui/dialog/desktop-tracker.cpp @@ -94,7 +94,7 @@ sigc::connection DesktopTracker::connectDesktopChanged( const sigc::slottrackActive) { self->setDesktop(desktop); diff --git a/src/ui/dialog/desktop-tracker.h b/src/ui/dialog/desktop-tracker.h index 7da55cf2f..7b944ddfa 100644 --- a/src/ui/dialog/desktop-tracker.h +++ b/src/ui/dialog/desktop-tracker.h @@ -12,11 +12,10 @@ typedef struct _GtkWidget GtkWidget; class SPDesktop; +struct InkscapeApplication; namespace Inkscape { -struct Application; - namespace UI { namespace Dialog { @@ -37,7 +36,7 @@ public: sigc::connection connectDesktopChanged( const sigc::slot & slot ); private: - static gboolean activateDesktopCB(Inkscape::Application *inkscape, SPDesktop *desktop, DesktopTracker *self ); + static gboolean activateDesktopCB(InkscapeApplication *inkscape, SPDesktop *desktop, DesktopTracker *self ); static bool hierarchyChangeCB(GtkWidget *widget, GtkWidget* prev, DesktopTracker *self); void handleHierarchyChange(); diff --git a/src/ui/dialog/dialog-manager.cpp b/src/ui/dialog/dialog-manager.cpp index 7e69e439a..0da638546 100644 --- a/src/ui/dialog/dialog-manager.cpp +++ b/src/ui/dialog/dialog-manager.cpp @@ -70,13 +70,13 @@ inline Dialog *create() { return PanelDialog::template create(); } /** * This class is provided as a container for Inkscape's various - * dialogs. This allows Inkscape::Application to treat the various + * dialogs. This allows InkscapeApplication to treat the various * dialogs it invokes, as abstractions. * * DialogManager is essentially a cache of dialogs. It lets us * initialize dialogs lazily - instead of constructing them during * application startup, they're constructed the first time they're - * actually invoked by Inkscape::Application. The constructed + * actually invoked by InkscapeApplication. The constructed * dialog is held here after that, so future invokations of the * dialog don't need to get re-constructed each time. The memory for * the dialogs are then reclaimed when the DialogManager is destroyed. diff --git a/src/ui/dialog/dialog.cpp b/src/ui/dialog/dialog.cpp index f2c63ed8d..4f0d9fbe1 100644 --- a/src/ui/dialog/dialog.cpp +++ b/src/ui/dialog/dialog.cpp @@ -41,7 +41,7 @@ namespace Inkscape { namespace UI { namespace Dialog { -void sp_retransientize(Inkscape::Application */*inkscape*/, SPDesktop *desktop, gpointer dlgPtr) +void sp_retransientize(InkscapeApplication */*inkscape*/, SPDesktop *desktop, gpointer dlgPtr) { Dialog *dlg = static_cast(dlgPtr); dlg->onDesktopActivated (desktop); diff --git a/src/ui/dialog/dialog.h b/src/ui/dialog/dialog.h index ec5d203bc..ccff43a56 100644 --- a/src/ui/dialog/dialog.h +++ b/src/ui/dialog/dialog.h @@ -18,10 +18,10 @@ #include "floating-behavior.h" class SPDesktop; +struct InkscapeApplication; namespace Inkscape { class Selection; -struct Application; } namespace Inkscape { @@ -30,7 +30,7 @@ namespace Dialog { enum BehaviorType { FLOATING, DOCK }; -void sp_retransientize(Inkscape::Application *inkscape, SPDesktop *desktop, gpointer dlgPtr); +void sp_retransientize(InkscapeApplication *inkscape, SPDesktop *desktop, gpointer dlgPtr); gboolean sp_retransientize_again(gpointer dlgPtr); void sp_dialog_shutdown(GObject *object, gpointer dlgPtr); diff --git a/src/ui/dialog/document-metadata.cpp b/src/ui/dialog/document-metadata.cpp index 09c505860..77ea175d9 100644 --- a/src/ui/dialog/document-metadata.cpp +++ b/src/ui/dialog/document-metadata.cpp @@ -223,7 +223,7 @@ DocumentMetadata::_handleDocumentReplaced(SPDesktop* desktop, SPDocument *) } void -DocumentMetadata::_handleActivateDesktop(Inkscape::Application *, SPDesktop *desktop) +DocumentMetadata::_handleActivateDesktop(InkscapeApplication *, SPDesktop *desktop) { Inkscape::XML::Node *repr = sp_desktop_namedview(desktop)->getRepr(); repr->addListener(&_repr_events, this); @@ -231,7 +231,7 @@ DocumentMetadata::_handleActivateDesktop(Inkscape::Application *, SPDesktop *des } void -DocumentMetadata::_handleDeactivateDesktop(Inkscape::Application *, SPDesktop *desktop) +DocumentMetadata::_handleDeactivateDesktop(InkscapeApplication *, SPDesktop *desktop) { Inkscape::XML::Node *repr = sp_desktop_namedview(desktop)->getRepr(); repr->removeListenerByData(this); diff --git a/src/ui/dialog/document-metadata.h b/src/ui/dialog/document-metadata.h index 3b7ed1ec8..77084bc3d 100644 --- a/src/ui/dialog/document-metadata.h +++ b/src/ui/dialog/document-metadata.h @@ -56,8 +56,8 @@ protected: void init(); void _handleDocumentReplaced(SPDesktop* desktop, SPDocument *document); - void _handleActivateDesktop(Inkscape::Application *application, SPDesktop *desktop); - void _handleDeactivateDesktop(Inkscape::Application *application, SPDesktop *desktop); + void _handleActivateDesktop(InkscapeApplication *application, SPDesktop *desktop); + void _handleDeactivateDesktop(InkscapeApplication *application, SPDesktop *desktop); Gtk::Notebook _notebook; diff --git a/src/ui/dialog/document-properties.cpp b/src/ui/dialog/document-properties.cpp index 4e4616724..5ad82644e 100644 --- a/src/ui/dialog/document-properties.cpp +++ b/src/ui/dialog/document-properties.cpp @@ -1594,7 +1594,7 @@ void DocumentProperties::_handleDocumentReplaced(SPDesktop* desktop, SPDocument update(); } -void DocumentProperties::_handleActivateDesktop(Inkscape::Application *, SPDesktop *desktop) +void DocumentProperties::_handleActivateDesktop(InkscapeApplication *, SPDesktop *desktop) { Inkscape::XML::Node *repr = sp_desktop_namedview(desktop)->getRepr(); repr->addListener(&_repr_events, this); @@ -1603,7 +1603,7 @@ void DocumentProperties::_handleActivateDesktop(Inkscape::Application *, SPDeskt update(); } -void DocumentProperties::_handleDeactivateDesktop(Inkscape::Application *, SPDesktop *desktop) +void DocumentProperties::_handleDeactivateDesktop(InkscapeApplication *, SPDesktop *desktop) { Inkscape::XML::Node *repr = sp_desktop_namedview(desktop)->getRepr(); repr->removeListenerByData(this); diff --git a/src/ui/dialog/document-properties.h b/src/ui/dialog/document-properties.h index 495f3177d..ee7e88b18 100644 --- a/src/ui/dialog/document-properties.h +++ b/src/ui/dialog/document-properties.h @@ -94,8 +94,8 @@ protected: void save_default_metadata(); void _handleDocumentReplaced(SPDesktop* desktop, SPDocument *document); - void _handleActivateDesktop(Inkscape::Application *application, SPDesktop *desktop); - void _handleDeactivateDesktop(Inkscape::Application *application, SPDesktop *desktop); + void _handleActivateDesktop(InkscapeApplication *application, SPDesktop *desktop); + void _handleDeactivateDesktop(InkscapeApplication *application, SPDesktop *desktop); Inkscape::XML::SignalObserver _emb_profiles_observer, _scripts_observer; Gtk::Notebook _notebook; diff --git a/src/ui/dialog/fill-and-stroke.h b/src/ui/dialog/fill-and-stroke.h index 340cb860f..35c98ef9c 100644 --- a/src/ui/dialog/fill-and-stroke.h +++ b/src/ui/dialog/fill-and-stroke.h @@ -41,7 +41,7 @@ public: virtual void setDesktop(SPDesktop *desktop); - void selectionChanged(Inkscape::Application *inkscape, + void selectionChanged(InkscapeApplication *inkscape, Inkscape::Selection *selection); void showPageFill(); diff --git a/src/ui/dialog/grid-arrange-tab.cpp b/src/ui/dialog/grid-arrange-tab.cpp index 72217c729..1417b39fa 100644 --- a/src/ui/dialog/grid-arrange-tab.cpp +++ b/src/ui/dialog/grid-arrange-tab.cpp @@ -572,7 +572,7 @@ void GridArrangeTab::updateSelection() ## Experimental ##########################*/ -static void updateSelectionCallback(Inkscape::Application */*inkscape*/, Inkscape::Selection */*selection*/, GridArrangeTab *dlg) +static void updateSelectionCallback(InkscapeApplication */*inkscape*/, Inkscape::Selection */*selection*/, GridArrangeTab *dlg) { dlg->updateSelection(); } diff --git a/src/ui/dialog/panel-dialog.h b/src/ui/dialog/panel-dialog.h index 1fefd811e..b4a355083 100644 --- a/src/ui/dialog/panel-dialog.h +++ b/src/ui/dialog/panel-dialog.h @@ -49,19 +49,19 @@ public: virtual UI::Widget::Panel &getPanel() { return _panel; } protected: - static void handle_deactivate_desktop(Inkscape::Application *application, SPDesktop *desktop, void *data) { + static void handle_deactivate_desktop(InkscapeApplication *application, SPDesktop *desktop, void *data) { g_return_if_fail(data != NULL); static_cast(data)->_propagateDesktopDeactivated(application, desktop); } - static void _handle_activate_desktop(Inkscape::Application *application, SPDesktop *desktop, void *data) { + static void _handle_activate_desktop(InkscapeApplication *application, SPDesktop *desktop, void *data) { g_return_if_fail(data != NULL); static_cast(data)->_propagateDesktopActivated(application, desktop); } inline virtual void _propagateDocumentReplaced(SPDesktop* desktop, SPDocument *document); - inline virtual void _propagateDesktopActivated(Inkscape::Application *, SPDesktop *); - inline virtual void _propagateDesktopDeactivated(Inkscape::Application *, SPDesktop *); + inline virtual void _propagateDesktopActivated(InkscapeApplication *, SPDesktop *); + inline virtual void _propagateDesktopDeactivated(InkscapeApplication *, SPDesktop *); UI::Widget::Panel &_panel; sigc::connection _document_replaced_connection; @@ -134,14 +134,14 @@ void PanelDialogBase::_propagateDocumentReplaced(SPDesktop *desktop, SPDocument _panel.signalDocumentReplaced().emit(desktop, document); } -void PanelDialogBase::_propagateDesktopActivated(Inkscape::Application *application, SPDesktop *desktop) +void PanelDialogBase::_propagateDesktopActivated(InkscapeApplication *application, SPDesktop *desktop) { _document_replaced_connection = desktop->connectDocumentReplaced(sigc::mem_fun(*this, &PanelDialogBase::_propagateDocumentReplaced)); _panel.signalActivateDesktop().emit(application, desktop); } -void PanelDialogBase::_propagateDesktopDeactivated(Inkscape::Application *application, SPDesktop *desktop) +void PanelDialogBase::_propagateDesktopDeactivated(InkscapeApplication *application, SPDesktop *desktop) { _document_replaced_connection.disconnect(); _panel.signalDeactiveDesktop().emit(application, desktop); diff --git a/src/ui/dialog/transformation.cpp b/src/ui/dialog/transformation.cpp index a7f0b068e..3e135b9b2 100644 --- a/src/ui/dialog/transformation.cpp +++ b/src/ui/dialog/transformation.cpp @@ -47,13 +47,13 @@ namespace Inkscape { namespace UI { namespace Dialog { -static void on_selection_changed(Inkscape::Application */*inkscape*/, Inkscape::Selection *selection, Transformation *daad) +static void on_selection_changed(InkscapeApplication */*inkscape*/, Inkscape::Selection *selection, Transformation *daad) { int page = daad->getCurrentPage(); daad->updateSelection((Inkscape::UI::Dialog::Transformation::PageType)page, selection); } -static void on_selection_modified( Inkscape::Application */*inkscape*/, +static void on_selection_modified( InkscapeApplication */*inkscape*/, Inkscape::Selection *selection, guint /*flags*/, Transformation *daad ) diff --git a/src/ui/widget/object-composite-settings.cpp b/src/ui/widget/object-composite-settings.cpp index 537db0fdd..e4cd76345 100644 --- a/src/ui/widget/object-composite-settings.cpp +++ b/src/ui/widget/object-composite-settings.cpp @@ -40,7 +40,7 @@ namespace UI { namespace Widget { /*void ObjectCompositeSettings::_on_desktop_activate( - Inkscape::Application *application, + InkscapeApplication *application, SPDesktop *desktop, ObjectCompositeSettings *w ) { @@ -50,7 +50,7 @@ namespace Widget { } void ObjectCompositeSettings::_on_desktop_deactivate( - Inkscape::Application *application, + InkscapeApplication *application, SPDesktop *desktop, ObjectCompositeSettings *w ) { diff --git a/src/ui/widget/object-composite-settings.h b/src/ui/widget/object-composite-settings.h index 19a6cb2a5..e375bf24a 100644 --- a/src/ui/widget/object-composite-settings.h +++ b/src/ui/widget/object-composite-settings.h @@ -30,9 +30,9 @@ #include "ui/widget/spinbutton.h" class SPDesktop; +struct InkscapeApplication; namespace Inkscape { -struct Application; namespace UI { namespace Widget { @@ -66,8 +66,8 @@ private: gulong _desktop_activated; sigc::connection _subject_changed; - static void _on_desktop_activate(Inkscape::Application *application, SPDesktop *desktop, ObjectCompositeSettings *w); - static void _on_desktop_deactivate(Inkscape::Application *application, SPDesktop *desktop, ObjectCompositeSettings *w); + static void _on_desktop_activate(InkscapeApplication *application, SPDesktop *desktop, ObjectCompositeSettings *w); + static void _on_desktop_deactivate(InkscapeApplication *application, SPDesktop *desktop, ObjectCompositeSettings *w); void _subjectChanged(); void _blendBlurValueChanged(); void _opacityValueChanged(); diff --git a/src/ui/widget/panel.cpp b/src/ui/widget/panel.cpp index b37137228..0abd81b16 100644 --- a/src/ui/widget/panel.cpp +++ b/src/ui/widget/panel.cpp @@ -643,13 +643,13 @@ Panel::signalDocumentReplaced() return _signal_document_replaced; } -sigc::signal & +sigc::signal & Panel::signalActivateDesktop() { return _signal_activate_desktop; } -sigc::signal & +sigc::signal & Panel::signalDeactiveDesktop() { return _signal_deactive_desktop; diff --git a/src/ui/widget/panel.h b/src/ui/widget/panel.h index 0c3d822b8..177314797 100644 --- a/src/ui/widget/panel.h +++ b/src/ui/widget/panel.h @@ -45,9 +45,9 @@ namespace Gtk { class MenuItem; } -namespace Inkscape { +struct InkscapeApplication; -struct Application; +namespace Inkscape { class Selection; namespace UI { @@ -116,8 +116,8 @@ public: void setResponseSensitive(int response_id, bool setting); virtual sigc::signal &signalDocumentReplaced(); - virtual sigc::signal &signalActivateDesktop(); - virtual sigc::signal &signalDeactiveDesktop(); + virtual sigc::signal &signalActivateDesktop(); + virtual sigc::signal &signalDeactiveDesktop(); protected: /** @@ -147,8 +147,8 @@ protected: sigc::signal _signal_response; sigc::signal _signal_present; sigc::signal _signal_document_replaced; - sigc::signal _signal_activate_desktop; - sigc::signal _signal_deactive_desktop; + sigc::signal _signal_activate_desktop; + sigc::signal _signal_deactive_desktop; private: void _init(); diff --git a/src/widgets/sp-widget.cpp b/src/widgets/sp-widget.cpp index 257d8ef30..fdf5ec500 100644 --- a/src/widgets/sp-widget.cpp +++ b/src/widgets/sp-widget.cpp @@ -59,7 +59,7 @@ public: static void changeSelectionCB(Application *inkscape, Selection *selection, SPWidget *spw); static void setSelectionCB(Application *inkscape, Selection *selection, SPWidget *spw); - static GtkWidget *constructGlobal(SPWidget *spw, Inkscape::Application *inkscape); + static GtkWidget *constructGlobal(SPWidget *spw, InkscapeApplication *inkscape); void modifySelection(Application *inkscape, Selection *selection, guint flags); void changeSelection(Application *inkscape, Selection *selection); @@ -264,7 +264,7 @@ void SPWidgetImpl::sizeAllocate(GtkWidget *widget, GtkAllocation *allocation) } } -GtkWidget *SPWidgetImpl::constructGlobal(SPWidget *spw, Inkscape::Application *inkscape) +GtkWidget *SPWidgetImpl::constructGlobal(SPWidget *spw, InkscapeApplication *inkscape) { g_return_val_if_fail(!spw->inkscape, NULL); @@ -316,7 +316,7 @@ void SPWidgetImpl::setSelection(Application * /*inkscape*/, Selection *selection // Methods -GtkWidget *sp_widget_new_global(Inkscape::Application *inkscape) +GtkWidget *sp_widget_new_global(InkscapeApplication *inkscape) { SPWidget *spw = reinterpret_cast(g_object_new(SP_TYPE_WIDGET, NULL)); diff --git a/src/widgets/sp-widget.h b/src/widgets/sp-widget.h index e23a6da4f..b3cce32a6 100644 --- a/src/widgets/sp-widget.h +++ b/src/widgets/sp-widget.h @@ -24,20 +24,18 @@ #define SP_IS_WIDGET(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), SP_TYPE_WIDGET)) #define SP_IS_WIDGET_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), SP_TYPE_WIDGET)) +struct InkscapeApplication; namespace Inkscape { - -struct Application; class Selection; class SPWidgetImpl; - } struct SPWidget { friend class Inkscape::SPWidgetImpl; GtkBin bin; - Inkscape::Application *inkscape; + InkscapeApplication *inkscape; Inkscape::SPWidgetImpl *_impl; }; @@ -56,7 +54,7 @@ struct SPWidgetClass { GType sp_widget_get_type(); /** Generic constructor for global widget. */ -GtkWidget *sp_widget_new_global(Inkscape::Application *inkscape); +GtkWidget *sp_widget_new_global(InkscapeApplication *inkscape); #endif // SEEN_SP_WIDGET_H /* -- cgit v1.2.3 From 5a4558e956e744287f638613c5907f83300b01b8 Mon Sep 17 00:00:00 2001 From: Alex Valavanis Date: Tue, 26 Aug 2014 12:14:18 +0100 Subject: sp-canvas: GObject boilerplate reduction (bzr r13341.1.180) --- src/display/sp-canvas-item.h | 5 +- src/display/sp-canvas.cpp | 112 ++++++------------------------------------- 2 files changed, 17 insertions(+), 100 deletions(-) (limited to 'src') diff --git a/src/display/sp-canvas-item.h b/src/display/sp-canvas-item.h index f34ec453c..6781be59c 100644 --- a/src/display/sp-canvas-item.h +++ b/src/display/sp-canvas-item.h @@ -37,7 +37,7 @@ struct SPCanvasGroup; typedef struct _SPCanvasItemClass SPCanvasItemClass; -#define SP_TYPE_CANVAS_ITEM (SPCanvasItem::getType()) +#define SP_TYPE_CANVAS_ITEM (sp_canvas_item_get_type()) #define SP_CANVAS_ITEM(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), SP_TYPE_CANVAS_ITEM, SPCanvasItem)) #define SP_CANVAS_ITEM_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), SP_TYPE_CANVAS_ITEM, SPCanvasItemClass)) #define SP_IS_CANVAS_ITEM(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), SP_TYPE_CANVAS_ITEM)) @@ -50,7 +50,6 @@ typedef struct _SPCanvasItemClass SPCanvasItemClass; */ struct SPCanvasItem { GInitiallyUnowned parent_instance; - static GType getType(); SPCanvas *canvas; SPCanvasItem *parent; @@ -73,6 +72,8 @@ struct SPCanvasItem { bool in_destruction; }; +GType sp_canvas_item_get_type(); + /** * The vtable of an SPCanvasItem. */ diff --git a/src/display/sp-canvas.cpp b/src/display/sp-canvas.cpp index 8434f6ae2..e9892c684 100644 --- a/src/display/sp-canvas.cpp +++ b/src/display/sp-canvas.cpp @@ -61,8 +61,6 @@ struct SPCanvasGroupClass { * A group of Items. */ struct SPCanvasGroup { - static GType getType(); - /** * Adds an item to a canvas group. */ @@ -113,17 +111,8 @@ struct SPCanvasGroup { GList *items; GList *last; - - static SPCanvasItemClass *parentClass; }; -SPCanvasItemClass *SPCanvasGroup::parentClass; - -GType sp_canvas_group_get_type() -{ - return SPCanvasGroup::getType(); -} - /** * The SPCanvas vtable. */ @@ -161,19 +150,6 @@ enum { LAST_SIGNAL }; -void sp_canvas_item_base_class_init(SPCanvasItemClass *klass); -void sp_canvas_item_base_class_finalize(SPCanvasItemClass *klass); - -/** - * Initializes the SPCanvasItem vtable and the "event" signal. - */ -void sp_canvas_item_class_init(SPCanvasItemClass *klass); - -/** - * Callback for initialization of SPCanvasItem. - */ -void sp_canvas_item_init(SPCanvasItem *item, SPCanvasItemClass *klass); - /** * Callback that removes item from all referers and destroys it. */ @@ -181,7 +157,6 @@ void sp_canvas_item_dispose(GObject *object); void sp_canvas_item_finalize(GObject *object); void sp_canvas_item_real_destroy(SPCanvasItem *object); -static gpointer parent_class = NULL; static guint object_signals[LAST_SIGNAL] = { 0 }; /** @@ -358,45 +333,12 @@ public: static void requestCanvasUpdate(SPCanvas *canvas); }; -GType SPCanvasItem::getType() -{ - static GType object_type = 0; - - if (!object_type) { - static GTypeInfo const object_info = { - sizeof(SPCanvasItemClass), - reinterpret_cast(sp_canvas_item_base_class_init), - reinterpret_cast(sp_canvas_item_base_class_finalize), - reinterpret_cast(sp_canvas_item_class_init), - NULL, // class_finalize - NULL, // class_data - sizeof(SPCanvasItem), - 16, // n_preallocs - reinterpret_cast(sp_canvas_item_init), - NULL // value_table - }; - - object_type = g_type_register_static(G_TYPE_INITIALLY_UNOWNED, - "SPCanvasItem", &object_info, GTypeFlags(0)); - } - - return object_type; -} - -namespace { - -void sp_canvas_item_base_class_init(SPCanvasItemClass * /*klass*/) -{ -} - -void sp_canvas_item_base_class_finalize(SPCanvasItemClass * /*klass*/) -{ -} +G_DEFINE_TYPE(SPCanvasItem, sp_canvas_item, G_TYPE_INITIALLY_UNOWNED); -void sp_canvas_item_class_init(SPCanvasItemClass *klass) +static void +sp_canvas_item_class_init(SPCanvasItemClass *klass) { GObjectClass *gobject_class = (GObjectClass *) klass; - parent_class = g_type_class_ref (G_TYPE_OBJECT); item_signals[ITEM_EVENT] = g_signal_new ("event", G_TYPE_FROM_CLASS (klass), @@ -421,7 +363,8 @@ void sp_canvas_item_class_init(SPCanvasItemClass *klass) G_TYPE_NONE, 0); } -void sp_canvas_item_init(SPCanvasItem *item, SPCanvasItemClass * /*klass*/) +static void +sp_canvas_item_init(SPCanvasItem *item) { item->xform = Geom::Affine(Geom::identity()); item->ctrlType = Inkscape::CTRL_TYPE_UNKNOWN; @@ -434,15 +377,13 @@ void sp_canvas_item_init(SPCanvasItem *item, SPCanvasItemClass * /*klass*/) item->in_destruction = false; } -} // namespace - SPCanvasItem *sp_canvas_item_new(SPCanvasGroup *parent, GType type, gchar const *first_arg_name, ...) { va_list args; g_return_val_if_fail(parent != NULL, NULL); g_return_val_if_fail(SP_IS_CANVAS_GROUP(parent), NULL); - g_return_val_if_fail(g_type_is_a(type, SPCanvasItem::getType()), NULL); + g_return_val_if_fail(g_type_is_a(type, SP_TYPE_CANVAS_ITEM), NULL); SPCanvasItem *item = SP_CANVAS_ITEM(g_object_new(type, NULL)); @@ -554,7 +495,7 @@ void sp_canvas_item_dispose(GObject *object) item->in_destruction = false; } - G_OBJECT_CLASS(parent_class)->dispose(object); + G_OBJECT_CLASS(sp_canvas_item_parent_class)->dispose(object); } void sp_canvas_item_real_destroy(SPCanvasItem *object) @@ -574,7 +515,7 @@ void sp_canvas_item_finalize(GObject *gobject) "and must be removed with g_object_ref_sink()."); } - G_OBJECT_CLASS (parent_class)->finalize (gobject); + G_OBJECT_CLASS (sp_canvas_item_parent_class)->finalize (gobject); } } // namespace @@ -982,37 +923,12 @@ gint sp_canvas_item_order (SPCanvasItem * item) } // SPCanvasGroup +G_DEFINE_TYPE(SPCanvasGroup, sp_canvas_group, SP_TYPE_CANVAS_ITEM); -/** - * Registers SPCanvasGroup class with Gtk and returns its type number. - */ -GType SPCanvasGroup::getType(void) -{ - static GType type = 0; - if (!type) { - GTypeInfo info = { - sizeof(SPCanvasGroupClass), - 0, // base_init - 0, // base_finalize - reinterpret_cast(SPCanvasGroup::classInit), - 0, // class_finalize - 0, // class_data - sizeof(SPCanvasGroup), - 0, // n_preallocs - reinterpret_cast(SPCanvasGroup::init), - 0 // value_table - }; - type = g_type_register_static(SPCanvasItem::getType(), "SPCanvasGroup", &info, static_cast(0)); - } - return type; -} - -void SPCanvasGroup::classInit(SPCanvasGroupClass *klass) +static void sp_canvas_group_class_init(SPCanvasGroupClass *klass) { SPCanvasItemClass *item_class = reinterpret_cast(klass); - parentClass = reinterpret_cast(g_type_class_peek_parent(klass)); - item_class->destroy = SPCanvasGroup::destroy; item_class->update = SPCanvasGroup::update; item_class->render = SPCanvasGroup::render; @@ -1020,7 +936,7 @@ void SPCanvasGroup::classInit(SPCanvasGroupClass *klass) item_class->viewbox_changed = SPCanvasGroup::viewboxChanged; } -void SPCanvasGroup::init(SPCanvasGroup * /*group*/) +static void sp_canvas_group_init(SPCanvasGroup * /*group*/) { // Nothing here } @@ -1040,8 +956,8 @@ void SPCanvasGroup::destroy(SPCanvasItem *object) sp_canvas_item_destroy(child); } - if (SP_CANVAS_ITEM_CLASS(parentClass)->destroy) { - (* SP_CANVAS_ITEM_CLASS(parentClass)->destroy)(object); + if (SP_CANVAS_ITEM_CLASS(sp_canvas_group_parent_class)->destroy) { + (* SP_CANVAS_ITEM_CLASS(sp_canvas_group_parent_class)->destroy)(object); } } @@ -1238,7 +1154,7 @@ sp_canvas_init(SPCanvas *canvas) canvas->pick_event.crossing.y = 0; // Create the root item as a special case - canvas->root = SP_CANVAS_ITEM(g_object_new(SPCanvasGroup::getType(), NULL)); + canvas->root = SP_CANVAS_ITEM(g_object_new(SP_TYPE_CANVAS_GROUP, NULL)); canvas->root->canvas = canvas; g_object_ref (canvas->root); -- cgit v1.2.3 From d1dcf26b22837dfb501c165d15e95dcbd15d85ae Mon Sep 17 00:00:00 2001 From: Alex Valavanis Date: Tue, 26 Aug 2014 12:21:55 +0100 Subject: Complete reduction of GObject boilerplate (bzr r13341.1.181) --- src/display/sodipodi-ctrlrect.cpp | 38 ++++++-------------------------------- src/display/sodipodi-ctrlrect.h | 4 ++-- 2 files changed, 8 insertions(+), 34 deletions(-) (limited to 'src') diff --git a/src/display/sodipodi-ctrlrect.cpp b/src/display/sodipodi-ctrlrect.cpp index e6e427047..75789ff50 100644 --- a/src/display/sodipodi-ctrlrect.cpp +++ b/src/display/sodipodi-ctrlrect.cpp @@ -26,45 +26,19 @@ * Corner coords can be in any order - i.e. x1 < x0 is allowed */ -static void sp_ctrlrect_class_init(SPCtrlRectClass *c); -static void sp_ctrlrect_init(CtrlRect *ctrlrect); static void sp_ctrlrect_destroy(SPCanvasItem *object); static void sp_ctrlrect_update(SPCanvasItem *item, Geom::Affine const &affine, unsigned int flags); static void sp_ctrlrect_render(SPCanvasItem *item, SPCanvasBuf *buf); -static SPCanvasItemClass *parent_class; - static const guint DASH_LENGTH = 4; -GType sp_ctrlrect_get_type() -{ - static GType type = 0; - - if (!type) { - GTypeInfo info = { - sizeof(SPCtrlRectClass), - 0, // base_init - 0, // base_finalize - (GClassInitFunc)sp_ctrlrect_class_init, - 0, // class_finalize - 0, // class_data - sizeof(CtrlRect), - 0, // n_preallocs - (GInstanceInitFunc)sp_ctrlrect_init, - 0 // value_table - }; - type = g_type_register_static(SP_TYPE_CANVAS_ITEM, "SPCtrlRect", &info, static_cast(0)); - } - return type; -} +G_DEFINE_TYPE(CtrlRect, sp_ctrlrect, SP_TYPE_CANVAS_ITEM); -static void sp_ctrlrect_class_init(SPCtrlRectClass *c) +static void sp_ctrlrect_class_init(CtrlRectClass *c) { SPCanvasItemClass *item_class = SP_CANVAS_ITEM_CLASS(c); - parent_class = SP_CANVAS_ITEM_CLASS(g_type_class_peek_parent(c)); - item_class->destroy = sp_ctrlrect_destroy; item_class->update = sp_ctrlrect_update; item_class->render = sp_ctrlrect_render; @@ -77,8 +51,8 @@ static void sp_ctrlrect_init(CtrlRect *cr) static void sp_ctrlrect_destroy(SPCanvasItem *object) { - if (SP_CANVAS_ITEM_CLASS(parent_class)->destroy) { - (* SP_CANVAS_ITEM_CLASS(parent_class)->destroy)(object); + if (SP_CANVAS_ITEM_CLASS(sp_ctrlrect_parent_class)->destroy) { + (* SP_CANVAS_ITEM_CLASS(sp_ctrlrect_parent_class)->destroy)(object); } } @@ -171,8 +145,8 @@ void CtrlRect::update(Geom::Affine const &affine, unsigned int flags) using Geom::X; using Geom::Y; - if ((SP_CANVAS_ITEM_CLASS(parent_class))->update) { - (SP_CANVAS_ITEM_CLASS(parent_class))->update(this, affine, flags); + if ((SP_CANVAS_ITEM_CLASS(sp_ctrlrect_parent_class))->update) { + (SP_CANVAS_ITEM_CLASS(sp_ctrlrect_parent_class))->update(this, affine, flags); } sp_canvas_item_reset_bounds(this); diff --git a/src/display/sodipodi-ctrlrect.h b/src/display/sodipodi-ctrlrect.h index 65a40a850..ff6c55b06 100644 --- a/src/display/sodipodi-ctrlrect.h +++ b/src/display/sodipodi-ctrlrect.h @@ -26,7 +26,7 @@ struct SPCanvasBuf; #define SP_TYPE_CTRLRECT (sp_ctrlrect_get_type ()) #define SP_CTRLRECT(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), SP_TYPE_CTRLRECT, CtrlRect)) -#define SP_CTRLRECT_CLASS(c) (G_TYPE_CHECK_CLASS_CAST((c), SP_TYPE_CTRLRECT, SPCtrlRectClass)) +#define SP_CTRLRECT_CLASS(c) (G_TYPE_CHECK_CLASS_CAST((c), SP_TYPE_CTRLRECT, CtrlRectClass)) #define SP_IS_CTRLRECT(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), SP_TYPE_CTRLRECT)) #define SP_IS_CTRLRECT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), SP_TYPE_CTRLRECT)) @@ -57,7 +57,7 @@ private: int _shadow; }; -struct SPCtrlRectClass : public SPCanvasItemClass {}; +struct CtrlRectClass : public SPCanvasItemClass {}; GType sp_ctrlrect_get_type(); -- cgit v1.2.3 From 604d6716361abbb6f0a71679c10a1f490d604541 Mon Sep 17 00:00:00 2001 From: Alex Valavanis Date: Tue, 26 Aug 2014 13:24:21 +0100 Subject: svg-view-widget: Gtk+ 3 fixes (bzr r13341.1.182) --- src/svg-view-widget.cpp | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/svg-view-widget.cpp b/src/svg-view-widget.cpp index 657ddb2bb..c568d3ca7 100644 --- a/src/svg-view-widget.cpp +++ b/src/svg-view-widget.cpp @@ -14,7 +14,6 @@ * Released under GNU GPL, read the file 'COPYING' for more information */ -#include #include "display/sp-canvas.h" #include "display/sp-canvas-group.h" #include "display/canvas-arena.h" @@ -69,7 +68,6 @@ static void sp_svg_view_widget_class_init(SPSVGSPViewWidgetClass *klass) */ static void sp_svg_view_widget_init(SPSVGSPViewWidget *vw) { - GtkStyle *style; SPCanvasItem *parent; /* Settings */ @@ -92,14 +90,22 @@ static void sp_svg_view_widget_init(SPSVGSPViewWidget *vw) vw->canvas = SPCanvas::createAA(); -#if !GTK_CHECK_VERSION(3,0,0) +#if GTK_CHECK_VERSION(3,0,0) + GdkRGBA white = {1,1,1,0}; + gtk_widget_override_background_color(vw->canvas, GTK_STATE_FLAG_NORMAL, &white); +#else gtk_widget_pop_colormap (); -#endif - - style = gtk_style_copy (gtk_widget_get_style (vw->canvas)); + GtkStyle *style = gtk_style_copy (gtk_widget_get_style (vw->canvas)); style->bg[GTK_STATE_NORMAL] = style->white; gtk_widget_set_style (vw->canvas, style); +#endif + +#if GTK_CHECK_VERSION(3,8,0) + gtk_container_add (GTK_CONTAINER (vw->sw), vw->canvas); +#else gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW (vw->sw), vw->canvas); +#endif + gtk_widget_show (vw->canvas); /* View */ -- cgit v1.2.3 From 7fd8ede6c698136bfa675dd4f1d5da6f5803154f Mon Sep 17 00:00:00 2001 From: Diederik van Lierop Date: Tue, 26 Aug 2014 22:38:14 +0200 Subject: Fix rotation center regression caused by my own commit 13512 Fixed bugs: - https://launchpad.net/bugs/1360953 - https://launchpad.net/bugs/1360946 (bzr r13534) --- src/sp-item.cpp | 20 ++++++++++++++------ src/ui/dialog/document-properties.cpp | 10 +++++++--- 2 files changed, 21 insertions(+), 9 deletions(-) (limited to 'src') diff --git a/src/sp-item.cpp b/src/sp-item.cpp index 428f9555e..19dc71785 100644 --- a/src/sp-item.cpp +++ b/src/sp-item.cpp @@ -234,9 +234,13 @@ void SPItem::setCenter(Geom::Point const &object_centre) { document->ensureUpToDate(); // Copied from DocumentProperties::onDocUnitChange() - gdouble viewscale_w = this->document->getWidth().value("px") / this->document->getRoot()->viewBox.width(); - gdouble viewscale_h = this->document->getHeight().value("px")/ this->document->getRoot()->viewBox.height(); - gdouble viewscale = std::min(viewscale_h, viewscale_w); + gdouble viewscale = 1.0; + Geom::Rect vb = this->document->getRoot()->viewBox; + if ( !vb.hasZeroArea() ) { + gdouble viewscale_w = this->document->getWidth().value("px") / vb.width(); + gdouble viewscale_h = this->document->getHeight().value("px")/ vb.height(); + viewscale = std::min(viewscale_h, viewscale_w); + } // FIXME this is seriously wrong Geom::OptRect bbox = desktopGeometricBounds(); @@ -267,9 +271,13 @@ Geom::Point SPItem::getCenter() const { document->ensureUpToDate(); // Copied from DocumentProperties::onDocUnitChange() - gdouble viewscale_w = this->document->getWidth().value("px") / this->document->getRoot()->viewBox.width(); - gdouble viewscale_h = this->document->getHeight().value("px")/ this->document->getRoot()->viewBox.height(); - gdouble viewscale = std::min(viewscale_h, viewscale_w); + gdouble viewscale = 1.0; + Geom::Rect vb = this->document->getRoot()->viewBox; + if ( !vb.hasZeroArea() ) { + gdouble viewscale_w = this->document->getWidth().value("px") / vb.width(); + gdouble viewscale_h = this->document->getHeight().value("px")/ vb.height(); + viewscale = std::min(viewscale_h, viewscale_w); + } // FIXME this is seriously wrong Geom::OptRect bbox = desktopGeometricBounds(); diff --git a/src/ui/dialog/document-properties.cpp b/src/ui/dialog/document-properties.cpp index 4e4616724..2757a0ec9 100644 --- a/src/ui/dialog/document-properties.cpp +++ b/src/ui/dialog/document-properties.cpp @@ -1736,9 +1736,13 @@ void DocumentProperties::onDocUnitChange() prefs->setBool("/options/transform/gradient", true); { ShapeEditor::blockSetItem(true); - gdouble viewscale_w = doc->getWidth().value("px")/doc->getRoot()->viewBox.width(); - gdouble viewscale_h = doc->getHeight().value("px")/doc->getRoot()->viewBox.height(); - gdouble viewscale = std::min(viewscale_h, viewscale_w); + gdouble viewscale = 1.0; + Geom::Rect vb = doc->getRoot()->viewBox; + if ( !vb.hasZeroArea() ) { + gdouble viewscale_w = doc->getWidth().value("px") / vb.width(); + gdouble viewscale_h = doc->getHeight().value("px")/ vb.height(); + viewscale = std::min(viewscale_h, viewscale_w); + } gdouble scale = Inkscape::Util::Quantity::convert(1, old_doc_unit, doc_unit); doc->getRoot()->scaleChildItemsRec(Geom::Scale(scale), Geom::Point(-viewscale*doc->getRoot()->viewBox.min()[Geom::X] + (doc->getWidth().value("px") - viewscale*doc->getRoot()->viewBox.width())/2, -- cgit v1.2.3 From 65e028240540fafc4269bd43e66cdeaf41408b12 Mon Sep 17 00:00:00 2001 From: Nicolas Dufour Date: Sat, 30 Aug 2014 08:24:40 +0200 Subject: Translators list update (bzr r13536) --- src/ui/dialog/aboutbox.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/ui/dialog/aboutbox.cpp b/src/ui/dialog/aboutbox.cpp index a66855b2a..7cd069132 100644 --- a/src/ui/dialog/aboutbox.cpp +++ b/src/ui/dialog/aboutbox.cpp @@ -482,6 +482,7 @@ void AboutBox::initStrings() { "Elias Norberg , 2009.\n" "Equipe de Tradução Inkscape Brasil , 2007.\n" "Fatih Demir , 2000.\n" +"Firas Hanife , 2014.\n" "Foppe Benedictus , 2007-2009.\n" "Francesc Dorca , 2003. TraducciĂł sodipodi.\n" "Francisco Javier F. Serrador , 2003.\n" @@ -493,8 +494,9 @@ void AboutBox::initStrings() { "Hizkuntza Politikarako Sailburuordetza , 2005.\n" "Ilia Penev , 2006.\n" "Ivan MasĂĄr , 2006-2010. \n" +"Ivan ƘihoĆĄek , 2014.\n" "Iñaki Larrañaga , 2006.\n" -"Jānis Eisaks , 2012, 2013.\n" +"Jānis Eisaks , 2012-2014.\n" "Jeffrey Steve BorbĂłn Sanabria , 2005.\n" "Jesper Öqvist , 2010, 2011.\n" "Joaquim Perez i Noguer , 2008-2009.\n" @@ -516,7 +518,7 @@ void AboutBox::initStrings() { "Kingsley Turner , 2006.\n" "Kitae , 2006.\n" "Kjartan Maraas , 2000-2002.\n" -"Kris De Gussem , 2008-2013.\n" +"Kris De Gussem , 2008-2014.\n" "Lauris Kaplinski , 2000.\n" "Leandro Regueiro , 2006-2008, 2010.\n" "Liu Xiaoqin , 2008.\n" @@ -536,7 +538,7 @@ void AboutBox::initStrings() { "Muhammad Bashir Al-Noimi , 2008.\n" "Myckel Habets , 2008.\n" "Nguyen Dinh Trung , 2007, 2008.\n" -"Nicolas Dufour , 2008-2013.\n" +"Nicolas Dufour , 2008-2014.\n" "Pawan Chitrakar , 2006.\n" "PrzemysƂaw Loesch , 2005.\n" "Quico Llach , 2000. TraducciĂł sodipodi.\n" -- cgit v1.2.3 From 9066e62e9f0cb4972f3b7988004393e96e55e09d Mon Sep 17 00:00:00 2001 From: Alex Valavanis Date: Sat, 30 Aug 2014 12:00:43 +0100 Subject: Fix modelines (bzr r13341.1.183) --- src/livarot/PathStroke.cpp | 18 +++++++++--------- src/ui/dialog/aboutbox.cpp | 6 +++--- src/ui/dialog/aboutbox.h | 6 +++--- src/ui/dialog/inkscape-preferences.h | 4 ++-- src/ui/widget/button.cpp | 6 +++--- src/ui/widget/button.h | 6 +++--- src/ui/widget/entity-entry.cpp | 4 ++-- src/ui/widget/entity-entry.h | 4 ++-- src/ui/widget/licensor.cpp | 4 ++-- src/ui/widget/licensor.h | 4 ++-- src/ui/widget/notebook-page.cpp | 6 +++--- src/ui/widget/notebook-page.h | 6 +++--- src/ui/widget/page-sizer.cpp | 4 ++-- src/ui/widget/page-sizer.h | 4 ++-- src/ui/widget/preferences-widget.h | 4 ++-- src/ui/widget/registered-widget.cpp | 4 ++-- src/ui/widget/registered-widget.h | 4 ++-- src/ui/widget/registry.cpp | 4 ++-- src/ui/widget/registry.h | 4 ++-- src/ui/widget/rotateable.cpp | 6 +++--- src/ui/widget/rotateable.h | 4 ++-- src/ui/widget/selected-style.cpp | 4 ++-- src/ui/widget/selected-style.h | 6 +++--- src/ui/widget/spin-scale.cpp | 6 +++--- src/ui/widget/spin-scale.h | 6 +++--- src/ui/widget/spin-slider.cpp | 6 +++--- src/ui/widget/spin-slider.h | 6 +++--- src/ui/widget/spinbutton.cpp | 6 +++--- src/ui/widget/spinbutton.h | 6 +++--- src/ui/widget/style-swatch.cpp | 4 ++-- src/ui/widget/style-swatch.h | 6 +++--- src/ui/widget/tolerance-slider.cpp | 4 ++-- src/ui/widget/tolerance-slider.h | 4 ++-- src/ui/widget/unit-menu.cpp | 6 +++--- src/ui/widget/unit-menu.h | 4 ++-- 35 files changed, 93 insertions(+), 93 deletions(-) (limited to 'src') diff --git a/src/livarot/PathStroke.cpp b/src/livarot/PathStroke.cpp index 50c335176..6ec7fa209 100644 --- a/src/livarot/PathStroke.cpp +++ b/src/livarot/PathStroke.cpp @@ -748,12 +748,12 @@ void Path::RecRound(Shape *dest, int sNo, int eNo, // start and end index } /* - Local Variables: -mode:c++ -c-file-style:"stroustrup" -c-file-offsets:((innamespace . 0)(inline-open . 0)) -indent-tabs-mode:nil -fill-column:99 -End: - */ -// vim: filetype=c++:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 : + 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 : diff --git a/src/ui/dialog/aboutbox.cpp b/src/ui/dialog/aboutbox.cpp index a66855b2a..44ed3b58f 100644 --- a/src/ui/dialog/aboutbox.cpp +++ b/src/ui/dialog/aboutbox.cpp @@ -941,13 +941,13 @@ void AboutBox::initStrings() { } // namespace UI } // namespace Inkscape -/* +/* Local Variables: mode:c++ c-file-style:"stroustrup" - c-file-offsets:((innamespace . 0)(inline-open . 0)) + c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +)) indent-tabs-mode:nil fill-column:99 End: */ -// vim: filetype=c++:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 : +// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 : diff --git a/src/ui/dialog/aboutbox.h b/src/ui/dialog/aboutbox.h index 7b3308672..015e344a1 100644 --- a/src/ui/dialog/aboutbox.h +++ b/src/ui/dialog/aboutbox.h @@ -55,13 +55,13 @@ private: #endif // INKSCAPE_UI_DIALOG_ABOUTBOX_H -/* +/* Local Variables: mode:c++ c-file-style:"stroustrup" - c-file-offsets:((innamespace . 0)(inline-open . 0)) + c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +)) indent-tabs-mode:nil fill-column:99 End: */ -// vim: filetype=c++:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 : +// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 : diff --git a/src/ui/dialog/inkscape-preferences.h b/src/ui/dialog/inkscape-preferences.h index 9f37626ed..dcea91741 100644 --- a/src/ui/dialog/inkscape-preferences.h +++ b/src/ui/dialog/inkscape-preferences.h @@ -545,9 +545,9 @@ private: Local Variables: mode:c++ c-file-style:"stroustrup" - c-file-offsets:((innamespace . 0)(inline-open . 0)) + c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +)) indent-tabs-mode:nil fill-column:99 End: */ -// vim: filetype=c++:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 : +// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 : diff --git a/src/ui/widget/button.cpp b/src/ui/widget/button.cpp index bac866920..6c2d419cf 100644 --- a/src/ui/widget/button.cpp +++ b/src/ui/widget/button.cpp @@ -51,13 +51,13 @@ RadioButton::RadioButton(Glib::ustring const &label, Glib::ustring const &toolti } // namespace UI } // namespace Inkscape -/* +/* Local Variables: mode:c++ c-file-style:"stroustrup" - c-file-offsets:((innamespace . 0)(inline-open . 0)) + c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +)) indent-tabs-mode:nil fill-column:99 End: */ -// vim: filetype=c++:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 : +// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 : diff --git a/src/ui/widget/button.h b/src/ui/widget/button.h index a214dd881..471b7d8a2 100644 --- a/src/ui/widget/button.h +++ b/src/ui/widget/button.h @@ -67,13 +67,13 @@ public: #endif // INKSCAPE_UI_WIDGET_BUTTON_H -/* +/* Local Variables: mode:c++ c-file-style:"stroustrup" - c-file-offsets:((innamespace . 0)(inline-open . 0)) + c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +)) indent-tabs-mode:nil fill-column:99 End: */ -// vim: filetype=c++:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 : +// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 : diff --git a/src/ui/widget/entity-entry.cpp b/src/ui/widget/entity-entry.cpp index 0f526f77a..c7d5efe29 100644 --- a/src/ui/widget/entity-entry.cpp +++ b/src/ui/widget/entity-entry.cpp @@ -206,9 +206,9 @@ EntityMultiLineEntry::on_changed() Local Variables: mode:c++ c-file-style:"stroustrup" - c-file-offsets:((innamespace . 0)(inline-open . 0)) + c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +)) indent-tabs-mode:nil fill-column:99 End: */ -// vim: filetype=c++:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 : +// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 : diff --git a/src/ui/widget/entity-entry.h b/src/ui/widget/entity-entry.h index 09289496d..35f6ecfb4 100644 --- a/src/ui/widget/entity-entry.h +++ b/src/ui/widget/entity-entry.h @@ -76,9 +76,9 @@ protected: Local Variables: mode:c++ c-file-style:"stroustrup" - c-file-offsets:((innamespace . 0)(inline-open . 0)) + c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +)) indent-tabs-mode:nil fill-column:99 End: */ -// vim: filetype=c++:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 : +// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 : diff --git a/src/ui/widget/licensor.cpp b/src/ui/widget/licensor.cpp index 42f352e3c..7429bb07e 100644 --- a/src/ui/widget/licensor.cpp +++ b/src/ui/widget/licensor.cpp @@ -160,9 +160,9 @@ void Licensor::update (SPDocument *doc) Local Variables: mode:c++ c-file-style:"stroustrup" - c-file-offsets:((innamespace . 0)(inline-open . 0)) + c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +)) indent-tabs-mode:nil fill-column:99 End: */ -// vim: filetype=c++:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 : +// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 : diff --git a/src/ui/widget/licensor.h b/src/ui/widget/licensor.h index 0ac3e5ab8..c75c5fe9e 100644 --- a/src/ui/widget/licensor.h +++ b/src/ui/widget/licensor.h @@ -56,9 +56,9 @@ protected: Local Variables: mode:c++ c-file-style:"stroustrup" - c-file-offsets:((innamespace . 0)(inline-open . 0)) + c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +)) indent-tabs-mode:nil fill-column:99 End: */ -// vim: filetype=c++:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 : +// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 : diff --git a/src/ui/widget/notebook-page.cpp b/src/ui/widget/notebook-page.cpp index 6653499b8..2f03ed23b 100644 --- a/src/ui/widget/notebook-page.cpp +++ b/src/ui/widget/notebook-page.cpp @@ -44,13 +44,13 @@ NotebookPage::NotebookPage(int n_rows, int n_columns, bool expand, bool fill, gu } // namespace UI } // namespace Inkscape -/* +/* Local Variables: mode:c++ c-file-style:"stroustrup" - c-file-offsets:((innamespace . 0)(inline-open . 0)) + c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +)) indent-tabs-mode:nil fill-column:99 End: */ -// vim: filetype=c++:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 : +// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 : diff --git a/src/ui/widget/notebook-page.h b/src/ui/widget/notebook-page.h index 38ae9e054..4f7915423 100644 --- a/src/ui/widget/notebook-page.h +++ b/src/ui/widget/notebook-page.h @@ -67,13 +67,13 @@ protected: #endif // INKSCAPE_UI_WIDGET_NOTEBOOK_PAGE_H -/* +/* Local Variables: mode:c++ c-file-style:"stroustrup" - c-file-offsets:((innamespace . 0)(inline-open . 0)) + c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +)) indent-tabs-mode:nil fill-column:99 End: */ -// vim: filetype=c++:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 : +// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 : diff --git a/src/ui/widget/page-sizer.cpp b/src/ui/widget/page-sizer.cpp index eae0d4a95..89b0b8f7e 100644 --- a/src/ui/widget/page-sizer.cpp +++ b/src/ui/widget/page-sizer.cpp @@ -728,9 +728,9 @@ PageSizer::on_units_changed() Local Variables: mode:c++ c-file-style:"stroustrup" - c-file-offsets:((innamespace . 0)(inline-open . 0)) + c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +)) indent-tabs-mode:nil fill-column:99 End: */ -// vim: filetype=c++:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 : +// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 : diff --git a/src/ui/widget/page-sizer.h b/src/ui/widget/page-sizer.h index dc8e34d82..f4bcae4b6 100644 --- a/src/ui/widget/page-sizer.h +++ b/src/ui/widget/page-sizer.h @@ -277,9 +277,9 @@ protected: Local Variables: mode:c++ c-file-style:"stroustrup" - c-file-offsets:((innamespace . 0)(inline-open . 0)) + c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +)) indent-tabs-mode:nil fill-column:99 End: */ -// vim: filetype=c++:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 : +// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 : diff --git a/src/ui/widget/preferences-widget.h b/src/ui/widget/preferences-widget.h index cb4ce17d1..5d9816e74 100644 --- a/src/ui/widget/preferences-widget.h +++ b/src/ui/widget/preferences-widget.h @@ -306,9 +306,9 @@ public: Local Variables: mode:c++ c-file-style:"stroustrup" - c-file-offsets:((innamespace . 0)(inline-open . 0)) + c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +)) indent-tabs-mode:nil fill-column:99 End: */ -// vim: filetype=c++:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 : +// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 : diff --git a/src/ui/widget/registered-widget.cpp b/src/ui/widget/registered-widget.cpp index 8a81b1c02..44d8dcbf3 100644 --- a/src/ui/widget/registered-widget.cpp +++ b/src/ui/widget/registered-widget.cpp @@ -788,9 +788,9 @@ RegisteredRandom::on_value_changed() Local Variables: mode:c++ c-file-style:"stroustrup" - c-file-offsets:((innamespace . 0)(inline-open . 0)) + c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +)) indent-tabs-mode:nil fill-column:99 End: */ -// vim: filetype=c++:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 : +// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 : diff --git a/src/ui/widget/registered-widget.h b/src/ui/widget/registered-widget.h index d8c0e6602..1f505a3cd 100644 --- a/src/ui/widget/registered-widget.h +++ b/src/ui/widget/registered-widget.h @@ -419,9 +419,9 @@ protected: Local Variables: mode:c++ c-file-style:"stroustrup" - c-file-offsets:((innamespace . 0)(inline-open . 0)) + c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +)) indent-tabs-mode:nil fill-column:99 End: */ -// vim: filetype=c++:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 : +// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 : diff --git a/src/ui/widget/registry.cpp b/src/ui/widget/registry.cpp index 725e52791..ea8198422 100644 --- a/src/ui/widget/registry.cpp +++ b/src/ui/widget/registry.cpp @@ -48,9 +48,9 @@ Registry::setUpdating (bool upd) Local Variables: mode:c++ c-file-style:"stroustrup" - c-file-offsets:((innamespace . 0)(inline-open . 0)) + c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +)) indent-tabs-mode:nil fill-column:99 End: */ -// vim: filetype=c++:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 : +// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 : diff --git a/src/ui/widget/registry.h b/src/ui/widget/registry.h index 2da29735c..a236b96ad 100644 --- a/src/ui/widget/registry.h +++ b/src/ui/widget/registry.h @@ -39,9 +39,9 @@ protected: Local Variables: mode:c++ c-file-style:"stroustrup" - c-file-offsets:((innamespace . 0)(inline-open . 0)) + c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +)) indent-tabs-mode:nil fill-column:99 End: */ -// vim: filetype=c++:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 : +// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 : diff --git a/src/ui/widget/rotateable.cpp b/src/ui/widget/rotateable.cpp index 72ec69362..2d7597d7c 100644 --- a/src/ui/widget/rotateable.cpp +++ b/src/ui/widget/rotateable.cpp @@ -173,13 +173,13 @@ Rotateable::~Rotateable() { } // namespace UI } // namespace Inkscape -/* +/* Local Variables: mode:c++ c-file-style:"stroustrup" - c-file-offsets:((innamespace . 0)(inline-open . 0)) + c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +)) indent-tabs-mode:nil fill-column:99 End: */ -// vim: filetype=c++:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 : +// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 : diff --git a/src/ui/widget/rotateable.h b/src/ui/widget/rotateable.h index 52fb5306c..6404c3550 100644 --- a/src/ui/widget/rotateable.h +++ b/src/ui/widget/rotateable.h @@ -62,9 +62,9 @@ private: Local Variables: mode:c++ c-file-style:"stroustrup" - c-file-offsets:((innamespace . 0)(inline-open . 0)) + c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +)) indent-tabs-mode:nil fill-column:99 End: */ -// vim: filetype=c++:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 : +// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 : diff --git a/src/ui/widget/selected-style.cpp b/src/ui/widget/selected-style.cpp index 85538c8c7..a0a163286 100644 --- a/src/ui/widget/selected-style.cpp +++ b/src/ui/widget/selected-style.cpp @@ -1571,9 +1571,9 @@ Dialog::FillAndStroke *get_fill_and_stroke_panel(SPDesktop *desktop) Local Variables: mode:c++ c-file-style:"stroustrup" - c-file-offsets:((innamespace . 0)(inline-open . 0)) + c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +)) indent-tabs-mode:nil fill-column:99 End: */ -// vim: filetype=c++:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 : +// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 : diff --git a/src/ui/widget/selected-style.h b/src/ui/widget/selected-style.h index df0f41507..0b6a14762 100644 --- a/src/ui/widget/selected-style.h +++ b/src/ui/widget/selected-style.h @@ -301,13 +301,13 @@ protected: #endif // INKSCAPE_UI_WIDGET_BUTTON_H -/* +/* Local Variables: mode:c++ c-file-style:"stroustrup" - c-file-offsets:((innamespace . 0)(inline-open . 0)) + c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +)) indent-tabs-mode:nil fill-column:99 End: */ -// vim: filetype=c++:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 : +// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 : diff --git a/src/ui/widget/spin-scale.cpp b/src/ui/widget/spin-scale.cpp index ade3d1e60..bb08d67df 100644 --- a/src/ui/widget/spin-scale.cpp +++ b/src/ui/widget/spin-scale.cpp @@ -235,13 +235,13 @@ void DualSpinScale::update_linked() } // namespace UI } // namespace Inkscape -/* +/* Local Variables: mode:c++ c-file-style:"stroustrup" - c-file-offsets:((innamespace . 0)(inline-open . 0)) + c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +)) indent-tabs-mode:nil fill-column:99 End: */ -// vim: filetype=c++:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 : +// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 : diff --git a/src/ui/widget/spin-scale.h b/src/ui/widget/spin-scale.h index 5fec8b1d8..d0447e4a6 100644 --- a/src/ui/widget/spin-scale.h +++ b/src/ui/widget/spin-scale.h @@ -113,13 +113,13 @@ private: #endif // INKSCAPE_UI_WIDGET_SPIN_SCALE_H -/* +/* Local Variables: mode:c++ c-file-style:"stroustrup" - c-file-offsets:((innamespace . 0)(inline-open . 0)) + c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +)) indent-tabs-mode:nil fill-column:99 End: */ -// vim: filetype=c++:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 : +// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 : diff --git a/src/ui/widget/spin-slider.cpp b/src/ui/widget/spin-slider.cpp index 1cb59a7b3..9b361ae78 100644 --- a/src/ui/widget/spin-slider.cpp +++ b/src/ui/widget/spin-slider.cpp @@ -262,13 +262,13 @@ void DualSpinSlider::update_linked() } // namespace UI } // namespace Inkscape -/* +/* Local Variables: mode:c++ c-file-style:"stroustrup" - c-file-offsets:((innamespace . 0)(inline-open . 0)) + c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +)) indent-tabs-mode:nil fill-column:99 End: */ -// vim: filetype=c++:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 : +// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 : diff --git a/src/ui/widget/spin-slider.h b/src/ui/widget/spin-slider.h index 5f86fd15a..74982ea58 100644 --- a/src/ui/widget/spin-slider.h +++ b/src/ui/widget/spin-slider.h @@ -111,13 +111,13 @@ private: #endif // INKSCAPE_UI_WIDGET_SPIN_SLIDER_H -/* +/* Local Variables: mode:c++ c-file-style:"stroustrup" - c-file-offsets:((innamespace . 0)(inline-open . 0)) + c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +)) indent-tabs-mode:nil fill-column:99 End: */ -// vim: filetype=c++:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 : +// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 : diff --git a/src/ui/widget/spinbutton.cpp b/src/ui/widget/spinbutton.cpp index 7709a837b..d7669d4e5 100644 --- a/src/ui/widget/spinbutton.cpp +++ b/src/ui/widget/spinbutton.cpp @@ -100,13 +100,13 @@ void SpinButton::undo() } // namespace UI } // namespace Inkscape -/* +/* Local Variables: mode:c++ c-file-style:"stroustrup" - c-file-offsets:((innamespace . 0)(inline-open . 0)) + c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +)) indent-tabs-mode:nil fill-column:99 End: */ -// vim: filetype=c++:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 : +// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 : diff --git a/src/ui/widget/spinbutton.h b/src/ui/widget/spinbutton.h index 812b5f515..cbe33e8ea 100644 --- a/src/ui/widget/spinbutton.h +++ b/src/ui/widget/spinbutton.h @@ -111,13 +111,13 @@ private: #endif // INKSCAPE_UI_WIDGET_SPINBUTTON_H -/* +/* Local Variables: mode:c++ c-file-style:"stroustrup" - c-file-offsets:((innamespace . 0)(inline-open . 0)) + c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +)) indent-tabs-mode:nil fill-column:99 End: */ -// vim: filetype=c++:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 : +// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 : diff --git a/src/ui/widget/style-swatch.cpp b/src/ui/widget/style-swatch.cpp index 98f4e47cd..157fd2ad9 100644 --- a/src/ui/widget/style-swatch.cpp +++ b/src/ui/widget/style-swatch.cpp @@ -386,9 +386,9 @@ void StyleSwatch::setStyle(SPStyle *query) Local Variables: mode:c++ c-file-style:"stroustrup" - c-file-offsets:((innamespace . 0)(inline-open . 0)) + c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +)) indent-tabs-mode:nil fill-column:99 End: */ -// vim: filetype=c++:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 : +// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 : diff --git a/src/ui/widget/style-swatch.h b/src/ui/widget/style-swatch.h index 557ca82e2..582d2ebb3 100644 --- a/src/ui/widget/style-swatch.h +++ b/src/ui/widget/style-swatch.h @@ -108,13 +108,13 @@ friend class ToolObserver; #endif // INKSCAPE_UI_WIDGET_BUTTON_H -/* +/* Local Variables: mode:c++ c-file-style:"stroustrup" - c-file-offsets:((innamespace . 0)(inline-open . 0)) + c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +)) indent-tabs-mode:nil fill-column:99 End: */ -// vim: filetype=c++:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 : +// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 : diff --git a/src/ui/widget/tolerance-slider.cpp b/src/ui/widget/tolerance-slider.cpp index 5fc588fdc..aac7451f4 100644 --- a/src/ui/widget/tolerance-slider.cpp +++ b/src/ui/widget/tolerance-slider.cpp @@ -216,9 +216,9 @@ void ToleranceSlider::update (double val) Local Variables: mode:c++ c-file-style:"stroustrup" - c-file-offsets:((innamespace . 0)(inline-open . 0)) + c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +)) indent-tabs-mode:nil fill-column:99 End: */ -// vim: filetype=c++:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 : +// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 : diff --git a/src/ui/widget/tolerance-slider.h b/src/ui/widget/tolerance-slider.h index 2184cd52b..7ae8e4712 100644 --- a/src/ui/widget/tolerance-slider.h +++ b/src/ui/widget/tolerance-slider.h @@ -88,9 +88,9 @@ protected: Local Variables: mode:c++ c-file-style:"stroustrup" - c-file-offsets:((innamespace . 0)(inline-open . 0)) + c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +)) indent-tabs-mode:nil fill-column:99 End: */ -// vim: filetype=c++:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 : +// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 : diff --git a/src/ui/widget/unit-menu.cpp b/src/ui/widget/unit-menu.cpp index 7416a2f02..423313a1f 100644 --- a/src/ui/widget/unit-menu.cpp +++ b/src/ui/widget/unit-menu.cpp @@ -140,13 +140,13 @@ bool UnitMenu::isRadial() const } // namespace UI } // namespace Inkscape -/* +/* Local Variables: mode:c++ c-file-style:"stroustrup" - c-file-offsets:((innamespace . 0)(inline-open . 0)) + c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +)) indent-tabs-mode:nil fill-column:99 End: */ -// vim: filetype=c++:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 : +// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 : diff --git a/src/ui/widget/unit-menu.h b/src/ui/widget/unit-menu.h index 114c536c9..2fd25a6a9 100644 --- a/src/ui/widget/unit-menu.h +++ b/src/ui/widget/unit-menu.h @@ -141,9 +141,9 @@ protected: Local Variables: mode:c++ c-file-style:"stroustrup" - c-file-offsets:((innamespace . 0)(inline-open . 0)) + c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +)) indent-tabs-mode:nil fill-column:99 End: */ -// vim: filetype=c++:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 : +// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 : -- cgit v1.2.3 From 977857ef75a45ed1ec79cfdcf0f25dd66d4a7e86 Mon Sep 17 00:00:00 2001 From: Alex Valavanis Date: Sat, 30 Aug 2014 14:00:28 +0100 Subject: Reduce header bloat (bzr r13341.1.184) --- src/axis-manip.h | 2 +- src/desktop-events.h | 8 +++++--- src/display/sp-canvas-item.h | 4 ++-- src/display/sp-canvas.h | 1 - src/ege-adjustment-action.h | 2 -- src/ege-output-action.h | 2 -- src/ege-select-one-action.h | 2 -- src/extension/input.h | 5 ++--- src/extension/internal/emf-inout.cpp | 2 +- src/extension/internal/wmf-inout.cpp | 1 + src/extension/output.h | 1 - src/helper/action.h | 6 +----- src/icon-size.h | 2 -- src/ink-action.h | 2 -- src/ink-comboboxentry-action.h | 4 ---- src/knot.cpp | 1 + src/knot.h | 4 +--- src/proj_pt.h | 2 +- src/sp-pattern.h | 6 +----- src/ui/dialog/clonetiler.h | 1 - src/ui/dialog/export.h | 9 --------- src/ui/dialog/filedialogimpl-gtkmm.cpp | 1 + src/ui/tools/flood-tool.h | 4 +--- src/ui/tools/select-tool.h | 1 - src/ui/tools/spiral-tool.h | 8 +++----- src/ui/tools/text-tool.h | 7 +++---- src/ui/widget/unit-tracker.h | 7 +++++-- src/widgets/button.cpp | 1 + src/widgets/button.h | 12 ++++++++++-- src/widgets/eek-preview.h | 1 - src/widgets/gradient-image.h | 1 - src/widgets/gradient-selector.cpp | 4 +++- src/widgets/gradient-selector.h | 20 ++++++++------------ src/widgets/gradient-vector.h | 8 -------- src/widgets/paint-selector.h | 1 - src/widgets/sp-color-icc-selector.h | 2 -- src/widgets/sp-color-notebook.h | 1 - src/widgets/sp-color-scales.h | 2 -- src/widgets/sp-color-selector.h | 4 +--- src/widgets/sp-color-slider.h | 2 -- src/widgets/sp-color-wheel-selector.h | 1 - src/widgets/sp-widget.h | 1 - src/widgets/sp-xmlview-content.h | 2 -- src/widgets/spinbutton-events.h | 4 +++- src/widgets/toolbox.h | 6 +++--- 45 files changed, 59 insertions(+), 109 deletions(-) (limited to 'src') diff --git a/src/axis-manip.h b/src/axis-manip.h index 9392e2ddd..7842b4135 100644 --- a/src/axis-manip.h +++ b/src/axis-manip.h @@ -13,7 +13,7 @@ #define SEEN_AXIS_MANIP_H #include -#include +#include namespace Proj { diff --git a/src/desktop-events.h b/src/desktop-events.h index 7123ce91b..dc85e563b 100644 --- a/src/desktop-events.h +++ b/src/desktop-events.h @@ -13,13 +13,15 @@ * Released under GNU GPL, read the file 'COPYING' for more information */ -#include -#include - class SPDesktop; struct SPDesktopWidget; struct SPCanvasItem; +typedef union _GdkEvent GdkEvent; +typedef struct _GdkEventCrossing GdkEventCrossing; +typedef struct _GdkEventMotion GdkEventMotion; +typedef struct _GtkWidget GtkWidget; + /* Item handlers */ int sp_desktop_root_handler (SPCanvasItem *item, GdkEvent *event, SPDesktop *desktop); diff --git a/src/display/sp-canvas-item.h b/src/display/sp-canvas-item.h index 6781be59c..a388ffa91 100644 --- a/src/display/sp-canvas-item.h +++ b/src/display/sp-canvas-item.h @@ -24,8 +24,6 @@ #endif #include -#include -#include #include <2geom/rect.h> #include "ui/control-types.h" @@ -36,6 +34,8 @@ struct SPCanvasBuf; struct SPCanvasGroup; typedef struct _SPCanvasItemClass SPCanvasItemClass; +typedef union _GdkEvent GdkEvent; +typedef struct _GdkCursor GdkCursor; #define SP_TYPE_CANVAS_ITEM (sp_canvas_item_get_type()) #define SP_CANVAS_ITEM(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), SP_TYPE_CANVAS_ITEM, SPCanvasItem)) diff --git a/src/display/sp-canvas.h b/src/display/sp-canvas.h index 72ae4b6bc..adae30f35 100644 --- a/src/display/sp-canvas.h +++ b/src/display/sp-canvas.h @@ -30,7 +30,6 @@ # endif #endif -#include #include #include #include diff --git a/src/ege-adjustment-action.h b/src/ege-adjustment-action.h index 590035eb3..8cfaa3e52 100644 --- a/src/ege-adjustment-action.h +++ b/src/ege-adjustment-action.h @@ -45,9 +45,7 @@ /* Note: this file should be kept compilable as both .cpp and .c */ -#include #include -#include G_BEGIN_DECLS diff --git a/src/ege-output-action.h b/src/ege-output-action.h index fc21c2f27..0f4e21805 100644 --- a/src/ege-output-action.h +++ b/src/ege-output-action.h @@ -45,9 +45,7 @@ /* Note: this file should be kept compilable as both .cpp and .c */ -#include #include -#include G_BEGIN_DECLS diff --git a/src/ege-select-one-action.h b/src/ege-select-one-action.h index d605f4a67..0c5cecaa3 100644 --- a/src/ege-select-one-action.h +++ b/src/ege-select-one-action.h @@ -48,9 +48,7 @@ /* Note: this file should be kept compilable as both .cpp and .c */ -#include #include -#include G_BEGIN_DECLS diff --git a/src/extension/input.h b/src/extension/input.h index b01ffeb86..2a0a177a0 100644 --- a/src/extension/input.h +++ b/src/extension/input.h @@ -14,9 +14,8 @@ #include #include #include "extension.h" -#include "xml/repr.h" -#include "document.h" -#include + +class SPDocument; namespace Inkscape { namespace Extension { diff --git a/src/extension/internal/emf-inout.cpp b/src/extension/internal/emf-inout.cpp index 084fbcd58..9a5a78a34 100644 --- a/src/extension/internal/emf-inout.cpp +++ b/src/extension/internal/emf-inout.cpp @@ -27,12 +27,12 @@ # include "config.h" #endif -//#include //This must precede text_reassemble.h or it blows up in pngconf.h when compiling #include #include #include #include +#include "document.h" #include "sp-root.h" // even though it is included indirectly by wmf-inout.h #include "sp-path.h" #include "print.h" diff --git a/src/extension/internal/wmf-inout.cpp b/src/extension/internal/wmf-inout.cpp index 5ccad678a..c03e7efe0 100644 --- a/src/extension/internal/wmf-inout.cpp +++ b/src/extension/internal/wmf-inout.cpp @@ -33,6 +33,7 @@ #include #include +#include "document.h" #include "sp-root.h" // even though it is included indirectly by wmf-inout.h #include "sp-path.h" #include "print.h" diff --git a/src/extension/output.h b/src/extension/output.h index c5b1beb45..44a731ca0 100644 --- a/src/extension/output.h +++ b/src/extension/output.h @@ -13,7 +13,6 @@ #ifndef INKSCAPE_EXTENSION_OUTPUT_H__ #define INKSCAPE_EXTENSION_OUTPUT_H__ -#include #include "extension.h" class SPDocument; diff --git a/src/helper/action.h b/src/helper/action.h index 1f2de87b4..4b81ee7f9 100644 --- a/src/helper/action.h +++ b/src/helper/action.h @@ -13,12 +13,8 @@ #define SEEN_INKSCAPE_SP_ACTION_H #include "helper/action-context.h" -#include +#include #include -#include - -struct SPAction; -struct SPActionClass; #define SP_TYPE_ACTION (sp_action_get_type()) #define SP_ACTION(o) (G_TYPE_CHECK_INSTANCE_CAST((o), SP_TYPE_ACTION, SPAction)) diff --git a/src/icon-size.h b/src/icon-size.h index 4bb4f1df6..d7a9c9b0b 100644 --- a/src/icon-size.h +++ b/src/icon-size.h @@ -12,8 +12,6 @@ * Released under GNU GPL, read the file 'COPYING' for more information */ -#include - #include namespace Inkscape { diff --git a/src/ink-action.h b/src/ink-action.h index 1d4106681..ac5cb9873 100644 --- a/src/ink-action.h +++ b/src/ink-action.h @@ -2,9 +2,7 @@ #define SEEN_INK_ACTION -#include #include -#include #include "icon-size.h" #include "attributes.h" diff --git a/src/ink-comboboxentry-action.h b/src/ink-comboboxentry-action.h index a66f0790e..04b66e8fe 100644 --- a/src/ink-comboboxentry-action.h +++ b/src/ink-comboboxentry-action.h @@ -19,12 +19,8 @@ #ifndef SEEN_INK_COMBOBOXENTRY_ACTION #define SEEN_INK_COMBOBOXENTRY_ACTION -#include -#include - #include - #define INK_COMBOBOXENTRY_TYPE_ACTION (ink_comboboxentry_action_get_type()) #define INK_COMBOBOXENTRY_ACTION(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), INK_COMBOBOXENTRY_TYPE_ACTION, Ink_ComboBoxEntry_Action)) #define INK_COMBOBOXENTRY_ACTION_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), INK_COMBOBOXENTRY_TYPE_ACTION, Ink_ComboBoxEntry_ActionClass)) diff --git a/src/knot.cpp b/src/knot.cpp index 6205af26a..49b4dbb54 100644 --- a/src/knot.cpp +++ b/src/knot.cpp @@ -28,6 +28,7 @@ #include "message-stack.h" #include "message-context.h" #include "ui/tools/tool-base.h" +#include using Inkscape::DocumentUndo; diff --git a/src/knot.h b/src/knot.h index b18f89566..b79614bcb 100644 --- a/src/knot.h +++ b/src/knot.h @@ -17,14 +17,12 @@ #include #include <2geom/point.h> #include "knot-enums.h" -#include #include #include "enums.h" -#include -#include "sp-item.h" class SPDesktop; struct SPCanvasItem; +class SPItem; #define SP_KNOT(obj) (dynamic_cast(static_cast(obj))) #define SP_IS_KNOT(obj) (dynamic_cast(static_cast(obj)) != NULL) diff --git a/src/proj_pt.h b/src/proj_pt.h index 226c182cc..28ec0aca3 100644 --- a/src/proj_pt.h +++ b/src/proj_pt.h @@ -13,7 +13,7 @@ #define SEEN_PROJ_PT_H #include <2geom/point.h> -#include +#include namespace Proj { diff --git a/src/sp-pattern.h b/src/sp-pattern.h index eb34b6714..8f7dbbadd 100644 --- a/src/sp-pattern.h +++ b/src/sp-pattern.h @@ -13,21 +13,17 @@ * Released under GNU GPL, read the file 'COPYING' for more information */ -#include - -#include "sp-item.h" - #define SP_PATTERN(obj) (dynamic_cast((SPObject*)obj)) #define SP_IS_PATTERN(obj) (dynamic_cast((SPObject*)obj) != NULL) class SPPatternReference; +class SPItem; #include "svg/svg-length.h" #include "sp-paint-server.h" #include "uri-references.h" #include "viewbox.h" -#include #include diff --git a/src/ui/dialog/clonetiler.h b/src/ui/dialog/clonetiler.h index 9bacc701d..70da86338 100644 --- a/src/ui/dialog/clonetiler.h +++ b/src/ui/dialog/clonetiler.h @@ -11,7 +11,6 @@ #define __SP_CLONE_TILER_H__ #include "ui/widget/panel.h" -#include #include "ui/dialog/desktop-tracker.h" #include "ui/widget/color-picker.h" diff --git a/src/ui/dialog/export.h b/src/ui/dialog/export.h index 6f3c0dfac..23af0109b 100644 --- a/src/ui/dialog/export.h +++ b/src/ui/dialog/export.h @@ -12,20 +12,11 @@ #ifndef SP_EXPORT_H #define SP_EXPORT_H -#include -#include - -#include -#include -#include #include -#include -#include "desktop.h" #include "ui/dialog/desktop-tracker.h" #include "ui/widget/panel.h" #include "ui/widget/button.h" -#include "ui/widget/entry.h" namespace Gtk { class Dialog; diff --git a/src/ui/dialog/filedialogimpl-gtkmm.cpp b/src/ui/dialog/filedialogimpl-gtkmm.cpp index 8ba3ad684..575519848 100644 --- a/src/ui/dialog/filedialogimpl-gtkmm.cpp +++ b/src/ui/dialog/filedialogimpl-gtkmm.cpp @@ -40,6 +40,7 @@ #include #include +#include "document.h" #include "extension/input.h" #include "extension/output.h" #include "extension/db.h" diff --git a/src/ui/tools/flood-tool.h b/src/ui/tools/flood-tool.h index 3ed670e8b..5104a42e9 100644 --- a/src/ui/tools/flood-tool.h +++ b/src/ui/tools/flood-tool.h @@ -11,9 +11,7 @@ * Released under GNU GPL */ -#include -#include -#include +#include #include "ui/tools/tool-base.h" #define SP_FLOOD_CONTEXT(obj) (dynamic_cast((Inkscape::UI::Tools::ToolBase*)obj)) diff --git a/src/ui/tools/select-tool.h b/src/ui/tools/select-tool.h index edc4069a2..5af99a56a 100644 --- a/src/ui/tools/select-tool.h +++ b/src/ui/tools/select-tool.h @@ -13,7 +13,6 @@ */ #include "ui/tools/tool-base.h" -#include #define SP_SELECT_CONTEXT(obj) (dynamic_cast((Inkscape::UI::Tools::ToolBase*)obj)) #define SP_IS_SELECT_CONTEXT(obj) (dynamic_cast((const Inkscape::UI::Tools::ToolBase*)obj) != NULL) diff --git a/src/ui/tools/spiral-tool.h b/src/ui/tools/spiral-tool.h index 416aeb7e4..add92342d 100644 --- a/src/ui/tools/spiral-tool.h +++ b/src/ui/tools/spiral-tool.h @@ -15,17 +15,15 @@ * Released under GNU GPL */ -#include -#include -#include +#include #include <2geom/point.h> #include "ui/tools/tool-base.h" -#include "sp-spiral.h" - #define SP_SPIRAL_CONTEXT(obj) (dynamic_cast((Inkscape::UI::Tools::ToolBase*)obj)) #define SP_IS_SPIRAL_CONTEXT(obj) (dynamic_cast((const Inkscape::UI::Tools::ToolBase*)obj) != NULL) +class SPSpiral; + namespace Inkscape { namespace UI { namespace Tools { diff --git a/src/ui/tools/text-tool.h b/src/ui/tools/text-tool.h index ca2b3d19a..289ee180d 100644 --- a/src/ui/tools/text-tool.h +++ b/src/ui/tools/text-tool.h @@ -14,10 +14,7 @@ * Released under GNU GPL, read the file 'COPYING' for more information */ -/* #include */ -#include -#include -#include +#include #include "ui/tools/tool-base.h" #include <2geom/point.h> @@ -26,6 +23,8 @@ #define SP_TEXT_CONTEXT(obj) (dynamic_cast((Inkscape::UI::Tools::ToolBase*)obj)) #define SP_IS_TEXT_CONTEXT(obj) (dynamic_cast((const Inkscape::UI::Tools::ToolBase*)obj) != NULL) +typedef struct _GtkIMContext GtkIMContext; + struct SPCtrlLine; namespace Inkscape { diff --git a/src/ui/widget/unit-tracker.h b/src/ui/widget/unit-tracker.h index 61bb556ef..06245930e 100644 --- a/src/ui/widget/unit-tracker.h +++ b/src/ui/widget/unit-tracker.h @@ -16,13 +16,16 @@ #define INKSCAPE_UI_WIDGET_UNIT_TRACKER_H #include -#include - #include "util/units.h" using Inkscape::Util::Unit; using Inkscape::Util::UnitType; +typedef struct _GObject GObject; +typedef struct _GtkAction GtkAction; +typedef struct _GtkAdjustment GtkAdjustment; +typedef struct _GtkListStore GtkListStore; + namespace Inkscape { namespace UI { namespace Widget { diff --git a/src/widgets/button.cpp b/src/widgets/button.cpp index f97bba072..cda97654e 100644 --- a/src/widgets/button.cpp +++ b/src/widgets/button.cpp @@ -18,6 +18,7 @@ #include "helper/action-context.h" #include "interface.h" #include "shortcuts.h" +#include "helper/action.h" #include diff --git a/src/widgets/button.h b/src/widgets/button.h index d5e29da1a..2bceb5e97 100644 --- a/src/widgets/button.h +++ b/src/widgets/button.h @@ -17,10 +17,18 @@ #define SP_IS_BUTTON(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), SP_TYPE_BUTTON)) #include -#include -#include "helper/action.h" +#include #include "icon-size.h" +struct SPAction; + +namespace Inkscape { +namespace UI { +namespace View { +class View; +} +} +} typedef enum { SP_BUTTON_TYPE_NORMAL, diff --git a/src/widgets/eek-preview.h b/src/widgets/eek-preview.h index e4c724cc5..883ce713e 100644 --- a/src/widgets/eek-preview.h +++ b/src/widgets/eek-preview.h @@ -37,7 +37,6 @@ #ifndef SEEN_EEK_PREVIEW_H #define SEEN_EEK_PREVIEW_H -#include #include /** diff --git a/src/widgets/gradient-image.h b/src/widgets/gradient-image.h index 6a9c89acf..0d3833441 100644 --- a/src/widgets/gradient-image.h +++ b/src/widgets/gradient-image.h @@ -17,7 +17,6 @@ class SPGradient; -#include #include #define SP_TYPE_GRADIENT_IMAGE (sp_gradient_image_get_type ()) diff --git a/src/widgets/gradient-selector.cpp b/src/widgets/gradient-selector.cpp index e85c115a8..a5e16aed2 100644 --- a/src/widgets/gradient-selector.cpp +++ b/src/widgets/gradient-selector.cpp @@ -16,8 +16,10 @@ #ifdef HAVE_CONFIG_H # include "config.h" #endif + +#include + #include "gradient-vector.h" -#include #include "document.h" #include "document-undo.h" diff --git a/src/widgets/gradient-selector.h b/src/widgets/gradient-selector.h index 1a6468ad4..e090d7cbd 100644 --- a/src/widgets/gradient-selector.h +++ b/src/widgets/gradient-selector.h @@ -19,27 +19,23 @@ # include #endif -#if GLIBMM_DISABLE_DEPRECATED && HAVE_GLIBMM_THREADS_H -#include -#endif - -#include -#include - -#include -#include -#include #include -#include #include #include -#include "sp-gradient.h" #include "sp-gradient-spread.h" #include "sp-gradient-units.h" +class SPDocument; class SPGradient; +namespace Gtk { +class CellRendererPixbuf; +class CellRendererText; +class ScrolledWindow; +class TreeView; +} + #define SP_TYPE_GRADIENT_SELECTOR (sp_gradient_selector_get_type ()) #define SP_GRADIENT_SELECTOR(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), SP_TYPE_GRADIENT_SELECTOR, SPGradientSelector)) #define SP_GRADIENT_SELECTOR_CLASS(k) (G_TYPE_CHECK_CLASS_CAST ((k), SP_TYPE_GRADIENT_SELECTOR, SPGradientSelectorClass)) diff --git a/src/widgets/gradient-vector.h b/src/widgets/gradient-vector.h index fc85b0d9c..5ae90b28f 100644 --- a/src/widgets/gradient-vector.h +++ b/src/widgets/gradient-vector.h @@ -19,16 +19,8 @@ # include "config.h" #endif -#if GLIBMM_DISABLE_DEPRECATED && HAVE_GLIBMM_THREADS_H -#include -#endif - #include - -#include #include - -#include #include "gradient-selector.h" #define SP_TYPE_GRADIENT_VECTOR_SELECTOR (sp_gradient_vector_selector_get_type ()) diff --git a/src/widgets/paint-selector.h b/src/widgets/paint-selector.h index 1e8ad6d2e..788aa673e 100644 --- a/src/widgets/paint-selector.h +++ b/src/widgets/paint-selector.h @@ -12,7 +12,6 @@ * */ -#include #include #include "color.h" diff --git a/src/widgets/sp-color-icc-selector.h b/src/widgets/sp-color-icc-selector.h index f63ab0853..6cdaff639 100644 --- a/src/widgets/sp-color-icc-selector.h +++ b/src/widgets/sp-color-icc-selector.h @@ -2,8 +2,6 @@ #define SEEN_SP_COLOR_ICC_SELECTOR_H #include -#include - #include "sp-color-selector.h" namespace Inkscape { diff --git a/src/widgets/sp-color-notebook.h b/src/widgets/sp-color-notebook.h index 50c2bb2e7..469bb56e8 100644 --- a/src/widgets/sp-color-notebook.h +++ b/src/widgets/sp-color-notebook.h @@ -12,7 +12,6 @@ * This code is in public domain */ -#include #include "sp-color-selector.h" #include diff --git a/src/widgets/sp-color-scales.h b/src/widgets/sp-color-scales.h index de6544d11..72cbafa2f 100644 --- a/src/widgets/sp-color-scales.h +++ b/src/widgets/sp-color-scales.h @@ -2,9 +2,7 @@ #define SEEN_SP_COLOR_SCALES_H #include -#include -#include #include struct SPColorScales; diff --git a/src/widgets/sp-color-selector.h b/src/widgets/sp-color-selector.h index 9d71a4a56..30061774a 100644 --- a/src/widgets/sp-color-selector.h +++ b/src/widgets/sp-color-selector.h @@ -2,9 +2,7 @@ #define SEEN_SP_COLOR_SELECTOR_H #include -#include "../color.h" - -#include +#include "color.h" struct SPColorSelector; diff --git a/src/widgets/sp-color-slider.h b/src/widgets/sp-color-slider.h index 85db01081..b81d62e41 100644 --- a/src/widgets/sp-color-slider.h +++ b/src/widgets/sp-color-slider.h @@ -14,8 +14,6 @@ #include -#include - #define SP_TYPE_COLOR_SLIDER (sp_color_slider_get_type ()) #define SP_COLOR_SLIDER(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), SP_TYPE_COLOR_SLIDER, SPColorSlider)) #define SP_COLOR_SLIDER_CLASS(k) (G_TYPE_CHECK_CLASS_CAST ((k), SP_TYPE_COLOR_SLIDER, SPColorSliderClass)) diff --git a/src/widgets/sp-color-wheel-selector.h b/src/widgets/sp-color-wheel-selector.h index 23ac0050d..12b060dbe 100644 --- a/src/widgets/sp-color-wheel-selector.h +++ b/src/widgets/sp-color-wheel-selector.h @@ -1,7 +1,6 @@ #ifndef SEEN_SP_COLOR_WHEEL_SELECTOR_H #define SEEN_SP_COLOR_WHEEL_SELECTOR_H -#include #include #include "sp-color-selector.h" diff --git a/src/widgets/sp-widget.h b/src/widgets/sp-widget.h index b3cce32a6..6227c3a72 100644 --- a/src/widgets/sp-widget.h +++ b/src/widgets/sp-widget.h @@ -15,7 +15,6 @@ * Released under GNU GPL, read the file 'COPYING' for more information */ -#include #include #define SP_TYPE_WIDGET (sp_widget_get_type()) diff --git a/src/widgets/sp-xmlview-content.h b/src/widgets/sp-xmlview-content.h index a09d2d92d..140eacf46 100644 --- a/src/widgets/sp-xmlview-content.h +++ b/src/widgets/sp-xmlview-content.h @@ -14,8 +14,6 @@ #include #include -#include - #define SP_TYPE_XMLVIEW_CONTENT (sp_xmlview_content_get_type ()) #define SP_XMLVIEW_CONTENT(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), SP_TYPE_XMLVIEW_CONTENT, SPXMLViewContent)) diff --git a/src/widgets/spinbutton-events.h b/src/widgets/spinbutton-events.h index c1df88c8a..9bf50d87c 100644 --- a/src/widgets/spinbutton-events.h +++ b/src/widgets/spinbutton-events.h @@ -10,7 +10,9 @@ */ #include -#include /* GtkWidget */ + +typedef struct _GdkEventKey GdkEventKey; +typedef struct _GtkWidget GtkWidget; gboolean spinbutton_focus_in (GtkWidget *w, GdkEventKey *event, gpointer data); void spinbutton_undo (GtkWidget *w); diff --git a/src/widgets/toolbox.h b/src/widgets/toolbox.h index fb749bfb5..db9130034 100644 --- a/src/widgets/toolbox.h +++ b/src/widgets/toolbox.h @@ -13,15 +13,15 @@ * Released under GNU GPL, read the file 'COPYING' for more information */ -#include #include #include "icon-size.h" -#include "../ege-adjustment-action.h" -#include "../preferences.h" +#include "preferences.h" #define TOOLBAR_SLIDER_HINT "full" +typedef struct _EgeAdjustmentAction EgeAdjustmentAction; + class SPDesktop; namespace Inkscape { -- cgit v1.2.3 From bb1fa6bf07ac6a00eaced3f60400a86cbcb6be0d Mon Sep 17 00:00:00 2001 From: "Liam P. White" Date: Sat, 30 Aug 2014 11:31:41 -0400 Subject: Fix SP_ACTIVE_DOCUMENT usage (document can be determined from context) (bzr r13341.1.185) --- src/live_effects/lpe-perspective_path.cpp | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/live_effects/lpe-perspective_path.cpp b/src/live_effects/lpe-perspective_path.cpp index a2372131c..9e21f5d25 100644 --- a/src/live_effects/lpe-perspective_path.cpp +++ b/src/live_effects/lpe-perspective_path.cpp @@ -18,6 +18,7 @@ #include "document.h" #include "document-private.h" #include "live_effects/lpe-perspective_path.h" +#include "live_effects/lpeobject.h" #include "sp-item-group.h" #include "knot-holder-entity.h" #include "knotholder.h" @@ -62,7 +63,7 @@ LPEPerspectivePath::LPEPerspectivePath(LivePathEffectObject *lpeobject) : concatenate_before_pwd2 = true; // don't split the path into its subpaths _provides_knotholder_entities = true; unapply = false; - Persp3D *persp = persp3d_document_first_persp(inkscape_active_document()); + Persp3D *persp = persp3d_document_first_persp(lpeobject->document); if(persp == 0 ){ char *msg = _("You need a BOX 3D object"); Gtk::MessageDialog dialog(msg, false, Gtk::MESSAGE_INFO, @@ -72,7 +73,7 @@ LPEPerspectivePath::LPEPerspectivePath(LivePathEffectObject *lpeobject) : return; } Proj::TransfMat3x4 pmat = persp->perspective_impl->tmat; - pmat = pmat * inkscape_active_desktop()->doc2dt(); + pmat = pmat * SP_ACTIVE_DESKTOP->doc2dt(); pmat.copy_tmat(tmat); } @@ -95,7 +96,7 @@ void LPEPerspectivePath::refresh(Gtk::Entry* perspective) { perspectiveID = perspective->get_text(); Persp3D *first = 0; Persp3D *persp = 0; - for ( SPObject *child = inkscape_active_document()->getDefs()->firstChild(); child && !persp; child = child->getNext() ) { + for ( SPObject *child = this->lpeobj->document->getDefs()->firstChild(); child && !persp; child = child->getNext() ) { if (SP_IS_PERSP3D(child) && first == 0) { first = SP_PERSP3D(child); } @@ -125,7 +126,7 @@ void LPEPerspectivePath::refresh(Gtk::Entry* perspective) { dialog.run(); } Proj::TransfMat3x4 pmat = persp->perspective_impl->tmat; - pmat = pmat * inkscape_active_desktop()->doc2dt(); + pmat = pmat * SP_ACTIVE_DESKTOP->doc2dt(); pmat.copy_tmat(tmat); }; @@ -144,7 +145,7 @@ LPEPerspectivePath::doEffect_pwd2 (Geom::Piecewise > cons Piecewise preimage[4]; //Geom::Point orig = Geom::Point(bounds_X.min(), bounds_Y.middle()); - //orig = Geom::Point(orig[X], sp_document_height(inkscape_active_document()) - orig[Y]); + //orig = Geom::Point(orig[X], sp_document_height(this->lpeobj->document) - orig[Y]); //double offset = uses_plane_xy ? boundingbox_X.extent() : 0.0; -- cgit v1.2.3 From 60c9a93dd37ecc1a4875dde3f827e9f6c3e0c642 Mon Sep 17 00:00:00 2001 From: "Liam P. White" Date: Sat, 30 Aug 2014 11:42:57 -0400 Subject: Fix gtk3 build (bzr r13341.1.186) --- src/widgets/gradient-vector.cpp | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) (limited to 'src') diff --git a/src/widgets/gradient-vector.cpp b/src/widgets/gradient-vector.cpp index 68f40f80c..53ce8ceac 100644 --- a/src/widgets/gradient-vector.cpp +++ b/src/widgets/gradient-vector.cpp @@ -23,6 +23,7 @@ # include "config.h" #endif +#include #include "gradient-vector.h" #include "ui/widget/color-preview.h" #include "verbs.h" @@ -30,17 +31,17 @@ #include "macros.h" #include #include -#include "../widgets/gradient-image.h" -#include "../inkscape.h" -#include "../document-private.h" -#include "../gradient-chemistry.h" -#include "../helper/window.h" +#include "widgets/gradient-image.h" +#include "inkscape.h" +#include "document-private.h" +#include "gradient-chemistry.h" +#include "helper/window.h" #include "io/resource.h" #include "xml/repr.h" -#include "../dialogs/dialog-events.h" -#include "../preferences.h" +#include "dialogs/dialog-events.h" +#include "preferences.h" #include "svg/css-ostringstream.h" #include "sp-stop.h" #include "selection-chemistry.h" @@ -50,8 +51,7 @@ #include "desktop.h" #include "layer-manager.h" -#include -#include +#include #include "document-undo.h" using Inkscape::DocumentUndo; @@ -468,10 +468,10 @@ void SPGradientVectorSelector::setSwatched() ### Vector Editing Widget ##################################################################*/ -#include "../widgets/sp-color-notebook.h" -#include "../widgets/widget-sizes.h" -#include "../xml/node-event-vector.h" -#include "../svg/svg-color.h" +#include "widgets/sp-color-notebook.h" +#include "widgets/widget-sizes.h" +#include "xml/node-event-vector.h" +#include "svg/svg-color.h" #define PAD 4 -- cgit v1.2.3 From 7290c6aa6cbaf9bbf8418eb463a0f7570f645e9a Mon Sep 17 00:00:00 2001 From: "Liam P. White" Date: Sat, 30 Aug 2014 11:44:33 -0400 Subject: Remove old stub from inkview (bzr r13341.1.187) --- src/inkview.cpp | 10 ---------- 1 file changed, 10 deletions(-) (limited to 'src') diff --git a/src/inkview.cpp b/src/inkview.cpp index 4188c832f..2969bb140 100644 --- a/src/inkview.cpp +++ b/src/inkview.cpp @@ -570,16 +570,6 @@ static void usage() exit(1); } -#ifdef XXX -/* TODO !!! make this temporary stub unnecessary */ -InkscapeApplication *inkscape_get_instance() { return NULL; } -void inkscape_ref (void) {} -void inkscape_unref (void) {} -void inkscape_add_document (SPDocument *document) {} -void inkscape_remove_document (SPDocument *document) {} -#endif - - /* Local Variables: mode:c++ -- cgit v1.2.3 From 77edfe45996574c82f66c2156ce6e8037520c8ff Mon Sep 17 00:00:00 2001 From: "Liam P. White" Date: Sat, 30 Aug 2014 13:23:17 -0400 Subject: Minor pass of header cleanup (bzr r13341.1.189) --- src/attribute-rel-util.h | 2 +- src/axis-manip.cpp | 9 ++++ src/axis-manip.h | 30 +++++------ src/cms-color-types.h | 5 +- src/cms-system.h | 8 ++- src/color-profile.h | 21 ++++---- src/color-rgba.h | 5 +- src/color.cpp | 8 +-- src/color.h | 6 +-- src/conn-avoid-ref.h | 2 +- src/display/cairo-utils.h | 6 +-- src/display/canvas-bpath.cpp | 3 -- src/display/canvas-text.cpp | 4 -- src/display/drawing.h | 7 ++- src/extension/internal/cairo-render-context.h | 3 ++ src/satisfied-guide-cns.h | 2 +- src/sp-gradient.cpp | 21 ++++---- src/sp-gradient.h | 27 +++++----- src/sp-guide.cpp | 2 +- src/sp-guide.h | 7 ++- src/sp-mesh-array.cpp | 2 + src/sp-mesh-gradient.cpp | 2 + src/sp-object.h | 73 ++++++++++++++------------- 23 files changed, 126 insertions(+), 129 deletions(-) (limited to 'src') diff --git a/src/attribute-rel-util.h b/src/attribute-rel-util.h index 3a6661965..604987779 100644 --- a/src/attribute-rel-util.h +++ b/src/attribute-rel-util.h @@ -8,7 +8,7 @@ * Author: tavmjong */ -#include "glibmm/ustring.h" +#include #include "xml/sp-css-attr.h" using Inkscape::XML::Node; diff --git a/src/axis-manip.cpp b/src/axis-manip.cpp index 1240d99e6..8955202c8 100644 --- a/src/axis-manip.cpp +++ b/src/axis-manip.cpp @@ -9,6 +9,7 @@ * Released under GNU GPL, read the file 'COPYING' for more information */ +#include #include "axis-manip.h" namespace Proj { @@ -31,6 +32,14 @@ get_remaining_axes (Axis axis) { return std::make_pair (extract_first_axis_direction (plane), extract_second_axis_direction (plane)); } +char * string_from_axes (Box3D::Axis axis) { + GString *pstring = g_string_new(""); + if (axis & Box3D::X) g_string_append_printf (pstring, "X"); + if (axis & Box3D::Y) g_string_append_printf (pstring, "Y"); + if (axis & Box3D::Z) g_string_append_printf (pstring, "Z"); + return pstring->str; +} + } // namespace Box3D /* diff --git a/src/axis-manip.h b/src/axis-manip.h index 7842b4135..619b9089c 100644 --- a/src/axis-manip.h +++ b/src/axis-manip.h @@ -12,8 +12,9 @@ #ifndef SEEN_AXIS_MANIP_H #define SEEN_AXIS_MANIP_H +#include +#include #include -#include namespace Proj { @@ -34,7 +35,7 @@ enum Axis { extern Axis axes[4]; -inline gchar const * +inline char const* string_from_axis(Proj::Axis axis) { switch (axis) { case X: return "X"; break; @@ -88,7 +89,7 @@ inline int axis_to_int(Box3D::Axis axis) { return -1; break; default: - g_assert_not_reached(); + assert(false); } } @@ -103,7 +104,7 @@ inline Proj::Axis toProj(Box3D::Axis axis) { case Box3D::NONE: return Proj::NONE; default: - g_assert_not_reached(); + assert(false); } } @@ -126,7 +127,7 @@ inline Box3D::Axis toAffine(Proj::Axis axis) { case Proj::NONE: return Box3D::NONE; default: - g_assert_not_reached(); + assert(false); } } @@ -144,7 +145,7 @@ namespace Box3D { // (which is normally used to index an array). Return -1 if the bit sequence // does not specify a face. A face can either be given by its plane (e.g, XY) // or by the axis that is orthogonal to it (e.g., Z). -inline gint face_to_int (guint face_id) { +inline int face_to_int (unsigned int face_id) { switch (face_id) { case 1: return 0; case 2: return 1; @@ -164,7 +165,7 @@ inline gint face_to_int (guint face_id) { } } -inline gint int_to_face (guint id) { +inline int int_to_face (unsigned id) { switch (id) { case 0: return Box3D::YZ ^ Box3D::FRONT; case 1: return Box3D::XZ ^ Box3D::FRONT; @@ -176,7 +177,7 @@ inline gint int_to_face (guint id) { return Box3D::NONE; // should not be reached } -inline bool is_face_id (guint face_id) { +inline bool is_face_id (unsigned int face_id) { return !((face_id & 0x7) == 0x7); } @@ -186,8 +187,8 @@ inline gint opposite_face (guint face_id) { } **/ -inline guint number_of_axis_directions (Box3D::Axis axis) { - guint num = 0; +inline unsigned int number_of_axis_directions (Box3D::Axis axis) { + unsigned int num = 0; if (axis & Box3D::X) num++; if (axis & Box3D::Y) num++; if (axis & Box3D::Z) num++; @@ -238,14 +239,7 @@ inline Box3D::Axis get_perpendicular_axis_direction (Box3D::Axis dirs) { return Box3D::NONE; } -inline gchar * string_from_axes (Box3D::Axis axis) { - GString *pstring = g_string_new(""); - if (axis & Box3D::X) g_string_append_printf (pstring, "X"); - if (axis & Box3D::Y) g_string_append_printf (pstring, "Y"); - if (axis & Box3D::Z) g_string_append_printf (pstring, "Z"); - return pstring->str; -} - +char * string_from_axes (Box3D::Axis axis); std::pair get_remaining_axes (Axis axis); } // namespace Box3D diff --git a/src/cms-color-types.h b/src/cms-color-types.h index 47157c243..b94c96029 100644 --- a/src/cms-color-types.h +++ b/src/cms-color-types.h @@ -10,15 +10,14 @@ # include "config.h" #endif // HAVE_CONFIG_H -#include - #if HAVE_LIBLCMS1 # include #endif #if HAVE_STDINT_H -# include +# include // uint8_t, etc #endif +typedef unsigned int guint32; typedef void * cmsHPROFILE; typedef void * cmsHTRANSFORM; diff --git a/src/cms-system.h b/src/cms-system.h index c528deb94..73d1a89c4 100644 --- a/src/cms-system.h +++ b/src/cms-system.h @@ -5,8 +5,6 @@ * Macros and fn declarations related to linear gradients. */ -#include -#include #include #include #include "cms-color-types.h" @@ -19,13 +17,13 @@ class ColorProfile; class CMSSystem { public: - static cmsHPROFILE getHandle( SPDocument* document, guint* intent, gchar const* name ); + static cmsHPROFILE getHandle( SPDocument* document, unsigned int* intent, char const* name ); static cmsHTRANSFORM getDisplayTransform(); static Glib::ustring getDisplayId( int screen, int monitor ); - static Glib::ustring setDisplayPer( gpointer buf, guint bufLen, int screen, int monitor ); + static Glib::ustring setDisplayPer( void* buf, unsigned int bufLen, int screen, int monitor ); static cmsHTRANSFORM getDisplayPer( Glib::ustring const& id ); @@ -39,7 +37,7 @@ public: static bool isPrintColorSpace(ColorProfile const *profile); - static gint getChannelCount(ColorProfile const *profile); + static int getChannelCount(ColorProfile const *profile); }; diff --git a/src/color-profile.h b/src/color-profile.h index 2da757b91..cb6b25945 100644 --- a/src/color-profile.h +++ b/src/color-profile.h @@ -2,7 +2,6 @@ #define SEEN_COLOR_PROFILE_H #include -#include #include #include #include "cms-color-types.h" @@ -31,7 +30,7 @@ public: ColorProfile(); virtual ~ColorProfile(); - friend cmsHPROFILE colorprofile_get_handle( SPDocument*, guint*, gchar const* ); + friend cmsHPROFILE colorprofile_get_handle( SPDocument*, unsigned int*, char const* ); friend class CMSSystem; static std::vector getBaseProfileDirs(); @@ -49,21 +48,21 @@ public: #endif // defined(HAVE_LIBLCMS1) || defined(HAVE_LIBLCMS2) - gchar* href; - gchar* local; - gchar* name; - gchar* intentStr; - guint rendering_intent; + char* href; + char* local; + char* name; + char* intentStr; + unsigned int rendering_intent; // FIXME: type the enum and hold that instead protected: ColorProfileImpl *impl; - virtual void build(SPDocument* doc, Inkscape::XML::Node* repr); - virtual void release(); + virtual void build(SPDocument* doc, Inkscape::XML::Node* repr); + virtual void release(); - virtual void set(unsigned int key, const gchar* value); + virtual void set(unsigned int key, char const* value); - virtual Inkscape::XML::Node* write(Inkscape::XML::Document* doc, Inkscape::XML::Node* repr, guint flags); + virtual Inkscape::XML::Node* write(Inkscape::XML::Document* doc, Inkscape::XML::Node* repr, unsigned int flags); }; } // namespace Inkscape diff --git a/src/color-rgba.h b/src/color-rgba.h index ef7d9aee1..55cf68877 100644 --- a/src/color-rgba.h +++ b/src/color-rgba.h @@ -9,8 +9,9 @@ #ifndef SEEN_COLOR_RGBA_H #define SEEN_COLOR_RGBA_H -#include // g_assert() +#include #include "decimal-round.h" +typedef unsigned int guint32; /** * A class to contain a floating point RGBA color as one unit. @@ -96,7 +97,7 @@ public: * @return The requested value. */ float operator[](unsigned int const i) const { - g_assert( unsigned(i) < 4 ); + assert( unsigned(i) < 4 ); return _c[i]; } diff --git a/src/color.cpp b/src/color.cpp index dccd603b0..da4406748 100644 --- a/src/color.cpp +++ b/src/color.cpp @@ -160,7 +160,7 @@ void SPColor::set( guint32 value ) * Convert SPColor with integer alpha value to 32bit RGBA value. * \pre alpha < 256 */ -guint32 SPColor::toRGBA32( gint alpha ) const +guint32 SPColor::toRGBA32( int alpha ) const { g_return_val_if_fail (alpha <= 0xff, 0x0); @@ -175,12 +175,12 @@ guint32 SPColor::toRGBA32( gint alpha ) const * Convert SPColor with float alpha value to 32bit RGBA value. * \pre color != NULL && 0 <= alpha <= 1 */ -guint32 SPColor::toRGBA32( gdouble alpha ) const +guint32 SPColor::toRGBA32( double alpha ) const { g_return_val_if_fail(alpha >= 0.0, 0x0); g_return_val_if_fail(alpha <= 1.0, 0x0); - return toRGBA32( static_cast(SP_COLOR_F_TO_U(alpha)) ); + return toRGBA32( static_cast(SP_COLOR_F_TO_U(alpha)) ); } std::string SPColor::toString() const @@ -284,7 +284,7 @@ sp_color_rgb_to_hsv_floatv (float *hsv, float r, float g, float b) void sp_color_hsv_to_rgb_floatv (float *rgb, float h, float s, float v) { - gdouble f, w, q, t, d; + double f, w, q, t, d; d = h * 5.99999999; f = d - floor (d); diff --git a/src/color.h b/src/color.h index 604dff0e3..887daf66b 100644 --- a/src/color.h +++ b/src/color.h @@ -13,8 +13,8 @@ * Released under GNU GPL, read the file 'COPYING' for more information */ -#include #include +typedef unsigned int guint32; // uint is guaranteed to hold up to 2^32 − 1 /* Useful composition macros */ @@ -52,8 +52,8 @@ struct SPColor { void set( float r, float g, float b ); void set( guint32 value ); - guint32 toRGBA32( gint alpha ) const; - guint32 toRGBA32( gdouble alpha ) const; + guint32 toRGBA32( int alpha ) const; + guint32 toRGBA32( double alpha ) const; std::string toString() const; diff --git a/src/conn-avoid-ref.h b/src/conn-avoid-ref.h index ce364abf1..e9e12118f 100644 --- a/src/conn-avoid-ref.h +++ b/src/conn-avoid-ref.h @@ -14,13 +14,13 @@ */ #include <2geom/point.h> -#include #include #include class SPDesktop; class SPObject; class SPItem; +typedef struct _GSList GSList; namespace Avoid { class ShapeRef; } class SPAvoidRef { diff --git a/src/display/cairo-utils.h b/src/display/cairo-utils.h index f252c4a44..9c46ef359 100644 --- a/src/display/cairo-utils.h +++ b/src/display/cairo-utils.h @@ -12,15 +12,13 @@ #ifndef SEEN_INKSCAPE_DISPLAY_CAIRO_UTILS_H #define SEEN_INKSCAPE_DISPLAY_CAIRO_UTILS_H +#include <2geom/forward.h> #include -//#include // workaround -//#include #include -//#include -#include <2geom/forward.h> #include "style.h" struct SPColor; +typedef struct _GdkPixbuf GdkPixbuf; namespace Inkscape { diff --git a/src/display/canvas-bpath.cpp b/src/display/canvas-bpath.cpp index 328409e12..46b59d25a 100644 --- a/src/display/canvas-bpath.cpp +++ b/src/display/canvas-bpath.cpp @@ -11,9 +11,6 @@ * */ -#ifdef HAVE_CONFIG_H -# include "config.h" -#endif #include #include #include "desktop.h" diff --git a/src/display/canvas-text.cpp b/src/display/canvas-text.cpp index 88812af0a..5ad87b4ef 100644 --- a/src/display/canvas-text.cpp +++ b/src/display/canvas-text.cpp @@ -12,10 +12,6 @@ * Released under GNU GPL, read the file 'COPYING' for more information */ -#ifdef HAVE_CONFIG_H -# include "config.h" -#endif - #include #include diff --git a/src/display/drawing.h b/src/display/drawing.h index cc74833ba..88e35b03b 100644 --- a/src/display/drawing.h +++ b/src/display/drawing.h @@ -13,7 +13,6 @@ #define SEEN_INKSCAPE_DISPLAY_DRAWING_H #include -#include #include #include #include @@ -23,7 +22,7 @@ #include "nr-filter-colormatrix.h" typedef struct _SPCanvasArena SPCanvasArena; - +typedef unsigned int guint32; namespace Inkscape { @@ -65,7 +64,7 @@ public: OutlineColors const &colors() const { return _colors; } - void setGrayscaleMatrix(gdouble value_matrix[20]); + void setGrayscaleMatrix(double value_matrix[20]); void update(Geom::IntRect const &area = Geom::IntRect::infinite(), UpdateContext const &ctx = UpdateContext(), unsigned flags = DrawingItem::STATE_ALL, unsigned reset = 0); void render(DrawingContext &dc, Geom::IntRect const &area, unsigned flags = 0); @@ -100,7 +99,7 @@ private: OutlineColors _colors; Filters::FilterColorMatrix::ColorMatrixMatrix _grayscale_colormatrix; - SPCanvasArena *_canvasarena; // may be NULL is this arena is not the screen + SPCanvasArena *_canvasarena; // may be NULL if this arena is not the screen // but used for export etc. friend class DrawingItem; diff --git a/src/extension/internal/cairo-render-context.h b/src/extension/internal/cairo-render-context.h index 8d3e63775..8071cae36 100644 --- a/src/extension/internal/cairo-render-context.h +++ b/src/extension/internal/cairo-render-context.h @@ -31,6 +31,9 @@ class SPClipPath; class SPMask; +typedef struct _PangoFont PangoFont; +typedef struct _PangoLayout PangoLayout; + namespace Inkscape { class Pixbuf; diff --git a/src/satisfied-guide-cns.h b/src/satisfied-guide-cns.h index 73e1e7e7f..25e5919d0 100644 --- a/src/satisfied-guide-cns.h +++ b/src/satisfied-guide-cns.h @@ -3,7 +3,7 @@ #include <2geom/forward.h> #include -#include +#include "sp-item.h" class SPDesktop; class SPGuideConstraint; diff --git a/src/sp-gradient.cpp b/src/sp-gradient.cpp index 70c54451a..b3e885560 100644 --- a/src/sp-gradient.cpp +++ b/src/sp-gradient.cpp @@ -54,9 +54,6 @@ #include "style.h" #include "display/grayscale.h" -#define SP_MACROS_SILENT -#include "macros.h" - /// Has to be power of 2 Seems to be unused. //#define NCOLORS NR_GRADIENT_VECTOR_LENGTH @@ -107,11 +104,11 @@ void SPGradient::setSwatch( bool swatch ) * Equivalent meaning they have the same stop count, same stop colors and same stop opacity * @param that - A gradient to compare this to */ -gboolean SPGradient::isEquivalent(SPGradient *that) +bool SPGradient::isEquivalent(SPGradient *that) { //TODO Make this work for mesh gradients - bool status = FALSE; + bool status = false; while(1){ // not really a loop, used to avoid deep nesting or multiple exit points from function if (this->getStopCount() != that->getStopCount()) { break; } @@ -132,11 +129,11 @@ gboolean SPGradient::isEquivalent(SPGradient *that) SPStop *as = this->getVector()->getFirstStop(); SPStop *bs = that->getVector()->getFirstStop(); - bool effective = TRUE; + bool effective = true; while (effective && (as && bs)) { if (!as->getEffectiveColor().isClose(bs->getEffectiveColor(), 0.001) || as->offset != bs->offset) { - effective = FALSE; + effective = false; break; } else { @@ -144,9 +141,9 @@ gboolean SPGradient::isEquivalent(SPGradient *that) bs = bs->getNextStop(); } } - if(!effective)break; + if (!effective) break; - status = TRUE; + status = true; break; } return status; @@ -157,9 +154,9 @@ gboolean SPGradient::isEquivalent(SPGradient *that) * Aligned means that they have exactly the same coordinates and transform. * @param that - A gradient to compare this to */ -gboolean SPGradient::isAligned(SPGradient *that) +bool SPGradient::isAligned(SPGradient *that) { - bool status = FALSE; + bool status = false; /* Some gradients have coordinates/other values specified, some don't. yes/yes check the coordinates/other values @@ -223,7 +220,7 @@ gboolean SPGradient::isAligned(SPGradient *that) } else { break; } - status = TRUE; + status = true; break; } return status; diff --git a/src/sp-gradient.h b/src/sp-gradient.h index 1dfff22ee..a14dcc09e 100644 --- a/src/sp-gradient.h +++ b/src/sp-gradient.h @@ -15,7 +15,6 @@ */ #include -#include #include #include <2geom/affine.h> #include "sp-paint-server.h" @@ -109,30 +108,30 @@ public: private: /** gradientUnits attribute */ SPGradientUnits units; - guint units_set : 1; + unsigned int units_set : 1; public: /** gradientTransform attribute */ Geom::Affine gradientTransform; - guint gradientTransform_set : 1; + unsigned int gradientTransform_set : 1; private: /** spreadMethod attribute */ SPGradientSpread spread; - guint spread_set : 1; + unsigned int spread_set : 1; /** Gradient stops */ - guint has_stops : 1; + unsigned int has_stops : 1; /** Gradient patches */ - guint has_patches : 1; + unsigned int has_patches : 1; public: /** Reference (href) */ SPGradientReference *ref; /** State in Inkscape gradient system */ - guint state; + unsigned int state; /** Linear and Radial Gradients */ @@ -146,8 +145,8 @@ public: SPStop* getFirstStop(); int getStopCount() const; - gboolean isEquivalent(SPGradient *b); - gboolean isAligned(SPGradient *b); + bool isEquivalent(SPGradient *b); + bool isAligned(SPGradient *b); /** Mesh Gradients **************/ @@ -175,7 +174,7 @@ public: */ SPGradient *getVector(bool force_private = false); - static GType getType(); + //static GType getType(); /** Forces vector to be built, if not present (i.e. changed) */ void ensureVector(); @@ -196,7 +195,7 @@ public: void setSwatch(bool swatch = true); - static void gradientRefModified(SPObject *href, guint flags, SPGradient *gradient); + static void gradientRefModified(SPObject *href, unsigned int flags, SPGradient *gradient); static void gradientRefChanged(SPObject *old_ref, SPObject *ref, SPGradient *gr); private: @@ -208,13 +207,13 @@ private: protected: virtual void build(SPDocument *document, Inkscape::XML::Node *repr); virtual void release(); - virtual void modified(guint flags); - virtual Inkscape::XML::Node* write(Inkscape::XML::Document *xml_doc, Inkscape::XML::Node *repr, guint flags); + virtual void modified(unsigned int flags); + virtual Inkscape::XML::Node* write(Inkscape::XML::Document *xml_doc, Inkscape::XML::Node *repr, unsigned int flags); virtual void child_added(Inkscape::XML::Node *child, Inkscape::XML::Node *ref); virtual void remove_child(Inkscape::XML::Node *child); - virtual void set(unsigned key, gchar const *value); + virtual void set(unsigned key, char const *value); }; void diff --git a/src/sp-guide.cpp b/src/sp-guide.cpp index 60f15a79d..0e83c2acf 100644 --- a/src/sp-guide.cpp +++ b/src/sp-guide.cpp @@ -341,7 +341,7 @@ void SPGuide::hideSPGuide(SPCanvas *canvas) g_assert_not_reached(); } -void SPGuide::sensitize(SPCanvas *canvas, gboolean sensitive) +void SPGuide::sensitize(SPCanvas *canvas, bool sensitive) { g_assert(canvas != NULL); g_assert(SP_IS_CANVAS(canvas)); diff --git a/src/sp-guide.h b/src/sp-guide.h index fa4f0033b..9f5d7ba03 100644 --- a/src/sp-guide.h +++ b/src/sp-guide.h @@ -19,6 +19,9 @@ #include "sp-object.h" #include "sp-guide-attachment.h" +typedef unsigned int guint32; +typedef void (*GCallback) (void); + struct SPCanvas; struct SPCanvasGroup; class SPDesktop; @@ -52,14 +55,14 @@ public: static SPGuide *createSPGuide(SPDocument *doc, Geom::Point const &pt1, Geom::Point const &pt2); void showSPGuide(SPCanvasGroup *group, GCallback handler); void hideSPGuide(SPCanvas *canvas); - void sensitize(SPCanvas *canvas, gboolean sensitive); + void sensitize(SPCanvas *canvas, bool sensitive); Geom::Point getPositionFrom(Geom::Point const &pt) const; double getDistanceFrom(Geom::Point const &pt) const; protected: virtual void build(SPDocument* doc, Inkscape::XML::Node* repr); virtual void release(); - virtual void set(unsigned int key, const gchar* value); + virtual void set(unsigned int key, const char* value); }; void sp_guide_pt_pairs_to_guides(SPDocument *doc, std::list > &pts); diff --git a/src/sp-mesh-array.cpp b/src/sp-mesh-array.cpp index 300f2ad19..8bfe23656 100644 --- a/src/sp-mesh-array.cpp +++ b/src/sp-mesh-array.cpp @@ -37,6 +37,8 @@ * Released under GNU GPL, read the file 'COPYING' for more information */ +#include + // For color picking #include "display/drawing.h" #include "display/drawing-context.h" diff --git a/src/sp-mesh-gradient.cpp b/src/sp-mesh-gradient.cpp index 1b04a6f8e..bf28164a9 100644 --- a/src/sp-mesh-gradient.cpp +++ b/src/sp-mesh-gradient.cpp @@ -1,3 +1,5 @@ +#include + #include "attributes.h" #include "display/cairo-utils.h" #include "xml/repr.h" diff --git a/src/sp-object.h b/src/sp-object.h index e58f161d6..21926ad90 100644 --- a/src/sp-object.h +++ b/src/sp-object.h @@ -46,7 +46,7 @@ class SPObject; #define SP_OBJECT_WRITE_EXT (1 << 1) #define SP_OBJECT_WRITE_ALL (1 << 2) -#include +#include #include #include #include @@ -57,6 +57,7 @@ class SPObject; class SPCSSAttr; class SPStyle; +typedef struct _GSList GSList; namespace Inkscape { namespace XML { @@ -109,8 +110,8 @@ class SPDocument; class SPIXmlSpace { public: SPIXmlSpace(): set(0), value(SP_XML_SPACE_DEFAULT) {}; - guint set : 1; - guint value : 1; + unsigned int set : 1; + unsigned int value : 1; }; /* @@ -183,7 +184,7 @@ SPObject *sp_object_hunref(SPObject *object, gpointer owner); * provides document level functionality such as the undo stack, * dictionary and so on. Source: doc/architecture.txt */ -class SPObject { // : public GObject { +class SPObject { public: enum CollectionPolicy { COLLECT_WITH_PARENT, @@ -209,7 +210,7 @@ private: SPObject(const SPObject&); SPObject& operator=(const SPObject&); - gchar *id; /* Our very own unique id */ + char *id; /* Our very own unique id */ Inkscape::XML::Node *repr; /* Our xml representation */ public: int refCount; @@ -217,7 +218,7 @@ public: /** * Returns the objects current ID string. */ - gchar const* getId() const; + char const* getId() const; /** * Returns the XML representation of tree @@ -281,7 +282,7 @@ public: typedef Inkscape::Util::ForwardPointerIterator ConstSiblingIterator; bool isSiblingOf(SPObject const *object) const { - g_return_val_if_fail(object != NULL, false); + if (object == NULL) return false; return this->parent && this->parent == object->parent; } @@ -332,26 +333,26 @@ public: * Gets the author-visible label property for the object or a default if * no label is defined. */ - gchar const *label() const; + char const *label() const; /** * Returns a default label property for this object. */ - gchar const *defaultLabel() const; + char const *defaultLabel() const; /** * Sets the author-visible label for this object. * * @param label the new label. */ - void setLabel(gchar const *label); + void setLabel(char const *label); /** * Returns the title of this object, or NULL if there is none. * The caller must free the returned string using g_free() - see comment * for getTitleOrDesc() below. */ - gchar *title() const; + char *title() const; /** * Sets the title of this object. @@ -359,14 +360,14 @@ public: * (if any) should be deleted. * The second argument is optional - @see setTitleOrDesc() below for details. */ - bool setTitle(gchar const *title, bool verbatim = false); + bool setTitle(char const *title, bool verbatim = false); /** * Returns the description of this object, or NULL if there is none. * The caller must free the returned string using g_free() - see comment * for getTitleOrDesc() below. */ - gchar *desc() const; + char *desc() const; /** * Sets the description of this object. @@ -374,7 +375,7 @@ public: * description (if any) should be deleted. * The second argument is optional - @see setTitleOrDesc() below for details. */ - bool setDesc(gchar const *desc, bool verbatim=false); + bool setDesc(char const *desc, bool verbatim=false); /** * Set the policy under which this object will be orphan-collected. @@ -501,9 +502,9 @@ public: * Indicates that another object supercedes this one. */ void setSuccessor(SPObject *successor) { - g_assert(successor != NULL); - g_assert(_successor == NULL); - g_assert(successor->_successor == NULL); + assert(successor != NULL); + assert(_successor == NULL); + assert(successor->_successor == NULL); sp_object_ref(successor, NULL); _successor = successor; } @@ -655,8 +656,8 @@ public: sigc::signal _modified_signal; SPObject *_successor; CollectionPolicy _collection_policy; - gchar *_label; - mutable gchar *_default_label; + char *_label; + mutable char *_default_label; // WARNING: // Methods below should not be used outside of the SP tree, @@ -690,7 +691,7 @@ public: unsigned getPosition(); - gchar const * getAttribute(gchar const *name,SPException *ex=NULL) const; + char const * getAttribute(char const *name,SPException *ex=NULL) const; void appendChild(Inkscape::XML::Node *child); @@ -699,18 +700,18 @@ public: /** * Call virtual set() function of object. */ - void setKeyValue(unsigned int key, gchar const *value); + void setKeyValue(unsigned int key, char const *value); - void setAttribute(gchar const *key, gchar const *value, SPException *ex=NULL); + void setAttribute(char const *key, char const *value, SPException *ex=NULL); /** * Read value of key attribute from XML node into object. */ - void readAttr(gchar const *key); + void readAttr(char const *key); - gchar const *getTagName(SPException *ex) const; + char const *getTagName(SPException *ex) const; - void removeAttribute(gchar const *key, SPException *ex=NULL); + void removeAttribute(char const *key, SPException *ex=NULL); /** * Returns an object style property. @@ -740,13 +741,13 @@ public: * element instead), we should probably make the caller * responsible for ascending the repr tree as necessary. */ - gchar const *getStyleProperty(gchar const *key, gchar const *def) const; + char const *getStyleProperty(char const *key, char const *def) const; - void setCSS(SPCSSAttr *css, gchar const *attr); + void setCSS(SPCSSAttr *css, char const *attr); - void changeCSS(SPCSSAttr *css, gchar const *attr); + void changeCSS(SPCSSAttr *css, char const *attr); - bool storeAsDouble( gchar const *key, double *val ) const; + bool storeAsDouble( char const *key, double *val ) const; private: // Private member functions used in the definitions of setTitle(), @@ -769,7 +770,7 @@ private: * The return value is true if a change was made to the title/description, * and usually false otherwise. */ - bool setTitleOrDesc(gchar const *value, gchar const *svg_tagname, bool verbatim); + bool setTitleOrDesc(char const *value, char const *svg_tagname, bool verbatim); /** * Returns the title or description of this object, or NULL if there is none. @@ -781,13 +782,13 @@ private: * Consequently, the return value is a newly allocated string (or NULL), and * must be freed (using g_free()) by the caller. */ - gchar * getTitleOrDesc(gchar const *svg_tagname) const; + char * getTitleOrDesc(char const *svg_tagname) const; /** * Find the first child of this object with a given tag name, * and return it. Returns NULL if there is no matching child. */ - SPObject * findFirstChild(gchar const *tagname) const; + SPObject * findFirstChild(char const *tagname) const; /** * Return the full textual content of an element (typically all the @@ -802,12 +803,12 @@ public: /** * Callback for attr_changed node event. */ - static void repr_attr_changed(Inkscape::XML::Node *repr, gchar const *key, gchar const *oldval, gchar const *newval, bool is_interactive, gpointer data); + static void repr_attr_changed(Inkscape::XML::Node *repr, char const *key, char const *oldval, char const *newval, bool is_interactive, gpointer data); /** * Callback for content_changed node event. */ - static void repr_content_changed(Inkscape::XML::Node *repr, gchar const *oldcontent, gchar const *newcontent, gpointer data); + static void repr_content_changed(Inkscape::XML::Node *repr, char const *oldcontent, char const *newcontent, gpointer data); /** * Callback for child_added node event. @@ -838,12 +839,12 @@ protected: virtual void order_changed(Inkscape::XML::Node* child, Inkscape::XML::Node* old_repr, Inkscape::XML::Node* new_repr); - virtual void set(unsigned int key, const gchar* value); + virtual void set(unsigned int key, const char* value); virtual void update(SPCtx* ctx, unsigned int flags); virtual void modified(unsigned int flags); - virtual Inkscape::XML::Node* write(Inkscape::XML::Document* doc, Inkscape::XML::Node* repr, guint flags); + virtual Inkscape::XML::Node* write(Inkscape::XML::Document* doc, Inkscape::XML::Node* repr, unsigned int flags); public: virtual void read_content(); -- cgit v1.2.3 From 1f2d8bc4ce99e970cead4ca96c1859c383a9c043 Mon Sep 17 00:00:00 2001 From: "Liam P. White" Date: Sun, 31 Aug 2014 14:17:26 -0400 Subject: Header cleanup: stop using Glib types where they aren't truly needed. Eases GThread deprecation errors. (bzr r13341.1.190) --- src/CMakeLists.txt | 1 - src/Makefile_insert | 1 - src/box3d-side.h | 8 +- src/box3d.h | 20 ++--- src/context-fns.cpp | 13 ++- src/context-fns.h | 15 ++-- src/desktop-style.h | 3 +- src/dir-util.h | 5 +- src/document-private.h | 1 + src/document-undo.cpp | 13 --- src/document.cpp | 2 +- src/document.h | 56 ++++++------ src/draw-anchor.cpp | 4 +- src/draw-anchor.h | 9 +- src/event-log.h | 8 -- src/extension/internal/gdkpixbuf-input.cpp | 13 ++- src/extension/internal/gdkpixbuf-input.h | 2 +- src/extract-uri.h | 4 +- src/factory.h | 2 +- src/file.h | 8 +- src/filter-chemistry.h | 9 +- src/filter-enums.h | 2 - src/gc-anchored.h | 1 - src/gc-core.h | 1 - src/gradient-chemistry.h | 21 ++--- src/graphlayout.h | 13 ++- src/helper-fns.h | 30 +------ src/inkscape-version.h | 2 +- src/interface.cpp | 2 +- src/interface.h | 18 ++-- src/isinf.h | 2 +- src/isnormal.h | 19 ---- src/knot-holder-entity.h | 30 +++---- src/knot.h | 62 +++++++------ src/knotholder.h | 9 +- src/layer-manager.h | 11 +-- src/layer-model.h | 6 +- src/line-geometry.h | 5 +- src/line-snapper.cpp | 5 +- src/line-snapper.h | 5 +- src/live_effects/lpe-copy_rotate.cpp | 1 + src/live_effects/lpe-knot.cpp | 1 + src/live_effects/lpeobject-reference.h | 6 +- src/live_effects/lpeobject.h | 4 +- src/main-cmdlineact.h | 6 +- src/marker.h | 10 +-- src/message-context.h | 15 ++-- src/message-stack.h | 31 +++---- src/number-opt-number.h | 30 +++---- src/object-edit.cpp | 140 ++++++++++++++--------------- src/object-hierarchy.cpp | 23 ++--- src/object-hierarchy.h | 3 +- src/path-chemistry.h | 5 +- src/path-prefix.h | 16 ++-- src/persp3d-reference.h | 7 +- src/persp3d.h | 15 ++-- src/perspective-line.h | 1 - src/preferences-skeleton.h | 3 +- src/preferences.h | 6 +- src/print.h | 6 +- src/profile-manager.h | 5 +- src/proj_pt.h | 16 ++-- src/rdf.h | 39 ++++---- src/removeoverlap.h | 2 +- src/rubberband.h | 10 +-- src/selcue.h | 8 +- src/selection-chemistry.h | 30 +++---- src/selection-describer.h | 6 +- src/selection.h | 21 ++--- src/seltrans-handles.h | 14 +-- src/seltrans.h | 67 +++++++------- src/shape-editor.h | 8 +- src/shortcuts.h | 11 +-- src/snap-candidate.h | 5 +- src/snap-preferences.h | 18 ++-- src/snap.h | 1 + src/snapped-curve.h | 6 +- src/snapped-point.h | 7 +- src/snapper.h | 13 ++- src/sp-anchor.h | 14 +-- src/sp-clippath.h | 21 +++-- src/sp-conn-end-pair.h | 18 ++-- src/sp-conn-end.h | 13 ++- src/sp-cursor.cpp | 9 +- src/sp-cursor.h | 9 +- src/sp-defs.h | 2 +- src/sp-desc.h | 6 +- src/sp-ellipse.h | 8 +- src/sp-filter-primitive.h | 12 +-- src/sp-filter.h | 17 ++-- src/sp-flowdiv.h | 26 +++--- src/sp-flowregion.h | 8 +- src/sp-flowtext.h | 10 +-- src/sp-font-face.h | 12 +-- src/sp-font.h | 8 +- src/sp-glyph-kerning.h | 10 +-- src/sp-glyph.h | 4 +- src/sp-gradient-vector.h | 5 +- src/sp-gradient.h | 21 ++--- src/sp-guide.h | 2 +- src/sp-image.h | 13 ++- src/sp-item-group.h | 17 ++-- src/sp-item-notify-moveto.cpp | 9 +- src/sp-item-transform.cpp | 2 + src/sp-item-transform.h | 9 +- src/sp-item.cpp | 2 +- src/sp-item.h | 25 +++--- src/sp-line.h | 6 +- src/sp-linear-gradient.cpp | 2 + src/sp-linear-gradient.h | 4 +- src/sp-lpe-item.h | 10 +-- src/sp-mask.h | 16 ++-- src/sp-mesh-array.h | 64 +++++++------ src/sp-mesh-gradient.h | 4 +- src/sp-mesh-patch.h | 6 +- src/sp-mesh-row.h | 5 +- src/sp-metadata.h | 9 +- src/sp-missing-glyph.h | 12 +-- src/sp-namedview.cpp | 2 +- src/sp-namedview.h | 29 +++--- src/sp-object-group.h | 2 +- src/sp-object.cpp | 16 ++-- src/sp-object.h | 14 +-- src/sp-offset.h | 18 ++-- src/sp-paint-server-reference.h | 3 +- src/sp-paint-server.h | 4 +- src/sp-path.h | 10 +-- src/sp-pattern.h | 31 +++---- src/sp-polygon.h | 13 ++- src/sp-polyline.h | 6 +- src/sp-radial-gradient.cpp | 2 + src/sp-radial-gradient.h | 8 +- src/sp-rect.h | 32 +++---- src/sp-root.h | 8 +- src/sp-script.h | 10 +-- src/sp-shape.h | 16 ++-- src/sp-solid-color.cpp | 2 + src/sp-solid-color.h | 8 +- src/sp-spiral.h | 16 ++-- src/sp-star.h | 18 ++-- src/sp-stop.h | 13 +-- src/sp-string.h | 4 +- src/sp-style-elem.h | 4 +- src/sp-switch.h | 10 ++- src/sp-symbol.h | 18 ++-- src/sp-text.h | 18 ++-- src/sp-textpath.h | 7 +- src/sp-title.h | 6 +- src/sp-tref-reference.h | 8 +- src/sp-tref.h | 6 +- src/sp-tspan.h | 7 +- src/sp-use-reference.h | 8 +- src/sp-use.h | 15 ++-- src/splivarot.h | 7 +- src/streq.h | 1 - src/style-enums.h | 6 +- src/style.h | 35 ++++---- src/svg-view-widget.h | 2 +- src/svg-view.h | 13 ++- src/text-chemistry.h | 2 + src/text-editing.h | 19 ++-- src/transf_mat_3x4.h | 4 +- src/unclump.cpp | 1 + src/unclump.h | 2 +- src/unicoderange.h | 14 +-- src/uri-references.h | 6 +- src/uri.h | 35 ++++---- src/vanishing-point.h | 12 ++- src/verbs.h | 49 +++++----- src/version.cpp | 22 ++--- src/version.h | 12 ++- 171 files changed, 1028 insertions(+), 1113 deletions(-) delete mode 100644 src/isnormal.h (limited to 'src') diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index ab697d126..34f06ed99 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -351,7 +351,6 @@ set(inkscape_SRC inkscape.h interface.h isinf.h - isnormal.h knot-enums.h knot-holder-entity.h knot.h diff --git a/src/Makefile_insert b/src/Makefile_insert index 8e45cb4e0..e1b95c1d6 100644 --- a/src/Makefile_insert +++ b/src/Makefile_insert @@ -74,7 +74,6 @@ ink_common_sources += \ inkscape.cpp inkscape.h inkscape-private.h \ interface.cpp interface.h \ isinf.h \ - isnormal.h \ knot.cpp knot.h \ knot-enums.h \ knotholder.cpp knotholder.h \ diff --git a/src/box3d-side.h b/src/box3d-side.h index 04bd196c2..89b3b0399 100644 --- a/src/box3d-side.h +++ b/src/box3d-side.h @@ -36,16 +36,16 @@ public: static Box3DSide * createBox3DSide(SPBox3D *box); virtual void build(SPDocument* doc, Inkscape::XML::Node* repr); - virtual void set(unsigned int key, gchar const* value); - virtual Inkscape::XML::Node* write(Inkscape::XML::Document *xml_doc, Inkscape::XML::Node *repr, guint flags); - virtual void update(SPCtx *ctx, guint flags); + virtual void set(unsigned int key, char const* value); + virtual Inkscape::XML::Node* write(Inkscape::XML::Document *xml_doc, Inkscape::XML::Node *repr, unsigned int flags); + virtual void update(SPCtx *ctx, unsigned int flags); virtual void set_shape(); }; void box3d_side_position_set (Box3DSide *side); // FIXME: Replace this by box3d_side_set_shape?? -gchar *box3d_side_axes_string(Box3DSide *side); +char *box3d_side_axes_string(Box3DSide *side); Persp3D *box3d_side_perspective(Box3DSide *side); diff --git a/src/box3d.h b/src/box3d.h index 4107d2452..60b966187 100644 --- a/src/box3d.h +++ b/src/box3d.h @@ -32,9 +32,9 @@ public: SPBox3D(); virtual ~SPBox3D(); - gint z_orders[6]; // z_orders[i] holds the ID of the face at position #i in the group (from top to bottom) + int z_orders[6]; // z_orders[i] holds the ID of the face at position #i in the group (from top to bottom) - gchar *persp_href; + char *persp_href; Persp3DReference *persp_ref; Proj::Pt3 orig_corner0; @@ -45,7 +45,7 @@ public: Box3D::Axis swapped; // to indicate which coordinates are swapped during dragging - gint my_counter; // for debugging only + int my_counter; // for debugging only /** * Create a SPBox3D and append it to the parent. @@ -54,24 +54,24 @@ public: virtual void build(SPDocument *document, Inkscape::XML::Node *repr); virtual void release(); - virtual void set(unsigned int key, gchar const* value); - virtual void update(SPCtx *ctx, guint flags); - virtual Inkscape::XML::Node* write(Inkscape::XML::Document *xml_doc, Inkscape::XML::Node *repr, guint flags); + virtual void set(unsigned int key, char const* value); + virtual void update(SPCtx *ctx, unsigned int flags); + virtual Inkscape::XML::Node* write(Inkscape::XML::Document *xml_doc, Inkscape::XML::Node *repr, unsigned int flags); virtual const char* display_name(); virtual Geom::Affine set_transform(Geom::Affine const &transform); virtual void convert_to_guides() const; virtual const char* displayName() const; - virtual gchar *description() const; + virtual char *description() const; }; void box3d_position_set (SPBox3D *box); -Proj::Pt3 box3d_get_proj_corner (SPBox3D const *box, guint id); -Geom::Point box3d_get_corner_screen (SPBox3D const *box, guint id, bool item_coords = true); +Proj::Pt3 box3d_get_proj_corner (SPBox3D const *box, unsigned int id); +Geom::Point box3d_get_corner_screen (SPBox3D const *box, unsigned int id, bool item_coords = true); Proj::Pt3 box3d_get_proj_center (SPBox3D *box); Geom::Point box3d_get_center_screen (SPBox3D *box); -void box3d_set_corner (SPBox3D *box, guint id, Geom::Point const &new_pos, Box3D::Axis movement, bool constrained); +void box3d_set_corner (SPBox3D *box, unsigned int id, Geom::Point const &new_pos, Box3D::Axis movement, bool constrained); void box3d_set_center (SPBox3D *box, Geom::Point const &new_pos, Geom::Point const &old_pos, Box3D::Axis movement, bool constrained); void box3d_corners_for_PLs (const SPBox3D * box, Proj::Axis axis, Geom::Point &corner1, Geom::Point &corner2, Geom::Point &corner3, Geom::Point &corner4); bool box3d_recompute_z_orders (SPBox3D *box); diff --git a/src/context-fns.cpp b/src/context-fns.cpp index 1e30e51de..e1df53d98 100644 --- a/src/context-fns.cpp +++ b/src/context-fns.cpp @@ -1,17 +1,14 @@ -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - #include -#include "sp-item.h" + +#include "context-fns.h" #include "desktop.h" +#include "display/snap-indicator.h" #include "message-context.h" #include "message-stack.h" -#include "context-fns.h" #include "snap.h" -#include "ui/tools/tool-base.h" +#include "sp-item.h" #include "sp-namedview.h" -#include "display/snap-indicator.h" +#include "ui/tools/tool-base.h" static const double midpt_1_goldenratio = (1 + goldenratio) / 2; static const double midpt_goldenratio_2 = (goldenratio + 2) / 2; diff --git a/src/context-fns.h b/src/context-fns.h index bd48e5fb8..82554a6c9 100644 --- a/src/context-fns.h +++ b/src/context-fns.h @@ -2,7 +2,6 @@ #define SEEN_CONTEXT_FNS_H /* - * * * Authors: * @@ -11,11 +10,13 @@ * Released under GNU GPL, read the file 'COPYING' for more information */ -#include #include <2geom/forward.h> -class SPDesktop; -class SPItem; +class SPDesktop; +class SPItem; +typedef union _GdkEvent GdkEvent; + +const double goldenratio = 1.61803398874989484820; // golden ratio namespace Inkscape { namespace UI { @@ -25,12 +26,6 @@ class ToolBase; } } -} - -const double goldenratio = 1.61803398874989484820; // golden ratio - -namespace Inkscape -{ class MessageContext; class MessageStack; diff --git a/src/desktop-style.h b/src/desktop-style.h index fc20e97b9..40ca27e9e 100644 --- a/src/desktop-style.h +++ b/src/desktop-style.h @@ -13,13 +13,12 @@ * Released under GNU GPL, read the file 'COPYING' for more information */ -#include - class ColorRGBA; class SPCSSAttr; class SPDesktop; class SPObject; class SPStyle; +typedef struct _GSList GSList; namespace Inkscape { namespace XML { class Node; diff --git a/src/dir-util.h b/src/dir-util.h index 17261af41..4865158bd 100644 --- a/src/dir-util.h +++ b/src/dir-util.h @@ -9,8 +9,7 @@ * */ -#include -#include +#include /** * Returns a form of \a path relative to \a base if that is easy to construct (eg if \a path @@ -49,7 +48,7 @@ char *inkscape_rel2abs(char const *path, char const *base, char *result, size_t char *inkscape_abs2rel(char const *path, char const *base, char *result, size_t const size); -gchar *prepend_current_dir_if_relative(gchar const *filename); +gchar *prepend_current_dir_if_relative(char const *filename); #endif // !SEEN_DIR_UTIL_H diff --git a/src/document-private.h b/src/document-private.h index 4560aa28f..8e28b288b 100644 --- a/src/document-private.h +++ b/src/document-private.h @@ -34,6 +34,7 @@ class Event; } } +typedef struct _GHashTable GHashTable; struct SPDocumentPrivate { typedef std::map IDChangedSignalMap; diff --git a/src/document-undo.cpp b/src/document-undo.cpp index 478266b7b..0519b6874 100644 --- a/src/document-undo.cpp +++ b/src/document-undo.cpp @@ -44,19 +44,6 @@ * (Lauris Kaplinski) */ -#ifdef HAVE_CONFIG_H -# include "config.h" -#endif - - - -#if HAVE_STRING_H -#endif - - -#if HAVE_STDLIB_H -#endif - #include #include #include "xml/repr.h" diff --git a/src/document.cpp b/src/document.cpp index f79a00178..bb1954916 100644 --- a/src/document.cpp +++ b/src/document.cpp @@ -1370,7 +1370,7 @@ GSList *SPDocument::getItemsAtPoints(unsigned const key, std::vectorpriv != NULL, NULL); diff --git a/src/document.h b/src/document.h index ee903449d..4ace249ae 100644 --- a/src/document.h +++ b/src/document.h @@ -75,8 +75,8 @@ class SPDocument : public Inkscape::GC::Managed<>, public: typedef sigc::signal IDChangedSignal; typedef sigc::signal ResourcesChangedSignal; - typedef sigc::signal ModifiedSignal; - typedef sigc::signal URISetSignal; + typedef sigc::signal ModifiedSignal; + typedef sigc::signal URISetSignal; typedef sigc::signal ResizedSignal; typedef sigc::signal ReconstructionStart; typedef sigc::signal ReconstructionFinish; @@ -100,9 +100,9 @@ public: CRCascade *style_cascade; protected: - gchar *uri; ///< A filename (not a URI yet), or NULL - gchar *base; ///< To be used for resolving relative hrefs. - gchar *name; ///< basename(uri) or other human-readable label for the document. + char *uri; ///< A filename (not a URI yet), or NULL + char *base; ///< To be used for resolving relative hrefs. + char *name; ///< basename(uri) or other human-readable label for the document. public: @@ -112,10 +112,10 @@ public: Glib::ustring actionkey; /// Handler ID - guint modified_id; + unsigned modified_id; /// Connector rerouting handler ID - guint rerouting_handler_id; + unsigned rerouting_handler_id; Inkscape::ProfileManager* profileManager; @@ -137,15 +137,15 @@ public: Inkscape::XML::Document const *getReprDoc() const { return rdoc; } /** A filename (not a URI yet), or NULL */ - gchar const *getURI() const { return uri; } - void setUri(gchar const *uri); + char const *getURI() const { return uri; } + void setUri(char const *uri); /** To be used for resolving relative hrefs. */ - gchar const *getBase() const { return base; }; - void setBase( gchar const* base ); + char const *getBase() const { return base; }; + void setBase( char const* base ); /** basename(uri) or other human-readable label for the document. */ - gchar const* getName() const { return name; } + char const* getName() const { return name; } /** Return the main defs object for the document. */ SPDefs *getDefs(); @@ -173,10 +173,10 @@ public: sigc::connection connectResized(ResizedSignal::slot_type slot); sigc::connection connectCommit(CommitSignal::slot_type slot); - void bindObjectToId(gchar const *id, SPObject *object); + void bindObjectToId(char const *id, SPObject *object); SPObject *getObjectById(Glib::ustring const &id) const; - SPObject *getObjectById(gchar const *id) const; - sigc::connection connectIdChanged(const gchar *id, IDChangedSignal::slot_type slot); + SPObject *getObjectById(char const *id) const; + sigc::connection connectIdChanged(const char *id, IDChangedSignal::slot_type slot); void bindObjectToRepr(Inkscape::XML::Node *repr, SPObject *object); SPObject *getObjectByRepr(Inkscape::XML::Node *repr) const; @@ -222,12 +222,12 @@ public: sigc::connection _selection_changed_connection; sigc::connection _desktop_activated_connection; - sigc::connection connectResourcesChanged(const gchar *key, SPDocument::ResourcesChangedSignal::slot_type slot); + sigc::connection connectResourcesChanged(char const *key, SPDocument::ResourcesChangedSignal::slot_type slot); void fitToRect(Geom::Rect const &rect, bool with_margins = false); - static SPDocument *createNewDoc(const gchar *uri, unsigned int keepalive, + static SPDocument *createNewDoc(char const*uri, unsigned int keepalive, bool make_new = false, SPDocument *parent=NULL ); - static SPDocument *createNewDocFromMem(const gchar *buffer, gint length, unsigned int keepalive); + static SPDocument *createNewDocFromMem(char const*buffer, int length, unsigned int keepalive); SPDocument *createChildDoc(std::string const &uri); /** @@ -235,8 +235,8 @@ public: */ static SPItem *getItemFromListAtPointBottom(unsigned int dkey, SPGroup *group, const GSList *list, Geom::Point const &p, bool take_insensitive = false); - static SPDocument *createDoc(Inkscape::XML::Document *rdoc, gchar const *uri, - gchar const *base, gchar const *name, unsigned int keepalive, + static SPDocument *createDoc(Inkscape::XML::Document *rdoc, char const *uri, + char const *base, char const *name, unsigned int keepalive, SPDocument *parent); SPDocument *doRef(); @@ -250,25 +250,25 @@ public: void setHeight(const Inkscape::Util::Quantity &height); void setViewBox(const Geom::Rect &viewBox); void requestModified(); - gint ensureUpToDate(); - bool addResource(const gchar *key, SPObject *object); - bool removeResource(const gchar *key, SPObject *object); - const GSList *getResourceList(const gchar *key) const; + int ensureUpToDate(); + bool addResource(char const *key, SPObject *object); + bool removeResource(char const *key, SPObject *object); + const GSList *getResourceList(char const *key) const; GSList *getItemsInBox(unsigned int dkey, Geom::Rect const &box) const; GSList *getItemsPartiallyInBox(unsigned int dkey, Geom::Rect const &box) const; - SPItem *getItemAtPoint(unsigned int key, Geom::Point const &p, gboolean into_groups, SPItem *upto = NULL) const; + SPItem *getItemAtPoint(unsigned int key, Geom::Point const &p, bool into_groups, SPItem *upto = NULL) const; GSList *getItemsAtPoints(unsigned const key, std::vector points) const; SPItem *getGroupAtPoint(unsigned int key, Geom::Point const &p) const; - void changeUriAndHrefs(gchar const *uri); - void emitResizedSignal(gdouble width, gdouble height); + void changeUriAndHrefs(char const *uri); + void emitResizedSignal(double width, double height); unsigned int vacuumDocument(); void importDefs(SPDocument *source); private: - void do_change_uri(gchar const *const filename, bool const rebase); + void do_change_uri(char const *const filename, bool const rebase); void setupViewport(SPItemCtx *ctx); }; diff --git a/src/draw-anchor.cpp b/src/draw-anchor.cpp index 00db936e1..6b02bb607 100644 --- a/src/draw-anchor.cpp +++ b/src/draw-anchor.cpp @@ -30,7 +30,7 @@ using Inkscape::ControlManager; /** * Creates an anchor object and initializes it. */ -SPDrawAnchor *sp_draw_anchor_new(Inkscape::UI::Tools::FreehandBase *dc, SPCurve *curve, gboolean start, Geom::Point delta) +SPDrawAnchor *sp_draw_anchor_new(Inkscape::UI::Tools::FreehandBase *dc, SPCurve *curve, bool start, Geom::Point delta) { if (SP_IS_LPETOOL_CONTEXT(dc)) { // suppress all kinds of anchors in LPEToolContext @@ -73,7 +73,7 @@ SPDrawAnchor *sp_draw_anchor_destroy(SPDrawAnchor *anchor) * Test if point is near anchor, if so fill anchor on canvas and return * pointer to it or NULL. */ -SPDrawAnchor *sp_draw_anchor_test(SPDrawAnchor *anchor, Geom::Point w, gboolean activate) +SPDrawAnchor *sp_draw_anchor_test(SPDrawAnchor *anchor, Geom::Point w, bool activate) { SPCtrl *ctrl = SP_CTRL(anchor->ctrl); diff --git a/src/draw-anchor.h b/src/draw-anchor.h index e7b252186..1f7b55920 100644 --- a/src/draw-anchor.h +++ b/src/draw-anchor.h @@ -5,7 +5,6 @@ * Drawing anchors. */ -#include #include <2geom/point.h> namespace Inkscape { @@ -26,17 +25,17 @@ struct SPCanvasItem; struct SPDrawAnchor { Inkscape::UI::Tools::FreehandBase *dc; SPCurve *curve; - guint start : 1; - guint active : 1; + unsigned int start : 1; + unsigned int active : 1; Geom::Point dp; SPCanvasItem *ctrl; }; -SPDrawAnchor *sp_draw_anchor_new(Inkscape::UI::Tools::FreehandBase *dc, SPCurve *curve, gboolean start, +SPDrawAnchor *sp_draw_anchor_new(Inkscape::UI::Tools::FreehandBase *dc, SPCurve *curve, bool start, Geom::Point delta); SPDrawAnchor *sp_draw_anchor_destroy(SPDrawAnchor *anchor); -SPDrawAnchor *sp_draw_anchor_test(SPDrawAnchor *anchor, Geom::Point w, gboolean activate); +SPDrawAnchor *sp_draw_anchor_test(SPDrawAnchor *anchor, Geom::Point w, bool activate); #endif /* !SEEN_DRAW_ANCHOR_H */ diff --git a/src/event-log.h b/src/event-log.h index 7e3ba6817..6d4112a5a 100644 --- a/src/event-log.h +++ b/src/event-log.h @@ -11,14 +11,6 @@ #ifndef INKSCAPE_EVENT_LOG_H #define INKSCAPE_EVENT_LOG_H -#ifdef HAVE_CONFIG_H -# include "config.h" -#endif - -#if GLIBMM_DISABLE_DEPRECATED && HAVE_GLIBMM_THREADS_H -#include -#endif - #include #include #include diff --git a/src/extension/internal/gdkpixbuf-input.cpp b/src/extension/internal/gdkpixbuf-input.cpp index da179bee0..28e44c461 100644 --- a/src/extension/internal/gdkpixbuf-input.cpp +++ b/src/extension/internal/gdkpixbuf-input.cpp @@ -1,21 +1,20 @@ -#ifdef HAVE_CONFIG_H -# include -#endif +#include + #include #include #include +#include "dir-util.h" +#include "display/cairo-utils.h" #include "document-private.h" -#include +#include "document-undo.h" #include "extension/input.h" #include "extension/system.h" +#include "image-resolution.h" #include "gdkpixbuf-input.h" #include "preferences.h" #include "selection-chemistry.h" #include "sp-image.h" -#include "document-undo.h" #include "util/units.h" -#include "image-resolution.h" -#include "display/cairo-utils.h" #include namespace Inkscape { diff --git a/src/extension/internal/gdkpixbuf-input.h b/src/extension/internal/gdkpixbuf-input.h index 597e7246b..2e03a96db 100644 --- a/src/extension/internal/gdkpixbuf-input.h +++ b/src/extension/internal/gdkpixbuf-input.h @@ -10,7 +10,7 @@ namespace Internal { class GdkpixbufInput : Inkscape::Extension::Implementation::Implementation { public: SPDocument *open(Inkscape::Extension::Input *mod, - gchar const *uri); + char const *uri); static void init(); }; diff --git a/src/extract-uri.h b/src/extract-uri.h index a6707f1a1..e9ee0b1d8 100644 --- a/src/extract-uri.h +++ b/src/extract-uri.h @@ -1,9 +1,7 @@ #ifndef SEEN_EXTRACT_URI_H #define SEEN_EXTRACT_URI_H -#include - -gchar *extract_uri(gchar const *s, gchar const** endptr = 0); +char *extract_uri(char const *s, char const** endptr = 0); #endif /* !SEEN_EXTRACT_URI_H */ diff --git a/src/factory.h b/src/factory.h index c76501cfd..c1288b460 100644 --- a/src/factory.h +++ b/src/factory.h @@ -91,7 +91,7 @@ struct NodeTraits { break; case Inkscape::XML::ELEMENT_NODE: { - gchar const *const sptype = node.attribute("sodipodi:type"); + char const *const sptype = node.attribute("sodipodi:type"); if (sptype) { name = sptype; diff --git a/src/file.h b/src/file.h index 7f80f3645..4ffbc8ec0 100644 --- a/src/file.h +++ b/src/file.h @@ -75,7 +75,7 @@ bool sp_file_open( * Displays a file open dialog. Calls sp_file_open on * an OK. */ -void sp_file_open_dialog (Gtk::Window &parentWindow, gpointer object, gpointer data); +void sp_file_open_dialog (Gtk::Window &parentWindow, void* object, void* data); /** * Reverts file to disk-copy on "YES" @@ -96,19 +96,19 @@ bool file_save_remote(SPDocument *doc, const Glib::ustring &uri, /** * */ -bool sp_file_save (Gtk::Window &parentWindow, gpointer object, gpointer data); +bool sp_file_save (Gtk::Window &parentWindow, void* object, void* data); /** * Saves the given document. Displays a file select dialog * to choose the new name. */ -bool sp_file_save_as (Gtk::Window &parentWindow, gpointer object, gpointer data); +bool sp_file_save_as (Gtk::Window &parentWindow, void* object, void* data); /** * Saves a copy of the given document. Displays a file select dialog * to choose a name for the copy. */ -bool sp_file_save_a_copy (Gtk::Window &parentWindow, gpointer object, gpointer data); +bool sp_file_save_a_copy (Gtk::Window &parentWindow, void* object, void* data); /** diff --git a/src/filter-chemistry.h b/src/filter-chemistry.h index 2ac3ebe8f..104016845 100644 --- a/src/filter-chemistry.h +++ b/src/filter-chemistry.h @@ -14,8 +14,6 @@ #ifndef SEEN_SP_FILTER_CHEMISTRY_H #define SEEN_SP_FILTER_CHEMISTRY_H -#include - #include "display/nr-filter-types.h" class SPDocument; @@ -24,12 +22,11 @@ class SPFilterPrimitive; class SPItem; class SPObject; - SPFilterPrimitive *filter_add_primitive(SPFilter *filter, Inkscape::Filters::FilterPrimitiveType); SPFilter *new_filter (SPDocument *document); -SPFilter *new_filter_gaussian_blur (SPDocument *document, gdouble stdDeviation, double expansion, double expansionX, double expansionY, double width, double height); -SPFilter *new_filter_simple_from_item (SPDocument *document, SPItem *item, const char *mode, gdouble stdDeviation); -SPFilter *modify_filter_gaussian_blur_from_item (SPDocument *document, SPItem *item, gdouble stdDeviation); +SPFilter *new_filter_gaussian_blur (SPDocument *document, double stdDeviation, double expansion, double expansionX, double expansionY, double width, double height); +SPFilter *new_filter_simple_from_item (SPDocument *document, SPItem *item, const char *mode, double stdDeviation); +SPFilter *modify_filter_gaussian_blur_from_item (SPDocument *document, SPItem *item, double stdDeviation); void remove_filter (SPObject *item, bool recursive); void remove_filter_gaussian_blur (SPObject *item); bool filter_is_single_gaussian_blur(SPFilter *filter); diff --git a/src/filter-enums.h b/src/filter-enums.h index e6d656f8a..3ced5ab94 100644 --- a/src/filter-enums.h +++ b/src/filter-enums.h @@ -12,8 +12,6 @@ * Released under GNU GPL, read the file 'COPYING' for more information */ -#include - #include "display/nr-filter-blend.h" #include "display/nr-filter-colormatrix.h" #include "display/nr-filter-component-transfer.h" diff --git a/src/gc-anchored.h b/src/gc-anchored.h index a20904dce..99b78c784 100644 --- a/src/gc-anchored.h +++ b/src/gc-anchored.h @@ -9,7 +9,6 @@ #ifndef SEEN_INKSCAPE_GC_ANCHORED_H #define SEEN_INKSCAPE_GC_ANCHORED_H -#include #include "gc-managed.h" namespace Inkscape { diff --git a/src/gc-core.h b/src/gc-core.h index 3957bda1a..d9d0bf4ff 100644 --- a/src/gc-core.h +++ b/src/gc-core.h @@ -24,7 +24,6 @@ #else # include #endif -#include namespace Inkscape { namespace GC { diff --git a/src/gradient-chemistry.h b/src/gradient-chemistry.h index 728874f88..792ccc72e 100644 --- a/src/gradient-chemistry.h +++ b/src/gradient-chemistry.h @@ -22,6 +22,7 @@ class SPCSSAttr; class SPItem; +typedef unsigned int guint32; /** * Either normalizes given gradient to vector, or returns fresh normalized @@ -53,7 +54,7 @@ SPGradient *sp_gradient_vector_for_object( SPDocument *doc, SPDesktop *desktop, void sp_object_ensure_fill_gradient_normalized (SPObject *object); void sp_object_ensure_stroke_gradient_normalized (SPObject *object); -SPGradient *sp_gradient_convert_to_userspace (SPGradient *gr, SPItem *item, const gchar *property); +SPGradient *sp_gradient_convert_to_userspace (SPGradient *gr, SPItem *item, const char *property); SPGradient *sp_gradient_reset_to_userspace (SPGradient *gr, SPItem *item); SPGradient *sp_gradient_fork_vector_if_necessary (SPGradient *gr); @@ -61,11 +62,11 @@ SPGradient *sp_gradient_get_forked_vector_if_necessary(SPGradient *gradient, boo SPStop* sp_last_stop(SPGradient *gradient); -SPStop* sp_get_stop_i(SPGradient *gradient, guint i); -guint sp_number_of_stops(SPGradient const *gradient); -guint sp_number_of_stops_before_stop(SPGradient const *gradient, SPStop *target); +SPStop* sp_get_stop_i(SPGradient *gradient, unsigned int i); +unsigned int sp_number_of_stops(SPGradient const *gradient); +unsigned int sp_number_of_stops_before_stop(SPGradient const *gradient, SPStop *target); -guint32 average_color(guint32 c1, guint32 c2, gdouble p = 0.5); +guint32 average_color(guint32 c1, guint32 c2, double p = 0.5); SPStop *sp_vector_add_stop(SPGradient *vector, SPStop* prev_stop, SPStop* next_stop, gfloat offset); @@ -86,20 +87,20 @@ void sp_gradient_unset_swatch(SPDesktop *desktop, std::string id); SPGradient *getGradient(SPItem *item, Inkscape::PaintTarget fill_or_stroke); -void sp_item_gradient_set_coords(SPItem *item, GrPointType point_type, guint point_i, Geom::Point p_desk, Inkscape::PaintTarget fill_or_stroke, bool write_repr, bool scale); +void sp_item_gradient_set_coords(SPItem *item, GrPointType point_type, unsigned int point_i, Geom::Point p_desk, Inkscape::PaintTarget fill_or_stroke, bool write_repr, bool scale); /** * Returns the position of point point_type of the gradient applied to item (either fill_or_stroke), * in desktop coordinates. */ -Geom::Point getGradientCoords(SPItem *item, GrPointType point_type, guint point_i, Inkscape::PaintTarget fill_or_stroke); +Geom::Point getGradientCoords(SPItem *item, GrPointType point_type, unsigned int point_i, Inkscape::PaintTarget fill_or_stroke); SPGradient *sp_item_gradient_get_vector(SPItem *item, Inkscape::PaintTarget fill_or_stroke); SPGradientSpread sp_item_gradient_get_spread(SPItem *item, Inkscape::PaintTarget fill_or_stroke); -void sp_item_gradient_stop_set_style(SPItem *item, GrPointType point_type, guint point_i, Inkscape::PaintTarget fill_or_stroke, SPCSSAttr *stop); -guint32 sp_item_gradient_stop_query_style(SPItem *item, GrPointType point_type, guint point_i, Inkscape::PaintTarget fill_or_stroke); -void sp_item_gradient_edit_stop(SPItem *item, GrPointType point_type, guint point_i, Inkscape::PaintTarget fill_or_stroke); +void sp_item_gradient_stop_set_style(SPItem *item, GrPointType point_type, unsigned int point_i, Inkscape::PaintTarget fill_or_stroke, SPCSSAttr *stop); +guint32 sp_item_gradient_stop_query_style(SPItem *item, GrPointType point_type, unsigned int point_i, Inkscape::PaintTarget fill_or_stroke); +void sp_item_gradient_edit_stop(SPItem *item, GrPointType point_type, unsigned int point_i, Inkscape::PaintTarget fill_or_stroke); void sp_item_gradient_reverse_vector(SPItem *item, Inkscape::PaintTarget fill_or_stroke); void sp_item_gradient_invert_vector_color(SPItem *item, Inkscape::PaintTarget fill_or_stroke); diff --git a/src/graphlayout.h b/src/graphlayout.h index 6083ad77f..0ffb645b6 100644 --- a/src/graphlayout.h +++ b/src/graphlayout.h @@ -14,10 +14,15 @@ #ifndef SEEN_GRAPHLAYOUT_H #define SEEN_GRAPHLAYOUT_H -struct _GSList; -void graphlayout(_GSList const *const items); +#include + +typedef struct _GSList GSList; class SPItem; + +void graphlayout(GSList const *const items); + bool isConnector(SPItem const *const item); -#include -void filterConnectors(_GSList const *const items, std::list &filtered); + +void filterConnectors(GSList const *const items, std::list &filtered); + #endif // SEEN_GRAPHLAYOUT_H diff --git a/src/helper-fns.h b/src/helper-fns.h index 699fbbe11..2f1829c37 100644 --- a/src/helper-fns.h +++ b/src/helper-fns.h @@ -10,7 +10,7 @@ * Released under GNU GPL, read the file 'COPYING' for more information */ -#include +#include #include #include @@ -59,34 +59,6 @@ inline bool helperfns_read_bool(gchar const *value, bool default_value){ return default_value; } -/* convert ascii representation to double - * the function can only be used to convert numbers as given by gui elements that use localized representation - * numbers are delimeted by space - * @param value ascii representation of the number - * @param size number of elements in string - * @return the vector of the converted numbers - */ -/* -inline std::vector helperfns_read_vector(const gchar* value, int size){ - std::vector v(size, (gdouble) 0); - std::istringstream is(value); - for(int i = 0; i < size; i++){ - std::string str; - is >> str; - char *end; - - double ret = g_ascii_strtod(str.c_str(), &end); - if (*end) { - g_warning("helper-fns::helperfns_read_vector() Unable to convert \"%s\" to number", str.c_str()); - // We could leave this out, too. If strtod can't convert - // anything, it will return zero. - ret = 0; - } - v[i] = ret; - }; - return v; -} -*/ /* convert ascii representation to double * the function can only be used to convert numbers as given by gui elements that use localized representation * numbers are delimeted by space diff --git a/src/inkscape-version.h b/src/inkscape-version.h index 791351184..ff219047e 100644 --- a/src/inkscape-version.h +++ b/src/inkscape-version.h @@ -16,7 +16,7 @@ namespace Inkscape { -extern gchar const *version_string; ///< Full version string +extern char const *version_string; ///< Full version string } // namespace Inkscape diff --git a/src/interface.cpp b/src/interface.cpp index 1cbeb44a3..3b5958a33 100644 --- a/src/interface.cpp +++ b/src/interface.cpp @@ -149,7 +149,7 @@ static void injectRenamedIcons(); static const int MIN_ONSCREEN_DISTANCE = 50; void -sp_create_window(SPViewWidget *vw, gboolean editable) +sp_create_window(SPViewWidget *vw, bool editable) { g_return_if_fail(vw != NULL); g_return_if_fail(SP_IS_VIEW_WIDGET(vw)); diff --git a/src/interface.h b/src/interface.h index 215a3bfc9..2418223ae 100644 --- a/src/interface.h +++ b/src/interface.h @@ -17,13 +17,9 @@ * Released under GNU GPL, read the file 'COPYING' for more information */ -#ifdef HAVE_CONFIG_H -# include -#endif - -#if GLIBMM_DISABLE_DEPRECATED && HAVE_GLIBMM_THREADS_H -#include -#endif +//#ifdef HAVE_CONFIG_H +//# include +//#endif #include @@ -50,7 +46,7 @@ class View; /** * Create a new document window. */ -void sp_create_window (SPViewWidget *vw, gboolean editable); +void sp_create_window (SPViewWidget *vw, bool editable); /** * \param widget unused @@ -87,15 +83,15 @@ unsigned int sp_ui_close_all (void); GtkWidget *sp_ui_main_menubar (Inkscape::UI::View::View *view); void sp_menu_append_recent_documents (GtkWidget *menu); -void sp_ui_dialog_title_string (Inkscape::Verb * verb, gchar* c); +void sp_ui_dialog_title_string (Inkscape::Verb * verb, char* c); Glib::ustring getLayoutPrefPath( Inkscape::UI::View::View *view ); /** * */ -void sp_ui_error_dialog (const gchar * message); -bool sp_ui_overwrite_file (const gchar * filename); +void sp_ui_error_dialog (char const* message); +bool sp_ui_overwrite_file (char const* filename); /** diff --git a/src/isinf.h b/src/isinf.h index b4c56f79d..8d590b972 100644 --- a/src/isinf.h +++ b/src/isinf.h @@ -2,7 +2,7 @@ #define __ISINF_H__ /* - * Fix for missing std::isnormal with SOLARIS8/GCC3.2 + * Fix for missing std::isinf with SOLARIS8/GCC3.2 */ #if defined (SOLARIS) diff --git a/src/isnormal.h b/src/isnormal.h deleted file mode 100644 index d53105926..000000000 --- a/src/isnormal.h +++ /dev/null @@ -1,19 +0,0 @@ -#ifndef __ISNORMAL_H__ -#define __ISNORMAL_H__ - -/* - * Fix for missing std::isnormal with SOLARIS8/GCC3.2 - */ - -#if defined (SOLARIS) - - #include - #define isnormal(x) (fpclass(x) >= FP_NZERO) - -#else - - using std::isnormal; - -#endif - -#endif /* __ISNORMAL_H__ */ diff --git a/src/knot-holder-entity.h b/src/knot-holder-entity.h index dde60f515..43ab25e5c 100644 --- a/src/knot-holder-entity.h +++ b/src/knot-holder-entity.h @@ -14,11 +14,11 @@ * Released under GNU GPL */ -#include -#include "knot.h" #include <2geom/forward.h> -#include "snapper.h" + #include "display/sp-canvas-item.h" +#include "knot.h" +#include "snapper.h" class SPItem; class SPKnot; @@ -31,7 +31,7 @@ namespace LivePathEffect { } // namespace LivePathEffect } // namespace Inkscape -typedef void (* SPKnotHolderSetFunc) (SPItem *item, Geom::Point const &p, Geom::Point const &origin, guint state); +typedef void (* SPKnotHolderSetFunc) (SPItem *item, Geom::Point const &p, Geom::Point const &origin, unsigned int state); typedef Geom::Point (* SPKnotHolderGetFunc) (SPItem *item); /** @@ -50,22 +50,22 @@ public: virtual void create(SPDesktop *desktop, SPItem *item, KnotHolder *parent, Inkscape::ControlType type = Inkscape::CTRL_TYPE_UNKNOWN, - const gchar *tip = "", + char const*tip = "", SPKnotShapeType shape = SP_KNOT_SHAPE_DIAMOND, SPKnotModeType mode = SP_KNOT_MODE_XOR, guint32 color = 0xffffff00); /* the get/set/click handlers are virtual functions; each handler class for a knot should be derived from KnotHolderEntity and override these functions */ - virtual void knot_set(Geom::Point const &p, Geom::Point const &origin, guint state) = 0; + virtual void knot_set(Geom::Point const &p, Geom::Point const &origin, unsigned int state) = 0; virtual Geom::Point knot_get() const = 0; - virtual void knot_click(guint /*state*/) {} + virtual void knot_click(unsigned int /*state*/) {} void update_knot(); //private: - Geom::Point snap_knot_position(Geom::Point const &p, guint state); - Geom::Point snap_knot_position_constrained(Geom::Point const &p, Inkscape::Snapper::SnapConstraint const &constraint, guint state); + Geom::Point snap_knot_position(Geom::Point const &p, unsigned int state); + Geom::Point snap_knot_position_constrained(Geom::Point const &p, Inkscape::Snapper::SnapConstraint const &constraint, unsigned int state); SPKnot *knot; SPItem *item; @@ -77,11 +77,11 @@ public: static int counter; /** Connection to \a knot's "moved" signal. */ - guint handler_id; + unsigned int handler_id; /** Connection to \a knot's "clicked" signal. */ - guint _click_handler_id; + unsigned int _click_handler_id; /** Connection to \a knot's "ungrabbed" signal. */ - guint _ungrab_handler_id; + unsigned int _ungrab_handler_id; private: sigc::connection _moved_connection; @@ -103,7 +103,7 @@ class PatternKnotHolderEntityXY : public KnotHolderEntity { public: PatternKnotHolderEntityXY(bool fill) : KnotHolderEntity(), _fill(fill) {} virtual Geom::Point knot_get() const; - virtual void knot_set(Geom::Point const &p, Geom::Point const &origin, guint state); + virtual void knot_set(Geom::Point const &p, Geom::Point const &origin, unsigned int state); private: // true if the entity tracks fill, false for stroke bool _fill; @@ -113,7 +113,7 @@ class PatternKnotHolderEntityAngle : public KnotHolderEntity { public: PatternKnotHolderEntityAngle(bool fill) : KnotHolderEntity(), _fill(fill) {} virtual Geom::Point knot_get() const; - virtual void knot_set(Geom::Point const &p, Geom::Point const &origin, guint state); + virtual void knot_set(Geom::Point const &p, Geom::Point const &origin, unsigned int state); private: bool _fill; }; @@ -122,7 +122,7 @@ class PatternKnotHolderEntityScale : public KnotHolderEntity { public: PatternKnotHolderEntityScale(bool fill) : KnotHolderEntity(), _fill(fill) {} virtual Geom::Point knot_get() const; - virtual void knot_set(Geom::Point const &p, Geom::Point const &origin, guint state); + virtual void knot_set(Geom::Point const &p, Geom::Point const &origin, unsigned int state); private: bool _fill; }; diff --git a/src/knot.h b/src/knot.h index b79614bcb..e3ad98e66 100644 --- a/src/knot.h +++ b/src/knot.h @@ -14,15 +14,19 @@ * Released under GNU GPL, read the file 'COPYING' for more information */ -#include #include <2geom/point.h> -#include "knot-enums.h" #include + +#include "knot-enums.h" #include "enums.h" class SPDesktop; -struct SPCanvasItem; class SPItem; +struct SPCanvasItem; + +typedef struct _GdkCursor GdkCursor; +typedef union _GdkEvent GdkEvent; +typedef unsigned int guint32; #define SP_KNOT(obj) (dynamic_cast(static_cast(obj))) #define SP_IS_KNOT(obj) (dynamic_cast(static_cast(obj)) != NULL) @@ -36,19 +40,17 @@ class SPItem; */ class SPKnot { public: - SPKnot(SPDesktop *desktop, gchar const *tip); + SPKnot(SPDesktop *desktop, char const *tip); virtual ~SPKnot(); - - int ref_count; - + int ref_count; // FIXME encapsulation SPDesktop *desktop; /**< Desktop we are on. */ SPCanvasItem *item; /**< Our CanvasItem. */ SPItem *owner; /**< Optional Owner Item */ - guint flags; + unsigned int flags; - guint size; /**< Always square. */ + unsigned int size; /**< Always square. */ Geom::Point pos; /**< Our desktop coordinates. */ Geom::Point grabbed_rel_pos; /**< Grabbed relative position. */ Geom::Point drag_origin; /**< Origin of drag. */ @@ -59,39 +61,41 @@ public: guint32 fill[SP_KNOT_VISIBLE_STATES]; guint32 stroke[SP_KNOT_VISIBLE_STATES]; - guchar *image[SP_KNOT_VISIBLE_STATES]; + unsigned char *image[SP_KNOT_VISIBLE_STATES]; GdkCursor *cursor[SP_KNOT_VISIBLE_STATES]; GdkCursor *saved_cursor; - gpointer pixbuf; + void* pixbuf; - gchar *tip; + char *tip; - gulong _event_handler_id; + unsigned long _event_handler_id; double pressure; /**< The tablet pen pressure when the knot is being dragged. */ - sigc::signal click_signal; - sigc::signal doubleclicked_signal; - sigc::signal grabbed_signal; - sigc::signal ungrabbed_signal; - sigc::signal moved_signal; + // FIXME: signals should NOT need to emit the object they came from, the callee should + // be able to figure that out + sigc::signal click_signal; + sigc::signal doubleclicked_signal; + sigc::signal grabbed_signal; + sigc::signal ungrabbed_signal; + sigc::signal moved_signal; sigc::signal event_signal; - sigc::signal request_signal; + sigc::signal request_signal; //TODO: all the members above should eventualle become private, accessible via setters/getters - void setSize(guint i); - void setShape(guint i); - void setAnchor(guint i); - void setMode(guint i); - void setPixbuf(gpointer p); + void setSize(unsigned int i); + void setShape(unsigned int i); + void setAnchor(unsigned int i); + void setMode(unsigned int i); + void setPixbuf(void* p); void setFill(guint32 normal, guint32 mouseover, guint32 dragging); void setStroke(guint32 normal, guint32 mouseover, guint32 dragging); - void setImage(guchar* normal, guchar* mouseover, guchar* dragging); + void setImage(unsigned char* normal, unsigned char* mouseover, unsigned char* dragging); void setCursor(GdkCursor* normal, GdkCursor* mouseover, GdkCursor* dragging); @@ -108,7 +112,7 @@ public: /** * Set flag in knot, with side effects. */ - void setFlag(guint flag, bool set); + void setFlag(unsigned int flag, bool set); /** * Update knot's pixbuf and set its control state. @@ -118,17 +122,17 @@ public: /** * Request or set new position for knot. */ - void requestPosition(Geom::Point const &pos, guint state); + void requestPosition(Geom::Point const &pos, unsigned int state); /** * Update knot for dragging and tell canvas an item was grabbed. */ - void startDragging(Geom::Point const &p, gint x, gint y, guint32 etime); + void startDragging(Geom::Point const &p, int x, int y, guint32 etime); /** * Move knot to new position and emits "moved" signal. */ - void setPosition(Geom::Point const &p, guint state); + void setPosition(Geom::Point const &p, unsigned int state); /** * Move knot to new position, without emitting a MOVED signal. diff --git a/src/knotholder.h b/src/knotholder.h index dc2300105..d33adb610 100644 --- a/src/knotholder.h +++ b/src/knotholder.h @@ -17,7 +17,6 @@ * */ -#include #include <2geom/forward.h> #include #include @@ -47,9 +46,9 @@ public: void update_knots(); - void knot_moved_handler(SPKnot *knot, Geom::Point const &p, guint state); - void knot_clicked_handler(SPKnot *knot, guint state); - void knot_ungrabbed_handler(SPKnot *knot, guint); + void knot_moved_handler(SPKnot *knot, Geom::Point const &p, unsigned int state); + void knot_clicked_handler(SPKnot *knot, unsigned int state); + void knot_ungrabbed_handler(SPKnot *knot, unsigned int); void add(KnotHolderEntity *e); @@ -76,7 +75,7 @@ protected: SPKnotHolderReleasedFunc released; - gboolean local_change; ///< if true, no need to recreate knotholder if repr was changed. + bool local_change; ///< if true, no need to recreate knotholder if repr was changed. bool dragging; diff --git a/src/layer-manager.h b/src/layer-manager.h index 1b69324d5..9eea68004 100644 --- a/src/layer-manager.h +++ b/src/layer-manager.h @@ -10,11 +10,12 @@ #ifndef SEEN_INKSCAPE_LAYER_MANAGER_H #define SEEN_INKSCAPE_LAYER_MANAGER_H +#include +#include + #include "document-subset.h" #include "gc-finalized.h" #include "gc-soft-ptr.h" -#include -#include class SPDesktop; class SPDocument; @@ -29,8 +30,8 @@ public: virtual ~LayerManager(); void setCurrentLayer( SPObject* obj ); - void renameLayer( SPObject* obj, gchar const *label, bool uniquify ); - Glib::ustring getNextLayerName( SPObject* obj, gchar const *label); + void renameLayer( SPObject* obj, char const *label, bool uniquify ); + Glib::ustring getNextLayerName( SPObject* obj, char const *label); sigc::connection connectCurrentLayerChanged(const sigc::slot & slot) { return _layer_changed_signal.connect(slot); @@ -44,7 +45,7 @@ private: friend class LayerWatcher; class LayerWatcher; - void _objectModified( SPObject* obj, guint flags ); + void _objectModified( SPObject* obj, unsigned int flags ); void _setDocument(SPDocument *document); void _rebuild(); void _selectedLayerChanged(SPObject *layer); diff --git a/src/layer-model.h b/src/layer-model.h index 79b7fbe44..86aba63ef 100644 --- a/src/layer-model.h +++ b/src/layer-model.h @@ -22,12 +22,8 @@ * */ -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include #include +#include class SPDocument; class SPObject; diff --git a/src/line-geometry.h b/src/line-geometry.h index d7be9570c..a77d6e1f3 100644 --- a/src/line-geometry.h +++ b/src/line-geometry.h @@ -12,13 +12,14 @@ #ifndef SEEN_LINE_GEOMETRY_H #define SEEN_LINE_GEOMETRY_H +#include <2geom/point.h> #include -#include "glib.h" + #include "axis-manip.h" // FIXME: This is only for Box3D::epsilon; move that to a better location -#include "2geom/point.h" #include "persp3d.h" class SPDesktop; +typedef unsigned int guint32; namespace Box3D { diff --git a/src/line-snapper.cpp b/src/line-snapper.cpp index 930b7fca9..6122b133a 100644 --- a/src/line-snapper.cpp +++ b/src/line-snapper.cpp @@ -11,9 +11,10 @@ */ #include <2geom/line.h> +#include + #include "line-snapper.h" #include "snapped-line.h" -//#include #include "snap.h" Inkscape::LineSnapper::LineSnapper(SnapManager *sm, Geom::Coord const d) : Snapper(sm, d) @@ -37,7 +38,7 @@ void Inkscape::LineSnapper::freeSnap(IntermSnapResults &isr, Geom::Point const p1 = i->second; // point at guide/grid line Geom::Point const p2 = p1 + Geom::rot90(i->first); // 2nd point at guide/grid line // std::cout << " line through " << i->second << " with normal " << i->first; - g_assert(i->first != Geom::Point(0,0)); // we cannot project on an linesegment of zero length + assert(i->first != Geom::Point(0,0)); // we cannot project on an linesegment of zero length Geom::Point const p_proj = Geom::projection(p.getPoint(), Geom::Line(p1, p2)); Geom::Coord const dist = Geom::L2(p_proj - p.getPoint()); diff --git a/src/line-snapper.h b/src/line-snapper.h index 4b165e0a5..b2fc3d389 100644 --- a/src/line-snapper.h +++ b/src/line-snapper.h @@ -12,10 +12,9 @@ #include "snapper.h" -namespace Inkscape -{ -class SnapCandidatePoint; +namespace Inkscape { +class SnapCandidatePoint; /** * Superclass for snappers to horizontal and vertical lines. diff --git a/src/live_effects/lpe-copy_rotate.cpp b/src/live_effects/lpe-copy_rotate.cpp index 65bbcdad1..e466093d3 100644 --- a/src/live_effects/lpe-copy_rotate.cpp +++ b/src/live_effects/lpe-copy_rotate.cpp @@ -12,6 +12,7 @@ */ #include +#include #include "live_effects/lpe-copy_rotate.h" #include "sp-shape.h" diff --git a/src/live_effects/lpe-knot.cpp b/src/live_effects/lpe-knot.cpp index cac3a9347..938287c22 100644 --- a/src/live_effects/lpe-knot.cpp +++ b/src/live_effects/lpe-knot.cpp @@ -22,6 +22,7 @@ #include "knotholder.h" #include +#include #include <2geom/sbasis-to-bezier.h> #include <2geom/sbasis.h> diff --git a/src/live_effects/lpeobject-reference.h b/src/live_effects/lpeobject-reference.h index b1ba1ee4e..374e715ec 100644 --- a/src/live_effects/lpeobject-reference.h +++ b/src/live_effects/lpeobject-reference.h @@ -9,10 +9,10 @@ * Released under GNU GPL, read the file 'COPYING' for more information. */ -#include -#include #include +#include "uri-references.h" + namespace Inkscape { namespace XML { class Node; @@ -33,7 +33,7 @@ public: SPObject *owner; // concerning the LPEObject that is refered to: - gchar *lpeobject_href; + char *lpeobject_href; Inkscape::XML::Node *lpeobject_repr; LivePathEffectObject *lpeobject; diff --git a/src/live_effects/lpeobject.h b/src/live_effects/lpeobject.h index 9700024fe..2e62707e3 100644 --- a/src/live_effects/lpeobject.h +++ b/src/live_effects/lpeobject.h @@ -47,9 +47,9 @@ protected: virtual void build(SPDocument* doc, Inkscape::XML::Node* repr); virtual void release(); - virtual void set(unsigned int key, const gchar* value); + virtual void set(unsigned int key, char const* value); - virtual Inkscape::XML::Node* write(Inkscape::XML::Document* doc, Inkscape::XML::Node* repr, guint flags); + virtual Inkscape::XML::Node* write(Inkscape::XML::Document* doc, Inkscape::XML::Node* repr, unsigned int flags); }; #endif diff --git a/src/main-cmdlineact.h b/src/main-cmdlineact.h index fe11357fa..c8ef64f10 100644 --- a/src/main-cmdlineact.h +++ b/src/main-cmdlineact.h @@ -15,20 +15,18 @@ * Released under GNU GPL v2.x, read the file 'COPYING' for more information */ -#include - namespace Inkscape { class ActionContext; class CmdLineAction { bool _isVerb; - gchar * _arg; + char * _arg; static std::list _list; public: - CmdLineAction (bool isVerb, gchar const * arg); + CmdLineAction (bool isVerb, char const * arg); virtual ~CmdLineAction (); void doIt (ActionContext const & context); diff --git a/src/marker.h b/src/marker.h index 9eefcdf16..b58523251 100644 --- a/src/marker.h +++ b/src/marker.h @@ -1,5 +1,5 @@ -#ifndef __SP_MARKER_H__ -#define __SP_MARKER_H__ +#ifndef SEEN_SP_MARKER_H +#define SEEN_SP_MARKER_H /* * SVG implementation @@ -12,7 +12,6 @@ * * Released under GNU GPL, read the file 'COPYING' for more information */ - /* * This is quite similar in logic to * Maybe we should merge them somehow (Lauris) @@ -26,8 +25,9 @@ struct SPMarkerView; #include <2geom/rect.h> #include <2geom/affine.h> -#include "svg/svg-length.h" + #include "enums.h" +#include "svg/svg-length.h" #include "sp-item-group.h" #include "uri-references.h" #include "viewbox.h" @@ -93,7 +93,7 @@ Inkscape::DrawingItem *sp_marker_show_instance (SPMarker *marker, Inkscape::Draw unsigned int key, unsigned int pos, Geom::Affine const &base, float linewidth); void sp_marker_hide (SPMarker *marker, unsigned int key); -const gchar *generate_marker (GSList *reprs, Geom::Rect bounds, SPDocument *document, Geom::Point center, Geom::Affine move); +const char *generate_marker (GSList *reprs, Geom::Rect bounds, SPDocument *document, Geom::Point center, Geom::Affine move); SPObject *sp_marker_fork_if_necessary(SPObject *marker); #endif diff --git a/src/message-context.h b/src/message-context.h index a92874d68..ea86c4ec0 100644 --- a/src/message-context.h +++ b/src/message-context.h @@ -14,8 +14,9 @@ #ifndef SEEN_INKSCAPE_MESSAGE_CONTEXT_H #define SEEN_INKSCAPE_MESSAGE_CONTEXT_H -#include +#include #include + #include "message.h" namespace Inkscape { @@ -48,7 +49,7 @@ public: * @param type the message type * @param message the message text */ - void set(MessageType type, gchar const *message); + void set(MessageType type, char const *message); /** @brief pushes a message on the stack using prinf-style formatting, * and replacing our old message @@ -56,7 +57,7 @@ public: * @param type the message type * @param format a printf-style formatting string */ - void setF(MessageType type, gchar const *format, ...) G_GNUC_PRINTF(3,4); + void setF(MessageType type, char const *format, ...) G_GNUC_PRINTF(3,4); /** @brief pushes a message on the stack using printf-style formatting, * and a stdarg argument list @@ -65,7 +66,7 @@ public: * @param format a printf-style formatting string * @param args printf-style arguments */ - void setVF(MessageType type, gchar const *format, va_list args); + void setVF(MessageType type, char const *format, va_list args); /** @brief pushes a message onto the stack for a brief period of time * without disturbing our "current" message @@ -73,7 +74,7 @@ public: * @param type the message type * @param message the message text */ - void flash(MessageType type, gchar const *message); + void flash(MessageType type, char const *message); /** @brief pushes a message onto the stack for a brief period of time * using printf-style formatting, without disturbing our current @@ -82,7 +83,7 @@ public: * @param type the message type * @param format a printf-style formatting string */ - void flashF(MessageType type, gchar const *format, ...) G_GNUC_PRINTF(3,4); + void flashF(MessageType type, char const *format, ...) G_GNUC_PRINTF(3,4); /** @brief pushes a message onto the stack for a brief period of time * using printf-style formatting and a stdarg argument list; @@ -92,7 +93,7 @@ public: * @param format a printf-style formatting string * @param args printf-style arguments */ - void flashVF(MessageType type, gchar const *format, va_list args); + void flashVF(MessageType type, char const *format, va_list args); /** @brief removes our current message from the stack */ void clear(); diff --git a/src/message-stack.h b/src/message-stack.h index 3b8307761..42bf4e8a7 100644 --- a/src/message-stack.h +++ b/src/message-stack.h @@ -16,11 +16,12 @@ #ifndef SEEN_INKSCAPE_MESSAGE_STACK_H #define SEEN_INKSCAPE_MESSAGE_STACK_H -#include -#include -#include -#include +#include +#include +#include // G_GNUC_PRINTF is the only thing worth having from here #include +#include + #include "gc-managed.h" #include "gc-finalized.h" #include "gc-anchored.h" @@ -61,14 +62,14 @@ public: /** @brief returns the text of the message currently at the top of * the stack */ - gchar const *currentMessage() { + char const *currentMessage() { return _messages ? _messages->message : NULL; } /** @brief connects to the "changed" signal which is emitted whenever * the topmost message on the stack changes. */ - sigc::connection connectChanged(sigc::slot slot) + sigc::connection connectChanged(sigc::slot slot) { return _changed_signal.connect(slot); } @@ -80,7 +81,7 @@ public: * * @return the id of the pushed message */ - MessageId push(MessageType type, gchar const *message); + MessageId push(MessageType type, char const *message); /** @brief pushes a message onto the stack using printf-like formatting * @@ -89,7 +90,7 @@ public: * * @return the id of the pushed message */ - MessageId pushF(MessageType type, gchar const *format, ...) G_GNUC_PRINTF(3,4); + MessageId pushF(MessageType type, char const *format, ...) G_GNUC_PRINTF(3,4); /** @brief pushes a message onto the stack using printf-like formatting, * using a stdarg argument list @@ -100,7 +101,7 @@ public: * * @return the id of the pushed message */ - MessageId pushVF(MessageType type, gchar const *format, va_list args); + MessageId pushVF(MessageType type, char const *format, va_list args); /** @brief removes a message from the stack, given its id * @@ -119,7 +120,7 @@ public: * * @return the id of the pushed message */ - MessageId flash(MessageType type, gchar const *message); + MessageId flash(MessageType type, char const *message); /** * Temporarily pushes a message onto the stack. @@ -140,7 +141,7 @@ public: * * @return the id of the pushed message */ - MessageId flashF(MessageType type, gchar const *format, ...) G_GNUC_PRINTF(3,4); + MessageId flashF(MessageType type, char const *format, ...) G_GNUC_PRINTF(3,4); /** @brief temporarily pushes a message onto the stack using * printf-like formatting, using a stdarg argument list @@ -151,7 +152,7 @@ public: * * @return the id of the pushed message */ - MessageId flashVF(MessageType type, gchar const *format, va_list args); + MessageId flashVF(MessageType type, char const *format, va_list args); private: struct Message { @@ -167,13 +168,13 @@ private: void operator=(MessageStack const &); // no assign /// pushes a message onto the stack with an optional timeout - MessageId _push(MessageType type, guint lifetime, gchar const *message); + MessageId _push(MessageType type, unsigned int lifetime, char const *message); Message *_discard(Message *m); ///< frees a message struct and returns the next such struct in the list void _emitChanged(); ///< emits the "changed" signal - static gboolean _timeout(gpointer data); ///< callback to expire flashed messages + static int _timeout(void* data); ///< callback to expire flashed messages - sigc::signal _changed_signal; + sigc::signal _changed_signal; Message *_messages; ///< the stack of messages as a linked list MessageId _next_id; ///< the next message id to assign }; diff --git a/src/number-opt-number.h b/src/number-opt-number.h index d9ab56102..f6fe584f9 100644 --- a/src/number-opt-number.h +++ b/src/number-opt-number.h @@ -13,27 +13,23 @@ * Released under GNU GPL, read the file 'COPYING' for more information */ -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - #include #include -//todo: use glib instead of stdlib -#include +#include + #include "svg/stringstream.h" class NumberOptNumber { public: - gfloat number; + float number; - gfloat optNumber; + float optNumber; - guint _set : 1; + unsigned int _set : 1; - guint optNumber_set : 1; + unsigned int optNumber_set : 1; NumberOptNumber() { @@ -44,27 +40,27 @@ public: optNumber_set = FALSE; } - gfloat getNumber() + float getNumber() { if(_set) return number; return -1; } - gfloat getOptNumber() + float getOptNumber() { if(optNumber_set) return optNumber; return -1; } - void setOptNumber(gfloat num) + void setOptNumber(float num) { optNumber_set = true; optNumber = num; } - void setNumber(gfloat num) + void setNumber(float num) { _set = true; number = num; @@ -78,7 +74,7 @@ public: return _set; } - gchar *getValueString() + char *getValueString() { Inkscape::SVGOStringStream os; @@ -96,12 +92,12 @@ public: return g_strdup(os.str().c_str()); } - void set(gchar const *str) + void set(char const *str) { if(!str) return; - gchar **values = g_strsplit(str, " ", 2); + char **values = g_strsplit(str, " ", 2); if( values[0] != NULL ) { diff --git a/src/object-edit.cpp b/src/object-edit.cpp index fe22f6c1c..14a5bd3d5 100644 --- a/src/object-edit.cpp +++ b/src/object-edit.cpp @@ -96,33 +96,33 @@ KnotHolder *createKnotHolder(SPItem *item, SPDesktop *desktop) class RectKnotHolderEntityRX : public KnotHolderEntity { public: virtual Geom::Point knot_get() const; - virtual void knot_set(Geom::Point const &p, Geom::Point const &origin, guint state); - virtual void knot_click(guint state); + virtual void knot_set(Geom::Point const &p, Geom::Point const &origin, unsigned int state); + virtual void knot_click(unsigned int state); }; /* handle for vertical rounding radius */ class RectKnotHolderEntityRY : public KnotHolderEntity { public: virtual Geom::Point knot_get() const; - virtual void knot_set(Geom::Point const &p, Geom::Point const &origin, guint state); - virtual void knot_click(guint state); + virtual void knot_set(Geom::Point const &p, Geom::Point const &origin, unsigned int state); + virtual void knot_click(unsigned int state); }; /* handle for width/height adjustment */ class RectKnotHolderEntityWH : public KnotHolderEntity { public: virtual Geom::Point knot_get() const; - virtual void knot_set(Geom::Point const &p, Geom::Point const &origin, guint state); + virtual void knot_set(Geom::Point const &p, Geom::Point const &origin, unsigned int state); protected: - void set_internal(Geom::Point const &p, Geom::Point const &origin, guint state); + void set_internal(Geom::Point const &p, Geom::Point const &origin, unsigned int state); }; /* handle for x/y adjustment */ class RectKnotHolderEntityXY : public KnotHolderEntity { public: virtual Geom::Point knot_get() const; - virtual void knot_set(Geom::Point const &p, Geom::Point const &origin, guint state); + virtual void knot_set(Geom::Point const &p, Geom::Point const &origin, unsigned int state); }; Geom::Point @@ -134,7 +134,7 @@ RectKnotHolderEntityRX::knot_get() const } void -RectKnotHolderEntityRX::knot_set(Geom::Point const &p, Geom::Point const &/*origin*/, guint state) +RectKnotHolderEntityRX::knot_set(Geom::Point const &p, Geom::Point const &/*origin*/, unsigned int state) { SPRect *rect = SP_RECT(item); @@ -159,7 +159,7 @@ RectKnotHolderEntityRX::knot_set(Geom::Point const &p, Geom::Point const &/*orig } void -RectKnotHolderEntityRX::knot_click(guint state) +RectKnotHolderEntityRX::knot_click(unsigned int state) { SPRect *rect = SP_RECT(item); @@ -183,7 +183,7 @@ RectKnotHolderEntityRY::knot_get() const } void -RectKnotHolderEntityRY::knot_set(Geom::Point const &p, Geom::Point const &/*origin*/, guint state) +RectKnotHolderEntityRY::knot_set(Geom::Point const &p, Geom::Point const &/*origin*/, unsigned int state) { SPRect *rect = SP_RECT(item); @@ -217,7 +217,7 @@ RectKnotHolderEntityRY::knot_set(Geom::Point const &p, Geom::Point const &/*orig } void -RectKnotHolderEntityRY::knot_click(guint state) +RectKnotHolderEntityRY::knot_click(unsigned int state) { SPRect *rect = SP_RECT(item); @@ -255,7 +255,7 @@ RectKnotHolderEntityWH::knot_get() const } void -RectKnotHolderEntityWH::set_internal(Geom::Point const &p, Geom::Point const &origin, guint state) +RectKnotHolderEntityWH::set_internal(Geom::Point const &p, Geom::Point const &origin, unsigned int state) { SPRect *rect = SP_RECT(item); @@ -327,7 +327,7 @@ RectKnotHolderEntityWH::set_internal(Geom::Point const &p, Geom::Point const &or } void -RectKnotHolderEntityWH::knot_set(Geom::Point const &p, Geom::Point const &origin, guint state) +RectKnotHolderEntityWH::knot_set(Geom::Point const &p, Geom::Point const &origin, unsigned int state) { set_internal(p, origin, state); update_knot(); @@ -342,7 +342,7 @@ RectKnotHolderEntityXY::knot_get() const } void -RectKnotHolderEntityXY::knot_set(Geom::Point const &p, Geom::Point const &origin, guint state) +RectKnotHolderEntityXY::knot_set(Geom::Point const &p, Geom::Point const &origin, unsigned int state) { SPRect *rect = SP_RECT(item); @@ -468,10 +468,10 @@ RectKnotHolder::RectKnotHolder(SPDesktop *desktop, SPItem *item, SPKnotHolderRel class Box3DKnotHolderEntity : public KnotHolderEntity { public: virtual Geom::Point knot_get() const = 0; - virtual void knot_set(Geom::Point const &p, Geom::Point const &origin, guint state) = 0; + virtual void knot_set(Geom::Point const &p, Geom::Point const &origin, unsigned int state) = 0; Geom::Point knot_get_generic(SPItem *item, unsigned int knot_id) const; - void knot_set_generic(SPItem *item, unsigned int knot_id, Geom::Point const &p, guint state); + void knot_set_generic(SPItem *item, unsigned int knot_id, Geom::Point const &p, unsigned int state); }; Geom::Point @@ -481,7 +481,7 @@ Box3DKnotHolderEntity::knot_get_generic(SPItem *item, unsigned int knot_id) cons } void -Box3DKnotHolderEntity::knot_set_generic(SPItem *item, unsigned int knot_id, Geom::Point const &new_pos, guint state) +Box3DKnotHolderEntity::knot_set_generic(SPItem *item, unsigned int knot_id, Geom::Point const &new_pos, unsigned int state) { Geom::Point const s = snap_knot_position(new_pos, state); @@ -504,55 +504,55 @@ Box3DKnotHolderEntity::knot_set_generic(SPItem *item, unsigned int knot_id, Geom class Box3DKnotHolderEntity0 : public Box3DKnotHolderEntity { public: virtual Geom::Point knot_get() const; - virtual void knot_set(Geom::Point const &p, Geom::Point const &origin, guint state); + virtual void knot_set(Geom::Point const &p, Geom::Point const &origin, unsigned int state); }; class Box3DKnotHolderEntity1 : public Box3DKnotHolderEntity { public: virtual Geom::Point knot_get() const; - virtual void knot_set(Geom::Point const &p, Geom::Point const &origin, guint state); + virtual void knot_set(Geom::Point const &p, Geom::Point const &origin, unsigned int state); }; class Box3DKnotHolderEntity2 : public Box3DKnotHolderEntity { public: virtual Geom::Point knot_get() const; - virtual void knot_set(Geom::Point const &p, Geom::Point const &origin, guint state); + virtual void knot_set(Geom::Point const &p, Geom::Point const &origin, unsigned int state); }; class Box3DKnotHolderEntity3 : public Box3DKnotHolderEntity { public: virtual Geom::Point knot_get() const; - virtual void knot_set(Geom::Point const &p, Geom::Point const &origin, guint state); + virtual void knot_set(Geom::Point const &p, Geom::Point const &origin, unsigned int state); }; class Box3DKnotHolderEntity4 : public Box3DKnotHolderEntity { public: virtual Geom::Point knot_get() const; - virtual void knot_set(Geom::Point const &p, Geom::Point const &origin, guint state); + virtual void knot_set(Geom::Point const &p, Geom::Point const &origin, unsigned int state); }; class Box3DKnotHolderEntity5 : public Box3DKnotHolderEntity { public: virtual Geom::Point knot_get() const; - virtual void knot_set(Geom::Point const &p, Geom::Point const &origin, guint state); + virtual void knot_set(Geom::Point const &p, Geom::Point const &origin, unsigned int state); }; class Box3DKnotHolderEntity6 : public Box3DKnotHolderEntity { public: virtual Geom::Point knot_get() const; - virtual void knot_set(Geom::Point const &p, Geom::Point const &origin, guint state); + virtual void knot_set(Geom::Point const &p, Geom::Point const &origin, unsigned int state); }; class Box3DKnotHolderEntity7 : public Box3DKnotHolderEntity { public: virtual Geom::Point knot_get() const; - virtual void knot_set(Geom::Point const &p, Geom::Point const &origin, guint state); + virtual void knot_set(Geom::Point const &p, Geom::Point const &origin, unsigned int state); }; class Box3DKnotHolderEntityCenter : public KnotHolderEntity { public: virtual Geom::Point knot_get() const; - virtual void knot_set(Geom::Point const &p, Geom::Point const &origin, guint state); + virtual void knot_set(Geom::Point const &p, Geom::Point const &origin, unsigned int state); }; Geom::Point @@ -610,55 +610,55 @@ Box3DKnotHolderEntityCenter::knot_get() const } void -Box3DKnotHolderEntity0::knot_set(Geom::Point const &new_pos, Geom::Point const &/*origin*/, guint state) +Box3DKnotHolderEntity0::knot_set(Geom::Point const &new_pos, Geom::Point const &/*origin*/, unsigned int state) { knot_set_generic(item, 0, new_pos, state); } void -Box3DKnotHolderEntity1::knot_set(Geom::Point const &new_pos, Geom::Point const &/*origin*/, guint state) +Box3DKnotHolderEntity1::knot_set(Geom::Point const &new_pos, Geom::Point const &/*origin*/, unsigned int state) { knot_set_generic(item, 1, new_pos, state); } void -Box3DKnotHolderEntity2::knot_set(Geom::Point const &new_pos, Geom::Point const &/*origin*/, guint state) +Box3DKnotHolderEntity2::knot_set(Geom::Point const &new_pos, Geom::Point const &/*origin*/, unsigned int state) { knot_set_generic(item, 2, new_pos, state); } void -Box3DKnotHolderEntity3::knot_set(Geom::Point const &new_pos, Geom::Point const &/*origin*/, guint state) +Box3DKnotHolderEntity3::knot_set(Geom::Point const &new_pos, Geom::Point const &/*origin*/, unsigned int state) { knot_set_generic(item, 3, new_pos, state); } void -Box3DKnotHolderEntity4::knot_set(Geom::Point const &new_pos, Geom::Point const &/*origin*/, guint state) +Box3DKnotHolderEntity4::knot_set(Geom::Point const &new_pos, Geom::Point const &/*origin*/, unsigned int state) { knot_set_generic(item, 4, new_pos, state); } void -Box3DKnotHolderEntity5::knot_set(Geom::Point const &new_pos, Geom::Point const &/*origin*/, guint state) +Box3DKnotHolderEntity5::knot_set(Geom::Point const &new_pos, Geom::Point const &/*origin*/, unsigned int state) { knot_set_generic(item, 5, new_pos, state); } void -Box3DKnotHolderEntity6::knot_set(Geom::Point const &new_pos, Geom::Point const &/*origin*/, guint state) +Box3DKnotHolderEntity6::knot_set(Geom::Point const &new_pos, Geom::Point const &/*origin*/, unsigned int state) { knot_set_generic(item, 6, new_pos, state); } void -Box3DKnotHolderEntity7::knot_set(Geom::Point const &new_pos, Geom::Point const &/*origin*/, guint state) +Box3DKnotHolderEntity7::knot_set(Geom::Point const &new_pos, Geom::Point const &/*origin*/, unsigned int state) { knot_set_generic(item, 7, new_pos, state); } void -Box3DKnotHolderEntityCenter::knot_set(Geom::Point const &new_pos, Geom::Point const &origin, guint state) +Box3DKnotHolderEntityCenter::knot_set(Geom::Point const &new_pos, Geom::Point const &origin, unsigned int state) { Geom::Point const s = snap_knot_position(new_pos, state); @@ -739,29 +739,29 @@ Box3DKnotHolder::Box3DKnotHolder(SPDesktop *desktop, SPItem *item, SPKnotHolderR class ArcKnotHolderEntityStart : public KnotHolderEntity { public: virtual Geom::Point knot_get() const; - virtual void knot_set(Geom::Point const &p, Geom::Point const &origin, guint state); - virtual void knot_click(guint state); + virtual void knot_set(Geom::Point const &p, Geom::Point const &origin, unsigned int state); + virtual void knot_click(unsigned int state); }; class ArcKnotHolderEntityEnd : public KnotHolderEntity { public: virtual Geom::Point knot_get() const; - virtual void knot_set(Geom::Point const &p, Geom::Point const &origin, guint state); - virtual void knot_click(guint state); + virtual void knot_set(Geom::Point const &p, Geom::Point const &origin, unsigned int state); + virtual void knot_click(unsigned int state); }; class ArcKnotHolderEntityRX : public KnotHolderEntity { public: virtual Geom::Point knot_get() const; - virtual void knot_set(Geom::Point const &p, Geom::Point const &origin, guint state); - virtual void knot_click(guint state); + virtual void knot_set(Geom::Point const &p, Geom::Point const &origin, unsigned int state); + virtual void knot_click(unsigned int state); }; class ArcKnotHolderEntityRY : public KnotHolderEntity { public: virtual Geom::Point knot_get() const; - virtual void knot_set(Geom::Point const &p, Geom::Point const &origin, guint state); - virtual void knot_click(guint state); + virtual void knot_set(Geom::Point const &p, Geom::Point const &origin, unsigned int state); + virtual void knot_click(unsigned int state); }; /* @@ -783,7 +783,7 @@ sp_genericellipse_side(SPGenericEllipse *ellipse, Geom::Point const &p) } void -ArcKnotHolderEntityStart::knot_set(Geom::Point const &p, Geom::Point const &/*origin*/, guint state) +ArcKnotHolderEntityStart::knot_set(Geom::Point const &p, Geom::Point const &/*origin*/, unsigned int state) { int snaps = Inkscape::Preferences::get()->getInt("/options/rotationsnapsperpi/value", 12); @@ -813,7 +813,7 @@ ArcKnotHolderEntityStart::knot_get() const } void -ArcKnotHolderEntityStart::knot_click(guint state) +ArcKnotHolderEntityStart::knot_click(unsigned int state) { SPGenericEllipse *ge = SP_GENERICELLIPSE(item); @@ -824,7 +824,7 @@ ArcKnotHolderEntityStart::knot_click(guint state) } void -ArcKnotHolderEntityEnd::knot_set(Geom::Point const &p, Geom::Point const &/*origin*/, guint state) +ArcKnotHolderEntityEnd::knot_set(Geom::Point const &p, Geom::Point const &/*origin*/, unsigned int state) { int snaps = Inkscape::Preferences::get()->getInt("/options/rotationsnapsperpi/value", 12); @@ -855,7 +855,7 @@ ArcKnotHolderEntityEnd::knot_get() const void -ArcKnotHolderEntityEnd::knot_click(guint state) +ArcKnotHolderEntityEnd::knot_click(unsigned int state) { SPGenericEllipse *ge = SP_GENERICELLIPSE(item); @@ -867,7 +867,7 @@ ArcKnotHolderEntityEnd::knot_click(guint state) void -ArcKnotHolderEntityRX::knot_set(Geom::Point const &p, Geom::Point const &/*origin*/, guint state) +ArcKnotHolderEntityRX::knot_set(Geom::Point const &p, Geom::Point const &/*origin*/, unsigned int state) { SPGenericEllipse *ge = SP_GENERICELLIPSE(item); @@ -891,7 +891,7 @@ ArcKnotHolderEntityRX::knot_get() const } void -ArcKnotHolderEntityRX::knot_click(guint state) +ArcKnotHolderEntityRX::knot_click(unsigned int state) { SPGenericEllipse *ge = SP_GENERICELLIPSE(item); @@ -902,7 +902,7 @@ ArcKnotHolderEntityRX::knot_click(guint state) } void -ArcKnotHolderEntityRY::knot_set(Geom::Point const &p, Geom::Point const &/*origin*/, guint state) +ArcKnotHolderEntityRY::knot_set(Geom::Point const &p, Geom::Point const &/*origin*/, unsigned int state) { SPGenericEllipse *ge = SP_GENERICELLIPSE(item); @@ -926,7 +926,7 @@ ArcKnotHolderEntityRY::knot_get() const } void -ArcKnotHolderEntityRY::knot_click(guint state) +ArcKnotHolderEntityRY::knot_click(unsigned int state) { SPGenericEllipse *ge = SP_GENERICELLIPSE(item); @@ -975,19 +975,19 @@ ArcKnotHolder::ArcKnotHolder(SPDesktop *desktop, SPItem *item, SPKnotHolderRelea class StarKnotHolderEntity1 : public KnotHolderEntity { public: virtual Geom::Point knot_get() const; - virtual void knot_set(Geom::Point const &p, Geom::Point const &origin, guint state); - virtual void knot_click(guint state); + virtual void knot_set(Geom::Point const &p, Geom::Point const &origin, unsigned int state); + virtual void knot_click(unsigned int state); }; class StarKnotHolderEntity2 : public KnotHolderEntity { public: virtual Geom::Point knot_get() const; - virtual void knot_set(Geom::Point const &p, Geom::Point const &origin, guint state); - virtual void knot_click(guint state); + virtual void knot_set(Geom::Point const &p, Geom::Point const &origin, unsigned int state); + virtual void knot_click(unsigned int state); }; void -StarKnotHolderEntity1::knot_set(Geom::Point const &p, Geom::Point const &/*origin*/, guint state) +StarKnotHolderEntity1::knot_set(Geom::Point const &p, Geom::Point const &/*origin*/, unsigned int state) { SPStar *star = SP_STAR(item); @@ -1013,7 +1013,7 @@ StarKnotHolderEntity1::knot_set(Geom::Point const &p, Geom::Point const &/*origi } void -StarKnotHolderEntity2::knot_set(Geom::Point const &p, Geom::Point const &/*origin*/, guint state) +StarKnotHolderEntity2::knot_set(Geom::Point const &p, Geom::Point const &/*origin*/, unsigned int state) { SPStar *star = SP_STAR(item); @@ -1063,7 +1063,7 @@ StarKnotHolderEntity2::knot_get() const } static void -sp_star_knot_click(SPItem *item, guint state) +sp_star_knot_click(SPItem *item, unsigned int state) { SPStar *star = SP_STAR(item); @@ -1080,13 +1080,13 @@ sp_star_knot_click(SPItem *item, guint state) } void -StarKnotHolderEntity1::knot_click(guint state) +StarKnotHolderEntity1::knot_click(unsigned int state) { sp_star_knot_click(item, state); } void -StarKnotHolderEntity2::knot_click(guint state) +StarKnotHolderEntity2::knot_click(unsigned int state) { sp_star_knot_click(item, state); } @@ -1119,14 +1119,14 @@ StarKnotHolder::StarKnotHolder(SPDesktop *desktop, SPItem *item, SPKnotHolderRel class SpiralKnotHolderEntityInner : public KnotHolderEntity { public: virtual Geom::Point knot_get() const; - virtual void knot_set(Geom::Point const &p, Geom::Point const &origin, guint state); - virtual void knot_click(guint state); + virtual void knot_set(Geom::Point const &p, Geom::Point const &origin, unsigned int state); + virtual void knot_click(unsigned int state); }; class SpiralKnotHolderEntityOuter : public KnotHolderEntity { public: virtual Geom::Point knot_get() const; - virtual void knot_set(Geom::Point const &p, Geom::Point const &origin, guint state); + virtual void knot_set(Geom::Point const &p, Geom::Point const &origin, unsigned int state); }; @@ -1137,7 +1137,7 @@ public: * [control] constrain inner arg to round per PI/4 */ void -SpiralKnotHolderEntityInner::knot_set(Geom::Point const &p, Geom::Point const &origin, guint state) +SpiralKnotHolderEntityInner::knot_set(Geom::Point const &p, Geom::Point const &origin, unsigned int state) { Inkscape::Preferences *prefs = Inkscape::Preferences::get(); int snaps = prefs->getInt("/options/rotationsnapsperpi/value", 12); @@ -1186,7 +1186,7 @@ SpiralKnotHolderEntityInner::knot_set(Geom::Point const &p, Geom::Point const &o * [control] constrain inner arg to round per PI/4 */ void -SpiralKnotHolderEntityOuter::knot_set(Geom::Point const &p, Geom::Point const &/*origin*/, guint state) +SpiralKnotHolderEntityOuter::knot_set(Geom::Point const &p, Geom::Point const &/*origin*/, unsigned int state) { Inkscape::Preferences *prefs = Inkscape::Preferences::get(); int snaps = prefs->getInt("/options/rotationsnapsperpi/value", 12); @@ -1276,7 +1276,7 @@ SpiralKnotHolderEntityOuter::knot_get() const } void -SpiralKnotHolderEntityInner::knot_click(guint state) +SpiralKnotHolderEntityInner::knot_click(unsigned int state) { SPSpiral *spiral = SP_SPIRAL(item); @@ -1314,11 +1314,11 @@ SpiralKnotHolder::SpiralKnotHolder(SPDesktop *desktop, SPItem *item, SPKnotHolde class OffsetKnotHolderEntity : public KnotHolderEntity { public: virtual Geom::Point knot_get() const; - virtual void knot_set(Geom::Point const &p, Geom::Point const &origin, guint state); + virtual void knot_set(Geom::Point const &p, Geom::Point const &origin, unsigned int state); }; void -OffsetKnotHolderEntity::knot_set(Geom::Point const &p, Geom::Point const &/*origin*/, guint /*state*/) +OffsetKnotHolderEntity::knot_set(Geom::Point const &p, Geom::Point const &/*origin*/, unsigned int /*state*/) { SPOffset *offset = SP_OFFSET(item); @@ -1357,7 +1357,7 @@ OffsetKnotHolder::OffsetKnotHolder(SPDesktop *desktop, SPItem *item, SPKnotHolde class FlowtextKnotHolderEntity : public RectKnotHolderEntityWH { public: virtual Geom::Point knot_get() const; - virtual void knot_set(Geom::Point const &p, Geom::Point const &origin, guint state); + virtual void knot_set(Geom::Point const &p, Geom::Point const &origin, unsigned int state); }; Geom::Point @@ -1369,7 +1369,7 @@ FlowtextKnotHolderEntity::knot_get() const } void -FlowtextKnotHolderEntity::knot_set(Geom::Point const &p, Geom::Point const &origin, guint state) +FlowtextKnotHolderEntity::knot_set(Geom::Point const &p, Geom::Point const &origin, unsigned int state) { set_internal(p, origin, state); } diff --git a/src/object-hierarchy.cpp b/src/object-hierarchy.cpp index f2bf177dc..f241da83d 100644 --- a/src/object-hierarchy.cpp +++ b/src/object-hierarchy.cpp @@ -9,6 +9,9 @@ * Released under GNU GPL, read the file 'COPYING' for more information */ +#include +#include + #include "sp-object.h" #include "object-hierarchy.h" @@ -32,7 +35,7 @@ void ObjectHierarchy::clear() { } void ObjectHierarchy::setTop(SPObject *object) { - g_return_if_fail(object != NULL); + if (object == NULL) { printf("Assertion object != NULL failed\n"); return; } if ( top() == object ) { return; @@ -53,8 +56,8 @@ void ObjectHierarchy::setTop(SPObject *object) { } void ObjectHierarchy::_addTop(SPObject *senior, SPObject *junior) { - g_assert(junior != NULL); - g_assert(senior != NULL); + assert(junior != NULL); + assert(senior != NULL); SPObject *object = junior->parent; do { @@ -64,7 +67,7 @@ void ObjectHierarchy::_addTop(SPObject *senior, SPObject *junior) { } void ObjectHierarchy::_addTop(SPObject *object) { - g_assert(object != NULL); + assert(object != NULL); _hierarchy.push_back(_attach(object)); _added_signal.emit(object); } @@ -82,7 +85,7 @@ void ObjectHierarchy::_trimAbove(SPObject *limit) { } void ObjectHierarchy::setBottom(SPObject *object) { - g_return_if_fail(object != NULL); + if (object == NULL) { printf("assertion object != NULL failed\n"); return; } if ( bottom() == object ) { return; @@ -125,8 +128,8 @@ void ObjectHierarchy::_trimBelow(SPObject *limit) { } void ObjectHierarchy::_addBottom(SPObject *senior, SPObject *junior) { - g_assert(junior != NULL); - g_assert(senior != NULL); + assert(junior != NULL); + assert(senior != NULL); if ( junior != senior ) { _addBottom(senior, junior->parent); @@ -135,15 +138,15 @@ void ObjectHierarchy::_addBottom(SPObject *senior, SPObject *junior) { } void ObjectHierarchy::_addBottom(SPObject *object) { - g_assert(object != NULL); + assert(object != NULL); _hierarchy.push_front(_attach(object)); _added_signal.emit(object); } void ObjectHierarchy::_trim_for_release(SPObject *object) { this->_trimBelow(object); - g_assert(!this->_hierarchy.empty()); - g_assert(this->_hierarchy.front().object == object); + assert(!this->_hierarchy.empty()); + assert(this->_hierarchy.front().object == object); sp_object_ref(object, NULL); this->_detach(this->_hierarchy.front()); diff --git a/src/object-hierarchy.h b/src/object-hierarchy.h index 0343d850e..16004c81a 100644 --- a/src/object-hierarchy.h +++ b/src/object-hierarchy.h @@ -10,12 +10,11 @@ #ifndef SEEN_INKSCAPE_OBJECT_HIERARCHY_H #define SEEN_INKSCAPE_OBJECT_HIERARCHY_H +#include #include #include -#include #include #include -#include class SPObject; diff --git a/src/path-chemistry.h b/src/path-chemistry.h index efc687b44..a2150440c 100644 --- a/src/path-chemistry.h +++ b/src/path-chemistry.h @@ -13,8 +13,6 @@ * Released under GNU GPL, read the file 'COPYING' for more information */ -#include - class SPDesktop; class SPItem; @@ -25,6 +23,9 @@ class Node; } // namespace XML } // namespace Inkscape +typedef unsigned int guint32; +typedef struct _GSList GSList; + void sp_selected_path_combine (SPDesktop *desktop); void sp_selected_path_break_apart (SPDesktop *desktop); // interactive=true only has an effect if desktop != NULL, i.e. if a GUI is available diff --git a/src/path-prefix.h b/src/path-prefix.h index be57ae354..6ef0ccbe9 100644 --- a/src/path-prefix.h +++ b/src/path-prefix.h @@ -10,15 +10,15 @@ * define'd directories, and instead should use only the paths defined here. * */ -#ifndef _PATH_PREFIX_H_ -#define _PATH_PREFIX_H_ +#ifndef SEEN_PATH_PREFIX_H +#define SEEN_PATH_PREFIX_H #include "require-config.h" // INKSCAPE_DATADIR #include "prefix.h" -#ifdef __cplusplus -extern "C" { -#endif /* __cplusplus */ +//#ifdef __cplusplus +//extern "C" { +//#endif /* __cplusplus */ #ifdef ENABLE_BINRELOC # define INKSCAPE_APPICONDIR BR_DATADIR( "/pixmaps" ) @@ -112,8 +112,8 @@ extern "C" { # endif #endif -#ifdef __cplusplus -} -#endif /* __cplusplus */ +//#ifdef __cplusplus +//} +//#endif /* __cplusplus */ #endif /* _PATH_PREFIX_H_ */ diff --git a/src/persp3d-reference.h b/src/persp3d-reference.h index fa9eca5c9..cce497d94 100644 --- a/src/persp3d-reference.h +++ b/src/persp3d-reference.h @@ -10,9 +10,10 @@ * Released under GNU GPL, read the file 'COPYING' for more information. */ -#include "uri-references.h" -#include +#include #include + +#include "uri-references.h" #include "persp3d.h" class SPObject; @@ -35,7 +36,7 @@ public: SPObject *owner; // concerning the Persp3D (we only use SPBox3D) that is refered to: - gchar *persp_href; + char *persp_href; Inkscape::XML::Node *persp_repr; Persp3D *persp; diff --git a/src/persp3d.h b/src/persp3d.h index bd3777a19..be5680bcb 100644 --- a/src/persp3d.h +++ b/src/persp3d.h @@ -1,5 +1,5 @@ -#ifndef __PERSP3D_H__ -#define __PERSP3D_H__ +#ifndef SEEN_PERSP3D_H +#define SEEN_PERSP3D_H /* * Implementation of 3D perspectives as SPObjects @@ -16,8 +16,9 @@ #define SP_IS_PERSP3D(obj) (dynamic_cast((SPObject*)obj) != NULL) #include -#include #include +#include + #include "transf_mat_3x4.h" #include "document.h" #include "inkscape.h" // for SP_ACTIVE_DOCUMENT @@ -64,11 +65,11 @@ protected: virtual void build(SPDocument* doc, Inkscape::XML::Node* repr); virtual void release(); - virtual void set(unsigned int key, const gchar* value); + virtual void set(unsigned int key, char const* value); virtual void update(SPCtx* ctx, unsigned int flags); - virtual Inkscape::XML::Node* write(Inkscape::XML::Document* doc, Inkscape::XML::Node* repr, guint flags); + virtual Inkscape::XML::Node* write(Inkscape::XML::Document* doc, Inkscape::XML::Node* repr, unsigned int flags); }; @@ -100,7 +101,7 @@ void persp3d_update_z_orders (Persp3D *persp); inline unsigned int persp3d_num_boxes (Persp3D *persp) { return persp->perspective_impl->boxes.size(); } std::list persp3d_list_of_boxes(Persp3D *persp); -bool persp3d_perspectives_coincide(const Persp3D *lhs, const Persp3D *rhs); +bool persp3d_perspectives_coincide(Persp3D const *lhs, Persp3D const *rhs); void persp3d_absorb(Persp3D *persp1, Persp3D *persp2); Persp3D * persp3d_create_xml_element (SPDocument *document, Persp3DImpl *dup = NULL); @@ -112,7 +113,7 @@ void persp3d_print_debugging_info (Persp3D *persp); void persp3d_print_debugging_info_all(SPDocument *doc); void persp3d_print_all_selected(); -void print_current_persp3d(gchar *func_name, Persp3D *persp); +void print_current_persp3d(char *func_name, Persp3D *persp); #endif /* __PERSP3D_H__ */ diff --git a/src/perspective-line.h b/src/perspective-line.h index 57abaae9c..64f7d03bd 100644 --- a/src/perspective-line.h +++ b/src/perspective-line.h @@ -13,7 +13,6 @@ #define SEEN_PERSPECTIVE_LINE_H #include "line-geometry.h" -#include class SPDesktop; diff --git a/src/preferences-skeleton.h b/src/preferences-skeleton.h index 734e8a582..66a3e47d4 100644 --- a/src/preferences-skeleton.h +++ b/src/preferences-skeleton.h @@ -1,8 +1,9 @@ #ifndef SEEN_PREFERENCES_SKELETON_H #define SEEN_PREFERENCES_SKELETON_H -#include +#include "inkscape-version.h" +// FIXME why is this here? #ifdef N_ #undef N_ #endif diff --git a/src/preferences.h b/src/preferences.h index d5429815e..d5ae40e56 100644 --- a/src/preferences.h +++ b/src/preferences.h @@ -13,14 +13,16 @@ #ifndef INKSCAPE_PREFSTORE_H #define INKSCAPE_PREFSTORE_H -#include -#include #include #include #include +#include +#include + #include "xml/repr.h" class SPCSSAttr; +typedef unsigned int guint32; namespace Inkscape { diff --git a/src/print.h b/src/print.h index bbf95b833..ab2bcc0a7 100644 --- a/src/print.h +++ b/src/print.h @@ -41,18 +41,18 @@ unsigned int sp_print_stroke(SPPrintContext *ctx, Geom::PathVector const &pathv, Geom::OptRect const &pbox, Geom::OptRect const &dbox, Geom::OptRect const &bbox); unsigned int sp_print_image_R8G8B8A8_N(SPPrintContext *ctx, - guchar *px, unsigned int w, unsigned int h, unsigned int rs, + unsigned char *px, unsigned int w, unsigned int h, unsigned int rs, Geom::Affine const &transform, SPStyle const *style); unsigned int sp_print_text(SPPrintContext *ctx, char const *text, Geom::Point p, SPStyle const *style); -void sp_print_get_param(SPPrintContext *ctx, gchar *name, bool *value); +void sp_print_get_param(SPPrintContext *ctx, char *name, bool *value); /* UI */ void sp_print_document(Gtk::Window& parentWindow, SPDocument *doc); -void sp_print_document_to_file(SPDocument *doc, gchar const *filename); +void sp_print_document_to_file(SPDocument *doc, char const *filename); #endif /* !PRINT_H_INKSCAPE */ diff --git a/src/profile-manager.h b/src/profile-manager.h index be9446c17..54cd4a1da 100644 --- a/src/profile-manager.h +++ b/src/profile-manager.h @@ -9,9 +9,10 @@ #ifndef SEEN_INKSCAPE_PROFILE_MANAGER_H #define SEEN_INKSCAPE_PROFILE_MANAGER_H +#include + #include "document-subset.h" #include "gc-finalized.h" -#include class SPDocument; @@ -26,7 +27,7 @@ public: ProfileManager(SPDocument *document); ~ProfileManager(); - ColorProfile* find(gchar const* name); + ColorProfile* find(char const* name); private: ProfileManager(ProfileManager const &); // no copy diff --git a/src/proj_pt.h b/src/proj_pt.h index 28ec0aca3..1ee4b7f14 100644 --- a/src/proj_pt.h +++ b/src/proj_pt.h @@ -13,7 +13,7 @@ #define SEEN_PROJ_PT_H #include <2geom/point.h> -#include +#include namespace Proj { @@ -25,7 +25,7 @@ public: Pt2 () { pt[0] = 0; pt[1] = 0; pt[2] = 1.0; } // we default to (0 : 0 : 1) Pt2 (double x, double y, double w) { pt[0] = x; pt[1] = y; pt[2] = w; } Pt2 (Geom::Point const &point) { pt[0] = point[Geom::X]; pt[1] = point[Geom::Y]; pt[2] = 1; } - Pt2 (const gchar *coord_str); + Pt2 (const char *coord_str); inline double operator[] (unsigned int index) const { if (index > 2) { return Geom::infinity(); } @@ -81,8 +81,8 @@ public: void normalize(); Geom::Point affine(); inline bool is_finite() { return pt[2] != 0; } // FIXME: Should we allow for some tolerance? - gchar *coord_string(); - inline void print(gchar const *s) const { g_print ("%s(%8.2f : %8.2f : %8.2f)\n", s, pt[0], pt[1], pt[2]); } + char *coord_string(); + inline void print(char const *s) const { printf ("%s(%8.2f : %8.2f : %8.2f)\n", s, pt[0], pt[1], pt[2]); } private: double pt[3]; @@ -93,7 +93,7 @@ class Pt3 { public: Pt3 () { pt[0] = 0; pt[1] = 0; pt[2] = 0; pt[3] = 1.0; } // we default to (0 : 0 : 0 : 1) Pt3 (double x, double y, double z, double w) { pt[0] = x; pt[1] = y; pt[2] = z; pt[3] = w; } - Pt3 (const gchar *coord_str); + Pt3 (const char *coord_str); inline bool operator== (Pt3 &rhs) { normalize(); @@ -146,9 +146,9 @@ public: } void normalize(); inline bool is_finite() { return pt[3] != 0; } // FIXME: Should we allow for some tolerance? - gchar *coord_string(); - inline void print(gchar const *s) const { - g_print ("%s(%8.2f : %8.2f : %8.2f : %8.2f)\n", s, pt[0], pt[1], pt[2], pt[3]); + char *coord_string(); + inline void print(char const *s) const { + printf ("%s(%8.2f : %8.2f : %8.2f : %8.2f)\n", s, pt[0], pt[1], pt[2], pt[3]); } private: diff --git a/src/rdf.h b/src/rdf.h index 3dde1cb48..c3ced1583 100644 --- a/src/rdf.h +++ b/src/rdf.h @@ -11,7 +11,6 @@ #ifndef SEEN_RDF_H #define SEEN_RDF_H -#include #include #include "document.h" @@ -22,18 +21,18 @@ * \brief Holds license name/resource doubles for rdf_license_t entries */ struct rdf_double_t { - gchar const *name; - gchar const *resource; + char const *name; + char const *resource; }; /** * \brief Holds license name and RDF information */ struct rdf_license_t { - gchar const *name; /* localized name of this license */ - gchar const *uri; /* URL for the RDF/Work/license element */ + char const *name; /* localized name of this license */ + char const *uri; /* URL for the RDF/Work/license element */ struct rdf_double_t *details; /* the license details */ -// gchar const *fragment; /* XML contents for the RDF/License tag */ +// char const *fragment; /* XML contents for the RDF/License tag */ }; extern rdf_license_t rdf_licenses []; @@ -69,10 +68,10 @@ enum RDF_Editable { */ struct rdf_work_entity_t { char const *name; /* unique name of this entity for internal reference */ - gchar const *title; /* localized title of this entity for data entry */ - gchar const *tag; /* namespace tag for the RDF/Work element */ + char const *title; /* localized title of this entity for data entry */ + char const *tag; /* namespace tag for the RDF/Work element */ RDFType datatype; /* how to extract/inject the RDF information */ - gchar const *tip; /* tool tip to explain the meaning of the entity */ + char const *tip; /* tool tip to explain the meaning of the entity */ RDF_Format format; /* in what format is this data edited? */ RDF_Editable editable;/* in what way is the data editable? */ }; @@ -83,19 +82,19 @@ extern rdf_work_entity_t rdf_work_entities []; * \brief Generic collection of RDF information for the RDF debug function */ struct rdf_t { - gchar* work_title; - gchar* work_date; - gchar* work_creator; - gchar* work_owner; - gchar* work_publisher; - gchar* work_type; - gchar* work_source; - gchar* work_subject; - gchar* work_description; + char* work_title; + char* work_date; + char* work_creator; + char* work_owner; + char* work_publisher; + char* work_type; + char* work_source; + char* work_subject; + char* work_description; struct rdf_license_t* license; }; -struct rdf_work_entity_t * rdf_find_entity(gchar const * name); +struct rdf_work_entity_t * rdf_find_entity(char const * name); /** * \brief Retrieves a known RDF/Work entity's contents from the document XML by name @@ -114,7 +113,7 @@ const gchar * rdf_get_work_entity(SPDocument const * doc, */ unsigned int rdf_set_work_entity(SPDocument * doc, struct rdf_work_entity_t * entity, - const gchar * text); + const char * text); /** * \brief Attempts to match and retrieve a known RDF/License from the document XML diff --git a/src/removeoverlap.h b/src/removeoverlap.h index 1ba41572a..7109c9513 100644 --- a/src/removeoverlap.h +++ b/src/removeoverlap.h @@ -13,7 +13,7 @@ #ifndef SEEN_REMOVEOVERLAP_H #define SEEN_REMOVEOVERLAP_H -#include +typedef struct _GSList GSList; void removeoverlap(GSList const *items, double xGap, double yGap); diff --git a/src/rubberband.h b/src/rubberband.h index fbebe2b08..a7bc57145 100644 --- a/src/rubberband.h +++ b/src/rubberband.h @@ -10,17 +10,17 @@ * Released under GNU GPL, read the file 'COPYING' for more information */ -#include -#include #include <2geom/point.h> #include <2geom/rect.h> +#include +#include /* fixme: do multidocument safe */ -class CtrlRect; +class CtrlRect; +class SPCurve; +class SPDesktop; struct SPCanvasItem; -class SPCurve; -class SPDesktop; enum { RUBBERBAND_MODE_RECT, diff --git a/src/selcue.h b/src/selcue.h index bcac7315f..d9b16b0f5 100644 --- a/src/selcue.h +++ b/src/selcue.h @@ -1,5 +1,5 @@ -#ifndef __SP_SELCUE_H__ -#define __SP_SELCUE_H__ +#ifndef SEEN_SP_SELCUE_H +#define SEEN_SP_SELCUE_H /* * Helper object for showing selected items @@ -13,8 +13,8 @@ * Released under GNU GPL, read the file 'COPYING' for more information */ +#include #include -#include #include class SPDesktop; @@ -52,7 +52,7 @@ private: void _updateItemBboxes(); void _updateItemBboxes(Inkscape::Preferences *prefs); - void _updateItemBboxes(gint mode, int prefs_bbox); + void _updateItemBboxes(int mode, int prefs_bbox); void _newItemBboxes(); void _newTextBaselines(); void _boundingBoxPrefsChanged(int prefs_bbox); diff --git a/src/selection-chemistry.h b/src/selection-chemistry.h index 01c35d65a..016a54b5c 100644 --- a/src/selection-chemistry.h +++ b/src/selection-chemistry.h @@ -17,21 +17,21 @@ * Released under GNU GPL, read the file 'COPYING' for more information */ +#include <2geom/forward.h> #include "sp-item.h" -#include "2geom/forward.h" -namespace Inkscape { class Selection; } +class SPCSSAttr; +class SPDesktop; +typedef struct _GSList GSList; namespace Inkscape { + +class Selection; + namespace LivePathEffect { class PathParam; } -} -class SPCSSAttr; -class SPDesktop; - -namespace Inkscape { class SelectionHelper { public: static void selectAll(SPDesktop *desktop); @@ -108,21 +108,21 @@ void sp_selection_apply_affine(Inkscape::Selection *selection, Geom::Affine cons void sp_selection_remove_transform (SPDesktop *desktop); void sp_selection_scale_absolute (Inkscape::Selection *selection, double x0, double x1, double y0, double y1); void sp_selection_scale_relative(Inkscape::Selection *selection, Geom::Point const &align, Geom::Scale const &scale); -void sp_selection_rotate_relative (Inkscape::Selection *selection, Geom::Point const ¢er, gdouble angle); +void sp_selection_rotate_relative (Inkscape::Selection *selection, Geom::Point const ¢er, double angle); void sp_selection_skew_relative (Inkscape::Selection *selection, Geom::Point const &align, double dx, double dy); void sp_selection_move_relative (Inkscape::Selection *selection, Geom::Point const &move, bool compensate = true); void sp_selection_move_relative (Inkscape::Selection *selection, double dx, double dy); void sp_selection_rotate_90 (SPDesktop *desktop, bool ccw); -void sp_selection_rotate (Inkscape::Selection *selection, gdouble angle); -void sp_selection_rotate_screen (Inkscape::Selection *selection, gdouble angle); +void sp_selection_rotate (Inkscape::Selection *selection, double angle); +void sp_selection_rotate_screen (Inkscape::Selection *selection, double angle); -void sp_selection_scale (Inkscape::Selection *selection, gdouble grow); -void sp_selection_scale_screen (Inkscape::Selection *selection, gdouble grow_pixels); -void sp_selection_scale_times (Inkscape::Selection *selection, gdouble times); +void sp_selection_scale (Inkscape::Selection *selection, double grow); +void sp_selection_scale_screen (Inkscape::Selection *selection, double grow_pixels); +void sp_selection_scale_times (Inkscape::Selection *selection, double times); -void sp_selection_move (Inkscape::Selection *selection, gdouble dx, gdouble dy); -void sp_selection_move_screen (Inkscape::Selection *selection, gdouble dx, gdouble dy); +void sp_selection_move (Inkscape::Selection *selection, double dx, double dy); +void sp_selection_move_screen (Inkscape::Selection *selection, double dx, double dy); void sp_selection_item_next (SPDesktop *desktop); void sp_selection_item_prev (SPDesktop *desktop); diff --git a/src/selection-describer.h b/src/selection-describer.h index b4174edd8..5514ce4b1 100644 --- a/src/selection-describer.h +++ b/src/selection-describer.h @@ -16,11 +16,10 @@ #include #include "message-context.h" -namespace Inkscape { class Selection; } - namespace Inkscape { class MessageStack; +class Selection; class SelectionDescriber : public sigc::trackable { public: @@ -29,7 +28,7 @@ public: private: void _updateMessageFromSelection(Inkscape::Selection *selection); - void _selectionModified(Inkscape::Selection *selection, guint /*flags*/); + void _selectionModified(Inkscape::Selection *selection, unsigned int /*flags*/); sigc::connection *_selection_changed_connection; sigc::connection *_selection_modified_connection; @@ -43,6 +42,7 @@ private: } #endif + /* Local Variables: mode:c++ diff --git a/src/selection.h b/src/selection.h index ba38bec08..5964b20e8 100644 --- a/src/selection.h +++ b/src/selection.h @@ -30,6 +30,7 @@ class SPDesktop; class SPItem; class SPBox3D; class Persp3D; +typedef struct _GSList GSList; namespace Inkscape { class LayerModel; @@ -256,10 +257,10 @@ public: std::list const box3DList(Persp3D *persp = NULL); /** Returns the number of layers in which there are selected objects. */ - guint numberOfLayers(); + unsigned int numberOfLayers(); /** Returns the number of parents to which the selected objects belong. */ - guint numberOfParents(); + unsigned int numberOfParents(); /** Returns the bounding rectangle of the selection. */ Geom::OptRect bounds(SPItem::BBoxType type) const; @@ -317,11 +318,11 @@ public: * @return the resulting connection * */ - sigc::connection connectModified(sigc::slot const &slot) + sigc::connection connectModified(sigc::slot const &slot) { return _modified_signal.connect(slot); } - sigc::connection connectModifiedFirst(sigc::slot const &slot) + sigc::connection connectModifiedFirst(sigc::slot const &slot) { return _modified_signal.slots().insert(_modified_signal.slots().begin(), slot); } @@ -333,12 +334,12 @@ private: void operator=(Selection const &); /** Issues modification notification signals. */ - static gboolean _emit_modified(Selection *selection); + static int _emit_modified(Selection *selection); /** Schedules an item modification signal to be sent. */ - void _schedule_modified(SPObject *obj, guint flags); + void _schedule_modified(SPObject *obj, unsigned int flags); /** Issues modified selection signal. */ - void _emitModified(guint flags); + void _emitModified(unsigned int flags); /** Issues changed selection signal. */ void _emitChanged(bool persist_selection_context = false); @@ -374,15 +375,15 @@ private: LayerModel *_layers; GC::soft_ptr _desktop; SPObject* _selection_context; - guint _flags; - guint _idle; + unsigned int _flags; + unsigned int _idle; std::map _modified_connections; std::map _release_connections; sigc::connection _context_release_connection; sigc::signal _changed_signal; - sigc::signal _modified_signal; + sigc::signal _modified_signal; }; } diff --git a/src/seltrans-handles.h b/src/seltrans-handles.h index 740729a6e..ebd5758c8 100644 --- a/src/seltrans-handles.h +++ b/src/seltrans-handles.h @@ -14,11 +14,13 @@ #include <2geom/forward.h> #include + #include "enums.h" -namespace Inkscape -{ - class SelTrans; +typedef unsigned int guint32; + +namespace Inkscape { + class SelTrans; } guint32 const DEF_COLOR[] = { 0xff, 0xff6600, 0xff6600, 0xff, 0xff, 0xff }; @@ -34,7 +36,7 @@ enum SPSelTransType { struct SPSelTransTypeInfo { guint32 const *color; - gchar const *tip; + char const *tip; }; // One per handle type in order extern SPSelTransTypeInfo const handtypes[5]; @@ -45,7 +47,7 @@ struct SPSelTransHandle { SPSelTransType type; SPAnchorType anchor; GdkCursorType cursor; - guint control; + unsigned int control; gdouble x, y; }; // These are 4 * each handle type + 1 for center @@ -64,5 +66,3 @@ extern SPSelTransHandle const hands[17]; End: */ // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 : - - diff --git a/src/seltrans.h b/src/seltrans.h index 44268ed69..d5db1542d 100644 --- a/src/seltrans.h +++ b/src/seltrans.h @@ -15,32 +15,33 @@ * Released under GNU GPL, read the file 'COPYING' for more information */ -#include -#include #include <2geom/point.h> #include <2geom/affine.h> #include <2geom/rect.h> +#include +#include +#include + #include "knot.h" -#include "selcue.h" #include "message-context.h" -#include -#include "sp-item.h" #include "seltrans-handles.h" +#include "selcue.h" +#include "sp-item.h" + class SPKnot; class SPDesktop; struct SPCanvasItem; struct SPCtrlLine; struct SPSelTransHandle; +typedef struct _GSList GSList; -namespace Inkscape -{ +namespace Inkscape { Geom::Scale calcScaleFactors(Geom::Point const &initial_point, Geom::Point const &new_point, Geom::Point const &origin, bool const skew = false); -namespace XML -{ - class Node; +namespace XML { + class Node; } class SelTrans @@ -56,26 +57,26 @@ public: void increaseState(); void resetState(); void setCenter(Geom::Point const &p); - void grab(Geom::Point const &p, gdouble x, gdouble y, bool show_handles, bool translating); + void grab(Geom::Point const &p, double x, double y, bool show_handles, bool translating); void transform(Geom::Affine const &rel_affine, Geom::Point const &norm); void ungrab(); void stamp(); - void moveTo(Geom::Point const &xy, guint state); - void stretch(SPSelTransHandle const &handle, Geom::Point &pt, guint state); - void scale(Geom::Point &pt, guint state); - void skew(SPSelTransHandle const &handle, Geom::Point &pt, guint state); - void rotate(Geom::Point &pt, guint state); - gboolean request(SPSelTransHandle const &handle, Geom::Point &pt, guint state); - gboolean scaleRequest(Geom::Point &pt, guint state); - gboolean stretchRequest(SPSelTransHandle const &handle, Geom::Point &pt, guint state); - gboolean skewRequest(SPSelTransHandle const &handle, Geom::Point &pt, guint state); - gboolean rotateRequest(Geom::Point &pt, guint state); - gboolean centerRequest(Geom::Point &pt, guint state); - - gboolean handleRequest(SPKnot *knot, Geom::Point *position, guint state, SPSelTransHandle const &handle); - void handleGrab(SPKnot *knot, guint state, SPSelTransHandle const &handle); - void handleClick(SPKnot *knot, guint state, SPSelTransHandle const &handle); - void handleNewEvent(SPKnot *knot, Geom::Point *position, guint state, SPSelTransHandle const &handle); + void moveTo(Geom::Point const &xy, unsigned int state); + void stretch(SPSelTransHandle const &handle, Geom::Point &pt, unsigned int state); + void scale(Geom::Point &pt, unsigned int state); + void skew(SPSelTransHandle const &handle, Geom::Point &pt, unsigned int state); + void rotate(Geom::Point &pt, unsigned int state); + int request(SPSelTransHandle const &handle, Geom::Point &pt, unsigned int state); + int scaleRequest(Geom::Point &pt, unsigned int state); + int stretchRequest(SPSelTransHandle const &handle, Geom::Point &pt, unsigned int state); + int skewRequest(SPSelTransHandle const &handle, Geom::Point &pt, unsigned int state); + int rotateRequest(Geom::Point &pt, unsigned int state); + int centerRequest(Geom::Point &pt, unsigned int state); + + int handleRequest(SPKnot *knot, Geom::Point *position, unsigned int state, SPSelTransHandle const &handle); + void handleGrab(SPKnot *knot, unsigned int state, SPSelTransHandle const &handle); + void handleClick(SPKnot *knot, unsigned int state, SPSelTransHandle const &handle); + void handleNewEvent(SPKnot *knot, Geom::Point *position, unsigned int state, SPSelTransHandle const &handle); enum Show { @@ -115,7 +116,7 @@ private: void _updateHandles(); void _updateVolatileState(); void _selChanged(Inkscape::Selection *selection); - void _selModified(Inkscape::Selection *selection, guint flags); + void _selModified(Inkscape::Selection *selection, unsigned int flags); void _boundingBoxPrefsChanged(int prefs_bbox); void _makeHandles(); void _showHandles(SPSelTransType type); @@ -156,7 +157,7 @@ private: Geom::OptRect _bbox; Geom::OptRect _visual_bbox; Geom::OptRect _geometric_bbox; - gdouble _strokewidth; + double _strokewidth; Geom::Affine _current_relative_affine; Geom::Affine _absolute_affine; @@ -173,8 +174,8 @@ private: Geom::Point _origin_for_specpoints; Geom::Point _origin_for_bboxpoints; - gdouble _handle_x; - gdouble _handle_y; + double _handle_x; + double _handle_y; boost::optional _center; bool _center_is_set; ///< we've already set _center, no need to reread it from items @@ -184,8 +185,8 @@ private: SPCanvasItem *_norm; SPCanvasItem *_grip; SPCtrlLine *_l[4]; - guint _sel_changed_id; - guint _sel_modified_id; + unsigned int _sel_changed_id; + unsigned int _sel_modified_id; GSList *_stamp_cache; Geom::Point _origin; ///< position of origin for transforms diff --git a/src/shape-editor.h b/src/shape-editor.h index df0dbfa3a..d2611b111 100644 --- a/src/shape-editor.h +++ b/src/shape-editor.h @@ -12,8 +12,6 @@ * */ -#include - namespace Inkscape { namespace XML { class Node; } } class KnotHolder; @@ -37,10 +35,10 @@ public: bool knot_mouseover() const; - static void blockSetItem(bool b) { _blockSetItem = b; } // kludge? + static void blockSetItem(bool b) { _blockSetItem = b; } // kludge - static void event_attr_changed(Inkscape::XML::Node * /*repr*/, gchar const *name, gchar const * /*old_value*/, - gchar const * /*new_value*/, bool /*is_interactive*/, void *data); + static void event_attr_changed(Inkscape::XML::Node * /*repr*/, char const *name, char const * /*old_value*/, + char const * /*new_value*/, bool /*is_interactive*/, void *data); private: bool has_knotholder(); void reset_item (bool keep_knotholder = true); diff --git a/src/shortcuts.h b/src/shortcuts.h index 406768f97..f24a82603 100644 --- a/src/shortcuts.h +++ b/src/shortcuts.h @@ -1,5 +1,5 @@ -#ifndef __SP_SHORTCUTS_H__ -#define __SP_SHORTCUTS_H__ +#ifndef SEEN_SP_SHORTCUTS_H +#define SEEN_SP_SHORTCUTS_H /* * Keyboard shortcut processing @@ -16,9 +16,6 @@ typedef struct _GtkAccelGroup GtkAccelGroup; typedef struct _GtkWidget GtkWidget; -struct _GtkAccelGroup; -struct _GtkWidget; - namespace Inkscape { class Verb; namespace UI { @@ -42,14 +39,14 @@ bool sp_shortcut_invoke (unsigned int shortcut, Inkscape::UI::View::View *view); void sp_shortcut_init(); Inkscape::Verb * sp_shortcut_get_verb (unsigned int shortcut); unsigned int sp_shortcut_get_primary (Inkscape::Verb * verb); // Returns GDK_VoidSymbol if no shortcut is found. -gchar* sp_shortcut_get_label (unsigned int shortcut); // Returns the human readable form of the shortcut (or NULL), for example Shift+Ctrl+F. Free the returned string with g_free. +char* sp_shortcut_get_label (unsigned int shortcut); // Returns the human readable form of the shortcut (or NULL), for example Shift+Ctrl+F. Free the returned string with g_free. void sp_shortcut_set(unsigned int const shortcut, Inkscape::Verb *const verb, bool const is_primary, bool const is_user_set=false); void sp_shortcut_unset(unsigned int const shortcut); void sp_shortcut_add_to_file(char const *action, unsigned int const shortcut); void sp_shortcut_delete_from_file(char const *action, unsigned int const shortcut); void sp_shortcuts_delete_all_from_file(); Glib::ustring sp_shortcut_to_label(unsigned int const shortcut); -unsigned int sp_gdkmodifier_to_shortcut(guint accel_key, Gdk::ModifierType gdkmodifier, guint hardware_keycode); +unsigned int sp_gdkmodifier_to_shortcut(unsigned int accel_key, Gdk::ModifierType gdkmodifier, unsigned int hardware_keycode); void sp_shortcut_get_file_names(std::vector *names, std::vector *paths); bool sp_shortcut_is_user_set(Inkscape::Verb *verb); void sp_shortcut_file_export(); diff --git a/src/snap-candidate.h b/src/snap-candidate.h index 8bb7cb52f..54e33e1a8 100644 --- a/src/snap-candidate.h +++ b/src/snap-candidate.h @@ -14,7 +14,10 @@ * Released under GNU GPL, read the file 'COPYING' for more information */ -//#include "snapped-point.h" +#include <2geom/point.h> +#include <2geom/rect.h> +#include + #include "snap-enums.h" class SPItem; // forward declaration diff --git a/src/snap-preferences.h b/src/snap-preferences.h index a7a2e2926..7bdeea52e 100644 --- a/src/snap-preferences.h +++ b/src/snap-preferences.h @@ -49,13 +49,13 @@ public: void setSnapPerp(bool enabled) {_snap_perp = enabled;} void setSnapTang(bool enabled) {_snap_tang = enabled;} - gdouble getGridTolerance() const {return _grid_tolerance;} - gdouble getGuideTolerance() const {return _guide_tolerance;} - gdouble getObjectTolerance() const {return _object_tolerance;} + double getGridTolerance() const {return _grid_tolerance;} + double getGuideTolerance() const {return _guide_tolerance;} + double getObjectTolerance() const {return _object_tolerance;} - void setGridTolerance(gdouble val) {_grid_tolerance = val;} - void setGuideTolerance(gdouble val) {_guide_tolerance = val;} - void setObjectTolerance(gdouble val) {_object_tolerance = val;} + void setGridTolerance(double val) {_grid_tolerance = val;} + void setGuideTolerance(double val) {_guide_tolerance = val;} + void setObjectTolerance(double val) {_object_tolerance = val;} private: @@ -91,9 +91,9 @@ private: bool _snap_perp; bool _snap_tang; - gdouble _grid_tolerance; - gdouble _guide_tolerance; - gdouble _object_tolerance; + double _grid_tolerance; + double _guide_tolerance; + double _object_tolerance; }; } diff --git a/src/snap.h b/src/snap.h index 67af20063..20b2b246f 100644 --- a/src/snap.h +++ b/src/snap.h @@ -32,6 +32,7 @@ enum SPGuideDragType { // used both here and in desktop-events.cpp class SPGuide; class SPNamedView; +typedef struct _GSList GSList; /** * Class to coordinate snapping operations. diff --git a/src/snapped-curve.h b/src/snapped-curve.h index 6bb8bfeca..0e3a1c747 100644 --- a/src/snapped-curve.h +++ b/src/snapped-curve.h @@ -11,14 +11,14 @@ * Released under GNU GPL, read the file 'COPYING' for more information. */ +#include <2geom/forward.h> #include #include + #include "snapped-point.h" #include "snapped-line.h" -#include <2geom/forward.h> -namespace Inkscape -{ +namespace Inkscape { /// Class describing the result of an attempt to snap to a curve. class SnappedCurve : public SnappedPoint diff --git a/src/snapped-point.h b/src/snapped-point.h index bf440c450..9d77ab162 100644 --- a/src/snapped-point.h +++ b/src/snapped-point.h @@ -12,10 +12,11 @@ * Released under GNU GPL, read the file 'COPYING' for more information. */ -#include -#include #include <2geom/geom.h> -#include +#include +#include + +#include "snap-candidate.h" namespace Inkscape { diff --git a/src/snapper.h b/src/snapper.h index c609239cf..9616d0954 100644 --- a/src/snapper.h +++ b/src/snapper.h @@ -12,15 +12,14 @@ * Released under GNU GPL, read the file 'COPYING' for more information. */ -#include -#include #include -#include // for g_assert +#include +#include +#include "snap-candidate.h" #include "snapped-point.h" #include "snapped-line.h" #include "snapped-curve.h" -#include "snap-candidate.h" struct IntermSnapResults { std::list points; @@ -86,7 +85,7 @@ public: bool hasPoint() const {return _type != DIRECTION && _type != UNDEFINED;} Geom::Point getPoint() const { - g_assert(_type != DIRECTION && _type != UNDEFINED); + assert(_type != DIRECTION && _type != UNDEFINED); return _point; } @@ -95,7 +94,7 @@ public: } Geom::Coord getRadius() const { - g_assert(_type == CIRCLE); + assert(_type == CIRCLE); return _radius; } @@ -121,7 +120,7 @@ public: Geom::Point const p2_on_cl = p1_on_cl + _direction; return Geom::projection(p, Geom::Line(p1_on_cl, p2_on_cl)); } else { - g_warning("Bug: trying to find the projection onto an undefined constraint"); + printf("WARNING: Bug: trying to find the projection onto an undefined constraint"); return Geom::Point(); } } diff --git a/src/sp-anchor.h b/src/sp-anchor.h index 778640032..d17718344 100644 --- a/src/sp-anchor.h +++ b/src/sp-anchor.h @@ -1,5 +1,5 @@ -#ifndef __SP_ANCHOR_H__ -#define __SP_ANCHOR_H__ +#ifndef SEEN_SP_ANCHOR_H +#define SEEN_SP_ANCHOR_H /* * SVG element implementation @@ -23,16 +23,16 @@ public: SPAnchor(); virtual ~SPAnchor(); - gchar *href; + char *href; virtual void build(SPDocument *document, Inkscape::XML::Node *repr); virtual void release(); - virtual void set(unsigned int key, gchar const* value); - virtual Inkscape::XML::Node* write(Inkscape::XML::Document *xml_doc, Inkscape::XML::Node *repr, guint flags); + virtual void set(unsigned int key, char const* value); + virtual Inkscape::XML::Node* write(Inkscape::XML::Document *xml_doc, Inkscape::XML::Node *repr, unsigned int flags); virtual const char* displayName() const; - virtual gchar* description() const; - virtual gint event(SPEvent *event); + virtual char* description() const; + virtual int event(SPEvent *event); }; #endif diff --git a/src/sp-clippath.h b/src/sp-clippath.h index ba7a90a57..eb8b14174 100644 --- a/src/sp-clippath.h +++ b/src/sp-clippath.h @@ -19,6 +19,9 @@ #define SP_IS_CLIPPATH(obj) (dynamic_cast((SPObject*)obj) != NULL) struct SPClipPathView; +typedef struct _GSList GSList; + +#include #include "sp-object-group.h" #include "uri-references.h" @@ -42,8 +45,8 @@ public: unsigned int clipPathUnits : 1; SPClipPathView *display; - static const gchar *create(GSList *reprs, SPDocument *document, Geom::Affine const* applyTransform); - static GType sp_clippath_get_type(void); + static char const *create(GSList *reprs, SPDocument *document, Geom::Affine const* applyTransform); + //static GType sp_clippath_get_type(void); Inkscape::DrawingItem *show(Inkscape::Drawing &drawing, unsigned int key); void hide(unsigned int key); @@ -57,12 +60,12 @@ protected: virtual void child_added(Inkscape::XML::Node* child, Inkscape::XML::Node* ref); - virtual void set(unsigned int key, const gchar* value); + virtual void set(unsigned int key, char const* value); virtual void update(SPCtx* ctx, unsigned int flags); virtual void modified(unsigned int flags); - virtual Inkscape::XML::Node* write(Inkscape::XML::Document* doc, Inkscape::XML::Node* repr, guint flags); + virtual Inkscape::XML::Node* write(Inkscape::XML::Document* doc, Inkscape::XML::Node* repr, unsigned int flags); }; @@ -90,10 +93,10 @@ protected: Inkscape::XML::Node * const owner_repr = owner->getRepr(); //XML Tree being used directly here while it shouldn't be... Inkscape::XML::Node * const obj_repr = obj->getRepr(); - gchar const * owner_name = NULL; - gchar const * owner_clippath = NULL; - gchar const * obj_name = NULL; - gchar const * obj_id = NULL; + char const * owner_name = NULL; + char const * owner_clippath = NULL; + char const * obj_name = NULL; + char const * obj_id = NULL; if (owner_repr != NULL) { owner_name = owner_repr->name(); owner_clippath = owner_repr->attribute("clippath"); @@ -102,7 +105,7 @@ protected: obj_name = obj_repr->name(); obj_id = obj_repr->attribute("id"); } - g_warning("Ignoring recursive clippath reference " + printf("WARNING: Ignoring recursive clippath reference " "<%s clippath=\"%s\"> in <%s id=\"%s\">", owner_name, owner_clippath, obj_name, obj_id); diff --git a/src/sp-conn-end-pair.h b/src/sp-conn-end-pair.h index 9f7f5a5d2..93f54378c 100644 --- a/src/sp-conn-end-pair.h +++ b/src/sp-conn-end-pair.h @@ -11,12 +11,10 @@ * * Released under GNU GPL, read the file 'COPYING' for more information */ -#include -#include -#include -#include -#include +#include +#include + #include "libavoid/connector.h" @@ -33,21 +31,21 @@ class Node; } } -extern void recreateCurve(SPCurve *curve, Avoid::ConnRef *connRef, gdouble curvature); +extern void recreateCurve(SPCurve *curve, Avoid::ConnRef *connRef, double curvature); class SPConnEndPair { public: SPConnEndPair(SPPath *); ~SPConnEndPair(); void release(); - void setAttr(unsigned const key, gchar const *const value); + void setAttr(unsigned const key, char const *const value); void writeRepr(Inkscape::XML::Node *const repr) const; void getAttachedItems(SPItem *[2]) const; void getEndpoints(Geom::Point endPts[]) const; - gdouble getCurvature(void) const; + double getCurvature(void) const; SPConnEnd** getConnEnds(void); bool isOrthogonal(void) const; - friend void recreateCurve(SPCurve *curve, Avoid::ConnRef *connRef, gdouble curvature); + friend void recreateCurve(SPCurve *curve, Avoid::ConnRef *connRef, double curvature); void tellLibavoidNewEndpoints(const bool processTransaction = false); bool reroutePathFromLibavoid(void); void makePathInvalid(void); @@ -64,7 +62,7 @@ private: Avoid::ConnRef *_connRef; int _connType; - gdouble _connCurvature; + double _connCurvature; // A sigc connection for transformed signal. sigc::connection _transformed_connection; diff --git a/src/sp-conn-end.h b/src/sp-conn-end.h index a0b1ba5df..2b89a159d 100644 --- a/src/sp-conn-end.h +++ b/src/sp-conn-end.h @@ -1,8 +1,7 @@ #ifndef SEEN_SP_CONN_END #define SEEN_SP_CONN_END -#include -#include +#include #include #include "sp-use-reference.h" @@ -15,7 +14,7 @@ public: SPConnEnd(SPObject *owner); SPUseReference ref; - gchar *href; + char *href; /** Change of href string (not a modification of the attributes of the referrent). */ sigc::connection _changed_connection; @@ -29,13 +28,13 @@ public: /** A sigc connection for owning group transformed, used to do move compensation. */ sigc::connection _group_connection; - void setAttacherHref(gchar const *, SPPath *); - void setAttacherEndpoint(gchar const *, SPPath *); + void setAttacherHref(char const * value, SPPath * unused); + //void setAttacherEndpoint(char const *, SPPath *); // not defined private: - SPConnEnd(SPConnEnd const &); - SPConnEnd &operator=(SPConnEnd const &); + SPConnEnd(SPConnEnd const &); // no copy + SPConnEnd &operator=(SPConnEnd const &); // no assign }; void sp_conn_end_href_changed(SPObject *old_ref, SPObject *ref, diff --git a/src/sp-cursor.cpp b/src/sp-cursor.cpp index ea73da00c..16659d1cf 100644 --- a/src/sp-cursor.cpp +++ b/src/sp-cursor.cpp @@ -17,13 +17,14 @@ */ #include +#include #include #include #include "color.h" #include "sp-cursor.h" -static void free_cursor_data(guchar *pixels, gpointer /*data*/) { +static void free_cursor_data(unsigned char *pixels, void* /*data*/) { delete [] reinterpret_cast(pixels); } @@ -53,7 +54,7 @@ struct RGBA { } }; -GdkPixbuf *sp_cursor_pixbuf_from_xpm(gchar const *const *xpm, GdkColor const& black, GdkColor const& white, guint32 fill, guint32 stroke) +GdkPixbuf *sp_cursor_pixbuf_from_xpm(char const *const *xpm, GdkColor const& black, GdkColor const& white, guint32 fill, guint32 stroke) { int height = 0; int width = 0; @@ -72,7 +73,7 @@ GdkPixbuf *sp_cursor_pixbuf_from_xpm(gchar const *const *xpm, GdkColor const& bl char const *p = xpm[1 + i]; g_assert(*p >=0); - guchar const ccode = (guchar) *p; + unsigned char const ccode = (guchar) *p; p++; while (isspace(*p)) { @@ -110,7 +111,7 @@ GdkPixbuf *sp_cursor_pixbuf_from_xpm(gchar const *const *xpm, GdkColor const& bl return gdk_pixbuf_new_from_data(reinterpret_cast(pixmap_buffer), GDK_COLORSPACE_RGB, TRUE, 8, width, height, width * sizeof(guint32), free_cursor_data, NULL); } -GdkCursor *sp_cursor_new_from_xpm(gchar const *const *xpm, gint hot_x, gint hot_y) +GdkCursor *sp_cursor_new_from_xpm(char const *const *xpm, int hot_x, int hot_y) { GdkCursor *cursor = 0; GdkPixbuf *pixbuf = gdk_pixbuf_new_from_xpm_data((const gchar **)xpm); diff --git a/src/sp-cursor.h b/src/sp-cursor.h index f445127ad..c0b8b46a3 100644 --- a/src/sp-cursor.h +++ b/src/sp-cursor.h @@ -1,10 +1,13 @@ #ifndef SP_CURSOR_H #define SP_CURSOR_H -#include +typedef unsigned int guint32; +typedef struct _GdkPixbuf GdkPixbuf; +typedef struct _GdkCursor GdkCursor; +typedef struct _GdkColor GdkColor; -GdkPixbuf* sp_cursor_pixbuf_from_xpm(gchar const *const *xpm, GdkColor const& black, GdkColor const& white, guint32 fill, guint32 stroke); -GdkCursor *sp_cursor_new_from_xpm(gchar const *const *xpm, gint hot_x, gint hot_y); +GdkPixbuf* sp_cursor_pixbuf_from_xpm(char const *const *xpm, GdkColor const& black, GdkColor const& white, guint32 fill, guint32 stroke); +GdkCursor *sp_cursor_new_from_xpm(char const *const *xpm, int hot_x, int hot_y); #endif diff --git a/src/sp-defs.h b/src/sp-defs.h index 6efdea1f3..c122cb2a9 100644 --- a/src/sp-defs.h +++ b/src/sp-defs.h @@ -27,7 +27,7 @@ protected: virtual void release(); virtual void update(SPCtx* ctx, unsigned int flags); virtual void modified(unsigned int flags); - virtual Inkscape::XML::Node* write(Inkscape::XML::Document *xml_doc, Inkscape::XML::Node *repr, guint flags); + virtual Inkscape::XML::Node* write(Inkscape::XML::Document *xml_doc, Inkscape::XML::Node *repr, unsigned int flags); }; #endif // !SEEN_SP_DEFS_H diff --git a/src/sp-desc.h b/src/sp-desc.h index 2bb42b333..40888bee4 100644 --- a/src/sp-desc.h +++ b/src/sp-desc.h @@ -1,5 +1,5 @@ -#ifndef __SP_DESC_H__ -#define __SP_DESC_H__ +#ifndef SEEN_SP_DESC_H +#define SEEN_SP_DESC_H /* * SVG implementation @@ -23,7 +23,7 @@ public: virtual ~SPDesc(); protected: - virtual Inkscape::XML::Node* write(Inkscape::XML::Document* doc, Inkscape::XML::Node* repr, guint flags); + virtual Inkscape::XML::Node* write(Inkscape::XML::Document* doc, Inkscape::XML::Node* repr, unsigned int flags); }; #endif diff --git a/src/sp-ellipse.h b/src/sp-ellipse.h index e575b8761..09768fd6d 100644 --- a/src/sp-ellipse.h +++ b/src/sp-ellipse.h @@ -24,7 +24,7 @@ #define SP_IS_GENERICELLIPSE(obj) (dynamic_cast((obj)) != NULL) enum GenericEllipseType { - SP_GENERIC_ELLIPSE_UNDEFINED, + SP_GENERIC_ELLIPSE_UNDEFINED, // FIXME shouldn't exist SP_GENERIC_ELLIPSE_ARC, SP_GENERIC_ELLIPSE_CIRCLE, SP_GENERIC_ELLIPSE_ELLIPSE @@ -53,10 +53,10 @@ public: virtual void build(SPDocument *document, Inkscape::XML::Node *repr); - virtual void set(unsigned int key, gchar const *value); + virtual void set(unsigned int key, char const *value); virtual void update(SPCtx *ctx, unsigned int flags); - virtual Inkscape::XML::Node *write(Inkscape::XML::Document *xml_doc, Inkscape::XML::Node *repr, guint flags); + virtual Inkscape::XML::Node *write(Inkscape::XML::Document *xml_doc, Inkscape::XML::Node *repr, unsigned int flags); virtual const char *displayName() const; virtual void set_shape(); @@ -76,7 +76,7 @@ public: Geom::Point getPointAtAngle(double arg) const; bool set_elliptical_path_attribute(Inkscape::XML::Node *repr); - void position_set(gdouble x, gdouble y, gdouble rx, gdouble ry); + void position_set(double x, double y, double rx, double ry); protected: /** diff --git a/src/sp-filter-primitive.h b/src/sp-filter-primitive.h index 040e2f31f..d81adbd10 100644 --- a/src/sp-filter-primitive.h +++ b/src/sp-filter-primitive.h @@ -1,5 +1,5 @@ -#ifndef __SP_FILTER_PRIMITIVE_H__ -#define __SP_FILTER_PRIMITIVE_H__ +#ifndef SEEN_SP_FILTER_PRIMITIVE_H +#define SEEN_SP_FILTER_PRIMITIVE_H /** \file * Document level base class for all SVG filter primitives. @@ -40,11 +40,11 @@ protected: virtual void build(SPDocument* doc, Inkscape::XML::Node* repr); virtual void release(); - virtual void set(unsigned int key, const gchar* value); + virtual void set(unsigned int key, char const* value); virtual void update(SPCtx* ctx, unsigned int flags); - virtual Inkscape::XML::Node* write(Inkscape::XML::Document* doc, Inkscape::XML::Node* repr, guint flags); + virtual Inkscape::XML::Node* write(Inkscape::XML::Document* doc, Inkscape::XML::Node* repr, unsigned int flags); public: virtual void build_renderer(Inkscape::Filters::Filter* filter) = 0; @@ -54,8 +54,8 @@ public: void sp_filter_primitive_renderer_common(SPFilterPrimitive *sp_prim, Inkscape::Filters::FilterPrimitive *nr_prim); int sp_filter_primitive_name_previous_out(SPFilterPrimitive *prim); -int sp_filter_primitive_read_in(SPFilterPrimitive *prim, gchar const *name); -int sp_filter_primitive_read_result(SPFilterPrimitive *prim, gchar const *name); +int sp_filter_primitive_read_in(SPFilterPrimitive *prim, char const *name); +int sp_filter_primitive_read_result(SPFilterPrimitive *prim, char const *name); #endif /* diff --git a/src/sp-filter.h b/src/sp-filter.h index 0d087c5bf..e6318c569 100644 --- a/src/sp-filter.h +++ b/src/sp-filter.h @@ -12,6 +12,7 @@ #ifndef SP_FILTER_H_SEEN #define SP_FILTER_H_SEEN +#include #include #include "number-opt-number.h" @@ -19,8 +20,6 @@ #include "sp-filter-units.h" #include "svg/svg-length.h" -#include - #define SP_FILTER(obj) (dynamic_cast((SPObject*)obj)) #define SP_IS_FILTER(obj) (dynamic_cast((SPObject*)obj) != NULL) @@ -45,9 +44,9 @@ public: virtual ~SPFilter(); SPFilterUnits filterUnits; - guint filterUnits_set : 1; + unsigned int filterUnits_set : 1; SPFilterUnits primitiveUnits; - guint primitiveUnits_set : 1; + unsigned int primitiveUnits_set : 1; SVGLength x; SVGLength y; SVGLength width; @@ -68,11 +67,11 @@ protected: virtual void child_added(Inkscape::XML::Node* child, Inkscape::XML::Node* ref); virtual void remove_child(Inkscape::XML::Node* child); - virtual void set(unsigned int key, const gchar* value); + virtual void set(unsigned int key, const char* value); virtual void update(SPCtx* ctx, unsigned int flags); - virtual Inkscape::XML::Node* write(Inkscape::XML::Document* doc, Inkscape::XML::Node* repr, guint flags); + virtual Inkscape::XML::Node* write(Inkscape::XML::Document* doc, Inkscape::XML::Node* repr, unsigned int flags); }; void sp_filter_set_filter_units(SPFilter *filter, SPFilterUnits filterUnits); @@ -88,14 +87,14 @@ void sp_filter_build_renderer(SPFilter *sp_filter, Inkscape::Filters::Filter *nr int sp_filter_primitive_count(SPFilter *filter); /// Returns a slot number for given image name, or -1 for unknown name. -int sp_filter_get_image_name(SPFilter *filter, gchar const *name); +int sp_filter_get_image_name(SPFilter *filter, char const *name); /// Returns slot number for given image name, even if it's unknown. -int sp_filter_set_image_name(SPFilter *filter, gchar const *name); +int sp_filter_set_image_name(SPFilter *filter, char const *name); /** Finds image name based on it's slot number. Returns 0 for unknown slot * numbers. */ -gchar const *sp_filter_name_for_image(SPFilter const *filter, int const image); +char const *sp_filter_name_for_image(SPFilter const *filter, int const image); /// Returns a result image name that is not in use inside this filter. Glib::ustring sp_filter_get_new_result_name(SPFilter *filter); diff --git a/src/sp-flowdiv.h b/src/sp-flowdiv.h index d00cfc51b..4a3690726 100644 --- a/src/sp-flowdiv.h +++ b/src/sp-flowdiv.h @@ -1,5 +1,5 @@ -#ifndef __SP_ITEM_FLOWDIV_H__ -#define __SP_ITEM_FLOWDIV_H__ +#ifndef SEEN_SP_ITEM_FLOWDIV_H +#define SEEN_SP_ITEM_FLOWDIV_H /* */ @@ -31,11 +31,11 @@ public: protected: virtual void build(SPDocument *document, Inkscape::XML::Node *repr); virtual void release(); - virtual void update(SPCtx* ctx, guint flags); + virtual void update(SPCtx* ctx, unsigned int flags); virtual void modified(unsigned int flags); - virtual void set(unsigned int key, gchar const* value); - virtual Inkscape::XML::Node* write(Inkscape::XML::Document *xml_doc, Inkscape::XML::Node *repr, guint flags); + virtual void set(unsigned int key, char const* value); + virtual Inkscape::XML::Node* write(Inkscape::XML::Document *xml_doc, Inkscape::XML::Node *repr, unsigned int flags); }; class SPFlowtspan : public SPItem { @@ -46,11 +46,11 @@ public: protected: virtual void build(SPDocument *document, Inkscape::XML::Node *repr); virtual void release(); - virtual void update(SPCtx* ctx, guint flags); + virtual void update(SPCtx* ctx, unsigned int flags); virtual void modified(unsigned int flags); - virtual void set(unsigned int key, gchar const* value); - virtual Inkscape::XML::Node* write(Inkscape::XML::Document *xml_doc, Inkscape::XML::Node *repr, guint flags); + virtual void set(unsigned int key, char const* value); + virtual Inkscape::XML::Node* write(Inkscape::XML::Document *xml_doc, Inkscape::XML::Node *repr, unsigned int flags); }; class SPFlowpara : public SPItem { @@ -61,11 +61,11 @@ public: protected: virtual void build(SPDocument *document, Inkscape::XML::Node *repr); virtual void release(); - virtual void update(SPCtx* ctx, guint flags); + virtual void update(SPCtx* ctx, unsigned int flags); virtual void modified(unsigned int flags); - virtual void set(unsigned int key, gchar const* value); - virtual Inkscape::XML::Node* write(Inkscape::XML::Document *xml_doc, Inkscape::XML::Node *repr, guint flags); + virtual void set(unsigned int key, char const* value); + virtual Inkscape::XML::Node* write(Inkscape::XML::Document *xml_doc, Inkscape::XML::Node *repr, unsigned int flags); }; // these do not need any style @@ -78,7 +78,7 @@ protected: virtual void release(); virtual void modified(unsigned int flags); - virtual Inkscape::XML::Node* write(Inkscape::XML::Document *xml_doc, Inkscape::XML::Node *repr, guint flags); + virtual Inkscape::XML::Node* write(Inkscape::XML::Document *xml_doc, Inkscape::XML::Node *repr, unsigned int flags); }; class SPFlowregionbreak : public SPObject { @@ -90,7 +90,7 @@ protected: virtual void release(); virtual void modified(unsigned int flags); - virtual Inkscape::XML::Node* write(Inkscape::XML::Document *xml_doc, Inkscape::XML::Node *repr, guint flags); + virtual Inkscape::XML::Node* write(Inkscape::XML::Document *xml_doc, Inkscape::XML::Node *repr, unsigned int flags); }; #endif diff --git a/src/sp-flowregion.h b/src/sp-flowregion.h index 721eb0432..024a298b8 100644 --- a/src/sp-flowregion.h +++ b/src/sp-flowregion.h @@ -1,5 +1,5 @@ -#ifndef __SP_ITEM_FLOWREGION_H__ -#define __SP_ITEM_FLOWREGION_H__ +#ifndef SEEN_SP_ITEM_FLOWREGION_H +#define SEEN_SP_ITEM_FLOWREGION_H /* */ @@ -30,7 +30,7 @@ public: virtual void remove_child(Inkscape::XML::Node *child); virtual void update(SPCtx *ctx, unsigned int flags); virtual void modified(guint flags); - virtual Inkscape::XML::Node* write(Inkscape::XML::Document *xml_doc, Inkscape::XML::Node *repr, guint flags); + virtual Inkscape::XML::Node* write(Inkscape::XML::Document *xml_doc, Inkscape::XML::Node *repr, unsigned int flags); virtual const char* displayName() const; }; @@ -47,7 +47,7 @@ public: virtual void remove_child(Inkscape::XML::Node *child); virtual void update(SPCtx *ctx, unsigned int flags); virtual void modified(guint flags); - virtual Inkscape::XML::Node* write(Inkscape::XML::Document *xml_doc, Inkscape::XML::Node *repr, guint flags); + virtual Inkscape::XML::Node* write(Inkscape::XML::Document *xml_doc, Inkscape::XML::Node *repr, unsigned int flags); virtual const char* displayName() const; }; diff --git a/src/sp-flowtext.h b/src/sp-flowtext.h index a5b7db22e..743d55030 100644 --- a/src/sp-flowtext.h +++ b/src/sp-flowtext.h @@ -4,10 +4,10 @@ /* */ -#include "sp-item.h" - #include <2geom/forward.h> + #include "libnrtype/Layout-TNG.h" +#include "sp-item.h" #define SP_FLOWTEXT(obj) (dynamic_cast((SPObject*)obj)) #define SP_IS_FLOWTEXT(obj) (dynamic_cast((SPObject*)obj) != NULL) @@ -63,18 +63,18 @@ public: virtual void child_added(Inkscape::XML::Node* child, Inkscape::XML::Node* ref); virtual void remove_child(Inkscape::XML::Node* child); - virtual void set(unsigned int key, const gchar* value); + virtual void set(unsigned int key, const char* value); virtual Geom::Affine set_transform(Geom::Affine const& xform); virtual void update(SPCtx* ctx, unsigned int flags); virtual void modified(unsigned int flags); - virtual Inkscape::XML::Node* write(Inkscape::XML::Document* doc, Inkscape::XML::Node* repr, guint flags); + virtual Inkscape::XML::Node* write(Inkscape::XML::Document* doc, Inkscape::XML::Node* repr, unsigned int flags); virtual Geom::OptRect bbox(Geom::Affine const &transform, SPItem::BBoxType type) const; virtual void print(SPPrintContext *ctx); virtual const char* displayName() const; - virtual gchar* description() const; + virtual char* description() const; virtual Inkscape::DrawingItem* show(Inkscape::Drawing &drawing, unsigned int key, unsigned int flags); virtual void hide(unsigned int key); virtual void snappoints(std::vector &p, Inkscape::SnapPreferences const *snapprefs) const; diff --git a/src/sp-font-face.h b/src/sp-font-face.h index 531dd5843..669b93197 100644 --- a/src/sp-font-face.h +++ b/src/sp-font-face.h @@ -1,9 +1,5 @@ -#ifdef HAVE_CONFIG_H -# include -#endif - -#ifndef __SP_FONTFACE_H__ -#define __SP_FONTFACE_H__ +#ifndef SEEN_SP_FONTFACE_H +#define SEEN_SP_FONTFACE_H #include @@ -117,11 +113,11 @@ protected: virtual void child_added(Inkscape::XML::Node* child, Inkscape::XML::Node* ref); virtual void remove_child(Inkscape::XML::Node* child); - virtual void set(unsigned int key, const gchar* value); + virtual void set(unsigned int key, const char* value); virtual void update(SPCtx* ctx, unsigned int flags); - virtual Inkscape::XML::Node* write(Inkscape::XML::Document* doc, Inkscape::XML::Node* repr, guint flags); + virtual Inkscape::XML::Node* write(Inkscape::XML::Document* doc, Inkscape::XML::Node* repr, unsigned int flags); }; #endif //#ifndef __SP_FONTFACE_H__ diff --git a/src/sp-font.h b/src/sp-font.h index 6e6f4eec2..6e26a02b2 100644 --- a/src/sp-font.h +++ b/src/sp-font.h @@ -1,7 +1,3 @@ -#ifdef HAVE_CONFIG_H -# include -#endif - #ifndef SP_FONT_H_SEEN #define SP_FONT_H_SEEN @@ -40,11 +36,11 @@ protected: virtual void child_added(Inkscape::XML::Node* child, Inkscape::XML::Node* ref); virtual void remove_child(Inkscape::XML::Node* child); - virtual void set(unsigned int key, const gchar* value); + virtual void set(unsigned int key, char const* value); virtual void update(SPCtx* ctx, unsigned int flags); - virtual Inkscape::XML::Node* write(Inkscape::XML::Document* doc, Inkscape::XML::Node* repr, guint flags); + virtual Inkscape::XML::Node* write(Inkscape::XML::Document* doc, Inkscape::XML::Node* repr, unsigned int flags); }; #endif //#ifndef SP_FONT_H_SEEN diff --git a/src/sp-glyph-kerning.h b/src/sp-glyph-kerning.h index 52413f8a7..c96c0b6e4 100644 --- a/src/sp-glyph-kerning.h +++ b/src/sp-glyph-kerning.h @@ -25,11 +25,11 @@ class GlyphNames { public: - GlyphNames(const gchar* value); + GlyphNames(char const* value); ~GlyphNames(); - bool contains(const char* name); + bool contains(char const* name); private: - gchar* names; + char* names; }; class SPGlyphKerning : public SPObject { @@ -47,9 +47,9 @@ public: protected: virtual void build(SPDocument* doc, Inkscape::XML::Node* repr); virtual void release(); - virtual void set(unsigned int key, const gchar* value); + virtual void set(unsigned int key, char const* value); virtual void update(SPCtx* ctx, unsigned int flags); - virtual Inkscape::XML::Node* write(Inkscape::XML::Document* doc, Inkscape::XML::Node* repr, guint flags); + virtual Inkscape::XML::Node* write(Inkscape::XML::Document* doc, Inkscape::XML::Node* repr, unsigned int flags); }; class SPHkern : public SPGlyphKerning { diff --git a/src/sp-glyph.h b/src/sp-glyph.h index e92357c94..297ac930e 100644 --- a/src/sp-glyph.h +++ b/src/sp-glyph.h @@ -52,9 +52,9 @@ public: protected: virtual void build(SPDocument* doc, Inkscape::XML::Node* repr); virtual void release(); - virtual void set(unsigned int key, const gchar* value); + virtual void set(unsigned int key, const char* value); virtual void update(SPCtx* ctx, unsigned int flags); - virtual Inkscape::XML::Node* write(Inkscape::XML::Document* doc, Inkscape::XML::Node* repr, guint flags); + virtual Inkscape::XML::Node* write(Inkscape::XML::Document* doc, Inkscape::XML::Node* repr, unsigned int flags); }; diff --git a/src/sp-gradient-vector.h b/src/sp-gradient-vector.h index 8e860c169..e57820b56 100644 --- a/src/sp-gradient-vector.h +++ b/src/sp-gradient-vector.h @@ -1,7 +1,6 @@ #ifndef SEEN_SP_GRADIENT_VECTOR_H #define SEEN_SP_GRADIENT_VECTOR_H -#include #include #include "color.h" @@ -14,9 +13,9 @@ * copying from SPStop to SPGradientStop. */ struct SPGradientStop { - gdouble offset; + double offset; SPColor color; - gfloat opacity; + float opacity; }; /** diff --git a/src/sp-gradient.h b/src/sp-gradient.h index a14dcc09e..fbb48df62 100644 --- a/src/sp-gradient.h +++ b/src/sp-gradient.h @@ -14,29 +14,18 @@ * Released under GNU GPL, read the file 'COPYING' for more information */ -#include -#include #include <2geom/affine.h> +#include +#include +#include +#include + #include "sp-paint-server.h" #include "sp-gradient-spread.h" #include "sp-gradient-units.h" #include "sp-gradient-vector.h" #include "sp-mesh-array.h" -#include -#include - - - -//#include -//#include -//#include <2geom/forward.h> -//#include "sp-gradient-spread.h" -//#include "sp-gradient-units.h" -// -//class SPGradient; -//struct SPMeshGradient; - class SPGradientReference; class SPStop; diff --git a/src/sp-guide.h b/src/sp-guide.h index 9f5d7ba03..cd67df222 100644 --- a/src/sp-guide.h +++ b/src/sp-guide.h @@ -13,9 +13,9 @@ * */ +#include <2geom/point.h> #include -#include <2geom/point.h> #include "sp-object.h" #include "sp-guide-attachment.h" diff --git a/src/sp-image.h b/src/sp-image.h index 17262d74f..9fa33b5de 100644 --- a/src/sp-image.h +++ b/src/sp-image.h @@ -14,7 +14,6 @@ #ifndef SEEN_INKSCAPE_SP_IMAGE_H #define SEEN_INKSCAPE_SP_IMAGE_H -#include #include #include "svg/svg-length.h" #include "display/curve.h" @@ -43,24 +42,24 @@ public: SPCurve *curve; // This curve is at the image's boundary for snapping - gchar *href; + char *href; #if defined(HAVE_LIBLCMS1) || defined(HAVE_LIBLCMS2) - gchar *color_profile; + char *color_profile; #endif // defined(HAVE_LIBLCMS1) || defined(HAVE_LIBLCMS2) Inkscape::Pixbuf *pixbuf; virtual void build(SPDocument *document, Inkscape::XML::Node *repr); virtual void release(); - virtual void set(unsigned int key, gchar const* value); - virtual void update(SPCtx *ctx, guint flags); - virtual Inkscape::XML::Node* write(Inkscape::XML::Document *xml_doc, Inkscape::XML::Node *repr, guint flags); + virtual void set(unsigned int key, char const* value); + virtual void update(SPCtx *ctx, unsigned int flags); + virtual Inkscape::XML::Node* write(Inkscape::XML::Document *xml_doc, Inkscape::XML::Node *repr, unsigned int flags); virtual void modified(unsigned int flags); virtual Geom::OptRect bbox(Geom::Affine const &transform, SPItem::BBoxType type) const; virtual void print(SPPrintContext *ctx); virtual const char* displayName() const; - virtual gchar* description() const; + virtual char* description() const; virtual Inkscape::DrawingItem* show(Inkscape::Drawing &drawing, unsigned int key, unsigned int flags); virtual void snappoints(std::vector &p, Inkscape::SnapPreferences const *snapprefs) const; virtual Geom::Affine set_transform(Geom::Affine const &transform); diff --git a/src/sp-item-group.h b/src/sp-item-group.h index 2004a72b8..4e15ee5df 100644 --- a/src/sp-item-group.h +++ b/src/sp-item-group.h @@ -1,5 +1,5 @@ -#ifndef __SP_ITEM_GROUP_H__ -#define __SP_ITEM_GROUP_H__ +#ifndef SEEN_SP_ITEM_GROUP_H +#define SEEN_SP_ITEM_GROUP_H /* * SVG implementation @@ -25,6 +25,7 @@ namespace Inkscape { class Drawing; class DrawingItem; +typedef struct _GSList GSList; } // namespace Inkscape @@ -54,7 +55,7 @@ public: void translateChildItems(Geom::Translate const &tr); void scaleChildItemsRec(Geom::Scale const &sc, Geom::Point const &p); - gint getItemCount() const; + int getItemCount() const; virtual void _showChildren (Inkscape::Drawing &drawing, Inkscape::DrawingItem *ai, unsigned int key, unsigned int flags); private: @@ -69,15 +70,15 @@ public: virtual void order_changed(Inkscape::XML::Node *child, Inkscape::XML::Node *old_ref, Inkscape::XML::Node *new_ref); virtual void update(SPCtx *ctx, unsigned int flags); - virtual void modified(guint flags); - virtual void set(unsigned int key, gchar const* value); + virtual void modified(unsigned int flags); + virtual void set(unsigned int key, char const* value); - virtual Inkscape::XML::Node* write(Inkscape::XML::Document *xml_doc, Inkscape::XML::Node *repr, guint flags); + virtual Inkscape::XML::Node* write(Inkscape::XML::Document *xml_doc, Inkscape::XML::Node *repr, unsigned int flags); virtual Geom::OptRect bbox(Geom::Affine const &transform, SPItem::BBoxType bboxtype) const; virtual void print(SPPrintContext *ctx); virtual const char* displayName() const; - virtual gchar *description() const; + virtual char *description() const; virtual Inkscape::DrawingItem *show (Inkscape::Drawing &drawing, unsigned int key, unsigned int flags); virtual void hide (unsigned int key); @@ -90,7 +91,7 @@ void sp_item_group_ungroup (SPGroup *group, GSList **children, bool do_done = tr GSList *sp_item_group_item_list (SPGroup *group); -SPObject *sp_item_group_get_child_by_name (SPGroup *group, SPObject *ref, const gchar *name); +SPObject *sp_item_group_get_child_by_name (SPGroup *group, SPObject *ref, const char *name); #endif diff --git a/src/sp-item-notify-moveto.cpp b/src/sp-item-notify-moveto.cpp index 0f5117289..90fd676ee 100644 --- a/src/sp-item-notify-moveto.cpp +++ b/src/sp-item-notify-moveto.cpp @@ -9,6 +9,7 @@ #include using std::vector; +#define return_if_fail(test) if (!(test)) { printf("WARNING: assertion '%s' failed", #test); return; } /** * Called by sp_guide_moveto to indicate that the guide line corresponding to g has been moved, and @@ -19,15 +20,15 @@ using std::vector; void sp_item_notify_moveto(SPItem &item, SPGuide const &mv_g, int const snappoint_ix, double const position, bool const commit) { - g_return_if_fail(SP_IS_ITEM(&item)); - g_return_if_fail( unsigned(snappoint_ix) < 8 ); + return_if_fail(SP_IS_ITEM(&item)); + return_if_fail( unsigned(snappoint_ix) < 8 ); Geom::Point const dir( mv_g.normal_to_line ); double const dir_lensq(dot(dir, dir)); - g_return_if_fail( dir_lensq != 0 ); + return_if_fail( dir_lensq != 0 ); std::vector snappoints; item.getSnappoints(snappoints, NULL); - g_return_if_fail( snappoint_ix < int(snappoints.size()) ); + return_if_fail( snappoint_ix < int(snappoints.size()) ); double const pos0 = dot(dir, snappoints[snappoint_ix].getPoint()); /// \todo effic: skip if mv_g is already satisfied. diff --git a/src/sp-item-transform.cpp b/src/sp-item-transform.cpp index 086da56ff..86beee907 100644 --- a/src/sp-item-transform.cpp +++ b/src/sp-item-transform.cpp @@ -18,6 +18,8 @@ #include "sp-item.h" #include "sp-item-transform.h" +#include + void sp_item_rotate_rel(SPItem *item, Geom::Rotate const &rotation) { Geom::Point center = item->getCenter(); diff --git a/src/sp-item-transform.h b/src/sp-item-transform.h index 230d5a3dd..d563c9768 100644 --- a/src/sp-item-transform.h +++ b/src/sp-item-transform.h @@ -1,9 +1,8 @@ #ifndef SEEN_SP_ITEM_TRANSFORM_H #define SEEN_SP_ITEM_TRANSFORM_H -#include - #include <2geom/forward.h> + class SPItem; void sp_item_rotate_rel(SPItem *item, Geom::Rotate const &rotation); @@ -11,9 +10,9 @@ void sp_item_scale_rel (SPItem *item, Geom::Scale const &scale); void sp_item_skew_rel (SPItem *item, double skewX, double skewY); void sp_item_move_rel(SPItem *item, Geom::Translate const &tr); -Geom::Affine get_scale_transform_for_uniform_stroke (Geom::Rect const &bbox_visual, gdouble stroke_x, gdouble stroke_y, bool transform_stroke, bool preserve, gdouble x0, gdouble y0, gdouble x1, gdouble y1); -Geom::Affine get_scale_transform_for_variable_stroke (Geom::Rect const &bbox_visual, Geom::Rect const &bbox_geom, bool transform_stroke, bool preserve, gdouble x0, gdouble y0, gdouble x1, gdouble y1); -Geom::Rect get_visual_bbox (Geom::OptRect const &initial_geom_bbox, Geom::Affine const &abs_affine, gdouble const initial_strokewidth, bool const transform_stroke); +Geom::Affine get_scale_transform_for_uniform_stroke (Geom::Rect const &bbox_visual, double stroke_x, double stroke_y, bool transform_stroke, bool preserve, double x0, double y0, double x1, double y1); +Geom::Affine get_scale_transform_for_variable_stroke (Geom::Rect const &bbox_visual, Geom::Rect const &bbox_geom, bool transform_stroke, bool preserve, double x0, double y0, double x1, double y1); +Geom::Rect get_visual_bbox (Geom::OptRect const &initial_geom_bbox, Geom::Affine const &abs_affine, double const initial_strokewidth, bool const transform_stroke); #endif // SEEN_SP_ITEM_TRANSFORM_H diff --git a/src/sp-item.cpp b/src/sp-item.cpp index 428f9555e..c79508199 100644 --- a/src/sp-item.cpp +++ b/src/sp-item.cpp @@ -360,7 +360,7 @@ void SPItem::lowerToBottom() { * \param target - the SPItem to move into or after * \param intoafter - move to after the target (false), move inside (sublayer) of the target (true) */ -void SPItem::moveTo(SPItem *target, gboolean intoafter) { +void SPItem::moveTo(SPItem *target, bool intoafter) { Inkscape::XML::Node *target_ref = ( target ? target->getRepr() : NULL ); Inkscape::XML::Node *our_ref = getRepr(); diff --git a/src/sp-item.h b/src/sp-item.h index 15784d041..197d33263 100644 --- a/src/sp-item.h +++ b/src/sp-item.h @@ -18,10 +18,11 @@ * * Released under GNU GPL, read the file 'COPYING' for more information */ -#include + #include <2geom/forward.h> #include <2geom/affine.h> #include <2geom/rect.h> +#include #include "sp-object.h" #include "snap-preferences.h" @@ -72,7 +73,7 @@ enum PatternTransform { class SPEvent { public: unsigned int type; - gpointer data; + void* data; }; /// SPItemView @@ -179,7 +180,7 @@ public: void lowerOne(); void raiseToTop(); void lowerToBottom(); - void moveTo(SPItem *target, gboolean intoafter); + void moveTo(SPItem *target, bool intoafter); sigc::connection connectTransformed(sigc::slot slot) { return _transformed_signal.connect(slot); @@ -198,7 +199,7 @@ public: unsigned int pos_in_parent() const; - gchar *detailedDescription() const; + char *detailedDescription() const; bool isFiltered() const; @@ -209,14 +210,14 @@ public: void getSnappoints(std::vector &p, Inkscape::SnapPreferences const *snapprefs=0) const; void adjust_pattern(/* Geom::Affine const &premul, */ Geom::Affine const &postmul, bool set = false, PatternTransform = TRANSFORM_BOTH); void adjust_gradient(/* Geom::Affine const &premul, */ Geom::Affine const &postmul, bool set = false); - void adjust_stroke(gdouble ex); - void adjust_stroke_width_recursive(gdouble ex); + void adjust_stroke(double ex); + void adjust_stroke_width_recursive(double ex); void freeze_stroke_width_recursive(bool freeze); void adjust_paint_recursive(Geom::Affine advertized_transform, Geom::Affine t_ancestors, bool is_pattern); void adjust_livepatheffect(Geom::Affine const &postmul, bool set = false); void doWriteTransform(Inkscape::XML::Node *repr, Geom::Affine const &transform, Geom::Affine const *adv = NULL, bool compensate = true); void set_item_transform(Geom::Affine const &transform_matrix); - gint emitEvent (SPEvent &event); + int emitEvent (SPEvent &event); Inkscape::DrawingItem *get_arenaitem(unsigned int key); Geom::Affine i2doc_affine() const; @@ -240,14 +241,14 @@ private: public: virtual void build(SPDocument *document, Inkscape::XML::Node *repr); virtual void release(); - virtual void set(unsigned int key, gchar const* value); - virtual void update(SPCtx *ctx, guint flags); - virtual Inkscape::XML::Node* write(Inkscape::XML::Document *xml_doc, Inkscape::XML::Node *repr, guint flags); + virtual void set(unsigned int key, char const* value); + virtual void update(SPCtx *ctx, unsigned int flags); + virtual Inkscape::XML::Node* write(Inkscape::XML::Document *xml_doc, Inkscape::XML::Node *repr, unsigned int flags); virtual Geom::OptRect bbox(Geom::Affine const &transform, SPItem::BBoxType type) const; virtual void print(SPPrintContext *ctx); virtual const char* displayName() const; - virtual gchar* description() const; + virtual char* description() const; virtual Inkscape::DrawingItem* show(Inkscape::Drawing &drawing, unsigned int key, unsigned int flags); virtual void hide(unsigned int key); virtual void snappoints(std::vector &p, Inkscape::SnapPreferences const *snapprefs) const; @@ -255,7 +256,7 @@ public: virtual void convert_to_guides() const; - virtual gint event(SPEvent *event); + virtual int event(SPEvent *event); }; diff --git a/src/sp-line.h b/src/sp-line.h index c1932d3ee..d6a075659 100644 --- a/src/sp-line.h +++ b/src/sp-line.h @@ -31,13 +31,13 @@ public: SVGLength y2; virtual void build(SPDocument *document, Inkscape::XML::Node *repr); - virtual Inkscape::XML::Node* write(Inkscape::XML::Document *xml_doc, Inkscape::XML::Node *repr, guint flags); - virtual void set(unsigned int key, gchar const* value); + virtual Inkscape::XML::Node* write(Inkscape::XML::Document *xml_doc, Inkscape::XML::Node *repr, unsigned int flags); + virtual void set(unsigned int key, char const* value); virtual const char* displayName() const; virtual Geom::Affine set_transform(Geom::Affine const &transform); virtual void convert_to_guides() const; - virtual void update(SPCtx* ctx, guint flags); + virtual void update(SPCtx* ctx, unsigned int flags); virtual void set_shape(); }; diff --git a/src/sp-linear-gradient.cpp b/src/sp-linear-gradient.cpp index 959e8d733..6e9f5e6dd 100644 --- a/src/sp-linear-gradient.cpp +++ b/src/sp-linear-gradient.cpp @@ -1,3 +1,5 @@ +#include + #include "sp-linear-gradient.h" #include "attributes.h" diff --git a/src/sp-linear-gradient.h b/src/sp-linear-gradient.h index ac3fdb04a..a152e7fe2 100644 --- a/src/sp-linear-gradient.h +++ b/src/sp-linear-gradient.h @@ -26,8 +26,8 @@ public: protected: virtual void build(SPDocument *document, Inkscape::XML::Node *repr); - virtual void set(unsigned key, gchar const *value); - virtual Inkscape::XML::Node* write(Inkscape::XML::Document *xml_doc, Inkscape::XML::Node *repr, guint flags); + virtual void set(unsigned key, char const *value); + virtual Inkscape::XML::Node* write(Inkscape::XML::Document *xml_doc, Inkscape::XML::Node *repr, unsigned int flags); }; #endif /* !SP_LINEAR_GRADIENT_H */ diff --git a/src/sp-lpe-item.h b/src/sp-lpe-item.h index 3e858748d..fbac467fd 100644 --- a/src/sp-lpe-item.h +++ b/src/sp-lpe-item.h @@ -14,14 +14,12 @@ * Released under GNU GPL, read the file 'COPYING' for more information */ -#include "sp-item.h" - #include +#include "sp-item.h" #define SP_LPE_ITEM(obj) (dynamic_cast((SPObject*)obj)) #define SP_IS_LPE_ITEM(obj) (dynamic_cast((SPObject*)obj) != NULL) -class CLPEItem; class LivePathEffectObject; class SPCurve; class SPDesktop; @@ -58,7 +56,7 @@ public: virtual void build(SPDocument* doc, Inkscape::XML::Node* repr); virtual void release(); - virtual void set(unsigned int key, gchar const* value); + virtual void set(unsigned int key, char const* value); virtual void update(SPCtx* ctx, unsigned int flags); virtual void modified(unsigned int flags); @@ -66,7 +64,7 @@ public: virtual void child_added(Inkscape::XML::Node* child, Inkscape::XML::Node* ref); virtual void remove_child(Inkscape::XML::Node* child); - virtual Inkscape::XML::Node* write(Inkscape::XML::Document *xml_doc, Inkscape::XML::Node *repr, guint flags); + virtual Inkscape::XML::Node* write(Inkscape::XML::Document *xml_doc, Inkscape::XML::Node *repr, unsigned int flags); virtual void update_patheffect(bool write); @@ -90,7 +88,7 @@ public: bool setCurrentPathEffect(Inkscape::LivePathEffect::LPEObjectReference* lperef); void removeCurrentPathEffect(bool keep_paths); void removeAllPathEffects(bool keep_paths); - void addPathEffect(gchar *value, bool reset); + void addPathEffect(char *value, bool reset); void addPathEffect(LivePathEffectObject * new_lpeobj); bool forkPathEffectsIfNecessary(unsigned int nr_of_allowed_users = 1); diff --git a/src/sp-mask.h b/src/sp-mask.h index e08d1e81e..e991fedb6 100644 --- a/src/sp-mask.h +++ b/src/sp-mask.h @@ -55,12 +55,12 @@ protected: virtual void child_added(Inkscape::XML::Node* child, Inkscape::XML::Node* ref); - virtual void set(unsigned int key, const gchar* value); + virtual void set(unsigned int key, const char* value); virtual void update(SPCtx* ctx, unsigned int flags); virtual void modified(unsigned int flags); - virtual Inkscape::XML::Node* write(Inkscape::XML::Document* doc, Inkscape::XML::Node* repr, guint flags); + virtual Inkscape::XML::Node* write(Inkscape::XML::Document* doc, Inkscape::XML::Node* repr, unsigned int flags); }; class SPMaskReference : public Inkscape::URIReference { @@ -86,10 +86,10 @@ protected: Inkscape::XML::Node * const owner_repr = owner->getRepr(); //XML Tree being used directly here while it shouldn't be... Inkscape::XML::Node * const obj_repr = obj->getRepr(); - gchar const * owner_name = NULL; - gchar const * owner_mask = NULL; - gchar const * obj_name = NULL; - gchar const * obj_id = NULL; + char const * owner_name = NULL; + char const * owner_mask = NULL; + char const * obj_name = NULL; + char const * obj_id = NULL; if (owner_repr != NULL) { owner_name = owner_repr->name(); owner_mask = owner_repr->attribute("mask"); @@ -98,7 +98,7 @@ protected: obj_name = obj_repr->name(); obj_id = obj_repr->attribute("id"); } - g_warning("Ignoring recursive mask reference " + printf("WARNING: Ignoring recursive mask reference " "<%s mask=\"%s\"> in <%s id=\"%s\">", owner_name, owner_mask, obj_name, obj_id); @@ -108,6 +108,6 @@ protected: } }; -const gchar *sp_mask_create (GSList *reprs, SPDocument *document, Geom::Affine const* applyTransform); +const char *sp_mask_create (GSList *reprs, SPDocument *document, Geom::Affine const* applyTransform); #endif // SEEN_SP_MASK_H diff --git a/src/sp-mesh-array.h b/src/sp-mesh-array.h index b10974e7e..330f6d87b 100644 --- a/src/sp-mesh-array.h +++ b/src/sp-mesh-array.h @@ -39,8 +39,6 @@ an array which simplifies things like inserting new rows or columns. */ -#include -#include #include <2geom/point.h> #include "color.h" @@ -89,13 +87,13 @@ public: opacity = 0.0; } NodeType node_type; - guint node_edge; + unsigned int node_edge; bool set; Geom::Point p; - guint draggable; // index of on-screen node - gchar path_type; + unsigned int draggable; // index of on-screen node + char path_type; SPColor color; - gdouble opacity; + double opacity; }; @@ -110,21 +108,21 @@ private: public: SPMeshPatchI( std::vector > *n, int r, int c ); - Geom::Point getPoint( guint side, guint point ); - std::vector< Geom::Point > getPointsForSide( guint i ); - void setPoint( guint side, guint point, Geom::Point p, bool set = true ); - gchar getPathType( guint i ); - void setPathType( guint, gchar t ); - Geom::Point getTensorPoint( guint i ); - void setTensorPoint( guint i, Geom::Point p ); + Geom::Point getPoint( unsigned int side, unsigned int point ); + std::vector< Geom::Point > getPointsForSide( unsigned int i ); + void setPoint( unsigned int side, unsigned int point, Geom::Point p, bool set = true ); + char getPathType( unsigned int i ); + void setPathType( unsigned int, char t ); + Geom::Point getTensorPoint( unsigned int i ); + void setTensorPoint( unsigned int i, Geom::Point p ); bool tensorIsSet(); - bool tensorIsSet( guint i ); - Geom::Point coonsTensorPoint( guint i ); + bool tensorIsSet( unsigned int i ); + Geom::Point coonsTensorPoint( unsigned int i ); void updateNodes(); - SPColor getColor( guint i ); - void setColor( guint i, SPColor c ); - gdouble getOpacity( guint i ); - void setOpacity( guint i, gdouble o ); + SPColor getColor( unsigned int i ); + void setColor( unsigned int i, SPColor c ); + double getOpacity( unsigned int i ); + void setOpacity( unsigned int i, double o ); }; class SPMeshGradient; @@ -160,26 +158,26 @@ public: void print(); // Get size of patch - guint patch_rows(); - guint patch_columns(); + unsigned int patch_rows(); + unsigned int patch_columns(); - SPMeshNode * node( guint i, guint j ) { return nodes[i][j]; } + SPMeshNode * node( unsigned int i, unsigned int j ) { return nodes[i][j]; } // Operations on corners - bool adjacent_corners( guint i, guint j, SPMeshNode* n[4] ); - guint side_toggle( std::vector< guint > ); - guint side_arc( std::vector< guint > ); - guint tensor_toggle( std::vector< guint > ); - guint color_smooth( std::vector< guint > ); - guint color_pick( std::vector< guint >, SPItem* ); + bool adjacent_corners( unsigned int i, unsigned int j, SPMeshNode* n[4] ); + unsigned int side_toggle( std::vector< unsigned int > ); + unsigned int side_arc( std::vector< unsigned int > ); + unsigned int tensor_toggle( std::vector< unsigned int > ); + unsigned int color_smooth( std::vector< unsigned int > ); + unsigned int color_pick( std::vector< unsigned int >, SPItem* ); // Update other nodes in response to a node move. - void update_handles( guint corner, std::vector< guint > selected_corners, Geom::Point old_p, MeshNodeOperation op ); + void update_handles( unsigned int corner, std::vector< unsigned int > selected_corners, Geom::Point old_p, MeshNodeOperation op ); - void split_row( guint i, guint n ); - void split_column( guint j, guint n ); - void split_row( guint i, double coord ); - void split_column( guint j, double coord ); + void split_row( unsigned int i, unsigned int n ); + void split_column( unsigned int j, unsigned int n ); + void split_row( unsigned int i, double coord ); + void split_column( unsigned int j, double coord ); }; #endif /* !SEEN_SP_MESH_ARRAY_H */ diff --git a/src/sp-mesh-gradient.h b/src/sp-mesh-gradient.h index 0b570c4dd..4df753f62 100644 --- a/src/sp-mesh-gradient.h +++ b/src/sp-mesh-gradient.h @@ -24,8 +24,8 @@ public: protected: virtual void build(SPDocument *document, Inkscape::XML::Node *repr); - virtual void set(unsigned key, gchar const *value); - virtual Inkscape::XML::Node* write(Inkscape::XML::Document *xml_doc, Inkscape::XML::Node *repr, guint flags); + virtual void set(unsigned key, char const *value); + virtual Inkscape::XML::Node* write(Inkscape::XML::Document *xml_doc, Inkscape::XML::Node *repr, unsigned int flags); }; #endif /* !SP_MESH_GRADIENT_H */ diff --git a/src/sp-mesh-patch.h b/src/sp-mesh-patch.h index ddade6503..e57ad1699 100644 --- a/src/sp-mesh-patch.h +++ b/src/sp-mesh-patch.h @@ -12,9 +12,7 @@ * Released under GNU GPL, read the file 'COPYING' for more information */ -#include #include -//#include "svg/svg-length.h" #include "sp-object.h" #define SP_MESHPATCH(obj) (dynamic_cast((SPObject*)obj)) @@ -34,8 +32,8 @@ public: protected: virtual void build(SPDocument* doc, Inkscape::XML::Node* repr); - virtual void set(unsigned int key, const gchar* value); - virtual Inkscape::XML::Node* write(Inkscape::XML::Document* doc, Inkscape::XML::Node* repr, guint flags); + virtual void set(unsigned int key, const char* value); + virtual Inkscape::XML::Node* write(Inkscape::XML::Document* doc, Inkscape::XML::Node* repr, unsigned int flags); }; #endif /* !SEEN_SP_MESHPATCH_H */ diff --git a/src/sp-mesh-row.h b/src/sp-mesh-row.h index e39bdc631..793b5a645 100644 --- a/src/sp-mesh-row.h +++ b/src/sp-mesh-row.h @@ -11,7 +11,6 @@ * Released under GNU GPL, read the file 'COPYING' for more information */ -#include #include "sp-object.h" #define SP_MESHROW(obj) (dynamic_cast((SPObject*)obj)) @@ -28,8 +27,8 @@ public: protected: virtual void build(SPDocument* doc, Inkscape::XML::Node* repr); - virtual void set(unsigned int key, const gchar* value); - virtual Inkscape::XML::Node* write(Inkscape::XML::Document* doc, Inkscape::XML::Node* repr, guint flags); + virtual void set(unsigned int key, const char* value); + virtual Inkscape::XML::Node* write(Inkscape::XML::Document* doc, Inkscape::XML::Node* repr, unsigned int flags); }; #endif /* !SEEN_SP_MESHROW_H */ diff --git a/src/sp-metadata.h b/src/sp-metadata.h index 2a9d58e11..a89020390 100644 --- a/src/sp-metadata.h +++ b/src/sp-metadata.h @@ -1,5 +1,5 @@ -#ifndef __SP_METADATA_H__ -#define __SP_METADATA_H__ +#ifndef SEEN_SP_METADATA_H +#define SEEN_SP_METADATA_H /* * SVG implementation @@ -14,7 +14,6 @@ #include "sp-object.h" - /* Metadata base class */ #define SP_METADATA(obj) (dynamic_cast((SPObject*)obj)) @@ -29,9 +28,9 @@ protected: virtual void build(SPDocument* doc, Inkscape::XML::Node* repr); virtual void release(); - virtual void set(unsigned int key, const gchar* value); + virtual void set(unsigned int key, const char* value); virtual void update(SPCtx* ctx, unsigned int flags); - virtual Inkscape::XML::Node* write(Inkscape::XML::Document* doc, Inkscape::XML::Node* repr, guint flags); + virtual Inkscape::XML::Node* write(Inkscape::XML::Document* doc, Inkscape::XML::Node* repr, unsigned int flags); }; SPMetadata * sp_document_metadata (SPDocument *document); diff --git a/src/sp-missing-glyph.h b/src/sp-missing-glyph.h index a72ed0e99..06bc92231 100644 --- a/src/sp-missing-glyph.h +++ b/src/sp-missing-glyph.h @@ -1,9 +1,5 @@ -#ifdef HAVE_CONFIG_H -# include -#endif - -#ifndef __SP_MISSING_GLYPH_H__ -#define __SP_MISSING_GLYPH_H__ +#ifndef SEEN_SP_MISSING_GLYPH_H +#define SEEN_SP_MISSING_GLYPH_H /* * SVG element implementation @@ -31,8 +27,8 @@ public: protected: virtual void build(SPDocument* doc, Inkscape::XML::Node* repr); virtual void release(); - virtual void set(unsigned int key, const gchar* value); - virtual Inkscape::XML::Node* write(Inkscape::XML::Document* doc, Inkscape::XML::Node* repr, guint flags); + virtual void set(unsigned int key, char const* value); + virtual Inkscape::XML::Node* write(Inkscape::XML::Document* doc, Inkscape::XML::Node* repr, unsigned int flags); private: double horiz_adv_x; diff --git a/src/sp-namedview.cpp b/src/sp-namedview.cpp index a01ba891e..1d9fa06a3 100644 --- a/src/sp-namedview.cpp +++ b/src/sp-namedview.cpp @@ -935,7 +935,7 @@ void SPNamedView::hide(SPDesktop const *desktop) views = g_slist_remove(views, desktop); } -void SPNamedView::activateGuides(gpointer desktop, gboolean active) +void SPNamedView::activateGuides(void* desktop, bool active) { g_assert(desktop != NULL); g_assert(g_slist_find(views, desktop)); diff --git a/src/sp-namedview.h b/src/sp-namedview.h index 05cbcc398..37310dc76 100644 --- a/src/sp-namedview.h +++ b/src/sp-namedview.h @@ -29,6 +29,9 @@ namespace Inkscape { } } +typedef unsigned int guint32; +typedef guint32 GQuark; + enum { SP_BORDER_LAYER_BOTTOM, SP_BORDER_LAYER_TOP @@ -48,11 +51,11 @@ public: double zoom; double cx; double cy; - gint window_width; - gint window_height; - gint window_x; - gint window_y; - gint window_maximized; + int window_width; + int window_height; + int window_x; + int window_y; + int window_maximized; SnapManager snap_manager; GSList * grids; @@ -74,13 +77,13 @@ public: GSList *guides; GSList *views; - gint viewcount; + int viewcount; void show(SPDesktop *desktop); void hide(SPDesktop const *desktop); - void activateGuides(gpointer desktop, gboolean active); - gchar const *getName() const; - guint getViewCount(); + void activateGuides(void* desktop, bool active); + char const *getName() const; + unsigned int getViewCount(); GSList const *getViewList() const; Inkscape::Util::Unit const * getDefaultUnit() const; @@ -100,17 +103,17 @@ private: protected: virtual void build(SPDocument *document, Inkscape::XML::Node *repr); virtual void release(); - virtual void set(unsigned int key, gchar const* value); + virtual void set(unsigned int key, char const* value); virtual void child_added(Inkscape::XML::Node* child, Inkscape::XML::Node* ref); virtual void remove_child(Inkscape::XML::Node* child); - virtual Inkscape::XML::Node* write(Inkscape::XML::Document *xml_doc, Inkscape::XML::Node *repr, guint flags); + virtual Inkscape::XML::Node* write(Inkscape::XML::Document *xml_doc, Inkscape::XML::Node *repr, unsigned int flags); }; -SPNamedView *sp_document_namedview(SPDocument *document, gchar const *name); -SPNamedView const *sp_document_namedview(SPDocument const *document, gchar const *name); +SPNamedView *sp_document_namedview(SPDocument *document, char const *name); +SPNamedView const *sp_document_namedview(SPDocument const *document, char const *name); void sp_namedview_window_from_document(SPDesktop *desktop); void sp_namedview_document_from_window(SPDesktop *desktop); diff --git a/src/sp-object-group.h b/src/sp-object-group.h index 4df346228..dcaa8a1d0 100644 --- a/src/sp-object-group.h +++ b/src/sp-object-group.h @@ -30,7 +30,7 @@ protected: virtual void order_changed(Inkscape::XML::Node* child, Inkscape::XML::Node* old, Inkscape::XML::Node* new_repr); - virtual Inkscape::XML::Node* write(Inkscape::XML::Document *xml_doc, Inkscape::XML::Node *repr, guint flags); + virtual Inkscape::XML::Node* write(Inkscape::XML::Document *xml_doc, Inkscape::XML::Node *repr, unsigned int flags); }; #endif // SEEN_SP_OBJECTGROUP_H diff --git a/src/sp-object.cpp b/src/sp-object.cpp index 65228ec0a..fcff43aa5 100644 --- a/src/sp-object.cpp +++ b/src/sp-object.cpp @@ -1406,12 +1406,12 @@ bool SPObject::setDesc(gchar const *desc, bool verbatim) return setTitleOrDesc(desc, "svg:desc", verbatim); } -gchar * SPObject::getTitleOrDesc(gchar const *svg_tagname) const +char * SPObject::getTitleOrDesc(gchar const *svg_tagname) const { - gchar *result = 0; + char *result = NULL; SPObject *elem = findFirstChild(svg_tagname); if ( elem ) { - result = g_string_free(elem->textualContent(), FALSE); + result = elem->textualContent(); } return result; } @@ -1493,7 +1493,7 @@ SPObject * SPObject::findFirstChild(gchar const *tagname) const return NULL; } -GString * SPObject::textualContent() const +char* SPObject::textualContent() const { GString* text = g_string_new(""); @@ -1502,15 +1502,15 @@ GString * SPObject::textualContent() const Inkscape::XML::NodeType child_type = child->repr->type(); if (child_type == Inkscape::XML::ELEMENT_NODE) { - GString * new_text = child->textualContent(); - g_string_append(text, new_text->str); - g_string_free(new_text, TRUE); + char* new_string = child->textualContent(); + g_string_append(text, new_string); + g_free(new_string); } else if (child_type == Inkscape::XML::TEXT_NODE) { g_string_append(text, child->repr->content()); } } - return text; + return g_string_free(text, FALSE); } /* diff --git a/src/sp-object.h b/src/sp-object.h index 21926ad90..423f6ba37 100644 --- a/src/sp-object.h +++ b/src/sp-object.h @@ -153,7 +153,7 @@ SPObject *sp_object_unref(SPObject *object, SPObject *owner=NULL); * \pre object points to real object * @todo need to move this to be a member of SPObject. */ -SPObject *sp_object_href(SPObject *object, gpointer owner); +SPObject *sp_object_href(SPObject *object, void* owner); /** * Decrease weak refcount. @@ -165,7 +165,7 @@ SPObject *sp_object_href(SPObject *object, gpointer owner); * \pre object points to real object and hrefcount>0 * @todo need to move this to be a member of SPObject. */ -SPObject *sp_object_hunref(SPObject *object, gpointer owner); +SPObject *sp_object_hunref(SPObject *object, void* owner); /** * SPObject is an abstract base class of all of the document nodes at the @@ -795,7 +795,7 @@ private: * content except the tags). * Must not be used on anything except elements. */ - GString * textualContent() const; + char * textualContent() const; /* Real handlers of repr signals */ @@ -803,17 +803,17 @@ public: /** * Callback for attr_changed node event. */ - static void repr_attr_changed(Inkscape::XML::Node *repr, char const *key, char const *oldval, char const *newval, bool is_interactive, gpointer data); + static void repr_attr_changed(Inkscape::XML::Node *repr, char const *key, char const *oldval, char const *newval, bool is_interactive, void* data); /** * Callback for content_changed node event. */ - static void repr_content_changed(Inkscape::XML::Node *repr, char const *oldcontent, char const *newcontent, gpointer data); + static void repr_content_changed(Inkscape::XML::Node *repr, char const *oldcontent, char const *newcontent, void* data); /** * Callback for child_added node event. */ - static void repr_child_added(Inkscape::XML::Node *repr, Inkscape::XML::Node *child, Inkscape::XML::Node *ref, gpointer data); + static void repr_child_added(Inkscape::XML::Node *repr, Inkscape::XML::Node *child, Inkscape::XML::Node *ref, void* data); /** * Callback for remove_child node event. @@ -825,7 +825,7 @@ public: * * \todo fixme: */ - static void repr_order_changed(Inkscape::XML::Node *repr, Inkscape::XML::Node *child, Inkscape::XML::Node *old, Inkscape::XML::Node *newer, gpointer data); + static void repr_order_changed(Inkscape::XML::Node *repr, Inkscape::XML::Node *child, Inkscape::XML::Node *old, Inkscape::XML::Node *newer, void* data); friend class SPObjectImpl; diff --git a/src/sp-offset.h b/src/sp-offset.h index 259a69b78..eb3fe227c 100644 --- a/src/sp-offset.h +++ b/src/sp-offset.h @@ -11,11 +11,11 @@ * Released under GNU GPL, read the file 'COPYING' for more information */ -#include "sp-shape.h" - -#include +#include #include +#include "sp-shape.h" + #define SP_OFFSET(obj) (dynamic_cast((SPObject*)obj)) #define SP_IS_OFFSET(obj) (dynamic_cast((SPObject*)obj) != NULL) @@ -54,7 +54,7 @@ public: SPOffset(); virtual ~SPOffset(); - void *originalPath; ///< will be a livarot Path, just don't declare it here to please the gcc linker + void *originalPath; ///< will be a livarot Path, just don't declare it here to please the gcc linker FIXME what? char *original; ///< SVG description of the source path float rad; ///< offset radius @@ -65,7 +65,7 @@ public: bool sourceDirty; bool isUpdating; - gchar *sourceHref; + char *sourceHref; SPUseReference *sourceRef; Inkscape::XML::Node *sourceRepr; ///< the repr associated with that id SPObject *sourceObject; @@ -76,14 +76,14 @@ public: sigc::connection _transformed_connection; virtual void build(SPDocument *document, Inkscape::XML::Node *repr); - virtual void set(unsigned int key, gchar const* value); - virtual void update(SPCtx *ctx, guint flags); - virtual Inkscape::XML::Node* write(Inkscape::XML::Document *xml_doc, Inkscape::XML::Node *repr, guint flags); + virtual void set(unsigned int key, char const* value); + virtual void update(SPCtx *ctx, unsigned int flags); + virtual Inkscape::XML::Node* write(Inkscape::XML::Document *xml_doc, Inkscape::XML::Node *repr, unsigned flags); virtual void release(); virtual void snappoints(std::vector &p, Inkscape::SnapPreferences const *snapprefs) const; virtual const char* displayName() const; - virtual gchar* description() const; + virtual char* description() const; virtual void set_shape(); }; diff --git a/src/sp-paint-server-reference.h b/src/sp-paint-server-reference.h index e08694c2f..bbd9c25fa 100644 --- a/src/sp-paint-server-reference.h +++ b/src/sp-paint-server-reference.h @@ -15,9 +15,10 @@ * Released under GNU GPL, read the file 'COPYING' for more information */ -#include "sp-object.h" #include "uri-references.h" +class SPDocument; +class SPObject; class SPPaintServer; class SPPaintServerReference : public Inkscape::URIReference { diff --git a/src/sp-paint-server.h b/src/sp-paint-server.h index c1c8d651e..beac72af5 100644 --- a/src/sp-paint-server.h +++ b/src/sp-paint-server.h @@ -15,10 +15,12 @@ * Released under GNU GPL, read the file 'COPYING' for more information */ -#include #include <2geom/rect.h> #include "sp-object.h" +typedef struct _cairo cairo_t; +typedef struct _cairo_pattern cairo_pattern_t; + #define SP_PAINT_SERVER(obj) (dynamic_cast((SPObject*)obj)) #define SP_IS_PAINT_SERVER(obj) (dynamic_cast((SPObject*)obj) != NULL) diff --git a/src/sp-path.h b/src/sp-path.h index 5f8a91d98..572fd648d 100644 --- a/src/sp-path.h +++ b/src/sp-path.h @@ -32,7 +32,7 @@ public: SPPath(); virtual ~SPPath(); - gint nodesInPath() const; + int nodesInPath() const; // still in lowercase because the names should be clearer on whether curve, curve->copy or curve-ref is returned. void set_original_curve (SPCurve *curve, unsigned int owner, bool write); @@ -49,13 +49,13 @@ public: virtual void build(SPDocument *document, Inkscape::XML::Node *repr); virtual void release(); - virtual void update(SPCtx* ctx, guint flags); + virtual void update(SPCtx* ctx, unsigned int flags); - virtual void set(unsigned int key, gchar const* value); - virtual Inkscape::XML::Node* write(Inkscape::XML::Document *xml_doc, Inkscape::XML::Node *repr, guint flags); + virtual void set(unsigned int key, char const* value); + virtual Inkscape::XML::Node* write(Inkscape::XML::Document *xml_doc, Inkscape::XML::Node *repr, unsigned int flags); virtual const char* displayName() const; - virtual gchar* description() const; + virtual char* description() const; virtual Geom::Affine set_transform(Geom::Affine const &transform); virtual void convert_to_guides() const; diff --git a/src/sp-pattern.h b/src/sp-pattern.h index 8f7dbbadd..f021101e2 100644 --- a/src/sp-pattern.h +++ b/src/sp-pattern.h @@ -18,6 +18,7 @@ class SPPatternReference; class SPItem; +typedef struct _GSList GSList; #include "svg/svg-length.h" #include "sp-paint-server.h" @@ -33,17 +34,17 @@ public: virtual ~SPPattern(); /* Reference (href) */ - gchar *href; + char *href; SPPatternReference *ref; /* patternUnits and patternContentUnits attribute */ - guint patternUnits : 1; - guint patternUnits_set : 1; - guint patternContentUnits : 1; - guint patternContentUnits_set : 1; + unsigned int patternUnits : 1; + unsigned int patternUnits_set : 1; + unsigned int patternContentUnits : 1; + unsigned int patternContentUnits_set : 1; /* patternTransform attribute */ Geom::Affine patternTransform; - guint patternTransform_set : 1; + unsigned int patternTransform_set : 1; /* Tile rectangle */ SVGLength x; SVGLength y; @@ -83,22 +84,22 @@ enum { SP_PATTERN_UNITS_OBJECTBOUNDINGBOX }; -guint pattern_users (SPPattern *pattern); +unsigned int pattern_users (SPPattern *pattern); SPPattern *pattern_chain (SPPattern *pattern); -SPPattern *sp_pattern_clone_if_necessary (SPItem *item, SPPattern *pattern, const gchar *property); +SPPattern *sp_pattern_clone_if_necessary (SPItem *item, SPPattern *pattern, const char *property); void sp_pattern_transform_multiply (SPPattern *pattern, Geom::Affine postmul, bool set); -const gchar *pattern_tile (GSList *reprs, Geom::Rect bounds, SPDocument *document, Geom::Affine transform, Geom::Affine move); +const char *pattern_tile (GSList *reprs, Geom::Rect bounds, SPDocument *document, Geom::Affine transform, Geom::Affine move); SPPattern *pattern_getroot (SPPattern *pat); -guint pattern_patternUnits (SPPattern const *pat); -guint pattern_patternContentUnits (SPPattern const *pat); +unsigned int pattern_patternUnits (SPPattern const *pat); +unsigned int pattern_patternContentUnits (SPPattern const *pat); Geom::Affine const &pattern_patternTransform(SPPattern const *pat); -gdouble pattern_x (SPPattern const *pat); -gdouble pattern_y (SPPattern const *pat); -gdouble pattern_width (SPPattern const *pat); -gdouble pattern_height (SPPattern const *pat); +double pattern_x (SPPattern const *pat); +double pattern_y (SPPattern const *pat); +double pattern_width (SPPattern const *pat); +double pattern_height (SPPattern const *pat); Geom::OptRect pattern_viewBox (SPPattern const *pat); #endif // SEEN_SP_PATTERN_H diff --git a/src/sp-polygon.h b/src/sp-polygon.h index 41ab245bd..438fdf794 100644 --- a/src/sp-polygon.h +++ b/src/sp-polygon.h @@ -1,5 +1,5 @@ -#ifndef __SP_POLYGON_H__ -#define __SP_POLYGON_H__ +#ifndef SEEN_SP_POLYGON_H +#define SEEN_SP_POLYGON_H /* * SVG implementation @@ -15,7 +15,6 @@ #include "sp-shape.h" - #define SP_POLYGON(obj) (dynamic_cast((SPObject*)obj)) #define SP_IS_POLYGON(obj) (dynamic_cast((SPObject*)obj) != NULL) @@ -25,12 +24,12 @@ public: virtual ~SPPolygon(); virtual void build(SPDocument *document, Inkscape::XML::Node *repr); - virtual Inkscape::XML::Node* write(Inkscape::XML::Document *xml_doc, Inkscape::XML::Node *repr, guint flags); - virtual void set(unsigned int key, gchar const* value); - virtual gchar* description() const; + virtual Inkscape::XML::Node* write(Inkscape::XML::Document *xml_doc, Inkscape::XML::Node *repr, unsigned int flags); + virtual void set(unsigned int key, char const* value); + virtual char* description() const; }; // made 'public' so that SPCurve can set it as friend: -void sp_polygon_set(SPObject *object, unsigned int key, const gchar *value); +void sp_polygon_set(SPObject *object, unsigned int key, char const*value); #endif diff --git a/src/sp-polyline.h b/src/sp-polyline.h index e24ea95c7..1ca102a9e 100644 --- a/src/sp-polyline.h +++ b/src/sp-polyline.h @@ -12,10 +12,10 @@ public: virtual ~SPPolyLine(); virtual void build(SPDocument* doc, Inkscape::XML::Node* repr); - virtual void set(unsigned int key, gchar const* value); - virtual Inkscape::XML::Node* write(Inkscape::XML::Document *xml_doc, Inkscape::XML::Node *repr, guint flags); + virtual void set(unsigned int key, char const* value); + virtual Inkscape::XML::Node* write(Inkscape::XML::Document *xml_doc, Inkscape::XML::Node *repr, unsigned int flags); - virtual gchar* description() const; + virtual char* description() const; }; #endif // SEEN_SP_POLYLINE_H diff --git a/src/sp-radial-gradient.cpp b/src/sp-radial-gradient.cpp index 7c481fead..2c2b17b7d 100644 --- a/src/sp-radial-gradient.cpp +++ b/src/sp-radial-gradient.cpp @@ -1,3 +1,5 @@ +#include + #include "sp-radial-gradient.h" #include "attributes.h" diff --git a/src/sp-radial-gradient.h b/src/sp-radial-gradient.h index 42ff109aa..f753623b7 100644 --- a/src/sp-radial-gradient.h +++ b/src/sp-radial-gradient.h @@ -5,10 +5,12 @@ * SPRadialGradient: SVG implementtion. */ -#include #include "sp-gradient.h" #include "svg/svg-length.h" +typedef struct _cairo cairo_t; +typedef struct _cairo_pattern cairo_pattern_t; + #define SP_RADIALGRADIENT(obj) (dynamic_cast((SPObject*)obj)) #define SP_IS_RADIALGRADIENT(obj) (dynamic_cast((SPObject*)obj) != NULL) @@ -28,8 +30,8 @@ public: protected: virtual void build(SPDocument *document, Inkscape::XML::Node *repr); - virtual void set(unsigned key, gchar const *value); - virtual Inkscape::XML::Node* write(Inkscape::XML::Document *xml_doc, Inkscape::XML::Node *repr, guint flags); + virtual void set(unsigned key, char const *value); + virtual Inkscape::XML::Node* write(Inkscape::XML::Document *xml_doc, Inkscape::XML::Node *repr, unsigned int flags); }; #endif /* !SP_RADIAL_GRADIENT_H */ diff --git a/src/sp-rect.h b/src/sp-rect.h index aa3f88e42..757229724 100644 --- a/src/sp-rect.h +++ b/src/sp-rect.h @@ -14,10 +14,10 @@ * Released under GNU GPL, read the file 'COPYING' for more information */ -#include "svg/svg-length.h" -#include "sp-shape.h" #include <2geom/forward.h> +#include "svg/svg-length.h" +#include "sp-shape.h" #define SP_RECT(obj) (dynamic_cast((SPObject*)obj)) #define SP_IS_RECT(obj) (dynamic_cast((SPObject*)obj) != NULL) @@ -27,34 +27,34 @@ public: SPRect(); virtual ~SPRect(); - void setPosition(gdouble x, gdouble y, gdouble width, gdouble height); + void setPosition(double x, double y, double width, double height); /* If SET if FALSE, VALUE is just ignored */ - void setRx(bool set, gdouble value); - void setRy(bool set, gdouble value); + void setRx(bool set, double value); + void setRy(bool set, double value); - gdouble getVisibleRx() const; - void setVisibleRx(gdouble rx); + double getVisibleRx() const; + void setVisibleRx(double rx); - gdouble getVisibleRy() const; - void setVisibleRy(gdouble ry); + double getVisibleRy() const; + void setVisibleRy(double ry); Geom::Rect getRect() const; - gdouble getVisibleWidth() const; - void setVisibleWidth(gdouble rx); + double getVisibleWidth() const; + void setVisibleWidth(double rx); - gdouble getVisibleHeight() const; - void setVisibleHeight(gdouble ry); + double getVisibleHeight() const; + void setVisibleHeight(double ry); void compensateRxRy(Geom::Affine xform); virtual void build(SPDocument* doc, Inkscape::XML::Node* repr); - virtual void set(unsigned key, gchar const *value); + virtual void set(unsigned key, char const *value); virtual void update(SPCtx* ctx, unsigned int flags); - virtual Inkscape::XML::Node* write(Inkscape::XML::Document *xml_doc, Inkscape::XML::Node *repr, guint flags); + virtual Inkscape::XML::Node* write(Inkscape::XML::Document *xml_doc, Inkscape::XML::Node *repr, unsigned int flags); virtual const char* displayName() const; virtual void set_shape(); @@ -71,7 +71,7 @@ public: SVGLength ry; private: - static gdouble vectorStretch(Geom::Point p0, Geom::Point p1, Geom::Affine xform); + static double vectorStretch(Geom::Point p0, Geom::Point p1, Geom::Affine xform); }; #endif // SEEN_SP_RECT_H diff --git a/src/sp-root.h b/src/sp-root.h index a25e8030c..2776ae887 100644 --- a/src/sp-root.h +++ b/src/sp-root.h @@ -40,7 +40,7 @@ public: SVGLength width; SVGLength height; - gchar *onload; + char *onload; /** * Primary \ element where we put new defs (patterns, gradients etc.). @@ -52,9 +52,9 @@ public: virtual void build(SPDocument *document, Inkscape::XML::Node *repr); virtual void release(); - virtual void set(unsigned int key, gchar const* value); - virtual void update(SPCtx *ctx, guint flags); - virtual Inkscape::XML::Node* write(Inkscape::XML::Document *xml_doc, Inkscape::XML::Node *repr, guint flags); + virtual void set(unsigned int key, char const* value); + virtual void update(SPCtx *ctx, unsigned int flags); + virtual Inkscape::XML::Node* write(Inkscape::XML::Document *xml_doc, Inkscape::XML::Node *repr, unsigned int flags); virtual void modified(unsigned int flags); virtual void child_added(Inkscape::XML::Node* child, Inkscape::XML::Node* ref); diff --git a/src/sp-script.h b/src/sp-script.h index 36072a0ca..b71f86720 100644 --- a/src/sp-script.h +++ b/src/sp-script.h @@ -1,5 +1,5 @@ -#ifndef __SP_SCRIPT_H__ -#define __SP_SCRIPT_H__ +#ifndef SEEN_SP_SCRIPT_H +#define SEEN_SP_SCRIPT_H /* * SVG