From e16e745317c4f6f4e9fe60061fe22fa07b225359 Mon Sep 17 00:00:00 2001 From: Jonathan Wilkes <jon.w.wilkes@gmail.com> Date: Sun, 1 Oct 2017 20:31:20 -0400 Subject: [PATCH] Add "svg" type for [draw svg] containers This makes it possible to define an editable viewport outside of which the contents are clipped. One big benefit is that the getrect routine doesn't need to fetch the bboxes of the shapes inside the viewport. It just needs the svg width, height, x, y, and parent transform. It's also possible to add an optimized branch if there is no parent transform specified. One drawback is that the HTML5 method getBBox() includes the clipped content in its calculation. That means the user will get scrollbars even though the [draw svg] is clipping the contents which cause the scrollbars. Hopefully we can just work around this by adding a "scrollbars" method for canvases to just turn them off altogether. Code for an experimental [draw array] is also added here. Combining it with the viewport of [draw svg] will make it possible to interact with arrays of widgets without the performance penalty normally associated with mouse motion on Pd canvases. Also: * fixes some display bugs in certain cases for [draw image] and [draw sprite] * adds a default png for both [draw image] and [draw sprite] if none are given --- pd/doc/5.reference/draw-help.pd | 63 +- pd/doc/5.reference/drawarray-help.pd | 73 ++ pd/doc/5.reference/drawimage-help.pd | 62 + pd/doc/5.reference/drawsprite-help.pd | 139 +++ .../drawsprite_images/longneck01.png | Bin 0 -> 1732 bytes .../drawsprite_images/longneck02.png | Bin 0 -> 1753 bytes .../drawsprite_images/longneck03.png | Bin 0 -> 1735 bytes .../drawsprite_images/longneck04.png | Bin 0 -> 1626 bytes .../drawsprite_images/longneck05.png | Bin 0 -> 1612 bytes .../drawsprite_images/longneck06.png | Bin 0 -> 1603 bytes .../drawsprite_images/longneck07.png | Bin 0 -> 1600 bytes .../drawsprite_images/longneck08.png | Bin 0 -> 1638 bytes .../drawsprite_images/longneck09.png | Bin 0 -> 1741 bytes .../drawsprite_images/longneck10.png | Bin 0 -> 1928 bytes .../drawsprite_images/longneck11.png | Bin 0 -> 1882 bytes .../drawsprite_images/longneck12.png | Bin 0 -> 1935 bytes .../drawsprite_images/longneck13.png | Bin 0 -> 1838 bytes .../drawsprite_images/longneck14.png | Bin 0 -> 1840 bytes .../drawsprite_images/longneck15.png | Bin 0 -> 1790 bytes .../drawsprite_images/longneck16.png | Bin 0 -> 1721 bytes .../drawsprite_images/longneck17.png | Bin 0 -> 1651 bytes .../drawsprite_images/longneck18.png | Bin 0 -> 1664 bytes .../drawsprite_images/longneck19.png | Bin 0 -> 1620 bytes .../drawsprite_images/longneck20.png | Bin 0 -> 1501 bytes .../drawsprite_images/longneck21.png | Bin 0 -> 1732 bytes .../drawsprite_images/longneck22.png | Bin 0 -> 1768 bytes pd/doc/5.reference/drawsvg-help.pd | 171 +++ pd/nw/css/default.css | 2 +- pd/nw/pdgui.js | 109 +- pd/src/g_canvas.c | 36 +- pd/src/g_scalar.c | 22 +- pd/src/g_template.c | 1086 ++++++++++++++--- pd/src/g_text.c | 4 + 33 files changed, 1486 insertions(+), 281 deletions(-) create mode 100644 pd/doc/5.reference/drawarray-help.pd create mode 100644 pd/doc/5.reference/drawimage-help.pd create mode 100644 pd/doc/5.reference/drawsprite-help.pd create mode 100644 pd/doc/5.reference/drawsprite_images/longneck01.png create mode 100644 pd/doc/5.reference/drawsprite_images/longneck02.png create mode 100644 pd/doc/5.reference/drawsprite_images/longneck03.png create mode 100644 pd/doc/5.reference/drawsprite_images/longneck04.png create mode 100644 pd/doc/5.reference/drawsprite_images/longneck05.png create mode 100644 pd/doc/5.reference/drawsprite_images/longneck06.png create mode 100644 pd/doc/5.reference/drawsprite_images/longneck07.png create mode 100644 pd/doc/5.reference/drawsprite_images/longneck08.png create mode 100644 pd/doc/5.reference/drawsprite_images/longneck09.png create mode 100644 pd/doc/5.reference/drawsprite_images/longneck10.png create mode 100644 pd/doc/5.reference/drawsprite_images/longneck11.png create mode 100644 pd/doc/5.reference/drawsprite_images/longneck12.png create mode 100644 pd/doc/5.reference/drawsprite_images/longneck13.png create mode 100644 pd/doc/5.reference/drawsprite_images/longneck14.png create mode 100644 pd/doc/5.reference/drawsprite_images/longneck15.png create mode 100644 pd/doc/5.reference/drawsprite_images/longneck16.png create mode 100644 pd/doc/5.reference/drawsprite_images/longneck17.png create mode 100644 pd/doc/5.reference/drawsprite_images/longneck18.png create mode 100644 pd/doc/5.reference/drawsprite_images/longneck19.png create mode 100644 pd/doc/5.reference/drawsprite_images/longneck20.png create mode 100644 pd/doc/5.reference/drawsprite_images/longneck21.png create mode 100644 pd/doc/5.reference/drawsprite_images/longneck22.png create mode 100644 pd/doc/5.reference/drawsvg-help.pd diff --git a/pd/doc/5.reference/draw-help.pd b/pd/doc/5.reference/draw-help.pd index 021c41682..b782e59c9 100644 --- a/pd/doc/5.reference/draw-help.pd +++ b/pd/doc/5.reference/draw-help.pd @@ -1,10 +1,10 @@ #N struct draw-help-struct float x float y; -#N canvas 270 52 555 619 10; +#N canvas 212 53 555 619 10; #X obj 0 595 cnv 15 552 21 empty \$0-pddp.cnv.footer empty 20 12 0 14 -228856 -66577 0; #X obj 0 0 cnv 15 552 40 empty \$0-pddp.cnv.header draw 3 12 0 18 -204280 -1 0; -#X obj 0 339 cnv 3 550 3 empty \$0-pddp.cnv.inlets inlets 8 12 0 13 +#X obj 0 309 cnv 3 550 3 empty \$0-pddp.cnv.inlets inlets 8 12 0 13 -228856 -1 0; #N canvas 494 296 482 332 META 0; #X text 12 115 LIBRARY internal; @@ -17,13 +17,13 @@ rx ry; #X text 12 135 AUTHOR Jonathan Wilkes; #X text 13 155 HELP_PATCH_AUTHORS Jonathan Wilkes; #X restore 500 597 pd META; -#X obj 0 436 cnv 3 550 3 empty \$0-pddp.cnv.outlets outlets 8 12 0 +#X obj 0 406 cnv 3 550 3 empty \$0-pddp.cnv.outlets outlets 8 12 0 13 -228856 -1 0; -#X obj 0 473 cnv 3 550 3 empty \$0-pddp.cnv.argument arguments 8 12 +#X obj 0 443 cnv 3 550 3 empty \$0-pddp.cnv.argument arguments 8 12 0 13 -228856 -1 0; -#X obj 0 573 cnv 3 550 3 empty \$0-pddp.cnv.more_info more_info 8 12 +#X obj 0 543 cnv 3 550 3 empty \$0-pddp.cnv.more_info more_info 8 12 0 13 -228856 -1 0; -#X obj 78 347 cnv 17 3 80 empty \$0-pddp.cnv.let.0 0 5 9 0 16 -228856 +#X obj 78 317 cnv 17 3 80 empty \$0-pddp.cnv.let.0 0 5 9 0 16 -228856 -162280 0; #N canvas 212 516 428 108 Related_objects 0; #X obj 1 1 cnv 15 425 20 empty \$0-pddp.cnv.subheading empty 3 12 0 @@ -34,37 +34,37 @@ rx ry; #X obj 162 36 drawsymbol; #X obj 232 36 plot; #X restore 101 597 pd Related_objects; -#X text 99 445 float; -#X obj 78 445 cnv 17 3 17 empty \$0-pddp.cnv.let.0 0 5 9 0 16 -228856 +#X text 99 415 float; +#X obj 78 415 cnv 17 3 17 empty \$0-pddp.cnv.let.0 0 5 9 0 16 -228856 -162280 0; -#X text 169 445 - outputs the stored value as a float message.; +#X text 169 415 - outputs the stored value as a float message.; #X obj 4 597 pddp/pddplink all_about_help_patches.pd -text Usage Guide ; #X text 11 20 draw an svg shape to represent a scalar; #X obj 492 12 draw; -#X text 101 554 float; -#X text 171 525 - [draw] accepts a list of coordinates and/or shape +#X text 101 524 float; +#X text 171 495 - [draw] accepts a list of coordinates and/or shape data used to specify where and how to draw the object; -#X scalar draw-help-struct 322 277 \;; -#X obj 117 64 struct draw-help-struct float x float y; -#X msg 128 201 stroke-width \$1; -#X floatatom 128 177 5 0 0 0 - - -, f 5; -#X floatatom 128 238 5 0 0 0 - - -, f 5; -#X msg 128 262 transform skewx \$1; -#X text 98 346 float; -#X text 168 347 - any nonzero number will display the drawing to represent +#X scalar draw-help-struct 322 250 \;; +#X obj 117 59 struct draw-help-struct float x float y; +#X msg 128 174 stroke-width \$1; +#X floatatom 128 150 5 0 0 0 - - -, f 5; +#X floatatom 128 211 5 0 0 0 - - -, f 5; +#X msg 128 235 transform skewx \$1; +#X text 98 316 float; +#X text 168 317 - any nonzero number will display the drawing to represent the corresponding scalar. SSending a "0" will hide it.; -#X text 98 386 [draw] also takes a number of messages. These are svg +#X text 98 356 [draw] also takes a number of messages. These are svg attributes that define how the object is drawn. See the subpatch above for a full list.; -#X text 81 490 1) symbol; -#X text 81 525 n) symbol; -#X text 107 539 or; -#X text 171 490 - name of an svg shape. Can be circle \, ellipse \, +#X text 81 460 1) symbol; +#X text 81 495 n) symbol; +#X text 107 509 or; +#X text 171 460 - name of an svg shape. Can be circle \, ellipse \, line \, path \, polygon \, polyline \, rectangle \, or group.; -#X obj 80 293 draw circle 40 40; -#X obj 299 158 draw rect 80 80 100 -40; -#X msg 80 112 fill red \, stroke blue; +#X obj 80 266 draw circle 40 40; +#X obj 299 138 draw rect 80 80 100 -40; +#X msg 80 92 fill red \, stroke blue; #N canvas 326 113 587 553 more_messages 0; #X obj 1 1 cnv 15 425 20 empty \$0-pddp.cnv.subheading empty 3 12 0 14 -204280 -1 0; @@ -125,8 +125,13 @@ line \, path \, polygon \, polyline \, rectangle \, or group.; #X connect 30 0 32 0; #X connect 31 0 32 0; #X connect 33 0 32 0; -#X restore 299 112 pd more_messages; -#X msg 89 137 fill blue \, stroke black; +#X restore 299 92 pd more_messages; +#X msg 89 117 fill blue \, stroke black; +#X obj 172 553 pddp/pddplink drawarray-help.pd -text draw array; +#X text 101 555 See also:; +#X obj 172 573 pddp/pddplink drawimage-help.pd -text draw image; +#X obj 242 553 pddp/pddplink drawsprite-help.pd -text draw sprite; +#X obj 242 573 pddp/pddplink ./drawsvg-help.pd -text draw svg; #X connect 19 0 30 0; #X connect 20 0 19 0; #X connect 21 0 22 0; diff --git a/pd/doc/5.reference/drawarray-help.pd b/pd/doc/5.reference/drawarray-help.pd new file mode 100644 index 000000000..d7b161037 --- /dev/null +++ b/pd/doc/5.reference/drawarray-help.pd @@ -0,0 +1,73 @@ +#N struct draw-array-help-element float y; +#N struct draw-array-help-struct float x float y array a draw-array-help-element +; +#N canvas 245 53 555 619 10; +#X obj 0 595 cnv 15 552 21 empty \$0-pddp.cnv.footer empty 20 12 0 +14 -228856 -66577 0; +#X obj 0 0 cnv 15 552 40 empty \$0-pddp.cnv.header draw\ array 3 12 +0 18 -204280 -1 0; +#X obj 0 339 cnv 3 550 3 empty \$0-pddp.cnv.inlets inlets 8 12 0 13 +-228856 -1 0; +#N canvas 494 296 482 332 META 0; +#X text 12 115 LIBRARY internal; +#X text 12 25 LICENSE SIBSD; +#X text 12 5 KEYWORDS control GUI data-structure; +#X text 12 45 DESCRIPTION draw an svg shape to represent a scalar; +#X text 12 65 INLET_0 float fill fill-opacity fill-rule stroke stroke-dasharray +stroke-linecap stroke-linejoin stroke-miterlimit stroke-opacity stroke-width +rx ry; +#X text 12 135 AUTHOR Jonathan Wilkes; +#X text 13 155 HELP_PATCH_AUTHORS Jonathan Wilkes; +#X restore 500 597 pd META; +#X obj 0 436 cnv 3 550 3 empty \$0-pddp.cnv.outlets outlets 8 12 0 +13 -228856 -1 0; +#X obj 0 473 cnv 3 550 3 empty \$0-pddp.cnv.argument arguments 8 12 +0 13 -228856 -1 0; +#X obj 0 573 cnv 3 550 3 empty \$0-pddp.cnv.more_info more_info 8 12 +0 13 -228856 -1 0; +#X obj 78 347 cnv 17 3 80 empty \$0-pddp.cnv.let.0 0 5 9 0 16 -228856 +-162280 0; +#N canvas 212 516 428 108 Related_objects 0; +#X obj 1 1 cnv 15 425 20 empty \$0-pddp.cnv.subheading empty 3 12 0 +14 -204280 -1 0; +#X text 7 1 [draw] Related Objects; +#X obj 27 35 drawcurve; +#X obj 92 36 drawnumber; +#X obj 162 36 drawsymbol; +#X obj 232 36 plot; +#X restore 101 597 pd Related_objects; +#X text 99 445 float; +#X obj 78 445 cnv 17 3 17 empty \$0-pddp.cnv.let.0 0 5 9 0 16 -228856 +-162280 0; +#X text 169 445 - outputs the stored value as a float message.; +#X obj 4 597 pddp/pddplink all_about_help_patches.pd -text Usage Guide +; +#X text 101 554 float; +#X text 171 525 - [draw] accepts a list of coordinates and/or shape +data used to specify where and how to draw the object; +#X text 98 346 float; +#X text 168 347 - any nonzero number will display the drawing to represent +the corresponding scalar. SSending a "0" will hide it.; +#X text 98 386 [draw] also takes a number of messages. These are svg +attributes that define how the object is drawn. See the subpatch above +for a full list.; +#X text 81 490 1) symbol; +#X text 81 525 n) symbol; +#X text 107 539 or; +#X text 171 490 - name of an svg shape. Can be circle \, ellipse \, +line \, path \, polygon \, polyline \, rectangle \, or group.; +#X text 11 20 draw an array of svg shapes; +#N canvas 731 197 450 323 draw-array-help-element 1; +#X obj 68 15 struct draw-array-help-element float y; +#X obj 149 89 draw circle 5; +#X restore 117 104 pd draw-array-help-element; +#X obj 117 64 struct draw-array-help-struct float x float y array a +draw-array-help-element; +#X scalar draw-array-help-struct 121 134 \; 0 \; 20 \; 25 \; 17 \; +8 \; 29 \; 30 \; 12 \; 14 \; 9 \; \;; +#X obj 118 271 draw array a 50 50; +#X floatatom 118 211 5 0 0 0 - - -, f 5; +#X msg 118 237 viewBox \$1 0 50 50; +#X text 261 245 Note: still a work-in-progress; +#X connect 27 0 28 0; +#X connect 28 0 26 0; diff --git a/pd/doc/5.reference/drawimage-help.pd b/pd/doc/5.reference/drawimage-help.pd new file mode 100644 index 000000000..f0e309a72 --- /dev/null +++ b/pd/doc/5.reference/drawimage-help.pd @@ -0,0 +1,62 @@ +#N struct draw-image-help-struct float x float y; +#N canvas 238 53 555 619 10; +#X obj 0 595 cnv 15 552 21 empty \$0-pddp.cnv.footer empty 20 12 0 +14 -228856 -66577 0; +#X obj 0 0 cnv 15 552 40 empty \$0-pddp.cnv.header draw\ image 3 12 +0 18 -204280 -1 0; +#X obj 0 329 cnv 3 550 3 empty \$0-pddp.cnv.inlets inlets 8 12 0 13 +-228856 -1 0; +#N canvas 494 296 482 332 META 0; +#X text 12 115 LIBRARY internal; +#X text 12 25 LICENSE SIBSD; +#X text 12 5 KEYWORDS control GUI data-structure; +#X text 12 45 DESCRIPTION draw an svg shape to represent a scalar; +#X text 12 65 INLET_0 float fill fill-opacity fill-rule stroke stroke-dasharray +stroke-linecap stroke-linejoin stroke-miterlimit stroke-opacity stroke-width +rx ry; +#X text 12 135 AUTHOR Jonathan Wilkes; +#X text 13 155 HELP_PATCH_AUTHORS Jonathan Wilkes; +#X restore 500 597 pd META; +#X obj 0 396 cnv 3 550 3 empty \$0-pddp.cnv.outlets outlets 8 12 0 +13 -228856 -1 0; +#X obj 0 433 cnv 3 550 3 empty \$0-pddp.cnv.argument arguments 8 12 +0 13 -228856 -1 0; +#X obj 0 533 cnv 3 550 3 empty \$0-pddp.cnv.more_info more_info 8 12 +0 13 -228856 -1 0; +#X obj 78 337 cnv 17 3 50 empty \$0-pddp.cnv.let.0 0 5 9 0 16 -228856 +-162280 0; +#N canvas 212 516 428 108 Related_objects 0; +#X obj 1 1 cnv 15 425 20 empty \$0-pddp.cnv.subheading empty 3 12 0 +14 -204280 -1 0; +#X obj 27 35 draw; +#X text 7 1 [draw image] Related Objects; +#X restore 101 597 pd Related_objects; +#X text 99 405 float; +#X obj 78 405 cnv 17 3 17 empty \$0-pddp.cnv.let.0 0 5 9 0 16 -228856 +-162280 0; +#X text 169 405 - outputs the stored value as a float message.; +#X obj 4 597 pddp/pddplink all_about_help_patches.pd -text Usage Guide +; +#X floatatom 80 168 5 0 0 0 - - -, f 5; +#X msg 80 192 transform skewx \$1; +#X text 98 336 float; +#X text 81 450 1) symbol; +#X text 11 20 draw an svg image or sequence of images; +#X obj 117 64 struct draw-image-help-struct float x float y; +#X obj 80 253 draw image; +#X scalar draw-image-help-struct 324 189 \;; +#X text 168 337 - for [draw sprite] \, the index of the image to display. +This has no effect for [draw image]; +#X text 171 450 - path to the image to display. Or for [draw sprite] +the path which contains a sequence of images; +#X text 81 485 2) float; +#X text 171 485 - x origin for the image; +#X text 81 505 3) float; +#X text 171 505 - y origin for the image; +#X obj 162 541 pddp/pddplink drawarray-help.pd -text draw array; +#X text 91 543 See also:; +#X obj 162 561 pddp/pddplink drawimage-help.pd -text draw image; +#X obj 232 541 pddp/pddplink drawsprite-help.pd -text draw sprite; +#X obj 232 561 pddp/pddplink ./drawsvg-help.pd -text draw svg; +#X connect 13 0 14 0; +#X connect 14 0 19 0; diff --git a/pd/doc/5.reference/drawsprite-help.pd b/pd/doc/5.reference/drawsprite-help.pd new file mode 100644 index 000000000..08569c970 --- /dev/null +++ b/pd/doc/5.reference/drawsprite-help.pd @@ -0,0 +1,139 @@ +#N struct draw-sprite-help float x float y; +#N canvas 255 53 555 619 10; +#X obj 0 595 cnv 15 552 21 empty \$0-pddp.cnv.footer empty 20 12 0 +14 -228856 -66577 0; +#X obj 0 0 cnv 15 552 40 empty \$0-pddp.cnv.header draw\ sprite 3 12 +0 18 -204280 -1 0; +#X obj 0 349 cnv 3 550 3 empty \$0-pddp.cnv.inlets inlets 8 12 0 13 +-228856 -1 0; +#N canvas 466 266 482 355 META 0; +#X text 12 115 LIBRARY internal; +#X text 12 25 LICENSE SIBSD; +#X text 12 5 KEYWORDS control GUI data-structure; +#X text 12 45 DESCRIPTION draw an svg shape to represent a scalar; +#X text 12 65 INLET_0 float fill fill-opacity fill-rule stroke stroke-dasharray +stroke-linecap stroke-linejoin stroke-miterlimit stroke-opacity stroke-width +rx ry; +#X text 12 135 AUTHOR Jonathan Wilkes; +#X text 13 155 HELP_PATCH_AUTHORS Jonathan Wilkes; +#X restore 500 597 pd META; +#X obj 0 446 cnv 3 550 3 empty \$0-pddp.cnv.outlets outlets 8 12 0 +13 -228856 -1 0; +#X obj 0 483 cnv 3 550 3 empty \$0-pddp.cnv.argument arguments 8 12 +0 13 -228856 -1 0; +#X obj 0 553 cnv 3 550 3 empty \$0-pddp.cnv.more_info more_info 8 12 +0 13 -228856 -1 0; +#X obj 78 357 cnv 17 3 80 empty \$0-pddp.cnv.let.0 0 5 9 0 16 -228856 +-162280 0; +#N canvas 212 516 428 108 Related_objects 0; +#X obj 1 1 cnv 15 425 20 empty \$0-pddp.cnv.subheading empty 3 12 0 +14 -204280 -1 0; +#X obj 17 35 draw image; +#X obj 92 36 draw; +#X text 7 1 [draw sprite] Related Objects; +#X restore 101 597 pd Related_objects; +#X obj 78 455 cnv 17 3 17 empty \$0-pddp.cnv.let.0 0 5 9 0 16 -228856 +-162280 0; +#X obj 4 597 pddp/pddplink all_about_help_patches.pd -text Usage Guide +; +#X obj 115 56 struct draw-sprite-help float x float y; +#X obj 293 81 tgl 15 0 empty empty empty 17 7 0 10 -262144 -1 -1 0 +1; +#X obj 293 101 metro 72; +#X obj 293 123 f; +#X obj 333 123 + 1; +#X obj 293 150 % 22; +#X msg 293 235 index \$1; +#N canvas 681 181 450 323 earth 0; +#X obj 62 8 loadbang; +#X msg 62 30 fill white \, stroke black \, stroke-width 3.98213; +#X obj 62 52 draw path m 125.441 64.4134 a 60.2251 60.2251 0 1 1 -120.45 +0 a 60.2251 60.2251 0 1 1 120.45 0 z; +#X obj 62 120 draw path m 36.6489 11.9887 c 4.57718 -3.98317 10.7935 +-5.0472 16.5767 -5.81134 c 3.18504 -1.70824 6.31674 0.661606 7.88578 +1.63077 c 1.39674 -2.8954 6.10067 1.22814 5.64238 -2.96455 c 2.59712 +-0.816215 4.03226 4.04543 6.8129 1.44597 c 3.1605 3.03694 -5.06567 +3.97271 -3.48434 6.17877 c 4.74075 -0.533508 7.14687 3.59104 10.9833 +5.05019 c -1.77232 -2.9487 -0.236351 -3.0666 -1.08089 -4.33422 c -1.70082 +-2.55124 -4.04772 -4.10695 0.967781 -2.90709 c 5.74748 3.20745 3.22719 +-1.26601 10.1905 4.28407 c 2.07054 -0.295027 2.88148 1.63521 2.82493 +2.80785 c -0.044815 0.936308 -0.633278 1.74884 -2.82493 0.431078 c +-2.9471 2.10148 -3.04153 3.66146 -0.571915 1.14331 c 2.42639 0.024004 +2.46533 4.76796 5.33081 2.10042 c -0.071487 0.805065 -0.488159 1.82406 +-1.03928 2.06894 c -0.724503 0.322243 -1.68161 -0.250748 -2.39651 0.004803 +c -0.856285 0.306236 -1.03821 0.967253 -1.3231 2.68515 c -1.97984 0.488155 +-2.80679 1.55197 -2.74276 2.97484 c 0.102966 2.28127 1.64961 5.16915 +-1.95638 5.70373 c -4.16509 2.05453 4.11335 9.57379 0.125908 9.42281 +c -2.49682 -2.52563 -3.15836 -6.4101 -7.54754 -5.47752 c -1.92757 -0.336651 +-2.34103 2.93749 -5.05071 0.927769 c -5.55862 -0.333981 -6.88439 6.72913 +-4.55029 10.4562 c 1.51356 4.85706 7.67611 1.85447 8.48598 -1.4058 +c 7.43977 -1.17158 -2.99565 9.21956 5.04272 7.69373 c 5.22891 -0.359581 +0.569252 8.99388 7.2285 7.77055 c 3.93409 0.47855 8.10132 -7.83297 +11.7628 -2.46001 c 2.07641 -0.521767 4.44412 -1.20785 6.30073 -0.417732 +c 2.1479 0.914429 3.74896 3.43952 5.6221 4.62178 c 6.18336 -0.486023 +1.35885 7.8399 7.38376 7.29892 c 6.32047 -0.660477 1.77445 6.23991 +1.39778 9.54607 c -1.61172 4.81811 -3.62944 9.54338 -6.3514 13.844 +c -4.9643 2.33623 -7.06739 8.11413 -11.0516 11.623 c -4.88587 1.42712 +-8.13493 5.76881 -12.4457 8.1584 c -2.41359 2.19859 -7.34267 5.98543 +-9.65596 5.20863 c 2.23113 -4.06532 5.00697 -7.37788 7.69212 -11.2389 +c 2.08067 -4.69486 9.2889 -10.9513 6.09533 -15.8004 c -5.09981 -2.38317 +-5.30521 -9.2857 -8.58522 -13.4289 c 2.15698 -2.10842 -0.325966 -6.02116 +3.56171 -7.95834 c 1.90089 -1.61653 2.04974 -9.53913 -1.85608 -7.05512 +c -5.60664 -1.25427 -8.09438 -7.61102 -13.9587 -7.99727 c -3.67107 +-3.2544 -9.10806 -1.65655 -13.5826 -4.74289 c -4.299 -1.90676 -3.89513 +-8.03836 -7.90979 -10.5848 c -0.979523 -1.29376 -3.42725 -6.86838 -4.23018 +-3.91649 c 0.296097 2.15163 6.10867 10.2364 1.52423 5.52554 c -3.09061 +-4.2766 -4.67299 -9.39934 -7.4307 -13.9096 c -2.43407 -4.04186 2.31276 +-7.36615 1.52424 -11.0511 c 2.66701 -0.489227 -2.42106 -4.53055 -1.79099 +-7.16448 c -1.94709 -2.7337 -2.29984 0.273157 -4.68734 -0.457218 c +-0.184116 2.0284 -1.78496 1.17265 -2.85816 0.476421 z; +#X connect 0 0 1 0; +#X connect 1 0 2 0; +#X restore 335 177 draw g earth; +#X scalar draw-sprite-help 87 105 \;; +#X floatatom 293 175 5 0 0 0 - - -, f 5; +#N canvas 0 0 450 300 rotate 0; +#X obj 98 21 inlet; +#X obj 98 182 outlet; +#X obj 108 115 loadbang; +#X msg 98 158 transform translate -30 85 rotate \$1 65 63; +#X msg 98 46 360 \$1; +#X obj 98 68 -; +#X obj 98 90 * 2.5; +#X msg 108 137 0; +#X connect 0 0 4 0; +#X connect 2 0 7 0; +#X connect 3 0 1 0; +#X connect 4 0 5 0; +#X connect 5 0 6 0; +#X connect 6 0 3 0; +#X connect 7 0 3 0; +#X restore 335 150 pd rotate; +#X text 98 356 index; +#X text 168 357 - index of the image to display from the loaded image +sequence. Indices are zero-based.; +#X text 98 396 [draw] also takes a number of messages. These are svg +attributes that define how the object is drawn. See the [draw] object +for more information about them.; +#X text 99 455 -; +#X text 169 455 - -; +#X text 81 500 1) directory; +#X text 91 570 Images may be: png \, jpg \, gif \, or svg; +#X text 171 500 - directory in which a sequence of images may be found. +Purr Data will load the images files found there in alphabetical order. +Relative paths are relative to the patch.; +#X obj 179 327 pddp/pddplink http://millionthvector.blogspot.com/p/free-sprites_12.html +; +#X text 237 309 Sprite from; +#X obj 293 259 draw sprite ./drawsprite_images; +#X text 11 20 draw a sprite from an image sequence; +#X connect 12 0 13 0; +#X connect 13 0 14 0; +#X connect 14 0 15 0; +#X connect 14 0 16 0; +#X connect 14 0 21 0; +#X connect 15 0 14 1; +#X connect 16 0 20 0; +#X connect 17 0 32 0; +#X connect 20 0 17 0; +#X connect 21 0 18 0; diff --git a/pd/doc/5.reference/drawsprite_images/longneck01.png b/pd/doc/5.reference/drawsprite_images/longneck01.png new file mode 100644 index 0000000000000000000000000000000000000000..c97e62d0047e02949c546856ba42fa88817bc09c GIT binary patch literal 1732 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 afcy{saFM83#x;fj0000<MNUMnLSTaFMHgNG literal 0 HcmV?d00001 diff --git a/pd/doc/5.reference/drawsprite_images/longneck02.png b/pd/doc/5.reference/drawsprite_images/longneck02.png new file mode 100644 index 0000000000000000000000000000000000000000..b0fea79b0247be652881ff221655a483f7a1023f GIT binary patch literal 1753 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 literal 0 HcmV?d00001 diff --git a/pd/doc/5.reference/drawsprite_images/longneck03.png b/pd/doc/5.reference/drawsprite_images/longneck03.png new file mode 100644 index 0000000000000000000000000000000000000000..2a636593f6bd78eb875bbff4ef564320dc59e64b GIT binary patch literal 1735 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 literal 0 HcmV?d00001 diff --git a/pd/doc/5.reference/drawsprite_images/longneck04.png b/pd/doc/5.reference/drawsprite_images/longneck04.png new file mode 100644 index 0000000000000000000000000000000000000000..a54afa16392ec9eeb989621240af61f560ad14aa GIT binary patch literal 1626 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 Y2VqZFrYahXfB*mh07*qoM6N<$f{*3e(*OVf literal 0 HcmV?d00001 diff --git a/pd/doc/5.reference/drawsprite_images/longneck05.png b/pd/doc/5.reference/drawsprite_images/longneck05.png new file mode 100644 index 0000000000000000000000000000000000000000..3f0b1dd8c6cfa51059fcab7c98cb46973cd3d31a GIT binary patch literal 1612 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 KMNUMnLSTZDH}`!2 literal 0 HcmV?d00001 diff --git a/pd/doc/5.reference/drawsprite_images/longneck06.png b/pd/doc/5.reference/drawsprite_images/longneck06.png new file mode 100644 index 0000000000000000000000000000000000000000..d480183b9239304f5fd94c5f01feb5ed2e0cd13a GIT binary patch literal 1603 zcmV-J2E6%+P)<h;3K|Lk000e1NJLTq002Dz003bK1^@s6WiF{@00004b3#c}2nYxW zd<bNS0001AdQ@0+Qek%>aB^>EX>4U6ba`-PAVE-2F#rGvnd3@N%}XuHOjal;%1_J8 zN##-i17i~|6H60IqeKG(0}BHPFf=eQHUyGJK(;wlDA51~n3$WT0in5BvY9D}&jkQa zx)o>}E!d0z00oapL_t(|ob8-lY!p=#$A7zps8pqXP+Np5AtWdfeX#IE5D5h3rB=WP z6O1vIG$kZ{#PEWNMgkJ`frv4RB>F&Xu%^b3U`We{3C0B>G!mo_3UsN2Rt&VIrBIF! zw`;fEnc3;?xih<Ue#uR`JF|EHr{~_8d(Szu5D^g(5m9`Uge|~>3ZNXg1?UGPTsd}G z0yF^^fnJ~sI1IcBl!d6v8V>_!F<y0QO-w+;8*w){)i&h&CGmVaP$Uk_aXYx89yYf^ z?M5C6P?L40W9G4=hj*PpIt6JLw&wdqh2-g_z%;jmClAAMpdVtvNwUvIvd?E(`XcX! zrqBXSWH-7Wcq%M`+RVUXKBu)$!xCtN56NzD5_m8qed^4_th%xpy(KJxHt^%+vzT@G zgy13kd3k+U0&Vam*$v(g+!>ZYZJq@N$!_#BVF}cx97vGe;IDwmA!$^{&&BH^@OW4P zwOI^YCcDv}ge6d$+km}fH@E|MAS8|Iti{Ks0{9{<fj0OWf18R$VF}cx66nU?(7xNI zkV%&MU5)WpInV?Af{AS2<>RwQflHQjS)mm82)IF}2mf(+&#CRSEmGUltAKi!V}3)o z-AY<q(T<U6EEz?i4^K3WE<xwsnpEh+6HTM1pmWtNDo>XJw=4E%4Q)@~s@R`33Mtqh z7}^&yjqHQ<42GuB<(OSmzH}+{;fbcvT321`OVC1_(?b;DiY#BQ@;~%+A7(dZ6-}du z6#D1^1{C`7MAPUljHmM9BxZ<PMbqe*LVwpZgak<?Z~=dT0=L!+G_Bk~U7PrdvJ?c{ zFvBw+!=-r;IVb$ue4SVD7h(#P65ui5B}}HV0eBnd@R4Jyc^x?=$QeO4w<5qX;Cal3 zrf8_b3|n7Dzn?(P3G$;LRgaE3wg<~mQcWs>zi}~gVJ)&|)5z-<K{^C^r^WGnmC7Pp zA>eebVgmRX%wG<hn&1xLbOHwYXsm?42B5m*6tgj#nDjeB(bR>O0p}UxwHLM_`@{_8 z<AN+-hXBot%-w0gLf~bLhgVZX!@C4HLYl$bPawYwk`&~aAg}G#AHs#eXQUautPc4> zkZ*4y&%K#3Z!ZBg;YrmaqXe>YuIE*JLKwb|@h?&m6ww@ZVlHMgGG4=rdVWvG4B7D- z-3`nSL9Yri;5%|#ix+iOLIb%OeE~C4)Ce+M)RyDt?gN%-3ehsU3RnQl!ibzY+;^Oj z;C(x$HY^va^A(tm#@c%Za1fKG?Zd>l`Y{)wo0w=w7pC$r*S)bu65&5Ij2^-iti~`| z%T(rarb6E-RI?r$!@D255zGP1NGd4e_$zMBwOKE`$(3C1!5M9GDf0AsBo;@2eVA)T zL9z=4gWqUGS_L^ONaGcDZ*Q|>uvRX(0aMOAmL#S!KQa6|j#+4|0%oU9+Ik2UEHW<b zg|0Gam<8X&Vhk$jv%(rOJ=cP{e><^r-V)@4BgV5Q1lcRdmIKHWYdKAklyNL3(`eWI z@W<`!I3&n#f_yI-frQV45UfE3ql;ZTfP39eZoa{e_kKoJ)H}{?>(6XxMMDP|orl_w zM{>Pp65?_w3H+p_$rY`&cMs5+_WI8(=eu2%J^xu+Xc;}k$Sx|0_q_Bfr#!Eu#}m!1 zWg8}E^%n4l$9Z1mlnIyj3zmC;Cw-h(fpePYGP;|Tf?^KNLBdV~O3Q{(XfqG@v}+*0 zcMyirZujpg1oR+j7)HCryQTswgAfqL4>r}2w%Hg%HE<ns+q)8&BFp%FHY<rq`qffo zWfxAkUAev59*QU#?}XoHEyuQI6q9*DlwXYfzH7KY2p+?%<5Pe44Y&I-IjsX4B7*)M zpcv*i$Gn0Bsd#yek$RN@bZSo{A|fIpA|eW$e*un9^1a}270Uns002ovPDHLkV1ik0 B(=z}7 literal 0 HcmV?d00001 diff --git a/pd/doc/5.reference/drawsprite_images/longneck07.png b/pd/doc/5.reference/drawsprite_images/longneck07.png new file mode 100644 index 0000000000000000000000000000000000000000..0546715d7f1fb44f1d2037da8cd603769815f1b9 GIT binary patch literal 1600 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 literal 0 HcmV?d00001 diff --git a/pd/doc/5.reference/drawsprite_images/longneck08.png b/pd/doc/5.reference/drawsprite_images/longneck08.png new file mode 100644 index 0000000000000000000000000000000000000000..921004eb1799a70bcd30410be03d48fd109a471d GIT binary patch literal 1638 zcmV-s2ATPZP)<h;3K|Lk000e1NJLTq002Dz003bK1^@s6WiF{@00004b3#c}2nYxW zd<bNS0001AdQ@0+Qek%>aB^>EX>4U6ba`-PAVE-2F#rGvnd3@N%}XuHOjal;%1_J8 zN##-i17i~|6H60IqeKG(0}BHPFf=eQHUyGJK(;wlDA51~n3$WT0in5BvY9D}&jkQa zx)o>}E!d0z00pv1L_t(|ob8-_XjWAm$3KsobGnstZqvCfF%{Bqs9A}Knxu}F;mjlv zQb{TZ|0yy|`Y+n(4~?)tGAJtOMYm~~xDv}USg19dwq7PSowD4EW!u=B`s<IgjjiY9 zKF@Q{x%avAe&DddxzD-Z?{n^X`<-(i@bU5S@$nu3w*`bCA6N=Z0os9cz!{*!O;IK( z0{#SKNV)~o03|N!GDZQ=z;MGu)8D`vx5Sy^DZ(2bNT-1`yEhtTw*ZY4hs#*?98?KZ zb}@O)4pQyjDA{fS8krC-BP~PqYU!yotSzO@?u`<~bS^MITxMk%^mW7Cg$biq3p0UE ztlRXDK)OpBwG&MzCcu+!2{b_k)`pJ*<6Y9Hou$A(SeqVElamA7X0<#EXy!Jn<xj9S zydN0tmO$Ms!MZJXp%x({g0Vmq*0ubhTLMk66>G!Izyh}f>ZSm=fVJtpZV5EO9;^*F z0#n@*sG9<yh1;wxM^no^z$&){>Lwp(#oF{AXo!wP!pX?VTwr1p*ZqK6W*Wo9qI?|i zIPeIn#;yV<ff-SL{;~m0MwtX0BD%G4xb(bfk-8u6BH&S*Wrz+Tk<e}06LD#srtbvq z(^#G{bebNA;h{zsx=q^-#5+ME?QjfWd?z&#O}Ci7flkv&=&2>6voX+XItLXIu}hDJ zG9seWw2n!|4LtUE-_%e>QhzdvPSY*eZ;w}jOB%F9M0f9Pw<G%(2M*LE+K|<W1A%>= z>*)aYYkD5=4R8e&W$AdQp5Io_;A}3`1On!VvslRm+OW5l4oY7Oa!I)Lc^_v`Vc};{ z0mg(N890ST!x{O=NkJL}dF|M+yo<m~#5pg}*`{v*Wx#b^1uj~n&RTQ>r;iNFx(j#% z)f{3*cSlx%+HclEW-g?lL<WMDHWKF-Y$7mt7}y-=XMaK+t-1-cHeI0kI`obQrpz3? zrXAJERRF)(QmT<OpqBr&&w|3Jg8Um%Lskj~mzXAMx^v+=j!&P<9JvMaSHippp`ihu zo)+<QDZpE(oyw0;weB72g=N1BQm=*^xgyBNtugi7ZNQs&B<2P{vyfgb)K&{}Sdh2R zAtl@68n#-17l8~HY{X9PJ-nAQL))0WACDMchu+!QK0IJN9rzjj#xv~-Gr3^zMRiCE z(Rc9eUesLWsHXCaQ4I8<ueRHOId%j&v7R1{-uXZ#aKD`boG=~DMtrPHxAS2qPRd8S z)w2V*19jfSYEsf<N01XW9Zg8L4=5L5_h;8QyLf};^$CAk;UTO$r#@iU%loMRUXT-l zynY-hTp4`rvQ0Ds*>(gu@!H`+pgP)%mu!U1rLdqteG^T<#X9Kif{A&MGns8g0rnVE ztBJ`(ca&;aD%p<gJ&#liQr90cx+r`l;*G=Z8K~%HT;uY@smO|FkevrPdQ8Z3L4RB% zp<XSDcQVolY{LWd?g5sg=F8oLF}40xl|tmzp<YRv<bv+FnG0Magwe-dKz5x{G3{Rk zDf@0P?=mWCvKF=VYXp;%lV;TG2os98!HO*~Z4RU*t0`Iv>bX650^WaxMpQ`mQ&gwt zX|`lfN6I^pT0y=Pr1V?liJi#9TL)|R2oO1X<}uQM@<r>B2TDS=+e?g~!|X$ujoN|@ zW%>g*1UWJHUVvIigyIVa?jM8`rX!sf^~4FoSji{yI~(QhNi)YLBG0z|0<xSIW%}{9 z3hRso#u(NRglW^^76=_f{&pMI5QNDYSw65hOx__>7^w&B|C&Xtm^8hd@a;7l*noz> zeWFoG_ztWcSnZxPGgu8(13~-UMEHFZuVFP*g)$%Z7j3*k8L>x5_Tx|+H?@IR1Dr<% z1-elOU6WA<XvPpa3OgIsqgNTyG>EC*yA61^|NjAlStwI^sHjL5YCCrpsy82niu$JF k!r1NO<KyGw<C7Tt2X>qAD*TmBH~;_u07*qoM6N<$f{DKGK>z>% literal 0 HcmV?d00001 diff --git a/pd/doc/5.reference/drawsprite_images/longneck09.png b/pd/doc/5.reference/drawsprite_images/longneck09.png new file mode 100644 index 0000000000000000000000000000000000000000..289de0feafb178cd7c675c41da5c37ecbddea646 GIT binary patch literal 1741 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 literal 0 HcmV?d00001 diff --git a/pd/doc/5.reference/drawsprite_images/longneck10.png b/pd/doc/5.reference/drawsprite_images/longneck10.png new file mode 100644 index 0000000000000000000000000000000000000000..97ffe0c6acf97fda816b062b853d78e56b55d9d3 GIT binary patch literal 1928 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 O0000<MNUMnLSTXk26r9+ literal 0 HcmV?d00001 diff --git a/pd/doc/5.reference/drawsprite_images/longneck11.png b/pd/doc/5.reference/drawsprite_images/longneck11.png new file mode 100644 index 0000000000000000000000000000000000000000..bb8fd71bb79005eab7df7ce9cf4562fa19d14848 GIT binary patch literal 1882 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 U-D;0o2mk;807*qoM6N<$f*6E(vH$=8 literal 0 HcmV?d00001 diff --git a/pd/doc/5.reference/drawsprite_images/longneck12.png b/pd/doc/5.reference/drawsprite_images/longneck12.png new file mode 100644 index 0000000000000000000000000000000000000000..aca29148b26a588e8b9b4160fffb895ad20df7ae GIT binary patch literal 1935 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 VON9+>^*#Uq002ovPDHLkV1ifagq8pR literal 0 HcmV?d00001 diff --git a/pd/doc/5.reference/drawsprite_images/longneck13.png b/pd/doc/5.reference/drawsprite_images/longneck13.png new file mode 100644 index 0000000000000000000000000000000000000000..50bfdd8a761ea0837f2d765717aa2b8a47d78148 GIT binary patch literal 1838 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 literal 0 HcmV?d00001 diff --git a/pd/doc/5.reference/drawsprite_images/longneck14.png b/pd/doc/5.reference/drawsprite_images/longneck14.png new file mode 100644 index 0000000000000000000000000000000000000000..98dc9229b06dc091e0b4a8103e0a56716d0c4df6 GIT binary patch literal 1840 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 literal 0 HcmV?d00001 diff --git a/pd/doc/5.reference/drawsprite_images/longneck15.png b/pd/doc/5.reference/drawsprite_images/longneck15.png new file mode 100644 index 0000000000000000000000000000000000000000..8b658c106b178555b1a4d9e81353606cba9aafea GIT binary patch literal 1790 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 literal 0 HcmV?d00001 diff --git a/pd/doc/5.reference/drawsprite_images/longneck16.png b/pd/doc/5.reference/drawsprite_images/longneck16.png new file mode 100644 index 0000000000000000000000000000000000000000..071909bb8d838dba0face63c49c749479c6be4fc GIT binary patch literal 1721 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 P00000NkvXXu0mjfv^F0g literal 0 HcmV?d00001 diff --git a/pd/doc/5.reference/drawsprite_images/longneck17.png b/pd/doc/5.reference/drawsprite_images/longneck17.png new file mode 100644 index 0000000000000000000000000000000000000000..14e46774acd10a4dd14f81d09de04d33aeeb7219 GIT binary patch literal 1651 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 literal 0 HcmV?d00001 diff --git a/pd/doc/5.reference/drawsprite_images/longneck18.png b/pd/doc/5.reference/drawsprite_images/longneck18.png new file mode 100644 index 0000000000000000000000000000000000000000..2977fe30266c494af4e72ba8b315c7c21fc9f215 GIT binary patch literal 1664 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 KMNUMnLSTYF%<_`} literal 0 HcmV?d00001 diff --git a/pd/doc/5.reference/drawsprite_images/longneck19.png b/pd/doc/5.reference/drawsprite_images/longneck19.png new file mode 100644 index 0000000000000000000000000000000000000000..9c75d7a038c843ee1722e1301be94c5aea17142d GIT binary patch literal 1620 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 SBYDjL0000<MNUMnLSTZnQt;&f literal 0 HcmV?d00001 diff --git a/pd/doc/5.reference/drawsprite_images/longneck20.png b/pd/doc/5.reference/drawsprite_images/longneck20.png new file mode 100644 index 0000000000000000000000000000000000000000..024eb0fd9acd98bd257d2a24b5619a54b436d91a GIT binary patch literal 1501 zcmV<31tR*1P)<h;3K|Lk000e1NJLTq002Dz003bK1^@s6WiF{@00004b3#c}2nYxW zd<bNS0001AdQ@0+Qek%>aB^>EX>4U6ba`-PAVE-2F#rGvnd3@N%}XuHOjal;%1_J8 zN##-i17i~|6H60IqeKG(0}BHPFf=eQHUyGJK(;wlDA51~n3$WT0in5BvY9D}&jkQa zx)o>}E!d0z00k*YL_t(|ob8)iY!yWq$A6__OTlunwP0JkB?dx_7%VZ-Mk~fk!UMG8 zt$2y@CW&bb#3xNOh!GPt(RgW^i19&1tt29*q79%;Fn~91sRj$2Qd$tP(2J1v^I@nd z+OxZy{bpy+aev9aoU>=<|39;{Gv7BekdTm&kdTlS<hvH&fi-P;wh9ix65xK|GT<*@ zH?R@-0_b<B%Nh;9X+Xxf)&W!9NwY&GaFnqPk6des=hK-n5948Y@d~7NCH=r`cM|n^ zjWmWAJc{fTWS7v@DwKq+Xk6F=6e&;l#lCIO1q?&qEzlR8B)e4L)1S+(Ms9wPBM`o& z<H91mUtlBGW}rB1WpR1DFAZ?d0PsA}YgtPqQ~(|LxAMD=^jYB{{0;X2*SivEgHP}` zz1EpJ3*1fmX=hHhav>&=@N4C_T?w?oGW-pvfXf}}Q>PNxkH6{Ft_0d3?L2$bbpW`; zl|XG~;~zo_@VG01Hh3R@!w1QsIrb9#hp3!u<scK0gTORb0=20Cj^S_mTiZe|uvqqV zU;-wROJO3ZAc?*G7BvBOOxFO*fohEDJfI!;gJ7X-rv*(`sl@cjAPE6y6B6wtLJh`v z7*ZNSywEniSfLD2D8my?)04@P5Kz;!kR_`Rnx=~|Z|m5jZMsmgJZr=y1so}f>6l>s zWf(`(M{QRSN7Kh`SD<M+pYV@nFR({Jizk{<)-=M8(<gvZpbC>Nn%jID=8Z=_Xrpw+ zjZ6f(f$xEBz>bjhh2|>Ef_az-YY;d*`m?v%kxoIH2mf>L3E;X+glazC{TR_<C;(=R z{@|A#a0VzXfD0#`b8jITu2pNA9>nbXQe{t@S(u&#%&Gq8<4#PXVsj>CYWC?~U<+`s zVwnu~!4QxKol|De3N&N#Xx*CigrNj@3HSy$Lb(1d!0uT$@#J?xZI@80CDPXHCl8Yd zted}x`hio-|9MlO-|Yf^#f;S(Fn?Z;C5`rY=1XQ?a~s_RYuUS8>C|R2Chz5E_&8?R zvre3*p;Iwy);U4YmKMwkNCPm%iBd(*$Mndx4uwr}F3H5SU^cbi;XtnnnVJ^NQjkV2 zJ#vc4-1La?1(B-`$#md%!p+P+C(B-LR}wzt6kv^(peV*^jf@JwJ^U-|%#<ihUyRPm z$4uaMg>oV>-GS-T8dPZ%5{2oY$%TGQzQ7BWWuquepTy+7#$@iD@N5e-ya)LA{S6v| zqA)!K{FLs?fs;^N0*};Fw0etYOQwLW>gp`A5}zSyO&jv#*{tXC#&f^RFF=4sH_|hs z40w|OWAW3UAzKA$7o=5?rr(fvQpox<>}~Ae3Reb#QVuKyK8C<q69Ht-t;lnmkgo;V zC&&R|?_r^OtV-fSH6~lxL&zD}xB?E<ucE0%;@`qA63%Q2_!M}9EZWgug^7v+nY^J6 zsb9r*pb4l2y)<vsyh?D>E!#zBKJA(k%&MZF=@vXr(q<zs@INy=3-6OSU!fEt#)S#M zdc0dXr;aKBJcWN>{>Yg+3oONikbb7S$dQvce*JhOX01wqVc=RfGW96Kgna1?cK{aw zb-<sPDQebELPqdALihtP{_MRE0IxXEs7ej~>D?jVzEQuK7_mlm7GlytelM?MKs{!A zbWSi2co{f^xA9@jYGhWeRQOR2Jb~F^bc*!mKO{>|0GtowFhkNZOhRF-%*jG$>LQ{7 zcno+Q*oiUSjKi%TQJ=0U!tCcP!~`A*2?+@a2?6;V`Qr2G0k(}_00000NkvXXu0mjf DdO5IM literal 0 HcmV?d00001 diff --git a/pd/doc/5.reference/drawsprite_images/longneck21.png b/pd/doc/5.reference/drawsprite_images/longneck21.png new file mode 100644 index 0000000000000000000000000000000000000000..5810c8723e39de66790e44631aff94b05bce50e6 GIT binary patch literal 1732 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 aG0cB_Ix=!Z9Qh0Y0000<MNUMnLSTX&lnCJf literal 0 HcmV?d00001 diff --git a/pd/doc/5.reference/drawsprite_images/longneck22.png b/pd/doc/5.reference/drawsprite_images/longneck22.png new file mode 100644 index 0000000000000000000000000000000000000000..ef61f97e3fe96d11b7abc9151bd344191199eb1e GIT binary patch literal 1768 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 KMNUMnLSTZUBs6jW literal 0 HcmV?d00001 diff --git a/pd/doc/5.reference/drawsvg-help.pd b/pd/doc/5.reference/drawsvg-help.pd new file mode 100644 index 000000000..ed2ba4d65 --- /dev/null +++ b/pd/doc/5.reference/drawsvg-help.pd @@ -0,0 +1,171 @@ +#N struct draw-svg-help-struct float x float y; +#N canvas 157 53 555 619 10; +#X obj 0 595 cnv 15 552 21 empty \$0-pddp.cnv.footer empty 20 12 0 +14 -228856 -66577 0; +#X obj 0 0 cnv 15 552 40 empty \$0-pddp.cnv.header draw\ svg 3 12 0 +18 -204280 -1 0; +#X obj 0 347 cnv 3 550 3 empty \$0-pddp.cnv.inlets inlets 8 12 0 13 +-228856 -1 0; +#N canvas 494 296 482 332 META 0; +#X text 12 115 LIBRARY internal; +#X text 12 25 LICENSE SIBSD; +#X text 12 5 KEYWORDS control GUI data-structure; +#X text 12 45 DESCRIPTION draw an svg shape to represent a scalar; +#X text 12 65 INLET_0 float fill fill-opacity fill-rule stroke stroke-dasharray +stroke-linecap stroke-linejoin stroke-miterlimit stroke-opacity stroke-width +rx ry; +#X text 12 135 AUTHOR Jonathan Wilkes; +#X text 13 155 HELP_PATCH_AUTHORS Jonathan Wilkes; +#X restore 500 597 pd META; +#X obj 0 444 cnv 3 550 3 empty \$0-pddp.cnv.outlets outlets 8 12 0 +13 -228856 -1 0; +#X obj 0 481 cnv 3 550 3 empty \$0-pddp.cnv.argument arguments 8 12 +0 13 -228856 -1 0; +#X obj 0 542 cnv 3 550 3 empty \$0-pddp.cnv.more_info more_info 8 12 +0 13 -228856 -1 0; +#X obj 78 355 cnv 17 3 80 empty \$0-pddp.cnv.let.0 0 5 9 0 16 -228856 +-162280 0; +#N canvas 212 516 428 108 Related_objects 0; +#X obj 1 1 cnv 15 425 20 empty \$0-pddp.cnv.subheading empty 3 12 0 +14 -204280 -1 0; +#X obj 27 35 draw; +#X text 7 1 [draw svg] Related Objects; +#X restore 101 597 pd Related_objects; +#X obj 78 453 cnv 17 3 17 empty \$0-pddp.cnv.let.0 0 5 9 0 16 -228856 +-162280 0; +#X obj 4 597 pddp/pddplink all_about_help_patches.pd -text Usage Guide +; +#X text 98 394 [draw] also takes a number of messages. These are svg +attributes that define how the object is drawn. See the subpatch above +for a full list.; +#X obj 172 552 pddp/pddplink drawarray-help.pd -text draw array; +#X text 101 554 See also:; +#X obj 172 572 pddp/pddplink drawimage-help.pd -text draw image; +#X obj 242 552 pddp/pddplink drawsprite-help.pd -text draw sprite; +#X text 11 20 draw shapes inside an svg container; +#X obj 146 52 struct draw-svg-help-struct float x float y; +#X scalar draw-svg-help-struct 207 120 \;; +#X obj 34 137 r \$0-drag; +#X obj 34 159 route drag; +#N canvas 0 0 450 300 pan 0; +#X obj 50 51 unpack p 0 0; +#X floatatom 82 75 5 0 0 0 - - -, f 5; +#X floatatom 123 72 5 0 0 0 - - -, f 5; +#X obj 47 20 inlet; +#X obj 71 122 * -1; +#X obj 128 120 * -1; +#X obj 71 154 +; +#X obj 128 152 +; +#X obj 71 176 t a; +#X obj 128 174 t a; +#X obj 71 198 outlet; +#X obj 128 196 outlet; +#X connect 0 1 1 0; +#X connect 0 1 4 0; +#X connect 0 2 2 0; +#X connect 0 2 5 0; +#X connect 3 0 0 0; +#X connect 4 0 6 0; +#X connect 5 0 7 0; +#X connect 6 0 8 0; +#X connect 7 0 9 0; +#X connect 8 0 6 1; +#X connect 8 0 10 0; +#X connect 9 0 7 1; +#X connect 9 0 11 0; +#X restore 34 181 pd pan; +#X obj 33 211 pack; +#X text 98 354 viewBox; +#X text 168 355 - Four floats to define the viewport of the container: +xOrigin yOrigin width height. See svg spec for more details; +#X text 99 453 anything; +#X text 169 453 - messages in response to any events set for the object +; +#X text 81 498 1) float; +#X text 171 498 - initial width of the container; +#X text 81 515 2) float; +#X text 171 515 - initial height of the container; +#N canvas 492 53 686 639 (subpatch) 0; +#X obj 41 52 draw path m 5 194.088 l 666.819 0 l 0 -36.9314 l -3.12158 +0 l 0 3.03125 l -5.96875 0 l 0 -1.5 l -7.40625 0 l 0 5.40625 l -5.65625 +0 l 0 1.6875 l -3.125 0 l 0 -1.65625 l -5.40625 0 l -6.84375 -6.84375 +l -1.84375 3.21875 l -2.5625 0 l 0 -19.1562 c 1.11498 -0.60865 1.90625 +-1.76523 1.90625 -3.125 c 0 -1.35977 -0.79127 -2.51635 -1.90625 -3.125 +l 0 -13.4375 l 2.03125 0 l 0 -2.3125 l -2.6938 0 l -0.99404 -12.4839 +l -0.90632 12.4839 l -3.62459 0 l 0 1.84375 l 2.51562 0 l 0 1.79466 +l -1.23437 0 l 0 1.99861 l 1.5625 0 l 0 10.0817 c -1.14211 0.60033 +-1.9375 1.77639 -1.9375 3.15625 c 0 1.37986 0.79539 2.55592 1.9375 +3.15625 l 0 19.625 l -2.90625 0 l 0 -5.59375 l -3.875 -3.90625 l -6.65625 +3.84375 l 0 -2.5 l -3.53125 0.96875 l 0 7.4375 l -2.59375 0 l 0 -3.8125 +l -17.5938 0 l 0 4 l -5.03125 0 l 0 -3.75 l -11.875 0 l 0 3.3125 l +-3.78125 0 l -0.78125 -26.4688 l -0.78125 25.1875 l -2.3125 0 l 0 -3.96875 +l -2.9375 0 l 0 3.5 l -3.5 0 l 0 -2.1875 l -5.21875 0 l 0 5.1875 l +-7.8125 0 l 0 -2.53125 l -7.53125 0 l 0.25 -20.8438 l -1.28125 21.3438 +l -4.09375 0 l 0 -6.3125 l -3.1875 0 l -0.9375 3.5 l -3.875 0 l 0 4.3125 +l -2.3125 0 l 0 -6.34375 l -2.03125 -0.53125 l 0 4.875 l -1.28125 0 +l 0 2.40625 l -1.59375 0 l 0 3.5 l -4.59375 0 l 0 -23.125 l -11.6875 +0 l 0 -3.15625 l -3.46875 0 l 0 3.15625 l -3.875 0 l 0 8.71875 l -4.09375 +0 l 0 5.15625 l -3.09375 0 l 0 4.375 l -2.125 0 l 0 -3.375 l -1.71875 +0 l 0 -5.40625 l -6.59375 0 l 0 2.59375 l -8.59375 0 l 0 3.34375 l +-9.75 0 l 0 -14.7188 l -3.90625 0 l 0 -1.71875 l -3.5625 0 l 0 2.3125 +l -2.0625 0 l 0 -2.59375 l -6.15625 0 l 0 6.96875 l -3.125 0 l 0 5.1875 +l -1.5625 0 l 0 -9 l -1.5 0 l 0 -2.15625 l -5.75 0 l -0.65625 -2.53125 +l -12.0938 0 l 0 5.15625 l -2.0625 0 l 0 6.6875 l -4.375 0 l -1.84375 +-3.09375 l 0 -77.75 l -1.46875 0 l 0 -1.96875 l 3.15625 0 l 0 -5.1875 +l 1.6875 0 l 0 -3.84375 l -1.6875 0 l 0 -8.28125 l -1.375 0 l 0 -3.5 +l 6.03125 0 l 0 -2.5625 l -2.4375 0 l 0 -5.0625 l 2.1875 0 l 0 -2.1875 +l -4.03125 0 l 0 -1.21875 l -2.78125 0 l 0 -3.125 l 1.71875 0 l 0 -1.9375 +l -4.28125 0 L 405.166 5 l -1.40625 26.7812 l -5.34375 0 l 0 1.9375 +l 1.96875 0 l 0 3.4375 c -2.95107 0.40253 -5.2699 1.439 -6.375 3.6875 +l 0 2.96875 l 2.03125 0 l 0 2.78125 l -1.40625 0 l 0 1.78125 l 5.09375 +0 l 0 3 l -2.125 0 l 0 8.28125 l -1.9375 0 l 0 3.84375 l 1.9375 0 l +0 4.6875 l 3.53125 0 l 0 2.46875 l -2.0625 0 l 0 78.25 l -12.4062 0 +l 0 11.8438 l -5.65625 0 l 0 -22.125 l -5.40625 0 l 0 -1.53125 l -6.375 +0 l -0.46875 -9.625 l -0.4375 9.625 l -8.57193 0 l 0 3.09375 l -3.0625 +0 l 0 5.375 l -16.6191 0 l 0 5.65625 l -5.125 0 l 0 -2.90625 l -0.78125 +-3 l -5.65625 0 l 0 2.84375 l -1.37218 0 l 0 15.3442 l -3.41612 0 l +0 -18.438 l -8.0867 0 l 0 -3.59375 l -4 0 l 0 3.78125 l -1.90625 1.09375 +l 0 5.65625 l -33.2439 0 l 0 1.3125 l -1.8125 0 l 0 -4.40625 l -4.875 +0 l 0 -1.03125 l -3.875 0 l 0 -2.5625 l -4.375 0 l 0 6.6875 l -12.1514 +0 l 0 -2.5625 l -3.84375 0 l 0 -3.34375 l -4.25 0 l 0 10.4062 l -3.21875 +-3.21875 l 0 -25.9688 l -6.15625 0 l 0 -6.15625 l -5.15625 0 l 0 13.375 +l -6.99996 0 l 0 28.0945 l -6.09379 0 l 0 -8.06316 l -2.90625 -3.28125 +l -3.53125 3.28125 l 0 -8.8125 l -5.28125 0 l 0 -2.875 l -5.59375 0 +l 0 3.96875 l -3.5625 0 l 0 4.6875 l -1.5 0 l 0 -1.84375 l -10.7927 +0 l 0 3.125 l -17.4334 0 l 0 -3.34375 l -3.96875 0 l 0 -2.34375 l -6.9375 +0 l 0 -3.34375 l -3.84375 0 l -0.90625 -32.4375 c 1.7461 -0.54309 3.03125 +-2.16894 3.03125 -4.09375 c 0 -2.01445 -1.409 -3.66423 -3.28125 -4.125 +l -0.84375 -30.25 l -1.375 30.2812 c -1.77984 0.52232 -3.09375 2.14493 +-3.09375 4.09375 c 0 1.81116 1.13148 3.37093 2.71875 4 l -1.96875 43.7812 +l -4.46905 4.75707 l 0 3.18537 l -6.03095 -4.03614 l 0 -11.5625 l -19.25 +0 l 0 6.0625 l -2.59375 0 l 0 -78.5 l -32.9688 0 l 0 74.2188 l -4.53125 +0 l 0 2.5625 l -4.03125 0 l 0 2.34375 l -3.46875 0 l 0 -4.375 l -2.3125 +0 l 0 -5.40625 l -3.34375 0 l 0 -6.6875 l -6.0746 0 l 0 22.754 l -4.59819 +0 l 0 -1.83383 l -8.10846 0.0134 l 0 1.97273 l -4.875 0 l 0 8.96875 +l -4.875 0 l 0 -8.96878 l -4.15862 0 l 0 -3.01004 l -2.34138 0 l 0 +3.01004 l -11.75 0 l 0 7.43748 l -2.3125 0 l 0 3.34375 l -5.50958 0 +z; +#X obj 41 9 loadbang; +#X msg 41 31 drag 1; +#X obj 41 981 s \$0-drag; +#X text 135 6 Skyline from:; +#X obj 135 26 pddp/pddplink https://upload.wikimedia.org/wikipedia/commons/1/13/JohannesburgArtisticSilhouette.svg +; +#X connect 0 0 3 0; +#X connect 1 0 2 0; +#X connect 2 0 0 0; +#X restore 33 285 draw svg 300 200; +#X msg 33 233 viewBox \$1 \$2 300 200; +#X obj 34 52 loadbang; +#X msg 34 84 fill none \, stroke-width 2 \, stroke black \, stroke-dasharray +5 5, f 61; +#X obj 34 107 draw rect 300 200; +#X text 270 322 Click to drag the skyline; +#X connect 19 0 20 0; +#X connect 20 0 21 0; +#X connect 21 0 22 0; +#X connect 21 1 22 1; +#X connect 22 0 32 0; +#X connect 32 0 31 0; +#X connect 33 0 34 0; +#X connect 34 0 35 0; diff --git a/pd/nw/css/default.css b/pd/nw/css/default.css index c40f4e37d..4df1ccc68 100644 --- a/pd/nw/css/default.css +++ b/pd/nw/css/default.css @@ -381,7 +381,7 @@ text { stroke: #ccc; } -/* A little hack for special canvas of [cnv]. +/* A little hack for special case of [cnv]. All other iemguis have a black border, but [cnv] sets its selection rectangle to the user-supplied fill color when the object diff --git a/pd/nw/pdgui.js b/pd/nw/pdgui.js index b3f2d9f95..b849fd414 100644 --- a/pd/nw/pdgui.js +++ b/pd/nw/pdgui.js @@ -3264,9 +3264,9 @@ function gui_scalar_draw_select_rect(cid, tag, state, x1, y1, x2, y2, basex, bas } } -function gui_scalar_draw_group(cid, tag, parent_tag, attr_array) { +function gui_scalar_draw_group(cid, tag, parent_tag, type, attr_array) { var parent_elem, - g; + group; if (!patchwin[cid]) { return; } @@ -3275,9 +3275,9 @@ function gui_scalar_draw_group(cid, tag, parent_tag, attr_array) { attr_array = []; } attr_array.push("id", tag); - g = create_item(cid, "g", attr_array); - parent_elem.appendChild(g); - return g; + group = create_item(cid, type, attr_array); + parent_elem.appendChild(group); + return group; } function gui_scalar_configure_gobj(cid, tag, isselected, t1, t2, t3, t4, t5, t6) { @@ -3383,6 +3383,19 @@ function gui_draw_configure(cid, tag, attr, val) { configure_item(item, obj); } +// Special case for viewBox which, in addition to its inexplicably inconsistent +// camelcasing also has no "none" value in the spec. This requires us to create +// a special case to remove the attribute if the user wants to get back to +// the default behavior. +function gui_draw_viewbox(cid, tag, attr, val) { + // Value will be an empty array if the user provided no values + if (val.length) { + gui_draw_configure(cid, tag, attr, val) + } else { + get_item(cid, tag).removeAttribute("viewBox"); + } +} + // Configure multiple attr/val pairs (this should be merged with gui_draw_configure at some point function gui_draw_configure_all(cid, tag, attr_array) { var item = get_item(cid, tag); @@ -3507,55 +3520,58 @@ function gui_drawimage_new(obj_tag, file_path, canvasdir, flags) { var drawsprite = 1, drawimage_data = [], // array for base64 image data image_seq, - i, + count = 0, matchchar = "*", files, ext, + img_types = [".gif", ".jpeg", ".jpg", ".png", ".svg"], img; // dummy image to measure width and height image_seq = flags & drawsprite; - if (!path.isAbsolute(file_path)) { - file_path = path.join(canvasdir, file_path); + if (file_path !== "") { + if(!path.isAbsolute(file_path)) { + file_path = path.join(canvasdir, file_path); + } + file_path = path.normalize(file_path); } - file_path = path.normalize(file_path); - if (fs.existsSync(file_path) && fs.lstatSync(file_path).isDirectory()) { + if (file_path !== "" && + fs.existsSync(file_path) && + fs.lstatSync(file_path).isDirectory()) { files = fs.readdirSync(file_path) .sort(); // Note that js's "sort" method doesn't do the // "right thing" for numbers. For that we'd need // to provide our own sorting function // todo: warn about image sequence with > 999 - for (i = 0; i < files.length && i < 1000; i++) { - ext = path.extname(files[i]); - - // todo: tolower() - - if (ext === ".gif" || - ext === ".jpg" || - ext === ".png" || - ext === ".jpeg" || - ext === ".svg") { - + files.forEach(function(file) { + ext = path.extname(file).toLowerCase(); + if (img_types.indexOf(ext) != -1) { // Now add an element to that array with the image data drawimage_data.push({ type: ext === ".jpeg" ? "jpg" : ext.slice(1), - data: fs.readFileSync(path.join(file_path, files[i]),"base64") + data: fs.readFileSync(path.join(file_path, file),"base64") }); + count++; } - } - } else { - i = 0; + }); } - //post("no of files: " + i); + post("no of files: " + count); - if (i > 0) { - img = new pd_window.Image(); // create an image in the pd_window context - img.onload = function() { - pdsend(obj_tag, "size", this.width, this.height); - }; - img.src = "data:image/" + drawimage_data[0].type + - ";base64," + drawimage_data[0].data; - } else { - post("drawimage: warning: no images loaded"); + if (count === 0) { + // set a default image + drawimage_data.push({ + type: "png", + data: get_default_png_data() + }); + if (file_path !== "") { + post("draw image: error: couldn't load image"); + } + post("draw image: warning: no image loaded. Using default png"); } + img = new pd_window.Image(); // create an image in the pd_window context + img.onload = function() { + pdsend(obj_tag, "size", this.width, this.height); + }; + img.src = "data:image/" + drawimage_data[0].type + + ";base64," + drawimage_data[0].data; pd_cache.set(obj_tag, drawimage_data); // add the data to container } @@ -3648,18 +3664,23 @@ function gui_drawimage_index(cid, obj, data, index) { configure_item(image, { visibility: "visible" }); } +// Default png image data +function get_default_png_data() { + return ["iVBORw0KGgoAAAANSUhEUgAAABkAAAAZCAMAAADzN3VRAAAAb1BMVEWBgYHX19", + "f///8vLy/8/Pzx8PH3+Pf19fXz8/Pu7u7l5eXj4+Pn5+fs7Oza2tr6+vnq6urh", + "4eHe3t7c3Nza2dr6+fro6Og1NTXr6+xYWFi1tbWjo6OWl5aLjItDQ0PPz8+/v7", + "+wsLCenZ5zc3NOTk4Rpd0DAAAAqElEQVQoz62L2Q6CMBBFhcFdCsomq+v/f6Mn", + "bdOSBn3ypNO5Nyez+kG0zN9NWZZK8RRbB/2XmMLSvSZp2mehTMVcLGIYbcWcLW", + "1/U4PIZCvmOCMSaWzEHGaMIq2NmJNn4ORuMybP6xxYD0SnE4NJDdc0fYv0LCJg", + "9g4RqV3BrJfB7Bzc+ILZOjC+YDYOjC+YKqsyHlOZAX5Msgwm1iRxgDYBSWjCm+", + "98AAfDEgD0K69gAAAAAElFTkSuQmCC" + ].join(""); +} + function gui_load_default_image(dummy_cid, key) { pd_cache.set(key, { type: "png", - data: ["iVBORw0KGgoAAAANSUhEUgAAABkAAAAZCAMAAADzN3VRAAAAb1BMVEWBgYHX19", - "f///8vLy/8/Pzx8PH3+Pf19fXz8/Pu7u7l5eXj4+Pn5+fs7Oza2tr6+vnq6urh", - "4eHe3t7c3Nza2dr6+fro6Og1NTXr6+xYWFi1tbWjo6OWl5aLjItDQ0PPz8+/v7", - "+wsLCenZ5zc3NOTk4Rpd0DAAAAqElEQVQoz62L2Q6CMBBFhcFdCsomq+v/f6Mn", - "bdOSBn3ypNO5Nyez+kG0zN9NWZZK8RRbB/2XmMLSvSZp2mehTMVcLGIYbcWcLW", - "1/U4PIZCvmOCMSaWzEHGaMIq2NmJNn4ORuMybP6xxYD0SnE4NJDdc0fYv0LCJg", - "9g4RqV3BrJfB7Bzc+ILZOjC+YDYOjC+YKqsyHlOZAX5Msgwm1iRxgDYBSWjCm+", - "98AAfDEgD0K69gAAAAAElFTkSuQmCC" - ].join("") + data: get_default_png_data() }); } diff --git a/pd/src/g_canvas.c b/pd/src/g_canvas.c index e9c8f2d27..fb50bb6c2 100644 --- a/pd/src/g_canvas.c +++ b/pd/src/g_canvas.c @@ -1101,9 +1101,9 @@ static void canvas_pop(t_canvas *x, t_floatarg fvis) extern void *svg_new(t_pd *x, t_symbol *s, int argc, t_atom *argv); extern t_pd *svg_header(t_pd *x); -static void group_svginit(t_glist *gl) +static void group_svginit(t_glist *gl, t_symbol *type, int argc, t_atom *argv) { - gl->gl_svg = (t_pd *)(svg_new((t_pd *)gl, gensym("g"), 0, 0)); + gl->gl_svg = (t_pd *)(svg_new((t_pd *)gl, type, argc, argv)); t_pd *proxy = svg_header(gl->gl_svg); inlet_new(&gl->gl_obj, proxy, 0, 0); outlet_new(&gl->gl_obj, &s_anything); @@ -1116,10 +1116,14 @@ void canvas_restore(t_canvas *x, t_symbol *s, int argc, t_atom *argv) t_pd *z; int is_draw_command = 0; //fprintf(stderr,"canvas_restore %lx\n", x); - /* for [draw group] we add an inlet to the svg attr proxy */ - if (argc > 2 && argv[2].a_w.w_symbol == gensym("draw")) - { - group_svginit(x); + /* for [draw g] and [draw svg] we add an inlet to the svg attr proxy */ + if (atom_getsymbolarg(2, argc, argv) == gensym("draw")) + { + t_symbol *type = (atom_getsymbolarg(3, argc, argv) == gensym("svg")) ? + gensym("svg") : gensym("g"); + group_svginit(x, type, + (type == gensym("svg") && argc > 4) ? argc-4 : 0, + (type == gensym("svg") && argc > 4) ? argv+4 : 0); is_draw_command = 1; } if (argc > 3 || (is_draw_command && argc > 4)) @@ -1352,12 +1356,18 @@ static void *subcanvas_new(t_symbol *s) return (x); } -void *group_new(t_symbol *s) +void *group_new(t_symbol *type, int argc, t_atom *argv) { - t_canvas *x = subcanvas_new(s); - group_svginit(x); + t_symbol *groupname; + if (type == gensym("g")) + groupname = atom_getsymbolarg(0, argc, argv); + else /* no name for inner svg */ + groupname = &s_; + t_canvas *x = subcanvas_new(groupname); + group_svginit(x, type, argc, argv); return (x); } + static void canvas_click(t_canvas *x, t_floatarg xpos, t_floatarg ypos, t_floatarg shift, t_floatarg ctrl, t_floatarg alt) @@ -1376,6 +1386,14 @@ void canvas_fattensub(t_canvas *x, static void canvas_rename_method(t_canvas *x, t_symbol *s, int ac, t_atom *av) { + /* special case for [draw g] where the 3rd arg is the receiver name */ + if (x->gl_svg) + { + if (atom_getsymbolarg(0, ac, av) == gensym("g") && ac > 1) + ac--, av++; + else + ac = 0; + } if (ac && av->a_type == A_SYMBOL) canvas_rename(x, av->a_w.w_symbol, 0); else if (ac && av->a_type == A_DOLLSYM) diff --git a/pd/src/g_scalar.c b/pd/src/g_scalar.c index 38463cd52..7432aa57e 100644 --- a/pd/src/g_scalar.c +++ b/pd/src/g_scalar.c @@ -409,6 +409,11 @@ extern int array_joc; extern void template_notifyforscalar(t_template *template, t_glist *owner, t_scalar *sc, t_symbol *s, int argc, t_atom *argv); +extern void scalar_getinnersvgrect(t_gobj *z, t_glist *owner, t_word *data, + t_template *template, t_float basex, t_float basey, + int *xp1, int *yp1, int *xp2, int *yp2); + +extern t_symbol *group_gettype(t_glist *glist); static void scalar_getgrouprect(t_glist *owner, t_glist *groupcanvas, t_word *data, t_template *template, int basex, int basey, int *x1, int *x2, int *y1, int *y2) @@ -420,8 +425,12 @@ static void scalar_getgrouprect(t_glist *owner, t_glist *groupcanvas, ((t_canvas *)y)->gl_svg) { /* todo: accumulate basex and basey for correct offset */ - scalar_getgrouprect(owner, (t_glist *)y, data, template, - basex, basey, x1, x2, y1, y2); + if (group_gettype((t_canvas *)y) == gensym("g")) + scalar_getgrouprect(owner, (t_glist *)y, data, template, + basex, basey, x1, x2, y1, y2); + else /* inner svg */ + scalar_getinnersvgrect(y, owner, data, template, basex, basey, + x1, y1, x2, y2); } else { @@ -876,8 +885,9 @@ static void scalar_groupvis(t_scalar *x, t_glist *owner, t_template *template, char parentbuf[MAXPDSTRING]; sprintf(parentbuf, "dgroup%lx.%lx", (long unsigned int)parent, (long unsigned int)x->sc_vec); - gui_start_vmess("gui_scalar_draw_group", "xss", - glist_getcanvas(owner), tagbuf, parentbuf); + gui_start_vmess("gui_scalar_draw_group", "xsss", + glist_getcanvas(owner), tagbuf, parentbuf, + group_gettype(gl)->s_name); svg_grouptogui(gl, template, x->sc_vec); gui_end_vmess(); @@ -998,8 +1008,8 @@ static void scalar_vis(t_gobj *z, t_glist *owner, int vis) sprintf(tagbuf, "scalar%lxgobj", (long unsigned int)x->sc_vec); sprintf(groupbuf, "dgroup%lx.%lx", (long unsigned int)templatecanvas, (long unsigned int)x->sc_vec); - gui_vmess("gui_scalar_draw_group", "xss", - glist_getcanvas(owner), groupbuf, tagbuf); + gui_vmess("gui_scalar_draw_group", "xsss", + glist_getcanvas(owner), groupbuf, tagbuf, "g"); pd_bind(&x->sc_gobj.g_pd, gensym(buf)); } diff --git a/pd/src/g_template.c b/pd/src/g_template.c index 866f67787..dec213da8 100644 --- a/pd/src/g_template.c +++ b/pd/src/g_template.c @@ -1102,6 +1102,8 @@ t_class *draw_class; t_class *drawimage_class; +t_class *drawarray_class; + t_class *svg_class; /* this is a wrapper around t_fielddesc-- it adds a flag for two reasons: @@ -1187,6 +1189,7 @@ typedef struct _svg t_svg_attr x_width; t_svg_attr x_height; t_svg_attr x_vis; + t_svg_attr x_viewbox[4]; t_fielddesc x_bbox; /* turn bbox calculation on or off */ int x_pathrect_cache; /* 0 to recalc on next draw_getrect call 1 for cached @@ -1214,18 +1217,23 @@ typedef struct _drawimage { t_object x_obj; t_fielddesc x_value; /* todo: rename to index */ - t_fielddesc x_xloc; - t_fielddesc x_yloc; t_fielddesc x_vis; t_symbol *x_img; t_float x_w; t_float x_h; int x_flags; - int x_deleteme; t_canvas *x_canvas; t_pd *x_attr; } t_drawimage; +typedef struct _drawarray +{ + t_object x_obj; + t_canvas *x_canvas; + t_fielddesc x_data; + t_pd *x_attr; +} t_drawarray; + extern t_outlet *obj_rightmost_outlet(t_object *x); void draw_notifyforscalar(t_object *x, t_glist *owner, @@ -1287,9 +1295,9 @@ void svg_attr_setfloatarg(t_svg_attr *a, int argc, t_atom *argv) a->a_flag = 1; } -void svg_attr_setfloat_const(t_svg_attr *a, float n) +void svg_attr_setfloat_const(t_svg_attr *a, t_float n) { - fielddesc_setfloat_const(&a->a_attr, 0); + fielddesc_setfloat_const(&a->a_attr, n); a->a_flag = 0; } @@ -1309,9 +1317,10 @@ void *svg_new(t_pd *parent, t_symbol *s, int argc, t_atom *argv) if (type == gensym("rect") || type == gensym("circle") || type == gensym("ellipse") || - type == gensym("line")) + type == gensym("line") || + type == gensym("svg")) { - if (type == gensym("rect")) + if (type == gensym("rect") || type == gensym("svg")) { if (argc) svg_attr_setfloatarg(&x->x_width, argc--, argv++); else svg_attr_setfloat_const(&x->x_width, 0); @@ -1349,10 +1358,13 @@ void *svg_new(t_pd *parent, t_symbol *s, int argc, t_atom *argv) for (i = 0; i < ncmds; i++) x->x_nargs_per_cmd[i] = 0; x->x_nargs = argc - ncmds; } - else if (x->x_type == gensym("g")) + else if (type == gensym("g") || type == gensym("svg")) { x->x_nargs = 0; x->x_vec = 0; + /* Hack to get around the path parsing below, which should really + be split out... */ + argc = 0; } else { @@ -1407,6 +1419,8 @@ void *svg_new(t_pd *parent, t_symbol *s, int argc, t_atom *argv) x->x_strokemiterlimit.a_flag = 0; x->x_strokeopacity.a_flag = 0; x->x_strokewidth.a_flag = 0; + /* set the flag of the first array element... */ + x->x_viewbox->a_flag = 0; x->x_x1 = 0; x->x_x2 = 0; x->x_y1 = 0; @@ -1466,7 +1480,8 @@ static int symbol_isdrawtype(t_symbol *s) s == gensym("line") || s == gensym("path") || s == gensym("polygon") || s == gensym("polyline") || s == gensym("rect") || s == gensym("image") || - s == gensym("sprite") || s == gensym("g")) + s == gensym("sprite") || s == gensym("g") || + s == gensym("svg") || s == gensym("array")) { return 1; } @@ -1475,7 +1490,8 @@ static int symbol_isdrawtype(t_symbol *s) } static void *drawimage_new(t_symbol *classsym, int argc, t_atom *argv); -extern void *group_new(t_symbol *s); +static void *drawarray_new(t_symbol *s, int argc, t_atom *argv); +extern void *group_new(t_symbol *type, int argc, t_atom *argv); static void *draw_new(t_symbol *classsym, t_int argc, t_atom *argv) { @@ -1484,19 +1500,14 @@ static void *draw_new(t_symbol *classsym, t_int argc, t_atom *argv) symbol_isdrawtype(argv[0].a_w.w_symbol)) { type = atom_getsymbolarg(0, argc--, argv++); - /* sprite and image have their own widgetbehavior, so they - have their own class and new function */ + /* sprite and image have their own widgetbehavior, and so does + array. They also have their own classes and constructors... */ if (type == gensym("sprite") || type == gensym("image")) return (drawimage_new(type, argc, argv)); - else if (type == gensym("g")) - { - t_symbol *group_name; - if (argc > 0 && argv->a_type == A_SYMBOL) - group_name = atom_getsymbolarg(0, argc, argv); - else group_name = &s_; - post("group name is %s", group_name->s_name); - return (group_new(group_name)); - } + else if (type == gensym("array")) + return (drawarray_new(type, argc, argv)); + else if (type == gensym("g") || type == gensym("svg")) + return (group_new(type, argc, argv)); } else { @@ -1537,7 +1548,7 @@ t_canvas *svg_parentcanvas(t_svg *x) use case, but that doesn't seem like a sensible interface in general. */ t_canvas *ret = 0; - if (x->x_type == gensym("g")) + if (x->x_type == gensym("g") || x->x_type == gensym("svg")) { t_canvas *c = (t_canvas *)x->x_parent; if (c->gl_owner) @@ -1551,6 +1562,11 @@ t_canvas *svg_parentcanvas(t_svg *x) t_drawimage *d = (t_drawimage *)x->x_parent; ret = d->x_canvas; } + else if (x->x_type == gensym("array")) + { + t_drawarray *d = (t_drawarray *)x->x_parent; + ret = d->x_canvas; + } else { t_draw *d = (t_draw *)x->x_parent; @@ -1705,6 +1721,11 @@ t_svg_attr *svg_getattr(t_svg *x, t_symbol *s) return 0; } +t_symbol *group_gettype(t_glist *glist) +{ + return ((t_svg *)glist->gl_svg)->x_type; +} + void svg_parsetransform(t_svg *x, t_template *template, t_word *data, t_float *mp1, t_float *mp2, t_float *mp3, t_float *mp4, t_float *mp5, t_float *mp6); @@ -1723,7 +1744,7 @@ void svg_sendupdate(t_svg *x, t_canvas *c, t_symbol *s, int in_array = (sc->sc_vec != data); //post("in_array is %d", in_array); char tag[MAXPDSTRING]; - if (x->x_type == gensym("g")) + if (x->x_type == gensym("g") || x->x_type == gensym("svg")) { sprintf(tag, "%s%lx.%lx", (in_array ? "scelem" : "dgroup"), @@ -1797,7 +1818,18 @@ void svg_sendupdate(t_svg *x, t_canvas *c, t_symbol *s, t_float m1, m2, m3, m4, m5, m6; /* we'll probably get a different bbox now, so we will calculate a new one the next time we call draw_getrect for this draw command. - For groups we need to do it for all of the draw commands inside it. + For g we need to do it for all of the draw commands inside it. + + For inner svgs, however, we can ignore the inner content since + it will never appear outside the width/height specified for the + container. (At least not for now, since we don't allow the user + to set an overflow style of "visible.") This allows us to get + a speedup when interacting with content inside an inner svg, as + Pd doesn't have to do any complex bbox calculations. + + Unfortunately, the HTML5 getBBox() method calculates the boundaries + _without_ regard to clipping, so clipped content in inner svg will + still trigger scrollbars. */ if (x->x_type == gensym("g")) svg_group_pathrect_cache(x, 0); @@ -1930,6 +1962,25 @@ void svg_sendupdate(t_svg *x, t_canvas *c, t_symbol *s, gui_vmess("gui_drawimage_index", "xxxi", glist_getcanvas(c), parent, data, drawimage_getindex(parent, template, data)); } + else if (s == gensym("viewbox")) + { + gui_start_vmess("gui_draw_viewbox", "xss", + glist_getcanvas(c), tag, "viewBox"); + gui_start_array(); + if (x->x_viewbox->a_flag) + { + gui_f(fielddesc_getcoord(&x->x_viewbox[0].a_attr, + template, data, 0)); + gui_f(fielddesc_getcoord(&x->x_viewbox[1].a_attr, + template, data, 0)); + gui_f(fielddesc_getcoord(&x->x_viewbox[2].a_attr, + template, data, 0)); + gui_f(fielddesc_getcoord(&x->x_viewbox[3].a_attr, + template, data, 0)); + } + gui_end_array(); + gui_end_vmess(); + } else if (s == gensym("points")) { char tagbuf[MAXPDSTRING]; @@ -2175,6 +2226,22 @@ void svg_setattr(t_svg *x, t_symbol *s, t_int argc, t_atom *argv) } } +/* Currently used just to update the arguments when the user changes + the arguments in an existing [draw svg] object. */ +void svg_update_args(t_svg *x, t_symbol *s, int argc, t_atom *argv) +{ +post("made it to args"); +if (argc) post("first arg is %s", atom_getsymbolarg(0, argc, argv)->s_name); + /* "g" doesn't take any args, so check for "svg" arg */ + if (atom_getsymbolarg(0, argc, argv) == gensym("svg")) + { + argc--, argv++; + if (argc) svg_setattr(x, gensym("width"), argc--, argv++), post("did width"); + if (argc) svg_setattr(x, gensym("height"), argc--, argv++); + if (argc) svg_setattr(x, gensym("x"), argc--, argv++); + if (argc) svg_setattr(x, gensym("y"), argc--, argv++); + } +} void svg_vis(t_svg *x, t_symbol *s, int argc, t_atom *argv) { @@ -2577,6 +2644,29 @@ void svg_linepoints(t_svg *x, t_symbol *s, int argc, t_atom *argv) } } +void svg_viewbox(t_svg *x, t_symbol *s, int argc, t_atom *argv) +{ + if (argc) + { + t_svg_attr *vbx = x->x_viewbox; + svg_attr_setfloatarg(vbx++, argc--, argv++); + + if (argc) svg_attr_setfloatarg(vbx++, argc--, argv++); + else svg_attr_setfloat_const(vbx++, 0); + + if (argc) svg_attr_setfloatarg(vbx++, argc--, argv++); + else svg_attr_setfloat_const(vbx++, 0); + + if (argc) svg_attr_setfloatarg(vbx, argc, argv); + else svg_attr_setfloat_const(vbx, 0); + } + else + { + x->x_viewbox->a_flag = 0; + } + svg_update(x, gensym("viewbox")); +} + static int minv(t_float a[][3], t_float b[][3]) { t_float tmp[3][3], determinant = 0; @@ -3513,6 +3603,90 @@ static void svg_getpathrect(t_svg *x, t_glist *glist, *yp2 = (int)(finaly2 + basey); } +static void svg_getrectrect(t_svg *x, t_glist *glist, + t_word *data, t_template *template, t_float basex, t_float basey, + int *xp1, int *yp1, int *xp2, int *yp2) +{ + int width, height, xoff, yoff; + int x1, y1, x2, y2; + x1 = y1 = 0x7fffffff; + x2 = y2 = -0x7fffffff; + + t_float mtx1[3][3] = { {1, 0, 0}, {0, 1, 0}, {0, 0, 1} }; + t_float mtx2[3][3] = { {1, 0, 0}, {0, 1, 0}, {1, 0, 1} }; + t_float m1, m2, m3, m4, m5, m6, + tx1, ty1, tx2, ty2, t5, t6; + if (!fielddesc_getfloat(&x->x_bbox, template, data, 0) || + (x->x_vis.a_flag && !fielddesc_getfloat(&x->x_vis.a_attr, + template, data, 0))) + { + *xp1 = *yp1 = 0x7fffffff; + *xp2 = *yp2 = -0x7fffffff; + return; + } + + svg_groupmtx(x, template, data, mtx1); + width = fielddesc_getcoord(&x->x_width.a_attr, template, data, 0); + height = fielddesc_getcoord(&x->x_height.a_attr, template, data, 0); + xoff = fielddesc_getcoord(&x->x_x.a_attr, template, data, 0); + yoff = fielddesc_getcoord(&x->x_y.a_attr, template, data, 0); + + mset(mtx2, xoff, yoff, xoff + width, yoff + height, 0, 0); + mtx2[2][0] = 1; mtx2[2][1] = 1; + mmult(mtx1, mtx2, mtx2); + mget(mtx2, &tx1, &ty1, &tx2, &ty2, &t5, &t6); + if (tx1 < x1) x1 = tx1; + if (tx2 < x1) x1 = tx2; + if (ty1 < y1) y1 = ty1; + if (ty2 < y1) y1 = ty2; + if (tx1 > x2) x2 = tx1; + if (tx2 > x2) x2 = tx2; + if (ty1 > y2) y2 = ty1; + if (ty2 > y2) y2 = ty2; + mset(mtx2, xoff, yoff + height, xoff + width, yoff, 0, 0); + mtx2[2][0] = 1; mtx2[2][1] = 1; + mmult(mtx1, mtx2, mtx2); + mget(mtx2, &tx1, &ty1, &tx2, &ty2, &t5, &t6); + if (tx1 < x1) x1 = tx1; + if (tx2 < x1) x1 = tx2; + if (ty1 < y1) y1 = ty1; + if (ty2 < y1) y1 = ty2; + if (tx1 > x2) x2 = tx1; + if (tx2 > x2) x2 = tx2; + if (ty1 > y2) y2 = ty1; + if (ty2 > y2) y2 = ty2; + //x1 = glist_xtopixels(glist, basex + x1); + //x2 = glist_xtopixels(glist, basex + x2); + //y1 = glist_ytopixels(glist, basey + y1); + //y2 = glist_ytopixels(glist, basey + y2); + + x1 = basex + x1; + x2 = basex + x2; + y1 = basey + y1; + y2 = basey + y2; + + /* todo: put these up top */ + if (!fielddesc_getfloat(&x->x_vis.a_attr, template, data, 0)) + { + *xp1 = *yp1 = 0x7fffffff; + *xp2 = *yp2 = -0x7fffffff; + return; + } + *xp1 = x1; + *yp1 = y1; + *xp2 = x2; + *yp2 = y2; +} + +void scalar_getinnersvgrect(t_gobj *z, t_glist *owner, t_word *data, + t_template *template, t_float basex, t_float basey, + int *xp1, int *yp1, int *xp2, int *yp2) +{ + t_canvas *c = (t_canvas *)z; + svg_getrectrect((t_svg *)c->gl_svg, + owner, data, template, basex, basey, xp1, yp1, xp2, yp2); +} + static void draw_getrect(t_gobj *z, t_glist *glist, t_word *data, t_template *template, t_float basex, t_float basey, int *xp1, int *yp1, int *xp2, int *yp2) @@ -3811,13 +3985,13 @@ static void svg_togui(t_svg *x, t_template *template, t_word *data) } if (x->x_x.a_flag) { - gui_s(x->x_type == gensym("rect") ? "x" : + gui_s(x->x_type == gensym("rect") || x->x_type == gensym("svg") ? "x" : x->x_type == gensym("line") ? "x1" : "cx"); gui_f(fielddesc_getcoord(&x->x_x.a_attr, template, data, 0)); } if (x->x_y.a_flag) { - gui_s(x->x_type == gensym("rect") ? "y" : + gui_s(x->x_type == gensym("rect") || x->x_type == gensym("svg") ? "y" : x->x_type == gensym("line") ? "y1" : "cy"); gui_f(fielddesc_getcoord(&x->x_y.a_attr, template, data, 0)); } @@ -3944,6 +4118,20 @@ static void svg_togui(t_svg *x, t_template *template, t_word *data) gui_f(fielddesc_getcoord(&x->x_ry.a_attr, template, data, 0)); } + if (x->x_viewbox->a_flag) + { + gui_s("viewBox"); + gui_start_array(); + gui_f(fielddesc_getcoord(&x->x_viewbox[0].a_attr, + template, data, 0)); + gui_f(fielddesc_getcoord(&x->x_viewbox[1].a_attr, + template, data, 0)); + gui_f(fielddesc_getcoord(&x->x_viewbox[2].a_attr, + template, data, 0)); + gui_f(fielddesc_getcoord(&x->x_viewbox[3].a_attr, + template, data, 0)); + gui_end_array(); + } // Not sure why display attr is here... gui_s("display"); gui_s("inline"); @@ -4564,6 +4752,8 @@ static void draw_setup(void) gensym("stroke-width"), A_GIMME, 0); class_addmethod(svg_class, (t_method)svg_transform, gensym("transform"), A_GIMME, 0); + class_addmethod(svg_class, (t_method)svg_viewbox, + gensym("viewBox"), A_GIMME, 0); class_addmethod(svg_class, (t_method)svg_setattr, gensym("vis"), A_GIMME, 0); class_addmethod(svg_class, (t_method)svg_setattr, @@ -4580,6 +4770,8 @@ static void draw_setup(void) gensym("y1"), A_GIMME, 0); class_addmethod(svg_class, (t_method)svg_setattr, gensym("y2"), A_GIMME, 0); + class_addmethod(svg_class, (t_method)svg_update_args, + gensym("update_svg"), A_GIMME, 0); } /* ------------------------------ event --------------------------------- */ @@ -5513,8 +5705,6 @@ static void plot_getgrouprect(t_glist *glist, t_template *elemtemplate, } } - - static void plot_getrect(t_gobj *z, t_glist *glist, t_word *data, t_template *template, t_float basex, t_float basey, int *xp1, int *yp1, int *xp2, int *yp2) @@ -5697,10 +5887,11 @@ static void plot_groupvis(t_scalar *x, t_glist *owner, t_word *data, (long unsigned int)data); sprintf(parent_tagbuf, "scelem%lx.%lx", (long unsigned int)parent, (long unsigned int)data); - gui_start_vmess("gui_create_scalar_group", "xss", + gui_start_vmess("gui_scalar_draw_group", "xsss", glist_getcanvas(owner), tagbuf, - parent_tagbuf); + parent_tagbuf, + "g"); svg_grouptogui(groupcanvas, template, data); gui_end_vmess(); for (y = groupcanvas->gl_list; y; y = y->g_next) @@ -6325,148 +6516,660 @@ static void plot_setup(void) class_setparentwidget(plot_class, &plot_widgetbehavior); } -/* ---------------- drawnumber: draw a number (or symbol) ---------------- */ - -/* - drawnumbers draw numeric fields at controllable locations, with - controllable color and label. invocation: - (drawnumber|drawsymbol) [-v <visible>] variable x y color label -*/ - -t_class *drawnumber_class; - -#define DRAW_SYMBOL 1 +/* --------- generic draw command for showing arrays --------------- */ -typedef struct _drawnumber +static void *drawarray_new(t_symbol *s, int argc, t_atom *argv) { - t_object x_obj; - t_fielddesc x_value; - t_fielddesc x_xloc; - t_fielddesc x_yloc; - t_fielddesc x_color; - t_fielddesc x_vis; - t_fielddesc x_fontsize; - t_symbol *x_label; - int x_flags; - t_canvas *x_canvas; -} t_drawnumber; + t_drawarray *x = (t_drawarray *)pd_new(drawarray_class); -static void *drawnumber_new(t_symbol *classsym, t_int argc, t_atom *argv) -{ - if (legacy_draw_in_group(canvas_getcurrent())) - return 0; + /* We need a t_svg to associate with it */ + x->x_attr = (t_pd *)svg_new((t_pd *)x, s, 0, 0); + t_svg *sa = (t_svg *)x->x_attr; - t_drawnumber *x = (t_drawnumber *)pd_new(drawnumber_class); - char *classname = classsym->s_name; - int flags = 0; - int got_font_size = 0; - - if (classname[4] == 's') - flags |= DRAW_SYMBOL; - x->x_flags = flags; - fielddesc_setfloat_const(&x->x_vis, 1); x->x_canvas = canvas_getcurrent(); - while (1) - { - t_symbol *firstarg = atom_getsymbolarg(0, argc, argv); - if (!strcmp(firstarg->s_name, "-v") && argc > 1) - { - fielddesc_setfloatarg(&x->x_vis, 1, argv+1); - argc -= 2; argv += 2; - } - else break; - } - if (flags & DRAW_SYMBOL) - { - if (argc) fielddesc_setsymbolarg(&x->x_value, argc--, argv++); - else fielddesc_setsymbol_const(&x->x_value, &s_); - } - else - { - if (argc) fielddesc_setfloatarg(&x->x_value, argc--, argv++); - else fielddesc_setfloat_const(&x->x_value, 0); - } - if (argc) fielddesc_setfloatarg(&x->x_xloc, argc--, argv++); - else fielddesc_setfloat_const(&x->x_xloc, 0); - if (argc) fielddesc_setfloatarg(&x->x_yloc, argc--, argv++); - else fielddesc_setfloat_const(&x->x_yloc, 0); - if (argc) fielddesc_setfloatarg(&x->x_color, argc--, argv++); - else fielddesc_setfloat_const(&x->x_color, 1); + t_template *t = template_findbyname( + canvas_makebindsym(x->x_canvas->gl_name)); - if (argc == 2) - { - fielddesc_setfloatarg(&x->x_fontsize, argc--, argv++); - got_font_size = 1; - } - if (argc) - { - if (argv->a_type == A_SYMBOL || got_font_size) - { - x->x_label = atom_getsymbolarg(0, argc, argv); - if (!got_font_size) - fielddesc_setfloatarg(&x->x_fontsize, 0, NULL); - } - else if (argv->a_type == A_FLOAT) - { - fielddesc_setfloatarg(&x->x_fontsize, argc, argv); - x->x_label = &s_; - } - } else { - fielddesc_setfloatarg(&x->x_fontsize, 0, NULL); - x->x_label = &s_; - } + if (argc) fielddesc_setarrayarg(&x->x_data, argc--, argv++); + else fielddesc_setfloat_const(&x->x_data, 1); + + /* Default dimensions for SVG: 150x100 */ + if (argc) svg_attr_setfloatarg(&sa->x_width, argc--, argv++); + else svg_attr_setfloat_const(&sa->x_width, 150); + if (argc) svg_attr_setfloatarg(&sa->x_height, argc--, argv++); + else svg_attr_setfloat_const(&sa->x_height, 100); return (x); } -void drawnumber_float(t_drawnumber *x, t_floatarg f) +void drawarray_float(t_drawarray *x, t_floatarg f) { - int viswas; - if (x->x_vis.fd_type != A_FLOAT || x->x_vis.fd_var) - { - pd_error(x, "global vis/invis for a template with variable visibility"); - return; - } - viswas = (x->x_vis.fd_un.fd_float != 0); - - if ((f != 0 && viswas) || (f == 0 && !viswas)) - return; - canvas_redrawallfortemplatecanvas(x->x_canvas, 2); - fielddesc_setfloat_const(&x->x_vis, (f != 0)); - canvas_redrawallfortemplatecanvas(x->x_canvas, 1); + /* toggle visibility on and off */ } -/* -------------------- widget behavior for drawnumber ------------ */ - -/*#define DRAWNUMBER_BUFSIZE 80 -static void drawnumber_sprintf(t_drawnumber *x, char *buf, t_atom *ap) +void drawarray_transform(t_drawarray *x, t_floatarg f) { - int nchars; - strncpy(buf, x->x_label->s_name, DRAWNUMBER_BUFSIZE); - buf[DRAWNUMBER_BUFSIZE - 1] = 0; - nchars = strlen(buf); - atom_string(ap, buf + nchars, DRAWNUMBER_BUFSIZE - nchars); -}*/ + /* draw array uses an inner svg as the container, which + has no transform attribute */ + pd_error(x, "draw array: no method for 'transform'"); +} -static int drawnumber_gettype(t_drawnumber *x, t_word *data, - t_template *template, int *onsetp) +static void drawarray_anything(t_drawarray *x, t_symbol *s, int argc, + t_atom *argv) { - int type; - t_symbol *arraytype; - if (template_find_field(template, /*x->x_fieldname*/ x->x_value.fd_un.fd_varsym, onsetp, &type, - &arraytype) && type != DT_ARRAY) - return (type); - else return (-1); + /* forward to t_svg thingy */ + pd_typedmess(x->x_attr, s, argc, argv); } -#define DRAWNUMBER_BUFSIZE 1024 -static void drawnumber_getbuf(t_drawnumber *x, t_word *data, - t_template *template, char *buf) +/* -------------------- widget behavior for drawarray ------------ */ + + + /* get everything we'll need from the owner template of the array being + drawn. Not used for garrays, but see below */ +static int drawarray_readownertemplate(t_drawarray *x, + t_word *data, t_template *ownertemplate, + t_symbol **elemtemplatesymp, t_array **arrayp) { - int nchars, onset, type = drawnumber_gettype(x, data, template, &onset); - if (type < 0) - buf[0] = 0; - else + int arrayonset, type; + t_symbol *elemtemplatesym; + t_array *array; + + /* find the data and verify it's an array */ + if (x->x_data.fd_type != A_ARRAY || !x->x_data.fd_var) + { + error("draw array: needs an array field"); + return (-1); + } + if (!template_find_field(ownertemplate, x->x_data.fd_un.fd_varsym, + &arrayonset, &type, &elemtemplatesym)) + { + error("draw array: %s: no such field", x->x_data.fd_un.fd_varsym->s_name); + return (-1); + } + if (type != DT_ARRAY) + { + error("draw array: %s: not an array", x->x_data.fd_un.fd_varsym->s_name); + return (-1); + } + array = *(t_array **)(((char *)data) + arrayonset); + *elemtemplatesymp = elemtemplatesym; + *arrayp = array; + + return (0); +} + +static void drawarray_getgrouprect(t_glist *glist, t_template *elemtemplate, + t_canvas *groupcanvas, int elemsize, + t_array *array, int i, t_float usexloc, t_float useyloc, + int *x1, int *y1, int *x2, int *y2) +{ + t_gobj *y; + for (y = groupcanvas->gl_list; y; y = y->g_next) + { + if (pd_class(&y->g_pd) == canvas_class && + ((t_canvas *)y)->gl_svg) + { + drawarray_getgrouprect(glist, elemtemplate, (t_canvas *)y, + elemsize, array, i, usexloc, useyloc, x1, y1, x2, y2); + } + //fprintf(stderr,".-.-. usexloc %f useyloc %f " + // "(alt %f %f)\n", + // usexloc, useyloc, + // basex + xloc + + // fielddesc_cvttocoord(xfielddesc, + // *(t_float *)(((char *)(array->a_vec) + elemsize * i) + // + xonset)), + // *(t_float *)(((char *)(array->a_vec) + elemsize * i) + + // yonset)); + int xx1, xx2, yy1, yy2; + t_parentwidgetbehavior *wb = pd_getparentwidget(&y->g_pd); + if (!wb) continue; + (*wb->w_parentgetrectfn)(y, glist, + (t_word *)((char *)(array->a_vec) + elemsize * i), + elemtemplate, usexloc, useyloc, + &xx1, &yy1, &xx2, &yy2); + //fprintf(stderr," .....drawarray_getrect %d %d %d %d\n", + // xx1, yy1, xx2, yy2); + if (xx1 < *x1) + *x1 = xx1; + if (yy1 < *y1) + *y1 = yy1; + if (xx2 > *x2) + *x2 = xx2; + if (yy2 > *y2) + *y2 = yy2; + //fprintf(stderr," ....drawarray_getrect %d %d %d %d\n", + // x1, y1, x2, y2); + } +} + +static void drawarray_getrect(t_gobj *z, t_glist *glist, + t_word *data, t_template *template, t_float basex, t_float basey, + int *xp1, int *yp1, int *xp2, int *yp2) +{ + t_drawarray *x = (t_drawarray *)z; + int width, height, xoff, yoff; + int x1, y1, x2, y2; + x1 = y1 = 0x7fffffff; + x2 = y2 = -0x7fffffff; + + t_float mtx1[3][3] = { {1, 0, 0}, {0, 1, 0}, {0, 0, 1} }; + t_float mtx2[3][3] = { {1, 0, 0}, {0, 1, 0}, {1, 0, 1} }; + t_float m1, m2, m3, m4, m5, m6, + tx1, ty1, tx2, ty2, t5, t6; + t_svg *sa = (t_svg *)x->x_attr; + if (!fielddesc_getfloat(&sa->x_bbox, template, data, 0) || + (sa->x_vis.a_flag && !fielddesc_getfloat(&sa->x_vis.a_attr, + template, data, 0))) + { + *xp1 = *yp1 = 0x7fffffff; + *xp2 = *yp2 = -0x7fffffff; + return; + } + + svg_groupmtx(sa, template, data, mtx1); + width = fielddesc_getcoord(&sa->x_width.a_attr, template, data, 0); + height = fielddesc_getcoord(&sa->x_height.a_attr, template, data, 0); + xoff = fielddesc_getcoord(&sa->x_x.a_attr, template, data, 0); + yoff = fielddesc_getcoord(&sa->x_y.a_attr, template, data, 0); + + mset(mtx2, xoff, yoff, xoff + width, yoff + height, 0, 0); + mtx2[2][0] = 1; mtx2[2][1] = 1; + mmult(mtx1, mtx2, mtx2); + mget(mtx2, &tx1, &ty1, &tx2, &ty2, &t5, &t6); + if (tx1 < x1) x1 = tx1; + if (tx2 < x1) x1 = tx2; + if (ty1 < y1) y1 = ty1; + if (ty2 < y1) y1 = ty2; + if (tx1 > x2) x2 = tx1; + if (tx2 > x2) x2 = tx2; + if (ty1 > y2) y2 = ty1; + if (ty2 > y2) y2 = ty2; + mset(mtx2, xoff, yoff + height, xoff + width, yoff, 0, 0); + mtx2[2][0] = 1; mtx2[2][1] = 1; + mmult(mtx1, mtx2, mtx2); + mget(mtx2, &tx1, &ty1, &tx2, &ty2, &t5, &t6); + if (tx1 < x1) x1 = tx1; + if (tx2 < x1) x1 = tx2; + if (ty1 < y1) y1 = ty1; + if (ty2 < y1) y1 = ty2; + if (tx1 > x2) x2 = tx1; + if (tx2 > x2) x2 = tx2; + if (ty1 > y2) y2 = ty1; + if (ty2 > y2) y2 = ty2; + //x1 = glist_xtopixels(glist, basex + x1); + //x2 = glist_xtopixels(glist, basex + x2); + //y1 = glist_ytopixels(glist, basey + y1); + //y2 = glist_ytopixels(glist, basey + y2); + + x1 = basex + x1; + x2 = basex + x2; + y1 = basey + y1; + y2 = basey + y2; + + /* todo: put these up top */ + if (!fielddesc_getfloat(&sa->x_vis.a_attr, template, data, 0)) + { + *xp1 = *yp1 = 0x7fffffff; + *xp2 = *yp2 = -0x7fffffff; + return; + } + *xp1 = x1; + *yp1 = y1; + *xp2 = x2; + *yp2 = y2; +} + +static void drawarray_displace(t_gobj *z, t_glist *glist, + t_word *data, t_template *template, t_float basex, t_float basey, + int dx, int dy) +{ + /* not yet */ +} + +static void drawarray_select(t_gobj *z, t_glist *glist, + t_word *data, t_template *template, t_float basex, t_float basey, + int state) +{ + //fprintf(stderr,"drawarray_select %d\n", state); + /* not yet */ +} + +static void drawarray_activate(t_gobj *z, t_glist *glist, + t_word *data, t_template *template, t_float basex, t_float basey, + int state) +{ + /* not yet */ +} + +static void drawarray_groupvis(t_scalar *x, t_glist *owner, t_word *data, + t_template *template, + t_glist *groupcanvas, t_glist *parent, t_float basex, t_float basey) +{ + t_gobj *y; + char tagbuf[MAXPDSTRING], parent_tagbuf[MAXPDSTRING]; + sprintf(tagbuf, "scelem%lx.%lx", (long unsigned int)groupcanvas, + (long unsigned int)data); + sprintf(parent_tagbuf, "scelem%lx.%lx", (long unsigned int)parent, + (long unsigned int)data); + gui_start_vmess("gui_scalar_draw_group", "xsss", + glist_getcanvas(owner), + tagbuf, + parent_tagbuf, + "g"); + svg_grouptogui(groupcanvas, template, data); + gui_end_vmess(); + for (y = groupcanvas->gl_list; y; y = y->g_next) + { + if (pd_class(&y->g_pd) == canvas_class && + ((t_glist *)y)->gl_svg) + { + drawarray_groupvis(x, owner, data, template, (t_glist *)y, + groupcanvas, basex, basey); + } + t_parentwidgetbehavior *wb = pd_getparentwidget(&y->g_pd); + if (!wb) continue; + (*wb->w_parentvisfn)(y, owner, groupcanvas, x, data, template, + basex, basey, 1); + } +} + +/* todo: merge this with plot_has_drawcommand */ +/* see if the elements we're plotting have any drawing commands */ +int drawarray_has_drawcommand(t_canvas *elemtemplatecanvas) +{ + t_gobj *y; + for (y = elemtemplatecanvas->gl_list; y; y = y->g_next) + { + if (pd_class(&y->g_pd) == canvas_class && ((t_glist *)y)->gl_svg) + return 1; + else if (class_isdrawcommand(y->g_pd)) + return 1; + } + return 0; +} + +static void drawarray_vis(t_gobj *z, t_glist *glist, t_glist *parentglist, + t_scalar *sc, t_word *data, t_template *template, + t_float basex, t_float basey, int tovis) +{ + t_drawarray *x = (t_drawarray *)z; + int elemsize, yonset, wonset, xonset, i; + t_canvas *elemtemplatecanvas; + t_template *elemtemplate; + t_symbol *elemtemplatesym; + t_fielddesc *xfielddesc, *yfielddesc, *wfielddesc; + /* Let's just set constant increment values and see how they + play out before adding xinc and yinc to the public interface... */ + t_float xinc = 40, yinc = 40, xsum, yval; + t_array *array; + int nelem; + char *elem; + + if (drawarray_readownertemplate(x, data, template, + &elemtemplatesym, &array) + || array_getfields(elemtemplatesym, &elemtemplatecanvas, + &elemtemplate, &elemsize, 0, 0, 0, + &xonset, &yonset, &wonset)) + return; + nelem = array->a_n; + elem = (char *)array->a_vec; + + /* id for the the viewport-- we prefix it with "draw" to be + compatible with the other svg-based drawcommands */ + char viewport_tagbuf[MAXPDSTRING]; + sprintf(viewport_tagbuf, "draw%lx.%lx", + (long unsigned int)x, (long unsigned int)data); + + if (tovis) + { + int in_array = (sc->sc_vec == data) ? 0 : 1; + int draw_scalars = plot_has_drawcommand(elemtemplatecanvas); + + /* make sure the array drawings are behind the graph */ + /* not doing this yet with the GUI port... */ + //sys_vgui(".x%lx.c lower plot%lx graph%lx\n", glist_getcanvas(glist), + // data, glist); + + /* 1. Set up the main <g> for this widget */ + char parent_tagbuf[MAXPDSTRING]; + if (in_array) + { + sprintf(parent_tagbuf, "scelem%lx.%lx", + (long unsigned int)parentglist, + (long unsigned int)data); + } + else + { + sprintf(parent_tagbuf, "dgroup%lx.%lx", + (long unsigned int)x->x_canvas, + (long unsigned int)data); + } + + t_svg *sa = (t_svg *)x->x_attr; + gui_start_vmess("gui_draw_vis", "xs", + glist_getcanvas(glist), "g"); + svg_togui(sa, template, data); + + gui_start_array(); + gui_s(parent_tagbuf); + gui_s(viewport_tagbuf); + gui_end_array(); + gui_end_vmess(); + + /* 2. Draw the individual elements */ + /* This code is inefficient since the template has to be + searched for drawing instructions for every last point. */ + if (draw_scalars) + { + //t_float xoffset = in_array ? basex: 0; + //t_float yoffset = in_array ? basey: 0; + t_float xoffset = 0; + t_float yoffset = 0; + + for (xsum = 0, i = 0; i < nelem; i++) + { + t_float usexloc, useyloc; + t_gobj *y; + if (xonset >= 0) + usexloc = xoffset + + *(t_float *)((elem + elemsize * i) + xonset); + else usexloc = xoffset + xsum, xsum += xinc; + if (yonset >= 0) + yval = *(t_float *)((elem + elemsize * i) + yonset); + else yval = 0; + useyloc = yoffset + yval; + /* fielddesc_cvttocoord(yfielddesc, yval); */ + /* We're setting up a special group that will get set as + the parent by array elements */ + + /* todo: need to check if drawarray itself is in an array */ + char tagbuf[MAXPDSTRING]; + sprintf(tagbuf, "scelem%lx.%lx", + (long unsigned int)elemtemplatecanvas, + (long unsigned int)((t_word *)(elem + elemsize * i))); + char transform_buf[MAXPDSTRING]; + sprintf(transform_buf, "translate(%g,%g)", usexloc, useyloc); + + gui_start_vmess("gui_draw_vis", "xs", + glist_getcanvas(glist), "g"); + gui_start_array(); + gui_s("transform"); + gui_s(transform_buf); + gui_end_array(); + gui_start_array(); + gui_s(viewport_tagbuf); + gui_s(tagbuf); + gui_end_array(); + gui_end_vmess(); + + for (y = elemtemplatecanvas->gl_list; y; y = y->g_next) + { + if (pd_class(&y->g_pd) == canvas_class && + ((t_glist *)y)->gl_svg) + { + drawarray_groupvis(sc, glist, + (t_word *)(elem + elemsize * i), + template, (t_glist *)y, + elemtemplatecanvas, usexloc, useyloc); + } + t_parentwidgetbehavior *wb = pd_getparentwidget(&y->g_pd); + if (!wb) continue; + (*wb->w_parentvisfn)(y, glist, elemtemplatecanvas, sc, + (t_word *)(elem + elemsize * i), + elemtemplate, usexloc, useyloc, tovis); + } + } + } + if (!glist_istoplevel(glist)) + { + t_canvas *gl = glist_getcanvas(glist); + char objtag[64]; + sprintf(objtag, ".x%lx.x%lx.template%lx", + (t_int)gl, (t_int)glist, (t_int)data); + canvas_restore_original_position(gl, (t_gobj *)glist, objtag, -1); + } + } + else + { + /* un-draw the individual points */ + //fprintf(stderr,"drawarray_vis UNVIS\n"); + + int i; + for (i = 0; i < nelem; i++) + { + t_gobj *y; + for (y = elemtemplatecanvas->gl_list; y; y = y->g_next) + { + t_parentwidgetbehavior *wb = pd_getparentwidget(&y->g_pd); + if (!wb) continue; + (*wb->w_parentvisfn)(y, glist, elemtemplatecanvas, sc, + (t_word *)(elem + elemsize * i), elemtemplate, + 0, 0, 0); + } + } + /* Now remove our drawarray svg container */ + gui_vmess("gui_draw_erase_item", "xs", glist_getcanvas(glist), + viewport_tagbuf); + } +} + +static int drawarray_click(t_gobj *z, t_glist *glist, + t_word *data, t_template *template, t_scalar *sc, t_array *ap, + t_float basex, t_float basey, + int xpix, int ypix, int shift, int alt, int dbl, int doit) +{ +/* Let's hold off on this for a bit... + //fprintf(stderr,"drawarray_click %lx %lx %f %f %d %d\n", + // (t_int)z, (t_int)glist, basex, basey, xpix, ypix); + t_drawarray *x = (t_drawarray *)z; + t_symbol *elemtemplatesym; + t_float linewidth, xloc, xinc, yloc, style, vis, scalarvis; + t_array *array; + t_fielddesc *xfielddesc, *yfielddesc, *wfielddesc; + t_symbol *symfillcolor; + t_symbol *symoutlinecolor; + + if (!drawarray_readownertemplate(x, data, template, + &elemtemplatesym, &array) + && (vis != 0)) + { + //fprintf(stderr," ->array_doclick\n"); + return (array_doclick(array, glist, sc, ap, + elemtemplatesym, + linewidth, basex + xloc, xinc, basey + yloc, scalarvis, + xfielddesc, yfielddesc, wfielddesc, + xpix, ypix, shift, alt, dbl, doit)); + } + else return (0); +*/ + return 0; +} + +static void drawarray_free(t_drawarray *x) +{ + //sys_queuegui(x->x_canvas, 0, canvas_redrawallfortemplatecanvas); + /* decrement variable of the template + to prevent transform as that would + make arrays break their hitboxes + and all kinds of other bad stuff */ + t_template *t = template_findbyname( + canvas_makebindsym(x->x_canvas->gl_name) + ); + if (t) + { + t->t_transformable--; + //fprintf(stderr,"drawarray_free > template:%lx(%s) transform:%d\n", + // (t_int)t, canvas_makebindsym(x->x_canvas->gl_name)->s_name, + // t->t_transformable); + } +} + +t_parentwidgetbehavior drawarray_widgetbehavior = +{ + drawarray_getrect, + drawarray_displace, + drawarray_select, + drawarray_activate, + drawarray_vis, + drawarray_click, +}; + +static void drawarray_setup(void) +{ + drawarray_class = class_new(gensym("drawarray"), + 0, + (t_method)drawarray_free, sizeof(t_drawarray), 0, A_GIMME, 0); + class_setdrawcommand(drawarray_class); + class_addfloat(drawarray_class, drawarray_float); + class_addmethod(drawarray_class, (t_method)drawarray_transform, + gensym("transform"), A_GIMME, 0); + class_addanything(drawarray_class, drawarray_anything); + class_setparentwidget(drawarray_class, &drawarray_widgetbehavior); +} + +/* ---------------- drawnumber: draw a number (or symbol) ---------------- */ + +/* + drawnumbers draw numeric fields at controllable locations, with + controllable color and label. invocation: + (drawnumber|drawsymbol) [-v <visible>] variable x y color label +*/ + +t_class *drawnumber_class; + +#define DRAW_SYMBOL 1 + +typedef struct _drawnumber +{ + t_object x_obj; + t_fielddesc x_value; + t_fielddesc x_xloc; + t_fielddesc x_yloc; + t_fielddesc x_color; + t_fielddesc x_vis; + t_fielddesc x_fontsize; + t_symbol *x_label; + int x_flags; + t_canvas *x_canvas; +} t_drawnumber; + +static void *drawnumber_new(t_symbol *classsym, t_int argc, t_atom *argv) +{ + if (legacy_draw_in_group(canvas_getcurrent())) + return 0; + + t_drawnumber *x = (t_drawnumber *)pd_new(drawnumber_class); + char *classname = classsym->s_name; + int flags = 0; + int got_font_size = 0; + + if (classname[4] == 's') + flags |= DRAW_SYMBOL; + x->x_flags = flags; + fielddesc_setfloat_const(&x->x_vis, 1); + x->x_canvas = canvas_getcurrent(); + while (1) + { + t_symbol *firstarg = atom_getsymbolarg(0, argc, argv); + if (!strcmp(firstarg->s_name, "-v") && argc > 1) + { + fielddesc_setfloatarg(&x->x_vis, 1, argv+1); + argc -= 2; argv += 2; + } + else break; + } + if (flags & DRAW_SYMBOL) + { + if (argc) fielddesc_setsymbolarg(&x->x_value, argc--, argv++); + else fielddesc_setsymbol_const(&x->x_value, &s_); + } + else + { + if (argc) fielddesc_setfloatarg(&x->x_value, argc--, argv++); + else fielddesc_setfloat_const(&x->x_value, 0); + } + if (argc) fielddesc_setfloatarg(&x->x_xloc, argc--, argv++); + else fielddesc_setfloat_const(&x->x_xloc, 0); + if (argc) fielddesc_setfloatarg(&x->x_yloc, argc--, argv++); + else fielddesc_setfloat_const(&x->x_yloc, 0); + if (argc) fielddesc_setfloatarg(&x->x_color, argc--, argv++); + else fielddesc_setfloat_const(&x->x_color, 1); + + if (argc == 2) + { + fielddesc_setfloatarg(&x->x_fontsize, argc--, argv++); + got_font_size = 1; + } + if (argc) + { + if (argv->a_type == A_SYMBOL || got_font_size) + { + x->x_label = atom_getsymbolarg(0, argc, argv); + if (!got_font_size) + fielddesc_setfloatarg(&x->x_fontsize, 0, NULL); + } + else if (argv->a_type == A_FLOAT) + { + fielddesc_setfloatarg(&x->x_fontsize, argc, argv); + x->x_label = &s_; + } + } else { + fielddesc_setfloatarg(&x->x_fontsize, 0, NULL); + x->x_label = &s_; + } + + return (x); +} + +void drawnumber_float(t_drawnumber *x, t_floatarg f) +{ + int viswas; + if (x->x_vis.fd_type != A_FLOAT || x->x_vis.fd_var) + { + pd_error(x, "global vis/invis for a template with variable visibility"); + return; + } + viswas = (x->x_vis.fd_un.fd_float != 0); + + if ((f != 0 && viswas) || (f == 0 && !viswas)) + return; + canvas_redrawallfortemplatecanvas(x->x_canvas, 2); + fielddesc_setfloat_const(&x->x_vis, (f != 0)); + canvas_redrawallfortemplatecanvas(x->x_canvas, 1); +} + +/* -------------------- widget behavior for drawnumber ------------ */ + +/*#define DRAWNUMBER_BUFSIZE 80 +static void drawnumber_sprintf(t_drawnumber *x, char *buf, t_atom *ap) +{ + int nchars; + strncpy(buf, x->x_label->s_name, DRAWNUMBER_BUFSIZE); + buf[DRAWNUMBER_BUFSIZE - 1] = 0; + nchars = strlen(buf); + atom_string(ap, buf + nchars, DRAWNUMBER_BUFSIZE - nchars); +}*/ + +static int drawnumber_gettype(t_drawnumber *x, t_word *data, + t_template *template, int *onsetp) +{ + int type; + t_symbol *arraytype; + if (template_find_field(template, /*x->x_fieldname*/ x->x_value.fd_un.fd_varsym, onsetp, &type, + &arraytype) && type != DT_ARRAY) + return (type); + else return (-1); +} + +#define DRAWNUMBER_BUFSIZE 1024 +static void drawnumber_getbuf(t_drawnumber *x, t_word *data, + t_template *template, char *buf) +{ + int nchars, onset, type = drawnumber_gettype(x, data, template, &onset); + if (type < 0) + buf[0] = 0; + else { strncpy(buf, x->x_label->s_name, DRAWNUMBER_BUFSIZE); buf[DRAWNUMBER_BUFSIZE - 1] = 0; @@ -7331,9 +8034,8 @@ static void *drawimage_new(t_symbol *classsym, int argc, t_atom *argv) t_drawimage *x = (t_drawimage *)pd_new(drawimage_class); /* we need a t_svg to associate with it */ - x->x_attr = (t_pd *)svg_new((t_pd *)x, classsym, 0, 0); - - x->x_deleteme = 0; + t_svg *sa = (t_svg *)svg_new((t_pd *)x, classsym, 0, 0); + char *classname = classsym->s_name; char buf[50]; sprintf(buf, "x%lx", (t_int)x); @@ -7343,16 +8045,17 @@ static void *drawimage_new(t_symbol *classsym, int argc, t_atom *argv) if (classname[0] == 's') flags |= DRAW_SPRITE; x->x_flags = flags; + x->x_attr = (t_pd *)sa; fielddesc_setfloat_const(&x->x_vis, 1); x->x_canvas = canvas_getcurrent(); t_symbol *dir = canvas_getdir(x->x_canvas); if (argc && argv->a_type == A_SYMBOL) x->x_img = atom_getsymbolarg(0, argc--, argv++); else x->x_img = &s_; - if (argc) fielddesc_setfloatarg(&x->x_xloc, argc--, argv++); - else fielddesc_setfloat_const(&x->x_xloc, 0); - if (argc) fielddesc_setfloatarg(&x->x_yloc, argc--, argv++); - else fielddesc_setfloat_const(&x->x_yloc, 0); + if (argc) svg_attr_setfloatarg(&sa->x_x, argc--, argv++); + else svg_attr_setfloat_const(&sa->x_x, 0); + if (argc) svg_attr_setfloatarg(&sa->x_y, argc--, argv++); + else svg_attr_setfloat_const(&sa->x_y, 0); /* [drawimage] allocates memory for an image or image sequence while the object is creating. The corresponding scalar gets drawn as a canvas image item using the "parent" tk image as @@ -7364,7 +8067,6 @@ static void *drawimage_new(t_symbol *classsym, int argc, t_atom *argv) x->x_img->s_name, dir->s_name, x->x_flags); - //post("deleteme is %d", x->x_deleteme); return (x); } @@ -7412,31 +8114,31 @@ void drawimage_symbol(t_drawimage *x, t_symbol *s) drawimage_index(x, 0, 1, at); } -static void drawimage_x(t_drawimage *x, t_symbol *s, int argc, +static void drawimage_forward(t_drawimage *x, t_symbol *s, int argc, t_atom *argv) { - if (argv[0].a_type == A_FLOAT || argv[0].a_type == A_SYMBOL) - { - fielddesc_setfloatarg(&x->x_xloc, argc, argv); - canvas_redrawallfortemplatecanvas(x->x_canvas, 0); - } + /* forward to t_svg thingy */ + pd_typedmess(x->x_attr, s, argc, argv); } -static void drawimage_y(t_drawimage *x, t_symbol *s, int argc, +/* With the current drawimage/sprite implementation we can't easily support + the x and y attributes. The reason is that we're currently just applying + attributes to the parent <g> for convenience, but <g> has no x/y atty. + + We could just forward everything to the child <image> element, but that + could get clunky when dealing with large image sequences. So for now we + just disallow setting the x/y with the knowledge that the user can get + the same functionality using a transform. */ +static void drawimage_x(t_drawimage *x, t_symbol *s, int argc, t_atom *argv) { - if (argv[0].a_type == A_FLOAT || argv[0].a_type == A_SYMBOL) - { - fielddesc_setfloatarg(&x->x_yloc, argc, argv); - canvas_redrawallfortemplatecanvas(x->x_canvas, 0); - } + pd_error(x, "draw: x attribute for image type not supported"); } -static void drawimage_forward(t_drawimage *x, t_symbol *s, int argc, +static void drawimage_y(t_drawimage *x, t_symbol *s, int argc, t_atom *argv) { - /* forward to t_svg thingy */ - pd_typedmess(x->x_attr, s, argc, argv); + pd_error(x, "draw: y attribute for image type not supported"); } static void drawimage_anything(t_drawimage *x, t_symbol *s, int argc, @@ -7492,8 +8194,8 @@ static void drawimage_getrect(t_gobj *z, t_glist *glist, &m4, &m5, &m6); mset(mtx2, m1, m2, m3, m4, m5, m6); mmult(mtx1, mtx2, mtx1); - xloc = fielddesc_getcoord(&x->x_xloc, template, data, 0); - yloc = fielddesc_getcoord(&x->x_yloc, template, data, 0); + xloc = fielddesc_getcoord(&sa->x_x.a_attr, template, data, 0); + yloc = fielddesc_getcoord(&sa->x_y.a_attr, template, data, 0); mset(mtx2, xloc, yloc, xloc + x->x_w, yloc + x->x_h, 0, 0); mtx2[2][0] = 1; mtx2[2][1] = 1; @@ -7578,13 +8280,15 @@ static void drawimage_vis(t_gobj *z, t_glist *glist, t_glist *parentglist, { int in_array = (sc->sc_vec == data) ? 0: 1; /*int xloc = glist_xtopixels(glist, - basex + fielddesc_getcoord(&x->x_xloc, template, data, 0)); + basex + fielddesc_getcoord(&svg->x_x.a_attr, template, data, 0)); int yloc = glist_ytopixels(glist, - basey + fielddesc_getcoord(&x->x_yloc, template, data, 0)); + basey + fielddesc_getcoord(&svg->x_y.a_attr, template, data, 0)); sys_vgui("pdtk_drawimage_vis .x%lx.c %d %d .x%lx .x%lx.i %d ",*/ - int xloc = fielddesc_getcoord(&x->x_xloc, template, data, 0); - int yloc = fielddesc_getcoord(&x->x_yloc, template, data, 0); + t_float xloc = fielddesc_getcoord(&svg->x_x.a_attr, template, data, 0); + t_float yloc = fielddesc_getcoord(&svg->x_y.a_attr, template, data, 0); +fprintf(stderr, "xloc is %g\n", xloc); +fprintf(stderr, "yloc is %g\n", yloc); char tagbuf[MAXPDSTRING]; char parent_tagbuf[MAXPDSTRING]; sprintf(tagbuf, "draw%lx.%lx", @@ -7594,7 +8298,7 @@ static void drawimage_vis(t_gobj *z, t_glist *glist, t_glist *parentglist, in_array ? (long unsigned int)parentglist : (long unsigned int)parent, (long unsigned int)data); - gui_vmess("gui_drawimage_vis", "xiixxis", + gui_vmess("gui_drawimage_vis", "xffxxis", glist_getcanvas(glist), xloc, yloc, @@ -7846,24 +8550,19 @@ t_canvas *canvas_templatecanvas_forgroup(t_canvas *c) { t_canvas *templatecanvas = c; if (!c->gl_owner) - { - return templatecanvas; - } + return templatecanvas; /* warning: this needs to be carefully considered-- seems like canvas's struct may not be initialized before the objects within it. */ t_binbuf *b = c->gl_obj.te_binbuf; if (!b) - { return c; - } t_atom *argv = binbuf_getvec(b); if (binbuf_getnatom(b) > 1 && - argv[0].a_type == A_SYMBOL && - argv[0].a_w.w_symbol == gensym("draw") && - argv[1].a_type == A_SYMBOL && - argv[1].a_w.w_symbol == gensym("g")) + atom_getsymbol(argv) == gensym("draw") && + (atom_getsymbol(argv+1) == gensym("g") || + atom_getsymbol(argv+1) == gensym("svg"))) { templatecanvas = canvas_templatecanvas_forgroup(c->gl_owner); } @@ -7886,6 +8585,8 @@ t_template *template_findbydrawcommand(t_gobj *g) c = ((t_drawimage *)g)->x_canvas; else if (g->g_pd == plot_class) c = ((t_plot *)g)->x_canvas; + else if (g->g_pd == drawarray_class) + c = ((t_drawarray *)g)->x_canvas; else if (g->g_pd == canvas_class) c = (t_canvas *)g; else return (0); @@ -7963,5 +8664,6 @@ void g_template_setup(void) drawnumber_setup(); drawsymbol_setup(); drawimage_setup(); + drawarray_setup(); } diff --git a/pd/src/g_text.c b/pd/src/g_text.c index 074d5aed7..6b735f3ac 100644 --- a/pd/src/g_text.c +++ b/pd/src/g_text.c @@ -3018,6 +3018,10 @@ void text_setto(t_text *x, t_glist *glist, char *buf, int bufsize, int pos) (void *)canvas_undo_set_recreate(glist_getcanvas(glist), &x->te_g, pos)); typedmess(&x->te_pd, gensym("rename"), natom2-1, vec2+1); + // Special case for [draw svg] -- update the args + if (((t_canvas *)x)->gl_svg) + typedmess(((t_canvas *)x)->gl_svg, gensym("update_svg"), + natom2-1, vec2+1); binbuf_free(x->te_binbuf); x->te_binbuf = b; glob_preset_node_list_seek_hub(); -- GitLab