Rendition Overview
      Most driver actions draw something on the display and, as a result, require attributes that specify how objects are to be drawn. Renditions are bundles of attribute values. The rendition is a substructure of the display context, which contains a set of pointers to instances of each of the defined rendition types, which contain the current values of the relevant attributes.

      The content of the HT_Rendition object consists of the following:

      The header file rendition.h contains declarations of several types of renditions, each applicable to a particular class of objects. The frequently used renditions, along with their attributes that can be queried or set, are listed below:
          HT_Net_Data
          HT_Transform_Data
             depth_buffering 
             hard_clip 
             viewport 
             camera 
             modelling_matrix
             viewing_matrix 
             projection_matrix 
             screen_matrix 
             object_to_device 
             world_to_device
          HT_Line_Data 
             line_weight 
             line_pattern 
             line_cap 
             line_join 
          HT_Color_Data 
             color 
             matched_color 
             color_index 
             contrast_color 
             matched_contrast_color
             contrast_color_index 
             background_color 
             matched_background_color 
             background_color_index
             shader 
             add_light 
             light 
          HT_Face_Data 
             face_pattern 
             face_displacement 
          HT_Marker_Data 
             marker_symbol 
             marker_size 
          HT_Misc_Data 
             mixing_mode 
             pattern_mode 
             perspective_correction 
             interpolation_level
      The drawing actions all take a rendition argument, giving the driver writer access to all the attributes that your driver needs for drawing all types of objects:
        HT_Rendition *hr


      Incarnations
      Every rendition has a set of incarnations that are identifiers unique to the particular set of attribute values contained in the rendition. An incarnation is a number that can be checked quickly to determine whether all attribute values have remained the same. A net incarnation provides a unique identifier for all attributes in the rendition. Your driver should maintain, in its local state data, the most recent incarnations of its relevant rendition types that it uses. Then, each action function can check the incarnations of its relevant renditions against the previous values. If the current incarnation value is unchanged from the previous call, then the action does not need to update the attribute state.

      Checking incarnations can be important on devices for which attribute changes are expensive. If the application retains a high level of attribute coherence when it is performing its database traversal, then the incarnation values may help limit the number of attribute changes significantly.

      This section describes particular rendition types with the actions that use them. Many drawing actions require you to adhere to the attributes in the rendition. For example, the draw_dc_polyline action needs to look up the attributes line_cap, line_pattern, and line_join that are specified in the line rendition. The driver may query these through the access member functions of the HT_Rendition class. Specifically, these rendition attributes can be queried like this:

        HT_Rendition *hr;
        HT_Line_Cap my_line_cap = hr->line_cap();
        HT_Line_Pattern my_line_pattern = hr->line_pattern();
        HT_Line_Join my_line_join = hr->line_join();
      Color Attributes
      Almost all drawing primitives reference the color attributes. Included in the color attributes are color by RGB, color by palette index, a contrast color for patterns and materials, a background color for XOR, and a matched color.

      The color system defines whether the color or color index is used when rendering primitives. Both the color and color index are always valid. Contrast colors are used to fill the 0 (off) bits in face and line patterns. Background colors are used as a reference for clearing the drawing buffer and drawing in the XOR mixing mode.

      Matched color needs more explanation. It is provided automatically by Heidi when the original RGB color that the application requested is not available in the current driver palette. In this case, matched color is the closest RGB value that approximates the original color. The best matched color index number is then stored in the color index.

      Usually, matched colors are the same as the color set provided by the application. Only when the application requests a true color on a mapped RGB (8-bit) display does the matched color differ from the original color. In this case, Heidi is trying to match the original color to the available RGB color entry. Since matched color is what the physical device uses, Heidi driver developers should always use the matched color as the current RGB drawing color.

      Miscellaneous Attributes
      The rendition contains two miscellaneous attributes. The first attribute, mixing_mode, defines the logical operation used when drawing filled primitives, such as faces and text, are drawn. The logical operation is an enumeration value defined in the class HT_Mixing_Mode. Currently, two values are supported, Exclusive_Or and Copy. The Exclusive_Or mode specifies that the destination pixel should be the XOR of the source pixel and the destination pixel. The Copy mode specifies that destination pixel should be replaced by the source pixel.

      The second attribute, pattern_mode, defines the drawing mode to use when filled primitives, such as faces and text, are drawn. The drawing mode is an enumeration value defined in the class HT_Pattern_Mode. For more information see HT_Rendition::pattern_mode in appendix A, "Heidi Class Reference."

      Line Primitive Attributes
      The rendition contains a set of line attributes that the driver must adhere to when displaying line primitives.

      Line primitives are all generally subject to the line_weight and line_pattern attributes. The polyline primitives are also subject to the line_cap and line_join attributes. In addition, line primitives are generally subject to the color attributes color and color_index. The exception is the colorized and Gouraud primitives, which are not subject to the line color attributes in the rendition. Instead, the colorized routines have their line color passed through a data structure in an additional parameter and the Gouraud routines are passed colors to be interpolated. They are also subject to the miscellaneous attributes mixing_mode and pattern_mode.

      Notes: A line_weight of "0" or "1" represents a single pixel line.
      Heidi now draws the last pixel of a polyline in order to facilitate the display of weighted lines rasterized as polytriangles. In the past, this pixel was drawn by applications¾for example, AutoCAD through its DisplayList, adding it as an extra point to the geometry.
       

        Line Patterns
        The line pattern is represented by the line_pattern attribute in the line rendition. Heidi defines a set of line patterns in an enumeration inside the class HT_Line_Pattern in pattern.h. The fixed patterns include the following:
           
          Solid,
          Dashed,
          Dotted,
          Dash_Dot,
          Short_Dash,
          Medium_Dash,
          Long_Dash,
          Short_Dash_X2,
          Medium_Dash_X2,
          Long_Dash_X2,
          Medium_Long_Dash,
          Medium_Dash_Short_Dash_Short_Dash,
          Long_Dash_Short_Dash,
          Long_Dash_Dot_Dot,
          Long_Dash_Dot,
          Medium_Dash_Dot_Short_Dash_Dot,
          Sparse_Dot,
          User_Defined,
        To access the line pattern definitions, you must use member functions of the HT_Renderer class. The initialization action is
         
          short const * line_pattern_lengths (HT_Line_Pattern pattern) const
        This method, line_pattern_lengths, allows access to each line pattern length array. The function accepts a line pattern index and returns a pointer to an array of shorts containing information defining the line pattern.

        The first element in the array is a scaling factor for adaptive patterns. It is the total of the lengths of dashes, spaces, dots and so forth in the pattern¾for example, the actual length or a percentage length that will display a line type pattern span within the varying segments of a polyline. This equals 50 in the example following. The second element in the array is a count of spans. This is followed by the set of numbers terminated by -1. The driver should alternate drawing styles for the percentage of pixels given by each successive span number. For the first number in the pair, draw the face color. For the next number in the pair, draw nothing if the pattern mode is Hollow or draw the contrast color if the pattern mode is Filled. Then, alternate with another pair. When the end of the span array has been reached, you should start again at the beginning of the array.

        This is best illustrated with an example. The internal code span array for dash_dot looks like this:

          dash_dot[] = {50, 4,     26, 12, 0, 12,                 -1}
          
          pattern_scale = dc->requirements().m_pattern_scale;
          
          where dc is a pointer to a HT_Renderer or HT_Device.
        In translation, this means that the scale factor is 50, there are 4 spans and the driver should draw 26 * pattern_scale * line_pattern_scale on pixels (the current drawing color), followed by 12 * pattern_scale * line_pattern_scale off pixels (the contrast color ), followed by a single on pixel that is as small as possible. 0, here, means that the line pattern requests a span that is as small as can  possibly be drawn. 0 is followed by 12 * pattern_scale * line_pattern_scale off pixels, followed by the terminator -1, which indicates that you must then repeat the array for the length of the line. The default pattern scale is 50 pixels. Note that in this example, the user would not see the nominal_length, the count, or the terminator, which are internal functions.

        m_pattern_scale, a method of HT_Device_Requirements, stores the pattern_scale factor and represents 100% of a normal line pattern for video displays. This defaults to 50 pixels. For hardcopy devices, it is recommended that the pattern_scale device requirements be set to a number of pixels corresponding to 1/2 inch. (It is the responsibility of the hardcopy driver writer to set the pattern_scale to a value that correctly represents their particular device.)

        The span value is again multiplied by another line scale parameter, line_pattern_scale, which is set at the rendition. Thus the plotted line pattern is affected by 2 scale factors¾at the renderer level, pattern_scale, and at the rendition level, line_pattern_scale.

        You may also override these definitions if your hardware has specific built-in lengths. By overriding, you can make standard routines match the output from your hardware, which generally accelerates line drawing. The hardware line patterns, however, do not always match the Heidi definitions. We recommend adding a driver specific option, for example "Use Hardware Line Pattern" and let the application decide whether it wants the faster but less accurate hardware line patterns or the more precise but slower software patterns.

        Custom line patterns can be developed from HT_Dash_Pattern. If set_line_pattern is called with an HT_Dash_Pattern, then the line pattern type is automatically set to User_Defined.

        Line Caps and Joins
        The line cap and line join attributes define the appearance of the line and dash start and endpoints, and inner vertices as follows:
         

          line_cap  specifies the line cap, or finish, of the ends of the line if they are the same: that is the first vertex and last vertex of a nonclosed polyline.
             
          line_start_cap and line_end_cap specify the type of  start cap and end cap for lines, if the start and end caps are different.

          line_end_cap_solid  controls the drawing of solid end caps for nonclosed polylines.

          dash_cap specifies the start and end caps for dash lines if the caps are the same. If the start and end caps are different, then it is undefined and dash_start_cap and dash_end_cap would be used.  dash_cap can be applied to dashes within the dash line.

          dash_start_cap and dash_end_cap specify the start and end caps for dashed lines, if the start and end caps are different. These methods can also be applied to dashes within the dashed line.

          There are four enumeration values defined in class HT_Line_Cap:
           

            Butt ¾ Line end is specified as the line perpendicular to the relevant segment of the polyline and going through the endpoint of the line or dash. This is shown in figure 10.

            Round ¾ Line end formed by a semicircle centered at the endpoint of the line. See figure 11.

            Square ¾ Line end formed by a square centered at the endpoint of the line. See figure 10.

            Diamond ¾ Line end formed by a triangle centered at the endpoint of the line. See figure 11.
             

          line_join specifies the line join, or finish, around a vertex other than an end.

          line_joins_solid controls the drawing of solid joins.

          There are four enumeration values for these line join methods defined in class HT_Line_Join:
           

            Miter ¾ The two edges of the nominal segment on the exterior side of the angle are extended to where they intersect and the polyline image is filled out to the boundary formed by those extended edges. Thus, the miter case involves adding another kite-shaped area to the line at each join, as shown in figure 10.

            Bevel ¾  A line is drawn between the corners of the two nominal segments exterior to the angle of the join, and the polyline image is filled out to this line. Thus, the bevel case involves adding an equilateral triangular area to the line at each joint, as shown in figure 10.

            Round ¾ An arc of a circle is drawn tangent to the two edges of the nominal segments exterior to the angle of the join, and the polyline image is filled out to this arc, as shown in figure 11.

            Diamond ¾ Two lines are drawn  from the corners of the two nominal segments exterior to the angle of the join. These lines extend to a point, and the polyline image is filled out to them. The "vertex" point of these lines is 1/2 line width from the intersection of the midpoints of the ends of the nominal segments, as shown in figure 11.
             

        Note, that the values of these methods are relevant only to wide polylines: that is, with
          line_weight() > 1
        To specify the shape of the different caps and joins, it is useful to introduce the notion of a nominal segment rectangle. This is the simplest figure generated by the polyline between two successive vertices. Specifically, the nominal segment rectangle of a line segment is a rectangular area with the two vertices of the line segment at midpoints of a pair of opposite edges of the rectangle (of length equal to the line width). The other pair of rectangle edges are equal to the distance between the vertices of the line segment.

        The top illustration, figure 9, shows a three-point (two-segment) wide polyline with its two nominal segment rectangles drawn in outline and its three vertices shown as heavy dots. The area inside either (or both) of the nominal segment rectangles is covered by the polyline, including the kite-shaped region just above the join vertex. However, there is a notch below the join vertex that is not in either nominal segment rectangle. This notch must be filled in to make a smooth wide polyline.



    Figure 9. Two segment polyline


     



     


    Figure 10. Butt & square caps with miter & bevel  joins


     



     


    Figure 11. Round & diamond caps with round & diamond  joins


      Face Primitive Attributes
      The face rendition contains a set of face attributes that the driver must adhere to when drawing any filled region. For a complete list, see class HT_Renderer in appendix A, "Heidi Class Reference."

      The face primitives are subject to the face attributes face_pattern and face_displacement of class HT_Rendition.  In addition, face primitives are generally subject to the color attributes color, color_index, contrast_color, contrast_color_index, and material, as well as the miscellaneous attributes mixing_mode and pattern_mode.
       

        Face Patterns
        The Heidi system defines a set of face patterns in an enumeration inside the class HT_Face_Pattern in pattern.h. The patterns include the following:
          Stipple00-Stipple64
          Solid
          Checkerboard
          Crosshatch
          Diamonds
          Horizontal_Bars
          Slant_Left
          Slant_Right
          Square_Dots
          Vertical_Bars
          User Defined
        For all patterns, the pixel to be drawn should take on the face color when the pattern contains a 1. For 0 pattern bits, two options exist: if the current pattern mode is Hollow, then the destination pixel should be left unmodified; if the current pattern mode is Filled, then the destination pixel should be drawn with the contrast color (from contrast_color() or contrast_color_index() in the rendition).

        To access the face pattern definitions, you must use member functions of the HT_Renderer class by calling the following function:

          HT_Byte const * face_pattern_bits (HT_Face_Pattern pattern) const
        This call accesses each face pattern bitmap. The function accepts a face pattern index and returns a pointer to the bitmap.

        The format for the bit patterns is an 8 x 8 monochromatic bitmap stored in 8 sequential bytes. The bytes store the bits of the pattern in row-major order, top row first, with the most significant bit of each byte representing the left-most pixel. The bitmap should be tiled across the face you are drawing.

        User Defined Face Patterns
        You may override the pattern definitions if your hardware has specific built-in patterns. By overriding, you can make standard routines match the output from your hardware.

        In addition to the built-in face patterns, you can specify a user defined face pattern from HT_Fill_Pattern. These user defined equivalents to face pattern definitions can have an arbitrary size and on, off patterning.

        The fill_pattern method of class HT_Rendition queries for the user specified bit map of a fill pattern defined by HT_Fill_Pattern, which is called by set_face_pattern, and is automatically set to User_Defined. The pattern is applied to area fill primitives in the face contrast color over whatever fill color is determined by the color attribute or the lighting and shading computation in effect. Solid means "no pattern", that is, the color covers the filled area completely and the contrast color is not used.  The pattern is applied as a "decal" in screen space, and is not subject to the transformations of the pipeline.

        Using the set_fill_pattern_offset method of class HT_Rendition, a Heidi application developer can supply an offset to control fill patterns ¾ fill pattern anchor. Fill patterns are normally offset from the origin of the view ¾ usually 0,0 for AutoCAD. In this case, the fill pattern does not follow any subsequent relocation of the geometry and appears to change within the polygon. The ability to specify a fill pattern offset allows the pattern to remain fixed with subsequent polygon offsets so that the user can drag a patterned polygon on the screen and the pattern moves with the polygon.

        Note: For all Heidi drivers that fill in the draw_dc_polygon, but not the draw_2d_polygon, core Heidi hands over clipped polygons instead of triangles.

        The built-in face patterns are 8 bits however using HT_Fill_Pattern, you could establish an 18 by 10 honeycomb pattern as shown in the following example.  In this honeycomb fill pattern example read the rows from the bottom up, low bits first with each row padded out to a full byte.
         
         

        //        _,_,_,1,1,1,1,1, 1,1,_,_,_,_,_,_, _,_, 
        //        _,_,1,_,_,_,_,_, _,_,1,_,_,_,_,_, _,_, 
        //        _,_,1,_,_,_,_,_, _,_,1,_,_,_,_,_, _,_, 
        //        _,1,_,_,_,_,_,_, _,_,_,1,_,_,_,_, _,_, 
        //        _,1,_,_,_,_,_,_, _,_,_,1,_,_,_,_, _,_, 
        //        1,_,_,_,_,_,_,_, _,_,_,_,1,1,1,1, 1,1, 
        //        _,1,_,_,_,_,_,_, _,_,_,1,_,_,_,_, _,_, 
        //        _,1,_,_,_,_,_,_, _,_,_,1,_,_,_,_, _,_, 
        //        _,_,1,_,_,_,_,_, _,_,1,_,_,_,_,_, _,_, 
        //        _,_,1,_,_,_,_,_, _,_,1,_,_,_,_,_, _,_,
        The array of values (bytes) for this honeycomb fill pattern is shown following:
         
        HT_Byte honeycomb[] = {
                0x04, 0x04, 0x00,
                0x04, 0x04, 0x00,
                0x02, 0x08, 0x00,
                0x02, 0x08, 0x00,
                0x01, 0xF0, 0x03,
                0x02, 0x08, 0x00,
                0x02, 0x08, 0x00,
                0x04, 0x04, 0x00,
                0x04, 0x04, 0x00,
                0xF8, 0x03, 0x00,
        };
        The face pattern definition for the honeycomb would be as follows:
         
          m_Rendition.set_face_pattern(HT_Fill_Pattern(18, 10, honeycomb));


        User Defined Hatch Patterns
        Hatch patterns are set from the rendition using a method similar to that of user defined face patterns explained in the preceding section. These are vector based fill patterns similar in look to the basic AutoCAD hatch patterns.

        The hatch_pattern method of class HT_Rendition queries for the user specified line set defined by HT_Hatch_Pattern, which is called by set_face_pattern. The pattern consists of some number of parallel line sets defined within a unit square. These are sets of parallel line patterns which cross at various angles and can be skewed (offset) to a specified distance. For more information, an example and illustration, see HT_Hatch_Pattern and HT_Parallel_Line_Set.
         

      Marker Primitive Attributes
      The marker primitive attributes are marker_symbol and marker_size. In addition, marker primitives are generally subject to the color attributes color and color_index, and the miscellaneous attribute mixing_mode.
       
        Marker Symbols
        The marker rendition contains a marker symbol type which may be used for displaying markers. Heidi defines a set of these marker symbols in an enumeration inside the class HT_Marker_Symbol in pattern.h. The symbol types include the following:
          Dot
          Plus
          X
          Star
          Circle
          Circle_With_Dot
          Circle_With_Plus
          Circle_With_X
          Circle_With_Circle
          Circle_Filled
          Box
          Box_With_Dot
          Box_With_X
          Box_Filled
          Diamond
          Diamond_With_Dot
          Diamond_With_Plus
          Diamond_Filled
          Triangle_Up
          Triangle_Up_With_Dot
          Triangle_Up_Filled
          Triangle_Up_Vertex
          Triangle_Up_Vertex_Filled
          Triangle_Down
          Triangle_Down_With_Dot
          Triangle_Down_Filled
          Triangle_Down_Vertex
          Triangle_Down_Vertex_Filled
          Triangle_Left
          Triangle_Left_With_Dot
          Triangle_Left_Filled
          Triangle_Left_Vertex
          Triangle_Left_Vertex_Filled
          Triangle_Right
          Triangle_Right_With_Dot
          Triangle_Right_Filled
          Triangle_Right_Vertex
          Triangle_Right_Vertex_Filled
        The marker size is defined in the rendition with the marker_size() method. This method specifies the size in pixels that the marker must occupy. The marker should be drawn such that its height is no taller than marker_size() pixels and is centered around the marker center location.


      Font Engine
      For a complete description and overview of the Font engine and its implementation, see chapter 5, "The Font Engine."


      NOTE: For a continuation of Chapter 2, "Heidi Architecture", see the "Transformation Pipeline" section.