📄 swconvrt.cpp
字号:
}
else if( pxo->flXlate == XO_TABLE )
{
DEBUGMSG(GPE_ZONE_BLT_LO,(TEXT("XO_TABLE\r\n")));
*ppLookup = pxo->pulXlate;
}
else if( pxo->flXlate == XO_TO_MONO )
{
DEBUGMSG(GPE_ZONE_BLT_LO,(TEXT("XO_TO_MONO\r\n")));
// we could optionally create a lookup table if the source is PAL_INDEXED
// for faster access
unsigned long backgroundColor = pxo->pulXlate[0];
if( ( converterIndex = gMonoLRU.Find( backgroundColor ) ) == -1 )
{
converterIndex = gMonoLRU.Add( backgroundColor );
}
gMonoConverter[converterIndex].Init(backgroundColor);
*ppConvertObj = &gMonoConverter[converterIndex];
*ppConvertFn = FNTYPE MonoColorConverter::AnyToMono;
}
else if( pxo->iSrcType == PAL_INDEXED )
{
DEBUGMSG(GPE_ZONE_BLT_LO,(TEXT("PAL_INDEXED->\r\n")));
if( ( converterIndex = gLookupLRU.Find( pxo->iUniq ) ) == -1 )
{
// there is no cached converter for this iUniq
converterIndex = gLookupLRU.Add( pxo->iUniq );
gLookupConverter[converterIndex].Init( pxo );
}
*ppLookup = gLookupConverter[converterIndex].LookupTable();
}
else if( pxo->iDstType == PAL_INDEXED )
{
DEBUGMSG(GPE_ZONE_BLT_LO,(TEXT("->PAL_INDEXED\r\n")));
if( ( converterIndex = gGroupLRU.Find( pxo->iUniq ) ) == -1 )
{
// there is no cached converter for this iUniq
converterIndex = gGroupLRU.Add( pxo->iUniq );
gGroupConverter[converterIndex].Init( pxo );
}
*ppConvertObj = &gGroupConverter[converterIndex];
*ppConvertFn = FNTYPE GroupColorConverter::MaskedSrcToPaletteDst;
}
else
{
// It is masked,rgb, or bgr --> masked,rgb, or bgr
// Look up the converter function based on the src & dst color types
DEBUGMSG(GPE_ZONE_BLT_LO,(TEXT("mask/rgb <-> mask/rgb\r\n")));
*ppConvertFn = m_afpConvertFunction[
log2nOver2[pxo->iSrcType/2]*4+log2nOver2[pxo->iDstType/2] - 4];
if( ( pxo->iSrcType | pxo->iDstType ) & PAL_BITFIELDS )
{
// for bitfields (i.e. masked), there is some storage required...
if( ( converterIndex = gMaskedLRU.Find( pxo->iUniq ) ) == -1 )
{
// there is no cached converter for this iUniq
converterIndex = gMaskedLRU.Add( pxo->iUniq );
gMaskedConverter[converterIndex].Init( pxo );
}
*ppConvertObj = &gMaskedConverter[converterIndex];
}
}
}
void MaskColorConverter::Init( XLATEOBJ *pxo )
{
DEBUGMSG(GPE_ZONE_BLT_LO,(TEXT("Mask Init\r\n")));
m_Src.InitMaskInfo( pxo, XO_SRCPALETTE, pxo->iSrcType );
m_Dst.InitMaskInfo( pxo, XO_DESTPALETTE, pxo->iDstType );
}
void GroupColorConverter::Init( XLATEOBJ *pxo )
{
// Create an intensity-grouped table
short group;
short lastHead;
short i;
DEBUGMSG(GPE_ZONE_BLT_LO,(TEXT("Group Init\r\n")));
m_Src.InitMaskInfo( pxo, XO_SRCPALETTE, pxo->iSrcType );
// Read in destination palette
unsigned short m_nPaletteSize = (unsigned short)XLATEOBJ_cGetPalette(pxo,XO_DESTPALETTE,0,(unsigned long *)NULL);
if( m_nPaletteSize > 256 )
m_nPaletteSize = 256;
XLATEOBJ_cGetPalette(pxo,XO_DESTPALETTE,m_nPaletteSize,m_pPalette);
m_nHighestGroup = 0;
m_nLowestGroup = 0x0100;
// Create chains of entries for each intensity group
for( group=0; group<=NUMINTENSITYGROUPS; group++ )
m_aiIntensityHead[group] = -1;
for( i=0; i<m_nPaletteSize; i++ )
{
group = RGBToGroup( m_pPalette[i] );
m_piDstNext[i] = m_aiIntensityHead[group];
m_aiIntensityHead[group] = i;
if( group > m_nHighestGroup )
m_nHighestGroup = group;
if( group < m_nLowestGroup )
m_nLowestGroup = group;
}
lastHead = m_aiIntensityHead[m_nHighestGroup];
m_nHighestGroup++;
m_aiIntensityHead[m_nHighestGroup] = -1;
for( group=m_nHighestGroup-2; group>=m_nLowestGroup; group-- )
{
if( ( i = m_aiIntensityHead[group] ) == -1 )
m_aiIntensityHead[group] = lastHead;
else
{
// Connect last entry in chain to first entry in next chain
while( m_piDstNext[i] != -1 )
i = m_piDstNext[i];
m_piDstNext[i] = lastHead;
lastHead = m_aiIntensityHead[group];
}
}
// Invalidate the recent entry cache
m_LRURecent.Fill(0xffffffff);
}
void LookupColorConverter::Init( XLATEOBJ *pxo )
{
unsigned short srcInd;
unsigned long dstPalette[256];
// Used for palette -> palette, or palette -> masked
// First, read in the source palette
unsigned short srcPaletteSize = (unsigned short)XLATEOBJ_cGetPalette(pxo,XO_SRCPALETTE,0,(unsigned long *)NULL);
if( srcPaletteSize > 256 )
srcPaletteSize = 256;
XLATEOBJ_cGetPalette(pxo,XO_SRCPALETTE,srcPaletteSize,m_aLookup);
if( pxo->iDstType == PAL_INDEXED )
{
// Read in the dest palette
DEBUGMSG(GPE_ZONE_BLT_LO,(TEXT("PAL_INDEXED->PAL_INDEXED\r\n")));
unsigned short dstPaletteSize = (unsigned short)XLATEOBJ_cGetPalette(pxo,XO_DESTPALETTE,0,(unsigned long *)NULL);
if( dstPaletteSize > 256 )
dstPaletteSize = 256;
XLATEOBJ_cGetPalette(pxo,XO_DESTPALETTE,dstPaletteSize,dstPalette);
// Create a closest-match lookup table
unsigned long *srcPtr;
srcPtr = m_aLookup;
for( srcInd=0; srcInd<srcPaletteSize; srcInd++ )
{
*srcPtr = DrvRealizeColor( PAL_INDEXED, dstPaletteSize, dstPalette, *srcPtr );
srcPtr++;
}
}
else
{
m_Dst.InitMaskInfo( pxo, XO_DESTPALETTE, pxo->iDstType );
DEBUGMSG(GPE_ZONE_BLT_LO,(TEXT("PAL_INDEXED->mask/rgb\r\n")));
// Populate a lookup table with an appropriately munged palette
for( srcInd=0; srcInd < srcPaletteSize; srcInd++ )
{
if( pxo->iDstType == PAL_BITFIELDS )
m_aLookup[srcInd] = RGBSrcToMaskedDst( m_aLookup[srcInd] );
if( pxo->iDstType == PAL_BGR )
m_aLookup[srcInd] = SwapRedBlue( m_aLookup[srcInd] );
}
}
}
unsigned long GroupColorConverter::MaskedSrcToPaletteDst( unsigned long maskedSrc )
{
short lruIndex;
unsigned long dstValue;
unsigned long srcRGB;
short possibleDst;
short lowGroup, highGroup;
unsigned long error;
unsigned long smallestError;
if( ( lruIndex = m_LRURecent.Find(maskedSrc) ) == -1 )
{
if( m_Src.m_iType == PAL_RGB )
srcRGB = maskedSrc;
else if( m_Src.m_iType == PAL_BGR )
srcRGB = RGBToFromBGR( maskedSrc );
else
srcRGB = MaskedSrcToRGB( maskedSrc );
// We need to find the closest lookup
// Determine range of intensity groups to check
highGroup = lowGroup = RGBToGroup( srcRGB );
lowGroup = (lowGroup<m_nLowestGroup+4)?m_nLowestGroup:lowGroup-4;
highGroup = (highGroup>m_nHighestGroup-5)?m_nHighestGroup:highGroup+5;
if( m_aiIntensityHead[lowGroup] == m_aiIntensityHead[highGroup] )
{
// No palette entries in range (i.e. inept palette) - scan all entries
lowGroup = m_nLowestGroup;
highGroup = m_nHighestGroup;
}
smallestError=0x10000000;
for( possibleDst = m_aiIntensityHead[lowGroup];
possibleDst != m_aiIntensityHead[highGroup];
possibleDst = m_piDstNext[possibleDst] )
{
error = RGBError( srcRGB, m_pPalette[possibleDst] );
if( error < smallestError )
{
smallestError = error;
dstValue = (unsigned long)possibleDst;
}
}
// add this conversion to the LRU
lruIndex = m_LRURecent.Add(maskedSrc);
m_aRecentResult[lruIndex] = dstValue;
}
else
{
// we've recently done the same conversion so we can look it up
dstValue = m_aRecentResult[lruIndex];
}
return dstValue;
}
unsigned long MaskColorConverter::RGBToFromBGR( unsigned long rgbSrc )
{
return SwapRedBlue( rgbSrc );
}
unsigned long GroupColorConverter::RGBToFromBGR( unsigned long rgbSrc )
{
return SwapRedBlue( rgbSrc );
}
unsigned long MaskColorConverter::MaskedSrcToRGB( unsigned long srcValue )
{
return
( ( ( srcValue & m_Src.m_aMask[0] ) << m_Src.m_anShift[0] ) >> 24 ) |
( ( ( srcValue & m_Src.m_aMask[1] ) << m_Src.m_anShift[1] ) >> 16 ) |
( ( ( srcValue & m_Src.m_aMask[2] ) << m_Src.m_anShift[2] ) >> 8 );
}
unsigned long GroupColorConverter::MaskedSrcToRGB( unsigned long srcValue )
{
return
( ( ( srcValue & m_Src.m_aMask[0] ) << m_Src.m_anShift[0] ) >> 24 ) |
( ( ( srcValue & m_Src.m_aMask[1] ) << m_Src.m_anShift[1] ) >> 16 ) |
( ( ( srcValue & m_Src.m_aMask[2] ) << m_Src.m_anShift[2] ) >> 8 );
}
unsigned long MaskColorConverter::MaskedSrcToBGR( unsigned long srcValue )
{
return
( ( ( srcValue & m_Src.m_aMask[0] ) << m_Src.m_anShift[0] ) >> 8 ) |
( ( ( srcValue & m_Src.m_aMask[1] ) << m_Src.m_anShift[1] ) >> 16 ) |
( ( ( srcValue & m_Src.m_aMask[2] ) << m_Src.m_anShift[2] ) >> 24 );
}
unsigned long MaskColorConverter::RGBSrcToMaskedDst( unsigned long srcValue )
{
return
((( srcValue << 24 ) >> m_Dst.m_anShift[0] ) & m_Dst.m_aMask[0] ) |
((( srcValue << 16 ) >> m_Dst.m_anShift[1] ) & m_Dst.m_aMask[1] ) |
((( srcValue << 8 ) >> m_Dst.m_anShift[2] ) & m_Dst.m_aMask[2] );
}
unsigned long LookupColorConverter::RGBSrcToMaskedDst( unsigned long srcValue )
{
return
((( srcValue << 24 ) >> m_Dst.m_anShift[0] ) & m_Dst.m_aMask[0] ) |
((( srcValue << 16 ) >> m_Dst.m_anShift[1] ) & m_Dst.m_aMask[1] ) |
((( srcValue << 8 ) >> m_Dst.m_anShift[2] ) & m_Dst.m_aMask[2] );
}
unsigned long MaskColorConverter::BGRSrcToMaskedDst( unsigned long srcValue )
{
return
((( srcValue << 8 ) >> m_Dst.m_anShift[0] ) & m_Dst.m_aMask[0] ) |
((( srcValue << 16 ) >> m_Dst.m_anShift[1] ) & m_Dst.m_aMask[1] ) |
((( srcValue << 24 ) >> m_Dst.m_anShift[2] ) & m_Dst.m_aMask[2] );
}
unsigned long MaskColorConverter::MaskedSrcToMaskedDst( unsigned long maskedSrc )
{
return
( ( ( ( maskedSrc & m_Src.m_aMask[0] ) << m_Src.m_anShift[0] )
>> m_Dst.m_anShift[0] ) & m_Dst.m_aMask[0] ) |
( ( ( ( maskedSrc & m_Src.m_aMask[1] ) << m_Src.m_anShift[1] )
>> m_Dst.m_anShift[1] ) & m_Dst.m_aMask[1] ) |
( ( ( ( maskedSrc & m_Src.m_aMask[2] ) << m_Src.m_anShift[2] )
>> m_Dst.m_anShift[2] ) & m_Dst.m_aMask[2] );
}
unsigned long MonoColorConverter::AnyToMono( unsigned long srcValue )
{
return ( srcValue == m_BackgroundColor ) ? 1 : 0;
}
ULONG APIENTRY DrvRealizeColor(
USHORT iDstType,
ULONG cEntries,
ULONG *pPalette,
ULONG rgbColor)
{
unsigned short palInd;
unsigned long *palPtr;
unsigned long dstValue;
unsigned long smallestError;
unsigned long error;
unsigned long mask;
char shiftRight;
char shiftLeft;
switch( iDstType )
{
case PAL_INDEXED:
smallestError = 0x7fffffff; // Set large value
palPtr = pPalette;
for( palInd=0; palInd < cEntries; palInd++ )
{
error = RGBError( rgbColor, *palPtr++ );
if( error > smallestError )
continue;
smallestError = error;
dstValue = palInd;
if( error == 0 ) // perfect match, no need to keep looking
break;
}
return dstValue;
case PAL_BITFIELDS:
dstValue = 0;
for( shiftLeft=24; (shiftLeft>=0)&&(cEntries--); shiftLeft-=8 )
{
mask = *pPalette;
for( shiftRight=32; mask; shiftRight-- )
mask>>=1;
dstValue |= ( ( rgbColor << shiftLeft ) >> shiftRight ) & *pPalette++;
}
return dstValue;
case PAL_BGR:
return SwapRedBlue( rgbColor );
case PAL_RGB:
return rgbColor;
}
return 0; // actually an illegal type was encountered
}
ULONG APIENTRY DrvUnrealizeColor(
USHORT iSrcType,
ULONG cEntries,
ULONG *pPalette,
ULONG iRealizedColor)
{
unsigned long dstValue;
unsigned long mask;
char shiftRight;
char shiftLeft;
switch( iSrcType )
{
case PAL_INDEXED:
return pPalette[iRealizedColor];
case PAL_BITFIELDS:
dstValue = 0;
for( shiftRight=24; (shiftRight>=0)&&(cEntries--); shiftRight-=8 )
{
mask = *pPalette;
for( shiftLeft=32; mask; shiftLeft-- )
mask>>=1;
dstValue |= ( ( iRealizedColor & *pPalette++ ) << shiftLeft ) >> shiftRight;
}
return dstValue;
case PAL_BGR:
return SwapRedBlue(iRealizedColor);
case PAL_RGB:
return iRealizedColor;
}
return 0; // actually an illegal type was encountered
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -