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

📄 brush.c

📁 这是一个开放源代码的与WINNT/WIN2K/WIN2003兼容的操作系统
💻 C
📖 第 1 页 / 共 2 页
字号:
/*
 * ReactOS Win32 Subsystem
 *
 * Copyright (C) 1998 - 2004 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: brush.c 28341 2007-08-14 23:22:07Z tkreuzer $
 */

#include <w32k.h>

#define NDEBUG
#include <debug.h>

static const USHORT HatchBrushes[NB_HATCH_STYLES][8] =
{
  {0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00}, /* HS_HORIZONTAL */
  {0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08}, /* HS_VERTICAL   */
  {0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80}, /* HS_FDIAGONAL  */
  {0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01}, /* HS_BDIAGONAL  */
  {0x08, 0x08, 0x08, 0xff, 0x08, 0x08, 0x08, 0x08}, /* HS_CROSS      */
  {0x81, 0x42, 0x24, 0x18, 0x18, 0x24, 0x42, 0x81}  /* HS_DIAGCROSS  */
};

BOOL INTERNAL_CALL
BRUSH_Cleanup(PVOID ObjectBody)
{
  PGDIBRUSHOBJ pBrush = (PGDIBRUSHOBJ)ObjectBody;
  if(pBrush->flAttrs & (GDIBRUSH_IS_HATCH | GDIBRUSH_IS_BITMAP))
  {
    ASSERT(pBrush->hbmPattern);
    GDIOBJ_SetOwnership(GdiHandleTable, pBrush->hbmPattern, PsGetCurrentProcess());
    NtGdiDeleteObject(pBrush->hbmPattern);
  }

  return TRUE;
}

INT FASTCALL
BRUSH_GetObject (PGDIBRUSHOBJ BrushObject, INT Count, LPLOGBRUSH Buffer)
{
   if( Buffer == NULL ) return sizeof(LOGBRUSH);
   if (Count == 0) return 0;

   /* Set colour */
    Buffer->lbColor =  BrushObject->BrushAttr.lbColor;

    /* set Hatch */
    if ((BrushObject->flAttrs & GDIBRUSH_IS_HATCH)!=0)
    {
        /* FIXME : is this right value */
        Buffer->lbHatch = (LONG)BrushObject->hbmPattern;
    }
    else
    {
        Buffer->lbHatch = 0;
    }

    Buffer->lbStyle = 0;

    /* Get the type of style */
    if ((BrushObject->flAttrs & GDIBRUSH_IS_SOLID)!=0)
    {
        Buffer->lbStyle = BS_SOLID;
    }
    else if ((BrushObject->flAttrs & GDIBRUSH_IS_NULL)!=0)
    {
        Buffer->lbStyle = BS_NULL; // BS_HOLLOW
    }
    else if ((BrushObject->flAttrs & GDIBRUSH_IS_HATCH)!=0)
    {
        Buffer->lbStyle = BS_HATCHED;
    }
    else if ((BrushObject->flAttrs & GDIBRUSH_IS_BITMAP)!=0)
    {
        Buffer->lbStyle = BS_PATTERN;
    }
    else if ((BrushObject->flAttrs & GDIBRUSH_IS_DIB)!=0)
    {
        Buffer->lbStyle = BS_DIBPATTERN; 
    }

    /* FIXME 
    else if ((BrushObject->flAttrs & )!=0)
    {
        Buffer->lbStyle = BS_INDEXED;
    }
    else if ((BrushObject->flAttrs & )!=0)
    {
        Buffer->lbStyle = BS_DIBPATTERNPT;
    }
    */

    /* FIXME */
    return sizeof(LOGBRUSH);
}


XLATEOBJ* FASTCALL
IntGdiCreateBrushXlate(PDC Dc, GDIBRUSHOBJ *BrushObj, BOOLEAN *Failed)
{
   XLATEOBJ *Result = NULL;

   if (BrushObj->flAttrs & GDIBRUSH_IS_NULL)
   {
      Result = NULL;
      *Failed = FALSE;
   }
   else if (BrushObj->flAttrs & GDIBRUSH_IS_SOLID)
   {
      Result = IntEngCreateXlate(0, PAL_RGB, Dc->w.hPalette, NULL);
      *Failed = FALSE;
   }
   else
   {
      BITMAPOBJ *Pattern = BITMAPOBJ_LockBitmap(BrushObj->hbmPattern);
      if (Pattern == NULL)
         return NULL;

      /* Special case: 1bpp pattern */
      if (Pattern->SurfObj.iBitmapFormat == BMF_1BPP)
      {
         if (Dc->w.bitsPerPixel != 1)
            Result = IntEngCreateSrcMonoXlate(Dc->w.hPalette, Dc->Dc_Attr.crForegroundClr, Dc->Dc_Attr.crBackgroundClr);
      }
      else if (BrushObj->flAttrs & GDIBRUSH_IS_DIB)
      {
         Result = IntEngCreateXlate(0, 0, Dc->w.hPalette, Pattern->hDIBPalette);
      }

      BITMAPOBJ_UnlockBitmap(Pattern);
      *Failed = FALSE;
   }

   return Result;
}

VOID FASTCALL
IntGdiInitBrushInstance(GDIBRUSHINST *BrushInst, PGDIBRUSHOBJ BrushObj, XLATEOBJ *XlateObj)
{
   ASSERT(BrushInst);
   ASSERT(BrushObj);
   if (BrushObj->flAttrs & GDIBRUSH_IS_NULL)
      BrushInst->BrushObject.iSolidColor = 0;
   else if (BrushObj->flAttrs & GDIBRUSH_IS_SOLID)
      BrushInst->BrushObject.iSolidColor = XLATEOBJ_iXlate(XlateObj, BrushObj->BrushAttr.lbColor);
   else
      BrushInst->BrushObject.iSolidColor = 0xFFFFFFFF;
   BrushInst->BrushObject.pvRbrush = BrushObj->ulRealization;
   BrushInst->BrushObject.flColorType = 0;
   BrushInst->GdiBrushObject = BrushObj;
   BrushInst->XlateObject = XlateObj;
}

/**
 * @name CalculateColorTableSize
 *
 * Internal routine to calculate the number of color table entries.
 *
 * @param BitmapInfoHeader
 *        Input bitmap information header, can be any version of
 *        BITMAPINFOHEADER or BITMAPCOREHEADER.
 *
 * @param ColorSpec
 *        Pointer to variable which specifiing the color mode (DIB_RGB_COLORS
 *        or DIB_RGB_COLORS). On successful return this value is normalized
 *        according to the bitmap info.
 *
 * @param ColorTableSize
 *        On successful return this variable is filled with number of
 *        entries in color table for the image with specified parameters.
 *
 * @return
 *    TRUE if the input values together form a valid image, FALSE otherwise.
 */

BOOL STDCALL
CalculateColorTableSize(
   CONST BITMAPINFOHEADER *BitmapInfoHeader,
   UINT *ColorSpec,
   UINT *ColorTableSize)
{
   WORD BitCount;
   DWORD ClrUsed;
   DWORD Compression;

   /*
    * At first get some basic parameters from the passed BitmapInfoHeader
    * structure. It can have one of the following formats:
    * - BITMAPCOREHEADER (the oldest one with totally different layout
    *                     from the others)
    * - BITMAPINFOHEADER (the standard and most common header)
    * - BITMAPV4HEADER (extension of BITMAPINFOHEADER)
    * - BITMAPV5HEADER (extension of BITMAPV4HEADER)
    */

   if (BitmapInfoHeader->biSize == sizeof(BITMAPCOREHEADER))
   {
      BitCount = ((LPBITMAPCOREHEADER)BitmapInfoHeader)->bcBitCount;
      ClrUsed = 0;
      Compression = BI_RGB;
   }
   else
   {
      BitCount = BitmapInfoHeader->biBitCount;
      ClrUsed = BitmapInfoHeader->biClrUsed;
      Compression = BitmapInfoHeader->biCompression;
   }

   switch (Compression)
   {
      case BI_BITFIELDS:
         if (*ColorSpec == DIB_PAL_COLORS)
            *ColorSpec = DIB_RGB_COLORS;

         if (BitCount != 16 && BitCount != 32)
            return FALSE;

         /*
          * For BITMAPV4HEADER/BITMAPV5HEADER the masks are included in
          * the structure itself (bV4RedMask, bV4GreenMask, and bV4BlueMask).
          * For BITMAPINFOHEADER the color masks are stored in the palette.
          */

         if (BitmapInfoHeader->biSize > sizeof(BITMAPINFOHEADER))
            *ColorTableSize = 0;
         else
            *ColorTableSize = 3;

         return TRUE;

      case BI_RGB:
         switch (BitCount)
         {
            case 1:
               *ColorTableSize = ClrUsed ? min(ClrUsed, 2) : 2;
               return TRUE;

            case 4:
               *ColorTableSize = ClrUsed ? min(ClrUsed, 16) : 16;
               return TRUE;

            case 8:
               *ColorTableSize = ClrUsed ? min(ClrUsed, 256) : 256;
               return TRUE;

            default:
               if (*ColorSpec == DIB_PAL_COLORS)
                  *ColorSpec = DIB_RGB_COLORS;
               if (BitCount != 16 && BitCount != 24 && BitCount != 32)
                  return FALSE;
               *ColorTableSize = ClrUsed;
               return TRUE;
         }

      case BI_RLE4:
         if (BitCount == 4)
         {
            *ColorTableSize = ClrUsed ? min(ClrUsed, 16) : 16;
            return TRUE;
         }
         return FALSE;

      case BI_RLE8:
         if (BitCount == 8)
         {
            *ColorTableSize = ClrUsed ? min(ClrUsed, 256) : 256;
            return TRUE;
         }
         return FALSE;

      case BI_JPEG:
      case BI_PNG:
         *ColorTableSize = ClrUsed;
         return TRUE;

      default:
         return FALSE;
   }
}

HBRUSH STDCALL
IntGdiCreateDIBBrush(
   CONST BITMAPINFO *BitmapInfo,
   UINT ColorSpec,
   UINT BitmapInfoSize,
   CONST VOID *PackedDIB)
{
   HBRUSH hBrush;
   PGDIBRUSHOBJ BrushObject;
   HBITMAP hPattern;
   ULONG_PTR DataPtr;
   UINT PaletteEntryCount;
   PBITMAPOBJ BitmapObject;
   INT PaletteType;

   if (BitmapInfo->bmiHeader.biSize < sizeof(BITMAPINFOHEADER))
   {
      SetLastWin32Error(ERROR_INVALID_PARAMETER);
      return NULL;
   }

   if (!CalculateColorTableSize(&BitmapInfo->bmiHeader, &ColorSpec,
                                &PaletteEntryCount))
   {
      SetLastWin32Error(ERROR_INVALID_PARAMETER);
      return NULL;
   }

   DataPtr = (ULONG_PTR)BitmapInfo + BitmapInfo->bmiHeader.biSize;
   if (ColorSpec == DIB_RGB_COLORS)
      DataPtr += PaletteEntryCount * sizeof(RGBQUAD);
   else
      DataPtr += PaletteEntryCount * sizeof(USHORT);

   hPattern = IntGdiCreateBitmap(BitmapInfo->bmiHeader.biWidth,
                                BitmapInfo->bmiHeader.biHeight,
                                BitmapInfo->bmiHeader.biPlanes,
                                BitmapInfo->bmiHeader.biBitCount,
                                (PVOID)DataPtr);
   if (hPattern == NULL)
   {
      SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY);
      return NULL;
   }

   BitmapObject = BITMAPOBJ_LockBitmap(hPattern);
   ASSERT(BitmapObject != NULL);
   BitmapObject->hDIBPalette = BuildDIBPalette(BitmapInfo, &PaletteType);
   BITMAPOBJ_UnlockBitmap(BitmapObject);

   hBrush = BRUSHOBJ_AllocBrush();
   if (hBrush == NULL)
   {
      NtGdiDeleteObject(hPattern);
      SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY);
      return NULL;
   }

   BrushObject = BRUSHOBJ_LockBrush(hBrush);
   ASSERT(BrushObject != NULL);

   BrushObject->flAttrs |= GDIBRUSH_IS_BITMAP | GDIBRUSH_IS_DIB;
   BrushObject->hbmPattern = hPattern;
   /* FIXME: Fill in the rest of fields!!! */

   GDIOBJ_SetOwnership(GdiHandleTable, hPattern, NULL);

   BRUSHOBJ_UnlockBrush(BrushObject);

   return hBrush;
}

HBRUSH STDCALL
IntGdiCreateHatchBrush(
   INT Style,
   COLORREF Color)
{
   HBRUSH hBrush;
   PGDIBRUSHOBJ BrushObject;
   HBITMAP hPattern;

   if (Style < 0 || Style >= NB_HATCH_STYLES)
   {
      return 0;
   }

   hPattern = IntGdiCreateBitmap(8, 8, 1, 1, (LPBYTE)HatchBrushes[Style]);
   if (hPattern == NULL)
   {
      SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY);
      return NULL;
   }

   hBrush = BRUSHOBJ_AllocBrush();
   if (hBrush == NULL)
   {
      NtGdiDeleteObject(hPattern);
      SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY);
      return NULL;
   }

   BrushObject = BRUSHOBJ_LockBrush(hBrush);
   ASSERT(BrushObject != NULL);

   BrushObject->flAttrs |= GDIBRUSH_IS_HATCH;
   BrushObject->hbmPattern = hPattern;
   BrushObject->BrushAttr.lbColor = Color & 0xFFFFFF;

   GDIOBJ_SetOwnership(GdiHandleTable, hPattern, NULL);

   BRUSHOBJ_UnlockBrush(BrushObject);

   return hBrush;
}

HBRUSH STDCALL
IntGdiCreatePatternBrush(
   HBITMAP hBitmap)
{
   HBRUSH hBrush;
   PGDIBRUSHOBJ BrushObject;
   HBITMAP hPattern;

   hPattern = BITMAPOBJ_CopyBitmap(hBitmap);
   if (hPattern == NULL)
   {
      SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY);
      return NULL;
   }

   hBrush = BRUSHOBJ_AllocBrush();
   if (hBrush == NULL)
   {
      NtGdiDeleteObject(hPattern);
      SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY);
      return NULL;
   }

⌨️ 快捷键说明

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