From 8477dcf909b529cb6c079e0579b265a16243a95c Mon Sep 17 00:00:00 2001 From: Huw Davies Date: Tue, 7 Jun 2016 11:18:23 +0100 Subject: [PATCH] riched20: Add support for saving enhanced metafiles. Signed-off-by: Huw Davies Signed-off-by: Alexandre Julliard --- dlls/riched20/writer.c | 94 +++++++++++++++++++++++++++++++++++++++++- 1 file changed, 93 insertions(+), 1 deletion(-) diff --git a/dlls/riched20/writer.c b/dlls/riched20/writer.c index 76cf5d73ce1..f76d5a5b745 100644 --- a/dlls/riched20/writer.c +++ b/dlls/riched20/writer.c @@ -21,6 +21,8 @@ #include "config.h" #include "wine/port.h" +#define NONAMELESSUNION + #include "editor.h" #include "rtf.h" @@ -115,6 +117,32 @@ ME_StreamOutPrint(ME_OutStream *pStream, const char *format, ...) return ME_StreamOutMove(pStream, string, len); } +#define HEX_BYTES_PER_LINE 40 + +static BOOL +ME_StreamOutHexData(ME_OutStream *stream, const BYTE *data, UINT len) +{ + + char line[HEX_BYTES_PER_LINE * 2 + 1]; + UINT size, i; + static const char hex[] = "0123456789abcdef"; + + while (len) + { + size = min( len, HEX_BYTES_PER_LINE ); + for (i = 0; i < size; i++) + { + line[i * 2] = hex[(*data >> 4) & 0xf]; + line[i * 2 + 1] = hex[*data & 0xf]; + data++; + } + line[size * 2] = '\n'; + if (!ME_StreamOutMove( stream, line, size * 2 + 1 )) + return FALSE; + len -= size; + } + return TRUE; +} static BOOL ME_StreamOutRTFHeader(ME_OutStream *pStream, int dwFormat) @@ -783,6 +811,69 @@ ME_StreamOutRTFText(ME_OutStream *pStream, const WCHAR *text, LONG nChars) return ME_StreamOutMove(pStream, buffer, pos); } +static BOOL stream_out_graphics( ME_TextEditor *editor, ME_OutStream *stream, + ME_Run *run ) +{ + IDataObject *data; + HRESULT hr; + FORMATETC fmt = { CF_ENHMETAFILE, NULL, DVASPECT_CONTENT, -1, TYMED_ENHMF }; + STGMEDIUM med = { TYMED_NULL }; + BOOL ret = FALSE; + ENHMETAHEADER *emf_bits = NULL; + UINT size; + SIZE goal, pic; + ME_Context c; + + hr = IOleObject_QueryInterface( run->ole_obj->poleobj, &IID_IDataObject, (void **)&data ); + if (FAILED(hr)) return FALSE; + + ME_InitContext( &c, editor, ITextHost_TxGetDC( editor->texthost ) ); + hr = IDataObject_QueryGetData( data, &fmt ); + if (hr != S_OK) goto done; + + hr = IDataObject_GetData( data, &fmt, &med ); + if (FAILED(hr)) goto done; + if (med.tymed != TYMED_ENHMF) goto done; + + size = GetEnhMetaFileBits( med.u.hEnhMetaFile, 0, NULL ); + if (size < FIELD_OFFSET(ENHMETAHEADER, cbPixelFormat)) goto done; + + emf_bits = HeapAlloc( GetProcessHeap(), 0, size ); + if (!emf_bits) goto done; + + size = GetEnhMetaFileBits( med.u.hEnhMetaFile, size, (BYTE *)emf_bits ); + if (size < FIELD_OFFSET(ENHMETAHEADER, cbPixelFormat)) goto done; + + /* size_in_pixels = (frame_size / 100) * szlDevice / szlMillimeters + pic = size_in_pixels * 2540 / dpi */ + pic.cx = MulDiv( emf_bits->rclFrame.right - emf_bits->rclFrame.left, emf_bits->szlDevice.cx * 254, + emf_bits->szlMillimeters.cx * c.dpi.cx * 10 ); + pic.cy = MulDiv( emf_bits->rclFrame.bottom - emf_bits->rclFrame.top, emf_bits->szlDevice.cy * 254, + emf_bits->szlMillimeters.cy * c.dpi.cy * 10 ); + + /* convert goal size to twips */ + goal.cx = MulDiv( run->ole_obj->sizel.cx, 144, 254 ); + goal.cy = MulDiv( run->ole_obj->sizel.cy, 144, 254 ); + + if (!ME_StreamOutPrint( stream, "{\\*\\shppict{\\pict\\emfblip\\picw%d\\pich%d\\picwgoal%d\\pichgoal%d\n", + pic.cx, pic.cy, goal.cx, goal.cy )) + goto done; + + if (!ME_StreamOutHexData( stream, (BYTE *)emf_bits, size )) + goto done; + + if (!ME_StreamOutPrint( stream, "}}\n" )) + goto done; + + ret = TRUE; + +done: + ME_DestroyContext( &c ); + HeapFree( GetProcessHeap(), 0, emf_bits ); + ReleaseStgMedium( &med ); + IDataObject_Release( data ); + return ret; +} static BOOL ME_StreamOutRTF(ME_TextEditor *editor, ME_OutStream *pStream, const ME_Cursor *start, int nChars, int dwFormat) @@ -834,7 +925,8 @@ static BOOL ME_StreamOutRTF(ME_TextEditor *editor, ME_OutStream *pStream, if (cursor.pPara->member.para.nFlags & (MEPF_ROWSTART|MEPF_ROWEND)) continue; if (cursor.pRun->member.run.nFlags & MERF_GRAPHICS) { - FIXME("embedded objects are not handled\n"); + if (!stream_out_graphics(editor, pStream, &cursor.pRun->member.run)) + return FALSE; } else if (cursor.pRun->member.run.nFlags & MERF_TAB) { if (editor->bEmulateVersion10 && /* v1.0 - 3.0 */ cursor.pPara->member.para.pFmt->dwMask & PFM_TABLE &&