Files
core/ASCImageStudio3/ASCVectorImage/agg/X__CacheFile.cpp

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;
}