97 :
DialogBase(
"/dialogs/clonetiler/",
"CloneTiler")
98 , table_row_labels(nullptr)
105 auto const mainbox = Gtk::make_managed<Gtk::Box>(Gtk::Orientation::VERTICAL, 4);
106 mainbox->set_margin(6);
109 nb = Gtk::make_managed<Gtk::Notebook>();
124 }
const sym_groups[] = {
126 {
TILE_P1, _(
"<b>P1</b>: simple translation")},
127 {
TILE_P2, _(
"<b>P2</b>: 180° rotation")},
128 {
TILE_PM, _(
"<b>PM</b>: reflection")},
131 {
TILE_PG, _(
"<b>PG</b>: glide reflection")},
132 {
TILE_CM, _(
"<b>CM</b>: reflection + glide reflection")},
133 {
TILE_PMM, _(
"<b>PMM</b>: reflection + reflection")},
134 {
TILE_PMG, _(
"<b>PMG</b>: reflection + 180° rotation")},
135 {
TILE_PGG, _(
"<b>PGG</b>: glide reflection + 180° rotation")},
136 {
TILE_CMM, _(
"<b>CMM</b>: reflection + reflection + 180° rotation")},
137 {
TILE_P4, _(
"<b>P4</b>: 90° rotation")},
138 {
TILE_P4M, _(
"<b>P4M</b>: 90° rotation + 45° reflection")},
139 {
TILE_P4G, _(
"<b>P4G</b>: 90° rotation + 90° reflection")},
140 {
TILE_P3, _(
"<b>P3</b>: 120° rotation")},
141 {
TILE_P31M, _(
"<b>P31M</b>: reflection + 120° rotation, dense")},
142 {
TILE_P3M1, _(
"<b>P3M1</b>: reflection + 120° rotation, sparse")},
143 {
TILE_P6, _(
"<b>P6</b>: 60° rotation")},
144 {
TILE_P6M, _(
"<b>P6M</b>: reflection + 60° rotation")},
150 auto const combo = Gtk::make_managed<Gtk::ComboBoxText>();
151 combo->set_tooltip_text(_(
"Select one of the 17 symmetry groups for the tiling"));
154 auto cell_list = gtk_cell_layout_get_cells(GTK_CELL_LAYOUT(combo->gobj()));
155 gtk_cell_layout_set_attributes(GTK_CELL_LAYOUT(combo->gobj()),
156 GTK_CELL_RENDERER(cell_list->data),
157 "markup", 0,
nullptr);
159 for (
const auto & sg : sym_groups) {
161 combo->append(sg.label);
170 table_row_labels = Gtk::SizeGroup::create(Gtk::SizeGroup::Mode::HORIZONTAL);
181 auto const l = Gtk::make_managed<Gtk::Label>(
"");
184 l->set_markup(_(
"<b>Shift X:</b>"));
193 _(
"Horizontal shift per row (in % of tile width)"),
"shiftx_per_j",
201 _(
"Horizontal shift per column (in % of tile width)"),
"shiftx_per_i",
207 auto l =
spinbox (_(
"Randomize the horizontal shift by this percentage"),
"shiftx_rand",
214 auto const l = Gtk::make_managed<Gtk::Label>(
"");
217 l->set_markup(_(
"<b>Shift Y:</b>"));
226 _(
"Vertical shift per row (in % of tile height)"),
"shifty_per_j",
234 _(
"Vertical shift per column (in % of tile height)"),
"shifty_per_i",
241 _(
"Randomize the vertical shift by this percentage"),
"shifty_rand",
248 auto const l = Gtk::make_managed<Gtk::Label>(
"");
249 l->set_markup(_(
"<b>Exponent:</b>"));
257 _(
"Whether rows are spaced evenly (1), converge (<1) or diverge (>1)"),
"shifty_exp",
264 _(
"Whether columns are spaced evenly (1), converge (<1) or diverge (>1)"),
"shiftx_exp",
270 auto const l = Gtk::make_managed<Gtk::Label>(
"");
272 l->set_markup(_(
"<small>Alternate:</small>"));
279 auto l =
checkbox (_(
"Alternate the sign of shifts for each row"),
"shifty_alternate");
284 auto l =
checkbox (_(
"Alternate the sign of shifts for each column"),
"shiftx_alternate");
289 auto const l = Gtk::make_managed<Gtk::Label>(
"");
291 l->set_markup(_(
"<small>Cumulate:</small>"));
298 auto l =
checkbox (_(
"Cumulate the shifts for each row"),
"shifty_cumulate");
303 auto l =
checkbox (_(
"Cumulate the shifts for each column"),
"shiftx_cumulate");
308 auto const l = Gtk::make_managed<Gtk::Label>(
"");
310 l->set_markup(_(
"<small>Exclude tile:</small>"));
317 auto l =
checkbox (_(
"Exclude tile height in shift"),
"shifty_excludeh");
322 auto l =
checkbox (_(
"Exclude tile width in shift"),
"shiftx_excludew");
338 auto const l = Gtk::make_managed<Gtk::Label>(
"");
339 l->set_markup(_(
"<b>Scale X:</b>"));
348 _(
"Horizontal scale per row (in % of tile width)"),
"scalex_per_j",
356 _(
"Horizontal scale per column (in % of tile width)"),
"scalex_per_i",
362 auto l =
spinbox (_(
"Randomize the horizontal scale by this percentage"),
"scalex_rand",
369 auto const l = Gtk::make_managed<Gtk::Label>(
"");
370 l->set_markup(_(
"<b>Scale Y:</b>"));
379 _(
"Vertical scale per row (in % of tile height)"),
"scaley_per_j",
387 _(
"Vertical scale per column (in % of tile height)"),
"scaley_per_i",
393 auto l =
spinbox (_(
"Randomize the vertical scale by this percentage"),
"scaley_rand",
400 auto const l = Gtk::make_managed<Gtk::Label>(
"");
401 l->set_markup(_(
"<b>Exponent:</b>"));
408 auto l =
spinbox (_(
"Whether row scaling is uniform (1), converge (<1) or diverge (>1)"),
"scaley_exp",
414 auto l =
spinbox (_(
"Whether column scaling is uniform (1), converge (<1) or diverge (>1)"),
"scalex_exp",
421 auto const l = Gtk::make_managed<Gtk::Label>(
"");
422 l->set_markup(_(
"<b>Base:</b>"));
429 auto l =
spinbox (_(
"Base for a logarithmic spiral: not used (0), converge (<1), or diverge (>1)"),
"scaley_log",
435 auto l =
spinbox (_(
"Base for a logarithmic spiral: not used (0), converge (<1), or diverge (>1)"),
"scalex_log",
441 auto const l = Gtk::make_managed<Gtk::Label>(
"");
443 l->set_markup(_(
"<small>Alternate:</small>"));
450 auto l =
checkbox (_(
"Alternate the sign of scales for each row"),
"scaley_alternate");
455 auto l =
checkbox (_(
"Alternate the sign of scales for each column"),
"scalex_alternate");
460 auto const l = Gtk::make_managed<Gtk::Label>(
"");
462 l->set_markup(_(
"<small>Cumulate:</small>"));
469 auto l =
checkbox (_(
"Cumulate the scales for each row"),
"scaley_cumulate");
474 auto l =
checkbox (_(
"Cumulate the scales for each column"),
"scalex_cumulate");
490 auto const l = Gtk::make_managed<Gtk::Label>(
"");
491 l->set_markup(_(
"<b>Angle:</b>"));
500 _(
"Rotate tiles by this angle for each row"),
"rotate_per_j",
501 -180, 180,
"°");
508 _(
"Rotate tiles by this angle for each column"),
"rotate_per_i",
509 -180, 180,
"°");
514 auto l =
spinbox (_(
"Randomize the rotation angle by this percentage"),
"rotate_rand",
520 auto const l = Gtk::make_managed<Gtk::Label>(
"");
522 l->set_markup(_(
"<small>Alternate:</small>"));
529 auto l =
checkbox (_(
"Alternate the rotation direction for each row"),
"rotate_alternatej");
534 auto l =
checkbox (_(
"Alternate the rotation direction for each column"),
"rotate_alternatei");
539 auto const l = Gtk::make_managed<Gtk::Label>(
"");
541 l->set_markup(_(
"<small>Cumulate:</small>"));
548 auto l =
checkbox (_(
"Cumulate the rotation for each row"),
"rotate_cumulatej");
553 auto l =
checkbox (_(
"Cumulate the rotation for each column"),
"rotate_cumulatei");
562 auto vb =
new_tab(
nb, _(
"_Blur & opacity"));
570 auto const l = Gtk::make_managed<Gtk::Label>(
"");
571 l->set_markup(_(
"<b>Blur:</b>"));
578 auto l =
spinbox (_(
"Blur tiles by this percentage for each row"),
"blur_per_j",
584 auto l =
spinbox (_(
"Blur tiles by this percentage for each column"),
"blur_per_i",
590 auto l =
spinbox (_(
"Randomize the tile blur by this percentage"),
"blur_rand",
596 auto const l = Gtk::make_managed<Gtk::Label>(
"");
598 l->set_markup(_(
"<small>Alternate:</small>"));
605 auto l =
checkbox (_(
"Alternate the sign of blur change for each row"),
"blur_alternatej");
610 auto l =
checkbox (_(
"Alternate the sign of blur change for each column"),
"blur_alternatei");
618 auto const l = Gtk::make_managed<Gtk::Label>(
"");
619 l->set_markup(_(
"<b>Opacity:</b>"));
626 auto l =
spinbox (_(
"Decrease tile opacity by this percentage for each row"),
"opacity_per_j",
632 auto l =
spinbox (_(
"Decrease tile opacity by this percentage for each column"),
"opacity_per_i",
638 auto l =
spinbox (_(
"Randomize the tile opacity by this percentage"),
"opacity_rand",
644 auto const l = Gtk::make_managed<Gtk::Label>(
"");
646 l->set_markup(_(
"<small>Alternate:</small>"));
653 auto l =
checkbox (_(
"Alternate the sign of opacity change for each row"),
"opacity_alternatej");
658 auto l =
checkbox (_(
"Alternate the sign of opacity change for each column"),
"opacity_alternatei");
669 auto const hb = Gtk::make_managed<Gtk::Box>(Gtk::Orientation::HORIZONTAL, 0);
671 auto const l = Gtk::make_managed<Gtk::Label>(_(
"Initial color: "));
674 auto color = prefs->getColor(
prefs_path +
"initial_color",
"#000000ff");
675 color_picker = Gtk::make_managed<UI::Widget::ColorPicker>(_(
"Initial color of tiled clones"),
676 _(
"Initial color for clones (works only if the original has unset fill or stroke or on spray tool in copy mode)"),
691 auto const l = Gtk::make_managed<Gtk::Label>(
"");
692 l->set_markup(_(
"<b>H:</b>"));
699 auto l =
spinbox (_(
"Change the tile hue by this percentage for each row"),
"hue_per_j",
705 auto l =
spinbox (_(
"Change the tile hue by this percentage for each column"),
"hue_per_i",
711 auto l =
spinbox (_(
"Randomize the tile hue by this percentage"),
"hue_rand",
719 auto const l = Gtk::make_managed<Gtk::Label>(
"");
720 l->set_markup(_(
"<b>S:</b>"));
727 auto l =
spinbox (_(
"Change the color saturation by this percentage for each row"),
"saturation_per_j",
733 auto l =
spinbox (_(
"Change the color saturation by this percentage for each column"),
"saturation_per_i",
739 auto l =
spinbox (_(
"Randomize the color saturation by this percentage"),
"saturation_rand",
746 auto const l = Gtk::make_managed<Gtk::Label>(
"");
747 l->set_markup(_(
"<b>L:</b>"));
754 auto l =
spinbox (_(
"Change the color lightness by this percentage for each row"),
"lightness_per_j",
760 auto l =
spinbox (_(
"Change the color lightness by this percentage for each column"),
"lightness_per_i",
766 auto l =
spinbox (_(
"Randomize the color lightness by this percentage"),
"lightness_rand",
773 auto const l = Gtk::make_managed<Gtk::Label>(
"");
774 l->set_markup(_(
"<small>Alternate:</small>"));
781 auto l =
checkbox (_(
"Alternate the sign of color changes for each row"),
"color_alternatej");
786 auto l =
checkbox (_(
"Alternate the sign of color changes for each column"),
"color_alternatei");
796 auto const hb = Gtk::make_managed<Gtk::Box>(Gtk::Orientation::HORIZONTAL,
VB_MARGIN);
800 _b = Gtk::make_managed<UI::Widget::CheckButtonInternal>(_(
"Trace the drawing under the clones/sprayed items"));
801 _b->set_uncheckable();
802 bool old = prefs->getBool(
prefs_path +
"dotrace");
804 _b->set_tooltip_text(_(
"For each clone/sprayed item, pick a value from the drawing in its location and apply it"));
810 auto const vvb = Gtk::make_managed<Gtk::Box>(Gtk::Orientation::VERTICAL, 0);
815 auto const frame = Gtk::make_managed<Gtk::Frame>(_(
"1. Pick from the drawing:"));
816 frame->add_css_class(
"flat");
819 auto const table = Gtk::make_managed<Gtk::Grid>();
820 table->set_row_spacing(4);
821 table->set_column_spacing(6);
822 table->set_margin(4);
823 frame->set_child(*table);
825 Gtk::CheckButton *rb_group;
827 auto const radio = Gtk::make_managed<Gtk::CheckButton>(_(
"Color"));
829 radio->set_tooltip_text(_(
"Pick the visible color and opacity"));
835 auto const radio = Gtk::make_managed<Gtk::CheckButton>(_(
"Opacity"));
836 radio->set_group(*rb_group);
837 radio->set_tooltip_text(_(
"Pick the total accumulated opacity"));
843 auto const radio = Gtk::make_managed<Gtk::CheckButton>(_(
"R"));
844 radio->set_group(*rb_group);
845 radio->set_tooltip_text(_(
"Pick the Red component of the color"));
851 auto const radio = Gtk::make_managed<Gtk::CheckButton>(_(
"G"));
852 radio->set_group(*rb_group);
853 radio->set_tooltip_text(_(
"Pick the Green component of the color"));
859 auto const radio = Gtk::make_managed<Gtk::CheckButton>(_(
"B"));
860 radio->set_group(*rb_group);
861 radio->set_tooltip_text(_(
"Pick the Blue component of the color"));
867 auto const radio = Gtk::make_managed<Gtk::CheckButton>(C_(
"Clonetiler color hue",
"H"));
868 radio->set_group(*rb_group);
869 radio->set_tooltip_text(_(
"Pick the hue of the color"));
875 auto const radio = Gtk::make_managed<Gtk::CheckButton>(C_(
"Clonetiler color saturation",
"S"));
876 radio->set_group(*rb_group);
877 radio->set_tooltip_text(_(
"Pick the saturation of the color"));
883 auto const radio = Gtk::make_managed<Gtk::CheckButton>(C_(
"Clonetiler color lightness",
"L"));
884 radio->set_group(*rb_group);
885 radio->set_tooltip_text(_(
"Pick the lightness of the color"));
894 auto const frame = Gtk::make_managed<Gtk::Frame>(_(
"2. Tweak the picked value:"));
895 frame->add_css_class(
"flat");
898 auto const table = Gtk::make_managed<Gtk::Grid>();
899 table->set_row_spacing(4);
900 table->set_column_spacing(6);
901 table->set_halign(Gtk::Align::START);
902 table->set_margin(4);
903 frame->set_child(*table);
906 auto const l = Gtk::make_managed<Gtk::Label>(
"");
907 l->set_markup(_(
"Gamma-correct:"));
911 auto l =
spinbox (_(
"Shift the mid-range of the picked value upwards (>0) or downwards (<0)"),
"gamma_picked",
917 auto const l = Gtk::make_managed<Gtk::Label>(
"");
918 l->set_markup(_(
"Randomize:"));
922 auto l =
spinbox (_(
"Randomize the picked value by this percentage"),
"rand_picked",
928 auto const l = Gtk::make_managed<Gtk::Label>(
"");
929 l->set_markup(_(
"Invert:"));
933 auto l =
checkbox (_(
"Invert the picked value"),
"invert_picked");
939 auto const frame = Gtk::make_managed<Gtk::Frame>(_(
"3. Apply the value to the clones':"));
940 frame->add_css_class(
"flat");
943 auto const table = Gtk::make_managed<Gtk::Grid>();
944 table->set_row_spacing(4);
945 table->set_column_spacing(6);
946 table->set_margin(4);
947 frame->set_child(*table);
950 auto const b = Gtk::make_managed<Gtk::CheckButton>(_(
"Presence"));
951 bool old = prefs->getBool(
prefs_path +
"pick_to_presence",
true);
953 b->set_tooltip_text(_(
"Each clone is created with the probability determined by the picked value in that point"));
955 b->signal_toggled().connect(sigc::bind(sigc::mem_fun(*
this, &
CloneTiler::pick_to), b,
"pick_to_presence"));
959 auto const b = Gtk::make_managed<Gtk::CheckButton>(_(
"Size"));
960 bool old = prefs->getBool(
prefs_path +
"pick_to_size");
962 b->set_tooltip_text(_(
"Each clone's size is determined by the picked value in that point"));
964 b->signal_toggled().connect(sigc::bind(sigc::mem_fun(*
this, &
CloneTiler::pick_to), b,
"pick_to_size"));
968 auto const b = Gtk::make_managed<Gtk::CheckButton>(_(
"Color"));
969 bool old = prefs->getBool(
prefs_path +
"pick_to_color",
false);
971 b->set_tooltip_text(_(
"Each clone is painted by the picked color (the original must have unset fill or stroke)"));
973 b->signal_toggled().connect(sigc::bind(sigc::mem_fun(*
this, &
CloneTiler::pick_to), b,
"pick_to_color"));
977 auto const b = Gtk::make_managed<Gtk::CheckButton>(_(
"Opacity"));
978 bool old = prefs->getBool(
prefs_path +
"pick_to_opacity",
false);
980 b->set_tooltip_text(_(
"Each clone's opacity is determined by the picked value in that point"));
982 b->signal_toggled().connect(sigc::bind(sigc::mem_fun(*
this, &
CloneTiler::pick_to), b,
"pick_to_opacity"));
985 vvb->set_sensitive(prefs->getBool(
prefs_path +
"dotrace"));
990 auto const hb = Gtk::make_managed<Gtk::Box>(Gtk::Orientation::HORIZONTAL,
VB_MARGIN);
993 auto const l = Gtk::make_managed<Gtk::Label>(
"");
994 l->set_markup(_(
"Apply to tiled clones:"));
1000 auto const table = Gtk::make_managed<Gtk::Grid>();
1001 table->set_row_spacing(4);
1002 table->set_column_spacing(6);
1008 auto a = Gtk::Adjustment::create(0.0, 1, 500, 1, 10, 0);
1009 int value = prefs->getInt(
prefs_path +
"jmax", 2);
1010 a->set_value (value);
1012 auto const sb = Gtk::make_managed<UI::Widget::SpinButton>(a, 1.0, 0);
1013 sb->set_tooltip_text (_(
"How many rows in the tiling"));
1014 sb->set_width_chars (7);
1015 sb->set_name(
"row");
1023 auto const l = Gtk::make_managed<Gtk::Label>(
"");
1024 l->set_markup(
"×");
1030 auto a = Gtk::Adjustment::create(0.0, 1, 500, 1, 10, 0);
1031 int value = prefs->getInt(
prefs_path +
"imax", 2);
1032 a->set_value (value);
1034 auto const sb = Gtk::make_managed<UI::Widget::SpinButton>(a, 1.0, 0);
1035 sb->set_tooltip_text (_(
"How many columns in the tiling"));
1036 sb->set_width_chars (7);
1046 unit_menu = Gtk::make_managed<UI::Widget::UnitMenu>();
1048 unit_menu->
setUnit(SP_ACTIVE_DESKTOP->getNamedView()->display_units->abbr);
1053 fill_width = Gtk::Adjustment::create(0.0, -1e6, 1e6, 1.0, 10.0, 0);
1055 double value = prefs->getDouble(
prefs_path +
"fillwidth", 50.0);
1060 auto const e = Gtk::make_managed<UI::Widget::SpinButton>(
fill_width, 1.0, 2);
1061 e->set_tooltip_text (_(
"Width of the rectangle to be filled"));
1062 e->set_width_chars (7);
1069 auto const l = Gtk::make_managed<Gtk::Label>(
"");
1070 l->set_markup(
"×");
1077 fill_height = Gtk::Adjustment::create(0.0, -1e6, 1e6, 1.0, 10.0, 0);
1079 double value = prefs->getDouble(
prefs_path +
"fillheight", 50.0);
1084 auto const e = Gtk::make_managed<UI::Widget::SpinButton>(
fill_height, 1.0, 2);
1085 e->set_tooltip_text (_(
"Height of the rectangle to be filled"));
1086 e->set_width_chars (7);
1098 Gtk::CheckButton *rb_group;
1100 auto const radio = Gtk::make_managed<Gtk::CheckButton>(_(
"Rows, columns: "));
1102 radio->set_tooltip_text(_(
"Create the specified number of rows and columns"));
1105 if (!prefs->getBool(
prefs_path +
"fillrect")) {
1106 radio->set_active(
true);
1112 auto const radio = Gtk::make_managed<Gtk::CheckButton>(_(
"Width, height: "));
1113 radio->set_group(*rb_group);
1114 radio->set_tooltip_text(_(
"Fill the specified width and height with the tiling"));
1117 if (prefs->getBool(
prefs_path +
"fillrect")) {
1118 radio->set_active(
true);
1128 auto const hb = Gtk::make_managed<Gtk::Box>(Gtk::Orientation::HORIZONTAL,
VB_MARGIN);
1131 _cb_keep_bbox = Gtk::make_managed<UI::Widget::CheckButtonInternal>(_(
"Use saved size and position of the tile"));
1132 auto keepbbox = prefs->getBool(
prefs_path +
"keepbbox",
true);
1134 _cb_keep_bbox->set_tooltip_text(_(
"Pretend that the size and position of the tile are the same "
1135 "as the last time you tiled it (if any), instead of using the "
1143 auto const hb = Gtk::make_managed<Gtk::Box>(Gtk::Orientation::HORIZONTAL,
VB_MARGIN);
1146 auto const l = Gtk::make_managed<Gtk::Label>(
"");
1153 auto const hb = Gtk::make_managed<Gtk::Box>(Gtk::Orientation::HORIZONTAL,
VB_MARGIN);
1157 auto const b = Gtk::make_managed<Gtk::Button>();
1158 auto const l = Gtk::make_managed<Gtk::Label>(
"");
1159 l->set_markup_with_mnemonic(_(
" <b>_Create</b> "));
1161 b->set_tooltip_text(_(
"Create and tile the clones of the selection"));
1167 auto const sb = Gtk::make_managed<Gtk::Box>(Gtk::Orientation::HORIZONTAL, 4);
1179 auto const b = Gtk::make_managed<Gtk::Button>(_(
" _Unclump "),
true);
1180 b->set_tooltip_text(_(
"Spread out clones to reduce clumping; can be applied repeatedly"));
1186 auto const b = Gtk::make_managed<Gtk::Button>(_(
" Re_move "),
true);
1187 b->set_tooltip_text(_(
"Remove existing tiled clones of the selected object (siblings only)"));
1202 auto const b = Gtk::make_managed<Gtk::Button>(_(
" R_eset "),
true);
1204 b->set_tooltip_text(_(
"Reset all shifts, scales, rotates, opacity and color changes in the dialog to zero"));
1272 double cx,
double cy,
1277 double shiftx_per_i,
double shifty_per_i,
1278 double shiftx_per_j,
double shifty_per_j,
1279 double shiftx_rand,
double shifty_rand,
1280 double shiftx_exp,
double shifty_exp,
1281 int shiftx_alternate,
int shifty_alternate,
1282 int shiftx_cumulate,
int shifty_cumulate,
1283 int shiftx_excludew,
int shifty_excludeh,
1286 double scalex_per_i,
double scaley_per_i,
1287 double scalex_per_j,
double scaley_per_j,
1288 double scalex_rand,
double scaley_rand,
1289 double scalex_exp,
double scaley_exp,
1290 double scalex_log,
double scaley_log,
1291 int scalex_alternate,
int scaley_alternate,
1292 int scalex_cumulate,
int scaley_cumulate,
1295 double rotate_per_i,
double rotate_per_j,
1297 int rotate_alternatei,
int rotate_alternatej,
1298 int rotate_cumulatei,
int rotate_cumulatej
1303 double delta_shifti = 0.0;
1304 double delta_shiftj = 0.0;
1306 if( shiftx_alternate ) {
1307 delta_shifti = (double)(i%2);
1309 if( shiftx_cumulate ) {
1310 delta_shifti = (double)(i*i);
1312 delta_shifti = (double)i;
1316 if( shifty_alternate ) {
1317 delta_shiftj = (double)(j%2);
1319 if( shifty_cumulate ) {
1320 delta_shiftj = (double)(j*j);
1322 delta_shiftj = (double)j;
1327 double delta_shiftx_rand = 0.0;
1328 double delta_shifty_rand = 0.0;
1329 if( shiftx_rand != 0.0 ) delta_shiftx_rand = shiftx_rand * g_random_double_range (-1, 1);
1330 if( shifty_rand != 0.0 ) delta_shifty_rand = shifty_rand * g_random_double_range (-1, 1);
1334 double di = shiftx_per_i * delta_shifti + shiftx_per_j * delta_shiftj + delta_shiftx_rand;
1335 double dj = shifty_per_i * delta_shifti + shifty_per_j * delta_shiftj + delta_shifty_rand;
1345 if( !shiftx_excludew ) shifti += i;
1346 if( !shifty_excludeh ) shiftj += j;
1349 double shifti_sign = (shifti > 0.0) ? 1.0 : -1.0;
1350 shifti = shifti_sign * pow(fabs(shifti), shiftx_exp);
1351 double shiftj_sign = (shiftj > 0.0) ? 1.0 : -1.0;
1352 shiftj = shiftj_sign * pow(fabs(shiftj), shifty_exp);
1358 double delta_rotationi = 0.0;
1359 double delta_rotationj = 0.0;
1361 if( rotate_alternatei ) {
1362 delta_rotationi = (double)(i%2);
1364 if( rotate_cumulatei ) {
1365 delta_rotationi = (double)(i*i + i)/2.0;
1367 delta_rotationi = (double)i;
1371 if( rotate_alternatej ) {
1372 delta_rotationj = (double)(j%2);
1374 if( rotate_cumulatej ) {
1375 delta_rotationj = (double)(j*j + j)/2.0;
1377 delta_rotationj = (double)j;
1381 double delta_rotate_rand = 0.0;
1382 if( rotate_rand != 0.0 ) delta_rotate_rand = rotate_rand * 180.0 * g_random_double_range (-1, 1);
1384 double dr = rotate_per_i * delta_rotationi + rotate_per_j * delta_rotationj + delta_rotate_rand;
1387 double delta_scalei = 0.0;
1388 double delta_scalej = 0.0;
1390 if( scalex_alternate ) {
1391 delta_scalei = (double)(i%2);
1393 if( scalex_cumulate ) {
1394 delta_scalei = (double)(i*i + i)/2.0;
1396 delta_scalei = (double)i;
1400 if( scaley_alternate ) {
1401 delta_scalej = (double)(j%2);
1403 if( scaley_cumulate ) {
1404 delta_scalej = (double)(j*j + j)/2.0;
1406 delta_scalej = (double)j;
1411 double delta_scalex_rand = 0.0;
1412 double delta_scaley_rand = 0.0;
1413 if( scalex_rand != 0.0 ) delta_scalex_rand = scalex_rand * g_random_double_range (-1, 1);
1414 if( scaley_rand != 0.0 ) delta_scaley_rand = scaley_rand * g_random_double_range (-1, 1);
1416 if( scalex_rand == scaley_rand ) delta_scalex_rand = delta_scaley_rand;
1419 double scalex = 1.0 + scalex_per_i * delta_scalei + scalex_per_j * delta_scalej + delta_scalex_rand;
1420 double scaley = 1.0 + scaley_per_i * delta_scalei + scaley_per_j * delta_scalej + delta_scaley_rand;
1422 if( scalex < 0.0 ) scalex = 0.0;
1423 if( scaley < 0.0 ) scaley = 0.0;
1426 if ( scalex_exp != 1.0 ) scalex = pow( scalex, scalex_exp );
1427 if ( scaley_exp != 1.0 ) scaley = pow( scaley, scaley_exp );
1430 if ( scalex_log > 0.0 ) scalex = pow( scalex_log, scalex - 1.0 );
1431 if ( scaley_log > 0.0 ) scaley = pow( scaley_log, scaley - 1.0 );
1460 const double cos60 = cos(M_PI/3);
1461 const double sin60 = sin(M_PI/3);
1462 const double cos30 = cos(M_PI/6);
1463 const double sin30 = sin(M_PI/6);
1468 return d_s_r * rect_translate;
1473 return d_s_r * rect_translate;
1475 return d_s_r * rotate_180_c * rect_translate;
1481 return d_s_r * rect_translate;
1483 return d_s_r * flip_x * rect_translate;
1489 return d_s_r * rect_translate;
1491 return d_s_r * flip_x * rect_translate;
1496 if ((i + j) % 2 == 0) {
1497 return d_s_r * rect_translate;
1499 return d_s_r * flip_x * rect_translate;
1506 return d_s_r * rect_translate;
1508 return d_s_r * flip_x * rect_translate;
1512 return d_s_r * flip_y * rect_translate;
1514 return d_s_r * flip_x * flip_y * rect_translate;
1522 return d_s_r * rect_translate;
1524 return d_s_r * rotate_180_c * rect_translate;
1528 return d_s_r * flip_y * rect_translate;
1530 return d_s_r * rotate_180_c * flip_y * rect_translate;
1538 return d_s_r * rect_translate;
1540 return d_s_r * flip_y * rect_translate;
1544 return d_s_r * rotate_180_c * rect_translate;
1546 return d_s_r * rotate_180_c * flip_y * rect_translate;
1554 return d_s_r * rect_translate;
1556 return d_s_r * flip_x * rect_translate;
1558 }
else if (j % 4 == 1) {
1560 return d_s_r * flip_y * rect_translate;
1562 return d_s_r * flip_x * flip_y * rect_translate;
1564 }
else if (j % 4 == 2) {
1566 return d_s_r * rect_translate;
1568 return d_s_r * flip_x * rect_translate;
1572 return d_s_r * flip_y * rect_translate;
1574 return d_s_r * flip_x * flip_y * rect_translate;
1588 return d_s_r * rotate_m90_c * dia1 * ori;
1592 return d_s_r * rotate_90_c * dia2 * ori;
1594 return d_s_r * rotate_180_c * dia1 * dia2 * ori;
1602 double max =
MAX(
w, h);
1609 }
else if (i % 4 == 1) {
1610 return d_s_r * flip_y * rotate_m90_c * dia1 * ori;
1611 }
else if (i % 4 == 2) {
1613 }
else if (i % 4 == 3) {
1619 }
else if (i % 4 == 1) {
1621 }
else if (i % 4 == 2) {
1623 }
else if (i % 4 == 3) {
1632 double max =
MAX(
w, h);
1636 if (((i/4) + j) % 2 == 0) {
1639 }
else if (i % 4 == 1) {
1640 return d_s_r * rotate_m90_c * dia1 * ori;
1641 }
else if (i % 4 == 2) {
1642 return d_s_r * rotate_90_c * dia2 * ori;
1643 }
else if (i % 4 == 3) {
1644 return d_s_r * rotate_180_c * dia1 * dia2 * ori;
1649 }
else if (i % 4 == 1) {
1650 return d_s_r * flip_y * rotate_m90_c * dia1 *
Geom::Translate (-h, 0) * ori;
1651 }
else if (i % 4 == 2) {
1652 return d_s_r * flip_y * rotate_90_c * dia2 *
Geom::Translate (h, 0) * ori;
1653 }
else if (i % 4 == 3) {
1672 width = h * cos (M_PI/6);
1680 }
else if (i % 3 == 1) {
1681 return d_s_r * rotate_m120_c * dia1 * ori;
1682 }
else if (i % 3 == 2) {
1683 return d_s_r * rotate_120_c * dia2 * ori;
1710 }
else if (i % 6 == 1) {
1711 return d_s_r * flip_y * rotate_m120_c * dia1 * ori;
1712 }
else if (i % 6 == 2) {
1713 return d_s_r * rotate_m120_c * dia2 * ori;
1714 }
else if (i % 6 == 3) {
1715 return d_s_r * flip_y * rotate_120_c * dia3 * ori;
1716 }
else if (i % 6 == 4) {
1717 return d_s_r * rotate_120_c * dia4 * ori;
1718 }
else if (i % 6 == 5) {
1740 width = 2 * h * cos (M_PI/6);
1750 }
else if (i % 6 == 1) {
1751 return d_s_r * flip_y * rotate_m120_c * dia1 * ori;
1752 }
else if (i % 6 == 2) {
1753 return d_s_r * rotate_m120_c * dia2 * ori;
1754 }
else if (i % 6 == 3) {
1755 return d_s_r * flip_y * rotate_120_c * dia3 * ori;
1756 }
else if (i % 6 == 4) {
1757 return d_s_r * rotate_120_c * dia4 * ori;
1758 }
else if (i % 6 == 5) {
1789 }
else if (i % 6 == 1) {
1790 return d_s_r * rotate_m60_c * dia1 * ori;
1791 }
else if (i % 6 == 2) {
1792 return d_s_r * rotate_m120_c * dia2 * ori;
1793 }
else if (i % 6 == 3) {
1794 return d_s_r * rotate_180_c * dia3 * ori;
1795 }
else if (i % 6 == 4) {
1796 return d_s_r * rotate_120_c * dia4 * ori;
1797 }
else if (i % 6 == 5) {
1798 return d_s_r * rotate_60_c * dia5 * ori;
1807 Geom::Affine dia1, dia2, dia3, dia4, dia5, dia6, dia7, dia8, dia9, dia10;
1819 dia10 = dia6 * dia4.
inverse();
1821 ori =
Geom::Affine(
Geom::Translate (4*h * cos30 * pow((i/12 + 0.5*(j%2)), shiftx_exp) +
dx, (2*h + 2*h * sin30) * pow(j, shifty_exp) + dy));
1831 dia10 = dia6 * dia4.
inverse();
1835 }
else if (i % 12 == 1) {
1836 return d_s_r * flip_y * rotate_m60_c * dia1 * ori;
1837 }
else if (i % 12 == 2) {
1838 return d_s_r * rotate_m60_c * dia2 * ori;
1839 }
else if (i % 12 == 3) {
1840 return d_s_r * flip_y * rotate_m120_c * dia3 * ori;
1841 }
else if (i % 12 == 4) {
1842 return d_s_r * rotate_m120_c * dia4 * ori;
1843 }
else if (i % 12 == 5) {
1844 return d_s_r * flip_x * dia5 * ori;
1845 }
else if (i % 12 == 6) {
1846 return d_s_r * flip_x * flip_y * dia6 * ori;
1847 }
else if (i % 12 == 7) {
1848 return d_s_r * flip_y * rotate_120_c * dia7 * ori;
1849 }
else if (i % 12 == 8) {
1850 return d_s_r * rotate_120_c * dia8 * ori;
1851 }
else if (i % 12 == 9) {
1852 return d_s_r * flip_y * rotate_60_c * dia9 * ori;
1853 }
else if (i % 12 == 10) {
1854 return d_s_r * rotate_60_c * dia10 * ori;
1855 }
else if (i % 12 == 11) {
2094 _status->set_markup(_(
"<small>Creating tiled clones...</small>"));
2100 std::cerr <<
"CloneTiler::clonetile_apply(): No object in single item selection!!!" << std::endl;
2104 const char *id_href = g_strdup_printf(
"#%s", obj_repr->
attribute(
"id"));
2195 auto item = cast<SPItem>(obj);
2207 obj_repr->
attribute(
"inkscape:tile-w") &&
2208 obj_repr->
attribute(
"inkscape:tile-h") &&
2209 obj_repr->
attribute(
"inkscape:tile-x0") &&
2210 obj_repr->
attribute(
"inkscape:tile-y0") &&
2211 obj_repr->
attribute(
"inkscape:tile-cx") &&
2212 obj_repr->
attribute(
"inkscape:tile-cy")) {
2223 bool prefs_bbox = prefs->
getBool(
"/tools/bounding_box",
false);
2228 w = scale_units*r->dimensions()[
Geom::X];
2229 h = scale_units*r->dimensions()[
Geom::Y];
2230 x0 = scale_units*r->min()[
Geom::X];
2231 y0 = scale_units*r->min()[
Geom::Y];
2249 double perimeter_original = (
w + h)/4;
2255 (fabs(cur[
Geom::X]) < fillwidth && i < 200)
2260 (fabs(cur[
Geom::Y]) < fillheight && j < 200)
2268 shiftx_per_i, shifty_per_i,
2269 shiftx_per_j, shifty_per_j,
2270 shiftx_rand, shifty_rand,
2271 shiftx_exp, shifty_exp,
2272 shiftx_alternate, shifty_alternate,
2273 shiftx_cumulate, shifty_cumulate,
2274 shiftx_excludew, shifty_excludeh,
2275 scalex_per_i, scaley_per_i,
2276 scalex_per_j, scaley_per_j,
2277 scalex_rand, scaley_rand,
2278 scalex_exp, scaley_exp,
2279 scalex_log, scaley_log,
2280 scalex_alternate, scaley_alternate,
2281 scalex_cumulate, scaley_cumulate,
2282 rotate_per_i, rotate_per_j,
2284 rotate_alternatei, rotate_alternatej,
2285 rotate_cumulatei, rotate_cumulatej );
2288 cur = center * t - center;
2295 std::string color_string;
2298 double eff_i = (color_alternatei? (i%2) : (i));
2299 double eff_j = (color_alternatej? (j%2) : (j));
2302 hsl.set(0, hsl[0] + hue_per_i * eff_i + hue_per_j * eff_j + hue_rand * g_random_double_range (-1, 1));
2303 hsl.set(1, hsl[1] + saturation_per_i * eff_i + saturation_per_j * eff_j + saturation_rand * g_random_double_range (-1, 1));
2304 hsl.set(2, hsl[2] + lightness_per_i * eff_i + lightness_per_j * eff_j + lightness_rand * g_random_double_range (-1, 1));
2308 color_string = hsl.toString();
2313 int eff_i = (blur_alternatei? (i%2) : (i));
2314 int eff_j = (blur_alternatej? (j%2) : (j));
2315 blur = (blur_per_i * eff_i + blur_per_j * eff_j + blur_rand * g_random_double_range (-1, 1));
2316 blur = CLAMP (blur, 0, 1);
2320 double opacity = 1.0;
2322 int eff_i = (opacity_alternatei? (i%2) : (i));
2323 int eff_j = (opacity_alternatej? (j%2) : (j));
2324 opacity = 1 - (opacity_per_i * eff_i + opacity_per_j * eff_j + opacity_rand * g_random_double_range (-1, 1));
2325 opacity = CLAMP (opacity, 0, 1);
2341 val = rgba.getOpacity();
2365 if (rand_picked > 0) {
2367 for (
auto i = 0; i < 3; i++)
2371 if (gamma_picked != 0) {
2373 if (gamma_picked > 0)
2374 power = 1/(1 + fabs(gamma_picked));
2376 power = 1 + fabs(gamma_picked);
2378 val = pow (val, power);
2379 for (
auto i = 0; i < 3; i++)
2380 rgba.set(i, pow(rgba[i], power));
2383 if (invert_picked) {
2388 val = CLAMP (val, 0, 1);
2391 if (pick_to_presence) {
2392 if (g_random_double_range (0, 1) > val) {
2399 * parent_transform.
inverse() * t;
2401 if (pick_to_opacity) {
2404 if (pick_to_color) {
2405 color_string = rgba.toString();
2409 if (opacity < 1e-6) {
2413 if (fabs(t[0]) + fabs (t[1]) + fabs(t[2]) + fabs(t[3]) < 1e-6) {
2419 clone->setAttribute(
"x",
"0");
2420 clone->setAttribute(
"y",
"0");
2421 clone->setAttribute(
"inkscape:tiled-clone-of", id_href);
2422 clone->setAttribute(
"xlink:href", id_href);
2425 bool center_set =
false;
2426 if (obj_repr->
attribute(
"inkscape:transform-center-x") || obj_repr->
attribute(
"inkscape:transform-center-y")) {
2433 if (opacity < 1.0) {
2434 clone->setAttributeCssDouble(
"opacity", opacity);
2437 if (!color_string.empty()) {
2438 clone->setAttribute(
"fill", color_string);
2439 clone->setAttribute(
"stroke", color_string);
2443 parent->getRepr()->appendChild(clone);
2447 auto item = cast<SPItem>(clone_object);
2448 double radius = blur * perimeter_original * t.
descrim();
2459 auto item = cast<SPItem>(clone_object);
2460 if (clone_object &&
item) {
Geom::Affine get_transform(int type, int i, int j, double cx, double cy, double w, double h, double shiftx_per_i, double shifty_per_i, double shiftx_per_j, double shifty_per_j, double shiftx_rand, double shifty_rand, double shiftx_exp, double shifty_exp, int shiftx_alternate, int shifty_alternate, int shiftx_cumulate, int shifty_cumulate, int shiftx_excludew, int shifty_excludeh, double scalex_per_i, double scaley_per_i, double scalex_per_j, double scaley_per_j, double scalex_rand, double scaley_rand, double scalex_exp, double scaley_exp, double scalex_log, double scaley_log, int scalex_alternate, int scaley_alternate, int scalex_cumulate, int scaley_cumulate, double rotate_per_i, double rotate_per_j, double rotate_rand, int rotate_alternatei, int rotate_alternatej, int rotate_cumulatei, int rotate_cumulatej)