summaryrefslogtreecommitdiff
path: root/libs/mTextControl/src/ImageDataObjectHlp.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'libs/mTextControl/src/ImageDataObjectHlp.cpp')
-rw-r--r--libs/mTextControl/src/ImageDataObjectHlp.cpp196
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;
}