The S3 presentation driver supports two different types of character output. One type is GRECharStringPos, which is implemented in the S3 driver by eddt_CharStringPos, in the EDDNGCHS.C file. The other type supports AVIO (Advanced Video Input/Output) text, which is used in OS/2 and DOS window sessions.
The eddt_CharStringPos function uses two strategies for displaying text to the screen. For most strings, it will cache glyphs from the font. While cached, it will draw text by expanding the monochrome bit maps in the font cache to the display. There are, however, some cases where it cannot do this. One case is when the character to be cached is higher than the height of the font cache. Very large fonts will overflow the font cache, as the font cache is typically 127 scan lines tall in the S3 driver. Another reason it may be impossible to cache the glyphs is that the driver may be in 24-bit-per-pel mode, and the requested text is not some shade of gray. A third possibility is that the requested raster operation may be one that has problems on certain S3 chips. A fourth possibility is that only a single character in a font appears, making it undesirable to put it in the font cache. (Doing so might evict a heavily used font so that a single character may be cached.) In any of these cases, eddt_CharStringPos draws characters using BitBlt.
The following is an example of pseudocode for eddt_CharStringPos:
eddt_CharStringPos: pFocaFont = Current Font Check that request is valid if simulation is required call back to engine to perform simulation if display is disabled remove COM_DRAW bit from command flags if correlation required get correlation rectangles if opaque rectangle is present if coordinates must be transformed set up opaque rect coordinates for transformation else get opaque rectangle coordinates Get starting coordinates for the string Transform any coordinates that need to be transformed to device space if increment vector is present convert increment vectors to device space if current font has only a single character BltOneChar = TRUE Set up character spacing set PerCharDefs to a pointer to the character get character width and height get character A, B, C space if increment vector is present add in increment vector else add in character width else BltOneChar = FALSE if character is too tall to fit in the cache CharTooBig = TRUE if font cache is disabled CharTooBig = TRUE if requested raster operation is defective on the S3 chip CharTooBig = TRUE if 24 bits per pixel get foreground and background colors if NOTGREY(foreground) and NOTGREY(background) CharTooBig = TRUE Compute starting position for the string if cursor is software Disable cursor if CharTooBig == FALSE if font is not in the font cache eddt_LocateCachedFont() //Get a font cache entry if eddh_update_cache() == FALSE //unable to fit font in cache eddt_LocateCachedFont() //Get a font cache entry if eddh_update_cache() == FALSE bail out of string operation, the font is too big reenable cursor do one last bit of boundary setup (eddt_GetTextBox) if there is an increment vector add in increment to x position if BltOneChar == TRUE adjust starting position to be compatible with BitBlt else adjust starting position to be compatible with string blt if opaqueing rectangle required build opaque rectangle if clipping rectangle clip bounding rectangle against clip rectangle if CharTooBig == FALSE and string completely clipped goto UPDATE_POS clip opaque rect against clipping rectangle if opaque rect entirely clipped disable COM_DRAW bit in command flags else handle multiple clip rects if necessary if we need to accumulate bounds accumulate bounds if we need to perform correlation perform correlation if COM_DRAW is not set in command flags goto CHARSTRPOS_OK_EXIT if destination is the display SetDrawModeHard else SetDrawModeSoft if software cursor exclude cursor setup foreground and background colors if opaque rectangle must be drawn set pixelop set mix, blt source, no color compare TransferShadowRegisters() //draw the opaque rect via pattern blt eddb_DrawThroughClips(index_PatDestBlt) if number of characters to draw is 0 goto CHARSTRPOS_OK_EXIT //special case #1 -- we have a font with a single character if BltOneChar == TRUE calculate size of character in bytes copy character into the Phunk, putting it in row major order Create a bit map header for the character set up pixelop, mix, source, colors etc. TransferShadowRegisters() Setup AIxfer for a BitBlt while count of characters > 0 fix up the character for BitBlt eddb_DrawThroughClips(index_SrcDestBlt) update position of next character decrement count of characters goto UPDATE_POS //special case #2 -- uncacheable font if CharTooBig == TRUE set up colors, mixes, source, etc. TransferShadowRegisters() while count of characters > 0 get character width and height set pCharDefn to point to the character bit map get A, B, and C space copy the character into the Phunk, putting it in row major order setup a bit map header for the character bit map setup AIxfer for a BitBlt fixup source and destination values so they are non-negative eddb_DrawThroughClips(index_SrcDestBlt) advance to next character position decrement count of characters goto UPDATE_POS //finally we get to draw text through the code in eddhgchs.asm set up pointer to the font in AIxfer store a pointer to the code points and position of first char in AIxfer set up mixes, source, colors TransferShadowRegisters() if position vector present //draw them one at a time -- we have a position vector set number of characters in AIxfer to 1 while count of characters > 0 store increment from vector in AIxfer.bCharWidth eddb_DrawThroughClips(index_DrawText) update position of next character from position vector point to next character decrement count of characters else Set count of character in AIxfer to number of characters in string eddb_DrawThroughClips(index_DrawText) UPDATE_POS: update position if required if destination cached evict cached bit map CHARSTRPOS_OK_EXIT: reenable cursor
In eddt_CharStringPos and in the character-caching code, notice the following loop:
for (i = 0; i < CharHeight; i++) { source_index = i; for (j = CharBytesPerRow; j--; ) { *pCharBuffer++ = pCharDefn[source_index]; source_index += CharHeight; } }
This loop is a difficult copy operation because presentation stores the bit maps for glyphs in column major order, rather than in row-major order. That is, all of the bytes that make up the first column of a character are stored one after another, followed by all of the bytes of the second column, and so forth. The bits in each byte of monochrome data are in Motorola** order; that is, bit 7 is the left-most bit, and bit 0 is the right-most bit. Also, after the inner loop rearranges the glyph, the byte ordering is in Motorola order. For other devices, it is possible that either or both the bit and byte ordering may have to be altered.
The eddt_CharStringPos function caches characters in off-screen VRAM. The first portion of this involves determining if the font has already been cached. The eddt_LocateCachedFont() data field, in EDDNCACH.C, searches the array of FontCacheInfo structures. If it finds a matching font, it returns. If not, it evicts a font from the cache, and sets the usCachedFontIndex field in the passed-in parameter in the FONTDETAILS structure. The FONTDETAILS structure is defined in the EDDTYPET.H file, and it stores a pointer to the font and a cache slot, among other things. The S3 driver supports the caching of up to 8 fonts; therefore, the array of pointers to FontCacheInfo structures (pFontCacheInfo) consists of 8 entries.
When an entry has been found for the font, it is necessary to actually cache the characters in the string. This caching is handled by eddh_update_cache, which is in the EDDHGCHS.ASM file. The eddh_update_cache loops through the string, and for each character that is not already cached, it calls eddt_CacheCharacter (in EDDNCACH.C). The code in eddt_CacheCharacter is similar to the code in eddt_CharStringPos that uses BitBlt to display a single character. First, it attempts to find a position in the cache for the character. The 8514/A and the S3 driver stores a single font in a single plane of VRAM. In 16-bit-per-pel modes, the S3 driver allows a font to wrap to another plane. Because the 8514/A interacts with bit maps as rectangles, eddt_CacheCharacter calculates an X-Y coordinate for the character in the font cache, and calls Cache8514Char (in EDDHGCHS.ASM) to copy the glyph into off-screen memory.
In the cases where it is not using BitBlt, eddt_CharStringPos uses either eddh_DrawText (if the destination is the display), or eddf_DrawText (if the destination is not the display). The eddh_DrawText function loops through an array of clipping rectangles, drawing the string (or portion thereof) into each clipping rectangle. The complexity of eddh_DrawText results from the fact that it does not use the S3 chip hardware-scissoring capabilities to clip the text. Instead, if part of a character is clipped, it calculates offsets into the character, and into the destination so that only the portions of the character that are inside the clipping rectangle are actually drawn. When all of that has been set up, the character is BitBlted by way of a hardware monochrome expansion blt from the character cache to the display.