Using Graphic objects: Canvas object
With the Canvas object you create an off-screen bitmap and use it as drawing destination for all typical graphical operations like the filling rectangular areas with solid color or color gradient, stroking lines and curves, printing text, etc. Thereupon the contents stored in Canvas can be simply displayed by views like the Image view, Bitmap Frame view, etc. The functionality of the Canvas object corresponds to the provided natively in the underlying Graphics Engine and it is implemented in the Mosaic framework class Graphics::Canvas.
The following sections are intended to provide you an introduction and useful tips of how to deal with the Canvas object. For the complete reference please see the documentation of the Graphics::Canvas class. Please note, with Canvas object you only create the bitmap. To display it on the screen you need a view.
CAUTION
Please consider, that each Canvas object reserves memory for an internal bitmap to store the resulting (drawn) image inside. The size of the bitmap corresponds to the configured size of the Canvas. In other words, a 200x100 pixel large Canvas will use a 200x100 pixel large bitmap. Assuming you are working with the RGBA8888 (32-bit per pixel) Platform Package, then the bitmap would occupy ~80 KB of the RAM. Thus, if RAM is a scarce resource in your target device, you should use the Canvas objects with prudence.
Add new Canvas object
To add a new Canvas object just at the design time of a GUI component do following:
★First ensure that the Templates window is visible.
★In Templates window switch to the folder Resources.
★In the folder locate the template Canvas.
★Drag & Drop the template into the Composer window:
★Eventually name the new added Canvas object.
Inspect the Canvas object
As long as the Canvas object is selected you can inspect and modify its properties conveniently in the Inspector window as demonstrated with the property FrameSize in the screenshot below:
This is in so far worth mentioning as all following sections describe diverse features of the Canvas object by explicitly referring to its corresponding properties. If you are not familiar with the concept of a property and the usage of Inspector window, please read first the preceding chapter Compositing component appearance.
Connect the Canvas object to a view
The Canvas object stores the drawn image internally within a bitmap. In order to display this bitmap on the screen you have to connect the Canvas object to one of the image views. Accordingly, the view will display the bitmap similarly to how regular static Bitmap resources are displayed.
To connect a Canvas object to a view you have to assign this object to the property Bitmap of the affected view. With the Inspector Assistant you can conveniently select the right object when you edit the initialization expression for the property Bitmap. The following example demonstrates how you assign the Canvas object to the Image view:
As soon as you have connected the both, the information provided in the Canvas object appears within the view. If desired, you can assign the same Canvas object to several views. If during the runtime of the application, the content of the Canvas object changes, all associated views are updated automatically.
Configure the Canvas object
The Canvas manages internally an off-screen bitmap where the resulting (drawn) image is stored. The size (width x height) of this bitmap is configured by using the property FrameSize. Consequently, if you configure the Canvas object with the size <200,100>, the bitmap will store 200x100 pixel of the drawn image. Graphical objects lying beyond this border are simply clipped.
Per default the Canvas object will create the off-screen bitmap with one frame. However, if your application case it requires, you can specify in the property NoOfFrames a higher value. For example, with the value 3 you would configure Canvas to create a bitmap with 3 frames each as large as the size specified in the property FrameSize. Later at the runtime you can fill each frame with different contents and the views connected to the Canvas object can select which frame should be displayed. This feature is similar to the of multi-frame Bitmap resources.
CAUTION
Please note, the higher the number of frames the higher the RAM usage of the Canvas object. For example, Canvas configured with 3 frames will occupy 3 times more RAM than the same Canvas object with one frame. Assuming FrameSize is <200,100> and you are working with the RGBA8888 (32-bit per pixel) Platform Package, then the bitmap would occupy ~240 KB of the RAM (3 x ~80 kB). Thus, if RAM is a scarce resource in your target device, you should use the Canvas objects with prudence.
In case of a Canvas object configured with more than one frame you can additionally specify in the property FrameDelay a time span between two frames expressed in milliseconds. This results in the Canvas object containing a kind of animated sequence of bitmap frames. You can fill each frame with another content and the connected view can play the frames automatically like a short video. Per default, the property FrameDelay is configured with the value 0 (zero), which means no animation.
Perform drawing operations
In order to draw within the Canvas you use respective methods of the Canvas object. For example, to fill a rectangular area with a solid color, invoke the method FillRectangle() and pass in its parameters the coordinates of the area as well as the desired color. The following table provides an overview of all relevant methods:
Method |
Description |
---|---|
Initiates the drawing and selects the frame within the Canvas as destination for subsequent operations. |
|
Terminates the drawing operations. |
|
Fills a rectangular area in the Canvas with solid color or color gradient. |
|
Draws a line segment in the Canvas. |
|
Copies an area of a source bitmap into the Canvas. |
|
Copies and scales an area of a source bitmap into the Canvas. |
|
Fills a rectangular area of the Canvas with multiple copies of an area of a source bitmap. |
|
Performs the projection of a rectangular source bitmap area onto a four corner polygon within the destination Canvas. |
|
Draws a free scalable frame by composing it of bitmap segments. |
|
Draws a hollow rectangle in the Canvas. |
|
Draws the text row with given font within the Canvas. |
|
Fills within the Canvas a polygon determined by data stored in the Graphics::Path object. |
|
Strokes within the Canvas the outline of a polygon determined by data stored in the Graphics::Path object. |
The drawing sequence should always start with an invocation of the method BeginDrawing() and it should end with EndDrawing(). In-between you place all the methods to achieve the desired drawing results. The following code example demonstrates it.
var rect area = rect(<0,0>, Canvas.FrameSize ); // Start the drawing sequence in the first frame Canvas.BeginDrawing( 0 ); // Fill two rectangles. One is green. The second, smaller, is red. Canvas.FillRectangle( area, <0,0,100,100>, #00FF00FF, #00FF00FF, #00FF00FF, #00FF00FF, false ); Canvas.FillRectangle( area, <10,10,20,20>, #FF0000FF, #FF0000FF, #FF0000FF, #FF0000FF, false ); // End the drawing sequence. This causes the associated views // to update their appearance Canvas.EndDrawing();
Usually, you execute such code sequence in response to user action or a timer or system event. It depends in fact on your application case. Please note, that all drawing operations are cumulative. This means, new operations overwrite or complement the contents created by preceding drawing sequences. Therefore it is often reasonable to clear the Canvas before you start with a new sequence. For this purpose simply fill the entire Canvas area with the transparent color #00000000 and disabled alpha-blending. Following example demonstrates it:
var rect area = rect(<0,0>, Canvas.FrameSize ); // Start the drawing sequence in the first frame Canvas.BeginDrawing( 0 ); // Clear the Canvas with transparent color Canvas.FillRectangle( area, area, #00000000, #00000000, #00000000, #00000000, false ); ... further drawing operations ... // End the drawing sequence. This causes the associated views // to update their appearance Canvas.EndDrawing();