Files
core/PdfReader/PdfReader.cpp
2016-12-14 16:56:56 +03:00

363 lines
12 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.

/*
* (c) Copyright Ascensio System SIA 2010-2016
*
* This program is a free software product. You can redistribute it and/or
* modify it under the terms of the GNU Affero General Public License (AGPL)
* version 3 as published by the Free Software Foundation. In accordance with
* Section 7(a) of the GNU AGPL its Section 15 shall be amended to the effect
* that Ascensio System SIA expressly excludes the warranty of non-infringement
* of any third-party rights.
*
* This program is distributed WITHOUT ANY WARRANTY; without even the implied
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. For
* details, see the GNU AGPL at: http://www.gnu.org/licenses/agpl-3.0.html
*
* You can contact Ascensio System SIA at Lubanas st. 125a-25, Riga, Latvia,
* EU, LV-1021.
*
* The interactive user interfaces in modified source and object code versions
* of the Program must display Appropriate Legal Notices, as required under
* Section 5 of the GNU AGPL version 3.
*
* Pursuant to Section 7(b) of the License you must retain the original Product
* logo when distributing the program. Pursuant to Section 7(e) we decline to
* grant you any rights under trademark law for use of our trademarks.
*
* All the Product's GUI elements, including illustrations and icon sets, as
* well as technical writing content are licensed under the terms of the
* Creative Commons Attribution-ShareAlike 4.0 International. See the License
* terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode
*
*/
#include "PdfReader.h"
#include "../Common/OfficeDefines.h"
#include "../DesktopEditor/raster/BgraFrame.h"
#include "../DesktopEditor/graphics/GraphicsRenderer.h"
#include "../DesktopEditor/fontengine/ApplicationFonts.h"
#include "../DesktopEditor/fontengine/FontManager.h"
#include "../DesktopEditor/graphics/IRenderer.h"
#include "../DesktopEditor/common/Directory.h"
#include "Src/StringExt.h"
#include "Src/PDFDoc.h"
#include "Src/GlobalParams.h"
#include "Src/ErrorConstants.h"
#include "Src/ExtractImageOutputDev.h"
#include "Src/RendererOutputDev.h"
#include <string>
namespace PdfReader
{
class CPdfReader_Private
{
public:
PDFDoc* m_pPDFDocument;
GlobalParams* m_pGlobalParams;
std::wstring m_wsTempFolder;
std::wstring m_wsCMapFolder;
CApplicationFonts* m_pAppFonts;
CFontManager* m_pFontManager;
CFontList* m_pFontList;
};
CPdfReader::CPdfReader(CApplicationFonts* pAppFonts)
{
m_pInternal = new CPdfReader_Private();
m_pInternal->m_wsTempFolder = L"";
m_pInternal->m_wsCMapFolder = L"";
m_pInternal->m_pPDFDocument = NULL;
m_pInternal->m_pFontManager = NULL;
m_pInternal->m_pGlobalParams = new GlobalParams();
m_pInternal->m_pFontList = new CFontList();
m_pInternal->m_pAppFonts = pAppFonts;
// Создаем менеджер шрифтов с собственным кэшем
m_pInternal->m_pFontManager = pAppFonts->GenerateFontManager();
CFontsCache* pMeasurerCache = new CFontsCache();
pMeasurerCache->SetStreams(pAppFonts->GetStreams());
m_pInternal->m_pFontManager->SetOwnerCache(pMeasurerCache);
pMeasurerCache->SetCacheSize(1);
m_pInternal->m_pGlobalParams->SetFontManager(m_pInternal->m_pFontManager);
m_eError = errorNone;
}
CPdfReader::~CPdfReader()
{
if (m_pInternal->m_pFontList)
{
m_pInternal->m_pFontList->Clear();
delete m_pInternal->m_pFontList;
}
m_pInternal->m_wsCMapFolder = L"";
if (!m_pInternal->m_wsTempFolder.empty())
{
NSDirectory::DeleteDirectory(m_pInternal->m_wsTempFolder);
m_pInternal->m_wsTempFolder = L"";
}
RELEASEOBJECT((m_pInternal->m_pPDFDocument));
RELEASEOBJECT((m_pInternal->m_pGlobalParams));
RELEASEINTERFACE((m_pInternal->m_pFontManager));
}
bool CPdfReader::LoadFromFile(const std::wstring& wsSrcPath, const std::wstring& wsOptions,
const std::wstring& wsOwnerPassword, const std::wstring& wsUserPassword)
{
// TODO: Сейчас при загрузке каждой новой картинки мы пересоздаем
// FontManager, потому что сейчас в нем кэш без ограничения.
//------------------------------------------------------
RELEASEINTERFACE((m_pInternal->m_pFontManager));
m_pInternal->m_pFontManager = m_pInternal->m_pAppFonts->GenerateFontManager();
CFontsCache* pMeasurerCache = new CFontsCache();
pMeasurerCache->SetStreams(m_pInternal->m_pAppFonts->GetStreams());
m_pInternal->m_pFontManager->SetOwnerCache(pMeasurerCache);
pMeasurerCache->SetCacheSize(1);
m_pInternal->m_pGlobalParams->SetFontManager(m_pInternal->m_pFontManager);
//------------------------------------------------------
if (m_pInternal->m_pPDFDocument)
delete m_pInternal->m_pPDFDocument;
StringExt *seOwner = NULL, *seUser = NULL;
if (!wsOwnerPassword.empty())
seOwner = new StringExt(wsOwnerPassword.c_str());
if (!wsUserPassword.empty())
seUser = new StringExt(wsUserPassword.c_str());
m_eError = errorNone;
m_pInternal->m_pPDFDocument = new PDFDoc(m_pInternal->m_pGlobalParams, wsSrcPath.c_str(), seOwner, seUser);
if (m_pInternal->m_pPDFDocument)
m_eError = m_pInternal->m_pPDFDocument->GetErrorCode();
else
m_eError = errorMemory;
if (seUser)
delete seUser;
if (seOwner)
delete seOwner;
if (!m_pInternal->m_pPDFDocument || !m_pInternal->m_pPDFDocument->CheckValidation())
{
RELEASEOBJECT(m_pInternal->m_pPDFDocument);
return false;
}
m_pInternal->m_pFontList->Clear();
return (errorNone == m_eError);
}
void CPdfReader::Close()
{
RELEASEOBJECT((m_pInternal->m_pPDFDocument));
}
EError CPdfReader::GetError()
{
if (!m_pInternal->m_pPDFDocument)
return m_eError;
return m_pInternal->m_pPDFDocument->GetErrorCode();
}
int CPdfReader::GetPagesCount()
{
if (!m_pInternal->m_pPDFDocument)
return 0;
return m_pInternal->m_pPDFDocument->GetPagesCount();
}
double CPdfReader::GetVersion()
{
if (!m_pInternal->m_pPDFDocument)
return 0;
return m_pInternal->m_pPDFDocument->GetPDFVersion();
}
int CPdfReader::GetPermissions()
{
if (!m_pInternal->m_pPDFDocument)
return 0;
int nPermissions = 0;
if (m_pInternal->m_pPDFDocument->CheckPrint())
nPermissions += PERMISSION_PRINT;
if (m_pInternal->m_pPDFDocument->CheckCopy())
nPermissions += PERMISSION_COPY;
if (m_pInternal->m_pPDFDocument->CheckChange())
nPermissions += PERMISSION_CHANGE;
return nPermissions;
}
bool CPdfReader::ExtractAllImages(const wchar_t* wsDstPath, const wchar_t* wsPrefix)
{
StringExt seString(wsDstPath);
ExtractImageOutputDev *pOutputDev = new ExtractImageOutputDev(m_pInternal->m_pGlobalParams, seString.GetBuffer(), true);
if (!pOutputDev)
return false;
int nPagesCount = GetPagesCount();
for (int nIndex = 1; nIndex <= nPagesCount; nIndex++)
{
m_pInternal->m_pPDFDocument->DisplayPage(pOutputDev, nIndex, 72, 72, 0, false, false, false);
}
delete pOutputDev;
return true;
}
void CPdfReader::GetPageInfo(int _nPageIndex, double* pdWidth, double* pdHeight, double* pdDpiX, double* pdDpiY)
{
int nPageIndex = _nPageIndex + 1;
if (!m_pInternal->m_pPDFDocument)
return;
const double c_dInch = 25.399; // Миллиметров в дюйме
const double c_dXResolution = 154.0;
const double c_dYResolution = 154.0;
double dKoefX = c_dInch / c_dXResolution;
double dKoefY = c_dInch / c_dYResolution;
int nRotate = m_pInternal->m_pPDFDocument->GetPageRotate(nPageIndex);
while (nRotate >= 360)
nRotate -= 360;
while (nRotate < 0)
nRotate += 360;
if (0 != nRotate && 180 != nRotate)
{
*pdHeight = m_pInternal->m_pPDFDocument->GetPageCropWidth(nPageIndex);
*pdWidth = m_pInternal->m_pPDFDocument->GetPageCropHeight(nPageIndex);
}
else
{
*pdWidth = m_pInternal->m_pPDFDocument->GetPageCropWidth(nPageIndex);
*pdHeight = m_pInternal->m_pPDFDocument->GetPageCropHeight(nPageIndex);
}
*pdDpiX = 72;
*pdDpiY = 72;
}
void CPdfReader::DrawPageOnRenderer(IRenderer* pRenderer, int _nPageIndex, bool* pbBreak)
{
int nPageIndex = _nPageIndex + 1;
if (m_pInternal->m_pPDFDocument && pRenderer)
{
RendererOutputDev oRendererOut(m_pInternal->m_pGlobalParams, pRenderer, m_pInternal->m_pFontManager, m_pInternal->m_pFontList);
oRendererOut.NewPDF(m_pInternal->m_pPDFDocument->GetXRef());
oRendererOut.SetBreak(pbBreak);
m_pInternal->m_pPDFDocument->DisplayPage(&oRendererOut, nPageIndex, 72.0, 72.0, 0, false, true, false);
}
}
void CPdfReader::ConvertToRaster(int nPageIndex, const std::wstring& wsDstPath, int nImageType, const int nRasterW, const int nRasterH)
{
CFontManager *pFontManager = m_pInternal->m_pAppFonts->GenerateFontManager();
CFontsCache* pFontCache = new CFontsCache();
pFontCache->SetStreams(m_pInternal->m_pAppFonts->GetStreams());
pFontManager->SetOwnerCache(pFontCache);
CGraphicsRenderer oRenderer;
oRenderer.SetFontManager(pFontManager);
double dWidth, dHeight;
double dDpiX, dDpiY;
GetPageInfo(nPageIndex, &dWidth, &dHeight, &dDpiX, &dDpiY);
int nWidth = (nRasterW > 0) ? nRasterW : ((int)dWidth * 72 / 25.4);
int nHeight = (nRasterH > 0) ? nRasterH : ((int)dHeight * 72 / 25.4);
BYTE* pBgraData = new BYTE[nWidth * nHeight * 4];
if (!pBgraData)
return;
memset(pBgraData, 0xff, nWidth * nHeight * 4);
CBgraFrame oFrame;
oFrame.put_Data(pBgraData);
oFrame.put_Width(nWidth);
oFrame.put_Height(nHeight);
oFrame.put_Stride(-4 * nWidth);
oRenderer.CreateFromBgraFrame(&oFrame);
oRenderer.SetSwapRGB(false);
dWidth *= 25.4 / dDpiX;
dHeight *= 25.4 / dDpiY;
oRenderer.put_Width(dWidth);
oRenderer.put_Height(dHeight);
bool bBreak = false;
DrawPageOnRenderer(&oRenderer, nPageIndex, &bBreak);
oFrame.SaveFile(wsDstPath, nImageType);
RELEASEINTERFACE(pFontManager);
}
int CPdfReader::GetImagesCount()
{
ExtractImageOutputDev *pOutputDev = new ExtractImageOutputDev(m_pInternal->m_pGlobalParams, NULL, true, true);
if (!pOutputDev)
return 0;
for (int nIndex = 1; nIndex <= m_pInternal->m_pPDFDocument->GetPagesCount(); nIndex++)
{
m_pInternal->m_pPDFDocument->DisplayPage(pOutputDev, nIndex, 72, 72, 0, false, false, false);
}
return pOutputDev->GetImagesCount();
}
void CPdfReader::SetTempDirectory(const std::wstring& wsTempFolder)
{
if (!m_pInternal->m_wsTempFolder.empty())
{
NSDirectory::DeleteDirectory(m_pInternal->m_wsTempFolder);
m_pInternal->m_wsTempFolder = wsTempFolder;
}
if (!wsTempFolder.empty())
{
std::wstring wsFolderName = std::wstring(wsTempFolder) + L"//pdftemp";
std::wstring wsFolder = wsFolderName;
int nCounter = 0;
while (NSDirectory::Exists(wsFolder))
{
nCounter++;
wsFolder = wsFolderName + L"_" + std::to_wstring(nCounter);
}
NSDirectory::CreateDirectory(wsFolder);
m_pInternal->m_wsTempFolder = wsFolder;
}
else
m_pInternal->m_wsTempFolder = L"";
if (m_pInternal->m_pGlobalParams)
m_pInternal->m_pGlobalParams->SetTempFolder(m_pInternal->m_wsTempFolder.c_str());
}
std::wstring CPdfReader::GetTempDirectory()
{
return m_pInternal->m_wsTempFolder;
}
void CPdfReader::SetCMapFolder(const wchar_t* wsCMapFolder)
{
m_pInternal->m_wsCMapFolder = std::wstring(wsCMapFolder);
if (m_pInternal->m_pGlobalParams)
m_pInternal->m_pGlobalParams->SetCMapFolder(m_pInternal->m_wsCMapFolder.c_str());
}
CFontManager* CPdfReader::GetFontManager()
{
return m_pInternal->m_pFontManager;
}
}