/*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 = prdb_PolyMarker
 *
 * DESCRIPTIVE NAME =
 *
 *
 * VERSION
 *
 * DATE
 *
 * DESCRIPTION
 *
 * FUNCTIONS
 *
 * ENTRY POINTS:
 *
 * DEPENDENCIES:
 *
 * NOTES
 *
 *
 * STRUCTURES
 *
 * EXTERNAL REFERENCES
 *
 * EXTERNAL FUNCTIONS
 *
*/

#define INCL_32                         /* Convert to C/SET2    CON3201       */
#define INCL_DOSPROCESS                 /* Convert to C/SET2    CON3201       */
#define INCL_DOSSEMAPHORES
#define INCL_GREALL
#define INCL_GPIPRIMITIVES
#define INCL_WINHEAP
#define INCL_GPIBITMAPS
#define INCL_GPIERRORS
#include <os2.h>
#undef INCL_DOSPROCESS                  /* Convert to C/SET2    CON3201       */
#undef INCL_DOSSEMAPHORES
#undef INCL_GREALL
#undef INCL_GPIPRIMITIVES
#undef INCL_WINHEAP
#undef INCL_GPIBITMAPS
#undef INCL_GPIERRORS

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

#define INCL_GRE_LINES
#include <pmddim.h>
#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                          /* Convert to C/SET2    CON3201       */

#include <prdconse.h>
#include <prdncone.h>
#include <prdtcone.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 <prdcextf.h>
#include <prdgextf.h>
#include <prdlextf.h>
#include <prdtextf.h>
#include <prdnextf.h>
#include <prduextf.h>


extern PFNL          da_PolyMarker;





/**********************************************************************/
/*                                                                    */
/*   FUNCTION: prdb_PolyMarker                                        */
/*                                                                    */
/*   PARAMETERS:                                                      */
/*                                                                    */
/*   See "OS/2 Technical Reference: I/O Subsytems and Device Drivers" */
/*                                                                    */
/*   HDC        DcH;                                                  */
/*   PPOINTL    ArgPoints;                                            */
/*   ULONG      ArgNoOfPoints;                                        */
/*   lpDCI      DCIData;                                              */
/*   ULONG      FunN;                                                 */
/*                                                                    */
/*   DESCRIPTION:                                                     */
/*                                                                    */
/*   This function draws a series of markers at the positions         */
/*   specified in ArgPoints (the first marker is drawn at the current */
/*   position, ArgPoints gives coordinates for subsequent markers).   */
/*                                                                    */
/**********************************************************************/
ULONG EXPENTRY prdb_PolyMarker( HDC     DcH,
                                PPOINTL ArgPoints,
                                ULONG   ArgNoOfPoints,
                                lpDCI   DCIData,
                                ULONG   FunN )

{
#define TFUNC "prdb_PolyMarker"

    /******************************************************************/
    /* Local variables                                                */
    /******************************************************************/
    LONG              RetVal;
    ULONG             TOFCommand;
    USHORT            HoldWord;
    ULONG             Command;     /* Command part of FunN            */
    POINTS            StepSize;    /* Size of the martker cell        */
    USHORT            i;           /* Loop control variable           */
    POINTL            StartPos;    /* Start of next marker cell       */
    DCHARBUNDLE       SaveCharDefs;/* Temporary character attributes  */
                                   /* to hold character attrs whilst  */
                                   /* they are replaced by marker     */
                                   /* attrs                           */
    ULONG             Options;
    PDMARKERBUNDLE    pCurMrkAts;
    PDCHARBUNDLE      pCurTxtAts;
    FontDataType      FontData;
    pBMListEntry      ListEntry;   /* Pointer to bitmap list entry    */
    TextAttrsType     TextAttrs;   /* Foreground and background       */
                                   /* colours and mixes               */
    SIZEF             SavedTextBox;
    USHORT            usSavePrecision;
    FMFFileStrucType  FMFData;     /* FMF for current font            */

    /******************************************************************/
    /* This function is a no-op if the number of points is zero.      */
    /******************************************************************/
    if ( ArgNoOfPoints == 0 )
        return (OK);

#ifdef PRD_TIMING
    DEKHOOK0(A,7,62)
#endif
    prdm_EnterDriver(DCIData);

    /******************************************************************/
    /* Check that if target is a memory DC then there is a currently  */
    /* selected bitmap.                                               */
    /******************************************************************/
    if ( (DCIData->DCIDCType == OD_MEMORY) &&
         (DCIData->DCISelBitmap == FNULL) )
    {
        LOGERR(TFUNC, "Bitmap not selected", FNULL, 0,
                                             PMERR_BITMAP_NOT_SELECTED);
        RetVal = ERROR_ZERO;
        goto EXIT_FUNCTION;
    }

    /******************************************************************/
    /* Extract the command bits from the function number parameter.   */
    /******************************************************************/
    Command = FunN & DCIData->CommandMask;

    /******************************************************************/
    /* Do the new framework drawing function - sets DRAWN_INTO flag   */
    /* if COM_DRAW is set. Returns error if not in a suitable state.  */
    /******************************************************************/
    if ( (RetVal = prdn_CheckDrawingState( (PULONG)&Command,
                                                  DCIData ) ) != OK    )
    {
        prdm_LeaveDriver(DCIData);
#ifdef PRD_TIMING
    DEKHOOK0(A,7,E2)
#endif
        return( (RetVal==ERR_PURGE) ? OK : ERROR_ZERO );
    }

    /******************************************************************/
    /* Call not allowed within area.                                  */
    /******************************************************************/
    if ( Command & COM_AREA )
    {
        LOGERR(TFUNC, "Invalid in area", FNULL, 0, PMERR_INV_IN_AREA);
        RetVal = ERROR_ZERO;
        goto EXIT_FUNCTION;
    }

    /******************************************************************/
    /* Set up local pointers.                                         */
    /******************************************************************/
    pCurMrkAts = DCIData->DCICurMrkAts;
    pCurTxtAts = DCIData->DCICurTxtAts;

    /******************************************************************/
    /* Use a simulation for attributed markers if possible - if       */
    /* can't then continue but ignore the attribute.                  */
    /******************************************************************/
    if ( pCurMrkAts->mdef.fFlags &
        (CDEF_BOLD | CDEF_STRIKEOUT | CDEF_ITALIC | CDEF_UNDERSCORE) )
    {
        if ( !(Command & COM_DEVICE) )
        {
            RetVal = ENG_CALL;
            goto EXIT_FUNCTION;
        }
    }

    /******************************************************************/
    /* PD00073                                                        */
    /******************************************************************/
    /******************************************************************/
    /* Copy the text bundle defs attached to the DC Instance          */
    /* data to temporary storage whilst we corrupt it to get the      */
    /* desired output from prdt_TextOut???Font.  Any function exit    */
    /* from now on must first restore the saved defs.                 */
    /******************************************************************/
    prdu_memcpy ( (PBYTE)&SaveCharDefs.cdef,
                  (PBYTE)&pCurTxtAts->cdef,
                  sizeof(CHARDEFS) );

    /******************************************************************/
    /* Also save the CharBundle structure.                            */
    /******************************************************************/
    prdu_memcpy ( (PBYTE)&SaveCharDefs.cbnd,
                  (PBYTE)&pCurTxtAts->cbnd,
                  sizeof(CHARBUNDLE) );

    /******************************************************************/
    /* Make sure the char angle, shear, direction are defaults.       */
    /******************************************************************/
    pCurTxtAts->cbnd.ptlAngle.x = 1;
    pCurTxtAts->cbnd.ptlAngle.y = 0;
    pCurTxtAts->cbnd.ptlShear.x = 0;
    pCurTxtAts->cbnd.ptlShear.x = 1;
    pCurTxtAts->cbnd.usDirection = CHDIRN_LEFTRIGHT;

    /******************************************************************/
    /* Copy over the cell and set the usPrecision to CM_MODE1         */
    /* PolyMarker has no char mode! Set to mode 1 always.             */
    /* Outline fonts same in all modes. (always mode3-like).          */
    /******************************************************************/
    pCurTxtAts->cbnd.sizfxCell = pCurMrkAts->mbnd.sizfxCell;
    pCurTxtAts->cbnd.usPrecision = CM_MODE1;

    /******************************************************************/
    /* Copy the mdef structure from the marker bundle to the cdef     */
    /* structure of the character bundle.                             */
    /******************************************************************/
    prdu_memcpy ( (PBYTE)&pCurTxtAts->cdef,
                  (PBYTE)&pCurMrkAts->mdef,
                  sizeof(MARKERDEFS) );

    if ( pCurMrkAts->mdef.defSet == 0 )
    {
        /**************************************************************/
        /* If the marker defSet is 0 then we use our default marker   */
        /* font - reset the char defset value to act as a flag to     */
        /* prdt_LocateFont.  We want to leave the marker defset value */
        /* at 0 to avoid having to check for both 0 and the value     */
        /* DFLT_MARKER_SET to detect that we've got the default       */
        /* marker set.                                                */
        /**************************************************************/
        pCurTxtAts->cdef.defSet = DFLT_MARKER_FONT;
    }

    /******************************************************************/
    /* Set up local copy of font data structure - prdt_LocateFont     */
    /* depends only on the cdef structure.                            */
    /******************************************************************/
    FontData.Info.pFont = &FMFData;
    if ( prdt_LocateFont(&FontData, DCIData) != OK )
    {
        RetVal = ERROR_ZERO;
        goto EXIT_RESTORE_DEFS;
    }

    /******************************************************************/
    /* Pass an engine outline font back for simulation.               */
    /*                                                                */
    /* Note that the default marker font is a bitmap font.            */
    /******************************************************************/
    if ( (FontData.pMetrics->fsDefn & FM_DEFN_OUTLINE) &&
         (FontData.Genre == NON_DEVICE_FONT) )
    {
        RetVal = ENG_CALL;
        goto EXIT_RESTORE_DEFS;
    }

    /******************************************************************/
    /* Image fonts are illegal in path.                               */
    /******************************************************************/
    if ( (Command & COM_PATH) &&
         !(FontData.pMetrics->fsDefn & FM_DEFN_OUTLINE) )
    {
        LOGERR(TFUNC, "Invalid in path", FNULL, 0, PMERR_INV_IN_PATH);
        RetVal = ERROR_ZERO;
        goto EXIT_RESTORE_DEFS;
    }

    /******************************************************************/
    /* Establish Foreground and Background Color and Mix.             */
    /******************************************************************/
    ListEntry = (pBMListEntry)DCIData->DCISelBitmap;

    TextAttrs.ForeColor = prdc_ColorToPelBits( pCurMrkAts->mbnd.lColor,
                                               DCIData,
                                               ListEntry->DCTPtr );

    TextAttrs.BackColor = prdc_ColorToPelBits( pCurMrkAts->mbnd.lBackColor,
                                               DCIData,
                                               ListEntry->DCTPtr );

    TextAttrs.ForeMix = pCurMrkAts->mbnd.usMixMode;
    TextAttrs.BackMix = pCurMrkAts->mbnd.usBackMixMode;

    /******************************************************************/
    /* In order to "centre the markers" we need to subtract           */
    /* (positive) x and y steps from the reqd marker position to get  */
    /* the start position to pass to prdt_TextOut???Font (these fns   */
    /* draw characters based on a point near the bottom left of the   */
    /* character cell).                                               */
    /*                                                                */
    /* If character set is default use marker step size of 3 (= 7/2); */
    /* otherwise use character cell size from metrics - StepSize is   */
    /* in device coords.                                              */
    /******************************************************************/
    if ( pCurMrkAts->mdef.defSet == 0 )
    {
        StepSize.x = 3;
        StepSize.y = 3;
    }
    else
    {
        prdt_NextCodePoint( pCurMrkAts->mbnd.usSymbol,
                            &FontData,
                            DCIData );

        /**************************************************************/
        /* The y step for an image font marker is                     */
        /*     (Height / 2) - (Height - BaseOffset)                   */
        /*                                                            */
        /* The x step for an image font marker is                     */
        /*     (Width / 2) if no per character definition             */
        /*     (A+B+C Space / 2) - ASpace if per character definition */
        /**************************************************************/
        if ( FontData.Genre != DEVICE_FONT )
        {
            /**********************************************************/
            /* Have we got per character definition...                */
            /**********************************************************/
            if ( FontData.pHeader->usCellSize != 0 )
            {
                StepSize.x = (FontData.CPtInfo.Width / 2) -
                                                FontData.CPtInfo.ASpace;
            }
            else
            {
                StepSize.x = (FontData.CPtInfo.Width / 2);
            }

            StepSize.y = (FontData.CPtInfo.Height / 2) -
                                 (FontData.CPtInfo.Height -
                                          FontData.CPtInfo.BaseOffset);
        }
        else
        {
            /**********************************************************/
            /* If this is a device font the values in the metrics wil */
            /* be in font coords - convert them to device coords.     */
            /* The values will already be adjusted for any double     */
            /* high/wide attributes.                                  */
            /**********************************************************/

            /**********************************************************/
            /* NOTE: WorkCoords are COORD_WORLD for outline or mode2; */
            /* or COORD_FONT. Never have mode2 device font here       */
            /* (see comments above); and for outline fonts the code   */
            /* in NextCodePoint sets up the Width and Height fields   */
            /* from the char box correctly.  Therefore no scaling     */
            /* needs to be done here.                                 */
            /**********************************************************/
            /* NB order of conversion & division improves the rounding*/
            /**********************************************************/

            StepSize.x = prdt_XformFontValue(
                                     FontData.CPtInfo.Width,
                                     FONT_TO_DEVICE | CONV_X_VALUE,
                                     &FontData ) / 2;

            HoldWord = (FontData.CPtInfo.BaseOffset * 2) -
                                 FontData.CPtInfo.Height;

            StepSize.y = prdt_XformFontValue(
                                     HoldWord,
                                     FONT_TO_DEVICE | CONV_Y_VALUE,
                                     &FontData ) / 2;
        }
    }

    /******************************************************************/
    /* Adjust the position so that the centre of the marker is at     */
    /* the current position.                                          */
    /******************************************************************/
    StartPos.x = (LONG)(DCIData->DCICurrPosDev.X - StepSize.x);
    StartPos.y = (LONG)(DCIData->DCICurrPosDev.Y - StepSize.y);

    /******************************************************************/
    /* The following options are required for prdt_TextOut???Font.    */
    /* StartPos is given (in device coords) and we must not update    */
    /* the current position on completion (this is done later).       */
    /******************************************************************/
    Options    = CHS_START_XY | CHS_LEAVEPOS;
    TOFCommand = Command & ~COM_TRANSFORM;

    /******************************************************************/
    /* Repeat for each marker - there are ArgNoOfPoints - 1 coords    */
    /* in ArgPoints.                                                  */
    /******************************************************************/
    for ( i = 0; ; i++ )
    {
        if ( FontData.Genre == DEVICE_FONT )
        {
            RetVal = prdt_TextOutDevFont( DcH,
                                          (ULONG)TOFCommand,
                                          &StartPos,
                                          FNULL,       /* Opaque rect */
                                          Options,
                                          1L,
                                          (PCH)&pCurMrkAts->mbnd.usSymbol,
                                          FNULL,       /* Pos vectors */
                                          &TextAttrs,
                                          DCIData,
                                          &FontData );

        }
        else
        {
            RetVal = prdt_TextOutEngFont( DcH,
                                          (ULONG)TOFCommand,
                                          (PPOINTL)&StartPos,
                                          FNULL,       /* Opaque rect */
                                          Options,
                                          1L,
                                          (PCH)&pCurMrkAts->mbnd.usSymbol,
                                          FNULL,       /* Pos vectors */
                                          (lpTextAttrsType)&TextAttrs,
                                          DCIData,
                                          (lpFontDataType)&FontData,
                                          pCurMrkAts->mbnd.lColor); /* PD00462*/
        }

        if ( RetVal != OK )
            goto EXIT_RESTORE_DEFS;

        /**************************************************************/
        /* Jump out now to avoid referencing ArgPoints out of range.  */
        /**************************************************************/
        if ( i == (USHORT)ArgNoOfPoints - 1 )
            goto EXIT_RESTORE_DEFS;

        /**************************************************************/
        /* Convert the position to device coordinates.                */
        /**************************************************************/
        if ( prdg_Convert( (PULONG)(ArgPoints + i),
                           (PULONG)&StartPos,
                           COORD_WORLD, COORD_DEVICE, 1L,
                           (hanDC)DcH, (ULONG)Command ) != OK )
        {
            RetVal = ERROR_ZERO;
            goto EXIT_RESTORE_DEFS;
        }

        StartPos.x -= (LONG)StepSize.x;
        StartPos.y -= (LONG)StepSize.y;
    }


EXIT_RESTORE_DEFS:
    /******************************************************************/
    /* PD00073                                                        */
    /******************************************************************/
    /******************************************************************/
    /* Reset text attribute bundle from our copy.                     */
    /******************************************************************/
    prdu_memcpy ( (PBYTE)&pCurTxtAts->cdef,
                  (PBYTE)&SaveCharDefs.cdef,
                  sizeof(CHARDEFS) );

    /******************************************************************/
    /* Restore the text box and precision.                            */
    /******************************************************************/
    prdu_memcpy ( (PBYTE)&pCurTxtAts->cbnd,
                  (PBYTE)&SaveCharDefs.cbnd,
                  sizeof(CHARBUNDLE) );


EXIT_FUNCTION:
    /******************************************************************/
    /* Update current position if points where given, otherwise only  */
    /* marker will have been output at the current position anyway.   */
    /******************************************************************/
    prdm_LeaveDriver(DCIData);

    if ( ((LONG)ArgNoOfPoints > 1) && (RetVal == OK) )
    {
#ifdef PRD_TIMING
    DEKHOOK0(A,7,E2)
#endif
        return( prdl_SetCurrentPosition(
                  DcH,
                  ArgPoints + ((USHORT)ArgNoOfPoints - 2),
                  DCIData,
                  MAKELONG(NGreSetCurrentPosition, (HIUSHORT(Command)))));
    }

#ifdef PRD_TIMING
    DEKHOOK0(A,7,E2)
#endif

    if ( RetVal == ENG_CALL )
    {
        /**************************************************************/
        /* Return to engine if the COM_DEVICE bit allows, otherwise   */
        /* just return OK.                                            */
        /**************************************************************/
        if ( !(Command & COM_DEVICE) )
            return( da_PolyMarker( DcH,
                                   ArgPoints, ArgNoOfPoints,
                                   DCIData, FunN ) );
        else
            return (OK);
    }
    else
    {
        return (RetVal);
    }

}
#undef TFUNC

