diff options
| author | Jabier Arraiza Cenoz <jabier.arraiza@marker.es> | 2016-12-03 16:11:45 +0000 |
|---|---|---|
| committer | tavmjong-free <tavmjong@free.fr> | 2016-12-03 16:11:45 +0000 |
| commit | 30f2c8a062594750f351f823aa78916f8e61bfe7 (patch) | |
| tree | 4e272161ac02199055fb064e826c68f8bd4204df | |
| parent | prevent use of string concat for compatibility with old cmake (diff) | |
| download | inkscape-30f2c8a062594750f351f823aa78916f8e61bfe7.tar.gz inkscape-30f2c8a062594750f351f823aa78916f8e61bfe7.zip | |
Add triangle knot.
(bzr r15293)
| -rw-r--r-- | src/display/sodipodi-ctrl.cpp | 74 | ||||
| -rw-r--r-- | src/display/sodipodi-ctrl.h | 2 | ||||
| -rw-r--r-- | src/knot-enums.h | 1 | ||||
| -rw-r--r-- | src/knot.cpp | 9 | ||||
| -rw-r--r-- | src/knot.h | 2 |
5 files changed, 84 insertions, 4 deletions
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; diff --git a/src/knot-enums.h b/src/knot-enums.h index 1045e0433..ea23a5a2c 100644 --- a/src/knot-enums.h +++ b/src/knot-enums.h @@ -19,6 +19,7 @@ typedef enum { SP_KNOT_SHAPE_SQUARE, SP_KNOT_SHAPE_DIAMOND, SP_KNOT_SHAPE_CIRCLE, + SP_KNOT_SHAPE_TRIANGLE, SP_KNOT_SHAPE_CROSS, SP_KNOT_SHAPE_BITMAP, SP_KNOT_SHAPE_IMAGE diff --git a/src/knot.cpp b/src/knot.cpp index b57c938c3..8ac84b97b 100644 --- a/src/knot.cpp +++ b/src/knot.cpp @@ -71,6 +71,7 @@ SPKnot::SPKnot(SPDesktop *desktop, gchar const *tip) this->flags = 0; this->size = 8; + this->angle = 0; this->pos = Geom::Point(0, 0); this->grabbed_rel_pos = Geom::Point(0, 0); this->anchor = SP_ANCHOR_CENTER; @@ -111,6 +112,7 @@ SPKnot::SPKnot(SPDesktop *desktop, gchar const *tip) SP_TYPE_CTRL, "anchor", SP_ANCHOR_CENTER, "size", 8.0, + "angle", 0.0, "filled", TRUE, "fill_color", 0xffffff00, "stroked", TRUE, @@ -214,7 +216,7 @@ static int sp_knot_handler(SPCanvasItem */*item*/, GdkEvent *event, SPKnot *knot if ((event->button.button == 1) && knot->desktop && knot->desktop->event_context && !knot->desktop->event_context->space_panning) { Geom::Point const p = knot->desktop->w2d(Geom::Point(event->button.x, event->button.y)); knot->startDragging(p, (gint) event->button.x, (gint) event->button.y, event->button.time); - + knot->grabbed_signal.emit(knot, event->button.state); consumed = TRUE; } break; @@ -449,6 +451,7 @@ void SPKnot::updateCtrl() { g_object_set(this->item, "shape", this->shape, NULL); g_object_set(this->item, "mode", this->mode, NULL); g_object_set(this->item, "size", (gdouble) this->size, NULL); + g_object_set(this->item, "angle", this->angle, NULL); g_object_set(this->item, "anchor", this->anchor, NULL); if (this->pixbuf) { @@ -492,6 +495,10 @@ void SPKnot::setPixbuf(gpointer p) { pixbuf = p; } +void SPKnot::setAngle(double i) { + angle = i; +} + void SPKnot::setFill(guint32 normal, guint32 mouseover, guint32 dragging) { fill[SP_KNOT_STATE_NORMAL] = normal; fill[SP_KNOT_STATE_MOUSEOVER] = mouseover; diff --git a/src/knot.h b/src/knot.h index e3ad98e66..954ddd8a6 100644 --- a/src/knot.h +++ b/src/knot.h @@ -51,6 +51,7 @@ public: unsigned int flags; unsigned int size; /**< Always square. */ + double angle; /**< Angle of mesh handle. */ Geom::Point pos; /**< Our desktop coordinates. */ Geom::Point grabbed_rel_pos; /**< Grabbed relative position. */ Geom::Point drag_origin; /**< Origin of drag. */ @@ -92,6 +93,7 @@ public: void setAnchor(unsigned int i); void setMode(unsigned int i); void setPixbuf(void* p); + void setAngle(double i); void setFill(guint32 normal, guint32 mouseover, guint32 dragging); void setStroke(guint32 normal, guint32 mouseover, guint32 dragging); |
