diff options
| author | Michael Soegtrop <MSoegtrop@yahoo.de> | 2016-05-23 20:36:18 +0000 |
|---|---|---|
| committer | Michael Soegtrop <MSoegtrop@yahoo.de> | 2016-05-23 20:36:18 +0000 |
| commit | 9b667f5ad22543b88067107425ec55ef972e2ff0 (patch) | |
| tree | 933384cbb74b5bca4c94417e1ebd6270688bbb9a /src | |
| parent | Added bool LPE (diff) | |
| parent | Fix regression: restore order in resources (e.g. pattern list) (diff) | |
| download | inkscape-9b667f5ad22543b88067107425ec55ef972e2ff0.tar.gz inkscape-9b667f5ad22543b88067107425ec55ef972e2ff0.zip | |
Fixed Bool LPE review issues
(bzr r14876.2.2)
Diffstat (limited to 'src')
46 files changed, 912 insertions, 554 deletions
diff --git a/src/2geom/elliptical-arc.cpp b/src/2geom/elliptical-arc.cpp index a0e379a21..ec62b4be2 100644 --- a/src/2geom/elliptical-arc.cpp +++ b/src/2geom/elliptical-arc.cpp @@ -570,13 +570,13 @@ void EllipticalArc::_filterIntersections(std::vector<ShapeIntersection> &xs, boo std::vector<ShapeIntersection>::reverse_iterator i = xs.rbegin(), last = xs.rend(); while (i != last) { Coord &t = is_first ? i->first : i->second; - assert(are_near(_ellipse.pointAt(t), i->point(), 1e-6)); + assert(are_near(_ellipse.pointAt(t), i->point(), 1e-5)); t = timeAtAngle(t); if (!unit.contains(t)) { xs.erase((++i).base()); continue; } else { - assert(are_near(pointAt(t), i->point(), 1e-6)); + assert(are_near(pointAt(t), i->point(), 1e-5)); ++i; } } diff --git a/src/color-profile.cpp b/src/color-profile.cpp index bcefe994a..523026aa5 100644 --- a/src/color-profile.cpp +++ b/src/color-profile.cpp @@ -489,8 +489,8 @@ static int getLcmsIntent( guint svgIntent ) static SPObject* bruteFind( SPDocument* document, gchar const* name ) { SPObject* result = 0; - std::set<SPObject *> current = document->getResourceList("iccprofile"); - for (std::set<SPObject *>::const_iterator it = current.begin(); (!result) && (it != current.end()); ++it) { + std::vector<SPObject *> current = document->getResourceList("iccprofile"); + for (std::vector<SPObject *>::const_iterator it = current.begin(); (!result) && (it != current.end()); ++it) { if ( IS_COLORPROFILE(*it) ) { ColorProfile* prof = COLORPROFILE(*it); if ( prof ) { diff --git a/src/document-private.h b/src/document-private.h index eaed0020e..9cac8fac6 100644 --- a/src/document-private.h +++ b/src/document-private.h @@ -49,7 +49,7 @@ struct SPDocumentPrivate { IDChangedSignalMap id_changed_signals; /* Resources */ - std::map<std::string, std::set<SPObject *> > resources; + std::map<std::string, std::vector<SPObject *> > resources; ResourcesChangedSignalMap resources_changed_signals; sigc::signal<void> destroySignal; diff --git a/src/document.cpp b/src/document.cpp index 7086fc0be..2500a5cee 100644 --- a/src/document.cpp +++ b/src/document.cpp @@ -1541,9 +1541,9 @@ bool SPDocument::addResource(gchar const *key, SPObject *object) bool result = false; if ( !object->cloned ) { - std::set<SPObject *> rlist = priv->resources[key]; - g_return_val_if_fail(rlist.find(object) == rlist.end(), false); - priv->resources[key].insert(object); + std::vector<SPObject *> rlist = priv->resources[key]; + g_return_val_if_fail(std::find(rlist.begin(),rlist.end(),object) == rlist.end(), false); + priv->resources[key].insert(priv->resources[key].begin(),object); GQuark q = g_quark_from_string(key); @@ -1572,10 +1572,11 @@ bool SPDocument::removeResource(gchar const *key, SPObject *object) bool result = false; if ( !object->cloned ) { - std::set<SPObject *> rlist = priv->resources[key]; + std::vector<SPObject *> rlist = priv->resources[key]; g_return_val_if_fail(!rlist.empty(), false); - g_return_val_if_fail(rlist.find(object) != rlist.end(), false); - priv->resources[key].erase(object); + std::vector<SPObject*>::iterator it = std::find(priv->resources[key].begin(),priv->resources[key].end(),object); + g_return_val_if_fail(it != rlist.end(), false); + priv->resources[key].erase(it); GQuark q = g_quark_from_string(key); priv->resources_changed_signals[q].emit(); @@ -1586,9 +1587,9 @@ bool SPDocument::removeResource(gchar const *key, SPObject *object) return result; } -std::set<SPObject *> const SPDocument::getResourceList(gchar const *key) const +std::vector<SPObject *> const SPDocument::getResourceList(gchar const *key) const { - std::set<SPObject *> emptyset; + std::vector<SPObject *> emptyset; g_return_val_if_fail(key != NULL, emptyset); g_return_val_if_fail(*key != '\0', emptyset); diff --git a/src/document.h b/src/document.h index 825049cd5..653e9d0db 100644 --- a/src/document.h +++ b/src/document.h @@ -260,7 +260,7 @@ public: int ensureUpToDate(); bool addResource(char const *key, SPObject *object); bool removeResource(char const *key, SPObject *object); - const std::set<SPObject *> getResourceList(char const *key) const; + const std::vector<SPObject *> getResourceList(char const *key) const; std::vector<SPItem*> getItemsInBox(unsigned int dkey, Geom::Rect const &box, bool into_groups = false) const; std::vector<SPItem*> getItemsPartiallyInBox(unsigned int dkey, Geom::Rect const &box, bool into_groups = false) const; SPItem *getItemAtPoint(unsigned int key, Geom::Point const &p, bool into_groups, SPItem *upto = NULL) const; diff --git a/src/gradient-chemistry.cpp b/src/gradient-chemistry.cpp index 7b4c0ac20..edeb523d7 100644 --- a/src/gradient-chemistry.cpp +++ b/src/gradient-chemistry.cpp @@ -1612,8 +1612,8 @@ void sp_gradient_unset_swatch(SPDesktop *desktop, std::string id) SPDocument *doc = desktop ? desktop->doc() : 0; if (doc) { - const std::set<SPObject *> gradients = doc->getResourceList("gradient"); - for (std::set<SPObject *>::const_iterator i = gradients.begin(); i != gradients.end(); ++i) { + const std::vector<SPObject *> gradients = doc->getResourceList("gradient"); + for (std::vector<SPObject *>::const_iterator i = gradients.begin(); i != gradients.end(); ++i) { SPGradient* grad = SP_GRADIENT(*i); if ( id == grad->getId() ) { grad->setSwatch(false); diff --git a/src/gradient-drag.cpp b/src/gradient-drag.cpp index 8fd997121..613dc2fc1 100644 --- a/src/gradient-drag.cpp +++ b/src/gradient-drag.cpp @@ -208,8 +208,8 @@ Glib::ustring GrDrag::makeStopSafeColor( gchar const *str, bool &isNull ) Glib::ustring::size_type pos = colorStr.find("url(#"); if ( pos != Glib::ustring::npos ) { Glib::ustring targetName = colorStr.substr(pos + 5, colorStr.length() - 6); - std::set<SPObject *> gradients = desktop->doc()->getResourceList("gradient"); - for (std::set<SPObject *>::const_iterator it = gradients.begin(); it != gradients.end(); ++it) { + std::vector<SPObject *> gradients = desktop->doc()->getResourceList("gradient"); + for (std::vector<SPObject *>::const_iterator it = gradients.begin(); it != gradients.end(); ++it) { SPGradient* grad = SP_GRADIENT(*it); if ( targetName == grad->getId() ) { SPGradient *vect = grad->getVector(); diff --git a/src/layer-manager.cpp b/src/layer-manager.cpp index c0fe95dd7..19c4b890c 100644 --- a/src/layer-manager.cpp +++ b/src/layer-manager.cpp @@ -191,10 +191,10 @@ Glib::ustring LayerManager::getNextLayerName( SPObject* obj, gchar const *label) } std::set<Glib::ustring> currentNames; - std::set<SPObject *> layers = _document->getResourceList("layer"); + std::vector<SPObject *> layers = _document->getResourceList("layer"); SPObject *root=_desktop->currentRoot(); if ( root ) { - for (std::set<SPObject *>::const_iterator iter = layers.begin(); iter != layers.end(); ++iter) { + for (std::vector<SPObject *>::const_iterator iter = layers.begin(); iter != layers.end(); ++iter) { if (*iter != obj) currentNames.insert( (*iter)->label() ? Glib::ustring((*iter)->label()) : Glib::ustring() ); } @@ -260,7 +260,7 @@ void LayerManager::_rebuild() { if (!_document) // http://sourceforge.net/mailarchive/forum.php?thread_name=5747bce9a7ed077c1b4fc9f0f4f8a5e0%40localhost&forum_name=inkscape-devel return; - std::set<SPObject *> layers = _document->getResourceList("layer"); + std::vector<SPObject *> layers = _document->getResourceList("layer"); SPObject *root=_desktop->currentRoot(); if ( root ) { @@ -268,7 +268,7 @@ void LayerManager::_rebuild() { std::set<SPGroup*> layersToAdd; - for ( std::set<SPObject *>::const_iterator iter = layers.begin(); iter != layers.end(); ++iter ) { + for ( std::vector<SPObject *>::const_iterator iter = layers.begin(); iter != layers.end(); ++iter ) { SPObject *layer = *iter; // Debug::EventTracker<DebugLayerNote> tracker(Util::format("Examining %s", layer->label())); bool needsAdd = false; @@ -281,7 +281,7 @@ void LayerManager::_rebuild() { SPGroup* group = SP_GROUP(curr); if ( group->layerMode() == SPGroup::LAYER ) { // If we have a layer-group as the one or a parent, ensure it is listed as a valid layer. - needsAdd &= ( layers.find(curr) != layers.end() ); + needsAdd &= ( std::find(layers.begin(),layers.end(),curr) != layers.end() ); // XML Tree being used here directly while it shouldn't be... if ( (!(group->getRepr())) || (!(group->getRepr()->parent())) ) { needsAdd = false; diff --git a/src/live_effects/effect.cpp b/src/live_effects/effect.cpp index b03671027..0d28836ca 100644 --- a/src/live_effects/effect.cpp +++ b/src/live_effects/effect.cpp @@ -105,7 +105,6 @@ const Util::EnumData<EffectType> LPETypeData[] = { {EXTRUDE, N_("Extrude"), "extrude"}, {LATTICE, N_("Lattice Deformation"), "lattice"}, {LINE_SEGMENT, N_("Line Segment"), "line_segment"}, - {MIRROR_SYMMETRY, N_("Mirror symmetry"), "mirror_symmetry"}, {OFFSET, N_("Offset"), "offset"}, {PARALLEL, N_("Parallel"), "parallel"}, {PATH_LENGTH, N_("Path length"), "path_length"}, @@ -114,6 +113,7 @@ const Util::EnumData<EffectType> 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"}, + {FILLET_CHAMFER, N_("Fillet/Chamfer"), "fillet-chamfer"}, #endif /* 0.46 */ {BEND_PATH, N_("Bend"), "bend_path"}, @@ -137,7 +137,6 @@ const Util::EnumData<EffectType> LPETypeData[] = { {SIMPLIFY, N_("Simplify"), "simplify"}, {LATTICE2, N_("Lattice Deformation 2"), "lattice2"}, {PERSPECTIVE_ENVELOPE, N_("Perspective/Envelope"), "perspective-envelope"}, - {FILLET_CHAMFER, N_("Fillet/Chamfer"), "fillet-chamfer"}, {INTERPOLATE_POINTS, N_("Interpolate points"), "interpolate_points"}, {TRANSFORM_2PTS, N_("Transform by 2 points"), "transform_2pts"}, {SHOW_HANDLES, N_("Show handles"), "show_handles"}, @@ -145,6 +144,7 @@ const Util::EnumData<EffectType> LPETypeData[] = { {BSPLINE, N_("BSpline"), "bspline"}, {JOIN_TYPE, N_("Join type"), "join_type"}, {TAPER_STROKE, N_("Taper stroke"), "taper_stroke"}, + {MIRROR_SYMMETRY, N_("Mirror symmetry"), "mirror_symmetry"}, {COPY_ROTATE, N_("Rotate copies"), "copy_rotate"}, /* Ponyscape -> Inkscape 0.92*/ {ATTACH_PATH, N_("Attach path"), "attach_path"}, diff --git a/src/live_effects/lpe-bool.cpp b/src/live_effects/lpe-bool.cpp index 902bb081b..6c9830fbd 100644 --- a/src/live_effects/lpe-bool.cpp +++ b/src/live_effects/lpe-bool.cpp @@ -34,53 +34,55 @@ namespace LivePathEffect { // Define an extended boolean operation type static const Util::EnumData<LPEBool::bool_op_ex> BoolOpData[LPEBool::bool_op_ex_count] = { - { LPEBool::bool_op_ex_union, N_("union"), "union" }, - { LPEBool::bool_op_ex_inters, N_("intersection"), "inters" }, - { LPEBool::bool_op_ex_diff, N_("difference"), "diff" }, - { LPEBool::bool_op_ex_symdiff, N_("symmetric difference"), "symdiff" }, - { LPEBool::bool_op_ex_cut, N_("cut"), "cut" }, - { LPEBool::bool_op_ex_slice, N_("slice, keep inner contours"), "slice" }, - { LPEBool::bool_op_ex_slice_inside, N_("slice inside, keep inner contours"), "slice-inside" }, - { LPEBool::bool_op_ex_slice_outside, N_("slice outside, keep inner contours"), "slice-outside" }, - { LPEBool::bool_op_ex_slice_rmv_inner, N_("slice, remove inner contours"), "slice-rmv-inner" }, - { LPEBool::bool_op_ex_slice_inside_rmv_inner, N_("slice inside, remove inner contours"), "slice-inside-rmv-inner" }, - { LPEBool::bool_op_ex_slice_outside_rmv_inner, N_("slice outside, remove inner contours"), "slice-outside-rmv-inner" } + { LPEBool::bool_op_ex_union, N_("union"), "union" }, + { LPEBool::bool_op_ex_inters, N_("intersection"), "inters" }, + { LPEBool::bool_op_ex_diff, N_("difference"), "diff" }, + { LPEBool::bool_op_ex_symdiff, N_("symmetric difference"), "symdiff" }, + { LPEBool::bool_op_ex_cut, N_("division"), "cut" }, + // Note on naming of operations: + // bool_op_cut is called "Division" in the manu, see sp_selected_path_cut + // bool_op_slice is called "Cut path" in the menu, see sp_selected_path_slice + { LPEBool::bool_op_ex_slice, N_("cut"), "slice" }, + { LPEBool::bool_op_ex_slice_inside, N_("cut inside"), "slice-inside" }, + { LPEBool::bool_op_ex_slice_outside, N_("cut outside"), "slice-outside" }, }; -static const Util::EnumDataConverter<LPEBool::bool_op_ex> BoolOpConverter(BoolOpData, sizeof(BoolOpData)/sizeof(*BoolOpData)); +static const Util::EnumDataConverter<LPEBool::bool_op_ex> BoolOpConverter(BoolOpData, sizeof(BoolOpData) / sizeof(*BoolOpData)); static const Util::EnumData<fill_typ> FillTypeData[] = { - { fill_oddEven, N_("odd-even"), "oddeven" }, - { fill_nonZero, N_("non-zero"), "nonzero" }, - { fill_positive, N_("positive"), "positive" }, - { fill_justDont, N_("from curve"), "from-curve" } + { fill_oddEven, N_("odd-even"), "oddeven" }, + { fill_nonZero, N_("non-zero"), "nonzero" }, + { fill_positive, N_("positive"), "positive" }, + { fill_justDont, N_("from curve"), "from-curve" } }; -static const Util::EnumDataConverter<fill_typ> FillTypeConverter(FillTypeData, sizeof(FillTypeData)/sizeof(*FillTypeData)); +static const Util::EnumDataConverter<fill_typ> FillTypeConverter(FillTypeData, sizeof(FillTypeData) / sizeof(*FillTypeData)); static const Util::EnumData<fill_typ> FillTypeDataThis[] = { - { fill_oddEven, N_("odd-even"), "oddeven" }, - { fill_nonZero, N_("non-zero"), "nonzero" }, - { fill_positive, N_("positive"), "positive" } + { fill_oddEven, N_("odd-even"), "oddeven" }, + { fill_nonZero, N_("non-zero"), "nonzero" }, + { fill_positive, N_("positive"), "positive" } }; -static const Util::EnumDataConverter<fill_typ> FillTypeConverterThis(FillTypeDataThis, sizeof(FillTypeDataThis)/sizeof(*FillTypeDataThis)); +static const Util::EnumDataConverter<fill_typ> FillTypeConverterThis(FillTypeDataThis, sizeof(FillTypeDataThis) / sizeof(*FillTypeDataThis)); LPEBool::LPEBool(LivePathEffectObject *lpeobject) : - Effect(lpeobject), - operand_path(_("Operand path:"), _("Operand for the boolean operation"), "operand-path", &wr, this), - bool_operation(_("Operation:"), _("Boolean Operation"), "operation", BoolOpConverter, &wr, this, bool_op_ex_union), - swap_operands(_("Swap operands:"), _("Swap operands (useful e.g. for difference)"), "swap-operands", &wr, this), - fill_type_this(_("Fill type this:"), _("Fill type (winding mode) for this path"), "filltype-this", FillTypeConverterThis, &wr, this, fill_oddEven), - fill_type_operand(_("Fill type operand:"), _("Fill type (winding mode) for operand path"), "filltype-operand", FillTypeConverter, &wr, this, fill_justDont) + Effect(lpeobject), + operand_path(_("Operand path:"), _("Operand for the boolean operation"), "operand-path", &wr, this), + bool_operation(_("Operation:"), _("Boolean Operation"), "operation", BoolOpConverter, &wr, this, bool_op_ex_union), + swap_operands(_("Swap operands:"), _("Swap operands (useful e.g. for difference)"), "swap-operands", &wr, this), + rmv_inner(_("Remove inner:"), _("For cut operations: remove inner (non-contour) lines of cutting path to avoid invisible extra points"), "rmv-inner", &wr, this), + fill_type_this(_("Fill type this:"), _("Fill type (winding mode) for this path"), "filltype-this", FillTypeConverterThis, &wr, this, fill_oddEven), + fill_type_operand(_("Fill type operand:"), _("Fill type (winding mode) for operand path"), "filltype-operand", FillTypeConverter, &wr, this, fill_justDont) { - registerParameter(&operand_path); - registerParameter(&bool_operation); - registerParameter(&swap_operands); - registerParameter(&fill_type_this); - registerParameter(&fill_type_operand); - - show_orig_path = true; + registerParameter(&operand_path); + registerParameter(&bool_operation); + registerParameter(&swap_operands); + registerParameter(&rmv_inner); + registerParameter(&fill_type_this); + registerParameter(&fill_type_operand); + + show_orig_path = true; } LPEBool::~LPEBool() @@ -92,231 +94,222 @@ void LPEBool::resetDefaults(SPItem const * /*item*/) { } -bool cmp_cut_position( const Path::cut_position &a, const Path::cut_position &b ) +bool cmp_cut_position(const Path::cut_position &a, const Path::cut_position &b) { - return a.piece==b.piece ? a.t<b.t : a.piece<b.piece; + return a.piece == b.piece ? a.t < b.t : a.piece < b.piece; } Geom::PathVector sp_pathvector_boolop_slice_intersect(Geom::PathVector const &pathva, Geom::PathVector const &pathvb, bool inside, fill_typ fra, fill_typ frb) { - // This is similar to sp_pathvector_boolop/bool_op_slice, but keeps only edges inside the cutter area. - // The code is also based on sp_pathvector_boolop_slice. - // - // We have two paths on input - // - a closed area which is used to cut out pieces from a contour (called area below) - // - a contour which is cut into pieces by the border of thr area (called contour below) - // - // The code below works in the following steps - // (a) Convert the area to a shape, so that we can ask the winding number for any point - // (b) Add both, the contour and the area to a single shape and intersect them - // (c) Find the intersection points between area border and contour (vector toCut) - // (d) Split the original contour at the intersection points - // (e) check for each contour edge in combined shape if its center is inside the area - if not discard it - // (f) create a vector of all inside edges - // (g) convert the piece numbers to the piece numbers after applying the cuts - // (h) fill a bool vector with information which pieces are in - // (i) filter the descr_cmd of the result path with this bool vector - // - // The main inefficieny here is step (e) because I use a winding function of the area-shape which goes - // through teh complete edge list for each point I ask for, so effort is n-edges-contour * n-edges-area. - // It is tricky to improve this without building into the livarot code. - // One way might be to decide at the intersection points which edges touching the intersection points are - // in by making a loop through all edges on the intersection vertex. Since this is a directed non intersecting - // graph, this should provide sufficient information. - // But since I anyway will change this to the new mechanism some time speed is fairly ok, I didn't look into this. - - - // extract the livarot Paths from the source objects - // also get the winding rule specified in the style - // Livarot's outline of arcs is broken. So convert the path to linear and cubics only, for which the outline is created correctly. - Path *contour_path = Path_for_pathvector(pathv_to_linear_and_cubic_beziers( pathva) ); - Path *area_path = Path_for_pathvector(pathv_to_linear_and_cubic_beziers( pathvb) ); - - // Shapes from above paths - Shape *area_shape = new Shape; - Shape *combined_shape = new Shape; - Shape *combined_inters = new Shape; - - // Add the area (process to intersection free shape) - area_path->ConvertWithBackData(1.0); - area_path->Fill(combined_shape, 1); - - // Convert this to a shape with full winding information - area_shape->ConvertToShape(combined_shape, frb); - - // Add the contour to the combined path (just add, no winding processing) - contour_path->ConvertWithBackData(1.0); - contour_path->Fill(combined_shape, 0,true,false,false); - - // Intersect the area and the contour - no fill processing - combined_inters->ConvertToShape(combined_shape, fill_justDont); - - // Result path - Path *result_path = new Path; - result_path->SetBackData(false); - - // Cutting positions for contour - std::vector<Path::cut_position> toCut; - - if ( combined_inters->hasBackData() ) { - // should always be the case, but ya never know - { - for (int i = 0; i < combined_inters->numberOfPoints(); i++) { - if ( combined_inters->getPoint(i).totalDegree() > 2 ) { - // possibly an intersection - // we need to check that at least one edge from the source path is incident to it - // before we declare it's an intersection - int cb = combined_inters->getPoint(i).incidentEdge[FIRST]; - int nbOrig=0; - int nbOther=0; - int piece=-1; - float t=0.0; - while ( cb >= 0 && cb < combined_inters->numberOfEdges() ) { - if ( combined_inters->ebData[cb].pathID == 0 ) { - // the source has an edge incident to the point, get its position on the path - piece=combined_inters->ebData[cb].pieceID; - if ( combined_inters->getEdge(cb).st == i ) { - t=combined_inters->ebData[cb].tSt; - } else { - t=combined_inters->ebData[cb].tEn; - } - nbOrig++; - } - if ( combined_inters->ebData[cb].pathID == 1 ) nbOther++; // the cut is incident to this point - cb=combined_inters->NextAt(i, cb); - } - if ( nbOrig > 0 && nbOther > 0 ) { - // point incident to both path and cut: an intersection - // note that you only keep one position on the source; you could have degenerate - // cases where the source crosses itself at this point, and you wouyld miss an intersection - Path::cut_position cutpos; - cutpos.piece=piece; - cutpos.t=t; - toCut.push_back( cutpos ); - } - } - } - } - { - // remove the edges from the intersection polygon - int i = combined_inters->numberOfEdges() - 1; - for (;i>=0;i--) { - if ( combined_inters->ebData[i].pathID == 1 ) { - combined_inters->SubEdge(i); - } else { - const Shape::dg_arete &edge = combined_inters->getEdge(i); - const Shape::dg_point &start = combined_inters->getPoint(edge.st); - const Shape::dg_point &end = combined_inters->getPoint(edge.en); - Geom::Point mid = 0.5*(start.x+end.x); - int wind = area_shape->PtWinding( mid ); - if ( wind==0 ) { - combined_inters->SubEdge(i); - } - } - } - } - } - - // create a vector of pieces, which are in the intersection - std::vector<Path::cut_position> inside_pieces( combined_inters->numberOfEdges() ); - for( int i=0; i<combined_inters->numberOfEdges(); i++ ) { - inside_pieces[i].piece = combined_inters->ebData[i].pieceID; - // Use the t middle point, this is safe to compare with values from toCut in the presence of roundoff errors - inside_pieces[i].t = 0.5 * (combined_inters->ebData[i].tSt + combined_inters->ebData[i].tEn); - } - std::sort( inside_pieces.begin(), inside_pieces.end(), cmp_cut_position ); - - // sort cut positions - std::sort( toCut.begin(), toCut.end(), cmp_cut_position ); - - // Compute piece ids after ConvertPositionsToMoveTo - { - int idIncr=0; - std::vector<Path::cut_position>::iterator itPiece=inside_pieces.begin(); - std::vector<Path::cut_position>::iterator itCut=toCut.begin(); - while( itPiece!=inside_pieces.end() ) - { - while( itCut!=toCut.end() && cmp_cut_position( *itCut, *itPiece ) ) - { - ++itCut; - idIncr+=2; - } - itPiece->piece += idIncr; - ++itPiece; - } - } - - // Copy the original path to result and cut at the intersection points - result_path->Copy( contour_path ); - result_path->ConvertPositionsToMoveTo( toCut.size(), toCut.data() ); // cut where you found intersections - - // Create an array of bools which states which pieces are in - std::vector<bool> inside_flags(result_path->descr_cmd.size(), false ); - for( std::vector<Path::cut_position>::iterator itPiece=inside_pieces.begin(); itPiece!=inside_pieces.end(); ++itPiece ) - { - inside_flags[ itPiece->piece ] = true; - // also enable the element -1 to get the MoveTo - if( itPiece->piece>=1 ) - { - inside_flags[ itPiece->piece-1 ] = true; - } - } + // This is similar to sp_pathvector_boolop/bool_op_slice, but keeps only edges inside the cutter area. + // The code is also based on sp_pathvector_boolop_slice. + // + // We have two paths on input + // - a closed area which is used to cut out pieces from a contour (called area below) + // - a contour which is cut into pieces by the border of thr area (called contour below) + // + // The code below works in the following steps + // (a) Convert the area to a shape, so that we can ask the winding number for any point + // (b) Add both, the contour and the area to a single shape and intersect them + // (c) Find the intersection points between area border and contour (vector toCut) + // (d) Split the original contour at the intersection points + // (e) check for each contour edge in combined shape if its center is inside the area - if not discard it + // (f) create a vector of all inside edges + // (g) convert the piece numbers to the piece numbers after applying the cuts + // (h) fill a bool vector with information which pieces are in + // (i) filter the descr_cmd of the result path with this bool vector + // + // The main inefficieny here is step (e) because I use a winding function of the area-shape which goes + // through teh complete edge list for each point I ask for, so effort is n-edges-contour * n-edges-area. + // It is tricky to improve this without building into the livarot code. + // One way might be to decide at the intersection points which edges touching the intersection points are + // in by making a loop through all edges on the intersection vertex. Since this is a directed non intersecting + // graph, this should provide sufficient information. + // But since I anyway will change this to the new mechanism some time speed is fairly ok, I didn't look into this. + + + // extract the livarot Paths from the source objects + // also get the winding rule specified in the style + // Livarot's outline of arcs is broken. So convert the path to linear and cubics only, for which the outline is created correctly. + Path *contour_path = Path_for_pathvector(pathv_to_linear_and_cubic_beziers(pathva)); + Path *area_path = Path_for_pathvector(pathv_to_linear_and_cubic_beziers(pathvb)); + + // Shapes from above paths + Shape *area_shape = new Shape; + Shape *combined_shape = new Shape; + Shape *combined_inters = new Shape; + + // Add the area (process to intersection free shape) + area_path->ConvertWithBackData(1.0); + area_path->Fill(combined_shape, 1); + + // Convert this to a shape with full winding information + area_shape->ConvertToShape(combined_shape, frb); + + // Add the contour to the combined path (just add, no winding processing) + contour_path->ConvertWithBackData(1.0); + contour_path->Fill(combined_shape, 0, true, false, false); + + // Intersect the area and the contour - no fill processing + combined_inters->ConvertToShape(combined_shape, fill_justDont); + + // Result path + Path *result_path = new Path; + result_path->SetBackData(false); + + // Cutting positions for contour + std::vector<Path::cut_position> toCut; + + if (combined_inters->hasBackData()) { + // should always be the case, but ya never know + { + for (int i = 0; i < combined_inters->numberOfPoints(); i++) { + if (combined_inters->getPoint(i).totalDegree() > 2) { + // possibly an intersection + // we need to check that at least one edge from the source path is incident to it + // before we declare it's an intersection + int cb = combined_inters->getPoint(i).incidentEdge[FIRST]; + int nbOrig = 0; + int nbOther = 0; + int piece = -1; + float t = 0.0; + while (cb >= 0 && cb < combined_inters->numberOfEdges()) { + if (combined_inters->ebData[cb].pathID == 0) { + // the source has an edge incident to the point, get its position on the path + piece = combined_inters->ebData[cb].pieceID; + if (combined_inters->getEdge(cb).st == i) { + t = combined_inters->ebData[cb].tSt; + } else { + t = combined_inters->ebData[cb].tEn; + } + nbOrig++; + } + if (combined_inters->ebData[cb].pathID == 1) { + nbOther++; // the cut is incident to this point + } + cb = combined_inters->NextAt(i, cb); + } + if (nbOrig > 0 && nbOther > 0) { + // point incident to both path and cut: an intersection + // note that you only keep one position on the source; you could have degenerate + // cases where the source crosses itself at this point, and you wouyld miss an intersection + Path::cut_position cutpos; + cutpos.piece = piece; + cutpos.t = t; + toCut.push_back(cutpos); + } + } + } + } + { + // remove the edges from the intersection polygon + int i = combined_inters->numberOfEdges() - 1; + for (; i >= 0; i--) { + if (combined_inters->ebData[i].pathID == 1) { + combined_inters->SubEdge(i); + } else { + const Shape::dg_arete &edge = combined_inters->getEdge(i); + const Shape::dg_point &start = combined_inters->getPoint(edge.st); + const Shape::dg_point &end = combined_inters->getPoint(edge.en); + Geom::Point mid = 0.5 * (start.x + end.x); + int wind = area_shape->PtWinding(mid); + if (wind == 0) { + combined_inters->SubEdge(i); + } + } + } + } + } + + // create a vector of pieces, which are in the intersection + std::vector<Path::cut_position> inside_pieces(combined_inters->numberOfEdges()); + for (int i = 0; i < combined_inters->numberOfEdges(); i++) { + inside_pieces[i].piece = combined_inters->ebData[i].pieceID; + // Use the t middle point, this is safe to compare with values from toCut in the presence of roundoff errors + inside_pieces[i].t = 0.5 * (combined_inters->ebData[i].tSt + combined_inters->ebData[i].tEn); + } + std::sort(inside_pieces.begin(), inside_pieces.end(), cmp_cut_position); + + // sort cut positions + std::sort(toCut.begin(), toCut.end(), cmp_cut_position); + + // Compute piece ids after ConvertPositionsToMoveTo + { + int idIncr = 0; + std::vector<Path::cut_position>::iterator itPiece = inside_pieces.begin(); + std::vector<Path::cut_position>::iterator itCut = toCut.begin(); + while (itPiece != inside_pieces.end()) { + while (itCut != toCut.end() && cmp_cut_position(*itCut, *itPiece)) { + ++itCut; + idIncr += 2; + } + itPiece->piece += idIncr; + ++itPiece; + } + } + + // Copy the original path to result and cut at the intersection points + result_path->Copy(contour_path); + result_path->ConvertPositionsToMoveTo(toCut.size(), toCut.data()); // cut where you found intersections + + // Create an array of bools which states which pieces are in + std::vector<bool> inside_flags(result_path->descr_cmd.size(), false); + for (std::vector<Path::cut_position>::iterator itPiece = inside_pieces.begin(); itPiece != inside_pieces.end(); ++itPiece) { + inside_flags[ itPiece->piece ] = true; + // also enable the element -1 to get the MoveTo + if (itPiece->piece >= 1) { + inside_flags[ itPiece->piece - 1 ] = true; + } + } #if 0 // CONCEPT TESTING - //Check if the inside/outside verdict is consistent - just for testing the concept - // Retrieve the pieces - int nParts=0; - Path** parts=result_path->SubPaths(nParts,false); + //Check if the inside/outside verdict is consistent - just for testing the concept + // Retrieve the pieces + int nParts = 0; + Path **parts = result_path->SubPaths(nParts, false); // Each piece should be either fully in or fully out - int iPiece=0; - for( int iPart=0; iPart<nParts; iPart++ ) - { - bool andsum=true; - bool orsum=false; - for( int iCmd=0; iCmd<parts[iPart]->descr_cmd.size(); iCmd++, iPiece++ ) - { - andsum = andsum && inside_flags[ iPiece ]; - orsum = andsum || inside_flags[ iPiece ]; - } - - if( andsum!=orsum ) - { - g_warning( "Inconsistent inside/outside verdict for part=%d", iPart ); - } + int iPiece = 0; + for (int iPart = 0; iPart < nParts; iPart++) { + bool andsum = true; + bool orsum = false; + for (int iCmd = 0; iCmd < parts[iPart]->descr_cmd.size(); iCmd++, iPiece++) { + andsum = andsum && inside_flags[ iPiece ]; + orsum = andsum || inside_flags[ iPiece ]; + } + + if (andsum != orsum) { + g_warning("Inconsistent inside/outside verdict for part=%d", iPart); + } } - g_free(parts); + g_free(parts); #endif - // iterate over the commands of a path and keep those which are inside - int iDest=0; - for( int iSrc=0; iSrc<result_path->descr_cmd.size(); iSrc++ ) - { - if( inside_flags[iSrc]==inside ) - { - result_path->descr_cmd[iDest++] = result_path->descr_cmd[iSrc]; - } - else - { - delete result_path->descr_cmd[iSrc]; - } - } - result_path->descr_cmd.resize( iDest ); - - delete combined_inters; - delete combined_shape; - delete area_shape; - delete contour_path; - delete area_path; - - gchar *result_str = result_path->svg_dump_path(); - Geom::PathVector outres = Geom::parse_svg_path(result_str); - // CONCEPT TESTING g_warning( "%s", result_str ); - g_free(result_str); - delete result_path; - - return outres; + // iterate over the commands of a path and keep those which are inside + int iDest = 0; + for (int iSrc = 0; iSrc < result_path->descr_cmd.size(); iSrc++) { + if (inside_flags[iSrc] == inside) { + result_path->descr_cmd[iDest++] = result_path->descr_cmd[iSrc]; + } else { + delete result_path->descr_cmd[iSrc]; + } + } + result_path->descr_cmd.resize(iDest); + + delete combined_inters; + delete combined_shape; + delete area_shape; + delete contour_path; + delete area_path; + + gchar *result_str = result_path->svg_dump_path(); + Geom::PathVector outres = Geom::parse_svg_path(result_str); + // CONCEPT TESTING g_warning( "%s", result_str ); + g_free(result_str); + delete result_path; + + return outres; } // remove inner contours @@ -324,17 +317,17 @@ Geom::PathVector sp_pathvector_boolop_remove_inner(Geom::PathVector const &pathva, fill_typ fra) { Geom::PathVector patht; - Path *patha = Path_for_pathvector(pathv_to_linear_and_cubic_beziers( pathva ) ); + Path *patha = Path_for_pathvector(pathv_to_linear_and_cubic_beziers(pathva)); Shape *shape = new Shape; Shape *shapeshape = new Shape; Path *resultp = new Path; resultp->SetBackData(false); - patha->ConvertWithBackData(0.1); - patha->Fill(shape, 0); - shapeshape->ConvertToShape(shape, fra); - shapeshape->ConvertToForme(resultp, 1, &patha); + patha->ConvertWithBackData(0.1); + patha->Fill(shape, 0); + shapeshape->ConvertToShape(shape, fra); + shapeshape->ConvertToForme(resultp, 1, &patha); delete shape; delete shapeshape; @@ -361,73 +354,46 @@ static fill_typ GetFillTyp(SPItem *item) } } -void LPEBool::doEffect (SPCurve * curve) +void LPEBool::doEffect(SPCurve *curve) { Geom::PathVector path_in = curve->get_pathvector(); - if ( operand_path.linksToPath() && operand_path.getObject() ) - { - bool_op_ex op = bool_operation.get_value(); - bool swap = swap_operands.get_value(); - - Geom::PathVector path_a = swap ? operand_path.get_pathvector() : path_in; - Geom::PathVector path_b = swap ? path_in : operand_path.get_pathvector(); - - // TODO: I would like to use the original objects fill rule if the UI selected rule is fill_justDont. - // But it doesn't seem possible to access them from here, because SPCurve is not derived from SPItem. - // The nearest function in the call stack, where this is available is SPLPEItem::performPathEffect (this is then an SPItem) - // For the parameter curve, this is possible. - // fill_typ fill_this = fill_type_this. get_value()!=fill_justDont ? fill_type_this.get_value() : GetFillTyp( curve ) ; - fill_typ fill_this = fill_type_this.get_value(); - fill_typ fill_operand = fill_type_operand.get_value()!=fill_justDont ? fill_type_operand.get_value() : GetFillTyp( operand_path.getObject() ); - - fill_typ fill_a = swap ? fill_operand : fill_this; - fill_typ fill_b = swap ? fill_this : fill_operand; - - switch( op ) - { - case bool_op_ex_slice_rmv_inner: - op = bool_op_ex_slice; - path_b = sp_pathvector_boolop_remove_inner( path_b, fill_b ); - break; - - case bool_op_ex_slice_inside_rmv_inner: - op = bool_op_ex_slice_inside; - path_b = sp_pathvector_boolop_remove_inner( path_b, fill_b ); - break; - - case bool_op_ex_slice_outside_rmv_inner: - op = bool_op_ex_slice_outside; - path_b = sp_pathvector_boolop_remove_inner( path_b, fill_b ); - break; - } - - Geom::PathVector path_out; - - if( op==bool_op_ex_slice || op == bool_op_ex_slice_rmv_inner) { - if( op==bool_op_ex_slice_rmv_inner ) - { - path_b = sp_pathvector_boolop_remove_inner( path_b, fill_b ); - } - path_out = sp_pathvector_boolop( path_b, path_a, to_bool_op(op), fill_b, fill_a); - } - else if( op==bool_op_ex_slice_inside || op==bool_op_ex_slice_inside_rmv_inner ) { - if( op==bool_op_ex_slice_inside_rmv_inner ) - { - path_b = sp_pathvector_boolop_remove_inner( path_b, fill_b ); - } - path_out = sp_pathvector_boolop_slice_intersect( path_a, path_b, true, fill_a, fill_b); - } else if( op==bool_op_ex_slice_outside || op == bool_op_ex_slice_outside_rmv_inner ) { - if( op==bool_op_ex_slice_outside_rmv_inner ) - { - path_b = sp_pathvector_boolop_remove_inner( path_b, fill_b ); - } - path_out = sp_pathvector_boolop_slice_intersect( path_a, path_b, false, fill_a, fill_b); - } else { - path_out = sp_pathvector_boolop( path_a, path_b, to_bool_op(op), fill_a, fill_b); - } - curve->set_pathvector( path_out ); - } + if (operand_path.linksToPath() && operand_path.getObject()) { + bool_op_ex op = bool_operation.get_value(); + bool swap = swap_operands.get_value(); + + Geom::PathVector path_a = swap ? operand_path.get_pathvector() : path_in; + Geom::PathVector path_b = swap ? path_in : operand_path.get_pathvector(); + + // TODO: I would like to use the original objects fill rule if the UI selected rule is fill_justDont. + // But it doesn't seem possible to access them from here, because SPCurve is not derived from SPItem. + // The nearest function in the call stack, where this is available is SPLPEItem::performPathEffect (this is then an SPItem) + // For the parameter curve, this is possible. + // fill_typ fill_this = fill_type_this. get_value()!=fill_justDont ? fill_type_this.get_value() : GetFillTyp( curve ) ; + fill_typ fill_this = fill_type_this.get_value(); + fill_typ fill_operand = fill_type_operand.get_value() != fill_justDont ? fill_type_operand.get_value() : GetFillTyp(operand_path.getObject()); + + fill_typ fill_a = swap ? fill_operand : fill_this; + fill_typ fill_b = swap ? fill_this : fill_operand; + + if (rmv_inner.get_value()) { + path_b = sp_pathvector_boolop_remove_inner(path_b, fill_b); + } + + Geom::PathVector path_out; + + if (op == bool_op_ex_slice) { + // For slicing, the bool op is added to the line group which is sliced, not the cut path. This swapped order is correct. + path_out = sp_pathvector_boolop(path_b, path_a, to_bool_op(op), fill_b, fill_a); + } else if (op == bool_op_ex_slice_inside) { + path_out = sp_pathvector_boolop_slice_intersect(path_a, path_b, true, fill_a, fill_b); + } else if (op == bool_op_ex_slice_outside) { + path_out = sp_pathvector_boolop_slice_intersect(path_a, path_b, false, fill_a, fill_b); + } else { + path_out = sp_pathvector_boolop(path_a, path_b, to_bool_op(op), fill_a, fill_b); + } + curve->set_pathvector(path_out); + } } } // namespace LivePathEffect diff --git a/src/live_effects/lpe-bool.h b/src/live_effects/lpe-bool.h index 12c51b4ec..1c0aa0243 100644 --- a/src/live_effects/lpe-bool.h +++ b/src/live_effects/lpe-bool.h @@ -24,40 +24,37 @@ public: LPEBool(LivePathEffectObject *lpeobject); virtual ~LPEBool(); - void doEffect (SPCurve * curve); - virtual void resetDefaults(SPItem const * item); - - enum bool_op_ex - { - bool_op_ex_union = bool_op_union, - bool_op_ex_inters = bool_op_inters, - bool_op_ex_diff = bool_op_diff, - bool_op_ex_symdiff = bool_op_symdiff, - bool_op_ex_cut = bool_op_cut, - bool_op_ex_slice = bool_op_slice, - bool_op_ex_slice_inside, // like bool_op_slice, but leaves only the contour pieces inside of the cut path - bool_op_ex_slice_outside, // like bool_op_slice, but leaves only the contour pieces outside of the cut path - bool_op_ex_slice_rmv_inner, // like bool_op_ex_slice, but remove inner contours - bool_op_ex_slice_inside_rmv_inner, // like bool_op_ex_slice_inside, but remove inner contours - bool_op_ex_slice_outside_rmv_inner, // like bool_op_ex_slice_outside, but remove inner contours - bool_op_ex_count + void doEffect(SPCurve *curve); + virtual void resetDefaults(SPItem const *item); + + enum bool_op_ex { + bool_op_ex_union = bool_op_union, + bool_op_ex_inters = bool_op_inters, + bool_op_ex_diff = bool_op_diff, + bool_op_ex_symdiff = bool_op_symdiff, + bool_op_ex_cut = bool_op_cut, + bool_op_ex_slice = bool_op_slice, + bool_op_ex_slice_inside, // like bool_op_slice, but leaves only the contour pieces inside of the cut path + bool_op_ex_slice_outside, // like bool_op_slice, but leaves only the contour pieces outside of the cut path + bool_op_ex_count }; - inline friend bool_op to_bool_op( bool_op_ex val ) + inline friend bool_op to_bool_op(bool_op_ex val) { - assert( val<=bool_op_ex_slice ); - (bool_op) val; + assert(val <= bool_op_ex_slice); + (bool_op) val; } private: - LPEBool(const LPEBool&); - LPEBool& operator=(const LPEBool&); + LPEBool(const LPEBool &); + LPEBool &operator=(const LPEBool &); OriginalPathParam operand_path; EnumParam<bool_op_ex> bool_operation; EnumParam<fill_typ> fill_type_this; EnumParam<fill_typ> fill_type_operand; BoolParam swap_operands; + BoolParam rmv_inner; }; }; //namespace LivePathEffect diff --git a/src/live_effects/lpe-mirror_symmetry.cpp b/src/live_effects/lpe-mirror_symmetry.cpp index c13cffb6a..9f3070ff4 100644 --- a/src/live_effects/lpe-mirror_symmetry.cpp +++ b/src/live_effects/lpe-mirror_symmetry.cpp @@ -6,36 +6,84 @@ * Maximilian Albert * Johan Engelen * Abhishek Sharma + * Jabiertxof * * Copyright (C) Johan Engelen 2007 <j.b.c.engelen@utwente.nl> * Copyright (C) Maximilin Albert 2008 <maximilian.albert@gmail.com> * * Released under GNU GPL, read the file 'COPYING' for more information */ - +#include <gtkmm.h> #include <glibmm/i18n.h> #include "live_effects/lpe-mirror_symmetry.h" #include <sp-path.h> #include <display/curve.h> #include <svg/path-string.h> - +#include "helper/geom.h" #include <2geom/path.h> +#include <2geom/path-intersection.h> #include <2geom/transforms.h> #include <2geom/affine.h> +#include "knot-holder-entity.h" +#include "knotholder.h" +#include "inkscape.h" namespace Inkscape { namespace LivePathEffect { +static const Util::EnumData<ModeType> ModeTypeData[MT_END] = { + { MT_V, N_("Vertical Page Center"), "Vertical Page Center, use select tool to move item instead line" }, + { MT_H, N_("Horizontal Page Center"), "Horizontal Page Center, use select tool to move item instead line" }, + { MT_FREE, N_("Free from reflection line"), "Free from path" }, + { MT_X, N_("X from middle knot"), "X from middle knot" }, + { MT_Y, N_("Y from middle knot"), "Y from middle knot" } +}; +static const Util::EnumDataConverter<ModeType> +MTConverter(ModeTypeData, MT_END); + +namespace MS { + +class KnotHolderEntityCenterMirrorSymmetry : public LPEKnotHolderEntity { +public: + KnotHolderEntityCenterMirrorSymmetry(LPEMirrorSymmetry *effect) : LPEKnotHolderEntity(effect){}; + virtual void knot_set(Geom::Point const &p, Geom::Point const &origin, guint state); + virtual Geom::Point knot_get() const; +}; + +class KnotHolderEntityStartMirrorSymmetry : public LPEKnotHolderEntity { +public: + KnotHolderEntityStartMirrorSymmetry(LPEMirrorSymmetry *effect) : LPEKnotHolderEntity(effect){}; + virtual void knot_set(Geom::Point const &p, Geom::Point const &origin, guint state); + virtual Geom::Point knot_get() const; +}; + +class KnotHolderEntityEndMirrorSymmetry : public LPEKnotHolderEntity { +public: + KnotHolderEntityEndMirrorSymmetry(LPEMirrorSymmetry *effect) : LPEKnotHolderEntity(effect){}; + virtual void knot_set(Geom::Point const &p, Geom::Point const &origin, guint state); + virtual Geom::Point knot_get() const; +}; + +} // namespace MS + LPEMirrorSymmetry::LPEMirrorSymmetry(LivePathEffectObject *lpeobject) : Effect(lpeobject), + mode(_("Mode"), _("Symmetry move mode"), "mode", MTConverter, &wr, this, MT_FREE), discard_orig_path(_("Discard original path?"), _("Check this to only keep the mirrored part of the path"), "discard_orig_path", &wr, this, false), - reflection_line(_("Reflection line:"), _("Line which serves as 'mirror' for the reflection"), "reflection_line", &wr, this, "M0,0 L100,100") + fuse_paths(_("Fuse paths"), _("Fuse original and the reflection into a single path"), "fuse_paths", &wr, this, false), + oposite_fuse(_("Opposite fuse"), _("Picks the other side of the mirror as the original"), "oposite_fuse", &wr, this, false), + start_point(_("Start mirror line"), _("Start mirror line"), "start_point", &wr, this, "Adjust the start of mirroring"), + end_point(_("End mirror line"), _("End mirror line"), "end_point", &wr, this, "Adjust end of mirroring") { show_orig_path = true; + registerParameter(&mode); + registerParameter( &discard_orig_path); + registerParameter( &fuse_paths); + registerParameter( &oposite_fuse); + registerParameter( &start_point); + registerParameter( &end_point); apply_to_clippath_and_mask = true; - registerParameter( dynamic_cast<Parameter *>(&discard_orig_path) ); - registerParameter( dynamic_cast<Parameter *>(&reflection_line) ); } LPEMirrorSymmetry::~LPEMirrorSymmetry() @@ -43,60 +91,276 @@ LPEMirrorSymmetry::~LPEMirrorSymmetry() } void + +LPEMirrorSymmetry::doBeforeEffect (SPLPEItem const* lpeitem) +{ + using namespace Geom; + + Point point_a(boundingbox_X.max(), boundingbox_Y.min()); + Point point_b(boundingbox_X.max(), boundingbox_Y.max()); + Point point_c(boundingbox_X.max(), boundingbox_Y.middle()); + if (mode == MT_Y) { + point_a = Geom::Point(boundingbox_X.min(),center_point[Y]); + point_b = Geom::Point(boundingbox_X.max(),center_point[Y]); + } + if (mode == MT_X) { + point_a = Geom::Point(center_point[X],boundingbox_Y.min()); + point_b = Geom::Point(center_point[X],boundingbox_Y.max()); + } + line_separation.setPoints(point_a, point_b); + if ( mode == MT_X || mode == MT_Y ) { + start_point.param_setValue(point_a); + end_point.param_setValue(point_b); + center_point = Geom::middle_point(point_a, point_b); + } else if ( mode == MT_FREE) { + if(!are_near(previous_center,center_point, 0.01)) { + Geom::Point trans = center_point - previous_center; + start_point.param_setValue(start_point * trans); + end_point.param_setValue(end_point * trans); + line_separation.setPoints(start_point, end_point); + } else { + center_point = Geom::middle_point((Geom::Point)start_point, (Geom::Point)end_point); + line_separation.setPoints(start_point, end_point); + } + } else if ( mode == MT_V){ + if(SP_ACTIVE_DESKTOP){ + SPDocument * doc = SP_ACTIVE_DESKTOP->getDocument(); + Geom::Rect view_box_rect = doc->getViewBox(); + Geom::Point sp = Geom::Point(view_box_rect.width()/2.0, 0); + sp *= i2anc_affine(SP_OBJECT(lpeitem), SP_OBJECT(SP_ACTIVE_DESKTOP->currentLayer()->parent)) .inverse(); + start_point.param_setValue(sp); + Geom::Point ep = Geom::Point(view_box_rect.width()/2.0, view_box_rect.height()); + ep *= i2anc_affine(SP_OBJECT(lpeitem), SP_OBJECT(SP_ACTIVE_DESKTOP->currentLayer()->parent)) .inverse(); + end_point.param_setValue(ep); + center_point = Geom::middle_point((Geom::Point)start_point, (Geom::Point)end_point); + line_separation.setPoints(start_point, end_point); + } + } else { //horizontal page + if(SP_ACTIVE_DESKTOP){ + SPDocument * doc = SP_ACTIVE_DESKTOP->getDocument(); + Geom::Rect view_box_rect = doc->getViewBox(); + Geom::Point sp = Geom::Point(0, view_box_rect.height()/2.0); + sp *= i2anc_affine(SP_OBJECT(lpeitem), SP_OBJECT(SP_ACTIVE_DESKTOP->currentLayer()->parent)) .inverse(); + start_point.param_setValue(sp); + Geom::Point ep = Geom::Point(view_box_rect.width(), view_box_rect.height()/2.0); + ep *= i2anc_affine(SP_OBJECT(lpeitem), SP_OBJECT(SP_ACTIVE_DESKTOP->currentLayer()->parent)) .inverse(); + end_point.param_setValue(ep); + center_point = Geom::middle_point((Geom::Point)start_point, (Geom::Point)end_point); + line_separation.setPoints(start_point, end_point); + } + } + previous_center = center_point; +} + +void LPEMirrorSymmetry::doOnApply (SPLPEItem const* lpeitem) { using namespace Geom; - // fixme: what happens if the bbox is empty? - // fixme: this is probably wrong - Geom::Affine t = lpeitem->i2dt_affine(); - Geom::Rect bbox = *lpeitem->desktopVisualBounds(); - - Point A(bbox.left(), bbox.bottom()); - Point B(bbox.left(), bbox.top()); - A *= t; - B *= t; - Piecewise<D2<SBasis> > rline = Piecewise<D2<SBasis> >(D2<SBasis>(SBasis(A[X], B[X]), SBasis(A[Y], B[Y]))); - reflection_line.set_new_value(rline, true); + original_bbox(lpeitem); + + Point point_a(boundingbox_X.max(), boundingbox_Y.min()); + Point point_b(boundingbox_X.max(), boundingbox_Y.max()); + Point point_c(boundingbox_X.max(), boundingbox_Y.middle()); + start_point.param_setValue(point_a); + start_point.param_update_default(point_a); + end_point.param_setValue(point_b); + end_point.param_update_default(point_b); + center_point = point_c; + previous_center = center_point; } + Geom::PathVector LPEMirrorSymmetry::doEffect_path (Geom::PathVector const & path_in) { - // Don't allow empty path parameter: - if ( reflection_line.get_pathvector().empty() ) { - return path_in; - } - + Geom::PathVector const original_pathv = pathv_to_linear_and_cubic_beziers(path_in); Geom::PathVector path_out; - if (!discard_orig_path) { - path_out = path_in; + + if (!discard_orig_path && !fuse_paths) { + path_out = pathv_to_linear_and_cubic_beziers(path_in); } - Geom::PathVector mline(reflection_line.get_pathvector()); - Geom::Point A(mline.front().initialPoint()); - Geom::Point B(mline.back().finalPoint()); + Geom::Point point_a(line_separation.initialPoint()); + Geom::Point point_b(line_separation.finalPoint()); - Geom::Affine m1(1.0, 0.0, 0.0, 1.0, A[0], A[1]); - double hyp = Geom::distance(A, B); - double c = (B[0] - A[0]) / hyp; // cos(alpha) - double s = (B[1] - A[1]) / hyp; // sin(alpha) + Geom::Translate m1(point_a[0], point_a[1]); + double hyp = Geom::distance(point_a, point_b); + double c = (point_b[0] - point_a[0]) / hyp; // cos(alpha) + double s = (point_b[1] - point_a[1]) / hyp; // sin(alpha) Geom::Affine m2(c, -s, s, c, 0.0, 0.0); - Geom::Affine sca(1.0, 0.0, 0.0, -1.0, 0.0, 0.0); + Geom::Scale sca(1.0, -1.0); Geom::Affine m = m1.inverse() * m2; m = m * sca; m = m * m2.inverse(); m = m * m1; - for (int i = 0; i < static_cast<int>(path_in.size()); ++i) { - path_out.push_back(path_in[i] * m); + if (fuse_paths && !discard_orig_path) { + for (Geom::PathVector::const_iterator path_it = original_pathv.begin(); + path_it != original_pathv.end(); ++path_it) + { + if (path_it->empty()) { + continue; + } + Geom::PathVector tmp_path; + double time_start = 0.0; + int position = 0; + bool end_open = false; + if (path_it->closed()) { + const Geom::Curve &closingline = path_it->back_closed(); + if (!are_near(closingline.initialPoint(), closingline.finalPoint())) { + end_open = true; + } + } + Geom::Path original = *path_it; + if (end_open && path_it->closed()) { + original.close(false); + original.appendNew<Geom::LineSegment>( original.initialPoint() ); + original.close(true); + } + Geom::Point s = start_point; + Geom::Point e = end_point; + double dir = line_separation.angle(); + double diagonal = Geom::distance(Geom::Point(boundingbox_X.min(),boundingbox_Y.min()),Geom::Point(boundingbox_X.max(),boundingbox_Y.max())); + Geom::Rect bbox(Geom::Point(boundingbox_X.min(),boundingbox_Y.min()),Geom::Point(boundingbox_X.max(),boundingbox_Y.max())); + double size_divider = Geom::distance(center_point, bbox) + diagonal; + s = Geom::Point::polar(dir,size_divider) + center_point; + e = Geom::Point::polar(dir + Geom::rad_from_deg(180),size_divider) + center_point; + Geom::Path divider = Geom::Path(s); + divider.appendNew<Geom::LineSegment>(e); + Geom::Crossings cs = crossings(original, divider); + std::vector<double> crossed; + for(unsigned int i = 0; i < cs.size(); i++) { + crossed.push_back(cs[i].ta); + } + std::sort(crossed.begin(), crossed.end()); + for (unsigned int i = 0; i < crossed.size(); i++) { + double time_end = crossed[i]; + if (time_start != time_end && time_end - time_start > Geom::EPSILON) { + Geom::Path portion = original.portion(time_start, time_end); + if (!portion.empty()) { + Geom::Point middle = portion.pointAt((double)portion.size()/2.0); + position = Geom::sgn(Geom::cross(e - s, middle - s)); + if (!oposite_fuse) { + position *= -1; + } + if (position == 1) { + Geom::Path mirror = portion.reversed() * m; + mirror.setInitial(portion.finalPoint()); + portion.append(mirror); + if(i!=0) { + portion.setFinal(portion.initialPoint()); + portion.close(); + } + tmp_path.push_back(portion); + } + portion.clear(); + } + } + time_start = time_end; + } + position = Geom::sgn(Geom::cross(e - s, original.finalPoint() - s)); + if (!oposite_fuse) { + position *= -1; + } + if (cs.size()!=0 && position == 1) { + if (time_start != original.size() && original.size() - time_start > Geom::EPSILON) { + Geom::Path portion = original.portion(time_start, original.size()); + if (!portion.empty()) { + portion = portion.reversed(); + Geom::Path mirror = portion.reversed() * m; + mirror.setInitial(portion.finalPoint()); + portion.append(mirror); + portion = portion.reversed(); + if (!original.closed()) { + tmp_path.push_back(portion); + } else { + if (cs.size() > 1 && tmp_path.size() > 0 && tmp_path[0].size() > 0 ) { + portion.setFinal(tmp_path[0].initialPoint()); + portion.setInitial(tmp_path[0].finalPoint()); + tmp_path[0].append(portion); + } else { + tmp_path.push_back(portion); + } + tmp_path[0].close(); + } + portion.clear(); + } + } + } + if (cs.size() == 0 && position == 1) { + tmp_path.push_back(original); + tmp_path.push_back(original * m); + } + path_out.insert(path_out.end(), tmp_path.begin(), tmp_path.end()); + tmp_path.clear(); + } + } + + if (!fuse_paths || discard_orig_path) { + for (int i = 0; i < static_cast<int>(path_in.size()); ++i) { + path_out.push_back(path_in[i] * m); + } } return path_out; } +void +LPEMirrorSymmetry::addCanvasIndicators(SPLPEItem const */*lpeitem*/, std::vector<Geom::PathVector> &hp_vec) +{ + using namespace Geom; + hp_vec.clear(); + Geom::Path path; + Geom::Point s = start_point; + Geom::Point e = end_point; + path.start( s ); + path.appendNew<Geom::LineSegment>( e ); + Geom::PathVector helper; + helper.push_back(path); + hp_vec.push_back(helper); +} + +void +LPEMirrorSymmetry::addKnotHolderEntities(KnotHolder *knotholder, SPDesktop *desktop, SPItem *item) +{ + SPKnotShapeType knot_shape = SP_KNOT_SHAPE_CIRCLE; + SPKnotModeType knot_mode = SP_KNOT_MODE_XOR; + guint32 knot_color = 0x0000ff00; + { + KnotHolderEntity *c = new MS::KnotHolderEntityCenterMirrorSymmetry(this); + c->create( desktop, item, knotholder, Inkscape::CTRL_TYPE_UNKNOWN, + _("Adjust the center"), knot_shape, knot_mode, knot_color ); + knotholder->add(c); + } +}; + +namespace MS { + +using namespace Geom; + +void +KnotHolderEntityCenterMirrorSymmetry::knot_set(Geom::Point const &p, Geom::Point const &origin, guint state) +{ + LPEMirrorSymmetry* lpe = dynamic_cast<LPEMirrorSymmetry *>(_effect); + Geom::Point const s = snap_knot_position(p, state); + lpe->center_point = s; + + // 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 +KnotHolderEntityCenterMirrorSymmetry::knot_get() const +{ + LPEMirrorSymmetry const *lpe = dynamic_cast<LPEMirrorSymmetry const*>(_effect); + return lpe->center_point; +} + +} // namespace CR + } //namespace LivePathEffect } /* namespace Inkscape */ diff --git a/src/live_effects/lpe-mirror_symmetry.h b/src/live_effects/lpe-mirror_symmetry.h index 64a72d7b3..3a244cb7e 100644 --- a/src/live_effects/lpe-mirror_symmetry.h +++ b/src/live_effects/lpe-mirror_symmetry.h @@ -8,6 +8,7 @@ * Authors: * Maximilian Albert * Johan Engelen + * Jabiertxof * * Copyright (C) Johan Engelen 2007 <j.b.c.engelen@utwente.nl> * Copyright (C) Maximilin Albert 2008 <maximilian.albert@gmail.com> @@ -19,22 +20,50 @@ #include "live_effects/parameter/parameter.h" #include "live_effects/parameter/point.h" #include "live_effects/parameter/path.h" +#include "live_effects/parameter/enum.h" +#include "live_effects/lpegroupbbox.h" namespace Inkscape { namespace LivePathEffect { -class LPEMirrorSymmetry : public Effect { +namespace MS { +// we need a separate namespace to avoid clashes with LPEPerpBisector +class KnotHolderEntityCenterMirrorSymmetry; +} + +enum ModeType { + MT_V, + MT_H, + MT_FREE, + MT_X, + MT_Y, + MT_END +}; + +class LPEMirrorSymmetry : public Effect, GroupBBoxEffect { public: LPEMirrorSymmetry(LivePathEffectObject *lpeobject); virtual ~LPEMirrorSymmetry(); - virtual void doOnApply (SPLPEItem const* lpeitem); - + virtual void doBeforeEffect (SPLPEItem const* lpeitem); virtual Geom::PathVector doEffect_path (Geom::PathVector const & path_in); + /* the knotholder entity classes must be declared friends */ + friend class MS::KnotHolderEntityCenterMirrorSymmetry; + void addKnotHolderEntities(KnotHolder *knotholder, SPDesktop *desktop, SPItem *item); + +protected: + virtual void addCanvasIndicators(SPLPEItem const *lpeitem, std::vector<Geom::PathVector> &hp_vec); private: + EnumParam<ModeType> mode; BoolParam discard_orig_path; - PathParam reflection_line; + BoolParam fuse_paths; + BoolParam oposite_fuse; + PointParam start_point; + PointParam end_point; + Geom::Line line_separation; + Geom::Point previous_center; + Geom::Point center_point; LPEMirrorSymmetry(const LPEMirrorSymmetry&); LPEMirrorSymmetry& operator=(const LPEMirrorSymmetry&); diff --git a/src/main.cpp b/src/main.cpp index 99e3ccfe6..8cf52127b 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -493,7 +493,7 @@ struct poptOption options[] = { POPT_ARG_NONE, &sp_vacuum_defs, SP_ARG_VACUUM_DEFS, N_("Remove unused definitions from the defs section(s) of the document"), NULL}, - + #ifdef WITH_DBUS {"dbus-listen", 0, POPT_ARG_NONE, &sp_dbus_listen, SP_ARG_DBUS_LISTEN, @@ -551,7 +551,7 @@ static void _win32_set_inkscape_env(gchar const *exe) gchar *perl = g_build_filename(exe, "python", NULL); gchar *pythonlib = g_build_filename(exe, "python", "Lib", NULL); gchar *pythondll = g_build_filename(exe, "python", "DLLs", NULL); - + // Python 2.x needs short paths in PYTHONPATH. // Otherwise it doesn't work when Inkscape is installed in Unicode directories. // g_win32_locale_filename_from_utf8 is the GLib wrapper for GetShortPathName. @@ -602,14 +602,14 @@ static void _win32_set_inkscape_env(gchar const *exe) g_free(perl); g_free(pythonlib); g_free(pythondll); - + g_free(python_s); g_free(pythonlib_s); g_free(pythondll_s); g_free(new_path); g_free(new_pythonpath); - + g_free(localepath); } #endif @@ -619,7 +619,7 @@ static void set_extensions_env() gchar const *pythonpath = g_getenv("PYTHONPATH"); gchar *extdir; gchar *new_pythonpath; - + #ifdef WIN32 extdir = g_win32_locale_filename_from_utf8(INKSCAPE_EXTENSIONDIR); #else @@ -905,7 +905,7 @@ static int sp_common_main( int argc, char const **argv, GSList **flDest ) if ( sp_global_printer ) sp_global_printer_utf8 = g_strdup( sp_global_printer ); } - + #ifdef WITH_DBUS // Before initializing extensions, we must set the DBus bus name if required if (sp_dbus_name != NULL) { @@ -1064,25 +1064,56 @@ sp_main_gui(int argc, char const **argv) Glib::ustring inkscape_style = INKSCAPE_UIDIR; inkscape_style += "/style.css"; // std::cout << "CSS Stylesheet Inkscape: " << inkscape_style << std::endl; - Glib::RefPtr<Gtk::CssProvider> provider = Gtk::CssProvider::create(); - try { - provider->load_from_path (inkscape_style); - } - catch (const Gtk::CssProviderError& ex) - { - std::cerr << "CSSProviderError::load_from_path(): failed to load: " << inkscape_style << "\n (" << ex.what() << ")" << std::endl; + + if (g_file_test (inkscape_style.c_str(), G_FILE_TEST_EXISTS)) { + Glib::RefPtr<Gtk::CssProvider> provider = Gtk::CssProvider::create(); + + // From 3.16, throws an error which we must catch. + try { + provider->load_from_path (inkscape_style); + } +#if GTK_CHECK_VERSION(3,16,0) + // Gtk::CssProviderError not defined until 3.16. + catch (const Gtk::CssProviderError& ex) + { + std::cerr << "CSSProviderError::load_from_path(): failed to load: " << inkscape_style + << "\n (" << ex.what() << ")" << std::endl; + } +#else + catch (...) + {} +#endif + + Gtk::StyleContext::add_provider_for_screen (screen, provider, GTK_STYLE_PROVIDER_PRIORITY_APPLICATION); + } else { + std::cerr << "sp_main_gui: Cannot find default style file:\n (" << inkscape_style + << ")" << std::endl; } - Gtk::StyleContext::add_provider_for_screen (screen, provider, GTK_STYLE_PROVIDER_PRIORITY_APPLICATION); Glib::ustring user_style = Inkscape::Application::profile_path("ui/style.css"); // std::cout << "CSS Stylesheet User: " << user_style << std::endl; - Glib::RefPtr<Gtk::CssProvider> provider2 = Gtk::CssProvider::create(); - try { - provider2->load_from_path (user_style); + + if (g_file_test (user_style.c_str(), G_FILE_TEST_EXISTS)) { + Glib::RefPtr<Gtk::CssProvider> provider2 = Gtk::CssProvider::create(); + + // From 3.16, throws an error which we must catch. + try { + provider2->load_from_path (user_style); + } +#if GTK_CHECK_VERSION(3,16,0) + // Gtk::CssProviderError not defined until 3.16. + catch (const Gtk::CssProviderError& ex) + { + std::cerr << "CSSProviderError::load_from_path(): failed to load: " << user_style + << "\n (" << ex.what() << ")" << std::endl; + } +#else + catch (...) + {} +#endif + + Gtk::StyleContext::add_provider_for_screen (screen, provider2, GTK_STYLE_PROVIDER_PRIORITY_APPLICATION); } - catch (const Gtk::CssProviderError& ex) - {} - Gtk::StyleContext::add_provider_for_screen (screen, provider2, GTK_STYLE_PROVIDER_PRIORITY_APPLICATION); #endif gdk_event_handler_set((GdkEventFunc)snooper, NULL, NULL); @@ -1168,7 +1199,7 @@ static int sp_process_file_list(GSList *fl) if (sp_vacuum_defs) { doc->vacuumDocument(); } - + // Execute command-line actions (selections and verbs) using our local models bool has_performed_actions = Inkscape::CmdLineAction::doList(INKSCAPE.active_action_context()); @@ -1679,9 +1710,9 @@ static int sp_do_export_png(SPDocument *doc) g_print("Background RRGGBBAA: %08x\n", bgcolor); g_print("Area %g:%g:%g:%g exported to %lu x %lu pixels (%g dpi)\n", area[Geom::X][0], area[Geom::Y][0], area[Geom::X][1], area[Geom::Y][1], width, height, dpi); - + reverse(items.begin(),items.end()); - + if ((width >= 1) && (height >= 1) && (width <= PNG_UINT_31_MAX) && (height <= PNG_UINT_31_MAX)) { if( sp_export_png_file(doc, path.c_str(), area, width, height, dpi, dpi, bgcolor, NULL, NULL, true, sp_export_id_only ? items : std::vector<SPItem*>()) == 1 ) { @@ -1851,7 +1882,7 @@ static int do_export_ps_pdf(SPDocument* doc, gchar const* uri, char const* mime) } /** - * Export a document to EMF or WMF + * Export a document to EMF or WMF * * \param doc Document to export. * \param uri URI to export to. diff --git a/src/profile-manager.cpp b/src/profile-manager.cpp index 035aa6051..26e1cd72c 100644 --- a/src/profile-manager.cpp +++ b/src/profile-manager.cpp @@ -34,9 +34,8 @@ void ProfileManager::_resourcesChanged() { std::vector<SPObject*> newList; if (_doc) { - std::set<SPObject *> current = _doc->getResourceList( "iccprofile" ); - for (std::set<SPObject *>::const_iterator i = current.begin(); i != current.end(); ++i) - newList.push_back(*i); + std::vector<SPObject *> current = _doc->getResourceList( "iccprofile" ); + newList = current; } sort( newList.begin(), newList.end() ); diff --git a/src/pure-transform.cpp b/src/pure-transform.cpp index 9c7054b9f..db4926258 100644 --- a/src/pure-transform.cpp +++ b/src/pure-transform.cpp @@ -63,9 +63,9 @@ void PureTransform::snap(::SnapManager *sm, std::vector<Inkscape::SnapCandidateP (*j).setSourceNum(0); first_free_snap = false; } + Inkscape::SnappedPoint snapped_point = snap(sm, *j, (*i).getPoint(), bbox); // Calls the snap() method of the derived classes - // std::cout << "dist = " << snapped_point.getSnapDistance() << std::endl; snapped_point.setPointerDistance(Geom::L2(pointer - (*i).getPoint())); /*Find the transformation that describes where the snapped point has @@ -85,16 +85,22 @@ void PureTransform::snap(::SnapManager *sm, std::vector<Inkscape::SnapCandidateP // We might still need to apply a constraint though, if we tried a constrained snap. And // in case of a free snap we might have use for the transformed point, so let's return that // point, whether it's constrained or not - if (best_snapped_point.isOtherSnapBetter(snapped_point, true) || points.size() == 1) { - // .. so we must keep track of the best non-snapped constrained point + + if (best_snapped_point.isOtherSnapBetter(snapped_point, true) ) { + // .. so we must keep track of the best non-snapped constrained point.. but what + // is the best? There is no best, or is there? We cannot compare on snapped distance + // because neither has snapped, and both have their snapped distance set to infinity. + // There might be a difference in "constrainedness" though, 1D vs 2D snapping store_best_snap = true; } } } - if (store_best_snap) { + if (store_best_snap || i == points.begin()) { best_original_point = (*i); - best_snapped_point = snapped_point; + best_snapped_point = snapped_point; // Can be a point that didn't snap, but then at least we + // return something meaningful; we might have use for the transformation. The default + // snapped_point, as initialized before this loop, is not very meaningful at all. } ++j; @@ -119,7 +125,7 @@ Geom::Point PureTranslate::getTransformedPoint(SnapCandidatePoint const &p) cons return p.getPoint() + _vector; } -void PureTranslate::storeTransform(SnapCandidatePoint const original_point, SnappedPoint const snapped_point) { +void PureTranslate::storeTransform(SnapCandidatePoint const &original_point, SnappedPoint &snapped_point) { /* Consider the case in which a box is almost aligned with a grid in both * horizontal and vertical directions. The distance to the intersection of * the grid lines will always be larger then the distance to a single grid @@ -156,7 +162,7 @@ Geom::Point PureScale::getTransformedPoint(SnapCandidatePoint const &p) const { return (p.getPoint() - _origin) * _scale + _origin; } -void PureScale::storeTransform(SnapCandidatePoint const original_point, SnappedPoint snapped_point) { +void PureScale::storeTransform(SnapCandidatePoint const &original_point, SnappedPoint &snapped_point) { _scale_snapped = Geom::Scale(Geom::infinity(), Geom::infinity()); // If this point *i is horizontally or vertically aligned with // the origin of the scaling, then it will scale purely in X or Y @@ -174,6 +180,14 @@ void PureScale::storeTransform(SnapCandidatePoint const original_point, SnappedP // we might have left result[1-index] = Geom::infinity() if scaling didn't occur in the other direction } } + + if (_scale_snapped == Geom::Scale(Geom::infinity(), Geom::infinity())) { + // This point must have been at the origin, so we cannot possibly snap; it won't scale (i.e. won't move while dragging) + snapped_point.setSnapDistance(Geom::infinity()); + snapped_point.setSecondSnapDistance(Geom::infinity()); + return; + } + if (_uniform) { // Lock the scaling the be uniform, but keep the sign such that we don't change which quadrant we have dragged into if (fabs(_scale_snapped[0]) < fabs(_scale_snapped[1])) { @@ -253,16 +267,16 @@ SnappedPoint PureStretchConstrained::snap(::SnapManager *sm, SnapCandidatePoint return sm->constrainedSnap(p, dedicated_constraint, bbox_to_snap); } -void PureStretchConstrained::storeTransform(SnapCandidatePoint const original_point, SnappedPoint snapped_point) { +void PureStretchConstrained::storeTransform(SnapCandidatePoint const &original_point, SnappedPoint &snapped_point) { Geom::Point const a = snapped_point.getPoint() - _origin; // vector to snapped point Geom::Point const b = original_point.getPoint() - _origin; // vector to original point (not the transformed point!) _stretch_snapped = Geom::Scale(Geom::infinity(), Geom::infinity()); - if (fabs(b[_direction]) > 1e-6) { // if STRETCHING will occur for this point + if (fabs(b[_direction]) > 1e-4) { // if STRETCHING will occur for this point _stretch_snapped[_direction] = a[_direction] / b[_direction]; _stretch_snapped[1-_direction] = _uniform ? _stretch_snapped[_direction] : 1; } else { // STRETCHING might occur for this point, but only when the stretching is uniform - if (_uniform && fabs(b[1-_direction]) > 1e-6) { + if (_uniform && fabs(b[1-_direction]) > 1e-4) { _stretch_snapped[1-_direction] = a[1-_direction] / b[1-_direction]; _stretch_snapped[_direction] = _stretch_snapped[1-_direction]; } @@ -304,7 +318,7 @@ SnappedPoint PureSkewConstrained::snap(::SnapManager *sm, SnapCandidatePoint con return sm->constrainedSnap(p, Inkscape::Snapper::SnapConstraint(constraint_vector), bbox_to_snap); } -void PureSkewConstrained::storeTransform(SnapCandidatePoint const original_point, SnappedPoint snapped_point) { +void PureSkewConstrained::storeTransform(SnapCandidatePoint const &original_point, SnappedPoint &snapped_point) { Geom::Point const b = original_point.getPoint() - _origin; // vector to original point (not the transformed point!) _skew_snapped = (snapped_point.getPoint()[_direction] - (original_point.getPoint())[_direction]) / b[1 - _direction]; // skew factor @@ -335,7 +349,7 @@ SnappedPoint PureRotateConstrained::snap(::SnapManager *sm, SnapCandidatePoint c return sm->constrainedSnap(p, dedicated_constraint, bbox_to_snap); } -void PureRotateConstrained::storeTransform(SnapCandidatePoint const original_point, SnappedPoint snapped_point) { +void PureRotateConstrained::storeTransform(SnapCandidatePoint const &original_point, SnappedPoint &snapped_point) { Geom::Point const a = snapped_point.getPoint() - _origin; // vector to snapped point Geom::Point const b = (original_point.getPoint() - _origin); // vector to original point (not the transformed point!) // a is vector to snapped point; b is vector to original point; now lets calculate angle between a and b diff --git a/src/pure-transform.h b/src/pure-transform.h index f973a95b1..98aa9772a 100644 --- a/src/pure-transform.h +++ b/src/pure-transform.h @@ -26,7 +26,7 @@ class PureTransform { protected: virtual SnappedPoint snap(::SnapManager *sm, SnapCandidatePoint const &p, Geom::Point pt_orig, Geom::OptRect const &bbox_to_snap) const = 0; virtual Geom::Point getTransformedPoint(SnapCandidatePoint const &p) const = 0; - virtual void storeTransform(SnapCandidatePoint const original_point, SnappedPoint snapped_point) = 0; + virtual void storeTransform(SnapCandidatePoint const &original_point, SnappedPoint &snapped_point) = 0; public: //PureTransform(); @@ -48,7 +48,7 @@ protected: virtual SnappedPoint snap(::SnapManager *sm, SnapCandidatePoint const &p, Geom::Point pt_orig, Geom::OptRect const &bbox_to_snap) const; virtual Geom::Point getTransformedPoint(SnapCandidatePoint const &p) const; - virtual void storeTransform(SnapCandidatePoint const original_point, SnappedPoint snapped_point); + virtual void storeTransform(SnapCandidatePoint const &original_point, SnappedPoint &snapped_point); public: // PureTranslate(); // Default constructor @@ -90,7 +90,7 @@ protected: virtual SnappedPoint snap(::SnapManager *sm, SnapCandidatePoint const &p, Geom::Point pt_orig, Geom::OptRect const &bbox_to_snap) const; virtual Geom::Point getTransformedPoint(SnapCandidatePoint const &p) const; - virtual void storeTransform(SnapCandidatePoint const original_point, SnappedPoint snapped_point); + virtual void storeTransform(SnapCandidatePoint const &original_point, SnappedPoint &snapped_point); public: // PureScale(); // Default constructor @@ -135,7 +135,7 @@ protected: virtual SnappedPoint snap(::SnapManager *sm, SnapCandidatePoint const &p, Geom::Point pt_orig, Geom::OptRect const &bbox_to_snap) const; virtual Geom::Point getTransformedPoint(SnapCandidatePoint const &p) const; - virtual void storeTransform(SnapCandidatePoint const original_point, SnappedPoint snapped_point); + virtual void storeTransform(SnapCandidatePoint const &original_point, SnappedPoint &snapped_point); public: virtual ~PureStretchConstrained() {}; @@ -172,7 +172,7 @@ protected: virtual SnappedPoint snap(::SnapManager *sm, SnapCandidatePoint const &p, Geom::Point pt_orig, Geom::OptRect const &bbox_to_snap) const; Geom::Point getTransformedPoint(SnapCandidatePoint const &p) const; - virtual void storeTransform(SnapCandidatePoint const original_point, SnappedPoint snapped_point); + virtual void storeTransform(SnapCandidatePoint const &original_point, SnappedPoint &snapped_point); public: virtual ~PureSkewConstrained() {}; @@ -203,7 +203,7 @@ protected: virtual SnappedPoint snap(::SnapManager *sm, SnapCandidatePoint const &p, Geom::Point pt_orig, Geom::OptRect const &bbox_to_snap) const; virtual Geom::Point getTransformedPoint(SnapCandidatePoint const &p) const; - virtual void storeTransform(SnapCandidatePoint const original_point, SnappedPoint snapped_point); + virtual void storeTransform(SnapCandidatePoint const &original_point, SnappedPoint &snapped_point); public: // PureRotate(); // Default constructor diff --git a/src/resource-manager.cpp b/src/resource-manager.cpp index 18d7c6ba2..09b9364c6 100644 --- a/src/resource-manager.cpp +++ b/src/resource-manager.cpp @@ -179,8 +179,8 @@ std::vector<Glib::ustring> ResourceManagerImpl::findBrokenLinks( SPDocument *doc std::set<Glib::ustring> uniques; if ( doc ) { - std::set<SPObject *> images = doc->getResourceList("image"); - for (std::set<SPObject *>::const_iterator it = images.begin(); it != images.end(); ++it) { + std::vector<SPObject *> images = doc->getResourceList("image"); + for (std::vector<SPObject *>::const_iterator it = images.begin(); it != images.end(); ++it) { Inkscape::XML::Node *ir = (*it)->getRepr(); gchar const *href = ir->attribute("xlink:href"); @@ -306,8 +306,8 @@ bool ResourceManagerImpl::fixupBrokenLinks(SPDocument *doc) bool savedUndoState = DocumentUndo::getUndoSensitive(doc); DocumentUndo::setUndoSensitive(doc, true); - std::set<SPObject *> images = doc->getResourceList("image"); - for (std::set<SPObject *>::const_iterator it = images.begin(); it != images.end(); ++it) { + std::vector<SPObject *> images = doc->getResourceList("image"); + for (std::vector<SPObject *>::const_iterator it = images.begin(); it != images.end(); ++it) { Inkscape::XML::Node *ir = (*it)->getRepr(); gchar const *href = ir->attribute("xlink:href"); diff --git a/src/sp-flowtext.h b/src/sp-flowtext.h index 9e6046469..9ee676893 100644 --- a/src/sp-flowtext.h +++ b/src/sp-flowtext.h @@ -49,6 +49,11 @@ public: bool _optimizeScaledText; + /** Converts the text object to its component curves */ + SPCurve *getNormalizedBpath() const { + return layout.convertToCurves(); + } + /** Optimize scaled flow text on next set_transform. */ void optimizeScaledText() {_optimizeScaledText = true;} diff --git a/src/sp-guide.cpp b/src/sp-guide.cpp index 17a1a9ff1..c80fc7122 100644 --- a/src/sp-guide.cpp +++ b/src/sp-guide.cpp @@ -264,7 +264,7 @@ void sp_guide_create_guides_around_page(SPDesktop *dt) void sp_guide_delete_all_guides(SPDesktop *dt) { SPDocument *doc=dt->getDocument(); - std::set<SPObject *> current = doc->getResourceList("guide"); + std::vector<SPObject *> current = doc->getResourceList("guide"); while (!current.empty()){ SPGuide* guide = SP_GUIDE(*(current.begin())); sp_guide_remove(guide); diff --git a/src/splivarot.cpp b/src/splivarot.cpp index c37df151c..1bc6da3e1 100644 --- a/src/splivarot.cpp +++ b/src/splivarot.cpp @@ -1776,11 +1776,14 @@ sp_selected_path_do_offset(SPDesktop *desktop, bool expand, double prefOffset) SPItem *item = *l; SPCurve *curve = NULL; - if (!SP_IS_SHAPE(item) && !SP_IS_TEXT(item)) + if (!SP_IS_SHAPE(item) && !SP_IS_TEXT(item) && !SP_IS_FLOWTEXT(item)) continue; else if (SP_IS_SHAPE(item)) { curve = SP_SHAPE(item)->getCurve(); } + else if (SP_IS_FLOWTEXT(item)) { + curve = SP_FLOWTEXT(item)->getNormalizedBpath(); + } else { // Item must be SP_TEXT curve = SP_TEXT(item)->getNormalizedBpath(); } diff --git a/src/ui/dialog/color-item.cpp b/src/ui/dialog/color-item.cpp index 6603d5c69..34cdb92e3 100644 --- a/src/ui/dialog/color-item.cpp +++ b/src/ui/dialog/color-item.cpp @@ -571,6 +571,8 @@ Gtk::Widget* ColorItem::getPreview(PreviewStyle style, ViewType view, ::PreviewS widget = lbl; } else { GtkWidget* eekWidget = eek_preview_new(); + gtk_widget_set_name( eekWidget, "ColorItemPreview" ); + EekPreview * preview = EEK_PREVIEW(eekWidget); Gtk::Widget* newBlot = Glib::wrap(eekWidget); _regenPreview(preview); diff --git a/src/ui/dialog/document-properties.cpp b/src/ui/dialog/document-properties.cpp index c2c5c5005..12eaba72a 100644 --- a/src/ui/dialog/document-properties.cpp +++ b/src/ui/dialog/document-properties.cpp @@ -492,8 +492,8 @@ void DocumentProperties::linkSelectedProfile() std::vector<std::pair<Glib::ustring, Glib::ustring> > pairs = ColorProfile::getProfileFilesWithNames(); Glib::ustring file = pairs[row].first; Glib::ustring name = pairs[row].second; - std::set<SPObject *> current = SP_ACTIVE_DOCUMENT->getResourceList( "iccprofile" ); - for (std::set<SPObject *>::const_iterator it = current.begin(); it != current.end(); ++it) { + std::vector<SPObject *> current = SP_ACTIVE_DOCUMENT->getResourceList( "iccprofile" ); + for (std::vector<SPObject *>::const_iterator it = current.begin(); it != current.end(); ++it) { SPObject* obj = *it; Inkscape::ColorProfile* prof = reinterpret_cast<Inkscape::ColorProfile*>(obj); if (!strcmp(prof->href, file.c_str())) @@ -532,11 +532,11 @@ void DocumentProperties::linkSelectedProfile() void DocumentProperties::populate_linked_profiles_box() { _LinkedProfilesListStore->clear(); - std::set<SPObject *> current = SP_ACTIVE_DOCUMENT->getResourceList( "iccprofile" ); + std::vector<SPObject *> current = SP_ACTIVE_DOCUMENT->getResourceList( "iccprofile" ); if (! current.empty()) { _emb_profiles_observer.set((*(current.begin()))->parent); } - for (std::set<SPObject *>::const_iterator it = current.begin(); it != current.end(); ++it) { + for (std::vector<SPObject *>::const_iterator it = current.begin(); it != current.end(); ++it) { SPObject* obj = *it; Inkscape::ColorProfile* prof = reinterpret_cast<Inkscape::ColorProfile*>(obj); Gtk::TreeModel::Row row = *(_LinkedProfilesListStore->append()); @@ -614,8 +614,8 @@ void DocumentProperties::removeSelectedProfile(){ return; } } - std::set<SPObject *> current = SP_ACTIVE_DOCUMENT->getResourceList( "iccprofile" ); - for (std::set<SPObject *>::const_iterator it = current.begin(); it != current.end(); ++it) { + std::vector<SPObject *> current = SP_ACTIVE_DOCUMENT->getResourceList( "iccprofile" ); + for (std::vector<SPObject *>::const_iterator it = current.begin(); it != current.end(); ++it) { SPObject* obj = *it; Inkscape::ColorProfile* prof = reinterpret_cast<Inkscape::ColorProfile*>(obj); if (!name.compare(prof->name)){ @@ -738,7 +738,7 @@ void DocumentProperties::build_cms() _LinkedProfilesList.signal_button_release_event().connect_notify(sigc::mem_fun(*this, &DocumentProperties::linked_profiles_list_button_release)); cms_create_popup_menu(_LinkedProfilesList, sigc::mem_fun(*this, &DocumentProperties::removeSelectedProfile)); - std::set<SPObject *> current = SP_ACTIVE_DOCUMENT->getResourceList( "defs" ); + std::vector<SPObject *> current = SP_ACTIVE_DOCUMENT->getResourceList( "defs" ); if (!current.empty()) { _emb_profiles_observer.set((*(current.begin()))->parent); } @@ -975,7 +975,7 @@ void DocumentProperties::build_scripting() #endif // defined(HAVE_LIBLCMS1) || defined(HAVE_LIBLCMS2) //TODO: review this observers code: - std::set<SPObject *> current = SP_ACTIVE_DOCUMENT->getResourceList( "script" ); + std::vector<SPObject *> current = SP_ACTIVE_DOCUMENT->getResourceList( "script" ); if (! current.empty()) { _scripts_observer.set((*(current.begin()))->parent); } @@ -1190,8 +1190,8 @@ void DocumentProperties::removeExternalScript(){ } } - std::set<SPObject *> current = SP_ACTIVE_DOCUMENT->getResourceList( "script" ); - for (std::set<SPObject *>::const_iterator it = current.begin(); it != current.end(); ++it) { + std::vector<SPObject *> current = SP_ACTIVE_DOCUMENT->getResourceList( "script" ); + for (std::vector<SPObject *>::const_iterator it = current.begin(); it != current.end(); ++it) { SPObject* obj = *it; if (obj) { SPScript* script = dynamic_cast<SPScript *>(obj); @@ -1268,8 +1268,8 @@ void DocumentProperties::changeEmbeddedScript(){ } bool voidscript=true; - std::set<SPObject *> current = SP_ACTIVE_DOCUMENT->getResourceList( "script" ); - for (std::set<SPObject *>::const_iterator it = current.begin(); it != current.end(); ++it) { + std::vector<SPObject *> current = SP_ACTIVE_DOCUMENT->getResourceList( "script" ); + for (std::vector<SPObject *>::const_iterator it = current.begin(); it != current.end(); ++it) { SPObject* obj = *it; if (id == obj->getId()){ @@ -1313,8 +1313,8 @@ void DocumentProperties::editEmbeddedScript(){ } Inkscape::XML::Document *xml_doc = SP_ACTIVE_DOCUMENT->getReprDoc(); - std::set<SPObject *> current = SP_ACTIVE_DOCUMENT->getResourceList( "script" ); - for (std::set<SPObject *>::const_iterator it = current.begin(); it != current.end(); ++it) { + std::vector<SPObject *> current = SP_ACTIVE_DOCUMENT->getResourceList( "script" ); + for (std::vector<SPObject *>::const_iterator it = current.begin(); it != current.end(); ++it) { SPObject* obj = *it; if (id == obj->getId()){ @@ -1337,13 +1337,13 @@ void DocumentProperties::editEmbeddedScript(){ void DocumentProperties::populate_script_lists(){ _ExternalScriptsListStore->clear(); _EmbeddedScriptsListStore->clear(); - std::set<SPObject *> current = SP_ACTIVE_DOCUMENT->getResourceList( "script" ); + std::vector<SPObject *> current = SP_ACTIVE_DOCUMENT->getResourceList( "script" ); if (!current.empty()) { SPObject *obj = *(current.begin()); g_assert(obj != NULL); _scripts_observer.set(obj->parent); } - for (std::set<SPObject *>::const_iterator it = current.begin(); it != current.end(); ++it) { + for (std::vector<SPObject *>::const_iterator it = current.begin(); it != current.end(); ++it) { SPObject* obj = *it; SPScript* script = dynamic_cast<SPScript *>(obj); g_assert(script != NULL); diff --git a/src/ui/dialog/filter-effects-dialog.cpp b/src/ui/dialog/filter-effects-dialog.cpp index ce08ed1f7..d3ad5d1da 100644 --- a/src/ui/dialog/filter-effects-dialog.cpp +++ b/src/ui/dialog/filter-effects-dialog.cpp @@ -1591,11 +1591,11 @@ void FilterEffectsDialog::FilterModifier::update_filters() SPDesktop* desktop = _dialog.getDesktop(); SPDocument* document = desktop->getDocument(); - std::set<SPObject *> filters = document->getResourceList( "filter" ); + std::vector<SPObject *> filters = document->getResourceList( "filter" ); _model->clear(); - for (std::set<SPObject *>::const_iterator it = filters.begin(); it != filters.end(); ++it) { + for (std::vector<SPObject *>::const_iterator it = filters.begin(); it != filters.end(); ++it) { Gtk::TreeModel::Row row = *_model->append(); SPFilter* f = SP_FILTER(*it); row[_columns.filter] = f; diff --git a/src/ui/dialog/inkscape-preferences.cpp b/src/ui/dialog/inkscape-preferences.cpp index c7a168dee..30bbd95c9 100644 --- a/src/ui/dialog/inkscape-preferences.cpp +++ b/src/ui/dialog/inkscape-preferences.cpp @@ -210,8 +210,8 @@ void InkscapePreferences::AddBaseSimplifySpinbutton(DialogPage &p, Glib::ustring { PrefSpinButton* sb = Gtk::manage( new PrefSpinButton); sb->init ( prefs_path + "/base-simplify", 0.0, 100.0, 1.0, 10.0, def_value, false, false); - p.add_line( false, _("Base simplify:"), *sb, _("on dinamic LPE simplify"), - _("Base simplify of dinamic LPE based simplify"), + p.add_line( false, _("Base simplify:"), *sb, _("on dynamic LPE simplify"), + _("Base simplify of dynamic LPE based simplify"), false ); } diff --git a/src/ui/dialog/svg-fonts-dialog.cpp b/src/ui/dialog/svg-fonts-dialog.cpp index 46e045c14..790c0e5fb 100644 --- a/src/ui/dialog/svg-fonts-dialog.cpp +++ b/src/ui/dialog/svg-fonts-dialog.cpp @@ -266,10 +266,10 @@ void SvgFontsDialog::update_fonts() { SPDesktop* desktop = this->getDesktop(); SPDocument* document = desktop->getDocument(); - std::set<SPObject *> fonts = document->getResourceList( "fonts" ); + std::vector<SPObject *> fonts = document->getResourceList( "fonts" ); _model->clear(); - for (std::set<SPObject *>::const_iterator it = fonts.begin(); it != fonts.end(); ++it) { + for (std::vector<SPObject *>::const_iterator it = fonts.begin(); it != fonts.end(); ++it) { Gtk::TreeModel::Row row = *_model->append(); SPFont* f = SP_FONT(*it); row[_columns.spfont] = f; diff --git a/src/ui/dialog/swatches.cpp b/src/ui/dialog/swatches.cpp index 924ebe03d..6577c8d4e 100644 --- a/src/ui/dialog/swatches.cpp +++ b/src/ui/dialog/swatches.cpp @@ -171,8 +171,8 @@ static void editGradient( GtkMenuItem */*menuitem*/, gpointer /*user_data*/ ) SPDocument *doc = desktop ? desktop->doc() : 0; if (doc) { std::string targetName(bounceTarget->def.descr); - std::set<SPObject *> gradients = doc->getResourceList("gradient"); - for (std::set<SPObject *>::const_iterator item = gradients.begin(); item != gradients.end(); ++item) { + std::vector<SPObject *> gradients = doc->getResourceList("gradient"); + for (std::vector<SPObject *>::const_iterator item = gradients.begin(); item != gradients.end(); ++item) { SPGradient* grad = SP_GRADIENT(*item); if ( targetName == grad->getId() ) { editGradientImpl( desktop, grad ); @@ -192,8 +192,8 @@ void SwatchesPanelHook::convertGradient( GtkMenuItem * /*menuitem*/, gpointer us gint index = GPOINTER_TO_INT(userData); if ( doc && (index >= 0) && (static_cast<guint>(index) < popupItems.size()) ) { Glib::ustring targetName = popupItems[index]; - std::set<SPObject *> gradients = doc->getResourceList("gradient"); - for (std::set<SPObject *>::const_iterator item = gradients.begin(); item != gradients.end(); ++item) { + std::vector<SPObject *> gradients = doc->getResourceList("gradient"); + for (std::vector<SPObject *>::const_iterator item = gradients.begin(); item != gradients.end(); ++item) { SPGradient* grad = SP_GRADIENT(*item); if ( targetName == grad->getId() ) { @@ -326,9 +326,9 @@ gboolean colorItemHandleButtonPress( GtkWidget* widget, GdkEventButton* event, g SPDesktopWidget *dtw = SP_DESKTOP_WIDGET(wdgt); if ( dtw && dtw->desktop ) { // Pick up all gradients with vectors - std::set<SPObject *> gradients = (dtw->desktop->doc())->getResourceList("gradient"); + std::vector<SPObject *> gradients = (dtw->desktop->doc())->getResourceList("gradient"); gint index = 0; - for (std::set<SPObject *>::const_iterator item = gradients.begin(); item != gradients.end(); ++item) { + for (std::vector<SPObject *>::const_iterator item = gradients.begin(); item != gradients.end(); ++item) { SPGradient* grad = SP_GRADIENT(*item); if ( grad->hasStops() && !grad->isSwatch() ) { //gl = g_slist_prepend(gl, curr->data); @@ -594,6 +594,7 @@ SwatchesPanel::SwatchesPanel(gchar const* prefsPath) : _currentDesktop(0), _currentDocument(0) { + set_name( "SwatchesPanel" ); Gtk::RadioMenuItem* hotItem = 0; _holder = new PreviewHolder(); _clear = new ColorItem( ege::PaintDef::CLEAR ); @@ -924,8 +925,8 @@ static void recalcSwatchContents(SPDocument* doc, std::map<ColorItem*, SPGradient*> &gradMappings) { std::vector<SPGradient*> newList; - std::set<SPObject *> gradients = doc->getResourceList("gradient"); - for (std::set<SPObject *>::const_iterator item = gradients.begin(); item != gradients.end(); ++item) { + std::vector<SPObject *> gradients = doc->getResourceList("gradient"); + for (std::vector<SPObject *>::const_iterator item = gradients.begin(); item != gradients.end(); ++item) { SPGradient* grad = SP_GRADIENT(*item); if ( grad->isSwatch() ) { newList.push_back(SP_GRADIENT(*item)); diff --git a/src/ui/interface.cpp b/src/ui/interface.cpp index 3e2a2004c..ab29471ed 100644 --- a/src/ui/interface.cpp +++ b/src/ui/interface.cpp @@ -1128,8 +1128,8 @@ sp_ui_drag_data_received(GtkWidget *widget, unsigned int b = color.getB(); SPGradient* matches = 0; - std::set<SPObject *> gradients = doc->getResourceList("gradient"); - for (std::set<SPObject *>::const_iterator item = gradients.begin(); item != gradients.end(); ++item) { + std::vector<SPObject *> gradients = doc->getResourceList("gradient"); + for (std::vector<SPObject *>::const_iterator item = gradients.begin(); item != gradients.end(); ++item) { SPGradient* grad = SP_GRADIENT(*item); if ( color.descr == grad->getId() ) { if ( grad->hasStops() ) { diff --git a/src/ui/previewholder.cpp b/src/ui/previewholder.cpp index beb83f35c..5e75179a3 100644 --- a/src/ui/previewholder.cpp +++ b/src/ui/previewholder.cpp @@ -49,16 +49,20 @@ PreviewHolder::PreviewHolder() : _wrap(false), _border(BORDER_NONE) { + set_name( "PreviewHolder" ); _scroller = Gtk::manage(new Gtk::ScrolledWindow()); + _scroller->set_name( "PreviewHolderScroller" ); ((Gtk::ScrolledWindow *)_scroller)->set_policy(Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC); #if WITH_GTKMM_3_0 _insides = Gtk::manage(new Gtk::Grid()); + _insides->set_name( "PreviewHolderGrid" ); _insides->set_column_spacing(8); // Add a container with the scroller and a spacer Gtk::Grid* spaceHolder = Gtk::manage(new Gtk::Grid()); + spaceHolder->set_name( "PreviewHolderSpaceHolder" ); _scroller->set_hexpand(); _scroller->set_vexpand(); diff --git a/src/ui/tool/path-manipulator.cpp b/src/ui/tool/path-manipulator.cpp index 3b25439f3..de071dad3 100644 --- a/src/ui/tool/path-manipulator.cpp +++ b/src/ui/tool/path-manipulator.cpp @@ -1292,7 +1292,7 @@ double PathManipulator::_bsplineHandlePosition(Handle *h, bool check_other) line_inside_nodes->moveto(n->position()); line_inside_nodes->lineto(next_node->position()); if(!are_near(h->position(), n->position())){ - pos = Geom::nearest_time(Geom::Point(h->position()[X] - HANDLE_CUBIC_GAP, h->position()[Y] + HANDLE_CUBIC_GAP), *line_inside_nodes->first_segment()); + pos = Geom::nearest_time(Geom::Point(h->position()[X] - HANDLE_CUBIC_GAP, h->position()[Y] - HANDLE_CUBIC_GAP), *line_inside_nodes->first_segment()); } } if (pos == NO_POWER && check_other){ diff --git a/src/ui/tools/freehand-base.cpp b/src/ui/tools/freehand-base.cpp index 613857626..c98ecb686 100644 --- a/src/ui/tools/freehand-base.cpp +++ b/src/ui/tools/freehand-base.cpp @@ -43,6 +43,7 @@ #include "snap.h" #include "sp-path.h" #include "sp-use.h" +#include "sp-item-group.h" #include "sp-namedview.h" #include "live_effects/lpe-powerstroke.h" #include "style.h" @@ -432,7 +433,7 @@ static void spdc_check_for_and_apply_waiting_LPE(FreehandBase *dc, SPItem *item, if(cm->paste(SP_ACTIVE_DESKTOP,true) == true){ gchar const *svgd = item->getRepr()->attribute("d"); bend_item = dc->selection->singleItem(); - if(bend_item){ + if(bend_item && (SP_IS_SHAPE(bend_item) || SP_IS_GROUP(bend_item))){ bend_item->moveTo(item,false); bend_item->transform.setTranslation(Geom::Point()); spdc_apply_bend_shape(svgd, dc, bend_item); @@ -440,9 +441,11 @@ static void spdc_check_for_and_apply_waiting_LPE(FreehandBase *dc, SPItem *item, shape = BEND_CLIPBOARD; } else { + bend_item = NULL; shape = NONE; } } else { + bend_item = NULL; shape = NONE; } break; diff --git a/src/ui/widget/color-icc-selector.cpp b/src/ui/widget/color-icc-selector.cpp index ec2e69fb3..2e30a48b5 100644 --- a/src/ui/widget/color-icc-selector.cpp +++ b/src/ui/widget/color-icc-selector.cpp @@ -687,8 +687,8 @@ void ColorICCSelectorImpl::_profilesChanged(std::string const &name) gtk_combo_box_set_active(combo, 0); int index = 1; - std::set<SPObject *> current = SP_ACTIVE_DOCUMENT->getResourceList("iccprofile"); - for (std::set<SPObject *>::const_iterator it = current.begin(); it != current.end(); ++it) { + std::vector<SPObject *> current = SP_ACTIVE_DOCUMENT->getResourceList("iccprofile"); + for (std::vector<SPObject *>::const_iterator it = current.begin(); it != current.end(); ++it) { SPObject *obj = *it; Inkscape::ColorProfile *prof = reinterpret_cast<Inkscape::ColorProfile *>(obj); diff --git a/src/ui/widget/color-preview.cpp b/src/ui/widget/color-preview.cpp index 5bcd16528..62c7cca1d 100644 --- a/src/ui/widget/color-preview.cpp +++ b/src/ui/widget/color-preview.cpp @@ -23,6 +23,7 @@ ColorPreview::ColorPreview (guint32 rgba) { _rgba = rgba; set_has_window(false); + set_name("ColorPreview"); } void diff --git a/src/ui/widget/dock.cpp b/src/ui/widget/dock.cpp index c5e14d4f0..fda647182 100644 --- a/src/ui/widget/dock.cpp +++ b/src/ui/widget/dock.cpp @@ -56,6 +56,7 @@ Dock::Dock(Gtk::Orientation orientation) #endif _scrolled_window (Gtk::manage(new Gtk::ScrolledWindow)) { + _scrolled_window->set_name("Dock"); #if WITH_GDL_3_6 gtk_orientable_set_orientation(GTK_ORIENTABLE(_gdl_dock_bar), static_cast<GtkOrientation>(orientation)); diff --git a/src/ui/widget/layer-selector.cpp b/src/ui/widget/layer-selector.cpp index 2a1fa352b..1a9ce617f 100644 --- a/src/ui/widget/layer-selector.cpp +++ b/src/ui/widget/layer-selector.cpp @@ -45,6 +45,7 @@ public: AlternateIcons(Inkscape::IconSize size, gchar const *a, gchar const *b) : _a(NULL), _b(NULL) { + set_name("AlternateIcons"); if (a) { _a = Gtk::manage(sp_icon_get_icon(a, size)); _a->set_no_show_all(true); @@ -94,6 +95,7 @@ private: LayerSelector::LayerSelector(SPDesktop *desktop) : _desktop(NULL), _layer(NULL) { + set_name("LayerSelector"); AlternateIcons *label; label = Gtk::manage(new AlternateIcons(Inkscape::ICON_SIZE_DECORATION, diff --git a/src/ui/widget/panel.cpp b/src/ui/widget/panel.cpp index 5d4a25a68..ab13577d7 100644 --- a/src/ui/widget/panel.cpp +++ b/src/ui/widget/panel.cpp @@ -73,6 +73,7 @@ Panel::Panel(Glib::ustring const &label, gchar const *prefs_path, _action_area(0), _fillable(0) { + set_name( "InkscapePanel" ); #if WITH_GTKMM_3_0 set_orientation( Gtk::ORIENTATION_VERTICAL ); #endif @@ -284,7 +285,10 @@ void Panel::_init() pack_start(_top_bar, false, false); Gtk::HBox* boxy = Gtk::manage(new Gtk::HBox()); - + boxy->set_name( "PanelBoxY" ); + _contents.set_name( "PanelContents" ); + _right_bar.set_name( "PanelRightBar" ); + _top_bar.set_name( "PanelTopBar" ); boxy->pack_start(_contents, true, true); boxy->pack_start(_right_bar, false, true); diff --git a/src/ui/widget/selected-style.cpp b/src/ui/widget/selected-style.cpp index 87cf0b8c4..f7fd63f51 100644 --- a/src/ui/widget/selected-style.cpp +++ b/src/ui/widget/selected-style.cpp @@ -155,6 +155,7 @@ SelectedStyle::SelectedStyle(bool /*layout*/) _unit_mis(NULL), _sw_unit(NULL) { + set_name("SelectedStyle"); _drop[0] = _drop[1] = 0; _dropEnabled[0] = _dropEnabled[1] = false; diff --git a/src/ui/widget/style-swatch.cpp b/src/ui/widget/style-swatch.cpp index fa8543c46..188be705d 100644 --- a/src/ui/widget/style-swatch.cpp +++ b/src/ui/widget/style-swatch.cpp @@ -124,6 +124,8 @@ StyleSwatch::StyleSwatch(SPCSSAttr *css, gchar const *main_tip) #endif _sw_unit(NULL) { + set_name("StyleSwatch"); + _label[SS_FILL].set_markup(_("Fill:")); _label[SS_STROKE].set_markup(_("Stroke:")); diff --git a/src/widgets/desktop-widget.cpp b/src/widgets/desktop-widget.cpp index 1a4fcccf4..164a06910 100644 --- a/src/widgets/desktop-widget.cpp +++ b/src/widgets/desktop-widget.cpp @@ -249,7 +249,7 @@ SPDesktopWidget::setMessage (Inkscape::MessageType type, const gchar *message) gdk_window_process_updates(gtk_widget_get_window(GTK_WIDGET(sb)), TRUE); } - gtk_widget_set_tooltip_text (this->select_status_eventbox, gtk_label_get_text (sb)); + gtk_widget_set_tooltip_text (this->select_status, gtk_label_get_text (sb)); } Geom::Point @@ -346,6 +346,7 @@ void SPDesktopWidget::init( SPDesktopWidget *dtw ) /* Main table */ #if GTK_CHECK_VERSION(3,0,0) dtw->vbox = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0); + gtk_widget_set_name(dtw->vbox, "DesktopMainTable"); #else dtw->vbox = gtk_vbox_new (FALSE, 0); #endif @@ -353,6 +354,7 @@ void SPDesktopWidget::init( SPDesktopWidget *dtw ) #if GTK_CHECK_VERSION(3,0,0) dtw->statusbar = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0); + gtk_widget_set_name(dtw->statusbar, "DesktopStatusBar"); #else dtw->statusbar = gtk_hbox_new (FALSE, 0); #endif @@ -364,7 +366,6 @@ void SPDesktopWidget::init( SPDesktopWidget *dtw ) dtw->panels = new SwatchesPanel("/embedded/swatches" /*false*/); dtw->panels->setOrientation(SP_ANCHOR_SOUTH); - #if GTK_CHECK_VERSION(3,0,0) dtw->panels->set_vexpand(false); #endif @@ -374,6 +375,7 @@ void SPDesktopWidget::init( SPDesktopWidget *dtw ) #if GTK_CHECK_VERSION(3,0,0) dtw->hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0); + gtk_widget_set_name(dtw->hbox, "DesktopHbox"); #else dtw->hbox = gtk_hbox_new(FALSE, 0); #endif @@ -404,7 +406,7 @@ void SPDesktopWidget::init( SPDesktopWidget *dtw ) Glib::RefPtr<Gtk::CssProvider> guides_lock_style_provider = Gtk::CssProvider::create(); guides_lock_style_provider->load_from_data("GtkWidget { padding-left: 0; padding-right: 0; padding-top: 0; padding-bottom: 0; }"); Gtk::Widget * wnd = Glib::wrap(dtw->guides_lock); - wnd->set_name("guides_lock"); + wnd->set_name("LockGuides"); Glib::RefPtr<Gtk::StyleContext> context = wnd->get_style_context(); context->add_provider(guides_lock_style_provider, GTK_STYLE_PROVIDER_PRIORITY_APPLICATION); #endif @@ -412,6 +414,7 @@ void SPDesktopWidget::init( SPDesktopWidget *dtw ) /* Horizontal ruler */ GtkWidget *eventbox = gtk_event_box_new (); dtw->hruler = sp_ruler_new(GTK_ORIENTATION_HORIZONTAL); + gtk_widget_set_name(dtw->hruler, "HorizontalRuler"); dtw->hruler_box = eventbox; Inkscape::Util::Unit const *pt = unit_table.getUnit("pt"); sp_ruler_set_unit(SP_RULER(dtw->hruler), pt); @@ -422,13 +425,15 @@ void SPDesktopWidget::init( SPDesktopWidget *dtw ) g_signal_connect (G_OBJECT (eventbox), "motion_notify_event", G_CALLBACK (sp_dt_hruler_event), dtw); #if GTK_CHECK_VERSION(3,0,0) - GtkWidget *tbl = gtk_grid_new(); + GtkWidget *tbl_wrapper = gtk_grid_new(); // Is this widget really needed? + gtk_widget_set_name(tbl_wrapper, "CanvasTableWrapper"); dtw->canvas_tbl = gtk_grid_new(); + gtk_widget_set_name(dtw->canvas_tbl, "CanvasTable"); gtk_grid_attach(GTK_GRID(dtw->canvas_tbl), dtw->guides_lock, 0, 0, 1, 1); gtk_grid_attach(GTK_GRID(dtw->canvas_tbl), eventbox, 1, 0, 1, 1); #else - GtkWidget *tbl = gtk_table_new(2, 3, FALSE); + GtkWidget *tbl_wrapper = gtk_table_new(2, 3, FALSE); dtw->canvas_tbl = gtk_table_new(3, 3, FALSE); gtk_table_attach(GTK_TABLE(dtw->canvas_tbl), @@ -443,11 +448,12 @@ void SPDesktopWidget::init( SPDesktopWidget *dtw ) 0, 0); #endif g_signal_connect (G_OBJECT (dtw->guides_lock), "toggled", G_CALLBACK (sp_update_guides_lock), dtw); - gtk_box_pack_start( GTK_BOX(dtw->hbox), tbl, TRUE, TRUE, 1 ); + gtk_box_pack_start( GTK_BOX(dtw->hbox), tbl_wrapper, TRUE, TRUE, 1 ); /* Vertical ruler */ eventbox = gtk_event_box_new (); dtw->vruler = sp_ruler_new(GTK_ORIENTATION_VERTICAL); + gtk_widget_set_name(dtw->vruler, "VerticalRuler"); /* Vertical ruler */ dtw->vruler_box = eventbox; @@ -472,11 +478,9 @@ void SPDesktopWidget::init( SPDesktopWidget *dtw ) // Horizontal scrollbar dtw->hadj = GTK_ADJUSTMENT(gtk_adjustment_new(0.0, -4000.0, 4000.0, 10.0, 100.0, 4.0)); - - - #if GTK_CHECK_VERSION(3,0,0) dtw->hscrollbar = gtk_scrollbar_new(GTK_ORIENTATION_HORIZONTAL, GTK_ADJUSTMENT (dtw->hadj)); + gtk_widget_set_name(dtw->hscrollbar, "HorizontalScrollbar"); gtk_grid_attach(GTK_GRID(dtw->canvas_tbl), dtw->hscrollbar, 1, 2, 1, 1); dtw->vscrollbar_box = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0); #else @@ -493,6 +497,7 @@ void SPDesktopWidget::init( SPDesktopWidget *dtw ) NULL, INKSCAPE_ICON("zoom-original"), _("Zoom drawing if window size changes")); + gtk_widget_set_name(dtw->sticky_zoom, "StickyZoom"); gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (dtw->sticky_zoom), prefs->getBool("/options/stickyzoom/value")); gtk_box_pack_start (GTK_BOX (dtw->vscrollbar_box), dtw->sticky_zoom, FALSE, FALSE, 0); g_signal_connect (G_OBJECT (dtw->sticky_zoom), "toggled", G_CALLBACK (sp_dtw_sticky_zoom_toggled), dtw); @@ -502,6 +507,7 @@ void SPDesktopWidget::init( SPDesktopWidget *dtw ) #if GTK_CHECK_VERSION(3,0,0) dtw->vscrollbar = gtk_scrollbar_new(GTK_ORIENTATION_VERTICAL, GTK_ADJUSTMENT(dtw->vadj)); + gtk_widget_set_name(dtw->vscrollbar, "VerticalScrollbar"); #else dtw->vscrollbar = gtk_vscrollbar_new (GTK_ADJUSTMENT (dtw->vadj)); #endif @@ -529,6 +535,8 @@ void SPDesktopWidget::init( SPDesktopWidget *dtw ) NULL, INKSCAPE_ICON("color-management"), tip ); + gtk_widget_set_name(dtw->cms_adjust, "CMS_Adjust"); + #if defined(HAVE_LIBLCMS1) || defined(HAVE_LIBLCMS2) { Glib::ustring current = prefs->getString("/options/displayprofile/uri"); @@ -608,9 +616,9 @@ void SPDesktopWidget::init( SPDesktopWidget *dtw ) if (create_dock) { dtw->dock = new Inkscape::UI::Widget::Dock(); - #if WITH_GTKMM_3_0 Gtk::Paned *paned = new Gtk::Paned(); + paned->set_name("Canvas_and_Dock"); #else Gtk::HPaned *paned = new Gtk::HPaned(); #endif @@ -627,9 +635,9 @@ void SPDesktopWidget::init( SPDesktopWidget *dtw ) #if GTK_CHECK_VERSION(3,0,0) gtk_widget_set_hexpand(GTK_WIDGET(paned->gobj()), TRUE); gtk_widget_set_vexpand(GTK_WIDGET(paned->gobj()), TRUE); - gtk_grid_attach(GTK_GRID(tbl), GTK_WIDGET (paned->gobj()), 1, 1, 1, 1); + gtk_grid_attach(GTK_GRID(tbl_wrapper), GTK_WIDGET (paned->gobj()), 1, 1, 1, 1); #else - gtk_table_attach (GTK_TABLE (tbl), GTK_WIDGET (paned->gobj()), 1, 2, 1, 2, (GtkAttachOptions)(GTK_EXPAND | GTK_FILL), + gtk_table_attach (GTK_TABLE (tbl_wrapper), GTK_WIDGET (paned->gobj()), 1, 2, 1, 2, (GtkAttachOptions)(GTK_EXPAND | GTK_FILL), (GtkAttachOptions)(GTK_EXPAND | GTK_FILL), 0, 0); #endif @@ -637,17 +645,26 @@ void SPDesktopWidget::init( SPDesktopWidget *dtw ) #if GTK_CHECK_VERSION(3,0,0) gtk_widget_set_hexpand(GTK_WIDGET(dtw->canvas_tbl), TRUE); gtk_widget_set_vexpand(GTK_WIDGET(dtw->canvas_tbl), TRUE); - gtk_grid_attach(GTK_GRID(tbl), GTK_WIDGET (dtw->canvas_tbl), 1, 1, 1, 1); + gtk_grid_attach(GTK_GRID(tbl_wrapper), GTK_WIDGET (dtw->canvas_tbl), 1, 1, 1, 1); #else - gtk_table_attach (GTK_TABLE (tbl), GTK_WIDGET (dtw->canvas_tbl), 1, 2, 1, 2, (GtkAttachOptions)(GTK_EXPAND | GTK_FILL), + gtk_table_attach (GTK_TABLE (tbl_wrapper), GTK_WIDGET (dtw->canvas_tbl), 1, 2, 1, 2, (GtkAttachOptions)(GTK_EXPAND | GTK_FILL), (GtkAttachOptions)(GTK_EXPAND | GTK_FILL), 0, 0); #endif } + // connect scrollbar signals + g_signal_connect (G_OBJECT (dtw->hadj), "value-changed", G_CALLBACK (sp_desktop_widget_adjustment_value_changed), dtw); + g_signal_connect (G_OBJECT (dtw->vadj), "value-changed", G_CALLBACK (sp_desktop_widget_adjustment_value_changed), dtw); + + + // --------------- Status Tool Bar ------------------// + + // Selected Style (Fill/Stroke/Opacity) dtw->selected_style = new Inkscape::UI::Widget::SelectedStyle(true); GtkHBox *ss_ = dtw->selected_style->gobj(); gtk_box_pack_start (GTK_BOX (dtw->statusbar), GTK_WIDGET(ss_), FALSE, FALSE, 0); + // Separator gtk_box_pack_start(GTK_BOX(dtw->statusbar), #if GTK_CHECK_VERSION(3,0,0) gtk_separator_new(GTK_ORIENTATION_VERTICAL), @@ -656,15 +673,39 @@ void SPDesktopWidget::init( SPDesktopWidget *dtw ) #endif FALSE, FALSE, 0); - // connect scrollbar signals - g_signal_connect (G_OBJECT (dtw->hadj), "value-changed", G_CALLBACK (sp_desktop_widget_adjustment_value_changed), dtw); - g_signal_connect (G_OBJECT (dtw->vadj), "value-changed", G_CALLBACK (sp_desktop_widget_adjustment_value_changed), dtw); + // Layer Selector + dtw->layer_selector = new Inkscape::Widgets::LayerSelector(NULL); + // FIXME: need to unreference on container destruction to avoid leak + dtw->layer_selector->reference(); + //dtw->layer_selector->set_size_request(-1, SP_ICON_SIZE_BUTTON); + gtk_box_pack_start(GTK_BOX(dtw->statusbar), GTK_WIDGET(dtw->layer_selector->gobj()), FALSE, FALSE, 1); + + // Select Status + dtw->select_status = gtk_label_new (NULL); + gtk_widget_set_name( dtw->select_status, "SelectStatus"); + gtk_label_set_ellipsize (GTK_LABEL(dtw->select_status), PANGO_ELLIPSIZE_END); +#if GTK_CHECK_VERSION(3,10,0) + gtk_label_set_line_wrap (GTK_LABEL(dtw->select_status), true); + gtk_label_set_lines (GTK_LABEL(dtw->select_status), 2); +#endif - GtkWidget *statusbar_tail=gtk_statusbar_new(); - gtk_box_pack_end (GTK_BOX (dtw->statusbar), statusbar_tail, FALSE, FALSE, 0); +#if GTK_CHECK_VERSION(3,0,0) + gtk_widget_set_halign(dtw->select_status, GTK_ALIGN_START); +#else + gtk_misc_set_alignment (GTK_MISC (dtw->select_status), 0.0, 0.5); +#endif - // zoom status spinbutton + gtk_widget_set_size_request (dtw->select_status, 1, -1); + + // Display the initial welcome message in the statusbar + gtk_label_set_markup (GTK_LABEL (dtw->select_status), _("<b>Welcome to Inkscape!</b> Use shape or freehand tools to create objects; use selector (arrow) to move or transform them.")); + + gtk_box_pack_start (GTK_BOX (dtw->statusbar), dtw->select_status, TRUE, TRUE, 0); + + + // Zoom status spinbutton dtw->zoom_status = gtk_spin_button_new_with_range (log(SP_DESKTOP_ZOOM_MIN)/log(2), log(SP_DESKTOP_ZOOM_MAX)/log(2), 0.1); + gtk_widget_set_name(dtw->zoom_status, "ZoomStatus"); gtk_widget_set_tooltip_text (dtw->zoom_status, _("Zoom")); gtk_widget_set_size_request (dtw->zoom_status, STATUS_ZOOM_WIDTH, -1); gtk_entry_set_width_chars (GTK_ENTRY (dtw->zoom_status), 6); @@ -678,12 +719,14 @@ void SPDesktopWidget::init( SPDesktopWidget *dtw ) dtw->zoom_update = g_signal_connect (G_OBJECT (dtw->zoom_status), "value_changed", G_CALLBACK (sp_dtw_zoom_value_changed), dtw); dtw->zoom_update = g_signal_connect (G_OBJECT (dtw->zoom_status), "populate_popup", G_CALLBACK (sp_dtw_zoom_populate_popup), dtw); - // cursor coordinates + // Cursor coordinates #if GTK_CHECK_VERSION(3,0,0) dtw->coord_status = gtk_grid_new(); + gtk_widget_set_name(dtw->coord_status, "CoordinateAndZStatus"); gtk_grid_set_row_spacing(GTK_GRID(dtw->coord_status), 0); gtk_grid_set_column_spacing(GTK_GRID(dtw->coord_status), 2); GtkWidget* sep = gtk_separator_new(GTK_ORIENTATION_VERTICAL); + gtk_widget_set_name(sep, "CoordinateSeparator"); gtk_grid_attach(GTK_GRID(dtw->coord_status), GTK_WIDGET(sep), 0, 0, 1, 2); @@ -697,9 +740,7 @@ void SPDesktopWidget::init( SPDesktopWidget *dtw ) GTK_FILL, GTK_FILL, 0, 0); #endif - eventbox = gtk_event_box_new (); - gtk_container_add (GTK_CONTAINER (eventbox), dtw->coord_status); - gtk_widget_set_tooltip_text (eventbox, _("Cursor coordinates")); + gtk_widget_set_tooltip_text (dtw->coord_status, _("Cursor coordinates")); GtkWidget *label_x = gtk_label_new(_("X:")); GtkWidget *label_y = gtk_label_new(_("Y:")); @@ -721,6 +762,7 @@ void SPDesktopWidget::init( SPDesktopWidget *dtw ) gtk_label_set_markup( GTK_LABEL(dtw->coord_status_y), "<tt> 0.00 </tt>" ); GtkWidget* label_z = gtk_label_new(_("Z:")); + gtk_widget_set_name(label_z, "ZLabel"); #if GTK_CHECK_VERSION(3,0,0) gtk_widget_set_halign(dtw->coord_status_x, GTK_ALIGN_END); @@ -739,14 +781,10 @@ void SPDesktopWidget::init( SPDesktopWidget *dtw ) #endif sp_set_font_size_smaller (dtw->coord_status); - gtk_box_pack_end (GTK_BOX (statusbar_tail), eventbox, FALSE, FALSE, 1); - dtw->layer_selector = new Inkscape::Widgets::LayerSelector(NULL); - // FIXME: need to unreference on container destruction to avoid leak - dtw->layer_selector->reference(); - //dtw->layer_selector->set_size_request(-1, SP_ICON_SIZE_BUTTON); - gtk_box_pack_start(GTK_BOX(dtw->statusbar), GTK_WIDGET(dtw->layer_selector->gobj()), FALSE, FALSE, 1); + gtk_box_pack_end (GTK_BOX (dtw->statusbar), dtw->coord_status, FALSE, FALSE, 0); + // --------------- Color Management ---------------- // dtw->_tracker = ege_color_prof_tracker_new(GTK_WIDGET(dtw->layer_selector->gobj())); #if defined(HAVE_LIBLCMS1) || defined(HAVE_LIBLCMS2) bool fromDisplay = prefs->getBool( "/options/displayprofile/from_display"); @@ -761,30 +799,7 @@ void SPDesktopWidget::init( SPDesktopWidget *dtw ) #endif // defined(HAVE_LIBLCMS1) || defined(HAVE_LIBLCMS2) g_signal_connect( G_OBJECT(dtw->_tracker), "changed", G_CALLBACK(sp_dtw_color_profile_event), dtw ); - dtw->select_status_eventbox = gtk_event_box_new (); - dtw->select_status = gtk_label_new (NULL); - gtk_label_set_ellipsize (GTK_LABEL(dtw->select_status), PANGO_ELLIPSIZE_END); - -#if GTK_CHECK_VERSION(3,0,0) - gtk_widget_set_halign(dtw->select_status, GTK_ALIGN_START); -#else - gtk_misc_set_alignment (GTK_MISC (dtw->select_status), 0.0, 0.5); -#endif - - gtk_widget_set_size_request (dtw->select_status, 1, -1); - // display the initial welcome message in the statusbar - gtk_label_set_markup (GTK_LABEL (dtw->select_status), _("<b>Welcome to Inkscape!</b> Use shape or freehand tools to create objects; use selector (arrow) to move or transform them.")); - // space label 2 pixels from left edge - gtk_container_add (GTK_CONTAINER (dtw->select_status_eventbox), dtw->select_status); -#if GTK_CHECK_VERSION(3,0,0) - gtk_box_pack_start(GTK_BOX(dtw->statusbar), - gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0), - FALSE, FALSE, 2); -#else - gtk_box_pack_start (GTK_BOX (dtw->statusbar), gtk_hbox_new(FALSE, 0), FALSE, FALSE, 2); -#endif - gtk_box_pack_start (GTK_BOX (dtw->statusbar), dtw->select_status_eventbox, TRUE, TRUE, 0); - + // ------------------ Finish Up -------------------- // gtk_widget_show_all (dtw->vbox); gtk_widget_grab_focus (GTK_WIDGET(dtw->canvas)); @@ -1453,6 +1468,7 @@ bool SPDesktopWidget::showInfoDialog( Glib::ustring const &message ) GTK_MESSAGE_INFO, GTK_BUTTONS_OK, "%s", message.c_str()); + gtk_widget_set_name(dialog, "InfoDialog"); gtk_window_set_title( GTK_WINDOW(dialog), _("Note:")); // probably want to take this as a parameter. gtk_dialog_run(GTK_DIALOG(dialog)); gtk_widget_destroy(dialog); @@ -1765,6 +1781,7 @@ SPDesktopWidget* SPDesktopWidget::createInstance(SPNamedView *namedview) dtw->layer_selector->setDesktop(dtw->desktop); dtw->menubar = sp_ui_main_menubar (dtw->desktop); + gtk_widget_set_name(dtw->menubar, "MenuBar"); gtk_widget_show_all (dtw->menubar); gtk_box_pack_start (GTK_BOX (dtw->vbox), dtw->menubar, FALSE, FALSE, 0); @@ -1885,8 +1902,8 @@ bool SPDesktopWidget::onFocusInEvent(GdkEventFocus*) { Inkscape::Preferences *prefs = Inkscape::Preferences::get(); if (prefs->getBool("/options/bitmapautoreload/value", true)) { - std::set<SPObject *> imageList = (desktop->doc())->getResourceList("image"); - for (std::set<SPObject *>::const_iterator it = imageList.begin(); it != imageList.end(); ++it) { + std::vector<SPObject *> imageList = (desktop->doc())->getResourceList("image"); + for (std::vector<SPObject *>::const_iterator it = imageList.begin(); it != imageList.end(); ++it) { SPImage* image = SP_IMAGE(*it); sp_image_refresh_if_outdated( image ); } diff --git a/src/widgets/eraser-toolbar.cpp b/src/widgets/eraser-toolbar.cpp index 45989936f..bb553f4e6 100644 --- a/src/widgets/eraser-toolbar.cpp +++ b/src/widgets/eraser-toolbar.cpp @@ -183,8 +183,8 @@ void sp_eraser_toolbox_prep(SPDesktop *desktop, GtkActionGroup* mainActions, GOb /* Overlap */ { InkToggleAction* act = ink_toggle_action_new( "EraserBreakAppart", - _("Break appart cutted items"), - _("Break appart cutted itemss"), + _("Break apart cut items"), + _("Break apart cut items"), INKSCAPE_ICON("distribute-randomize"), secondarySize ); gtk_toggle_action_set_active( GTK_TOGGLE_ACTION(act), prefs->getBool("/tools/eraser/break_apart", false) ); diff --git a/src/widgets/gradient-toolbar.cpp b/src/widgets/gradient-toolbar.cpp index 858aa05db..a44e9962e 100644 --- a/src/widgets/gradient-toolbar.cpp +++ b/src/widgets/gradient-toolbar.cpp @@ -140,8 +140,8 @@ gboolean gr_vector_list(GtkWidget *combo_box, SPDesktop *desktop, bool selection gtk_list_store_clear(store); std::vector<SPObject *> gl; - std::set<SPObject *> gradients = document->getResourceList( "gradient" ); - for (std::set<SPObject *>::const_iterator it = gradients.begin(); it != gradients.end(); ++it) { + std::vector<SPObject *> gradients = document->getResourceList( "gradient" ); + for (std::vector<SPObject *>::const_iterator it = gradients.begin(); it != gradients.end(); ++it) { SPGradient *grad = SP_GRADIENT(*it); if ( grad->hasStops() && !grad->isSolid() ) { gl.push_back(*it); diff --git a/src/widgets/gradient-vector.cpp b/src/widgets/gradient-vector.cpp index 3aa44c90a..97e65141f 100644 --- a/src/widgets/gradient-vector.cpp +++ b/src/widgets/gradient-vector.cpp @@ -298,8 +298,8 @@ static void sp_gvs_rebuild_gui_full(SPGradientVectorSelector *gvs) /* Pick up all gradients with vectors */ GSList *gl = NULL; if (gvs->gr) { - std::set<SPObject *> gradients = gvs->gr->document->getResourceList("gradient"); - for (std::set<SPObject *>::const_iterator it = gradients.begin(); it != gradients.end(); ++it) { + std::vector<SPObject *> gradients = gvs->gr->document->getResourceList("gradient"); + for (std::vector<SPObject *>::const_iterator it = gradients.begin(); it != gradients.end(); ++it) { SPGradient* grad = SP_GRADIENT(*it); if ( grad->hasStops() && (grad->isSwatch() == gvs->swatched) ) { gl = g_slist_prepend(gl, *it); diff --git a/src/widgets/paint-selector.cpp b/src/widgets/paint-selector.cpp index 602cad3c3..aafa6bd1e 100644 --- a/src/widgets/paint-selector.cpp +++ b/src/widgets/paint-selector.cpp @@ -844,8 +844,8 @@ ink_pattern_list_get (SPDocument *source) return NULL; GSList *pl = NULL; - std::set<SPObject *> patterns = source->getResourceList("pattern"); - for (std::set<SPObject *>::const_iterator it = patterns.begin(); it != patterns.end(); ++it) { + std::vector<SPObject *> patterns = source->getResourceList("pattern"); + for (std::vector<SPObject *>::const_iterator it = patterns.begin(); it != patterns.end(); ++it) { if (SP_PATTERN(*it) == SP_PATTERN(*it)->rootPattern()) { // only if this is a root pattern pl = g_slist_prepend(pl, *it); } diff --git a/src/widgets/ruler.cpp b/src/widgets/ruler.cpp index bcab535f9..deffd384a 100644 --- a/src/widgets/ruler.cpp +++ b/src/widgets/ruler.cpp @@ -168,6 +168,10 @@ sp_ruler_class_init (SPRulerClass *klass) GObjectClass *object_class = G_OBJECT_CLASS (klass); GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass); +#if GTK_CHECK_VERSION(3,20,0) + gtk_widget_class_set_css_name (widget_class, "ruler-widget"); +#endif + object_class->dispose = sp_ruler_dispose; object_class->set_property = sp_ruler_set_property; object_class->get_property = sp_ruler_get_property; diff --git a/src/widgets/toolbox.cpp b/src/widgets/toolbox.cpp index 0697ff0fb..f7b5e585f 100644 --- a/src/widgets/toolbox.cpp +++ b/src/widgets/toolbox.cpp @@ -999,6 +999,7 @@ static GtkWidget* toolboxNewCommon( GtkWidget* tb, BarId id, GtkPositionType /*h gtk_widget_set_sensitive(tb, FALSE); GtkWidget *hb = gtk_event_box_new(); // A simple, neutral container. + gtk_widget_set_name(hb, "ToolboxCommon"); gtk_container_add(GTK_CONTAINER(hb), tb); gtk_widget_show(GTK_WIDGET(tb)); @@ -1016,6 +1017,7 @@ GtkWidget *ToolboxFactory::createToolToolbox() { #if GTK_CHECK_VERSION(3,0,0) GtkWidget *tb = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0); + gtk_widget_set_name(tb, "ToolToolbox"); gtk_box_set_homogeneous(GTK_BOX(tb), FALSE); #else GtkWidget *tb = gtk_vbox_new(FALSE, 0); @@ -1028,6 +1030,7 @@ GtkWidget *ToolboxFactory::createAuxToolbox() { #if GTK_CHECK_VERSION(3,0,0) GtkWidget *tb = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0); + gtk_widget_set_name(tb, "AuxToolbox"); gtk_box_set_homogeneous(GTK_BOX(tb), FALSE); #else GtkWidget *tb = gtk_vbox_new(FALSE, 0); @@ -1044,6 +1047,7 @@ GtkWidget *ToolboxFactory::createCommandsToolbox() { #if GTK_CHECK_VERSION(3,0,0) GtkWidget *tb = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0); + gtk_widget_set_name(tb, "CommandsToolbox"); gtk_box_set_homogeneous(GTK_BOX(tb), FALSE); #else GtkWidget *tb = gtk_vbox_new(FALSE, 0); @@ -1056,6 +1060,7 @@ GtkWidget *ToolboxFactory::createSnapToolbox() { #if GTK_CHECK_VERSION(3,0,0) GtkWidget *tb = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0); + gtk_widget_set_name(tb, "SnapToolbox"); gtk_box_set_homogeneous(GTK_BOX(tb), FALSE); #else GtkWidget *tb = gtk_vbox_new(FALSE, 0); @@ -1406,6 +1411,7 @@ void setup_aux_toolbox(GtkWidget *toolbox, SPDesktop *desktop) // converted to GtkActions and UIManager GtkWidget* kludge = gtk_toolbar_new(); + gtk_widget_set_name( kludge, "Kludge" ); g_object_set_data( G_OBJECT(kludge), "dtw", desktop->canvas); g_object_set_data( G_OBJECT(kludge), "desktop", desktop); dataHolders[aux_toolboxes[i].type_name] = kludge; @@ -1418,7 +1424,7 @@ void setup_aux_toolbox(GtkWidget *toolbox, SPDesktop *desktop) } else { sub_toolbox = aux_toolboxes[i].create_func(desktop); } - + gtk_widget_set_name( sub_toolbox, "SubToolBox" ); gtk_size_group_add_widget( grouper, sub_toolbox ); gtk_container_add(GTK_CONTAINER(toolbox), sub_toolbox); @@ -1436,6 +1442,7 @@ void setup_aux_toolbox(GtkWidget *toolbox, SPDesktop *desktop) #if GTK_CHECK_VERSION(3,0,0) GtkWidget* holder = gtk_grid_new(); + gtk_widget_set_name( holder, "ToolbarHolder" ); gtk_grid_attach( GTK_GRID(holder), kludge, 2, 0, 1, 1); #else GtkWidget* holder = gtk_table_new( 1, 3, FALSE ); diff --git a/src/xml/rebase-hrefs.cpp b/src/xml/rebase-hrefs.cpp index 2bcae5d81..a8ac3b4cc 100644 --- a/src/xml/rebase-hrefs.cpp +++ b/src/xml/rebase-hrefs.cpp @@ -220,8 +220,8 @@ void Inkscape::XML::rebase_hrefs(SPDocument *const doc, gchar const *const new_b * * Note also that Inkscape only supports fragment hrefs (href="#pattern257") for many of these * cases. */ - std::set<SPObject *> images = doc->getResourceList("image"); - for (std::set<SPObject *>::const_iterator it = images.begin(); it != images.end(); ++it) { + std::vector<SPObject *> images = doc->getResourceList("image"); + for (std::vector<SPObject *>::const_iterator it = images.begin(); it != images.end(); ++it) { Inkscape::XML::Node *ir = (*it)->getRepr(); std::string uri; |
