static void goc_line_get_property (GObject *gobject, guint param_id, GValue *value, GParamSpec *pspec) { GocLine *line = GOC_LINE (gobject); switch (param_id) { case LINE_PROP_X0: g_value_set_double (value, line->startx); break; case LINE_PROP_Y0: g_value_set_double (value, line->starty); break; case LINE_PROP_X1: g_value_set_double (value, line->endx); break; case LINE_PROP_Y1: g_value_set_double (value, line->endy); break; case LINE_PROP_START_ARROW: g_value_set_boxed (value, &line->start_arrow); break; case LINE_PROP_END_ARROW: g_value_set_boxed (value, &line->end_arrow); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, param_id, pspec); return; /* NOTE : RETURN */ } }
static void goc_line_update_bounds (GocItem *item) { GocLine *line = GOC_LINE (item); GOStyle *style = go_styled_object_get_style (GO_STYLED_OBJECT (item)); double extra_width = style->line.width /2.; /* FIXME: take transform into account */ if (extra_width <= 0.) extra_width = .5; if (style->line.cap == CAIRO_LINE_CAP_SQUARE) extra_width *= 1.5; /* 1.4142 should be enough */ if (line->startx < line->endx) { item->x0 = line->startx - extra_width; item->x1 = line->endx + extra_width; } else { item->x0 = line->endx - extra_width; item->x1 = line->startx + extra_width; } if (line->starty < line->endy) { item->y0 = line->starty - extra_width; item->y1 = line->endy + extra_width; } else { item->y0 = line->endy - extra_width; item->y1 = line->starty + extra_width; } handle_arrow_bounds (&line->start_arrow, item); handle_arrow_bounds (&line->end_arrow, item); }
static void goc_line_draw (GocItem const *item, cairo_t *cr) { GocLine *line = GOC_LINE (item); GOStyle *style = go_styled_object_get_style (GO_STYLED_OBJECT (item)); double sign = (goc_canvas_get_direction (item->canvas) == GOC_DIRECTION_RTL)? -1: 1; double endx = (line->endx - line->startx) * sign, endy = line->endy - line->starty; double hoffs, voffs = ceil (style->line.width); double startx = 0, starty = 0; double phi; if (line->startx == line->endx && line->starty == line->endy) return; if (voffs <= 0.) voffs = 1.; hoffs = ((int) voffs & 1)? .5: 0.; voffs = (line->starty == line->endy)? hoffs: 0.; if (line->startx != line->endx) hoffs = 0.; cairo_save (cr); _goc_item_transform (item, cr, TRUE); goc_group_cairo_transform (item->parent, cr, hoffs + floor (line->startx), voffs + floor (line->starty)); endx = (endx > 0.)? ceil (endx): floor (endx); endy = (endy > 0.)? ceil (endy): floor (endy); phi = atan2 (endy, endx); draw_arrow (&line->start_arrow, cr, style, &startx, &starty, phi + M_PI); draw_arrow (&line->end_arrow, cr, style, &endx, &endy, phi); if ((endx != 0. || endy!= 0.) && go_styled_object_set_cairo_line (GO_STYLED_OBJECT (item), cr)) { /* try to avoid horizontal and vertical lines between two pixels */ cairo_move_to (cr, startx, starty); cairo_line_to (cr, endx, endy); cairo_stroke (cr); } cairo_restore (cr); }
static void goc_line_set_property (GObject *gobject, guint param_id, GValue const *value, GParamSpec *pspec) { GocLine *line = GOC_LINE (gobject); switch (param_id) { case LINE_PROP_X0: line->startx = g_value_get_double (value); break; case LINE_PROP_Y0: line->starty = g_value_get_double (value); break; case LINE_PROP_X1: line->endx = g_value_get_double (value); break; case LINE_PROP_Y1: line->endy = g_value_get_double (value); break; case LINE_PROP_START_ARROW: line->start_arrow = *((GOArrow *)g_value_peek_pointer (value)); break; case LINE_PROP_END_ARROW: line->end_arrow = *((GOArrow *)g_value_peek_pointer (value)); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, param_id, pspec); return; /* NOTE : RETURN */ } goc_item_bounds_changed (GOC_ITEM (gobject)); }
static double goc_line_distance (GocItem *item, double x, double y, GocItem **near_item) { GocLine *line = GOC_LINE (item); double dx, dy, l, t; GOStyle *style; dx = line->endx - line->startx; dy = line->endy - line->starty; l = hypot (dx, dy); x -= line->startx; y -= line->starty; t = (x * dx + y * dy) / l; y = (-x * dy + y * dx) / l; *near_item = item; if (t < 0.) return hypot (t, y); /* that might be not fully exact, but we don't need a large precision */ if (t > l) return hypot (t - l, y); style = go_styled_object_get_style (GO_STYLED_OBJECT (item)); t = fabs (y) - ((style->line.width > 5)? style->line.width/ 2.: 2.5); /* FIXME: do we need to take the arrow end into account? */ return (t > 0.)? t: 0.; }