GraphApp: Designing for Portability and Internationalisation

Overview

  • GUI toolkits
  • GraphApp
  • What is Portability?
  • What is Internationalisation?
  • How to achieve these goals

History

  • 1992: Network Morning Herald
  • libg / libXg / Mac libg
  • Win libg ... GraphApp 1
  • 1995: GraphApp 2 for Windows and X-Windows
  • 1995: Java 1.0 AWT
  • 1996: Java 1.1 AWT
  • 2000: GraphApp 3

How GUI Toolkits work

Emulated vs Layered

Examples: Tk, Java's AWT, wxWindows, GraphApp, ...

How X-Windows works

X-Windows uses a client/server approach to graphics.

The picture is a good model for how other environments work, too.

The important points to note are that drawing within the client or server is fast, but sending information between client and server is relatively slow.

Images versus Bitmaps

Images are on the client-side, so manipulating them can be fast, provided you can access the memory they occupy. This is the whole point of Images. They provide a way for the programmer to directly control the picture.

Bitmaps are on the server or otherwise close to the hardware. They are fast to copy to a Window, but cannot be easily manipulated by a client program. You need drawing operations to fill a bitmap with information.

A good graphics system needs both Images and Bitmaps. Images give programmability. Bitmaps give speed when displaying.

Thus, fast translation between these two formats is needed.

Drawing

Images are client-side pictures. Bitmaps are server-side pictures. Ideally, we would not need two objects which replicate the same functionality, but practical concerns motivate this replication of effort.

Windows are server-side representations of on-screen overlapping windows.

Drawing is allowed in the directions indicated by arrows. Bitmaps and Windows are output devices only.

Transparency? Alpha blending? Gamma correction?

Core GUI Objects

A GUI toolkit should provide access to several user interface objects, such as Windows. Which of these objects should the operating system provide?

1. Windows (create, destroy, show, hide, draw to)

2. Bitmaps (create, destroy, draw to, copy to Bitmap/Window)

3. Cursors (create, destroy, set_cursor)

4. Colours (set_window_palette)

5. Fonts? (load, use)

6. Sub-windows?

7. Controls? (buttons, scrollbars, text fields, menus)

Items 1-4 must be provided by the operating system.

Items 5-7 might be better provided using portable code, for reasons which will be explained later.

Core Drawing Operations

What drawing operations are needed?

1. set_colour

2. fill_rect

3. bitblt (copy_rect)

That's all you need! Everything can be built with those operations. For efficiency, one other operation also helps:

4. draw_font (UTF-8)

Other Drawing Operations

There are several other drawing operations which could be useful, but which of them should be implemented by the operating system?

1. draw_line (Bresenham's algorithm)

2. draw_rect

3. draw_ellipse

4. fill_ellipse

5. draw_round_rect

6. fill_round_rect

etc.

There are arguments both ways, but I prefer to build these operations from portable code using the fill_rect operation.

Portability

What do I mean by portability, anyway?

Ideal portability means that code can be moved without any changes, between platforms.

'Code' mostly means code which uses the toolkit's interface, but may also refer to code within the toolkit itself.

'Platforms' can mean different operating systems, different versions of the same operating system, or even just different screen resolutions.

Usually, portability means much less than this. With GraphApp, I've striven for true portability. That's a tall order!

Portability 2

How to achieve true portability?

Some ideas:

1. Rely on the operating system for as little as possible

2. Draw fonts using bitblt, images and bitmaps

3. Build images from portable formats, such as PNG

4. Build controls using portable code, not operating system controls

The Font Problem

Fonts are not a good way to provide portability. Thus, they are not a good way to support internationalisation.

What if my computer has a font, but yours doesn't have the same font?

What if my computer can display Greek, but yours can't?

This is a nasty problem which crops up in World-Wide-Web browsers all the time. A poor solution is to rely on a 'document encoding' to specify how the font is to be viewed, and give an error message if it cannot be displayed correctly.

Unicode, and the UTF-8 encoding, are much better solutions, because they allow multiple languages in the one document, but they still rely on having a Unicode font installed on all operating systems.

GraphApp Unicode Fonts

Unicode font ranges 00000000, 00000300 and 00005000.

Example: viewutf8

Client-side clipping

To build controls, you need Regions.

A Region is a union of distinct rectangles.

Clipping is where drawing is restricted to those rectangles.

Client-side clipping is where we implement this logic inside the client program, preferably in the toolkit itself. (GraphApp does this clipping inside the three drawing operations, fill_rect, copy_rect and draw_utf8.)

Main advantages: portability and speed.

Main disadvantage: if the client is slow, it may be faster to perform all clipping on the server, but usually this is not the case.

Portable Controls

Controls can then be implemented portably by using Regions to subtract a portion of the window from the window's drawable area.

Advantage 1: controls look and behave exactly the same way on all platforms. In particular, events are propagated in the same way on all platforms, within a given window.

Advantage 2: controls can be internationalised in the same way on all platforms.

Disadvantage: does not use native look-and-feel (but is this an advantage in disguise?)

Identical pixels

GraphApp thus supports a form of portability where the pixels are identical on all platforms (colours may vary a little, but the placement of the pixels is the same).

This applies not just to text, but to controls within the window.

This allows you to produce truly portable code. You need a few other things to get there, however:

1. Eliminate different path separators

2. Provide consistent access to other services, such as the network, databases, etc.

Geometry Managers

There are alternatives to this pixel-level portability. The main one is the use of geometry managers.

A geometry manager is a clever piece of code which smoothes over the differences between different font vendors, screen resolutions, and widget designs.

It knows about how the operating system places borders around controls which have the input focus, about the spacing around words needed within controls, about the preferred sizes of scrollbars, etc.

In short, it is a smart buffer between the logical placement of GUI elements, as specified by the programmer, and the physical placement needed at the low-level graphics interface.

Advantages

Geometry managers have three main advantages over pixel-level portability:

1. Changing the screen resolution: fonts can still be readable because they can be specified in point sizes, not pixel sizes (GraphApp can do this too)

2. Changing the operating system: the geometry manager understands each native look-and-feel so because the programmer has specified the 'logical' look of the application, it can do a fair job of translating to the new environment

3. Internationalising the program: changing the language used by an application can be made easier with a geometry manager, because a change of say English to Chinese may mean the buttons take up a lot less space (words are more compact). Again, 'logical' positions means space is used optimally.

Disadvantages

There are some disadvantages to geometry managers too.

1. Sometimes you want pixel-level control. Drawing applications, viewing images, cases where the programmer wants exact control...

2. Sometimes there isn't a geometry manager for the task. Most GM's are rectangular in nature, but what if the application doesn't want the standard layout...

3. Internationalisation is more than just changing the English words into another language. Case in point: Hebrew is written right-to-left. Cultural differences too. Different icons. Different behaviours. Different layouts, beyond what the GM can do...

If you need a guarantee that the application will look a certain way on all platforms, GMs may not be able to give that guarantee.

GraphApp

GraphApp thus provides a lower-level portability and internationalisation approach than other toolkits.

It aims to guarantee that the pixels are right, and that this is true on all platforms.

It guarantees that a Unicode font is available for each application. You can package a small part of the font with the application, or you can provide the entire font.

It guarantees that controls will look and behave predictably on all platforms, too.

In short, it sets a good foundation for higher level software to build upon.

GraphApp vs Java

GraphApp can even do a few things other systems (e.g. Java) cannot.

1. Drawing fonts to images

2. Drawing images without having access to X-Windows (e.g. in a CGI program)

3. Drawing fonts without having access to X-Windows

4. Guarantees about font sizes and scaling

Objections

There may be some objections to these approaches:

1. Some of these technologies belong in the operating system. E.g. a font server caches fonts for efficiency and should be close to the graphics system, not each application. (Mixtures? Portable font servers?)

2. Pixel-level control is less useful than geometry management. I consider it a 'complementary' technology, not a challenge to GMs.

3. Bitmapped fonts will get too small as display resolution increases. Not a problem as long as you provide new higher resolution fonts later, and/or allow font scaling.

Summary

GraphApp provides portability and internationalisation capabilities to applications, in ways which are sometimes different to other comparable tools, such as Java.

The ideas are not necessarily new, but the blending of these ideas (bitmapped fonts, Unicode, similar access to drawing for images, bitmaps and windows, pixel-level portability) is a significant change from the way most graphics toolkits operate.