Qt显示PDF之四pdfium封装

如果你已经按照前面的步骤成功生成了库,那么恭喜你。如果没有也不要气馁 ,我后面会放送编译好的库。

我们可以看一下pdfium的pdfium\build\Debug\lib目录和pdfium\build\Debug\,可以看到其实就一个dll文件和一堆lib。如果使用呢

可以参考pdfium\samples目录下的例子程序。下面我对其进行封装:

首先建立一个win32 dll工程PDFIumReader并引入pdfium头文件和lib目录

并在dllmain函数进行初始化

B#include "stdafx.h"
#include "fpdf_ext.h"
#include "vld.h"
#include "v8.h"
#include
#include

void Unsupported_Handler(UNSUPPORT_INFO*, int type) {
    std::string feature = "Unknown";
    switch (type) {
    case FPDF_UNSP_DOC_XFAFORM:
        feature = "XFA";
        break;
    case FPDF_UNSP_DOC_PORTABLECOLLECTION:
        feature = "Portfolios_Packages";
        break;
    case FPDF_UNSP_DOC_ATTACHMENT:
    case FPDF_UNSP_ANNOT_ATTACHMENT:
        feature = "Attachment";
        break;
    case FPDF_UNSP_DOC_SECURITY:
        feature = "Rights_Management";
        break;
    case FPDF_UNSP_DOC_SHAREDREVIEW:
        feature = "Shared_Review";
        break;
    case FPDF_UNSP_DOC_SHAREDFORM_ACROBAT:
    case FPDF_UNSP_DOC_SHAREDFORM_FILESYSTEM:
    case FPDF_UNSP_DOC_SHAREDFORM_EMAIL:
        feature = "Shared_Form";
        break;
    case FPDF_UNSP_ANNOT_3DANNOT:
        feature = "3D";
        break;
    case FPDF_UNSP_ANNOT_MOVIE:
        feature = "Movie";
        break;
    case FPDF_UNSP_ANNOT_SOUND:
        feature = "Sound";
        break;
    case FPDF_UNSP_ANNOT_SCREEN_MEDIA:
    case FPDF_UNSP_ANNOT_SCREEN_RICHMEDIA:
        feature = "Screen";
        break;
    case FPDF_UNSP_ANNOT_SIG:
        feature = "Digital_Signature";
        break;
    }
    printf("Unsupported feature: %s.\n", feature.c_str());
}


BOOL APIENTRY DllMain( HMODULE hModule,
                       DWORD  ul_reason_for_call,
                       LPVOID lpReserved
                     )
{
    switch (ul_reason_for_call)
    {
    case DLL_PROCESS_ATTACH:
    {
        v8::V8::InitializeICU();
        FPDF_InitLibrary(NULL);
        UNSUPPORT_INFO unsuppored_info;
        memset(&unsuppored_info, '\0', sizeof(unsuppored_info));
        unsuppored_info.version = 1;
        unsuppored_info.FSDK_UnSupport_Handler = Unsupported_Handler;
        FSDK_SetUnSpObjProcessHandler(&unsuppored_info);
    }
        break;
    case DLL_THREAD_ATTACH:
        break;
    case DLL_THREAD_DETACH:
        break;
    case DLL_PROCESS_DETACH:
        FPDF_DestroyLibrary();
        break;
    }
    return TRUE;
}


然后新建一个类PDFIumReaderMgr用于管理多个pdf

头文件:

   PDFIumReaderMgr

#pragma once
#include
#include


class PDFIumReader;

typedef std::map PDFReaders;

class PDFIumReaderMgr
{
public:
    static PDFIumReaderMgr *Instance();
    bool LoadPDF(const char *name);
    void Closepdf(const char *name);
    char *LoadPage(const char* filename, int page, float& width, float& height,  bool OutBmp);
    int  GetPageCount(const char* filename);
    char* GetNextPage(const char* filename, int &page, float& width, float& height, bool OutBmp);
    void SetCurrentPage(const char* filename, int page);

private:
    PDFIumReaderMgr(){}
    ~PDFIumReaderMgr(){}

public:
    PDFReaders m_pdfReaders;

};


   ------------------------------------------------------------------------------------PDFIumReaderMgr.cpp-----------------------------------------------------------------------------------------------

#include "stdafx.h"
#include "PDFReaderMgr.h"
#include "PDFIumReader.h"
#include
using namespace std;

PDFIumReaderMgr * PDFIumReaderMgr::Instance()
{
    static PDFIumReaderMgr mgr;
    return &mgr;
}

bool PDFIumReaderMgr::LoadPDF(const char *name)
{
    if (m_pdfReaders.find(name) != m_pdfReaders.end())
    {
        std::cout << "this file has loaded" << endl;
        return true;
    }
    PDFIumReader *reader = new PDFIumReader();
    m_pdfReaders[name] = reader;
    return reader->Reader(name);
}

void PDFIumReaderMgr::Closepdf(const char *name)
{
    if (m_pdfReaders.find(name) == m_pdfReaders.end())
        return;
    m_pdfReaders.find(name)->second->Close();
    m_pdfReaders.erase(name);
}

char * PDFIumReaderMgr::LoadPage(const char* filename, int page, float& width, float& height, bool OutBmp)
{
    if (m_pdfReaders.find(filename) == m_pdfReaders.end())
        return 0;
    return m_pdfReaders.find(filename)->second->GetPdfPage(page, width, height, OutBmp);
}

int PDFIumReaderMgr::GetPageCount(const char* filename)
{
    if (m_pdfReaders.find(filename) == m_pdfReaders.end())
        return 0;
    return m_pdfReaders.find(filename)->second->GetPageCount();
}


char* PDFIumReaderMgr::GetNextPage(const char* filename, int &page, float& width, float& height, bool OutBmp)
{
    if (m_pdfReaders.find(filename) == m_pdfReaders.end())
        return 0;
    return m_pdfReaders.find(filename)->second->GetNextPage(page, width, height, OutBmp);
}

void PDFIumReaderMgr::SetCurrentPage(const char* filename, int page)
{
    if (m_pdfReaders.find(filename) == m_pdfReaders.end())
        return ;
    m_pdfReaders.find(filename)->second->SetCurrentPage(page);
}

最后创建一个真正读取pdf的类PDFIumReader

-------------------------------------------------------------------------PDFIumReader.h-----------------------------------------------------------------------------------------

#pragma once
#include "fpdf_dataavail.h"
#include "fpdfview.h"
#include "fpdfformfill.h"
#include "fpdf_dataavail.h"
#include "fpdfedit.h"
#include "fpdftext.h"
#include "fpdfview.h"
#include
#include
#include
#include
#include
#include
#include
#include

enum ResultType
{
    PDF_DATA_ERROR = 0,
    PDF_DATA_NO_ERROR = 1,
    PDF_DATA_NO_DATA = 2
};

enum Output_Type
{
    OUTPUT_STR,
    OUTPUT_BMP
};

class PDFIumLoader {
public:
    PDFIumLoader(){}
    PDFIumLoader(const char* pBuf, size_t len);
    const char* m_pBuf;
    size_t m_Len;
};

class PDFIumReader
{
private:
    static void WritePpm(const char* pdf_name, int num, const char* buffer, int stride, int width, int height);
    static void AddSegment(FX_DOWNLOADHINTS* pThis, size_t offset, size_t size);
    static bool IsDataAvail(FX_FILEAVAIL* pThis, size_t offset, size_t size);
    static int  GetBlock(void* param, unsigned long pos, unsigned char* pBuf, unsigned long size);
    static int  FormAlert(IPDF_JSPLATFORM*, FPDF_WIDESTRING, FPDF_WIDESTRING, int, int);
public:
    PDFIumReader(){}
    ~PDFIumReader();
    bool Reader(const char *name);
    void Close();
    char* GetPdfPage(int pageIndex, float& width, float& height,  bool OutBmp = false);
    int GetPageCount(){ return m_nPageCount; }
    char* GetNextPage(int &page, float& width, float& height, bool OutBmp);
    void SetCurrentPage(int page);

private:
    void  RenderPdf(const char* pBuf, size_t len);

private:
    FPDF_DOCUMENT m_pPdfDoc = nullptr;
    FPDF_FORMFILLINFO m_formCallbacks;
    IPDF_JSPLATFORM m_platformcallbacks;
    FPDF_FORMHANDLE m_formHandle;
    FX_DOWNLOADHINTS m_hints;
    FX_FILEAVAIL m_fileAvail;
    FPDF_FILEACCESS m_fileAccess;
    PDFIumLoader m_PDFIumLoader;
    FPDF_AVAIL m_PdfAvail;
    char *m_pdfBuf;
    bool m_bIsLinearized = false;
    std::string m_strFileName;
    int m_nPageCount = 0;
    int m_nCurrentPage = 0;
};


-------------------------------------------------------------------------------------PDFIumReader.cpp______________________________________________

#include "PDFIumReader.h"


using namespace std;


void PDFIumReader::RenderPdf(const char* pBuf, size_t len)
{
    memset(&m_platformcallbacks, '\0', sizeof(m_platformcallbacks));
    m_platformcallbacks.version = 1;
    m_platformcallbacks.app_alert = FormAlert;

    memset(&m_formCallbacks, '\0', sizeof(m_formCallbacks));
    m_formCallbacks.version = 1;
    m_formCallbacks.m_pJsPlatform = &m_platformcallbacks;

    m_PDFIumLoader.m_pBuf = pBuf;
    m_PDFIumLoader.m_Len = len;

    memset(&m_fileAccess, '\0', sizeof(m_fileAccess));
    m_fileAccess.m_FileLen = static_cast(len);
    m_fileAccess.m_GetBlock = GetBlock;
    m_fileAccess.m_Param = &m_PDFIumLoader;

    memset(&m_fileAvail, '\0', sizeof(m_fileAvail));
    m_fileAvail.version = 1;
    m_fileAvail.IsDataAvail = IsDataAvail;

    memset(&m_hints, '\0', sizeof(m_hints));
    m_hints.version = 1;
    m_hints.AddSegment = AddSegment;

    m_PdfAvail = FPDFAvail_Create(&m_fileAvail, &m_fileAccess);

    (void)FPDFAvail_IsDocAvail(m_PdfAvail, &m_hints);

    if (!FPDFAvail_IsLinearized(m_PdfAvail)) {
        printf("Non-linearized path...\n");
        m_pPdfDoc = FPDF_LoadCustomDocument(&m_fileAccess, NULL);
    }
    else {
        printf("Linearized path...\n");
        m_pPdfDoc = FPDFAvail_GetDocument(m_PdfAvail, NULL);
    }

    (void)FPDF_GetDocPermissions(m_pPdfDoc);
    (void)FPDFAvail_IsFormAvail(m_PdfAvail, &m_hints);

    m_formHandle = FPDFDOC_InitFormFillEnviroument(m_pPdfDoc, &m_formCallbacks);
    FPDF_SetFormFieldHighlightColor(m_formHandle, 0, 0xFFE4DD);
    FPDF_SetFormFieldHighlightAlpha(m_formHandle, 100);

    int first_page = FPDFAvail_GetFirstPageNum(m_pPdfDoc);
    FPDFAvail_IsPageAvail(m_PdfAvail, first_page, &m_hints);

    m_nPageCount = FPDF_GetPageCount(m_pPdfDoc);
    for (int i = 0; i < m_nPageCount; ++i) {
        FPDFAvail_IsPageAvail(m_PdfAvail, i, &m_hints);
    }

    FORM_DoDocumentJSAction(m_formHandle);
    FORM_DoDocumentOpenAction(m_formHandle);
}

void PDFIumReader::WritePpm(const char* pdf_name, int num, const char* buffer, int stride, int width, int height)
{
    if (stride < 0 || width < 0 || height < 0)
        return;
    if (height > 0 && width > INT_MAX / height)
        return;
    int out_len = width * height;
    if (out_len > INT_MAX / 3)
        return;
    out_len *= 3;

    char filename[256];
    _snprintf(filename, sizeof(filename), "%s.%d.ppm", pdf_name, num);
    FILE* fp = fopen(filename, "w");
    if (!fp)
        return;
    fprintf(fp, "P6\n# PDF test render\n%d %d\n255\n", width, height);
    // Source data is B, G, R, unused.
    // Dest data is R, G, B.
    char* result = new char[out_len];
    if (result) {
        for (int h = 0; h < height; ++h) {
            const char* src_line = buffer + (stride * h);
            char* dest_line = result + (width * h * 3);
            for (int w = 0; w < width; ++w) {
                // R
                dest_line[w * 3] = src_line[(w * 4) + 2];
                // G
                dest_line[(w * 3) + 1] = src_line[(w * 4) + 1];
                // B
                dest_line[(w * 3) + 2] = src_line[w * 4];
            }
        }
        fwrite(result, out_len, 1, fp);
        delete[] result;
    }
    fclose(fp);
}

void PDFIumReader::AddSegment(FX_DOWNLOADHINTS* pThis, size_t offset, size_t size)
{
    
}

bool PDFIumReader::IsDataAvail(FX_FILEAVAIL* pThis, size_t offset, size_t size)
{
    return true;
}

int PDFIumReader::GetBlock(void* param, unsigned long pos, unsigned char* pBuf, unsigned long size)
{
    PDFIumLoader* pLoader = (PDFIumLoader*)param;
    if (pos + size < pos || pos + size > pLoader->m_Len) return 0;
    memcpy(pBuf, pLoader->m_pBuf + pos, size);
    return 1;
}

int PDFIumReader::FormAlert(IPDF_JSPLATFORM*, FPDF_WIDESTRING, FPDF_WIDESTRING, int, int)
{
    printf("Form_Alert called.\n");
    return 0;
}

PDFIumReader::~PDFIumReader()
{
    Close();
}

bool PDFIumReader::Reader(const char *filename)
{
    if (NULL == filename)
        return false;
    m_strFileName = filename;
    FILE* file = fopen(filename, "rb");
    if (!file) {
        fprintf(stderr, "Failed to open: %s\n", filename);
        return false;
    }
    (void)fseek(file, 0, SEEK_END);
    size_t len = ftell(file);
    (void)fseek(file, 0, SEEK_SET);
    m_pdfBuf = (char*)malloc(len);
    size_t ret = fread(m_pdfBuf, 1, len, file);
    (void)fclose(file);
    RenderPdf(m_pdfBuf, len);
    return true;
}

char* PDFIumReader::GetPdfPage(int pageIndex, float& width, float& height, bool OutBmp)
{
    if (pageIndex < 0)
        return 0;
    pageIndex = min(pageIndex, m_nPageCount - 1);
    m_nCurrentPage = pageIndex;
    FPDF_PAGE page = FPDF_LoadPage(m_pPdfDoc, pageIndex);
    FPDF_TEXTPAGE text_page = FPDFText_LoadPage(page);
    FORM_OnAfterLoadPage(page, m_formHandle);
    FORM_DoPageAAction(page, m_formHandle, FPDFPAGE_AACTION_OPEN);

    width = static_cast(FPDF_GetPageWidth(page));
    height = static_cast(FPDF_GetPageHeight(page));
    FPDF_BITMAP bitmap = FPDFBitmap_Create(width, height, 0);
    FPDFBitmap_FillRect(bitmap, 0, 0, width, height, 255, 255, 255, 255);

    FPDF_RenderPageBitmap(bitmap, page, 0, 0, width, height, 0, 0);
    FPDF_FFLDraw(m_formHandle, bitmap, page, 0, 0, width, height, 0, 0);
    char* buffer = reinterpret_cast(
        FPDFBitmap_GetBuffer(bitmap));
    if (OutBmp) {
        int stride = FPDFBitmap_GetStride(bitmap);
        WritePpm(m_strFileName.c_str(), pageIndex, buffer, stride, width, height);
    }

    FPDFBitmap_Destroy(bitmap);

    FORM_DoPageAAction(page, m_formHandle, FPDFPAGE_AACTION_CLOSE);
    FORM_OnBeforeClosePage(page, m_formHandle);
    FPDFText_ClosePage(text_page);
    FPDF_ClosePage(page);
    return buffer;
}


char* PDFIumReader::GetNextPage(int &page, float& width, float& height, bool OutBmp)
{
    page = ++m_nCurrentPage;
    page = min(page, m_nPageCount - 1);
    page = max(0, page);
    return GetPdfPage(page, width, height, OutBmp);
}

void PDFIumReader::SetCurrentPage(int page)
{
    m_nCurrentPage = page;
    m_nCurrentPage = min(m_nCurrentPage, m_nPageCount - 1);
    m_nCurrentPage = max(0, m_nCurrentPage);
}

void PDFIumReader::Close()
{
    if (!this->m_pPdfDoc)
        return;
    FORM_DoDocumentAAction(this->m_pPdfDoc, FPDFDOC_AACTION_WC);
    FPDFDOC_ExitFormFillEnviroument(this->m_formHandle);
    FPDF_CloseDocument(this->m_pPdfDoc);
    FPDFAvail_Destroy(this->m_PdfAvail);
    free(m_pdfBuf);
    this->m_pPdfDoc = NULL;
}
PDFIumLoader::PDFIumLoader(const char* pBuf, size_t len)
: m_pBuf(pBuf), m_Len(len) {
}






然后建立导出接口:新建一个PDFIumReaerII.h

加入如下导出接口:


#ifndef _PDF_IUM_READER_H_
#define _PDF_IUM_READER_H_

#ifdef PDF_IUM_READER_API extern "C" _declspec(dllexport)  
#else 
#define PDF_IUM_READER_API extern "C" _declspec(dllexport) 
#endif 

//加载
PDF_IUM_READER_API bool  PDFIumReader_Loadpdf(const char* filename, int length);
//关闭
 PDF_IUM_READER_API bool  PDFIumReader_Closepdf(const char* filename);
//加载某个page
PDF_IUM_READER_API char* PDFIumReader_LoadPage(const char* filename, int page, float& width, float& height, int& size, bool OutBmp);
//关闭个page
PDF_IUM_READER_API void  PDFIumReader_ClosePage(const char* filename, int page);
//获取总页数
PDF_IUM_READER_API  int  PDFIumReader_GetPageCount(const char* filename);
//获取下一页该渲染的页
 PDF_IUM_READER_API int  PDFIumReader_GetNextPage(const char* filename);
#endif



最后定义导出函数如下

--------------------------------------------------------------------------PDFIumReaderII.h-----------------------------------------------------------------------------------------------

#ifndef _PDF_IUM_READER_H_
#define _PDF_IUM_READER_H_

#ifdef PDF_IUM_READER_API extern "C" _declspec(dllexport)   
#else  
#define PDF_IUM_READER_API extern "C" _declspec(dllexport)  
#endif  

//加载
PDF_IUM_READER_API bool  PDFIumReader_Loadpdf(const char* filename);
//关闭
 PDF_IUM_READER_API void  PDFIumReader_Closepdf(const char* filename);
//加载某个page
PDF_IUM_READER_API char* PDFIumReader_GetPage(const char* filename, int page, float& width, float& height, bool OutBmp = false);
//获取总页数
PDF_IUM_READER_API  int  PDFIumReader_GetPageCount(const char* filename);
//获取下一页该渲染的页
PDF_IUM_READER_API  char*  PDFIumReader_GetNextPage(const char* filename, int &page, float& width, float& height, bool OutBmp =false);
//设置当前页
PDF_IUM_READER_API void  PDFIumReader_SetCurrentPage(const char* filename, int page);
#endif

--------------------------------------------------------------------PDFIumReaderII.cpp----------------------------------------------------------------------------------------

// PdfIumManager.cpp : 定义 DLL 应用程序的导出函数。
//
#include "PDFIumReaderII.h"
#include "PDFReaderMgr.h"

using namespace std;

PDF_IUM_READER_API bool PDFIumReader_Loadpdf(const char* filename)
{
    return PDFIumReaderMgr::Instance()->LoadPDF(filename);
}

PDF_IUM_READER_API void  PDFIumReader_Closepdf(const char* filename)
{
    PDFIumReaderMgr::Instance()->Closepdf(filename);
}

PDF_IUM_READER_API char*   PDFIumReader_GetPage(const char* filename, int page, float& width, float& height, bool OutBmp)
{
    return PDFIumReaderMgr::Instance()->LoadPage(filename, page, width, height, OutBmp);
}

PDF_IUM_READER_API int  PDFIumReader_GetPageCount(const char* filename)
{
    return PDFIumReaderMgr::Instance()->GetPageCount(filename);
}

PDF_IUM_READER_API char * PDFIumReader_GetNextPage(const char* filename, int &page, float& width, float& height,  bool OutBmp)
{
    return PDFIumReaderMgr::Instance()->GetNextPage(filename, page, width, height, OutBmp);
}
PDF_IUM_READER_API void  PDFIumReader_SetCurrentPage(const char* filename, int page)
{
    PDFIumReaderMgr::Instance()->SetCurrentPage(filename, page);
}





最后引入库 如果编译32为引入32的pdfium库 64的引入64位库


使用:

#include "F:\\Qt-pdf\\PdfIumReader64\\PdfIumManager\\PDFIumReaderII.h"
#pragma  comment(lib, "F:\\Work\\Win32Project2\\x64\\Debug\\PDFIumReaderII.lib")
int _tmain(int argc, _TCHAR* argv[])
{
    PDFIumReader_Loadpdf("F:\\Work\\Win32Project2\\x64\\Debug\\1.pdf");
   int counts = PDFIumReader_GetPageCount("F:\\Work\\Win32Project2\\x64\\Debug\\1.pdf");
   for (int i = 0; i < counts; ++i)
   {

       float width, height = 0;
       int length = 0;
       char *buf = PDFIumReader_GetPage("F:\\Work\\Win32Project2\\x64\\Debug\\1.pdf", i, width, height,true);
   }
   PDFIumReader_Closepdf("F:\\Work\\Win32Project2\\x64\\Debug\\1.pdf");
   getchar();
    return 0;
}


这里返回的是char类型的数据,可以直接在vc和Qt上使用,后面再介绍




你可能感兴趣的:(Qt,PDF)