402 lines
8.4 KiB
C++
402 lines
8.4 KiB
C++
|
#include "HGPdf.h"
|
|||
|
#include "../base/HGInc.h"
|
|||
|
#include "mupdf/pdf.h"
|
|||
|
#include "mupdf/fitz.h"
|
|||
|
#include "pdflib.h"
|
|||
|
#include "../utility/HGString.h"
|
|||
|
#include <string>
|
|||
|
|
|||
|
struct HGPdfReaderImpl
|
|||
|
{
|
|||
|
HGPdfReaderImpl()
|
|||
|
{
|
|||
|
m_pContext = NULL;
|
|||
|
m_pDoc = NULL;
|
|||
|
}
|
|||
|
|
|||
|
~HGPdfReaderImpl()
|
|||
|
{
|
|||
|
if (NULL != m_pDoc)
|
|||
|
{
|
|||
|
fz_drop_document(m_pContext, m_pDoc);
|
|||
|
m_pDoc = NULL;
|
|||
|
}
|
|||
|
|
|||
|
if (NULL != m_pContext)
|
|||
|
{
|
|||
|
fz_drop_context(m_pContext);
|
|||
|
m_pContext = NULL;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
fz_context* m_pContext;
|
|||
|
fz_document *m_pDoc;
|
|||
|
};
|
|||
|
|
|||
|
struct HGPdfImageWriterImpl
|
|||
|
{
|
|||
|
HGPdfImageWriterImpl()
|
|||
|
{
|
|||
|
m_pPdf = NULL;
|
|||
|
}
|
|||
|
|
|||
|
~HGPdfImageWriterImpl()
|
|||
|
{
|
|||
|
if (NULL != m_pPdf)
|
|||
|
{
|
|||
|
PDF_TRY(m_pPdf)
|
|||
|
{
|
|||
|
PDF_end_document(m_pPdf, "");
|
|||
|
}
|
|||
|
PDF_CATCH(m_pPdf)
|
|||
|
{
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
PDF_delete(m_pPdf);
|
|||
|
m_pPdf = NULL;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
PDF* m_pPdf;
|
|||
|
};
|
|||
|
|
|||
|
#if defined(HG_CMP_MSC)
|
|||
|
static WCHAR* GetUnicodeStr(const char* text)
|
|||
|
{
|
|||
|
int len = ::MultiByteToWideChar(CP_ACP, 0, text, -1, NULL, 0);
|
|||
|
WCHAR* pUnicode = new WCHAR[len];
|
|||
|
::MultiByteToWideChar(CP_ACP, 0, text, -1, pUnicode, len);
|
|||
|
return pUnicode;
|
|||
|
}
|
|||
|
static uint32_t GetUnicodeStrLen(const WCHAR* pUnicode)
|
|||
|
{
|
|||
|
return (uint32_t)wcslen(pUnicode);
|
|||
|
}
|
|||
|
#else
|
|||
|
static uint16_t* GetUnicodeStr(const char* text)
|
|||
|
{
|
|||
|
if (0 == *text)
|
|||
|
{
|
|||
|
uint16_t* pUnicode = new uint16_t[1];
|
|||
|
*pUnicode = 0;
|
|||
|
return pUnicode;
|
|||
|
}
|
|||
|
|
|||
|
uint16_t* pUnicode = new uint16_t[strlen(text) + 2];
|
|||
|
memset(pUnicode, 0, sizeof(uint16_t) * (strlen(text) + 2));
|
|||
|
|
|||
|
iconv_t cd = iconv_open("UNICODE//IGNORE", "UTF-8");
|
|||
|
if ((iconv_t)-1 != cd)
|
|||
|
{
|
|||
|
char* inbuf = (char*)text;
|
|||
|
size_t inbytes = strlen(text);
|
|||
|
char* outbuf = (char*)pUnicode;
|
|||
|
size_t outsize = sizeof(uint16_t) * (strlen(text) + 1);
|
|||
|
|
|||
|
iconv(cd, &inbuf, &inbytes, &outbuf, &outsize);
|
|||
|
iconv_close(cd);
|
|||
|
}
|
|||
|
|
|||
|
return pUnicode;
|
|||
|
}
|
|||
|
static uint32_t GetUnicodeStrLen(const uint16_t* pUnicode)
|
|||
|
{
|
|||
|
uint32_t i = 0;
|
|||
|
while (0 != pUnicode[i])
|
|||
|
{
|
|||
|
++i;
|
|||
|
}
|
|||
|
|
|||
|
return i;
|
|||
|
}
|
|||
|
#endif
|
|||
|
|
|||
|
HGResult HGAPI HGImgFmt_CheckPdfFile(const HGChar* fileName, HGBool* isPdf)
|
|||
|
{
|
|||
|
if (NULL == fileName || NULL == isPdf)
|
|||
|
{
|
|||
|
return HGBASE_ERR_INVALIDARG;
|
|||
|
}
|
|||
|
|
|||
|
*isPdf = HGFALSE;
|
|||
|
HGPdfReader reader = NULL;
|
|||
|
HGImgFmt_OpenPdfReader(fileName, &reader);
|
|||
|
if (NULL != reader)
|
|||
|
{
|
|||
|
*isPdf = HGTRUE;
|
|||
|
HGImgFmt_ClosePdfReader(reader);
|
|||
|
}
|
|||
|
return HGBASE_ERR_OK;
|
|||
|
}
|
|||
|
|
|||
|
HGResult HGAPI HGImgFmt_OpenPdfReader(const HGChar* fileName, HGPdfReader* reader)
|
|||
|
{
|
|||
|
if (NULL == fileName || NULL == reader)
|
|||
|
{
|
|||
|
return HGBASE_ERR_INVALIDARG;
|
|||
|
}
|
|||
|
|
|||
|
HGBool isPdfFile = HGFALSE;
|
|||
|
FILE* file = fopen(fileName, "r");
|
|||
|
if (NULL != file)
|
|||
|
{
|
|||
|
HGByte data[4];
|
|||
|
size_t len = fread(data, 1, 4, file);
|
|||
|
if (4 == len && 0 == memcmp(data, "%PDF", 4))
|
|||
|
{
|
|||
|
isPdfFile = HGTRUE;
|
|||
|
}
|
|||
|
|
|||
|
fclose(file);
|
|||
|
}
|
|||
|
|
|||
|
if (!isPdfFile)
|
|||
|
{
|
|||
|
return HGBASE_ERR_FAIL;
|
|||
|
}
|
|||
|
|
|||
|
fz_context* pContext = fz_new_context(NULL, NULL, FZ_STORE_DEFAULT);
|
|||
|
if (NULL == pContext)
|
|||
|
{
|
|||
|
return HGBASE_ERR_FAIL;
|
|||
|
}
|
|||
|
|
|||
|
HGResult ret = HGBASE_ERR_FAIL;
|
|||
|
fz_try(pContext)
|
|||
|
{
|
|||
|
fz_register_document_handlers(pContext);
|
|||
|
fz_document* pDoc = fz_open_document(pContext, StdStringToUtf8(fileName).c_str());
|
|||
|
|
|||
|
HGPdfReaderImpl* pdfReaderImpl = new HGPdfReaderImpl;
|
|||
|
pdfReaderImpl->m_pContext = pContext;
|
|||
|
pdfReaderImpl->m_pDoc = pDoc;
|
|||
|
*reader = (HGPdfReader)pdfReaderImpl;
|
|||
|
ret = HGBASE_ERR_OK;
|
|||
|
}
|
|||
|
fz_catch(pContext)
|
|||
|
{
|
|||
|
fz_drop_context(pContext);
|
|||
|
pContext = NULL;
|
|||
|
}
|
|||
|
|
|||
|
return ret;
|
|||
|
}
|
|||
|
|
|||
|
HGResult HGAPI HGImgFmt_ClosePdfReader(HGPdfReader reader)
|
|||
|
{
|
|||
|
if (NULL == reader)
|
|||
|
{
|
|||
|
return HGBASE_ERR_INVALIDARG;
|
|||
|
}
|
|||
|
|
|||
|
HGPdfReaderImpl* pdfReaderImpl = (HGPdfReaderImpl*)reader;
|
|||
|
delete pdfReaderImpl;
|
|||
|
return HGBASE_ERR_OK;
|
|||
|
}
|
|||
|
|
|||
|
HGResult HGAPI HGImgFmt_GetPdfPageCount(HGPdfReader reader, HGUInt* count)
|
|||
|
{
|
|||
|
if (NULL == reader || NULL == count)
|
|||
|
{
|
|||
|
return HGBASE_ERR_INVALIDARG;
|
|||
|
}
|
|||
|
|
|||
|
HGPdfReaderImpl* pdfReaderImpl = (HGPdfReaderImpl*)reader;
|
|||
|
|
|||
|
HGResult ret = HGBASE_ERR_FAIL;
|
|||
|
fz_try(pdfReaderImpl->m_pContext)
|
|||
|
{
|
|||
|
*count = (uint32_t)fz_count_pages(pdfReaderImpl->m_pContext, pdfReaderImpl->m_pDoc);
|
|||
|
ret = HGBASE_ERR_OK;
|
|||
|
}
|
|||
|
fz_catch(pdfReaderImpl->m_pContext)
|
|||
|
{
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
return ret;
|
|||
|
}
|
|||
|
|
|||
|
HGResult HGAPI HGImgFmt_GetPdfPageInfo(HGPdfReader reader, HGUInt page, HGPdfPageInfo* info)
|
|||
|
{
|
|||
|
if (NULL == reader || NULL == info)
|
|||
|
{
|
|||
|
return HGBASE_ERR_INVALIDARG;
|
|||
|
}
|
|||
|
|
|||
|
HGPdfReaderImpl* pdfReaderImpl = (HGPdfReaderImpl*)reader;
|
|||
|
|
|||
|
HGResult ret = HGBASE_ERR_FAIL;
|
|||
|
fz_page* fzpage = NULL;
|
|||
|
|
|||
|
fz_try(pdfReaderImpl->m_pContext)
|
|||
|
{
|
|||
|
fzpage = fz_load_page(pdfReaderImpl->m_pContext, pdfReaderImpl->m_pDoc, (int)page);
|
|||
|
pdf_page* page = pdf_page_from_fz_page(pdfReaderImpl->m_pContext, fzpage);
|
|||
|
if (NULL != page)
|
|||
|
{
|
|||
|
fz_rect pdfRect = pdf_bound_page(pdfReaderImpl->m_pContext, page);
|
|||
|
info->width = ceil(pdfRect.x1);
|
|||
|
info->height = ceil(pdfRect.y1);
|
|||
|
ret = HGBASE_ERR_OK;
|
|||
|
}
|
|||
|
}
|
|||
|
fz_catch(pdfReaderImpl->m_pContext)
|
|||
|
{
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
if (NULL != fzpage)
|
|||
|
fz_drop_page(pdfReaderImpl->m_pContext, fzpage);
|
|||
|
return ret;
|
|||
|
}
|
|||
|
|
|||
|
HGResult HGAPI HGImgFmt_LoadImageFromPdfReader(HGPdfReader reader, HGUInt page, HGFloat xScale, HGFloat yScale,
|
|||
|
HGUInt imgType, HGUInt imgOrigin, HGImage* image)
|
|||
|
{
|
|||
|
if (NULL == reader || NULL == image)
|
|||
|
{
|
|||
|
return HGBASE_ERR_INVALIDARG;
|
|||
|
}
|
|||
|
|
|||
|
HGPdfReaderImpl* pdfReaderImpl = (HGPdfReaderImpl*)reader;
|
|||
|
|
|||
|
HGResult ret = HGBASE_ERR_FAIL;
|
|||
|
fz_pixmap* pix = NULL;
|
|||
|
|
|||
|
fz_try(pdfReaderImpl->m_pContext)
|
|||
|
{
|
|||
|
fz_matrix ctm = fz_scale(xScale, yScale);
|
|||
|
pix = fz_new_pixmap_from_page_number(pdfReaderImpl->m_pContext, pdfReaderImpl->m_pDoc, (int)page,
|
|||
|
ctm, fz_device_rgb(pdfReaderImpl->m_pContext), 0);
|
|||
|
|
|||
|
int width = fz_pixmap_width(pdfReaderImpl->m_pContext, pix);
|
|||
|
int height = fz_pixmap_height(pdfReaderImpl->m_pContext, pix);
|
|||
|
|
|||
|
*image = NULL;
|
|||
|
HGImageInfo imgInfo = { (uint32_t)width, (uint32_t)height, HGBASE_IMGTYPE_RGB, (uint32_t)pix->stride, HGBASE_IMGORIGIN_TOP };
|
|||
|
HGBase_CreateImageFromData(pix->samples, &imgInfo, NULL, imgType, imgOrigin, image);
|
|||
|
if (NULL != *image)
|
|||
|
{
|
|||
|
ret = HGBASE_ERR_OK;
|
|||
|
}
|
|||
|
}
|
|||
|
fz_catch(pdfReaderImpl->m_pContext)
|
|||
|
{
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
if (NULL != pix)
|
|||
|
fz_drop_pixmap(pdfReaderImpl->m_pContext, pix);
|
|||
|
return ret;
|
|||
|
}
|
|||
|
|
|||
|
HGResult HGAPI HGImgFmt_OpenPdfImageWriter(const HGChar* fileName, HGPdfImageWriter* writer)
|
|||
|
{
|
|||
|
if (NULL == fileName || NULL == writer)
|
|||
|
{
|
|||
|
return HGBASE_ERR_INVALIDARG;
|
|||
|
}
|
|||
|
|
|||
|
PDF* p = PDF_new();
|
|||
|
if (NULL == p)
|
|||
|
{
|
|||
|
return HGBASE_ERR_OUTOFMEMORY;
|
|||
|
}
|
|||
|
|
|||
|
#if defined(HG_CMP_MSC)
|
|||
|
WCHAR* pUnicode = GetUnicodeStr(fileName);
|
|||
|
#else
|
|||
|
uint16_t* pUnicode = GetUnicodeStr(fileName);
|
|||
|
#endif
|
|||
|
|
|||
|
PDF_TRY(p)
|
|||
|
{
|
|||
|
PDF_set_parameter(p, "compatibility", "1.4");
|
|||
|
PDF_set_parameter(p, "errorpolicy", "return");
|
|||
|
PDF_set_parameter(p, "hypertextencoding", "host");
|
|||
|
|
|||
|
#if defined(HG_CMP_MSC)
|
|||
|
if (-1 == PDF_begin_document(p, (const char*)pUnicode, (int)(GetUnicodeStrLen(pUnicode) * sizeof(WCHAR)), ""))
|
|||
|
#else
|
|||
|
if (-1 == PDF_begin_document(p, (const char*)pUnicode, (int)(GetUnicodeStrLen(pUnicode) * sizeof(uint16_t)), ""))
|
|||
|
#endif
|
|||
|
{
|
|||
|
delete[] pUnicode;
|
|||
|
PDF_delete(p);
|
|||
|
return HGBASE_ERR_FAIL;
|
|||
|
}
|
|||
|
}
|
|||
|
PDF_CATCH(p)
|
|||
|
{
|
|||
|
delete[] pUnicode;
|
|||
|
PDF_delete(p);
|
|||
|
return HGBASE_ERR_FAIL;
|
|||
|
}
|
|||
|
|
|||
|
delete[] pUnicode;
|
|||
|
|
|||
|
HGPdfImageWriterImpl* pdfImageWriterImpl = new HGPdfImageWriterImpl;
|
|||
|
pdfImageWriterImpl->m_pPdf = p;
|
|||
|
*writer = (HGPdfImageWriter)pdfImageWriterImpl;
|
|||
|
return HGBASE_ERR_OK;
|
|||
|
}
|
|||
|
|
|||
|
HGResult HGAPI HGImgFmt_ClosePdfImageWriter(HGPdfImageWriter writer)
|
|||
|
{
|
|||
|
if (NULL == writer)
|
|||
|
{
|
|||
|
return HGBASE_ERR_INVALIDARG;
|
|||
|
}
|
|||
|
|
|||
|
HGPdfImageWriterImpl* pdfImageWriterImpl = (HGPdfImageWriterImpl*)writer;
|
|||
|
delete pdfImageWriterImpl;
|
|||
|
return HGBASE_ERR_OK;
|
|||
|
}
|
|||
|
|
|||
|
HGResult HGAPI HGImgFmt_SaveJpegImageToPdfImageWriter(HGPdfImageWriter writer, HGImage image, const HGJpegSaveInfo* info, HGUInt quality)
|
|||
|
{
|
|||
|
if (NULL == writer || NULL == image)
|
|||
|
{
|
|||
|
return HGBASE_ERR_INVALIDARG;
|
|||
|
}
|
|||
|
|
|||
|
HGBuffer buffer = NULL;
|
|||
|
HGResult ret = HGImgFmt_SaveJpegImageToBuffer(image, info, quality, &buffer);
|
|||
|
if (HGBASE_ERR_OK != ret)
|
|||
|
{
|
|||
|
return ret;
|
|||
|
}
|
|||
|
|
|||
|
HGByte* imgBuf = NULL;
|
|||
|
HGBase_GetBufferData(buffer, &imgBuf);
|
|||
|
HGUSize size = 0;
|
|||
|
HGBase_GetBufferSize(buffer, &size);
|
|||
|
|
|||
|
HGPdfImageWriterImpl* pdfImageWriterImpl = (HGPdfImageWriterImpl*)writer;
|
|||
|
|
|||
|
PDF_TRY(pdfImageWriterImpl->m_pPdf)
|
|||
|
{
|
|||
|
PDF_create_pvf(pdfImageWriterImpl->m_pPdf, "virtual_file", 0, imgBuf, size, "");
|
|||
|
}
|
|||
|
PDF_CATCH(pdfImageWriterImpl->m_pPdf)
|
|||
|
{
|
|||
|
return HGBASE_ERR_OUTOFMEMORY;
|
|||
|
}
|
|||
|
|
|||
|
int img = PDF_load_image(pdfImageWriterImpl->m_pPdf, "auto", "virtual_file", 0, "page 1");
|
|||
|
if (-1 != img)
|
|||
|
{
|
|||
|
PDF_begin_page_ext(pdfImageWriterImpl->m_pPdf, 0.0, 0.0, "");
|
|||
|
PDF_fit_image(pdfImageWriterImpl->m_pPdf, img, 0.0, 0.0, "adjustpage");
|
|||
|
PDF_end_page_ext(pdfImageWriterImpl->m_pPdf, "");
|
|||
|
PDF_close_image(pdfImageWriterImpl->m_pPdf, img);
|
|||
|
}
|
|||
|
|
|||
|
PDF_delete_pvf(pdfImageWriterImpl->m_pPdf, "virtual_file", 0);
|
|||
|
|
|||
|
HGBase_DestroyBuffer(buffer);
|
|||
|
return HGBASE_ERR_OK;
|
|||
|
}
|