Graphics

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 screen. 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 graphic 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 parameters of certain elements, or GR.HIDE and GR.SHOW to inhibit some elements from being displayed, and finally executes GR.RENDER.

Graphics operations work in portrait 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 Android device is rotated.
 * Geometry

When drawing an object onto the graphics screen, the location (typically of the 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.

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.
 * Color, transparency, and style

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. signifies black,  signifies bright red, and   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

Even if the program does not save an element's number to refer to it later, the program has still created a small data structure. A program that runs continuously for hours and creates new graphics elements rather than modify existing ones, and does not call GR.CLS periodically, can run out of memory. See also the sidebar at the start of the section on Paints.  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 a 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. (See below.) In this case, BASIC 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 will not appear on the graphics screen unless the program explicitly draws it.

GR.OPEN
Begin graphics operations

GR.OPEN { {}{, }{, }{, }{, }{, }}
 * Synopsis

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.
 * Description

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,  is used, specifying bright white.

If  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  expression 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 will depend 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.

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.
 * Example

GR.CLOSE
End graphics operations

GR.CLOSE
 * Synopsis

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.
 * Description

GR.CLS
Clear the graphics screen

GR.CLS
 * Synopsis

The GR.CLS statement deletes all the data structures of the graphics subsystem, including:
 * Description
 * 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
Render the graphics screen

GR.RENDER
 * Synopsis

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.
 * Description

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.

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
 * Example

Interacting with Android
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
Specify the screen orientation

GR.ORIENTATION 
 * Synopsis

An Android device can be operated in one of two Modes:
 * Description
 * 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  parameter can have one of the following values:

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

GR.SCREEN
Obtain the screen dimensions

GR.SCREEN , {,  }
 * Synopsis

The GR.SCREEN statement obtains the dimensions of the Android display. These include:
 * Description
 * 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 arbitrary points in the BASIC program.

The  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.

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

GR.SCALE
Transform all rendered elements to specified dimensions

GR.SCALE , <y_nexp>
 * Synopsis

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.
 * Description

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 20x20 square at origin (30,50) achieves a 40x20 rectangle with origin at (60,50).


 * Example

Scaling with GR.SCALE does not affect the geometry of touch sensing. If the program uses the GR.TOUCH statements to sense finger touches and if it uses scaling to adapt to having been written for a device with a different screen, the origin and size parameters of the GR.TOUCH statements must be adjusted too. </DIV> 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-by-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

The above example is for a device with an 800-by-480 screen (thus, operating in Landscape Mode). To work correctly when the device is in, or switches to, Portrait Mode, more complex code is needed.

GR.SET.ANTIALIAS
Control the Android anti-alias mode

GR.SET.ANTIALIAS
 * Synopsis

Anti-aliasing is an Android feature that blurs adjacent pixels to create smoother curves. For example, when anti-aliasing is 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.
 * Description

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 must be disabled; otherwise, the single pixel will be diffused among neighboring pixels. This is also the case when drawing 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.

Paints
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.

The BASIC statements in this section take an optional parameter denoted as <paint_nexp>. This is typically the number of a paint.
 * General syntax
 * 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 that had been draw using that paint will 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.

Statements that merely affect the current paint still create and register a paint. This is a small data structure that requires memory. Unless the program periodically calls GR.CLS and rebuilds the graphics screen, a program that runs for a long time will eventually run out of memory. </DIV> 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.
 * Basic 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
 * Advanced usage

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
Specify transparency, color, and drawing style

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

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

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.
 * Examples

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
Reset the current paint to the default settings

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

The GR.PAINT.RESET statement works exactly like a GR.COLOR statement that specifies:
 * Description
 * 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
Copy one paint to another

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

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.
 * Description

GR.PAINT.COPY s As <dst_nexp> is omitted, this statement uses the settings of paint number s as the current paint.
 * Examples

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.