/*DDK*************************************************************************/
/*                                                                           */
/* COPYRIGHT (C) Lexmark Corporation, 1989                                   */
/* COPYRIGHT    Copyright (C) 1995 IBM Corporation                           */
/*                                                                           */
/*    The following IBM OS/2 WARP source code is provided to you solely for  */
/*    the purpose of assisting you in your development of OS/2 WARP device   */
/*    drivers. You may use this code in accordance with the IBM License      */
/*    Agreement provided in the IBM Device Driver Source Kit for OS/2. This  */
/*    Copyright statement may not be removed.                                */
/*                                                                           */
/*****************************************************************************/
/**************************************************************************
 *
 * SOURCE FILE NAME = PRDTEFNT
 *
 * DESCRIPTIVE NAME =
 *
 *
 * VERSION
 *
 * DATE
 *
 * DESCRIPTION
 *
 * FUNCTIONS   prdt_ImageChar
 *             prdt_TextOutEngFont
 *
 * ENTRY POINTS:
 *
 * DEPENDENCIES:
 *
 * NOTES
 *
 *
 * STRUCTURES
 *
 * EXTERNAL REFERENCES
 *
 * EXTERNAL FUNCTIONS
 *
*/

#define INCL_32                     /* CON3201 */
#define INCL_DOSPROCESS             /* CON3201 */
#define INCL_DOSSEMAPHORES
#define INCL_GPIPRIMITIVES
#define INCL_WINHEAP
#define INCL_GPIBITMAPS
#include <os2.h>
#undef INCL_DOSPROCESS              /* CON3201 */
#undef INCL_DOSSEMAPHORES
#undef INCL_GPIPRIMITIVES
#undef INCL_WINHEAP
#undef INCL_GPIBITMAPS

#define INCL_DDICOMFLAGS
#define INCL_DDIBUNDLES
#define INCL_DDIFONTSTRUCS
#define INCL_DDIDEFS
#define INCL_DDIMISC
#define INCL_GRE_LINES
#include <pmddi.h>
#undef INCL_DDICOMFLAGS
#undef INCL_DDIBUNDLES
#undef INCL_DDIFONTSTRUCS
#undef INCL_DDIDEFS
#undef INCL_DDIMISC
#undef INCL_GRE_LINES

#define INCL_WINP_SELECTIVE
#define INCL_WINP_SEI
#include <pmwinx.h>
#undef INCL_WINP_SELECTIVE
#undef INCL_WINP_SEI
#undef INCL_32                      /* CON3201 */

#include <prdconse.h>
#include <prdtcone.h>
#include <prdbcone.h>
#include <prddcone.h>

#define PRDLTYPE_INCL
#define NO_CONSTANT_INCL
#include <prdinclt.h>
#undef NO_CONSTANT_INCL
#undef PRDLTYPE_INCL

#include <prdbtyp1.h>
#include <prdbextf.h>
#include <prdbext1.h>
#include <prdcextf.h>
#include <prdgextf.h>
#include <prdiextf.h>
#include <prdlextf.h>
#include <prdtextf.h>


/******************************************************************************/
/*  FUNCTION: prdt_ImageChar                                                  */
/*                                                                            */
/*  PARAMETERS:                                                               */
/*                                                                            */
/*  PBYTE            lpCharDef;   Pointer to the character definition         */
/*  DevRect far *    SourceRect;  Rectangle of area of character to output -  */
/*                                this rectangle is EXCLUSIVE                 */
/*  POINTS           CurrPos;     Start position in selected bitmap to        */
/*                                transfer character                          */
/*  USHORT           Width;       The width and height of the...              */
/*  USHORT           Height;      character cell                              */
/*  pBMListEntry     ListEntry;   Pointer to currently selected bitmap        */
/*  lpTextAttrsType  pTextAttrs;  The colour and mix attrs                    */
/*                                                                            */
/*  DESCRIPTION:                                                              */
/*                                                                            */
/*  This function transfers a character from the engine font to the required  */
/*  position in the currently selected bit map by scanning the bit image of   */
/*  the character stored in the font definition and using MixPel to set the   */
/*  appropriate pels in the bit map.                                          */
/******************************************************************************/
/* CON3201
VOID prdt_ImageChar(lpCharDef, SourceRect, CurrPos, Width, Height,
                           ListEntry, pTextAttrs)

PBYTE               lpCharDef;
DevRect           * SourceRect;
POINTS              CurrPos;
USHORT              Width;
USHORT              Height;
pBMListEntry        ListEntry;
lpTextAttrsType     pTextAttrs;
                                 */

VOID prdt_ImageChar( PBYTE               lpCharDef,
                     DevRect           * SourceRect,
                     POINTS              CurrPos,
                     USHORT              Width,
                     USHORT              Height,
                     pBMListEntry        ListEntry,
                     lpTextAttrsType     pTextAttrs)

{
#define TFUNC "prdt_ImageChar"

    /**************************************************************************/
    /*  Local Variables                                                       */
    /**************************************************************************/
    USHORT  x, y;                      /* Loop control variables for moving   */
                                       /* through the character image         */
    USHORT  Mask;                      /* Mask for extracting one pel at a    */
                                       /* time from the engine character image*/
    USHORT  RowBytes;                  /* Index into current byte of the      */
                                       /* character definition                */
    USHORT  StartMask;                 /* The starting value for the mask for */
                                       /* each row                            */

    /**************************************************************************/
    /*      ______________________________                                    */
    /*      |            ++++            |    + Set bits                      */
    /*      |           ++++++           |    X Set bits in clip              */
    /*      |      ....XXX..XXX..........|        rectangle                   */
    /*      |      ...XXX....XXX.........|    . Reset bits in clip            */
    /*      |      ..XXX......XXX........|        rectangle                   */
    /*      |      .XXX........XXX.......|                                    */
    /*      |      XXXXXXXXXXXXXXXX......|                                    */
    /*      |     +XXXXXXXXXXXXXXXXX.....|                                    */
    /*      |    ++X..............XXX....|                                    */
    /*      |   +++                +++   |                                    */
    /*      |  +++                  +++  |                                    */
    /*      ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~                                    */
    /*                                                                        */
    /*  A character in the engine image font will be defined as a pattern of  */
    /*  bits.  We may only want a portion of the character (due to clipping)  */
    /*  so SourceRect defines a rectangle which is relative to the bottom left*/
    /*  of the character definition and we only transfer this portion of the  */
    /*  character image.                                                      */
    /*                                                                        */
    /*  The order of storage of the bytes in a character image in the engine  */
    /*  fonts is down the Y axis and along the X axis ie:                     */
    /*     __________________                                                 */
    /*     |:--00--::--09--:|      The height and width of the character cell */
    /*     |:--01--::--10--:|      for the current character set is passed as */
    /*     |:--02--:        |      a parameter to the function.               */
    /*     |                |                                                 */
    /*     |:--04--:        |                                                 */
    /*     |                |                                                 */
    /*     |                |                                                 */
    /*     |                |                                                 */
    /*     |:--08--::--17--:|                                                 */
    /*     ~~~~~~~~~~~~~~~~~~                                                 */
    /**************************************************************************/

    /**************************************************************************/
    /*  Consider each row in turn so that the character map is "RIGHTUP".  Set*/
    /*  the StartMask to mask the leftmost bit which is to be copied.         */
    /**************************************************************************/
    StartMask = 0x80 >> (*SourceRect)[0].X % 8;

    /**************************************************************************/
    /*  For every line in the engine character image that is in SourceRect    */
    /*  transfer the required part of it.                                     */
    /**************************************************************************/
    for (y = (*SourceRect)[0].Y; y < (*SourceRect)[1].Y; y++)
    {
        Mask = StartMask;

        /**********************************************************************/
        /*  For every bit in the current line in the engine character image   */
        /*  that is in SourceRect transfer it to the bitmap.                  */
        /**********************************************************************/
        for (x = (*SourceRect)[0].X; x < (*SourceRect)[1].X; x++)
        {

            /******************************************************************/
            /*  RowBytes is the index into the engine character image of the  */
            /*  byte which contains the bit corresponding to the position we  */
            /*  are interested in.  The +Height-y part allows for the fact    */
            /*  that the bytes in the columns of font definitions are ordered */
            /*  from top to bottom and the -1 allows for the y position       */
            /*  starting at 0.                                                */
            /******************************************************************/
            RowBytes = Height * ( x / 8 ) + Height - y - 1;
            if (lpCharDef[RowBytes] & Mask)
            {

                /**************************************************************/
                /*  If the bit in the engine character image is set the       */
                /*  correpsonding pel using mixpel.                           */
                /**************************************************************/
                prdb_MixPel(ListEntry, CurrPos.x + x, CurrPos.y + y,
                            (BYTE)pTextAttrs->ForeColor, pTextAttrs->ForeMix);
            }
            else
            {
                if (pTextAttrs->BackMix != FM_LEAVEALONE)
                    prdb_MixPel(ListEntry, CurrPos.x + x, CurrPos.y + y,
                                (BYTE)pTextAttrs->BackColor,
                                pTextAttrs->BackMix);
            }

            /******************************************************************/
            /*  Advance the mask to the next position,                        */
            /******************************************************************/
            Mask >>= 1;
            if (Mask == 0)
                Mask = 0x80;
        }
    }
    return;
}
#undef TFUNC



/******************************************************************************/
/*  FUNCTION: prdt_ImageCharGrey                           PD00462            */
/*                                                                            */
/*  PARAMETERS:                                                               */
/*                                                                            */
/*  PBYTE            lpCharDef;   Pointer to the character definition         */
/*  DevRect        * SourceRect;  Rectangle of area of character to output -  */
/*                                this rectangle is EXCLUSIVE                 */
/*  POINTS           CurrPos;     Start position in selected bitmap to        */
/*                                transfer character                          */
/*  USHORT           Width;       The width and height of the...              */
/*  USHORT           Height;      character cell                              */
/*  pBMListEntry     ListEntry;   Pointer to currently selected bitmap        */
/*  lpTextAttrsType  pTextAttrs;  The colour and mix attrs                    */
/*  PBYTE            pPattern;    The pointer to Byte x 8 Bytes greyscale ptrn*/
/*                                                                            */
/*  DESCRIPTION:                                                              */
/*                                                                            */
/*  This function is used when the engine text foreground color is not BLACK. */
/*  This function transfers a character from the engine font to the required  */
/*  position in the currently selected bit map by scanning the bit image of   */
/*  the character stored in the font definition and using MixPel to set the   */
/*  appropriate pels in the bit map corresponding to the greyscale pattern.   */
/******************************************************************************/
/*CON3201
VOID  prdt_ImageCharGrey(lpCharDef, SourceRect, CurrPos, Width, Height,
                           ListEntry, pTextAttrs, pPattern)

PBYTE               lpCharDef;
DevRect          *  SourceRect;
POINTS              CurrPos;
USHORT              Width;
USHORT              Height;
pBMListEntry        ListEntry;
lpTextAttrsType     pTextAttrs;
PBYTE               pPattern;
                              */

VOID  prdt_ImageCharGrey(PBYTE               lpCharDef,
                         DevRect          *  SourceRect,
                         POINTS              CurrPos,
                         USHORT              Width,
                         USHORT              Height,
                         pBMListEntry        ListEntry,
                         lpTextAttrsType     pTextAttrs,
                         PBYTE               pPattern)

{
#define TFUNC "prdt_ImageCharGrey"

    /**************************************************************************/
    /*  Local Variables                                                       */
    /**************************************************************************/
    USHORT  x, y;                      /* Loop control variables for moving   */
                                       /* through the character image         */
    USHORT  Mask;                      /* Mask for extracting one pel at a    */
                                       /* time from the engine character image*/
    USHORT  RowBytes;                  /* Index into current byte of the      */
                                       /* character definition                */
    USHORT  StartMask;                 /* The starting value for the mask for */
                                       /* each row                            */
    USHORT  RowCount;
    PBYTE   pPatternRow;

    /**************************************************************************/
    /*      ______________________________                                    */
    /*      |            ++++            |    + Set bits                      */
    /*      |           ++++++           |    X Set bits in clip              */
    /*      |      ....XXX..XXX..........|        rectangle                   */
    /*      |      ...XXX....XXX.........|    . Reset bits in clip            */
    /*      |      ..XXX......XXX........|        rectangle                   */
    /*      |      .XXX........XXX.......|                                    */
    /*      |      XXXXXXXXXXXXXXXX......|                                    */
    /*      |     +XXXXXXXXXXXXXXXXX.....|                                    */
    /*      |    ++X..............XXX....|                                    */
    /*      |   +++                +++   |                                    */
    /*      |  +++                  +++  |                                    */
    /*      ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~                                    */
    /*                                                                        */
    /*  A character in the engine image font will be defined as a pattern of  */
    /*  bits.  We may only want a portion of the character (due to clipping)  */
    /*  so SourceRect defines a rectangle which is relative to the bottom left*/
    /*  of the character definition and we only transfer this portion of the  */
    /*  character image.                                                      */
    /*                                                                        */
    /*  The order of storage of the bytes in a character image in the engine  */
    /*  fonts is down the Y axis and along the X axis ie:                     */
    /*     __________________                                                 */
    /*     |:--00--::--09--:|      The height and width of the character cell */
    /*     |:--01--::--10--:|      for the current character set is passed as */
    /*     |:--02--:        |      a parameter to the function.               */
    /*     |                |                                                 */
    /*     |:--04--:        |                                                 */
    /*     |                |                                                 */
    /*     |                |                                                 */
    /*     |                |                                                 */
    /*     |:--08--::--17--:|                                                 */
    /*     ~~~~~~~~~~~~~~~~~~                                                 */
    /**************************************************************************/

    /**************************************************************************/
    /*  Consider each row in turn so that the character map is "RIGHTUP".  Set*/
    /*  the StartMask to mask the leftmost bit which is to be copied.         */
    /**************************************************************************/
    StartMask = 0x80 >> (*SourceRect)[0].X % 8;

    pPatternRow = pPattern;
    RowCount = GS_PATTERN_HEIGHT;
    /**************************************************************************/
    /*  For every line in the engine character image that is in SourceRect    */
    /*  transfer the required part of it.                                     */
    /**************************************************************************/
    for (y = (*SourceRect)[0].Y; y < (*SourceRect)[1].Y; y++)
    {
        Mask = StartMask;

        if ( ++RowCount < GS_PATTERN_HEIGHT )
        {
           pPatternRow++;
        }
        else
        {
           pPatternRow = pPattern;
           RowCount = 0;
        }

        /**********************************************************************/
        /*  For every bit in the current line in the engine character image   */
        /*  that is in SourceRect transfer it to the bitmap.                  */
        /**********************************************************************/
        for (x = (*SourceRect)[0].X; x < (*SourceRect)[1].X; x++)
        {

            /******************************************************************/
            /*  RowBytes is the index into the engine character image of the  */
            /*  byte which contains the bit corresponding to the position we  */
            /*  are interested in.  The +Height-y part allows for the fact    */
            /*  that the bytes in the columns of font definitions are ordered */
            /*  from top to bottom and the -1 allows for the y position       */
            /*  starting at 0.                                                */
            /******************************************************************/
            RowBytes = Height * ( x / 8 ) + Height - y - 1;

            if (lpCharDef[RowBytes] & Mask)
            {

                /**************************************************************/
                /*  If the bit in the engine character image is set the       */
                /*  correpsonding pel using mixpel if the pattern bit is set. */
                /**************************************************************/
                if (*pPatternRow & Mask)
                {
                   prdb_MixPel(ListEntry, CurrPos.x + x, CurrPos.y + y,
                              (BYTE)pTextAttrs->ForeColor,
                              FM_ONE);
                }
                else
                {
                   prdb_MixPel(ListEntry, CurrPos.x + x, CurrPos.y + y,
                              (BYTE)pTextAttrs->ForeColor,
                              FM_ZERO);
                }
            }
            else
            {
                if (pTextAttrs->BackMix != FM_LEAVEALONE)
                    prdb_MixPel(ListEntry, CurrPos.x + x, CurrPos.y + y,
                                (BYTE)pTextAttrs->BackColor,
                                pTextAttrs->BackMix);
            }

            /******************************************************************/
            /*  Advance the mask to the next position,                        */
            /******************************************************************/
            Mask >>= 1;
            if (Mask == 0)
                Mask = 0x80;
        }
    }
    return;
}
#undef TFUNC


/******************************************************************************/
/*  FUNCTION: prdt_TextOutEngFont                                             */
/*                                                                            */
/*  PARAMETERS:                                                               */
/*                                                                            */
/*  HDC              DcH;            Handle to DC                             */
/*  USHORT           Command;                                                 */
/*  PPOINTL          ArgStart;       The starting position for the string of  */
/*                                   characters                               */
/*  PRECTL           ArgOpaqueRect;  Pointer to opaque rectangle (if opaque   */
/*                                   rectangle is specified in ArgOptions)    */
/*  ULONG            ArgOptions;     Flags for the various options            */
/*  LONG             ArgCharNum;     Number of characters to output           */
/*  PCH              ArgCodePoints;  Pointer to the first character code      */
/*                                   point in the list to be printed          */
/*  PLONG            ArgPosVector;   Pointer to an array of values used to    */
/*                                   determine the spacing between characters */
/*                                   in the string                            */
/*  lpTextAttrsType  pTextAttrs;     Pointer to struct containing the colors  */
/*                                   and mixes                                */
/*  lpDCI            DCIData;        Pointer to DC Instance data              */
/*  lpFontDataType   pFontData;                                               */
/*                                                                            */
/*  DESCRIPTION:                                                              */
/*                                                                            */
/*  This function prints a string of characters in engine font to the         */
/*  currently selected bit map.  Opaque rectangles, bounds accumulation and   */
/*  clipping are all handled in this function.  Depending on the CHS_LEAVEPOS */
/*  bit in ArgOptions the function may or may not update the current position */
/*  in the DC Instance data after printing the sequence of characters.        */
/******************************************************************************/
/*CON3201
USHORT prdt_TextOutEngFont(DcH, Command, ArgStart, ArgOpaqueRect,
                                  ArgOptions, ArgCharNum, ArgCodePoints,
                                  ArgPosVector, pTextAttrs, DCIData,
                                  pFontData, ForeColor)
HDC                DcH;
USHORT             Command;
PPOINTL            ArgStart;
PRECTL             ArgOpaqueRect;
ULONG              ArgOptions;
LONG               ArgCharNum;
PCH                ArgCodePoints;
PLONG              ArgPosVector;
lpTextAttrsType    pTextAttrs;
lpDCI              DCIData;
lpFontDataType     pFontData;
ULONG              ForeColor;
                             */

USHORT prdt_TextOutEngFont(HDC                DcH,
                           ULONG              Command,
                           PPOINTL            ArgStart,
                           PRECTL             ArgOpaqueRect,
                           ULONG              ArgOptions,
                           LONG               ArgCharNum,
                           PCH                ArgCodePoints,
                           PLONG              ArgPosVector,
                           lpTextAttrsType    pTextAttrs,
                           lpDCI              DCIData,
                           lpFontDataType     pFontData,
                           ULONG              ForeColor)

{
#define TFUNC "prdt_TxtOEngFnt"

    /**************************************************************************/
    /*  Local variables                                                       */
    /**************************************************************************/
    pBMListEntry         ListEntry;
    USHORT               WorkCoords;
    PDCHARBUNDLE         CurTxtAts;
    ULONG                xStep;
    BOOL                 bFixedPitch;
    POINTS               DevSP;
    POINTS               DevCP;
    POINTL               LongCoords;
    POINTL               WorldCP;
    lpCodePointType      pCPtInfo;
    DevRect              BoundsRect;   /* The bounding rectangle              */
    DevRect              DevOpaqueRect;/* The opaque rect in device coords    */
    USHORT               i, j;         /* Loop control variables              */
    USHORT               SCPCommand;
    DevRect              TrgRect;      /* The area of the bitmap we want to   */
                                       /* write the current character to      */
                                       /* (before clipping)                   */
    DevRect              ClpdSrcRect;  /* The source rectangle which          */
                                       /* determines how much of the character*/
                                       /* we will print after clipping        */
    DevRect              ClpdTrgRect;  /* The area of the bitmap we will write*/
                                       /* the current character to (after     */
                                       /* clipping).                          */
    RECTL                BoundsRectL;  /* Bounds for clipping processing      */
                                       /* PD00462                             */
    BOOL                 fGreyScale;   /* true is greyscaling                 */
    USHORT               usPatType;    /* Type of  greyscale pattern          */
    lpDDTType            pDDT;         /* DDT Pointer                         */
    PBYTE                GSTabPtr;     /* Pointer to greyscale pattern        */

    Command &= DCIData->CommandMask;

    /**************************************************************************/
    /*  Set up local pointers.                                                */
    /**************************************************************************/
    ListEntry = (pBMListEntry)DCIData->DCISelBitmap;
    CurTxtAts = DCIData->DCICurTxtAts;
    pCPtInfo  = &pFontData->CPtInfo;
    pDDT = &DCIData->DCIPdbInstance->DDT;

    /**************************************************************************/
    /*  Set up working coordinate system.  NOTE: This routine has code to     */
    /*  handle mode 2 text.  However currently (Dec 90) mode 2 text is        */
    /*  returned for simulation (this is achieved using the "text simulation" */
    /*  flag set up by prda_SetTextAttrs); see comments in PRDASETB.C (SMP).  */
    /*  Note (AK:Feb 91) changes in scaling functions mean that Mode 2 will   */
    /*  definitely NOT work, and MUST be returned for simulation.             */
    /**************************************************************************/

    if ((ArgOptions & CHS_VECTOR) || (CurTxtAts->cbnd.usPrecision == CM_MODE2))
        WorkCoords = COORD_WORLD;
    else
        WorkCoords = COORD_DEVICE;

    /**************************************************************************/
    /*  Pick up the starting position in device cords and also in world if    */
    /*  neccesary - once set the y coords remain unchanged.                   */
    /**************************************************************************/
    if (prdt_GetStartPos(DcH, ArgStart, ArgOptions, &LongCoords, COORD_DEVICE,
                         Command, DCIData) != OK)
        return (ERROR_ZERO);
    DevSP.x = (SHORT)LongCoords.x;
    DevSP.y = (SHORT)LongCoords.y;
    if (WorkCoords == COORD_WORLD)
    {
        if (prdt_GetStartPos(DcH, ArgStart, ArgOptions, &WorldCP, COORD_WORLD,
                             Command, DCIData) != OK)
            return (ERROR_ZERO);
    }

    /**************************************************************************/
    /*  Adjust the current position - already done for markers.  Note the     */
    /*  assumption that the height and base offset do not vary between        */
    /*  characters in the font.                                               */
    /**************************************************************************/
    DevCP = DevSP;
    if (pFontData->Info.Type != FT_MARKER)
        DevCP.y -= (pCPtInfo->Height - pCPtInfo->BaseOffset);

    /**************************************************************************/
    /*  Set the device text only flag to FALSE since we're about to draw into */
    /*  the band - could be clipped out but it's a reasonable assumption.     */
    /**************************************************************************/
    DCIData->TextOnlyDC = FALSE;

    /**************************************************************************/
    /*  If we need to clip to the opaque rectangle set it up in device coords.*/
    /**************************************************************************/
    if (ArgOptions & CHS_CLIP)
    {
        if (prdg_Convert((PULONG)ArgOpaqueRect, (PULONG)DevOpaqueRect,
                         COORD_WORLD, COORD_DEVICE_WORD, 2L, (hanDC)DcH,
                         Command) != OK)
            return(ERROR_ZERO);
    }

    /**************************************************************************/
    /*  If working in mode 2 with a fixed pitch font pick up the character box*/
    /*  x step to be used throughout.                                         */
    /**************************************************************************/
    if (pFontData->pMetrics->fsTypeFlags & FM_TYPE_FIXED)
    {
        bFixedPitch = TRUE;
        if (CurTxtAts->cbnd.usPrecision == CM_MODE2)
        {
            xStep = prdg_ScaleValue((LONG)CurTxtAts->cbnd.sizfxCell.cx,
                                    (LONG)pFontData->pMetrics->xEmInc,
                                    (LONG)(pFontData->pMetrics->xMaxCharInc *
                                           0x10000));
        }
    }
    else
    {
        bFixedPitch = FALSE;
    }


    /******************************************************************/
    /*  PD00462 : GreyScale engine text                               */
    /******************************************************************/
    if (Command & COM_DRAW)
    {
        /**********************************************************************/
        /*  See if we should greyscale                         12/04/91       */
        /**********************************************************************/
        fGreyScale = prdb_GetGreyScaleInfo(ForeColor, &usPatType,
                                           &GSTabPtr, DCIData);
    }

    for (i = 0; i < (USHORT)ArgCharNum; i++)
    {

        /**********************************************************************/
        /*  Set up access to information about the character we are about to  */
        /*  print (like the defn and width).                                  */
        /**********************************************************************/
        prdt_NextCodePoint((USHORT)ArgCodePoints[i], pFontData, DCIData);

        /**********************************************************************/
        /*  Now clip the character to the currently valid clip rectangles and */
        /*  draw any intersection.  The clipping loop should only be executed */
        /*  if the Draw Bit is on.                                            */
        /**********************************************************************/
        if (Command & COM_DRAW)
        {

            /******************************************************************/
            /*  Set bottom left of target area for the current char to the    */
            /*  current position.  Use the character size which was set up by */
            /*  the call to prdt_NextCodePoint to determine the top right     */
            /*  corner of the target rectangle.  Note that all the rectangles */
            /*  used (except for bounds) are EXCLUSIVE.                       */
            /******************************************************************/
            TrgRect[0].X = DevCP.x;
            TrgRect[0].Y = DevCP.y;
            TrgRect[1].X = TrgRect[0].X + pCPtInfo->Width;
            TrgRect[1].Y = TrgRect[0].Y + pCPtInfo->Height;

            /******************************************************************/
            /*  PD00267 : Pick up the bounding rectangle for the image and    */
            /*  pass it to prdi_GetNextClip().                                */
            /******************************************************************/
            BoundsRectL.xLeft   = (ULONG)TrgRect[0].X;
            BoundsRectL.yBottom = (ULONG)TrgRect[0].Y;
            BoundsRectL.xRight  = (ULONG)TrgRect[1].X + 2; /* PD00311...      */
            BoundsRectL.yTop    = (ULONG)TrgRect[1].Y + 2; /* PD00311...      */

            for (j = 1; prdi_GetNextClip(DCIData, j, (DevRect *)ClpdTrgRect,
                                         &BoundsRectL) == OK;
                 j++)
            {
                /**************************************************************/
                /*  If required clip the character to the opaque rectangle.   */
                /**************************************************************/
                if (ArgOptions & CHS_CLIP)
                {
                    if (!prdi_ClipIntSect((DevRect *)DevOpaqueRect,
                                          (DevRect *)ClpdTrgRect))
                                          {
                                              continue;
                                          }
                }

                /**************************************************************/
                /*  Clip the character to the clip rectangle.                 */
                /**************************************************************/
                if (!prdi_ClipIntSect((DevRect *)TrgRect,
                                      (DevRect *)ClpdTrgRect))
                                      {
                                          continue;
                                      }

                /**************************************************************/
                /*  Establish adjusted ClpdSrcRect.  This is a rect with      */
                /*  coordinates relative to the character cell which defines  */
                /*  how much of the character we want to print.  It can       */
                /*  therefore be determined from the offsets from the         */
                /*  rectangle bounding the whole character cell to the        */
                /*  rectangle bounding the clipped area.                      */
                /**************************************************************/
                ClpdSrcRect[0].X = ClpdTrgRect[0].X - DevCP.x;
                ClpdSrcRect[0].Y = ClpdTrgRect[0].Y - DevCP.y;
                ClpdSrcRect[1].X = ClpdTrgRect[1].X - DevCP.x;
                ClpdSrcRect[1].Y = ClpdTrgRect[1].Y - DevCP.y;

                /**************************************************************/
                /*  Draw the required code point into the bitmap using        */
                /*  ImageChar.                                                */
                /**************************************************************/
                /**************************************************************/
                /*  PD00462 : GreyScale engine text                           */
                /**************************************************************/
                if ( fGreyScale && (usPatType != PAT_ALL_ONES) )
                {
                   prdt_ImageCharGrey(pCPtInfo->Defn,
                                     (DevRect *)ClpdSrcRect,
                                     DevCP, pCPtInfo->Width, pCPtInfo->Height,
                                     ListEntry, pTextAttrs, GSTabPtr);
                }
                else
                {
                    prdt_ImageChar(pCPtInfo->Defn, (DevRect  *)ClpdSrcRect,
                                   DevCP, pCPtInfo->Width, pCPtInfo->Height,
                                   ListEntry, pTextAttrs);
                }
            }
        }

        /**********************************************************************/
        /*  Calculate new current position - not done within COM_DRAW branch  */
        /*  as may reqd for bounds.                                           */
        /**********************************************************************/
        if (WorkCoords == COORD_DEVICE)
        {
            DevCP.x += pCPtInfo->Width;
        }
        else
        {
            if (ArgOptions & CHS_VECTOR)
            {
                WorldCP.x += ArgPosVector[i];
            }
            else
            {
                if (bFixedPitch)
                {
                    WorldCP.x += xStep;
                }
                else
                {
                    WorldCP.x += prdg_ScaleValue((LONG)CurTxtAts->
                                                 cbnd.sizfxCell.cx,
                                                 (LONG)pCPtInfo->Width,
                                                 (LONG)(pFontData->pMetrics->
                                                 xMaxCharInc * 0x10000));
                }
            }
            if (prdg_Convert((PULONG)&WorldCP, (PULONG)&LongCoords, COORD_WORLD,
                             COORD_DEVICE, 1L, (hanDC)DcH, COM_TRANSFORM) != OK)
                return(ERROR_ZERO);
            DevCP.x = (SHORT)LongCoords.x;
        }
    }

    /**************************************************************************/
    /*  Set bounds rectangle if necessary ..  -1 since bounds rectangle is    */
    /*  INCLUSIVE.                                                            */
    /**************************************************************************/
    if (Command & COM_BOUND)
    {
        BoundsRect[0].X = DevSP.x;
        BoundsRect[0].Y = DevCP.y;
        BoundsRect[1].X = DevCP.x - 1;
        BoundsRect[1].Y = DevCP.y + pCPtInfo->Height - 1;
        (VOID)prdg_AddBounds((DevRect  *)BoundsRect, DCIData);
    }

    /**************************************************************************/
    /*  If required (by the CHS_LEAVEPOS flag in ArgOptions) set the current  */
    /*  position in the DC Instance data to the position where a further      */
    /*  character would be printed.                                           */
    /**************************************************************************/
    if (!(ArgOptions & CHS_LEAVEPOS))
    {
        if (WorkCoords == COORD_DEVICE)
        {
            LongCoords.x = (LONG)DevCP.x;
            LongCoords.y = (LONG)DevSP.y;
            SCPCommand = 0;
        }
        else
        {
            LongCoords = WorldCP;
/* CON3201  SCPCommand = COM_TRANSFORM;                 Bits are in HIUSHORT */
            SCPCommand = HIUSHORT(COM_TRANSFORM);
        }

        if (prdl_SetCurrentPosition( DcH, &LongCoords, DCIData,
                                     MAKELONG(NGreSetCurrentPosition,
                                              SCPCommand)) != OK)
            return(ERROR_ZERO);
    }
    return (OK);
}
#undef TFUNC
