PLUG'N SCRIPT
rapid plugin development
Tutorial
DSP
KUIML
How-to
Scripts
GUI
  • Drawing
  • Simple knobs
Library
  • Params
Rave Generation
  • Preamp
ScriptsGUIDrawing
November 04, 2025   Ilya Orlov

Drawing examples

About

Here are some examples of drawing on CANVAS.

Download

drawing.cxx  ·  drawing.kuiml

Contents

drawing.cxx

  1. // THE MAIN CODE IS IN KUIML FILE
  2. string name="CANVAS Examples";

drawing.kuiml

  1. <?xml version="1.0" encoding="utf-8" ?>
  2. <SKIN layout_type="column" h_margin="0" v_margin="0">

  3. <!--
  4. Some examples of drawing on CANVAS
  5. =========================
  6. Demo by Ilya Orlov (LetiMix.com) | St. Petersburg, Russia, 2019-20
  7. Original url: https://pns.letimix.com/scripts/gui/drawing
  8. =========================
  9. To make CANVAS updated (redrawn) on some event, you can use something like that:
  10. <ACTION_TRIGGER event_id="SOME_PARAM.value_changed" script="CANVAS_ID.Invalidate()" requires="CANVAS_ID.Invalidate" />
  11. (instead of SOME_PARAM use real param like `custom_param0`,
  12. instead of CANVAS_ID use real element_id, like 'canvas_2')
  13. -->

  14. <ROW spacing="10">
  15. <!-- how to do gradient -->
  16. <CANVAS opacity="1" id="canvas_2" width="100" height="100" render_script=" 
  17. double h=this.height, w=this.width;
  18. auto ctx=Kt::Graphics::GetCurrentContext();
  19. auto gradient = ctx.patterns.NewLinearGradient(0,0,0,h);
  20. gradient.AddColorStopRGB(0, 1, 0, 0);
  21. gradient.AddColorStopRGB(0.3, 1, 0.7, 0);
  22. gradient.AddColorStopRGB(0.7, 0, 0.8, 0);
  23. gradient.SelectAsSource();
  24. ctx.path.Clear();
  25. ctx.path.Rectangle(0,0,w,h);
  26. ctx.FillPath();
  27.  " requires="canvas_2.*" />

  28. <!-- how to draw circle -->
  29. <CANVAS opacity="1" id="canvas_3" requires="canvas_3.*" width="100" height="100" render_script=" 
  30. double h=this.height, w=this.width;
  31. auto ctx=Kt::Graphics::GetCurrentContext();

  32. /* draw a simple circle using arc */
  33. ctx.path.Clear();
  34. ctx.source.SetRGBA (1,0,0, 0.8);
  35. ctx.path.Arc(w/2, h/2, w/2, 0.01, 0); /* cx, cy, radius, angle_start, angle_end */
  36. ctx.FillPath();

  37. /* let's add a 'flare' to our circle */
  38. float xc = w/2-18, yc = h/2-18, radius_start = 5, radius_end = 25;
  39. float r=1, g=0.8, b=0.8, start_alpha=1, end_alpha=0;
  40. auto sh_gradient = ctx.patterns.NewRadialGradient(xc,yc,radius_start,xc-1,yc-1,radius_end);
  41. sh_gradient.AddColorStopRGBA(0, r, g, b, start_alpha);
  42. sh_gradient.AddColorStopRGBA(1, r, g, b, end_alpha);
  43. sh_gradient.SelectAsSource();
  44. ctx.path.Clear();
  45. ctx.path.Arc(xc, yc, radius_end, 0.001, 0);
  46. ctx.FillPath();
  47.  " />

  48. <!-- how to use path masking -->
  49. <CANVAS opacity="1" id="canvas_4" width="80" height="100" render_script=" 
  50. double h=this.height, w=this.width;
  51. auto ctx=Kt::Graphics::GetCurrentContext();

  52. ctx.path.Clear();
  53. ctx.source.SetRGBA (0.5,0.5,1, 0.9);
  54. ctx.path.MoveTo(10,10);
  55. ctx.path.LineTo(80,50);
  56. ctx.settings.set_lineWidth(2);
  57. ctx.path.LineTo(20,90);
  58. ctx.path.Close();
  59. ctx.StrokePath();
  60. ctx.ClipWithPath(); /* this limits future drawing to this path bounds */

  61. ctx.path.Clear();
  62. ctx.source.SetRGBA (1,0.2,0.2, 0.7);
  63. ctx.path.Arc(20, 20, 20, 0.1, 0); /* cx, cy, radius, angle_start, angle_end */
  64. ctx.FillPath();

  65.  " requires="canvas_4.*" />

  66. <!-- how to draw text-->
  67. <CANVAS opacity="1" id="canvas_5" requires="canvas_5.*" width="135" height="100" render_script=" 
  68. double h=this.height, w=this.width;
  69. auto ctx=Kt::Graphics::GetCurrentContext();

  70. /* demos of context modifiers */
  71. ctx.transform.Translate(10,5); /* shift viewpoint */
  72. ctx.transform.Scale(0.9,1); /* scale in x,y */
  73. ctx.transform.Rotate(-5); /* rotate context */

  74. /* `glowing` text */

  75. ctx.font.SetFontSize(40);
  76. ctx.font.SelectFontFace(&quot;Courier New&quot;, Kt::Graphics::kFontSlantNormal, Kt::Graphics::kFontWeightBold);
  77. ctx.path.Clear();
  78. ctx.path.MoveTo(5,40);
  79. ctx.path.Text(&quot;Hello&quot;);

  80. /* create backing `glow` */
  81. float r=0.2, g=.7, b=0.2;
  82. for (int n=1;n&lt;9;n++){
  83. float alpha = n/70.0;
  84. float lw = 18-n*2;
  85. ctx.source.SetRGBA (r,g,b, alpha);
  86. ctx.settings.set_lineWidth(lw);
  87. ctx.StrokePath();
  88. }

  89. /* stroke and fill the `normal` text */
  90. ctx.source.SetRGBA (r,g,b, 1);
  91. ctx.FillPath();
  92. ctx.source.SetRGBA (1,1,1, 0.15);
  93. ctx.settings.set_lineWidth(1);
  94. ctx.StrokePath();

  95. ctx.transform.Rotate(5); /* rotate context back */

  96. /* easy way to write text (but no so beautiful) */
  97. ctx.source.SetRGBA (0.5,0.5,1, 0.9);
  98. ctx.font.SelectFontFace(&quot;Verdana&quot;);
  99. ctx.path.MoveTo(0,80);
  100. ctx.WriteText(&quot;THERE&quot;);

  101.  " />

  102. </ROW>

  103. <CELL height="10" />

  104. <ROW spacing="10">
  105. <!-- how to make "blurred" elements -->
  106. <CANVAS opacity="1" id="canvas_6" requires="canvas_6.*" width="100" height="100" render_script=" 
  107. double h=this.height, w=this.width;
  108. auto ctx=Kt::Graphics::GetCurrentContext();
  109. ctx.source.SetRGBA (0.5,0.5,0.5, 0.3);
  110. ctx.path.Rectangle(0,0,w,h);
  111. ctx.settings.set_lineWidth(1);
  112. ctx.StrokePath();

  113. float r=0.1, g=0.5, b=0.1, last_alpha=0.27;

  114. /* drawing blurred rectangle */
  115. float xc=50, yc=20, w0=60, h0=20, max_steps = 9, step_px = 2;
  116. for (int n=1;n&lt;=max_steps;n++){
  117. float this_alpha = last_alpha*pow(n/max_steps, 1.5);
  118. float this_w = max_steps*step_px+w0-n*step_px;
  119. float this_h = max_steps*step_px+h0-n*step_px;
  120. ctx.path.Clear();
  121. ctx.path.Rectangle(xc-this_w/2, yc-this_h/2, this_w, this_h);
  122. ctx.source.SetRGBA (r,g,b, this_alpha);
  123. ctx.FillPath();
  124. }

  125. /* drawing blurred circle */
  126. r=0.5; g=0.1; b=0.1;
  127. xc=25; yc=60; max_steps = 9; step_px = 1;
  128. float radius=15; last_alpha=0.2;
  129. for (int n=1;n&lt;=max_steps;n++){
  130. float this_alpha = last_alpha*pow(n/max_steps, 1.5);
  131. float r_this = max_steps*step_px+radius-n*step_px;
  132. ctx.path.Clear();
  133. ctx.path.Arc(xc, yc, r_this, 0.1, 0);
  134. ctx.source.SetRGBA (r,g,b, this_alpha);
  135. ctx.FillPath();
  136. }

  137. /* gradient way of drawing blurred circle */
  138. {
  139. r=0.1; g=0.1; b=0.5;
  140. xc=75; yc=60;
  141. float radius_start=15, radius_end=20, start_alpha=0.6, end_alpha=0;
  142. auto sh_gradient = ctx.patterns.NewRadialGradient(xc,yc,radius_start,xc,yc,radius_end);
  143. sh_gradient.AddColorStopRGBA(0, r, g, b, start_alpha);
  144. sh_gradient.AddColorStopRGBA(1, r, g, b, end_alpha);
  145. sh_gradient.SelectAsSource();
  146. ctx.path.Clear();
  147. ctx.path.Arc(xc, yc, radius_end, 0.001, 0);
  148. ctx.FillPath();
  149. }

  150.  " />

  151. <!-- add second gradient on top of first -->
  152. <CANVAS opacity="1" id="canvas_7" requires="canvas_7.*" width="100" height="100" render_script=" 
  153. double h=this.height, w=this.width;
  154. auto ctx=Kt::Graphics::GetCurrentContext();
  155. ctx.source.SetRGBA (0.5,0.5,0.5, 0.3);
  156. ctx.path.Rectangle(0,0,w,h);
  157. ctx.settings.set_lineWidth(1);
  158. ctx.StrokePath();

  159. ctx.path.Rectangle(0, 0, w, h);

  160. /* draw main gradient up-down */
  161. float r=0.1, g=0.1, b=0.5, aa = 1;
  162. auto grad = ctx.patterns.NewLinearGradient(0,0,0,h);
  163. grad.AddColorStopRGBA(0.0, r, g, b, 0.2*aa);
  164. grad.AddColorStopRGBA(1, r, g, b, 0.8*aa);
  165. grad.SelectAsSource();
  166. ctx.FillPath();

  167. /* draw secondary 'mask' gradient */
  168. ctx.settings.set_blendMode(Kt::Graphics::kDrawOpXor);
  169. auto grad2 = ctx.patterns.NewLinearGradient(0,0,w,h);
  170. grad2.AddColorStopRGBA(0.3, 1, 1, 1, 0);
  171. grad2.AddColorStopRGBA(1, 1, 1, 1, 0.2);
  172. grad2.SelectAsSource();
  173. ctx.FillPath();
  174.  " />

  175. <!-- masking 2 -->
  176. <CANVAS opacity="1" id="canvas_8" requires="canvas_8.*" width="100" height="100" render_script=" 
  177. double h=this.height, w=this.width;
  178. auto ctx=Kt::Graphics::GetCurrentContext();
  179. ctx.source.SetRGBA (0.5,0.5,0.5, 0.5);
  180. ctx.settings.set_lineWidth(1);
  181. ctx.path.Clear();
  182. ctx.path.Arc(30,30,15,0.001,0);
  183. ctx.path.Close();

  184. ctx.path.Arc(60,60,15,0.001,0);
  185. ctx.path.Close();

  186. ctx.transform.Translate(w/2,h/2); /* shift viewpoint */
  187. ctx.transform.Scale(0.5,0.5); /* scale in x,y */
  188. ctx.transform.Rotate(45); /* rotate context */

  189. ctx.path.Rectangle(-40,-8,80,16);
  190. ctx.path.Close();
  191. ctx.ClipWithPath();

  192. ctx.transform.Scale(2,2); /* scale in x,y */
  193. ctx.transform.Rotate(-45); /* rotate context */
  194. ctx.transform.Translate(-w/2,-h/2); /* shift viewpoint */

  195. auto grad = ctx.patterns.NewLinearGradient(0,0,w,h);
  196. grad.AddColorStopRGBA(0.0, 0.5,0.1,0.5, 1);
  197. grad.AddColorStopRGBA(1, 0.5,0.1,0.5, 0.2);
  198. grad.SelectAsSource();

  199. ctx.path.Rectangle(0, 0, w, h);

  200. ctx.FillPath();
  201.  " />

  202. </ROW>
  203. </SKIN>

Comments

Please, authorize to view and post comments.

2020 - 2026 © Site by LetiMix · Donate  |  Plug'n Script and KUIML by Blue Cat Audio