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

📄 bitblt.c

📁 winNT技术操作系统,国外开放的原代码和LIUX一样
💻 C
📖 第 1 页 / 共 4 页
字号:
/*
 *  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: bitblt.c 25198 2006-12-21 02:43:31Z greatlrd $
 *
 * 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 <w32k.h>

#define NDEBUG
#include <debug.h>

typedef BOOLEAN (STDCALL *PBLTRECTFUNC)(SURFOBJ* OutputObj,
                                        SURFOBJ* InputObj,
                                        SURFOBJ* Mask,
                                        XLATEOBJ* ColorTranslation,
                                        RECTL* OutputRect,
                                        POINTL* InputPoint,
                                        POINTL* MaskOrigin,
                                        BRUSHOBJ* Brush,
                                        POINTL* BrushOrigin,
                                        ROP4 Rop4);
typedef BOOLEAN (STDCALL *PSTRETCHRECTFUNC)(SURFOBJ* OutputObj,
                                            SURFOBJ* InputObj,
                                            SURFOBJ* Mask,
                                            CLIPOBJ* ClipRegion,
                                            XLATEOBJ* ColorTranslation,
                                            RECTL* OutputRect,
                                            RECTL* InputRect,
                                            POINTL* MaskOrigin,
                                            POINTL* BrushOrigin,
                                            ULONG Mode);

BOOL STDCALL EngIntersectRect(RECTL* prcDst, RECTL* prcSrc1, RECTL* 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;
}

static BOOLEAN STDCALL
BltMask(SURFOBJ* Dest,
	SURFOBJ* Source,
	SURFOBJ* Mask,
	XLATEOBJ* ColorTranslation,
	RECTL* DestRect,
	POINTL* SourcePoint,
	POINTL* MaskPoint,
	BRUSHOBJ* Brush,
	POINTL* BrushPoint,
	ROP4 Rop4)
{
   LONG i, j, dx, dy, c8;
   BYTE *tMask, *lMask;
   static BYTE maskbit[8] = { 0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01 };
   /* Pattern brushes */
   PGDIBRUSHINST GdiBrush = NULL;
   SURFOBJ *PatternObj = NULL;
   PBITMAPOBJ PatternBitmap;
   ULONG PatternWidth = 0, PatternHeight = 0, PatternY = 0;

   if (Mask == NULL)
   {
      return FALSE;
   }

   dx = DestRect->right  - DestRect->left;
   dy = DestRect->bottom - DestRect->top;

   if (Brush->iSolidColor == 0xFFFFFFFF)
   {
      GdiBrush = CONTAINING_RECORD(
         Brush,
         GDIBRUSHINST,
         BrushObject);

      PatternBitmap = BITMAPOBJ_LockBitmap(GdiBrush->GdiBrushObject->hbmPattern);
      if(PatternBitmap != NULL)
      {
        PatternObj = &PatternBitmap->SurfObj;
        PatternWidth = PatternObj->sizlBitmap.cx;
        PatternHeight = PatternObj->sizlBitmap.cy;
      }
   }
   else
     PatternBitmap = NULL;

   tMask = (PBYTE)Mask->pvScan0 + SourcePoint->y * Mask->lDelta + (SourcePoint->x >> 3);
   for (j = 0; j < dy; j++)
   {
      lMask = tMask;
      c8 = SourcePoint->x & 0x07;

      if(PatternBitmap != NULL)
         PatternY = (DestRect->top + j) % PatternHeight;

      for (i = 0; i < dx; i++)
      {
         if (0 != (*lMask & maskbit[c8]))
         {
            if (PatternBitmap == NULL)
            {
               DibFunctionsForBitmapFormat[Dest->iBitmapFormat].DIB_PutPixel(
                  Dest, DestRect->left + i, DestRect->top + j, Brush->iSolidColor);
            }
            else
            {
               DibFunctionsForBitmapFormat[Dest->iBitmapFormat].DIB_PutPixel(
                  Dest, DestRect->left + i, DestRect->top + j,
                  DIB_GetSource(PatternObj, (DestRect->left + i) % PatternWidth, PatternY, GdiBrush->XlateObject));
            }
         }
         c8++;
         if (8 == c8)
         {
            lMask++;
            c8 = 0;
         }
      }
      tMask += Mask->lDelta;
   }

   if (PatternBitmap != NULL)
      BITMAPOBJ_UnlockBitmap(PatternBitmap);

   return TRUE;
}

static BOOLEAN STDCALL
BltPatCopy(SURFOBJ* Dest,
	   SURFOBJ* Source,
	   SURFOBJ* Mask,
	   XLATEOBJ* ColorTranslation,
	   RECTL* DestRect,
	   POINTL* SourcePoint,
	   POINTL* MaskPoint,
	   BRUSHOBJ* Brush,
	   POINTL* BrushPoint,
	   ROP4 Rop4)
{
  // These functions are assigned if we're working with a DIB
  // The assigned functions depend on the bitsPerPixel of the DIB

  DibFunctionsForBitmapFormat[Dest->iBitmapFormat].DIB_ColorFill(Dest, DestRect, Brush->iSolidColor);

  return TRUE;
}

static BOOLEAN STDCALL
CallDibBitBlt(SURFOBJ* OutputObj,
              SURFOBJ* InputObj,
              SURFOBJ* Mask,
              XLATEOBJ* ColorTranslation,
              RECTL* OutputRect,
              POINTL* InputPoint,
              POINTL* MaskOrigin,
              BRUSHOBJ* Brush,
              POINTL* BrushOrigin,
              ROP4 Rop4)
{
   BLTINFO BltInfo;
   PGDIBRUSHINST GdiBrush = NULL;
   BITMAPOBJ *bmPattern;
   BOOLEAN Result;

   BltInfo.DestSurface = OutputObj;
   BltInfo.SourceSurface = InputObj;
   BltInfo.PatternSurface = NULL;
   BltInfo.XlateSourceToDest = ColorTranslation;
   BltInfo.DestRect = *OutputRect;
   BltInfo.SourcePoint = *InputPoint;

   if (ROP3_TO_ROP4(SRCCOPY) == Rop4)
      return DibFunctionsForBitmapFormat[OutputObj->iBitmapFormat].DIB_BitBltSrcCopy(&BltInfo);

   BltInfo.XlatePatternToDest = NULL;
   BltInfo.Brush = Brush;
   BltInfo.BrushOrigin = *BrushOrigin;
   BltInfo.Rop4 = Rop4;

   /* Pattern brush */
   if (ROP4_USES_PATTERN(Rop4) && Brush->iSolidColor == 0xFFFFFFFF)
   {
      GdiBrush = CONTAINING_RECORD(Brush, GDIBRUSHINST, BrushObject);
      if((bmPattern = BITMAPOBJ_LockBitmap(GdiBrush->GdiBrushObject->hbmPattern)))
      {
        BltInfo.PatternSurface = &bmPattern->SurfObj;
      }
      else
      {
        /* FIXME - What to do here? */
      }
      BltInfo.XlatePatternToDest = GdiBrush->XlateObject;
   }
   else
   {
     bmPattern = NULL;
   }

   Result = DibFunctionsForBitmapFormat[OutputObj->iBitmapFormat].DIB_BitBlt(&BltInfo);

   /* Pattern brush */
   if (bmPattern != NULL)
   {
      BITMAPOBJ_UnlockBitmap(bmPattern);
   }

   return Result;
}

INT __cdecl abs(INT nm);

/*
 * @implemented
 */
BOOL STDCALL
EngBitBlt(SURFOBJ *DestObj,
	  SURFOBJ *SourceObj,
	  SURFOBJ *Mask,
	  CLIPOBJ *ClipRegion,
	  XLATEOBJ *ColorTranslation,
	  RECTL *DestRect,
	  POINTL *SourcePoint,
	  POINTL *MaskOrigin,
	  BRUSHOBJ *Brush,
	  POINTL *BrushOrigin,
	  ROP4 Rop4)
{
  BYTE               clippingType;
  RECTL              CombinedRect;
  RECT_ENUM          RectEnum;
  BOOL               EnumMore;
  POINTL             InputPoint;
  RECTL              InputRect;
  RECTL              OutputRect;
  POINTL             Translate;
  INTENG_ENTER_LEAVE EnterLeaveSource;
  INTENG_ENTER_LEAVE EnterLeaveDest;
  SURFOBJ*           InputObj;
  SURFOBJ*           OutputObj;
  PBLTRECTFUNC       BltRectFunc;
  BOOLEAN            Ret = TRUE;
  RECTL              ClipRect;
  unsigned           i;
  POINTL             Pt;
  ULONG              Direction;
  BOOL               UsesSource;
  BOOL               UsesPattern;
  POINTL             AdjustedBrushOrigin;

  UsesSource = ROP4_USES_SOURCE(Rop4);
  UsesPattern = ROP4_USES_PATTERN(Rop4);
  if (R4_NOOP == Rop4)
    {
    /* Copy destination onto itself: nop */
    return TRUE;
    }

  OutputRect = *DestRect;
  if (OutputRect.right < OutputRect.left)
    {
    OutputRect.left = DestRect->right;
    OutputRect.right = DestRect->left;
    }
  if (OutputRect.bottom < OutputRect.top)
    {
    OutputRect.left = DestRect->right;
    OutputRect.right = DestRect->left;
    }

  if (UsesSource)
    {
    if (NULL == SourcePoint)
      {
      return FALSE;
      }

    /* Make sure we don't try to copy anything outside the valid source
       region */
    InputPoint = *SourcePoint;
    if (InputPoint.x < 0)
      {
        OutputRect.left -= InputPoint.x;
        InputPoint.x = 0;
      }
    if (InputPoint.y < 0)
      {
        OutputRect.top -= InputPoint.y;
        InputPoint.y = 0;
      }
    if (SourceObj->sizlBitmap.cx < InputPoint.x +
                                   OutputRect.right - OutputRect.left)
      {
        OutputRect.right = OutputRect.left +
                           SourceObj->sizlBitmap.cx - InputPoint.x;
      }
    if (SourceObj->sizlBitmap.cy < InputPoint.y +
                                   OutputRect.bottom - OutputRect.top)
      {
        OutputRect.bottom = OutputRect.top +
                            SourceObj->sizlBitmap.cy - InputPoint.y;
      }

    InputRect.left = InputPoint.x;
    InputRect.right = InputPoint.x + (OutputRect.right - OutputRect.left);
    InputRect.top = InputPoint.y;
    InputRect.bottom = InputPoint.y + (OutputRect.bottom - OutputRect.top);

    if (! IntEngEnter(&EnterLeaveSource, SourceObj, &InputRect, TRUE,
                      &Translate, &InputObj))
      {
      return FALSE;
      }

    InputPoint.x += Translate.x;
    InputPoint.y += Translate.y;
    }
  else
    {
    InputRect.left = 0;
    InputRect.right = DestRect->right - DestRect->left;
    InputRect.top = 0;
    InputRect.bottom = DestRect->bottom - DestRect->top;
    }

  if (NULL != ClipRegion)
    {
      if (OutputRect.left < ClipRegion->rclBounds.left)
	{
	  InputRect.left += ClipRegion->rclBounds.left - OutputRect.left;
	  InputPoint.x += ClipRegion->rclBounds.left - OutputRect.left;
	  OutputRect.left = ClipRegion->rclBounds.left;
	}
      if (ClipRegion->rclBounds.right < OutputRect.right)
	{
	  InputRect.right -=  OutputRect.right - ClipRegion->rclBounds.right;
	  OutputRect.right = ClipRegion->rclBounds.right;
	}
      if (OutputRect.top < ClipRegion->rclBounds.top)
	{
	  InputRect.top += ClipRegion->rclBounds.top - OutputRect.top;
	  InputPoint.y += ClipRegion->rclBounds.top - OutputRect.top;
	  OutputRect.top = ClipRegion->rclBounds.top;
	}
      if (ClipRegion->rclBounds.bottom < OutputRect.bottom)
	{
	  InputRect.bottom -=  OutputRect.bottom - ClipRegion->rclBounds.bottom;
	  OutputRect.bottom = ClipRegion->rclBounds.bottom;
	}
    }

  /* Check for degenerate case: if height or width of OutputRect is 0 pixels
     there's nothing to do */
  if (OutputRect.right <= OutputRect.left ||
      OutputRect.bottom <= OutputRect.top)

⌨️ 快捷键说明

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