summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/ui/tools/spray-tool.cpp115
-rw-r--r--src/ui/tools/spray-tool.h1
-rw-r--r--src/widgets/spray-toolbar.cpp28
-rw-r--r--src/widgets/toolbox.cpp7
4 files changed, 125 insertions, 26 deletions
diff --git a/src/ui/tools/spray-tool.cpp b/src/ui/tools/spray-tool.cpp
index 99cb78936..1ec7815c5 100644
--- a/src/ui/tools/spray-tool.cpp
+++ b/src/ui/tools/spray-tool.cpp
@@ -175,6 +175,7 @@ SprayTool::SprayTool()
, dilate_area(NULL)
, nooverlap(false)
, picker(false)
+ , pickcenter(true)
, pickinversevalue(false)
, pickfill(false)
, pickstroke(false)
@@ -257,6 +258,7 @@ void SprayTool::setup() {
sp_event_context_read(this, "Scale");
sp_event_context_read(this, "offset");
sp_event_context_read(this, "picker");
+ sp_event_context_read(this, "pickcenter");
sp_event_context_read(this, "pickinversevalue");
sp_event_context_read(this, "pickfill");
sp_event_context_read(this, "pickstroke");
@@ -308,6 +310,8 @@ void SprayTool::set(const Inkscape::Preferences::Entry& val) {
this->offset = CLAMP(val.getDouble(), -1000.0, 1000.0);
} else if (path == "picker") {
this->picker = val.getBool();
+ } else if (path == "pickcenter") {
+ this->pickcenter = val.getBool();
} else if (path == "pickinversevalue") {
this->pickinversevalue = val.getBool();
} else if (path == "pickfill") {
@@ -432,6 +436,33 @@ double randomize01(double val, double rand)
return CLAMP(val, 0, 1); // this should be unnecessary with the above provisions, but just in case...
}
+guint32 getPickerData(Geom::IntRect area){
+ SPDesktop *desktop = SP_ACTIVE_DESKTOP;
+ double R = 0, G = 0, B = 0, A = 0;
+ cairo_surface_t *s = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, area.width(), area.height());
+ sp_canvas_arena_render_surface(SP_CANVAS_ARENA(desktop->getDrawing()), s, area);
+ ink_cairo_surface_average_color(s, R, G, B, A);
+ cairo_surface_destroy(s);
+ return SP_RGBA32_F_COMPOSE(R, G, B, A);
+}
+
+bool isTrans(Geom::Point N){
+ gint32 rgba = getPickerData(Geom::IntRect::from_xywh(floor(N[Geom::X]), floor(N[Geom::Y]), 1, 1));
+ return SP_RGBA32_A_F(rgba)==0 || SP_RGBA32_A_F(rgba) < 1e-6;
+}
+
+bool overTrans(Geom::Point A, Geom::Point B, Geom::Point C, Geom::Point D){
+ return isTrans(A) || isTrans(B) || isTrans(C) || isTrans(D);
+}
+
+static void showHidden(std::vector<SPItem *> items_down){
+ for (std::vector<SPItem *>::const_iterator k=items_down.begin(); k!=items_down.end(); k++) {
+ SPItem *item_hidden = *k;
+ item_hidden->setHidden(false);
+ item_hidden->updateRepr();
+ }
+}
+
static bool fit_item(SPDesktop *desktop,
SPItem *item,
Geom::OptRect bbox,
@@ -441,6 +472,7 @@ static bool fit_item(SPDesktop *desktop,
double &_scale,
double scale,
bool picker,
+ bool pickcenter,
bool pickinversevalue,
bool pickfill,
bool pickstroke,
@@ -479,21 +511,32 @@ static bool fit_item(SPDesktop *desktop,
path *= desktop->doc2dt();
bbox_procesed = path.boundsFast();
double bbox_left_main = bbox_procesed->left();
+ double bbox_right_main = bbox_procesed->right();
double bbox_top_main = bbox_procesed->top();
+ double bbox_bottom_main = bbox_procesed->bottom();
double width_transformed = bbox_procesed->width();
double height_transformed = bbox_procesed->height();
Geom::Point mid_point = desktop->d2w(bbox_procesed->midpoint());
+ Geom::Rect rect_sprayed(mid_point, mid_point);
+ rect_sprayed.expandBy(width_transformed/2.0, height_transformed/2.0);
Geom::IntRect area = Geom::IntRect::from_xywh(floor(mid_point[Geom::X]), floor(mid_point[Geom::Y]), 1, 1);
- double R = 0, G = 0, B = 0, A = 0;
- cairo_surface_t *s = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, 1, 1);
- sp_canvas_arena_render_surface(SP_CANVAS_ARENA(desktop->getDrawing()), s, area);
- ink_cairo_surface_average_color(s, R, G, B, A);
- cairo_surface_destroy(s);
- guint32 rgba = SP_RGBA32_F_COMPOSE(R, G, B, A);
- if(nooverlap && !overtransparent && (A==0 || A < 1e-6)){
+ if (!rect_sprayed.hasZeroArea() && (!pickcenter || (overtransparent && !overnotransparent))) {
+ area = rect_sprayed.roundOutwards();
+ }
+ guint32 rgba = getPickerData(area);
+ if(!overtransparent && overnotransparent){
+ Geom::Point lt = desktop->d2w(Geom::Point(floor(bbox_left_main),floor(bbox_top_main)));
+ Geom::Point rt = desktop->d2w(Geom::Point(floor(bbox_right_main),floor(bbox_top_main)));
+ Geom::Point rb = desktop->d2w(Geom::Point(floor(bbox_right_main),floor(bbox_bottom_main)));
+ Geom::Point lb = desktop->d2w(Geom::Point(floor(bbox_left_main),floor(bbox_bottom_main)));
+ if(overTrans(lt, rt, rb, lb)){
+ return false;
+ }
+ }
+ if(nooverlap && !overtransparent && (SP_RGBA32_A_F(rgba)==0 || SP_RGBA32_A_F(rgba) < 1e-6)){
return false;
}
- if(nooverlap && !overnotransparent && A>0){
+ if(nooverlap && !overnotransparent && SP_RGBA32_A_F(rgba)>0){
return false;
}
size = std::min(width_transformed,height_transformed);
@@ -533,16 +576,29 @@ static bool fit_item(SPDesktop *desktop,
std::abs(bbox_top - bbox_top_main) > std::abs(offset_min))){
return false;
}
- } else if(picker || !overtransparent || !overnotransparent){
+ } else if(picker || overtransparent || overnotransparent){
item_down->setHidden(true);
item_down->updateRepr();
}
}
}
}
- if(picker || !overtransparent || !overnotransparent){
+ if(picker || overtransparent || overnotransparent){
if(!nooverlap){
doc->ensureUpToDate();
+ rgba = getPickerData(area);
+ }
+ if(!overtransparent && overnotransparent){
+ Geom::Point lt = desktop->d2w(Geom::Point(floor(bbox_left_main),floor(bbox_top_main)));
+ Geom::Point rt = desktop->d2w(Geom::Point(floor(bbox_right_main),floor(bbox_top_main)));
+ Geom::Point rb = desktop->d2w(Geom::Point(floor(bbox_right_main),floor(bbox_bottom_main)));
+ Geom::Point lb = desktop->d2w(Geom::Point(floor(bbox_left_main),floor(bbox_bottom_main)));
+ if(overTrans(lt, rt, rb, lb)){
+ if(!nooverlap && (picker || overtransparent || overnotransparent)){
+ showHidden(items_down);
+ }
+ return false;
+ }
}
int pick = prefs->getInt("/dialogs/clonetiler/pick");
bool pick_to_presence = prefs->getBool("/dialogs/clonetiler/pick_to_presence", false);
@@ -564,9 +620,15 @@ static bool fit_item(SPDesktop *desktop,
b = 1;
}
if(!overtransparent && (a == 0 || a < 1e-6)){
+ if(!nooverlap && (picker || overtransparent || overnotransparent)){
+ showHidden(items_down);
+ }
return false;
}
- if(!overnotransparent && a >0){
+ if(!overnotransparent && a > 0){
+ if(!nooverlap && (picker || overtransparent || overnotransparent)){
+ showHidden(items_down);
+ }
return false;
}
@@ -646,6 +708,9 @@ static bool fit_item(SPDesktop *desktop,
_scale = val;
}
if(_scale == 0.0) {
+ if(!nooverlap && (picker || overtransparent || overnotransparent)){
+ showHidden(items_down);
+ }
return false;
}
if(!fit_item(desktop,
@@ -657,6 +722,7 @@ static bool fit_item(SPDesktop *desktop,
_scale,
scale,
picker,
+ pickcenter,
pickinversevalue,
pickfill,
pickstroke,
@@ -666,6 +732,9 @@ static bool fit_item(SPDesktop *desktop,
offset,
css,
true)){
+ if(!nooverlap && (picker || overtransparent || overnotransparent)){
+ showHidden(items_down);
+ }
return false;
}
}
@@ -699,10 +768,19 @@ static bool fit_item(SPDesktop *desktop,
}
}
if (opacity < 1e-6) { // invisibly transparent, skip
+ if(!nooverlap && (picker || overtransparent || overnotransparent)){
+ showHidden(items_down);
+ }
return false;
}
}
if(!trace){
+ if (pickinversevalue) {
+ r = 1 - r;
+ g = 1 - g;
+ b = 1 - b;
+ }
+ rgba = SP_RGBA32_F_COMPOSE(r, g, b, a);
sp_svg_write_color(color_string, sizeof(color_string), rgba);
if(pickfill){
sp_repr_css_set_property(css, "fill", color_string);
@@ -711,12 +789,8 @@ static bool fit_item(SPDesktop *desktop,
sp_repr_css_set_property(css, "stroke", color_string);
}
}
- if(!nooverlap && (picker || !overtransparent || !overnotransparent)){
- for (std::vector<SPItem *>::const_iterator k=items_down.begin(); k!=items_down.end(); k++) {
- SPItem *item_hidden = *k;
- item_hidden->setHidden(false);
- item_hidden->updateRepr();
- }
+ if(!nooverlap && (picker || overtransparent || overnotransparent)){
+ showHidden(items_down);
}
}
return true;
@@ -741,6 +815,7 @@ static bool sp_spray_recursive(SPDesktop *desktop,
gint _distrib,
bool nooverlap,
bool picker,
+ bool pickcenter,
bool pickinversevalue,
bool pickfill,
bool pickstroke,
@@ -787,7 +862,7 @@ static bool sp_spray_recursive(SPDesktop *desktop,
Geom::Point move = (Geom::Point(cos(tilt)*cos(dp)*dr/(1-ratio)+sin(tilt)*sin(dp)*dr/(1+ratio), -sin(tilt)*cos(dp)*dr/(1-ratio)+cos(tilt)*sin(dp)*dr/(1+ratio)))+(p-a->midpoint());
SPCSSAttr *css = sp_repr_css_attr_new();
if(nooverlap || picker || !overtransparent || !overnotransparent){
- if(!fit_item(desktop, item, a, move, center, angle, _scale, scale, picker, pickinversevalue, pickfill, pickstroke, overnotransparent, overtransparent, nooverlap, offset, css, false)){
+ if(!fit_item(desktop, item, a, move, center, angle, _scale, scale, picker, pickcenter, pickinversevalue, pickfill, pickstroke, overnotransparent, overtransparent, nooverlap, offset, css, false)){
return false;
}
}
@@ -894,7 +969,7 @@ static bool sp_spray_recursive(SPDesktop *desktop,
Geom::Point move = (Geom::Point(cos(tilt)*cos(dp)*dr/(1-ratio)+sin(tilt)*sin(dp)*dr/(1+ratio), -sin(tilt)*cos(dp)*dr/(1-ratio)+cos(tilt)*sin(dp)*dr/(1+ratio)))+(p-a->midpoint());
SPCSSAttr *css = sp_repr_css_attr_new();
if(nooverlap || picker || !overtransparent || !overnotransparent){
- if(!fit_item(desktop, item, a, move, center, angle, _scale, scale, picker, pickinversevalue, pickfill, pickstroke, overnotransparent, overtransparent, nooverlap, offset, css, false)){
+ if(!fit_item(desktop, item, a, move, center, angle, _scale, scale, picker, pickcenter, pickinversevalue, pickfill, pickstroke, overnotransparent, overtransparent, nooverlap, offset, css, false)){
return false;
}
}
@@ -972,7 +1047,7 @@ static bool sp_spray_dilate(SprayTool *tc, Geom::Point /*event_p*/, Geom::Point
for(std::vector<SPItem*>::const_iterator i=items.begin();i!=items.end();i++){
SPItem *item = *i;
g_assert(item != NULL);
- if (sp_spray_recursive(desktop, selection, item, p, vector, tc->mode, radius, population, tc->scale, tc->scale_variation, reverse, move_mean, move_standard_deviation, tc->ratio, tc->tilt, tc->rotation_variation, tc->distrib, tc->nooverlap, tc->picker, tc->pickinversevalue, tc->pickfill, tc->pickstroke, tc->overnotransparent, tc->overtransparent, tc->offset, tc->usepressurescale, get_pressure(tc))) {
+ if (sp_spray_recursive(desktop, selection, item, p, vector, tc->mode, radius, population, tc->scale, tc->scale_variation, reverse, move_mean, move_standard_deviation, tc->ratio, tc->tilt, tc->rotation_variation, tc->distrib, tc->nooverlap, tc->picker, tc->pickcenter, tc->pickinversevalue, tc->pickfill, tc->pickstroke, tc->overnotransparent, tc->overtransparent, tc->offset, tc->usepressurescale, get_pressure(tc))) {
did = true;
}
}
diff --git a/src/ui/tools/spray-tool.h b/src/ui/tools/spray-tool.h
index ba4e75f70..066ced00e 100644
--- a/src/ui/tools/spray-tool.h
+++ b/src/ui/tools/spray-tool.h
@@ -91,6 +91,7 @@ public:
SPCanvasItem *dilate_area;
bool nooverlap;
bool picker;
+ bool pickcenter;
bool pickinversevalue;
bool pickfill;
bool pickstroke;
diff --git a/src/widgets/spray-toolbar.cpp b/src/widgets/spray-toolbar.cpp
index fe69b5050..a9a038c0e 100644
--- a/src/widgets/spray-toolbar.cpp
+++ b/src/widgets/spray-toolbar.cpp
@@ -72,6 +72,7 @@ static void sp_stb_sensitivize( GObject *tbl )
GtkAction *pickfill = GTK_ACTION( g_object_get_data(tbl, "pickfill") );
GtkAction *pickstroke = GTK_ACTION( g_object_get_data(tbl, "pickstroke") );
GtkAction *pickinversevalue = GTK_ACTION( g_object_get_data(tbl, "pickinversevalue") );
+ GtkAction *pickcenter = GTK_ACTION( g_object_get_data(tbl, "pickcenter") );
gtk_adjustment_set_value( adj_offset, 100.0 );
if (gtk_toggle_action_get_active(nooverlap)) {
gtk_action_set_sensitive( offset, TRUE );
@@ -88,10 +89,12 @@ static void sp_stb_sensitivize( GObject *tbl )
gtk_action_set_sensitive( pickfill, TRUE );
gtk_action_set_sensitive( pickstroke, TRUE );
gtk_action_set_sensitive( pickinversevalue, TRUE );
+ gtk_action_set_sensitive( pickcenter, TRUE );
} else {
gtk_action_set_sensitive( pickfill, FALSE );
gtk_action_set_sensitive( pickstroke, FALSE );
gtk_action_set_sensitive( pickinversevalue, FALSE );
+ gtk_action_set_sensitive( pickcenter, FALSE );
}
}
@@ -218,6 +221,13 @@ static void sp_toggle_picker( GtkToggleAction* act, gpointer data )
sp_stb_sensitivize(tbl);
}
+static void sp_toggle_pick_center( GtkToggleAction* act, gpointer data )
+{
+ Inkscape::Preferences *prefs = Inkscape::Preferences::get();
+ gboolean active = gtk_toggle_action_get_active(act);
+ prefs->setBool("/tools/spray/pickcenter", active);
+}
+
static void sp_toggle_pick_fill( GtkToggleAction* act, gpointer data )
{
Inkscape::Preferences *prefs = Inkscape::Preferences::get();
@@ -428,7 +438,6 @@ void sp_spray_toolbox_prep(SPDesktop *desktop, GtkActionGroup* mainActions, GObj
gtk_action_group_add_action( mainActions, GTK_ACTION(act) );
}
-
/* Picker */
{
InkToggleAction* act = ink_toggle_action_new( "SprayPickColorAction",
@@ -441,12 +450,25 @@ void sp_spray_toolbox_prep(SPDesktop *desktop, GtkActionGroup* mainActions, GObj
g_signal_connect_after( G_OBJECT(act), "toggled", G_CALLBACK(sp_toggle_picker), holder) ;
gtk_action_group_add_action( mainActions, GTK_ACTION(act) );
}
+
+ /* Pick from center */
+ {
+ InkToggleAction* act = ink_toggle_action_new( "SprayPickCenterAction",
+ _("Pick from center instead average area."),
+ _("Pick from center instead average area."),
+ INKSCAPE_ICON("snap-bounding-box-center"),
+ secondarySize );
+ gtk_toggle_action_set_active( GTK_TOGGLE_ACTION(act), prefs->getBool("/tools/spray/pickcenter", true) );
+ g_object_set_data( holder, "pickcenter", act );
+ g_signal_connect_after( G_OBJECT(act), "toggled", G_CALLBACK(sp_toggle_pick_center), holder) ;
+ gtk_action_group_add_action( mainActions, GTK_ACTION(act) );
+ }
/* Inverse Value Size */
{
InkToggleAction* act = ink_toggle_action_new( "SprayOverPickInverseValueAction",
- _("Inversed pick value retaining color"),
- _("Inversed pick value retaining color"),
+ _("Inversed pick value, retaining color in advanced trace mode"),
+ _("Inversed pick value, retaining color in advanced trace mode"),
INKSCAPE_ICON("object-tweak-shrink"),
secondarySize );
gtk_toggle_action_set_active( GTK_TOGGLE_ACTION(act), prefs->getBool("/tools/spray/pickinversevalue", false) );
diff --git a/src/widgets/toolbox.cpp b/src/widgets/toolbox.cpp
index b9051dd50..0aaba39f9 100644
--- a/src/widgets/toolbox.cpp
+++ b/src/widgets/toolbox.cpp
@@ -327,10 +327,11 @@ static gchar const * ui_descr =
" <toolitem action='SprayToolOffsetAction' />"
" <separator />"
" <toolitem action='SprayPickColorAction' />"
- " <toolitem action='SprayOverPickInverseValueAction' />"
" <toolitem action='SprayOverPickFillAction' />"
" <toolitem action='SprayOverPickStrokeAction' />"
-
+ " <toolitem action='SprayOverPickInverseValueAction' />"
+ " <toolitem action='SprayPickCenterAction' />"
+
" </toolbar>"
" <toolbar name='ZoomToolbar'>"
@@ -369,7 +370,7 @@ static gchar const * ui_descr =
" <toolitem action='MeasureToGuides' />"
" <toolitem action='MeasureMarkDimension' />"
" <toolitem action='MeasureToItem' />"
- " </toolbar>"
+ " </toolbar>"
" <toolbar name='StarToolbar'>"
" <separator />"