1 |
673 |
markom |
<html>
|
2 |
|
|
|
3 |
|
|
<head>
|
4 |
|
|
<meta http-equiv="Content-Language" content="en-us">
|
5 |
|
|
<meta http-equiv="Content-Type" content="text/html; charset=windows-1252">
|
6 |
|
|
<meta name="GENERATOR" content="Microsoft FrontPage 4.0">
|
7 |
|
|
<meta name="ProgId" content="FrontPage.Editor.Document">
|
8 |
|
|
<title>MicroWindows Architecture</title>
|
9 |
|
|
</head>
|
10 |
|
|
|
11 |
|
|
<body>
|
12 |
|
|
|
13 |
|
|
<h1 align="left"><img border="0" src="file:///C:/My%20Documents/My%20Webs/myweb2/images/clouds.gif" width="72" height="33">Microwindows Architecture</h1>
|
14 |
|
|
|
15 |
|
|
<p align="left">1999/12/04 Copyright (c) 1999 Greg Haerr <<a href="mailto:greg@censoft.com">greg@censoft.com</a>> All Rights Reserved.</p>
|
16 |
|
|
|
17 |
|
|
<p align="left">This is my first cut at getting the architecture and implementation
|
18 |
|
|
spilled out. Please let me know if there's more detail needed in some areas, or
|
19 |
|
|
whether you're confused by my explanations. This document is for educational and
|
20 |
|
|
porting purposes, so please read on.</p>
|
21 |
|
|
|
22 |
|
|
<h3>Contents</h3>
|
23 |
|
|
|
24 |
|
|
<p>1. Architecture<br>
|
25 |
|
|
1.1 Layered Design<br>
|
26 |
|
|
1.2 Device Drivers<br>
|
27 |
|
|
1.2.1 Screen Driver<br>
|
28 |
|
|
1.2.2 Mouse Driver<br>
|
29 |
|
|
1.2.3 Keyboard Driver<br>
|
30 |
|
|
1.3 MicroGUI - Device
|
31 |
|
|
Independent Graphics Engine <br>
|
32 |
|
|
1.4 Applications Programmer
|
33 |
|
|
Interfaces<br>
|
34 |
|
|
1.4.1 Microwindows API<br>
|
35 |
|
|
1.4.2 Nano-X API</p>
|
36 |
|
|
|
37 |
|
|
<p>2. Device-Independent Engine Features<br>
|
38 |
|
|
2.1 Graphics Engine Features
|
39 |
|
|
and Implementation<br>
|
40 |
|
|
2.1.1 Regions<br>
|
41 |
|
|
2.1.2 Clipping<br>
|
42 |
|
|
2.1.3 Line Drawing<br>
|
43 |
|
|
2.1.4 Rectangles, Circles,
|
44 |
|
|
Ellipses<br>
|
45 |
|
|
2.1.5 Polygons<br>
|
46 |
|
|
2.1.6 Area Fills<br>
|
47 |
|
|
2.1.7 Fonts<br>
|
48 |
|
|
2.1.8 Text Drawing<br>
|
49 |
|
|
2.1.9 Color model and
|
50 |
|
|
palettes<br>
|
51 |
|
|
2.1.10 Image Drawing<br>
|
52 |
|
|
2.1.11 Blitting</p>
|
53 |
|
|
|
54 |
|
|
<p>3. Microwindows API<br>
|
55 |
|
|
3.1 Message-passing
|
56 |
|
|
architecture<br>
|
57 |
|
|
3.2 Window creation and
|
58 |
|
|
destruction<br>
|
59 |
|
|
3.3 Window showing, hiding
|
60 |
|
|
and moving<br>
|
61 |
|
|
3.4 Window painting<br>
|
62 |
|
|
3.4.1 Client and screen
|
63 |
|
|
coordinates<br>
|
64 |
|
|
3.4.2 Device contexts<br>
|
65 |
|
|
3.4.3 Graphics drawing API<br>
|
66 |
|
|
3.5 Utility functions<br>
|
67 |
|
|
3.5.1 Setting window focus<br>
|
68 |
|
|
3.5.2 Mouse capture<br>
|
69 |
|
|
3.5.3 Rectangle and Region
|
70 |
|
|
management</p>
|
71 |
|
|
|
72 |
|
|
<p>4. Nano-X API<br>
|
73 |
|
|
4.1 Client/Server model<br>
|
74 |
|
|
4.2 Events<br>
|
75 |
|
|
4.3 Window creation and
|
76 |
|
|
destruction<br>
|
77 |
|
|
4.4 Window showing, hiding
|
78 |
|
|
and moving<br>
|
79 |
|
|
4.5 Drawing to a window<br>
|
80 |
|
|
4.5.1 Graphics contexts<br>
|
81 |
|
|
4.5.2 Graphics drawing API<br>
|
82 |
|
|
4.6 Utility functions</p>
|
83 |
|
|
|
84 |
|
|
<h3>1. Architecture</h3>
|
85 |
|
|
|
86 |
|
|
<h3>1.1 Layered Design</h3>
|
87 |
|
|
|
88 |
|
|
<p>Microwindows is essentially a layered design that allows different layers to be used or
|
89 |
|
|
rewritten to suite the needs of the implementation. At the lowest level, screen,
|
90 |
|
|
mouse/touchpad and keyboard drivers provide access to the actual display and other
|
91 |
|
|
user-input hardware. At the mid level, a portable graphics engine is implemented,
|
92 |
|
|
providing support for line draws, area fills, polygons, clipping and color models.
|
93 |
|
|
At the upper level, various API's are implemented providing access to the graphics
|
94 |
|
|
applications programmer. These APIs may or may not provide desktop and/or window
|
95 |
|
|
look and feel. Currently, Microwindows supports the ECMA APIW and Nano-X APIs.
|
96 |
|
|
These APIs provide close compatibility with the Win32 and X Window systems, allowing
|
97 |
|
|
programs to be ported from other systems easily.</p>
|
98 |
|
|
|
99 |
|
|
<h3>1.2 Device Drivers</h3>
|
100 |
|
|
|
101 |
|
|
<p>The device driver interfaces are defined in device.h. A given implementation of
|
102 |
|
|
Microwindows will link at least one screen, mouse and keyboard driver into the
|
103 |
|
|
system. The mid level routines in the device-independent graphics engine core then
|
104 |
|
|
call the device driver directly to perform the hardware-specific operations. This
|
105 |
|
|
setup allows varying hardware devices to be added to the Microwindows system without
|
106 |
|
|
affecting the way the entire system works.</p>
|
107 |
|
|
|
108 |
|
|
<h3>1.2.1 Screen Driver</h3>
|
109 |
|
|
|
110 |
|
|
<p>There are currently screen drivers written for Linux 2.2.x framebuffer systems, as well
|
111 |
|
|
as 16-bit ELKS and MSDOS drivers for real-mode VGA cards. The real mode drivers
|
112 |
|
|
(scr_bios.c, vgaplan4.c, mempl4.c, scr_her.c) can be configured to initialize the VGA
|
113 |
|
|
hardware directly, or utilize the PC BIOS to begin and end graphics mode. The
|
114 |
|
|
framebuffer drivers (scr_fb.c, fb.c, fblin?.c) have routines for 1, 2, 4 and 8bpp
|
115 |
|
|
palletized displays, as well as 8, 15, 16, and 32 bpp truecolor displays. The
|
116 |
|
|
framebuffer system works in Linux by opening /dev/fd0 (or getenv("FRAMEBUFFER"))
|
117 |
|
|
and mmap()ing the display memory into a linear buffer in memory. Some display modes,
|
118 |
|
|
like the VGA 4 planes mode, require that OUT instructions be issued by the screen driver,
|
119 |
|
|
while packed pixel drivers typically can get away with just reading and writing the
|
120 |
|
|
framebuffer only. All the graphics mode initialization and deinitialization is
|
121 |
|
|
handled by the Linux kernel. Getting this set up can be a real pain.</p>
|
122 |
|
|
|
123 |
|
|
<p>The screen driver is the most complex driver in the system, but was designed so that it
|
124 |
|
|
can be extremely easy to port new hardware to Microwindows. For this reason, there
|
125 |
|
|
are but a few entry points that must actually talk to the hardware, while other routines
|
126 |
|
|
are provided that allow just the small set of core routines to be used, if desired.
|
127 |
|
|
For example, a screen driver must implement ReadPixel, DrawPixel, DrawHorzLine, and
|
128 |
|
|
DrawVertLine. These routines read and write a pixel from display memory, as well as
|
129 |
|
|
draw a horizontal and vertical line. Clipping is handled at the device-independent
|
130 |
|
|
layer. Currently, all mouse movement, text drawing, and bitmap drawing run on top of
|
131 |
|
|
these low level functions. In the future, entry points will be provided for fast
|
132 |
|
|
text and bitmap drawing capabilities. If the display is palletized, a SetPalette
|
133 |
|
|
routine must be included, unless a static palette that matches the system palette is
|
134 |
|
|
linked into the system. The screen driver, on initialization, returns values telling
|
135 |
|
|
the system the x,y size of the screen, along with the color model supported.</p>
|
136 |
|
|
|
137 |
|
|
<p>Two font models are currently provided, to be linked in at your desire. The
|
138 |
|
|
proportional font model has in-core font tables built from .bdf and other font conversion
|
139 |
|
|
utilities provided. The rom-based font uses the PC BIOS to find the character
|
140 |
|
|
generator table address and has routines to draw that fixed-pitch font format.</p>
|
141 |
|
|
|
142 |
|
|
<p>The screen driver can choose to implement bitblitting, by ORing in PSF_HAVEBLIT into
|
143 |
|
|
the returned flags field. When present, bit blitting allows Microwindows to perform
|
144 |
|
|
off-screen drawing. Microwindows allows any graphics operation that can be performed
|
145 |
|
|
on a physical screen to be performed off-screen, and then copied (bit-blitted) to the
|
146 |
|
|
physical screen. Implementing a blitting screen driver can be fairly complex.
|
147 |
|
|
The first consideration in implementing a blitting driver is whether the low-level display
|
148 |
|
|
hardware can be passed a hardware address for a framebuffer. If so, then the same
|
149 |
|
|
routines that draw to the physical screen can be used to draw to off-screen buffers.
|
150 |
|
|
This is the method used for the linear framebuffer drivers provided for Linux packed-pixel
|
151 |
|
|
displays. The system replaces the mmap()'d physical framebuffer address with a
|
152 |
|
|
malloc()'d memory address and calls the original screen driver entry point. In the
|
153 |
|
|
case where the system doesn't use an actual physical memory address, like when running on
|
154 |
|
|
top of X or MS Windows, then two sets of routines must be written; one to write the the
|
155 |
|
|
underlying graphics system hardware, and another to write to memory addresses. In
|
156 |
|
|
addition, the blit entry point must then know how to copy both ways between the two
|
157 |
|
|
formats. In fact, all four operations, screen-to-memory, memory-to-screen,
|
158 |
|
|
memory-to-memory, and screen-to-screen are supported by Microwindows and may need to be
|
159 |
|
|
performed. And of course the bit blitting routine must be _fast_. See the
|
160 |
|
|
files fblin8.c and mempl4.c for examples of supporting both types of display hardware.</p>
|
161 |
|
|
|
162 |
|
|
<p>If writing your first screen driver, I would recommend you start with the PC BIOS real
|
163 |
|
|
mode driver, scr_bios.c, or take a look at the framebuffer driver, scr_fb.c, which is
|
164 |
|
|
essentially a wrapper around all the fblin?.c routines to read and write various
|
165 |
|
|
framebuffer formats. Don't set the PSF_HAVEBLIT flag at first, and you won't have to
|
166 |
|
|
write a bitblit routine from the start.</p>
|
167 |
|
|
|
168 |
|
|
<p>Note that currently, all SCREENDEVICE function pointers must be filled in to at least a
|
169 |
|
|
void function. For speed reasons, the system always assumes that the function
|
170 |
|
|
pointers are valid. Thus, even if not implementing bitblit, a do-nothing bit-blit
|
171 |
|
|
procedure must be provided.</p>
|
172 |
|
|
|
173 |
|
|
<h3>1.2.2 Mouse Driver</h3>
|
174 |
|
|
|
175 |
|
|
<p>There are three mouse drivers currently included in Microwindows. A GPM driver
|
176 |
|
|
for Linux, mou_gpm.c, as well as a serial port mouse driver for Linux and ELKS,
|
177 |
|
|
mou_ser.c. For MSDOS, an int33 driver mou_dos.c is provided. The provided
|
178 |
|
|
mouse drivers decode MS, PC and Logitech mice formats. A mouse driver's basic
|
179 |
|
|
function is to decode the mouse data and return either relative or absolute data for the
|
180 |
|
|
mouse position and buttons.</p>
|
181 |
|
|
|
182 |
|
|
<p>In addition, Brad LaRonde has written a touch panel driver mou_tp.c, which masquerades
|
183 |
|
|
as a mouse driver. It returns the value of x, y value of the pen on the display
|
184 |
|
|
surface, and can be used like a mouse.</p>
|
185 |
|
|
|
186 |
|
|
<p>Under Linux, the main loop of Microwindows is a select() statement, with file
|
187 |
|
|
descriptors for the mouse and keyboard driver always passed in. If the system that
|
188 |
|
|
Microwindows is running on doesn't support select() or doesn't pass mouse data through a
|
189 |
|
|
file descriptor, a Poll() entry point is provided.</p>
|
190 |
|
|
|
191 |
|
|
<h3>1.2.3 Keyboard Driver</h3>
|
192 |
|
|
|
193 |
|
|
<p>There are two keyboard drivers provided. The first, kbd_tty.c, is used for Linux
|
194 |
|
|
and ELKS systems where the keyboard is opened and read as through a file descriptor.
|
195 |
|
|
The second, kbd_bios.c, read the PC BIOS for keystrokes and is used in MSDOS real
|
196 |
|
|
mode. The keyboard driver currently returns 8-bit data from the keyboard, but
|
197 |
|
|
doesn't decode multi-character function key codes. This functionality will need to be
|
198 |
|
|
added soon, by reading termcap files or the like.</p>
|
199 |
|
|
|
200 |
|
|
<h3>1.3 MicroGUI - Device Independent Graphics
|
201 |
|
|
Engine</h3>
|
202 |
|
|
|
203 |
|
|
<p> The core graphics functionality of Microwindows resides in the device independent
|
204 |
|
|
graphics engine, which calls the screen, mouse and keyboard drivers to interface with the
|
205 |
|
|
hardware. User applications programs never all the core graphics engine routines
|
206 |
|
|
directly, but rather through the programmer API's, discussed in the next sections.
|
207 |
|
|
The core engine routines are separated from the applications API's is for a variety of
|
208 |
|
|
reasons. The core routines will always reside on the server in a client/server
|
209 |
|
|
environment. Also, the core routines use internal text font and bitmap formats that
|
210 |
|
|
are designed for speed and may or may not be the same as the structures used in standard
|
211 |
|
|
API's. In addition, the core routines always use pointers, never ID's, and can then
|
212 |
|
|
be used together to implement more complex functions without always converting handles,
|
213 |
|
|
etc.</p>
|
214 |
|
|
|
215 |
|
|
<p>In Microwindows, the core routines all begin as GdXXX() functions, and are concerned
|
216 |
|
|
with graphics output, not window management. In addition, all clipping and color
|
217 |
|
|
conversion is handled within this layer. The following files comprise the core
|
218 |
|
|
modules of Microwindows:</p>
|
219 |
|
|
|
220 |
|
|
<p> devdraw.c Core graphics
|
221 |
|
|
routines for line, circle, polygon draw and fill, text and bitmap drawing, color
|
222 |
|
|
conversion</p>
|
223 |
|
|
|
224 |
|
|
<p> devclip.c Core
|
225 |
|
|
clipping routines. (devclip2.c is the new y-x-banding algorithm, devclip1.c an older
|
226 |
|
|
method)</p>
|
227 |
|
|
|
228 |
|
|
<p> devrgn.c
|
229 |
|
|
New dynamically allocated routines for intersect/union/subtract/xor region creation.</p>
|
230 |
|
|
|
231 |
|
|
<p> devmouse.c Core routines for keeping
|
232 |
|
|
the mouse pointer updated or clipped from the screen.</p>
|
233 |
|
|
|
234 |
|
|
<p> devkbd.c Core
|
235 |
|
|
keyboard handling routines.</p>
|
236 |
|
|
|
237 |
|
|
<p> devpalX.c Linked in
|
238 |
|
|
static palettes for 1, 2, 4 and 8bpp palletized systems.</p>
|
239 |
|
|
|
240 |
|
|
<p>Section 2 following discusses the MicroGUI graphics engine routines in detail.</p>
|
241 |
|
|
|
242 |
|
|
<h3>1.4 Applications Programmer Interfaces</h3>
|
243 |
|
|
|
244 |
|
|
<p>Microwindows currently supports two different application programming interfaces.
|
245 |
|
|
This set of routines handles client/server activity, window manager activities like
|
246 |
|
|
drawing title bars, close boxes, etc, as well as, of course, handling the programmer's
|
247 |
|
|
requests for graphics output. Both the API's run on top of the core graphics engine
|
248 |
|
|
routines and device drivers. </p>
|
249 |
|
|
|
250 |
|
|
<p>The basic model of any API on top of Microwindows is to hang in initialize the screen,
|
251 |
|
|
keyboard and mouse drivers, then hang in a select() loop waiting for an event. When
|
252 |
|
|
an event occurs, if it's a system event like keyboard or mouse activity, then this
|
253 |
|
|
information is passed to the user program converted to an expose event, paint message,
|
254 |
|
|
etc. If it's a user requesting a graphics operation, then the parameters are decoded
|
255 |
|
|
and passed to the appropriate GdXXX engine routine. Note that the concept of a
|
256 |
|
|
window versus raw graphics operations are handled at this API level. That is, the
|
257 |
|
|
API defines the concepts of what a window is, what the coordinate systems are, etc, and
|
258 |
|
|
then the coordinates are all converted to "screen coordinates" and passed to the
|
259 |
|
|
core GdXXX engine routines to do the real work. This level also defines graphics or
|
260 |
|
|
display contexts and passes that information, including clipping information, to the core
|
261 |
|
|
engine routines.</p>
|
262 |
|
|
|
263 |
|
|
<p>Currently, the Microwindows API code is in win*.c, while the Nano-X API code is in
|
264 |
|
|
nanox/srv*.c.</p>
|
265 |
|
|
|
266 |
|
|
<h3>1.4.1 Microwindows API</h3>
|
267 |
|
|
|
268 |
|
|
<p>The Microwindows API tries to be compliant with the European ECMA APIW standard.
|
269 |
|
|
Currently, there is support for most of the graphics drawing and clipping routines, as
|
270 |
|
|
well as automatic window title bar drawing and dragging windows for movement. The
|
271 |
|
|
Microwindows API is message-based, and allows programs to be written without regard to the
|
272 |
|
|
eventual window management policies implemented by the system. The Microwindows API
|
273 |
|
|
is not currently client/server, and will be discussed in more detail in section 4.</p>
|
274 |
|
|
|
275 |
|
|
<h3>1.4.2 Nano-X API</h3>
|
276 |
|
|
|
277 |
|
|
<p>The Nano-X API is modeled after the mini-x server written initially by David Bell,
|
278 |
|
|
which was a reimplementation of X on the MINIX operating system. It loosely follows
|
279 |
|
|
the X Window System Xlib API, but the names all being with GrXXX() rather than
|
280 |
|
|
X...(). Currently, the Nano-X API is client/server, but does not have any provisions
|
281 |
|
|
for automatic window dressings, title bars, or user window moves. There are several
|
282 |
|
|
groups writing widget sets currently, which will provide such things. Unfortunately,
|
283 |
|
|
the user programs must also then write only to a specific widget set API, rather than
|
284 |
|
|
using the Nano-X API directly, which means that only the functionality provided by the
|
285 |
|
|
widget set will be upwardly available to the applications programmer. (Although this
|
286 |
|
|
could be considerable, in the case that, say Gdk was ported.)</p>
|
287 |
|
|
|
288 |
|
|
<h3>2. Device-Independent Engine Features</h3>
|
289 |
|
|
|
290 |
|
|
<p>This section discusses in the capabilities and implementation of Microwindows' core
|
291 |
|
|
graphics engine in detail. It's purpose is both educational and to allow extending
|
292 |
|
|
an API by understanding how the engine works.</p>
|
293 |
|
|
|
294 |
|
|
<h3> 2.1 Graphics Engine
|
295 |
|
|
Features and Implementation</h3>
|
296 |
|
|
|
297 |
|
|
<p>These routines concern themselves with drawing operations to off-screen or screen
|
298 |
|
|
surfaces. Each routine starts with Gd... and is passed a pointer to the SCREENDEVICE
|
299 |
|
|
structure (PSD) as it's first parameter. The PSD parameter specifies the low level
|
300 |
|
|
display details, like the x, y size of the device and the color model used by the
|
301 |
|
|
hardware, for example. In addition, the actual routines to perform drawing are
|
302 |
|
|
function pointers in this structure. All screen coordinates are of type COORD, and
|
303 |
|
|
specified in device coordinates, that is, offsets from the upper left corner of the
|
304 |
|
|
screen.</p>
|
305 |
|
|
|
306 |
|
|
<p>Colors are always specified as an RGB COLORVAL value into the graphics engine.
|
307 |
|
|
They are then possibly converted to palette indices and sent to the display hardware as
|
308 |
|
|
PIXELVAL values. In the case of 32bpp truecolor displays, no conversion is
|
309 |
|
|
required. The color model will be discussed in detail below.</p>
|
310 |
|
|
|
311 |
|
|
<h3> 2.1.1 Regions</h3>
|
312 |
|
|
|
313 |
|
|
<p>Regions are used to describe arbitrary sets of pixels on the screen. A simple,
|
314 |
|
|
square region of pixels can be described by a single rectangle. More complex sets of
|
315 |
|
|
pixels require more complex data structures. In Microwindows, regions are described
|
316 |
|
|
by an array of non-overlapping rectangles. Currently, there are two different
|
317 |
|
|
implementations of regions in Microwindows, as I've been enhancing the capabilities in
|
318 |
|
|
this area. The original design used a single static array of CLIPRECTs to describe
|
319 |
|
|
complex regions. Any point within any rectangle in the array was considered to be in
|
320 |
|
|
the region. The array wasn't sorted in any particular order, but was always
|
321 |
|
|
guaranteed to contain non-overlapping rectangles. Another global variable,
|
322 |
|
|
clipcount, specified the number of rectangles in the array. This original design had
|
323 |
|
|
no engine entry points for region management, the entire array was passed to the clipping
|
324 |
|
|
functions, described below. </p>
|
325 |
|
|
|
326 |
|
|
<p>In the new design, any number of regions can be created, as the regions (CLIPREGION *)
|
327 |
|
|
are stored as dynamically allocated arrays of rectangles. In this implementation,
|
328 |
|
|
the non-overlapping rectangles are always kept in "y-x" sorted bands, such that
|
329 |
|
|
each band's y height is the same for all rectangles in the band. This means that
|
330 |
|
|
only the x position and width of the rectangles in each band varied. Because of
|
331 |
|
|
this, it is easier to create a set of functions for combining regions, since effectively
|
332 |
|
|
only a single dimension had to be compared for each region operation. The new region
|
333 |
|
|
handling routines allow for creating and destroying regions, as well as combining
|
334 |
|
|
rectangles and regions with regions using Intersection, Union, Subtraction, and Exclusive
|
335 |
|
|
Or. This model allows regions to be implemented apart from the clipping routines,
|
336 |
|
|
unlike the first version. Following are the new region routines:</p>
|
337 |
|
|
|
338 |
|
|
<p>
|
339 |
|
|
GdAllocRegion
|
340 |
|
|
- Create a region<br>
|
341 |
|
|
|
342 |
|
|
GdDestroyRegion
|
343 |
|
|
- Destroy a region<br>
|
344 |
|
|
|
345 |
|
|
GdCopyRegion
|
346 |
|
|
- Copy a region<br>
|
347 |
|
|
GdUnionRectWithRegion - Union a rectangle with
|
348 |
|
|
a region<br>
|
349 |
|
|
|
350 |
|
|
GdIntersectRegion
|
351 |
|
|
- Create a region from the intersection of two regions<br>
|
352 |
|
|
|
353 |
|
|
GdSubtractRegion
|
354 |
|
|
- Create a region from the difference of two regions<br>
|
355 |
|
|
|
356 |
|
|
GdUnionRegion
|
357 |
|
|
- Create a region from the union of two regions<br>
|
358 |
|
|
|
359 |
|
|
GdXorRegion
|
360 |
|
|
- Create a region from the XOR of two regions<br>
|
361 |
|
|
</p>
|
362 |
|
|
|
363 |
|
|
<h3> 2.1.2 Clipping</h3>
|
364 |
|
|
|
365 |
|
|
<p>Clipping in Microwindows is closely tied to the region management code. At any
|
366 |
|
|
point in time, the graphics engine has a single clipping region, that is a set of
|
367 |
|
|
rectangles, defined for any graphics operation. A point is drawn if it is
|
368 |
|
|
"inside" any of the current set of clip rectangles. Two slightly modified
|
369 |
|
|
versions of the clipping algorithm are supplied, devclip1.c for the original, static
|
370 |
|
|
rectangle array, and devclip2.c for the newer dynamically allocated array. A single
|
371 |
|
|
entry point GdSetClipRects, takes the passed region and specifies it's use for all
|
372 |
|
|
subsequent graphics operations. All the drawing routines then use the two additional
|
373 |
|
|
routines to determine whether or not to draw. GdClipPoint takes an x,y point in
|
374 |
|
|
screen coordinates and returns TRUE if the point can be drawn, that is, the point is
|
375 |
|
|
within one of the region rectangles. GdClipArea takes an upper left and lower right
|
376 |
|
|
point, and returns one of the following: CLIP_VISIBLE, if the specified area is completely
|
377 |
|
|
within the region, CLIP_INVISIBLE, if the area is completely not in the region, which
|
378 |
|
|
means that no drawing should be performed, or CLIP_PARTIAL, if a part but not the whole
|
379 |
|
|
area is within the region. A typical graphics primitive will call the screen driver
|
380 |
|
|
with unmodified passed inputs if CLIP_VISIBLE is returned, or return if CLIP_INIVISIBLE is
|
381 |
|
|
returned. In the CLIP_PARTIAL case, the primitive must break up the original request
|
382 |
|
|
into areas that are within the clip region before calling the screen driver. This
|
383 |
|
|
slows down the operation considerably.</p>
|
384 |
|
|
|
385 |
|
|
<p>Because the clipping code is called constantly before drawing operations, Microwindows
|
386 |
|
|
keeps a global cache rectangle of the last rectangle checked with GdClipArea, for speed
|
387 |
|
|
and also to allow the mid level to quickly calculate how partial drawing lengths.</p>
|
388 |
|
|
|
389 |
|
|
<h3> 2.1.3 Line Drawing</h3>
|
390 |
|
|
|
391 |
|
|
<p>Line drawing is the simplest of graphics operations. Microwindows supports
|
392 |
|
|
GdPoint to draw a point, and GdLine to draw a horizontal, vertical or diagonal (using
|
393 |
|
|
Bresenham algorithm) line. Just before any call to the screen driver, a call to
|
394 |
|
|
GdCheckCursor assures that the software cursor is removed prior to drawing.
|
395 |
|
|
GdFixCursor restores the cursor if previously visible.</p>
|
396 |
|
|
|
397 |
|
|
<p>There is a tricky part to line drawing that had to be added during the support for
|
398 |
|
|
multiple API's. This has to do with whether or not the last point in specified line
|
399 |
|
|
segment is drawn or not. There are two schools of thought on this, and to make it
|
400 |
|
|
short, Microwindows supports both of them. The last parameter to GdLine specifies
|
401 |
|
|
whether or not to draw the last point. The Microwindows API doesn't draw the last
|
402 |
|
|
point, but the Nano-X API does.</p>
|
403 |
|
|
|
404 |
|
|
<p>Most drawing functions, including line drawing draw using the "current"
|
405 |
|
|
foreground color, specified using GdSetForeground. In addition a drawing mode,
|
406 |
|
|
currently either MODE_SET or MODE_XOR can be specified using GdSetMode.</p>
|
407 |
|
|
|
408 |
|
|
<h3> 2.1.4 Rectangles,
|
409 |
|
|
Circles, Ellipses</h3>
|
410 |
|
|
|
411 |
|
|
<p>Rectangles, circles and ellipses are drawn using the GdRect and GdEllipse
|
412 |
|
|
routines. A circle is an ellipse with the same x and y radius. As with lines,
|
413 |
|
|
rectangles and ellipses are drawn using the current foreground color and mode.</p>
|
414 |
|
|
|
415 |
|
|
<h3> 2.1.5 Polygons</h3>
|
416 |
|
|
|
417 |
|
|
<p>Microwindows supports polygon drawing by specifying an array of x, y points. The
|
418 |
|
|
points are then connected using the GdLine function. The current foreground color,
|
419 |
|
|
drawing mode, and clip region is used during output.</p>
|
420 |
|
|
|
421 |
|
|
<h3> 2.1.6 Area Fills</h3>
|
422 |
|
|
|
423 |
|
|
<p>Microwindows supports filled rectangular areas using the GdFillRect function. The
|
424 |
|
|
rectangle's outline and contents are filled using the current foreground color.
|
425 |
|
|
Filled circles and ellipses are performed with GdFillEllipse, and polygon fills with
|
426 |
|
|
GdFillPoly. Area filling is implemented through successive calls to the DrawHorzLine
|
427 |
|
|
in the screen driver, and are much faster if fully not clipped.</p>
|
428 |
|
|
|
429 |
|
|
<h3> 2.1.7 Fonts</h3>
|
430 |
|
|
|
431 |
|
|
<p>Both fixed pitch and proportional fonts are supported in Microwindows. Because of
|
432 |
|
|
potentially large differences in display hardware, the actual font format is known only to
|
433 |
|
|
the screen driver, although a set of standard functions are supplied for dealing with
|
434 |
|
|
converted .bdf fonts and Microsoft Windows fonts, if you have a license. The engine
|
435 |
|
|
function GdSetFont specifies a font number that is passed to the driver and used to index
|
436 |
|
|
a static array of linked in fonts. Screen driver entry points GetTextSize return the
|
437 |
|
|
font height and width for a passed string, and GetTextBits returns an individual character
|
438 |
|
|
bitmap. The engine layer uses these values to calculate a clipping region for text
|
439 |
|
|
drawing, as well as to draw the character as a monochrome bitmap.</p>
|
440 |
|
|
|
441 |
|
|
<p>The screen drivers currently supplied implement both fixed pitch PC ROM based fonts, as
|
442 |
|
|
well as a proportional font format that is linked into the screen driver. A few
|
443 |
|
|
conversion programs allow conversion of fonts from different formats to the driver
|
444 |
|
|
format. Bdftobogl converts X Window System .bdf files to Microwindows format.
|
445 |
|
|
Convfnt32 converts raster and truetype Microsoft Windows fonts, if you have a license, to
|
446 |
|
|
Microwindows format. Convrom converts PC ROM bios fonts.</p>
|
447 |
|
|
|
448 |
|
|
<p>A number of free fonts are supplied with the system, a heavier proportional 14x16
|
449 |
|
|
system font, and a sans-serif 11x13 font for title bar and edit box displays. Any
|
450 |
|
|
number of fonts can be linked into the system, and it's fairly easy to dynamically load
|
451 |
|
|
fonts if one writes the routines for it.</p>
|
452 |
|
|
|
453 |
|
|
<h3> 2.1.8 Text Drawing</h3>
|
454 |
|
|
|
455 |
|
|
<p>Text output is performed by first selecting the desired font with GdSetFont, and then
|
456 |
|
|
calling the GdText function. Full text clipping is performed, although currently
|
457 |
|
|
there is no "fast" text output entry point in the screen driver, so each
|
458 |
|
|
character bitmap is grabbed using the GetTextBits entrypoint and then drawn using
|
459 |
|
|
Drawpixel. While this will have to remain the same for partially clipped text, a
|
460 |
|
|
screen driver entry point to draw fast text will probably be required shortly.</p>
|
461 |
|
|
|
462 |
|
|
<p>Text is drawn using the current foreground color. The background is drawn if the
|
463 |
|
|
current "use background" mode set via GdUseBackground is TRUE. In this
|
464 |
|
|
case the background is drawn using the current background color set via
|
465 |
|
|
GdSetBackground. The GdText function also takes a bottomAlign parameter that
|
466 |
|
|
specifies whether the text is to be bottom or top aligned, to help with differing API's.</p>
|
467 |
|
|
|
468 |
|
|
<h3> 2.1.9 Color model and
|
469 |
|
|
palettes</h3>
|
470 |
|
|
|
471 |
|
|
<p>The Microwindows graphics engine requires all colors to be specified as either 24-bit
|
472 |
|
|
RGB color values, or in rare cases, as palette indices for speed. The palette index
|
473 |
|
|
method will only work on systems that have hardware palettes, so it's not
|
474 |
|
|
recommended. All of the upper-level color parameters are specified to the engine
|
475 |
|
|
routines using a COLORVAL value, which is a long containing the desired RGB color, created
|
476 |
|
|
using the RGB() macro. The engine then converts the COLORVAL to a PIXELVAL value,
|
477 |
|
|
which is normally a long also, but on some smaller systems can be compiled as an unsigned
|
478 |
|
|
char. The PIXELVAL value is the actual value passed to any screen driver entry point
|
479 |
|
|
requiring a color. So the mid level routines all work with RGB COLORVALs, while the
|
480 |
|
|
device driver routines all work with PIXELVALs. The graphics engine converts these
|
481 |
|
|
values using two routines, GdFindColor and GdFindNearestColor, described below.</p>
|
482 |
|
|
|
483 |
|
|
<p>GdFindColor takes a hardware independent RGB value and converts it to a hardware
|
484 |
|
|
dependent PIXELVAL pixel value. In the case of 32bpp display drivers, no conversion
|
485 |
|
|
is required. Otherwise for truecolor systems, Microwindows converts the RGB value to
|
486 |
|
|
a 5/5/5 15-bit or 5/6/5 16 bit truecolor value. For 8bpp truecolor displays, the RGB
|
487 |
|
|
value is converted to 3/3/2. For palletized displays, the GdFindNearestColor
|
488 |
|
|
function is called to convert the RGB color to the nearest palette index in the current
|
489 |
|
|
system palette. GdFindNearestColor uses a weighted distance-cubed method to find the
|
490 |
|
|
palette value nearest to the requested color, and returns it. Standard palettes for
|
491 |
|
|
1, 2, 4 and 8bpp are included in the files devpal1, devpal2, devpal4 and devpal8.c.
|
492 |
|
|
These palettes associate an RGB value with an index, but may be overwritten.</p>
|
493 |
|
|
|
494 |
|
|
<p>The GdSetPalette function determines whether there are any free entries in the system
|
495 |
|
|
palette (discussed shortly) and if so, adds entries to the system palette, and calls the
|
496 |
|
|
screen driver SetPalette entry point to set the hardware palette. There is a single
|
497 |
|
|
global variable, gr_firstuserpalentry, that contains the index of the next available
|
498 |
|
|
system palette entry. Initially, this is set to 24. Thus, systems with less
|
499 |
|
|
than 24 total palette entries will never have an available palette entry to remap.
|
500 |
|
|
On systems that do, like 256 color systems, then images requiring more color entries keep
|
501 |
|
|
calling GdSetPalette until the system palette is full. To reset marker, the function
|
502 |
|
|
GdResetPalette is called. This allows upper level API's to distinguish between
|
503 |
|
|
different images and force the system palette to be rewritten.</p>
|
504 |
|
|
|
505 |
|
|
<h3> 2.1.10 Image Drawing</h3>
|
506 |
|
|
|
507 |
|
|
<p>Microwindows supports two styles of images, monochrome and palettized. Monochrome
|
508 |
|
|
images are specified with an IMAGEBITS structure, which is an array of words with 1 bits
|
509 |
|
|
specifying the foreground color and 0 bits the background. The IMAGEBITS bits are
|
510 |
|
|
short-word padded to the width of the bitmap. The GdBitmap routine draws monochrome
|
511 |
|
|
bitmaps, similar to GdText, by drawing all the 1 bits in the foreground color, and the 0
|
512 |
|
|
bits in the background color if the "use background" set by GdUseBackground is
|
513 |
|
|
TRUE.</p>
|
514 |
|
|
|
515 |
|
|
<p>Color bitmaps are specified using a 1, 4 or 8bpp image palette, and an array of indices
|
516 |
|
|
into this palette, all stuffed into an IMAGEHDR structure, and drawn via
|
517 |
|
|
GdDrawImage. First, the system creates a conversion palette by calling
|
518 |
|
|
GdMakePaletteConversionTable, which converts the images' palette entries into system
|
519 |
|
|
indices. At the same time, the system attempts to increase the system palette if
|
520 |
|
|
necessary by calling the GdSetPalette function described above. At the end of this
|
521 |
|
|
operation, the image has a converted palette which necessarily corresponds to the system
|
522 |
|
|
palette. In the case of truecolor hardware, the image's palette entries are
|
523 |
|
|
converted to hardware truecolor pixel values, and output directly.</p>
|
524 |
|
|
|
525 |
|
|
<p>After converting the image color entries the GdDrawImage determines the whether the
|
526 |
|
|
image is clipped, and outputs the image, pixel by pixel. In the future, a blitting
|
527 |
|
|
routine could be used for faster image drawing.</p>
|
528 |
|
|
|
529 |
|
|
<h3> 2.1.11 Blitting</h3>
|
530 |
|
|
|
531 |
|
|
<p>Blitting functionality is required in the screen driver for offscreen drawing
|
532 |
|
|
capability, discussed earlier in the screen drivers section. The engine function
|
533 |
|
|
GdBlit allows upper level APIs to implement copy operations from offscreen memory to the
|
534 |
|
|
display, or vice versa. The blit format is driver specific, and generally only works
|
535 |
|
|
for memory images created by the screen driver during runtime. The upper level APIs
|
536 |
|
|
implement this by allocating a new SCREENDRIVER structure, copying an existing
|
537 |
|
|
SCREENDRIVER structure into it, replacing the address field with a malloc()'d value, and
|
538 |
|
|
setting the PSF_MEMORY bit, which indicates to the display driver that this is now an
|
539 |
|
|
offscreen surface. Any subsequent calls to the engine routines then draw onto this
|
540 |
|
|
surface. When it is desired to copy the offscreen surface back to the physical
|
541 |
|
|
display, the GdBlit routine is called. Currently, only SRCCOPY operations are
|
542 |
|
|
performed, but future plans will add blitting opcodes.</p>
|
543 |
|
|
|
544 |
|
|
<p> </p>
|
545 |
|
|
|
546 |
|
|
<h3>3. Microwindows API</h3>
|
547 |
|
|
|
548 |
|
|
<h3> 3.1 Message-passing
|
549 |
|
|
architecture</h3>
|
550 |
|
|
|
551 |
|
|
<p>The fundamental communications mechanism in the Microwindows API is the message.
|
552 |
|
|
A message consists of a well-known message number, and two parameters, known as wParam and
|
553 |
|
|
lParam. Messages are stored in an application's message-queue, and retrieved via the
|
554 |
|
|
GetMessage function. The application blocks while waiting for a message. There
|
555 |
|
|
are messages that correspond to hardware events, like WM_CHAR for keyboard input or
|
556 |
|
|
WM_LBUTTONDOWN for mouse button down. In addtiion, events signaling window creation
|
557 |
|
|
and destruction WM_CREATE and WM_DESTROY are sent. In most cases, a message is
|
558 |
|
|
associated with a window, identified as an HWND. After retrieving the message, the
|
559 |
|
|
application sends the message to the associated window's handling procedure using
|
560 |
|
|
DispatchMessage. When a window class is created, it's associated message handling
|
561 |
|
|
procedure is specified, so the system knows where to send the message.</p>
|
562 |
|
|
|
563 |
|
|
<p>The message-passing architecture allows the core API to manage many system functions by
|
564 |
|
|
sending messages on all sorts of events, like window creation, painting needed, moving,
|
565 |
|
|
etc. By default, the associated window handling function gets a "first
|
566 |
|
|
pass" at the message, and then calls the DefWindowProc function, which handles
|
567 |
|
|
default actions for all the messages. In this way, all windows can behave the same
|
568 |
|
|
way when dragged, etc, unless specifically overridden by the user. Major window
|
569 |
|
|
management policies can be redefined by merely re-implementing DefWindowProc, rather than
|
570 |
|
|
making changes throughout the system.</p>
|
571 |
|
|
|
572 |
|
|
<p>The following functions deal with messages directly:</p>
|
573 |
|
|
|
574 |
|
|
<p>
|
575 |
|
|
SendMessage
|
576 |
|
|
Send a message directly to a window<br>
|
577 |
|
|
|
578 |
|
|
PostMessage
|
579 |
|
|
Queue a message on the application's message queue for later dispatch<br>
|
580 |
|
|
PostQuitMessage
|
581 |
|
|
Queue a WM_QUIT message telling the application to terminate when read<br>
|
582 |
|
|
|
583 |
|
|
GetMessage
|
584 |
|
|
Block until a message is queued for this application<br>
|
585 |
|
|
TranslateMessage
|
586 |
|
|
Translate up/down keystrokes to WM_CHAR messages<br>
|
587 |
|
|
|
588 |
|
|
DispatchMessage Send a
|
589 |
|
|
messages to it's associated window procedure</p>
|
590 |
|
|
|
591 |
|
|
<p>A Microwindows application's entry point is the function WinMain, rather than main.</p>
|
592 |
|
|
|
593 |
|
|
<h3> 3.2 Window creation and
|
594 |
|
|
destruction</h3>
|
595 |
|
|
|
596 |
|
|
<p>The basic unit of screen organization in Microwindows API is the window. Windows
|
597 |
|
|
describe an area of the screen to draw onto, as well as an associate "window
|
598 |
|
|
procedure" for handling messages destined for this window. Applications
|
599 |
|
|
programmers can create windows from pre-defined classes, like buttons, edit boxes, and the
|
600 |
|
|
like, or define their own window classes. In both cases, the method of creating and
|
601 |
|
|
communicating with the windows remains exactly the same. The following functions
|
602 |
|
|
deal with window registration, creation, and destruction:</p>
|
603 |
|
|
|
604 |
|
|
<p>
|
605 |
|
|
RegisterClass
|
606 |
|
|
Define a new window class name and associated window procedure<br>
|
607 |
|
|
|
608 |
|
|
UnRegisterClass Undefine
|
609 |
|
|
a window class<br>
|
610 |
|
|
CreateWindowEx Create
|
611 |
|
|
an instance of a window of a certain class<br>
|
612 |
|
|
|
613 |
|
|
DestroyWindow Destroy a
|
614 |
|
|
window instance</p>
|
615 |
|
|
|
616 |
|
|
<p>The WM_CREATE message is just after window creation, before returning from
|
617 |
|
|
CreateWindowEx. The WM_DESTROY message is sent just before destroying a window with
|
618 |
|
|
DestroyWindow. </p>
|
619 |
|
|
|
620 |
|
|
<p>When a window is registered, extra bytes can be allocated to the window structure when
|
621 |
|
|
created. The GetWindowLong, GetWindowWord, SetWindowLong and SetWindowWord
|
622 |
|
|
manipulate these bytes. In addition, a fixed number of extra bytes per window class
|
623 |
|
|
can be allocated on registration and retrieved via the GetClassLong function.</p>
|
624 |
|
|
|
625 |
|
|
<h3> 3.3 Window showing,
|
626 |
|
|
hiding and moving</h3>
|
627 |
|
|
|
628 |
|
|
<p>The ShowWindow function allows windows to be made visible or hidden. In addition,
|
629 |
|
|
this can be specified during the creation of the window, through CreateWindowEx.
|
630 |
|
|
MoveWindow is called to change a window's position or size. A WM_MOVE message is
|
631 |
|
|
sent if the window's position changes, and WM_SIZE is sent on size changes.</p>
|
632 |
|
|
|
633 |
|
|
<h3> 3.4 Window painting</h3>
|
634 |
|
|
|
635 |
|
|
<p>The Microwindows system determines when a window needs to be initially painted or
|
636 |
|
|
repainted as the result of other window movement, and a WM_PAINT message is sent to the
|
637 |
|
|
associated window procedure. At this point, it's up the the application to use the
|
638 |
|
|
graphics primitives available to paint the window, described below. Microwindows
|
639 |
|
|
keeps track of a windows' "update" region, and sends WM_PAINT whenever the
|
640 |
|
|
region is non-empty. For speed reasons, the WM_PAINT message is only sent when there
|
641 |
|
|
are no other messages in the application's queue. This allows the application to
|
642 |
|
|
repaint in one, rather than possibly many, steps. To force a repaint rather than
|
643 |
|
|
waiting, the UpdateWindow function can be called. The InvalidateRect function
|
644 |
|
|
specifies a rectangle to add to the update region, causing a subsequent WM_PAINT.</p>
|
645 |
|
|
|
646 |
|
|
<p>The window title is automatically painted and is set with the SetWindowText function,
|
647 |
|
|
and retrieved with the GetWindowText function.</p>
|
648 |
|
|
|
649 |
|
|
<h3> 3.4.1 Client and screen
|
650 |
|
|
coordinates</h3>
|
651 |
|
|
|
652 |
|
|
<p>Every window is drawn on the screen using the device global screen coordinate system
|
653 |
|
|
for absolute reference to any pixel on the screen. The Microwindows API allows
|
654 |
|
|
applications programmers to be concerned with only the relative coordinates from the upper
|
655 |
|
|
left portion of their window, not including the title bar and 3d effects. This
|
656 |
|
|
coordinate system is called "client coordinates." As will be explained
|
657 |
|
|
below, the Microwindows programmer has the option of getting a device context in either
|
658 |
|
|
screen or client coordinates. If device coordinates are specified, then the
|
659 |
|
|
coordinate system is device-based and includes the title area and 3d areas of the
|
660 |
|
|
window. Otherwise, the drawable region is clipped to just that area that is
|
661 |
|
|
reserved by the system for the application's drawing. The GetClientRect and
|
662 |
|
|
GetWindowRect functions return client or screen coordinates for the passed window.
|
663 |
|
|
ClientToScreen and ScreenToClient can be called to translate between window coordinate
|
664 |
|
|
systems.</p>
|
665 |
|
|
|
666 |
|
|
<h3> 3.4.2 Device contexts</h3>
|
667 |
|
|
|
668 |
|
|
<p>An applications programmer must obtain a "device context" before calling any
|
669 |
|
|
graphics drawing API functions. As explained above, this specifies to the system
|
670 |
|
|
which window and what coordinate system are desired, so that these don't have to be passed
|
671 |
|
|
to every graphics function. In addition, various other attributes like foreground
|
672 |
|
|
and background color are also set in a device context, so that these parameters don't have
|
673 |
|
|
to be specified for every graphics operation. The device context selects the
|
674 |
|
|
appropriate clipping region based on the window specified and the coordinate system.
|
675 |
|
|
When a device context is obtained, various graphics values are set to default values.</p>
|
676 |
|
|
|
677 |
|
|
<p>To obtain a client device context, call GetDC. To obtain a screen device context,
|
678 |
|
|
required when drawing onto title bars and the like, call GetWindowDC. In addition,
|
679 |
|
|
fancy clipping operations and child/sibling window clipping can be specified if GetDCEx is
|
680 |
|
|
called. When finished drawing, the ReleaseDC function must be called to deallocate
|
681 |
|
|
the DC.</p>
|
682 |
|
|
|
683 |
|
|
<p>On receipt of the WM_PAINT message, two special calls, BeginPaint and EndPaint are
|
684 |
|
|
called, that serve as replacements to the GetDC/ReleaseDC functions. These functions
|
685 |
|
|
essentially allocate a DC but also validate the update region so that no subsequent
|
686 |
|
|
WM_PAINT messages are generated. BeginPaint also combines the update region and the
|
687 |
|
|
clipping region so that user output will only occur where previously invalidated.</p>
|
688 |
|
|
|
689 |
|
|
<h3> 3.4.3 Graphics drawing
|
690 |
|
|
API</h3>
|
691 |
|
|
|
692 |
|
|
<p>There are many graphics drawing API's in the Microwindows API. Following is a
|
693 |
|
|
list, most of these match up to the engine GdXXX functions discussed in section 2.</p>
|
694 |
|
|
|
695 |
|
|
<p>
|
696 |
|
|
SetTextColor
|
697 |
|
|
Set the foreground text color in a DC<br>
|
698 |
|
|
|
699 |
|
|
SetBkColor
|
700 |
|
|
Set the background color in a DC<br>
|
701 |
|
|
|
702 |
|
|
GetSysColor
|
703 |
|
|
Get the system color defined for the current look and feel scheme<br>
|
704 |
|
|
|
705 |
|
|
SetBkMode
|
706 |
|
|
Set the use background flag in a DC<br>
|
707 |
|
|
|
708 |
|
|
SetROP2
|
709 |
|
|
Set the drawing mode (XOR, SET, etc) for drawing<br>
|
710 |
|
|
|
711 |
|
|
SetPixel
|
712 |
|
|
Draw a pixel in the current fg color<br>
|
713 |
|
|
|
714 |
|
|
MoveToEx
|
715 |
|
|
Prepare to draw a line<br>
|
716 |
|
|
|
717 |
|
|
LineTo
|
718 |
|
|
Draw a line from the last location to this one in the current fg color<br>
|
719 |
|
|
|
720 |
|
|
Rectangle
|
721 |
|
|
Draw a rectangle in the current pen color<br>
|
722 |
|
|
|
723 |
|
|
FillRect
|
724 |
|
|
Fill a rectangle with the current brush color<br>
|
725 |
|
|
|
726 |
|
|
TextOut
|
727 |
|
|
Draw text in the current fg/bg color<br>
|
728 |
|
|
|
729 |
|
|
ExtTextOut
|
730 |
|
|
Draw text in the current fg/bg color<br>
|
731 |
|
|
|
732 |
|
|
DrawText
|
733 |
|
|
Draw text or compute text height and width sizes<br>
|
734 |
|
|
|
735 |
|
|
DrawDIB
|
736 |
|
|
Draw a color bitmap<br>
|
737 |
|
|
|
738 |
|
|
SelectObject
|
739 |
|
|
Select a pen, brush or font to use in a DC<br>
|
740 |
|
|
|
741 |
|
|
GetStockObject
|
742 |
|
|
Get a predefined standard pen, brush or font<br>
|
743 |
|
|
|
744 |
|
|
CreatePen
|
745 |
|
|
Create a pen of a certain color<br>
|
746 |
|
|
|
747 |
|
|
CreateSolidBrush
|
748 |
|
|
Create a brush of a certain color<br>
|
749 |
|
|
CreateCompatibleBitmap Create an offscreen area to draw onto<br>
|
750 |
|
|
|
751 |
|
|
DeleteObject
|
752 |
|
|
Delete a pen, brush or bitmap<br>
|
753 |
|
|
CreateCompatibleDC Create an
|
754 |
|
|
offscreen DC<br>
|
755 |
|
|
|
756 |
|
|
DeleteDC
|
757 |
|
|
Delete an offscreen DC<br>
|
758 |
|
|
|
759 |
|
|
BitBlit
|
760 |
|
|
Copy from one bitmap in a DC to another<br>
|
761 |
|
|
GetSystemPaletteEntries Get the currently in-use
|
762 |
|
|
system palette entries<br>
|
763 |
|
|
</p>
|
764 |
|
|
|
765 |
|
|
<h3> 3.5 Utility functions</h3>
|
766 |
|
|
|
767 |
|
|
<p>A number of routines are provided for various purposes, described below. In
|
768 |
|
|
addition, Microwindows currently exports some helper routines, named WndXXX, that are
|
769 |
|
|
useful but subject to change. These are detailed following:</p>
|
770 |
|
|
|
771 |
|
|
<p>
|
772 |
|
|
WndSetDesktopWallpaper
|
773 |
|
|
Set the desktop background image<br>
|
774 |
|
|
|
775 |
|
|
WndSetCursor
|
776 |
|
|
Set the cursor for a window<br>
|
777 |
|
|
|
778 |
|
|
WndRaiseWindow
|
779 |
|
|
Raise a window's z-order<br>
|
780 |
|
|
|
781 |
|
|
WndLowerWindow
|
782 |
|
|
Lower a window's z-order<br>
|
783 |
|
|
|
784 |
|
|
WndGetTopWindow
|
785 |
|
|
Return the topmost window's handle<br>
|
786 |
|
|
|
787 |
|
|
WndRegisterFdInput
|
788 |
|
|
Register to send a message when file descriptor has read data available<br>
|
789 |
|
|
|
790 |
|
|
WndUnregisterFdInput
|
791 |
|
|
Unregister file descriptor for read data messages</p>
|
792 |
|
|
|
793 |
|
|
<p>
|
794 |
|
|
GetTickCount
|
795 |
|
|
Return # milliseconds elapsed since startup<br>
|
796 |
|
|
|
797 |
|
|
Sleep
|
798 |
|
|
Delay processing for specified milliseconds</p>
|
799 |
|
|
|
800 |
|
|
<h3> 3.5.1 Setting window
|
801 |
|
|
focus</h3>
|
802 |
|
|
|
803 |
|
|
<p>The SetFocus routine is used to pass keyboard focus from one window to another.
|
804 |
|
|
Keystrokes are always sent to the window with focus. The WM_SETFOCUS and
|
805 |
|
|
WM_KILLFOCUS messages are sent to windows just receiving and losing focus. The
|
806 |
|
|
GetActiveWindow routines returns the first non-child ancestor of the focus window, which
|
807 |
|
|
is the window that is currently highlighted. The GetDesktopWindow routine returns
|
808 |
|
|
the window handle of the desktop window.</p>
|
809 |
|
|
|
810 |
|
|
<h3> 3.5.2 Mouse capture</h3>
|
811 |
|
|
|
812 |
|
|
<p>Normally, Microwindows sends WM_MOUSEMOVE messages to the window the mouse is currently
|
813 |
|
|
moving over. If desired, the 7applications programmer can "capture" the
|
814 |
|
|
mouse and receive all mouse move messages by calling SetCapture. ReleaseCapture
|
815 |
|
|
returns the processing to normal. In addition, the GetCapture function will return
|
816 |
|
|
the window with capture, if any.</p>
|
817 |
|
|
|
818 |
|
|
<h3> 3.5.3 Rectangle and
|
819 |
|
|
Region management</h3>
|
820 |
|
|
|
821 |
|
|
<p>There are a number of functions that are used for rectangles and regions.
|
822 |
|
|
Following is the group:</p>
|
823 |
|
|
|
824 |
|
|
<p>
|
825 |
|
|
SetRect
|
826 |
|
|
Define a rectangle structure<br>
|
827 |
|
|
|
828 |
|
|
SetRectEmpty
|
829 |
|
|
Define an empty rectangle<br>
|
830 |
|
|
|
831 |
|
|
CopyRect
|
832 |
|
|
Copy a rectangle<br>
|
833 |
|
|
|
834 |
|
|
IsRectEmpty
|
835 |
|
|
Return TRUE if empty rectangle<br>
|
836 |
|
|
|
837 |
|
|
InflateRect
|
838 |
|
|
Enlarge a rectangle<br>
|
839 |
|
|
|
840 |
|
|
OffsetRect
|
841 |
|
|
Move a rectangle<br>
|
842 |
|
|
|
843 |
|
|
PtInRect
|
844 |
|
|
Determine if a point is in a rectangle<br>
|
845 |
|
|
</p>
|
846 |
|
|
|
847 |
|
|
<p>A large number of region management routines are defined and declared in the winrgn.c
|
848 |
|
|
file. </p>
|
849 |
|
|
|
850 |
|
|
<p> </p>
|
851 |
|
|
|
852 |
|
|
<h3>4. Nano-X API</h3>
|
853 |
|
|
|
854 |
|
|
<p>The Nano-X API was originally designed by David Bell, with his mini-x package for the
|
855 |
|
|
MINIX operating system. Nano-X is now running on top of the core graphics engine
|
856 |
|
|
routines discussed in section 2. Nano-X was designed for a client/server
|
857 |
|
|
environment, as no pointers to structures are passed to the API routines, instead a call
|
858 |
|
|
is made to the server to get an ID, which is passed to the API functions and is used to
|
859 |
|
|
reference the data on the server. In addition, Nano-X is not message-oriented,
|
860 |
|
|
instead modeled after the X protocol which was designed for speed on systems where the
|
861 |
|
|
client and server machines were different.</p>
|
862 |
|
|
|
863 |
|
|
<h3> 4.1 Client/Server model</h3>
|
864 |
|
|
|
865 |
|
|
<p>In Nano-X, there are two linking mechanisms that can be used for applications
|
866 |
|
|
programs. In the client/server model, the application program is linked with a
|
867 |
|
|
client library that forms a UNIX socket connection with the Nano-X server, a separate
|
868 |
|
|
process. Each application then communicates all parameters over the UNIX
|
869 |
|
|
socket. For speed and debugging, it is sometimes desirable to link the application
|
870 |
|
|
directly with the server. In this case, a stub library is provided that just passes
|
871 |
|
|
the client routines parameters to the server function.</p>
|
872 |
|
|
|
873 |
|
|
<p>The Nano-X naming convention uses GrXXX to designate client side callable routines,
|
874 |
|
|
with a marshalling layer implemented in the files nanox/client.c, nanox/nxproto.c, and
|
875 |
|
|
nanox/srvnet.c. The client/server network layer currently uses a fast approach to
|
876 |
|
|
marshalling the data from the Gr routine into a buffer, and sent all at once to the
|
877 |
|
|
receiving stubs in nanox/srvnet.c, before calling the server drawing routines in
|
878 |
|
|
nanox/srvfunc.c. In the linked application scenario, the Nano-X client links
|
879 |
|
|
directly with the functions in nanox/srvfunc.c, and the nanox/client.c and nanox/srvnet.c
|
880 |
|
|
files are not required.</p>
|
881 |
|
|
|
882 |
|
|
<p>A Nano-X application must call GrOpen before calling any other Nano-X function, and
|
883 |
|
|
call GrClose before exiting. These functions establish a connection with the server
|
884 |
|
|
when running the client/server model, and return an error status if the server can't be
|
885 |
|
|
found or isn't currently running.</p>
|
886 |
|
|
|
887 |
|
|
<p>The main loop in a Nano-X application is to create some windows, define the events you
|
888 |
|
|
want with GrSelectEvents, and then wait for an event with GrGetNextEvent. If it is
|
889 |
|
|
desired to merely check for an event, but not wait if there isn't one, GrCheckNextEvent
|
890 |
|
|
can be used. GrPeekEvent can be used to examine the next event without removing it
|
891 |
|
|
from the queue.</p>
|
892 |
|
|
|
893 |
|
|
<p>When running Nano-X programs in the client/server model, it's currently necessary to
|
894 |
|
|
run the server first in a shell script, then wait a second, then run the
|
895 |
|
|
application. Some rewriting is needed to fire up the server when an application
|
896 |
|
|
requires it, I believe.</p>
|
897 |
|
|
|
898 |
|
|
<h3> 4.2 Events</h3>
|
899 |
|
|
|
900 |
|
|
<p>Nano-X applications specify which events they would like to see on a per-window basis
|
901 |
|
|
using GrSelectEvents. Then, in the main loop, the application calls GrGetNextEvent
|
902 |
|
|
and waits for one of the event types selected for in any of the windows. Typically,
|
903 |
|
|
a switch statement is used to determine what to do after receiving the event. This
|
904 |
|
|
is similar to the Microwindows's API GetMessage/DispatchMessage loop, except that in
|
905 |
|
|
Microwindows API, DispatchMessage is used to send the event to the window's handling
|
906 |
|
|
procedure, typically located with the window object. In Nano-X, all the event
|
907 |
|
|
handling code for each of the windows must be placed together in the main event loop,
|
908 |
|
|
there is no automatic dispatching. Of course, widget sets serve to provide
|
909 |
|
|
object-orientation, but this is in addition to the Nano-X API.</p>
|
910 |
|
|
|
911 |
|
|
<p>Following are the event types that Nano-X programs can recieve:</p>
|
912 |
|
|
|
913 |
|
|
<p> GR_EVENT_TYPE_NONE, ERROR, EXPOSURE, BUTTON_DOWN, BUTTON_UP,
|
914 |
|
|
MOUSE_ENTER, MOUSE_EXIT, MOUSE_MOTION, MOUSE_POSITION, KEY_UP, KEY_DOWN, FOCUS_IN,
|
915 |
|
|
FOCUS_OUT, FDINPUT</p>
|
916 |
|
|
|
917 |
|
|
<p>Note that Nano-X API provides mouse enter and exit events whereas Microwindows API does
|
918 |
|
|
not. Also, the exposure events are calculated and sent immediately by the server,
|
919 |
|
|
and not combined and possibly delayed for better paint throughput as in the Microwindows
|
920 |
|
|
API.</p>
|
921 |
|
|
|
922 |
|
|
<h3> 4.3 Window creation and destruction</h3>
|
923 |
|
|
|
924 |
|
|
<p>Windows are created in Nano-X with the GrNewWindow function. Windows can be
|
925 |
|
|
specified to be input-only, in which case the GrNewInputWindow function is used. The
|
926 |
|
|
window border and color is specified in these calls, but will have to be rewritten when
|
927 |
|
|
fancier window dressings are required. The return value from these functions is an
|
928 |
|
|
ID that can be used in later calls to get a graphics context or perform window
|
929 |
|
|
manipulation.</p>
|
930 |
|
|
|
931 |
|
|
<h3> 4.4 Window showing,
|
932 |
|
|
hiding and moving</h3>
|
933 |
|
|
|
934 |
|
|
<p>Windows are shown by calling the GrMapWindow function, and hidden using
|
935 |
|
|
GrUnmapWindow. Mapping a window is required for all ancestors of a window in order
|
936 |
|
|
for it to be visible. The GrRaiseWindow call is used to raise the Z order of a
|
937 |
|
|
window, while GrLowerWindow is used to lower the Z order. GrMoveWindow is used to
|
938 |
|
|
change the position of a window, and GrResizeWindow is used to resize a window.</p>
|
939 |
|
|
|
940 |
|
|
<h3> 4.5 Drawing to a window</h3>
|
941 |
|
|
|
942 |
|
|
<p>Nano-X requires both a window ID and a graphics context ID in order to draw to a
|
943 |
|
|
window. Nano-X sends expose events to the application when a window needs to be
|
944 |
|
|
redrawn. Unlike the Microwindows API, Nano-X clients are typically required to
|
945 |
|
|
create their drawing graphics contexts early on and keep them for the duration of the
|
946 |
|
|
application. Like Microwindows though, the graphics contexts record information like
|
947 |
|
|
the current background and foreground colors so they don't have to be specified in every
|
948 |
|
|
graphics API call.</p>
|
949 |
|
|
|
950 |
|
|
<h3> 4.5.1 Graphics contexts</h3>
|
951 |
|
|
|
952 |
|
|
<p>To allocate a graphics context for a window, call GrNewGC. On termination, call
|
953 |
|
|
GrDestroyGC. GrCopyGC can be used to copy on GC to another. GrGetGCInfo is
|
954 |
|
|
used to retrieve the settings contained in a GC. After creating a graphics context,
|
955 |
|
|
the server returns a graphics context ID. This is then used as a parameter in all
|
956 |
|
|
the graphics drawing API functions. In Nano-X programs, the current clipping region
|
957 |
|
|
and window coordinate system aren't stored with the GC, as they are in Microwindows'
|
958 |
|
|
DCs. This is because, first, Nano-X doesn't support dual coordinate systems for
|
959 |
|
|
drawing to the "window dressing" area versus the "user" area of the
|
960 |
|
|
window (window and client coordinates in Microwindows). User programs can't draw the
|
961 |
|
|
border area of the window, only a single color and width can be specified. Although
|
962 |
|
|
resembling X, this will have to change, so that widget sets can specify the look and feel
|
963 |
|
|
of all aspects of the windows they maintain. Since the clipping region isn't
|
964 |
|
|
maintained with the graphics context, but instead with the window data structure, Nano-X
|
965 |
|
|
applications must specify both a window ID and a graphics context ID when calling any
|
966 |
|
|
graphics API function. Because of this, many Nano-X applications allocate all
|
967 |
|
|
graphics contexts in the beginning of the program, and hold them throughout execution,
|
968 |
|
|
since the graphics contexts hold only things like foreground color, etc, and no window
|
969 |
|
|
information. This cannot be done with Microwindows API because the DC's contain
|
970 |
|
|
window clipping information and must be released before processing the next message.</p>
|
971 |
|
|
|
972 |
|
|
<h3> 4.5.2 Graphics drawing
|
973 |
|
|
API</h3>
|
974 |
|
|
|
975 |
|
|
<p>Following are the graphics drawing functions available with Nano-X. Like
|
976 |
|
|
Microwindows API, these all match up eventually to the graphics engine GdXXX routines.</p>
|
977 |
|
|
|
978 |
|
|
<p>
|
979 |
|
|
GrGetGCTextSize
|
980 |
|
|
Return text width and height information<br>
|
981 |
|
|
|
982 |
|
|
GrClearWindow
|
983 |
|
|
Clear a window to it's background color<br>
|
984 |
|
|
|
985 |
|
|
GrSetGCForeground
|
986 |
|
|
Set the foreground color in a graphics context<br>
|
987 |
|
|
|
988 |
|
|
GrSetGCBackground
|
989 |
|
|
Set the background color in a graphics context<br>
|
990 |
|
|
GrSetGCUseBackground
|
991 |
|
|
Set the "use background color" in a graphics context<br>
|
992 |
|
|
|
993 |
|
|
GrSetGCMode
|
994 |
|
|
Set the drawing mode<br>
|
995 |
|
|
|
996 |
|
|
GrSetGCFont
|
997 |
|
|
Set the font<br>
|
998 |
|
|
|
999 |
|
|
GrPoint
|
1000 |
|
|
Draw a point in the passed gc's foreground color<br>
|
1001 |
|
|
|
1002 |
|
|
GrLine
|
1003 |
|
|
Draw a line in the passed gc's foreground color<br>
|
1004 |
|
|
|
1005 |
|
|
GrRect
|
1006 |
|
|
Draw a rectangle in passed gc's foreground color<br>
|
1007 |
|
|
|
1008 |
|
|
GrFillRect
|
1009 |
|
|
Fill a rectangle with the passed gc's foreground color<br>
|
1010 |
|
|
|
1011 |
|
|
GrEllipse
|
1012 |
|
|
Draw a circle or ellipse with the passed gc's foreground color<br>
|
1013 |
|
|
|
1014 |
|
|
GrFillEllipse
|
1015 |
|
|
Fill a circle or ellipse with the passed gc's foreground color<br>
|
1016 |
|
|
|
1017 |
|
|
GrPoly
|
1018 |
|
|
Draw a polygon using the passed gc's foreground color<br>
|
1019 |
|
|
|
1020 |
|
|
GrFillPoly
|
1021 |
|
|
Fill a polygon using the passed gc's foreground color<br>
|
1022 |
|
|
|
1023 |
|
|
GrText
|
1024 |
|
|
Draw a text string using the foreground and possibly background colors<br>
|
1025 |
|
|
|
1026 |
|
|
GrBitmap
|
1027 |
|
|
Draw an image using a passed monocrhome bitmap, use fb/bg colors<br>
|
1028 |
|
|
|
1029 |
|
|
GrArea
|
1030 |
|
|
Draw a rectangular area using the passed device-dependent pixels<br>
|
1031 |
|
|
|
1032 |
|
|
GrReadArea
|
1033 |
|
|
Read the pixel values from the screen and return them<br>
|
1034 |
|
|
GrGetSystemPaletteEntries Get
|
1035 |
|
|
the currently in-use system palette entries<br>
|
1036 |
|
|
GrFindColor
|
1037 |
|
|
Translate an RGB color value to a PIXELVAL pixel value<br>
|
1038 |
|
|
</p>
|
1039 |
|
|
|
1040 |
|
|
<h3> 4.6 Utility functions</h3>
|
1041 |
|
|
|
1042 |
|
|
<p>Various functions serve as utility functions to manipulate windows and provide other
|
1043 |
|
|
information. These include the following:</p>
|
1044 |
|
|
|
1045 |
|
|
<p>
|
1046 |
|
|
GrSetBorderColor
|
1047 |
|
|
Set the border color of a window. Not suitable for 3d look and feel.<br>
|
1048 |
|
|
|
1049 |
|
|
GrSetCursor
|
1050 |
|
|
Set the cursor bitmap for the window.<br>
|
1051 |
|
|
|
1052 |
|
|
GrMoveCursor
|
1053 |
|
|
Move the cursor to absolute screen coordinates.<br>
|
1054 |
|
|
|
1055 |
|
|
GrSetFocus
|
1056 |
|
|
Set the keyboard input focus window.<br>
|
1057 |
|
|
|
1058 |
|
|
GrRedrawScreen
|
1059 |
|
|
Redraw the entire screen.<br>
|
1060 |
|
|
|
1061 |
|
|
GrGetScreenInfo
|
1062 |
|
|
Return information about the size of the physical display.<br>
|
1063 |
|
|
|
1064 |
|
|
GrGetWindowInfo
|
1065 |
|
|
Return information about the passed window.<br>
|
1066 |
|
|
|
1067 |
|
|
GrGetGCInfo
|
1068 |
|
|
Return information about the passed graphics context.<br>
|
1069 |
|
|
|
1070 |
|
|
GrGetFontInfo
|
1071 |
|
|
Return information about the passed font number.<br>
|
1072 |
|
|
|
1073 |
|
|
GrRegisterInput
|
1074 |
|
|
Register a file descriptor to return an event when read data available<br>
|
1075 |
|
|
GrPrepareSelect
|
1076 |
|
|
|
1077 |
|
|
Prepare the fd_set and maxfd variables for using Nano-X as a passive library<br>
|
1078 |
|
|
GrServiceSelect
|
1079 |
|
|
|
1080 |
|
|
Callback the passed GetNextEvent routine when Nano-X has events requiring processing<br>
|
1081 |
|
|
GrMainLoop
|
1082 |
|
|
|
1083 |
|
|
A convenience routine for a typical Nano-X application main loop</p>
|
1084 |
|
|
</body>
|
1085 |
|
|
</html>
|