Fix errors

This commit is contained in:
Oleg Korshul
2021-10-05 15:13:22 +03:00
parent 54e10c7b55
commit d7c4ceba92
11 changed files with 148 additions and 129 deletions

View File

@ -104,9 +104,6 @@ int CFontStream::CreateFromMemory(BYTE* pData, LONG lSize, bool bClear)
return TRUE; return TRUE;
} }
#ifndef BUILDING_WASM_MODULE
CGlobalFontsMemoryStorage* CApplicationFontStreams::m_pMemoryStorage = NULL;
#endif
CApplicationFontStreams::CApplicationFontStreams() : NSFonts::IApplicationFontStreams() CApplicationFontStreams::CApplicationFontStreams() : NSFonts::IApplicationFontStreams()
{ {
} }
@ -117,12 +114,15 @@ CApplicationFontStreams::~CApplicationFontStreams()
NSFonts::IFontStream* CApplicationFontStreams::GetStream(const std::wstring &strFile) NSFonts::IFontStream* CApplicationFontStreams::GetStream(const std::wstring &strFile)
{ {
CFontStream* pStream = m_mapStreams[strFile]; CFontStream* pStream = m_mapStreams[strFile];
if (NULL != pStream) if (NULL != pStream)
return pStream; return pStream;
if (m_pMemoryStorage)
pStream = m_pMemoryStorage->Get(strFile); if (NSFonts::NSApplicationFontStream::GetGlobalMemoryStorage())
{
pStream = (CFontStream*)NSFonts::NSApplicationFontStream::GetGlobalMemoryStorage()->Get(strFile);
}
else else
{ {
pStream = new CFontStream(); pStream = new CFontStream();
@ -141,10 +141,7 @@ void CApplicationFontStreams::CheckStreams(std::map<std::wstring,bool> &mapFiles
if (mapFiles.find(iter->first) != mapFiles.end()) if (mapFiles.find(iter->first) != mapFiles.end())
{ {
if (m_pMemoryStorage) RELEASEINTERFACE(pFile);
m_pMemoryStorage->Remove(iter->first);
else
RELEASEINTERFACE(pFile);
iter = m_mapStreams.erase(iter); iter = m_mapStreams.erase(iter);
} }
else else
@ -154,15 +151,13 @@ void CApplicationFontStreams::CheckStreams(std::map<std::wstring,bool> &mapFiles
void CApplicationFontStreams::Clear() void CApplicationFontStreams::Clear()
{ {
if (NSFonts::NSApplicationFontStream::GetGlobalMemoryStorage())
NSFonts::NSApplicationFontStream::GetGlobalMemoryStorage()->Clear();
for (std::map<std::wstring, CFontStream*>::iterator iter = m_mapStreams.begin(); iter != m_mapStreams.end(); ++iter) for (std::map<std::wstring, CFontStream*>::iterator iter = m_mapStreams.begin(); iter != m_mapStreams.end(); ++iter)
{ {
if (m_pMemoryStorage) CFontStream* pFile = iter->second;
m_pMemoryStorage->Remove(iter->first); RELEASEINTERFACE(pFile);
else
{
CFontStream* pFile = iter->second;
RELEASEINTERFACE(pFile);
}
} }
m_mapStreams.clear(); m_mapStreams.clear();
} }
@ -701,13 +696,10 @@ INT CFontManager::LoadFontByName(const std::wstring& sName, const double& dSize,
*oFormat.bItalic = TRUE; *oFormat.bItalic = TRUE;
NSFonts::CFontInfo* pInfo = m_pApplication->GetList()->GetByParams(oFormat); NSFonts::CFontInfo* pInfo = m_pApplication->GetList()->GetByParams(oFormat);
if (NULL == pInfo && !((CApplicationFontStreams*)m_pApplication->GetStreams())->m_pMemoryStorage) if (NULL == pInfo)
return FALSE; return FALSE;
INT bLoad = LoadFontFromFile(pInfo->m_wsFontPath, pInfo->m_lIndex, dSize, dDpiX, dDpiY);
INT bLoad = ((CApplicationFontStreams*)m_pApplication->GetStreams())->m_pMemoryStorage ?
LoadFontFromFile(sName, 0, dSize, dDpiX, dDpiY) :
LoadFontFromFile(pInfo->m_wsFontPath, pInfo->m_lIndex, dSize, dDpiX, dDpiY);
if (bLoad == TRUE) if (bLoad == TRUE)
{ {

View File

@ -52,70 +52,13 @@ public:
virtual int CreateFromMemory(BYTE* pData, LONG lSize, bool bClear); virtual int CreateFromMemory(BYTE* pData, LONG lSize, bool bClear);
}; };
class CGlobalFontsMemoryStorage
{
private:
std::map<std::wstring, CFontStream*> m_mapStreams;
void string_replace(std::wstring& text, const std::wstring& replaceFrom, const std::wstring& replaceTo)
{
size_t posn = 0;
while (std::wstring::npos != (posn = text.find(replaceFrom, posn)))
{
text.replace(posn, replaceFrom.length(), replaceTo);
posn += replaceTo.length();
}
}
public:
CGlobalFontsMemoryStorage(){}
~CGlobalFontsMemoryStorage()
{
for (std::map<std::wstring, CFontStream*>::iterator it = m_mapStreams.begin(); it != m_mapStreams.end(); it++)
RELEASEOBJECT(it->second);
m_mapStreams.clear();
}
void Add(const std::wstring& id, BYTE* data, LONG size, bool bClear = false)
{
std::wstring sFile = id;
string_replace(sFile, L"\\", L"/");
std::map<std::wstring, CFontStream*>::iterator it = m_mapStreams.find(sFile);
if (it == m_mapStreams.end())
{
CFontStream* pStream = (CFontStream*)NSFonts::NSStream::Create();
pStream->CreateFromMemory(data, size, bClear);
m_mapStreams.insert({sFile, pStream});
}
}
void Remove(const std::wstring& id)
{
std::wstring sFile = id;
string_replace(sFile, L"\\", L"/");
std::map<std::wstring, CFontStream*>::iterator it = m_mapStreams.find(sFile);
if (it != m_mapStreams.end())
{
RELEASEOBJECT(it->second);
m_mapStreams.erase(it);
}
}
CFontStream* Get(const std::wstring& id)
{
std::wstring sFile = id;
string_replace(sFile, L"\\", L"/");
std::map<std::wstring, CFontStream*>::iterator it = m_mapStreams.find(sFile);
return it != m_mapStreams.end() ? it->second : NULL;
}
};
class CApplicationFontStreams : public NSFonts::IApplicationFontStreams class CApplicationFontStreams : public NSFonts::IApplicationFontStreams
{ {
private: private:
// этот мап нужно периодически опрашивать и удалять неиспользуемые стримы // этот мап нужно периодически опрашивать и удалять неиспользуемые стримы
std::map<std::wstring, CFontStream*> m_mapStreams; std::map<std::wstring, CFontStream*> m_mapStreams;
public:
static CGlobalFontsMemoryStorage* m_pMemoryStorage;
public:
CApplicationFontStreams(); CApplicationFontStreams();
virtual ~CApplicationFontStreams(); virtual ~CApplicationFontStreams();

View File

@ -429,6 +429,20 @@ namespace NSFonts
virtual int CreateFromMemory(BYTE* pData, LONG lSize, bool bClear) = 0; virtual int CreateFromMemory(BYTE* pData, LONG lSize, bool bClear) = 0;
}; };
class GRAPHICS_DECL IFontsMemoryStorage : public NSBase::CBaseRefCounter
{
public:
IFontsMemoryStorage();
virtual ~IFontsMemoryStorage();
virtual bool Add(const std::wstring& id, BYTE* data, LONG size, bool bClear = false) = 0;
virtual bool Remove(const std::wstring& id) = 0;
virtual IFontStream* Get(const std::wstring& id) = 0;
virtual std::wstring GenerateId() = 0;
virtual void Clear() = 0;
};
class GRAPHICS_DECL IApplicationFontStreams : public NSBase::CBaseRefCounter class GRAPHICS_DECL IApplicationFontStreams : public NSBase::CBaseRefCounter
{ {
public: public:
@ -449,6 +463,13 @@ namespace NSFonts
namespace NSApplicationFontStream namespace NSApplicationFontStream
{ {
GRAPHICS_DECL IApplicationFontStreams* Create(); GRAPHICS_DECL IApplicationFontStreams* Create();
// create default
GRAPHICS_DECL IFontsMemoryStorage* CreateDefaultGlobalMemoryStorage();
// without AddRef!!!
GRAPHICS_DECL IFontsMemoryStorage* GetGlobalMemoryStorage();
GRAPHICS_DECL void SetGlobalMemoryStorage(IFontsMemoryStorage* pStorage);
} }
} }

View File

@ -1,7 +1,6 @@
#include <malloc.h> #include <malloc.h>
#include <iostream> #include <iostream>
#include "../../../../GraphicsRenderer.h"
#include "../../../../pro/Graphics.h" #include "../../../../pro/Graphics.h"
#include "../../../../../common/Base64.h" #include "../../../../../common/Base64.h"
#include "drawingfile.h" #include "drawingfile.h"
@ -12,8 +11,6 @@
#define WASM_EXPORT __attribute__((visibility("default"))) #define WASM_EXPORT __attribute__((visibility("default")))
#endif #endif
CGlobalFontsMemoryStorage* CApplicationFontStreams::m_pMemoryStorage = NULL;
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
@ -33,20 +30,20 @@ WASM_EXPORT int GetType (BYTE* data, LONG size)
} }
WASM_EXPORT CGraphicsFileDrawing* Open(BYTE* data, LONG size) WASM_EXPORT CGraphicsFileDrawing* Open(BYTE* data, LONG size)
{ {
// всегда пересоздаем сторадж
NSFonts::NSApplicationFontStream::SetGlobalMemoryStorage(NSFonts::NSApplicationFontStream::CreateDefaultGlobalMemoryStorage());
CGraphicsFileDrawing* pGraphics = new CGraphicsFileDrawing(); CGraphicsFileDrawing* pGraphics = new CGraphicsFileDrawing();
if (pGraphics->Open(data, size, GetType(data, size))) if (pGraphics->Open(data, size, GetType(data, size)))
{
if (!CApplicationFontStreams::m_pMemoryStorage)
CApplicationFontStreams::m_pMemoryStorage = new CGlobalFontsMemoryStorage();
return pGraphics; return pGraphics;
}
delete pGraphics; delete pGraphics;
return NULL; return NULL;
} }
WASM_EXPORT void Close (CGraphicsFileDrawing* pGraphics) WASM_EXPORT void Close (CGraphicsFileDrawing* pGraphics)
{ {
delete pGraphics; delete pGraphics;
RELEASEOBJECT(CApplicationFontStreams::m_pMemoryStorage); NSFonts::NSApplicationFontStream::SetGlobalMemoryStorage(NULL);
} }
WASM_EXPORT int* GetInfo (CGraphicsFileDrawing* pGraphics) WASM_EXPORT int* GetInfo (CGraphicsFileDrawing* pGraphics)
{ {

View File

@ -38,6 +38,8 @@
#include <libkern/OSAtomic.h> #include <libkern/OSAtomic.h>
#endif #endif
NSFonts::IFontsMemoryStorage* g_global_fonts_memory_storage = NULL;
namespace NSFonts namespace NSFonts
{ {
CLibrary::CLibrary() CLibrary::CLibrary()
@ -122,12 +124,96 @@ namespace NSFonts
IApplicationFontStreams::IApplicationFontStreams() : NSBase::CBaseRefCounter() {} IApplicationFontStreams::IApplicationFontStreams() : NSBase::CBaseRefCounter() {}
IApplicationFontStreams::~IApplicationFontStreams() {} IApplicationFontStreams::~IApplicationFontStreams() {}
IFontsMemoryStorage::IFontsMemoryStorage() {}
IFontsMemoryStorage::~IFontsMemoryStorage() {}
namespace NSApplicationFontStream namespace NSApplicationFontStream
{ {
IApplicationFontStreams* Create() IApplicationFontStreams* Create()
{ {
return new CApplicationFontStreams(); return new CApplicationFontStreams();
} }
// default global memory storage
class CDefaultGlobalFontsMemoryStorage : public IFontsMemoryStorage
{
private:
std::map<std::wstring, IFontStream*> m_mapStreams;
int m_nInternalCounter;
public:
CDefaultGlobalFontsMemoryStorage()
{
m_nInternalCounter = 1;
}
virtual ~CDefaultGlobalFontsMemoryStorage()
{
Clear();
}
virtual bool Add(const std::wstring& id, BYTE* data, LONG size, bool bClear = false)
{
std::map<std::wstring, IFontStream*>::iterator it = m_mapStreams.find(id);
if (it != m_mapStreams.end())
return false;
IFontStream* pStream = NSFonts::NSStream::Create();
pStream->CreateFromMemory(data, size, bClear);
m_mapStreams.insert(std::pair<std::wstring, IFontStream*>(id, pStream));
return true;
}
virtual bool Remove(const std::wstring& id)
{
std::map<std::wstring, IFontStream*>::iterator it = m_mapStreams.find(id);
if (it == m_mapStreams.end())
return false;
it->second->Release();
m_mapStreams.erase(it);
return true;
}
virtual void Clear()
{
for (std::map<std::wstring, IFontStream*>::iterator it = m_mapStreams.begin(); it != m_mapStreams.end(); it++)
it->second->Release();
m_mapStreams.clear();
}
virtual IFontStream* Get(const std::wstring& id)
{
std::map<std::wstring, IFontStream*>::iterator it = m_mapStreams.find(id);
return it != m_mapStreams.end() ? it->second : NULL;
}
virtual std::wstring GenerateId()
{
while (true)
{
std::wstring sKey = L"storage_internal_" + std::to_wstring(m_nInternalCounter++);
if (m_mapStreams.find(sKey) == m_mapStreams.end())
return sKey;
}
return L"";
}
};
GRAPHICS_DECL IFontsMemoryStorage* CreateDefaultGlobalMemoryStorage()
{
return new CDefaultGlobalFontsMemoryStorage();
}
GRAPHICS_DECL IFontsMemoryStorage* GetGlobalMemoryStorage()
{
return g_global_fonts_memory_storage;
}
GRAPHICS_DECL void SetGlobalMemoryStorage(IFontsMemoryStorage* pStorage)
{
if (g_global_fonts_memory_storage && g_global_fonts_memory_storage != pStorage)
g_global_fonts_memory_storage->Release();
g_global_fonts_memory_storage = pStorage;
}
} }
IFontFile::IFontFile() : NSBase::CBaseRefCounter() {} IFontFile::IFontFile() : NSBase::CBaseRefCounter() {}

View File

@ -110,7 +110,7 @@ void CDjVuFile::ConvertToPdf(const std::wstring& wsDstPath)
if (m_pImplementation) if (m_pImplementation)
m_pImplementation->ConvertToPdf(wsDstPath); m_pImplementation->ConvertToPdf(wsDstPath);
} }
#ifdef WASM_MODE #ifdef BUILDING_WASM_MODULE
BYTE* CDjVuFile::GetStructure() BYTE* CDjVuFile::GetStructure()
{ {
if (m_pImplementation) if (m_pImplementation)

View File

@ -336,7 +336,7 @@ void CDjVuFileImplementation::ConvertToPdf(const std::wstring& wsD
oPdf.SaveToFile(wsDstPath); oPdf.SaveToFile(wsDstPath);
} }
#ifdef WASM_MODE #ifdef BUILDING_WASM_MODULE
class CData class CData
{ {
protected: protected:

View File

@ -79,7 +79,7 @@ public:
BYTE* ConvertToPixels(int nPageIndex, const int& nRasterW = -1, const int& nRasterH = -1, bool bIsFlip = false); BYTE* ConvertToPixels(int nPageIndex, const int& nRasterW = -1, const int& nRasterH = -1, bool bIsFlip = false);
void ConvertToRaster(int nPageIndex, const std::wstring& wsDstPath, int nImageType, const int& nRasterW = -1, const int& nRasterH = -1); void ConvertToRaster(int nPageIndex, const std::wstring& wsDstPath, int nImageType, const int& nRasterW = -1, const int& nRasterH = -1);
void ConvertToPdf(const std::wstring& wsDstPath); void ConvertToPdf(const std::wstring& wsDstPath);
#ifdef WASM_MODE #ifdef BUILDING_WASM_MODULE
BYTE* GetStructure(); BYTE* GetStructure();
BYTE* GetPageGlyphs(int nPageIndex, const int& nRasterW, const int& nRasterH); BYTE* GetPageGlyphs(int nPageIndex, const int& nRasterW, const int& nRasterH);
BYTE* GetPageLinks (int nPageIndex, const int& nRasterW, const int& nRasterH); BYTE* GetPageLinks (int nPageIndex, const int& nRasterW, const int& nRasterH);

View File

@ -43,13 +43,11 @@
#include "../DesktopEditor/graphics/IRenderer.h" #include "../DesktopEditor/graphics/IRenderer.h"
#include "../DesktopEditor/common/Directory.h" #include "../DesktopEditor/common/Directory.h"
//#include "Src/StringExt.h"
#include "lib/xpdf/PDFDoc.h" #include "lib/xpdf/PDFDoc.h"
#include "lib/xpdf/GlobalParams.h" #include "lib/xpdf/GlobalParams.h"
#include "lib/xpdf/ErrorCodes.h" #include "lib/xpdf/ErrorCodes.h"
#include "lib/xpdf/ImageOutputDev.h" #include "lib/xpdf/ImageOutputDev.h"
#include "Src/RendererOutputDev.h" #include "Src/RendererOutputDev.h"
//#include "Src/PageLabels.h"
namespace PdfReader namespace PdfReader
{ {

View File

@ -56,11 +56,6 @@
#include "../../PdfWriter/PdfRenderer.h" #include "../../PdfWriter/PdfRenderer.h"
#endif #endif
#ifdef BUILDING_WASM_MODULE
#include <time.h>
#include "../../DesktopEditor/graphics/GraphicsRenderer.h"
#endif
// TODO: 1. Реализовать по-нормальному градиентные заливки (Axial и Radial) // TODO: 1. Реализовать по-нормальному градиентные заливки (Axial и Radial)
// 2. m_pRenderer->SetAdditionalParam(L"TilingHtmlPattern", oWriter.GetXmlString()); // 2. m_pRenderer->SetAdditionalParam(L"TilingHtmlPattern", oWriter.GetXmlString());
// 3. Подбор шрифтов необходимо перенести в GlobalParams->FindFontFile // 3. Подбор шрифтов необходимо перенести в GlobalParams->FindFontFile
@ -660,22 +655,12 @@ namespace PdfReader
case fontCIDType2OT: wsExt = L".cid_2ot"; break; case fontCIDType2OT: wsExt = L".cid_2ot"; break;
} }
#ifdef BUILDING_WASM_MODULE #ifdef BUILDING_WASM_MODULE
std::wstring wsTemp = ((GlobalParamsAdaptor *)globalParams)->GetTempFolder() + L"/x"; if (NSFonts::NSApplicationFontStream::GetGlobalMemoryStorage())
int nTime = (int)time(NULL);
for (int nIndex = 0; nIndex < 1000; ++nIndex)
{ {
wsTempFileName = wsTemp + std::to_wstring(nTime + nIndex) + wsExt; wsTempFileName = NSFonts::NSApplicationFontStream::GetGlobalMemoryStorage()->GenerateId();
if (!CApplicationFontStreams::m_pMemoryStorage->Get(wsTempFileName))
break;
} }
#else
if (CApplicationFontStreams::m_pMemoryStorage->Get(wsTempFileName))
{
pEntry->bAvailable = true;
return;
}
#else
FILE* pTempFile = NULL; FILE* pTempFile = NULL;
if (!NSFile::CFileBinary::OpenTempFile(&wsTempFileName, &pTempFile, L"wb", (wchar_t*)wsExt.c_str(), if (!NSFile::CFileBinary::OpenTempFile(&wsTempFileName, &pTempFile, L"wb", (wchar_t*)wsExt.c_str(),
(wchar_t*)((GlobalParamsAdaptor *)globalParams)->GetTempFolder().c_str(), NULL)) (wchar_t*)((GlobalParamsAdaptor *)globalParams)->GetTempFolder().c_str(), NULL))
@ -686,7 +671,8 @@ namespace PdfReader
pEntry->bAvailable = true; pEntry->bAvailable = true;
return; return;
} }
#endif #endif
Object oReferenceObject, oStreamObject; Object oReferenceObject, oStreamObject;
oReferenceObject.initRef(oEmbRef.num, oEmbRef.gen); oReferenceObject.initRef(oEmbRef.num, oEmbRef.gen);
@ -696,18 +682,20 @@ namespace PdfReader
{ {
// Внедренный шрифт неправильно записан // Внедренный шрифт неправильно записан
oStreamObject.free(); oStreamObject.free();
#ifndef BUILDING_WASM_MODULE
#ifndef BUILDING_WASM_MODULE
fclose(pTempFile); fclose(pTempFile);
if (L"" != wsTempFileName) if (L"" != wsTempFileName)
NSFile::CFileBinary::Remove(wsTempFileName); NSFile::CFileBinary::Remove(wsTempFileName);
#endif #endif
pEntry->bAvailable = true; pEntry->bAvailable = true;
return; return;
} }
oStreamObject.streamReset(); oStreamObject.streamReset();
#ifdef BUILDING_WASM_MODULE
#ifdef BUILDING_WASM_MODULE
LONG nCurrentPos = 0; LONG nCurrentPos = 0;
LONG nCurrentSize = 0xffff; LONG nCurrentSize = 0xffff;
BYTE* pTempStream = new BYTE[nCurrentSize]; BYTE* pTempStream = new BYTE[nCurrentSize];
@ -725,19 +713,17 @@ namespace PdfReader
} }
pTempStream[nCurrentPos++] = nChar; pTempStream[nCurrentPos++] = nChar;
} }
BYTE* pResBuffer = new BYTE[nCurrentPos];
memcpy(pResBuffer, pTempStream, nCurrentPos); NSFonts::NSApplicationFontStream::GetGlobalMemoryStorage()->Add(wsTempFileName, pTempStream, (LONG)nCurrentPos, true);
RELEASEARRAYOBJECTS(pTempStream); RELEASEARRAYOBJECTS(pTempStream);
CApplicationFontStreams::m_pMemoryStorage->Add(wsTempFileName, pResBuffer, nCurrentPos, true); #else
RELEASEARRAYOBJECTS(pResBuffer);
#else
int nChar; int nChar;
while ((nChar = oStreamObject.streamGetChar()) != EOF) while ((nChar = oStreamObject.streamGetChar()) != EOF)
{ {
fputc(nChar, pTempFile); fputc(nChar, pTempFile);
} }
fclose(pTempFile); fclose(pTempFile);
#endif #endif
oStreamObject.streamClose(); oStreamObject.streamClose();
oStreamObject.free(); oStreamObject.free();
wsFileName = wsTempFileName; wsFileName = wsTempFileName;

View File

@ -33,7 +33,6 @@
#include <stdio.h> #include <stdio.h>
#include "../../DesktopEditor/common/StringExt.h" #include "../../DesktopEditor/common/StringExt.h"
#include "../../DesktopEditor/graphics/structures.h" #include "../../DesktopEditor/graphics/structures.h"
#include "../../DesktopEditor/fontengine/FontManager.h"
#include "Document.h" #include "Document.h"
#include "StaticResources.h" #include "StaticResources.h"
@ -47,9 +46,6 @@
#endif #endif
#define IsFromResource(String) (!String.empty() && '{' == String[0]) #define IsFromResource(String) (!String.empty() && '{' == String[0])
#ifndef BUILDING_WASM_MODULE
CGlobalFontsMemoryStorage* CApplicationFontStreams::m_pMemoryStorage = NULL;
#endif
namespace XPS namespace XPS
{ {
@ -515,8 +511,8 @@ namespace XPS
IFolder::CBuffer* buffer = NULL; IFolder::CBuffer* buffer = NULL;
m_wsRootPath->read(wsFontPath, buffer); m_wsRootPath->read(wsFontPath, buffer);
m_pFontList->Check(wsFontName, buffer->Buffer, buffer->Size); m_pFontList->Check(wsFontName, buffer->Buffer, buffer->Size);
if (CApplicationFontStreams::m_pMemoryStorage) if (NSFonts::NSApplicationFontStream::GetGlobalMemoryStorage())
CApplicationFontStreams::m_pMemoryStorage->Add(wsFontPath, buffer->Buffer, buffer->Size); NSFonts::NSApplicationFontStream::GetGlobalMemoryStorage()->Add(wsFontPath, buffer->Buffer, buffer->Size);
m_wsRootPath->write(wsFontPath, buffer->Buffer, buffer->Size); m_wsRootPath->write(wsFontPath, buffer->Buffer, buffer->Size);
RELEASEOBJECT(buffer); RELEASEOBJECT(buffer);
} }