Drawing examples

About
Here are some examples of drawing on CANVAS. More documentation on available methods is here.
Download
Contents
drawing.cxx
- // THE MAIN CODE IS IN KUIML FILE
drawing.kuiml
- <?xml version="1.0" encoding="utf-8" ?>
- <SKIN layout_type="column" h_margin="0" v_margin="0">
- <!--
- Some examples of drawing on CANVAS
- =========================
- Demo by Ilya Orlov (LetiMix.com) | St. Petersburg, Russia, 2019-20
- Original url: https://pns.letimix.com/scripts/gui/drawing
- =========================
- To make CANVAS updated (redrawn) on some event, you can use something like that:
- <ACTION_TRIGGER event_id="SOME_PARAM.value_changed" script="CANVAS_ID.Invalidate()" requires="CANVAS_ID.Invalidate" />
- (instead of SOME_PARAM use real param like `custom_param0`,
- instead of CANVAS_ID use real element_id, like 'canvas_2')
- -->
- <ROW spacing="10">
- <!-- how to do gradient -->
- <CANVAS opacity="1" id="canvas_2" width="100" height="100" render_script="
- double h=this.height, w=this.width;
- auto ctx=Kt::Graphics::GetCurrentContext();
- auto gradient = ctx.patterns.NewLinearGradient(0,0,0,h);
- gradient.AddColorStopRGB(0, 1, 0, 0);
- gradient.AddColorStopRGB(0.3, 1, 0.7, 0);
- gradient.AddColorStopRGB(0.7, 0, 0.8, 0);
- gradient.SelectAsSource();
- ctx.path.Clear();
- ctx.path.Rectangle(0,0,w,h);
- ctx.FillPath();
- " requires="canvas_2.*" />
- <!-- how to draw circle -->
- <CANVAS opacity="1" id="canvas_3" requires="canvas_3.*" width="100" height="100" render_script="
- double h=this.height, w=this.width;
- auto ctx=Kt::Graphics::GetCurrentContext();
- /* draw a simple circle using arc */
- ctx.path.Clear();
- ctx.source.SetRGBA (1,0,0, 0.8);
- ctx.path.Arc(w/2, h/2, w/2, 0.01, 0); /* cx, cy, radius, angle_start, angle_end */
- ctx.FillPath();
- /* let's add a 'flare' to our circle */
- float xc = w/2-18, yc = h/2-18, radius_start = 5, radius_end = 25;
- float r=1, g=0.8, b=0.8, start_alpha=1, end_alpha=0;
- auto sh_gradient = ctx.patterns.NewRadialGradient(xc,yc,radius_start,xc-1,yc-1,radius_end);
- sh_gradient.AddColorStopRGBA(0, r, g, b, start_alpha);
- sh_gradient.AddColorStopRGBA(1, r, g, b, end_alpha);
- sh_gradient.SelectAsSource();
- ctx.path.Clear();
- ctx.path.Arc(xc, yc, radius_end, 0.001, 0);
- ctx.FillPath();
- " />
- <!-- how to use path masking -->
- <CANVAS opacity="1" id="canvas_4" width="80" height="100" render_script="
- double h=this.height, w=this.width;
- auto ctx=Kt::Graphics::GetCurrentContext();
- ctx.path.Clear();
- ctx.source.SetRGBA (0.5,0.5,1, 0.9);
- ctx.path.MoveTo(10,10);
- ctx.path.LineTo(80,50);
- ctx.settings.set_lineWidth(2);
- ctx.path.LineTo(20,90);
- ctx.path.Close();
- ctx.StrokePath();
- ctx.ClipWithPath(); /* this limits future drawing to this path bounds */
- ctx.path.Clear();
- ctx.source.SetRGBA (1,0.2,0.2, 0.7);
- ctx.path.Arc(20, 20, 20, 0.1, 0); /* cx, cy, radius, angle_start, angle_end */
- ctx.FillPath();
- " requires="canvas_4.*" />
- <!-- how to draw text-->
- <CANVAS opacity="1" id="canvas_5" requires="canvas_5.*" width="135" height="100" render_script="
- double h=this.height, w=this.width;
- auto ctx=Kt::Graphics::GetCurrentContext();
- /* demos of context modifiers */
- ctx.transform.Translate(10,5); /* shift viewpoint */
- ctx.transform.Scale(0.9,1); /* scale in x,y */
- ctx.transform.Rotate(-5); /* rotate context */
- /* `glowing` text */
- ctx.font.SetFontSize(40);
- ctx.font.SelectFontFace("Courier New", Kt::Graphics::kFontSlantNormal, Kt::Graphics::kFontWeightBold);
- ctx.path.Clear();
- ctx.path.MoveTo(5,40);
- ctx.path.Text("Hello");
- /* create backing `glow` */
- float r=0.2, g=.7, b=0.2;
- for (int n=1;n<9;n++){
- float alpha = n/70.0;
- float lw = 18-n*2;
- ctx.source.SetRGBA (r,g,b, alpha);
- ctx.settings.set_lineWidth(lw);
- ctx.StrokePath();
- }
- /* stroke and fill the `normal` text */
- ctx.source.SetRGBA (r,g,b, 1);
- ctx.FillPath();
- ctx.source.SetRGBA (1,1,1, 0.15);
- ctx.settings.set_lineWidth(1);
- ctx.StrokePath();
- ctx.transform.Rotate(5); /* rotate context back */
- /* easy way to write text (but no so beautiful) */
- ctx.source.SetRGBA (0.5,0.5,1, 0.9);
- ctx.font.SelectFontFace("Verdana");
- ctx.path.MoveTo(0,80);
- ctx.WriteText("THERE");
- " />
- </ROW>
- <CELL height="10" />
- <ROW spacing="10">
- <!-- how to make "blurred" elements -->
- <CANVAS opacity="1" id="canvas_6" requires="canvas_6.*" width="100" height="100" render_script="
- double h=this.height, w=this.width;
- auto ctx=Kt::Graphics::GetCurrentContext();
- ctx.source.SetRGBA (0.5,0.5,0.5, 0.3);
- ctx.path.Rectangle(0,0,w,h);
- ctx.settings.set_lineWidth(1);
- ctx.StrokePath();
- float r=0.1, g=0.5, b=0.1, last_alpha=0.27;
- /* drawing blurred rectangle */
- float xc=50, yc=20, w0=60, h0=20, max_steps = 9, step_px = 2;
- for (int n=1;n<=max_steps;n++){
- float this_alpha = last_alpha*pow(n/max_steps, 1.5);
- float this_w = max_steps*step_px+w0-n*step_px;
- float this_h = max_steps*step_px+h0-n*step_px;
- ctx.path.Clear();
- ctx.path.Rectangle(xc-this_w/2, yc-this_h/2, this_w, this_h);
- ctx.source.SetRGBA (r,g,b, this_alpha);
- ctx.FillPath();
- }
- /* drawing blurred circle */
- r=0.5; g=0.1; b=0.1;
- xc=25; yc=60; max_steps = 9; step_px = 1;
- float radius=15; last_alpha=0.2;
- for (int n=1;n<=max_steps;n++){
- float this_alpha = last_alpha*pow(n/max_steps, 1.5);
- float r_this = max_steps*step_px+radius-n*step_px;
- ctx.path.Clear();
- ctx.path.Arc(xc, yc, r_this, 0.1, 0);
- ctx.source.SetRGBA (r,g,b, this_alpha);
- ctx.FillPath();
- }
- /* gradient way of drawing blurred circle */
- {
- r=0.1; g=0.1; b=0.5;
- xc=75; yc=60;
- float radius_start=15, radius_end=20, start_alpha=0.6, end_alpha=0;
- auto sh_gradient = ctx.patterns.NewRadialGradient(xc,yc,radius_start,xc,yc,radius_end);
- sh_gradient.AddColorStopRGBA(0, r, g, b, start_alpha);
- sh_gradient.AddColorStopRGBA(1, r, g, b, end_alpha);
- sh_gradient.SelectAsSource();
- ctx.path.Clear();
- ctx.path.Arc(xc, yc, radius_end, 0.001, 0);
- ctx.FillPath();
- }
- " />
- <!-- add second gradient on top of first -->
- <CANVAS opacity="1" id="canvas_7" requires="canvas_7.*" width="100" height="100" render_script="
- double h=this.height, w=this.width;
- auto ctx=Kt::Graphics::GetCurrentContext();
- ctx.source.SetRGBA (0.5,0.5,0.5, 0.3);
- ctx.path.Rectangle(0,0,w,h);
- ctx.settings.set_lineWidth(1);
- ctx.StrokePath();
- ctx.path.Rectangle(0, 0, w, h);
- /* draw main gradient up-down */
- float r=0.1, g=0.1, b=0.5, aa = 1;
- auto grad = ctx.patterns.NewLinearGradient(0,0,0,h);
- grad.AddColorStopRGBA(0.0, r, g, b, 0.2*aa);
- grad.AddColorStopRGBA(1, r, g, b, 0.8*aa);
- grad.SelectAsSource();
- ctx.FillPath();
- /* draw secondary 'mask' gradient */
- ctx.settings.set_blendMode(Kt::Graphics::kDrawOpXor);
- auto grad2 = ctx.patterns.NewLinearGradient(0,0,w,h);
- grad2.AddColorStopRGBA(0.3, 1, 1, 1, 0);
- grad2.AddColorStopRGBA(1, 1, 1, 1, 0.2);
- grad2.SelectAsSource();
- ctx.FillPath();
- " />
- <!-- masking 2 -->
- <CANVAS opacity="1" id="canvas_8" requires="canvas_8.*" width="100" height="100" render_script="
- double h=this.height, w=this.width;
- auto ctx=Kt::Graphics::GetCurrentContext();
- ctx.source.SetRGBA (0.5,0.5,0.5, 0.5);
- ctx.settings.set_lineWidth(1);
- ctx.path.Clear();
- ctx.path.Arc(30,30,15,0.001,0);
- ctx.path.Close();
- ctx.path.Arc(60,60,15,0.001,0);
- ctx.path.Close();
- ctx.transform.Translate(w/2,h/2); /* shift viewpoint */
- ctx.transform.Scale(0.5,0.5); /* scale in x,y */
- ctx.transform.Rotate(45); /* rotate context */
- ctx.path.Rectangle(-40,-8,80,16);
- ctx.path.Close();
- ctx.ClipWithPath();
- ctx.transform.Scale(2,2); /* scale in x,y */
- ctx.transform.Rotate(-45); /* rotate context */
- ctx.transform.Translate(-w/2,-h/2); /* shift viewpoint */
- auto grad = ctx.patterns.NewLinearGradient(0,0,w,h);
- grad.AddColorStopRGBA(0.0, 0.5,0.1,0.5, 1);
- grad.AddColorStopRGBA(1, 0.5,0.1,0.5, 0.2);
- grad.SelectAsSource();
- ctx.path.Rectangle(0, 0, w, h);
- ctx.FillPath();
- " />
- </ROW>
- </SKIN>