1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3 * Copyright (C) Johan Engelen 2007 <j.b.c.engelen@utwente.nl>
4 *
5 * Released under GNU GPL v2+, read the file 'COPYING' for more information.
6 */
7
8 #include "ui/widget/registered-widget.h"
9 #include "live_effects/parameter/random.h"
10 #include "live_effects/effect.h"
11 #include <glibmm/i18n.h>
12 #include "svg/svg.h"
13 #include "ui/widget/random.h"
14
15 #include "svg/stringstream.h"
16
17 #include "verbs.h"
18
19 #define noLPERANDOMPARAM_DEBUG
20
21 namespace Inkscape {
22
23 namespace LivePathEffect {
24
25
RandomParam(const Glib::ustring & label,const Glib::ustring & tip,const Glib::ustring & key,Inkscape::UI::Widget::Registry * wr,Effect * effect,gdouble default_value,long default_seed)26 RandomParam::RandomParam( const Glib::ustring& label, const Glib::ustring& tip,
27 const Glib::ustring& key, Inkscape::UI::Widget::Registry* wr,
28 Effect* effect, gdouble default_value, long default_seed)
29 : Parameter(label, tip, key, wr, effect)
30 {
31 defvalue = default_value;
32 value = defvalue;
33 min = -Geom::infinity();
34 max = Geom::infinity();
35 integer = false;
36
37 defseed = default_seed;
38 startseed = defseed;
39 seed = startseed;
40 }
41
42 RandomParam::~RandomParam()
43 = default;
44
45 bool
param_readSVGValue(const gchar * strvalue)46 RandomParam::param_readSVGValue(const gchar * strvalue)
47 {
48 double newval, newstartseed;
49 gchar** stringarray = g_strsplit (strvalue, ";", 2);
50 unsigned int success = sp_svg_number_read_d(stringarray[0], &newval);
51 if (success == 1) {
52 success += sp_svg_number_read_d(stringarray[1], &newstartseed);
53 if (success == 2) {
54 param_set_value(newval, static_cast<long>(newstartseed));
55 } else {
56 param_set_value(newval, defseed);
57 }
58 g_strfreev(stringarray);
59 return true;
60 }
61 g_strfreev(stringarray);
62 return false;
63 }
64
65 Glib::ustring
param_getSVGValue() const66 RandomParam::param_getSVGValue() const
67 {
68 Inkscape::SVGOStringStream os;
69 os << value << ';' << startseed;
70 return os.str();
71 }
72
73 Glib::ustring
param_getDefaultSVGValue() const74 RandomParam::param_getDefaultSVGValue() const
75 {
76 Inkscape::SVGOStringStream os;
77 os << defvalue << ';' << defseed;
78 return os.str();
79 }
80
81 void
param_set_default()82 RandomParam::param_set_default()
83 {
84 param_set_value(defvalue, defseed);
85 }
86
87 void
param_update_default(gdouble default_value)88 RandomParam::param_update_default(gdouble default_value){
89 defvalue = default_value;
90 }
91
92 void
param_update_default(const gchar * default_value)93 RandomParam::param_update_default(const gchar * default_value){
94 double newval;
95 unsigned int success = sp_svg_number_read_d(default_value, &newval);
96 if (success == 1) {
97 param_update_default(newval);
98 }
99 }
100
101 void
param_set_value(gdouble val,long newseed)102 RandomParam::param_set_value(gdouble val, long newseed)
103 {
104 value = val;
105 if (integer)
106 value = round(value);
107 if (value > max)
108 value = max;
109 if (value < min)
110 value = min;
111
112 startseed = setup_seed(newseed);
113 seed = startseed;
114 }
115
116 void
param_set_range(gdouble min,gdouble max)117 RandomParam::param_set_range(gdouble min, gdouble max)
118 {
119 this->min = min;
120 this->max = max;
121 }
122
123 void
param_make_integer(bool yes)124 RandomParam::param_make_integer(bool yes)
125 {
126 integer = yes;
127 }
128
129 void
resetRandomizer()130 RandomParam::resetRandomizer()
131 {
132 seed = startseed;
133 }
134
135
136 Gtk::Widget *
param_newWidget()137 RandomParam::param_newWidget()
138 {
139 Inkscape::UI::Widget::RegisteredRandom* regrandom = Gtk::manage(
140 new Inkscape::UI::Widget::RegisteredRandom( param_label,
141 param_tooltip,
142 param_key,
143 *param_wr,
144 param_effect->getRepr(),
145 param_effect->getSPDoc() ) );
146
147 regrandom->setValue(value, startseed);
148 if (integer) {
149 regrandom->setDigits(0);
150 regrandom->setIncrements(1, 10);
151 }
152 regrandom->setRange(min, max);
153 regrandom->setProgrammatically = false;
154 regrandom->signal_button_release_event().connect(sigc::mem_fun (*this, &RandomParam::on_button_release));
155
156 regrandom->set_undo_parameters(SP_VERB_DIALOG_LIVE_PATH_EFFECT, _("Change random parameter"));
157
158 return dynamic_cast<Gtk::Widget *> (regrandom);
159 }
160
on_button_release(GdkEventButton * button_event)161 bool RandomParam::on_button_release(GdkEventButton* button_event) {
162 param_effect->refresh_widgets = true;
163 return false;
164 }
165
operator gdouble()166 RandomParam::operator gdouble()
167 {
168 return rand() * value;
169 };
170
171 /* RNG stolen from /display/nr-filter-turbulence.cpp */
172 #define RAND_m 2147483647 /* 2**31 - 1 */
173 #define RAND_a 16807 /* 7**5; primitive root of m */
174 #define RAND_q 127773 /* m / a */
175 #define RAND_r 2836 /* m % a */
176 #define BSize 0x100
177
178 long
setup_seed(long lSeed)179 RandomParam::setup_seed(long lSeed)
180 {
181 if (lSeed <= 0) lSeed = -(lSeed % (RAND_m - 1)) + 1;
182 if (lSeed > RAND_m - 1) lSeed = RAND_m - 1;
183 return lSeed;
184 }
185
186 // generates random number between 0 and 1
187 gdouble
rand()188 RandomParam::rand()
189 {
190 long result;
191 result = RAND_a * (seed % RAND_q) - RAND_r * (seed / RAND_q);
192 if (result <= 0) result += RAND_m;
193 seed = result;
194
195 gdouble dresult = (gdouble)(result % BSize) / BSize;
196 return dresult;
197 }
198
199
200 } /* namespace LivePathEffect */
201 } /* namespace Inkscape */
202
203 /*
204 Local Variables:
205 mode:c++
206 c-file-style:"stroustrup"
207 c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
208 indent-tabs-mode:nil
209 fill-column:99
210 End:
211 */
212 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :
213