#include "HGPdfImpl.hpp" #include "../base/HGInc.h" #include "../base/HGUtility.h" #include "../base/HGInfo.h" #include "HGString.h" #include #include HGPdfReaderImpl::HGPdfReaderImpl() { m_dll = NULL; m_pContext = NULL; m_pDoc = NULL; } HGPdfReaderImpl::~HGPdfReaderImpl() { } HGResult HGPdfReaderImpl::Open(const HGChar* fileName) { if (NULL != m_pDoc) { return HGBASE_ERR_FAIL; } if (NULL == fileName) { return HGBASE_ERR_INVALIDARG; } #if defined(HG_CMP_MSC) if (0 != _access(fileName, 0)) #else if (0 != access(fileName, 0)) #endif { return HGBASE_ERR_FILENOTEXIST; } 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); } else { return HGBASE_ERR_ACCESSDENIED; } if (!isPdfFile) { return HGBASE_ERR_FILEERROR; } assert(NULL == m_dll); HGChar moduleName[256]; HGBase_GetModuleName((void *)HGImgFmt_OpenPdfReader, moduleName, 256); HGChar dllPath[256]; HGBase_GetFilePath(moduleName, dllPath, 256); #if defined(HG_CMP_MSC) strcat(dllPath, "libmupdf.dll"); #else strcat(dllPath, "libmupdf.so"); #endif HGResult ret = HGBase_CreateDll(dllPath, &m_dll); if (HGBASE_ERR_OK != ret) { return ret; } fz_context* pContext = fz_new_context(NULL, NULL, FZ_STORE_DEFAULT); if (NULL == pContext) { HGBase_DestroyDll(m_dll); m_dll = NULL; return HGIMGFMT_ERR_FAIL; } ret = HGIMGFMT_ERR_FAIL; fz_try(pContext) { fz_register_document_handlers(pContext); fz_document* pDoc = fz_open_document(pContext, StdStringToUtf8(fileName).c_str()); m_pContext = pContext; m_pDoc = pDoc; ret = HGBASE_ERR_OK; } fz_catch(pContext) { fz_drop_context(pContext); pContext = NULL; HGBase_DestroyDll(m_dll); m_dll = NULL; } return ret; } HGResult HGPdfReaderImpl::Close() { if (NULL == m_pDoc) { return HGBASE_ERR_FAIL; } fz_drop_document(m_pContext, m_pDoc); m_pDoc = NULL; fz_drop_context(m_pContext); m_pContext = NULL; HGBase_DestroyDll(m_dll); m_dll = NULL; return HGBASE_ERR_OK; } HGResult HGPdfReaderImpl::GetPageCount(HGUInt* count) { if (NULL == m_pDoc) { return HGBASE_ERR_FAIL; } if (NULL == count) { return HGBASE_ERR_INVALIDARG; } HGResult ret = HGIMGFMT_ERR_FAIL; fz_try(m_pContext) { *count = (uint32_t)fz_count_pages(m_pContext, m_pDoc); ret = HGBASE_ERR_OK; } fz_catch(m_pContext) { } return ret; } HGResult HGPdfReaderImpl::GetPageInfo(HGUInt page, HGPdfPageInfo* info) { if (NULL == m_pDoc) { return HGBASE_ERR_FAIL; } if (NULL == info) { return HGBASE_ERR_INVALIDARG; } HGResult ret = HGIMGFMT_ERR_FAIL; fz_page* fzpage = NULL; fz_try(m_pContext) { fzpage = fz_load_page(m_pContext, m_pDoc, (int)page); pdf_page* page = pdf_page_from_fz_page(m_pContext, fzpage); if (NULL != page) { fz_rect pdfRect = pdf_bound_page(m_pContext, page); info->width = ceil(pdfRect.x1); info->height = ceil(pdfRect.y1); info->bpp = 24; ret = HGBASE_ERR_OK; } } fz_catch(m_pContext) { } if (NULL != fzpage) fz_drop_page(m_pContext, fzpage); return ret; } HGResult HGPdfReaderImpl::LoadImage(HGUInt page, HGFloat xScale, HGFloat yScale, HGUInt imgType, HGUInt imgOrigin, HGImage* image) { if (NULL == m_pDoc) { return HGBASE_ERR_FAIL; } if (0 != imgOrigin && HGBASE_IMGORIGIN_TOP != imgOrigin && HGBASE_IMGORIGIN_BOTTOM != imgOrigin) { return HGBASE_ERR_INVALIDARG; } if (NULL == image) { return HGBASE_ERR_INVALIDARG; } HGResult ret = HGIMGFMT_ERR_FAIL; fz_pixmap* pix = NULL; fz_try(m_pContext) { fz_matrix ctm = fz_scale(xScale, yScale); pix = fz_new_pixmap_from_page_number(m_pContext, m_pDoc, (int)page, ctm, fz_device_rgb(m_pContext), 0); int width = fz_pixmap_width(m_pContext, pix); int height = fz_pixmap_height(m_pContext, pix); if (0 == imgType) imgType = HGBASE_IMGTYPE_RGB; if (imgOrigin == 0) imgOrigin = HGBASE_IMGORIGIN_TOP; HGImage image2 = NULL; HGImageInfo imgInfo = { (uint32_t)width, (uint32_t)height, HGBASE_IMGTYPE_RGB, (uint32_t)pix->stride, HGBASE_IMGORIGIN_TOP }; if (HGBASE_ERR_OK == HGBase_CreateImageWithData(pix->samples, &imgInfo, &image2)) { HGBase_SetImageDpi(image2, (HGUInt)(xScale * 72 + 0.5f), (HGUInt)(yScale * 72 + 0.5f)); ret = HGBase_CloneImage(image2, imgType, imgOrigin, image); HGBase_DestroyImage(image2); } } fz_catch(m_pContext) { } if (NULL != pix) fz_drop_pixmap(m_pContext, pix); return ret; } fz_context* HGPdfReaderImpl::fz_new_context_imp(const fz_alloc_context* alloc, const fz_locks_context* locks, size_t max_store, const char* version) { typedef fz_context* (*Func)(const fz_alloc_context*, const fz_locks_context*, size_t, const char*); Func func = NULL; HGBase_GetDllProcAddress(m_dll, "fz_new_context_imp", (HGPointer*)&func); if (NULL == func) { return NULL; } return func(alloc, locks, max_store, version); } void HGPdfReaderImpl::fz_register_document_handlers(fz_context* ctx) { typedef void (*Func)(fz_context*); Func func = NULL; HGBase_GetDllProcAddress(m_dll, "fz_register_document_handlers", (HGPointer*)&func); if (NULL == func) { return; } func(ctx); } fz_document* HGPdfReaderImpl::fz_open_document(fz_context* ctx, const char* filename) { typedef fz_document* (*Func)(fz_context*, const char*); Func func = NULL; HGBase_GetDllProcAddress(m_dll, "fz_open_document", (HGPointer*)&func); if (NULL == func) { return NULL; } return func(ctx, filename); } void HGPdfReaderImpl::fz_drop_context(fz_context* ctx) { typedef void (*Func)(fz_context*); Func func = NULL; HGBase_GetDllProcAddress(m_dll, "fz_drop_context", (HGPointer*)&func); if (NULL == func) { return; } func(ctx); } void HGPdfReaderImpl::fz_drop_document(fz_context* ctx, fz_document* doc) { typedef void (*Func)(fz_context*, fz_document*); Func func = NULL; HGBase_GetDllProcAddress(m_dll, "fz_drop_document", (HGPointer*)&func); if (NULL == func) { return; } func(ctx, doc); } int HGPdfReaderImpl::fz_count_pages(fz_context* ctx, fz_document* doc) { typedef int (*Func)(fz_context*, fz_document*); Func func = NULL; HGBase_GetDllProcAddress(m_dll, "fz_count_pages", (HGPointer*)&func); if (NULL == func) { return -1; } return func(ctx, doc); } fz_page* HGPdfReaderImpl::fz_load_page(fz_context* ctx, fz_document* doc, int number) { typedef fz_page* (*Func)(fz_context*, fz_document* doc, int); Func func = NULL; HGBase_GetDllProcAddress(m_dll, "fz_load_page", (HGPointer*)&func); if (NULL == func) { return NULL; } return func(ctx, doc, number); } pdf_page* HGPdfReaderImpl::pdf_page_from_fz_page(fz_context* ctx, fz_page* ptr) { typedef pdf_page* (*Func)(fz_context*, fz_page*); Func func = NULL; HGBase_GetDllProcAddress(m_dll, "pdf_page_from_fz_page", (HGPointer*)&func); if (NULL == func) { return NULL; } return func(ctx, ptr); } fz_rect HGPdfReaderImpl::pdf_bound_page(fz_context* ctx, pdf_page* page) { typedef fz_rect (*Func)(fz_context*, pdf_page*); Func func = NULL; HGBase_GetDllProcAddress(m_dll, "pdf_bound_page", (HGPointer*)&func); if (NULL == func) { fz_rect rect = {0, 0, 0, 0}; return rect; } return func(ctx, page); } void HGPdfReaderImpl::fz_drop_page(fz_context* ctx, fz_page* page) { typedef void (*Func)(fz_context*, fz_page*); Func func = NULL; HGBase_GetDllProcAddress(m_dll, "fz_drop_page", (HGPointer*)&func); if (NULL == func) { return; } func(ctx, page); } fz_matrix HGPdfReaderImpl::fz_scale(float sx, float sy) { typedef fz_matrix (*Func)(float, float); Func func = NULL; HGBase_GetDllProcAddress(m_dll, "fz_scale", (HGPointer*)&func); if (NULL == func) { fz_matrix matrix = { 0, 0, 0, 0, 0, 0 }; return matrix; } return func(sx, sy); } fz_pixmap* HGPdfReaderImpl::fz_new_pixmap_from_page_number(fz_context* ctx, fz_document* doc, int number, fz_matrix ctm, fz_colorspace* cs, int alpha) { typedef fz_pixmap* (*Func)(fz_context*, fz_document*, int, fz_matrix, fz_colorspace*, int); Func func = NULL; HGBase_GetDllProcAddress(m_dll, "fz_new_pixmap_from_page_number", (HGPointer*)&func); if (NULL == func) { return NULL; } return func(ctx, doc, number, ctm, cs, alpha); } fz_colorspace* HGPdfReaderImpl::fz_device_rgb(fz_context* ctx) { typedef fz_colorspace* (*Func)(fz_context*); Func func = NULL; HGBase_GetDllProcAddress(m_dll, "fz_device_rgb", (HGPointer*)&func); if (NULL == func) { return NULL; } return func(ctx); } int HGPdfReaderImpl::fz_pixmap_width(fz_context* ctx, const fz_pixmap* pix) { typedef int (*Func)(fz_context*, const fz_pixmap*); Func func = NULL; HGBase_GetDllProcAddress(m_dll, "fz_pixmap_width", (HGPointer*)&func); if (NULL == func) { return -1; } return func(ctx, pix); } int HGPdfReaderImpl::fz_pixmap_height(fz_context* ctx, const fz_pixmap* pix) { typedef int (*Func)(fz_context*, const fz_pixmap*); Func func = NULL; HGBase_GetDllProcAddress(m_dll, "fz_pixmap_height", (HGPointer*)&func); if (NULL == func) { return -1; } return func(ctx, pix); } void HGPdfReaderImpl::fz_drop_pixmap(fz_context* ctx, fz_pixmap* pix) { typedef void (*Func)(fz_context*, fz_pixmap*); Func func = NULL; HGBase_GetDllProcAddress(m_dll, "fz_drop_pixmap", (HGPointer*)&func); if (NULL == func) { return; } func(ctx, pix); } fz_jmp_buf* HGPdfReaderImpl::fz_push_try(fz_context* ctx) { typedef fz_jmp_buf* (*Func)(fz_context*); Func func = NULL; HGBase_GetDllProcAddress(m_dll, "fz_push_try", (HGPointer*)&func); if (NULL == func) { return NULL; } return func(ctx); } int HGPdfReaderImpl::fz_do_try(fz_context* ctx) { typedef int (*Func)(fz_context*); Func func = NULL; HGBase_GetDllProcAddress(m_dll, "fz_do_try", (HGPointer*)&func); if (NULL == func) { return -1; } return func(ctx); } int HGPdfReaderImpl::fz_do_catch(fz_context* ctx) { typedef int (*Func)(fz_context*); Func func = NULL; HGBase_GetDllProcAddress(m_dll, "fz_do_catch", (HGPointer*)&func); if (NULL == func) { return -1; } return func(ctx); } #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 HGPdfImageWriterImpl::HGPdfImageWriterImpl() { m_dll = NULL; m_pPdf = NULL; } HGPdfImageWriterImpl::~HGPdfImageWriterImpl() { } HGResult HGPdfImageWriterImpl::Open(const HGChar* fileName) { if (NULL != m_pPdf) { return HGBASE_ERR_FAIL; } if (NULL == fileName) { return HGBASE_ERR_INVALIDARG; } assert(NULL == m_dll); HGChar moduleName[256]; HGBase_GetModuleName((void*)HGImgFmt_OpenPdfImageWriter, moduleName, 256); HGChar dllPath[256]; HGBase_GetFilePath(moduleName, dllPath, 256); #if defined(HG_CMP_MSC) strcat(dllPath, "pdflib.dll"); #else strcat(dllPath, "libpdf.so"); #endif HGResult ret = HGBase_CreateDll(dllPath, &m_dll); if (HGBASE_ERR_OK != ret) { return ret; } PDF* p = PDF_new(); if (NULL == p) { HGBase_DestroyDll(m_dll); m_dll = NULL; return HGIMGFMT_ERR_FAIL; } #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 { HGBase_WriteInfo(HGBASE_INFOTYPE_ERROR, "HGPdfImageWriterImpl::Open: PDF_begin_document fail, %s", fileName); delete[] pUnicode; PDF_delete(p); HGBase_DestroyDll(m_dll); m_dll = NULL; return HGBASE_ERR_ACCESSDENIED; } } PDF_CATCH(p) { delete[] pUnicode; PDF_delete(p); HGBase_DestroyDll(m_dll); m_dll = NULL; return HGIMGFMT_ERR_FAIL; } delete[] pUnicode; m_pPdf = p; return HGBASE_ERR_OK; } HGResult HGPdfImageWriterImpl::Close() { if (NULL == m_pPdf) { return HGBASE_ERR_FAIL; } PDF_TRY(m_pPdf) { PDF_end_document(m_pPdf, ""); } PDF_CATCH(m_pPdf) { } PDF_delete(m_pPdf); m_pPdf = NULL; HGBase_DestroyDll(m_dll); m_dll = NULL; return HGBASE_ERR_OK; } HGResult HGPdfImageWriterImpl::SaveJpegImage(HGImage image, const HGJpegSaveInfo* info) { if (NULL == m_pPdf) { return HGBASE_ERR_FAIL; } if (NULL == image) { return HGBASE_ERR_INVALIDARG; } HGBuffer buffer = NULL; HGResult ret = HGImgFmt_SaveJpegImageToBuffer(image, info, &buffer); if (HGBASE_ERR_OK != ret) { return ret; } HGByte* imgBuf = NULL; HGBase_GetBufferData(buffer, &imgBuf); HGUSize size = 0; HGBase_GetBufferSize(buffer, &size); PDF_TRY(m_pPdf) { PDF_create_pvf(m_pPdf, "virtual_file", 0, imgBuf, size, ""); } PDF_CATCH(m_pPdf) { HGBase_DestroyBuffer(buffer); return HGIMGFMT_ERR_FAIL; } int img = PDF_load_image(m_pPdf, "auto", "virtual_file", 0, "page 1"); if (-1 != img) { PDF_begin_page_ext(m_pPdf, 0.0, 0.0, ""); PDF_fit_image(m_pPdf, img, 0.0, 0.0, "adjustpage"); PDF_end_page_ext(m_pPdf, ""); PDF_close_image(m_pPdf, img); } PDF_delete_pvf(m_pPdf, "virtual_file", 0); HGBase_DestroyBuffer(buffer); return HGBASE_ERR_OK; } PDF* HGPdfImageWriterImpl::PDF_new(void) { typedef PDF* (PDFLIB_CALL *Func)(); Func func = NULL; HGBase_GetDllProcAddress(m_dll, "PDF_new", (HGPointer*)&func); if (NULL == func) { return NULL; } return func(); } void HGPdfImageWriterImpl::PDF_set_parameter(PDF* p, const char* key, const char* value) { typedef void (PDFLIB_CALL* Func)(PDF*, const char*, const char*); Func func = NULL; HGBase_GetDllProcAddress(m_dll, "PDF_set_parameter", (HGPointer*)&func); if (NULL == func) { return; } func(p, key, value); } int HGPdfImageWriterImpl::PDF_begin_document(PDF* p, const char* filename, int len, const char* optlist) { typedef int (PDFLIB_CALL* Func)(PDF*, const char*, int, const char*); Func func = NULL; HGBase_GetDllProcAddress(m_dll, "PDF_begin_document", (HGPointer*)&func); if (NULL == func) { return -1; } return func(p, filename, len, optlist); } void HGPdfImageWriterImpl::PDF_delete(PDF* p) { typedef void (PDFLIB_CALL* Func)(PDF*); Func func = NULL; HGBase_GetDllProcAddress(m_dll, "PDF_delete", (HGPointer*)&func); if (NULL == func) { return; } func(p); } void HGPdfImageWriterImpl::PDF_end_document(PDF* p, const char* optlist) { typedef void (PDFLIB_CALL* Func)(PDF*, const char*); Func func = NULL; HGBase_GetDllProcAddress(m_dll, "PDF_end_document", (HGPointer*)&func); if (NULL == func) { return; } func(p, optlist); } void HGPdfImageWriterImpl::PDF_create_pvf(PDF* p, const char* filename, int len, const void* data, size_t size, const char* optlist) { typedef void (PDFLIB_CALL* Func)(PDF*, const char*, int, const void*, size_t, const char*); Func func = NULL; HGBase_GetDllProcAddress(m_dll, "PDF_create_pvf", (HGPointer*)&func); if (NULL == func) { return; } func(p, filename, len, data, size, optlist); } int HGPdfImageWriterImpl::PDF_load_image(PDF* p, const char* imagetype, const char* filename, int len, const char* optlist) { typedef int (PDFLIB_CALL* Func)(PDF*, const char*, const char*, int, const char*); Func func = NULL; HGBase_GetDllProcAddress(m_dll, "PDF_load_image", (HGPointer*)&func); if (NULL == func) { return -1; } return func(p, imagetype, filename, len, optlist); } void HGPdfImageWriterImpl::PDF_begin_page_ext(PDF* p, double width, double height, const char* optlist) { typedef void (PDFLIB_CALL* Func)(PDF*, double, double, const char*); Func func = NULL; HGBase_GetDllProcAddress(m_dll, "PDF_begin_page_ext", (HGPointer*)&func); if (NULL == func) { return; } func(p, width, height, optlist); } void HGPdfImageWriterImpl::PDF_fit_image(PDF* p, int image, double x, double y, const char* optlist) { typedef void (PDFLIB_CALL* Func)(PDF*, int, double, double, const char*); Func func = NULL; HGBase_GetDllProcAddress(m_dll, "PDF_fit_image", (HGPointer*)&func); if (NULL == func) { return; } func(p, image, x, y, optlist); } void HGPdfImageWriterImpl::PDF_end_page_ext(PDF* p, const char* optlist) { typedef void (PDFLIB_CALL* Func)(PDF*, const char*); Func func = NULL; HGBase_GetDllProcAddress(m_dll, "PDF_end_page_ext", (HGPointer*)&func); if (NULL == func) { return; } func(p, optlist); } void HGPdfImageWriterImpl::PDF_close_image(PDF* p, int image) { typedef void (PDFLIB_CALL* Func)(PDF*, int); Func func = NULL; HGBase_GetDllProcAddress(m_dll, "PDF_close_image", (HGPointer*)&func); if (NULL == func) { return; } func(p, image); } int HGPdfImageWriterImpl::PDF_delete_pvf(PDF* p, const char* filename, int len) { typedef int (PDFLIB_CALL* Func)(PDF*, const char*, int); Func func = NULL; HGBase_GetDllProcAddress(m_dll, "PDF_delete_pvf", (HGPointer*)&func); if (NULL == func) { return -1; } return func(p, filename, len); } pdf_jmpbuf* HGPdfImageWriterImpl::pdf_jbuf(PDF* p) { typedef pdf_jmpbuf* (PDFLIB_CALL* Func)(PDF*); Func func = NULL; HGBase_GetDllProcAddress(m_dll, "pdf_jbuf", (HGPointer*)&func); if (NULL == func) { return NULL; } return func(p); } int HGPdfImageWriterImpl::pdf_catch(PDF* p) { typedef int (PDFLIB_CALL* Func)(PDF*); Func func = NULL; HGBase_GetDllProcAddress(m_dll, "pdf_catch", (HGPointer*)&func); if (NULL == func) { return -1; } return func(p); }