text: /******************************Module*Header*******************************\
  * Module Name: simulate.c
  *
  *  routines associated with simulated faces i.e. emboldened
  *  and/or italicized  faces
  *
  * Created: 17-Apr-1991 08:31:18
  * Author: Bodin Dresevic [BodinD]
  *
  * Copyright (c) 1990 Microsoft Corporation
  *
  \**************************************************************************/
  
  #include "fd.h"
  
  #ifdef SAVE_FOR_HISTORICAL_REASONS
  
  /******************************Public*Routine******************************\
  *
  * VOID vEmboldenBitmap(RASTERGLYPH * pgldtSrc,RASTERGLYPH * pgldtDst,LONG culDst)
  *
  * modifies an original glyph bitmap for the default face
  * to produce the bitmap that corresponds to an emboldened char.
  * Emboldened bitmap is simply an original bitmap offsetted to the right
  * by one pel and OR-ed with the original bitmap itself.
  *
  * History:
  *  22-Apr-1991 -by- Bodin Dresevic [BodinD]
  * Wrote it.
  \**************************************************************************/
  
  VOID
  vEmboldenBitmap(
      RASTERGLYPH * prgSrc,
      RASTERGLYPH * prgDst
      )
  {
      ULONG cxSrc = prgSrc->gb.sizlBitmap.cx;
      ULONG cy    = prgSrc->gb.sizlBitmap.cy;      // same for src and dst
      ULONG cxDst = cxSrc + 1;                // + 1 for emboldening
  
      PBYTE pjSrc = prgSrc->gb.aj;
      PBYTE pjDst = prgDst->gb.aj;
  
      ULONG iScan,iByte;        // loop indices
      PBYTE pjS,pjD;
  
  // number of bytes in one scan of the Dst or Src bitmaps. (dword aligned)
  
      ULONG cjScanDst = CJ_SCAN(cxDst);
      ULONG cjScanSrc = CJ_SCAN(cxSrc);
      ULONG cjBmp        = cjScanDst * cy;
  
      ULONG cjScanDst = CJ_SCAN(cxDst);
      ULONG cjScanSrc = CJ_SCAN(cxSrc);
      BYTE  jCarry;   // carry bit from shifting Src byte by 1;
  
      GLYPHDATA *pgldtSrc = &prgSrc->gd;
      GLYPHDATA *pgldtDst = &prgDst->gd;
  
  #ifdef DUMPCALL
      DbgPrint("\nvEmboldenBitmap(");
      DbgPrint("\n    RASTERGLYPH *prgSrc = %-#8lx",prgSrc);
      DbgPrint("\n    RASTERGLYPH *prgDst = %-#8lx",prgDst);
      DbgPrint("\n    )\n");
  #endif
  
      RtlCopyMemory(prgDst,
                    prgSrc,
                    offsetof(RASTERGLYPH,gb) + offsetof(GLYPHBITS,sizlBitmap));
  
  // if engine requested memory that is zero-ed out we would not have to do it
  // ourselves
  
      RtlZeroMemory(pjDst, cjBmp);
  
  // make necessary changes to the fields of GLYPHDATA which
  // are affected by emboldening
  
      pgldtDst->gdf.pgb = &prgDst->gb;
  
      pgldtDst->rclInk.right += (LONG)1;
  
  // pre and post bearings have not changed nor bmp origin, only inked box
  
      pgldtDst->fxD = LTOFX(cxDst);
      pgldtDst->ptqD.x.HighPart = (LONG)pgldtDst->fxD;
      pgldtDst->fxAB = pgldtDst->fxD;     // right edge of the black box
  
  // this needs to be changed a bit since aulBMData will not live
  // in the GLYPHDATA structure any more
  
      prgDst->gb.sizlBitmap.cx = cxDst;
      prgDst->gb.sizlBitmap.cy = cy;
  
  // embolden bitmap scan by scan
  
      for (iScan = 0L; iScan < cy; iScan++)
      {
          pjS = pjSrc;
          pjD = pjDst;
  
      // embolden individual scans
  
          jCarry = (BYTE)0;   // no carry to the first byte in the row
  
          for(iByte = 0L; iByte < cjScanSrc; iByte++, pjS++, pjD++)
          {
              *pjD = (BYTE)(*pjS | ((*pjS >> 1) | jCarry));
  
          // remember the rightmost bit and shift it to the leftmost position
  
              jCarry = (BYTE)(*pjS << 7);
          }
  
          if ((cxSrc & 7L) == 0L)
              *pjD = jCarry;
  
      // advance to the next scan of the src and dst
  
          pjSrc += cjScanSrc;
          pjDst += cjScanDst;
      }
  }
  #endif // SAVE_FOR_HISTORICAL_REASONS
  
  /******************************Public*Routine******************************\
  * cjGlyphDataSimulated
  *
  * Computes the size of the glyphdata for the simulated face given cx and cy
  * for the corresponding char in the default face
  *
  * History:
  *  22-Apr-1991 -by- Bodin Dresevic [BodinD]
  * Wrote it.
  \**************************************************************************/
  
  #ifdef FE_SB // cjGlyphDataSimulated():
  LONG
  cjGlyphDataSimulated(
      FONTOBJ *pfo,
      ULONG    cxNoSim,    // cx for the same char of the default face
      ULONG    cyNoSim,    // cy for the same char of the default face
      ULONG   *pcxSim,
      ULONG    ulRotate    // Rotation degree
      )
  #else
  LONG
  cjGlyphDataSimulated(
      FONTOBJ *pfo,
      ULONG    cxNoSim,    // cx for the same char of the default face
      ULONG    cyNoSim,    // cy for the same char of the default face
      ULONG   *pcxSim
      )
  #endif
  {
      ULONG cxSim;
  
  #ifdef DUMPCALL
      DbgPrint("\ncjGlyphDataSimulated(");
      DbgPrint("\n    ULONG        cxNoSim = %-#8lx",cxNoSim);
      DbgPrint("\n    ULONG        cyNoSim = %-#8lx",cyNoSim);
      DbgPrint("\n    ULONG       *pcxSim  = %-#8lx",pcxSim );
      DbgPrint("\n    )\n");
  #endif
  
      if (cxNoSim == 0)
      {
      // blank 1x1 bitmap
  
          cxSim    = 1;
          cyNoSim  = 1;
      }
      else
      {
          switch( pfo->flFontType & (FO_SIM_BOLD | FO_SIM_ITALIC) )
          {
          case 0:
              cxSim = cxNoSim;
              break;
  
          case FO_SIM_BOLD:
  
              cxSim = cxNoSim + 1;
              break;
  
          case FO_SIM_ITALIC:
  
              cxSim = cxNoSim + (cyNoSim - 1) / 2;
              break;
  
          default:
  
          // here we have used that
          // (k - 1) / 2 + 1 == (k + 1) / 2 for every integer k, (k == cy)
  
              cxSim = cxNoSim + (cyNoSim + 1) / 2;
              break;
          }
      }
  
      if (pcxSim != (ULONG *)NULL)
      {
          *pcxSim = cxSim;
      }
  
  #ifdef FE_SB // cjGlyphDataSimulated():
  
  #ifdef DBG_MORE
      DbgPrint("cxSim - 0x%x\n : cyNoSim - 0x%x\n",cxSim , cyNoSim);
  #endif // DBG_MORE
  
      switch( ulRotate )
      {
      case 0L :
      case 1800L :
  
          return(CJ_GLYPHDATA(cxSim, cyNoSim));
  
      case 900L :
      case 2700L :
  
          return(CJ_GLYPHDATA(cyNoSim, cxSim));
      default :
          /* we should never be here */
          return(CJ_GLYPHDATA(cxSim, cyNoSim));
      }
  #else
      return(CJ_GLYPHDATA(cxSim, cyNoSim));
  #endif
  
  }
  
  /******************************Public*Routine******************************\
  *
  * cFacesRes
  *
  * History:
  *  13-May-1991 -by- Bodin Dresevic [BodinD]
  * Wrote it.
  \**************************************************************************/
  
  ULONG
  cFacesRes(
      PRES_ELEM pre
      )
  {
      FSHORT fs = fsSelectionFlags((PBYTE)pre->pvResData);
  
  #ifdef DUMPCALL
      DbgPrint("\ncFacesRes(");
      DbgPrint("\n    PRES_ELEM pre = %-#8lx", pre);
      DbgPrint("\n    )\n");
  #endif
  
  // kill all the bits but BOLD and ITALIC
  
      fs = fs & (FSHORT)(FM_SEL_BOLD | FM_SEL_ITALIC);
  
      //!!! DbgPrint("fsSelection = 0x%lx\n", (ULONG)fs);
  
      if (fs == 0)    // default face is NORMAL
          return(4L);
  
      if ((fs == FM_SEL_BOLD) || (fs == FM_SEL_ITALIC))
          return(2L);
  
      if (fs == (FM_SEL_BOLD | FM_SEL_ITALIC))
          return(1L);
  
      /* we should never be here */
      return (4L);
  }
  
  /******************************Public*Routine******************************\
  * VOID vDefFace
  *
  * History:
  *  13-May-1991 -by- Bodin Dresevic [BodinD]
  * Wrote it.
  \**************************************************************************/
  
  VOID
  vDefFace(
      FACEINFO   *pfai,
      RES_ELEM   *pre
      )
  {
  // kill all bits but BOLD and ITALIC bits that should remain unchanged
  
      FSHORT fs = (FSHORT)(
          fsSelectionFlags((PBYTE) pre->pvResData) &
          (FM_SEL_BOLD  | FM_SEL_ITALIC)
          );
  
      switch (fs)
      {
      case 0:
          pfai->iDefFace = FF_FACE_NORMAL;
          return;
  
      case FM_SEL_BOLD:
          pfai->iDefFace = FF_FACE_BOLD;
          return;
  
      case FM_SEL_ITALIC:
          pfai->iDefFace = FF_FACE_ITALIC;
          return;
  
      case (FM_SEL_ITALIC | FM_SEL_BOLD):
          pfai->iDefFace = FF_FACE_BOLDITALIC;
          return;
  
      default:
          RIP("bmfd!_which ape has messed up the code ?\n");
          return;
      }
  }
  
  #if 0 /* This function is never used, and ignores memory accesses outside the mapped file. */
  
  /******************************Public*Routine******************************\
  *
  * ULONG cFacesFON     // no. of faces associated with this FON file
  *
  * History:
  *  January 2002 -by- Jay Krell [JayKrell]
  *    #if 0'ed out.
  *  13-May-1991 -by- Bodin Dresevic [BodinD]
  * Wrote it.
  \**************************************************************************/
  
  ULONG
  cFacesFON(
      PWINRESDATA pwrd
      )
  {
      ULONG cFace;
      ULONG iRes;
      RES_ELEM re;
  
  #ifdef DUMPCALL
      DbgPrint("\ncFacesFON(");
      DbgPrint("\n    PWINRESDATA pwrd = %-#8lx", pwrd);
      DbgPrint("\n    )\n");
  #endif
  
  // this function should have not been called if there are no
  // font resources associated with this pwrd
  
      ASSERTGDI(pwrd->cFntRes != 0L, "No font resources\n");
  
      cFace = 0L;     // init the sum
  
      for (iRes = 0L; iRes < pwrd->cFntRes; iRes++)
      {
          if (bGetFntResource(pwrd,iRes,&re))
              cFace += cFacesRes(&re);
      }
      return(cFace);
  }
  #endif
  
  /******************************Public*Routine******************************\
  *
  * vComputeSimulatedGLYPHDATA
  *
  * History:
  *  06-Oct-1992 -by- Bodin Dresevic [BodinD]
  * Wrote it.
  \**************************************************************************/
  
  VOID
  vComputeSimulatedGLYPHDATA(
      GLYPHDATA *pgldt    ,
      PBYTE      pjBitmap ,
      ULONG      cxNoSim  ,
      ULONG      cy       ,
      ULONG      yBaseLine,
      ULONG      cxScale,
      ULONG      cyScale,
      FONTOBJ   *pfo
      )
  {
      ULONG cxSim;            // cx for the bitmap
      LONG  xCharInc;         // x component of the char inc vector
  
  // the following coords refer to bitmap coord system, i.e. the one in which
  // the BM origin has coors (0,0)
  
      ULONG yTopIncMin;    // min over non zero raws
      ULONG yBottomExcMax; // max+1 over non zero raws
  
  #ifdef DUMPCALL
      DbgPrint("\nvComputeSimulatedGLYPHDATA(");
      DbgPrint("\n    GLYPHDATA         *pgldt     = %-#8lx",pgldt     );
      DbgPrint("\n    PBYTE              pjBitmap  = %-#8lx",pjBitmap  );
      DbgPrint("\n    ULONG              cxNoSim   = %-#8lx",cxNoSim   );
      DbgPrint("\n    ULONG              cy        = %-#8lx",cy        );
      DbgPrint("\n    ULONG              yBaseLine = %-#8lx",yBaseLine );
      DbgPrint("\n    FONTOBJ           *pfo       = %-#8lx",pfo       );
      DbgPrint("\n    )\n");
  #endif
  
  // compute top and bottom by looking into the bitmap in the row format:
  
      vFindTAndB (
          pjBitmap, // pointer to the bitmap in *.fnt column format
          cxNoSim,
          cy,
          &yTopIncMin,
          &yBottomExcMax
          );
  
      if( cyScale != 1 )
      {
          yTopIncMin *= cyScale;
          yBottomExcMax *= cyScale;
          cy *= cyScale;
          yBaseLine *= cyScale;
      }
  
      cxNoSim *= cxScale;
  
      pgldt->gdf.pgb = NULL;
  
      if (yTopIncMin == yBottomExcMax) // no ink at all
      {
      // this is a tricky point. We are dealing with a blank bitmap.
      // The first thought would be to report the zero inked box. It
      // then ambiguous what an A and C spaces should be. The right way to
      // think of this bitmap (this is in fact the break char) is that the
      // inked box is the whole bitmap, just the "color" of the ink happens
      // to be invisible. This is important when dealing with strings
      // which have break character as the first or the last char in the string.
      // If the inked box was reported as zero, text extent for such a string
      // would be computed incorrectly when the corrections for the first A
      // and last C are taken into account
  
          yTopIncMin = 0L;    // coincides with the top
          yBottomExcMax = cy * cyScale; // coincides with the bottom
      }
  
  // these have to be correct, important for computing char inc for esc != 0
  
      pgldt->rclInk.top = (LONG)(yTopIncMin - yBaseLine);
      pgldt->rclInk.bottom = (LONG)(yBottomExcMax - yBaseLine);
  
  // minus sign is because the scalar product is supposed to be taken with
  // a unit ascender vector
  
      pgldt->fxInkTop    = -LTOFX(pgldt->rclInk.top);
      pgldt->fxInkBottom = -LTOFX(pgldt->rclInk.bottom);
  
      switch(pfo->flFontType & (FO_SIM_BOLD | FO_SIM_ITALIC))
      {
      case 0:
          cxSim = cxNoSim;
          xCharInc = (LONG)cxNoSim;
          break;
  
      case FO_SIM_BOLD:
  
          cxSim = cxNoSim + 1;
          xCharInc = (LONG)(cxNoSim + 1);
          break;
  
      case FO_SIM_ITALIC:
  
          cxSim = cxNoSim + (cy - 1) / 2;
          xCharInc = (LONG)cxNoSim;
          break;
  
      case (FO_SIM_BOLD | FO_SIM_ITALIC):
  
      // here we have used that
      // (k - 1) / 2 + 1 == (k + 1) / 2 for every integer k, (k == cy)
  
          cxSim = cxNoSim + (cy + 1) / 2;
          xCharInc = (LONG)(cxNoSim + 1);
          break;
  
      default:
          // to silence prefix
          cxSim = 1;
          RIP("BMFD!BAD SIM FLAG\n");
      }
  
      if (cxNoSim == 0)
      {
          cxSim = 1; // 1X1 blank box
          xCharInc = 0;
      }
  
      pgldt->fxD = LTOFX(xCharInc);
      pgldt->ptqD.x.HighPart = (LONG)pgldt->fxD;
      pgldt->ptqD.x.LowPart  = 0;
      pgldt->ptqD.y.HighPart = 0;
      pgldt->ptqD.y.LowPart  = 0;
  
  // in this crude picture we are luying about x extents of the black box
  // and report the whole bitmap width as an extent
  
      pgldt->rclInk.left  = 0;           // rclInk.left == lhs of the bitmap, => A < 0
      pgldt->rclInk.right = (LONG)cxSim; // the rhs of the bitmap => c < 0
  
  // compute bearings, remember the rule A + B + C == char inc
  // where B is the size of the inked box. For the horizontal case:
  //          A == ePreBearing , C == ePostBearing
  // In view of these sum rules and the definitions of A,B,C we have
  //          B = rclInk.right - rclInk.left;
  //          A = rclInk.left;
  //          C = xCharInc - rclInk.right;
  //      The sum rule is trivially obeyed.
  
      pgldt->fxA =  LTOFX(pgldt->rclInk.left); // fxA
      pgldt->fxAB = LTOFX(pgldt->rclInk.right); // right edge of the black box
  }
  
  /******************************Public*Routine******************************\
  *
  * VOID vCvtToBmp
  *
  * Effects: takes the bitmap in the original *.fnt column format and converts
  *          it to the Bmp format.
  *
  * History:
  *  25-Nov-1990 -by- Bodin Dresevic [BodinD]
  * Wrote it.
  \**************************************************************************/
  
  VOID vCvtToBmp
  (
  GLYPHBITS *pgb,
  GLYPHDATA *pgd,
  PBYTE pjBitmap,     // pointer to the bitmap in *.fnt column format
  ULONG cx,
  ULONG cy,
  ULONG yBaseLine
  )
  {
      ULONG cjScan = CJ_SCAN(cx);  // # of bytes per scan of the Bmp
  
  // pjColumn points to one of the bytes in the first ROW of the Bmp
  
      PBYTE pjColumn, pjColumnEnd;
      PBYTE pjDst, pjDstEnd;           // current destination byte
  
  #ifdef DUMPCALL
      DbgPrint("\nvCvtToDIB(");
      DbgPrint("\n    GLYPHBITS    pgb       = %-#8lx",pgb      );
      DbgPrint("\n    GLYPHDATA    pgd       = %-#8lx",pgd      );
      DbgPrint("\n    PBYTE        pjBitmap  = %-#8lx",pjBitmap );
      DbgPrint("\n    ULONG        cx        = %-#8lx",cx       );
      DbgPrint("\n    ULONG        cy        = %-#8lx",cy       );
      DbgPrint("\n    ULONG        yBaseLine = %-#8lx",yBaseLine);
      DbgPrint("\n    )\n");
  #endif
  
  // store cx and cy at the top, before Bits
  
      pgb->sizlBitmap.cx = cx;
      pgb->sizlBitmap.cy = cy;
  
  // this is character independent for BM fonts
  
      pgb->ptlOrigin.x = 0L;
      pgb->ptlOrigin.y = -(LONG)yBaseLine;
  
      RtlZeroMemory(pgb->aj, cjScan * cy);
  
  // we shall fill the Bmp column by column, thus traversing the src a byte at
  // the time:
  
      for
      (
          pjColumn = pgb->aj, pjColumnEnd = pjColumn + cjScan;
          pjColumn < pjColumnEnd;
          pjColumn++
      )
      {
          for
          (
              pjDst = pjColumn, pjDstEnd = pjColumn + cy * cjScan;
              pjDst < pjDstEnd;
              pjDst += cjScan, pjBitmap++
          )
          {
              *pjDst = *pjBitmap;
          }
      }
  }
  
  /******************************Public*Routine******************************\
  *
  * vCvtToBoldBmp
  *
  * History:
  *  06-Oct-1992 -by- Bodin Dresevic [BodinD]
  * Wrote it.
  \**************************************************************************/
  
  VOID vCvtToBoldBmp
  (
  GLYPHBITS *pgb,
  GLYPHDATA *pgd,
  PBYTE pjBitmap,     // pointer to the bitmap in *.fnt column format
  ULONG cxSrc,
  ULONG cy,
  ULONG yBaseLine
  )
  {
      PBYTE pjSrc;
      PBYTE pjDst;
  
      ULONG cxDst = cxSrc + 1;                // + 1 for emboldening
      ULONG iScan,iByte;        // loop indices
      PBYTE pjS,pjD;
  
  // number of bytes in one scan of the Dst or Src bitmaps. (dword aligned)
  
      ULONG cjScanDst = CJ_SCAN(cxDst);
      ULONG cjScanSrc = CJ_SCAN(cxSrc);
      BYTE  jCarry;   // carry bit from shifting Src byte by 1;
  
  #ifdef DUMPCALL
      DbgPrint("\nVOID");
      DbgPrint("\nvCvtToBoldDIB(");
      DbgPrint("\n    GLYPHBITS    pgb       = %-#8lx",pgb      );
      DbgPrint("\n    GLYPHDATA    pgd       = %-#8lx",pgd      );
      DbgPrint("\n    PBYTE        pjBitmap  = %-#8lx",pjBitmap );
      DbgPrint("\n    ULONG        cxSrc     = %-#8lx",cxSrc    );
      DbgPrint("\n    ULONG        cy        = %-#8lx",cy       );
      DbgPrint("\n    ULONG        yBaseLine = %-#8lx",yBaseLine);
      DbgPrint("\n    )\n");
  #endif
  
  // this is character independent for BM fonts
  
      pgb->ptlOrigin.x = 0L;
      pgb->ptlOrigin.y = -(LONG)yBaseLine;
  
      pgb->sizlBitmap.cx = cxDst;
      pgb->sizlBitmap.cy = cy;
  
  // init the loop over scans
  
      pjSrc = pjBitmap;
      pjDst = pgb->aj;
  
  // embolden bitmap scan by scan
  
  // if engine requested memory that is zero-ed out we would not have to do it
  // ourselves
  
      RtlZeroMemory(pjDst, cjScanDst * cy);
  
      for (iScan = 0L; iScan < cy; iScan++)
      {
          pjS = pjSrc;
          pjD = pjDst;
  
      // embolden individual scans
  
          jCarry = (BYTE)0;   // no carry to the first byte in the row
  
          for
          (
              iByte = 0L;
              iByte < cjScanSrc;
              iByte++, pjS += cy, pjD++
          )
          {
              *pjD = (BYTE)(*pjS | ((*pjS >> 1) | jCarry));
  
          // remember the rightmost bit and shift it to the leftmost position
  
              jCarry = (BYTE)(*pjS << 7);
          }
  
          if ((cxSrc & 7L) == 0L)
              *pjD = jCarry;
  
      // advance to the next scan of the src and dst
  
          pjSrc++;
          pjDst += cjScanDst;
      }
  }
  
  /******************************Public*Routine******************************\
  *
  * vCvtToItalicBmp
  *
  * History:
  *  06-Oct-1992 -by- Bodin Dresevic [BodinD]
  * Wrote it.
  \**************************************************************************/
  
  VOID vCvtToItalicBmp
  (
  GLYPHBITS *pgb,
  GLYPHDATA *pgd,
  PBYTE pjBitmap,     // pointer to the bitmap in *.fnt column format
  ULONG cxSrc,
  ULONG cy,
  ULONG yBaseLine
  )
  {
      ULONG cxDst = cxSrc + (ULONG)(cy - 1) / 2; // add correction for the
  
      PBYTE pjSrcScan, pjS;
      PBYTE pjDstScan, pjD;
  
      LONG  iScan,iByte;        // loop indices
  
  // number of bytes in one scan of the Dst or Src bitmaps. (dword aligned)
  
      ULONG cjScanDst = CJ_SCAN(cxDst);
  
      LONG  cjScanSrc = (LONG)CJ_SCAN(cxSrc);
      LONG  lShift;
      BYTE  jCarry;   // carry from shifting Src byte by lShift;
      LONG  cjEmpty;  // number of untouched bytes at the begining of the dest scans
  
  #ifdef DUMPCALL
      DbgPrint("\nVOID");
      DbgPrint("\nvCvtToItalicDIB(");
      DbgPrint("\n    GLYPHBITS    pgb       = %-#8lx",pgb      );
      DbgPrint("\n    GLYPHDATA    pgd       = %-#8lx",pgd      );
      DbgPrint("\n    PBYTE        pjBitmap  = %-#8lx",pjBitmap );
      DbgPrint("\n    ULONG        cxSrc     = %-#8lx",cxSrc    );
      DbgPrint("\n    ULONG        cy        = %-#8lx",cy       );
      DbgPrint("\n    ULONG        yBaseLine = %-#8lx",yBaseLine);
      DbgPrint("\n    )\n");
  #endif
  
  
  // this is character independent for BM fonts
  
      pgb->ptlOrigin.x = 0;
      pgb->ptlOrigin.y = -(LONG)yBaseLine;
  
      pgb->sizlBitmap.cx = cxDst;
      pgb->sizlBitmap.cy = cy;
  
  // init the loop over scans
  
      pjSrcScan = pjBitmap;
      pjDstScan = pgb->aj;
  
  // italicize bitmap row by row
  
      lShift = ((cy - 1) / 2) & (LONG)7;
      cjEmpty = ((cy - 1) / 2) >> 3;
  
  #ifdef DEBUGITAL
      DbgPrint("cy = %ld,  yBaseLine = %ld, lShift = %ld, cjEmpty = %ld\n",
                cy,  -pgldtSrc->ptlBmpOrigin.y, lShift, cjEmpty);
      DbgPrint("cxSrc = %ld, cxDst = %ld, cjScanSrc = %ld, cjScanDst = %ld\n",
                cxSrc, cxDst, cjScanSrc, cjScanDst);
      DbgPrint("cy = %ld,  cjScanSrc = %ld, \n",
                cy, cjScanSrc);
  
  #endif //  DEBUGITAL
  
  // if engine requested memory that is zero-ed out we would not have to do it
  // ourselves
  
      RtlZeroMemory(pjDstScan , cjScanDst * cy);
  
      for (iScan = 0L; iScan < (LONG)cy; iScan++)
      {
          if (lShift < 0L)
          {
              lShift = 7L;
              cjEmpty--;
          }
  
          ASSERTGDI(cjEmpty >= 0L, "cjEmpty\n");
  
      #ifdef DEBUGITALIC
          DbgPrint("iScan = %ld, lShift = %ld\n", iScan, lShift);
      #endif  // DEBUGITALIC
  
          pjS = pjSrcScan;
          pjD = pjDstScan + cjEmpty;
  
      // italicize individual scans
  
          jCarry = (BYTE)0;   // no carry to the first byte in the row
  
          for
          (
              iByte = 0L;
              iByte < cjScanSrc;
              iByte++, pjS += cy, pjD++
          )
          {
              *pjD = (BYTE)((*pjS >> lShift) | jCarry);
  
          // remember the lShift rightmost bits and move them over to the left
  
              jCarry = (BYTE)(*pjS << (8 - lShift));
          }
  
      // see if an extra bit in the destination has to be used to store info
  
          if ((LONG)((8 - (cxSrc & 7L)) & 7L) < lShift)
              *pjD = jCarry;
  
      // advance to the next scan
  
          pjSrcScan++;
          pjDstScan += cjScanDst;
  
      // decrease shift if switching to the next row (row = 2 scans)
  
          lShift -= (iScan & 1);
      }
  
      ASSERTGDI(lShift <= 0L, "vItalicizeBitmap: lShift > 0\n");
  }
  
  /******************************Public*Routine******************************\
  *
  * vCvtToBoldItalicBmp
  *
  * History:
  *  06-Oct-1992 -by- Bodin Dresevic [BodinD]
  * Wrote it.
  \**************************************************************************/
  
  VOID vCvtToBoldItalicBmp
  (
  GLYPHBITS *pgb,
  GLYPHDATA *pgd,
  PBYTE pjBitmap,     // pointer to the bitmap in *.fnt column format
  ULONG cxSrc,
  ULONG cy,
  ULONG yBaseLine
  )
  {
  // This is the length in pels for the destination for italicizing
  // which serves as a source for subsequent emboldening
  // This length is a length in pels of the "virtual"
  // italicized source that is to be emboldened.
  
      ULONG cxSrcItalic = cxSrc + (cy - 1) / 2;  // + slope of italic chars
  
  // length in pels of the true emboldened and italicized destination
  
      ULONG cxDst = cxSrcItalic + 1;  // + 1 for emboldening
  
      PBYTE pjSrcScan, pjS;
      PBYTE pjDstScan, pjD;
  
      LONG iScan,iByte;        // loop indices
  
  // number of bytes in one scan of the Dst or Src bitmaps. (dword aligned)
  
      ULONG cjScanDst = CJ_SCAN(cxDst);
      ULONG cjScanSrc = CJ_SCAN(cxSrc);
  
      LONG  lShift;   // shift used to italicize;
      BYTE  jCarry;   // carry from shifting Src byte by lShift;
      LONG  cjEmpty;  // number of untouched bytes at the begining of the dest scans
      BYTE  jSrcItalic;
      BYTE  jCarryBold;
  
  #ifdef DUMPCALL
      DbgPrint("\nVOID");
      DbgPrint("\nvCvtToBoldItalicDIB(");
      DbgPrint("\n    GLYPHBITS    pgb       = %-#8lx",pgb      );
      DbgPrint("\n    GLYPHDATA    pgd       = %-#8lx",pgd      );
      DbgPrint("\n    PBYTE        pjBitmap  = %-#8lx",pjBitmap );
      DbgPrint("\n    ULONG        cxSrc     = %-#8lx",cxSrc    );
      DbgPrint("\n    ULONG        cy        = %-#8lx",cy       );
      DbgPrint("\n    ULONG        yBaseLine = %-#8lx",yBaseLine);
      DbgPrint("\n    )\n");
  #endif
  
  
  // this is character independent for BM fonts
  
      pgb->ptlOrigin.x = 0;
      pgb->ptlOrigin.y = -(LONG)yBaseLine;
  
      pgb->sizlBitmap.cx = cxDst;
      pgb->sizlBitmap.cy = cy;
  
  // init the loop over scans
  
      pjSrcScan = pjBitmap;
      pjDstScan = pgb->aj;
  
  // embold and italicize bitmap row by row   (row = 2 scans)
  
      lShift = ((cy - 1) / 2) & (LONG)7;
      cjEmpty = ((cy - 1) / 2) >> 3;
  
  #ifdef DEBUGBOLDITAL
      DbgPrint("cy = %ld,  yBaseLine = %ld, lShift = %ld, cjEmpty = %ld\n",
                cy, -pgldtSrc->ptlBmpOrigin.y, lShift, cjEmpty);
      DbgPrint("cxSrc = %ld, cxDst = %ld, cjScanSrc = %ld, cjScanDst = %ld\n",
                cxSrc, cxDst, cjScanSrc, cjScanDst);
      DbgPrint("cy = %ld,  cjScanSrc = %ld\n",
                cy, cjScanSrc);
  
  #endif //  DEBUGBOLDITAL
  
  // if engine requested memory that is zero-ed out we would not have to do it
  // ourselves
  
      RtlZeroMemory(pjDstScan , cjScanDst * cy);
  
      for (iScan = 0L; iScan < (LONG)cy; iScan++)
      {
          if (lShift < 0L)
          {
              lShift = 7L;
              cjEmpty--;
          }
  
      #ifdef DEBUGBOLDITAL
          DbgPrint("iScan = %ld, lShift = %ld\n", iScan, lShift);
      #endif  // DEBUGBOLDITAL
  
          ASSERTGDI(cjEmpty >= 0L, "cjEmpty\n");
  
          pjS = pjSrcScan;
          pjD = pjDstScan + cjEmpty;
  
      // embolden individual scans
  
          jCarry = (BYTE)0;   // no carry to the first byte in the row
          jCarryBold = (BYTE)0;
  
          for
          (
              iByte = 0L;
              iByte < (LONG)cjScanSrc;
              iByte++, pjS += cy, pjD++
          )
          {
              jSrcItalic = (BYTE)((*pjS >> lShift) | jCarry);
              *pjD = (BYTE)(jSrcItalic | (jSrcItalic >> 1) | jCarryBold);
  
          // remember the lShift rightmost bits and move them over to the left
  
              jCarry = (BYTE)(*pjS << (8 - lShift));
              jCarryBold = (BYTE)(jSrcItalic << 7);
          }
  
      // see if an extra bit in the destination has to be used to store info
  
          if ((LONG)((8 - (cxSrc & 7L)) & 7L) < lShift)
          {
              jSrcItalic = jCarry;
              *pjD = (BYTE)(jSrcItalic | (jSrcItalic >> 1) | jCarryBold);
              jCarryBold = (BYTE)(jSrcItalic << 7);
  
              if ((cxSrcItalic & 7L) == 0L)
              {
                  pjD++;
                  *pjD = jCarryBold;
              }
  
          }
  
      // advance to the next scan
  
          pjSrcScan++;
          pjDstScan += cjScanDst;
  
      // change the value of the shift if doing the next row
  
          lShift -= (iScan & 1);
      }
  
  
      ASSERTGDI(lShift <= 0L, "vBoldItalicizeBitmap: lShift > 0\n");
  }
  