summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/2geom/toposweep.cpp1
-rw-r--r--src/desktop.h2
-rw-r--r--src/display/drawing-context.h1
-rw-r--r--src/display/drawing-text.cpp471
-rw-r--r--src/display/drawing-text.h4
-rw-r--r--src/display/nr-style.cpp158
-rw-r--r--src/display/nr-style.h11
-rw-r--r--src/inkscape-manifest-x64.xml10
-rw-r--r--src/inkscape-x64.rc30
-rw-r--r--src/inkview-manifest-x64.xml10
-rw-r--r--src/inkview-x64.rc29
-rw-r--r--src/libdepixelize/kopftracer2011.cpp4
-rw-r--r--src/libdepixelize/kopftracer2011.h1
-rw-r--r--src/live_effects/CMakeLists.txt4
-rw-r--r--src/live_effects/Makefile_insert4
-rw-r--r--src/live_effects/effect-enum.h2
-rw-r--r--src/live_effects/effect.cpp21
-rw-r--r--src/live_effects/lpe-bspline.cpp35
-rw-r--r--src/live_effects/lpe-lattice.h1
-rw-r--r--src/live_effects/lpe-lattice2.cpp496
-rw-r--r--src/live_effects/lpe-lattice2.h92
-rw-r--r--src/live_effects/lpe-simplify.cpp287
-rw-r--r--src/live_effects/lpe-simplify.h59
-rw-r--r--src/live_effects/lpe-vonkoch.cpp3
-rw-r--r--src/live_effects/parameter/Makefile_insert4
-rw-r--r--src/live_effects/parameter/pointreseteable.cpp210
-rw-r--r--src/live_effects/parameter/pointreseteable.h74
-rw-r--r--src/live_effects/parameter/togglebutton.cpp92
-rw-r--r--src/live_effects/parameter/togglebutton.h56
-rw-r--r--src/prefix.cpp3
-rw-r--r--src/sp-paint-server.cpp5
-rw-r--r--src/sp-paint-server.h1
-rw-r--r--src/sp-pattern.cpp14
-rw-r--r--src/sp-pattern.h2
-rw-r--r--src/sp-tag-use-reference.h2
-rw-r--r--src/style-internal.cpp208
-rw-r--r--src/style-internal.h20
-rw-r--r--src/ui/dialog/filedialogimpl-win32.cpp12
-rw-r--r--src/ui/dialog/filedialogimpl-win32.h8
-rw-r--r--src/ui/dialog/tags.cpp6
-rw-r--r--src/ui/dialog/text-edit.cpp8
-rw-r--r--src/ui/tool/node.cpp6
-rw-r--r--src/ui/tool/node.h3
-rw-r--r--src/ui/tools/node-tool.cpp48
-rw-r--r--src/ui/tools/node-tool.h2
-rw-r--r--src/ui/tools/pen-tool.cpp22
-rw-r--r--src/ui/widget/registered-widget.cpp53
-rw-r--r--src/ui/widget/registered-widget.h25
-rw-r--r--src/widgets/ege-paint-def.cpp1
49 files changed, 2291 insertions, 330 deletions
diff --git a/src/2geom/toposweep.cpp b/src/2geom/toposweep.cpp
index cfb91857c..4da3f6922 100644
--- a/src/2geom/toposweep.cpp
+++ b/src/2geom/toposweep.cpp
@@ -53,6 +53,7 @@ TopoGraph::Edge TopoGraph::remove_edge(unsigned ix, unsigned jx) {
}
}
assert(0);
+ return v[0]; // if assert is disabled, return first Edge.
}
void TopoGraph::cannonize() {
diff --git a/src/desktop.h b/src/desktop.h
index be2bf891f..ec240dd40 100644
--- a/src/desktop.h
+++ b/src/desktop.h
@@ -442,7 +442,7 @@ private:
prefs->addObserver(*this);
}
private:
- void notify(Inkscape::Preferences::Entry const &val) {
+ void notify(Inkscape::Preferences::Entry const &) {
_desktop->redrawDesktop();
}
SPDesktop *_desktop;
diff --git a/src/display/drawing-context.h b/src/display/drawing-context.h
index d990bcb73..0d82087c3 100644
--- a/src/display/drawing-context.h
+++ b/src/display/drawing-context.h
@@ -61,6 +61,7 @@ public:
cairo_curve_to(_ct, p1[Geom::X], p1[Geom::Y], p2[Geom::X], p2[Geom::Y], p3[Geom::X], p3[Geom::Y]);
}
void arc(Geom::Point const &center, double radius, Geom::AngleInterval const &angle);
+ void closePath() { cairo_close_path(_ct); }
void rectangle(Geom::Rect const &r) {
cairo_rectangle(_ct, r.left(), r.top(), r.width(), r.height());
}
diff --git a/src/display/drawing-text.cpp b/src/display/drawing-text.cpp
index 4178cb1d8..05a2c3c2a 100644
--- a/src/display/drawing-text.cpp
+++ b/src/display/drawing-text.cpp
@@ -67,16 +67,14 @@ unsigned DrawingGlyphs::_updateItem(Geom::IntRect const &/*area*/, UpdateContext
_pick_bbox = Geom::IntRect();
_bbox = Geom::IntRect();
-/* orignally it did the one line below,
- but it did not handle ws characters at all, and it had problems with scaling for overline/underline.
- Replaced with the section below, which seems to be much more stable.
-
- Geom::OptRect b = bounds_exact_transformed(*_font->PathVector(_glyph), ctx.ctm);
-*/
- /* Make a bounding box that is a little taller and lower (currently 10% extra) than the font's drawing box. Extra space is
- to hold overline or underline, if present. All characters in a font use the same ascent and descent,
- but different widths. This lets leading and trailing spaces have text decorations. If it is not done
- the bounding box is limited to the box surrounding the drawn parts of visible glyphs only, and draws outside are ignored.
+ /*
+ Make a bounding box for drawing that is a little taller and lower (currently 10% extra) than
+ the font's drawing box. Extra space is to hold overline or underline, if present. All
+ characters in a font use the same ascent and descent, but different widths. This lets leading
+ and trailing spaces have text decorations. If it is not done the bounding box is limited to
+ the box surrounding the drawn parts of visible glyphs only, and draws outside are ignored.
+ The box is also a hair wider than the text, since the glyphs do not always start or end at
+ the left and right edges of the box defined in the font.
*/
float scale_bigbox = 1.0;
@@ -84,9 +82,45 @@ unsigned DrawingGlyphs::_updateItem(Geom::IntRect const &/*area*/, UpdateContext
scale_bigbox /= _transform->descrim();
}
- Geom::Rect bigbox(Geom::Point(0.0, _asc*scale_bigbox*1.1),Geom::Point(_width*scale_bigbox, -_dsc*scale_bigbox*1.1));
+ Geom::Rect bigbox(Geom::Point(-_width*scale_bigbox*0.1, _asc*scale_bigbox*1.1),Geom::Point(_width*scale_bigbox, -_dsc*scale_bigbox*1.1));
Geom::Rect b = bigbox * ctx.ctm;
+ /*
+ The pick box matches the characters as best as it can, leaving no extra space above or below
+ for decorations. The pathvector may include spaces, and spaces have no drawable glyph.
+ Catch those and do not pass them to bounds_exact_transformed(), which crashes Inkscape if it
+ sees a nondrawable glyph. Instead mock up a pickbox for them using font characteristics.
+ There may also be some other similar white space characters in some other unforeseen context
+ which should be handled by this code as well..
+ */
+
+ Geom::OptRect pb;
+ if(_drawable){
+ pb = bounds_exact_transformed(*_font->PathVector(_glyph), ctx.ctm);
+ }
+ if(!pb){ // Fallback
+ Geom::Rect pbigbox(Geom::Point(0.0, _asc*scale_bigbox*0.66),Geom::Point(_width*scale_bigbox, 0.0));
+ pb = pbigbox * ctx.ctm;
+ }
+
+#if 0
+ /* FIXME if this is commented out then not even an approximation of pick on decorations */
+ /* adjust the pick box up or down to include the decorations.
+ This is only approximate since at this point we don't know how wide that line is, if it has
+ an unusual offset, and so forth. The selection point is set at what is roughly the center of
+ the decoration (vertically) for the wide ones, like wavy and double line.
+ The text decorations are not actually selectable.
+ */
+ if (_decorations.overline || _decorations.underline) {
+ double top = _asc*scale_bigbox*0.66;
+ double bot = 0;
+ if (_decorations.overline) { top = _asc * scale_bigbox * 1.025; }
+ if (_decorations.underline) { bot = -_dsc * scale_bigbox * 0.2; }
+ Geom::Rect padjbox(Geom::Point(0.0, top),Geom::Point(_width*scale_bigbox, bot));
+ pb.unionWith(padjbox * ctx.ctm);
+ }
+#endif
+
if (ggroup->_nrstyle.stroke.type != NRStyle::PAINT_NONE) {
// this expands the selection box for cases where the stroke is "thick"
float scale = ctx.ctm.descrim();
@@ -96,10 +130,11 @@ unsigned DrawingGlyphs::_updateItem(Geom::IntRect const &/*area*/, UpdateContext
float width = MAX(0.125, ggroup->_nrstyle.stroke_width * scale);
if ( fabs(ggroup->_nrstyle.stroke_width * scale) > 0.01 ) { // FIXME: this is always true
b.expandBy(0.5 * width);
+ pb->expandBy(0.5 * width);
}
// save bbox without miters for picking
- _pick_bbox = b.roundOutwards();
+ _pick_bbox = pb->roundOutwards();
float miterMax = width * ggroup->_nrstyle.miter_limit;
if ( miterMax > 0.01 ) {
@@ -110,14 +145,8 @@ unsigned DrawingGlyphs::_updateItem(Geom::IntRect const &/*area*/, UpdateContext
_bbox = b.roundOutwards();
} else {
_bbox = b.roundOutwards();
- _pick_bbox = *_bbox;
+ _pick_bbox = pb->roundOutwards();
}
-/*
-std::cout << "DEBUG _bbox"
-<< " { " << _bbox->min()[Geom::X] << " , " << _bbox->min()[Geom::Y]
-<< " } , { " << _bbox->max()[Geom::X] << " , " << _bbox->max()[Geom::Y]
-<< " }" << std::endl;
-*/
return STATE_ALL;
}
@@ -136,7 +165,8 @@ DrawingGlyphs::_pickItem(Geom::Point const &p, double delta, unsigned /*flags*/)
// With text we take a simple approach: pick if the point is in a character bbox
Geom::Rect expanded(_pick_bbox);
- expanded.expandBy(delta);
+ // FIXME, why expand by delta? When is the next line needed?
+ // expanded.expandBy(delta);
if (expanded.contains(p)) return this;
return NULL;
}
@@ -195,7 +225,7 @@ DrawingText::_updateItem(Geom::IntRect const &area, UpdateContext const &ctx, un
return DrawingGroup::_updateItem(area, ctx, flags, reset);
}
-void DrawingText::decorateStyle(DrawingContext &dc, double vextent, double xphase, Geom::Point const &p1, Geom::Point const &p2)
+void DrawingText::decorateStyle(DrawingContext &dc, double vextent, double xphase, Geom::Point const &p1, Geom::Point const &p2, double thickness)
{
double wave[16]={
0.000000, 0.382499, 0.706825, 0.923651, 1.000000, 0.923651, 0.706825, 0.382499,
@@ -213,7 +243,6 @@ void DrawingText::decorateStyle(DrawingContext &dc, double vextent, double xphas
4, 3, 2, 1,
-4, -3, -2, -1
};
- Geom::Point p3,p4,ps,pf;
double step = vextent/32.0;
unsigned i = 15 & (unsigned) round(xphase/step); // xphase is >= 0.0
@@ -221,26 +250,19 @@ void DrawingText::decorateStyle(DrawingContext &dc, double vextent, double xphas
This allows decoration continuity within the line, and does not step outside the clip box off the end
For the first/last section on the line though, stay well clear of the edge, or when the
text is dragged it may "spray" pixels.
- if(_nrstyle.tspan_line_end){ pf = p2 - Geom::Point(2*step, 0.0); }
- else { pf = p2; }
- if(_nrstyle.tspan_line_start){ ps = p1 + Geom::Point(2*step, 0.0);
- i = 15 & (i + 2);
- }
- else { ps = p1; }
*/
/* snap to nearest step in X */
-ps = Geom::Point(step * round(p1[Geom::X]/step),p1[Geom::Y]);
-pf = Geom::Point(step * round(p2[Geom::X]/step),p2[Geom::Y]);
+ Geom::Point ps = Geom::Point(step * round(p1[Geom::X]/step),p1[Geom::Y]);
+ Geom::Point pf = Geom::Point(step * round(p2[Geom::X]/step),p2[Geom::Y]);
+ Geom::Point poff = Geom::Point(0,thickness/2.0);
if(_nrstyle.text_decoration_style & TEXT_DECORATION_STYLE_ISDOUBLE){
ps -= Geom::Point(0, vextent/12.0);
pf -= Geom::Point(0, vextent/12.0);
- dc.moveTo(ps);
- dc.lineTo(pf);
+ dc.rectangle( Geom::Rect(ps + poff, pf - poff));
ps += Geom::Point(0, vextent/6.0);
pf += Geom::Point(0, vextent/6.0);
- dc.moveTo(ps);
- dc.lineTo(pf);
+ dc.rectangle( Geom::Rect(ps + poff, pf - poff));
}
/* The next three have a problem in that they are phase dependent. The bits of a line are not
necessarily passing through this routine in order, so we have to use the xphase information
@@ -248,43 +270,52 @@ pf = Geom::Point(step * round(p2[Geom::X]/step),p2[Geom::Y]);
Huge possitive offset should keep the phase calculation from ever being negative.
*/
else if(_nrstyle.text_decoration_style & TEXT_DECORATION_STYLE_DOTTED){
+ // FIXME: Per spec, this should produce round dots.
+ Geom::Point pv = ps;
while(1){
+ Geom::Point pvlast = pv;
if(dots[i]>0){
- if(ps[Geom::X]> pf[Geom::X])break;
- dc.moveTo(ps);
- ps += Geom::Point(step * (double)dots[i], 0.0);
- if(ps[Geom::X]>= pf[Geom::X]){
- dc.lineTo(pf);
+ if(pv[Geom::X] > pf[Geom::X]) break;
+
+ pv += Geom::Point(step * (double)dots[i], 0.0);
+
+ if(pv[Geom::X]>= pf[Geom::X]){
+ // Last dot
+ dc.rectangle( Geom::Rect(pvlast + poff, pf - poff));
break;
+ } else {
+ dc.rectangle( Geom::Rect(pvlast + poff, pv - poff));
}
- else {
- dc.lineTo(ps);
- }
- ps += Geom::Point(step * 4.0, 0.0);
- }
- else {
- ps += Geom::Point(step * -(double)dots[i], 0.0);
+
+ pv += Geom::Point(step * 4.0, 0.0);
+
+ } else {
+ pv += Geom::Point(step * -(double)dots[i], 0.0);
}
i = 0; // once in phase, it stays in phase
}
}
else if(_nrstyle.text_decoration_style & TEXT_DECORATION_STYLE_DASHED){
+ Geom::Point pv = ps;
while(1){
+ Geom::Point pvlast = pv;
if(dashes[i]>0){
- if(ps[Geom::X]> pf[Geom::X])break;
- dc.moveTo(ps);
- ps += Geom::Point(step * (double)dashes[i], 0.0);
- if(ps[Geom::X]>= pf[Geom::X]){
- dc.lineTo(pf);
+ if(pv[Geom::X]> pf[Geom::X]) break;
+
+ pv += Geom::Point(step * (double)dashes[i], 0.0);
+
+ if(pv[Geom::X]>= pf[Geom::X]){
+ // Last dash
+ dc.rectangle( Geom::Rect(pvlast + poff, pf - poff));
break;
+ } else {
+ dc.rectangle( Geom::Rect(pvlast + poff, pv - poff));
}
- else {
- dc.lineTo(ps);
- }
- ps += Geom::Point(step * 8.0, 0.0);
- }
- else {
- ps += Geom::Point(step * -(double)dashes[i], 0.0);
+
+ pv += Geom::Point(step * 8.0, 0.0);
+
+ } else {
+ pv += Geom::Point(step * -(double)dashes[i], 0.0);
}
i = 0; // once in phase, it stays in phase
}
@@ -292,7 +323,7 @@ pf = Geom::Point(step * round(p2[Geom::X]/step),p2[Geom::Y]);
else if(_nrstyle.text_decoration_style & TEXT_DECORATION_STYLE_WAVY){
double amp = vextent/10.0;
double x = ps[Geom::X];
- double y = ps[Geom::Y];
+ double y = ps[Geom::Y] + poff[Geom::Y];
dc.moveTo(Geom::Point(x, y + amp * wave[i]));
while(1){
i = ((i + 1) & 15);
@@ -300,17 +331,25 @@ pf = Geom::Point(step * round(p2[Geom::X]/step),p2[Geom::Y]);
dc.lineTo(Geom::Point(x, y + amp * wave[i]));
if(x >= pf[Geom::X])break;
}
- }
+ y = ps[Geom::Y] - poff[Geom::Y];
+ dc.lineTo(Geom::Point(x, y + amp * wave[i]));
+ while(1){
+ i = ((i - 1) & 15);
+ x -= step;
+ dc.lineTo(Geom::Point(x, y + amp * wave[i]));
+ if(x <= ps[Geom::X])break;
+ }
+ dc.closePath();
+ }
else { // TEXT_DECORATION_STYLE_SOLID, also default in case it was not set for some reason
- dc.moveTo(ps);
- dc.lineTo(pf);
-// dc.revrectangle(Geom::Rect(ps,pf));
+ dc.rectangle( Geom::Rect(ps + poff, pf - poff));
}
}
/* returns scaled line thickness */
-double DrawingText::decorateItem(DrawingContext &dc, Geom::Affine const &aff, double phase_length)
+void DrawingText::decorateItem(DrawingContext &dc, double phase_length, bool under)
{
+ if (_nrstyle.font_size < 1.0e-32)return; // would cause a divide by zero and nothing would be visible anyway
double tsp_width_adj = _nrstyle.tspan_width / _nrstyle.font_size;
double tsp_asc_adj = _nrstyle.ascender / _nrstyle.font_size;
double tsp_size_adj = (_nrstyle.ascender + _nrstyle.descender) / _nrstyle.font_size;
@@ -318,49 +357,54 @@ double DrawingText::decorateItem(DrawingContext &dc, Geom::Affine const &aff, do
double final_underline_thickness = CLAMP(_nrstyle.underline_thickness, tsp_size_adj/30.0, tsp_size_adj/10.0);
double final_line_through_thickness = CLAMP(_nrstyle.line_through_thickness, tsp_size_adj/30.0, tsp_size_adj/10.0);
- double scale = aff.descrim();
double xphase = phase_length/ _nrstyle.font_size; // used to figure out phase of patterns
- Inkscape::DrawingContext::Save save(dc);
- dc.transform(aff); // must be leftmost affine in span
-
Geom::Point p1;
Geom::Point p2;
// All lines must be the same thickness, in combinations, line_through trumps underline
double thickness = final_underline_thickness;
- if(_nrstyle.text_decoration_line & TEXT_DECORATION_LINE_UNDERLINE){
- p1 = Geom::Point(0.0, -_nrstyle.underline_position);
- p2 = Geom::Point(tsp_width_adj,-_nrstyle.underline_position);
- decorateStyle(dc, tsp_size_adj, xphase, p1, p2);
- }
- if(_nrstyle.text_decoration_line & TEXT_DECORATION_LINE_OVERLINE){
- p1 = Geom::Point(0.0, tsp_asc_adj -_nrstyle.underline_position + 1 * final_underline_thickness);
- p2 = Geom::Point(tsp_width_adj,tsp_asc_adj -_nrstyle.underline_position + 1 * final_underline_thickness);
- decorateStyle(dc, tsp_size_adj, xphase, p1, p2);
- }
- if(_nrstyle.text_decoration_line & TEXT_DECORATION_LINE_LINETHROUGH){
- thickness = final_line_through_thickness;
- p1 = Geom::Point(0.0, _nrstyle.line_through_position);
- p2 = Geom::Point(tsp_width_adj,_nrstyle.line_through_position);
- decorateStyle(dc, tsp_size_adj, xphase, p1, p2);
- }
- // Obviously this does not blink, but it does indicate which text has been set with that attribute
- if(_nrstyle.text_decoration_line & TEXT_DECORATION_LINE_BLINK){
- thickness = final_line_through_thickness;
- p1 = Geom::Point(0.0, _nrstyle.line_through_position - 2*final_line_through_thickness);
- p2 = Geom::Point(tsp_width_adj,_nrstyle.line_through_position - 2*final_line_through_thickness);
- decorateStyle(dc, tsp_size_adj, xphase, p1, p2);
- p1 = Geom::Point(0.0, _nrstyle.line_through_position + 2*final_line_through_thickness);
- p2 = Geom::Point(tsp_width_adj,_nrstyle.line_through_position + 2*final_line_through_thickness);
- decorateStyle(dc, tsp_size_adj, xphase, p1, p2);
+ dc.setTolerance(0.5); // Is this really necessary... could effect dots.
+
+ if( under ) {
+
+ if(_nrstyle.text_decoration_line & TEXT_DECORATION_LINE_UNDERLINE){
+ p1 = Geom::Point(0.0, -_nrstyle.underline_position);
+ p2 = Geom::Point(tsp_width_adj,-_nrstyle.underline_position);
+ decorateStyle(dc, tsp_size_adj, xphase, p1, p2, thickness);
+ }
+
+ if(_nrstyle.text_decoration_line & TEXT_DECORATION_LINE_OVERLINE){
+ p1 = Geom::Point(0.0, tsp_asc_adj -_nrstyle.underline_position + 1 * final_underline_thickness);
+ p2 = Geom::Point(tsp_width_adj,tsp_asc_adj -_nrstyle.underline_position + 1 * final_underline_thickness);
+ decorateStyle(dc, tsp_size_adj, xphase, p1, p2, thickness);
+ }
+
+ } else {
+ // Over
+
+ if(_nrstyle.text_decoration_line & TEXT_DECORATION_LINE_LINETHROUGH){
+ thickness = final_line_through_thickness;
+ p1 = Geom::Point(0.0, _nrstyle.line_through_position);
+ p2 = Geom::Point(tsp_width_adj,_nrstyle.line_through_position);
+ decorateStyle(dc, tsp_size_adj, xphase, p1, p2, thickness);
+ }
+
+ // Obviously this does not blink, but it does indicate which text has been set with that attribute
+ if(_nrstyle.text_decoration_line & TEXT_DECORATION_LINE_BLINK){
+ thickness = final_line_through_thickness;
+ p1 = Geom::Point(0.0, _nrstyle.line_through_position - 2*final_line_through_thickness);
+ p2 = Geom::Point(tsp_width_adj,_nrstyle.line_through_position - 2*final_line_through_thickness);
+ decorateStyle(dc, tsp_size_adj, xphase, p1, p2, thickness);
+ p1 = Geom::Point(0.0, _nrstyle.line_through_position + 2*final_line_through_thickness);
+ p2 = Geom::Point(tsp_width_adj,_nrstyle.line_through_position + 2*final_line_through_thickness);
+ decorateStyle(dc, tsp_size_adj, xphase, p1, p2, thickness);
+ }
}
- thickness *= scale;
- return(thickness);
}
unsigned DrawingText::_renderItem(DrawingContext &dc, Geom::IntRect const &/*area*/, unsigned /*flags*/, DrawingItem * /*stop_at*/)
{
- if (_drawing.outline()) {
+ if (_drawing.outline()) {
guint32 rgba = _drawing.outlinecolor;
Inkscape::DrawingContext::Save save(dc);
dc.setSource(rgba);
@@ -382,124 +426,187 @@ unsigned DrawingText::_renderItem(DrawingContext &dc, Geom::IntRect const &/*are
return RENDER_OK;
}
- // NOTE: this is very similar to drawing-shape.cpp; the only difference is in path feeding
- double leftmost = DBL_MAX;
- double phase_length = 0.0;
- bool firsty = true;
- bool decorate = true;
- double starty = 0.0;
- Geom::Affine aff;
- using Geom::X;
- using Geom::Y;
-
- // NOTE:
+ // NOTE: This is very similar to drawing-shape.cpp; the only differences are in path feeding
+ // and in applying text decorations.
+
+
+ // Do we have text decorations?
+ bool decorate = (_nrstyle.text_decoration_line != TEXT_DECORATION_LINE_CLEAR );
+
// prepareFill / prepareStroke need to be called with _ctm in effect.
// However, we might need to apply a different ctm for glyphs.
// Therefore, only apply this ctm temporarily.
- bool has_stroke, has_fill;
+ bool has_stroke = false;
+ bool has_fill = false;
+ bool has_td_fill = false;
+ bool has_td_stroke = false;
{
Inkscape::DrawingContext::Save save(dc);
dc.transform(_ctm);
- has_fill = _nrstyle.prepareFill( dc, _item_bbox);
- has_stroke = _nrstyle.prepareStroke(dc, _item_bbox);
+ has_fill = _nrstyle.prepareFill( dc, _item_bbox);
+ has_stroke = _nrstyle.prepareStroke( dc, _item_bbox);
+
+ // Avoid creating patterns if not needed
+ if( decorate ) {
+ has_td_fill = _nrstyle.prepareTextDecorationFill( dc, _item_bbox);
+ has_td_stroke = _nrstyle.prepareTextDecorationStroke(dc, _item_bbox);
+ }
}
- if (has_fill || has_stroke) {
- Geom::Affine rotinv;
- bool invset = false;
+ if (has_fill || has_stroke || has_td_fill || has_td_stroke) {
- // accumulate the path that represents the glyphs
- for (ChildrenList::iterator i = _children.begin(); i != _children.end(); ++i) {
- DrawingGlyphs *g = dynamic_cast<DrawingGlyphs *>(&*i);
- if (!g) throw InvalidItemException();
- if (!invset) {
- rotinv = g->_ctm.withoutTranslation().inverse();
- invset = true;
- }
+ // Determine order for fill and stroke.
+ // Text doesn't have markers, we can do paint-order quick and dirty.
+ bool fill_first = false;
+ if( _nrstyle.paint_order_layer[0] == NRStyle::PAINT_ORDER_NORMAL ||
+ _nrstyle.paint_order_layer[0] == NRStyle::PAINT_ORDER_FILL ||
+ _nrstyle.paint_order_layer[2] == NRStyle::PAINT_ORDER_STROKE ) {
+ fill_first = true;
+ } // Won't get "stroke fill stroke" but that isn't 'valid'
+
+
+ // Determine geometry of text decoration
+ double phase_length = 0.0;
+ Geom::Affine aff;
+ if( decorate ) {
+
+ Geom::Affine rotinv;
+ bool invset = false;
+ double leftmost = DBL_MAX;
+ bool first_y = true;
+ double start_y = 0.0;
+ for (ChildrenList::iterator i = _children.begin(); i != _children.end(); ++i) {
+
+ DrawingGlyphs *g = dynamic_cast<DrawingGlyphs *>(&*i);
+ if (!g) throw InvalidItemException();
+
+ if (!invset) {
+ rotinv = g->_ctm.withoutTranslation().inverse();
+ invset = true;
+ }
- Inkscape::DrawingContext::Save save(dc);
- if (g->_ctm.isSingular()) continue;
- dc.transform(g->_ctm);
- if (g->_drawable) {
- dc.path(*g->_font->PathVector(g->_glyph));
- }
- // get the leftmost affine transform (leftmost defined with respect to the x axis of the first transform).
- // That way the decoration will work no matter what mix of L->R, R->L text is in the span.
- if (_nrstyle.text_decoration_line != TEXT_DECORATION_LINE_CLEAR) {
Geom::Point pt = g->_ctm.translation() * rotinv;
- if (pt[X] < leftmost) {
- leftmost = pt[X];
+ if (pt[Geom::X] < leftmost) {
+ leftmost = pt[Geom::X];
aff = g->_ctm;
phase_length = g->_pl;
}
- /* If the text has been mapped onto a path, which causes y to vary, drop the text decorations.
- To handle that properly would need a conformal map
- */
- if (firsty) {
- firsty = false;
- starty = pt[Y];
+
+ // Check for text on a path. FIXME: This needs better test (and probably not here).
+ if (first_y) {
+ first_y = false;
+ start_y = pt[Geom::Y];
}
- else if (fabs(pt[Y] - starty) > 1.0e-6) {
+ else if (fabs(pt[Geom::Y] - start_y) > 1.0e-6) {
+ // If the text has been mapped onto a path, which causes y to vary, drop the
+ // text decorations. To handle that properly would need a conformal map.
decorate = false;
}
}
}
- // draw the text itself
- // we need to apply this object's ctm again
- Inkscape::DrawingContext::Save save(dc);
- dc.transform(_ctm);
+ // Draw text decorations that go UNDER the text (underline, over-line)
+ if( decorate ) {
- // Text doesn't have markers, we can do paint-order quick and dirty.
- bool fill_first = false;
- if( _nrstyle.paint_order_layer[0] == NRStyle::PAINT_ORDER_NORMAL ||
- _nrstyle.paint_order_layer[0] == NRStyle::PAINT_ORDER_FILL ||
- _nrstyle.paint_order_layer[2] == NRStyle::PAINT_ORDER_STROKE ) {
- fill_first = true;
- } // Won't get "stroke fill stroke" but that isn't 'valid'
+ {
+ Inkscape::DrawingContext::Save save(dc);
+ dc.transform(aff); // must be leftmost affine in span
+ decorateItem(dc, phase_length, true);
+ }
+
+ {
+ Inkscape::DrawingContext::Save save(dc);
+ dc.transform(_ctm); // Needed so that fill pattern rotates with text
+
+ if (has_td_fill && fill_first) {
+ _nrstyle.applyTextDecorationFill(dc);
+ dc.fillPreserve();
+ }
+
+ if (has_td_stroke) {
+ _nrstyle.applyTextDecorationStroke(dc);
+ dc.strokePreserve();
+ }
+
+ if (has_td_fill && !fill_first) {
+ _nrstyle.applyTextDecorationFill(dc);
+ dc.fillPreserve();
+ }
- if (has_fill && fill_first) {
- _nrstyle.applyFill(dc);
- dc.fillPreserve();
+ }
+
+ dc.newPath(); // Clear text-decoration path
}
- if (has_stroke) {
- _nrstyle.applyStroke(dc);
- dc.strokePreserve();
+ // accumulate the path that represents the glyphs
+ for (ChildrenList::iterator i = _children.begin(); i != _children.end(); ++i) {
+ DrawingGlyphs *g = dynamic_cast<DrawingGlyphs *>(&*i);
+ if (!g) throw InvalidItemException();
+
+ Inkscape::DrawingContext::Save save(dc);
+ if (g->_ctm.isSingular()) continue;
+ dc.transform(g->_ctm);
+ if (g->_drawable) {
+ dc.path(*g->_font->PathVector(g->_glyph));
+ }
}
- if (has_fill && !fill_first) {
- _nrstyle.applyFill(dc);
- dc.fillPreserve();
+ // Draw the glyphs.
+ {
+ Inkscape::DrawingContext::Save save(dc);
+ dc.transform(_ctm);
+
+ if (has_fill && fill_first) {
+ _nrstyle.applyFill(dc);
+ dc.fillPreserve();
+ }
+
+ if (has_stroke) {
+ _nrstyle.applyStroke(dc);
+ dc.strokePreserve();
+ }
+
+ if (has_fill && !fill_first) {
+ _nrstyle.applyFill(dc);
+ dc.fillPreserve();
+ }
}
+ dc.newPath(); // Clear glyphs path
+
+ // Draw text decorations that go OVER the text (line through, blink)
+ if (decorate) {
- dc.newPath(); // clear path
-
- // draw text decoration
- if (_nrstyle.text_decoration_line != TEXT_DECORATION_LINE_CLEAR && decorate) {
- guint32 ergba;
- if (_nrstyle.text_decoration_useColor) { // color different from the glyph
- ergba = SP_RGBA32_F_COMPOSE(
- _nrstyle.text_decoration_color.color.v.c[0],
- _nrstyle.text_decoration_color.color.v.c[1],
- _nrstyle.text_decoration_color.color.v.c[2],
- 1.0);
+ {
+ Inkscape::DrawingContext::Save save(dc);
+ dc.transform(aff); // must be leftmost affine in span
+ decorateItem(dc, phase_length, false);
}
- else { // whatever the current fill color is
- ergba = SP_RGBA32_F_COMPOSE(
- _nrstyle.fill.color.v.c[0],
- _nrstyle.fill.color.v.c[1],
- _nrstyle.fill.color.v.c[2],
- 1.0);
+
+ {
+ Inkscape::DrawingContext::Save save(dc);
+ dc.transform(_ctm); // Needed so that fill pattern rotates with text
+
+ if (has_td_fill && fill_first) {
+ _nrstyle.applyTextDecorationFill(dc);
+ dc.fillPreserve();
+ }
+
+ if (has_td_stroke) {
+ _nrstyle.applyTextDecorationStroke(dc);
+ dc.strokePreserve();
+ }
+
+ if (has_td_fill && !fill_first) {
+ _nrstyle.applyTextDecorationFill(dc);
+ dc.fillPreserve();
+ }
+
}
- dc.setSource(ergba);
- dc.setTolerance(0.5);
- double thickness = decorateItem(dc, aff, phase_length);
- dc.setLineWidth(thickness);
- dc.strokePreserve();
- dc.newPath(); // clear path
+
+ dc.newPath(); // Clear text-decoration path
}
+
}
return RENDER_OK;
}
diff --git a/src/display/drawing-text.h b/src/display/drawing-text.h
index 41039d85d..4453a3db4 100644
--- a/src/display/drawing-text.h
+++ b/src/display/drawing-text.h
@@ -68,8 +68,8 @@ protected:
virtual DrawingItem *_pickItem(Geom::Point const &p, double delta, unsigned flags);
virtual bool _canClip();
- double decorateItem(DrawingContext &dc, Geom::Affine const &aff, double phase_length);
- void decorateStyle(DrawingContext &dc, double vextent, double xphase, Geom::Point const &p1, Geom::Point const &p2);
+ void decorateItem(DrawingContext &dc, double phase_length, bool under);
+ void decorateStyle(DrawingContext &dc, double vextent, double xphase, Geom::Point const &p1, Geom::Point const &p2, double thickness);
NRStyle _nrstyle;
friend class DrawingGlyphs;
diff --git a/src/display/nr-style.cpp b/src/display/nr-style.cpp
index 09a28e63c..a9f101f69 100644
--- a/src/display/nr-style.cpp
+++ b/src/display/nr-style.cpp
@@ -54,8 +54,13 @@ NRStyle::NRStyle()
, line_join(CAIRO_LINE_JOIN_MITER)
, fill_pattern(NULL)
, stroke_pattern(NULL)
+ , text_decoration_fill_pattern(NULL)
+ , text_decoration_stroke_pattern(NULL)
, text_decoration_line(TEXT_DECORATION_LINE_CLEAR)
, text_decoration_style(TEXT_DECORATION_STYLE_CLEAR)
+ , text_decoration_fill()
+ , text_decoration_stroke()
+ , text_decoration_stroke_width(0.0)
, phase_length(0.0)
, tspan_line_start(false)
, tspan_line_end(false)
@@ -76,17 +81,28 @@ NRStyle::~NRStyle()
{
if (fill_pattern) cairo_pattern_destroy(fill_pattern);
if (stroke_pattern) cairo_pattern_destroy(stroke_pattern);
+ if (text_decoration_fill_pattern) cairo_pattern_destroy(text_decoration_fill_pattern);
+ if (text_decoration_stroke_pattern) cairo_pattern_destroy(text_decoration_stroke_pattern);
if (dash){
delete [] dash;
}
fill.clear();
stroke.clear();
+ text_decoration_fill.clear();
+ text_decoration_stroke.clear();
}
void NRStyle::set(SPStyle *style)
{
if ( style->fill.isPaintserver() ) {
- fill.set(style->getFillPaintServer());
+ SPPaintServer* server = style->getFillPaintServer();
+ if ( server && server->isValid() ) {
+ fill.set(server);
+ } else if ( style->fill.colorSet ) {
+ fill.set(style->fill.value.color);
+ } else {
+ fill.clear();
+ }
} else if ( style->fill.isColor() ) {
fill.set(style->fill.value.color);
} else if ( style->fill.isNone() ) {
@@ -108,7 +124,14 @@ void NRStyle::set(SPStyle *style)
}
if ( style->stroke.isPaintserver() ) {
- stroke.set(style->getStrokePaintServer());
+ SPPaintServer* server = style->getStrokePaintServer();
+ if ( server && server->isValid() ) {
+ stroke.set(server);
+ } else if ( style->stroke.isColor() ) {
+ stroke.set(style->stroke.colorSet);
+ } else {
+ stroke.clear();
+ }
} else if ( style->stroke.isColor() ) {
stroke.set(style->stroke.value.color);
} else if ( style->stroke.isNone() ) {
@@ -195,15 +218,65 @@ void NRStyle::set(SPStyle *style)
if(style->text_decoration_style.dashed ){ text_decoration_style |= TEXT_DECORATION_STYLE_DASHED + TEXT_DECORATION_STYLE_SET; }
if(style->text_decoration_style.wavy ){ text_decoration_style |= TEXT_DECORATION_STYLE_WAVY + TEXT_DECORATION_STYLE_SET; }
+ /* FIXME
+ The meaning of text-decoration-color in CSS3 for SVG is ambiguous (2014-05-06). Set
+ it for fill, for stroke, for both? Both would seem like the obvious choice but what happens
+ is that for text which is just fill (very common) it makes the lines fatter because it
+ enables stroke on the decorations when it wasn't present on the text. That contradicts the
+ usual behavior where the text and decorations by default have the same fill/stroke.
+
+ The behavior here is that if color is defined it is applied to text_decoration_fill/stroke
+ ONLY if the corresponding fill/stroke is also present.
+
+ Hopefully the standard will be clarified to resolve this issue.
+ */
+
+ SPStyle* style_td = style;
+ if ( style->text_decoration.style_td ) style_td = style->text_decoration.style_td;
+ text_decoration_stroke.opacity = SP_SCALE24_TO_FLOAT(style_td->stroke_opacity.value);
+ text_decoration_stroke_width = style_td->stroke_width.computed;
+
if( style->text_decoration_color.set ||
style->text_decoration_color.inherit ||
- style->text_decoration_color.currentcolor ){
- text_decoration_color.set(style->text_decoration_color.value.color);
- text_decoration_useColor = true;
- }
- else {
- text_decoration_color.clear();
- text_decoration_useColor = false;
+ style->text_decoration_color.currentcolor ) {
+
+ if(style->fill.isPaintserver() || style->fill.isColor()) {
+ // SVG sets color specifically
+ text_decoration_fill.set(style->text_decoration_color.value.color);
+ } else {
+ // No decoration fill because no text fill
+ text_decoration_fill.clear();
+ }
+
+ if(style->stroke.isPaintserver() || style->stroke.isColor()) {
+ // SVG sets color specifically
+ text_decoration_stroke.set(style->text_decoration_color.value.color);
+ } else {
+ // No decoration stroke because no text stroke
+ text_decoration_stroke.clear();
+ }
+
+ } else {
+ // Pick color/pattern from text
+ if ( style_td->fill.isPaintserver() ) {
+ text_decoration_fill.set(style_td->getFillPaintServer());
+ } else if ( style_td->fill.isColor() ) {
+ text_decoration_fill.set(style_td->fill.value.color);
+ } else if ( style_td->fill.isNone() ) {
+ text_decoration_fill.clear();
+ } else {
+ g_assert_not_reached();
+ }
+
+ if ( style_td->stroke.isPaintserver() ) {
+ text_decoration_stroke.set(style_td->getStrokePaintServer());
+ } else if ( style_td->stroke.isColor() ) {
+ text_decoration_stroke.set(style_td->stroke.value.color);
+ } else if ( style_td->stroke.isNone() ) {
+ text_decoration_stroke.clear();
+ } else {
+ g_assert_not_reached();
+ }
}
if(text_decoration_line != TEXT_DECORATION_LINE_CLEAR){
@@ -232,10 +305,8 @@ bool NRStyle::prepareFill(Inkscape::DrawingContext &dc, Geom::OptRect const &pai
if (!fill_pattern) {
switch (fill.type) {
case PAINT_SERVER: {
- //fill_pattern = sp_paint_server_create_pattern(fill.server, dc.raw(), paintbox, fill.opacity);
- fill_pattern = fill.server->pattern_new(dc.raw(), paintbox, fill.opacity);
-
- } break;
+ fill_pattern = fill.server->pattern_new(dc.raw(), paintbox, fill.opacity);
+ } break;
case PAINT_COLOR: {
SPColor const &c = fill.color;
fill_pattern = cairo_pattern_create_rgba(
@@ -254,14 +325,38 @@ void NRStyle::applyFill(Inkscape::DrawingContext &dc)
dc.setFillRule(fill_rule);
}
+bool NRStyle::prepareTextDecorationFill(Inkscape::DrawingContext &dc, Geom::OptRect const &paintbox)
+{
+ // update text decoration pattern
+ if (!text_decoration_fill_pattern) {
+ switch (text_decoration_fill.type) {
+ case PAINT_SERVER: {
+ text_decoration_fill_pattern = text_decoration_fill.server->pattern_new(dc.raw(), paintbox, text_decoration_fill.opacity);
+ } break;
+ case PAINT_COLOR: {
+ SPColor const &c = text_decoration_fill.color;
+ text_decoration_fill_pattern = cairo_pattern_create_rgba(
+ c.v.c[0], c.v.c[1], c.v.c[2], text_decoration_fill.opacity);
+ } break;
+ default: break;
+ }
+ }
+ if (!text_decoration_fill_pattern) return false;
+ return true;
+}
+
+void NRStyle::applyTextDecorationFill(Inkscape::DrawingContext &dc)
+{
+ dc.setSource(text_decoration_fill_pattern);
+ // Fill rule does not matter, no intersections.
+}
+
bool NRStyle::prepareStroke(Inkscape::DrawingContext &dc, Geom::OptRect const &paintbox)
{
if (!stroke_pattern) {
switch (stroke.type) {
case PAINT_SERVER: {
- //stroke_pattern = sp_paint_server_create_pattern(stroke.server, dc.raw(), paintbox, stroke.opacity);
stroke_pattern = stroke.server->pattern_new(dc.raw(), paintbox, stroke.opacity);
-
} break;
case PAINT_COLOR: {
SPColor const &c = stroke.color;
@@ -285,13 +380,46 @@ void NRStyle::applyStroke(Inkscape::DrawingContext &dc)
cairo_set_dash(dc.raw(), dash, n_dash, dash_offset); // fixme
}
+bool NRStyle::prepareTextDecorationStroke(Inkscape::DrawingContext &dc, Geom::OptRect const &paintbox)
+{
+ if (!text_decoration_stroke_pattern) {
+ switch (text_decoration_stroke.type) {
+ case PAINT_SERVER: {
+ text_decoration_stroke_pattern = text_decoration_stroke.server->pattern_new(dc.raw(), paintbox, text_decoration_stroke.opacity);
+ } break;
+ case PAINT_COLOR: {
+ SPColor const &c = text_decoration_stroke.color;
+ text_decoration_stroke_pattern = cairo_pattern_create_rgba(
+ c.v.c[0], c.v.c[1], c.v.c[2], text_decoration_stroke.opacity);
+ } break;
+ default: break;
+ }
+ }
+ if (!text_decoration_stroke_pattern) return false;
+ return true;
+}
+
+void NRStyle::applyTextDecorationStroke(Inkscape::DrawingContext &dc)
+{
+ dc.setSource(text_decoration_stroke_pattern);
+ dc.setLineWidth(text_decoration_stroke_width);
+ dc.setLineCap(CAIRO_LINE_CAP_BUTT);
+ dc.setLineJoin(CAIRO_LINE_JOIN_MITER);
+ dc.setMiterLimit(miter_limit);
+ cairo_set_dash(dc.raw(), 0, 0, 0.0); // fixme (no dash)
+}
+
void NRStyle::update()
{
// force pattern update
if (fill_pattern) cairo_pattern_destroy(fill_pattern);
if (stroke_pattern) cairo_pattern_destroy(stroke_pattern);
+ if (text_decoration_fill_pattern) cairo_pattern_destroy(text_decoration_fill_pattern);
+ if (text_decoration_stroke_pattern) cairo_pattern_destroy(text_decoration_stroke_pattern);
fill_pattern = NULL;
stroke_pattern = NULL;
+ text_decoration_fill_pattern = NULL;
+ text_decoration_stroke_pattern = NULL;
}
/*
diff --git a/src/display/nr-style.h b/src/display/nr-style.h
index ca880c00b..83bcb1ab7 100644
--- a/src/display/nr-style.h
+++ b/src/display/nr-style.h
@@ -30,8 +30,12 @@ struct NRStyle {
void set(SPStyle *);
bool prepareFill(Inkscape::DrawingContext &dc, Geom::OptRect const &paintbox);
bool prepareStroke(Inkscape::DrawingContext &dc, Geom::OptRect const &paintbox);
+ bool prepareTextDecorationFill(Inkscape::DrawingContext &dc, Geom::OptRect const &paintbox);
+ bool prepareTextDecorationStroke(Inkscape::DrawingContext &dc, Geom::OptRect const &paintbox);
void applyFill(Inkscape::DrawingContext &dc);
void applyStroke(Inkscape::DrawingContext &dc);
+ void applyTextDecorationFill(Inkscape::DrawingContext &dc);
+ void applyTextDecorationStroke(Inkscape::DrawingContext &dc);
void update();
enum PaintType {
@@ -67,6 +71,8 @@ struct NRStyle {
cairo_pattern_t *fill_pattern;
cairo_pattern_t *stroke_pattern;
+ cairo_pattern_t *text_decoration_fill_pattern;
+ cairo_pattern_t *text_decoration_stroke_pattern;
enum PaintOrderType {
PAINT_ORDER_NORMAL,
@@ -97,8 +103,9 @@ struct NRStyle {
int text_decoration_line;
int text_decoration_style;
- Paint text_decoration_color;
- bool text_decoration_useColor; // if false, use whatever the glyph color was
+ Paint text_decoration_fill;
+ Paint text_decoration_stroke;
+ float text_decoration_stroke_width;
// These are the same as in style.h
float phase_length;
bool tspan_line_start;
diff --git a/src/inkscape-manifest-x64.xml b/src/inkscape-manifest-x64.xml
new file mode 100644
index 000000000..38526cfe6
--- /dev/null
+++ b/src/inkscape-manifest-x64.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
+<dependency>
+<dependentAssembly>
+<assemblyIdentity type="win32" name="Microsoft.Windows.Common-Controls"
+ version="6.0.0.0" processorArchitecture="amd64"
+ publicKeyToken="6595b64144ccf1df" language="*"/>
+</dependentAssembly>
+</dependency>
+</assembly> \ No newline at end of file
diff --git a/src/inkscape-x64.rc b/src/inkscape-x64.rc
new file mode 100644
index 000000000..ce286c2ca
--- /dev/null
+++ b/src/inkscape-x64.rc
@@ -0,0 +1,30 @@
+
+APPLICATION_ICON ICON DISCARDABLE "../inkscape.ico"
+1 24 DISCARDABLE "./inkscape-manifest-x64.xml"
+
+1 VERSIONINFO
+ FILEVERSION 0,48,0,9
+ PRODUCTVERSION 0,48,0,9
+BEGIN
+ BLOCK "StringFileInfo"
+ BEGIN
+ BLOCK "040901b5"
+ BEGIN
+ VALUE "Comments", "Published under the GNU GPL"
+ VALUE "CompanyName", "inkscape.org"
+ VALUE "FileDescription", "Inkscape"
+ VALUE "FileVersion", "0.48+devel"
+ VALUE "InternalName", "Inkscape"
+ VALUE "LegalCopyright", "© 2014 Inkscape"
+ VALUE "ProductName", "Inkscape"
+ VALUE "ProductVersion", "0.48+devel"
+ END
+ END
+ BLOCK "VarFileInfo"
+ BEGIN
+ VALUE "Translation", 1033, 437
+ END
+END
+
+1000 BITMAP "./show-preview.bmp"
+
diff --git a/src/inkview-manifest-x64.xml b/src/inkview-manifest-x64.xml
new file mode 100644
index 000000000..38526cfe6
--- /dev/null
+++ b/src/inkview-manifest-x64.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
+<dependency>
+<dependentAssembly>
+<assemblyIdentity type="win32" name="Microsoft.Windows.Common-Controls"
+ version="6.0.0.0" processorArchitecture="amd64"
+ publicKeyToken="6595b64144ccf1df" language="*"/>
+</dependentAssembly>
+</dependency>
+</assembly> \ No newline at end of file
diff --git a/src/inkview-x64.rc b/src/inkview-x64.rc
new file mode 100644
index 000000000..2de16060b
--- /dev/null
+++ b/src/inkview-x64.rc
@@ -0,0 +1,29 @@
+
+APPLICATION_ICON ICON DISCARDABLE "../inkscape.ico"
+1 24 DISCARDABLE "./inkview-manifest-x64.xml"
+
+1 VERSIONINFO
+ FILEVERSION 0,48,0,9
+ PRODUCTVERSION 0,48,0,9
+BEGIN
+ BLOCK "StringFileInfo"
+ BEGIN
+ BLOCK "040901b5"
+ BEGIN
+ VALUE "Comments", "Published under the GNU GPL"
+ VALUE "CompanyName", "inkscape.org"
+ VALUE "FileDescription", "Inkview"
+ VALUE "FileVersion", "0.48+devel"
+ VALUE "InternalName", "Inkview"
+ VALUE "LegalCopyright", "© 2014 Inkscape"
+ VALUE "ProductName", "Inkview"
+ VALUE "ProductVersion", "0.48+devel"
+ END
+ END
+ BLOCK "VarFileInfo"
+ BEGIN
+ VALUE "Translation", 1033, 437
+ END
+END
+
+1000 BITMAP "./show-preview.bmp"
diff --git a/src/libdepixelize/kopftracer2011.cpp b/src/libdepixelize/kopftracer2011.cpp
index e2f387c86..bbb73d445 100644
--- a/src/libdepixelize/kopftracer2011.cpp
+++ b/src/libdepixelize/kopftracer2011.cpp
@@ -26,13 +26,15 @@
# include <config.h>
#endif
+
+#include "kopftracer2011.h"
+
// Build fix under Inkscape build tree
#if GLIBMM_DISABLE_DEPRECATED && HAVE_GLIBMM_THREADS_H
#include <glibmm/threads.h>
#endif
#include <algorithm>
-#include "kopftracer2011.h"
#include "priv/colorspace.h"
#include "priv/homogeneoussplines.h"
#include "priv/branchless.h"
diff --git a/src/libdepixelize/kopftracer2011.h b/src/libdepixelize/kopftracer2011.h
index 598f6c79c..c60d0a61a 100644
--- a/src/libdepixelize/kopftracer2011.h
+++ b/src/libdepixelize/kopftracer2011.h
@@ -27,6 +27,7 @@
#include <string>
+#include <glibmm.h>
// Contains exception definitions
#include <glibmm/fileutils.h>
#include <gdkmm/pixbuf.h>
diff --git a/src/live_effects/CMakeLists.txt b/src/live_effects/CMakeLists.txt
index 58bd7a7dc..c7547ded3 100644
--- a/src/live_effects/CMakeLists.txt
+++ b/src/live_effects/CMakeLists.txt
@@ -34,6 +34,7 @@ set(live_effects_SRC
lpe-recursiveskeleton.cpp
lpe-rough-hatches.cpp
lpe-ruler.cpp
+ lpe-simplify.cpp
# lpe-skeleton.cpp
lpe-sketch.cpp
lpe-spiro.cpp
@@ -60,6 +61,7 @@ set(live_effects_SRC
parameter/random.cpp
parameter/text.cpp
paramter/transformedpoint.cpp
+ parameter/togglebutton.cpp
parameter/unit.cpp
parameter/vector.cpp
@@ -102,6 +104,7 @@ set(live_effects_SRC
lpe-recursiveskeleton.h
lpe-rough-hatches.h
lpe-ruler.h
+ lpe-simplify.h
lpe-skeleton.h
lpe-sketch.h
lpe-spiro.h
@@ -128,6 +131,7 @@ set(live_effects_SRC
parameter/powerstrokepointarray.h
parameter/random.h
parameter/text.h
+ parameter/togglebutton.h
parameter/unit.h
parameter/vector.h
diff --git a/src/live_effects/Makefile_insert b/src/live_effects/Makefile_insert
index 5dcd3ee28..922a4a966 100644
--- a/src/live_effects/Makefile_insert
+++ b/src/live_effects/Makefile_insert
@@ -42,6 +42,10 @@ ink_common_sources += \
live_effects/lpe-bspline.h \
live_effects/lpe-lattice.cpp \
live_effects/lpe-lattice.h \
+ live_effects/lpe-lattice2.cpp \
+ live_effects/lpe-lattice2.h \
+ live_effects/lpe-simplify.cpp \
+ live_effects/lpe-simplify.h \
live_effects/lpe-envelope.cpp \
live_effects/lpe-envelope.h \
live_effects/lpe-spiro.cpp \
diff --git a/src/live_effects/effect-enum.h b/src/live_effects/effect-enum.h
index 8295196d5..82ce36225 100644
--- a/src/live_effects/effect-enum.h
+++ b/src/live_effects/effect-enum.h
@@ -28,6 +28,8 @@ enum EffectType {
PERSPECTIVE_PATH,
SPIRO,
LATTICE,
+ LATTICE2,
+ SIMPLIFY,
ENVELOPE,
CONSTRUCT_GRID,
PERP_BISECTOR,
diff --git a/src/live_effects/effect.cpp b/src/live_effects/effect.cpp
index d94f1e242..3c13ee9a9 100644
--- a/src/live_effects/effect.cpp
+++ b/src/live_effects/effect.cpp
@@ -27,6 +27,8 @@
#include "live_effects/lpe-perspective_path.h"
#include "live_effects/lpe-spiro.h"
#include "live_effects/lpe-lattice.h"
+#include "live_effects/lpe-lattice2.h"
+#include "live_effects/lpe-simplify.h"
#include "live_effects/lpe-envelope.h"
#include "live_effects/lpe-constructgrid.h"
#include "live_effects/lpe-perp_bisector.h"
@@ -139,6 +141,9 @@ const Util::EnumData<EffectType> LPETypeData[] = {
{FILL_BETWEEN_MANY, N_("Fill between many"), "fill_between_many"},
{ELLIPSE_5PTS, N_("Ellipse by 5 points"), "ellipse_5pts"},
{BOUNDING_BOX, N_("Bounding Box"), "bounding_box"},
+/* 0.91 */
+ {SIMPLIFY, N_("Simplify"), "simplify"},
+ {LATTICE2, N_("Lattice Deformation 2"), "lattice2"},
};
const Util::EnumDataConverter<EffectType> LPETypeConverter(LPETypeData, sizeof(LPETypeData)/sizeof(*LPETypeData));
@@ -285,9 +290,14 @@ Effect::New(EffectType lpenr, LivePathEffectObject *lpeobj)
break;
case TAPER_STROKE:
neweffect = static_cast<Effect*> ( new LPETaperStroke(lpeobj) );
+ case SIMPLIFY:
+ neweffect = static_cast<Effect*> ( new LPESimplify(lpeobj) );
+ break;
+ case LATTICE2:
+ neweffect = static_cast<Effect*> ( new LPELattice2(lpeobj) );
break;
default:
- g_warning("LivePathEffect::Effect::New called with invalid patheffect type (%d)", lpenr);
+ g_warning("LivePathEffect::Effect::New called with invalid patheffect type (%d)", lpenr);
neweffect = NULL;
break;
}
@@ -564,9 +574,12 @@ Effect::getCanvasIndicators(SPLPEItem const* lpeitem)
{
std::vector<Geom::PathVector> hp_vec;
- if (!SP_IS_SHAPE(lpeitem)) {
-// g_print ("How to handle helperpaths for non-shapes?\n"); // non-shapes are for example SPGroups.
- return hp_vec;
+ // TODO: we can probably optimize this by using a lot more references
+ // rather than copying PathVectors all over the place
+ if (SP_IS_SHAPE(lpeitem) && show_orig_path) {
+ // add original path to helperpaths
+ SPCurve* curve = SP_SHAPE(lpeitem)->getCurve ();
+ hp_vec.push_back(curve->get_pathvector());
}
// add indicators provided by the effect itself
diff --git a/src/live_effects/lpe-bspline.cpp b/src/live_effects/lpe-bspline.cpp
index edf19d1e5..b19b697c0 100644
--- a/src/live_effects/lpe-bspline.cpp
+++ b/src/live_effects/lpe-bspline.cpp
@@ -1,14 +1,27 @@
#define INKSCAPE_LPE_BSPLINE_C
+
/*
* Released under GNU GPL, read the file 'COPYING' for more information
*/
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#if WITH_GLIBMM_2_32
+# include <glibmm/threads.h>
+#endif
+
#include <gtkmm/box.h>
#include <gtkmm/entry.h>
#include <gtkmm/box.h>
#include <gtkmm/button.h>
#include <gtkmm/checkbutton.h>
+
#include <glib.h>
#include <glibmm/i18n.h>
+
+
#include "display/curve.h"
#include <2geom/bezier-curve.h>
#include <2geom/point.h>
@@ -96,7 +109,7 @@ void LPEBSpline::createAndApply(const char *name, SPDocument *doc,
}
void LPEBSpline::doEffect(SPCurve *curve) {
- if (curve->get_segment_count() < 2)
+ if (curve->get_segment_count() < 1)
return;
// Make copy of old path as it is changed during processing
Geom::PathVector const original_pathv = curve->get_pathvector();
@@ -216,10 +229,26 @@ void LPEBSpline::doEffect(SPCurve *curve) {
++curve_it1;
++curve_it2;
}
+ SPCurve *out = new SPCurve();
+ out->moveto(curve_it1->initialPoint());
+ out->lineto(curve_it1->finalPoint());
+ cubic = dynamic_cast<Geom::CubicBezier const *>(&*curve_it1);
+ if (cubic) {
+ SBasisOut = out->first_segment()->toSBasis();
+ nextPointAt1 = SBasisOut.valueAt(Geom::nearest_point((*cubic)[1], *out->first_segment()));
+ nextPointAt2 = SBasisOut.valueAt(Geom::nearest_point((*cubic)[2], *out->first_segment()));
+ nextPointAt3 = out->first_segment()->finalPoint();
+ } else {
+ nextPointAt1 = out->first_segment()->initialPoint();
+ nextPointAt2 = out->first_segment()->finalPoint();
+ nextPointAt3 = out->first_segment()->finalPoint();
+ }
+ out->reset();
+ delete out;
//Si está cerrada la curva, la cerramos sobre el valor guardado
//previamente
//Si no finalizamos en el punto final
- Geom::Point startNode(0, 0);
+ Geom::Point startNode = path_it->begin()->initialPoint();
if (path_it->closed()) {
SPCurve *start = new SPCurve();
start->moveto(path_it->begin()->initialPoint());
@@ -421,7 +450,7 @@ void LPEBSpline::doBSplineFromWidget(SPCurve *curve, double weightValue) {
}
}
//bool hasNodesSelected = LPEBspline::hasNodesSelected();
- if (curve->get_segment_count() < 2)
+ if (curve->get_segment_count() < 1)
return;
// Make copy of old path as it is changed during processing
Geom::PathVector const original_pathv = curve->get_pathvector();
diff --git a/src/live_effects/lpe-lattice.h b/src/live_effects/lpe-lattice.h
index a44dda3fd..5eb48909b 100644
--- a/src/live_effects/lpe-lattice.h
+++ b/src/live_effects/lpe-lattice.h
@@ -58,7 +58,6 @@ private:
PointParam grid_point13;
PointParam grid_point14;
PointParam grid_point15;
-
LPELattice(const LPELattice&);
LPELattice& operator=(const LPELattice&);
};
diff --git a/src/live_effects/lpe-lattice2.cpp b/src/live_effects/lpe-lattice2.cpp
new file mode 100644
index 000000000..db609c9e1
--- /dev/null
+++ b/src/live_effects/lpe-lattice2.cpp
@@ -0,0 +1,496 @@
+/** \file
+ * LPE <lattice2> implementation
+
+ */
+/*
+ * Authors:
+ * Johan Engelen <j.b.c.engelen@utwente.nl>
+ * Steren Giannini
+ * Noé Falzon
+ * Victor Navez
+ * ~suv
+ * Jabiertxo Arraiza
+*
+* Copyright (C) 2007-2008 Authors
+ *
+ * Released under GNU GPL, read the file 'COPYING' for more information
+ */
+
+#include "live_effects/lpe-lattice2.h"
+
+#include "sp-shape.h"
+#include "sp-item.h"
+#include "sp-path.h"
+#include "display/curve.h"
+#include "svg/svg.h"
+
+#include <2geom/sbasis.h>
+#include <2geom/sbasis-2d.h>
+#include <2geom/sbasis-geometric.h>
+#include <2geom/bezier-to-sbasis.h>
+#include <2geom/sbasis-to-bezier.h>
+#include <2geom/d2.h>
+#include <2geom/piecewise.h>
+#include <2geom/transforms.h>
+#include <tools-switch.h>
+
+#include "desktop.h" // TODO: should be factored out (see below)
+
+using namespace Geom;
+
+namespace Inkscape {
+namespace LivePathEffect {
+
+LPELattice2::LPELattice2(LivePathEffectObject *lpeobject) :
+ Effect(lpeobject),
+ // initialise your parameters here:
+ grid_point0(_("Control handle 0:"), _("Control handle 0 - Ctrl+Alt+Click to reset"), "gridpoint0", &wr, this),
+ grid_point1(_("Control handle 1:"), _("Control handle 1 - Ctrl+Alt+Click to reset"), "gridpoint1", &wr, this),
+ grid_point2(_("Control handle 2:"), _("Control handle 2 - Ctrl+Alt+Click to reset"), "gridpoint2", &wr, this),
+ grid_point3(_("Control handle 3:"), _("Control handle 3 - Ctrl+Alt+Click to reset"), "gridpoint3", &wr, this),
+ grid_point4(_("Control handle 4:"), _("Control handle 4 - Ctrl+Alt+Click to reset"), "gridpoint4", &wr, this),
+ grid_point5(_("Control handle 5:"), _("Control handle 5 - Ctrl+Alt+Click to reset"), "gridpoint5", &wr, this),
+ grid_point6(_("Control handle 6:"), _("Control handle 6 - Ctrl+Alt+Click to reset"), "gridpoint6", &wr, this),
+ grid_point7(_("Control handle 7:"), _("Control handle 7 - Ctrl+Alt+Click to reset"), "gridpoint7", &wr, this),
+ grid_point8x9(_("Control handle 8x9:"), _("Control handle 8x9 - Ctrl+Alt+Click to reset"), "gridpoint8x9", &wr, this),
+ grid_point10x11(_("Control handle 10x11:"), _("Control handle 10x11 - Ctrl+Alt+Click to reset"), "gridpoint10x11", &wr, this),
+ grid_point12(_("Control handle 12:"), _("Control handle 12 - Ctrl+Alt+Click to reset"), "gridpoint12", &wr, this),
+ grid_point13(_("Control handle 13:"), _("Control handle 13 - Ctrl+Alt+Click to reset"), "gridpoint13", &wr, this),
+ grid_point14(_("Control handle 14:"), _("Control handle 14 - Ctrl+Alt+Click to reset"), "gridpoint14", &wr, this),
+ grid_point15(_("Control handle 15:"), _("Control handle 15 - Ctrl+Alt+Click to reset"), "gridpoint15", &wr, this),
+ grid_point16(_("Control handle 16:"), _("Control handle 16 - Ctrl+Alt+Click to reset"), "gridpoint16", &wr, this),
+ grid_point17(_("Control handle 17:"), _("Control handle 17 - Ctrl+Alt+Click to reset"), "gridpoint17", &wr, this),
+ grid_point18(_("Control handle 18:"), _("Control handle 18 - Ctrl+Alt+Click to reset"), "gridpoint18", &wr, this),
+ grid_point19(_("Control handle 19:"), _("Control handle 19 - Ctrl+Alt+Click to reset"), "gridpoint19", &wr, this),
+ grid_point20x21(_("Control handle 20x21:"), _("Control handle 20x21 - Ctrl+Alt+Click to reset"), "gridpoint20x21", &wr, this),
+ grid_point22x23(_("Control handle 22x23:"), _("Control handle 22x23 - Ctrl+Alt+Click to reset"), "gridpoint22x23", &wr, this),
+ grid_point24x26(_("Control handle 24x26:"), _("Control handle 24x26 - Ctrl+Alt+Click to reset"), "gridpoint24x26", &wr, this),
+ grid_point25x27(_("Control handle 25x27:"), _("Control handle 25x27 - Ctrl+Alt+Click to reset"), "gridpoint25x27", &wr, this),
+ grid_point28x30(_("Control handle 28x30:"), _("Control handle 28x30 - Ctrl+Alt+Click to reset"), "gridpoint28x30", &wr, this),
+ grid_point29x31(_("Control handle 29x31:"), _("Control handle 29x31 - Ctrl+Alt+Click to reset"), "gridpoint29x31", &wr, this),
+ grid_point32x33x34x35(_("Control handle 32x33x34x35:"), _("Control handle 32x33x34x35 - Ctrl+Alt+Click to reset"), "gridpoint32x33x34x35", &wr, this)
+
+
+{
+ // register all your parameters here, so Inkscape knows which parameters this effect has:
+ registerParameter( dynamic_cast<Parameter *>(&grid_point0) );
+ registerParameter( dynamic_cast<Parameter *>(&grid_point1) );
+ registerParameter( dynamic_cast<Parameter *>(&grid_point2) );
+ registerParameter( dynamic_cast<Parameter *>(&grid_point3) );
+ registerParameter( dynamic_cast<Parameter *>(&grid_point4) );
+ registerParameter( dynamic_cast<Parameter *>(&grid_point5) );
+ registerParameter( dynamic_cast<Parameter *>(&grid_point6) );
+ registerParameter( dynamic_cast<Parameter *>(&grid_point7) );
+ registerParameter( dynamic_cast<Parameter *>(&grid_point8x9) );
+ registerParameter( dynamic_cast<Parameter *>(&grid_point10x11) );
+ registerParameter( dynamic_cast<Parameter *>(&grid_point12) );
+ registerParameter( dynamic_cast<Parameter *>(&grid_point13) );
+ registerParameter( dynamic_cast<Parameter *>(&grid_point14) );
+ registerParameter( dynamic_cast<Parameter *>(&grid_point15) );
+ registerParameter( dynamic_cast<Parameter *>(&grid_point16) );
+ registerParameter( dynamic_cast<Parameter *>(&grid_point17) );
+ registerParameter( dynamic_cast<Parameter *>(&grid_point18) );
+ registerParameter( dynamic_cast<Parameter *>(&grid_point19) );
+ registerParameter( dynamic_cast<Parameter *>(&grid_point20x21) );
+ registerParameter( dynamic_cast<Parameter *>(&grid_point22x23) );
+ registerParameter( dynamic_cast<Parameter *>(&grid_point24x26) );
+ registerParameter( dynamic_cast<Parameter *>(&grid_point25x27) );
+ registerParameter( dynamic_cast<Parameter *>(&grid_point28x30) );
+ registerParameter( dynamic_cast<Parameter *>(&grid_point29x31) );
+ registerParameter( dynamic_cast<Parameter *>(&grid_point32x33x34x35) );
+}
+
+LPELattice2::~LPELattice2()
+{
+}
+
+Geom::Piecewise<Geom::D2<Geom::SBasis> >
+LPELattice2::doEffect_pwd2 (Geom::Piecewise<Geom::D2<Geom::SBasis> > const & pwd2_in)
+{
+ D2<SBasis2d> sb2;
+
+ //Initialisation of the sb2
+ for(unsigned dim = 0; dim < 2; dim++) {
+ sb2[dim].us = 3;
+ sb2[dim].vs = 3;
+ const int depth = sb2[dim].us*sb2[dim].vs;
+ sb2[dim].resize(depth, Linear2d(0));
+ }
+
+ //Grouping the point params in a convenient vector
+ std::vector<Geom::Point *> handles(36);
+
+ handles[0] = &grid_point0;
+ handles[1] = &grid_point1;
+ handles[2] = &grid_point2;
+ handles[3] = &grid_point3;
+ handles[4] = &grid_point4;
+ handles[5] = &grid_point5;
+ handles[6] = &grid_point6;
+ handles[7] = &grid_point7;
+ handles[8] = &grid_point8x9;
+ handles[9] = &grid_point8x9;
+ handles[10] = &grid_point10x11;
+ handles[11] = &grid_point10x11;
+ handles[12] = &grid_point12;
+ handles[13] = &grid_point13;
+ handles[14] = &grid_point14;
+ handles[15] = &grid_point15;
+ handles[16] = &grid_point16;
+ handles[17] = &grid_point17;
+ handles[18] = &grid_point18;
+ handles[19] = &grid_point19;
+ handles[20] = &grid_point20x21;
+ handles[21] = &grid_point20x21;
+ handles[22] = &grid_point22x23;
+ handles[23] = &grid_point22x23;
+ handles[24] = &grid_point24x26;
+ handles[25] = &grid_point25x27;
+ handles[26] = &grid_point24x26;
+ handles[27] = &grid_point25x27;
+ handles[28] = &grid_point28x30;
+ handles[29] = &grid_point29x31;
+ handles[30] = &grid_point28x30;
+ handles[31] = &grid_point29x31;
+ handles[32] = &grid_point32x33x34x35;
+ handles[33] = &grid_point32x33x34x35;
+ handles[34] = &grid_point32x33x34x35;
+ handles[35] = &grid_point32x33x34x35;
+
+ Geom::Point origin = Geom::Point(boundingbox_X.min(),boundingbox_Y.min());
+
+ double width = boundingbox_X.extent();
+ double height = boundingbox_Y.extent();
+
+ //numbering is based on 4 rectangles.16
+ for(unsigned dim = 0; dim < 2; dim++) {
+ Geom::Point dir(0,0);
+ dir[dim] = 1;
+ for(unsigned vi = 0; vi < sb2[dim].vs; vi++) {
+ for(unsigned ui = 0; ui < sb2[dim].us; ui++) {
+ for(unsigned iv = 0; iv < 2; iv++) {
+ for(unsigned iu = 0; iu < 2; iu++) {
+ unsigned corner = iu + 2*iv;
+ unsigned i = ui + vi*sb2[dim].us;
+
+ //This is the offset from the Upperleft point
+ Geom::Point base( (ui + iu*(4-2*ui))*width/4.,
+ (vi + iv*(4-2*vi))*height/4.);
+
+ //Special action for corners
+ if(vi == 0 && ui == 0) {
+ base = Geom::Point(0,0);
+ }
+
+ // i = Upperleft corner of the considerated rectangle
+ // corner = actual corner of the rectangle
+ // origin = Upperleft point
+ double dl = dot((*handles[corner+4*i] - (base + origin)), dir)/dot(dir,dir);
+ sb2[dim][i][corner] = dl/( dim ? height : width )*pow(4.0,ui+vi);
+ }
+ }
+ }
+ }
+ }
+
+ Piecewise<D2<SBasis> > output;
+ output.push_cut(0.);
+ for(unsigned i = 0; i < pwd2_in.size(); i++) {
+ D2<SBasis> B = pwd2_in[i];
+ B[Geom::X] -= origin[Geom::X];
+ B[Geom::X]*= 1/width;
+ B[Geom::Y] -= origin[Geom::Y];
+ B[Geom::Y]*= 1/height;
+ //Here comes the magic
+ D2<SBasis> tB = compose_each(sb2,B);
+ tB[Geom::X] = tB[Geom::X] * width + origin[Geom::X];
+ tB[Geom::Y] = tB[Geom::Y] * height + origin[Geom::Y];
+
+ output.push(tB,i+1);
+ }
+ return output;
+}
+
+Gtk::Widget *
+LPELattice2::newWidget()
+{
+ // use manage here, because after deletion of Effect object, others might still be pointing to this widget.
+ Gtk::VBox * vbox = Gtk::manage( new Gtk::VBox(Effect::newWidget()) );
+
+ vbox->set_border_width(5);
+ Gtk::Button* resetButton = Gtk::manage(new Gtk::Button(Glib::ustring(_("Reset grid"))));
+ resetButton->set_alignment(0.0, 0.5);
+ resetButton->signal_clicked().connect(sigc::mem_fun (*this,&LPELattice2::resetGrid));
+ Gtk::Widget* resetButtonWidget = dynamic_cast<Gtk::Widget *>(resetButton);
+ resetButtonWidget->set_tooltip_text("Reset grid");
+ vbox->pack_start(*resetButtonWidget, true, true,2);
+ std::vector<Parameter *>::iterator it = param_vector.begin();
+ while (it != param_vector.end()) {
+ if ((*it)->widget_is_visible) {
+ Parameter * param = *it;
+ Gtk::Widget * widg = dynamic_cast<Gtk::Widget *>(param->param_newWidget());
+ if(param->param_key == "grid"){
+ widg = NULL;
+ }
+ Glib::ustring * tip = param->param_getTooltip();
+ if (widg) {
+ vbox->pack_start(*widg, true, true, 2);
+ if (tip) {
+ widg->set_tooltip_text(*tip);
+ } else {
+ widg->set_tooltip_text("");
+ widg->set_has_tooltip(false);
+ }
+ }
+ }
+
+ ++it;
+ }
+ return dynamic_cast<Gtk::Widget *>(vbox);
+}
+
+void
+LPELattice2::doBeforeEffect (SPLPEItem const* lpeitem)
+{
+ original_bbox(lpeitem);
+ setDefaults();
+}
+
+void
+LPELattice2::setDefaults()
+{
+ Geom::Point gp0((boundingbox_X.max()-boundingbox_X.min())/4*0+boundingbox_X.min(),
+ (boundingbox_Y.max()-boundingbox_Y.min())/4*0+boundingbox_Y.min());
+
+ Geom::Point gp1((boundingbox_X.max()-boundingbox_X.min())/4*4+boundingbox_X.min(),
+ (boundingbox_Y.max()-boundingbox_Y.min())/4*0+boundingbox_Y.min());
+
+ Geom::Point gp2((boundingbox_X.max()-boundingbox_X.min())/4*0+boundingbox_X.min(),
+ (boundingbox_Y.max()-boundingbox_Y.min())/4*4+boundingbox_Y.min());
+
+ Geom::Point gp3((boundingbox_X.max()-boundingbox_X.min())/4*4+boundingbox_X.min(),
+ (boundingbox_Y.max()-boundingbox_Y.min())/4*4+boundingbox_Y.min());
+
+ Geom::Point gp4((boundingbox_X.max()-boundingbox_X.min())/4*1+boundingbox_X.min(),
+ (boundingbox_Y.max()-boundingbox_Y.min())/4*0+boundingbox_Y.min());
+
+ Geom::Point gp5((boundingbox_X.max()-boundingbox_X.min())/4*3+boundingbox_X.min(),
+ (boundingbox_Y.max()-boundingbox_Y.min())/4*0+boundingbox_Y.min());
+
+ Geom::Point gp6((boundingbox_X.max()-boundingbox_X.min())/4*1+boundingbox_X.min(),
+ (boundingbox_Y.max()-boundingbox_Y.min())/4*4+boundingbox_Y.min());
+
+ Geom::Point gp7((boundingbox_X.max()-boundingbox_X.min())/4*3+boundingbox_X.min(),
+ (boundingbox_Y.max()-boundingbox_Y.min())/4*4+boundingbox_Y.min());
+
+ Geom::Point gp8x9((boundingbox_X.max()-boundingbox_X.min())/4*2+boundingbox_X.min(),
+ (boundingbox_Y.max()-boundingbox_Y.min())/4*0+boundingbox_Y.min());
+
+ Geom::Point gp10x11((boundingbox_X.max()-boundingbox_X.min())/4*2+boundingbox_X.min(),
+ (boundingbox_Y.max()-boundingbox_Y.min())/4*4+boundingbox_Y.min());
+
+ Geom::Point gp12((boundingbox_X.max()-boundingbox_X.min())/4*0+boundingbox_X.min(),
+ (boundingbox_Y.max()-boundingbox_Y.min())/4*1+boundingbox_Y.min());
+
+ Geom::Point gp13((boundingbox_X.max()-boundingbox_X.min())/4*4+boundingbox_X.min(),
+ (boundingbox_Y.max()-boundingbox_Y.min())/4*1+boundingbox_Y.min());
+
+ Geom::Point gp14((boundingbox_X.max()-boundingbox_X.min())/4*0+boundingbox_X.min(),
+ (boundingbox_Y.max()-boundingbox_Y.min())/4*3+boundingbox_Y.min());
+
+ Geom::Point gp15((boundingbox_X.max()-boundingbox_X.min())/4*4+boundingbox_X.min(),
+ (boundingbox_Y.max()-boundingbox_Y.min())/4*3+boundingbox_Y.min());
+
+ Geom::Point gp16((boundingbox_X.max()-boundingbox_X.min())/4*1+boundingbox_X.min(),
+ (boundingbox_Y.max()-boundingbox_Y.min())/4*1+boundingbox_Y.min());
+
+ Geom::Point gp17((boundingbox_X.max()-boundingbox_X.min())/4*3+boundingbox_X.min(),
+ (boundingbox_Y.max()-boundingbox_Y.min())/4*1+boundingbox_Y.min());
+
+ Geom::Point gp18((boundingbox_X.max()-boundingbox_X.min())/4*1+boundingbox_X.min(),
+ (boundingbox_Y.max()-boundingbox_Y.min())/4*3+boundingbox_Y.min());
+
+ Geom::Point gp19((boundingbox_X.max()-boundingbox_X.min())/4*3+boundingbox_X.min(),
+ (boundingbox_Y.max()-boundingbox_Y.min())/4*3+boundingbox_Y.min());
+
+ Geom::Point gp20x21((boundingbox_X.max()-boundingbox_X.min())/4*2+boundingbox_X.min(),
+ (boundingbox_Y.max()-boundingbox_Y.min())/4*1+boundingbox_Y.min());
+
+ Geom::Point gp22x23((boundingbox_X.max()-boundingbox_X.min())/4*2+boundingbox_X.min(),
+ (boundingbox_Y.max()-boundingbox_Y.min())/4*3+boundingbox_Y.min());
+
+ Geom::Point gp24x26((boundingbox_X.max()-boundingbox_X.min())/4*0+boundingbox_X.min(),
+ (boundingbox_Y.max()-boundingbox_Y.min())/4*2+boundingbox_Y.min());
+
+ Geom::Point gp25x27((boundingbox_X.max()-boundingbox_X.min())/4*4+boundingbox_X.min(),
+ (boundingbox_Y.max()-boundingbox_Y.min())/4*2+boundingbox_Y.min());
+
+ Geom::Point gp28x30((boundingbox_X.max()-boundingbox_X.min())/4*1+boundingbox_X.min(),
+ (boundingbox_Y.max()-boundingbox_Y.min())/4*2+boundingbox_Y.min());
+
+ Geom::Point gp29x31((boundingbox_X.max()-boundingbox_X.min())/4*3+boundingbox_X.min(),
+ (boundingbox_Y.max()-boundingbox_Y.min())/4*2+boundingbox_Y.min());
+
+ Geom::Point gp32x33x34x35((boundingbox_X.max()-boundingbox_X.min())/4*2+boundingbox_X.min(),
+ (boundingbox_Y.max()-boundingbox_Y.min())/4*2+boundingbox_Y.min());
+
+ grid_point0.param_update_default(gp0);
+ grid_point1.param_update_default(gp1);
+ grid_point2.param_update_default(gp2);
+ grid_point3.param_update_default(gp3);
+ grid_point4.param_update_default(gp4);
+ grid_point5.param_update_default(gp5);
+ grid_point6.param_update_default(gp6);
+ grid_point7.param_update_default(gp7);
+ grid_point8x9.param_update_default(gp8x9);
+ grid_point10x11.param_update_default(gp10x11);
+ grid_point12.param_update_default(gp12);
+ grid_point13.param_update_default(gp13);
+ grid_point14.param_update_default(gp14);
+ grid_point15.param_update_default(gp15);
+ grid_point16.param_update_default(gp16);
+ grid_point17.param_update_default(gp17);
+ grid_point18.param_update_default(gp18);
+ grid_point19.param_update_default(gp19);
+ grid_point20x21.param_update_default(gp20x21);
+ grid_point22x23.param_update_default(gp22x23);
+ grid_point24x26.param_update_default(gp24x26);
+ grid_point25x27.param_update_default(gp25x27);
+ grid_point28x30.param_update_default(gp28x30);
+ grid_point29x31.param_update_default(gp29x31);
+ grid_point32x33x34x35.param_update_default(gp32x33x34x35);
+}
+
+void
+LPELattice2::resetGrid()
+{
+ grid_point0.param_set_and_write_default();
+ grid_point1.param_set_and_write_default();
+ grid_point2.param_set_and_write_default();
+ grid_point3.param_set_and_write_default();
+ grid_point4.param_set_and_write_default();
+ grid_point5.param_set_and_write_default();
+ grid_point6.param_set_and_write_default();
+ grid_point7.param_set_and_write_default();
+ grid_point8x9.param_set_and_write_default();
+ grid_point10x11.param_set_and_write_default();
+ grid_point12.param_set_and_write_default();
+ grid_point13.param_set_and_write_default();
+ grid_point14.param_set_and_write_default();
+ grid_point15.param_set_and_write_default();
+ grid_point16.param_set_and_write_default();
+ grid_point17.param_set_and_write_default();
+ grid_point18.param_set_and_write_default();
+ grid_point19.param_set_and_write_default();
+ grid_point20x21.param_set_and_write_default();
+ grid_point22x23.param_set_and_write_default();
+ grid_point24x26.param_set_and_write_default();
+ grid_point25x27.param_set_and_write_default();
+ grid_point28x30.param_set_and_write_default();
+ grid_point29x31.param_set_and_write_default();
+ grid_point32x33x34x35.param_set_and_write_default();
+ //todo:this hack is only to reposition the knots on reser grid button
+ //Better update path effect in LPEITEM
+ SPDesktop * desktop = inkscape_active_desktop();
+ tools_switch(desktop, TOOLS_SELECT);
+ tools_switch(desktop, TOOLS_NODES);
+}
+
+void
+LPELattice2::resetDefaults(SPItem const* item)
+{
+ Effect::resetDefaults(item);
+ original_bbox(SP_LPE_ITEM(item));
+ setDefaults();
+ resetGrid();
+}
+
+void
+LPELattice2::calculateCurve(Geom::Point a,Geom::Point b, SPCurve* c, bool horizontal, bool move)
+{
+ using Geom::X;
+ using Geom::Y;
+ if(move) c->moveto(a);
+ Geom::Point cubic1 = a + (1./3)* (b - a);
+ Geom::Point cubic2 = b + (1./3)* (a - b);
+ if(horizontal) c->curveto(Geom::Point(cubic1[X],a[Y]),Geom::Point(cubic2[X],b[Y]),b);
+ else c->curveto(Geom::Point(a[X],cubic1[Y]),Geom::Point(b[X],cubic2[Y]),b);
+}
+
+void
+LPELattice2::addCanvasIndicators(SPLPEItem const */*lpeitem*/, std::vector<Geom::PathVector> &hp_vec)
+{
+ hp_vec.clear();
+
+ SPCurve *c = new SPCurve();
+ calculateCurve(grid_point0,grid_point4, c,true, true);
+ calculateCurve(grid_point4,grid_point8x9, c,true, false);
+ calculateCurve(grid_point8x9,grid_point5, c,true, false);
+ calculateCurve(grid_point5,grid_point1, c,true, false);
+
+ calculateCurve(grid_point12,grid_point16, c,true, true);
+ calculateCurve(grid_point16,grid_point20x21, c,true, false);
+ calculateCurve(grid_point20x21,grid_point17, c,true, false);
+ calculateCurve(grid_point17,grid_point13, c,true, false);
+
+ calculateCurve(grid_point24x26,grid_point28x30, c,true, true);
+ calculateCurve(grid_point28x30,grid_point32x33x34x35, c,true, false);
+ calculateCurve(grid_point32x33x34x35,grid_point29x31, c,true, false);
+ calculateCurve(grid_point29x31,grid_point25x27, c,true, false);
+
+ calculateCurve(grid_point14,grid_point18, c,true, true);
+ calculateCurve(grid_point18,grid_point22x23, c,true, false);
+ calculateCurve(grid_point22x23,grid_point19, c,true, false);
+ calculateCurve(grid_point19,grid_point15, c,true, false);
+
+ calculateCurve(grid_point2,grid_point6, c,true, true);
+ calculateCurve(grid_point6,grid_point10x11, c,true, false);
+ calculateCurve(grid_point10x11,grid_point7, c,true, false);
+ calculateCurve(grid_point7,grid_point3, c,true, false);
+
+ calculateCurve(grid_point0,grid_point12, c,false, true);
+ calculateCurve(grid_point12,grid_point24x26, c,false, false);
+ calculateCurve(grid_point24x26,grid_point14, c,false, false);
+ calculateCurve(grid_point14,grid_point2, c,false, false);
+
+ calculateCurve(grid_point4,grid_point16, c,false, true);
+ calculateCurve(grid_point16,grid_point28x30, c,false, false);
+ calculateCurve(grid_point28x30,grid_point18, c,false, false);
+ calculateCurve(grid_point18,grid_point6, c,false, false);
+
+ calculateCurve(grid_point8x9,grid_point20x21, c,false, true);
+ calculateCurve(grid_point20x21,grid_point32x33x34x35, c,false, false);
+ calculateCurve(grid_point32x33x34x35,grid_point22x23, c,false, false);
+ calculateCurve(grid_point22x23,grid_point10x11, c,false, false);
+
+ calculateCurve(grid_point5,grid_point17, c, false, true);
+ calculateCurve(grid_point17,grid_point29x31, c,false, false);
+ calculateCurve(grid_point29x31,grid_point19, c,false, false);
+ calculateCurve(grid_point19,grid_point7, c,false, false);
+
+ calculateCurve(grid_point1,grid_point13, c, false, true);
+ calculateCurve(grid_point13,grid_point25x27, c,false, false);
+ calculateCurve(grid_point25x27,grid_point15, c,false, false);
+ calculateCurve(grid_point15,grid_point3, c, false, false);
+ hp_vec.push_back(c->get_pathvector());
+}
+
+
+/* ######################## */
+
+} //namespace LivePathEffect
+} /* namespace Inkscape */
+
+
+
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :
diff --git a/src/live_effects/lpe-lattice2.h b/src/live_effects/lpe-lattice2.h
new file mode 100644
index 000000000..461f835c6
--- /dev/null
+++ b/src/live_effects/lpe-lattice2.h
@@ -0,0 +1,92 @@
+#ifndef INKSCAPE_LPE_LATTICE2_H
+#define INKSCAPE_LPE_LATTICE2_H
+
+/** \file
+ * LPE <lattice2> implementation, see lpe-lattice2.cpp.
+ */
+
+/*
+ * Authors:
+ * Johan Engelen
+ * Steren Giannini
+ * Noé Falzon
+ * Victor Navez
+ * ~suv
+ * Jabiertxo Arraiza
+*
+* Copyright (C) Johan Engelen 2007 <j.b.c.engelen@utwente.nl>
+ *
+ * Released under GNU GPL, read the file 'COPYING' for more information
+ */
+
+#include "live_effects/parameter/enum.h"
+#include "live_effects/effect.h"
+#include "live_effects/parameter/pointreseteable.h"
+#include "live_effects/lpegroupbbox.h"
+
+namespace Inkscape {
+namespace LivePathEffect {
+
+class LPELattice2 : public Effect, GroupBBoxEffect {
+public:
+
+ LPELattice2(LivePathEffectObject *lpeobject);
+ virtual ~LPELattice2();
+
+ virtual Geom::Piecewise<Geom::D2<Geom::SBasis> > doEffect_pwd2 (Geom::Piecewise<Geom::D2<Geom::SBasis> > const & pwd2_in);
+
+ virtual void resetDefaults(SPItem const* item);
+
+ virtual void doBeforeEffect(SPLPEItem const* lpeitem);
+
+ virtual Gtk::Widget * newWidget();
+
+ virtual void calculateCurve(Geom::Point a,Geom::Point b, SPCurve *c, bool horizontal, bool move);
+
+ virtual void setDefaults();
+
+ virtual void resetGrid();
+
+ //virtual void original_bbox(SPLPEItem const* lpeitem, bool absolute = false);
+
+ //virtual void addCanvasIndicators(SPLPEItem const*/*lpeitem*/, std::vector<Geom::PathVector> &/*hp_vec*/);
+
+ //virtual std::vector<Geom::PathVector> getHelperPaths(SPLPEItem const* lpeitem);
+protected:
+ void addCanvasIndicators(SPLPEItem const */*lpeitem*/, std::vector<Geom::PathVector> &hp_vec);
+private:
+
+ PointReseteableParam grid_point0;
+ PointReseteableParam grid_point1;
+ PointReseteableParam grid_point2;
+ PointReseteableParam grid_point3;
+ PointReseteableParam grid_point4;
+ PointReseteableParam grid_point5;
+ PointReseteableParam grid_point6;
+ PointReseteableParam grid_point7;
+ PointReseteableParam grid_point8x9;
+ PointReseteableParam grid_point10x11;
+ PointReseteableParam grid_point12;
+ PointReseteableParam grid_point13;
+ PointReseteableParam grid_point14;
+ PointReseteableParam grid_point15;
+ PointReseteableParam grid_point16;
+ PointReseteableParam grid_point17;
+ PointReseteableParam grid_point18;
+ PointReseteableParam grid_point19;
+ PointReseteableParam grid_point20x21;
+ PointReseteableParam grid_point22x23;
+ PointReseteableParam grid_point24x26;
+ PointReseteableParam grid_point25x27;
+ PointReseteableParam grid_point28x30;
+ PointReseteableParam grid_point29x31;
+ PointReseteableParam grid_point32x33x34x35;
+
+ LPELattice2(const LPELattice2&);
+ LPELattice2& operator=(const LPELattice2&);
+};
+
+} //namespace LivePathEffect
+} //namespace Inkscape
+
+#endif
diff --git a/src/live_effects/lpe-simplify.cpp b/src/live_effects/lpe-simplify.cpp
new file mode 100644
index 000000000..d010e75a2
--- /dev/null
+++ b/src/live_effects/lpe-simplify.cpp
@@ -0,0 +1,287 @@
+#define INKSCAPE_LPE_SIMPLIFY_C
+/*
+ * Released under GNU GPL, read the file 'COPYING' for more information
+ */
+#include <gtkmm/box.h>
+#include <gtkmm/entry.h>
+#include "live_effects/lpe-simplify.h"
+#include "display/curve.h"
+#include "live_effects/parameter/parameter.h"
+#include <glibmm/i18n.h>
+#include "helper/geom.h"
+#include "livarot/Path.h"
+#include "splivarot.h"
+#include <2geom/svg-path-parser.h>
+#include "desktop.h"
+#include "inkscape.h"
+#include "svg/svg.h"
+#include "ui/tools/node-tool.h"
+#include <2geom/d2.h>
+#include <2geom/generic-rect.h>
+#include <2geom/interval.h>
+
+
+namespace Inkscape {
+namespace LivePathEffect {
+
+LPESimplify::LPESimplify(LivePathEffectObject *lpeobject)
+ : Effect(lpeobject),
+ steps(_("Steps:"),_("Change number of simplify steps "), "steps", &wr, this,1),
+ threshold(_("Roughly threshold:"), _("Roughly threshold:"), "threshold", &wr, this, 0.003),
+ helper_size(_("Helper size:"), _("Helper size"), "helper_size", &wr, this, 2.),
+ nodes(_("Helper nodes"), _("Show helper nodes"), "nodes", &wr, this, false),
+ handles(_("Helper handles"), _("Show helper handles"), "handles", &wr, this, false),
+ simplifyindividualpaths(_("Paths separately"), _("Simplifying paths (separately)"), "simplifyindividualpaths", &wr, this, false),
+ simplifyJustCoalesce(_("Just coalesce"), _("Simplify just coalesce"), "simplifyJustCoalesce", &wr, this, false)
+ {
+ registerParameter(dynamic_cast<Parameter *>(&steps));
+ registerParameter(dynamic_cast<Parameter *>(&threshold));
+ registerParameter(dynamic_cast<Parameter *>(&helper_size));
+ registerParameter(dynamic_cast<Parameter *>(&nodes));
+ registerParameter(dynamic_cast<Parameter *>(&handles));
+ registerParameter(dynamic_cast<Parameter *>(&simplifyindividualpaths));
+ registerParameter(dynamic_cast<Parameter *>(&simplifyJustCoalesce));
+ threshold.param_set_range(0., Geom::infinity());
+ threshold.param_set_increments(0.0001, 0.0001);
+ threshold.param_set_digits(6);
+ steps.param_set_range(0, 100);
+ steps.param_set_increments(1, 1);
+ steps.param_set_digits(0);
+ helper_size.param_set_range(0.1, 100);
+ helper_size.param_set_increments(1, 1);
+ helper_size.param_set_digits(1);
+}
+
+LPESimplify::~LPESimplify() {}
+
+void
+LPESimplify::doBeforeEffect (SPLPEItem const* lpeitem)
+{
+ if(!hp.empty()){
+ hp.clear();
+ }
+ bbox = SP_ITEM(lpeitem)->visualBounds();
+
+}
+
+Gtk::Widget *
+LPESimplify::newWidget()
+{
+ // use manage here, because after deletion of Effect object, others might still be pointing to this widget.
+ Gtk::VBox * vbox = Gtk::manage( new Gtk::VBox(Effect::newWidget()) );
+ vbox->set_border_width(5);
+ vbox->set_homogeneous(false);
+ vbox->set_spacing(2);
+ std::vector<Parameter *>::iterator it = param_vector.begin();
+ Gtk::HBox * buttons = Gtk::manage(new Gtk::HBox(true,0));
+ Gtk::HBox * buttonsTwo = Gtk::manage(new Gtk::HBox(true,0));
+ while (it != param_vector.end()) {
+ if ((*it)->widget_is_visible) {
+ Parameter * param = *it;
+ Gtk::Widget * widg = dynamic_cast<Gtk::Widget *>(param->param_newWidget());
+ if (param->param_key == "simplifyindividualpaths" ||
+ param->param_key == "simplifyJustCoalesce")
+ {
+ Glib::ustring * tip = param->param_getTooltip();
+ if (widg) {
+ buttonsTwo->pack_start(*widg, true, true, 2);
+ if (tip) {
+ widg->set_tooltip_text(*tip);
+ } else {
+ widg->set_tooltip_text("");
+ widg->set_has_tooltip(false);
+ }
+ }
+ } else if (param->param_key == "nodes" ||
+ param->param_key == "handles")
+ {
+ Glib::ustring * tip = param->param_getTooltip();
+ if (widg) {
+ buttons->pack_start(*widg, true, true, 2);
+ if (tip) {
+ widg->set_tooltip_text(*tip);
+ } else {
+ widg->set_tooltip_text("");
+ widg->set_has_tooltip(false);
+ }
+ }
+ }else{
+ Glib::ustring * tip = param->param_getTooltip();
+ if (widg) {
+ Gtk::HBox * scalarParameter = dynamic_cast<Gtk::HBox *>(widg);
+ std::vector< Gtk::Widget* > childList = scalarParameter->get_children();
+ Gtk::Entry* entryWidg = dynamic_cast<Gtk::Entry *>(childList[1]);
+ entryWidg->set_width_chars(8);
+ vbox->pack_start(*widg, true, true, 2);
+ if (tip) {
+ widg->set_tooltip_text(*tip);
+ } else {
+ widg->set_tooltip_text("");
+ widg->set_has_tooltip(false);
+ }
+ }
+ }
+ }
+
+ ++it;
+ }
+ vbox->pack_start(*buttons,true, true, 2);
+ vbox->pack_start(*buttonsTwo,true, true, 2);
+ return dynamic_cast<Gtk::Widget *>(vbox);
+}
+
+void
+LPESimplify::doEffect(SPCurve *curve) {
+ Geom::PathVector const original_pathv = pathv_to_linear_and_cubic_beziers(curve->get_pathvector());
+ gdouble size = Geom::L2(bbox->dimensions());
+ //size /= Geom::Affine(0,0,0,0,0,0).descrim();
+ Path* pathliv = Path_for_pathvector(original_pathv);
+ if(simplifyindividualpaths){
+ size = Geom::L2(Geom::bounds_fast(original_pathv)->dimensions());
+ }
+ for (int unsigned i = 0; i < steps; i++){
+ if ( simplifyJustCoalesce ) {
+ pathliv->Coalesce(threshold * size);
+ }else{
+ pathliv->ConvertEvenLines(threshold * size);
+ pathliv->Simplify(threshold * size);
+ }
+ }
+ Geom::PathVector outres = Geom::parse_svg_path(pathliv->svg_dump_path());
+ generateHelperPath(outres);
+ curve->set_pathvector(outres);
+ if(SP_ACTIVE_DESKTOP && INK_IS_NODE_TOOL(SP_ACTIVE_DESKTOP->event_context)){
+ SPDesktop* desktop = SP_ACTIVE_DESKTOP;
+ Inkscape::UI::Tools::NodeTool *nt = static_cast<Inkscape::UI::Tools::NodeTool*>(desktop->event_context);
+ nt->update_helperpath();
+ }
+}
+
+void
+LPESimplify::generateHelperPath(Geom::PathVector result)
+{
+ if(!handles && !nodes){
+ return;
+ }
+
+ if(steps < 1){
+ return;
+ }
+
+ Geom::CubicBezier const *cubic = NULL;
+ for (Geom::PathVector::iterator path_it = result.begin(); path_it != result.end(); ++path_it) {
+ //Si está vacío...
+ if (path_it->empty()){
+ continue;
+ }
+ //Itreadores
+ Geom::Path::const_iterator curve_it1 = path_it->begin(); // incoming curve
+ Geom::Path::const_iterator curve_it2 =
+ ++(path_it->begin()); // outgoing curve
+ Geom::Path::const_iterator curve_endit =
+ path_it->end_default(); // this determines when the loop has to stop
+
+ if (path_it->closed()) {
+ // if the path is closed, maybe we have to stop a bit earlier because the
+ // closing line segment has zerolength.
+ const Geom::Curve &closingline =
+ path_it->back_closed(); // the closing line segment is always of type
+ // Geom::LineSegment.
+ if (are_near(closingline.initialPoint(), closingline.finalPoint())) {
+ // closingline.isDegenerate() did not work, because it only checks for
+ // *exact* zero length, which goes wrong for relative coordinates and
+ // rounding errors...
+ // the closing line segment has zero-length. So stop before that one!
+ curve_endit = path_it->end_open();
+ }
+ }
+ if(nodes){
+ drawNode(curve_it1->initialPoint());
+ }
+ while (curve_it2 != curve_endit) {
+ cubic = dynamic_cast<Geom::CubicBezier const *>(&*curve_it1);
+ if (cubic) {
+ if(handles){
+ drawHandle((*cubic)[1]);
+ drawHandle((*cubic)[2]);
+ drawHandleLine((*cubic)[0],(*cubic)[1]);
+ drawHandleLine((*cubic)[2],(*cubic)[3]);
+ }
+ }
+ if(nodes){
+ drawNode(curve_it1->finalPoint());
+ }
+ ++curve_it1;
+ ++curve_it2;
+ }
+ cubic = dynamic_cast<Geom::CubicBezier const *>(&*curve_it1);
+ if (cubic) {
+ if(handles){
+ drawHandle((*cubic)[1]);
+ drawHandle((*cubic)[2]);
+ drawHandleLine((*cubic)[0],(*cubic)[1]);
+ drawHandleLine((*cubic)[2],(*cubic)[3]);
+ }
+ }
+ if(nodes){
+ drawNode(curve_it1->finalPoint());
+ }
+ }
+}
+
+void
+LPESimplify::drawNode(Geom::Point p)
+{
+ double r = helper_size/0.67;
+ char const * svgd;
+ svgd = "M 0.999993,0.5 C 1.000065,0.7757576 0.7761859,1 0.4999926,1 0.2237994,1 -7.933901e-5,0.7757576 -7.339015e-6,0.5 -7.933901e-5,0.2242424 0.2237994,0 0.4999926,0 0.7761859,0 1.000065,0.2242424 0.999993,0.5 Z m -0.058561,0 C 0.9414949,0.74327 0.7438375,0.9416286 0.4999928,0.9416286 0.2561481,0.9416286 0.0584908,0.74327 0.0585543,0.5 0.0584908,0.25673 0.2561481,0.0583714 0.4999928,0.0583714 0.7438375,0.0583714 0.9414949,0.25673 0.9414313,0.5 Z m -0.3828447,0 c 8.5e-6,0.030303 -0.026228,0.060606 -0.058593,0.060606 -0.032366,0 -0.058603,-0.030303 -0.058593,-0.060606 -8.5e-6,-0.030303 0.026227,-0.060606 0.058593,-0.060606 0.032366,0 0.058603,0.030303 0.058593,0.060606 z";
+ Geom::PathVector pathv = sp_svg_read_pathv(svgd);
+ pathv *= Geom::Affine(r,0,0,r,0,0);
+ pathv += p - Geom::Point(0.5*r,0.5*r);
+ hp.push_back(pathv[0]);
+ hp.push_back(pathv[1]);
+ hp.push_back(pathv[2]);
+}
+
+void
+LPESimplify::drawHandle(Geom::Point p)
+{
+ double r = helper_size/0.67;
+ char const * svgd;
+ svgd = "M 0.6999623,0.35 C 0.7000128,0.5430303 0.5433044,0.7 0.3499775,0.7 0.1566506,0.7 -5.778776e-5,0.5430303 -7.344202e-6,0.35 -5.778776e-5,0.1569697 0.1566506,0 0.3499775,0 0.5433044,0 0.7000128,0.1569697 0.6999623,0.35 Z";
+ Geom::PathVector pathv = sp_svg_read_pathv(svgd);
+ pathv *= Geom::Affine(r,0,0,r,0,0);
+ pathv += p - Geom::Point(0.35*r,0.35*r);
+ hp.push_back(pathv[0]);
+}
+
+
+void
+LPESimplify::drawHandleLine(Geom::Point p,Geom::Point p2)
+{
+ Geom::Path path;
+ path.start( p );
+ path.appendNew<Geom::LineSegment>( p2 );
+ hp.push_back(path);
+}
+
+void
+LPESimplify::addCanvasIndicators(SPLPEItem const */*lpeitem*/, std::vector<Geom::PathVector> &hp_vec)
+{
+ hp_vec.push_back(hp);
+}
+
+
+}; //namespace LivePathEffect
+}; /* namespace Inkscape */
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :
diff --git a/src/live_effects/lpe-simplify.h b/src/live_effects/lpe-simplify.h
new file mode 100644
index 000000000..6acf2f2d4
--- /dev/null
+++ b/src/live_effects/lpe-simplify.h
@@ -0,0 +1,59 @@
+#ifndef INKSCAPE_LPE_SIMPLIFY_H
+#define INKSCAPE_LPE_SIMPLIFY_H
+
+/*
+ * Inkscape::LPESimplify
+ *
+ * Released under GNU GPL, read the file 'COPYING' for more information
+ */
+
+#include "live_effects/effect.h"
+#include "live_effects/parameter/togglebutton.h"
+#include "live_effects/lpegroupbbox.h"
+
+namespace Inkscape {
+namespace LivePathEffect {
+
+class LPESimplify : public Effect , GroupBBoxEffect{
+
+public:
+ LPESimplify(LivePathEffectObject *lpeobject);
+ virtual ~LPESimplify();
+
+ virtual void doEffect(SPCurve *curve);
+
+ virtual void doBeforeEffect (SPLPEItem const* lpeitem);
+
+ virtual void generateHelperPath(Geom::PathVector result);
+
+ virtual Gtk::Widget * newWidget();
+
+ virtual void drawNode(Geom::Point p);
+
+ virtual void drawHandle(Geom::Point p);
+
+ virtual void drawHandleLine(Geom::Point p,Geom::Point p2);
+
+protected:
+ void addCanvasIndicators(SPLPEItem const */*lpeitem*/, std::vector<Geom::PathVector> &hp_vec);
+
+private:
+ ScalarParam steps;
+ ScalarParam threshold;
+ ScalarParam helper_size;
+ ToggleButtonParam nodes;
+ ToggleButtonParam handles;
+ ToggleButtonParam simplifyindividualpaths;
+ ToggleButtonParam simplifyJustCoalesce;
+
+ Geom::PathVector hp;
+ Geom::OptRect bbox;
+
+ LPESimplify(const LPESimplify &);
+ LPESimplify &operator=(const LPESimplify &);
+
+};
+
+}; //namespace LivePathEffect
+}; //namespace Inkscape
+#endif
diff --git a/src/live_effects/lpe-vonkoch.cpp b/src/live_effects/lpe-vonkoch.cpp
index c0050fa60..8b0b716fe 100644
--- a/src/live_effects/lpe-vonkoch.cpp
+++ b/src/live_effects/lpe-vonkoch.cpp
@@ -4,11 +4,10 @@
* Released under GNU GPL, read the file 'COPYING' for more information
*/
-#include <cstdio>
+#include "live_effects/lpe-vonkoch.h"
#include <glibmm/i18n.h>
-#include "live_effects/lpe-vonkoch.h"
#include <2geom/transforms.h>
//using std::vector;
diff --git a/src/live_effects/parameter/Makefile_insert b/src/live_effects/parameter/Makefile_insert
index 37cc3dc62..330035ad6 100644
--- a/src/live_effects/parameter/Makefile_insert
+++ b/src/live_effects/parameter/Makefile_insert
@@ -11,6 +11,8 @@ ink_common_sources += \
live_effects/parameter/random.h \
live_effects/parameter/point.cpp \
live_effects/parameter/point.h \
+ live_effects/parameter/pointreseteable.cpp \
+ live_effects/parameter/pointreseteable.h \
live_effects/parameter/enum.h \
live_effects/parameter/path-reference.cpp \
live_effects/parameter/path-reference.h \
@@ -26,6 +28,8 @@ ink_common_sources += \
live_effects/parameter/text.h \
live_effects/parameter/transformedpoint.cpp \
live_effects/parameter/transformedpoint.h \
+ live_effects/parameter/togglebutton.cpp \
+ live_effects/parameter/togglebutton.h \
live_effects/parameter/unit.cpp \
live_effects/parameter/unit.h \
live_effects/parameter/vector.cpp \
diff --git a/src/live_effects/parameter/pointreseteable.cpp b/src/live_effects/parameter/pointreseteable.cpp
new file mode 100644
index 000000000..ec36fc035
--- /dev/null
+++ b/src/live_effects/parameter/pointreseteable.cpp
@@ -0,0 +1,210 @@
+/*
+ * Copyright (C) Johan Engelen 2007 <j.b.c.engelen@utwente.nl>
+ *
+ * Released under GNU GPL, read the file 'COPYING' for more information
+ */
+
+#include "ui/widget/registered-widget.h"
+#include "live_effects/parameter/pointreseteable.h"
+#include "live_effects/effect.h"
+#include "svg/svg.h"
+#include "svg/stringstream.h"
+#include "ui/widget/point.h"
+#include "widgets/icon.h"
+#include "inkscape.h"
+#include "verbs.h"
+#include "knotholder.h"
+#include <glibmm/i18n.h>
+#include "tools-switch.h"
+#include "ui/tools/node-tool.h"
+
+// needed for on-canvas editting:
+#include "desktop.h"
+
+namespace Inkscape {
+
+namespace LivePathEffect {
+
+PointReseteableParam::PointReseteableParam( const Glib::ustring& label, const Glib::ustring& tip,
+ const Glib::ustring& key, Inkscape::UI::Widget::Registry* wr,
+ Effect* effect, const gchar *htip, Geom::Point default_value)
+ : Geom::Point(default_value), Parameter(label, tip, key, wr, effect), defvalue(default_value)
+{
+ knot_shape = SP_KNOT_SHAPE_DIAMOND;
+ knot_mode = SP_KNOT_MODE_XOR;
+ knot_color = 0xffffff00;
+ handle_tip = g_strdup(htip);
+}
+
+PointReseteableParam::~PointReseteableParam()
+{
+ if (handle_tip)
+ g_free(handle_tip);
+}
+
+void
+PointReseteableParam::param_set_default()
+{
+ param_setValue(defvalue);
+}
+
+void
+PointReseteableParam::param_set_and_write_default()
+{
+ param_set_and_write_new_value(defvalue);
+}
+
+void
+PointReseteableParam::param_update_default(Geom::Point newpoint)
+{
+ this->defvalue = newpoint;
+}
+
+bool
+PointReseteableParam::param_readSVGValue(const gchar * strvalue)
+{
+ gchar ** strarray = g_strsplit(strvalue, ",", 2);
+ double newx, newy;
+ unsigned int success = sp_svg_number_read_d(strarray[0], &newx);
+ success += sp_svg_number_read_d(strarray[1], &newy);
+ g_strfreev (strarray);
+ if (success == 2) {
+ param_setValue( Geom::Point(newx, newy) );
+ return true;
+ }
+ return false;
+}
+
+gchar *
+PointReseteableParam::param_getSVGValue() const
+{
+ Inkscape::SVGOStringStream os;
+ os << *dynamic_cast<Geom::Point const *>( this );
+ gchar * str = g_strdup(os.str().c_str());
+ return str;
+}
+
+Gtk::Widget *
+PointReseteableParam::param_newWidget()
+{
+ Inkscape::UI::Widget::RegisteredTransformedPoint * pointwdg = Gtk::manage(
+ new Inkscape::UI::Widget::RegisteredTransformedPoint( param_label,
+ param_tooltip,
+ param_key,
+ *param_wr,
+ param_effect->getRepr(),
+ param_effect->getSPDoc() ) );
+ // TODO: fix to get correct desktop (don't use SP_ACTIVE_DESKTOP)
+ SPDesktop *desktop = SP_ACTIVE_DESKTOP;
+ Geom::Affine transf = desktop->doc2dt();
+ pointwdg->setTransform(transf);
+ pointwdg->setValue( *this );
+ pointwdg->clearProgrammatically();
+ pointwdg->set_undo_parameters(SP_VERB_DIALOG_LIVE_PATH_EFFECT, _("Change point parameter"));
+
+ Gtk::HBox * hbox = Gtk::manage( new Gtk::HBox() );
+ static_cast<Gtk::HBox*>(hbox)->pack_start(*pointwdg, true, true);
+ static_cast<Gtk::HBox*>(hbox)->show_all_children();
+
+ return dynamic_cast<Gtk::Widget *> (hbox);
+}
+
+void
+PointReseteableParam::param_setValue(Geom::Point newpoint)
+{
+ *dynamic_cast<Geom::Point *>( this ) = newpoint;
+ if(SP_ACTIVE_DESKTOP){
+ SPDesktop* desktop = SP_ACTIVE_DESKTOP;
+ if (tools_isactive( desktop, TOOLS_NODES)) {
+ Inkscape::UI::Tools::NodeTool *nt = static_cast<Inkscape::UI::Tools::NodeTool*>( desktop->event_context);
+ nt->update_helperpath();
+ }
+ }
+}
+
+void
+PointReseteableParam::param_set_and_write_new_value (Geom::Point newpoint)
+{
+ Inkscape::SVGOStringStream os;
+ os << newpoint;
+ gchar * str = g_strdup(os.str().c_str());
+ param_write_to_repr(str);
+ g_free(str);
+}
+
+void
+PointReseteableParam::param_transform_multiply(Geom::Affine const& postmul, bool /*set*/)
+{
+ param_set_and_write_new_value( (*this) * postmul );
+}
+
+
+void
+PointReseteableParam::set_oncanvas_looks(SPKnotShapeType shape, SPKnotModeType mode, guint32 color)
+{
+ knot_shape = shape;
+ knot_mode = mode;
+ knot_color = color;
+}
+
+class PointReseteableParamKnotHolderEntity : public KnotHolderEntity {
+public:
+ PointReseteableParamKnotHolderEntity(PointReseteableParam *p) { this->pparam = p; }
+ virtual ~PointReseteableParamKnotHolderEntity() {}
+
+ virtual void knot_set(Geom::Point const &p, Geom::Point const &origin, guint state);
+ virtual Geom::Point knot_get() const;
+ virtual void knot_click(guint state);
+
+private:
+ PointReseteableParam *pparam;
+};
+
+void
+PointReseteableParamKnotHolderEntity::knot_set(Geom::Point const &p, Geom::Point const &/*origin*/, guint state)
+{
+ Geom::Point const s = snap_knot_position(p, state);
+ pparam->param_setValue(s);
+ sp_lpe_item_update_patheffect(SP_LPE_ITEM(item), false, false);
+}
+
+Geom::Point
+PointReseteableParamKnotHolderEntity::knot_get() const
+{
+ return *pparam;
+}
+
+void
+PointReseteableParamKnotHolderEntity::knot_click(guint state)
+{
+ if (state & GDK_CONTROL_MASK) {
+ if (state & GDK_MOD1_MASK) {
+ this->pparam->param_set_default();
+ sp_lpe_item_update_patheffect(SP_LPE_ITEM(item), false, false);
+ }
+ }
+}
+
+void
+PointReseteableParam::addKnotHolderEntities(KnotHolder *knotholder, SPDesktop *desktop, SPItem *item)
+{
+ PointReseteableParamKnotHolderEntity *e = new PointReseteableParamKnotHolderEntity(this);
+ // TODO: can we ditch handleTip() etc. because we have access to handle_tip etc. itself???
+ e->create(desktop, item, knotholder, Inkscape::CTRL_TYPE_UNKNOWN, handleTip(), knot_shape, knot_mode, knot_color);
+ knotholder->add(e);
+}
+
+} /* namespace LivePathEffect */
+
+} /* namespace Inkscape */
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :
diff --git a/src/live_effects/parameter/pointreseteable.h b/src/live_effects/parameter/pointreseteable.h
new file mode 100644
index 000000000..5ae1fdf02
--- /dev/null
+++ b/src/live_effects/parameter/pointreseteable.h
@@ -0,0 +1,74 @@
+#ifndef INKSCAPE_LIVEPATHEFFECT_PARAMETER_POINT_RESETEABLE_H
+#define INKSCAPE_LIVEPATHEFFECT_PARAMETER_POINT_RESETEABLE_H
+
+/*
+ * Inkscape::LivePathEffectParameters
+ *
+* Copyright (C) Johan Engelen 2007 <j.b.c.engelen@utwente.nl>
+ *
+ * Released under GNU GPL, read the file 'COPYING' for more information
+ */
+
+#include <glib.h>
+#include <2geom/point.h>
+
+#include "live_effects/parameter/parameter.h"
+
+#include "knot-holder-entity.h"
+
+namespace Inkscape {
+
+namespace LivePathEffect {
+
+class PointReseteableParamKnotHolderEntity;
+
+class PointReseteableParam : public Geom::Point, public Parameter {
+public:
+ PointReseteableParam( const Glib::ustring& label,
+ const Glib::ustring& tip,
+ const Glib::ustring& key,
+ Inkscape::UI::Widget::Registry* wr,
+ Effect* effect,
+ const gchar *handle_tip = NULL,
+ Geom::Point default_value = Geom::Point(0,0) ); // tip for automatically associated on-canvas handle
+ virtual ~PointReseteableParam();
+
+ virtual Gtk::Widget * param_newWidget();
+
+ bool param_readSVGValue(const gchar * strvalue);
+ gchar * param_getSVGValue() const;
+ inline const gchar *handleTip() const { return handle_tip ? handle_tip : param_tooltip.c_str(); }
+
+ void param_setValue(Geom::Point newpoint);
+ void param_set_default();
+ void param_set_and_write_default();
+ void param_update_default(Geom::Point newpoint);
+
+ void param_set_and_write_new_value(Geom::Point newpoint);
+
+ virtual void param_transform_multiply(Geom::Affine const& /*postmul*/, bool /*set*/);
+
+ void set_oncanvas_looks(SPKnotShapeType shape, SPKnotModeType mode, guint32 color);
+
+ virtual bool providesKnotHolderEntities() const { return true; }
+ virtual void addKnotHolderEntities(KnotHolder *knotholder, SPDesktop *desktop, SPItem *item);
+
+ friend class PointReseteableParamKnotHolderEntity;
+private:
+ PointReseteableParam(const PointReseteableParam&);
+ PointReseteableParam& operator=(const PointReseteableParam&);
+
+ Geom::Point defvalue;
+
+ SPKnotShapeType knot_shape;
+ SPKnotModeType knot_mode;
+ guint32 knot_color;
+ gchar *handle_tip;
+};
+
+
+} //namespace LivePathEffect
+
+} //namespace Inkscape
+
+#endif
diff --git a/src/live_effects/parameter/togglebutton.cpp b/src/live_effects/parameter/togglebutton.cpp
new file mode 100644
index 000000000..03238f935
--- /dev/null
+++ b/src/live_effects/parameter/togglebutton.cpp
@@ -0,0 +1,92 @@
+/*
+ * Copyright (C) Johan Engelen 2007 <j.b.c.engelen@utwente.nl>
+ * Copyright (C) Jabiertxo Arraiza Cenoz 2014 <j.b.c.engelen@utwente.nl>
+ *
+ * Released under GNU GPL, read the file 'COPYING' for more information
+ */
+
+#include "ui/widget/registered-widget.h"
+#include "live_effects/parameter/togglebutton.h"
+#include "live_effects/effect.h"
+#include "svg/svg.h"
+#include "svg/stringstream.h"
+#include "widgets/icon.h"
+#include "inkscape.h"
+#include "verbs.h"
+#include "helper-fns.h"
+#include <glibmm/i18n.h>
+
+namespace Inkscape {
+
+namespace LivePathEffect {
+
+ToggleButtonParam::ToggleButtonParam( const Glib::ustring& label, const Glib::ustring& tip,
+ const Glib::ustring& key, Inkscape::UI::Widget::Registry* wr,
+ Effect* effect, bool default_value )
+ : Parameter(label, tip, key, wr, effect), value(default_value), defvalue(default_value)
+{
+}
+
+ToggleButtonParam::~ToggleButtonParam()
+{
+}
+
+void
+ToggleButtonParam::param_set_default()
+{
+ param_setValue(defvalue);
+}
+
+bool
+ToggleButtonParam::param_readSVGValue(const gchar * strvalue)
+{
+ param_setValue(helperfns_read_bool(strvalue, defvalue));
+ return true; // not correct: if value is unacceptable, should return false!
+}
+
+gchar *
+ToggleButtonParam::param_getSVGValue() const
+{
+ gchar * str = g_strdup(value ? "true" : "false");
+ return str;
+}
+
+Gtk::Widget *
+ToggleButtonParam::param_newWidget()
+{
+ Inkscape::UI::Widget::RegisteredToggleButton * checkwdg = Gtk::manage(
+ new Inkscape::UI::Widget::RegisteredToggleButton( param_label,
+ param_tooltip,
+ param_key,
+ *param_wr,
+ false,
+ param_effect->getRepr(),
+ param_effect->getSPDoc()) );
+
+ checkwdg->setActive(value);
+ checkwdg->setProgrammatically = false;
+ checkwdg->set_undo_parameters(SP_VERB_DIALOG_LIVE_PATH_EFFECT, _("Change togglebutton parameter"));
+
+ return dynamic_cast<Gtk::Widget *> (checkwdg);
+}
+
+void
+ToggleButtonParam::param_setValue(bool newvalue)
+{
+ value = newvalue;
+}
+
+} /* namespace LivePathEffect */
+
+} /* namespace Inkscape */
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :
diff --git a/src/live_effects/parameter/togglebutton.h b/src/live_effects/parameter/togglebutton.h
new file mode 100644
index 000000000..9b1c71185
--- /dev/null
+++ b/src/live_effects/parameter/togglebutton.h
@@ -0,0 +1,56 @@
+#ifndef INKSCAPE_LIVEPATHEFFECT_PARAMETER_TOGGLEBUTTON_H
+#define INKSCAPE_LIVEPATHEFFECT_PARAMETER_TOGGLEBUTTON_H
+
+/*
+ * Inkscape::LivePathEffectParameters
+ *
+* Copyright (C) Johan Engelen 2007 <j.b.c.engelen@utwente.nl>
+ *
+ * Released under GNU GPL, read the file 'COPYING' for more information
+ */
+
+#include <glib.h>
+
+#include "live_effects/parameter/parameter.h"
+
+namespace Inkscape {
+
+namespace LivePathEffect {
+
+
+class ToggleButtonParam : public Parameter {
+public:
+ ToggleButtonParam( const Glib::ustring& label,
+ const Glib::ustring& tip,
+ const Glib::ustring& key,
+ Inkscape::UI::Widget::Registry* wr,
+ Effect* effect,
+ bool default_value = false);
+ virtual ~ToggleButtonParam();
+
+ virtual Gtk::Widget * param_newWidget();
+
+ virtual bool param_readSVGValue(const gchar * strvalue);
+ virtual gchar * param_getSVGValue() const;
+
+ void param_setValue(bool newvalue);
+ virtual void param_set_default();
+
+ bool get_value() const { return value; };
+
+ inline operator bool() const { return value; };
+
+private:
+ ToggleButtonParam(const ToggleButtonParam&);
+ ToggleButtonParam& operator=(const ToggleButtonParam&);
+
+ bool value;
+ bool defvalue;
+};
+
+
+} //namespace LivePathEffect
+
+} //namespace Inkscape
+
+#endif
diff --git a/src/prefix.cpp b/src/prefix.cpp
index 99e20171f..630d6caa8 100644
--- a/src/prefix.cpp
+++ b/src/prefix.cpp
@@ -44,9 +44,6 @@ extern "C" {
#endif /* __cplusplus */
-#undef NULL
-#define NULL ((void *) 0)
-
#ifdef __GNUC__
#define br_return_val_if_fail(expr,val) if (!(expr)) {fprintf (stderr, "** BinReloc (%s): assertion %s failed\n", __PRETTY_FUNCTION__, #expr); return val;}
#else
diff --git a/src/sp-paint-server.cpp b/src/sp-paint-server.cpp
index 692265bd8..77ad7a35f 100644
--- a/src/sp-paint-server.cpp
+++ b/src/sp-paint-server.cpp
@@ -58,6 +58,11 @@ bool SPPaintServer::isSolid() const
return solid;
}
+bool SPPaintServer::isValid() const
+{
+ return true;
+}
+
/*
Local Variables:
mode:c++
diff --git a/src/sp-paint-server.h b/src/sp-paint-server.h
index 02e2f10ec..c1c8d651e 100644
--- a/src/sp-paint-server.h
+++ b/src/sp-paint-server.h
@@ -29,6 +29,7 @@ public:
bool isSwatch() const;
bool isSolid() const;
+ virtual bool isValid() const;
virtual cairo_pattern_t* pattern_new(cairo_t *ct, Geom::OptRect const &bbox, double opacity) = 0;
diff --git a/src/sp-pattern.cpp b/src/sp-pattern.cpp
index e465565c4..9aa54eadf 100644
--- a/src/sp-pattern.cpp
+++ b/src/sp-pattern.cpp
@@ -541,6 +541,16 @@ static bool pattern_hasItemChildren (SPPattern const *pat)
return hasChildren;
}
+bool SPPattern::isValid() const
+{
+ double tile_width = pattern_width(this);
+ double tile_height = pattern_height(this);
+
+ if (tile_width <= 0 || tile_height <= 0)
+ return false;
+ return true;
+}
+
cairo_pattern_t* SPPattern::pattern_new(cairo_t *base_ct, Geom::OptRect const &bbox, double opacity) {
bool needs_opacity = (1.0 - opacity) >= 1e-3;
@@ -593,7 +603,7 @@ cairo_pattern_t* SPPattern::pattern_new(cairo_t *base_ct, Geom::OptRect const &b
double tile_y = pattern_y(this);
double tile_width = pattern_width(this);
double tile_height = pattern_height(this);
- if (pattern_patternUnits(this) == SP_PATTERN_UNITS_OBJECTBOUNDINGBOX) {
+ if ( bbox && (pattern_patternUnits(this) == SP_PATTERN_UNITS_OBJECTBOUNDINGBOX) ) {
tile_x *= bbox->width();
tile_y *= bbox->height();
tile_width *= bbox->width();
@@ -614,7 +624,7 @@ cairo_pattern_t* SPPattern::pattern_new(cairo_t *base_ct, Geom::OptRect const &b
} else {
// Content to bbox
- if (pattern_patternContentUnits (this) == SP_PATTERN_UNITS_OBJECTBOUNDINGBOX) {
+ if (bbox && (pattern_patternContentUnits(this) == SP_PATTERN_UNITS_OBJECTBOUNDINGBOX) ) {
content2ps = Geom::Affine(bbox->width(), 0.0, 0.0, bbox->height(), 0,0);
}
}
diff --git a/src/sp-pattern.h b/src/sp-pattern.h
index f69ba10b3..eb34b6714 100644
--- a/src/sp-pattern.h
+++ b/src/sp-pattern.h
@@ -56,6 +56,8 @@ public:
sigc::connection modified_connection;
+ bool isValid() const;
+
virtual cairo_pattern_t* pattern_new(cairo_t *ct, Geom::OptRect const &bbox, double opacity);
protected:
diff --git a/src/sp-tag-use-reference.h b/src/sp-tag-use-reference.h
index b38e45837..f4c0e6a94 100644
--- a/src/sp-tag-use-reference.h
+++ b/src/sp-tag-use-reference.h
@@ -19,7 +19,7 @@ class Path;
namespace Inkscape {
namespace XML {
- struct Node;
+ class Node;
}
}
diff --git a/src/style-internal.cpp b/src/style-internal.cpp
index df08d0adf..b15892128 100644
--- a/src/style-internal.cpp
+++ b/src/style-internal.cpp
@@ -65,13 +65,13 @@ SPIFloat::read( gchar const *str ) {
if( !str ) return;
if ( !strcmp(str, "inherit") ) {
- set = TRUE;
- inherit = TRUE;
+ set = true;
+ inherit = true;
} else {
gfloat value_tmp;
if (sp_svg_number_read_f(str, &value_tmp)) {
- set = TRUE;
- inherit = FALSE;
+ set = true;
+ inherit = false;
value = value_tmp;
}
}
@@ -140,13 +140,13 @@ SPIScale24::read( gchar const *str ) {
if( !str ) return;
if ( !strcmp(str, "inherit") ) {
- set = TRUE;
- inherit = TRUE;
+ set = true;
+ inherit = true;
} else {
gfloat value_in;
if (sp_svg_number_read_f(str, &value_in)) {
- set = TRUE;
- inherit = FALSE;
+ set = true;
+ inherit = false;
value_in = CLAMP(value_in, 0.0, 1.0);
value = SP_SCALE24_FROM_FLOAT( value_in );
}
@@ -228,8 +228,8 @@ SPILength::read( gchar const *str ) {
if( !str ) return;
if (!strcmp(str, "inherit")) {
- set = TRUE;
- inherit = TRUE;
+ set = true;
+ inherit = true;
unit = SP_CSS_UNIT_NONE;
value = computed = 0.0;
} else {
@@ -291,8 +291,8 @@ SPILength::read( gchar const *str ) {
/* Invalid */
return;
}
- set = TRUE;
- inherit = FALSE;
+ set = true;
+ inherit = false;
}
}
}
@@ -439,11 +439,11 @@ SPILengthOrNormal::read( gchar const *str ) {
if( !str ) return;
if ( !strcmp(str, "normal") ) {
- set = TRUE;
- inherit = FALSE;
+ set = true;
+ inherit = false;
unit = SP_CSS_UNIT_NONE;
value = computed = 0.0;
- normal = TRUE;
+ normal = true;
} else {
SPILength::read( str );
normal = false;
@@ -501,13 +501,13 @@ SPIEnum::read( gchar const *str ) {
if( !str ) return;
if( !strcmp(str, "inherit") ) {
- set = TRUE;
- inherit = TRUE;
+ set = true;
+ inherit = true;
} else {
for (unsigned i = 0; enums[i].key; i++) {
if (!strcmp(str, enums[i].key)) {
- set = TRUE;
- inherit = FALSE;
+ set = true;
+ inherit = false;
value = enums[i].value;
/* Save copying for values not needing it */
computed = value;
@@ -648,17 +648,20 @@ SPIString::read( gchar const *str ) {
if( !str ) return;
- g_free(value);
+ // libcroco puts quotes around some strings... remove
+ gchar *str_unquoted = attribute_unquote(str);
if (!strcmp(str, "inherit")) {
- set = TRUE;
- inherit = TRUE;
+ set = true;
+ inherit = true;
value = NULL;
} else {
- set = TRUE;
- inherit = FALSE;
- value = g_strdup(str);
+ set = true;
+ inherit = false;
+ value = g_strdup(str_unquoted);
}
+
+ g_free( str_unquoted );
}
@@ -762,13 +765,13 @@ void SPIColor::read( gchar const *str ) {
if( name.compare( "color") == 0 ) {
inherit = true; // CSS3
} else {
- value.color = style->color.value.color;
+ setColor( style->color.value.color );
}
} else {
guint32 const rgb0 = sp_svg_read_color(str, 0xff);
if (rgb0 != 0xff) {
setColor(rgb0);
- set = TRUE;
+ set = true;
}
}
}
@@ -821,7 +824,7 @@ SPIColor::cascade( const SPIBase* const parent ) {
if( const SPIColor* p = dynamic_cast<const SPIColor*>(parent) ) {
if( (inherits && !set) || inherit) { // FIXME verify for 'color'
if( !(inherit && currentcolor) ) currentcolor = p->currentcolor;
- value.color = p->value.color;
+ setColor( p->value.color );
} else {
// Add CSS4 Color: Lighter, Darker
}
@@ -910,8 +913,8 @@ SPIPaint::read( gchar const *str ) {
}
if (streq(str, "inherit")) {
- set = TRUE;
- inherit = TRUE;
+ set = true;
+ inherit = true;
} else {
// Read any URL first. The other values can be stand-alone or backup to the URL.
@@ -924,7 +927,7 @@ SPIPaint::read( gchar const *str ) {
} else if (!style ) {
std::cerr << "SPIPaint::read: url with empty SPStyle pointer" << std::endl;
} else {
- set = TRUE;
+ set = true;
SPDocument *document = (style->object) ? style->object->document : NULL;
// Create href if not done already
@@ -946,17 +949,17 @@ SPIPaint::read( gchar const *str ) {
}
if (streq(str, "currentColor")) {
- set = TRUE;
- currentcolor = TRUE;
- value.color = style->color.value.color;
+ set = true;
+ currentcolor = true;
+ setColor( style->color.value.color );
} else if (streq(str, "none")) {
- set = TRUE;
- noneSet = TRUE;
+ set = true;
+ noneSet = true;
} else {
guint32 const rgb0 = sp_svg_read_color(str, &str, 0xff);
if (rgb0 != 0xff) {
setColor( rgb0 );
- set = TRUE;
+ set = true;
while (g_ascii_isspace(*str)) {
++str;
@@ -1076,7 +1079,7 @@ SPIPaint::reset( bool init ) {
setColor(0.0, 0.0, 0.0);
}
if( name.compare( "text-decoration-color" ) == 0 ) {
- currentcolor = true;
+ // currentcolor = true;
}
}
}
@@ -1100,10 +1103,10 @@ SPIPaint::cascade( const SPIBase* const parent ) {
} else if( p->isColor() ) {
setColor( p->value.color );
} else if( p->isNoneSet() ) {
- noneSet = TRUE;
+ noneSet = true;
} else if( p->currentcolor ) {
- currentcolor = TRUE;
- value.color = style->color.value.color;
+ currentcolor = true;
+ setColor( style->color.value.color );
} else if( isNone() ) {
//
} else {
@@ -1112,7 +1115,7 @@ SPIPaint::cascade( const SPIBase* const parent ) {
} else {
if( currentcolor ) {
// Update in case color value changed.
- value.color = style->color.value.color;
+ setColor( style->color.value.color );
}
}
@@ -1179,14 +1182,14 @@ SPIPaintOrder::read( gchar const *str ) {
if( !str ) return;
g_free(value);
- set = FALSE;
- inherit = FALSE;
+ set = false;
+ inherit = false;
if (!strcmp(str, "inherit")) {
- set = TRUE;
- inherit = TRUE;
+ set = true;
+ inherit = true;
} else {
- set = TRUE;
+ set = true;
value = g_strdup(str);
if (!strcmp(value, "normal")) {
@@ -1347,10 +1350,10 @@ SPIFilter::read( gchar const *str ) {
clear();
if ( streq(str, "inherit") ) {
- set = TRUE;
- inherit = TRUE;
+ set = true;
+ inherit = true;
} else if(streq(str, "none")) {
- set = TRUE;
+ set = true;
} else if (strneq(str, "url", 3)) {
gchar *uri = extract_uri(str);
if(uri == NULL || uri[0] == '\0') {
@@ -1360,7 +1363,7 @@ SPIFilter::read( gchar const *str ) {
std::cerr << "SPIFilter::read: url with empty SPStyle pointer" << std::endl;
return;
}
- set = TRUE;
+ set = true;
// Create href if not already done.
if (!href && style->object) {
@@ -1592,14 +1595,14 @@ SPIFontSize::read( gchar const *str ) {
if( !str ) return;
if (!strcmp(str, "inherit")) {
- set = TRUE;
- inherit = TRUE;
+ set = true;
+ inherit = true;
} else if ((*str == 'x') || (*str == 's') || (*str == 'm') || (*str == 'l')) {
// xx-small, x-small, etc.
for (unsigned i = 0; enum_font_size[i].key; i++) {
if (!strcmp(str, enum_font_size[i].key)) {
- set = TRUE;
- inherit = FALSE;
+ set = true;
+ inherit = false;
type = SP_FONT_SIZE_LITERAL;
literal = enum_font_size[i].value;
return;
@@ -1609,10 +1612,10 @@ SPIFontSize::read( gchar const *str ) {
return;
} else {
SPILength length("temp");
- length.set = FALSE;
+ length.set = false;
length.read( str );
if( length.set ) {
- set = TRUE;
+ set = true;
inherit = length.inherit;
unit = length.unit;
value = length.value;
@@ -1824,8 +1827,8 @@ SPIFont::read( gchar const *str ) {
}
if ( !strcmp(str, "inherit") ) {
- set = TRUE;
- inherit = TRUE;
+ set = true;
+ inherit = true;
} else {
// Break string into white space separated tokens
@@ -1957,14 +1960,14 @@ SPIBaselineShift::read( gchar const *str ) {
if( !str ) return;
if (!strcmp(str, "inherit")) {
- set = TRUE;
- inherit = TRUE;
+ set = true;
+ inherit = true;
} else if ((*str == 'b') || (*str == 's')) {
// baseline or sub or super
for (unsigned i = 0; enum_baseline_shift[i].key; i++) {
if (!strcmp(str, enum_baseline_shift[i].key)) {
- set = TRUE;
- inherit = FALSE;
+ set = true;
+ inherit = false;
type = SP_BASELINE_SHIFT_LITERAL;
literal = enum_baseline_shift[i].value;
return;
@@ -2405,31 +2408,65 @@ SPITextDecoration::read( gchar const *str ) {
if( !str ) return;
- style->text_decoration_line.read( str );
- style->text_decoration_style.read( str );
+ bool is_css3 = false;
+
+ SPITextDecorationLine test_line;
+ test_line.read( str );
+ if( test_line.set ) {
+ style->text_decoration_line = test_line;
+ }
+
+ SPITextDecorationStyle test_style;
+ test_style.read( str );
+ if( test_style.set ) {
+ style->text_decoration_style = test_style;
+ is_css3 = true;
+ }
+
// the color routine must be fed one token at a time - if multiple colors are found the LAST
// one is used ???? then why break on set?
- const gchar *hstr = str;
- style->text_decoration_color.read( "currentColor" ); // Default value
- style->text_decoration_color.set = false;
+ // This could certainly be designed better
+ SPIColor test_color("text-decoration-color");
+ test_color.setStylePointer( style );
+ test_color.read( "currentColor" ); // Default value
+ test_color.set = false;
+ const gchar *hstr = str;
while (1) {
if (*str == ' ' || *str == ',' || *str == '\0'){
int slen = str - hstr;
gchar *frag = g_strndup(hstr,slen+1); // only send one piece at a time, since keywords may be intermixed
if( strcmp( frag, "none" ) != 0 ) { // 'none' not allowed
- style->text_decoration_color.read( frag );
+ test_color.read( frag );
}
free(frag);
- if( style->text_decoration_color.set ) break;
- style->text_decoration_color.read( "currentColor" ); // Default value
+ if( test_color.set ) {
+ style->text_decoration_color = test_color;
+ is_css3 = true;
+ break;
+ }
+ test_color.read( "currentColor" ); // Default value
+ test_color.set = false;
if( *str == '\0' )break;
hstr = str + 1;
}
str++;
}
+
+ // If we read a style or color then we have CSS3 which require any non-set values to be
+ // set to their default values.
+ if( is_css3 ) {
+ style->text_decoration_line.set = true;
+ style->text_decoration_style.set = true;
+ style->text_decoration_color.set = true;
+ }
+
+ // If we set text_decoration_line, then update style_td (for CSS2 text-decoration)
+ if( style->text_decoration_line.set == true ) {
+ style_td = style;
+ }
}
// Returns CSS2 'text-decoration' (using settings in SPTextDecorationLine)
@@ -2464,14 +2501,29 @@ SPITextDecoration::write( guint const flags, SPIBase const *const base) const {
return Glib::ustring("");
}
-// Done in SPITextDecorationLine
-// void
-// SPITextDecoration::cascade( const SPIBase* const parent ) {
-// }
+void
+SPITextDecoration::cascade( const SPIBase* const parent ) {
+ if( const SPITextDecoration* p = dynamic_cast<const SPITextDecoration*>(parent) ) {
+ if( style_td == NULL ) {
+ style_td = p->style_td;
+ }
+ } else {
+ std::cerr << "SPITextDecoration::cascade(): Incorrect parent type" << std::endl;
+ }
-// void
-// SPITextDecoration::merge( const SPIBase* const parent ) {
-// }
+}
+
+void
+SPITextDecoration::merge( const SPIBase* const parent ) {
+ if( const SPITextDecoration* p = dynamic_cast<const SPITextDecoration*>(parent) ) {
+ if( style_td == NULL ) {
+ style_td = p->style_td;
+ }
+ } else {
+ std::cerr << "SPITextDecoration::merge(): Incorrect parent type" << std::endl;
+ }
+
+}
// Use CSS2 value
bool
diff --git a/src/style-internal.h b/src/style-internal.h
index e9cf6e604..e76f9faaf 100644
--- a/src/style-internal.h
+++ b/src/style-internal.h
@@ -116,8 +116,8 @@ class SPIBase {
virtual const Glib::ustring write( guint const flags = SP_STYLE_FLAG_IFSET,
SPIBase const *const base = NULL ) const = 0;
virtual void clear() { set = false, inherit = false; };
- virtual void cascade( const SPIBase* const parent ) {};
- virtual void merge( const SPIBase* const parent ) {}; // To do: Set to 0
+ virtual void cascade( const SPIBase* const parent ) = 0;
+ virtual void merge( const SPIBase* const parent ) = 0;
virtual void setStylePointer( SPStyle *style_in ) { style = style_in; };
@@ -698,8 +698,8 @@ class SPIFont : public SPIBase {
virtual void clear() {
SPIBase::clear();
};
- virtual void cascade( const SPIBase* const parent ) {}; // Done in dependent properties
- virtual void merge( const SPIBase* const parent ) {};
+ virtual void cascade( const SPIBase* const parent ) { (void)parent; }; // Done in dependent properties
+ virtual void merge( const SPIBase* const parent ) { (void)parent; };
SPIFont& operator=(const SPIFont& rhs) {
SPIBase::operator=(rhs);
@@ -837,19 +837,20 @@ class SPITextDecorationStyle : public SPIBase {
// the right style. (See http://www.w3.org/TR/css-text-decor-3/#text-decoration-property )
/// Text decoration type internal to SPStyle.
-class SPITextDecoration: public SPIBase {
+class SPITextDecoration : public SPIBase {
public:
- SPITextDecoration() : SPIBase( "text-decoration" ) {};
+ SPITextDecoration() : SPIBase( "text-decoration" ), style_td( NULL ) {};
virtual ~SPITextDecoration() {};
virtual void read( gchar const *str );
virtual const Glib::ustring write( guint const flags = SP_STYLE_FLAG_IFSET,
SPIBase const *const base = NULL ) const;
virtual void clear() {
SPIBase::clear();
+ style_td = NULL;
};
- virtual void cascade( const SPIBase* const parent ) {}; // Done in SPITextDecorationLine
- virtual void merge( const SPIBase* const parent ) {}; // Done in SPITextDecorationLine
+ virtual void cascade( const SPIBase* const parent );
+ virtual void merge( const SPIBase* const parent );
SPITextDecoration& operator=(const SPITextDecoration& rhs) {
SPIBase::operator=(rhs);
@@ -859,6 +860,9 @@ class SPITextDecoration: public SPIBase {
// Use CSS2 value
virtual bool operator==(const SPIBase& rhs);
virtual bool operator!=(const SPIBase& rhs) { return !(*this == rhs); };
+
+ public:
+ SPStyle* style_td; // Style to be used for drawing CSS2 text decorations
};
diff --git a/src/ui/dialog/filedialogimpl-win32.cpp b/src/ui/dialog/filedialogimpl-win32.cpp
index 9d91f5d56..06153a2d8 100644
--- a/src/ui/dialog/filedialogimpl-win32.cpp
+++ b/src/ui/dialog/filedialogimpl-win32.cpp
@@ -72,13 +72,6 @@ const unsigned long MaxPreviewFileSize = 10240; // kB
#define IDC_SHOW_PREVIEW 1000
-// Windows 2000 version of OPENFILENAMEW
-struct OPENFILENAMEEXW : public OPENFILENAMEW {
- void * pvReserved;
- DWORD dwReserved;
- DWORD FlagsEx;
-};
-
struct Filter
{
gunichar2* name;
@@ -483,7 +476,7 @@ void FileOpenDialogImplWin32::createFilterMenu()
void FileOpenDialogImplWin32::GetOpenFileName_thread()
{
- OPENFILENAMEEXW ofn;
+ OPENFILENAMEW ofn;
g_assert(this != NULL);
g_assert(_mutex != NULL);
@@ -1829,7 +1822,7 @@ void FileSaveDialogImplWin32::addFileType(Glib::ustring name, Glib::ustring patt
void FileSaveDialogImplWin32::GetSaveFileName_thread()
{
- OPENFILENAMEEXW ofn;
+ OPENFILENAMEW ofn;
g_assert(this != NULL);
g_assert(_main_loop != NULL);
@@ -1860,7 +1853,6 @@ void FileSaveDialogImplWin32::GetSaveFileName_thread()
ofn.nFilterIndex = _filter_index;
ofn.lpfnHook = GetSaveFileName_hookproc;
ofn.lCustData = (LPARAM)this;
-
_result = GetSaveFileNameW(&ofn) != 0;
g_assert(ofn.nFilterIndex >= 1 && ofn.nFilterIndex <= _filter_count);
diff --git a/src/ui/dialog/filedialogimpl-win32.h b/src/ui/dialog/filedialogimpl-win32.h
index 29bcb9a45..c523f041d 100644
--- a/src/ui/dialog/filedialogimpl-win32.h
+++ b/src/ui/dialog/filedialogimpl-win32.h
@@ -13,14 +13,20 @@
# include "config.h"
#endif
+#include <glibmm.h>
+
#ifdef WIN32
#if WITH_GLIBMM_2_32
#if GLIBMM_DISABLE_DEPRECATED && HAVE_GLIBMM_THREADS_H
# include <glibmm/threads.h>
#endif
-
#endif
+
#include "gc-core.h"
+ // define WINVER high enough so we get the correct OPENFILENAMEW size
+#ifndef WINVER
+#define WINVER 0x0500
+#endif
#include <windows.h>
#include "filedialogimpl-gtkmm.h"
diff --git a/src/ui/dialog/tags.cpp b/src/ui/dialog/tags.cpp
index 1b5dd9400..b2ca1b6da 100644
--- a/src/ui/dialog/tags.cpp
+++ b/src/ui/dialog/tags.cpp
@@ -8,16 +8,22 @@
*
* Released under GNU GPL, read the file 'COPYING' for more information
*/
+
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
+#if WITH_GLIBMM_2_32
+# include <glibmm/threads.h>
+#endif
+
#include "tags.h"
#include <gtkmm/widget.h>
#include <gtkmm/icontheme.h>
#include <gtkmm/imagemenuitem.h>
#include <gtkmm/separatormenuitem.h>
+#include <glibmm/main.h>
#include <glibmm/i18n.h>
#include "desktop.h"
diff --git a/src/ui/dialog/text-edit.cpp b/src/ui/dialog/text-edit.cpp
index 17c29c69f..c1ebb32e0 100644
--- a/src/ui/dialog/text-edit.cpp
+++ b/src/ui/dialog/text-edit.cpp
@@ -404,12 +404,12 @@ void TextEdit::setPreviewText (Glib::ustring font_spec, Glib::ustring phrase)
double pt_size = Inkscape::Util::Quantity::convert(sp_style_css_size_units_to_px(sp_font_selector_get_size(fsel), unit), "px", "pt");
// Pango font size is in 1024ths of a point
- // C++11: Glib::ustring size = std::to_string( pt_size * PANGO_SCALE );
+ // C++11: Glib::ustring size = std::to_string( int(pt_size * PANGO_SCALE) );
std::ostringstream size_st;
- size_st << pt_size * PANGO_SCALE;
+ size_st << int(pt_size * PANGO_SCALE); // Markup code expects integers
- Glib::ustring markup = "<span font=\"" + font_spec +
- "\" size=\"" + size_st.str() + "\">" + phrase_escaped + "</span>";
+ Glib::ustring markup = "<span font=\'" + font_spec +
+ "\' size=\'" + size_st.str() + "\'>" + phrase_escaped + "</span>";
preview_label.set_markup(markup.c_str());
}
diff --git a/src/ui/tool/node.cpp b/src/ui/tool/node.cpp
index 1434a5c5b..ed0843b65 100644
--- a/src/ui/tool/node.cpp
+++ b/src/ui/tool/node.cpp
@@ -371,7 +371,7 @@ void Handle::dragged(Geom::Point &new_pos, GdkEventMotion *event)
std::vector<Inkscape::SnapCandidatePoint> unselected;
//if the snap adjustment is activated and it is not bspline
- if (snap && !_pm().isBSpline()) {
+ if (snap && !_pm().isBSpline(false)) {
ControlPointSelection::Set &nodes = _parent->_selection.allPoints();
for (ControlPointSelection::Set::iterator i = nodes.begin(); i != nodes.end(); ++i) {
Node *n = static_cast<Node*>(*i);
@@ -623,7 +623,7 @@ void Node::move(Geom::Point const &new_pos)
Node *n = this;
Node * nextNode = n->nodeToward(n->front());
Node * prevNode = n->nodeToward(n->back());
- nodeWeight = _pm().BSplineHandlePosition(n->front());
+ nodeWeight = fmax(_pm().BSplineHandlePosition(n->front()),_pm().BSplineHandlePosition(n->back()));
if(prevNode){
if(prevNode->isEndNode()){
prevNodeWeight = _pm().BSplineHandlePosition(prevNode->front(),prevNode->front());
@@ -659,7 +659,7 @@ void Node::move(Geom::Point const &new_pos)
if(nextNode->isEndNode()){
nextNode->back()->setPosition(_pm().BSplineHandleReposition(nextNode->back(),nextNodeWeight));
}else{
- nextNode->back()->setPosition(_pm().BSplineHandleReposition(nextNode->back(),nextNode->back()));
+ nextNode->back()->setPosition(_pm().BSplineHandleReposition(nextNode->back(),nextNode->front()));
}
}
}
diff --git a/src/ui/tool/node.h b/src/ui/tool/node.h
index 5971956e1..101af4817 100644
--- a/src/ui/tool/node.h
+++ b/src/ui/tool/node.h
@@ -41,6 +41,7 @@ template <typename> class NodeIterator;
}
}
+/*
#if HAVE_TR1_UNORDERED_SET
namespace std {
namespace tr1 {
@@ -48,6 +49,8 @@ template <typename N> struct hash< Inkscape::UI::NodeIterator<N> >;
}
}
#endif
+#endif
+*/
namespace Inkscape {
namespace UI {
diff --git a/src/ui/tools/node-tool.cpp b/src/ui/tools/node-tool.cpp
index 719b67108..72f5159ae 100644
--- a/src/ui/tools/node-tool.cpp
+++ b/src/ui/tools/node-tool.cpp
@@ -23,6 +23,8 @@
#include "message-context.h"
#include "selection.h"
#include "shape-editor.h" // temporary!
+#include "live_effects/effect.h"
+#include "display/curve.h"
#include "sp-clippath.h"
#include "sp-item-group.h"
#include "sp-mask.h"
@@ -167,6 +169,10 @@ NodeTool::~NodeTool() {
this->desktop->remove_temporary_canvasitem(this->flash_tempitem);
}
+ if (this->helperpath_tmpitem) {
+ this->desktop->remove_temporary_canvasitem(this->helperpath_tmpitem);
+ }
+
this->_selection_changed_connection.disconnect();
//this->_selection_modified_connection.disconnect();
this->_mouseover_changed_connection.disconnect();
@@ -252,6 +258,7 @@ void NodeTool::setup() {
this->flash_tempitem = NULL;
this->flashed_item = NULL;
this->_last_over = NULL;
+ this->helperpath_tmpitem = NULL;
// read prefs before adding items to selection to prevent momentarily showing the outline
sp_event_context_read(this, "show_handles");
@@ -278,6 +285,41 @@ void NodeTool::setup() {
}
this->desktop->emitToolSubselectionChanged(NULL); // sets the coord entry fields to inactive
+ this->update_helperpath();
+}
+
+void NodeTool::update_helperpath(){
+ Inkscape::Selection *selection = sp_desktop_selection (this->desktop);
+ if (this->helperpath_tmpitem) {
+ this->desktop->remove_temporary_canvasitem(this->helperpath_tmpitem);
+ this->helperpath_tmpitem = NULL;
+ }
+ if (SP_IS_LPE_ITEM(selection->singleItem())) {
+ Inkscape::LivePathEffect::Effect *lpe = SP_LPE_ITEM(selection->singleItem())->getCurrentLPE();
+ if (lpe && lpe->isVisible()/* && lpe->showOrigPath()*/) {
+ if (lpe) {
+ SPCurve *c = new SPCurve();
+ SPCurve *cc = new SPCurve();
+ std::vector<Geom::PathVector> cs = lpe->getCanvasIndicators(SP_LPE_ITEM(selection->singleItem()));
+ for (std::vector<Geom::PathVector>::iterator p = cs.begin(); p != cs.end(); ++p) {
+ cc->set_pathvector(*p);
+ c->append(cc, false);
+ cc->reset();
+ }
+ if (!c->is_empty()) {
+ c->transform(selection->singleItem()->i2dt_affine());
+ SPCanvasItem *helperpath = sp_canvas_bpath_new(sp_desktop_tempgroup(this->desktop), c);
+ sp_canvas_bpath_set_stroke(SP_CANVAS_BPATH(helperpath),
+ 0x0000ff9A, 1.0,
+ SP_STROKE_LINEJOIN_MITER, SP_STROKE_LINECAP_BUTT);
+ sp_canvas_bpath_set_fill(SP_CANVAS_BPATH(helperpath), 0, SP_WIND_RULE_NONZERO);
+ this->helperpath_tmpitem = this->desktop->add_temporary_canvasitem(helperpath,0);
+ }
+ c->unref();
+ cc->unref();
+ }
+ }
+ }
}
void NodeTool::set(const Inkscape::Preferences::Entry& value) {
@@ -392,7 +434,7 @@ void NodeTool::selection_changed(Inkscape::Selection *sel) {
for (std::set<ShapeRecord>::iterator i = shapes.begin(); i != shapes.end(); ++i) {
ShapeRecord const &r = *i;
- if ((SP_IS_SHAPE(r.item) || SP_IS_TEXT(r.item)) &&
+ if ((SP_IS_SHAPE(r.item) || SP_IS_TEXT(r.item) || SP_IS_GROUP(r.item) || SP_IS_OBJECTGROUP(r.item)) &&
this->_shape_editors.find(r.item) == this->_shape_editors.end())
{
ShapeEditor *si = new ShapeEditor(this->desktop);
@@ -416,7 +458,7 @@ bool NodeTool::root_handler(GdkEvent* event) {
Inkscape::Selection *selection = desktop->selection;
static Inkscape::Preferences *prefs = Inkscape::Preferences::get();
-
+
if (this->_multipath->event(this, event)) {
return true;
}
@@ -433,6 +475,7 @@ bool NodeTool::root_handler(GdkEvent* event) {
{
case GDK_MOTION_NOTIFY: {
combine_motion_events(desktop->canvas, event->motion, 0);
+ this->update_helperpath();
SPItem *over_item = sp_event_context_find_item (desktop, event_point(event->button),
FALSE, TRUE);
@@ -441,7 +484,6 @@ bool NodeTool::root_handler(GdkEvent* event) {
//ink_node_tool_update_tip(nt, event);
this->update_tip(event);
}
-
// create pathflash outline
if (prefs->getBool("/tools/nodes/pathflash_enabled")) {
if (over_item == this->flashed_item) {
diff --git a/src/ui/tools/node-tool.h b/src/ui/tools/node-tool.h
index 42f89cd1c..9f0c40aa8 100644
--- a/src/ui/tools/node-tool.h
+++ b/src/ui/tools/node-tool.h
@@ -54,6 +54,7 @@ public:
static const std::string prefsPath;
virtual void setup();
+ virtual void update_helperpath();
virtual void set(const Inkscape::Preferences::Entry& val);
virtual bool root_handler(GdkEvent* event);
@@ -66,6 +67,7 @@ private:
SPItem *flashed_item;
Inkscape::Display::TemporaryItem *flash_tempitem;
+ Inkscape::Display::TemporaryItem *helperpath_tmpitem;
Inkscape::UI::Selector* _selector;
Inkscape::UI::PathSharedData* _path_data;
SPCanvasGroup *_transform_handle_group;
diff --git a/src/ui/tools/pen-tool.cpp b/src/ui/tools/pen-tool.cpp
index 9e4df5031..386dc43e9 100644
--- a/src/ui/tools/pen-tool.cpp
+++ b/src/ui/tools/pen-tool.cpp
@@ -1811,9 +1811,9 @@ void PenTool::_bspline_spiro_build()
void PenTool::_bspline_doEffect(SPCurve * curve)
{
// commenting the function doEffect in src/live_effects/lpe-bspline.cpp
- if(curve->get_segment_count() < 2)
- return;
Geom::PathVector const original_pathv = curve->get_pathvector();
+ if (curve->get_segment_count() < 1)
+ return;
curve->reset();
for(Geom::PathVector::const_iterator path_it = original_pathv.begin(); path_it != original_pathv.end(); ++path_it) {
@@ -1890,9 +1890,25 @@ void PenTool::_bspline_doEffect(SPCurve * curve)
++curve_it1;
++curve_it2;
}
+ SPCurve *out = new SPCurve();
+ out->moveto(curve_it1->initialPoint());
+ out->lineto(curve_it1->finalPoint());
+ cubic = dynamic_cast<Geom::CubicBezier const *>(&*curve_it1);
+ if (cubic) {
+ SBasisOut = out->first_segment()->toSBasis();
+ nextPointAt1 = SBasisOut.valueAt(Geom::nearest_point((*cubic)[1], *out->first_segment()));
+ nextPointAt2 = SBasisOut.valueAt(Geom::nearest_point((*cubic)[2], *out->first_segment()));
+ nextPointAt3 = out->first_segment()->finalPoint();
+ } else {
+ nextPointAt1 = out->first_segment()->initialPoint();
+ nextPointAt2 = out->first_segment()->finalPoint();
+ nextPointAt3 = out->first_segment()->finalPoint();
+ }
+ out->reset();
+ delete out;
SPCurve *curveHelper = new SPCurve();
curveHelper->moveto(node);
- Geom::Point startNode(0,0);
+ Geom::Point startNode = path_it->begin()->initialPoint();
if (path_it->closed()) {
SPCurve * start = new SPCurve();
start->moveto(path_it->begin()->initialPoint());
diff --git a/src/ui/widget/registered-widget.cpp b/src/ui/widget/registered-widget.cpp
index 92cb3f03d..83da1a6d6 100644
--- a/src/ui/widget/registered-widget.cpp
+++ b/src/ui/widget/registered-widget.cpp
@@ -99,6 +99,59 @@ RegisteredCheckButton::on_toggled()
_wr->setUpdating (false);
}
+/*#########################################
+ * Registered TOGGLEBUTTON
+ */
+
+RegisteredToggleButton::~RegisteredToggleButton()
+{
+ _toggled_connection.disconnect();
+}
+
+RegisteredToggleButton::RegisteredToggleButton (const Glib::ustring& label, const Glib::ustring& tip, const Glib::ustring& key, Registry& wr, bool right, Inkscape::XML::Node* repr_in, SPDocument *doc_in, char const *active_str, char const *inactive_str)
+ : RegisteredWidget<Gtk::ToggleButton>(label)
+ , _active_str(active_str)
+ , _inactive_str(inactive_str)
+{
+ init_parent(key, wr, repr_in, doc_in);
+ setProgrammatically = false;
+ set_tooltip_text (tip);
+ set_alignment (right? 1.0 : 0.0, 0.5);
+ _toggled_connection = signal_toggled().connect (sigc::mem_fun (*this, &RegisteredToggleButton::on_toggled));
+}
+
+void
+RegisteredToggleButton::setActive (bool b)
+{
+ setProgrammatically = true;
+ set_active (b);
+ //The slave button is greyed out if the master button is untoggled
+ for (std::list<Gtk::Widget*>::const_iterator i = _slavewidgets.begin(); i != _slavewidgets.end(); ++i) {
+ (*i)->set_sensitive(b);
+ }
+ setProgrammatically = false;
+}
+
+void
+RegisteredToggleButton::on_toggled()
+{
+ if (setProgrammatically) {
+ setProgrammatically = false;
+ return;
+ }
+
+ if (_wr->isUpdating())
+ return;
+ _wr->setUpdating (true);
+
+ write_to_xml(get_active() ? _active_str : _inactive_str);
+ //The slave button is greyed out if the master button is untoggled
+ for (std::list<Gtk::Widget*>::const_iterator i = _slavewidgets.begin(); i != _slavewidgets.end(); ++i) {
+ (*i)->set_sensitive(get_active());
+ }
+
+ _wr->setUpdating (false);
+}
/*#########################################
* Registered UNITMENU
diff --git a/src/ui/widget/registered-widget.h b/src/ui/widget/registered-widget.h
index d64c09c16..d8c0e6602 100644
--- a/src/ui/widget/registered-widget.h
+++ b/src/ui/widget/registered-widget.h
@@ -163,6 +163,31 @@ protected:
void on_toggled();
};
+class RegisteredToggleButton : public RegisteredWidget<Gtk::ToggleButton> {
+public:
+ virtual ~RegisteredToggleButton();
+ RegisteredToggleButton (const Glib::ustring& label, const Glib::ustring& tip, const Glib::ustring& key, Registry& wr, bool right=true, Inkscape::XML::Node* repr_in=NULL, SPDocument *doc_in=NULL, char const *active_str = "true", char const *inactive_str = "false");
+
+ void setActive (bool);
+
+ std::list<Gtk::Widget*> _slavewidgets;
+
+ // a slave button is only sensitive when the master button is active
+ // i.e. a slave button is greyed-out when the master button is not checked
+
+ void setSlaveWidgets(std::list<Gtk::Widget*> btns) {
+ _slavewidgets = btns;
+ }
+
+ bool setProgrammatically; // true if the value was set by setActive, not changed by the user;
+ // if a callback checks it, it must reset it back to false
+
+protected:
+ char const *_active_str, *_inactive_str;
+ sigc::connection _toggled_connection;
+ void on_toggled();
+};
+
class RegisteredUnitMenu : public RegisteredWidget<Labelled> {
public:
~RegisteredUnitMenu();
diff --git a/src/widgets/ege-paint-def.cpp b/src/widgets/ege-paint-def.cpp
index 542205b53..1a8ad041a 100644
--- a/src/widgets/ege-paint-def.cpp
+++ b/src/widgets/ege-paint-def.cpp
@@ -44,7 +44,6 @@
#include <string>
#include <iostream>
#include <sstream>
-#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <glibmm/i18n.h>