summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJabier Arraiza Cenoz <jabier.arraiza@marker.es>2016-12-03 16:11:45 +0000
committertavmjong-free <tavmjong@free.fr>2016-12-03 16:11:45 +0000
commit30f2c8a062594750f351f823aa78916f8e61bfe7 (patch)
tree4e272161ac02199055fb064e826c68f8bd4204df
parentprevent use of string concat for compatibility with old cmake (diff)
downloadinkscape-30f2c8a062594750f351f823aa78916f8e61bfe7.tar.gz
inkscape-30f2c8a062594750f351f823aa78916f8e61bfe7.zip
Add triangle knot.
(bzr r15293)
-rw-r--r--src/display/sodipodi-ctrl.cpp74
-rw-r--r--src/display/sodipodi-ctrl.h2
-rw-r--r--src/knot-enums.h1
-rw-r--r--src/knot.cpp9
-rw-r--r--src/knot.h2
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);