/******************************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