NAME

Prima::gp-problems - Problems, questionable or intricate topics in 2-D Graphics

Introduction

One of the most important goals of the Prima project is the portability between different operating systems. Independently to efforts in keeping Prima's internal code that behaves more or less identically on different platforms, it is always possible to write non-portable and platform-dependent code. Here are some guidelines and suggestions for 2-D graphics programming.

Minimal display capabilities

A compliant display is expected to have a minimal set of capabilities, that a programmer can rely upon. The following items are always supported by Prima:

Minimal capabilities

Distinct black and white colors

At least one monospaced font

Solid fill

rop::Copy and rop::NoOper

Plotting primitives

SetPixel,GetPixel

Line,PolyLine

Rectangle

FillPoly

TextOut

PutImage,GetImage

Information services

GetTextWidth,GetFontMetrics,GetCharacterABCWidths

GetImageBitsLayout

Properties

color

backColor

rop

rop2

fillPattern

fillMode

textOpaque

clipRect

All these properties must be present, however, it is not required for them to be changeable. Even if an underlying platform-specific code can only support one mode for a property, it has to follow all obligations for the mode. For example, if the platform supports full functionality for black color but limited functionality for the other colors, the wrapping code should not allow the color property to be writable.

Inevident issues

Colors

Black and white colors on paletted displays

Since paletted displays use indexed color representation, the 'black' and 'white' indices are not always 0 and 2^n-1, so if one uses the indexes for the actual black and white colors in the palette, the result of raster image operations may look garbled (X11). Win32 protects itself from this condition by forcing white to be the last color in the system palette.

Example: if the white color on the 8-bit display occupies palette index 15 then the desired masking effect wouldn't work for xoring transparent areas with cl::White.

Workaround: Use two special color constants cl::Clear and cl::Set, that represent all zeros and all ones values for bit-sensitive raster operations.

Black might be not 0, and white not 0xffffff

This obscure issue happens mostly on the 15- and 16-bit pixel displays. Internal color representation for the white color on a 15-color display ( assuming R,G and B are 5-bit fields) is

 11111000 11111000 11111000
 --R----- --G----- --B-----

that equals 0xf8f8f8.

A bit of advice: do not check for 'blackness' and 'whiteness' merely by comparing to the 0x000000 or 0xffffff constant.

Filled shapes

Dithering

If a non-solid pattern is selected and the background and/or foreground color cannot be drawn as a solid, the correct rendering may require 3 or even 4 colors. Some rendering engines (Win9X) fail to produce correct results.

Pattern offset

If a widget contains a pattern-filled shape, its picture will always be garbled after scrolling because it is impossible to provide an algorithm for a correct rendering without prior knowledge of the widget's nature. (All)

Workaround: Do not use patterned backgrounds or use fillPatternOffset property. Since the same effect is visible on dithered backgrounds, check if the color used is pure.

Lines

Dithering

Dithering might be not used for line plotting. (Win9X)

Fonts

Font metric inconsistency

A font is loaded by request with one size but claims another afterward (X11).

Impact: system-dependent font description may not match Prima's.

An advice: do not try to deduce Prima font metrics from system-dependent ones and vice versa.

Transparent plotting

No internal function for drawing transparent bitmaps (to implement text plotting). Therefore, if a font emulation is desired, special ROPs cannot be reproduced. (Win9X, WinNT)

Impact: font emulation is laborious, primarily because the glyphs have to be plotted by consequential and-ing and xor-ing a bitmap. A full spectrum of the raster operations cannot be achieved with this approach.

Text background

If a text is drawn with a non-CopyPut raster operation, the text background is not expected to be mixed with glyphs - however, this is too hard to implement uniformly, so results may differ for different platforms.

Text background may be only drawn with pure ( non-dithered ) color (win32) - but this is (arguably) a more correct behavior.

A bit of advice: Do not use ::rop2 and text background for special effects

Internal platform features

Font change notification is not provided. (X11)

Raster fonts cannot be synthesized (partly X11)

Raster operations ( ROPs)

The background raster operations are not supported (X11,Win9X,WinNT. Not all ROPs can be emulated for certain primitives, like fonts, complex shapes, and patterned shapes.

It is yet unclear which primitives have to support ROPs, - like FloodFill and SetPixel. The behavior of the current implementation is that they do not.

Palettes

Static palettes

Some displays are unable to change their hardware palette, so detecting an 8- or 4-bit display doesn't automatically mean that the palette is writable.(X11)

Widget::palette

The Widget::palette property is used for an explicit declaration of extra colors needed by a widget. The request might be satisfied in different ways, or might not be at all. It is advisable not to rely on platform behavior for the palette operations.

Dynamic palette change

It is possible (usually on 8-bit displays) for a display to change asynchronously its hardware palette to process different color requests. All platforms behave differently.

Win9X/WinNT - only one top-level window at a time and its direct children ( not ::clipOwner(0)) can benefit from using the Widget::palette property. The system palette is switched every time as different windows move to the front.

X11 - Any application can easily ruin the system color table. Since this behavior is such by design, no workaround can be applied here.

Bitmaps

Invalid scaling

Bitmap scaling is invalid (Win9X) or not supported (X11 without XRender). A common mistake is to not take into account the fractional pixels that appear when the scaling factor is more than 1

Workaround: described in "zoom" in Prima::ImageViewer .

Large scale factors

Request for drawing a bitmap might fail if a large scaling factor is selected. (Win9X,WinNT). This is probably because these platforms scale the bitmap into memory before the plotting takes place.

Layering

On win32, layered widgets with pixels assigned zero alpha component, will not receive mouse events.

Platform-specific peculiarities

Windows 9X

The number of GDI objects can not exceed some unknown threshold - experiments show that 128 objects is a number that is safe enough.

The color cursor creation routine is broken.

Filled shapes are broken.

X11

No bitmap scaling (if compiled without XRender)

No font rotation (if compiled without Xft)

No GetPixel, FloodFill ( along with some other primitives)

White is not 2^n-1 on n-bit paletted displays (tested on XFree86).

Filled shapes are broken.

Color bitmaps cannot be drawn onto mono bitmaps.

Implementation notes

Win32

The plotting speed of DeviceBitmaps is somewhat less on 8-bit displays than when plotting Images and Icons. It is because DeviceBitmaps are bound to their original palette, so putting a DeviceBitmap on a drawable with a different palette uses inefficient algorithms to provide correct results.

X11

If an image was first drawn on a paletted Drawable, then drawing it on another paletted Drawable would reduce the image to 8 safe colors.

This is by design and is so because the image has a special cache in the display pixel format. Refreshing the cache on every PutImage call is very inefficient (although technically possible). It is planned to fix the problem by checking the palette difference for every PutImage invocation. NB - the effect is seen on dynamic color displays only.

AUTHOR

Dmitry Karasik, <dmitry@karasik.eu.org>.

SEE ALSO

Prima