/*********************************************************************** * MFDRV_SetDIBitsToDeivce */ INT CDECL MFDRV_SetDIBitsToDevice( PHYSDEV dev, INT xDst, INT yDst, DWORD cx, DWORD cy, INT xSrc, INT ySrc, UINT startscan, UINT lines, LPCVOID bits, const BITMAPINFO *info, UINT coloruse ) { DWORD len, infosize, imagesize; METARECORD *mr; infosize = bitmap_info_size(info, coloruse); imagesize = DIB_GetDIBImageBytes( info->bmiHeader.biWidth, info->bmiHeader.biHeight, info->bmiHeader.biBitCount ); len = sizeof(METARECORD) + 8 * sizeof(WORD) + infosize + imagesize; mr = HeapAlloc( GetProcessHeap(), 0, len ); if(!mr) return 0; mr->rdSize = len / 2; mr->rdFunction = META_SETDIBTODEV; mr->rdParm[0] = coloruse; mr->rdParm[1] = lines; mr->rdParm[2] = startscan; mr->rdParm[3] = (INT16)ySrc; mr->rdParm[4] = (INT16)xSrc; mr->rdParm[5] = (INT16)cy; mr->rdParm[6] = (INT16)cx; mr->rdParm[7] = (INT16)yDst; mr->rdParm[8] = (INT16)xDst; memcpy(mr->rdParm + 9, info, infosize); memcpy(mr->rdParm + 9 + infosize / 2, bits, imagesize); MFDRV_WriteRecord( dev, mr, mr->rdSize * 2 ); HeapFree( GetProcessHeap(), 0, mr ); return lines; }
INT CDECL EMFDRV_SetDIBitsToDevice( PHYSDEV dev, INT xDst, INT yDst, DWORD width, DWORD height, INT xSrc, INT ySrc, UINT startscan, UINT lines, LPCVOID bits, const BITMAPINFO *info, UINT wUsage ) { EMRSETDIBITSTODEVICE* pEMR; DWORD size, bmiSize, bitsSize; bmiSize = bitmap_info_size(info, wUsage); bitsSize = DIB_GetDIBImageBytes( info->bmiHeader.biWidth, info->bmiHeader.biHeight, info->bmiHeader.biBitCount ); size = sizeof(EMRSETDIBITSTODEVICE) + bmiSize + bitsSize; pEMR = HeapAlloc(GetProcessHeap(), 0, size); if (!pEMR) return 0; pEMR->emr.iType = EMR_SETDIBITSTODEVICE; pEMR->emr.nSize = size; pEMR->rclBounds.left = xDst; pEMR->rclBounds.top = yDst; pEMR->rclBounds.right = xDst + width - 1; pEMR->rclBounds.bottom = yDst + height - 1; pEMR->xDest = xDst; pEMR->yDest = yDst; pEMR->xSrc = xSrc; pEMR->ySrc = ySrc; pEMR->cxSrc = width; pEMR->cySrc = height; pEMR->offBmiSrc = sizeof(EMRSETDIBITSTODEVICE); pEMR->cbBmiSrc = bmiSize; pEMR->offBitsSrc = sizeof(EMRSETDIBITSTODEVICE) + bmiSize; pEMR->cbBitsSrc = bitsSize; pEMR->iUsageSrc = wUsage; pEMR->iStartScan = startscan; pEMR->cScans = lines; memcpy((BYTE*)pEMR + pEMR->offBmiSrc, info, bmiSize); memcpy((BYTE*)pEMR + pEMR->offBitsSrc, bits, bitsSize); if (EMFDRV_WriteRecord(dev, (EMR*)pEMR)) EMFDRV_UpdateBBox(dev, &(pEMR->rclBounds)); HeapFree( GetProcessHeap(), 0, pEMR); return lines; }
/*********************************************************************** * BRUSH_SelectDIBPatternBrush */ static BOOL BRUSH_SelectDIBPatternBrush( X11DRV_PDEVICE *physDev, HGLOBAL mem ) { BOOL ret; HDC memdc; BITMAPINFO *info = GlobalLock( mem ); HBITMAP bitmap = CreateDIBitmap( physDev->dev.hdc, &info->bmiHeader, CBM_INIT, (LPBYTE)info + bitmap_info_size( info, DIB_RGB_COLORS ), info, DIB_RGB_COLORS ); /* make sure it's owned by x11drv */ memdc = CreateCompatibleDC( physDev->dev.hdc ); SelectObject( memdc, bitmap ); DeleteDC( memdc ); if ((ret = BRUSH_SelectPatternBrush( physDev, bitmap ))) { X_PHYSBITMAP *physBitmap = X11DRV_get_phys_bitmap( bitmap ); physBitmap->pixmap = 0; /* so it doesn't get freed */ } DeleteObject( bitmap ); GlobalUnlock( mem ); return ret; }
static HGLOBAL dib_copy(const BITMAPINFO *info, UINT coloruse) { BITMAPINFO *newInfo; HGLOBAL hmem; INT size; if (info->bmiHeader.biCompression != BI_RGB && info->bmiHeader.biCompression != BI_BITFIELDS) size = info->bmiHeader.biSizeImage; else size = DIB_GetDIBImageBytes(info->bmiHeader.biWidth, info->bmiHeader.biHeight, info->bmiHeader.biBitCount); size += bitmap_info_size( info, coloruse ); if (!(hmem = GlobalAlloc( GMEM_MOVEABLE, size ))) { return 0; } newInfo = GlobalLock( hmem ); memcpy( newInfo, info, size ); GlobalUnlock( hmem ); return hmem; }
/*********************************************************************** * MFDRV_StretchDIBits */ INT CDECL MFDRV_StretchDIBits( PHYSDEV dev, INT xDst, INT yDst, INT widthDst, INT heightDst, INT xSrc, INT ySrc, INT widthSrc, INT heightSrc, const void *bits, const BITMAPINFO *info, UINT wUsage, DWORD dwRop ) { DWORD len, infosize, imagesize; METARECORD *mr; infosize = bitmap_info_size(info, wUsage); imagesize = DIB_GetDIBImageBytes( info->bmiHeader.biWidth, info->bmiHeader.biHeight, info->bmiHeader.biBitCount ); len = sizeof(METARECORD) + 10 * sizeof(WORD) + infosize + imagesize; mr = HeapAlloc( GetProcessHeap(), 0, len ); if(!mr) return 0; mr->rdSize = len / 2; mr->rdFunction = META_STRETCHDIB; mr->rdParm[0] = LOWORD(dwRop); mr->rdParm[1] = HIWORD(dwRop); mr->rdParm[2] = wUsage; mr->rdParm[3] = (INT16)heightSrc; mr->rdParm[4] = (INT16)widthSrc; mr->rdParm[5] = (INT16)ySrc; mr->rdParm[6] = (INT16)xSrc; mr->rdParm[7] = (INT16)heightDst; mr->rdParm[8] = (INT16)widthDst; mr->rdParm[9] = (INT16)yDst; mr->rdParm[10] = (INT16)xDst; memcpy(mr->rdParm + 11, info, infosize); memcpy(mr->rdParm + 11 + infosize / 2, bits, imagesize); MFDRV_WriteRecord( dev, mr, mr->rdSize * 2 ); HeapFree( GetProcessHeap(), 0, mr ); return heightSrc; }
INT16 MFDRV_CreateBrushIndirect(PHYSDEV dev, HBRUSH hBrush ) { DWORD size; METARECORD *mr; LOGBRUSH logbrush; BOOL r; if (!GetObjectA( hBrush, sizeof(logbrush), &logbrush )) return -1; switch(logbrush.lbStyle) { case BS_SOLID: case BS_NULL: case BS_HATCHED: { LOGBRUSH16 lb16; lb16.lbStyle = logbrush.lbStyle; lb16.lbColor = logbrush.lbColor; lb16.lbHatch = logbrush.lbHatch; size = sizeof(METARECORD) + sizeof(LOGBRUSH16) - 2; mr = HeapAlloc( GetProcessHeap(), 0, size ); mr->rdSize = size / 2; mr->rdFunction = META_CREATEBRUSHINDIRECT; memcpy( mr->rdParm, &lb16, sizeof(LOGBRUSH16)); break; } case BS_PATTERN: { char buffer[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )]; BITMAPINFO *dst_info, *src_info = (BITMAPINFO *)buffer; struct gdi_image_bits bits; COLORREF cref; if (!get_bitmap_image( (HANDLE)logbrush.lbHatch, src_info, &bits )) goto done; if (src_info->bmiHeader.biBitCount != 1) { FIXME("Trying to store a colour pattern brush\n"); if (bits.free) bits.free( &bits ); goto done; } size = FIELD_OFFSET( METARECORD, rdParm[2] ) + FIELD_OFFSET( BITMAPINFO, bmiColors[2] ) + src_info->bmiHeader.biSizeImage; if (!(mr = HeapAlloc( GetProcessHeap(), 0, size ))) { if (bits.free) bits.free( &bits ); goto done; } mr->rdFunction = META_DIBCREATEPATTERNBRUSH; mr->rdSize = size / 2; mr->rdParm[0] = BS_PATTERN; mr->rdParm[1] = DIB_RGB_COLORS; dst_info = (BITMAPINFO *)(mr->rdParm + 2); dst_info->bmiHeader = src_info->bmiHeader; dst_info->bmiHeader.biClrUsed = 0; cref = GetTextColor( dev->hdc ); dst_info->bmiColors[0].rgbRed = GetRValue(cref); dst_info->bmiColors[0].rgbGreen = GetGValue(cref); dst_info->bmiColors[0].rgbBlue = GetBValue(cref); dst_info->bmiColors[0].rgbReserved = 0; cref = GetBkColor( dev->hdc ); dst_info->bmiColors[1].rgbRed = GetRValue(cref); dst_info->bmiColors[1].rgbGreen = GetGValue(cref); dst_info->bmiColors[1].rgbBlue = GetBValue(cref); dst_info->bmiColors[1].rgbReserved = 0; /* always return a bottom-up DIB */ if (dst_info->bmiHeader.biHeight < 0) { int i, width_bytes = get_dib_stride( dst_info->bmiHeader.biWidth, dst_info->bmiHeader.biBitCount ); char *dst_ptr = (char *)&dst_info->bmiColors[2]; dst_info->bmiHeader.biHeight = -dst_info->bmiHeader.biHeight; dst_ptr += (dst_info->bmiHeader.biHeight - 1) * width_bytes; for (i = 0; i < dst_info->bmiHeader.biHeight; i++, dst_ptr -= width_bytes) memcpy( dst_ptr, (char *)bits.ptr + i * width_bytes, width_bytes ); } else memcpy( &dst_info->bmiColors[2], bits.ptr, dst_info->bmiHeader.biSizeImage ); if (bits.free) bits.free( &bits ); break; } case BS_DIBPATTERN: { BITMAPINFO *info; DWORD bmSize, biSize; info = GlobalLock( (HGLOBAL)logbrush.lbHatch ); if (info->bmiHeader.biCompression) bmSize = info->bmiHeader.biSizeImage; else bmSize = get_dib_image_size( info ); biSize = bitmap_info_size(info, LOWORD(logbrush.lbColor)); size = sizeof(METARECORD) + biSize + bmSize + 2; mr = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size); if (!mr) { GlobalUnlock( (HGLOBAL)logbrush.lbHatch ); goto done; } mr->rdFunction = META_DIBCREATEPATTERNBRUSH; mr->rdSize = size / 2; *(mr->rdParm) = logbrush.lbStyle; *(mr->rdParm + 1) = LOWORD(logbrush.lbColor); memcpy(mr->rdParm + 2, info, biSize + bmSize); GlobalUnlock( (HGLOBAL)logbrush.lbHatch ); break; } default: FIXME("Unkonwn brush style %x\n", logbrush.lbStyle); return 0; } r = MFDRV_WriteRecord( dev, mr, mr->rdSize * 2); HeapFree(GetProcessHeap(), 0, mr); if( !r ) return -1; done: return MFDRV_AddHandle( dev, hBrush ); }
BOOL CDECL MFDRV_StretchBlt( PHYSDEV devDst, INT xDst, INT yDst, INT widthDst, INT heightDst, PHYSDEV devSrc, INT xSrc, INT ySrc, INT widthSrc, INT heightSrc, DWORD rop ) { BOOL ret; DWORD len; METARECORD *mr; BITMAP BM; METAFILEDRV_PDEVICE *physDevSrc = (METAFILEDRV_PDEVICE *)devSrc; #ifdef STRETCH_VIA_DIB LPBITMAPINFOHEADER lpBMI; WORD nBPP; #endif HBITMAP hBitmap = GetCurrentObject(physDevSrc->hdc, OBJ_BITMAP); if (GetObjectW(hBitmap, sizeof(BITMAP), &BM) != sizeof(BITMAP)) { WARN("bad bitmap object %p passed for hdc %p\n", hBitmap, physDevSrc->hdc); return FALSE; } #ifdef STRETCH_VIA_DIB nBPP = BM.bmPlanes * BM.bmBitsPixel; if(nBPP > 8) nBPP = 24; /* FIXME Can't get 16bpp to work for some reason */ len = sizeof(METARECORD) + 10 * sizeof(INT16) + sizeof(BITMAPINFOHEADER) + (nBPP <= 8 ? 1 << nBPP: 0) * sizeof(RGBQUAD) + DIB_GetDIBWidthBytes(BM.bmWidth, nBPP) * BM.bmHeight; if (!(mr = HeapAlloc( GetProcessHeap(), 0, len))) return FALSE; mr->rdFunction = META_DIBSTRETCHBLT; lpBMI=(LPBITMAPINFOHEADER)(mr->rdParm+10); lpBMI->biSize = sizeof(BITMAPINFOHEADER); lpBMI->biWidth = BM.bmWidth; lpBMI->biHeight = BM.bmHeight; lpBMI->biPlanes = 1; lpBMI->biBitCount = nBPP; lpBMI->biSizeImage = DIB_GetDIBWidthBytes(BM.bmWidth, nBPP) * lpBMI->biHeight; lpBMI->biClrUsed = nBPP <= 8 ? 1 << nBPP : 0; lpBMI->biCompression = BI_RGB; lpBMI->biXPelsPerMeter = MulDiv(GetDeviceCaps(physDevSrc->hdc,LOGPIXELSX),3937,100); lpBMI->biYPelsPerMeter = MulDiv(GetDeviceCaps(physDevSrc->hdc,LOGPIXELSY),3937,100); lpBMI->biClrImportant = 0; /* 1 meter = 39.37 inch */ TRACE("MF_StretchBltViaDIB->len = %d rop=%x PixYPM=%d Caps=%d\n", len,rop,lpBMI->biYPelsPerMeter,GetDeviceCaps(physDevSrc->hdc, LOGPIXELSY)); if (GetDIBits(physDevSrc->hdc, hBitmap, 0, (UINT)lpBMI->biHeight, (LPSTR)lpBMI + bitmap_info_size( (BITMAPINFO *)lpBMI, DIB_RGB_COLORS ), (LPBITMAPINFO)lpBMI, DIB_RGB_COLORS)) #else len = sizeof(METARECORD) + 15 * sizeof(INT16) + BM.bmWidthBytes * BM.bmHeight; if (!(mr = HeapAlloc( GetProcessHeap(), 0, len ))) return FALSE; mr->rdFunction = META_STRETCHBLT; *(mr->rdParm +10) = BM.bmWidth; *(mr->rdParm +11) = BM.bmHeight; *(mr->rdParm +12) = BM.bmWidthBytes; *(mr->rdParm +13) = BM.bmPlanes; *(mr->rdParm +14) = BM.bmBitsPixel; TRACE("len = %ld rop=%lx\n", len, rop); if (GetBitmapBits( hBitmap, BM.bmWidthBytes * BM.bmHeight, mr->rdParm + 15)) #endif { mr->rdSize = len / sizeof(INT16); *(mr->rdParm) = LOWORD(rop); *(mr->rdParm + 1) = HIWORD(rop); *(mr->rdParm + 2) = heightSrc; *(mr->rdParm + 3) = widthSrc; *(mr->rdParm + 4) = ySrc; *(mr->rdParm + 5) = xSrc; *(mr->rdParm + 6) = heightDst; *(mr->rdParm + 7) = widthDst; *(mr->rdParm + 8) = yDst; *(mr->rdParm + 9) = xDst; ret = MFDRV_WriteRecord( devDst, mr, mr->rdSize * 2); } else ret = FALSE; HeapFree( GetProcessHeap(), 0, mr); return ret; }
/*********************************************************************** * EMFDRV_CreateBrushIndirect */ DWORD EMFDRV_CreateBrushIndirect( PHYSDEV dev, HBRUSH hBrush ) { DWORD index = 0; LOGBRUSH logbrush; if (!GetObjectA( hBrush, sizeof(logbrush), &logbrush )) return 0; switch (logbrush.lbStyle) { case BS_SOLID: case BS_HATCHED: case BS_NULL: { EMRCREATEBRUSHINDIRECT emr; emr.emr.iType = EMR_CREATEBRUSHINDIRECT; emr.emr.nSize = sizeof(emr); emr.ihBrush = index = EMFDRV_AddHandle( dev, hBrush ); emr.lb.lbStyle = logbrush.lbStyle; emr.lb.lbColor = logbrush.lbColor; emr.lb.lbHatch = logbrush.lbHatch; if(!EMFDRV_WriteRecord( dev, &emr.emr )) index = 0; } break; case BS_DIBPATTERN: { EMRCREATEDIBPATTERNBRUSHPT *emr; DWORD bmSize, biSize, size; BITMAPINFO *info = GlobalLock( (HGLOBAL)logbrush.lbHatch ); if (info->bmiHeader.biCompression) bmSize = info->bmiHeader.biSizeImage; else bmSize = get_dib_image_size( info ); biSize = bitmap_info_size(info, LOWORD(logbrush.lbColor)); size = sizeof(EMRCREATEDIBPATTERNBRUSHPT) + biSize + bmSize; emr = HeapAlloc( GetProcessHeap(), 0, size ); if(!emr) break; emr->emr.iType = EMR_CREATEDIBPATTERNBRUSHPT; emr->emr.nSize = size; emr->ihBrush = index = EMFDRV_AddHandle( dev, hBrush ); emr->iUsage = LOWORD(logbrush.lbColor); emr->offBmi = sizeof(EMRCREATEDIBPATTERNBRUSHPT); emr->cbBmi = biSize; emr->offBits = sizeof(EMRCREATEDIBPATTERNBRUSHPT) + biSize; emr->cbBits = bmSize; memcpy((char *)emr + sizeof(EMRCREATEDIBPATTERNBRUSHPT), info, biSize + bmSize ); if(!EMFDRV_WriteRecord( dev, &emr->emr )) index = 0; HeapFree( GetProcessHeap(), 0, emr ); GlobalUnlock( (HGLOBAL)logbrush.lbHatch ); } break; case BS_PATTERN: { EMRCREATEDIBPATTERNBRUSHPT *emr; char buffer[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )]; BITMAPINFO *dst_info, *src_info = (BITMAPINFO *)buffer; struct gdi_image_bits bits; DWORD size; if (!get_bitmap_image( (HANDLE)logbrush.lbHatch, src_info, &bits )) break; if (src_info->bmiHeader.biBitCount != 1) { FIXME("Trying to create a color pattern brush\n"); if (bits.free) bits.free( &bits ); break; } /* FIXME: There is an extra DWORD written by native before the BMI. * Not sure what its meant to contain. */ size = sizeof(EMRCREATEDIBPATTERNBRUSHPT) + sizeof(DWORD) + sizeof(BITMAPINFOHEADER) + src_info->bmiHeader.biSizeImage; emr = HeapAlloc( GetProcessHeap(), 0, size ); if(!emr) { if (bits.free) bits.free( &bits ); break; } dst_info = (BITMAPINFO *)((LPBYTE)(emr + 1) + sizeof(DWORD)); dst_info->bmiHeader = src_info->bmiHeader; memcpy( &dst_info->bmiHeader + 1, bits.ptr, dst_info->bmiHeader.biSizeImage ); if (bits.free) bits.free( &bits ); 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 supports 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)dst_info - (LPBYTE)emr; emr->cbBmi = sizeof( BITMAPINFOHEADER ); emr->offBits = emr->offBmi + emr->cbBmi; emr->cbBits = dst_info->bmiHeader.biSizeImage; if(!EMFDRV_WriteRecord( dev, &emr->emr )) index = 0; HeapFree( GetProcessHeap(), 0, emr ); } break; default: FIXME("Unknown style %x\n", logbrush.lbStyle); break; } return index; }
INT CDECL EMFDRV_StretchDIBits( PHYSDEV dev, INT xDst, INT yDst, INT widthDst, INT heightDst, INT xSrc, INT ySrc, INT widthSrc, INT heightSrc, const void *bits, const BITMAPINFO *info, UINT wUsage, DWORD dwRop ) { EMRSTRETCHDIBITS *emr; BOOL ret; UINT bmi_size=0, bits_size, emr_size; bits_size = DIB_GetDIBImageBytes(info->bmiHeader.biWidth, info->bmiHeader.biHeight, info->bmiHeader.biBitCount); /* calculate the size of the colour table */ bmi_size = bitmap_info_size(info, wUsage); emr_size = sizeof (EMRSTRETCHDIBITS) + bmi_size + bits_size; emr = HeapAlloc(GetProcessHeap(), 0, emr_size ); if (!emr) return 0; /* write a bitmap info header (with colours) to the record */ memcpy( &emr[1], info, bmi_size); /* write bitmap bits to the record */ memcpy ( ( (BYTE *) (&emr[1]) ) + bmi_size, bits, bits_size); /* fill in the EMR header at the front of our piece of memory */ emr->emr.iType = EMR_STRETCHDIBITS; emr->emr.nSize = emr_size; emr->xDest = xDst; emr->yDest = yDst; emr->cxDest = widthDst; emr->cyDest = heightDst; emr->dwRop = dwRop; emr->xSrc = xSrc; /* FIXME: only save the piece of the bitmap needed */ emr->ySrc = ySrc; emr->iUsageSrc = wUsage; emr->offBmiSrc = sizeof (EMRSTRETCHDIBITS); emr->cbBmiSrc = bmi_size; emr->offBitsSrc = emr->offBmiSrc + bmi_size; emr->cbBitsSrc = bits_size; emr->cxSrc = widthSrc; emr->cySrc = heightSrc; emr->rclBounds.left = xDst; emr->rclBounds.top = yDst; emr->rclBounds.right = xDst + widthDst; emr->rclBounds.bottom = yDst + heightDst; /* save the record we just created */ ret = EMFDRV_WriteRecord( dev, &emr->emr ); if(ret) EMFDRV_UpdateBBox( dev, &emr->rclBounds ); HeapFree(GetProcessHeap(), 0, emr); return ret ? heightSrc : GDI_ERROR; }
/*********************************************************************** * EMFDRV_CreateBrushIndirect */ DWORD EMFDRV_CreateBrushIndirect( PHYSDEV dev, HBRUSH hBrush ) { DWORD index = 0; LOGBRUSH logbrush; if (!GetObjectA( hBrush, sizeof(logbrush), &logbrush )) return 0; switch (logbrush.lbStyle) { case BS_SOLID: case BS_HATCHED: case BS_NULL: { EMRCREATEBRUSHINDIRECT emr; emr.emr.iType = EMR_CREATEBRUSHINDIRECT; emr.emr.nSize = sizeof(emr); emr.ihBrush = index = EMFDRV_AddHandle( dev, hBrush ); emr.lb.lbStyle = logbrush.lbStyle; emr.lb.lbColor = logbrush.lbColor; emr.lb.lbHatch = logbrush.lbHatch; if(!EMFDRV_WriteRecord( dev, &emr.emr )) index = 0; } break; case BS_DIBPATTERN: { EMRCREATEDIBPATTERNBRUSHPT *emr; DWORD bmSize, biSize, size; BITMAPINFO *info = GlobalLock( (HGLOBAL)logbrush.lbHatch ); if (info->bmiHeader.biCompression) bmSize = info->bmiHeader.biSizeImage; else bmSize = DIB_GetDIBImageBytes(info->bmiHeader.biWidth, info->bmiHeader.biHeight, info->bmiHeader.biBitCount); biSize = bitmap_info_size(info, LOWORD(logbrush.lbColor)); size = sizeof(EMRCREATEDIBPATTERNBRUSHPT) + biSize + bmSize; emr = HeapAlloc( GetProcessHeap(), 0, size ); if(!emr) break; emr->emr.iType = EMR_CREATEDIBPATTERNBRUSHPT; emr->emr.nSize = size; emr->ihBrush = index = EMFDRV_AddHandle( dev, hBrush ); emr->iUsage = LOWORD(logbrush.lbColor); emr->offBmi = sizeof(EMRCREATEDIBPATTERNBRUSHPT); emr->cbBmi = biSize; emr->offBits = sizeof(EMRCREATEDIBPATTERNBRUSHPT) + biSize; emr->cbBits = bmSize; memcpy((char *)emr + sizeof(EMRCREATEDIBPATTERNBRUSHPT), info, biSize + bmSize ); if(!EMFDRV_WriteRecord( dev, &emr->emr )) index = 0; HeapFree( GetProcessHeap(), 0, emr ); GlobalUnlock( (HGLOBAL)logbrush.lbHatch ); } break; case BS_PATTERN: { 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 be DIB compatible 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 supports 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; } return index; }
/*********************************************************************** * SelectBrush (X11DRV.@) */ HBRUSH CDECL X11DRV_SelectBrush( X11DRV_PDEVICE *physDev, HBRUSH hbrush ) { LOGBRUSH logbrush; HBITMAP hBitmap; BITMAPINFO * bmpInfo; if (!GetObjectA( hbrush, sizeof(logbrush), &logbrush )) return 0; TRACE("hdc=%p hbrush=%p\n", physDev->hdc,hbrush); if (physDev->brush.pixmap) { wine_tsx11_lock(); XFreePixmap( gdi_display, physDev->brush.pixmap ); wine_tsx11_unlock(); physDev->brush.pixmap = 0; } physDev->brush.style = logbrush.lbStyle; if (hbrush == GetStockObject( DC_BRUSH )) logbrush.lbColor = GetDCBrushColor( physDev->hdc ); switch(logbrush.lbStyle) { case BS_NULL: TRACE("BS_NULL\n" ); break; case BS_SOLID: TRACE("BS_SOLID\n" ); BRUSH_SelectSolidBrush( physDev, logbrush.lbColor ); break; case BS_HATCHED: TRACE("BS_HATCHED\n" ); physDev->brush.pixel = X11DRV_PALETTE_ToPhysical( physDev, logbrush.lbColor ); wine_tsx11_lock(); physDev->brush.pixmap = XCreateBitmapFromData( gdi_display, root_window, HatchBrushes[logbrush.lbHatch], 8, 8 ); wine_tsx11_unlock(); physDev->brush.fillStyle = FillStippled; break; case BS_PATTERN: TRACE("BS_PATTERN\n"); if (!BRUSH_SelectPatternBrush( physDev, (HBITMAP)logbrush.lbHatch )) return 0; break; case BS_DIBPATTERN: TRACE("BS_DIBPATTERN\n"); if ((bmpInfo = GlobalLock( (HGLOBAL)logbrush.lbHatch ))) { int size = bitmap_info_size( bmpInfo, logbrush.lbColor ); hBitmap = CreateDIBitmap( physDev->hdc, &bmpInfo->bmiHeader, CBM_INIT, ((char *)bmpInfo) + size, bmpInfo, (WORD)logbrush.lbColor ); BRUSH_SelectPatternBrush( physDev, hBitmap ); DeleteObject( hBitmap ); GlobalUnlock( (HGLOBAL)logbrush.lbHatch ); } break; } return hbrush; }
/*********************************************************************** * create_icon_from_bmi * * Create an icon from its BITMAPINFO. */ static HICON create_icon_from_bmi( const BITMAPINFO *bmi, DWORD maxsize, HMODULE module, LPCWSTR resname, HRSRC rsrc, POINT hotspot, BOOL bIcon, INT width, INT height, UINT cFlag ) { DWORD size, color_size, mask_size; HBITMAP color = 0, mask = 0, alpha = 0; const void *color_bits, *mask_bits; BITMAPINFO *bmi_copy; BOOL ret = FALSE; BOOL do_stretch; HICON hObj = 0; HDC hdc = 0; /* Check bitmap header */ if (maxsize < sizeof(BITMAPCOREHEADER)) { return 0; } if (maxsize < bmi->bmiHeader.biSize) { WARN( "invalid header size %u\n", bmi->bmiHeader.biSize ); return 0; } if ( (bmi->bmiHeader.biSize != sizeof(BITMAPCOREHEADER)) && (bmi->bmiHeader.biSize != sizeof(BITMAPINFOHEADER) || (bmi->bmiHeader.biCompression != BI_RGB && bmi->bmiHeader.biCompression != BI_BITFIELDS)) ) { WARN( "invalid bitmap header %u\n", bmi->bmiHeader.biSize ); return 0; } size = bitmap_info_size( bmi, DIB_RGB_COLORS ); color_size = get_dib_image_size( bmi->bmiHeader.biWidth, bmi->bmiHeader.biHeight / 2, bmi->bmiHeader.biBitCount ); mask_size = get_dib_image_size( bmi->bmiHeader.biWidth, bmi->bmiHeader.biHeight / 2, 1 ); if (size > maxsize || color_size > maxsize - size) { WARN( "truncated file %u < %u+%u+%u\n", maxsize, size, color_size, mask_size ); return 0; } if (mask_size > maxsize - size - color_size) mask_size = 0; /* no mask */ if (cFlag & LR_DEFAULTSIZE) { if (!width) width = GetSystemMetrics( bIcon ? SM_CXICON : SM_CXCURSOR ); if (!height) height = GetSystemMetrics( bIcon ? SM_CYICON : SM_CYCURSOR ); } else { if (!width) width = bmi->bmiHeader.biWidth; if (!height) height = bmi->bmiHeader.biHeight/2; } do_stretch = (bmi->bmiHeader.biHeight/2 != height) || (bmi->bmiHeader.biWidth != width); /* Scale the hotspot */ if (bIcon) { hotspot.x = width / 2; hotspot.y = height / 2; } else if (do_stretch) { hotspot.x = (hotspot.x * width) / bmi->bmiHeader.biWidth; hotspot.y = (hotspot.y * height) / (bmi->bmiHeader.biHeight / 2); } if (!screen_dc) screen_dc = CreateDCW( DISPLAYW, NULL, NULL, NULL ); if (!screen_dc) return 0; if (!(bmi_copy = (BITMAPINFO*)HeapAlloc( GetProcessHeap(), 0, max( size, FIELD_OFFSET( BITMAPINFO, bmiColors[2] ))))) return 0; if (!(hdc = CreateCompatibleDC( 0 ))) goto done; memcpy( bmi_copy, bmi, size ); bmi_copy->bmiHeader.biHeight /= 2; color_bits = (const char*)bmi + size; mask_bits = (const char*)color_bits + color_size; alpha = 0; if (is_dib_monochrome( bmi )) { if (!(mask = CreateBitmap( width, height * 2, 1, 1, NULL ))) goto done; color = 0; /* copy color data into second half of mask bitmap */ SelectObject( hdc, mask ); StretchDIBits( hdc, 0, height, width, height, 0, 0, bmi_copy->bmiHeader.biWidth, bmi_copy->bmiHeader.biHeight, color_bits, bmi_copy, DIB_RGB_COLORS, SRCCOPY ); } else { if (!(mask = CreateBitmap( width, height, 1, 1, NULL ))) goto done; if (!(color = CreateBitmap( width, height, GetDeviceCaps( screen_dc, PLANES ), GetDeviceCaps( screen_dc, BITSPIXEL ), NULL ))) { DeleteObject( mask ); goto done; } SelectObject( hdc, color ); StretchDIBits( hdc, 0, 0, width, height, 0, 0, bmi_copy->bmiHeader.biWidth, bmi_copy->bmiHeader.biHeight, color_bits, bmi_copy, DIB_RGB_COLORS, SRCCOPY ); if (bmi_has_alpha( bmi_copy, color_bits )) alpha = create_alpha_bitmap(bmi_copy, color_bits ,width,height); /* convert info to monochrome to copy the mask */ bmi_copy->bmiHeader.biBitCount = 1; if (bmi_copy->bmiHeader.biSize != sizeof(BITMAPCOREHEADER)) { RGBQUAD *rgb = bmi_copy->bmiColors; bmi_copy->bmiHeader.biClrUsed = bmi_copy->bmiHeader.biClrImportant = 2; rgb[0].rgbBlue = rgb[0].rgbGreen = rgb[0].rgbRed = 0x00; rgb[1].rgbBlue = rgb[1].rgbGreen = rgb[1].rgbRed = 0xff; rgb[0].rgbReserved = rgb[1].rgbReserved = 0; } else { RGBTRIPLE *rgb = (RGBTRIPLE *)(((BITMAPCOREHEADER *)bmi_copy) + 1); rgb[0].rgbtBlue = rgb[0].rgbtGreen = rgb[0].rgbtRed = 0x00; rgb[1].rgbtBlue = rgb[1].rgbtGreen = rgb[1].rgbtRed = 0xff; } } if (mask_size) { SelectObject( hdc, mask ); StretchDIBits( hdc, 0, 0, width, height, 0, 0, bmi_copy->bmiHeader.biWidth, bmi_copy->bmiHeader.biHeight, mask_bits, bmi_copy, DIB_RGB_COLORS, SRCCOPY ); } ret = TRUE; done: DeleteDC( hdc ); HeapFree( GetProcessHeap(), 0, bmi_copy ); if(ret) { ICONINFO iconInfo={0}; iconInfo.fIcon=bIcon; iconInfo.xHotspot=hotspot.x; iconInfo.yHotspot=hotspot.y; if(alpha) { iconInfo.hbmColor=alpha; iconInfo.hbmMask=mask; } else { iconInfo.hbmColor=color; iconInfo.hbmMask=mask; } hObj=CreateIconIndirect(&iconInfo); if(color) DeleteObject( color ); if(alpha) DeleteObject( alpha ); if(mask) DeleteObject( mask ); } return hObj; }
INT16 MFDRV_CreateBrushIndirect(PHYSDEV dev, HBRUSH hBrush ) { DWORD size; METARECORD *mr; LOGBRUSH logbrush; METAFILEDRV_PDEVICE *physDev = (METAFILEDRV_PDEVICE *)dev; BOOL r; if (!GetObjectA( hBrush, sizeof(logbrush), &logbrush )) return -1; switch(logbrush.lbStyle) { case BS_SOLID: case BS_NULL: case BS_HATCHED: { LOGBRUSH16 lb16; lb16.lbStyle = logbrush.lbStyle; lb16.lbColor = logbrush.lbColor; lb16.lbHatch = logbrush.lbHatch; size = sizeof(METARECORD) + sizeof(LOGBRUSH16) - 2; mr = HeapAlloc( GetProcessHeap(), 0, size ); mr->rdSize = size / 2; mr->rdFunction = META_CREATEBRUSHINDIRECT; memcpy( mr->rdParm, &lb16, sizeof(LOGBRUSH16)); break; } case BS_PATTERN: { BITMAP bm; BITMAPINFO *info; DWORD bmSize; COLORREF cref; GetObjectA((HANDLE)logbrush.lbHatch, sizeof(bm), &bm); if(bm.bmBitsPixel != 1 || bm.bmPlanes != 1) { FIXME("Trying to store a colour pattern brush\n"); goto done; } bmSize = DIB_GetDIBImageBytes(bm.bmWidth, bm.bmHeight, DIB_PAL_COLORS); size = sizeof(METARECORD) + sizeof(WORD) + sizeof(BITMAPINFO) + sizeof(RGBQUAD) + bmSize; mr = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size); if(!mr) goto done; mr->rdFunction = META_DIBCREATEPATTERNBRUSH; mr->rdSize = size / 2; mr->rdParm[0] = BS_PATTERN; mr->rdParm[1] = DIB_RGB_COLORS; info = (BITMAPINFO *)(mr->rdParm + 2); info->bmiHeader.biSize = sizeof(BITMAPINFOHEADER); info->bmiHeader.biWidth = bm.bmWidth; info->bmiHeader.biHeight = bm.bmHeight; info->bmiHeader.biPlanes = 1; info->bmiHeader.biBitCount = 1; info->bmiHeader.biSizeImage = bmSize; GetBitmapBits((HANDLE)logbrush.lbHatch, bm.bmHeight * BITMAP_GetWidthBytes (bm.bmWidth, bm.bmBitsPixel), (LPBYTE)info + sizeof(BITMAPINFO) + sizeof(RGBQUAD)); /* Change the padding to be DIB compatible if needed */ if(bm.bmWidth & 31) MFDRV_PadTo32((LPBYTE)info + sizeof(BITMAPINFO) + sizeof(RGBQUAD), bm.bmWidth, bm.bmHeight); /* BMP and DIB have opposite row order conventions */ MFDRV_Reverse((LPBYTE)info + sizeof(BITMAPINFO) + sizeof(RGBQUAD), bm.bmWidth, bm.bmHeight); cref = GetTextColor(physDev->hdc); info->bmiColors[0].rgbRed = GetRValue(cref); info->bmiColors[0].rgbGreen = GetGValue(cref); info->bmiColors[0].rgbBlue = GetBValue(cref); info->bmiColors[0].rgbReserved = 0; cref = GetBkColor(physDev->hdc); info->bmiColors[1].rgbRed = GetRValue(cref); info->bmiColors[1].rgbGreen = GetGValue(cref); info->bmiColors[1].rgbBlue = GetBValue(cref); info->bmiColors[1].rgbReserved = 0; break; } case BS_DIBPATTERN: { BITMAPINFO *info; DWORD bmSize, biSize; info = GlobalLock16((HGLOBAL16)logbrush.lbHatch); if (info->bmiHeader.biCompression) bmSize = info->bmiHeader.biSizeImage; else bmSize = DIB_GetDIBImageBytes(info->bmiHeader.biWidth, info->bmiHeader.biHeight, info->bmiHeader.biBitCount); biSize = bitmap_info_size(info, LOWORD(logbrush.lbColor)); size = sizeof(METARECORD) + biSize + bmSize + 2; mr = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size); if(!mr) goto done; mr->rdFunction = META_DIBCREATEPATTERNBRUSH; mr->rdSize = size / 2; *(mr->rdParm) = logbrush.lbStyle; *(mr->rdParm + 1) = LOWORD(logbrush.lbColor); memcpy(mr->rdParm + 2, info, biSize + bmSize); break; } default: FIXME("Unkonwn brush style %x\n", logbrush.lbStyle); return 0; } r = MFDRV_WriteRecord( dev, mr, mr->rdSize * 2); HeapFree(GetProcessHeap(), 0, mr); if( !r ) return -1; done: return MFDRV_AddHandle( dev, hBrush ); }