a canvas implementation for DesktopX
Published on August 26, 2008 By Littleboy In DesktopX

Update:

This small update brings a proper shadow implementation with blurring, two new functions (textPath and textAlongPath) and a few bug fixes. textAlongPath is still somewhat buggy with multi-segment paths but otherwise works great (see the TextWave demo). I fixed a few problems with arcTo that wasn’t working as specified and made a few changes here and there. More importantly, I fixed a nasty crash bug that was sometimes happening on exit.

There is also two new utility functions available from script allowing you to suspend the canvas drawing updates. This allows you to do all the drawing necessary for a frame of animation and refresh the canvas at the end, instead of having it refresh at 30fps while your script is doing all the drawing operations.

With this new API, it was possible to fix all the flickering in the included examples! I’ve also added a few new example scripts. Check out the Polygon example, as well as all the text-related ones.

Download


 

Every major browser has support for it, Yahoo! Widgets has support for it, how come there isn't something for DesktopX?

Enter DXCanvas, a DesktopX drawing plugin that implements the Canvas spec (plus some DesktopX-specific additions).

How does it work

Canvas Controller

DXCanvas is a DesktopX drawing plugin, which means it takes over drawing for the object it is associated to.

In the configuration, you can set the initial size for the canvas. By default, the drawing surface size will be 300x150. You can also specify whether you want the surface to be transparent and show the other objects or windows under it, or opaque.

A canvas object is made available to scripting. To be able to draw on the canvas, you need to request a context. This is done by calling getContext(type) on the canvas object. The only supported type right now is "2d".

See the list of functions in the implementation section. Note that some are slightly different from the Canvas specification, or are completely new. This is to adjust to differences in what is possible in a browser and in DesktopX.

Canvas Controller Widget

I've made a little widget to make testing easier. It loads a list of scripts from a user-defined folder and allows you to switch between them. It support scripts written in both JScript and VBScript.

It basically associate the script to an object having the DXCanvas plugin as a capability.

Two functions are required for the scripts to work: Object_OnScriptEnter() and Object_OnScriptExit().

The canvas size is reset its default size of 300x150 when switching between scripts, so make sure to set it to the required size if needed by your script.

To add a new script to the list, create a new .js or .vbs file in a folder and select this folder in the widget preferences. A few test scripts are included in the Script folder.

It also support subfolders (only 1 folder deep), so you can organize your scripts in subfolders.

How to help

Download the Canvas Controller widget and start creating scripts!

What to look for

  • strange behavior: colors are not right, context is not saved or restored correctly, etc.
  • the output from a script is different in Firefox or Safari
  • crashes or memory leaks

What is broken/not working properly

  • Drawing still flicker (not as badly as before)
  • This is a DEBUG build, so it's going to be slower than normal

Links

Changelog

1.1 Build 287:

  • Added manual drawing mode with suspendDrawing/resumeDrawing methods
    (this should allow users to work around the flickering)
  • Fixed text position being off baseline when drawing on a path
  • Fixed a rare crash when drawing text on a path
  • Activated Pixman MMX&SSE2 fast paths
  • Updated Pango to fix font leak (rev 2746)
  • Updated Pixman (0.13.2)

1.1 Build 269:

  • Added textPath, textAlongPath (with stroke or fill option)
  • Added support for shadows
  • arcTo is incorrect when the three points are collinear
  • arcTo should draw a straight line from P0 to P1
  • restore() with an empty stack has no effect
  • Corrected order of data returned by getImageData (BRGA -> RGBA)
  • ImageData is now converted to non-premultiplied color
  • Preserve the current path when clipping
  • rgba colors were not converted to string properly (green had the wrong value)
  • Some composite operations are now handled correctly
  • Fixed Debug build crashing when expired
  • Fixed stack overflow crash on exit
  • Added check for font validity on assignment and fallback to default font (will raise an error in debug mode if font is incorrect)
  • Moved state management to its own class
  • Updated Cairo(1.8.4), Pixman(0.12.0), Pango(1.22.3), Glib(2.18.3) and libpng(1.2.33)

1.0 Build 225:

  • Fixed large canvas objects taking a lot of CPU
  • Log is always enabled

1.0 Build 217

  • Fixed drawing being incomplete in some cases
  • Added workaround for pink color drawing transparent. DesktopX always use pink to draw transparent surfaces, even in per-pixel mode. rgb(255, 0, 255) will be changed to rgb(255, 1, 255)

1.0 Build 214

  • Added per-object log files
  • Added more log info when creating a new context object

1.0 Build 211

  • Added support for % in rgb/rgba colors
  • Added "transparent" color (equivalent to "rgba(0,0,0,0)")
  • Added SVG colors "darkgrey", "darkslategrey", "dimgrey", "grey", "lightgray", "lightslategrey" and "slategrey"
  • Zero size canvas is allowed
  • Properly share canvas state (context style stack was not properly shared before)
  • DrawImage and DrawImageRegion check for negative width and height and adjust the coordinates
  • Only match full color strings
  • Accept rgb values outside [0;255] and clamp the value properly
  • Clamp alpha and use premultiplied color values when painting with alpha (still somewhat wrong)
  • Fixed leak and crash with CanvasImageData & CanvasPixelArray
  • Fixed crash with invalid parameters in createImageData and getImageData
  • Zero-length line gradients should paint nothing
  • Radial gradients with the same start and end circle should paint nothing
  • Image data now accepts negative width and height (you get the untransformed data for the resulting rectangle)
  • arc() with zero radius draws a line to the start point.
  • arcTo() has no effect if the context has no subpaths or if P0 = P1
  • arcTo() draws a straight line to P1 if P1 = P2 or if radius = 0
  • bezierCurveTo() has no effect if the context has no subpaths
  • lineTo() has no effect if the context has no subpaths
  • quadraticCurveTo() has no effect if the context has no subpaths
  • Updated cairo, pixman and pango libraries

1.0 Build 201

  • Added hsl/hsla color parsing
  • Added some logging (DXCanvas.log in object directory)
  • Fixed text stroking always drawing at position (0,0)
  • Fixed text baseline being off by the text height

1.0 Build 191

  • Added redraw calls buffering (less flickering)
  • Added debugMode attribute to canvas. In debug mode, passing invalid parameters will result in an error being raised instead of the invalid value being silently ignored.
  • No longer returns errors when passing invalid parameters to a lot of functions (as specified in Canvas specification)
  • CanvasPixelArray.XXX6(index, value) now takes an int instead of a char and will clamp that value to [0;255]

1.0 Build 180

  • Implemented toImage
  • Implemented createImageData, getImageData and putImageData
  • Added canvas support to createPattern, drawImage and drawImageRegion
  • Fixed createPattern, drawImage and drawImageRegion not working in VBScript
  • Fixed createPattern, drawImage and drawImageRegion not making a copy of the source image or canvas
  • Fixed drawImageRegion using wrong default values for dw and dh
  • Fixed drawImageRegion not creating a new path, resulting in image "corruption"

1.0 Build 168

  • Implemented font attribute setter/getter
  • Implemented fillText, strokeText and measureText (using Pango)
  • Implemented arcTo (using patch from Behdad Esfahbod)
  • Fixed image loading (SD_LOAD_IMAGE seems to be corrupting some images...)

1.0 Build 159

  • Implemented textAlign and textBaseline attributes setters/getters  (not used yet)
  • Implemented createPattern, loadImage, drawImage and drawImageRegion
  • Update to cairo 1.7.4 (better support for text)
  • Statically linked to cairo lib (no need for cairo.dll anymore)

1.0 Build 149

  •  First test version

Download

You can download a test version here. It only includes the Canvas Controller widget for now. Please do not use the DXCanvas plugin in your own objects and widgets yet. This version of the plugin will expire on the 10/01/2008.

Implementation

Under the hood, it's using Cairo, a 2D vector graphics library that also powers the Mozilla and Yahoo Widgets implementations. Right now, the Cairo library is dynamically loaded at runtime, but I hope to have it statically linked into the plugin for the final version.

Here is a list classes with their attributes and functions and the state of their implementation

Canvas

NameImplementedComment
width YES  
height YES  
debugMode YES Invalid input will raise an error instead of being ignored.
getContext(type) YES  
toImage(path) YES Saves to a PNG file (replaces toDataURL)
suspendDrawing() YES  
resumeDrawing() YES  

 

CanvasRenderingContext2D

NameImplementedComment
globalAlpha YES  
globalCompositeOperation YES  
strokeStyle YES  
fillStyle YES  
lineWidth YES  
lineCap YES  
lineJoin YES  
miterLimit YES  
shadowOffsetX YES Shadows are not implemented yet.
shadowOffsetY YES Shadows are not implemented yet.
shadowBlur YES Shadows are not implemented yet.
shadowColor YES Shadows are not implemented yet.
font YES  
textAlign YES  
textBaseLine YES Hanging and ideographic baselines are treated as alphabetic.
canvas YES  
save YES  
restore YES  
scale(x, y) YES  
rotate(angle) YES  
translate(x, y) YES  
transform(m11, m12, m21, m22, dx, dy) YES  
setTransform(m11, m12, m21, m22, dx, dy) YES  
createLinearGradient(x0, y0, x1, y1) YES  
createRadialGradient(x0, y0, r0, x1, y1, r1) YES  
createPattern(input, repeat) YES  
clearRect(x, y, w, h) YES  
fillRect(x, y, w, h) YES  
strokeRect(x, y, w, h) YES  
beginPath YES  
closePath YES  
moveTo(x, y) YES  
lineTo(x, y) YES  
quadraticCurveTo(cpx, cpy, x, y) YES  
bezierCurveTo(cp1x, cp1y, cp2x, cp2y, x, y) YES  
arcTo(x1, y1, x2, y2, radius) YES  
rect(x, y, width, height) YES  
arc(x, y, radius, startAngle, endAngle, anticlockwise) YES  
fill() YES  
stroke() YES  
clip() YES  
isPointInPath(x, y) YES  
fillText(text, x, y) YES  
strokeText(text, x, y) YES  
measureText(text) YES  
textAlongPath(text, stroke) YES Adds (or draws) the specified text along the current path
pathText(text) YES Adds the strokes from the specified text to the current path
loadImage(path) YES  
drawImage(input, dx, dy, dw, dh) YES  
drawImageRegion(input, sx, sy, sw, sh, dx, dy, dz, dh) YES  
createImageData(sw, sh) YES  
getImageData(sx, sy, sw, sh) YES  image data uses the BGRA format
putImageData(imageData, dx, dy, dirtyX, dirtyY, dirtyWidth, dirtyHeight) YES  

 

Gradient

NameImplementedComment
addColorStop(offset, color) YES  

 

ImageData

NameImplementedComment
width YES  
height YES  
data YES  

 

PixelArray

NameImplementedComment
length YES  
XXX5(index) YES  
XXX6(index, value) YES  

 

TextMetrics

NameImplementedComment
width YES  

 


Comments (Page 5)
6 PagesFirst 3 4 5 6 
on Sep 17, 2008

Hopefully last build before releasing it on Wincustomize. It should feel a little bit faster

on Sep 17, 2008

Had a crash with both Build 214 & 217 but, not when I built a gadget from your widget.

Was copying over top of previous build's. So when I deleted the old version folder & the gadget cache folder (each time) then build's 211,214 and 217 all ran perfectly.

on Sep 17, 2008

Good to hear! I'm waiting for CaptainBeaker to test it on his Vista computer before uploading it on WC.

Build 217 is a release build and won't expire, so if you're confident it will work, you can start building and distributing things based on it.

on Sep 18, 2008

Littleboy,

Unfortunately I still get the Null error on this line:

Set ctx = canvas.getContext("2d")

The DXCanvas log is empty.  I did hovever notice this.  I went into the plugin configuration and unchecked 'use per-pixel alpha blending and I get a black box (in the dimensions I set in the plugin) instead of the context.  After I get the Null error and select 'Disable and Edit' or 'Continue' the black box remains.  If I select per-pixel alpha blending and try to run the script again, the black context box does not show up.

?????......

on Sep 18, 2008

My bad, the log was disabled in release mode. I've uploaded a new build. Can you try it and see what appears in the log?

If that doesn't work, can you try another scripting plugin and see if it works? There is DXVolumeControl or the scriptable email plugin included with DesktopX. If none of those two work, then it's probably a problem on your side or DesktopX acting strange...

Do you run any antispyware or anything that could cause scripts to be blocked?

The behavior with the black box seems to be normal. Since you cannot use the context and paint anything on it, it appears as fully transparent black in per-pixel mode and opaque black otherwise.

on Sep 18, 2008

You might want to lock down a layer. Specifically the list box. At the moment I'm looking at the list box control and the rest of the gadget has gone AWOL.

on Sep 18, 2008

Yeah, it seems to be a bug with DesktopX. The listbox will move no matter what. The only way to prevent it from moving is to lock movement on the main object, which AFAIK is not possible from script. I tried locking the object, adding a new layer and locking that layer in addition to the object, but with no luck. If I add OnMove, OnDrag, OnLButtonUp callbacks, I get called alright when dragging the object, but then if I call Object.Move it doesn't do anything. DesktopX seems to think the listbox is still at the previous coordinates (shows them in objects list and object properties), even though the listbox clearly moved.

I'm probably going to have to remove the lock option

on Sep 18, 2008

Littleboy,

I tried your Vistavolume control and get the same (null) error that I do with the Canvas plugin.  I think there must be something going on with my Vista systems.  I'm using Avast! AV on each of them.  I'll unistall Avast and see if the plugins start working.  I have no problems running any of the scripts I add to objects and the DXmeter plugin works for me.  It looks like something is stopping the scriptable plugins as you suggested.  I don't think there is a problem with your plugin.

Thanks for your help...

on Sep 18, 2008

Scripting plugins are registering as COM components (in HKCU, so it works as a standard user). Avast might be blocking registry access in some way.

on Sep 18, 2008

I've been working with UAC turned off.  I turned it back on tonight and I do not get the (Null) error.  I'm able to run Canvas scripts in an object and see output.  However, if I crash my script with a syntax error or an undefined variable, when I select 'Cancel and edit' or 'continue' the context flashes on and of very rapidly like it's flickering and my CPU(s) max out.  I have a hell of a time killing the object.

I'm getting closer, but something's still up.

on Sep 18, 2008

This one might be a problem with my code. Can you send me an object that exhibits this behavior (max CPU and flicker)?

on Sep 18, 2008

I just made a new object and pasted a simple script which draws concentric circles.  The script has no errors  and the object starts flickering and then maxing out the CPU.  I have to kill DesktopX to get rid of it.  I packaged the object but need your e-mail again to send it.

on Sep 18, 2008

I just found your e-mail and sent the test object.

on Sep 19, 2008

Littleboy,

I just tried the latest build on my work computer (XP Pro). The flickering and pegged CPU is occuring on this computer also when I run the test scripts.  The Canvas Controller has been working consistently on this machine until this build.

 

 

on Sep 19, 2008

The flickering is most pronounced when I run this script.  I pasted it as is in case there is something about the script that is causing the flicker, but it might just be the size of the context causing the problem.  I tried running the script with different context sizes.  I start to see the flicker when the context gets around 800 X 800 and it gets worse as it gets bigger.  Looks like the context is having a hard time refreshing as it gets bigger.  When I noticed the problem on my Vista machine, I was using a context of 800 X 800. 

Hope this helps.

 

Code: vbscript
  1. Option Explicit
  2. Sub Object_OnScriptEnter
  3.     Dim ctx
  4.  Set ctx = canvas.getContext("2d")
  5.     Dim L
  6.     Dim F
  7.     Dim Dist
  8.  
  9.     canvas.width = 1000
  10.     canvas.height = 1000
  11.    
  12.     ctx.strokeStyle = "crimson"
  13.     ctx.lineWidth = 1
  14.     
  15.      drawRectangle ctx,0,0,1000,1000,false
  16.                 
  17.     drawGrid ctx,0,0,1000,1000,10
  18.    
  19.         
  20.      
  21.                 
  22. End Sub
  23. Sub Object_OnScriptExit
  24. End Sub
  25. '************************************************************************************
  26. 'Converts angles to radians
  27. '************************************************************************************
  28. Function inRadians(angle)
  29. Dim PI
  30. PI = 3.14159265
  31.    inRadians = (angle * PI) / 180
  32. End Function
  33. '******************************************************************************
  34. 'Usage: drawLine context,startx,starty,endx,endy
  35. '******************************************************************************
  36. Sub drawLine(ctx,x1,y1,x2,y2)
  37.             ctx.beginPath
  38.             ctx.moveto x1, y1
  39.             ctx.lineTo x2,y2
  40.             ctx.stroke
  41. End Sub
  42.  
  43. '************************************************************************************
  44. 'Usage: showImage(context,locx,locy,path)
  45. '************************************************************************************
  46. Sub showImage(ctx,x,y,path)
  47.   Dim img
  48.     Set img = ctx.loadImage(path)
  49.     ctx.drawImage img,x,y
  50. End Sub
  51. '************************************************************************************
  52. 'Usage: drawArc(context,locx,locy,radius, startangle - in degrees, endangle - in degrees, direction)
  53. '  - direction = anticlockwise (true)  clockwise (false)
  54. '************************************************************************************
  55. Sub drawArc(ctx,x,y,radius,startAngle,endAngle,anticlockwise)
  56. Dim startA
  57. Dim endA
  58.     startA = inRadians(startAngle)
  59.     endA = inRadians(endAngle)
  60.     ctx.beginPath
  61.     ctx.arc x,y,radius,startA,endA, anticlockwise
  62.     ctx.stroke
  63. End Sub
  64. '************************************************************************************
  65. 'Usage: drawPieSlice(context,locx,locy,radius, startangle - in degrees, endangle - in degrees, direction, filled)
  66. '  - direction = anticlockwise (true)  clockwise (false)
  67. '************************************************************************************
  68. Sub drawPieSlice(ctx,x,y,radius,startAngle,endAngle,anticlockwise,filled)
  69. Dim startA
  70. Dim endA
  71.     startA = inRadians(startAngle)
  72.     endA = inRadians(endAngle)
  73.     ctx.beginPath
  74.     ctx.moveTo x,y
  75.     ctx.arc x,y,radius,startA,endA, anticlockwise
  76.     ctx.lineTo x,y
  77.     ctx.stroke
  78.     if filled = true then
  79.        ctx.fill
  80.     end if
  81. End Sub
  82. '************************************************************************************
  83. 'Usage: drawRoundRectangle context,Leftx,Lefty, width, height, corner radius, filled
  84. '************************************************************************************
  85. Sub drawRoundRectangle(ctx, x, y, width, height, radius, filled)
  86.     ctx.beginPath
  87.     ctx.moveTo x, y + radius
  88.     ctx.lineTo x, y + height - radius
  89.     ctx.quadraticCurveTo x , y + height, x + radius, y + height
  90.     ctx.lineTo x + width - radius, y + height
  91.     ctx.quadraticCurveTo x + width, y + height, x + width, y + height - radius
  92.     ctx.lineTo x + width, y + radius
  93.     ctx.quadraticCurveTo x + width, y, x + width - radius, y
  94.     ctx.lineTo x + radius, y
  95.     ctx.quadraticCurveTo x, y, x, y + radius
  96.     if filled = true then
  97.        ctx.fill
  98.     end if
  99.     ctx.stroke
  100. End Sub
  101. '******************************************************************************
  102. 'Usage: drawCircle context,centerx,centery, radius, number of segments, filled
  103. '******************************************************************************
  104. Sub drawCircle(ctx,cx,cy,radius,num_segments, filled)
  105. Const PI = 3.14159265
  106. Dim X
  107. Dim Y
  108. Dim theta
  109. Dim dtheta
  110. Dim seg
  111.     dtheta = 2 * PI/ num_segments
  112.    
  113.     ctx.beginPath
  114.     ctx.moveto cx+radius, cy
  115.    
  116.     theta = 0
  117.     For seg = 1 To num_segments
  118.         theta = theta + dtheta
  119.         ctx.lineto cx + (radius * Cos(theta)), cy + (radius * Sin(theta))
  120.     Next
  121.     if filled = true then
  122.        ctx.fill
  123.     end if
  124.     ctx.stroke
  125. End Sub
  126. '******************************************************************************
  127. 'Usage: drawAngleLine context,startx,starty, length of line, angle in degrees
  128. '******************************************************************************
  129. Sub drawAngleLine(ctx,startx,starty,linelength,angle)
  130. Const PI = 3.14159265
  131. Dim theta
  132.   
  133.     theta = (2 * PI/ 360) * angle
  134.     ctx.beginPath
  135.     ctx.moveto startx,starty
  136.     ctx.lineto startx + (linelength * Cos(theta)), starty + (linelength * Sin(theta))
  137.     'drawLine ctx, startx + ((linelength-200) * Cos(theta)), starty + ((linelength-200) * Sin(theta)), startx +
  138. (linelength * Cos(theta)), starty + (linelength * Sin(theta))
  139.    
  140.     ctx.stroke
  141. End Sub
  142.  
  143. '************************************************************************************
  144. 'usage : returns distance from point x1,x1 to point x2,y2
  145. '************************************************************************************
  146. Function distance(x1,y1,x2,y2)
  147.   distance = sqr( ((x2-x1)*(x2-X1)) + ((y2-y1)*(y2-y1)))
  148. End Function
  149.  
  150. '******************************************************************************
  151. 'Usage: drawRectangle context,startx,starty,endx,endy, filled
  152. '******************************************************************************
  153. Sub drawRectangle(ctx,x1,y1,x2,y2, filled)
  154.  ctx.beginPath
  155.  ctx.moveto x1, y1
  156.  ctx.rect x1,y1,abs(x2-x1),abs(y2-y1)
  157.  if filled = true then
  158.            ctx.fill
  159.         end if
  160.  ctx.stroke
  161. End Sub
  162.  
  163. '******************************************************************************
  164. 'Usage: drawGrid context,startx,starty,endx,endy, grid size
  165. ' - Draws grid by specifying the grid size in pixels
  166. '******************************************************************************
  167. Sub drawGrid(ctx,x1,y1,x2,y2,gridsize)
  168.   Dim
  169.   Dim Width
  170.   Dim Height
  171.         Width = ABS(x2-x1)
  172.         Height = ABS(y2-y1)
  173.         
  174.         For L = 1 to (width+gridsize) step gridsize
  175.           drawLine ctx,x1+L,y1,x1+L,y2
  176.           drawLine ctx,x1,y1+L,x2,y1+L
  177.         Next
  178.  drawRectangle ctx,x1,y1,x2,y2,false
  179.        
  180. End Sub
  181. '******************************************************************************
  182. 'Usage: drawGrid2 context,startx,starty,endx,endy, num of divisions along x, num of divisions along y
  183. '  - Draws grid by specifying the number of divisions per direction
  184. '******************************************************************************
  185. Sub drawGrid2(ctx,x1,y1,x2,y2,xdivisions, ydivisions)
  186.   Dim
  187.   Dim Width
  188.   Dim Height
  189.   Dim xgridsize
  190.   Dim ygridsize
  191.         Width = ABS(x2-x1) 
  192.         Height = ABS(y2-y1)
  193.         xgridsize = round(Width/xdivisions)
  194.         ygridsize = round(Height/ydivisions)
  195.         
  196.        
  197.         For L = 1 to width step xgridsize
  198.           drawLine ctx,x1+L,y1,x1+L,y2   
  199.         Next
  200.         For L = 1 to height step ygridsize
  201.           drawLine ctx,x1,y1+L,x2,y1+L
  202.         Next
  203.  drawRectangle ctx,x1,y1,x2,y2,false
  204.        
  205. End Sub
  206. '******************************************************************************
  207. 'Usage:  draws a line on the x-axis with ticks on it, could be used for graph axis
  208. '******************************************************************************
  209. Sub tick_x(ctx,x1,y1,x2,xdivisions,ticklength)
  210.   Dim
  211.   Dim Width
  212.   Dim xgridsize
  213.  
  214.         Width = ABS(x2-x1) 
  215.         xgridsize = round(Width/xdivisions)
  216.      
  217.         For L = 0 to width step xgridsize
  218.           drawLine ctx,x1+L,y1,x1+L,y1-ticklength   
  219.         Next
  220.     
  221.  drawLine ctx,x1,y1,x2,y1
  222.        
  223. End Sub
  224. '******************************************************************************
  225. 'Usage:  draws a line on the y-axis with ticks on it, could be used for graph axis
  226. '******************************************************************************
  227. Sub tick_y(ctx,x1,y1,y2,ydivisions,ticklength)
  228.   Dim
  229.   Dim Height
  230.   Dim ygridsize
  231.          
  232.         Height = ABS(y2-y1)
  233.         
  234.         ygridsize = round(Height/ydivisions)
  235.         
  236.        
  237.         For L = 0 to height step ygridsize
  238.          drawLine ctx,x1,y1+L,x1+ticklength,y1+L
  239.         Next
  240.  drawLine ctx,x1,y1,x1,y2
  241.        
  242. End Sub
  243. '******************************************************************************
  244. 'Usage: drawEllipse context,centerx,centery, radiuswide, raiustall, number of segments, filled
  245. '******************************************************************************
  246. Sub drawEllipse(ctx,cx,cy,radius1,radius2,num_segments, filled)
  247. Const PI = 3.14159265
  248. Dim startX
  249. Dim startY
  250. Dim theta
  251. Dim dtheta
  252. Dim seg
  253.     dtheta = 2 * PI/ num_segments
  254.    
  255.     ctx.beginPath
  256.     ctx.moveto cx+radius1, cy
  257.    
  258.     theta = 0
  259.     For seg = 1 To num_segments
  260.         theta = theta + dtheta
  261.         ctx.lineto cx + ((radius1) * Cos(theta)), cy + (radius2 * Sin(theta))
  262.  if seg =1 then
  263.         startX=cx + (radius1 * Cos(theta))
  264.  startY=cy + (radius2 * Sin(theta))
  265.         end if
  266.     Next
  267.     ctx.lineto startX, StartY
  268.     if filled = true then
  269.            ctx.fill
  270.         end if
  271.    
  272.     ctx.stroke
  273.    
  274. End Sub
  275.  
  276.  
  277.  
6 PagesFirst 3 4 5 6