mirror of
https://github.com/ONLYOFFICE/core.git
synced 2026-04-07 13:55:33 +08:00
290 lines
8.2 KiB
C++
290 lines
8.2 KiB
C++
// X__CacheFile.cpp: implementation of the X__CacheFile class.
|
|
//
|
|
//////////////////////////////////////////////////////////////////////
|
|
#include "stdafx.h"
|
|
#include "ap_AggPlusTypes.h"
|
|
#include "X__CacheFile.h"
|
|
#include "ap_Mem.h"
|
|
|
|
#include "../CxImage/CxImage/ximage.h"
|
|
|
|
X__CacheFile Z__CacheFile;
|
|
|
|
|
|
BOOL if_file_exists(LPCWSTR szwFilename)
|
|
{
|
|
HANDLE hFile;
|
|
hFile=CreateFileW(szwFilename,GENERIC_READ,FILE_SHARE_READ,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL);
|
|
if(hFile==INVALID_HANDLE_VALUE)
|
|
{
|
|
if(GetLastError()==ERROR_SHARING_VIOLATION) return(TRUE); //File exists but is open
|
|
return(FALSE);
|
|
}
|
|
CloseHandle(hFile);
|
|
return(TRUE);
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////
|
|
// Construction/Destruction
|
|
//////////////////////////////////////////////////////////////////////
|
|
|
|
X__CacheFile::X__CacheFile()
|
|
{
|
|
m_dwBuffSizeTotal=0;
|
|
m_cache_items.reserve(255);
|
|
}
|
|
|
|
X__CacheFile::~X__CacheFile()
|
|
{
|
|
for(unsigned int i=0;i<m_cache_items.size(); ++i)
|
|
{
|
|
CItem *pItm=(CItem *) m_cache_items.at(i);
|
|
Aggplus::ap_free(pItm->m_pBuff);
|
|
#ifdef _DEBUG
|
|
assert(m_dwBuffSizeTotal>=pItm->m_dwBuffSize);
|
|
m_dwBuffSizeTotal-=pItm->m_dwBuffSize;
|
|
#endif
|
|
delete(pItm);
|
|
}
|
|
/*
|
|
for(CChain *pc_item=m_cache_items.GetPrev(); pc_item; pc_item=pc_item->GetPrev())
|
|
{
|
|
CItem *pItm=(CItem *) pc_item->GetData();
|
|
Aggplus::ap_free(pItm->m_pBuff);
|
|
#ifdef _DEBUG
|
|
assert(m_dwBuffSizeTotal>=pItm->m_dwBuffSize);
|
|
m_dwBuffSizeTotal-=pItm->m_dwBuffSize;
|
|
#endif
|
|
delete(pItm);
|
|
}
|
|
*/
|
|
|
|
}
|
|
|
|
LPVOID X__CacheFile::GetCreateItemBuff(LPCWSTR szwFilename, DWORD *pdwRetWidth, DWORD *pdwRetHeight)
|
|
{
|
|
*pdwRetWidth=*pdwRetHeight=0;
|
|
if(!if_file_exists(szwFilename)) return(NULL);
|
|
|
|
WIN32_FILE_ATTRIBUTE_DATA FileInfo;
|
|
if(!GetFileAttributesExW(szwFilename, GetFileExInfoStandard, &FileInfo)) return(NULL);
|
|
|
|
CKey key_search;
|
|
key_search.m_dwFileSizeLow=FileInfo.nFileSizeLow;
|
|
key_search.m_dwFileSizeHigh=FileInfo.nFileSizeHigh;
|
|
key_search.m_ftCreationTime=FileInfo.ftCreationTime;
|
|
key_search.m_ftLastWriteTime=FileInfo.ftLastWriteTime;
|
|
|
|
//Search Cache
|
|
for(unsigned int i=0;i<m_cache_items.size(); ++i)
|
|
{
|
|
CItem *pItm=(CItem *) m_cache_items.at(i);
|
|
//for(CChain *pc_item=m_cache_items.GetPrev(); pc_item; pc_item=pc_item->GetPrev())
|
|
// {
|
|
// CItem *pItm=(CItem *) pc_item->GetData();
|
|
if( memcmp(&(pItm->m_Key), &key_search, sizeof(CKey)) == 0
|
|
&& wcscmp(pItm->m_wcFilename, szwFilename)==0
|
|
)
|
|
{
|
|
GetSystemTimeAsFileTime(&pItm->m_ftLastRequested);
|
|
*pdwRetWidth=pItm->m_dwWidth;
|
|
*pdwRetHeight=pItm->m_dwHeight;
|
|
pItm->m_nUsage++;
|
|
return(pItm->m_pBuff);
|
|
}
|
|
}
|
|
|
|
|
|
DWORD dwWidth, dwHeight;
|
|
void *ppBuff;
|
|
if(xx_Get_RGBA_from_file(szwFilename, &dwWidth, &dwHeight, &ppBuff))
|
|
{
|
|
if(EnsureFreeSpace(dwWidth*dwHeight*4))
|
|
{
|
|
//Dodadi vo cache i vrati nazad params i buff
|
|
CItem *pItm=new CItem;
|
|
wcscpy(pItm->m_wcFilename, szwFilename);
|
|
|
|
memcpy(&(pItm->m_Key), &key_search, sizeof(CKey));
|
|
|
|
pItm->m_dwWidth=dwWidth;
|
|
pItm->m_dwHeight=dwHeight;
|
|
|
|
pItm->m_pBuff=ppBuff;
|
|
pItm->m_dwBuffSize=dwWidth*dwHeight*4;
|
|
m_dwBuffSizeTotal+=pItm->m_dwBuffSize;
|
|
GetSystemTimeAsFileTime(&pItm->m_ftLastRequested);
|
|
pItm->m_nUsage=1;
|
|
//m_cache_items.Add(pItm);
|
|
m_cache_items.push_back(pItm);
|
|
|
|
*pdwRetWidth=pItm->m_dwWidth;
|
|
*pdwRetHeight=pItm->m_dwHeight;
|
|
//pItm->m_psMemBuff->AddUsage();
|
|
//DbgAddLine("X__CacheFile: %.2f Mb %d items", (double(GetBuffSize())/1024.00)/1024.00, GetCount());
|
|
return(pItm->m_pBuff);
|
|
}
|
|
else
|
|
{
|
|
//No free space, return ordinary pointer
|
|
*pdwRetWidth=dwWidth;
|
|
*pdwRetHeight=dwHeight;
|
|
//DbgAddLine("X__CacheFile: %.2f Mb %d items (NO SPACE)", (double(GetBuffSize())/1024.00)/1024.00, GetCount());
|
|
return(ppBuff);
|
|
}
|
|
}
|
|
|
|
return(NULL);
|
|
}
|
|
|
|
void X__CacheFile::Release(LPVOID pBuff)
|
|
{
|
|
if(!pBuff) return;
|
|
//Search Cache
|
|
for(unsigned int i=0;i<m_cache_items.size(); ++i)
|
|
{
|
|
CItem *pItm=(CItem *) m_cache_items.at(i);
|
|
//for(CChain *pc_item=m_cache_items.GetPrev(); pc_item; pc_item=pc_item->GetPrev())
|
|
// {
|
|
// CItem *pItm=(CItem *) pc_item->GetData();
|
|
if(pItm->m_pBuff == pBuff)
|
|
{
|
|
pItm->m_nUsage--;
|
|
assert(pItm->m_nUsage>=0);
|
|
//DbgAddLine("X__CacheFile: %.2f Mb %d items (Release usage %d)", (double(GetBuffSize())/1024.00)/1024.00, GetCount(), pItm->m_nUsage);
|
|
return;
|
|
}
|
|
}
|
|
|
|
//Invalid-not in cache
|
|
Aggplus::ap_free(pBuff);
|
|
}
|
|
|
|
LPVOID X__CacheFile::GetCreateCopy(LPVOID pSourceBuff, DWORD dwWidth, DWORD dwHeight)
|
|
{
|
|
if(!pSourceBuff) return(NULL);
|
|
//Search Cache
|
|
for(unsigned int i=0;i<m_cache_items.size(); ++i)
|
|
{
|
|
CItem *pItm=(CItem *) m_cache_items.at(i);
|
|
//for(CChain *pc_item=m_cache_items.GetPrev(); pc_item; pc_item=pc_item->GetPrev())
|
|
// {
|
|
// CItem *pItm=(CItem *) pc_item->GetData();
|
|
if(pItm->m_pBuff == pSourceBuff)
|
|
{
|
|
pItm->m_nUsage++;
|
|
//DbgAddLine("X__CacheFile: %.2f Mb %d items (Fnd New usage %d)", (double(GetBuffSize())/1024.00)/1024.00, GetCount(), pItm->m_nUsage);
|
|
return(pSourceBuff);
|
|
}
|
|
}
|
|
|
|
//Invalid-not in cache, return ordinary pointer and copy from source
|
|
LPVOID pRet=Aggplus::ap_malloc16(4*dwWidth*dwHeight);
|
|
memcpy(pRet, pSourceBuff, 4*dwWidth*dwHeight);
|
|
//DbgAddLine("X__CacheFile: %.2f Mb %d items (NO Fnd found)", (double(GetBuffSize())/1024.00)/1024.00, GetCount());
|
|
return(pRet);
|
|
}
|
|
|
|
bool X__CacheFile::EnsureFreeSpace(DWORD dwSize)
|
|
{
|
|
while(GetBuffSize()+dwSize>GetMaxBuffSize())
|
|
{
|
|
//free some space if I can
|
|
FILETIME ftLastRequested={0, 0};
|
|
GetSystemTimeAsFileTime(&ftLastRequested);
|
|
|
|
//CChain *pc_Found=NULL;
|
|
//CItem *pc_Found=NULL;
|
|
int nFound=-1;
|
|
for(unsigned int i=0;i<m_cache_items.size(); ++i)
|
|
{
|
|
CItem *pItm=(CItem *) m_cache_items.at(i);
|
|
//for(CChain *pc_item=m_cache_items.GetPrev(); pc_item; pc_item=pc_item->GetPrev())
|
|
// {
|
|
// CItem *pItm=(CItem *) pc_item->GetData();
|
|
if(pItm->m_nUsage==0)
|
|
{
|
|
if(CompareFileTime(&ftLastRequested, &(pItm->m_ftLastRequested))>0)
|
|
{
|
|
//pc_Found=pc_item;
|
|
nFound=i;
|
|
ftLastRequested=pItm->m_ftLastRequested;
|
|
}
|
|
}
|
|
}
|
|
|
|
//if(pc_Found)
|
|
if(nFound>=0)
|
|
{
|
|
//CItem *pItm=(CItem *) pc_Found->GetData();
|
|
CItem *pItm=(CItem *) m_cache_items.at(nFound);
|
|
//DbgAddLine("X__CacheFile: Delete item %d", nLastUsedIndex);
|
|
assert(m_dwBuffSizeTotal>=pItm->m_dwBuffSize);
|
|
m_dwBuffSizeTotal-=pItm->m_dwBuffSize;
|
|
|
|
Aggplus::ap_free(pItm->m_pBuff);
|
|
delete(pItm);
|
|
//m_cache_items.Remove(pc_Found);
|
|
m_cache_items.erase(m_cache_items.begin() + nFound);
|
|
//TRACE("XC:Remove Item\n");
|
|
}
|
|
else
|
|
{
|
|
return(false);
|
|
}
|
|
}
|
|
return(true);
|
|
}
|
|
|
|
|
|
|
|
BOOL xx_Get_RGBA_from_file(LPCWSTR szwFilename, DWORD *pdwWidth, DWORD *pdwHeight, void **ppBuff)
|
|
{
|
|
if(!szwFilename || wcslen(szwFilename)<4) return(FALSE);
|
|
LPCWSTR wExt=szwFilename+(wcslen(szwFilename)-4);
|
|
|
|
DWORD dwImgType=CXIMAGE_FORMAT_UNKNOWN;
|
|
|
|
if( _wcsicmp(wExt, L".tga")==0) dwImgType=CXIMAGE_FORMAT_TGA; //TGA
|
|
else if(_wcsicmp(wExt, L".png")==0) dwImgType=CXIMAGE_FORMAT_PNG; //PNG
|
|
else if(_wcsicmp(wExt, L".bmp")==0) dwImgType=CXIMAGE_FORMAT_BMP; //BMP
|
|
else if(_wcsicmp(wExt, L".jpg")==0) dwImgType=CXIMAGE_FORMAT_JPG; //JPG
|
|
else if(_wcsicmp(wExt, L".gif")==0) dwImgType=CXIMAGE_FORMAT_GIF; //GIF
|
|
|
|
BOOL retRes = FALSE;
|
|
FILE* hFile = NULL;
|
|
|
|
if(dwImgType!=CXIMAGE_FORMAT_UNKNOWN)
|
|
{
|
|
CxImage MXimage(dwImgType);
|
|
if((hFile=_wfopen(szwFilename, L"rb"))==NULL)
|
|
return FALSE; // For UNICODE support
|
|
|
|
if(MXimage.Decode(hFile,dwImgType))
|
|
{
|
|
DWORD dwWidth=MXimage.GetWidth();
|
|
DWORD dwHeight=MXimage.GetHeight();
|
|
if(!dwWidth || !dwHeight)
|
|
{
|
|
goto endLbl;
|
|
}
|
|
*pdwWidth=dwWidth;
|
|
*pdwHeight=dwHeight;
|
|
(*ppBuff)=Aggplus::ap_malloc16(4*dwWidth*dwHeight);
|
|
MXimage.CopyToBuffRGBA32((*ppBuff));
|
|
retRes = TRUE;
|
|
}
|
|
else
|
|
{
|
|
//TRACE(">>>Load Image Error:%s\n", MXimage.GetLastError());
|
|
}
|
|
}
|
|
|
|
endLbl:
|
|
|
|
if (hFile)
|
|
fclose(hFile);
|
|
|
|
return retRes;
|
|
}
|