Graphics

From RFO-BASIC! Manual
Jump to: navigation, search

The RFO-BASIC! graphics interface lets you combine text, shapes, and images on the graphics screen. This screen occupies the entire display of the Android device. Display of the graphics screen prevents the display of the text output screen, which is the simpler method of interaction between user and program, but does not destroy it. Pressing the BACK key recalls the text output console. In addition, a GR.FRONT statement lets the program switch between the graphics screen and the text output screen. Statements that raise a pop-up window for user input (such as INPUT and SELECT) work normally even when the graphics screen is displayed.

Unlike the text output screen, the graphics screen gives the program precise control over size, position, color, and transparency.

The GR.OPEN statement initializes the graphics interface and puts the graphics screen on display. The GR.CLOSE statement ends graphics operations. Graphics operations also end when the program ends, such as after the user presses the MENU key. To keep the graphics screen on display after the program has completed its computing, use a long PAUSE statement or an infinite loop with a method, such as an interrupt routine, to let the user force the program to terminate.

The GR.CLS statement clears the graphics screen and destroys all graphics elements. The GR.RENDER statement puts graphics elements onto the graphics screen. Nothing appears on the graphics screen until the program executes GR.RENDER. GR.RENDER achieves a flicker-free transition from what was displayed on the graphics screen, to elements the program specified more recently.

A typical use of graphics is to put elements on the graphics screen, and to update them based on real-world events such as received messages. There are two ways to achieve this:

  1. Code a main loop that begins with GR.CLS, uses graphics statements to place the desired graphic elements on the screen, and finally executes GR.RENDER.
  2. Do the above only once to specify the graphics screen's initial appearance. Then code a main loop in which the program may use GR.MODIFY to change the attributes of certain elements, or GR.HIDE and GR.SHOW to inhibit some elements from being displayed, and finally executes GR.RENDER.
Geometry

Graphics operations work in Portrait Mode and Landscape Mode. The GR.OPEN command can state that the program operates in one specific orientation, or can specify that the orientation will change as the user rotates the Android device.

When drawing an object onto the graphics screen, the location (typically of the object's upper-left corner) and the size of the object are stated as a number of pixels. The upper-left corner of the graphics screen is identified with horizontal location x=0 and vertical location y=0. Pixels to the right and below this corner are identified with increasing positive pixel addresses (as in Quadrant IV of a Cartesian coordinate system).

Coordinates are measured with respect to the physical screen, not to anything on it. If you choose to show the Android Status Bar, anything you draw at the top of the screen is covered by the Status Bar.

A program can use the GR.SCREEN statement to query the size of the graphics screen. If the program has allowed the orientation to shift, the size of the graphics screen may change if the user rotates the Android device during the program's execution. RFO-BASIC! attempts to reconstruct the graphics objects in the new orientation, but the program may elect to re-draw the entire screen (notably because the program has different preferred uses or layouts based on the orientation). GR.SCREEN indicates that the device is in Portrait Mode if y > x.

Color, transparency, and style

Transparency is specified by an integer. 0 means the element is completely invisible, yielding to material previously drawn on the graphics screen at its location. 255 means the element is opaque; it is visible, hiding anything previously drawn at its location. Values in between give a mix of the new element and the background elements at the same location.

Colors are specified by three integers, red, green, and blue. 0 means that dimension of the color is dark; 255 means that dimension of the color is bright. 0,0,0 signifies black, 255,0,0 signifies bright red, and 255,255,255 signifies white.

Style is one of three options: 0 means to trace the outline of the graphics element, 1 means to fill it in, and 2 means to do both. If drawing a circle, this is the difference between a filled-in circle and simply drawing the circumference. However, style also applies when drawing text. Selecting a style of 0 does not draw the text but only the outlines of each character. This is an interesting alternative to "graying out" text that is not relevant at the moment. A style of 2 is most common when drawing text.

Only the low-order byte of color and transparency is relevant. If you should specify a value of 256, it wraps around and the effect is the same as specifying 0.

Color, transparency, and style are often stored together in a data structure called a paint.

General rules

The BASIC program can draw elements onto the graphics screen, such as lines, circles, text, and images. Whenever it does so:

  1. The element's color, transparency, and style is dictated by the current paint.
  2. The element receives a number, which the program must use if it refers to the element later, such as in a GR.MODIFY statement.
  3. The element's number is added to a display list. Elements have no "z address," but the GR.RENDER statement draws elements in the order in which they appear in the Display List. Later elements appear to be drawn "on top of" earlier elements. Programs can create custom display lists and thereby change the order in which elements are drawn.

An exception to this scheme is while BASIC is placed into Draw-Into Mode. In this case, BASIC draws every specified element into a specified bitmap.

Major operations[edit]

GR.OPEN[edit]

Begin graphics operations

Synopsis
GR.OPEN {{<alpha_nexp>}{, <red_nexp>}{, <green_nexp>}{, <blue_nexp>}{, <status_lexp>}{, <orientation_nexp>}}
Description

The GR.OPEN statement opens the graphics screen and prepares BASIC to paint graphics elements into it. It is a run-time error to execute any other graphics statement without first executing GR.OPEN.

The alpha, red, green, and blue expressions become the graphics screen's background color. The alpha parameter does not achieve transparency, as there is nothing beneath the background that might show through; but it is an alternative way to dim the color selected for the background. If any transparency or color parameter is omitted, GR.OPEN uses 255. (If all are omitted, 255,255,255,255 is used, specifying bright white.)

If <status_lexp> has a value other than 0, the graphics screen incorporates the Android Status Bar. If it is 0 or omitted, the Android Status Bar is not present. If the Android Status Bar is displayed, screen geometry continues to be based on the total size of the Android display; it does not reflect a "client screen" remaining after the Status Bar. This means the program could draw elements that conflict with the Status Bar.

The <orientation_nexp> parameter specifies the initial orientation. Valid values are the same as for the GR.ORIENTATION statement. Notably, a value of -1 means that the orientation of the graphics screen depends on how the user holds the Android device and can change at any time while the program is running. If the expression is omitted, the graphics screen begins in Landscape Mode.

Example
GR.OPEN ,,,,,-1

This statement defaults to a bright white screen without the Android Status Bar. The -1 means that the orientation at any moment will depend on how the user holds the device.

GR.CLOSE[edit]

End graphics operations

Synopsis
GR.CLOSE
Description

The GR.CLOSE statement ends graphics operations, causes the graphics screen to no longer be displayed, and raises the output screen in its place. It does not end the BASIC program. However, if the program ends for some other reason, graphics shuts down as with the GR.CLOSE statement.

GR.CLS[edit]

Clear the graphics screen

Synopsis
GR.CLS
Description

The GR.CLS statement deletes all the data structures of the graphics subsystem, including:

  • All elements that have been drawn on the graphics screen (making their numbers invalid for future use)
  • All paints
  • All settings of GR.COLOR and GR.TEXT
  • The current display list

GR.CLS does not affect what is shown on the Android display. To display an empty graphics screen in the chosen background color, the program would have to execute GR.RENDER. However, typically, the program first draws a new set of elements that is to be displayed next.

GR.CLS does not delete bitmaps that have been loaded. They are not set to appear on the graphics screen, because the data structures that would achieve this have been deleted, but their bitmap numbers remain valid, and a program could re-draw them (without having to reload them) before executing GR.RENDER.

GR.RENDER[edit]

Render the graphics screen

Synopsis
GR.RENDER
Description

The GR.RENDER statement displays all the objects in the current working display list. That is, it causes every element that the program has drawn to physically appear on the graphics screen. An exception is objects in the display list that are inhibited from display using GR.HIDE.

GR.RENDER waits until the next screen refresh (typically, 60 times per second). GR.RENDER does not complete execution until fully displaying the contents of the display list. This means that two consecutive GR.RENDER statements will delay the BASIC program about 16.7 msec. There is no benefit to trying to render the screen faster than this.

A program designed to display smooth animation should not perform computations that take more than 16.7 msec between GR.RENDER commands; otherwise, some renderings may skip an Android screen refresh and the animation can become jerky. A program can use the CLOCK() or TIME() functions to measure the amount of time its computations are taking.

If RFO-BASIC! is running in the background (see the BACKGROUND() function and the HOME key), GR.RENDER suspends the program's execution until the user returns BASIC to the foreground.

The figures of 60 refreshes per second and 16.7 msec between refreshes may be different on some Android devices.

Example

Here is a working program that combines the GR.OPEN and GR.RENDER statements with others discussed later:

GR.OPEN                    % Start graphics; background assumed to be bright white, screen is cleared
GR.COLOR 255,0,0,0         % Specify opaque black drawing (bright white is the default paint color too)
GR.TEXT.SIZE 80            % Text lines are 80 pixels high
GR.TEXT.DRAW textline1, 0,100, "Hello, world!"
GR.RENDER                  % Make the text appear
PAUSE 2000                 % Stay on the graphics screen for 2 seconds before the program ends

GR.FRONT[edit]

Select between the graphics screen and the text output console

Synopsis
GR.FRONT <flag_nexp>
Description

An RFO-BASIC! program can maintain both the graphics screen and the text output console, but only one is visible at any time. The GR.FRONT statement makes this selection.

  • If <flag_nexp> is true (nonzero), then the graphics screen is the one the user sees. The BASIC program can still operate on the text output console, such as by executing PRINT statements.
  • If <flag_nexp> is false (0), then the text output console is the one the user sees. The BASIC program can still draw to the graphics screen, but GR.RENDER will fail unless the program puts the graphics screen on display.

Interacting with Android[edit]

Given that Android devices range from a flip-phone with a tiny screen to a Chromebook with a keyboard, one of the first steps of a BASIC program that uses the graphics screen is to discover the attributes and set the operating mode.

GR.ORIENTATION[edit]

Specify the screen orientation

Synopsis
GR.ORIENTATION <orientation_nexp>
Description

An Android device can be operated in one of two Modes:

  • Portrait Mode, in which the long dimension of the display is vertical
  • Landscape Mode, in which the long dimension of the display is horizontal.

The GR.ORIENTATION statement specifies which Mode the program will use. The <orientation_nexp> parameter can have one of the following values:

Value Meaning
-1 The initial orientation depends on how the user is holding the Android device. If the user subsequently rotates the device, the orientation will change. For example, a GR.SCREEN statement executed after the user rotates the device returns height and width values that are exchanged.
0 The orientation is Landscape Mode, no matter how the user rotates the device.
1 The orientation is Portrait Mode (rotated 90 degrees clockwise from Landscape Mode), no matter how the user rotates the device.
2 The orientation is Reverse Landscape Mode, no matter how the user rotates the device.
3 The orientation is Reverse Portrait Mode, no matter how the user rotates the device. This is upside-down for a cellphone. Some phones do not support upside-down operation.
See also

Orientation can also be specified in the GR.OPEN statement.

GR.SCREEN[edit]

Obtain the screen dimensions

Synopsis
GR.SCREEN <width_nvar>, <height_nvar>{, <density_nvar> }
Description

The GR.SCREEN statement obtains the dimensions of the Android display. These include:

  • The screen width, in pixels
  • The screen height, in pixels
  • Optionally, the pixel density, in dots per inch (dpi).

The GR.SCREEN statement lets the program determine whether the device is in Portrait Mode or Landscape Mode. For example:

GR.SCREEN w, h
IsPortrait = (w < h)

If the GR.OPEN or GR.ORIENTATION statement has permitted the mode to change depending on the manner in which the user holds the device, then the output of GR.SCREEN can change at any moment.

The <density_nvar> parameter, if present, is set to one of the standard Android pixel density values, such as 120, 160, or 240 dpi. This is not necessarily the actual pixel density.

See also

The SCREEN statement, and its subsets SCREEN.ROTATION and SCREEN.SIZE, return additional information.

GR.SCALE[edit]

Transform all rendered elements to specified dimensions

Synopsis
GR.SCALE <x_nexp>, <y_nexp>
Description

The GR.SCALE statement transforms all rendered elements by a factor of <x_nexp> horizontally, and by a factor of <y_nexp> vertically. This includes rendering text in a condensed or expanded font, as needed. GR.SCALE applies to the entire screen, including elements specified before and after the GR.SCALE statement is executed.

For example, GR.SCALE 1,1 has no effect except to cancel any other scaling that might have been specified. GR.SCALE 2,1 stretches all elements to double width. Drawing a 20✕20 square at origin (30,50) achieves a 40✕20 rectangle with origin at (60,50).

Example

GR.SCALE lets a BASIC program be written, assuming some screen size, and then transformed at the time it is run to fit the screen of the Android device on which the program is running. A program written to run on an 800✕480 screen will run on any Android device if it includes code such as the following:

!Specify the dimensions of the screen for which this program is designed
di_width = 800
di_height = 480

!Get the dimensions of the screen on which the program is running
GR.OPEN
GR.SCREEN actual_w, actual_h

!Make this program's graphics work on the actual screen
GR.SCALE actual_w/di_width, actual_h/di_height

Assuming an 800✕480 screen means the program is assuming the screen is in Landscape Mode. To work correctly when the device is in, or switches to, Portrait Mode, more complex code is needed.

GR.SET.ANTIALIAS[edit]

Control the Android anti-alias mode

Synopsis
GR.SET.ANTIALIAS {{<enable_lexp>}{, <paint_nexp>}}
Description
The letter A, drawn without anti-aliasing (left) and with anti-aliasing (right). The pixels on an Android device are much smaller than shown and the jaggedness is less evident, but anti-aliasing still leads to more attractive graphics in most cases.

Anti-aliasing is an Android feature that blurs adjacent pixels to create smoother curves. For example, with anti-aliasing enabled, when drawing a black circle on a white background, pixels on the edge of a circle are drawn in gray to avoid jaggedness (aliases) where the edge jumps from one tier of pixels to the next.

Anti-aliasing is enabled by default. It almost always produces a more attractive effect. When drawing polygons, anti-aliasing makes the corners appear to be slightly rounded.

When drawing single pixels that need to appear clearly, anti-aliasing should be disabled; otherwise, the pixel will be diffused among neighboring pixels. Anti-aliasing will also produce a less satisfactory result when drawing horizontal or vertical lines whose width is 1 pixel.


The GR.SET.ANTIALIAS statement affects the anti-aliasing setting:

  • If <enable_lexp> is false (0), then anti-aliasing is disabled.
  • If <enable_lexp> is true (1), then anti-aliasing is enabled.
  • If <enable_lexp> is omitted, then the state of anti-aliasing is reversed.

If <paint_nexp> is omitted, then the change modifies the current paint, and affects subsequent drawing commands. If <paint_nexp> is specified, then the change affects the paint by that number, and does not modify the current paint.

GR.BRIGHTNESS[edit]

Select the light level of the display

Synopsis
GR.BRIGHTNESS <br_nexp>
Description

The GR.BRIGHTNESS statement sets the brightness of the Android display. A value of 0.01 is the darkest level and 1.00 is the brightest.

RFO-BASIC! provides no way to obtain the brightness the user selected. However, when the BASIC program ends, the screen illumination returns to that level.

Paints[edit]

A paint is an RFO-BASIC! data structure that holds all the implicit settings needed to render a graphics element. These include:

  • Transparency, color, and drawing style, which are specified by GR.COLOR.
  • The anti-alias setting, which is specified by GR.SET.ANTIALIAS.
  • The line stroke width, which is specified by GR.SET.STROKE.

It also holds the following settings needed to render text characters on the graphics screen. These include:

  • The font, which is specified by GR.TEXT.SETFONT.
  • Text size, which is specified by GR.TEXT.SIZE.
  • The alignment of text, relative to the specified point on the graphics screen. Alignment is specified by GR.TEXT.ALIGN.
  • Bloating of text, which is specified by GR.TEXT.BOLD. This effect is comparable to boldfacing, but specifying a boldfaced typeface is preferable.
  • Skewing of text, which is specified by GR.TEXT.SKEW. This effect is comparable to italics, but specifying an italic typeface is preferable.
  • Whether the text is underlined, which is specified by GR.TEXT.UNDERLINE.
  • Whether the text is struck through, which is specified by GR.TEXT.STRIKE.
General syntax

The BASIC statements in this section take an optional parameter denoted as <paint_nexp>. This is typically the number of a paint.

  • If you omit <paint_nexp>, or specify a value of -1, the statement affects the current paint. This is the paint that affects the drawing of all elements until the program makes another change to one or more of the settings.
  • If you specify 0, such as providing a variable that has not been used before, then the statement creates a working paint and sets the variable to its number.
  • If you specify some other number that is the number of an existing paint:
    • The statement modifies the setting of the specified paint. Any element drawn using that paint will adopt the modification, and will typically be drawn differently the next time the program executes GR.RENDER.
    • The statement does not affect the current paint, and does not influence the drawing of new elements.
  • If you specify some other number that is not the number of an existing paint, it is a run-time error.
Basic usage

You can use GR.COLOR and other statements without specifying a paint number, to affect the drawing of upcoming elements. Each setting remains in effect unless the program should change it again. Since the statement does not provide <paint_nvar>, it has no way to capture the number of this paint in order to specify it by number.

Advanced usage

A program can capture all the settings in a paint. For example:

GR.COLOR 128,255,0,0,1,NewPaint   % Semi-transparent red, fill but don't draw the outline
GR.TEXT.ALIGN 2,NewPaint          % Text is drawn centered on the specified point
GR.TEXT.SKEW -0.25,NewPaint       % Text is skewed to create an italic effect
GR.PAINT.GET NewPaint             % All of the above become the current paint

Assuming NewPaint is an unused variable, the GR.COLOR statement assigns it to the number of a newly created paint, and the next two statements make further modifications to its contents. The GR.PAINT.GET statement fetches this paint so that it affects elements drawn thereafter.

GR.COLOR[edit]

Specify transparency, color, and drawing style

Synopsis
GR.COLOR {{<alpha_nexp>}{, <red_nexp>}{, <green_nexp>}{, <blue_nexp>}{, <style_nexp>}{, <paint_nvar>}}
Description

The GR.COLOR statement specifies transparency, color, and drawing style for subsequent drawing statements.

Examples
GR.COLOR 255,0,0,0,2

This specifies opaque black and stroke-and-fill style. It applies to subsequent drawing statements that do not specify a paint by number. This example does not save the number of the newly created paint in a variable.

GR.COLOR 100

It is especially useful to omit parameters of GR.COLOR in order to change only certain settings. This example changes only the transparency (to 100/255), leaving the color and drawing style unchanged. It "grays out" elements drawn by subsequent drawing statements.

GR.PAINT.RESET[edit]

Reset the current paint to the default settings

Synopsis
GR.PAINT.RESET {<paint_nexp>}
Description

The GR.PAINT.RESET statement works exactly like a GR.COLOR statement that specifies:

  • Total opaqueness (255)
  • The color black (0,0,0)
  • Filling of shapes (0)

GR.PAINT.RESET also specifies the minimum stroke width (0.0). If the statement includes <paint_nexp>, then these default settings are assigned to an existing paint or a paint is created with the default settings.

GR.PAINT.COPY[edit]

Copy one paint to another

Synopsis
GR.PAINT.COPY {{<src_nexp>}{, <dst_nexp>}}
Description

Given two paint numbers, the GR.PAINT.COPY statement copies all the settings from the source paint to the destination paint. If either parameter is omitted, GR.PAINT.COPY uses the current paint.

Examples
GR.PAINT.COPY s

As <dst_nexp> is omitted, this statement uses the settings of paint number s as the current paint.

GR.PAINT.COPY ,d

As <src_nexp> is omitted, this statement stores the settings of the current paint as paint number d.

GR.PAINT.COPY s,d

This statement modifies paint number d to have the same settings as paint number s.

Graphic objects[edit]

Creating a graphic object adds an element to the Display List. Each RFO-BASIC! statement has parameters that describe what to draw and where. Three other BASIC statements that create graphic objects are GR.TEXT.DRAW, GR.BITMAP.DRAW, and GR.CLIP.

Apart from points, lines, and arcs under certain settings, drawing an element may mean:

  1. Tracing it, according to the color and fill style, stroke width, and anti-aliasing setting specified by the current paint, then
  2. Filling it in, according to the color.

If the style specified by GR.COLOR is 0, BASIC traces the outline of the element. A value of 1 means to fill it in, and 2 means to do both.

GR.POINT[edit]

Draw a single pixel

Synopsis
GR.POINT <obj_nvar>, <x_nexp>, <y_nexp>
Description

The GR.POINT statement draws a point at the location (x, y) specified by <x_nexp> and <y_nexp>, and returns its object number in <obj_nvar>.

By default, the point is a single pixel. If the stroke width is greater than 1, GR.POINT draws a square centered at (x, y). The point's appearance is also affected by the anti-aliasing setting. Unless anti-aliasing is disabled, a single pixel will be blurred with adjacent pixels and may be hard to see.

Modifiable attributes

x, y

See also

The GR.SET.PIXELS statement, below, lets a BASIC program draw many pixels in a single operation, whose coordinates are specified in an array.

GR.LINE[edit]

Draw a line

Synopsis
GR.LINE <obj_nvar>, <x1_nexp>, <y1_nexp>, <x2_nexp>, <y2_nexp>
Description

The GR.LINE statement draws a line between (x1, y1) and (x2, y2), and returns its object number in <obj_nvar>.

The line's appearance is affected by the stroke width and the anti-aliasing setting. By default, anti-aliasing and the stroke width of 1 blur each point on a horizontal or vertical line over two side-by-side pixels. To draw horizontal or vertical lines a single pixel in width, the program should disable anti-aliasing.

Modifiable attributes

x1, y1, x2, y2

GR.RECT[edit]

Draw a rectangle

Synopsis
GR.RECT <obj_nvar>, <left_nexp>, <top_nexp>, <right_nexp>, <bottom_nexp>
Description

The GR.RECT statement draws a rectangle where one corner is at (left, top) and whose opposite corner is at (right, bottom), and returns its object number in <obj_nvar>.

The left and right edges can be exchanged, and the top and bottom edges can be exchanged, and the specified rectangle is drawn without a run-time error. If either pair has the same value, it specifies a width or a height of 0, in which a line segment or a single point may be drawn.

Modifiable attributes

bottom, left, right, top

GR.OVAL[edit]

Draw an oval

Synopsis
GR.OVAL <obj_nvar>, <left_nexp>, <top_nexp>, <right_nexp>, <bottom_nexp>
Description

The GR.OVAL statement draws an oval whose bounding box is a rectangle (as in GR.RECT, just above) extending from (left, top) to (right, bottom), and returns its object number in <obj_nvar>.

If the bounding box is a rectangle, then GR.OVAL draws an oval that is tangent with each side of the bounding box at its midpoint. The oval's major axis is always horizontal or vertical, depending on which dimension of the bounding box is longer; but it can be rotated. If the bounding box is a square, then GR.OVAL draws a circle whose diameter is | left−right | = | top−bottom |.

If the bounding box is a line segment or a single point, then GR.OVAL draws the same thing as GR.RECT with the same parameters would draw.

Modifiable attributes

bottom, left, right, top

See also

A circle can also be drawn by specifying its center and radius using GR.CIRCLE.

GR.CIRCLE[edit]

Draw a circle

Synopsis
GR.CIRCLE <obj_nvar>, <x_nexp>, <y_nexp>, <radius_nexp>
Description

The GR.CIRCLE statement draws a circle whose center is at (x, y) and whose radius is given in <radius_nexp>, and returns its object number in <obj_nvar>. As usual, depending on the style set by GR.COLOR, this may be a circle or a filled-in disc.

Modifiable attributes

radius, x, y

See also

A circle can also be drawn by specifying its horizontal and vertical boundaries, using GR.OVAL.

GR.ARC[edit]

The results of the example program with f=0 and s=0.
The results of the example program with f=0 and s=1.
The results of the example program with f=1 and s=0.
The results of the example program with f=1 and s=1.

Draw an arc

Synopsis
GR.ARC <obj_nvar>, <left_nexp>, <top_nexp>, <right_nexp>, <bottom_nexp>,
 <start_angle_nexp>, <sweep_angle_nexp>, <fill_mode_nexp>
Description

The GR.ARC statement draws an arc-shaped object based on the oval that fits entirely within the bounding box from (left, top) to (right, bottom) that GR.OVAL, would have drawn, and returns its object number in <obj_nvar>.

The arc is the portion of the oval starting at <start_angle_nexp>, measuring clockwise from the right edge of the bounding box, and continuing clockwise through <sweep_angle_nexp>. Both numbers are expressed in degrees.

GR.ARC has four effects, depending on the style (set by GR.COLOR) and the fill mode (the <fill_mode_nexp> parameter of GR.ARC):

Fill mode Style Effect
0 0 The arc is traced
0 nonzero A wedge is drawn consisting of the arc and a straight line between its endpoints. This figure is filled in.
nonzero 0 A pie shape is traced consisting of the arc and lines between each endpoint of the arc and the center of the bounding box.
nonzero nonzero A pie shape is drawn, consisting of the arc and lines between each endpoint of the arc and the center of the bounding box. This figure is filled in.
Example

The following program produced the four illustrations shown in this section. The numbers shown in green were changed to produce the four effects:

f=0  % Fill mode
s=0  % Style
GR.OPEN                % Assumes white background
GR.COLOR 255,0,0,0     % Draw bounding rectangle in opaque black
GR.RECT obj1, 100,100, 500,300
GR.COLOR 255,255,0,0,s % Set opaque red and desired style
GR.SET.STROKE 5        % Wide red line to illustrate
GR.ARC  obj2, 100,100, 500,300, 30, 90, f
GR.RENDER              % Start at 30 deg, continue thru 30+90 deg
PAUSE 10000            % Keep it displayed for ten seconds
Modifiable attributes

bottom, fill_mode, left, right, start_angle, sweep_angle, top

GR.SET.PIXELS[edit]

Draw pixels according to an array

Synopsis
GR.SET.PIXELS <obj_nvar>, <pixels_narray> {, <x_nexp>, <y_nexp>}
Description

The GR.SET.PIXELS statement draws individual pixels on the screen according to a list of x and y coordinates contained in <pixels_narray>, and returns, in <obj_nvar>, an object number in the Display List that refers to the entire set of pixels.

The array can be specified in either of the following ways:

  • Without subscripts, to denote the entire array: name[]
  • With two numbers, denoting the starting position and number of elements: name[start,length]

The number of array elements must be even. In each pair of elements, the first is an x coordinate and the second is a y coordinate, and GR.SET.PIXELS draws a point at the(x, y) coordinate specified by the pair.

If the parameters <x_nexp> and <y_nexp> are present, they are a relocation to be added to each location in the array to determine where the corresponding point is drawn. This means that the array can describe a figure, relative to itself, and rely on <x_nexp> and <y_nexp> to specify where to put it on the screen. In addition, by using GR.MODIFY on these attributes, the program can easily move the figure around on the screen. Negative <x_nexp> and <y_nexp> values are valid and result in relocation to the left and upward, respectively. If <x_nexp> and <y_nexp> are omitted, no relocation occurs and the (x, y) pairs in the array are absolute screen positions.

Not only can the program use GR.MODIFY to change the relocation distances, it can assign new values to relevant elements in the array to change the figure that BASIC draws, the next time GR.RENDER occurs.

Modifiable attributes

x, y

GR.POLY[edit]

Draw a polygon from a BASIC list

Synopsis
GR.POLY <obj_nvar>, <list_nexp> {, <x_nexp>, <y_nexp>}
Description

The GR.POLY statement draws a closed polygon, and returns its object number in <obj_nvar>. The <list_nexp> is the number of a numeric List (see Data structures). Starting with list element 1, GR.POLY reads pairs of numbers from the list and interprets them as (x, y) coordinates of a point on the graphics screen. If there is only one pair of numbers, GR.POLY has no effect. Otherwise, GR.POLY draws lines from point to point, until reaching the end of the list, then draws a line back to the first point specified in the list. The process of drawing a line is as specified for the GR.LINE statement. It uses the settings in the current paint, which means that it may fill in the polygon if the fill style of GR.COLOR says to do so.

If the parameters <x_nexp> and <y_nexp> are present, they are a relocation to be added to each location in the list to determine where the corresponding point is drawn. As with GR.SET.PIXELS above, the list may describe a polygon relative to itself, and rely on <x_nexp> and <y_nexp> to specify where to put it on the screen. In addition, by using GR.MODIFY on these attributes, the program can easily move the polygon around on the screen. Negative <x_nexp> and <y_nexp> values are valid and result in relocation to the left and upward, respectively. If <x_nexp> and <y_nexp> are omitted, no relocation occurs and the (x, y) pairs in the list are absolute screen positions.

The same list can be used in different GR.POLY statements, and the statements may specify a paint that has a different color, stroke width, and fill mode.

The program can use GR.MODIFY to change the relocation distances, and to change the list number that defines the polygon. It can also assign new values to relevant elements in the list to change the shape of the polygon that BASIC draws, the next time GR.RENDER occurs. This includes adding and removing points.

When GR.POLY is executed, or when the program changes the list using GR.MODIFY, the specified list must have an even number of elements, 4 or greater, so as to specify at least a line segment. If the program modifies the list, then subsequent GR.RENDER operations silently ignore violations of this rule: If the list now contains an odd number of elements, GR.RENDER does not use the final coordinate pair; and if the list now contains fewer than 4 elements, then GR.RENDER does not draw the polygon at all.

Modifiable attributes

list, x, y

Examples

The program Sample Programs/f30_poly.bas, included in the RFO-BASIC! distribution, provides several working examples of GR.POLY.

Graphic text[edit]

The text output screen makes it easy to output text, such as with the PRINT statement, but without any special effects, even color. An RFO-BASIC! program can draw text on the graphics screen and take detailed control over things like size, color, exact location, and other typography.

Every character in graphic text is a shape. In rendering that character, BASIC may trace its outline, as it would draw any line or arc; and may then fill in the shape, depending as usual on the fill style that is set by GR.COLOR.

Only the GR.TEXT.DRAW statement draws text onto the graphics screen. There are many other GR.TEXT statements that set the rules for drawing text. These settings are stored in a paint, described above.

GR.TEXT.DRAW[edit]

Draw text on the graphics screen

Synopsis
GR.TEXT.DRAW <obj_nvar>, <x_nexp>, <y_nexp>, <text_sexp>
Description

The GR.TEXT.DRAW statement draws the contents of <text_sexp> as a line of text onto the graphics screen, using tracing and drawing settings, such as color, that are contained in the current paint. The entire line of text is an object, and GR.TEXT.DRAW returns its object number in <obj_nvar>.

The text is drawn starting at <x_nexp> and <y_nexp>, which are pixel positions on the graphics screen.

The horizontal position of the text, specified by <x_nexp>, is by default the left edge of the text. However, a program can use GR.TEXT.ALIGN to make GR.TEXT.DRAW statements accept the center or the right edge.

The vertical position of the text, specified by <y_nexp>, is the position of the text baseline. This is the line for the bottoms of any capital letters, and of most lowercase letters. On letters with descenders, such as "g", the character extends below the baseline. Consequently, the BASIC program should avoid two things:

  • Specifying <y_nexp> close to 0, to write to the "top line" of the graphics screen. This instead puts most of the text off the top of the screen. Only the descenders would be visible.
  • Specifying <y_nexp> close to the height of the screen, to write to the "bottom line." The program should specify a smaller number so that the descenders are on the screen. This may depend on the font being used.
Modifiable attributes

text, x, y (If using GR.MODIFY to modify text, the new value must be a string representing the new text to draw.)

Example

There is a primitive but complete example of drawing text at GR.RENDER.

See also

See Text measurement below for:

  • A more detailed discussion of the height of text drawn onto the graphics screen, including certain non-English characters.
  • BASIC statements that measure the dimensions of text if it were drawn on the graphics screen.
  • Formulas to tell if text will fit on the screen.

Fonts[edit]

A font is the style of the characters in which RFO-BASIC! draws text. Typical Android devices have a monospace font (a font in which all the characters have equal width), a serif font (in which characters have "feet" to enhance readability, like the fonts in a newspaper), and a sans-serif (without serif) font, which looks simpler and more modern.

GR.TEXT.SETFONT[edit]

Set the font in which text is drawn

Synopsis
GR.TEXT.SETFONT {<font_exp> {, <style_sexp>} {,<paint_nexp>}}
Description

The GR.TEXT.SETFONT statement selects a font in which subsequent text is drawn. If <paint_nexp> is present, it is the number of a paint in which the setting is stored; if omitted, the statement affects the current paint.

The <font_exp> parameter specifies the font. If it is a string expression, it must specify one of the font families available on the Android device, or else the default font is used, which is usually sans serif. The string can use capital or lowercase letters. Fonts called monospace, serif, and sans serif are available on all Android devices. More recent Android versions also support sans-serif, sans-serif-light, sans-serif-condensed, and sans-serif-thin.

If <font_exp> is a string, then <style_sexp> can specify the style, again using capital or lowercase letters. If it is not one of the following, or is omitted, or the font is monospace, then neither boldfacing nor italics is in effect:

  • bold (or b) for boldfacing
  • italic (or i) for italics
  • bold_italic (or bi) for both effects

If <font_exp> is a numerical expression, it must be a font pointer value to a user font that the FONT.LOAD statement returned. In this case, BASIC ignores <style_sexp>. You cannot load a font, such as Palatino, and specify italic, but you may be able to load Palatino Italic.

If <font_exp> is omitted entirely, then GR.TEXT.SETFONT uses the user font most recently loaded by FONT.LOAD and not deleted. If there are no such fonts, then it reverts to the default font.

GR.TEXT.TYPEFACE[edit]

Set the font in which text is drawn (deprecated)

Synopsis
GR.TEXT.TYPEFACE {{<font_nexp>} {, <style_nexp>} {,<paint_nexp>}}
Description

The GR.TEXT.TYPEFACE statement selects a font in which subsequent text is drawn. If <paint_nexp> is present, it is the number of a paint in which the setting is stored; if omitted, the statement affects the current paint.

GR.TEXT.TYPEFACE is older and less powerful than the GR.TEXT.SETFONT statement described above. It is limited to the four built-in fonts that have numerical codes. The numerical parameters are optional, and have the following effects:

<font_nexp> <style_nexp>
Value Effect Value Effect
1 or omitted Default font (usually sans-serif) 1 or omitted Normal (not bold or italic)
2 Monospace
(<style_nexp> is ignored)
2 Bold
3 Sans-serif 3 Italic
4 Serif 4 Bold and italic

GR.TEXT.SIZE[edit]

Specify the size (height) of text

Synopsis
GR.TEXT.SIZE {{<size_nexp>}{,<paint_nexp>}}

The GR.TEXT.SIZE statement specifies the height of text, in pixels. BASIC will render text in a size such that characters entirely fit in <size_nexp> pixels, even characters with diacritical marks above the letter, and characters with descenders, such as "g".

Character width varies along with height, to preserve the font as designed. There is no option to stretch text by a specified percentage. To obtain characters wider or narrower than those designed into the font, here are several options:

  • Obtain a font with Condensed, Expanded, or Oblique style designed into it.
  • Use GR.SCALE to stretch or shrink everything written to the screen.
  • For the text that is to be condensed or expanded, use Draw-Into Mode to draw the text into a bitmap, then display the bitmap with altered dimensions. See the example at GR.BITMAP.DRAWINTO.END.

Other typography[edit]

GR.TEXT.UNDERLINE[edit]

Specify underlining

Synopsis
GR.TEXT.UNDERLINE {{<enabled_lexp>}{,<paint_nexp>}}
Description

The GR.TEXT.UNDERLINE statement determines whether text is drawn with a line beneath it. If <enabled_lexp> has the value 0, underlining is disabled. If it has any other value, underlining is enabled. If the parameter is omitted entirely, underlining is set to the opposite of what it was.

GR.TEXT.STRIKE[edit]

Specify strikethrough (overstrike)

Synopsis
GR.TEXT.STRIKE {{<enabled_lexp>}{,<paint_nexp>}}
Description

The GR.TEXT.STRIKE statement determines whether text is drawn with a line across it (struck out). If <enabled_lexp> has the value 0, strikethrough is disabled. If it has any other value, strikethrough is enabled. If the parameter is omitted entirely, strikethrough is set to the opposite of what it was.

Strikethrough is a technique sometimes used to show that text has been deleted, or that information on the screen is no longer in effect.

GR.TEXT.SKEW[edit]

Specify skew (italics)

Synopsis
GR.TEXT.SKEW {{<enabled_nexp>}{,<paint_nexp>}}
Description

The GR.TEXT.SKEW statement determines whether text is drawn skewed, that is, in italics. If <enabled_lexp> has the value 0, skewing is disabled. If it has any other value, skewing is enabled. If the parameter is omitted entirely, skewing is set to the opposite of what it was.

It is more attractive to use a font where font designers have designed italic characters, than to use a font where they have not, and ask BASIC to render italics by simple skewing. Therefore, instead of using GR.TEXT.SKEW, the following techniques are preferred:

  • Specify italics when selecting a font, such as with GR.TEXT.SETFONT "serif", "italic"
  • Load a user font designed with italics, such as Helvetica Italic

However, if the Android device has a font and does not have the corresponding italic font, then there is no alternative to GR.TEXT.SKEW except to not show italics at all.

GR.TEXT.BOLD[edit]

Specify boldfacing

Synopsis
GR.TEXT.BOLD {{<enabled_lexp>}{,<paint_nexp>}}
Description

The GR.TEXT.BOLD statement determines whether text is drawn in boldface. If <enabled_lexp> has the value 0, boldfacing is disabled. If it has any other value, boldfacing is enabled. If the parameter is omitted entirely, boldfacing is set to the opposite of what it was.

It is more attractive to use a font where font designers have designed boldfaced characters, than to use a font where they have not, and ask BASIC to render boldfaced characters by computation. Therefore, instead of using GR.TEXT.BOLD, the following techniques are preferred:

  • Specify boldfacing when selecting a font, such as with GR.TEXT.SETFONT "serif", "bold"
  • Load a user font designed with boldface, such as Helvetica Bold

However, if the Android device has a font and does not have the corresponding boldface font, then there is no alternative to GR.TEXT.BOLD except to not show boldfacing at all.

Yet another technique for producing fatter characters is to set the fill style of GR.COLOR to 2 (stroke-and-fill) and use GR.SET.STROKE to set a stroke width much greater than 1. (Suitable values will depend on the text size and on the number of pixels on the Android device.) However, again, this method produces boldfacing by algorithm, which is likely to be less attractive than using a font with boldfacing designed into the characters.

Related techniques[edit]

There are several useful techniques that can also be achieved by taking advantage of the fact that drawing text is divided into tracing and filling shapes.

Outline

By setting the fill style of GR.COLOR to 0 (stroke and do not fill), text can be drawn as an outline and not filled in. This is an alternative to graying-out text, for instance, to indicate to the user options that are temporarily irrelevant or disabled, with less confusion than removing the options from the screen entirely.

Shadowing

By setting GR.COLOR to opaque white with a fill style of stroke-only, drawing text, setting GR.COLOR to a dark color with a fill style of fill-only, then drawing the same text, a program can produce text with contrasting edges. For example, such text can be drawn on top of a bitmap with good visibility no matter whether it lands over a light or a dark area of the bitmap.

Text measurement[edit]

GR.TEXT.ALIGN[edit]

Specify text alignment

Synopsis
GR.TEXT.ALIGN {{<align_nexp>}{,<paint_nexp>}}
Description

The GR.TEXT.ALIGN statement governs how subsequent GR.TEXT.DRAW statements interpret their <x_nexp> parameters. This parameter normally marks the left edge of the box where GR.TEXT.DRAW draws the text. However:

  • If <align_nexp> is 2, then GR.TEXT.DRAW statements will interpret their <x_nexp> as the center of the text.
  • If <align_nexp> is 3, then GR.TEXT.DRAW statements will interpret their <x_nexp> as the right edge of the text.

If <align_nexp> has any other value, or is omitted entirely, GR.TEXT.DRAW reverts to positioning text so that the horizontal position parameter gives the left edge.

A program can locate text exactly where desired; GR.TEXT.ALIGN merely simplifies the job of specifying it. When drawing several lines that are to appear centered around the same horizontal position, specifying GR.TEXT.ALIGN 2 lets the program use this position as the <x_nexp> for all those lines. When drawing several lines that are to be right-justified, specifying GR.TEXT.ALIGN 3 lets the program supply the right edge to all the GR.TEXT.DRAW statements. Without this simplification, the program would have to compute the position of each line based on the rendered width of the text.

See also

The following Text measurement statements are how a program performs such computations.

GR.TEXT.HEIGHT[edit]

Measure the height of graphic text

Synopsis
GR.TEXT.HEIGHT {<height_nvar>} {, <up_nvar>} {, <down_nvar>}
Description
Portions of the characters in red are the descenders. The thicker gray line is the baseline. Characters such as the Polish letter "Ż" are off the bounds of this diagram.

The GR.TEXT.HEIGHT statement obtains information on the vertical size of text that would be drawn using the current paint. (RFO-BASIC! provides no way to compute the actual height occupied by text that was drawn.)

If <height_nvar> is present, GR.TEXT.HEIGHT sets it to the height in pixels of most text in most languages. If the program used GR.TEXT.SIZE, then this value is the value it specified.

Some characters require additional space. For example, "É" in French and Spanish, and "Ż" in Polish, have a diacritical mark above a capital letter. Any font that has this character renders it above the height specified in GR.TEXT.SIZE. The dot is above the entire illustration. If <up_nvar> is specified, GR.TEXT.HEIGHT sets it to the distance in pixels of the tallest character above the baseline. This is always a negative number, because it is a distance from the baseline back toward the top of the screen.

If <down_nvar> is specified, GR.TEXT.HEIGHT sets it to the height of the zone occupied by descenders. This is a positive value, and again, measured from the baseline. Therefore:

  • The sum of these two numbers (actually, down − up since up is a negative number) is the space that must be allowed to accommodate text in the most extreme case.
  • When GR.TEXT.DRAW draws text at vertical position y, the lowest vertical position that descenders could occupy is y + down, and the highest vertical position that a diacritical mark above a capital letter could occupy is y + up.
  • Excluding these foreign characters, text will not range above y + down − height.

GR.TEXT.WIDTH[edit]

Measure the width of graphic text

Synopsis
GR.TEXT.WIDTH <width_nvar>, <text_exp>
Description

The GR.TEXT.WIDTH returns, in <width_nvar>, the width of graphic text.

  • If <text_exp> is a string, then GR.TEXT.WIDTH returns the number of horizontal pixels it would take to draw that string as graphic text, using the settings in the current paint, such as the typeface, size, and style specified most recently.
  • If <text_exp> is numeric, then its value must be the object number returned by a GR.TEXT.DRAW statement, or else it is a run-time error. GR.TEXT.WIDTH returns the number of horizontal pixels that the GR.TEXT.DRAW statement would use if its text element were rendered right now. (If the program uses GR.MODIFY, or modifies the relevant paint, before calling GR.RENDER, then this value might become inaccurate.)

GR.GET.TEXTBOUNDS[edit]

Measure the size of text

Synopsis
GR.GET.TEXTBOUNDS <text_exp>, <left_nvar>, <top_nvar>, <right_nvar>, <bottom_nvar>
Description

The GR.GET.TEXTBOUNDS statement gets the boundary rectangle of a string as it would be drawn on the screen.

  • If <text_exp> is a string, then GR.GET.TEXTBOUNDS returns the rectangle that would contain that string as graphic text, using the settings in the current paint, such as the typeface, size, and style specified most recently.
  • If <text_exp> is numeric, then its value must be the object number returned by a GR.TEXT.DRAW statement, or else it is a run-time error. GR.GET.TEXTBOUNDS returns the rectangle that the GR.TEXT.DRAW statement would use if its text element were rendered right now. (If the program uses GR.MODIFY before GR.RENDER, then this value might become inaccurate.)

GR.GET.TEXTBOUNDS reports the dimensions as though a GR.TEXT.DRAW statement were written to draw the text at 0,0. To determine the actual screen space used to hold that text, one must add the x or y values passed to the GR.TEXT.DRAW statement.

Bitmaps[edit]

Bitmaps comprise the illustrations on the graphics screen. Instead of points, lines, shapes, or text, these elements come from a file, or through a use of Draw-Into Mode. The file may be of type .BMP, which describes each point (or bit or pixel) in the illustration, or of type .GIF or .JPG or .PNG, which use coding to compress the size of the file.

The GR.BITMAP.LOAD statement loads a bitmap from storage (internal storage or a device such as a microSD card) into Android memory and returns a bitmap pointer the BASIC program uses to refer to the bitmap. The GR.BITMAP.DRAW statement creates a separate object in the Display List. Like any other drawing statement, this object calls for the illustration to be drawn when the program calls GR.RENDER.

Even if a program uses GR.CLS to discard the Display List (typically to start over and regenerate the information to be rendered on the graphics screen), RFO-BASIC! does not discard bitmaps until the program ends, or calls GR.BITMAP.DELETE. Programs structured with a main loop that calls GR.CLS, regenerates the graphics screen, and calls GR.RENDER to render the information, must not reload the bitmap on each pass through the main loop (unless they discard the bitmap after rendering), or they will quickly exhaust the available memory.

Whether or not the stored version of the bitmap uses techniques to reduce file size, the in-memory version of the bitmap uses four bytes of memory for each pixel. So a 400-by-400-pixel bitmap uses 400✕400✕4 = 640,000 bytes. Any BASIC statement that creates a bitmap will fail if there are insufficient memory bytes available to the program. In this case, the statement returns -1 as the bitmap pointer. The program should always check for this. If the returned pointer is -1, the program can call the GETERROR$() function to get more details about the error.

Some cases that exhaust the available Android memory might not be detected by the GR.BITMAP statements. Subsequent statements might fail, displaying an error message on the console screen. When the user returns to the editor, BASIC highlights a line near the one that exceeded the memory limit. This might not be the exact BASIC statement that exceeded it.

GR.BITMAP.LOAD[edit]

Load a bitmap

Synopsis
GR.BITMAP.LOAD <bptr_nvar>, <filename_sexp>
Description

The GR.BITMAP.LOAD statement creates a bitmap from the file specified in <filename_sexp>. This string is the name of a file containing the bitmap. It is assumed to reside in the <pref base drive>/rfo-basic/data/ directory. However, the string can contain relative pathnames, using ../, to specify a different directory. The bitmap may be on a device such as a microSD card, although the pathname that refers to such a device differs among Android devices.

If GR.BITMAP.LOAD loads a bitmap, <bptr_nvar> is the bitmap pointer the program uses to refer to the bitmap, such as in a subsequent GR.BITMAP.DRAW statement. If it does not load a bitmap, then it sets <bptr_nvar> to -1, which cannot be used as a bitmap pointer. The program should check for this case. It can call the GETERROR$() function for more information about the failure. This function may return:

  • The file or resource does not exist.
  • There is not enough memory available to create the bitmap.

Loaded bitmaps cannot be used with Draw-Into Mode. However, a program can create an empty bitmap, draw a loaded bitmap into it, and draw over the bitmap.

See also

After loading a bitmap, the program can resize it into another bitmap using GR.BITMAP.SCALE. The bitmap is not added to the Display List until the program draws it using GR.BITMAP.DRAW, and as always, it is not visible on the graphics screen until the program renders the Display List by calling GR.RENDER.

GR.BITMAP.SCALE[edit]

Load a scaled bitmap

Synopsis
GR.BITMAP.SCALE <new_bptr_nvar>, <bptr_nexp>, <width_nexp>, <height_nexp> {, <smoothing_lexp>}
Descrption

The GR.BITMAP.SCALE statement creates a bitmap whose contents are those of the previously loaded bitmap <bptr_nexp>, changed to the specified width and height. The statement sets <new_bptr_nvar> to a pointer that refers to the new (derived) bitmap. The original bitmap still exists. If the program loaded the original bitmap only to create a scaled bitmap, then it should delete the original bitmap using GR.BITMAP.DELETE.

GR.BITMAP.SCALE can fail just as GR.BITMAP.LOAD can. The program can react to such failures as it does in the case of GR.BITMAP.LOAD.

Neither <width_nexp> nor <height_nexp> may be zero. However, either or both may be negative. In this case, the scaled bitmap is flipped in that dimension (left-to-right or upside-down).

Normally, the scaled bitmap is smoothed. This uses image enhancement to increase the visual attractiveness of the scaled bitmap. If the optional <smoothing_lexp> parameter is present and if its value is 0, then the scaled bitmap is not smoothed. Instead, if either height or width is reduced from the original bitmap, this is achieved by removing entire rows or columns of pixels. If either height or width is increased from the original bitmap, this is achieved by duplicating entire rows or columns of pixels.

GR.BITMAP.CROP[edit]

Load a cropped bitmap

Synopsis
GR.BITMAP.CROP <new_bptr_nvar>, <bptr_nexp>, <x_nexp>, <y_nexp>, <width_nexp>, <height_nexp>
Descrption

The GR.BITMAP.CROP statement creates a bitmap whose contents are a rectangular piece of the previously loaded bitmap <bptr_nexp>, starting at the upper-left corner given by (<x_nexp>, <y_nexp>), and with the specified width and height. The statement sets <new_bptr_nvar> to a pointer that refers to the new (derived) bitmap. The original bitmap still exists. If the program loaded the original bitmap only to create a cropped bitmap, then it should delete the original bitmap using GR.BITMAP.DELETE.

The cropped bitmap is exactly the size of the specified rectangular region of the original bitmap. To obtain a bitmap with a different size — for example, to take a piece of the original bitmap and produce a bitmap of the same dimensions, consisting only of this piece — pass <new_bptr_nvar> as the <bptr_nexp> in a call to GR.BITMAP.SCALE.

GR.BITMAP.CROP can fail just as GR.BITMAP.LOAD can. The program can react to such failures as it does in the case of GR.BITMAP.LOAD.

GR.BITMAP.DRAW[edit]

Draw a bitmap

Synopsis
GR.BITMAP.DRAW <obj_nexp>, <bptr_nexp>, <x_nexp>, <y_nexp>
Description

The GR.BITMAP.DRAW statement draws the bitmap whose bitmap pointer is <bptr_nexp>. The statement creates an object in the Display List so that the bitmap appears on the graphics screen, with its upper-left corner at (<x_nexp>, <y_nexp>), when the program renders the graphics screen with GR.RENDER.

If the current paint has an alpha value other than 255 (opaque), then the bitmap is drawn on top of what was previously on that region of the graphics screen, with the specified degree of transparency.

Modifiable attributes

bitmap, x, y

GR.BITMAP.DELETE[edit]

Delete a bitmap

Synopsis
GR.BITMAP.DELETE <bptr_nexp>
Description

The GR.BITMAP.DELETE statement releases the specified bitmap from Android memory. The memory the bitmap used is available for other uses by the BASIC program.

The program should delete bitmaps from memory if it only loaded them to create a scaled bitmap using GR.BITMAP.SCALE, or a cropped bitmap using GR.BITMAP.CROP, once the bitmap has served that purpose.

Deleting a bitmap does not remove objects in the Display List that refer to the bitmap, such as those created by the GR.BITMAP.DRAW statement. Unless the program applies GR.HIDE to such objects, or uses GR.CLS and then regenerates the Display List to not refer to bitmaps it has deleted, the GR.RENDER statement will fail.

Other bitmap statements[edit]

The statements in this section can be used either with bitmaps loaded from storage by GR.BITMAP.LOAD, or blank bitmaps created by GR.BITMAP.CREATE and drawn into using Draw-Into Mode.

GR.BITMAP.SIZE <bptr_nexp>, <width_nvar>, <height_nvar>
The GR.BITMAP.SIZE statement returns the dimensions of the specified bitmap in <width_nvar> and <height_nvar>.
GR.BITMAP.SAVE <bptr_nexp>, <filename_sexp>{, <quality_nexp>}
The GR.BITMAP.SAVE statement saves the specified bitmap into a stored file whose name is <filename_sexp>, which is assumed to be in the directory <pref base drive>/rfo-basic/data/. If the filename ends in ".jpg" then the bitmap is saved as a file in the JPEG format. Otherwise, the bitmap is saved as a file in the PNG format.
GR.GET.BMPIXEL <bptr_nexp>, <x_nexp>, <y_nexp>, <alpha_nvar>, <red_nvar>, <green_nvar>, <blue_nvar>
The GR.GET.BMPIXEL statement analyzes a single pixel of the specified bitmap, at pixel coordinates (x, y), and returns in the variables its alpha (transparency), red, green, and blue components. The pixel coordinates must be valid for the size of the bitmap.
GR.BITMAP.FILL <bptr_nexp>, <x_nexp>, <y_nexp>
The GR.BITMAP.FILL statement performs a flood-fill of the specified bitmap. Starting with the pixel at coordinates (x, y), it sets that pixel, and any adjacent area of pixels of the same color, to the color of the current paint.
If the specified bitmap was drawn using anti-aliasing, then boundaries between graphic elements are blurred to appear smoother. This means that pixels on the boundary will not be exactly the same color as the rest of the area, and the flood-fill will not reach to the exact edge of the area.

Draw-Into Mode[edit]

Normally, the drawing statements of RFO-BASIC! build a Display List of objects, and calling GR.RENDER renders the corresponding elements onto the graphics screen. The objects can be moved, rotated, and modified, affecting their appearance the next time the program renders the Display List.

In Draw-Into Mode, BASIC instead draws every specified element into a specified bitmap. Elements do not receive numbers that would make it easy to modify the elements later, and they are not added to a Display List. It is still true that elements drawn into a bitmap can be modified by elements drawn into it later in time. The bitmap itself does not appear in the Display List until explicitly drawn with GR.BITMAP.DRAW, and does not appear on the graphics screen until the Display List is rendered with GR.RENDER.

GR.BITMAP.CREATE[edit]

Create a bitmap to be drawn into

Synopsis
GR.BITMAP.CREATE <bptr_nvar>, <width_nvar>, <height_nvar>
Description

The GR.BITMAP.CREATE statement creates an empty bitmap of the specified width and height. This is not limited to the size of the physical screen; the program can prepare a large bitmap and can crop pieces of it for actual display. The statement returns <bptr_nvar>, a bitmap pointer that the program can use to refer to the new bitmap.

The new bitmap requires width✕height✕4 bytes of memory. GR.BITMAP.CREATE can fail just as GR.BITMAP.LOAD can. The program can react to such failures as it does in the case of GR.BITMAP.LOAD.

GR.BITMAP.DRAWINTO.START[edit]

Start Draw-Into Mode

Synopsis
GR.BITMAP.DRAWINTO.START <bptr_nexp>
Description

The GR.BITMAP.DRAWINTO.START statement starts Draw-Into Mode. All subsequent drawing statements do not create objects in the Display List, but instead draw directly into the bitmap whose number is <bptr_nexp>. This must be a blank bitmap created by GR.BITMAP.CREATE; it cannot be a bitmap loaded from storage by GR.BITMAP.LOAD. However, preloaded bitmaps can be drawn into <bptr_nexp> during Draw-Into Mode.

While BASIC is in Draw-Into Mode, the <ptr_nexp> returned by any drawing statements is not valid, and the program cannot use any of the usual techniques to affect graphic elements before rendering them, such as moving, hiding, or modifying them.

The bitmap being drawn into has no effect on the graphics screen until the program exits Draw-Into Mode, draws the bitmap normally, using GR.BITMAP.DRAW, and renders the Display List using GR.RENDER.

GR.BITMAP.DRAWINTO.END[edit]

End Draw-Into Mode

Synopsis
GR.BITMAP.DRAWINTO.END
Description

The GR.BITMAP.DRAWINTO.END statement ends Draw-Into Mode and returns RFO-BASIC! to the usual mode, in which drawing statements assemble a Display List to be rendered on the graphics screen by GR.RENDER.

Having drawn into a bitmap during Draw-Into Mode, what the BASIC program does after ending Draw-Into Mode is use the bitmap it was drawing into: Either draw it or derive another bitmap from it by cropping or scaling.

Example

To draw condensed text if a Condensed font is not available, a program could draw the text into a bitmap(Bmp1), compress the entire bitmap into a new bitmap (Bmp2) using GR.BITMAP.SCALE, and draw that bitmap onto the graphics screen:

Output from the example.
OutdoorTmp = 23
GR.OPEN
GR.COLOR 255,0,0,0

!Temporary bitmap is 100 pixels high. GR.TEXT.DRAW puts the baseline at y=90.
!Text size of 80 means numerals are drawn between y=10 and y=90.
GR.BITMAP.CREATE Bmp1,200,100
GR.BITMAP.DRAWINTO.START Bmp1
 GR.TEXT.TYPEFACE 2,2
 GR.TEXT.SIZE 80
 GR.TEXT.DRAW unused,0,90,STR$(OutdoorTmp)
GR.BITMAP.DRAWINTO.END
GR.BITMAP.SCALE Bmp2,Bmp1,100,100   % Copy into new bitmap of half the width
GR.BITMAP.DRAW obj1,Bmp2,0,0        % Draw the second bitmap onto graphic screen
GR.TEXT.DRAW obj2,100,90,"Degrees"  % Add some uncompressed text
GR.RENDER
PAUSE 5000
END

Modifying the Display List[edit]

Every drawing of a point, line, shape, or string of text adds an object to the Display List. The elements are actually rendered on the screen of the Android device only when the program executes GR.RENDER.

As set out in the introduction, one way to structure a program that outputs to the graphics screen is to have a prologue that draws everything, and a main loop that modifies the objects in response to real-time inputs and then calls GR.RENDER.

Each section that defines a BASIC statement that draws, sets out a list of Modifiable attributes. These attributes can be modified by calling GR.MODIFY. In addition, any object in the Display List can be hidden with GR.HIDE — that is, set to inhibit display — and later re-enabled with GR.SHOW. All such modifications take effect the next time the graphics screen is rendered.

GR.MODIFY[edit]

Modify an object in the Display List

Synopsis
GR.MODIFY <obj_nexp>{, <tag_sexp>, <value_exp>}...
Description

The GR.MODIFY statement modifies one or more modifiable attributes of an object in the Display List. The <obj_nexp> parameter must have a value that is the number of such an object, as returned by a BASIC statement that draws a graphic element. The <tag_sexp> parameter must be the name of a modifiable attribute of that kind of object. The <value_exp> parameter contains the new value for that modifiable attribute. Most attributes require that <value_exp> be numeric, but the text attribute of an object created by GR.TEXT.DRAW must be followed by a string value. GR.MODIFY can change only one object at a time, but it can contain any number of tag/value pairs.

For any object in the Display List, the valid tags depend on the BASIC statement that drew the element and thus created the object. A list of valid tags is set out in the definition of that statement, under Modifiable attributes. Every object has two additional modifiable attributes:

  • paint is the number of the paint that contains the settings governing the drawing of that object, such as color, transparency, stroke width, fill style, and so on. This tag can be modified with the number of another paint. For example, a circle that was drawn in opaque black paint can be modified to be drawn in transparent blue paint, the next time it is rendered. This is a simple alternative to re-drawing the element, which also consumes Android memory.
  • alpha is the transparency. Transparency is one component of a paint. However, by specifying alpha, the program can change an object's transparency without having to create or modify paints. This makes it easy to animate fade-out and fade-in effects. Transparency values range from 0 (invisible) to 255 (opaque). The value of 256 in GR.MODIFY is a special case that makes the object use the transparency value in the current paint.
Examples

The following GR.MODIFY statement changes text that was drawn, to reflect current conditions. If a program is using the graphics screen just as a gauge, its main loop may obtain those conditions somehow, execute one or more GR.MODIFY statements like this one, and then do GR.RENDER. The original GR.TEXT.DRAW fixed the size, style, and location of the text, and this GR.MODIFY does not modify those attributes:

GR.MODIFY text_ptr, "text", FORMAT$("-##%.%", OutdoorTemp)

Suppose BM_ptr is the object number of a bitmap drawn by GR.BITMAP.DRAW BM_ptr, galaxy_ptr, 400, 120. Then the program can move it rightward, from 400 to 420, with:

GR.MODIFY BM_ptr, "x", 420

The program can change the object to use a different (pre-loaded) bitmap:

GR.MODIFY BM_ptr, "bitmap", saturn_ptr

These two effects could be achieved in a single GR.MODIFY statement:

GR.MODIFY BM_ptr, "x", 420, "bitmap", saturn_ptr

The following code uses alpha to make an object fade in and out:

DO
 FOR a = 1 TO 255 STEP 10
 GR.MODIFY object, "alpha", a
 GR.RENDER
 PAUSE 250 
 NEXT a

 FOR a = 255 TO 1 STEP -10
 GR.MODIFY object, "alpha", a
 GR.RENDER
 PAUSE 250 
 NEXT a
UNTIL 0
See also

Some drawing statements allow their effects to be modified without using GR.MODIFY:

  • For GR.SET.PIXELS, the program can make changes to the array that specifies the (x, y) coordinates for the pixels to be drawn.
  • For GR.POLY, the program can modify the List structure that gives the (x, y) coordinates with which to draw the polygon.
  • The program can modify a paint, rather than using GR.MODIFY to make an object use a different paint.

GR.HIDE[edit]

Inhibit a graphic element from being rendered

Synopsis
GR.HIDE <obj_nexp>
Description

The GR.HIDE statement inhibits a graphic element from being rendered. The <obj_nexp> parameter must be the number of an object in the Display List. It may be the number of a group, in which case, all elements in the group are hidden.

GR.SHOW[edit]

Allow a graphic element to be rendered

Synopsis
GR.SHOW <obj_nexp>
Description

The GR.SHOW statement allows a graphic element to be rendered. The <obj_nexp> parameter must be the number of an object in the Display List. It may be the number of a group, in which case, all elements in the group are shown.

All graphic elements are renderable by default, though none is actually rendered until a call to GR.RENDER. There is no reason to use GR.SHOW unless the program had hidden elements by calling GR.HIDE.

GR.SHOW.TOGGLE[edit]

Reverse the hidden status of a graphic element

Synopsis
GR.SHOW.TOGGLE <obj_nexp>
Description

The GR.SHOW.TOGGLE statement reverses the hidden status of a graphic element. The <obj_nexp> parameter must be the number of an object in the Display List. If <obj_nexp> had been hidden, then GR.SHOW.TOGGLE un-hides it, like GR.SHOW. Otherwise, GR.SHOW.TOGGLE hides it, like GR.HIDE. It may be the number of a group, in which case, each elements in the group has its hidden status reversed; those that were hidden become un-hidden, and those that were shown become hidden.

GR.MOVE[edit]

Move a graphic element

Synopsis
GR.MOVE <obj_nexp> {{, <dx_nexp>}{, <dy_nexp>}}
Description

The GR.MOVE statement moves a graphic element in the direction specified by (dx, dy). Both these parameters can be omitted, in which case they default to a value of 0 (the graphic element is not moved in that dimension).

The effect of GR.MOVE is to modify the x and y modifiable attributes of the specified object. Therefore, any subsequent GR.MOVE statement moves the element further in the direction the follow-on statement specifies. GR.MOVE is equivalent, but generally more concise, than modifying these attributes with GR.MODIFY.

The original x and y values are lost. If the program did not store the values, there is no BASIC statement that returns the element to the screen location where it was originally drawn.

The <obj_nexp> parameter can refer to a group, in which case all elements in that group move together (when the graphics screen is next rendered).

Examples
GR.MOVE circle1,1,0   % Move a circle one pixel to the right
GR.MOVE circle1,1     % Equivalent to omit dy
GR.MOVE circle1,0,-5  % Move the circle five pixels up
GR.MOVE circle1,,-5   % Equivalent to omit dx

Examining the Display List[edit]

Normally, a program stores in well-named variables the objects that it might elect to modify later. However, a program may create graphic elements in response to user input, and use the Display List as a database from which it can extract information later, if the need arises. The following statements query the Display List:

GR.GET.TYPE <obj_nexp>, <type_svar>
If <obj_nexp> is the number of an object in the Display List, then GR.GET.TYPE sets <type_svar> to a string value that indicates the BASIC statement that drew it. This may be: arc, bitmap, circle, line, oval, pixels, point, poly, rect, or text.
If <obj_nexp> is the number of a group, then GR.GET.TYPE sets <type_svar> to group. If it is the number of an object created by GR.CLIP, then <type_svar> is clip. If it is the number of an object created by GR.ROTATE, then <type_svar> is rotate. If it is not an object from the Display List, then <type_svar> is the empty string. The program can use GETERROR$() to get details about the error.
GR.GET.PARAMS <obj_nexp>, <param_array$[]>
If <obj_nexp> is the number of an object in the Display List, then GR.GET.PARAMS places in the one-dimensional string array <param_array$[]> all the modifiable attributes of that object, in no particular order. If the array exists, GR.GET.PARAMS overwrites it; otherwise, it creates a new array.
Once obtaining the names of the modifiable attributes with GR.GET.PARAMS, the program can obtain their current values with GR.GET.VALUE and can modify them with GR.MODIFY.
GR.GET.VALUE <obj_nexp> {, <tag_sexp>, <value_var>}...
If <obj_nexp> is the number of an object in the Display List, then for each <tag_sexp> containing a modifiable attribute of that object, GR.GET.VALUE sets <value_var> to the current value of that attribute. GR.GET.VALUE can query only one object at a time, but it can obtain any number of values from it.
Valid values for <tag_sexp> depend on what type of object <obj_nexp> is. This can be determined using GR.GET.TYPE, above. The program can also call GR.GET.PARAMS, below, to enumerate the modifiable attributes of <obj_nexp>. If any <tag_sexp> is not a modifiable attribute of <obj_nexp>, then the corresponding <value_var> is the empty string. Most attributes require that <value_var> be a string variable, but any time that <tag_sexp> contains text, the corresponding <value_var> must be a string variable. If the program violates any of these rules, GR.GET.VALUE does not set the corresponding <value_var>. The program can use GETERROR$() to get details about the error.

Groups[edit]

The RFO-BASIC! program can organize arbitrary objects from the Display List into a group. The group receives an object with a number unique to all others in the Display List. Grouping elements into a group does not affect their rendering, but lets the program easily specify changes to each member of the group.

The program can use the group object, as the <obj_nexp> parameter instead of an object describing a single graphic element, in the following statements:

  • In the GR.MOVE statement, to move each element in the group
  • In the GR.HIDE statement, to hide each element in the group
  • In the GR.SHOW statement, to un-hide each element in the group
  • In the GR.SHOW.TOGGLE statement, to reverse the hidden status of each element in the group

GR.GROUP[edit]

Create a group by naming specific elements

Synopsis
GR.GROUP <group_obj_nvar>{, <obj_nexp>}...
Description

The GR.GROUP statement creates a group and returns the number of its object in <group_obj_nvar>. The program follows this numeric variable with one or more numeric expressions, shown above as <obj_nexp>. Each of these must be a number of an object already in the Display List. Each object becomes a member of the new group.

GR.GROUP creates a List (see Data structures) to hold the numbers of the objects that are members of the group. The program can obtain the number of this List with GR.GET.VALUE and can change the list that belongs to the group using GR.MODIFY.

Modifiable attribute

list

Example

The following is a complete program that creates four red circles, then creates a group containing one of the circles, and uses its membership in the group to move that circle:

GR.OPEN ,,,,,1
GR.COLOR ,255,0,0,2
GR.CIRCLE c1,100,100,40
GR.CIRCLE c2,100,200,40
GR.CIRCLE c3,100,300,40
GR.CIRCLE c4,100,400,40
GR.RENDER : PAUSE 1000            % draw four red circles

GR.GROUP g, c1                    % create a group with one circle
GR.MOVE g, 0, 50                  % move whole group 0 up/down, 50 right
GR.RENDER : PAUSE 1000            % the circle moves

GR.GET.VALUE g, "list", gList     % get the number of the list the group is using
LIST.ADD gList, c2                % add another circle to the group’s list
GR.MOVE g, 0, 50
GR.RENDER : PAUSE 1000            % two circles move

LIST.ADD gList, c3                % add another circle to the group’s list
GR.MOVE g, 0, 50                  % three circles move
GR.RENDER : PAUSE 1000

GR.CLOSE : END

Other Group statements[edit]

GR.GROUP.LIST <group_obj_nvar>{, <list_nexp>}
Rather than create a BASIC List to hold a sequence of parameters, as GR.GROUP does, GR.GROUP.LIST uses an existing List (see Data structures). GR.GROUP.LIST performs no validation of the contents of the List. If <list_nexp> is not the number of an existing List, or if the parameter is omitted, then the resulting group contains no elements.
GR.GROUP.GETDL <group_obj_nvar>
The GR.GROUP.GETDL statement includes every object currently in the Display List in a new group.
GR.GROUP.NEWDL <group_obj_nvar>
The GR.GROUP.NEWDL statement discards the current Display List and installs the specified group as the Display List.

By using GR.GROUP.GETDL and GR.GROUP.NEWDL, the BASIC program could maintain multiple groups and substitute one or the other, from time to time, as the Display List with which to render the graphics screen.

Modifiable attribute

list

Rotation[edit]

The GR.ROTATE.START and GR.ROTATE.END statements add objects to the Display List. These objects do not draw anything by themselves. Instead, they provide that any objects between them in the Display List are rotated before being drawn.

The program must call both GR.ROTATE.START and GR.ROTATE.END to put both objects in the Display List, bracketing the graphic elements that are to be rotated. Any list of renderable objects to be rotated, such as a list passed to GR.NEWDL to create an alternate Display List, must include both objects.

GR.ROTATE.START[edit]

Start a rotation region

Synopsis
GR.ROTATE.START <angle_nexp>, <x_nexp>, <y_nexp>{, <obj_nvar>}
Description

The GR.ROTATE.START statement adds an object to the Display List that provides that subsequent objects are rotated before being drawn. The rotation is by <angle_nexp> degrees in the clockwise direction around the point on the graphics screen given by (<x_nexp>, <y_nexp>) pixels.

Modifiable attributes

angle, x, y

GR.ROTATE.END[edit]

End a rotation region

Synopsis
GR.ROTATE.END {<obj_nvar>}
Description

The GR.ROTATE.END statement adds an object to the Display List that ends a rotation region begun by GR.ROTATE.START. Subsequent objects are not rotated.

Modifiable attributes

None; a program modifies the attributes of a rotation region by applying GR.MODIFY to the object that GR.ROTATE.START creates.

Example
The circular, rotating "compass" background is drawn by the user-defined routine below.

The following user-defined routine shows how the compass point in the nearby illustration can be rotated in any desired direction. The compass point itself is drawn as three nearly parallel lines. The routine draws it pointing North but the two GR.ROTATE statements rotate it appropriately. You might instead define a polygon and pass its index to the routine, which would draw it with GR.POLY.

FN.DEF Compass(xcenter, ycenter, radius, bearing)
 GR.SCREEN w, h       % Get screen dimensions
 GR.SET.STROKE 3      % Temporarily draw with broad lines
                      % Caller specifies the hue;
 GR.COLOR 64,,,,0     % circle (outline, not disc) is drawn semi-transparent
 GR.CIRCLE ignore, xcenter,ycenter, radius
 GR.COLOR 64          % Set transparency for rotating compass point
!The following three GR.LINE elements are rotated by "bearing" degrees
 GR.ROTATE.START bearing, xcenter, ycenter, CompassObject
 radius *= 0.9
 GR.LINE ignore, xcenter,ycenter,          xcenter,ycenter-radius
 GR.LINE ignore, xcenter+(0.02*h),ycenter, xcenter,ycenter-radius
 GR.LINE ignore, xcenter-(0.02*h),ycenter, xcenter,ycenter-radius
 GR.ROTATE.END
 GR.SET.STROKE 0      % Return to the default stroke width
 FN.RTN CompassObject
 FN.END

If the main program regenerated and re-rendered the screen, it would call this routine each time. If the main program used GR.MODIFY on the display elements and then re-rendered, it would not have to call the routine again, but could rotate the compass point with:

GR.MODIFY CompassObject, "angle", NewBearing

Clip regions[edit]

Clipping means that the effect of an RFO-BASIC! drawing statement applies only to a rectangular sub-region of the graphics screen called a clip region. Clip regions can be combined to produce a clip region that is more complex than a single rectangle.

GR.CLIP[edit]

The first example with RO=0 (Intersect)
The first example with RO=1 (Difference)
The first example with RO=2 (Replace)
The first example with RO=3 (Reverse Difference)
The first example with RO=4 (Union)
The first example with RO=5 (XOR)

Start a clip region

Synopsis
GR.CLIP <ptr_nexp>, <left_nexp>, <top_nexp>, <right_nexp>, <bottom_nexp>{, <RO_nexp>}
Description

The GR.CLIP statement does not draw anything, but places an object in the Display List that affects how subsequent drawing statements function. The statement defines a rectangle on the graphics screen by specifying one corner at pixel address (left, top) and the opposite corner at (right, bottom). Usually, any drawing statement that follows GR.CLIP affects only the pixels in this rectangle.

The optional <RO_nexp> parameter is the Region Operator. It affects the meaning of the rectangle. If GR.CLIP is used more than once, <RO_nexp> specifies how the new rectangle interacts with the clip region previously established.

<RO_nexp> value Effect for first GR.CLIP Effect for subsequent GR.CLIP
0 or omitted Clips drawing to the rectangle Intersect — The clip region is the space within both the rectangle and the previous clip region.
1 Clips drawing to everything outside the rectangle Difference — The clip region is the previous clip region, excluding the new rectangle.
2 same as 0 Replace — The rectangle is the clip region; previous clip regions are overridden.
3 inhibits all drawing Reverse difference — The clip region is the rectangle excluding the previous clip region.
4 no effect Union — The clip region is the space within either the rectangle or the previous clip region.
5 same as 1 XOR — The clip region is the space within either the rectangle or the previous clip region, but not both.
Modifiable attributes

bottom, left, right, RO, top.

Examples

The following program defines two clip regions (two intersecting rectangles) and a Region Operator of Intersect. It displays an image, subject to both clip regions. Then it uses GR.MODIFY to modify the Region Operator of the second GR.CLIP (which was initialized to 0 by the number in red) to each of the five other valid values, re-rendering the display for three seconds each:

GR.OPEN
GR.BITMAP.LOAD Bmp1,"Fox.jpg"       % Or use a photo in your rfo-basic/data directory
GR.CLIP obj1, 20,20,   300,150, 0   % Define the first clip region
GR.CLIP obj2, 100,100, 450,250, 0   % Define the second clip region
GR.BITMAP.DRAW obj3,Bmp1,0,0        % Draw clipped photo from upper left corner
GR.RENDER
PAUSE 3000                          % Leave it up for 3 seconds

FOR I=1 TO 5
 GR.MODIFY obj2, "RO", I     % Modify 2nd GR.CLIP to have another Region Operator
 GR.RENDER                   % Re-render it that way
 PAUSE 3000                  % Leave it up for 3 seconds
NEXT I
END

The results of this program are the illustrations on the right side of this section. It is not just that the photograph trimmed; anything the program draws is clipped in the same manner.

To cancel a clip region for subsequent drawing statements, a program would specify a new clip region, comprising the entire screen, with a Region Operator of Replace:

GR.SCREEN wid, ht
GR.CLIP 0,0, wid-1,ht-1, 2

Sources[edit]

Examples[edit]

Manual contents (Statement index)
Language features ArraysData structuresInterrupt routinesUser-defined functions
Interfaces Audio playerBluetoothGraphicsHTMLSocketsSQL
Programming notes Coexisting with Android