| Manual |
|
Graphic |
|
14. GRAPHIC LIBRARY
Seed7 provides a portable graphics library. Below is the graphic "hello world" program:
$ include "seed7_05.s7i"; include "dialog.s7i"; const proc: main is func begin messageWindow("hello world"); end func;
This program displays a popup window with the message "hello world". In the popup window there is an OK button, which ends the program. A program that creates an empty window and a message popup is:
$ include "seed7_05.s7i"; include "dialog.s7i"; const proc: main is func begin screen(640, 480); messageWindow("hello world"); end func;
The function screen(640, 480) opens a window with a width of 640 and a height of 480. The window is assigned to the variable curr_win, which is used as the default window by drawing functions.
Displaying an empty window without message box is done with:
$ include "seed7_05.s7i"; include "draw.s7i"; include "keybd.s7i"; const proc: main is func begin screen(640, 480); ignore(getc(GRAPH_KEYBOARD)); end func;
This program waits until a key is pressed. The key is read from GRAPH_KEYBOARD. Without reading from GRAPH_KEYBOARD, the program would terminate immediately. Regarding the keyboard:
- In graphic programs the keyboard is connected to GRAPH_KEYBOARD.
- In console programs the keyboard is connected to CONSOLE_KEYBOARD.
For that reason a graphic program should do the following assignment:
KEYBOARD := GRAPH_KEYBOARD;
Afterwards, it should just use the variable KEYBOARD.
The program below clears the window with a color computed from the keys pressed:
$ include "seed7_05.s7i"; include "draw.s7i"; include "keybd.s7i"; const proc: main is func local var char: command is ' '; begin screen(640, 480); KEYBOARD := GRAPH_KEYBOARD; repeat command := getc(KEYBOARD); clear(color(1009 * ord(command) mod 65536, 4999 * ord(command) mod 65536, 9973 * ord(command) mod 65536)); until command = KEY_ESC; end func;
The function color creates a color from red, green and blue lights in the additive color model. The red, green and blue lights are specified by integer values in the range 0 .. 65535.
Below is a "hello world" program that uses a Seed7 font:
$ include "seed7_05.s7i"; include "draw.s7i"; include "keybd.s7i"; include "text.s7i"; include "stdfont24.s7i"; const proc: main is func local var text: textWindow is text.value; begin screen(203, 45); textWindow := openPixmapFontFile(curr_win); setFont(textWindow, stdFont24); writeln(textWindow, " hello world"); ignore(getc(GRAPH_KEYBOARD)); end func;
The function screen opens a window with a width of 203 pixels and a height of 45 pixels. The window is stored in the global variable curr_win. The function openPixmapFontFile opens a pixmapFontFile for curr_win. Everything written to textWindow is displayed in the current window. The function setFont defines which font should be used. The font stdfont24.s7i is a bitmapFont with a cap-height of 24 pixels. The function writeln displays hello world to the current window with the specified font.
Seed7 fonts are not as perfect as professional fonts. They have the following properties:
- They are open source.
- They are implemented in Seed7.
- No external library is needed.
- Seed7 programs can use them always.
- There are bitmap and vector fonts.
Below is a "hello world" program which writes "hello world" at clicked positions
$ include "seed7_05.s7i"; include "draw.s7i"; include "keybd.s7i"; include "text.s7i"; include "stdfont24.s7i"; const proc: main is func local var text: textWindow is text.value; var char: command is ' '; begin screen(640, 480); textWindow := openPixmapFontFile(curr_win); setFont(textWindow, stdFont24); KEYBOARD := GRAPH_KEYBOARD; repeat command := getc(KEYBOARD); if command = KEY_MOUSE1 then setPosXY(textWindow, clickedXPos(KEYBOARD), clickedYPos(KEYBOARD)); color(textWindow, color(rand(0, 65535), rand(0, 65535), rand(0, 65535))); write(textWindow, "hello world"); end if; until command <> KEY_MOUSE1; end func;
The functions clickedXPos and clickedYPos return the X and Y coordinates of the mouse cursor at the last time when a mouse button was clicked. The function setPosXY sets the current position of a text window to the given X and Y coordinates. There are two functions named color. The inner function color creates a color from random red, green and blue lights. The outer function color sets the foreground color of a text.
The function screen opens the default window (curr_win) of a program. The created window has window decorations such as a title bar and border and it is managed by the window manager. Using screen is convenient if just one window is needed. In case more than one window is needed a new top-level window can be opened with openWindow as well:
$ include "seed7_05.s7i"; include "draw.s7i"; include "keybd.s7i"; const proc: main is func local var PRIMITIVE_WINDOW: redWindow is PRIMITIVE_WINDOW.value; var PRIMITIVE_WINDOW: greenWindow is PRIMITIVE_WINDOW.value; begin redWindow := openWindow(100, 100, 200, 200, "red"); clear(redWindow, light_red); greenWindow := openWindow(400, 100, 200, 200, "green"); clear(greenWindow, light_green); ignore(getc(GRAPH_KEYBOARD)); end func;
The function openSubWindow can be used to open a sub-window inside a parent window. The new sub-window has no window decorations and is not managed by the window manager. Below is a program which uses a sub-window to draw an hourglass at the cursor position:
$ include "seed7_05.s7i"; include "draw.s7i"; include "keybd.s7i"; include "pic32.s7i"; include "time.s7i"; include "duration.s7i"; const proc: main is func local var PRIMITIVE_WINDOW: hourglass is PRIMITIVE_WINDOW.value; begin screen(640, 480); hourglass := openSubWindow(curr_win, 1000, 1000, length(hourglass_pic[1]), length(hourglass_pic)); put(hourglass, 0, 0, createPixmap(hourglass_pic, 1, black)); KEYBOARD := GRAPH_KEYBOARD; setCursorVisible(curr_win, FALSE); repeat setPos(hourglass, pointerXPos(curr_win) - width(hourglass) div 2, pointerYPos(curr_win) - height(hourglass) div 2); wait(30000 . MICRO_SECONDS); until inputReady(KEYBOARD); end func;
The variable hourglass is of type PRIMITIVE_WINDOW. A variable of this type can hold a window (which is on screen) or a pixmap (which is off-screen). The function openSubWindow creates a sub-window inside the parent window curr_win. The window curr_win has a title bar. The window created by openSubWindow does not have a title bar or a border. The function createPixmap is used to create the pixmap of an hourglass by using a picture from the library "pic32.s7i". The function setCursorVisible disables the visibility of the mouse cursor for curr_win. The functions pointerXPos and pointerYPos return the current X and Y coordinates of the mouse cursor. The function setPos is used to position the hourglass to the cursor position (minus half of the width and height of the hourglass).
If openSubWindow is called with an empty window as parent window, an unmanaged top-level window without window decorations is generated. The program below displays an hourglass at the cursor position until a key is pressed:
$ include "seed7_05.s7i"; include "draw.s7i"; include "keybd.s7i"; include "pic32.s7i"; include "time.s7i"; include "duration.s7i"; const proc: main is func local var PRIMITIVE_WINDOW: hourglass is PRIMITIVE_WINDOW.value; begin hourglass := openSubWindow(PRIMITIVE_WINDOW.value, 1000, 1000, length(hourglass_pic[1]), length(hourglass_pic)); put(hourglass, 0, 0, createPixmap(hourglass_pic, 1, black)); KEYBOARD := GRAPH_KEYBOARD; repeat setPos(hourglass, pointerXPos(PRIMITIVE_WINDOW.value) - width(hourglass) div 2, pointerYPos(PRIMITIVE_WINDOW.value) - height(hourglass) div 2); wait(30000 . MICRO_SECONDS); until inputReady(KEYBOARD); end func;
14.2 Reading an image
The library "imagefile.s7i" supports PNG, GIF, JPEG, BMP, ICO, PBM, PGM, PPM, TIFF, TGA, and PCX images.
The program below displays an image whose filename is provided via the command line:
$ include "seed7_05.s7i"; include "imagefile.s7i"; include "draw.s7i"; include "keybd.s7i"; const proc: main is func local var PRIMITIVE_WINDOW: myImage is PRIMITIVE_WINDOW.value; begin if length(argv(PROGRAM)) >= 1 then myImage := readImage(argv(PROGRAM)[1]); if myImage <> PRIMITIVE_WINDOW.value then screen(width(myImage), height(myImage)); put(0, 0, myImage); ignore(getc(GRAPH_KEYBOARD)); end if; end if; end func;
This program uses readImage to decode the image data from the given file. The function checks the file for magic numbers and calls the corresponding read function to read the actual image. If the decoding succeeds, a window with the size of the image is opened with screen. Afterwards, the image is drawn to the window with put. Finally the program waits until a key is pressed.
If the image data is already in a string, a striFile must be used since the string parameter of readImage refers to a path and not to image data. In the example below, a string is fetched from the Internet, and an associated string file is passed to readImage, which decodes the image data:
$ include "seed7_05.s7i"; include "gethttps.s7i"; include "strifile.s7i"; include "imagefile.s7i"; include "draw.s7i"; include "keybd.s7i"; const proc: main is func local var string: imageData is ""; var file: imageStream is STD_NULL; var PRIMITIVE_WINDOW: myImage is PRIMITIVE_WINDOW.value; begin imageData := getHttps("seed7.net/images/header3.png"); imageStream := openStriFile(imageData); myImage := readImage(imageStream); if myImage <> PRIMITIVE_WINDOW.value then screen(width(myImage), height(myImage)); put(0, 0, myImage); ignore(getc(GRAPH_KEYBOARD)); end if; end func;
Note that "seed7.net/images/header3.png" is not prefixed with "https://" like in a URL, since the protocol used is specified by the function name getHttps. For other protocols, functions like getHttp and getFtp are available.
The program below creates a 64x64 pixel sized icon from a given image and stores it as PNG:
$ include "seed7_05.s7i"; include "imagefile.s7i"; include "draw.s7i"; const proc: main is func local var PRIMITIVE_WINDOW: myImage is PRIMITIVE_WINDOW.value; var PRIMITIVE_WINDOW: anIcon is PRIMITIVE_WINDOW.value; begin if length(argv(PROGRAM)) >= 1 then myImage := readImage(argv(PROGRAM)[1]); if myImage <> PRIMITIVE_WINDOW.value then anIcon := getPixmap(myImage, 0, 0, width(myImage), height(myImage), 64, 64, black); writePng(argv(PROGRAM)[1] & "_ico.png", anIcon); end if; end if; end func;
The function getPixmap takes a rectangle from a window or pixmap and scales it to the desired width and height. In the example above the rectangle extends over the whole of the myImage pixmap and it is scaled to 64x64.
14.3 String array images
As an alternative to reading an image from a file, Seed7 supports string array images. Such an image is called a picture and consists of an array of strings where single characters are used to encode the colors of the pixels. E.g.:
const array string: hourglass_pic is []( " bbbbbbbbbbbbbbbbbbbbbbbbbbbbbb ", # Mapping from character to color: " bbbbbbbbbbbbbbbbbbbbbbbbbbbbbb ", # char | color " bb XWWWWWWWWWWWWWWWWWWX bb ", # ------+--------------- " bbXWWWWWWWWWWWWWWWWWWWWXbb ", # space | background color " bbWWXXXXXXXXXXXXXXXXXXWWbb ", # B | light_blue " bbWWX XWWbb ", # G | light_green " bbWWX YYYY XWWbb ", # L | lavender " bbWWX YYYYYY XWWbb ", # M | light_magenta " bbXWWX YYYYYYYY XWWXbb ", # O | orange " bb XWWX YYYYYYYYYY XWWX bb ", # P | light_pink " bb XWWYYYYYYYYYYYYWWX bb ", # R | light_red " bb XWWYYYYYYYYYYWWX bb ", # W | white " bb XWWYYYYYYYYWWX bb ", # X | black " bb XWWYYYYYYWWX bb ", # Y | yellow " bb XWWYYYYWWX bb ", # b | brown " bb XWWYYWWX bb ", # c | light_cyan " bb XWWYYWWX bb ", # d | dark_gray " bb XWWXYYXWWX bb ", # f | forestgreen " bb XWWX YY XWWX bb ", # g | dark_green " bb XWWX YY XWWX bb ", # i | mint " bb XWWX YY XWWX bb ", # l | middle_blue " bb XWWX YY XWWX bb ", # m | dark_magenta " bb XWWX YY XWWX bb ", # n | dark_blue " bbXWWX YYYY XWWXbb ", # p | pink " bbWWX YYYYYY XWWbb ", # r | dark_red " bbWWX YYYYYYYY XWWbb ", # x | light_gray " bbWWX YYYYYYYYYY XWWbb ", # y | middle_gray " bbWWXXXYYYYYYYYYYYYXXXWWbb ", # other | black " bbXWWWWWWWWWWWWWWWWWWWWXbb ", " bb XWWWWWWWWWWWWWWWWWWX bb ", " bbbbbbbbbbbbbbbbbbbbbbbbbbbbbb ", " bbbbbbbbbbbbbbbbbbbbbbbbbbbbbb ");
The code above shows the definition of the picture hourglass_pic, which is provided by the "pic32.s7i" library.
The libraries "pic32.s7i" and "pic16.s7i" contain collections of
pictures. For example:
The function createPixmap can be used to convert pictures into pixmaps. The function createPixmap is defined in the library "pic_util.s7i". The program below writes hourglass_pic as PNG:
$ include "seed7_05.s7i"; include "pic32.s7i"; include "png.s7i"; const proc: main is func local var PRIMITIVE_WINDOW: pixmap is PRIMITIVE_WINDOW.value; begin pixmap := createPixmap(hourglass_pic, 1, black); writePng("hourglass.png", pixmap); end func;
|
|
|
