|
|
/******************************Module*Header*******************************\
* Module Name: textddi.cxx * * EngTextOut text drawing to DIBs * * Copyright (c) 1994-1999 Microsoft Corporation \**************************************************************************/
#include "precomp.hxx"
VOID vRectBlt(PBYTE, ULONG, LONG, LONG, LONG, LONG); VOID vRectBlt4(BYTE*,ULONG, LONG, LONG, LONG, LONG); VOID vRectBlt8(BYTE*,ULONG, LONG, LONG, LONG, LONG);
class FRINGERECT { private: SURFACE *pSurf; PVOID pvBits; // see comment [1] below
CLIPOBJ *pco; BRUSHOBJ *pboOpaque; int crcl; // Count of fringe rectangles to do.
RECTL arcl[4];
public: FRINGERECT(SURFACE *pSurf1,CLIPOBJ *pco1,BRUSHOBJ *pboOpaque1) { pSurf = pSurf1;
if (pSurf1->iType() == STYPE_BITMAP) pvBits = pSurf1->pvBits(); else pvBits = NULL;
pco = pco1; pboOpaque = pboOpaque1; crcl = 0; }
~FRINGERECT() { //
// We just assume the Rop is P according to the DDI.
//
if (pvBits) { while (--crcl >= 0) { vDIBSolidBlt( pSurf , &arcl[crcl] , pco , pboOpaque->iSolidColor, FALSE ); } } else { // this section was put in to support AntiAliased
// text. It is possible that for the case of
// antialiased text EngTextOut could be asked to
// render to a device managed surface. In that
// case, we use the device's BitBlt function to
// render the rectangles
POINTL ptlBrush = {0,0}; // it does not matter, it is solid color always
RECTL *prcl; SURFOBJ *pso = pSurf->pSurfobj(); PFN_DrvBitBlt pFnBitBlt = pSurf->pfnBitBlt();
for (prcl = arcl; prcl < arcl + crcl; prcl++) { (*(pFnBitBlt))( pso , // psoTrg
0 , // psoSrc
0 , // psoMask
pco , // pco
0 , // pxlo
prcl , // prclTrg
0 , // pptlSrc
0 , // pptlMask
pboOpaque , // pbo
&ptlBrush , // pptlBrush
0x0000f0f0 // rop4
); } } }
VOID vAddRect(LONG left, LONG top, LONG right, LONG bottom) { arcl[crcl].left = left; arcl[crcl].top = top; arcl[crcl].right = right; arcl[crcl].bottom = bottom; crcl++; } };
/***********************************************************************
* [1] * * * * Before GDI provided support for antialiased text it would * * not have been possible to have a surface without a pointer * * to the DIB bits. However, in the case of antialiased text * * it is possible that we reached here by way of GreExtTextOutW() * * ( this case is signaled by pSurf->pdcoAA != 0 ). In this * * case, the original surface of the device may not be accessible * * by GDI. This case would be indicated by a zero value for * * pvBits. You might worry that this means that we cannot take * * care of the background rectangles. But this is not the case! * * The background rectangle will be taken care of by GreExtTextOutW. * * * ***********************************************************************/
#define SO_MASK \
( \ SO_FLAG_DEFAULT_PLACEMENT | \ SO_ZERO_BEARINGS | \ SO_CHAR_INC_EQUAL_BM_BASE | \ SO_MAXEXT_EQUAL_BM_SIDE \ )
#define TEXT_BUFFER_SIZE 1024
#define KERNEL_ALLOC_SIZE 65536
//
// accelerator masks for four canonical directions of
// writing (multiples of 90 degrees)
//
#define SO_LTOR (SO_MASK | SO_HORIZONTAL)
#define SO_RTOL (SO_LTOR | SO_REVERSED)
#define SO_TTOB (SO_MASK | SO_VERTICAL)
#define SO_BTOT (SO_TTOB | SO_REVERSED)
//
// Glyph copy Declarations
//
typedef VOID (*PFN_MASTERTEXTTYPE)(PGLYPHPOS,ULONG,PUCHAR,ULONG,ULONG,ULONG,ULONG);
//
// Temp buffer expansion Declarations
//
typedef VOID (*PFN_TEXTSRCCPY)( BYTE*,LONG,LONG,BYTE*,LONG,LONG,LONG,LONG,ULONG,ULONG,SURFACE*);
VOID vExpandAndCopyText( SURFACE *, FONTOBJ * , GLYPHPOS *, ULONG , PBYTE, ULONG, ULONG, SURFACE *, SURFACE *, RECTL *, RECTL *, INT, INT, ULONG, RECTL *, RECTL *, ULONG, BRUSHOBJ *, POINTL * );
extern "C" {
VOID vFastText( GLYPHPOS *, ULONG , PBYTE, ULONG, ULONG, SURFOBJ *, RECTL *, RECTL *, INT, INT, ULONG, RECTL *, RECTL * );
VOID vSrcTranCopyError( BYTE*,LONG,LONG,BYTE*,LONG,LONG,LONG,LONG,ULONG,ULONG,SURFACE*);
VOID vSrcTranCopyS1D1( BYTE*,LONG,LONG,BYTE*,LONG,LONG,LONG,LONG,ULONG,ULONG,SURFACE*); VOID vSrcTranCopyS1D4( BYTE*,LONG,LONG,BYTE*,LONG,LONG,LONG,LONG,ULONG,ULONG,SURFACE*); VOID vSrcTranCopyS1D8( BYTE*,LONG,LONG,BYTE*,LONG,LONG,LONG,LONG,ULONG,ULONG,SURFACE*); VOID vSrcTranCopyS1D16( BYTE*,LONG,LONG,BYTE*,LONG,LONG,LONG,LONG,ULONG,ULONG,SURFACE*); VOID vSrcTranCopyS1D24( BYTE*,LONG,LONG,BYTE*,LONG,LONG,LONG,LONG,ULONG,ULONG,SURFACE*); VOID vSrcTranCopyS1D32( BYTE*,LONG,LONG,BYTE*,LONG,LONG,LONG,LONG,ULONG,ULONG,SURFACE*);
VOID vSrcOpaqCopyS1D1( BYTE*,LONG,LONG,BYTE*,LONG,LONG,LONG,LONG,ULONG,ULONG,SURFACE*); VOID vSrcOpaqCopyS1D4( BYTE*,LONG,LONG,BYTE*,LONG,LONG,LONG,LONG,ULONG,ULONG,SURFACE*); VOID vSrcOpaqCopyS1D8( BYTE*,LONG,LONG,BYTE*,LONG,LONG,LONG,LONG,ULONG,ULONG,SURFACE*); VOID vSrcOpaqCopyS1D8_64(BYTE*,LONG,LONG,BYTE*,LONG,LONG,LONG,LONG,ULONG,ULONG,SURFACE*); VOID vSrcOpaqCopyS1D32( BYTE*,LONG,LONG,BYTE*,LONG,LONG,LONG,LONG,ULONG,ULONG,SURFACE*); VOID vSrcOpaqCopyS1D16( BYTE*,LONG,LONG,BYTE*,LONG,LONG,LONG,LONG,ULONG,ULONG,SURFACE*); VOID vSrcOpaqCopyS1D24( BYTE*,LONG,LONG,BYTE*,LONG,LONG,LONG,LONG,ULONG,ULONG,SURFACE*);
VOID vSrcTranCopyS4D16( BYTE*,LONG,LONG,BYTE*,LONG,LONG,LONG,LONG,ULONG,ULONG,SURFACE*); VOID vSrcTranCopyS4D24( BYTE*,LONG,LONG,BYTE*,LONG,LONG,LONG,LONG,ULONG,ULONG,SURFACE*); VOID vSrcTranCopyS4D32( BYTE*,LONG,LONG,BYTE*,LONG,LONG,LONG,LONG,ULONG,ULONG,SURFACE*);
VOID vSrcOpaqCopyS4D16( BYTE*,LONG,LONG,BYTE*,LONG,LONG,LONG,LONG,ULONG,ULONG,SURFACE*); VOID vSrcOpaqCopyS4D24( BYTE*,LONG,LONG,BYTE*,LONG,LONG,LONG,LONG,ULONG,ULONG,SURFACE*); VOID vSrcOpaqCopyS4D32( BYTE*,LONG,LONG,BYTE*,LONG,LONG,LONG,LONG,ULONG,ULONG,SURFACE*);
VOID vSrcOpaqCopyS8D16( BYTE*,LONG,LONG,BYTE*,LONG,LONG,LONG,LONG,ULONG,ULONG,SURFACE*); VOID vSrcOpaqCopyS8D24( BYTE*,LONG,LONG,BYTE*,LONG,LONG,LONG,LONG,ULONG,ULONG,SURFACE*); VOID vSrcOpaqCopyS8D32( BYTE*,LONG,LONG,BYTE*,LONG,LONG,LONG,LONG,ULONG,ULONG,SURFACE*);
VOID vSrcTranCopyS8D16( BYTE*,LONG,LONG,BYTE*,LONG,LONG,LONG,LONG,ULONG,ULONG,SURFACE*); VOID vSrcTranCopyS8D24( BYTE*,LONG,LONG,BYTE*,LONG,LONG,LONG,LONG,ULONG,ULONG,SURFACE*); VOID vSrcTranCopyS8D32( BYTE*,LONG,LONG,BYTE*,LONG,LONG,LONG,LONG,ULONG,ULONG,SURFACE*);
VOID draw_f_tb_no_to_temp_start(PGLYPHPOS,ULONG,PUCHAR,ULONG,ULONG,ULONG,ULONG); VOID draw_nf_tb_no_to_temp_start(PGLYPHPOS,ULONG,PUCHAR,ULONG,ULONG,ULONG,ULONG); VOID draw_f_ntb_o_to_temp_start(PGLYPHPOS,ULONG,PUCHAR,ULONG,ULONG,ULONG,ULONG); VOID draw_nf_ntb_o_to_temp_start(PGLYPHPOS,ULONG,PUCHAR,ULONG,ULONG,ULONG,ULONG);
// grayscale routines
VOID draw_gray_nf_ntb_o_to_temp_start(PGLYPHPOS,ULONG,PUCHAR,ULONG,ULONG,ULONG,ULONG); VOID draw_gray_f_ntb_o_to_temp_start(PGLYPHPOS,ULONG,PUCHAR,ULONG,ULONG,ULONG,ULONG);
// cleartype routines
VOID draw_clrt_nf_ntb_o_to_temp_start(PGLYPHPOS,ULONG,PUCHAR,ULONG,ULONG,ULONG,ULONG); VOID draw_clrt_f_ntb_o_to_temp_start(PGLYPHPOS,ULONG,PUCHAR,ULONG,ULONG,ULONG,ULONG);
ULONG TextExpStartMask[] = {0xFFFFFFFF, 0xFFFFFF00, 0xFFFF0000, 0xFF000000 };
ULONG TextExpEndMask[] = {0xFFFFFFFF, 0x000000FF, 0x0000FFFF, 0x00FFFFFF };
LONG TextExpStartByteCount[] = {0,3,2,1};
}
#define NO_TARGET 0
#define FIFTEEN_BITS ((1 << 15)-1)
#if DBG
void vDump8bppDIB(SURFMEM& surfmem); #endif
/******************************Public*Routine******************************\
* Routine Name: * * EngTextOut * * Routine Description: * * This routine blts glyphs to a DIB. * * Arguments: * * pso - Surface object for destination surface * pstro - String object for enumerating glyphs * pfo - Font object of glyphs * pco - Clip object * prclExtra - Extra rectangles to draw with text * prclOpaque - Opaque rectangle * pboFore - Foreground brush * pboOpaque - Background brush * pptlOrg - Brush starting origin * mix - Equal to SRCCOPY for now * * Return Value: * * BOOL Status * \**************************************************************************/ #define ETO_GRAY 8
#define ETO_DEVICE_SURFACE 16
#define ETO_CLEARTYPE_X 32
#define ETO_CLEARTYPE_Y 64
VOID EngTextOutBitBlt( SURFACE *pSurf, FONTOBJ *pfo, ULONG fDrawFlags, SURFOBJ *psoSrc, SURFOBJ *psoMsk, CLIPOBJ *pco, XLATEOBJ *plxo, RECTL *prclTrg, POINTL *pptlSrc, POINTL *pptlMsk, BRUSHOBJ *pbo, POINTL *pptlBrush, ROP4 rop4 ) {
if (fDrawFlags & ETO_DEVICE_SURFACE) { RFONTTMPOBJ rfo(PFO_TO_PRF(pfo));
TextOutBitBlt(pSurf, rfo, psoSrc, psoMsk, pco, plxo, prclTrg, pptlSrc, pptlMsk, pbo, pptlBrush, rop4); } else { EngBitBlt(pSurf->pSurfobj(), psoSrc, psoMsk, pco, plxo, prclTrg, pptlSrc, pptlMsk, pbo, pptlBrush, rop4); } }
BOOL EngTextOut( SURFOBJ *pso, STROBJ *pstro, FONTOBJ *pfo, CLIPOBJ *pco, PRECTL prclExtra, PRECTL prclOpaque, BRUSHOBJ *pboFore, BRUSHOBJ *pboOpaque, PPOINTL pptlOrg, MIX mix ) { ULONG iClip; // Clip object's complexity
BOOL bMore; // Flag for clip enumeration
CLIPENUMRECT txen; // Clip enumeration object
GLYPHPOS *pgp; // pointer to the 1st glyph
BOOL bMoreGlyphs; // Glyph enumeration flag
ULONG cGlyph; // number of glyphs in one batch
ULONG iSolidForeColor; // Solid foreground color
ULONG iSolidBkColor; // Solid background color
FLONG flStr = 0; // Accelator flag for DrvTextOut()
FLONG flOption = 0; // Accelator flag for pfnBlt
RECTL arclTmp[4]; // Temp storage for portions of
// opaquing rect
RECTL *prclClip; // ptr to list of clip rectangles
ULONG ulBufferWidthInBytes = 0; ULONG ulBufferHeight; ULONG ulBufferBytes; BOOL bTextPerfectFit; ULONG fDrawFlags = 0; BYTE *pjTempBuffer; BOOL bTempAlloc; BOOL bKernelAlloc; BYTE szTextBuffer[TEXT_BUFFER_SIZE]; ULONG Native64BitAccess = TRUE; ULONG iTrgType = 0; SURFACE *pSurfDraw; RECTL rcScreen; // intersection of Screen & DIB
// in screen coordinates
RECTL rcDIB; // intersection of Screen & DIB
// in DIB coordinates
XDCOBJ *pdco = 0; // equal to pSurf->pdcoAA
// this is non-zero in the case
// where the text in anti-aliased
// and the device does not support
// antialiased text directly. In such
// a case we must be able to pass
// information about the original
// deivce surface
SURFACE *pSurfDevice = 0; // pointer to original device surface
// this is obtained via pdco
// This hack, due to filtering needs to be put in textgdi.cxx
// filtering leeks color one pixel to the left and one pixel to the right
ASSERTGDI(pso != (SURFOBJ *) NULL, "ERROR: EngTextOut Surface\n"); ASSERTGDI(pstro != (STROBJ *) NULL, "ERROR: EngTextOut String\n" ); ASSERTGDI(pfo != (FONTOBJ *) NULL, "ERROR: EngTextOut Font\n" );
// In order to support antialiasing text on devices that don't
// support antialiasing GDI will first render the text to
// a DIB then later copy the DIB to the original device surface.
// In such a case pso represents the DIB surface and mix
// contains a pointer to the original XDCOBJ which will
// be needed in order to interpret the colors corectly. The
// way that we recognize this situation is that
// pSurf->pdcoAA is non-zero
PSURFACE pSurf = SURFOBJ_TO_SURFACE(pso); pSurfDraw = pSurf;
if (pfo->flFontType & FO_GRAY16) { if ( pdco = pSurf->pdcoAA ) { ASSERTGDI(pdco->dctp() != DCTYPE_INFO, "dctp == DCTYPE_INFO\n");
pSurfDevice = pdco->pdc->ppdev()->pSurface;
} else { pSurfDevice = pSurf; }
if (pSurf->iType() != STYPE_BITMAP) { fDrawFlags |= ETO_DEVICE_SURFACE; } }
if ((pfo->flFontType & DEVICE_FONTTYPE) != 0) { WARNING("Attempting EngTextOut with Device Font\n"); return(FALSE); }
//
// Note that we don't synchronize with the device here (we do that in
// vExpandAndCopyText after doing a bunch of work not involving the
// frame buffer), but we do let the driver know we're going to be
// calling Synchronize soon via FLUSH, to get it to empty its DMA
// buffer.
//
// {
// PDEVOBJ po(pSurf->hdev());
// if (po.flGraphicsCaps2() & GCAPS2_SYNCFLUSH)
// {
// po.vSync(pso, NULL, DSS_FLUSH_EVENT);
// }
// }
iClip = (pco != NULL) ? pco->iDComplexity : DC_TRIVIAL;
iSolidForeColor = pboFore->iSolidColor;
//
// assume no opaque rectangle
//
iSolidBkColor = 0xFFFFFFFF;
//
// See if the temp buffer is big enough for the text; if not,
// try to allocate enough memory.
// Round up to the nearest dword multiple so that the alignment
// will stay constant when blt to the destination surface.
//
if(pfo->flFontType & FO_GRAY16) { if (pSurf->iFormat() == BMF_8BPP) { if (pboOpaque->iSolidColor == -1L) { RIP("EngTextOut Error attempting anti-aliased text\n" "at 8bpp with a transparent background.\n"); return(FALSE); } }
fDrawFlags |= ETO_GRAY;
if (pfo->flFontType & FO_CLEARTYPE_X) { //
// This is the case 8-bpp antialiased text
//
// The strategy is to create a 8-bpp buffer representing
// the entire string.
//
// The buffer shall be aligned with the destination. That
// is, 32-bit boundaries in the buffer correspond to 32
// bit boundaries in the destination surface and the text
// in the buffer has the same relative alignment as the
// destination. To do this, we bump boundaries of the buffer
// such that the left and right boundaries of the buffer
// land on 32-bit aligned postions. This is done in the
// following way. We note that a DWORD is 32 bits, this
// is enough information to specify 4 (8bpp) pixels. The
// number aligned DWORD's needed to surround the nibbles
// defining the text is calculated by finding the nearest
// multiple of 4 above and below the x-boundaries of the
// text. The difference between these two numbers is a
// count of DWORD's. Then since each DWORD is made up
// of 4 bytes, we multiply by 4 at the end to get a count
// of bytes.
//
// buffer width in bytes = 4 * (ceiling((right+1)/4) - floor(left/4))
//
fDrawFlags |= ETO_CLEARTYPE_X;
ulBufferWidthInBytes = ( ((pstro->rclBkGround.right + 4) >> 2) - ((pstro->rclBkGround.left ) >> 2) ) << 2;
} else if (pfo->flFontType & FO_CLEARTYPE_Y) { RIP("FO_CLEARTYPE_Y, not supported yet\n"); } else { //
// This is the case 4-bpp antialiased text
//
// The strategy is to create a 4-bpp buffer representing
// the entire string.
//
// The buffer shall be aligned with the destination. That
// is, 32-bit boundaries in the buffer correspond to 32
// bit boundaries in the destination surface and the text
// in the buffer has the same relative alignment as the
// destination. To do this, we bump boundaries of the buffer
// such that the left and right boundaries of the buffer
// land on 32-bit aligned postions. This is done in the
// following way. We note that a DWORD is 32 bits, this
// is enough information to specify 8 (4bpp) pixels. The
// number aligned DWORD's needed to surround the nibbles
// defining the text is calculated by finding the nearest
// multiple of 8 above and below the x-boundaries of the
// text. The difference between these two numbers is a
// count of DWORD's. Then since each DWORD is made up
// of 4 bytes, we multiply by 4 at the end to get a count
// of bytes.
//
// buffer width in bytes = 4 * (ceiling((right+1)/8) - floor(left/8))
//
ulBufferWidthInBytes = ( ((pstro->rclBkGround.right + 8) >> 3) - ((pstro->rclBkGround.left ) >> 3) ) << 2;
} } else { ulBufferWidthInBytes = ((((pstro->rclBkGround.right + 32) & ~31) - (pstro->rclBkGround.left & ~31)) >> 3); } ulBufferHeight = (ULONG)(pstro->rclBkGround.bottom - pstro->rclBkGround.top);
if ((ulBufferWidthInBytes > FIFTEEN_BITS) || (ulBufferHeight > FIFTEEN_BITS)) { //
// the math will have overflowed
//
return(FALSE); } ulBufferBytes = ulBufferWidthInBytes * ulBufferHeight;
if (ulBufferBytes <= TEXT_BUFFER_SIZE) { //
// The temp buffer on the stack is big enough, so we'll use it
//
pjTempBuffer = szTextBuffer; bTempAlloc = FALSE; } else { //
// The temp buffer isn't big enough, so we'll try to allocate
// enough memory
//
#if DBG
if (ulBufferBytes >= (PAGE_SIZE * 10000)) { WARNING("EngTextOut: temp buffer >= 10000 pages"); return(FALSE); }
#endif
bKernelAlloc = (ulBufferBytes < KERNEL_ALLOC_SIZE); if (bKernelAlloc) { pjTempBuffer = (BYTE*) PALLOCNOZ(ulBufferBytes, 'oteG'); } else { pjTempBuffer = (BYTE*) EngAllocUserMem(ulBufferBytes,'oteG'); }
if (pjTempBuffer == NULL) { return(FALSE); }
//
// Mark that we have to free the buffer when we're done
//
bTempAlloc = TRUE; }
//
// One way or another, we've found a buffer that's big enough; set up
// for accelerated text drawing
//
// Set fixed pitch, overlap, and top & bottom Y alignment flags
//
if ((!(pstro->flAccel & SO_HORIZONTAL)) || (pstro->flAccel & SO_REVERSED)) { ; } else { fDrawFlags |= ((pstro->ulCharInc != 0) |
( ( (pstro->flAccel & (SO_ZERO_BEARINGS | SO_FLAG_DEFAULT_PLACEMENT)) != (SO_ZERO_BEARINGS | SO_FLAG_DEFAULT_PLACEMENT) ) << 1 ) |
( ((pstro->flAccel & (SO_ZERO_BEARINGS | SO_FLAG_DEFAULT_PLACEMENT | SO_MAXEXT_EQUAL_BM_SIDE)) == (SO_ZERO_BEARINGS | SO_FLAG_DEFAULT_PLACEMENT | SO_MAXEXT_EQUAL_BM_SIDE) ) << 2 ) ); }
//
// Handle the opaque rectangle if given.
//
// If the background brush is a pattern brush or the foreground brush is
// a pattern brush (foreground pattern brush is not supported), we
// will output the whole rectangle now.
//
// Otherwise, we will compute the fringe opaque area outside the text
// rectangle and include the remaining rectangle in the text output.
// The fringe rectangles will be output last to reduce flickering when
// a string is "moved" continuously across the screen.
//
FRINGERECT fr(pSurf, pco, pboOpaque);
if (prclOpaque != (PRECTL) NULL) { //
// If we have a device managed surface then the pattern should be
// laid down with the device's BitBlt function
//
iSolidBkColor = pboOpaque->iSolidColor; if ((iSolidBkColor == 0xFFFFFFFF) || // Background brush is pattern.
(iSolidForeColor == 0xFFFFFFFF)) // Foreground brush is pattern.
{
//
// Output the whole rectangle.
//
EngTextOutBitBlt( pSurf, pfo, fDrawFlags, (SURFOBJ *) NULL, // Source surface.
(SURFOBJ *) NULL, // Mask surface.
pco, // Clip object.
NULL, // Palette translation object.
prclOpaque, // Destination rectangle.
(POINTL *) NULL, // Source origin.
(POINTL *) NULL, // Mask origin.
pboOpaque, // Realized opaque brush.
pptlOrg, // brush origin
0x0000f0f0 // PATCOPY
); } else { //
// Compute the four fringe rectangles.
//
// According to the DDI, the opaque rectangle,
// if given, always bounds the text to be drawn.
//
// (iClip == DC_RECT) added because display driver changes prclOpq
// after intersecting the original prclOpq, rclBkGrnd and rclClip
// iClip == DC_RECT if there is a clipping rectangle.
//
ASSERTGDI((iClip != DC_TRIVIAL) || ((ERECTL *) prclOpaque)->bContain(pstro->rclBkGround), "EngTextOut: opaque rectangle does not bound text background!");
if (pstro->rclBkGround.top > prclOpaque->top) { fr.vAddRect(prclOpaque->left, prclOpaque->top, prclOpaque->right, pstro->rclBkGround.top); }
if (pstro->rclBkGround.left > prclOpaque->left) { fr.vAddRect(prclOpaque->left, pstro->rclBkGround.top, pstro->rclBkGround.left, pstro->rclBkGround.bottom); }
if (pstro->rclBkGround.right < prclOpaque->right) { fr.vAddRect(pstro->rclBkGround.right, pstro->rclBkGround.top, prclOpaque->right, pstro->rclBkGround.bottom); }
if (pstro->rclBkGround.bottom < prclOpaque->bottom) { fr.vAddRect(prclOpaque->left, pstro->rclBkGround.bottom, prclOpaque->right, prclOpaque->bottom); } } }
//
// Draw the text into the temp buffer, and thence to the screen
//
//
// IF (a device surface) THEN BEGIN
// create a DIB;
// IF (allocation was not successful) THEN return(FAILURE);
// IF (transparent text) THEN
// copy the surface bits to the DIB;
// END
//
SURFMEM surfmem; DEVBITMAPINFO dbmi; if (fDrawFlags & ETO_DEVICE_SURFACE) { ASSERTGDI(fDrawFlags & ETO_GRAY, "Device surface but not antialiased text\n");
// Rectangles of interest (in screen coordinates)
//
// 1. screen
//
// left_s = 0
// top_s = 0
// right_s = pso->sizlBitmap.cx
// bottom_s = pso->sizlBitmap.cy
//
// 2. text
//
// left_t = prcl->left
// top_t = prcl->top
// right_t = prcl->right
// bottom_t = prcl->bottom
//
// 3. buffer
//
// left_b = left_t & ~7
// top_b = top_t
// right_b = (right_t + 7) & ~7
// bottom_b = bottom_t
//
// 4. dib
//
// left_d = left_b
// top_d = top_b
// right_d = right_t
// bottom_d = bottom_t
//
// The intersection of the screen and dib rectangles
// have screen coordinates
//
// 5. interesection of the screen and text rectangles
// (screen coordinates)
//
// left_st = max(left_t, left_s )
// top_st = max(top_t, top_s )
// right_st = min(right_t, right_s )
// bottom_st = min(bottom_t, bottom_s)
//
// 6. intersection of the screen and text coordinates
// (DIB coordinates)
//
// left_st' = left_st - left_d
// top_st' = top_st - top_d
// right_st' = right_st - left_d
// bottom_st' = bottom_st - top_d
//
// Make the DIB aligned with the buffer on the left
// and aligned with the text on the right
//
// Actually, I could have been less aggressive in allocating
// memory. There is actually no reason to allocate memory
// that is larger than the screen. However, if I did that
// I would have to watch for the end of the dib while I
// processed the glyphs which would slow things down.
//
long left = pstro->rclBkGround.left & ~7; // left of DIB (screen coordinates)
if (fDrawFlags & ETO_CLEARTYPE_X) left = pstro->rclBkGround.left & ~3;
long top = pstro->rclBkGround.top; // top of DIB (screen coordinates)
dbmi.iFormat = pSurf->iFormat(); dbmi.cxBitmap = pstro->rclBkGround.right - left; dbmi.cyBitmap = pstro->rclBkGround.bottom - top; dbmi.hpal = 0; dbmi.fl = BMF_TOPDOWN;
if (pSurf->bUMPD()) dbmi.fl |= UMPD_SURFACE;
if (!surfmem.bCreateDIB(&dbmi,0)) { WARNING("EngTextOut: surfmem.bCreateDIB failed\n"); if (bTempAlloc) { if (bKernelAlloc) VFREEMEM(pjTempBuffer); else EngFreeUserMem(pjTempBuffer); } return(FALSE); } pSurfDraw = surfmem.ps;
//
// Compute the source surface origin, taking into account multi-mon
// and negative offsets:
//
LONG xOrigin = 0; LONG yOrigin = 0;
PDEVOBJ pdoSrc(pSurf->hdev()); ASSERTGDI(pdoSrc.bValid(),"Invalid pdoSrc I\n");
if (pdoSrc.bPrimary(pSurf) && pdoSrc.bMetaDriver()) { xOrigin = pdoSrc.pptlOrigin()->x; yOrigin = pdoSrc.pptlOrigin()->y; }
//
// rcScreen = screen & text intersection (screen coordinates)
//
rcDIB = pstro->rclBkGround;
rcScreen.left = max(xOrigin, pstro->rclBkGround.left); rcScreen.top = max(yOrigin, pstro->rclBkGround.top ); rcScreen.right = min(xOrigin + pso->sizlBitmap.cx, pstro->rclBkGround.right ); rcScreen.bottom = min(yOrigin + pso->sizlBitmap.cy, pstro->rclBkGround.bottom);
//
// The DDI guarantees the driver that 'pco->rclBounds' is guaranteed
// to intersect with 'prclDst' on a DrvCopyBits call. Later on, we
// will use 'pco' and 'rcScreen' in a DrvCopyBits call, so check for
// no drawing here:
//
if ((iClip != DC_TRIVIAL) && !bIntersect(&rcScreen, &pco->rclBounds)) { if (bTempAlloc) { if (bKernelAlloc) VFREEMEM(pjTempBuffer); else EngFreeUserMem(pjTempBuffer); } return(TRUE); }
//
// rcDIB = screen & text intersection (DIB coordinates)
//
rcDIB = rcScreen; rcDIB.left -= left; rcDIB.top -= top; rcDIB.right -= left; rcDIB.bottom -= top;
if (iSolidBkColor == (ULONG) -1) { //
// background is transparent copy bits from surface to DIB
//
if (rcScreen.left < rcScreen.right && rcScreen.top < rcScreen.bottom) { (*PPFNGET(pdoSrc,CopyBits,pSurf->flags())) ( surfmem.pSurfobj(), pSurf->pSurfobj(), 0, &xloIdent, &rcDIB, (POINTL*) &rcScreen); } } }
//
// Some drivers do banking meaning they will call EngTextOut multiple times
// per TextOut call. Most of the time all the GLYPH positions in the STROBJ will
// be valid meaning it doesn't matter that you call STROBJ_vEnumStart. But if
// they aren't, it does matter. This is always true in the case of linked text out
// calls.
//
STROBJ_vEnumStart(pstro);
//
// clear buffer for opaque mode
//
if (iSolidBkColor != -1L) RtlFillMemoryUlong((ULONG*) pjTempBuffer, ulBufferBytes, 0);
do { //
// Get the next batch of glyphs
//
//
// clear buffer, transparent mode, we need to clean the buffer in the while loop to get the font linking
// with antialiazing work right
//
if (iSolidBkColor == -1L) RtlFillMemoryUlong((ULONG*) pjTempBuffer, ulBufferBytes, 0);
if (pstro->pgp != NULL) { //
// There's only the one batch of glyphs, so save ourselves a call
//
pgp = pstro->pgp; cGlyph = pstro->cGlyphs; bMoreGlyphs = FALSE; } else { bMoreGlyphs = STROBJ_bEnum(pstro,&cGlyph,&pgp); }
//
// No glyph, no work!
//
if (cGlyph) { arclTmp[0].left = LONG_MIN; arclTmp[0].top = LONG_MIN; arclTmp[0].right = LONG_MAX; arclTmp[0].bottom = LONG_MAX; arclTmp[1].bottom = 0; prclClip = &arclTmp[0];
{ switch (iClip) { case DC_RECT: arclTmp[0] = pco->rclBounds; // copy clip rect to arclTmp[0]
arclTmp[1].bottom = 0; // make arclTmp[1] a null rect
//
// falling through !
//
case DC_TRIVIAL: vExpandAndCopyText(pSurf, pfo, pgp, cGlyph, (PBYTE)pjTempBuffer, ulBufferWidthInBytes, pstro->ulCharInc, pSurfDraw, pSurfDevice, &pstro->rclBkGround, prclOpaque, iSolidForeColor, iSolidBkColor, fDrawFlags, prclClip, prclExtra, Native64BitAccess, pboFore, pptlOrg); break;
case DC_COMPLEX: prclClip = &txen.arcl[0];
CLIPOBJ_cEnumStart(pco, FALSE, CT_RECTANGLES, CD_ANY, 0);
do { bMore = CLIPOBJ_bEnum(pco, (ULONG) (sizeof(txen) - sizeof(RECT)), (PULONG) &txen);
txen.arcl[txen.c].bottom = 0; // terminate txen.arcl[]
// with a null rect
vExpandAndCopyText(pSurf, pfo, pgp, cGlyph, (PBYTE)pjTempBuffer, ulBufferWidthInBytes, pstro->ulCharInc, pSurfDraw, pSurfDevice, &pstro->rclBkGround, prclOpaque, iSolidForeColor, iSolidBkColor, fDrawFlags, prclClip, prclExtra, Native64BitAccess, pboFore, pptlOrg); } while (bMore); break; } } } } while (bMoreGlyphs);
if (fDrawFlags & ETO_DEVICE_SURFACE) { PDEVOBJ pdoSrc(pSurf->hdev()); ASSERTGDI(pdoSrc.bValid(), "Invalid pdoSrc II\n");
(*PPFNGET(pdoSrc,CopyBits,pSurf->flags())) ( pSurf->pSurfobj(), surfmem.pSurfobj(), pco, 0, &rcScreen, (POINTL*) &rcDIB); }
//
// Free up any memory we allocated for the temp buffer
//
if (bTempAlloc) {
if (bKernelAlloc) VFREEMEM(pjTempBuffer); else EngFreeUserMem(pjTempBuffer); }
return(TRUE); }
//
// lookup tables for character drawing and temp buffer expansion
//
#if !defined (_X86_)
PVOID MastertextTypeTabel[] = { draw_nf_ntb_o_to_temp_start, draw_f_ntb_o_to_temp_start, draw_nf_ntb_o_to_temp_start, draw_f_ntb_o_to_temp_start, draw_nf_tb_no_to_temp_start, draw_f_tb_no_to_temp_start, draw_nf_ntb_o_to_temp_start, draw_f_ntb_o_to_temp_start,
draw_gray_nf_ntb_o_to_temp_start, draw_gray_f_ntb_o_to_temp_start, draw_gray_nf_ntb_o_to_temp_start, draw_gray_f_ntb_o_to_temp_start, draw_gray_nf_ntb_o_to_temp_start, draw_gray_f_ntb_o_to_temp_start, draw_gray_nf_ntb_o_to_temp_start, draw_gray_f_ntb_o_to_temp_start }; #endif
//
// MIPS has separate code for 8bpp destination depending
// on whether the driver supports the GCAPS_64BITMEMACCESS flag.
// This is because on some MIPS systems, 64 bit memory accesses
// the video space are truncated to 32. These systems must use the
// 32 bit version of 8 bpp output.
//
// SrcCopyTextFunctionTable is an array of 32 pointers to functions
// takeing BYTE*,LONG,LONG,BYTE*,LONG,LONG,LONG,LONG,ULONG,ULONG,SURFACE*
// as arguments and returning a VOID.
#if !defined (_MIPS_)
VOID (*(SrcCopyTextFunctionTable[48])) (BYTE*,LONG,LONG,BYTE*,LONG,LONG,LONG,LONG,ULONG,ULONG,SURFACE*) = {
vSrcTranCopyError, // 0 opaque
vSrcOpaqCopyS1D1, // 1
vSrcOpaqCopyS1D4, // 2
vSrcOpaqCopyS1D8, // 3
vSrcOpaqCopyS1D16, // 4
vSrcOpaqCopyS1D24, // 5
vSrcOpaqCopyS1D32, // 6
vSrcTranCopyError, // 7
vSrcTranCopyError, // 8 transparent
vSrcTranCopyS1D1, // 9
vSrcTranCopyS1D4, // a
vSrcTranCopyS1D8, // b
vSrcTranCopyS1D16, // c
vSrcTranCopyS1D24, // d
vSrcTranCopyS1D32, // e
vSrcTranCopyError, // f
// gray pixels
vSrcTranCopyError, // 10 opaque
vSrcTranCopyError, // 11
vSrcTranCopyError, // 12
vSrcTranCopyError, // 13
vSrcOpaqCopyS4D16, // 14
vSrcOpaqCopyS4D24, // 15
vSrcOpaqCopyS4D32, // 16
vSrcTranCopyError, // 17
vSrcTranCopyError, // 18 transparent
vSrcTranCopyError, // 19
vSrcTranCopyError, // 1a
vSrcTranCopyError, // 1b
vSrcTranCopyS4D16, // 1c
vSrcTranCopyS4D24, // 1d
vSrcTranCopyS4D32, // 1e
vSrcTranCopyError, // 1f
// CLEARTYPE_X
vSrcTranCopyError, // 20 opaque
vSrcTranCopyError, // 21
vSrcTranCopyError, // 22
vSrcTranCopyError, // 23
vSrcOpaqCopyS8D16, // 24
vSrcOpaqCopyS8D24, // 25
vSrcOpaqCopyS8D32, // 26
vSrcTranCopyError, // 27
vSrcTranCopyError, // 28 transparent
vSrcTranCopyError, // 29
vSrcTranCopyError, // 2a
vSrcTranCopyError, // 2b
vSrcTranCopyS8D16, // 24
vSrcTranCopyS8D24, // 25
vSrcTranCopyS8D32, // 26
vSrcTranCopyError, // 2f
};
#else
VOID (*(SrcCopyTextFunctionTable[48])) (BYTE*,LONG,LONG,BYTE*,LONG,LONG,LONG,LONG,ULONG,ULONG,SURFACE*) = {
vSrcOpaqCopyS1D8, // 0 opaque
vSrcOpaqCopyS1D1, // 1
vSrcOpaqCopyS1D4, // 2
vSrcOpaqCopyS1D8_64, // 3
vSrcOpaqCopyS1D16, // 4
vSrcOpaqCopyS1D24, // 5
vSrcOpaqCopyS1D32, // 6
vSrcTranCopyError, // 7
vSrcTranCopyError, // 8 transparent
vSrcTranCopyS1D1, // 9
vSrcTranCopyS1D4, // a
vSrcTranCopyS1D8, // b
vSrcTranCopyS1D16, // c
vSrcTranCopyS1D24, // d
vSrcTranCopyS1D32, // e
vSrcTranCopyError, // f
// gray pixels
vSrcTranCopyError, // 10 opaque
vSrcTranCopyError, // 11
vSrcTranCopyError, // 12
vSrcTranCopyError, // 13
vSrcOpaqCopyS4D16, // 14
vSrcOpaqCopyS4D24, // 15
vSrcOpaqCopyS4D32, // 16
vSrcTranCopyError, // 17
vSrcTranCopyError, // 18 transparent
vSrcTranCopyError, // 19
vSrcTranCopyError, // 1a
vSrcTranCopyError, // 1b
vSrcTranCopyS4D16, // 1c
vSrcTranCopyS4D24, // 1d
vSrcTranCopyS4D32, // 1e
vSrcTranCopyError, // 1f
// CLEARTYPE_X
vSrcTranCopyError, // 20 opaque
vSrcTranCopyError, // 21
vSrcTranCopyError, // 22
vSrcTranCopyError, // 23
vSrcOpaqCopyS8D16, // 24
vSrcOpaqCopyS8D24, // 25
vSrcOpaqCopyS8D32, // 26
vSrcTranCopyError, // 27
vSrcTranCopyError, // 28 transparent
vSrcTranCopyError, // 29
vSrcTranCopyError, // 2a
vSrcTranCopyError, // 2b
vSrcTranCopyS8D16, // 2c
vSrcTranCopyS8D24, // 2d
vSrcTranCopyS8D32, // 2e
vSrcTranCopyError, // 2f
}; #endif
/******************************Public*Routine******************************\
* * Routine Name * * vExpandAndCopyText * * Routine Description: * * Break down glyph drawing into several classes, based on * pitch, alignment and overlap, and in this loop dispatch to * highly specialized glyph drawing routines based on width * and bit rotation. * * Arguments: * * pGlyphPos - Pointer to first in list of GLYPHPOS structs * cGlyph - Number of glyphs to draw * pjTempBuffer - temp 1BPP [4BPP] buffer to draw into * ulBufferWidthInBytes - Delta for temp buffer * ulCharInc - pstro->ulCharInc, increment for fixed pitch * pSurf - surface obj, for drawing on actual surface * pSurfDevice - surface object for original device * (for antialiased text on devices that * don't support antialiased text natively). * prclText - bounding rectangle on dest surface * prclOpaque - boundary of opaque rect * iSolidForeColor - foreground color when drawing on dest surface * iSolidBkColor - background color when drawing on dest surface * fDrawFlags - special flags to allow for table lookup of routines * prclClip - clipping rect * prclExtra - extra rects to draw * Native64BitAccess - can use 64 bit accesses * * Return Value: * * None * \**************************************************************************/
VOID vExpandAndCopyText( SURFACE* pSurface, FONTOBJ* pfo, GLYPHPOS *pGlyphPos, ULONG cGlyph, BYTE *pjTempBuffer, ULONG ulBufferWidthInBytes, ULONG ulCharInc, SURFACE *pSurf, SURFACE *pSurfDevice, RECTL *prclText, RECTL *prclOpaque, INT iSolidForeColor, INT iSolidBkColor, ULONG fDrawFlags, RECTL *prclClip, RECTL *prclExtra, ULONG Native64BitAccess, BRUSHOBJ *pboFore, POINTL *pptlOrg ) {
PFN_MASTERTEXTTYPE pfnMasterType; BLTINFO SrcCopyBltInfo; PFN_TEXTSRCCPY pfnTextSrcCopy; EXLATEOBJ exlo; XLATE *pxlo = NULL; RECTL *pCurrentRect; ULONG BufferAlign; ULONG BufferOffset; ULONG ulSrcCopyFlag; ULONG ulTempTop;
#if DBG
/**/void vDumpGrayBuffer(BYTE *, ULONG, RECTL*); #endif
GLYPHPOS *pGPosTmp = pGlyphPos;
//
// pGlyphPos->pgdf->pgb must not be NULL.
// But if there is printer a driver bug and GetGlyphMode() returns FO_HGLYPHS
// instead of FO_GLYPHBITS, then it can be NULL and crash system.
// To protect from this situation, vExpandAndCopyText() just return without copying
// in this case.
//
for(ULONG i=0; i<cGlyph; i++, pGPosTmp++){ if(pGPosTmp->pgdf->pgb == NULL){ WARNING("pGlyphPos->pgdf->pgb is NULL. Possibly GetGlyphMode() bug of Printer Driver\n"); return; } }
//
// XP bug #352368
// Due to bad design of LTOFX and FXToL, overflow will alway happen when >0x7ffffff or <0xf8000000
// At worst case, there can be big jump in the middle among the returned long values and will cause AV in vFastText
// To avoid this, if the difference of pGlyphPos between the first char and last char is too big
// We reject it.
//
if( !(fDrawFlags & 1) && cGlyph > 1){ pGPosTmp=pGlyphPos+(cGlyph-1); if((pGlyphPos->ptl.x - pGPosTmp->ptl.x) > 0x8000000 || (pGlyphPos->ptl.x - pGPosTmp->ptl.x) < -0x8000000 ){ WARNING("Big jump among pGlyphPos.ptl.x. Mustbe LToFx overflow"); return; } }
// UMPD NtGdiEngTextOut holding RFONT cache semaphore.
// vExpandAndCopyText might call back into user mode.
BOOL bSem = FALSE; ULONG fl = 0, numLinks = 0; BOOL aFaceLink[UMPD_MAX_FONTFACELINK], *pFaceLink = aFaceLink; //
// Release rfont semaphores, otherwise holding rfont semaphores can
// disable APC queue while calling to the user mode.
//
//
// WINBUG #214225 tessiew 10-27-2000 Blackcomb: re-visit the RFONT.hsemCache acquiring/releasing issue
// Need to revisit the font semaphore problem in Blackcomb
// It seems that a thread doesn't need to hold the font caching semaphore
// during the whole GreExtTextOutWLocked call.
//
PDEVOBJ po(pSurface->hdev()); RFONTTMPOBJ rfo(PFO_TO_PRF(pfo));
if (po.bValid() && po.bPrinter() && po.bUMPD() && rfo.bValid()) { bSem = UMPDReleaseRFONTSem(rfo, NULL, &fl, &numLinks, &pFaceLink); }
//
// save global params
//
ulTempTop = prclText->top;
//
// DWORD Align temp buffer to DST.
//
// For 1Bpp addresses, left[31:05] = DWORD Address
// left[04:03] = Byte in DWORD
// left[02:00] = Pixel in Byte
//
// To optimize 1bpp drawing, both buffers must be DWORD aligned,
// this makes the temp buffer starting point is left[04:00].
//
// This means that the glyph offset in the temporary buffer is xPos - left[31:05]
//
//
// BufferOffset = x-position of nearest pixel to the left of the text rectangle
// whose address is on a 32-bit boundary in the glyph source
// which is either monchrome (1bpp) or gray (4bpp). This
// is also the position of the first pixel position on
// a temporary DIB buffer provided for anti-aliased text
// simulation.
//
// BufferAlign = number of pixels the left portion of the text is
// offset to the right from BufferOffset
//
// prclText = BufferOffset + BufferAlign
//
// monochrome text
//
// BufferOffset = prclText->left & ~31
// BufferAlign = prclText->left & 31
//
// gray (4bpp) text
//
// BufferOffset = prclText->left & ~7
// BufferAlign = prclText->left & 7
//
// clear type 8bpp text
//
// BufferOffset = prclText->left & ~3
// BufferAlign = prclText->left & 3
//
#if DBG
if (gflFontDebug & DEBUG_AA) { if (fDrawFlags & ETO_GRAY) { GLYPHPOS *pgp, *pgpBad; DbgPrint( "vExpandAndCopyText(\n" " GLYPHPOS *pGlyphPos = %-#x\n" " ULONG cGlyph = %u\n" " BYTE *pjTempBuffer = %-#x\n" " ULONG ulBufferWidthInBytes = %u\n" " ULONG ulCharInc = %u\n" " SURFACE *pSurf = %-#x\n" " SURFACE *pSurfDevice = %-#x\n" , pGlyphPos , cGlyph , pjTempBuffer , ulBufferWidthInBytes , ulCharInc , pSurf , pSurfDevice ); DbgPrint( " RECTL *prclText = %-#x\n" " RECTL *prclOpaque = %-#x\n" " INT iSolidForeColor = %-#x\n" " INT iSolidBkColor = %-#x\n" , prclText , prclOpaque , iSolidForeColor , iSolidBkColor ); DbgPrint( " RECTL *prclClip = %-#x\n" " RECTL *prclExtra = %-#x\n" " ULONG Native64BitAccess = %-#x\n" , prclClip , prclExtra , Native64BitAccess ); DbgPrint( " ULONG fDrawFlags = %-#x\n" , fDrawFlags ); if (fDrawFlags & 1) { DbgPrint("\t\t\t\t\tETO_FIXED_PITCH\n"); } if (fDrawFlags & 2) { DbgPrint( "\t\t\t\t\tETO_NOT_DEFAULT\n" ); } if (fDrawFlags & ETO_GRAY) { DbgPrint("\t\t\t\t\tETO_GRAY\n"); } if (fDrawFlags & ETO_DEVICE_SURFACE) { DbgPrint("\t\t\t\t\tETO_DEVICE_SURFACE\n"); } DbgPrint(")\n"); DbgPrint("---\n"); pSurf->vDump(); if (pSurfDevice) pSurfDevice->vDump(); DbgBreakPoint(); } } #endif
//
// pSurfDevice is an argument given to the SrcTextCopy function
// It must be non-zero in order to get information about the
// device palette
//
if (!pSurfDevice) { pSurfDevice = pSurf; }
// This is a wasted calculation for the case of a device surface
// but what the heck, a branch costs too
BufferAlign = prclText->left & ((fDrawFlags & ETO_GRAY) ? ((fDrawFlags & ETO_CLEARTYPE_X) ? 3 : 7) : 31); BufferOffset = prclText->left - BufferAlign;
if(!(fDrawFlags & ETO_CLEARTYPE_X)) {
#if !defined (_X86_)
//
// select and jump to appropriate glyph dispatch
// routine
//
pfnMasterType = (PFN_MASTERTEXTTYPE)MastertextTypeTabel[ fDrawFlags & ~(ETO_DEVICE_SURFACE | ETO_CLEARTYPE_X) ]; pfnMasterType( pGlyphPos , cGlyph , pjTempBuffer , BufferOffset , ulBufferWidthInBytes , ulCharInc , ulTempTop );
#else
//
// call x86 version for glyph copy
//
vFastText( pGlyphPos, cGlyph, pjTempBuffer + ((prclText->left >> 3) & 3), ulBufferWidthInBytes, ulCharInc, pSurf->pSurfobj(), prclText, prclOpaque, iSolidForeColor, iSolidBkColor, fDrawFlags & ~(ETO_DEVICE_SURFACE | ETO_CLEARTYPE_X), prclClip, prclExtra ); #endif
} else // cleartype
{ PVOID MastertextClearTypeTable[] = { draw_clrt_nf_ntb_o_to_temp_start, draw_clrt_f_ntb_o_to_temp_start, };
pfnMasterType = (PFN_MASTERTEXTTYPE)MastertextClearTypeTable[fDrawFlags & 1];
pfnMasterType( pGlyphPos , cGlyph , pjTempBuffer , BufferOffset , ulBufferWidthInBytes , ulCharInc , ulTempTop ); }
//
// draw extra rects (if any)
//
if (prclExtra != (PRECTL) NULL) { //
// intersect extra rects with temp buffer, draw any
// that intersect
//
VOID (*pfn)(PBYTE, ULONG, LONG, LONG, LONG, LONG);
pfn = (fDrawFlags & ETO_GRAY) ? ((fDrawFlags & ETO_CLEARTYPE_X) ? vRectBlt8 : vRectBlt4) : vRectBlt;
while (prclExtra->left != prclExtra->right) {
LONG xleft, xright, ytop, ybottom;
xleft = max(prclExtra->left, prclText->left) - BufferOffset; xright = min(prclExtra->right, prclText->right) - BufferOffset; ytop = max(prclExtra->top, prclText->top) - prclText->top; ybottom = min(prclExtra->bottom, prclText->bottom) - prclText->top;
//
// Render the clipped 'extra' rectangle into the mono dib.
//
if (xleft < xright && ytop < ybottom) { (*pfn)(pjTempBuffer,ulBufferWidthInBytes, xleft, ytop, xright, ybottom); }
prclExtra++; } }
//
// draw/expand 1bpp temp buffer onto target surface
//
ASSERTGDI(pSurf->iFormat() > 0,"Error in DIB format"); ASSERTGDI(pSurf->iFormat() <= BMF_32BPP,"Error in DIB format");
ULONG iFormat = pSurf->iFormat();
#if defined (_MIPS_)
//
// special check for MIPS 64 bit opaque,
// set format to 0 (use 32 bit opaque routine)
//
if ( (iFormat == BMF_8BPP) && (!Native64BitAccess) && (iSolidBkColor != 0xFFFFFFFF) ) { iFormat = 0; }
#endif
//
// Get a pointer to the appropriate function
//
{ int i = iFormat; ASSERTGDI(i < 8, "bad index"); if (iSolidBkColor == -1L) { i += 8; // transparent background
}
if (ETO_GRAY & fDrawFlags) { i += 16; // anti-aliased text
if (ETO_CLEARTYPE_X & fDrawFlags) i += 16; } pfnTextSrcCopy = SrcCopyTextFunctionTable[i]; }
//
// blt each clip rectangle
//
for (pCurrentRect=prclClip; pCurrentRect->bottom; pCurrentRect++) { LONG Left = max(prclText->left , pCurrentRect->left ); LONG Right = min(prclText->right , pCurrentRect->right ); LONG Top = max(prclText->top , pCurrentRect->top ); LONG Bottom = min(prclText->bottom, pCurrentRect->bottom); ULONG dX = (ULONG) (Left - prclText->left); ULONG dY = (ULONG) (Top - prclText->top );
if (fDrawFlags & ETO_DEVICE_SURFACE) { // Left = position of first pixel relative to the left
// hand edge of the temporary 4bpp buffer
Left -= BufferOffset; Right -= BufferOffset; Top -= prclText->top; Bottom -= prclText->top;
#if DBG
if (gflFontDebug & DEBUG_AA) { DbgPrint( "*pCurrentRect = 0x%lx 0x%lx 0x%lx 0x%lx\n" "*prclText = 0x%lx 0x%lx 0x%lx 0x%lx\n" " intersection = 0x%lx 0x%lx 0x%lx 0x%lx\n" " BuffOffset BuffAlign = 0x%lx 0x%lx \n" " dX dY = 0x%lx 0x%lx \n" , pCurrentRect->left , pCurrentRect->top , pCurrentRect->right , pCurrentRect->bottom , prclText->left , prclText->top , prclText->right , prclText->bottom , Left , Top , Right , Bottom , BufferOffset, BufferAlign , dX,dY ); } #endif
} else { //
// Synchronize with the driver
//
PDEVOBJ poSurf(pSurf->hdev()); poSurf.vSync(pSurf->pSurfobj(), NULL, 0); }
if ((Left < Right) && (Top < Bottom)) { if (iSolidForeColor == 0xffffffff) { //
// Our (*pfnTextSrcCopy) routines can only expand solid
// colors, so if the foreground color is a dither we fall
// back to our slower MaskBlt support. We set the mask
// to the monochrome text bitmap and do a masked PatBlt
// using the dithered brush.
//
// Note that we've already laid down the opaquing rectangle,
// so this is now effectively a "transparent" textout
// operation.
//
ASSERTGDI(!(fDrawFlags & ETO_GRAY), "Can't do dithered anti-aliased text");
RECTL rclDst; SURFACE surfMask; POINTL ptlMask;
rclDst.left = Left; rclDst.top = Top; rclDst.right = Right; rclDst.bottom = Bottom;
surfMask.iFormat(BMF_1BPP); surfMask.iType(STYPE_BITMAP); surfMask.pvScan0(pjTempBuffer); surfMask.lDelta(ulBufferWidthInBytes); surfMask.sizl().cx = 8 * ulBufferWidthInBytes; surfMask.sizl().cy = prclText->bottom - prclText->top;
ptlMask.x = dX + BufferAlign; ptlMask.y = dY;
BltLnk(pSurf, NULL, &surfMask, NULL, NULL, &rclDst, NULL, &ptlMask, pboFore, pptlOrg, 0xaaf0); } else { // The brush is a solid color, so use our optimized monochrome
// solid color expansion routines.
__try { PBYTE pjSrc = (PBYTE)pjTempBuffer + dY * ulBufferWidthInBytes; PBYTE pjDst = (PBYTE)pSurf->pvScan0() + Top * pSurf->lDelta(); (*pfnTextSrcCopy)( pjSrc, BufferAlign + dX, ulBufferWidthInBytes, pjDst, Left, Right, pSurf->lDelta(), Bottom - Top, iSolidForeColor, iSolidBkColor, pSurfDevice ); } __except(EXCEPTION_EXECUTE_HANDLER) { WARNING("pfnTextSrcCopy: exception raised!!!"); } } } }
// acquire the font semaphore(s)
if (bSem) { UMPDAcquireRFONTSem(rfo, NULL, fl, numLinks, pFaceLink); if (pFaceLink && pFaceLink != aFaceLink) { VFREEMEM(pFaceLink); } } }
/******************************Public*Routine******************************\
* * Routine Name * * vSrcTranCopyS1D1 * * Routine Description: * * Transparent blt of 1BPP src to all destination format * src bits that are "1" are copied to the dest as foreground color, * src bits that are "0" are not copied * * Arguments: * * pjSrcIn - pointer to beginning of current scan line of src buffer * SrcLeft - left (starting) pixel in src rectangle * DeltaSrcIn - bytes from one src scan line to next * pjDstIn - pointer to beginning of current scan line of Dst buffer * DstLeft - left(first) dst pixel * DstRight - right(last) dst pixel * DeltaDstIn - bytes from one Dst scan line to next * cy - number of scan lines * uF - Foreground color * uB - Background color * pSurf - not used * * Return Value: * * None * \**************************************************************************/
#if !defined (_X86_)
VOID vSrcTranCopyS1D1( PBYTE pjSrcIn, LONG SrcLeft, LONG DeltaSrcIn, PBYTE pjDstIn, LONG DstLeft, LONG DstRight, LONG DeltaDstIn, LONG cy, ULONG uF, ULONG uB, SURFACE *pSurf )
{
//
// DWORD version
//
// if uF == 1 then Dst |= Src
//
// if uF == 0 then Dst &= ~Src
//
//
LONG cx = DstRight - DstLeft;
LONG lStartCase = SrcLeft; LONG lEndCase = SrcLeft + cx; ULONG uStartMask = (ULONG)~0; ULONG uEndMask = (ULONG)~0; LONG lEndOffset; LONG lSrcStride = DeltaSrcIn; LONG lDstStride = DeltaDstIn;
PBYTE pjSrc; PBYTE pjDst; PBYTE pjSrcEnd; PBYTE pjSrcEndY;
lStartCase = lStartCase & 0x1F; lEndCase = lEndCase & 0x1F;
//
// big endian masks
//
if (lStartCase) { uStartMask >>= lStartCase;
//
// convert to little
// // 0 1 2 3
ULONG u0 = uStartMask << 24; // 3 - - -
ULONG u1 = uStartMask >> 24; // - - - 0
ULONG u2 = (uStartMask >> 8) & 0xFF00; // - - 1 -
uStartMask = (uStartMask & 0xFF00) << 8; // - 2 - -
uStartMask |= u0 | u1 | u2;
}
if (lEndCase) {
uEndMask <<= (32 - lEndCase);
//
// convert to little
// // 0 1 2 3
ULONG u0 = uEndMask << 24; // 3 - - -
ULONG u1 = uEndMask >> 24; // - - - 0
ULONG u2 = (uEndMask >> 8) & 0xFF00; // - - 1 -
uEndMask = (uEndMask & 0xFF00) << 8; // - 2 - -
uEndMask |= u0 | u1 | u2; }
//
// calc starting and ending addresses (DWORD aligned)
//
pjDst = pjDstIn + ((DstLeft >> 5) << 2); pjSrc = pjSrcIn + ((SrcLeft >> 5) << 2); pjSrcEnd = pjSrcIn + (((SrcLeft+cx) >> 5) << 2);
// Sundown safe truncation
lEndOffset = (ULONG)((ULONG_PTR)pjSrcEnd - (ULONG_PTR)pjSrc);
pjSrcEndY = pjSrc + cy * lSrcStride;
if (uF) {
if (pjSrc != pjSrcEnd) {
//
// start and stop are not in same byte
//
lDstStride -= lEndOffset; lSrcStride -= lEndOffset;
do {
pjSrcEnd = pjSrc + lEndOffset;
if (lStartCase) { *(PULONG)pjDst |= *(PULONG)pjSrc & uStartMask; pjDst+=4; pjSrc+=4; }
while (pjSrc != pjSrcEnd) {
*(PULONG)pjDst |= *(PULONG)pjSrc; pjSrc +=4; pjDst +=4;
}
if (lEndCase) { *(PULONG)pjDst |= *(PULONG)pjSrc & uEndMask; }
pjSrc += lSrcStride; pjDst += lDstStride;
} while (pjSrc != pjSrcEndY);
} else {
//
// start and stop are in same byte
//
uStartMask &= uEndMask;
do {
*(PULONG)pjDst |= *(PULONG)pjSrc & uStartMask;
pjSrc += lSrcStride; pjDst += lDstStride;
} while (pjSrc != pjSrcEndY); }
} else {
//
// uF == 0, Dst &= ~Src
//
if (pjSrc != pjSrcEnd) {
//
// start and stop are not in same byte
//
lDstStride -= lEndOffset; lSrcStride -= lEndOffset;
do {
pjSrcEnd = pjSrc + lEndOffset;
if (lStartCase) { *(PULONG)pjDst &= ~(*(PULONG)pjSrc & uStartMask); pjDst+=4; pjSrc+=4; }
while (pjSrc != pjSrcEnd) {
*(PULONG)pjDst &= ~(*(PULONG)pjSrc); pjSrc +=4; pjDst +=4;
}
if (lEndCase) { *(PULONG)pjDst &= ~(*(PULONG)pjSrc & uEndMask); }
pjSrc += lSrcStride; pjDst += lDstStride;
} while (pjSrc != pjSrcEndY);
} else {
//
// start and stop are in same byte
//
uStartMask &= uEndMask;
do {
*(PULONG)pjDst &= ~(*(PULONG)pjSrc & uStartMask);
pjSrc += lSrcStride; pjDst += lDstStride;
} while (pjSrc != pjSrcEndY); } } }
#endif
/******************************Public*Routine******************************\
* * Routine Name * * vSrcTranCopyS1D4 * * Routine Description: * * Transparent blt of 1BPP src to all destination format * src bits that are "1" are copied to the dest as foreground color, * src bits that are "0" are not copied * * Arguments: * * pjSrcIn - pointer to beginning of current scan line of src buffer * SrcLeft - left (starting) pixel in src rectangle * DeltaSrcIn - bytes from one src scan line to next * pjDstIn - pointer to beginning of current scan line of Dst buffer * DstLeft - left(first) dst pixel * DstRight - right(last) dst pixel * DeltaDstIn - bytes from one Dst scan line to next * cy - number of scan lines * uF - Foreground color * uB - Background color * * Return Value: * * None * \**************************************************************************/ VOID vSrcTranCopyS1D4( PBYTE pjSrcIn, LONG SrcLeft, LONG DeltaSrcIn, PBYTE pjDstIn, LONG DstLeft, LONG DstRight, LONG DeltaDstIn, LONG cy, ULONG uF, ULONG uB, SURFACE *pSurf )
{ //
// Warning, noot optimized. It is not expected that 4 bit text
// will be handled by the negine
//
LONG cx = DstRight - DstLeft; BYTE jF = (BYTE)uF; BYTE jB = (BYTE)uB; BYTE TextExpMask[4] = {0x00,0x0f,0xf0,0xff};
//
// build byte of replicate foreground
//
BYTE Accum = jF | (jF << 4); LONG SrcRight = SrcLeft + cx; LONG lStartCase = SrcLeft & 0x07; LONG lEndCase = SrcRight & 0x07; PBYTE pjSrc = pjSrcIn + ((SrcLeft + 7) >> 3); PBYTE pjSrcEndY = pjSrc + cy * DeltaSrcIn; PBYTE pjSrcEnd; LONG lSrcStartOffset = (8 - lStartCase); LONG lSrcStride;
PBYTE pjDst;
BYTE jSrc; BYTE Mask;
if (lStartCase == 0) { lSrcStartOffset = 0; }
cx = cx - lSrcStartOffset - (SrcRight & 0x07);
if (cx > 0) {
LONG lDstStride = DeltaDstIn - (cx >> 1); lSrcStride = DeltaSrcIn - (cx >> 3);
pjDst = pjDstIn + ((DstLeft + lSrcStartOffset) >> 1);
do {
pjSrcEnd = pjSrc + (cx >> 3);
//
// aligned middle
//
do {
jSrc = *pjSrc;
Mask = TextExpMask[(jSrc & 0xC0) >> 6];
*pjDst = (*pjDst & ~Mask ) | (Accum & Mask);
Mask = TextExpMask[(jSrc & 0x30) >> 4];
*(pjDst+1) = (*(pjDst+1) & ~Mask ) | (Accum & Mask);
Mask = TextExpMask[(jSrc & 0x0C) >> 2];
*(pjDst+2) = (*(pjDst+2) & ~Mask ) | (Accum & Mask);
Mask = TextExpMask[(jSrc & 0x03) ];
*(pjDst+3) = (*(pjDst+3) & ~Mask ) | (Accum & Mask);
pjDst += 4; pjSrc ++;
} while (pjSrc != pjSrcEnd);
pjDst += lDstStride; pjSrc += lSrcStride;
} while (pjSrc != pjSrcEndY);
}
//
// start case
//
if (lStartCase) {
//
// check for start and stop in same src byte
//
BOOL bSameByte = ((SrcLeft) & ~0x07) == ((SrcRight) & ~0x07);
if (bSameByte) {
//
// start and stop in same src byte
//
PBYTE pjDstEnd2; PBYTE pjDstScan = pjDstIn + ((DstLeft >> 1)); LONG lTextWidth = lEndCase - lStartCase;
//
// check for bad width
//
if (lTextWidth <= 0) { return; }
pjSrc = pjSrcIn + (SrcLeft >> 3); pjSrcEndY = pjSrc + cy * DeltaSrcIn;
do {
pjDst = pjDstScan; jSrc = *pjSrc << lStartCase; LONG ix = lTextWidth;
//
// partial nibble on left edge
//
if (lStartCase & 0x01) {
if (jSrc & 0x80) { *pjDst = (*pjDst & 0xF0) | (Accum & 0x0F); }
jSrc <<= 1; pjDst++; ix--; }
//
// bytes
//
while (ix >= 2) {
Mask = TextExpMask[(jSrc & 0xc0) >> 6]; *(pjDst) = (*(pjDst) & ~Mask ) | (Accum & Mask); jSrc<<=2; ix -= 2; pjDst++;
}
//
// last nibble on right edge
//
if (ix & 0x01) { if (jSrc & 0x80) { *pjDst = (*pjDst & 0x0F) | (Accum & 0xF0); } }
pjSrc += DeltaSrcIn; pjDstScan += DeltaDstIn;
} while (pjSrc != pjSrcEndY);
//
// make sure end case doesn't run
//
lEndCase = 0;
} else {
//
// start case
//
pjSrc = pjSrcIn + (SrcLeft >> 3); pjDst = pjDstIn + ((DstLeft >> 1)); pjSrcEndY = pjSrc + cy * DeltaSrcIn; LONG lDstStride = DeltaDstIn - ((9 - lStartCase) >> 1);
do {
jSrc = *pjSrc << lStartCase; LONG ix = 8 - lStartCase;
//
// partial
//
if (ix & 0x01) {
if (jSrc & 0x80) { *pjDst = (*pjDst & 0xF0) | (Accum & 0x0F); }
jSrc <<= 1; pjDst++; ix--; }
//
// bytes
//
while (ix != 0) {
Mask = TextExpMask[(jSrc & 0xc0) >> 6]; *(pjDst) = (*(pjDst) & ~Mask ) | (Accum & Mask); jSrc<<=2; ix-=2; pjDst++;
}
pjSrc += DeltaSrcIn; pjDst += lDstStride;
} while (pjSrc != pjSrcEndY); }
}
//
// end case
//
if (lEndCase) {
pjSrc = pjSrcIn + (SrcRight >> 3); pjDst = pjDstIn + ((DstRight - lEndCase) >> 1); pjSrcEndY = pjSrc + cy * DeltaSrcIn; LONG lDstStride = DeltaDstIn - ((lEndCase + 1) >> 1);
do {
jSrc = *pjSrc;
LONG ix = lEndCase;
//
// bytes
//
while (ix >= 2) {
Mask = TextExpMask[(jSrc & 0xC0) >> 6];
*(pjDst) = (*(pjDst) & ~Mask ) | (Accum & Mask);
jSrc <<= 2; ix -= 2; pjDst ++;
}
//
// last partial
//
if (ix) {
if (jSrc & 0x80) { *pjDst = (*pjDst & 0x0F) | (Accum & 0xF0); }
pjDst++;
}
pjSrc += DeltaSrcIn; pjDst += lDstStride;
} while (pjSrc != pjSrcEndY); } }
#if !defined(_MIPS_)
const ULONG TranTable [] = { 0x00000000, 0xff000000, 0x00ff0000, 0xffff0000, 0x0000ff00, 0xff00ff00, 0x00ffff00, 0xffffff00, 0x000000ff, 0xff0000ff, 0x00ff00ff, 0xffff00ff, 0x0000ffff, 0xff00ffff, 0x00ffffff, 0xffffffff };
/******************************Public*Routine******************************\
* * Routine Name * * vSrcTranCopyS1D8 * * Routine Description: * * Transparent blt of 1BPP src to all destination format * src bits that are "1" are copied to the dest as foreground color, * src bits that are "0" are not copied * * Arguments: * * pjSrcIn - pointer to beginning of current scan line of src buffer * SrcLeft - left (starting) pixel in src rectangle * DeltaSrcIn - bytes from one src scan line to next * pjDstIn - pointer to beginning of current scan line of Dst buffer * DstLeft - left(first) dst pixel * DstRight - right(last) dst pixel * DeltaDstIn - bytes from one Dst scan line to next * cy - number of scan lines * uF - Foreground color * uB - Background color * * Return Value: * * None * \**************************************************************************/ VOID vSrcTranCopyS1D8( PBYTE pjSrcIn, LONG SrcLeft, LONG DeltaSrcIn, PBYTE pjDstIn, LONG DstLeft, LONG DstRight, LONG DeltaDstIn, LONG cy, ULONG uF, ULONG uB, SURFACE *pSurf ) { //
// start at 8-byte aligned left edge
//
ULONG uExpand = uF | (uF << 8); ULONG LeftAln = (DstLeft & ~0x07); ULONG LeftEdgeMask = 0xFF >> (DstLeft & 0x07); ULONG RightAln = (DstRight & ~0x07); ULONG EndOffset = RightAln - LeftAln; LONG DeltaDst; LONG DeltaSrc; PBYTE pjDstEndY; PBYTE pjSrc; PBYTE pjDst;
uExpand = uExpand | (uExpand << 16);
//
// calc addresses and strides
//
pjDst = pjDstIn + LeftAln; pjDstEndY = pjDst + cy * DeltaDstIn; pjSrc = pjSrcIn + (SrcLeft >> 3);
DeltaSrc = DeltaSrcIn - (EndOffset >> 3); DeltaDst = DeltaDstIn - EndOffset;
//
// make sure at least 1 QWORD needs copied
//
if (RightAln != LeftAln) {
do {
PBYTE pjDstEnd = pjDst + EndOffset;
//
// and first src byte to cover left edge
//
BYTE c0 = *pjSrc & (BYTE)LeftEdgeMask;
if (c0 != 0) {
ULONG MaskLow = TranTable[c0 >> 4]; ULONG MaskHi = TranTable[c0 & 0x0F]; ULONG d0 = *(PULONG)pjDst; ULONG d1 = *(PULONG)(pjDst + 4);
d0 = (d0 & ~MaskLow) | (uExpand & MaskLow); d1 = (d1 & ~MaskHi) | (uExpand & MaskHi);
*(PULONG)pjDst = d0; *(PULONG)(pjDst + 4) = d1; }
pjSrc ++; pjDst += 8;
while (pjDst != pjDstEnd) {
c0 = *pjSrc;
if (c0 != 0) {
ULONG MaskLow = TranTable[c0 >> 4]; ULONG MaskHi = TranTable[c0 & 0x0F]; ULONG d0 = *(PULONG)pjDst; ULONG d1 = *(PULONG)(pjDst + 4);
d0 = (d0 & ~MaskLow) | (uExpand & MaskLow); d1 = (d1 & ~MaskHi) | (uExpand & MaskHi);
*(PULONG)pjDst = d0; *(PULONG)(pjDst + 4) = d1; }
pjSrc ++; pjDst += 8;
};
pjDst += DeltaDst; pjSrc += DeltaSrc;
} while (pjDst != pjDstEndY); }
RightAln = DstRight & 0x07;
if (RightAln) {
BOOL bSameQWord = ((DstLeft) & ~0x07) == ((DstRight) & ~0x07);
//
// if left and right edges are in same qword handle with masked
// read-modify-write
//
if (bSameQWord) {
LeftAln = DstLeft & 0x07;
LONG xCount = RightAln - LeftAln;
//
// assert ic xCount < 0
//
if (xCount <= 0) { return; }
LONG lDeltaDst = DeltaDstIn - xCount;
PBYTE pjDstEnd;
pjDst = pjDstIn + DstLeft; pjDstEndY = pjDst + cy * DeltaDstIn; pjSrc = pjSrcIn + (SrcLeft >> 3);
//
// expand, one src byte is all that's required
//
BYTE jSrc; do {
//
// load src and shift into place
//
jSrc = *pjSrc; jSrc <<= LeftAln;
pjDstEnd = pjDst + xCount;
do {
if (jSrc & 0x80) { *pjDst = (BYTE)uF; }
jSrc <<=1; pjDst++;
} while (pjDst != pjDstEnd);
pjDst += lDeltaDst; pjSrc += DeltaSrcIn;
} while (pjDst != pjDstEndY);
return;
} else {
ULONG ul0,ul1; BYTE jSrc; LONG lDeltaDst = DeltaDstIn - RightAln; PBYTE pjDstEnd;
pjDst = pjDstIn + (DstRight & ~0x07); pjDstEndY = pjDst + cy * DeltaDstIn; pjSrc = pjSrcIn + ((SrcLeft + (DstRight - DstLeft)) >> 3);
do {
//
// read src
//
jSrc = *pjSrc;
if (jSrc != 0) {
pjDstEnd = pjDst + RightAln;
do { if (jSrc & 0x80) { *pjDst = (BYTE)uF; } jSrc <<=1; pjDst++; } while (pjDst != pjDstEnd);
} else {
//
// short cut for zero
//
pjDst += RightAln;
}
pjDst += lDeltaDst; pjSrc += DeltaSrcIn;
} while (pjDst != pjDstEndY);
} } }
#endif
/******************************Public*Routine******************************\
* * Routine Name * * vSrcTranCopyS1D16 * * Routine Description: * * Transparent blt of 1BPP src to all destination format * src bits that are "1" are copied to the dest as foreground color, * src bits that are "0" are not copied * * Arguments: * * pjSrcIn - pointer to beginning of current scan line of src buffer * SrcLeft - left (starting) pixel in src rectangle * DeltaSrcIn - bytes from one src scan line to next * pjDstIn - pointer to beginning of current scan line of Dst buffer * DstLeft - left(first) dst pixel * DstRight - right(last) dst pixel * DeltaDstIn - bytes from one Dst scan line to next * cy - number of scan lines * uF - Foreground color * uB - Background color * * Return Value: * * None * \**************************************************************************/ VOID vSrcTranCopyS1D16( PBYTE pjSrcIn, LONG SrcLeft, LONG DeltaSrcIn, PBYTE pjDstIn, LONG DstLeft, LONG DstRight, LONG DeltaDstIn, LONG cy, ULONG uF, ULONG uB, SURFACE *pSurf ) { BYTE jSrc; LONG ixStart = SrcLeft & 0x07; PUSHORT pusEnd; PUSHORT pusEnd8; PUSHORT pusDst = (PUSHORT)pjDstIn + DstLeft; PBYTE pjSrc = pjSrcIn + (SrcLeft >> 3); LONG cx = DstRight - DstLeft; LONG lDstStride = DeltaDstIn - (cx << 1); LONG lSrcStride = DeltaSrcIn - ((cx + ixStart + 7) >> 3); PUSHORT pusEndY = (PUSHORT)((PBYTE)pusDst + DeltaDstIn * cy); LONG StartOffset = min(cx, (8 - ixStart));
do {
pusEnd = pusDst + cx;
//
// do starting pixels
//
if (ixStart) {
jSrc = *pjSrc << ixStart;
pjSrc++;
PUSHORT pusEndSt = pusDst + StartOffset;
do {
if (jSrc & 0x80) { *pusDst = (USHORT)uF; }
pusDst++; jSrc <<=1;
} while (pusDst != pusEndSt); }
//
// number of full bytes that can be expanded
//
pusEnd8 = (PUSHORT)((PBYTE)pusDst + (((ULONG_PTR)pusEnd - (ULONG_PTR)pusDst) & ~0x0F));
//
// expand full bytes
//
while (pusDst != pusEnd8) {
jSrc = *pjSrc;
if (jSrc & 0x80) { *(pusDst+0) = (USHORT)uF; } if (jSrc & 0x40) { *(pusDst+1) = (USHORT)uF; } if (jSrc & 0x20) { *(pusDst+2) = (USHORT)uF; } if (jSrc & 0x10) { *(pusDst+3) = (USHORT)uF; } if (jSrc & 0x08) { *(pusDst+4) = (USHORT)uF; } if (jSrc & 0x04) { *(pusDst+5) = (USHORT)uF; } if (jSrc & 0x02) { *(pusDst+6) = (USHORT)uF; } if (jSrc & 0x01) { *(pusDst+7) = (USHORT)uF; }
pjSrc++; pusDst += 8;
}
//
// finish off scan line if needed
//
if (pusDst != pusEnd) {
jSrc = *pjSrc++;
do { if (jSrc & 0x80) { *pusDst = (USHORT)uF; } jSrc<<=1; pusDst++; } while (pusDst != pusEnd);
}
pusDst = (PUSHORT)((PBYTE)pusDst + lDstStride); pjSrc += lSrcStride;
} while(pusDst != pusEndY);
}
/******************************Public*Routine******************************\
* * Routine Name * * vSrcTranCopyS1D24 * * Routine Description: * * Transparent blt of 1BPP src to all destination format * src bits that are "1" are copied to the dest as foreground color, * src bits that are "0" are not copied * * Arguments: * * pjSrcIn - pointer to beginning of current scan line of src buffer * SrcLeft - left (starting) pixel in src rectangle * DeltaSrcIn - bytes from one src scan line to next * pjDstIn - pointer to beginning of current scan line of Dst buffer * DstLeft - left(first) dst pixel * DstRight - right(last) dst pixel * DeltaDstIn - bytes from one Dst scan line to next * cy - number of scan lines * uF - Foreground color * uB - Background color * * Return Value: * * None * \**************************************************************************/
VOID vSrcTranCopyS1D24( PBYTE pjSrcIn, LONG SrcLeft, LONG DeltaSrcIn, PBYTE pjDstIn, LONG DstLeft, LONG DstRight, LONG DeltaDstIn, LONG cy, ULONG uF, ULONG uB, SURFACE *pSurf ) { BYTE jSrc; BYTE jF0 = (BYTE)uF; BYTE jF1 = (BYTE)(uF >> 8); BYTE jF2 = (BYTE)(uF >> 16); LONG ixStart = SrcLeft & 0x07; PBYTE pjEnd; PBYTE pjEnd8; PBYTE pjDst = (PBYTE)pjDstIn + 3 * DstLeft; PBYTE pjSrc = pjSrcIn + (SrcLeft >> 3); LONG cx = DstRight - DstLeft; LONG lDstStride = DeltaDstIn - 3* cx; LONG lSrcStride = DeltaSrcIn - ((cx + ixStart + 7) >> 3); PBYTE pjEndY = (PBYTE)((PBYTE)pjDst + DeltaDstIn * cy); LONG StartOffset = 3 * min(cx, (8 - ixStart));
do {
pjEnd = pjDst + 3 * cx;
//
// do starting pixels
//
if (ixStart) {
jSrc = *pjSrc << ixStart;
pjSrc++;
PBYTE pjEndSt = pjDst + StartOffset;
do {
if (jSrc & 0x80) { *pjDst = jF0; *(pjDst+1) = jF1; *(pjDst+2) = jF2; }
pjDst += 3; jSrc <<=1;
} while (pjDst != pjEndSt); }
//
// number of full bytes that can be expanded
//
pjEnd8 = (PBYTE)((PBYTE)pjDst + ( 24 * (((ULONG_PTR)(pjEnd - pjDst))/24)));
//
// expand full bytes
//
while (pjDst != pjEnd8) {
jSrc = *pjSrc;
if (jSrc & 0x80) { *(pjDst+0) = jF0; *(pjDst+1) = jF1; *(pjDst+2) = jF2; } if (jSrc & 0x40) { *(pjDst+3) = jF0; *(pjDst+4) = jF1; *(pjDst+5) = jF2; } if (jSrc & 0x20) { *(pjDst+6) = jF0; *(pjDst+7) = jF1; *(pjDst+8) = jF2; } if (jSrc & 0x10) { *(pjDst+9) = jF0; *(pjDst+10) = jF1; *(pjDst+11) = jF2; } if (jSrc & 0x08) { *(pjDst+12) = jF0; *(pjDst+13) = jF1; *(pjDst+14) = jF2; } if (jSrc & 0x04) { *(pjDst+15) = jF0; *(pjDst+16) = jF1; *(pjDst+17) = jF2; } if (jSrc & 0x02) { *(pjDst+18) = jF0; *(pjDst+19) = jF1; *(pjDst+20) = jF2; } if (jSrc & 0x01) { *(pjDst+21) = jF0; *(pjDst+22) = jF1; *(pjDst+23) = jF2; }
pjSrc++; pjDst += 3*8;
}
//
// finish off scan line if needed
//
if (pjDst != pjEnd) {
jSrc = *pjSrc++;
do { if (jSrc & 0x80) { *(pjDst+0) = jF0; *(pjDst+1) = jF1; *(pjDst+2) = jF2; } jSrc <<= 1; pjDst += 3; } while (pjDst != pjEnd);
}
pjDst = (PBYTE)((PBYTE)pjDst + lDstStride); pjSrc += lSrcStride;
} while(pjDst != pjEndY);
}
/******************************Public*Routine******************************\
* * Routine Name * * vSrcTranCopyS1D32 * * Routine Description: * * Transparent blt of 1BPP src to all destination format * src bits that are "1" are copied to the dest as foreground color, * src bits that are "0" are not copied * * Arguments: * * pjSrcIn - pointer to beginning of current scan line of src buffer * SrcLeft - left (starting) pixel in src rectangle * DeltaSrcIn - bytes from one src scan line to next * pjDstIn - pointer to beginning of current scan line of Dst buffer * DstLeft - left(first) dst pixel * DstRight - right(last) dst pixel * DeltaDstIn - bytes from one Dst scan line to next * cy - number of scan lines * uF - Foreground color * uB - Background color * * Return Value: * * None * \**************************************************************************/
VOID vSrcTranCopyS1D32( PBYTE pjSrcIn, LONG SrcLeft, LONG DeltaSrcIn, PBYTE pjDstIn, LONG DstLeft, LONG DstRight, LONG DeltaDstIn, LONG cy, ULONG uF, ULONG uB, SURFACE *pSurf ) { BYTE jSrc; LONG ixStart = SrcLeft & 0x07; PULONG pulEnd; PULONG pulEnd8; PULONG pulDst = (PULONG)pjDstIn + DstLeft; PBYTE pjSrc = pjSrcIn + (SrcLeft >> 3); LONG cx = DstRight - DstLeft; LONG lDstStride = DeltaDstIn - (cx << 2); LONG lSrcStride = DeltaSrcIn - ((cx + ixStart + 7) >> 3); PULONG pulEndY = (PULONG)((PBYTE)pulDst + DeltaDstIn * cy); LONG StartOffset = min(cx, (8 - ixStart));
do {
pulEnd = pulDst + cx;
//
// do starting pixels
//
if (ixStart) {
jSrc = *pjSrc << ixStart;
pjSrc++;
PULONG pulEndSt = pulDst + StartOffset;
do {
if (jSrc & 0x80) { *pulDst = uF; }
pulDst++; jSrc <<=1;
} while (pulDst != pulEndSt); }
//
// number of full bytes that can be expanded
//
pulEnd8 = (PULONG)((PBYTE)pulDst + (((ULONG_PTR)pulEnd - (ULONG_PTR)pulDst) & ~0x1F));
//
// expand full bytes
//
while (pulDst != pulEnd8) {
jSrc = *pjSrc;
if (jSrc & 0x80) { *(pulDst+0) = uF; } if (jSrc & 0x40) { *(pulDst+1) = uF; } if (jSrc & 0x20) { *(pulDst+2) = uF; } if (jSrc & 0x10) { *(pulDst+3) = uF; } if (jSrc & 0x08) { *(pulDst+4) = uF; } if (jSrc & 0x04) { *(pulDst+5) = uF; } if (jSrc & 0x02) { *(pulDst+6) = uF; } if (jSrc & 0x01) { *(pulDst+7) = uF; }
pjSrc++; pulDst += 8;
}
//
// finish off scan line if needed
//
if (pulDst != pulEnd) {
jSrc = *pjSrc++;
do { if (jSrc & 0x80) { *pulDst = uF; } jSrc<<=1; pulDst++; } while (pulDst != pulEnd);
}
pulDst = (PULONG)((PBYTE)pulDst + lDstStride); pjSrc += lSrcStride;
} while(pulDst != pulEndY);
}
/******************************Public*Routine******************************\
* * Routine Name * * vSrcOpaqCopyS1D1 * * Routine Description: * * Opaque blt of 1BPP src to destination format * * * Arguments: * * pjSrcIn - pointer to beginning of current scan line of src buffer * SrcLeft - left (starting) pixel in src rectangle * DeltaSrcIn - bytes from one src scan line to next * pjDstIn - pointer to beginning of current scan line of Dst buffer * DstLeft - left(first) dst pixel * DstRight - right(last) dst pixel * DeltaDstIn - bytes from one Dst scan line to next * cy - number of scan lines * uF - Foreground color * uB - Background color * * Return Value: * * None * \**************************************************************************/
#if !defined (_X86_)
VOID vSrcOpaqCopyS1D1( PBYTE pjSrcIn, LONG SrcLeft, LONG DeltaSrcIn, PBYTE pjDstIn, LONG DstLeft, LONG DstRight, LONG DeltaDstIn, LONG cy, ULONG uF, ULONG uB, SURFACE *pSurf )
{
//
// DWORD version
//
//
// build and and xor mask
//
// and mask is set to 0x00 if uF == uB, so that
// this routine acts like a solid fill. (although src is not needed!)
//
// The xor mask is set to 0xFF if inversion is needed:
// either uF == uB == 1, for solid fill 1s or
// uF = 0, uB = 1 for inverted text
//
uF &= 1; uB &= 1;
LONG cx = DstRight - DstLeft;
LONG lStartCase = SrcLeft; LONG lEndCase = SrcLeft + cx; ULONG uStartMask = (ULONG)~0; ULONG uEndMask = (ULONG)~0; LONG lEndOffset; LONG lSrcStride = DeltaSrcIn; LONG lDstStride = DeltaDstIn;
PBYTE pjSrc; PBYTE pjDst; PBYTE pjSrcEnd; PBYTE pjSrcEndY;
lStartCase = lStartCase & 0x1F; lEndCase = lEndCase & 0x1F;
//
// big endian masks
//
if (lStartCase) { uStartMask >>= lStartCase;
//
// convert to little
// // 0 1 2 3
ULONG u0 = uStartMask << 24; // 3 - - -
ULONG u1 = uStartMask >> 24; // - - - 0
ULONG u2 = (uStartMask >> 8) & 0xFF00; // - - 1 -
uStartMask = (uStartMask & 0xFF00) << 8; // - 2 - -
uStartMask |= u0 | u1 | u2;
}
if (lEndCase) {
uEndMask <<= (32 - lEndCase);
//
// convert to little
// // 0 1 2 3
ULONG u0 = uEndMask << 24; // 3 - - -
ULONG u1 = uEndMask >> 24; // - - - 0
ULONG u2 = (uEndMask >> 8) & 0xFF00; // - - 1 -
uEndMask = (uEndMask & 0xFF00) << 8; // - 2 - -
uEndMask |= u0 | u1 | u2; }
//
// calc starting and ending full dword addresses (DWORD aligned)
//
pjDst = pjDstIn + (((DstLeft) >> 3) & ~0x03); pjSrc = pjSrcIn + (((SrcLeft) >> 3) & ~0x03); pjSrcEnd = pjSrcIn + (((SrcLeft+cx) >> 3) & ~0x03);
//Sundown safe truncation
lEndOffset = (ULONG)((ULONG_PTR)pjSrcEnd - (ULONG_PTR)pjSrc);
pjSrcEndY = pjSrc + cy * lSrcStride;
//
// special case uF = 1 and uB = 0
//
if (uF && !uB) {
//
// special case direct copy
//
if (pjSrc != pjSrcEnd) {
//
// start and stop are not in same byte
//
lDstStride -= lEndOffset; lSrcStride -= lEndOffset;
do {
pjSrcEnd = pjSrc + lEndOffset;
if (lStartCase) { *(PULONG)pjDst = (*(PULONG)pjDst & ~uStartMask) | (*(PULONG)pjSrc & uStartMask); pjDst+=4; pjSrc+=4; }
while (pjSrc != pjSrcEnd) {
*(PULONG)pjDst = *(PULONG)pjSrc; pjSrc +=4; pjDst +=4;
}
if (lEndCase) { *(PULONG)pjDst = (*(PULONG)pjDst & ~uEndMask) | (*(PULONG)pjSrc & uEndMask); }
pjSrc += lSrcStride; pjDst += lDstStride;
} while (pjSrc != pjSrcEndY);
} else {
//
// start and stop are in same byte
//
uStartMask &= uEndMask;
do {
*(PULONG)pjDst = (*(PULONG)pjDst & ~uStartMask) | (*(PULONG)pjSrc & uStartMask);
pjSrc += lSrcStride; pjDst += lDstStride;
} while (pjSrc != pjSrcEndY); }
//
// special case uF = 0 and uB = 1 (invert)
//
} else if (!uF && uB) {
//
// dst = ~Src
//
if (pjSrc != pjSrcEnd) {
//
// start and stop are not in same byte
//
lDstStride -= lEndOffset; lSrcStride -= lEndOffset;
do {
pjSrcEnd = pjSrc + lEndOffset;
if (lStartCase) { *(PULONG)pjDst = (*(PULONG)pjDst & ~uStartMask) | (~(*(PULONG)pjSrc) & uStartMask); pjDst+=4; pjSrc+=4; }
while (pjSrc != pjSrcEnd) {
*(PULONG)pjDst = ~(*(PULONG)pjSrc); pjSrc +=4; pjDst +=4;
}
if (lEndCase) { *(PULONG)pjDst = (*(PULONG)pjDst & ~uEndMask) | (~(*(PULONG)pjSrc) & uEndMask); }
pjSrc += lSrcStride; pjDst += lDstStride;
} while (pjSrc != pjSrcEndY);
} else {
//
// start and stop are in same byte
//
uStartMask &= uEndMask;
do {
*(PULONG)pjDst = (*(PULONG)pjDst & ~uStartMask) | (~(*(PULONG)pjSrc) & uStartMask);
pjSrc += lSrcStride; pjDst += lDstStride;
} while (pjSrc != pjSrcEndY); }
} else {
ULONG AndMask = (uF == uB) ? 0x00 : 0xFF; AndMask |= AndMask << 8; AndMask |= AndMask << 16;
ULONG XorMask = (uB == 1) ? 0xFF : 0x00; XorMask |= XorMask << 8; XorMask |= XorMask << 16;
if (pjSrc != pjSrcEnd) {
//
// start and stop are not in same byte
//
lDstStride -= lEndOffset; lSrcStride -= lEndOffset;
do {
pjSrcEnd = pjSrc + lEndOffset;
if (lStartCase) { *(PULONG)pjDst = (*(PULONG)pjDst & ~uStartMask) | (((*(PULONG)pjSrc & AndMask) ^ XorMask) & uStartMask); pjDst+=4; pjSrc+=4; }
while (pjSrc != pjSrcEnd) {
*(PULONG)pjDst = *(PULONG)pjSrc & AndMask ^ XorMask; pjSrc +=4; pjDst +=4;
}
if (lEndCase) { *(PULONG)pjDst = (*(PULONG)pjDst & ~uEndMask) | (((*(PULONG)pjSrc & AndMask) ^ XorMask) & uEndMask); }
pjSrc += lSrcStride; pjDst += lDstStride;
} while (pjSrc != pjSrcEndY);
} else {
//
// start and stop are in same byte
//
uStartMask &= uEndMask;
do {
*(PULONG)pjDst = (*(PULONG)pjDst & ~uStartMask) | (((*(PULONG)pjSrc & AndMask) ^ XorMask) & uStartMask);
pjSrc += lSrcStride; pjDst += lDstStride;
} while (pjSrc != pjSrcEndY); }
} }
#endif
/******************************Public*Routine******************************\
* * Routine Name * * vSrcOpaqCopyS1D4 * * Routine Description: * * Opaque blt of 1BPP src to destination format * * Arguments: * * pjSrcIn - pointer to beginning of current scan line of src buffer * SrcLeft - left (starting) pixel in src rectangle * DeltaSrcIn - bytes from one src scan line to next * pjDstIn - pointer to beginning of current scan line of Dst buffer * DstLeft - left(first) dst pixel * DstRight - right(last) dst pixel * DeltaDstIn - bytes from one Dst scan line to next * cy - number of scan lines * uF - Foreground color * uB - Background color * * Return Value: * * None * \**************************************************************************/
VOID vSrcOpaqCopyS1D4( PBYTE pjSrcIn, LONG SrcLeft, LONG DeltaSrcIn, PBYTE pjDstIn, LONG DstLeft, LONG DstRight, LONG DeltaDstIn, LONG cy, ULONG uF, ULONG uB, SURFACE *pSurf ) {
//
// Warning, this 4bit code is not optimized, it is not expected that
// we will draw many 4bpp engine bitmaps.
//
//
// check for quick out?
//
BYTE jF = (BYTE)uF; BYTE jB = (BYTE)uB; BYTE TextExpTable[4]; LONG cx = DstRight - DstLeft;
//
// build small table
//
BYTE Accum = jB | (jB << 4);
TextExpTable[0] = Accum; // 0 0
Accum <<= 4; Accum |= jF; TextExpTable[1] = Accum; // 0 1
Accum <<= 4; Accum |= jF; TextExpTable[3] = Accum; // 1 1
Accum <<= 4; Accum |= jB; TextExpTable[2] = Accum; // 1 0
LONG lStartCase = SrcLeft & 0x07; LONG SrcRight = SrcLeft+cx; LONG lEndCase = SrcRight & 0x07; PBYTE pjSrc = pjSrcIn + ((SrcLeft + 7) >> 3); PBYTE pjSrcEndY = pjSrc + cy * DeltaSrcIn; PBYTE pjSrcEnd; LONG lSrcStartOffset = (8 - lStartCase); LONG lSrcStride; PBYTE pjDst; BYTE jSrc;
if (lStartCase == 0) { lSrcStartOffset = 0; }
cx = cx - lSrcStartOffset - lEndCase;
if (cx > 0) {
LONG lDstStride = DeltaDstIn - (cx >> 1); lSrcStride = DeltaSrcIn - (cx >> 3);
pjDst = pjDstIn + ((DstLeft + lSrcStartOffset) >> 1);
do {
pjSrcEnd = pjSrc + (cx >> 3);
//
// aligned middle
//
do {
jSrc = *pjSrc;
*pjDst = TextExpTable[(jSrc & 0xC0) >> 6]; *(pjDst+1) = TextExpTable[(jSrc & 0x30) >> 4]; *(pjDst+2) = TextExpTable[(jSrc & 0x0C) >> 2]; *(pjDst+3) = TextExpTable[ jSrc & 0x03 ];
pjDst += 4; pjSrc ++;
} while (pjSrc != pjSrcEnd);
pjDst += lDstStride; pjSrc += lSrcStride;
} while (pjSrc != pjSrcEndY);
}
//
// start case
//
if (lStartCase) {
//
// are start and stop in same src byte
//
BOOL bSameByte = ((SrcLeft) & ~0x07) == ((SrcRight) & ~0x07);
if (bSameByte) {
//
// start and stop in same byte
//
PBYTE pjDstScan = pjDstIn + ((DstLeft >> 1)); PBYTE pjDstEnd2; LONG lTextWidth = lEndCase - lStartCase;
//
// check for bad width
//
if (lTextWidth <= 0) { return; }
pjSrc = pjSrcIn + (SrcLeft >> 3); pjSrcEndY = pjSrc + cy * DeltaSrcIn;
do {
pjDst = pjDstScan; jSrc = *pjSrc << (lStartCase & ~0x01); LONG ix = lTextWidth;
//
// starting odd nibble
//
if (lStartCase & 0x01) { *pjDst = (*pjDst & 0xF0) | (TextExpTable[(jSrc & 0xc0) >> 6] & 0x0F); jSrc <<= 2; pjDst++; ix--; }
//
// full byte nibble pairs
//
while (ix >= 2) { *(pjDst) = TextExpTable[(jSrc & 0xC0) >> 6]; jSrc<<=2; pjDst++; ix -= 2; }
//
// last nibble
//
if (ix) { *(pjDst) = (*(pjDst) & 0x0F) | (TextExpTable[(jSrc & 0xc0) >> 6] & 0xF0); }
pjSrc += DeltaSrcIn; pjDstScan += DeltaDstIn;
} while (pjSrc != pjSrcEndY);
//
// make sure end case doesn't run
//
lEndCase = 0;
} else {
pjSrc = pjSrcIn + (SrcLeft >> 3); pjDst = pjDstIn + ((DstLeft >> 1)); pjSrcEndY = pjSrc + cy * DeltaSrcIn; LONG lDstStride = DeltaDstIn - ((9 - lStartCase) >> 1); // ((8 - lStartCase) + 1) / 2
do {
jSrc = *pjSrc << (lStartCase & ~0x01); LONG ix = 8 - lStartCase;
//
// partial
//
if (ix & 0x01) {
*pjDst = (*pjDst & 0xF0) | (TextExpTable[(jSrc & 0xc0) >> 6] & 0x0F);
jSrc <<= 2; pjDst++; ix--; }
//
// bytes
//
while (ix != 0) {
*(pjDst) = TextExpTable[(jSrc & 0xC0) >> 6]; jSrc<<=2; ix-=2; pjDst++; }
pjSrc += DeltaSrcIn; pjDst += lDstStride;
} while (pjSrc != pjSrcEndY); } }
//
// end case
//
if (lEndCase) {
pjSrc = pjSrcIn + (SrcRight >> 3); pjDst = pjDstIn + ((DstRight - lEndCase) >> 1); pjSrcEndY = pjSrc + cy * DeltaSrcIn; LONG lDstStride = DeltaDstIn - ((lEndCase + 1) >> 1);
do {
jSrc = *pjSrc;
LONG ix = lEndCase;
//
// bytes
//
while (ix >= 2) {
*(pjDst) = TextExpTable[(jSrc & 0xC0) >> 6];
jSrc <<= 2; ix -= 2; pjDst ++;
}
//
// last partial
//
if (ix) {
*(pjDst) = (*(pjDst) & 0x0F) | (TextExpTable[(jSrc & 0xc0) >> 6] & 0xF0); pjDst++;
}
pjSrc += DeltaSrcIn; pjDst += lDstStride;
} while (pjSrc != pjSrcEndY); } }
//
// edge mask for 8 bit expansion
//
extern "C" {
ULONG gTextLeftMask[8][2] = { {0xffffffff,0xffffffff}, {0xffffff00,0xffffffff}, {0xffff0000,0xffffffff}, {0xff000000,0xffffffff}, {0x00000000,0xffffffff}, {0x00000000,0xffffff00}, {0x00000000,0xffff0000}, {0x00000000,0xff000000} }; ULONG gTextRightMask[8][2] = { {0xffffffff,0xffffffff}, {0x000000ff,0x00000000}, {0x0000ffff,0x00000000}, {0x00ffffff,0x00000000}, {0xffffffff,0x00000000}, {0xffffffff,0x000000ff}, {0xffffffff,0x0000ffff}, {0xffffffff,0x00ffffff} }; }
/******************************Public*Routine******************************\
* * Routine Name * * vSrcOpaqCopyS1D8 * * Routine Description: * * Opaque blt of 1BPP src to destination format * * Arguments: * * pjSrcIn - pointer to beginning of current scan line of src buffer * SrcLeft - left (starting) pixel in src rectangle * DeltaSrcIn - bytes from one src scan line to next * pjDstIn - pointer to beginning of current scan line of Dst buffer * DstLeft - left(first) dst pixel * DstRight - right(last) dst pixel * DeltaDstIn - bytes from one Dst scan line to next * cy - number of scan lines * uF - Foreground color * uB - Background color * * Return Value: * * None * \**************************************************************************/
VOID vSrcOpaqCopyS1D8( PBYTE pjSrcIn, LONG SrcLeft, LONG DeltaSrcIn, PBYTE pjDstIn, LONG DstLeft, LONG DstRight, LONG DeltaDstIn, LONG cy, ULONG uF, ULONG uB, SURFACE *pSurf ) { //
// Aligned portion
//
ULONG LeftAln = ((DstLeft + 7) & ~0x07); ULONG RightAln = ((DstRight) & ~0x07); ULONG EndOffset = RightAln - LeftAln; ULONG EndOffset4 = EndOffset & ~0x0F; ULONG EndOffset8 = EndOffset & ~0x1F; LONG DeltaDst; LONG DeltaSrc; PBYTE pjDstEndY; PBYTE pjSrc; PBYTE pjDst; ULONG TextExpTable[16];
//
// Generate text expasion table
//
ULONG Accum = uB;
Accum = Accum | (Accum << 8); Accum = Accum | (Accum << 16); TextExpTable[0] = Accum; // 0 0 0 0
Accum <<= 8; Accum |= uF; TextExpTable[8] = Accum; // 0 0 0 1
Accum <<= 8; Accum |= uB; TextExpTable[4] = Accum; // 0 0 1 0
Accum <<= 8; Accum |= uF; TextExpTable[10] = Accum; // 0 1 0 1
Accum <<= 8; Accum |= uB; TextExpTable[5] = Accum; // 1 0 1 0
Accum <<= 8; Accum |= uB; TextExpTable[ 2] = Accum; // 0 1 0 0
Accum <<= 8; Accum |= uF; TextExpTable[ 9] = Accum; // 1 0 0 1
Accum <<= 8; Accum |= uF; TextExpTable[12] = Accum; // 0 0 1 1
Accum <<= 8; Accum |= uF; TextExpTable[14] = Accum; // 0 1 1 1
Accum <<= 8; Accum |= uF; TextExpTable[15] = Accum; // 1 1 1 1
Accum <<= 8; Accum |= uB; TextExpTable[ 7] = Accum; // 1 1 1 0
Accum <<= 8; Accum |= uF; TextExpTable[11] = Accum; // 1 1 0 1
Accum <<= 8; Accum |= uF; TextExpTable[13] = Accum; // 1 0 1 1
Accum <<= 8; Accum |= uB; TextExpTable[06] = Accum; // 0 1 1 0
Accum <<= 8; Accum |= uB; TextExpTable[ 3] = Accum; // 1 1 0 0
Accum <<= 8; Accum |= uB; TextExpTable[ 1] = Accum; // 1 0 0 0
//
// calc addresses and strides
//
pjDst = pjDstIn + LeftAln; pjDstEndY = pjDst + cy * DeltaDstIn; pjSrc = pjSrcIn + ((SrcLeft+7) >> 3);
DeltaSrc = DeltaSrcIn - (EndOffset >> 3); DeltaDst = DeltaDstIn - EndOffset;
//
// make sure at least 1 QWORD needs copied
//
if (RightAln > LeftAln) {
//
// expand buffer
//
do {
PBYTE pjDstEnd = pjDst + EndOffset; PBYTE pjDstEnd4 = pjDst + EndOffset4; PBYTE pjDstEnd8 = pjDst + EndOffset8;
//
// 4 times unrolled
//
while (pjDst != pjDstEnd8) { BYTE c0 = *(pjSrc + 0); BYTE c1 = *(pjSrc + 1); BYTE c2 = *(pjSrc + 2); BYTE c3 = *(pjSrc + 3);
*(PULONG)(pjDst + 0) = TextExpTable[c0 >> 4]; *(PULONG)(pjDst + 4) = TextExpTable[c0 & 0x0F];
*(PULONG)(pjDst + 8) = TextExpTable[c1 >> 4]; *(PULONG)(pjDst +12) = TextExpTable[c1 & 0x0F];
*(PULONG)(pjDst +16) = TextExpTable[c2 >> 4]; *(PULONG)(pjDst +20) = TextExpTable[c2 & 0x0F];
*(PULONG)(pjDst +24) = TextExpTable[c3 >> 4]; *(PULONG)(pjDst +28) = TextExpTable[c3 & 0x0F];
pjSrc += 4; pjDst += 32; }
//
// 2 times unrolled
//
while (pjDst != pjDstEnd4) { BYTE c0 = *(pjSrc + 0); BYTE c1 = *(pjSrc + 1);
*(PULONG)(pjDst + 0) = TextExpTable[c0 >> 4]; *(PULONG)(pjDst + 4) = TextExpTable[c0 & 0x0F];
*(PULONG)(pjDst + 8) = TextExpTable[c1 >> 4]; *(PULONG)(pjDst +12) = TextExpTable[c1 & 0x0F];
pjSrc += 2; pjDst += 16; }
//
// 1 byte expansion loop
//
while (pjDst != pjDstEnd) { BYTE c0 = *(pjSrc + 0);
*(PULONG)(pjDst + 0) = TextExpTable[c0 >> 4]; *(PULONG)(pjDst + 4) = TextExpTable[c0 & 0x0F];
pjSrc++; pjDst += 8; }
pjDst += DeltaDst; pjSrc += DeltaSrc;
} while (pjDst != pjDstEndY); }
//
// Starting alignment case: at most 1 src byte is required.
// Start and end may occur in same Quadword.
//
//
// Left Right
// 0 1 2 3�4 5 6 7 0 1 2 3�4 5 6 7
// ���������������Ŀ �������ĺ������Ŀ
// 1 � �x�x�x�x�x�x�x� 1 �x� � � � � � � �
// �������ĺ������Ĵ �������ĺ������Ĵ
// 2 � � �x�x�x�x�x�x� 2 �x�x� � � � � � �
// �������ĺ������Ĵ �������ĺ������Ĵ
// 3 � � � �x�x�x�x�x� 3 �x�x�x� � � � � �
// �������ĺ������Ĵ �������ĺ������Ĵ
// 4 � � � � �x�x�x�x� 4 �x�x�x�x� � � � �
// �������ĺ������Ĵ �������ĺ������Ĵ
// 5 � � � � � �x�x�x� 5 �x�x�x�x�x� � � �
// �������ĺ������Ĵ �������ĺ������Ĵ
// 6 � � � � � � �x�x� 6 �x�x�x�x�x�x� � �
// �������ĺ������Ĵ �������ĺ������Ĵ
// 7 � � � � � � � �x� 7 �x�x�x�x�x�x�x� �
// ����������������� ��������������
//
LeftAln = DstLeft & 0x07; RightAln = DstRight & 0x07;
if (LeftAln) {
BYTE jSrc; BOOL bSameDWord = ((DstLeft) & ~0x03) == ((DstRight-1) & ~0x03); BOOL bSameQWord = ((DstLeft) & ~0x07) == ((DstRight-1) & ~0x07); ULONG ul0,ul1;
ASSERTGDI (DstLeft < DstRight, "vSrcOpaqCopyS1D8: null rectangle passed in.");
// if left and right edges are in the same dword or the same qword,
// handle with masked read-modify-write
if (bSameDWord) {
ULONG Mask0;
Mask0 = gTextLeftMask[LeftAln & 3][0] & gTextRightMask[RightAln & 3][0];
pjDst = pjDstIn + (DstLeft & ~0x03); pjDstEndY = pjDst + cy * DeltaDstIn;
// (SrcLeft >> 3) is the number of bytes to offset by
// (1 BPP in the src buffer).
pjSrc = pjSrcIn + (SrcLeft >> 3);
// expand
do {
jSrc = *pjSrc;
if (LeftAln < 4) ul0 = TextExpTable[jSrc >> 4]; else ul0 = TextExpTable[jSrc & 0xf];
*(PULONG)pjDst = (*(PULONG)pjDst & ~Mask0) | (ul0 & Mask0);
pjDst += DeltaDstIn; pjSrc += DeltaSrcIn;
} while (pjDst != pjDstEndY);
return;
} else if (bSameQWord) {
ULONG Mask0,Mask1;
Mask0 = gTextLeftMask[LeftAln][0] & gTextRightMask[RightAln][0]; Mask1 = gTextLeftMask[LeftAln][1] & gTextRightMask[RightAln][1];
pjDst = pjDstIn + (DstLeft & ~0x07); pjDstEndY = pjDst + cy * DeltaDstIn; // (SrcLeft >> 3) is the number of bytes to offset by
// (1 BPP in the src buffer).
pjSrc = pjSrcIn + (SrcLeft >> 3);
//
// expand
//
do {
jSrc = *pjSrc;
ul0 = TextExpTable[jSrc >> 4]; ul1 = TextExpTable[jSrc & 0x0F];
*(PULONG)(pjDst) = (*(PULONG)(pjDst) & ~Mask0) | (ul0 & Mask0); *(PULONG)(pjDst+4) = (*(PULONG)(pjDst+4) & ~Mask1) | (ul1 & Mask1);
pjDst += DeltaDstIn; pjSrc += DeltaSrcIn;
} while (pjDst != pjDstEndY);
return; }
//
// Left edge only, handle with special write-only loops
//
pjDst = pjDstIn + (DstLeft & ~0x07); pjDstEndY = pjDst + cy * DeltaDstIn; pjSrc = pjSrcIn + (SrcLeft >> 3);
switch (LeftAln) {
case 1:
do {
jSrc = *pjSrc; ul0 = TextExpTable[jSrc >> 4]; ul1 = TextExpTable[jSrc & 0x0F];
*(pjDst+1) = (BYTE)(ul0 >> 8); *((PUSHORT)(pjDst+2)) = (USHORT)(ul0 >> 16); *((PULONG)(pjDst+4)) = ul1;
pjDst += DeltaDstIn; pjSrc += DeltaSrcIn;
} while (pjDst != pjDstEndY);
break;
case 2:
do {
jSrc = *pjSrc; ul0 = TextExpTable[jSrc >> 4]; ul1 = TextExpTable[jSrc & 0x0F];
*((PUSHORT)(pjDst+2)) = (USHORT)(ul0 >> 16); *((PULONG)(pjDst+4)) = ul1;
pjDst += DeltaDstIn; pjSrc += DeltaSrcIn;
} while (pjDst != pjDstEndY);
break;
case 3:
do {
jSrc = *pjSrc; ul0 = TextExpTable[jSrc >> 4]; ul1 = TextExpTable[jSrc & 0x0F];
*(pjDst+3) = (BYTE)(ul0 >> 24); *((PULONG)(pjDst+4)) = ul1;
pjDst += DeltaDstIn; pjSrc += DeltaSrcIn;
} while (pjDst != pjDstEndY);
break;
case 4:
do {
jSrc = *pjSrc; ul1 = TextExpTable[jSrc & 0x0F];
*((PULONG)(pjDst+4)) = ul1;
pjDst += DeltaDstIn; pjSrc += DeltaSrcIn;
} while (pjDst != pjDstEndY);
break;
case 5:
do {
jSrc = *pjSrc; ul1 = TextExpTable[jSrc & 0x0F];
*(pjDst+5) = (BYTE)(ul1 >> 8); *((PUSHORT)(pjDst+6)) = (USHORT)(ul1 >> 16);
pjDst += DeltaDstIn; pjSrc += DeltaSrcIn;
} while (pjDst != pjDstEndY);
break;
case 6:
do {
jSrc = *pjSrc; ul1 = TextExpTable[jSrc & 0x0F];
*((PUSHORT)(pjDst+6)) = (USHORT)(ul1 >> 16);
pjDst += DeltaDstIn; pjSrc += DeltaSrcIn;
} while (pjDst != pjDstEndY);
break;
case 7:
do {
jSrc = *pjSrc; ul1 = TextExpTable[jSrc & 0x0F];
*(pjDst+7) = (BYTE)(ul1 >> 24);
pjDst += DeltaDstIn; pjSrc += DeltaSrcIn;
} while (pjDst != pjDstEndY);
break; } }
//
// handle right edge only, use special write-only loops for each case
//
if (RightAln) {
ULONG ul0,ul1; BYTE jSrc;
pjDst = pjDstIn + (DstRight & ~0x07); pjDstEndY = pjDst + cy * DeltaDstIn; pjSrc = pjSrcIn + ((SrcLeft + (DstRight - DstLeft)) >> 3);
//
// select right case
//
switch (RightAln) { case 1:
do {
jSrc = *pjSrc;
ul0 = TextExpTable[jSrc >> 4];
*(pjDst) = (BYTE)ul0;
pjDst += DeltaDstIn; pjSrc += DeltaSrcIn;
} while (pjDst != pjDstEndY); break;
case 2:
do {
jSrc = *pjSrc;
ul0 = TextExpTable[jSrc >> 4];
*(PUSHORT)(pjDst) = (USHORT)ul0;
pjDst += DeltaDstIn; pjSrc += DeltaSrcIn;
} while (pjDst != pjDstEndY); break;
case 3:
do {
jSrc = *pjSrc;
ul0 = TextExpTable[jSrc >> 4];
*(PUSHORT)(pjDst) = (USHORT)ul0; *(pjDst+2) = (BYTE)(ul0 >> 16);
pjDst += DeltaDstIn; pjSrc += DeltaSrcIn;
} while (pjDst != pjDstEndY); break;
case 4:
do {
jSrc = *pjSrc;
ul0 = TextExpTable[jSrc >> 4];
*(PULONG)(pjDst) = ul0;
pjDst += DeltaDstIn; pjSrc += DeltaSrcIn;
} while (pjDst != pjDstEndY); break;
case 5:
do {
jSrc = *pjSrc;
ul0 = TextExpTable[jSrc >> 4]; ul1 = TextExpTable[jSrc & 0x0F];
*(PULONG)(pjDst) = ul0; *(pjDst+4) = (BYTE)ul1;
pjDst += DeltaDstIn; pjSrc += DeltaSrcIn;
} while (pjDst != pjDstEndY); break;
case 6:
do {
jSrc = *pjSrc;
ul0 = TextExpTable[jSrc >> 4]; ul1 = TextExpTable[jSrc & 0x0F];
*(PULONG)(pjDst) = ul0; *(PUSHORT)(pjDst+4) = (USHORT)ul1;
pjDst += DeltaDstIn; pjSrc += DeltaSrcIn;
} while (pjDst != pjDstEndY); break;
case 7:
do {
jSrc = *pjSrc;
ul0 = TextExpTable[jSrc >> 4]; ul1 = TextExpTable[jSrc & 0x0F];
*(PULONG)(pjDst) = ul0; *(PUSHORT)(pjDst+4) = (USHORT)ul1; *(pjDst+6) = (BYTE)(ul1 >> 16);
pjDst += DeltaDstIn; pjSrc += DeltaSrcIn;
} while (pjDst != pjDstEndY); break; } } }
/******************************Public*Routine******************************\
* * Routine Name * * vSrcOpaqCopyS1D16 * * Routine Description: * * Opaque blt of 1BPP src to destination format * * Arguments: * * pjSrcIn - pointer to beginning of current scan line of src buffer * SrcLeft - left (starting) pixel in src rectangle * DeltaSrcIn - bytes from one src scan line to next * pjDstIn - pointer to beginning of current scan line of Dst buffer * DstLeft - left(first) dst pixel * DstRight - right(last) dst pixel * DeltaDstIn - bytes from one Dst scan line to next * cy - number of scan lines * uF - Foreground color * uB - Background color * * Return Value: * * None * \**************************************************************************/
VOID vSrcOpaqCopyS1D16( PBYTE pjSrcIn, LONG SrcLeft, LONG DeltaSrcIn, PBYTE pjDstIn, LONG DstLeft, LONG DstRight, LONG DeltaDstIn, LONG cy, ULONG uF, ULONG uB, SURFACE *pSurf )
{ BYTE jSrc; LONG ixStart = SrcLeft & 0x07; PUSHORT pusEnd; PUSHORT pusEnd8; PUSHORT pusDst = (PUSHORT)pjDstIn + DstLeft; PBYTE pjSrc = pjSrcIn + (SrcLeft >> 3); LONG cx = DstRight - DstLeft; LONG lDstStride = DeltaDstIn - (cx << 1); LONG lSrcStride = DeltaSrcIn - ((cx + ixStart + 7) >> 3); UCHAR ExpTable[4]; PUSHORT pusEndY = (PUSHORT)((PBYTE)pusDst + DeltaDstIn * cy); LONG StartOffset = min(cx, (8 - ixStart));
//
// build exp table
//
*(PUSHORT)ExpTable = (USHORT)uB; *(PUSHORT)(ExpTable+2) = (USHORT)uF;
do {
pusEnd = pusDst + cx;
//
// do starting pixels
//
if (ixStart) {
jSrc = *pjSrc << ixStart;
pjSrc++;
PUSHORT pusEndSt = pusDst + StartOffset;
do { *pusDst = *(PUSHORT)(ExpTable + ((jSrc & 0x80) >> (7-1))); pusDst++; jSrc <<=1;
} while (pusDst != pusEndSt); }
//
// number of full bytes that can be expanded
//
pusEnd8 = (PUSHORT)((PBYTE)pusDst + (((ULONG_PTR)pusEnd - (ULONG_PTR)pusDst) & ~0x0F));
//
// expand full bytes
//
while (pusDst != pusEnd8) {
jSrc = *pjSrc;
*(pusDst + 0) = *(PUSHORT)(ExpTable + ((jSrc & 0x80) >> (7-1))); *(pusDst + 1) = *(PUSHORT)(ExpTable + ((jSrc & 0x40) >> (6-1))); *(pusDst + 2) = *(PUSHORT)(ExpTable + ((jSrc & 0x20) >> (5-1))); *(pusDst + 3) = *(PUSHORT)(ExpTable + ((jSrc & 0x10) >> (4-1))); *(pusDst + 4) = *(PUSHORT)(ExpTable + ((jSrc & 0x08) >> (3-1))); *(pusDst + 5) = *(PUSHORT)(ExpTable + ((jSrc & 0x04) >> (2-1))); *(pusDst + 6) = *(PUSHORT)(ExpTable + ((jSrc & 0x02) >> (1-1))); *(pusDst + 7) = *(PUSHORT)(ExpTable + ((jSrc & 0x01) << 1));
pjSrc++; pusDst += 8;
}
//
// finish off scan line if needed
//
if (pusDst != pusEnd) {
jSrc = *pjSrc++;
do { *pusDst = *(PUSHORT)(ExpTable + ((jSrc & 0x80) >> (7-1))); jSrc<<=1; pusDst++; } while (pusDst != pusEnd);
}
pusDst = (PUSHORT)((PBYTE)pusDst + lDstStride); pjSrc += lSrcStride;
} while(pusDst != pusEndY);
}
/******************************Public*Routine******************************\
* * Routine Name * * vSrcOpaqCopyS1D24 * * Routine Description: * * Opaque blt of 1BPP src to destination format * * Arguments: * * pjSrcIn - pointer to beginning of current scan line of src buffer * SrcLeft - left (starting) pixel in src rectangle * DeltaSrcIn - bytes from one src scan line to next * pjDstIn - pointer to beginning of current scan line of Dst buffer * DstLeft - left(first) dst pixel * DstRight - right(last) dst pixel * DeltaDstIn - bytes from one Dst scan line to next * cy - number of scan lines * uF - Foreground color * uB - Background color * * Return Value: * * None * \**************************************************************************/
VOID vSrcOpaqCopyS1D24( PBYTE pjSrcIn, LONG SrcLeft, LONG DeltaSrcIn, PBYTE pjDstIn, LONG DstLeft, LONG DstRight, LONG DeltaDstIn, LONG cy, ULONG uF, ULONG uB, SURFACE *pSurf )
{ BYTE jSrc; BYTE F0,F1,F2; BYTE B0,B1,B2; LONG ixStart = SrcLeft & 0x07; PBYTE pjEnd; PBYTE pjEnd8; PBYTE pjDst = pjDstIn + 3 * DstLeft; PBYTE pjSrc = pjSrcIn + (SrcLeft >> 3); LONG cx = DstRight - DstLeft; LONG lDstStride = DeltaDstIn - (cx * 3); LONG lSrcStride = DeltaSrcIn - ((cx + ixStart + 7) >> 3); UCHAR ExpTable[8]; PBYTE pjEndY = pjDst + DeltaDstIn * cy; LONG StartOffset = 3 * (min(cx, (8 - ixStart))); PBYTE pTable;
//
// build exp table
//
*(PULONG)ExpTable = uB; *(PULONG)(ExpTable+4) = uF;
do {
pjEnd = pjDst + 3 * cx;
//
// do starting pixels
//
if (ixStart) {
jSrc = *pjSrc << ixStart;
pjSrc++;
PBYTE pjEndSt = pjDst + StartOffset;
do {
pTable = ExpTable + ((jSrc & 0x80) >> (7-2));
*pjDst = *pTable; *(pjDst+1) = *(pTable+1); *(pjDst+2) = *(pTable+2);
pjDst += 3;
jSrc <<=1;
} while (pjDst != pjEndSt); }
//
// number of full bytes that can be expanded
//
pjEnd8 = pjDst + (24 * (((ULONG_PTR)pjEnd - (ULONG_PTR)pjDst)/24));
//
// expand full bytes
//
while (pjDst != pjEnd8) {
jSrc = *pjSrc;
pTable = ExpTable + ((jSrc & 0x80) >> (7-2));
*(pjDst + 0) = *pTable; *(pjDst + 1) = *(pTable+1); *(pjDst + 2) = *(pTable+2);
pTable = ExpTable + ((jSrc & 0x40) >> (6-2));
*(pjDst + 3) = *pTable; *(pjDst + 4) = *(pTable+1); *(pjDst + 5) = *(pTable+2);
pTable = ExpTable + ((jSrc & 0x20) >> (5-2));
*(pjDst + 6) = *pTable; *(pjDst + 7) = *(pTable+1); *(pjDst + 8) = *(pTable+2);
pTable = ExpTable + ((jSrc & 0x10) >> (4-2));
*(pjDst + 9) = *pTable; *(pjDst + 10) = *(pTable+1); *(pjDst + 11) = *(pTable+2);
pTable = ExpTable + ((jSrc & 0x08) >> (3-2));
*(pjDst + 12) = *pTable; *(pjDst + 13) = *(pTable+1); *(pjDst + 14) = *(pTable+2);
pTable = ExpTable + (jSrc & 0x04);
*(pjDst + 15) = *pTable; *(pjDst + 16) = *(pTable+1); *(pjDst + 17) = *(pTable+2);
pTable = ExpTable + ((jSrc & 0x02) << 1);
*(pjDst + 18) = *pTable; *(pjDst + 19) = *(pTable+1); *(pjDst + 20) = *(pTable+2);
pTable = ExpTable + ((jSrc & 0x01) << 2);
*(pjDst + 21) = *pTable; *(pjDst + 22) = *(pTable+1); *(pjDst + 23) = *(pTable+2);
pjSrc++; pjDst += (3*8);
}
//
// finish off scan line if needed
//
if (pjDst != pjEnd) {
jSrc = *pjSrc++;
do {
pTable = ExpTable + ((jSrc & 0x80) >> (7-2));
*(pjDst + 0) = *pTable; *(pjDst + 1) = *(pTable+1); *(pjDst + 2) = *(pTable+2);
jSrc<<=1; pjDst+= 3; } while (pjDst != pjEnd);
}
pjDst = (PBYTE)((PBYTE)pjDst + lDstStride); pjSrc += lSrcStride;
} while(pjDst != pjEndY);
}
/******************************Public*Routine******************************\
* * Routine Name * * vSrcOpaqCopyS1D32 * * Routine Description: * * Opaque blt of 1BPP src to destination format * * Arguments: * * pjSrcIn - pointer to beginning of current scan line of src buffer * SrcLeft - left (starting) pixel in src rectangle * DeltaSrcIn - bytes from one src scan line to next * pjDstIn - pointer to beginning of current scan line of Dst buffer * DstLeft - left(first) dst pixel * DstRight - right(last) dst pixel * DeltaDstIn - bytes from one Dst scan line to next * cy - number of scan lines * uF - Foreground color * uB - Background color * * Return Value: * * None * \**************************************************************************/
VOID vSrcOpaqCopyS1D32( PBYTE pjSrcIn, LONG SrcLeft, LONG DeltaSrcIn, PBYTE pjDstIn, LONG DstLeft, LONG DstRight, LONG DeltaDstIn, LONG cy, ULONG uF, ULONG uB, SURFACE *pSurf )
{ BYTE jSrc; LONG ixStart = SrcLeft & 0x07; PULONG pulEnd; PULONG pulEnd8; PULONG pulDst = (PULONG)pjDstIn + DstLeft; PBYTE pjSrc = pjSrcIn + (SrcLeft >> 3); LONG cx = DstRight - DstLeft; LONG lDstStride = DeltaDstIn - (cx << 2); LONG lSrcStride = DeltaSrcIn - ((cx + ixStart + 7) >> 3); UCHAR ExpTable[8]; PULONG pulEndY = (PULONG)((PBYTE)pulDst + DeltaDstIn * cy); LONG StartOffset = min(cx, (8 - ixStart));
//
// build exp table
//
*(PULONG)ExpTable = uB; *(PULONG)(ExpTable+4) = uF;
do {
pulEnd = pulDst + cx;
//
// do starting pixels
//
if (ixStart) {
jSrc = *pjSrc << ixStart;
pjSrc++;
PULONG pulEndSt = pulDst + StartOffset;
do { *pulDst = *(PULONG)(ExpTable + ((jSrc & 0x80) >> (7-2))); pulDst++; jSrc <<=1;
} while (pulDst != pulEndSt); }
//
// number of full bytes that can be expanded
//
pulEnd8 = (PULONG)((PBYTE)pulDst + (((ULONG_PTR)pulEnd - (ULONG_PTR)pulDst) & ~0x1F));
//
// expand full bytes
//
while (pulDst != pulEnd8) {
jSrc = *pjSrc;
*(pulDst + 0) = *(PULONG)(ExpTable + ((jSrc & 0x80) >> (7-2))); *(pulDst + 1) = *(PULONG)(ExpTable + ((jSrc & 0x40) >> (6-2))); *(pulDst + 2) = *(PULONG)(ExpTable + ((jSrc & 0x20) >> (5-2))); *(pulDst + 3) = *(PULONG)(ExpTable + ((jSrc & 0x10) >> (4-2))); *(pulDst + 4) = *(PULONG)(ExpTable + ((jSrc & 0x08) >> (3-2))); *(pulDst + 5) = *(PULONG)(ExpTable + ((jSrc & 0x04) >> (2-2))); *(pulDst + 6) = *(PULONG)(ExpTable + ((jSrc & 0x02) << 1)); *(pulDst + 7) = *(PULONG)(ExpTable + ((jSrc & 0x01) << 2));
pjSrc++; pulDst += 8;
}
//
// finish off scan line if needed
//
if (pulDst != pulEnd) {
jSrc = *pjSrc++;
do { *pulDst = *(PULONG)(ExpTable + ((jSrc & 0x80) >> (7-2))); jSrc<<=1; pulDst++; } while (pulDst != pulEnd);
}
pulDst = (PULONG)((PBYTE)pulDst + lDstStride); pjSrc += lSrcStride;
} while(pulDst != pulEndY);
}
VOID vSrcTranCopyError( PBYTE pjSrcIn, LONG SrcLeft, LONG DeltaSrcIn, PBYTE pjDstIn, LONG DstLeft, LONG DstRight, LONG DeltaDstIn, LONG cy, ULONG uF, ULONG uB, SURFACE *pSurf ) { /**/WARNING("!!vSrcTranCopyError!!\n"); }
/******************************Public*Routine******************************\
* vRectBlt * * 'Extra' rectangle on a monochrome dib. * * History: * Thu Dec 03 11:22:21 1992 -by- Hock San Lee [hockl] * Wrote it. \**************************************************************************/
VOID vRectBlt ( PBYTE pjMonoDib, ULONG cjScanMono, LONG xleft, LONG ytop, LONG xright, LONG ybottom ) { PWORD pwDst; ULONG cy = (ULONG) (ybottom - ytop);
//
// Left mask
//
static WORD awMaskL[16] = { 0x0000, 0x0080, 0x00C0, 0x00E0, 0x00F0, 0x00F8, 0x00FC, 0x00FE, 0x00FF, 0x80FF, 0xC0FF, 0xE0FF, 0xF0FF, 0xF8FF, 0xFCFF, 0xFEFF};
//
// Right mask
//
static WORD awMaskR[16] = { 0xFFFF, 0xFF7F, 0xFF3F, 0xFF1F, 0xFF0F, 0xFF07, 0xFF03, 0xFF01, 0xFF00, 0x7F00, 0x3F00, 0x1F00, 0x0F00, 0x0700, 0x0300, 0x0100};
ASSERTGDI(xleft < xright && ytop < ybottom, "vRectBlt: bad rectangle");
pjMonoDib += (ytop * cjScanMono); pjMonoDib += (xleft >> 4 << 1);
//
// Since the mono dib is word-aligned, we will set one word at a time
// in the main loop.
//
LONG cWords = (xright >> 4) - ((xleft + 0xF) >> 4);
do {
pwDst = (PWORD) pjMonoDib; pjMonoDib += cjScanMono;
//
// Handle the special case where both xleft and xright are in
// the same word and ((xleft & 0xF) != 0) and ((xright & 0xF) != 0).
//
if (cWords < 0) { WORD wMask = awMaskR[xleft & 0xF] & awMaskL[xright & 0xF]; *pwDst = *pwDst | wMask; continue; }
//
// Handle the first partial source word.
//
if (xleft & 0xF) { *pwDst = *pwDst | awMaskR[xleft & 0xF]; pwDst++; }
//
// Handle the main loop for each source word.
//
for (LONG i = cWords; i > 0; i--) { *pwDst++ = (WORD) ~0; }
//
// Handle the last partial source word.
//
if (xright & 0xF) { *pwDst = *pwDst | awMaskL[xright & 0xF]; } } while (--cy); }
VOID vRectBlt4 ( PBYTE pj4bpp, ULONG cjScanMono, LONG xleft, LONG ytop, LONG xright, LONG ybottom ) { // Put in a rectangle by hand. This is a matter of setting each
// of the appropriate nibbles to 0xf
}
VOID vRectBlt8 ( PBYTE pj8bpp, ULONG cjScanMono, LONG xleft, LONG ytop, LONG xright, LONG ybottom ) { // Put in a rectangle by hand. This is a matter of setting each
// of the appropriate pixels to ????
RIP("cleartype vRectBlt8 \n");
}
/******************************Public*Routine******************************\
* STROBJ_dwGetCodePage * * Code page corresponding to the current TextOut * * History: * Wed Jan 24 11:09:21 1996 -by- Tessie Wu [tessiew] * Wrote it. \**************************************************************************/
extern "C" DWORD STROBJ_dwGetCodePage( STROBJ* pstro) { return ( ((ESTROBJ*)pstro)->dwCodePage ); }
/******************************Public*Routine******************************\
* * more accelerators for ps driver: * * FIX APIENTRY STROBJ_fxCharacterExtra(STROBJ *pstro) * FIX APIENTRY STROBJ_fxBreakExtra(STROBJ *pstro) * Effects: * * History: * 25-Oct-1996 -by- Bodin Dresevic [BodinD] * Wrote it. \**************************************************************************/
extern "C" FIX APIENTRY STROBJ_fxCharacterExtra(STROBJ *pstro) { if (((ESTROBJ*)pstro)->flAccel & SO_CHARACTER_EXTRA) return ((ESTROBJ*)pstro)->xExtra; else return 0; }
extern "C" FIX APIENTRY STROBJ_fxBreakExtra(STROBJ *pstro) { if (((ESTROBJ*)pstro)->flAccel & SO_BREAK_EXTRA) return ((ESTROBJ*)pstro)->xBreakExtra; else return 0; }
|