The information in this article applies to:
SUMMARY
Mapping modes, window extents/origins, and viewport extents/origins
allow for very powerful coordinate manipulation, such as scaling or
moving objects. However, you should be aware that there are cases when
using mapping modes other than MM_TEXT results in improper painting
due to round-off errors.
MORE INFORMATIONTo better understand round-off errors, consider the following code:
This code tells the GDI to treat two logical units (the coordinates
used by most GDI functions), in both the vertical and horizontal
direction, as being equal to three device units (pixels). It then asks
the GDI to draw what amounts to a black rectangle five logical units
wide by three logical units tall starting at the logical point (0,0).
The GDI would translate this request into a request to draw a rectangle 7.5 (5 * 3/2 = 7.5) pixels wide by 3 (2 * 3/2 = 3) pixels tall. However, display cards cannot draw half a pixel, so the GDI would either have to round the width up to 8 or truncate it to 7. If an application relied on one behavior or the other, improper painting could occur. Note that using mapping modes, window origins/extents, and viewport origins/extents does not mean that an application will have round-off errors. The occurrence of round-off errors depends on what these features are used for, the structure of the application, and other factors. Many applications take advantage of mapping modes, window origins/extents, and viewport origins/extents without ever encountering adverse round-off errors. If an application exhibits round-off errors, there are a number of ways to prevent them, some which are described below. Method 1Only use MM_TEXT mapping mode, where one logical unit always equals one device unit. However, the application must do all its own scaling and moving of objects. The benefit of this approach is that the application has strict control over how objects are scaled and moved; you can look at your code to see the algebra that leads to round-off errors, and counter these errors appropriately. The drawback to this approach is that it makes the code more complicated and harder to read than it might be if the SetMapMode, SetWindowOrg, SetWindowExt, SetViewportOrg, and SetViewportExt functions were used.Method 2Mix MM_TEXT mapping mode with the mapping mode required. Sometimes applications only have round-off problems with certain types of objects. For example, in a graphing program, the application might want to set a certain mapping mode to draw a bar graph; this mapping mode might cause the fonts that the application draws to be of the wrong size.To work around problems like this, mix MM_TEXT mapping mode with your mapping mode of choice. You could use MM_TEXT when dealing with objects that need exact sizes or placement and the other mapping mode for other drawing. The benefits and drawbacks of this method are almost the same as those for method 1. However, with method 2, applications can take advantage of mapping modes for some of the scaling and moving of objects. Method 3If window/viewport origins/extents are set at compile time, be sure to only do operations that would result in no round-off errors. For example, take the fraction WindowExt over ViewportExt, and reduce this fraction. Then only do operations that involve multiples of the reduced WindowExt values. For example, given the following
turn this into a fraction and reduce it. It yields:
Therefore, anything done in the x direction could be done using a
multiple of three logical units; anything done in the y direction
could be done using a multiple of nine logical units. For example, if
the application wanted to scroll the window horizontally, it could
scroll 3, 6, 9, 12, and so on logical units without having to deal
with rounding errors. By using these values, the application will
never have round-off errors.
One benefit of this method is that an application can take advantage of window origins/extents and viewport origins/extents. A disadvantage is that the application is limited to a certain set of origins/extents (that is, those built into the application at compile time). Method 4Applications can perform method 3 on-the-fly. This allows the application to deal with arbitrary window origins/extents and viewport origins/extents. To determine the minimum number of logical units an application could use given arbitrary extent values, the following code might prove useful (the code shown is for determining the value to use in the horizontal direction):
The return value from the GetMinWinXFactor function above can then be used just like in method 3 (that is, the application can do all output
based on multiples of this value).
Final NotesThe discussion above did not take into account the window origin, which can contribute to round-off errors. How origins and extents affect the coordinates that GDI uses is summed up in "Programmer's Reference.Developers using mapping modes are encouraged to study the equations presented in the programmer's reference. The GDI uses these equations when converting between logical and device units. When round-off errors occur in an application, it is always a good idea to run the numbers through these equations to try to determine the cause of the errors. Additional query words: 3.00 3.10 4.00 rounding
Keywords : kbNTOS350 kbNTOS351 kbSDKWin32 kbWinOS95 |
Last Reviewed: June 14, 1999 © 2000 Microsoft Corporation. All rights reserved. Terms of Use. |