示例#1
0
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:
        RIP("BMFD!BAD SIM FLAG\n");


    }

    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
}
示例#2
0
ULONG cjTestFdDeviceMetrics( FONTFILE *pff, FD_DEVICEMETRICS *pdevm)
{
// compute the accelerator flags for this font

    IFIMETRICS *pifi = pff->pifi;

    pdevm->flRealizedType =
        (
        FDM_TYPE_BM_SIDE_CONST          |  // all char bitmaps have the same cy
        FDM_TYPE_MAXEXT_EQUAL_BM_SIDE   |
        FDM_TYPE_CHAR_INC_EQUAL_BM_BASE |
        FDM_TYPE_CONST_BEARINGS         |  // ac spaces for all chars the same,  not 0 necessarilly
        FDM_TYPE_ZERO_BEARINGS
        );

// the direction unit vectors for all ANSI bitmap fonts are the
// same. We do not even have to look to the font context:

    vLToE(&pdevm->pteBase.x, 1L);
    vLToE(&pdevm->pteBase.y, 0L);
    vLToE(&pdevm->pteSide.x, 0L);
    vLToE(&pdevm->pteSide.y, -1L);    // y axis points down

// Set the constant increment for a fixed pitch font.  Don't forget to
// take into account a bold simulation!

    pdevm->lD = 0;

// for a bitmap font there is no difference between notional and device
// coords, so that the Ascender and Descender can be copied directly
// from PIFIMETRICS where these two numbers are in notional coords

    pdevm->fxMaxAscender  = LTOFX((LONG)pifi->fwdWinAscender);
    pdevm->fxMaxDescender = LTOFX((LONG)pifi->fwdWinDescender);

    pdevm->ptlUnderline1.x = 0L;
    pdevm->ptlUnderline1.y = - pifi->fwdUnderscorePosition;

    pdevm->ptlStrikeOut.y  = - pifi->fwdStrikeoutPosition;
    pdevm->ptlStrikeOut.x  = (LONG)pifi->fwdStrikeoutPosition / 2 ;

    pdevm->ptlULThickness.x = 0;
    pdevm->ptlULThickness.y = (LONG)pifi->fwdUnderscoreSize;

    pdevm->ptlSOThickness.x = 0;
    pdevm->ptlSOThickness.y = (LONG)pifi->fwdStrikeoutSize;

// for a bitmap font there is no difference between notional and device
// coords, so that the Ascender and Descender can be copied directly
// from PIFIMETRICS where these two numbers are in notional coords

    pdevm->ptlUnderline1.x = 0L;
    pdevm->ptlUnderline1.y = - pifi->fwdUnderscorePosition;

    pdevm->ptlStrikeOut.y  = - pifi->fwdStrikeoutPosition;
    pdevm->ptlStrikeOut.x  = (LONG)pifi->fwdStrikeoutPosition / 2;

    pdevm->ptlULThickness.x = 0;
    pdevm->ptlULThickness.y = (LONG)pifi->fwdUnderscoreSize;

    pdevm->ptlSOThickness.x = 0;
    pdevm->ptlSOThickness.y = (LONG)pifi->fwdStrikeoutSize;

    pdevm->cxMax = pifi->fwdMaxCharInc;
    pdevm->cyMax = pifi->fwdUnitsPerEm;
    pdevm->cjGlyphMax = CJ_BMP(pdevm->cxMax,pdevm->cyMax);

    return (sizeof(FD_DEVICEMETRICS));
}
示例#3
0
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;
    }
}
示例#4
0
文件: path.c 项目: Realhram/wdk81
BOOL
DoStrokePathByEnumingClipLines(
    PPDEV       pPDev,
    SURFOBJ     *pso,
    CLIPOBJ     *pco,
    PATHOBJ     *ppo,
    PPOINTL     pptlBrushOrg,
    BRUSHOBJ    *pbo,
    ROP4        rop4,
    LINEATTRS   *plineattrs
    )

/*++

Routine Description:

    Strokes a path through a complex clipping region by utilizing the
    engine helper functions. This is done because there is no way to
    fail a DrvStrokePath and have it come back in any simpler format by
    the NT graphics engine. In general, we can fail DrvXXX calls and the
    NT graphic engine will simply the object to draw, then call back into
    the driver. Stroking a path however cannot be simplified any more, so
    the best we can hope for is having the PATHOBJ converted to straight
    line segments (removing BEZIERS if present). We then must stroke the
    path ourselves, using the provided EngXXX helpers.
    Since helper functions exist that allow us to to enumerate the
    portions of a path as CLIPLINE segments that fall within the
    clipping region, we do that here, thus stroking the segments that lie
    inside of the passed CLIPOBJ.


Arguments:

    pPDev            Pointer to the current PDEV

    pso              SURFOBJ to write to

    pco              CLIPOBJ to use when enuming paths

    ppo              PATHOBJ to stroke through clip path

    pptlBrushOrg     BRUSH origin

    pbo              BRUSH to stroke with

    rop4             ROP4 to use

    plineattrs       LINEATTRS structure that describes the styling for the line



Return Value:

    TRUE if sucessful FALSE if failed, If the path we are asked to stroke
          contains BEZIERS, this function will fail in order to allow the
          Engine to break the path down to line segments.

Author:


    2/01/94  JB

Revision History:


--*/

{
    PLOT_CLIPLINE   PlotClipLine;
    CLIPLINE        *pCurClipLine;
    RUN             *pCurRun;
    POINTFIX        ptsfx[2];
    POINTL          ptlCur;
    FIX             iStartInFX;
    FIX             iStopInFX;
    LONG            dx;
    LONG            dy;
    LONG            i;
    BOOL            bMore;
    BOOL            bXordered;
    BOOL            bFlipX;
    BOOL            bFlipY;


    //
    // First check for Beziers and if we have them fail the call since we
    // want straight line segments to stroke, with the appropriate style
    //

    if (ppo->fl & PO_BEZIERS) {

        PLOTDBG(DBG_STROKECLIPLINES,
                ("DoStrokePathByEnumingClipLines:Path had BEZ returning FALSE"));
        return(FALSE);
    }

    PLOTDBG(DBG_STROKECLIPLINES,
            ("DoStrokeByEnumingClipLines: NO CLIPOBJ %p",
                  (pco != NULL) ,
                  (LONG_PTR)pco));

    PLOTDBG(DBG_STROKECLIPLINES, 
            ("DoStrokeByEnumingClipLines: CLIPOBJ is TRIVIAL (%lx)",
                  (pco->iDComplexity != DC_TRIVIAL) ,
                  (LONG)pco->iDComplexity ));

    //
    // Send out the line attributes , so the residue will be calculated
    // correctly
    //

    DoSetupOfStrokeAttributes(pPDev, pptlBrushOrg, pbo, rop4, NULL);

    //
    // Initiate enumeration of the CLIPLINES by calling the Engine helper
    //

    PATHOBJ_vEnumStartClipLines(ppo, pco, pso, plineattrs);

    //
    // Start a loop to enum through all the available CLIPLINE structures
    //

    pCurClipLine = (CLIPLINE *)&PlotClipLine;

    do {

        //
        // Get the first batch of CLIPLINE structures then go to work on them
        //

        bMore = PATHOBJ_bEnumClipLines(ppo, sizeof(PlotClipLine), pCurClipLine);

        //
        // Calculate dx and dy in order to determine if the line is Xordered or
        // Yordered this is needed because of the way the engine passes us RUNS
        // if dx > dy then the line is said to be Xordered and thus any given
        // RUN iStart and iStop values is a projection on the x axis. Given this
        // informatino we can calculate the adjoining Y coordinate and draw the
        // line appropriately.
        //

        dx = pCurClipLine->ptfxB.x - pCurClipLine->ptfxA.x;
        dy = pCurClipLine->ptfxB.y - pCurClipLine->ptfxA.y;



        if ( bFlipX = (dx < 0 )) {

            dx = -dx;
        }

        if ( bFlipY = (dy < 0 )) {

            dy = -dy;
        }


        //
        // Now calculate if the line is x ordered or y ordered
        //

        bXordered = (dx >= dy);

        PLOTDBG(DBG_STROKECLIPLINES,
                   ("DoStrokePathByEnumingClipLines:Compute ClipLine runs=%u, xordered %d",
                   pCurClipLine->c, bXordered ));

        //
        // Enum through all the given RUNS drawing with the pen down between any
        // iStart and iStop value in each RUN
        //

        for (i = 0, pCurRun = &(pCurClipLine->arun[0]);
             i < (LONG)pCurClipLine->c;
             i++, pCurRun++) {


            //
            // The value of iStart and iStop are always positive!! so
            // we must handle it ourselves, so the correct thing happens
            //

            iStartInFX = LTOFX(pCurRun->iStart);
            iStopInFX  = LTOFX(pCurRun->iStop);


            if (bFlipX ) {

                ptsfx[0].x = -iStartInFX;
                ptsfx[1].x = -iStopInFX;

            } else {

                ptsfx[0].x = iStartInFX;
                ptsfx[1].x = iStopInFX;
            }

            if (bFlipY ) {

                ptsfx[0].y = -iStartInFX;
                ptsfx[1].y = -iStopInFX;

            } else {

                ptsfx[0].y = iStartInFX;
                ptsfx[1].y = iStopInFX;
            }


            //
            // We must output the correct line attributes structure with the
            // correct calculated residue in order for this to work correctly
            //

            HandleLineAttributes(pPDev,
                                 plineattrs,
                                 &pCurClipLine->lStyleState,
                                 pCurRun->iStart);



            //
            // The calculations for the opposing coordinate varies based on the
            // ordering of the line. If the line is Xordered we calculate the
            // Y value, if itsYordered we calculate the X value. We do this
            // in order to determine the correct target coordinate. Since the
            // RUN is given to us as START and STOP, we must manually determine
            // what coordinate this represents inside the device coordinate
            // space. If the RUN is xordered, the x-coordinate is correct, and
            // the y-coordinate must be projected based on the ratio.
            //

            if (bXordered) {

                ptsfx[0].x +=  pCurClipLine->ptfxA.x;
                ptsfx[0].y =   MulDiv( ptsfx[0].y, dy, dx) +
                                                        pCurClipLine->ptfxA.y;
                ptsfx[1].x +=  pCurClipLine->ptfxA.x;
                ptsfx[1].y =   MulDiv( ptsfx[1].y, dy, dx) +
                                                        pCurClipLine->ptfxA.y;

            } else {

                ptsfx[0].x =   MulDiv(ptsfx[0].x, dx, dy) +
                                                        pCurClipLine->ptfxA.x;
                ptsfx[0].y +=  pCurClipLine->ptfxA.y;
                ptsfx[1].x =   MulDiv(ptsfx[1].x, dx, dy) +
                                                        pCurClipLine->ptfxA.x;
                ptsfx[1].y +=  pCurClipLine->ptfxA.y;
            }


            //
            // Do PE with pen up first, in order to move to the starting
            // position.
            //

            OutputString(pPDev, "PE<");

            if (!i) {

                //
                // If we are at first point then output that now.
                //

                ptlCur.x =
                ptlCur.y = 0;

                OutputString(pPDev, "=");
            }


            //
            // Stroke the segment with the pen down.
            //

            OutputXYParams(pPDev,
                           (PPOINTL)ptsfx,
                           (PPOINTL)NULL,
                           (PPOINTL)&ptlCur,
                           (UINT)2,
                           (UINT)1,
                           'F');

            OutputString(pPDev, ";");
        }

    } while (bMore);  // While we need to enum again..

    return(TRUE);
}