Code

Spray Tool by the students at Ecole Centrale de Lyon, Lyon, France
authorJosh Andler <scislac@gmail.com>
Mon, 30 Nov 2009 20:53:48 +0000 (12:53 -0800)
committerJosh Andler <scislac@gmail.com>
Mon, 30 Nov 2009 20:53:48 +0000 (12:53 -0800)
22 files changed:
AUTHORS
share/icons/icons.svg
src/Makefile_insert
src/pixmaps/cursor-spray-move.xpm [new file with mode: 0644]
src/pixmaps/cursor-spray.xpm [new file with mode: 0644]
src/preferences-skeleton.h
src/spray-context.cpp [new file with mode: 0644]
src/spray-context.h [new file with mode: 0644]
src/tools-switch.cpp
src/tools-switch.h
src/ui/dialog/Makefile_insert
src/ui/dialog/dialog-manager.cpp
src/ui/dialog/inkscape-preferences.cpp
src/ui/dialog/inkscape-preferences.h
src/ui/dialog/spray-option.cpp [new file with mode: 0644]
src/ui/dialog/spray-option.h [new file with mode: 0644]
src/ui/icon-names.h
src/ui/view/edit-widget.cpp
src/ui/view/edit-widget.h
src/verbs.cpp
src/verbs.h
src/widgets/toolbox.cpp

diff --git a/AUTHORS b/AUTHORS
index fcea87043fa1c95fc813764ca125f0a69498ea04..d498ff98a7977d9c289f27cf6b43623a9e88bc46 100644 (file)
--- a/AUTHORS
+++ b/AUTHORS
@@ -1,5 +1,6 @@
 Maximilian Albert
 Josh Andler
+Pierre Barbry-Blot
 Jean-François Barraud
 Bill Baxter
 John Bintz
@@ -17,6 +18,7 @@ Marcus Brubaker
 Luca Bruno
 Nicu Buculei
 Bulia Byak
+Pierre Caclin
 Ian Caldwell
 Gail Carmichael
 Ed Catmur
@@ -76,11 +78,15 @@ Jason Kivlighn
 Adrian Knoth
 Krzysztof Kosiński
 Petr Kovar
+Benoît Lavorata
+Julien Leray
 Raph Levien
 Diederik van Lierop
 Nicklas Lindgren
 Vitaly Lipatov
 Ivan Louette
+Pierre-Antoine Marc
+Aurel-Aimé Marmion
 Colin Marquardt
 Dmitry G. Mastrukov
 Matiphas
@@ -88,6 +94,7 @@ Michael Meeks
 Federico Mena
 MenTaLguY
 Aubanel Monnier
+Vincent Montagne
 Tim Mooney
 Derek P. Moore
 Peter Moulder
index dd0fe6068aa804ed4db48b7d2a5562894ce770a9..baa74483a77de2382d8a4091073c7c5f7b760ef4 100644 (file)
@@ -8,7 +8,7 @@
    xmlns:xlink="http://www.w3.org/1999/xlink"
    xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
    xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
-   inkscape:version="0.46+devel r21165 custom"
+   inkscape:version="0.47+devel"
    sodipodi:docname="icons.svg"
    height="540"
    width="1250"
        gradientUnits="userSpaceOnUse"
        id="linearGradient3740"
        inkscape:collect="always" />
+    <linearGradient
+       x1="148.57143"
+       y1="580.93359"
+       x2="403.95001"
+       y2="556.64789"
+       id="linearGradient9514-8"
+       xlink:href="#linearGradient3550-4"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(0.6307248,-0.78569617,0.65179606,0.51329457,256.28855,114.28429)" />
+    <linearGradient
+       id="linearGradient3550-4">
+      <stop
+         id="stop3552-6"
+         style="stop-color:#8b9174;stop-opacity:1"
+         offset="0" />
+      <stop
+         id="stop3554-9"
+         style="stop-color:#ffffff;stop-opacity:1"
+         offset="1" />
+    </linearGradient>
+    <linearGradient
+       x1="348.60065"
+       y1="338.07721"
+       x2="375.36154"
+       y2="318.01028"
+       id="linearGradient6466-2"
+       xlink:href="#linearGradient3185-9"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="translate(19.052029,-3.0895185)" />
+    <linearGradient
+       id="linearGradient3185-9">
+      <stop
+         id="stop3187-0"
+         style="stop-color:#189415;stop-opacity:1"
+         offset="0" />
+      <stop
+         id="stop3189-3"
+         style="stop-color:#2be126;stop-opacity:1"
+         offset="1" />
+    </linearGradient>
+    <linearGradient
+       x1="348.60065"
+       y1="338.07721"
+       x2="375.36154"
+       y2="318.01028"
+       id="linearGradient6468-0"
+       xlink:href="#linearGradient3185-9"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="translate(4.119358,37.589137)" />
+    <linearGradient
+       x1="348.60065"
+       y1="338.07721"
+       x2="375.36154"
+       y2="318.01028"
+       id="linearGradient6563-3"
+       xlink:href="#linearGradient3185-9"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="translate(28.320583,70.029077)" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient3185-9"
+       id="linearGradient5783-6-3"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(0.8269532,0,0,0.8236011,90.718402,44.233294)"
+       x1="348.60065"
+       y1="338.07721"
+       x2="375.36154"
+       y2="318.01028" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient3185-9"
+       id="linearGradient6583-7"
+       x1="371.23682"
+       y1="322.88614"
+       x2="395.26917"
+       y2="322.88614"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="translate(0.33790588,-0.16552734)" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient3550-8-4"
+       id="linearGradient7199-9"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(0.03020671,-0.0376286,0.03121585,0.02458273,840.07621,-472.64274)"
+       x1="148.57143"
+       y1="580.93359"
+       x2="403.95001"
+       y2="556.64789" />
+    <linearGradient
+       id="linearGradient3550-8-4">
+      <stop
+         id="stop3552-7-9"
+         style="stop-color:#d01e1e;stop-opacity:1;"
+         offset="0" />
+      <stop
+         offset="0.25"
+         style="stop-color:#d24949;stop-opacity:1;"
+         id="stop7121-9" />
+      <stop
+         offset="0.5"
+         style="stop-color:#d57575;stop-opacity:1;"
+         id="stop7119-1" />
+      <stop
+         id="stop3554-0-9"
+         style="stop-color:#dacccc;stop-opacity:1;"
+         offset="1" />
+    </linearGradient>
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient3466-1-2"
+       id="linearGradient7201-4"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(0.78857386,0.7805965,-0.7805965,0.78857386,713.6582,12.339179)"
+       x1="337.11661"
+       y1="117.24895"
+       x2="338.0838"
+       y2="126.52245" />
+    <linearGradient
+       id="linearGradient3466-1-2">
+      <stop
+         id="stop3468-8-0"
+         style="stop-color:#ffffff;stop-opacity:1"
+         offset="0" />
+      <stop
+         id="stop3470-9-6"
+         style="stop-color:#a0a0a0;stop-opacity:1"
+         offset="1" />
+    </linearGradient>
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient5704-6-9"
+       id="linearGradient7203-5"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(0.00564085,1.1095707,-1.1095707,0.00564085,1019.2742,0.51541278)"
+       x1="332.87787"
+       y1="121.99369"
+       x2="336.84845"
+       y2="124.19406" />
+    <linearGradient
+       id="linearGradient5704-6-9">
+      <stop
+         id="stop5706-5-5"
+         style="stop-color:#5a5a5a;stop-opacity:1"
+         offset="0" />
+      <stop
+         id="stop5708-5-6"
+         style="stop-color:#000000;stop-opacity:1"
+         offset="1" />
+    </linearGradient>
   </defs>
   <sodipodi:namedview
      inkscape:guide-bbox="true"
      inkscape:window-x="0"
      inkscape:window-height="737"
      inkscape:window-width="1024"
-     inkscape:cy="439.31911"
-     inkscape:cx="846.86933"
-     inkscape:zoom="2.7464742"
+     inkscape:cy="118.75673"
+     inkscape:cx="458.6199"
+     inkscape:zoom="1.9420505"
      gridtolerance="6"
      snaptogrid="false"
      showgrid="true"
      inkscape:snap-midpoints="false"
      inkscape:snap-intersection-paths="false"
      inkscape:object-paths="false"
-     inkscape:snap-object-midpoints="false">
+     inkscape:snap-object-midpoints="false"
+     inkscape:window-maximized="0">
     <inkscape:grid
        type="xygrid"
        id="grid9252"
@@ -19650,4 +19800,512 @@ http://www.inkscape.org/</dc:description>
          d="m 910.68469,121.666 c 0.89363,0.12497 1.4826,1.05773 1.2925,1.92328 -0.0941,1.00279 -1.11367,1.5906 -2.04198,1.62018 -0.72256,0.0699 -1.45173,-0.0589 -2.13313,-0.29781 0,-0.27759 0,-0.55517 0,-0.83276 0.83664,0.45611 1.92451,0.60201 2.80073,0.17757 0.80169,-0.43444 0.69059,-1.81155 -0.19684,-2.08095 -0.48076,-0.18386 -1.00008,-0.10942 -1.50209,-0.12512 0,-0.2363 0,-0.47261 0,-0.70891 0.6676,-0.0288 1.50939,0.14892 1.9565,-0.47536 0.4177,-0.66094 -0.14468,-1.53437 -0.90782,-1.51097 -0.66571,-0.0681 -1.33009,0.0928 -1.95831,0.2995 0,-0.25623 0,-0.51247 0,-0.7687 1.08005,-0.28661 2.40764,-0.52909 3.35334,0.23188 0.80208,0.64443 0.62653,2.14224 -0.3992,2.46393 l -0.12785,0.0456 -0.13585,0.0387" />
     </g>
   </g>
+  <g
+     transform="matrix(0.04789205,0,0,0.04789205,455.86867,510.0249)"
+     id="tool-spray">
+    <g
+       transform="matrix(-0.94143174,-0.33720363,-0.33720363,0.94143174,720.80661,-81.205214)"
+       id="g9509">
+      <path
+         d="m 438.15602,87.082496 -55.9059,66.568004 22.80746,20.82679 36.56243,-43.53544 c -1.294,-3.25228 -0.58217,-7.44694 2.10329,-10.64455 2.68545,-3.19761 6.57911,-4.48676 9.84153,-3.57832 l 7.39866,-8.80969 -22.80747,-20.826794 z"
+         id="rect2774-1"
+         style="fill:#cccccc;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:2.24399996;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
+      <path
+         d="m 314.28571,330.93362 a 135.71428,135.71428 0 1 1 -271.428563,0 135.71428,135.71428 0 1 1 271.428563,0 z"
+         transform="matrix(0.43213144,0.39460388,-0.4413757,0.52555273,428.57034,-40.143962)"
+         id="path2776"
+         style="fill:#b8b8b8;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:11.57818031;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
+      <rect
+         width="159.96521"
+         height="287.74951"
+         x="327.78137"
+         y="-119.49641"
+         transform="matrix(0.73844372,0.67431511,-0.6431164,0.76576844,0,0)"
+         id="rect2774-3"
+         style="fill:url(#linearGradient9514-8);fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:7.22261095;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
+    </g>
+    <g
+       transform="matrix(-0.7512503,-0.20129692,-0.20129692,0.7512503,613.4079,-111.64166)"
+       id="g9516">
+      <path
+         d="m 581.84786,283.6361 0.24239,11.1012 9.28231,6.09376 -10.48296,3.66098 -2.92713,10.71108 -6.72121,-8.83858 -11.09137,0.52604 6.32902,-9.12352 -3.92772,-10.38597 10.63277,3.19994 8.6639,-6.94493 z"
+         transform="matrix(0.47520756,0.70195011,-0.67326918,0.49534453,466.98533,-132.476)"
+         id="path3599"
+         style="fill:#ffff00;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:2.62631679;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
+      <path
+         d="m 581.84786,283.6361 0.24239,11.1012 9.28231,6.09376 -10.48296,3.66098 -2.92713,10.71108 -6.72121,-8.83858 -11.09137,0.52604 6.32902,-9.12352 -3.92772,-10.38597 10.63277,3.19994 8.6639,-6.94493 z"
+         transform="matrix(0.23528449,0.67141567,-0.64400457,0.24522185,681.59007,-129.97399)"
+         id="path3601"
+         style="fill:#ffff00;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:2.62631679;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
+      <path
+         d="m 581.84786,283.6361 0.24239,11.1012 9.28231,6.09376 -10.48296,3.66098 -2.92713,10.71108 -6.72121,-8.83858 -11.09137,0.52604 6.32902,-9.12352 -3.92772,-10.38597 10.63277,3.19994 8.6639,-6.94493 z"
+         transform="matrix(0.55375067,0.61475467,-0.5896225,0.57723652,476.58624,-132.31409)"
+         id="path3603"
+         style="fill:#ffff00;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:2.62631679;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
+      <path
+         d="m 581.84786,283.6361 0.24239,11.1012 9.28231,6.09376 -10.48296,3.66098 -2.92713,10.71108 -6.72121,-8.83858 -11.09137,0.52604 6.32902,-9.12352 -3.92772,-10.38597 10.63277,3.19994 8.6639,-6.94493 z"
+         transform="matrix(0.33445431,0.65112443,-0.62453097,0.34861091,652.26955,-183.56984)"
+         id="path3605"
+         style="fill:#ffff00;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:2.62631679;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
+      <path
+         d="m 581.84786,283.6361 0.24239,11.1012 9.28231,6.09376 -10.48296,3.66098 -2.92713,10.71108 -6.72121,-8.83858 -11.09137,0.52604 6.32902,-9.12352 -3.92772,-10.38597 10.63277,3.19994 8.6639,-6.94493 z"
+         transform="matrix(0.27828,0.74781303,-0.7172813,0.29003798,627.53269,-164.64526)"
+         id="path3607"
+         style="fill:#ffff00;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:2.62631679;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
+      <path
+         d="m 581.84786,283.6361 0.24239,11.1012 9.28231,6.09376 -10.48296,3.66098 -2.92713,10.71108 -6.72121,-8.83858 -11.09137,0.52604 6.32902,-9.12352 -3.92772,-10.38597 10.63277,3.19994 8.6639,-6.94493 z"
+         transform="matrix(0.49032601,0.68961049,-0.66143135,0.51110713,640.27079,-195.75188)"
+         id="path3609"
+         style="fill:#ffff00;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:2.62631679;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
+      <path
+         d="m 581.84786,283.6361 0.24239,11.1012 9.28231,6.09376 -10.48296,3.66098 -2.92713,10.71108 -6.72121,-8.83858 -11.09137,0.52604 6.32902,-9.12352 -3.92772,-10.38597 10.63277,3.19994 8.6639,-6.94493 z"
+         transform="matrix(0.41674056,0.57738271,-0.55371602,0.43455271,467.75556,-241.39201)"
+         id="path3611"
+         style="fill:#ffff00;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:2.29145432;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
+      <path
+         d="m 581.84786,283.6361 0.24239,11.1012 9.28231,6.09376 -10.48296,3.66098 -2.92713,10.71108 -6.72121,-8.83858 -11.09137,0.52604 6.32902,-9.12352 -3.92772,-10.38597 10.63277,3.19994 8.6639,-6.94493 z"
+         transform="matrix(0.55251369,0.61604388,-0.59085924,0.5759468,474.99185,-135.85699)"
+         id="path3613"
+         style="fill:#ffff00;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:2.62631679;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
+      <path
+         d="m 581.84786,283.6361 0.24239,11.1012 9.28231,6.09376 -10.48296,3.66098 -2.92713,10.71108 -6.72121,-8.83858 -11.09137,0.52604 6.32902,-9.12352 -3.92772,-10.38597 10.63277,3.19994 8.6639,-6.94493 z"
+         transform="matrix(0.47258702,0.4856349,-0.46577779,0.49263449,374.91635,-122.028)"
+         id="path3615"
+         style="fill:#ffff00;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:2.62631679;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
+      <path
+         d="m 581.84786,283.6361 0.24239,11.1012 9.28231,6.09376 -10.48296,3.66098 -2.92713,10.71108 -6.72121,-8.83858 -11.09137,0.52604 6.32902,-9.12352 -3.92772,-10.38597 10.63277,3.19994 8.6639,-6.94493 z"
+         transform="matrix(0.49703855,0.58813893,-0.56409817,0.51811541,576.10428,-185.32735)"
+         id="path3617"
+         style="fill:#ffff00;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:2.62631679;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
+      <path
+         d="m 581.84786,283.6361 0.24239,11.1012 9.28231,6.09376 -10.48296,3.66098 -2.92713,10.71108 -6.72121,-8.83858 -11.09137,0.52604 6.32902,-9.12352 -3.92772,-10.38597 10.63277,3.19994 8.6639,-6.94493 z"
+         transform="matrix(0.31461336,0.79763843,-0.76507062,0.32791137,543.40186,-108.86608)"
+         id="path3619"
+         style="fill:#ffff00;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:2.62631679;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
+      <path
+         d="m 581.84786,283.6361 0.24239,11.1012 9.28231,6.09376 -10.48296,3.66098 -2.92713,10.71108 -6.72121,-8.83858 -11.09137,0.52604 6.32902,-9.12352 -3.92772,-10.38597 10.63277,3.19994 8.6639,-6.94493 z"
+         transform="matrix(0.43193517,0.73167878,-0.70178959,0.45022897,489.14342,-132.12767)"
+         id="path3621"
+         style="fill:#ffff00;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:2.62631679;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
+      <path
+         d="m 581.84786,283.6361 0.24239,11.1012 9.28231,6.09376 -10.48296,3.66098 -2.92713,10.71108 -6.72121,-8.83858 -11.09137,0.52604 6.32902,-9.12352 -3.92772,-10.38597 10.63277,3.19994 8.6639,-6.94493 z"
+         transform="matrix(0.40456762,0.62087357,-0.59550694,0.42170884,630.76331,-168.65799)"
+         id="path3623"
+         style="fill:#ffff00;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:2.62631679;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
+      <path
+         d="m 581.84786,283.6361 0.24239,11.1012 9.28231,6.09376 -10.48296,3.66098 -2.92713,10.71108 -6.72121,-8.83858 -11.09137,0.52604 6.32902,-9.12352 -3.92772,-10.38597 10.63277,3.19994 8.6639,-6.94493 z"
+         transform="matrix(0.57353443,0.59247606,-0.56825063,0.59786383,455.6305,-132.04336)"
+         id="path3625"
+         style="fill:#ffff00;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:2.62631679;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
+      <path
+         d="m 581.84786,283.6361 0.24239,11.1012 9.28231,6.09376 -10.48296,3.66098 -2.92713,10.71108 -6.72121,-8.83858 -11.09137,0.52604 6.32902,-9.12352 -3.92772,-10.38597 10.63277,3.19994 8.6639,-6.94493 z"
+         transform="matrix(0.63006282,0.56602991,-0.54287749,0.65679877,459.86442,-107.56064)"
+         id="path3627"
+         style="fill:#ffff00;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:2.62631679;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
+      <path
+         d="m 581.84786,283.6361 0.24239,11.1012 9.28231,6.09376 -10.48296,3.66098 -2.92713,10.71108 -6.72121,-8.83858 -11.09137,0.52604 6.32902,-9.12352 -3.92772,-10.38597 10.63277,3.19994 8.6639,-6.94493 z"
+         transform="matrix(-0.1983519,0.82551639,-0.79186345,-0.20687051,898.06846,25.460342)"
+         id="path3629"
+         style="fill:#ffff00;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:2.62631679;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
+      <path
+         d="m 581.84786,283.6361 0.24239,11.1012 9.28231,6.09376 -10.48296,3.66098 -2.92713,10.71108 -6.72121,-8.83858 -11.09137,0.52604 6.32902,-9.12352 -3.92772,-10.38597 10.63277,3.19994 8.6639,-6.94493 z"
+         transform="matrix(-0.2458629,0.8135784,-0.78041723,-0.2564007,918.63978,42.528998)"
+         id="path3631"
+         style="fill:#ffff00;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:2.62631679;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
+      <path
+         d="m 581.84786,283.6361 0.24239,11.1012 9.28231,6.09376 -10.48296,3.66098 -2.92713,10.71108 -6.72121,-8.83858 -11.09137,0.52604 6.32902,-9.12352 -3.92772,-10.38597 10.63277,3.19994 8.6639,-6.94493 z"
+         transform="matrix(0.31409671,0.667486,-0.6402272,0.32738595,614.15155,-150.39368)"
+         id="path3633"
+         style="fill:#ffff00;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:2.62631679;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
+      <path
+         d="m 581.84786,283.6361 0.24239,11.1012 9.28231,6.09376 -10.48296,3.66098 -2.92713,10.71108 -6.72121,-8.83858 -11.09137,0.52604 6.32902,-9.12352 -3.92772,-10.38597 10.63277,3.19994 8.6639,-6.94493 z"
+         transform="matrix(0.03063804,0.72511034,-0.69552978,0.03186738,816.92733,-126.20221)"
+         id="path3635"
+         style="fill:#ffff00;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:2.62631679;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
+      <path
+         d="m 581.84786,283.6361 0.24239,11.1012 9.28231,6.09376 -10.48296,3.66098 -2.92713,10.71108 -6.72121,-8.83858 -11.09137,0.52604 6.32902,-9.12352 -3.92772,-10.38597 10.63277,3.19994 8.6639,-6.94493 z"
+         transform="matrix(0.46033764,0.57656967,-0.55300455,0.47985498,482.13936,-194.03029)"
+         id="path3637"
+         style="fill:#ffff00;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:2.62631679;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
+      <path
+         d="m 581.84786,283.6361 0.24239,11.1012 9.28231,6.09376 -10.48296,3.66098 -2.92713,10.71108 -6.72121,-8.83858 -11.09137,0.52604 6.32902,-9.12352 -3.92772,-10.38597 10.63277,3.19994 8.6639,-6.94493 z"
+         transform="matrix(0.60162945,0.55546522,-0.53269692,0.62734404,401.99584,-244.95759)"
+         id="path3639"
+         style="fill:#ffff00;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:2.29145432;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
+      <path
+         d="m 581.84786,283.6361 0.24239,11.1012 9.28231,6.09376 -10.48296,3.66098 -2.92713,10.71108 -6.72121,-8.83858 -11.09137,0.52604 6.32902,-9.12352 -3.92772,-10.38597 10.63277,3.19994 8.6639,-6.94493 z"
+         transform="matrix(0.52595624,0.60244374,-0.57781654,0.54826139,579.5719,-185.82295)"
+         id="path3641"
+         style="fill:#ffff00;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:2.62631679;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
+      <path
+         d="m 581.84786,283.6361 0.24239,11.1012 9.28231,6.09376 -10.48296,3.66098 -2.92713,10.71108 -6.72121,-8.83858 -11.09137,0.52604 6.32902,-9.12352 -3.92772,-10.38597 10.63277,3.19994 8.6639,-6.94493 z"
+         transform="matrix(0.37305621,0.58918111,-0.56511041,0.38886063,581.3744,-126.97008)"
+         id="path3643"
+         style="fill:#ffff00;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:2.62631679;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
+      <path
+         d="m 581.84786,283.6361 0.24239,11.1012 9.28231,6.09376 -10.48296,3.66098 -2.92713,10.71108 -6.72121,-8.83858 -11.09137,0.52604 6.32902,-9.12352 -3.92772,-10.38597 10.63277,3.19994 8.6639,-6.94493 z"
+         transform="matrix(0.39417287,0.62024258,-0.59490274,0.41087214,579.31683,-134.01961)"
+         id="path3645"
+         style="fill:#ffff00;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:2.62631679;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
+      <path
+         d="m 581.84786,283.6361 0.24239,11.1012 9.28231,6.09376 -10.48296,3.66098 -2.92713,10.71108 -6.72121,-8.83858 -11.09137,0.52604 6.32902,-9.12352 -3.92772,-10.38597 10.63277,3.19994 8.6639,-6.94493 z"
+         transform="matrix(0.37494905,0.58206185,-0.55828136,0.39083469,618.05277,-126.73792)"
+         id="path3647"
+         style="fill:#ffff00;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:2.62631679;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
+      <path
+         d="m 581.84786,283.6361 0.24239,11.1012 9.28231,6.09376 -10.48296,3.66098 -2.92713,10.71108 -6.72121,-8.83858 -11.09137,0.52604 6.32902,-9.12352 -3.92772,-10.38597 10.63277,3.19994 8.6639,-6.94493 z"
+         transform="matrix(0.47220324,0.5168641,-0.49567804,0.49238595,366.51392,-220.32748)"
+         id="path3649"
+         style="fill:#ffff00;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:2.29145432;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
+      <path
+         d="m 581.84786,283.6361 0.24239,11.1012 9.28231,6.09376 -10.48296,3.66098 -2.92713,10.71108 -6.72121,-8.83858 -11.09137,0.52604 6.32902,-9.12352 -3.92772,-10.38597 10.63277,3.19994 8.6639,-6.94493 z"
+         transform="matrix(0.55637359,0.6434196,-0.61711791,0.57996807,367.16353,-109.78265)"
+         id="path3651"
+         style="fill:#ffff00;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:2.62631679;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
+      <path
+         d="m 581.84786,283.6361 0.24239,11.1012 9.28231,6.09376 -10.48296,3.66098 -2.92713,10.71108 -6.72121,-8.83858 -11.09137,0.52604 6.32902,-9.12352 -3.92772,-10.38597 10.63277,3.19994 8.6639,-6.94493 z"
+         transform="matrix(0.56655772,0.57316188,-0.54972499,0.59059241,521.88966,-141.55567)"
+         id="path3653"
+         style="fill:#ffff00;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:2.62631679;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
+      <path
+         d="m 581.84786,283.6361 0.24239,11.1012 9.28231,6.09376 -10.48296,3.66098 -2.92713,10.71108 -6.72121,-8.83858 -11.09137,0.52604 6.32902,-9.12352 -3.92772,-10.38597 10.63277,3.19994 8.6639,-6.94493 z"
+         transform="matrix(0.61514533,0.73099436,-0.70103119,0.64143761,496.58722,-369.79801)"
+         id="path3655"
+         style="fill:#ffff00;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:2.29145432;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
+      <path
+         d="m 581.84786,283.6361 0.24239,11.1012 9.28231,6.09376 -10.48296,3.66098 -2.92713,10.71108 -6.72121,-8.83858 -11.09137,0.52604 6.32902,-9.12352 -3.92772,-10.38597 10.63277,3.19994 8.6639,-6.94493 z"
+         transform="matrix(0.28771238,0.75147664,-0.72079451,0.29987111,591.19628,-157.05351)"
+         id="path3657"
+         style="fill:#ffff00;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:2.62631679;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
+      <path
+         d="m 581.84786,283.6361 0.24239,11.1012 9.28231,6.09376 -10.48296,3.66098 -2.92713,10.71108 -6.72121,-8.83858 -11.09137,0.52604 6.32902,-9.12352 -3.92772,-10.38597 10.63277,3.19994 8.6639,-6.94493 z"
+         transform="matrix(0.56631856,0.61943061,-0.59410643,0.59033838,303.76998,-208.44611)"
+         id="path3659"
+         style="fill:#ffff00;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:2.62631679;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
+      <path
+         d="m 581.84786,283.6361 0.24239,11.1012 9.28231,6.09376 -10.48296,3.66098 -2.92713,10.71108 -6.72121,-8.83858 -11.09137,0.52604 6.32902,-9.12352 -3.92772,-10.38597 10.63277,3.19994 8.6639,-6.94493 z"
+         transform="matrix(0.4929128,0.52616161,-0.50464934,0.51382051,522.36167,-108.57976)"
+         id="path3661"
+         style="fill:#ffff00;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:2.62631679;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
+      <path
+         d="m 581.84786,283.6361 0.24239,11.1012 9.28231,6.09376 -10.48296,3.66098 -2.92713,10.71108 -6.72121,-8.83858 -11.09137,0.52604 6.32902,-9.12352 -3.92772,-10.38597 10.63277,3.19994 8.6639,-6.94493 z"
+         transform="matrix(0.35098984,0.55235846,-0.52979201,0.36585963,509.19171,-152.16385)"
+         id="path3663"
+         style="fill:#ffff00;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:2.62631679;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
+      <path
+         d="m 581.84786,283.6361 0.24239,11.1012 9.28231,6.09376 -10.48296,3.66098 -2.92713,10.71108 -6.72121,-8.83858 -11.09137,0.52604 6.32902,-9.12352 -3.92772,-10.38597 10.63277,3.19994 8.6639,-6.94493 z"
+         transform="matrix(0.17650292,0.66162285,-0.63461717,0.18394159,748.84341,-122.89488)"
+         id="path3665"
+         style="fill:#ffff00;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:2.62631679;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
+      <path
+         d="m 581.84786,283.6361 0.24239,11.1012 9.28231,6.09376 -10.48296,3.66098 -2.92713,10.71108 -6.72121,-8.83858 -11.09137,0.52604 6.32902,-9.12352 -3.92772,-10.38597 10.63277,3.19994 8.6639,-6.94493 z"
+         transform="matrix(0.42628761,0.5263415,-0.50482865,0.44436207,399.21769,-141.83818)"
+         id="path3667"
+         style="fill:#ffff00;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:2.62631679;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
+      <path
+         d="m 581.84786,283.6361 0.24239,11.1012 9.28231,6.09376 -10.48296,3.66098 -2.92713,10.71108 -6.72121,-8.83858 -11.09137,0.52604 6.32902,-9.12352 -3.92772,-10.38597 10.63277,3.19994 8.6639,-6.94493 z"
+         transform="matrix(0.43287629,0.61015892,-0.58522646,0.45122242,532.45836,-146.29388)"
+         id="path3669"
+         style="fill:#ffff00;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:2.62631679;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
+      <path
+         d="m 581.84786,283.6361 0.24239,11.1012 9.28231,6.09376 -10.48296,3.66098 -2.92713,10.71108 -6.72121,-8.83858 -11.09137,0.52604 6.32902,-9.12352 -3.92772,-10.38597 10.63277,3.19994 8.6639,-6.94493 z"
+         transform="matrix(0.46956225,0.67290143,-0.64540597,0.4894621,434.99739,-55.33732)"
+         id="path3671"
+         style="fill:#ffff00;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:2.62631679;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
+      <path
+         d="m 581.84786,283.6361 0.24239,11.1012 9.28231,6.09376 -10.48296,3.66098 -2.92713,10.71108 -6.72121,-8.83858 -11.09137,0.52604 6.32902,-9.12352 -3.92772,-10.38597 10.63277,3.19994 8.6639,-6.94493 z"
+         transform="matrix(0.43889456,0.63736413,-0.61123882,0.4576536,435.47355,-331.48855)"
+         id="path3673"
+         style="fill:#ffff00;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:2.29145432;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
+      <path
+         d="m 581.84786,283.6361 0.24239,11.1012 9.28231,6.09376 -10.48296,3.66098 -2.92713,10.71108 -6.72121,-8.83858 -11.09137,0.52604 6.32902,-9.12352 -3.92772,-10.38597 10.63277,3.19994 8.6639,-6.94493 z"
+         transform="matrix(0.61360527,0.58953593,-0.56542636,0.63963898,549.16036,-157.74722)"
+         id="path3675"
+         style="fill:#ffff00;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:2.62631679;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
+      <path
+         d="m 581.84786,283.6361 0.24239,11.1012 9.28231,6.09376 -10.48296,3.66098 -2.92713,10.71108 -6.72121,-8.83858 -11.09137,0.52604 6.32902,-9.12352 -3.92772,-10.38597 10.63277,3.19994 8.6639,-6.94493 z"
+         transform="matrix(0.32809642,0.49654591,-0.47625839,0.34199833,468.08659,-119.57341)"
+         id="path3677-9"
+         style="fill:#ffff00;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:2.62631679;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
+      <path
+         d="m 581.84786,283.6361 0.24239,11.1012 9.28231,6.09376 -10.48296,3.66098 -2.92713,10.71108 -6.72121,-8.83858 -11.09137,0.52604 6.32902,-9.12352 -3.92772,-10.38597 10.63277,3.19994 8.6639,-6.94493 z"
+         transform="matrix(-0.08338906,0.76251997,-0.73142503,-0.0870125,820.83709,-79.153239)"
+         id="path3679"
+         style="fill:#ffff00;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:2.62631679;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
+      <path
+         d="m 581.84786,283.6361 0.24239,11.1012 9.28231,6.09376 -10.48296,3.66098 -2.92713,10.71108 -6.72121,-8.83858 -11.09137,0.52604 6.32902,-9.12352 -3.92772,-10.38597 10.63277,3.19994 8.6639,-6.94493 z"
+         transform="matrix(0.10282914,0.76713446,-0.7358324,0.10712414,709.02409,-133.60265)"
+         id="path3681"
+         style="fill:#ffff00;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:2.62631679;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
+      <path
+         d="m 581.84786,283.6361 0.24239,11.1012 9.28231,6.09376 -10.48296,3.66098 -2.92713,10.71108 -6.72121,-8.83858 -11.09137,0.52604 6.32902,-9.12352 -3.92772,-10.38597 10.63277,3.19994 8.6639,-6.94493 z"
+         transform="matrix(0.56922558,0.59684162,-0.57243855,0.59337132,562.50285,-188.35402)"
+         id="path3683"
+         style="fill:#ffff00;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:2.62631679;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
+      <path
+         d="m 581.84786,283.6361 0.24239,11.1012 9.28231,6.09376 -10.48296,3.66098 -2.92713,10.71108 -6.72121,-8.83858 -11.09137,0.52604 6.32902,-9.12352 -3.92772,-10.38597 10.63277,3.19994 8.6639,-6.94493 z"
+         transform="matrix(0.52586224,0.5977614,-0.5733252,0.54816386,570.59228,-195.83416)"
+         id="path3685"
+         style="fill:#ffff00;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:2.62631679;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
+      <path
+         d="m 581.84786,283.6361 0.24239,11.1012 9.28231,6.09376 -10.48296,3.66098 -2.92713,10.71108 -6.72121,-8.83858 -11.09137,0.52604 6.32902,-9.12352 -3.92772,-10.38597 10.63277,3.19994 8.6639,-6.94493 z"
+         transform="matrix(0.34955854,0.49388172,-0.47370069,0.36437339,484.0619,-109.93119)"
+         id="path3687"
+         style="fill:#ffff00;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:2.62631679;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
+      <path
+         d="m 581.84786,283.6361 0.24239,11.1012 9.28231,6.09376 -10.48296,3.66098 -2.92713,10.71108 -6.72121,-8.83858 -11.09137,0.52604 6.32902,-9.12352 -3.92772,-10.38597 10.63277,3.19994 8.6639,-6.94493 z"
+         transform="matrix(0.22819514,0.55936211,-0.53652242,0.23784239,568.03778,-125.28098)"
+         id="path3689"
+         style="fill:#ffff00;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:2.62631679;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
+      <path
+         d="m 581.84786,283.6361 0.24239,11.1012 9.28231,6.09376 -10.48296,3.66098 -2.92713,10.71108 -6.72121,-8.83858 -11.09137,0.52604 6.32902,-9.12352 -3.92772,-10.38597 10.63277,3.19994 8.6639,-6.94493 z"
+         transform="matrix(0.30712819,0.67002137,-0.64265986,0.32012083,666.14384,-189.4803)"
+         id="path3691"
+         style="fill:#ffff00;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:2.62631679;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
+      <path
+         d="m 581.84786,283.6361 0.24239,11.1012 9.28231,6.09376 -10.48296,3.66098 -2.92713,10.71108 -6.72121,-8.83858 -11.09137,0.52604 6.32902,-9.12352 -3.92772,-10.38597 10.63277,3.19994 8.6639,-6.94493 z"
+         transform="matrix(0.40900903,0.62238246,-0.59695383,0.42633897,629.70039,-171.20121)"
+         id="path3693"
+         style="fill:#ffff00;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:2.62631679;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
+      <path
+         d="m 581.84786,283.6361 0.24239,11.1012 9.28231,6.09376 -10.48296,3.66098 -2.92713,10.71108 -6.72121,-8.83858 -11.09137,0.52604 6.32902,-9.12352 -3.92772,-10.38597 10.63277,3.19994 8.6639,-6.94493 z"
+         transform="matrix(0.44879149,0.60505052,-0.58032482,0.46781493,454.95879,-119.24367)"
+         id="path3695"
+         style="fill:#ffff00;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:2.62631679;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
+      <path
+         d="m 581.84786,283.6361 0.24239,11.1012 9.28231,6.09376 -10.48296,3.66098 -2.92713,10.71108 -6.72121,-8.83858 -11.09137,0.52604 6.32902,-9.12352 -3.92772,-10.38597 10.63277,3.19994 8.6639,-6.94493 z"
+         transform="matrix(0.37369945,0.72343719,-0.69378378,0.38967195,480.48271,-367.11927)"
+         id="path3697"
+         style="fill:#ffff00;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:2.29145432;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
+      <path
+         d="m 581.84786,283.6361 0.24239,11.1012 9.28231,6.09376 -10.48296,3.66098 -2.92713,10.71108 -6.72121,-8.83858 -11.09137,0.52604 6.32902,-9.12352 -3.92772,-10.38597 10.63277,3.19994 8.6639,-6.94493 z"
+         transform="matrix(0.26607441,0.68878858,-0.66066572,0.27731935,718.19588,-137.79167)"
+         id="path3699"
+         style="fill:#ffff00;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:2.62631679;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
+      <path
+         d="m 581.84786,283.6361 0.24239,11.1012 9.28231,6.09376 -10.48296,3.66098 -2.92713,10.71108 -6.72121,-8.83858 -11.09137,0.52604 6.32902,-9.12352 -3.92772,-10.38597 10.63277,3.19994 8.6639,-6.94493 z"
+         transform="matrix(0.2757404,0.52962938,-0.50799768,0.28741252,506.63841,-126.75106)"
+         id="path3701"
+         style="fill:#ffff00;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:2.62631679;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
+      <path
+         d="m 581.84786,283.6361 0.24239,11.1012 9.28231,6.09376 -10.48296,3.66098 -2.92713,10.71108 -6.72121,-8.83858 -11.09137,0.52604 6.32902,-9.12352 -3.92772,-10.38597 10.63277,3.19994 8.6639,-6.94493 z"
+         transform="matrix(0.56236328,0.53040763,-0.50871512,0.58622393,431.21262,-210.35965)"
+         id="path3703"
+         style="fill:#ffff00;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:2.62631679;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
+      <path
+         d="m 581.84786,283.6361 0.24239,11.1012 9.28231,6.09376 -10.48296,3.66098 -2.92713,10.71108 -6.72121,-8.83858 -11.09137,0.52604 6.32902,-9.12352 -3.92772,-10.38597 10.63277,3.19994 8.6639,-6.94493 z"
+         transform="matrix(0.66961659,0.60167977,-0.57701715,0.69823705,253.41874,-410.88154)"
+         id="path3705"
+         style="fill:#ffff00;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:2.29145432;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
+      <path
+         d="m 581.84786,283.6361 0.24239,11.1012 9.28231,6.09376 -10.48296,3.66098 -2.92713,10.71108 -6.72121,-8.83858 -11.09137,0.52604 6.32902,-9.12352 -3.92772,-10.38597 10.63277,3.19994 8.6639,-6.94493 z"
+         transform="matrix(0.32903138,0.74281819,-0.71248505,0.34294808,576.69189,-156.07083)"
+         id="path3707"
+         style="fill:#ffff00;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:2.62631679;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
+      <path
+         d="m 581.84786,283.6361 0.24239,11.1012 9.28231,6.09376 -10.48296,3.66098 -2.92713,10.71108 -6.72121,-8.83858 -11.09137,0.52604 6.32902,-9.12352 -3.92772,-10.38597 10.63277,3.19994 8.6639,-6.94493 z"
+         transform="matrix(0.41989145,0.60368439,-0.57901736,0.43768607,598.80486,-130.94614)"
+         id="path3709"
+         style="fill:#ffff00;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:2.62631679;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
+      <path
+         d="m 581.84786,283.6361 0.24239,11.1012 9.28231,6.09376 -10.48296,3.66098 -2.92713,10.71108 -6.72121,-8.83858 -11.09137,0.52604 6.32902,-9.12352 -3.92772,-10.38597 10.63277,3.19994 8.6639,-6.94493 z"
+         transform="matrix(0.50568145,0.667589,-0.64030657,0.52711779,508.05486,-143.94461)"
+         id="path3711"
+         style="fill:#ffff00;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:2.62631679;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
+      <path
+         d="m 581.84786,283.6361 0.24239,11.1012 9.28231,6.09376 -10.48296,3.66098 -2.92713,10.71108 -6.72121,-8.83858 -11.09137,0.52604 6.32902,-9.12352 -3.92772,-10.38597 10.63277,3.19994 8.6639,-6.94493 z"
+         transform="matrix(0.56991181,0.5273505,-0.50578193,0.59409376,463.17516,-114.1298)"
+         id="path3713"
+         style="fill:#ffff00;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:2.62631679;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
+      <path
+         d="m 581.84786,283.6361 0.24239,11.1012 9.28231,6.09376 -10.48296,3.66098 -2.92713,10.71108 -6.72121,-8.83858 -11.09137,0.52604 6.32902,-9.12352 -3.92772,-10.38597 10.63277,3.19994 8.6639,-6.94493 z"
+         transform="matrix(0.38328825,0.61417645,-0.58908514,0.39952525,528.50516,-179.36895)"
+         id="path3715"
+         style="fill:#ffff00;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:2.62631679;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
+      <path
+         d="m 581.84786,283.6361 0.24239,11.1012 9.28231,6.09376 -10.48296,3.66098 -2.92713,10.71108 -6.72121,-8.83858 -11.09137,0.52604 6.32902,-9.12352 -3.92772,-10.38597 10.63277,3.19994 8.6639,-6.94493 z"
+         transform="matrix(0.21228283,0.6694725,-0.642143,0.22124223,736.24094,-145.48175)"
+         id="path3717"
+         style="fill:#ffff00;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:2.62631679;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
+      <path
+         d="m 581.84786,283.6361 0.24239,11.1012 9.28231,6.09376 -10.48296,3.66098 -2.92713,10.71108 -6.72121,-8.83858 -11.09137,0.52604 6.32902,-9.12352 -3.92772,-10.38597 10.63277,3.19994 8.6639,-6.94493 z"
+         transform="matrix(0.52690686,0.65971841,-0.63275486,0.54924661,385.49523,-151.70652)"
+         id="path3719-0"
+         style="fill:#ffff00;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:2.62631679;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
+      <path
+         d="m 581.84786,283.6361 0.24239,11.1012 9.28231,6.09376 -10.48296,3.66098 -2.92713,10.71108 -6.72121,-8.83858 -11.09137,0.52604 6.32902,-9.12352 -3.92772,-10.38597 10.63277,3.19994 8.6639,-6.94493 z"
+         transform="matrix(0.41957988,0.47252748,-0.4532104,0.43737455,434.38962,-118.51804)"
+         id="path3721-8"
+         style="fill:#ffff00;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:2.62631679;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
+      <path
+         d="m 581.84786,283.6361 0.24239,11.1012 9.28231,6.09376 -10.48296,3.66098 -2.92713,10.71108 -6.72121,-8.83858 -11.09137,0.52604 6.32902,-9.12352 -3.92772,-10.38597 10.63277,3.19994 8.6639,-6.94493 z"
+         transform="matrix(-0.19273964,0.6687388,-0.64148031,-0.20100369,946.5828,-14.710004)"
+         id="path3723-3"
+         style="fill:#ffff00;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:2.62631679;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
+      <path
+         d="m 581.84786,283.6361 0.24239,11.1012 9.28231,6.09376 -10.48296,3.66098 -2.92713,10.71108 -6.72121,-8.83858 -11.09137,0.52604 6.32902,-9.12352 -3.92772,-10.38597 10.63277,3.19994 8.6639,-6.94493 z"
+         transform="matrix(0.47101974,0.47621255,-0.45673995,0.49100151,375.78838,-117.43423)"
+         id="path3725-8"
+         style="fill:#ffff00;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:2.62631679;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
+      <path
+         d="m 581.84786,283.6361 0.24239,11.1012 9.28231,6.09376 -10.48296,3.66098 -2.92713,10.71108 -6.72121,-8.83858 -11.09137,0.52604 6.32902,-9.12352 -3.92772,-10.38597 10.63277,3.19994 8.6639,-6.94493 z"
+         transform="matrix(-0.15857073,0.66640619,-0.63909046,-0.16534829,765.95393,-149.94831)"
+         id="path3727"
+         style="fill:#ffff00;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:2.29145432;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
+      <path
+         d="m 581.84786,283.6361 0.24239,11.1012 9.28231,6.09376 -10.48296,3.66098 -2.92713,10.71108 -6.72121,-8.83858 -11.09137,0.52604 6.32902,-9.12352 -3.92772,-10.38597 10.63277,3.19994 8.6639,-6.94493 z"
+         transform="matrix(0.45835154,0.47927283,-0.45967667,0.47779429,385.71237,-117.12216)"
+         id="path3729"
+         style="fill:#ffff00;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:2.62631679;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
+      <path
+         d="m 581.84786,283.6361 0.24239,11.1012 9.28231,6.09376 -10.48296,3.66098 -2.92713,10.71108 -6.72121,-8.83858 -11.09137,0.52604 6.32902,-9.12352 -3.92772,-10.38597 10.63277,3.19994 8.6639,-6.94493 z"
+         transform="matrix(0.4276062,0.48742288,-0.4674974,0.44574067,400.45691,-121.55545)"
+         id="path3731-1"
+         style="fill:#ffff00;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:2.62631679;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
+      <path
+         d="m 581.84786,283.6361 0.24239,11.1012 9.28231,6.09376 -10.48296,3.66098 -2.92713,10.71108 -6.72121,-8.83858 -11.09137,0.52604 6.32902,-9.12352 -3.92772,-10.38597 10.63277,3.19994 8.6639,-6.94493 z"
+         transform="matrix(0.2133432,0.78684264,-0.75472547,0.2223358,639.43024,-145.65066)"
+         id="path3733-6"
+         style="fill:#ffff00;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:2.62631679;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
+      <path
+         d="m 581.84786,283.6361 0.24239,11.1012 9.28231,6.09376 -10.48296,3.66098 -2.92713,10.71108 -6.72121,-8.83858 -11.09137,0.52604 6.32902,-9.12352 -3.92772,-10.38597 10.63277,3.19994 8.6639,-6.94493 z"
+         transform="matrix(0.35200522,0.77626244,-0.74456278,0.36689548,618.16456,-166.14695)"
+         id="path3735"
+         style="fill:#ffff00;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:2.62631679;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
+      <path
+         d="m 581.84786,283.6361 0.24239,11.1012 9.28231,6.09376 -10.48296,3.66098 -2.92713,10.71108 -6.72121,-8.83858 -11.09137,0.52604 6.32902,-9.12352 -3.92772,-10.38597 10.63277,3.19994 8.6639,-6.94493 z"
+         transform="matrix(0.55587905,0.62577173,-0.60018995,0.57945429,398.38029,-123.74225)"
+         id="path3737"
+         style="fill:#ffff00;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:2.62631679;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
+    </g>
+  </g>
+  <g
+     transform="matrix(0.8557944,0,0,0.8106021,188.92188,242.35843)"
+     id="spray-copy-mode">
+    <path
+       d="m 368.21875,315.40625 c -0.5938,0 -1.09375,0.49995 -1.09375,1.09375 l 0,8.1875 -6.625,0 c -0.5938,0 -1.09375,0.4687 -1.09375,1.0625 l 0,18.96875 c 0,0.41391 0.2519,0.75879 0.59375,0.9375 0.026,0.0136 0.0353,0.051 0.0625,0.0625 0.17831,0.34313 0.52264,0.59376 0.9375,0.59375 l 24.625,0 c 0.5938,0 1.09376,-0.46869 1.09375,-1.0625 l 0,-8.71875 6.125,0 c 0.5938,0 1.06251,-0.46869 1.0625,-1.0625 l 0,-18.96875 c 0,-0.5938 -0.4687,-1.09375 -1.0625,-1.09375 l -24.625,0 z"
+       id="rect6196"
+       style="fill:#000000;fill-opacity:1;stroke:#000000;stroke-width:1.20000005;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
+    <g
+       transform="translate(-3.5450574e-7,0.5149192)"
+       id="g6335">
+      <rect
+         width="26.775824"
+         height="21.111708"
+         ry="1.0718389"
+         x="367.13776"
+         y="315.42078"
+         id="rect6337"
+         style="fill:url(#linearGradient6466-2);fill-opacity:1;stroke:#000000;stroke-width:1.20000005;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
+      <g
+         transform="translate(7.2088757,-31.410101)"
+         id="g6339">
+        <rect
+           width="26.775824"
+           height="21.111708"
+           ry="1.0718389"
+           x="352.72"
+           y="356.61435"
+           id="rect6341"
+           style="fill:#000000;fill-opacity:1;stroke:#000000;stroke-width:1.20000005;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
+        <rect
+           width="26.775824"
+           height="21.111708"
+           ry="1.0718389"
+           x="352.20511"
+           y="356.09943"
+           id="rect6343"
+           style="fill:url(#linearGradient6468-0);fill-opacity:1;stroke:#000000;stroke-width:1.20000005;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
+      </g>
+    </g>
+  </g>
+  <g
+     transform="matrix(0.8413762,0,0,0.8105392,266.3079,183.1218)"
+     id="spray-union-mode">
+    <path
+       d="m 377.48731,389.03977 c -0.5938,0 -1.09375,0.49995 -1.09375,1.09375 l 0,8.1875 -6.625,0 c -0.5938,0 -1.09375,0.4687 -1.09375,1.0625 l 0,18.96875 c 0,0.41391 0.2519,0.75879 0.59375,0.9375 0.026,0.0136 0.0353,0.0511 0.0625,0.0625 0.17831,0.34313 0.52264,0.59376 0.9375,0.59375 l 24.625,0 c 0.5938,0 1.09376,-0.46869 1.09375,-1.0625 l 0,-8.71875 6.125,0 c 0.5938,0 1.06251,-0.46869 1.0625,-1.0625 l 0,-18.96875 c 0,-0.5938 -0.4687,-1.09375 -1.0625,-1.09375 l -24.625,0 z"
+       id="path6506"
+       style="fill:#000000;fill-opacity:1;stroke:#000000;stroke-width:1.20000005;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
+    <path
+       d="m 377.47944,388.53223 c -0.5938,0 -1.0625,0.49995 -1.0625,1.09375 l 0,8.1875 -6.65625,0 c -0.5938,0 -1.09375,0.4687 -1.09375,1.0625 l 0,18.96875 c 0,0.44535 0.27129,0.83772 0.65625,1 0.17597,0.35015 0.51748,0.59376 0.9375,0.59375 l 24.65625,0 c 0.5938,0 1.06251,-0.46869 1.0625,-1.0625 l 0,-8.71875 6.125,0 c 0.5938,0 1.06251,-0.46869 1.0625,-1.0625 l 0,-18.96875 c 0,-0.5938 -0.4687,-1.09375 -1.0625,-1.09375 l -24.625,0 z"
+       id="rect6510"
+       style="fill:url(#linearGradient6563-3);fill-opacity:1;stroke:#000000;stroke-width:1.20000005;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
+  </g>
+  <g
+     transform="translate(164.42529,191.5008)"
+     id="spray-clone-mode"
+     inkscape:label="#g5793">
+    <path
+       transform="matrix(0.8269532,0,0,0.8236011,70.705122,33.206996)"
+       d="m 373.36795,331.88368 c -0.5938,0 -1.09375,0.49995 -1.09375,1.09375 l 0,8.1875 -6.625,0 c -0.5938,0 -1.09375,0.4687 -1.09375,1.0625 l 0,18.96875 c 0,0.41391 0.2519,0.75879 0.59375,0.9375 0.026,0.0136 0.0353,0.051 0.0625,0.0625 0.17831,0.34313 0.52264,0.59376 0.9375,0.59375 l 24.625,0 c 0.5938,0 1.09376,-0.46869 1.09375,-1.0625 l 0,-8.71875 6.125,0 c 0.5938,0 1.06251,-0.46869 1.0625,-1.0625 l 0,-18.96875 c 0,-0.5938 -0.4687,-1.09375 -1.0625,-1.09375 l -24.625,0 z"
+       id="path6442"
+       style="fill:#000000;fill-opacity:1;stroke:#000000;stroke-width:1.20000005;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
+    <g
+       id="g5785">
+      <g
+         id="g5780">
+        <rect
+           width="22.142353"
+           height="17.387625"
+           ry="0.88276768"
+           x="378.569"
+           y="306.55872"
+           id="rect6446"
+           style="fill:url(#linearGradient5783-6-3);fill-opacity:1;stroke:#000000;stroke-width:0.99000001;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
+      </g>
+      <g
+         id="g5775">
+        <rect
+           transform="matrix(0.8269532,0,0,0.8236011,80.498855,-10.474112)"
+           width="26.775824"
+           height="21.111708"
+           ry="1.0718389"
+           x="353.23492"
+           y="394.71841"
+           id="rect6450"
+           style="fill:#000000;fill-opacity:1;stroke:#000000;stroke-width:1.20000005;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
+        <rect
+           width="22.142353"
+           height="17.387625"
+           ry="0.88276768"
+           x="372.51971"
+           y="314.02679"
+           id="rect6452"
+           style="fill:url(#linearGradient6583-7);fill-opacity:1;stroke:#c2c2c2;stroke-width:1.88999999;stroke-linejoin:miter;stroke-miterlimit:4.19999981;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0" />
+        <rect
+           style="fill:none;stroke:#000000;stroke-width:1.88999999;stroke-linejoin:miter;stroke-miterlimit:4.19999981;stroke-opacity:1;stroke-dasharray:3.77999997, 3.77999997;stroke-dashoffset:0"
+           id="rect6585"
+           y="314.02679"
+           x="372.51971"
+           ry="0.88276768"
+           height="17.387625"
+           width="22.142353" />
+      </g>
+    </g>
+  </g>
+  <g
+     id="dialog-spray-options"
+     transform="matrix(1.4792628,0,0,1.4792628,-674.73187,-34.196449)"
+     inkscape:label="spray-options">
+    <path
+       style="fill:#d32b2b;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.70700002;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+       id="rect2774-1-5"
+       d="m 889.56228,361.00892 -3.20403,2.65834 0.89649,1.17656 2.09543,-1.73855 c -0.0331,-0.16432 0.0363,-0.35589 0.1902,-0.48358 0.15391,-0.1277 0.34842,-0.15512 0.49437,-0.0844 l 0.42403,-0.3518 -0.89649,-1.17657 z" />
+    <path
+       style="fill:#de7c7c;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.75099999;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+       id="path2776-8"
+       d="m 887.1665,368.88345 a 3.7917328,4.4707858 44.150037 0 1 -4.61038,-6.05077 3.7917328,4.4707858 44.150037 0 1 4.61038,6.05077 z" />
+    <rect
+       style="fill:url(#linearGradient7199-9);fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.84636402;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+       id="rect2774-7"
+       transform="matrix(0.60606627,0.79541416,-0.76960011,0.63852617,0,0)"
+       y="-483.83899"
+       x="843.50018"
+       height="13.780915"
+       width="7.6610627" />
+    <path
+       d="m 881.92186,374.5484 c 0.008,1.66436 -1.0983,2.22479 -2.20786,2.23043 l -2.77394,0.0141 -0.56042,-1.10675 -0.006,-1.10957 2.21914,-0.0113 -0.0226,-4.43829 -2.21914,0.0113 -0.006,-1.10957 0.54914,-1.1124 2.77393,-0.0141 c 1.10957,-0.006 2.22196,0.54351 2.23042,2.20786 l 5.54785,-0.0282 c -0.008,-1.66435 1.0983,-2.22479 2.20786,-2.23043 l 2.77393,-0.0141 0.56043,1.10676 0.006,1.10956 -2.21914,0.0113 0.0226,4.43829 2.21914,-0.0113 0.006,1.10958 -0.54916,1.11239 -2.77392,0.0141 c -0.55478,0.003 -2.22196,-0.5435 -2.23042,-2.20786 l -5.54785,0.0282 z"
+       id="path11005-9"
+       style="fill:url(#linearGradient7201-4);fill-opacity:1;fill-rule:evenodd;stroke:url(#linearGradient7203-5);stroke-width:1.1095854px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" />
+  </g>
 </svg>
index de986ca16e3a19fec2f3f1943ede0926a82c766e..18beaec37c46d9844c60e841e3c5bfbdaa1f4a60 100644 (file)
@@ -222,6 +222,7 @@ ink_common_sources +=       \
        sp-tspan.cpp sp-tspan.h                 \
        sp-use.cpp sp-use.h                     \
        sp-use-reference.cpp sp-use-reference.h \
+       spray-context.cpp spray-context.h       \
        star-context.cpp star-context.h         \
        streq.h                                 \
        strneq.h                                \
diff --git a/src/pixmaps/cursor-spray-move.xpm b/src/pixmaps/cursor-spray-move.xpm
new file mode 100644 (file)
index 0000000..ad898b3
--- /dev/null
@@ -0,0 +1,38 @@
+/* XPM */
+static char const * cursor_spray_move_xpm[] = {
+"32 32 3 1",
+"      c None",
+".     c #FFFFFF",
+"+     c #000000",
+"   ...                          ",
+"   .+.                          ",
+"   .+.                          ",
+"....+....                       ",
+".+++ +++.                       ",
+"....+....                       ",
+"   .+.                          ",
+"   .+.                          ",
+"   ...                          ",
+"         ...  ...  ...  ...     ",
+"        ..+. ..+. ..+. ..+.     ",
+"        .+++ .+++ .+++ .+++     ",
+"        ..+. .+++ .+++ ..+      ",
+"        .... .+++ .+++ ....     ",
+"        ..+. ..+  ..+  ..+.     ",
+"        .+++ ..+. ..+. .+++     ",
+"        ..+  .+++ .+++ ..+      ",
+"        .... ..+  ..+  ....     ",
+"        ..+. .... .... ..+.     ",
+"        .+++ ..+. ..+. .+++     ",
+"        ..+  .+++ .+++ ..+      ",
+"             ..+  ..+           ",
+"         ...            ...     ",
+"        ..+.           ..+.     ",
+"        .+++           .+++     ",
+"        ..+            ..+      ",
+"                                ",
+"                                ",
+"                                ",
+"                                ",
+"                                ",
+"                                "};
diff --git a/src/pixmaps/cursor-spray.xpm b/src/pixmaps/cursor-spray.xpm
new file mode 100644 (file)
index 0000000..9ccefee
--- /dev/null
@@ -0,0 +1,38 @@
+/* XPM */
+static char const * cursor_spray_xpm[] = {
+"32 32 3 1",
+"      c None",
+".     c #FFFFFF",
+"+     c #000000",
+"   ...                          ",
+"   .+.                          ",
+"   .+.                          ",
+"....+....                       ",
+".+++ +++.                       ",
+"....+....                       ",
+"   .+.                          ",
+"   .+.                          ",
+"   ...   .+.  +.                ",
+"        .+.+.+.+.               ",
+"       .+...+...+.              ",
+"       +...+.....+.             ",
+" . . . .+.+.......+.            ",
+"  + + + .+.........+.           ",
+" . . . .+...........+.          ",
+"  + + .+.............+.         ",
+" . . . .+.............+.        ",
+"  + + + .+.............+.       ",
+"   . .   .+.............+.      ",
+"          .+.............+.     ",
+"           .+.............+.    ",
+"            .+...........+.     ",
+"             .+.........+.      ",
+"              .+.......+.       ",
+"               .+.....+.        ",
+"                .+...+.         ",
+"                 .+.+.          ",
+"                  .+.           ",
+"                   .            ",
+"                                ",
+"                                ",
+"                                "};
index 6185ff729230a68ca568c52772d951ec2d756056..80a1bd5eaad1d51ac6e07abe327bcf791885fe09 100644 (file)
@@ -114,6 +114,7 @@ static char const preferences_skeleton[] =
 "                  style=\"fill:black;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans;font-style:normal;font-weight:normal;font-size:40px;\" selcue=\"1\"/>\n"
 "    <eventcontext id=\"nodes\" selcue=\"1\" gradientdrag=\"1\" highlight_color=\"4278190335\" pathflash_enabled=\"1\" pathflash_unselected=\"0\" pathflash_timeout=\"500\" show_handles=\"1\" show_helperpath=\"0\" sculpting_profile=\"1\" />\n"
 "    <eventcontext id=\"tweak\" selcue=\"0\" gradientdrag=\"0\" show_handles=\"0\" width=\"0.2\" force=\"0.2\" fidelity=\"0.5\" usepressure=\"1\" style=\"fill:red;stroke:none;\" usecurrent=\"0\"/>\n"
+"    <eventcontext id=\"spray\" selcue=\"0\" gradientdrag=\"0\" show_handles=\"0\" width=\"0.2\" force=\"0.2\" fidelity=\"0.5\" usepressure=\"1\" style=\"fill:red;stroke:none;\" usecurrent=\"0\"/>\n"
 "    <eventcontext id=\"gradient\" selcue=\"1\"/>\n"
 "    <eventcontext id=\"zoom\" selcue=\"1\" gradientdrag=\"0\"/>\n"
 "    <eventcontext id=\"dropper\" selcue=\"1\" gradientdrag=\"1\" pick=\"1\" setalpha=\"1\"/>\n"
diff --git a/src/spray-context.cpp b/src/spray-context.cpp
new file mode 100644 (file)
index 0000000..71dc964
--- /dev/null
@@ -0,0 +1,1199 @@
+#define __SP_SPRAY_CONTEXT_C__
+
+/*
+ * Spray Tool
+ *
+ * Authors:
+ *   Pierre-Antoine MARC
+ *   Pierre CACLIN
+ *   Aurel-Aimé MARMION   
+ *   Julien LERAY
+ *   Benoît LAVORATA
+ *   Vincent MONTAGNE
+ *   Pierre BARBRY-BLOT
+ *
+ * Copyright (C) 2009 authors
+ *
+ * Released under GNU GPL, read the file 'COPYING' for more information
+ */
+
+#include "config.h"
+
+#include <gtk/gtk.h>
+#include <gdk/gdkkeysyms.h>
+#include <glibmm/i18n.h>
+
+#include <numeric>
+
+#include "svg/svg.h"
+#include "display/canvas-bpath.h"
+
+#include <glib/gmem.h>
+#include "macros.h"
+#include "document.h"
+#include "selection.h"
+#include "desktop.h"
+#include "desktop-events.h"
+#include "desktop-handles.h"
+#include "unistd.h"
+#include "desktop-style.h"
+#include "message-context.h"
+#include "pixmaps/cursor-spray.xpm"
+#include "pixmaps/cursor-spray-move.xpm"
+#include "pixmaps/cursor-thin.xpm"
+#include "pixmaps/cursor-thicken.xpm"
+#include "pixmaps/cursor-attract.xpm"
+#include "pixmaps/cursor-repel.xpm"
+#include "pixmaps/cursor-push.xpm"
+#include "pixmaps/cursor-roughen.xpm"
+#include "pixmaps/cursor-color.xpm"
+#include <boost/optional.hpp>
+#include "libnr/nr-matrix-ops.h"
+#include "libnr/nr-scale-translate-ops.h"
+#include "xml/repr.h"
+#include "context-fns.h"
+#include "sp-item.h"
+#include "inkscape.h"
+#include "color.h"
+#include "svg/svg-color.h"
+#include "splivarot.h"
+#include "sp-item-group.h"
+#include "sp-shape.h"
+#include "sp-path.h"
+#include "path-chemistry.h"
+#include "sp-gradient.h"
+#include "sp-stop.h"
+#include "sp-stop-fns.h"
+#include "sp-gradient-reference.h"
+#include "sp-linear-gradient.h"
+#include "sp-radial-gradient.h"
+#include "gradient-chemistry.h"
+#include "sp-text.h"
+#include "sp-flowtext.h"
+#include "display/canvas-bpath.h"
+#include "display/canvas-arena.h"
+#include "display/curve.h"
+#include "livarot/Shape.h"
+#include <2geom/isnan.h>        
+#include <2geom/transforms.h>
+#include "preferences.h"
+#include "style.h"
+#include "box3d.h"
+#include "sp-item-transform.h"
+#include "filter-chemistry.h"
+#include "sp-gaussian-blur-fns.h"
+#include "sp-gaussian-blur.h"
+
+#include "spray-context.h"
+#include "ui/dialog/dialog-manager.h"
+#include "helper/action.h"
+
+#include <iostream>
+using namespace std;
+
+
+#define DDC_RED_RGBA 0xff0000ff
+
+#define DYNA_MIN_WIDTH 1.0e-6
+
+static void sp_spray_context_class_init(SPSprayContextClass *klass);
+static void sp_spray_context_init(SPSprayContext *ddc);
+static void sp_spray_context_dispose(GObject *object);
+
+static void sp_spray_context_setup(SPEventContext *ec);
+static void sp_spray_context_set(SPEventContext *ec, Inkscape::Preferences::Entry *val);
+static gint sp_spray_context_root_handler(SPEventContext *ec, GdkEvent *event);
+
+static SPEventContextClass *parent_class;
+
+
+
+// The following code implements NormalDistribution wich is used for the density of the spray
+
+
+/*
+   RAND is a macro which returns a pseudo-random numbers from a uniform
+   distribution on the interval [0 1]
+*/
+#define RAND ((double) rand())/((double) RAND_MAX)
+
+/*
+   TWOPI = 2.0*pi
+*/
+#define TWOPI 2.0*3.141592653589793238462643383279502884197169399375
+
+/*
+   RANDN is a macro which returns a pseudo-random numbers from a normal
+   distribution with mean zero and standard deviation one. This macro uses Box
+   Muller's algorithm
+*/
+#define RANDN sqrt(-2.0*log(RAND))*cos(TWOPI*RAND)
+
+
+double NormalDistribution(double mu,double sigma)
+{
+/*
+   This function returns a pseudo-random numbers from a normal distribution with
+   mean equal at mu and standard deviation equal at sigma > 0
+*/
+
+  return (mu+sigma*RANDN);
+
+}
+
+//Fin de la création de NormalDistribution
+
+GtkType
+sp_spray_context_get_type(void)
+{
+    static GType type = 0;
+    if (!type) {
+        GTypeInfo info = {
+            sizeof(SPSprayContextClass),
+            NULL, NULL,
+            (GClassInitFunc) sp_spray_context_class_init,
+            NULL, NULL,
+            sizeof(SPSprayContext),
+            4,
+            (GInstanceInitFunc) sp_spray_context_init,
+            NULL,   /* value_table */
+        };
+        type = g_type_register_static(SP_TYPE_EVENT_CONTEXT, "SPSprayContext", &info, (GTypeFlags)0);
+    }
+    return type;
+}
+
+static void
+sp_spray_context_class_init(SPSprayContextClass *klass)
+{
+    GObjectClass *object_class = (GObjectClass *) klass;
+    SPEventContextClass *event_context_class = (SPEventContextClass *) klass;
+
+    parent_class = (SPEventContextClass*)g_type_class_peek_parent(klass);
+
+    object_class->dispose = sp_spray_context_dispose;
+
+    event_context_class->setup = sp_spray_context_setup;
+    event_context_class->set = sp_spray_context_set;
+    event_context_class->root_handler = sp_spray_context_root_handler;
+}
+/*Method to rotate items*/
+void
+sp_spray_rotate_rel(Geom::Point c,SPDesktop *desktop,SPItem *item, Geom::Rotate const &rotation)
+{
+
+    Geom::Point center = c;
+    Geom::Translate const s(c);
+    Geom::Matrix affine = Geom::Matrix(s).inverse() * Geom::Matrix(rotation) * Geom::Matrix(s);
+
+    // Rotate item.
+    sp_item_set_i2d_affine(item, sp_item_i2d_affine(item) * (Geom::Matrix)affine);
+    // Use each item's own transform writer, consistent with sp_selection_apply_affine()
+    sp_item_write_transform(item, SP_OBJECT_REPR(item), item->transform);
+
+    // Restore the center position (it's changed because the bbox center changed)
+    if (item->isCenterSet()) {
+        item->setCenter(c);
+        item->updateRepr();
+    }
+}
+/*Method to scale items*/
+void
+sp_spray_scale_rel (Geom::Point c, SPDesktop *desktop, SPItem *item, Geom::Scale  const &scale)
+{
+        Geom::Translate const s(c); 
+
+        
+        sp_item_set_i2d_affine(item, sp_item_i2d_affine(item) * s.inverse() * scale * s  );
+        sp_item_write_transform(item, SP_OBJECT_REPR(item), item->transform);
+
+
+}
+static void
+sp_spray_context_init(SPSprayContext *tc)
+{   
+   SPEventContext *event_context = SP_EVENT_CONTEXT(tc);
+    
+
+
+    event_context->cursor_shape = cursor_spray_xpm;
+    event_context->hot_x = 4;
+    event_context->hot_y = 4;
+
+    /* attributes */
+    tc->dragging = FALSE;
+    tc->distrib = 1;
+    tc->width = 0.2;
+    tc->force = 0.2;
+    tc->ratio = 0;
+    tc->tilt=0;
+    tc->mean = 0.2;
+    tc->rot_min=0;
+    tc->rot_max=0;
+    tc->standard_deviation=0.2;
+    tc->scale=1;
+    tc->scale_min = 1;
+    tc->scale_max=1;
+    tc->pressure = TC_DEFAULT_PRESSURE;
+
+    tc->is_dilating = false;
+    tc->has_dilated = false;
+
+    tc->do_h = true;
+    tc->do_s = true;
+    tc->do_l = true;
+    tc->do_o = false;
+
+    new (&tc->style_set_connection) sigc::connection();
+}
+
+static void
+sp_spray_context_dispose(GObject *object)
+{
+    SPSprayContext *tc = SP_SPRAY_CONTEXT(object);
+
+    tc->style_set_connection.disconnect();
+    tc->style_set_connection.~connection();
+
+    if (tc->dilate_area) {
+        gtk_object_destroy(GTK_OBJECT(tc->dilate_area));
+        tc->dilate_area = NULL;
+    }
+
+    if (tc->_message_context) {
+        delete tc->_message_context;
+    }
+
+    G_OBJECT_CLASS(parent_class)->dispose(object);
+}
+
+bool is_transform_modes (gint mode)
+{
+    return (mode == SPRAY_MODE_COPY ||
+            mode == SPRAY_MODE_CLONE ||
+            mode == SPRAY_MODE_SINGLE_PATH ||
+            mode == SPRAY_OPTION);
+}
+
+void
+sp_spray_update_cursor (SPSprayContext *tc, bool with_shift)
+{
+   SPEventContext *event_context = SP_EVENT_CONTEXT(tc);
+   SPDesktop *desktop = event_context->desktop;
+
+                guint num = 0;
+                gchar *sel_message = NULL;
+                if (!desktop->selection->isEmpty()) {
+                    num = g_slist_length((GSList *) desktop->selection->itemList());
+                    sel_message = g_strdup_printf(ngettext("<b>%i</b> object selected","<b>%i</b> objects selected",num), num);
+                } else {
+                    sel_message = g_strdup_printf(_("<b>Nothing</b> selected"));
+                }
+
+
+   switch (tc->mode) {
+       case SPRAY_MODE_COPY:
+           tc->_message_context->setF(Inkscape::NORMAL_MESSAGE, _("%s. Drag, click or scroll to spray <b>copies</b> of the initial selection"), sel_message);
+           break;
+       case SPRAY_MODE_CLONE:
+           tc->_message_context->setF(Inkscape::NORMAL_MESSAGE, _("%s. Drag, click or scroll to spray <b>clones</b> of the initial selection"), sel_message);
+           break;
+       case SPRAY_MODE_SINGLE_PATH:
+           tc->_message_context->setF(Inkscape::NORMAL_MESSAGE, _("%s. Drag, click or scroll to spray in a <b>single path</b> of the initial selection"), sel_message);
+           break;
+       case SPRAY_OPTION:
+           tc->_message_context->setF(Inkscape::NORMAL_MESSAGE, _("%s. Modify <b>spray</b> options"), sel_message);
+           break;
+   }
+   sp_event_context_update_cursor(event_context);
+   g_free(sel_message);
+}
+
+static void
+sp_spray_context_setup(SPEventContext *ec)
+{
+    SPSprayContext *tc = SP_SPRAY_CONTEXT(ec);
+
+    if (((SPEventContextClass *) parent_class)->setup)
+        ((SPEventContextClass *) parent_class)->setup(ec);
+
+    {
+        /* TODO: have a look at sp_dyna_draw_context_setup where the same is done.. generalize? at least make it an arcto! */
+        SPCurve *c = new SPCurve();
+        const double C1 = 0.552;
+        c->moveto(-1,0);
+        c->curveto(-1, C1, -C1, 1, 0, 1 );
+        c->curveto(C1, 1, 1, C1, 1, 0 );
+        c->curveto(1, -C1, C1, -1, 0, -1 );
+        c->curveto(-C1, -1, -1, -C1, -1, 0 );
+        c->closepath();
+        tc->dilate_area = sp_canvas_bpath_new(sp_desktop_controls(ec->desktop), c);
+        c->unref();
+        sp_canvas_bpath_set_fill(SP_CANVAS_BPATH(tc->dilate_area), 0x00000000,(SPWindRule)0);
+        sp_canvas_bpath_set_stroke(SP_CANVAS_BPATH(tc->dilate_area), 0xff9900ff, 1.0, SP_STROKE_LINEJOIN_MITER, SP_STROKE_LINECAP_BUTT);
+        sp_canvas_item_hide(tc->dilate_area);
+    }
+
+    tc->is_drawing = false;
+
+    tc->_message_context = new Inkscape::MessageContext((ec->desktop)->messageStack());
+
+    sp_event_context_read(ec, "distrib");    
+    sp_event_context_read(ec, "width");
+    sp_event_context_read(ec, "ratio");
+    sp_event_context_read(ec, "tilt");
+    sp_event_context_read(ec, "rot_min");
+    sp_event_context_read(ec, "rot_max");
+    sp_event_context_read(ec, "scale_min");
+    sp_event_context_read(ec, "scale_max");
+    sp_event_context_read(ec, "mode");
+    sp_event_context_read(ec, "population");
+    sp_event_context_read(ec, "force");
+    sp_event_context_read(ec, "mean");
+    sp_event_context_read(ec, "standard_deviation");
+    sp_event_context_read(ec, "usepressure");
+    sp_event_context_read(ec, "Rotation min");
+    sp_event_context_read(ec, "Rotation max");
+    sp_event_context_read(ec, "Scale");
+    sp_event_context_read(ec, "doh");
+    sp_event_context_read(ec, "dol");
+    sp_event_context_read(ec, "dos");
+    sp_event_context_read(ec, "doo");
+
+    ;
+
+    Inkscape::Preferences *prefs = Inkscape::Preferences::get();
+    if (prefs->getBool("/tools/spray/selcue")) {
+        ec->enableSelectionCue();
+    }
+
+    if (prefs->getBool("/tools/spray/gradientdrag")) {
+        ec->enableGrDrag();
+    }
+}
+
+static void
+sp_spray_context_set(SPEventContext *ec, Inkscape::Preferences::Entry *val)
+{
+    SPSprayContext *tc = SP_SPRAY_CONTEXT(ec);
+    Glib::ustring path = val->getEntryName();
+
+    if (path == "width") {
+        tc->width = CLAMP(val->getDouble(0.1), -1000.0, 1000.0);
+    } else if (path == "mode") {
+        tc->mode = val->getInt();
+        sp_spray_update_cursor(tc, false);
+    } else if (path == "distribution") {
+        tc->distrib = val->getInt(1);
+    } else if (path == "population") {
+        tc->population = CLAMP(val->getDouble(), 0.0, 1.0);
+     } else if (path == "tilt") {
+        tc->tilt = CLAMP(val->getDouble(0.1), 0, 1000.0);
+     } else if (path == "ratio") {
+        tc->ratio = CLAMP(val->getDouble(), 0.0, 0.9);
+    } else if (path == "force") {
+        tc->force = CLAMP(val->getDouble(1.0), 0, 1.0);
+    } else if (path == "rot_min") {
+        tc->rot_min = CLAMP(val->getDouble(0), 0, 10.0);
+    } else if (path == "rot_max") {
+        tc->rot_max = CLAMP(val->getDouble(0), 0, 10.0);
+    } else if (path == "scale_min") {
+        tc->scale_min = CLAMP(val->getDouble(1.0), 0, 10.0);    
+    } else if (path == "scale_max") {
+        tc->scale_max = CLAMP(val->getDouble(1.0), 0, 10.0);
+    } else if (path == "mean") {
+        tc->mean = CLAMP(val->getDouble(1.0), 0, 1.0);
+    } else if (path == "standard_deviation") {
+        tc->standard_deviation = CLAMP(val->getDouble(1.0), 0, 1.0);
+    } else if (path == "usepressure") {
+        tc->usepressure = val->getBool();
+    } else if (path == "doh") {
+        tc->do_h = val->getBool();
+    } else if (path == "dos") {
+        tc->do_s = val->getBool();
+    } else if (path == "dol") {
+        tc->do_l = val->getBool();
+    } else if (path == "doo") {
+        tc->do_o = val->getBool();
+    }
+}
+
+static void
+sp_spray_extinput(SPSprayContext *tc, GdkEvent *event)
+{
+    if (gdk_event_get_axis (event, GDK_AXIS_PRESSURE, &tc->pressure))
+        tc->pressure = CLAMP (tc->pressure, TC_MIN_PRESSURE, TC_MAX_PRESSURE);
+    else
+        tc->pressure = TC_DEFAULT_PRESSURE;
+}
+
+double
+get_dilate_radius (SPSprayContext *tc)
+{
+
+    return 250 * tc->width/SP_EVENT_CONTEXT(tc)->desktop->current_zoom();
+
+
+}
+
+double
+get_path_force (SPSprayContext *tc)
+{
+    double force = 8 * (tc->usepressure? tc->pressure : TC_DEFAULT_PRESSURE)
+        /sqrt(SP_EVENT_CONTEXT(tc)->desktop->current_zoom());
+    if (force > 3) {
+        force += 4 * (force - 3);
+    }
+    return force * tc->force;
+}
+
+double
+get_path_mean (SPSprayContext *tc)
+{
+    return tc->mean;
+}
+
+double
+get_path_standard_deviation (SPSprayContext *tc)
+{
+    return tc->standard_deviation;
+}
+
+double
+get_move_force (SPSprayContext *tc)
+{
+    double force = (tc->usepressure? tc->pressure : TC_DEFAULT_PRESSURE);
+    return force * tc->force;
+}
+
+double
+get_move_mean (SPSprayContext *tc)
+{
+    return tc->mean;
+}
+
+double
+get_move_standard_deviation (SPSprayContext *tc)
+{
+    return tc->standard_deviation;
+}
+
+/* Method to handle the distribution of the items */
+
+
+void random_position( double &r, double &p, double &a, double &s, int choix)
+{
+       if (choix == 0) // Mode 1 : uniform repartition
+    {
+        r = (1-pow(g_random_double_range(0, 1),2));
+        p = g_random_double_range(0, M_PI*2);
+    }
+    if (choix == 1) //Mode 0 : gaussian repartition
+    {
+        double r_temp =-1;
+while(!((r_temp>=0)&&(r_temp<=1)))
+{
+         r_temp = NormalDistribution(a,s/4);
+}
+// generates a number following a normal distribution
+        p = g_random_double_range(0, M_PI*2);
+        r=r_temp;
+       /* if (r_temp<=0) r=0;
+        else
+        {
+            if (r_temp>1) r=1;
+            else r = r_temp;
+        }*/
+    }
+}
+
+
+
+
+
+bool
+sp_spray_dilate_recursive (SPDesktop *desktop, Inkscape::Selection *selection, SPItem *item, Geom::Point p, Geom::Point vector, gint mode, double radius, double force, double population, double &scale, double scale_min, double scale_max, bool reverse, double mean, double standard_deviation, double ratio,double tilt, double rot_min, double rot_max, gint _distrib )
+{
+
+
+
+    bool did = false;
+
+    if (SP_IS_BOX3D(item) /*&& !is_transform_modes(mode)*/) {
+        // convert 3D boxes to ordinary groups before spraying their shapes
+        item = SP_ITEM(box3d_convert_to_group(SP_BOX3D(item)));
+        selection->add(item);
+    }
+
+/*if (SP_IS_TEXT(item) || SP_IS_FLOWTEXT(item)) {
+        GSList *items = g_slist_prepend (NULL, item);
+        GSList *selected = NULL;
+        GSList *to_select = NULL;
+        SPDocument *doc = SP_OBJECT_DOCUMENT(item);
+        sp_item_list_to_curves (items, &selected, &to_select);
+        g_slist_free (items);
+        SPObject* newObj = doc->getObjectByRepr((Inkscape::XML::Node *) to_select->data);
+        g_slist_free (to_select);
+        item = (SPItem *) newObj;
+      //  selection->add(item);
+    }
+*/
+   /*if (SP_IS_GROUP(item) && !SP_IS_BOX3D(item)) {
+        for (SPObject *child = sp_object_first_child(SP_OBJECT(item)) ; child != NULL; child = SP_OBJECT_NEXT(child) ) {
+            if (SP_IS_ITEM(child)) {
+                if (sp_spray_dilate_recursive (desktop,selection, SP_ITEM(child), p, vector, mode, radius, force, population, scale, scale_min, scale_max, reverse, mean, standard_deviation,ratio,tilt, rot_min, rot_max,_distrib))
+                    did = true;
+            }
+        }
+
+    } else {*/
+        if (mode == SPRAY_MODE_COPY) {
+
+            Geom::OptRect a = item->getBounds(sp_item_i2doc_affine(item));
+            if (a) {
+                double dr; double dp; 
+                random_position(dr,dp,mean,standard_deviation,_distrib);
+                dr=dr*radius;
+                double _fid = g_random_double_range(0,1);
+                SPItem *item_copied;
+                double angle = g_random_double_range(rot_min, rot_max);                
+                double _scale = g_random_double_range(scale_min, scale_max);  
+                if(_fid<=population)
+                {
+                          // duplicate
+                            SPDocument *doc = SP_OBJECT_DOCUMENT(item);
+                            Inkscape::XML::Document* xml_doc = sp_document_repr_doc(doc);
+                            Inkscape::XML::Node *old_repr = SP_OBJECT_REPR(item);
+                            Inkscape::XML::Node *parent = old_repr->parent();
+                            Inkscape::XML::Node *copy = old_repr->duplicate(xml_doc);
+                            parent->appendChild(copy);
+
+                            SPObject *new_obj = doc->getObjectByRepr(copy);
+                            item_copied = (SPItem *) new_obj;   //convertion object->item
+                            Geom::Point center=item->getCenter();
+                            sp_spray_scale_rel(center,desktop,item_copied, Geom::Scale(_scale,_scale));  
+                            sp_spray_scale_rel(center,desktop,item_copied, Geom::Scale(scale,scale));   
+                            
+                            sp_spray_rotate_rel(center,desktop,item_copied, Geom::Rotate(angle));                             
+                            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());//Move the cursor p
+                            sp_item_move_rel(item_copied, Geom::Translate(move[Geom::X], -move[Geom::Y]));
+
+
+                   
+                         
+                            
+                        did = true;
+                        }
+            }
+
+        } else if (mode == SPRAY_MODE_SINGLE_PATH) {
+
+
+            SPItem *Pere; //Objet initial
+            SPItem *item_copied;//Objet projeté
+            SPItem *Union;//Union précédente
+            SPItem *fils;//Copie du père
+
+           // GSList *items = g_slist_copy((GSList *) selection->itemList()); //Récupère la liste des objects sélectionnés
+//Pere = (SPItem *) items->data;//Le premier objet est le père du spray
+
+            int i=1;
+            for (GSList *items = g_slist_copy((GSList *) selection->itemList());
+                    items != NULL;
+                    items = items->next) {
+
+                SPItem *item1 = (SPItem *) items->data;
+                if (i==1) {
+                    Pere=item1;
+                }
+                if (i==2) {
+                    Union=item1;
+                }
+                i++;
+            }
+            SPDocument *doc = SP_OBJECT_DOCUMENT(Pere);
+            Inkscape::XML::Document* xml_doc = sp_document_repr_doc(doc);
+            Inkscape::XML::Node *old_repr = SP_OBJECT_REPR(Pere);
+            //SPObject *old_obj = doc->getObjectByRepr(old_repr);
+            Inkscape::XML::Node *parent = old_repr->parent();
+
+            Geom::OptRect a = Pere->getBounds(sp_item_i2doc_affine(Pere));
+            if (a) {
+                double dr; double dp; //initialisation des variables
+                random_position(dr,dp,mean,standard_deviation,_distrib);
+                dr=dr*radius;
+                double _fid = g_random_double_range(0,1);
+                double angle = (g_random_double_range(rot_min, rot_max)); 
+                double _scale = g_random_double_range(scale_min, scale_max);  
+                if (i==2) {
+                    Inkscape::XML::Node *copy1 = old_repr->duplicate(xml_doc);
+                    parent->appendChild(copy1);
+                    SPObject *new_obj1 = doc->getObjectByRepr(copy1);
+                    fils = (SPItem *) new_obj1;   //conversion object->item
+                    Union=fils;
+                    Inkscape::GC::release(copy1);
+                   }
+
+                if (_fid<=population) { //Rules the population of objects sprayed
+                    // duplicates the father
+                    Inkscape::XML::Node *copy2 = old_repr->duplicate(xml_doc);
+                    parent->appendChild(copy2);
+                    SPObject *new_obj2 = doc->getObjectByRepr(copy2);
+                    item_copied = (SPItem *) new_obj2;
+                    
+                    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());//Move around the cursor                          
+
+                            Geom::Point center=Pere->getCenter();
+                            sp_spray_scale_rel(center,desktop,item_copied, Geom::Scale(_scale,_scale));     
+                            sp_spray_scale_rel(center,desktop,item_copied, Geom::Scale(scale,scale));
+                            sp_spray_rotate_rel(center,desktop,item_copied, Geom::Rotate(angle));
+                            sp_item_move_rel(item_copied, Geom::Translate(move[Geom::X], -move[Geom::Y]));
+
+//UNION et surduplication
+                    selection->clear();
+                    selection->add(item_copied);
+                    selection->add(Union);
+                    sp_selected_path_union(selection->desktop());
+                    selection->add(Pere);
+                    Inkscape::GC::release(copy2);
+                    did = true;
+                }
+
+            }
+        } else if (mode == SPRAY_MODE_CLONE) {
+         
+        Geom::OptRect a = item->getBounds(sp_item_i2doc_affine(item));
+                if (a) {
+                double dr; double dp; 
+                random_position(dr,dp,mean,standard_deviation,_distrib);
+                dr=dr*radius;
+                double _fid = g_random_double_range(0,1);
+                double angle = (g_random_double_range(rot_min, rot_max));
+                double _scale = g_random_double_range(scale_min, scale_max);
+
+        if(_fid<=population)
+                {
+                            SPItem *item_copied; 
+                            SPDocument *doc = SP_OBJECT_DOCUMENT(item);
+                            Inkscape::XML::Document* xml_doc = sp_document_repr_doc(doc);
+                            Inkscape::XML::Node *old_repr = SP_OBJECT_REPR(item);
+                            Inkscape::XML::Node *parent = old_repr->parent();
+
+                            //Creation of the clone
+                            Inkscape::XML::Node *clone = xml_doc->createElement("svg:use");
+                            parent->appendChild(clone); //Ajout du clone à la liste d'enfants du père (selection initiale
+                            clone->setAttribute("xlink:href", g_strdup_printf("#%s", old_repr->attribute("id")), false); //Génère le lien entre les attributs du père et du fils
+                            
+                            SPObject *clone_object = doc->getObjectByRepr(clone); 
+                            item_copied = (SPItem *) clone_object;//conversion object->item
+                              Geom::Point center=item->getCenter();
+                            sp_spray_scale_rel(center,desktop,item_copied, Geom::Scale(_scale,_scale));     
+                            sp_spray_scale_rel(center,desktop,item_copied, Geom::Scale(scale,scale));
+                            sp_spray_rotate_rel(center,desktop,item_copied, Geom::Rotate(angle)); 
+                            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());
+                            sp_item_move_rel(item_copied, Geom::Translate(move[Geom::X], -move[Geom::Y]));                               
+
+                            Inkscape::GC::release(clone);
+
+                            did = true;
+                } }}
+                return did;
+               
+}
+
+
+bool
+sp_spray_color_recursive (guint mode, SPItem *item, SPItem *item_at_point,
+                          guint32 fill_goal, bool do_fill,
+                          guint32 stroke_goal, bool do_stroke,
+                          float opacity_goal, bool do_opacity,
+                          bool do_blur, bool reverse,
+                          Geom::Point p, double radius, double force,
+                          bool do_h, bool do_s, bool do_l, bool do_o)
+{
+    bool did = false;
+
+    return did;
+}
+
+
+bool
+sp_spray_dilate (SPSprayContext *tc, Geom::Point event_p, Geom::Point p, Geom::Point vector, bool reverse)
+{
+    Inkscape::Selection *selection = sp_desktop_selection(SP_EVENT_CONTEXT(tc)->desktop);
+    SPDesktop *desktop = SP_EVENT_CONTEXT(tc)->desktop;
+
+
+    if (selection->isEmpty()) {
+        return false;
+    }
+
+    bool did = false;
+    double radius = get_dilate_radius(tc);
+
+
+
+    bool do_fill = false, do_stroke = false, do_opacity = false;
+    guint32 fill_goal = sp_desktop_get_color_tool(desktop, "/tools/spray", true, &do_fill);
+    guint32 stroke_goal = sp_desktop_get_color_tool(desktop, "/tools/spray", false, &do_stroke);
+    double opacity_goal = sp_desktop_get_master_opacity_tool(desktop, "/tools/spray", &do_opacity);
+    if (reverse) {
+#if 0
+        // HSL inversion
+        float hsv[3];
+        float rgb[3];
+        sp_color_rgb_to_hsv_floatv (hsv,
+                                    SP_RGBA32_R_F(fill_goal),
+                                    SP_RGBA32_G_F(fill_goal),
+                                    SP_RGBA32_B_F(fill_goal));
+        sp_color_hsv_to_rgb_floatv (rgb, hsv[0]<.5? hsv[0]+.5 : hsv[0]-.5, 1 - hsv[1], 1 - hsv[2]);
+        fill_goal = SP_RGBA32_F_COMPOSE(rgb[0], rgb[1], rgb[2], 1);
+        sp_color_rgb_to_hsv_floatv (hsv,
+                                    SP_RGBA32_R_F(stroke_goal),
+                                    SP_RGBA32_G_F(stroke_goal),
+                                    SP_RGBA32_B_F(stroke_goal));
+        sp_color_hsv_to_rgb_floatv (rgb, hsv[0]<.5? hsv[0]+.5 : hsv[0]-.5, 1 - hsv[1], 1 - hsv[2]);
+        stroke_goal = SP_RGBA32_F_COMPOSE(rgb[0], rgb[1], rgb[2], 1);
+#else
+        // RGB inversion
+        fill_goal = SP_RGBA32_U_COMPOSE(
+            (255 - SP_RGBA32_R_U(fill_goal)),
+            (255 - SP_RGBA32_G_U(fill_goal)),
+            (255 - SP_RGBA32_B_U(fill_goal)),
+            (255 - SP_RGBA32_A_U(fill_goal)));
+        stroke_goal = SP_RGBA32_U_COMPOSE(
+            (255 - SP_RGBA32_R_U(stroke_goal)),
+            (255 - SP_RGBA32_G_U(stroke_goal)),
+            (255 - SP_RGBA32_B_U(stroke_goal)),
+            (255 - SP_RGBA32_A_U(stroke_goal)));
+#endif
+        opacity_goal = 1 - opacity_goal;
+    }
+
+    double path_force = get_path_force(tc);
+    if (radius == 0 || path_force == 0) {
+        return false;
+    }
+    double path_mean = get_path_mean(tc);
+    if (radius == 0 || path_mean == 0) {
+        return false;
+    }
+    double path_standard_deviation = get_path_standard_deviation(tc);
+    if (radius == 0 || path_standard_deviation == 0) {
+        return false;
+    }
+    double move_force = get_move_force(tc);
+    double move_mean = get_move_mean(tc);
+    double move_standard_deviation = get_move_standard_deviation(tc);
+
+
+    for (GSList *items = g_slist_copy((GSList *) selection->itemList());
+         items != NULL;
+         items = items->next) {
+
+        SPItem *item = (SPItem *) items->data;
+
+        /*if (is_color_modes (tc->mode)) {
+            if (do_fill || do_stroke || do_opacity) {
+                if (sp_spray_color_recursive (tc->mode, item, item_at_point,
+                                          fill_goal, do_fill,
+                                          stroke_goal, do_stroke,
+                                          opacity_goal, do_opacity,
+                                          tc->mode == SPRAY_MODE_BLUR, reverse,
+                                          p, radius, color_force, tc->do_h, tc->do_s, tc->do_l, tc->do_o))
+                did = true;
+            }
+        }else*/ if (is_transform_modes(tc->mode)) {
+            if (sp_spray_dilate_recursive (desktop,selection, item, p, vector, tc->mode, radius, move_force, tc->population,tc->scale, tc->scale_min, tc->scale_max, reverse, move_mean, move_standard_deviation,tc->ratio,tc->tilt, tc->rot_min, tc->rot_max, tc->distrib))
+                did = true;
+        } else {
+            if (sp_spray_dilate_recursive (desktop,selection, item, p, vector, tc->mode, radius, path_force, tc->population,tc->scale, tc->scale_min, tc->scale_max, reverse, path_mean, path_standard_deviation,tc->ratio,tc->tilt, tc->rot_min, tc->rot_max, tc->distrib))
+                did = true;
+        }
+    }
+
+    return did;
+}
+
+void
+sp_spray_update_area (SPSprayContext *tc)
+{
+        double radius = get_dilate_radius(tc);
+        Geom::Matrix const sm ( Geom::Scale(radius/(1-tc->ratio), radius/(1+tc->ratio)) );
+        sp_canvas_item_affine_absolute(tc->dilate_area,   (sm* Geom::Rotate(tc->tilt))* Geom::Translate(SP_EVENT_CONTEXT(tc)->desktop->point()));
+        sp_canvas_item_show(tc->dilate_area);
+}
+
+void
+sp_spray_switch_mode (SPSprayContext *tc, gint mode, bool with_shift)
+{
+    SP_EVENT_CONTEXT(tc)->desktop->setToolboxSelectOneValue ("spray_tool_mode", mode); //sélectionne le bouton numéro "mode"
+    // need to set explicitly, because the prefs may not have changed by the previous
+    tc->mode = mode;
+    sp_spray_update_cursor (tc, with_shift);
+}
+
+void
+sp_spray_switch_mode_temporarily (SPSprayContext *tc, gint mode, bool with_shift)
+{
+    Inkscape::Preferences *prefs = Inkscape::Preferences::get();
+   // Juggling about so that prefs have the old value but tc->mode and the button show new mode:
+   gint now_mode = prefs->getInt("/tools/spray/mode", 0);
+   SP_EVENT_CONTEXT(tc)->desktop->setToolboxSelectOneValue ("spray_tool_mode", mode);
+   // button has changed prefs, restore
+   prefs->setInt("/tools/spray/mode", now_mode);
+   // changing prefs changed tc->mode, restore back :)
+   tc->mode = mode;
+   sp_spray_update_cursor (tc, with_shift);
+}
+
+gint
+sp_spray_context_root_handler(SPEventContext *event_context,
+                                  GdkEvent *event)
+{
+    SPSprayContext *tc = SP_SPRAY_CONTEXT(event_context);
+    SPDesktop *desktop = event_context->desktop;
+
+    gint ret = FALSE;
+
+    switch (event->type) {
+        case GDK_ENTER_NOTIFY:
+            sp_canvas_item_show(tc->dilate_area);
+            break;
+        case GDK_LEAVE_NOTIFY:
+            sp_canvas_item_hide(tc->dilate_area);
+            break;
+        case GDK_BUTTON_PRESS:
+            if (event->button.button == 1 && !event_context->space_panning) {
+
+                if (Inkscape::have_viable_layer(desktop, tc->_message_context) == false) {
+                    return TRUE;
+                }
+
+                Geom::Point const motion_w(event->button.x,
+                                         event->button.y);
+                Geom::Point const motion_dt(desktop->w2d(motion_w));
+                tc->last_push = desktop->dt2doc(motion_dt);
+
+                sp_spray_extinput(tc, event);
+
+                sp_canvas_force_full_redraw_after_interruptions(desktop->canvas, 3);
+                tc->is_drawing = true;
+                tc->is_dilating = true;
+                                tc->has_dilated = false;
+
+
+
+                if(tc->is_dilating && event->button.button == 1 && !event_context->space_panning)
+
+                                sp_spray_dilate (tc, motion_w, desktop->dt2doc(motion_dt), Geom::Point(0,0), MOD__SHIFT);
+
+
+
+                                                          tc->has_dilated=true;
+
+                ret = TRUE;
+            }
+            break;
+        case GDK_MOTION_NOTIFY:
+        {
+            Geom::Point const motion_w(event->motion.x,
+                                     event->motion.y);
+            Geom::Point motion_dt(desktop->w2d(motion_w));
+            Geom::Point motion_doc(desktop->dt2doc(motion_dt));
+            sp_spray_extinput(tc, event);
+
+            // draw the dilating cursor
+                double radius = get_dilate_radius(tc);
+                Geom::Matrix const sm (Geom::Scale(radius/(1-tc->ratio), radius/(1+tc->ratio)) );
+                sp_canvas_item_affine_absolute(tc->dilate_area, (sm*Geom::Rotate(tc->tilt))*Geom::Translate(desktop->w2d(motion_w)));
+                sp_canvas_item_show(tc->dilate_area);
+
+                guint num = 0;
+                if (!desktop->selection->isEmpty()) {
+                    num = g_slist_length((GSList *) desktop->selection->itemList());
+                }
+                if (num == 0) {
+                    tc->_message_context->flash(Inkscape::ERROR_MESSAGE, _("<b>Nothing selected!</b> Select objects to spray."));
+                }
+
+            // dilating:
+            if (tc->is_drawing && ( event->motion.state & GDK_BUTTON1_MASK )) {
+                sp_spray_dilate (tc, motion_w, motion_doc, motion_doc - tc->last_push, event->button.state & GDK_SHIFT_MASK? true : false);
+                //tc->last_push = motion_doc;
+                tc->has_dilated = true;
+               
+                // it's slow, so prevent clogging up with events
+                gobble_motion_events(GDK_BUTTON1_MASK);
+                return TRUE;
+            }
+
+        }
+        break;
+/*Spray with the scroll*/
+        case GDK_SCROLL:
+               {
+              if (event->scroll.state & GDK_BUTTON1_MASK)
+                                  {
+                  double temp ;
+                  temp=tc->population;
+                  tc->population=1.0;
+                  desktop->setToolboxAdjustmentValue ("population", tc->population * 100);
+                  Geom::Point const scroll_w(event->button.x,event->button.y);
+                  Geom::Point const scroll_dt = desktop->point();;
+                  Geom::Point motion_doc(desktop->dt2doc(scroll_dt));
+                       switch (event->scroll.direction) 
+                       {
+                         case GDK_SCROLL_UP:
+                           {
+                                   if (Inkscape::have_viable_layer(desktop, tc->_message_context) == false)
+                                   {
+                                    return TRUE;
+                                   }
+                                   tc->last_push = desktop->dt2doc(scroll_dt);
+                                   sp_spray_extinput(tc, event);
+                                   sp_canvas_force_full_redraw_after_interruptions(desktop->canvas, 3);
+                                   tc->is_drawing = true;
+                                   tc->is_dilating = true;
+                                   tc->has_dilated = false;
+                                   if(tc->is_dilating && !event_context->space_panning)
+                                                        sp_spray_dilate (tc, scroll_w, desktop->dt2doc(scroll_dt), Geom::Point(0,0),false);
+
+
+                                   tc->has_dilated=true;
+                                   tc->population=temp;
+
+                                   desktop->setToolboxAdjustmentValue ("population", tc->population * 100);
+                                    
+                                   ret = TRUE;
+                           }
+                               break;
+                           case GDK_SCROLL_DOWN:
+                           {
+                                   if (Inkscape::have_viable_layer(desktop, tc->_message_context) == false)
+                                                                   {
+                                                                    return TRUE;
+                                                                   }
+                                                                   tc->last_push = desktop->dt2doc(scroll_dt);
+                                                                   sp_spray_extinput(tc, event);
+                                                                   sp_canvas_force_full_redraw_after_interruptions(desktop->canvas, 3);
+                                                                   tc->is_drawing = true;
+                                                                   tc->is_dilating = true;
+                                                                   tc->has_dilated = false;
+                                                                   if(tc->is_dilating && !event_context->space_panning)
+                                                                                        sp_spray_dilate (tc, scroll_w, desktop->dt2doc(scroll_dt), Geom::Point(0,0), false);
+
+                                                                   tc->has_dilated=true;
+
+                                                                   ret = TRUE;
+
+
+                           }
+                               break;
+case GDK_SCROLL_RIGHT:
+                           {} break;
+case GDK_SCROLL_LEFT:
+                           {} break;
+                                                                                                                   }
+                                  }
+
+
+                               break;
+
+               }
+    case GDK_BUTTON_RELEASE:
+    {
+        Geom::Point const motion_w(event->button.x, event->button.y);
+        Geom::Point const motion_dt(desktop->w2d(motion_w));
+
+        sp_canvas_end_forced_full_redraws(desktop->canvas);
+        tc->is_drawing = false;
+
+        if (tc->is_dilating && event->button.button == 1 && !event_context->space_panning) {
+            if (!tc->has_dilated) {
+                // if we did not rub, do a light tap
+                tc->pressure = 0.03;
+                sp_spray_dilate (tc, motion_w, desktop->dt2doc(motion_dt), Geom::Point(0,0), MOD__SHIFT);
+            }
+            tc->is_dilating = false;
+            tc->has_dilated = false;
+            switch (tc->mode) {
+                case SPRAY_MODE_COPY:
+                    sp_document_done(sp_desktop_document(SP_EVENT_CONTEXT(tc)->desktop),
+                                     SP_VERB_CONTEXT_SPRAY, _("Spray with copies"));
+                    break;
+                case SPRAY_MODE_CLONE:
+                    sp_document_done(sp_desktop_document(SP_EVENT_CONTEXT(tc)->desktop),
+                                     SP_VERB_CONTEXT_SPRAY, _("Spray with clones"));
+                    break;
+                case SPRAY_MODE_SINGLE_PATH:
+                    sp_document_done(sp_desktop_document(SP_EVENT_CONTEXT(tc)->desktop),
+                                     SP_VERB_CONTEXT_SPRAY, _("Spray in single path"));
+                    break;
+            }
+        }
+        break;
+    }
+
+    case GDK_KEY_PRESS:
+        switch (get_group0_keyval (&event->key)) {
+case GDK_j:  if (MOD__SHIFT_ONLY) {
+                sp_spray_switch_mode(tc, SPRAY_MODE_COPY, MOD__SHIFT);
+                ret = TRUE;
+            }   
+case GDK_J: if (MOD__SHIFT_ONLY) {
+                sp_spray_switch_mode(tc, SPRAY_MODE_COPY, MOD__SHIFT);
+                ret = TRUE;
+            }
+                
+break;
+        case GDK_m:
+        case GDK_M:
+        case GDK_0:
+        
+            break;
+        case GDK_i:
+        case GDK_I:
+        case GDK_k:    if (MOD__SHIFT_ONLY) {
+                sp_spray_switch_mode(tc, SPRAY_MODE_SINGLE_PATH, MOD__SHIFT);
+                ret = TRUE;
+            }
+        case GDK_K:if (MOD__SHIFT_ONLY) {
+                sp_spray_switch_mode(tc, SPRAY_MODE_SINGLE_PATH, MOD__SHIFT);
+                ret = TRUE;
+            }
+break;
+   
+        case GDK_l: if (MOD__SHIFT_ONLY) {
+                sp_spray_switch_mode(tc, SPRAY_MODE_CLONE, MOD__SHIFT);
+                ret = TRUE;
+            }
+            
+        case GDK_L:
+ if (MOD__SHIFT_ONLY) {
+                sp_spray_switch_mode(tc, SPRAY_MODE_CLONE, MOD__SHIFT);
+                ret = TRUE;
+            }
+            break;
+        case GDK_Up:
+        case GDK_KP_Up:
+            if (!MOD__CTRL_ONLY) {
+                tc->scale += 0.05;
+
+                //desktop->setToolboxAdjustmentValue ("spray-force", tc->force * 100);
+                ret = TRUE;
+            }
+            break;
+        case GDK_Down:
+        case GDK_KP_Down:
+            if (!MOD__CTRL_ONLY) {
+
+                tc->scale -= 0.05;
+                if (tc->scale < 0.0)
+                    tc->scale = 0.0;
+                //desktop->setToolboxAdjustmentValue ("spray-force", tc->force * 100);
+
+                ret = TRUE;
+
+            }
+            break;
+        case GDK_Right:
+        case GDK_KP_Right:
+            if (!MOD__CTRL_ONLY) {
+                tc->width += 0.01;
+                if (tc->width > 1.0)
+                    tc->width = 1.0;
+                desktop->setToolboxAdjustmentValue ("altx-spray", tc->width * 100); // the same spinbutton is for alt+x
+                sp_spray_update_area(tc);
+                ret = TRUE;
+            }
+            break;
+        case GDK_Left:
+        case GDK_KP_Left:
+            if (!MOD__CTRL_ONLY) {
+                tc->width -= 0.01;
+                if (tc->width < 0.01)
+                    tc->width = 0.01;
+                desktop->setToolboxAdjustmentValue ("altx-spray", tc->width * 100);
+                sp_spray_update_area(tc);
+                ret = TRUE;
+            }
+            break;
+        case GDK_Home:
+        case GDK_KP_Home:
+            tc->width = 0.01;
+            desktop->setToolboxAdjustmentValue ("altx-spray", tc->width * 100);
+            sp_spray_update_area(tc);
+            ret = TRUE;
+            break;
+        case GDK_End:
+        case GDK_KP_End:
+            tc->width = 1.0;
+            desktop->setToolboxAdjustmentValue ("altx-spray", tc->width * 100);
+            sp_spray_update_area(tc);
+            ret = TRUE;
+            break;
+        case GDK_x:
+        case GDK_X:
+            if (MOD__ALT_ONLY) {
+                desktop->setToolboxFocusTo ("altx-spray");
+                ret = TRUE;
+            }
+            break;
+
+        case GDK_Shift_L:
+        case GDK_Shift_R:
+            sp_spray_update_cursor(tc, true);
+            break;
+/*Set the scale to 1*/
+        case GDK_Control_L:
+                tc->scale=1;
+        default:
+            break;
+        }
+        break;
+
+    case GDK_KEY_RELEASE: {
+        Inkscape::Preferences *prefs = Inkscape::Preferences::get();
+        switch (get_group0_keyval(&event->key)) {
+            case GDK_Shift_L:
+            case GDK_Shift_R:
+                sp_spray_update_cursor(tc, false);
+                break;
+            case GDK_Control_L:
+            case GDK_Control_R:
+                sp_spray_switch_mode (tc, prefs->getInt("/tools/spray/mode"), MOD__SHIFT);
+                tc->_message_context->clear();
+                break;
+            default:
+                sp_spray_switch_mode (tc, prefs->getInt("/tools/spray/mode"), MOD__SHIFT);
+                break;
+        }
+    }
+
+    default:
+        break;
+    }
+
+    if (!ret) {
+        if (((SPEventContextClass *) parent_class)->root_handler) {
+            ret = ((SPEventContextClass *) parent_class)->root_handler(event_context, event);
+        }
+    }
+
+    return ret;
+}
+
+/*
+  Local Variables:
+  mode:c++
+  c-file-style:"stroustrup"
+  c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+  indent-tabs-mode:nil
+  fill-column:99
+  End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :
+
diff --git a/src/spray-context.h b/src/spray-context.h
new file mode 100644 (file)
index 0000000..f8822ce
--- /dev/null
@@ -0,0 +1,125 @@
+#ifndef __SP_SPRAY_CONTEXT_H__
+#define __SP_SPRAY_CONTEXT_H__
+
+/*
+ * Spray Tool
+ *
+ * Authors:
+ *   Pierre-Antoine MARC
+ *   Pierre CACLIN
+ *   Aurel-Aimé MARMION   
+ *   Julien LERAY
+ *   Benoît LAVORATA
+ *   Vincent MONTAGNE
+ *   Pierre BARBRY-BLOT
+ *
+ * Copyright (C) 2009 authors
+ *
+ * Released under GNU GPL, read the file 'COPYING' for more information
+ */
+
+#include "event-context.h"
+#include <display/display-forward.h>
+#include <libnr/nr-point.h>
+//#include "ui/widget/spray-option.h"
+#include "ui/dialog/dialog.h"
+
+#define SP_TYPE_SPRAY_CONTEXT (sp_spray_context_get_type())
+#define SP_SPRAY_CONTEXT(o) (GTK_CHECK_CAST((o), SP_TYPE_SPRAY_CONTEXT, SPSprayContext))
+#define SP_SPRAY_CONTEXT_CLASS(k) (GTK_CHECK_CLASS_CAST((k), SP_TYPE_SPRAY_CONTEXT, SPSprayContextClass))
+#define SP_IS_SPRAY_CONTEXT(o) (GTK_CHECK_TYPE((o), SP_TYPE_SPRAY_CONTEXT))
+#define SP_IS_SPRAY_CONTEXT_CLASS(k) (GTK_CHECK_CLASS_TYPE((k), SP_TYPE_SPRAY_CONTEXT))
+
+class SPSprayContext;
+class SPSprayContextClass;
+
+namespace Inkscape {
+  namespace UI {
+      namespace Dialog {
+          class Dialog;
+      }
+  }
+}
+
+
+#define SAMPLING_SIZE 8        /* fixme: ?? */
+
+#define TC_MIN_PRESSURE      0.0
+#define TC_MAX_PRESSURE      1.0
+#define TC_DEFAULT_PRESSURE  0.35
+
+enum {
+    SPRAY_MODE_COPY,
+    SPRAY_MODE_CLONE,
+    SPRAY_MODE_SINGLE_PATH,    
+    SPRAY_OPTION,
+};
+
+struct SPSprayContext
+{
+    SPEventContext event_context;
+    //Inkscape::UI::Dialog::Dialog *dialog_option;//Attribut de type SprayOptionClass, localisé dans scr/ui/dialog    
+    /* extended input data */
+    gdouble pressure;
+
+    /* attributes */
+    guint dragging : 1;           /* mouse state: mouse is dragging */
+    guint usepressure : 1;
+    guint usetilt : 1;
+    bool usetext ;
+
+    double width;
+    double ratio;
+    double tilt;
+    double rot_min;
+    double rot_max;
+    double force;
+    double population;
+    double scale_min;
+    double scale_max;
+    double scale;
+    double mean;
+    double standard_deviation;
+   
+    gint distrib;
+
+    gint mode;
+
+    Inkscape::MessageContext *_message_context;
+
+    bool is_drawing;
+
+    bool is_dilating;
+    bool has_dilated;
+    Geom::Point last_push;
+    SPCanvasItem *dilate_area;
+
+    bool do_h;
+    bool do_s;
+    bool do_l;
+    bool do_o;
+
+    sigc::connection style_set_connection;
+};
+
+struct SPSprayContextClass
+{
+    SPEventContextClass parent_class;
+};
+
+GtkType sp_spray_context_get_type(void);
+
+
+#endif
+
+/*
+  Local Variables:
+  mode:c++
+  c-file-style:"stroustrup"
+  c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+  indent-tabs-mode:nil
+  fill-column:99
+  End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :
+
index 7902a79883f9da6e6231c7adfac3056ac54d79eb..6c53ce61c8183d8e9532d8ba7fc4562e213d5c50 100644 (file)
@@ -28,6 +28,7 @@
 #include "select-context.h"
 #include "node-context.h"
 #include "tweak-context.h"
+#include "spray-context.h"
 #include "sp-path.h"
 #include "rect-context.h"
 #include "sp-rect.h"
@@ -62,6 +63,7 @@ static char const *const tool_names[] = {
     "/tools/select",
     "/tools/nodes",
     "/tools/tweak",
+    "/tools/spray",
     "/tools/shapes/rect",
     "/tools/shapes/3dbox",
     "/tools/shapes/arc",
@@ -135,6 +137,12 @@ tools_switch(SPDesktop *dt, int num)
             inkscape_eventcontext_set(sp_desktop_event_context(dt));
             dt->tipsMessageContext()->set(Inkscape::NORMAL_MESSAGE, _("To tweak a path by pushing, select it and drag over it."));
             break;
+        case TOOLS_SPRAY:
+            dt->set_event_context(SP_TYPE_SPRAY_CONTEXT, tool_names[num]);
+            dt->activate_guides(true);
+            inkscape_eventcontext_set(sp_desktop_event_context(dt));
+            dt->tipsMessageContext()->set(Inkscape::NORMAL_MESSAGE, _("To spray a path by pushing, select it and drag over it."));
+            break;
         case TOOLS_SHAPES_RECT:
             dt->set_event_context(SP_TYPE_RECT_CONTEXT, tool_names[num]);
             dt->activate_guides(false);
index 36dd8f80bac69a3f135d3d80d108933b9d9cdc1e..4cc9aa93d8649015e41d4d61e5335725a8287b8f 100644 (file)
@@ -19,6 +19,7 @@ enum {
   TOOLS_SELECT,
   TOOLS_NODES,
   TOOLS_TWEAK,
+  TOOLS_SPRAY,
   TOOLS_SHAPES_RECT,
   TOOLS_SHAPES_3DBOX,
   TOOLS_SHAPES_ARC,
index 565a24ecc049e5f8913120db0e51e6808a2e0959..fd1b073943e1192b58e7e9f63d2acd76d46466a0 100644 (file)
@@ -73,6 +73,8 @@ ink_common_sources +=         \
        ui/dialog/print.h                       \
        ui/dialog/scriptdialog.cpp              \
        ui/dialog/scriptdialog.h                \
+       ui/dialog/spray-option.cpp              \
+       ui/dialog/spray-option.h                \
        ui/dialog/svg-fonts-dialog.cpp          \
        ui/dialog/svg-fonts-dialog.h            \
        ui/dialog/swatches.cpp                  \
index d1b818d236a781f6eacd8b1ca88b94bac2901367..7f853bedcdd17b75034ed3ea5026fa1d719205b8 100644 (file)
@@ -40,6 +40,7 @@
 #include "ui/dialog/icon-preview.h"
 #include "ui/dialog/floating-behavior.h"
 #include "ui/dialog/dock-behavior.h"
+#include "ui/dialog/spray-option.h"
 #include "preferences.h"
 
 #ifdef ENABLE_SVG_FONTS
@@ -88,7 +89,6 @@ DialogManager::DialogManager() {
     int dialogs_type = prefs->getIntLimited("/options/dialogtype/value", DOCK, 0, 1);
 
     if (dialogs_type == FLOATING) {
-
         registerFactory("AlignAndDistribute",  &create<AlignAndDistribute,   FloatingBehavior>);
         registerFactory("DocumentMetadata",    &create<DocumentMetadata,     FloatingBehavior>);
         registerFactory("DocumentProperties",  &create<DocumentProperties,   FloatingBehavior>);
@@ -111,7 +111,8 @@ DialogManager::DialogManager() {
         registerFactory("Trace",               &create<TraceDialog,          FloatingBehavior>);
         registerFactory("Transformation",      &create<Transformation,       FloatingBehavior>);
         registerFactory("UndoHistory",         &create<UndoHistory,          FloatingBehavior>);
-        registerFactory("InputDevices",        &create<InputDialog,           FloatingBehavior>);
+        registerFactory("InputDevices",        &create<InputDialog,          FloatingBehavior>);
+        registerFactory("SprayOptionClass",    &create<SprayOptionClass,     FloatingBehavior>);
 
     } else {
 
@@ -138,6 +139,7 @@ DialogManager::DialogManager() {
         registerFactory("Transformation",      &create<Transformation,       DockBehavior>);
         registerFactory("UndoHistory",         &create<UndoHistory,          DockBehavior>);
         registerFactory("InputDevices",        &create<InputDialog,          DockBehavior>);
+        registerFactory("SprayOptionClass",    &create<SprayOptionClass,     DockBehavior>);
 
     }
 }
index c7dc789ca7fbbc876dd2924bc139c1127515b050..6e30ef61a39623d53cf5e8f37e3e71d26fe4a3ad 100644 (file)
@@ -449,6 +449,12 @@ void InkscapePreferences::initPageTools()
     AddSelcueCheckbox(_page_tweak, "/tools/tweak", true);
     AddGradientCheckbox(_page_tweak, "/tools/tweak", false);
 
+ //Spray
+    this->AddPage(_page_spray, _("Spray"), iter_tools, PREFS_PAGE_TOOLS_SPRAY);
+    this->AddNewObjectsStyle(_page_spray, "/tools/spray", _("Paint objects with:"));
+    AddSelcueCheckbox(_page_spray, "/tools/spray", true);
+    AddGradientCheckbox(_page_spray, "/tools/spray", false);
+
     //Zoom
     this->AddPage(_page_zoom, _("Zoom"), iter_tools, PREFS_PAGE_TOOLS_ZOOM);
     AddSelcueCheckbox(_page_zoom, "/tools/zoom", true);
index 364b0eb1da2195f141946b94a600e815fb757063..705e7a352007dbab597699dd38939da6f93a0174 100644 (file)
@@ -43,6 +43,7 @@ enum {
     PREFS_PAGE_TOOLS_SELECTOR,
     PREFS_PAGE_TOOLS_NODE,
     PREFS_PAGE_TOOLS_TWEAK,
+  PREFS_PAGE_TOOLS_SPRAY,
     PREFS_PAGE_TOOLS_ZOOM,
     PREFS_PAGE_TOOLS_SHAPES,
     PREFS_PAGE_TOOLS_SHAPES_RECT,
@@ -118,7 +119,7 @@ protected:
         _page_clones, _page_mask, _page_transforms, _page_filters, _page_select,
         _page_importexport, _page_cms, _page_grids, _page_svgoutput, _page_misc,
         _page_ui, _page_save, _page_bitmaps, _page_spellcheck;
-    DialogPage _page_selector, _page_node, _page_tweak, _page_zoom, _page_shapes, _page_pencil, _page_pen,
+    DialogPage _page_selector, _page_node, _page_tweak, _page_spray, _page_zoom, _page_shapes, _page_pencil, _page_pen,
                _page_calligraphy, _page_text, _page_gradient, _page_connector, _page_dropper, _page_lpetool;
     DialogPage _page_rectangle, _page_3dbox, _page_ellipse, _page_star, _page_spiral, _page_paintbucket, _page_eraser;
 
diff --git a/src/ui/dialog/spray-option.cpp b/src/ui/dialog/spray-option.cpp
new file mode 100644 (file)
index 0000000..8bfe455
--- /dev/null
@@ -0,0 +1,381 @@
+/*Julien LERAY (julien.leray@ecl2010.ec-lyon.fr), interface for the spray tool*/
+
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <gtkmm/spinbutton.h>
+
+#include "desktop-handles.h"
+#include "unclump.h"
+#include "document.h"
+#include "enums.h"
+#include "graphlayout/graphlayout.h"
+#include "inkscape.h"
+#include "macros.h"
+#include "node-context.h" 
+#include "preferences.h"
+#include "removeoverlap/removeoverlap.h"
+#include "selection.h"
+#include "shape-editor.h" 
+#include "sp-flowtext.h"
+#include "sp-item-transform.h"
+#include "sp-text.h"
+#include "text-editing.h"
+#include "tools-switch.h"
+#include "ui/icon-names.h"
+#include "util/glib-list-iterators.h"
+#include "verbs.h"
+#include "widgets/icon.h"
+
+#include "spray-option.h"
+
+namespace Inkscape {
+namespace UI {
+namespace Dialog {
+
+
+//Classes qui permettent de créer les environnements Gaussienne, Witdh...
+
+
+
+class Action {
+public:
+    Action(const Glib::ustring &id,
+           const Glib::ustring &tiptext,
+           guint row, guint column,
+           Gtk::Table &parent,
+           Gtk::Tooltips &tooltips,
+           SprayOptionClass &dialog):
+        _dialog(dialog),
+        _id(id),
+        _parent(parent) {}
+    
+    virtual ~Action(){}
+    virtual void on_button_click(){}
+    SprayOptionClass &_dialog;
+    
+private :
+    
+    Glib::ustring _id;
+    Gtk::Table &_parent;
+};
+
+class ActionE : public Action {
+private:
+    Gtk::Label _Label;
+    Gtk::SpinButton _Gap;
+    guint _min, _max;
+    Glib::ustring _pref_path;
+
+public:
+    ActionE(const Glib::ustring &id,
+                const Glib::ustring &tiptext,
+                guint row, guint column,
+                SprayOptionClass &dialog,
+                guint min, guint max,
+                Glib::ustring const &pref_path ):
+        Action(id, tiptext, row, column,
+               dialog._Table(), dialog.tooltips(), dialog),
+        _min(min),
+        _max(max),
+        _pref_path(pref_path)
+        {
+            dialog._Table().set_col_spacings(3);
+
+            double increm = ((double)_max - (double)_min)/10;
+            double val_ini = ((double)_max + (double)_min)/2;            
+            _Gap.set_digits(1);
+            _Gap.set_size_request(60, -1);
+            _Gap.set_increments(increm , 0);
+            _Gap.set_range(_min, _max);
+            _Gap.set_value(val_ini);
+            dialog.tooltips().set_tip(_Gap,
+                                  tiptext);
+            _Gap.signal_changed().connect(sigc::mem_fun(*this, &ActionE::on_button_click));  //rajout douteux
+            _Label.set_label(id);
+
+            dialog._Table().attach(_Label, column, column+1, row, row+1, Gtk::FILL, Gtk::FILL);
+            dialog._Table().attach(_Gap, column+1, column+2, row, row+1, Gtk::EXPAND, Gtk::EXPAND);
+        }
+
+    virtual void on_button_click(){
+        if (!_dialog.getDesktop()) return;
+              
+        Inkscape::Preferences *prefs = Inkscape::Preferences::get();
+        
+        prefs->setDouble(_pref_path, SP_VERB_CONTEXT_SPRAY);
+       
+        double const Gap = _Gap.get_value();
+        
+         
+        prefs->setDouble(_pref_path, Gap);
+
+        sp_document_done(sp_desktop_document(_dialog.getDesktop()), SP_VERB_CONTEXT_SPRAY,
+                         _("Remove overlaps"));
+    }
+
+
+};    
+
+class ActionF : public Action {
+private:
+    Gtk::Label _Label;
+    Gtk::Label _Label1;
+    Gtk::Label _Label2;
+    Gtk::SpinButton _Gap1;
+    Gtk::SpinButton _Gap2;
+    Glib::ustring _pref1_path;
+    Glib::ustring _pref2_path;
+
+public:
+    ActionF(const Glib::ustring &id,
+                const Glib::ustring &tiptext,
+                guint row, guint column,
+                SprayOptionClass &dialog,
+                Glib::ustring const &pref1_path,
+                Glib::ustring const &pref2_path ):
+        Action(id, tiptext, row, column,
+               dialog._Table(), dialog.tooltips(), dialog),
+        _pref1_path(pref1_path),
+        _pref2_path(pref2_path)
+        {
+            dialog.F_Table().set_col_spacings(3);
+
+            _Label.set_label(id);            
+
+            _Gap1.set_digits(1);
+            _Gap1.set_size_request(60, -1);
+            _Gap1.set_increments(0.1, 0);
+            _Gap1.set_range(0, 10);
+            _Gap1.set_value(1);
+            dialog.tooltips().set_tip(_Gap1,
+                                  _("Minimum"));
+        
+            _Label1.set_label(Q_("Min"));
+
+            _Gap2.set_digits(1);
+            _Gap2.set_size_request(60, -1);
+            _Gap2.set_increments(0.1, 0);
+            _Gap2.set_range(0, 10);
+            _Gap2.set_value(1);
+            dialog.tooltips().set_tip(_Gap2,
+                                  _("Maximum"));
+        
+            _Label2.set_label(_("Max:"));
+            
+            _Gap1.signal_changed().connect(sigc::mem_fun(*this, &ActionF::on_button_click));
+            _Gap2.signal_changed().connect(sigc::mem_fun(*this, &ActionF::on_button_click)); 
+
+            dialog.F_Table().attach(_Label, column, column+1, row, row+1, Gtk::FILL, Gtk::FILL);
+            dialog.F_Table().attach(_Label1, column+1, column+2, row, row+1, Gtk::FILL, Gtk::FILL);
+            dialog.F_Table().attach(_Gap1, column+2, column+3, row, row+1, Gtk::EXPAND, Gtk::EXPAND);
+            dialog.F_Table().attach(_Label2, column+3, column+4, row, row+1, Gtk::FILL, Gtk::FILL);
+            dialog.F_Table().attach(_Gap2, column+4, column+5, row, row+1, Gtk::EXPAND, Gtk::EXPAND);
+
+        }
+
+    virtual void on_button_click(){
+        if (!_dialog.getDesktop()) return;
+              
+        Inkscape::Preferences *prefs = Inkscape::Preferences::get();
+        
+        prefs->setDouble(_pref1_path, SP_VERB_CONTEXT_SPRAY);
+        prefs->setDouble(_pref2_path, SP_VERB_CONTEXT_SPRAY);
+       
+        double const Gap1 = _Gap1.get_value();
+        double const Gap2 = _Gap2.get_value();
+                 
+        prefs->setDouble(_pref1_path, Gap1);
+        prefs->setDouble(_pref2_path, Gap2);
+
+        sp_document_done(sp_desktop_document(_dialog.getDesktop()), SP_VERB_CONTEXT_SPRAY,
+                         _("Remove overlaps"));
+    }
+
+
+};    
+
+
+
+void SprayOptionClass::combo_action() {
+    Inkscape::Preferences *prefs = Inkscape::Preferences::get();
+    cout<<"combo.get_active_row_number = "<<_combo.get_active_row_number()<<endl;
+        
+    int const distrib = _combo.get_active_row_number();
+                 
+    prefs->setInt("/tools/spray/distribution", distrib);
+       
+
+    sp_document_done(sp_desktop_document(this->getDesktop()), SP_VERB_CONTEXT_SPRAY,
+                         _("Remove overlaps"));    
+
+}
+
+
+
+
+void SprayOptionClass::action() {
+    int r=1;    
+    for (list<Action *>::iterator it = _actionList.begin();
+         it != _actionList.end();
+         it ++)
+        (*it)->on_button_click();
+    combo_action();
+}
+
+
+
+
+
+
+void on_selection_changed(Inkscape::Application */*inkscape*/, Inkscape::Selection */*selection*/, SprayOptionClass *daad)
+{
+    daad->randomize_bbox = Geom::OptRect();
+}
+
+/////////////////////////////////////////////////////////
+//Construction de l'interface
+/////////////////////////////////////////////////////////
+
+
+SprayOptionClass::SprayOptionClass()
+    : UI::Widget::Panel ("", "/dialogs/spray", SP_VERB_DIALOG_SPRAY_OPTION),
+      _distributionFrame(_("Distribution")),
+      _Frame(_("Cursor Options")),
+      _FFrame(_("Random Options")),
+      _gaussianTable(1, 5, false),
+      _ETable(3,2,false),
+      _FTable(2,5,false),
+      _unifLabel(_("Uniform")),
+      _gaussLabel(_("Gaussian   ")),
+      _anchorLabel(_("Distribution : "))
+      
+{
+    Inkscape::Preferences *prefs = Inkscape::Preferences::get();
+
+    //ComboBoxText
+
+    _combo.append_text(_("Uniforme"));
+    _combo.append_text(_("Gaussienne"));
+    
+    _combo.set_active(prefs->getInt("/tools/spray/distribution", 1));
+    _combo.signal_changed().connect(sigc::mem_fun(*this, &SprayOptionClass::combo_action));
+
+    _anchorBox.pack_start(_anchorLabel);
+    _anchorBox.pack_start(_combo);
+
+    _gaussianBox.pack_start(_anchorBox);
+
+
+    _distributionBox.pack_start(_gaussianBox);
+    _distributionFrame.add(_distributionBox);
+
+
+    //Hbox Random
+    addFButton(_("Scale : ") ,_("Applique un facteur d'échelle"), 0, 0, "/tools/spray/scale_min","/tools/spray/scale_max");
+    addFButton(_("Rotation : ") ,_("Fait tourner"), 1, 0, "/tools/spray/rot_min","/tools/spray/rot_max");
+    _FHBox.pack_start(_FLabel);
+    _FHBox.pack_start(_FTable);
+
+    //Implementation dans la Vbox Cursor
+    _FVBox.pack_start(_FHBox);
+    _FFrame.add(_FVBox);    
+
+    //Hbox Cursor
+    addEButton(_("Ratio : ") ,_("Excentricité de l'ellipse"), 0, 0, 0, 1,"/tools/spray/ratio");
+    addEButton(_("Angle : ") ,_("Angle de l'ellipse"), 1, 0, 0, 5,"/tools/spray/tilt");
+    addEButton(_("Width : ") ,_("Taille de l'ellipse"), 2, 0, 0, 1,"/tools/spray/width");
+    _HBox.pack_start(_Label);
+    _HBox.pack_start(_ETable);
+
+    //Implementation dans la Vbox Cursor
+    _VBox.pack_start(_HBox);
+    _Frame.add(_VBox);
+
+    Gtk::Box *contents = _getContents();
+    contents->set_spacing(4);
+
+    
+    
+
+    
+
+    // Crée dans l'ordre suivant les différentes Frames (cadres de réglages)
+
+    contents->pack_start(_distributionFrame, true, true);
+    contents->pack_start(_FFrame, true, true);    
+    contents->pack_start(_Frame, true, true);
+    
+    
+
+    // Connect to the global selection change, to invalidate cached randomize_bbox
+    g_signal_connect (G_OBJECT (INKSCAPE), "change_selection", G_CALLBACK (on_selection_changed), this);
+    randomize_bbox = Geom::OptRect();
+
+    show_all_children();
+    
+    
+
+}
+
+SprayOptionClass::~SprayOptionClass()
+{
+    sp_signal_disconnect_by_data (G_OBJECT (INKSCAPE), this);
+
+    for (std::list<Action *>::iterator it = _actionList.begin();
+         it != _actionList.end();
+         it ++)
+        delete *it;
+}
+
+
+
+
+
+
+
+//Fonctions qui lient la demande d'ajout d'une interface graphique à l'action correspondante
+
+void SprayOptionClass::addEButton(const Glib::ustring &id,
+                const Glib::ustring &tiptext,
+                guint row, guint column,
+                guint min, guint max,
+                Glib::ustring const &pref_path) 
+{
+        _actionList.push_back( new ActionE(id, tiptext,row, column,*this,min ,max, pref_path ));
+}
+
+void SprayOptionClass::addFButton(const Glib::ustring &id,
+                const Glib::ustring &tiptext,
+                guint row, guint column,
+                Glib::ustring const &pref1_path,
+                Glib::ustring const &pref2_path) 
+{
+        _actionList.push_back( new ActionF(id, tiptext,row, column,*this,pref1_path, pref2_path ));
+}
+
+
+
+
+
+SprayOptionClass &SprayOptionClass::get_SprayOptionClass()
+{
+    return *this;
+}
+
+} // namespace Dialog
+} // namespace UI
+} // namespace Inkscape
+
+/*
+  Local Variables:
+  mode:c++
+  c-file-style:"stroustrup"
+  c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+  indent-tabs-mode:nil
+  fill-column:99
+  End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :
diff --git a/src/ui/dialog/spray-option.h b/src/ui/dialog/spray-option.h
new file mode 100644 (file)
index 0000000..75dfe1e
--- /dev/null
@@ -0,0 +1,130 @@
+
+/*Julien LERAY (julien.leray@ecl2010.ec-lyon.fr), interface for the spray tool*/
+
+#ifndef INKSCAPE_UI_DIALOG_SPRAY_OPTION_H
+#define INKSCAPE_UI_DIALOG_SPRAY_OPTION_H
+
+#include <gtkmm/notebook.h>
+#include <glibmm/i18n.h>
+
+#include <list>
+#include <gtkmm/frame.h>
+#include <gtkmm/tooltips.h>
+#include <gtkmm/comboboxtext.h>
+#include <gtkmm/table.h>
+#include <gtkmm/buttonbox.h>
+#include <gtkmm/label.h>
+#include "libnr/nr-dim2.h"
+#include "libnr/nr-rect.h"
+
+
+#include "ui/widget/panel.h"
+#include "ui/widget/notebook-page.h"
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <gtkmm/spinbutton.h>
+#include "desktop-handles.h"
+#include "unclump.h"
+#include "document.h"
+#include "enums.h"
+#include "graphlayout/graphlayout.h"
+#include "inkscape.h"
+#include "macros.h"
+#include "node-context.h" 
+#include "preferences.h"
+#include "removeoverlap/removeoverlap.h"
+#include "selection.h"
+#include "shape-editor.h" 
+#include "sp-flowtext.h"
+#include "sp-item-transform.h"
+#include "sp-text.h"
+#include "text-editing.h"
+#include "tools-switch.h"
+#include "ui/icon-names.h"
+#include "util/glib-list-iterators.h"
+#include "verbs.h"
+#include "widgets/icon.h"
+
+#include "spray-context.h"
+#include "verbs.h"
+
+#include <iostream>
+using namespace std;
+
+using namespace Inkscape::UI::Widget;
+
+class SPItem;
+
+
+namespace Inkscape {
+namespace UI {
+namespace Dialog {
+
+class Action;
+
+class SprayOptionClass : public Widget::Panel {
+
+private:
+
+    SprayOptionClass(SprayOptionClass const &d);
+    SprayOptionClass& operator=(SprayOptionClass const &d);
+    
+public:
+    SprayOptionClass();
+    virtual ~SprayOptionClass();   
+    void test() {    cout<<"appel de test !!"<<endl;  }
+    static SprayOptionClass &getInstance() { return *new SprayOptionClass(); }
+
+    
+    Gtk::Table &_Table(){return _ETable;}
+    Gtk::Table &F_Table(){return _FTable;}
+    Gtk::Tooltips &tooltips(){return _tooltips;}
+    void action();
+    void combo_action(); 
+    Geom::OptRect randomize_bbox;
+
+    SprayOptionClass &get_SprayOptionClass();
+
+protected:
+
+    void addGaussianButton(guint row, guint col);
+    void addEButton(const Glib::ustring &id, const Glib::ustring &tiptext, guint row, guint column,
+                guint min, guint max, const Glib::ustring &pref_path);
+    void addFButton(const Glib::ustring &id, const Glib::ustring &tiptext, guint row, guint column,
+                const Glib::ustring &pref1_path, const Glib::ustring &pref2_path);
+
+    std::list<Action *> _actionList;
+    Gtk::Frame _distributionFrame,  _Frame, _FFrame ;
+    Gtk::Table _distributionTable, _gaussianTable, _ETable, _FTable;
+    Gtk::HBox _anchorBox;
+    Gtk::HBox _unifBox, _gaussianBox, _HBox, _FHBox, _BoutonBox;
+    Gtk::VBox _distributionBox,  _VBox, _FVBox, _ActionBox;
+    Gtk::Label _anchorLabel;
+    Gtk::Label _unifLabel, _gaussLabel, _Label, _FLabel;
+    Gtk::CheckButton _unif, _gauss;
+    Gtk::ComboBoxText _combo;
+    Gtk::Tooltips _tooltips;
+
+};
+
+
+} // namespace Dialog
+} // namespace UI
+} // namespace Inkscape
+
+#endif // INKSCAPE_UI_DIALOG_ALIGN_AND_DISTRIBUTE_H
+
+/*
+  Local Variables:
+  mode:c++
+  c-file-style:"stroustrup"
+  c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+  indent-tabs-mode:nil
+  fill-column:99
+  End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :
+
index f9a6f2a7d59e80ca4492e21b6b26fadaaa2bc6ba..0388b200f48036450136c499b7197e5a875626e1 100644 (file)
     "snap-nodes-smooth"
 #define INKSCAPE_ICON_SNAP_PAGE \
     "snap-page"
+#define INKSCAPE_ICON_SPRAY_COPY_MODE \
+    "spray-copy-mode"
+#define INKSCAPE_ICON_SPRAY_CLONE_MODE \
+    "spray-clone-mode"
+#define INKSCAPE_ICON_SPRAY_UNION_MODE \
+    "spray-union-mode"
+#define INKSCAPE_ICON_DIALOG_SPRAY_OPTIONS \
+    "dialog-spray-options"
 #define INKSCAPE_ICON_STROKE_CAP_BUTT \
     "stroke-cap-butt"
 #define INKSCAPE_ICON_STROKE_CAP_ROUND \
     "tool-pointer"
 #define INKSCAPE_ICON_TOOL_TWEAK \
     "tool-tweak"
+#define INKSCAPE_ICON_TOOL_SPRAY \
+    "tool-spray"
 #define INKSCAPE_ICON_TRANSFORM_AFFECT_GRADIENT \
     "transform-affect-gradient"
 #define INKSCAPE_ICON_TRANSFORM_AFFECT_PATTERN \
index 770a9bf87c076472040c5f5c39a0400e106d4f12..d34b18771a9bc750e5ec75d410119485d00fd7e2 100644 (file)
@@ -227,6 +227,12 @@ EditWidget::onDialogAlignAndDistribute()
     _dlg_mgr.showDialog("AlignAndDistribute");
 }
 
+void
+EditWidget::onDialogSprayOptionClass()
+{
+    _dlg_mgr.showDialog("SprayOptionClass");
+}
+
 void
 EditWidget::onDialogDocumentProperties()
 {
index 2bb7083054f817c459662620a6338d42f0b32dc8..452641e8023b2d5d27a8e901316a7912debbacf6 100644 (file)
@@ -70,6 +70,7 @@ public:
 
     void onDialogAbout();
     void onDialogAlignAndDistribute();
+    void onDialogSprayOptionClass();
     void onDialogInkscapePreferences();
     void onDialogDialog();
     void onDialogDocumentProperties();
index 29d24c10143690aa54f7a097ad73e5f5bbb5f7f7..56b63e95eb2bd305796789ec0e7556284285f7a5 100644 (file)
@@ -1464,6 +1464,9 @@ ContextVerb::perform(SPAction *action, void *data, void */*pdata*/)
         case SP_VERB_CONTEXT_TWEAK:
             tools_switch(dt, TOOLS_TWEAK);
             break;
+        case SP_VERB_CONTEXT_SPRAY:
+            tools_switch(dt, TOOLS_SPRAY);
+            break;
         case SP_VERB_CONTEXT_RECT:
             tools_switch(dt, TOOLS_SHAPES_RECT);
             break;
@@ -1525,6 +1528,10 @@ ContextVerb::perform(SPAction *action, void *data, void */*pdata*/)
             prefs->setInt("/dialogs/preferences/page", PREFS_PAGE_TOOLS_TWEAK);
             dt->_dlg_mgr->showDialog("InkscapePreferences");
             break;
+        case SP_VERB_CONTEXT_SPRAY_PREFS:
+            prefs->setInt("/dialogs/preferences/page", PREFS_PAGE_TOOLS_SPRAY);
+            dt->_dlg_mgr->showDialog("InkscapePreferences");
+            break;
         case SP_VERB_CONTEXT_RECT_PREFS:
             prefs->setInt("/dialogs/preferences/page", PREFS_PAGE_TOOLS_SHAPES_RECT);
             dt->_dlg_mgr->showDialog("InkscapePreferences");
@@ -1797,6 +1804,9 @@ DialogVerb::perform(SPAction *action, void *data, void */*pdata*/)
         case SP_VERB_DIALOG_ALIGN_DISTRIBUTE:
             dt->_dlg_mgr->showDialog("AlignAndDistribute");
             break;
+        case SP_VERB_DIALOG_SPRAY_OPTION:
+            dt->_dlg_mgr->showDialog("SprayOptionClass");
+            break;
         case SP_VERB_DIALOG_TEXT:
             sp_text_edit_dialog();
             break;
@@ -2503,6 +2513,8 @@ Verb *Verb::_base_verbs[] = {
                     N_("Edit paths by nodes"), INKSCAPE_ICON_TOOL_NODE_EDITOR),
     new ContextVerb(SP_VERB_CONTEXT_TWEAK, "ToolTweak", N_("Tweak"),
                     N_("Tweak objects by sculpting or painting"), INKSCAPE_ICON_TOOL_TWEAK),
+    new ContextVerb(SP_VERB_CONTEXT_SPRAY, "ToolSpray", N_("Spray"),
+                    N_("Spray objects by sculpting or painting"), INKSCAPE_ICON_TOOL_SPRAY), 
     new ContextVerb(SP_VERB_CONTEXT_RECT, "ToolRect", N_("Rectangle"),
                     N_("Create rectangles and squares"), INKSCAPE_ICON_DRAW_RECTANGLE),
     new ContextVerb(SP_VERB_CONTEXT_3DBOX, "Tool3DBox", N_("3D Box"),
@@ -2544,6 +2556,8 @@ Verb *Verb::_base_verbs[] = {
                     N_("Open Preferences for the Node tool"), NULL),
     new ContextVerb(SP_VERB_CONTEXT_TWEAK_PREFS, "TweakPrefs", N_("Tweak Tool Preferences"),
                     N_("Open Preferences for the Tweak tool"), NULL),
+    new ContextVerb(SP_VERB_CONTEXT_SPRAY_PREFS, "SprayPrefs", N_("Spray Tool Preferences"),
+                    N_("Open Preferences for the Spray tool"), NULL),
     new ContextVerb(SP_VERB_CONTEXT_RECT_PREFS, "RectPrefs", N_("Rectangle Preferences"),
                     N_("Open Preferences for the Rectangle tool"), NULL),
     new ContextVerb(SP_VERB_CONTEXT_3DBOX_PREFS, "3DBoxPrefs", N_("3D Box Preferences"),
@@ -2645,6 +2659,8 @@ Verb *Verb::_base_verbs[] = {
                    N_("Precisely control objects' transformations"), INKSCAPE_ICON_DIALOG_TRANSFORM),
     new DialogVerb(SP_VERB_DIALOG_ALIGN_DISTRIBUTE, "DialogAlignDistribute", N_("_Align and Distribute..."),
                    N_("Align and distribute objects"), INKSCAPE_ICON_DIALOG_ALIGN_AND_DISTRIBUTE),
+    new DialogVerb(SP_VERB_DIALOG_SPRAY_OPTION, "DialogSprayOption", N_("_Spray options..."),
+                   N_("Some options for the spray"), INKSCAPE_ICON_DIALOG_SPRAY_OPTIONS),
     new DialogVerb(SP_VERB_DIALOG_UNDO_HISTORY, "DialogUndoHistory", N_("Undo _History..."),
                    N_("Undo History"), INKSCAPE_ICON_EDIT_UNDO_HISTORY),
     new DialogVerb(SP_VERB_DIALOG_TEXT, "DialogText", N_("_Text and Font..."),
index 87fe27075fdcf230a669de9cc38dcd6daafb54c9..3ea2fdee89f908a6767e52816c96b46d0da75f51 100644 (file)
@@ -153,6 +153,7 @@ enum {
     SP_VERB_CONTEXT_SELECT,
     SP_VERB_CONTEXT_NODE,
     SP_VERB_CONTEXT_TWEAK,
+    SP_VERB_CONTEXT_SPRAY,
     SP_VERB_CONTEXT_RECT,
     SP_VERB_CONTEXT_3DBOX,
     SP_VERB_CONTEXT_ARC,
@@ -174,6 +175,7 @@ enum {
     SP_VERB_CONTEXT_SELECT_PREFS,
     SP_VERB_CONTEXT_NODE_PREFS,
     SP_VERB_CONTEXT_TWEAK_PREFS,
+    SP_VERB_CONTEXT_SPRAY_PREFS,
     SP_VERB_CONTEXT_RECT_PREFS,
     SP_VERB_CONTEXT_3DBOX_PREFS,
     SP_VERB_CONTEXT_ARC_PREFS,
@@ -227,6 +229,7 @@ enum {
     SP_VERB_DIALOG_SWATCHES,
     SP_VERB_DIALOG_TRANSFORM,
     SP_VERB_DIALOG_ALIGN_DISTRIBUTE,
+    SP_VERB_DIALOG_SPRAY_OPTION,
     SP_VERB_DIALOG_UNDO_HISTORY,
     SP_VERB_DIALOG_TEXT,
     SP_VERB_DIALOG_XML_EDITOR,
index e0fe9bfd100c681617843ce0c865ac83bb1e8075..41a70f08aad6e01eae5964bd666b83bb5dde406e 100644 (file)
@@ -86,6 +86,7 @@
 #include "../svg/css-ostringstream.h"
 #include "../tools-switch.h"
 #include "../tweak-context.h"
+#include "../spray-context.h"
 #include "../ui/dialog/calligraphic-profile-rename.h"
 #include "../ui/icon-names.h"
 #include "../ui/widget/style-swatch.h"
@@ -107,6 +108,7 @@ typedef void (*UpdateFunction)(SPDesktop *desktop, SPEventContext *eventcontext,
 
 static void       sp_node_toolbox_prep(SPDesktop *desktop, GtkActionGroup* mainActions, GObject* holder);
 static void       sp_tweak_toolbox_prep(SPDesktop *desktop, GtkActionGroup* mainActions, GObject* holder);
+static void       sp_spray_toolbox_prep(SPDesktop *desktop, GtkActionGroup* mainActions, GObject* holder);
 static void       sp_zoom_toolbox_prep(SPDesktop *desktop, GtkActionGroup* mainActions, GObject* holder);
 static void       sp_star_toolbox_prep(SPDesktop *desktop, GtkActionGroup* mainActions, GObject* holder);
 static void       sp_arc_toolbox_prep(SPDesktop *desktop, GtkActionGroup* mainActions, GObject* holder);
@@ -146,6 +148,7 @@ static struct {
     { "SPSelectContext",   "select_tool",    SP_VERB_CONTEXT_SELECT,  SP_VERB_CONTEXT_SELECT_PREFS},
     { "SPNodeContext",     "node_tool",      SP_VERB_CONTEXT_NODE, SP_VERB_CONTEXT_NODE_PREFS },
     { "SPTweakContext",    "tweak_tool",     SP_VERB_CONTEXT_TWEAK, SP_VERB_CONTEXT_TWEAK_PREFS },
+    { "SPSprayContext",    "spray_tool",     SP_VERB_CONTEXT_SPRAY, SP_VERB_CONTEXT_SPRAY_PREFS },
     { "SPZoomContext",     "zoom_tool",      SP_VERB_CONTEXT_ZOOM, SP_VERB_CONTEXT_ZOOM_PREFS },
     { "SPRectContext",     "rect_tool",      SP_VERB_CONTEXT_RECT, SP_VERB_CONTEXT_RECT_PREFS },
     { "Box3DContext",      "3dbox_tool",     SP_VERB_CONTEXT_3DBOX, SP_VERB_CONTEXT_3DBOX_PREFS },
@@ -181,6 +184,8 @@ static struct {
       SP_VERB_INVALID, 0, 0},
     { "SPTweakContext",   "tweak_toolbox",   0, sp_tweak_toolbox_prep,              "TweakToolbar",
       SP_VERB_CONTEXT_TWEAK_PREFS, "/tools/tweak", N_("Color/opacity used for color tweaking")},
+    { "SPSprayContext",   "spray_toolbox",   0, sp_spray_toolbox_prep,              "SprayToolbar",
+      SP_VERB_CONTEXT_SPRAY_PREFS, "/tools/spray", N_("Color/opacity used for color spraying")},
     { "SPZoomContext",   "zoom_toolbox",   0, sp_zoom_toolbox_prep,              "ZoomToolbar",
       SP_VERB_INVALID, 0, 0},
     { "SPStarContext",   "star_toolbox",   0, sp_star_toolbox_prep,              "StarToolbar",
@@ -299,6 +304,21 @@ static gchar const * ui_descr =
         "    <toolitem action='TweakDoO' />"
         "  </toolbar>"
 
+  "  <toolbar name='SprayToolbar'>"
+        "    <toolitem action='SprayModeAction' />"
+        "    <separator />"
+        "    <toolitem action='SprayWidthAction' />"
+        "    <separator />"
+        "    <toolitem action='SprayPressureAction' />"
+        "    <separator />"
+        "    <toolitem action='SprayPopulationAction' />"
+        "    <separator />"
+        "    <toolitem action='SprayMeanAction' />"
+        "    <toolitem action='SprayStandard_deviationAction' />"
+        "    <separator />"
+        "    <toolitem action='DialogSprayOption' />"
+        "  </toolbar>"
+
         "  <toolbar name='ZoomToolbar'>"
         "    <toolitem action='ZoomIn' />"
         "    <toolitem action='ZoomOut' />"
@@ -718,6 +738,7 @@ Glib::RefPtr<Gtk::ActionGroup> create_or_fetch_actions( SPDesktop* desktop )
         //SP_VERB_EDIT_TILE,
         //SP_VERB_EDIT_UNTILE,
         SP_VERB_DIALOG_ALIGN_DISTRIBUTE,
+        SP_VERB_DIALOG_SPRAY_OPTION,
         SP_VERB_DIALOG_DISPLAY,
         SP_VERB_DIALOG_FILL_STROKE,
         SP_VERB_DIALOG_NAMEDVIEW,
@@ -1627,6 +1648,7 @@ setup_tool_toolbox(GtkWidget *toolbox, SPDesktop *desktop)
         "    <toolitem action='ToolSelector' />"
         "    <toolitem action='ToolNode' />"
         "    <toolitem action='ToolTweak' />"
+        "    <toolitem action='ToolSpray' />"
         "    <toolitem action='ToolZoom' />"
         "    <toolitem action='ToolRect' />"
         "    <toolitem action='Tool3DBox' />"
@@ -4371,6 +4393,198 @@ static void sp_tweak_toolbox_prep(SPDesktop *desktop, GtkActionGroup* mainAction
 }
 
 
+//########################
+//##       Spray        ##
+//########################
+
+static void sp_spray_width_value_changed( GtkAdjustment *adj, GObject */*tbl*/ )
+{
+    Inkscape::Preferences *prefs = Inkscape::Preferences::get();
+    prefs->setDouble( "/tools/spray/width", adj->value );
+}
+
+static void sp_spray_force_value_changed( GtkAdjustment *adj, GObject */*tbl*/ )
+{
+    //Inkscape::Preferences *prefs = Inkscape::Preferences::get();
+    //prefs->setDouble( "/tools/spray/force", adj->value * 0.01 );
+}
+
+static void sp_spray_mean_value_changed( GtkAdjustment *adj, GObject */*tbl*/ )
+{
+    Inkscape::Preferences *prefs = Inkscape::Preferences::get();
+    prefs->setDouble( "/tools/spray/mean", adj->value );
+}
+
+static void sp_spray_standard_deviation_value_changed( GtkAdjustment *adj, GObject */*tbl*/ )
+{
+    Inkscape::Preferences *prefs = Inkscape::Preferences::get();
+    prefs->setDouble( "/tools/spray/standard_deviation", adj->value );
+}
+
+static void sp_spray_pressure_state_changed( GtkToggleAction *act, gpointer /*data*/ )
+{
+    Inkscape::Preferences *prefs = Inkscape::Preferences::get();
+    prefs->setBool("/tools/spray/usepressure", gtk_toggle_action_get_active(act));
+}
+
+static void sp_spray_mode_changed( EgeSelectOneAction *act, GObject *tbl )
+{
+    int mode = ege_select_one_action_get_active( act );
+    Inkscape::Preferences *prefs = Inkscape::Preferences::get();
+    prefs->setInt("/tools/spray/mode", mode);
+}
+
+static void sp_spray_population_value_changed( GtkAdjustment *adj, GObject */*tbl*/ )
+{
+    Inkscape::Preferences *prefs = Inkscape::Preferences::get();
+    prefs->setDouble( "/tools/spray/population", adj->value );
+}
+
+/*static void spray_toggle_doh (GtkToggleAction *act, gpointer ) {
+    Inkscape::Preferences *prefs = Inkscape::Preferences::get();
+    prefs->setBool("/tools/spray/doh", gtk_toggle_action_get_active(act));
+}
+static void spray_toggle_dos (GtkToggleAction *act, gpointer ) {
+    Inkscape::Preferences *prefs = Inkscape::Preferences::get();
+    prefs->setBool("/tools/spray/dos", gtk_toggle_action_get_active(act));
+}
+static void spray_toggle_dol (GtkToggleAction *act, gpointer ) {
+    Inkscape::Preferences *prefs = Inkscape::Preferences::get();
+    prefs->setBool("/tools/spray/dol", gtk_toggle_action_get_active(act));
+}
+static void spray_toggle_doo (GtkToggleAction *act, gpointer ) {
+    Inkscape::Preferences *prefs = Inkscape::Preferences::get();
+    prefs->setBool("/tools/spray/doo", gtk_toggle_action_get_active(act));
+}
+*/
+static void sp_spray_toolbox_prep(SPDesktop *desktop, GtkActionGroup* mainActions, GObject* holder)
+{
+    Inkscape::IconSize secondarySize = prefToSize("/toolbox/secondary", 1);
+    Inkscape::Preferences *prefs = Inkscape::Preferences::get();
+
+    {
+        /* Width */
+        gchar const* labels[] = {_("(pinch spray)"), 0, 0, 0, _("(default)"), 0, 0, 0, 0, _("(broad spray)")};
+        gdouble values[] = {1, 3, 5, 10, 15, 20, 30, 50, 75, 100};
+        EgeAdjustmentAction *eact = create_adjustment_action( "SprayWidthAction",
+                                                              _("Width"), _("Width:"), _("The width of the spray area (relative to the visible canvas area)"),
+                                                              "/tools/spray/width", 15,
+                                                              GTK_WIDGET(desktop->canvas), NULL, holder, TRUE, "altx-spray",
+                                                              1, 100, 1.0, 0.0,
+                                                              labels, values, G_N_ELEMENTS(labels),
+                                                              sp_spray_width_value_changed,  0.01, 0, 100 );
+        ege_adjustment_action_set_appearance( eact, TOOLBAR_SLIDER_HINT );
+        gtk_action_group_add_action( mainActions, GTK_ACTION(eact) );
+        gtk_action_set_sensitive( GTK_ACTION(eact), TRUE );
+    }
+
+    {
+        /* Mean */
+        gchar const* labels[] = {_("(minimum mean)"), 0, 0, _("(default)"), 0, 0, 0, _("(maximum mean)")};
+        gdouble values[] = {1, 5, 10, 20, 30, 50, 70, 100};
+        EgeAdjustmentAction *eact = create_adjustment_action( "SprayMeanAction",
+                                                              _("Mean"), _("Mean:"), _("The mean of the spray action"),
+                                                              "/tools/spray/mean", 20,
+                                                              GTK_WIDGET(desktop->canvas), NULL, holder, TRUE, "spray-mean",
+                                                              1, 100, 1.0, 0.0,
+                                                              labels, values, G_N_ELEMENTS(labels),
+                                                              sp_spray_mean_value_changed,  0.01, 0, 100 );
+        ege_adjustment_action_set_appearance( eact, TOOLBAR_SLIDER_HINT );
+        gtk_action_group_add_action( mainActions, GTK_ACTION(eact) );
+        gtk_action_set_sensitive( GTK_ACTION(eact), TRUE );
+    }
+
+    {
+        /* Standard_deviation */
+        gchar const* labels[] = {_("(minimum standard_deviation)"), 0, 0, _("(default)"), 0, 0, 0, _("(maximum standard_deviation)")};
+        gdouble values[] = {1, 5, 10, 20, 30, 50, 70, 100};
+        EgeAdjustmentAction *eact = create_adjustment_action( "SprayStandard_deviationAction",
+                                                              _("SD"), _("SD:"), _("The standard deviation of the spray action"),
+                                                              "/tools/spray/standard_deviation", 20,
+                                                              GTK_WIDGET(desktop->canvas), NULL, holder, TRUE, "spray-standard_deviation",
+                                                              1, 100, 1.0, 0.0,
+                                                              labels, values, G_N_ELEMENTS(labels),
+                                                              sp_spray_standard_deviation_value_changed,  0.01, 0, 100 );
+        ege_adjustment_action_set_appearance( eact, TOOLBAR_SLIDER_HINT );
+        gtk_action_group_add_action( mainActions, GTK_ACTION(eact) );
+        gtk_action_set_sensitive( GTK_ACTION(eact), TRUE );
+    }
+
+    /* Mode */
+    {
+        GtkListStore* model = gtk_list_store_new( 3, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING );
+
+        GtkTreeIter iter;
+        gtk_list_store_append( model, &iter );
+        gtk_list_store_set( model, &iter,
+                            0, _("Spray with copies"),
+                            1, _("Spray copies of the initial selection"),
+                            2, INKSCAPE_ICON_SPRAY_COPY_MODE,
+                            -1 );
+
+        gtk_list_store_append( model, &iter );
+        gtk_list_store_set( model, &iter,
+                            0, _("Spray with clones"),
+                            1, _("Spray clones of the initial selection"),
+                            2, INKSCAPE_ICON_SPRAY_CLONE_MODE,
+                            -1 );
+
+        gtk_list_store_append( model, &iter );
+        gtk_list_store_set( model, &iter,
+                            0, _("Spray single path"),
+                            1, _("Spray objects in a single path"),
+                            2, INKSCAPE_ICON_SPRAY_UNION_MODE,
+                            -1 );
+
+        EgeSelectOneAction* act = ege_select_one_action_new( "SprayModeAction", _("Mode"), (""), NULL, GTK_TREE_MODEL(model) );
+        g_object_set( act, "short_label", _("Mode:"), NULL );
+        gtk_action_group_add_action( mainActions, GTK_ACTION(act) );
+        g_object_set_data( holder, "mode_action", act );
+
+        ege_select_one_action_set_appearance( act, "full" );
+        ege_select_one_action_set_radio_action_type( act, INK_RADIO_ACTION_TYPE );
+        g_object_set( G_OBJECT(act), "icon-property", "iconId", NULL );
+        ege_select_one_action_set_icon_column( act, 2 );
+        ege_select_one_action_set_icon_size( act, secondarySize );
+        ege_select_one_action_set_tooltip_column( act, 1  );
+
+        gint mode = prefs->getInt("/tools/spray/mode", 0);
+        ege_select_one_action_set_active( act, mode );
+        g_signal_connect_after( G_OBJECT(act), "changed", G_CALLBACK(sp_spray_mode_changed), holder );
+
+        g_object_set_data( G_OBJECT(holder), "spray_tool_mode", act);
+    }
+
+    {   /* Population */
+        gchar const* labels[] = {_("(rough, simplified)"), 0, 0, _("(default)"), 0, 0, _("(fine, but many nodes)")};
+        gdouble values[] = {10, 25, 35, 50, 60, 80, 100};
+        EgeAdjustmentAction *eact = create_adjustment_action( "SprayPopulationAction",
+                                                              _("Population"), _("Population:"),
+                                                              _("This setting adjusts the number of items sprayed"),
+                                                              "/tools/spray/population", 50,
+                                                              GTK_WIDGET(desktop->canvas), NULL, holder, TRUE, "spray-population",
+                                                              1, 100, 1.0, 10.0,
+                                                              labels, values, G_N_ELEMENTS(labels),
+                                                              sp_spray_population_value_changed,  0.01, 0, 100 );
+        gtk_action_group_add_action( mainActions, GTK_ACTION(eact) );
+        gtk_action_set_sensitive( GTK_ACTION(eact), TRUE );
+        g_object_set_data( holder, "spray_population", eact );
+    }
+
+    /* Use Pressure button */
+    {
+        InkToggleAction* act = ink_toggle_action_new( "SprayPressureAction",
+                                                      _("Pressure"),
+                                                      _("Use the pressure of the input device to alter the force of spray action"),
+                                                      "use_pressure",
+                                                      Inkscape::ICON_SIZE_DECORATION );
+        gtk_action_group_add_action( mainActions, GTK_ACTION( act ) );
+        g_signal_connect_after( G_OBJECT(act), "toggled", G_CALLBACK(sp_spray_pressure_state_changed), NULL);
+        gtk_toggle_action_set_active( GTK_TOGGLE_ACTION(act), prefs->getBool("/tools/spray/usepressure", true) );
+    }
+}
+
+
 //########################
 //##     Calligraphy    ##
 //########################