gterm GTermDisplay : QOpenGLWindow -> frameSwapped() -> drawing at a low level <-> serial command data stream --> API calls execution on a) thread b) frameSwapped() o.Ä. -> List of QImages as layers, sprites and offscreen images Modes: 1: static single layer framebuffer -> direct drawing in Window framebuffer, persistent between frames, updated as drawing commands are issued offscreen images can be used for sprites 2: dynamic single layer framebuffer -> direct drawing in Window framebuffer, *not* persistent between frames OR erased by command, drawing commands (are buffered and) executed after frameSwapped() offscreen images can be used for sprites 3: multi layer framebuffer -> the Window framebuffer can be used as in 2) on top of that layers and sprites are copied each frame in paintEvent() offscreen images are used for layers and sprites conclusion: The client *may* place layers and sprites into the framebuffer. -> Then it must clear and repaint the screen or at least paint the layers and sprites again whenever it draws to the framebuffer. -> It must clear and repaint the impacted region or everything when a plane or sprite is moved. The client may also *not* use layers and sprites. -> Then it may use the framebuffer in a 'static' way and only update contents as needed, or -> it may use the framebuffer in a 'dynamic' way and clear & redraw everything after each ffb. "Framebuffer" Layout and other Specs ==================================== Background: The background is the window widget's own drawable. The background may be erased to transparency, if possible. The client can draw additively or erase and draw synchronously with ffb. Planes and Sprites: Above the background may hover additional planes and sprites. These can't be implemented as child widgets of the background if this is a QOpenGLWindow. All drawing for Planes and Sprites is therefore done on QImages like offscreen bitmaps and Composition is therefore done manually in paintEvent() or paintGL(). Drawing to the plane or sprite QImage using a QPainter is the same as drawing to the background. Drawing: Drawing is performed on a selected QOpenGLWindow or QImage. There are lines and filled shapes, text, images which use stroke and fill attributes. Drawing may use transformation. Drawing may use clip regions. Machines: Virtual machines which execute a byte code can be programmed to run regular or single shot tasks. They can communicate via global variables which can also be set and read by the client. Keyboard input and mouse pointer: Mouse and keyboard input can be sent to the client or to a virtual machine. The scope of events is configurable, e.g. whether mouse move events are reported. The mouse position and the currently pressed keys can be queried. The mouse pointer can be repositioned, hidden or the sprite can be set by the client. The mouse pointer sprite can be programmed to change shape over certain widgets or regions. Disk storage: Images can be stored and read from disk files on the gterm server. API: If the library is linked with the client, then the client can use API calls. The gterm app can run stand-alone and connect to a serial input: pipe, tcpip stream, sio, bt, ... :cmd arg,arg,arg,... :reset reset all internal state to initial state :push [t,p,c] push internal state (transformations, pen (stroke+fill), clip) :pop pop internal state :key ... response :mouse ... response :tty ... response after reset :ffb response :setstroke argb, w=xx, ... :setfill argb, ... :setclip rect :transform ... :translate dx,dy :rotate rad | deg° :scale fx [,fy] :clear clear whole screen with fill color :line x,y,x,y draw simple line :rect x,y,w,h draw simple rect :circ x,y,w,h draw simpe circle / ellipse :text x,y, font, text :define sprite index, w, h, color_format, [clut_size, clut,] pixels :store sprite name, index, [count] :load sprite name, index, [count] :machine index [global] int|float|point|rect|trans NAME, NAME[SIZE], ... TYPE NAME(ARGs) { TYPE NAME = VALUE; // vdef NAME=VALUE; // assign NAME(VALUEs); // call proc // operators: +-*/&|^<<>> && || ?: () [] get VREF put VALUE } :machine index after TIME run every TIME :machine index run on FFB :machine index run in background :machine index stop|pause|resume|restart.. :msg #index, text send data to machine: get() :msg #index, text response from machine: put()