2003-05-18 17:16:18 +00:00
|
|
|
/*
|
2003-06-06 10:17:44 +00:00
|
|
|
* ReactOS W32 Subsystem
|
|
|
|
* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 ReactOS Team
|
2003-05-18 17:16:18 +00:00
|
|
|
*
|
2003-06-06 10:17:44 +00:00
|
|
|
* 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.
|
2003-05-18 17:16:18 +00:00
|
|
|
*
|
2003-06-06 10:17:44 +00:00
|
|
|
* 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.
|
|
|
|
*
|
2009-10-27 10:34:16 +00:00
|
|
|
* 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.
|
2003-05-18 17:16:18 +00:00
|
|
|
*/
|
2005-06-29 07:09:25 +00:00
|
|
|
|
2010-04-26 13:58:46 +00:00
|
|
|
#include <win32k.h>
|
2005-06-29 07:09:25 +00:00
|
|
|
|
|
|
|
#define NDEBUG
|
|
|
|
#include <debug.h>
|
2003-03-06 00:56:59 +00:00
|
|
|
|
2011-02-28 23:46:02 +00:00
|
|
|
static const RGBQUAD EGAColorsQuads[16] =
|
|
|
|
{
|
|
|
|
/* rgbBlue, rgbGreen, rgbRed, rgbReserved */
|
2008-12-01 00:13:45 +00:00
|
|
|
{ 0x00, 0x00, 0x00, 0x00 },
|
|
|
|
{ 0x00, 0x00, 0x80, 0x00 },
|
|
|
|
{ 0x00, 0x80, 0x00, 0x00 },
|
|
|
|
{ 0x00, 0x80, 0x80, 0x00 },
|
|
|
|
{ 0x80, 0x00, 0x00, 0x00 },
|
|
|
|
{ 0x80, 0x00, 0x80, 0x00 },
|
|
|
|
{ 0x80, 0x80, 0x00, 0x00 },
|
|
|
|
{ 0x80, 0x80, 0x80, 0x00 },
|
|
|
|
{ 0xc0, 0xc0, 0xc0, 0x00 },
|
|
|
|
{ 0x00, 0x00, 0xff, 0x00 },
|
|
|
|
{ 0x00, 0xff, 0x00, 0x00 },
|
|
|
|
{ 0x00, 0xff, 0xff, 0x00 },
|
|
|
|
{ 0xff, 0x00, 0x00, 0x00 },
|
|
|
|
{ 0xff, 0x00, 0xff, 0x00 },
|
|
|
|
{ 0xff, 0xff, 0x00, 0x00 },
|
|
|
|
{ 0xff, 0xff, 0xff, 0x00 }
|
|
|
|
};
|
|
|
|
|
2011-02-28 23:46:02 +00:00
|
|
|
static const RGBTRIPLE EGAColorsTriples[16] =
|
|
|
|
{
|
|
|
|
/* rgbBlue, rgbGreen, rgbRed */
|
2010-07-29 16:12:43 +00:00
|
|
|
{ 0x00, 0x00, 0x00 },
|
|
|
|
{ 0x00, 0x00, 0x80 },
|
|
|
|
{ 0x00, 0x80, 0x00 },
|
|
|
|
{ 0x00, 0x80, 0x80 },
|
|
|
|
{ 0x80, 0x00, 0x00 },
|
|
|
|
{ 0x80, 0x00, 0x80 },
|
|
|
|
{ 0x80, 0x80, 0x00 },
|
|
|
|
{ 0x80, 0x80, 0x80 },
|
|
|
|
{ 0xc0, 0xc0, 0xc0 },
|
|
|
|
{ 0x00, 0x00, 0xff },
|
|
|
|
{ 0x00, 0xff, 0x00 },
|
|
|
|
{ 0x00, 0xff, 0xff },
|
|
|
|
{ 0xff, 0x00, 0x00 },
|
|
|
|
{ 0xff, 0x00, 0xff },
|
|
|
|
{ 0xff, 0xff, 0x00 },
|
|
|
|
{ 0xff, 0xff, 0xff }
|
|
|
|
};
|
|
|
|
|
2011-02-28 23:46:02 +00:00
|
|
|
static const RGBQUAD DefLogPaletteQuads[20] = /* Copy of Default Logical Palette */
|
|
|
|
{
|
|
|
|
/* rgbBlue, rgbGreen, rgbRed, rgbReserved */
|
2008-12-01 00:13:45 +00:00
|
|
|
{ 0x00, 0x00, 0x00, 0x00 },
|
|
|
|
{ 0x00, 0x00, 0x80, 0x00 },
|
|
|
|
{ 0x00, 0x80, 0x00, 0x00 },
|
|
|
|
{ 0x00, 0x80, 0x80, 0x00 },
|
|
|
|
{ 0x80, 0x00, 0x00, 0x00 },
|
|
|
|
{ 0x80, 0x00, 0x80, 0x00 },
|
|
|
|
{ 0x80, 0x80, 0x00, 0x00 },
|
|
|
|
{ 0xc0, 0xc0, 0xc0, 0x00 },
|
|
|
|
{ 0xc0, 0xdc, 0xc0, 0x00 },
|
|
|
|
{ 0xf0, 0xca, 0xa6, 0x00 },
|
|
|
|
{ 0xf0, 0xfb, 0xff, 0x00 },
|
|
|
|
{ 0xa4, 0xa0, 0xa0, 0x00 },
|
|
|
|
{ 0x80, 0x80, 0x80, 0x00 },
|
|
|
|
{ 0x00, 0x00, 0xf0, 0x00 },
|
|
|
|
{ 0x00, 0xff, 0x00, 0x00 },
|
|
|
|
{ 0x00, 0xff, 0xff, 0x00 },
|
|
|
|
{ 0xff, 0x00, 0x00, 0x00 },
|
|
|
|
{ 0xff, 0x00, 0xff, 0x00 },
|
|
|
|
{ 0xff, 0xff, 0x00, 0x00 },
|
|
|
|
{ 0xff, 0xff, 0xff, 0x00 }
|
|
|
|
};
|
|
|
|
|
2011-02-28 23:46:02 +00:00
|
|
|
static const RGBQUAD DefLogPaletteTriples[20] = /* Copy of Default Logical Palette */
|
|
|
|
{
|
|
|
|
/* rgbBlue, rgbGreen, rgbRed, rgbReserved */
|
2010-07-29 16:12:43 +00:00
|
|
|
{ 0x00, 0x00, 0x00 },
|
|
|
|
{ 0x00, 0x00, 0x80 },
|
|
|
|
{ 0x00, 0x80, 0x00 },
|
|
|
|
{ 0x00, 0x80, 0x80 },
|
|
|
|
{ 0x80, 0x00, 0x00 },
|
|
|
|
{ 0x80, 0x00, 0x80 },
|
|
|
|
{ 0x80, 0x80, 0x00 },
|
|
|
|
{ 0xc0, 0xc0, 0xc0 },
|
|
|
|
{ 0xc0, 0xdc, 0xc0 },
|
|
|
|
{ 0xf0, 0xca, 0xa6 },
|
|
|
|
{ 0xf0, 0xfb, 0xff },
|
|
|
|
{ 0xa4, 0xa0, 0xa0 },
|
|
|
|
{ 0x80, 0x80, 0x80 },
|
|
|
|
{ 0x00, 0x00, 0xf0 },
|
|
|
|
{ 0x00, 0xff, 0x00 },
|
|
|
|
{ 0x00, 0xff, 0xff },
|
|
|
|
{ 0xff, 0x00, 0x00 },
|
|
|
|
{ 0xff, 0x00, 0xff },
|
|
|
|
{ 0xff, 0xff, 0x00 },
|
|
|
|
{ 0xff, 0xff, 0xff }
|
|
|
|
};
|
|
|
|
|
2008-12-01 00:13:45 +00:00
|
|
|
|
2009-06-10 00:23:15 +00:00
|
|
|
UINT
|
|
|
|
APIENTRY
|
|
|
|
IntSetDIBColorTable(
|
|
|
|
HDC hDC,
|
|
|
|
UINT StartIndex,
|
|
|
|
UINT Entries,
|
|
|
|
CONST RGBQUAD *Colors)
|
2001-03-31 15:35:08 +00:00
|
|
|
{
|
2009-06-10 00:23:15 +00:00
|
|
|
PDC dc;
|
|
|
|
PSURFACE psurf;
|
|
|
|
PPALETTE PalGDI;
|
|
|
|
UINT Index;
|
|
|
|
ULONG biBitCount;
|
|
|
|
|
|
|
|
if (!(dc = DC_LockDc(hDC))) return 0;
|
|
|
|
if (dc->dctype == DC_TYPE_INFO)
|
|
|
|
{
|
|
|
|
DC_UnlockDc(dc);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
psurf = dc->dclevel.pSurface;
|
|
|
|
if (psurf == NULL)
|
|
|
|
{
|
|
|
|
DC_UnlockDc(dc);
|
2010-12-25 11:01:14 +00:00
|
|
|
EngSetLastError(ERROR_INVALID_PARAMETER);
|
2009-06-10 00:23:15 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (psurf->hSecure == NULL)
|
|
|
|
{
|
|
|
|
DC_UnlockDc(dc);
|
2010-12-25 11:01:14 +00:00
|
|
|
EngSetLastError(ERROR_INVALID_PARAMETER);
|
2009-06-10 00:23:15 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
biBitCount = BitsPerFormat(psurf->SurfObj.iBitmapFormat);
|
|
|
|
if (biBitCount <= 8 && StartIndex < (1 << biBitCount))
|
|
|
|
{
|
|
|
|
if (StartIndex + Entries > (1 << biBitCount))
|
|
|
|
Entries = (1 << biBitCount) - StartIndex;
|
|
|
|
|
2010-05-12 22:56:24 +00:00
|
|
|
if (psurf->ppal == NULL)
|
2009-06-10 00:23:15 +00:00
|
|
|
{
|
|
|
|
DC_UnlockDc(dc);
|
2010-12-25 11:01:14 +00:00
|
|
|
EngSetLastError(ERROR_INVALID_HANDLE);
|
2009-06-10 00:23:15 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
[WIN32K]
Rewrite of the GDI handle manager
- The old handle manager used a completely retarded spinlock in combination with KeDelayExecutionThread() for both exclusive
and shared locks. This is probably the most uneffective algorithm possible. It was also duplicating code everywhere and it was a overall mess It
is now replaced with a lock-free reference counter for shared locks and a pushlock for exclusive locks. -> Better performance and scalability.
- Allocate user mode object attributes from the new gdi pool. This way, we don't need any caching, since the pool serves as a cache. Its also
much faster and uses much less memory.
- Allow object allocations of different size, instead of fixed size from a table. This way a single allocation can take care of actual needs.
- Allow allcoating objects without a handle and insert them into the handle table later
- Properly synchronize the process GDIHandleCount. Now gdiview and taskmanager show the correct number of gdi handles.
- Implement a new event tracking system, that is capable of tracking all reverences and locks of objects and pool allocations to help track
possible leaks
- Make sure that all objects of a process are deleted in cleanup
- Make sure all usermode memory allocations are freed, when cleaning up the process pool.
- Make sure that each object type is using the correct type of lock (either shared or exclusive, not a mixture)
- Fix some object / reference leaks
- Lots of inferface improvements
- Use global variables for certain things instead of members in the mapped gdi handle table
- Make IntSysCreateRectpRgn create a region without a handle
- Fix detection od source and mask use in GreStretchBltMask
- Use GDIOBJ_bLockMultipleObjects in NtGdiCombineRegion to avoid possible deadlocks
- Fix NtGdiAbortPath to reset DCPATH_ACTIVE flag in the dc and only bail out on error, instead of always
- Replace DC_AllocateDcAttr and DC_AllocDcAttr with DC_bAllocDcAttr using the new user mode pool
- Remove DCU_SyncDcAttrtoUser and DCU_SynchDcAttrtoUser. Those functions were unused and didn't do anything useful anyway,
- Replace IntGdiSetDCOwnerEx and DC_SetOwnership with GreSetDCOwner, remove unused NoSetBrush parameter
- Replace GDIOBJ_bValidateHandle and IsObjectDead with GreIsHandleValid
- Chage GDIOBJ_bLockMultipleObjects: pass object type, return a BOOL, whether all objects could be locked, cleanup on failure
svn path=/trunk/; revision=51470
2011-04-28 08:26:46 +00:00
|
|
|
PalGDI = psurf->ppal;
|
2010-05-12 22:56:24 +00:00
|
|
|
|
2009-06-10 00:23:15 +00:00
|
|
|
for (Index = StartIndex;
|
2011-02-28 23:46:02 +00:00
|
|
|
Index < StartIndex + Entries && Index < PalGDI->NumColors;
|
|
|
|
Index++)
|
2009-06-10 00:23:15 +00:00
|
|
|
{
|
|
|
|
PalGDI->IndexedColors[Index].peRed = Colors[Index - StartIndex].rgbRed;
|
|
|
|
PalGDI->IndexedColors[Index].peGreen = Colors[Index - StartIndex].rgbGreen;
|
|
|
|
PalGDI->IndexedColors[Index].peBlue = Colors[Index - StartIndex].rgbBlue;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
Entries = 0;
|
|
|
|
|
|
|
|
/* Mark the brushes invalid */
|
|
|
|
dc->pdcattr->ulDirty_ |= DIRTY_FILL|DIRTY_LINE|DIRTY_BACKGROUND|DIRTY_TEXT;
|
|
|
|
|
|
|
|
DC_UnlockDc(dc);
|
|
|
|
|
|
|
|
return Entries;
|
2004-05-15 08:52:25 +00:00
|
|
|
}
|
|
|
|
|
2009-06-10 00:23:15 +00:00
|
|
|
UINT
|
|
|
|
APIENTRY
|
|
|
|
IntGetDIBColorTable(
|
|
|
|
HDC hDC,
|
|
|
|
UINT StartIndex,
|
|
|
|
UINT Entries,
|
|
|
|
RGBQUAD *Colors)
|
2004-05-15 08:52:25 +00:00
|
|
|
{
|
2009-06-10 00:23:15 +00:00
|
|
|
PDC dc;
|
|
|
|
PSURFACE psurf;
|
2011-02-27 21:45:43 +00:00
|
|
|
PPALETTE ppal;
|
2009-12-25 17:54:41 +00:00
|
|
|
UINT Index, Count = 0;
|
2009-06-10 00:23:15 +00:00
|
|
|
|
|
|
|
if (!(dc = DC_LockDc(hDC))) return 0;
|
|
|
|
if (dc->dctype == DC_TYPE_INFO)
|
|
|
|
{
|
|
|
|
DC_UnlockDc(dc);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
psurf = dc->dclevel.pSurface;
|
|
|
|
if (psurf == NULL)
|
|
|
|
{
|
|
|
|
DC_UnlockDc(dc);
|
2010-12-25 11:01:14 +00:00
|
|
|
EngSetLastError(ERROR_INVALID_PARAMETER);
|
2009-06-10 00:23:15 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (psurf->hSecure == NULL)
|
|
|
|
{
|
|
|
|
DC_UnlockDc(dc);
|
2010-12-25 11:01:14 +00:00
|
|
|
EngSetLastError(ERROR_INVALID_PARAMETER);
|
2009-06-10 00:23:15 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2011-02-27 21:45:43 +00:00
|
|
|
ppal = psurf->ppal;
|
|
|
|
ASSERT(ppal);
|
2009-06-10 00:23:15 +00:00
|
|
|
|
2011-02-27 21:45:43 +00:00
|
|
|
if (ppal->flFlags & PAL_INDEXED)
|
|
|
|
{
|
2010-05-12 22:56:24 +00:00
|
|
|
|
2009-06-10 00:23:15 +00:00
|
|
|
for (Index = StartIndex;
|
2011-02-28 23:46:02 +00:00
|
|
|
Index < StartIndex + Entries && Index < ppal->NumColors;
|
|
|
|
Index++)
|
2009-06-10 00:23:15 +00:00
|
|
|
{
|
2011-02-27 21:45:43 +00:00
|
|
|
Colors[Index - StartIndex].rgbRed = ppal->IndexedColors[Index].peRed;
|
|
|
|
Colors[Index - StartIndex].rgbGreen = ppal->IndexedColors[Index].peGreen;
|
|
|
|
Colors[Index - StartIndex].rgbBlue = ppal->IndexedColors[Index].peBlue;
|
2009-06-10 00:23:15 +00:00
|
|
|
Colors[Index - StartIndex].rgbReserved = 0;
|
2009-12-25 17:54:41 +00:00
|
|
|
Count++;
|
2009-06-10 00:23:15 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
DC_UnlockDc(dc);
|
|
|
|
|
2009-12-25 17:54:41 +00:00
|
|
|
return Count;
|
2001-03-31 15:35:08 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Converts a DIB to a device-dependent bitmap
|
2009-06-10 00:23:15 +00:00
|
|
|
static INT
|
|
|
|
FASTCALL
|
2004-03-15 22:06:55 +00:00
|
|
|
IntSetDIBits(
|
2009-06-10 00:23:15 +00:00
|
|
|
PDC DC,
|
|
|
|
HBITMAP hBitmap,
|
|
|
|
UINT StartScan,
|
|
|
|
UINT ScanLines,
|
|
|
|
CONST VOID *Bits,
|
2010-08-01 12:17:35 +00:00
|
|
|
CONST BITMAPINFO *bmi,
|
2009-06-10 00:23:15 +00:00
|
|
|
UINT ColorUse)
|
2001-03-31 15:35:08 +00:00
|
|
|
{
|
2010-08-02 19:40:42 +00:00
|
|
|
HBITMAP SourceBitmap;
|
2011-02-28 23:46:02 +00:00
|
|
|
PSURFACE psurfDst, psurfSrc;
|
2009-06-10 00:23:15 +00:00
|
|
|
INT result = 0;
|
2011-02-28 23:46:02 +00:00
|
|
|
RECT rcDst;
|
|
|
|
POINTL ptSrc;
|
|
|
|
PVOID pvBits;
|
|
|
|
EXLATEOBJ exlo;
|
2009-06-10 00:23:15 +00:00
|
|
|
|
2010-08-01 12:17:35 +00:00
|
|
|
SourceBitmap = DIB_CreateDIBSection(DC, bmi, ColorUse, &pvBits, NULL, 0, 0);
|
2011-02-28 23:46:02 +00:00
|
|
|
if (0 == SourceBitmap)
|
2009-06-10 00:23:15 +00:00
|
|
|
{
|
2011-02-28 23:46:02 +00:00
|
|
|
DPRINT1("Error : Could not create a DIBSection.\n");
|
2010-12-25 11:01:14 +00:00
|
|
|
EngSetLastError(ERROR_NO_SYSTEM_RESOURCES);
|
2009-06-10 00:23:15 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2011-02-28 23:46:02 +00:00
|
|
|
RtlCopyMemory(pvBits, Bits, DIB_GetDIBImageBytes(bmi->bmiHeader.biWidth,
|
|
|
|
bmi->bmiHeader.biHeight,
|
|
|
|
bmi->bmiHeader.biBitCount));
|
2009-06-10 00:23:15 +00:00
|
|
|
|
2011-04-18 19:09:05 +00:00
|
|
|
psurfDst = SURFACE_ShareLockSurface(hBitmap);
|
|
|
|
psurfSrc = SURFACE_ShareLockSurface(SourceBitmap);
|
2009-06-10 00:23:15 +00:00
|
|
|
|
2011-02-28 23:46:02 +00:00
|
|
|
if(!(psurfSrc && psurfDst))
|
|
|
|
{
|
|
|
|
DPRINT1("Error, could not lock surfaces\n");
|
|
|
|
goto cleanup;
|
|
|
|
}
|
2009-06-10 00:23:15 +00:00
|
|
|
|
2011-03-09 15:46:13 +00:00
|
|
|
rcDst.top = StartScan;
|
2011-02-28 23:46:02 +00:00
|
|
|
rcDst.left = 0;
|
|
|
|
rcDst.bottom = rcDst.top + ScanLines;
|
|
|
|
rcDst.right = psurfDst->SurfObj.sizlBitmap.cx;
|
2009-06-10 00:23:15 +00:00
|
|
|
|
2011-02-28 23:46:02 +00:00
|
|
|
ptSrc.x = 0;
|
|
|
|
ptSrc.y = 0;
|
2002-09-17 23:20:44 +00:00
|
|
|
|
2011-03-02 00:15:57 +00:00
|
|
|
/* 1bpp bitmaps have 0 for white, 1 for black */
|
2011-03-09 15:46:13 +00:00
|
|
|
EXLATEOBJ_vInitialize(&exlo, psurfSrc->ppal, psurfDst->ppal, 0xFFFFFF, 0xFFFFFF, 0);
|
2001-03-31 15:35:08 +00:00
|
|
|
|
2011-02-28 23:46:02 +00:00
|
|
|
result = IntEngCopyBits(&psurfDst->SurfObj,
|
|
|
|
&psurfSrc->SurfObj,
|
|
|
|
NULL,
|
|
|
|
&exlo.xlo,
|
|
|
|
&rcDst,
|
|
|
|
&ptSrc);
|
|
|
|
if(result)
|
|
|
|
result = ScanLines;
|
2001-03-31 15:35:08 +00:00
|
|
|
|
2011-02-28 23:46:02 +00:00
|
|
|
EXLATEOBJ_vCleanup(&exlo);
|
2010-08-02 19:40:42 +00:00
|
|
|
|
2010-08-01 12:17:35 +00:00
|
|
|
cleanup:
|
2011-02-28 23:46:02 +00:00
|
|
|
if(psurfSrc)
|
|
|
|
{
|
2011-04-18 19:09:05 +00:00
|
|
|
SURFACE_ShareUnlockSurface(psurfSrc);
|
2011-02-28 23:46:02 +00:00
|
|
|
}
|
|
|
|
if(psurfDst)
|
|
|
|
{
|
2011-04-18 19:09:05 +00:00
|
|
|
SURFACE_ShareUnlockSurface(psurfDst);
|
2011-02-28 23:46:02 +00:00
|
|
|
}
|
|
|
|
GreDeleteObject(SourceBitmap);
|
2001-03-31 15:35:08 +00:00
|
|
|
|
2009-06-10 00:23:15 +00:00
|
|
|
return result;
|
2001-03-31 15:35:08 +00:00
|
|
|
}
|
|
|
|
|
2007-08-19 23:49:47 +00:00
|
|
|
W32KAPI
|
|
|
|
INT
|
|
|
|
APIENTRY
|
|
|
|
NtGdiSetDIBitsToDeviceInternal(
|
|
|
|
IN HDC hDC,
|
|
|
|
IN INT XDest,
|
|
|
|
IN INT YDest,
|
|
|
|
IN DWORD Width,
|
|
|
|
IN DWORD Height,
|
|
|
|
IN INT XSrc,
|
|
|
|
IN INT YSrc,
|
|
|
|
IN DWORD StartScan,
|
|
|
|
IN DWORD ScanLines,
|
|
|
|
IN LPBYTE Bits,
|
|
|
|
IN LPBITMAPINFO bmi,
|
|
|
|
IN DWORD ColorUse,
|
|
|
|
IN UINT cjMaxBits,
|
|
|
|
IN UINT cjMaxInfo,
|
|
|
|
IN BOOL bTransformCoordinates,
|
2009-06-10 00:23:15 +00:00
|
|
|
IN OPTIONAL HANDLE hcmXform)
|
2001-03-31 15:35:08 +00:00
|
|
|
{
|
2007-09-27 17:04:29 +00:00
|
|
|
INT ret = 0;
|
|
|
|
NTSTATUS Status = STATUS_SUCCESS;
|
|
|
|
PDC pDC;
|
2008-04-19 00:24:34 +00:00
|
|
|
HBITMAP hSourceBitmap = NULL;
|
|
|
|
SURFOBJ *pDestSurf, *pSourceSurf = NULL;
|
2009-04-02 17:25:56 +00:00
|
|
|
SURFACE *pSurf;
|
2007-09-27 17:04:29 +00:00
|
|
|
RECTL rcDest;
|
|
|
|
POINTL ptSource;
|
2011-09-11 16:56:56 +00:00
|
|
|
//INT DIBWidth;
|
2007-09-27 17:04:29 +00:00
|
|
|
SIZEL SourceSize;
|
2009-08-04 20:37:10 +00:00
|
|
|
EXLATEOBJ exlo;
|
2010-06-08 00:40:42 +00:00
|
|
|
PPALETTE ppalDIB = NULL;
|
2010-05-08 22:10:41 +00:00
|
|
|
HPALETTE hpalDIB = NULL;
|
2007-09-27 17:04:29 +00:00
|
|
|
|
2007-12-08 18:32:22 +00:00
|
|
|
if (!Bits) return 0;
|
|
|
|
|
2008-12-01 00:13:45 +00:00
|
|
|
_SEH2_TRY
|
|
|
|
{
|
2010-08-01 12:17:35 +00:00
|
|
|
ProbeForRead(bmi, cjMaxInfo, 1);
|
2010-06-09 00:08:50 +00:00
|
|
|
ProbeForRead(Bits, cjMaxBits, 1);
|
2008-12-01 00:13:45 +00:00
|
|
|
}
|
|
|
|
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
|
|
|
|
{
|
2009-06-10 00:23:15 +00:00
|
|
|
Status = _SEH2_GetExceptionCode();
|
2008-12-01 00:13:45 +00:00
|
|
|
}
|
|
|
|
_SEH2_END
|
|
|
|
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
{
|
2009-06-10 00:23:15 +00:00
|
|
|
return 0;
|
2008-12-01 00:13:45 +00:00
|
|
|
}
|
|
|
|
|
2007-09-27 17:04:29 +00:00
|
|
|
pDC = DC_LockDc(hDC);
|
|
|
|
if (!pDC)
|
|
|
|
{
|
2010-12-25 11:01:14 +00:00
|
|
|
EngSetLastError(ERROR_INVALID_HANDLE);
|
2007-09-27 17:04:29 +00:00
|
|
|
return 0;
|
|
|
|
}
|
2009-03-20 01:35:49 +00:00
|
|
|
if (pDC->dctype == DC_TYPE_INFO)
|
2007-09-27 17:04:29 +00:00
|
|
|
{
|
|
|
|
DC_UnlockDc(pDC);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2009-04-14 20:50:02 +00:00
|
|
|
pSurf = pDC->dclevel.pSurface;
|
2007-09-27 17:04:29 +00:00
|
|
|
|
2009-04-14 20:50:02 +00:00
|
|
|
pDestSurf = pSurf ? &pSurf->SurfObj : NULL;
|
2009-04-02 17:25:56 +00:00
|
|
|
|
2010-08-01 12:17:35 +00:00
|
|
|
ScanLines = min(ScanLines, abs(bmi->bmiHeader.biHeight) - StartScan);
|
2009-12-23 17:41:20 +00:00
|
|
|
|
2007-09-27 17:04:29 +00:00
|
|
|
rcDest.left = XDest;
|
|
|
|
rcDest.top = YDest;
|
2008-06-05 22:23:19 +00:00
|
|
|
if (bTransformCoordinates)
|
|
|
|
{
|
2011-03-07 10:00:27 +00:00
|
|
|
IntLPtoDP(pDC, (LPPOINT)&rcDest, 2);
|
2008-06-05 22:23:19 +00:00
|
|
|
}
|
|
|
|
rcDest.left += pDC->ptlDCOrig.x;
|
|
|
|
rcDest.top += pDC->ptlDCOrig.y;
|
|
|
|
rcDest.right = rcDest.left + Width;
|
|
|
|
rcDest.bottom = rcDest.top + Height;
|
2009-12-23 17:41:20 +00:00
|
|
|
rcDest.top += StartScan;
|
|
|
|
|
2007-09-27 17:04:29 +00:00
|
|
|
ptSource.x = XSrc;
|
|
|
|
ptSource.y = YSrc;
|
|
|
|
|
2010-08-01 12:17:35 +00:00
|
|
|
SourceSize.cx = bmi->bmiHeader.biWidth;
|
2009-12-23 17:41:20 +00:00
|
|
|
SourceSize.cy = ScanLines;
|
|
|
|
|
2011-09-11 16:56:56 +00:00
|
|
|
//DIBWidth = WIDTH_BYTES_ALIGN32(SourceSize.cx, bmi->bmiHeader.biBitCount);
|
2008-05-06 20:44:25 +00:00
|
|
|
|
2011-03-07 10:00:27 +00:00
|
|
|
hSourceBitmap = GreCreateBitmapEx(bmi->bmiHeader.biWidth,
|
|
|
|
ScanLines,
|
|
|
|
0,
|
|
|
|
BitmapFormat(bmi->bmiHeader.biBitCount,
|
|
|
|
bmi->bmiHeader.biCompression),
|
|
|
|
bmi->bmiHeader.biHeight < 0 ? BMF_TOPDOWN : 0,
|
|
|
|
bmi->bmiHeader.biSizeImage,
|
|
|
|
Bits,
|
|
|
|
0);
|
|
|
|
|
2008-12-01 00:13:45 +00:00
|
|
|
if (!hSourceBitmap)
|
|
|
|
{
|
2010-12-25 11:01:14 +00:00
|
|
|
EngSetLastError(ERROR_NO_SYSTEM_RESOURCES);
|
2008-12-01 00:13:45 +00:00
|
|
|
Status = STATUS_NO_MEMORY;
|
|
|
|
goto Exit;
|
|
|
|
}
|
2008-05-06 20:44:25 +00:00
|
|
|
|
2008-12-01 00:13:45 +00:00
|
|
|
pSourceSurf = EngLockSurface((HSURF)hSourceBitmap);
|
|
|
|
if (!pSourceSurf)
|
|
|
|
{
|
2009-06-10 00:23:15 +00:00
|
|
|
Status = STATUS_UNSUCCESSFUL;
|
|
|
|
goto Exit;
|
2008-12-01 00:13:45 +00:00
|
|
|
}
|
2008-04-19 00:24:34 +00:00
|
|
|
|
2010-06-08 00:40:42 +00:00
|
|
|
ASSERT(pSurf->ppal);
|
2007-09-27 17:04:29 +00:00
|
|
|
|
2009-10-30 14:02:42 +00:00
|
|
|
/* Create a palette for the DIB */
|
2010-08-01 12:17:35 +00:00
|
|
|
hpalDIB = BuildDIBPalette(bmi);
|
2009-10-30 14:02:42 +00:00
|
|
|
if (!hpalDIB)
|
2008-12-01 00:13:45 +00:00
|
|
|
{
|
2010-12-25 11:01:14 +00:00
|
|
|
EngSetLastError(ERROR_NO_SYSTEM_RESOURCES);
|
2009-06-10 00:23:15 +00:00
|
|
|
Status = STATUS_NO_MEMORY;
|
|
|
|
goto Exit;
|
2007-09-27 17:04:29 +00:00
|
|
|
}
|
2008-12-01 00:13:45 +00:00
|
|
|
|
2009-10-30 14:02:42 +00:00
|
|
|
/* Lock the DIB palette */
|
2011-04-15 15:29:08 +00:00
|
|
|
ppalDIB = PALETTE_ShareLockPalette(hpalDIB);
|
2010-05-08 22:10:41 +00:00
|
|
|
if (!ppalDIB)
|
2009-10-30 14:02:42 +00:00
|
|
|
{
|
2010-12-25 11:01:14 +00:00
|
|
|
EngSetLastError(ERROR_INVALID_HANDLE);
|
2009-10-30 14:02:42 +00:00
|
|
|
Status = STATUS_UNSUCCESSFUL;
|
|
|
|
goto Exit;
|
|
|
|
}
|
|
|
|
|
2009-08-04 20:37:10 +00:00
|
|
|
/* Initialize EXLATEOBJ */
|
2011-03-07 10:00:27 +00:00
|
|
|
EXLATEOBJ_vInitialize(&exlo,
|
|
|
|
ppalDIB,
|
|
|
|
pSurf->ppal,
|
|
|
|
RGB(0xff, 0xff, 0xff),
|
|
|
|
pDC->pdcattr->crBackgroundClr,
|
|
|
|
pDC->pdcattr->crForegroundClr);
|
2007-09-27 17:04:29 +00:00
|
|
|
|
2008-12-01 00:13:45 +00:00
|
|
|
/* Copy the bits */
|
2010-05-08 22:10:41 +00:00
|
|
|
DPRINT("BitsToDev with dstsurf=(%d|%d) (%d|%d), src=(%d|%d) w=%d h=%d\n",
|
2011-02-28 23:46:02 +00:00
|
|
|
rcDest.left, rcDest.top, rcDest.right, rcDest.bottom,
|
|
|
|
ptSource.x, ptSource.y, SourceSize.cx, SourceSize.cy);
|
2008-12-01 00:13:45 +00:00
|
|
|
Status = IntEngBitBlt(pDestSurf,
|
|
|
|
pSourceSurf,
|
|
|
|
NULL,
|
2009-03-20 01:35:49 +00:00
|
|
|
pDC->rosdc.CombinedClip,
|
2009-08-04 20:37:10 +00:00
|
|
|
&exlo.xlo,
|
2008-12-01 00:13:45 +00:00
|
|
|
&rcDest,
|
|
|
|
&ptSource,
|
|
|
|
NULL,
|
|
|
|
NULL,
|
|
|
|
NULL,
|
2011-03-01 01:03:58 +00:00
|
|
|
ROP4_FROM_INDEX(R3_OPINDEX_SRCCOPY));
|
2009-08-04 20:37:10 +00:00
|
|
|
|
|
|
|
/* Cleanup EXLATEOBJ */
|
|
|
|
EXLATEOBJ_vCleanup(&exlo);
|
|
|
|
|
2008-12-01 00:13:45 +00:00
|
|
|
Exit:
|
2007-09-27 17:04:29 +00:00
|
|
|
if (NT_SUCCESS(Status))
|
|
|
|
{
|
2009-12-23 17:41:20 +00:00
|
|
|
ret = ScanLines;
|
2007-09-27 17:04:29 +00:00
|
|
|
}
|
|
|
|
|
2011-04-15 15:29:08 +00:00
|
|
|
if (ppalDIB) PALETTE_ShareUnlockPalette(ppalDIB);
|
2009-08-04 20:37:10 +00:00
|
|
|
|
2008-04-19 00:24:34 +00:00
|
|
|
if (pSourceSurf) EngUnlockSurface(pSourceSurf);
|
|
|
|
if (hSourceBitmap) EngDeleteSurface((HSURF)hSourceBitmap);
|
[WIN32K]
Rewrite of the GDI handle manager
- The old handle manager used a completely retarded spinlock in combination with KeDelayExecutionThread() for both exclusive
and shared locks. This is probably the most uneffective algorithm possible. It was also duplicating code everywhere and it was a overall mess It
is now replaced with a lock-free reference counter for shared locks and a pushlock for exclusive locks. -> Better performance and scalability.
- Allocate user mode object attributes from the new gdi pool. This way, we don't need any caching, since the pool serves as a cache. Its also
much faster and uses much less memory.
- Allow object allocations of different size, instead of fixed size from a table. This way a single allocation can take care of actual needs.
- Allow allcoating objects without a handle and insert them into the handle table later
- Properly synchronize the process GDIHandleCount. Now gdiview and taskmanager show the correct number of gdi handles.
- Implement a new event tracking system, that is capable of tracking all reverences and locks of objects and pool allocations to help track
possible leaks
- Make sure that all objects of a process are deleted in cleanup
- Make sure all usermode memory allocations are freed, when cleaning up the process pool.
- Make sure that each object type is using the correct type of lock (either shared or exclusive, not a mixture)
- Fix some object / reference leaks
- Lots of inferface improvements
- Use global variables for certain things instead of members in the mapped gdi handle table
- Make IntSysCreateRectpRgn create a region without a handle
- Fix detection od source and mask use in GreStretchBltMask
- Use GDIOBJ_bLockMultipleObjects in NtGdiCombineRegion to avoid possible deadlocks
- Fix NtGdiAbortPath to reset DCPATH_ACTIVE flag in the dc and only bail out on error, instead of always
- Replace DC_AllocateDcAttr and DC_AllocDcAttr with DC_bAllocDcAttr using the new user mode pool
- Remove DCU_SyncDcAttrtoUser and DCU_SynchDcAttrtoUser. Those functions were unused and didn't do anything useful anyway,
- Replace IntGdiSetDCOwnerEx and DC_SetOwnership with GreSetDCOwner, remove unused NoSetBrush parameter
- Replace GDIOBJ_bValidateHandle and IsObjectDead with GreIsHandleValid
- Chage GDIOBJ_bLockMultipleObjects: pass object type, return a BOOL, whether all objects could be locked, cleanup on failure
svn path=/trunk/; revision=51470
2011-04-28 08:26:46 +00:00
|
|
|
if (hpalDIB) GreDeleteObject(hpalDIB);
|
2007-09-27 17:04:29 +00:00
|
|
|
DC_UnlockDc(pDC);
|
|
|
|
|
|
|
|
return ret;
|
2001-03-31 15:35:08 +00:00
|
|
|
}
|
|
|
|
|
2007-10-01 11:53:31 +00:00
|
|
|
|
2004-07-03 13:55:37 +00:00
|
|
|
/* Converts a device-dependent bitmap to a DIB */
|
2009-06-10 00:23:15 +00:00
|
|
|
INT
|
|
|
|
APIENTRY
|
|
|
|
NtGdiGetDIBitsInternal(
|
|
|
|
HDC hDC,
|
|
|
|
HBITMAP hBitmap,
|
|
|
|
UINT StartScan,
|
|
|
|
UINT ScanLines,
|
|
|
|
LPBYTE Bits,
|
|
|
|
LPBITMAPINFO Info,
|
|
|
|
UINT Usage,
|
|
|
|
UINT MaxBits,
|
|
|
|
UINT MaxInfo)
|
2001-03-31 15:35:08 +00:00
|
|
|
{
|
2011-02-28 23:46:02 +00:00
|
|
|
BITMAPCOREINFO* pbmci = NULL;
|
|
|
|
PSURFACE psurf = NULL;
|
|
|
|
PDC pDC;
|
|
|
|
LONG width, height;
|
|
|
|
WORD planes, bpp;
|
|
|
|
DWORD compr, size ;
|
|
|
|
int i, bitmap_type;
|
|
|
|
RGBTRIPLE* rgbTriples;
|
|
|
|
RGBQUAD* rgbQuads;
|
|
|
|
VOID* colorPtr;
|
|
|
|
NTSTATUS Status = STATUS_SUCCESS;
|
2007-10-01 11:53:31 +00:00
|
|
|
|
|
|
|
DPRINT("Entered NtGdiGetDIBitsInternal()\n");
|
2007-09-18 15:24:34 +00:00
|
|
|
|
2009-06-10 00:23:15 +00:00
|
|
|
if ((Usage && Usage != DIB_PAL_COLORS) || !Info || !hBitmap)
|
|
|
|
return 0;
|
2008-12-01 00:13:45 +00:00
|
|
|
|
|
|
|
_SEH2_TRY
|
|
|
|
{
|
2011-02-28 23:46:02 +00:00
|
|
|
/* Probe for read and write */
|
2010-07-29 16:12:43 +00:00
|
|
|
ProbeForRead(Info, MaxInfo, 1);
|
2011-02-28 23:46:02 +00:00
|
|
|
ProbeForWrite(Info, MaxInfo, 1);
|
2010-07-29 16:12:43 +00:00
|
|
|
if (Bits) ProbeForWrite(Bits, MaxBits, 1);
|
2008-12-01 00:13:45 +00:00
|
|
|
}
|
|
|
|
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
|
|
|
|
{
|
2009-06-10 00:23:15 +00:00
|
|
|
Status = _SEH2_GetExceptionCode();
|
2008-12-01 00:13:45 +00:00
|
|
|
}
|
|
|
|
_SEH2_END
|
|
|
|
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
{
|
2009-06-10 00:23:15 +00:00
|
|
|
return 0;
|
2008-12-01 00:13:45 +00:00
|
|
|
}
|
|
|
|
|
2011-02-28 23:46:02 +00:00
|
|
|
colorPtr = (LPBYTE)Info + Info->bmiHeader.biSize;
|
|
|
|
rgbTriples = colorPtr;
|
|
|
|
rgbQuads = colorPtr;
|
|
|
|
|
|
|
|
bitmap_type = DIB_GetBitmapInfo(&Info->bmiHeader,
|
|
|
|
&width,
|
|
|
|
&height,
|
|
|
|
&planes,
|
|
|
|
&bpp,
|
|
|
|
&compr,
|
|
|
|
&size);
|
|
|
|
if(bitmap_type == -1)
|
|
|
|
{
|
|
|
|
DPRINT("Wrong bitmap format\n");
|
|
|
|
EngSetLastError(ERROR_INVALID_PARAMETER);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
else if(bitmap_type == 0)
|
|
|
|
{
|
|
|
|
/* We need a BITMAPINFO to create a DIB, but we have to fill
|
|
|
|
* the BITMAPCOREINFO we're provided */
|
|
|
|
pbmci = (BITMAPCOREINFO*)Info;
|
|
|
|
Info = DIB_ConvertBitmapInfo((BITMAPINFO*)pbmci, Usage);
|
|
|
|
if(Info == NULL)
|
|
|
|
{
|
|
|
|
DPRINT1("Error, could not convert the BITMAPCOREINFO!\n");
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
rgbQuads = Info->bmiColors;
|
|
|
|
}
|
2010-07-29 16:12:43 +00:00
|
|
|
|
|
|
|
pDC = DC_LockDc(hDC);
|
|
|
|
if (pDC == NULL || pDC->dctype == DC_TYPE_INFO)
|
2007-09-18 15:24:34 +00:00
|
|
|
{
|
2011-02-28 23:46:02 +00:00
|
|
|
ScanLines = 0;
|
2010-07-29 16:12:43 +00:00
|
|
|
goto done;
|
2007-09-18 15:24:34 +00:00
|
|
|
}
|
2003-12-20 14:51:41 +00:00
|
|
|
|
2007-10-01 11:53:31 +00:00
|
|
|
/* Get a pointer to the source bitmap object */
|
2011-02-27 17:38:18 +00:00
|
|
|
psurf = SURFACE_ShareLockSurface(hBitmap);
|
2009-01-08 16:33:40 +00:00
|
|
|
if (psurf == NULL)
|
2010-05-08 22:10:41 +00:00
|
|
|
{
|
2010-07-29 16:12:43 +00:00
|
|
|
ScanLines = 0;
|
|
|
|
goto done;
|
2009-03-21 19:15:52 +00:00
|
|
|
}
|
|
|
|
|
2011-02-28 23:46:02 +00:00
|
|
|
/* Fill in the structure */
|
|
|
|
switch(bpp)
|
|
|
|
{
|
|
|
|
case 0: /* Only info */
|
|
|
|
if(pbmci)
|
|
|
|
{
|
|
|
|
pbmci->bmciHeader.bcWidth = psurf->SurfObj.sizlBitmap.cx;
|
|
|
|
pbmci->bmciHeader.bcHeight = (psurf->SurfObj.fjBitmap & BMF_TOPDOWN) ?
|
|
|
|
-psurf->SurfObj.sizlBitmap.cy :
|
|
|
|
psurf->SurfObj.sizlBitmap.cy;
|
|
|
|
pbmci->bmciHeader.bcPlanes = 1;
|
|
|
|
pbmci->bmciHeader.bcBitCount = BitsPerFormat(psurf->SurfObj.iBitmapFormat);
|
|
|
|
}
|
|
|
|
Info->bmiHeader.biWidth = psurf->SurfObj.sizlBitmap.cx;
|
|
|
|
Info->bmiHeader.biHeight = (psurf->SurfObj.fjBitmap & BMF_TOPDOWN) ?
|
|
|
|
-psurf->SurfObj.sizlBitmap.cy :
|
|
|
|
psurf->SurfObj.sizlBitmap.cy;;
|
|
|
|
Info->bmiHeader.biPlanes = 1;
|
|
|
|
Info->bmiHeader.biBitCount = BitsPerFormat(psurf->SurfObj.iBitmapFormat);
|
|
|
|
Info->bmiHeader.biSizeImage = DIB_GetDIBImageBytes( Info->bmiHeader.biWidth,
|
|
|
|
Info->bmiHeader.biHeight,
|
|
|
|
Info->bmiHeader.biBitCount);
|
|
|
|
if(psurf->hSecure)
|
|
|
|
{
|
|
|
|
switch(Info->bmiHeader.biBitCount)
|
|
|
|
{
|
|
|
|
case 16:
|
|
|
|
case 32:
|
|
|
|
Info->bmiHeader.biCompression = BI_BITFIELDS;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
Info->bmiHeader.biCompression = BI_RGB;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if(Info->bmiHeader.biBitCount > 8)
|
|
|
|
{
|
|
|
|
Info->bmiHeader.biCompression = BI_BITFIELDS;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
Info->bmiHeader.biCompression = BI_RGB;
|
|
|
|
}
|
|
|
|
Info->bmiHeader.biXPelsPerMeter = 0;
|
2010-07-29 16:12:43 +00:00
|
|
|
Info->bmiHeader.biYPelsPerMeter = 0;
|
|
|
|
Info->bmiHeader.biClrUsed = 0;
|
|
|
|
Info->bmiHeader.biClrImportant = 0;
|
2011-02-28 23:46:02 +00:00
|
|
|
ScanLines = abs(Info->bmiHeader.biHeight);
|
|
|
|
goto done;
|
|
|
|
|
|
|
|
case 1:
|
|
|
|
case 4:
|
|
|
|
case 8:
|
|
|
|
Info->bmiHeader.biClrUsed = 0;
|
|
|
|
|
|
|
|
/* If the bitmap if a DIB section and has the same format than what
|
|
|
|
* we're asked, go ahead! */
|
|
|
|
if((psurf->hSecure) &&
|
|
|
|
(BitsPerFormat(psurf->SurfObj.iBitmapFormat) == bpp))
|
|
|
|
{
|
|
|
|
if(Usage == DIB_RGB_COLORS)
|
|
|
|
{
|
|
|
|
unsigned int colors = min(psurf->ppal->NumColors, 1 << bpp);
|
|
|
|
|
|
|
|
if(pbmci)
|
|
|
|
{
|
|
|
|
for(i=0; i < colors; i++)
|
|
|
|
{
|
|
|
|
rgbTriples[i].rgbtRed = psurf->ppal->IndexedColors[i].peRed;
|
|
|
|
rgbTriples[i].rgbtGreen = psurf->ppal->IndexedColors[i].peGreen;
|
|
|
|
rgbTriples[i].rgbtBlue = psurf->ppal->IndexedColors[i].peBlue;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if(colors != 1 << bpp) Info->bmiHeader.biClrUsed = colors;
|
|
|
|
for(i=0; i < colors; i++)
|
|
|
|
{
|
|
|
|
rgbQuads[i].rgbRed = psurf->ppal->IndexedColors[i].peRed;
|
|
|
|
rgbQuads[i].rgbGreen = psurf->ppal->IndexedColors[i].peGreen;
|
|
|
|
rgbQuads[i].rgbBlue = psurf->ppal->IndexedColors[i].peBlue;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
for(i=0; i < 1 << bpp; i++)
|
|
|
|
{
|
|
|
|
if(pbmci) ((WORD*)rgbTriples)[i] = i;
|
|
|
|
((WORD*)rgbQuads)[i] = i;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if(Usage == DIB_PAL_COLORS)
|
|
|
|
{
|
|
|
|
for(i=0; i < 1 << bpp; i++)
|
|
|
|
{
|
|
|
|
if(pbmci) ((WORD*)rgbTriples)[i] = i;
|
|
|
|
((WORD*)rgbQuads)[i] = i;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if(bpp > 1 && bpp == BitsPerFormat(psurf->SurfObj.iBitmapFormat))
|
|
|
|
{
|
2010-07-29 16:12:43 +00:00
|
|
|
/* For color DDBs in native depth (mono DDBs always have
|
|
|
|
a black/white palette):
|
|
|
|
Generate the color map from the selected palette */
|
2011-04-18 19:09:05 +00:00
|
|
|
PPALETTE pDcPal = PALETTE_ShareLockPalette(pDC->dclevel.hpal);
|
2011-02-28 23:46:02 +00:00
|
|
|
if(!pDcPal)
|
|
|
|
{
|
|
|
|
ScanLines = 0 ;
|
|
|
|
goto done ;
|
|
|
|
}
|
|
|
|
for (i = 0; i < pDcPal->NumColors; i++)
|
|
|
|
{
|
2010-07-29 16:12:43 +00:00
|
|
|
if (pbmci)
|
2009-06-10 00:23:15 +00:00
|
|
|
{
|
2010-07-29 16:12:43 +00:00
|
|
|
rgbTriples[i].rgbtRed = pDcPal->IndexedColors[i].peRed;
|
|
|
|
rgbTriples[i].rgbtGreen = pDcPal->IndexedColors[i].peGreen;
|
|
|
|
rgbTriples[i].rgbtBlue = pDcPal->IndexedColors[i].peBlue;
|
2009-06-10 00:23:15 +00:00
|
|
|
}
|
2010-08-05 21:12:57 +00:00
|
|
|
|
2010-07-29 16:12:43 +00:00
|
|
|
rgbQuads[i].rgbRed = pDcPal->IndexedColors[i].peRed;
|
|
|
|
rgbQuads[i].rgbGreen = pDcPal->IndexedColors[i].peGreen;
|
|
|
|
rgbQuads[i].rgbBlue = pDcPal->IndexedColors[i].peBlue;
|
|
|
|
rgbQuads[i].rgbReserved = 0;
|
2011-02-28 23:46:02 +00:00
|
|
|
}
|
2011-04-18 19:09:05 +00:00
|
|
|
PALETTE_ShareUnlockPalette(pDcPal);
|
2011-02-28 23:46:02 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
switch (bpp)
|
|
|
|
{
|
2010-07-29 16:12:43 +00:00
|
|
|
case 1:
|
|
|
|
if (pbmci)
|
2009-06-10 00:23:15 +00:00
|
|
|
{
|
2010-07-29 16:12:43 +00:00
|
|
|
rgbTriples[0].rgbtRed = rgbTriples[0].rgbtGreen =
|
2011-02-28 23:46:02 +00:00
|
|
|
rgbTriples[0].rgbtBlue = 0;
|
2010-07-29 16:12:43 +00:00
|
|
|
rgbTriples[1].rgbtRed = rgbTriples[1].rgbtGreen =
|
2011-02-28 23:46:02 +00:00
|
|
|
rgbTriples[1].rgbtBlue = 0xff;
|
2009-06-10 00:23:15 +00:00
|
|
|
}
|
2010-07-29 16:12:43 +00:00
|
|
|
rgbQuads[0].rgbRed = rgbQuads[0].rgbGreen =
|
2011-02-28 23:46:02 +00:00
|
|
|
rgbQuads[0].rgbBlue = 0;
|
2010-07-29 16:12:43 +00:00
|
|
|
rgbQuads[0].rgbReserved = 0;
|
|
|
|
rgbQuads[1].rgbRed = rgbQuads[1].rgbGreen =
|
2011-02-28 23:46:02 +00:00
|
|
|
rgbQuads[1].rgbBlue = 0xff;
|
2010-07-29 16:12:43 +00:00
|
|
|
rgbQuads[1].rgbReserved = 0;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 4:
|
|
|
|
if (pbmci)
|
|
|
|
RtlCopyMemory(rgbTriples, EGAColorsTriples, sizeof(EGAColorsTriples));
|
|
|
|
RtlCopyMemory(rgbQuads, EGAColorsQuads, sizeof(EGAColorsQuads));
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 8:
|
2011-02-28 23:46:02 +00:00
|
|
|
{
|
|
|
|
INT r, g, b;
|
|
|
|
RGBQUAD *color;
|
|
|
|
if (pbmci)
|
2009-06-10 00:23:15 +00:00
|
|
|
{
|
2011-02-28 23:46:02 +00:00
|
|
|
RGBTRIPLE *colorTriple;
|
|
|
|
|
|
|
|
RtlCopyMemory(rgbTriples, DefLogPaletteTriples,
|
|
|
|
10 * sizeof(RGBTRIPLE));
|
|
|
|
RtlCopyMemory(rgbTriples + 246, DefLogPaletteTriples + 10,
|
|
|
|
10 * sizeof(RGBTRIPLE));
|
|
|
|
colorTriple = rgbTriples + 10;
|
2010-07-29 16:12:43 +00:00
|
|
|
for(r = 0; r <= 5; r++) /* FIXME */
|
2011-02-28 23:46:02 +00:00
|
|
|
{
|
2010-07-29 16:12:43 +00:00
|
|
|
for(g = 0; g <= 5; g++)
|
2011-02-28 23:46:02 +00:00
|
|
|
{
|
2010-07-29 16:12:43 +00:00
|
|
|
for(b = 0; b <= 5; b++)
|
2011-02-28 23:46:02 +00:00
|
|
|
{
|
|
|
|
colorTriple->rgbtRed = (r * 0xff) / 5;
|
|
|
|
colorTriple->rgbtGreen = (g * 0xff) / 5;
|
|
|
|
colorTriple->rgbtBlue = (b * 0xff) / 5;
|
2010-07-29 16:12:43 +00:00
|
|
|
color++;
|
|
|
|
}
|
2011-02-28 23:46:02 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
memcpy(rgbQuads, DefLogPaletteQuads,
|
|
|
|
10 * sizeof(RGBQUAD));
|
|
|
|
memcpy(rgbQuads + 246, DefLogPaletteQuads + 10,
|
|
|
|
10 * sizeof(RGBQUAD));
|
|
|
|
color = rgbQuads + 10;
|
|
|
|
for(r = 0; r <= 5; r++) /* FIXME */
|
|
|
|
{
|
|
|
|
for(g = 0; g <= 5; g++)
|
|
|
|
{
|
|
|
|
for(b = 0; b <= 5; b++)
|
|
|
|
{
|
|
|
|
color->rgbRed = (r * 0xff) / 5;
|
|
|
|
color->rgbGreen = (g * 0xff) / 5;
|
|
|
|
color->rgbBlue = (b * 0xff) / 5;
|
|
|
|
color->rgbReserved = 0;
|
|
|
|
color++;
|
|
|
|
}
|
|
|
|
}
|
2009-06-10 00:23:15 +00:00
|
|
|
}
|
|
|
|
}
|
2011-02-28 23:46:02 +00:00
|
|
|
}
|
2009-03-21 19:15:52 +00:00
|
|
|
}
|
2010-07-29 16:12:43 +00:00
|
|
|
}
|
|
|
|
break;
|
2009-06-10 00:23:15 +00:00
|
|
|
|
2010-07-29 16:12:43 +00:00
|
|
|
case 15:
|
|
|
|
if (Info->bmiHeader.biCompression == BI_BITFIELDS)
|
|
|
|
{
|
|
|
|
((PDWORD)Info->bmiColors)[0] = 0x7c00;
|
|
|
|
((PDWORD)Info->bmiColors)[1] = 0x03e0;
|
|
|
|
((PDWORD)Info->bmiColors)[2] = 0x001f;
|
|
|
|
}
|
|
|
|
break;
|
2009-06-10 00:23:15 +00:00
|
|
|
|
2010-07-29 16:12:43 +00:00
|
|
|
case 16:
|
|
|
|
if (Info->bmiHeader.biCompression == BI_BITFIELDS)
|
|
|
|
{
|
2010-07-30 02:15:46 +00:00
|
|
|
if (psurf->hSecure)
|
2011-02-28 23:46:02 +00:00
|
|
|
{
|
|
|
|
((PDWORD)Info->bmiColors)[0] = psurf->ppal->RedMask;
|
2010-07-30 02:15:46 +00:00
|
|
|
((PDWORD)Info->bmiColors)[1] = psurf->ppal->GreenMask;
|
|
|
|
((PDWORD)Info->bmiColors)[2] = psurf->ppal->BlueMask;
|
2011-02-28 23:46:02 +00:00
|
|
|
}
|
2010-07-29 16:12:43 +00:00
|
|
|
else
|
2009-03-21 19:15:52 +00:00
|
|
|
{
|
2010-07-29 16:12:43 +00:00
|
|
|
((PDWORD)Info->bmiColors)[0] = 0xf800;
|
|
|
|
((PDWORD)Info->bmiColors)[1] = 0x07e0;
|
|
|
|
((PDWORD)Info->bmiColors)[2] = 0x001f;
|
2009-03-21 19:15:52 +00:00
|
|
|
}
|
2010-07-29 16:12:43 +00:00
|
|
|
}
|
|
|
|
break;
|
2009-06-10 00:23:15 +00:00
|
|
|
|
2010-07-29 16:12:43 +00:00
|
|
|
case 24:
|
|
|
|
case 32:
|
|
|
|
if (Info->bmiHeader.biCompression == BI_BITFIELDS)
|
|
|
|
{
|
2010-07-30 02:15:46 +00:00
|
|
|
if (psurf->hSecure)
|
2011-02-28 23:46:02 +00:00
|
|
|
{
|
|
|
|
((PDWORD)Info->bmiColors)[0] = psurf->ppal->RedMask;
|
2010-07-30 02:15:46 +00:00
|
|
|
((PDWORD)Info->bmiColors)[1] = psurf->ppal->GreenMask;
|
|
|
|
((PDWORD)Info->bmiColors)[2] = psurf->ppal->BlueMask;
|
2011-02-28 23:46:02 +00:00
|
|
|
}
|
2010-07-29 16:12:43 +00:00
|
|
|
else
|
2009-03-21 19:15:52 +00:00
|
|
|
{
|
2010-07-29 16:12:43 +00:00
|
|
|
((PDWORD)Info->bmiColors)[0] = 0xff0000;
|
|
|
|
((PDWORD)Info->bmiColors)[1] = 0x00ff00;
|
|
|
|
((PDWORD)Info->bmiColors)[2] = 0x0000ff;
|
2009-03-21 19:15:52 +00:00
|
|
|
}
|
2009-06-10 00:23:15 +00:00
|
|
|
}
|
2010-07-29 16:12:43 +00:00
|
|
|
break;
|
2007-10-01 11:53:31 +00:00
|
|
|
}
|
2011-02-28 23:46:02 +00:00
|
|
|
Info->bmiHeader.biSizeImage = DIB_GetDIBImageBytes(width, height, bpp);
|
2008-12-01 00:13:45 +00:00
|
|
|
|
2011-02-28 23:46:02 +00:00
|
|
|
if(Bits && ScanLines)
|
|
|
|
{
|
|
|
|
/* Create a DIBSECTION, blt it, profit */
|
|
|
|
PVOID pDIBits ;
|
|
|
|
HBITMAP hBmpDest;
|
|
|
|
PSURFACE psurfDest;
|
|
|
|
EXLATEOBJ exlo;
|
|
|
|
RECT rcDest;
|
|
|
|
POINTL srcPoint;
|
|
|
|
BOOL ret ;
|
2010-07-29 16:12:43 +00:00
|
|
|
|
2011-02-28 23:46:02 +00:00
|
|
|
if (StartScan > psurf->SurfObj.sizlBitmap.cy)
|
2009-06-10 00:23:15 +00:00
|
|
|
{
|
2011-02-28 23:46:02 +00:00
|
|
|
ScanLines = 0;
|
2010-07-29 16:12:43 +00:00
|
|
|
goto done;
|
2009-06-10 00:23:15 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
ScanLines = min(ScanLines, psurf->SurfObj.sizlBitmap.cy - StartScan);
|
2011-02-28 23:46:02 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Fixup values */
|
|
|
|
Info->bmiHeader.biWidth = psurf->SurfObj.sizlBitmap.cx;
|
|
|
|
Info->bmiHeader.biHeight = height < 0 ?
|
|
|
|
-ScanLines : ScanLines;
|
|
|
|
/* Create the DIB */
|
|
|
|
hBmpDest = DIB_CreateDIBSection(pDC, Info, Usage, &pDIBits, NULL, 0, 0);
|
|
|
|
/* Restore them */
|
|
|
|
Info->bmiHeader.biWidth = width;
|
|
|
|
Info->bmiHeader.biHeight = height;
|
|
|
|
|
|
|
|
if(!hBmpDest)
|
|
|
|
{
|
|
|
|
DPRINT1("Unable to create a DIB Section!\n");
|
|
|
|
EngSetLastError(ERROR_INVALID_PARAMETER);
|
|
|
|
ScanLines = 0;
|
|
|
|
goto done ;
|
|
|
|
}
|
|
|
|
|
|
|
|
psurfDest = SURFACE_ShareLockSurface(hBmpDest);
|
|
|
|
|
|
|
|
rcDest.left = 0;
|
|
|
|
rcDest.top = 0;
|
|
|
|
rcDest.bottom = ScanLines;
|
|
|
|
rcDest.right = psurf->SurfObj.sizlBitmap.cx;
|
2010-08-02 16:49:51 +00:00
|
|
|
|
2011-02-28 12:47:01 +00:00
|
|
|
srcPoint.x = 0;
|
|
|
|
|
|
|
|
if(height < 0)
|
|
|
|
{
|
|
|
|
srcPoint.y = 0;
|
|
|
|
|
|
|
|
if(ScanLines <= StartScan)
|
|
|
|
{
|
|
|
|
ScanLines = 1;
|
|
|
|
SURFACE_ShareUnlockSurface(psurfDest);
|
|
|
|
GreDeleteObject(hBmpDest);
|
|
|
|
goto done;
|
|
|
|
}
|
|
|
|
|
|
|
|
ScanLines -= StartScan;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
srcPoint.y = StartScan;
|
|
|
|
}
|
2010-07-29 16:12:43 +00:00
|
|
|
|
2011-02-28 23:46:02 +00:00
|
|
|
EXLATEOBJ_vInitialize(&exlo, psurf->ppal, psurfDest->ppal, 0xffffff, 0xffffff, 0);
|
2010-08-02 16:49:51 +00:00
|
|
|
|
2011-02-28 23:46:02 +00:00
|
|
|
ret = IntEngCopyBits(&psurfDest->SurfObj,
|
|
|
|
&psurf->SurfObj,
|
|
|
|
NULL,
|
|
|
|
&exlo.xlo,
|
|
|
|
&rcDest,
|
|
|
|
&srcPoint);
|
2010-07-29 16:12:43 +00:00
|
|
|
|
2011-02-27 17:38:18 +00:00
|
|
|
SURFACE_ShareUnlockSurface(psurfDest);
|
|
|
|
|
2011-02-28 23:46:02 +00:00
|
|
|
if(!ret)
|
|
|
|
ScanLines = 0;
|
|
|
|
else
|
|
|
|
{
|
|
|
|
Status = STATUS_SUCCESS;
|
|
|
|
_SEH2_TRY
|
|
|
|
{
|
|
|
|
RtlCopyMemory(Bits, pDIBits, DIB_GetDIBImageBytes (width, ScanLines, bpp));
|
|
|
|
}
|
|
|
|
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
|
|
|
|
{
|
|
|
|
Status = _SEH2_GetExceptionCode();
|
|
|
|
}
|
|
|
|
_SEH2_END
|
|
|
|
|
|
|
|
if(!NT_SUCCESS(Status))
|
|
|
|
{
|
|
|
|
DPRINT1("Unable to copy bits to the user provided pointer\n");
|
|
|
|
ScanLines = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
GreDeleteObject(hBmpDest);
|
|
|
|
EXLATEOBJ_vCleanup(&exlo);
|
|
|
|
}
|
|
|
|
else ScanLines = abs(height);
|
2007-10-01 11:53:31 +00:00
|
|
|
|
2010-07-29 16:12:43 +00:00
|
|
|
done:
|
2003-12-20 14:51:41 +00:00
|
|
|
|
2011-02-28 23:46:02 +00:00
|
|
|
if(pDC) DC_UnlockDc(pDC);
|
|
|
|
if(psurf) SURFACE_ShareUnlockSurface(psurf);
|
|
|
|
if(pbmci) DIB_FreeConvertedBitmapInfo(Info, (BITMAPINFO*)pbmci);
|
2007-10-01 11:53:31 +00:00
|
|
|
|
2011-02-28 23:46:02 +00:00
|
|
|
return ScanLines;
|
2001-03-31 15:35:08 +00:00
|
|
|
}
|
|
|
|
|
2011-03-09 15:46:13 +00:00
|
|
|
#define ROP_TO_ROP4(Rop) ((Rop) >> 16)
|
2010-07-29 16:12:43 +00:00
|
|
|
|
2011-03-09 15:46:13 +00:00
|
|
|
W32KAPI
|
2008-02-16 18:14:36 +00:00
|
|
|
INT
|
|
|
|
APIENTRY
|
|
|
|
NtGdiStretchDIBitsInternal(
|
2011-03-09 15:46:13 +00:00
|
|
|
IN HDC hdc,
|
|
|
|
IN INT xDst,
|
|
|
|
IN INT yDst,
|
|
|
|
IN INT cxDst,
|
|
|
|
IN INT cyDst,
|
|
|
|
IN INT xSrc,
|
|
|
|
IN INT ySrc,
|
|
|
|
IN INT cxSrc,
|
|
|
|
IN INT cySrc,
|
|
|
|
IN OPTIONAL LPBYTE pjInit,
|
|
|
|
IN LPBITMAPINFO pbmi,
|
|
|
|
IN DWORD dwUsage,
|
|
|
|
IN DWORD dwRop, // ms ntgdi.h says dwRop4(?)
|
|
|
|
IN UINT cjMaxInfo,
|
|
|
|
IN UINT cjMaxBits,
|
|
|
|
IN HANDLE hcmXform)
|
2001-03-31 15:35:08 +00:00
|
|
|
{
|
2011-03-09 15:46:13 +00:00
|
|
|
BOOL bResult = FALSE;
|
|
|
|
SIZEL sizel;
|
|
|
|
RECTL rcSrc, rcDst;
|
2010-08-05 21:12:57 +00:00
|
|
|
PDC pdc;
|
2011-03-09 15:46:13 +00:00
|
|
|
HBITMAP hbmTmp;
|
|
|
|
PSURFACE psurfTmp, psurfDst;
|
|
|
|
EXLATEOBJ exlo;
|
2009-06-10 00:23:15 +00:00
|
|
|
|
2011-03-09 15:46:13 +00:00
|
|
|
if (!(pdc = DC_LockDc(hdc)))
|
2011-01-09 18:11:44 +00:00
|
|
|
{
|
2011-03-09 15:46:13 +00:00
|
|
|
EngSetLastError(ERROR_INVALID_HANDLE);
|
2011-01-09 18:11:44 +00:00
|
|
|
return 0;
|
|
|
|
}
|
2009-06-10 00:23:15 +00:00
|
|
|
|
2011-03-09 15:46:13 +00:00
|
|
|
/* Transform dest size */
|
|
|
|
sizel.cx = cxDst;
|
|
|
|
sizel.cy = cyDst;
|
|
|
|
IntLPtoDP(pdc, (POINTL*)&sizel, 1);
|
|
|
|
DC_UnlockDc(pdc);
|
2003-12-07 10:31:56 +00:00
|
|
|
|
2011-03-09 15:46:13 +00:00
|
|
|
/* Check if we can use NtGdiSetDIBitsToDeviceInternal */
|
|
|
|
if (sizel.cx == cxSrc && sizel.cy == cySrc && dwRop == SRCCOPY)
|
|
|
|
{
|
|
|
|
/* Yes, we can! */
|
|
|
|
return NtGdiSetDIBitsToDeviceInternal(hdc,
|
|
|
|
xDst,
|
|
|
|
yDst,
|
|
|
|
cxDst,
|
|
|
|
cyDst,
|
|
|
|
xSrc,
|
|
|
|
ySrc,
|
|
|
|
0,
|
|
|
|
cySrc,
|
|
|
|
pjInit,
|
|
|
|
pbmi,
|
|
|
|
dwUsage,
|
|
|
|
cjMaxBits,
|
|
|
|
cjMaxInfo,
|
|
|
|
TRUE,
|
|
|
|
hcmXform);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Create an intermediate bitmap from the DIB */
|
|
|
|
hbmTmp = NtGdiCreateDIBitmapInternal(hdc,
|
|
|
|
cxSrc,
|
|
|
|
cySrc,
|
|
|
|
CBM_INIT,
|
|
|
|
pjInit,
|
|
|
|
pbmi,
|
|
|
|
dwUsage,
|
|
|
|
cjMaxInfo,
|
|
|
|
cjMaxBits,
|
|
|
|
0,
|
|
|
|
hcmXform);
|
|
|
|
if (!hbmTmp)
|
|
|
|
{
|
|
|
|
DPRINT1("NtGdiCreateDIBitmapInternal failed\n");
|
2010-08-05 21:12:57 +00:00
|
|
|
return 0;
|
|
|
|
}
|
2007-04-18 00:38:36 +00:00
|
|
|
|
2011-03-09 15:46:13 +00:00
|
|
|
/* FIXME: locking twice is cheesy, coord tranlation in UM will fix it */
|
|
|
|
if (!(pdc = DC_LockDc(hdc)))
|
2011-02-19 22:29:31 +00:00
|
|
|
{
|
2011-03-09 15:46:13 +00:00
|
|
|
DPRINT1("Could not lock dc\n");
|
2011-02-19 22:29:31 +00:00
|
|
|
EngSetLastError(ERROR_INVALID_HANDLE);
|
2011-03-09 15:46:13 +00:00
|
|
|
GreDeleteObject(hbmTmp);
|
2011-02-19 22:29:31 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2011-03-09 15:46:13 +00:00
|
|
|
psurfTmp = SURFACE_ShareLockSurface(hbmTmp);
|
|
|
|
if (!psurfTmp)
|
2010-08-05 21:12:57 +00:00
|
|
|
{
|
2011-03-09 15:46:13 +00:00
|
|
|
DPRINT1("Could not lock bitmap :-(\n");
|
|
|
|
goto cleanup;
|
2010-08-05 21:12:57 +00:00
|
|
|
}
|
2008-06-07 11:35:53 +00:00
|
|
|
|
2011-03-09 15:46:13 +00:00
|
|
|
psurfDst = pdc->dclevel.pSurface;
|
|
|
|
if (!psurfDst)
|
2010-08-05 21:12:57 +00:00
|
|
|
{
|
2011-03-09 15:46:13 +00:00
|
|
|
// CHECKME
|
|
|
|
bResult = TRUE;
|
2011-01-09 18:11:44 +00:00
|
|
|
goto cleanup;
|
2010-08-05 21:12:57 +00:00
|
|
|
}
|
2011-01-09 18:11:44 +00:00
|
|
|
|
2011-03-09 15:46:13 +00:00
|
|
|
/* Calculate source and destination rect */
|
|
|
|
rcSrc.left = xSrc;
|
|
|
|
rcSrc.top = ySrc;
|
|
|
|
rcSrc.right = xSrc + abs(cxSrc);
|
|
|
|
rcSrc.bottom = ySrc + abs(cySrc);
|
|
|
|
rcDst.left = xDst;
|
|
|
|
rcDst.top = yDst;
|
|
|
|
rcDst.right = rcDst.left + cxDst;
|
|
|
|
rcDst.bottom = rcDst.top + cyDst;
|
|
|
|
IntLPtoDP(pdc, (POINTL*)&rcDst, 2);
|
|
|
|
RECTL_vOffsetRect(&rcDst, pdc->ptlDCOrig.x, pdc->ptlDCOrig.y);
|
2011-01-09 18:11:44 +00:00
|
|
|
|
2011-03-09 15:46:13 +00:00
|
|
|
/* Initialize XLATEOBJ */
|
|
|
|
EXLATEOBJ_vInitialize(&exlo,
|
|
|
|
psurfTmp->ppal,
|
|
|
|
psurfDst->ppal,
|
|
|
|
RGB(0xff, 0xff, 0xff),
|
|
|
|
pdc->pdcattr->crBackgroundClr,
|
|
|
|
pdc->pdcattr->crForegroundClr);
|
|
|
|
|
|
|
|
/* Prepare DC for blit */
|
|
|
|
DC_vPrepareDCsForBlit(pdc, rcDst, NULL, rcSrc);
|
|
|
|
|
|
|
|
/* Perform the stretch operation */
|
|
|
|
bResult = IntEngStretchBlt(&psurfDst->SurfObj,
|
|
|
|
&psurfTmp->SurfObj,
|
|
|
|
NULL,
|
|
|
|
pdc->rosdc.CombinedClip,
|
|
|
|
&exlo.xlo,
|
|
|
|
&rcDst,
|
|
|
|
&rcSrc,
|
|
|
|
NULL,
|
|
|
|
&pdc->eboFill.BrushObject,
|
|
|
|
NULL,
|
|
|
|
ROP_TO_ROP4(dwRop));
|
|
|
|
|
|
|
|
/* Cleanup */
|
|
|
|
DC_vFinishBlit(pdc, NULL);
|
|
|
|
EXLATEOBJ_vCleanup(&exlo);
|
2010-08-01 12:17:35 +00:00
|
|
|
cleanup:
|
2011-03-09 15:46:13 +00:00
|
|
|
if (psurfTmp) SURFACE_ShareUnlockSurface(psurfTmp);
|
|
|
|
if (hbmTmp) GreDeleteObject(hbmTmp);
|
|
|
|
if (pdc) DC_UnlockDc(pdc);
|
|
|
|
|
|
|
|
return bResult;
|
2001-03-31 15:35:08 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-03-30 22:37:42 +00:00
|
|
|
HBITMAP
|
|
|
|
FASTCALL
|
2009-06-10 00:23:15 +00:00
|
|
|
IntCreateDIBitmap(
|
|
|
|
PDC Dc,
|
|
|
|
INT width,
|
|
|
|
INT height,
|
|
|
|
UINT bpp,
|
|
|
|
DWORD init,
|
|
|
|
LPBYTE bits,
|
2010-08-01 12:17:35 +00:00
|
|
|
PBITMAPINFO data,
|
2009-06-10 00:23:15 +00:00
|
|
|
DWORD coloruse)
|
2001-03-31 15:35:08 +00:00
|
|
|
{
|
2009-06-10 00:23:15 +00:00
|
|
|
HBITMAP handle;
|
|
|
|
BOOL fColor;
|
2001-03-31 15:35:08 +00:00
|
|
|
|
2009-06-10 00:23:15 +00:00
|
|
|
// Check if we should create a monochrome or color bitmap. We create a monochrome bitmap only if it has exactly 2
|
|
|
|
// colors, which are black followed by white, nothing else. In all other cases, we create a color bitmap.
|
2001-03-31 15:35:08 +00:00
|
|
|
|
2009-06-10 00:23:15 +00:00
|
|
|
if (bpp != 1) fColor = TRUE;
|
|
|
|
else if ((coloruse != DIB_RGB_COLORS) || (init != CBM_INIT) || !data) fColor = FALSE;
|
|
|
|
else
|
2001-08-28 18:16:32 +00:00
|
|
|
{
|
2010-08-01 12:17:35 +00:00
|
|
|
const RGBQUAD *rgb = (RGBQUAD*)((PBYTE)data + data->bmiHeader.biSize);
|
2010-06-09 00:08:50 +00:00
|
|
|
DWORD col = RGB(rgb->rgbRed, rgb->rgbGreen, rgb->rgbBlue);
|
2004-03-15 22:06:55 +00:00
|
|
|
|
2010-06-09 00:08:50 +00:00
|
|
|
// Check if the first color of the colormap is black
|
|
|
|
if ((col == RGB(0, 0, 0)))
|
2009-06-10 00:23:15 +00:00
|
|
|
{
|
2010-06-09 00:08:50 +00:00
|
|
|
rgb++;
|
|
|
|
col = RGB(rgb->rgbRed, rgb->rgbGreen, rgb->rgbBlue);
|
2009-06-10 00:23:15 +00:00
|
|
|
|
2010-06-09 00:08:50 +00:00
|
|
|
// If the second color is white, create a monochrome bitmap
|
|
|
|
fColor = (col != RGB(0xff,0xff,0xff));
|
2009-06-10 00:23:15 +00:00
|
|
|
}
|
2010-06-09 00:08:50 +00:00
|
|
|
else fColor = TRUE;
|
2009-01-28 13:55:37 +00:00
|
|
|
}
|
|
|
|
|
2009-06-10 00:23:15 +00:00
|
|
|
// Now create the bitmap
|
|
|
|
if (fColor)
|
|
|
|
{
|
|
|
|
handle = IntCreateCompatibleBitmap(Dc, width, height);
|
2001-08-28 18:16:32 +00:00
|
|
|
}
|
2009-01-28 13:55:37 +00:00
|
|
|
else
|
|
|
|
{
|
[WIN32K]
Rewrite the bitmap API. There were a lot of bugs. NtGdiCreateBitmap allowed a negative height, leading to either topdown or bottomup bitmaps, a behaviour that Windows doesn't have. The function copied the bitmap bits directly from the caller to the bitmap using RtlCopyMemory, ignoring different scanline length and direction (resulting in bitmaps being upside down), not SEH protected. This function (IntSetBitmapBits) is replaced by a better solution UnsafeSetBitmapBits, that takes these things into account. The name is chosen to give a hint that the function can/should be SEH protected. IntSetBitmapBits is still there, as its retarded behaviour is actually required in some places. There were also IntCreateBitmap and IntGdiCreateBitmap, now both being replaced by GreCreateBitmap. The code that set the palette is removed, as it's already done in SURFACE_AllocSurface, here gpalRGB is replaced with gpalBGR, fixing some inverted color issues. The alignment correction in SURFACE_bSetBitmapBits is reapplied, now that the callers are behaving as they are supposed to do.
svn path=/branches/reactos-yarotows/; revision=47641
2010-06-06 22:01:41 +00:00
|
|
|
handle = GreCreateBitmap(width,
|
|
|
|
height,
|
|
|
|
1,
|
|
|
|
1,
|
|
|
|
NULL);
|
2009-06-10 00:23:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (height < 0)
|
|
|
|
height = -height;
|
|
|
|
|
|
|
|
if (NULL != handle && CBM_INIT == init)
|
|
|
|
{
|
2010-07-25 11:35:45 +00:00
|
|
|
IntSetDIBits(Dc, handle, 0, height, bits, data, coloruse);
|
2009-06-10 00:23:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return handle;
|
2001-03-31 15:35:08 +00:00
|
|
|
}
|
|
|
|
|
2004-03-15 22:06:55 +00:00
|
|
|
// The CreateDIBitmap function creates a device-dependent bitmap (DDB) from a DIB and, optionally, sets the bitmap bits
|
|
|
|
// The DDB that is created will be whatever bit depth your reference DC is
|
2008-03-30 22:37:42 +00:00
|
|
|
HBITMAP
|
|
|
|
APIENTRY
|
2009-06-10 00:23:15 +00:00
|
|
|
NtGdiCreateDIBitmapInternal(
|
|
|
|
IN HDC hDc,
|
|
|
|
IN INT cx,
|
|
|
|
IN INT cy,
|
|
|
|
IN DWORD fInit,
|
|
|
|
IN OPTIONAL LPBYTE pjInit,
|
|
|
|
IN OPTIONAL LPBITMAPINFO pbmi,
|
|
|
|
IN DWORD iUsage,
|
|
|
|
IN UINT cjMaxInitInfo,
|
|
|
|
IN UINT cjMaxBits,
|
|
|
|
IN FLONG fl,
|
|
|
|
IN HANDLE hcmXform)
|
2004-03-15 22:06:55 +00:00
|
|
|
{
|
2010-06-09 00:08:50 +00:00
|
|
|
NTSTATUS Status = STATUS_SUCCESS;
|
2011-02-28 23:46:02 +00:00
|
|
|
PBYTE safeBits = NULL;
|
|
|
|
HBITMAP hbmResult = NULL;
|
|
|
|
|
|
|
|
if(pjInit && (fInit == CBM_INIT))
|
|
|
|
{
|
|
|
|
safeBits = ExAllocatePoolWithTag(PagedPool, cjMaxBits, TAG_DIB);
|
|
|
|
if(!safeBits)
|
|
|
|
{
|
|
|
|
EngSetLastError(ERROR_NOT_ENOUGH_MEMORY);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
}
|
2010-06-09 00:08:50 +00:00
|
|
|
|
|
|
|
_SEH2_TRY
|
|
|
|
{
|
2010-08-01 12:17:35 +00:00
|
|
|
if(pbmi) ProbeForRead(pbmi, cjMaxInitInfo, 1);
|
2010-09-01 22:36:00 +00:00
|
|
|
if(pjInit && (fInit == CBM_INIT))
|
2011-02-28 23:46:02 +00:00
|
|
|
{
|
|
|
|
ProbeForRead(pjInit, cjMaxBits, 1);
|
|
|
|
RtlCopyMemory(safeBits, pjInit, cjMaxBits);
|
|
|
|
}
|
2010-06-09 00:08:50 +00:00
|
|
|
}
|
|
|
|
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
|
|
|
|
{
|
|
|
|
Status = _SEH2_GetExceptionCode();
|
|
|
|
}
|
|
|
|
_SEH2_END
|
|
|
|
|
|
|
|
if(!NT_SUCCESS(Status))
|
|
|
|
{
|
|
|
|
SetLastNtError(Status);
|
2011-02-28 23:46:02 +00:00
|
|
|
goto cleanup;
|
2010-06-09 00:08:50 +00:00
|
|
|
}
|
2009-06-10 00:23:15 +00:00
|
|
|
|
2010-09-01 22:36:00 +00:00
|
|
|
hbmResult = GreCreateDIBitmapInternal(hDc,
|
2011-02-28 23:46:02 +00:00
|
|
|
cx,
|
|
|
|
cy,
|
|
|
|
fInit,
|
2010-09-01 22:36:00 +00:00
|
|
|
safeBits,
|
|
|
|
pbmi,
|
|
|
|
iUsage,
|
|
|
|
fl,
|
|
|
|
hcmXform);
|
|
|
|
|
|
|
|
cleanup:
|
2011-02-28 23:46:02 +00:00
|
|
|
if (safeBits) ExFreePoolWithTag(safeBits, TAG_DIB);
|
|
|
|
return hbmResult;
|
2010-06-10 11:36:20 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
HBITMAP
|
|
|
|
FASTCALL
|
|
|
|
GreCreateDIBitmapInternal(
|
|
|
|
IN HDC hDc,
|
|
|
|
IN INT cx,
|
|
|
|
IN INT cy,
|
|
|
|
IN DWORD fInit,
|
|
|
|
IN OPTIONAL LPBYTE pjInit,
|
2010-08-01 12:17:35 +00:00
|
|
|
IN OPTIONAL PBITMAPINFO pbmi,
|
2010-06-10 11:36:20 +00:00
|
|
|
IN DWORD iUsage,
|
|
|
|
IN FLONG fl,
|
|
|
|
IN HANDLE hcmXform)
|
|
|
|
{
|
|
|
|
PDC Dc;
|
|
|
|
HBITMAP Bmp;
|
|
|
|
WORD bpp;
|
2010-06-10 14:32:05 +00:00
|
|
|
HDC hdcDest;
|
2010-06-10 11:36:20 +00:00
|
|
|
|
2010-06-10 14:32:05 +00:00
|
|
|
if (!hDc) /* 1bpp monochrome bitmap */
|
2011-02-28 23:46:02 +00:00
|
|
|
{
|
|
|
|
// Should use System Bitmap DC hSystemBM, with CreateCompatibleDC for this.
|
2010-08-02 14:45:51 +00:00
|
|
|
hdcDest = NtGdiCreateCompatibleDC(0);
|
2010-06-10 14:32:05 +00:00
|
|
|
if(!hdcDest)
|
2009-06-10 00:23:15 +00:00
|
|
|
{
|
|
|
|
return NULL;
|
|
|
|
}
|
2010-06-10 14:32:05 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
hdcDest = hDc;
|
|
|
|
}
|
2006-09-03 18:16:08 +00:00
|
|
|
|
2010-06-10 14:32:05 +00:00
|
|
|
Dc = DC_LockDc(hdcDest);
|
|
|
|
if (!Dc)
|
|
|
|
{
|
2010-12-25 11:01:14 +00:00
|
|
|
EngSetLastError(ERROR_INVALID_HANDLE);
|
2010-06-10 14:32:05 +00:00
|
|
|
return NULL;
|
2009-06-10 00:23:15 +00:00
|
|
|
}
|
2010-06-10 14:32:05 +00:00
|
|
|
/* It's OK to set bpp=0 here, as IntCreateDIBitmap will create a compatible Bitmap
|
|
|
|
* if bpp != 1 and ignore the real value that was passed */
|
|
|
|
if (pbmi)
|
2010-08-01 12:17:35 +00:00
|
|
|
bpp = pbmi->bmiHeader.biBitCount;
|
2010-06-10 14:32:05 +00:00
|
|
|
else
|
|
|
|
bpp = 0;
|
|
|
|
Bmp = IntCreateDIBitmap(Dc, cx, cy, bpp, fInit, pjInit, pbmi, iUsage);
|
|
|
|
DC_UnlockDc(Dc);
|
|
|
|
|
|
|
|
if(!hDc)
|
2009-06-10 00:23:15 +00:00
|
|
|
{
|
2010-06-10 14:32:05 +00:00
|
|
|
NtGdiDeleteObjectApp(hdcDest);
|
2009-06-10 00:23:15 +00:00
|
|
|
}
|
|
|
|
return Bmp;
|
2004-03-15 22:06:55 +00:00
|
|
|
}
|
|
|
|
|
2008-03-30 22:37:42 +00:00
|
|
|
|
2009-06-10 00:23:15 +00:00
|
|
|
HBITMAP
|
|
|
|
APIENTRY
|
|
|
|
NtGdiCreateDIBSection(
|
|
|
|
IN HDC hDC,
|
|
|
|
IN OPTIONAL HANDLE hSection,
|
|
|
|
IN DWORD dwOffset,
|
2010-07-29 16:12:43 +00:00
|
|
|
IN BITMAPINFO* bmi,
|
2009-06-10 00:23:15 +00:00
|
|
|
IN DWORD Usage,
|
|
|
|
IN UINT cjHeader,
|
|
|
|
IN FLONG fl,
|
|
|
|
IN ULONG_PTR dwColorSpace,
|
|
|
|
OUT PVOID *Bits)
|
2001-03-31 15:35:08 +00:00
|
|
|
{
|
2009-06-10 00:23:15 +00:00
|
|
|
HBITMAP hbitmap = 0;
|
|
|
|
DC *dc;
|
|
|
|
BOOL bDesktopDC = FALSE;
|
2011-02-28 23:46:02 +00:00
|
|
|
NTSTATUS Status = STATUS_SUCCESS;
|
2009-06-10 00:23:15 +00:00
|
|
|
|
|
|
|
if (!bmi) return hbitmap; // Make sure.
|
|
|
|
|
2011-02-28 23:46:02 +00:00
|
|
|
_SEH2_TRY
|
2010-07-25 11:35:45 +00:00
|
|
|
{
|
2010-07-29 16:12:43 +00:00
|
|
|
ProbeForRead(&bmi->bmiHeader.biSize, sizeof(DWORD), 1);
|
2011-02-28 23:46:02 +00:00
|
|
|
ProbeForRead(bmi, bmi->bmiHeader.biSize, 1);
|
|
|
|
ProbeForRead(bmi, DIB_BitmapInfoSize(bmi, Usage), 1);
|
2010-07-25 11:35:45 +00:00
|
|
|
}
|
|
|
|
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
|
|
|
|
{
|
|
|
|
Status = _SEH2_GetExceptionCode();
|
|
|
|
}
|
|
|
|
_SEH2_END
|
|
|
|
|
|
|
|
if(!NT_SUCCESS(Status))
|
|
|
|
{
|
|
|
|
SetLastNtError(Status);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2009-06-10 00:23:15 +00:00
|
|
|
// If the reference hdc is null, take the desktop dc
|
|
|
|
if (hDC == 0)
|
|
|
|
{
|
|
|
|
hDC = NtGdiCreateCompatibleDC(0);
|
|
|
|
bDesktopDC = TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((dc = DC_LockDc(hDC)))
|
|
|
|
{
|
|
|
|
hbitmap = DIB_CreateDIBSection(dc,
|
2010-07-29 16:12:43 +00:00
|
|
|
bmi,
|
2009-06-10 00:23:15 +00:00
|
|
|
Usage,
|
|
|
|
Bits,
|
|
|
|
hSection,
|
|
|
|
dwOffset,
|
|
|
|
0);
|
|
|
|
DC_UnlockDc(dc);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2010-12-25 11:01:14 +00:00
|
|
|
EngSetLastError(ERROR_INVALID_HANDLE);
|
2009-06-10 00:23:15 +00:00
|
|
|
}
|
2001-03-31 15:35:08 +00:00
|
|
|
|
2009-06-10 00:23:15 +00:00
|
|
|
if (bDesktopDC)
|
|
|
|
NtGdiDeleteObjectApp(hDC);
|
2001-03-31 15:35:08 +00:00
|
|
|
|
2009-06-10 00:23:15 +00:00
|
|
|
return hbitmap;
|
2001-03-31 15:35:08 +00:00
|
|
|
}
|
|
|
|
|
2009-06-10 00:23:15 +00:00
|
|
|
HBITMAP
|
|
|
|
APIENTRY
|
2003-05-18 17:16:18 +00:00
|
|
|
DIB_CreateDIBSection(
|
2009-06-10 00:23:15 +00:00
|
|
|
PDC dc,
|
2010-07-29 16:12:43 +00:00
|
|
|
CONST BITMAPINFO *bmi,
|
2009-06-10 00:23:15 +00:00
|
|
|
UINT usage,
|
|
|
|
LPVOID *bits,
|
|
|
|
HANDLE section,
|
|
|
|
DWORD offset,
|
|
|
|
DWORD ovr_pitch)
|
2001-03-31 15:35:08 +00:00
|
|
|
{
|
2009-06-10 00:23:15 +00:00
|
|
|
HBITMAP res = 0;
|
|
|
|
SURFACE *bmp = NULL;
|
|
|
|
void *mapBits = NULL;
|
2010-05-12 22:56:24 +00:00
|
|
|
HPALETTE hpal ;
|
2009-06-10 00:23:15 +00:00
|
|
|
|
|
|
|
// Fill BITMAP32 structure with DIB data
|
2010-07-29 16:12:43 +00:00
|
|
|
CONST BITMAPINFOHEADER *bi = &bmi->bmiHeader;
|
2009-06-10 00:23:15 +00:00
|
|
|
INT effHeight;
|
|
|
|
ULONG totalSize;
|
|
|
|
BITMAP bm;
|
2011-09-11 16:56:56 +00:00
|
|
|
//SIZEL Size;
|
2009-06-10 00:23:15 +00:00
|
|
|
HANDLE hSecure;
|
|
|
|
|
|
|
|
DPRINT("format (%ld,%ld), planes %d, bpp %d, size %ld, colors %ld (%s)\n",
|
2010-07-29 16:12:43 +00:00
|
|
|
bi->biWidth, bi->biHeight, bi->biPlanes, bi->biBitCount,
|
|
|
|
bi->biSizeImage, bi->biClrUsed, usage == DIB_PAL_COLORS? "PAL" : "RGB");
|
2009-06-10 00:23:15 +00:00
|
|
|
|
|
|
|
/* CreateDIBSection should fail for compressed formats */
|
2010-07-29 16:12:43 +00:00
|
|
|
if (bi->biCompression == BI_RLE4 || bi->biCompression == BI_RLE8)
|
2009-06-10 00:23:15 +00:00
|
|
|
{
|
2011-03-07 10:00:27 +00:00
|
|
|
DPRINT1("no compressed format allowed\n");
|
2009-06-10 00:23:15 +00:00
|
|
|
return (HBITMAP)NULL;
|
|
|
|
}
|
|
|
|
|
2010-07-29 16:12:43 +00:00
|
|
|
effHeight = bi->biHeight >= 0 ? bi->biHeight : -bi->biHeight;
|
2009-06-10 00:23:15 +00:00
|
|
|
bm.bmType = 0;
|
2010-07-29 16:12:43 +00:00
|
|
|
bm.bmWidth = bi->biWidth;
|
2009-06-10 00:23:15 +00:00
|
|
|
bm.bmHeight = effHeight;
|
2010-09-01 16:52:23 +00:00
|
|
|
bm.bmWidthBytes = ovr_pitch ? ovr_pitch : WIDTH_BYTES_ALIGN32(bm.bmWidth, bi->biBitCount);
|
2009-06-10 00:23:15 +00:00
|
|
|
|
2010-07-29 16:12:43 +00:00
|
|
|
bm.bmPlanes = bi->biPlanes;
|
|
|
|
bm.bmBitsPixel = bi->biBitCount;
|
2009-06-10 00:23:15 +00:00
|
|
|
bm.bmBits = NULL;
|
|
|
|
|
|
|
|
// Get storage location for DIB bits. Only use biSizeImage if it's valid and
|
|
|
|
// we're dealing with a compressed bitmap. Otherwise, use width * height.
|
2011-01-12 00:26:20 +00:00
|
|
|
totalSize = bi->biSizeImage && bi->biCompression != BI_RGB && bi->biCompression != BI_BITFIELDS
|
2010-07-29 16:12:43 +00:00
|
|
|
? bi->biSizeImage : (ULONG)(bm.bmWidthBytes * effHeight);
|
2009-06-10 00:23:15 +00:00
|
|
|
|
|
|
|
if (section)
|
|
|
|
{
|
|
|
|
SYSTEM_BASIC_INFORMATION Sbi;
|
|
|
|
NTSTATUS Status;
|
|
|
|
DWORD mapOffset;
|
|
|
|
LARGE_INTEGER SectionOffset;
|
|
|
|
SIZE_T mapSize;
|
|
|
|
|
|
|
|
Status = ZwQuerySystemInformation(SystemBasicInformation,
|
|
|
|
&Sbi,
|
|
|
|
sizeof Sbi,
|
|
|
|
0);
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
{
|
2011-03-07 10:00:27 +00:00
|
|
|
DPRINT1("ZwQuerySystemInformation failed (0x%lx)\n", Status);
|
2009-06-10 00:23:15 +00:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
mapOffset = offset - (offset % Sbi.AllocationGranularity);
|
2010-07-29 16:12:43 +00:00
|
|
|
mapSize = bi->biSizeImage + (offset - mapOffset);
|
2009-06-10 00:23:15 +00:00
|
|
|
|
|
|
|
SectionOffset.LowPart = mapOffset;
|
|
|
|
SectionOffset.HighPart = 0;
|
|
|
|
|
|
|
|
Status = ZwMapViewOfSection(section,
|
|
|
|
NtCurrentProcess(),
|
|
|
|
&mapBits,
|
|
|
|
0,
|
|
|
|
0,
|
|
|
|
&SectionOffset,
|
|
|
|
&mapSize,
|
|
|
|
ViewShare,
|
|
|
|
0,
|
|
|
|
PAGE_READWRITE);
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
{
|
2011-03-07 10:00:27 +00:00
|
|
|
DPRINT1("ZwMapViewOfSection failed (0x%lx)\n", Status);
|
2010-12-25 11:01:14 +00:00
|
|
|
EngSetLastError(ERROR_INVALID_PARAMETER);
|
2009-06-10 00:23:15 +00:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (mapBits) bm.bmBits = (char *)mapBits + (offset - mapOffset);
|
|
|
|
}
|
|
|
|
else if (ovr_pitch && offset)
|
|
|
|
bm.bmBits = (LPVOID) offset;
|
|
|
|
else
|
|
|
|
{
|
|
|
|
offset = 0;
|
|
|
|
bm.bmBits = EngAllocUserMem(totalSize, 0);
|
2011-03-07 10:00:27 +00:00
|
|
|
if(!bm.bmBits)
|
|
|
|
{
|
|
|
|
DPRINT1("Failed to allocate memory\n");
|
|
|
|
goto cleanup;
|
|
|
|
}
|
2009-06-10 00:23:15 +00:00
|
|
|
}
|
2001-03-31 15:35:08 +00:00
|
|
|
|
2009-01-09 02:06:39 +00:00
|
|
|
// hSecure = MmSecureVirtualMemory(bm.bmBits, totalSize, PAGE_READWRITE);
|
2009-06-10 00:23:15 +00:00
|
|
|
hSecure = (HANDLE)0x1; // HACK OF UNIMPLEMENTED KERNEL STUFF !!!!
|
2009-01-09 02:06:39 +00:00
|
|
|
|
2009-06-10 00:23:15 +00:00
|
|
|
if (usage == DIB_PAL_COLORS)
|
2009-12-27 13:02:19 +00:00
|
|
|
{
|
2011-02-28 23:46:02 +00:00
|
|
|
if(dc)
|
|
|
|
{
|
2011-04-18 19:09:05 +00:00
|
|
|
PPALETTE ppalDc;
|
|
|
|
ppalDc = PALETTE_ShareLockPalette(dc->dclevel.hpal);
|
|
|
|
hpal = DIB_MapPaletteColors(ppalDc, bmi);
|
|
|
|
PALETTE_ShareUnlockPalette(ppalDc);
|
2011-02-28 23:46:02 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* For DIB Brushes */
|
|
|
|
DPRINT1("FIXME : Unsupported DIB_PAL_COLORS without a DC to map colors.\n");
|
|
|
|
/* HACK */
|
|
|
|
hpal = (HPALETTE) 0xFFFFFFFF;
|
|
|
|
}
|
2009-12-27 13:02:19 +00:00
|
|
|
}
|
2010-08-05 21:12:57 +00:00
|
|
|
else
|
2011-02-28 23:46:02 +00:00
|
|
|
{
|
2010-08-01 12:17:35 +00:00
|
|
|
hpal = BuildDIBPalette(bmi);
|
2011-02-28 23:46:02 +00:00
|
|
|
}
|
2010-08-01 12:17:35 +00:00
|
|
|
|
2011-02-28 23:46:02 +00:00
|
|
|
if(!hpal)
|
|
|
|
{
|
|
|
|
DPRINT1("Error : Could not create a palette for the DIB.\n");
|
|
|
|
goto cleanup;
|
|
|
|
}
|
2001-03-31 15:35:08 +00:00
|
|
|
|
2008-10-01 10:05:02 +00:00
|
|
|
// Create Device Dependent Bitmap and add DIB pointer
|
2011-09-11 16:56:56 +00:00
|
|
|
//Size.cx = bm.bmWidth;
|
|
|
|
//Size.cy = abs(bm.bmHeight);
|
2010-06-07 15:55:03 +00:00
|
|
|
res = GreCreateBitmapEx(bm.bmWidth,
|
|
|
|
abs(bm.bmHeight),
|
|
|
|
bm.bmWidthBytes,
|
2010-07-29 16:12:43 +00:00
|
|
|
BitmapFormat(bi->biBitCount * bi->biPlanes, bi->biCompression),
|
2010-06-07 15:55:03 +00:00
|
|
|
BMF_DONTCACHE | BMF_USERMEM | BMF_NOZEROINIT |
|
2011-03-09 15:46:13 +00:00
|
|
|
((bi->biHeight < 0) ? BMF_TOPDOWN : 0),
|
2010-07-29 16:12:43 +00:00
|
|
|
bi->biSizeImage,
|
2010-08-02 00:53:25 +00:00
|
|
|
bm.bmBits,
|
2011-02-28 23:46:02 +00:00
|
|
|
0);
|
2009-06-10 00:23:15 +00:00
|
|
|
if (!res)
|
2008-11-20 15:11:43 +00:00
|
|
|
{
|
2011-03-07 10:00:27 +00:00
|
|
|
DPRINT1("GreCreateBitmapEx failed\n");
|
2010-12-25 11:01:14 +00:00
|
|
|
EngSetLastError(ERROR_NO_SYSTEM_RESOURCES);
|
2010-07-25 11:35:45 +00:00
|
|
|
goto cleanup;
|
2008-11-20 15:11:43 +00:00
|
|
|
}
|
2011-04-15 15:29:08 +00:00
|
|
|
bmp = SURFACE_ShareLockSurface(res); // HACK
|
2003-08-31 07:56:24 +00:00
|
|
|
if (NULL == bmp)
|
2008-11-20 15:11:43 +00:00
|
|
|
{
|
2011-03-07 10:00:27 +00:00
|
|
|
DPRINT1("SURFACE_LockSurface failed\n");
|
2011-02-28 23:46:02 +00:00
|
|
|
EngSetLastError(ERROR_INVALID_HANDLE);
|
2010-07-25 11:35:45 +00:00
|
|
|
goto cleanup;
|
2008-11-20 15:11:43 +00:00
|
|
|
}
|
2002-09-24 20:22:10 +00:00
|
|
|
|
2008-11-20 15:11:43 +00:00
|
|
|
/* WINE NOTE: WINE makes use of a colormap, which is a color translation
|
|
|
|
table between the DIB and the X physical device. Obviously,
|
|
|
|
this is left out of the ReactOS implementation. Instead,
|
|
|
|
we call NtGdiSetDIBColorTable. */
|
2009-01-28 11:55:56 +00:00
|
|
|
bmp->hDIBSection = section;
|
|
|
|
bmp->hSecure = hSecure;
|
|
|
|
bmp->dwOffset = offset;
|
2010-06-05 21:19:41 +00:00
|
|
|
bmp->flags = API_BITMAP;
|
2010-07-29 16:12:43 +00:00
|
|
|
bmp->biClrImportant = bi->biClrImportant;
|
2011-01-12 01:01:30 +00:00
|
|
|
bmp->SurfObj.fjBitmap &= ~BMF_DONT_FREE;
|
2009-01-28 11:55:56 +00:00
|
|
|
|
2011-02-28 23:46:02 +00:00
|
|
|
/* HACK */
|
|
|
|
if(hpal != (HPALETTE)0xFFFFFFFF)
|
|
|
|
{
|
|
|
|
bmp->ppal = PALETTE_ShareLockPalette(hpal);
|
|
|
|
/* Lazy delete hpal, it will be freed at surface release */
|
|
|
|
GreDeleteObject(hpal);
|
|
|
|
}
|
2010-05-12 22:56:24 +00:00
|
|
|
|
2009-06-10 00:23:15 +00:00
|
|
|
// Clean up in case of errors
|
2010-07-25 11:35:45 +00:00
|
|
|
cleanup:
|
2009-06-10 00:23:15 +00:00
|
|
|
if (!res || !bmp || !bm.bmBits)
|
|
|
|
{
|
|
|
|
DPRINT("got an error res=%08x, bmp=%p, bm.bmBits=%p\n", res, bmp, bm.bmBits);
|
|
|
|
if (bm.bmBits)
|
|
|
|
{
|
|
|
|
// MmUnsecureVirtualMemory(hSecure); // FIXME: Implement this!
|
|
|
|
if (section)
|
|
|
|
{
|
|
|
|
ZwUnmapViewOfSection(NtCurrentProcess(), mapBits);
|
|
|
|
bm.bmBits = NULL;
|
|
|
|
}
|
2011-02-28 23:46:02 +00:00
|
|
|
else if (!offset)
|
|
|
|
EngFreeUserMem(bm.bmBits), bm.bmBits = NULL;
|
2009-06-10 00:23:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (bmp)
|
|
|
|
bmp = NULL;
|
|
|
|
|
|
|
|
if (res)
|
|
|
|
{
|
[WIN32K]
Rewrite of the GDI handle manager
- The old handle manager used a completely retarded spinlock in combination with KeDelayExecutionThread() for both exclusive
and shared locks. This is probably the most uneffective algorithm possible. It was also duplicating code everywhere and it was a overall mess It
is now replaced with a lock-free reference counter for shared locks and a pushlock for exclusive locks. -> Better performance and scalability.
- Allocate user mode object attributes from the new gdi pool. This way, we don't need any caching, since the pool serves as a cache. Its also
much faster and uses much less memory.
- Allow object allocations of different size, instead of fixed size from a table. This way a single allocation can take care of actual needs.
- Allow allcoating objects without a handle and insert them into the handle table later
- Properly synchronize the process GDIHandleCount. Now gdiview and taskmanager show the correct number of gdi handles.
- Implement a new event tracking system, that is capable of tracking all reverences and locks of objects and pool allocations to help track
possible leaks
- Make sure that all objects of a process are deleted in cleanup
- Make sure all usermode memory allocations are freed, when cleaning up the process pool.
- Make sure that each object type is using the correct type of lock (either shared or exclusive, not a mixture)
- Fix some object / reference leaks
- Lots of inferface improvements
- Use global variables for certain things instead of members in the mapped gdi handle table
- Make IntSysCreateRectpRgn create a region without a handle
- Fix detection od source and mask use in GreStretchBltMask
- Use GDIOBJ_bLockMultipleObjects in NtGdiCombineRegion to avoid possible deadlocks
- Fix NtGdiAbortPath to reset DCPATH_ACTIVE flag in the dc and only bail out on error, instead of always
- Replace DC_AllocateDcAttr and DC_AllocDcAttr with DC_bAllocDcAttr using the new user mode pool
- Remove DCU_SyncDcAttrtoUser and DCU_SynchDcAttrtoUser. Those functions were unused and didn't do anything useful anyway,
- Replace IntGdiSetDCOwnerEx and DC_SetOwnership with GreSetDCOwner, remove unused NoSetBrush parameter
- Replace GDIOBJ_bValidateHandle and IsObjectDead with GreIsHandleValid
- Chage GDIOBJ_bLockMultipleObjects: pass object type, return a BOOL, whether all objects could be locked, cleanup on failure
svn path=/trunk/; revision=51470
2011-04-28 08:26:46 +00:00
|
|
|
GreDeleteObject(res);
|
2009-06-10 00:23:15 +00:00
|
|
|
res = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (bmp)
|
|
|
|
{
|
2011-04-15 15:29:08 +00:00
|
|
|
SURFACE_ShareUnlockSurface(bmp);
|
2009-06-10 00:23:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Return BITMAP handle and storage location
|
|
|
|
if (NULL != bm.bmBits && NULL != bits)
|
|
|
|
{
|
|
|
|
*bits = bm.bmBits;
|
|
|
|
}
|
2002-09-24 20:22:10 +00:00
|
|
|
|
2009-06-10 00:23:15 +00:00
|
|
|
return res;
|
2001-03-31 15:35:08 +00:00
|
|
|
}
|
|
|
|
|
2010-07-29 16:12:43 +00:00
|
|
|
/***********************************************************************
|
|
|
|
* DIB_GetBitmapInfo
|
|
|
|
*
|
|
|
|
* Get the info from a bitmap header.
|
|
|
|
* Return 0 for COREHEADER, 1 for INFOHEADER, -1 for error.
|
|
|
|
*/
|
2010-08-05 21:12:57 +00:00
|
|
|
int
|
2010-07-29 16:12:43 +00:00
|
|
|
FASTCALL
|
|
|
|
DIB_GetBitmapInfo( const BITMAPINFOHEADER *header, LONG *width,
|
2011-02-28 23:46:02 +00:00
|
|
|
LONG *height, WORD *planes, WORD *bpp, DWORD *compr, DWORD *size )
|
2010-07-29 16:12:43 +00:00
|
|
|
{
|
|
|
|
if (header->biSize == sizeof(BITMAPCOREHEADER))
|
|
|
|
{
|
|
|
|
const BITMAPCOREHEADER *core = (const BITMAPCOREHEADER *)header;
|
|
|
|
*width = core->bcWidth;
|
|
|
|
*height = core->bcHeight;
|
|
|
|
*planes = core->bcPlanes;
|
|
|
|
*bpp = core->bcBitCount;
|
2010-08-05 21:12:57 +00:00
|
|
|
*compr = BI_RGB;
|
2010-07-29 16:12:43 +00:00
|
|
|
*size = 0;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
if (header->biSize >= sizeof(BITMAPINFOHEADER)) /* assume BITMAPINFOHEADER */
|
|
|
|
{
|
|
|
|
*width = header->biWidth;
|
|
|
|
*height = header->biHeight;
|
|
|
|
*planes = header->biPlanes;
|
|
|
|
*bpp = header->biBitCount;
|
|
|
|
*compr = header->biCompression;
|
|
|
|
*size = header->biSizeImage;
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
DPRINT1("(%d): unknown/wrong size for header\n", header->biSize );
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2001-03-31 15:35:08 +00:00
|
|
|
/***********************************************************************
|
|
|
|
* DIB_GetDIBImageBytes
|
|
|
|
*
|
|
|
|
* Return the number of bytes used to hold the image in a DIB bitmap.
|
|
|
|
* 11/16/1999 (RJJ) lifted from wine
|
|
|
|
*/
|
|
|
|
|
2009-06-10 00:23:15 +00:00
|
|
|
INT APIENTRY DIB_GetDIBImageBytes(INT width, INT height, INT depth)
|
2001-03-31 15:35:08 +00:00
|
|
|
{
|
2010-09-01 16:52:23 +00:00
|
|
|
return WIDTH_BYTES_ALIGN32(width, depth) * (height < 0 ? -height : height);
|
2001-03-31 15:35:08 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/***********************************************************************
|
|
|
|
* DIB_BitmapInfoSize
|
|
|
|
*
|
|
|
|
* Return the size of the bitmap info structure including color table.
|
|
|
|
* 11/16/1999 (RJJ) lifted from wine
|
|
|
|
*/
|
|
|
|
|
2009-06-10 00:23:15 +00:00
|
|
|
INT FASTCALL DIB_BitmapInfoSize(const BITMAPINFO * info, WORD coloruse)
|
2001-03-31 15:35:08 +00:00
|
|
|
{
|
2010-07-29 16:12:43 +00:00
|
|
|
unsigned int colors, size, masks = 0;
|
2009-06-10 00:23:15 +00:00
|
|
|
|
|
|
|
if (info->bmiHeader.biSize == sizeof(BITMAPCOREHEADER))
|
|
|
|
{
|
2010-07-29 16:12:43 +00:00
|
|
|
const BITMAPCOREHEADER *core = (const BITMAPCOREHEADER *)info;
|
2009-06-10 00:23:15 +00:00
|
|
|
colors = (core->bcBitCount <= 8) ? 1 << core->bcBitCount : 0;
|
2010-07-29 16:12:43 +00:00
|
|
|
return sizeof(BITMAPCOREHEADER) + colors *
|
2011-02-28 23:46:02 +00:00
|
|
|
((coloruse == DIB_RGB_COLORS) ? sizeof(RGBTRIPLE) : sizeof(WORD));
|
2009-06-10 00:23:15 +00:00
|
|
|
}
|
|
|
|
else /* assume BITMAPINFOHEADER */
|
|
|
|
{
|
|
|
|
colors = info->bmiHeader.biClrUsed;
|
2010-07-29 16:12:43 +00:00
|
|
|
if (colors > 256) colors = 256;
|
|
|
|
if (!colors && (info->bmiHeader.biBitCount <= 8))
|
|
|
|
colors = 1 << info->bmiHeader.biBitCount;
|
|
|
|
if (info->bmiHeader.biCompression == BI_BITFIELDS) masks = 3;
|
|
|
|
size = max( info->bmiHeader.biSize, sizeof(BITMAPINFOHEADER) + masks * sizeof(DWORD) );
|
|
|
|
return size + colors * ((coloruse == DIB_RGB_COLORS) ? sizeof(RGBQUAD) : sizeof(WORD));
|
2009-06-10 00:23:15 +00:00
|
|
|
}
|
2001-03-31 15:35:08 +00:00
|
|
|
}
|
|
|
|
|
2010-08-01 12:17:35 +00:00
|
|
|
HPALETTE
|
2009-06-10 00:23:15 +00:00
|
|
|
FASTCALL
|
2010-08-01 12:17:35 +00:00
|
|
|
DIB_MapPaletteColors(PPALETTE ppal, CONST BITMAPINFO* lpbmi)
|
2001-03-31 15:35:08 +00:00
|
|
|
{
|
2010-08-01 12:17:35 +00:00
|
|
|
PALETTEENTRY* ppalEntries;
|
2009-06-10 00:23:15 +00:00
|
|
|
ULONG nNumColors,i;
|
|
|
|
USHORT *lpIndex;
|
2011-02-28 23:46:02 +00:00
|
|
|
HPALETTE hpal;
|
2001-03-31 15:35:08 +00:00
|
|
|
|
2010-10-24 22:52:50 +00:00
|
|
|
if (!(ppal->flFlags & PAL_INDEXED))
|
2005-07-26 11:22:48 +00:00
|
|
|
{
|
2009-06-10 00:23:15 +00:00
|
|
|
return NULL;
|
2005-07-26 11:22:48 +00:00
|
|
|
}
|
|
|
|
|
2010-07-29 16:12:43 +00:00
|
|
|
nNumColors = 1 << lpbmi->bmiHeader.biBitCount;
|
|
|
|
if (lpbmi->bmiHeader.biClrUsed)
|
2003-08-28 12:35:59 +00:00
|
|
|
{
|
2010-07-29 16:12:43 +00:00
|
|
|
nNumColors = min(nNumColors, lpbmi->bmiHeader.biClrUsed);
|
2003-08-28 12:35:59 +00:00
|
|
|
}
|
2001-03-31 15:35:08 +00:00
|
|
|
|
2011-02-28 23:46:02 +00:00
|
|
|
/* Don't have more colors than we need */
|
|
|
|
nNumColors = min(ppal->NumColors, nNumColors);
|
2010-08-01 12:17:35 +00:00
|
|
|
|
|
|
|
ppalEntries = ExAllocatePoolWithTag(PagedPool, sizeof(PALETTEENTRY) * nNumColors, TAG_COLORMAP);
|
|
|
|
if (ppalEntries == NULL)
|
2009-06-10 00:23:15 +00:00
|
|
|
{
|
2010-08-01 12:17:35 +00:00
|
|
|
DPRINT1("Could not allocate palette entries\n");
|
2009-06-10 00:23:15 +00:00
|
|
|
return NULL;
|
|
|
|
}
|
2007-10-19 23:21:45 +00:00
|
|
|
|
2010-08-01 12:17:35 +00:00
|
|
|
lpIndex = (USHORT *)((PBYTE)lpbmi + lpbmi->bmiHeader.biSize);
|
2001-03-31 15:35:08 +00:00
|
|
|
|
2009-06-10 00:23:15 +00:00
|
|
|
for (i = 0; i < nNumColors; i++)
|
2003-08-28 12:35:59 +00:00
|
|
|
{
|
2010-08-01 12:17:35 +00:00
|
|
|
if (*lpIndex < ppal->NumColors)
|
2009-12-27 13:02:19 +00:00
|
|
|
{
|
2010-08-01 12:17:35 +00:00
|
|
|
ppalEntries[i] = ppal->IndexedColors[*lpIndex];
|
2009-12-27 13:02:19 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2010-08-01 12:17:35 +00:00
|
|
|
ppalEntries[i].peRed = 0;
|
2011-02-28 23:46:02 +00:00
|
|
|
ppalEntries[i].peGreen = 0;
|
|
|
|
ppalEntries[i].peBlue = 0;
|
|
|
|
ppalEntries[i].peFlags = 0;
|
2009-12-27 13:02:19 +00:00
|
|
|
}
|
2010-08-05 21:12:57 +00:00
|
|
|
|
2009-06-10 00:23:15 +00:00
|
|
|
lpIndex++;
|
2003-08-28 12:35:59 +00:00
|
|
|
}
|
2010-08-05 21:12:57 +00:00
|
|
|
|
2011-02-28 23:46:02 +00:00
|
|
|
hpal = PALETTE_AllocPalette(PAL_INDEXED, nNumColors, (ULONG*)ppalEntries, 0, 0, 0);
|
2010-08-01 12:17:35 +00:00
|
|
|
|
2011-02-28 23:46:02 +00:00
|
|
|
ExFreePoolWithTag(ppalEntries, TAG_COLORMAP);
|
2003-08-28 12:35:59 +00:00
|
|
|
|
2011-02-28 23:46:02 +00:00
|
|
|
return hpal;
|
2001-03-31 15:35:08 +00:00
|
|
|
}
|
|
|
|
|
2009-06-10 00:23:15 +00:00
|
|
|
HPALETTE
|
|
|
|
FASTCALL
|
2010-08-01 12:17:35 +00:00
|
|
|
BuildDIBPalette(CONST BITMAPINFO *bmi)
|
2001-03-31 15:35:08 +00:00
|
|
|
{
|
2009-06-10 00:23:15 +00:00
|
|
|
BYTE bits;
|
|
|
|
ULONG ColorCount;
|
|
|
|
HPALETTE hPal;
|
2010-08-01 12:17:35 +00:00
|
|
|
ULONG RedMask = 0, GreenMask = 0, BlueMask = 0;
|
2010-06-08 00:40:42 +00:00
|
|
|
PDWORD pdwColors = (PDWORD)((PBYTE)bmi + bmi->bmiHeader.biSize);
|
2011-02-28 23:46:02 +00:00
|
|
|
INT paletteType;
|
2001-03-31 15:35:08 +00:00
|
|
|
|
2009-06-10 00:23:15 +00:00
|
|
|
// Determine Bits Per Pixel
|
|
|
|
bits = bmi->bmiHeader.biBitCount;
|
2001-03-31 15:35:08 +00:00
|
|
|
|
2009-06-10 00:23:15 +00:00
|
|
|
// Determine paletteType from Bits Per Pixel
|
|
|
|
if (bits <= 8)
|
2003-08-28 12:35:59 +00:00
|
|
|
{
|
2010-08-01 12:17:35 +00:00
|
|
|
paletteType = PAL_INDEXED;
|
2009-06-10 00:23:15 +00:00
|
|
|
RedMask = GreenMask = BlueMask = 0;
|
2003-08-28 12:35:59 +00:00
|
|
|
}
|
2009-06-10 00:23:15 +00:00
|
|
|
else if (bmi->bmiHeader.biCompression == BI_BITFIELDS)
|
2008-06-26 22:22:57 +00:00
|
|
|
{
|
2010-08-01 12:17:35 +00:00
|
|
|
paletteType = PAL_BITFIELDS;
|
2011-02-12 20:30:09 +00:00
|
|
|
if (bmi->bmiHeader.biSize >= sizeof(BITMAPV4HEADER))
|
|
|
|
{
|
|
|
|
PBITMAPV4HEADER pV4Header = (PBITMAPV4HEADER)&bmi->bmiHeader;
|
|
|
|
RedMask = pV4Header->bV4RedMask;
|
|
|
|
GreenMask = pV4Header->bV4GreenMask;
|
|
|
|
BlueMask = pV4Header->bV4BlueMask;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
RedMask = pdwColors[0];
|
|
|
|
GreenMask = pdwColors[1];
|
|
|
|
BlueMask = pdwColors[2];
|
|
|
|
}
|
2008-06-26 22:22:57 +00:00
|
|
|
}
|
2009-06-10 00:23:15 +00:00
|
|
|
else
|
2003-08-28 12:35:59 +00:00
|
|
|
{
|
2010-10-24 22:52:50 +00:00
|
|
|
paletteType = PAL_BITFIELDS;
|
|
|
|
switch (bits)
|
|
|
|
{
|
2011-02-28 23:46:02 +00:00
|
|
|
case 16:
|
|
|
|
paletteType |= PAL_RGB16_555;
|
|
|
|
RedMask = 0x7C00;
|
|
|
|
GreenMask = 0x03E0;
|
|
|
|
BlueMask = 0x001F;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 24:
|
|
|
|
case 32:
|
|
|
|
paletteType |= PAL_BGR;
|
|
|
|
RedMask = 0xFF0000;
|
|
|
|
GreenMask = 0x00FF00;
|
|
|
|
BlueMask = 0x0000FF;
|
|
|
|
break;
|
2010-10-24 22:52:50 +00:00
|
|
|
}
|
2003-08-28 12:35:59 +00:00
|
|
|
}
|
2001-03-31 15:35:08 +00:00
|
|
|
|
2009-06-10 00:23:15 +00:00
|
|
|
if (bmi->bmiHeader.biClrUsed == 0)
|
2002-09-03 22:44:21 +00:00
|
|
|
{
|
2009-06-10 00:23:15 +00:00
|
|
|
ColorCount = 1 << bmi->bmiHeader.biBitCount;
|
2002-09-03 22:44:21 +00:00
|
|
|
}
|
2009-06-10 00:23:15 +00:00
|
|
|
else
|
2002-09-03 22:44:21 +00:00
|
|
|
{
|
2009-06-10 00:23:15 +00:00
|
|
|
ColorCount = bmi->bmiHeader.biClrUsed;
|
2002-09-03 22:44:21 +00:00
|
|
|
}
|
|
|
|
|
2010-08-01 12:17:35 +00:00
|
|
|
if (PAL_INDEXED == paletteType)
|
2003-08-31 07:56:24 +00:00
|
|
|
{
|
2010-06-08 00:40:42 +00:00
|
|
|
hPal = PALETTE_AllocPaletteIndexedRGB(ColorCount, (RGBQUAD*)pdwColors);
|
2003-08-31 07:56:24 +00:00
|
|
|
}
|
2009-06-10 00:23:15 +00:00
|
|
|
else
|
2003-08-31 07:56:24 +00:00
|
|
|
{
|
2010-08-01 12:17:35 +00:00
|
|
|
hPal = PALETTE_AllocPalette(paletteType, 0,
|
2010-06-08 00:40:42 +00:00
|
|
|
NULL,
|
2009-06-10 00:23:15 +00:00
|
|
|
RedMask, GreenMask, BlueMask);
|
2003-08-31 07:56:24 +00:00
|
|
|
}
|
2002-10-05 17:13:16 +00:00
|
|
|
|
2009-06-10 00:23:15 +00:00
|
|
|
return hPal;
|
2001-03-31 15:35:08 +00:00
|
|
|
}
|
2003-08-28 12:35:59 +00:00
|
|
|
|
2010-07-29 18:01:14 +00:00
|
|
|
/* Converts a BITMAPCOREINFO to a BITMAPINFO structure,
|
|
|
|
* or does nothing if it's already a BITMAPINFO (or V4 or V5) */
|
|
|
|
BITMAPINFO*
|
|
|
|
FASTCALL
|
|
|
|
DIB_ConvertBitmapInfo (CONST BITMAPINFO* pbmi, DWORD Usage)
|
|
|
|
{
|
2011-02-28 23:46:02 +00:00
|
|
|
CONST BITMAPCOREINFO* pbmci = (BITMAPCOREINFO*)pbmi;
|
|
|
|
BITMAPINFO* pNewBmi ;
|
|
|
|
UINT numColors = 0, ColorsSize = 0;
|
|
|
|
|
|
|
|
if(pbmi->bmiHeader.biSize >= sizeof(BITMAPINFOHEADER)) return (BITMAPINFO*)pbmi;
|
|
|
|
if(pbmi->bmiHeader.biSize != sizeof(BITMAPCOREHEADER)) return NULL;
|
|
|
|
|
|
|
|
if(pbmci->bmciHeader.bcBitCount <= 8)
|
|
|
|
{
|
|
|
|
numColors = 1 << pbmci->bmciHeader.bcBitCount;
|
|
|
|
if(Usage == DIB_PAL_COLORS)
|
|
|
|
{
|
|
|
|
ColorsSize = numColors * sizeof(WORD);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
ColorsSize = numColors * sizeof(RGBQUAD);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (Usage == DIB_PAL_COLORS)
|
|
|
|
{
|
|
|
|
/* Invalid at high Res */
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
pNewBmi = ExAllocatePoolWithTag(PagedPool, sizeof(BITMAPINFOHEADER) + ColorsSize, TAG_DIB);
|
|
|
|
if(!pNewBmi) return NULL;
|
|
|
|
|
|
|
|
RtlZeroMemory(pNewBmi, sizeof(BITMAPINFOHEADER) + ColorsSize);
|
|
|
|
|
|
|
|
pNewBmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
|
|
|
|
pNewBmi->bmiHeader.biBitCount = pbmci->bmciHeader.bcBitCount;
|
|
|
|
pNewBmi->bmiHeader.biWidth = pbmci->bmciHeader.bcWidth;
|
|
|
|
pNewBmi->bmiHeader.biHeight = pbmci->bmciHeader.bcHeight;
|
|
|
|
pNewBmi->bmiHeader.biPlanes = pbmci->bmciHeader.bcPlanes;
|
|
|
|
pNewBmi->bmiHeader.biCompression = BI_RGB ;
|
|
|
|
pNewBmi->bmiHeader.biSizeImage = DIB_GetDIBImageBytes(pNewBmi->bmiHeader.biWidth,
|
|
|
|
pNewBmi->bmiHeader.biHeight,
|
|
|
|
pNewBmi->bmiHeader.biBitCount);
|
|
|
|
|
|
|
|
if(Usage == DIB_PAL_COLORS)
|
|
|
|
{
|
|
|
|
RtlCopyMemory(pNewBmi->bmiColors, pbmci->bmciColors, ColorsSize);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
UINT i;
|
|
|
|
for(i=0; i<numColors; i++)
|
|
|
|
{
|
|
|
|
pNewBmi->bmiColors[i].rgbRed = pbmci->bmciColors[i].rgbtRed;
|
|
|
|
pNewBmi->bmiColors[i].rgbGreen = pbmci->bmciColors[i].rgbtGreen;
|
|
|
|
pNewBmi->bmiColors[i].rgbBlue = pbmci->bmciColors[i].rgbtBlue;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return pNewBmi ;
|
2010-07-29 18:01:14 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Frees a BITMAPINFO created with DIB_ConvertBitmapInfo */
|
|
|
|
VOID
|
|
|
|
FASTCALL
|
|
|
|
DIB_FreeConvertedBitmapInfo(BITMAPINFO* converted, BITMAPINFO* orig)
|
|
|
|
{
|
2011-02-28 23:46:02 +00:00
|
|
|
if(converted != orig)
|
|
|
|
ExFreePoolWithTag(converted, TAG_DIB);
|
2010-07-29 18:01:14 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2003-05-18 17:16:18 +00:00
|
|
|
/* EOF */
|