diff options
| author | Liam P. White <inkscapebrony@gmail.com> | 2014-11-09 05:13:46 +0000 |
|---|---|---|
| committer | Liam P. White <inkscapebrony@gmail.com> | 2014-11-09 05:13:46 +0000 |
| commit | 4b236f3f1e3fe5374e18dac9e6c35567d9dc0995 (patch) | |
| tree | d6a8f361b37294feb8da05c2ce61271e5137a237 /src | |
| parent | Remove FIXME from refactoring (diff) | |
| parent | Fix bug in previous commit. Add test against it (diff) | |
| download | inkscape-4b236f3f1e3fe5374e18dac9e6c35567d9dc0995.tar.gz inkscape-4b236f3f1e3fe5374e18dac9e6c35567d9dc0995.zip | |
Update to trunk r13690
(bzr r13341.5.22)
Diffstat (limited to 'src')
49 files changed, 568 insertions, 521 deletions
diff --git a/src/display/drawing-pattern.cpp b/src/display/drawing-pattern.cpp index cf6358278..d0bf5de58 100644 --- a/src/display/drawing-pattern.cpp +++ b/src/display/drawing-pattern.cpp @@ -149,8 +149,8 @@ DrawingPattern::renderPattern(float opacity) { return cp; } -unsigned -DrawingPattern::_updateItem(Geom::IntRect const &area, UpdateContext const &ctx, unsigned flags, unsigned reset) +// TODO investigate if area should be used. +unsigned DrawingPattern::_updateItem(Geom::IntRect const &area, UpdateContext const &ctx, unsigned flags, unsigned reset) { UpdateContext pattern_ctx; diff --git a/src/extension/internal/cairo-ps-out.cpp b/src/extension/internal/cairo-ps-out.cpp index 4defc2ab9..d1511ba84 100644 --- a/src/extension/internal/cairo-ps-out.cpp +++ b/src/extension/internal/cairo-ps-out.cpp @@ -333,7 +333,7 @@ CairoPsOutput::init (void) "<param name=\"textToPath\" gui-text=\"" N_("Convert texts to paths") "\" type=\"boolean\">false</param>\n" "<param name=\"textToLaTeX\" gui-text=\"" N_("PS+LaTeX: Omit text in PS, and create LaTeX file") "\" type=\"boolean\">false</param>\n" "<param name=\"blurToBitmap\" gui-text=\"" N_("Rasterize filter effects") "\" type=\"boolean\">true</param>\n" - "<param name=\"resolution\" gui-text=\"" N_("Resolution for rasterization (dpi):") "\" type=\"int\" min=\"1\" max=\"10000\">90</param>\n" + "<param name=\"resolution\" gui-text=\"" N_("Resolution for rasterization (dpi):") "\" type=\"int\" min=\"1\" max=\"10000\">96</param>\n" "<param name=\"area\" gui-text=\"" N_("Output page size") "\" type=\"optiongroup\" >\n" "<_option value=\"page\">" N_("Use document's page size") "</_option>" "<_option value=\"drawing\">" N_("Use exported object's size") "</_option>" @@ -372,7 +372,7 @@ CairoEpsOutput::init (void) "<param name=\"textToPath\" gui-text=\"" N_("Convert texts to paths") "\" type=\"boolean\">false</param>\n" "<param name=\"textToLaTeX\" gui-text=\"" N_("EPS+LaTeX: Omit text in EPS, and create LaTeX file") "\" type=\"boolean\">false</param>\n" "<param name=\"blurToBitmap\" gui-text=\"" N_("Rasterize filter effects") "\" type=\"boolean\">true</param>\n" - "<param name=\"resolution\" gui-text=\"" N_("Resolution for rasterization (dpi):") "\" type=\"int\" min=\"1\" max=\"10000\">90</param>\n" + "<param name=\"resolution\" gui-text=\"" N_("Resolution for rasterization (dpi):") "\" type=\"int\" min=\"1\" max=\"10000\">96</param>\n" "<param name=\"area\" gui-text=\"" N_("Output page size") "\" type=\"optiongroup\" >\n" "<_option value=\"page\">" N_("Use document's page size") "</_option>" "<_option value=\"drawing\">" N_("Use exported object's size") "</_option>" diff --git a/src/extension/internal/cairo-render-context.cpp b/src/extension/internal/cairo-render-context.cpp index cb414b3b2..d76c187a2 100644 --- a/src/extension/internal/cairo-render-context.cpp +++ b/src/extension/internal/cairo-render-context.cpp @@ -658,12 +658,12 @@ CairoRenderContext::popLayer(void) CairoRenderContext *mask_ctx = _renderer->createContext(); // Fix Me: This is a kludge. PDF and PS output is set to 72 dpi but the - // Cairo surface is expecting the mask to be 90 dpi. + // Cairo surface is expecting the mask to be 96 dpi. float surface_width = _width; float surface_height = _height; if( _vector_based_target ) { - surface_width *= 1.25; - surface_height *= 1.25; + surface_width *= 4.0/3.0; + surface_height *= 4.0/3.0; } if (!mask_ctx->setupSurface( surface_width, surface_height )) { TRACE(("mask: setupSurface failed\n")); diff --git a/src/extension/internal/cairo-renderer-pdf-out.cpp b/src/extension/internal/cairo-renderer-pdf-out.cpp index 0c314a576..0c4ad4f0a 100644 --- a/src/extension/internal/cairo-renderer-pdf-out.cpp +++ b/src/extension/internal/cairo-renderer-pdf-out.cpp @@ -250,7 +250,7 @@ CairoRendererPdfOutput::init (void) "<param name=\"textToPath\" gui-text=\"" N_("Convert texts to paths") "\" type=\"boolean\">false</param>\n" "<param name=\"textToLaTeX\" gui-text=\"" N_("PDF+LaTeX: Omit text in PDF, and create LaTeX file") "\" type=\"boolean\">false</param>\n" "<param name=\"blurToBitmap\" gui-text=\"" N_("Rasterize filter effects") "\" type=\"boolean\">true</param>\n" - "<param name=\"resolution\" gui-text=\"" N_("Resolution for rasterization (dpi):") "\" type=\"int\" min=\"1\" max=\"10000\">90</param>\n" + "<param name=\"resolution\" gui-text=\"" N_("Resolution for rasterization (dpi):") "\" type=\"int\" min=\"1\" max=\"10000\">96</param>\n" "<param name=\"area\" gui-text=\"" N_("Output page size:") "\" type=\"optiongroup\" >\n" "<_option value=\"page\">" N_("Use document's page size") "</_option>" "<_option value=\"drawing\">" N_("Use exported object's size") "</_option>" diff --git a/src/extension/internal/cairo-renderer.cpp b/src/extension/internal/cairo-renderer.cpp index a725685d4..1d9bb09d0 100644 --- a/src/extension/internal/cairo-renderer.cpp +++ b/src/extension/internal/cairo-renderer.cpp @@ -479,7 +479,7 @@ static void sp_asbitmap_render(SPItem *item, CairoRenderContext *ctx) double shift_x = bbox->min()[Geom::X]; double shift_y = bbox->max()[Geom::Y]; - // For default 90 dpi, snap bitmap to pixel grid + // For default 96 dpi, snap bitmap to pixel grid if (res == Inkscape::Util::Quantity::convert(1, "in", "px")) { shift_x = round (shift_x); shift_y = -round (-shift_y); // Correct rounding despite coordinate inversion. diff --git a/src/extension/param/radiobutton.cpp b/src/extension/param/radiobutton.cpp index 75d5a40e3..f9515197c 100644 --- a/src/extension/param/radiobutton.cpp +++ b/src/extension/param/radiobutton.cpp @@ -122,7 +122,7 @@ ParamRadioButton::ParamRadioButton (const gchar * name, defaultval = (static_cast<optionentry*> (choices->data))->value->c_str(); } - const char * indent = xml->attribute("indent"); + const char *indent = xml ? xml->attribute("indent") : NULL; if (indent != NULL) { _indent = atoi(indent) * 12; } diff --git a/src/live_effects/effect.cpp b/src/live_effects/effect.cpp index b002eaf7f..349caafd9 100644 --- a/src/live_effects/effect.cpp +++ b/src/live_effects/effect.cpp @@ -75,8 +75,6 @@ #include <glibmm/i18n.h> #include "ui/tools/pen-tool.h" #include "ui/tools-switch.h" -#include "message-stack.h" -#include "desktop.h" #include "knotholder.h" #include "sp-lpe-item.h" #include "live_effects/lpeobject.h" @@ -370,6 +368,7 @@ Effect::Effect(LivePathEffectObject *lpeobject) { registerParameter( dynamic_cast<Parameter *>(&is_visible) ); is_visible.widget_is_visible = false; + current_zoom = 0.0; } Effect::~Effect() @@ -398,6 +397,36 @@ Effect::doOnApply (SPLPEItem const*/*lpeitem*/) { } +void +Effect::setSelectedNodePoints(std::vector<Geom::Point> sNP) +{ + selectedNodesPoints = sNP; +} + +void +Effect::setCurrentZoom(double cZ) +{ + current_zoom = cZ; +} + +bool +Effect::isNodePointSelected(Geom::Point const &nodePoint) const +{ + if (selectedNodesPoints.size() > 0) { + for (std::vector<Geom::Point>::const_iterator i = selectedNodesPoints.begin(); + i != selectedNodesPoints.end(); ++i) { + Geom::Point p = *i; + std::cout << p << "p\n"; + p[Geom::X] = Inkscape::Util::Quantity::convert(p[Geom::X], "px", *defaultUnit); + p[Geom::Y] = Inkscape::Util::Quantity::convert(p[Geom::Y], "px", *defaultUnit); + if (Geom::are_near(p, nodePoint, 0.01)) { + return true; + } + } + } + return false; +} + /** * Is performed each time before the effect is updated. */ @@ -419,6 +448,7 @@ void Effect::doOnRemove (SPLPEItem const* /*lpeitem*/) void Effect::doOnApply_impl(SPLPEItem const* lpeitem) { sp_lpe_item = const_cast<SPLPEItem *>(lpeitem); + defaultUnit = &sp_lpe_item->document->getDefaultUnit()->abbr; /*sp_curve = SP_SHAPE(sp_lpe_item)->getCurve(); pathvector_before_effect = sp_curve->get_pathvector();*/ doOnApply(lpeitem); @@ -427,6 +457,7 @@ void Effect::doOnApply_impl(SPLPEItem const* lpeitem) void Effect::doBeforeEffect_impl(SPLPEItem const* lpeitem) { sp_lpe_item = const_cast<SPLPEItem *>(lpeitem); + defaultUnit = &sp_lpe_item->document->getDefaultUnit()->abbr; //printf("(SPLPEITEM*) %p\n", sp_lpe_item); sp_curve = SP_SHAPE(sp_lpe_item)->getCurve(); pathvector_before_effect = sp_curve->get_pathvector(); diff --git a/src/live_effects/effect.h b/src/live_effects/effect.h index a486e8491..7da76b267 100644 --- a/src/live_effects/effect.h +++ b/src/live_effects/effect.h @@ -13,6 +13,7 @@ #include "parameter/bool.h" #include "effect-enum.h" + #define LPE_CONVERSION_TOLERANCE 0.01 // FIXME: find good solution for this. class SPDocument; @@ -57,7 +58,9 @@ public: //of indirection is needed. We first call these methods, then the below. void doOnApply_impl(SPLPEItem const* lpeitem); void doBeforeEffect_impl(SPLPEItem const* lpeitem); - + void setCurrentZoom(double cZ); + void setSelectedNodePoints(std::vector<Geom::Point> sNP); + bool isNodePointSelected(Geom::Point const &nodePoint) const; virtual void doOnApply (SPLPEItem const* lpeitem); virtual void doBeforeEffect (SPLPEItem const* lpeitem); @@ -156,6 +159,9 @@ protected: bool concatenate_before_pwd2; SPLPEItem * sp_lpe_item; // these get stored in doBeforeEffect_impl, and derived classes may do as they please with them. + Glib::ustring const * defaultUnit; // these get stored in doBeforeEffect_impl, and derived classes may do as they please with them. + double current_zoom; + std::vector<Geom::Point> selectedNodesPoints; SPCurve * sp_curve; std::vector<Geom::Path> pathvector_before_effect; private: diff --git a/src/live_effects/lpe-bspline.cpp b/src/live_effects/lpe-bspline.cpp index 7703b8221..fdaeaf897 100644 --- a/src/live_effects/lpe-bspline.cpp +++ b/src/live_effects/lpe-bspline.cpp @@ -24,11 +24,6 @@ #include "live_effects/lpeobject.h" #include "live_effects/parameter/parameter.h" #include "ui/widget/scalar.h" -#include "ui/tool/node.h" -#include "ui/tools/node-tool.h" -#include "ui/tool/control-point-selection.h" -#include "ui/tool/selectable-control-point.h" -#include "selection.h" #include "xml/repr.h" #include "svg/svg.h" #include "sp-path.h" @@ -36,7 +31,6 @@ #include "document-private.h" #include "document.h" #include "document-undo.h" -#include "desktop-handles.h" #include "verbs.h" #include "sp-lpe-item.h" #include "sp-namedview.h" @@ -47,7 +41,6 @@ // For handling un-continuous paths: #include "message-stack.h" #include "inkscape.h" -#include "desktop.h" using Inkscape::DocumentUndo; @@ -64,7 +57,7 @@ LPEBSpline::LPEBSpline(LivePathEffectObject *lpeobject) // initialise your parameters here: //testpointA(_("Test Point A"), _("Test A"), "ptA", &wr, this, //Geom::Point(100,100)), - steps(_("Steps whith CTRL:"), _("Change number of steps whith CTRL pressed"), "steps", &wr, this, 2), + steps(_("Steps with CTRL:"), _("Change number of steps with CTRL pressed"), "steps", &wr, this, 2), ignoreCusp(_("Ignore cusp nodes"), _("Change ignoring cusp nodes"), "ignoreCusp", &wr, this, true), onlySelected(_("Change only selected nodes"), _("Change only selected nodes"), "onlySelected", &wr, this, false), showHelper(_("Show helper paths"), _("Show helper paths"), "showHelper", &wr, this, false), @@ -87,7 +80,7 @@ LPEBSpline::LPEBSpline(LivePathEffectObject *lpeobject) LPEBSpline::~LPEBSpline() {} -void LPEBSpline::doBeforeEffect (SPLPEItem const* lpeitem) +void LPEBSpline::doBeforeEffect (SPLPEItem const* /*lpeitem*/) { if(!hp.empty()){ hp.clear(); @@ -127,12 +120,8 @@ void LPEBSpline::doEffect(SPCurve *curve) Geom::PathVector const original_pathv = curve->get_pathvector(); curve->reset(); double radiusHelperNodes = 6.0; - SPDesktop *desktop = SP_ACTIVE_DESKTOP; - if (desktop){ - radiusHelperNodes /= SP_ACTIVE_DESKTOP->current_zoom(); - SPNamedView *nv = sp_desktop_namedview(desktop); - radiusHelperNodes = Inkscape::Util::Quantity::convert(radiusHelperNodes, "px", nv->doc_units->abbr); - } + radiusHelperNodes /= current_zoom; + radiusHelperNodes = Inkscape::Util::Quantity::convert(radiusHelperNodes, "px", *defaultUnit); for (Geom::PathVector::const_iterator path_it = original_pathv.begin(); path_it != original_pathv.end(); ++path_it) { if (path_it->empty()) @@ -165,16 +154,8 @@ void LPEBSpline::doEffect(SPCurve *curve) curve_endit = path_it->end_open(); } } - //Si la curva está cerrada calculamos el punto donde - //deveria estar el nodo BSpline de cierre/inicio de la curva - //en posible caso de que se cierre con una linea recta creando un nodo - //BSPline nCurve->moveto(curve_it1->initialPoint()); - //Recorremos todos los segmentos menos el último while (curve_it1 != curve_endit) { - //previousPointAt3 = pointAt3; - //Calculamos los puntos que dividirían en tres segmentos iguales el path - //recto de entrada y de salida SPCurve *in = new SPCurve(); in->moveto(curve_it1->initialPoint()); in->lineto(curve_it1->finalPoint()); @@ -260,10 +241,7 @@ void LPEBSpline::doEffect(SPCurve *curve) SBasisHelper = lineHelper->first_segment()->toSBasis(); lineHelper->reset(); delete lineHelper; - //almacenamos el punto del anterior bucle -o el de cierre- que nos hara de - //principio de curva previousNode = node; - //Y este hará de final de curva node = SBasisHelper.valueAt(0.5); Geom::CubicBezier const *cubic2 = dynamic_cast<Geom::CubicBezier const *>(&*curve_it1); if((cubic && are_near((*cubic)[0],(*cubic)[1])) || (cubic2 && are_near((*cubic2)[2],(*cubic2)[3]))) { @@ -274,12 +252,6 @@ void LPEBSpline::doEffect(SPCurve *curve) if(!are_near(node,curve_it1->finalPoint()) && showHelper){ drawHandle(node, radiusHelperNodes); } - //La curva BSpline se forma calculando el centro del segmanto de unión - //de el punto situado en las 2/3 partes de el segmento de entrada - //con el punto situado en la posición 1/3 del segmento de salida - //Estos dos puntos ademas estan posicionados en el lugas correspondiente - //de los manejadores de la curva - //aumentamos los valores para el siguiente paso en el bucle ++curve_it1; ++curve_it2; } @@ -293,7 +265,7 @@ void LPEBSpline::doEffect(SPCurve *curve) } if(showHelper){ Geom::PathVector const pathv = curve->get_pathvector(); - hp.push_back(pathv[0]); + hp.push_back(pathv[0]); } } @@ -314,7 +286,6 @@ LPEBSpline::addCanvasIndicators(SPLPEItem const */*lpeitem*/, std::vector<Geom:: { hp_vec.push_back(hp); } - Gtk::Widget *LPEBSpline::newWidget() { // use manage here, because after deletion of Effect object, others might @@ -332,12 +303,12 @@ Gtk::Widget *LPEBSpline::newWidget() Gtk::Button *defaultWeight = Gtk::manage(new Gtk::Button(Glib::ustring(_("Default weight")))); defaultWeight->signal_clicked() - .connect(sigc::bind<Gtk::Widget *>(sigc::mem_fun(*this, &LPEBSpline::toDefaultWeight), widg)); + .connect(sigc::mem_fun(*this, &LPEBSpline::toDefaultWeight)); buttons->pack_start(*defaultWeight, true, true, 2); Gtk::Button *makeCusp = Gtk::manage(new Gtk::Button(Glib::ustring(_("Make cusp")))); makeCusp->signal_clicked() - .connect(sigc::bind<Gtk::Widget *>(sigc::mem_fun(*this, &LPEBSpline::toMakeCusp), widg)); + .connect(sigc::mem_fun(*this, &LPEBSpline::toMakeCusp)); buttons->pack_start(*makeCusp, true, true, 2); vbox->pack_start(*buttons, true, true, 2); } @@ -381,24 +352,14 @@ Gtk::Widget *LPEBSpline::newWidget() return dynamic_cast<Gtk::Widget *>(vbox); } -void LPEBSpline::toDefaultWeight(Gtk::Widget *widgWeight) +void LPEBSpline::toDefaultWeight() { - weight.param_set_value(defaultStartPower); changeWeight(defaultStartPower); - Gtk::HBox * scalarParameter = dynamic_cast<Gtk::HBox *>(widgWeight); - std::vector< Gtk::Widget* > childList = scalarParameter->get_children(); - Gtk::Entry* entryWidg = dynamic_cast<Gtk::Entry *>(childList[1]); - entryWidg->set_text("defaultStartPower"); } -void LPEBSpline::toMakeCusp(Gtk::Widget *widgWeight) +void LPEBSpline::toMakeCusp() { - weight.param_set_value(noPower); changeWeight(noPower); - Gtk::HBox * scalarParameter = dynamic_cast<Gtk::HBox *>(widgWeight); - std::vector< Gtk::Widget* > childList = scalarParameter->get_children(); - Gtk::Entry* entryWidg = dynamic_cast<Gtk::Entry *>(childList[1]); - entryWidg->set_text("noPower"); } void LPEBSpline::toWeight() @@ -408,91 +369,34 @@ void LPEBSpline::toWeight() void LPEBSpline::changeWeight(double weightValue) { - SPDesktop *desktop = SP_ACTIVE_DESKTOP; - Inkscape::Selection *selection = sp_desktop_selection(desktop); - GSList *items = (GSList *)selection->itemList(); - SPItem *item = (SPItem *)g_slist_nth(items, 0)->data; - SPPath *path = SP_PATH(item); + SPPath *path = SP_PATH(sp_lpe_item); SPCurve *curve = path->get_curve_for_edit(); LPEBSpline::doBSplineFromWidget(curve, weightValue); gchar *str = sp_svg_write_path(curve->get_pathvector()); path->getRepr()->setAttribute("inkscape:original-d", str); - if (INK_IS_NODE_TOOL(desktop->event_context)) { - Inkscape::UI::Tools::NodeTool *nt = INK_NODE_TOOL(desktop->event_context); - nt->desktop->updateNow(); - } - g_free(str); - curve->unref(); - desktop->clearWaitingCursor(); - DocumentUndo::done(sp_desktop_document(desktop), SP_VERB_CONTEXT_LPE, - _("Modified the weight of the BSpline")); -} - -bool LPEBSpline::nodeIsSelected(Geom::Point nodePoint) -{ - using Geom::X; - using Geom::Y; - - if (points.size() > 0) { - for (std::vector<Geom::Point>::iterator i = points.begin(); - i != points.end(); ++i) { - Geom::Point p = *i; - if (Geom::are_near(p, nodePoint, handleCubicGap)) { - return true; - } else { - } - } - } - return false; } void LPEBSpline::doBSplineFromWidget(SPCurve *curve, double weightValue) { using Geom::X; using Geom::Y; - SPDesktop *desktop = SP_ACTIVE_DESKTOP; - if (INK_IS_NODE_TOOL(desktop->event_context)) { - Inkscape::UI::Tools::NodeTool *nt = INK_NODE_TOOL(desktop->event_context); - Inkscape::UI::ControlPointSelection::Set &selection = - nt->_selected_nodes->allPoints(); - points.clear(); - std::vector<Geom::Point>::iterator pbegin; - for (Inkscape::UI::ControlPointSelection::Set::iterator i = - selection.begin(); - i != selection.end(); ++i) { - if ((*i)->selected()) { - Inkscape::UI::Node *n = dynamic_cast<Inkscape::UI::Node *>(*i); - pbegin = points.begin(); - points.insert(pbegin, desktop->doc2dt(n->position())); - } - } - } - //bool hasNodesSelected = LPEBspline::hasNodesSelected(); + 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(); curve->reset(); - //Recorremos todos los paths a los que queremos aplicar el efecto, hasta el - //penúltimo for (Geom::PathVector::const_iterator path_it = original_pathv.begin(); path_it != original_pathv.end(); ++path_it) { - //Si está vacío... - if (path_it->empty()) + + 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 - //Creamos las lineas rectas que unen todos los puntos del trazado y donde se - //calcularán - //los puntos clave para los manejadores. - //Esto hace que la curva BSpline no pierda su condición aunque se trasladen - //dichos manejadores + } + Geom::Path::const_iterator curve_it1 = path_it->begin(); + Geom::Path::const_iterator curve_it2 = ++(path_it->begin()); + Geom::Path::const_iterator curve_endit = path_it->end_default(); + SPCurve *nCurve = new SPCurve(); Geom::Point pointAt0(0, 0); Geom::Point pointAt1(0, 0); @@ -515,16 +419,8 @@ void LPEBSpline::doBSplineFromWidget(SPCurve *curve, double weightValue) curve_endit = path_it->end_open(); } } - //Si la curva está cerrada calculamos el punto donde - //deveria estar el nodo BSpline de cierre/inicio de la curva - //en posible caso de que se cierre con una linea recta creando un nodo - //BSPline nCurve->moveto(curve_it1->initialPoint()); - //Recorremos todos los segmentos menos el último while (curve_it1 != curve_endit) { - //previousPointAt3 = pointAt3; - //Calculamos los puntos que dividirían en tres segmentos iguales el path - //recto de entrada y de salida SPCurve *in = new SPCurve(); in->moveto(curve_it1->initialPoint()); in->lineto(curve_it1->finalPoint()); @@ -572,7 +468,7 @@ void LPEBSpline::doBSplineFromWidget(SPCurve *curve, double weightValue) } else { if (cubic) { if (!ignoreCusp || !Geom::are_near((*cubic)[1], pointAt0)) { - if (nodeIsSelected(pointAt0)) { + if (isNodePointSelected(pointAt0)) { pointAt1 = SBasisIn.valueAt(weightValue); if (weightValue != noPower) { pointAt1 = @@ -585,7 +481,7 @@ void LPEBSpline::doBSplineFromWidget(SPCurve *curve, double weightValue) pointAt1 = in->first_segment()->initialPoint(); } if (!ignoreCusp || !Geom::are_near((*cubic)[2], pointAt3)) { - if (nodeIsSelected(pointAt3)) { + if (isNodePointSelected(pointAt3)) { pointAt2 = SBasisIn.valueAt(1 - weightValue); if (weightValue != noPower) { pointAt2 = @@ -599,14 +495,14 @@ void LPEBSpline::doBSplineFromWidget(SPCurve *curve, double weightValue) } } else { if (!ignoreCusp && weightValue != noPower) { - if (nodeIsSelected(pointAt0)) { + if (isNodePointSelected(pointAt0)) { pointAt1 = SBasisIn.valueAt(weightValue); pointAt1 = Geom::Point(pointAt1[X] + handleCubicGap, pointAt1[Y] + handleCubicGap); } else { pointAt1 = in->first_segment()->initialPoint(); } - if (nodeIsSelected(pointAt3)) { + if (isNodePointSelected(pointAt3)) { pointAt2 = SBasisIn.valueAt(weightValue); pointAt2 = Geom::Point(pointAt2[X] + handleCubicGap, pointAt2[Y] + handleCubicGap); @@ -621,14 +517,7 @@ void LPEBSpline::doBSplineFromWidget(SPCurve *curve, double weightValue) } in->reset(); delete in; - //La curva BSpline se forma calculando el centro del segmanto de unión - //de el punto situado en las 2/3 partes de el segmento de entrada - //con el punto situado en la posición 1/3 del segmento de salida - //Estos dos puntos ademas estan posicionados en el lugas correspondiente - //de - //los manejadores de la curva nCurve->curveto(pointAt1, pointAt2, pointAt3); - //aumentamos los valores para el siguiente paso en el bucle ++curve_it1; ++curve_it2; } @@ -638,7 +527,6 @@ void LPEBSpline::doBSplineFromWidget(SPCurve *curve, double weightValue) } else { nCurve->move_endpoints(path_it->begin()->initialPoint(), pointAt3); } - //y cerramos la curva if (path_it->closed()) { nCurve->closepath_current(); } diff --git a/src/live_effects/lpe-bspline.h b/src/live_effects/lpe-bspline.h index 169658b94..8751a5720 100644 --- a/src/live_effects/lpe-bspline.h +++ b/src/live_effects/lpe-bspline.h @@ -26,20 +26,18 @@ public: virtual void doEffect(SPCurve *curve); virtual void doBeforeEffect (SPLPEItem const* lpeitem); void drawHandle(Geom::Point p, double radiusHelperNodes); - void addCanvasIndicators(SPLPEItem const */*lpeitem*/, std::vector<Geom::PathVector> &hp_vec); virtual void doBSplineFromWidget(SPCurve *curve, double value); - virtual bool nodeIsSelected(Geom::Point nodePoint); + void addCanvasIndicators(SPLPEItem const */*lpeitem*/, std::vector<Geom::PathVector> &hp_vec); virtual Gtk::Widget *newWidget(); virtual void changeWeight(double weightValue); - virtual void toDefaultWeight(Gtk::Widget *widgWeight); - virtual void toMakeCusp(Gtk::Widget *widgWeight); + virtual void toDefaultWeight(); + virtual void toMakeCusp(); virtual void toWeight(); // TODO make this private ScalarParam steps; private: - std::vector<Geom::Point> points; BoolParam ignoreCusp; BoolParam onlySelected; BoolParam showHelper; diff --git a/src/live_effects/lpe-fillet-chamfer.cpp b/src/live_effects/lpe-fillet-chamfer.cpp index a3964f553..c491ea858 100644 --- a/src/live_effects/lpe-fillet-chamfer.cpp +++ b/src/live_effects/lpe-fillet-chamfer.cpp @@ -28,12 +28,7 @@ #include "live_effects/parameter/filletchamferpointarray.h" // for programmatically updating knots -#include "selection.h" #include "ui/tools-switch.h" -#include "ui/tool/control-point-selection.h" -#include "ui/tool/selectable-control-point.h" -#include "ui/tool/node.h" -#include "ui/tools/node-tool.h" #include <util/units.h> // TODO due to internal breakage in glibmm headers, this must be last: @@ -65,12 +60,15 @@ LPEFilletChamfer::LPEFilletChamfer(LivePathEffectObject *lpeobject) : unit(_("Unit"), _("Unit"), "unit", &wr, this), method(_("Method"), _("Fillets methods"), "method", FMConverter, &wr, this, FM_AUTO), radius(_("Radius (unit or %)"), _("Radius, in unit or %"), "radius", &wr, this, 0.), + chamfer_steps(_("Chamfer steps"), _("Chamfer steps"), "chamfer_steps", &wr, this, 0), + helper_size(_("Helper size with direction"), _("Helper size with direction"), "helper_size", &wr, this, 0) { registerParameter(&fillet_chamfer_values); registerParameter(&unit); registerParameter(&method); registerParameter(&radius); + registerParameter(&chamfer_steps); registerParameter(&helper_size); registerParameter(&flexible); registerParameter(&use_knot_distance); @@ -81,9 +79,13 @@ LPEFilletChamfer::LPEFilletChamfer(LivePathEffectObject *lpeobject) : radius.param_set_range(0., infinity()); radius.param_set_increments(1, 1); radius.param_set_digits(4); + chamfer_steps.param_set_range(0, infinity()); + chamfer_steps.param_set_increments(1, 1); + chamfer_steps.param_set_digits(0); helper_size.param_set_range(0, infinity()); helper_size.param_set_increments(5, 5); helper_size.param_set_digits(0); + fillet_chamfer_values.set_chamfer_steps(3); } LPEFilletChamfer::~LPEFilletChamfer() {} @@ -112,6 +114,16 @@ Gtk::Widget *LPEFilletChamfer::newWidget() Gtk::Entry *entryWidg = dynamic_cast<Gtk::Entry *>(childList[1]); entryWidg->set_width_chars(6); } + } else if (param->param_key == "chamfer_steps") { + Inkscape::UI::Widget::Scalar *widgRegistered = Gtk::manage(dynamic_cast<Inkscape::UI::Widget::Scalar *>(widg)); + widgRegistered->signal_value_changed().connect(sigc::mem_fun(*this, &LPEFilletChamfer::chamfer)); + widg = widgRegistered; + 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(3); + } } else if (param->param_key == "flexible") { Gtk::CheckButton *widgRegistered = Gtk::manage(dynamic_cast<Gtk::CheckButton *>(widg)); widgRegistered->signal_clicked().connect(sigc::mem_fun(*this, &LPEFilletChamfer::toggleFlexFixed)); @@ -142,26 +154,20 @@ Gtk::Widget *LPEFilletChamfer::newWidget() ++it; } - Gtk::HBox *filletButtonsContainer = Gtk::manage(new Gtk::HBox(true, 0)); + Gtk::VBox *buttonsContainer = Gtk::manage(new Gtk::VBox(true, 0)); Gtk::Button *fillet = Gtk::manage(new Gtk::Button(Glib::ustring(_("Fillet")))); fillet->signal_clicked().connect(sigc::mem_fun(*this, &LPEFilletChamfer::fillet)); - filletButtonsContainer->pack_start(*fillet, true, true, 2); + buttonsContainer->pack_start(*fillet, true, true, 2); Gtk::Button *inverse = Gtk::manage(new Gtk::Button(Glib::ustring(_("Inverse fillet")))); inverse->signal_clicked().connect(sigc::mem_fun(*this, &LPEFilletChamfer::inverse)); - filletButtonsContainer->pack_start(*inverse, true, true, 2); + buttonsContainer->pack_start(*inverse, true, true, 2); - Gtk::HBox *chamferButtonsContainer = Gtk::manage(new Gtk::HBox(true, 0)); Gtk::Button *chamfer = Gtk::manage(new Gtk::Button(Glib::ustring(_("Chamfer")))); chamfer->signal_clicked().connect(sigc::mem_fun(*this, &LPEFilletChamfer::chamfer)); + buttonsContainer->pack_start(*chamfer, true, true, 2); - chamferButtonsContainer->pack_start(*chamfer, true, true, 2); - Gtk::Button *doubleChamfer = Gtk::manage(new Gtk::Button(Glib::ustring(_("Double chamfer")))); - doubleChamfer->signal_clicked().connect(sigc::mem_fun(*this, &LPEFilletChamfer::doubleChamfer)); - chamferButtonsContainer->pack_start(*doubleChamfer, true, true, 2); - - vbox->pack_start(*filletButtonsContainer, true, true, 2); - vbox->pack_start(*chamferButtonsContainer, true, true, 2); + vbox->pack_start(*buttonsContainer, true, true, 2); return vbox; } @@ -212,8 +218,7 @@ void LPEFilletChamfer::updateFillet() { double power = 0; if (!flexible) { - Inkscape::Util::Unit const *doc_units = SP_ACTIVE_DESKTOP->namedview->doc_units; - power = Inkscape::Util::Quantity::convert(radius, unit.get_abbreviation(), doc_units->abbr) * -1; + power = Inkscape::Util::Quantity::convert(radius, unit.get_abbreviation(), *defaultUnit) * -1; } else { power = radius; } @@ -235,14 +240,9 @@ void LPEFilletChamfer::inverse() void LPEFilletChamfer::chamfer() { + fillet_chamfer_values.set_chamfer_steps(chamfer_steps + 3); Piecewise<D2<SBasis> > const &pwd2 = fillet_chamfer_values.get_pwd2(); - doChangeType(path_from_piecewise(pwd2, tolerance), 3); -} - -void LPEFilletChamfer::doubleChamfer() -{ - Piecewise<D2<SBasis> > const &pwd2 = fillet_chamfer_values.get_pwd2(); - doChangeType(path_from_piecewise(pwd2, tolerance), 4); + doChangeType(path_from_piecewise(pwd2, tolerance), chamfer_steps + 3); } void LPEFilletChamfer::refreshKnots() @@ -256,35 +256,8 @@ void LPEFilletChamfer::refreshKnots() } } -bool LPEFilletChamfer::nodeIsSelected(Geom::Point nodePoint, std::vector<Geom::Point> point) -{ - if (point.size() > 0) { - for (std::vector<Geom::Point>::iterator i = point.begin(); i != point.end(); - ++i) { - Geom::Point p = *i; - if (Geom::are_near(p, nodePoint, 2)) { - return true; - } - } - } - return false; -} void LPEFilletChamfer::doUpdateFillet(std::vector<Geom::Path> const& original_pathv, double power) { - std::vector<Geom::Point> point; - SPDesktop *desktop = SP_ACTIVE_DESKTOP; - if (INK_IS_NODE_TOOL(desktop->event_context)) { - Inkscape::UI::Tools::NodeTool *nodeTool = INK_NODE_TOOL(desktop->event_context); - Inkscape::UI::ControlPointSelection::Set &selection = nodeTool->_selected_nodes->allPoints(); - std::vector<Geom::Point>::iterator pBegin; - for (Inkscape::UI::ControlPointSelection::Set::iterator i = selection.begin(); i != selection.end(); ++i) { - if ((*i)->selected()) { - Inkscape::UI::Node *n = dynamic_cast<Inkscape::UI::Node *>(*i); - pBegin = point.begin(); - point.insert(pBegin, desktop->doc2dt(n->position())); - } - } - } std::vector<Point> filletChamferData = fillet_chamfer_values.data(); std::vector<Geom::Point> result; std::vector<Geom::Path> original_pathv_processed = pathv_to_linear_and_cubic_beziers(original_pathv); @@ -319,7 +292,7 @@ void LPEFilletChamfer::doUpdateFillet(std::vector<Geom::Path> const& original_pa if (filletChamferData[counter][Y] == 0) { powerend = filletChamferData[counter][X]; } - if (only_selected && !nodeIsSelected(curve_it1->initialPoint(), point)) { + if (only_selected && !isNodePointSelected(curve_it1->initialPoint())) { powerend = filletChamferData[counter][X]; } result.push_back(Point(powerend, filletChamferData[counter][Y])); @@ -333,24 +306,6 @@ void LPEFilletChamfer::doUpdateFillet(std::vector<Geom::Path> const& original_pa void LPEFilletChamfer::doChangeType(std::vector<Geom::Path> const& original_pathv, int type) { - std::vector<Geom::Point> point; - SPDesktop *desktop = SP_ACTIVE_DESKTOP; - if (INK_IS_NODE_TOOL(desktop->event_context)) { - Inkscape::UI::Tools::NodeTool *nodeTool = - INK_NODE_TOOL(desktop->event_context); - Inkscape::UI::ControlPointSelection::Set &selection = - nodeTool->_selected_nodes->allPoints(); - std::vector<Geom::Point>::iterator pBegin; - for (Inkscape::UI::ControlPointSelection::Set::iterator i = - selection.begin(); - i != selection.end(); ++i) { - if ((*i)->selected()) { - Inkscape::UI::Node *n = dynamic_cast<Inkscape::UI::Node *>(*i); - pBegin = point.begin(); - point.insert(pBegin, desktop->doc2dt(n->position())); - } - } - } std::vector<Point> filletChamferData = fillet_chamfer_values.data(); std::vector<Geom::Point> result; std::vector<Geom::Path> original_pathv_processed = pathv_to_linear_and_cubic_beziers(original_pathv); @@ -373,9 +328,8 @@ void LPEFilletChamfer::doChangeType(std::vector<Geom::Path> const& original_path bool toggle = true; if (filletChamferData[counter][Y] == 0 || (ignore_radius_0 && (filletChamferData[counter][X] == 0 || - filletChamferData[counter][X] == counter)) || - (only_selected && - !nodeIsSelected(curve_it1->initialPoint(), point))) { + filletChamferData[counter][X] == counter)) || + (only_selected && !isNodePointSelected(curve_it1->initialPoint()))) { toggle = false; } if (toggle) { @@ -597,11 +551,19 @@ LPEFilletChamfer::doEffect_path(std::vector<Geom::Path> const &path_in) } else { type = std::abs(filletChamferData[counter + 1][Y]); } - if (type == 3 || type == 4) { - if (type == 4) { - Geom::Point central = middle_point(startArcPoint, endArcPoint); - LineSegment chamferCenter(central, curve_it1->finalPoint()); - path_out.appendNew<Geom::LineSegment>(chamferCenter.pointAt(0.5)); + if (type >= 3) { + unsigned int chamferSubs = type-2; + Geom::Path path_chamfer; + path_chamfer.start(path_out.finalPoint()); + if((is_straight_curve(*curve_it1) && is_straight_curve(*curve_it2Fixed) && method != FM_BEZIER )|| method == FM_ARC){ + path_chamfer.appendNew<SVGEllipticalArc>(rx, ry, angleArc, 0, ccwToggle, endArcPoint); + } else { + path_chamfer.appendNew<Geom::CubicBezier>(handle1, handle2, endArcPoint); + } + double chamfer_stepsTime = 1.0/chamferSubs; + for(unsigned int i = 1; i < chamferSubs; i++){ + Geom::Point chamferStep = path_chamfer.pointAt(chamfer_stepsTime * i); + path_out.appendNew<Geom::LineSegment>(chamferStep); } path_out.appendNew<Geom::LineSegment>(endArcPoint); } else if (type == 2) { diff --git a/src/live_effects/lpe-fillet-chamfer.h b/src/live_effects/lpe-fillet-chamfer.h index 873684101..e3589197c 100644 --- a/src/live_effects/lpe-fillet-chamfer.h +++ b/src/live_effects/lpe-fillet-chamfer.h @@ -57,12 +57,10 @@ public: void toggleFlexFixed(); void chamfer(); void fillet(); - void doubleChamfer(); void inverse(); void updateFillet(); void doUpdateFillet(std::vector<Geom::Path> const& original_pathv, double power); void doChangeType(std::vector<Geom::Path> const& original_pathv, int type); - bool nodeIsSelected(Geom::Point nodePoint, std::vector<Geom::Point> points); void refreshKnots(); FilletChamferPointArrayParam fillet_chamfer_values; @@ -77,6 +75,7 @@ private: UnitParam unit; EnumParam<FilletMethod> method; ScalarParam radius; + ScalarParam chamfer_steps; ScalarParam helper_size; LPEFilletChamfer(const LPEFilletChamfer &); diff --git a/src/live_effects/lpe-lattice2.cpp b/src/live_effects/lpe-lattice2.cpp index 7036b0cfa..e1cd91340 100644 --- a/src/live_effects/lpe-lattice2.cpp +++ b/src/live_effects/lpe-lattice2.cpp @@ -394,7 +394,7 @@ LPELattice2::resetGrid() 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(); + SPDesktop * desktop = SP_ACTIVE_DESKTOP; tools_switch(desktop, TOOLS_SELECT); tools_switch(desktop, TOOLS_NODES); } diff --git a/src/live_effects/lpe-perspective-envelope.cpp b/src/live_effects/lpe-perspective-envelope.cpp index c070cf17b..b5ef26e2f 100644 --- a/src/live_effects/lpe-perspective-envelope.cpp +++ b/src/live_effects/lpe-perspective-envelope.cpp @@ -193,8 +193,8 @@ LPEPerspectiveEnvelope::project_point(Geom::Point p){ double height = boundingbox_Y.extent(); double delta_x = boundingbox_X.min() - p[X]; double delta_y = boundingbox_Y.max() - p[Y]; - Geom::Coord xratio = (delta_x * sgn(delta_x)) / width; - Geom::Coord yratio = (delta_y * sgn(delta_y)) / height; + Geom::Coord xratio = (delta_x * -1) / width; + Geom::Coord yratio = delta_y / height; Geom::Line* horiz = new Geom::Line(); Geom::Line* vert = new Geom::Line(); vert->setPoints (pointAtRatio(yratio,Down_Left_Point,Up_Left_Point),pointAtRatio(yratio,Down_Right_Point,Up_Right_Point)); @@ -337,7 +337,7 @@ LPEPerspectiveEnvelope::resetGrid() Down_Left_Point.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(); + SPDesktop * desktop = SP_ACTIVE_DESKTOP; tools_switch(desktop, TOOLS_SELECT); tools_switch(desktop, TOOLS_NODES); } diff --git a/src/live_effects/lpe-powerstroke.cpp b/src/live_effects/lpe-powerstroke.cpp index 03a10807a..f7fe9592d 100644 --- a/src/live_effects/lpe-powerstroke.cpp +++ b/src/live_effects/lpe-powerstroke.cpp @@ -277,7 +277,7 @@ LPEPowerStroke::doOnApply(SPLPEItem const* lpeitem) double width = (lpeitem && lpeitem->style) ? lpeitem->style->stroke_width.computed / 2 : 1.; SPCSSAttr *css = sp_repr_css_attr_new (); - if (true) { + if (lpeitem->style) { if (lpeitem->style->stroke.isPaintserver()) { SPPaintServer * server = lpeitem->style->getStrokePaintServer(); if (server) { diff --git a/src/live_effects/lpe-roughen.cpp b/src/live_effects/lpe-roughen.cpp index ffd5433bf..07d9e63e8 100644 --- a/src/live_effects/lpe-roughen.cpp +++ b/src/live_effects/lpe-roughen.cpp @@ -14,12 +14,13 @@ */ #include <gtkmm.h> - +#include "desktop.h" #include "live_effects/lpe-roughen.h" #include "display/curve.h" #include "live_effects/parameter/parameter.h" #include "helper/geom.h" #include <glibmm/i18n.h> +#include <util/units.h> #include <cmath> namespace Inkscape { @@ -46,6 +47,8 @@ LPERoughen::LPERoughen(LivePathEffectObject *lpeobject) "displaceX", &wr, this, 10.), displaceY(_("Max. displacement in Y"), _("Max. displacement in Y"), "displaceY", &wr, this, 10.), + globalRandomize(_("Global randomize"), _("Global randomize"), + "globalRandomize", &wr, this, 1.), shiftNodes(_("Shift nodes"), _("Shift nodes"), "shiftNodes", &wr, this, true), shiftNodeHandles(_("Shift node handles"), _("Shift node handles"), @@ -57,10 +60,12 @@ LPERoughen::LPERoughen(LivePathEffectObject *lpeobject) registerParameter(&segments); registerParameter(&displaceX); registerParameter(&displaceY); + registerParameter(&globalRandomize); registerParameter(&shiftNodes); registerParameter(&shiftNodeHandles); displaceX.param_set_range(0., Geom::infinity()); displaceY.param_set_range(0., Geom::infinity()); + globalRandomize.param_set_range(0., Geom::infinity()); maxSegmentSize.param_set_range(0., Geom::infinity()); maxSegmentSize.param_set_increments(1, 1); maxSegmentSize.param_set_digits(1); @@ -75,6 +80,7 @@ void LPERoughen::doBeforeEffect(SPLPEItem const *lpeitem) { displaceX.resetRandomizer(); displaceY.resetRandomizer(); + globalRandomize.resetRandomizer(); srand(1); SPLPEItem * item = const_cast<SPLPEItem*>(lpeitem); item->apply_to_clippath(item); @@ -118,6 +124,15 @@ Gtk::Widget *LPERoughen::newWidget() vbox->pack_start(*Gtk::manage(new Gtk::HSeparator()), Gtk::PACK_EXPAND_WIDGET); } + if (param->param_key == "globalRandomize") { + Gtk::Label *displaceXLabel = Gtk::manage(new Gtk::Label( + Glib::ustring(_("<b>Extra roughen</b> Add a extra layer of rough")), + Gtk::ALIGN_START)); + displaceXLabel->set_use_markup(true); + vbox->pack_start(*displaceXLabel, false, false, 2); + vbox->pack_start(*Gtk::manage(new Gtk::HSeparator()), + Gtk::PACK_EXPAND_WIDGET); + } Glib::ustring *tip = param->param_getTooltip(); if (widg) { vbox->pack_start(*widg, true, true, 2); @@ -145,10 +160,11 @@ double LPERoughen::sign(double randNumber) Geom::Point LPERoughen::randomize() { + Inkscape::Util::Unit const *doc_units = SP_ACTIVE_DESKTOP->namedview->doc_units; double displaceXParsed = Inkscape::Util::Quantity::convert( - displaceX, unit.get_abbreviation(), "px"); + displaceX * globalRandomize, unit.get_abbreviation(), doc_units->abbr); double displaceYParsed = Inkscape::Util::Quantity::convert( - displaceY, unit.get_abbreviation(), "px"); + displaceY * globalRandomize, unit.get_abbreviation(), doc_units->abbr); Geom::Point output = Geom::Point(sign(displaceXParsed), sign(displaceYParsed)); return output; @@ -159,6 +175,7 @@ void LPERoughen::doEffect(SPCurve *curve) Geom::PathVector const original_pathv = pathv_to_linear_and_cubic_beziers(curve->get_pathvector()); curve->reset(); + Inkscape::Util::Unit const *doc_units = SP_ACTIVE_DESKTOP->namedview->doc_units; for (Geom::PathVector::const_iterator path_it = original_pathv.begin(); path_it != original_pathv.end(); ++path_it) { if (path_it->empty()) @@ -185,6 +202,7 @@ void LPERoughen::doEffect(SPCurve *curve) Geom::Point A1(0, 0); Geom::Point A2(0, 0); Geom::Point A3(0, 0); + bool first = true; while (curve_it1 != curve_endit) { Geom::CubicBezier const *cubic = NULL; A0 = curve_it1->initialPoint(); @@ -194,7 +212,7 @@ void LPERoughen::doEffect(SPCurve *curve) cubic = dynamic_cast<Geom::CubicBezier const *>(&*curve_it1); if (cubic) { A1 = (*cubic)[1]; - if (shiftNodes) { + if (shiftNodes && first) { A1 = (*cubic)[1] + initialMove; } A2 = (*cubic)[2]; @@ -203,7 +221,7 @@ void LPERoughen::doEffect(SPCurve *curve) nCurve->lineto(A3); } double length = Inkscape::Util::Quantity::convert( - curve_it1->length(0.001), "px", unit.get_abbreviation()); + curve_it1->length(0.001), doc_units->abbr, unit.get_abbreviation()); std::size_t splits = 0; if (method == DM_SEGMENTS) { splits = segments; @@ -232,6 +250,7 @@ void LPERoughen::doEffect(SPCurve *curve) if(curve_it2 != curve_endit) { ++curve_it2; } + first = false; } if (path_it->closed()) { nCurve->closepath_current(); diff --git a/src/live_effects/lpe-roughen.h b/src/live_effects/lpe-roughen.h index d5ec726bd..74331f1ef 100644 --- a/src/live_effects/lpe-roughen.h +++ b/src/live_effects/lpe-roughen.h @@ -51,8 +51,10 @@ private: ScalarParam segments; RandomParam displaceX; RandomParam displaceY; + RandomParam globalRandomize; BoolParam shiftNodes; BoolParam shiftNodeHandles; + LPERoughen(const LPERoughen &); LPERoughen &operator=(const LPERoughen &); diff --git a/src/live_effects/lpe-simplify.cpp b/src/live_effects/lpe-simplify.cpp index c191fbbe6..2b2efb1a9 100644 --- a/src/live_effects/lpe-simplify.cpp +++ b/src/live_effects/lpe-simplify.cpp @@ -157,8 +157,8 @@ LPESimplify::doEffect(SPCurve *curve) { 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; + SPDesktop* desktop = SP_ACTIVE_DESKTOP; + if(desktop && INK_IS_NODE_TOOL(desktop->event_context)){ Inkscape::UI::Tools::NodeTool *nt = static_cast<Inkscape::UI::Tools::NodeTool*>(desktop->event_context); nt->update_helperpath(); } diff --git a/src/live_effects/parameter/filletchamferpointarray.cpp b/src/live_effects/parameter/filletchamferpointarray.cpp index db24a9735..31d996ad0 100644 --- a/src/live_effects/parameter/filletchamferpointarray.cpp +++ b/src/live_effects/parameter/filletchamferpointarray.cpp @@ -359,6 +359,11 @@ void FilletChamferPointArrayParam::set_helper_size(int hs) helper_size = hs; } +void FilletChamferPointArrayParam::set_chamfer_steps(int value_chamfer_steps) +{ + chamfer_steps = value_chamfer_steps; +} + void FilletChamferPointArrayParam::set_use_distance(bool use_knot_distance ) { use_distance = use_knot_distance; @@ -712,8 +717,8 @@ FilletChamferPointArrayParamKnotHolderEntity( : _pparam(p), _index(index) {} void FilletChamferPointArrayParamKnotHolderEntity::knot_set(Point const &p, - Point const &origin, - guint state) + Point const &/*origin*/, + guint /*state*/) { using namespace Geom; @@ -766,15 +771,24 @@ void FilletChamferPointArrayParamKnotHolderEntity::knot_click(guint state) sp_lpe_item_update_patheffect(SP_LPE_ITEM(item), false, false); }else{ using namespace Geom; - double type = _pparam->_vector.at(_index)[Y] + 1; - if (type > 4) { - type = 1; + int type = (int)_pparam->_vector.at(_index)[Y]; + + switch(type){ + case 1: + type = 2; + break; + case 2: + type = _pparam->chamfer_steps; + break; + default: + type = 1; + break; } - _pparam->_vector.at(_index) = Point(_pparam->_vector.at(_index)[X], type); + _pparam->_vector.at(_index) = Point(_pparam->_vector.at(_index)[X], (double)type); _pparam->param_set_and_write_new_value(_pparam->_vector); sp_lpe_item_update_patheffect(SP_LPE_ITEM(item), false, false); const gchar *tip; - if (type == 3) { + if (type >= 3) { tip = _("<b>Chamfer</b>: <b>Ctrl+Click</b> toogle type, " "<b>Shift+Click</b> open dialog, " "<b>Ctrl+Alt+Click</b> reset"); @@ -782,12 +796,8 @@ void FilletChamferPointArrayParamKnotHolderEntity::knot_click(guint state) tip = _("<b>Inverse Fillet</b>: <b>Ctrl+Click</b> toogle type, " "<b>Shift+Click</b> open dialog, " "<b>Ctrl+Alt+Click</b> reset"); - } else if (type == 1) { - tip = _("<b>Fillet</b>: <b>Ctrl+Click</b> toogle type, " - "<b>Shift+Click</b> open dialog, " - "<b>Ctrl+Alt+Click</b> reset"); } else { - tip = _("<b>Double Chamfer</b>: <b>Ctrl+Click</b> toogle type, " + tip = _("<b>Fillet</b>: <b>Ctrl+Click</b> toogle type, " "<b>Shift+Click</b> open dialog, " "<b>Ctrl+Alt+Click</b> reset"); } @@ -835,7 +845,7 @@ void FilletChamferPointArrayParam::addKnotHolderEntities(KnotHolder *knotholder, continue; } const gchar *tip; - if (_vector[i][Y] == 3) { + if (_vector[i][Y] >= 3) { tip = _("<b>Chamfer</b>: <b>Ctrl+Click</b> toogle type, " "<b>Shift+Click</b> open dialog, " "<b>Ctrl+Alt+Click</b> reset"); @@ -843,12 +853,8 @@ void FilletChamferPointArrayParam::addKnotHolderEntities(KnotHolder *knotholder, tip = _("<b>Inverse Fillet</b>: <b>Ctrl+Click</b> toogle type, " "<b>Shift+Click</b> open dialog, " "<b>Ctrl+Alt+Click</b> reset"); - } else if (_vector[i][Y] == 1) { - tip = _("<b>Fillet</b>: <b>Ctrl+Click</b> toogle type, " - "<b>Shift+Click</b> open dialog, " - "<b>Ctrl+Alt+Click</b> reset"); } else { - tip = _("<b>Double Chamfer</b>: <b>Ctrl+Click</b> toogle type, " + tip = _("<b>Fillet</b>: <b>Ctrl+Click</b> toogle type, " "<b>Shift+Click</b> open dialog, " "<b>Ctrl+Alt+Click</b> reset"); } diff --git a/src/live_effects/parameter/filletchamferpointarray.h b/src/live_effects/parameter/filletchamferpointarray.h index a1fa698ae..1dd31d6d4 100644 --- a/src/live_effects/parameter/filletchamferpointarray.h +++ b/src/live_effects/parameter/filletchamferpointarray.h @@ -52,6 +52,7 @@ public: std::vector<double> get_times(int index, std::vector<Geom::Path> subpaths, bool last); virtual void set_helper_size(int hs); virtual void set_use_distance(bool use_knot_distance); + virtual void set_chamfer_steps(int value_chamfer_steps); virtual void set_unit(const gchar *abbr); virtual void addCanvasIndicators(SPLPEItem const *lpeitem, std::vector<Geom::PathVector> &hp_vec); @@ -85,6 +86,7 @@ private: SPKnotModeType knot_mode; guint32 knot_color; int helper_size; + int chamfer_steps; bool use_distance; const gchar *unit; Geom::PathVector hp; diff --git a/src/live_effects/parameter/parameter.cpp b/src/live_effects/parameter/parameter.cpp index 7a2fd9769..beb750404 100644 --- a/src/live_effects/parameter/parameter.cpp +++ b/src/live_effects/parameter/parameter.cpp @@ -47,7 +47,7 @@ Parameter::param_write_to_repr(const char * svgd) // in gtk3, it is an issue: it allocates widget size for the maxmium // value you pass to it, leading to some insane lengths. // If you need this to be more, please be conservative about it. -const double SCALARPARAM_G_MAXDOUBLE = 10000000000; +const double SCALARPARAM_G_MAXDOUBLE = 10000000000.0; // TODO fixme: using an arbitrary large number as a magic value seems fragile. void Parameter::write_to_SVG(void) { diff --git a/src/main.cpp b/src/main.cpp index a60ed1f25..06c0d4873 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -322,7 +322,7 @@ struct poptOption options[] = { {"export-dpi", 'd', POPT_ARG_STRING, &sp_export_dpi, SP_ARG_EXPORT_DPI, - N_("Resolution for exporting to bitmap and for rasterization of filters in PS/EPS/PDF (default 90)"), + N_("Resolution for exporting to bitmap and for rasterization of filters in PS/EPS/PDF (default 96)"), N_("DPI")}, {"export-area", 'a', @@ -1738,12 +1738,12 @@ static int do_export_ps_pdf(SPDocument* doc, gchar const* uri, char const* mime) } else { (*i)->set_param_bool("blurToBitmap", TRUE); - gdouble dpi = 90.0; + gdouble dpi = 96.0; if (sp_export_dpi) { dpi = atof(sp_export_dpi); if ((dpi < 1) || (dpi > 10000.0)) { - g_warning("DPI value %s out of range [1 - 10000]. Using 90 dpi instead.", sp_export_dpi); - dpi = 90; + g_warning("DPI value %s out of range [1 - 10000]. Using 96 dpi instead.", sp_export_dpi); + dpi = 96; } } diff --git a/src/selection-chemistry.cpp b/src/selection-chemistry.cpp index c81646d6c..b4f7ebdd7 100644 --- a/src/selection-chemistry.cpp +++ b/src/selection-chemistry.cpp @@ -1198,6 +1198,9 @@ take_style_from_item(SPObject *object) } } + // Remove black-listed properties (those that should not be used in a default style) + css = sp_css_attr_unset_blacklist(css); + if (!(dynamic_cast<SPText *>(object) || dynamic_cast<SPTSpan *>(object) || dynamic_cast<SPTRef *>(object) || dynamic_cast<SPString *>(object))) { // do not copy text properties from non-text objects, it's confusing css = sp_css_attr_unset_text(css); @@ -3661,7 +3664,7 @@ void sp_selection_create_bitmap_copy(SPDesktop *desktop) if (hint_xdpi != 0) { res = hint_xdpi; } else { - // if all else fails, take the default 90 dpi + // if all else fails, take the default 96 dpi res = Inkscape::Util::Quantity::convert(1, "in", "px"); } } @@ -3709,7 +3712,7 @@ void sp_selection_create_bitmap_copy(SPDesktop *desktop) double shift_x = bbox->min()[Geom::X]; double shift_y = bbox->max()[Geom::Y]; - if (res == Inkscape::Util::Quantity::convert(1, "in", "px")) { // for default 90 dpi, snap it to pixel grid + if (res == Inkscape::Util::Quantity::convert(1, "in", "px")) { // for default 96 dpi, snap it to pixel grid shift_x = round(shift_x); shift_y = -round(-shift_y); // this gets correct rounding despite coordinate inversion, remove the negations when the inversion is gone } @@ -3744,7 +3747,7 @@ void sp_selection_create_bitmap_copy(SPDesktop *desktop) // TODO: avoid unnecessary roundtrip between data URI and decoded pixbuf Inkscape::XML::Node * repr = xml_doc->createElement("svg:image"); sp_embed_image(repr, pb); - if (res == Inkscape::Util::Quantity::convert(1, "in", "px")) { // for default 90 dpi, snap it to pixel grid + if (res == Inkscape::Util::Quantity::convert(1, "in", "px")) { // for default 96 dpi, snap it to pixel grid sp_repr_set_svg_double(repr, "width", width); sp_repr_set_svg_double(repr, "height", height); } else { diff --git a/src/sp-filter.cpp b/src/sp-filter.cpp index 9a184952c..9cb33a6f3 100644 --- a/src/sp-filter.cpp +++ b/src/sp-filter.cpp @@ -465,6 +465,10 @@ int sp_filter_set_image_name(SPFilter *filter, gchar const *name) { pair<gchar*,int> new_pair(name_copy, value); pair<map<gchar*,int,ltstr>::iterator,bool> ret = filter->_image_name->insert(new_pair); if (ret.second == false) { + // The element is not inserted (because an element with the same key was already in the map) + // Therefore, free the memory allocated for the new entry: + free(name_copy); + return (*ret.first).second; } return value; diff --git a/src/sp-item.cpp b/src/sp-item.cpp index 94ab1b181..2fa36f834 100644 --- a/src/sp-item.cpp +++ b/src/sp-item.cpp @@ -1,6 +1,3 @@ -/** \file - * Base class for visual SVG elements - */ /* * Authors: * Lauris Kaplinski <lauris@kaplinski.com> @@ -15,12 +12,6 @@ * Released under GNU GPL, read the file 'COPYING' for more information */ -/** \class SPItem - * - * SPItem is an abstract base class for all graphic (visible) SVG nodes. It - * is a subclass of SPObject, with great deal of specific functionality. - */ - #ifdef HAVE_CONFIG_H # include "config.h" #endif @@ -232,20 +223,12 @@ bool SPItem::isEvaluated() const { return _is_evaluated; } -/** - * Returns something suitable for the `Hide' checkbox in the Object Properties dialog box. - * Corresponds to setExplicitlyHidden. - */ bool SPItem::isExplicitlyHidden() const { return (style->display.set && style->display.value == SP_CSS_DISPLAY_NONE); } -/** - * Sets the display CSS property to `hidden' if \a val is true, - * otherwise makes it unset - */ void SPItem::setExplicitlyHidden(bool val) { style->display.set = val; style->display.value = ( val ? SP_CSS_DISPLAY_NONE : SP_CSS_DISPLAY_INLINE ); @@ -253,9 +236,6 @@ void SPItem::setExplicitlyHidden(bool val) { updateRepr(); } -/** - * Sets the transform_center_x and transform_center_y properties to retain the rotation center -*/ void SPItem::setCenter(Geom::Point const &object_centre) { document->ensureUpToDate(); @@ -389,11 +369,6 @@ void SPItem::lowerToBottom() { } } -/* - * Move this SPItem into or after another SPItem in the doc - * \param target - the SPItem to move into or after - * \param intoafter - move to after the target (false), move inside (sublayer) of the target (true) - */ void SPItem::moveTo(SPItem *target, bool intoafter) { Inkscape::XML::Node *target_ref = ( target ? target->getRepr() : NULL ); @@ -826,11 +801,7 @@ Geom::OptRect SPItem::bbox(Geom::Affine const & /*transform*/, SPItem::BBoxType //throw; return Geom::OptRect(); } -/** - * Get item's geometric bounding box in this item's coordinate system. - * - * The geometric bounding box includes only the path, disregarding all style attributes. - */ + Geom::OptRect SPItem::geometricBounds(Geom::Affine const &transform) const { Geom::OptRect bbox; @@ -843,11 +814,6 @@ Geom::OptRect SPItem::geometricBounds(Geom::Affine const &transform) const return bbox; } -/** - * Get item's visual bounding box in this item's coordinate system. - * - * The visual bounding box includes the stroke and the filter region. - */ Geom::OptRect SPItem::visualBounds(Geom::Affine const &transform) const { using Geom::X; @@ -924,14 +890,11 @@ Geom::OptRect SPItem::bounds(BBoxType type, Geom::Affine const &transform) const } } -/** Get item's geometric bbox in document coordinate system. - * Document coordinates are the default coordinates of the root element: - * the origin is at the top left, X grows to the right and Y grows downwards. */ Geom::OptRect SPItem::documentGeometricBounds() const { return geometricBounds(i2doc_affine()); } -/// Get item's visual bbox in document coordinate system. + Geom::OptRect SPItem::documentVisualBounds() const { if (!bbox_valid) { @@ -948,14 +911,12 @@ Geom::OptRect SPItem::documentBounds(BBoxType type) const return documentVisualBounds(); } } -/** Get item's geometric bbox in desktop coordinate system. - * Desktop coordinates should be user defined. Currently they are hardcoded: - * origin is at bottom left, X grows to the right and Y grows upwards. */ + Geom::OptRect SPItem::desktopGeometricBounds() const { return geometricBounds(i2dt_affine()); } -/// Get item's visual bbox in desktop coordinate system. + Geom::OptRect SPItem::desktopVisualBounds() const { /// @fixme hardcoded desktop transform @@ -1079,11 +1040,6 @@ gchar* SPItem::description() const { return g_strdup(""); } -/** - * Returns a string suitable for status bar, formatted in pango markup language. - * - * Must be freed by caller. - */ gchar *SPItem::detailedDescription() const { gchar* s = g_strdup_printf("<b>%s</b> %s", this->displayName(), this->description()); @@ -1117,20 +1073,10 @@ gchar *SPItem::detailedDescription() const { return s; } -/** - * Returns true if the item is filtered, false otherwise. Used with groups/lists to determine how many, or if any, are filtered - * - */ bool SPItem::isFiltered() const { return (style && style->filter.href && style->filter.href->getObject()); } -/** - * Allocates unique integer keys. - * \param numkeys Number of keys required. - * \return First allocated key; hence if the returned key is n - * you can use n, n + 1, ..., n + (numkeys - 1) - */ unsigned SPItem::display_key_new(unsigned numkeys) { static unsigned dkey = 0; @@ -1367,9 +1313,6 @@ static Geom::Affine sp_item_transform_repr (SPItem *item) } -/** - * Recursively scale stroke width in \a item and its children by \a expansion. - */ void SPItem::adjust_stroke_width_recursive(double expansion) { adjust_stroke (expansion); @@ -1414,9 +1357,6 @@ sp_item_adjust_rects_recursive(SPItem *item, Geom::Affine advertized_transform) } } -/** - * Recursively compensate pattern or gradient transform. - */ void SPItem::adjust_paint_recursive (Geom::Affine advertized_transform, Geom::Affine t_ancestors, bool is_pattern) { // _Before_ full pattern/gradient transform: t_paint * t_item * t_ancestors @@ -1478,14 +1418,6 @@ Geom::Affine SPItem::set_transform(Geom::Affine const &transform) { return transform; } -/** - * Set a new transform on an object. - * - * Compensate for stroke scaling and gradient/pattern fill transform, if - * necessary. Call the object's set_transform method if transforms are - * stored optimized. Send _transformed_signal. Invoke _write method so that - * the repr is updated with the new transform. - */ void SPItem::doWriteTransform(Inkscape::XML::Node *repr, Geom::Affine const &transform, Geom::Affine const *adv, bool compensate) { g_return_if_fail(repr != NULL); @@ -1597,10 +1529,6 @@ gint SPItem::emitEvent(SPEvent &event) return this->event(&event); } -/** - * Sets item private transform (not propagated to repr), without compensating stroke widths, - * gradients, patterns as sp_item_write_transform does. - */ void SPItem::set_item_transform(Geom::Affine const &transform_matrix) { if (!Geom::are_near(transform_matrix, transform, 1e-18)) { @@ -1618,12 +1546,7 @@ void SPItem::set_item_transform(Geom::Affine const &transform_matrix) //} -/** - * \pre \a ancestor really is an ancestor (\>=) of \a object, or NULL. - * ("Ancestor (\>=)" here includes as far as \a object itself.) - */ -Geom::Affine -i2anc_affine(SPObject const *object, SPObject const *const ancestor) { +Geom::Affine i2anc_affine(SPObject const *object, SPObject const *const ancestor) { Geom::Affine ret(Geom::identity()); g_return_val_if_fail(object != NULL, ret); @@ -1650,18 +1573,11 @@ Geom::Affine SPItem::getRelativeTransform(SPObject const *dest) const { return i2i_affine(this, dest); } -/** - * Returns the accumulated transformation of the item and all its ancestors, including root's viewport. - * \pre (item != NULL) and SP_IS_ITEM(item). - */ Geom::Affine SPItem::i2doc_affine() const { return i2anc_affine(this, NULL); } -/** - * Returns the transformation from item to desktop coords - */ Geom::Affine SPItem::i2dt_affine() const { Geom::Affine ret; @@ -1692,9 +1608,6 @@ void SPItem::set_i2d_affine(Geom::Affine const &i2dt) } -/** - * should rather be named "sp_item_d2i_affine" to match "sp_item_i2d_affine" (or vice versa) - */ Geom::Affine SPItem::dt2i_affine() const { /* fixme: Implement the right way (Lauris) */ @@ -1738,10 +1651,6 @@ sp_item_view_list_remove(SPItemView *list, SPItemView *view) return ret; } -/** - * Return the arenaitem corresponding to the given item in the display - * with the given key - */ Inkscape::DrawingItem *SPItem::get_arenaitem(unsigned key) { for ( SPItemView *iv = display ; iv ; iv = iv->next ) { diff --git a/src/sp-item.h b/src/sp-item.h index 1656a0c2b..b9d71c551 100644 --- a/src/sp-item.h +++ b/src/sp-item.h @@ -1,7 +1,8 @@ #ifndef SEEN_SP_ITEM_H #define SEEN_SP_ITEM_H -/** \file +/** + * @file * Some things pertinent to all visible shapes: SPItem, SPItemView, SPItemCtx, SPItemClass, SPEvent. */ @@ -65,7 +66,7 @@ enum PatternTransform { /** * Event structure. * - * \todo This is just placeholder. Plan: + * @todo This is just placeholder. Plan: * We do extensible event structure, that hold applicable (ui, non-ui) * data pointers. So it is up to given object/arena implementation * to process correct ones in meaningful way. @@ -78,7 +79,6 @@ public: void* data; }; -/// SPItemView class SPItemView { public: SPItemView *next; @@ -95,17 +95,21 @@ public: /** * Flag for referenced views (i.e. markers, clippaths, masks and patterns); - currently unused, does the same as DISPLAY + * currently unused, does the same as DISPLAY */ #define SP_ITEM_REFERENCE_FLAGS (1 << 1) -/// Contains transformations to document/viewport and the viewport size. +/** + * Contains transformations to document/viewport and the viewport size. + */ class SPItemCtx : public SPCtx { public: /** Item to document transformation */ Geom::Affine i2doc; + /** Viewport size */ Geom::Rect viewport; + /** Item to viewport transformation */ Geom::Affine i2vp; }; @@ -113,7 +117,11 @@ public: #define SP_ITEM(obj) (dynamic_cast<SPItem*>((SPObject*)obj)) #define SP_IS_ITEM(obj) (dynamic_cast<const SPItem*>((SPObject*)obj) != NULL) -/** Abstract base class for all visible shapes. */ +/** + * Base class for visual SVG elements. + * SPItem is an abstract base class for all graphic (visible) SVG nodes. It + * is a subclass of SPObject, with great deal of specific functionality. + */ class SPItem : public SPObject { public: enum BBoxType { @@ -156,7 +164,7 @@ public: bool isHidden() const; void setHidden(bool hidden); - /* Objects dialogue */ + // Objects dialogue bool isSensitive() const { return sensitive; }; @@ -167,7 +175,7 @@ public: void setHighlightColor(guint32 color); void unsetHighlightColor(); - /********************/ + //==================== bool isEvaluated() const; void setEvaluated(bool visible); @@ -175,11 +183,23 @@ public: bool isHidden(unsigned display_key) const; + /** + * Returns something suitable for the `Hide' checkbox in the Object Properties dialog box. + * Corresponds to setExplicitlyHidden. + */ bool isExplicitlyHidden() const; + /** + * Sets the display CSS property to `hidden' if \a val is true, + * otherwise makes it unset. + */ void setExplicitlyHidden(bool val); + /** + * Sets the transform_center_x and transform_center_y properties to retain the rotation center + */ void setCenter(Geom::Point const &object_centre); + void unsetCenter(); bool isCenterSet() const; Geom::Point getCenter() const; @@ -195,52 +215,155 @@ public: void lowerOne(); void raiseToTop(); void lowerToBottom(); + + /** + * Move this SPItem into or after another SPItem in the doc. + * + * @param target the SPItem to move into or after. + * @param intoafter move to after the target (false), move inside (sublayer) of the target (true). + */ void moveTo(SPItem *target, bool intoafter); sigc::connection connectTransformed(sigc::slot<void, Geom::Affine const *, SPItem *> slot) { return _transformed_signal.connect(slot); } + /** + * Get item's geometric bounding box in this item's coordinate system. + * + * The geometric bounding box includes only the path, disregarding all style attributes. + */ Geom::OptRect geometricBounds(Geom::Affine const &transform = Geom::identity()) const; + + /** + * Get item's visual bounding box in this item's coordinate system. + * + * The visual bounding box includes the stroke and the filter region. + */ Geom::OptRect visualBounds(Geom::Affine const &transform = Geom::identity()) const; + Geom::OptRect bounds(BBoxType type, Geom::Affine const &transform = Geom::identity()) const; + + /** + * Get item's geometric bbox in document coordinate system. + * Document coordinates are the default coordinates of the root element: + * the origin is at the top left, X grows to the right and Y grows downwards. + */ Geom::OptRect documentGeometricBounds() const; + + /** + * Get item's visual bbox in document coordinate system. + */ Geom::OptRect documentVisualBounds() const; + Geom::OptRect documentBounds(BBoxType type) const; + + /** + * Get item's geometric bbox in desktop coordinate system. + * Desktop coordinates should be user defined. Currently they are hardcoded: + * origin is at bottom left, X grows to the right and Y grows upwards. + */ Geom::OptRect desktopGeometricBounds() const; + + /** + * Get item's visual bbox in desktop coordinate system. + */ Geom::OptRect desktopVisualBounds() const; + Geom::OptRect desktopPreferredBounds() const; Geom::OptRect desktopBounds(BBoxType type) const; unsigned int pos_in_parent() const; + /** + * Returns a string suitable for status bar, formatted in pango markup language. + * + * Must be freed by caller. + */ char *detailedDescription() const; + /** + * Returns true if the item is filtered, false otherwise. + * Used with groups/lists to determine how many, or if any, are filtered. + */ bool isFiltered() const; void invoke_print(SPPrintContext *ctx); + + /** + * Allocates unique integer keys. + * + * @param numkeys Number of keys required. + * @return First allocated key; hence if the returned key is n + * you can use n, n + 1, ..., n + (numkeys - 1) + */ static unsigned int display_key_new(unsigned int numkeys); + Inkscape::DrawingItem *invoke_show(Inkscape::Drawing &drawing, unsigned int key, unsigned int flags); void invoke_hide(unsigned int key); void getSnappoints(std::vector<Inkscape::SnapCandidatePoint> &p, Inkscape::SnapPreferences const *snapprefs=0) const; void adjust_pattern(/* Geom::Affine const &premul, */ Geom::Affine const &postmul, bool set = false, PatternTransform = TRANSFORM_BOTH); void adjust_gradient(/* Geom::Affine const &premul, */ Geom::Affine const &postmul, bool set = false); void adjust_stroke(double ex); + + /** + * Recursively scale stroke width in \a item and its children by \a expansion. + */ void adjust_stroke_width_recursive(double ex); + void freeze_stroke_width_recursive(bool freeze); + + /** + * Recursively compensate pattern or gradient transform. + */ void adjust_paint_recursive(Geom::Affine advertized_transform, Geom::Affine t_ancestors, bool is_pattern); + void adjust_livepatheffect(Geom::Affine const &postmul, bool set = false); + + /** + * Set a new transform on an object. + * + * Compensate for stroke scaling and gradient/pattern fill transform, if + * necessary. Call the object's set_transform method if transforms are + * stored optimized. Send _transformed_signal. Invoke _write method so that + * the repr is updated with the new transform. + */ void doWriteTransform(Inkscape::XML::Node *repr, Geom::Affine const &transform, Geom::Affine const *adv = NULL, bool compensate = true); + + /** + * Sets item private transform (not propagated to repr), without compensating stroke widths, + * gradients, patterns as sp_item_write_transform does. + */ void set_item_transform(Geom::Affine const &transform_matrix); + int emitEvent (SPEvent &event); + + /** + * Return the arenaitem corresponding to the given item in the display + * with the given key + */ Inkscape::DrawingItem *get_arenaitem(unsigned int key); + /** + * Returns the accumulated transformation of the item and all its ancestors, including root's viewport. + * @pre (item != NULL) and SP_IS_ITEM(item). + */ Geom::Affine i2doc_affine() const; + + /** + * Returns the transformation from item to desktop coords + */ Geom::Affine i2dt_affine() const; + void set_i2d_affine(Geom::Affine const &transform); + + /** + * should rather be named "sp_item_d2i_affine" to match "sp_item_i2d_affine" (or vice versa). + */ Geom::Affine dt2i_affine() const; char *_highlightColor; + private: enum EvaluatedStatus { @@ -281,17 +404,16 @@ public: // Utility +/** + * @pre \a ancestor really is an ancestor (\>=) of \a object, or NULL. + * ("Ancestor (\>=)" here includes as far as \a object itself.) + */ Geom::Affine i2anc_affine(SPObject const *item, SPObject const *ancestor); + Geom::Affine i2i_affine(SPObject const *src, SPObject const *dest); /* fixme: - these are evil, but OK */ -/* Fill *TRANSFORM with the item-to-desktop transform. See doc/coordinates.txt - * for a description of `Desktop coordinates'; though see also mental's comment - * at the top of that file. - * - * \return TRANSFORM. - */ int sp_item_repr_compare_position(SPItem const *first, SPItem const *second); SPItem *sp_item_first_item_child (SPObject *obj); SPItem const *sp_item_first_item_child (SPObject const *obj); diff --git a/src/style-test.h b/src/style-test.h index 2fe270336..e14ed4db7 100644 --- a/src/style-test.h +++ b/src/style-test.h @@ -104,30 +104,30 @@ public: TestCase("font:bold 12px Arial", "font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:12px;line-height:normal;font-family:Arial"), TestCase("font:bold 12px/24px 'Times New Roman'", - "font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:12px;line-height:24px;font-family:\'\"Times New Roman\"\'"), + "font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:12px;line-height:24px;font-family:\'Times New Roman\'"), // From CSS 3 Fonts (examples): - TestCase("font: 12pt/14pt sans-serif", - "font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:15px;line-height:14pt;font-family:sans-serif"), + TestCase("font: 12pt/15pt sans-serif", + "font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:16px;line-height:15pt;font-family:sans-serif"), TestCase("font: 80% sans-serif", "font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:80.00000119%;line-height:normal;font-family:sans-serif"), TestCase("font: x-large/110% 'new century schoolbook', serif", - "font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:x-large;line-height:110.00000238%;font-family:\'\"new century schoolbook\", serif\'"), + "font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:x-large;line-height:110.00000238%;font-family:\'new century schoolbook\', serif"), TestCase("font: bold italic large Palatino, serif", - "font-style:italic;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:large;line-height:normal;font-family:\'Palatino, serif\'"), + "font-style:italic;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:large;line-height:normal;font-family:Palatino, serif"), TestCase("font: normal small-caps 120%/120% fantasy", "font-style:normal;font-variant:small-caps;font-weight:normal;font-stretch:normal;font-size:120.00000477%;line-height:120.00000477%;font-family:fantasy"), TestCase("font: condensed oblique 12pt 'Helvetica Neue', serif;", - "font-style:oblique;font-variant:normal;font-weight:normal;font-stretch:condensed;font-size:15px;line-height:normal;font-family:\'\"Helvetica Neue\", serif\'"), + "font-style:oblique;font-variant:normal;font-weight:normal;font-stretch:condensed;font-size:16px;line-height:normal;font-family:\'Helvetica Neue\', serif"), TestCase("font-family:sans-serif"), // SPIString, text_private TestCase("font-family:Arial"), - TestCase("font-variant:normal;font-stretch:normal;-inkscape-font-specification:Nimbus Roman No9 L Bold Italic"), + // TestCase("font-variant:normal;font-stretch:normal;-inkscape-font-specification:Nimbus Roman No9 L Bold Italic"), // Needs to be fixed (quotes should be around each font-family): - TestCase("font-family:Georgia, 'Minion Web'","font-family:'Georgia, \"Minion Web\"'"), + TestCase("font-family:Georgia, 'Minion Web'","font-family:Georgia, \'Minion Web\'"), TestCase("font-size:12", "font-size:12px"), // SPIFontSize TestCase("font-size:12px"), - TestCase("font-size:12pt", "font-size:15px"), + TestCase("font-size:12pt", "font-size:16px"), TestCase("font-size:medium"), TestCase("font-size:smaller"), TestCase("font-style:italic"), // SPIEnum @@ -145,10 +145,10 @@ public: // The default value for 'text-decoration-color' is 'currentColor', but // we cannot set the default to that value yet. (We need to switch // SPIPaint to SPIColor and then add the ability to set default.) - TestCase("text-decoration: underline", - "text-decoration: underline;text-decoration-line: underline;text-decoration-color:currentColor"), - TestCase("text-decoration: overline underline", - "text-decoration: underline overline;text-decoration-line: underline overline;text-decoration-color:currentColor"), + // TestCase("text-decoration: underline", + // "text-decoration: underline;text-decoration-line: underline;text-decoration-color:currentColor"), + // TestCase("text-decoration: overline underline", + // "text-decoration: underline overline;text-decoration-line: underline overline;text-decoration-color:currentColor"), TestCase("text-decoration: underline wavy #0000ff", "text-decoration: underline;text-decoration-line: underline;text-decoration-style:wavy;text-decoration-color:#0000ff"), @@ -358,7 +358,7 @@ public: TestCase("text-decoration:underline", "text-decoration:overline", false), TestCase("text-decoration:underline overline","text-decoration:underline overline",true ), TestCase("text-decoration:overline underline","text-decoration:underline overline",true ), - TestCase("text-decoration:none", "text-decoration-color:currentColor", true ), // Default + // TestCase("text-decoration:none", "text-decoration-color:currentColor", true ), // Default // Terminate diff --git a/src/style.cpp b/src/style.cpp index e0c8536fc..a7e50b17a 100644 --- a/src/style.cpp +++ b/src/style.cpp @@ -1720,7 +1720,6 @@ sp_css_attr_unset_text(SPCSSAttr *css) sp_repr_css_set_property(css, "font-family", NULL); sp_repr_css_set_property(css, "text-indent", NULL); sp_repr_css_set_property(css, "text-align", NULL); - sp_repr_css_set_property(css, "text-decoration", NULL); sp_repr_css_set_property(css, "line-height", NULL); sp_repr_css_set_property(css, "letter-spacing", NULL); sp_repr_css_set_property(css, "word-spacing", NULL); @@ -1729,12 +1728,48 @@ sp_css_attr_unset_text(SPCSSAttr *css) sp_repr_css_set_property(css, "block-progression", NULL); sp_repr_css_set_property(css, "writing-mode", NULL); sp_repr_css_set_property(css, "text-anchor", NULL); - sp_repr_css_set_property(css, "white_space", NULL); + sp_repr_css_set_property(css, "white-space", NULL); sp_repr_css_set_property(css, "kerning", NULL); // not implemented yet sp_repr_css_set_property(css, "dominant-baseline", NULL); // not implemented yet sp_repr_css_set_property(css, "alignment-baseline", NULL); // not implemented yet sp_repr_css_set_property(css, "baseline-shift", NULL); + sp_repr_css_set_property(css, "text-decoration", NULL); + sp_repr_css_set_property(css, "text-decoration-line", NULL); + sp_repr_css_set_property(css, "text-decoration-color", NULL); + sp_repr_css_set_property(css, "text-decoration-style", NULL); + + return css; +} + +// ui/dialog/inkscape-preferences.cpp +/** + * Unset properties that should not be set for default tool style. + * This list needs to be reviewed. + */ +SPCSSAttr * +sp_css_attr_unset_blacklist(SPCSSAttr *css) +{ + sp_repr_css_set_property(css, "color", NULL); + sp_repr_css_set_property(css, "clip-rule", NULL); + sp_repr_css_set_property(css, "display", NULL); + sp_repr_css_set_property(css, "overflow", NULL); + sp_repr_css_set_property(css, "visibility", NULL); + sp_repr_css_set_property(css, "isolation", NULL); + sp_repr_css_set_property(css, "mix-blend-mode", NULL); + sp_repr_css_set_property(css, "color-interpolation", NULL); + sp_repr_css_set_property(css, "color-interpolation-filters", NULL); + sp_repr_css_set_property(css, "solid-color", NULL); + sp_repr_css_set_property(css, "solid-opacity", NULL); + sp_repr_css_set_property(css, "fill-rule", NULL); + sp_repr_css_set_property(css, "filter-blend-mode", NULL); + sp_repr_css_set_property(css, "filter-gaussianBlur-deviation", NULL); + sp_repr_css_set_property(css, "color-rendering", NULL); + sp_repr_css_set_property(css, "image-rendering", NULL); + sp_repr_css_set_property(css, "shape-rendering", NULL); + sp_repr_css_set_property(css, "text-rendering", NULL); + sp_repr_css_set_property(css, "enable-background", NULL); + return css; } diff --git a/src/style.h b/src/style.h index a4c2b3043..1b1596458 100644 --- a/src/style.h +++ b/src/style.h @@ -314,6 +314,7 @@ double sp_style_css_size_units_to_px(double size, int unit); // No change? SPCSSAttr *sp_css_attr_from_style (SPStyle const *const style, unsigned int flags); SPCSSAttr *sp_css_attr_from_object(SPObject *object, unsigned int flags = SP_STYLE_FLAG_IFSET); SPCSSAttr *sp_css_attr_unset_text(SPCSSAttr *css); +SPCSSAttr *sp_css_attr_unset_blacklist(SPCSSAttr *css); SPCSSAttr *sp_css_attr_unset_uris(SPCSSAttr *css); SPCSSAttr *sp_css_attr_scale(SPCSSAttr *css, double ex); diff --git a/src/svg/svg-affine-test.h b/src/svg/svg-affine-test.h index 11b9012a8..6d8387328 100644 --- a/src/svg/svg-affine-test.h +++ b/src/svg/svg-affine-test.h @@ -34,7 +34,7 @@ private: static char const * const read_fail_tests[25]; static test_t const write_matrix_tests[2]; static test_t const write_translate_tests[3]; - static test_t const write_scale_tests[2]; + static test_t const write_scale_tests[3]; static test_t const write_rotate_tests[2]; static test_t const write_skew_tests[3]; public: @@ -238,8 +238,9 @@ SvgAffineTest::test_t const SvgAffineTest::write_translate_tests[3] = { {"translate(1,1)",Geom::Affine(1,0,0,1,1,1)}, {"translate(1)",Geom::Affine(1,0,0,1,1,0)}, {"translate(-1345,0.123)",Geom::Affine(1,0,0,1,-1.345e3,.123)}}; -SvgAffineTest::test_t const SvgAffineTest::write_scale_tests[2] = { +SvgAffineTest::test_t const SvgAffineTest::write_scale_tests[3] = { {"scale(0)",Geom::Affine(0,0,0,0,0,0)}, + {"scale(7)",Geom::Affine(7,0,0,7,0,0)}, {"scale(2,3)",Geom::Affine(2,0,0,3,0,0)}}; SvgAffineTest::test_t const SvgAffineTest::write_rotate_tests[2] = { {"rotate(13)",Geom::Affine(cos(13.*DEGREE),sin(13.*DEGREE),-sin(13.*DEGREE),cos(13.*DEGREE),0,0)}, @@ -247,7 +248,7 @@ SvgAffineTest::test_t const SvgAffineTest::write_rotate_tests[2] = { SvgAffineTest::test_t const SvgAffineTest::write_skew_tests[3] = { {"skewX(30)",Geom::Affine(1,0,tan(30.*DEGREE),1,0,0)}, {"skewX(-30)",Geom::Affine(1,0,tan(-30.*DEGREE),1,0,0)}, - {"skewY(390)",Geom::Affine(1,tan(30.*DEGREE),0,1,0,0)}}; + {"skewY(30)",Geom::Affine(1,tan(30.*DEGREE),0,1,0,0)}}; /* Local Variables: diff --git a/src/svg/svg-affine.cpp b/src/svg/svg-affine.cpp index 44567a2bd..af58c4544 100644 --- a/src/svg/svg-affine.cpp +++ b/src/svg/svg-affine.cpp @@ -162,65 +162,105 @@ sp_svg_transform_write(Geom::Affine const &transform) int prec = prefs->getInt("/options/svgoutput/numericprecision", 8); int min_exp = prefs->getInt("/options/svgoutput/minimumexponent", -8); - /* fixme: We could use t1 * t1 + t2 * t2 here instead */ - if ( Geom::are_near(transform[1], 0.0, e) && Geom::are_near (transform[2], 0.0, e)) { - if (Geom::are_near (transform[4], 0.0, e) && Geom::are_near (transform[5], 0.0, e)) { - if (Geom::are_near (transform[0], 1.0, e) && Geom::are_near (transform[3], 1.0, e)) { - /* We are more or less identity */ - return NULL; - } else { - /* We are more or less scale */ - gchar c[256]; - unsigned p = 0; - strcpy (c + p, "scale("); - p += 6; - p += sp_svg_number_write_de( c + p, sizeof(c) - p, transform[0], prec, min_exp ); - c[p++] = ','; - p += sp_svg_number_write_de( c + p, sizeof(c) - p, transform[3], prec, min_exp ); - c[p++] = ')'; - c[p] = '\000'; - g_assert( p <= sizeof(c) ); - return g_strdup(c); - } + // Special case: when all fields of the affine are zero, + // the optimized transformation is scale(0) + if (transform[0] == 0 && transform[1] == 0 && transform[2] == 0 && + transform[3] == 0 && transform[4] == 0 && transform[5] == 0) + { + return g_strdup("scale(0)"); + } + + // FIXME legacy C code! + // the function sp_svg_number_write_de is stopping me from using a proper C++ string + + gchar c[256]; // string buffer + unsigned p = 0; // position in the buffer + + if (transform.isIdentity()) { + // We are more or less identity, so no transform attribute needed: + return NULL; + } else if (transform.isScale()) { + // We are more or less a uniform scale + strcpy (c + p, "scale("); + p += 6; + p += sp_svg_number_write_de( c + p, sizeof(c) - p, transform[0], prec, min_exp ); + if (Geom::are_near(transform[0], transform[3], e)) { + c[p++] = ')'; + c[p] = '\000'; } else { - if (Geom::are_near (transform[0], 1.0, e) && Geom::are_near (transform[3], 1.0, e)) { - /* We are more or less translate */ - gchar c[256]; - unsigned p = 0; - strcpy (c + p, "translate("); - p += 10; - p += sp_svg_number_write_de( c + p, sizeof(c) - p, transform[4], prec, min_exp ); - c[p++] = ','; - p += sp_svg_number_write_de( c + p, sizeof(c) - p, transform[5], prec, min_exp ); - c[p++] = ')'; - c[p] = '\000'; - g_assert( p <= sizeof(c) ); - return g_strdup(c); - } else { - gchar c[256]; - unsigned p = 0; - strcpy (c + p, "matrix("); - p += 7; - p += sp_svg_number_write_de( c + p, sizeof(c) - p, transform[0], prec, min_exp ); - c[p++] = ','; - p += sp_svg_number_write_de( c + p, sizeof(c) - p, transform[1], prec, min_exp ); - c[p++] = ','; - p += sp_svg_number_write_de( c + p, sizeof(c) - p, transform[2], prec, min_exp ); - c[p++] = ','; - p += sp_svg_number_write_de( c + p, sizeof(c) - p, transform[3], prec, min_exp ); - c[p++] = ','; - p += sp_svg_number_write_de( c + p, sizeof(c) - p, transform[4], prec, min_exp ); - c[p++] = ','; - p += sp_svg_number_write_de( c + p, sizeof(c) - p, transform[5], prec, min_exp ); - c[p++] = ')'; - c[p] = '\000'; - g_assert( p <= sizeof(c) ); - return g_strdup(c); - } + c[p++] = ','; + p += sp_svg_number_write_de( c + p, sizeof(c) - p, transform[3], prec, min_exp ); + c[p++] = ')'; + c[p] = '\000'; } + } else if (transform.isTranslation()) { + // We are more or less a pure translation + strcpy (c + p, "translate("); + p += 10; + p += sp_svg_number_write_de( c + p, sizeof(c) - p, transform[4], prec, min_exp ); + if (Geom::are_near(transform[5], 0.0, e)) { + c[p++] = ')'; + c[p] = '\000'; + } else { + c[p++] = ','; + p += sp_svg_number_write_de( c + p, sizeof(c) - p, transform[5], prec, min_exp ); + c[p++] = ')'; + c[p] = '\000'; + } + } else if (transform.isRotation()) { + // We are more or less a pure rotation + strcpy(c + p, "rotate("); + p += 7; + + double angle = std::atan2(transform[1], transform[0]) * (180 / M_PI); + p += sp_svg_number_write_de(c + p, sizeof(c) - p, angle, prec, min_exp); + + c[p++] = ')'; + c[p] = '\000'; + /* } else if (transform.withoutTranslation().isRotation()) { + // FIXME someone please figure out if this can actually be done + // The rotation angle is correct, the points are not + // Refer to the matrix in svg-affine-test.h + + // We are a rotation about a special axis + strcpy(c + p, "rotate("); + p += 7; + + Geom::Affine const sans_translate = transform.withoutTranslation(); + double angle = std::atan2(sans_translate[1], sans_translate[0]) * (180 / M_PI); + p += sp_svg_number_write_de(c + p, sizeof(c) - p, angle, prec, min_exp); + c[p++] = ','; + + Geom::Point pt = transform.translation(); + p += sp_svg_number_write_de(c + p, sizeof(c) - p, pt[Geom::X], prec, min_exp); + + c[p++] = ','; + + p += sp_svg_number_write_de(c + p, sizeof(c) - p, pt[Geom::Y], prec, min_exp); + + c[p++] = ')'; + c[p] = '\000';*/ + } else if (transform.isHShear()) { + // We are more or less a pure skewX + strcpy(c + p, "skewX("); + p += 6; + + double angle = atan(transform[2]) * (180 / M_PI); + p += sp_svg_number_write_de(c + p, sizeof(c) - p, angle, prec, min_exp); + + c[p++] = ')'; + c[p] = '\000'; + } else if (transform.isVShear()) { + // We are more or less a pure skewY + strcpy(c + p, "skewY("); + p += 6; + + double angle = atan(transform[1]) * (180 / M_PI); + p += sp_svg_number_write_de(c + p, sizeof(c) - p, angle, prec, min_exp); + + c[p++] = ')'; + c[p] = '\000'; } else { - gchar c[256]; - unsigned p = 0; strcpy (c + p, "matrix("); p += 7; p += sp_svg_number_write_de( c + p, sizeof(c) - p, transform[0], prec, min_exp ); @@ -236,9 +276,10 @@ sp_svg_transform_write(Geom::Affine const &transform) p += sp_svg_number_write_de( c + p, sizeof(c) - p, transform[5], prec, min_exp ); c[p++] = ')'; c[p] = '\000'; - g_assert( p <= sizeof(c) ); - return g_strdup(c); } + + assert(p <= sizeof(c)); + return g_strdup(c); } diff --git a/src/svg/svg-angle.cpp b/src/svg/svg-angle.cpp index 63152368e..ed5ccd45e 100644 --- a/src/svg/svg-angle.cpp +++ b/src/svg/svg-angle.cpp @@ -104,15 +104,19 @@ static bool sp_svg_angle_read_lff(gchar const *str, SVGAngle::Unit &unit, float } else { if (strncmp(e, "deg", 3) == 0) { unit = SVGAngle::DEG; + val = v; computed = v; } else if (strncmp(e, "grad", 4) == 0) { unit = SVGAngle::GRAD; + val = v; computed = Inkscape::Util::Quantity::convert(v, "grad", "°"); } else if (strncmp(e, "rad", 3) == 0) { unit = SVGAngle::RAD; + val = v; computed = Inkscape::Util::Quantity::convert(v, "rad", "°"); } else if (strncmp(e, "turn", 4) == 0) { unit = SVGAngle::TURN; + val = v; computed = Inkscape::Util::Quantity::convert(v, "turn", "°"); } else { return false; diff --git a/src/svg/svg-length-test.h b/src/svg/svg-length-test.h index 81a28c9e7..fbdb7588d 100644 --- a/src/svg/svg-length-test.h +++ b/src/svg/svg-length-test.h @@ -164,13 +164,13 @@ SvgLengthTest::test_t const SvgLengthTest::absolute_tests[12] = { {"1.00001", SVGLength::NONE, 1.00001 , 1.00001}, {"1px", SVGLength::PX , 1 , 1}, {".1px", SVGLength::PX , 0.1 , 0.1}, - {"100pt", SVGLength::PT , 100 , 125}, - {"1e2pt", SVGLength::PT , 100 , 125}, - {"3pc", SVGLength::PC , 3 , 45}, - {"-3.5pc", SVGLength::PC , -3.5 , -3.5*15.}, - {"1.2345678mm", SVGLength::MM , 1.2345678, 1.2345678*3.543307}, // TODO: More precise constants? (a 7 digit constant when the default precision is 8 digits?) - {"123.45678cm", SVGLength::CM , 123.45678 , 123.45678*35.43307}, - {"73.162987in", SVGLength::INCH, 73.162987 , 73.162987*90}}; + {"100pt", SVGLength::PT , 100 , 400.0/3.0}, + {"1e2pt", SVGLength::PT , 100 , 400.0/3.0}, + {"3pc", SVGLength::PC , 3 , 48}, + {"-3.5pc", SVGLength::PC , -3.5 , -3.5*16.0}, + {"1.2345678mm", SVGLength::MM , 1.2345678, 1.2345678*96.0/25.4}, // TODO: More precise constants? (a 7 digit constant when the default precision is 8 digits?) + {"123.45678cm", SVGLength::CM , 123.45678 , 123.45678*96.0/2.54}, + {"73.162987in", SVGLength::INCH, 73.162987 , 73.162987*96}}; SvgLengthTest::test_t const SvgLengthTest::relative_tests[3] = { {"123em", SVGLength::EM, 123, 123. * 7.}, {"123ex", SVGLength::EX, 123, 123. * 13.}, diff --git a/src/ui/dialog/Makefile_insert b/src/ui/dialog/Makefile_insert index 26a59ce2c..cbdae1cb0 100644 --- a/src/ui/dialog/Makefile_insert +++ b/src/ui/dialog/Makefile_insert @@ -101,7 +101,7 @@ ink_common_sources += \ ui/dialog/template-widget.cpp \ ui/dialog/template-widget.h \ ui/dialog/tags.cpp \ - ui/dialpg/tags.h \ + ui/dialog/tags.h \ ui/dialog/text-edit.cpp \ ui/dialog/text-edit.h \ ui/dialog/tile.cpp \ diff --git a/src/ui/dialog/export.cpp b/src/ui/dialog/export.cpp index 6d5d894ef..ba30c8e6b 100644 --- a/src/ui/dialog/export.cpp +++ b/src/ui/dialog/export.cpp @@ -537,7 +537,7 @@ Gtk::Adjustment * Export::createSpinbutton( gchar const * /*key*/, float val, fl sb->set_sensitive (sensitive); pos++; - if (!ll.empty()) { + if (l) { l->set_mnemonic_widget(*sb); } diff --git a/src/ui/dialog/inkscape-preferences.cpp b/src/ui/dialog/inkscape-preferences.cpp index e113b325f..87b698673 100644 --- a/src/ui/dialog/inkscape-preferences.cpp +++ b/src/ui/dialog/inkscape-preferences.cpp @@ -234,6 +234,9 @@ static void StyleFromSelectionToTool(Glib::ustring const &prefs_path, StyleSwatc if (!css) return; + // remove black-listed properties + css = sp_css_attr_unset_blacklist (css); + // only store text style for the text tool if (prefs_path != "/tools/text") { css = sp_css_attr_unset_text (css); @@ -838,7 +841,7 @@ void InkscapePreferences::initPageIO() _save_use_current_dir.init( _("Use current directory for \"Save As ...\""), "/dialogs/save_as/use_current_dir", true); _page_io.add_line( false, "", _save_use_current_dir, "", - _("When this option is on, the \"Save as...\" and \"Save a Copy\" dialogs will always open in the directory where the currently open document is; when it's off, each will open in the directory where you last saved a file using it"), true); + _("When this option is on, the \"Save as...\" and \"Save a Copy...\" dialogs will always open in the directory where the currently open document is; when it's off, each will open in the directory where you last saved a file using it"), true); _misc_comment.init( _("Add label comments to printing output"), "/printing/debug/show-label-comments", false); _page_io.add_line( false, "", _misc_comment, "", diff --git a/src/ui/dialog/lpe-fillet-chamfer-properties.cpp b/src/ui/dialog/lpe-fillet-chamfer-properties.cpp index ad8b66b8c..fa909924d 100644 --- a/src/ui/dialog/lpe-fillet-chamfer-properties.cpp +++ b/src/ui/dialog/lpe-fillet-chamfer-properties.cpp @@ -46,7 +46,7 @@ FilletChamferPropertiesDialog::FilletChamferPropertiesDialog() Gtk::Box *mainVBox = get_vbox(); mainVBox->set_homogeneous(false); _layout_table.set_spacings(4); - _layout_table.resize(2, 2); + _layout_table.resize(3, 3); // Layer name widgets _fillet_chamfer_position_numeric.set_digits(4); @@ -61,20 +61,30 @@ FilletChamferPropertiesDialog::FilletChamferPropertiesDialog() Gtk::FILL); _layout_table.attach(_fillet_chamfer_position_numeric, 1, 2, 0, 1, Gtk::FILL | Gtk::EXPAND, Gtk::FILL); + _fillet_chamfer_chamfer_subdivisions.set_digits(0); + _fillet_chamfer_chamfer_subdivisions.set_increments(1,1); + //todo: get tha max aloable infinity freeze the widget + _fillet_chamfer_chamfer_subdivisions.set_range(0, 999999999999999999); + + _fillet_chamfer_chamfer_subdivisions_label.set_label(_("Chamfer subdivisions:")); + _fillet_chamfer_chamfer_subdivisions_label.set_alignment(1.0, 0.5); + + _layout_table.attach(_fillet_chamfer_chamfer_subdivisions_label, 0, 1, 1, 2, Gtk::FILL, + Gtk::FILL); + _layout_table.attach(_fillet_chamfer_chamfer_subdivisions, 1, 2, 1, 2, + Gtk::FILL | Gtk::EXPAND, Gtk::FILL); _fillet_chamfer_type_fillet.set_label(_("Fillet")); _fillet_chamfer_type_fillet.set_group(_fillet_chamfer_type_group); _fillet_chamfer_type_inverse_fillet.set_label(_("Inverse fillet")); _fillet_chamfer_type_inverse_fillet.set_group(_fillet_chamfer_type_group); _fillet_chamfer_type_chamfer.set_label(_("Chamfer")); _fillet_chamfer_type_chamfer.set_group(_fillet_chamfer_type_group); - _fillet_chamfer_type_double_chamfer.set_label(_("Double chamfer")); - _fillet_chamfer_type_double_chamfer.set_group(_fillet_chamfer_type_group); + mainVBox->pack_start(_layout_table, true, true, 4); mainVBox->pack_start(_fillet_chamfer_type_fillet, true, true, 4); mainVBox->pack_start(_fillet_chamfer_type_inverse_fillet, true, true, 4); mainVBox->pack_start(_fillet_chamfer_type_chamfer, true, true, 4); - mainVBox->pack_start(_fillet_chamfer_type_double_chamfer, true, true, 4); // Buttons _close_button.set_use_stock(true); @@ -146,10 +156,8 @@ void FilletChamferPropertiesDialog::_apply() d_width = 1; } else if (_fillet_chamfer_type_inverse_fillet.get_active() == true) { d_width = 2; - } else if (_fillet_chamfer_type_chamfer.get_active() == true) { - d_width = 3; } else { - d_width = 4; + d_width = _fillet_chamfer_chamfer_subdivisions.get_value() + 3; } if (_flexible) { if (d_pos > 99.99999 || d_pos < 0) { @@ -177,7 +185,7 @@ void FilletChamferPropertiesDialog::_close() ); } -bool FilletChamferPropertiesDialog::_handleKeyEvent(GdkEventKey *event) +bool FilletChamferPropertiesDialog::_handleKeyEvent(GdkEventKey * /*event*/) { return false; } @@ -194,7 +202,7 @@ void FilletChamferPropertiesDialog::_setKnotPoint(Geom::Point knotpoint) double position; std::string distance_or_radius = std::string(_("Radius ")); if(aprox){ - distance_or_radius = std::string(_("Radius aproximated ")); + distance_or_radius = std::string(_("Radius approximated ")); } if(use_distance){ distance_or_radius = std::string(_("Knot distance ")); @@ -218,10 +226,8 @@ void FilletChamferPropertiesDialog::_setKnotPoint(Geom::Point knotpoint) _fillet_chamfer_type_fillet.set_active(true); } else if (knotpoint.y() == 2) { _fillet_chamfer_type_inverse_fillet.set_active(true); - } else if (knotpoint.y() == 3) { - _fillet_chamfer_type_chamfer.set_active(true); - } else if (knotpoint.y() == 1) { - _fillet_chamfer_type_double_chamfer.set_active(true); + } else if (knotpoint.y() >= 3) { + _fillet_chamfer_chamfer_subdivisions.set_value(knotpoint.y() - 3); } } diff --git a/src/ui/dialog/lpe-fillet-chamfer-properties.h b/src/ui/dialog/lpe-fillet-chamfer-properties.h index 47ff97b00..deae0cee0 100644 --- a/src/ui/dialog/lpe-fillet-chamfer-properties.h +++ b/src/ui/dialog/lpe-fillet-chamfer-properties.h @@ -46,7 +46,8 @@ protected: Gtk::RadioButton _fillet_chamfer_type_fillet; Gtk::RadioButton _fillet_chamfer_type_inverse_fillet; Gtk::RadioButton _fillet_chamfer_type_chamfer; - Gtk::RadioButton _fillet_chamfer_type_double_chamfer; + Gtk::Label _fillet_chamfer_chamfer_subdivisions_label; + Gtk::SpinButton _fillet_chamfer_chamfer_subdivisions; Gtk::Table _layout_table; bool _position_visible; diff --git a/src/ui/dialog/lpe-powerstroke-properties.cpp b/src/ui/dialog/lpe-powerstroke-properties.cpp index c34351511..55f938a48 100644 --- a/src/ui/dialog/lpe-powerstroke-properties.cpp +++ b/src/ui/dialog/lpe-powerstroke-properties.cpp @@ -152,7 +152,7 @@ PowerstrokePropertiesDialog::_close() ); } -bool PowerstrokePropertiesDialog::_handleKeyEvent(GdkEventKey *event) +bool PowerstrokePropertiesDialog::_handleKeyEvent(GdkEventKey * /*event*/) { /*switch (get_group0_keyval(event)) { diff --git a/src/ui/dialog/objects.cpp b/src/ui/dialog/objects.cpp index 93d5dfbd5..c95529a56 100644 --- a/src/ui/dialog/objects.cpp +++ b/src/ui/dialog/objects.cpp @@ -988,7 +988,7 @@ void ObjectsPanel::_storeHighlightTarget(const Gtk::TreeModel::iterator& iter) /* * Drap and drop within the tree */ -bool ObjectsPanel::_handleDragDrop(const Glib::RefPtr<Gdk::DragContext>& context, int x, int y, guint time) +bool ObjectsPanel::_handleDragDrop(const Glib::RefPtr<Gdk::DragContext>& /*context*/, int x, int y, guint /*time*/) { int cell_x = 0, cell_y = 0; Gtk::TreeModel::Path target_path; diff --git a/src/ui/dialog/tags.cpp b/src/ui/dialog/tags.cpp index 127e4d95e..8a104d137 100644 --- a/src/ui/dialog/tags.cpp +++ b/src/ui/dialog/tags.cpp @@ -380,7 +380,7 @@ void TagsPanel::_objectsSelected( Selection *sel ) { _checkTreeSelection(); } -bool TagsPanel::_checkForSelected(const Gtk::TreePath &path, const Gtk::TreeIter& iter, SPObject* obj) +bool TagsPanel::_checkForSelected(const Gtk::TreePath &/*path*/, const Gtk::TreeIter& iter, SPObject* obj) { Gtk::TreeModel::Row row = *iter; SPObject * it = row[_model->_colObject]; @@ -393,6 +393,7 @@ bool TagsPanel::_checkForSelected(const Gtk::TreePath &path, const Gtk::TreeIter return false; } +// TODO does not look good that we're ignoring the passed in root. Investigate. void TagsPanel::_objectsChanged(SPObject* root) { while (!_objectWatchers.empty()) @@ -754,7 +755,7 @@ void TagsPanel::_storeDragSource(const Gtk::TreeModel::iterator& iter) * Drap and drop within the tree * Save the drag source and drop target SPObjects and if its a drag between layers or into (sublayer) a layer */ -bool TagsPanel::_handleDragDrop(const Glib::RefPtr<Gdk::DragContext>& context, int x, int y, guint time) +bool TagsPanel::_handleDragDrop(const Glib::RefPtr<Gdk::DragContext>& /*context*/, int x, int y, guint /*time*/) { int cell_x = 0, cell_y = 0; Gtk::TreeModel::Path target_path; @@ -885,7 +886,7 @@ void TagsPanel::_renameObject(Gtk::TreeModel::Row row, const Glib::ustring& name } } -bool TagsPanel::_noSelection( Glib::RefPtr<Gtk::TreeModel> const & /*model*/, Gtk::TreeModel::Path const & /*path*/, bool currentlySelected ) +bool TagsPanel::_noSelection( Glib::RefPtr<Gtk::TreeModel> const & /*model*/, Gtk::TreeModel::Path const & /*path*/, bool /*currentlySelected*/ ) { return false; } diff --git a/src/ui/tool/path-manipulator.cpp b/src/ui/tool/path-manipulator.cpp index 52ff5d42c..8b99c33b8 100644 --- a/src/ui/tool/path-manipulator.cpp +++ b/src/ui/tool/path-manipulator.cpp @@ -59,7 +59,7 @@ enum PathChange { const double handleCubicGap = 0.01; const double noPower = 0.0; const double defaultStartPower = 0.3334; -const double defaultEndPower = 0.6667; + /** * Notifies the path manipulator when something changes the path being edited @@ -1000,7 +1000,6 @@ NodeList::iterator PathManipulator::subdivideSegment(NodeList::iterator first, d n->front()->setPosition(seg2[1]); n->setType(NODE_SMOOTH, false); } else { - const double handleCubicGap = 0.01; Geom::D2< Geom::SBasis > SBasisInsideNodes; SPCurve *lineInsideNodes = new SPCurve(); if(second->back()->isDegenerate()){ @@ -1251,7 +1250,6 @@ double PathManipulator::BSplineHandlePosition(Handle *h, Handle *h2){ h = h2; } double pos = noPower; - const double handleCubicGap = 0.01; Node *n = h->parent(); Node * nextNode = NULL; nextNode = n->nodeToward(h); @@ -1279,7 +1277,6 @@ Geom::Point PathManipulator::BSplineHandleReposition(Handle *h, Handle *h2){ Geom::Point PathManipulator::BSplineHandleReposition(Handle *h,double pos){ using Geom::X; using Geom::Y; - const double handleCubicGap = 0.01; Geom::Point ret = h->position(); Node *n = h->parent(); Geom::D2< Geom::SBasis > SBasisInsideNodes; diff --git a/src/ui/tools/node-tool.cpp b/src/ui/tools/node-tool.cpp index e2bb85d11..99d60e2b7 100644 --- a/src/ui/tools/node-tool.cpp +++ b/src/ui/tools/node-tool.cpp @@ -305,6 +305,16 @@ void NodeTool::update_helperpath () { if (SP_IS_LPE_ITEM(selection->singleItem())) { Inkscape::LivePathEffect::Effect *lpe = SP_LPE_ITEM(selection->singleItem())->getCurrentLPE(); if (lpe && lpe->isVisible()/* && lpe->showOrigPath()*/) { + Inkscape::UI::ControlPointSelection::Set &selectionNodes = _selected_nodes->allPoints(); + std::vector<Geom::Point> selectedNodesPositions; + for (Inkscape::UI::ControlPointSelection::Set::iterator i = selectionNodes.begin(); i != selectionNodes.end(); ++i) { + if ((*i)->selected()) { + Inkscape::UI::Node *n = dynamic_cast<Inkscape::UI::Node *>(*i); + selectedNodesPositions.push_back(desktop->doc2dt(n->position())); + } + } + lpe->setSelectedNodePoints(selectedNodesPositions); + lpe->setCurrentZoom(this->desktop->current_zoom()); SPCurve *c = new SPCurve(); SPCurve *cc = new SPCurve(); std::vector<Geom::PathVector> cs = lpe->getCanvasIndicators(SP_LPE_ITEM(selection->singleItem())); diff --git a/src/ui/tools/select-tool.cpp b/src/ui/tools/select-tool.cpp index 21459e5d0..a8267ea1d 100644 --- a/src/ui/tools/select-tool.cpp +++ b/src/ui/tools/select-tool.cpp @@ -1153,7 +1153,7 @@ bool SelectTool::root_handler(GdkEvent* event) { if (selection->singleItem()) { SPItem *clicked_item = selection->singleItem(); SPGroup *clickedGroup = dynamic_cast<SPGroup *>(clicked_item); - if ( (clickedGroup && (clickedGroup->layerMode() == SPGroup::LAYER)) || dynamic_cast<SPBox3D *>(clicked_item)) { // enter group or a 3D box + if ( (clickedGroup && (clickedGroup->layerMode() != SPGroup::LAYER)) || dynamic_cast<SPBox3D *>(clicked_item)) { // enter group or a 3D box desktop->setCurrentLayer(clicked_item); sp_desktop_selection(desktop)->clear(); } else { diff --git a/src/ui/widget/addtoicon.cpp b/src/ui/widget/addtoicon.cpp index ce665295b..0798d1c98 100644 --- a/src/ui/widget/addtoicon.cpp +++ b/src/ui/widget/addtoicon.cpp @@ -127,13 +127,12 @@ void AddToIcon::render_vfunc( const Glib::RefPtr<Gdk::Drawable>& window, #endif } -bool -AddToIcon::activate_vfunc(GdkEvent* event, - Gtk::Widget& /*widget*/, - const Glib::ustring& path, - const Gdk::Rectangle& /*background_area*/, - const Gdk::Rectangle& /*cell_area*/, - Gtk::CellRendererState /*flags*/) +bool AddToIcon::activate_vfunc(GdkEvent* /*event*/, + Gtk::Widget& /*widget*/, + const Glib::ustring& /*path*/, + const Gdk::Rectangle& /*background_area*/, + const Gdk::Rectangle& /*cell_area*/, + Gtk::CellRendererState /*flags*/) { return false; } diff --git a/src/ui/widget/clipmaskicon.cpp b/src/ui/widget/clipmaskicon.cpp index 6331d70d8..943b1bebc 100644 --- a/src/ui/widget/clipmaskicon.cpp +++ b/src/ui/widget/clipmaskicon.cpp @@ -154,13 +154,12 @@ void ClipMaskIcon::render_vfunc( const Glib::RefPtr<Gdk::Drawable>& window, #endif } -bool -ClipMaskIcon::activate_vfunc(GdkEvent* event, - Gtk::Widget& /*widget*/, - const Glib::ustring& path, - const Gdk::Rectangle& /*background_area*/, - const Gdk::Rectangle& /*cell_area*/, - Gtk::CellRendererState /*flags*/) +bool ClipMaskIcon::activate_vfunc(GdkEvent* /*event*/, + Gtk::Widget& /*widget*/, + const Glib::ustring& /*path*/, + const Gdk::Rectangle& /*background_area*/, + const Gdk::Rectangle& /*cell_area*/, + Gtk::CellRendererState /*flags*/) { return false; } diff --git a/src/ui/widget/highlight-picker.cpp b/src/ui/widget/highlight-picker.cpp index 8593f0bdf..09999b52d 100644 --- a/src/ui/widget/highlight-picker.cpp +++ b/src/ui/widget/highlight-picker.cpp @@ -147,13 +147,12 @@ void HighlightPicker::render_vfunc( const Glib::RefPtr<Gdk::Drawable>& window, #endif } -bool -HighlightPicker::activate_vfunc(GdkEvent* event, - Gtk::Widget& /*widget*/, - const Glib::ustring& path, - const Gdk::Rectangle& /*background_area*/, - const Gdk::Rectangle& /*cell_area*/, - Gtk::CellRendererState /*flags*/) +bool HighlightPicker::activate_vfunc(GdkEvent* /*event*/, + Gtk::Widget& /*widget*/, + const Glib::ustring& /*path*/, + const Gdk::Rectangle& /*background_area*/, + const Gdk::Rectangle& /*cell_area*/, + Gtk::CellRendererState /*flags*/) { return false; } diff --git a/src/ui/widget/insertordericon.cpp b/src/ui/widget/insertordericon.cpp index a28b0f834..9aec7d135 100644 --- a/src/ui/widget/insertordericon.cpp +++ b/src/ui/widget/insertordericon.cpp @@ -135,13 +135,12 @@ void InsertOrderIcon::render_vfunc( const Glib::RefPtr<Gdk::Drawable>& window, #endif } -bool -InsertOrderIcon::activate_vfunc(GdkEvent* event, - Gtk::Widget& /*widget*/, - const Glib::ustring& path, - const Gdk::Rectangle& /*background_area*/, - const Gdk::Rectangle& /*cell_area*/, - Gtk::CellRendererState /*flags*/) +bool InsertOrderIcon::activate_vfunc(GdkEvent* /*event*/, + Gtk::Widget& /*widget*/, + const Glib::ustring& /*path*/, + const Gdk::Rectangle& /*background_area*/, + const Gdk::Rectangle& /*cell_area*/, + Gtk::CellRendererState /*flags*/) { return false; } diff --git a/src/ui/widget/registered-widget.cpp b/src/ui/widget/registered-widget.cpp index 44d8dcbf3..e97285de4 100644 --- a/src/ui/widget/registered-widget.cpp +++ b/src/ui/widget/registered-widget.cpp @@ -108,7 +108,7 @@ 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) +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>() , _active_str(active_str) , _inactive_str(inactive_str) |
