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.
2313 lines
71 KiB
2313 lines
71 KiB
/******************************Module*Header*******************************\
|
|
* Module Name: rleblt4.cxx
|
|
*
|
|
* This contains the bitmap simulation functions that blt from a 4 bit
|
|
* Run-Length Encoded (RLE) source to a DIB surface. The DIB surface can be
|
|
* 1, 4, 8, 16, 24, or 32 bits/pel.
|
|
*
|
|
* The code is based on functions found in 'rleblt8.cxx', version 2.
|
|
*
|
|
* Added RLE Encoding functions: 10 Oct 92 @ 10:18
|
|
* Gerrit van Wingerden [gerritv]
|
|
*
|
|
* Created: 03 Feb 92 @ 21:00
|
|
*
|
|
* Author: Andrew Milton (w-andym)
|
|
*
|
|
* Notes:
|
|
*
|
|
* 1) These functions return a BOOL value. This value is TRUE if the
|
|
* function ends before running out of data in the source RLE or before
|
|
* hitting an End-of-Bitmap code. Otherwise, we return FALSE. This return
|
|
* value is used by <EngCopyajBits> in the complex clipping case to decide
|
|
* if the blt is complete.
|
|
*
|
|
* 2) Before exiting a function with a TRUE value, position information is
|
|
* saved by the macro <RLE_SavePosition>. This is used by <EngCopyajBits>
|
|
* to speed up the complex clipping case.
|
|
*
|
|
* 3) The below functions use about twenty different macros. This is
|
|
* because they are all using the same basic algorithm to play an RLE
|
|
* compression. The macros allow us to focus in on the nifty stuff of writing
|
|
* the bytes out to the DIB. Routine administrivia is handled by the macros.
|
|
*
|
|
* The macros themselves are used to manage
|
|
*
|
|
* - Source Access and data alignment
|
|
* - Visability Checking
|
|
* - Output position changes with Newline & Delta codes
|
|
*
|
|
* The macro <RLE_InitVars> is used to define the varibles that relate to
|
|
* the above information, and to define variables common to all RLE 4
|
|
* blt functions. Note that actual names of the common variables are passed
|
|
* in as parameters to the macro. Why? Two reasons. Firstly, they are
|
|
* initialized by values taken of the BLTINFO structure passed into the blt
|
|
* function. Secondly, showing the variable names in the macro 'call' means
|
|
* they don't just appear from nowhere into the function. RLE_InitVars
|
|
* is the one macro that you should think three times about before modifying.
|
|
*
|
|
* One further note. The variables 'ulDstLeft' and 'ulDstRight' appear to
|
|
* come from nowhere. This is not true. They are in fact declared by the
|
|
* macro <RLE_GetVisibleRect>. However, showing these names in the macro
|
|
* 'call' tended to obscure the code. Pretend you can see the declaration.
|
|
*
|
|
* Where can I find a macro definition?
|
|
*
|
|
* Good question, glad you asked. Look at the prefix:
|
|
*
|
|
* RLE_<stuff> - lives in RLEBLT.H
|
|
* RLE4_<blah> - lives in RLE4BLT.H
|
|
*
|
|
* Anything else in here that looks like function call is not. It's a macro.
|
|
* Probably for bitwise manipulations. Look for it in BITMANIP.H or in
|
|
* the Miscellaneous section of RLEBLT.H
|
|
*
|
|
* 4) The 8 and 16 ajBits/Pel cases can be optimized by packing the source
|
|
* colours into a word / dword. However, to actually see some net gain in
|
|
* run time, it will take some tricky-dicky-doo pointer alignment checking.
|
|
* This sort of thing may break on MIPS.
|
|
*
|
|
*
|
|
* Copyright (c) 1990-1999 Microsoft Corporation
|
|
*
|
|
\**************************************************************************/
|
|
|
|
#include "precomp.hxx"
|
|
|
|
/*******************************Public*Routine*****************************\
|
|
* bSrcCopySRLE4D8
|
|
*
|
|
* Secure RLE blting that does clipping and won't die or write somewhere
|
|
* it shouldn't if given bad data.
|
|
*
|
|
* History:
|
|
* 3 Feb 1992 - Andrew Milton (w-andym): Creation.
|
|
*
|
|
\**************************************************************************/
|
|
|
|
BOOL
|
|
bSrcCopySRLE4D8(
|
|
PBLTINFO psb)
|
|
{
|
|
|
|
// Common RLE Initialization
|
|
|
|
RLE_InitVars(psb, pjSrc, pjDst, PBYTE, ulCount, ulNext, lOutCol, pulXlate);
|
|
RLE_AssertValid(psb);
|
|
RLE_FetchVisibleRect(psb);
|
|
RLE_SetStartPos(psb, lOutCol);
|
|
|
|
// Outta here if we start past the top edge. Don't need to save our position.
|
|
|
|
if (RLE_PastTopEdge)
|
|
return(TRUE); // Must have bits left in the bitmap since we haven't
|
|
// consumed any.
|
|
// Extra Variables
|
|
|
|
BYTE jSource; // Packed RLE 4 colour code
|
|
BYTE ajColours[2]; // Destination for unpacking an RLE 4 code
|
|
BOOL bExtraByte; // TRUE when an absolute run ends with a partial byte
|
|
ULONG ulClipMargin; // Number of bytes clipped in an Encoded run
|
|
|
|
|
|
// Main process loop
|
|
|
|
LOOP_FOREVER
|
|
{
|
|
// Outta here if we can't get two more bytes
|
|
|
|
if (RLE_SourceExhausted(2))
|
|
return(FALSE);
|
|
|
|
RLE_GetNextCode(pjSrc, ulCount, ulNext);
|
|
|
|
if (ulCount == 0)
|
|
{
|
|
// Absolute or Escape Mode.
|
|
|
|
switch (ulNext)
|
|
{
|
|
case 0:
|
|
|
|
// New Line
|
|
|
|
RLE_NextLine(PBYTE, pjDst, lOutCol);
|
|
|
|
if (RLE_PastTopEdge)
|
|
{
|
|
RLE_SavePosition(psb, pjSrc, pjDst, lOutCol);
|
|
return(TRUE);
|
|
}
|
|
|
|
break;
|
|
|
|
case 1:
|
|
|
|
// End of the bitmap
|
|
|
|
return(FALSE);
|
|
|
|
case 2:
|
|
|
|
/* Positional Delta.
|
|
* The delta values live in the next two source bytes
|
|
*/
|
|
|
|
// Outta here if we can't get two more bytes
|
|
|
|
if (RLE_SourceExhausted(2))
|
|
return(FALSE);
|
|
|
|
RLE_GetNextCode(pjSrc, ulCount, ulNext);
|
|
RLE_PosDelta(pjDst, lOutCol, ulCount, ulNext);
|
|
|
|
if (RLE_PastTopEdge)
|
|
{
|
|
RLE_SavePosition(psb, pjSrc, pjDst, lOutCol);
|
|
return(TRUE);
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
/* Absolute Mode.
|
|
* The run length is stored in <ulNext>, <ulCount> is used to
|
|
* hold left and right clip amounts.
|
|
*/
|
|
|
|
// Outta here if the bytes aren't in the source
|
|
|
|
if (RLE_SourceExhausted(RLE4_ByteLength(ulNext)))
|
|
return(FALSE);
|
|
|
|
RLE4_AlignToWord(pjSrc, ulNext);
|
|
|
|
if (RLE_InVisibleRect(ulNext, lOutCol))
|
|
{
|
|
// Left Side Clipping
|
|
|
|
if (lOutCol < (LONG)ulDstLeft)
|
|
{
|
|
ulCount = ulDstLeft - lOutCol;
|
|
ulNext -= ulCount;
|
|
lOutCol += ulCount;
|
|
|
|
pjSrc += (ulCount >> 1);
|
|
|
|
// Force the Source Run to a byte boundary
|
|
|
|
if (bIsOdd(ulCount))
|
|
{
|
|
jSource = *pjSrc++;
|
|
pjDst[lOutCol] =
|
|
(BYTE) pulXlate[GetLowNybble(jSource)];
|
|
lOutCol++;
|
|
ulNext--;
|
|
}
|
|
|
|
}
|
|
|
|
// Right Side Clipping.
|
|
|
|
if ((lOutCol + (LONG) ulNext) > (LONG)ulDstRight)
|
|
{
|
|
ulCount = (lOutCol + ulNext) - ulDstRight;
|
|
ulNext -= ulCount;
|
|
}
|
|
else
|
|
ulCount = 0;
|
|
|
|
// Slap the bits on. -- this is the funky-doodle stuff.
|
|
|
|
bExtraByte = (BOOL) bIsOdd(ulNext);
|
|
ulNext >>= 1;
|
|
|
|
// Write complete bytes from the source
|
|
|
|
while (ulNext)
|
|
{
|
|
jSource = *pjSrc++;
|
|
RLE4_MakeColourBlock(jSource, ajColours, BYTE,
|
|
pulXlate);
|
|
pjDst[lOutCol] = ajColours[0];
|
|
pjDst[lOutCol+1] = ajColours[1];
|
|
lOutCol += 2;
|
|
ulNext--;
|
|
}
|
|
|
|
// Account for a partial source byte in the run
|
|
|
|
if (bExtraByte)
|
|
{
|
|
jSource = *pjSrc++;
|
|
pjDst[lOutCol] =
|
|
(BYTE) pulXlate[GetHighNybble(jSource)];
|
|
lOutCol++;
|
|
pjSrc += (ulCount >> 1); // Clip Adjustment
|
|
}
|
|
else
|
|
pjSrc += ((ulCount + 1) >> 1); // Clip Adjustment
|
|
|
|
// Adjust the column for the right side clipping.
|
|
|
|
lOutCol += ulCount;
|
|
|
|
}
|
|
else
|
|
{
|
|
/* Not on a visible scanline.
|
|
* Adjust our x output position and source pointer.
|
|
*/
|
|
|
|
lOutCol += ulNext;
|
|
pjSrc += (ulNext + 1) >> 1;
|
|
|
|
} /* if */
|
|
|
|
// Pad so the run ends on a WORD boundary
|
|
|
|
RLE4_FixAlignment(pjSrc)
|
|
|
|
} /* switch */
|
|
}
|
|
else
|
|
{
|
|
/* Encoded Mode
|
|
* The run length is stored in <ulCount>, <ulClipMargin> is used
|
|
* to hold left and right clip amounts.
|
|
*/
|
|
|
|
if (RLE_InVisibleRect(ulCount, lOutCol))
|
|
{
|
|
|
|
// Left Side Clipping
|
|
|
|
if (lOutCol < (LONG)ulDstLeft)
|
|
{
|
|
ulClipMargin = ulDstLeft - lOutCol;
|
|
ulCount -= ulClipMargin;
|
|
lOutCol += ulClipMargin;
|
|
}
|
|
|
|
// Right Side Clipping
|
|
|
|
if ((lOutCol + (LONG) ulCount) > (LONG)ulDstRight)
|
|
{
|
|
ulClipMargin = (lOutCol + ulCount) - ulDstRight;
|
|
ulCount -= ulClipMargin;
|
|
}
|
|
else
|
|
ulClipMargin = 0;
|
|
|
|
// Setup for the run
|
|
|
|
bExtraByte = (BOOL) bIsOdd(ulCount);
|
|
ulCount >>= 1;
|
|
RLE4_MakeColourBlock(ulNext, ajColours, BYTE, pulXlate);
|
|
|
|
// Write it
|
|
|
|
while (ulCount)
|
|
{
|
|
pjDst[lOutCol] = ajColours[0];
|
|
pjDst[lOutCol+1] = ajColours[1];
|
|
lOutCol += 2;
|
|
ulCount--;
|
|
}
|
|
|
|
/* Write the extra byte from an odd run length */
|
|
|
|
if (bExtraByte)
|
|
{
|
|
pjDst[lOutCol] = ajColours[0];
|
|
lOutCol++;
|
|
}
|
|
|
|
// Adjust for the right side clipping.
|
|
|
|
lOutCol += ulClipMargin;
|
|
}
|
|
else
|
|
{
|
|
/* Not on a visible scanline. Adjust our x output position */
|
|
|
|
lOutCol += ulCount;
|
|
|
|
} /* if */
|
|
|
|
} /* if */
|
|
} /* LOOP_FOREVER */
|
|
} /* bSrcCopySRLE4D8 */
|
|
|
|
/********************************Public*Routine****************************\
|
|
* bSrcCopySRLE4D1
|
|
*
|
|
* Secure RLE blting to a 1 BPP DIB that does clipping and won't die or
|
|
* write somewhere it shouldn't if given bad data.
|
|
*
|
|
* History:
|
|
* 5 Feb 1992 - Andrew Milton (w-andym):
|
|
* Added clip support.
|
|
* 22 Jan 1992 - Andrew Milton (w-andym): Creation.
|
|
*
|
|
\**************************************************************************/
|
|
|
|
/* Local Macros ***********************************************************/
|
|
|
|
/* NOTE: In the Escape Modes, the current working byte must be
|
|
* written to destination before the escape is executed.
|
|
* These writes look unpleasant because we have to mask
|
|
* current destination contents onto the working byte when
|
|
* it is written. To such an end, the below macro...
|
|
*/
|
|
|
|
#define RLE4to1_WritePartial(DstPtr, OutByte, OutColumn, WritePos) \
|
|
if (RLE_RowVisible && (jBitPos = (BYTE) (OutColumn) & 7)) \
|
|
{ \
|
|
if (RLE_ColVisible(OutColumn)) \
|
|
DstPtr[WritePos] = OutByte | \
|
|
((~ajBits[jBitPos]) & DstPtr[WritePos]); \
|
|
else \
|
|
if (RLE_PastRightEdge(OutColumn)) \
|
|
DstPtr[ulRightWritePos] = OutByte | \
|
|
(DstPtr[ulRightWritePos] & jRightMask); \
|
|
} \
|
|
|
|
/* Converts an output column to a bitnumber in the working byte */
|
|
#define ColToBitPos(col) (7 - (BYTE)((col) & 7))
|
|
|
|
/* Lookup tables for bit patterns *****************************************/
|
|
|
|
static BYTE
|
|
ajPosMask[] = // The i'th entry contains a byte with the i'th bit set
|
|
{
|
|
0x01, 0x02, 0x04, 0x08,
|
|
0x10, 0x20, 0x40, 0x80, 0x00
|
|
};
|
|
|
|
static BYTE
|
|
ajBits[] = // The i'th entry contains a byte with the high i bits set
|
|
{
|
|
0x00, 0x80, 0xC0, 0xE0, 0xF0,
|
|
0xF8, 0xFC, 0xFE, 0xFF
|
|
};
|
|
|
|
static BYTE
|
|
ajBitPatterns[] = // The four possible full byte bit patterns of a packed colour
|
|
{
|
|
0x00, 0x55, 0xAA, 0xFF
|
|
};
|
|
|
|
/* And now the function ***************************************************/
|
|
|
|
BOOL
|
|
bSrcCopySRLE4D1(
|
|
PBLTINFO psb)
|
|
{
|
|
|
|
// Common RLE Initialization
|
|
|
|
RLE_InitVars(psb, pjSrc, pjDst, PBYTE, ulCount, ulNext, lOutCol,
|
|
pulXlate);
|
|
RLE_AssertValid(psb);
|
|
RLE_FetchVisibleRect(psb);
|
|
RLE_SetStartPos(psb, lOutCol);
|
|
|
|
// Outta here if we start past the top edge. Don't need to save our position.
|
|
|
|
if (RLE_PastTopEdge)
|
|
return(TRUE); // Must have bits left in the bitmap since we haven't
|
|
// consumed any.
|
|
// Extra Variables
|
|
|
|
BYTE jWorking; // Hold area to build a byte for output
|
|
ULONG ulWritePos; // Write position off <pjDst> into the destination
|
|
|
|
ULONG ulLeftWritePos; // Leftmost write position
|
|
BYTE jLeftMask; // Bitmask for taking bytes off the left edge
|
|
|
|
ULONG ulRightWritePos; // Rightmost write position
|
|
BYTE jRightMask; // Bitmask for taking bytes off the right edge
|
|
|
|
BYTE jBitPos; // Bit number of the next write into <jWorking>
|
|
BYTE jBitPosMask; // Bitmask with the <jBitPos>th bit set.
|
|
|
|
ULONG ulCompBytes; // Number of full bytes in an Encoded run.
|
|
ULONG ulClipMargin; // Number of bytes clipped off the right side of a run
|
|
|
|
BYTE jSource; // Packed RLE 4 colour code
|
|
BYTE ajColours[2]; // Destination for unpacking an RLE 4 code
|
|
BOOL bExtraByte; // TRUE when an absolute run ends with a partial byte
|
|
|
|
UINT i=0, j=0;
|
|
|
|
// Our Initialization
|
|
|
|
ulLeftWritePos = (ULONG)(ulDstLeft >> 3);
|
|
jLeftMask = ajBits[ulDstLeft % 8];
|
|
ulRightWritePos = (ULONG) (ulDstRight >> 3);
|
|
jRightMask = ~ajBits[(ulDstRight % 8)];
|
|
|
|
/* Fetch first working byte from the source. Yes, this is ugly.
|
|
* We cannot assume we are at a left edge because the complex clipping
|
|
* case could resume an RLE in the middle of its bitmap. We cannot do
|
|
* a simple bounds check like RLE 8 to 4 because of bitmasking. Argh.
|
|
*/
|
|
|
|
ulWritePos = lOutCol >> 3;
|
|
|
|
if (RLE_RowVisible)
|
|
{
|
|
if (RLE_ColVisible(lOutCol))
|
|
jWorking = pjDst[ulWritePos] & ajBits[lOutCol & 7];
|
|
else
|
|
{
|
|
if (RLE_PastRightEdge(lOutCol))
|
|
jWorking = pjDst[ulRightWritePos];
|
|
else
|
|
jWorking = pjDst[ulLeftWritePos] & jLeftMask;
|
|
}
|
|
}
|
|
|
|
// Diddle the translation table
|
|
|
|
for (i = 1, j = 1; i < 16; i+=1, j ^= 1) pulXlate[i] = j;
|
|
|
|
// Main Process loop
|
|
|
|
LOOP_FOREVER
|
|
{
|
|
// Outta here if we can't get two more bytes
|
|
|
|
if (RLE_SourceExhausted(2))
|
|
return(FALSE);
|
|
|
|
RLE_GetNextCode(pjSrc, ulCount, ulNext);
|
|
|
|
ulWritePos = lOutCol >> 3;
|
|
|
|
if (ulCount == 0)
|
|
{
|
|
// Absolute or Escape Mode
|
|
|
|
switch (ulNext)
|
|
{
|
|
|
|
case 0:
|
|
|
|
// New Line.
|
|
|
|
RLE4to1_WritePartial(pjDst, jWorking, lOutCol, ulWritePos);
|
|
RLE_NextLine(PBYTE, pjDst, lOutCol);
|
|
|
|
if (RLE_PastTopEdge)
|
|
{
|
|
RLE_SavePosition(psb, pjSrc, pjDst, lOutCol);
|
|
return(TRUE);
|
|
}
|
|
|
|
if (RLE_RowVisible)
|
|
jWorking = pjDst[ulLeftWritePos] & jLeftMask;
|
|
break;
|
|
|
|
case 1:
|
|
|
|
// End of the bitmap.
|
|
|
|
RLE4to1_WritePartial(pjDst, jWorking, lOutCol, ulWritePos);
|
|
return(FALSE);
|
|
|
|
case 2:
|
|
|
|
// Positional Delta
|
|
|
|
RLE4to1_WritePartial(pjDst, jWorking, lOutCol, ulWritePos);
|
|
|
|
// Outta here if we can't get the delta values
|
|
|
|
if (RLE_SourceExhausted(2))
|
|
return(FALSE);
|
|
|
|
RLE_GetNextCode(pjSrc, ulCount, ulNext);
|
|
RLE_PosDelta(pjDst, lOutCol, ulCount, ulNext);
|
|
|
|
if (RLE_PastTopEdge)
|
|
{
|
|
RLE_SavePosition(psb, pjSrc, pjDst, lOutCol);
|
|
return(TRUE);
|
|
}
|
|
|
|
// Fetch a new working byte off the destination
|
|
|
|
ulWritePos = lOutCol >> 3;
|
|
if (RLE_ColVisible(lOutCol))
|
|
jWorking = pjDst[ulWritePos] & ajBits[lOutCol & 7];
|
|
else
|
|
if (RLE_PastRightEdge(lOutCol))
|
|
jWorking = pjDst[ulRightWritePos];
|
|
else
|
|
jWorking = pjDst[ulLeftWritePos] & jLeftMask;
|
|
break;
|
|
|
|
default:
|
|
|
|
/* Absolute Mode.
|
|
* The run length is stored in <ulNext>, <ulCount> is used to
|
|
* hold left and right clip amounts.
|
|
*/
|
|
|
|
// Outta here if the bytes aren't in the source
|
|
|
|
if (RLE_SourceExhausted(RLE4_ByteLength(ulNext)))
|
|
return(FALSE);
|
|
|
|
RLE4_AlignToWord(pjSrc, ulNext);
|
|
|
|
if (RLE_InVisibleRect(ulNext, lOutCol))
|
|
{
|
|
// Left side clipping
|
|
|
|
if (lOutCol < (LONG)ulDstLeft)
|
|
{
|
|
ulCount = ulDstLeft - lOutCol;
|
|
ulNext -= ulCount;
|
|
lOutCol += ulCount;
|
|
ulWritePos = lOutCol >> 3;
|
|
|
|
pjSrc += (ulCount >> 1);
|
|
|
|
jBitPos = (BYTE) ColToBitPos(lOutCol);
|
|
jBitPosMask = ajPosMask[jBitPos]; // Always non-zero.
|
|
|
|
// Force the source to a byte boundary
|
|
|
|
if (bIsOdd(ulCount))
|
|
{
|
|
jSource = (BYTE)
|
|
pulXlate[GetLowNybble(*pjSrc++)];
|
|
if (jSource)
|
|
jWorking |= jBitPosMask;
|
|
jBitPosMask >>= 1;
|
|
lOutCol++;
|
|
ulNext--;
|
|
}
|
|
|
|
}
|
|
else
|
|
{
|
|
jBitPos = (BYTE) ColToBitPos(lOutCol);
|
|
jBitPosMask = ajPosMask[jBitPos]; // Always non-zero.
|
|
}
|
|
|
|
// Right side clipping
|
|
|
|
if ((lOutCol + (LONG) ulNext) > (LONG)ulDstRight)
|
|
{
|
|
ulCount = (lOutCol + ulNext) - ulDstRight;
|
|
ulNext -= ulCount;
|
|
}
|
|
else
|
|
ulCount = 0;
|
|
|
|
// Run Initialization
|
|
|
|
bExtraByte = (BOOL) bIsOdd(ulNext);
|
|
lOutCol += ulNext;
|
|
|
|
// Slap the bits on. -- this is the funky-doodle stuff.
|
|
|
|
i = 0; // Source read toggle.
|
|
do {
|
|
|
|
// Fill the working byte
|
|
|
|
while(jBitPosMask && ulNext)
|
|
{
|
|
if (!i)
|
|
{
|
|
jSource = *pjSrc++;
|
|
RLE4_MakeColourBlock(jSource, ajColours,
|
|
BYTE, pulXlate);
|
|
}
|
|
if (ajColours[i])
|
|
jWorking |= jBitPosMask;
|
|
jBitPosMask >>= 1;
|
|
ulNext--;
|
|
i ^= 1;
|
|
}
|
|
|
|
// Write it
|
|
|
|
if (!(jBitPosMask))
|
|
{
|
|
pjDst[ulWritePos] = jWorking;
|
|
ulWritePos++;
|
|
jBitPosMask = 0x80;
|
|
jWorking = 0;
|
|
}
|
|
|
|
} while (ulNext);
|
|
|
|
// Adjust for the right side clipping.
|
|
|
|
pjSrc += bExtraByte ? (ulCount >> 1) :
|
|
((ulCount + 1) >> 1);
|
|
lOutCol += ulCount;
|
|
}
|
|
else
|
|
{
|
|
/* Not on a visible scanline.
|
|
* Adjust our x output position and source pointer.
|
|
*/
|
|
lOutCol += ulNext;
|
|
pjSrc += ((ulNext + 1) >> 1);
|
|
|
|
} /* if */
|
|
|
|
// Fix up if this run was not WORD aligned.
|
|
RLE4_FixAlignment(pjSrc);
|
|
|
|
} /* switch */
|
|
|
|
}
|
|
else
|
|
{
|
|
/* Encoded Mode
|
|
* The run length is stored in <ulCount>, <ulClipMargin> is used
|
|
* to hold left and right clip amounts.
|
|
*/
|
|
if (RLE_InVisibleRect(ulCount, lOutCol))
|
|
{
|
|
// Left side clipping
|
|
|
|
if (lOutCol < (LONG)ulDstLeft)
|
|
{
|
|
ulClipMargin = ulDstLeft - lOutCol;
|
|
ulCount -= ulClipMargin;
|
|
lOutCol += ulClipMargin;
|
|
ulWritePos = lOutCol >> 3;
|
|
}
|
|
|
|
// Right side clipping
|
|
|
|
if ((lOutCol + (LONG) ulCount) > (LONG)ulDstRight)
|
|
{
|
|
ulClipMargin = (lOutCol + ulCount) - ulDstRight;
|
|
ulCount -= ulClipMargin;
|
|
}
|
|
else
|
|
ulClipMargin = 0;
|
|
|
|
// Initialize for the run
|
|
|
|
RLE4_MakeColourBlock(ulNext, ajColours, BYTE, pulXlate);
|
|
jSource = ajBitPatterns[2*ajColours[0] + ajColours[1]];
|
|
|
|
// jSource |= ((jSource << 2) |
|
|
// (jSource << 4) |
|
|
// (jSource << 6));
|
|
|
|
jBitPos = (BYTE) ColToBitPos(lOutCol);
|
|
jBitPosMask = ajPosMask[jBitPos];
|
|
ulCompBytes = (ulCount < (ULONG)jBitPos + 1) ? 0 :
|
|
((BYTE)ulCount - jBitPos - 1) >> 3;
|
|
|
|
lOutCol += ulCount;
|
|
|
|
ulCount -= (ulCompBytes << 3);
|
|
|
|
// Deal with a partial byte on the left
|
|
|
|
if (jBitPos >= (LONG) ulCount)
|
|
{
|
|
// Will not fill the working byte
|
|
|
|
jSource &= ajBits[ulCount];
|
|
jWorking |= (BYTE)(jSource >> (7-jBitPos));
|
|
jBitPos -= (BYTE)ulCount;
|
|
ulCount = 0;
|
|
}
|
|
else
|
|
{
|
|
// Will fill the working byte
|
|
|
|
jWorking |= (jSource & ajBits[jBitPos + 1])
|
|
>> (7-jBitPos);
|
|
pjDst[ulWritePos] = jWorking;
|
|
if (!bIsOdd(jBitPos))
|
|
jSource = RollLeft(jSource);
|
|
ulWritePos++;
|
|
jWorking = 0;
|
|
ulCount -= (jBitPos + 1);
|
|
jBitPos = 7;
|
|
}
|
|
|
|
// Deal with complete byte output
|
|
|
|
if (ulCompBytes)
|
|
{
|
|
for (i = 0; i < ulCompBytes; i++)
|
|
pjDst[ulWritePos + i] = jSource;
|
|
ulWritePos += ulCompBytes;
|
|
jBitPos = 7;
|
|
jWorking = 0;
|
|
|
|
}
|
|
|
|
// Deal with the right side partial byte
|
|
|
|
if (ulCount)
|
|
jWorking |= (ajBits[ulCount] & jSource);
|
|
|
|
|
|
// Adjust for the right side clipping.
|
|
|
|
lOutCol += ulClipMargin;
|
|
}
|
|
else
|
|
{
|
|
/* Not on a visible scanline.
|
|
* Adjust our x output position and source pointer.
|
|
*/
|
|
|
|
lOutCol += ulCount;
|
|
|
|
} /* if */
|
|
|
|
} /* if */
|
|
|
|
} /* LOOP_FOREVER */
|
|
|
|
} /* bSrcCopySRLE4D1 */
|
|
|
|
/******************************Public*Routine*****************************
|
|
** bSrcCopySRLE4D4
|
|
*
|
|
* Secure RLE blting to a 4 BPP DIB that does clipping and won't die or
|
|
* write somewhere it shouldn't if given bad data.
|
|
*
|
|
* History:
|
|
* 5 Feb 1992 - Andrew Milton (w-andym):
|
|
* Added clip support.
|
|
*
|
|
* 24 Jan 1992 - Andrew Milton (w-andym): Creation.
|
|
*
|
|
\**************************************************************************/
|
|
|
|
/* NOTE: In the Escape Modes, the current working byte must be
|
|
* written to destination before the escape is executed.
|
|
* To this end, the below macro...
|
|
*/
|
|
|
|
#define RLE4to4_WritePartial(DstPtr, OutByte, OutColumn, WritePos) \
|
|
if (RLE_RowVisible) \
|
|
{ \
|
|
if (RLE_ColVisible(OutColumn) && bIsOdd(OutColumn)) \
|
|
{ \
|
|
SetLowNybble(OutByte, DstPtr[WritePos]); \
|
|
DstPtr[WritePos] = OutByte; \
|
|
} \
|
|
else \
|
|
{ \
|
|
if (bRightPartial && RLE_PastRightEdge(OutColumn)) \
|
|
{ \
|
|
SetLowNybble(OutByte, DstPtr[ulRightWritePos]); \
|
|
DstPtr[ulRightWritePos] = OutByte; \
|
|
} \
|
|
} \
|
|
} \
|
|
|
|
BOOL
|
|
bSrcCopySRLE4D4(
|
|
PBLTINFO psb)
|
|
{
|
|
|
|
// Common RLE Initialization
|
|
|
|
RLE_InitVars(psb, pjSrc, pjDst, PBYTE, ulCount, ulNext,
|
|
lOutCol, pulXlate);
|
|
RLE_AssertValid(psb);
|
|
RLE_FetchVisibleRect(psb);
|
|
RLE_SetStartPos(psb, lOutCol);
|
|
|
|
// Outta here if we start past the top edge. Don't need to save our position.
|
|
|
|
if (RLE_PastTopEdge)
|
|
return(TRUE); // Must have bits left in the bitmap since we haven't
|
|
// consumed any.
|
|
|
|
// Extra Variables
|
|
|
|
BOOL bRightPartial; // TRUE when a visible row ends in a partial byte
|
|
BYTE jWorking; // Hold area to build a byte for output
|
|
ULONG ulWritePos; // Write position off <pjDst> into the destination
|
|
ULONG ulLeftWritePos; // Leftmost write position
|
|
ULONG ulRightWritePos; // Rightmost write position
|
|
|
|
BYTE jSource; // Packed RLE 4 colour code
|
|
BYTE ajColours[2]; // Destination for unpacking an RLE 4 code
|
|
|
|
// Our Initialization
|
|
|
|
ulLeftWritePos = ulDstLeft >> 1;
|
|
ulRightWritePos = ulDstRight >> 1;
|
|
bRightPartial = (BOOL) bIsOdd(ulDstRight);
|
|
|
|
// Fetch our inital working byte
|
|
|
|
ulWritePos = lOutCol >> 1;
|
|
if (RLE_RowVisible)
|
|
jWorking = pjDst[BoundsCheck(ulLeftWritePos, ulRightWritePos,
|
|
ulWritePos)];
|
|
|
|
// Main processing loop
|
|
|
|
LOOP_FOREVER
|
|
{
|
|
ulWritePos = lOutCol >> 1;
|
|
|
|
// Outta here if we can't get two more bytes
|
|
|
|
if (RLE_SourceExhausted(2))
|
|
return(FALSE);
|
|
|
|
RLE_GetNextCode(pjSrc, ulCount, ulNext);
|
|
|
|
if (ulCount == 0)
|
|
{
|
|
// Absolute or Escape Mode.
|
|
|
|
switch (ulNext)
|
|
{
|
|
case 0:
|
|
|
|
// New Line
|
|
|
|
RLE4to4_WritePartial(pjDst, jWorking, lOutCol, ulWritePos);
|
|
|
|
RLE_NextLine(PBYTE, pjDst, lOutCol);
|
|
|
|
if (RLE_PastTopEdge)
|
|
{
|
|
RLE_SavePosition(psb, pjSrc, pjDst, lOutCol);
|
|
return(TRUE);
|
|
}
|
|
|
|
if (RLE_RowVisible)
|
|
jWorking = pjDst[ulLeftWritePos];
|
|
|
|
break;
|
|
|
|
case 1:
|
|
|
|
// End of bitmap
|
|
|
|
RLE4to4_WritePartial(pjDst, jWorking, lOutCol, ulWritePos);
|
|
|
|
return(FALSE);
|
|
|
|
case 2:
|
|
|
|
// Positional Delta
|
|
|
|
RLE4to4_WritePartial(pjDst, jWorking, lOutCol, ulWritePos);
|
|
|
|
// Outta here if we can't get the delta values
|
|
|
|
if (RLE_SourceExhausted(2))
|
|
return(FALSE);
|
|
|
|
RLE_GetNextCode(pjSrc, ulCount, ulNext);
|
|
RLE_PosDelta(pjDst, lOutCol, ulCount, ulNext);
|
|
|
|
if (RLE_PastTopEdge)
|
|
{
|
|
RLE_SavePosition(psb, pjSrc, pjDst, lOutCol);
|
|
return(TRUE);
|
|
}
|
|
|
|
// Read initial working byte
|
|
|
|
ulWritePos = lOutCol >> 1;
|
|
jWorking =
|
|
pjDst[BoundsCheck(ulLeftWritePos, ulRightWritePos,
|
|
ulWritePos)];
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
// Absolute Mode
|
|
|
|
// Outta here if the bytes aren't in the source
|
|
|
|
if (RLE_SourceExhausted(RLE4_ByteLength(ulNext)))
|
|
return(FALSE);
|
|
|
|
RLE4_AlignToWord(pjSrc, ulNext);
|
|
|
|
if (RLE_InVisibleRect(ulNext, lOutCol))
|
|
{
|
|
|
|
// Left Side Clipping. Lots 'o stuff happenin'
|
|
|
|
if (lOutCol < (LONG)ulDstLeft)
|
|
{
|
|
ulCount = ulDstLeft - lOutCol;
|
|
|
|
lOutCol = ulDstLeft;
|
|
ulWritePos = ulDstLeft >> 1;
|
|
|
|
ulNext -= ulCount;
|
|
pjSrc += (ulCount >> 1);
|
|
|
|
// Align the source run to a byte boundary
|
|
|
|
if (bIsOdd(ulCount))
|
|
{
|
|
jSource = (BYTE) pulXlate[GetLowNybble(*pjSrc++)];
|
|
|
|
if (bIsOdd(lOutCol))
|
|
{
|
|
SetLowNybble(jWorking, jSource);
|
|
pjDst[ulWritePos] = jWorking;
|
|
ulWritePos++;
|
|
}
|
|
else
|
|
SetHighNybble(jWorking, jSource);
|
|
lOutCol++;
|
|
ulNext--;
|
|
|
|
// Deal with the special case only one byte is visible
|
|
|
|
if (!ulNext)
|
|
{
|
|
RLE4_FixAlignment(pjSrc);
|
|
continue;
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
// Right Side Clipping
|
|
|
|
if ((lOutCol + (LONG) ulNext) > (LONG)ulDstRight)
|
|
{
|
|
ulCount = (lOutCol + ulNext) - ulDstRight;
|
|
ulNext = ulDstRight - lOutCol;
|
|
}
|
|
else
|
|
ulCount = 0;
|
|
|
|
// Write the Run
|
|
|
|
ASSERTGDI(lOutCol < (LONG) ulDstRight,
|
|
"No longer visible\n");
|
|
|
|
if (ulNext != 0)
|
|
{
|
|
if (bIsOdd(lOutCol))
|
|
{
|
|
// Case 1: Source & Dest misaligned w.r.t. bytes
|
|
|
|
lOutCol += ulNext;
|
|
jSource = *pjSrc++;
|
|
RLE4_MakeColourBlock(jSource, ajColours,
|
|
BYTE, pulXlate);
|
|
SetLowNybble(jWorking, ajColours[0]);
|
|
pjDst[ulWritePos] = jWorking;
|
|
ulWritePos++;
|
|
ulNext--;
|
|
ulNext >>= 1;
|
|
|
|
while (ulNext)
|
|
{
|
|
SetHighNybble(jWorking, ajColours[1]);
|
|
jSource = *pjSrc++;
|
|
RLE4_MakeColourBlock(jSource, ajColours,
|
|
BYTE, pulXlate);
|
|
SetLowNybble(jWorking, ajColours[0]);
|
|
pjDst[ulWritePos] = jWorking;
|
|
ulWritePos++;
|
|
ulNext--;
|
|
|
|
} /* while */
|
|
|
|
/* Account for the right side partial byte
|
|
* and do the right clip adjustment on the source
|
|
*/
|
|
|
|
if (bIsOdd(lOutCol))
|
|
{
|
|
SetHighNybble(jWorking, ajColours[1]);
|
|
pjSrc += ((ulCount + 1) >> 1);
|
|
|
|
}
|
|
else
|
|
{
|
|
pjSrc += (ulCount >> 1);
|
|
}
|
|
|
|
}
|
|
else
|
|
{
|
|
// Case 2: Source & Dest aligned on byte boundaries
|
|
|
|
lOutCol += ulNext;
|
|
ulNext >>= 1;
|
|
|
|
while (ulNext)
|
|
{
|
|
jSource = *pjSrc++;
|
|
RLE4_MakeColourBlock(jSource, ajColours,
|
|
BYTE, pulXlate);
|
|
jWorking = BuildByte(ajColours[0], ajColours[1]);
|
|
pjDst[ulWritePos] = jWorking;
|
|
ulWritePos++;
|
|
ulNext--;
|
|
} /* while */
|
|
|
|
/* Account for the right side partial byte
|
|
* and do the right clip adjustment on the source
|
|
*/
|
|
|
|
if (bIsOdd(lOutCol))
|
|
{
|
|
jSource = GetHighNybble(*pjSrc++);
|
|
SetHighNybble(jWorking,
|
|
(BYTE)pulXlate[(ULONG)jSource]);
|
|
pjSrc += (ulCount >> 1);
|
|
}
|
|
else
|
|
{
|
|
pjSrc += ((ulCount + 1) >> 1);
|
|
}
|
|
|
|
}
|
|
}
|
|
else
|
|
{
|
|
/* Do the right clip adjustment on the source
|
|
*/
|
|
|
|
pjSrc += ((ulCount + 1) >> 1);
|
|
}
|
|
|
|
lOutCol += ulCount;
|
|
}
|
|
else
|
|
{
|
|
/* Not on a visible scanline.
|
|
* Adjust our x output position and source pointer.
|
|
*/
|
|
|
|
lOutCol += ulNext;
|
|
pjSrc += ((ulNext + 1) >> 1);
|
|
|
|
} /* if */
|
|
|
|
// Fix up if this run was not WORD aligned.
|
|
|
|
RLE4_FixAlignment(pjSrc);
|
|
|
|
} /* switch */
|
|
}
|
|
else
|
|
{
|
|
// Encoded Mode
|
|
|
|
if (RLE_InVisibleRect(ulCount, lOutCol))
|
|
{
|
|
ULONG ulClipMargin = 0;
|
|
|
|
// Left side clipping
|
|
|
|
if (lOutCol < (LONG)ulDstLeft)
|
|
{
|
|
ulClipMargin = ulDstLeft - lOutCol;
|
|
lOutCol = ulDstLeft;
|
|
ulWritePos = ulDstLeft >> 1;
|
|
ulCount -= ulClipMargin;
|
|
}
|
|
|
|
// Right side clipping
|
|
|
|
if ((lOutCol + (LONG) ulCount) > (LONG)ulDstRight)
|
|
{
|
|
ulClipMargin = (lOutCol + ulCount) - ulDstRight;
|
|
ulCount = ulDstRight - lOutCol;
|
|
}
|
|
else
|
|
ulClipMargin = 0;
|
|
|
|
|
|
RLE4_MakeColourBlock(ulNext, ajColours, BYTE, pulXlate);
|
|
|
|
// Align the destination to a byte boundary
|
|
|
|
if (bIsOdd(lOutCol))
|
|
{
|
|
SetLowNybble(jWorking, ajColours[0]);
|
|
pjDst[ulWritePos] = jWorking;
|
|
ulWritePos++;
|
|
lOutCol++;
|
|
ulCount--;
|
|
SwapValues(ajColours[0], ajColours[1]);
|
|
}
|
|
|
|
lOutCol += ulCount;
|
|
|
|
// Run initialization
|
|
|
|
ulCount >>= 1;
|
|
|
|
jWorking = BuildByte(ajColours[0], ajColours[1]);
|
|
|
|
// Write complete bytes
|
|
|
|
while(ulCount)
|
|
{
|
|
pjDst[ulWritePos] = jWorking;
|
|
ulWritePos++;
|
|
ulCount--;
|
|
}
|
|
|
|
// Account for writing a partial byte on the right side
|
|
|
|
if (bIsOdd(lOutCol))
|
|
SetHighNybble(jWorking, ajColours[0]);
|
|
|
|
// Adjust for the right side clipping.
|
|
|
|
lOutCol += ulClipMargin;
|
|
|
|
}
|
|
else
|
|
{
|
|
// Not on a visible scanline. Adjust our x output position
|
|
|
|
lOutCol += ulCount;
|
|
|
|
} /* if */
|
|
|
|
} /* if */
|
|
|
|
} /* LOOP_FOREVER */
|
|
|
|
} /* bSrcCopySRLE4D4 */
|
|
|
|
/******************************Public*Routine******************************\
|
|
* bSrcCopySRLE4D16
|
|
*
|
|
* Secure RLE blting to a 16 BPP DIB that does clipping and won't die or
|
|
* write somewhere it shouldn't if given bad data.
|
|
*
|
|
* History:
|
|
* 28 Feb 1992 - Andrew Milton (w-andym): Creation.
|
|
*
|
|
\**************************************************************************/
|
|
BOOL
|
|
bSrcCopySRLE4D16(
|
|
PBLTINFO psb)
|
|
{
|
|
|
|
// Common RLE Initialization
|
|
|
|
RLE_InitVars(psb, pjSrc, pwDst, PWORD, ulCount, ulNext, lOutCol,
|
|
pulXlate);
|
|
RLE_AssertValid(psb);
|
|
RLE_FetchVisibleRect(psb);
|
|
RLE_SetStartPos(psb, lOutCol);
|
|
|
|
// Outta here if we start past the top edge. Don't need to save our position.
|
|
|
|
if (RLE_PastTopEdge)
|
|
return(TRUE); // Must have bits left in the bitmap since we haven't
|
|
// consumed any.
|
|
|
|
// Extra Variables
|
|
|
|
BYTE jSource; // Packed RLE 4 colour code
|
|
WORD awColours[2]; // Destination for unpacking an RLE 4 code
|
|
BOOL bExtraByte; // TRUE when an absolute run ends with a partial byte
|
|
|
|
// Main process loop
|
|
|
|
LOOP_FOREVER
|
|
{
|
|
// Outta here if we can't get two more bytes
|
|
|
|
if (RLE_SourceExhausted(2))
|
|
return(FALSE);
|
|
|
|
RLE_GetNextCode(pjSrc, ulCount, ulNext);
|
|
if (ulCount == 0)
|
|
{
|
|
// Absolute or Escape Mode
|
|
|
|
switch (ulNext)
|
|
{
|
|
case 0:
|
|
|
|
// New Line
|
|
|
|
RLE_NextLine(PWORD, pwDst, lOutCol);
|
|
|
|
if (RLE_PastTopEdge)
|
|
{
|
|
RLE_SavePosition(psb, pjSrc, pwDst, lOutCol);
|
|
return(TRUE);
|
|
}
|
|
break;
|
|
|
|
case 1:
|
|
|
|
// End of the Bitmap.
|
|
|
|
return(FALSE);
|
|
|
|
case 2:
|
|
|
|
/* Positional Delta.
|
|
* The delta values live in the next two source bytes
|
|
*/
|
|
|
|
// Outta here if we can't get the delta values
|
|
|
|
if (RLE_SourceExhausted(2))
|
|
return(FALSE);
|
|
|
|
RLE_GetNextCode(pjSrc, ulCount, ulNext);
|
|
RLE_PosDelta(pwDst, lOutCol, ulCount, ulNext);
|
|
|
|
if (RLE_PastTopEdge)
|
|
{
|
|
RLE_SavePosition(psb, pjSrc, pwDst, lOutCol);
|
|
return(TRUE);
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
/* Absolute Mode.
|
|
* The run length is stored in <ulNext>, <ulCount> is used to
|
|
* hold left and right clip amounts.
|
|
*/
|
|
|
|
// Outta here if the bytes aren't in the source
|
|
|
|
if (RLE_SourceExhausted(RLE4_ByteLength(ulNext)))
|
|
return(FALSE);
|
|
|
|
RLE4_AlignToWord(pjSrc, ulNext);
|
|
|
|
if (RLE_InVisibleRect(ulNext, lOutCol))
|
|
{
|
|
// Left side clipping
|
|
|
|
if (lOutCol < (LONG)ulDstLeft)
|
|
{
|
|
ulCount = ulDstLeft - lOutCol;
|
|
lOutCol = ulDstLeft;
|
|
ulNext -= ulCount;
|
|
|
|
pjSrc += (ulCount >> 1);
|
|
|
|
// Align the source run to a byte boundary
|
|
|
|
if (bIsOdd(ulCount))
|
|
{
|
|
jSource = (BYTE) *pjSrc++;
|
|
pwDst[lOutCol] =
|
|
(WORD) pulXlate[GetLowNybble(jSource)];
|
|
lOutCol++;
|
|
ulNext--;
|
|
}
|
|
|
|
}
|
|
|
|
// Right side clipping
|
|
|
|
if ((lOutCol + (LONG) ulNext) > (LONG)ulDstRight)
|
|
{
|
|
ulCount = (lOutCol + ulNext) - ulDstRight;
|
|
ulNext -= ulCount;
|
|
}
|
|
else
|
|
ulCount = 0;
|
|
|
|
// Slap the bits on. -- this is the funky-doodle stuff.
|
|
|
|
bExtraByte = (BOOL) bIsOdd(ulNext);
|
|
ulNext >>= 1;
|
|
|
|
// Deal with complete source bytes
|
|
|
|
while (ulNext)
|
|
{
|
|
jSource = *pjSrc++;
|
|
RLE4_MakeColourBlock(jSource, awColours, WORD,
|
|
pulXlate);
|
|
pwDst[lOutCol] = awColours[0];
|
|
pwDst[lOutCol+1] = awColours[1];
|
|
|
|
lOutCol += 2;
|
|
ulNext--;
|
|
}
|
|
|
|
// Account for right partial byte in the source */
|
|
|
|
if (bExtraByte)
|
|
{
|
|
jSource = *pjSrc++;
|
|
RLE4_MakeColourBlock(jSource, awColours, WORD,
|
|
pulXlate);
|
|
pwDst[lOutCol] = awColours[0];
|
|
lOutCol++;
|
|
pjSrc += (ulCount >> 1); // Clip Adjustment
|
|
}
|
|
else
|
|
pjSrc += ((ulCount + 1) >> 1); // Clip Adjustment
|
|
|
|
// Adjust the column for the right side clipping.
|
|
|
|
lOutCol += ulCount;
|
|
|
|
}
|
|
else
|
|
{
|
|
/* Not on a visible scanline.
|
|
* Adjust our x output position and source pointer.
|
|
*/
|
|
|
|
lOutCol += ulNext;
|
|
pjSrc += (ulNext + 1) >> 1;
|
|
|
|
} /* if */
|
|
|
|
// Fix up if this run was not WORD aligned.
|
|
|
|
RLE4_FixAlignment(pjSrc)
|
|
|
|
} /* switch */
|
|
}
|
|
else
|
|
{
|
|
/* Encoded Mode
|
|
* The run length is stored in <ulCount>, <ulClipMargin> is used
|
|
* to hold left and right clip amounts.
|
|
*/
|
|
|
|
if (RLE_InVisibleRect(ulCount, lOutCol))
|
|
{
|
|
ULONG ulClipMargin = 0;
|
|
|
|
// Left side clipping
|
|
|
|
if (lOutCol < (LONG)ulDstLeft)
|
|
{
|
|
ulClipMargin = ulDstLeft - lOutCol;
|
|
lOutCol = ulDstLeft;
|
|
ulCount -= ulClipMargin;
|
|
}
|
|
|
|
// Right side clipping
|
|
|
|
if ((lOutCol + (LONG) ulCount) > (LONG)ulDstRight)
|
|
{
|
|
ulClipMargin = (lOutCol + ulCount) - ulDstRight;
|
|
ulCount -= ulClipMargin;
|
|
}
|
|
else
|
|
ulClipMargin = 0;
|
|
|
|
// Run initialization
|
|
|
|
bExtraByte = (BOOL) bIsOdd(ulCount);
|
|
ulCount >>= 1;
|
|
RLE4_MakeColourBlock(ulNext, awColours, WORD, pulXlate);
|
|
|
|
// Write the run
|
|
|
|
while (ulCount)
|
|
{
|
|
pwDst[lOutCol] = awColours[0];
|
|
pwDst[lOutCol+1] = awColours[1];
|
|
lOutCol += 2;
|
|
ulCount --;
|
|
}
|
|
|
|
// ... and an extra byte for an odd run length
|
|
|
|
if (bExtraByte)
|
|
{
|
|
pwDst[lOutCol] = awColours[0];
|
|
lOutCol++;
|
|
}
|
|
|
|
// Adjust for the right side clipping.
|
|
|
|
lOutCol += ulClipMargin;
|
|
}
|
|
else
|
|
{
|
|
/* Not on a visible scanline.
|
|
* Adjust our x output position
|
|
*/
|
|
|
|
lOutCol += ulCount;
|
|
|
|
} /* if */
|
|
|
|
} /* if */
|
|
} /* LOOP_FOREVER */
|
|
} /* bSrcCopySRLE4D16 */
|
|
|
|
|
|
/******************************Public*Routine*****************************
|
|
** bSrcCopySRLE4D24
|
|
*
|
|
* Secure RLE blting to a 24 BPP DIB that does clipping and won't die or
|
|
* write somewhere it shouldn't if given bad data.
|
|
*
|
|
* History:
|
|
* 28 Feb 1992 - Andrew Milton (w-andym): Creation.
|
|
*
|
|
\**************************************************************************/
|
|
|
|
#define RLE_24BitWrite(DstPtr, BytePos, Colour) \
|
|
DstPtr[BytePos] = (BYTE)Colour; \
|
|
DstPtr[BytePos+1] = (BYTE)(Colour >> 8); \
|
|
DstPtr[BytePos+2] = (BYTE)(Colour >> 16); \
|
|
BytePos += 3; \
|
|
|
|
BOOL
|
|
bSrcCopySRLE4D24(
|
|
PBLTINFO psb)
|
|
{
|
|
|
|
// Common RLE Initialization
|
|
|
|
RLE_InitVars(psb, pjSrc, pjDst, PBYTE, ulCount, ulNext, lOutCol, pulXlate);
|
|
RLE_AssertValid(psb);
|
|
RLE_FetchVisibleRect(psb);
|
|
RLE_SetStartPos(psb, lOutCol);
|
|
|
|
// Outta here if we start past the top edge. Don't need to save our position.
|
|
|
|
if (RLE_PastTopEdge)
|
|
return(TRUE); // Must have bits left in the bitmap since we haven't
|
|
// consumed any.
|
|
|
|
// Extra Variables
|
|
|
|
ULONG ulWritePos; // Write position off <pjDst> into the destination
|
|
BYTE jSource; // Packed RLE 4 colour code
|
|
DWORD adwColours[2]; // Destination for unpacking an RLE 4 code
|
|
BOOL bExtraByte; // TRUE when an absolute run ends with a partial byte
|
|
ULONG ulClipMargin; // Number of bytes clipped off an Encoded run
|
|
|
|
// Main process loop
|
|
|
|
LOOP_FOREVER
|
|
{
|
|
// Outta here if we can't get two more bytes
|
|
|
|
if (RLE_SourceExhausted(2))
|
|
return(FALSE);
|
|
|
|
RLE_GetNextCode(pjSrc, ulCount, ulNext);
|
|
|
|
if (ulCount == 0)
|
|
{
|
|
// Absolute or Escape Mode
|
|
|
|
switch (ulNext)
|
|
{
|
|
case 0:
|
|
|
|
// New line
|
|
|
|
RLE_NextLine(PBYTE, pjDst, lOutCol);
|
|
|
|
if (RLE_PastTopEdge)
|
|
{
|
|
RLE_SavePosition(psb, pjSrc, pjDst, lOutCol);
|
|
return(TRUE);
|
|
}
|
|
|
|
break;
|
|
|
|
case 1:
|
|
|
|
// End of the Bitmap
|
|
|
|
return(FALSE);
|
|
|
|
case 2:
|
|
|
|
/* Positional Delta.
|
|
* The delta values live in the next two source bytes
|
|
*/
|
|
|
|
// Outta here if we can't get two more bytes
|
|
|
|
if (RLE_SourceExhausted(2))
|
|
return(FALSE);
|
|
|
|
RLE_GetNextCode(pjSrc, ulCount, ulNext);
|
|
RLE_PosDelta(pjDst, lOutCol, ulCount, ulNext);
|
|
|
|
if (RLE_PastTopEdge)
|
|
{
|
|
RLE_SavePosition(psb, pjSrc, pjDst, lOutCol);
|
|
return(TRUE);
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
/* Absolute Mode.
|
|
* The run length is stored in <ulNext>, <ulCount> is used to
|
|
* hold left and right clip amounts.
|
|
*/
|
|
|
|
// Outta here if the bytes aren't in the source
|
|
|
|
if (RLE_SourceExhausted(RLE4_ByteLength(ulNext)))
|
|
return(FALSE);
|
|
|
|
RLE4_AlignToWord(pjSrc, ulNext);
|
|
|
|
if (RLE_InVisibleRect(ulNext, lOutCol))
|
|
{
|
|
// Left side clipping
|
|
|
|
if (lOutCol < (LONG)ulDstLeft)
|
|
{
|
|
ulCount = ulDstLeft - lOutCol;
|
|
lOutCol = ulDstLeft;
|
|
ulNext -= ulCount;
|
|
ulWritePos = 3*lOutCol;
|
|
|
|
pjSrc += (ulCount >> 1);
|
|
|
|
// Align the Source run to a byte boundary
|
|
|
|
if (bIsOdd(ulCount))
|
|
{
|
|
adwColours[0] = pulXlate[GetLowNybble(*pjSrc++)];
|
|
RLE_24BitWrite(pjDst, ulWritePos, adwColours[0]);
|
|
lOutCol++;
|
|
ulNext--;
|
|
}
|
|
|
|
}
|
|
else
|
|
ulWritePos = 3*lOutCol;
|
|
|
|
// Right side clipping
|
|
|
|
if ((lOutCol + (LONG) ulNext) > (LONG)ulDstRight)
|
|
{
|
|
ulCount = (lOutCol + ulNext) - ulDstRight;
|
|
ulNext -= ulCount;
|
|
}
|
|
else
|
|
ulCount = 0;
|
|
|
|
// Run Initialization.
|
|
|
|
bExtraByte = (BOOL) bIsOdd(ulNext);
|
|
lOutCol += ulNext;
|
|
ulNext >>= 1;
|
|
|
|
// Write complete bytes from the source
|
|
|
|
while (ulNext)
|
|
{
|
|
jSource = *pjSrc++;
|
|
RLE4_MakeColourBlock(jSource, adwColours, DWORD,
|
|
pulXlate);
|
|
RLE_24BitWrite(pjDst, ulWritePos, adwColours[0]);
|
|
RLE_24BitWrite(pjDst, ulWritePos, adwColours[1]);
|
|
ulNext--;
|
|
}
|
|
|
|
// Account for a right partial byte in the source
|
|
|
|
if (bExtraByte)
|
|
{
|
|
adwColours[0] = pulXlate[GetHighNybble(*pjSrc++)];
|
|
RLE_24BitWrite(pjDst, ulWritePos, adwColours[0]);
|
|
pjSrc += (ulCount >> 1); // Clip Adjustment
|
|
}
|
|
else
|
|
pjSrc += ((ulCount + 1) >> 1); // Clip Adjustment
|
|
|
|
// Adjust the column for the right side clipping.
|
|
|
|
lOutCol += ulCount;
|
|
|
|
}
|
|
else
|
|
{
|
|
/* Not on a visible scanline.
|
|
* Adjust our x output position and source pointer.
|
|
*/
|
|
|
|
lOutCol += ulNext;
|
|
pjSrc += (ulNext + 1) >> 1;
|
|
|
|
} /* if */
|
|
|
|
// Fix up if this run was not WORD aligned.
|
|
|
|
RLE4_FixAlignment(pjSrc)
|
|
|
|
} /* switch */
|
|
}
|
|
else
|
|
{
|
|
/* Encoded Mode
|
|
* The run length is stored in <ulCount>, <ulClipMargin> is used
|
|
* to hold left and right clip amounts.
|
|
*/
|
|
|
|
if (RLE_InVisibleRect(ulCount, lOutCol))
|
|
{
|
|
|
|
// Left side clipping
|
|
|
|
if (lOutCol < (LONG)ulDstLeft)
|
|
{
|
|
ulClipMargin = ulDstLeft - lOutCol;
|
|
lOutCol = ulDstLeft;
|
|
ulCount -= ulClipMargin;
|
|
}
|
|
|
|
|
|
// Right side clipping
|
|
|
|
if ((lOutCol + (LONG) ulCount) > (LONG)ulDstRight)
|
|
{
|
|
ulClipMargin = (lOutCol + ulCount) - ulDstRight;
|
|
ulCount -= ulClipMargin;
|
|
}
|
|
else
|
|
ulClipMargin = 0;
|
|
|
|
// Run initialization
|
|
|
|
ulWritePos = 3*lOutCol;
|
|
lOutCol += ulCount;
|
|
bExtraByte = (BOOL) bIsOdd(ulCount);
|
|
ulCount >>= 1;
|
|
|
|
RLE4_MakeColourBlock(ulNext, adwColours, DWORD, pulXlate);
|
|
|
|
// Write the run
|
|
|
|
while (ulCount)
|
|
{
|
|
RLE_24BitWrite(pjDst, ulWritePos, adwColours[0]);
|
|
RLE_24BitWrite(pjDst, ulWritePos, adwColours[1]);
|
|
ulCount --;
|
|
}
|
|
|
|
// Write the extra byte from an odd run length
|
|
|
|
if (bExtraByte)
|
|
{
|
|
RLE_24BitWrite(pjDst, ulWritePos, adwColours[0]);
|
|
}
|
|
|
|
// Adjust for the right side clipping.
|
|
|
|
lOutCol += ulClipMargin;
|
|
}
|
|
else
|
|
{
|
|
/* Not on a visible scanline.
|
|
* Adjust our x output position
|
|
*/
|
|
|
|
lOutCol += ulCount;
|
|
|
|
} /* if */
|
|
|
|
} /* if */
|
|
} /* LOOP_FOREVER */
|
|
} /* bSrcCopySRLE4D24 */
|
|
|
|
/******************************Public*Routine*****************************
|
|
** bSrcCopySRLE4D32
|
|
*
|
|
* Secure RLE blting to a 32 BPP DIB that does clipping and won't die or
|
|
* write somewhere it shouldn't if given bad data.
|
|
*
|
|
* History:
|
|
* 28 Feb 1992 - Andrew Milton (w-andym): Creation.
|
|
*
|
|
\**************************************************************************/
|
|
|
|
BOOL
|
|
bSrcCopySRLE4D32(
|
|
PBLTINFO psb)
|
|
{
|
|
// Common RLE Initialization
|
|
|
|
RLE_InitVars(psb, pjSrc, pdwDst, PDWORD, ulCount, ulNext,
|
|
lOutCol, pulXlate);
|
|
RLE_AssertValid(psb);
|
|
RLE_FetchVisibleRect(psb);
|
|
RLE_SetStartPos(psb, lOutCol);
|
|
|
|
// Outta here if we start past the top edge. Don't need to save our position.
|
|
|
|
if (RLE_PastTopEdge)
|
|
return(TRUE); // Must have bits left in the bitmap since we haven't
|
|
// consumed any.
|
|
|
|
// Extra Variables
|
|
|
|
BYTE jSource; // Packed RLE 4 colour code
|
|
DWORD adwColours[2]; // Destination for unpacking an RLE 4 code
|
|
BOOL bExtraByte; // TRUE when an absolute run ends with a partial byte
|
|
ULONG ulClipMargin; // Number of bytes clipped off an Encoded run
|
|
|
|
|
|
// Main processing loop
|
|
|
|
LOOP_FOREVER
|
|
{
|
|
// Outta here if we can't get two more bytes
|
|
|
|
if (RLE_SourceExhausted(2))
|
|
return(FALSE);
|
|
|
|
RLE_GetNextCode(pjSrc, ulCount, ulNext);
|
|
|
|
if (ulCount == 0)
|
|
{
|
|
// Absolute or Escape Mode
|
|
|
|
switch (ulNext)
|
|
{
|
|
case 0:
|
|
|
|
// New line
|
|
|
|
RLE_NextLine(PDWORD, pdwDst, lOutCol);
|
|
|
|
if (RLE_PastTopEdge)
|
|
{
|
|
RLE_SavePosition(psb, pjSrc, pdwDst, lOutCol);
|
|
return(TRUE);
|
|
}
|
|
|
|
break;
|
|
|
|
case 1:
|
|
|
|
// End of the Bitmap
|
|
|
|
return(FALSE);
|
|
|
|
case 2:
|
|
|
|
/* Positional Delta.
|
|
* The delta values live in the next two source bytes
|
|
*/
|
|
// Outta here if we can't get two more bytes
|
|
|
|
if (RLE_SourceExhausted(2))
|
|
return(FALSE);
|
|
|
|
RLE_GetNextCode(pjSrc, ulCount, ulNext);
|
|
RLE_PosDelta(pdwDst, lOutCol, ulCount, ulNext);
|
|
|
|
if (RLE_PastTopEdge)
|
|
{
|
|
RLE_SavePosition(psb, pjSrc, pdwDst, lOutCol);
|
|
return(TRUE);
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
// Absolute Mode
|
|
|
|
// Outta here if the bytes aren't in the source
|
|
|
|
if (RLE_SourceExhausted(RLE4_ByteLength(ulNext)))
|
|
return(FALSE);
|
|
|
|
RLE4_AlignToWord(pjSrc, ulNext);
|
|
|
|
if (RLE_InVisibleRect(ulNext, lOutCol))
|
|
{
|
|
|
|
// Left side clipping
|
|
|
|
if (lOutCol < (LONG)ulDstLeft)
|
|
{
|
|
ulCount = ulDstLeft - lOutCol;
|
|
lOutCol = ulDstLeft;
|
|
ulNext -= ulCount;
|
|
|
|
pjSrc += (ulCount >> 1);
|
|
|
|
// Align the source run to a byte boundary
|
|
|
|
if (bIsOdd(ulCount))
|
|
{
|
|
jSource = (BYTE) *pjSrc++;
|
|
pdwDst[lOutCol] =
|
|
(DWORD) pulXlate[GetLowNybble(jSource)];
|
|
lOutCol++;
|
|
ulNext--;
|
|
}
|
|
|
|
}
|
|
|
|
// Right side clipping
|
|
|
|
if ((lOutCol + (LONG) ulNext) > (LONG)ulDstRight)
|
|
{
|
|
ulCount = (lOutCol + ulNext) - ulDstRight;
|
|
ulNext -= ulCount;
|
|
}
|
|
else
|
|
ulCount = 0;
|
|
|
|
// Slap the bits on. -- this is the funky-doodle stuff.
|
|
|
|
bExtraByte = (BOOL) bIsOdd(ulNext);
|
|
ulNext >>= 1;
|
|
|
|
// Write complete bytes from the source
|
|
|
|
while (ulNext)
|
|
{
|
|
jSource = *pjSrc++;
|
|
RLE4_MakeColourBlock(jSource, adwColours, DWORD,
|
|
pulXlate);
|
|
pdwDst[lOutCol] = adwColours[0];
|
|
pdwDst[lOutCol+1] = adwColours[1];
|
|
|
|
lOutCol += 2;
|
|
ulNext--;
|
|
}
|
|
|
|
// Account for a right partial byte in the source
|
|
|
|
if (bExtraByte)
|
|
{
|
|
jSource = *pjSrc++;
|
|
RLE4_MakeColourBlock(jSource, adwColours, DWORD,
|
|
pulXlate);
|
|
pdwDst[lOutCol] = adwColours[0];
|
|
lOutCol++;
|
|
pjSrc += (ulCount >> 1); // Clip Adjustment
|
|
}
|
|
else
|
|
pjSrc += ((ulCount + 1) >> 1); // Clip Adjustment
|
|
|
|
// Adjust the column for the right side clipping.
|
|
|
|
lOutCol += ulCount;
|
|
|
|
}
|
|
else
|
|
{
|
|
/* Not on a visible scanline.
|
|
* Adjust our x output position and source pointer.
|
|
*/
|
|
|
|
lOutCol += ulNext;
|
|
pjSrc += (ulNext + 1) >> 1;
|
|
|
|
} /* if */
|
|
|
|
// Fix up if this run was not WORD aligned.
|
|
|
|
RLE4_FixAlignment(pjSrc);
|
|
|
|
} /* switch */
|
|
}
|
|
else
|
|
{
|
|
/* Encoded Mode
|
|
* The run length is stored in <ulCount>, <ulClipMargin> is used
|
|
* to hold left and right clip amounts.
|
|
*/
|
|
|
|
if (RLE_InVisibleRect(ulCount, lOutCol))
|
|
{
|
|
// Left side clipping
|
|
|
|
if (lOutCol < (LONG)ulDstLeft)
|
|
{
|
|
ulClipMargin = ulDstLeft - lOutCol;
|
|
lOutCol = ulDstLeft;
|
|
ulCount -= ulClipMargin;
|
|
}
|
|
|
|
// Right side clipping
|
|
|
|
if ((lOutCol + (LONG) ulCount) > (LONG)ulDstRight)
|
|
{
|
|
ulClipMargin = (lOutCol + ulCount) - ulDstRight;
|
|
ulCount -= ulClipMargin;
|
|
}
|
|
else
|
|
ulClipMargin = 0;
|
|
|
|
// Run Initialization.
|
|
|
|
bExtraByte = (BOOL) bIsOdd(ulCount);
|
|
ulCount >>= 1;
|
|
RLE4_MakeColourBlock(ulNext, adwColours, DWORD, pulXlate);
|
|
|
|
// Write the run
|
|
|
|
while (ulCount)
|
|
{
|
|
pdwDst[lOutCol] = adwColours[0];
|
|
pdwDst[lOutCol+1] = adwColours[1];
|
|
lOutCol += 2;
|
|
ulCount --;
|
|
}
|
|
|
|
// Write the extra byte from an odd run length
|
|
|
|
if (bExtraByte)
|
|
{
|
|
pdwDst[lOutCol] = adwColours[0];
|
|
lOutCol++;
|
|
}
|
|
|
|
// Adjust for the right side clipping.
|
|
|
|
lOutCol += ulClipMargin;
|
|
}
|
|
else
|
|
{
|
|
/* Not on a visible scanline.
|
|
* Adjust our x output position
|
|
*/
|
|
|
|
lOutCol += ulCount;
|
|
|
|
} /* if */
|
|
|
|
} /* if */
|
|
} /* LOOP_FOREVER */
|
|
} /* bSrcCopySRLE4D32 */
|
|
|
|
|
|
|
|
|
|
/*******************************Public*Routine*****************************\
|
|
* WriteEncoded4
|
|
*
|
|
* A helper function for EncodeRLE4. Writes a run of bytes in encoded format.
|
|
*
|
|
* Created: 28 Oct 92 @ 14:00
|
|
*
|
|
* Author: Gerrit van Wingerden [gerritv]
|
|
*
|
|
\**************************************************************************/
|
|
|
|
|
|
int WriteEncoded4( BYTE bValue, BYTE *pbTarget, UINT uiLength,
|
|
BYTE *pbEndOfBuffer )
|
|
{
|
|
|
|
if( pbTarget == NULL )
|
|
return(2);
|
|
|
|
if( pbTarget + 2 > pbEndOfBuffer )
|
|
return(0);
|
|
|
|
*pbTarget++ = (BYTE) uiLength;
|
|
*pbTarget++ = bValue;
|
|
return(2);
|
|
}
|
|
|
|
|
|
|
|
/*******************************Public*Routine*****************************\
|
|
* WriteAbsolute4
|
|
*
|
|
* A helper function for EncodeRLE4. Writes a run of bytes in absolute format.
|
|
*
|
|
* Created: 28 Oct 92 @ 14:00
|
|
*
|
|
* Author: Gerrit van Wingerden [gerritv]
|
|
*
|
|
\**************************************************************************/
|
|
|
|
|
|
int WriteAbsolute4( BYTE *pbRunStart, BYTE *pbTarget, int cRunLength,
|
|
BYTE *pbEndOfBuffer )
|
|
{
|
|
int iRet;
|
|
|
|
|
|
if( cRunLength < 3 )
|
|
{
|
|
iRet = 2;
|
|
}
|
|
else
|
|
{
|
|
|
|
if( ( cRunLength + 1 ) & 0x02 )
|
|
{
|
|
iRet = (( cRunLength + 1 ) >> 1) + 3;
|
|
}
|
|
else
|
|
{
|
|
iRet = (( cRunLength + 1 ) >> 1) + 2;
|
|
}
|
|
}
|
|
|
|
if( pbTarget == NULL )
|
|
return(iRet);
|
|
|
|
if( pbTarget + iRet > pbEndOfBuffer )
|
|
return(0);
|
|
|
|
if( cRunLength < 3 )
|
|
{
|
|
*pbTarget++ = (BYTE) cRunLength;
|
|
*pbTarget = *pbRunStart;
|
|
return(2);
|
|
|
|
}
|
|
|
|
*pbTarget++ = 0;
|
|
*pbTarget++ = (BYTE) cRunLength;
|
|
|
|
RtlMoveMemory( pbTarget, pbRunStart, ( cRunLength + 1 ) >> 1 );
|
|
|
|
pbTarget += ( cRunLength + 1 ) >> 1;
|
|
|
|
if( ( cRunLength + 1 ) & 0x02 )
|
|
{
|
|
*pbTarget++ = 0;
|
|
return( iRet );
|
|
}
|
|
else
|
|
return( iRet );
|
|
|
|
}
|
|
|
|
|
|
|
|
/*******************************Public*Routine*****************************\
|
|
* EncodeRLE4
|
|
*
|
|
* Encodes a bitmap into RLE4 format and returns the length of the of the
|
|
* encoded format. If the source is NULL it just returns the length of
|
|
* the format. If the encoded output turns out to be longer than cBufferSize
|
|
* the functions stops encoding.
|
|
*
|
|
* History:
|
|
* 28 Oct 1992 Gerrit van Wingerden [gerritv] : creation
|
|
* 15 Mar 1993 Stephan J. Zachwieja [szach] : return 0 if buffer too small
|
|
*
|
|
\**************************************************************************/
|
|
|
|
|
|
|
|
|
|
int EncodeRLE4( BYTE *pbSource, BYTE *pbTarget, UINT uiWidth, UINT cNumLines,
|
|
UINT cBufferSize )
|
|
{
|
|
|
|
UINT cLineCount, uiLineWidth;
|
|
BYTE bLastByte,bCurChar;
|
|
BYTE *pbRunStart;
|
|
BYTE *pbLineEnd;
|
|
BYTE *pbEndOfBuffer;
|
|
BYTE *pbCurPos;
|
|
INT cCurrentRunLength;
|
|
INT iMode, cTemp;
|
|
UINT cTotal = 0;
|
|
|
|
pbEndOfBuffer = pbTarget + cBufferSize;
|
|
|
|
// Compute width of line in bytes rounded to a DWORD boundary
|
|
|
|
uiLineWidth = ( ( uiWidth + 7 ) >> 3 ) << 2 ;
|
|
|
|
for( cLineCount = 0; cLineCount < cNumLines; cLineCount ++ )
|
|
{
|
|
pbRunStart = pbSource + uiLineWidth * cLineCount;
|
|
bLastByte = *pbRunStart;
|
|
pbLineEnd = pbRunStart + ( ( uiWidth + 1 ) >> 1 );
|
|
iMode = RLE_START;
|
|
cCurrentRunLength = 2;
|
|
|
|
for(pbCurPos = pbRunStart+1;pbCurPos <= pbLineEnd; pbCurPos += 1)
|
|
{
|
|
|
|
// We won't really encode the value at *pbLineEnd since it points
|
|
// past the end of the scan so it doesn't matter what value we use.
|
|
// However, it is important not to reference it since it may point
|
|
// past the end of the buffer which can be uncommited memory.
|
|
|
|
if( pbCurPos == pbLineEnd )
|
|
{
|
|
bCurChar = 0xFF;
|
|
}
|
|
else
|
|
{
|
|
bCurChar = *pbCurPos;
|
|
}
|
|
|
|
|
|
switch( iMode )
|
|
{
|
|
case RLE_START:
|
|
iMode = ( bCurChar == bLastByte ) ? RLE_ENCODED : RLE_ABSOLUTE;
|
|
bLastByte = bCurChar;
|
|
break;
|
|
case RLE_ABSOLUTE:
|
|
|
|
// There are two ways that this run could be over. We could have exceeded the
|
|
// maximum length 0xFE ( since this algorithm works with bytes ), or there
|
|
// could be a switch into absolute mode.
|
|
|
|
if( ( bCurChar == bLastByte ) ||
|
|
( cCurrentRunLength == 0xFE ) )
|
|
|
|
{
|
|
int iOffset;
|
|
|
|
if( cCurrentRunLength == 0xFE )
|
|
{
|
|
// If this is the end of the line and there is and odd line length, ignore the
|
|
// last nibble of the the final byte.
|
|
|
|
if( (pbCurPos == pbLineEnd ) && ( uiWidth & 0x01 ))
|
|
iOffset = 1;
|
|
else
|
|
iOffset = 0;
|
|
|
|
iMode = RLE_START;
|
|
}
|
|
else
|
|
{
|
|
iOffset = 2;
|
|
iMode = RLE_ENCODED;
|
|
}
|
|
|
|
cTemp = WriteAbsolute4(pbRunStart, pbTarget,
|
|
cCurrentRunLength - iOffset, pbEndOfBuffer);
|
|
|
|
// if pbTarget is not NULL and cTemp is zero then
|
|
// the buffer is too small to hold encoded data
|
|
|
|
if(pbTarget != NULL) {
|
|
if (cTemp == 0) return(0);
|
|
pbTarget += cTemp;
|
|
}
|
|
|
|
cTotal += cTemp;
|
|
pbRunStart = pbCurPos;
|
|
cCurrentRunLength = iOffset;
|
|
}
|
|
|
|
bLastByte = bCurChar;
|
|
break;
|
|
|
|
case RLE_ENCODED:
|
|
if( ( bCurChar != bLastByte ) ||
|
|
( cCurrentRunLength == 0xFE ) )
|
|
|
|
{
|
|
// Don't include last nibble if the width of the scan line is odd and this
|
|
// this is the last byte.
|
|
|
|
if( (pbCurPos == pbLineEnd ) && ( uiWidth & 0x01 ))
|
|
cCurrentRunLength -= 1;
|
|
|
|
cTemp = WriteEncoded4(bLastByte,
|
|
pbTarget, cCurrentRunLength, pbEndOfBuffer);
|
|
|
|
// if pbTarget is not NULL and cTemp is zero then
|
|
// the buffer is too small to hold encoded data
|
|
|
|
if(pbTarget != NULL) {
|
|
if (cTemp == 0) return(0);
|
|
pbTarget += cTemp;
|
|
}
|
|
|
|
cTotal += cTemp;
|
|
bLastByte = bCurChar;
|
|
pbRunStart = pbCurPos;
|
|
cCurrentRunLength = 0;
|
|
iMode = RLE_START ;
|
|
}
|
|
|
|
}
|
|
cCurrentRunLength += 2;
|
|
}
|
|
|
|
if( cCurrentRunLength > 3 )
|
|
{
|
|
// Don't include last nibble if the width of the scan line is odd and this
|
|
// this is the last byte.
|
|
|
|
if( uiWidth & 0x01 )
|
|
cCurrentRunLength -= 1;
|
|
|
|
|
|
// if pbTarget is not NULL and cTemp is zero then
|
|
// the buffer is too small to hold encoded data
|
|
|
|
if(iMode == RLE_ABSOLUTE)
|
|
cTemp = WriteAbsolute4(pbRunStart, pbTarget,
|
|
cCurrentRunLength - 2, pbEndOfBuffer);
|
|
else {
|
|
cTemp = WriteEncoded4(bLastByte, pbTarget,
|
|
cCurrentRunLength - 2, pbEndOfBuffer);
|
|
}
|
|
|
|
if (pbTarget != NULL) {
|
|
if (cTemp == 0) return(0);
|
|
pbTarget += cTemp;
|
|
}
|
|
|
|
cTotal += cTemp;
|
|
}
|
|
|
|
if( pbTarget <= pbEndOfBuffer )
|
|
cTotal += 2;
|
|
|
|
if( pbTarget != NULL )
|
|
{
|
|
*((WORD *) pbTarget) = 0;
|
|
pbTarget += 2;
|
|
}
|
|
|
|
}
|
|
// Write "End of bitmap" at the end so we're win31 compatible.
|
|
|
|
if( pbTarget == NULL )
|
|
return(cTotal + 2);
|
|
|
|
if( pbTarget + 2 > pbEndOfBuffer )
|
|
return(0);
|
|
|
|
*pbTarget++ = 0;
|
|
*pbTarget++ = 1;
|
|
return(cTotal + 2);
|
|
}
|