From dca182031f3a9c95ae6a1f06c139a89c298846a1 Mon Sep 17 00:00:00 2001 From: Tavmjong Bah Date: Sun, 10 Jul 2016 16:51:02 +0200 Subject: Improve font editing dialog: 1. Allow for fonts with other than 1000 units per em. 2. Allow setting 'ascent', 'descent', etc. 3. Allow setting individual glyph horizontal advances. 4. Fix bug where 'units-per-em' was not read correctly. (bzr r15014.1.1) --- src/display/nr-svgfonts.cpp | 42 +++++++++++++++++++++++++++++++----------- src/display/nr-svgfonts.h | 3 ++- 2 files changed, 33 insertions(+), 12 deletions(-) (limited to 'src/display') diff --git a/src/display/nr-svgfonts.cpp b/src/display/nr-svgfonts.cpp index 011f51977..3f8113de8 100644 --- a/src/display/nr-svgfonts.cpp +++ b/src/display/nr-svgfonts.cpp @@ -197,6 +197,7 @@ SvgFont::scaled_font_text_to_glyphs (cairo_scaled_font_t */*scaled_font*/, bool is_horizontal_text = true; //TODO _utf8 = (char*) utf8; + double font_height = units_per_em(); while(g_utf8_get_char(_utf8)){ len = 0; for (i=0; i < (unsigned long) this->glyphs.size(); i++){ @@ -207,11 +208,11 @@ SvgFont::scaled_font_text_to_glyphs (cairo_scaled_font_t */*scaled_font*/, //apply glyph kerning if appropriate SPHkern *hkern = dynamic_cast(node); if (hkern && is_horizontal_text && MatchHKerningRule(hkern, this->glyphs[i], previous_unicode, previous_glyph_name) ){ - x -= (hkern->k / 1000.0);//TODO: use here the height of the font + x -= (hkern->k / font_height); } SPVkern *vkern = dynamic_cast(node); if (vkern && !is_horizontal_text && MatchVKerningRule(vkern, this->glyphs[i], previous_unicode, previous_glyph_name) ){ - y -= (vkern->k / 1000.0);//TODO: use here the "height" of the font + y -= (vkern->k / font_height); } } previous_unicode = const_cast(this->glyphs[i]->unicode.c_str());//used for kerning checking @@ -221,8 +222,15 @@ SvgFont::scaled_font_text_to_glyphs (cairo_scaled_font_t */*scaled_font*/, (*glyphs)[count++].y = y; //advance glyph coordinates: - if (is_horizontal_text) x+=(this->font->horiz_adv_x/1000.0);//TODO: use here the height of the font - else y+=(this->font->vert_adv_y/1000.0);//TODO: use here the "height" of the font + if (is_horizontal_text) { + if (this->glyphs[i]->horiz_adv_x != 0) { + x+=(this->glyphs[i]->horiz_adv_x/font_height); + } else { + x+=(this->font->horiz_adv_x/font_height); + } + } else { + y+=(this->font->vert_adv_y/font_height); + } _utf8+=len; //advance 'len' bytes in our string pointer //continue; goto raptorz; @@ -235,8 +243,8 @@ SvgFont::scaled_font_text_to_glyphs (cairo_scaled_font_t */*scaled_font*/, (*glyphs)[count++].y = y; //advance glyph coordinates: - if (is_horizontal_text) x+=(this->font->horiz_adv_x/1000.0);//TODO: use here the height of the font - else y+=(this->font->vert_adv_y/1000.0);//TODO: use here the "height" of the font + if (is_horizontal_text) x+=(this->font->horiz_adv_x/font_height);//TODO: use here the height of the font + else y+=(this->font->vert_adv_y/font_height);//TODO: use here the "height" of the font _utf8 = g_utf8_next_char(_utf8); //advance 1 char in our string pointer } @@ -252,9 +260,7 @@ SvgFont::render_glyph_path(cairo_t* cr, Geom::PathVector* pathv){ cairo_new_path(cr); //adjust scale of the glyph -// Geom::Scale s(1.0/((SPFont*) node->parent)->horiz_adv_x); - Geom::Scale s(1.0/1000);//TODO: use here the units-per-em attribute? - + Geom::Scale s(1.0/units_per_em()); Geom::Rect area( Geom::Point(0,0), Geom::Point(1,1) ); //I need help here! (reaction: note that the 'area' parameter is an *optional* rect, so you can pass an empty Geom::OptRect() ) feed_pathvector_to_cairo (cr, *pathv, s, area, false, 0); @@ -270,11 +276,11 @@ SvgFont::glyph_modified(SPObject* /* blah */, unsigned int /* bleh */){ Geom::PathVector SvgFont::flip_coordinate_system(SPFont* spfont, Geom::PathVector pathv){ - double units_per_em = 1000; + double units_per_em = 1024; for (SPObject *obj = spfont->children; obj; obj = obj->next){ if (dynamic_cast(obj)) { //XML Tree being directly used here while it shouldn't be. - sp_repr_get_double(obj->getRepr(), "units_per_em", &units_per_em); + sp_repr_get_double(obj->getRepr(), "units-per-em", &units_per_em); } } @@ -395,6 +401,20 @@ void SvgFont::refresh(){ this->userfont = NULL; } +double SvgFont::units_per_em() { + double units_per_em = 1024; + for (SPObject *obj = font->children; obj; obj = obj->next){ + if (dynamic_cast(obj)) { + //XML Tree being directly used here while it shouldn't be. + sp_repr_get_double(obj->getRepr(), "units-per-em", &units_per_em); + } + } + if (units_per_em <= 0.0) { + units_per_em = 1024; + } + return units_per_em; +} + /* Local Variables: mode:c++ diff --git a/src/display/nr-svgfonts.h b/src/display/nr-svgfonts.h index 21ab3ed02..d4488fb17 100644 --- a/src/display/nr-svgfonts.h +++ b/src/display/nr-svgfonts.h @@ -52,7 +52,8 @@ private: SPMissingGlyph* missingglyph; sigc::connection glyph_modified_connection; - bool drawing_expose_cb (Gtk::Widget *widget, GdkEventExpose *event, void* data); + double units_per_em(); + //bool drawing_expose_cb (Gtk::Widget *widget, GdkEventExpose *event, void* data); }; #endif //#ifndef NR_SVGFONTS_H_SEEN -- cgit v1.2.3 From 9e210a6d1333c3366681547e3e81593ef69ff73e Mon Sep 17 00:00:00 2001 From: Adrian Boguszewski Date: Thu, 14 Jul 2016 12:56:49 +0200 Subject: Last part of new SPObject children list (bzr r14954.1.20) --- src/display/nr-svgfonts.cpp | 35 ++++++++++++++++++++--------------- 1 file changed, 20 insertions(+), 15 deletions(-) (limited to 'src/display') diff --git a/src/display/nr-svgfonts.cpp b/src/display/nr-svgfonts.cpp index 011f51977..927093ef4 100644 --- a/src/display/nr-svgfonts.cpp +++ b/src/display/nr-svgfonts.cpp @@ -203,14 +203,19 @@ SvgFont::scaled_font_text_to_glyphs (cairo_scaled_font_t */*scaled_font*/, //check whether is there a glyph declared on the SVG document // that matches with the text string in its current position if ( (len = size_of_substring(this->glyphs[i]->unicode.c_str(), _utf8)) ){ - for(SPObject* node = this->font->children;previous_unicode && node;node=node->next){ + for(auto& node: font->_children) { + if (!previous_unicode) { + break; + } //apply glyph kerning if appropriate - SPHkern *hkern = dynamic_cast(node); - if (hkern && is_horizontal_text && MatchHKerningRule(hkern, this->glyphs[i], previous_unicode, previous_glyph_name) ){ + SPHkern *hkern = dynamic_cast(&node); + if (hkern && is_horizontal_text && + MatchHKerningRule(hkern, this->glyphs[i], previous_unicode, previous_glyph_name)) { x -= (hkern->k / 1000.0);//TODO: use here the height of the font } - SPVkern *vkern = dynamic_cast(node); - if (vkern && !is_horizontal_text && MatchVKerningRule(vkern, this->glyphs[i], previous_unicode, previous_glyph_name) ){ + SPVkern *vkern = dynamic_cast(&node); + if (vkern && !is_horizontal_text && + MatchVKerningRule(vkern, this->glyphs[i], previous_unicode, previous_glyph_name)) { y -= (vkern->k / 1000.0);//TODO: use here the "height" of the font } } @@ -271,10 +276,10 @@ SvgFont::glyph_modified(SPObject* /* blah */, unsigned int /* bleh */){ Geom::PathVector SvgFont::flip_coordinate_system(SPFont* spfont, Geom::PathVector pathv){ double units_per_em = 1000; - for (SPObject *obj = spfont->children; obj; obj = obj->next){ - if (dynamic_cast(obj)) { + for(auto& obj: spfont->_children) { + if (dynamic_cast(&obj)) { //XML Tree being directly used here while it shouldn't be. - sp_repr_get_double(obj->getRepr(), "units_per_em", &units_per_em); + sp_repr_get_double(obj.getRepr(), "units_per_em", &units_per_em); } } @@ -339,19 +344,19 @@ SvgFont::scaled_font_render_glyph (cairo_scaled_font_t */*scaled_font*/, if (node->hasChildren()){ //render the SVG described on this glyph's child nodes. - for(node = node->children; node; node=node->next){ + for(auto& child: node->_children) { { - SPPath *path = dynamic_cast(node); + SPPath *path = dynamic_cast(&child); if (path) { pathv = path->_curve->get_pathvector(); pathv = flip_coordinate_system(spfont, pathv); render_glyph_path(cr, &pathv); } } - if (dynamic_cast(node)) { + if (dynamic_cast(&child)) { g_warning("TODO: svgfonts: render OBJECTGROUP"); } - SPUse *use = dynamic_cast(node); + SPUse *use = dynamic_cast(&child); if (use) { SPItem* item = use->ref->getObject(); SPPath *path = dynamic_cast(item); @@ -374,12 +379,12 @@ SvgFont::scaled_font_render_glyph (cairo_scaled_font_t */*scaled_font*/, cairo_font_face_t* SvgFont::get_font_face(){ if (!this->userfont) { - for(SPObject* node = this->font->children;node;node=node->next){ - SPGlyph *glyph = dynamic_cast(node); + for(auto& node: font->_children) { + SPGlyph *glyph = dynamic_cast(&node); if (glyph) { glyphs.push_back(glyph); } - SPMissingGlyph *missing = dynamic_cast(node); + SPMissingGlyph *missing = dynamic_cast(&node); if (missing) { missingglyph = missing; } -- cgit v1.2.3 From 24d3f50003ca3cec6a03a7f5267cc4fe5588c69f Mon Sep 17 00:00:00 2001 From: Adrian Boguszewski Date: Thu, 14 Jul 2016 13:17:21 +0200 Subject: Renamed children list in SPObject (bzr r14954.1.21) --- src/display/nr-svgfonts.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'src/display') diff --git a/src/display/nr-svgfonts.cpp b/src/display/nr-svgfonts.cpp index 927093ef4..53a5cba49 100644 --- a/src/display/nr-svgfonts.cpp +++ b/src/display/nr-svgfonts.cpp @@ -203,7 +203,7 @@ SvgFont::scaled_font_text_to_glyphs (cairo_scaled_font_t */*scaled_font*/, //check whether is there a glyph declared on the SVG document // that matches with the text string in its current position if ( (len = size_of_substring(this->glyphs[i]->unicode.c_str(), _utf8)) ){ - for(auto& node: font->_children) { + for(auto& node: font->children) { if (!previous_unicode) { break; } @@ -276,7 +276,7 @@ SvgFont::glyph_modified(SPObject* /* blah */, unsigned int /* bleh */){ Geom::PathVector SvgFont::flip_coordinate_system(SPFont* spfont, Geom::PathVector pathv){ double units_per_em = 1000; - for(auto& obj: spfont->_children) { + for(auto& obj: spfont->children) { if (dynamic_cast(&obj)) { //XML Tree being directly used here while it shouldn't be. sp_repr_get_double(obj.getRepr(), "units_per_em", &units_per_em); @@ -344,7 +344,7 @@ SvgFont::scaled_font_render_glyph (cairo_scaled_font_t */*scaled_font*/, if (node->hasChildren()){ //render the SVG described on this glyph's child nodes. - for(auto& child: node->_children) { + for(auto& child: node->children) { { SPPath *path = dynamic_cast(&child); if (path) { @@ -379,7 +379,7 @@ SvgFont::scaled_font_render_glyph (cairo_scaled_font_t */*scaled_font*/, cairo_font_face_t* SvgFont::get_font_face(){ if (!this->userfont) { - for(auto& node: font->_children) { + for(auto& node: font->children) { SPGlyph *glyph = dynamic_cast(&node); if (glyph) { glyphs.push_back(glyph); -- cgit v1.2.3 From a2d656579397cef6bdfd4d9501af3b542e3b5617 Mon Sep 17 00:00:00 2001 From: Alex Valavanis Date: Wed, 27 Jul 2016 17:37:57 +0100 Subject: display.canvas-*grid: Drop GTK2 fallbacks (bzr r15023.2.3) --- src/display/canvas-axonomgrid.cpp | 40 ++------------------------------------- src/display/canvas-grid.cpp | 40 ++------------------------------------- 2 files changed, 4 insertions(+), 76 deletions(-) (limited to 'src/display') diff --git a/src/display/canvas-axonomgrid.cpp b/src/display/canvas-axonomgrid.cpp index 14f36376f..421a39fbd 100644 --- a/src/display/canvas-axonomgrid.cpp +++ b/src/display/canvas-axonomgrid.cpp @@ -19,12 +19,7 @@ #include #include - -#if WITH_GTKMM_3_0 -# include -#else -# include -#endif +#include #include @@ -94,15 +89,10 @@ namespace Inkscape { #define SPACE_SIZE_X 15 #define SPACE_SIZE_Y 10 static inline void -#if WITH_GTKMM_3_0 attach_all(Gtk::Grid &table, Gtk::Widget const *const arr[], unsigned size, int start = 0) -#else -attach_all(Gtk::Table &table, Gtk::Widget const *const arr[], unsigned size, int start = 0) -#endif { for (unsigned i=0, r=start; i(*arr[i])).set_hexpand(); (const_cast(*arr[i])).set_valign(Gtk::ALIGN_CENTER); table.attach(const_cast(*arr[i]), 1, r, 1, 1); @@ -110,44 +100,23 @@ attach_all(Gtk::Table &table, Gtk::Widget const *const arr[], unsigned size, int (const_cast(*arr[i+1])).set_hexpand(); (const_cast(*arr[i+1])).set_valign(Gtk::ALIGN_CENTER); table.attach(const_cast(*arr[i+1]), 2, r, 1, 1); -#else - table.attach (const_cast(*arr[i]), 1, 2, r, r+1, - Gtk::FILL|Gtk::EXPAND, (Gtk::AttachOptions)0,0,0); - table.attach (const_cast(*arr[i+1]), 2, 3, r, r+1, - Gtk::FILL|Gtk::EXPAND, (Gtk::AttachOptions)0,0,0); -#endif } else { if (arr[i+1]) { -#if WITH_GTKMM_3_0 (const_cast(*arr[i+1])).set_hexpand(); (const_cast(*arr[i+1])).set_valign(Gtk::ALIGN_CENTER); table.attach(const_cast(*arr[i+1]), 1, r, 2, 1); -#else - table.attach (const_cast(*arr[i+1]), 1, 3, r, r+1, - Gtk::FILL|Gtk::EXPAND, (Gtk::AttachOptions)0,0,0); -#endif } else if (arr[i]) { Gtk::Label& label = reinterpret_cast (const_cast(*arr[i])); label.set_alignment (0.0); -#if WITH_GTKMM_3_0 label.set_hexpand(); label.set_valign(Gtk::ALIGN_CENTER); table.attach(label, 0, r, 3, 1); -#else - table.attach (label, 0, 3, r, r+1, - Gtk::FILL|Gtk::EXPAND, (Gtk::AttachOptions)0,0,0); -#endif } else { Gtk::HBox *space = Gtk::manage (new Gtk::HBox); space->set_size_request (SPACE_SIZE_X, SPACE_SIZE_Y); -#if WITH_GTKMM_3_0 space->set_halign(Gtk::ALIGN_CENTER); space->set_valign(Gtk::ALIGN_CENTER); table.attach(*space, 0, r, 1, 1); -#else - table.attach (*space, 0, 1, r, r+1, - (Gtk::AttachOptions)0, (Gtk::AttachOptions)0,0,0); -#endif } } ++r; @@ -342,14 +311,9 @@ CanvasAxonomGrid::onReprAttrChanged(Inkscape::XML::Node */*repr*/, gchar const * Gtk::Widget * CanvasAxonomGrid::newSpecificWidget() { -#if WITH_GTKMM_3_0 - Gtk::Grid *table = Gtk::manage(new Gtk::Grid()); + auto table = Gtk::manage(new Gtk::Grid()); table->set_row_spacing(2); table->set_column_spacing(2); -#else - Gtk::Table * table = Gtk::manage( new Gtk::Table(1,1) ); - table->set_spacings(2); -#endif _wr.setUpdating (true); diff --git a/src/display/canvas-grid.cpp b/src/display/canvas-grid.cpp index decf93626..fa45fe02c 100644 --- a/src/display/canvas-grid.cpp +++ b/src/display/canvas-grid.cpp @@ -19,12 +19,7 @@ #include #include - -#if WITH_GTKMM_3_0 -# include -#else -# include -#endif +#include #include @@ -400,15 +395,10 @@ void CanvasGrid::setOrigin(Geom::Point const &origin_px) **/ #define SPACE_SIZE_X 15 #define SPACE_SIZE_Y 10 -#if WITH_GTKMM_3_0 static inline void attach_all(Gtk::Grid &table, Gtk::Widget const *const arr[], unsigned size, int start = 0) -#else -static inline void attach_all(Gtk::Table &table, Gtk::Widget const *const arr[], unsigned size, int start = 0) -#endif { for (unsigned i=0, r=start; i(*arr[i])).set_hexpand(); (const_cast(*arr[i])).set_valign(Gtk::ALIGN_CENTER); table.attach(const_cast(*arr[i]), 1, r, 1, 1); @@ -416,44 +406,23 @@ static inline void attach_all(Gtk::Table &table, Gtk::Widget const *const arr[], (const_cast(*arr[i+1])).set_hexpand(); (const_cast(*arr[i+1])).set_valign(Gtk::ALIGN_CENTER); table.attach(const_cast(*arr[i+1]), 2, r, 1, 1); -#else - table.attach (const_cast(*arr[i]), 1, 2, r, r+1, - Gtk::FILL|Gtk::EXPAND, (Gtk::AttachOptions)0,0,0); - table.attach (const_cast(*arr[i+1]), 2, 3, r, r+1, - Gtk::FILL|Gtk::EXPAND, (Gtk::AttachOptions)0,0,0); -#endif } else { if (arr[i+1]) { -#if WITH_GTKMM_3_0 (const_cast(*arr[i+1])).set_hexpand(); (const_cast(*arr[i+1])).set_valign(Gtk::ALIGN_CENTER); table.attach(const_cast(*arr[i+1]), 1, r, 2, 1); -#else - table.attach (const_cast(*arr[i+1]), 1, 3, r, r+1, - Gtk::FILL|Gtk::EXPAND, (Gtk::AttachOptions)0,0,0); -#endif } else if (arr[i]) { Gtk::Label& label = reinterpret_cast (const_cast(*arr[i])); label.set_alignment (0.0); -#if WITH_GTKMM_3_0 label.set_hexpand(); label.set_valign(Gtk::ALIGN_CENTER); table.attach(label, 0, r, 3, 1); -#else - table.attach (label, 0, 3, r, r+1, - Gtk::FILL|Gtk::EXPAND, (Gtk::AttachOptions)0,0,0); -#endif } else { Gtk::HBox *space = Gtk::manage (new Gtk::HBox); space->set_size_request (SPACE_SIZE_X, SPACE_SIZE_Y); -#if WITH_GTKMM_3_0 space->set_halign(Gtk::ALIGN_CENTER); space->set_valign(Gtk::ALIGN_CENTER); table.attach(*space, 0, r, 1, 1); -#else - table.attach (*space, 0, 1, r, r+1, - (Gtk::AttachOptions)0, (Gtk::AttachOptions)0,0,0); -#endif } } ++r; @@ -684,14 +653,9 @@ CanvasXYGrid::onReprAttrChanged(Inkscape::XML::Node */*repr*/, gchar const */*ke Gtk::Widget * CanvasXYGrid::newSpecificWidget() { -#if WITH_GTKMM_3_0 - Gtk::Grid * table = Gtk::manage( new Gtk::Grid() ); + auto table = Gtk::manage( new Gtk::Grid() ); table->set_row_spacing(2); table->set_column_spacing(2); -#else - Gtk::Table * table = Gtk::manage( new Gtk::Table(1,1) ); - table->set_spacings(2); -#endif Inkscape::UI::Widget::RegisteredUnitMenu *_rumg = Gtk::manage( new Inkscape::UI::Widget::RegisteredUnitMenu( _("Grid _units:"), "units", _wr, repr, doc) ); -- cgit v1.2.3 From 49a7927ecf31ace696e9e5770e8d6543c356db7a Mon Sep 17 00:00:00 2001 From: Alex Valavanis Date: Thu, 28 Jul 2016 19:15:34 +0100 Subject: Finish removing GTK+ 2 fallbacks (bzr r15023.2.8) --- src/display/sp-canvas.cpp | 100 +++++----------------------------------------- src/display/sp-canvas.h | 7 ---- 2 files changed, 10 insertions(+), 97 deletions(-) (limited to 'src/display') diff --git a/src/display/sp-canvas.cpp b/src/display/sp-canvas.cpp index 7d76fa043..9201168ef 100644 --- a/src/display/sp-canvas.cpp +++ b/src/display/sp-canvas.cpp @@ -322,13 +322,9 @@ void sp_canvas_item_dispose(GObject *object) if (item == item->canvas->_grabbed_item) { item->canvas->_grabbed_item = NULL; -#if GTK_CHECK_VERSION(3,0,0) - GdkDeviceManager *dm = gdk_display_get_device_manager(gdk_display_get_default()); - GdkDevice *device = gdk_device_manager_get_client_pointer(dm); + auto dm = gdk_display_get_device_manager(gdk_display_get_default()); + auto device = gdk_device_manager_get_client_pointer(dm); gdk_device_ungrab(device, GDK_CURRENT_TIME); -#else - gdk_pointer_ungrab (GDK_CURRENT_TIME); -#endif } if (item == item->canvas->_focused_item) { @@ -617,9 +613,8 @@ int sp_canvas_item_grab(SPCanvasItem *item, guint event_mask, GdkCursor *cursor, // fixme: Top hack (Lauris) // fixme: If we add key masks to event mask, Gdk will abort (Lauris) // fixme: But Canvas actualle does get key events, so all we need is routing these here -#if GTK_CHECK_VERSION(3,0,0) - GdkDeviceManager *dm = gdk_display_get_device_manager(gdk_display_get_default()); - GdkDevice *device = gdk_device_manager_get_client_pointer(dm); + auto dm = gdk_display_get_device_manager(gdk_display_get_default()); + auto device = gdk_device_manager_get_client_pointer(dm); gdk_device_grab(device, getWindow(item->canvas), GDK_OWNERSHIP_NONE, @@ -627,11 +622,6 @@ int sp_canvas_item_grab(SPCanvasItem *item, guint event_mask, GdkCursor *cursor, (GdkEventMask)(event_mask & (~(GDK_KEY_PRESS_MASK | GDK_KEY_RELEASE_MASK))), cursor, etime); -#else - gdk_pointer_grab( getWindow(item->canvas), FALSE, - (GdkEventMask)(event_mask & (~(GDK_KEY_PRESS_MASK | GDK_KEY_RELEASE_MASK))), - NULL, cursor, etime); -#endif item->canvas->_grabbed_item = item; item->canvas->_grabbed_event_mask = event_mask; @@ -658,13 +648,9 @@ void sp_canvas_item_ungrab(SPCanvasItem *item, guint32 etime) item->canvas->_grabbed_item = NULL; -#if GTK_CHECK_VERSION(3,0,0) - GdkDeviceManager *dm = gdk_display_get_device_manager(gdk_display_get_default()); - GdkDevice *device = gdk_device_manager_get_client_pointer(dm); + auto dm = gdk_display_get_device_manager(gdk_display_get_default()); + auto device = gdk_device_manager_get_client_pointer(dm); gdk_device_ungrab(device, etime); -#else - gdk_pointer_ungrab (etime); -#endif } /** @@ -913,16 +899,9 @@ void sp_canvas_class_init(SPCanvasClass *klass) widget_class->realize = SPCanvas::handle_realize; widget_class->unrealize = SPCanvas::handle_unrealize; - -#if GTK_CHECK_VERSION(3,0,0) widget_class->get_preferred_width = SPCanvas::handle_get_preferred_width; widget_class->get_preferred_height = SPCanvas::handle_get_preferred_height; widget_class->draw = SPCanvas::handle_draw; -#else - widget_class->size_request = SPCanvas::handle_size_request; - widget_class->expose_event = SPCanvas::handle_expose; -#endif - widget_class->size_allocate = SPCanvas::handle_size_allocate; widget_class->button_press_event = SPCanvas::handle_button; widget_class->button_release_event = SPCanvas::handle_button; @@ -980,13 +959,9 @@ void SPCanvas::shutdownTransients() if (_grabbed_item) { _grabbed_item = NULL; -#if GTK_CHECK_VERSION(3,0,0) - GdkDeviceManager *dm = gdk_display_get_device_manager(gdk_display_get_default()); - GdkDevice *device = gdk_device_manager_get_client_pointer(dm); + auto dm = gdk_display_get_device_manager(gdk_display_get_default()); + auto device = gdk_device_manager_get_client_pointer(dm); gdk_device_ungrab(device, GDK_CURRENT_TIME); -#else - gdk_pointer_ungrab(GDK_CURRENT_TIME); -#endif } removeIdle(); } @@ -1053,10 +1028,6 @@ void SPCanvas::handle_realize(GtkWidget *widget) attributes.wclass = GDK_INPUT_OUTPUT; attributes.visual = gdk_visual_get_system(); -#if !GTK_CHECK_VERSION(3,0,0) - attributes.colormap = gdk_colormap_get_system(); -#endif - attributes.event_mask = (gtk_widget_get_events (widget) | GDK_EXPOSURE_MASK | GDK_BUTTON_PRESS_MASK | @@ -1073,11 +1044,7 @@ void SPCanvas::handle_realize(GtkWidget *widget) GDK_SCROLL_MASK | GDK_FOCUS_CHANGE_MASK); -#if GTK_CHECK_VERSION(3,0,0) gint attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL; -#else - gint attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP; -#endif GdkWindow *window = gdk_window_new (gtk_widget_get_parent_window (widget), &attributes, attributes_mask); gtk_widget_set_window (widget, window); @@ -1086,18 +1053,8 @@ void SPCanvas::handle_realize(GtkWidget *widget) Inkscape::Preferences *prefs = Inkscape::Preferences::get(); if (prefs->getBool("/options/useextinput/value", true)) { gtk_widget_set_events(widget, attributes.event_mask); -#if !GTK_CHECK_VERSION(3,0,0) - gtk_widget_set_extension_events(widget, GDK_EXTENSION_EVENTS_ALL); - // TODO: Extension event stuff has been deprecated in GTK+ 3 -#endif } -#if !GTK_CHECK_VERSION(3,0,0) - // This does nothing in GTK+ 3 - GtkStyle *style = gtk_widget_get_style (widget); - gtk_widget_set_style (widget, gtk_style_attach (style, window)); -#endif - gtk_widget_set_realized (widget, TRUE); } @@ -1115,8 +1072,6 @@ void SPCanvas::handle_unrealize(GtkWidget *widget) (* GTK_WIDGET_CLASS(sp_canvas_parent_class)->unrealize)(widget); } - -#if GTK_CHECK_VERSION(3,0,0) void SPCanvas::handle_get_preferred_width(GtkWidget *widget, gint *minimum_width, gint *natural_width) { static_cast(SP_CANVAS (widget)); @@ -1130,16 +1085,6 @@ void SPCanvas::handle_get_preferred_height(GtkWidget *widget, gint *minimum_heig *minimum_height = 256; *natural_height = 256; } -#else -void SPCanvas::handle_size_request(GtkWidget *widget, GtkRequisition *req) -{ - static_cast(SP_CANVAS (widget)); - - req->width = 256; - req->height = 256; -} -#endif - void SPCanvas::handle_size_allocate(GtkWidget *widget, GtkAllocation *allocation) { @@ -1219,9 +1164,7 @@ int SPCanvas::emitEvent(GdkEvent *event) break; case GDK_SCROLL: mask = GDK_SCROLL_MASK; -#if GTK_CHECK_VERSION(3,0,0) mask |= GDK_SMOOTH_SCROLL_MASK; -#endif break; default: mask = 0; @@ -1503,13 +1446,9 @@ gint SPCanvas::handle_scroll(GtkWidget *widget, GdkEventScroll *event) } static inline void request_motions(GdkWindow *w, GdkEventMotion *event) { -#if GTK_CHECK_VERSION(3,0,0) gdk_window_get_device_position(w, gdk_event_get_device((GdkEvent *)(event)), NULL, NULL, NULL); -#else - gdk_window_get_pointer(w, NULL, NULL, NULL); -#endif gdk_event_request_motions(event); } @@ -1746,16 +1685,12 @@ bool SPCanvas::paintRect(int xx0, int yy0, int xx1, int yy1) // Save the mouse location gint x, y; -#if GTK_CHECK_VERSION(3,0,0) - GdkDeviceManager *dm = gdk_display_get_device_manager(gdk_display_get_default()); - GdkDevice *device = gdk_device_manager_get_client_pointer(dm); + auto dm = gdk_display_get_device_manager(gdk_display_get_default()); + auto device = gdk_device_manager_get_client_pointer(dm); gdk_window_get_device_position(gtk_widget_get_window(GTK_WIDGET(this)), device, &x, &y, NULL); -#else - gdk_window_get_pointer(gtk_widget_get_window(GTK_WIDGET(this)), &x, &y, NULL); -#endif setup.mouse_loc = sp_canvas_window_to_world(this, Geom::Point(x,y)); @@ -1818,21 +1753,6 @@ gboolean SPCanvas::handle_draw(GtkWidget *widget, cairo_t *cr) { return TRUE; } -#if !GTK_CHECK_VERSION(3,0,0) -gboolean SPCanvas::handle_expose(GtkWidget *widget, GdkEventExpose *event) -{ - cairo_t *cr = gdk_cairo_create(gtk_widget_get_window(widget)); - - gdk_cairo_region (cr, event->region); - cairo_clip (cr); - gboolean result = SPCanvas::handle_draw(widget, cr); - - cairo_destroy (cr); - - return result; -} -#endif - gint SPCanvas::handle_key_event(GtkWidget *widget, GdkEventKey *event) { diff --git a/src/display/sp-canvas.h b/src/display/sp-canvas.h index 171fdaf67..78d96d728 100644 --- a/src/display/sp-canvas.h +++ b/src/display/sp-canvas.h @@ -145,12 +145,8 @@ public: static void dispose(GObject *object); static void handle_realize(GtkWidget *widget); static void handle_unrealize(GtkWidget *widget); -#if GTK_CHECK_VERSION(3,0,0) static void handle_get_preferred_width(GtkWidget *widget, gint *min_w, gint *nat_w); static void handle_get_preferred_height(GtkWidget *widget, gint *min_h, gint *nat_h); -#else - static void handle_size_request(GtkWidget *widget, GtkRequisition *req); -#endif static void handle_size_allocate(GtkWidget *widget, GtkAllocation *allocation); static gint handle_button(GtkWidget *widget, GdkEventButton *event); @@ -162,9 +158,6 @@ public: static gint handle_scroll(GtkWidget *widget, GdkEventScroll *event); static gint handle_motion(GtkWidget *widget, GdkEventMotion *event); static gboolean handle_draw(GtkWidget *widget, cairo_t *cr); -#if !GTK_CHECK_VERSION(3,0,0) - static gboolean handle_expose(GtkWidget *widget, GdkEventExpose *event); -#endif static gint handle_key_event(GtkWidget *widget, GdkEventKey *event); static gint handle_crossing(GtkWidget *widget, GdkEventCrossing *event); static gint handle_focus_in(GtkWidget *widget, GdkEventFocus *event); -- cgit v1.2.3 From e471a664f923f517b68071f2e33fbb6ce070f8b7 Mon Sep 17 00:00:00 2001 From: Alex Valavanis Date: Mon, 8 Aug 2016 13:56:40 +0100 Subject: Remove deprecated Autotools and btool files. Please use CMake instead (bzr r15046) --- src/display/Makefile_insert | 125 -------------------------------------------- 1 file changed, 125 deletions(-) delete mode 100644 src/display/Makefile_insert (limited to 'src/display') diff --git a/src/display/Makefile_insert b/src/display/Makefile_insert deleted file mode 100644 index 419852f7d..000000000 --- a/src/display/Makefile_insert +++ /dev/null @@ -1,125 +0,0 @@ -## Makefile.am fragment sourced by src/Makefile.am. - -display/canvas-arena.$(OBJEXT): helper/sp-marshal.h -display/sp-canvas.$(OBJEXT): helper/sp-marshal.h - -ink_common_sources += \ - display/cairo-templates.h \ - display/cairo-utils.cpp \ - display/cairo-utils.h \ - display/canvas-arena.cpp \ - display/canvas-arena.h \ - display/canvas-axonomgrid.cpp \ - display/canvas-axonomgrid.h \ - display/canvas-bpath.cpp \ - display/canvas-bpath.h \ - display/canvas-grid.cpp \ - display/canvas-grid.h \ - display/canvas-temporary-item.cpp \ - display/canvas-temporary-item.h \ - display/canvas-temporary-item-list.cpp \ - display/canvas-temporary-item-list.h \ - display/canvas-text.cpp \ - display/canvas-text.h \ - display/curve.cpp \ - display/curve.h \ - display/drawing.cpp \ - display/drawing.h \ - display/drawing-context.cpp \ - display/drawing-context.h \ - display/drawing-group.cpp \ - display/drawing-group.h \ - display/drawing-image.cpp \ - display/drawing-image.h \ - display/drawing-item.cpp \ - display/drawing-item.h \ - display/drawing-pattern.cpp \ - display/drawing-pattern.h \ - display/drawing-shape.cpp \ - display/drawing-shape.h \ - display/drawing-surface.cpp \ - display/drawing-surface.h \ - display/drawing-text.cpp \ - display/drawing-text.h \ - display/gnome-canvas-acetate.cpp \ - display/gnome-canvas-acetate.h \ - display/grayscale.cpp \ - display/grayscale.h \ - display/guideline.cpp \ - display/guideline.h \ - display/nr-3dutils.cpp \ - display/nr-3dutils.h \ - display/nr-filter-blend.cpp \ - display/nr-filter-blend.h \ - display/nr-filter-colormatrix.cpp \ - display/nr-filter-colormatrix.h \ - display/nr-filter-component-transfer.cpp \ - display/nr-filter-component-transfer.h \ - display/nr-filter-composite.cpp \ - display/nr-filter-composite.h \ - display/nr-filter-convolve-matrix.cpp \ - display/nr-filter-convolve-matrix.h \ - display/nr-filter.cpp \ - display/nr-filter-diffuselighting.cpp \ - display/nr-filter-diffuselighting.h \ - display/nr-filter-displacement-map.cpp \ - display/nr-filter-displacement-map.h \ - display/nr-filter-flood.cpp \ - display/nr-filter-flood.h \ - display/nr-filter-gaussian.cpp \ - display/nr-filter-gaussian.h \ - display/nr-filter.h \ - display/nr-filter-image.cpp \ - display/nr-filter-image.h \ - display/nr-filter-merge.cpp \ - display/nr-filter-merge.h \ - display/nr-filter-morphology.cpp \ - display/nr-filter-morphology.h \ - display/nr-filter-offset.cpp \ - display/nr-filter-offset.h \ - display/nr-filter-primitive.cpp \ - display/nr-filter-primitive.h \ - display/nr-filter-slot.cpp \ - display/nr-filter-slot.h \ - display/nr-filter-specularlighting.cpp \ - display/nr-filter-specularlighting.h \ - display/nr-filter-tile.cpp \ - display/nr-filter-tile.h \ - display/nr-filter-turbulence.cpp \ - display/nr-filter-turbulence.h \ - display/nr-filter-types.h \ - display/nr-filter-units.cpp \ - display/nr-filter-units.h \ - display/nr-filter-utils.h \ - display/nr-light.cpp \ - display/nr-light.h \ - display/nr-light-types.h \ - display/nr-style.cpp \ - display/nr-style.h \ - display/nr-svgfonts.cpp \ - display/nr-svgfonts.h \ - display/rendermode.h \ - display/snap-indicator.cpp \ - display/snap-indicator.h \ - display/sodipodi-ctrl.cpp \ - display/sodipodi-ctrl.h \ - display/sodipodi-ctrlrect.cpp \ - display/sodipodi-ctrlrect.h \ - display/sp-canvas.cpp \ - display/sp-canvas.h \ - display/sp-canvas-item.h \ - display/sp-canvas-group.h \ - display/sp-canvas-util.cpp \ - display/sp-canvas-util.h \ - display/sp-ctrlcurve.cpp \ - display/sp-ctrlcurve.h \ - display/sp-ctrlline.cpp \ - display/sp-ctrlline.h \ - display/sp-ctrlquadr.cpp \ - display/sp-ctrlquadr.h - -# ###################### -# ### CxxTest stuff #### -# ###################### -CXXTEST_TESTSUITES += \ - $(srcdir)/display/curve-test.h -- cgit v1.2.3 From 7f779f28e67eac1653e0f7751bb3f224b67894c7 Mon Sep 17 00:00:00 2001 From: Tavmjong Bah Date: Mon, 15 Aug 2016 22:55:21 +0200 Subject: Fix a bunch of errors as reported at http://www.viva64.com/en/b/0419/ (bzr r15059) --- src/display/drawing-text.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/display') diff --git a/src/display/drawing-text.cpp b/src/display/drawing-text.cpp index f0d83abfd..a0918e9f5 100644 --- a/src/display/drawing-text.cpp +++ b/src/display/drawing-text.cpp @@ -269,7 +269,7 @@ void DrawingText::decorateStyle(DrawingContext &dc, double vextent, double xphas int dashes[16]={ 8, 7, 6, 5, 4, 3, 2, 1, - -8, -7, -6, -5 + -8, -7, -6, -5, -4, -3, -2, -1 }; int dots[16]={ -- cgit v1.2.3 From 2f53e4dbb4620edcabaffc964c55cb71090912f8 Mon Sep 17 00:00:00 2001 From: Tavmjong Bah Date: Wed, 17 Aug 2016 09:39:43 +0200 Subject: Use M_PI, M_PI_2. We use these constants everywhere so if they are not defined we are already in trouble. No need to define them ourselves (except maybe in shared libraries). (bzr r15063) --- src/display/guideline.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/display') diff --git a/src/display/guideline.cpp b/src/display/guideline.cpp index 126fcf87c..f66b65e1a 100644 --- a/src/display/guideline.cpp +++ b/src/display/guideline.cpp @@ -48,7 +48,7 @@ static void sp_guideline_init(SPGuideLine *gl) gl->locked = false; gl->normal_to_line = Geom::Point(0,1); - gl->angle = 3.14159265358979323846/2; + gl->angle = M_PI_2; gl->point_on_line = Geom::Point(0,0); gl->sensitive = 0; -- cgit v1.2.3 From 1b8b972f1e0d6ee32c1f85514ec334c654d1e29c Mon Sep 17 00:00:00 2001 From: Jabier Arraiza Cenoz Date: Mon, 29 Aug 2016 22:39:07 +0200 Subject: Partial fix for bug 172063 while we find a better solution for XOR in helper lines (bzr r15090) --- src/display/canvas-bpath.cpp | 34 +++++++++++++++++++++++++--------- src/display/canvas-bpath.h | 6 +++--- src/display/sp-ctrlline.cpp | 2 +- 3 files changed, 29 insertions(+), 13 deletions(-) (limited to 'src/display') diff --git a/src/display/canvas-bpath.cpp b/src/display/canvas-bpath.cpp index 46b59d25a..fd10a96f5 100644 --- a/src/display/canvas-bpath.cpp +++ b/src/display/canvas-bpath.cpp @@ -53,6 +53,7 @@ sp_canvas_bpath_init (SPCanvasBPath * bpath) bpath->stroke_linejoin = SP_STROKE_LINEJOIN_MITER; bpath->stroke_linecap = SP_STROKE_LINECAP_BUTT; bpath->stroke_miterlimit = 11.0; + bpath->phantom_line = false; } static void sp_canvas_bpath_destroy(SPCanvasItem *object) @@ -71,7 +72,7 @@ static void sp_canvas_bpath_update(SPCanvasItem *item, Geom::Affine const &affin { SPCanvasBPath *cbp = SP_CANVAS_BPATH(item); - item->canvas->requestRedraw((int)item->x1, (int)item->y1, (int)item->x2, (int)item->y2); + item->canvas->requestRedraw((int)item->x1 - 1, (int)item->y1 - 1, (int)item->x2 + 1 , (int)item->y2 + 1); if (reinterpret_cast(sp_canvas_bpath_parent_class)->update) { reinterpret_cast(sp_canvas_bpath_parent_class)->update(item, affine, flags); @@ -86,10 +87,10 @@ static void sp_canvas_bpath_update(SPCanvasItem *item, Geom::Affine const &affin Geom::OptRect bbox = bounds_exact_transformed(cbp->curve->get_pathvector(), affine); if (bbox) { - item->x1 = (int)bbox->min()[Geom::X] - 1; - item->y1 = (int)bbox->min()[Geom::Y] - 1; - item->x2 = (int)bbox->max()[Geom::X] + 1; - item->y2 = (int)bbox->max()[Geom::Y] + 1; + item->x1 = (int)floor(bbox->min()[Geom::X]) - 1; + item->y1 = (int)floor(bbox->min()[Geom::Y]) - 1; + item->x2 = (int)ceil(bbox->max()[Geom::X]) + 1; + item->y2 = (int)ceil(bbox->max()[Geom::Y]) + 1; } else { item->x1 = 0; item->y1 = 0; @@ -131,7 +132,21 @@ sp_canvas_bpath_render (SPCanvasItem *item, SPCanvasBuf *buf) cairo_fill_preserve(buf->ct); } - if (dostroke) { + if (dostroke && cbp->phantom_line) { + ink_cairo_set_source_rgba32(buf->ct, 0xffffff7f); + cairo_set_line_width(buf->ct, 2); + if (cbp->dashes[0] != 0 && cbp->dashes[1] != 0) { + cairo_set_dash (buf->ct, cbp->dashes, 2, 0); + } + cairo_stroke(buf->ct); + cairo_set_tolerance(buf->ct, 0.5); + cairo_new_path(buf->ct); + feed_pathvector_to_cairo (buf->ct, cbp->curve->get_pathvector(), cbp->affine, area, + /* optimized_stroke = */ !dofill, 1); + ink_cairo_set_source_rgba32(buf->ct, cbp->stroke_rgba); + cairo_set_line_width(buf->ct, 1); + cairo_stroke(buf->ct); + } else if (dostroke) { ink_cairo_set_source_rgba32(buf->ct, cbp->stroke_rgba); cairo_set_line_width(buf->ct, 1); if (cbp->dashes[0] != 0 && cbp->dashes[1] != 0) { @@ -167,24 +182,25 @@ sp_canvas_bpath_point (SPCanvasItem *item, Geom::Point p, SPCanvasItem **actual_ } SPCanvasItem * -sp_canvas_bpath_new (SPCanvasGroup *parent, SPCurve *curve) +sp_canvas_bpath_new (SPCanvasGroup *parent, SPCurve *curve, bool phantom_line) { g_return_val_if_fail (parent != NULL, NULL); g_return_val_if_fail (SP_IS_CANVAS_GROUP (parent), NULL); SPCanvasItem *item = sp_canvas_item_new (parent, SP_TYPE_CANVAS_BPATH, NULL); - sp_canvas_bpath_set_bpath (SP_CANVAS_BPATH (item), curve); + sp_canvas_bpath_set_bpath (SP_CANVAS_BPATH (item), curve, phantom_line); return item; } void -sp_canvas_bpath_set_bpath (SPCanvasBPath *cbp, SPCurve *curve) +sp_canvas_bpath_set_bpath (SPCanvasBPath *cbp, SPCurve *curve, bool phantom_line) { g_return_if_fail (cbp != NULL); g_return_if_fail (SP_IS_CANVAS_BPATH (cbp)); + cbp->phantom_line = phantom_line; if (cbp->curve) { cbp->curve = cbp->curve->unref(); } diff --git a/src/display/canvas-bpath.h b/src/display/canvas-bpath.h index 72eca6eeb..686eb7c5a 100644 --- a/src/display/canvas-bpath.h +++ b/src/display/canvas-bpath.h @@ -80,7 +80,7 @@ struct SPCanvasBPath { SPStrokeJoinType stroke_linejoin; SPStrokeCapType stroke_linecap; gdouble stroke_miterlimit; - + bool phantom_line; /* State */ Shape *fill_shp; Shape *stroke_shp; @@ -92,9 +92,9 @@ struct SPCanvasBPathClass { GType sp_canvas_bpath_get_type (void); -SPCanvasItem *sp_canvas_bpath_new (SPCanvasGroup *parent, SPCurve *curve); +SPCanvasItem *sp_canvas_bpath_new (SPCanvasGroup *parent, SPCurve *curve, bool phantom_line = false); -void sp_canvas_bpath_set_bpath (SPCanvasBPath *cbp, SPCurve *curve); +void sp_canvas_bpath_set_bpath (SPCanvasBPath *cbp, SPCurve *curve, bool phantom_line = false); void sp_canvas_bpath_set_fill (SPCanvasBPath *cbp, guint32 rgba, SPWindRule rule); void sp_canvas_bpath_set_stroke (SPCanvasBPath *cbp, guint32 rgba, gdouble width, SPStrokeJoinType join, SPStrokeCapType cap, double dash=0, double gap=0); diff --git a/src/display/sp-ctrlline.cpp b/src/display/sp-ctrlline.cpp index 1bde540c0..6c5674935 100644 --- a/src/display/sp-ctrlline.cpp +++ b/src/display/sp-ctrlline.cpp @@ -84,7 +84,7 @@ void sp_ctrlline_render(SPCanvasItem *item, SPCanvasBuf *buf) Geom::Point s = cl->s * cl->affine; Geom::Point e = cl->e * cl->affine; - ink_cairo_set_source_rgba32(buf->ct, 0xffffffbf); + ink_cairo_set_source_rgba32(buf->ct, 0xffffff7f); cairo_set_line_width(buf->ct, 2); cairo_new_path(buf->ct); -- cgit v1.2.3 From b0285abe2d1329a012c116f359551a40112708df Mon Sep 17 00:00:00 2001 From: Jabier Arraiza Cenoz Date: Mon, 29 Aug 2016 22:52:05 +0200 Subject: Decrease contrast of phantom bpath (bzr r15091) --- src/display/canvas-bpath.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/display') diff --git a/src/display/canvas-bpath.cpp b/src/display/canvas-bpath.cpp index fd10a96f5..fc6b79b43 100644 --- a/src/display/canvas-bpath.cpp +++ b/src/display/canvas-bpath.cpp @@ -133,7 +133,7 @@ sp_canvas_bpath_render (SPCanvasItem *item, SPCanvasBuf *buf) } if (dostroke && cbp->phantom_line) { - ink_cairo_set_source_rgba32(buf->ct, 0xffffff7f); + ink_cairo_set_source_rgba32(buf->ct, 0xffffff4d); cairo_set_line_width(buf->ct, 2); if (cbp->dashes[0] != 0 && cbp->dashes[1] != 0) { cairo_set_dash (buf->ct, cbp->dashes, 2, 0); -- cgit v1.2.3 From 4a6c4b8cbe4a68d172c0eeb333c23bcf19b2f3ff Mon Sep 17 00:00:00 2001 From: ohtsuka-yoshio Date: Wed, 14 Sep 2016 17:39:02 +0200 Subject: [Bug #459914] Non-ascii (ja) charactors aren't displayed properly in Handle to grid intersection. Fixed bugs: - https://launchpad.net/bugs/459914 (bzr r15116) --- src/display/canvas-text.cpp | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src/display') diff --git a/src/display/canvas-text.cpp b/src/display/canvas-text.cpp index 7c019caf5..efef018e6 100644 --- a/src/display/canvas-text.cpp +++ b/src/display/canvas-text.cpp @@ -84,6 +84,7 @@ sp_canvastext_render (SPCanvasItem *item, SPCanvasBuf *buf) if (!buf->ct) return; + cairo_select_font_face(buf->ct, "sans-serif", CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_NORMAL); cairo_set_font_size(buf->ct, cl->fontsize); if (cl->background){ @@ -138,6 +139,7 @@ sp_canvastext_update (SPCanvasItem *item, Geom::Affine const &affine, unsigned i cairo_surface_t *tmp_surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, 1, 1); cairo_t* tmp_buf = cairo_create(tmp_surface); + cairo_select_font_face(tmp_buf, "sans-serif", CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_NORMAL); cairo_set_font_size(tmp_buf, cl->fontsize); cairo_text_extents_t extents; cairo_text_extents(tmp_buf, cl->text, &extents); -- cgit v1.2.3 From ee2e7c9c9907008de656773b98e1239a7f1af2a9 Mon Sep 17 00:00:00 2001 From: Marc Jeanmougin Date: Sun, 25 Sep 2016 23:59:45 +0200 Subject: Exposes to the user additional PNG settings: Interlacing, grayscale, bit depth, alpha, compression level, PNG pHYs dpi. Fixed bugs: - https://launchpad.net/bugs/170650 (bzr r15131) --- src/display/cairo-utils.cpp | 86 +++++++++++++++++++++++++++++++++++++++++++++ src/display/cairo-utils.h | 2 ++ 2 files changed, 88 insertions(+) (limited to 'src/display') diff --git a/src/display/cairo-utils.cpp b/src/display/cairo-utils.cpp index 24a75de4c..a7625f4a1 100644 --- a/src/display/cairo-utils.cpp +++ b/src/display/cairo-utils.cpp @@ -13,6 +13,7 @@ #endif #include "display/cairo-utils.h" +#include #include #include @@ -1321,6 +1322,91 @@ guint32 argb32_from_rgba(guint32 in) return px; } + +/** + * Converts a pixbuf to a PNG data structure. + * For 8-but RGBA png, this is like copying. + * + */ +const guchar* pixbuf_to_png(guchar const**rows, guchar* px, int num_rows, int num_cols, int stride, int color_type, int bit_depth) +{ + int n_fields = 1 + (color_type&2) + (color_type&4)/4; + const guchar* new_data = (const guchar*)malloc((n_fields * bit_depth * num_rows * num_cols)/8 + 64); + char* ptr = (char*) new_data; + int pad=0; //used when we write image data smaller than one byte (for instance in black and white images where 1px = 1bit) + for(int row = 0; row < num_rows; ++row){ + rows[row] = (const guchar*)ptr; + for(int col = 0; col < num_cols; ++col){ + guint32 *pixel = reinterpret_cast(px + row*stride)+col; +#if G_BYTE_ORDER == G_LITTLE_ENDIAN + //this part should probably be rewritten as (a tested, working) big endian, using htons() and ntohs() + guint64 a = (*pixel & 0xff000000) >> 24; + guint64 b = (*pixel & 0x00ff0000) >> 16; + guint64 g = (*pixel & 0x0000ff00) >> 8; + guint64 r = (*pixel & 0x000000ff); + + //one of possible rgb to greyscale formulas. This one is called "luminance, "luminosity" or "luma" + guint16 gray = (guint16)((guint32)((0.2126*(r<<24) + 0.7152*(g<<24) + 0.0722*(b<<24)))>>16); + + if (!pad) *((guint64*)ptr)=0; + if (color_type & 2) { //RGB + // for 8bit->16bit transition, I take the FF -> FFFF convention (multiplication by 0x101). + // If you prefer FF -> FF00 (multiplication by 0x100), remove the <<8, <<24, <<40 and <<56 + if (color_type & 4) { //RGBA + if (bit_depth==8) + *((guint32*)ptr) = *pixel; + else + *((guint64*)ptr) = (guint64)((a<<56)+(a<<48)+(b<<40)+(b<<32)+(g<<24)+(g<<16)+(r<<8)+(r)); + } + else{ //no alpha + if(bit_depth==8) + *((guint32*)ptr) = ((*pixel)<<8)>>8; + else + *((guint64*)ptr) = (guint64)((b<<40)+(b<<32)+(g<<24)+(g<<16)+(r<<8)+r); + } + } else { //Grayscale + if(bit_depth==16) + *(guint16*)ptr= ((gray & 0xff00)>>8) + ((gray &0x00ff)<<8); + else *((guint16*)ptr) += guint16(((gray >> (16-bit_depth))< #include <2geom/affine.h> -#include "display/cairo-utils.h" #include "display/sp-canvas.h" #include "display/sp-canvas-group.h" +#include "display/rendermode.h" +#include "display/cairo-utils.h" +#include "display/cairo-templates.h" +#include "display/drawing-context.h" +#include "display/drawing-item.h" +#include "display/nr-filter-colormatrix.h" +#include "display/canvas-arena.h" #include "preferences.h" #include "inkscape.h" #include "sodipodi-ctrlrect.h" #include "cms-system.h" -#include "display/rendermode.h" -#include "display/cairo-utils.h" #include "debug/gdk-event-latency-tracker.h" #include "desktop.h" #include "color.h" @@ -1945,6 +1949,165 @@ void SPCanvas::scrollTo(double cx, double cy, unsigned int clear, bool is_scroll } addIdle(); } +gdouble grayscale_value_matrix[20] = { + 0.21, 0.72, 0.072, 0, 0, + 0.21, 0.72, 0.072, 0, 0, + 0.21, 0.72, 0.072, 0, 0, + 0 , 0 , 0 , 1, 0 + }; +cairo_surface_t *surface_rotated; +cairo_surface_t *surface_origin; +cairo_surface_t *surface_measure; +double start_angle = 0; +bool started = false; +void SPCanvas::startRotateTo(double angle) +{ + if (!_backing_store || started) { + return; + } + start_angle = angle; + started = true; + GtkAllocation allocation; + gtk_widget_get_allocation(&_widget, &allocation); + int half_w = allocation.width/2; + int half_h = allocation.height/2; + int half_min = std::min(half_w,half_h); + cairo_surface_t *new_backing_store = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, allocation.width, allocation.height); + cairo_t *cr = cairo_create(new_backing_store); + cairo_arc(cr, half_w, half_h, half_min-15, 0, 2*M_PI); + cairo_fill(cr); + cairo_set_operator(cr, CAIRO_OPERATOR_IN); + cairo_set_source_surface(cr, _backing_store, 0, 0); + cairo_paint(cr); + cairo_set_operator(cr, CAIRO_OPERATOR_OVER); + cairo_arc(cr, half_w, half_h, half_min-16, 0, 2*M_PI); + cairo_set_source_rgba (cr, 1, 1, 1, 0.5); + cairo_stroke(cr); + cairo_destroy(cr); + surface_rotated = new_backing_store; + + cairo_surface_t *new_backing_store_measure = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, allocation.width, allocation.height); + cr = cairo_create(new_backing_store_measure); + cairo_arc(cr, half_w, half_h, half_min-15, 0, 2*M_PI); + cairo_set_source_rgba (cr, 1, 1, 1, 0.2); + cairo_fill(cr); + cairo_translate(cr, half_w, half_h); + for (gint x = 0; x < 360 ; x++){ + gint ang = 360 - x ;//+ 90; + if (ang > 180) { + ang -= 360; + } + double rot = (-180.0 + x - start_angle)*(M_PI/180.); + double dist = half_min-9; + gint inverse = 1; + if((x- start_angle) < 91 || (x- start_angle) > 270) { + inverse = -1; + } + if(x%10 == 0) { + cairo_rotate(cr, -rot); + cairo_select_font_face(cr, "sans-serif", CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_NORMAL); + cairo_set_font_size(cr, 10.0); + cairo_text_extents_t extents; + std::string s = std::to_string(ang) + "º"; + cairo_text_extents(cr, s.c_str(), &extents); + //std::cout << extents.width/2 << "extents.x_bearing\n"; + cairo_translate(cr, (extents.width/2) * inverse * -1, (dist + ((extents.height/2)* inverse))); + if((x- start_angle) < 91 || (x- start_angle) > 270) { + cairo_rotate(cr, 180*(M_PI/180.0)); + } + cairo_text_path(cr, s.c_str()); + if((x- start_angle) < 91 || (x- start_angle) > 270) { + cairo_rotate(cr, -180*(M_PI/180.0)); + } + cairo_translate(cr, (extents.width/2) * inverse , (dist + ((extents.height/2)* inverse)) * -1); + cairo_set_source_rgba (cr, 1, 1, 1, 1); + cairo_fill(cr); + cairo_rotate(cr, rot); + } + cairo_rotate(cr, x*(M_PI/180.)); + if(x%5 == 0) { + cairo_move_to(cr, 0, half_min-30); + cairo_line_to(cr, 0, half_min-17); + } else { + cairo_move_to(cr, 0, half_min-20); + cairo_line_to(cr, 0, half_min-15); + } + cairo_line_to(cr, 0, half_min-15); + cairo_set_source_rgba (cr, 0, 0, 0, 0.4); + cairo_set_line_width (cr,1); + cairo_stroke(cr); + cairo_rotate(cr, -x*(M_PI/180.)); + } + cairo_set_operator(cr, CAIRO_OPERATOR_CLEAR); + cairo_translate(cr, -half_w, -half_h); + cairo_arc(cr, half_w, half_h, half_min-30, 0, 2*M_PI); + cairo_set_source_rgba (cr, 1, 1, 1, 1); + cairo_fill(cr); + cairo_destroy(cr); + surface_measure = new_backing_store_measure; + + cairo_surface_t *new_backing_store_grey = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, allocation.width, allocation.height); + cr = cairo_create(new_backing_store_grey); + cairo_set_operator(cr, CAIRO_OPERATOR_OVER); + cairo_set_source_surface(cr, _backing_store, 0, 0); + cairo_paint(cr); + Inkscape::Filters::FilterColorMatrix::ColorMatrixMatrix _grayscale_colormatrix = std::vector (grayscale_value_matrix, grayscale_value_matrix + 20); + cairo_surface_t *out = ink_cairo_surface_create_identical(new_backing_store_grey); + ink_cairo_surface_filter(new_backing_store_grey, out, _grayscale_colormatrix); + cairo_set_source_surface(cr, out, 0, 0); + cairo_surface_destroy(out); + cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE); + cairo_paint(cr); + cairo_destroy(cr); + surface_origin = new_backing_store_grey; + +} + +void SPCanvas::endRotateTo() +{ + if (!_backing_store) { + return; + } + started = false; + surface_rotated = NULL; + surface_origin = NULL; + gtk_widget_queue_draw(GTK_WIDGET(this)); + dirtyAll(); + addIdle(); +} + +void SPCanvas::rotateTo(SPCanvasItem * item, double angle) +{ + if (!_backing_store) { + return; + } + GtkAllocation allocation; + gtk_widget_get_allocation(&_widget, &allocation); + cairo_surface_t *new_backing_store = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, allocation.width, allocation.height); + cairo_t *cr = cairo_create(new_backing_store); + cairo_set_source_surface(cr, surface_origin, 0, 0); + cairo_paint(cr); + cairo_set_source_rgba (cr, 0, 0, 0, 0.5); + cairo_paint(cr); + cairo_pattern_t *source_pattern; + cairo_matrix_t matrix; + source_pattern = cairo_pattern_create_for_surface (surface_rotated); + cairo_matrix_init_identity (&matrix); + cairo_matrix_translate (&matrix, allocation.width/2.0, allocation.height/2.0); + cairo_matrix_rotate (&matrix, Geom::rad_from_deg(angle - start_angle) * -1); + cairo_matrix_translate (&matrix, -allocation.width/2.0, -allocation.height/2.0); + cairo_pattern_set_matrix (source_pattern, &matrix); + cairo_set_source(cr, source_pattern); + cairo_paint(cr); + cairo_set_source_surface(cr, surface_measure, 0, 0); + cairo_paint(cr); + cairo_destroy(cr); + cairo_surface_destroy(_backing_store); + _backing_store = new_backing_store; + cairo_pattern_destroy (source_pattern); + gtk_widget_queue_draw(GTK_WIDGET(this)); + addIdle(); +} void SPCanvas::updateNow() { diff --git a/src/display/sp-canvas.h b/src/display/sp-canvas.h index 78d96d728..b78cdcdd5 100644 --- a/src/display/sp-canvas.h +++ b/src/display/sp-canvas.h @@ -72,7 +72,9 @@ GType sp_canvas_get_type() G_GNUC_CONST; struct SPCanvas { /// Scrolls canvas to specific position (cx and cy are measured in screen pixels). void scrollTo(double cx, double cy, unsigned int clear, bool is_scrolling = false); - + void startRotateTo(double angle); + void rotateTo(SPCanvasItem * item, double angle); + void endRotateTo(); /// Synchronously updates the canvas if necessary. void updateNow(); -- cgit v1.2.3 From 96bf3670efc23ecee2b9546b0b55993b1601c221 Mon Sep 17 00:00:00 2001 From: Tavmjong Bah Date: Wed, 19 Oct 2016 13:11:05 +0200 Subject: Implement 'vector-effect' value 'non-scaling-stroke'. No GUI yet. (bzr r15177) --- src/display/drawing-shape.cpp | 14 +++++++++++--- src/display/drawing-text.cpp | 13 ++++++++++--- 2 files changed, 21 insertions(+), 6 deletions(-) (limited to 'src/display') diff --git a/src/display/drawing-shape.cpp b/src/display/drawing-shape.cpp index 63efb3c0d..ba95a63ce 100644 --- a/src/display/drawing-shape.cpp +++ b/src/display/drawing-shape.cpp @@ -180,6 +180,10 @@ DrawingShape::_renderStroke(DrawingContext &dc) if( has_stroke ) { // TODO: remove segments outside of bbox when no dashes present dc.path(_curve->get_pathvector()); + if (_style && _style->vector_effect.computed == SP_VECTOR_EFFECT_NON_SCALING_STROKE) { + dc.restore(); + dc.save(); + } _nrstyle.applyStroke(dc); dc.strokePreserve(); dc.newPath(); // clear path @@ -213,7 +217,7 @@ DrawingShape::_renderItem(DrawingContext &dc, Geom::IntRect const &area, unsigne } { Inkscape::DrawingContext::Save save(dc); dc.setSource(rgba); - dc.setLineWidth(0.5); + dc.setLineWidth(5); dc.setTolerance(0.5); dc.stroke(); } @@ -230,6 +234,8 @@ DrawingShape::_renderItem(DrawingContext &dc, Geom::IntRect const &area, unsigne // we assume the context has no path Inkscape::DrawingContext::Save save(dc); dc.transform(_ctm); + dc.path(_curve->get_pathvector()); + // update fill and stroke paints. // this cannot be done during nr_arena_shape_update, because we need a Cairo context @@ -237,14 +243,16 @@ DrawingShape::_renderItem(DrawingContext &dc, Geom::IntRect const &area, unsigne bool has_fill = _nrstyle.prepareFill(dc, _item_bbox, _fill_pattern); bool has_stroke = _nrstyle.prepareStroke(dc, _item_bbox, _stroke_pattern); has_stroke &= (_nrstyle.stroke_width != 0); - if (has_fill || has_stroke) { // TODO: remove segments outside of bbox when no dashes present - dc.path(_curve->get_pathvector()); if (has_fill) { _nrstyle.applyFill(dc); dc.fillPreserve(); } + if (_style && _style->vector_effect.computed == SP_VECTOR_EFFECT_NON_SCALING_STROKE) { + dc.restore(); + dc.save(); + } if (has_stroke) { _nrstyle.applyStroke(dc); dc.strokePreserve(); diff --git a/src/display/drawing-text.cpp b/src/display/drawing-text.cpp index a0918e9f5..1280a2db9 100644 --- a/src/display/drawing-text.cpp +++ b/src/display/drawing-text.cpp @@ -592,17 +592,24 @@ unsigned DrawingText::_renderItem(DrawingContext &dc, Geom::IntRect const &/*are { Inkscape::DrawingContext::Save save(dc); dc.transform(_ctm); - if (has_fill && fill_first) { _nrstyle.applyFill(dc); dc.fillPreserve(); } - + } + { + Inkscape::DrawingContext::Save save(dc); + if (!_style || ! _style->vector_effect.computed == SP_VECTOR_EFFECT_NON_SCALING_STROKE) { + dc.transform(_ctm); + } if (has_stroke) { _nrstyle.applyStroke(dc); dc.strokePreserve(); } - + } + { + Inkscape::DrawingContext::Save save(dc); + dc.transform(_ctm); if (has_fill && !fill_first) { _nrstyle.applyFill(dc); dc.fillPreserve(); -- cgit v1.2.3 From ab9795b860412f259eecc095225893b9b130bc42 Mon Sep 17 00:00:00 2001 From: Jabier Arraiza Cenoz Date: Wed, 19 Oct 2016 22:02:50 +0200 Subject: Styling rotate (bzr r15142.1.17) --- src/display/sp-canvas.cpp | 53 +++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 49 insertions(+), 4 deletions(-) (limited to 'src/display') diff --git a/src/display/sp-canvas.cpp b/src/display/sp-canvas.cpp index 36d0b7e7c..ae20cd92d 100644 --- a/src/display/sp-canvas.cpp +++ b/src/display/sp-canvas.cpp @@ -1997,10 +1997,10 @@ void SPCanvas::startRotateTo(double angle) if (ang > 180) { ang -= 360; } - double rot = (-180.0 + x - start_angle)*(M_PI/180.); + double rot = (-180.0 + x)*(M_PI/180.); double dist = half_min-9; gint inverse = 1; - if((x- start_angle) < 91 || (x- start_angle) > 270) { + if((x) < 91 || (x) > 270) { inverse = -1; } if(x%10 == 0) { @@ -2012,11 +2012,11 @@ void SPCanvas::startRotateTo(double angle) cairo_text_extents(cr, s.c_str(), &extents); //std::cout << extents.width/2 << "extents.x_bearing\n"; cairo_translate(cr, (extents.width/2) * inverse * -1, (dist + ((extents.height/2)* inverse))); - if((x- start_angle) < 91 || (x- start_angle) > 270) { + if((x) < 91 || (x) > 270) { cairo_rotate(cr, 180*(M_PI/180.0)); } cairo_text_path(cr, s.c_str()); - if((x- start_angle) < 91 || (x- start_angle) > 270) { + if((x) < 91 || (x) > 270) { cairo_rotate(cr, -180*(M_PI/180.0)); } cairo_translate(cr, (extents.width/2) * inverse , (dist + ((extents.height/2)* inverse)) * -1); @@ -2043,6 +2043,21 @@ void SPCanvas::startRotateTo(double angle) cairo_arc(cr, half_w, half_h, half_min-30, 0, 2*M_PI); cairo_set_source_rgba (cr, 1, 1, 1, 1); cairo_fill(cr); + cairo_translate(cr, half_w, half_h); + cairo_set_operator(cr, CAIRO_OPERATOR_OVER); + cairo_rotate(cr, start_angle*(M_PI/180.)); + cairo_move_to(cr, 0, 0); + cairo_line_to(cr, 0, (half_min-17) * -1); + cairo_set_source_rgba (cr, 1, 1, 1, 0.25); + cairo_set_line_cap(cr, CAIRO_LINE_CAP_ROUND); + cairo_set_line_width (cr,5); + cairo_stroke(cr); + cairo_move_to(cr, 0, 0); + cairo_line_to(cr, 0, (half_min-17) * -1); + cairo_set_source_rgba (cr, 1, 0, 0, 0.9); + cairo_set_line_width (cr,1); + cairo_stroke(cr); + cairo_rotate(cr, -start_angle*(M_PI/180.)); cairo_destroy(cr); surface_measure = new_backing_store_measure; @@ -2083,6 +2098,9 @@ void SPCanvas::rotateTo(SPCanvasItem * item, double angle) } GtkAllocation allocation; gtk_widget_get_allocation(&_widget, &allocation); + int half_w = allocation.width/2; + int half_h = allocation.height/2; + int half_min = std::min(half_w,half_h); cairo_surface_t *new_backing_store = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, allocation.width, allocation.height); cairo_t *cr = cairo_create(new_backing_store); cairo_set_source_surface(cr, surface_origin, 0, 0); @@ -2101,6 +2119,33 @@ void SPCanvas::rotateTo(SPCanvasItem * item, double angle) cairo_paint(cr); cairo_set_source_surface(cr, surface_measure, 0, 0); cairo_paint(cr); + cairo_translate(cr, half_w, half_h); + cairo_rotate(cr, angle*(M_PI/180.)); + cairo_move_to(cr, 0, 0); + cairo_line_to(cr, 0, (half_min-17) * -1); + cairo_set_source_rgba (cr, 1, 1, 1, 0.25); + cairo_set_line_cap(cr, CAIRO_LINE_CAP_ROUND); + cairo_set_line_width (cr,5); + cairo_stroke(cr); + cairo_move_to(cr, 0, 0); + cairo_line_to(cr, 0, (half_min-17) * -1); + cairo_set_source_rgba (cr, 1, 1, 1, 0.9); + cairo_set_line_width (cr,1); + cairo_stroke(cr); + cairo_move_to(cr, 0, 0); + cairo_line_to(cr, 0, (half_min-17) * -1); + cairo_set_source_rgba (cr, 1, 0, 0, 0.9); + const double dashed[] = {6.0, 3.0}; + int len = sizeof(dashed) / sizeof(dashed[0]); + cairo_set_dash(cr, dashed, len, 1); + cairo_stroke(cr); + cairo_translate(cr, -half_w, -half_h); + cairo_set_source_rgba (cr, 1, 1, 1, 0.25); + cairo_arc(cr, half_w, half_h, 7, 0, 2*M_PI); + cairo_fill(cr); + cairo_set_source_rgba (cr, 1, 0, 0, 0.7); + cairo_arc(cr, half_w, half_h, 5, 0, 2*M_PI); + cairo_fill(cr); cairo_destroy(cr); cairo_surface_destroy(_backing_store); _backing_store = new_backing_store; -- cgit v1.2.3 From 50c101849a9f591972b5478a7a83407558e7bff7 Mon Sep 17 00:00:00 2001 From: Jabier Arraiza Cenoz Date: Sun, 23 Oct 2016 11:03:35 +0200 Subject: Add right click attempt (bzr r15142.1.20) --- src/display/sp-canvas.cpp | 68 +++++++++++++++++++++++++++++++++++++++++++---- src/display/sp-canvas.h | 2 +- 2 files changed, 64 insertions(+), 6 deletions(-) (limited to 'src/display') diff --git a/src/display/sp-canvas.cpp b/src/display/sp-canvas.cpp index ae20cd92d..745896dd7 100644 --- a/src/display/sp-canvas.cpp +++ b/src/display/sp-canvas.cpp @@ -43,6 +43,8 @@ #include "debug/gdk-event-latency-tracker.h" #include "desktop.h" #include "color.h" +#include +#include using Inkscape::Debug::GdkEventLatencyTracker; @@ -1992,6 +1994,8 @@ void SPCanvas::startRotateTo(double angle) cairo_set_source_rgba (cr, 1, 1, 1, 0.2); cairo_fill(cr); cairo_translate(cr, half_w, half_h); + cairo_select_font_face(cr, "sans-serif", CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_NORMAL); + cairo_set_font_size(cr, 10.0); for (gint x = 0; x < 360 ; x++){ gint ang = 360 - x ;//+ 90; if (ang > 180) { @@ -2005,8 +2009,6 @@ void SPCanvas::startRotateTo(double angle) } if(x%10 == 0) { cairo_rotate(cr, -rot); - cairo_select_font_face(cr, "sans-serif", CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_NORMAL); - cairo_set_font_size(cr, 10.0); cairo_text_extents_t extents; std::string s = std::to_string(ang) + "º"; cairo_text_extents(cr, s.c_str(), &extents); @@ -2075,7 +2077,9 @@ void SPCanvas::startRotateTo(double angle) cairo_paint(cr); cairo_destroy(cr); surface_origin = new_backing_store_grey; - + gtk_widget_queue_draw(GTK_WIDGET(this)); + dirtyAll(); + addIdle(); } void SPCanvas::endRotateTo() @@ -2091,9 +2095,9 @@ void SPCanvas::endRotateTo() addIdle(); } -void SPCanvas::rotateTo(SPCanvasItem * item, double angle) +void SPCanvas::rotateTo(SPCanvasItem * item, double angle, bool widget) { - if (!_backing_store) { + if (!_backing_store || !started) { return; } GtkAllocation allocation; @@ -2146,6 +2150,60 @@ void SPCanvas::rotateTo(SPCanvasItem * item, double angle) cairo_set_source_rgba (cr, 1, 0, 0, 0.7); cairo_arc(cr, half_w, half_h, 5, 0, 2*M_PI); cairo_fill(cr); + cairo_translate(cr, half_w, half_h); + cairo_rotate(cr, -angle*(M_PI/180.)); + if (!widget) { + cairo_select_font_face(cr, "sans-serif", CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_NORMAL); + cairo_set_font_size(cr, 15.0); + cairo_text_extents_t extents; + std::ostringstream s; + s << _("Original angle ") << std::fixed << std::setprecision(2) << start_angle << "º"; + cairo_text_extents(cr, s.str().c_str(), &extents); + cairo_translate(cr, half_w - extents.width -15 ,-half_h + 25); + cairo_set_source_rgba (cr, 1, 1, 1, 1); + cairo_text_path(cr, s.str().c_str()); + cairo_fill(cr); + cairo_translate(cr, (half_w - extents.width -15) *-1 ,(-half_h + 25) *-1); + s.str(""); + s << _("New angle ") << std::fixed << std::setprecision(2) << angle << "º"; + cairo_text_extents(cr, s.str().c_str(), &extents); + cairo_translate(cr, half_w - extents.width -15 ,-half_h + 45); + cairo_text_path(cr, s.str().c_str()); + cairo_fill(cr); + cairo_translate(cr, (half_w - extents.width -15) *-1 ,(-half_h + 45) *-1); + s.str(""); + s << _("Gap ") << std::fixed << std::setprecision(2) << std::abs(start_angle-angle) << "º"; + cairo_text_extents(cr, s.str().c_str(), &extents); + cairo_translate(cr, half_w - extents.width -15 ,-half_h + 65); + cairo_text_path(cr, s.str().c_str()); + cairo_fill(cr); + cairo_translate(cr, (half_w - extents.width -15) *-1 ,(-half_h + 65) *-1); + cairo_translate(cr, -half_w + 10 ,-half_h + 25); + s.str(""); + cairo_set_font_size(cr, 12.0); + s << _("Normal mode, 1º round step"); + cairo_text_path(cr, s.str().c_str()); + cairo_fill(cr); + cairo_translate(cr, (-half_w +10) * -1 ,(-half_h + 25) * -1); + cairo_translate(cr, -half_w + 10 ,-half_h + 40); + s.str(""); + s << _("+CTRL, Fractional degrees"); + cairo_text_path(cr, s.str().c_str()); + cairo_fill(cr); + cairo_translate(cr, (-half_w + 10) * -1 ,(-half_h + 40) * -1); + cairo_translate(cr, -half_w + 10 ,-half_h + 55); + s.str(""); + s << _("+SHIFT, 5º round step"); + cairo_text_path(cr, s.str().c_str()); + cairo_fill(cr); + cairo_translate(cr, (-half_w + 10) * -1 ,(-half_h + 55) * -1); + cairo_translate(cr, -half_w + 10 ,-half_h + 70); + s.str(""); + s << _("+ALT, Reset"); + cairo_text_path(cr, s.str().c_str()); + cairo_fill(cr); + //cairo_translate(cr, (-half_w + 10) * -1 ,(-half_h + 60) * -1); + } cairo_destroy(cr); cairo_surface_destroy(_backing_store); _backing_store = new_backing_store; diff --git a/src/display/sp-canvas.h b/src/display/sp-canvas.h index b78cdcdd5..5c4cd5047 100644 --- a/src/display/sp-canvas.h +++ b/src/display/sp-canvas.h @@ -73,7 +73,7 @@ struct SPCanvas { /// Scrolls canvas to specific position (cx and cy are measured in screen pixels). void scrollTo(double cx, double cy, unsigned int clear, bool is_scrolling = false); void startRotateTo(double angle); - void rotateTo(SPCanvasItem * item, double angle); + void rotateTo(SPCanvasItem * item, double angle, bool widget = false); void endRotateTo(); /// Synchronously updates the canvas if necessary. void updateNow(); -- cgit v1.2.3 From 74edf9fcbc3106cccddb2a293275748fefa08f0b Mon Sep 17 00:00:00 2001 From: Jabier Arraiza Cenoz Date: Sun, 23 Oct 2016 20:04:23 +0200 Subject: Add right click rotation panning (bzr r15142.1.22) --- src/display/sp-canvas.cpp | 19 +++++++++++-------- src/display/sp-canvas.h | 2 +- 2 files changed, 12 insertions(+), 9 deletions(-) (limited to 'src/display') diff --git a/src/display/sp-canvas.cpp b/src/display/sp-canvas.cpp index 2f6caadd3..115b8c613 100644 --- a/src/display/sp-canvas.cpp +++ b/src/display/sp-canvas.cpp @@ -2077,31 +2077,33 @@ void SPCanvas::startRotateTo(double angle) cairo_paint(cr); cairo_destroy(cr); surface_origin = new_backing_store_grey; - clearRotateTo(true); + gtk_widget_queue_draw(GTK_WIDGET(this)); + dirtyAll(); + addIdle(); } bool SPCanvas::endRotateTo() { - if (!started) { + if (!_backing_store || !started) { return false; } started = false; surface_rotated = NULL; surface_origin = NULL; - clearRotateTo(true); + gtk_widget_queue_draw(GTK_WIDGET(this)); + dirtyAll(); + addIdle(); return true; } -void SPCanvas::clearRotateTo(bool clear) +void SPCanvas::clearRotateTo() { if (!started) { return; } gtk_widget_queue_draw(GTK_WIDGET(this)); dirtyAll(); - if (clear) { - addIdle(); - } + addIdle(); } void SPCanvas::rotateTo(SPCanvasItem * item, double angle, bool widget) @@ -2217,7 +2219,8 @@ void SPCanvas::rotateTo(SPCanvasItem * item, double angle, bool widget) cairo_surface_destroy(_backing_store); _backing_store = new_backing_store; cairo_pattern_destroy (source_pattern); - clearRotateTo(false); + gtk_widget_queue_draw(GTK_WIDGET(this)); + addIdle(); } void SPCanvas::updateNow() diff --git a/src/display/sp-canvas.h b/src/display/sp-canvas.h index 122cc2d8c..628bc74ca 100644 --- a/src/display/sp-canvas.h +++ b/src/display/sp-canvas.h @@ -75,7 +75,7 @@ struct SPCanvas { void startRotateTo(double angle); void rotateTo(SPCanvasItem * item, double angle, bool widget = false); bool endRotateTo(); - void clearRotateTo(bool clear); + void clearRotateTo(); /// Synchronously updates the canvas if necessary. void updateNow(); -- cgit v1.2.3 From b65d3fdc9c15af81c5e433d8f1b714ef4ab61487 Mon Sep 17 00:00:00 2001 From: Jabier Arraiza Cenoz Date: Sun, 23 Oct 2016 21:18:11 +0200 Subject: Add right click rotation panning, some fixes (bzr r15142.1.23) --- src/display/sp-canvas.cpp | 113 ++++++++++++++++++++++++---------------------- src/display/sp-canvas.h | 2 +- 2 files changed, 61 insertions(+), 54 deletions(-) (limited to 'src/display') diff --git a/src/display/sp-canvas.cpp b/src/display/sp-canvas.cpp index 115b8c613..242a30248 100644 --- a/src/display/sp-canvas.cpp +++ b/src/display/sp-canvas.cpp @@ -2101,12 +2101,21 @@ void SPCanvas::clearRotateTo() if (!started) { return; } + GtkAllocation allocation; + gtk_widget_get_allocation(&_widget, &allocation); + cairo_surface_t *new_backing_store = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, allocation.width, allocation.height); + cairo_t *cr = cairo_create(new_backing_store); + cairo_set_source(cr, _background); + cairo_paint(cr); + cairo_destroy(cr); + cairo_surface_destroy(_backing_store); + _backing_store = new_backing_store; gtk_widget_queue_draw(GTK_WIDGET(this)); dirtyAll(); addIdle(); } -void SPCanvas::rotateTo(SPCanvasItem * item, double angle, bool widget) +void SPCanvas::rotateTo(SPCanvasItem * item, double angle) { if (!_backing_store || !started) { return; @@ -2163,58 +2172,56 @@ void SPCanvas::rotateTo(SPCanvasItem * item, double angle, bool widget) cairo_fill(cr); cairo_translate(cr, half_w, half_h); cairo_rotate(cr, -angle*(M_PI/180.)); - if (!widget) { - cairo_select_font_face(cr, "sans-serif", CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_NORMAL); - cairo_set_font_size(cr, 15.0); - cairo_text_extents_t extents; - std::ostringstream s; - s << _("Original angle ") << std::fixed << std::setprecision(2) << start_angle << "º"; - cairo_text_extents(cr, s.str().c_str(), &extents); - cairo_translate(cr, half_w - extents.width -15 ,-half_h + 25); - cairo_set_source_rgba (cr, 1, 1, 1, 1); - cairo_text_path(cr, s.str().c_str()); - cairo_fill(cr); - cairo_translate(cr, (half_w - extents.width -15) *-1 ,(-half_h + 25) *-1); - s.str(""); - s << _("New angle ") << std::fixed << std::setprecision(2) << angle << "º"; - cairo_text_extents(cr, s.str().c_str(), &extents); - cairo_translate(cr, half_w - extents.width -15 ,-half_h + 45); - cairo_text_path(cr, s.str().c_str()); - cairo_fill(cr); - cairo_translate(cr, (half_w - extents.width -15) *-1 ,(-half_h + 45) *-1); - s.str(""); - s << _("Gap ") << std::fixed << std::setprecision(2) << std::abs(start_angle-angle) << "º"; - cairo_text_extents(cr, s.str().c_str(), &extents); - cairo_translate(cr, half_w - extents.width -15 ,-half_h + 65); - cairo_text_path(cr, s.str().c_str()); - cairo_fill(cr); - cairo_translate(cr, (half_w - extents.width -15) *-1 ,(-half_h + 65) *-1); - cairo_translate(cr, -half_w + 10 ,-half_h + 25); - s.str(""); - cairo_set_font_size(cr, 12.0); - s << _("Normal mode, 1º round step"); - cairo_text_path(cr, s.str().c_str()); - cairo_fill(cr); - cairo_translate(cr, (-half_w +10) * -1 ,(-half_h + 25) * -1); - cairo_translate(cr, -half_w + 10 ,-half_h + 40); - s.str(""); - s << _("+CTRL, Fractional degrees"); - cairo_text_path(cr, s.str().c_str()); - cairo_fill(cr); - cairo_translate(cr, (-half_w + 10) * -1 ,(-half_h + 40) * -1); - cairo_translate(cr, -half_w + 10 ,-half_h + 55); - s.str(""); - s << _("+SHIFT, 5º round step"); - cairo_text_path(cr, s.str().c_str()); - cairo_fill(cr); - cairo_translate(cr, (-half_w + 10) * -1 ,(-half_h + 55) * -1); - cairo_translate(cr, -half_w + 10 ,-half_h + 70); - s.str(""); - s << _("+CTRL+SHIFT, Reset"); - cairo_text_path(cr, s.str().c_str()); - cairo_fill(cr); - //cairo_translate(cr, (-half_w + 10) * -1 ,(-half_h + 60) * -1); - } + cairo_select_font_face(cr, "sans-serif", CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_NORMAL); + cairo_set_font_size(cr, 15.0); + cairo_text_extents_t extents; + std::ostringstream s; + s << _("Original angle ") << std::fixed << std::setprecision(2) << start_angle << "º"; + cairo_text_extents(cr, s.str().c_str(), &extents); + cairo_translate(cr, half_w - extents.width -15 ,-half_h + 25); + cairo_set_source_rgba (cr, 1, 1, 1, 1); + cairo_text_path(cr, s.str().c_str()); + cairo_fill(cr); + cairo_translate(cr, (half_w - extents.width -15) *-1 ,(-half_h + 25) *-1); + s.str(""); + s << _("New angle ") << std::fixed << std::setprecision(2) << angle << "º"; + cairo_text_extents(cr, s.str().c_str(), &extents); + cairo_translate(cr, half_w - extents.width -15 ,-half_h + 45); + cairo_text_path(cr, s.str().c_str()); + cairo_fill(cr); + cairo_translate(cr, (half_w - extents.width -15) *-1 ,(-half_h + 45) *-1); + s.str(""); + s << _("Gap ") << std::fixed << std::setprecision(2) << std::abs(start_angle-angle) << "º"; + cairo_text_extents(cr, s.str().c_str(), &extents); + cairo_translate(cr, half_w - extents.width -15 ,-half_h + 65); + cairo_text_path(cr, s.str().c_str()); + cairo_fill(cr); + cairo_translate(cr, (half_w - extents.width -15) *-1 ,(-half_h + 65) *-1); + cairo_translate(cr, -half_w + 10 ,-half_h + 25); + s.str(""); + cairo_set_font_size(cr, 12.0); + s << _("Normal mode, 1º round step"); + cairo_text_path(cr, s.str().c_str()); + cairo_fill(cr); + cairo_translate(cr, (-half_w +10) * -1 ,(-half_h + 25) * -1); + cairo_translate(cr, -half_w + 10 ,-half_h + 40); + s.str(""); + s << _("+CTRL, Fractional degrees"); + cairo_text_path(cr, s.str().c_str()); + cairo_fill(cr); + cairo_translate(cr, (-half_w + 10) * -1 ,(-half_h + 40) * -1); + cairo_translate(cr, -half_w + 10 ,-half_h + 55); + s.str(""); + s << _("+SHIFT, 5º round step"); + cairo_text_path(cr, s.str().c_str()); + cairo_fill(cr); + cairo_translate(cr, (-half_w + 10) * -1 ,(-half_h + 55) * -1); + cairo_translate(cr, -half_w + 10 ,-half_h + 70); + s.str(""); + s << _("+CTRL+SHIFT, Reset"); + cairo_text_path(cr, s.str().c_str()); + cairo_fill(cr); + //cairo_translate(cr, (-half_w + 10) * -1 ,(-half_h + 60) * -1); cairo_destroy(cr); cairo_surface_destroy(_backing_store); _backing_store = new_backing_store; diff --git a/src/display/sp-canvas.h b/src/display/sp-canvas.h index 628bc74ca..53b852140 100644 --- a/src/display/sp-canvas.h +++ b/src/display/sp-canvas.h @@ -73,7 +73,7 @@ struct SPCanvas { /// Scrolls canvas to specific position (cx and cy are measured in screen pixels). void scrollTo(double cx, double cy, unsigned int clear, bool is_scrolling = false); void startRotateTo(double angle); - void rotateTo(SPCanvasItem * item, double angle, bool widget = false); + void rotateTo(SPCanvasItem * item, double angle); bool endRotateTo(); void clearRotateTo(); /// Synchronously updates the canvas if necessary. -- cgit v1.2.3 From 043578ee79ae7dccc1967a9e380d276c9f73ed46 Mon Sep 17 00:00:00 2001 From: Jabier Arraiza Cenoz Date: Tue, 25 Oct 2016 23:30:06 +0200 Subject: Some bug fixes and improvements (bzr r15142.1.25) --- src/display/sp-canvas.cpp | 12 ------------ 1 file changed, 12 deletions(-) (limited to 'src/display') diff --git a/src/display/sp-canvas.cpp b/src/display/sp-canvas.cpp index 242a30248..c4d454cb9 100644 --- a/src/display/sp-canvas.cpp +++ b/src/display/sp-canvas.cpp @@ -2077,9 +2077,6 @@ void SPCanvas::startRotateTo(double angle) cairo_paint(cr); cairo_destroy(cr); surface_origin = new_backing_store_grey; - gtk_widget_queue_draw(GTK_WIDGET(this)); - dirtyAll(); - addIdle(); } bool SPCanvas::endRotateTo() @@ -2101,15 +2098,6 @@ void SPCanvas::clearRotateTo() if (!started) { return; } - GtkAllocation allocation; - gtk_widget_get_allocation(&_widget, &allocation); - cairo_surface_t *new_backing_store = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, allocation.width, allocation.height); - cairo_t *cr = cairo_create(new_backing_store); - cairo_set_source(cr, _background); - cairo_paint(cr); - cairo_destroy(cr); - cairo_surface_destroy(_backing_store); - _backing_store = new_backing_store; gtk_widget_queue_draw(GTK_WIDGET(this)); dirtyAll(); addIdle(); -- cgit v1.2.3 From b539e66398261e60f2b9218ff72058e962fe832d Mon Sep 17 00:00:00 2001 From: Jabier Arraiza Cenoz Date: Wed, 26 Oct 2016 12:31:09 +0200 Subject: Add fadding from temporary rotate draw to real ones (bzr r15142.1.27) --- src/display/sp-canvas.cpp | 31 ++++++++++++++++++++----------- 1 file changed, 20 insertions(+), 11 deletions(-) (limited to 'src/display') diff --git a/src/display/sp-canvas.cpp b/src/display/sp-canvas.cpp index c4d454cb9..f168cffe6 100644 --- a/src/display/sp-canvas.cpp +++ b/src/display/sp-canvas.cpp @@ -1891,6 +1891,19 @@ SPCanvasGroup *SPCanvas::getRoot() return SP_CANVAS_GROUP(_root); } +gdouble grayscale_value_matrix[20] = { + 0.21, 0.72, 0.072, 0, 0, + 0.21, 0.72, 0.072, 0, 0, + 0.21, 0.72, 0.072, 0, 0, + 0 , 0 , 0 , 1, 0 + }; +cairo_surface_t *surface_rotated; +cairo_surface_t *surface_origin; +cairo_surface_t *surface_measure; +double start_angle = 0; +bool started = false; +bool rotated = false; + void SPCanvas::scrollTo(double cx, double cy, unsigned int clear, bool is_scrolling) { GtkAllocation allocation; @@ -1913,9 +1926,14 @@ void SPCanvas::scrollTo(double cx, double cy, unsigned int clear, bool is_scroll cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE); // Paint the background cairo_translate(cr, -ix, -iy); + if (rotated) { + cairo_translate(cr, dx, dy); + rotated = false; + } cairo_set_source(cr, _background); cairo_paint(cr); // Copy the old backing store contents + cairo_set_source_surface(cr, _backing_store, _x0, _y0); cairo_rectangle(cr, _x0, _y0, allocation.width, allocation.height); cairo_clip(cr); @@ -1951,17 +1969,7 @@ void SPCanvas::scrollTo(double cx, double cy, unsigned int clear, bool is_scroll } addIdle(); } -gdouble grayscale_value_matrix[20] = { - 0.21, 0.72, 0.072, 0, 0, - 0.21, 0.72, 0.072, 0, 0, - 0.21, 0.72, 0.072, 0, 0, - 0 , 0 , 0 , 1, 0 - }; -cairo_surface_t *surface_rotated; -cairo_surface_t *surface_origin; -cairo_surface_t *surface_measure; -double start_angle = 0; -bool started = false; + void SPCanvas::startRotateTo(double angle) { if (!_backing_store || started) { @@ -2090,6 +2098,7 @@ bool SPCanvas::endRotateTo() gtk_widget_queue_draw(GTK_WIDGET(this)); dirtyAll(); addIdle(); + rotated = true; return true; } -- cgit v1.2.3 From 126cabd5f87ca04262879584dd4ec1ac923edacd Mon Sep 17 00:00:00 2001 From: Jabier Arraiza Cenoz Date: Tue, 1 Nov 2016 18:01:07 +0100 Subject: Fix angle constrain, thanks to vlada, Mc and LiamW (bzr r15142.1.29) --- src/display/sp-canvas.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/display') diff --git a/src/display/sp-canvas.cpp b/src/display/sp-canvas.cpp index e84303816..427cec20a 100644 --- a/src/display/sp-canvas.cpp +++ b/src/display/sp-canvas.cpp @@ -2211,7 +2211,7 @@ void SPCanvas::rotateTo(double angle) cairo_translate(cr, -half_w + 10 ,-half_h + 55); s.str(""); Inkscape::Preferences *prefs = Inkscape::Preferences::get(); - s << _("+CTRL, ") << prefs->getInt("/options/rotationsnapsperpi/value", 15) << _("º round step"); + s << _("+CTRL, ") << 180.0/prefs->getInt("/options/rotationsnapsperpi/value", 12) << _("º round step"); cairo_text_path(cr, s.str().c_str()); cairo_fill(cr); cairo_translate(cr, (-half_w + 10) * -1 ,(-half_h + 55) * -1); -- cgit v1.2.3 From f3a1e56cfdaa68c8de656cfb351c1ca6f29d7387 Mon Sep 17 00:00:00 2001 From: Marc Jeanmougin Date: Thu, 3 Nov 2016 02:55:39 +0100 Subject: Revert two changes from r15177 Fixed bugs: - https://launchpad.net/bugs/1636475 - https://launchpad.net/bugs/1637885 (bzr r15204) --- src/display/drawing-shape.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/display') diff --git a/src/display/drawing-shape.cpp b/src/display/drawing-shape.cpp index ba95a63ce..d7329e670 100644 --- a/src/display/drawing-shape.cpp +++ b/src/display/drawing-shape.cpp @@ -217,7 +217,7 @@ DrawingShape::_renderItem(DrawingContext &dc, Geom::IntRect const &area, unsigne } { Inkscape::DrawingContext::Save save(dc); dc.setSource(rgba); - dc.setLineWidth(5); + dc.setLineWidth(0.5); dc.setTolerance(0.5); dc.stroke(); } @@ -234,7 +234,6 @@ DrawingShape::_renderItem(DrawingContext &dc, Geom::IntRect const &area, unsigne // we assume the context has no path Inkscape::DrawingContext::Save save(dc); dc.transform(_ctm); - dc.path(_curve->get_pathvector()); // update fill and stroke paints. @@ -244,6 +243,7 @@ DrawingShape::_renderItem(DrawingContext &dc, Geom::IntRect const &area, unsigne bool has_stroke = _nrstyle.prepareStroke(dc, _item_bbox, _stroke_pattern); has_stroke &= (_nrstyle.stroke_width != 0); if (has_fill || has_stroke) { + dc.path(_curve->get_pathvector()); // TODO: remove segments outside of bbox when no dashes present if (has_fill) { _nrstyle.applyFill(dc); -- cgit v1.2.3 From 05d344828f919fad7846d2d76534eb02b554dc00 Mon Sep 17 00:00:00 2001 From: Jabier Arraiza Cenoz Date: Sat, 5 Nov 2016 03:32:30 +0100 Subject: Fix bug:1639083 crach closing segment with shortcut LPE Fixed bugs: - https://launchpad.net/bugs/1639083 (bzr r15210) --- src/display/curve.cpp | 12 ++++++++++++ src/display/curve.h | 1 + 2 files changed, 13 insertions(+) (limited to 'src/display') diff --git a/src/display/curve.cpp b/src/display/curve.cpp index b6c387034..1998e9bec 100644 --- a/src/display/curve.cpp +++ b/src/display/curve.cpp @@ -301,6 +301,18 @@ SPCurve::is_empty() const return _pathv.empty(); } +/** + * True if paths are in curve. If it only contains a path with only a moveto, the path is considered as unset FALSE + */ +bool +SPCurve::is_unset() const +{ + if (get_segment_count()) { + return false; + } + return true; +} + /** * True iff all subpaths are closed. * Returns false if the curve is empty. diff --git a/src/display/curve.h b/src/display/curve.h index 42b899210..72e6df95c 100644 --- a/src/display/curve.h +++ b/src/display/curve.h @@ -43,6 +43,7 @@ public: size_t nodes_in_path() const; bool is_empty() const; + bool is_unset() const; bool is_closed() const; Geom::Curve const * last_segment() const; Geom::Path const * last_path() const; -- cgit v1.2.3 From c4922f5c1b54802623bc43f04191495e2338fc24 Mon Sep 17 00:00:00 2001 From: Tavmjong Bah Date: Wed, 23 Nov 2016 10:23:22 +0100 Subject: Select mesh nodes by clicking on control lines. (bzr r15267) --- src/display/sp-ctrlcurve.cpp | 2 ++ src/display/sp-ctrlcurve.h | 3 +++ src/display/sp-ctrlline.cpp | 1 + src/display/sp-ctrlline.h | 2 ++ 4 files changed, 8 insertions(+) (limited to 'src/display') diff --git a/src/display/sp-ctrlcurve.cpp b/src/display/sp-ctrlcurve.cpp index 2e0e8105b..79ef20d6c 100644 --- a/src/display/sp-ctrlcurve.cpp +++ b/src/display/sp-ctrlcurve.cpp @@ -47,6 +47,8 @@ sp_ctrlcurve_init(SPCtrlCurve *ctrlcurve) // Points are initialized to 0,0 ctrlcurve->rgba = 0x0000ff7f; ctrlcurve->item=NULL; + ctrlcurve->corner0 = -1; + ctrlcurve->corner1 = -1; } namespace { diff --git a/src/display/sp-ctrlcurve.h b/src/display/sp-ctrlcurve.h index 847944f38..56b3089d9 100644 --- a/src/display/sp-ctrlcurve.h +++ b/src/display/sp-ctrlcurve.h @@ -31,6 +31,9 @@ struct SPCtrlCurve : public SPCtrlLine { Geom::Point const &q2, Geom::Point const &q3); Geom::Point p0, p1, p2, p3; + + int corner0; // Used to store index of corner for finding dragger. + int corner1; }; GType sp_ctrlcurve_get_type(); diff --git a/src/display/sp-ctrlline.cpp b/src/display/sp-ctrlline.cpp index 6c5674935..c4ced2a33 100644 --- a/src/display/sp-ctrlline.cpp +++ b/src/display/sp-ctrlline.cpp @@ -52,6 +52,7 @@ static void sp_ctrlline_init(SPCtrlLine *ctrlline) ctrlline->rgba = 0x0000ff7f; ctrlline->s[Geom::X] = ctrlline->s[Geom::Y] = ctrlline->e[Geom::X] = ctrlline->e[Geom::Y] = 0.0; ctrlline->item=NULL; + ctrlline->is_fill = true; } namespace { diff --git a/src/display/sp-ctrlline.h b/src/display/sp-ctrlline.h index b2e222437..bac0cfa54 100644 --- a/src/display/sp-ctrlline.h +++ b/src/display/sp-ctrlline.h @@ -33,6 +33,8 @@ struct SPCtrlLine : public SPCanvasItem { SPItem *item; // the item to which this line belongs in some sense; may be NULL for some users + bool is_fill; // fill or stroke... used with meshes. + guint32 rgba; Geom::Point s; Geom::Point e; -- cgit v1.2.3 From 07212a0ac053f34a7a695a82690196b5f38d80ab Mon Sep 17 00:00:00 2001 From: Tavmjong Bah Date: Fri, 25 Nov 2016 14:17:44 +0100 Subject: Provide a way to update a legacy document to account for the 90 to 96 dpi change. This method relies on setting the 'viewBox'. (bzr r15273) --- src/display/canvas-grid.cpp | 34 +++++++++++++++++++++++++++++++++- src/display/canvas-grid.h | 10 +++++++++- 2 files changed, 42 insertions(+), 2 deletions(-) (limited to 'src/display') diff --git a/src/display/canvas-grid.cpp b/src/display/canvas-grid.cpp index fa45fe02c..81d194b35 100644 --- a/src/display/canvas-grid.cpp +++ b/src/display/canvas-grid.cpp @@ -139,7 +139,7 @@ grid_canvasitem_update (SPCanvasItem *item, Geom::Affine const &affine, unsigned }; CanvasGrid::CanvasGrid(SPNamedView * nv, Inkscape::XML::Node * in_repr, SPDocument *in_doc, GridType type) - : visible(true), gridtype(type) + : visible(true), gridtype(type), legacy(false), pixel(false) { repr = in_repr; doc = in_doc; @@ -528,6 +528,10 @@ CanvasXYGrid::readRepr() if( q.unit->type == UNIT_TYPE_LINEAR ) { // Legacy grid not in 'user units' origin[Geom::X] = q.value("px"); + legacy = true; + if (q.unit->abbr == "px" ) { + pixel = true; + } } else { // Grid in 'user units' origin[Geom::X] = q.quantity * scale_x; @@ -541,6 +545,10 @@ CanvasXYGrid::readRepr() if( q.unit->type == UNIT_TYPE_LINEAR ) { // Legacy grid not in 'user units' origin[Geom::Y] = q.value("px"); + legacy = true; + if (q.unit->abbr == "px" ) { + pixel = true; + } } else { // Grid in 'user units' origin[Geom::Y] = q.quantity * scale_y; @@ -559,6 +567,10 @@ CanvasXYGrid::readRepr() if( q.unit->type == UNIT_TYPE_LINEAR ) { // Legacy grid not in 'user units' spacing[Geom::X] = q.value("px"); + legacy = true; + if (q.unit->abbr == "px" ) { + pixel = true; + } } else { // Grid in 'user units' spacing[Geom::X] = q.quantity * scale_x; @@ -578,6 +590,10 @@ CanvasXYGrid::readRepr() if( q.unit->type == UNIT_TYPE_LINEAR ) { // Legacy grid not in 'user units' spacing[Geom::Y] = q.value("px"); + legacy = true; + if (q.unit->abbr == "px" ) { + pixel = true; + } } else { // Grid in 'user units' spacing[Geom::Y] = q.quantity * scale_y; @@ -798,7 +814,23 @@ CanvasXYGrid::updateWidgets() */ } +// For correcting old SVG Inkscape files +void +CanvasXYGrid::Scale (Geom::Scale const &scale ) { + origin *= scale; + spacing *= scale; + // Write out in 'user-units' + Inkscape::SVGOStringStream os_x, os_y, ss_x, ss_y; + os_x << origin[Geom::X]; + os_y << origin[Geom::Y]; + ss_x << spacing[Geom::X]; + ss_y << spacing[Geom::Y]; + repr->setAttribute("originx", os_x.str().c_str()); + repr->setAttribute("originy", os_y.str().c_str()); + repr->setAttribute("spacingx", ss_x.str().c_str()); + repr->setAttribute("spacingy", ss_y.str().c_str()); +} void CanvasXYGrid::Update (Geom::Affine const &affine, unsigned int /*flags*/) diff --git a/src/display/canvas-grid.h b/src/display/canvas-grid.h index 557bd6dab..bf520467a 100644 --- a/src/display/canvas-grid.h +++ b/src/display/canvas-grid.h @@ -101,6 +101,9 @@ public: static void on_repr_attr_changed (Inkscape::XML::Node * repr, const gchar *key, const gchar *oldval, const gchar *newval, bool is_interactive, void * data); + bool isLegacy() const { return legacy; } + bool isPixel() const { return pixel; } + bool isVisible() const { return (isEnabled() &&visible); }; bool isEnabled() const; @@ -118,7 +121,11 @@ protected: GridType gridtype; -private: + // For dealing with old Inkscape SVG files (pre 0.92) + bool legacy; + bool pixel; + + private: CanvasGrid(const CanvasGrid&); CanvasGrid& operator=(const CanvasGrid&); }; @@ -129,6 +136,7 @@ public: CanvasXYGrid(SPNamedView * nv, Inkscape::XML::Node * in_repr, SPDocument * in_doc); virtual ~CanvasXYGrid(); + virtual void Scale (Geom::Scale const &scale); virtual void Update (Geom::Affine const &affine, unsigned int flags); virtual void Render (SPCanvasBuf *buf); -- cgit v1.2.3 From 7b685637d0701a15424815b0a4202b43e28be0ab Mon Sep 17 00:00:00 2001 From: Eduard Braun Date: Sun, 27 Nov 2016 14:29:07 +0100 Subject: Remove unneeded "#include " in "cairo-utils.cpp" Fixed bugs: - https://launchpad.net/bugs/1645062 (bzr r15280) --- src/display/cairo-utils.cpp | 1 - 1 file changed, 1 deletion(-) (limited to 'src/display') diff --git a/src/display/cairo-utils.cpp b/src/display/cairo-utils.cpp index a7625f4a1..01b0d807c 100644 --- a/src/display/cairo-utils.cpp +++ b/src/display/cairo-utils.cpp @@ -13,7 +13,6 @@ #endif #include "display/cairo-utils.h" -#include #include #include -- cgit v1.2.3 From 30f2c8a062594750f351f823aa78916f8e61bfe7 Mon Sep 17 00:00:00 2001 From: Jabier Arraiza Cenoz Date: Sat, 3 Dec 2016 17:11:45 +0100 Subject: Add triangle knot. (bzr r15293) --- src/display/sodipodi-ctrl.cpp | 74 +++++++++++++++++++++++++++++++++++++++++-- src/display/sodipodi-ctrl.h | 2 ++ 2 files changed, 73 insertions(+), 3 deletions(-) (limited to 'src/display') diff --git a/src/display/sodipodi-ctrl.cpp b/src/display/sodipodi-ctrl.cpp index 327fbce1f..27b6988c5 100644 --- a/src/display/sodipodi-ctrl.cpp +++ b/src/display/sodipodi-ctrl.cpp @@ -18,6 +18,7 @@ enum { ARG_MODE, ARG_ANCHOR, ARG_SIZE, + ARG_ANGLE, ARG_FILLED, ARG_FILL_COLOR, ARG_STROKED, @@ -53,7 +54,7 @@ sp_ctrl_class_init (SPCtrlClass *klass) g_object_class_install_property (g_object_class, ARG_SIZE, g_param_spec_double ("size", "size", "Size", 0.0, G_MAXDOUBLE, 8.0, (GParamFlags) G_PARAM_READWRITE)); g_object_class_install_property (g_object_class, - ARG_PIXBUF, g_param_spec_pointer ("pixbuf", "pixbuf", "Pixbuf", (GParamFlags) G_PARAM_READWRITE)); + ARG_ANGLE, g_param_spec_double ("angle", "angle", "Angle", -G_MAXDOUBLE, G_MAXDOUBLE, 0.0, (GParamFlags) G_PARAM_READWRITE)); g_object_class_install_property (g_object_class, ARG_FILLED, g_param_spec_boolean ("filled", "filled", "Filled", TRUE, (GParamFlags) G_PARAM_READWRITE)); g_object_class_install_property (g_object_class, @@ -62,6 +63,8 @@ sp_ctrl_class_init (SPCtrlClass *klass) ARG_STROKED, g_param_spec_boolean ("stroked", "stroked", "Stroked", FALSE, (GParamFlags) G_PARAM_READWRITE)); g_object_class_install_property (g_object_class, ARG_STROKE_COLOR, g_param_spec_int ("stroke_color", "stroke_color", "Stroke Color", G_MININT, G_MAXINT, 0x000000ff, (GParamFlags) G_PARAM_READWRITE)); + g_object_class_install_property (g_object_class, + ARG_PIXBUF, g_param_spec_pointer ("pixbuf", "pixbuf", "Pixbuf", (GParamFlags) G_PARAM_READWRITE)); item_class->destroy = sp_ctrl_destroy; item_class->update = sp_ctrl_update; @@ -95,6 +98,9 @@ sp_ctrl_set_property(GObject *object, guint prop_id, const GValue *value, GParam ctrl->height = ctrl->width; ctrl->defined = (ctrl->width > 0); break; + case ARG_ANGLE: + ctrl->angle = (double)g_value_get_double(value); + break; case ARG_FILLED: ctrl->filled = g_value_get_boolean(value); break; @@ -151,6 +157,10 @@ sp_ctrl_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec g_value_set_double(value, ctrl->width); break; + case ARG_ANGLE: + g_value_set_double(value, ctrl->angle); + break; + case ARG_FILLED: g_value_set_boolean(value, ctrl->filled); break; @@ -192,6 +202,7 @@ sp_ctrl_init (SPCtrl *ctrl) ctrl->stroked = 0; ctrl->fill_color = 0x000000ff; ctrl->stroke_color = 0x000000ff; + ctrl->angle = 0.0; new (&ctrl->box) Geom::IntRect(0,0,0,0); ctrl->cache = NULL; @@ -291,6 +302,23 @@ sp_ctrl_point (SPCanvasItem *item, Geom::Point p, SPCanvasItem **actual_item) return 1e18; } +bool +sp_point_inside_line(Geom::Point a, Geom::Point b, Geom::Point c, double tolerance = 0.1){ + //http://stackoverflow.com/questions/328107/how-can-you-determine-a-point-is-between-two-other-points-on-a-line-segment + return Geom::are_near(Geom::distance(a,c) + Geom::distance(c,b) , Geom::distance(a,b), tolerance); +} + +bool +sp_point_inside_triangle(Geom::Point p1,Geom::Point p2,Geom::Point p3, Geom::Point point){ + using Geom::X; + using Geom::Y; + double denominator = (p1[X]*(p2[Y] - p3[Y]) + p1[Y]*(p3[X] - p2[X]) + p2[X]*p3[Y] - p2[Y]*p3[X]); + double t1 = (point[X]*(p3[Y] - p1[Y]) + point[Y]*(p1[X] - p3[X]) - p1[X]*p3[Y] + p1[Y]*p3[X]) / denominator; + double t2 = (point[X]*(p2[Y] - p1[Y]) + point[Y]*(p1[X] - p2[X]) - p1[X]*p2[Y] + p1[Y]*p2[X]) / -denominator; + double see = t1 + t2; + return 0 <= t1 && t1 <= 1 && 0 <= t2 && t2 <= 1 && see <= 1; +} + static void sp_ctrl_build_cache (SPCtrl *ctrl) { @@ -316,7 +344,7 @@ sp_ctrl_build_cache (SPCtrl *ctrl) } else { stroke_color = fill_color; } - + gint32 stroke_color_smooth = SP_RGBA32_F_COMPOSE(SP_RGBA32_R_F(stroke_color), SP_RGBA32_G_F(stroke_color), SP_RGBA32_B_F(stroke_color), 0.15); width = (ctrl->width * 2 +1); height = (ctrl->height * 2 +1); c = ctrl->width; // Only used for pre-set square drawing @@ -325,7 +353,24 @@ sp_ctrl_build_cache (SPCtrl *ctrl) if (ctrl->cache) delete[] ctrl->cache; ctrl->cache = new guint32[size]; - + Geom::Point point; + Geom::Point p1; + Geom::Point p2; + Geom::Point p3; + if(ctrl->shape == SP_CTRL_SHAPE_TRIANGLE){ + Geom::Affine m = Geom::Translate(Geom::Point(-width/2.0,-height/2.0)); + m *= Geom::Rotate(-ctrl->angle); + m *= Geom::Translate(Geom::Point(width/2.0, height/2.0)); + p1 = Geom::Point(0,height/2); + p2 = Geom::Point(width - (width/M_PI), height/M_PI); + p3 = Geom::Point(width - (width/M_PI), height-(height/M_PI)); + p1 *= m; + p2 *= m; + p3 *= m; + p1 = p1.floor(); + p2 = p2.floor(); + p3 = p3.floor(); + } switch (ctrl->shape) { case SP_CTRL_SHAPE_SQUARE: p = ctrl->cache; @@ -407,6 +452,29 @@ sp_ctrl_build_cache (SPCtrl *ctrl) ctrl->build = TRUE; break; + case SP_CTRL_SHAPE_TRIANGLE: + p = ctrl->cache; + for(y = 0; y < height; y++) { + for(x = 0; x < width; x++) { + point = Geom::Point(x,y); + if (sp_point_inside_triangle(p1, p2, p3, point)) { + p[(y*width)+x] = fill_color; + } else if (point == p1 || point == p2 || point == p3 || sp_point_inside_line(p1, p2, point, 0.2) || + sp_point_inside_line(p3, p1, point, 0.2)) + { + p[(y*width)+x] = stroke_color; + } else if (sp_point_inside_line(p1, p2, point, 0.5) || + sp_point_inside_line(p3, p1, point, 0.5)) + { + p[(y*width)+x] = stroke_color_smooth; + } else { + p[(y*width)+x] = 0; + } + } + } + ctrl->build = TRUE; + break; + case SP_CTRL_SHAPE_CROSS: p = ctrl->cache; for (y = 0; y < height; y++) { diff --git a/src/display/sodipodi-ctrl.h b/src/display/sodipodi-ctrl.h index ecdb896a7..ac5ac9442 100644 --- a/src/display/sodipodi-ctrl.h +++ b/src/display/sodipodi-ctrl.h @@ -22,6 +22,7 @@ typedef enum { SP_CTRL_SHAPE_SQUARE, SP_CTRL_SHAPE_DIAMOND, SP_CTRL_SHAPE_CIRCLE, + SP_CTRL_SHAPE_TRIANGLE, SP_CTRL_SHAPE_CROSS, SP_CTRL_SHAPE_BITMAP, SP_CTRL_SHAPE_IMAGE @@ -46,6 +47,7 @@ struct SPCtrl : public SPCanvasItem { guint stroked : 1; guint32 fill_color; guint32 stroke_color; + gdouble angle; Geom::IntRect box; /* NB! x1 & y1 are included */ guint32 *cache; -- cgit v1.2.3 From f799b5d6e8278c76326a6fec8da0e017eac342ec Mon Sep 17 00:00:00 2001 From: Jabiertxof Date: Tue, 6 Dec 2016 21:41:55 +0100 Subject: Fixes for measure LPE and speed path based LPE operations (bzr r15302) --- src/display/curve.cpp | 14 ++++++++++++++ src/display/curve.h | 1 + 2 files changed, 15 insertions(+) (limited to 'src/display') diff --git a/src/display/curve.cpp b/src/display/curve.cpp index 1998e9bec..6e662b17b 100644 --- a/src/display/curve.cpp +++ b/src/display/curve.cpp @@ -334,6 +334,20 @@ SPCurve::is_closed() const } } +/** + * True if both curves are equal + */ +bool +SPCurve::is_equal(SPCurve * other) const +{ + if(other == NULL) { + return false; + } else if(_pathv == other->get_pathvector()){ + return true; + } + return false; +} + /** * Return last pathsegment (possibly the closing path segment) of the last path in PathVector or NULL. * If the last path is empty (contains only a moveto), the function returns NULL diff --git a/src/display/curve.h b/src/display/curve.h index 72e6df95c..8375e1105 100644 --- a/src/display/curve.h +++ b/src/display/curve.h @@ -45,6 +45,7 @@ public: bool is_empty() const; bool is_unset() const; bool is_closed() const; + bool is_equal(SPCurve * other) const; Geom::Curve const * last_segment() const; Geom::Path const * last_path() const; Geom::Curve const * first_segment() const; -- cgit v1.2.3 From 2848c20cfc7f196ba4205cffd2726445485a1df1 Mon Sep 17 00:00:00 2001 From: Alex Valavanis Date: Sun, 25 Dec 2016 19:26:50 +0000 Subject: sp-canvas: Gtkmmify to squash a few warnings (bzr r15353) --- src/display/sp-canvas.cpp | 31 +++++++++++++++++-------------- 1 file changed, 17 insertions(+), 14 deletions(-) (limited to 'src/display') diff --git a/src/display/sp-canvas.cpp b/src/display/sp-canvas.cpp index 9201168ef..416c2c804 100644 --- a/src/display/sp-canvas.cpp +++ b/src/display/sp-canvas.cpp @@ -21,6 +21,8 @@ # include #endif +#include +#include #include #include @@ -61,6 +63,14 @@ struct SPCanvasGroupClass { SPCanvasItemClass parent_class; }; +static void ungrab_default_client_pointer(guint32 const time = GDK_CURRENT_TIME) +{ + auto const display = Gdk::Display::get_default(); + auto const dm = display->get_device_manager(); + auto const device = dm->get_client_pointer(); + device->ungrab(time); +} + /** * A group of items. */ @@ -321,10 +331,7 @@ void sp_canvas_item_dispose(GObject *object) if (item == item->canvas->_grabbed_item) { item->canvas->_grabbed_item = NULL; - - auto dm = gdk_display_get_device_manager(gdk_display_get_default()); - auto device = gdk_device_manager_get_client_pointer(dm); - gdk_device_ungrab(device, GDK_CURRENT_TIME); + ungrab_default_client_pointer(); } if (item == item->canvas->_focused_item) { @@ -647,10 +654,7 @@ void sp_canvas_item_ungrab(SPCanvasItem *item, guint32 etime) } item->canvas->_grabbed_item = NULL; - - auto dm = gdk_display_get_device_manager(gdk_display_get_default()); - auto device = gdk_device_manager_get_client_pointer(dm); - gdk_device_ungrab(device, etime); + ungrab_default_client_pointer(etime); } /** @@ -959,9 +963,7 @@ void SPCanvas::shutdownTransients() if (_grabbed_item) { _grabbed_item = NULL; - auto dm = gdk_display_get_device_manager(gdk_display_get_default()); - auto device = gdk_device_manager_get_client_pointer(dm); - gdk_device_ungrab(device, GDK_CURRENT_TIME); + ungrab_default_client_pointer(); } removeIdle(); } @@ -1685,11 +1687,12 @@ bool SPCanvas::paintRect(int xx0, int yy0, int xx1, int yy1) // Save the mouse location gint x, y; - auto dm = gdk_display_get_device_manager(gdk_display_get_default()); - auto device = gdk_device_manager_get_client_pointer(dm); + auto const display = Gdk::Display::get_default(); + auto const dm = display->get_device_manager(); + auto const device = dm->get_client_pointer(); gdk_window_get_device_position(gtk_widget_get_window(GTK_WIDGET(this)), - device, + device->gobj(), &x, &y, NULL); setup.mouse_loc = sp_canvas_window_to_world(this, Geom::Point(x,y)); -- cgit v1.2.3 From 3182218af4961cfc0a92b2f1eae4cfab74e64eff Mon Sep 17 00:00:00 2001 From: Alex Valavanis Date: Mon, 26 Dec 2016 12:07:14 +0000 Subject: Fix a few Gtkmm deprecations (bzr r15357) --- src/display/canvas-axonomgrid.cpp | 5 +++++ src/display/canvas-grid.cpp | 5 +++++ 2 files changed, 10 insertions(+) (limited to 'src/display') diff --git a/src/display/canvas-axonomgrid.cpp b/src/display/canvas-axonomgrid.cpp index 421a39fbd..94ee4ccfd 100644 --- a/src/display/canvas-axonomgrid.cpp +++ b/src/display/canvas-axonomgrid.cpp @@ -107,7 +107,12 @@ attach_all(Gtk::Grid &table, Gtk::Widget const *const arr[], unsigned size, int table.attach(const_cast(*arr[i+1]), 1, r, 2, 1); } else if (arr[i]) { Gtk::Label& label = reinterpret_cast (const_cast(*arr[i])); +#if GTK_CHECK_VERSION(3,16,0) + label.set_xalign(0.0); + label.set_yalign(0.5); +#else label.set_alignment (0.0); +#endif label.set_hexpand(); label.set_valign(Gtk::ALIGN_CENTER); table.attach(label, 0, r, 3, 1); diff --git a/src/display/canvas-grid.cpp b/src/display/canvas-grid.cpp index 81d194b35..cf7d04555 100644 --- a/src/display/canvas-grid.cpp +++ b/src/display/canvas-grid.cpp @@ -413,7 +413,12 @@ static inline void attach_all(Gtk::Grid &table, Gtk::Widget const *const arr[], table.attach(const_cast(*arr[i+1]), 1, r, 2, 1); } else if (arr[i]) { Gtk::Label& label = reinterpret_cast (const_cast(*arr[i])); +#if GTK_CHECK_VERSION(3,16,0) + label.set_xalign(0.0); + label.set_yalign(0.5); +#else label.set_alignment (0.0); +#endif label.set_hexpand(); label.set_valign(Gtk::ALIGN_CENTER); table.attach(label, 0, r, 3, 1); -- cgit v1.2.3 From d3b4bc2816e0d19e9ecea778ddc01717ea11efb3 Mon Sep 17 00:00:00 2001 From: Tavmjong Bah Date: Tue, 3 Jan 2017 15:39:48 +0100 Subject: Fix logic error (non-scaling stroke on text). (bzr r15386) --- src/display/drawing-text.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/display') diff --git a/src/display/drawing-text.cpp b/src/display/drawing-text.cpp index 1280a2db9..21af7b200 100644 --- a/src/display/drawing-text.cpp +++ b/src/display/drawing-text.cpp @@ -599,7 +599,7 @@ unsigned DrawingText::_renderItem(DrawingContext &dc, Geom::IntRect const &/*are } { Inkscape::DrawingContext::Save save(dc); - if (!_style || ! _style->vector_effect.computed == SP_VECTOR_EFFECT_NON_SCALING_STROKE) { + if (!_style || !(_style->vector_effect.computed == SP_VECTOR_EFFECT_NON_SCALING_STROKE)) { dc.transform(_ctm); } if (has_stroke) { -- cgit v1.2.3 From b6200950a88ac9b1bb7eee4fb7f86b01e323dbcc Mon Sep 17 00:00:00 2001 From: Marc Jeanmougin Date: Thu, 5 Jan 2017 00:08:02 +0100 Subject: antialiasing options on export (bzr r15391) --- src/display/drawing-group.cpp | 3 +++ src/display/drawing-item.cpp | 23 +++++++++++++++++------ src/display/drawing-item.h | 4 ++-- src/display/drawing.cpp | 6 +++++- src/display/drawing.h | 2 +- 5 files changed, 28 insertions(+), 10 deletions(-) (limited to 'src/display') diff --git a/src/display/drawing-group.cpp b/src/display/drawing-group.cpp index 1a9cbfdcc..018f23e74 100644 --- a/src/display/drawing-group.cpp +++ b/src/display/drawing-group.cpp @@ -95,6 +95,7 @@ DrawingGroup::_renderItem(DrawingContext &dc, Geom::IntRect const &area, unsigne if (stop_at == NULL) { // normal rendering for (ChildrenList::iterator i = _children.begin(); i != _children.end(); ++i) { + i->setAntialiasing(_antialias); i->render(dc, area, flags, stop_at); } } else { @@ -103,10 +104,12 @@ DrawingGroup::_renderItem(DrawingContext &dc, Geom::IntRect const &area, unsigne if (&*i == stop_at) return RENDER_OK; // do not render the stop_at item at all if (i->isAncestorOf(stop_at)) { // render its ancestors without masks, opacity or filters + i->setAntialiasing(_antialias); i->render(dc, area, flags | RENDER_FILTER_BACKGROUND, stop_at); // stop further rendering return RENDER_OK; } else { + i->setAntialiasing(_antialias); i->render(dc, area, flags, stop_at); } } diff --git a/src/display/drawing-item.cpp b/src/display/drawing-item.cpp index 89ca66dc4..c4af81efc 100644 --- a/src/display/drawing-item.cpp +++ b/src/display/drawing-item.cpp @@ -132,7 +132,7 @@ DrawingItem::DrawingItem(Drawing &drawing) , _propagate(0) // , _renders_opacity(0) , _pick_children(0) - , _antialias(1) + , _antialias(2) , _isolation(SP_CSS_ISOLATION_AUTO) , _mix_blend_mode(SP_CSS_BLEND_NORMAL) {} @@ -291,7 +291,7 @@ DrawingItem::setOpacity(float opacity) } void -DrawingItem::setAntialiasing(bool a) +DrawingItem::setAntialiasing(unsigned a) { if (_antialias != a) { _antialias = a; @@ -699,10 +699,21 @@ DrawingItem::render(DrawingContext &dc, Geom::IntRect const &area, unsigned flag Geom::OptIntRect carea = Geom::intersect(area, _drawbox); if (!carea) return RENDER_OK; - if (_antialias) { - cairo_set_antialias(dc.raw(), CAIRO_ANTIALIAS_DEFAULT); - } else { - cairo_set_antialias(dc.raw(), CAIRO_ANTIALIAS_NONE); + switch(_antialias){ + case 0: + cairo_set_antialias(dc.raw(), CAIRO_ANTIALIAS_NONE); + break; + case 1: + cairo_set_antialias(dc.raw(), CAIRO_ANTIALIAS_FAST); + break; + case 2: + cairo_set_antialias(dc.raw(), CAIRO_ANTIALIAS_GOOD); + break; + case 3: + cairo_set_antialias(dc.raw(), CAIRO_ANTIALIAS_BEST); + break; + default: // should not happen + g_assert_not_reached(); } // render from cache if possible diff --git a/src/display/drawing-item.h b/src/display/drawing-item.h index 3c593ceaa..21f6ffacc 100644 --- a/src/display/drawing-item.h +++ b/src/display/drawing-item.h @@ -115,7 +115,7 @@ public: virtual void setStyle(SPStyle *style, SPStyle *context_style = NULL); virtual void setChildrenStyle(SPStyle *context_style); void setOpacity(float opacity); - void setAntialiasing(bool a); + void setAntialiasing(unsigned a); void setIsolation(unsigned isolation); // CSS Compositing and Blending void setBlendMode(unsigned blend_mode); void setTransform(Geom::Affine const &trans); @@ -222,7 +222,7 @@ protected: //unsigned _renders_opacity : 1; ///< Whether object needs temporary surface for opacity unsigned _pick_children : 1; ///< For groups: if true, children are returned from pick(), /// otherwise the group is returned - unsigned _antialias : 1; ///< Whether to use antialiasing + unsigned _antialias : 2; ///< antialiasing level (NONE/FAST/GOOD(DEFAULT)/BEST) unsigned _isolation : 1; unsigned _mix_blend_mode : 4; diff --git a/src/display/drawing.cpp b/src/display/drawing.cpp index eadd7e528..71fb94be0 100644 --- a/src/display/drawing.cpp +++ b/src/display/drawing.cpp @@ -167,10 +167,14 @@ Drawing::update(Geom::IntRect const &area, UpdateContext const &ctx, unsigned fl } void -Drawing::render(DrawingContext &dc, Geom::IntRect const &area, unsigned flags) +Drawing::render(DrawingContext &dc, Geom::IntRect const &area, unsigned flags, int antialiasing) { if (_root) { + int prev_a = _root->_antialias; + if(antialiasing >= 0) + _root->setAntialiasing(antialiasing); _root->render(dc, area, flags); + _root->setAntialiasing(prev_a); } if (colorMode() == COLORMODE_GRAYSCALE) { diff --git a/src/display/drawing.h b/src/display/drawing.h index 0c12b1510..e472c8f5b 100644 --- a/src/display/drawing.h +++ b/src/display/drawing.h @@ -68,7 +68,7 @@ public: void setGrayscaleMatrix(double value_matrix[20]); void update(Geom::IntRect const &area = Geom::IntRect::infinite(), UpdateContext const &ctx = UpdateContext(), unsigned flags = DrawingItem::STATE_ALL, unsigned reset = 0); - void render(DrawingContext &dc, Geom::IntRect const &area, unsigned flags = 0); + void render(DrawingContext &dc, Geom::IntRect const &area, unsigned flags = 0, int antialiasing = -1); DrawingItem *pick(Geom::Point const &p, double delta, unsigned flags); sigc::signal signal_request_update; -- cgit v1.2.3 From 5d4aa9ac147ae6db7428aa876293cf2c46fae7a5 Mon Sep 17 00:00:00 2001 From: Diederik van Lierop Date: Wed, 11 Jan 2017 21:58:37 +0100 Subject: Fix snapping tooltips and highlighting of snapped bounding boxes (both of which were not shown) (bzr r15410) --- src/display/snap-indicator.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/display') diff --git a/src/display/snap-indicator.cpp b/src/display/snap-indicator.cpp index 17deea16d..f2271e0c6 100644 --- a/src/display/snap-indicator.cpp +++ b/src/display/snap-indicator.cpp @@ -287,7 +287,7 @@ SnapIndicator::set_new_snaptarget(Inkscape::SnappedPoint const &p, bool pre_snap } else if (p.getSource() != SNAPSOURCE_UNDEFINED) { tooltip_str = g_strdup(source_name); } - double fontsize = prefs->getInt("/tools/measure/fontsize"); + double fontsize = prefs->getDouble("/tools/measure/fontsize", 10.0); if (tooltip_str) { Geom::Point tooltip_pos = p.getPoint(); @@ -327,7 +327,7 @@ SnapIndicator::set_new_snaptarget(Inkscape::SnappedPoint const &p, bool pre_snap SP_CTRLRECT(box)->setDashed(true); SP_CTRLRECT(box)->pickable = false; // See the extensive comment above sp_canvas_item_move_to_z(box, 0); - _snaptarget_bbox = _desktop->add_temporary_canvasitem(box, timeout_val); + _snaptarget_bbox = _desktop->add_temporary_canvasitem(box, timeout_val*1000.0); } } } -- cgit v1.2.3 From 00bf8be09a333bb7434eeba9e885e6089b6eb5fd Mon Sep 17 00:00:00 2001 From: Eduard Braun Date: Thu, 12 Jan 2017 22:45:33 +0100 Subject: Use GStatBuf where appropriate to ensure usage of the correct type (fixes compilation with i686-w64-mingw32) (bzr r15414) --- src/display/cairo-utils.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/display') diff --git a/src/display/cairo-utils.cpp b/src/display/cairo-utils.cpp index 01b0d807c..8045007e7 100644 --- a/src/display/cairo-utils.cpp +++ b/src/display/cairo-utils.cpp @@ -290,7 +290,7 @@ Pixbuf *Pixbuf::create_from_file(std::string const &fn) if (!g_file_test(fn.c_str(), G_FILE_TEST_EXISTS)) { return NULL; } - struct stat stdir; + GStatBuf stdir; int val = g_stat(fn.c_str(), &stdir); if (val == 0 && stdir.st_mode & S_IFDIR){ return NULL; -- cgit v1.2.3 From 1e3e159499532a145cf09af2dbd1de2ae4d8d565 Mon Sep 17 00:00:00 2001 From: Alex Valavanis Date: Mon, 6 Feb 2017 15:34:17 +0000 Subject: Remove some unneeded < C++11 fallback code (bzr r15485) --- src/display/canvas-axonomgrid.cpp | 1 - src/display/nr-filter-turbulence.cpp | 12 ------------ src/display/nr-filter-utils.h | 2 -- src/display/nr-filter.cpp | 5 ----- 4 files changed, 20 deletions(-) (limited to 'src/display') diff --git a/src/display/canvas-axonomgrid.cpp b/src/display/canvas-axonomgrid.cpp index 94ee4ccfd..589cc849d 100644 --- a/src/display/canvas-axonomgrid.cpp +++ b/src/display/canvas-axonomgrid.cpp @@ -42,7 +42,6 @@ #include "2geom/line.h" #include "2geom/angle.h" #include "helper/mathfns.h" -#include "round.h" #include "util/units.h" using Inkscape::Util::unit_table; diff --git a/src/display/nr-filter-turbulence.cpp b/src/display/nr-filter-turbulence.cpp index 19dedb67c..1397c0f34 100644 --- a/src/display/nr-filter-turbulence.cpp +++ b/src/display/nr-filter-turbulence.cpp @@ -286,15 +286,7 @@ private: static int const BSize = 0x100; static int const BMask = 0xff; -#ifdef CPP11 // GCC 4.6.1 (currently used on Windows) does not correctly set __cplusplus in C++11 mode, so configure with -DCPP11 to make this work in C++11 mode static double constexpr PerlinOffset = 4096.0; -#else -#if (__cplusplus < 201103L) - static double const PerlinOffset; -#else - static double constexpr PerlinOffset = 4096.0; -#endif -#endif Geom::Rect _tile; Geom::Point _baseFreq; @@ -311,10 +303,6 @@ private: bool _fractalnoise; }; -#if !defined(CPP11) && __cplusplus < 201103L - double const TurbulenceGenerator::PerlinOffset = 4096.0; -#endif - FilterTurbulence::FilterTurbulence() : gen(new TurbulenceGenerator()) , XbaseFrequency(0) diff --git a/src/display/nr-filter-utils.h b/src/display/nr-filter-utils.h index 35a74d7c1..52b6bd11a 100644 --- a/src/display/nr-filter-utils.h +++ b/src/display/nr-filter-utils.h @@ -14,8 +14,6 @@ * Released under GNU GPL, read the file 'COPYING' for more information */ -#include "round.h" - namespace Inkscape { namespace Filters { diff --git a/src/display/nr-filter.cpp b/src/display/nr-filter.cpp index 789758d9c..d430553d4 100644 --- a/src/display/nr-filter.cpp +++ b/src/display/nr-filter.cpp @@ -48,11 +48,6 @@ #include "sp-filter-units.h" #include "preferences.h" -#if defined (SOLARIS) && (SOLARIS == 8) -#include "round.h" -using Inkscape::round; -#endif - namespace Inkscape { namespace Filters { -- cgit v1.2.3 From 58808234db8381a86518229e176f429f440ff93f Mon Sep 17 00:00:00 2001 From: Alex Valavanis Date: Tue, 7 Feb 2017 18:34:57 +0000 Subject: Fix some new Gdk deprecations (bzr r15491) --- src/display/sp-canvas.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/display') diff --git a/src/display/sp-canvas.cpp b/src/display/sp-canvas.cpp index 68eae0a65..41d136ee9 100644 --- a/src/display/sp-canvas.cpp +++ b/src/display/sp-canvas.cpp @@ -1034,7 +1034,7 @@ void SPCanvas::handle_realize(GtkWidget *widget) attributes.width = allocation.width; attributes.height = allocation.height; attributes.wclass = GDK_INPUT_OUTPUT; - attributes.visual = gdk_visual_get_system(); + attributes.visual = gdk_screen_get_system_visual(gdk_screen_get_default()); attributes.event_mask = (gtk_widget_get_events (widget) | GDK_EXPOSURE_MASK | -- cgit v1.2.3 From 06be77e76584d2a419ce942fd3f6db891f318c7d Mon Sep 17 00:00:00 2001 From: Alex Valavanis Date: Tue, 7 Feb 2017 19:19:46 +0000 Subject: Fix Gdk deprecations (bzr r15492) --- src/display/sp-canvas.cpp | 27 +++++++++++++++++++++++++-- 1 file changed, 25 insertions(+), 2 deletions(-) (limited to 'src/display') diff --git a/src/display/sp-canvas.cpp b/src/display/sp-canvas.cpp index 41d136ee9..623e417c6 100644 --- a/src/display/sp-canvas.cpp +++ b/src/display/sp-canvas.cpp @@ -48,6 +48,10 @@ #include #include +#if GTK_CHECK_VERSION(3,20,0) +# include +#endif + using Inkscape::Debug::GdkEventLatencyTracker; // gtk_check_version returns non-NULL on failure @@ -72,8 +76,14 @@ struct SPCanvasGroupClass { static void ungrab_default_client_pointer(guint32 const time = GDK_CURRENT_TIME) { auto const display = Gdk::Display::get_default(); + +#if GTK_CHECK_VERSION(3,20,0) + auto const seat = display->get_default_seat(); + auto const device = seat->get_pointer(); +#else auto const dm = display->get_device_manager(); auto const device = dm->get_client_pointer(); +#endif device->ungrab(time); } @@ -625,9 +635,16 @@ int sp_canvas_item_grab(SPCanvasItem *item, guint event_mask, GdkCursor *cursor, // fixme: Top hack (Lauris) // fixme: If we add key masks to event mask, Gdk will abort (Lauris) - // fixme: But Canvas actualle does get key events, so all we need is routing these here - auto dm = gdk_display_get_device_manager(gdk_display_get_default()); + // fixme: But Canvas actually does get key events, so all we need is routing these here + auto display = gdk_display_get_default(); +#if GTK_CHECK_VERSION(3,20,0) + auto seat = gdk_display_get_default_seat(display); + auto device = gdk_seat_get_pointer(seat); +#else + auto dm = gdk_display_get_device_manager(display); auto device = gdk_device_manager_get_client_pointer(dm); +#endif + gdk_device_grab(device, getWindow(item->canvas), GDK_OWNERSHIP_NONE, @@ -1694,8 +1711,14 @@ bool SPCanvas::paintRect(int xx0, int yy0, int xx1, int yy1) gint x, y; auto const display = Gdk::Display::get_default(); + +#if GTK_CHECK_VERSION(3,20,0) + auto const seat = display->get_default_seat(); + auto const device = seat->get_pointer(); +#else auto const dm = display->get_device_manager(); auto const device = dm->get_client_pointer(); +#endif gdk_window_get_device_position(gtk_widget_get_window(GTK_WIDGET(this)), device->gobj(), -- cgit v1.2.3 From 5d9c07e014cf054a8936478f6d097805cb2a84f6 Mon Sep 17 00:00:00 2001 From: Alex Valavanis Date: Sun, 26 Feb 2017 17:58:40 +0000 Subject: sp-canvas: Migrate to seat_grab (bzr r15548) --- src/display/sp-canvas.cpp | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) (limited to 'src/display') diff --git a/src/display/sp-canvas.cpp b/src/display/sp-canvas.cpp index 623e417c6..9cc9e51a2 100644 --- a/src/display/sp-canvas.cpp +++ b/src/display/sp-canvas.cpp @@ -78,13 +78,13 @@ static void ungrab_default_client_pointer(guint32 const time = GDK_CURRENT_TIME) auto const display = Gdk::Display::get_default(); #if GTK_CHECK_VERSION(3,20,0) - auto const seat = display->get_default_seat(); - auto const device = seat->get_pointer(); + auto const seat = display->get_default_seat(); + seat->ungrab(); #else auto const dm = display->get_device_manager(); auto const device = dm->get_client_pointer(); -#endif device->ungrab(time); +#endif } /** @@ -639,11 +639,17 @@ int sp_canvas_item_grab(SPCanvasItem *item, guint event_mask, GdkCursor *cursor, auto display = gdk_display_get_default(); #if GTK_CHECK_VERSION(3,20,0) auto seat = gdk_display_get_default_seat(display); - auto device = gdk_seat_get_pointer(seat); + gdk_seat_grab(seat, + getWindow(item->canvas), + GDK_SEAT_CAPABILITY_ALL_POINTING, + FALSE, + cursor, + NULL, + NULL, + NULL); #else auto dm = gdk_display_get_device_manager(display); auto device = gdk_device_manager_get_client_pointer(dm); -#endif gdk_device_grab(device, getWindow(item->canvas), @@ -652,6 +658,7 @@ int sp_canvas_item_grab(SPCanvasItem *item, guint event_mask, GdkCursor *cursor, (GdkEventMask)(event_mask & (~(GDK_KEY_PRESS_MASK | GDK_KEY_RELEASE_MASK))), cursor, etime); +#endif item->canvas->_grabbed_item = item; item->canvas->_grabbed_event_mask = event_mask; -- cgit v1.2.3 From 014489163050d8abe9e5c4949fb80f3c21b1c17b Mon Sep 17 00:00:00 2001 From: Tavmjong Bah Date: Mon, 13 Mar 2017 15:22:22 +0100 Subject: Replace rectangle based zooming by affine based zooming. This allows a rotation to be included in the drawing to window mapping. General code cleanup. Added documentation. Any change to zooming behavior is probably a bug. (bzr r15592) --- src/display/canvas-grid.cpp | 4 +++- src/display/sp-canvas.cpp | 8 +++++++- src/display/sp-canvas.h | 4 ++-- 3 files changed, 12 insertions(+), 4 deletions(-) (limited to 'src/display') diff --git a/src/display/canvas-grid.cpp b/src/display/canvas-grid.cpp index cf7d04555..2dadde336 100644 --- a/src/display/canvas-grid.cpp +++ b/src/display/canvas-grid.cpp @@ -841,7 +841,9 @@ void CanvasXYGrid::Update (Geom::Affine const &affine, unsigned int /*flags*/) { ow = origin * affine; - sw = spacing * affine; + // Temp hack to insure grid doesn't collapse with rotation. + sw[0] = spacing[0] * sqrt(affine[0]*affine[0] + affine[1]*affine[1]); + sw[1] = spacing[1] * sqrt(affine[2]*affine[2] + affine[3]*affine[3]); sw -= Geom::Point(affine[4], affine[5]); for(int dim = 0; dim < 2; dim++) { diff --git a/src/display/sp-canvas.cpp b/src/display/sp-canvas.cpp index 9cc9e51a2..61602e880 100644 --- a/src/display/sp-canvas.cpp +++ b/src/display/sp-canvas.cpp @@ -1937,10 +1937,16 @@ double start_angle = 0; bool started = false; bool rotated = false; -void SPCanvas::scrollTo(double cx, double cy, unsigned int clear, bool is_scrolling) +/** + * Scroll screen to point 'c'. 'c' is measured in screen pixels. + */ +void SPCanvas::scrollTo( Geom::Point const &c, unsigned int clear, bool is_scrolling) { GtkAllocation allocation; + double cx = c[Geom::X]; + double cy = c[Geom::Y]; + int ix = (int) round(cx); // ix and iy are the new canvas coordinates (integer screen pixels) int iy = (int) round(cy); // cx might be negative, so (int)(cx + 0.5) will not do! int dx = ix - _x0; // dx and dy specify the displacement (scroll) of the diff --git a/src/display/sp-canvas.h b/src/display/sp-canvas.h index 21b6760f2..708653bdf 100644 --- a/src/display/sp-canvas.h +++ b/src/display/sp-canvas.h @@ -70,8 +70,8 @@ GType sp_canvas_get_type() G_GNUC_CONST; * Port of GnomeCanvas for inkscape needs. */ struct SPCanvas { - /// Scrolls canvas to specific position (cx and cy are measured in screen pixels). - void scrollTo(double cx, double cy, unsigned int clear, bool is_scrolling = false); + /// Scrolls canvas to specific position (c is measured in screen pixels). + void scrollTo(Geom::Point const &c, unsigned int clear, bool is_scrolling = false); void startRotateTo(double angle); void rotateTo(double angle); bool endRotateTo(); -- cgit v1.2.3 From e63d47761375ee56dc2e221de1a3cbea54dd1f66 Mon Sep 17 00:00:00 2001 From: Tavmjong Bah Date: Wed, 15 Mar 2017 10:45:17 +0100 Subject: Fix rendering when canvas rotated. General code clean-up and documentation. (bzr r15598) --- src/display/guideline.cpp | 104 ++++++++++++++++++++-------------------------- 1 file changed, 44 insertions(+), 60 deletions(-) (limited to 'src/display') diff --git a/src/display/guideline.cpp b/src/display/guideline.cpp index f66b65e1a..cde10f6c2 100644 --- a/src/display/guideline.cpp +++ b/src/display/guideline.cpp @@ -10,12 +10,15 @@ * Copyright (C) 2000-2002 Lauris Kaplinski * Copyright (C) 2007 Johan Engelen * Copyright (C) 2009 Maximilian Albert + * Copyright (C) 2017 Tavmjong Bah * * Released under GNU GPL, read the file 'COPYING' for more information */ #include <2geom/coord.h> #include <2geom/transforms.h> +#include <2geom/line.h> + #include "sp-canvas-util.h" #include "guideline.h" #include "display/cairo-utils.h" @@ -29,8 +32,6 @@ static void sp_guideline_render(SPCanvasItem *item, SPCanvasBuf *buf); static double sp_guideline_point(SPCanvasItem *item, Geom::Point p, SPCanvasItem **actual_item); -static void sp_guideline_drawline (SPCanvasBuf *buf, gint x0, gint y0, gint x1, gint y1, guint32 rgba); - G_DEFINE_TYPE(SPGuideLine, sp_guideline, SP_TYPE_CANVAS_ITEM); static void sp_guideline_class_init(SPGuideLineClass *c) @@ -76,10 +77,6 @@ static void sp_guideline_destroy(SPCanvasItem *object) static void sp_guideline_render(SPCanvasItem *item, SPCanvasBuf *buf) { - //TODO: the routine that renders the label of a specific guideline sometimes - // ends up erasing the labels of the other guidelines. - // Maybe we should render all labels everytime. - SPGuideLine const *gl = SP_GUIDELINE (item); cairo_save(buf->ct); @@ -89,8 +86,9 @@ static void sp_guideline_render(SPCanvasItem *item, SPCanvasBuf *buf) cairo_set_line_cap(buf->ct, CAIRO_LINE_CAP_SQUARE); cairo_set_font_size(buf->ct, 10); - Geom::Point normal_dt = /*unit_vector*/(gl->normal_to_line * gl->affine.withoutTranslation()); // note that normal_dt does not have unit length - Geom::Point point_on_line_dt = gl->point_on_line * gl->affine; + // normal_dt does not have unit length + Geom::Point normal_dt = gl->normal_to_line * gl->affine.withoutTranslation(); + Geom::Point point_on_line_dt = gl->point_on_line * gl->affine; if (gl->label) { int px = round(point_on_line_dt[Geom::X]); @@ -104,55 +102,54 @@ static void sp_guideline_render(SPCanvasItem *item, SPCanvasBuf *buf) cairo_restore(buf->ct); } - if ( Geom::are_near(normal_dt[Geom::Y], 0.) ) { // is vertical? + // Draw guide. + // Special case horizontal and vertical lines so they snap to pixels. + // Don't use isHorizontal()/isVertical() as they test only exact matches. + if ( Geom::are_near(normal_dt[Geom::Y], 0.0) ) { // Vertical? + int position = round(point_on_line_dt[Geom::X]); cairo_move_to(buf->ct, position + 0.5, buf->rect.top() + 0.5); cairo_line_to(buf->ct, position + 0.5, buf->rect.bottom() - 0.5); cairo_stroke(buf->ct); - } else if ( Geom::are_near(normal_dt[Geom::X], 0.) ) { // is horizontal? + + } else if ( Geom::are_near(normal_dt[Geom::X], 0.0) ) { // Horizontal? + int position = round(point_on_line_dt[Geom::Y]); cairo_move_to(buf->ct, buf->rect.left() + 0.5, position + 0.5); cairo_line_to(buf->ct, buf->rect.right() - 0.5, position + 0.5); cairo_stroke(buf->ct); - } else { - // render angled line. Once intersection has been detected, draw from there. - Geom::Point parallel_to_line( normal_dt.ccw() ); - - //try to intersect with left vertical of rect - double y_intersect_left = (buf->rect.left() - point_on_line_dt[Geom::X]) * parallel_to_line[Geom::Y] / parallel_to_line[Geom::X] + point_on_line_dt[Geom::Y]; - if ( (y_intersect_left >= buf->rect.top()) && (y_intersect_left <= buf->rect.bottom()) ) { - // intersects with left vertical! - double y_intersect_right = (buf->rect.right() - point_on_line_dt[Geom::X]) * parallel_to_line[Geom::Y] / parallel_to_line[Geom::X] + point_on_line_dt[Geom::Y]; - sp_guideline_drawline (buf, buf->rect.left(), static_cast(round(y_intersect_left)), buf->rect.right(), static_cast(round(y_intersect_right)), gl->rgba); - goto end; - } - //try to intersect with right vertical of rect - double y_intersect_right = (buf->rect.right() - point_on_line_dt[Geom::X]) * parallel_to_line[Geom::Y] / parallel_to_line[Geom::X] + point_on_line_dt[Geom::Y]; - if ( (y_intersect_right >= buf->rect.top()) && (y_intersect_right <= buf->rect.bottom()) ) { - // intersects with right vertical! - sp_guideline_drawline (buf, buf->rect.right(), static_cast(round(y_intersect_right)), buf->rect.left(), static_cast(round(y_intersect_left)), gl->rgba); - goto end; - } + } else { - //try to intersect with top horizontal of rect - double x_intersect_top = (buf->rect.top() - point_on_line_dt[Geom::Y]) * parallel_to_line[Geom::X] / parallel_to_line[Geom::Y] + point_on_line_dt[Geom::X]; - if ( (x_intersect_top >= buf->rect.left()) && (x_intersect_top <= buf->rect.right()) ) { - // intersects with top horizontal! - double x_intersect_bottom = (buf->rect.bottom() - point_on_line_dt[Geom::Y]) * parallel_to_line[Geom::X] / parallel_to_line[Geom::Y] + point_on_line_dt[Geom::X]; - sp_guideline_drawline (buf, static_cast(round(x_intersect_top)), buf->rect.top(), static_cast(round(x_intersect_bottom)), buf->rect.bottom(), gl->rgba); - goto end; + Geom::Line guide = + Geom::Line::from_origin_and_vector( point_on_line_dt, Geom::rot90(normal_dt) ); + + // Find intersections of guide with buf rectangle. There should be zero or two. + std::vector intersections; + for (unsigned i = 0; i < 4; ++i) { + Geom::LineSegment side( buf->rect.corner(i), buf->rect.corner((i+1)%4) ); + try { + Geom::OptCrossing oc = Geom::intersection(guide, side); + if (oc) { + intersections.push_back( guide.pointAt((*oc).ta)); + } + } catch (Geom::InfiniteSolutions) { + // Shouldn't happen as we have already taken care of horizontal/vertical guides. + std::cerr << "sp_guideline_render: Error: Infinite intersections." << std::endl; + } } - //try to intersect with bottom horizontal of rect - double x_intersect_bottom = (buf->rect.bottom() - point_on_line_dt[Geom::Y]) * parallel_to_line[Geom::X] / parallel_to_line[Geom::Y] + point_on_line_dt[Geom::X]; - if ( (x_intersect_top >= buf->rect.left()) && (x_intersect_top <= buf->rect.right()) ) { - // intersects with bottom horizontal! - sp_guideline_drawline (buf, static_cast(round(x_intersect_bottom)), buf->rect.bottom(), static_cast(round(x_intersect_top)), buf->rect.top(), gl->rgba); - goto end; + if (intersections.size() == 2) { + double x0 = intersections[0][Geom::X]; + double x1 = intersections[1][Geom::X]; + double y0 = intersections[0][Geom::Y]; + double y1 = intersections[1][Geom::Y]; + cairo_move_to(buf->ct, x0, y0); + cairo_line_to(buf->ct, x1, y1); + cairo_stroke(buf->ct); } } - end: + cairo_restore(buf->ct); } @@ -179,15 +176,10 @@ static void sp_guideline_update(SPCanvasItem *item, Geom::Affine const &affine, } gl->affine = affine; - Geom::Point pol_transformed = gl->point_on_line * affine; - if (gl->is_horizontal()) { - sp_canvas_update_bbox (item, -1000000, round(pol_transformed[Geom::Y] - 16), 1000000, round(pol_transformed[Geom::Y] + 1)); - } else if (gl->is_vertical()) { - sp_canvas_update_bbox (item, round(pol_transformed[Geom::X]), -1000000, round(pol_transformed[Geom::X] + 16), 1000000); - } else { - //TODO: labels in angled guidelines are not showing up for some reason. - sp_canvas_update_bbox (item, -1000000, -1000000, 1000000, 1000000); - } + + // Rotated canvas requires large bbox for all guides. + sp_canvas_update_bbox (item, -1000000, -1000000, 1000000, 1000000); + } // Returns 0.0 if point is on the guideline @@ -276,14 +268,6 @@ void sp_guideline_delete(SPGuideLine *gl) sp_canvas_item_destroy(SP_CANVAS_ITEM(gl)); } -static void -sp_guideline_drawline (SPCanvasBuf *buf, gint x0, gint y0, gint x1, gint y1, guint32 /*rgba*/) -{ - cairo_move_to(buf->ct, x0 + 0.5, y0 + 0.5); - cairo_line_to(buf->ct, x1 + 0.5, y1 + 0.5); - cairo_stroke(buf->ct); -} - /* Local Variables: mode:c++ -- cgit v1.2.3 From a3dda4d25b4b6ed4d23e3003fa4538cb1c5df0e1 Mon Sep 17 00:00:00 2001 From: Tavmjong Bah Date: Fri, 17 Mar 2017 10:01:27 +0100 Subject: Modifiy CtrlRect to work with rotated canvas. (bzr r15600) --- src/display/sodipodi-ctrlrect.cpp | 261 +++++++++++++++++--------------------- src/display/sodipodi-ctrlrect.h | 11 +- 2 files changed, 127 insertions(+), 145 deletions(-) (limited to 'src/display') diff --git a/src/display/sodipodi-ctrlrect.cpp b/src/display/sodipodi-ctrlrect.cpp index ecc952c48..b27a81ab3 100644 --- a/src/display/sodipodi-ctrlrect.cpp +++ b/src/display/sodipodi-ctrlrect.cpp @@ -6,9 +6,11 @@ * bulia byak * Carl Hetherington * Jon A. Cruz + * Tavmjong Bah * * Copyright (C) 1999-2001 Lauris Kaplinski * Copyright (C) 2000-2001 Ximian, Inc. + * Copyright (C) 2017 Tavmjong Bah * * Released under GNU GPL * @@ -18,6 +20,7 @@ #include "sp-canvas-util.h" #include "display/cairo-utils.h" #include "display/sp-canvas.h" +#include <2geom/transforms.h> /* * Currently we do not have point method, as it should always be painted @@ -76,14 +79,12 @@ void CtrlRect::init() _dashed = false; _checkerboard = false; - _shadow = 0; + _shadow_width = 0; _area = Geom::OptIntRect(); _rect = Geom::Rect(Geom::Point(0,0),Geom::Point(0,0)); - _shadow_size = 0; - _border_color = 0x000000ff; _fill_color = 0xffffffff; _shadow_color = 0x000000ff; @@ -98,52 +99,119 @@ void CtrlRect::render(SPCanvasBuf *buf) if (!_area) { return; } - Geom::IntRect area = *_area; - Geom::IntRect area_w_shadow (area[X].min(), area[Y].min(), - area[X].max() + _shadow_size, area[Y].max() + _shadow_size); - if ( area_w_shadow.intersects(buf->rect) ) + + Geom::IntRect area = *_area; // _area already includes space for shadow. + if ( area.intersects(buf->rect) ) { - static double const dashes[2] = {4.0, 4.0}; + cairo_save(buf->ct); cairo_translate(buf->ct, -buf->rect.left(), -buf->rect.top()); - cairo_set_line_width(buf->ct, 1); - if (_dashed) cairo_set_dash(buf->ct, dashes, 2, 0); - cairo_rectangle(buf->ct, 0.5 + area[X].min(), 0.5 + area[Y].min(), - area[X].max() - area[X].min(), area[Y].max() - area[Y].min()); + + // Get canvas rotation (scale is isotropic). + double rotation = atan2( _affine[1], _affine[0] ); + + // Are we axis aligned? + double mod_rot = fmod(rotation * M_2_PI, 1); + bool axis_aligned = Geom::are_near( mod_rot, 0 ) || Geom::are_near( mod_rot, 1.0 ); + + // Get the points we need transformed to window coordinates. + Geom::Point rect_transformed[4]; + for (unsigned i = 0; i < 4; ++i) { + rect_transformed[i] = _rect.corner(i) * _affine; + } + + // Draw shadow first. Shadow extends under rectangle to reduce aliasing effects. + if (_shadow_width > 0 && !_dashed) { + + // Offset by half stroke width (_shadow_width is in window coordinates). + Geom::Point shadow( _shadow_width/2.0, _shadow_width/2.0 ); + shadow *= Geom::Rotate( rotation ); + + if (axis_aligned) { + // Snap to pixel grid (add 0.5 to center on pixel). + cairo_move_to( buf->ct, + floor(rect_transformed[0][X]+shadow[X]+0.5) + 0.5, + floor(rect_transformed[0][Y]+shadow[Y]+0.5) + 0.5 ); + cairo_line_to( buf->ct, + floor(rect_transformed[1][X]+shadow[X]+0.5) + 0.5, + floor(rect_transformed[1][Y]+shadow[Y]+0.5) + 0.5 ); + cairo_line_to( buf->ct, + floor(rect_transformed[2][X]+shadow[X]+0.5) + 0.5, + floor(rect_transformed[2][Y]+shadow[Y]+0.5) + 0.5 ); + } else { + cairo_move_to( buf->ct, + rect_transformed[0][X]+shadow[X], + rect_transformed[0][Y]+shadow[Y] ); + cairo_line_to( buf->ct, + rect_transformed[1][X]+shadow[X], + rect_transformed[1][Y]+shadow[Y] ); + cairo_line_to( buf->ct, + rect_transformed[2][X]+shadow[X], + rect_transformed[2][Y]+shadow[Y] ); + } + + ink_cairo_set_source_rgba32( buf->ct, _shadow_color ); + cairo_set_line_width( buf->ct, _shadow_width + 1 ); + cairo_stroke( buf->ct ); + } + + // Setup rectangle path + if (axis_aligned) { + + // Snap to pixel grid + Geom::Rect outline( _rect.min() * _affine, _rect.max() * _affine); + // Check if there is a simpler way to go from 'outline' to 'int_rect'. + Geom::IntRect int_rect ( (int) floor(outline.min()[X] + 0.5), + (int) floor(outline.min()[Y] + 0.5), + (int) floor(outline.max()[X] + 0.5), + (int) floor(outline.max()[Y] + 0.5) ); + cairo_rectangle (buf->ct, + 0.5 + int_rect[X].min(), + 0.5 + int_rect[Y].min(), + int_rect[X].max() - int_rect[X].min(), + int_rect[Y].max() - int_rect[Y].min() ); + } else { + + // Angled + cairo_move_to( buf->ct, rect_transformed[0][X], rect_transformed[0][Y] ); + cairo_line_to( buf->ct, rect_transformed[1][X], rect_transformed[1][Y] ); + cairo_line_to( buf->ct, rect_transformed[2][X], rect_transformed[2][Y] ); + cairo_line_to( buf->ct, rect_transformed[3][X], rect_transformed[3][Y] ); + cairo_close_path( buf->ct ); + } + + // This doesn't seem to be used anywhere. If it is, then we should + // probably rotate the coordinate system and fill using a cairo_rectangle(). if (_checkerboard) { cairo_pattern_t *cb = ink_cairo_pattern_create_checkerboard(); cairo_set_source(buf->ct, cb); cairo_pattern_destroy(cb); cairo_fill_preserve(buf->ct); } + if (_has_fill) { ink_cairo_set_source_rgba32(buf->ct, _fill_color); cairo_fill_preserve(buf->ct); } + // Set up stroke. ink_cairo_set_source_rgba32(buf->ct, _border_color); - cairo_stroke(buf->ct); + cairo_set_line_width(buf->ct, 1); + static double const dashes[2] = {4.0, 4.0}; + if (_dashed) cairo_set_dash(buf->ct, dashes, 2, 0); - if (_shadow_size == 1) { // highlight the border by drawing it in _shadow_color - if (_dashed) { - cairo_set_dash(buf->ct, dashes, 2, 4); - cairo_rectangle(buf->ct, 0.5 + area[X].min(), 0.5 + area[Y].min(), - area[X].max() - area[X].min(), area[Y].max() - area[Y].min()); - } else { - cairo_rectangle(buf->ct, -0.5 + area[X].min(), -0.5 + area[Y].min(), - area[X].max() - area[X].min(), area[Y].max() - area[Y].min()); - } - ink_cairo_set_source_rgba32(buf->ct, _shadow_color); - cairo_stroke(buf->ct); - } else if (_shadow_size > 1) { // fill the shadow + // Stroke rectangle. + cairo_stroke_preserve(buf->ct); + + // Highlight the border by drawing it in _shadow_color. + if (_shadow_width == 1 && _dashed) { ink_cairo_set_source_rgba32(buf->ct, _shadow_color); - cairo_rectangle(buf->ct, 1 + area[X].max(), area[Y].min() + _shadow_size, - _shadow_size, area[Y].max() - area[Y].min() + 1); // right shadow - cairo_rectangle(buf->ct, area[X].min() + _shadow_size, 1 + area[Y].max(), - area[X].max() - area[X].min() - _shadow_size + 1, _shadow_size); - cairo_fill(buf->ct); + cairo_set_dash(buf->ct, dashes, 2, 4); // Dash offset by dash length. + cairo_stroke_preserve(buf->ct); } + + cairo_new_path( buf->ct ); // Clear path or get wierd artifacts. cairo_restore(buf->ct); } } @@ -158,124 +226,33 @@ void CtrlRect::update(Geom::Affine const &affine, unsigned int flags) (SP_CANVAS_ITEM_CLASS(sp_ctrlrect_parent_class))->update(this, affine, flags); } - sp_canvas_item_reset_bounds(this); + // Note: There is no harm if 'area' is too large other than a possible small slow down in + // rendering speed. - Geom::Rect bbox(_rect.min() * affine, _rect.max() * affine); + // Calculate an axis-aligned bounding box that include all of transformed _rect. + Geom::Rect bbox = _rect; + bbox *= affine; - Geom::OptIntRect _area_old = _area; - Geom::IntRect area ( (int) floor(bbox.min()[Geom::X] + 0.5), - (int) floor(bbox.min()[Geom::Y] + 0.5), - (int) floor(bbox.max()[Geom::X] + 0.5), - (int) floor(bbox.max()[Geom::Y] + 0.5) ); - _area = area; - Geom::IntRect area_old(0,0,0,0); - if (_area_old) { // this weird construction is because the code below assumes _area_old to be 'valid' - area_old = *_area_old; - } + // Enlarge bbox by twice shadow size (to allow for shadow on any side with a 45deg rotation). + bbox.expandBy( 2.0 *_shadow_width ); - gint _shadow_size_old = _shadow_size; - _shadow_size = _shadow; - - // FIXME: we don't process a possible change in _has_fill - if (_has_fill) { - if (_area_old) { - canvas->requestRedraw(area_old[X].min() - 1, area_old[Y].min() - 1, - area_old[X].max() + _shadow_size + 1, area_old[Y].max() + _shadow_size + 1); - } - if (_area) { - canvas->requestRedraw(area[X].min() - 1, area[Y].min() - 1, - area[X].max() + _shadow_size + 1, area[Y].max() + _shadow_size + 1); - } - } else { // clear box, be smart about what part of the frame to redraw - - /* Top */ - if (area[Y].min() != area_old[Y].min()) { // different level, redraw fully old and new - if (area_old[X].min() != area_old[X].max()) - canvas->requestRedraw(area_old[X].min() - 1, area_old[Y].min() - 1, - area_old[X].max() + 1, area_old[Y].min() + 1); - - if (area[X].min() != area[X].max()) - canvas->requestRedraw(area[X].min() - 1, area[Y].min() - 1, - area[X].max() + 1, area[Y].min() + 1); - } else { // same level, redraw only the ends - if (area[X].min() != area_old[X].min()) { - canvas->requestRedraw(MIN(area_old[X].min(),area[X].min()) - 1, area[Y].min() - 1, - MAX(area_old[X].min(),area[X].min()) + 1, area[Y].min() + 1); - } - if (area[X].max() != area_old[X].max()) { - canvas->requestRedraw(MIN(area_old[X].max(),area[X].max()) - 1, area[Y].min() - 1, - MAX(area_old[X].max(),area[X].max()) + 1, area[Y].min() + 1); - } - } - - /* Left */ - if (area[X].min() != area_old[X].min()) { // different level, redraw fully old and new - if (area_old[Y].min() != area_old[Y].max()) - canvas->requestRedraw(area_old[X].min() - 1, area_old[Y].min() - 1, - area_old[X].min() + 1, area_old[Y].max() + 1); - - if (area[Y].min() != area[Y].max()) - canvas->requestRedraw(area[X].min() - 1, area[Y].min() - 1, - area[X].min() + 1, area[Y].max() + 1); - } else { // same level, redraw only the ends - if (area[Y].min() != area_old[Y].min()) { - canvas->requestRedraw(area[X].min() - 1, MIN(area_old[Y].min(),area[Y].min()) - 1, - area[X].min() + 1, MAX(area_old[Y].min(),area[Y].min()) + 1); - } - if (area[Y].max() != area_old[Y].max()) { - canvas->requestRedraw(area[X].min() - 1, MIN(area_old[Y].max(),area[Y].max()) - 1, - area[X].min() + 1, MAX(area_old[Y].max(),area[Y].max()) + 1); - } - } - - /* Right */ - if (area[X].max() != area_old[X].max() || _shadow_size_old != _shadow_size) { - if (area_old[Y].min() != area_old[Y].max()) - canvas->requestRedraw(area_old[X].max() - 1, area_old[Y].min() - 1, - area_old[X].max() + _shadow_size + 1, area_old[Y].max() + _shadow_size + 1); - - if (area[Y].min() != area[Y].max()) - canvas->requestRedraw(area[X].max() - 1, area[Y].min() - 1, - area[X].max() + _shadow_size + 1, area[Y].max() + _shadow_size + 1); - } else { // same level, redraw only the ends - if (area[Y].min() != area_old[Y].min()) { - canvas->requestRedraw(area[X].max() - 1, MIN(area_old[Y].min(),area[Y].min()) - 1, - area[X].max() + _shadow_size + 1, MAX(area_old[Y].min(),area[Y].min()) + _shadow_size + 1); - } - if (area[Y].max() != area_old[Y].max()) { - canvas->requestRedraw(area[X].max() - 1, MIN(area_old[Y].max(),area[Y].max()) - 1, - area[X].max() + _shadow_size + 1, MAX(area_old[Y].max(),area[Y].max()) + _shadow_size + 1); - } - } + // Generate an integer rectangle that includes bbox. + Geom::OptIntRect _area_old = _area; + _area = bbox.roundOutwards(); - /* Bottom */ - if (area[Y].max() != area_old[Y].max() || _shadow_size_old != _shadow_size) { - if (area_old[X].min() != area_old[X].max()) - canvas->requestRedraw(area_old[X].min() - 1, area_old[Y].max() - 1, - area_old[X].max() + _shadow_size + 1, area_old[Y].max() + _shadow_size + 1); - - if (area[X].min() != area[X].max()) - canvas->requestRedraw(area[X].min() - 1, area[Y].max() - 1, - area[X].max() + _shadow_size + 1, area[Y].max() + _shadow_size + 1); - } else { // same level, redraw only the ends - if (area[X].min() != area_old[X].min()) { - canvas->requestRedraw(MIN(area_old[X].min(),area[X].min()) - 1, area[Y].max() - 1, - MAX(area_old[X].min(),area[X].min()) + _shadow_size + 1, area[Y].max() + _shadow_size + 1); - } - if (area[X].max() != area_old[X].max()) { - canvas->requestRedraw(MIN(area_old[X].max(),area[X].max()) - 1, area[Y].max() - 1, - MAX(area_old[X].max(),area[X].max()) + _shadow_size + 1, area[Y].max() + _shadow_size + 1); - } - } - } + // std::cout << " _rect: " << _rect << std::endl; + // std::cout << " bbox: " << bbox << std::endl; + // std::cout << " area: " << *_area << std::endl; - // update SPCanvasItem box if (_area) { - x1 = area[X].min() - 1; - y1 = area[Y].min() - 1; - x2 = area[X].max() + _shadow_size + 1; - y2 = area[Y].max() + _shadow_size + 1; + Geom::IntRect area = *_area; + sp_canvas_update_bbox( this, area[X].min(), area[Y].min(), area[X].max(), area[Y].max() ); + } else { + std::cerr << "CtrlRect::update: No area!!" << std::endl; } + + // At rendering stage, we need to know affine: + _affine = affine; } @@ -289,7 +266,7 @@ void CtrlRect::setColor(guint32 b, bool h, guint f) void CtrlRect::setShadow(int s, guint c) { - _shadow = s; + _shadow_width = s; _shadow_color = c; _requestUpdate(); } diff --git a/src/display/sodipodi-ctrlrect.h b/src/display/sodipodi-ctrlrect.h index 08a085649..02fc85647 100644 --- a/src/display/sodipodi-ctrlrect.h +++ b/src/display/sodipodi-ctrlrect.h @@ -4,14 +4,17 @@ /** * @file * Simple non-transformed rectangle, usable for rubberband. + * Modified to work with rotated canvas. */ /* * Authors: * Lauris Kaplinski * Carl Hetherington + * Tavmjong Bah * * Copyright (C) 1999-2001 Lauris Kaplinski * Copyright (C) 2000-2001 Ximian, Inc. + * Copyright (C) 2017 Tavmjong Bah * * Released under GNU GPL * @@ -21,6 +24,7 @@ #include "sp-canvas-item.h" #include <2geom/rect.h> #include <2geom/int-rect.h> +#include <2geom/transforms.h> struct SPCanvasBuf; @@ -48,23 +52,24 @@ private: void _requestUpdate(); Geom::Rect _rect; + Geom::Affine _affine; + bool _has_fill; bool _dashed; bool _checkerboard; Geom::OptIntRect _area; - gint _shadow_size; + gint _shadow_width; guint32 _border_color; guint32 _fill_color; guint32 _shadow_color; - int _shadow; }; struct CtrlRectClass : public SPCanvasItemClass {}; GType sp_ctrlrect_get_type(); -#endif // SEEN_RUBBERBAND_H +#endif // SEEN_CTRLRECT_H /* Local Variables: -- cgit v1.2.3 From c73d9bc801357960ce8398040d27844de26465d7 Mon Sep 17 00:00:00 2001 From: Tavmjong Bah Date: Sat, 18 Mar 2017 17:14:06 +0100 Subject: Modify CanvasXYGrid to work with rotated canvas. (bzr r15602) --- src/display/canvas-grid.cpp | 249 ++++++++++++++++++++++++++------------------ src/display/canvas-grid.h | 2 +- 2 files changed, 147 insertions(+), 104 deletions(-) (limited to 'src/display') diff --git a/src/display/canvas-grid.cpp b/src/display/canvas-grid.cpp index 2dadde336..c8951525f 100644 --- a/src/display/canvas-grid.cpp +++ b/src/display/canvas-grid.cpp @@ -5,6 +5,7 @@ * Copyright (C) Lauris Kaplinski 2000 * Abhishek Sharma * Jon A. Cruz + * Copyright (C) Tavmong Bah 2017 */ /* As a general comment, I am not exactly proud of how things are done. @@ -841,21 +842,19 @@ void CanvasXYGrid::Update (Geom::Affine const &affine, unsigned int /*flags*/) { ow = origin * affine; - // Temp hack to insure grid doesn't collapse with rotation. - sw[0] = spacing[0] * sqrt(affine[0]*affine[0] + affine[1]*affine[1]); - sw[1] = spacing[1] * sqrt(affine[2]*affine[2] + affine[3]*affine[3]); - sw -= Geom::Point(affine[4], affine[5]); + sw[0] = Geom::Point(spacing[0], 0) * affine.withoutTranslation(); + sw[1] = Geom::Point(0, spacing[1]) * affine.withoutTranslation(); + // Find suitable grid spacing for display for(int dim = 0; dim < 2; dim++) { gint scaling_factor = empspacing; if (scaling_factor <= 1) scaling_factor = 5; - scaled[dim] = FALSE; - sw[dim] = fabs (sw[dim]); - while (sw[dim] < 8.0) { - scaled[dim] = TRUE; + scaled[dim] = false; + while (sw[dim].length() < 8.0) { + scaled[dim] = true; sw[dim] *= scaling_factor; /* First pass, go up to the major line spacing, then keep increasing by two. */ @@ -865,49 +864,45 @@ CanvasXYGrid::Update (Geom::Affine const &affine, unsigned int /*flags*/) } -static void -grid_hline (SPCanvasBuf *buf, gint y, gint xs, gint xe, guint32 rgba) -{ - if ((y < buf->rect.top()) || (y >= buf->rect.bottom())) - return; - - cairo_move_to(buf->ct, 0.5 + xs, 0.5 + y); - cairo_line_to(buf->ct, 0.5 + xe, 0.5 + y); - ink_cairo_set_source_rgba32(buf->ct, rgba); - cairo_stroke(buf->ct); -} - -static void -grid_vline (SPCanvasBuf *buf, gint x, gint ys, gint ye, guint32 rgba) +// Find intersections of line with rectangle. There should be zero or two. +// If line is degenerate with rectangle side, two corner points are returned. +static std::vector +intersect_line_rectangle( Geom::Line const &line, Geom::Rect const &rect ) { - if ((x < buf->rect.left()) || (x >= buf->rect.right())) - return; - - cairo_move_to(buf->ct, 0.5 + x, 0.5 + ys); - cairo_line_to(buf->ct, 0.5 + x, 0.5 + ye); - ink_cairo_set_source_rgba32(buf->ct, rgba); - cairo_stroke(buf->ct); + std::vector intersections; + for (unsigned i = 0; i < 4; ++i) { + Geom::LineSegment side( rect.corner(i), rect.corner((i+1)%4) ); + try { + Geom::OptCrossing oc = Geom::intersection(line, side); + if (oc) { + intersections.push_back( line.pointAt((*oc).ta)); + } + } catch (Geom::InfiniteSolutions) { + intersections.clear(); + intersections.push_back( side.pointAt(0) ); + intersections.push_back( side.pointAt(1) ); + return intersections; + } + } + return intersections; } -static void -grid_dot (SPCanvasBuf *buf, gint x, gint y, guint32 rgba) -{ - if ( (y < buf->rect.top()) || (y >= buf->rect.bottom()) - || (x < buf->rect.left()) || (x >= buf->rect.right()) ) - return; - - cairo_rectangle(buf->ct, x, y, 1, 1); - ink_cairo_set_source_rgba32(buf->ct, rgba); - cairo_fill(buf->ct); +// Find the signed distance of a point to a line. The distance is negative if +// the point lies to the left of the line considering the line's versor. +static double +signed_distance( Geom::Point const &point, Geom::Line const &line ) { + Geom::Coord t = line.nearestTime( point ); + Geom::Point p = line.pointAt(t); + double distance = Geom::distance( p, point ); + if ( Geom::cross( Geom::Line( p, point ).versor(), line.versor() ) < 0.0 ) { + distance = -distance; + } + return distance; } void CanvasXYGrid::Render (SPCanvasBuf *buf) { - gdouble const sxg = floor ((buf->rect.left() - ow[Geom::X]) / sw[Geom::X]) * sw[Geom::X] + ow[Geom::X]; - gint const xlinestart = round((sxg - ow[Geom::X]) / sw[Geom::X]); - gdouble const syg = floor ((buf->rect.top() - ow[Geom::Y]) / sw[Geom::Y]) * sw[Geom::Y] + ow[Geom::Y]; - gint const ylinestart = round((syg - ow[Geom::Y]) / sw[Geom::Y]); // no_emphasize_when_zoomedout determines color (minor or major) when only major grid lines/dots shown. Inkscape::Preferences *prefs = Inkscape::Preferences::get(); @@ -924,75 +919,123 @@ CanvasXYGrid::Render (SPCanvasBuf *buf) cairo_set_line_width(buf->ct, 1.0); cairo_set_line_cap(buf->ct, CAIRO_LINE_CAP_SQUARE); - if (!render_dotted) { - // Line grid - gint ylinenum; - gdouble y; - for (y = syg, ylinenum = ylinestart; y < buf->rect.bottom(); y += sw[Geom::Y], ylinenum++) { - gint const y0 = round(y); - if (!scaled[Geom::Y] && (ylinenum % empspacing) != 0) { - grid_hline (buf, y0, buf->rect.left(), buf->rect.right() - 1, color); - } else { - grid_hline (buf, y0, buf->rect.left(), buf->rect.right() - 1, _empcolor); - } - } + for (unsigned dim = 0; dim < 2; ++dim) { - gint xlinenum; - gdouble x; - for (x = sxg, xlinenum = xlinestart; x < buf->rect.right(); x += sw[Geom::X], xlinenum++) { - gint const ix = round(x); - if (!scaled[Geom::X] && (xlinenum % empspacing) != 0) { - grid_vline (buf, ix, buf->rect.top(), buf->rect.bottom(), color); - } else { - grid_vline (buf, ix, buf->rect.top(), buf->rect.bottom(), _empcolor); + // std::cout << "\n " << (dim==0?"Horizontal":"Vertical") << " ------------" << std::endl; + + // Construct an axis line through origin with direction normal to grid spacing. + Geom::Line axis = Geom::Line::from_origin_and_vector( ow, sw[dim] ); + Geom::Line orth = Geom::Line::from_origin_and_vector( ow, sw[(dim+1)%2] ); + + double spacing = fabs( sw[(dim+1)%2].length()); // Spacing between grid lines. + double dash = fabs( sw[dim].length()); // Total length of dash pattern. + + // std::cout << " axis: " << axis.origin() << ", " << axis.vector() << std::endl; + // std::cout << " spacing: " << spacing << std::endl; + // std::cout << " dash period: " << dash << std::endl; + + // Find the minimum and maximum distances of the buffer corners from axis. + double min = 1000000; + double max = -1000000; + for (unsigned c = 0; c < 4; ++c) { + + // We need signed distance... lib2geom offers only positive distance. + double distance = signed_distance( buf->rect.corner(c), axis ); + if (dim == 1 ) { // YFLIP? + distance = -distance; } + if (distance < min) + min = distance; + if (distance > max) + max = distance; } - } else { - // Dotted grid - gint ylinenum; - gdouble y; - - // alpha needs to be larger than in the line case to maintain a similar visual impact but - // setting it to the maximal value makes the dots dominant in some cases. Solution, - // increase the alpha by a factor of 4. This then allows some user adjustment. - guint32 _empdot = (_empcolor & 0xff) << 2; - if (_empdot > 0xff) - _empdot = 0xff; - _empdot += (_empcolor & 0xffffff00); - - guint32 _colordot = (color & 0xff) << 2; - if (_colordot > 0xff) - _colordot = 0xff; - _colordot += (color & 0xffffff00); - - for (y = syg, ylinenum = ylinestart; y < buf->rect.bottom(); y += sw[Geom::Y], ylinenum++) { - gint const iy = round(y); - - gint xlinenum; - gdouble x; - for (x = sxg, xlinenum = xlinestart; x < buf->rect.right(); x += sw[Geom::X], xlinenum++) { - gint const ix = round(x); - if ( (!scaled[Geom::X] && (xlinenum % empspacing) != 0) - || (!scaled[Geom::Y] && (ylinenum % empspacing) != 0) - || ((scaled[Geom::X] || scaled[Geom::Y]) && no_emp_when_zoomed_out) ) - { - // Minor point: dot only - grid_dot (buf, ix, iy, _colordot); // | (guint32)0x000000FF); // put alpha to max value + int start = floor( min/spacing ); + int stop = floor( max/spacing ); + + // std::cout << " rect: " << buf->rect << std::endl; + // std::cout << " min: " << min << " max: " << max << std::endl; + // std::cout << " start: " << start << " stop: " << stop << std::endl; + + // Loop over grid lines that intersected buf rectangle. + for (int j = start+1; j <= stop; ++j) { + + Geom::Line grid_line = Geom::make_parallel_line( ow + j * sw[(dim+1)%2], axis ); + + std::vector x = intersect_line_rectangle( grid_line, buf->rect ); + + // If we have two intersections, grid line intersects buffer rectangle. + if (x.size() == 2 ) { + + // Make sure lines are always drawn in the same direction (or dashes misplaced). + Geom::Line vector( x[0], x[1]); + if (Geom::dot( vector.vector(), axis.vector() ) < 0.0) { + std::swap(x[0], x[1]); + } + + // Set up line. + cairo_move_to(buf->ct, x[0][Geom::X] + 0.5, x[0][Geom::Y] + 0.5); + cairo_line_to(buf->ct, x[1][Geom::X] + 0.5, x[1][Geom::Y] + 0.5); + + // Set dash pattern and color. + if (render_dotted) { + + // alpha needs to be larger than in the line case to maintain a similar + // visual impact but setting it to the maximal value makes the dots + // dominant in some cases. Solution, increase the alpha by a factor of + // 4. This then allows some user adjustment. + guint32 _empdot = (_empcolor & 0xff) << 2; + if (_empdot > 0xff) + _empdot = 0xff; + _empdot += (_empcolor & 0xffffff00); + + guint32 _colordot = (color & 0xff) << 2; + if (_colordot > 0xff) + _colordot = 0xff; + _colordot += (color & 0xffffff00); + + // Dash pattern must use spacing from orthogonal direction. + // Offset is to center dash on orthogonal lines. + double offset = fmod( signed_distance( x[0], orth ), sw[dim].length()); + if (dim == 1) offset = -offset; + + double dashes[2]; + if (!scaled[dim] && (j % empspacing) != 0) { + // Minor lines + dashes[0] = 1; + dashes[1] = dash -1; + offset -= 0.5; + ink_cairo_set_source_rgba32(buf->ct, _colordot); + } else { + // Major lines + dashes[0] = 3; + dashes[1] = dash - 3; + offset -= 1.5; // Center dash on intersection. + ink_cairo_set_source_rgba32(buf->ct, _empdot); + } + + cairo_set_line_cap(buf->ct, CAIRO_LINE_CAP_BUTT); + cairo_set_dash(buf->ct, dashes, 2, -offset); + } else { - // Major point: small cross - gint const pitch = 1; - grid_dot (buf, ix-pitch, iy, _empcolor); - grid_dot (buf, ix+pitch, iy, _empcolor); - grid_dot (buf, ix, iy, _empdot ); // | (guint32)0x000000FF); // put alpha to max value + // Solid lines - grid_dot (buf, ix, iy-pitch, _empcolor); - grid_dot (buf, ix, iy+pitch, _empcolor); + // Set color + if (!scaled[dim] && (j % empspacing) != 0) { + ink_cairo_set_source_rgba32(buf->ct, color ); + } else { + ink_cairo_set_source_rgba32(buf->ct, _empcolor ); + } } - } + cairo_stroke(buf->ct); + + } else { + std::cerr << "CanvasXYGrid::render: Grid line doesn't intersect!" << std::endl; + } } } + cairo_restore(buf->ct); } @@ -1031,7 +1074,7 @@ CanvasXYGridSnapper::_getSnapLines(Geom::Point const &p) const if (getSnapVisibleOnly()) { // Only snapping to visible grid lines - spacing = grid->sw[i]; // this is the spacing of the visible grid lines measured in screen pixels + spacing = grid->sw[i].length(); // this is the spacing of the visible grid lines measured in screen pixels // convert screen pixels to px // FIXME: after we switch to snapping dist in screen pixels, this will be unnecessary SPDesktop const *dt = _snapmanager->getDesktop(); diff --git a/src/display/canvas-grid.h b/src/display/canvas-grid.h index bf520467a..91fa43e69 100644 --- a/src/display/canvas-grid.h +++ b/src/display/canvas-grid.h @@ -148,7 +148,7 @@ public: be different in the X or Y direction, hence two variables */ Geom::Point ow; /**< Transformed origin by the affine for the zoom */ - Geom::Point sw; /**< Transformed spacing by the affine for the zoom */ + Geom::Point sw[2]; /**< Transformed spacing by the affine for the zoom */ protected: virtual Gtk::Widget * newSpecificWidget(); -- cgit v1.2.3 From f47466c701b2256b2ce232f6d311d2be47136eab Mon Sep 17 00:00:00 2001 From: Tavmjong Bah Date: Mon, 20 Mar 2017 21:12:31 +0100 Subject: Implement rotation via desktop to window affine. Remove rotation via viewbox. Still some work to do... (bzr r15603) --- src/display/canvas-temporary-item-list.h | 1 - src/display/sp-canvas.cpp | 291 +------------------------------ src/display/sp-canvas.h | 5 +- 3 files changed, 2 insertions(+), 295 deletions(-) (limited to 'src/display') diff --git a/src/display/canvas-temporary-item-list.h b/src/display/canvas-temporary-item-list.h index 6b0e5796b..471bb99b9 100644 --- a/src/display/canvas-temporary-item-list.h +++ b/src/display/canvas-temporary-item-list.h @@ -14,7 +14,6 @@ struct SPCanvasItem; class SPDesktop; -class SPViewBox; namespace Inkscape { namespace Display { diff --git a/src/display/sp-canvas.cpp b/src/display/sp-canvas.cpp index 61602e880..f27038593 100644 --- a/src/display/sp-canvas.cpp +++ b/src/display/sp-canvas.cpp @@ -33,11 +33,6 @@ #include "display/sp-canvas-group.h" #include "display/rendermode.h" #include "display/cairo-utils.h" -#include "display/cairo-templates.h" -#include "display/drawing-context.h" -#include "display/drawing-item.h" -#include "display/nr-filter-colormatrix.h" -#include "display/canvas-arena.h" #include "preferences.h" #include "inkscape.h" #include "sodipodi-ctrlrect.h" @@ -45,8 +40,6 @@ #include "debug/gdk-event-latency-tracker.h" #include "desktop.h" #include "color.h" -#include -#include #if GTK_CHECK_VERSION(3,20,0) # include @@ -1924,19 +1917,6 @@ SPCanvasGroup *SPCanvas::getRoot() return SP_CANVAS_GROUP(_root); } -gdouble grayscale_value_matrix[20] = { - 0.21, 0.72, 0.072, 0, 0, - 0.21, 0.72, 0.072, 0, 0, - 0.21, 0.72, 0.072, 0, 0, - 0 , 0 , 0 , 1, 0 - }; -cairo_surface_t *surface_rotated; -cairo_surface_t *surface_origin; -cairo_surface_t *surface_measure; -double start_angle = 0; -bool started = false; -bool rotated = false; - /** * Scroll screen to point 'c'. 'c' is measured in screen pixels. */ @@ -1965,14 +1945,10 @@ void SPCanvas::scrollTo( Geom::Point const &c, unsigned int clear, bool is_scrol cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE); // Paint the background cairo_translate(cr, -ix, -iy); - if (rotated) { - cairo_translate(cr, dx, dy); - rotated = false; - } cairo_set_source(cr, _background); cairo_paint(cr); + // Copy the old backing store contents - cairo_set_source_surface(cr, _backing_store, _x0, _y0); cairo_rectangle(cr, _x0, _y0, allocation.width, allocation.height); cairo_clip(cr); @@ -2009,271 +1985,6 @@ void SPCanvas::scrollTo( Geom::Point const &c, unsigned int clear, bool is_scrol addIdle(); } -void SPCanvas::startRotateTo(double angle) -{ - if (!_backing_store || started) { - return; - } - start_angle = angle; - started = true; - GtkAllocation allocation; - gtk_widget_get_allocation(&_widget, &allocation); - int half_w = allocation.width/2; - int half_h = allocation.height/2; - int half_min = std::min(half_w,half_h); - - cairo_surface_t *new_backing_store = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, allocation.width, allocation.height); - cairo_t *cr = cairo_create(new_backing_store); - cairo_arc(cr, half_w, half_h, half_min-15, 0, 2*M_PI); - cairo_fill(cr); - cairo_set_operator(cr, CAIRO_OPERATOR_IN); - cairo_set_source_surface(cr, _backing_store, 0, 0); - cairo_paint(cr); - cairo_set_operator(cr, CAIRO_OPERATOR_OVER); - cairo_arc(cr, half_w, half_h, half_min-16, 0, 2*M_PI); - cairo_set_source_rgba (cr, 1, 1, 1, 0.5); - cairo_stroke(cr); - cairo_destroy(cr); - surface_rotated = new_backing_store; - - cairo_surface_t *new_backing_store_measure = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, allocation.width, allocation.height); - cr = cairo_create(new_backing_store_measure); - cairo_arc(cr, half_w, half_h, half_min-15, 0, 2*M_PI); - cairo_set_source_rgba (cr, 1, 1, 1, 0.2); - cairo_fill(cr); - cairo_translate(cr, half_w, half_h); - cairo_select_font_face(cr, "sans-serif", CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_NORMAL); - cairo_set_font_size(cr, 10.0); - for (gint x = 0; x < 360 ; x++){ - gint ang = 360 - x ;//+ 90; - if (ang > 180) { - ang -= 360; - } - double rot = (-180.0 + x)*(M_PI/180.); - double dist = half_min-9; - gint inverse = 1; - if((x) < 91 || (x) > 270) { - inverse = -1; - } - if(x%10 == 0) { - cairo_rotate(cr, -rot); - cairo_text_extents_t extents; - std::string s = std::to_string(ang) + "º"; - cairo_text_extents(cr, s.c_str(), &extents); - //std::cout << extents.width/2 << "extents.x_bearing\n"; - cairo_translate(cr, (extents.width/2) * inverse * -1, (dist + ((extents.height/2)* inverse))); - if((x) < 91 || (x) > 270) { - cairo_rotate(cr, 180*(M_PI/180.0)); - } - cairo_text_path(cr, s.c_str()); - if((x) < 91 || (x) > 270) { - cairo_rotate(cr, -180*(M_PI/180.0)); - } - cairo_translate(cr, (extents.width/2) * inverse , (dist + ((extents.height/2)* inverse)) * -1); - cairo_set_source_rgba (cr, 1, 1, 1, 1); - cairo_fill(cr); - cairo_rotate(cr, rot); - } - cairo_rotate(cr, x*(M_PI/180.)); - if(x%5 == 0) { - cairo_move_to(cr, 0, half_min-30); - cairo_line_to(cr, 0, half_min-17); - } else { - cairo_move_to(cr, 0, half_min-20); - cairo_line_to(cr, 0, half_min-15); - } - cairo_line_to(cr, 0, half_min-15); - cairo_set_source_rgba (cr, 0, 0, 0, 0.4); - cairo_set_line_width (cr,1); - cairo_stroke(cr); - cairo_rotate(cr, -x*(M_PI/180.)); - } - cairo_set_operator(cr, CAIRO_OPERATOR_CLEAR); - cairo_translate(cr, -half_w, -half_h); - cairo_arc(cr, half_w, half_h, half_min-30, 0, 2*M_PI); - cairo_set_source_rgba (cr, 1, 1, 1, 1); - cairo_fill(cr); - cairo_translate(cr, half_w, half_h); - cairo_set_operator(cr, CAIRO_OPERATOR_OVER); - cairo_rotate(cr, start_angle*(M_PI/180.)); - cairo_move_to(cr, 0, 0); - cairo_line_to(cr, 0, (half_min-17) * -1); - cairo_set_source_rgba (cr, 1, 1, 1, 0.25); - cairo_set_line_cap(cr, CAIRO_LINE_CAP_ROUND); - cairo_set_line_width (cr,5); - cairo_stroke(cr); - cairo_move_to(cr, 0, 0); - cairo_line_to(cr, 0, (half_min-17) * -1); - cairo_set_source_rgba (cr, 1, 0, 0, 0.9); - cairo_set_line_width (cr,1); - cairo_stroke(cr); - cairo_rotate(cr, -start_angle*(M_PI/180.)); - cairo_destroy(cr); - surface_measure = new_backing_store_measure; - - cairo_surface_t *new_backing_store_grey = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, allocation.width, allocation.height); - cr = cairo_create(new_backing_store_grey); - cairo_set_operator(cr, CAIRO_OPERATOR_OVER); - cairo_set_source_surface(cr, _backing_store, 0, 0); - cairo_paint(cr); - Inkscape::Filters::FilterColorMatrix::ColorMatrixMatrix _grayscale_colormatrix = std::vector (grayscale_value_matrix, grayscale_value_matrix + 20); - cairo_surface_t *out = ink_cairo_surface_create_identical(new_backing_store_grey); - ink_cairo_surface_filter(new_backing_store_grey, out, _grayscale_colormatrix); - cairo_set_source_surface(cr, out, 0, 0); - cairo_surface_destroy(out); - cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE); - cairo_paint(cr); - cairo_destroy(cr); - surface_origin = new_backing_store_grey; -} - -bool SPCanvas::endRotateTo() -{ - if (!_backing_store || !started) { - return false; - } - started = false; - surface_rotated = NULL; - surface_origin = NULL; - gtk_widget_queue_draw(GTK_WIDGET(this)); - dirtyAll(); - addIdle(); - rotated = true; - return true; -} - -void SPCanvas::clearRotateTo() -{ - if (!started) { - return; - } - gtk_widget_queue_draw(GTK_WIDGET(this)); - dirtyAll(); - addIdle(); -} - -void SPCanvas::rotateTo(double angle) -{ - if (!_backing_store || !started) { - return; - } - GtkAllocation allocation; - gtk_widget_get_allocation(&_widget, &allocation); - int half_w = allocation.width/2; - int half_h = allocation.height/2; - int half_min = std::min(half_w,half_h); - cairo_surface_t *new_backing_store = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, allocation.width, allocation.height); - cairo_t *cr = cairo_create(new_backing_store); - cairo_set_source_surface(cr, surface_origin, 0, 0); - cairo_paint(cr); - cairo_set_source_rgba (cr, 0, 0, 0, 0.5); - cairo_paint(cr); - cairo_pattern_t *source_pattern; - cairo_matrix_t matrix; - source_pattern = cairo_pattern_create_for_surface (surface_rotated); - cairo_matrix_init_identity (&matrix); - cairo_matrix_translate (&matrix, allocation.width/2.0, allocation.height/2.0); - cairo_matrix_rotate (&matrix, Geom::rad_from_deg(angle - start_angle) * -1); - cairo_matrix_translate (&matrix, -allocation.width/2.0, -allocation.height/2.0); - cairo_pattern_set_matrix (source_pattern, &matrix); - cairo_set_source(cr, source_pattern); - cairo_paint(cr); - cairo_set_source_surface(cr, surface_measure, 0, 0); - cairo_paint(cr); - cairo_translate(cr, half_w, half_h); - cairo_rotate(cr, angle*(M_PI/180.)); - cairo_move_to(cr, 0, 0); - cairo_line_to(cr, 0, (half_min-17) * -1); - cairo_set_source_rgba (cr, 1, 1, 1, 0.25); - cairo_set_line_cap(cr, CAIRO_LINE_CAP_ROUND); - cairo_set_line_width (cr,5); - cairo_stroke(cr); - cairo_move_to(cr, 0, 0); - cairo_line_to(cr, 0, (half_min-17) * -1); - cairo_set_source_rgba (cr, 1, 1, 1, 0.9); - cairo_set_line_width (cr,1); - cairo_stroke(cr); - cairo_move_to(cr, 0, 0); - cairo_line_to(cr, 0, (half_min-17) * -1); - cairo_set_source_rgba (cr, 1, 0, 0, 0.9); - const double dashed[] = {6.0, 3.0}; - int len = sizeof(dashed) / sizeof(dashed[0]); - cairo_set_dash(cr, dashed, len, 1); - cairo_stroke(cr); - cairo_translate(cr, -half_w, -half_h); - cairo_set_source_rgba (cr, 1, 1, 1, 0.25); - cairo_arc(cr, half_w, half_h, 7, 0, 2*M_PI); - cairo_fill(cr); - cairo_set_source_rgba (cr, 1, 0, 0, 0.7); - cairo_arc(cr, half_w, half_h, 5, 0, 2*M_PI); - cairo_fill(cr); - cairo_translate(cr, half_w, half_h); - cairo_rotate(cr, -angle*(M_PI/180.)); - cairo_select_font_face(cr, "sans-serif", CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_NORMAL); - cairo_set_font_size(cr, 15.0); - cairo_text_extents_t extents; - std::ostringstream s; - s << _("Original angle ") << std::fixed << std::setprecision(2) << start_angle << "º"; - cairo_text_extents(cr, s.str().c_str(), &extents); - cairo_translate(cr, half_w - extents.width -15 ,-half_h + 25); - cairo_set_source_rgba (cr, 1, 1, 1, 1); - cairo_text_path(cr, s.str().c_str()); - cairo_fill(cr); - cairo_translate(cr, (half_w - extents.width -15) *-1 ,(-half_h + 25) *-1); - s.str(""); - s << _("New angle ") << std::fixed << std::setprecision(2) << angle << "º"; - cairo_text_extents(cr, s.str().c_str(), &extents); - cairo_translate(cr, half_w - extents.width -15 ,-half_h + 45); - cairo_text_path(cr, s.str().c_str()); - cairo_fill(cr); - cairo_translate(cr, (half_w - extents.width -15) *-1 ,(-half_h + 45) *-1); - s.str(""); - s << _("Gap ") << std::fixed << std::setprecision(2) << std::abs(start_angle-angle) << "º"; - cairo_text_extents(cr, s.str().c_str(), &extents); - cairo_translate(cr, half_w - extents.width -15 ,-half_h + 65); - cairo_text_path(cr, s.str().c_str()); - cairo_fill(cr); - cairo_translate(cr, (half_w - extents.width -15) *-1 ,(-half_h + 65) *-1); - cairo_translate(cr, -half_w + 10 ,-half_h + 25); - s.str(""); - cairo_set_font_size(cr, 12.0); - s << _("Normal mode, 1º round step"); - cairo_text_path(cr, s.str().c_str()); - cairo_fill(cr); - cairo_translate(cr, (-half_w +10) * -1 ,(-half_h + 25) * -1); - cairo_translate(cr, -half_w + 10 ,-half_h + 40); - s.str(""); - s << _("+ALT, Fractional degrees"); - cairo_text_path(cr, s.str().c_str()); - cairo_fill(cr); - cairo_translate(cr, (-half_w + 10) * -1 ,(-half_h + 40) * -1); - cairo_translate(cr, -half_w + 10 ,-half_h + 55); - s.str(""); - Inkscape::Preferences *prefs = Inkscape::Preferences::get(); - s << _("+CTRL, ") << 180.0/prefs->getInt("/options/rotationsnapsperpi/value", 12) << _("º round step"); - cairo_text_path(cr, s.str().c_str()); - cairo_fill(cr); - cairo_translate(cr, (-half_w + 10) * -1 ,(-half_h + 55) * -1); - cairo_translate(cr, -half_w + 10 ,-half_h + 70); - s.str(""); - s << _("+SHIFT, Reset"); - cairo_text_path(cr, s.str().c_str()); - cairo_fill(cr); - cairo_translate(cr, (-half_w + 10) * -1 ,(-half_h + 70) * -1); - cairo_translate(cr, -half_w + 10 ,-half_h + 85); - s.str(""); - s << _("+CTRL+SHIFT, 0º"); - cairo_text_path(cr, s.str().c_str()); - cairo_fill(cr); - //cairo_translate(cr, (-half_w + 10) * -1 ,(-half_h + 60) * -1); - cairo_destroy(cr); - cairo_surface_destroy(_backing_store); - _backing_store = new_backing_store; - cairo_pattern_destroy (source_pattern); - gtk_widget_queue_draw(GTK_WIDGET(this)); - addIdle(); -} - void SPCanvas::updateNow() { if (_need_update) { diff --git a/src/display/sp-canvas.h b/src/display/sp-canvas.h index 708653bdf..b13477283 100644 --- a/src/display/sp-canvas.h +++ b/src/display/sp-canvas.h @@ -72,10 +72,7 @@ GType sp_canvas_get_type() G_GNUC_CONST; struct SPCanvas { /// Scrolls canvas to specific position (c is measured in screen pixels). void scrollTo(Geom::Point const &c, unsigned int clear, bool is_scrolling = false); - void startRotateTo(double angle); - void rotateTo(double angle); - bool endRotateTo(); - void clearRotateTo(); + /// Synchronously updates the canvas if necessary. void updateNow(); -- cgit v1.2.3 From a184a53752fb8027c22e4a5d68819fd7b78a15d8 Mon Sep 17 00:00:00 2001 From: Tavmjong Bah Date: Wed, 22 Mar 2017 20:03:41 +0100 Subject: Add canvas flip. No GUI. Can be bound to keys via preferences. (bzr r15606) --- src/display/canvas-grid.cpp | 15 ++++++++++----- src/display/sodipodi-ctrlrect.cpp | 3 ++- 2 files changed, 12 insertions(+), 6 deletions(-) (limited to 'src/display') diff --git a/src/display/canvas-grid.cpp b/src/display/canvas-grid.cpp index c8951525f..4243d3365 100644 --- a/src/display/canvas-grid.cpp +++ b/src/display/canvas-grid.cpp @@ -853,7 +853,7 @@ CanvasXYGrid::Update (Geom::Affine const &affine, unsigned int /*flags*/) scaling_factor = 5; scaled[dim] = false; - while (sw[dim].length() < 8.0) { + while (fabs(sw[dim].length()) < 8.0) { scaled[dim] = true; sw[dim] *= scaling_factor; /* First pass, go up to the major line spacing, then @@ -927,8 +927,8 @@ CanvasXYGrid::Render (SPCanvasBuf *buf) Geom::Line axis = Geom::Line::from_origin_and_vector( ow, sw[dim] ); Geom::Line orth = Geom::Line::from_origin_and_vector( ow, sw[(dim+1)%2] ); - double spacing = fabs( sw[(dim+1)%2].length()); // Spacing between grid lines. - double dash = fabs( sw[dim].length()); // Total length of dash pattern. + double spacing = sw[(dim+1)%2].length(); // Spacing between grid lines. + double dash = sw[dim].length(); // Total length of dash pattern. // std::cout << " axis: " << axis.origin() << ", " << axis.vector() << std::endl; // std::cout << " spacing: " << spacing << std::endl; @@ -941,9 +941,12 @@ CanvasXYGrid::Render (SPCanvasBuf *buf) // We need signed distance... lib2geom offers only positive distance. double distance = signed_distance( buf->rect.corner(c), axis ); - if (dim == 1 ) { // YFLIP? + + // Correct it for coordinate flips (inverts handedness). + if (Geom::cross( axis.vector(), orth.vector() ) > 0 ) { distance = -distance; } + if (distance < min) min = distance; if (distance > max) @@ -996,7 +999,9 @@ CanvasXYGrid::Render (SPCanvasBuf *buf) // Dash pattern must use spacing from orthogonal direction. // Offset is to center dash on orthogonal lines. double offset = fmod( signed_distance( x[0], orth ), sw[dim].length()); - if (dim == 1) offset = -offset; + if (Geom::cross( axis.vector(), orth.vector() ) > 0 ) { + offset = -offset; + } double dashes[2]; if (!scaled[dim] && (j % empspacing) != 0) { diff --git a/src/display/sodipodi-ctrlrect.cpp b/src/display/sodipodi-ctrlrect.cpp index b27a81ab3..075e04e6d 100644 --- a/src/display/sodipodi-ctrlrect.cpp +++ b/src/display/sodipodi-ctrlrect.cpp @@ -124,7 +124,8 @@ void CtrlRect::render(SPCanvasBuf *buf) if (_shadow_width > 0 && !_dashed) { // Offset by half stroke width (_shadow_width is in window coordinates). - Geom::Point shadow( _shadow_width/2.0, _shadow_width/2.0 ); + // Need to handle change in handedness with flips. + Geom::Point shadow( _shadow_width/2.0, (_affine.det()>0?-1:1)*_shadow_width/2.0 ); shadow *= Geom::Rotate( rotation ); if (axis_aligned) { -- cgit v1.2.3 From 3de63445fe736ca7c67cdce96426f6e5e3b8ebf4 Mon Sep 17 00:00:00 2001 From: Tavmjong Bah Date: Thu, 30 Mar 2017 11:41:29 +0200 Subject: Add canvas-rotate for rapid previewing canvas rotation. Add canvas-debug for study of canvas tiling. (bzr r15612) --- src/display/CMakeLists.txt | 4 + src/display/canvas-debug.cpp | 100 ++++++++++++ src/display/canvas-debug.h | 41 +++++ src/display/canvas-rotate.cpp | 288 +++++++++++++++++++++++++++++++++++ src/display/canvas-rotate.h | 50 ++++++ src/display/gnome-canvas-acetate.cpp | 8 + src/display/sp-canvas.cpp | 9 +- src/display/sp-canvas.h | 6 +- 8 files changed, 499 insertions(+), 7 deletions(-) create mode 100644 src/display/canvas-debug.cpp create mode 100644 src/display/canvas-debug.h create mode 100644 src/display/canvas-rotate.cpp create mode 100644 src/display/canvas-rotate.h (limited to 'src/display') diff --git a/src/display/CMakeLists.txt b/src/display/CMakeLists.txt index 0bf1d6e45..8eaaee99a 100644 --- a/src/display/CMakeLists.txt +++ b/src/display/CMakeLists.txt @@ -4,7 +4,9 @@ set(display_SRC canvas-arena.cpp canvas-axonomgrid.cpp canvas-bpath.cpp + canvas-debug.cpp canvas-grid.cpp + canvas-rotate.cpp canvas-temporary-item-list.cpp canvas-temporary-item.cpp canvas-text.cpp @@ -64,7 +66,9 @@ set(display_SRC canvas-arena.h canvas-axonomgrid.h canvas-bpath.h + canvas-debug.h canvas-grid.h + canvas-rotate.h canvas-temporary-item-list.h canvas-temporary-item.h canvas-text.h diff --git a/src/display/canvas-debug.cpp b/src/display/canvas-debug.cpp new file mode 100644 index 000000000..1748029e9 --- /dev/null +++ b/src/display/canvas-debug.cpp @@ -0,0 +1,100 @@ +/* + * A simple surface for debugging the canvas. Shows how tiles are drawn. + * + * Author: + * Tavmjong Bah + * + * Copyright (C) 2017 Tavmjong Bah + * + * Released under GNU GPL, read the file 'COPYING' for more information + */ + +#include "inkscape.h" +#include "desktop.h" + +#include "canvas-debug.h" +#include "sp-canvas.h" +#include "cairo-utils.h" +#include "ui/event-debug.h" + +namespace { + +static void sp_canvas_debug_destroy(SPCanvasItem *item); +static void sp_canvas_debug_update (SPCanvasItem *item, Geom::Affine const &affine, unsigned int flags); +static void sp_canvas_debug_render (SPCanvasItem *item, SPCanvasBuf *buf); +static int sp_canvas_debug_event (SPCanvasItem *item, GdkEvent *event); + +} // namespace + +G_DEFINE_TYPE(SPCanvasDebug, sp_canvas_debug, SP_TYPE_CANVAS_ITEM); + +static void sp_canvas_debug_class_init (SPCanvasDebugClass *klass) +{ + klass->destroy = sp_canvas_debug_destroy; + klass->update = sp_canvas_debug_update; + klass->render = sp_canvas_debug_render; + klass->event = sp_canvas_debug_event; +} + +static void sp_canvas_debug_init (SPCanvasDebug *debug) +{ + debug->pickable = true; // So we can receive events. +} + +namespace { +static void sp_canvas_debug_destroy (SPCanvasItem *object) +{ + g_return_if_fail (object != NULL); + g_return_if_fail (SP_IS_CANVAS_DEBUG (object)); + + if (SP_CANVAS_ITEM_CLASS(sp_canvas_debug_parent_class)->destroy) { + SP_CANVAS_ITEM_CLASS(sp_canvas_debug_parent_class)->destroy(object); + } +} + +static void sp_canvas_debug_update( SPCanvasItem *item, Geom::Affine const &/*affine*/, unsigned int /*flags*/ ) +{ + // We cover the entire canvas + item->x1 = -G_MAXINT; + item->y1 = -G_MAXINT; + item->x2 = G_MAXINT; + item->y2 = G_MAXINT; +} + +static void sp_canvas_debug_render( SPCanvasItem *item, SPCanvasBuf *buf) +{ + if (!buf->ct) { + return; + } + + cairo_set_line_width (buf->ct, 2); + + // Draw box around buffer (for debugging) + cairo_new_path (buf->ct); + cairo_move_to (buf->ct, 0, 0); + cairo_line_to (buf->ct, buf->rect.width(), 0); + cairo_line_to (buf->ct, buf->rect.width(), buf->rect.height()); + cairo_line_to (buf->ct, 0, buf->rect.height()); + cairo_close_path (buf->ct); + ink_cairo_set_source_rgba32 (buf->ct, 0xff7f7f7f); + cairo_stroke (buf->ct); +} + +static int sp_canvas_debug_event (SPCanvasItem *item, GdkEvent *event) +{ + ui_dump_event (event, Glib::ustring("sp_canvas_debug_event")); + return false; // We don't use any events... +} + +} // namespace + +/* + Local Variables: + mode:c++ + c-file-style:"stroustrup" + c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +)) + indent-tabs-mode:nil + fill-column:99 + End: +*/ +// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 : diff --git a/src/display/canvas-debug.h b/src/display/canvas-debug.h new file mode 100644 index 000000000..d5a166da9 --- /dev/null +++ b/src/display/canvas-debug.h @@ -0,0 +1,41 @@ +#ifndef SEEN_SP_CANVAS_DEBUG_H +#define SEEN_SP_CANVAS_DEBUG_H + +/* + * A simple surface for debugging the canvas. Shows how tiles are drawn. + * + * Author: + * Tavmjong Bah + * + * Copyright (C) 2017 Tavmjong Bah + * + * Released under GNU GPL, read the file 'COPYING' for more information + */ + +#include "sp-canvas-item.h" + +class SPItem; + +#define SP_TYPE_CANVAS_DEBUG (sp_canvas_debug_get_type ()) +#define SP_CANVAS_DEBUG(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), SP_TYPE_CANVAS_DEBUG, SPCanvasDebug)) +#define SP_IS_CANVAS_DEBUG(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), SP_TYPE_CANVAS_DEBUG)) + +struct SPCanvasDebug : public SPCanvasItem { +}; + +GType sp_canvas_debug_get_type (void); + +struct SPCanvasDebugClass : public SPCanvasItemClass{}; + +#endif // SEEN_SP_CANVAS_DEBUG_H + +/* + Local Variables: + mode:c++ + c-file-style:"stroustrup" + c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +)) + indent-tabs-mode:nil + fill-column:99 + End: +*/ +// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 : diff --git a/src/display/canvas-rotate.cpp b/src/display/canvas-rotate.cpp new file mode 100644 index 000000000..aaf6b962c --- /dev/null +++ b/src/display/canvas-rotate.cpp @@ -0,0 +1,288 @@ +/* + * Temporary surface for previewing rotated canvas. + * + * Author: + * Tavmjong Bah + * + * Copyright (C) 2017 Tavmjong Bah + * + * Released under GNU GPL, read the file 'COPYING' for more information + */ + +#include "inkscape.h" +#include "desktop.h" + +#include "canvas-rotate.h" +#include "sp-canvas.h" +#include "cairo-utils.h" +#include "ui/event-debug.h" + +#include "2geom/point.h" +#include "2geom/rect.h" + +#include + +namespace { + +static void sp_canvas_rotate_destroy(SPCanvasItem *item); +static void sp_canvas_rotate_update (SPCanvasItem *item, Geom::Affine const &affine, unsigned int flags); +static void sp_canvas_rotate_render (SPCanvasItem *item, SPCanvasBuf *buf); +static int sp_canvas_rotate_event (SPCanvasItem *item, GdkEvent *event); + +} // namespace + +void sp_canvas_rotate_paint (SPCanvasRotate *canvas_rotate, cairo_surface_t *background); + +G_DEFINE_TYPE(SPCanvasRotate, sp_canvas_rotate, SP_TYPE_CANVAS_ITEM); + +static void sp_canvas_rotate_class_init (SPCanvasRotateClass *klass) +{ + klass->destroy = sp_canvas_rotate_destroy; + //klass->update = sp_canvas_rotate_update; + //klass->render = sp_canvas_rotate_render; + klass->event = sp_canvas_rotate_event; +} + +static void sp_canvas_rotate_init (SPCanvasRotate *rotate) +{ + rotate->pickable = true; // So we can receive events. + rotate->angle = 0.0; + rotate->start_angle = -1000; + rotate->surface_copy = NULL; + rotate->surface_rotated = NULL; +} + +namespace { +static void sp_canvas_rotate_destroy (SPCanvasItem *object) +{ + g_return_if_fail (object != NULL); + g_return_if_fail (SP_IS_CANVAS_ROTATE (object)); + + if (SP_CANVAS_ITEM_CLASS(sp_canvas_rotate_parent_class)->destroy) { + SP_CANVAS_ITEM_CLASS(sp_canvas_rotate_parent_class)->destroy(object); + } +} + +// NOT USED... TOO SLOW +static void sp_canvas_rotate_update( SPCanvasItem *item, Geom::Affine const &/*affine*/, unsigned int /*flags*/ ) +{ + SPCanvasRotate *cr = SP_CANVAS_ROTATE(item); + + if (cr->surface_copy == NULL) { + // std::cout << "sp_canvas_rotate_update: surface_copy is NULL" << std::endl; + return; + } + + // Destroy surface_rotated if it already exists. + if (cr->surface_rotated != NULL) { + cairo_surface_destroy (cr->surface_rotated); + cr->surface_rotated = NULL; + } + + // Create rotated surface + cr->surface_rotated = ink_cairo_surface_create_identical(cr->surface_copy); + double width = cairo_image_surface_get_width (cr->surface_rotated); + double height = cairo_image_surface_get_height (cr->surface_rotated); + cairo_t *context = cairo_create( cr->surface_rotated ); + cairo_set_operator( context, CAIRO_OPERATOR_SOURCE ); + cairo_translate( context, width/2.0, height/2.0 ); + cairo_rotate( context, Geom::rad_from_deg(-cr->angle) ); + cairo_translate( context, -width/2.0, -height/2.0 ); + cairo_set_source_surface( context, cr->surface_copy, 0, 0 ); + cairo_paint( context ); + cairo_destroy( context); + + // We cover the entire canvas + item->x1 = -G_MAXINT; + item->y1 = -G_MAXINT; + item->x2 = G_MAXINT; + item->y2 = G_MAXINT; + + item->canvas->requestRedraw(item->x1, item->y1, item->x2, item->y2); +} + +// NOT USED... TOO SLOW +static void sp_canvas_rotate_render( SPCanvasItem *item, SPCanvasBuf *buf) +{ + // std::cout << "sp_canvas_rotate_render:" << std::endl; + // std::cout << " buf->rect: " << buf->rect << std::endl; + // std::cout << " buf->canvas_rect: " << buf->canvas_rect << std::endl; + SPCanvasRotate *cr = SP_CANVAS_ROTATE(item); + + if (!buf->ct) { + return; + } + + if (cr->surface_rotated == NULL ) { + // std::cout << " surface_rotated is NULL" << std::endl; + return; + } + + // Draw rotated canvas + cairo_save (buf->ct); + cairo_translate (buf->ct, + buf->canvas_rect.left() - buf->rect.left(), + buf->canvas_rect.top() - buf->rect.top() ); + cairo_set_operator (buf->ct, CAIRO_OPERATOR_SOURCE ); + cairo_set_source_surface (buf->ct, cr->surface_rotated, 0, 0 ); + cairo_paint (buf->ct); + cairo_restore (buf->ct); + + + // Draw line from center to cursor + cairo_save (buf->ct); + cairo_translate (buf->ct, -buf->rect.left(), -buf->rect.top()); + cairo_new_path (buf->ct); + cairo_move_to (buf->ct, cr->center[Geom::X], cr->center[Geom::Y]); + cairo_rel_line_to (buf->ct, cr->cursor[Geom::X], cr->cursor[Geom::Y]); + cairo_set_line_width (buf->ct, 2); + ink_cairo_set_source_rgba32 (buf->ct, 0xff00007f); + cairo_stroke (buf->ct); + cairo_restore (buf->ct); + +} + +static int sp_canvas_rotate_event (SPCanvasItem *item, GdkEvent *event) +{ + SPCanvasRotate *cr = SP_CANVAS_ROTATE(item); + +// ui_dump_event (event, Glib::ustring("sp_canvas_rotate_event")); + + SPDesktop *desktop = SP_ACTIVE_DESKTOP; + Geom::Rect viewbox = desktop->canvas->getViewbox(); // Not SVG viewbox! + cr->center = viewbox.midpoint(); + + switch (event->type) { + case GDK_MOTION_NOTIFY: + { + Geom::Point cursor( event->motion.x, event->motion.y ); + + // Both cursor and center are in window coordinates + Geom::Point rcursor( cursor - cr->center ); + double angle = Geom::deg_from_rad( Geom::atan2(rcursor) ); + + // Set start angle + if (cr->start_angle < -360) { + cr->start_angle = angle; + } + + double rotation_snap = 15; + + double delta_angle = cr->start_angle - angle; + + if (event->motion.state & GDK_SHIFT_MASK && + event->motion.state & GDK_CONTROL_MASK) { + delta_angle = 0; + } else if (event->motion.state & GDK_SHIFT_MASK) { + delta_angle = round(delta_angle/rotation_snap) * rotation_snap; + } else if (event->motion.state & GDK_CONTROL_MASK) { + // ? + } else if (event->motion.state & GDK_MOD1_MASK) { + // Decimal raw angle + } else { + delta_angle = floor(delta_angle); + } + + cr->angle = delta_angle; + + // Correct line for snapping of angle + double distance = rcursor.length(); + cr->cursor = Geom::Point::polar( Geom::rad_from_deg(angle), distance ); + + // Update screen + // sp_canvas_item_request_update( item ); + sp_canvas_rotate_paint (cr, cr->canvas->_backing_store); + break; + } + case GDK_BUTTON_RELEASE: + + // Rotate the actual canvas + desktop->rotate_relative_center_point (desktop->w2d(cr->center), + Geom::rad_from_deg(cr->angle) ); + + // We're done + sp_canvas_item_ungrab (item, event->button.time); + sp_canvas_item_hide (item); + + cr->start_angle = -1000; + if (cr->surface_copy != NULL) { + cairo_surface_destroy( cr->surface_copy ); + cr->surface_copy = NULL; + } + if (cr->surface_rotated != NULL) { + cairo_surface_destroy( cr->surface_rotated ); + cr->surface_rotated = NULL; + } + // sp_canvas_item_show (desktop->drawing); + + break; + case GDK_KEY_PRESS: + // std::cout << " Key press: " << std::endl; + break; + case GDK_KEY_RELEASE: + // std::cout << " Key release: " << std::endl; + break; + default: + // ui_dump_event (event, "sp_canvas_rotate_event: unwanted event: "); + break; + } + + if (event->type == GDK_KEY_PRESS) return false; + + return true; +} + +} // namespace + +void sp_canvas_rotate_start (SPCanvasRotate *canvas_rotate, cairo_surface_t *background) +{ + if (background == NULL) { + std::cerr << "sp_canvas_rotate_start: background is NULL!" << std::endl; + return; + } + + canvas_rotate->angle = 0.0; + + // Copy current background + canvas_rotate->surface_copy = ink_cairo_surface_copy( background ); + + // Paint canvas with background... since we are hiding drawing. + sp_canvas_item_request_update( canvas_rotate ); +} + +// Paint the canvas ourselves for speed.... +void sp_canvas_rotate_paint (SPCanvasRotate *canvas_rotate, cairo_surface_t *background) +{ + if (background == NULL) { + std::cerr << "sp_canvas_rotate_paint: background is NULL!" << std::endl; + return; + } + + double width = cairo_image_surface_get_width (background); + double height = cairo_image_surface_get_height (background); + + // Draw rotated canvas + cairo_t *context = cairo_create( background ); + + cairo_save (context); + cairo_set_operator( context, CAIRO_OPERATOR_SOURCE ); + cairo_translate( context, width/2.0, height/2.0 ); + cairo_rotate( context, Geom::rad_from_deg(-canvas_rotate->angle) ); + cairo_translate( context, -width/2.0, -height/2.0 ); + cairo_set_source_surface( context, canvas_rotate->surface_copy, 0, 0 ); + cairo_paint( context ); + cairo_restore( context ); + cairo_destroy( context ); + + gtk_widget_queue_draw (GTK_WIDGET (canvas_rotate->canvas)); +} +/* + Local Variables: + mode:c++ + c-file-style:"stroustrup" + c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +)) + indent-tabs-mode:nil + fill-column:99 + End: +*/ +// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 : diff --git a/src/display/canvas-rotate.h b/src/display/canvas-rotate.h new file mode 100644 index 000000000..8620dcced --- /dev/null +++ b/src/display/canvas-rotate.h @@ -0,0 +1,50 @@ +#ifndef SEEN_SP_CANVAS_ROTATE_H +#define SEEN_SP_CANVAS_ROTATE_H + +/* + * Temporary surface for previewing rotated canvas. + * + * Author: + * Tavmjong Bah + * + * Copyright (C) 2017 Tavmjong Bah + * + * Released under GNU GPL, read the file 'COPYING' for more information + */ + +#include "sp-canvas-item.h" +#include "2geom/line.h" + +class SPItem; + +#define SP_TYPE_CANVAS_ROTATE (sp_canvas_rotate_get_type ()) +#define SP_CANVAS_ROTATE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), SP_TYPE_CANVAS_ROTATE, SPCanvasRotate)) +#define SP_IS_CANVAS_ROTATE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), SP_TYPE_CANVAS_ROTATE)) + +struct SPCanvasRotate : public SPCanvasItem { + Geom::Point center; // Center of screen + Geom::Point cursor; // Position of cursor relative to center (after angle snapping) + double angle; // Rotation angle in degrees + double start_angle; // Starting angle of cursor + cairo_surface_t *surface_copy; // Copy of original surface + cairo_surface_t *surface_rotated; // Copy of original surface, rotated +}; + +void sp_canvas_rotate_start( SPCanvasRotate *canvas_rotate, cairo_surface_t *background ); + +GType sp_canvas_rotate_get_type (void); + +struct SPCanvasRotateClass : public SPCanvasItemClass{}; + +#endif // SEEN_SP_CANVAS_ROTATE_H + +/* + Local Variables: + mode:c++ + c-file-style:"stroustrup" + c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +)) + indent-tabs-mode:nil + fill-column:99 + End: +*/ +// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 : diff --git a/src/display/gnome-canvas-acetate.cpp b/src/display/gnome-canvas-acetate.cpp index 9147a1bbf..297d69068 100644 --- a/src/display/gnome-canvas-acetate.cpp +++ b/src/display/gnome-canvas-acetate.cpp @@ -14,11 +14,13 @@ */ #include "gnome-canvas-acetate.h" +#include "ui/event-debug.h" static void sp_canvas_acetate_destroy(SPCanvasItem *object); static void sp_canvas_acetate_update (SPCanvasItem *item, Geom::Affine const &affine, unsigned int flags); static double sp_canvas_acetate_point (SPCanvasItem *item, Geom::Point p, SPCanvasItem **actual_item); +static int sp_canvas_acetate_event( SPCanvasItem *item, GdkEvent *event); G_DEFINE_TYPE(SPCanvasAcetate, sp_canvas_acetate, SP_TYPE_CANVAS_ITEM); @@ -29,6 +31,7 @@ static void sp_canvas_acetate_class_init (SPCanvasAcetateClass *klass) item_class->destroy = sp_canvas_acetate_destroy; item_class->update = sp_canvas_acetate_update; item_class->point = sp_canvas_acetate_point; + // item_class->event = sp_canvas_acetate_event; } static void sp_canvas_acetate_init (SPCanvasAcetate */*acetate*/) @@ -60,3 +63,8 @@ static double sp_canvas_acetate_point( SPCanvasItem *item, Geom::Point /*p*/, SP return 0.0; } +// static int sp_canvas_acetate_event( SPCanvasItem *item, GdkEvent *event) +// { +// ui_dump_event (event, "sp_canvas_acetate_event"); +// return 0; // ? +// } diff --git a/src/display/sp-canvas.cpp b/src/display/sp-canvas.cpp index f27038593..74aa4807a 100644 --- a/src/display/sp-canvas.cpp +++ b/src/display/sp-canvas.cpp @@ -1507,7 +1507,7 @@ void SPCanvas::paintSingleBuffer(Geom::IntRect const &paint_rect, Geom::IntRect buf.buf = NULL; buf.buf_rowstride = 0; buf.rect = paint_rect; - buf.visible_rect = canvas_rect; + buf.canvas_rect = canvas_rect; buf.is_empty = true; // create temporary surface @@ -1571,7 +1571,7 @@ void SPCanvas::paintSingleBuffer(Geom::IntRect const &paint_rect, Geom::IntRect } struct PaintRectSetup { - Geom::IntRect big_rect; + Geom::IntRect canvas_rect; GTimeVal start_time; int max_pixels; Geom::Point mouse_loc; @@ -1630,7 +1630,7 @@ int SPCanvas::paintRectInternal(PaintRectSetup const *setup, Geom::IntRect const gdk_window_begin_paint_rect(window, &r); */ - paintSingleBuffer(this_rect, setup->big_rect, bw); + paintSingleBuffer(this_rect, setup->canvas_rect, bw); //gdk_window_end_paint(window); return 1; } @@ -1695,6 +1695,7 @@ bool SPCanvas::paintRect(int xx0, int yy0, int xx1, int yy1) gtk_widget_get_allocation(GTK_WIDGET(this), &allocation); + // Find window rectangle in 'world coordinates'. Geom::IntRect canvas_rect = Geom::IntRect::from_xywh(_x0, _y0, allocation.width, allocation.height); Geom::IntRect paint_rect(xx0, yy0, xx1, yy1); @@ -1705,7 +1706,7 @@ bool SPCanvas::paintRect(int xx0, int yy0, int xx1, int yy1) paint_rect = *area; PaintRectSetup setup; - setup.big_rect = paint_rect; + setup.canvas_rect = canvas_rect; // Save the mouse location gint x, y; diff --git a/src/display/sp-canvas.h b/src/display/sp-canvas.h index b13477283..a2cbe0b27 100644 --- a/src/display/sp-canvas.h +++ b/src/display/sp-canvas.h @@ -51,7 +51,7 @@ enum { struct SPCanvasBuf { cairo_t *ct; Geom::IntRect rect; - Geom::IntRect visible_rect; + Geom::IntRect canvas_rect; // visible window in world coordinates (i.e. offset by _x0, _y0) unsigned char *buf; int buf_rowstride; @@ -174,8 +174,8 @@ public: bool _is_dragging; double _dx0; double _dy0; - int _x0; ///< World coordinate of the leftmost pixels - int _y0; ///< World coordinate of the topmost pixels + int _x0; ///< World coordinate of the leftmost pixels of window + int _y0; ///< World coordinate of the topmost pixels of window /// Image surface storing the contents of the widget cairo_surface_t *_backing_store; -- cgit v1.2.3 From f27f16912ec71d7567c71891badb6adb543411e9 Mon Sep 17 00:00:00 2001 From: Tavmjong Bah Date: Thu, 30 Mar 2017 21:14:41 +0200 Subject: Add preference that allows user to increase the canvas tile size. A larger tile size vastly speeds up rendering for drawings with heavy filter use by reducing the need to recalculate filter effects that cross multiple tiles. (bzr r15614) --- src/display/sp-canvas.cpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'src/display') diff --git a/src/display/sp-canvas.cpp b/src/display/sp-canvas.cpp index 74aa4807a..d04c81ecb 100644 --- a/src/display/sp-canvas.cpp +++ b/src/display/sp-canvas.cpp @@ -1727,10 +1727,16 @@ bool SPCanvas::paintRect(int xx0, int yy0, int xx1, int yy1) setup.mouse_loc = sp_canvas_window_to_world(this, Geom::Point(x,y)); + static unsigned tile_multiplier = 0; + if (tile_multiplier == 0) { + Inkscape::Preferences *prefs = Inkscape::Preferences::get(); + tile_multiplier = prefs->getIntLimited("/options/rendering/tile-multiplier", 1, 1, 64); + } + if (_rendermode != Inkscape::RENDERMODE_OUTLINE) { // use 256K as a compromise to not slow down gradients // 256K is the cached buffer and we need 4 channels - setup.max_pixels = 65536; // 256K/4 + setup.max_pixels = 65536 * tile_multiplier; // 256K/4 } else { // paths only, so 1M works faster // 1M is the cached buffer and we need 4 channels -- cgit v1.2.3 From c3a191e4275ade05cf4bb4aab045ee22d050e703 Mon Sep 17 00:00:00 2001 From: Tavmjong Bah Date: Mon, 29 May 2017 15:09:06 +0200 Subject: Update for CSS 3 'image-rendering'. (bzr r15714) --- src/display/drawing-image.cpp | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) (limited to 'src/display') diff --git a/src/display/drawing-image.cpp b/src/display/drawing-image.cpp index e23c89c59..508fcc503 100644 --- a/src/display/drawing-image.cpp +++ b/src/display/drawing-image.cpp @@ -116,16 +116,22 @@ unsigned DrawingImage::_renderItem(DrawingContext &dc, Geom::IntRect const &/*ar if (_style) { // See: http://www.w3.org/TR/SVG/painting.html#ImageRenderingProperty // http://www.w3.org/TR/css4-images/#the-image-rendering + // It's back in CSS Images 3 now. // style.h/style.cpp switch (_style->image_rendering.computed) { case SP_CSS_IMAGE_RENDERING_AUTO: - // Do nothing - break; case SP_CSS_IMAGE_RENDERING_OPTIMIZEQUALITY: + case SP_CSS_IMAGE_RENDERING_CRISPEDGES: + // CSS 3 defines: + // 'auto' to use smoothing + // 'optimize-quality' as alias for auto + // We don't have special rendering for 'crisp-edges' yet + // so follow what browsers do. // In recent Cairo, BEST used Lanczos3, which is prohibitively slow dc.patternSetFilter( CAIRO_FILTER_GOOD ); break; case SP_CSS_IMAGE_RENDERING_OPTIMIZESPEED: + case SP_CSS_IMAGE_RENDERING_PIXELATED: default: dc.patternSetFilter( CAIRO_FILTER_NEAREST ); break; -- cgit v1.2.3