/*DDK*************************************************************************/
/*                                                                           */
/* 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.                                */
/*                                                                           */
/*****************************************************************************/
/******************************************************************************/
/*  Module Name: FDPM.C                                                       */
/*                                                                            */
/*      Physical font resource access support routine for OS/2 DBCS PM        */
/*      font drivers.                                                         */
/*                                                                            */
/*  Created: 15-Oct-1991                                                      */
/*  Author:  Soh Ohta     [jl09057 @ ymtvm3, IBM Japan]                       */
/*                                                                            */
/*                        Refer to Copyright Inscruction Form No.G120-2083    */
/*                                                                            */
/*  Exported Functions:   none                                                */
/*                                                                            */
/*  Public Functions:     LoadPMFont                                          */
/*                        FreePMFont                                          */
/*                        QueryPMWidth                                        */
/*                        QueryDefPMWidth                                     */
/*                        QueryPMImage                                        */
/*                        QueryDefPMImage                                     */
/*                        BitmapFromUserFont                                  */
/*                                                                            */
/*  Public Data:          none                                                */
/*                                                                            */
/*  General Description:                                                      */
/*                                                                            */
/******************************************************************************/

#define INCL_PM
#define INCL_DOS
#include <os2.h>
#define INCL_WINP_SELSERVER
#include <pmwinx.h>                     // SSAllocSeg(),SSFreeSeg()
#include <memory.h>
#include "resmap.h"


extern NPBYTE   npImageSrc;             // image mapping work area.
extern NPBYTE   npImageDst;             // image mapping work area.
extern CPINFO   cpInfo;                 // codepage vector.
extern UCHAR    chBootDrive;            // boot drive (A,B,C...).
extern SEL      selDs;                  // FD's shared data segment selector.
extern HMODULE  hmod;                   // FD's module handle.

typedef struct _CHARDEF {   /* cd */
    ULONG       dBits;                  // offset to characrer image.
    USHORT      width;                  // width  of character image.
} CHARDEF, FAR *PCHARDEF;

#define cbFailName  0
#define pszFailName NULL

VOID                FontFromBitmap (PBYTE,NPBITSDEF);
VOID                BitmapFromFont (NPBITSDEF,PBYTE);
NPBITSDEF PASCAL    Bitblt (NPBITSDEF,NPBITSDEF);
USHORT FAR PASCAL   Font_Get (USHORT,PUFONTMAP,PSZ);



/******************************************************************************/
/*  LoadPMFont                                                                */
/*                                                                            */
/*  Load resoures associated to the specified physical font.                  */
/*                                                                            */
/*  Parameter:                                                                */
/*      npFont    = physical font descriptor (font to be modified)            */
/*  Return:                                                                   */
/*      success   = 0                                                         */
/*      error     = -1                                                        */
/******************************************************************************/

USHORT LoadPMFont (NPRESMAP npFont)
{
    register USHORT         rc;
    register NPRESOURCEINFO npResInfo;
    NPUSERFONTINFO          npUsrInfo;
    HMODULE                 hdll;
    USHORT                  GetFontSeg (HMODULE,NPRESOURCEINFO);

    switch (npFont->fontId)
    {
        case FONT_PM_SBCS_RESOURCE:
            npResInfo = (NPRESOURCEINFO)npFont->npPrivate;
            return GetFontSeg (hmod,npResInfo);

        case FONT_PM_SBCS_OTHERDLL:
            npResInfo = (NPRESOURCEINFO)npFont->npPrivate;
            npResInfo->szModule[0] = chBootDrive;
            if (DosLoadModule (pszFailName,cbFailName,npResInfo->szModule,&hdll) == 0) {
                rc = GetFontSeg (hdll,npResInfo);
                DosFreeModule (hdll);
            }
            return rc;

        case FONT_PM_DBCS_USERFONT:
            npUsrInfo = (NPUSERFONTINFO)npFont->npPrivate;
            npUsrInfo->szFile[0] = chBootDrive;
            return 0;

        case FONT_PM_DBCS_FONTFILE:
            return 0;

        default:
            return -1;
    }
}


USHORT GetFontSeg (HMODULE hModule, NPRESOURCEINFO npResInfo)
{
    PBYTE   lp;
    SEL     sel;
    ULONG   ulSize;

    if (DosGetResource2 (hModule,npResInfo->resType,npResInfo->resId,&lp) == 0) {
        DosSizeSeg (SELECTOROF (lp),&ulSize);
        if (SSAllocSeg ((USHORT)ulSize,&sel,SEG_GETTABLE|SEG_GIVEABLE) == 0) {
            npResInfo->lpFoca = (PFOCAFONT)MAKEP(sel,0);
            _fmemcpy (npResInfo->lpFoca,lp,(size_t)ulSize);
            DosFreeResource (lp);
            return 0;
        }
        DosFreeResource (lp);
    }
    return -1;
}

/******************************************************************************/
/*  FreePMFont                                                                */
/*                                                                            */
/*  Free resoures associated to the specified physical font.                  */
/*                                                                            */
/*  Parameter:                                                                */
/*      npFont    = physical font descriptor (font to be modified)            */
/*  Return:                                                                   */
/*      nothing                                                               */
/******************************************************************************/

VOID FreePMFont (NPRESMAP npFont)
{
    register NPRESOURCEINFO npResInfo;

    switch (npFont->fontId)
    {
        case FONT_PM_SBCS_RESOURCE:
        case FONT_PM_SBCS_OTHERDLL:
            npResInfo = (NPRESOURCEINFO)npFont->npPrivate;
            SSFreeSeg (SELECTOROF (npResInfo->lpFoca));
            return;

        case FONT_PM_DBCS_USERFONT:
        case FONT_PM_DBCS_FONTFILE:
        default:
            return;
    }
}

/******************************************************************************/
/*  QueryPMWidth                                                              */
/*                                                                            */
/*  Return specified character cell width.                                    */
/*                                                                            */
/*  Parameter:                                                                */
/*      index     = glyph index                                               */
/*      npVirtual = virtual  font descriptor (FD font being requested)        */
/*      npFont    = physical font descriptor (font to be modified)            */
/*  Return:                                                                   */
/*      success   = character cell width                                      */
/*      error     = 0                                                         */
/******************************************************************************/

USHORT QueryPMWidth (USHORT index, NPRESMAP npVirtual, NPRESMAP npFont)
{
    USHORT      width;
    PFOCAFONT   lpFoca;

    switch (npFont->fontId)
    {
        case FONT_PM_SBCS_RESOURCE:
        case FONT_PM_SBCS_OTHERDLL:

            lpFoca = ((NPRESOURCEINFO)npFont->npPrivate)->lpFoca;
            index -= lpFoca->fmMetrics.usFirstChar;
            if (index <= lpFoca->fmMetrics.usLastChar) {

                if ((npVirtual->fsTypeFlags & FM_TYPE_FIXED) ||
                    (npFont->fsTypeFlags & FM_TYPE_FIXED))
                    return npVirtual->xAveCharWidth;

                width = ((PCHARDEF)&lpFoca[1])[index].width;
                if (npFont->xAveCharWidth == width)
                    return npVirtual->xAveCharWidth;

                return GetMappedWidth (width,npVirtual,npFont);
            }
            return 0;

        case FONT_PM_DBCS_USERFONT:
            return npVirtual->xAveCharWidth;

        case FONT_PM_DBCS_FONTFILE:
        default:
            return 0;
    }
}

/******************************************************************************/
/*  QueryDefPMWidth                                                           */
/*                                                                            */
/*  Return default character cell width.                                      */
/*                                                                            */
/*  Parameter:                                                                */
/*      npVirtual = virtual  font descriptor (FD font being requested)        */
/*      npFont    = physical font descriptor (font to be modified)            */
/*  Return:                                                                   */
/*      success   = character cell width                                      */
/*      error     = 0                                                         */
/******************************************************************************/

USHORT QueryDefPMWidth (NPRESMAP npVirtual, NPRESMAP npFont)
{
    if (npVirtual->fsTypeFlags & FM_TYPE_DBCS)
        // get DBCS default character image.
        return QueryPMWidth (cpInfo.usDefaultChar,npVirtual,npFont);
    else
        // get SBCS default character image.
        return QueryPMWidth (((NPRESOURCEINFO)npFont->npPrivate)->lpFoca->fmMetrics.usDefaultChar,
                             npVirtual,npFont);
}

/******************************************************************************/
/*  QueryPMImage                                                              */
/*                                                                            */
/*  Get specified character image and return its width.                       */
/*                                                                            */
/*  Parameter:                                                                */
/*      index     = glyph index                                               */
/*      npVirtual = virtual  font descriptor (FD font being requested)        */
/*      npFont    = physical font descriptor (font to be modified)            */
/*      lpBuf     = image buffer into which the font is to be built           */
/*      cbBuf     = image buffer size                                         */
/*  Return:                                                                   */
/*      success   = character cell width                                      */
/*      error     = 0                                                         */
/******************************************************************************/

USHORT QueryPMImage (USHORT index, NPRESMAP npVirtual, NPRESMAP npFont, PBYTE lpBuf, USHORT cbBuf)
{
    static BITSDEF      bdSrc,bdDst;
    static UFONTMAP     umSrc;
    register NPBITSDEF  npBdSrc,npBdDst;
    PFOCAFONT           lpFoca;
    PBYTE               lpChar;
    USHORT              cb,widthSrc,widthDst;
    VOID BitmapFromUserFont (NPBITSDEF,NPBYTE,NPUFONTMAP);

    switch (npFont->fontId)
    {
        case FONT_PM_SBCS_RESOURCE:
        case FONT_PM_SBCS_OTHERDLL:

            lpFoca = ((NPRESOURCEINFO)npFont->npPrivate)->lpFoca;
            index -= lpFoca->fmMetrics.usFirstChar;
            if (index <= lpFoca->fmMetrics.usLastChar) {

                npVirtual->bitsDef.npBits = npImageDst;
                npFont->bitsDef.npBits    = npImageSrc;

                lpChar    = MAKEP (SELECTOROF (lpFoca),((PCHARDEF)&lpFoca[1])[index].dBits);
                widthSrc  = ((PCHARDEF)&lpFoca[1])[index].width;

                if ((npFont->fsTypeFlags & FM_TYPE_FIXED) ||
                    (npFont->xAveCharWidth == widthSrc)) {

                    npBdSrc  = &npFont->bitsDef;
                    npBdDst  = &npVirtual->bitsDef;
                    widthDst = npVirtual->xAveCharWidth;

                } else {
                    npBdSrc = &bdSrc;

                    bdSrc.npBits = npFont->bitsDef.npBits;
                    bdSrc.cbScan = (widthSrc-1)/8+1;
                    bdSrc.nScans = npFont->bitsDef.nScans;
                    bdSrc.x      = (npFont->bitsDef.x*widthSrc)/npFont->xAveCharWidth;
                    bdSrc.y      = npFont->bitsDef.y;
                    bdSrc.cx     = (npFont->bitsDef.cx*widthSrc)/npFont->xAveCharWidth;
                    bdSrc.cy     = npFont->bitsDef.cy;

                    if (npVirtual->fsTypeFlags & FM_TYPE_FIXED) {
                        npBdDst  = &npVirtual->bitsDef;
                        widthDst = npVirtual->xAveCharWidth;

                    } else {
                        npBdDst  = &bdDst;
                        widthDst = GetMappedWidth (widthSrc,npVirtual,npFont);

                        bdDst.npBits = npVirtual->bitsDef.npBits;
                        bdDst.cbScan = (widthDst-1)/8+1;
                        bdDst.nScans = npVirtual->bitsDef.nScans;
                        bdDst.x      = (npVirtual->bitsDef.x*widthDst)/npVirtual->xAveCharWidth;
                        bdDst.y      = npVirtual->bitsDef.y;
                        bdDst.cx     = (npVirtual->bitsDef.cx*widthDst)/npVirtual->xAveCharWidth;
                        bdDst.cy     = npVirtual->bitsDef.cy;
                    }
                }

                if ((cb = npBdDst->cbScan*npBdDst->nScans) > cbBuf)
                    return 0;

                if ((npBdSrc->cbScan == npBdDst->cbScan) &&
                    (npBdSrc->nScans == npBdDst->nScans) &&
                    (npBdSrc->x      == npBdDst->x     ) &&
                    (npBdSrc->y      == npBdDst->y     ) &&
                    (npBdSrc->cx     == npBdDst->cx    ) &&
                    (npBdSrc->cy     == npBdDst->cy    )) {

                    _fmemcpy (lpBuf,lpChar,(size_t)cb);
                    return widthDst;
                }

                BitmapFromFont (npBdSrc,lpChar);
                FontFromBitmap (lpBuf,Bitblt(npBdDst,npBdSrc));
                return widthDst;
            }
            return 0;

        case FONT_PM_DBCS_USERFONT:

            if (npVirtual->bitsDef.cbScan*npVirtual->bitsDef.nScans <= cbBuf) {

                // setup image mapping work area.
                npVirtual->bitsDef.npBits = npImageDst;
                npFont->bitsDef.npBits    = npImageSrc;

                // setup font get parameters (dst is used as work area).
                umSrc.lpBits = MAKEP(selDs,npImageDst);
                umSrc.width  = npFont->xAveCharWidth;
                umSrc.height = npFont->yMaxBaselineExt;

                // get user font image and convert it to bitmap format.
                if (Font_Get (index,&umSrc,((NPUSERFONTINFO)npFont->npPrivate)->szFile) != 0)
                    return 0;
                BitmapFromUserFont (&npFont->bitsDef,npImageDst,&umSrc);

                // do image mapping and convert image to font format.
                FontFromBitmap (lpBuf,Bitblt(&npVirtual->bitsDef,&npFont->bitsDef));
                return npVirtual->xAveCharWidth;
            }
            return 0;

        case FONT_PM_DBCS_FONTFILE:
        default:
            return 0;
    }
}

/******************************************************************************/
/*  QueryDefPMImage                                                           */
/*                                                                            */
/*  Get default character image and return its width.                         */
/*                                                                            */
/*  Parameter:                                                                */
/*      npVirtual = virtual  font descriptor (FD font being requested)        */
/*      npFont    = physical font descriptor (font to be modified)            */
/*      lpBuf     = image buffer into which the font is to be built           */
/*      cbBuf     = image buffer size                                         */
/*  Return:                                                                   */
/*      success   = character cell width                                      */
/*      error     = 0                                                         */
/******************************************************************************/

USHORT QueryDefPMImage (NPRESMAP npVirtual, NPRESMAP npFont, PBYTE lpBuf, USHORT cbBuf)
{
    if (npVirtual->fsTypeFlags & FM_TYPE_DBCS)
        // get DBCS default character image.
        return QueryPMImage (cpInfo.usDefaultChar,npVirtual,npFont,lpBuf,cbBuf);
    else
        // get SBCS default character image.
        return QueryPMImage (((NPRESOURCEINFO)npFont->npPrivate)->lpFoca->fmMetrics.usDefaultChar,
                             npVirtual,npFont,lpBuf,cbBuf);
}

/******************************************************************************/
/*  BitmapFromUserFont                                                        */
/*                                                                            */
/*  Convert user font image to bitmap image.                                  */
/*                                                                            */
/*  Parameter:                                                                */
/*      npBd      = destination bitmap image                                  */
/*      npFont    = source user font image                                    */
/*      npUserInfo= user font format information                              */
/*  Return:                                                                   */
/*      nothing                                                               */
/******************************************************************************/

VOID BitmapFromUserFont (NPBITSDEF npBd, NPBYTE npFont, NPUFONTMAP npUserInfo)
{
    NPBYTE  npBitmap;
    USHORT  nScans;

    if (npUserInfo->width == 16) {
        // 16x16 is already in bitmap format.

        memcpy (npBd->npBits,npFont,(size_t)npBd->cbScan*npBd->nScans);
        return;
    }

    if (npUserInfo->width == 20) {
        // 24x24 format.

        npBitmap = npBd->npBits;
        nScans   = npBd->nScans;
        _asm {
            mov     si,npFont           // si = npFont
            mov     di,npBitmap         // di = npBitmap = npBd->npBits
            mov     cx,nScans           // cx = nScans   = npBd->nScans
        store_one_scan_20:              // do {
            mov     ax,[si]             //   al:ah = 11111111:22______
            mov     dx,[si][20*2]       //   dl:dh = 22222233:33______
            ror     dx,2                //   dl:dh = __222222:3333____
            or      ah,dl               //   al:ah = 11111111:22222222
            mov     [di],ax             //   npBitmap[0] = al:ah
            mov     [di][2],dh          //   npBitmap[2] = dh
            add     di,4                //   npBitmap += 4
            add     si,2                //   npFont += 2
            loop    store_one_scan_20   // } while (cx--)
        }
        return;
    }

    if (npUserInfo->width == 24) {
        // 24x24 format.

        npBitmap = npBd->npBits;
        nScans   = npBd->nScans;
        _asm {
            mov     si,npFont           // si = npFont
            mov     di,npBitmap         // di = npBitmap = npBd->npBits
            mov     cx,nScans           // cx = nScans   = npBd->nScans
        store_one_scan_24:              // do {
            mov     ax,[si]             //   al:ah = 11111111:2222____
            mov     dx,[si][24*2]       //   dl:dh = 22223333:3333____
            ror     dx,4                //   dl:dh = ____2222:33333333
            or      ah,dl               //   al:ah = 11111111:22222222
            mov     [di],ax             //   npBitmap[0] = al:ah
            mov     [di][2],dh          //   npBitmap[2] = dh
            add     di,4                //   npBitmap += 4
            add     si,2                //   npFont += 2
            loop    store_one_scan_24   // } while (cx--)
        }
        return;
    }

    if (npUserInfo->width == 28) {
        // 28x28 format.

        npBitmap = npBd->npBits;
        nScans   = npBd->nScans;
        _asm {
            mov     si,npFont           // si = npFont
            mov     di,npBitmap         // di = npBitmap = npBd->npBits
            mov     cx,nScans           // cx = nScans   = npBd->nScans
        store_one_scan_28:              // do {
            mov     ax,[si]             //   al:ah = 11111111:222222__
            mov     dx,[si][28*2]       //   dl:dh = 22333333:334444__
            rol     dx,2                //   dl:dh = 33333333:4444__22
            mov     bh,03h
            and     bh,dh               //      bh =         :______22
            xor     dh,bh               //   dl:dh = 33333333:4444____
            or      ah,bh               //   al:ah = 11111111:22222222
            mov     [di],ax             //   npBitmap[0] = al:ah
            mov     [di][2],dx          //   npBitmap[2] = dl:dh
            add     di,4                //   npBitmap += 4
            add     si,2                //   npFont += 2
            loop    store_one_scan_28   // } while (cx--)
        }
        return;
    }

    if (npUserInfo->width == 32) {
        // 32x32 format.

        npBitmap = npBd->npBits;
        nScans   = npBd->nScans;
        _asm {
            mov     si,npFont           // si = npFont
            mov     di,npBitmap         // di = npBitmap = npBd->npBits
            mov     cx,nScans           // cx = nScans   = npBd->nScans
        store_one_scan_32:              // do {
            mov     ax,[si]             //   al:ah = 11111111:22222222
            mov     dx,[si][32*2]       //   dl:dh = 33333333:44444444
            mov     [di],ax             //   npBitmap[0] = al:ah
            mov     [di][2],dx          //   npBitmap[2] = dl:dh
            add     di,4                //   npBitmap += 4
            add     si,2                //   npFont += 2
            loop    store_one_scan_32   // } while (cx--)
        }
        return;
    }
}

