diff --git a/reactos/subsys/win32k/eng/bitblt.c b/reactos/subsys/win32k/eng/bitblt.c new file mode 100644 index 00000000000..c22ff5825bb --- /dev/null +++ b/reactos/subsys/win32k/eng/bitblt.c @@ -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 +#include +#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; dybottom; 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); +} diff --git a/reactos/subsys/win32k/eng/clip.c b/reactos/subsys/win32k/eng/clip.c new file mode 100644 index 00000000000..49cd2b3e2f6 --- /dev/null +++ b/reactos/subsys/win32k/eng/clip.c @@ -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 +#include +#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; +} diff --git a/reactos/subsys/win32k/eng/copybits.c b/reactos/subsys/win32k/eng/copybits.c new file mode 100644 index 00000000000..057c1ad76f9 --- /dev/null +++ b/reactos/subsys/win32k/eng/copybits.c @@ -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 +#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; dybottom; 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; +} diff --git a/reactos/subsys/win32k/eng/handle.c b/reactos/subsys/win32k/eng/handle.c new file mode 100644 index 00000000000..3795b791793 --- /dev/null +++ b/reactos/subsys/win32k/eng/handle.c @@ -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 +#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 +#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; ixBytesPerPixel; 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(deltaxiSolidColor); + y=y+ychange; + error=error+deltax; + + if(error>deltay) + { + x=x+xchange; + error=error-deltay; + } + i=i+1; + } + } else + { + length=deltax+1; + while(iiSolidColor); + x=x+xchange; + error=error+deltay; + if(error>deltax) + { + y=y+ychange; + error=error-deltax; + } + i=i+1; + } + } + + return TRUE; +} diff --git a/reactos/subsys/win32k/eng/paint.c b/reactos/subsys/win32k/eng/paint.c new file mode 100644 index 00000000000..6b8500b196d --- /dev/null +++ b/reactos/subsys/win32k/eng/paint.c @@ -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 +#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); +} diff --git a/reactos/subsys/win32k/eng/palette.c b/reactos/subsys/win32k/eng/palette.c index 527c615158c..70964bd47cf 100644 --- a/reactos/subsys/win32k/eng/palette.c +++ b/reactos/subsys/win32k/eng/palette.c @@ -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 +#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; iIndexedColors[i]; + } + + return Colors; } diff --git a/reactos/subsys/win32k/eng/surface.c b/reactos/subsys/win32k/eng/surface.c index 758fb6dc8b1..e061106fba8 100644 --- a/reactos/subsys/win32k/eng/surface.c +++ b/reactos/subsys/win32k/eng/surface.c @@ -9,36 +9,219 @@ */ #include +#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; ic; 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); } diff --git a/reactos/subsys/win32k/eng/xlate.c b/reactos/subsys/win32k/eng/xlate.c new file mode 100644 index 00000000000..bb0339fa3e1 --- /dev/null +++ b/reactos/subsys/win32k/eng/xlate.c @@ -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 +#include +#include + +#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; iRed - 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; iNumColors; 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; +}