riched20: Added support for image reading from RTF stream.

This commit is contained in:
Eric Pouech 2008-01-27 19:02:21 +01:00 committed by Alexandre Julliard
parent 1e62b0e3b0
commit e5f91bab15
2 changed files with 162 additions and 1 deletions

View file

@ -692,6 +692,163 @@ static void ME_RTFTblAttrHook(RTF_Info *info)
}
}
static BOOL ME_RTFInsertOleObject(RTF_Info *info, HENHMETAFILE h, const SIZEL* sz)
{
LPOLEOBJECT lpObject = NULL;
LPSTORAGE lpStorage = NULL;
LPOLECLIENTSITE lpClientSite = NULL;
LPDATAOBJECT lpDataObject = NULL;
LPOLECACHE lpOleCache = NULL;
STGMEDIUM stgm;
FORMATETC fm;
CLSID clsid;
BOOL ret = FALSE;
DWORD conn;
stgm.tymed = TYMED_ENHMF;
stgm.u.hEnhMetaFile = h;
stgm.pUnkForRelease = NULL;
fm.cfFormat = CF_ENHMETAFILE;
fm.ptd = NULL;
fm.dwAspect = DVASPECT_CONTENT;
fm.lindex = -1;
fm.tymed = stgm.tymed;
if (!info->lpRichEditOle)
{
CreateIRichEditOle(info->editor, (VOID**)&info->lpRichEditOle);
}
if (OleCreateDefaultHandler(&CLSID_NULL, NULL, &IID_IOleObject, (void**)&lpObject) == S_OK &&
#if 0
/* FIXME: enable it when rich-edit properly implements this method */
IRichEditOle_GetClientSite(info->lpRichEditOle, &lpClientSite) == S_OK &&
IOleObject_SetClientSite(lpObject, lpClientSite) == S_OK &&
#endif
IOleObject_GetUserClassID(lpObject, &clsid) == S_OK &&
IOleObject_QueryInterface(lpObject, &IID_IOleCache, (void**)&lpOleCache) == S_OK &&
IOleCache_Cache(lpOleCache, &fm, 0, &conn) == S_OK &&
IOleObject_QueryInterface(lpObject, &IID_IDataObject, (void**)&lpDataObject) == S_OK &&
IDataObject_SetData(lpDataObject, &fm, &stgm, TRUE) == S_OK)
{
REOBJECT reobject;
reobject.cbStruct = sizeof(reobject);
reobject.cp = REO_CP_SELECTION;
reobject.clsid = clsid;
reobject.poleobj = lpObject;
reobject.pstg = lpStorage;
reobject.polesite = lpClientSite;
/* convert from twips to .01 mm */
reobject.sizel.cx = MulDiv(sz->cx, 254, 144);
reobject.sizel.cy = MulDiv(sz->cy, 254, 144);
reobject.dvaspect = DVASPECT_CONTENT;
reobject.dwFlags = 0; /* FIXME */
reobject.dwUser = 0;
/* FIXME: could be simpler */
ret = IRichEditOle_InsertObject(info->lpRichEditOle, &reobject) == S_OK;
}
if (lpObject) IOleObject_Release(lpObject);
if (lpClientSite) IOleClientSite_Release(lpClientSite);
if (lpStorage) IStorage_Release(lpStorage);
if (lpDataObject) IDataObject_Release(lpDataObject);
if (lpOleCache) IOleCache_Release(lpOleCache);
return ret;
}
static void ME_RTFReadPictGroup(RTF_Info *info)
{
SIZEL sz;
BYTE* buffer = NULL;
unsigned bufsz, bufidx;
BOOL flip;
BYTE val;
METAFILEPICT mfp;
HENHMETAFILE hemf;
RTFGetToken (info);
if (info->rtfClass == rtfEOF)
return;
mfp.mm = MM_TEXT;
/* fetch picture type */
if (RTFCheckMM (info, rtfPictAttr, rtfWinMetafile))
{
mfp.mm = info->rtfParam;
}
else
{
FIXME("%d %d\n", info->rtfMajor, info->rtfMinor);
goto skip_group;
}
sz.cx = sz.cy = 0;
/* fetch picture attributes */
for (;;)
{
RTFGetToken (info);
if (info->rtfClass == rtfEOF)
return;
if (info->rtfClass == rtfText)
break;
if (!RTFCheckCM (info, rtfControl, rtfPictAttr))
{
ERR("Expected picture attribute (%d %d)\n",
info->rtfClass, info->rtfMajor);
goto skip_group;
}
else if (RTFCheckMM (info, rtfPictAttr, rtfPicWid))
mfp.xExt = info->rtfParam;
else if (RTFCheckMM (info, rtfPictAttr, rtfPicHt))
mfp.yExt = info->rtfParam;
else if (RTFCheckMM (info, rtfPictAttr, rtfPicGoalWid))
sz.cx = info->rtfParam;
else if (RTFCheckMM (info, rtfPictAttr, rtfPicGoalHt))
sz.cy = info->rtfParam;
else
FIXME("Non supported attribute: %d %d %d\n", info->rtfClass, info->rtfMajor, info->rtfMinor);
}
/* fetch picture data */
bufsz = 1024;
bufidx = 0;
buffer = HeapAlloc(GetProcessHeap(), 0, bufsz);
val = info->rtfMajor;
for (flip = TRUE;; flip = !flip)
{
RTFGetToken (info);
if (info->rtfClass == rtfEOF)
{
HeapFree(GetProcessHeap(), 0, buffer);
return; /* Warn ?? */
}
if (RTFCheckCM(info, rtfGroup, rtfEndGroup))
break;
if (info->rtfClass != rtfText) goto skip_group;
if (flip)
{
if (bufidx >= bufsz &&
!(buffer = HeapReAlloc(GetProcessHeap(), 0, buffer, bufsz += 1024)))
goto skip_group;
buffer[bufidx++] = RTFCharToHex(val) * 16 + RTFCharToHex(info->rtfMajor);
}
else
val = info->rtfMajor;
}
if (flip) FIXME("wrong hex string\n");
if ((hemf = SetWinMetaFileBits(bufidx, buffer, NULL, &mfp)))
ME_RTFInsertOleObject(info, hemf, &sz);
HeapFree(GetProcessHeap(), 0, buffer);
RTFRouteToken (info); /* feed "}" back to router */
return;
skip_group:
HeapFree(GetProcessHeap(), 0, buffer);
RTFSkipGroup(info);
RTFRouteToken(info); /* feed "}" back to router */
}
static void ME_RTFReadHook(RTF_Info *info) {
switch(info->rtfClass)
{
@ -830,12 +987,15 @@ static LRESULT ME_StreamIn(ME_TextEditor *editor, DWORD format, EDITSTREAM *stre
WriterInit(&parser);
RTFInit(&parser);
RTFSetReadHook(&parser, ME_RTFReadHook);
RTFSetDestinationCallback(&parser, rtfPict, ME_RTFReadPictGroup);
BeginFile(&parser);
/* do the parsing */
RTFRead(&parser);
RTFFlushOutputBuffer(&parser);
RTFDestroy(&parser);
if (parser.lpRichEditOle)
IRichEditOle_Release(parser.lpRichEditOle);
style = parser.style;
}

View file

@ -1103,6 +1103,7 @@ struct _RTF_Info {
RTFState stack[maxStack];
int stackTop;
BOOL styleChanged;
LPRICHEDITOLE lpRichEditOle;
};