- 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 * along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * 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 * COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel * PROJECT: ReactOS kernel
@ -32,17 +32,13 @@
* @implemented * @implemented
*/ */
HPALETTE STDCALL HPALETTE STDCALL
EngCreatePalette(ULONG Mode, EngCreatePalette(ULONG Mode, ULONG NumColors, ULONG *Colors,
ULONG NumColors, ULONG Red, ULONG Green, ULONG Blue)
ULONG *Colors,
ULONG Red,
ULONG Green,
ULONG Blue)
{ {
HPALETTE Palette; HPALETTE Palette;
Palette = PALETTE_AllocPalette(Mode, NumColors, Colors, Red, Green, Blue); Palette = PALETTE_AllocPalette(Mode, NumColors, Colors, Red, Green, Blue);
if (NULL != Palette) if (Palette != NULL)
{ {
GDIOBJ_SetOwnership(Palette, NULL); GDIOBJ_SetOwnership(Palette, NULL);
} }
@ -65,25 +61,22 @@ EngDeletePalette(IN HPALETTE Palette)
* @implemented * @implemented
*/ */
ULONG STDCALL ULONG STDCALL
PALOBJ_cGetColors(PALOBJ *PalObj, PALOBJ_cGetColors(PALOBJ *PalObj, ULONG Start, ULONG Colors, ULONG *PaletteEntry)
ULONG Start,
ULONG Colors,
ULONG *PaletteEntry)
{ {
ULONG i;
PALGDI *PalGDI; PALGDI *PalGDI;
PalGDI = (PALGDI*)PalObj; PalGDI = (PALGDI*)PalObj;
//PalGDI = (PALGDI*)AccessInternalObjectFromUserObject(PalObj); /* PalGDI = (PALGDI*)AccessInternalObjectFromUserObject(PalObj); */
for(i=Start; i<Colors; i++) if (Start >= PalGDI->NumColors)
{ return 0;
PaletteEntry[i] = RGB(
PalGDI->IndexedColors[i].peRed, Colors = min(Colors, PalGDI->NumColors - Start);
PalGDI->IndexedColors[i].peGreen,
PalGDI->IndexedColors[i].peBlue); /* NOTE: PaletteEntry ULONGs are in the same order as PALETTEENTRY. */
} RtlCopyMemory(PaletteEntry, PalGDI->IndexedColors + Start, sizeof(ULONG) * Colors);
return Colors; return Colors;
} }
/* EOF */ /* EOF */

View file

@ -16,7 +16,7 @@
* along with this program; if not, write to the Free Software * along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * 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 * COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel * 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 // 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) static ULONG FASTCALL ShiftAndMask(XLATEGDI *XlateGDI, ULONG Color)
{ {
ULONG TranslatedColor; ULONG TranslatedColor;
@ -72,14 +70,6 @@ ClosestColorMatch(XLATEGDI *XlateGDI, ULONG SourceColor,
ULONG SourceRed, SourceGreen, SourceBlue; ULONG SourceRed, SourceGreen, SourceBlue;
ULONG cxRed, cxGreen, cxBlue, rt, BestMatch = 16777215; 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) if (PAL_BITFIELDS == XlateGDI->XlateObj.iSrcType || PAL_BGR == XlateGDI->XlateObj.iSrcType)
{ {
/* FIXME: must use bitfields */ /* FIXME: must use bitfields */
@ -112,9 +102,6 @@ ClosestColorMatch(XLATEGDI *XlateGDI, ULONG SourceColor,
} }
} }
CCMLastSourceColor = SourceColor;
CCMLastColorMatch = idx;
return idx; return idx;
} }
@ -141,6 +128,10 @@ static VOID STDCALL
BitMasksFromPal(USHORT PalType, PPALGDI Palette, BitMasksFromPal(USHORT PalType, PPALGDI Palette,
PULONG RedMask, PULONG BlueMask, PULONG GreenMask) 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) switch(PalType)
{ {
case PAL_RGB: case PAL_RGB:
@ -155,8 +146,13 @@ BitMasksFromPal(USHORT PalType, PPALGDI Palette,
break; break;
case PAL_BITFIELDS: case PAL_BITFIELDS:
*RedMask = Palette->RedMask; *RedMask = Palette->RedMask;
*BlueMask = Palette->BlueMask;
*GreenMask = Palette->GreenMask; *GreenMask = Palette->GreenMask;
*BlueMask = Palette->BlueMask;
break;
case PAL_INDEXED:
*RedMask = Red.Mask;
*GreenMask = Green.Mask;
*BlueMask = Blue.Mask;
break; break;
} }
} }
@ -201,55 +197,50 @@ VOID FASTCALL EngDeleteXlate(XLATEOBJ *XlateObj)
FreeGDIHandle((ULONG)HXlate); FreeGDIHandle((ULONG)HXlate);
} }
XLATEOBJ * STDCALL IntEngCreateXlate(USHORT DestPalType, USHORT SourcePalType, XLATEOBJ* STDCALL
IntEngCreateXlate(USHORT DestPalType, USHORT SourcePalType,
HPALETTE PaletteDest, HPALETTE PaletteSource) HPALETTE PaletteDest, HPALETTE PaletteSource)
{ {
// FIXME: Add support for BGR conversions ULONG NewXlate;
HPALETTE NewXlate;
XLATEOBJ *XlateObj; XLATEOBJ *XlateObj;
XLATEGDI *XlateGDI; XLATEGDI *XlateGDI;
PALGDI *SourcePalGDI, *DestPalGDI; PALGDI *SourcePalGDI = 0;
ULONG IndexedColors; PALGDI *DestPalGDI = 0;
ULONG SourceRedMask, SourceGreenMask, SourceBlueMask; ULONG SourceRedMask, SourceGreenMask, SourceBlueMask;
ULONG DestRedMask, DestGreenMask, DestBlueMask; ULONG DestRedMask, DestGreenMask, DestBlueMask;
UINT i; ULONG i;
NewXlate = (HPALETTE)CreateGDIHandle(sizeof( XLATEGDI ), sizeof( XLATEOBJ ), (PVOID*)&XlateGDI, (PVOID*)&XlateObj); NewXlate = CreateGDIHandle(sizeof(XLATEGDI), sizeof(XLATEOBJ), (PVOID*)&XlateGDI, (PVOID*)&XlateObj);
if (!ValidEngHandle(NewXlate)) if (!ValidEngHandle(NewXlate))
return NULL; return NULL;
if (NULL != PaletteSource) if (PaletteSource != NULL)
{
SourcePalGDI = PALETTE_LockPalette(PaletteSource); SourcePalGDI = PALETTE_LockPalette(PaletteSource);
}
if (PaletteDest == PaletteSource) if (PaletteDest == PaletteSource)
{
DestPalGDI = SourcePalGDI; DestPalGDI = SourcePalGDI;
} else if (PaletteDest != NULL)
else if (NULL != PaletteDest)
{
DestPalGDI = PALETTE_LockPalette(PaletteDest); DestPalGDI = PALETTE_LockPalette(PaletteDest);
}
XlateObj->iSrcType = SourcePalType; XlateObj->iSrcType = SourcePalType;
XlateObj->iDstType = DestPalType; XlateObj->iDstType = DestPalType;
// Store handles of palettes in internal Xlate GDI object (or NULLs)
XlateGDI->DestPal = PaletteDest;
XlateGDI->SourcePal = PaletteSource;
XlateObj->flXlate = 0; XlateObj->flXlate = 0;
/* Store handles of palettes in internal Xlate GDI object (or NULLs) */
XlateGDI->SourcePal = PaletteSource;
XlateGDI->DestPal = PaletteDest;
XlateGDI->UseShiftAndMask = FALSE; 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) * Compute bit fiddeling constants unless both palettes are indexed, then
* we don't need them.
*/
if (SourcePalType != PAL_INDEXED || DestPalType != PAL_INDEXED)
{ {
BitMasksFromPal(PAL_INDEXED == SourcePalType ? PAL_RGB : SourcePalType, BitMasksFromPal(SourcePalType, SourcePalGDI, &SourceRedMask,
SourcePalGDI, &SourceRedMask, &SourceBlueMask, &SourceGreenMask); &SourceBlueMask, &SourceGreenMask);
BitMasksFromPal(PAL_INDEXED == DestPalType ? PAL_RGB : DestPalType, BitMasksFromPal(DestPalType, DestPalGDI, &DestRedMask,
DestPalGDI, &DestRedMask, &DestBlueMask, &DestGreenMask); &DestBlueMask, &DestGreenMask);
XlateGDI->RedShift = CalculateShift(SourceRedMask) - CalculateShift(DestRedMask); XlateGDI->RedShift = CalculateShift(SourceRedMask) - CalculateShift(DestRedMask);
XlateGDI->RedMask = DestRedMask; XlateGDI->RedMask = DestRedMask;
XlateGDI->GreenShift = CalculateShift(SourceGreenMask) - CalculateShift(DestGreenMask); XlateGDI->GreenShift = CalculateShift(SourceGreenMask) - CalculateShift(DestGreenMask);
@ -258,26 +249,23 @@ XLATEOBJ * STDCALL IntEngCreateXlate(USHORT DestPalType, USHORT SourcePalType,
XlateGDI->BlueMask = DestBlueMask; XlateGDI->BlueMask = DestBlueMask;
} }
// If source and destination palettes are the same or if they're RGB/BGR /* If source and destination palettes are the same or if they're RGB/BGR */
if( (PaletteDest == PaletteSource) || if (PaletteDest == PaletteSource ||
((DestPalType == PAL_RGB) && (SourcePalType == PAL_RGB)) || (DestPalType == PAL_RGB && SourcePalType == PAL_RGB) ||
((DestPalType == PAL_BGR) && (SourcePalType == PAL_BGR)) ) (DestPalType == PAL_BGR && SourcePalType == PAL_BGR))
{ {
XlateObj->flXlate |= XO_TRIVIAL; XlateObj->flXlate |= XO_TRIVIAL;
if (NULL != PaletteSource) goto end;
{
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) && * If source and destination are bitfield based (RGB and BGR are just
(PAL_RGB == SourcePalType || PAL_BGR == SourcePalType || PAL_BITFIELDS == SourcePalType)) * 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 && if (SourceRedMask == DestRedMask &&
SourceBlueMask == DestBlueMask && SourceBlueMask == DestBlueMask &&
@ -286,99 +274,43 @@ XLATEOBJ * STDCALL IntEngCreateXlate(USHORT DestPalType, USHORT SourcePalType,
XlateObj->flXlate |= XO_TRIVIAL; XlateObj->flXlate |= XO_TRIVIAL;
} }
XlateGDI->UseShiftAndMask = TRUE; XlateGDI->UseShiftAndMask = TRUE;
if (NULL != PaletteSource) goto end;
{
PALETTE_UnlockPalette(PaletteSource);
}
if (NULL != PaletteDest && PaletteDest != PaletteSource)
{
PALETTE_UnlockPalette(PaletteDest);
}
return XlateObj;
} }
// Prepare the translation table /* Indexed -> Indexed */
if (PAL_INDEXED == SourcePalType || PAL_RGB == SourcePalType || PAL_BGR == SourcePalType) if (SourcePalType == PAL_INDEXED && DestPalType == PAL_INDEXED)
{ {
XlateObj->flXlate |= XO_TABLE; XlateGDI->translationTable =
if ((SourcePalType == PAL_INDEXED) && (DestPalType == PAL_INDEXED)) EngAllocMem(0, sizeof(ULONG) * SourcePalGDI->NumColors, 0);
{
if(SourcePalGDI->NumColors > DestPalGDI->NumColors)
{
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;
}
}
// Source palette is indexed
if(XlateObj->iSrcType == PAL_INDEXED)
{
if(XlateObj->iDstType == PAL_INDEXED)
{
// Converting from indexed to indexed
IndexedToIndexedTranslationTable(XlateGDI, XlateGDI->translationTable, DestPalGDI, SourcePalGDI); IndexedToIndexedTranslationTable(XlateGDI, XlateGDI->translationTable, DestPalGDI, SourcePalGDI);
} else XlateObj->flXlate |= XO_TABLE;
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
// Converting from indexed to RGB
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]);
}
}
}
XlateObj->pulXlate = XlateGDI->translationTable; XlateObj->pulXlate = XlateGDI->translationTable;
goto end;
} }
// Source palette is RGB /* Indexed -> Bitfields/RGB/BGR */
if (PAL_RGB == XlateObj->iSrcType || PAL_BGR == XlateObj->iSrcType) if (SourcePalType == PAL_INDEXED)
{ {
if(PAL_INDEXED == XlateObj->iDstType) XlateGDI->translationTable =
{ EngAllocMem(0, sizeof(ULONG) * SourcePalGDI->NumColors, 0);
// FIXME: Is this necessary? I think the driver has to call this for (i = 0; i < SourcePalGDI->NumColors; i++)
// function anyways if pulXlate is NULL and Dest is PAL_INDEXED XlateGDI->translationTable[i] =
ShiftAndMask(XlateGDI, *((ULONG *)&SourcePalGDI->IndexedColors[i]));
// Converting from RGB to indexed XlateObj->flXlate |= XO_TABLE;
RtlCopyMemory(XlateGDI->translationTable, DestPalGDI->IndexedColors, sizeof(ULONG) * DestPalGDI->NumColors); XlateObj->pulXlate = XlateGDI->translationTable;
} goto end;
} }
// FIXME: Add support for XO_TO_MONO /*
if (NULL != PaletteSource) * Last case: Bitfields/RGB/BGR -> Indexed
{ * isn't handled here yet and all the logic is in XLATEOBJ_iXlate now.
*/
end:
if (PaletteSource != NULL)
PALETTE_UnlockPalette(PaletteSource); PALETTE_UnlockPalette(PaletteSource);
} if (PaletteDest != NULL && PaletteDest != PaletteSource)
if (NULL != PaletteDest && PaletteDest != PaletteSource)
{
PALETTE_UnlockPalette(PaletteDest); PALETTE_UnlockPalette(PaletteDest);
}
return XlateObj; return XlateObj;
} }
@ -458,6 +390,7 @@ XLATEOBJ_piVector(XLATEOBJ *XlateObj)
ULONG STDCALL ULONG STDCALL
XLATEOBJ_iXlate(XLATEOBJ *XlateObj, ULONG Color) XLATEOBJ_iXlate(XLATEOBJ *XlateObj, ULONG Color)
{ {
XLATEGDI *XlateGDI;
PALGDI *PalGDI; PALGDI *PalGDI;
ULONG Closest; ULONG Closest;
@ -466,20 +399,19 @@ XLATEOBJ_iXlate(XLATEOBJ *XlateObj, ULONG Color)
return Color; return Color;
if (XlateObj->flXlate & XO_TRIVIAL) if (XlateObj->flXlate & XO_TRIVIAL)
{
return Color; return Color;
} else
{ if (XlateObj->flXlate & XO_TABLE)
XLATEGDI *XlateGDI = (XLATEGDI *)AccessInternalObjectFromUserObject(XlateObj); return XlateObj->pulXlate[Color];
XlateGDI = (XLATEGDI *)AccessInternalObjectFromUserObject(XlateObj);
if (XlateObj->flXlate & XO_TO_MONO) if (XlateObj->flXlate & XO_TO_MONO)
{
return Color == XlateGDI->BackgroundColor; return Color == XlateGDI->BackgroundColor;
} else
if (XlateGDI->UseShiftAndMask) if (XlateGDI->UseShiftAndMask)
{
return ShiftAndMask(XlateGDI, Color); return ShiftAndMask(XlateGDI, Color);
} else
if (XlateObj->iSrcType == PAL_RGB || XlateObj->iSrcType == PAL_BGR || if (XlateObj->iSrcType == PAL_RGB || XlateObj->iSrcType == PAL_BGR ||
XlateObj->iSrcType == PAL_BITFIELDS) XlateObj->iSrcType == PAL_BITFIELDS)
{ {
@ -489,15 +421,13 @@ XLATEOBJ_iXlate(XLATEOBJ *XlateObj, ULONG Color)
/* Extract the destination palette. */ /* Extract the destination palette. */
PalGDI = PALETTE_LockPalette(XlateGDI->DestPal); 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. */ /* Return closest match for the given color. */
Closest = ClosestColorMatch(XlateGDI, Color, PalGDI->IndexedColors, PalGDI->NumColors); Closest = ClosestColorMatch(XlateGDI, Color, PalGDI->IndexedColors, PalGDI->NumColors);
PALETTE_UnlockPalette(XlateGDI->DestPal); PALETTE_UnlockPalette(XlateGDI->DestPal);
return Closest; return Closest;
} else
if (XlateObj->iSrcType == PAL_INDEXED)
{
return XlateGDI->translationTable[Color];
}
} }
return 0; return 0;