From ad30f531f53c28db8e21441264a34f4a7fbb16c7 Mon Sep 17 00:00:00 2001 From: Jabier Arraiza Date: Mon, 27 May 2019 18:31:12 +0200 Subject: Allow translations in LPE add dialog --- src/ui/dialog/livepatheffect-add.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/ui/dialog/livepatheffect-add.cpp b/src/ui/dialog/livepatheffect-add.cpp index 5d5517149..a31f71a8c 100644 --- a/src/ui/dialog/livepatheffect-add.cpp +++ b/src/ui/dialog/livepatheffect-add.cpp @@ -125,7 +125,7 @@ LivePathEffectAdd::LivePathEffectAdd() sigc::mem_fun(*this, &LivePathEffectAdd::mouseout), GTK_WIDGET(LPESelectorEffect->gobj()))); Gtk::Label *LPEName; builder_effect->get_widget("LPEName", LPEName); - const Glib::ustring label = converter.get_label(data->id); + const Glib::ustring label = _(converter.get_label(data->id).c_str()); const Glib::ustring untranslated_label = converter.get_untranslated_label(data->id); if (untranslated_label == label) { LPEName->set_text(label); -- cgit v1.2.3 From 931aa4a4032c99997058e33df72cd2a31e8e5eba Mon Sep 17 00:00:00 2001 From: Tobias Ellinghaus Date: Tue, 28 May 2019 08:48:23 +0200 Subject: Fix align-to of text objects Inkscape used to align text baselines relative to the wrong object when using "First selected" or "Last selected". Closes !699 --- src/ui/dialog/align-and-distribute.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/ui/dialog/align-and-distribute.cpp b/src/ui/dialog/align-and-distribute.cpp index c112f965d..a714b96f6 100644 --- a/src/ui/dialog/align-and-distribute.cpp +++ b/src/ui/dialog/align-and-distribute.cpp @@ -135,10 +135,10 @@ void ActionAlign::do_action(SPDesktop *desktop, int index) switch (AlignTarget(prefs->getInt("/dialogs/align/align-to", 6))) { case LAST: - focus = SP_ITEM(*--(selected.end())); + focus = SP_ITEM(selected.back()); break; case FIRST: - focus = SP_ITEM(*selected.begin()); + focus = SP_ITEM(selected.front()); break; case BIGGEST: focus = selection->largestItem(horiz); @@ -844,10 +844,10 @@ private : switch (AlignTarget(prefs->getInt("/dialogs/align/align-to", 6))) { case LAST: - focus = SP_ITEM(*selected.begin()); + focus = SP_ITEM(selected.back()); break; case FIRST: - focus = SP_ITEM(*--(selected.end())); + focus = SP_ITEM(selected.front()); break; case BIGGEST: focus = selection->largestItem(Selection::AREA); @@ -867,7 +867,7 @@ private : default: g_assert_not_reached (); break; - }; + }; if(focus) { if (SP_IS_TEXT (focus) || SP_IS_FLOWTEXT (focus)) { -- cgit v1.2.3 From deeb7b9d0523ebe9ea718737f1ff9d65bb4f8242 Mon Sep 17 00:00:00 2001 From: Tavmjong Bah Date: Tue, 28 May 2019 09:36:06 +0200 Subject: Set default PDF page to 1 (PDF's don't have page 0). --- src/inkscape-application.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/inkscape-application.cpp b/src/inkscape-application.cpp index 3b034b06b..70a27e1fd 100644 --- a/src/inkscape-application.cpp +++ b/src/inkscape-application.cpp @@ -66,7 +66,7 @@ InkscapeApplication::InkscapeApplication() , _active_document(nullptr) , _active_selection(nullptr) , _active_view(nullptr) - , _pdf_page(0) + , _pdf_page(1) , _pdf_poppler(false) {} -- cgit v1.2.3 From 901ad6c37df1b2f810599546901cc17a06b7b307 Mon Sep 17 00:00:00 2001 From: Tavmjong Bah Date: Tue, 28 May 2019 09:47:10 +0200 Subject: Prevent settng PDF page to less than 1. Fixes #265. --- src/inkscape.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/inkscape.h b/src/inkscape.h index 840620171..91af346cd 100644 --- a/src/inkscape.h +++ b/src/inkscape.h @@ -200,7 +200,9 @@ public: return _pdf_poppler; } void set_pdf_page(gint page) { - _pdf_page = page; + if (page > 0) { + _pdf_page = page; + } } gint get_pdf_page() { return _pdf_page; -- cgit v1.2.3 From b38dc8c2f956b367ca681dbdc8ed6ffc3c440fa1 Mon Sep 17 00:00:00 2001 From: Marc Jeanmougin Date: Tue, 28 May 2019 12:52:07 +0200 Subject: Update pofiles --- src/io/resource-manager.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'src') diff --git a/src/io/resource-manager.cpp b/src/io/resource-manager.cpp index 1ae02a886..c5ac0ef45 100644 --- a/src/io/resource-manager.cpp +++ b/src/io/resource-manager.cpp @@ -423,8 +423,7 @@ bool ResourceManagerImpl::searchUpwards( std::string const &base, std::string co static ResourceManagerImpl* theInstance = nullptr; ResourceManager::ResourceManager() -{ -} += default; ResourceManager::~ResourceManager() = default; -- cgit v1.2.3 From 9bba313d56fd87fc0a5033f566c3d63fe3c3d53e Mon Sep 17 00:00:00 2001 From: Sergei Izmailov Date: Tue, 28 May 2019 13:48:16 +0300 Subject: Fix segfault for bad `--pdf-page` argument values pdf-page value sanitization should be done after total number of pages is available, so it's can't be done in inkscape.h On negative or greater-than-number-of-pages values 1) the error message is printed to stderr 2) first page gets import pdf-page==0 sanitized elsewhere, so no error message is printed in this case --- src/extension/internal/pdfinput/pdf-input.cpp | 17 +++++++++++++++++ src/inkscape.h | 4 +--- 2 files changed, 18 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/extension/internal/pdfinput/pdf-input.cpp b/src/extension/internal/pdfinput/pdf-input.cpp index 3ff599ebf..5e0bb16e2 100644 --- a/src/extension/internal/pdfinput/pdf-input.cpp +++ b/src/extension/internal/pdfinput/pdf-input.cpp @@ -62,6 +62,19 @@ #include + +namespace { + void sanitize_page_number(int& page_num, const int num_pages){ + if (page_num < 1 || page_num > num_pages){ + std::cerr << "Inkscape::Extension::Internal::PdfInput::open: Bad page number " + << page_num + << ". Import first page instead." + << std::endl; + page_num = 1; + } + } +} + namespace Inkscape { namespace Extension { namespace Internal { @@ -815,6 +828,8 @@ PdfInput::open(::Inkscape::Extension::Input * /*mod*/, const gchar * uri) { sp_repr_get_double(prefs, "cropTo", &crop_setting); Catalog *catalog = pdf_doc->getCatalog(); + int const num_pages = catalog->getNumPages(); + sanitize_page_number(page_num, num_pages); Page *page = catalog->getPage(page_num); if ( crop_setting >= 0.0 ) { // Do page clipping @@ -899,6 +914,8 @@ PdfInput::open(::Inkscape::Extension::Input * /*mod*/, const gchar * uri) { if (document != NULL) { double width, height; + int const num_pages = poppler_document_get_n_pages(document); + sanitize_page_number(page_num, num_pages); PopplerPage* page = poppler_document_get_page(document, page_num - 1); poppler_page_get_size(page, &width, &height); diff --git a/src/inkscape.h b/src/inkscape.h index 91af346cd..840620171 100644 --- a/src/inkscape.h +++ b/src/inkscape.h @@ -200,9 +200,7 @@ public: return _pdf_poppler; } void set_pdf_page(gint page) { - if (page > 0) { - _pdf_page = page; - } + _pdf_page = page; } gint get_pdf_page() { return _pdf_page; -- cgit v1.2.3 From a290421b993dd260112ddc86fc8ba3496bcbaef8 Mon Sep 17 00:00:00 2001 From: Sergei Izmailov Date: Tue, 28 May 2019 14:14:18 +0300 Subject: Fix formatting --- src/extension/internal/pdfinput/pdf-input.cpp | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) (limited to 'src') diff --git a/src/extension/internal/pdfinput/pdf-input.cpp b/src/extension/internal/pdfinput/pdf-input.cpp index 5e0bb16e2..0a543ca1a 100644 --- a/src/extension/internal/pdfinput/pdf-input.cpp +++ b/src/extension/internal/pdfinput/pdf-input.cpp @@ -64,15 +64,17 @@ namespace { - void sanitize_page_number(int& page_num, const int num_pages){ - if (page_num < 1 || page_num > num_pages){ - std::cerr << "Inkscape::Extension::Internal::PdfInput::open: Bad page number " - << page_num - << ". Import first page instead." - << std::endl; - page_num = 1; - } - } + +void sanitize_page_number(int &page_num, const int num_pages) { + if (page_num < 1 || page_num > num_pages) { + std::cerr << "Inkscape::Extension::Internal::PdfInput::open: Bad page number " + << page_num + << ". Import first page instead." + << std::endl; + page_num = 1; + } +} + } namespace Inkscape { -- cgit v1.2.3 From 437e28d328fd12bc757245cb8aa5039172811661 Mon Sep 17 00:00:00 2001 From: Sergei Izmailov Date: Mon, 27 May 2019 00:59:36 +0300 Subject: feature: Allow effect extensions to disable working dialog Effect extensions with custom GUI don't need 'effect is working' dialog window which distracts from effect main window. New "suppress-working-dialog" optional attribute added to effect node of `.inx` file. --- src/extension/effect.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/extension/effect.cpp b/src/extension/effect.cpp index f69ece42f..618b6f84a 100644 --- a/src/extension/effect.cpp +++ b/src/extension/effect.cpp @@ -63,6 +63,9 @@ Effect::Effect (Inkscape::XML::Node * in_repr, Implementation::Implementation * if (child->attribute("needs-live-preview") && !strcmp(child->attribute("needs-live-preview"), "false")) { no_live_preview = true; } + if (child->attribute("suppress-working-dialog") && !strcmp(child->attribute("suppress-working-dialog"), "true")) { + _workingDialog = false; + } for (Inkscape::XML::Node *effect_child = child->firstChild(); effect_child != nullptr; effect_child = effect_child->next()) { if (!strcmp(effect_child->name(), INKSCAPE_EXTENSION_NS "effects-menu")) { // printf("Found local effects menu in %s\n", this->get_name()); @@ -269,7 +272,7 @@ Effect::effect (Inkscape::UI::View::View * doc) if (!loaded()) set_state(Extension::STATE_LOADED); if (!loaded()) return; - ExecutionEnv executionEnv(this, doc); + ExecutionEnv executionEnv(this, doc, nullptr, _workingDialog, true); execution_env = &executionEnv; timer->lock(); executionEnv.run(); -- cgit v1.2.3 From 40b26e345fc729d5cc89105c437c2b934da8dd0e Mon Sep 17 00:00:00 2001 From: Sergei Izmailov Date: Mon, 27 May 2019 20:13:14 +0300 Subject: Rename "suppress-working-dialog" effect attribute to "application" --- src/extension/effect.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/extension/effect.cpp b/src/extension/effect.cpp index 618b6f84a..d0079e7cc 100644 --- a/src/extension/effect.cpp +++ b/src/extension/effect.cpp @@ -63,7 +63,7 @@ Effect::Effect (Inkscape::XML::Node * in_repr, Implementation::Implementation * if (child->attribute("needs-live-preview") && !strcmp(child->attribute("needs-live-preview"), "false")) { no_live_preview = true; } - if (child->attribute("suppress-working-dialog") && !strcmp(child->attribute("suppress-working-dialog"), "true")) { + if (child->attribute("application") && !strcmp(child->attribute("application"), "true")) { _workingDialog = false; } for (Inkscape::XML::Node *effect_child = child->firstChild(); effect_child != nullptr; effect_child = effect_child->next()) { -- cgit v1.2.3 From 9317c612c998b18b2334ea17ca89d9b9e2a97085 Mon Sep 17 00:00:00 2001 From: Sergei Izmailov Date: Mon, 27 May 2019 20:14:01 +0300 Subject: Fix indentation --- src/extension/effect.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/extension/effect.cpp b/src/extension/effect.cpp index d0079e7cc..2b08e4da1 100644 --- a/src/extension/effect.cpp +++ b/src/extension/effect.cpp @@ -58,13 +58,13 @@ Effect::Effect (Inkscape::XML::Node * in_repr, Implementation::Implementation * for (Inkscape::XML::Node *child = repr->firstChild(); child != nullptr; child = child->next()) { if (!strcmp(child->name(), INKSCAPE_EXTENSION_NS "effect")) { if (child->attribute("needs-document") && !strcmp(child->attribute("needs-document"), "false")) { - no_doc = true; + no_doc = true; } if (child->attribute("needs-live-preview") && !strcmp(child->attribute("needs-live-preview"), "false")) { - no_live_preview = true; + no_live_preview = true; } if (child->attribute("application") && !strcmp(child->attribute("application"), "true")) { - _workingDialog = false; + _workingDialog = false; } for (Inkscape::XML::Node *effect_child = child->firstChild(); effect_child != nullptr; effect_child = effect_child->next()) { if (!strcmp(effect_child->name(), INKSCAPE_EXTENSION_NS "effects-menu")) { -- cgit v1.2.3 From c79a9bc365eb0b1f638e7ffa670dffb61c665e22 Mon Sep 17 00:00:00 2001 From: Sergei Izmailov Date: Wed, 29 May 2019 02:59:11 +0300 Subject: Rename effect attribute to "implements-custom-gui" Effect with `implements-custom-gui="true"` MUST implement custom GUI --- src/extension/effect.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/extension/effect.cpp b/src/extension/effect.cpp index 2b08e4da1..3c9940240 100644 --- a/src/extension/effect.cpp +++ b/src/extension/effect.cpp @@ -63,7 +63,7 @@ Effect::Effect (Inkscape::XML::Node * in_repr, Implementation::Implementation * if (child->attribute("needs-live-preview") && !strcmp(child->attribute("needs-live-preview"), "false")) { no_live_preview = true; } - if (child->attribute("application") && !strcmp(child->attribute("application"), "true")) { + if (child->attribute("implements-custom-gui") && !strcmp(child->attribute("implements-custom-gui"), "true")) { _workingDialog = false; } for (Inkscape::XML::Node *effect_child = child->firstChild(); effect_child != nullptr; effect_child = effect_child->next()) { -- cgit v1.2.3 From d66a11f144601d1bb2fb0007e3e4463a393b6bd3 Mon Sep 17 00:00:00 2001 From: Thomas Holder Date: Wed, 29 May 2019 19:28:02 +0000 Subject: macOS: gtk-mac-integration --- src/inkscape-application.cpp | 28 ++++++++++++++++++++++++++++ src/widgets/desktop-widget.cpp | 19 +++++++++++++++++++ src/widgets/desktop-widget.h | 2 ++ 3 files changed, 49 insertions(+) (limited to 'src') diff --git a/src/inkscape-application.cpp b/src/inkscape-application.cpp index 70a27e1fd..a019d8515 100644 --- a/src/inkscape-application.cpp +++ b/src/inkscape-application.cpp @@ -42,6 +42,10 @@ #include "actions/actions-selection.h" // Actions #include "actions/actions-transform.h" // Actions +#ifdef GDK_WINDOWING_QUARTZ +#include +#endif + #ifdef WITH_DBUS # include "extension/dbus/dbus-init.h" #endif @@ -572,6 +576,11 @@ ConcreteInkscapeApplication::on_startup2() Inkscape::Application::create(nullptr, false); } +#ifdef GDK_WINDOWING_QUARTZ +static gboolean osx_openfile_callback(GtkosxApplication *, gchar const *, + ConcreteInkscapeApplication *); +#endif + template<> void ConcreteInkscapeApplication::on_startup2() @@ -614,6 +623,11 @@ ConcreteInkscapeApplication::on_startup2() } else { // set_app_menu(menu); } + +#ifdef GDK_WINDOWING_QUARTZ + GtkosxApplication *osxapp = gtkosx_application_get(); + g_signal_connect(G_OBJECT(osxapp), "NSApplicationOpenFile", G_CALLBACK(osx_openfile_callback), this); +#endif } /** We should not create a window if T is Gio::Applicaton. @@ -709,6 +723,20 @@ ConcreteInkscapeApplication::create_window(const Glib::RefPtr< return (desktop); // Temp: Need to track desktop for shell mode. } +#ifdef GDK_WINDOWING_QUARTZ +/** + * On macOS, handle dropping files on Inkscape.app icon and "Open With" file association. + */ +static gboolean osx_openfile_callback(GtkosxApplication *osxapp, gchar const *path, + ConcreteInkscapeApplication *app) +{ + auto ptr = Gio::File::create_for_path(path); + g_return_val_if_fail(ptr, false); + app->create_window(ptr); + return true; +} +#endif + /** No need to destroy window if T is Gio::Application. */ template diff --git a/src/widgets/desktop-widget.cpp b/src/widgets/desktop-widget.cpp index 32ca1bac2..f4e278a5a 100644 --- a/src/widgets/desktop-widget.cpp +++ b/src/widgets/desktop-widget.cpp @@ -79,6 +79,9 @@ #include "toolbox.h" #include "widget-sizes.h" +#ifdef GDK_WINDOWING_QUARTZ +#include +#endif using Inkscape::DocumentUndo; using Inkscape::UI::Widget::UnitTracker; @@ -928,6 +931,17 @@ sp_desktop_widget_realize (GtkWidget *widget) window->get_style_context()->remove_class("symbolic"); } } + +#ifdef GDK_WINDOWING_QUARTZ + // native macOS menu + auto osxapp = gtkosx_application_get(); + auto menushell = static_cast(dtw->menubar()); + if (osxapp && menushell && window) { + menushell->set_parent(*window); + gtkosx_application_set_menu_bar(osxapp, menushell->gobj()); + gtkosx_application_set_use_quartz_accelerators(osxapp, false); + } +#endif } /* This is just to provide access to common functionality from sp_desktop_widget_realize() above @@ -1691,7 +1705,12 @@ SPDesktopWidget* SPDesktopWidget::createInstance(SPDocument *document) dtw->_menubar = build_menubar(dtw->desktop); dtw->_menubar->set_name("MenuBar"); dtw->_menubar->show_all(); + +#ifdef GDK_WINDOWING_QUARTZ + // native macOS menu: do this later because we don't have the window handle yet +#else dtw->_vbox->pack_start(*dtw->_menubar, false, false); +#endif dtw->layoutWidgets(); diff --git a/src/widgets/desktop-widget.h b/src/widgets/desktop-widget.h index f0b42222d..d21ba7bb8 100644 --- a/src/widgets/desktop-widget.h +++ b/src/widgets/desktop-widget.h @@ -269,6 +269,8 @@ public: void updateTitle(gchar const *uri); bool onFocusInEvent(GdkEventFocus*); + Gtk::MenuBar *menubar() { return _menubar; } + Inkscape::UI::Widget::Dock* getDock(); static GType getType(); -- cgit v1.2.3 From 6e3334d29bdd5e7581a64258a560514b8832f128 Mon Sep 17 00:00:00 2001 From: Thomas Holder Date: Thu, 30 May 2019 20:42:09 +0200 Subject: fix global-buffer-overflow (AddressSanitizer) --- src/seltrans.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/seltrans.cpp b/src/seltrans.cpp index ff3804acb..c173c9474 100644 --- a/src/seltrans.cpp +++ b/src/seltrans.cpp @@ -677,8 +677,8 @@ void Inkscape::SelTrans::_makeHandles() knots[i]->setSize(13); knots[i]->setAnchor(hands[i].anchor); knots[i]->setMode(SP_CTRL_MODE_XOR); - knots[i]->setFill(info.color[0], info.color[1], info.color[2], info.color[1]); - knots[i]->setStroke(info.color[3], info.color[4], info.color[5], info.color[4]); + knots[i]->setFill(info.color[0], info.color[1], info.color[1], info.color[1]); + knots[i]->setStroke(info.color[2], info.color[3], info.color[3], info.color[3]); knots[i]->setPixbuf(handles[hands[i].control]); knots[i]->updateCtrl(); -- cgit v1.2.3 From f75834db06399fac617526b12adf70bc3cf379e1 Mon Sep 17 00:00:00 2001 From: Thomas Holder Date: Wed, 29 May 2019 20:04:33 +0200 Subject: fix #140 scaled text flow into frame --- src/text-chemistry.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/text-chemistry.cpp b/src/text-chemistry.cpp index 8a2433ec6..802f10a3f 100644 --- a/src/text-chemistry.cpp +++ b/src/text-chemistry.cpp @@ -334,9 +334,10 @@ text_flow_into_shape() } else { // SVG 1.2 Flowed Text - if (SP_IS_TEXT(text)) { + if (SP_IS_TEXT(text) || SP_IS_FLOWTEXT(text)) { // remove transform from text, but recursively scale text's fontsize by the expansion - SP_TEXT(text)->_adjustFontsizeRecursive(text, text->transform.descrim()); + auto ex = i2i_affine(text, shape->parent).descrim(); + SP_TEXT(text)->_adjustFontsizeRecursive(text, ex); text->getRepr()->setAttribute("transform", nullptr); } -- cgit v1.2.3 From 174908a7e0d4fec3657da94d243ef30b14b8f30b Mon Sep 17 00:00:00 2001 From: Jabier Arraiza Date: Sat, 1 Jun 2019 08:39:07 +0200 Subject: Allow rects be LPE like other primitives --- src/object/sp-rect.cpp | 48 +++++++++++++++++++++++++++------ src/object/sp-rect.h | 2 +- src/ui/clipboard.cpp | 3 --- src/ui/dialog/livepatheffect-editor.cpp | 23 ---------------- src/ui/dialog/livepatheffect-editor.h | 1 - 5 files changed, 41 insertions(+), 36 deletions(-) (limited to 'src') diff --git a/src/object/sp-rect.cpp b/src/object/sp-rect.cpp index 207d2fc5a..1ecfab558 100644 --- a/src/object/sp-rect.cpp +++ b/src/object/sp-rect.cpp @@ -19,9 +19,10 @@ #include "attributes.h" #include "style.h" #include "sp-rect.h" -#include #include "sp-guide.h" #include "preferences.h" +#include "svg/svg.h" +#include #define noRECT_VERBOSE @@ -193,6 +194,20 @@ const char* SPRect::displayName() const { #define C1 0.554 void SPRect::set_shape() { + if (hasBrokenPathEffect()) { + g_warning ("The spiral shape has unknown LPE on it! Convert to path to make it editable preserving the appearance; editing it as spiral will remove the bad LPE"); + + if (this->getRepr()->attribute("d")) { + // unconditionally read the curve from d, if any, to preserve appearance + Geom::PathVector pv = sp_svg_read_pathv(this->getRepr()->attribute("d")); + SPCurve *cold = new SPCurve(pv); + this->setCurveInsync(cold); + this->setCurveBeforeLPE( cold ); + cold->unref(); + } + + return; + } if ((this->height.computed < 1e-18) || (this->width.computed < 1e-18)) { this->setCurveInsync(nullptr); this->setCurveBeforeLPE(nullptr); @@ -259,13 +274,26 @@ void SPRect::set_shape() { c->lineto(x + w, y + h); c->lineto(x + 0.0, y + h); } - - c->closepath(); - this->setCurveInsync(c); - this->setCurveBeforeLPE(c); - - // LPE is not applied because result can generally not be represented as SPRect - + /* Reset the shape's curve to the "original_curve" + * This is very important for LPEs to work properly! (the bbox might be recalculated depending on the curve in shape)*/ + SPCurve * before = this->getCurveBeforeLPE(); + bool haslpe = this->hasPathEffectOnClipOrMaskRecursive(this); + if (before || haslpe) { + if (c && before && before->get_pathvector() != c->get_pathvector()){ + this->setCurveBeforeLPE(c); + sp_lpe_item_update_patheffect(this, true, false); + } else if(haslpe) { + this->setCurveBeforeLPE(c); + } else { + //This happends on undo, fix bug:#1791784 + this->setCurveInsync(c); + } + } else { + this->setCurveInsync(c); + } + if (before) { + before->unref(); + } c->unref(); } @@ -300,6 +328,10 @@ void SPRect::setRy(bool set, gdouble value) { this->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG); } +void SPRect::update_patheffect(bool write) { + SPShape::update_patheffect(write); +} + Geom::Affine SPRect::set_transform(Geom::Affine const& xform) { /* Calculate rect start in parent coords. */ Geom::Point pos(Geom::Point(this->x.computed, this->y.computed) * xform); diff --git a/src/object/sp-rect.h b/src/object/sp-rect.h index 39fac16f9..bbc9d3c69 100644 --- a/src/object/sp-rect.h +++ b/src/object/sp-rect.h @@ -57,7 +57,7 @@ public: Inkscape::XML::Node* write(Inkscape::XML::Document *xml_doc, Inkscape::XML::Node *repr, unsigned int flags) override; const char* displayName() const override; - + void update_patheffect(bool write) override; void set_shape() override; Geom::Affine set_transform(Geom::Affine const& xform) override; diff --git a/src/ui/clipboard.cpp b/src/ui/clipboard.cpp index f96fa607e..7460822c9 100644 --- a/src/ui/clipboard.cpp +++ b/src/ui/clipboard.cpp @@ -1100,9 +1100,6 @@ void ClipboardManagerImpl::_applyPathEffect(SPItem *item, gchar const *effectsta if ( item == nullptr ) { return; } - if ( dynamic_cast(item) ) { - return; - } SPLPEItem *lpeitem = dynamic_cast(item); if (lpeitem) diff --git a/src/ui/dialog/livepatheffect-editor.cpp b/src/ui/dialog/livepatheffect-editor.cpp index 097078e56..8767a109f 100644 --- a/src/ui/dialog/livepatheffect-editor.cpp +++ b/src/ui/dialog/livepatheffect-editor.cpp @@ -35,7 +35,6 @@ #include "object/sp-item-group.h" #include "object/sp-path.h" -#include "object/sp-rect.h" #include "object/sp-use.h" #include "object/sp-text.h" @@ -407,27 +406,6 @@ LivePathEffectEditor::setDesktop(SPDesktop *desktop) } } -void -LivePathEffectEditor::rectsToCurves(SPItem* topitem, SPItem *item) -{ - Inkscape::Selection *sel = _getSelection(); - if ( dynamic_cast(item) ) { - sel->clear(); - sel->set(item); - sel->toCurves(); - if (topitem == item) { - return; - } - } else if( SPGroup *group = dynamic_cast(item)){ - std::vector const item_list = sp_item_group_item_list(group); - for (auto sub_item : item_list) { - rectsToCurves(topitem, sub_item); - } - } - sel->set(topitem); -} - - /*######################################################################## # BUTTON CLICK HANDLERS (callbacks) ########################################################################*/ @@ -455,7 +433,6 @@ LivePathEffectEditor::onAdd() if (!data) { return; } - rectsToCurves(item, item); item = sel->singleItem(); // get new item LivePathEffect::Effect::createAndApply(data->key.c_str(), doc, item); diff --git a/src/ui/dialog/livepatheffect-editor.h b/src/ui/dialog/livepatheffect-editor.h index 600754ce3..30524e483 100644 --- a/src/ui/dialog/livepatheffect-editor.h +++ b/src/ui/dialog/livepatheffect-editor.h @@ -71,7 +71,6 @@ private: void effect_list_reload(SPLPEItem *lpeitem); void set_sensitize_all(bool sensitive); - void rectsToCurves(SPItem *topitem, SPItem *item); void showParams(LivePathEffect::Effect& effect); void showText(Glib::ustring const &str); void selectInList(LivePathEffect::Effect* effect); -- cgit v1.2.3 From e00088acaec9f2a7587e215d6771eadf8a216b3c Mon Sep 17 00:00:00 2001 From: octycs <2087987-octycs@users.noreply.gitlab.com> Date: Sat, 1 Jun 2019 16:50:20 +0200 Subject: Cache bounding box of shapes --- src/object/sp-shape.cpp | 15 +++++++++++++++ src/object/sp-shape.h | 5 +++++ 2 files changed, 20 insertions(+) (limited to 'src') diff --git a/src/object/sp-shape.cpp b/src/object/sp-shape.cpp index d615980c0..eb4c01e54 100644 --- a/src/object/sp-shape.cpp +++ b/src/object/sp-shape.cpp @@ -121,6 +121,10 @@ void SPShape::update(SPCtx* ctx, guint flags) { // std::cout << "SPShape::update(): " << (getId()?getId():"null") << std::endl; SPLPEItem::update(ctx, flags); + // Any update can change the bounding box, + // so the cached version can no longer be used. + bbox_cache_is_valid = false; + /* This stanza checks that an object's marker style agrees with * the marker objects it has allocated. sp_shape_set_marker ensures * that the appropriate marker objects are present (or absent) to @@ -456,6 +460,13 @@ void SPShape::modified(unsigned int flags) { } Geom::OptRect SPShape::bbox(Geom::Affine const &transform, SPItem::BBoxType bboxtype) const { + // If the object is clipped, the update funcation that invalidates + // the cache doesn't get called if the object is moved, so we need + // to compare the transformations as well. + if (bbox_cache_is_valid && transform == bbox_transform_cache) { + return bbox_cache; + } + Geom::OptRect bbox; if (!this->_curve || this->_curve->get_pathvector().empty()) { @@ -641,6 +652,10 @@ Geom::OptRect SPShape::bbox(Geom::Affine const &transform, SPItem::BBoxType bbox } } + bbox_transform_cache = transform; + bbox_cache = bbox; + bbox_cache_is_valid = true; + return bbox; } diff --git a/src/object/sp-shape.h b/src/object/sp-shape.h index 6289be079..10d719648 100644 --- a/src/object/sp-shape.h +++ b/src/object/sp-shape.h @@ -49,6 +49,11 @@ public: int hasMarkers () const; int numberOfMarkers (int type) const; + // bbox cache + mutable bool bbox_cache_is_valid = false; + mutable Geom::Affine bbox_transform_cache; + mutable Geom::OptRect bbox_cache; + public: // temporarily public, until SPPath is properly classed, etc. SPCurve *_curve_before_lpe; -- cgit v1.2.3 From 099344712de8f79db29196442411c7bbdf1d227a Mon Sep 17 00:00:00 2001 From: Jabier Arraiza Date: Sat, 6 Apr 2019 03:23:31 +0200 Subject: Add CSSDialog simplify --- src/ui/dialog/styledialog.cpp | 105 ++++++++++++++++++++++++++++++------------ src/ui/dialog/styledialog.h | 11 ++--- 2 files changed, 78 insertions(+), 38 deletions(-) (limited to 'src') diff --git a/src/ui/dialog/styledialog.cpp b/src/ui/dialog/styledialog.cpp index 93f699ec2..68c957dc7 100644 --- a/src/ui/dialog/styledialog.cpp +++ b/src/ui/dialog/styledialog.cpp @@ -83,8 +83,6 @@ StyleDialog::StyleDialog() Gtk::TreeViewColumn *col = _treeView.get_column(addCol); if (col) { col->add_attribute(addRenderer->property_visible(), _cssColumns.deleteButton); - col->set_sort_column(_cssColumns.deleteButton); - Gtk::Image *add_icon = Gtk::manage(sp_get_icon_image("list-add", Gtk::ICON_SIZE_SMALL_TOOLBAR)); col->set_clickable(true); col->set_widget(*add_icon); @@ -105,33 +103,22 @@ StyleDialog::StyleDialog() if (_propCol) { _propCol->add_attribute(renderer->property_text(), _cssColumns.label); _propCol->add_attribute(renderer->property_foreground_rgba(), _cssColumns.label_color); - _propCol->set_sort_column(_cssColumns.label); } - + renderer->signal_edited().connect(sigc::mem_fun(*this, &CssDialog::nameEdited)); renderer = Gtk::manage(new Gtk::CellRendererText()); - renderer->property_editable() = false; - int attrColNum = _treeView.append_column("Set", *renderer) - 1; + renderer->property_editable() = true; + int attrColNum = _treeView.append_column("Value", *renderer) - 1; _attrCol = _treeView.get_column(attrColNum); if (_attrCol) { _attrCol->add_attribute(renderer->property_text(), _cssColumns._styleAttrVal); _attrCol->add_attribute(renderer->property_foreground_rgba(), _cssColumns.attr_color); - _attrCol->add_attribute(renderer->property_strikethrough(), _cssColumns.attr_strike); - _attrCol->add_attribute(renderer->property_editable(), _cssColumns.editable); - _attrCol->set_sort_column(_cssColumns._styleAttrVal); } - + renderer->signal_edited().connect(sigc::mem_fun(*this, &CssDialog::valueEdited)); renderer = Gtk::manage(new Gtk::CellRendererText()); renderer->property_editable() = true; - int sheetColNum = _treeView.append_column("Actual", *renderer) - 1; - _sheetCol = _treeView.get_column(sheetColNum); - if (_sheetCol) { - _sheetCol->add_attribute(renderer->property_text(), _cssColumns._styleSheetVal); - _sheetCol->add_attribute(renderer->property_foreground_rgba(), _cssColumns.label_color); - _sheetCol->set_sort_column(_cssColumns._styleSheetVal); - } // Set the initial sort column (and direction) to place real attributes at the top. - _store->set_sort_column(_cssColumns.deleteButton, Gtk::SORT_DESCENDING); + _store->set_sort_column(_cssColumns.label, Gtk::SORT_ASCENDING); _getContents()->pack_start(*_scrolledWindow, Gtk::PACK_EXPAND_WIDGET); @@ -264,24 +251,24 @@ void StyleDialog::onAttrChanged(Inkscape::XML::Node *repr, const gchar *name, co std::map attr_prop = parseStyle(new_value); for (auto iter : obj->style->properties()) { - if (iter->style && iter->style_src != SP_STYLE_SRC_UNSET) { - Gtk::TreeModel::Row row = *(_store->append()); - // Delete is available to attribute properties only in attr mode. - row[_cssColumns.deleteButton] = iter->style_src == SP_STYLE_SRC_ATTRIBUTE; - row[_cssColumns.label] = iter->name; + if (iter->style_src != SP_STYLE_SRC_UNSET) { if (attr_prop.count(iter->name)) { + Gtk::TreeModel::Row row = *(_store->append()); + // Delete is available to attribute properties only in attr mode. + row[_cssColumns.deleteButton] = iter->style_src == SP_STYLE_SRC_ATTRIBUTE; + row[_cssColumns.label] = iter->name; row[_cssColumns._styleAttrVal] = attr_prop[iter->name]; - if (attr_prop[iter->name] != iter->get_value()) { - row[_cssColumns._styleSheetVal] = iter->get_value(); - row[_cssColumns.attr_color] = Gdk::RGBA("gray"); - row[_cssColumns.attr_strike] = true; - } row[_cssColumns.deleteButton] = true; - } else { - row[_cssColumns._styleSheetVal] = iter->get_value(); +/* } else if (iter->style) { + Gtk::TreeModel::Row row = *(_store->append()); + // Delete is available to attribute properties only in attr mode. + row[_cssColumns.deleteButton] = iter->style_src == SP_STYLE_SRC_ATTRIBUTE; + row[_cssColumns.label] = iter->name; + row[_cssColumns._styleAttrVal] = iter->get_value(); row[_cssColumns.label_color] = Gdk::RGBA("gray"); row[_cssColumns.attr_color] = Gdk::RGBA("gray"); row[_cssColumns.deleteButton] = false; + */ } } } @@ -362,6 +349,64 @@ bool StyleDialog::onPropertyCreate(GdkEventButton *event) return false; } +/** + * @brief CssDialog::onKeyPressed + * @param event_description + * @return + * Send an undo message and mark this point for undo + */ +void CssDialog::setUndo(Glib::ustring const &event_description) +{ + SPDocument *document = this->_desktop->doc(); + DocumentUndo::done(document, SP_VERB_DIALOG_XML_EDITOR, event_description); +} + +/** + * @brief CssDialog::nameEdited + * @param event + * @return + * Called when the name is edited in the TreeView editable column + */ +void CssDialog::nameEdited (const Glib::ustring& path, const Glib::ustring& name) +{ + Gtk::TreeModel::Row row = *_store->get_iter(path); + if(row && this->_repr) { + Glib::ustring old_name = row[_cssColumns.label]; + Glib::ustring value = row[_cssColumns._styleAttrVal]; + // Move to editing value, we set the name as a temporary store value + if (!old_name.empty()) { + // Remove old named value + onPropertyDelete(path); + setStyleProperty(name, " "); + } + if (!name.empty()) { + row[_cssColumns.label] = name; + } + this->setUndo(_("Rename CSS attribute")); + } +} + +/** + * @brief CssDialog::valueEdited + * @param event + * @return + * Called when the value is edited in the TreeView editable column + */ +void CssDialog::valueEdited (const Glib::ustring& path, const Glib::ustring& value) +{ + Gtk::TreeModel::Row row = *_store->get_iter(path); + if(row && this->_repr) { + Glib::ustring name = row[_cssColumns.label]; + if(name.empty()) return; + setStyleProperty(name, value); + if(!value.empty()) { + row[_cssColumns._styleAttrVal] = value; + } + + this->setUndo(_("Change attribute value")); + } +} + } // namespace Dialog } // namespace UI } // namespace Inkscape diff --git a/src/ui/dialog/styledialog.h b/src/ui/dialog/styledialog.h index 07d409ded..bb7c8b6e3 100644 --- a/src/ui/dialog/styledialog.h +++ b/src/ui/dialog/styledialog.h @@ -57,21 +57,15 @@ public: CssColumns() { add(deleteButton); add(label); - add(_styleSheetVal); add(_styleAttrVal); add(label_color); add(attr_color); - add(attr_strike); - add(editable); } Gtk::TreeModelColumn deleteButton; Gtk::TreeModelColumn label; Gtk::TreeModelColumn _styleAttrVal; - Gtk::TreeModelColumn _styleSheetVal; Gtk::TreeModelColumn label_color; Gtk::TreeModelColumn attr_color; - Gtk::TreeModelColumn attr_strike; - Gtk::TreeModelColumn editable; }; CssColumns _cssColumns; @@ -86,7 +80,6 @@ public: Glib::RefPtr _store; Gtk::TreeModel::Row _propRow; Gtk::TreeViewColumn *_propCol; - Gtk::TreeViewColumn *_sheetCol; Gtk::TreeViewColumn *_attrCol; Gtk::HBox status_box; Gtk::Label status; @@ -116,7 +109,9 @@ public: private: Glib::RefPtr r_props = Glib::Regex::create("\\s*;\\s*"); Glib::RefPtr r_pair = Glib::Regex::create("\\s*:\\s*"); - + void setUndo(Glib::ustring const &event_description); + void valueEdited (const Glib::ustring& path, const Glib::ustring& value); + void nameEdited (const Glib::ustring& path, const Glib::ustring& name); bool onPropertyCreate(GdkEventButton *event); void onPropertyDelete(Glib::ustring path); bool setStyleProperty(Glib::ustring name, Glib::ustring value); -- cgit v1.2.3 From 915ab57c874951759ffad4d144caf898789f1319 Mon Sep 17 00:00:00 2001 From: Jabiertxof Date: Sat, 6 Apr 2019 14:18:05 +0200 Subject: Including widgets --- src/ui/dialog/styledialog.cpp | 5 +- src/ui/dialog/styledialog.h | 112 +++++++++++++++++++++++++----------------- 2 files changed, 70 insertions(+), 47 deletions(-) (limited to 'src') diff --git a/src/ui/dialog/styledialog.cpp b/src/ui/dialog/styledialog.cpp index 68c957dc7..fb17fe21d 100644 --- a/src/ui/dialog/styledialog.cpp +++ b/src/ui/dialog/styledialog.cpp @@ -23,7 +23,6 @@ #include "ui/icon-loader.h" #include "ui/widget/iconrenderer.h" #include "verbs.h" - #include "xml/attribute-record.h" #include "xml/node-event-vector.h" #include @@ -33,7 +32,8 @@ static void on_attr_changed(Inkscape::XML::Node *repr, const gchar *name, const gchar * /*old_value*/, const gchar *new_value, bool /*is_interactive*/, gpointer data) { - STYLE_DIALOG(data)->onAttrChanged(repr, name, new_value); + CSS_DIALOG(data)->onAttrChanged(repr, name, new_value); + CSS_DIALOG(data)->styledialog = new Inkscape::UI::Dialog::StyleDialog(); } Inkscape::XML::NodeEventVector css_repr_events = { @@ -65,6 +65,7 @@ StyleDialog::StyleDialog() _treeView.set_headers_visible(true); auto _scrolledWindow = new Gtk::ScrolledWindow(); _scrolledWindow->add(_treeView); + _scrolledWindow->add(*styledialog); _scrolledWindow->set_policy(Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC); _store = Gtk::ListStore::create(_cssColumns); diff --git a/src/ui/dialog/styledialog.h b/src/ui/dialog/styledialog.h index bb7c8b6e3..05bbdb05c 100644 --- a/src/ui/dialog/styledialog.h +++ b/src/ui/dialog/styledialog.h @@ -50,7 +50,18 @@ public: ~StyleDialog() override; static StyleDialog &getInstance() { return *new StyleDialog(); } + Gtk::TreeView _treeView; + private: + // Monitor