summaryrefslogtreecommitdiffstats
path: root/src/display/guideline.cpp
diff options
context:
space:
mode:
authorAndrew Higginson <at.higginson@gmail.com>2011-12-27 21:04:47 +0000
committerAndrew <at.higginson@gmail.com>2011-12-27 21:04:47 +0000
commit80960b623a99aae1402ab651b2974ef544ed3b03 (patch)
treeba49d42c2789e9e11f805e2d5263e10f9fedeef8 /src/display/guideline.cpp
parenttry to fix bug (diff)
parentGDL: Cherry-pick upstream patch 73852 (2011-03-23) - Add missing return value. (diff)
downloadinkscape-80960b623a99aae1402ab651b2974ef544ed3b03.tar.gz
inkscape-80960b623a99aae1402ab651b2974ef544ed3b03.zip
merged with trunk so I can build again...
(bzr r10092.1.36)
Diffstat (limited to 'src/display/guideline.cpp')
-rw-r--r--src/display/guideline.cpp239
1 files changed, 91 insertions, 148 deletions
diff --git a/src/display/guideline.cpp b/src/display/guideline.cpp
index bebec2852..f2802c6fe 100644
--- a/src/display/guideline.cpp
+++ b/src/display/guideline.cpp
@@ -13,12 +13,16 @@
* Released under GNU GPL, read the file 'COPYING' for more information
*/
-
-#include <libnr/nr-pixops.h>
+#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);
@@ -78,6 +82,7 @@ static void sp_guideline_init(SPGuideLine *gl)
gl->sensitive = 0;
gl->origin = NULL;
+ gl->label = NULL;
}
static void sp_guideline_destroy(GtkObject *object)
@@ -99,88 +104,84 @@ static void sp_guideline_destroy(GtkObject *object)
static void sp_guideline_render(SPCanvasItem *item, SPCanvasBuf *buf)
{
- SPGuideLine const *gl = SP_GUIDELINE (item);
-
- sp_canvas_prepare_buffer(buf);
-
- unsigned int const r = NR_RGBA32_R (gl->rgba);
- unsigned int const g = NR_RGBA32_G (gl->rgba);
- unsigned int const b = NR_RGBA32_B (gl->rgba);
- unsigned int const a = NR_RGBA32_A (gl->rgba);
+ //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.
- if (gl->is_vertical()) {
- int position = (int) Inkscape::round(gl->point_on_line[Geom::X]);
- if (position < buf->rect.x0 || position >= buf->rect.x1) {
- return;
- }
-
- int p0 = buf->rect.y0;
- int p1 = buf->rect.y1;
- int step = buf->buf_rowstride;
- unsigned char *d = buf->buf + 4 * (position - buf->rect.x0);
-
- for (int p = p0; p < p1; p++) {
- d[0] = NR_COMPOSEN11_1111(r, a, d[0]);
- d[1] = NR_COMPOSEN11_1111(g, a, d[1]);
- d[2] = NR_COMPOSEN11_1111(b, a, d[2]);
- d += step;
- }
- } else if (gl->is_horizontal()) {
- int position = (int) Inkscape::round(gl->point_on_line[Geom::Y]);
- if (position < buf->rect.y0 || position >= buf->rect.y1) {
- return;
- }
+ SPGuideLine const *gl = SP_GUIDELINE (item);
- int p0 = buf->rect.x0;
- int p1 = buf->rect.x1;
- int step = 4;
- unsigned char *d = buf->buf + (position - buf->rect.y0) * buf->buf_rowstride;
+ cairo_save(buf->ct);
+ cairo_translate(buf->ct, -buf->rect.left(), -buf->rect.top());
+ ink_cairo_set_source_rgba32(buf->ct, gl->rgba);
+ cairo_set_line_width(buf->ct, 1);
+ 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;
+
+ 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(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);
+ }
- for (int p = p0; p < p1; p++) {
- d[0] = NR_COMPOSEN11_1111(r, a, d[0]);
- d[1] = NR_COMPOSEN11_1111(g, a, d[1]);
- d[2] = NR_COMPOSEN11_1111(b, a, d[2]);
- d += step;
- }
+ 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.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?
+ 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( 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];
- if ( (y_intersect_left >= buf->rect.y0) && (y_intersect_left <= buf->rect.y1) ) {
+ 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.x1 - gl->point_on_line[Geom::X]) * parallel_to_line[Geom::Y] / parallel_to_line[Geom::X] + gl->point_on_line[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);
- return;
+ 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<gint>(round(y_intersect_left)), buf->rect.right(), 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];
- if ( (y_intersect_right >= buf->rect.y0) && (y_intersect_right <= buf->rect.y1) ) {
+ 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.x1, static_cast<gint>(round(y_intersect_right)), buf->rect.x0, static_cast<gint>(round(y_intersect_left)), gl->rgba);
- return;
+ sp_guideline_drawline (buf, buf->rect.right(), static_cast<gint>(round(y_intersect_right)), buf->rect.left(), static_cast<gint>(round(y_intersect_left)), gl->rgba);
+ goto end;
}
//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];
- if ( (x_intersect_top >= buf->rect.x0) && (x_intersect_top <= buf->rect.x1) ) {
+ 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.y1 - gl->point_on_line[Geom::Y]) * parallel_to_line[Geom::X] / parallel_to_line[Geom::Y] + gl->point_on_line[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);
- return;
+ 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<gint>(round(x_intersect_top)), buf->rect.top(), static_cast<gint>(round(x_intersect_bottom)), buf->rect.bottom(), 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];
- if ( (x_intersect_top >= buf->rect.x0) && (x_intersect_top <= buf->rect.x1) ) {
+ 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<gint>(round(x_intersect_bottom)), buf->rect.y1, static_cast<gint>(round(x_intersect_top)), buf->rect.y0, gl->rgba);
- return;
+ sp_guideline_drawline (buf, static_cast<gint>(round(x_intersect_bottom)), buf->rect.bottom(), static_cast<gint>(round(x_intersect_top)), buf->rect.top(), gl->rgba);
+ goto end;
}
}
+ end:
+ cairo_restore(buf->ct);
}
static void sp_guideline_update(SPCanvasItem *item, Geom::Affine const &affine, unsigned int flags)
@@ -191,17 +192,18 @@ 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, (int) Inkscape::round(gl->point_on_line[Geom::Y]), 1000000, (int) Inkscape::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, (int) Inkscape::round(gl->point_on_line[Geom::X]), -1000000, (int) Inkscape::round(gl->point_on_line[Geom::X] + 1), 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);
}
}
@@ -212,17 +214,17 @@ static double sp_guideline_point(SPCanvasItem *item, Geom::Point p, SPCanvasItem
SPGuideLine *gl = SP_GUIDELINE (item);
if (!gl->sensitive) {
- return NR_HUGE;
+ return Geom::infinity();
}
*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);
}
-SPCanvasItem *sp_guideline_new(SPCanvasGroup *parent, Geom::Point point_on_line, Geom::Point normal)
+SPCanvasItem *sp_guideline_new(SPCanvasGroup *parent, char* label, Geom::Point point_on_line, Geom::Point normal)
{
SPCanvasItem *item = sp_canvas_item_new(parent, SP_TYPE_GUIDELINE, NULL);
SPCanvasItem *origin = sp_canvas_item_new(parent, SP_TYPE_CTRLPOINT, NULL);
@@ -232,6 +234,7 @@ SPCanvasItem *sp_guideline_new(SPCanvasGroup *parent, Geom::Point point_on_line,
gl->origin = cp;
normal.normalize();
+ gl->label = label;
gl->normal_to_line = normal;
gl->angle = tan( -gl->normal_to_line[Geom::X] / gl->normal_to_line[Geom::Y]);
sp_guideline_set_position(gl, point_on_line);
@@ -241,10 +244,20 @@ SPCanvasItem *sp_guideline_new(SPCanvasGroup *parent, Geom::Point point_on_line,
return item;
}
+void sp_guideline_set_label(SPGuideLine *gl, const char* label)
+{
+ if (gl->label) {
+ g_free(gl->label);
+ }
+ gl->label = g_strdup(label);
+
+ sp_canvas_item_request_update(SP_CANVAS_ITEM (gl));
+}
+
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)
@@ -274,82 +287,12 @@ void sp_guideline_delete(SPGuideLine *gl)
gtk_object_destroy(GTK_OBJECT(gl));
}
-//##########################################################
-// Line rendering
-#define SAFE_SETPIXEL //undefine this when it is certain that setpixel is never called with invalid params
-
-/**
- \brief This function renders a pixel on a particular buffer.
-
- The topleft of the buffer equals
- ( rect.x0 , rect.y0 ) in screen coordinates
- ( 0 , 0 ) in setpixel coordinates
- The bottomright of the buffer equals
- ( rect.x1 , rect,y1 ) in screen coordinates
- ( rect.x1 - rect.x0 , rect.y1 - rect.y0 ) in setpixel coordinates
-*/
-static void
-sp_guideline_setpixel (SPCanvasBuf *buf, gint x, gint y, guint32 rgba)
-{
-#ifdef SAFE_SETPIXEL
- if ( (x >= buf->rect.x0) && (x < buf->rect.x1) && (y >= buf->rect.y0) && (y < buf->rect.y1) ) {
-#endif
- guint r, g, b, a;
- r = NR_RGBA32_R (rgba);
- g = NR_RGBA32_G (rgba);
- b = NR_RGBA32_B (rgba);
- a = NR_RGBA32_A (rgba);
- guchar * p = buf->buf + (y - buf->rect.y0) * buf->buf_rowstride + (x - buf->rect.x0) * 4;
- p[0] = NR_COMPOSEN11_1111 (r, a, p[0]);
- p[1] = NR_COMPOSEN11_1111 (g, a, p[1]);
- p[2] = NR_COMPOSEN11_1111 (b, a, p[2]);
-#ifdef SAFE_SETPIXEL
- }
-#endif
-}
-
-/**
- \brief This function renders a line on a particular canvas buffer,
- using Bresenham's line drawing function.
- http://www.cs.unc.edu/~mcmillan/comp136/Lecture6/Lines.html
- Coordinates are interpreted as SCREENcoordinates
-*/
static void
-sp_guideline_drawline (SPCanvasBuf *buf, gint x0, gint y0, gint x1, gint y1, guint32 rgba)
+sp_guideline_drawline (SPCanvasBuf *buf, gint x0, gint y0, gint x1, gint y1, guint32 /*rgba*/)
{
- int dy = y1 - y0;
- int dx = x1 - x0;
- int stepx, stepy;
-
- if (dy < 0) { dy = -dy; stepy = -1; } else { stepy = 1; }
- if (dx < 0) { dx = -dx; stepx = -1; } else { stepx = 1; }
- dy <<= 1; // dy is now 2*dy
- dx <<= 1; // dx is now 2*dx
-
- sp_guideline_setpixel(buf, x0, y0, rgba);
- if (dx > dy) {
- int fraction = dy - (dx >> 1); // same as 2*dy - dx
- while (x0 != x1) {
- if (fraction >= 0) {
- y0 += stepy;
- fraction -= dx; // same as fraction -= 2*dx
- }
- x0 += stepx;
- fraction += dy; // same as fraction -= 2*dy
- sp_guideline_setpixel(buf, x0, y0, rgba);
- }
- } else {
- int fraction = dx - (dy >> 1);
- while (y0 != y1) {
- if (fraction >= 0) {
- x0 += stepx;
- fraction -= dy;
- }
- y0 += stepy;
- fraction += dx;
- sp_guideline_setpixel(buf, x0, y0, 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);
}
/*