summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTavmjong Bah <tavmjong@free.fr>2017-03-02 13:08:17 +0000
committertavmjong-free <tavmjong@free.fr>2017-03-02 13:08:17 +0000
commitc35eeadff685fb93343ee334ec6da857c95c8288 (patch)
tree0480364cfec63f8730f4f8394d52305ada65ff15
parentAdd units (px) to size being shown in native Windows file open dialog and fix... (diff)
downloadinkscape-c35eeadff685fb93343ee334ec6da857c95c8288.tar.gz
inkscape-c35eeadff685fb93343ee334ec6da857c95c8288.zip
Implement arc "chord" type. (Matches Krita "chord" arc type.)
(bzr r15561)
-rw-r--r--share/icons/icons.svg10
-rw-r--r--src/attributes.cpp3
-rw-r--r--src/attributes.h1
-rw-r--r--src/sp-ellipse.cpp75
-rw-r--r--src/sp-ellipse.h17
-rw-r--r--src/ui/object-edit.cpp8
-rw-r--r--src/widgets/arc-toolbar.cpp91
7 files changed, 139 insertions, 66 deletions
diff --git a/share/icons/icons.svg b/share/icons/icons.svg
index 3fd4e8bf6..4556054bf 100644
--- a/share/icons/icons.svg
+++ b/share/icons/icons.svg
@@ -3055,11 +3055,15 @@ http://www.inkscape.org/</dc:description>
</g>
<g style="fill:none" id="draw-ellipse-segment" transform="translate(20)" inkscape:label="#circle_closed_arc">
<rect id="rect4316" width="16" height="16" x="500" y="150" />
-<path d="m 514,158 a 6,6 0 0 1 -4.9581,5.9088 6,6 0 0 1 -6.6801,-3.8567 A 6,6 0 0 1 505,152.8038 L 508,158 Z" sodipodi:ry="6" sodipodi:rx="6" sodipodi:cy="158" sodipodi:cx="508" id="path4318" style="fill:#b0c5da;stroke:#0000ff;stroke-miterlimit:1.5" sodipodi:type="arc" sodipodi:start="0" sodipodi:end="4.18879" />
+<path d="m 514,158 a 6,6 0 0 1 -4.9581,5.9088 6,6 0 0 1 -6.6801,-3.8567 A 6,6 0 0 1 505,152.8038 L 508,158 Z" sodipodi:ry="6" sodipodi:rx="6" sodipodi:cy="158" sodipodi:cx="508" id="path4318" style="fill:#b0c5da;stroke:#0000ff;stroke-miterlimit:1.5" sodipodi:type="arc" sodipodi:start="0" sodipodi:end="4.18879" sodipodi:arc-type="slice" />
</g>
<g transform="translate(40)" id="draw-ellipse-arc" style="fill:none" inkscape:label="#circle_open_arc">
-<rect y="150" x="500" height="16" width="16" id="rect4326" />
-<path sodipodi:end="4.18879" sodipodi:start="0" sodipodi:type="arc" style="fill:#b0c5da;stroke:#0000ff;stroke-miterlimit:1.5" id="path4328" sodipodi:cx="508" sodipodi:cy="158" sodipodi:rx="6" sodipodi:ry="6" d="m 514,158 a 6,6 0 0 1 -4.9581,5.9088 6,6 0 0 1 -6.6801,-3.8567 6,6 0 0 1 2.6382,-7.2483" sodipodi:open="true" />
+<rect y="150" x="500" height="16" width="16" id="draw-ellipse-arc-rect" />
+<path sodipodi:end="4.18879" sodipodi:start="0" sodipodi:type="arc" style="fill:#b0c5da;stroke:#0000ff;stroke-miterlimit:1.5" id="draw-ellipse-arc-arc" sodipodi:cx="508" sodipodi:cy="158" sodipodi:rx="6" sodipodi:ry="6" d="m 514,158 a 6,6 0 0 1 -4.9581,5.9088 6,6 0 0 1 -6.6801,-3.8567 6,6 0 0 1 2.6382,-7.2483" sodipodi:arc-type="arc" />
+</g>
+<g transform="translate(60)" id="draw-ellipse-chord" style="fill:none" inkscape:label="#circle_chord">
+<rect y="150" x="500" height="16" width="16" id="draw-ellipse-chord-rect" />
+<path sodipodi:end="4.18879" sodipodi:start="0" sodipodi:type="arc" style="fill:#b0c5da;stroke:#0000ff;stroke-miterlimit:1.5" id="draw-ellipse-chord-arc" sodipodi:cx="508" sodipodi:cy="158" sodipodi:rx="6" sodipodi:ry="6" d="m 514,158 a 6,6 0 0 1 -4.9581,5.9088 6,6 0 0 1 -6.6801,-3.8567 6,6 0 0 1 2.6382,-7.2483" sodipodi:arc-type="chord" />
</g>
<g id="draw-cuboid" inkscape:label="#draw_3dbox">
<path style="fill:#ffffff;fill-rule:evenodd;stroke:#000000;stroke-width:1.0492821px;stroke-linejoin:round" d="M 604.0245,114.9402 592.1873,119.5308 591.9578,132.5813 600.8438,138.7786 612.1565,135.1716 612.3859,122.613 604.0245,114.9402 Z" id="path5192" inkscape:connector-curvature="0" />
diff --git a/src/attributes.cpp b/src/attributes.cpp
index 8154bfbbe..5b3d35590 100644
--- a/src/attributes.cpp
+++ b/src/attributes.cpp
@@ -174,7 +174,8 @@ static SPStyleProp const props[] = {
{SP_ATTR_SODIPODI_RY, "sodipodi:ry"},
{SP_ATTR_SODIPODI_START, "sodipodi:start"},
{SP_ATTR_SODIPODI_END, "sodipodi:end"},
- {SP_ATTR_SODIPODI_OPEN, "sodipodi:open"},
+ {SP_ATTR_SODIPODI_OPEN, "sodipodi:open"}, // Deprecated
+ {SP_ATTR_SODIPODI_ARC_TYPE, "sodipodi:arc-type"},
/* SPStar */
{SP_ATTR_SODIPODI_SIDES, "sodipodi:sides"},
{SP_ATTR_SODIPODI_R1, "sodipodi:r1"},
diff --git a/src/attributes.h b/src/attributes.h
index e21851bcf..6d4ac7543 100644
--- a/src/attributes.h
+++ b/src/attributes.h
@@ -182,6 +182,7 @@ enum SPAttributeEnum {
SP_ATTR_SODIPODI_START,
SP_ATTR_SODIPODI_END,
SP_ATTR_SODIPODI_OPEN,
+ SP_ATTR_SODIPODI_ARC_TYPE,
/* SPStar */
SP_ATTR_SODIPODI_SIDES,
SP_ATTR_SODIPODI_R1,
diff --git a/src/sp-ellipse.cpp b/src/sp-ellipse.cpp
index ed1e2b504..5dfc60f1a 100644
--- a/src/sp-ellipse.cpp
+++ b/src/sp-ellipse.cpp
@@ -39,7 +39,7 @@ SPGenericEllipse::SPGenericEllipse()
, start(0)
, end(SP_2PI)
, type(SP_GENERIC_ELLIPSE_UNDEFINED)
- , _closed(true)
+ , arc_type(SP_GENERIC_ELLIPSE_ARC_TYPE_ARC)
{
}
@@ -47,14 +47,6 @@ SPGenericEllipse::~SPGenericEllipse()
{
}
-void SPGenericEllipse::setClosed(bool value) {
- _closed = value;
-}
-
-bool SPGenericEllipse::closed() {
- return _closed;
-}
-
void SPGenericEllipse::build(SPDocument *document, Inkscape::XML::Node *repr)
{
// std::cout << "SPGenericEllipse::build: Entrance: " << this->type
@@ -69,6 +61,7 @@ void SPGenericEllipse::build(SPDocument *document, Inkscape::XML::Node *repr)
this->readAttr("sodipodi:start");
this->readAttr("sodipodi:end");
this->readAttr("sodipodi:open");
+ this->readAttr("sodipodi:arc-type");
break;
case SP_GENERIC_ELLIPSE_CIRCLE:
@@ -166,7 +159,25 @@ void SPGenericEllipse::set(unsigned int key, gchar const *value)
break;
case SP_ATTR_SODIPODI_OPEN:
- this->_closed = (!value);
+ // This is only for reading in old files so rely on constructor to set default.
+ if (!value) { // Only set if not "true"
+ this->arc_type = SP_GENERIC_ELLIPSE_ARC_TYPE_SLICE;
+ }
+ this->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG);
+ break;
+
+ case SP_ATTR_SODIPODI_ARC_TYPE:
+ // To read in old files that use 'open', we need to not set if value is null.
+ // We could also check inkscape version.
+ if (value) {
+ if (!strcmp(value,"arc")) {
+ this->arc_type = SP_GENERIC_ELLIPSE_ARC_TYPE_ARC;
+ } else if (!strcmp(value,"chord")) {
+ this->arc_type = SP_GENERIC_ELLIPSE_ARC_TYPE_CHORD;
+ } else {
+ this->arc_type = SP_GENERIC_ELLIPSE_ARC_TYPE_SLICE;
+ }
+ }
this->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG);
break;
@@ -285,11 +296,28 @@ Inkscape::XML::Node *SPGenericEllipse::write(Inkscape::XML::Document *xml_doc, I
sp_repr_set_svg_double(repr, "sodipodi:start", start);
sp_repr_set_svg_double(repr, "sodipodi:end", end);
- repr->setAttribute("sodipodi:open", (!_closed) ? "true" : NULL);
+ switch ( arc_type ) {
+ case SP_GENERIC_ELLIPSE_ARC_TYPE_SLICE:
+ repr->setAttribute("sodipodi:open", NULL); // For backwards compat.
+ repr->setAttribute("sodipodi:arc-type", "slice");
+ break;
+ case SP_GENERIC_ELLIPSE_ARC_TYPE_CHORD:
+ // A chord's path isn't "open" but its fill most closely resembles an arc.
+ repr->setAttribute("sodipodi:open", "true"); // For backwards compat.
+ repr->setAttribute("sodipodi:arc-type", "chord");
+ break;
+ case SP_GENERIC_ELLIPSE_ARC_TYPE_ARC:
+ repr->setAttribute("sodipodi:open", "true"); // For backwards compat.
+ repr->setAttribute("sodipodi:arc-type", "arc");
+ break;
+ default:
+ std::cerr << "SPGenericEllipse::write: unknown arc-type." << std::endl;
+ }
} else {
repr->setAttribute("sodipodi:end", NULL);
repr->setAttribute("sodipodi:start", NULL);
repr->setAttribute("sodipodi:open", NULL);
+ repr->setAttribute("sodipodi:arc-type", NULL);
}
}
@@ -310,6 +338,7 @@ Inkscape::XML::Node *SPGenericEllipse::write(Inkscape::XML::Document *xml_doc, I
repr->setAttribute("sodipodi:end", NULL );
repr->setAttribute("sodipodi:start", NULL );
repr->setAttribute("sodipodi:open", NULL );
+ repr->setAttribute("sodipodi:arc-type", NULL);
repr->setAttribute("sodipodi:type", NULL );
repr->setAttribute("d", NULL );
break;
@@ -327,6 +356,7 @@ Inkscape::XML::Node *SPGenericEllipse::write(Inkscape::XML::Document *xml_doc, I
repr->setAttribute("sodipodi:end", NULL );
repr->setAttribute("sodipodi:start", NULL );
repr->setAttribute("sodipodi:open", NULL );
+ repr->setAttribute("sodipodi:arc-type", NULL);
repr->setAttribute("sodipodi:type", NULL );
repr->setAttribute("d", NULL );
break;
@@ -350,10 +380,16 @@ const char *SPGenericEllipse::displayName() const
case SP_GENERIC_ELLIPSE_ARC:
if (_isSlice()) {
- if (_closed) {
- return _("Segment");
- } else {
- return _("Arc");
+ switch ( arc_type ) {
+ case SP_GENERIC_ELLIPSE_ARC_TYPE_SLICE:
+ return _("Slice");
+ break;
+ case SP_GENERIC_ELLIPSE_ARC_TYPE_CHORD:
+ return _("Chord");
+ break;
+ case SP_GENERIC_ELLIPSE_ARC_TYPE_ARC:
+ return _("Arc");
+ break;
}
} else {
return _("Ellipse");
@@ -419,10 +455,10 @@ void SPGenericEllipse::set_shape()
}
Geom::PathBuilder pb;
pb.append(path);
- if (this->_isSlice() && this->_closed) {
+ if (this->_isSlice() && this->arc_type == SP_GENERIC_ELLIPSE_ARC_TYPE_SLICE) {
pb.lineTo(Geom::Point(0, 0));
}
- if (this->_closed) {
+ if ( !(this->arc_type == SP_GENERIC_ELLIPSE_ARC_TYPE_ARC) ) {
pb.closePath();
} else {
pb.flush();
@@ -543,7 +579,8 @@ void SPGenericEllipse::snappoints(std::vector<Inkscape::SnapCandidatePoint> &p,
bool slice = this->_isSlice();
// Add the centre, if we have a closed slice or when explicitly asked for
- if (snapprefs->isTargetSnappable(Inkscape::SNAPTARGET_NODE_CUSP) && slice && this->_closed) {
+ if (snapprefs->isTargetSnappable(Inkscape::SNAPTARGET_NODE_CUSP) && slice &&
+ this->arc_type == SP_GENERIC_ELLIPSE_ARC_TYPE_SLICE) {
Geom::Point pt = Geom::Point(cx, cy) * i2dt;
p.push_back(Inkscape::SnapCandidatePoint(pt, Inkscape::SNAPSOURCE_NODE_CUSP, Inkscape::SNAPTARGET_NODE_CUSP));
}
@@ -654,7 +691,7 @@ void SPGenericEllipse::position_set(gdouble x, gdouble y, gdouble rx, gdouble ry
this->end = Geom::Angle::from_degrees(prefs->getDouble("/tools/shapes/arc/end", 0.0)).radians0();
}
- this->_closed = !prefs->getBool("/tools/shapes/arc/open");
+ this->arc_type = (GenericEllipseArcType)prefs->getInt("/tools/shapes/arc/arc_type", 0);
this->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG);
}
diff --git a/src/sp-ellipse.h b/src/sp-ellipse.h
index 09768fd6d..dafece625 100644
--- a/src/sp-ellipse.h
+++ b/src/sp-ellipse.h
@@ -30,6 +30,12 @@ enum GenericEllipseType {
SP_GENERIC_ELLIPSE_ELLIPSE
};
+enum GenericEllipseArcType {
+ SP_GENERIC_ELLIPSE_ARC_TYPE_SLICE, // Default
+ SP_GENERIC_ELLIPSE_ARC_TYPE_CHORD,
+ SP_GENERIC_ELLIPSE_ARC_TYPE_ARC
+};
+
class SPGenericEllipse : public SPShape {
public:
SPGenericEllipse();
@@ -42,14 +48,13 @@ public:
SVGLength rx;
SVGLength ry;
- /**
- * If we have a slice, returns whether the shape is closed ("pizza slice") or not (arc only).
- */
- bool closed();
- void setClosed(bool value);
+ // Return slice, chord, or arc.
+ GenericEllipseArcType arcType() { return arc_type; };
+ void setArcType(GenericEllipseArcType type) { arc_type = type; };
double start, end;
GenericEllipseType type;
+ GenericEllipseArcType arc_type;
virtual void build(SPDocument *document, Inkscape::XML::Node *repr);
@@ -83,8 +88,6 @@ protected:
* @brief Determines whether the shape is a part of an ellipse.
*/
bool _isSlice() const;
-
- bool _closed;
};
#endif
diff --git a/src/ui/object-edit.cpp b/src/ui/object-edit.cpp
index cf2c03396..b11a61710 100644
--- a/src/ui/object-edit.cpp
+++ b/src/ui/object-edit.cpp
@@ -812,7 +812,9 @@ ArcKnotHolderEntityStart::knot_set(Geom::Point const &p, Geom::Point const &/*or
g_assert(arc != NULL);
gint side = sp_genericellipse_side(arc, p);
- if(side != 0) { arc->setClosed(side == -1); }
+ if(side != 0) { arc->setArcType( (side == -1) ?
+ SP_GENERIC_ELLIPSE_ARC_TYPE_SLICE :
+ SP_GENERIC_ELLIPSE_ARC_TYPE_ARC); }
Geom::Point delta = p - Geom::Point(arc->cx.computed, arc->cy.computed);
Geom::Scale sc(arc->rx.computed, arc->ry.computed);
@@ -861,7 +863,9 @@ ArcKnotHolderEntityEnd::knot_set(Geom::Point const &p, Geom::Point const &/*orig
g_assert(arc != NULL);
gint side = sp_genericellipse_side(arc, p);
- if(side != 0) { arc->setClosed(side == -1); }
+ if(side != 0) { arc->setArcType( (side == -1) ?
+ SP_GENERIC_ELLIPSE_ARC_TYPE_SLICE :
+ SP_GENERIC_ELLIPSE_ARC_TYPE_ARC); }
Geom::Point delta = p - Geom::Point(arc->cx.computed, arc->cy.computed);
Geom::Scale sc(arc->rx.computed, arc->ry.computed);
diff --git a/src/widgets/arc-toolbar.cpp b/src/widgets/arc-toolbar.cpp
index 9b408a7b2..56eeb8922 100644
--- a/src/widgets/arc-toolbar.cpp
+++ b/src/widgets/arc-toolbar.cpp
@@ -148,7 +148,7 @@ static void sp_arctb_open_state_changed( EgeSelectOneAction *act, GObject *tbl )
SPDesktop *desktop = static_cast<SPDesktop *>(g_object_get_data( tbl, "desktop" ));
if (DocumentUndo::getUndoSensitive(desktop->getDocument())) {
Inkscape::Preferences *prefs = Inkscape::Preferences::get();
- prefs->setBool("/tools/shapes/arc/open", ege_select_one_action_get_active(act) != 0);
+ prefs->setInt("/tools/shapes/arc/arc_type", ege_select_one_action_get_active(act));
}
// quit if run by the attr_changed listener
@@ -159,35 +159,43 @@ static void sp_arctb_open_state_changed( EgeSelectOneAction *act, GObject *tbl )
// in turn, prevent listener from responding
g_object_set_data( tbl, "freeze", GINT_TO_POINTER(TRUE) );
- bool modmade = false;
- if ( ege_select_one_action_get_active(act) != 0 ) {
- auto itemlist= desktop->getSelection()->items();
- for(auto i=itemlist.begin();i!=itemlist.end();++i){
- SPItem *item = *i;
- if (SP_IS_GENERICELLIPSE(item)) {
- Inkscape::XML::Node *repr = item->getRepr();
- repr->setAttribute("sodipodi:open", "true");
- item->updateRepr();
- modmade = true;
- }
- }
- } else {
- auto itemlist= desktop->getSelection()->items();
- for(auto i=itemlist.begin();i!=itemlist.end();++i){
- SPItem *item = *i;
- if (SP_IS_GENERICELLIPSE(item)) {
- Inkscape::XML::Node *repr = item->getRepr();
- repr->setAttribute("sodipodi:open", NULL);
- item->updateRepr();
- modmade = true;
- }
+ int mode = ege_select_one_action_get_active(act);
+ Glib::ustring arc_type = "slice";
+ bool open = false;
+ switch (mode) {
+ case 0:
+ arc_type = "slice";
+ open = false;
+ break;
+ case 1:
+ arc_type = "arc";
+ open = true;
+ break;
+ case 2:
+ arc_type = "chord";
+ open = true; // For backward compat, not truly open but chord most like arc.
+ break;
+ default:
+ std::cerr << "sp_arctb_open_state_changed: bad arc type: " << mode << std::endl;
+ }
+
+ bool modmade = false;
+ auto itemlist= desktop->getSelection()->items();
+ for(auto i=itemlist.begin();i!=itemlist.end();++i){
+ SPItem *item = *i;
+ if (SP_IS_GENERICELLIPSE(item)) {
+ Inkscape::XML::Node *repr = item->getRepr();
+ repr->setAttribute("sodipodi:open", (open?"true":NULL) );
+ repr->setAttribute("sodipodi:arc-type", arc_type.c_str());
+ item->updateRepr();
+ modmade = true;
}
}
if (modmade) {
DocumentUndo::done(desktop->getDocument(), SP_VERB_CONTEXT_ARC,
- _("Arc: Change open/closed"));
+ _("Arc: Changed arc type"));
}
g_object_set_data( tbl, "freeze", GINT_TO_POINTER(FALSE) );
@@ -234,14 +242,22 @@ static void arc_tb_event_attr_changed(Inkscape::XML::Node *repr, gchar const * /
sp_arctb_sensitivize( tbl, gtk_adjustment_get_value(adj1), gtk_adjustment_get_value(adj2) );
- char const *openstr = NULL;
- openstr = repr->attribute("sodipodi:open");
+ char const *arctypestr = NULL;
+ arctypestr = repr->attribute("sodipodi:arc-type");
+ if (!arctypestr) { // For old files.
+ char const *openstr = NULL;
+ openstr = repr->attribute("sodipodi:open");
+ arctypestr = (openstr ? "arc" : "slice");
+ }
+
EgeSelectOneAction *ocb = EGE_SELECT_ONE_ACTION( g_object_get_data( tbl, "open_action" ) );
- if (openstr) {
+ if (!strcmp(arctypestr,"slice")) {
+ ege_select_one_action_set_active( ocb, 0 );
+ } else if (!strcmp(arctypestr,"arc")) {
ege_select_one_action_set_active( ocb, 1 );
} else {
- ege_select_one_action_set_active( ocb, 0 );
+ ege_select_one_action_set_active( ocb, 2 );
}
g_object_set_data( tbl, "freeze", GINT_TO_POINTER(FALSE) );
@@ -338,25 +354,32 @@ void sp_arc_toolbox_prep(SPDesktop *desktop, GtkActionGroup* mainActions, GObjec
gtk_action_group_add_action( mainActions, GTK_ACTION(eact) );
}
- /* Segments / Pie checkbox */
+ /* Arc: Slice, Arc, Chord */
{
GtkListStore* model = gtk_list_store_new( 3, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING );
GtkTreeIter iter;
gtk_list_store_append( model, &iter );
gtk_list_store_set( model, &iter,
- 0, _("Closed arc"),
- 1, _("Switch to segment (closed shape with two radii)"),
+ 0, _("Slice"),
+ 1, _("Switch to slice (closed shape with two radii)"),
2, INKSCAPE_ICON("draw-ellipse-segment"),
-1 );
gtk_list_store_append( model, &iter );
gtk_list_store_set( model, &iter,
- 0, _("Open Arc"),
+ 0, _("Arc (Open)"),
1, _("Switch to arc (unclosed shape)"),
2, INKSCAPE_ICON("draw-ellipse-arc"),
-1 );
+ gtk_list_store_append( model, &iter );
+ gtk_list_store_set( model, &iter,
+ 0, _("Chord"),
+ 1, _("Switch to chord (closed shape)"),
+ 2, INKSCAPE_ICON("draw-ellipse-chord"),
+ -1 );
+
EgeSelectOneAction* act = ege_select_one_action_new( "ArcOpenAction", (""), (""), NULL, GTK_TREE_MODEL(model) );
gtk_action_group_add_action( mainActions, GTK_ACTION(act) );
g_object_set_data( holder, "open_action", act );
@@ -368,8 +391,8 @@ void sp_arc_toolbox_prep(SPDesktop *desktop, GtkActionGroup* mainActions, GObjec
ege_select_one_action_set_icon_size( act, secondarySize );
ege_select_one_action_set_tooltip_column( act, 1 );
- bool isClosed = !prefs->getBool("/tools/shapes/arc/open", false);
- ege_select_one_action_set_active( act, isClosed ? 0 : 1 );
+ int arc_type = prefs->getInt("/tools/shapes/arc/arc_type", 0);
+ ege_select_one_action_set_active( act, arc_type );
g_signal_connect_after( G_OBJECT(act), "changed", G_CALLBACK(sp_arctb_open_state_changed), holder );
}