CanvasContext
[[DensKeelin] New in Analytica 5.0
CanvasContext( canvas, clip, clipMode, rotAngle, rotx, roty, shiftx, shifty, scalex, scaley )
Returns a drawing context with a new clip region or coordinate system. The result can be passed to the «canvas» parameter of any of the Canvas functions.
The clip or coordinate system of the original canvas or context is not changed, and you can continue to draw to the original canvas or coordinate system or to the new canvas.
Parameters
- «canvas» is a canvas obtained from calling the
Canvas()
function, or a canvas context obtained by calling theCanvasContext()
function. - «clip»: (Optional) When specified, four numbers must be provided: x, y, width, height. See #Clipping below.
- «clipMode»: (Optional) Specifies how the new «clip» should be combined with the previous clip. The possible values are
'Replace'
,'Intersect'
(default),'Union'
,'Exclude'
,'Complement'
, or'Xor'
. - «rotAngle», «rotx», «roty»: (Optional) Specifies the rotation. See #Rotations below.
- «shiftx», «shifty»: (Optional) Specifies a translation for the context's coordinate system relative to the original coordinate system. See #Shifting below.
- «scalex», «scaley»: (Optional) Specifies a scaling for the context's coordinate system -- how many of the original context's units correspond to one unit in the new coordinate system. See #Scaling below.
When multiple context changes are specified in one call, they are applied in this order: Rotation, translation, scaling then clipping. See #Order of context changes below.
Clipping
Clipping limits the area where stuff that you draw shows up. You specify a clipping rectangle using the «clip» parameter. To illustrate, let's first consider an example with several items drawn without any clipping.
Local canv := Canvas( 200, 100, 'Yellow' ); CanvasDrawRectangle( canv, 30, 15, 110, 70, fillColor:'lightgreen', lineColor:'Red' ); CanvasDrawLine(canv, 20, 80, 180, 20 ); CanvasDrawLine(canv,1,1,200,100); CanvasDrawEllipse(canv,10,50,50,60,fillColor:0x40FF33FF,sweepAngle:-90,pie:true,startAngle:-50,lineColor:'Black',lineWidth:0.5); CanvasDrawImage( canv, pict of Analytica_Logo ); CanvasImage(canv )
We'll leave the rectangle as is so we have a visual indication of where our clipping rectangle is, but the other items are now drawn to a new context with a clipping region with the same dimensions as the rectangle. Changes are highlighted.
Local canv := Canvas( 200, 100, 'Yellow' ); Local cxt := CanvasContext(canv, clip:[30,15,110,70]); CanvasDrawRectangle( canv, 30, 15, 110, 70, fillColor:'lightgreen', lineColor:'Red' ); CanvasDrawLine(cxt, 20, 80, 180, 20 ); CanvasDrawLine(cxt,1,1,200,100); CanvasDrawEllipse(cxt,10,50,50,60,fillColor:0x40FF33FF,sweepAngle:-90,pie:true,startAngle:-50,lineColor:'Black',lineWidth:0.5); CanvasDrawImage( cxt, pict of Analytica_Logo ); CanvasImage(canv )
When you extend an existing clip (i.e., when «canvas» is already a context), «clipMode» specifies how «clip» is combined with the previous clip. The shaded region in the following shows the resulting clip region for each clip mode.
The clip modes act as follows:
'Replace'
: Use «clip» as the new clip rect, regardless of the previous clip region.'Intersect'
: Use the area in both «clip» and in the previous clip.'Union'
: Use the area in either «clip» or «canvas»'s clip..'Exclude'
: Use the area in the previous clip that is outside of «clip».'Complement'
: Use the area in «clip» that is outside of the previous clip.'Xor'
: Use the area in «clip» or the previous clip, but not both.
Each of the example clip regions above was drawn using:
Local c := For i:=Clip_mode Do Canvas(200,200); CanvasDrawRectangle(c,10,10,150,150); CanvasDrawRectangle(c,40,40,150,150); CanvasDrawText(c,"Existing clip", 15,15); CanvasDrawText(c,"New clip", 185,185, hAlign:'Right', vAlign:'Bottom'); Local cxt1 := CanvasContext(c, clip:10,10,150,150); Local cxt2 := CanvasContext(cxt1, clip:40,40,150,150, clipMode:Clip_mode); CanvasDrawRectangle(cxt2,0,0,200,200,fillColor:0x60888811); CanvasImage(c)
with
- Index Clip_mode :=
['Replace','Intersect','Union','Exclude','Complement','Xor']
Rotating
To rotate the coordinate system, specify «rotAngle» in degrees, and optionally specify the point to rotation around using «rotx», «roty». A positive «rotAngle» will cause your new coordinate system to be rotated clockwise relative to the original coordinate system.
Local c := Canvas(200,100); Local cxt := CanvasContext( c, rot:10, rotx:100, roty:50 ); CanvasDrawEllipse( c, 25, 25, 150, 50, dash:'dot', lineColor:'Green' ); CanvasDrawEllipse( cxt, 25, 25, 150, 50, lineColor:'Blue' ); CanvasImage(c)
Shifting
«Shiftx» and «shifty» specifies a point in the original context where the origin of your new context's coordinate system will be located.
Local c := Canvas(200,100); Local cxt := CanvasContext( c, shiftx:20 ); CanvasDrawEllipse( c, 25, 25, 150, 50, dash:'dot', lineColor:'Green' ); CanvasDrawEllipse( cxt, 25, 25, 150, 50, lineColor:'Blue' ); CanvasImage(c)
Scaling
You can shrink or magnify your context's coordinate frame compared to the original context using the «scalex» and «scaley» parameters. «Scalex» specifies the number of units in the original context that become one unit in the next context.
Initially, the y-axis increases as you go from the top of the image to the bottom. You can specify a negative scaling for «scaley» to flip the y-axis; however, when you do so you should also specify «shifty» to be the height of image in the parent context to move the origin to the bottom at the same time.
Assume these variables exist.
In this example, after the scaling, the coordinates of the image extend from 0 to 1 in the y-axis, and from 0 to IndexLength(Time)
in the x-axis.
Local canv := Canvas(200,50); Local cxt := CanvasContext(canv, scaley:-50, shifty:50, scalex:200/IndexLength(Time) ); CanvasDrawLine( cxt, Time-1, data[Time=Time-1], Time, data ); CanvasImage(canv)
Order of context changes
TBD. To do: explain with examples how when multiple changes to the context are specified in a single call, rotation is applied first, then shifting, then then scaling, and lastly clipping.
Enable comment auto-refresher