.if n .pH arch.cmap @(#)cmap	40.1

.ig
imaged dc 8/30/89
docformat -c -s4 -dqm4 fn
..
.\" turn off automatic hyphenation -- JHevelin (08-09-89)
.am RT
.nh
..
.nh
.ds S) Shapes
.BK "Shapes Internal Architecture"
.CH "CMAP Object" "5"
.H 1 "CMAP Object" 
.H 2 "Introduction"
.P
The cmap object has two functions.
It supports access to hardware color map capabilities.
It also provides software color map functionality
on devices without a hardware color map.
.P
The implementation of the various color map
operations primarily depends on the depth of the
RASTER with which the color map is associated.
\*(S) has generic implementations for rasters of depth 1 and 8.
Shapes also has an implementation for depth 4 VGA devices.
The only cmap operation that is always
device-dependent is color map installation,
where the contents of the color map are copied
from an internal data structure
(which is not device-dependent)
into the color map hardware.
.H 2 "Cmap Attributes"
The external cmap attributes are documented in the
\f2Shapes Reference Manual\f1.
This section discusses the internal attributes that are
used in the implementation of the cmap object.
All cmap attributes are defined in include/sh_CMAP.ah;
their values are defined in include/sh_CMAP.h and
include/di/cmap.h.
.PC
COL_type CMAP_INPUT;
COL_type CMAP_OUTPUT;
COLOR    *((*CMAP_FUNC)());
short    CMAP_OFFSET;
RASTER   CMAP_RASTER;
short    CMAP_SIZE;
int      (*cmap_apply_func)();
char     cmap_depth;
char     cmap_flags;
OBJID    cmap_data;
.SF
.H 2 cmap_depth
.P
The minimum raster depth required to support a color map specified by the
variables of CMAP_SIZE entries and offset CMAP_OFFSET.
It is used internally to convert the CMAP_SIZE
information from ``number of entries'' to
``bits per pixel required for color map,''
and can be easily converted to a bit plane mask.
It is computed by the internal function
CMAP.c:new_depth whenever the color map offset or
size is changed.
.H 2 cmap_flags
.P
The CMAP_FUNC_FLAG indicates the contents of the
hardware color map are invalid and forces
Install_Cmap to reapply the color mapping
function to generate new color map data.
If this flag is set,
Install_Cmap assumes the hardware color map
is valid and does nothing.
Otherwise, it regenerates cmap_data by calling
CMAP_FUNC and loads the result into the hardware
unless the CMAP_FUNC_IGNORE flag is set.
This flag is set whenever cmap_data has been
written using the Write_Cmap operator.
It is assumed that the data supplied in
Write_Cmap overrides that which would be produced
by CMAP_FUNC.
Once the CMAP_FUNC_IGNORE flag is set for a particular cmap,
it remains set until the CMAP_FUNC attribute is reset.
.H 2 cmap_data
.P
Although cmap_data can be both device- and depth-dependent,
the generic implementation uses the same format
for all cmap objects.
The color map entries are held as 3 successive
tables of characters, one for red, one for green,
and one for blue.
For monochrome color maps, however,
only the red section is allocated and used.
.P
Creation and population of cmap_data is deferred
until the color map is actually installed by
Install_Cmap.
Its size is based on the next power of 2 greater
than or equal to CMAP_SIZE,
and it holds the return values of successive
calls to CMAP_FUNC.
If the color map size changes between one
Install_Cmap call and another,
cmap_data is re-sized.
.P
Once the color map is installed,
cmap_data is created.
Its size is based on CMAP_SIZE,
and it holds the return values of successive
calls to CMAP_FUNC.
If the color map size changes between one
Install_Cmap call and another,
cmap_data is re-sized.
.H 2 cmap_apply_func
.P
This variable points to the function that
implements the Apply_Cmap operator.
Apply_Cmap converts the device-independent \*(S)
COLOR structure to a device-dependent color.
This color may be a color map index or a pixel value.
It is represented as a longword (4 bytes).
In most cases,
\*(S) uses inline Apply_Cmap macros to convert colors,
but when it is necessary to call Apply_Cmap from
device-independent code,
this function is called.
.P
The exact function of cmap_apply_func is based on
raster depth and color model.
For example, Apply_Cmap for an indexed color
model on a 1-bit raster would be different from
that of a direct color model on an 8-bit raster.
The former would use the color as an index into a
software color map,
and the return value would be the pixel (1 bit)
to paint.
The latter would decompose the RGB color into 3
indices for mapping tables to select a color out
of the RGB color cube that is closest to the RGB
color requested.
The return value would be an index into the color
map representing the RGB color cube.
.P
It is important to note that although Apply_Cmap
is dependent on raster depth and color model,
it is not totally device-dependent.
It returns a device-dependent color
representation but does not handle actually
loading this color into device registers.
.H 2 "Cmap Operators"
The calling conventions of the external cmap operators
are documented in the
\f2Shapes Reference Manual\f1.
This section discusses the implementation of these operators,
assuming the reader is familiar with their behavior.
We also describe internal cmap operators that are used by \*(S)
but not intended to be user-callable.
All cmap operators are defined in include/sh_CMAP.h.
.H 2 "Get_Cmap, Set_Cmap"
.P
All of the cmap attributes are inquired via macros.
The name of the attribute is used to generate a specific macro to
return the structure field associated with the attribute.
Macros for attributes that require computation generate calls
to the internal Get_Cmap operator.
All cmap attributes are set with subroutine calls.
.P
The following section of code shows the macro definitions for
cmap attributes to illustrate the different methods:
.PC
#define Get_Cmap(c,a)     CAT(a,get)((CMAP)(c))
#define CMAP_INPUTget(c)  ((c)->CMAP_INPUT)
#define Set_Cmap(c,a,v)   ((void) GetOper_Obj(c, CMAP_OP_Set)
                                             (c, a, v))
.SF
.H 2 Apply_Cmap
.P
Converts a \*(S) color object values to pseudo-device-dependent values.
.H 2 Install_Cmap
.P
Copies the color map entries associated with cmap
into the appropriate color mapping hardware.
The generic version of Install_Cmap maintains the
color map entries in a device-independent data
area referenced by the cmap_data field.
.P
The existence of cmap_data is a performance
enhancement and is used to support Write_Cmap amd Read_Cmap.
Since color mapping is specified by a user function (CMAP_FUNC),
you can re-apply this function each time the color map is
installed.
Although the format of cmap_data is the same for
all generic implementations of the cmap object,
it is not a requirement.
Since cmap_data is private to the cmap object,
its format may be device-dependent if desired.
.P
Install_Cmap is called by Set_Raster when the
RAS_CMAP attribute is changed and performs the following:
.AL
.LI
If the color map data in the hardware is valid, returns.
The CMAP_FUNC_FLAG is set if the hardware has
already been loaded and no relevant cmap
attributes have changed since then.
.LI
Establishes a color map data area (cmap_data) by
re-sizing the existing data area or allocating a
new one (if cmap_data is NULL).
.LI
Recalculates the color map by calling the color
mapping function CMAP_FUNC
(from CMAP_OFFSET to CMAP_SIZE \(mi 1).
.LI
Copies the color map data into the color map hardware
.LE
.H 2 Remove_Cmap
.P
Removes the color map data from the hardware.
In the generic versions,
this operation is device-independent.
It clears CMAP_FUNC_FLAG to indicate the color
map hardware no longer has a valid color map.
It is called by Set_Raster when the RAS_cmap
attribute is changed to invalidate the old color map.
.H 2 "Write_Cmap
.P
This routine provides an efficient method of
writing arrays of device dependent color data
directly to the color map,
assuming that the color data exists in one of
several supported formats.
.H 2 "Read_Cmap
.P
This routine provides an efficient method for
reading arrays of device dependent color data
directly from the color map.
It will output the color data in one of several
supported formats.
.P
Currently supported formats for Write/Read_Cmap
include the following:
.PC
/*
 *	Write/Read_Cmap data formats
 */
#define	CMAP_UNPACKED_RGB	0
#define	CMAP_PACKED_RGB		1

typedef	struct
  {
    Sgn16	index;		/* starting cmap index */
    Sgn16	count;		/* number of cmap locations */
    Sgn16	*red;		/* list of RED values */
    Sgn16	*green;		/* list of GREEN values */
    Sgn16	*blue;		/* list of BLUE values */
  } *CMAP_RGB_UNPACKED, CMAP_RGB_UNPACKED_DATA;

typedef	struct
  {
    Sgn16	index;		/* starting cmap index */
    Sgn16	count;		/* number of cmap locations */
    Unsgn32	*rgb;		/* list of 0/B/G/R values */
  }*CMAP_RGB_PACKED, CMAP_RGB_PACKED_DATA;
.SF
.H 2 "Porting Considerations"
.P
The implementation of most cmap operations is
determined by the depth of the RASTER with which
the color map is associated.
The reference port has generic implementations
for rasters of depth 1 and 8 and for depth 4 VGA.
Color map installation (Install_Cmap) is
the only operation that is always device-dependent.
During installation,
the contents of the color map are copied from an
internal data structure into the color map hardware.
.P
The simplest way to port the cmap object is to
select one of the generic implementations and
replace the color map installation operator
Install_Cmap.
You will need to supply implementations for other
cmap operations under the following conditions:
.BL
.LI
Your color mapping hardware requirements are not
satisfied by the generic implementation.
.LI
You have a raster that is not depth 1, 4, or 8.
.LE
.P
If you are redefining Install_Cmap for a raster
depth that is already supported (1 or 8),
you can just call the generic Install_Cmap to
generate the color map in cmap_data and then copy
the contents of cmap_data into your hardware.
.P
If your color map is for a raster depth that is not in
the generic version,
or if the generic cmap_data is
incompatible with your hardware,
you will need to define your own cmap_data format.
In this case,
you must explicitly call the color mapping function, CMAP_FUNC,
in your version of Install_Cmap and use the
results to generate your own cmap_data.
The creation and use of cmap_data is confined
within the Install_Cmap operation;
it is not public to other Shapes objects or used
by other cmap operations.
