mirror of
https://github.com/reactos/reactos.git
synced 2024-08-27 13:48:42 +00:00
440 lines
10 KiB
C
440 lines
10 KiB
C
/*
|
|
* ReactOS W32 Subsystem
|
|
* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 ReactOS Team
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation; either version 2 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License along
|
|
* with this program; if not, write to the Free Software Foundation, Inc.,
|
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
*/
|
|
|
|
#include <w32k.h>
|
|
|
|
#define NDEBUG
|
|
#include <debug.h>
|
|
|
|
HCOLORSPACE hStockColorSpace = NULL;
|
|
|
|
|
|
HCOLORSPACE
|
|
FASTCALL
|
|
IntGdiCreateColorSpace(
|
|
PLOGCOLORSPACEEXW pLogColorSpace)
|
|
{
|
|
PCOLORSPACE pCS;
|
|
HCOLORSPACE hCS;
|
|
|
|
pCS = COLORSPACEOBJ_AllocCSWithHandle();
|
|
hCS = pCS->BaseObject.hHmgr;
|
|
|
|
pCS->lcsColorSpace = pLogColorSpace->lcsColorSpace;
|
|
pCS->dwFlags = pLogColorSpace->dwFlags;
|
|
|
|
COLORSPACEOBJ_UnlockCS(pCS);
|
|
return hCS;
|
|
}
|
|
|
|
BOOL
|
|
FASTCALL
|
|
IntGdiDeleteColorSpace(
|
|
HCOLORSPACE hColorSpace)
|
|
{
|
|
BOOL Ret = FALSE;
|
|
|
|
if ( hColorSpace != hStockColorSpace )
|
|
{
|
|
Ret = COLORSPACEOBJ_FreeCSByHandle(hColorSpace);
|
|
if ( !Ret ) SetLastWin32Error(ERROR_INVALID_PARAMETER);
|
|
}
|
|
return Ret;
|
|
}
|
|
|
|
HANDLE
|
|
APIENTRY
|
|
NtGdiCreateColorSpace(
|
|
IN PLOGCOLORSPACEEXW pLogColorSpace)
|
|
{
|
|
LOGCOLORSPACEEXW Safelcs;
|
|
NTSTATUS Status = STATUS_SUCCESS;
|
|
|
|
_SEH2_TRY
|
|
{
|
|
ProbeForRead( pLogColorSpace,
|
|
sizeof(LOGCOLORSPACEEXW),
|
|
1);
|
|
RtlCopyMemory(&Safelcs, pLogColorSpace, sizeof(LOGCOLORSPACEEXW));
|
|
}
|
|
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
|
|
{
|
|
Status = _SEH2_GetExceptionCode();
|
|
}
|
|
_SEH2_END;
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
SetLastNtError(Status);
|
|
return NULL;
|
|
}
|
|
return IntGdiCreateColorSpace(&Safelcs);
|
|
}
|
|
|
|
BOOL
|
|
APIENTRY
|
|
NtGdiDeleteColorSpace(
|
|
IN HANDLE hColorSpace)
|
|
{
|
|
return IntGdiDeleteColorSpace(hColorSpace);
|
|
}
|
|
|
|
BOOL
|
|
FASTCALL
|
|
IntGetDeviceGammaRamp(HDEV hPDev, PGAMMARAMP Ramp)
|
|
{
|
|
PPDEVOBJ pGDev = (PPDEVOBJ) hPDev;
|
|
int i;
|
|
|
|
if (!(pGDev->flFlags & PDEV_DISPLAY )) return FALSE;
|
|
|
|
if ((pGDev->devinfo.iDitherFormat == BMF_8BPP) ||
|
|
(pGDev->devinfo.iDitherFormat == BMF_16BPP) ||
|
|
(pGDev->devinfo.iDitherFormat == BMF_24BPP) ||
|
|
(pGDev->devinfo.iDitherFormat == BMF_32BPP))
|
|
{
|
|
if (pGDev->flFlags & PDEV_GAMMARAMP_TABLE)
|
|
RtlCopyMemory( Ramp,
|
|
pGDev->pvGammaRamp,
|
|
sizeof(GAMMARAMP));
|
|
else
|
|
// Generate the 256-colors array
|
|
for(i=0; i<256; i++ )
|
|
{
|
|
int NewValue = i * 256;
|
|
|
|
Ramp->Red[i] = Ramp->Green[i] = Ramp->Blue[i] = ((WORD)NewValue);
|
|
}
|
|
return TRUE;
|
|
}
|
|
else
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL
|
|
APIENTRY
|
|
NtGdiGetDeviceGammaRamp(HDC hDC,
|
|
LPVOID Ramp)
|
|
{
|
|
BOOL Ret;
|
|
PDC dc;
|
|
NTSTATUS Status = STATUS_SUCCESS;
|
|
PGAMMARAMP SafeRamp;
|
|
|
|
if (!Ramp) return FALSE;
|
|
|
|
dc = DC_LockDc(hDC);
|
|
if (!dc)
|
|
{
|
|
SetLastWin32Error(ERROR_INVALID_HANDLE);
|
|
return FALSE;
|
|
}
|
|
|
|
SafeRamp = ExAllocatePool(PagedPool, sizeof(GAMMARAMP));
|
|
if (!SafeRamp)
|
|
{
|
|
DC_UnlockDc(dc);
|
|
SetLastWin32Error(STATUS_NO_MEMORY);
|
|
return FALSE;
|
|
}
|
|
|
|
Ret = IntGetDeviceGammaRamp((HDEV)dc->ppdev, SafeRamp);
|
|
|
|
if (!Ret) return Ret;
|
|
|
|
_SEH2_TRY
|
|
{
|
|
ProbeForWrite( Ramp,
|
|
sizeof(PVOID),
|
|
1);
|
|
RtlCopyMemory( Ramp,
|
|
SafeRamp,
|
|
sizeof(GAMMARAMP));
|
|
}
|
|
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
|
|
{
|
|
Status = _SEH2_GetExceptionCode();
|
|
}
|
|
_SEH2_END;
|
|
|
|
DC_UnlockDc(dc);
|
|
ExFreePool(SafeRamp);
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
SetLastNtError(Status);
|
|
return FALSE;
|
|
}
|
|
return Ret;
|
|
}
|
|
|
|
BOOL
|
|
APIENTRY
|
|
NtGdiSetColorSpace(IN HDC hdc,
|
|
IN HCOLORSPACE hColorSpace)
|
|
{
|
|
PDC pDC;
|
|
PDC_ATTR pdcattr;
|
|
PCOLORSPACE pCS;
|
|
|
|
pDC = DC_LockDc(hdc);
|
|
if (!pDC)
|
|
{
|
|
SetLastWin32Error(ERROR_INVALID_HANDLE);
|
|
return FALSE;
|
|
}
|
|
pdcattr = pDC->pdcattr;
|
|
|
|
if (pdcattr->hColorSpace == hColorSpace)
|
|
{
|
|
DC_UnlockDc(pDC);
|
|
return TRUE;
|
|
}
|
|
|
|
pCS = COLORSPACEOBJ_LockCS(hColorSpace);
|
|
if (!pCS)
|
|
{
|
|
SetLastWin32Error(ERROR_INVALID_HANDLE);
|
|
return FALSE;
|
|
}
|
|
|
|
if (pDC->dclevel.pColorSpace)
|
|
{
|
|
GDIOBJ_ShareUnlockObjByPtr((POBJ) pDC->dclevel.pColorSpace);
|
|
}
|
|
|
|
pDC->dclevel.pColorSpace = pCS;
|
|
pdcattr->hColorSpace = hColorSpace;
|
|
|
|
COLORSPACEOBJ_UnlockCS(pCS);
|
|
DC_UnlockDc(pDC);
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL
|
|
FASTCALL
|
|
UpdateDeviceGammaRamp( HDEV hPDev )
|
|
{
|
|
BOOL Ret = FALSE;
|
|
PPALETTE palGDI;
|
|
PALOBJ *palPtr;
|
|
PPDEVOBJ pGDev = (PPDEVOBJ) hPDev;
|
|
|
|
if ((pGDev->devinfo.iDitherFormat == BMF_8BPP) ||
|
|
(pGDev->devinfo.iDitherFormat == BMF_16BPP) ||
|
|
(pGDev->devinfo.iDitherFormat == BMF_24BPP) ||
|
|
(pGDev->devinfo.iDitherFormat == BMF_32BPP))
|
|
{
|
|
if (pGDev->DriverFunctions.IcmSetDeviceGammaRamp)
|
|
return pGDev->DriverFunctions.IcmSetDeviceGammaRamp( pGDev->dhpdev,
|
|
IGRF_RGB_256WORDS,
|
|
pGDev->pvGammaRamp);
|
|
|
|
if ( (pGDev->devinfo.iDitherFormat != BMF_8BPP) ||
|
|
!(pGDev->gdiinfo.flRaster & RC_PALETTE)) return FALSE;
|
|
|
|
if (!(pGDev->flFlags & PDEV_GAMMARAMP_TABLE)) return FALSE;
|
|
|
|
palGDI = PALETTE_LockPalette(pGDev->devinfo.hpalDefault);
|
|
if(!palGDI) return FALSE;
|
|
palPtr = (PALOBJ*) palGDI;
|
|
|
|
if (pGDev->flFlags & PDEV_GAMMARAMP_TABLE)
|
|
palGDI->Mode |= PAL_GAMMACORRECTION;
|
|
else
|
|
palGDI->Mode &= ~PAL_GAMMACORRECTION;
|
|
|
|
if (!(pGDev->flFlags & PDEV_DRIVER_PUNTED_CALL)) // No punting, we hook
|
|
{
|
|
// BMF_8BPP only!
|
|
// PALOBJ_cGetColors check mode flags and update Gamma Correction.
|
|
// Set the HDEV to pal and go.
|
|
palGDI->hPDev = hPDev;
|
|
Ret = pGDev->DriverFunctions.SetPalette(pGDev->dhpdev,
|
|
palPtr,
|
|
0,
|
|
0,
|
|
palGDI->NumColors);
|
|
}
|
|
PALETTE_UnlockPalette(palGDI);
|
|
return Ret;
|
|
}
|
|
else
|
|
return FALSE;
|
|
}
|
|
|
|
//
|
|
// ICM registry subkey sets internal brightness range, gamma range is 128 or
|
|
// 256 when icm is init.
|
|
INT IcmGammaRangeSet = 128; // <- make it global
|
|
|
|
BOOL
|
|
FASTCALL
|
|
IntSetDeviceGammaRamp(HDEV hPDev, PGAMMARAMP Ramp, BOOL Test)
|
|
{
|
|
WORD IcmGR, i, R, G, B;
|
|
BOOL Ret = FALSE, TstPeak;
|
|
PPDEVOBJ pGDev = (PPDEVOBJ) hPDev;
|
|
|
|
if (!hPDev) return FALSE;
|
|
|
|
if (!(pGDev->flFlags & PDEV_DISPLAY )) return FALSE;
|
|
|
|
if ((pGDev->devinfo.iDitherFormat == BMF_8BPP) ||
|
|
(pGDev->devinfo.iDitherFormat == BMF_16BPP) ||
|
|
(pGDev->devinfo.iDitherFormat == BMF_24BPP) ||
|
|
(pGDev->devinfo.iDitherFormat == BMF_32BPP))
|
|
{
|
|
if (!pGDev->DriverFunctions.IcmSetDeviceGammaRamp)
|
|
{ // No driver support
|
|
if (!(pGDev->devinfo.flGraphicsCaps2 & GCAPS2_CHANGEGAMMARAMP))
|
|
{ // Driver does not support Gamma Ramp, so test to see we
|
|
// have BMF_8BPP only and palette operation support.
|
|
if ((pGDev->devinfo.iDitherFormat != BMF_8BPP) ||
|
|
!(pGDev->gdiinfo.flRaster & RC_PALETTE)) return FALSE;
|
|
}
|
|
}
|
|
|
|
if (pGDev->flFlags & PDEV_GAMMARAMP_TABLE)
|
|
if (RtlCompareMemory( pGDev->pvGammaRamp, Ramp, sizeof(GAMMARAMP)) ==
|
|
sizeof(GAMMARAMP)) return TRUE;
|
|
// Verify Ramp is inside range.
|
|
IcmGR = -IcmGammaRangeSet;
|
|
TstPeak = (Test == FALSE);
|
|
for (i = 0; i < 256; i++)
|
|
{
|
|
R = Ramp->Red[i] / 256;
|
|
G = Ramp->Green[i] / 256;
|
|
B = Ramp->Blue[i] / 256;
|
|
if ( R >= IcmGR)
|
|
{
|
|
if ( R <= IcmGammaRangeSet + i)
|
|
{
|
|
if ( G >= IcmGR &&
|
|
(G <= IcmGammaRangeSet + i) &&
|
|
B >= IcmGR &&
|
|
(B <= IcmGammaRangeSet + i) ) continue;
|
|
}
|
|
}
|
|
if (Test) return Ret; // Don't set and return.
|
|
// No test override, check max range
|
|
if (TstPeak)
|
|
{
|
|
if ( R != (IcmGR * 256) ||
|
|
G != (IcmGR * 256) ||
|
|
B != (IcmGR * 256) ) TstPeak = FALSE; // W/i range.
|
|
}
|
|
}
|
|
// ReactOS allocates a ramp even if it is 8BPP and Palette only.
|
|
// This way we have a record of the change in memory.
|
|
if (!pGDev->pvGammaRamp && !(pGDev->flFlags & PDEV_GAMMARAMP_TABLE))
|
|
{ // If the above is true and we have nothing allocated, create it.
|
|
pGDev->pvGammaRamp = ExAllocatePoolWithTag(PagedPool, sizeof(GAMMARAMP), TAG_GDIICM);
|
|
pGDev->flFlags |= PDEV_GAMMARAMP_TABLE;
|
|
}
|
|
if (pGDev->pvGammaRamp)
|
|
RtlCopyMemory( pGDev->pvGammaRamp, Ramp, sizeof(GAMMARAMP));
|
|
|
|
Ret = UpdateDeviceGammaRamp(hPDev);
|
|
|
|
return Ret;
|
|
}
|
|
else
|
|
return Ret;
|
|
}
|
|
|
|
BOOL
|
|
APIENTRY
|
|
NtGdiSetDeviceGammaRamp(HDC hDC,
|
|
LPVOID Ramp)
|
|
{
|
|
BOOL Ret;
|
|
PDC dc;
|
|
NTSTATUS Status = STATUS_SUCCESS;
|
|
PGAMMARAMP SafeRamp;
|
|
if (!Ramp) return FALSE;
|
|
|
|
dc = DC_LockDc(hDC);
|
|
if (!dc)
|
|
{
|
|
SetLastWin32Error(ERROR_INVALID_HANDLE);
|
|
return FALSE;
|
|
}
|
|
|
|
SafeRamp = ExAllocatePool(PagedPool, sizeof(GAMMARAMP));
|
|
if (!SafeRamp)
|
|
{
|
|
DC_UnlockDc(dc);
|
|
SetLastWin32Error(STATUS_NO_MEMORY);
|
|
return FALSE;
|
|
}
|
|
_SEH2_TRY
|
|
{
|
|
ProbeForRead( Ramp,
|
|
sizeof(PVOID),
|
|
1);
|
|
RtlCopyMemory( SafeRamp,
|
|
Ramp,
|
|
sizeof(GAMMARAMP));
|
|
}
|
|
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
|
|
{
|
|
Status = _SEH2_GetExceptionCode();
|
|
}
|
|
_SEH2_END;
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
DC_UnlockDc(dc);
|
|
ExFreePool(SafeRamp);
|
|
SetLastNtError(Status);
|
|
return FALSE;
|
|
}
|
|
|
|
Ret = IntSetDeviceGammaRamp((HDEV)dc->ppdev, SafeRamp, TRUE);
|
|
DC_UnlockDc(dc);
|
|
ExFreePool(SafeRamp);
|
|
return Ret;
|
|
}
|
|
|
|
INT
|
|
APIENTRY
|
|
NtGdiSetIcmMode(HDC hDC,
|
|
ULONG nCommand,
|
|
ULONG EnableICM) // ulMode
|
|
{
|
|
/* FIXME: this should be coded someday */
|
|
if (EnableICM == ICM_OFF)
|
|
{
|
|
return ICM_OFF;
|
|
}
|
|
if (EnableICM == ICM_ON)
|
|
{
|
|
return 0;
|
|
}
|
|
if (EnableICM == ICM_QUERY)
|
|
{
|
|
return ICM_OFF;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
/* EOF */
|