Prev: User Interface
Module graph: Screen Graphics
This module supports drawing of arbitrary two-dimensional graphic objects and images from files on the screen. The module has its own view, which can be shown or hidden under programmatic control. When shown, it appears on top of the normal console window and hides it.
The view supports two modes: "console mode", with the view covering the area of the m console, and "full screen mode", with the view covering the entire screen. The default mode is "console", but it can be changed any time by graph.full.
By default, the drawing area's size ("canvas" size) corresponds to the console's size, but it can be changed to any size which fits into memory via the graph.size function. If the canvas is bigger than the view, the origin of the view on the canvas can be specified via the graph.show function.
Graphic objects are drawn on the canvas by calling the corresponding functions. The canvas is not transferred to screen until graph.show is called, or the operating system requests redrawing.
Coordinates
Position and size of graphic objects are given by coordinates. This module supports two modes for specifying coordinates (see also graph.scale):
- Unscaled, with the unit being a single screen pixel, defining the area to draw on as a rectangle of integer width and height. Following conventions for pixel coordinates, y=0 is at the top of the rectangle, and y increases downwards.
- Scaled, normalizing the rectangle to draw on as a square with sides of length 1, and an additional rectangle on the right for x>1 (typically on S60 devices), or at the bottom for y<0 (typically on UIQ devices). Following conventions for mathematical coordinates, y=0 is at the bottom of the square, and y increases upwards.
Drawing coordinates are always relative to the current clipping rectangle. See also graph.clip.
Colors
Colors for the graphic are expressed as RGB, i.e. as the three intensities of red, green and blue. In m, there are two ways to specify an RGB value:
- As an array of three color intensities between 0 and 1. For instance, [0.5,0,0.5] specifies a dark magenta (50% red and 50% blue).
- As an integer encoding the three color intensities between 0 and 255 as red shl 16 | green shl 8 | blue. This is typically written in hexadecimal notation as 0xrrggbb. For instance, 0x800080 is (after rounding) equivalent to [0.5,0,0.5].
Eight standard colors are predefined as module constants:
• const black = 0x000000
• const white = 0xffffff
• const red = 0xff0000
• const green = 0x00ff00
• const blue = 0x0000ff
• const yellow = 0xffff00
• const cyan = 0x00ffff
• const magenta = 0xff00ff
The view itself has a background color (set via graph.bg), which initially is white. Graphic items drawn on the background generally have two colors:
- The pen color defines the color in which lines, texts and outlines are drawn. It can also be set to false, so no outlines are drawn. It is initially black, and set via graph.pen.
- The brush color defines the color by which areas are filled. It can also be set to false, so areas are not filled. It is initially false, and set via graph.brush.
Alpha Blending
All drawing operations can optionally be modified such that the item drawn is blended with the background. Blending is configured by a parameter α, a number between 0 and 1 indicating to what extent the background image is blended in:
- α = 0: no blending, the background is ignored. This is the default setting.
- 0 < α < 1: the background is blended in.
- α = 1: the background is completely blended in, i.e. the drawing operation has no effect.
α is set via
graph.alpha. Setting it to a value other than 0 causes a small performance penalty on drawing operations.
Simple Example
The following example draws the graph of a normal distribution around the average 0.5, coloring it from almost pure blue to almost pure red, then blends a black rectangle over it with the text "sample".
// use the normalized 0 to 1 coordinate system
graph.scale(true);
h=0.02;
for x=0.1 to 0.9 by h do
t=-4*(x-0.5); y=math.exp(-t*t)*0.9;
color=[x,0,1-x];
graph.pen(color); graph.brush(color);
graph.rect(x,0.1,h,y)
end;
graph.pen(graph.black);
graph.text(0.1, h, "Value");
graph.text(0.1-h, 0.1, "Frequency", graph.up);
graph.brush(graph.black);
graph.alpha(0.7);
graph.rect(0.2, 0.2, 0.6, 0.2);
graph.pen(graph.white);
graph.alpha(0);
graph.text(0.25, 0.25, "Sample");
graph.show();
|
 | |  |
| Series 60 sample screen | | UIQ sample screen |
graph.alpha
• function alpha(factor) → Number
• function alpha() → Number
Gets or sets the background blending factor α applied to all drawing operations. With one argument, sets the blending factor, and returns the old factor. Without arguments, returns the current factor.
The factor α is a value between 0 and 1, inclusive. See section * () for more information.
// blend all drawing operations with 30%
// of the background
graph.alpha(0.3)
|
graph.bg
• function bg(color) → Array
• function bg() → Array
Gets or sets the background color of the graph view. With one argument, sets the background color, and returns the old background color, as an array of red, green and blue intensities. Without arguments, returns the current background color.
See section * () for the definition of colors.
// set the background color to a light gray
graph.bg([0.9,0.9,0.9])
|
graph.brush
• function brush(color) → Array
• function brush() → Array
Gets or sets the brush color. This is the color used to fill areas surrounded by objects. With one argument, sets the brush color or disables it (if color=false), and returns the old brush color as an array of red, green and blue intensities, or false if the brush was disabled. Subsequently added objects will use the new brush color.
Without arguments, returns the current brush color.
By default, the brush is disabled. See section * () for the definition of colors.
// fill the objects with white
graph.brush(graph.white)
|
graph.circle
• function circle(x, y, diameter) → null
Draws a circle in the square defined by the corners (x,y) and (x+diameter,y+diameter). The outline is drawn with the current pen color, and the circle is filled with the current brush color.
graph.scale(true);
graph.pen(graph.red);
graph.brush(graph.green); // fill with green
graph.circle(0.5, 0.4, 0.3);
graph.brush(false); // do not fill
graph.circle(0.5, 0.6, 0.3);
|
 | Sample m screen |
graph.clear
• function clear() → null
Fills the entire view with the current background color, as defined by graph.bg.
graph.clip
• function clip() → Array | null
• function clip(xywh) → Array | null
Returns the current clipping rectangle, or null if there is no clipping (default). Without arguments, the clipping rectangle is not modified.
With one argument xywh=[x,y,w,h], the clipping rectangle is set to this rectangle (scaled if in scaled mode). All subsequent drawing operations are relative to the upper left (unscaled) or lower left (scaled) corner of the clipping rectangle.
With one argument xywh=null, the clipping rectangle is removed, and the drawing origin is set back to the upper left (unscaled) or lower left (scaled) corner of the canvas.
// unscaled clipping
graph.scale(false); graph.pen(graph.black);
graph.rect(20, 30, 100, 40);
graph.clip([20, 30, 100, 40]);
graph.text(5, 30, "Unscaled text (will be clipped)");
// scaled clipping
graph.scale(true); graph.pen(graph.red);
print graph.clip(null);
→ [0.0694444444,0.8958333333,0.3472222222,
0.1388888889]
graph.rect(0.2, 0.3, 0.6, 0.1);
graph.clip([0.2, 0.3, 0.6, 0.1]);
graph.text(0.02, 0.02, "Scaled text (will be clipped)");
|
 | Sample m screen |
graph.ellipse
• function ellipse(x, y, w, h) → null
• function ellipse(x, y, w, h, alpha, beta) → null
Draws an ellipse, an arc or a pie slice:
- With four arguments, draws an ellipse into the rectangle with corner at x,y, width w and height h. The outline is drawn with the current pen color, and the ellipse is filled with the current brush color.
- With six arguments and the brush enabled, draws the outline of a pie slice with the current pen color, and fills it with the current brush color. The pie is defined by two angles alpha and beta measured in degrees from the x axis, on a circle around the center of the ellipse:
- With six arguments and the brush disabled, draws just the arc, i.e. the part of the pie on the outline of the ellipse.
// draw an elliptic pie, with parallel arcs
percent=[26, 18, 43, 13];
colors=[graph.red,graph.green,graph.blue,graph.yellow];
alpha=0;
for i=0 to len(percent)-1 do
beta=alpha+360*percent[i]/100;
// the pie slice (brush enabled)
graph.pen(graph.black); graph.brush(colors[i]);
graph.ellipse(10, 10, 160, 140, alpha, beta);
// the parellel arc (brush disbled)
graph.pen(colors[i]); graph.brush(false);
graph.ellipse(5, 5, 170, 150, alpha, beta);
alpha=beta
end;
graph.show()
|
 | Sample m screen |
graph.font
• function font(font) → Array
• function font() → Array
Gets or sets the text font. With one argument, sets the current font, and returns the old font. Subsequently via graph.text added texts will use the new font. Without arguments, returns the current font.
The default font is the m console font. See ui.mfont for the definition of fonts, and graph.text for an example using fonts.
graph.full
• function full() → Array
• function full(enabled) → Array
| | |
| Compatibility of function graph.full |
| Sony Ericsson phones[8]. | Restricted menu access |
|
Without arguments, returns the size of the view in the current mode, scaled if in scaled mode.
With one argument, enables (enabled=true) or disables (enabled=false) full screen mode, and returns the new view size, scaled if in scaled mode. Note that this does not change the size of the canvas; the canvas size can only be changed with graph.size.
The following function fills the screen (not the canvas) with an ellipse in a given color:
function fill(color)
graph.clear();
graph.pen(color); graph.brush(color);
s=graph.full(); // get screen size
graph.ellipse(0, 0, s[0], s[1])
end
|
Drawing a red ellipse in console mode just fills the console view, as usual:
graph.full(false);
fill(graph.red);
graph.show()
|
 | |  |
| Series 60 sample screen | | UIQ sample screen |
Drawing a green ellipse after changing to full screen mode truncates the ellipse to the console view size (assuming the canvas size wasn't changed):
graph.full(true);
fill(graph.green);
graph.show()
|
 | |  |
| Series 60 sample screen | | UIQ sample screen |
Drawing a blue ellipse after setting the canvas size to the view size fills the entire screen with the ellipse:
s=graph.full(true);
graph.size(s[0], s[1]);
fill(graph.blue);
graph.show()
|
 | |  |
| Series 60 sample screen | | UIQ sample screen |
graph.get
• function get(x, y) → Number
• function get(x, y, w) → Array
• function get(x, y, w, h) → Array
Gets a pixel, a scan line or a rectangle from the current image.
With two arguments, returns the color of the pixel at (x,y) as a single integer (see section * ()).
With three arguments, returns an array with the pixel colors of the horizontal line of length w starting at (x,y).
With four arguments, returns a matrix with the pixel colors of the rectangle with corner (x,y), width w and height h.
In scaled mode, coordinates and dimensions are scaled.
See also graph.put.
graph.hide
• function hide() → null
Hides the graph view, showing the standard process view, or any previous view. If the graph view is not shown, this call is ignored.
graph.icon
• function icon(path, transparent=null) → Native Object
Permissions: Read(path)
• function icon(data, transparent=null) → Native Object
• function icon(data, maskData) → Native Object
• function icon(icon) → Native Object
Creates an icon from an image file, or from color data, and returns the icon object. Icons may have an optional transparency mask, defining which pixels are opaque (drawn) and which are transparent (not drawn) when drawing the icon with graph.put.
With a single path argument, loads an image from the file at path, and returns it as an icon. The image file formats supported vary from device to device, but usually include BMP, GIF, JPEG and PNG formats. If the image has transparency information, it is also loaded to define the icon's transparency mask. Alternatively, if transparent is a number, all pixels of this color are assumed transparent.
With a single data argument, the icon's image is defined by the colors in data. data is typically a matrix as returned by graph.get, but can also be a single pixel or a scan line. If transparent is a number, all pixels of this color are assumed transparent. Alternatively, the matrix maskData can define transparency on a pixel by pixel basis: all black (zero) pixels in maskData are assumed transparent. maskData must have the same dimensions as data.
With a single icon argument, a copy of the icon is created and returned, e.g. to scale it while still keeping the original.
Use graph.size to obtain the size of an icon, or to rescale it.
Large icons, e.g. those produced by a high resolution camera, consume considerable memory.
// load the icon
i=graph.icon("mShell.png")
// get its size
graph.size(i)
→ [156,92]
// draw it
graph.put(20,20,i)
// copy the icon
i2=graph.icon(i);
// scale the copy into a 80x80 square and draw it
graph.size(i2,80,80);
graph.put(20,120,i2);
graph.show()
|
 | Sample m screen |
graph.line
• function line(x1, y1, x2, y2) → null
Draws a line from (x1,y1) to (x2,y2), using the current pen color.
// plot a sine wave from 0 to 4 pi
graph.scale(true);
x1=0; y1=0;
for x=0 to 1 by 0.02 do
y=(math.sin(4*math.pi*x)+1)/2;
if x>0 then graph.line(x1,y1,x,y) end;
x1=x; y1=y
end;
graph.show()
|
 | Sample m screen |
graph.pen
• function pen(color) → Array
• function pen() → Array
Gets or sets the pen color. This is the color used to draw the outlines of objects. With one argument, sets the pen color or disables it (if color=false), and returns the old pen color as an array of red, green and blue intensities, or false if the pen was disabled. Subsequently added objects will use the new pen color.
Without arguments, returns the current pen color.
The default pen color is black. See section * () for the definition of colors.
// use a slightly dark magenta pen
graph.pen(0xc000c0)
|
graph.poly
• function poly(x, y) → null
Draws a closed polygon following the points given by x and y. x and y must be two arrays of identical length. The polygon's edges are lines from (x[i],y[i]) to (x[i+1],y[i+1]) (0 <= i < len(x) - 1), with the last (closing) line going from (x[len(x)-1],y[len(x)-1]) to (x[0],y[0]). The lines of the polygon are drawn with current pen color, and the polygon's interior (or interiors) are filled with the current brush color.
// draw a blue bowtie, filled with cyan
graph.pen(graph.blue); graph.brush(graph.cyan);
graph.poly([20,150,150,20],[40,140,40,140]);
graph.show()
|
 | Sample m screen |
graph.put
• function put(x, y, color) → null
• function put(x, y, icon) → null
Draws a single pixel, a scan line or a rectangle, or draws an icon.
If color is a number, sets the pixel at (x,y) to the color color.
If color is an array of numbers, sets the pixels from (x,y) to (x+len(color)-1,y) to the colors in color.
If color is a matrix of numbers, sets the rectangle with upper left corner (x,y), height len(data) and width len(data[0]) to the colors in color.
If the third parameter is an icon, draws icon with upper left corner (x,y). If the icon has a mask, only opaque pixels are drawn.
In scaled mode, (x,y) are scaled, but always define the upper left corner of the rectangle.
Current pen and brush color do not affect what is being drawn.
A graph.put example drawing single points:
// plot a sine wave with single red points
graph.bg([0.8,1,0.8]); graph.clear();
graph.scale(true);
for x=0 to 1 by 0.01 do
y=(math.sin(4*math.pi*x)+1)/2;
graph.put(x,y,graph.red)
end;
graph.show()
|
 | Sample m screen |
A graph.put example drawing icons, with and without transparent background:
// Draw a blue ellipse
graph.brush(graph.blue);
graph.ellipse(0,0,60,40)
// Copy the ellipse and replicate it
data=graph.get(0,0,60,40);
for i=0 to 3 do
graph.put(40*i,30*i,data)
end;
// The entire rectangle is overwritten
graph.show()
// Create an icon, making white transparent
icon=graph.icon(data, graph.white);
graph.clear()
// Replicate the icon
for i=0 to 3 do
graph.put(40*i,30*i,icon)
end
// Only non-white pixels are overwritten
graph.show()
|
graph.rect
• function rect(x, y, w, h) → null
Draws a rectangle between the corners (x,y) and (x+w,y+h). The outline is drawn with the current pen color, and the rectangle is filled with the current brush color.
rect(x,y,w,h) produces the same as
poly([x,x+w,x+w,x],[y,y,y+h,y+h]).
graph.save
• function save(path) → null
Permissions: Write(path)
• function save(path, x, y, w, h) → null
Permissions: Write(path)
Saves the current image to the file given by path. With one argument, saves the whole image. With five arguments, saves only the rectangle between the corners (x,y) and (x+w,y+h).
The desired image file format is determined from the image file suffix. Supported file suffices are .gif (GIF format), .jpg (JPEG format) and .png (PNG format).
| | |
| Compatibility of saving to PNG |
| Sony Ericsson phones | ErrNotSupported |
|
// save the entire drawing to rates.jpg
graph.save("rates.jpg");
// save only the upper right quadrant to d:\rates.gif
graph.scale(true);
graph.save("d:\rates.gif", 0.5, 0.5, 0.5, 0.5)
|
graph.scale
• function scale(scaled) → Boolean
• function scale() → Boolean
Gets or sets the current scaling mode. With one argument, sets the scaling mode to scaled, and returns the old scaling mode. Without an argument, returns the current scaling mode.
For information about scaling, see section * ().
graph.screen
• function screen() → Native Object
• function screen(x, y, w, h) → Native Object
Permissions: ReadApp
Produces an icon of the image (or a portion of it) on the device screen and returns it. If m is running in the background, this takes a device screen shot.
Without arguments, the icon will contain the entire screen image. With four arguments, only the rectangle between screen coordinates (x,y) and (x+w,y+h) will be copied. In scaled mode, x, y, w and h are scaled.
// make the canvas as large as the screen
graph.size(graph.full(true));
// take a screen shot and save it to screen.gif
i=graph.screen();
graph.put(0,0,i);
graph.save("screen.gif");
|
graph.show
• function show() → null
• function show(x, y) → null
• function show(x, y, degrees) → null
Shows the graph view, hiding the standard process view, and draws all objects added so far. If the graph view is already shown, it is redrawn.
With two arguments, also aligns the origin of the graph view with point (x,y) of the the canvas. In unscaled mode, the origin of the view is in its upper left corner, and graph.show(0,0) aligns the upper left corner of the canvas with it. In scaled mode, x and y are scaled, and graph.show(0,0) aligns the lower left corner of the view with the lower left corner of the canvas.
With three arguments, the view is rotated counterclockwise by rotate degrees (must be a multiple of 90).
// get the original size and create a canvas of 480x320
s=graph.size(480, 320)
// draw a red circle on it
graph.brush(graph.red);
graph.ellipse(10, 10, 460, 300)
// show its upper left quadrant
graph.show(0, 0)
// show its lower right quadrant
graph.show(480-s[0], 320-s[1])
|
graph.size
• function size() → Array
• function size(icon) → Array
• function size(text, bounds=false) → Array
• function size(wh) → Array
• function size(w, h) → Array
• function size(icon, scale) → Array
• function size(icon, w, h) → Array
Without arguments, returns the size (width and height) of the drawable area. The drawable area includes all the points in the rectangle between (0,0) and (graph.size()[0], graph.size()[1]). In unscaled mode, graph.size() returns the width and height as number of pixels. In scaled mode, one of width or height will always be one.
With one icon argument, returns the size (width and height) of the icon.
With one text argument and an optional boolean argument, returns returns the size (width and height) of the text if it were drawn using the current font. If bounds=true, the size of the bounding box around the text is returned, considering the actual ascents and descents in the text. If bounds=false, the height returned only depends on the font and can thus be used to vertically align chunks of text.
With one array argument wh=[w,h] or two numeric arguments w and h, sets the size of the canvas to width w and height h, and returns the size of the old canvas (initially, the size of the canvas matches the size of the view). In unscaled mode, w and h are measured in pixels. In scaled mode, w and h are resizing factors (relative to the current size), and the scale is recalculated. See graph.show for an example using a canvas larger than the view.
With two arguments icon and a scale, scales the icon icon by the factor scale. Returns the old size (width and height) of the icon.
With three arguments, scales the icon icon to the width w and height h. Returns the old size (width and height) of the icon.
// get unscaled and scaled sizes
graph.scale(false);
print graph.size()
→ [208,227]
graph.scale(true);
print graph.size()
→ [1,1.0913461538]
// draw text centered in a red rectangle
text="Alarm"; x=0.5; y=0.2; w=0.6; h=0.2;
graph.brush(red); graph.rect(x, y, w, h);
s=graph.size(text);
graph.text(x+(w-s[0])/2,y+(h-s[1])/2,text);
graph.show()
|
 | Sample m screen |
graph.text
• function text(x, y, text, direction=0) → null
Draws text starting (the baseline of the first character) at point (x,y) using the current font. Text can be drawn horizontally or vertically:
- If direction=0, text is drawn horizontally.
- If direction>0, text is drawn vertically going up.
- If direction<0, text is drawn vertically going down.
Two indicate the direction, two constants are defined:
• const up = 1
For vertical text going upwards.
• const down = -1
For vertical text going downwards.
graph.pen(0x800080);
graph.text(50,70,"mShell");
graph.text(50,70,"mShell",graph.up);
old=graph.font(["SwissA", 24, true, false]);
graph.pen(0x808000);
graph.text(50,90,"mShell");
graph.text(50,90,"mShell",graph.down);
graph.font(old);
graph.show()
|
 | Sample m screen |
Next: Module light: Control Device Lighting© 2004-2011 airbit AG, CH-8008 Zürich
Document AB-M-LIB-888