riched20: Add support for saving enhanced metafiles.

Huw Davies huw at codeweavers.com
Tue Jun 7 05:18:23 CDT 2016


Signed-off-by: Huw Davies <huw at codeweavers.com>
---
 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 76cf5d7..f76d5a5 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 &&
-- 
2.8.2




More information about the wine-patches mailing list