mirror of
https://github.com/reactos/reactos.git
synced 2025-05-28 05:28:14 +00:00
Added eng files
svn path=/trunk/; revision=1068
This commit is contained in:
parent
e1d6086025
commit
690a781452
9 changed files with 1306 additions and 39 deletions
226
reactos/subsys/win32k/eng/bitblt.c
Normal file
226
reactos/subsys/win32k/eng/bitblt.c
Normal file
|
@ -0,0 +1,226 @@
|
|||
/*
|
||||
* COPYRIGHT: See COPYING in the top level directory
|
||||
* PROJECT: ReactOS kernel
|
||||
* PURPOSE: GDI BitBlt Functions
|
||||
* FILE: subsys/win32k/eng/bitblt.c
|
||||
* PROGRAMER: Jason Filby
|
||||
* REVISION HISTORY:
|
||||
* 2/10/1999: Created
|
||||
*/
|
||||
|
||||
#include <ddk/winddi.h>
|
||||
#include <ddk/ntddk.h>
|
||||
#include "brush.h"
|
||||
#include "enum.h"
|
||||
#include "objects.h"
|
||||
|
||||
VOID BitBltCopy(SURFOBJ *DestSurf, SURFOBJ *SourceSurf,
|
||||
SURFGDI *DestGDI, SURFGDI *SourceGDI,
|
||||
PRECTL DestRect, POINTL *SourcePoint,
|
||||
ULONG Delta)
|
||||
{
|
||||
ULONG dy, leftOfSource, leftOfDest, Width, CopyPos;
|
||||
|
||||
// FIXME: Get ColorTranslation passed here and do something with it
|
||||
|
||||
leftOfSource = SourcePoint->x * SourceGDI->BytesPerPixel;
|
||||
leftOfDest = DestRect->left * DestGDI->BytesPerPixel;
|
||||
Width = (DestRect->right - DestRect->left) * DestGDI->BytesPerPixel;
|
||||
CopyPos = leftOfDest;
|
||||
|
||||
for(dy=DestRect->top; dy<DestRect->bottom; dy++)
|
||||
{
|
||||
RtlCopyMemory(DestSurf->pvBits+CopyPos,
|
||||
SourceSurf->pvBits+CopyPos,
|
||||
Width);
|
||||
|
||||
CopyPos += Delta;
|
||||
}
|
||||
}
|
||||
|
||||
BOOL EngIntersectRect(PRECTL prcDst, PRECTL prcSrc1, PRECTL prcSrc2)
|
||||
|
||||
{
|
||||
static const RECTL rclEmpty = { 0, 0, 0, 0 };
|
||||
|
||||
prcDst->left = max(prcSrc1->left, prcSrc2->left);
|
||||
prcDst->right = min(prcSrc1->right, prcSrc2->right);
|
||||
|
||||
if (prcDst->left < prcDst->right)
|
||||
{
|
||||
prcDst->top = max(prcSrc1->top, prcSrc2->top);
|
||||
prcDst->bottom = min(prcSrc1->bottom, prcSrc2->bottom);
|
||||
|
||||
if (prcDst->top < prcDst->bottom)
|
||||
return(TRUE);
|
||||
}
|
||||
|
||||
*prcDst = rclEmpty;
|
||||
|
||||
return(FALSE);
|
||||
}
|
||||
|
||||
BOOL EngBitBlt(SURFOBJ *Dest, SURFOBJ *Source,
|
||||
SURFOBJ *Mask, CLIPOBJ *ClipRegion,
|
||||
XLATEOBJ *ColorTranslation, RECTL *DestRect,
|
||||
POINTL *SourcePoint, POINTL *MaskRect,
|
||||
BRUSHOBJ *Brush, POINTL *BrushOrigin, ROP4 rop4)
|
||||
{
|
||||
BYTE clippingType;
|
||||
RECTL rclTmp;
|
||||
POINTL ptlTmp;
|
||||
RECT_ENUM RectEnum;
|
||||
BOOL EnumMore;
|
||||
SURFGDI *DestGDI, *SourceGDI;
|
||||
BOOLEAN canCopyBits;
|
||||
|
||||
// If we don't have to do anything special, we can punt to DrvCopyBits
|
||||
// if it exists
|
||||
if( (Mask == NULL) && (MaskRect == NULL) && (Brush == NULL) &&
|
||||
(BrushOrigin == NULL) && (rop4 == NULL) )
|
||||
{
|
||||
canCopyBits = TRUE;
|
||||
} else
|
||||
canCopyBits = FALSE;
|
||||
|
||||
// FIXME: Use XLATEOBJ to translate source bitmap into destination bitmap's
|
||||
// format. Call DrvDitherColor function where necessary and if available
|
||||
|
||||
// FIXME: If canCopyBits == TRUE AND the driver has a DrvCopyBits then
|
||||
// punt to EngCopyBits and not the driver's DrvCopyBits just yet so
|
||||
// that the EngCopyBits can take care of the clipping drivers
|
||||
// DrvCopyBits
|
||||
|
||||
// FIXME: Don't punt to DrvBitBlt straight away. Instead, mark a typedef'd
|
||||
// function to go there instead of the Engine's bltting function
|
||||
// so as to do the clipping for the driver
|
||||
|
||||
// Check for CopyBits or BitBlt hooks if one is not a GDI managed bitmap
|
||||
if((Dest->iType!=STYPE_BITMAP) || (Source->iType!=STYPE_BITMAP))
|
||||
{
|
||||
|
||||
// Destination surface is device managed
|
||||
if(Dest->iType!=STYPE_BITMAP)
|
||||
{
|
||||
DestGDI = AccessInternalObjectFromUserObject(Dest);
|
||||
|
||||
if ((DestGDI->CopyBits!=NULL) && (canCopyBits == TRUE))
|
||||
{
|
||||
return DestGDI->CopyBits(Dest, Source, ClipRegion,
|
||||
ColorTranslation, DestRect, SourcePoint);
|
||||
}
|
||||
|
||||
if (DestGDI->BitBlt!=NULL)
|
||||
{
|
||||
return DestGDI->BitBlt(Dest, Source, Mask, ClipRegion,
|
||||
ColorTranslation, DestRect, SourcePoint,
|
||||
MaskRect, Brush, BrushOrigin, rop4);
|
||||
}
|
||||
}
|
||||
|
||||
// Source surface is device managed
|
||||
if(Source->iType!=STYPE_BITMAP)
|
||||
{
|
||||
SourceGDI = AccessInternalObjectFromUserObject(Source);
|
||||
|
||||
if ((SourceGDI->CopyBits!=NULL) && (canCopyBits == TRUE))
|
||||
{
|
||||
return SourceGDI->CopyBits(Dest, Source, ClipRegion,
|
||||
ColorTranslation, DestRect, SourcePoint);
|
||||
}
|
||||
|
||||
if (SourceGDI->BitBlt!=NULL)
|
||||
{
|
||||
return SourceGDI->BitBlt(Dest, Source, Mask, ClipRegion,
|
||||
ColorTranslation, DestRect, SourcePoint,
|
||||
MaskRect, Brush, BrushOrigin, rop4);
|
||||
}
|
||||
|
||||
|
||||
// Should never get here, if it's not GDI managed then the device
|
||||
// should take care of it
|
||||
|
||||
// FIXME: Error message here
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
DestGDI = AccessInternalObjectFromUserObject(Dest);
|
||||
SourceGDI = AccessInternalObjectFromUserObject(Source);
|
||||
|
||||
// Determine clipping type
|
||||
if (ClipRegion == (CLIPOBJ *) NULL)
|
||||
{
|
||||
clippingType = DC_TRIVIAL;
|
||||
} else {
|
||||
clippingType = ClipRegion->iDComplexity;
|
||||
}
|
||||
|
||||
// We don't handle color translation just yet
|
||||
|
||||
if ((rop4 == 0x0000CCCC) &&
|
||||
((ColorTranslation == NULL) || (ColorTranslation->flXlate & XO_TRIVIAL)))
|
||||
{
|
||||
switch(clippingType)
|
||||
{
|
||||
case DC_TRIVIAL:
|
||||
BitBltCopy(Dest, Source,
|
||||
DestGDI, SourceGDI,
|
||||
DestRect, SourcePoint, Source->lDelta);
|
||||
|
||||
return(TRUE);
|
||||
|
||||
case DC_RECT:
|
||||
|
||||
// Clip the blt to the clip rectangle
|
||||
|
||||
EngIntersectRect(&rclTmp, DestRect, &ClipRegion->rclBounds);
|
||||
|
||||
ptlTmp.x = SourcePoint->x + rclTmp.left - DestRect->left;
|
||||
ptlTmp.y = SourcePoint->y + rclTmp.top - DestRect->top;
|
||||
|
||||
BitBltCopy(Dest, Source,
|
||||
DestGDI, SourceGDI,
|
||||
&rclTmp, &ptlTmp, Source->lDelta);
|
||||
|
||||
return(TRUE);
|
||||
|
||||
case DC_COMPLEX:
|
||||
|
||||
CLIPOBJ_cEnumStart(ClipRegion, FALSE, CT_RECTANGLES,
|
||||
CD_ANY, ENUM_RECT_LIMIT);
|
||||
|
||||
do {
|
||||
EnumMore = CLIPOBJ_bEnum(ClipRegion,(ULONG) sizeof(RectEnum),
|
||||
(PVOID) &RectEnum);
|
||||
|
||||
if (RectEnum.c > 0)
|
||||
{
|
||||
RECTL* prclEnd = &RectEnum.arcl[RectEnum.c];
|
||||
RECTL* prcl = &RectEnum.arcl[0];
|
||||
|
||||
do {
|
||||
EngIntersectRect(prcl, prcl, DestRect);
|
||||
|
||||
ptlTmp.x = SourcePoint->x + prcl->left
|
||||
- DestRect->left;
|
||||
ptlTmp.y = SourcePoint->y + prcl->top
|
||||
- DestRect->top;
|
||||
|
||||
BitBltCopy(Dest, Source,
|
||||
DestGDI, SourceGDI,
|
||||
prcl, &ptlTmp, Source->lDelta);
|
||||
|
||||
prcl++;
|
||||
|
||||
} while (prcl < prclEnd);
|
||||
}
|
||||
|
||||
} while(EnumMore);
|
||||
|
||||
return(TRUE);
|
||||
}
|
||||
}
|
||||
|
||||
return(FALSE);
|
||||
}
|
124
reactos/subsys/win32k/eng/clip.c
Normal file
124
reactos/subsys/win32k/eng/clip.c
Normal file
|
@ -0,0 +1,124 @@
|
|||
/*
|
||||
* COPYRIGHT: See COPYING in the top level directory
|
||||
* PROJECT: ReactOS kernel
|
||||
* PURPOSE: GDI Clipping Functions
|
||||
* FILE: subsys/win32k/eng/clip.c
|
||||
* PROGRAMER: Jason Filby
|
||||
* REVISION HISTORY:
|
||||
* 21/8/1999: Created
|
||||
*/
|
||||
|
||||
#include <ddk/winddi.h>
|
||||
#include <ddk/ntddk.h>
|
||||
#include "objects.h"
|
||||
#include "clip.h"
|
||||
|
||||
// FIXME: Complex clipping doesn't work
|
||||
|
||||
CLIPOBJ *EngCreateClipRegion(ULONG NumRects, RECTL Rects[],
|
||||
ULONG Mode, ULONG Options)
|
||||
{
|
||||
HCLIP NewClip;
|
||||
CLIPOBJ *ClipObj;
|
||||
CLIPGDI *ClipGDI;
|
||||
|
||||
ClipObj = EngAllocMem(FL_ZERO_MEMORY, sizeof(CLIPOBJ), NULL);
|
||||
ClipGDI = EngAllocMem(FL_ZERO_MEMORY, sizeof(CLIPGDI), NULL);
|
||||
|
||||
NewClip = CreateGDIHandle(ClipGDI, ClipObj);
|
||||
|
||||
ClipGDI->NumRegionRects = NumRects;
|
||||
ClipGDI->RegionRects = Rects;
|
||||
ClipObj->iMode = Mode;
|
||||
ClipObj->fjOptions = Options;
|
||||
ClipObj->iDComplexity = DC_TRIVIAL;
|
||||
|
||||
if(NumRects == 1)
|
||||
{
|
||||
ClipObj->iFComplexity = FC_RECT;
|
||||
ClipObj->iDComplexity = DC_RECT;
|
||||
|
||||
// FIXME: Is this correct??
|
||||
ClipObj->rclBounds = Rects[0];
|
||||
} else
|
||||
{
|
||||
ClipObj->iDComplexity = DC_COMPLEX;
|
||||
if(NumRects <= 4)
|
||||
{
|
||||
ClipObj->iFComplexity = FC_RECT4;
|
||||
} else
|
||||
{
|
||||
ClipObj->iFComplexity = FC_COMPLEX;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
VOID EngDeleteClipRegion(CLIPOBJ *ClipObj)
|
||||
{
|
||||
HCLIP HClip = AccessHandleFromUserObject(ClipObj);
|
||||
CLIPGDI *ClipGDI = AccessInternalObject(HClip);
|
||||
|
||||
EngFreeMem(ClipGDI);
|
||||
EngFreeMem(ClipObj);
|
||||
FreeGDIHandle(HClip);
|
||||
}
|
||||
|
||||
VOID EngIntersectClipRegion(CLIPOBJ *ClipObj, ULONG NumRects, RECTL *IntersectRects)
|
||||
{
|
||||
CLIPGDI *ClipGDI = AccessInternalObjectFromUserObject(ClipObj);
|
||||
|
||||
ClipGDI->NumIntersectRects = NumRects;
|
||||
ClipGDI->IntersectRects = IntersectRects;
|
||||
|
||||
if(NumRects == 1)
|
||||
{
|
||||
ClipObj->iDComplexity = DC_RECT;
|
||||
ClipObj->rclBounds = IntersectRects[0];
|
||||
} else
|
||||
{
|
||||
ClipObj->iDComplexity = DC_COMPLEX;
|
||||
ClipGDI->IntersectRects = IntersectRects;
|
||||
}
|
||||
}
|
||||
|
||||
CLIPOBJ *EngCreateClip(VOID)
|
||||
{
|
||||
return EngAllocMem(FL_ZERO_MEMORY, sizeof(CLIPOBJ), NULL);
|
||||
}
|
||||
|
||||
VOID EngDeleteClip(CLIPOBJ *ClipRegion)
|
||||
{
|
||||
EngFreeMem(ClipRegion);
|
||||
}
|
||||
|
||||
ULONG CLIPOBJ_cEnumStart(IN PCLIPOBJ ClipObj, IN BOOL ShouldDoAll,
|
||||
IN ULONG ClipType, IN ULONG BuildOrder,
|
||||
IN ULONG MaxRects)
|
||||
{
|
||||
CLIPGDI *ClipGDI = AccessInternalObjectFromUserObject(ClipObj);
|
||||
|
||||
ClipGDI->EnumPos = 0;
|
||||
ClipGDI->EnumRects.c = MaxRects;
|
||||
|
||||
// Return the number of rectangles enumerated
|
||||
if(ClipGDI->EnumRects.c>MaxRects)
|
||||
{
|
||||
ClipGDI->EnumRects.c = 0xFFFFFFFF;
|
||||
}
|
||||
|
||||
return ClipGDI->EnumRects.c;
|
||||
}
|
||||
|
||||
BOOL CLIPOBJ_bEnum(IN PCLIPOBJ ClipObj, IN ULONG ObjSize,
|
||||
OUT ULONG *EnumRects)
|
||||
{
|
||||
CLIPGDI *ClipGDI = AccessInternalObjectFromUserObject(ClipObj);
|
||||
|
||||
ClipGDI->EnumPos++;
|
||||
|
||||
if(ClipGDI->EnumPos > ClipGDI->EnumRects.c)
|
||||
{
|
||||
return FALSE;
|
||||
} else
|
||||
return TRUE;
|
||||
}
|
162
reactos/subsys/win32k/eng/copybits.c
Normal file
162
reactos/subsys/win32k/eng/copybits.c
Normal file
|
@ -0,0 +1,162 @@
|
|||
/*
|
||||
* COPYRIGHT: See COPYING in the top level directory
|
||||
* PROJECT: ReactOS kernel
|
||||
* PURPOSE: GDI EngCopyBits Function
|
||||
* FILE: subsys/win32k/eng/copybits.c
|
||||
* PROGRAMER: Jason Filby
|
||||
* REVISION HISTORY:
|
||||
* 8/18/1999: Created
|
||||
*/
|
||||
|
||||
#include <ddk/winddi.h>
|
||||
#include "objects.h"
|
||||
#include "enum.h"
|
||||
|
||||
VOID CopyBitsCopy(SURFOBJ *DestSurf, SURFOBJ *SourceSurf,
|
||||
SURFGDI *DestGDI, SURFGDI *SourceGDI,
|
||||
PRECTL DestRect, POINTL *SourcePoint,
|
||||
ULONG Delta)
|
||||
{
|
||||
ULONG dy, leftOfSource, leftOfDest, Width;
|
||||
|
||||
// FIXME: Get ColorTranslation passed here and do something with it
|
||||
|
||||
leftOfSource = SourcePoint->x * SourceGDI->BytesPerPixel;
|
||||
leftOfDest = DestRect->left * DestGDI->BytesPerPixel;
|
||||
Width = (DestRect->right - DestRect->left) * DestGDI->BytesPerPixel;
|
||||
|
||||
for(dy=DestRect->top; dy<DestRect->bottom; dy++)
|
||||
{
|
||||
memcpy(DestSurf->pvBits+Delta*dy+leftOfDest,
|
||||
SourceSurf->pvBits+Delta*dy+leftOfSource,
|
||||
Width);
|
||||
}
|
||||
}
|
||||
|
||||
BOOL EngCopyBits(SURFOBJ *Dest, SURFOBJ *Source,
|
||||
CLIPOBJ *Clip, XLATEOBJ *ColorTranslation,
|
||||
RECTL *DestRect, POINTL *SourcePoint)
|
||||
{
|
||||
SURFGDI *DestGDI, *SourceGDI;
|
||||
BYTE clippingType;
|
||||
RECTL rclTmp;
|
||||
POINTL ptlTmp;
|
||||
RECT_ENUM RectEnum;
|
||||
BOOL EnumMore;
|
||||
|
||||
// FIXME: Do color translation -- refer to eng\bitblt.c
|
||||
|
||||
// FIXME: Don't punt to the driver's DrvCopyBits immediately. Instead,
|
||||
// mark the copy block function to be DrvCopyBits instead of the
|
||||
// GDI's copy bit function so as to remove clipping from the
|
||||
// driver's responsibility
|
||||
|
||||
// If one of the surfaces isn't managed by the GDI
|
||||
if((Dest->iType!=STYPE_BITMAP) || (Source->iType!=STYPE_BITMAP))
|
||||
{
|
||||
|
||||
// Destination surface is device managed
|
||||
if(Dest->iType!=STYPE_BITMAP)
|
||||
{
|
||||
DestGDI = AccessInternalObjectFromUserObject(Dest);
|
||||
|
||||
if (DestGDI->CopyBits!=NULL)
|
||||
{
|
||||
return DestGDI->CopyBits(Dest, Source, Clip,
|
||||
ColorTranslation, DestRect, SourcePoint);
|
||||
}
|
||||
}
|
||||
|
||||
// Source surface is device managed
|
||||
if(Source->iType!=STYPE_BITMAP)
|
||||
{
|
||||
SourceGDI = AccessInternalObjectFromUserObject(Dest);
|
||||
|
||||
if (SourceGDI->CopyBits!=NULL)
|
||||
{
|
||||
return SourceGDI->CopyBits(Dest, Source, Clip,
|
||||
ColorTranslation, DestRect, SourcePoint);
|
||||
}
|
||||
}
|
||||
|
||||
// If CopyBits wasn't hooked, BitBlt must be
|
||||
return EngBitBlt(Dest, Source,
|
||||
NULL, Clip, ColorTranslation, DestRect, SourcePoint,
|
||||
NULL, NULL, NULL, NULL);
|
||||
}
|
||||
|
||||
// Determine clipping type
|
||||
if (Clip == (CLIPOBJ *) NULL)
|
||||
{
|
||||
clippingType = DC_TRIVIAL;
|
||||
} else {
|
||||
clippingType = Clip->iDComplexity;
|
||||
}
|
||||
|
||||
// We don't handle color translation just yet
|
||||
|
||||
if ((ColorTranslation == NULL) || (ColorTranslation->flXlate & XO_TRIVIAL))
|
||||
{
|
||||
switch(clippingType)
|
||||
{
|
||||
case DC_TRIVIAL:
|
||||
CopyBitsCopy(Dest, Source,
|
||||
DestGDI, SourceGDI,
|
||||
DestRect, SourcePoint, Source->lDelta);
|
||||
|
||||
return(TRUE);
|
||||
|
||||
case DC_RECT:
|
||||
|
||||
// Clip the blt to the clip rectangle
|
||||
|
||||
EngIntersectRect(&rclTmp, DestRect, &Clip->rclBounds);
|
||||
|
||||
ptlTmp.x = SourcePoint->x + rclTmp.left - DestRect->left;
|
||||
ptlTmp.y = SourcePoint->y + rclTmp.top - DestRect->top;
|
||||
|
||||
CopyBitsCopy(Dest, Source,
|
||||
DestGDI, SourceGDI,
|
||||
&rclTmp, &ptlTmp, Source->lDelta);
|
||||
|
||||
return(TRUE);
|
||||
|
||||
case DC_COMPLEX:
|
||||
|
||||
CLIPOBJ_cEnumStart(Clip, FALSE, CT_RECTANGLES,
|
||||
CD_ANY, ENUM_RECT_LIMIT);
|
||||
|
||||
do {
|
||||
EnumMore = CLIPOBJ_bEnum(Clip,(ULONG) sizeof(RectEnum),
|
||||
(PVOID) &RectEnum);
|
||||
|
||||
if (RectEnum.c > 0)
|
||||
{
|
||||
RECTL* prclEnd = &RectEnum.arcl[RectEnum.c];
|
||||
RECTL* prcl = &RectEnum.arcl[0];
|
||||
|
||||
do {
|
||||
EngIntersectRect(prcl, prcl, DestRect);
|
||||
|
||||
ptlTmp.x = SourcePoint->x + prcl->left
|
||||
- DestRect->left;
|
||||
ptlTmp.y = SourcePoint->y + prcl->top
|
||||
- DestRect->top;
|
||||
|
||||
CopyBitsCopy(Dest, Source,
|
||||
DestGDI, SourceGDI,
|
||||
prcl, &ptlTmp, Source->lDelta);
|
||||
|
||||
prcl++;
|
||||
|
||||
} while (prcl < prclEnd);
|
||||
}
|
||||
|
||||
} while(EnumMore);
|
||||
|
||||
return(TRUE);
|
||||
}
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
66
reactos/subsys/win32k/eng/handle.c
Normal file
66
reactos/subsys/win32k/eng/handle.c
Normal file
|
@ -0,0 +1,66 @@
|
|||
/*
|
||||
* COPYRIGHT: See COPYING in the top level directory
|
||||
* PROJECT: ReactOS kernel
|
||||
* PURPOSE: Manage GDI Handles
|
||||
* FILE: subsys/win32k/eng/handle.c
|
||||
* PROGRAMER: Jason Filby
|
||||
* REVISION HISTORY:
|
||||
* 29/8/1999: Created
|
||||
*/
|
||||
|
||||
#include <ddk/winddi.h>
|
||||
#include "handle.h"
|
||||
|
||||
// FIXME: Total rewrite..
|
||||
|
||||
ULONG CreateGDIHandle(PVOID InternalObject, PVOID UserObject)
|
||||
{
|
||||
ULONG NewHandle = HandleCounter++;
|
||||
|
||||
GDIHandles[NewHandle].InternalObject = InternalObject;
|
||||
GDIHandles[NewHandle].UserObject = UserObject;
|
||||
|
||||
return NewHandle;
|
||||
}
|
||||
|
||||
VOID FreeGDIHandle(ULONG Handle)
|
||||
{
|
||||
GDIHandles[Handle].InternalObject = NULL;
|
||||
GDIHandles[Handle].UserObject = NULL;
|
||||
}
|
||||
|
||||
PVOID AccessInternalObject(ULONG Handle)
|
||||
{
|
||||
return GDIHandles[Handle].InternalObject;
|
||||
}
|
||||
|
||||
PVOID AccessUserObject(ULONG Handle)
|
||||
{
|
||||
return GDIHandles[Handle].UserObject;
|
||||
}
|
||||
|
||||
PVOID AccessInternalObjectFromUserObject(PVOID UserObject)
|
||||
{
|
||||
ULONG i;
|
||||
|
||||
for(i=0; i<MAX_GDI_HANDLES; i++)
|
||||
{
|
||||
if(GDIHandles[i].UserObject == UserObject)
|
||||
return GDIHandles[i].InternalObject;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ULONG AccessHandleFromUserObject(PVOID UserObject)
|
||||
{
|
||||
ULONG i;
|
||||
|
||||
for(i=0; i<MAX_GDI_HANDLES; i++)
|
||||
{
|
||||
if(GDIHandles[i].UserObject == UserObject)
|
||||
return i;
|
||||
}
|
||||
|
||||
return INVALID_HANDLE;
|
||||
}
|
109
reactos/subsys/win32k/eng/lineto.c
Normal file
109
reactos/subsys/win32k/eng/lineto.c
Normal file
|
@ -0,0 +1,109 @@
|
|||
#include <ddk/winddi.h>
|
||||
#include "objects.h"
|
||||
|
||||
VOID LinePoint(SURFOBJ *Surface, SURFGDI *SurfGDI,
|
||||
LONG x, LONG y, ULONG iColor)
|
||||
{
|
||||
ULONG offset;
|
||||
|
||||
offset = (Surface->lDelta*y)+(x*SurfGDI->BytesPerPixel);
|
||||
|
||||
memcpy(Surface->pvBits+offset,
|
||||
&iColor, SurfGDI->BytesPerPixel);
|
||||
}
|
||||
|
||||
BOOL EngHLine(SURFOBJ *Surface, SURFGDI *SurfGDI,
|
||||
LONG x, LONG y, LONG len, ULONG iColor)
|
||||
{
|
||||
ULONG offset, ix;
|
||||
|
||||
offset = (Surface->lDelta*y)+(x*SurfGDI->BytesPerPixel);
|
||||
|
||||
for(ix=0; ix<len*SurfGDI->BytesPerPixel; ix+=SurfGDI->BytesPerPixel)
|
||||
memcpy(Surface->pvBits+offset+ix,
|
||||
&iColor, SurfGDI->BytesPerPixel);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL EngLineTo(SURFOBJ *Surface, CLIPOBJ *Clip, BRUSHOBJ *Brush,
|
||||
LONG x1, LONG y1, LONG x2, LONG y2,
|
||||
RECTL *RectBounds, MIX mix)
|
||||
{
|
||||
SURFGDI *SurfGDI;
|
||||
LONG x, y, d, deltax, deltay, i, length, xchange, ychange, error;
|
||||
|
||||
SurfGDI = AccessInternalObjectFromUserObject(Surface);
|
||||
|
||||
if(Surface->iType!=STYPE_BITMAP)
|
||||
{
|
||||
// Call the driver's DrvLineTo
|
||||
return SurfGDI->LineTo(Surface, Clip, Brush, x1, y1, x2, y2,
|
||||
RectBounds, mix);
|
||||
}
|
||||
|
||||
// FIXME: Implement clipping
|
||||
|
||||
if(y1==y2) return EngHLine(Surface, SurfGDI, x1, y1, (x2-x1), Brush->iSolidColor);
|
||||
|
||||
x=x1;
|
||||
y=y1;
|
||||
deltax=x2-x1;
|
||||
deltay=y2-y1;
|
||||
|
||||
if(deltax<0)
|
||||
{
|
||||
xchange=-1;
|
||||
deltax=-deltax;
|
||||
} else
|
||||
{
|
||||
xchange=1;
|
||||
}
|
||||
|
||||
if(deltay<0)
|
||||
{
|
||||
ychange=-1;
|
||||
deltay=-deltay;
|
||||
} else
|
||||
{
|
||||
ychange=1;
|
||||
};
|
||||
|
||||
error=0;
|
||||
i=0;
|
||||
|
||||
if(deltax<deltay)
|
||||
{
|
||||
length=deltay+1;
|
||||
while(i<length)
|
||||
{
|
||||
LinePoint(Surface, SurfGDI, x, y, Brush->iSolidColor);
|
||||
y=y+ychange;
|
||||
error=error+deltax;
|
||||
|
||||
if(error>deltay)
|
||||
{
|
||||
x=x+xchange;
|
||||
error=error-deltay;
|
||||
}
|
||||
i=i+1;
|
||||
}
|
||||
} else
|
||||
{
|
||||
length=deltax+1;
|
||||
while(i<length)
|
||||
{
|
||||
LinePoint(Surface, SurfGDI, x, y, Brush->iSolidColor);
|
||||
x=x+xchange;
|
||||
error=error+deltay;
|
||||
if(error>deltax)
|
||||
{
|
||||
y=y+ychange;
|
||||
error=error-deltax;
|
||||
}
|
||||
i=i+1;
|
||||
}
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
94
reactos/subsys/win32k/eng/paint.c
Normal file
94
reactos/subsys/win32k/eng/paint.c
Normal file
|
@ -0,0 +1,94 @@
|
|||
/*
|
||||
* COPYRIGHT: See COPYING in the top level directory
|
||||
* PROJECT: ReactOS kernel
|
||||
* PURPOSE: GDI Driver Paint Functions
|
||||
* FILE: subsys/win32k/eng/paint.c
|
||||
* PROGRAMER: Jason Filby
|
||||
* REVISION HISTORY:
|
||||
* 3/7/1999: Created
|
||||
*/
|
||||
|
||||
#include <ddk/winddi.h>
|
||||
#include "objects.h"
|
||||
#include "brush.h"
|
||||
#include "enum.h"
|
||||
|
||||
BOOL FillSolid(SURFOBJ *Surface, PRECTL Dimensions, ULONG iColor)
|
||||
{
|
||||
ULONG x, y, LineWidth, leftOfBitmap;
|
||||
SURFGDI *SurfaceGDI;
|
||||
|
||||
SurfaceGDI = AccessInternalObjectFromUserObject(Surface);
|
||||
LineWidth = Dimensions->right - Dimensions->left;
|
||||
|
||||
for (y = Dimensions->top; y < Dimensions->bottom; y++)
|
||||
{
|
||||
EngHLine(Surface, SurfaceGDI, Dimensions->left, y, LineWidth, iColor);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL EngPaintRgn(SURFOBJ *Surface, CLIPOBJ *ClipRegion, ULONG iColor, MIX Mix,
|
||||
BRUSHINST *BrushInst, POINTL *BrushPoint)
|
||||
{
|
||||
RECT_ENUM RectEnum;
|
||||
BOOL EnumMore;
|
||||
|
||||
switch(ClipRegion->iMode) {
|
||||
|
||||
case TC_RECTANGLES:
|
||||
|
||||
/* Rectangular clipping can be handled without enumeration.
|
||||
Note that trivial clipping is not possible, since the clipping
|
||||
region defines the area to fill */
|
||||
|
||||
if (ClipRegion->iDComplexity == DC_RECT)
|
||||
{
|
||||
FillSolid(Surface, &ClipRegion->rclBounds, iColor);
|
||||
} else {
|
||||
|
||||
/* Enumerate all the rectangles and draw them */
|
||||
|
||||
CLIPOBJ_cEnumStart(ClipRegion, FALSE, CT_RECTANGLES, CD_ANY,
|
||||
ENUM_RECT_LIMIT);
|
||||
|
||||
do {
|
||||
EnumMore = CLIPOBJ_bEnum(ClipRegion, sizeof(RectEnum), (PVOID) &RectEnum);
|
||||
|
||||
FillSolid(Surface, &RectEnum.arcl[0], iColor);
|
||||
|
||||
} while (EnumMore);
|
||||
}
|
||||
|
||||
return(TRUE);
|
||||
|
||||
default:
|
||||
return(FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
BOOL EngPaint(IN SURFOBJ *Surface, IN CLIPOBJ *ClipRegion,
|
||||
IN BRUSHOBJ *Brush, IN POINTL *BrushOrigin,
|
||||
IN MIX Mix)
|
||||
{
|
||||
SURFGDI *SurfGDI;
|
||||
|
||||
// Is the surface's Paint function hooked?
|
||||
SurfGDI = AccessInternalObjectFromUserObject(Surface);
|
||||
|
||||
if((Surface->iType!=STYPE_BITMAP) && (SurfGDI->Paint!=NULL))
|
||||
{
|
||||
// Call the driver's DrvPaint
|
||||
return SurfGDI->Paint(Surface, ClipRegion, Brush, BrushOrigin, Mix);
|
||||
}
|
||||
|
||||
// FIXME: We only support a brush's solid color attribute
|
||||
return(EngPaintRgn(Surface, ClipRegion, Brush->iSolidColor, Mix, NULL,
|
||||
BrushOrigin));
|
||||
}
|
||||
|
||||
BOOL EngEraseSurface(SURFOBJ *Surface, RECTL *Rect, ULONG iColor)
|
||||
{
|
||||
return FillSolid(Surface, Rect, iColor);
|
||||
}
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
* COPYRIGHT: See COPYING in the top level directory
|
||||
* PROJECT: ReactOS kernel
|
||||
* PURPOSE: GDI Driver Bitmap Functions
|
||||
* PURPOSE: GDI Palette Functions
|
||||
* FILE: subsys/win32k/eng/palette.c
|
||||
* PROGRAMER: Jason Filby
|
||||
* REVISION HISTORY:
|
||||
|
@ -9,33 +9,68 @@
|
|||
*/
|
||||
|
||||
#include <ddk/winddi.h>
|
||||
#include "objects.h"
|
||||
|
||||
HPALETTE EngCreatePalette(IN ULONG Mode,
|
||||
IN ULONG NumColors,
|
||||
IN PULONG *Colors,
|
||||
IN ULONG Red,
|
||||
IN ULONG Green,
|
||||
IN ULONG Blue)
|
||||
HPALETTE EngCreatePalette(ULONG Mode,
|
||||
ULONG NumColors,
|
||||
PULONG *Colors, // FIXME: This was implemented with ULONG *Colors!!
|
||||
ULONG Red,
|
||||
ULONG Green,
|
||||
ULONG Blue)
|
||||
{
|
||||
/* We need to take the colors given to us and generate a nice default color
|
||||
model */
|
||||
HPALETTE NewPalette;
|
||||
PALOBJ *PalObj;
|
||||
PALGDI *PalGDI;
|
||||
|
||||
if(Mode==PAL_INDEXED)
|
||||
{
|
||||
/* For now the ultimate color model is just colors.. */
|
||||
}
|
||||
PalObj = EngAllocMem(FL_ZERO_MEMORY, sizeof(PALOBJ), NULL);
|
||||
PalGDI = EngAllocMem(FL_ZERO_MEMORY, sizeof(PALGDI), NULL);
|
||||
|
||||
/* FIXME: Add support for other given palette types */
|
||||
NewPalette = CreateGDIHandle(PalGDI, PalObj);
|
||||
|
||||
/* FIXME: Generate a handle for Colors */
|
||||
PalGDI->Mode = Mode;
|
||||
|
||||
return Colors;
|
||||
if(Mode==PAL_INDEXED)
|
||||
{
|
||||
PalGDI->NumColors = NumColors;
|
||||
PalGDI->IndexedColors = Colors;
|
||||
} else
|
||||
if(Mode==PAL_BITFIELDS)
|
||||
{
|
||||
PalGDI->RedMask = Red;
|
||||
PalGDI->GreenMask = Green;
|
||||
PalGDI->BlueMask = Blue;
|
||||
}
|
||||
|
||||
return NewPalette;
|
||||
}
|
||||
|
||||
BOOL EngDeletePalette(IN HPALETTE hpal)
|
||||
BOOL EngDeletePalette(IN HPALETTE Palette)
|
||||
{
|
||||
/* Should actually get the pointer from this handle.. which for now IS
|
||||
the pointer */
|
||||
PALOBJ *PalObj;
|
||||
PALGDI *PalGDI;
|
||||
|
||||
EngFreeMem(hpal);
|
||||
PalGDI = AccessInternalObject(Palette);
|
||||
PalObj = AccessInternalObject(Palette);
|
||||
|
||||
EngFreeMem(PalGDI);
|
||||
EngFreeMem(PalObj);
|
||||
FreeGDIHandle(Palette);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
ULONG PALOBJ_cGetColors(PALOBJ *PalObj, ULONG Start, ULONG Colors,
|
||||
ULONG *PaletteEntry)
|
||||
{
|
||||
ULONG i, entry;
|
||||
PALGDI *PalGDI;
|
||||
|
||||
PalGDI = AccessInternalObjectFromUserObject(PalObj);
|
||||
|
||||
for(i=Start; i<Colors; i++)
|
||||
{
|
||||
PaletteEntry[i] = PalGDI->IndexedColors[i];
|
||||
}
|
||||
|
||||
return Colors;
|
||||
}
|
||||
|
|
|
@ -9,36 +9,219 @@
|
|||
*/
|
||||
|
||||
#include <ddk/winddi.h>
|
||||
#include "objects.h"
|
||||
|
||||
BOOL EngAssociateSurface(IN HSURF Surface,
|
||||
IN HDEV Dev,
|
||||
IN ULONG Hooks)
|
||||
BYTE bytesPerPixel(ULONG Format)
|
||||
{
|
||||
SURFOBJ *Surfobj;
|
||||
// FIXME: GDI bitmaps are supposed to be pixel-packed. Right now if the
|
||||
// pixel size if < 1 byte we expand it to 1 byte
|
||||
|
||||
// Point our new Surfobj to hsurf (assumes hsurf is value returned by
|
||||
// ExAllocatePool)
|
||||
Surfobj = Surface;
|
||||
if(Format==BMF_1BPP)
|
||||
{
|
||||
return 1;
|
||||
} else
|
||||
if((Format==BMF_4BPP) || (Format==BMF_4RLE))
|
||||
{
|
||||
return 1;
|
||||
} else
|
||||
if((Format==BMF_8BPP) || (Format==BMF_8RLE))
|
||||
{
|
||||
return 1;
|
||||
} else
|
||||
if(Format==BMF_16BPP)
|
||||
{
|
||||
return 2;
|
||||
} else
|
||||
if(Format==BMF_24BPP)
|
||||
{
|
||||
return 3;
|
||||
} else
|
||||
if(Format==BMF_32BPP)
|
||||
{
|
||||
return 4;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
VOID InitializeHooks(SURFGDI *SurfGDI)
|
||||
{
|
||||
SurfGDI->BitBlt = NULL;
|
||||
SurfGDI->CopyBits = NULL;
|
||||
}
|
||||
|
||||
HBITMAP EngCreateDeviceBitmap(DHSURF dhsurf, SIZEL Size, ULONG Format)
|
||||
{
|
||||
HBITMAP NewBitmap;
|
||||
SURFOBJ *SurfObj;
|
||||
SURFGDI *SurfGDI;
|
||||
|
||||
SurfObj = EngAllocMem(FL_ZERO_MEMORY, sizeof(SURFOBJ), NULL);
|
||||
SurfGDI = EngAllocMem(FL_ZERO_MEMORY, sizeof(SURFGDI), NULL);
|
||||
|
||||
NewBitmap = CreateGDIHandle(SurfGDI, SurfObj);
|
||||
|
||||
InitializeHooks(SurfGDI);
|
||||
SurfGDI->BytesPerPixel = bytesPerPixel(Format);
|
||||
|
||||
SurfObj->dhsurf = dhsurf;
|
||||
SurfObj->hsurf = dhsurf; // FIXME: Is this correct??
|
||||
SurfObj->sizlBitmap = Size;
|
||||
SurfObj->iBitmapFormat = Format;
|
||||
SurfObj->lDelta = SurfGDI->BytesPerPixel * Size.cx;
|
||||
SurfObj->iType = STYPE_DEVBITMAP;
|
||||
|
||||
return NewBitmap;
|
||||
}
|
||||
|
||||
HBITMAP EngCreateBitmap(IN SIZEL Size,
|
||||
IN LONG Width,
|
||||
IN ULONG Format,
|
||||
IN ULONG Flags,
|
||||
IN PVOID Bits)
|
||||
{
|
||||
HBITMAP NewBitmap;
|
||||
SURFOBJ *SurfObj;
|
||||
SURFGDI *SurfGDI;
|
||||
|
||||
SurfObj = EngAllocMem(FL_ZERO_MEMORY, sizeof(SURFOBJ), NULL);
|
||||
SurfGDI = EngAllocMem(FL_ZERO_MEMORY, sizeof(SURFGDI), NULL);
|
||||
|
||||
NewBitmap = CreateGDIHandle(SurfGDI, SurfObj);
|
||||
|
||||
InitializeHooks(SurfGDI);
|
||||
SurfGDI->BytesPerPixel = bytesPerPixel(Format);
|
||||
|
||||
SurfObj->cjBits = Width * Size.cy;
|
||||
|
||||
if(Bits!=NULL)
|
||||
{
|
||||
SurfObj->pvBits = Bits;
|
||||
} else
|
||||
{
|
||||
if(Flags & BMF_USERMEM)
|
||||
{
|
||||
SurfObj->pvBits = EngAllocUserMem(SurfObj->cjBits, 0);
|
||||
} else {
|
||||
if(Flags & BMF_NOZEROINIT)
|
||||
{
|
||||
SurfObj->pvBits = EngAllocMem(0, SurfObj->cjBits, 0);
|
||||
} else {
|
||||
SurfObj->pvBits = EngAllocMem(FL_ZERO_MEMORY, SurfObj->cjBits, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SurfObj->dhsurf = 0;
|
||||
SurfObj->hsurf = 0;
|
||||
SurfObj->sizlBitmap = Size;
|
||||
SurfObj->iBitmapFormat = Format;
|
||||
SurfObj->lDelta = Width;
|
||||
SurfObj->iType = STYPE_BITMAP;
|
||||
|
||||
// Use flags to determine bitmap type -- TOP_DOWN or whatever
|
||||
|
||||
return NewBitmap;
|
||||
}
|
||||
|
||||
HSURF EngCreateDeviceSurface(DHSURF dhsurf, SIZEL Size, ULONG Format)
|
||||
{
|
||||
HSURF NewSurface;
|
||||
SURFOBJ *SurfObj;
|
||||
SURFGDI *SurfGDI;
|
||||
|
||||
// DrvCreateDeviceSurface???
|
||||
|
||||
SurfObj = EngAllocMem(FL_ZERO_MEMORY, sizeof(SURFOBJ), NULL);
|
||||
SurfGDI = EngAllocMem(FL_ZERO_MEMORY, sizeof(SURFGDI), NULL);
|
||||
|
||||
NewSurface = CreateGDIHandle(SurfGDI, SurfObj);
|
||||
|
||||
InitializeHooks(SurfGDI);
|
||||
SurfGDI->BytesPerPixel = bytesPerPixel(Format);
|
||||
|
||||
SurfObj->dhsurf = dhsurf;
|
||||
SurfObj->hsurf = dhsurf; // FIXME: Is this correct??
|
||||
SurfObj->sizlBitmap = Size;
|
||||
SurfObj->iBitmapFormat = Format;
|
||||
SurfObj->lDelta = SurfGDI->BytesPerPixel * Size.cx;
|
||||
SurfObj->iType = STYPE_DEVICE;
|
||||
|
||||
return NewSurface;
|
||||
}
|
||||
|
||||
PFN DriverFunction(DRVENABLEDATA *DED, ULONG DriverFunc)
|
||||
{
|
||||
ULONG i;
|
||||
|
||||
for(i=0; i<DED->c; i++)
|
||||
{
|
||||
if(DED->pdrvfn[i].iFunc == DriverFunc)
|
||||
return DED->pdrvfn[i].pfn;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
BOOL EngAssociateSurface(HSURF Surface, HDEV Dev, ULONG Hooks)
|
||||
{
|
||||
SURFOBJ *SurfObj;
|
||||
SURFGDI *SurfGDI;
|
||||
|
||||
DRVENABLEDATA *DED;
|
||||
|
||||
SurfGDI = AccessInternalObject(Surface);
|
||||
SurfObj = AccessUserObject(Surface);
|
||||
|
||||
DED = AccessInternalObject(Dev);
|
||||
|
||||
// Associate the hdev
|
||||
Surfobj->hdev = Dev;
|
||||
SurfObj->hdev = Dev;
|
||||
|
||||
// FIXME: Hook up the specified functions
|
||||
// Hook up specified functions
|
||||
if(Hooks & HOOK_BITBLT)
|
||||
SurfGDI->BitBlt = DriverFunction(DED, INDEX_DrvBitBlt);
|
||||
if(Hooks & HOOK_STRETCHBLT)
|
||||
SurfGDI->StretchBlt = DriverFunction(DED, INDEX_DrvStretchBlt);
|
||||
if(Hooks & HOOK_TEXTOUT)
|
||||
SurfGDI->TextOut = DriverFunction(DED, INDEX_DrvTextOut);
|
||||
if(Hooks & HOOK_PAINT)
|
||||
SurfGDI->Paint = DriverFunction(DED, INDEX_DrvPaint);
|
||||
if(Hooks & HOOK_STROKEPATH)
|
||||
SurfGDI->StrokePath = DriverFunction(DED, INDEX_DrvStrokePath);
|
||||
if(Hooks & HOOK_FILLPATH)
|
||||
SurfGDI->FillPath = DriverFunction(DED, INDEX_DrvFillPath);
|
||||
if(Hooks & HOOK_STROKEANDFILLPATH)
|
||||
SurfGDI->StrokeAndFillPath = DriverFunction(DED, INDEX_DrvStrokeAndFillPath);
|
||||
if(Hooks & HOOK_LINETO)
|
||||
SurfGDI->LineTo = DriverFunction(DED, INDEX_DrvLineTo);
|
||||
if(Hooks & HOOK_COPYBITS)
|
||||
SurfGDI->CopyBits = DriverFunction(DED, INDEX_DrvCopyBits);
|
||||
if(Hooks & HOOK_SYNCHRONIZE)
|
||||
SurfGDI->Synchronize = DriverFunction(DED, INDEX_DrvSynchronize);
|
||||
if(Hooks & HOOK_SYNCHRONIZEACCESS)
|
||||
SurfGDI->SynchronizeAccess = TRUE;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL APIENTRY EngDeleteSurface(HSURF hsurf)
|
||||
BOOL EngDeleteSurface(HSURF Surface)
|
||||
{
|
||||
// Assume the hsurf was the value returned by ExAllocatePool
|
||||
ExFreePool(hsurf);
|
||||
SURFOBJ *SurfObj;
|
||||
SURFGDI *SurfGDI;
|
||||
|
||||
SurfGDI = AccessInternalObject(Surface);
|
||||
SurfObj = AccessUserObject(Surface);
|
||||
|
||||
EngFreeMem(SurfGDI);
|
||||
EngFreeMem(SurfObj);
|
||||
FreeGDIHandle(Surface);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
SURFOBJ *EngLockSurface(IN HSURF hsurf)
|
||||
SURFOBJ *EngLockSurface(HSURF Surface)
|
||||
{
|
||||
/* We assume that hsurf is the value returned from ExAllocatePool */
|
||||
return EngAllocUserMem(NULL, sizeof(SURFOBJ), "");
|
||||
}
|
||||
// FIXME: Do we need to allocate new memory for this user object??
|
||||
|
||||
VOID EngUnlockSurface(IN SURFOBJ *pso)
|
||||
{
|
||||
EngFreeUserMem(sizeof(pso));
|
||||
return AccessUserObject(Surface);
|
||||
}
|
||||
|
|
268
reactos/subsys/win32k/eng/xlate.c
Normal file
268
reactos/subsys/win32k/eng/xlate.c
Normal file
|
@ -0,0 +1,268 @@
|
|||
/*
|
||||
* COPYRIGHT: See COPYING in the top level directory
|
||||
* PROJECT: ReactOS kernel
|
||||
* PURPOSE: GDI Color Translation Functions
|
||||
* FILE: subsys/win32k/eng/xlate.c
|
||||
* PROGRAMER: Jason Filby
|
||||
* REVISION HISTORY:
|
||||
* 8/20/1999: Created
|
||||
*/
|
||||
|
||||
#include <ddk/ntddk.h>
|
||||
#include <ddk/winddi.h>
|
||||
#include <ddk/ntddvid.h>
|
||||
|
||||
#include "objects.h"
|
||||
|
||||
ULONG CCMLastSourceColor = 0, CCMLastColorMatch = 0;
|
||||
|
||||
ULONG RGBtoULONG(BYTE Red, BYTE Green, BYTE Blue)
|
||||
{
|
||||
return ((Red & 0xff) << 16) | ((Green & 0xff) << 8) | (Blue & 0xff);
|
||||
}
|
||||
|
||||
ULONG BGRtoULONG(BYTE Blue, BYTE Green, BYTE Red)
|
||||
{
|
||||
return ((Blue & 0xff) << 16) | ((Green & 0xff) << 8) | (Red & 0xff);
|
||||
}
|
||||
|
||||
INT abs(INT nm)
|
||||
{
|
||||
if(nm<0)
|
||||
{
|
||||
return nm * -1;
|
||||
} else
|
||||
{
|
||||
return nm;
|
||||
}
|
||||
}
|
||||
|
||||
// FIXME: If the caller knows that the destinations are indexed and not RGB
|
||||
// then we should cache more than one value. Same with the source.
|
||||
|
||||
ULONG ClosestColorMatch(ULONG SourceColor, ULONG *DestColors,
|
||||
ULONG NumColors)
|
||||
{
|
||||
PVIDEO_CLUTDATA cSourceColor;
|
||||
PVIDEO_CLUTDATA cDestColors;
|
||||
ULONG bestMatch = 256, idx = 0, i;
|
||||
ULONG rt;
|
||||
|
||||
// Simple cache -- only one value because we don't want to waste time
|
||||
// if the colors aren't very sequential
|
||||
|
||||
if(SourceColor == CCMLastSourceColor)
|
||||
{
|
||||
return CCMLastColorMatch;
|
||||
}
|
||||
|
||||
cSourceColor = &SourceColor;
|
||||
|
||||
for (i=0; i<NumColors; i++)
|
||||
{
|
||||
cDestColors = &DestColors[i];
|
||||
|
||||
rt = ( abs(cSourceColor->Red - cDestColors->Red) +
|
||||
abs(cSourceColor->Green - cDestColors->Green) +
|
||||
abs(cSourceColor->Blue - cDestColors->Blue) ) / 3;
|
||||
|
||||
if(rt<=bestMatch)
|
||||
{
|
||||
idx = i;
|
||||
bestMatch = rt;
|
||||
}
|
||||
}
|
||||
|
||||
CCMLastSourceColor = SourceColor;
|
||||
CCMLastColorMatch = idx;
|
||||
|
||||
return idx;
|
||||
}
|
||||
|
||||
VOID IndexedToIndexedTranslationTable(ULONG *TranslationTable,
|
||||
PALGDI *PalDest, PALGDI *PalSource)
|
||||
{
|
||||
ULONG i;
|
||||
|
||||
for(i=0; i<PalSource->NumColors; i++)
|
||||
{
|
||||
TranslationTable[i] = ClosestColorMatch(PalSource->IndexedColors[i],
|
||||
PalDest->IndexedColors, PalDest->NumColors);
|
||||
}
|
||||
}
|
||||
|
||||
XLATEOBJ *EngCreateXlate(USHORT DestPalType, USHORT SourcePalType,
|
||||
HPALETTE PaletteDest, HPALETTE PaletteSource)
|
||||
{
|
||||
// FIXME: Add support for BGR conversions
|
||||
|
||||
HPALETTE NewXlate;
|
||||
XLATEOBJ *XlateObj;
|
||||
XLATEGDI *XlateGDI;
|
||||
PALGDI *SourcePalGDI, *DestPalGDI;
|
||||
ULONG IndexedColors;
|
||||
|
||||
XlateObj = EngAllocMem(FL_ZERO_MEMORY, sizeof(XLATEOBJ), NULL);
|
||||
XlateGDI = EngAllocMem(FL_ZERO_MEMORY, sizeof(XLATEGDI), NULL);
|
||||
|
||||
NewXlate = CreateGDIHandle(XlateGDI, XlateObj);
|
||||
|
||||
if(SourcePalType == PAL_INDEXED)
|
||||
{
|
||||
SourcePalGDI = AccessInternalObject(PaletteSource);
|
||||
} else
|
||||
if(DestPalType == PAL_INDEXED)
|
||||
{
|
||||
DestPalGDI = AccessInternalObject(PaletteDest);
|
||||
}
|
||||
|
||||
XlateObj->iSrcType = SourcePalType;
|
||||
XlateObj->iDstType = DestPalType;
|
||||
|
||||
// Store handles of palettes in internal Xlate GDI object (or NULLs)
|
||||
XlateGDI->DestPal = PaletteDest;
|
||||
XlateGDI->SourcePal = PaletteSource;
|
||||
|
||||
XlateObj->flXlate = 0;
|
||||
|
||||
// If source and destination palettes are the same or if they're RGB/BGR
|
||||
if( (PaletteDest == PaletteSource) ||
|
||||
((DestPalType == PAL_RGB) && (SourcePalType == PAL_RGB)) ||
|
||||
((DestPalType == PAL_BGR) && (SourcePalType == PAL_BGR)) )
|
||||
{
|
||||
XlateObj->flXlate |= XO_TRIVIAL;
|
||||
}
|
||||
|
||||
// Prepare the translation table
|
||||
if( (SourcePalType == PAL_INDEXED) || (SourcePalType == PAL_RGB) )
|
||||
{
|
||||
XlateObj->flXlate |= XO_TABLE;
|
||||
|
||||
if (SourcePalType == PAL_INDEXED) IndexedColors = SourcePalGDI->NumColors;
|
||||
if (DestPalType == PAL_INDEXED) IndexedColors = DestPalGDI->NumColors;
|
||||
|
||||
XlateGDI->translationTable = EngAllocMem(
|
||||
FL_ZERO_MEMORY, sizeof(ULONG)*IndexedColors, NULL);
|
||||
}
|
||||
|
||||
// Source palette is indexed
|
||||
if(XlateObj->iSrcType == PAL_INDEXED)
|
||||
{
|
||||
if(XlateObj->iDstType == PAL_INDEXED)
|
||||
{
|
||||
// Converting from indexed to indexed
|
||||
IndexedToIndexedTranslationTable(XlateGDI->translationTable,
|
||||
DestPalGDI, SourcePalGDI);
|
||||
} else
|
||||
if(XlateObj->iDstType == PAL_RGB)
|
||||
{
|
||||
// FIXME: Is this necessary? I think the driver has to call this
|
||||
// function anyways if pulXlate is NULL and Source is PAL_INDEXED
|
||||
|
||||
// Converting from indexed to RGB
|
||||
|
||||
XLATEOBJ_cGetPalette(XlateObj, XO_SRCPALETTE,
|
||||
SourcePalGDI->NumColors,
|
||||
XlateGDI->translationTable);
|
||||
}
|
||||
|
||||
XlateObj->pulXlate = XlateGDI->translationTable;
|
||||
}
|
||||
|
||||
// Source palette is RGB
|
||||
if(XlateObj->iSrcType == PAL_RGB)
|
||||
{
|
||||
if(XlateObj->iDstType == PAL_INDEXED)
|
||||
{
|
||||
// FIXME: Is this necessary? I think the driver has to call this
|
||||
// function anyways if pulXlate is NULL and Dest is PAL_INDEXED
|
||||
|
||||
// Converting from RGB to indexed
|
||||
XLATEOBJ_cGetPalette(XlateObj, XO_DESTPALETTE,
|
||||
DestPalGDI->NumColors,
|
||||
XlateGDI->translationTable);
|
||||
}
|
||||
}
|
||||
|
||||
// FIXME: Add support for XO_TO_MONO
|
||||
|
||||
return XlateObj;
|
||||
}
|
||||
|
||||
EngDeleteXlate(XLATEOBJ *XlateObj)
|
||||
{
|
||||
HPALETTE HXlate = AccessHandleFromUserObject(XlateObj);
|
||||
XLATEGDI *XlateGDI = AccessInternalObject(HXlate);
|
||||
|
||||
if(XlateGDI->translationTable!=NULL)
|
||||
{
|
||||
EngFreeMem(XlateGDI->translationTable);
|
||||
}
|
||||
|
||||
EngFreeMem(XlateGDI);
|
||||
EngFreeMem(XlateObj);
|
||||
FreeGDIHandle(HXlate);
|
||||
}
|
||||
|
||||
ULONG *XLATEOBJ_piVector(XLATEOBJ *XlateObj)
|
||||
{
|
||||
XLATEGDI *XlateGDI = AccessInternalObjectFromUserObject(XlateObj);
|
||||
|
||||
|
||||
if(XlateObj->iSrcType == PAL_INDEXED)
|
||||
{
|
||||
return XlateGDI->translationTable;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ULONG XLATEOBJ_iXlate(XLATEOBJ *XlateObj, ULONG Color)
|
||||
{
|
||||
PALGDI *PalGDI;
|
||||
XLATEGDI *XlateGDI = AccessInternalObjectFromUserObject(XlateObj);
|
||||
|
||||
if(XlateObj->iSrcType == PAL_RGB)
|
||||
{
|
||||
// FIXME: should we cache colors used often?
|
||||
// FIXME: won't work if destination isn't indexed
|
||||
|
||||
// Extract the destination palette
|
||||
PalGDI = AccessInternalObject(XlateGDI->DestPal);
|
||||
|
||||
// Return closest match for the given RGB color
|
||||
return ClosestColorMatch(Color, PalGDI->IndexedColors, PalGDI->NumColors);
|
||||
} else
|
||||
|
||||
if(XlateObj->iSrcType == PAL_INDEXED)
|
||||
{
|
||||
return XlateGDI->translationTable[Color];
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
ULONG XLATEOBJ_cGetPalette(XLATEOBJ *XlateObj,
|
||||
ULONG PalOutType, ULONG cPal, ULONG *OutPal)
|
||||
{
|
||||
ULONG i;
|
||||
HPALETTE HPal;
|
||||
XLATEGDI *XlateGDI;
|
||||
PALGDI *PalGDI;
|
||||
|
||||
XlateGDI = AccessInternalObjectFromUserObject(XlateObj);
|
||||
|
||||
if(PalOutType == XO_SRCPALETTE)
|
||||
{
|
||||
HPal = XlateGDI->SourcePal;
|
||||
} else
|
||||
if(PalOutType == XO_DESTPALETTE)
|
||||
{
|
||||
HPal = XlateGDI->DestPal;
|
||||
}
|
||||
|
||||
PalGDI = AccessInternalObject(HPal);
|
||||
RtlCopyMemory(OutPal, PalGDI->IndexedColors, sizeof(ULONG)*cPal);
|
||||
|
||||
return i;
|
||||
}
|
Loading…
Reference in a new issue