| United States-English |
|
|
|
![]() |
HP PEX Implementation and Programming Supplement: HP9000 Series 700 Color Workstations > Chapter 6 Writing HP PEXlib Programs HP PEXlib Programming |
|
The remaining sections of this chapter are arranged to supplement the information in the same order that it is presented in the O'Reilly PEXlib Programming Manual. The sections are in order, beginning with the following section, “Color ”. This section begins with a general discussion, a quick primer, on the basics of PEX color support, and follows with a more detailed discussion of the specifics of the HP implementation. A companion publication, Portable Programming with CGE PEX 5.1, covers issues and general interoperability programming recommendations. The application of color in the X Window System and interactions with PEX are often complex so that an understanding of background information makes it easier to accomplish color portability among a wide variety of X servers and display devices. In some areas, conventions for interoperable X color programming have already been developed, particularly in the area of allocating colormap cells. If you're not familiar with X visuals, colormaps, and other basics, a good place to begin is the book Xlib Programming Manual, from O'Reilly. In addition, you'll find good program examples to guide you in dealing with colormaps in the examples directories under 〈pex〉[13]. Various utilities that help you deal with color support are also available and are explained later in this chapter, as well as in the Portable Programming with CGE PEX 5.1. PEX itself does not create any new issues in managing X colors. It requires the same basic series of steps that X applications require:
Color is an important element in shaded images such as those typically drawn via PEX. A PEX application may be more "demanding" in each of these steps than a simple X application. The colormap that is used by your HP PEXlib program must be consistent with the color approximation specified in your program. The colormap's interpolation ramp and the color approximation describing that ramp are limited by the visual selected, which in turn are limited by individual vendors or graphics devices. PEX may not be supported in all visuals. With this in mind, let's take a closer look at these steps. Many simple X applications don't take explicit actions to evaluate the color capabilities of a visual for this step. That's because they simply use the default visual for the X server. The default visual is often a PseudoColor visual of eight or fewer planes and is occasionally located in the overlay planes if the device has them. A PEX application, on the other hand, is often more sophisticated about visual selection. PEX rendering may not be supported in the default visual for the server, either because the default visual is not capable of the kinds of color ranges that PEX images require, or because the graphics rendering pipeline needed for PEX cannot support that visual. It may also be because it has other limitations that make using it difficult for PEX. The bottom line is, an application should not simply create a window in the default visual and expect PEX to successfully create a renderer and draw in it. Instead, the application should select a visual type based on application needs and one which PEX supports. You'll find that the PEXlib Programming Manual features a utility procedure that chooses a PEX-capable visual, ora_find_best_visual(). Since PEX usually requires a lot of color cells in order to display a shaded image well, this utility searches for the visual with the most colors. It also prefers read-only visuals such as TrueColor. While this procedure can be used on many servers, it may not work on some others. Your application may need to use a more involved method to choose a PEX visual. For example, if your application needs to use double-buffering, it must choose a visual that supports that operation. It is wise to use PEXMatchRenderingTargets when using a PEX 5.1 server, because this routine lets the application know positively whether or not a visual is supported by PEX. Ready-made solutions to the visual selection problem and other problems are available in the utilities directories under 〈pex〉[14]. They contain a number of utilities to help programs select visuals as well as resolve colormap issues, and create windows for HP workstations. One such utility of interest here is PEXUtSelectVisual. Programmers are encouraged to use the cge_utilities in order to advance portability and interoperability. In the PEXlib Programming Manual, 5.7, "Color Approximation," mention is made of "window memory," or "frame buffer," and its role in rendering and making pixels on the display take on desired colors. In Hewlett-Packard terms, all the rows and columns of the frame buffer array are mapped directly onto the rows and columns of pixels on the display. And as you'd expect, the display refreshes images by scanning through the frame buffer, line by line, to re-display the image. To display color and intensity on the screen, each place in the frame buffer must have more than one bit. This is described in literature from Hewlett-Packard as the depth of the frame buffer. (Also see PEXlib Programming Manual, 5.7.1.1, for its discussion of the number of bits in the pixel segments determining the number of colors displayed.) Frame buffer depth, of course, is determined by the hardware or software with which it can be implemented. Simple monochrome systems only require the frame buffer to record whether or not individual pixels are on or off, so the frame buffer has a depth of one. A simple color system will provide at least four bits to describe each pixel and is termed a 4-plane system. Most graphics systems provide eight-bit pixels, termed 8-plane systems, and so on, up to 12-, 24-, and 48-plane systems. To this system of planes devoted to the color approximation and display of images, Hewlett-Packard adds a capability for planes that "overlay" the image planes. Rendering to the overlay plane visuals generally does not affect the contents of the image plane visuals that appear underneath. This makes it possible to render text or other graphics to the overlay window without re-rendering the image window graphics. This is especially useful for user-interface objects (menus and such) or annotation text that "floats" over image-plane objects. These overlay planes provide lesser functionality than the image planes. The overlay planes' transparency feature enables you to render opaque objects (for example, menus and text) to a transparent overlay plane and at the same time, view rendered objects in the image planes. For example, you may want to show a map of the United States without all of its state boundaries, and then add the state boundaries as you need them. This can be done by creating two X windows: one in the overlay planes and one in the images planes. The United States map would be draw in the image planes window and the state boundaries in a transparent overlay planes window. The overlay and image planes, then, are accessed by using different visuals to create X windows and colormaps. Once you've chosen a visual, it may be necessary to find or create an X colormap for it before any windows can be created in that visual. If the chosen visual is not the default, this is necessary be cause the X server often creates only a colormap for the default visual. Even in the default visual, it can be beneficial for an application to share a colormap rather than create one of its own. This will, for example, reduce color flashing — the distracting effect of displayed objects changing colors as colormaps with different contents are installed. (Colormap installation is typically under control of a window manager, and is often triggered by moving the pointer from one window to another.) If multiple windows can be rendered using the same color map, the chances of this flashing can be reduced. Convenience and efficiency are other reasons to share a colormap. If your application will create four windows and put similar information in all of them, why create and set up four colormaps? This is time-consuming and wastes server resources. On the other hand, your application may actually need different colormaps for the four windows — but be ready for the color flashing. These same principles apply to concurrent PEX clients. In fact, it is likely that all PEX clients coexisting in a particular visual can be satisfied sharing the same colormap (see the next item in this list that discusses the colormap contents). Even if each PEX client has its own colormap resource, it is likely that the colormap contents will be very similar, and the severity of color flashing among them will be much reduced. X standard colormap properties are elements of an established convention that allows description and sharing between X clients of the kind of colormaps that are appropriate for PEX. The book Xlib Programming Manual offers information on this convention. Once a colormap is found or created, it may be necessary to load colors into the cells. Typically, if a colormap is being shared, the contents of most of the cells have already been agreed upon. The convention in sharing is the first client that needs a standard colormap may set it up. By putting the resource ID into the standard colormap property, it makes the colormap available for sharing. Later clients simply use it without changing it. PEX never deals directly with the contents of the colormap, it only generates pixel values as directed by the color approximation table entry that is in effect during rendering. To get a correct image on the screen, the colormap must be set up to match the color approximation table entry. Color approximation is the "translation step" between the RGBs (or other colors) that are the output of the PEX rendering pipeline, and the X colormap attached to the window. Color approximation, and the corresponding setup of the colormap, are the most critical elements in achieving correct appearance of PEX rendering. Most PEX applications will find that color approximation type PEXColorSpace is the most natural method to use. This is because PEXColorSpace attempts to reproduce the RGB values produced by the PEX rendering pipeline as faithfully as it can, given a limited number of color levels for each of red, green, and blue. In other words, the colors that are displayed are as true to the colors of the primitives, lights, etc., as possible. The colors in the X colormap for PEXColorSpace are expected to represent a "sampling" of the color space, also called a color ramp. For a set number of red levels, green levels, and blue levels, all the combinations are expected to be represented in the colormap, either by separate cells (in the case of PseudoColor visuals) or by combinations of red, green, and blue components (in the case of DirectColor and TrueColor visuals). Again, the 〈cge_utils〉 directory[15] provides utilities that aid in setting up a colormap to contain a color sampling. Ideally, every PEX implementation could support any color approximation setup that is "legal." However, this is not likely to be the case and even if it were, rendering performance would be impaired for setups that were unnatural to the device. You should expect that each implementation will only support a small set of possible color approximation entries well — so your application must choose one of those. The HP server implements an escape that can be used to decide whether or not a color approximation entry is supported. This escape is part of a recently established convention for PEX color interoperability. Other PEX servers will also be implementing this escape; it is discussed in more detail later in this chapter “Color Approximation — Utilities And Escapes ”. PEXColorRange is used primarily for applications using the RGB channels in the PEX rendering pipeline to represent data other than color. For example, a finite-element analysis might use the red channel to represent temperature, and the green and blue channels to represent other data. PEXColorRange gives the application a way to apply a simple function to the data (after the pipeline may have interpolated it across surfaces) to convert it to colors that represent the data combinations. There is one other interesting application of PEXColorRange. On a GrayScale or StaticGray visual, many colormap cells can be saved by using PEXColorRange to convert the RGB coming from the rendering pipeline to a gray intensity level before the lookup in the X colormap. One more step may be needed in order to load the colormap correctly for PEX rendering. Some graphics hardware or software may not be able to render to a colormap setup conforming to the PEX color approximation scheme, perhaps because the hardware or driver software was developed before the advent of PEX. Rather than not supporting PEX on such hardware, the vendor may furnish instructions (or a utility routine) to adjust the colormap contents to the behavior of the hard ware rendering. PEX adds no new tasks to this step. Assuming the visual that has been chosen is supported by PEX, and the colormap has been set up to match the color approximation, your application can create the window normally, and should then be able to create Lookup Tables and Renderers using the window as an example drawable, and/or bind a Renderer to the window for drawing or picking. A basic PEXlib programming goal is to enable your application to run, without change, across all the X platforms from one vendor. It may also be a goal that your application port, without significant change, to PEXlib from other vendors, and/or to run via PEX protocol to servers from other vendors. PEX and PEXlib are intended to support these similar and valuable objectives. When writing the part of your application dealing with X and PEX color issues, you are dealing in one area where these device-specific and vendor-specific capabilities and issues are exposed. Therefore, it is important to anticipate the wide range of color capabilities your application may encounter when operating across the network or during a port to another vendor's PEX implementation. For example, not all workstations support all the visual classes. This means that on some servers, there may be several PEX-capable visuals to choose from and you must write your application so that it can find one that exactly meets its color requirements. However, there are often advantages in choosing a visual other than the default, if you can. Advantages include these:
On other servers, there may only be one relatively limited visual. In such a situation, your application has two choices:
Some servers may have several hardware colormaps and color flashing may not be much of a problem when running on those servers. If you have not incorporated any code to attempt to share colormaps with other clients, and then you run the application on a server that has only one hardware colormap resource, the flashing could be severe. (The flashing could be severe anyway; it can only be avoided when all the clients that are running concurrently cooperate in the sharing of limited color resources.) The implementation limitations on color-approximation support mentioned earlier are another example of the kind of configuration dependency that must be dealt with in order to make an application truly interoperable and portable. Programming for this kind of portability and interoperability requires some decided effort. You should note, however, that with X and PEX, the same solutions that give portability across a single vendor's platforms can also contribute to portability and interoperability across vendors and networks — so time spent on design for interoperability is seldom wasted. Although at this time there are no completely-established interoperability conventions specific to PEX color issues, these conventions are being developed through the efforts of software application developers via the PEX Interoperability Consortium. Staying up to date on these conventions, and even participating in their development, is of value to you as a PEXlib programmer. Now, apply these basic strategies (that your application might use for selecting a visual and setting up a compatible color approximation table and colormap contents) to Hewlett-Packard graphics workstations:
HP PEX helps you resolve PEX color issues through the definition of X standard colormap properties, predefined color-approximation LUT entries that are appropriate for the HP graphics devices on which PEX programs run, and a complete set of utilities for selecting visuals, creating and loading colormaps and creating windows in the visuals. These utilities are in one of the utilities directories under the 〈pex〉 directories[16]. Instructions for using the utilities are documented in README files in the same directories. Several of the devices supported by HP PEX have only a single visual; several others have two or more visuals that are PEX-capable. The visuals range from 8-bit PseudoColor all the way up to 24-plane DirectColor. Because interactivity is important to most PEX applications, HP PEX largely supports visuals that are capable of double-buffering (see the appropriate section of this manual for more information on double-buffering). In the table "Visual Types Capable of Multi-Buffering," you see a list of supported visuals on HP PEX graphics devices and whether or not double-buffering is supported. For maximum application portability, it is best to use the PEXMatchRenderingTargets call and the PEXGetEnumTypeInfo call to determine whether or not the visual of interest to your application is supported on HP. Many programs have similar requirements in choosing a visual. The HP PEX server defines a standard X colormap property, PEX_BEST_MAP, that defines what HP considers to be the "best" color approximation on each visual on a particular device for the widest range of applications. The first entry in the property describes the visual that provides the most color capabilities but can still be double-buffered. If these are your criteria for selecting a visual in your application, you can fetch the value of the property using XGetWindowProperty (an Xlib entry point) and use the visual named in the first entry. If you need an overlay colormap that supports transparency, create the color map using the visual that includes transparency in its SERVER_OVERLAY_VISUALS property. If this property exists on the root window of a particular screen, that screen has overlay planes. This property also allows a program be able to determine which visuals are in the overlay planes and which are not, and to access the transparency information to determine if there is a "transparent color" which can be used to "see through" the overlay planes to the image planes. This property is accessed by the visual-selection utility PEXUtSelectVisual in 〈cge_utils〉[17], then the layer criterion (image or overlay) is applied as a selection factor. HP PEX changes nothing in the process of creating a colormap in X — colormaps are created using the XCreateColormap call. XCreateColormap returns a resource ID that can be used for the new colormap. Shareable colormaps can be found using the colormap properties. If the colormap ID in the XStandardColormap structure returned by XGetRGBColormaps or XGetWindowProperty is "None", (a constant defined by Xlib), you'll need to create a colormap with XCreateColormap. This ID can be put into a standard colormap property if you wish to share the resource with other clients. How can your application determine the particular color sampling that HP PEX supports? As discussed in Chapter 25 of the PEXlib Programming Manual, escapes provide for features not defined by the standard PEX specification. In this case, the escape PEXEscapeQueryColorApprox enables applications to inquire whether or not a particular color approximation entry is supported by the PEX server and its (or that of the very similar CGE extension escape PEXExtQueryColorApprox) use is recommended to assure portability. To illustrate a basic color approximation inquiry, see the file pexutcmap.c in the 〈pex-utils〉 directory. A basic color-approximation inquiry is implemented by PEXUtVerifyColorApproximation. The syntax for PEXEscapeWithReply is:
Table 6-9 PEX Escape With Reply Parameters
As with all PEX escapes, the technique which most contributes to interoperability is to inquire whether or not the PEX server supports an escape_id before attempting to use it by calling PEXGetEnumTypeInfo for the PEXETEscape enumeration. The values returned for index and mnemonic fields for this escape are PEXETEscapeQueryColorApproxData and PEXETMEscapeQueryColorApproxData respectively. If you send an escape_id to a server that does not support it, a BadValue error is reported. The input data structure (*escape_data) for PEXEscapeWithReply for this particular opcode is defined as:
Table 6-10 Data Structure Parameters
Notice that the capx field is not a pointer. You must actually copy the information into this embedded structure (by using a C structure copy). The function of the PEXEscapeQueryColorApprox opcode is to allow the server to verify whether or not the supplied color entry can be supported by the PEX server. If the entry is supported, the return data indicates such. If the entry is not supported, the server returns one or more supported entries from which your application may choose. The PEXEscapeQueryColorApproxReplyData is defined as:
Table 6-11 Return Data
The set of alternative color approximation entries can be accessed by computing the appropriate pointer and using array indexing, as in the following example:
This escape can also report a BadDrawable error (if the example drawable ID is not valid) or BadValue (due to an illegal value in one of the color approximation entry fields). Table 6-12 Encoding of HP-Supported Color Escape Extensions
The Hewlett-Packard implementation of PEX does not support arbitrary color samplings. In fact, for any given device and environment, only one color sampling (and therefore, only one particular PEXColorSpace color approximation setup) is supported. You need access to the color sampling information — you must use the escape — at the time that you load the colormap. PEXEscapeWithReply cannot be called before PEXInitialize; therefore, it is convenient to call PEXInitialize before window and colormap creation, not afterwards. The predefined entry support in the HP PEX color approximation table means that if you plan to use PEXColorSpace approximation, you don't even need to call PEXSetTableEntries to set up a table entry, although in general, this is an important practice to assure interoperability. It is very important that you do create a color approximation table, because HP PEX cannot set up the correct predefined entry (which may vary from one device to the next) until you indicate what screen and visual to use, by passing an example drawable to PEXCreateLookupTable. We recommend that you always set the table entry explicitly because other PEX implementations may not have predefined entries. Here is another implication of the single color-sampling support per configuration in HP PEX: If you call PEXSetTableEntries to set a PEXColorSpace color approximation table entry to values that do not match the one supported setting, the server reports an error. Some applications may need to use PEXColorRange color approximation rather than PEXColorSpace. While PEXColorRange is supported on HP devices on PseudoColor and StaticColor visuals, it is not supported on DirectColor or TrueColor visuals. The only restriction on the color approximation entry values, beyond what the PEX standard prescribes, is that the mult1, mult2, and mult3 values in the color approximation entry must be 1.0, 0.0, and 0.0, respectively. In cases where the device depends on colormap interpolation ramps that can be described in an XStandardColormap structure, you can use some of the utilities described in the PEXlib Programming Manual, but in other cases, you will need to use the utility code provided by Hewlett-Packard to set the colormap properly. If your graphics device is a CRX, you will need to use the special utilities for adjusting the colormap for that hardware. Source code for these utilities is provided online and described in the README file in the 〈pex-utils〉 directory[18]. For some applications, it is desirable to disable dithering — such as finite-element analysis or data visualization that benefit from the resulting color banding effects. On most devices, this is accomplished in the color approximation table entry by setting the dither hint to PEXOff. However, dithering cannot be disabled on CRX devices when using PEXColorSpace. Dithering is not performed in 24-bit visuals so the dither hint has no effect for those targets. PEX supports specification of color attributes for primitives and light sources and the renderer's background color via color indices as well as via RGB triples. In fact, the PEX standard specifies that the default value for all colors is index 1 (except for the renderer background color, which defaults to index 0). By default, however, the PEX standard does not specify what color is selected by index 1. HP PEX defines that default color to be white. This means that if you don't create a table of type PEXLUTColor and associate it with the renderer, all primitives will be drawn in white by default. For many applications, it is natural to specify colors in terms of RGB. These applications do not need to create a color lookup table, but do need to set the renderer background color and the primitive colors to RGB values before they cause PEX to use those attributes, otherwise everything will be drawn in white. For applications that need to use indexed colors, it is important to note that the HP PEX color table only has eight entries predefined to a set of simple primary colors. If you use many color indices but don't load the entries in the table, you'll still end up with a lot of things drawn in white. Remember, the color table is at the "front end" of the PEX rendering pipeline. Indexed colors are always converted to RGBs as primitives enter the pipeline (unless using PEXHPColorApproxTypeIndexed). This means that there is no correspondence between colors you load into the PEX color lookup table, and the colors you must put in the X colormap. The rendering pipeline always operates in RGB. For this reason, PEXColorSpace is the most natural color approximation method, even for applications that use indexed colors. Alpha blending is a frame buffer operation that blends a source color with whatever color is already in the frame buffer, for each pixel in an image. Alpha transparency allows per-pixel blending of surface colors with other objects in the scene to produce high-quality transparency effects. The alpha transparency method results in a much smoother transparency than that achieved via the screen-door transparency method that has been available to date. See the example programs in 〈hp-examples〉[19] and the README for instructions. Screen-door transparency (available in previous releases of HP PEX) is computationally very fast. Currently, the only control over screen-door transparency is the "transmission coefficient" in the front- and back-surface reflection attributes. A coefficient of 0.0 indicates a completely opaque surface; a coefficient of 1.0 means the surface is completely transparent and does not contribute to the image. Screen-door transparency is accomplished by mapping the coefficient value into one of a discrete number of levels defined by a "screen door pattern cell". On most HP devices, this is a 4×4 cell, so there are 17 possible levels, from $0\over16$, completely opaque (all pixels in the cell are drawn), to $16\over16$, completely transparent (no pixels are drawn). Screen-door transparency is very fast because it requires no frame buffer reads and can be built into the rasterizers or the frame buffer data path. This allows transparent objects to be animated with little or no performance impact. The fixed-raster nature of the screen-door cell, and the fact that it is typically tiled either in screen coordinates or window coordinates, sometimes creates unpleasant visual artifacts. For example, two equally-transparent surfaces, one in front of the other, result in only the top surface being visible, because the screen-door cells overlay exactly. The image gets no color contribution from the surface that is farther away, and the user cannot see it at all. There also may be interference patterns between the screen-door cell and any dithering pattern that is in use. "Alpha" is an extra channel carried along with colors (or vertex data from which colors can be computed; for example, by lighting equations) that specifies the opacity of the color. Typically, an alpha of 1.0 indicates complete opacity, and 0.0 indicates complete transparency (i.e., the inverse of the transmission coefficient). Alpha transparency blends the color of a transparent surface with the colors of other primitives that are "behind" it for every pixel of the surface. This eliminates the aliasing artifacts due to screen-door cells, but requires that the current color of each pixel be read out of the frame buffer and that a blending algorithm be applied to mix the new surface color with the existing color. The blending functions make use of the alpha channel to do the mixing. These extra operations can have significant performance impacts if not built into the graphics hardware, and have some even when the hardware does offer support. This part of the necessary functionality is called alpha blending, and it has uses in other techniques besides alpha transparency; for example, antialiasing and texture mapping both require some alpha blending. In addition to alpha blending, to render a correct picture, alpha transparency requires two or more passes to render the primitives in the image. The first pass renders the background color and all "opaque" primitives. This creates the "background image" to be used in blending with transparent primitives. Then, the transparent primitives are rendered in one or more passes, blending their colors with the image already rendered. Ideally, the primitives are rendered in sorted order from most-distant in Z to nearest, for each pixel in the image. Compromises for better performance are possible, but introduce various sorts of visual artifacts. HP PEX provides extensions to support simple alpha blending and to use the Z-buffer in a read-only mode — to test the Z-buffer value without changing it. These features can be utilized in an application to implement various alpha transparency effects. Additional work would be required in the application to do view-dependent Z-buffer sorting even at the level of HP PEX primitives. Values are shown here; mnemonic strings have names derived from the value identifiers in the usual fashion. Table 6-13 Encoding of HP-Supported Alpha Transparency Extensions
The transparency_method HP extension Renderer attribute controls the type of transparency algorithm supported by the renderer. Its default is PEXHPTransparencyMethodScreenDoor. See PEXHPChangeRenderer in the on-line documentation for information on how to set this attribute. There is one new Pipeline Context attribute supported for alpha blending. The alpha_blend_function default is PEXHPAlphaBlendFunctionSrcColor. Please see PEXHPChangePipelineContext in the on-line documentation for information on how to change it. An additional color type is defined, which carries alpha as a fourth channel. This color type is currently accepted only by primitives that can include color data per facet or per vertex. Since HP PEX only supports floating-point color values, only one type, PEXHPColorTypeRGB, need be supported (added to the PEXETColorType enumerated type). The encoding for the new color type is straightforward; its size is four words. In order to pass alpha values per-vertex or -facet into the CGE PEX extended with-data primitive entrypoints, additional vertex and facet data types are defined that use the new color types. There was no need to define new bits for the vertex_attributes and facet_attributes masks, because the color_type attribute in the existing parameter lists carries all the information that is necessary. There are three unions that appear in with-data primitive parameter lists that might support RGBA color: PEXFacetData, PEXArrayOfFacetData, and PEXArrayOfVertex. PEXListOfVertex is also indirectly affected since it contains PEXArrayOfVertex as a field. Also affected are the vertex data structures, PEXExtArrayOfVertex and PEXExtListOfVertex. The PEXFacetData union is most affected since its size would be changed, though it is only passed to primitives by reference and in all cases only a single facet's worth of data is passed. However, it is embedded directly inside members of the PEXOCData union, so changing it would create an incompatibility for old programs using the PEXlib OC encoding routines. Therefore, the union has not been changed and typecasting of the pointer is necessary when calling the entry points that use this union. A typical example of the typecasting technique would be:
In a similar vein, no change to union PEX[Ext]ArrayOfFacetData is implemented. Instead, the following technique can be used to pass a pointer to the data.
A technique similar to that shown above for PEXArrayOfFacetData can be used to pass this color data via PEX[Ext]ArrayOfVertexData or, indirectly, PEX[Ext]ListOfVertex. The function PEXHPSetAlphaBlendFunction creates an output primitive attribute that sets the blend functions for alpha blending and alpha transparency. Unsupported values will default to PEXHPAlphaBlendFunctionSrcColor, which results in source color rendering. Also see PEXHPChangeRenderer.
Using this routine, parameters are as follows: Table 6-14 Alpha Blending Reply Parameters
This entrypoint generates an extended OC with an output command number of 0x8700. The encoding for the output command is: Table 6-15 Encoding of HP-Supported Alpha Blending Extension
The default value of all attributes results in alpha transparency being off; screen-door transparency is in effect. Alpha values are not interpolated across primitives when in screen door mode; only the front and back surface transmission coefficients induces screen-door transparency. The transmission coefficient in the surface reflection attributes is directly mapped to an alpha value for surfaces as 1-〈coeff〉. This alpha value is used for surfaces that do not have per-facet or per-vertex alpha data, when alpha transparency is enabled. Texture mapping can produce textures with alpha values. Depending on the compositing rule in use, alpha values from the surface color or alpha-per-vertex may or may not be used. For example, a texture map with alpha values and a "replace" composition rule does not use any color channels (including alpha) from the surface, but the "modulate" rule does. When surface alpha is used, it is applied as part of the surface color, during the first texture mapping compositing operation. For example, an opaque surface may become transparent due to alpha in a texture. Alpha is not applied to vector/edge antialiasing. It is not effective for interior style "hollow". When depth cueing is enabled, it is applied after a source alpha value is derived for the pixel, but it does not modify the alpha channel of the pixel color as it does the red, green, and blue channels — that is, during depth-cue modification of the color, the source alpha value is carried through unchanged. After depth cueing, the alpha value is used to blend with the pre-existing frame buffer contents. On targets that do not support alpha blending (e.g., 8-plane visuals and CRX-24), when the transparency method calls for alpha blending, HP PEX does not do transparency. Specifically, screen-door transparency is not substituted for alpha blending. (In fact, the PEXHPETTransparencyMethod enumerated type does not list any alpha method as a supported value on such platforms, so a BadValue error is reported if an attempt is made to put the renderer in such a mode.) Two sequences to set up alpha blending are illustrated in pseudocode below.
HP supports two methods of anti-aliasing for producing high-quality images, most noticeable as smooth lines and polygon edges. In the first, which was provided with HP PEX 5.1v1, anti-aliasing is provided through a GSE (see “Line Types ”). However, this GSE is not the preferred method and is retained primarily for compatibility reasons. The second and preferred method, added for HP PEX 5.1v2 is an OC routine PEXExtOCSetPrimitiveAA, which selects the primitives that are to be anti-aliased. A blending operation specifies the anti-aliased method to be used. Note that there is no mention of gamma correction made in the PEX 5.2 or CGE PEX 1.0 specifications. Thus, it is not addressed in the specification. However, HP PEX supports the Gamma Correction Escape in order to maintain compatibility with older programs. Other tools for setting up a gamma corrected colormap should be considered by application developers. The PEXExtSetPrimitiveAA entry point controls anti-aliasing. The blend_op parameter indicates the blend operation to be used. For HP PEX, PEXExtPrimAABlendOpImpDep and PEXExtPrimAABlendOpSimpleAlpha have the same result. The calculation for PEXExtPrimAABlendOpSimpleAlpha is α×〈src_color〉 + (1-α)×〈dest_color〉. The HP/CGE PEX 1.0 supported/unsupported anti-aliasing methods are: Table 6-16 Title not available (Anti-aliasing )
Setting the mode to an unsupported index will cause the mode to default to PEXExtPrimAANone. Enumerated type PEXExtETPrimitiveAABlendOp indicates the supported blend operations. PEXExtPrimAABlendOpImpDep and PEXExtPrimAABlendOpSimpleAlpha are both supported on HP. Both methods use the same algorithm on HP. Note that anti-aliasing is not supported on some unaccelerated devices and on all 8-bit visuals. Use PEXGetEnumTypeInfo to determine anti-aliasing capability for a particular drawable. If anti-aliasing is not supported attempts to enable it will be silently ignored. These line types are supported:
Additional information and recommendations about extended line types, the PEXExtETMLineType enumerated type lists, and the use of antialiasing to enhance the appearance of lines and edges are also covered in the Portable Programming with CGE PEX 5.1. HP PEX supports only an edgewidth scale factor of 1.0. Any OC that attempts to set it is silently mapped to 1.0. To improve the quality of images, of lines and polygon edges in particular, antialiasing functionality is available. Antialiased images, however, do not look their best unless gamma correction has been performed on the X colormap contents. Therefore, it is recommended that if you use the HP GSE for anti-aliasing that you also apply gamma correction to your colormap. Utilities in the 〈pex-utils〉 directory[20] include a utility procedure that you can call to create a gamma-corrected colormap. Note that gamma correction may cause some vectors to be drawn without antialiasing to appear dimmed. You should be aware of this effect, although it is unusual for an application to enable and disable antialiasing during traversal. The PEXGSE entrypoint has the following interface:
Table 6-17 PEXGSE Parameters
To use the HP antialias mode GSE, the ID parameter should be set to HP_GSE_SET_ANTIALIAS_MODE. The data structure type name needed for the data parameter is hpGSESetAntialiasMode. The antialias_mode field in this structure can take one of the following values: Table 6-18 Valid antialias_mode Values
Table 6-19 Encoding HP-Supported Antialiasing and Gamma Correction Extensions
Cap and join style support is provided through two CGE extension OCs: PEXExtOCSetLineCapStyle and PEXExtOCSetLineJoinStyle. Defined values (not all necessarily supported by HP PEX) for these additional enumerated types are:
The PEX standard makes interior style PEXInteriorStylePattern optional and HP PEXlib does not support "pattern" interior styles, defaulting to PEXInteriorStyleHollow. Attempts to set an unsupported style results in the default PEXInteriorStyleHollow. Attempts to create a pattern LUT result in a BadPEXLookupTable error. Setting the curve approximation criteria to a particular value for NURBS surface trim curves has no effect in HP PEX. Trimming curves are automatically computed with a resolution compatible with the surface approximation criteria. The parametric surface characteristics attribute can be set to either of two values: PEXNone or PEXPSCImpDep. The setting PEXPSCImpDep is intended to implement a method by which all edges of all fill areas generated by NURBS surface tessellation are made visible. In the HP PEX 5.1 release, the parametric surface characteristics attribute has no effect. The appearance of NURBS surfaces is governed entirely by interior attributes. When fill area edging is enabled, NURBS interior edges are visible. This behavior is avoided by disabling edging around NURBS. Hewlett-Packard recommends that applications set the parameter surface characteristics attribute for portability and because HP PEX behavior may change in future releases. HP PEX supports a Generalized Structure Element (GSE) to enable or disable line- and edge antialiasing. This is not a standard feature (there are no standard GSEs specified by PEX), but may have value for your application. The constants and data structure for the PEXlib interface are defined in the header file PEXHPlib.h. Please see the section “Line Types ” for more information. These two visualization techniques are suited to the modeling of solid objects common to MCAD applications. Capping is an adjunct to model clipping that re-closes a capped volume where it has been clipped. The result appears as though a section has been cut from a solid object. Interference checking can detect interpenetrating solids by highlighting overlapping caps within a clip plane. HP PEX supports the formation and rendering of capping facets to indicate how a volume-enclosing set of surfaces is intersected by a model clipping plane. It also allows capping facets for different enclosed volumes to be collected and their intersection to be rendered, usually using a distinguishing set of attributes. This is called "interference checking," since it can be used to show intersection of two or more volumes (solids) in a model clipping plane. PEX defines model clipping, but does not address capping or interference checking. Responding to customer request, HP developed an interface to provide access to these features through PEXlib. This interface supports the definition of volumes independently of the primitives or structures used to define them. The interface is implemented with the procedure PEXHPSetCappingPlanes (see the reference page in the on-line documentation). This entrypoint is implemented as an Extended Output Command (extended-OC). Another technique useful for modeling of solid objects and MCAD applications is deformation. Deformation modifies geometric coordinates in the "with-data" primitives before modeling transformations are applied. There are four steps required to control deformation:
In the HP PEX 5.1v2 implementation, a new attribute command, PEXHPSetDeformationMode is used to set the deformation mode, and the value of the global complex deformation factor. The initial deformation mode and factors can be set in the pipeline context. The following CGE PEX 1.0 extended area primitives will accept deformation values in the vertex data:
These primitives are defined in the CGE PEX 1.0 specification. Existing 5.1 area primitives (PEXFillAreaSetWithData, PEXTriangleStrip, PEXSetOfFillAreaSets, etc.) are unaffected by the deformation mode. The HP extended primitives PEXHPPolylineSetWithData and PEXHPMarkersWithData will also accept deformation data. Deformation values are stored in a list of floats. There may be one list of floats containing "extra data" like texture mapping data or deformation values per vertex. These values are passed to PEXlib for each vertex, following the vertex normals, colors and edges flags. Extra vertex data, like deformation values and texture mapping coordinates, can appear anywhere in this list of floats. PEXHPSetDeformationValueLocation indicates where in the list of extra data deformation values can be found. The deformation value location is also an attribute whose initial value can be set in the pipeline context, modifiable via PEXHPChangePipelineContext. It is not likely that deformation will be incorporated in a future revision of the PEX standard. There is no (inquirable) enumerated type for the deformation mode since HP is the only vendor that supports deformation. These are the HP extended OCs required to support deformation, inquirable by enumerated type PEXETExtOC.
These values are part of the list returned by an inquiry of enumerated type PEXETExtPC.
Deformation mode may be set in the pipeline context. The default value for deformation mode is PEXHPDeformationOff. PEXHPChangePipelineContext is used to modify the extended pipeline context. See Chapter 6 “Writing HP PEXlib Programs ” for details on changing the HP-only attributes in the pipeline context. Deformation values are stored in a list of floats associated with each vertex in a with-data primitive. The deformation value location is an index into that list of floats. The default value for the deformation value location is index 0. The deformation value location can also be changed using the PEXHPChangePipelineContext routine defined in Chapter 6 “Writing HP PEXlib Programs ”. This value is returned by an inquiry of enumerated type PEXExtETID:
The fonts supported by HP PEXlib are accessed using the X Logical Font Description (XLFD) conventions. PEX stroke fonts can be regarded as infinitely scalable and rotatable, although, unlike scalable bitmap fonts, no process of font generation occurs when a font is opened. The values shown in the following tables are supported for XLFD name fields to access HP fonts that are returned by PEXListFonts and PEXListFontswithInfo and are accepted by PEXLoadFont. Table 6-20 Text and Fonts
These properties are defined for HP PEX fonts: FOUNDRY, FAMILY_NAME, WEIGHT_NAME, ADD_STYLE_NAME, SPACING, CHARSET_REGISTRY, and CHARSET_ENCODING. The default font used by PEX is a monospaced, stroke, hproman8 font (i.e., non-proportional, hproman8 glyph layout, one byte per character). This applies to both DHA applications and to the PEX server. Unlike other PEX fonts that you can inquire for font information, additional font information is not available for the default font. The pattern of the FAMILY_NAME field starting with PEX is an HP convention for stroke fonts, it is not yet an interoperability convention. HP PEX font files, used by both the HP PEX server and DHA PEXlib, are organized in the following directory structure that parallels the X11 font structure. Table 6-21 HP PEX Font File Structure
The fonts are represented in an HP-specific format (the same used by Starbase and HP-PHIGS). All PEX fonts have the file name suffix ".pht" and their file names also indicate the character set and font style. The specific fonts supported by Hewlett-Packard, including both the XLFD and file names, are listed at the end of this section in the three "Fonts" tables. The X server font path is used by the PEX server to gain access to the PEX fonts. At server startup, whenever the font path is changed, and whenever the font directories are explicitly rescanned using xset -fp or xset -rehash, the X server (and font server in X11R6) searches the new directories for fonts.dir files. It will merge new files into a hash table so it can quickly find all fonts without searching each of the directories named in the font path. For PEX font directories there is a corresponding phonts.dir file that is ignored by the X server, but is read by the PEX extension. This keeps the sets of X11 fonts and PEX fonts disjoint so XListFonts never returns PEX fonts and PEXListFonts never return X bitmap fonts. X11R6 supports the X font server. However, the font server supports only X fonts, not PEX fonts. Another file, 〈extensions〉[21]/fp.PEX, contains a list of directories to be added to the X font path during server initialization; it should always contain at least one of those directories. Since HP CDE saves and restores the X font path across multiple sessions, HP CDE users will need to explicitly modify the X font path to access fonts other than the default. This can often be done by resetting the font path to the default, including the directories in 〈extensions〉/fp.PEX. To reset the font path, type:
This is not an appropriate solution for users who have customized their font paths. The specific fonts supported by Hewlett-Packard, including both the XLFD and file names are: Table 6-22 〈fonts〉/usascii/stroke fonts
Table 6-23 〈fonts〉/usascii/stroke fonts
Table 6-24 〈fonts〉/hp_japanese/stroke fonts
With the HP PEX 5.1v2 release and later, HP supports both annotation text styles PEXATextNotConnected (default) and PEXATextConnected. The kanjeuc* fonts are two-byte fonts which support two-byte-encoded text strings. HP PEX supports rendering two-byte PEX-encoded text and two-byte PEX-encoded annotation strings and two-byte encoded fonts. PEXCSByte, PEXCSShort and PEXCSLong are supported lengths for PEX-encoded text strings. Since HP PEX does not support three-byte fonts, using PEXCSLong-encoded text is not recommended at this time. Hewlett-Packard adds the following extension marker types: Table 6-25 Marker Type Additions
The HP PEXlib implementation meets the PEX "cell array" requirements by simulating the cell array: drawing its outline with polylines. Animation, or imparting the appearance of motion to objects, is accomplished with any of several methods. Each method offers specific advantages that you'll need to consider when selecting the most appropriate method for the circumstances. HP PEXlib supports rendering to X multi-buffer (MBX) as an efficient and portable method for creating animated images. However, the option to resort to double-buffering with a pixmap, when MBX and E&S escapes are not available, is not supported. HP PEXlib 5.1v3 and later releases support the use of the Double-Buffering Extension (DBE) version 1.0, as a means for double-buffering PEX (and X) graphics. DBE is a newer, simpler standard than MBX, which was supported in HP PEXlib 5.1v2 and which is still recommended for applications that wish to be CGE PEX 1.0 compliant. In the 5.1v2 release, HP PEXlib supported the Multi-buffering Extension (MBX) to accomplish double-buffering. In other words, MBX buffers were accepted as valid targets for the Renderer, and could be used in any inquiry or procedure call that required an example drawable. The application program would need to make MBX calls directly (Xmbuf(...)) to create and swap buffers, but could pass the ID of an MBX buffer to the Renderer to cause drawing to that buffer. This allowed mixed X and PEX rendering in the back buffer, something that the earlier Evans &Sutherland escapes did not allow. Since that release, a simpler double-buffering extension (DBE) has been brought through a rapid review process to become a new standard. DBE is very similar to MBX in many respects, but is simpler in that it only supports basic double-buffering (MBX supports creation of more than two buffers for a window) and allows for API-dependent interaction during clearing and swapping. Again, the application must directly make DBE calls (Xdbe...()) in order to create and swap buffers. HP PEXlib 5.1v3 and later releases support the use of a DBE back buffer name in a manner very similar to the MBX support. Here is a brief summary of the DBE client side entrypoints. To use these, the application program must include header file X11/extensions/Xdbe.h. For more detail, please see the reference pages in the appropriate X library manuals. Table 6-26 DBE Entry Points
PEXMatchRenderingTargets Visuals that support creation of a DBE back buffer name match the PEXBufferDrawable target type. For practical purposes, the set of visuals on each device that support DBE is the same set that supports at least two MBX buffers. An application can directly inquire what Visuals support DBE via the XdbeGetVisualInfo entrypoint. It is important to note that in HP's implementation, some visuals that cannot support double-buffering will be listed as supporting creation of one MBX buffer (see XmbufGetScreenInfo), in accordance with CGE PEX 1.0 requirements. However, these visuals will not be listed as supporting DBE (via the function XdbeGetVisualInfo) because no back buffer can be created for them. The following procedures that have an "example Drawable" entrypoint will all accept a DBE back buffer name as a valid example drawable:
In this release, no changes have been made to either the HP-originated utilities (in /usr/lib/PEX5/utilities) or to the CGE utilities (in .../cge_utilities) to make use of DBE. Applications that wish to use DBE can select a visual that can double-buffer using the utilities as provided, and then use XdbeGetVisualInfo to verify that DBE is supported on the visual. This is not different in nature from the current usage, where a visual can be selected using a double-buffering criterion, but the application must determine whether MBX is supported. The HP PEX library (libPEX5.sl) generates references to some DBE client library entrypoints. The library that implements these is libXext.sl. It is absolutely necessary that the version of libXext.sl on a client system be new enough to implement these entrypoints, otherwise a runtime error (unsatisfied reference) will occur when PEXlib attempts to validate a Drawable ID passed into any procedure. The system release that includes HP PEXlib 5.1v3 and later releases also include an appropriate version of libXext.sl. Whether or not the X server actually supports DBE is another matter. PEXlib will operate correctly whether or not the X server supports DBE. It is recommended that the application use XdbeQueryExtension or a more general Xlib extension query to verify that DBE is actually supported before attempting to create a back buffer name. No special compatibility issues are created by adding the support. However, if an application is modified to use DBE, then it will only compile and link successfully on systems that have the header files and the client library entrypoints. This is a portability consideration for application writers. MBX works as described in PEXlib Programming Manual (section 14.2), rendering to specific and separate image buffers. Buffer IDs can be used in any PEXlib call that requires a drawable ID. It is recommended that you use the function XmbufQueryExtension first, in order to determine whether the MBX extension is supported. Additionally, PEXMatchRenderingTargets reports PEXBufferDrawable targets on visuals that support multi-buffering. The visuals reported to be multi-buffer-capable are listed in the table below. You should be aware of other characteristics of MBX that affect your programs. On systems with hardware double-buffering, setting up two buffers will provide hardware double-buffering sup port. However, on low-end systems or visual types without hardware double-buffering, operation is software-buffered. See the Graphics Administration Guide for information about supported visuals on particular devices. If MBX is not available on your device, then you can use the Evans & Sutherland double-buffering escapes on the same visuals to achieve motion. The escapes PEXEscape and PEXEscapeWithReply allow for access to the Evans & Sutherland method of double-buffering, an HP implementation-dependent functionality, that is described here. The structures for these functions are defined in the file PEXHPlib.h which also includes both the Evans & Sutherland escape requests and the HP companion escape request, HPESCAPE_DFRONT.
Using either escape, data parameters are as shown in the table below: Table 6-27 Double-Buffering Escape and -Escape With Reply Parameters
Table 6-28 Encoding HP Supported Double-Buffering Extensions
By specifying the Evans & Sutherland escape requests the following defined functionality is accessed.
If the specified escape identifier is not supported, a value error is generated. The HP escape, HP_ESCAPE_DFRONT, is a companion escape to the Evans & Sutherland double-buffering escapes described above. It allows you to set the Renderer drawing destination to either the front (visible) buffer or the back (hidden) buffer. This feature is useful for supporting interactive echoes over a visible rendered image and it allows buffer swapping to be reserved for actual image regeneration alone, rather than requiring both echoes and image regeneration to jointly control buffer swapping. By specifying the HP companion escape request, the following defined functionality is accessed:
You can use the enumerated type descriptors to inquire which double-buffering escapes are supported. These are also defined in the implementation-dependent header file, PEXHPlib.h. The enumerated-type mnemonic strings and values returned from PEXGetEnumTypeInfo when inquiring with PEXEscape are: Table 6-29 Inquiring Supported Escapes
Search context resources are not supported with HP PEX 5.1v3 and later releases; however, protocol requests can be issued to PEX servers that do support search contexts. The O'Reilly PEXlib Programming Manual, Section 15.6.4, "Copying Output Commands Between Servers," describes the transmission of data and the need for conversion of floating-point formats between servers. At this release of HP PEXlib, floating-point conversion support is not implemented. This means that an application using HP PEXlib to generate PEX protocol to a non-HP server that does not support PEXIEEE_754_32 floating-point format will fail when PEXInitialize is called. Any attempt to use other floating-point formats will silently fail when using the PEX Protocol Method. Texture mapping simulates a wide variety of surface material properties and detail for relatively modest costs in computation. Specific control of interior colors and transparency of an area primitive results from a special "mapped" correspondence between a texture image and 3D surface during rendering. PEX support for texture mapping is currently under development by the PEX consortium, as noted in the PEXlib Programming Manual (16.1.9). However, HP is supporting CGE-extension texture mapping in the HP PEX 5.1v3 and 5.1v4 product releases. As such, a tutorial for texture mapping and the HP implementation details of the extension are covered in the later chapters of this book with the other advanced features (see Chapter 10 “Texture Mapping Tutorial ”). If PowerShade is not installed, certain lighting and shading functions are disabled, leaving 3D wireframe functionality still available. Specific lighting and shading functions that are disabled in the wireframe configuration are:
In order for code to run unmodified on workstations regardless of PowerShade, errors as a result of calls to these non-supported functions are not reported. Also, the following attributes retain their default values despite attempts to change them:
The following table illustrates the enumerated types and implementation-dependent constants that are different in the 3D wireframe configuration than when PowerShade is present. Table 6-30 Enumerated Types and Implementation-Dependent Constants
Hewlett-Packard makes no implementation-dependent additions to these functions of PEXlib. See “Renderers ”, next. HP PEXlib offers immediate dynamics for all attributes, including Lookup Tables and Nameset contents. This list describes the specifics of immediate dynamics for hlhsr_mode, if changed while the renderer is active: Table 6-31 HLHSR Mode Transition Behaviors
The color approximation lookup table (LUT) does not support arbitrary definitions of type PEXColorSpace. The default entry for the LUT may not represent the supported definition of that type for drawables of a particular depth and visual class. However, the predefined entry in a LUT that has been created for that visual and class does represent the supported definition. Servers from other vendors may support arbitrary values. It is the application's responsibility to use the LUT appropriately. The color approximation LUT on most devices respects the dither flag. The implementation-dependent constant DitheringSupported is false on devices that never dither. It is True on devices where dithering is possible and on those devices the dither hint in the color approximation LUT entry may or may not have an effect, depending on the device. If it has no effect, then dithering is always used. When realized values are inquired from the color LUT, the values will be in the same color type used when the entry was specified. Visible LUT behavior is specified in the table "LUT Default Entries" below. These are the values that are used when there isn't a current LUT of the specified type bound to a renderer, or if the entry being indexed does not exist and there is not any entry at the default index of the LUT. The values shown in the table are also the values of the predefined entries for the LUTs in all cases except Color and ColorApprox LUTS. In the case of a Color LUT, entries 07 are defined as: Table 6-32 Visible LUT Behavior
In the case of ColorApprox LUTs, the predefined entries depend on the drawable (visual) characteristics associated with the LUT. Table 6-33 LUT Default Entries
HP PEX supports the PEXPickLast method for PickOne traversals and the PEXPickAllAll method for PEXPickAll traversals. Neither of these methods uses the current setting of HLHSR. The actual visual appearance of echo and highlight modes is an implementation-dependent choice that is not prescribed by the PEX and PEXlib specifications. The following are the echo and highlight attributes for HP PEXlib:
HP PEXlib implements echo mode using "exclusive or" drawing mode for rapid display and erasure of echo images. This implementation causes the following behaviors:
[13] The actual pathname of this directory depends on the file system structure. See the Graphics Administration Guide for details. [14] The actual pathname of this directory depends on the file system structure. See the Graphics Administration Guide for details. [15] The actual pathname of this directory depends on the file system structure. See the Graphics Administration Guide for details. [16] The actual pathname of this directory depends on the file system structure. See the Graphics Administration Guide for details. [17] The actual pathname of this directory depends on the file system structure. See the Graphics Administration Guide for details. [18] The actual pathname of this directory depends on the file system structure. See the Graphics Administration Guide for details. [19] The actual pathname of this directory depends on the file system structure. See the Graphics Administration Guide for details. [20] The actual pathname of this directory depends on the file system structure. See the Graphics Administration Guide for details. [21] The actual pathname of this directory depends on the file system structure. See the Graphics Administration Guide for details. |
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|||||||||||||||