/*********************************************************************** * MFDRV_SetDIBitsToDeivce */ INT 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 = DIB_BitmapInfoSize(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; }
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 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 = DIB_BitmapInfoSize(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; }
/*********************************************************************** * EMFDRV_CreateBrushIndirect */ DWORD EMFDRV_CreateBrushIndirect( DC *dc, 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_AddHandleDC( dc ); emr.lb = logbrush; if(!EMFDRV_WriteRecord( dc, &emr.emr )) index = 0; } break; case BS_DIBPATTERN: { EMRCREATEDIBPATTERNBRUSHPT *emr; DWORD bmSize, biSize, size; BITMAPINFO *info = GlobalLock16(logbrush.lbHatch); if (info->bmiHeader.biCompression) bmSize = info->bmiHeader.biSizeImage; else bmSize = DIB_GetDIBImageBytes(info->bmiHeader.biWidth, info->bmiHeader.biHeight, info->bmiHeader.biBitCount); biSize = DIB_BitmapInfoSize(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_AddHandleDC( dc ); emr->iUsage = LOWORD(logbrush.lbColor); emr->offBmi = sizeof(EMRCREATEDIBPATTERNBRUSHPT); emr->cbBmi = biSize; emr->offBits = sizeof(EMRCREATEDIBPATTERNBRUSHPT) + biSize; memcpy((char *)emr + sizeof(EMRCREATEDIBPATTERNBRUSHPT), info, biSize + bmSize ); if(!EMFDRV_WriteRecord( dc, &emr->emr )) index = 0; HeapFree( GetProcessHeap(), 0, emr ); GlobalUnlock16(logbrush.lbHatch); } break; case BS_PATTERN: FIXME("Unsupported style %x\n", logbrush.lbStyle); 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; }
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 ); }