Mapping Modes


Although the enumeration unit documents the available mapping modes, further elaboration is in order. The mapping mode is a device context attribute that affects virtually all drawing that can be performed on the client area of a window. Closely related to the mapping mode are the device context attributes of

Most functions that output to a device context require the specification of coordinates. For example, the function text_out requires a vector to position the text to be rendered (or it draws text at the current position). The point supplied to position the text is relative to the logical, two dimensional coordinate system in effect. When rendering graphics, the operating system translates logical coordinates into device coordinates. The transformation that is performed is governed by:

currently in effect. The mapping mode determines the orientation of the x and y axes. The enumeration unit contains eight mapping modes, including the mapping mode unit::twips. The expression twip comes from the phrase "twientieth of a point". A point is a typographic value representing 1/72 of an inch. Therefore, 1 twip = 1/1440 inches. The mapping mode may be set and queried (respectively) by the functions:

The default mapping mode is unit::pixel. In this mode, logical units map directly to pixels (starting at the top, left corner of the window and proceeding to the right for positive x-values and down for positive y-values).

The Device Coordinate System

Although most of the measurements that have been discussed lie within the client area of a window, the operating system uses two other coordinate systems. all device coordinate systems are expressed in terms of pixels. When reference is made to the entire area of the display, the coordinate system is referred to as screen coordinates, where, the upper left corner of the screen is the origin (0,0). When dealing with main (non-child) windows, screen coordinates are used for the message message::move. Screen coordinates are also used for creating and moving main windows. Other functions that make use of screen coordinates are:

Whole window coordinates refer to coordinates relative to the actual origin of the window rather than the origin of the client portion of the window. This is usually the upper-left point of the sizing border of the window. The function get_window_device_context yields a device context whose logical coordinate system maps to whole window coordinates.

The third coordinate system is the client coordinate system. Logical coordinates are mapped to client coordinates when a device context is obtained through:

Client coordinates may be converted to screen coordinates and vice-versa via the C functions:

The Window and the Viewport

The following functions are applicable to changing window and viewport extents:

The unit or mapping mode defines how windows maps logical coordinates to device coordinates. The window coordinate system is specified in logical coordinates whereas the viewport coordinate system is measured in device coordinates. For all mapping modes of a device context, logical (window) coordinates are mapped to device (viewport) coordinates according to the following formulae:

xViewport = (xWindow - xWindowOrigin) * xViewportExtent/xWindowExtent + xViewportOrigin
yViewport = (yWindow - yWindowOrigin) * yViewportExtent/yWindowExtent + yViewportOrigin

where:

(xWindow,yWindow) is the point being mapped,
(xWindowOrigin,yWindowOrigin) is the window origin in logical coordinates,
(xWindowExtent,yWindowExtent) is the window extent in logical coordinates,
(xViewportOrigin,yViewportOrigin) is the viewport origin in device coordinates and
(xViewportExtent,yViewportExtent) is the viewport extent in device coordinates.

Each of the extents has no meaning in itself; however, the ratios of the window extents to the viewport extents provide the scaling factors when performing the conversion of logical units to device units and vice-versa. The extents may be negative. In most mapping modes, the extents are implied by the mapping mode. The formulae for translating viewport (device) coordinates to window (logical) coordinates are shown below.

xWindow = (xViewport - xViewportOrigin) * xWindowExtent/xViewportExtent + xWindowOrigin
yWindow = (yViewport - yViewportOrigin) * yWindowExtent/yViewportExtent + yWindowOrigin

The function device_points_to_logical_points may be used to convert device points to logical points; whereas, the function logical_points_to_device_points converts logical points to device points.

The Mapping mode unit::pixel

The mode unit::pixel is such that the programmer may interpret coordinates as pixels relative to the upper-left corner of the window. Other unit modes have their origin as the upper-left corner of the window; however, positive y-coordinates extend upwards instead of downwards (which yields a right handed coordinate system). In the case of unit::pixel, the mapping from logical to device coordinates reduces to the following equations.

xViewport = xWindow - xWindowOrigin + xViewportOrigin
yViewport = yWindow - yWindowOrigin + yViewportOrigin

The default origins and extents are shown in the table below.

Entity Default Changeability
window Origin (0,0) Can be changed.
window Extent (1,1) Cannot be changed.
Viewport Origin (0,0) Can be changed.
Viewport Extent (1,1) Cannot be changed.

The Metric Mapping Modes

Five of the available mapping modes map logical coordinates to fixed physical measurements. These are: unit::low_metric, unit::high_metric, unit::low_english, unit::high_english and unit::twips. For each of these units, the default viewport origin and the default window origin is (0,0), which may be adjusted. The window and viewport extents are calculated to obtain the correct mapping of logical to device units and are based on the aspect ratio and resolution of the device. Clearly, these extents may not be changed.

For all units apart from unit::pixel, coordinates within the client window have negative y values; although, the functions set_viewport_origin and set_window_origin may be used to change this. This fact is illustrated by the snapshot (below) of the program of this section running. Irrespective of what coordinate system is in effect, windows uses device coordinates for all messages - such as: message::move, message::size and message::mouse_move.

All non-graphics functions and some graphics functions also use device coordinates. Each function in the reference documents whether the coordinates are device coordinates or logical coordinates.

unit::isotropic and unit::anisotropic

The only unit modes for which the viewport and window extents can be changed are unit::isotropic and unit::anisotropic. These unit modes allow the physical size of a logical unit to be adjusted - whereas the other unit modes do not. Isotropic coordinates are such that equal logical coordinates on the x and y axes represent the same physical distance. This is partially constrained in the sense that the operating system adjusts the viewport and window extents such that mapping from logical to physical coordinates yields equal physical values for both directions. Mapping mode unit::anisotropic is unconstrained in the sense that the viewport and window extents may be altered without the operating system making other adjustments. all other unit modes are fully constrained and the window and viewport extents may not be adjusted.

What size is the window

The program of this section demonstrates the various mapping modes applicable to drawing in a window. The output of the program is shown below.

To facilitate displaying the size of the window for the different unit modes, the unit mode unit::anisotropic is used with logical units set to the dimensions of a character. The code fragment:

set_mapping_mode(device_context,unit::anisotropic);
set_window_extent(device_context,1,1);
set_viewport_extent(device_context,
                  width_of_character,
                  height_of_character);

does this. This enables the function text_out to specify logical coordinates in character row and column coordinates for a fixed pitch font. The calls that cause each unit mode to be displayed are:

show_size(window_handle, device_context, 1, 3, unit::pixel, L"Pixels                  ");
show_size(window_handle, device_context, 1, 4, unit::low_metric, L"Low Metric (.1mm)       ");
show_size(window_handle, device_context, 1, 5, unit::high_metric, L"High Metric (.01mm)     ");
show_size(window_handle, device_context, 1, 6, unit::low_english, L"Low English (.01 inch)  ");
show_size(window_handle, device_context, 1, 7, unit::high_english, L"High English (.001 inch)");
show_size(window_handle, device_context, 1, 8, unit::twips, L"TWIPS (1/1440 inch)     ");

where, the function show_size is as shown below.

void show_size(handle window_handle,
    handle device_context,
    int x_text,
    int y_text,
    int map_mode,
    const character* map_mode_string)
{
    character buffer[60];

    save_device_context(device_context);

    set_mapping_mode(device_context, map_mode);

    irectangle client;
    get_client_rectangle(window_handle, &client);
    device_points_to_logical_points(device_context, (ipoint*)&client, 2);

    restore_device_context(device_context, -1);

    text_out(device_context,
        x_text,
        y_text,
        buffer,
        print_string(buffer, L"%-20s %8d %10d",
            map_mode_string,
            client[1](0),
            client[1](1)));
}

Firstly, the current device context is saved. The specified unit mode is then set for the device context. The client rectangle is queried and converted to logical coordinates. This yields the size of the window in the logical coordinates currently in vogue. The function print_string is used to format the string to be displayed. The device context is then restored and the resultant string is drawn in the previously defined anisotropic coordinate system.