You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
2880 lines
96 KiB
2880 lines
96 KiB
/****************************************************************************/
|
|
// wghint.c
|
|
//
|
|
// Glyph handler - internal Windows specific
|
|
//
|
|
// Copyright (C) 1997-1999 Microsoft Corporation 1997-1999
|
|
/****************************************************************************/
|
|
|
|
#include <adcg.h>
|
|
|
|
extern "C" {
|
|
#define TRC_GROUP TRC_GROUP_CORE
|
|
#define TRC_FILE "wghint"
|
|
#include <atrcapi.h>
|
|
}
|
|
#define TSC_HR_FILEID TSC_HR_GHINT_CPP
|
|
|
|
#include "autil.h"
|
|
#include "gh.h"
|
|
#include "uh.h"
|
|
#include <wxlint.h>
|
|
|
|
|
|
|
|
|
|
#if defined(OS_WINCE) || defined(OS_WINNT)
|
|
|
|
#ifdef DC_HICOLOR
|
|
/******************************Public*Routine******************************\
|
|
* vSrcOpaqCopyS1D8_24
|
|
*
|
|
* Opaque blt of 1BPP src to 24bpp destination
|
|
*
|
|
* 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
|
|
* fgCol - Foreground color
|
|
* bgCol - Background color
|
|
\**************************************************************************/
|
|
VOID CGH::vSrcOpaqCopyS1D8_24(
|
|
PBYTE pjSrcIn,
|
|
LONG SrcLeft,
|
|
LONG DeltaSrcIn,
|
|
PBYTE pjDstIn,
|
|
LONG DstLeft,
|
|
LONG DstRight,
|
|
LONG DeltaDstIn,
|
|
LONG cy,
|
|
DCRGB fgCol,
|
|
DCRGB bgCol)
|
|
{
|
|
// We access the 1bpp source a byte at a time, so we have to start accessing
|
|
// the destination on a corresponding 8-pel aligned left edge
|
|
ULONG LeftAln = (DstLeft & ~0x07);
|
|
ULONG LeftEdgeMask = 0xFF >> (DstLeft & 0x07);
|
|
ULONG RightAln = (DstRight & ~0x07);
|
|
ULONG AlnDelta = RightAln - LeftAln;
|
|
|
|
LONG DeltaDst;
|
|
LONG DeltaSrc;
|
|
|
|
PBYTE pjDstEndY;
|
|
PBYTE pjSrc;
|
|
PBYTE pjDst;
|
|
|
|
DC_BEGIN_FN("vSrcTranCopyS1D8_24");
|
|
|
|
// calculate the pel-aligned pointers and row deltas
|
|
pjDst = pjDstIn + LeftAln * 3;
|
|
pjDstEndY = pjDst + cy * DeltaDstIn * 3;
|
|
|
|
pjSrc = pjSrcIn + (SrcLeft >> 3);
|
|
|
|
DeltaSrc = DeltaSrcIn - (AlnDelta >> 3);
|
|
DeltaDst = (DeltaDstIn - AlnDelta) * 3;
|
|
|
|
// make sure at least 1 QWORD needs copying
|
|
if (RightAln != LeftAln)
|
|
{
|
|
|
|
// for each row...
|
|
do
|
|
{
|
|
PBYTE pjDstEnd = pjDst + AlnDelta * 3;
|
|
BYTE currentPels;
|
|
ULONG i;
|
|
|
|
// Mask off the left edge
|
|
currentPels = (BYTE)(*pjSrc & (BYTE)(LeftEdgeMask));
|
|
|
|
for (i = 0; i < 8; i++)
|
|
{
|
|
if ((0xff >> i) > (BYTE)(LeftEdgeMask))
|
|
{
|
|
pjDst += 3;
|
|
}
|
|
else if ((currentPels & 0x80) == 0)
|
|
{
|
|
*pjDst++ = bgCol.blue;
|
|
*pjDst++ = bgCol.green;
|
|
*pjDst++ = bgCol.red;
|
|
}
|
|
else
|
|
{
|
|
*pjDst++ = fgCol.blue;
|
|
*pjDst++ = fgCol.green;
|
|
*pjDst++ = fgCol.red;
|
|
}
|
|
currentPels = (BYTE)(currentPels << 1);
|
|
}
|
|
pjSrc ++;
|
|
|
|
// now do the rest of the row
|
|
while (pjDst != pjDstEnd)
|
|
{
|
|
currentPels = *pjSrc;
|
|
if (currentPels != 0)
|
|
{
|
|
for (i = 0; i < 8 ; i++)
|
|
{
|
|
if ((currentPels & 0x80) == 0)
|
|
{
|
|
*pjDst++ = bgCol.blue;
|
|
*pjDst++ = bgCol.green;
|
|
*pjDst++ = bgCol.red;
|
|
}
|
|
else
|
|
{
|
|
*pjDst++ = fgCol.blue;
|
|
*pjDst++ = fgCol.green;
|
|
*pjDst++ = fgCol.red;
|
|
}
|
|
currentPels = (BYTE)(currentPels << 1);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
for (i = 0; i < 8 ; i++)
|
|
{
|
|
*pjDst++ = bgCol.blue;
|
|
*pjDst++ = bgCol.green;
|
|
*pjDst++ = bgCol.red;
|
|
}
|
|
}
|
|
|
|
pjSrc++;
|
|
}
|
|
|
|
pjDst += DeltaDst;
|
|
pjSrc += DeltaSrc;
|
|
|
|
} while (pjDst != pjDstEndY);
|
|
}
|
|
|
|
// Now fill in the right edge
|
|
RightAln = DstRight & 0x07;
|
|
if (RightAln)
|
|
{
|
|
BYTE currentPels;
|
|
BOOL bSameQWord = ((DstLeft) & ~0x07) == ((DstRight) & ~0x07);
|
|
|
|
LeftAln = DstLeft & 0x07;
|
|
|
|
// if left and right edges are in same qword handle with masked
|
|
// read-modify-write
|
|
if (bSameQWord)
|
|
{
|
|
LONG xCount;
|
|
LONG lDeltaDst;
|
|
PBYTE pjDstEnd;
|
|
|
|
xCount = RightAln - LeftAln;
|
|
|
|
// sanity checks!
|
|
if (xCount <= 0)
|
|
{
|
|
return;
|
|
}
|
|
|
|
lDeltaDst = (DeltaDstIn - xCount) * 3;
|
|
|
|
pjDst = pjDstIn + DstLeft * 3;
|
|
pjDstEndY = pjDst + cy * DeltaDstIn * 3;
|
|
pjSrc = pjSrcIn + (SrcLeft >> 3);
|
|
|
|
// expand, one src byte is all that's required
|
|
do
|
|
{
|
|
// load src and shift into place
|
|
currentPels = *pjSrc;
|
|
currentPels <<= LeftAln;
|
|
pjDstEnd = pjDst + xCount * 3;
|
|
|
|
do
|
|
{
|
|
if ((currentPels & 0x80) == 0)
|
|
{
|
|
*pjDst++ = bgCol.blue;
|
|
*pjDst++ = bgCol.green;
|
|
*pjDst++ = bgCol.red;
|
|
}
|
|
else
|
|
{
|
|
*pjDst++ = fgCol.blue;
|
|
*pjDst++ = fgCol.green;
|
|
*pjDst++ = fgCol.red;
|
|
}
|
|
|
|
currentPels = (BYTE)(currentPels << 1);
|
|
|
|
} while (pjDst != pjDstEnd);
|
|
|
|
pjDst += lDeltaDst;
|
|
pjSrc += DeltaSrcIn;
|
|
|
|
} while (pjDst != pjDstEndY);
|
|
|
|
return;
|
|
}
|
|
else
|
|
{
|
|
BYTE currentPels;
|
|
LONG lDeltaDst = (DeltaDstIn - RightAln) * 3;
|
|
PBYTE pjDstEnd;
|
|
ULONG i;
|
|
|
|
pjDst = pjDstIn + (DstRight & ~0x07) * 3;
|
|
pjDstEndY = pjDst + cy * DeltaDstIn * 3;
|
|
pjSrc = pjSrcIn + ((SrcLeft + (DstRight - DstLeft)) >> 3);
|
|
|
|
do
|
|
{
|
|
// read src
|
|
currentPels = *pjSrc;
|
|
|
|
if (currentPels != 0)
|
|
{
|
|
pjDstEnd = pjDst + RightAln * 3;
|
|
do
|
|
{
|
|
if ((currentPels & 0x80) == 0)
|
|
{
|
|
*pjDst++ = bgCol.blue;
|
|
*pjDst++ = bgCol.green;
|
|
*pjDst++ = bgCol.red;
|
|
}
|
|
else
|
|
{
|
|
*pjDst++ = fgCol.blue;
|
|
*pjDst++ = fgCol.green;
|
|
*pjDst++ = fgCol.red;
|
|
}
|
|
currentPels = (BYTE)(currentPels << 1);
|
|
|
|
} while (pjDst != pjDstEnd);
|
|
}
|
|
else
|
|
{
|
|
// short cut for zero
|
|
for (i = 0; i < RightAln ; i++)
|
|
{
|
|
*pjDst++ = bgCol.blue;
|
|
*pjDst++ = bgCol.green;
|
|
*pjDst++ = bgCol.red;
|
|
}
|
|
}
|
|
|
|
pjDst += lDeltaDst;
|
|
pjSrc += DeltaSrcIn;
|
|
|
|
} while (pjDst != pjDstEndY);
|
|
}
|
|
}
|
|
|
|
DC_END_FN();
|
|
|
|
}
|
|
|
|
/******************************Public*Routine******************************\
|
|
* vSrcOpaqCopyS1D8_16
|
|
*
|
|
* Opaque blt of 1BPP src to 16bpp destination
|
|
*
|
|
* 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
|
|
* fgCol - Foreground color
|
|
* bgCol - Background color
|
|
\**************************************************************************/
|
|
VOID CGH::vSrcOpaqCopyS1D8_16(
|
|
PBYTE pjSrcIn,
|
|
LONG SrcLeft,
|
|
LONG DeltaSrcIn,
|
|
PBYTE pjDstIn,
|
|
LONG DstLeft,
|
|
LONG DstRight,
|
|
LONG DeltaDstIn,
|
|
LONG cy,
|
|
ULONG fgCol,
|
|
ULONG bgCol)
|
|
{
|
|
// We access the 1bpp source a byte at a time, so we have to start accessing
|
|
// the destination on a corresponding 8-pel aligned left edge
|
|
ULONG LeftAln = (DstLeft & ~0x07);
|
|
ULONG LeftEdgeMask = 0xFF >> (DstLeft & 0x07);
|
|
ULONG RightAln = (DstRight & ~0x07);
|
|
ULONG AlnDelta = RightAln - LeftAln;
|
|
|
|
LONG DeltaDst;
|
|
LONG DeltaSrc;
|
|
|
|
PBYTE pjDstEndY;
|
|
PBYTE pjSrc;
|
|
PBYTE pjDst;
|
|
|
|
DC_BEGIN_FN("vSrcTranCopyS1D8_16");
|
|
|
|
// calculate the pel-aligned pointers and row deltas
|
|
pjDst = pjDstIn + LeftAln * 2;
|
|
pjDstEndY = pjDst + cy * DeltaDstIn * 2;
|
|
|
|
pjSrc = pjSrcIn + (SrcLeft >> 3);
|
|
|
|
DeltaSrc = DeltaSrcIn - (AlnDelta >> 3);
|
|
DeltaDst = (DeltaDstIn - AlnDelta) * 2;
|
|
|
|
// make sure at least 1 QWORD needs copying
|
|
if (RightAln != LeftAln)
|
|
{
|
|
|
|
// for each row...
|
|
do
|
|
{
|
|
PBYTE pjDstEnd = pjDst + AlnDelta * 2;
|
|
BYTE currentPels;
|
|
ULONG i;
|
|
|
|
// Mask off the left edge
|
|
currentPels = (BYTE)(*pjSrc & (BYTE)(LeftEdgeMask));
|
|
|
|
for (i = 0; i < 8; i++)
|
|
{
|
|
if ((0xff >> i) <= (BYTE)(LeftEdgeMask))
|
|
{
|
|
if ((currentPels & 0x80) == 0)
|
|
{
|
|
*(UINT16 *)pjDst = (UINT16)bgCol;
|
|
|
|
}
|
|
else
|
|
{
|
|
*(UINT16 *)pjDst = (UINT16)fgCol;
|
|
}
|
|
}
|
|
pjDst += 2;
|
|
currentPels = (BYTE)(currentPels << 1);
|
|
}
|
|
pjSrc ++;
|
|
|
|
// now do the rest of the row
|
|
while (pjDst != pjDstEnd)
|
|
{
|
|
currentPels = *pjSrc;
|
|
if (currentPels != 0)
|
|
{
|
|
for (i = 0; i < 8 ; i++)
|
|
{
|
|
if ((currentPels & 0x80) == 0)
|
|
{
|
|
*(UINT16 *)pjDst = (UINT16)bgCol;
|
|
}
|
|
else
|
|
{
|
|
*(UINT16 *)pjDst = (UINT16)fgCol;
|
|
}
|
|
pjDst += 2;
|
|
currentPels = (BYTE)(currentPels << 1);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
for (i = 0; i < 8 ; i++)
|
|
{
|
|
*(UINT16 *)pjDst = (UINT16)bgCol;
|
|
pjDst += 2;
|
|
}
|
|
}
|
|
|
|
pjSrc++;
|
|
}
|
|
|
|
pjDst += DeltaDst;
|
|
pjSrc += DeltaSrc;
|
|
|
|
} while (pjDst != pjDstEndY);
|
|
}
|
|
|
|
// Now fill in the right edge
|
|
RightAln = DstRight & 0x07;
|
|
if (RightAln)
|
|
{
|
|
BYTE currentPels;
|
|
BOOL bSameQWord = ((DstLeft) & ~0x07) == ((DstRight) & ~0x07);
|
|
|
|
LeftAln = DstLeft & 0x07;
|
|
|
|
// if left and right edges are in same qword handle with masked
|
|
// read-modify-write
|
|
if (bSameQWord)
|
|
{
|
|
LONG xCount;
|
|
LONG lDeltaDst;
|
|
PBYTE pjDstEnd;
|
|
|
|
xCount = RightAln - LeftAln;
|
|
|
|
// sanity checks!
|
|
if (xCount <= 0)
|
|
{
|
|
return;
|
|
}
|
|
|
|
lDeltaDst = (DeltaDstIn - xCount) * 2;
|
|
|
|
pjDst = pjDstIn + DstLeft * 2;
|
|
pjDstEndY = pjDst + cy * DeltaDstIn * 2;
|
|
pjSrc = pjSrcIn + (SrcLeft >> 3);
|
|
|
|
// expand, one src byte is all that's required
|
|
do
|
|
{
|
|
// load src and shift into place
|
|
currentPels = *pjSrc;
|
|
currentPels <<= LeftAln;
|
|
pjDstEnd = pjDst + xCount * 2;
|
|
|
|
do
|
|
{
|
|
if ((currentPels & 0x80) == 0)
|
|
{
|
|
*(UINT16 *)pjDst = (UINT16)bgCol;
|
|
|
|
}
|
|
else
|
|
{
|
|
*(UINT16 *)pjDst = (UINT16)fgCol;
|
|
}
|
|
pjDst += 2;
|
|
currentPels = (BYTE)(currentPels << 1);
|
|
|
|
} while (pjDst != pjDstEnd);
|
|
|
|
pjDst += lDeltaDst;
|
|
pjSrc += DeltaSrcIn;
|
|
|
|
} while (pjDst != pjDstEndY);
|
|
|
|
return;
|
|
}
|
|
else
|
|
{
|
|
BYTE currentPels;
|
|
LONG lDeltaDst = (DeltaDstIn - RightAln) * 2;
|
|
PBYTE pjDstEnd;
|
|
ULONG i;
|
|
|
|
pjDst = pjDstIn + (DstRight & ~0x07) * 2;
|
|
pjDstEndY = pjDst + cy * DeltaDstIn * 2;
|
|
pjSrc = pjSrcIn + ((SrcLeft + (DstRight - DstLeft)) >> 3);
|
|
|
|
do
|
|
{
|
|
// read src
|
|
currentPels = *pjSrc;
|
|
|
|
if (currentPels != 0)
|
|
{
|
|
pjDstEnd = pjDst + RightAln * 2;
|
|
do
|
|
{
|
|
if ((currentPels & 0x80) == 0)
|
|
{
|
|
*(UINT16 *)pjDst = (UINT16)bgCol;
|
|
|
|
}
|
|
else
|
|
{
|
|
*(UINT16 *)pjDst = (UINT16)fgCol;
|
|
}
|
|
pjDst += 2;
|
|
currentPels = (BYTE)(currentPels << 1);
|
|
|
|
} while (pjDst != pjDstEnd);
|
|
}
|
|
else
|
|
{
|
|
// short cut for zero
|
|
for (i = 0; i < RightAln ; i++)
|
|
{
|
|
*(UINT16 *)pjDst = (UINT16)bgCol;
|
|
pjDst += 2;
|
|
}
|
|
}
|
|
|
|
pjDst += lDeltaDst;
|
|
pjSrc += DeltaSrcIn;
|
|
|
|
} while (pjDst != pjDstEndY);
|
|
}
|
|
}
|
|
|
|
DC_END_FN();
|
|
}
|
|
#endif // HICOLOR
|
|
|
|
/******************************Public*Routine******************************\
|
|
* vSrcOpaqCopyS1D8
|
|
*
|
|
* 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
|
|
\**************************************************************************/
|
|
VOID CGH::vSrcOpaqCopyS1D8(
|
|
PBYTE pjSrcIn,
|
|
LONG SrcLeft,
|
|
LONG DeltaSrcIn,
|
|
PBYTE pjDstIn,
|
|
LONG DstLeft,
|
|
LONG DstRight,
|
|
LONG DeltaDstIn,
|
|
LONG cy,
|
|
ULONG uF,
|
|
ULONG uB)
|
|
{
|
|
// 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 bSameQWord = ((DstLeft) & ~0x07) == ((DstRight) & ~0x07);
|
|
ULONG ul0,ul1;
|
|
|
|
// if left and right edges are in same qword handle with masked
|
|
// read-modify-write
|
|
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;
|
|
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;
|
|
}
|
|
}
|
|
}
|
|
|
|
#ifdef DC_HICOLOR
|
|
/******************************Public*Routine******************************\
|
|
* vSrcTranCopyS1D8_24
|
|
*
|
|
* Transparent blt of 1BPP src to 24bpp destination
|
|
* 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
|
|
* fgCol - Foreground color
|
|
\**************************************************************************/
|
|
VOID CGH::vSrcTranCopyS1D8_24(
|
|
PBYTE pjSrcIn,
|
|
LONG SrcLeft,
|
|
LONG DeltaSrcIn,
|
|
PBYTE pjDstIn,
|
|
LONG DstLeft,
|
|
LONG DstRight,
|
|
LONG DeltaDstIn,
|
|
LONG cy,
|
|
DCRGB fgCol)
|
|
{
|
|
// We access the 1bpp source a byte at a time, so we have to start accessing
|
|
// the destination on a corresponding 8-pel aligned left edge
|
|
ULONG LeftAln = (DstLeft & ~0x07);
|
|
ULONG LeftEdgeMask = 0xFF >> (DstLeft & 0x07);
|
|
ULONG RightAln = (DstRight & ~0x07);
|
|
ULONG AlnDelta = RightAln - LeftAln;
|
|
|
|
LONG DeltaDst;
|
|
LONG DeltaSrc;
|
|
|
|
PBYTE pjDstEndY;
|
|
PBYTE pjSrc;
|
|
PBYTE pjDst;
|
|
|
|
DC_BEGIN_FN("vSrcTranCopyS1D8_24");
|
|
|
|
// calculate the pel-aligned pointers and row deltas
|
|
pjDst = pjDstIn + LeftAln * 3;
|
|
pjDstEndY = pjDst + cy * DeltaDstIn * 3;
|
|
|
|
pjSrc = pjSrcIn + (SrcLeft >> 3);
|
|
|
|
DeltaSrc = DeltaSrcIn - (AlnDelta >> 3);
|
|
DeltaDst = (DeltaDstIn - AlnDelta) * 3;
|
|
|
|
// make sure at least 1 QWORD needs copying
|
|
if (RightAln != LeftAln)
|
|
{
|
|
|
|
// for each row...
|
|
do
|
|
{
|
|
PBYTE pjDstEnd = pjDst + AlnDelta * 3;
|
|
|
|
// Mask off the left edge
|
|
BYTE currentPels = (BYTE)(*pjSrc & (BYTE)(LeftEdgeMask));
|
|
|
|
if (currentPels != 0)
|
|
{
|
|
int i;
|
|
|
|
for (i = 0; i < 8 ; i++)
|
|
{
|
|
if ((currentPels & 0x80) == 0)
|
|
{
|
|
pjDst += 3;
|
|
}
|
|
else
|
|
{
|
|
*pjDst++ = fgCol.blue;
|
|
*pjDst++ = fgCol.green;
|
|
*pjDst++ = fgCol.red;
|
|
}
|
|
currentPels = (BYTE)(currentPels << 1);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
pjDst += 24;
|
|
}
|
|
|
|
pjSrc ++;
|
|
|
|
// now do the rest of the row
|
|
while (pjDst != pjDstEnd)
|
|
{
|
|
currentPels = *pjSrc;
|
|
if (currentPels != 0)
|
|
{
|
|
int i;
|
|
|
|
for (i = 0; i < 8 ; i++)
|
|
{
|
|
if ((currentPels & 0x80) == 0)
|
|
{
|
|
pjDst += 3;
|
|
}
|
|
else
|
|
{
|
|
*pjDst++ = fgCol.blue;
|
|
*pjDst++ = fgCol.green;
|
|
*pjDst++ = fgCol.red;
|
|
}
|
|
currentPels = (BYTE)(currentPels << 1);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
pjDst += 24;
|
|
}
|
|
|
|
pjSrc++;
|
|
}
|
|
|
|
pjDst += DeltaDst;
|
|
pjSrc += DeltaSrc;
|
|
|
|
} while (pjDst != pjDstEndY);
|
|
}
|
|
|
|
// Now fill in the right edge
|
|
RightAln = DstRight & 0x07;
|
|
if (RightAln)
|
|
{
|
|
BYTE currentPels;
|
|
BOOL bSameQWord = ((DstLeft) & ~0x07) == ((DstRight) & ~0x07);
|
|
|
|
LeftAln = DstLeft & 0x07;
|
|
|
|
// if left and right edges are in same qword handle with masked
|
|
// read-modify-write
|
|
if (bSameQWord)
|
|
{
|
|
LONG xCount;
|
|
LONG lDeltaDst;
|
|
PBYTE pjDstEnd;
|
|
|
|
xCount = RightAln - LeftAln;
|
|
|
|
// sanity checks!
|
|
if (xCount <= 0)
|
|
{
|
|
return;
|
|
}
|
|
|
|
lDeltaDst = (DeltaDstIn - xCount) * 3;
|
|
|
|
pjDst = pjDstIn + DstLeft * 3;
|
|
pjDstEndY = pjDst + cy * DeltaDstIn * 3;
|
|
pjSrc = pjSrcIn + (SrcLeft >> 3);
|
|
|
|
// expand, one src byte is all that's required
|
|
do
|
|
{
|
|
// load src and shift into place
|
|
currentPels = *pjSrc;
|
|
currentPels <<= LeftAln;
|
|
pjDstEnd = pjDst + xCount * 3;
|
|
|
|
do
|
|
{
|
|
if ((currentPels & 0x80) == 0)
|
|
{
|
|
pjDst += 3;
|
|
}
|
|
else
|
|
{
|
|
*pjDst++ = fgCol.blue;
|
|
*pjDst++ = fgCol.green;
|
|
*pjDst++ = fgCol.red;
|
|
}
|
|
|
|
currentPels = (BYTE)(currentPels << 1);
|
|
|
|
} while (pjDst != pjDstEnd);
|
|
|
|
pjDst += lDeltaDst;
|
|
pjSrc += DeltaSrcIn;
|
|
|
|
} while (pjDst != pjDstEndY);
|
|
|
|
return;
|
|
}
|
|
else
|
|
{
|
|
BYTE currentPels;
|
|
LONG lDeltaDst = (DeltaDstIn - RightAln) * 3;
|
|
PBYTE pjDstEnd;
|
|
|
|
pjDst = pjDstIn + (DstRight & ~0x07) * 3;
|
|
pjDstEndY = pjDst + cy * DeltaDstIn * 3;
|
|
pjSrc = pjSrcIn + ((SrcLeft + (DstRight - DstLeft)) >> 3);
|
|
|
|
do
|
|
{
|
|
// read src
|
|
currentPels = *pjSrc;
|
|
|
|
if (currentPels != 0)
|
|
{
|
|
pjDstEnd = pjDst + RightAln * 3;
|
|
do
|
|
{
|
|
if ((currentPels & 0x80) == 0)
|
|
{
|
|
pjDst += 3;
|
|
}
|
|
else
|
|
{
|
|
*pjDst++ = fgCol.blue;
|
|
*pjDst++ = fgCol.green;
|
|
*pjDst++ = fgCol.red;
|
|
}
|
|
currentPels = (BYTE)(currentPels << 1);
|
|
|
|
} while (pjDst != pjDstEnd);
|
|
}
|
|
else
|
|
{
|
|
// short cut for zero
|
|
pjDst += RightAln * 3;
|
|
}
|
|
|
|
pjDst += lDeltaDst;
|
|
pjSrc += DeltaSrcIn;
|
|
|
|
} while (pjDst != pjDstEndY);
|
|
}
|
|
}
|
|
|
|
DC_END_FN();
|
|
}
|
|
|
|
|
|
/******************************Public*Routine******************************\
|
|
* vSrcTranCopyS1D8_16
|
|
*
|
|
* Transparent blt of 1BPP src to 16bpp destination
|
|
* 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
|
|
* fgCol - Foreground color
|
|
\**************************************************************************/
|
|
VOID CGH::vSrcTranCopyS1D8_16(
|
|
PBYTE pjSrcIn,
|
|
LONG SrcLeft,
|
|
LONG DeltaSrcIn,
|
|
PBYTE pjDstIn,
|
|
LONG DstLeft,
|
|
LONG DstRight,
|
|
LONG DeltaDstIn,
|
|
LONG cy,
|
|
ULONG fgCol)
|
|
{
|
|
// We access the 1bpp source a byte at a time, so we have to start accessing
|
|
// the destination on a corresponding 8-pel aligned left edge
|
|
ULONG LeftAln = (DstLeft & ~0x07);
|
|
ULONG LeftEdgeMask = 0xFF >> (DstLeft & 0x07);
|
|
ULONG RightAln = (DstRight & ~0x07);
|
|
ULONG AlnDelta = RightAln - LeftAln;
|
|
|
|
LONG DeltaDst;
|
|
LONG DeltaSrc;
|
|
|
|
PBYTE pjDstEndY;
|
|
PBYTE pjSrc;
|
|
PBYTE pjDst;
|
|
|
|
DC_BEGIN_FN("vSrcTranCopyS1D8_16");
|
|
|
|
// calculate the pel-aligned pointers and row deltas
|
|
pjDst = pjDstIn + LeftAln * 2;
|
|
pjDstEndY = pjDst + cy * DeltaDstIn * 2;
|
|
|
|
pjSrc = pjSrcIn + (SrcLeft >> 3);
|
|
|
|
DeltaSrc = DeltaSrcIn - (AlnDelta >> 3);
|
|
DeltaDst = (DeltaDstIn - AlnDelta) * 2;
|
|
|
|
// make sure at least 1 QWORD needs copying
|
|
if (RightAln != LeftAln)
|
|
{
|
|
|
|
// for each row...
|
|
do
|
|
{
|
|
PBYTE pjDstEnd = pjDst + AlnDelta * 2;
|
|
|
|
// Mask off the left edge
|
|
BYTE currentPels = (BYTE)(*pjSrc & (BYTE)(LeftEdgeMask));
|
|
|
|
if (currentPels != 0)
|
|
{
|
|
int i;
|
|
|
|
for (i = 0; i < 8 ; i++)
|
|
{
|
|
if (currentPels & 0x80)
|
|
{
|
|
*(UINT16 *)pjDst = (UINT16)fgCol;
|
|
}
|
|
pjDst += 2;
|
|
currentPels = (BYTE)(currentPels << 1);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
pjDst += 16;
|
|
}
|
|
|
|
pjSrc ++;
|
|
|
|
// now do the rest of the row
|
|
while (pjDst != pjDstEnd)
|
|
{
|
|
currentPels = *pjSrc;
|
|
if (currentPels != 0)
|
|
{
|
|
int i;
|
|
|
|
for (i = 0; i < 8 ; i++)
|
|
{
|
|
if (currentPels & 0x80)
|
|
{
|
|
*(UINT16 *)pjDst = (UINT16)fgCol;
|
|
}
|
|
pjDst += 2;
|
|
currentPels = (BYTE)(currentPels << 1);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
pjDst += 16;
|
|
}
|
|
|
|
pjSrc++;
|
|
}
|
|
|
|
pjDst += DeltaDst;
|
|
pjSrc += DeltaSrc;
|
|
|
|
} while (pjDst != pjDstEndY);
|
|
}
|
|
|
|
// Now fill in the right edge
|
|
RightAln = DstRight & 0x07;
|
|
if (RightAln)
|
|
{
|
|
BYTE currentPels;
|
|
BOOL bSameQWord = ((DstLeft) & ~0x07) == ((DstRight) & ~0x07);
|
|
|
|
LeftAln = DstLeft & 0x07;
|
|
|
|
// if left and right edges are in same qword handle with masked
|
|
// read-modify-write
|
|
if (bSameQWord)
|
|
{
|
|
LONG xCount;
|
|
LONG lDeltaDst;
|
|
PBYTE pjDstEnd;
|
|
|
|
xCount = RightAln - LeftAln;
|
|
|
|
// sanity checks!
|
|
if (xCount <= 0)
|
|
{
|
|
return;
|
|
}
|
|
|
|
lDeltaDst = (DeltaDstIn - xCount) * 2;
|
|
|
|
pjDst = pjDstIn + DstLeft * 2;
|
|
pjDstEndY = pjDst + cy * DeltaDstIn * 2;
|
|
pjSrc = pjSrcIn + (SrcLeft >> 3);
|
|
|
|
// expand, one src byte is all that's required
|
|
do
|
|
{
|
|
// load src and shift into place
|
|
currentPels = *pjSrc;
|
|
currentPels <<= LeftAln;
|
|
pjDstEnd = pjDst + xCount * 2;
|
|
|
|
do
|
|
{
|
|
if (currentPels & 0x80)
|
|
{
|
|
*(UINT16 *)pjDst = (UINT16)fgCol;
|
|
}
|
|
pjDst += 2;
|
|
|
|
currentPels = (BYTE)(currentPels << 1);
|
|
|
|
} while (pjDst != pjDstEnd);
|
|
|
|
pjDst += lDeltaDst;
|
|
pjSrc += DeltaSrcIn;
|
|
|
|
} while (pjDst != pjDstEndY);
|
|
|
|
return;
|
|
}
|
|
else
|
|
{
|
|
BYTE currentPels;
|
|
LONG lDeltaDst = (DeltaDstIn - RightAln) * 2;
|
|
PBYTE pjDstEnd;
|
|
|
|
pjDst = pjDstIn + (DstRight & ~0x07) * 2;
|
|
pjDstEndY = pjDst + cy * DeltaDstIn * 2;
|
|
pjSrc = pjSrcIn + ((SrcLeft + (DstRight - DstLeft)) >> 3);
|
|
|
|
do
|
|
{
|
|
// read src
|
|
currentPels = *pjSrc;
|
|
|
|
if (currentPels != 0)
|
|
{
|
|
pjDstEnd = pjDst + RightAln * 2;
|
|
do
|
|
{
|
|
if (currentPels & 0x80)
|
|
{
|
|
*(UINT16 *)pjDst = (UINT16)fgCol;
|
|
}
|
|
pjDst += 2;
|
|
currentPels = (BYTE)(currentPels << 1);
|
|
|
|
} while (pjDst != pjDstEnd);
|
|
}
|
|
else
|
|
{
|
|
// short cut for zero
|
|
pjDst += RightAln * 2;
|
|
}
|
|
|
|
pjDst += lDeltaDst;
|
|
pjSrc += DeltaSrcIn;
|
|
|
|
} while (pjDst != pjDstEndY);
|
|
}
|
|
}
|
|
|
|
DC_END_FN();
|
|
}
|
|
#endif // DC_HICOLOR
|
|
|
|
/******************************Public*Routine******************************\
|
|
* vSrcTranCopyS1D8
|
|
*
|
|
#ifdef DC_HICOLOR
|
|
* Transparent blt of 1BPP src to 8bpp destination
|
|
#else
|
|
* Transparent blt of 1BPP src to all destination format
|
|
#endif
|
|
* 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
|
|
\**************************************************************************/
|
|
VOID CGH::vSrcTranCopyS1D8(
|
|
PBYTE pjSrcIn,
|
|
LONG SrcLeft,
|
|
LONG DeltaSrcIn,
|
|
PBYTE pjDstIn,
|
|
LONG DstLeft,
|
|
LONG DstRight,
|
|
LONG DeltaDstIn,
|
|
LONG cy,
|
|
ULONG uF,
|
|
ULONG uB)
|
|
{
|
|
// 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;
|
|
|
|
DC_IGNORE_PARAMETER(uB);
|
|
|
|
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 = (BYTE)(*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) {
|
|
BYTE jSrc;
|
|
BOOL bSameQWord = ((DstLeft) & ~0x07) == ((DstRight) & ~0x07);
|
|
|
|
// if left and right edges are in same qword handle with masked
|
|
// read-modify-write
|
|
if (bSameQWord) {
|
|
LONG xCount;
|
|
LONG lDeltaDst;
|
|
PBYTE pjDstEnd;
|
|
|
|
LeftAln = DstLeft & 0x07;
|
|
xCount = RightAln - LeftAln;
|
|
|
|
// assert ic xCount < 0
|
|
if (xCount <= 0)
|
|
return;
|
|
|
|
lDeltaDst = DeltaDstIn - xCount;
|
|
|
|
pjDst = pjDstIn + DstLeft;
|
|
pjDstEndY = pjDst + cy * DeltaDstIn;
|
|
pjSrc = pjSrcIn + (SrcLeft >> 3);
|
|
|
|
// expand, one src byte is all that's required
|
|
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 {
|
|
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 // defined(OS_WINCE) || defined(OS_WINNT)
|
|
|
|
/****************************************************************************/
|
|
/* Name: CalculateGlyphClipRect */
|
|
/* */
|
|
/* This function is used to determine if the glyph bits should be clipped */
|
|
/* using the clip rect passed in the order. */
|
|
/* */
|
|
/* It returns one of the values bellow: */
|
|
/* GLYPH_CLIP_NONE-The glyph will fit in the clip rect.No clipping needed */
|
|
/* GLYPH_CLIP_PARTIAL-The glyph is clipped by the clip rect */
|
|
/* GLYPH_CLIP_ALL - The glyph is completly clipped. */
|
|
/* */
|
|
/* */
|
|
/* Params: pGlyphRectClipOffset - OUT - it receives the clip offsets */
|
|
/* pOrder - Pointer to the order */
|
|
/* pHdr - Pointer to the glyph header */
|
|
/* x,y - The coord where the glyph will be drawn */
|
|
/****************************************************************************/
|
|
inline DCUINT CalculateGlyphClipRect( PRECTCLIPOFFSET pGlyphRectClipOffset,
|
|
LPINDEX_ORDER pOrder,
|
|
HPUHGLYPHCACHEENTRYHDR pHdr,
|
|
DCINT x,
|
|
DCINT y)
|
|
{
|
|
RECT rcGlyph;
|
|
|
|
DC_BEGIN_FN("CalculateGlyphClipRect");
|
|
|
|
// Here we calculate how the glyph bits will map in the clip rect.
|
|
rcGlyph.left = x + pHdr->x;
|
|
rcGlyph.top = y + pHdr->y;
|
|
rcGlyph.right = rcGlyph.left + pHdr->cx;
|
|
rcGlyph.bottom = rcGlyph.top + pHdr->cy;
|
|
|
|
// Check if the clip rect clips the glyph rect all the way
|
|
if ((rcGlyph.left >= pOrder->BkRight) ||
|
|
(rcGlyph.right <= pOrder->BkLeft) ||
|
|
(rcGlyph.top >= pOrder->BkBottom) ||
|
|
(rcGlyph.bottom <= pOrder->BkTop)) {
|
|
|
|
return GLYPH_CLIP_ALL;
|
|
}
|
|
|
|
pGlyphRectClipOffset->left = pOrder->BkLeft - rcGlyph.left;
|
|
pGlyphRectClipOffset->top = pOrder->BkTop - rcGlyph.top;
|
|
pGlyphRectClipOffset->right = rcGlyph.right - pOrder->BkRight;
|
|
pGlyphRectClipOffset->bottom = rcGlyph.bottom - pOrder->BkBottom;
|
|
|
|
if ((pGlyphRectClipOffset->left > 0) ||
|
|
(pGlyphRectClipOffset->top > 0) ||
|
|
(pGlyphRectClipOffset->right > 0) ||
|
|
(pGlyphRectClipOffset->bottom > 0)) {
|
|
|
|
return GLYPH_CLIP_PARTIAL;
|
|
};
|
|
|
|
DC_END_FN();
|
|
return GLYPH_CLIP_NONE;
|
|
}
|
|
|
|
/****************************************************************************/
|
|
/* Name: ClipGlyphBits */
|
|
/* */
|
|
/* This function will clip the glyph bits according to the clipping rect. */
|
|
/* It will actually generate a new glyph that would fit inside the */
|
|
/* clip rect. */
|
|
/* */
|
|
/* Params: inst - pointer to a CGH instance */
|
|
/* pGlyphRectClipOffset - Pointer to the glyph clip offset struct */
|
|
/* filled in by CalculateGlyphClipRect */
|
|
/* pHdr - Pointer to the glyph header. This will */
|
|
/* be modified accordingly */
|
|
/* ppData (IN/OUT) - Pointer to the start of the glyph bits */
|
|
/* ppEndData (IN/OUT) - Pointer to the end of the glyph bits */
|
|
/****************************************************************************/
|
|
inline HRESULT ClipGlyphBits(CGH* inst,
|
|
PRECTCLIPOFFSET pGlyphRectClipOffset,
|
|
HPUHGLYPHCACHEENTRYHDR pHdr,
|
|
PPDCUINT8 ppData,
|
|
PPDCUINT8 ppEndData)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
PDCUINT8 pNewData, pNewDataEnd;
|
|
DCUINT ScanLineSize, NewScanLineSize;
|
|
DCUINT LastByteIndex;
|
|
DCUINT8 LastByteMask;
|
|
DCUINT16 wTmp;
|
|
DCUINT8 clipRightMask, clipLeftBits, clipRightBits;
|
|
DCUINT clipLeftBytes;
|
|
DCUINT i,j;
|
|
PDCUINT8 pSrcScanLineStart, pDstScanLineStart, pTmpData, pEndTmpData;
|
|
|
|
DC_BEGIN_FN("ClipGlyphBits");
|
|
|
|
ScanLineSize = (pHdr->cx+7) / 8;
|
|
|
|
// If we have to clip from the top we just decrease the
|
|
// number of scanlines in the glyph and advance the start
|
|
// pointer for the glyph bitmap.
|
|
|
|
if (pGlyphRectClipOffset->top > 0) {
|
|
// When we clip the top of the glypy we will modify the actual origin
|
|
// of the glyph so we have to adjust the vector.
|
|
pHdr->y += pGlyphRectClipOffset->top;
|
|
// We decrease the height of the glyph
|
|
pHdr->cy -= pGlyphRectClipOffset->top;
|
|
// We move the start pointer
|
|
pNewData = *ppData + ScanLineSize * (pGlyphRectClipOffset->top);
|
|
} else {
|
|
pNewData = *ppData;
|
|
}
|
|
|
|
// If we have to clip the bootom we just decrease the number
|
|
// of lines in the glyph and we adjust the end pointer.
|
|
if (pGlyphRectClipOffset->bottom > 0) {
|
|
pHdr->cy -= pGlyphRectClipOffset->bottom;
|
|
pNewDataEnd = pNewData + ScanLineSize * pHdr->cy;
|
|
} else {
|
|
pNewDataEnd = *ppEndData;
|
|
}
|
|
|
|
// Check that the new pointers are still inside the src buffer.
|
|
TRC_ASSERT(((pNewData >=*ppData) && (pNewDataEnd <= *ppEndData)),
|
|
(TB, _T("Error recalculating the glyph src buffer")));
|
|
|
|
// In case we clipped only top/bottom we don't have to do any copy
|
|
// operation because the scanline start and the scanlise size remains
|
|
// the same. We just adjust pointers. In case we have to clip from the
|
|
// width we have to generate a new glyph and return its start address
|
|
// in ppData. In case we clip to the left we have to rotate some bits.
|
|
// in case we clip to the right we have to mask some bits.
|
|
|
|
clipRightMask = 0xff;
|
|
|
|
if ((pGlyphRectClipOffset->right > 0) ||
|
|
(pGlyphRectClipOffset->left > 0)) {
|
|
|
|
if (pGlyphRectClipOffset->right > 0) {
|
|
// Calculate how many bits are we gonna clip to the right
|
|
clipRightBits = (DCUINT8)(pGlyphRectClipOffset->right & 7);
|
|
// Then adjust the with of the glyph
|
|
pHdr->cx -= pGlyphRectClipOffset->right;
|
|
} else {
|
|
clipRightBits = 0;
|
|
}
|
|
|
|
if (pGlyphRectClipOffset->left > 0) {
|
|
// Calculate how many bytes we clip to the left. These are bytes
|
|
// we just won't copy. Then calculate how many bits are left to
|
|
// clip after we clip the bytes. This will tell us how much we
|
|
// have to rotate.
|
|
clipLeftBytes = pGlyphRectClipOffset->left / 8;
|
|
clipLeftBits = (DCUINT8)(pGlyphRectClipOffset->left & 7);
|
|
// Adjust the glyph width
|
|
pHdr->cx -= pGlyphRectClipOffset->left;
|
|
// Adjust the origin pointer. Clipping to the right actually
|
|
// modifies the origin.
|
|
pHdr->x += pGlyphRectClipOffset->left;
|
|
} else {
|
|
clipLeftBytes = 0;
|
|
clipLeftBits = 0;
|
|
}
|
|
|
|
//
|
|
// We check if we have to keep some bits at the end of the
|
|
// scanline. We update the mask...
|
|
if ((pHdr->cx+clipLeftBits) & 7) {
|
|
clipRightMask <<= ( 8 - ((pHdr->cx + clipLeftBits) & 7) );
|
|
}
|
|
|
|
NewScanLineSize = (pHdr->cx+7) / 8;
|
|
|
|
// This buffer is maintained by CGH. We don't have to free it.
|
|
pTmpData = inst->GetGlyphClipBuffer(NewScanLineSize * pHdr->cy);
|
|
if (pTmpData == NULL) {
|
|
hr = E_OUTOFMEMORY;
|
|
DC_QUIT;
|
|
}
|
|
|
|
pEndTmpData = pTmpData + NewScanLineSize * pHdr->cy;
|
|
|
|
pSrcScanLineStart = pNewData + clipLeftBytes;
|
|
pDstScanLineStart = pTmpData;
|
|
|
|
if (clipLeftBits == 0) {
|
|
// In case we don't clip to the left we don't have to rotate so
|
|
// things go faster.
|
|
for (i=0; i < pHdr->cy; i++) {
|
|
memcpy(pDstScanLineStart, pSrcScanLineStart, NewScanLineSize);
|
|
pDstScanLineStart[NewScanLineSize-1] &= clipRightMask;
|
|
|
|
pSrcScanLineStart += ScanLineSize;
|
|
pDstScanLineStart += NewScanLineSize;
|
|
}
|
|
} else {
|
|
// The transfer requires rotation
|
|
// We check to see if we need the last byte.
|
|
LastByteIndex = ((pHdr->cx + clipLeftBits + 7) / 8) - 1;
|
|
|
|
// LastByteIndex+1 is equal to the size of a scanline before
|
|
// clipping the left bits. If this size is grater then NewScanLineSize
|
|
// it means that clipping to the left would shrink the buffer with
|
|
// one byte and that some of the bits we need have to be transfered
|
|
// from that last byte.
|
|
// Note that LastByteIndex+1 can be grater then NewScanLineSize only
|
|
// with 1 byte.
|
|
|
|
// this is the case where LastByteIndex+1 is grater then NewScanLineSize
|
|
if ((LastByteIndex==NewScanLineSize)) {
|
|
for (i=0; i < pHdr->cy; i++) {
|
|
TRC_ASSERT(((pSrcScanLineStart + NewScanLineSize - 1 < pNewDataEnd) &&
|
|
(pDstScanLineStart + NewScanLineSize - 1 < pEndTmpData)),
|
|
(TB, _T("Overflow transfering glyph bits.")));
|
|
|
|
wTmp = (pSrcScanLineStart[LastByteIndex] & clipRightMask) <<
|
|
clipLeftBits;
|
|
|
|
for (j=NewScanLineSize; j>0; j--) {
|
|
pDstScanLineStart[j-1] = HIBYTE(wTmp);
|
|
wTmp = pSrcScanLineStart[j-1] << clipLeftBits;
|
|
pDstScanLineStart[j-1] |= LOBYTE(wTmp);
|
|
}
|
|
|
|
pSrcScanLineStart += ScanLineSize;
|
|
pDstScanLineStart += NewScanLineSize;
|
|
}
|
|
}else {
|
|
for (i=0; i < pHdr->cy; i++) {
|
|
TRC_ASSERT(((pSrcScanLineStart + NewScanLineSize - 1 < pNewDataEnd) &&
|
|
(pDstScanLineStart + NewScanLineSize - 1 < pEndTmpData)),
|
|
(TB, _T("Overflow transfering glyph bits.")));
|
|
|
|
wTmp = (pSrcScanLineStart[LastByteIndex] & clipRightMask) <<
|
|
clipLeftBits;
|
|
|
|
pDstScanLineStart[NewScanLineSize-1] = LOBYTE(wTmp);
|
|
|
|
for (j=NewScanLineSize-1; j>0; j--) {
|
|
pDstScanLineStart[j-1] = HIBYTE(wTmp);
|
|
wTmp = pSrcScanLineStart[j-1] << clipLeftBits;
|
|
pDstScanLineStart[j-1] |= LOBYTE(wTmp);
|
|
}
|
|
|
|
pSrcScanLineStart += ScanLineSize;
|
|
pDstScanLineStart += NewScanLineSize;
|
|
}
|
|
}
|
|
}
|
|
|
|
*ppData = pTmpData;
|
|
*ppEndData = pEndTmpData;
|
|
|
|
} else {
|
|
*ppData = pNewData;
|
|
*ppEndData = pNewDataEnd;
|
|
}
|
|
|
|
DC_EXIT_POINT:
|
|
|
|
DC_END_FN();
|
|
return hr;
|
|
}
|
|
|
|
inline BOOL CheckSourceGlyphBits(UINT32 cx,
|
|
UINT32 cy,
|
|
PDCUINT8 pStart,
|
|
PDCUINT8 pEnd)
|
|
{
|
|
DC_BEGIN_FN("CheckSourceGlyphBits");
|
|
|
|
UINT32 SrcScanLineSize = (cx+7) / 8;
|
|
UINT32 SrcBitmapSize = SrcScanLineSize & cy ;
|
|
TRC_ASSERT((pEnd >= pStart),(TB, _T("pEnd is less then pStart!!")));
|
|
|
|
DC_END_FN();
|
|
|
|
return ((SrcBitmapSize <= (UINT32)((PBYTE)pEnd - (PBYTE)pStart)) &&
|
|
(SrcBitmapSize <= SrcScanLineSize) &&
|
|
(SrcBitmapSize <= cy));
|
|
|
|
}
|
|
|
|
/****************************************************************************/
|
|
/* Name: GHSlowOutputBuffer */
|
|
/* */
|
|
/* Routine to output the composite glyphout buffer via normal bitblt */
|
|
/* operation(s) */
|
|
/* */
|
|
/* Params: pOrder - Pointer to glyph index order */
|
|
/* pData - Pointer to composite glyph buffer */
|
|
/* BufferAlign - Buffer alignment */
|
|
/* ulBufferWidth - Buffer width (in bytes) */
|
|
/****************************************************************************/
|
|
void DCINTERNAL CGH::GHSlowOutputBuffer(
|
|
LPINDEX_ORDER pOrder,
|
|
PDCUINT8 pData,
|
|
ULONG BufferAlign,
|
|
unsigned ulBufferWidth)
|
|
{
|
|
HBITMAP hbmOld;
|
|
unsigned cxBits;
|
|
unsigned cyBits;
|
|
#ifndef OS_WINCE
|
|
DCCOLOR color;
|
|
DWORD dwRop;
|
|
#ifdef DISABLE_SHADOW_IN_FULLSCREEN
|
|
COLORREF rgb;
|
|
#endif // DISABLE_SHADOW_IN_FULLSCREEN
|
|
#else // OS_WINCE
|
|
HBRUSH hbr;
|
|
COLORREF rgb;
|
|
#endif // OS_WINCE
|
|
|
|
DC_BEGIN_FN("GHSlowOutputBuffer");
|
|
|
|
/************************************************************************/
|
|
/* Use the glyph GDI resources */
|
|
/************************************************************************/
|
|
// Calculate the proper cx and cy aligned sizes.
|
|
cxBits = (int)(ulBufferWidth << 3);
|
|
cyBits = (int)(pOrder->BkBottom - pOrder->BkTop);
|
|
|
|
#ifdef OS_WINCE
|
|
// Create a bitmap with the composite glyph data provided.
|
|
_pUh->_UH.hbmGlyph = CreateBitmap(cxBits, cyBits, 1, 1, pData);
|
|
if (_pUh->_UH.hbmGlyph == NULL) {
|
|
TRC_NRM((TB, _T("Unable to create composite glyph bitmap")));
|
|
DC_QUIT;
|
|
}
|
|
#else
|
|
// If the current cache bitmap is not large enough to accomodate the
|
|
// request, then free it so we can alloc one properly sized.
|
|
if (cxBits != _pUh->_UH.cxGlyphBits || cyBits > _pUh->_UH.cyGlyphBits) {
|
|
if (_pUh->_UH.hbmGlyph != NULL) {
|
|
DeleteObject(_pUh->_UH.hbmGlyph);
|
|
_pUh->_UH.hbmGlyph = NULL;
|
|
goto NullGlyphBitmap;
|
|
}
|
|
}
|
|
|
|
// If we have a bitmap of sufficient dimensions, then just set the bits
|
|
// otherwise we need to alloc a new bitmap with the given data.
|
|
if (_pUh->_UH.hbmGlyph != NULL) {
|
|
SetBitmapBits(_pUh->_UH.hbmGlyph, (cxBits * cyBits) >> 3, pData);
|
|
}
|
|
else {
|
|
NullGlyphBitmap:
|
|
_pUh->_UH.hbmGlyph = CreateBitmap(cxBits, cyBits, 1, 1, pData);
|
|
if (_pUh->_UH.hbmGlyph != NULL) {
|
|
_pUh->_UH.cxGlyphBits = cxBits;
|
|
_pUh->_UH.cyGlyphBits = cyBits;
|
|
}
|
|
else {
|
|
TRC_NRM((TB, _T("Unable to create composite glyph bitmap")));
|
|
DC_QUIT;
|
|
}
|
|
}
|
|
#endif
|
|
|
|
|
|
// Create a DC for the composite bitmap and load it into it.
|
|
if (_pUh->_UH.hdcGlyph == NULL)
|
|
_pUh->_UH.hdcGlyph = CreateCompatibleDC(NULL);
|
|
if (_pUh->_UH.hdcGlyph != NULL) {
|
|
hbmOld = (HBITMAP)SelectObject(_pUh->_UH.hdcGlyph, _pUh->_UH.hbmGlyph);
|
|
}
|
|
else {
|
|
TRC_NRM((TB, _T("Unable to create compatible DC")));
|
|
DC_QUIT;
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* If the output is to be opaque, then set the fore and back colors */
|
|
/* appropriately and set the correct rop code */
|
|
/************************************************************************/
|
|
if (pOrder->OpTop < pOrder->OpBottom) {
|
|
|
|
#ifndef OS_WINCE
|
|
|
|
#ifndef DISABLE_SHADOW_IN_FULLSCREEN
|
|
UHUseTextColor(pOrder->ForeColor, UH_COLOR_PALETTE, _pUh);
|
|
UHUseBkColor(pOrder->BackColor, UH_COLOR_PALETTE, _pUh);
|
|
#else
|
|
// When in multimon and two desktops have different color depths
|
|
// glyph color don't look right in 256 color connection
|
|
// Here is the temporary solution, need to investigate more later.
|
|
if (_pUh->_UH.protocolBpp <= 8) {
|
|
rgb = UHGetColorRef(pOrder->ForeColor, UH_COLOR_PALETTE, _pUh);
|
|
rgb = GetNearestColor(_pUh->_UH.hdcDraw, rgb);
|
|
SetTextColor(_pUh->_UH.hdcDraw, rgb);
|
|
_pUh->_UH.lastTextColor = rgb;
|
|
|
|
#if defined (OS_WINCE)
|
|
_pUh->_UH.validTextColorDC = _pUh->_UH.hdcDraw;
|
|
#endif
|
|
|
|
rgb = UHGetColorRef(pOrder->BackColor, UH_COLOR_PALETTE, _pUh);
|
|
rgb = GetNearestColor(_pUh->_UH.hdcDraw, rgb);
|
|
SetBkColor(_pUh->_UH.hdcDraw, rgb);
|
|
_pUh->_UH.lastBkColor = rgb;
|
|
|
|
#if defined (OS_WINCE)
|
|
_pUh->_UH.validBkColorDC = _pUh->_UH.hdcDraw;
|
|
#endif
|
|
}
|
|
else {
|
|
UHUseTextColor(pOrder->ForeColor, UH_COLOR_PALETTE, _pUh);
|
|
UHUseBkColor(pOrder->BackColor, UH_COLOR_PALETTE, _pUh);
|
|
}
|
|
#endif // DISABLE_SHADOW_IN_FULLSCREEN
|
|
|
|
dwRop = SRCCOPY;
|
|
#else // OS_WINCE
|
|
/********************************************************************/
|
|
/* On WinCE, the Transparent ROP is heavily accelerated. For opaque */
|
|
/* just draw a solid rectangle, and then go on to do the */
|
|
/* transparent blt. */
|
|
/********************************************************************/
|
|
rgb = UHGetColorRef(pOrder->ForeColor, UH_COLOR_PALETTE, _pUh);
|
|
hbr = CECreateSolidBrush(rgb);
|
|
if(hbr != NULL) {
|
|
FillRect(_pUh->_UH.hdcDraw, (LPRECT) &pOrder->BkLeft, hbr);
|
|
CEDeleteBrush(hbr);
|
|
}
|
|
#endif // OS_WINCE
|
|
|
|
}
|
|
|
|
#ifndef OS_WINCE
|
|
// If the output is to be transparent, then set the fore and back
|
|
// colors appropriately and set the correct rop code.
|
|
else {
|
|
UHUseBrushOrg(0, 0, _pUh);
|
|
_pUh->UHUseSolidPaletteBrush(pOrder->BackColor);
|
|
|
|
color.u.rgb.red = 0;
|
|
color.u.rgb.green = 0;
|
|
color.u.rgb.blue = 0;
|
|
UHUseTextColor(color, UH_COLOR_RGB, _pUh);
|
|
|
|
color.u.rgb.red = 0xff;
|
|
color.u.rgb.green = 0xff;
|
|
color.u.rgb.blue = 0xff;
|
|
UHUseBkColor(color, UH_COLOR_RGB, _pUh);
|
|
|
|
dwRop = 0xE20746;
|
|
}
|
|
#endif // OS_WINCE
|
|
|
|
/************************************************************************/
|
|
/* The opaque vs transparent preamble is done, now just do the right */
|
|
/* blt operation */
|
|
/************************************************************************/
|
|
|
|
#ifdef OS_WINCE
|
|
/************************************************************************/
|
|
/* Create a brush for the foreground color and maskblt with that */
|
|
/* brush with the glyph bitmap as the mask */
|
|
/************************************************************************/
|
|
UHUseBrushOrg(0, 0, _pUh);
|
|
_pUh->UHUseSolidPaletteBrush(pOrder->BackColor);
|
|
|
|
/************************************************************************/
|
|
/* The 6th, 7th and 8th parameters (src bitmap) aren't used by the ROP */
|
|
/* that we pass in. The documentation says that in this case, hdcSrc */
|
|
/* should be zero but this causes the call to fail. We also have to */
|
|
/* pass in reasonable values for nXSrc and nYSrc or the parameter */
|
|
/* checking will fail. */
|
|
/************************************************************************/
|
|
if (!MaskBlt(_pUh->_UH.hdcDraw,
|
|
(int)pOrder->BkLeft,
|
|
(int)pOrder->BkTop,
|
|
(int)(pOrder->BkRight - pOrder->BkLeft),
|
|
(int)(pOrder->BkBottom - pOrder->BkTop),
|
|
_pUh->_UH.hdcGlyph, // next 3 not used for this ROP
|
|
0,
|
|
0,
|
|
_pUh->_UH.hbmGlyph,
|
|
(int)BufferAlign,
|
|
0,
|
|
0xAAF00000))
|
|
{
|
|
TRC_ERR((TB, _T("Composite glyph MaskBlt failed, %lu"), GetLastError()));
|
|
}
|
|
|
|
/************************************************************************/
|
|
// If we're drawing opaque we need to set the brush back to what
|
|
// the fringe rect code is expecting.
|
|
/************************************************************************/
|
|
if (pOrder->OpTop < pOrder->OpBottom)
|
|
{
|
|
_pUh->UHUseSolidPaletteBrush(pOrder->ForeColor);
|
|
}
|
|
|
|
#else // OS_WINCE
|
|
/************************************************************************/
|
|
/* Bitblt out the composite bitmap */
|
|
/************************************************************************/
|
|
if (!BitBlt(_pUh->_UH.hdcDraw,
|
|
(int)pOrder->BkLeft,
|
|
(int)pOrder->BkTop,
|
|
(int)(pOrder->BkRight - pOrder->BkLeft),
|
|
(int)(pOrder->BkBottom - pOrder->BkTop),
|
|
_pUh->_UH.hdcGlyph,
|
|
(int)BufferAlign,
|
|
0,
|
|
dwRop))
|
|
{
|
|
TRC_ERR((TB, _T("Composite glyph BitBlt failed")));
|
|
}
|
|
#endif // OS_WINCE
|
|
|
|
/************************************************************************/
|
|
/* Release GDI resources */
|
|
/************************************************************************/
|
|
SelectObject(_pUh->_UH.hdcGlyph, hbmOld);
|
|
#ifdef OS_WINCE
|
|
DeleteDC(_pUh->_UH.hdcGlyph);
|
|
_pUh->_UH.hdcGlyph = NULL;
|
|
|
|
DeleteObject(_pUh->_UH.hbmGlyph);
|
|
_pUh->_UH.hbmGlyph = NULL;
|
|
#endif
|
|
|
|
DC_EXIT_POINT:
|
|
DC_END_FN();
|
|
}
|
|
|
|
/****************************************************************************/
|
|
/* Name: draw_nf_ntb_o_to_temp_start */
|
|
/* */
|
|
/* Specialized glyph dispatch routine for non-fixed pitch, top and */
|
|
/* bottom not aligned glyphs that do overlap. This routine calculates */
|
|
/* the glyph's position on the temp buffer, then determines the correct */
|
|
/* highly specialized routine to be used to draw each glyph based on */
|
|
/* the glyph width, alignment and rotation */
|
|
/* */
|
|
/* Params: pGlyphPos - Pointer to first in list of GLYPHPOS structs */
|
|
/* pjTempBuffer - Pointer to temp 1Bpp buffer to draw into */
|
|
/* TempBufDelta - Scan line Delta for TempBuffer (always pos) */
|
|
/****************************************************************************/
|
|
HRESULT CGH::draw_nf_ntb_o_to_temp_start(
|
|
CGH* inst,
|
|
LPINDEX_ORDER pOrder,
|
|
unsigned iGlyph,
|
|
PDCUINT8 DCPTR ppjItem,
|
|
PDCUINT8 pjEndItem,
|
|
PDCINT px,
|
|
PDCINT py,
|
|
PDCUINT8 pjTempBuffer,
|
|
PDCUINT8 pjEndTempBuffer,
|
|
ULONG ulCharInc,
|
|
unsigned TempBufDelta,
|
|
PDCUINT16 pUnicode,
|
|
int * pnRet)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
PDCUINT8 pTempOutput;
|
|
LONG GlyphPosX;
|
|
int GlyphPixels;
|
|
LONG GlyphAlignment;
|
|
LONG SrcBytes;
|
|
LONG DstBytes;
|
|
ULONG ulDrawFlag;
|
|
PFN_GLYPHLOOPN pfnGlyphLoopN;
|
|
PFN_GLYPHLOOP pfnGlyphLoop;
|
|
LONG GlyphPosY;
|
|
HPUHGLYPHCACHE pCache;
|
|
HPUHGLYPHCACHEENTRYHDR pHdr;
|
|
PDCUINT8 pData;
|
|
PDCUINT8 pEndData;
|
|
ULONG cacheIndex;
|
|
INT16 delta;
|
|
INT32 GlyphClippingMode;
|
|
UHGLYPHCACHEENTRYHDR NewHdr;
|
|
RECTCLIPOFFSET rcOffset;
|
|
|
|
DC_BEGIN_FN("draw_nf_ntb_o_to_temp_start");
|
|
|
|
DC_IGNORE_PARAMETER(iGlyph);
|
|
|
|
*pnRet = 0;
|
|
|
|
CHECK_READ_ONE_BYTE(*ppjItem, pjEndItem, hr,
|
|
(TB, _T("Read Glyph Cache ID error")));
|
|
cacheIndex = **ppjItem;
|
|
(*ppjItem)++;
|
|
|
|
hr = inst->_pUh->UHIsValidGlyphCacheIDIndex(pOrder->cacheId, cacheIndex);
|
|
DC_QUIT_ON_FAIL(hr);
|
|
|
|
pCache = &(inst->_pUh->_UH.glyphCache[pOrder->cacheId]);
|
|
|
|
pHdr = &(pCache->pHdr[cacheIndex]);
|
|
pData = &(pCache->pData[pCache->cbEntrySize * cacheIndex]);
|
|
pEndData = (PDCUINT8)((PBYTE)pData + pCache->cbEntrySize);
|
|
|
|
if (pUnicode)
|
|
pUnicode[iGlyph] = (UINT16)(pHdr->unicode);
|
|
|
|
// Draw non fixed pitch, tops and bottoms not aligned,overlap
|
|
if ((pOrder->flAccel & SO_CHAR_INC_EQUAL_BM_BASE) == 0) {
|
|
CHECK_READ_ONE_BYTE(*ppjItem, pjEndItem, hr,
|
|
(TB, _T("Read Glyph delta")));
|
|
|
|
delta = (char)(*(*ppjItem)++);
|
|
|
|
if (delta & 0x80) {
|
|
CHECK_READ_N_BYTES(*ppjItem, pjEndItem, sizeof(INT16), hr,
|
|
(TB, _T("Read Glyph delta")));
|
|
|
|
delta = (*(short UNALIGNED FAR *)(*ppjItem));
|
|
(*ppjItem) += sizeof(INT16);
|
|
}
|
|
|
|
if (pOrder->flAccel & SO_HORIZONTAL)
|
|
*px += delta;
|
|
else
|
|
*py += delta;
|
|
}
|
|
|
|
// We make sure that we actually have enough bits for the glyph in the buffer
|
|
if (!CheckSourceGlyphBits(pHdr->cx, pHdr->cy, pData, pEndData)) {
|
|
hr=E_TSC_UI_GLYPH;
|
|
DC_QUIT;
|
|
}
|
|
|
|
GlyphClippingMode = CalculateGlyphClipRect(&rcOffset, pOrder, pHdr, *px, *py);
|
|
if (GlyphClippingMode!=GLYPH_CLIP_NONE) {
|
|
if (GlyphClippingMode==GLYPH_CLIP_ALL) {
|
|
goto SkipGlyphOutput;
|
|
} else {
|
|
// In case we do clipping we have to modify the header. We make a
|
|
// copy so we don't modify the cache.
|
|
memcpy(&NewHdr, pHdr, sizeof(UHGLYPHCACHEENTRYHDR));
|
|
pHdr = &NewHdr;
|
|
hr = ClipGlyphBits(inst, &rcOffset, pHdr, &pData, &pEndData);
|
|
if (FAILED(hr)) {
|
|
DC_QUIT;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Glyph position in temp buffer = point.x + org.c - (TextRect.left & 0xffffffe0)
|
|
GlyphPosX = *px + pHdr->x - ulCharInc;
|
|
GlyphPosY = *py + pHdr->y - pOrder->BkTop;
|
|
|
|
GlyphPosY = DC_MAX(0,GlyphPosY);
|
|
|
|
GlyphAlignment = GlyphPosX & 0x07;
|
|
|
|
// calc byte offset
|
|
pTempOutput = pjTempBuffer + (GlyphPosX >> 3);
|
|
|
|
// glyph width
|
|
GlyphPixels = (int)pHdr->cx;
|
|
|
|
// source and dest bytes required
|
|
DstBytes = ((GlyphAlignment) + GlyphPixels + 7) >> 3;
|
|
SrcBytes = (GlyphPixels + 7) >> 3;
|
|
|
|
pTempOutput += (GlyphPosY * TempBufDelta);
|
|
|
|
TRC_ASSERT((pTempOutput >= pjTempBuffer) &&
|
|
(pTempOutput < pjTempBuffer + inst->g_ulBytes - DstBytes),
|
|
(TB,_T("Bad glyph buffer addressing: pTempOutput=%p, pjTempBuffer=%p, g_ulBytes=%d, DstBytes=%d"),
|
|
pTempOutput, pjTempBuffer, inst->g_ulBytes, DstBytes));
|
|
|
|
if (pTempOutput < pjTempBuffer) {
|
|
TRC_ABORT((TB, _T("Reading before buffer")));
|
|
goto SkipGlyphOutput;
|
|
}
|
|
|
|
if (DstBytes < 0) {
|
|
TRC_ABORT((TB,_T("Bad index into glyph drawing tables")
|
|
_T("DstBytes=%d GlyphAlignment=%d GlyphPixels=%d pHdr->cx=%d ")
|
|
_T("GlyphPosX=%d *px=%d pHdr->x=%d ulCharInc=%d"),
|
|
DstBytes, GlyphAlignment, GlyphPixels, pHdr->cx, GlyphPosX, *px,
|
|
pHdr->x, ulCharInc));
|
|
hr = E_TSC_UI_GLYPH;
|
|
DC_QUIT;
|
|
}
|
|
|
|
if (DstBytes <= 4) {
|
|
// use narrow initial table
|
|
ulDrawFlag = ((DstBytes << 2) |
|
|
((DstBytes > SrcBytes) << 1) |
|
|
((GlyphAlignment == 0)));
|
|
|
|
pfnGlyphLoop = (PFN_GLYPHLOOP)OrAllTableNarrow[ulDrawFlag];
|
|
pfnGlyphLoop(pHdr->cy,
|
|
GlyphAlignment,
|
|
TempBufDelta,
|
|
pData,
|
|
pEndData,
|
|
pTempOutput,
|
|
pjEndTempBuffer,
|
|
SrcBytes);
|
|
}
|
|
else {
|
|
// use wide glyph drawing
|
|
ulDrawFlag = (((DstBytes > SrcBytes) << 1) |
|
|
((GlyphAlignment == 0)));
|
|
|
|
pfnGlyphLoopN = (PFN_GLYPHLOOPN)OrAllTableWide[ulDrawFlag];
|
|
pfnGlyphLoopN(pHdr->cy,
|
|
GlyphAlignment,
|
|
TempBufDelta,
|
|
pData,
|
|
pEndData,
|
|
pTempOutput,
|
|
pjEndTempBuffer,
|
|
SrcBytes,
|
|
DstBytes);
|
|
}
|
|
|
|
SkipGlyphOutput:
|
|
|
|
if (pOrder->flAccel & SO_CHAR_INC_EQUAL_BM_BASE) {
|
|
if (pOrder->flAccel & SO_HORIZONTAL)
|
|
*px += (unsigned)pHdr->cx;
|
|
else
|
|
*py += (unsigned)pHdr->cy;
|
|
}
|
|
*pnRet = GlyphPixels;
|
|
|
|
DC_EXIT_POINT:
|
|
|
|
DC_END_FN();
|
|
return hr;
|
|
}
|
|
|
|
/****************************************************************************/
|
|
/* Name: draw_f_ntb_o_to_temp_start */
|
|
/* */
|
|
/* Specialized glyph dispatch routine for fixed pitch, top and */
|
|
/* bottom not aligned glyphs that do overlap. This routine calculates */
|
|
/* the glyph's position on the temp buffer, then determines the correct */
|
|
/* highly specialized routine to be used to draw each glyph based on */
|
|
/* the glyph width, alignment and rotation */
|
|
/* */
|
|
/* Params: pGlyphPos - Pointer to first in list of GLYPHPOS structs */
|
|
/* pjTempBuffer - Pointer to temp 1Bpp buffer to draw into */
|
|
/* TempBufDelta - Scan line Delta for TempBuffer (always pos) */
|
|
/****************************************************************************/
|
|
HRESULT CGH::draw_f_ntb_o_to_temp_start(
|
|
CGH* inst,
|
|
LPINDEX_ORDER pOrder,
|
|
unsigned iGlyph,
|
|
PDCUINT8 DCPTR ppjItem,
|
|
PDCUINT8 pjEndItem,
|
|
PDCINT px,
|
|
PDCINT py,
|
|
PDCUINT8 pjTempBuffer,
|
|
PDCUINT8 pjEndTempBuffer,
|
|
ULONG ulCharInc,
|
|
unsigned TempBufDelta,
|
|
PDCUINT16 pUnicode,
|
|
int * pnRet)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
PDCUINT8 pTempOutput;
|
|
LONG GlyphPosX;
|
|
LONG GlyphPixels;
|
|
LONG GlyphAlignment;
|
|
LONG SrcBytes;
|
|
LONG DstBytes;
|
|
ULONG ulDrawFlag;
|
|
PFN_GLYPHLOOP pfnGlyphLoop;
|
|
PFN_GLYPHLOOPN pfnGlyphLoopN;
|
|
LONG GlyphPitchX;
|
|
LONG GlyphPitchY;
|
|
LONG GlyphPosY;
|
|
HPUHGLYPHCACHE pCache;
|
|
HPUHGLYPHCACHEENTRYHDR pHdr;
|
|
PDCUINT8 pData;
|
|
PDCUINT8 pEndData;
|
|
ULONG cacheIndex;
|
|
INT32 GlyphClippingMode;
|
|
UHGLYPHCACHEENTRYHDR NewHdr;
|
|
RECTCLIPOFFSET rcOffset;
|
|
|
|
DC_BEGIN_FN("draw_f_ntb_o_to_temp_start");
|
|
|
|
DC_IGNORE_PARAMETER(iGlyph);
|
|
|
|
*pnRet = 0;
|
|
|
|
CHECK_READ_ONE_BYTE(*ppjItem, pjEndItem, hr,
|
|
(TB, _T("Read Glyph Cache ID error")));
|
|
cacheIndex = **ppjItem;
|
|
(*ppjItem)++;
|
|
|
|
hr = inst->_pUh->UHIsValidGlyphCacheIDIndex(pOrder->cacheId, cacheIndex);
|
|
DC_QUIT_ON_FAIL(hr);
|
|
|
|
pCache = &(inst->_pUh->_UH.glyphCache[pOrder->cacheId]);
|
|
|
|
// Draw fixed pitch, tops and bottoms not aligned,overlap
|
|
GlyphPitchX = *px;
|
|
GlyphPitchY = *py - pOrder->BkTop;
|
|
|
|
pHdr = &(pCache->pHdr[cacheIndex]);
|
|
pData = &(pCache->pData[pCache->cbEntrySize * cacheIndex]);
|
|
pEndData = (PDCUINT8)((PBYTE)pData + pCache->cbEntrySize);
|
|
|
|
if (pUnicode)
|
|
pUnicode[iGlyph] = (DCUINT16)(pHdr->unicode);
|
|
|
|
// We make sure that we actually have enough bits for the glyph in the buffer
|
|
if (!CheckSourceGlyphBits(pHdr->cx, pHdr->cy, pData, pEndData)) {
|
|
hr=E_TSC_UI_GLYPH;
|
|
DC_QUIT;
|
|
}
|
|
|
|
|
|
GlyphClippingMode = CalculateGlyphClipRect(&rcOffset, pOrder, pHdr, *px, *py);
|
|
if (GlyphClippingMode!=GLYPH_CLIP_NONE) {
|
|
if (GlyphClippingMode==GLYPH_CLIP_ALL) {
|
|
goto SkipGlyphOutput;
|
|
} else {
|
|
// In case we do clipping we have to modify the header. We make a
|
|
// copy so we don't modify the cache.
|
|
memcpy(&NewHdr, pHdr, sizeof(UHGLYPHCACHEENTRYHDR));
|
|
pHdr = &NewHdr;
|
|
hr = ClipGlyphBits(inst, &rcOffset, pHdr, &pData, &pEndData);
|
|
if (FAILED(hr)) {
|
|
DC_QUIT;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Glyph position in temp buffer = point.x + org.c - (TextRect.left & 0xfffffff8)
|
|
GlyphPosX = GlyphPitchX + pHdr->x - ulCharInc;
|
|
GlyphPosY = GlyphPitchY + pHdr->y;
|
|
|
|
GlyphAlignment = GlyphPosX & 0x07;
|
|
|
|
// calc byte offset
|
|
pTempOutput = pjTempBuffer + (GlyphPosX >> 3);
|
|
|
|
// glyph width
|
|
GlyphPixels = pHdr->cx;
|
|
|
|
// source and dest bytes required
|
|
DstBytes = ((GlyphAlignment) + GlyphPixels + 7) >> 3;
|
|
SrcBytes = (GlyphPixels + 7) >> 3;
|
|
|
|
// calc glyph destination scan line
|
|
pTempOutput += (GlyphPosY * TempBufDelta);
|
|
TRC_ASSERT((pTempOutput >= pjTempBuffer) &&
|
|
(pTempOutput < pjTempBuffer + inst->g_ulBytes - DstBytes),
|
|
(TB,_T("Bad glyph buffer addressing")));
|
|
|
|
if (pTempOutput < pjTempBuffer) {
|
|
TRC_ABORT((TB, _T("Reading before buffer")));
|
|
goto SkipGlyphOutput;
|
|
}
|
|
|
|
if (DstBytes < 0) {
|
|
TRC_ABORT((TB,_T("Bad index into glyph drawing tables")
|
|
_T("DstBytes=%d GlyphAlignment=%d GlyphPixels=%d pHdr->cx=%d ")
|
|
_T("GlyphPosX=%d *px=%d pHdr->x=%d ulCharInc=%d"),
|
|
DstBytes, GlyphAlignment, GlyphPixels, pHdr->cx, GlyphPosX, *px,
|
|
pHdr->x, ulCharInc));
|
|
hr = E_TSC_UI_GLYPH;
|
|
DC_QUIT;
|
|
}
|
|
|
|
if (DstBytes <= 4) {
|
|
// use narrow initial table
|
|
ulDrawFlag = ((DstBytes << 2) |
|
|
((DstBytes > SrcBytes) << 1) |
|
|
((GlyphAlignment == 0)));
|
|
|
|
pfnGlyphLoop = (PFN_GLYPHLOOP)OrAllTableNarrow[ulDrawFlag];
|
|
pfnGlyphLoop(pHdr->cy,
|
|
GlyphAlignment,
|
|
TempBufDelta,
|
|
pData,
|
|
pEndData,
|
|
pTempOutput,
|
|
pjEndTempBuffer,
|
|
SrcBytes);
|
|
}
|
|
else {
|
|
// use wide glyph drawing
|
|
ulDrawFlag = (((DstBytes > SrcBytes) << 1) |
|
|
((GlyphAlignment == 0)));
|
|
|
|
pfnGlyphLoopN = (PFN_GLYPHLOOPN)OrAllTableWide[ulDrawFlag];
|
|
pfnGlyphLoopN(pHdr->cy,
|
|
GlyphAlignment,
|
|
TempBufDelta,
|
|
pData,
|
|
pEndData,
|
|
pTempOutput,
|
|
pjEndTempBuffer,
|
|
SrcBytes,
|
|
DstBytes);
|
|
}
|
|
|
|
SkipGlyphOutput:
|
|
*px += pOrder->ulCharInc;
|
|
|
|
*pnRet = pOrder->ulCharInc;
|
|
DC_EXIT_POINT:
|
|
|
|
DC_END_FN();
|
|
return hr;
|
|
}
|
|
|
|
|
|
/****************************************************************************/
|
|
/* Name: draw_nf_tb_no_to_temp_start */
|
|
/* */
|
|
/* Specialized glyph dispatch routine for non-fixed pitch, top and */
|
|
/* bottom aligned glyphs that do not overlap. This routine calculates */
|
|
/* the glyph's position on the temp buffer, then determines the correct */
|
|
/* highly specialized routine to be used to draw each glyph based on */
|
|
/* the glyph width, alignment and rotation */
|
|
/* */
|
|
/* Params: pGlyphPos - Pointer to first in list of GLYPHPOS structs */
|
|
/* pjTempBuffer - Pointer to temp 1Bpp buffer to draw into */
|
|
/* TempBufDelta - Scan line Delta for TempBuffer (always pos) */
|
|
/****************************************************************************/
|
|
HRESULT CGH::draw_nf_tb_no_to_temp_start(
|
|
CGH* inst,
|
|
LPINDEX_ORDER pOrder,
|
|
unsigned iGlyph,
|
|
PDCUINT8 DCPTR ppjItem,
|
|
PDCUINT8 pjEndItem,
|
|
PDCINT px,
|
|
PDCINT py,
|
|
PDCUINT8 pjTempBuffer,
|
|
PDCUINT8 pjEndTempBuffer,
|
|
ULONG ulCharInc,
|
|
unsigned TempBufDelta,
|
|
PDCUINT16 pUnicode,
|
|
int * pnRet)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
PDCUINT8 pTempOutput;
|
|
LONG GlyphPosX;
|
|
int GlyphPixels;
|
|
LONG GlyphAlignment;
|
|
LONG SrcBytes;
|
|
LONG DstBytes;
|
|
ULONG ulDrawFlag;
|
|
PFN_GLYPHLOOP pfnGlyphLoop;
|
|
PFN_GLYPHLOOPN pfnGlyphLoopN;
|
|
HPUHGLYPHCACHE pCache;
|
|
HPUHGLYPHCACHEENTRYHDR pHdr;
|
|
PDCUINT8 pData;
|
|
PDCUINT8 pEndData;
|
|
ULONG cacheIndex;
|
|
INT16 delta;
|
|
INT32 GlyphClippingMode;
|
|
UHGLYPHCACHEENTRYHDR NewHdr;
|
|
RECTCLIPOFFSET rcOffset;
|
|
|
|
DC_BEGIN_FN("draw_nf_tb_no_to_temp_start");
|
|
|
|
DC_IGNORE_PARAMETER(iGlyph);
|
|
|
|
*pnRet = 0;
|
|
|
|
CHECK_READ_ONE_BYTE(*ppjItem, pjEndItem, hr,
|
|
(TB, _T("Read Glyph Cache ID error")));
|
|
// Draw non fixed pitch, tops and bottoms not aligned, overlap
|
|
cacheIndex = **ppjItem;
|
|
(*ppjItem)++;
|
|
|
|
hr = inst->_pUh->UHIsValidGlyphCacheIDIndex(pOrder->cacheId, cacheIndex);
|
|
DC_QUIT_ON_FAIL(hr);
|
|
|
|
pCache = &(inst->_pUh->_UH.glyphCache[pOrder->cacheId]);
|
|
|
|
if ((pOrder->flAccel & SO_CHAR_INC_EQUAL_BM_BASE) == 0) {
|
|
CHECK_READ_ONE_BYTE(*ppjItem, pjEndItem, hr,
|
|
(TB, _T("Read Glyph delta error")));
|
|
|
|
delta = (DCINT8)(*(*ppjItem)++);
|
|
|
|
if (delta & 0x80) {
|
|
CHECK_READ_N_BYTES(*ppjItem, pjEndItem, sizeof(DCINT16), hr,
|
|
(TB, _T("Read Glyph delta error")));
|
|
|
|
delta = (*(short UNALIGNED FAR *)(*ppjItem));
|
|
(*ppjItem) += sizeof(DCINT16);
|
|
}
|
|
|
|
if (pOrder->flAccel & SO_HORIZONTAL)
|
|
*px += delta;
|
|
else
|
|
*py += delta;
|
|
}
|
|
|
|
pHdr = &(pCache->pHdr[cacheIndex]);
|
|
pData = &(pCache->pData[pCache->cbEntrySize * cacheIndex]);
|
|
pEndData = (PDCUINT8)((PBYTE)pData + pCache->cbEntrySize);
|
|
|
|
if (pUnicode)
|
|
pUnicode[iGlyph] = (DCUINT16)(pHdr->unicode);
|
|
|
|
// We make sure that we actually have enough bits for the glyph in the buffer
|
|
if (!CheckSourceGlyphBits(pHdr->cx, pHdr->cy, pData, pEndData)) {
|
|
hr=E_TSC_UI_GLYPH;
|
|
DC_QUIT;
|
|
}
|
|
|
|
GlyphClippingMode = CalculateGlyphClipRect(&rcOffset, pOrder, pHdr, *px, *py);
|
|
if (GlyphClippingMode!=GLYPH_CLIP_NONE) {
|
|
if (GlyphClippingMode==GLYPH_CLIP_ALL) {
|
|
goto SkipGlyphOutput;
|
|
} else {
|
|
// In case we do clipping we have to modify the header. We make a
|
|
// copy so we don't modify the cache.
|
|
memcpy(&NewHdr, pHdr, sizeof(UHGLYPHCACHEENTRYHDR));
|
|
pHdr = &NewHdr;
|
|
hr = ClipGlyphBits(inst, &rcOffset, pHdr, &pData, &pEndData);
|
|
if (FAILED(hr)) {
|
|
DC_QUIT;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Glyph position in temp buffer = point.x + org.c - (TextRect.left & 0xfffffff8)
|
|
GlyphPosX = *px + pHdr->x - ulCharInc;
|
|
GlyphAlignment = GlyphPosX & 0x07;
|
|
|
|
// calc byte offset
|
|
pTempOutput = pjTempBuffer + (GlyphPosX >> 3);
|
|
|
|
// glyph width
|
|
GlyphPixels = (DCINT) pHdr->cx;
|
|
|
|
// source and dest bytes required
|
|
DstBytes = ((GlyphAlignment) + GlyphPixels + 7) >> 3;
|
|
SrcBytes = (GlyphPixels + 7) >> 3;
|
|
|
|
TRC_ASSERT((pTempOutput >= pjTempBuffer) &&
|
|
(pTempOutput < pjTempBuffer + inst->g_ulBytes - DstBytes),
|
|
(TB,_T("Bad glyph buffer addressing")));
|
|
|
|
if (pTempOutput < pjTempBuffer) {
|
|
TRC_ABORT((TB, _T("Reading before buffer")));
|
|
goto SkipGlyphOutput;
|
|
}
|
|
|
|
if (DstBytes < 0) {
|
|
TRC_ABORT((TB,_T("Bad index into glyph drawing tables")
|
|
_T("DstBytes=%d GlyphAlignment=%d GlyphPixels=%d pHdr->cx=%d ")
|
|
_T("GlyphPosX=%d *px=%d pHdr->x=%d ulCharInc=%d"),
|
|
DstBytes, GlyphAlignment, GlyphPixels, pHdr->cx, GlyphPosX, *px,
|
|
pHdr->x, ulCharInc));
|
|
hr = E_TSC_UI_GLYPH;
|
|
DC_QUIT;
|
|
}
|
|
|
|
if (DstBytes <= 4) {
|
|
// use narrow initial table
|
|
ulDrawFlag = ((DstBytes << 2) |
|
|
((DstBytes > SrcBytes) << 1) |
|
|
((GlyphAlignment == 0)));
|
|
|
|
pfnGlyphLoop = (PFN_GLYPHLOOP)OrInitialTableNarrow[ulDrawFlag];
|
|
pfnGlyphLoop(pHdr->cy,
|
|
GlyphAlignment,
|
|
TempBufDelta,
|
|
pData,
|
|
pEndData,
|
|
pTempOutput,
|
|
pjEndTempBuffer,
|
|
SrcBytes);
|
|
}
|
|
else {
|
|
// use wide glyph drawing
|
|
ulDrawFlag = (((DstBytes > SrcBytes) << 1) |
|
|
((GlyphAlignment == 0)));
|
|
|
|
pfnGlyphLoopN = (PFN_GLYPHLOOPN)OrAllTableWide[ulDrawFlag];
|
|
pfnGlyphLoopN(pHdr->cy,
|
|
GlyphAlignment,
|
|
TempBufDelta,
|
|
pData,
|
|
pEndData,
|
|
pTempOutput,
|
|
pjEndTempBuffer,
|
|
SrcBytes,
|
|
DstBytes);
|
|
}
|
|
|
|
SkipGlyphOutput:
|
|
|
|
if (pOrder->flAccel & SO_CHAR_INC_EQUAL_BM_BASE)
|
|
*px += (DCINT) pHdr->cx;
|
|
|
|
*pnRet = GlyphPixels;
|
|
DC_EXIT_POINT:
|
|
|
|
DC_END_FN();
|
|
return hr;
|
|
}
|
|
|
|
|
|
/****************************************************************************/
|
|
/* Name: draw_f_tb_no_to_temp_start */
|
|
/* */
|
|
/* Specialized glyph dispatch routine for fixed pitch, top and */
|
|
/* bottom aligned glyphs that do not overlap. This routine calculates */
|
|
/* the glyph's position on the temp buffer, then determines the correct */
|
|
/* highly specialized routine to be used to draw each glyph based on */
|
|
/* the glyph width, alignment and rotation */
|
|
/* */
|
|
/* Params: pGlyphPos - Pointer to first in list of GLYPHPOS structs */
|
|
/* pjTempBuffer - Pointer to temp 1Bpp buffer to draw into */
|
|
/* TempBufDelta - Scan line Delta for TempBuffer (always pos) */
|
|
/****************************************************************************/
|
|
HRESULT CGH::draw_f_tb_no_to_temp_start(
|
|
CGH* inst,
|
|
LPINDEX_ORDER pOrder,
|
|
unsigned iGlyph,
|
|
PDCUINT8 DCPTR ppjItem,
|
|
PDCUINT8 pjEndItem,
|
|
PDCINT px,
|
|
PDCINT py,
|
|
PDCUINT8 pjTempBuffer,
|
|
PDCUINT8 pjEndTempBuffer,
|
|
ULONG ulLeftEdge,
|
|
unsigned TempBufDelta,
|
|
PDCUINT16 pUnicode,
|
|
int * pnRet)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
PDCUINT8 pTempOutput;
|
|
LONG GlyphPosX;
|
|
LONG GlyphPixels;
|
|
LONG GlyphPitchX;
|
|
LONG GlyphAlignment;
|
|
LONG SrcBytes;
|
|
LONG DstBytes;
|
|
ULONG ulDrawFlag;
|
|
PFN_GLYPHLOOPN pfnGlyphLoopN;
|
|
PFN_GLYPHLOOP pfnGlyphLoop;
|
|
HPUHGLYPHCACHE pCache;
|
|
HPUHGLYPHCACHEENTRYHDR pHdr;
|
|
PDCUINT8 pData;
|
|
PDCUINT8 pEndData;
|
|
ULONG cacheIndex;
|
|
INT32 GlyphClippingMode;
|
|
UHGLYPHCACHEENTRYHDR NewHdr;
|
|
RECTCLIPOFFSET rcOffset;
|
|
|
|
DC_BEGIN_FN("draw_f_tb_no_to_temp_start");
|
|
|
|
DC_IGNORE_PARAMETER(iGlyph);
|
|
DC_IGNORE_PARAMETER(py);
|
|
|
|
*pnRet = 0;
|
|
|
|
CHECK_READ_ONE_BYTE(*ppjItem, pjEndItem, hr,
|
|
(TB, _T("Read Glyph Cache ID error")));
|
|
cacheIndex = **ppjItem;
|
|
(*ppjItem)++;
|
|
|
|
hr = inst->_pUh->UHIsValidGlyphCacheIDIndex(pOrder->cacheId, cacheIndex);
|
|
DC_QUIT_ON_FAIL(hr);
|
|
|
|
pCache = &(inst->_pUh->_UH.glyphCache[pOrder->cacheId]);
|
|
|
|
// Draw fixed pitch, tops and bottoms not aligned,overlap
|
|
GlyphPitchX = *px;
|
|
|
|
pHdr = &(pCache->pHdr[cacheIndex]);
|
|
pData = &(pCache->pData[pCache->cbEntrySize * cacheIndex]);
|
|
pEndData = (PDCUINT8)((PBYTE)pData + pCache->cbEntrySize);
|
|
|
|
if (pUnicode)
|
|
pUnicode[iGlyph] = (UINT16)(pHdr->unicode);
|
|
|
|
// We make sure that we actually have enough bits for the glyph in the buffer
|
|
if (!CheckSourceGlyphBits(pHdr->cx, pHdr->cy, pData, pEndData)) {
|
|
hr=E_TSC_UI_GLYPH;
|
|
DC_QUIT;
|
|
}
|
|
|
|
GlyphClippingMode = CalculateGlyphClipRect(&rcOffset, pOrder, pHdr, *px, *py);
|
|
if (GlyphClippingMode!=GLYPH_CLIP_NONE) {
|
|
if (GlyphClippingMode==GLYPH_CLIP_ALL) {
|
|
goto SkipGlyphOutput;
|
|
} else {
|
|
// In case we do clipping we have to modify the header. We make a
|
|
// copy so we don't modify the cache.
|
|
memcpy(&NewHdr, pHdr, sizeof(UHGLYPHCACHEENTRYHDR));
|
|
pHdr = &NewHdr;
|
|
hr = ClipGlyphBits(inst, &rcOffset, pHdr, &pData, &pEndData);
|
|
if (FAILED(hr)) {
|
|
DC_QUIT;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Glyph position in temp buffer = point.x + org.c - (TextRect.left & 0xfffffff8)
|
|
GlyphPosX = GlyphPitchX + pHdr->x - ulLeftEdge;
|
|
GlyphAlignment = GlyphPosX & 0x07;
|
|
|
|
// calc byte offset
|
|
pTempOutput = pjTempBuffer + (GlyphPosX >> 3);
|
|
|
|
// glyph width
|
|
GlyphPixels = pHdr->cx;
|
|
|
|
// source and dest bytes required
|
|
DstBytes = ((GlyphAlignment) + GlyphPixels + 7) >> 3;
|
|
SrcBytes = (GlyphPixels + 7) >> 3;
|
|
|
|
TRC_ASSERT((pTempOutput >= pjTempBuffer) &&
|
|
(pTempOutput < pjTempBuffer + inst->g_ulBytes - DstBytes),
|
|
(TB,_T("Bad glyph buffer addressing")));
|
|
|
|
if (pTempOutput < pjTempBuffer) {
|
|
TRC_ABORT((TB, _T("Reading before buffer")));
|
|
goto SkipGlyphOutput;
|
|
}
|
|
|
|
if (DstBytes < 0) {
|
|
TRC_ABORT((TB,_T("Bad index into glyph drawing tables")
|
|
_T("DstBytes=%d GlyphAlignment=%d GlyphPixels=%d pHdr->cx=%d ")
|
|
_T("GlyphPosX=%d *px=%d pHdr->x=%d ulLeftEdge=%d"),
|
|
DstBytes, GlyphAlignment, GlyphPixels, pHdr->cx, GlyphPosX, *px,
|
|
pHdr->x, ulLeftEdge));
|
|
hr = E_TSC_UI_GLYPH;
|
|
DC_QUIT;
|
|
}
|
|
|
|
if (DstBytes <= 4) {
|
|
// use narrow initial table
|
|
ulDrawFlag = ((DstBytes << 2) |
|
|
((DstBytes > SrcBytes) << 1) |
|
|
(GlyphAlignment == 0));
|
|
|
|
pfnGlyphLoop = (PFN_GLYPHLOOP)OrInitialTableNarrow[ulDrawFlag];
|
|
pfnGlyphLoop(pHdr->cy,
|
|
GlyphAlignment,
|
|
TempBufDelta,
|
|
pData,
|
|
pEndData,
|
|
pTempOutput,
|
|
pjEndTempBuffer,
|
|
SrcBytes);
|
|
}
|
|
else {
|
|
// use wide glyph drawing
|
|
ulDrawFlag = (((DstBytes > SrcBytes) << 1) |
|
|
((GlyphAlignment == 0)));
|
|
|
|
pfnGlyphLoopN = (PFN_GLYPHLOOPN)OrAllTableWide[ulDrawFlag];
|
|
pfnGlyphLoopN(pHdr->cy,
|
|
GlyphAlignment,
|
|
TempBufDelta,
|
|
pData,
|
|
pEndData,
|
|
pTempOutput,
|
|
pjEndTempBuffer,
|
|
SrcBytes,
|
|
DstBytes);
|
|
}
|
|
|
|
SkipGlyphOutput:
|
|
*px += pOrder->ulCharInc;
|
|
|
|
*pnRet = pOrder->ulCharInc;
|
|
DC_EXIT_POINT:
|
|
|
|
DC_END_FN();
|
|
return hr;
|
|
}
|
|
|
|
|