Files
core/ASCOfficePDFWriter/PdfWriterLib/Document.cpp
Elen.Subbotina 12dee7dfc5 JBig2 в PdfWriter
git-svn-id: svn://fileserver/activex/AVS/Sources/TeamlabOffice/trunk/ServerComponents@62533 954022d7-b5bf-4e40-9824-e11837661b57
2016-05-21 00:02:29 +03:00

2417 lines
65 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include "Document.h"
#include "../../../Common/DocxFormat/Source/SystemUtility/FileSystem/Directory.h"
#include "../../../DesktopEditor/graphics/Image.h"
unsigned long WriteHeader (Doc pPDF, StreamRecPtr pStream)
{
unsigned int nIndex = (int)pPDF->ePdfVersion;
if ( OK != StreamWriteStr( pStream, VERSION_STR[ nIndex ] ) )
return pPDF->oError.nErrorNo;
return OK;
}
unsigned int DocGetTempFile (Doc pPDF, CString *pwsTempFileName)
{
unsigned int unRet = 0;
// Создаем временный файл
CString pathTemp = CString( pPDF->wsTempDir );
if ( pathTemp.GetLength() < 1)
{
pathTemp = FileSystem::Directory::GetTempPath();
}
*pwsTempFileName = FileSystem::Directory::CreateTempFileWithUniqueName(pathTemp, _T("PDF"));
if (pwsTempFileName->GetLength() != 0)
return 1;
return unRet;
}
unsigned long InitCMapEncoding (EncoderRecPtr pEncoder)
{
//CMapEncoderAttr pAttr = (CMapEncoderAttr)pEncoder->pAttr;
pEncoder->eType = EncoderTypeToUnicode;
return OK;
}
unsigned long PrepareTrailer (Doc pPDF)
{
if ( OK != DictAdd( pPDF->pTrailer, "Root", pPDF->pCatalog ) )
return pPDF->oError.nErrorNo;
if ( OK != DictAdd( pPDF->pTrailer, "Info", pPDF->pInfo ) )
return pPDF->oError.nErrorNo;
return OK;
}
//----------------- Функции для работы с ToUnicode -------------------------------------------------
PToUnicode DocFindToUnicode (Doc pPDF, const char *sToUnicodeName)
{
List pList = pPDF->pToUnicodeList;
for ( unsigned int nIndex = 0; nIndex < pList->nCount; nIndex++)
{
PToUnicode pToUnicode = (PToUnicode)ListItemAt( pList, nIndex );
if ( 0 == UtilsStrCmp( sToUnicodeName, pToUnicode->sName ) )
{
return pToUnicode;
}
}
return NULL;
}
PToUnicode DocFindToUnicode (Doc pPDF, unsigned short *pUnicode, unsigned int unSize)
{
List pList = pPDF->pToUnicodeList;
for ( unsigned int nIndex = 0; nIndex < pList->nCount; nIndex++)
{
PToUnicode pToUnicode = (PToUnicode)ListItemAt( pList, nIndex );
if ( ToUnicodeBuilt == pToUnicode->eType )
{
// Проверяем все ли значения из pUnicode есть в данной кодировке ToUnicode
bool bGood = true;
for ( unsigned int unCharIndex = 0; unCharIndex < unSize; unCharIndex++ )
{
if ( 0xFFFF == ToUnicodeToCode( pToUnicode, pUnicode[unCharIndex] ) )
{
bGood = false;
break;
}
}
if ( bGood )
return pToUnicode;
}
}
return NULL;
}
PToUnicode DocFindToUnicode (Doc pPDF, BYTE *pBuffer, unsigned int unSize)
{
List pList = pPDF->pToUnicodeList;
for ( unsigned int nIndex = 0; nIndex < pList->nCount; nIndex++)
{
PToUnicode pToUnicode = (PToUnicode)ListItemAt( pList, nIndex );
if ( ToUnicodeStream == pToUnicode->eType )
{
// Проверяем совпадение по чексумме буффера
CRC32 oCRC;
oCRC.ProcessCRC( (void*)pBuffer, unSize );
ToUnicodeStreamAttr pAttr = (ToUnicodeStreamAttr)pToUnicode->pAttr;
if ( pAttr->pStream->nCheckSum == oCRC.m_nCRC32 )
return pToUnicode;
}
}
return NULL;
}
PToUnicode GetToUnicode (Doc pPDF, const char *sToUnicodeName)
{
if ( !HasDoc( pPDF ) )
return NULL;
PToUnicode pToUnicode = DocFindToUnicode( pPDF, sToUnicodeName );
return pToUnicode;
}
PToUnicode GetToUnicode (Doc pPDF, unsigned short *pUnicode, unsigned int unSize)
{
if ( !HasDoc( pPDF) || NULL == pUnicode || 0 == unSize )
return NULL;
// возможно кодировка, в которой есть все данные символы уже присутствует
PToUnicode pToUnicode = DocFindToUnicode( pPDF, pUnicode, unSize );
unsigned long nRet = OK;
if ( NULL == pToUnicode )
{
// Попробуем дополнить последнюю кодировку
pToUnicode = pPDF->pLastToUnicodeBuilt;
if ( NULL != pToUnicode && ToUnicodeUpdateUnicodeArray( pToUnicode, pUnicode, unSize ) )
return pToUnicode;
// Дополнить не получилось, значит состовляем новую кодировку
pPDF->nToUnicodeBuiltCount++;
char sToUnicodeBuiltName[LIMIT_MAX_NAME_LEN + 1];
sprintf( sToUnicodeBuiltName, "CMap%d", pPDF->nToUnicodeBuiltCount );
pToUnicode = ToUnicodeBuiltNew( pPDF->oMMgr, sToUnicodeBuiltName, 8 );
if ( !pToUnicode )
{
CheckError( &pPDF->oError );
return NULL;
}
// Обычные шрифты в PDF поддерживают до 256 символов. ( 0 символ зарезервирован )
unSize = ( unSize >= 256 ? 255 : unSize );
ToUnicodeBuiltAttr pAttr = (ToUnicodeBuiltAttr)pToUnicode->pAttr;
pAttr->nFirstChar = 0;
pAttr->nLastChar = 0;
// Внутри данной функции сразу идет проверка на дублирование символов
ToUnicodeUpdateUnicodeArray( pToUnicode, pUnicode, unSize );
if ( OK != ( nRet = ListAdd( pPDF->pToUnicodeList, pToUnicode ) ) )
{
ToUnicodeFree( pToUnicode );
RaiseError( &pPDF->oError, nRet, 0);
return NULL;
}
pPDF->pLastToUnicodeBuilt = pToUnicode;
pPDF->pCurToUnicode = pToUnicode;
}
return pToUnicode;
}
PToUnicode GetToUnicode (Doc pPDF, BYTE *pBuffer, unsigned int unSize)
{
if ( !HasDoc( pPDF) || NULL == pBuffer || 0 == unSize )
return NULL;
// возможно кодировка, в которой есть все данные символы уже присутствует
PToUnicode pToUnicode = DocFindToUnicode( pPDF, pBuffer, unSize );
unsigned long nRet = OK;
if ( NULL == pToUnicode )
{
pPDF->nToUnicodeStreamCount++;
char sToUnicodeBuiltName[LIMIT_MAX_NAME_LEN + 1];
sprintf( sToUnicodeBuiltName, "Stream%d", pPDF->nToUnicodeStreamCount );
pToUnicode = ToUnicodeStreamNew( pPDF->oMMgr, pBuffer, unSize, sToUnicodeBuiltName );
if ( !pToUnicode )
{
CheckError( &pPDF->oError );
return NULL;
}
if ( OK != ( nRet = ListAdd( pPDF->pToUnicodeList, pToUnicode ) ) )
{
ToUnicodeFree( pToUnicode );
RaiseError( &pPDF->oError, nRet, 0);
return NULL;
}
pPDF->pCurToUnicode = pToUnicode;
}
return pToUnicode;
}
PToUnicode DocGetCurrentToUnicode(Doc pPDF)
{
if ( !HasDoc( pPDF ) )
return NULL;
return pPDF->pCurToUnicode;
}
void FreeToUnicodeList (Doc pPDF)
{
List pList = pPDF->pToUnicodeList;
for ( unsigned int nIndex = 0; nIndex < pList->nCount; nIndex++)
{
PToUnicode pToUnicode = (PToUnicode)ListItemAt( pList, nIndex );
ToUnicodeFree( pToUnicode );
}
ListFree( pList );
pPDF->pToUnicodeList = NULL;
}
PToUnicode FindToUnicodeForString(Doc pPDF, std::wstring sSrc)
{
unsigned short *aUnicodeMap = new unsigned short[sSrc.length() + 1];
for ( int nIndex = 0; nIndex < sSrc.length(); nIndex++ )
{
aUnicodeMap[nIndex] = (unsigned short)sSrc.at(nIndex);
}
aUnicodeMap[sSrc.length()] = 0xFFFF;
unsigned int unSize = sSrc.length();
PToUnicode pToUnicode = GetToUnicode( pPDF, aUnicodeMap, unSize );
delete []aUnicodeMap;
return pToUnicode;
}
//----------------- Функции для работы с кодировками -----------------------------------------------
EncoderRecPtr DocFindEncoder (Doc pPDF, const char *sEncodingName, unsigned short *pUnicode /*= NULL*/, int nCount/* = 0*/)
{
if ( NULL == pUnicode )
{
List pList = pPDF->pEncoderList;
for ( unsigned int nIndex = 0; nIndex < pList->nCount; nIndex++)
{
EncoderRecPtr pEncoder = (EncoderRecPtr)ListItemAt( pList, nIndex );
if ( 0 == UtilsStrCmp( sEncodingName, pEncoder->sName ) )
{
// если кодировка не инициализирована, тогда вызываем функцию InitFn
if ( EncoderTypeUninitialized == pEncoder->eType )
{
if ( !pEncoder->pInitFn || OK != pEncoder->pInitFn( pEncoder ) )
return NULL;
}
return pEncoder;
}
}
return NULL;
}
else
{
// Тут надо сделать поиск кодировки с данным pUnicode
return NULL;
}
}
unsigned long DocRegisterEncoder (Doc pPDF, EncoderRecPtr pEncoder)
{
unsigned long nRet = OK;
if ( !pEncoder )
return SetError( &pPDF->oError, AVS_OFFICEPDFWRITER_ERROR_INVALID_OBJECT, 0);
if ( NULL != DocFindEncoder( pPDF, pEncoder->sName ) )
{
EncoderFree( pEncoder );
return SetError( &pPDF->oError, AVS_OFFICEPDFWRITER_ERROR_DUPLICATE_REGISTRATION, 0 );
}
if ( OK != ( nRet = ListAdd( pPDF->pEncoderList, pEncoder ) ) )
{
EncoderFree( pEncoder );
return SetError( &pPDF->oError, nRet, 0 );
}
return OK;
}
EncoderRecPtr GetEncoder (Doc pPDF, const char *sEncodingName, unsigned short *pUnicode/* = NULL*/, int nCount/* = 0*/)
{
if ( NULL == pUnicode )
{
if ( !HasDoc( pPDF ) )
return NULL;
EncoderRecPtr pEncoder = DocFindEncoder( pPDF, sEncodingName );
unsigned long nRet = OK;
if ( !pEncoder )
{
pEncoder = BasicEncoderNew( pPDF->oMMgr, sEncodingName );
if ( !pEncoder )
{
CheckError( &pPDF->oError );
return NULL;
}
if ( OK != ( nRet = ListAdd( pPDF->pEncoderList, pEncoder ) ) )
{
EncoderFree( pEncoder );
RaiseError( &pPDF->oError, nRet, 0);
return NULL;
}
}
return pEncoder;
}
else
{
if ( !HasDoc( pPDF) )
return NULL;
// возможно кодировка, в которой есть все данные символы уже присутствует
EncoderRecPtr pEncoder = DocFindEncoder( pPDF, sEncodingName, pUnicode, nCount );
unsigned long nRet = OK;
if ( !pEncoder )
{
pPDF->nCMapCount++;
char sEncodingName[100];
sprintf( sEncodingName, "CMap%d", pPDF->nCMapCount );
pEncoder = CMapEncoderNew( pPDF->oMMgr, sEncodingName, &InitCMapEncoding );
if ( !pEncoder )
{
CheckError( &pPDF->oError );
return NULL;
}
pEncoder->eType = EncoderTypeToUnicode;
CMapEncoderInitAttr( pEncoder );
// Обычные шрифты в PDF поддерживают до 256 символов. ( 0 символ зарезервирован )
nCount = ( nCount >= 256 ? 255 : nCount );
UtilsUIntArrayClearRepeat( &pUnicode, &nCount );
UnicodeMapRec *aUnicodeMap = new UnicodeMapRec[nCount + 2]; // первый и последний символы зарезервированы
aUnicodeMap[0].nCode = 0;
aUnicodeMap[0].nUnicode = 0x0000;
for ( int nIndex = 1; nIndex <= nCount; nIndex++ )
{
aUnicodeMap[nIndex].nCode = nIndex;
aUnicodeMap[nIndex].nUnicode = pUnicode[nIndex - 1];
}
aUnicodeMap[nCount + 1].nCode = nCount + 1;
aUnicodeMap[nCount + 1].nUnicode = 0xffff; // Таким образом мы обозначаем конец массива
CMapEncoderSetUnicodeArray( pEncoder, aUnicodeMap );
delete []aUnicodeMap;
CMapEncoderAttr pAttr = (CMapEncoderAttr)pEncoder->pAttr;
pAttr->nFirstChar = 0;
pAttr->nLastChar = nCount;
if ( OK != ( nRet = ListAdd( pPDF->pEncoderList, pEncoder ) ) )
{
EncoderFree( pEncoder );
RaiseError( &pPDF->oError, nRet, 0);
return NULL;
}
pPDF->pLastCMapEncoder = pEncoder;
}
return pEncoder;
}
}
EncoderRecPtr DocGetCurrentEncoder(Doc pPDF)
{
if ( !HasDoc( pPDF ) )
return NULL;
return pPDF->pCurEncoder;
}
unsigned long DocSetCurrentEncoder(Doc pPDF, const char *sEncodingName)
{
if ( !HasDoc( pPDF ) )
return GetError( pPDF );
EncoderRecPtr pEncoder = GetEncoder( pPDF, sEncodingName );
pPDF->pCurEncoder = pEncoder;
if ( !pPDF )
return GetError( pPDF );
return OK;
}
void FreeEncoderList (Doc pPDF)
{
List pList = pPDF->pEncoderList;
for ( unsigned int nIndex = 0; nIndex < pList->nCount; nIndex++)
{
EncoderRecPtr pEncoder = (EncoderRecPtr)ListItemAt( pList, nIndex );
EncoderFree( pEncoder );
}
ListFree( pList );
pPDF->pEncoderList = NULL;
}
EncoderRecPtr FindEncoderForString(Doc pPDF, CString sSrc, bool *pbNew)
{
*pbNew = false;
// Среди всех кодировок, имеющихся в документе, ищем ту, в которой можно написать заданную строку
List pEncoderList = pPDF->pEncoderList;
for ( int nIndex = 0; nIndex < pEncoderList->nCount; nIndex++ )
{
EncoderRecPtr pCurEncoder = (EncoderRecPtr)ListItemAt( pEncoderList, nIndex );
if ( EncoderTypeToUnicode != pCurEncoder->eType )
continue;
bool bResult = false;
CString sDst;
if ( NULL != pCurEncoder )
bResult = EncoderWCharToString( pCurEncoder, sSrc, &sDst );
if ( bResult )
{
return pCurEncoder;
}
}
// Среди имеющихся кодировок нужной кодировки нет, поэтому попробуем дополнить pLastCMapEncoder
unsigned short *aUnicodeMap = new unsigned short[sSrc.GetAllocLength() + 1];
for ( int nIndex = 0; nIndex < sSrc.GetLength(); nIndex++ )
{
aUnicodeMap[nIndex] = (unsigned short)sSrc.GetAt(nIndex);
}
aUnicodeMap[sSrc.GetLength()] = 0xFFFF;
int nCount = sSrc.GetLength();
UtilsUIntArrayClearRepeat( &aUnicodeMap, &nCount );
if ( pPDF->pLastCMapEncoder && CMapEncoderUpdateUnicodeArray( pPDF->pLastCMapEncoder, aUnicodeMap ) )
{
delete []aUnicodeMap;
return pPDF->pLastCMapEncoder;
}
else
{
EncoderRecPtr pNewEncoder = GetEncoder( pPDF, "", aUnicodeMap, nCount );
delete []aUnicodeMap;
*pbNew = true;
return pNewEncoder;
}
}
//----------------- Функции для работы с фонтами ---------------------------------------------------
//----------------- FontDef ------------------------------------------------------------------------
void FreeFontDefList (Doc pPDF)
{
List pList = pPDF->pFontDefList;
for ( unsigned int nIndex = 0; nIndex < pList->nCount; nIndex++)
{
FontDef pDef = (FontDef)ListItemAt( pList, nIndex );
FontDefFree( pDef );
}
ListFree( pList );
pPDF->pFontDefList = NULL;
}
void CleanupFontDefList(Doc pPDF)
{
List pList = pPDF->pFontDefList;
for ( unsigned int nIndex = 0; nIndex < pList->nCount; nIndex++)
{
FontDef pDef = (FontDef)ListItemAt( pList, nIndex );
FontDefCleanup( pDef );
}
}
FontDef DocFindFontDef (Doc pPDF, const char *sFontName, const char *sToUnicodeName /*= NULL*/)
{
List pList = pPDF->pFontDefList;
for ( unsigned int nIndex = 0; nIndex < pList->nCount; nIndex++)
{
FontDef pDef = (FontDef)ListItemAt( pList, nIndex );
if ( FontDefTrueType == pDef->eType && NULL != sToUnicodeName )
{
TTFontDefAttrRecPtr pAttr = (TTFontDefAttrRecPtr)pDef->pAttr;
if ( 0 == UtilsStrCmp( sFontName, pDef->sBaseFont) && 0 == UtilsStrCmp( sToUnicodeName, pAttr->sToUnicodeName ) )
{
if ( FontDefUninitialized == pDef->eType )
{
if ( !pDef->pInitFn || OK != pDef->pInitFn( pDef ) )
return NULL;
}
return pDef;
}
}
else
{
if ( 0 == UtilsStrCmp( sFontName, pDef->sBaseFont ) )
{
if ( FontDefUninitialized == pDef->eType )
{
if ( !pDef->pInitFn || OK != pDef->pInitFn( pDef ) )
return NULL;
}
return pDef;
}
}
}
return NULL;
}
unsigned long DocRegisterFontDef (Doc pPDF, FontDef pFontDef)
{
unsigned long nRet = OK;
if ( !pFontDef )
return SetError( &pPDF->oError, AVS_OFFICEPDFWRITER_ERROR_INVALID_OBJECT, 0);
if ( NULL != DocFindFontDef( pPDF, pFontDef->sBaseFont ) )
{
FontDefFree( pFontDef );
return SetError( &pPDF->oError, AVS_OFFICEPDFWRITER_ERROR_DUPLICATE_REGISTRATION, 0 );
}
if ( OK != ( nRet = ListAdd( pPDF->pFontDefList, pFontDef ) ) )
{
FontDefFree( pFontDef );
return SetError( &pPDF->oError, nRet, 0);
}
return OK;
}
FontDef GetFontDef (Doc pPDF, const char *sFontName, const char *sToUnicode /*= NULL*/)
{
unsigned long nRet = OK;
if ( !HasDoc( pPDF ) )
return NULL;
FontDef pDef = DocFindFontDef( pPDF, sFontName, sToUnicode );
if ( !pDef )
{
pDef = Base14FontDefNew( pPDF->oMMgr, sFontName);
if ( !pDef )
{
pDef = BaseFontDefNew( pPDF->oMMgr, sFontName );
if ( !pDef )
return NULL;
}
if ( OK != ( nRet = ListAdd( pPDF->pFontDefList, pDef ) ) )
{
FontDefFree( pDef );
RaiseError( &pPDF->oError, nRet, 0 );
pDef = NULL;
}
}
return pDef;
}
//----------------- Font ----------------------------------------------------------------------------
FontDict DocFindFont (Doc pPDF, const char *sFontName, const char *sEncodingName, const char *sToUnicodeName /*= NULL*/)
{
FontDict pFont = NULL;
for ( unsigned int nIndex = 0; nIndex < pPDF->pFontManager->nCount; nIndex++)
{
pFont = (FontDict)ListItemAt( pPDF->pFontManager, nIndex);
FontAttr pAttr = (FontAttr)pFont->pAttr;
// Строка sToUnicodeName может быть NULL. Функция UtilsStrCmp безопасно работает в данном случае
if ( NULL != pAttr->pToUnicode )
{
if ( 0 == UtilsStrCmp( pAttr->pFontDef->sBaseFont, sFontName ) && 0 == UtilsStrCmp( pAttr->pEncoder->sName, sEncodingName ) && 0 == UtilsStrCmp( pAttr->pToUnicode->sName, sToUnicodeName ) )
return pFont;
}
else if ( NULL == pAttr->pToUnicode && NULL == sToUnicodeName )
{
if ( 0 == UtilsStrCmp( pAttr->pFontDef->sBaseFont, sFontName ) && 0 == UtilsStrCmp( pAttr->pEncoder->sName, sEncodingName ) )
return pFont;
}
}
return NULL;
}
FontDict GetFont (Doc pPDF, const char *sFontName, const char *sEncodingName, const char *sToUnicodeName /*= NULL*/, unsigned short *pUnicode /*= NULL*/, int nCount/* = 0*/)
{
if ( !HasDoc( pPDF ) )
return NULL;
if ( !sFontName )
{
RaiseError( &pPDF->oError, AVS_OFFICEPDFWRITER_ERROR_INVALID_FONT_NAME, 0 );
return NULL;
}
FontDef pFontDef = NULL;
EncoderRecPtr pEncoder = NULL;
FontDict pFont = NULL;
PToUnicode pToUnicode = NULL;
// если кодировка не определена, тогда ищем стандартную кодировку для данного фонта
if ( !sEncodingName )
{
pFontDef = GetFontDef( pPDF, sFontName, sToUnicodeName );
if ( pFontDef )
{
if ( FontDefTrueType == pFontDef->eType )
pEncoder = GetEncoder( pPDF, ENCODING_FONT_SPECIFIC );
else if ( FontDefType1 == pFontDef->eType )
{
Type1FontDefAttr pAttr = (Type1FontDefAttr)pFontDef->pAttr;
if ( FontDefType1 == pFontDef->eType && 0 == UtilsStrCmp( pAttr->sEncodingScheme, ENCODING_FONT_SPECIFIC ) )
pEncoder = GetEncoder( pPDF, ENCODING_FONT_SPECIFIC );
else
pEncoder = GetEncoder( pPDF, ENCODING_WIN_ANSI/*ENCODING_STANDARD*/, pUnicode, nCount );
}
}
else
{
CheckError( &pPDF->oError );
return NULL;
}
pFont = DocFindFont( pPDF, sFontName, pEncoder->sName, sToUnicodeName );
}
else
pFont = DocFindFont( pPDF, sFontName, sEncodingName, sToUnicodeName );
if ( pFont )
return pFont;
if ( !pFontDef )
{
pFontDef = GetFontDef( pPDF, sFontName, sToUnicodeName );
if ( !pFontDef )
{
CheckError( &pPDF->oError );
return NULL;
}
}
if ( !pEncoder )
{
pEncoder = GetEncoder( pPDF, sEncodingName, pUnicode, nCount );
if ( !pEncoder )
return NULL;
}
if ( !pToUnicode )
{
pToUnicode = GetToUnicode( pPDF, sToUnicodeName );
}
switch ( pFontDef->eType )
{
case FontDefType1:
pFont = Type1FontNew( pPDF->oMMgr, pFontDef, pEncoder, pPDF->pXref, pToUnicode );
if ( pFont )
ListAdd( pPDF->pFontManager, pFont);
break;
case FontDefTrueType:
if ( EncoderTypeDoubleByteBuilt == pEncoder->eType )
pFont = Type0FontNew( pPDF->oMMgr, pFontDef, pEncoder, pPDF->pXref, pToUnicode );
else
pFont = TTFontNew( pPDF->oMMgr, pFontDef, pEncoder, pPDF->pXref, pToUnicode);
if ( pFont )
ListAdd( pPDF->pFontManager, pFont);
break;
case FontDefCID:
pFont = Type0FontNew( pPDF->oMMgr, pFontDef, pEncoder, pPDF->pXref, pToUnicode );
if ( pFont )
ListAdd( pPDF->pFontManager, pFont);
break;
case FontBase:
pFont = BaseFontNew( pPDF->oMMgr, pFontDef, pEncoder, pPDF->pXref, pToUnicode );
if ( pFont )
ListAdd( pPDF->pFontManager, pFont );
break;
default:
RaiseError( &pPDF->oError, AVS_OFFICEPDFWRITER_ERROR_UNSUPPORTED_FONT_TYPE, 0);
return NULL;
}
if ( !pFont )
CheckError( &pPDF->oError );
#ifdef FILTER_FLATE_DECODE_ENABLED
if ( pFont && ( pPDF->nCompressionMode & COMP_METADATA ) )
pFont->nFilter |= STREAM_FILTER_FLATE_DECODE;
#endif
return pFont;
}
const char* LoadType1FontFromFile (Doc pPDF, std::wstring & wsAFMFileName, std::wstring & wsDataFileName, short nType/* = 0*/)
{
StreamRecPtr pAFM = NULL;
StreamRecPtr pData = NULL;
const char *sRet;
if ( !HasDoc( pPDF ) )
return NULL;
// создаем поток
pAFM = FileReaderNew( pPDF->oMMgr, wsAFMFileName );
if ( wsDataFileName.length() > 0 )
pData = FileReaderNew( pPDF->oMMgr, wsDataFileName );
if ( StreamValidate( pAFM ) && ( wsDataFileName.length() > 0 || StreamValidate( pData ) ) )
sRet = LoadType1FontFromStream( pPDF, pAFM, pData, nType );
else
sRet = NULL;
// удаляем поток
if ( pAFM )
StreamFree( pAFM );
if ( pData )
StreamFree( pData );
if ( !sRet )
CheckError( &pPDF->oError );
return sRet;
}
const char* LoadType1FontFromStream (Doc pPDF, StreamRecPtr pAFMData, StreamRecPtr pPFMData, short nType)
{
if ( !HasDoc( pPDF ) )
return NULL;
FontDef pDef = Type1FontDefLoad( pPDF->oMMgr, pAFMData, pPFMData, nType );
if ( pDef )
{
FontDef pTempDef = DocFindFontDef( pPDF, pDef->sBaseFont );
if ( pTempDef )
{
FontDefFree( pDef );
SetError( &pPDF->oError, AVS_OFFICEPDFWRITER_ERROR_FONT_EXISTS, 0);
return pTempDef->sBaseFont;
}
if ( OK != ListAdd( pPDF->pFontDefList, pDef ) )
{
FontDefFree( pDef );
return NULL;
}
}
return pDef->sBaseFont;
}
const char* LoadTTFontFromFile (Doc pPDF, std::wstring & wsFileName, bool bEmbedding, const char* sEncodingName/* = NULL*/, const char *sPrefix /*= NULL*/)
{
if ( !HasDoc( pPDF ) )
return NULL;
const char *sRet = LoadTTFontFromStream( pPDF, bEmbedding, wsFileName, sEncodingName, sPrefix );
if ( !sRet )
CheckError( &pPDF->oError );
return sRet;
}
const char* LoadTTFontFromStream (Doc pPDF, bool bEmbedding, std::wstring & wsFileName, const char *sEncodingName, const char *sPrefix)
{
FontDef pDef = TTFontDefLoad( pPDF->oMMgr, wsFileName, bEmbedding, sEncodingName, false, false, false, true );
if ( pDef )
{
if ( NULL != sPrefix )
strcat( pDef->sBaseFont, sPrefix );
FontDef pTempDef = DocFindFontDef( pPDF, pDef->sBaseFont, sEncodingName );
if ( pTempDef )
{
FontDefFree( pDef );
SetError( &pPDF->oError, AVS_OFFICEPDFWRITER_ERROR_FONT_EXISTS, 0);
return pTempDef->sBaseFont;
}
else
{
FontDefFree(pDef);
pDef = TTFontDefLoad( pPDF->oMMgr, wsFileName, bEmbedding, sEncodingName, false, false, false, false );
if ( NULL != sPrefix )
strcat( pDef->sBaseFont, sPrefix );
}
if ( OK != ListAdd( pPDF->pFontDefList, pDef ) )
{
FontDefFree( pDef );
return NULL;
}
}
else
return NULL;
if ( bEmbedding )
{
if ( 0 == pPDF->aTTFontTag[0] )
{
UtilsMemCpy( pPDF->aTTFontTag, (BYTE*)"BAAAAA", 6);
}
else
{
for ( unsigned int nIndex = 0; nIndex <= 5; nIndex++)
{
pPDF->aTTFontTag[nIndex] += 1;
if ( pPDF->aTTFontTag[nIndex] > 'Z')
pPDF->aTTFontTag[nIndex] = 'A';
else
break;
}
}
TTFontDefSetTagName( pDef, (char*)pPDF->aTTFontTag );
}
return pDef->sBaseFont;
}
const char* LoadTTFontFromFile2 (Doc pPDF, std::wstring & wsFileName, unsigned int nIndex, bool bEmbedding)
{
if ( !HasDoc( pPDF ) )
return NULL;
const char *sRet = LoadTTFontFromStream2( pPDF, nIndex, bEmbedding, wsFileName );
if ( !sRet )
CheckError( &pPDF->oError );
return sRet;
}
const char* LoadTTFontFromStream2 (Doc pPDF, unsigned int nIndex, bool bEmbedding, std::wstring & wsFileName)
{
FontDef pDef = TTFontDefLoad2( pPDF->oMMgr, wsFileName, nIndex, bEmbedding );
if ( pDef )
{
FontDef pTempDef = DocFindFontDef( pPDF, pDef->sBaseFont );
if ( pTempDef )
{
FontDefFree( pDef );
SetError( &pPDF->oError, AVS_OFFICEPDFWRITER_ERROR_FONT_EXISTS, 0);
return NULL;
}
if ( OK != ListAdd( pPDF->pFontDefList, pDef ) )
{
FontDefFree( pDef );
return NULL;
}
}
else
return NULL;
if ( bEmbedding )
{
if ( 0 == pPDF->aTTFontTag[0] )
UtilsMemCpy( pPDF->aTTFontTag, (BYTE*)"AVSAAA", 6);
else
{
for ( unsigned int nIndex = 5; nIndex >= 0; nIndex--)
{
pPDF->aTTFontTag[nIndex] += 1;
if ( pPDF->aTTFontTag[nIndex] > 'Z' )
pPDF->aTTFontTag[nIndex] = 'A';
else
break;
}
}
TTFontDefSetTagName( pDef, (char*)pPDF->aTTFontTag );
}
return pDef->sBaseFont;
}
////----------------- Images --------------------------------------------------------------------------
//ImageDict LoadRawImageFromFile (Doc pPDF, const wchar_t *wsFileName, unsigned int nWidth, unsigned int nHeight, ColorSpace eColorSpace)
//{
// ImageDict pImage = NULL;
//
// if ( !HasDoc( pPDF ) )
// return NULL;
//
// // создаем файловый поток
// Stream pImageData = FileReaderNew( pPDF->oMMgr, wsFileName );
//
// if ( StreamValidate( pImageData ) )
// pImage = ImageLoadRawImage( pPDF->oMMgr, pImageData, pPDF->pXref, nWidth, nHeight, eColorSpace);
// else
// pImage = NULL;
//
// // удаялем поток
// StreamFree( pImageData );
//
// if ( !pImage )
// CheckError( &pPDF->oError );
//
//#ifdef FILTER_FLATE_DECODE_ENABLED
// if ( pPDF->nCompressionMode & COMP_IMAGE )
// pImage->nFilter = STREAM_FILTER_FLATE_DECODE;
//#endif
//
// return pImage;
//}
//
//ImageDict LoadRawImageFromMem (Doc pPDF, const BYTE *pBuffer, unsigned int nWidth, unsigned int nHeight, ColorSpace eColorSpace, unsigned int nBitsPerComponent, bool bAlpha = false, const BYTE *pAlphaBuffer = NULL)
//{
// if ( !HasDoc( pPDF ))
// return NULL;
//
// ImageDict pImage = ImageLoadRawImageFromMem( pPDF->oMMgr, pBuffer, pPDF->pXref, nWidth, nHeight, eColorSpace, nBitsPerComponent, bAlpha, pAlphaBuffer );
//
// if ( !pImage )
// CheckError( &pPDF->oError );
//
//#ifdef FILTER_FLATE_DECODE_ENABLED
// if ( pPDF->nCompressionMode & COMP_IMAGE )
// pImage->nFilter = STREAM_FILTER_FLATE_DECODE;
//#endif
//
// return pImage;
//}
ImageDict LoadJbig2ImageFromMem(Doc pPDF, BYTE *pBuffer, unsigned int nWidth, unsigned int nHeight, unsigned int unImageCheckSum)
{
ImageDict pImage = NULL;
if ( !(HasDoc(pPDF)) )
return NULL;
// Создаем временный файл
CString wsTempFile;
if ( 0 == DocGetTempFile( pPDF, &wsTempFile ) )
{
SetError( pPDF->oMMgr->oError, AVS_OFFICEPDFWRITER_ERROR_FILE_WRITE_ERROR, errno );
return NULL;
}
// Записываем во временный файл картинку в формате JBig2
Aggplus::CImage image;
int BitsPerSample = 3;//alfa отдельно oO ???
image.Create(pBuffer,nWidth, nHeight, - BitsPerSample * nWidth);//+ flip
image.m_bExternalBuffer = true;
image.SaveFile(string2std_string(wsTempFile), 21/*JBig2*/);
image.Destroy();
//монохромные с альфой ???
//if ( bAlpha )
//{
// // Создаем темповый файл для записи туда альфа-канала
// if ( 0 == DocGetTempFile( pPDF, &wsTempAlpha ) )
// {
// SetError( pPDF->oMMgr->oError, AVS_OFFICEPDFWRITER_ERROR_FILE_WRITE_ERROR, errno );
// return NULL;
// }
// CEncoderLZW oLZW( pAlphaBuffer, nWidth * nHeight, false );
// oLZW.Encode( wsTempAlpha.GetBuffer() );
//}
pImage = ImageLoadJBig2Image( pPDF->oMMgr, wsTempFile, pPDF->pXref, nWidth, nHeight, unImageCheckSum );
// Декодирование во Flate картинок в формате JBig2 отключено, из-за того что Acrobat
// может плохо прочитать такие картинки.
#ifdef FILTER_FLATE_DECODE_ENABLED
//if ( pPDF->nCompressionMode & COMP_IMAGE )
// pImage->nFilter |= STREAM_FILTER_FLATE_DECODE;
#endif
return pImage;
}
ImageDict LoadJpegImageFromFile(Doc pPDF, std::wstring wsFileName)
{
ImageDict pImage = NULL;
if ( !HasDoc( pPDF ) )
return NULL;
// Создаем файловый поток
StreamRecPtr pImageData = FileReaderNew( pPDF->oMMgr, wsFileName );
if ( StreamValidate(pImageData) )
pImage = ImageLoadJpegImage( pPDF->oMMgr, pImageData, pPDF->pXref );
else
pImage = NULL;
// освобождаем файловый поток
StreamFree( pImageData );
if ( !pImage )
CheckError( &pPDF->oError );
return pImage;
}
ImageDict LoadJpxImageFromFile (Doc pPDF, std::wstring wsFileName, long nOpacityFlag)
{
ImageDict pImage = NULL;
if ( !(HasDoc(pPDF) ) )
return NULL;
// Создаем файловый поток
StreamRecPtr pImageData = FileReaderNew( pPDF->oMMgr, wsFileName );
if ( StreamValidate( pImageData ) )
pImage = ImageLoadJpxImage( pPDF->oMMgr, pImageData, pPDF->pXref, nOpacityFlag );
else
pImage = NULL;
// Освобождаем файлоый поток
StreamFree( pImageData );
if ( !pImage )
CheckError( &pPDF->oError );
return pImage;
}
//ImageDict LoadJpxImageFromMem (Doc pPDF, const BYTE *pBuffer, unsigned int nWidth, unsigned int nHeight, unsigned int unImageCheckSum, bool bAlpha = false, const BYTE *pAlphaBuffer = NULL, unsigned int unAlphaCheckSum = 0)
//{
//#ifdef BUILD_CONFIG_OPENSOURCE_VERSION
// return NULL;
//#else
// if ( !HasDoc( pPDF ))
// return NULL;
//
// // Переводим Image -> IAVSUncompressedVideoFrame
// MediaCore::IAVSUncompressedVideoFrame *pInterface = NULL;
// HRESULT hRes = CoCreateInstance( MediaCore::CLSID_CAVSUncompressedVideoFrame, NULL, CLSCTX_ALL, MediaCore::IID_IAVSUncompressedVideoFrame, (void**)&pInterface );
// if ( hRes != S_OK )
// return NULL;
//
// int nBufferSize = 4 * nWidth * nHeight;
// if ( nBufferSize < 1 )
// return NULL;
//
// pInterface->put_ColorSpace( 1 << 6 ); // CPS_BGRA
// pInterface->put_Width( nWidth );
// pInterface->put_Height( nHeight );
// pInterface->put_AspectRatioX( nWidth );
// pInterface->put_AspectRatioY( nHeight );
// pInterface->put_Interlaced( VARIANT_FALSE );
// pInterface->put_Stride( 0, 4 * nWidth );
// pInterface->AllocateBuffer( nBufferSize );
//
// unsigned char *pBufferPtr = NULL;
// long nCreatedBufferSize = 0;
//
// pInterface->get_Buffer( &pBufferPtr );
// pInterface->get_BufferSize( &nCreatedBufferSize );
// pInterface->put_Plane( 0, pBufferPtr );
//
// if ( !pBufferPtr || nCreatedBufferSize != nBufferSize )
// return NULL;
//
// // Пишем данные в pBufferPtr
//
// for ( int nIndex = 0; nIndex < nWidth * nHeight; nIndex++, pBufferPtr += 4, pBuffer += 3 )
// {
// pBufferPtr[0] = pBuffer[ 2 ];
// pBufferPtr[1] = pBuffer[ 1 ];
// pBufferPtr[2] = pBuffer[ 0 ];
// pBufferPtr[3] = 255;
// }
//
// // Создаем темповый файл для записи туда Jpx
// CString wsTempFile, wsTempAlpha;
// if ( 0 == DocGetTempFile( pPDF, &wsTempFile ) )
// {
// SetError( pPDF->oMMgr->oError, AVS_OFFICEPDFWRITER_ERROR_FILE_WRITE_ERROR, errno );
// return NULL;
// }
//
// // Записываем во временный файл картинку в формате Jpx
// Jpx::IJ2kFile *pJpx = NULL;
// ::CoCreateInstance( __uuidof( Jpx::CJ2kFile ), NULL, CLSCTX_ALL, __uuidof( Jpx::IJ2kFile ), (void**)&pJpx );
//
// if ( !pJpx )
// return NULL;
//
// CString sOptions;
// sOptions.Format( _T("<Jpeg2000-Options><SaveOptions><ComponentsCount value='3'/><Format value='1' /></SaveOptions></Jpeg2000-Options>" ), nWidth, nHeight );
//
// BSTR bsTempFile = ::SysAllocString( wsTempFile );
// BSTR bsOptions = sOptions.AllocSysString();
// pJpx->InterfaceToJ2k( (IUnknown **)&pInterface, bsTempFile, bsOptions );
//
// ::SysFreeString( bsTempFile );
// ::SysFreeString( bsOptions );
//
// RELEASEINTERFACE( pInterface );
// RELEASEINTERFACE( pJpx );
//
// if ( bAlpha )
// {
// // Переводим Image -> IAVSUncompressedVideoFrame
// pInterface = NULL;
// hRes = CoCreateInstance( MediaCore::CLSID_CAVSUncompressedVideoFrame, NULL, CLSCTX_ALL, MediaCore::IID_IAVSUncompressedVideoFrame, (void**)&pInterface );
// if ( hRes != S_OK )
// return NULL;
//
// pInterface->put_ColorSpace( ( 1 << 6 ) ); // CPS_BGRA
// pInterface->put_Width( nWidth );
// pInterface->put_Height( nHeight );
// pInterface->put_AspectRatioX( nWidth );
// pInterface->put_AspectRatioY( nHeight );
// pInterface->put_Interlaced( VARIANT_FALSE );
// pInterface->put_Stride( 0, 4 * nWidth );
// pInterface->AllocateBuffer( nBufferSize );
//
// pBufferPtr = NULL;
// nCreatedBufferSize = 0;
//
// pInterface->get_Buffer( &pBufferPtr );
// pInterface->get_BufferSize( &nCreatedBufferSize );
// pInterface->put_Plane( 0, pBufferPtr );
//
// if ( !pBufferPtr || nCreatedBufferSize != nBufferSize )
// return NULL;
//
// // Пишем данные в pBufferPtr
//
// for ( int nIndex = 0; nIndex < nWidth * nHeight; nIndex++, pBufferPtr += 4 )
// {
// pBufferPtr[0] = pAlphaBuffer[ nIndex ];
// pBufferPtr[1] = pAlphaBuffer[ nIndex ];
// pBufferPtr[2] = pAlphaBuffer[ nIndex ];
// pBufferPtr[3] = 255;
// }
//
// if ( 0 == DocGetTempFile( pPDF, &wsTempAlpha ) )
// {
// SetError( pPDF->oMMgr->oError, AVS_OFFICEPDFWRITER_ERROR_FILE_WRITE_ERROR, errno );
// return NULL;
// }
//
//
// // Записываем во временный файл картинку в формате Jpx
// Jpx::IJ2kFile *pJpx = NULL;
// ::CoCreateInstance( __uuidof( Jpx::CJ2kFile ), NULL, CLSCTX_ALL, __uuidof( Jpx::IJ2kFile ), (void**)&pJpx );
//
// if ( !pJpx )
// return NULL;
//
// CString sOptions;
// sOptions.Format( _T("<Jpeg2000-Options><SaveOptions><ComponentsCount value='1'/><Format value='0' /><Tile width='%d' height='%d' /></SaveOptions></Jpeg2000-Options>" ), nWidth, nHeight );
//
// BSTR bsTempFile = ::SysAllocString( wsTempAlpha );
// BSTR bsOptions = sOptions.AllocSysString();
// pJpx->InterfaceToJ2k( (IUnknown **)&pInterface, bsTempFile, bsOptions );
//
// ::SysFreeString( bsTempFile );
// ::SysFreeString( bsOptions );
//
// RELEASEINTERFACE( pInterface );
// RELEASEINTERFACE( pJpx );
// }
//
// ImageDict pImage = ImageLoadJpxImage ( pPDF->oMMgr, wsTempFile.GetBuffer(), pPDF->pXref, nWidth, nHeight, unImageCheckSum, bAlpha, wsTempAlpha.GetBuffer(), unAlphaCheckSum );
//
// if ( !pImage )
// CheckError( &pPDF->oError );
//
//#ifdef FILTER_FLATE_DECODE_ENABLED
// if ( pPDF->nCompressionMode & COMP_IMAGE )
// pImage->nFilter |= STREAM_FILTER_FLATE_DECODE;
//#endif
//
// return pImage;
//#endif
//}
ImageDict LoadJpegImageFromMem (Doc pPDF, BYTE *pBuffer, unsigned int nWidth, unsigned int nHeight, unsigned int unImageCheckSum, bool bAlpha/* = false*/, const BYTE *pAlphaBuffer/* = NULL*/, unsigned int unAlphaCheckSum/* = 0*/)
{
if ( !HasDoc( pPDF ))
return NULL;
// Создаем темповый файл для записи туда Jpeg
CString wsTempFile, wsTempAlpha;
if ( 0 == DocGetTempFile( pPDF, &wsTempFile ) )
{
SetError( pPDF->oMMgr->oError, AVS_OFFICEPDFWRITER_ERROR_FILE_WRITE_ERROR, errno );
return NULL;
}
// Записываем во временный файл картинку в формате Jpg
Aggplus::CImage image;
int BitsPerSample = 3;//alfa отдельно oO ???
image.Create(pBuffer,nWidth, nHeight, - BitsPerSample * nWidth);//+ flip
image.m_bExternalBuffer = true;
image.SaveFile(string2std_string(wsTempFile), 3/*Jpeg*/);
image.Destroy();
if ( bAlpha )
{
// Создаем темповый файл для записи туда альфа-канала
if ( 0 == DocGetTempFile( pPDF, &wsTempAlpha ) )
{
SetError( pPDF->oMMgr->oError, AVS_OFFICEPDFWRITER_ERROR_FILE_WRITE_ERROR, errno );
return NULL;
}
CEncoderLZW oLZW( pAlphaBuffer, nWidth * nHeight, false );
oLZW.Encode( wsTempAlpha.GetBuffer() );
}
ImageDict pImage = ImageLoadJpegImage ( pPDF->oMMgr, wsTempFile.GetBuffer(), pPDF->pXref, nWidth, nHeight, unImageCheckSum, bAlpha, wsTempAlpha.GetBuffer(), unAlphaCheckSum );
if ( !pImage )
CheckError( &pPDF->oError );
#ifdef FILTER_FLATE_DECODE_ENABLED
if (pImage && pPDF->nCompressionMode & COMP_IMAGE )
pImage->nFilter |= STREAM_FILTER_FLATE_DECODE;
#endif
return pImage;
}
//----------------- Catalog -------------------------------------------------------------------------
PageLayout GetPageLayout (Doc pPDF)
{
if ( !HasDoc( pPDF ) )
return PLSingle;
return CatalogGetPageLayout( pPDF->pCatalog );
}
unsigned long SetPageLayout (Doc pPDF, PageLayout eLayout)
{
unsigned long nRet = OK;
if ( !HasDoc( pPDF ) )
return AVS_OFFICEPDFWRITER_ERROR_INVALID_DOCUMENT;
if ( eLayout < 0 || eLayout >= PLEOF )
return RaiseError( &pPDF->oError, AVS_OFFICEPDFWRITER_ERROR_PAGE_LAYOUT_OUT_OF_RANGE, (unsigned long)eLayout);
nRet = CatalogSetPageLayout( pPDF->pCatalog, eLayout);
if ( OK != nRet )
CheckError( &pPDF->oError );
return OK;
}
PageMode GetPageMode (Doc pPDF)
{
if ( !HasDoc( pPDF ) )
return PageModeUseNone;
return CatalogGetPageMode( pPDF->pCatalog );
}
unsigned long SetPageMode (Doc pPDF, PageMode eMode)
{
unsigned long nRet = OK;
if ( !HasDoc( pPDF ) )
return AVS_OFFICEPDFWRITER_ERROR_INVALID_DOCUMENT;
if ( eMode < 0 || eMode >= PageModeEOF )
return RaiseError( &pPDF->oError, AVS_OFFICEPDFWRITER_ERROR_PAGE_MODE_OUT_OF_RANGE, (unsigned long)eMode);
nRet = CatalogSetPageMode( pPDF->pCatalog, eMode);
if ( OK != nRet )
return CheckError( &pPDF->oError);
return OK;
}
unsigned long SetOpenAction (Doc pPDF, Destination pOpenAction)
{
unsigned long nRet = OK;
if ( !HasDoc( pPDF ) )
return AVS_OFFICEPDFWRITER_ERROR_INVALID_DOCUMENT;
if ( pOpenAction && !DestinationValidate( pOpenAction ) )
return RaiseError( &pPDF->oError, AVS_OFFICEPDFWRITER_ERROR_INVALID_DESTINATION, 0);
nRet = CatalogSetOpenAction( pPDF->pCatalog, pOpenAction );
if ( OK != nRet )
return CheckError( &pPDF->oError);
return OK;
}
unsigned int GetViewerPreference (Doc pPDF)
{
if ( !HasDoc( pPDF ) )
return 0;
return CatalogGetViewerPreference( pPDF->pCatalog );
}
unsigned long SetViewerPreference (Doc pPDF, unsigned int nValue)
{
unsigned long nRet = OK;
if ( !HasDoc( pPDF ) )
return AVS_OFFICEPDFWRITER_ERROR_INVALID_DOCUMENT;
nRet = CatalogSetViewerPreference( pPDF->pCatalog, nValue );
if ( OK != nRet )
return CheckError( &pPDF->oError);
return OK;
}
unsigned long AddPageLabel (Doc pPDF, unsigned int nPageNum, PageNumStyle eStyle, unsigned int nFirstPage, const char *sPrefix)
{
Dict pPageLabel = NULL;
unsigned long nRet = OK;
if ( !HasDoc( pPDF ) )
return AVS_OFFICEPDFWRITER_ERROR_INVALID_DOCUMENT;
pPageLabel = PageLabelNew( pPDF, eStyle, nFirstPage, sPrefix );
if ( !pPageLabel )
return CheckError( &pPDF->oError);
if ( eStyle < 0 || eStyle >= PageNumStyleEOF )
return RaiseError( &pPDF->oError, AVS_OFFICEPDFWRITER_ERROR_PAGE_NUM_STYLE_OUT_OF_RANGE, (unsigned long)eStyle );
nRet = CatalogAddPageLabel( pPDF->pCatalog, nPageNum, pPageLabel);
if ( OK != nRet )
return CheckError( &pPDF->oError);
return OK;
}
//----------------- Info -----------------------------------------------------------------------------
Dict GetInfo (Doc pPDF)
{
if ( !HasDoc( pPDF ) )
return NULL;
if ( !pPDF->pInfo )
{
pPDF->pInfo = DictNew( pPDF->oMMgr );
if ( !pPDF->pInfo || XrefAdd( pPDF->pXref, pPDF->pInfo ) != OK )
pPDF->pInfo = NULL;
}
return pPDF->pInfo;
}
unsigned long SetInfoAttr (Doc pPDF, InfoType eType, const char *sValue)
{
unsigned long nRet = OK;
Dict pInfo = GetInfo( pPDF );
if ( !pInfo )
return CheckError( &pPDF->oError );
nRet = InfoSetInfoAttr( pInfo, eType, sValue, pPDF->pCurEncoder );
if ( OK != nRet )
return CheckError( &pPDF->oError );
return nRet;
}
const char* GetInfoAttr (Doc pPDF, InfoType eType)
{
const char *sRes = NULL;
Dict pInfo = GetInfo( pPDF );
if ( pInfo )
sRes = InfoGetInfoAttr( pInfo, eType);
else
CheckError( &pPDF->oError );
return sRes;
}
unsigned long SetInfoDateAttr (Doc pPDF, InfoType eType, TDate oDate)
{
unsigned long nRet = OK;
Dict pInfo = GetInfo( pPDF );
if ( !pInfo )
return CheckError( &pPDF->oError );
nRet = InfoSetInfoDateAttr( pInfo, eType, oDate );
if ( OK != nRet )
return CheckError( &pPDF->oError );
return nRet;
}
Outline CreateOutline (Doc pPDF, Outline pParent, const char *sTitle, EncoderRecPtr pEncoder)
{
Outline pOutline = NULL;
if ( !HasDoc( pPDF ) )
return NULL;
if ( !pParent )
{
if ( pPDF->pOutlines )
{
pParent = pPDF->pOutlines;
}
else
{
pPDF->pOutlines = OutlineRootNew( pPDF->oMMgr, pPDF->pXref );
if ( pPDF->pOutlines )
{
unsigned long nRet = DictAdd( pPDF->pCatalog, "Outlines", pPDF->pOutlines );
if ( OK != nRet )
{
CheckError( &pPDF->oError );
pPDF->pOutlines = NULL;
return NULL;
}
pParent = pPDF->pOutlines;
}
else
{
CheckError( &pPDF->oError );
return NULL;
}
}
}
if ( !OutlineValidate( pParent ) || pPDF->oMMgr != pParent->oMMgr )
{
RaiseError( &pPDF->oError, AVS_OFFICEPDFWRITER_ERROR_INVALID_OUTLINE, 0);
return NULL;
}
pOutline = OutlineNew( pPDF->oMMgr, pParent, sTitle, pEncoder, pPDF->pXref );
if ( !pOutline )
CheckError( &pPDF->oError );
return pOutline;
}
ExtGState CreateExtGState (Doc pPDF)
{
ExtGState pExtGState = NULL;
if ( !HasDoc( pPDF ) )
return NULL;
pPDF->ePdfVersion = PDF_1_4;
pExtGState = ExtGStateNew( pPDF->oMMgr, pPDF->pXref );
if (!pExtGState)
CheckError( &pPDF->oError );
return pExtGState;
}
ExtGState FindExtGState (Doc pPDF, float fAlphaStroke/* = -1*/, float fAlphaFill/* = -1*/, BlendMode eMode/* = BMEOF*/, int nStrokeAdjustment/* = -1*/)
{
ExtGState pExtGState = NULL;
for ( unsigned int nIndex = 0; nIndex < pPDF->pExtGStateList->nCount; nIndex++)
{
pExtGState = (ExtGState)ListItemAt( pPDF->pExtGStateList, nIndex);
// Сравниваем CA
Real pAlphaStroke = (Real)DictGetItem( (Dict)pExtGState, "CA", OCLASS_REAL );
if ( NULL == pAlphaStroke )
{
if ( -1 != fAlphaStroke )
continue;
}
else
{
if ( -1 == fAlphaStroke || pAlphaStroke->fValue != fAlphaStroke )
continue;
}
// Сравниваем ca
Real pAlphaFill = (Real)DictGetItem( (Dict)pExtGState, "ca", OCLASS_REAL );
if ( NULL == pAlphaFill )
{
if ( -1 != fAlphaFill )
continue;
}
else
{
if ( -1 == fAlphaFill || pAlphaFill->fValue != fAlphaFill )
continue;
}
// Сравниваем BlendMode
Name pBlendMode = (Name)DictGetItem( (Dict)pExtGState, "BM", OCLASS_NAME );
if ( NULL == pBlendMode )
{
if ( BMEOF != eMode )
continue;
}
else
{
if ( BMEOF == eMode || 0 != UtilsStrCmp( pBlendMode->sValue, BM_NAMES[ (int)eMode ] ) )
continue;
}
// Сравниваем StrokeAdjustment
BooleanRecPtr pSA = (BooleanRecPtr)DictGetItem( (Dict)pExtGState, "SA", OCLASS_BOOLEAN );
if ( NULL == pSA )
{
if ( -1 != nStrokeAdjustment )
continue;
}
else
{
if ( -1 == nStrokeAdjustment || ( 0 == nStrokeAdjustment && true == pSA->bValue ) || ( 1 == nStrokeAdjustment && false == pSA->bValue ) )
continue;
}
return pExtGState;
}
return NULL;
}
ExtGState GetExtGState (Doc pPDF, float fAlphaStroke/* = -1*/, float fAlphaFill/* = -1*/, BlendMode eMode/* = BMEOF*/, int nStrokeAdjustment /*= -1*/)
{
ExtGState pExtGState = FindExtGState( pPDF, fAlphaStroke, fAlphaFill, eMode, nStrokeAdjustment );
if ( NULL == pExtGState )
{
pExtGState = CreateExtGState( pPDF );
if ( NULL == pExtGState )
return NULL;
if ( -1 != fAlphaStroke )
ExtGStateSetAlphaStroke( pExtGState, fAlphaStroke );
if ( -1 != fAlphaFill )
ExtGStateSetAlphaFill( pExtGState, fAlphaFill );
if ( BMEOF != eMode )
ExtGStateSetBlendMode( pExtGState, eMode );
if ( -1 != nStrokeAdjustment )
ExtGStateSetStrokeAdjustment( pExtGState, (bool)nStrokeAdjustment );
ListAdd( pPDF->pExtGStateList, pExtGState );
}
return pExtGState;
}
unsigned long SetCompressionMode (Doc pPDF, unsigned int nMode)
{
if ( !DocValidate( pPDF ) )
return AVS_OFFICEPDFWRITER_ERROR_INVALID_DOCUMENT;
if ( nMode != ( nMode & COMP_MASK ) )
return RaiseError( &pPDF->oError, AVS_OFFICEPDFWRITER_ERROR_INVALID_COMPRESSION_MODE, 0);
#ifndef NOZLIB
pPDF->nCompressionMode = nMode;
return OK;
#else /* NOZLIB */
return AVS_OFFICEPDFWRITER_ERROR_INVALID_COMPRESSION_MODE;
#endif /* NOZLIB */
}
unsigned long GetError (Doc pPDF)
{
if ( !DocValidate( pPDF ) )
return AVS_OFFICEPDFWRITER_ERROR_INVALID_DOCUMENT;
return ErrorGetCode( &pPDF->oError );
}
unsigned long GetErrorDetail (Doc pPDF)
{
if ( !DocValidate( pPDF ) )
return AVS_OFFICEPDFWRITER_ERROR_INVALID_DOCUMENT;
return ErrorGetDetailCode( &pPDF->oError );
}
void ResetError (Doc pPDF)
{
if ( !DocValidate( pPDF ) )
return;
ErrorReset( &pPDF->oError );
}
//----------------- Основные функции -----------------------------------------------------------------
bool DocValidate (Doc pPDF)
{
if ( !pPDF || pPDF->nSigBytes != SIG_BYTES )
return false;
else
return true;
}
bool HasDoc (Doc pPDF)
{
if ( !pPDF || pPDF->nSigBytes != SIG_BYTES )
return false;
if ( !pPDF->pCatalog/* || pPDF->oError.nErrorNo != NOERROR*/)
{
RaiseError( &pPDF->oError, AVS_OFFICEPDFWRITER_ERROR_INVALID_DOCUMENT, 0 );
return false;
}
else
return true;
}
void FreeDoc (Doc pPDF)
{
if ( DocValidate( pPDF ) )
{
if ( pPDF->pXref )
{
XrefFree( pPDF->pXref );
pPDF->pXref = NULL;
}
if ( pPDF->pFontManager )
{
ListFree( pPDF->pFontManager );
pPDF->pFontManager = NULL;
}
if ( pPDF->pFontDefList )
CleanupFontDefList( pPDF );
UtilsMemSet( pPDF->aTTFontTag, 0, 6);
pPDF->ePdfVersion = PDF_1_3;
pPDF->pOutlines = NULL;
pPDF->pCatalog = NULL;
pPDF->pRootPages = NULL;
pPDF->pCurPages = NULL;
pPDF->pCurPage = NULL;
pPDF->bEncryptOn = false;
pPDF->nCurPageNum = 0;
pPDF->pCurEncoder = NULL;
pPDF->pDefEncoder = NULL;
pPDF->nPagePerPages = 0;
if ( pPDF->pPageList )
{
ListFree( pPDF->pPageList );
pPDF->pPageList = NULL;
}
if ( pPDF->pExtGStateList )
{
ListFree( pPDF->pExtGStateList );
pPDF->pExtGStateList = NULL;
}
pPDF->pEncryptDict = NULL;
pPDF->pInfo = NULL;
ErrorReset( &pPDF->oError );
if ( pPDF->pStream )
{
StreamFree( pPDF->pStream );
pPDF->pStream = NULL;
}
::memset( pPDF->wsTempDir, 0x00, MAX_PATH );
}
}
void FreeDocAll (Doc pPDF)
{
if ( DocValidate( pPDF ) )
{
FreeDoc( pPDF );
if ( pPDF->pFontDefList )
FreeFontDefList( pPDF );
if ( pPDF->pEncoderList )
FreeEncoderList( pPDF );
if ( pPDF->pToUnicodeList )
FreeToUnicodeList( pPDF );
pPDF->nCompressionMode = COMP_NONE;
ErrorReset( &pPDF->oError );
}
}
void Free (Doc pPDF)
{
if ( pPDF )
{
MMgr oMMgr = pPDF->oMMgr;
FreeDocAll( pPDF );
pPDF->nSigBytes = 0;
FreeMem( oMMgr, pPDF );
MMgrFree( oMMgr );
}
}
unsigned long NewDoc (Doc pPDF)
{
if ( !DocValidate( pPDF ) )
return AVS_OFFICEPDFWRITER_ERROR_DOC_INVALID_OBJECT;
FreeDoc( pPDF );
pPDF->pXref = XrefNew( pPDF->oMMgr, 0);
if ( !pPDF->pXref )
return CheckError( &pPDF->oError );
pPDF->pTrailer = pPDF->pXref->oTrailer;
pPDF->pFontManager = ListNew( pPDF->oMMgr, DEF_ITEMS_PER_BLOCK );
if ( !pPDF->pFontManager )
return CheckError( &pPDF->oError );
if ( !pPDF->pFontDefList )
{
pPDF->pFontDefList = ListNew( pPDF->oMMgr, DEF_ITEMS_PER_BLOCK);
if ( !pPDF->pFontDefList )
return CheckError( &pPDF->oError );
}
if ( !pPDF->pEncoderList )
{
pPDF->pEncoderList = ListNew( pPDF->oMMgr, DEF_ITEMS_PER_BLOCK );
if ( !pPDF->pEncoderList )
return CheckError( &pPDF->oError );
}
if ( !pPDF->pToUnicodeList )
{
pPDF->pToUnicodeList = ListNew( pPDF->oMMgr, DEF_ITEMS_PER_BLOCK );
if ( !pPDF->pToUnicodeList )
return CheckError( &pPDF->oError );
}
if ( !pPDF->pExtGStateList )
{
pPDF->pExtGStateList = ListNew( pPDF->oMMgr, DEF_ITEMS_PER_BLOCK );
if ( !pPDF->pExtGStateList )
return CheckError( &pPDF->oError );
}
pPDF->pCatalog = CatalogNew( pPDF->oMMgr, pPDF->pXref );
if ( !pPDF->pCatalog)
return CheckError( &pPDF->oError );
pPDF->pRootPages = CatalogGetRoot( pPDF->pCatalog );
if ( !pPDF->pRootPages )
return CheckError( &pPDF->oError );
pPDF->pPageList = ListNew( pPDF->oMMgr, DEF_PAGE_LIST_NUM );
if ( !pPDF->pPageList )
return CheckError( &pPDF->oError );
pPDF->pCurPages = pPDF->pRootPages;
char sBuf[TEMP_BUFFER_SIZE];
char *pPointer = sBuf;
char *pEndPointer = sBuf + TEMP_BUFFER_SIZE - 1;
const char *sVersion;
pPointer = (char *)UtilsStrCpy( pPointer, "Ascensio System SIA Copyright (c) 2013", pEndPointer);
//sVersion = STRVER;
// UtilsStrCpy( pPointer, sVersion, pEndPointer);
if ( OK != SetInfoAttr( pPDF, InfoProducer, sBuf ) )
return CheckError( &pPDF->oError );
//pPDF->resources = CreateExtGState(pPDF); // список ресурсов ( в атрибут Resources если записывать данные то Adobe просмотрщик не видит их )
return OK;
}
Doc NewEx (ErrorHandler pUserErrorFn, AllocFunc pUserAllocFn, FreeFunc pUserFreeFn, unsigned int nMemPoolBufSize, void *pUserData)
{
ErrorRec oTempError;
// инициализируем временный объект описания ошибок
ErrorInit( &oTempError, pUserData );
// создаем объект для управления памятью
MMgr oMMgr = MMgrNew( &oTempError, nMemPoolBufSize, pUserAllocFn, pUserFreeFn );
if ( !oMMgr )
{
CheckError( &oTempError );
return NULL;
}
// создаем объект - документ
Doc pPDF = (Doc)GetMem( oMMgr, sizeof (DocRec) );
if ( !pPDF )
{
MMgrFree( oMMgr );
CheckError( &oTempError );
return NULL;
}
oMMgr->pDoc = pPDF;
UtilsMemSet( pPDF, 0, sizeof( DocRec ) );
pPDF->nSigBytes = SIG_BYTES;
pPDF->oMMgr = oMMgr;
pPDF->ePdfVersion = PDF_1_3;
pPDF->nCompressionMode = COMP_NONE;
// копируем данные из oTempError в объект для ошибок, содержащийся в структуре Doc
pPDF->oError = oTempError;
// меням указатель на объект Error для MemoryManager
oMMgr->oError = &pPDF->oError;
if ( OK != NewDoc( pPDF ) )
{
Free( pPDF );
CheckError( &oTempError );
return NULL;
}
pPDF->oError.ErrorFn = pUserErrorFn;
pPDF->nCMapCount = 0;
return pPDF;
}
Doc New (ErrorHandler pUserErrorFn, void *pUserData)
{
return NewEx( pUserErrorFn, NULL, NULL, 0, pUserData);
}
Doc New (void)
{
return New( NULL, NULL);
}
unsigned long SetPagesConfiguration (Doc pPDF, unsigned int nPagePerPages)
{
if ( !HasDoc( pPDF ) )
return AVS_OFFICEPDFWRITER_ERROR_INVALID_DOCUMENT;
if ( pPDF->pCurPage )
return RaiseError( &pPDF->oError, AVS_OFFICEPDFWRITER_ERROR_INVALID_DOCUMENT_STATE, 0);
if ( nPagePerPages > LIMIT_MAX_ARRAY )
return RaiseError( &pPDF->oError, AVS_OFFICEPDFWRITER_ERROR_INVALID_PARAMETER, 0);
if ( pPDF->pCurPages == pPDF->pRootPages )
{
pPDF->pCurPages = DocAddPagesTo( pPDF, pPDF->pRootPages );
if ( !pPDF->pCurPages )
return pPDF->oError.nErrorNo;
pPDF->nCurPageNum = 0;
}
pPDF->nPagePerPages = nPagePerPages;
return OK;
}
unsigned long DocSetEncryptOn (Doc pPDF)
{
if ( pPDF->bEncryptOn )
return OK;
if ( !pPDF->pEncryptDict )
return SetError( &pPDF->oError, AVS_OFFICEPDFWRITER_ERROR_DOC_ENCRYPTDICT_NOT_FOUND, 0);
if ( OTYPE_NONE == pPDF->pEncryptDict->pHeader.nObjClass )
if ( OK != XrefAdd( pPDF->pXref, pPDF->pEncryptDict ) )
return pPDF->oError.nErrorNo;
if ( OK != DictAdd( pPDF->pTrailer, "EncryptRecPtr", pPDF->pEncryptDict ) )
return pPDF->oError.nErrorNo;
pPDF->bEncryptOn = true;
return OK;
}
unsigned long SetPassword (Doc pPDF, const char *sOwnerPassword, const char *sUserPassword)
{
if ( !HasDoc( pPDF ) )
return AVS_OFFICEPDFWRITER_ERROR_DOC_INVALID_OBJECT;
if ( !pPDF->pEncryptDict )
{
pPDF->pEncryptDict = EncryptDictNew( pPDF->oMMgr, pPDF->pXref );
if ( !pPDF->pEncryptDict )
return CheckError( &pPDF->oError );
}
if ( OK != EncryptDictSetPassword( pPDF->pEncryptDict, sOwnerPassword, sUserPassword ) )
return CheckError( &pPDF->oError );
return DocSetEncryptOn( pPDF );
}
unsigned long SetPermission (Doc pPDF, unsigned int nPermission)
{
if ( !HasDoc( pPDF ) )
return AVS_OFFICEPDFWRITER_ERROR_DOC_INVALID_OBJECT;
EncryptRecPtr pEncrypt = EncryptDictGetAttr( pPDF->pEncryptDict );
if ( !pEncrypt )
return RaiseError( &pPDF->oError, AVS_OFFICEPDFWRITER_ERROR_DOC_ENCRYPTDICT_NOT_FOUND, 0);
else
pEncrypt->nPermission = nPermission;
return OK;
}
unsigned long SetEncryptionMode (Doc pPDF, EncryptMode eMode, unsigned int nKeyLen)
{
if ( !HasDoc( pPDF ) )
return AVS_OFFICEPDFWRITER_ERROR_DOC_INVALID_OBJECT;
EncryptRecPtr pEncrypt = EncryptDictGetAttr( pPDF->pEncryptDict );
if ( !pEncrypt )
return RaiseError( &pPDF->oError, AVS_OFFICEPDFWRITER_ERROR_DOC_ENCRYPTDICT_NOT_FOUND, 0);
else
{
if ( EncryptR2 == eMode )
pEncrypt->nKeyLen = 5;
else
{
pPDF->ePdfVersion = PDF_1_4;
if ( nKeyLen >= 5 && nKeyLen <= 16 )
pEncrypt->nKeyLen = nKeyLen;
else if ( 0 == nKeyLen )
pEncrypt->nKeyLen = 16;
else
return RaiseError( &pPDF->oError, AVS_OFFICEPDFWRITER_ERROR_INVALID_ENCRYPT_KEY_LEN, 0 );
}
pEncrypt->eMode = eMode;
}
return OK;
}
unsigned long DocSetEncryptOff (Doc pPDF)
{
if ( !pPDF->bEncryptOn )
return OK;
// Если EncryptDict зарегистрирован в cross-reference-table, заменяем его нулевым объектом.
// Кроме этого, удаляем EncryptDict из трайлера.
if ( pPDF->pEncryptDict )
{
unsigned int nObjId = pPDF->pEncryptDict->pHeader.nObjId;
if ( nObjId & OTYPE_INDIRECT )
{
DictRemoveElement( pPDF->pTrailer, "EncryptRecPtr" );
XrefEntry pEntry = XrefGetEntryByObjectId( pPDF->pXref, nObjId & 0x00FFFFFF );
if ( !pEntry )
return SetError( &pPDF->oError, AVS_OFFICEPDFWRITER_ERROR_DOC_ENCRYPTDICT_NOT_FOUND, 0);
Null pNull = NullNew( pPDF->oMMgr );
if ( !pNull )
return pPDF->oError.nErrorNo;
pEntry->pObj = pNull;
pNull->pHeader.nObjId = nObjId | OTYPE_INDIRECT;
pPDF->pEncryptDict->pHeader.nObjId = OTYPE_NONE;
}
}
pPDF->bEncryptOn = false;
return OK;
}
unsigned long DocPrepareEncryption (Doc pPDF)
{
EncryptRecPtr pEncrypt = EncryptDictGetAttr( pPDF->pEncryptDict );
Dict pInfo = GetInfo( pPDF );
if ( !pEncrypt )
return AVS_OFFICEPDFWRITER_ERROR_DOC_ENCRYPTDICT_NOT_FOUND;
if ( !pInfo )
return pPDF->oError.nErrorNo;
if ( OK != EncryptDictPrepare( pPDF->pEncryptDict, pInfo, pPDF->pXref ) )
return pPDF->oError.nErrorNo;
Array pID = (Array)DictGetItem( pPDF->pTrailer, "ID", OCLASS_ARRAY );
if ( !pID )
{
pID = ArrayNew( pPDF->oMMgr );
if ( !pID || OK != DictAdd( pPDF->pTrailer, "ID", pID ) )
return pPDF->oError.nErrorNo;
}
else
ArrayClear( pID );
if ( OK != ArrayAdd( pID, BinaryNew( pPDF->oMMgr, pEncrypt->anEncryptID, ID_LEN ) ) )
return pPDF->oError.nErrorNo;
if ( OK != ArrayAdd( pID, BinaryNew( pPDF->oMMgr, pEncrypt->anEncryptID, ID_LEN ) ) )
return pPDF->oError.nErrorNo;
return OK;
}
unsigned long SaveToStream (Doc pPDF)
{
if ( !HasDoc( pPDF ) )
return AVS_OFFICEPDFWRITER_ERROR_INVALID_DOCUMENT;
if ( !pPDF->pStream )
pPDF->pStream = MemStreamNew( pPDF->oMMgr, STREAM_BUF_SIZ );
if ( !StreamValidate( pPDF->pStream ) )
return RaiseError( &pPDF->oError, AVS_OFFICEPDFWRITER_ERROR_INVALID_STREAM, 0);
MemStreamFreeData( pPDF->pStream );
if ( OK != InternalSaveToStream( pPDF, pPDF->pStream ) )
return CheckError( &pPDF->oError );
return OK;
}
unsigned long InternalSaveToStream (Doc pPDF, StreamRecPtr pStream)
{
unsigned long nRet = OK;
// пишем заголовок
if ( OK != ( nRet = WriteHeader( pPDF, pStream ) ) )
return nRet;
// подготовка trailer
if ( OK != ( nRet = PrepareTrailer( pPDF ) ) )
return nRet;
// подготовка шифрования
if ( pPDF->bEncryptOn )
{
EncryptRecPtr pEncrypt = EncryptDictGetAttr( pPDF->pEncryptDict );
if ( OK != ( nRet = DocPrepareEncryption( pPDF ) ) )
return nRet;
if ( OK != ( nRet = XrefWriteToStream( pPDF->pXref, pStream, pEncrypt ) ) )
return nRet;
}
else
{
if ( OK != ( nRet = XrefWriteToStream( pPDF->pXref, pStream, NULL ) ) )
return nRet;
}
return OK;
}
//const char* LoadType1FontFromStream(Doc pPDF, StreamRecPtr pAfmData, StreamRecPtr pPfmData, short nType/* = 0*/);
//const char* LoadTTFontFromStream (Doc pPDF, bool bEmbedding, std::wstring & wsFileName, const char *sEncodingName = NULL, const char *sPrefix = NULL);
//const char* LoadTTFontFromStream2 (Doc pPDF, unsigned int nIndex, bool bEmbedding, std::wstring & wsFileName);
unsigned int GetStreamSize (Doc pPDF)
{
if ( !HasDoc( pPDF ) )
return AVS_OFFICEPDFWRITER_ERROR_INVALID_DOCUMENT;
if ( !StreamValidate( pPDF->pStream ) )
return 0;
return StreamSize( pPDF->pStream );
}
unsigned long ReadFromStream (Doc pPDF, BYTE *pBuf, unsigned int *pnSize)
{
unsigned int nSize = *pnSize;
unsigned long nRet = OK;
if ( !HasDoc( pPDF ) )
return AVS_OFFICEPDFWRITER_ERROR_INVALID_DOCUMENT;
if ( !StreamValidate( pPDF->pStream ) )
return RaiseError( &pPDF->oError, AVS_OFFICEPDFWRITER_ERROR_INVALID_OPERATION, 0);
if ( *pnSize == 0 )
return RaiseError( &pPDF->oError, AVS_OFFICEPDFWRITER_ERROR_INVALID_PARAMETER, 0);
nRet = StreamRead( pPDF->pStream, pBuf, &nSize );
*pnSize = nSize;
if ( OK != nRet )
CheckError( &pPDF->oError );
return nRet;
}
unsigned long ResetStream (Doc pPDF)
{
if ( !HasDoc( pPDF ) )
return AVS_OFFICEPDFWRITER_ERROR_INVALID_DOCUMENT;
if ( !StreamValidate( pPDF->pStream ) )
return RaiseError( &pPDF->oError, AVS_OFFICEPDFWRITER_ERROR_INVALID_OPERATION, 0);
return StreamSeek( pPDF->pStream, 0, SeekSet );
}
unsigned long SaveDocToFile (Doc pPDF, std::wstring & wsFileName)
{
if ( !HasDoc( pPDF ) )
return AVS_OFFICEPDFWRITER_ERROR_INVALID_DOCUMENT;
StreamRecPtr pStream = FileWriterNew( pPDF->oMMgr, wsFileName, true );
if ( !pStream )
return CheckError( &pPDF->oError );
InternalSaveToStream( pPDF, pStream );
StreamFree( pStream );
return CheckError( &pPDF->oError );
}
Page GetCurrentPage (Doc pPDF)
{
if ( !HasDoc( pPDF ) )
return NULL;
return pPDF->pCurPage;
}
Page GetPageByIndex (Doc pPDF, unsigned int nIndex)
{
Page pRes = NULL;
if ( !HasDoc( pPDF ) )
return NULL;
pRes = (Page)ListItemAt( pPDF->pPageList, nIndex );
if ( !pRes )
{
RaiseError( &pPDF->oError, AVS_OFFICEPDFWRITER_ERROR_INVALID_PAGE_INDEX, 0 );
return NULL;
}
return pRes;
}
Pages DocGetCurrentPages (Doc pPDF)
{
if ( !HasDoc( pPDF ) )
return NULL;
return pPDF->pCurPages;
}
unsigned long DocSetCurrentPages (Doc pPDF, Pages pPages)
{
if ( !HasDoc( pPDF ) )
return AVS_OFFICEPDFWRITER_ERROR_INVALID_DOCUMENT;
if ( !PagesValidate( pPages ) )
return SetError( &pPDF->oError, AVS_OFFICEPDFWRITER_ERROR_INVALID_PAGES, 0 );
// проверяем принадлежит ли объект pPages нашему pdf - документу
if ( pPDF->oMMgr != pPages->oMMgr )
return SetError( &pPDF->oError, AVS_OFFICEPDFWRITER_ERROR_INVALID_PAGES, 0 );
pPDF->pCurPages = pPages;
return OK;
}
unsigned long DocSetCurrentPage (Doc pPDF, Page pPage)
{
if ( !HasDoc( pPDF ) )
return AVS_OFFICEPDFWRITER_ERROR_INVALID_DOCUMENT;
if ( !PageValidate( pPage ) )
return SetError( &pPDF->oError, AVS_OFFICEPDFWRITER_ERROR_INVALID_PAGE, 0);
// проверяем принадлежит ли объект pPage нашему pdf - документу
if ( pPDF->oMMgr != pPage->oMMgr )
return SetError( &pPDF->oError, AVS_OFFICEPDFWRITER_ERROR_INVALID_PAGE, 0 );
pPDF->pCurPage = pPage;
return OK;
}
unsigned long DocSetTempDir (Doc pPDF, wchar_t *wsTempDir)
{
if ( !HasDoc( pPDF ) )
return AVS_OFFICEPDFWRITER_ERROR_INVALID_DOCUMENT;
wcscpy( pPDF->wsTempDir, wsTempDir );
return OK;
}
Page AddPage (Doc pPDF)
{
if ( !HasDoc( pPDF ) )
return NULL;
Page pPage;
unsigned long nRet = OK;
if ( pPDF->nPagePerPages )
{
if ( pPDF->nPagePerPages <= pPDF->nCurPageNum )
{
pPDF->pCurPages = DocAddPagesTo( pPDF, pPDF->pRootPages );
if ( !pPDF->pCurPages )
return NULL;
pPDF->nCurPageNum = 0;
}
}
pPage = PageNew( pPDF->oMMgr, pPDF->pXref );
if ( !pPage )
{
CheckError( &pPDF->oError );
return NULL;
}
if ( OK != ( nRet = PagesAddKids( pPDF->pCurPages, pPage ) ) )
{
RaiseError( &pPDF->oError, nRet, 0);
return NULL;
}
if ( OK != ( nRet = ListAdd( pPDF->pPageList, pPage ) ) )
{
RaiseError( &pPDF->oError, nRet, 0);
return NULL;
}
pPDF->pCurPage = pPage;
#ifdef FILTER_FLATE_DECODE_ENABLED
if ( pPDF->nCompressionMode & COMP_TEXT )
PageSetFilter( pPage, STREAM_FILTER_FLATE_DECODE );
#endif
pPDF->nCurPageNum++;
return pPage;
}
Pages DocAddPagesTo (Doc pPDF, Pages pParent)
{
Pages pPages = NULL;
if ( !HasDoc( pPDF ) )
return NULL;
if ( !PagesValidate( pParent ) )
{
RaiseError( &pPDF->oError, AVS_OFFICEPDFWRITER_ERROR_INVALID_PAGES, 0);
return NULL;
}
// проверяем принадлежит ли страница нашему PDF документу
if ( pPDF->oMMgr != pParent->oMMgr )
{
RaiseError( &pPDF->oError, AVS_OFFICEPDFWRITER_ERROR_INVALID_PAGES, 0);
return NULL;
}
pPages = PagesNew( pPDF->oMMgr, pParent, pPDF->pXref );
if ( pPages )
pPDF->pCurPages = pPages;
else
CheckError( &pPDF->oError );
return pPages;
}
Page InsertPage (Doc pPDF, Page pTarget)
{
Page pPage = NULL;
unsigned long nRet = OK;
if ( !HasDoc( pPDF ) )
return NULL;
if ( !PageValidate( pTarget ) )
{
RaiseError( &pPDF->oError, AVS_OFFICEPDFWRITER_ERROR_INVALID_PAGE, 0);
return NULL;
}
// проверяем принадлежит ли объект pTarget нашему pdf - документу
if ( pPDF->oMMgr != pTarget->oMMgr )
{
RaiseError( &pPDF->oError, AVS_OFFICEPDFWRITER_ERROR_INVALID_PAGE, 0);
return NULL;
}
pPage = PageNew( pPDF->oMMgr, pPDF->pXref );
if ( !pPage )
{
CheckError( &pPDF->oError );
return NULL;
}
if ( OK != ( nRet = PageInsertBefore( pPage, pTarget ) ) )
{
RaiseError( &pPDF->oError, nRet, 0 );
return NULL;
}
if ( OK != ( nRet = ListInsert( pPDF->pPageList, pTarget, pPage ) ) )
{
RaiseError( &pPDF->oError, nRet, 0 );
return NULL;
}
#ifdef FILTER_FLATE_DECODE_ENABLED
if ( pPDF->nCompressionMode & COMP_TEXT )
PageSetFilter( pPage, STREAM_FILTER_FLATE_DECODE );
#endif
return pPage;
}
unsigned long SetErrorHandler (Doc pPDF, ErrorHandler pUserErrorFn)
{
if ( !DocValidate( pPDF ) )
return AVS_OFFICEPDFWRITER_ERROR_INVALID_DOCUMENT;
pPDF->oError.ErrorFn = pUserErrorFn;
return OK;
}