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
andcl::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>.