diff options
Diffstat (limited to 'libs/mTextControl/src/ImageDataObjectHlp.cpp')
-rw-r--r-- | libs/mTextControl/src/ImageDataObjectHlp.cpp | 196 |
1 files changed, 103 insertions, 93 deletions
diff --git a/libs/mTextControl/src/ImageDataObjectHlp.cpp b/libs/mTextControl/src/ImageDataObjectHlp.cpp index 71f5824d82..eac28e6c6d 100644 --- a/libs/mTextControl/src/ImageDataObjectHlp.cpp +++ b/libs/mTextControl/src/ImageDataObjectHlp.cpp @@ -22,11 +22,18 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include "stdafx.h" #include "ImageDataObjectHlp.h" +#include "dataobject.h" + +// cache up to 1000 objects +#define MAX_CACHE_SIZE 2000 struct EMFCACHE { - HENHMETAFILE hEmf; + CEMFObject *pEmfObj; + IStorage *pStorage; + IOleObject *pOleObject; HICON hIcon; + HWND hwnd; EMFCACHE *prev; EMFCACHE *next; } *emfCache = nullptr; @@ -37,133 +44,150 @@ void UnloadEmfCache() { while (emfCache) { EMFCACHE *tmp = emfCache->next; + emfCache->pEmfObj->Release(); + emfCache->pStorage->Release(); delete emfCache; emfCache = tmp; } } -HENHMETAFILE CacheIconToEmf(HICON hIcon) +void CleanupEmfCache(HWND hwnd) +{ + EMFCACHE *p = emfCache; + while (p) { + if (p->hwnd == hwnd) { + EMFCACHE *tmp = p; + if (p->prev) p->prev->next = p->next; + if (p->next) p->next->prev = p->prev; + p = p->next; + if (tmp == emfCache) emfCache = p; + tmp->pEmfObj->Release(); + tmp->pOleObject->Release(); + tmp->pStorage->Release(); + delete tmp; + emfCacheSize--; + } + else { + p = p->next; + } + } +} + +IDataObject *CacheIconToIDataObject(HWND hwnd, HICON hIcon, IOleClientSite *pOleClientSite, IStorage **ppStorage, IOleObject **ppOleObject) { - HENHMETAFILE result = nullptr; + IDataObject *result = nullptr; + static const FORMATETC lc_format[] = + { + { CF_ENHMETAFILE, nullptr, DVASPECT_CONTENT, -1, TYMED_ENHMF } + }; + mir_cslock lck(csEmfCache); for (EMFCACHE *p = emfCache; p; p = p->next) - if (p->hIcon == hIcon) { - if (p->prev) { - p->prev->next = p->next; - if (p->next) p->next->prev = p->prev; - p->prev = nullptr; - emfCache->prev = p; - p->next = emfCache; - emfCache = p; - result = CopyEnhMetaFile(emfCache->hEmf, nullptr); - break; - } + if (p->hIcon == hIcon && p->hwnd == hwnd) { + if (p->prev) p->prev->next = p->next; + if (p->next) p->next->prev = p->prev; + p->prev = nullptr; + emfCache->prev = p; + p->next = emfCache; + emfCache = p; + result = emfCache->pEmfObj; + *ppStorage = emfCache->pStorage; + *ppOleObject = emfCache->pOleObject; + break; } // cache new item if (!result) { EMFCACHE *newItem = new EMFCACHE; + + LPLOCKBYTES lpLockBytes = nullptr; + SCODE sc = CreateILockBytesOnHGlobal(nullptr, TRUE, &lpLockBytes); + if (sc != S_OK) { + delete newItem; + return nullptr; + } + + sc = StgCreateDocfileOnILockBytes(lpLockBytes, + STGM_SHARE_EXCLUSIVE | STGM_CREATE | STGM_READWRITE, 0, &newItem->pStorage); + + lpLockBytes->Release(); + + if (sc != S_OK) { + delete newItem; + return nullptr; + } + + HDC emfdc = CreateEnhMetaFile(nullptr, nullptr, nullptr, L"icon"); + DrawIconEx(emfdc, 0, 0, (HICON)hIcon, 16, 16, 0, nullptr, DI_NORMAL); + newItem->pEmfObj = new CEMFObject(CloseEnhMetaFile(emfdc)); + newItem->hIcon = hIcon; + newItem->hwnd = hwnd; + + sc = OleCreateStaticFromData(newItem->pEmfObj, IID_IOleObject, OLERENDER_FORMAT, + (LPFORMATETC)lc_format, pOleClientSite, newItem->pStorage, (void **)&newItem->pOleObject); + + if (sc != S_OK) { + newItem->pStorage->Release(); + newItem->pEmfObj->Release(); + delete newItem; + return nullptr; + } + + OleSetContainedObject(newItem->pOleObject, TRUE); + newItem->prev = nullptr; newItem->next = emfCache; if (emfCache) emfCache->prev = newItem; emfCache = newItem; emfCacheSize++; - HDC emfdc = CreateEnhMetaFile(nullptr, nullptr, nullptr, L"icon"); - DrawIconEx(emfdc, 0, 0, (HICON)hIcon, 16, 16, 0, nullptr, DI_NORMAL); - emfCache->hIcon = hIcon; - emfCache->hEmf = CloseEnhMetaFile(emfdc); - result = CopyEnhMetaFile(emfCache->hEmf, nullptr); + result = emfCache->pEmfObj; + *ppStorage = emfCache->pStorage; + *ppOleObject = emfCache->pOleObject; } - // tail cutoff - if (emfCacheSize > 20) { + // tail cutoff - cache up to MAX_CACHE_SIZE data sources (smaller than 1/2 of 10000 GDI objects) + if (emfCacheSize > MAX_CACHE_SIZE) { int n = 0; EMFCACHE *p; for (p = emfCache; p; p = p->next) - if (++n > 20) + if (++n > MAX_CACHE_SIZE) break; + while (p->next) { EMFCACHE *tmp = p->next; p->next = p->next->next; + tmp->pEmfObj->Release(); + tmp->pStorage->Release(); delete tmp; } - if (p->next) p->next->prev = p; - emfCacheSize = 20; + if (p->next) + p->next->prev = p; + emfCacheSize = MAX_CACHE_SIZE; } return result; } -HRESULT CreateDataObject(const FORMATETC *fmtetc, const STGMEDIUM *stgmed, UINT count, IDataObject **ppDataObject); - // returns true on success, false on failure -//bool InsertBitmap(IRichEditOle* pRichEditOle, HBITMAP hBitmap, HGLOBAL hGlobal) -bool InsertBitmap(IRichEditOle *pRichEditOle, HENHMETAFILE hEmf) +bool InsertBitmap(HWND hwnd, IRichEditOle *pRichEditOle, HICON hIcon) { - SCODE sc; - - // Get the image data object - // - static const FORMATETC lc_format[] = - { - { CF_ENHMETAFILE, nullptr, DVASPECT_CONTENT, -1, TYMED_ENHMF }//, - // { CF_BITMAP, 0, DVASPECT_CONTENT, -1, TYMED_GDI }, - // { CF_TEXT, 0, DVASPECT_CONTENT, -1, TYMED_HGLOBAL } - }; - - STGMEDIUM lc_stgmed[] = - { - { TYMED_ENHMF, { (HBITMAP)hEmf }, nullptr }//, - // { TYMED_GDI, { hBitmap }, 0 }, - // { TYMED_HGLOBAL, { (HBITMAP)hGlobal }, 0 } - }; - - IDataObject *pods; - CreateDataObject(lc_format, lc_stgmed, 1, &pods); - // Get the RichEdit container site - // IOleClientSite *pOleClientSite; pRichEditOle->GetClientSite(&pOleClientSite); - // Initialize a Storage Object - // - LPLOCKBYTES lpLockBytes = nullptr; - sc = CreateILockBytesOnHGlobal(nullptr, TRUE, &lpLockBytes); - if (sc != S_OK) { - pOleClientSite->Release(); - return false; - } - IStorage *pStorage; - sc = StgCreateDocfileOnILockBytes(lpLockBytes, - STGM_SHARE_EXCLUSIVE | STGM_CREATE | STGM_READWRITE, 0, &pStorage); - if (sc != S_OK) { - lpLockBytes->Release(); - pOleClientSite->Release(); - pods->Release(); - return false; - } - - // The final ole object which will be inserted in the richedit control - // IOleObject *pOleObject; - sc = OleCreateStaticFromData(pods, IID_IOleObject, OLERENDER_FORMAT, - (LPFORMATETC)lc_format, pOleClientSite, pStorage, (void **)&pOleObject); - if (sc != S_OK) { - pStorage->Release(); - lpLockBytes->Release(); + IDataObject *pods = CacheIconToIDataObject(hwnd, hIcon, pOleClientSite, &pStorage, &pOleObject); + if (pods == nullptr) { pOleClientSite->Release(); return false; } // all items are "contained" -- this makes our reference to this object // weak -- which is needed for links to embedding silent update. - OleSetContainedObject(pOleObject, TRUE); // Now Add the object to the RichEdit - // REOBJECT reobject = { 0 }; reobject.cbStruct = sizeof(REOBJECT); @@ -174,26 +198,12 @@ bool InsertBitmap(IRichEditOle *pRichEditOle, HENHMETAFILE hEmf) reobject.pstg = pStorage; reobject.dwFlags = REO_BELOWBASELINE; - sc = pOleObject->GetUserClassID(&reobject.clsid); - if (sc != S_OK) { - pOleObject->Release(); - pStorage->Release(); - lpLockBytes->Release(); - pOleClientSite->Release(); + SCODE sc = pOleObject->GetUserClassID(&reobject.clsid); + if (sc != S_OK) return false; - } // Insert the bitmap at the current location in the richedit control - // sc = pRichEditOle->InsertObject(&reobject); - // Release all unnecessary interfaces - // - pOleObject->Release(); - pStorage->Release(); - lpLockBytes->Release(); - pOleClientSite->Release(); - pods->Release(); - return sc == S_OK; } |