mirror of
git://source.winehq.org/git/wine.git
synced 2024-11-03 03:35:55 +00:00
gdi32: Add support for creating EMF spool files.
This commit is contained in:
parent
f79c9f3568
commit
ca66b3eb84
3 changed files with 231 additions and 0 deletions
|
@ -2216,6 +2216,7 @@ BOOL WINAPI CancelDC(HDC hdc)
|
|||
*/
|
||||
INT WINAPI StartDocW( HDC hdc, const DOCINFOW *doc )
|
||||
{
|
||||
DOC_INFO_1W spool_info;
|
||||
WCHAR *output = NULL;
|
||||
struct print *print;
|
||||
DC_ATTR *dc_attr;
|
||||
|
@ -2240,6 +2241,7 @@ INT WINAPI StartDocW( HDC hdc, const DOCINFOW *doc )
|
|||
debugstr_w(info.lpszDatatype), info.fwType);
|
||||
|
||||
if (!(dc_attr = get_dc_attr( hdc ))) return SP_ERROR;
|
||||
if (dc_attr->print && dc_attr->emf) return SP_ERROR;
|
||||
|
||||
proc = (ABORTPROC)(UINT_PTR)dc_attr->abort_proc;
|
||||
if (proc && !proc( hdc, 0 )) return 0;
|
||||
|
@ -2250,6 +2252,23 @@ INT WINAPI StartDocW( HDC hdc, const DOCINFOW *doc )
|
|||
if (!info.lpszOutput) info.lpszOutput = print->output;
|
||||
output = StartDocDlgW( print->printer, &info );
|
||||
if (output) info.lpszOutput = output;
|
||||
|
||||
if (!info.lpszDatatype || !wcsicmp(info.lpszDatatype, L"EMF"))
|
||||
{
|
||||
spool_info.pDocName = (WCHAR *)info.lpszDocName;
|
||||
spool_info.pOutputFile = (WCHAR *)info.lpszOutput;
|
||||
spool_info.pDatatype = (WCHAR *)L"NT EMF 1.003";
|
||||
if ((ret = StartDocPrinterW( print->printer, 1, (BYTE *)&spool_info )))
|
||||
{
|
||||
if (!spool_start_doc( dc_attr, print->printer, &info ))
|
||||
{
|
||||
AbortDoc( hdc );
|
||||
ret = 0;
|
||||
}
|
||||
HeapFree( GetProcessHeap(), 0, output );
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ret = NtGdiStartDoc( hdc, &info, NULL, 0 );
|
||||
|
@ -2306,6 +2325,12 @@ INT WINAPI StartDocA( HDC hdc, const DOCINFOA *doc )
|
|||
*/
|
||||
INT WINAPI StartPage( HDC hdc )
|
||||
{
|
||||
struct print *print;
|
||||
DC_ATTR *dc_attr;
|
||||
|
||||
if (!(dc_attr = get_dc_attr( hdc ))) return SP_ERROR;
|
||||
if ((print = get_dc_print( dc_attr )) && dc_attr->emf)
|
||||
return spool_start_page( dc_attr, print->printer );
|
||||
return NtGdiStartPage( hdc );
|
||||
}
|
||||
|
||||
|
@ -2314,6 +2339,12 @@ INT WINAPI StartPage( HDC hdc )
|
|||
*/
|
||||
INT WINAPI EndPage( HDC hdc )
|
||||
{
|
||||
struct print *print;
|
||||
DC_ATTR *dc_attr;
|
||||
|
||||
if (!(dc_attr = get_dc_attr( hdc ))) return SP_ERROR;
|
||||
if ((print = get_dc_print( dc_attr )) && dc_attr->emf)
|
||||
return spool_end_page( dc_attr, print->printer );
|
||||
return NtGdiEndPage( hdc );
|
||||
}
|
||||
|
||||
|
@ -2322,6 +2353,12 @@ INT WINAPI EndPage( HDC hdc )
|
|||
*/
|
||||
INT WINAPI EndDoc( HDC hdc )
|
||||
{
|
||||
struct print *print;
|
||||
DC_ATTR *dc_attr;
|
||||
|
||||
if (!(dc_attr = get_dc_attr( hdc ))) return SP_ERROR;
|
||||
if ((print = get_dc_print( dc_attr )) && dc_attr->emf)
|
||||
return spool_end_doc( dc_attr, print->printer );
|
||||
return NtGdiEndDoc( hdc );
|
||||
}
|
||||
|
||||
|
@ -2330,6 +2367,12 @@ INT WINAPI EndDoc( HDC hdc )
|
|||
*/
|
||||
INT WINAPI AbortDoc( HDC hdc )
|
||||
{
|
||||
struct print *print;
|
||||
DC_ATTR *dc_attr;
|
||||
|
||||
if (!(dc_attr = get_dc_attr( hdc ))) return SP_ERROR;
|
||||
if ((print = get_dc_print( dc_attr )) && dc_attr->emf)
|
||||
return spool_abort_doc( dc_attr, print->printer );
|
||||
return NtGdiAbortDoc( hdc );
|
||||
}
|
||||
|
||||
|
|
|
@ -44,8 +44,39 @@ struct emf
|
|||
DWORD palette_size;
|
||||
DWORD palette_used;
|
||||
PALETTEENTRY *palette;
|
||||
enum
|
||||
{
|
||||
DOCUMENT_NOT_STARTED,
|
||||
NEEDS_START_PAGE,
|
||||
NEEDS_END_PAGE
|
||||
} document_state;
|
||||
};
|
||||
|
||||
typedef enum
|
||||
{
|
||||
EMRI_METAFILE = 1,
|
||||
EMRI_ENGINE_FONT,
|
||||
EMRI_DEVMODE,
|
||||
EMRI_TYPE1_FONT,
|
||||
EMRI_PRESTARTPAGE,
|
||||
EMRI_DESIGNVECTOR,
|
||||
EMRI_SUBSET_FONT,
|
||||
EMRI_DELTA_FONT,
|
||||
EMRI_FORM_METAFILE,
|
||||
EMRI_BW_METAFILE,
|
||||
EMRI_BW_FORM_METAFILE,
|
||||
EMRI_METAFILE_DATA,
|
||||
EMRI_METAFILE_EXT,
|
||||
EMRI_BW_METAFILE_EXT,
|
||||
EMRI_ENGINE_FONT_EXT,
|
||||
EMRI_TYPE1_FONT_EXT,
|
||||
EMRI_DESIGNVECTOR_EXT,
|
||||
EMRI_SUBSET_FONT_EXT,
|
||||
EMRI_DELTA_FONT_EXT,
|
||||
EMRI_PS_JOB_DATA,
|
||||
EMRI_EMBED_FONT_EXT,
|
||||
} emfspool_record_type;
|
||||
|
||||
#define HANDLE_LIST_INC 20
|
||||
static const RECTL empty_bounds = { 0, 0, -1, -1 };
|
||||
|
||||
|
@ -2474,6 +2505,7 @@ static void emf_reset( DC_ATTR *dc_attr, const RECT *rect )
|
|||
emf->dc_pen = 0;
|
||||
emf->path = FALSE;
|
||||
emf->palette_used = 0;
|
||||
emf->document_state = DOCUMENT_NOT_STARTED;
|
||||
|
||||
dc_attr->emf_bounds.left = dc_attr->emf_bounds.top = 0;
|
||||
dc_attr->emf_bounds.right = dc_attr->emf_bounds.bottom = -1;
|
||||
|
@ -2688,3 +2720,152 @@ HENHMETAFILE WINAPI CloseEnhMetaFile( HDC hdc )
|
|||
DeleteDC( hdc );
|
||||
return hmf;
|
||||
}
|
||||
|
||||
BOOL spool_start_doc( DC_ATTR *dc_attr, HANDLE hspool, const DOCINFOW *doc_info )
|
||||
{
|
||||
struct
|
||||
{
|
||||
unsigned int dwVersion;
|
||||
unsigned int cjSize;
|
||||
unsigned int dpszDocName;
|
||||
unsigned int dpszOutput;
|
||||
} *header;
|
||||
size_t size = sizeof(*header);
|
||||
struct emf *emf;
|
||||
DWORD written;
|
||||
WCHAR *p;
|
||||
|
||||
TRACE( "(%p %p)\n", dc_attr, hspool );
|
||||
|
||||
if (doc_info->lpszDocName)
|
||||
size += (wcslen( doc_info->lpszDocName ) + 1) * sizeof(WCHAR);
|
||||
if (doc_info->lpszOutput)
|
||||
size += (wcslen( doc_info->lpszOutput ) + 1) * sizeof(WCHAR);
|
||||
header = HeapAlloc( GetProcessHeap(), 0, size );
|
||||
if (!header) return FALSE;
|
||||
|
||||
header->dwVersion = 0x10000;
|
||||
header->cjSize = size;
|
||||
p = (WCHAR *)(header + 1);
|
||||
if (doc_info->lpszDocName)
|
||||
{
|
||||
header->dpszDocName = (BYTE *)p - (BYTE *)header;
|
||||
wcscpy( p, doc_info->lpszDocName );
|
||||
p += wcslen( doc_info->lpszDocName ) + 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
header->dpszDocName = 0;
|
||||
}
|
||||
if (doc_info->lpszOutput)
|
||||
{
|
||||
header->dpszOutput = (BYTE *)p - (BYTE *)header;
|
||||
wcscpy( p, doc_info->lpszOutput );
|
||||
}
|
||||
else
|
||||
{
|
||||
header->dpszOutput = 0;
|
||||
}
|
||||
if (!WritePrinter( hspool, header, size, &written )) written = 0;
|
||||
HeapFree( GetProcessHeap(), 0, header );
|
||||
if (written != size) return FALSE;
|
||||
|
||||
emf = emf_create( dc_attr_handle(dc_attr), NULL, NULL );
|
||||
if (!emf) return FALSE;
|
||||
emf->document_state = NEEDS_START_PAGE;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
int spool_start_page( DC_ATTR *dc_attr, HANDLE hspool )
|
||||
{
|
||||
struct emf *emf = get_dc_emf( dc_attr );
|
||||
HDC hdc = dc_attr_handle( dc_attr );
|
||||
POINT pos = { 0 };
|
||||
XFORM xform;
|
||||
|
||||
TRACE( "(%p)\n", dc_attr );
|
||||
|
||||
/* Save current DC state to EMF */
|
||||
/* FIXME: SetTextJustification if needed */
|
||||
EMFDC_SelectObject( dc_attr, GetCurrentObject(hdc, OBJ_PEN) );
|
||||
EMFDC_SelectObject( dc_attr, GetCurrentObject(hdc, OBJ_BRUSH) );
|
||||
EMFDC_SelectObject( dc_attr, GetCurrentObject(hdc, OBJ_FONT) );
|
||||
if (GetBkColor( hdc ) != 0xffffff)
|
||||
EMFDC_SetBkColor( dc_attr, GetBkColor(hdc) );
|
||||
if (GetBkMode( hdc ) != OPAQUE)
|
||||
EMFDC_SetBkMode( dc_attr, GetBkMode(hdc) );
|
||||
GetCurrentPositionEx( hdc, &pos );
|
||||
if (pos.x || pos.y)
|
||||
EMFDC_MoveTo( dc_attr, pos.x, pos.y );
|
||||
if (GetMapMode( hdc ) != MM_TEXT)
|
||||
EMFDC_SetMapMode( dc_attr, GetMapMode(hdc) );
|
||||
if (GetPolyFillMode( hdc ) != ALTERNATE)
|
||||
EMFDC_SetPolyFillMode( dc_attr, GetPolyFillMode(hdc) );
|
||||
if (GetROP2( hdc ) != R2_COPYPEN)
|
||||
EMFDC_SetROP2( dc_attr, GetROP2(hdc) );
|
||||
if (GetStretchBltMode( hdc ) != BLACKONWHITE)
|
||||
EMFDC_SetStretchBltMode( dc_attr, GetStretchBltMode(hdc) );
|
||||
if (GetTextAlign( hdc ) != (TA_LEFT | TA_TOP))
|
||||
EMFDC_SetTextAlign( dc_attr, GetTextAlign(hdc) );
|
||||
if (GetTextColor( hdc ))
|
||||
EMFDC_SetTextColor( dc_attr, GetTextColor(hdc) );
|
||||
GetWorldTransform(hdc, &xform);
|
||||
if (xform.eM11 != 1 || xform.eM22 != 1 || xform.eM12 || xform.eM21 || xform.eDx || xform.eDy)
|
||||
EMFDC_SetWorldTransform( dc_attr, &xform );
|
||||
|
||||
emf->document_state = NEEDS_END_PAGE;
|
||||
return StartPagePrinter( hspool );
|
||||
}
|
||||
|
||||
int spool_end_page( DC_ATTR *dc_attr, HANDLE hspool )
|
||||
{
|
||||
struct record_hdr
|
||||
{
|
||||
unsigned int ulID;
|
||||
unsigned int cjSize;
|
||||
} record_hdr;
|
||||
struct
|
||||
{
|
||||
struct record_hdr hdr;
|
||||
LARGE_INTEGER pos;
|
||||
} metafile_ext;
|
||||
struct emf *emf = get_dc_emf( dc_attr );
|
||||
DWORD written;
|
||||
|
||||
TRACE( "(%p %p)\n", dc_attr, hspool );
|
||||
|
||||
if (!emf_eof( dc_attr )) return 0;
|
||||
|
||||
record_hdr.ulID = EMRI_METAFILE_DATA;
|
||||
record_hdr.cjSize = emf->emh->nBytes;
|
||||
if (!WritePrinter( hspool, &record_hdr, sizeof(record_hdr), &written )) return 0;
|
||||
if (!WritePrinter( hspool, emf->emh, emf->emh->nBytes, &written )) return 0;
|
||||
|
||||
metafile_ext.hdr.ulID = EMRI_METAFILE_EXT;
|
||||
metafile_ext.hdr.cjSize = sizeof(metafile_ext) - sizeof(struct record_hdr);
|
||||
metafile_ext.pos.QuadPart = emf->emh->nBytes + sizeof(record_hdr);
|
||||
if (!WritePrinter( hspool, &metafile_ext, sizeof(metafile_ext), &written )) return 0;
|
||||
|
||||
emf_reset( dc_attr, NULL );
|
||||
emf->document_state = NEEDS_START_PAGE;
|
||||
return EndPagePrinter( hspool );
|
||||
}
|
||||
|
||||
int spool_abort_doc( DC_ATTR *dc_attr, HANDLE hspool )
|
||||
{
|
||||
TRACE( "(%p %p)\n", dc_attr, hspool );
|
||||
|
||||
EMFDC_DeleteDC( dc_attr );
|
||||
return AbortPrinter( hspool );
|
||||
}
|
||||
|
||||
int spool_end_doc( DC_ATTR *dc_attr, HANDLE hspool )
|
||||
{
|
||||
struct emf *emf = get_dc_emf( dc_attr );
|
||||
|
||||
TRACE( "(%p %p)\n", dc_attr, hspool );
|
||||
|
||||
if (emf->document_state == NEEDS_END_PAGE) spool_end_page( dc_attr, hspool );
|
||||
EMFDC_DeleteDC( dc_attr );
|
||||
return EndDocPrinter( hspool );
|
||||
}
|
||||
|
|
|
@ -280,6 +280,13 @@ extern BOOL EMFDC_WidenPath( DC_ATTR *dc_attr ) DECLSPEC_HIDDEN;
|
|||
extern HENHMETAFILE EMF_Create_HENHMETAFILE( ENHMETAHEADER *emh, DWORD filesize,
|
||||
BOOL on_disk ) DECLSPEC_HIDDEN;
|
||||
|
||||
extern BOOL spool_start_doc( DC_ATTR *dc_attr, HANDLE hspool,
|
||||
const DOCINFOW *doc_info ) DECLSPEC_HIDDEN;
|
||||
extern int spool_start_page( DC_ATTR *dc_attr, HANDLE hspool ) DECLSPEC_HIDDEN;
|
||||
extern int spool_end_page( DC_ATTR *dc_attr, HANDLE hspool ) DECLSPEC_HIDDEN;
|
||||
extern int spool_end_doc( DC_ATTR *dc_attr, HANDLE hspool ) DECLSPEC_HIDDEN;
|
||||
extern int spool_abort_doc( DC_ATTR *dc_attr, HANDLE hspool ) DECLSPEC_HIDDEN;
|
||||
|
||||
static inline int get_dib_stride( int width, int bpp )
|
||||
{
|
||||
return ((width * bpp + 31) >> 3) & ~3;
|
||||
|
|
Loading…
Reference in a new issue