summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorJohan B. C. Engelen <jbc.engelen@swissonline.ch>2011-07-18 20:44:25 +0000
committerJohan Engelen <goejendaagh@zonnet.nl>2011-07-18 20:44:25 +0000
commit61ec015d8734244ecd6223e941ecc09eccdfcdaa (patch)
treef1327ce92272cf6dfa86c59f9bd8794002b1edf9 /src
parentfix hardcoded desktop2doc transform (diff)
downloadinkscape-61ec015d8734244ecd6223e941ecc09eccdfcdaa.tar.gz
inkscape-61ec015d8734244ecd6223e941ecc09eccdfcdaa.zip
refactor the guideline drawing. now it obeys desktop transforms a lot better.
(bzr r10471)
Diffstat (limited to 'src')
-rw-r--r--src/display/guideline.cpp56
-rw-r--r--src/display/guideline.h2
-rw-r--r--src/sp-guide.cpp26
3 files changed, 56 insertions, 28 deletions
diff --git a/src/display/guideline.cpp b/src/display/guideline.cpp
index c1c3e7740..0d2905d23 100644
--- a/src/display/guideline.cpp
+++ b/src/display/guideline.cpp
@@ -13,12 +13,17 @@
* Released under GNU GPL, read the file 'COPYING' for more information
*/
+#include <2geom/coord.h>
#include <2geom/transforms.h>
#include "sp-canvas-util.h"
#include "sp-ctrlpoint.h"
#include "guideline.h"
#include "display/cairo-utils.h"
+#include "inkscape.h" // for inkscape_active_desktop()
+#include "desktop.h"
+#include "sp-namedview.h"
+
static void sp_guideline_class_init(SPGuideLineClass *c);
static void sp_guideline_init(SPGuideLine *guideline);
static void sp_guideline_destroy(GtkObject *object);
@@ -112,45 +117,46 @@ 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);
- int px = round(gl->point_on_line[Geom::X]);
- int py = round(gl->point_on_line[Geom::Y]);
+ 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;
if (gl->label) {
+ int px = round(point_on_line_dt[Geom::X]);
+ int py = round(point_on_line_dt[Geom::Y]);
cairo_save(buf->ct);
cairo_translate(buf->ct, px, py);
- cairo_rotate(buf->ct, atan2(gl->normal_to_line[Geom::X], gl->normal_to_line[Geom::Y]));
+ cairo_rotate(buf->ct, atan2(normal_dt.cw()));
cairo_translate(buf->ct, 0, -5);
cairo_move_to(buf->ct, 0, 0);
cairo_show_text(buf->ct, gl->label);
cairo_restore(buf->ct);
}
- if (gl->is_vertical()) {
- int position = round(gl->point_on_line[Geom::X]);
+ if ( Geom::are_near(normal_dt[Geom::Y], 0.) ) { // is vertical?
+ int position = round(point_on_line_dt[Geom::X]);
cairo_move_to(buf->ct, position + 0.5, buf->rect.y0 + 0.5);
cairo_line_to(buf->ct, position + 0.5, buf->rect.y1 - 0.5);
cairo_stroke(buf->ct);
- } else if (gl->is_horizontal()) {
- int position = round(gl->point_on_line[Geom::Y]);
+ } else if ( Geom::are_near(normal_dt[Geom::X], 0.) ) { // is horizontal?
+ int position = round(point_on_line_dt[Geom::Y]);
cairo_move_to(buf->ct, buf->rect.x0 + 0.5, position + 0.5);
cairo_line_to(buf->ct, buf->rect.x1 - 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( gl->normal_to_line[Geom::Y],
- /*should be minus, but inverted y axis*/ gl->normal_to_line[Geom::X]);
+ // 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.x0 - gl->point_on_line[Geom::X]) * parallel_to_line[Geom::Y] / parallel_to_line[Geom::X] + gl->point_on_line[Geom::Y];
+ double y_intersect_left = (buf->rect.x0 - 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.y0) && (y_intersect_left <= buf->rect.y1) ) {
// intersects with left vertical!
- double y_intersect_right = (buf->rect.x1 - gl->point_on_line[Geom::X]) * parallel_to_line[Geom::Y] / parallel_to_line[Geom::X] + gl->point_on_line[Geom::Y];
+ double y_intersect_right = (buf->rect.x1 - 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.x0, static_cast<gint>(round(y_intersect_left)), buf->rect.x1, static_cast<gint>(round(y_intersect_right)), gl->rgba);
goto end;
}
//try to intersect with right vertical of rect
- double y_intersect_right = (buf->rect.x1 - gl->point_on_line[Geom::X]) * parallel_to_line[Geom::Y] / parallel_to_line[Geom::X] + gl->point_on_line[Geom::Y];
+ double y_intersect_right = (buf->rect.x1 - 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.y0) && (y_intersect_right <= buf->rect.y1) ) {
// intersects with right vertical!
sp_guideline_drawline (buf, buf->rect.x1, static_cast<gint>(round(y_intersect_right)), buf->rect.x0, static_cast<gint>(round(y_intersect_left)), gl->rgba);
@@ -158,16 +164,16 @@ static void sp_guideline_render(SPCanvasItem *item, SPCanvasBuf *buf)
}
//try to intersect with top horizontal of rect
- double x_intersect_top = (buf->rect.y0 - gl->point_on_line[Geom::Y]) * parallel_to_line[Geom::X] / parallel_to_line[Geom::Y] + gl->point_on_line[Geom::X];
+ double x_intersect_top = (buf->rect.y0 - 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.x0) && (x_intersect_top <= buf->rect.x1) ) {
// intersects with top horizontal!
- double x_intersect_bottom = (buf->rect.y1 - gl->point_on_line[Geom::Y]) * parallel_to_line[Geom::X] / parallel_to_line[Geom::Y] + gl->point_on_line[Geom::X];
+ double x_intersect_bottom = (buf->rect.y1 - 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<gint>(round(x_intersect_top)), buf->rect.y0, static_cast<gint>(round(x_intersect_bottom)), buf->rect.y1, gl->rgba);
goto end;
}
//try to intersect with bottom horizontal of rect
- double x_intersect_bottom = (buf->rect.y1 - gl->point_on_line[Geom::Y]) * parallel_to_line[Geom::X] / parallel_to_line[Geom::Y] + gl->point_on_line[Geom::X];
+ double x_intersect_bottom = (buf->rect.y1 - 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.x0) && (x_intersect_top <= buf->rect.x1) ) {
// intersects with bottom horizontal!
sp_guideline_drawline (buf, static_cast<gint>(round(x_intersect_bottom)), buf->rect.y1, static_cast<gint>(round(x_intersect_top)), buf->rect.y0, gl->rgba);
@@ -186,16 +192,16 @@ static void sp_guideline_update(SPCanvasItem *item, Geom::Affine const &affine,
((SPCanvasItemClass *) parent_class)->update(item, affine, flags);
}
- gl->point_on_line[Geom::X] = affine[4];
- gl->point_on_line[Geom::Y] = affine[5];
+ gl->affine = affine;
- sp_ctrlpoint_set_coords(gl->origin, gl->point_on_line * affine.inverse());
+ sp_ctrlpoint_set_coords(gl->origin, gl->point_on_line);
sp_canvas_item_request_update(SP_CANVAS_ITEM (gl->origin));
+ Geom::Point pol_transformed = gl->point_on_line*affine;
if (gl->is_horizontal()) {
- sp_canvas_update_bbox (item, -1000000, round(gl->point_on_line[Geom::Y] - 16), 1000000, round(gl->point_on_line[Geom::Y] + 1));
+ 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(gl->point_on_line[Geom::X]), -1000000, round(gl->point_on_line[Geom::X] + 16), 1000000);
+ 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);
@@ -213,8 +219,8 @@ static double sp_guideline_point(SPCanvasItem *item, Geom::Point p, SPCanvasItem
*actual_item = item;
- Geom::Point vec(gl->normal_to_line[Geom::X], - gl->normal_to_line[Geom::Y]);
- double distance = Geom::dot((p - gl->point_on_line), vec);
+ Geom::Point vec = gl->normal_to_line * gl->affine.withoutTranslation();
+ double distance = Geom::dot((p - gl->point_on_line * gl->affine), unit_vector(vec));
return MAX(fabs(distance)-1, 0);
}
@@ -250,8 +256,8 @@ void sp_guideline_set_label(SPGuideLine *gl, const char* label)
void sp_guideline_set_position(SPGuideLine *gl, Geom::Point point_on_line)
{
- sp_canvas_item_affine_absolute(SP_CANVAS_ITEM (gl), Geom::Affine(Geom::Translate(point_on_line)));
- sp_canvas_item_affine_absolute(SP_CANVAS_ITEM (gl->origin), Geom::Affine(Geom::Translate(point_on_line)));
+ gl->point_on_line = point_on_line;
+ sp_canvas_item_request_update(SP_CANVAS_ITEM (gl));
}
void sp_guideline_set_normal(SPGuideLine *gl, Geom::Point normal_to_line)
diff --git a/src/display/guideline.h b/src/display/guideline.h
index a3966f76f..164244c46 100644
--- a/src/display/guideline.h
+++ b/src/display/guideline.h
@@ -25,6 +25,8 @@ class SPCtrlPoint;
struct SPGuideLine {
SPCanvasItem item;
+ Geom::Affine affine;
+
SPCtrlPoint *origin; // unlike 'item', this is only held locally
guint32 rgba;
diff --git a/src/sp-guide.cpp b/src/sp-guide.cpp
index f71bc1762..71312b698 100644
--- a/src/sp-guide.cpp
+++ b/src/sp-guide.cpp
@@ -40,6 +40,7 @@
#include "desktop.h"
#include "sp-namedview.h"
#include <2geom/angle.h>
+#include <2geom/transforms.h>
#include "document.h"
using Inkscape::DocumentUndo;
@@ -321,7 +322,14 @@ sp_guide_delete_all_guides(SPDesktop *dt) {
void SPGuide::showSPGuide(SPCanvasGroup *group, GCallback handler)
{
- SPCanvasItem *item = sp_guideline_new(group, label, point_on_line, normal_to_line);
+ // historically, normal_to_line and point_on_line are stored in desktop coordinates (without desktop rotation)
+ // therefore, we have to correct for this first...
+ SPDesktop const *desktop = inkscape_active_desktop(); /// @fixme Obtain SPDesktop in better way...
+ Geom::Affine correction = Geom::Translate(0, -desktop->namedview->document->getHeight()) * Geom::Scale(1, -1);
+ Geom::Point normal_dt = normal_to_line * correction.withoutTranslation() * desktop->doc2dt().withoutTranslation();
+ Geom::Point point_on_line_dt = point_on_line * correction * desktop->doc2dt();
+
+ SPCanvasItem *item = sp_guideline_new(group, label, point_on_line_dt, normal_dt);
sp_guideline_set_color(SP_GUIDELINE(item), color);
g_signal_connect(G_OBJECT(item), "event", G_CALLBACK(handler), this);
@@ -379,8 +387,14 @@ void sp_guide_moveto(SPGuide &guide, Geom::Point const point_on_line, bool const
{
g_assert(SP_IS_GUIDE(&guide));
+ // historically, normal_to_line and point_on_line are stored in desktop coordinates (without desktop rotation)
+ // therefore, we have to correct for this first...
+ SPDesktop const *desktop = inkscape_active_desktop(); /// @fixme Obtain SPDesktop in better way...
+ Geom::Affine correction = Geom::Translate(0, -desktop->namedview->document->getHeight()) * Geom::Scale(1, -1);
+ Geom::Point point_on_line_dt = point_on_line * correction * desktop->doc2dt();
+
for (GSList *l = guide.views; l != NULL; l = l->next) {
- sp_guideline_set_position(SP_GUIDELINE(l->data), point_on_line);
+ sp_guideline_set_position(SP_GUIDELINE(l->data), point_on_line_dt);
}
/* Calling sp_repr_set_point must precede calling sp_item_notify_moveto in the commit
@@ -410,8 +424,14 @@ void sp_guide_set_normal(SPGuide &guide, Geom::Point const normal_to_line, bool
{
g_assert(SP_IS_GUIDE(&guide));
+ // historically, normal_to_line and point_on_line are stored in desktop coordinates (without desktop rotation)
+ // therefore, we have to correct for this first...
+ SPDesktop const *desktop = inkscape_active_desktop(); /// @fixme Obtain SPDesktop in better way...
+ Geom::Affine correction = Geom::Translate(0, -desktop->namedview->document->getHeight()) * Geom::Scale(1, -1);
+ Geom::Point normal_dt = normal_to_line * correction.withoutTranslation() * desktop->doc2dt().withoutTranslation();
+
for (GSList *l = guide.views; l != NULL; l = l->next) {
- sp_guideline_set_normal(SP_GUIDELINE(l->data), normal_to_line);
+ sp_guideline_set_normal(SP_GUIDELINE(l->data), normal_dt);
}
/* Calling sp_repr_set_svg_point must precede calling sp_item_notify_moveto in the commit