2 * ReactOS W32 Subsystem
3 * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 ReactOS Team
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License along
16 * with this program; if not, write to the Free Software Foundation, Inc.,
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
25 HCOLORSPACE hStockColorSpace
= NULL
;
30 IntGdiCreateColorSpace(
31 PLOGCOLORSPACEEXW pLogColorSpace
)
36 pCS
= COLORSPACEOBJ_AllocCSWithHandle();
37 hCS
= pCS
->BaseObject
.hHmgr
;
39 pCS
->lcsColorSpace
= pLogColorSpace
->lcsColorSpace
;
40 pCS
->dwFlags
= pLogColorSpace
->dwFlags
;
42 COLORSPACEOBJ_UnlockCS(pCS
);
48 IntGdiDeleteColorSpace(
49 HCOLORSPACE hColorSpace
)
53 if ( hColorSpace
!= hStockColorSpace
)
55 Ret
= COLORSPACEOBJ_FreeCSByHandle(hColorSpace
);
56 if ( !Ret
) SetLastWin32Error(ERROR_INVALID_PARAMETER
);
63 NtGdiCreateColorSpace(
64 IN PLOGCOLORSPACEEXW pLogColorSpace
)
66 LOGCOLORSPACEEXW Safelcs
;
67 NTSTATUS Status
= STATUS_SUCCESS
;
71 ProbeForRead( pLogColorSpace
,
72 sizeof(LOGCOLORSPACEEXW
),
74 RtlCopyMemory(&Safelcs
, pLogColorSpace
, sizeof(LOGCOLORSPACEEXW
));
76 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
78 Status
= _SEH2_GetExceptionCode();
82 if (!NT_SUCCESS(Status
))
84 SetLastNtError(Status
);
87 return IntGdiCreateColorSpace(&Safelcs
);
92 NtGdiDeleteColorSpace(
93 IN HANDLE hColorSpace
)
95 return IntGdiDeleteColorSpace(hColorSpace
);
100 IntGetDeviceGammaRamp(HDEV hPDev
, PGAMMARAMP Ramp
)
102 PPDEVOBJ pGDev
= (PPDEVOBJ
) hPDev
;
105 if (!(pGDev
->flFlags
& PDEV_DISPLAY
)) return FALSE
;
107 if ((pGDev
->devinfo
.iDitherFormat
== BMF_8BPP
) ||
108 (pGDev
->devinfo
.iDitherFormat
== BMF_16BPP
) ||
109 (pGDev
->devinfo
.iDitherFormat
== BMF_24BPP
) ||
110 (pGDev
->devinfo
.iDitherFormat
== BMF_32BPP
))
112 if (pGDev
->flFlags
& PDEV_GAMMARAMP_TABLE
)
117 // Generate the 256-colors array
118 for(i
=0; i
<256; i
++ )
120 int NewValue
= i
* 256;
122 Ramp
->Red
[i
] = Ramp
->Green
[i
] = Ramp
->Blue
[i
] = ((WORD
)NewValue
);
132 NtGdiGetDeviceGammaRamp(HDC hDC
,
137 NTSTATUS Status
= STATUS_SUCCESS
;
140 if (!Ramp
) return FALSE
;
145 SetLastWin32Error(ERROR_INVALID_HANDLE
);
149 SafeRamp
= ExAllocatePoolWithTag(PagedPool
, sizeof(GAMMARAMP
), TAG_GDIICM
);
153 SetLastWin32Error(STATUS_NO_MEMORY
);
157 Ret
= IntGetDeviceGammaRamp((HDEV
)dc
->ppdev
, SafeRamp
);
159 if (!Ret
) return Ret
;
170 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
172 Status
= _SEH2_GetExceptionCode();
177 ExFreePoolWithTag(SafeRamp
, TAG_GDIICM
);
179 if (!NT_SUCCESS(Status
))
181 SetLastNtError(Status
);
189 NtGdiSetColorSpace(IN HDC hdc
,
190 IN HCOLORSPACE hColorSpace
)
196 pDC
= DC_LockDc(hdc
);
199 SetLastWin32Error(ERROR_INVALID_HANDLE
);
202 pdcattr
= pDC
->pdcattr
;
204 if (pdcattr
->hColorSpace
== hColorSpace
)
210 pCS
= COLORSPACEOBJ_LockCS(hColorSpace
);
213 SetLastWin32Error(ERROR_INVALID_HANDLE
);
217 if (pDC
->dclevel
.pColorSpace
)
219 GDIOBJ_ShareUnlockObjByPtr((POBJ
) pDC
->dclevel
.pColorSpace
);
222 pDC
->dclevel
.pColorSpace
= pCS
;
223 pdcattr
->hColorSpace
= hColorSpace
;
225 COLORSPACEOBJ_UnlockCS(pCS
);
232 UpdateDeviceGammaRamp( HDEV hPDev
)
237 PPDEVOBJ pGDev
= (PPDEVOBJ
) hPDev
;
239 if ((pGDev
->devinfo
.iDitherFormat
== BMF_8BPP
) ||
240 (pGDev
->devinfo
.iDitherFormat
== BMF_16BPP
) ||
241 (pGDev
->devinfo
.iDitherFormat
== BMF_24BPP
) ||
242 (pGDev
->devinfo
.iDitherFormat
== BMF_32BPP
))
244 if (pGDev
->DriverFunctions
.IcmSetDeviceGammaRamp
)
245 return pGDev
->DriverFunctions
.IcmSetDeviceGammaRamp( pGDev
->dhpdev
,
249 if ( (pGDev
->devinfo
.iDitherFormat
!= BMF_8BPP
) ||
250 !(pGDev
->gdiinfo
.flRaster
& RC_PALETTE
)) return FALSE
;
252 if (!(pGDev
->flFlags
& PDEV_GAMMARAMP_TABLE
)) return FALSE
;
254 palGDI
= PALETTE_LockPalette(pGDev
->devinfo
.hpalDefault
);
255 if(!palGDI
) return FALSE
;
256 palPtr
= (PALOBJ
*) palGDI
;
258 if (pGDev
->flFlags
& PDEV_GAMMARAMP_TABLE
)
259 palGDI
->Mode
|= PAL_GAMMACORRECTION
;
261 palGDI
->Mode
&= ~PAL_GAMMACORRECTION
;
263 if (!(pGDev
->flFlags
& PDEV_DRIVER_PUNTED_CALL
)) // No punting, we hook
266 // PALOBJ_cGetColors check mode flags and update Gamma Correction.
267 // Set the HDEV to pal and go.
268 palGDI
->hPDev
= hPDev
;
269 Ret
= pGDev
->DriverFunctions
.SetPalette(pGDev
->dhpdev
,
275 PALETTE_UnlockPalette(palGDI
);
283 // ICM registry subkey sets internal brightness range, gamma range is 128 or
284 // 256 when icm is init.
285 INT IcmGammaRangeSet
= 128; // <- make it global
289 IntSetDeviceGammaRamp(HDEV hPDev
, PGAMMARAMP Ramp
, BOOL Test
)
291 WORD IcmGR
, i
, R
, G
, B
;
292 BOOL Ret
= FALSE
, TstPeak
;
293 PPDEVOBJ pGDev
= (PPDEVOBJ
) hPDev
;
295 if (!hPDev
) return FALSE
;
297 if (!(pGDev
->flFlags
& PDEV_DISPLAY
)) return FALSE
;
299 if ((pGDev
->devinfo
.iDitherFormat
== BMF_8BPP
) ||
300 (pGDev
->devinfo
.iDitherFormat
== BMF_16BPP
) ||
301 (pGDev
->devinfo
.iDitherFormat
== BMF_24BPP
) ||
302 (pGDev
->devinfo
.iDitherFormat
== BMF_32BPP
))
304 if (!pGDev
->DriverFunctions
.IcmSetDeviceGammaRamp
)
305 { // No driver support
306 if (!(pGDev
->devinfo
.flGraphicsCaps2
& GCAPS2_CHANGEGAMMARAMP
))
307 { // Driver does not support Gamma Ramp, so test to see we
308 // have BMF_8BPP only and palette operation support.
309 if ((pGDev
->devinfo
.iDitherFormat
!= BMF_8BPP
) ||
310 !(pGDev
->gdiinfo
.flRaster
& RC_PALETTE
)) return FALSE
;
314 if (pGDev
->flFlags
& PDEV_GAMMARAMP_TABLE
)
315 if (RtlCompareMemory( pGDev
->pvGammaRamp
, Ramp
, sizeof(GAMMARAMP
)) ==
316 sizeof(GAMMARAMP
)) return TRUE
;
317 // Verify Ramp is inside range.
318 IcmGR
= -IcmGammaRangeSet
;
319 TstPeak
= (Test
== FALSE
);
320 for (i
= 0; i
< 256; i
++)
322 R
= Ramp
->Red
[i
] / 256;
323 G
= Ramp
->Green
[i
] / 256;
324 B
= Ramp
->Blue
[i
] / 256;
327 if ( R
<= IcmGammaRangeSet
+ i
)
330 (G
<= IcmGammaRangeSet
+ i
) &&
332 (B
<= IcmGammaRangeSet
+ i
) ) continue;
335 if (Test
) return Ret
; // Don't set and return.
336 // No test override, check max range
339 if ( R
!= (IcmGR
* 256) ||
340 G
!= (IcmGR
* 256) ||
341 B
!= (IcmGR
* 256) ) TstPeak
= FALSE
; // W/i range.
344 // ReactOS allocates a ramp even if it is 8BPP and Palette only.
345 // This way we have a record of the change in memory.
346 if (!pGDev
->pvGammaRamp
&& !(pGDev
->flFlags
& PDEV_GAMMARAMP_TABLE
))
347 { // If the above is true and we have nothing allocated, create it.
348 pGDev
->pvGammaRamp
= ExAllocatePoolWithTag(PagedPool
, sizeof(GAMMARAMP
), TAG_GDIICM
);
349 pGDev
->flFlags
|= PDEV_GAMMARAMP_TABLE
;
351 if (pGDev
->pvGammaRamp
)
352 RtlCopyMemory( pGDev
->pvGammaRamp
, Ramp
, sizeof(GAMMARAMP
));
354 Ret
= UpdateDeviceGammaRamp(hPDev
);
364 NtGdiSetDeviceGammaRamp(HDC hDC
,
369 NTSTATUS Status
= STATUS_SUCCESS
;
371 if (!Ramp
) return FALSE
;
376 SetLastWin32Error(ERROR_INVALID_HANDLE
);
380 SafeRamp
= ExAllocatePoolWithTag(PagedPool
, sizeof(GAMMARAMP
), TAG_GDIICM
);
384 SetLastWin32Error(STATUS_NO_MEMORY
);
392 RtlCopyMemory( SafeRamp
,
396 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
398 Status
= _SEH2_GetExceptionCode();
402 if (!NT_SUCCESS(Status
))
405 ExFreePoolWithTag(SafeRamp
, TAG_GDIICM
);
406 SetLastNtError(Status
);
410 Ret
= IntSetDeviceGammaRamp((HDEV
)dc
->ppdev
, SafeRamp
, TRUE
);
412 ExFreePoolWithTag(SafeRamp
, TAG_GDIICM
);
418 NtGdiSetIcmMode(HDC hDC
,
420 ULONG EnableICM
) // ulMode
422 /* FIXME: this should be coded someday */
423 if (EnableICM
== ICM_OFF
)
427 if (EnableICM
== ICM_ON
)
431 if (EnableICM
== ICM_QUERY
)