/*********************************************************************** * 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_PATTERN: case BS_DIBPATTERN: { EMRCREATEDIBPATTERNBRUSHPT *emr; char buffer[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )]; BITMAPINFO *info = (BITMAPINFO *)buffer; DWORD info_size; void *bits; UINT usage; if (!get_brush_bitmap_info( hBrush, info, &bits, &usage )) break; info_size = get_dib_info_size( info, usage ); emr = HeapAlloc( GetProcessHeap(), 0, sizeof(EMRCREATEDIBPATTERNBRUSHPT)+info_size+info->bmiHeader.biSizeImage ); if(!emr) break; if (logbrush.lbStyle == BS_PATTERN && info->bmiHeader.biBitCount == 1) { /* 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->emr.iType = EMR_CREATEMONOBRUSH; usage = DIB_PAL_MONO; /* FIXME: There is an extra DWORD written by native before the BMI. * Not sure what its meant to contain. */ emr->offBmi = sizeof( EMRCREATEDIBPATTERNBRUSHPT ) + sizeof(DWORD); emr->cbBmi = sizeof( BITMAPINFOHEADER ); } else { emr->emr.iType = EMR_CREATEDIBPATTERNBRUSHPT; emr->offBmi = sizeof( EMRCREATEDIBPATTERNBRUSHPT ); emr->cbBmi = info_size; } emr->ihBrush = index = EMFDRV_AddHandle( dev, hBrush ); emr->iUsage = usage; emr->offBits = emr->offBmi + emr->cbBmi; emr->cbBits = info->bmiHeader.biSizeImage; emr->emr.nSize = emr->offBits + emr->cbBits; memcpy( (BYTE *)emr + emr->offBmi, info, emr->cbBmi ); memcpy( (BYTE *)emr + emr->offBits, bits, emr->cbBits ); 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; 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: case BS_DIBPATTERN: { char buffer[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )]; BITMAPINFO *dst_info, *src_info = (BITMAPINFO *)buffer; DWORD info_size; char *dst_ptr; void *bits; UINT usage; if (!get_brush_bitmap_info( hBrush, src_info, &bits, &usage )) goto done; info_size = get_dib_info_size( src_info, usage ); size = FIELD_OFFSET( METARECORD, rdParm[2] ) + info_size + src_info->bmiHeader.biSizeImage; if (!(mr = HeapAlloc( GetProcessHeap(), 0, size ))) goto done; mr->rdFunction = META_DIBCREATEPATTERNBRUSH; mr->rdSize = size / 2; mr->rdParm[0] = logbrush.lbStyle; mr->rdParm[1] = usage; dst_info = (BITMAPINFO *)(mr->rdParm + 2); memcpy( dst_info, src_info, info_size ); if (dst_info->bmiHeader.biClrUsed == 1 << dst_info->bmiHeader.biBitCount) dst_info->bmiHeader.biClrUsed = 0; dst_ptr = (char *)dst_info + info_size; /* 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 ); 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 + i * width_bytes, width_bytes ); } else memcpy( dst_ptr, bits, src_info->bmiHeader.biSizeImage ); 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 ); }