- Fixed implementation of PALOBJ_cGetColors.

- Cleaned up IntEngCreateXlate and XLATEOBJ_iXlate a bit and fixed some cases (Indexed -> Bitfields/BGR, Bitfields/BGR -> Indexed).
- Removed simple color cache from ClosestColorMatch, because it wasn't thread safe and would return bogus values when more XLATEOBJs are used at once.

svn path=/trunk/; revision=9914
This commit is contained in:
Filip Navara 2004-06-28 15:53:17 +00:00
parent 6c9226bcbf
commit a630cd560f
2 changed files with 160 additions and 237 deletions

View file

@ -16,7 +16,7 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/* $Id: palette.c,v 1.21 2004/05/10 17:07:17 weiden Exp $
/* $Id: palette.c,v 1.22 2004/06/28 15:53:17 navaraf Exp $
*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
@ -32,22 +32,18 @@
* @implemented
*/
HPALETTE STDCALL
EngCreatePalette(ULONG Mode,
ULONG NumColors,
ULONG *Colors,
ULONG Red,
ULONG Green,
ULONG Blue)
EngCreatePalette(ULONG Mode, ULONG NumColors, ULONG *Colors,
ULONG Red, ULONG Green, ULONG Blue)
{
HPALETTE Palette;
HPALETTE Palette;
Palette = PALETTE_AllocPalette(Mode, NumColors, Colors, Red, Green, Blue);
if (NULL != Palette)
{
Palette = PALETTE_AllocPalette(Mode, NumColors, Colors, Red, Green, Blue);
if (Palette != NULL)
{
GDIOBJ_SetOwnership(Palette, NULL);
}
}
return Palette;
return Palette;
}
/*
@ -56,34 +52,31 @@ EngCreatePalette(ULONG Mode,
BOOL STDCALL
EngDeletePalette(IN HPALETTE Palette)
{
GDIOBJ_SetOwnership(Palette, PsGetCurrentProcess());
GDIOBJ_SetOwnership(Palette, PsGetCurrentProcess());
return PALETTE_FreePalette(Palette);
return PALETTE_FreePalette(Palette);
}
/*
* @implemented
*/
ULONG STDCALL
PALOBJ_cGetColors(PALOBJ *PalObj,
ULONG Start,
ULONG Colors,
ULONG *PaletteEntry)
PALOBJ_cGetColors(PALOBJ *PalObj, ULONG Start, ULONG Colors, ULONG *PaletteEntry)
{
ULONG i;
PALGDI *PalGDI;
PALGDI *PalGDI;
PalGDI = (PALGDI*)PalObj;
//PalGDI = (PALGDI*)AccessInternalObjectFromUserObject(PalObj);
PalGDI = (PALGDI*)PalObj;
/* PalGDI = (PALGDI*)AccessInternalObjectFromUserObject(PalObj); */
for(i=Start; i<Colors; i++)
{
PaletteEntry[i] = RGB(
PalGDI->IndexedColors[i].peRed,
PalGDI->IndexedColors[i].peGreen,
PalGDI->IndexedColors[i].peBlue);
}
if (Start >= PalGDI->NumColors)
return 0;
return Colors;
Colors = min(Colors, PalGDI->NumColors - Start);
/* NOTE: PaletteEntry ULONGs are in the same order as PALETTEENTRY. */
RtlCopyMemory(PaletteEntry, PalGDI->IndexedColors + Start, sizeof(ULONG) * Colors);
return Colors;
}
/* EOF */

View file

@ -16,7 +16,7 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/* $Id: xlate.c,v 1.35 2004/05/30 14:01:12 weiden Exp $
/* $Id: xlate.c,v 1.36 2004/06/28 15:53:17 navaraf Exp $
*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
@ -30,8 +30,6 @@
// TODO: Cache XLATEOBJs that are created by EngCreateXlate by checking if the given palettes match a cached list
ULONG CCMLastSourceColor = 0, CCMLastColorMatch = 0;
static ULONG FASTCALL ShiftAndMask(XLATEGDI *XlateGDI, ULONG Color)
{
ULONG TranslatedColor;
@ -72,14 +70,6 @@ ClosestColorMatch(XLATEGDI *XlateGDI, ULONG SourceColor,
ULONG SourceRed, SourceGreen, SourceBlue;
ULONG cxRed, cxGreen, cxBlue, rt, BestMatch = 16777215;
// Simple cache -- only one value because we don't want to waste time
// if the colors aren't very sequential
if(SourceColor == CCMLastSourceColor)
{
return CCMLastColorMatch;
}
if (PAL_BITFIELDS == XlateGDI->XlateObj.iSrcType || PAL_BGR == XlateGDI->XlateObj.iSrcType)
{
/* FIXME: must use bitfields */
@ -112,9 +102,6 @@ ClosestColorMatch(XLATEGDI *XlateGDI, ULONG SourceColor,
}
}
CCMLastSourceColor = SourceColor;
CCMLastColorMatch = idx;
return idx;
}
@ -141,6 +128,10 @@ static VOID STDCALL
BitMasksFromPal(USHORT PalType, PPALGDI Palette,
PULONG RedMask, PULONG BlueMask, PULONG GreenMask)
{
static const union { PALETTEENTRY Color; ULONG Mask; } Red = {{255, 0, 0}};
static const union { PALETTEENTRY Color; ULONG Mask; } Green = {{0, 255, 0}};
static const union { PALETTEENTRY Color; ULONG Mask; } Blue = {{0, 0, 255}};
switch(PalType)
{
case PAL_RGB:
@ -155,8 +146,13 @@ BitMasksFromPal(USHORT PalType, PPALGDI Palette,
break;
case PAL_BITFIELDS:
*RedMask = Palette->RedMask;
*BlueMask = Palette->BlueMask;
*GreenMask = Palette->GreenMask;
*BlueMask = Palette->BlueMask;
break;
case PAL_INDEXED:
*RedMask = Red.Mask;
*GreenMask = Green.Mask;
*BlueMask = Blue.Mask;
break;
}
}
@ -201,185 +197,121 @@ VOID FASTCALL EngDeleteXlate(XLATEOBJ *XlateObj)
FreeGDIHandle((ULONG)HXlate);
}
XLATEOBJ * STDCALL IntEngCreateXlate(USHORT DestPalType, USHORT SourcePalType,
HPALETTE PaletteDest, HPALETTE PaletteSource)
XLATEOBJ* STDCALL
IntEngCreateXlate(USHORT DestPalType, USHORT SourcePalType,
HPALETTE PaletteDest, HPALETTE PaletteSource)
{
// FIXME: Add support for BGR conversions
ULONG NewXlate;
XLATEOBJ *XlateObj;
XLATEGDI *XlateGDI;
PALGDI *SourcePalGDI = 0;
PALGDI *DestPalGDI = 0;
ULONG SourceRedMask, SourceGreenMask, SourceBlueMask;
ULONG DestRedMask, DestGreenMask, DestBlueMask;
ULONG i;
HPALETTE NewXlate;
XLATEOBJ *XlateObj;
XLATEGDI *XlateGDI;
PALGDI *SourcePalGDI, *DestPalGDI;
ULONG IndexedColors;
ULONG SourceRedMask, SourceGreenMask, SourceBlueMask;
ULONG DestRedMask, DestGreenMask, DestBlueMask;
UINT i;
NewXlate = CreateGDIHandle(sizeof(XLATEGDI), sizeof(XLATEOBJ), (PVOID*)&XlateGDI, (PVOID*)&XlateObj);
if (!ValidEngHandle(NewXlate))
return NULL;
NewXlate = (HPALETTE)CreateGDIHandle(sizeof( XLATEGDI ), sizeof( XLATEOBJ ), (PVOID*)&XlateGDI, (PVOID*)&XlateObj);
if ( !ValidEngHandle ( NewXlate ) )
return NULL;
if (PaletteSource != NULL)
SourcePalGDI = PALETTE_LockPalette(PaletteSource);
if (PaletteDest == PaletteSource)
DestPalGDI = SourcePalGDI;
else if (PaletteDest != NULL)
DestPalGDI = PALETTE_LockPalette(PaletteDest);
if (NULL != PaletteSource)
{
SourcePalGDI = PALETTE_LockPalette(PaletteSource);
}
if (PaletteDest == PaletteSource)
{
DestPalGDI = SourcePalGDI;
}
else if (NULL != PaletteDest)
{
DestPalGDI = PALETTE_LockPalette(PaletteDest);
}
XlateObj->iSrcType = SourcePalType;
XlateObj->iDstType = DestPalType;
XlateObj->flXlate = 0;
XlateObj->iSrcType = SourcePalType;
XlateObj->iDstType = DestPalType;
/* Store handles of palettes in internal Xlate GDI object (or NULLs) */
XlateGDI->SourcePal = PaletteSource;
XlateGDI->DestPal = PaletteDest;
// Store handles of palettes in internal Xlate GDI object (or NULLs)
XlateGDI->DestPal = PaletteDest;
XlateGDI->SourcePal = PaletteSource;
XlateGDI->UseShiftAndMask = FALSE;
XlateObj->flXlate = 0;
/*
* Compute bit fiddeling constants unless both palettes are indexed, then
* we don't need them.
*/
if (SourcePalType != PAL_INDEXED || DestPalType != PAL_INDEXED)
{
BitMasksFromPal(SourcePalType, SourcePalGDI, &SourceRedMask,
&SourceBlueMask, &SourceGreenMask);
BitMasksFromPal(DestPalType, DestPalGDI, &DestRedMask,
&DestBlueMask, &DestGreenMask);
XlateGDI->RedShift = CalculateShift(SourceRedMask) - CalculateShift(DestRedMask);
XlateGDI->RedMask = DestRedMask;
XlateGDI->GreenShift = CalculateShift(SourceGreenMask) - CalculateShift(DestGreenMask);
XlateGDI->GreenMask = DestGreenMask;
XlateGDI->BlueShift = CalculateShift(SourceBlueMask) - CalculateShift(DestBlueMask);
XlateGDI->BlueMask = DestBlueMask;
}
XlateGDI->UseShiftAndMask = FALSE;
/* Compute bit fiddeling constants unless both palettes are indexed, then we don't need them */
if (PAL_INDEXED != SourcePalType || PAL_INDEXED != DestPalType)
{
BitMasksFromPal(PAL_INDEXED == SourcePalType ? PAL_RGB : SourcePalType,
SourcePalGDI, &SourceRedMask, &SourceBlueMask, &SourceGreenMask);
BitMasksFromPal(PAL_INDEXED == DestPalType ? PAL_RGB : DestPalType,
DestPalGDI, &DestRedMask, &DestBlueMask, &DestGreenMask);
XlateGDI->RedShift = CalculateShift(SourceRedMask) - CalculateShift(DestRedMask);
XlateGDI->RedMask = DestRedMask;
XlateGDI->GreenShift = CalculateShift(SourceGreenMask) - CalculateShift(DestGreenMask);
XlateGDI->GreenMask = DestGreenMask;
XlateGDI->BlueShift = CalculateShift(SourceBlueMask) - CalculateShift(DestBlueMask);
XlateGDI->BlueMask = DestBlueMask;
}
// If source and destination palettes are the same or if they're RGB/BGR
if( (PaletteDest == PaletteSource) ||
((DestPalType == PAL_RGB) && (SourcePalType == PAL_RGB)) ||
((DestPalType == PAL_BGR) && (SourcePalType == PAL_BGR)) )
{
XlateObj->flXlate |= XO_TRIVIAL;
if (NULL != PaletteSource)
{
PALETTE_UnlockPalette(PaletteSource);
}
if (NULL != PaletteDest && PaletteDest != PaletteSource)
{
PALETTE_UnlockPalette(PaletteDest);
}
return XlateObj;
}
/* If source and destination are bitfield based (RGB and BGR are just special bitfields) */
if ((PAL_RGB == DestPalType || PAL_BGR == DestPalType || PAL_BITFIELDS == DestPalType) &&
(PAL_RGB == SourcePalType || PAL_BGR == SourcePalType || PAL_BITFIELDS == SourcePalType))
{
if (SourceRedMask == DestRedMask &&
SourceBlueMask == DestBlueMask &&
SourceGreenMask == DestGreenMask)
{
/* If source and destination palettes are the same or if they're RGB/BGR */
if (PaletteDest == PaletteSource ||
(DestPalType == PAL_RGB && SourcePalType == PAL_RGB) ||
(DestPalType == PAL_BGR && SourcePalType == PAL_BGR))
{
XlateObj->flXlate |= XO_TRIVIAL;
}
XlateGDI->UseShiftAndMask = TRUE;
if (NULL != PaletteSource)
{
PALETTE_UnlockPalette(PaletteSource);
}
if (NULL != PaletteDest && PaletteDest != PaletteSource)
{
PALETTE_UnlockPalette(PaletteDest);
}
return XlateObj;
}
goto end;
}
// Prepare the translation table
if (PAL_INDEXED == SourcePalType || PAL_RGB == SourcePalType || PAL_BGR == SourcePalType)
{
XlateObj->flXlate |= XO_TABLE;
if ((SourcePalType == PAL_INDEXED) && (DestPalType == PAL_INDEXED))
{
if(SourcePalGDI->NumColors > DestPalGDI->NumColors)
/*
* If source and destination are bitfield based (RGB and BGR are just
* special bitfields) we can use simple shifting.
*/
if ((DestPalType == PAL_RGB || DestPalType == PAL_BGR ||
DestPalType == PAL_BITFIELDS) &&
(SourcePalType == PAL_RGB || SourcePalType == PAL_BGR ||
SourcePalType == PAL_BITFIELDS))
{
if (SourceRedMask == DestRedMask &&
SourceBlueMask == DestBlueMask &&
SourceGreenMask == DestGreenMask)
{
IndexedColors = SourcePalGDI->NumColors;
} else
IndexedColors = DestPalGDI->NumColors;
}
else if (SourcePalType == PAL_INDEXED) { IndexedColors = SourcePalGDI->NumColors; }
else if (DestPalType == PAL_INDEXED) { IndexedColors = DestPalGDI->NumColors; }
XlateGDI->translationTable = EngAllocMem(FL_ZERO_MEMORY, sizeof(ULONG)*IndexedColors, 0);
if (NULL == XlateGDI->translationTable)
{
if (NULL != PaletteSource)
{
PALETTE_UnlockPalette(PaletteSource);
}
if (NULL != PaletteDest && PaletteDest != PaletteSource)
{
PALETTE_UnlockPalette(PaletteDest);
}
EngDeleteXlate(XlateObj);
return NULL;
XlateObj->flXlate |= XO_TRIVIAL;
}
}
XlateGDI->UseShiftAndMask = TRUE;
goto end;
}
// Source palette is indexed
if(XlateObj->iSrcType == PAL_INDEXED)
{
if(XlateObj->iDstType == PAL_INDEXED)
{
// Converting from indexed to indexed
/* Indexed -> Indexed */
if (SourcePalType == PAL_INDEXED && DestPalType == PAL_INDEXED)
{
XlateGDI->translationTable =
EngAllocMem(0, sizeof(ULONG) * SourcePalGDI->NumColors, 0);
IndexedToIndexedTranslationTable(XlateGDI, XlateGDI->translationTable, DestPalGDI, SourcePalGDI);
} else
if (PAL_RGB == XlateObj->iDstType || PAL_BITFIELDS == XlateObj->iDstType )
{
// FIXME: Is this necessary? I think the driver has to call this
// function anyways if pulXlate is NULL and Source is PAL_INDEXED
XlateObj->flXlate |= XO_TABLE;
XlateObj->pulXlate = XlateGDI->translationTable;
goto end;
}
// Converting from indexed to RGB
/* Indexed -> Bitfields/RGB/BGR */
if (SourcePalType == PAL_INDEXED)
{
XlateGDI->translationTable =
EngAllocMem(0, sizeof(ULONG) * SourcePalGDI->NumColors, 0);
for (i = 0; i < SourcePalGDI->NumColors; i++)
XlateGDI->translationTable[i] =
ShiftAndMask(XlateGDI, *((ULONG *)&SourcePalGDI->IndexedColors[i]));
XlateObj->flXlate |= XO_TABLE;
XlateObj->pulXlate = XlateGDI->translationTable;
goto end;
}
RtlCopyMemory(XlateGDI->translationTable, SourcePalGDI->IndexedColors, sizeof(ULONG) * SourcePalGDI->NumColors);
if (PAL_BITFIELDS == XlateObj->iDstType)
{
for (i = 0; i < SourcePalGDI->NumColors; i++)
{
XlateGDI->translationTable[i] = ShiftAndMask(XlateGDI, XlateGDI->translationTable[i]);
}
}
}
/*
* Last case: Bitfields/RGB/BGR -> Indexed
* isn't handled here yet and all the logic is in XLATEOBJ_iXlate now.
*/
XlateObj->pulXlate = XlateGDI->translationTable;
}
// Source palette is RGB
if (PAL_RGB == XlateObj->iSrcType || PAL_BGR == XlateObj->iSrcType)
{
if(PAL_INDEXED == XlateObj->iDstType)
{
// FIXME: Is this necessary? I think the driver has to call this
// function anyways if pulXlate is NULL and Dest is PAL_INDEXED
// Converting from RGB to indexed
RtlCopyMemory(XlateGDI->translationTable, DestPalGDI->IndexedColors, sizeof(ULONG) * DestPalGDI->NumColors);
}
}
// FIXME: Add support for XO_TO_MONO
if (NULL != PaletteSource)
{
PALETTE_UnlockPalette(PaletteSource);
}
if (NULL != PaletteDest && PaletteDest != PaletteSource)
{
PALETTE_UnlockPalette(PaletteDest);
}
return XlateObj;
end:
if (PaletteSource != NULL)
PALETTE_UnlockPalette(PaletteSource);
if (PaletteDest != NULL && PaletteDest != PaletteSource)
PALETTE_UnlockPalette(PaletteDest);
return XlateObj;
}
XLATEOBJ * STDCALL IntEngCreateMonoXlate(
@ -458,6 +390,7 @@ XLATEOBJ_piVector(XLATEOBJ *XlateObj)
ULONG STDCALL
XLATEOBJ_iXlate(XLATEOBJ *XlateObj, ULONG Color)
{
XLATEGDI *XlateGDI;
PALGDI *PalGDI;
ULONG Closest;
@ -466,41 +399,38 @@ XLATEOBJ_iXlate(XLATEOBJ *XlateObj, ULONG Color)
return Color;
if (XlateObj->flXlate & XO_TRIVIAL)
{
return Color;
} else
if (XlateObj->flXlate & XO_TABLE)
return XlateObj->pulXlate[Color];
XlateGDI = (XLATEGDI *)AccessInternalObjectFromUserObject(XlateObj);
if (XlateObj->flXlate & XO_TO_MONO)
return Color == XlateGDI->BackgroundColor;
if (XlateGDI->UseShiftAndMask)
return ShiftAndMask(XlateGDI, Color);
if (XlateObj->iSrcType == PAL_RGB || XlateObj->iSrcType == PAL_BGR ||
XlateObj->iSrcType == PAL_BITFIELDS)
{
XLATEGDI *XlateGDI = (XLATEGDI *)AccessInternalObjectFromUserObject(XlateObj);
/* FIXME: should we cache colors used often? */
/* FIXME: won't work if destination isn't indexed */
if (XlateObj->flXlate & XO_TO_MONO)
{
return Color == XlateGDI->BackgroundColor;
} else
if (XlateGDI->UseShiftAndMask)
{
return ShiftAndMask(XlateGDI, Color);
} else
if (XlateObj->iSrcType == PAL_RGB || XlateObj->iSrcType == PAL_BGR ||
XlateObj->iSrcType == PAL_BITFIELDS)
{
/* FIXME: should we cache colors used often? */
/* FIXME: won't work if destination isn't indexed */
/* Extract the destination palette. */
PalGDI = PALETTE_LockPalette(XlateGDI->DestPal);
/* Extract the destination palette. */
PalGDI = PALETTE_LockPalette(XlateGDI->DestPal);
/* Convert the source color to the palette RGB format. */
Color = ShiftAndMask(XlateGDI, Color);
/* Return closest match for the given color. */
Closest = ClosestColorMatch(XlateGDI, Color, PalGDI->IndexedColors, PalGDI->NumColors);
PALETTE_UnlockPalette(XlateGDI->DestPal);
return Closest;
} else
if (XlateObj->iSrcType == PAL_INDEXED)
{
return XlateGDI->translationTable[Color];
}
}
/* Return closest match for the given color. */
Closest = ClosestColorMatch(XlateGDI, Color, PalGDI->IndexedColors, PalGDI->NumColors);
PALETTE_UnlockPalette(XlateGDI->DestPal);
return Closest;
}
return 0;
return 0;
}
/*