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