#include "wine/port.h"
#include <stdarg.h>
+#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include "windef.h"
* black, we can't convert it to a monochrome DDB with
* SetDIBits, because black and white would be inverted.
*/
-static BOOL is_dib_monochrome( const BITMAPINFO* info )
+static inline BOOL is_dib_monochrome( const BITMAPINFO* info )
{
if (info->bmiHeader.biBitCount != 1) return FALSE;
if (info->bmiHeader.biSize == sizeof(BITMAPCOREHEADER))
{
RGBTRIPLE *rgb = ((BITMAPCOREINFO *) info)->bmciColors;
-
+
/* Check if the first color is black */
if ((rgb->rgbtRed == 0) && (rgb->rgbtGreen == 0) && (rgb->rgbtBlue == 0))
{
rgb++;
-
/* Check if the second color is white */
return ((rgb->rgbtRed == 0xff) && (rgb->rgbtGreen == 0xff)
&& (rgb->rgbtBlue == 0xff));
#if 0
PEMREXTSELECTCLIPRGN lpRgn = (PEMREXTSELECTCLIPRGN)mr;
HRGN hRgn = ExtCreateRegion(NULL, lpRgn->cbRgnData, (RGNDATA *)lpRgn->RgnData);
+
ExtSelectClipRgn(hdc, hRgn, (INT)(lpRgn->iMode));
/* ExtSelectClipRgn created a copy of the region */
DeleteObject(hRgn);
lpCreate->cbBmi + lpCreate->cbBits );
if(!lpPackedStruct)
{
- SetLastError(ERROR_NOT_ENOUGH_MEMORY);
+ SetLastError(ERROR_NOT_ENOUGH_MEMORY);
break;
}
(UINT)lpCreate->iUsage );
HeapFree(GetProcessHeap(), 0, lpPackedStruct);
-
break;
}
/* Need to check if the bitmap is monochrome, and if the
two colors are really black and white */
- if (is_dib_monochrome(pbi))
+ if (pCreateMonoBrush->iUsage == DIB_PAL_MONO)
+ {
+ BITMAP bm;
+
+ /* Undocumented iUsage indicates a mono bitmap with no palette table,
+ * aligned to 32 rather than 16 bits.
+ */
+ bm.bmType = 0;
+ bm.bmWidth = pbi->bmiHeader.biWidth;
+ bm.bmHeight = abs(pbi->bmiHeader.biHeight);
+ bm.bmWidthBytes = 4 * ((pbi->bmiHeader.biWidth + 31) / 32);
+ bm.bmPlanes = pbi->bmiHeader.biPlanes;
+ bm.bmBitsPixel = pbi->bmiHeader.biBitCount;
+ bm.bmBits = (BYTE *)mr + pCreateMonoBrush->offBits;
+ hBmp = CreateBitmapIndirect(&bm);
+ }
+ else if (is_dib_monochrome(pbi))
{
/* Top-down DIBs have a negative height */
LONG height = pbi->bmiHeader.biHeight;
- if (height < 0) height = -height;
- hBmp = CreateBitmap(pbi->bmiHeader.biWidth, height, 1, 1, NULL);
+ hBmp = CreateBitmap(pbi->bmiHeader.biWidth, abs(height), 1, 1, NULL);
SetDIBits(hdc, hBmp, 0, pbi->bmiHeader.biHeight,
(BYTE *)mr + pCreateMonoBrush->offBits, pbi, pCreateMonoBrush->iUsage);
}
- else
- {
- hBmp = CreateDIBitmap(hdc, (BITMAPINFOHEADER *)pbi, CBM_INIT,
+ else
+ {
+ hBmp = CreateDIBitmap(hdc, (BITMAPINFOHEADER *)pbi, CBM_INIT,
(BYTE *)mr + pCreateMonoBrush->offBits, pbi, pCreateMonoBrush->iUsage);
}
return ret;
}
-
+
/***********************************************************************
* EMFDRV_SelectBitmap
*/
}
+/* Internal helper for EMFDRV_CreateBrushIndirect():
+ * Change the padding of a bitmap from 16 (BMP) to 32 (DIB) bits.
+ */
+static inline void EMFDRV_PadTo32(LPBYTE lpRows, int height, int width)
+{
+ int bytes16 = 2 * ((width + 15) / 16);
+ int bytes32 = 4 * ((width + 31) / 32);
+ LPBYTE lpSrc, lpDst;
+ int i;
+
+ if (!height)
+ return;
+
+ height = abs(height) - 1;
+ lpSrc = lpRows + height * bytes16;
+ lpDst = lpRows + height * bytes32;
+
+ /* Note that we work backwards so we can re-pad in place */
+ while (height >= 0)
+ {
+ for (i = bytes32; i > bytes16; i--)
+ lpDst[i - 1] = 0; /* Zero the padding bytes */
+ for (; i > 0; i--)
+ lpDst[i - 1] = lpSrc[i - 1]; /* Move image bytes into alignment */
+ lpSrc -= bytes16;
+ lpDst -= bytes32;
+ height--;
+ }
+}
+
/***********************************************************************
* EMFDRV_CreateBrushIndirect
*/
break;
case BS_PATTERN:
- FIXME("Unsupported style %x\n",
- logbrush.lbStyle);
- break;
+ {
+ EMRCREATEDIBPATTERNBRUSHPT *emr;
+ BITMAPINFOHEADER *info;
+ BITMAP bm;
+ DWORD bmSize, biSize, size;
+
+ GetObjectA((HANDLE)logbrush.lbHatch, sizeof(bm), &bm);
+
+ if (bm.bmBitsPixel != 1 || bm.bmPlanes != 1)
+ {
+ FIXME("Trying to create a color pattern brush\n");
+ break;
+ }
+
+ /* BMP will be aligned to 32 bits, not 16 */
+ bmSize = DIB_GetDIBImageBytes(bm.bmWidth, bm.bmHeight, bm.bmBitsPixel);
+
+ biSize = sizeof(BITMAPINFOHEADER);
+ /* FIXME: There is an extra DWORD written by native before the BMI.
+ * Not sure what its meant to contain.
+ */
+ size = sizeof(EMRCREATEDIBPATTERNBRUSHPT) + biSize + bmSize + sizeof(DWORD);
+
+ emr = HeapAlloc( GetProcessHeap(), 0, size );
+ if(!emr)
+ break;
+
+ info = (BITMAPINFOHEADER *)((LPBYTE)emr +
+ sizeof(EMRCREATEDIBPATTERNBRUSHPT) + sizeof(DWORD));
+ info->biSize = sizeof(BITMAPINFOHEADER);
+ info->biWidth = bm.bmWidth;
+ info->biHeight = bm.bmHeight;
+ info->biPlanes = bm.bmPlanes;
+ info->biBitCount = bm.bmBitsPixel;
+ info->biSizeImage = bmSize;
+ GetBitmapBits((HANDLE)logbrush.lbHatch,
+ bm.bmHeight * BITMAP_GetWidthBytes(bm.bmWidth, bm.bmBitsPixel),
+ (LPBYTE)info + sizeof(BITMAPINFOHEADER));
+
+ /* Change the padding to DIB compatable if needed */
+ if (bm.bmWidth & 31)
+ EMFDRV_PadTo32((LPBYTE)info + sizeof(BITMAPINFOHEADER), bm.bmWidth, bm.bmHeight);
+
+ emr->emr.iType = EMR_CREATEMONOBRUSH;
+ emr->emr.nSize = size;
+ emr->ihBrush = index = EMFDRV_AddHandle( dev, hBrush );
+ /* Presumably to reduce the size of the written EMF, MS support an
+ * undocumented iUsage value of 2, indicating a mono bitmap without the
+ * 8 byte 2 entry black/white palette. Stupidly, they could have saved
+ * over 20 bytes more by also ignoring the BITMAPINFO fields that are
+ * irrelevant/constant for monochrome bitmaps.
+ * FIXME: It may be that the DIB functions themselves accept this value.
+ */
+ emr->iUsage = DIB_PAL_MONO;
+ emr->offBmi = (LPBYTE)info - (LPBYTE)emr;
+ emr->cbBmi = biSize;
+ emr->offBits = emr->offBmi + biSize;
+ emr->cbBits = bmSize;
+
+ if(!EMFDRV_WriteRecord( dev, &emr->emr ))
+ index = 0;
+ HeapFree( GetProcessHeap(), 0, emr );
+ }
+ break;
+
default:
FIXME("Unknown style %x\n", logbrush.lbStyle);
break;
/* bitmap.c */
extern HBITMAP BITMAP_CopyBitmap( HBITMAP hbitmap );
extern BOOL BITMAP_SetOwnerDC( HBITMAP hbitmap, DC *dc );
+extern INT BITMAP_GetWidthBytes( INT bmWidth, INT bpp );
/* clipping.c */
extern void CLIPPING_UpdateGCRegion( DC * dc );
/* region.c */
extern BOOL REGION_FrameRgn( HRGN dest, HRGN src, INT x, INT y );
+/* Undocumented value for DIB's iUsage: Indicates a mono DIB w/o pal enties */
+#define DIB_PAL_MONO 2
#endif /* __WINE_GDI_PRIVATE_H */