⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 bitmaps.c

📁 winNT技术操作系统,国外开放的原代码和LIUX一样
💻 C
📖 第 1 页 / 共 3 页
字号:
/*
 *  ReactOS W32 Subsystem
 *  Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 ReactOS Team
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */
/* $Id: bitmaps.c 25936 2007-03-01 19:14:59Z greatlrd $ */

#include <w32k.h>

#define NDEBUG
#include <debug.h>

#define IN_RECT(r,x,y) \
( \
 (x) >= (r).left && \
 (y) >= (r).top && \
 (x) < (r).right && \
 (y) < (r).bottom \
)

BOOL STDCALL
NtGdiBitBlt(
	HDC  hDCDest,
	INT  XDest,
	INT  YDest,
	INT  Width,
	INT  Height,
	HDC  hDCSrc,
	INT  XSrc,
	INT  YSrc,
	DWORD  ROP,
	IN DWORD crBackColor,
	IN FLONG fl)
{
	PDC DCDest = NULL;
	PDC DCSrc  = NULL;
	BITMAPOBJ *BitmapDest, *BitmapSrc;
	RECTL DestRect;
	POINTL SourcePoint, BrushOrigin;
	BOOL Status;
	XLATEOBJ *XlateObj = NULL;
	HPALETTE SourcePalette = 0, DestPalette = 0;
	PGDIBRUSHOBJ BrushObj;
	GDIBRUSHINST BrushInst;
	BOOL UsesSource = ROP3_USES_SOURCE(ROP);
	BOOL UsesPattern = ROP3_USES_PATTERN(ROP);

	DCDest = DC_LockDc(hDCDest);
	if (NULL == DCDest)
	{
		DPRINT1("Invalid destination dc handle (0x%08x) passed to NtGdiBitBlt\n", hDCDest);
		SetLastWin32Error(ERROR_INVALID_HANDLE);
		return FALSE;
	}
	if (DCDest->IsIC)
	{
		DC_UnlockDc(DCDest);
		/* Yes, Windows really returns TRUE in this case */
		return TRUE;
	}

	if (UsesSource)
	{
		if (hDCSrc != hDCDest)
		{
			DCSrc = DC_LockDc(hDCSrc);
			if (NULL == DCSrc)
			{
				DC_UnlockDc(DCDest);
				DPRINT1("Invalid source dc handle (0x%08x) passed to NtGdiBitBlt\n", hDCSrc);
				SetLastWin32Error(ERROR_INVALID_HANDLE);
				return FALSE;
			}
			if (DCSrc->IsIC)
			{
				DC_UnlockDc(DCSrc);
				DC_UnlockDc(DCDest);
				/* Yes, Windows really returns TRUE in this case */
				return TRUE;
			}
		}
		else
		{
			DCSrc = DCDest;
		}
	}
	else
	{
		DCSrc = NULL;
	}

	/* Offset the destination and source by the origin of their DCs. */
	XDest += DCDest->w.DCOrgX;
	YDest += DCDest->w.DCOrgY;
	if (UsesSource)
	{
		XSrc += DCSrc->w.DCOrgX;
		YSrc += DCSrc->w.DCOrgY;
	}

	DestRect.left   = XDest;
	DestRect.top    = YDest;
	DestRect.right  = XDest+Width;
	DestRect.bottom = YDest+Height;

        IntLPtoDP(DCDest, (LPPOINT)&DestRect, 2);

	SourcePoint.x = XSrc;
	SourcePoint.y = YSrc;

	BrushOrigin.x = 0;
	BrushOrigin.y = 0;

	/* Determine surfaces to be used in the bitblt */
	BitmapDest = BITMAPOBJ_LockBitmap(DCDest->w.hBitmap);
	if (UsesSource)
	{
	        if (DCSrc->w.hBitmap == DCDest->w.hBitmap)
			BitmapSrc = BitmapDest;
		else
			BitmapSrc = BITMAPOBJ_LockBitmap(DCSrc->w.hBitmap);
	}
	else
	{
		BitmapSrc = NULL;
	}

	if (UsesPattern)
	{
		BrushObj = BRUSHOBJ_LockBrush(DCDest->w.hBrush);
		if (NULL == BrushObj)
		{
			if (UsesSource && hDCSrc != hDCDest)
			{
				DC_UnlockDc(DCSrc);
			}
			if(BitmapDest != NULL)
			{
                                BITMAPOBJ_UnlockBitmap(BitmapDest);
			}
			if(BitmapSrc != NULL && BitmapSrc != BitmapDest)
			{
                                BITMAPOBJ_UnlockBitmap(BitmapSrc);
			}
			DC_UnlockDc(DCDest);
			SetLastWin32Error(ERROR_INVALID_HANDLE);
			return FALSE;
		}
		BrushOrigin = *((PPOINTL)&BrushObj->ptOrigin);
		IntGdiInitBrushInstance(&BrushInst, BrushObj, DCDest->XlateBrush);
	}
	else
	{
		BrushObj = NULL;
	}

	/* Create the XLATEOBJ. */
	if (UsesSource)
	{
		if (DCDest->w.hPalette != 0)
			DestPalette = DCDest->w.hPalette;

		if (DCSrc->w.hPalette != 0)
			SourcePalette = DCSrc->w.hPalette;

		/* KB41464 details how to convert between mono and color */
		if (DCDest->w.bitsPerPixel == 1 && DCSrc->w.bitsPerPixel == 1)
		{
			XlateObj = NULL;
		}
		else
		{
			if (DCDest->w.bitsPerPixel == 1)
			{
				XlateObj = IntEngCreateMonoXlate(0, DestPalette, SourcePalette, DCSrc->w.backgroundColor);
			}
			else if (DCSrc->w.bitsPerPixel == 1)
			{
				XlateObj = IntEngCreateSrcMonoXlate(DestPalette, DCSrc->w.backgroundColor, DCSrc->w.textColor);
			}
			else
			{
				XlateObj = IntEngCreateXlate(0, 0, DestPalette, SourcePalette);
			}
			if (NULL == XlateObj)
			{
				if (UsesSource && hDCSrc != hDCDest)
				{
					DC_UnlockDc(DCSrc);
				}
				DC_UnlockDc(DCDest);
				if(BitmapDest != NULL)
				{
                                	BITMAPOBJ_UnlockBitmap(BitmapDest);
				}
				if(BitmapSrc != NULL && BitmapSrc != BitmapDest)
				{
                                	BITMAPOBJ_UnlockBitmap(BitmapSrc);
				}
				if(BrushObj != NULL)
				{
                                        BRUSHOBJ_UnlockBrush(BrushObj);
				}
				SetLastWin32Error(ERROR_NO_SYSTEM_RESOURCES);
				return FALSE;
			}
		}
	}

	/* Perform the bitblt operation */
	Status = IntEngBitBlt(&BitmapDest->SurfObj, &BitmapSrc->SurfObj, NULL,
                              DCDest->CombinedClip, XlateObj, &DestRect,
                              &SourcePoint, NULL,
                              BrushObj ? &BrushInst.BrushObject : NULL,
	                      &BrushOrigin, ROP3_TO_ROP4(ROP));

	if (UsesSource && XlateObj != NULL)
		EngDeleteXlate(XlateObj);

        if(BitmapDest != NULL)
        {
                BITMAPOBJ_UnlockBitmap(BitmapDest);
        }
	if (UsesSource && BitmapSrc != BitmapDest)
	{
		BITMAPOBJ_UnlockBitmap(BitmapSrc);
	}
	if (BrushObj != NULL)
	{
		BRUSHOBJ_UnlockBrush(BrushObj);
	}
	if (UsesSource && hDCSrc != hDCDest)
	{
		DC_UnlockDc(DCSrc);
	}
	DC_UnlockDc(DCDest);

	return Status;
}

BOOL STDCALL
NtGdiTransparentBlt(
	HDC			hdcDst,
	INT			xDst,
	INT			yDst,
	INT			cxDst,
	INT			cyDst,
	HDC			hdcSrc,
	INT			xSrc,
	INT			ySrc,
	INT			cxSrc,
	INT			cySrc,
	COLORREF	TransColor)
{
  PDC DCDest, DCSrc;
  RECTL rcDest, rcSrc;
  BITMAPOBJ *BitmapDest, *BitmapSrc;
  XLATEOBJ *XlateObj;
  HPALETTE SourcePalette = 0, DestPalette = 0;
  PPALGDI PalDestGDI, PalSourceGDI;
  USHORT PalDestMode, PalSrcMode;
  ULONG TransparentColor = 0;
  BOOL Ret = FALSE;

  if(!(DCDest = DC_LockDc(hdcDst)))
  {
    DPRINT1("Invalid destination dc handle (0x%08x) passed to NtGdiTransparentBlt\n", hdcDst);
    SetLastWin32Error(ERROR_INVALID_HANDLE);
    return FALSE;
  }
  if (DCDest->IsIC)
  {
    DC_UnlockDc(DCDest);
    /* Yes, Windows really returns TRUE in this case */
    return TRUE;
  }

  if((hdcDst != hdcSrc) && !(DCSrc = DC_LockDc(hdcSrc)))
  {
    DC_UnlockDc(DCDest);
    DPRINT1("Invalid source dc handle (0x%08x) passed to NtGdiTransparentBlt\n", hdcSrc);
    SetLastWin32Error(ERROR_INVALID_HANDLE);
    return FALSE;
  }
  if(hdcDst == hdcSrc)
  {
    DCSrc = DCDest;
  }
  if (DCSrc->IsIC)
  {
    DC_UnlockDc(DCSrc);
    if(hdcDst != hdcSrc)
    {
      DC_UnlockDc(DCDest);
    }
    /* Yes, Windows really returns TRUE in this case */
    return TRUE;
  }

  /* Offset positions */
  xDst += DCDest->w.DCOrgX;
  yDst += DCDest->w.DCOrgY;
  xSrc += DCSrc->w.DCOrgX;
  ySrc += DCSrc->w.DCOrgY;

  if(DCDest->w.hPalette)
    DestPalette = DCDest->w.hPalette;

  if(DCSrc->w.hPalette)
    SourcePalette = DCSrc->w.hPalette;

  if(!(PalSourceGDI = PALETTE_LockPalette(SourcePalette)))
  {
    DC_UnlockDc(DCSrc);
    DC_UnlockDc(DCDest);
    SetLastWin32Error(ERROR_INVALID_HANDLE);
    return FALSE;
  }
  if((DestPalette != SourcePalette) && !(PalDestGDI = PALETTE_LockPalette(DestPalette)))
  {
    PALETTE_UnlockPalette(PalSourceGDI);
    DC_UnlockDc(DCSrc);
    DC_UnlockDc(DCDest);
    SetLastWin32Error(ERROR_INVALID_HANDLE);
    return FALSE;
  }
  if(DestPalette != SourcePalette)
  {
    PalDestMode = PalDestGDI->Mode;
    PalSrcMode = PalSourceGDI->Mode;
    PALETTE_UnlockPalette(PalDestGDI);
  }
  else
  {
    PalDestMode = PalSrcMode = PalSourceGDI->Mode;
  }
  PALETTE_UnlockPalette(PalSourceGDI);

  /* Translate Transparent (RGB) Color to the source palette */
  if((XlateObj = (XLATEOBJ*)IntEngCreateXlate(PalSrcMode, PAL_RGB, SourcePalette, NULL)))
  {
    TransparentColor = XLATEOBJ_iXlate(XlateObj, (ULONG)TransColor);
    EngDeleteXlate(XlateObj);
  }

  /* Create the XLATE object to convert colors between source and destination */
  XlateObj = (XLATEOBJ*)IntEngCreateXlate(PalDestMode, PalSrcMode, DestPalette, SourcePalette);

  BitmapDest = BITMAPOBJ_LockBitmap(DCDest->w.hBitmap);
  /* FIXME - BitmapDest can be NULL!!!! Don't assert here! */
  ASSERT(BitmapDest);
  BitmapSrc = BITMAPOBJ_LockBitmap(DCSrc->w.hBitmap);
  /* FIXME - BitmapSrc can be NULL!!!! Don't assert here! */
  ASSERT(BitmapSrc);

  rcDest.left = xDst;
  rcDest.top = yDst;
  rcDest.right = rcDest.left + cxDst;
  rcDest.bottom = rcDest.top + cyDst;
  rcSrc.left = xSrc;
  rcSrc.top = ySrc;
  rcSrc.right = rcSrc.left + cxSrc;
  rcSrc.bottom = rcSrc.top + cySrc;

  if((cxDst != cxSrc) || (cyDst != cySrc))
  {
    DPRINT1("TransparentBlt() does not support stretching at the moment!\n");
    goto done;
  }

  Ret = IntEngTransparentBlt(&BitmapDest->SurfObj, &BitmapSrc->SurfObj,
                             DCDest->CombinedClip, XlateObj, &rcDest, &rcSrc,
                             TransparentColor, 0);

done:
  BITMAPOBJ_UnlockBitmap(BitmapDest);
  BITMAPOBJ_UnlockBitmap(BitmapSrc);
  DC_UnlockDc(DCSrc);
  if(hdcDst != hdcSrc)
  {
    DC_UnlockDc(DCDest);
  }
  if(XlateObj)
  {
    EngDeleteXlate(XlateObj);
  }
  return Ret;
}

static HBITMAP
IntCreateBitmapIndirect(CONST BITMAP *BM)
{
   PBITMAPOBJ bmp;
   HBITMAP hBitmap;
   SIZEL Size;
   UINT BitsPixel;

   /* NOTE: Windows also doesn't store nr. of planes separately! */
   BitsPixel = BM->bmBitsPixel * BM->bmPlanes;

   /* Check parameters */
   if (0 == BM->bmHeight || 0 == BM->bmWidth)
   {
      Size.cx = Size.cy = 1;
   }
   else
   {
      Size.cx = abs(BM->bmWidth);
      Size.cy = abs(BM->bmHeight);
   }

   /* Create the bitmap object. */
   hBitmap = IntCreateBitmap(Size, BM->bmWidthBytes,
                             BitmapFormat(BitsPixel, BI_RGB),
                             (BM->bmHeight < 0 ? BMF_TOPDOWN : 0) |
                             (NULL == BM->bmBits ? 0 : BMF_NOZEROINIT), NULL);
   if (!hBitmap)
   {
      DPRINT("NtGdiCreateBitmap: IntCreateBitmap returned 0\n");
      return 0;
   }

   DPRINT("NtGdiCreateBitmap:%dx%d, %d BPP colors returning %08x\n",
          Size.cx, Size.cy, BitsPixel, hBitmap);

   bmp = BITMAPOBJ_LockBitmap( hBitmap );
   if (bmp == NULL)
   {
	   /* FIXME should we free the hBitmap or return it ?? */
	   return 0;
   }
   
   bmp->flFlags = BITMAPOBJ_IS_APIBITMAP;
   BITMAPOBJ_UnlockBitmap( bmp );

   /*
    * NOTE: It's ugly practice, but we are using the object even
    * after unlocking. Since the handle is currently known only
    * to us it should be safe.
    */

   if (NULL != BM->bmBits)
   {
      NtGdiSetBitmapBits(hBitmap, bmp->SurfObj.cjBits, BM->bmBits);
   }

   return hBitmap;
}

HBITMAP STDCALL
NtGdiCreateBitmap(
	INT  Width,
	INT  Height,
	UINT  Planes,
	UINT  BitsPixel,
	IN OPTIONAL LPBYTE Bits)
{
   BITMAP BM;

   BM.bmType = 0;
   BM.bmWidth = Width;
   BM.bmHeight = Height;
   BM.bmWidthBytes = BITMAPOBJ_GetWidthBytes(Width, Planes * BitsPixel);
   BM.bmPlanes = Planes;
   BM.bmBitsPixel = BitsPixel;
   BM.bmBits = Bits;

   return IntCreateBitmapIndirect(&BM);
}

BOOL INTERNAL_CALL
BITMAP_Cleanup(PVOID ObjectBody)
{
        PBITMAPOBJ pBmp = (PBITMAPOBJ)ObjectBody;
	if (pBmp->SurfObj.pvBits != NULL &&
	    (pBmp->flFlags & BITMAPOBJ_IS_APIBITMAP))
	{
		if (pBmp->dib == NULL)
		{
			if (pBmp->SurfObj.pvBits != NULL)
			    ExFreePool(pBmp->SurfObj.pvBits);
		}
		else
		{
			if (pBmp->SurfObj.pvBits != NULL)
				EngFreeUserMem(pBmp->SurfObj.pvBits);
		}
		if (pBmp->hDIBPalette != NULL)
		{			
			NtGdiDeleteObject(pBmp->hDIBPalette);
		}
	}

	if (NULL != pBmp->BitsLock)
	{
		ExFreePoolWithTag(pBmp->BitsLock, TAG_BITMAPOBJ);
		pBmp->BitsLock = NULL;
	}

	return TRUE;
}


HBITMAP FASTCALL
IntCreateCompatibleBitmap(
	PDC Dc,
	INT Width,
	INT Height)
{
	HBITMAP Bmp;

	Bmp = NULL;

	if ((Width >= 0x10000) || (Height >= 0x10000))
	{
		DPRINT1("got bad width %d or height %d, please look for reason\n", Width, Height);
		return NULL;
	}

	/* MS doc says if width or height is 0, return 1-by-1 pixel, monochrome bitmap */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -