|
|
/******************************Module*Header*******************************\
* Module Name: textxl.c * * Draw glyphs to 1Bpp temporary buffer. This is the portable version * of the x86 code from the VGA driver. * * * Copyright (c) 1994-1999 Microsoft Corporation \**************************************************************************/
#include "engine.h"
#if !defined (_X86_)
typedef VOID (*PFN_GLYPHLOOP)(LONG,LONG,LONG,PUCHAR,PUCHAR,LONG); typedef VOID (*PFN_GLYPHLOOPN)(LONG,LONG,LONG,PUCHAR,PUCHAR,LONG,LONG);
PFN_GLYPHLOOP pfnGlyphLoop;
//
// debug routine
//
VOID exit_fast_text( LONG cyGlyph, LONG RightRot, LONG ulBufDelta, PUCHAR pGlyph, PUCHAR pBuffer, LONG cxGlyph ) { return; }
//
// or_all_1_wide_rotated_need_last::
// or_all_1_wide_rotated_no_last::
// or_first_1_wide_rotated_need_last
// or_first_1_wide_rotated_no_last::
//
VOID or_all_1_wide_rotated_need_last( LONG cyGlyph, LONG RightRot, LONG ulBufDelta, PUCHAR pGlyph, PUCHAR pBuffer, LONG cxGlyph ) { PUCHAR pjEnd = pGlyph + cyGlyph; UCHAR c;
do { c = *pGlyph++; *pBuffer |= c >> RightRot; pBuffer += ulBufDelta; } while (pGlyph != pjEnd); }
//
// mov_first_1_wide_rotated_need_last::
// mov_first_1_wide_rotated_no_last::
//
VOID mov_first_1_wide_rotated_need_last( LONG cyGlyph, LONG RightRot, LONG ulBufDelta, PUCHAR pGlyph, PUCHAR pBuffer, LONG cxGlyph ) { PUCHAR pjEnd = pGlyph + cyGlyph; UCHAR c;
do { c = *pGlyph++; *pBuffer = c >> RightRot; pBuffer += ulBufDelta; } while (pGlyph != pjEnd); }
//
// mov_first_1_wide_unrotated::
//
VOID mov_first_1_wide_unrotated( LONG cyGlyph, LONG RightRot, LONG ulBufDelta, PUCHAR pGlyph, PUCHAR pBuffer, LONG cxGlyph ) { PUCHAR pjEnd = pGlyph + cyGlyph; do { *pBuffer = *pGlyph++; pBuffer += ulBufDelta; } while (pGlyph != pjEnd); }
//
//or_all_1_wide_unrotated::
//or_all_1_wide_unrotated_loop::
//
VOID or_all_1_wide_unrotated( LONG cyGlyph, LONG RightRot, LONG ulBufDelta, PUCHAR pGlyph, PUCHAR pBuffer, LONG cxGlyph ) { PUCHAR pjEnd = pGlyph + cyGlyph; do { *pBuffer |= *pGlyph++; pBuffer += ulBufDelta; } while (pGlyph != pjEnd); }
//
// or_first_2_wide_rotated_need_last::
//
VOID or_first_2_wide_rotated_need_last( LONG cyGlyph, LONG RightRot, LONG ulBufDelta, PUCHAR pGlyph, PUCHAR pBuffer, LONG cxGlyph ) { PUCHAR pjEnd = pGlyph + 2*cyGlyph; ULONG rl = 8-RightRot; UCHAR c0,c1;
do { c0 = *pGlyph; c1 = *(pGlyph+1); pGlyph+=2; *pBuffer |= c0 >> RightRot; *(pBuffer+1) = (c1 >> RightRot) | (c0 << rl); pBuffer += ulBufDelta; } while (pGlyph != pjEnd); }
//
//or_all_2_wide_rotated_need_last::
//
VOID or_all_2_wide_rotated_need_last( LONG cyGlyph, LONG RightRot, LONG ulBufDelta, PUCHAR pGlyph, PUCHAR pBuffer, LONG cxGlyph ) { PUCHAR pjEnd = pGlyph + 2*cyGlyph; ULONG rl = 8-RightRot; USHORT usTmp; UCHAR c0,c1;
do { usTmp = *(PUSHORT)pGlyph; pGlyph += 2; c0 = (UCHAR)usTmp; c1 = (UCHAR)(usTmp >> 8); *pBuffer |= (UCHAR)(c0 >> RightRot); *(pBuffer+1) |= (UCHAR)((c1 >> RightRot) | (c0 << rl)); pBuffer += ulBufDelta; } while (pGlyph != pjEnd); }
//
// mov_first_2_wide_rotated_need_last::
//
VOID mov_first_2_wide_rotated_need_last( LONG cyGlyph, LONG RightRot, LONG ulBufDelta, PUCHAR pGlyph, PUCHAR pBuffer, LONG cxGlyph ) { PUCHAR pjEnd = pGlyph + 2*cyGlyph; ULONG rl = 8-RightRot; USHORT us; UCHAR c0; UCHAR c1;
do { us = *(PUSHORT)pGlyph; c0 = (us & 0xff); c1 = us >> 8; pGlyph += 2; *pBuffer = c0 >> RightRot; *(pBuffer+1) = (c1 >> RightRot) | (c0 << rl); pBuffer += ulBufDelta; } while (pGlyph != pjEnd); }
//
// or_first_2_wide_rotated_no_last
//
VOID or_first_2_wide_rotated_no_last( LONG cyGlyph, LONG RightRot, LONG ulBufDelta, PUCHAR pGlyph, PUCHAR pBuffer, LONG cxGlyph ) { PUCHAR pjEnd = pGlyph + cyGlyph; ULONG rl = 8-RightRot; UCHAR c0;
do { c0 = *pGlyph++; *pBuffer |= c0 >> RightRot; *(pBuffer+1) = (c0 << rl); pBuffer += ulBufDelta; } while (pGlyph != pjEnd); }
//
//or_all_2_wide_rotated_no_last::
//
VOID or_all_2_wide_rotated_no_last( LONG cyGlyph, LONG RightRot, LONG ulBufDelta, PUCHAR pGlyph, PUCHAR pBuffer, LONG cxGlyph ) { PUCHAR pjEnd = pGlyph + cyGlyph; ULONG rl = 8-RightRot; UCHAR c;
do { c = *pGlyph; pGlyph ++; *pBuffer |= (UCHAR)(c >> RightRot); *(pBuffer+1) |= (UCHAR)(c << rl); pBuffer += ulBufDelta; } while (pGlyph != pjEnd); }
//
// or_all_2_wide_unrotated::
//
VOID or_all_2_wide_unrotated( LONG cyGlyph, LONG RightRot, LONG ulBufDelta, PUCHAR pGlyph, PUCHAR pBuffer, LONG cxGlyph ) { PUCHAR pjEnd = pGlyph + 2*cyGlyph;
//
// aligned?
//
if ((ULONG_PTR)pBuffer & 0x01) {
//
// not aligned
//
USHORT usTmp; UCHAR c1,c0;
do { usTmp = *(PUSHORT)pGlyph; pGlyph +=2; *pBuffer |= (UCHAR)usTmp; *(pBuffer+1) |= (UCHAR)(usTmp >> 8); pBuffer += ulBufDelta; } while (pGlyph != pjEnd);
} else {
//
// aligned
//
USHORT usTmp;
do { usTmp = *(PUSHORT)pGlyph; pGlyph +=2; *(PUSHORT)pBuffer |= usTmp; pBuffer += ulBufDelta; } while (pGlyph != pjEnd);
}
}
//
// mov_first_2_wide_unrotated::
//
VOID mov_first_2_wide_unrotated( LONG cyGlyph, LONG RightRot, LONG ulBufDelta, PUCHAR pGlyph, PUCHAR pBuffer, LONG cxGlyph ) { PUCHAR pjEnd = pGlyph + 2*cyGlyph; USHORT us;
do { us = *(PUSHORT)pGlyph; pGlyph +=2; *pBuffer = us & 0xff; *(pBuffer+1) = (UCHAR)(us >> 8); pBuffer += ulBufDelta; } while (pGlyph != pjEnd); }
//
// mov_first_2_wide_rotated_no_last::
//
VOID mov_first_2_wide_rotated_no_last( LONG cyGlyph, LONG RightRot, LONG ulBufDelta, PUCHAR pGlyph, PUCHAR pBuffer, LONG cxGlyph ) { PUCHAR pjEnd = pGlyph + cyGlyph; ULONG rl = 8-RightRot; UCHAR c0; UCHAR c1;
do { c0 = *pGlyph++; *pBuffer = c0 >> RightRot; *(pBuffer+1) = c0 << rl; pBuffer += ulBufDelta; } while (pGlyph != pjEnd); }
//
// or_first_3_wide_rotated_need_last::
//
VOID or_first_3_wide_rotated_need_last( LONG cyGlyph, LONG RightRot, LONG ulBufDelta, PUCHAR pGlyph, PUCHAR pBuffer, LONG cxGlyph ) { PUCHAR pjEnd = pGlyph + 3*cyGlyph; ULONG ul; UCHAR c0,c1,c2;
do { c0 = *pGlyph; c1 = *(pGlyph+1); c2 = *(pGlyph+2);
//
// make into big-endian ulong and shift
//
ul = (c0 << 16) | (c1 << 8) | c2; ul >>= RightRot;
*pBuffer |= (BYTE)(ul >> 16); *(pBuffer+1) = (BYTE)(ul >> 8); *(pBuffer+2) = (BYTE)(ul);
pGlyph += 3; pBuffer += ulBufDelta; } while (pGlyph != pjEnd); }
//
// or_all_3_wide_rotated_need_last::
//
VOID or_all_3_wide_rotated_need_last( LONG cyGlyph, LONG RightRot, LONG ulBufDelta, PUCHAR pGlyph, PUCHAR pBuffer, LONG cxGlyph ) { PUCHAR pjEnd = pGlyph + 3*cyGlyph; ULONG ul; UCHAR c0,c1,c2; do { c0 = *pGlyph; c1 = *(pGlyph+1); c2 = *(pGlyph+2);
//
// make into big-endian ulong and shift
//
ul = (c0 << 16) | (c1 << 8) | c2; ul >>= RightRot;
*pBuffer |= (BYTE)(ul >> 16); *(pBuffer+1) |= (BYTE)(ul >> 8); *(pBuffer+2) |= (BYTE)(ul);
pGlyph += 3; pBuffer += ulBufDelta;
} while (pGlyph != pjEnd); }
//
// or_all_3_wide_rotated_no_last::
//
VOID or_all_3_wide_rotated_no_last( LONG cyGlyph, LONG RightRot, LONG ulBufDelta, PUCHAR pGlyph, PUCHAR pBuffer, LONG cxGlyph ) { PUCHAR pjEnd = pGlyph + 2*cyGlyph; ULONG ul; UCHAR c0,c1;
do {
c0 = *pGlyph; c1 = *(pGlyph+1);
//
// make big-endian and shift
//
ul = (c0 << 16) | (c1 << 8); ul >>= RightRot;
//
// store result
//
*pBuffer |= (BYTE)(ul >> 16); *(pBuffer+1) |= (BYTE)(ul >> 8); *(pBuffer+2) |= (BYTE)ul;
pGlyph += 2; pBuffer += ulBufDelta;
} while (pGlyph != pjEnd); }
//
// or_first_3_wide_rotated_no_last::
//
VOID or_first_3_wide_rotated_no_last( LONG cyGlyph, LONG RightRot, LONG ulBufDelta, PUCHAR pGlyph, PUCHAR pBuffer, LONG cxGlyph ) { PUCHAR pjEnd = pGlyph + 2*cyGlyph; ULONG ul; UCHAR c0,c1;
do {
c0 = *pGlyph; c1 = *(pGlyph+1);
//
// make big-endian and shift
//
ul = (c0 << 16) | (c1 << 8); ul >>= RightRot;
//
// store result, only or in first byte
//
*pBuffer |= (BYTE)(ul >> 16); *(pBuffer+1) = (BYTE)(ul >> 8); *(pBuffer+2) = (BYTE)ul;
pGlyph += 2; pBuffer += ulBufDelta;
} while (pGlyph != pjEnd); }
//
// mov_first_3_wide_unrotated::
//
VOID mov_first_3_wide_unrotated( LONG cyGlyph, LONG RightRot, LONG ulBufDelta, PUCHAR pGlyph, PUCHAR pBuffer, LONG cxGlyph ) { PUCHAR pjEnd = pGlyph + 3*cyGlyph; ULONG rl = 8-RightRot; UCHAR c0,c1,c2;
do {
c0 = *pGlyph; c1 = *(pGlyph+1); c2 = *(pGlyph+2);
*pBuffer = c0; *(pBuffer+1) = c1; *(pBuffer+2) = c2;
pGlyph += 3; pBuffer += ulBufDelta;
} while (pGlyph != pjEnd); }
//
//or_all_3_wide_unrotated::
//
VOID or_all_3_wide_unrotated( LONG cyGlyph, LONG RightRot, LONG ulBufDelta, PUCHAR pGlyph, PUCHAR pBuffer, LONG cxGlyph ) { PUCHAR pjEnd = pGlyph + 3*cyGlyph; ULONG rl = 8-RightRot; UCHAR c0,c1,c2;
do { c0 = *pGlyph; c1 = *(pGlyph+1); c2 = *(pGlyph+2);
*pBuffer |= c0; *(pBuffer+1) |= c1; *(pBuffer+2) |= c2;
pBuffer += ulBufDelta; pGlyph += 3;
} while (pGlyph != pjEnd); }
//
// or_first_4_wide_rotated_need_last::
//
VOID or_first_4_wide_rotated_need_last( LONG cyGlyph, LONG RightRot, LONG ulBufDelta, PUCHAR pGlyph, PUCHAR pBuffer, LONG cxGlyph ) { PUCHAR pjEnd = pGlyph + 4*cyGlyph; ULONG ul; ULONG t0,t1,t2;
do {
ul = *(PULONG)pGlyph;
//
// endian swap
//
t0 = ul << 24; t1 = ul >> 24; t2 = (ul >> 8) & (0xff << 8); ul = (ul << 8) & (0xff << 16);
ul = ul | t0 | t1 | t2;
ul >>= RightRot;
*pBuffer |= (BYTE)(ul >> 24);
*(pBuffer+1) = (BYTE)(ul >> 16);
*(pBuffer+2) = (BYTE)(ul >> 8);
*(pBuffer+3) = (BYTE)(ul);
pGlyph += 4; pBuffer += ulBufDelta; } while (pGlyph != pjEnd); }
//
// or_all_4_wide_rotated_need_last::
//
VOID or_all_4_wide_rotated_need_last( LONG cyGlyph, LONG RightRot, LONG ulBufDelta, PUCHAR pGlyph, PUCHAR pBuffer, LONG cxGlyph ) { PUCHAR pjEnd = pGlyph + 4*cyGlyph; ULONG ul; ULONG t0,t1,t2;
do {
ul = *(PULONG)pGlyph;
//
// endian swap
//
t0 = ul << 24; t1 = ul >> 24; t2 = (ul >> 8) & (0xff << 8); ul = (ul << 8) & (0xff << 16);
ul = ul | t0 | t1 | t2;
ul >>= RightRot;
*pBuffer |= (BYTE)(ul >> 24);
*(pBuffer+1) |= (BYTE)(ul >> 16);
*(pBuffer+2) |= (BYTE)(ul >> 8);
*(pBuffer+3) |= (BYTE)(ul);
pGlyph += 4; pBuffer += ulBufDelta;
} while (pGlyph != pjEnd); }
//
// or_first_4_wide_rotated_no_last::
//
VOID or_first_4_wide_rotated_no_last( LONG cyGlyph, LONG RightRot, LONG ulBufDelta, PUCHAR pGlyph, PUCHAR pBuffer, LONG cxGlyph ) { PBYTE pjEnd = pGlyph + 3*cyGlyph; BYTE c0,c1,c2; ULONG ul;
while (pGlyph != pjEnd) {
//
// load src
//
c0 = *pGlyph; c1 = *(pGlyph+1); c2 = *(pGlyph+2);
//
// or into big endian ULONG and shift
//
ul = (c0 << 24) | (c1 << 16) | (c2 << 8); ul >>= RightRot;
//
// store result, ony or in fisrt byte
//
*pBuffer |= (BYTE)(ul >> 24);
*(pBuffer+1) = (BYTE)(ul >> 16);;
*(pBuffer+2) = (BYTE)(ul >> 8);
*(pBuffer+3) = (BYTE)(ul);
//
// inc scan line
//
pGlyph += 3; pBuffer += ulBufDelta; } }
//
// or_all_4_wide_rotated_no_last::
//
VOID or_all_4_wide_rotated_no_last( LONG cyGlyph, LONG RightRot, LONG ulBufDelta, PUCHAR pGlyph, PUCHAR pBuffer, LONG cxGlyph ) { PBYTE pjEnd = pGlyph + 3*cyGlyph; BYTE c0,c1,c2; ULONG ul;
while (pGlyph != pjEnd) {
//
// load src
//
c0 = *pGlyph; c1 = *(pGlyph+1); c2 = *(pGlyph+2);
//
// or into big endian ULONG and shift
//
ul = (c0 << 24) | (c1 << 16) | (c2 << 8); ul >>= RightRot;
//
// store result
//
*pBuffer |= (BYTE)(ul >> 24);
*(pBuffer+1) |= (BYTE)(ul >> 16);;
*(pBuffer+2) |= (BYTE)(ul >> 8);
*(pBuffer+3) |= (BYTE)(ul);
//
// inc scan line
//
pGlyph += 3; pBuffer += ulBufDelta; } }
VOID mov_first_4_wide_unrotated( LONG cyGlyph, LONG RightRot, LONG ulBufDelta, PUCHAR pGlyph, PUCHAR pBuffer, LONG cxGlyph ) { PUCHAR pjEnd = pGlyph + 4*cyGlyph;
switch ((ULONG_PTR)pBuffer & 0x03 ) { case 0:
while (pGlyph != pjEnd) { *(PULONG)pBuffer = *(PULONG)pGlyph; pGlyph += 4; pBuffer += ulBufDelta; } break;
case 1: case 3: while (pGlyph != pjEnd) {
*pBuffer = *pGlyph; *(pBuffer+1) = *(pGlyph+1); *(pBuffer+2) = *(pGlyph+2); *(pBuffer+3) = *(pGlyph+3);
pGlyph += 4; pBuffer += ulBufDelta; } break; case 2: while (pGlyph != pjEnd) {
*(PUSHORT)(pBuffer) = *(PUSHORT)pGlyph; *(PUSHORT)(pBuffer+2) = *(PUSHORT)(pGlyph+2);
pBuffer += ulBufDelta; pGlyph += 4; } break; } }
//
// or_all_4_wide_unrotated::
//
VOID or_all_4_wide_unrotated( LONG cyGlyph, LONG RightRot, LONG ulBufDelta, PUCHAR pGlyph, PUCHAR pBuffer, LONG cxGlyph ) { PUCHAR pjEnd = pGlyph + 4*cyGlyph;
switch ((ULONG_PTR)pBuffer & 0x03 ) { case 0:
while (pGlyph != pjEnd) {
*(PULONG)pBuffer |= *(PULONG)pGlyph;
pGlyph += 4; pBuffer += ulBufDelta; } break;
case 1: case 3:
while (pGlyph != pjEnd) {
*pBuffer |= *pGlyph; *(pBuffer+1) |= *(pGlyph+1); *(pBuffer+2) |= *(pGlyph+2); *(pBuffer+3) |= *(pGlyph+3);
pGlyph += 4; pBuffer += ulBufDelta; } break;
case 2:
while (pGlyph != pjEnd) {
*(PUSHORT)pBuffer |= *(PUSHORT)pGlyph; *(PUSHORT)(pBuffer+2) |= *(PUSHORT)(pGlyph+2);
pGlyph += 4; pBuffer += ulBufDelta; } break; } }
/******************************Public*Routine******************************\
* * Routine Name * * or_first_N_wide_rotated_need_last * * * Routine Description: * * Draw arbitrarily wide glyphs to 1BPP temp buffer * * * Arguments: * * cyGlyph - glyph height * RightRot - alignment * ulBufDelta - scan line stride of temp buffer * pGlyph - pointer to glyph bitmap * pBuffer - pointer to temp buffer * cxGlyph - glyph width in pixels * cxDst - Dest width in bytes * * Return Value: * * None * \**************************************************************************/ VOID or_first_N_wide_rotated_need_last( LONG cyGlyph, LONG RightRot, LONG ulBufDelta, PUCHAR pGlyph, PUCHAR pBuffer, LONG cxGlyph, LONG cxDst ) { PUCHAR pjDst = (PUCHAR)pBuffer; PUCHAR pjDstEnd; PUCHAR pjDstEndy = pBuffer + ulBufDelta * cyGlyph; LONG lStride = ulBufDelta - cxDst; LONG rl = 8-RightRot;
//
// source doesn't advance after first byte, and
// we do the first byte outside the loop
//
do {
UCHAR c0 = *pGlyph++; UCHAR c1; pjDstEnd = pjDst + cxDst;
*pjDst |= c0 >> RightRot; pjDst++; c1 = c0 << rl;
//
// know cxDst is at least 4, use do-while
//
do { c0 = *pGlyph; *pjDst = (c0 >> RightRot) | c1; c1 = c0 << rl; pjDst++; pGlyph++;
} while (pjDst != pjDstEnd);
pjDst += lStride;
} while (pjDst != pjDstEndy); }
VOID or_all_N_wide_rotated_need_last( LONG cyGlyph, LONG RightRot, LONG ulBufDelta, PUCHAR pGlyph, PUCHAR pBuffer, LONG cxGlyph, LONG cxDst ) { PUCHAR pjDst = (PUCHAR)pBuffer; PUCHAR pjDstEnd; PUCHAR pjDstEndy = pBuffer + ulBufDelta * cyGlyph; LONG lStride = ulBufDelta - cxDst; LONG rl = 8-RightRot;
//
// source doesn't advance after first byte, and
// we do the first byte outside the loop
//
do {
UCHAR c0 = *pGlyph++; UCHAR c1; pjDstEnd = pjDst + cxDst;
*pjDst |= c0 >> RightRot; pjDst++; c1 = c0 << rl;
//
// know cxDst is at least 4, use do-while
//
do { c0 = *pGlyph; *pjDst |= ((c0 >> RightRot) | c1); c1 = c0 << rl; pjDst++; pGlyph++;
} while (pjDst != pjDstEnd);
pjDst += lStride;
} while (pjDst != pjDstEndy); }
VOID or_first_N_wide_rotated_no_last( LONG cyGlyph, LONG RightRot, LONG ulBufDelta, PUCHAR pGlyph, PUCHAR pBuffer, LONG cxGlyph, LONG cxDst ) { PUCHAR pjDst = (PUCHAR)pBuffer; PUCHAR pjDstEnd; PUCHAR pjDstEndy = pBuffer + ulBufDelta * cyGlyph; LONG lStride = ulBufDelta - cxDst; LONG rl = 8-RightRot;
//
// source doesn't advance after first byte, and
// we do the first byte outside the loop
//
do {
UCHAR c0; UCHAR c1; pjDstEnd = pjDst + cxDst - 1;
//
// do first dest byte outside loop for OR
//
c1 = 0; c0 = *pGlyph; *pjDst |= ((c0 >> RightRot) | c1); pjDst++; pGlyph++;
//
// know cxDst is at least 4, use do-while
//
do { c0 = *pGlyph; *pjDst = ((c0 >> RightRot) | c1); c1 = c0 << rl; pjDst++; pGlyph++;
} while (pjDst != pjDstEnd);
//
// last dst byte outside loop, no new src needed
//
*pjDst = c1; pjDst++;
pjDst += lStride;
} while (pjDst != pjDstEndy); }
VOID or_all_N_wide_rotated_no_last( LONG cyGlyph, LONG RightRot, LONG ulBufDelta, PUCHAR pGlyph, PUCHAR pBuffer, LONG cxGlyph, LONG cxDst ) { PUCHAR pjDst = (PUCHAR)pBuffer; PUCHAR pjDstEnd; PUCHAR pjDstEndy = pBuffer + ulBufDelta * cyGlyph; LONG lStride = ulBufDelta - cxDst; LONG rl = 8-RightRot;
//
// source doesn't advance after first byte, and
// we do the first byte outside the loop
//
do {
UCHAR c0; UCHAR c1; pjDstEnd = pjDst + cxDst - 1;
//
// do first dest byte outside loop for OR
//
c1 = 0;
//
// know cxDst is at least 4, use do-while
//
do { c0 = *pGlyph; *pjDst |= ((c0 >> RightRot) | c1); c1 = c0 << rl; pjDst++; pGlyph++;
} while (pjDst != pjDstEnd);
//
// last dst byte outside loop, no new src needed
//
*pjDst |= c1; pjDst++;
pjDst += lStride;
} while (pjDst != pjDstEndy); }
//
// The following routines can be significantly sped up by
// breaking them out into DWORD alignment cases.
//
VOID mov_first_N_wide_unrotated( LONG cyGlyph, LONG RightRot, LONG ulBufDelta, PUCHAR pGlyph, PUCHAR pBuffer, LONG cxGlyph, LONG cxDst ) { PUCHAR pjDst = (PUCHAR)pBuffer; PUCHAR pjDstEnd; PUCHAR pjDstEndy = pBuffer + ulBufDelta * cyGlyph; LONG lStride = ulBufDelta - cxDst;
//
// byte aligned copy
//
do {
pjDstEnd = pjDst + cxDst;
//
// let compiler unroll inner loop
//
do {
*pjDst++ = *pGlyph++;
} while (pjDst != pjDstEnd );
pjDst += lStride;
} while (pjDst != pjDstEndy); }
VOID or_all_N_wide_unrotated( LONG cyGlyph, LONG RightRot, LONG ulBufDelta, PUCHAR pGlyph, PUCHAR pBuffer, LONG cxGlyph, LONG cxDst ) { PUCHAR pjDst = (PUCHAR)pBuffer; PUCHAR pjDstEnd; PUCHAR pjDstEndy = pBuffer + ulBufDelta * cyGlyph; LONG lStride = ulBufDelta - cxDst;
//
// byte aligned copy
//
do {
pjDstEnd = pjDst + cxDst;
//
// let compiler unroll inner loop
//
do {
*pjDst++ |= *pGlyph++;
} while (pjDst != pjDstEnd );
pjDst += lStride;
} while (pjDst != pjDstEndy); }
VOID exit_fast_text(LONG,LONG,LONG,PUCHAR,PUCHAR,LONG); VOID or_all_1_wide_rotated_need_last(LONG,LONG,LONG,PUCHAR,PUCHAR,LONG); VOID or_all_1_wide_unrotated (LONG,LONG,LONG,PUCHAR,PUCHAR,LONG); VOID or_all_1_wide_unrotated (LONG,LONG,LONG,PUCHAR,PUCHAR,LONG); VOID or_all_2_wide_rotated_need_last(LONG,LONG,LONG,PUCHAR,PUCHAR,LONG); VOID or_all_2_wide_unrotated (LONG,LONG,LONG,PUCHAR,PUCHAR,LONG); VOID or_all_2_wide_rotated_no_last (LONG,LONG,LONG,PUCHAR,PUCHAR,LONG); VOID or_all_2_wide_unrotated (LONG,LONG,LONG,PUCHAR,PUCHAR,LONG); VOID or_all_3_wide_rotated_need_last(LONG,LONG,LONG,PUCHAR,PUCHAR,LONG); VOID or_all_3_wide_unrotated (LONG,LONG,LONG,PUCHAR,PUCHAR,LONG); VOID or_all_3_wide_rotated_no_last (LONG,LONG,LONG,PUCHAR,PUCHAR,LONG); VOID or_all_3_wide_unrotated (LONG,LONG,LONG,PUCHAR,PUCHAR,LONG); VOID or_all_4_wide_rotated_need_last(LONG,LONG,LONG,PUCHAR,PUCHAR,LONG); VOID or_all_4_wide_unrotated (LONG,LONG,LONG,PUCHAR,PUCHAR,LONG); VOID or_all_4_wide_rotated_no_last (LONG,LONG,LONG,PUCHAR,PUCHAR,LONG); VOID or_all_4_wide_unrotated (LONG,LONG,LONG,PUCHAR,PUCHAR,LONG); VOID or_all_N_wide_rotated_need_last(LONG,LONG,LONG,PUCHAR,PUCHAR,LONG,LONG); VOID or_all_N_wide_unrotated (LONG,LONG,LONG,PUCHAR,PUCHAR,LONG,LONG); VOID or_all_N_wide_rotated_no_last (LONG,LONG,LONG,PUCHAR,PUCHAR,LONG,LONG); VOID or_all_N_wide_unrotated (LONG,LONG,LONG,PUCHAR,PUCHAR,LONG,LONG);
PVOID OrAllTableNarrow[] = { exit_fast_text, exit_fast_text, exit_fast_text, exit_fast_text, or_all_1_wide_rotated_need_last, or_all_1_wide_unrotated, or_all_1_wide_rotated_need_last, or_all_1_wide_unrotated, or_all_2_wide_rotated_need_last, or_all_2_wide_unrotated, or_all_2_wide_rotated_no_last, or_all_2_wide_unrotated, or_all_3_wide_rotated_need_last, or_all_3_wide_unrotated, or_all_3_wide_rotated_no_last, or_all_3_wide_unrotated, or_all_4_wide_rotated_need_last, or_all_4_wide_unrotated, or_all_4_wide_rotated_no_last, or_all_4_wide_unrotated };
PVOID OrInitialTableNarrow[] = { exit_fast_text , exit_fast_text , exit_fast_text , exit_fast_text ,
or_all_1_wide_rotated_need_last , mov_first_1_wide_unrotated , or_all_1_wide_rotated_need_last , mov_first_1_wide_unrotated ,
or_first_2_wide_rotated_need_last , mov_first_2_wide_unrotated , or_first_2_wide_rotated_no_last , mov_first_2_wide_unrotated ,
or_first_3_wide_rotated_need_last , mov_first_3_wide_unrotated , or_first_3_wide_rotated_no_last , mov_first_3_wide_unrotated , or_first_4_wide_rotated_need_last , mov_first_4_wide_unrotated , or_first_4_wide_rotated_no_last , mov_first_4_wide_unrotated };
//
// Handles arbitrarily wide glyph drawing, for case where initial byte should be
// ORed if it's not aligned (intended for use in drawing all but the first glyph
// in a string). Table format is:
// Bit 1 : 1 if don't need last source byte, 0 if do need last source byte
// Bit 0 : 1 if no rotation (aligned), 0 if rotation (non-aligned)
//
PVOID OrInitialTableWide[] = { or_first_N_wide_rotated_need_last, mov_first_N_wide_unrotated, or_first_N_wide_rotated_no_last, mov_first_N_wide_unrotated };
//
// Handles arbitrarily wide glyph drawing, for case where all bytes should
// be ORed (intended for use in drawing potentially overlapping glyphs).
// Table format is:
// Bit 1 : 1 if don't need last source byte, 0 if do need last source byte
// Bit 0 : 1 if no rotation (aligned), 0 if rotation (non-aligned)
//
//
PVOID OrAllTableWide[] = { or_all_N_wide_rotated_need_last, or_all_N_wide_unrotated, or_all_N_wide_rotated_no_last, or_all_N_wide_unrotated };
/******************************Public*Routine******************************\
* * Routine Name * * draw_nf_ntb_o_to_temp_start * * Routine Description: * * 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 * * Arguments: * * pGlyphPos - Pointer to first in list of GLYPHPOS structs * cGlyph - Number of glyphs to draw * pjTempBuffer - Pointer to temp 1Bpp buffer to draw into * ulLeftEdge - left edge of TextRect & 0xFFFFFFF80 * TempBufDelta - Scan line Delta for TempBuffer (always pos) * * Return Value: * * None * \**************************************************************************/ VOID draw_nf_ntb_o_to_temp_start( PGLYPHPOS pGlyphPos, ULONG cGlyphs, PUCHAR pjTempBuffer, ULONG ulLeftEdge, ULONG TempBufDelta, ULONG ulCharInc, ULONG ulTempTop ) {
LONG NumScans; LONG RightRot; PBYTE pGlyphData; PBYTE pTempOutput; GLYPHBITS *pGlyphBits; LONG GlyphPosX; LONG GlyphPixels; LONG GlyphAlignment; LONG SrcBytes; LONG DstBytes; ULONG ulDrawFlag; PFN_GLYPHLOOPN pfnGlyphLoopN; PFN_GLYPHLOOP pfnGlyphLoop; ULONG iGlyph = 0; LONG GlyphPosY;
//
// Draw non fixed pitch, tops and bottoms not aligned,overlap
//
while (cGlyphs--) {
pGlyphBits = pGlyphPos[iGlyph].pgdf->pgb;
//
// Glyph position in temp buffer = point.x + org.c - (TextRect.left & 0xffffffe0)
//
GlyphPosX = pGlyphPos[iGlyph].ptl.x + pGlyphPos[iGlyph].pgdf->pgb->ptlOrigin.x - ulLeftEdge; GlyphPosY = pGlyphPos[iGlyph].ptl.y + pGlyphPos[iGlyph].pgdf->pgb->ptlOrigin.y - ulTempTop ; GlyphAlignment = GlyphPosX & 0x07;
//
// calc byte offset
//
pTempOutput = pjTempBuffer + (GlyphPosX >> 3);
//
// glyph width
//
GlyphPixels = pGlyphPos[iGlyph].pgdf->pgb->sizlBitmap.cx;
//
// source and dest bytes required
//
DstBytes = ((GlyphAlignment) + GlyphPixels + 7) >> 3; SrcBytes = (GlyphPixels + 7) >> 3;
pTempOutput += (GlyphPosY * TempBufDelta);
if (DstBytes <= 4) {
//
// use narrow initial table
//
ulDrawFlag = ( (DstBytes << 2) | ((DstBytes > SrcBytes) << 1) | ((GlyphAlignment == 0)) );
pfnGlyphLoop = (PFN_GLYPHLOOP)OrAllTableNarrow[ulDrawFlag];
pfnGlyphLoop( pGlyphPos[iGlyph].pgdf->pgb->sizlBitmap.cy, GlyphAlignment, TempBufDelta, pGlyphPos[iGlyph].pgdf->pgb->aj, pTempOutput, SrcBytes );
} else {
//
// use wide glyph drawing
//
ulDrawFlag = ( ((DstBytes > SrcBytes) << 1) | ((GlyphAlignment == 0)) );
pfnGlyphLoopN = (PFN_GLYPHLOOPN)OrAllTableWide[ulDrawFlag];
pfnGlyphLoopN( pGlyphPos[iGlyph].pgdf->pgb->sizlBitmap.cy, GlyphAlignment, TempBufDelta, pGlyphPos[iGlyph].pgdf->pgb->aj, pTempOutput, SrcBytes, DstBytes );
}
iGlyph++; }
}
/******************************Public*Routine******************************\
* * Routine Name * * draw_f_ntb_o_to_temp_start * * Routine Description: * * 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 * * Arguments: * * pGlyphPos - Pointer to first in list of GLYPHPOS structs * cGlyph - Number of glyphs to draw * pjTempBuffer - Pointer to temp 1Bpp buffer to draw into * ulLeftEdge - left edge of TextRect & 0xFFFFFFF80 * TempBufDelta - Scan line Delta for TempBuffer (always pos) * * Return Value: * * None * \**************************************************************************/ VOID draw_f_ntb_o_to_temp_start( PGLYPHPOS pGlyphPos, ULONG cGlyphs, PUCHAR pjTempBuffer, ULONG ulLeftEdge, ULONG TempBufDelta, ULONG ulCharInc, ULONG ulTempTop ) { LONG NumScans; LONG RightRot; PBYTE pGlyphData; PBYTE pTempOutput; GLYPHBITS *pGlyphBits; LONG GlyphPosX; LONG GlyphPixels; LONG GlyphAlignment; LONG SrcBytes; LONG DstBytes; ULONG ulDrawFlag; PFN_GLYPHLOOP pfnGlyphLoop; PFN_GLYPHLOOPN pfnGlyphLoopN; ULONG iGlyph = 0; LONG GlyphPitchX; LONG GlyphPitchY; LONG GlyphPosY;
//
// Draw fixed pitch, tops and bottoms not aligned,overlap
//
GlyphPitchX = pGlyphPos->ptl.x - ulLeftEdge; GlyphPitchY = pGlyphPos->ptl.y - ulTempTop;
while (cGlyphs--) {
pGlyphBits = pGlyphPos[iGlyph].pgdf->pgb;
//
// Glyph position in temp buffer = point.x + org.c - (TextRect.left & 0xfffffff8)
//
GlyphPosX = GlyphPitchX + pGlyphPos[iGlyph].pgdf->pgb->ptlOrigin.x; GlyphPosY = GlyphPitchY + pGlyphPos[iGlyph].pgdf->pgb->ptlOrigin.y;
GlyphAlignment = GlyphPosX & 0x07;
//
// calc byte offset
//
pTempOutput = pjTempBuffer + (GlyphPosX >> 3);
//
// glyph width
//
GlyphPixels = pGlyphPos[iGlyph].pgdf->pgb->sizlBitmap.cx;
//
// source and dest bytes required
//
DstBytes = ((GlyphAlignment) + GlyphPixels + 7) >> 3; SrcBytes = (GlyphPixels + 7) >> 3;
//
// calc glyph destination scan line
//
pTempOutput += (GlyphPosY * TempBufDelta);
if (DstBytes <= 4) {
//
// use narrow initial table
//
ulDrawFlag = ( (DstBytes << 2) | ((DstBytes > SrcBytes) << 1) | ((GlyphAlignment == 0)) );
pfnGlyphLoop = (PFN_GLYPHLOOP)OrAllTableNarrow[ulDrawFlag];
pfnGlyphLoop( pGlyphPos[iGlyph].pgdf->pgb->sizlBitmap.cy, GlyphAlignment, TempBufDelta, pGlyphPos[iGlyph].pgdf->pgb->aj, pTempOutput, SrcBytes );
} else {
//
// use wide glyph drawing
//
ulDrawFlag = ( ((DstBytes > SrcBytes) << 1) | ((GlyphAlignment == 0)) );
pfnGlyphLoopN = (PFN_GLYPHLOOPN)OrAllTableWide[ulDrawFlag];
pfnGlyphLoopN( pGlyphPos[iGlyph].pgdf->pgb->sizlBitmap.cy, GlyphAlignment, TempBufDelta, pGlyphPos[iGlyph].pgdf->pgb->aj, pTempOutput, SrcBytes, DstBytes );
}
GlyphPitchX += ulCharInc; iGlyph++; }
}
/******************************Public*Routine******************************\
* * Routine Name * * draw_nf_tb_no_to_temp_start * * Routine Description: * * 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 * * Arguments: * * pGlyphPos - Pointer to first in list of GLYPHPOS structs * cGlyph - Number of glyphs to draw * pjTempBuffer - Pointer to temp 1Bpp buffer to draw into * ulLeftEdge - left edge of TextRect & 0xFFFFFFF80 * TempBufDelta - Scan line Delta for TempBuffer (always pos) * * Return Value: * * None * \**************************************************************************/ VOID draw_nf_tb_no_to_temp_start( PGLYPHPOS pGlyphPos, ULONG cGlyphs, PUCHAR pjTempBuffer, ULONG ulLeftEdge, ULONG TempBufDelta, ULONG ulCharInc, ULONG ulTempTop ) {
LONG NumScans; LONG RightRot; PBYTE pGlyphData; PBYTE pTempOutput; GLYPHBITS *pGlyphBits; LONG GlyphPosX; LONG GlyphPixels; LONG GlyphAlignment; LONG SrcBytes; LONG DstBytes; ULONG ulDrawFlag; PFN_GLYPHLOOP pfnGlyphLoop; PFN_GLYPHLOOPN pfnGlyphLoopN; ULONG iGlyph = 0;
//
// Draw non fixed pitch, tops and bottoms not aligned,overlap
//
while (cGlyphs--) {
pGlyphBits = pGlyphPos[iGlyph].pgdf->pgb;
//
// Glyph position in temp buffer = point.x + org.c - (TextRect.left & 0xfffffff8)
//
GlyphPosX = pGlyphPos[iGlyph].ptl.x + pGlyphPos[iGlyph].pgdf->pgb->ptlOrigin.x - ulLeftEdge; GlyphAlignment = GlyphPosX & 0x07;
//
// calc byte offset
//
pTempOutput = pjTempBuffer + (GlyphPosX >> 3);
//
// glyph width
//
GlyphPixels = pGlyphPos[iGlyph].pgdf->pgb->sizlBitmap.cx;
//
// source and dest bytes required
//
DstBytes = ((GlyphAlignment) + GlyphPixels + 7) >> 3; SrcBytes = (GlyphPixels + 7) >> 3;
if (DstBytes <= 4) {
//
// use narrow initial table
//
ulDrawFlag = ( (DstBytes << 2) | ((DstBytes > SrcBytes) << 1) | ((GlyphAlignment == 0)) );
pfnGlyphLoop = (PFN_GLYPHLOOP)OrInitialTableNarrow[ulDrawFlag];
pfnGlyphLoop( pGlyphPos[iGlyph].pgdf->pgb->sizlBitmap.cy, GlyphAlignment, TempBufDelta, pGlyphPos[iGlyph].pgdf->pgb->aj, pTempOutput, SrcBytes );
} else {
//
// use wide glyph drawing
//
ulDrawFlag = ( ((DstBytes > SrcBytes) << 1) | ((GlyphAlignment == 0)) );
pfnGlyphLoopN = (PFN_GLYPHLOOPN)OrAllTableWide[ulDrawFlag];
pfnGlyphLoopN( pGlyphPos[iGlyph].pgdf->pgb->sizlBitmap.cy, GlyphAlignment, TempBufDelta, pGlyphPos[iGlyph].pgdf->pgb->aj, pTempOutput, SrcBytes, DstBytes );
}
iGlyph++; }
}
/******************************Public*Routine******************************\
* * Routine Name * * draw_f_tb_no_to_temp_start * * Routine Description: * * 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 * * Arguments: * * pGlyphPos - Pointer to first in list of GLYPHPOS structs * cGlyph - Number of glyphs to draw * pjTempBuffer - Pointer to temp 1Bpp buffer to draw into * ulLeftEdge - left edge of TextRect & 0xFFFFFFF80 * TempBufDelta - Scan line Delta for TempBuffer (always pos) * * Return Value: * * None * \**************************************************************************/
VOID draw_f_tb_no_to_temp_start( PGLYPHPOS pGlyphPos, ULONG cGlyphs, PUCHAR pjTempBuffer, ULONG ulLeftEdge, ULONG TempBufDelta, ULONG ulCharInc, ULONG ulTempTop ) {
LONG NumScans; LONG RightRot; PBYTE pGlyphData; PBYTE pTempOutput; GLYPHBITS *pGlyphBits; LONG GlyphPosX; LONG GlyphPixels; LONG GlyphAlignment; LONG SrcBytes; LONG DstBytes; ULONG ulDrawFlag; PFN_GLYPHLOOPN pfnGlyphLoopN; PFN_GLYPHLOOP pfnGlyphLoop; ULONG iGlyph = 0; LONG GlyphPitchX;
GlyphPitchX = pGlyphPos->ptl.x;
//
// Draw fixed pitch, tops and bottoms not aligned,overlap
//
while (cGlyphs--) {
pGlyphBits = pGlyphPos[iGlyph].pgdf->pgb;
//
// Glyph position in temp buffer = point.x + org.c - (TextRect.left & 0xfffffff8)
//
GlyphPosX = GlyphPitchX + pGlyphPos[iGlyph].pgdf->pgb->ptlOrigin.x - ulLeftEdge; GlyphAlignment = GlyphPosX & 0x07;
//
// calc byte offset
//
pTempOutput = pjTempBuffer + (GlyphPosX >> 3);
//
// glyph width
//
GlyphPixels = pGlyphPos[iGlyph].pgdf->pgb->sizlBitmap.cx;
//
// source and dest bytes required
//
DstBytes = ((GlyphAlignment) + GlyphPixels + 7) >> 3; SrcBytes = (GlyphPixels + 7) >> 3;
if (DstBytes <= 4) {
//
// use narrow initial table
//
ulDrawFlag = ( (DstBytes << 2) | ((DstBytes > SrcBytes) << 1) | (GlyphAlignment == 0) );
pfnGlyphLoop = (PFN_GLYPHLOOP)OrInitialTableNarrow[ulDrawFlag];
pfnGlyphLoop( pGlyphPos[iGlyph].pgdf->pgb->sizlBitmap.cy, GlyphAlignment, TempBufDelta, pGlyphPos[iGlyph].pgdf->pgb->aj, pTempOutput, SrcBytes );
} else {
//
// use wide glyph drawing
//
ulDrawFlag = ( ((DstBytes > SrcBytes) << 1) | ((GlyphAlignment == 0)) );
pfnGlyphLoopN = (PFN_GLYPHLOOPN)OrAllTableWide[ulDrawFlag];
pfnGlyphLoopN( pGlyphPos[iGlyph].pgdf->pgb->sizlBitmap.cy, GlyphAlignment, TempBufDelta, pGlyphPos[iGlyph].pgdf->pgb->aj, pTempOutput, SrcBytes, DstBytes );
}
iGlyph++; GlyphPitchX += ulCharInc;
}
} #endif
|