summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorJabier Arraiza <jabier.arraiza@marker.es>2018-04-02 11:44:14 +0000
committerJabier Arraiza <jabier.arraiza@marker.es>2018-04-23 21:37:56 +0000
commitb75538b5e6844804ac518d01b7bf534bb886b5aa (patch)
tree68c2e665c9db20b307a3145e7c8fd9c9fc22520b /src
parentAdd UX for Lazuur projection idea (diff)
downloadinkscape-b75538b5e6844804ac518d01b7bf534bb886b5aa.tar.gz
inkscape-b75538b5e6844804ac518d01b7bf534bb886b5aa.zip
Finish projection phase
Diffstat (limited to 'src')
-rw-r--r--src/live_effects/lpe-measure-segments.cpp248
-rw-r--r--src/live_effects/lpe-measure-segments.h8
2 files changed, 223 insertions, 33 deletions
diff --git a/src/live_effects/lpe-measure-segments.cpp b/src/live_effects/lpe-measure-segments.cpp
index bf21cb2a2..f488fc565 100644
--- a/src/live_effects/lpe-measure-segments.cpp
+++ b/src/live_effects/lpe-measure-segments.cpp
@@ -18,7 +18,11 @@
#include "2geom/ray.h"
#include "display/curve.h"
#include "helper/geom.h"
+#include "text-editing.h"
#include "object/sp-defs.h"
+#include "object/sp-text.h"
+#include "object/sp-flowtext.h"
+#include "object/sp-item-group.h"
#include "object/sp-item.h"
#include "object/sp-path.h"
#include "object/sp-root.h"
@@ -32,7 +36,7 @@
#include "util/units.h"
#include "xml/node.h"
#include "xml/sp-css-attr.h"
-
+#include "libnrtype/Layout-TNG.h"
#include "document.h"
#include "document-undo.h"
#include "inkscape.h"
@@ -174,7 +178,8 @@ LPEMeasureSegments::LPEMeasureSegments(LivePathEffectObject *lpeobject) :
locale_base = strdup(setlocale(LC_NUMERIC, NULL));
previous_size = 0;
pagenumber = 0;
- notebook = NULL;
+ hasprojection = false;
+ notebookpointer = NULL;
general.param_update_default(_("Base of the lpe, focus on meassure display and positioning"));
projection.param_update_default(_("This section is optional. To activate pulse the icon down \"Active\" "
" to set the elements on clipboard, the element is converted to a line with measures based on the selected items"));
@@ -267,7 +272,7 @@ LPEMeasureSegments::newWidget()
//And the signal that fire page change is called on destroy, making imposible to
//retain last used page with this signal.
//https://mail.gnome.org/archives/gtkmm-list/2013-June/msg00020.html
- notebook = Gtk::manage(new Gtk::Notebook());
+ Gtk::Notebook * notebook = Gtk::manage(new Gtk::Notebook());
notebook->append_page (*vbox0, Glib::ustring(_("General")));
notebook->append_page (*vbox1, Glib::ustring(_("Projection")));
notebook->append_page (*vbox2, Glib::ustring(_("Options")));
@@ -278,6 +283,7 @@ LPEMeasureSegments::newWidget()
vbox3->show_all();
vbox->pack_start(*notebook, true, true, 2);
notebook->set_current_page(pagenumber);
+ notebookpointer = Gtk::manage(notebook);
if(Gtk::Widget* widg = defaultParamSet()) {
//Wrap to make it more omogenious
Gtk::VBox *vbox4 = Gtk::manage(new Gtk::VBox());
@@ -442,10 +448,14 @@ LPEMeasureSegments::createTextLabel(Geom::Point pos, size_t counter, double leng
setlocale (LC_NUMERIC, "C");
}
gchar length_str[64];
- if (smallx100 && length < 1.0) {
- length *= 100;
+ bool x100 = false;
+ if (smallx100 && length < 1 ) {
+ length *=100;
+ x100 = true;
+ g_snprintf(length_str, 64, "%.*f", (int)precision - 2, length);
+ } else {
+ g_snprintf(length_str, 64, "%.*f", (int)precision, length);
}
- g_snprintf(length_str, 64, "%.*f", (int)precision, length);
setlocale (LC_NUMERIC, locale_base);
gchar * format_str = format.param_getSVGValue();
Glib::ustring label_value(format_str);
@@ -454,9 +464,14 @@ LPEMeasureSegments::createTextLabel(Geom::Point pos, size_t counter, double leng
if(s < label_value.length()) {
label_value.replace(s,s+9,length_str);
}
+
s = label_value.find(Glib::ustring("{unit}"),0);
if(s < label_value.length()) {
- label_value.replace(s,s+6,unit.get_abbreviation());
+ if (x100) {
+ label_value.replace(s,s+6,"");
+ } else {
+ label_value.replace(s,s+6,unit.get_abbreviation());
+ }
}
if ( !valid ) {
label_value = Glib::ustring(_("Non Uniform Scale"));
@@ -590,10 +605,12 @@ LPEMeasureSegments::createLine(Geom::Point start,Geom::Point end, Glib::ustring
}
if (main) {
line->setAttribute("inkscape:label", "dinline");
- if (arrows_outside) {
- style += "marker-start:url(#ArrowDINout-start);marker-end:url(#ArrowDINout-end);";
- } else {
- style += "marker-start:url(#ArrowDIN-start);marker-end:url(#ArrowDIN-end);";
+ if (!hide_arrows) {
+ if (arrows_outside) {
+ style += "marker-start:url(#ArrowDINout-start);marker-end:url(#ArrowDINout-end);";
+ } else {
+ style += "marker-start:url(#ArrowDIN-start);marker-end:url(#ArrowDIN-end);";
+ }
}
} else {
line->setAttribute("inkscape:label", "dinhelpline");
@@ -689,10 +706,19 @@ LPEMeasureSegments::doOnApply(SPLPEItem const* lpeitem)
DocumentUndo::setUndoSensitive(document, saved);
}
+Geom::PathVector
+LPEMeasureSegments::doEffect_path (Geom::PathVector const & path_in) {
+ if (hasprojection) {
+ Geom::PathVector projectline_pv;
+ projectline_pv.push_back(projectionline);
+ return projectline_pv;
+ }
+ return path_in;
+}
+
bool
-LPEMeasureSegments::hasMeassure (size_t i)
+LPEMeasureSegments::isWhitelist (size_t i, gchar * blacklist_str, bool whitelist)
{
- gchar * blacklist_str = blacklist.param_getSVGValue();
std::string listsegments(std::string(blacklist_str) + std::string(","));
g_free(blacklist_str);
listsegments.erase(std::remove(listsegments.begin(), listsegments.end(), ' '), listsegments.end());
@@ -713,7 +739,8 @@ LPEMeasureSegments::hasMeassure (size_t i)
return false;
}
-double getAngle(Geom::Point p1, Geom::Point p2, Geom::Point p3, bool flip_side, double fix_overlaps){
+double getAngle(Geom::Point p1, Geom::Point p2, Geom::Point p3, bool flip_side, double fix_overlaps)
+{
Geom::Ray ray_1(p2,p1);
Geom::Ray ray_2(p3,p1);
bool ccw_toggle = cross(p1 - p2, p3 - p2) < 0;
@@ -727,6 +754,69 @@ double getAngle(Geom::Point p1, Geom::Point p2, Geom::Point p3, bool flip_side,
return angle;
}
+std::vector< Point > getNodes(SPItem * item)
+{
+ std::vector< Point > current_nodes;
+ SPShape * shape = dynamic_cast<SPShape *> (item);
+ SPText * text = dynamic_cast<SPText *> (item);
+ SPGroup * group = dynamic_cast<SPGroup *> (item);
+ SPFlowtext * flowtext = dynamic_cast<SPFlowtext *> (item);
+ //TODO handle clones/use
+ if (group) {
+ std::vector<SPItem*> const item_list = sp_item_group_item_list(group);
+ for ( std::vector<SPItem*>::const_iterator iter=item_list.begin();iter!=item_list.end();++iter) {
+ SPItem *sub_item = *iter;
+ std::vector< Point > nodes = getNodes(sub_item);
+ current_nodes.insert(current_nodes.end(), nodes.begin(), nodes.end());
+ }
+ } else if (shape) {
+ SPCurve * c = shape->getCurve();
+ current_nodes = c->get_pathvector().nodes();
+ c->unref();
+ } else if (text || flowtext) {
+ Inkscape::Text::Layout::iterator iter = te_get_layout(item)->begin();
+ do {
+ Inkscape::Text::Layout::iterator iter_next = iter;
+ iter_next.nextGlyph(); // iter_next is one glyph ahead from iter
+ if (iter == iter_next) {
+ break;
+ }
+ // get path from iter to iter_next:
+ SPCurve *curve = te_get_layout(item)->convertToCurves(iter, iter_next);
+ iter = iter_next; // shift to next glyph
+ if (!curve) {
+ continue; // error converting this glyph
+ }
+ if (curve->is_empty()) { // whitespace glyph?
+ curve->unref();
+ continue;
+ }
+ std::vector< Point > letter_nodes = curve->get_pathvector().nodes();
+ current_nodes.insert(current_nodes.end(),letter_nodes.begin(),letter_nodes.end());
+ if (iter == te_get_layout(item)->end()) {
+ break;
+ }
+ } while (true);
+ } else {
+ Geom::OptRect bbox = item->geometricBounds();
+ if (bbox) {
+ current_nodes.push_back((*bbox).corner(0));
+ current_nodes.push_back((*bbox).corner(1));
+ current_nodes.push_back((*bbox).corner(2));
+ current_nodes.push_back((*bbox).corner(3));
+ }
+ }
+ return current_nodes;
+}
+
+bool sortPointsX (Geom::Point a,Geom::Point b) {
+ return (a[Geom::X] < b[Geom::X]);
+}
+
+bool sortPointsY (Geom::Point a,Geom::Point b) {
+ return (a[Geom::Y] < b[Geom::Y]);
+}
+
void
LPEMeasureSegments::doBeforeEffect (SPLPEItem const* lpeitem)
{
@@ -740,9 +830,97 @@ LPEMeasureSegments::doBeforeEffect (SPLPEItem const* lpeitem)
if (root_origin != root) {
return;
}
- if (notebook) {
- pagenumber = notebook->get_current_page();
+ SPDesktop * desktop = SP_ACTIVE_DESKTOP;
+ if (desktop && notebookpointer &&
+ desktop->getSelection()->includes(sp_lpe_item) &&
+ desktop->getSelection()->singleItem ())
+ {
+ pagenumber = notebookpointer->get_current_page();
+ } else {
+ notebookpointer = NULL;
}
+ //Projection prepare
+ Geom::PathVector pathvector;
+ std::vector< Point > nodes;
+ for (std::vector<ItemAndActive*>::iterator iter = linked_items._vector.begin(); iter != linked_items._vector.end(); ++iter) {
+ SPObject *obj;
+ if ((*iter)->ref.isAttached() && (obj = (*iter)->ref.getObject()) && SP_IS_ITEM(obj)) {
+ SPItem * item = dynamic_cast<SPItem *>(obj);
+ if (item) {
+ hasprojection = true;
+ std::vector< Point > current_nodes = getNodes(item);
+ nodes.insert(nodes.end(),current_nodes.begin(), current_nodes.end());
+ }
+ }
+ }
+ if (hasprojection) {
+ std::vector<Point> result;
+ double mindistance = std::numeric_limits<double>::max();
+ double maxdistance = 0.0;
+ for ( std::vector<Point>::iterator iter = nodes.begin(); iter != nodes.end(); ++iter ) {
+ Geom::Point point = (*iter);
+
+ if (vertical_projection) {
+ if (point[Geom::X] < mindistance) {
+ mindistance = point[Geom::X];
+ }
+ if (point[Geom::X] > maxdistance) {
+ maxdistance = point[Geom::X];
+ }
+ } else {
+ if (point[Geom::Y] < mindistance) {
+ mindistance = point[Geom::Y];
+ }
+ if (point[Geom::Y] > maxdistance) {
+ maxdistance = point[Geom::Y];
+ }
+ }
+ }
+ for ( std::vector<Point>::iterator iter = nodes.begin(); iter != nodes.end(); ++iter ) {
+ Geom::Point point = (*iter);
+ if (vertical_projection) {
+ Geom::Coord xpos = oposite_projection?distance_projection+maxdistance:-distance_projection+mindistance;
+ result.push_back(Geom::Point(xpos, point[Geom::Y]));
+ } else {
+ Geom::Coord ypos = oposite_projection?distance_projection+maxdistance:-distance_projection+mindistance;
+ result.push_back(Geom::Point(point[Geom::X], ypos));
+ }
+ }
+ if (vertical_projection) {
+ std::sort (result.begin(), result.end(), sortPointsY);
+ } else {
+ std::sort (result.begin(), result.end(), sortPointsX);
+ }
+ Geom::Path path;
+ Geom::Point prevpoint(0,0);
+ size_t counter = 0;
+ bool started = false;
+ for ( std::vector<Point>::iterator iter = result.begin(); iter != result.end(); ++iter ) {
+ Geom::Point point = (*iter);
+ if (Geom::are_near(prevpoint, point)){
+ continue;
+ }
+ gchar * blacklist_nodes_str = blacklist_nodes.param_getSVGValue();
+ if (isWhitelist(counter + 1, blacklist_nodes_str, (bool)whitelist_nodes)) {
+ if (!started) {
+ path.setInitial(point);
+ started = true;
+ } else {
+ path.appendNew<Geom::LineSegment>(point);
+ }
+ }
+ counter ++;
+ prevpoint = point;
+ }
+ Geom::Affine affinetransform = i2anc_affine(SP_OBJECT(lpeitem->parent), SP_OBJECT(document->getRoot()));
+ path *= affinetransform;
+ projectionline.clear();
+ projectionline.setInitial(path.initialPoint());
+ projectionline.appendNew<Geom::LineSegment>(path.finalPoint());
+ pathvector.push_back(path);
+ }
+
+ //end projection prepare
SPShape *shape = dynamic_cast<SPShape *>(splpeitem);
if (shape) {
//only check constrain viewbox on X
@@ -778,7 +956,9 @@ LPEMeasureSegments::doBeforeEffect (SPLPEItem const* lpeitem)
Geom::Point end_stored = Geom::Point(0,0);
Geom::Point next_stored = Geom::Point(0,0);
Geom::Affine affinetransform = i2anc_affine(SP_OBJECT(lpeitem->parent), SP_OBJECT(document->getRoot()));
- Geom::PathVector pathvector = pathv_to_linear_and_cubic_beziers(c->get_pathvector());
+ if (!hasprojection) {
+ pathvector = pathv_to_linear_and_cubic_beziers(c->get_pathvector());
+ }
c->unref();
Geom::Affine writed_transform = Geom::identity();
sp_svg_transform_read(splpeitem->getAttribute("transform"), &writed_transform );
@@ -814,7 +994,8 @@ LPEMeasureSegments::doBeforeEffect (SPLPEItem const* lpeitem)
} else if (pathvector[i].size() > j + 1) {
next = pathvector[i].pointAt(j+2);
}
- if (hasMeassure(counter) && !Geom::are_near(start, end)) {
+ gchar * blacklist_str = blacklist.param_getSVGValue();
+ if (isWhitelist(counter + 1, blacklist_str, (bool)whitelist) && !Geom::are_near(start, end)) {
Glib::ustring idprev = Glib::ustring("infoline-on-start-");
idprev += Glib::ustring::format(counter-1);
idprev += "-";
@@ -895,12 +1076,14 @@ LPEMeasureSegments::doBeforeEffect (SPLPEItem const* lpeitem)
texton += "-";
texton += lpobjid;
items.push_back(texton);
- if (arrows_outside) {
- items.push_back(Glib::ustring("ArrowDINout-start"));
- items.push_back(Glib::ustring("ArrowDINout-end"));
- } else {
- items.push_back(Glib::ustring("ArrowDIN-start"));
- items.push_back(Glib::ustring("ArrowDIN-end"));
+ if (!hide_arrows) {
+ if (arrows_outside) {
+ items.push_back(Glib::ustring("ArrowDINout-start"));
+ items.push_back(Glib::ustring("ArrowDINout-end"));
+ } else {
+ items.push_back(Glib::ustring("ArrowDIN-start"));
+ items.push_back(Glib::ustring("ArrowDIN-end"));
+ }
}
if (((Geom::are_near(prev, prev_stored, 0.01) && Geom::are_near(next, next_stored, 0.01)) ||
fix_overlaps_degree == 180) &&
@@ -1002,12 +1185,14 @@ LPEMeasureSegments::doBeforeEffect (SPLPEItem const* lpeitem)
}
length = Geom::distance(start,end) * scale;
Geom::Point pos = Geom::middle_point(hstart,hend);
- if (arrows_outside) {
- createArrowMarker(Glib::ustring("ArrowDINout-start"));
- createArrowMarker(Glib::ustring("ArrowDINout-end"));
- } else {
- createArrowMarker(Glib::ustring("ArrowDIN-start"));
- createArrowMarker(Glib::ustring("ArrowDIN-end"));
+ if (!hide_arrows) {
+ if (arrows_outside) {
+ createArrowMarker(Glib::ustring("ArrowDINout-start"));
+ createArrowMarker(Glib::ustring("ArrowDINout-end"));
+ } else {
+ createArrowMarker(Glib::ustring("ArrowDIN-start"));
+ createArrowMarker(Glib::ustring("ArrowDIN-end"));
+ }
}
if (angle >= rad_from_deg(90) && angle < rad_from_deg(270)) {
pos = pos - Point::polar(angle_cross, text_top_bottom + (fontsize/2.5));
@@ -1038,6 +1223,9 @@ LPEMeasureSegments::doBeforeEffect (SPLPEItem const* lpeitem)
if(flip_side) {
arrow_gap *= -1;
}
+ if(hide_arrows) {
+ arrow_gap *= 0;
+ }
createLine(end, hend, Glib::ustring("infoline-on-end-"), counter, false, false);
if (!arrows_outside) {
hstart = hstart + Point::polar(angle, arrow_gap);
diff --git a/src/live_effects/lpe-measure-segments.h b/src/live_effects/lpe-measure-segments.h
index 1c46c073b..08f20f2a3 100644
--- a/src/live_effects/lpe-measure-segments.h
+++ b/src/live_effects/lpe-measure-segments.h
@@ -38,14 +38,14 @@ public:
virtual void doOnApply(SPLPEItem const* lpeitem);
virtual void doBeforeEffect (SPLPEItem const* lpeitem);
virtual void doOnRemove(SPLPEItem const* /*lpeitem*/);
- virtual void doEffect(SPCurve * curve){}; //stop the chain
+ virtual Geom::PathVector doEffect_path (Geom::PathVector const & path_in);
virtual void doOnVisibilityToggled(SPLPEItem const* /*lpeitem*/);
virtual Gtk::Widget * newWidget();
virtual void transform_multiply(Geom::Affine const& postmul, bool set);
void createLine(Geom::Point start,Geom::Point end, Glib::ustring name, size_t counter, bool main, bool remove, bool arrows = false);
void createTextLabel(Geom::Point pos, size_t counter, double length, Geom::Coord angle, bool remove, bool valid);
void createArrowMarker(Glib::ustring mode);
- bool hasMeassure (size_t i);
+ bool isWhitelist(size_t i, gchar * blacklist_str, bool whitelist);
private:
UnitParam unit;
EnumParam<OrientationMethod> orientation;
@@ -82,16 +82,18 @@ private:
MessageParam tips;
Glib::ustring display_unit;
bool locked_pagenumber;
+ bool hasprojection;
double doc_scale;
double fontsize;
double anotation_width;
double previous_size;
unsigned rgb24;
double arrow_gap;
+ Geom::Path projectionline;
guint pagenumber;
gchar const* locale_base;
Geom::Affine star_ellipse_fix;
- Gtk::Notebook * notebook;
+ Gtk::Notebook * notebookpointer;
LPEMeasureSegments(const LPEMeasureSegments &);
LPEMeasureSegments &operator=(const LPEMeasureSegments &);