Foxit PDF SDK 简介
您是否曾经想要构建一个可以对PDF文档进行任何操作的应用程序?如果您的答案是 “Yes”, 那么恭喜您!您找到了业界中可以构建稳定、安全、高效且功能齐全的PDF应用的优选解决方案。
Foxit PDF SDK提供高性能的开发库,帮助软件开发人员使用最流行的开发语言和环境在不同平台 (包括Windows、Mac、Linux、Web、Android、iOS 和 UWP) 的企业版、移动版和云应用程序中添加强大的PDF功能。
为什么选择Foxit PDF SDK
Foxit 是领先的PDF软件解决方案供应商,专注于PDF显示、编辑、创建、管理以及安全方面。Foxit PDF SDK 开发库已在当今许多知名的应用程序中使用,并且经过长期的测试证明Foxit PDF SDK的质量、性能和功能正是业界大部分应用程序所需要的。选择Foxit PDF SDK 产品的几大理由:
易于集成
开发人员可以将SDK无缝集成到他们自己的应用程序中。
轻量级
部署简单快速,占用系统资源少。
支持跨平台
支持当前主流的平台,比如Windows、Mac、Linux、Web、Android、iOS和UWP。
基于福昕高保真的PDF渲染引擎
Foxit PDF SDK的核心技术是基于世界众多知名企业所信赖的福昕PDF引擎。福昕强大的PDF引擎可快速解析和渲染文档,不受设备环境的约束。
优秀的技术支持
福昕对自己的开发产品提供了优秀的技术支持,当您在开发关键重要的产品时,可以提供高效的帮助和支持。福昕拥有一支PDF行业优秀的技术支持工程师团队,同时将定期地进行版本更新发布,通过添加新的功能和增强已有的功能来提升用户体验。
Foxit PDF SDK for C++ API
使用Foxit PDF SDK的应用程序开发人员可以利用Foxit强大、符合标准的PDF技术来安全地显示、创建、编辑、注释、格式化、组织、打印、共享、保护、搜索文档,以及填写PDF表单。此外,Foxit PDF SDK (C++和.NET) 包含一个内置可嵌入的PDF Viewer,使开发过程更容易和更快捷。有关更多详细信息,请访问网站https://developers.foxitsoftware.cn/pdf-sdk/。
在本手册中,我们专注于介绍Windows、Linux和Mac平台的Foxit PDF SDK for C++ API。
Foxit PDF SDK for C ++ API提供简单易用的API,帮助C ++开发人员将强大的PDF技术无缝集成到他们自己的Windows、Linux和Mac平台项目中。并且提供了PDF文档相关的丰富功能,比如PDF浏览、书签导航、文本选择/复制/搜索、PDF签名、PDF表单、权限管理、PDF注释以及全文搜索等。
评估
用户可申请下载Foxit PDF SDK的试用版本进行试用评估。试用版除了有试用期10天时间的限制以及生成的PDF页面上会有试用水印以外,其他都和标准认证版一样。当试用期到期后,用户需联系福昕销售团队并购买licenses以便继续使用Foxit PDF SDK.
授权
程序开发人员需购买licenses授权才能在其解决方案中使用Foxit PDF SDK。Licenses授予用户发布基于Foxit PDF SDK开发的应用程序的权限。然而,在未经福昕软件公司授权下,用户不能将Foxit PDF SDK包中的任何文档、示例代码以及源代码分发给任何第三方机构。
关于此文档
此文档适用于需要使用C++开发语言将Foxit PDF SDK集成到自己的应用程序中的开发人员。它旨在介绍SDK 包结构和SDK的用法。
入门指南
安装并集成Foxit PDF SDK非常简单。本手册将提供SDK包的简要介绍。作为跨平台产品,Foxit PDF SDK支持Windows、Linux和Mac桌面平台统一的接口。本章的主要内容是介绍系统要求、SDK包结构、以及如何运行demo和创建自己的项目。
系统要求
平台 | 系统要求 | 备注 |
Windows | Windows XP, Vista, 7, 8, 10 (32-bit 和 64-bit) Windows Server 2003, 2008, 2012 (32-bit 和 64-bit) |
仅支持 Windows 8/10经典样式,不支持Store APP和 Universal App。 |
Linux | 32-bit 和64-bit OS | 所有的Linux示例在 Ubuntu14.0 32/64 bit上进行过测试。 |
Mac | Mac OS 10.6及以上 |
Windows
在本手册中,请知晓:图片上面高亮的矩形区域指的是SDK的版本号,当前SDK的版本是7.2,则其代表7_2。
包结构说明
下载Foxit PDF SDK for Windows包,解压到一个新的目录如 “foxitpdfsdk_7_2_win”,如Figure 2-1所示。其中解压包中包括如下的内容:
doc: API 手册,开发者指南
examples: 示例工程和demos
include: Foxit PDF SDK API的头文件
lib: SDK库和授权文件
Figure 2-1
在 “examples” 文件夹下,有两种类型的demos。”\examples\simple_demo” 包含30多个简单示例 demo,涵盖各种PDF应用程序。”\examples\view_demo” 包含一个UI demo,该demo实现的是一个精简的PDF阅读器。
运行demo
Simple Demo
Simple demo工程提供了一些示例,向开发人员展示如何有效地应用Foxit PDF SDK APIs来完成其应用程序中所需的功能。
在Visual Studio中运行demo (除了security, signature, ocr, compliance 和html2pdf demo,这些将在后面介绍),您可以按照如下的步骤:
1) 在 “\examples\simple_demo” 文件夹下,根据您Visual Studio的版本双击 “simple_demo_vs2010.sln” 或者 “simple_demo_vs2015.sln” 或者 “simple_demo_vs2017.sln”。
2) 单击 “Build > Build Solution” 编译所有的demo。或者,如果您只想编译某个特定的demo,您可以右击该demo工程,然后选择 “Build”,或者在该demo工程的文件夹下双击”*.vxcproj”,然后编译该工程。
编译后,在 “\examples\simple_demo\bin” 文件夹下将生成 “.exe” 可执行文件。可执行文件的名称取决于工程编译的配置。
3) 运行某个特定的可执行文件,只需要双击即可。
对于会生成输出文件 (pdf, 文本或者图片文件) 的demo,会在 “\examples\simple_demo\output_files\” 文件夹下生成以该demo名称命名的文件夹,并且输出文件将会在该文件夹下生成。
备注:如果您需要查看详细的执行过程,您可以在命令行中运行。启动 “cmd.exe”,导航到 “\examples\simple_demo\bin”,然后运行特定的可执行文件。
Security demo
在运行security demo之前,您需要安装 “\examples\simple_demo\input_files” 文件夹下的”foxit.cer” 和 “foxit_all.pfx” 证书。
- 安装 “foxit.cer”,双击其启动证书导入向导。然后选择”Install certificate… > Next > Next > Finish”。
- 安装 “foxit_all.pfx”,双击其启动证书导入向导。然后选择 “Next > Next > (在文本框中输入私钥的密码) ,然后点击Next > Next > Finish”。
- 参考其他demo的运行步骤运行该demo。
Signature demo
在运行signature demo之前,您需要确保已经安装了OpenSSL。从OpenSSL官网下载OpenSSL 源码包,或者您可以直接与我们客服联系。获取到源码包后,解压并进行如下操作:
- 将OpenSSL文件夹拷贝到 “include”文件夹下,以确保demo中引用的OpenSSL头文件可以被识别到。
- 将 “libeay32.lib” 库拷贝到 “lib” 文件夹下。
- 参考其他demo的运行步骤运行该demo。
备注:OpenSSL 1.0.2m 版本在signature demo中已经验证是可用的。您可以替换为其他所需的版本,但可能需要做一些相应的更改。
OCR 和 Compliance demo
对于ocr 和 compliance demo,您需要首先构建一个资源目录,请联系Foxit支持团队或者销售团队获取相应的资源包。关于如何运行该demo的更详细的信息,请参考3.34小节 “OCR” 和3.35小节 “Compliance“。
HTML to PDF demo
对于html2pdf demo,您需要首先联系Foxit支持团队或者销售团队获取HTML 转PDF的引擎包。关于如何运行该demo的更详细的信息,请参考3.37小节 “HTML转PDF“。
View Demo
View demo为开发人员提供了一个使用Foxit PDF SDK APIs实现一个PDF阅读器的示例。
在Visual Studio中运行该demo,根据您Visual Studio的版本双击”\examples\view_demo\PDFReader\project” 文件夹下的 “PDFReader_VS2010.sln” 或者 “PDFReader_VS2015.sln” 或者 “PDFReader_VS2017.sln”,然后点击 “Debug > Start Without Debugging” 运行该demo。当demo运行起来后,您将看到如下的文件选择对话框:
Figure 2-2
您可以将PDF文档拖动到上面的窗体 (Figure 2-2) 来打开该文档,然后通过向下滚动或者按住鼠标左键移动PDF页面来浏览文档内容。此外,您可以点击 “Annot > HighLight” 来高亮文本,如Figure 2-3所示。
Figure 2-3
创建一个简单的工程
本节主要介绍如何使用Foxit PDF SDK for Windows创建一个简单的工程,该工程将PDF文档的首页渲染成bitmap,然后将其另存为JPG图片。请按照如下的步骤操作:
1)打开Visual Studio,创建一个名为 “test_win” 的Win32控制台应用程序。
2)将 “foxitpdfsdk_7_2_win” 文件夹下的 “include” 和 “lib” 文件夹拷贝到 “test_win” 工程目录下。
3)添加 “include” 文件夹到 “Additional Include Directories”。在Solution Explorer中右击test_win 工程,选择 “Properties”,然后找到 “Configuration Properties > C/C++ > General > Additional Include Directories”。
4)在test_win.cpp的开头添加include 头文件声明。
#include <iostream> #include "../include/common/fs_common.h" #include "../include/pdf/fs_pdfdoc.h" #include "../include/pdf/fs_pdfpage.h" #include "../include/common/fs_render.h"
5)添加using namespace命名空间声明。
using namespace std; using namespace foxit; using namespace common; using namespace pdf; using namespace foxit::common;
6)包含 Foxit PDF SDK库。
#if defined (_WIN64) // windows 64bit platforms. #if defined (_DEBUG) #pragma comment (lib, "../lib/fsdk_win64.lib") #else #pragma comment (lib, "../lib/fsdk_win64.lib") #endif #elif defined (_WIN32) // windows 32bit platforms. #if defined (_DEBUG) #pragma comment (lib, "../lib/fsdk_win32.lib") #else #pragma comment (lib, "../lib/fsdk_win32.lib") #endif #endif
7)初始化Foxit PDF SDK 库。在调用任何APIs之前,应用程序必须使用license授权码初始化Foxit PDF SDK 库。试用license文件在 “lib” 文件夹下。
const char* sn = " "; const char* key = " "; foxit::ErrorCode code = Library::Initialize(sn, key); if (code != foxit::e_ErrSuccess) { return FALSE; }
备注:参数 “sn”的值在 “gsdk_sn.txt” 中 (“SN=”后面的字符串),“key” 的值在 “gsdk_key.txt“中 (“Sign=”后面的字符串)。
8)加载一个PDF文档,然后解析该文档的首页。假设您已经在 “test_win\test_win” 文件夹下放入了一个 “Sample.pdf” 文件。
PDFDoc doc("Sample.pdf"); ErrorCode error_code = doc.Load(); if (error_code!= foxit::e_ErrSuccess) return 0; PDFPage page = doc.GetPage(0); page.StartParse(foxit::pdf::PDFPage::e_ParsePageNormal, NULL, false);
9)将页面渲染成bitmap,然后将其另存为JPG图片。
int width = static_cast<int>(page.GetWidth()); int height = static_cast<int>(page.GetHeight()); Matrix matrix = page.GetDisplayMatrix(0, 0, width, height, page.GetRotation()); // Prepare a bitmap for rendering. Bitmap bitmap(width, height, Bitmap::e_DIBArgb, NULL, 0); bitmap.FillRect(0xFFFFFFFF, NULL); // Render page. Renderer render(bitmap, false); render.StartRender(page, matrix, NULL); // Add the bitmap to image and save the image. Image img; img.AddFrame(bitmap); img.SaveAs("testpage.jpg");
10)点击 “Build > Build Solution” 编译该工程。可执行文件 “test_win.exe” 将在 “test_win\Debug” 或者 “test_win\Release” 文件夹下生成,具体取决于编译配置。
11)将 “lib” 文件夹下的 “fsdk_win32.dll” 或者 “fsdk_win64.dll” 拷贝到输出目录(“test_win\Debug” 或者 “test_win\Release”)。请确保 “fsdk_win**.dll” 架构需要与应用程序的platform target (Win32 或者 Win64) 相匹配。
12)选择如下其中一种方式运行该工程:
i. 在Visual Studio中点击 “Debug > Start Without Debugging” 运行工程,然后在 “test_win\test_win” 文件夹下将会生成 “testpage.jpg”。
ii. 双击可执行文件 “test_win.exe” 运行工程。使用这种方式,您需要将 “Sample.pdf” 文档放在与 “test_win.exe” 相同的文件夹中,并且 “testpage.jpg” 也将在同一文件夹中生成。
“test_win.cpp” 的完整内容如下:
#include "stdafx.h" #include <iostream> #include "../include/common/fs_common.h" #include "../include/pdf/fs_pdfdoc.h" #include "../include/pdf/fs_pdfpage.h" #include "../include/common/fs_render.h" using namespace std; using namespace foxit; using namespace common; using namespace pdf; using namespace foxit::common; // Include Foxit PDF SDK library. #if defined (_WIN64) // windows 64bit platforms. #if defined (_DEBUG) #pragma comment (lib, "../lib/fsdk_win64.lib") #else #pragma comment (lib, "../lib/fsdk_win64.lib") #endif #elif defined (_WIN32) // windows 32bit platforms. #if defined (_DEBUG) #pragma comment (lib, "../lib/fsdk_win32.lib") #else #pragma comment (lib, "../lib/fsdk_win32.lib") #endif #endif int _tmain(int argc, _TCHAR* argv[]) { // The value of "sn" can be got from "gsdk_sn.txt" (the string after "SN="). // The value of "key" can be got from "gsdk_key.txt" (the string after "Sign="). const char* sn = " "; const char* key = " "; foxit::ErrorCode code = Library::Initialize(sn, key); if (code != foxit::e_ErrSuccess) { return FALSE; } // Load a PDF document, and parse the first page of the document. PDFDoc doc("Sample.pdf"); ErrorCode error_code = doc.Load(); if (error_code!= foxit::e_ErrSuccess) return 0; PDFPage page = doc.GetPage(0); page.StartParse(foxit::pdf::PDFPage::e_ParsePageNormal, NULL, false); int width = static_cast<int>(page.GetWidth()); int height = static_cast<int>(page.GetHeight()); Matrix matrix = page.GetDisplayMatrix(0, 0, width, height, page.GetRotation()); // Prepare a bitmap for rendering. Bitmap bitmap(width, height, Bitmap::e_DIBArgb, NULL, 0); bitmap.FillRect(0xFFFFFFFF, NULL); // Render page. Renderer render(bitmap, false); render.StartRender(page, matrix, NULL); // Add the bitmap to image and save the image. Image img; img.AddFrame(bitmap); img.SaveAs("testpage.jpg"); return 0; }
Linux
在本手册中,请知晓:图片上面高亮的矩形区域指的是SDK的版本号,当前SDK的版本是7.2,则其代表7_2。
包结构说明
下载Foxit PDF SDK for Linux包,解压到一个新的目录如 “foxitpdfsdk_7_2_linux”,如 Figure 2-4所示。其中解压包中包括如下的内容:
doc: API 手册,开发者指南
examples: 示例工程和demos
include: Foxit PDF SDK API的头文件
lib: SDK库和授权文件
Figure 2-4
在 “examples” 文件夹下,有两种类型的demos。”\examples\simple_demo” 包含了大量的PDF应用程序的demo。”\examples\view_demo” 包含一个Qt UI demo,该demo实现的是一个精简的PDF阅读器。
运行demo
Simple Demo
Simple demo工程提供了一些示例,向开发人员展示如何有效地应用Foxit PDF SDK APIs来完成其应用程序中所需的功能。
在运行demo之前,请确保您已经正确配置环境,并且已安装CMake 3.1或更高版本。
OS | 编译工具或IDE | 版本 |
Linux | GCC | 4.8 或更高 |
在终端运行demo (除了security, signature, 和 compliance demo,这些将在后面介绍),您可以按照如下的步骤:
1)打开一个终端,导航到 “foxitpdfsdk_7_2_linux\examples\simple_demo”;
2)运行 “cmake -DPRJ_NAME=XXX” 以编译指定的demo。”XXX” 是demo的名称,该名称必须为 “annotation”, “attachment”, “pdf2text” 等等。例如,运行 “cmake -DPRJ_NAME=annotation”。
3)运行 “make” 以构建上述命令中指定的demo。然后将生成名为 “XXX_xxx” 的可执行文件。”XXX” 是demo的名称,”xxx” 是架构名,例如 “annotation_linux64″。
4)执行 “./XXX_xxx” 以运行demo。例如,执行 “./annotation_linux64” 来运行annotation demo。
对于有输出文件 (pdf, 文本或者图片文件) 的demo来说,会在 “examples\simple_demo\output_files\” 文件夹下生成以该demo名称命名的文件夹,并且输出文件将会在该文件夹下生成。
Security 和 Signature demo
在运行security和signature demo之前,请确保您已经安装了OpenSSL。从OpenSSL官网下载OpenSSL 源码包,或者您可以直接与我们客服联系。获取到源码包后,解压并进行如下操作:
1)将OpenSSL文件夹拷贝到 “include”文件夹下,以确保demo中引用的OpenSSL头文件可以被识别到。
2)将 “libssl.a” 和 “libcrypto.a” 库拷贝到 “lib” 文件夹下。
3)参考其他demo的运行步骤运行该demo。
备注:OpenSSL 1.0.2 版本在security 和 signature demo中已经验证是可用的。您可以替换为其他所需的版本,但可能需要做一些相应的更改。
Compliance demo
对于如何运行compliance demo,请参阅3.35小节 “Compliance“。
View Demo
View demo为开发人员提供了一个Qt示例,用来展示如何使用Foxit PDF SDK APIs实现一个PDF阅读器。
在运行demo之前,请确保您Linux系统已经安装了compiler tool (GCC 4.8或更高) 和 “Qt Creator” IDE。
在Qt Creator中运行demo,请按照如下的步骤:
1)打开Qt Creator,点击Open Project,然后导航到”\examples\view_demo\PDFReader_Qt” 文件夹,选择PDFReader_Qt.pro文件打开该demo。
如果出现 “Configure Project” 窗口,请根据提示选择一种kit, 然后点击Configure Project按钮,如图Figure 2-5所示。
Figure 2-5
2)Demo打开后,点击左侧工具栏的Projects,将 “Build&Run -> Build Settings -> General” 下的Shadow build选项的勾选去掉,如图Figure 2-6所示。
Figure 2-6
3)编译并运行demo。点击Build -> Run运行demo。当demo运行起来后,您将看到如下的窗体:
Figure 2-7
点击上面图片 (Figure 2-7) 的按钮打开一个PDF文档。然后可以通过向下滚动来浏览文档内容,翻页,以及放大缩小PDF页面,如Figure 2-8所示。
Figure 2-8
创建一个简单的工程
本节主要介绍如何使用Foxit PDF SDK for Linux创建一个简单的工程,该工程将PDF文档的首页渲染成bitmap,然后将其另存为JPG图片。请按照如下的步骤操作:
1)新建一个名为 “test_linux” 的文件夹。
2)将 “foxitpdfsdk_7_2_linux” 文件夹下的 “include” 和 “lib” 文件夹拷贝到 “test_linux” 文件夹下。
3)在 “test_linux” 文件夹下,创建一个 “test_linux.cpp” 文件,然后添加代码,具体代码见2.2.3小节 “创建一个简单的工程” 中的 “test_win.cpp”。
“test_linux.cpp” 如下所示: (为了更好的阅读,我们将代码拷贝到Visual Studio中以便使用不同的颜色显示代码)
#include <iostream> #include "common/fs_common.h" #include "pdf/fs_pdfdoc.h" #include "pdf/fs_pdfpage.h" #include "common/fs_render.h" using namespace std; using namespace foxit; using namespace common; using namespace pdf; using namespace foxit::common; int main(int argc, char* argv[]) { // The value of "sn" can be got from "gsdk_sn.txt" (the string after "SN="). // The value of "key" can be got from "gsdk_key.txt" (the string after "Sign="). const char* sn = " "; const char* key = " "; foxit::ErrorCode code = Library::Initialize(sn, key); if (code != foxit::e_ErrSuccess) { return FALSE; } // Load a PDF document, and parse the first page of the document. PDFDoc doc("../../Sample.pdf"); ErrorCode error_code = doc.Load(); if (error_code!= foxit::e_ErrSuccess) return 0; PDFPage page = doc.GetPage(0); page.StartParse(foxit::pdf::PDFPage::e_ParsePageNormal, NULL, false); int width = static_cast<int>(page.GetWidth()); int height = static_cast<int>(page.GetHeight()); Matrix matrix = page.GetDisplayMatrix(0, 0, width, height, page.GetRotation()); // Prepare a bitmap for rendering. Bitmap bitmap(width, height, Bitmap::e_DIBArgb, NULL, 0); bitmap.FillRect(0xFFFFFFFF, NULL); // Render page. Renderer render(bitmap, false); render.StartRender(page, matrix, NULL); // Add the bitmap to image and save the image. Image img; img.AddFrame(bitmap); img.SaveAs("testpage.jpg"); return 0; }
4)在 “test_linux” 文件夹下放入了一个 “Sample.pdf” 文档。
5)创建一个Makefile。在该Makefile中,构建路径应包含PDF SDK库。64位系统使用libfsdk_linux64.so,32位系统使用libfsdk_linux32.so。Makefile文件示例如下所示:
CXX=g++ # Foxit PDF SDK lib and head files include INCLUDE_PATH=-Iinclude FSDKLIB_PATH=-Llib LIB_PATH=lib FSDKLIB=-lfsdk_linux64 LIBNAME=libfsdk_linux64.so LIBS=$(FSDKLIB) -lpthread LDFLAGS=-Wl,--rpath=. DEST_PATH=./bin/rel_gcc OBJ_PATH=./obj/rel CCFLAGS=-c # Copy the given library to the destination path CP_LIB=cp $(LIB_PATH)/$(LIBNAME) $(DEST_PATH) DEST=-o $(DEST_PATH)/$@ OBJ_DEST= -o $(OBJ_PATH)/$@ all: test_linux dir: mkdir -p $(DEST_PATH) mkdir -p $(OBJ_PATH) test_linux.o :test_linux.cpp $(CXX) $(CCFLAGS) $(INCLUDE_PATH) $^ $(OBJ_DEST) test_linux: dir test_linux.o $(CXX) $(OBJ_PATH)/test_linux.o $(DEST) $(FSDKLIB_PATH) $(LIBS) $(LDFLAGS)
6)构建工程。打开终端,导航到 “test_linux”,然后运行 “make test_linux“以在”test_linux\bin\rel_gcc” 文件夹下生成二进制文件。
7)执行二进制文件。在终端中导航到二进制文件所在的目录,运行 “./test_linux“,然后在当前文件夹下会生成 “testpage.jpg”。
Mac
在本手册中,请知晓:图片上面高亮的矩形区域指的是SDK的版本号,当前SDK的版本是7.2,则其代表7_2。
包结构说明
下载Foxit PDF SDK for Mac包,解压到一个新的目录如 “foxitpdfsdk_7_2_mac”,如Figure 2-9所示。其中解压包中包括如下的内容:
doc: API 手册,开发者指南
examples: 示例工程和demos
include: Foxit PDF SDK API的头文件
lib: SDK库和授权文件
Figure 2-9
在 “\examples\simple_demo” 文件夹下,包含了大量的PDF应用程序的demo。
运行demo
在运行demo之前,请确保您已经正确配置环境,并且已安装CMake 3.1或更高版本。
OS | 编译工具或IDE | 版本 |
Mac | Xcode | 8 或更高 |
在终端运行demo (除了security, signature, compliance 和html2pdf demo,这些将在后面介绍),您可以按照如下的步骤:
- 打开一个终端,导航到 “foxitpdfsdk_7_2_mac\examples\simple_demo”;
- 运行 “cmake -DPRJ_NAME=XXX” 以编译指定的demo。”XXX” 是demo的名称,该名称必须为 “annotation”, “attachment”, “pdf2text” 等等。例如,运行 “cmake -DPRJ_NAME=annotation”。
- 运行 “make” 以构建上述命令中指定的demo。然后将生成名为 “XXX_xxx” 的可执行文件。”XXX” 是demo的名称,”xxx” 是架构名,例如 “annotation_mac64″。
- 执行 “./XXX_xxx” 以运行demo。例如,执行 “./annotation_mac64” 来运行annotation demo。
“\examples\simple_demo\input_files” 包含了所有demo中需要使用的测试文档。对于有输出文件 (pdf, 文本或者图片文件) 的demo来说,会在 “examples\simple_demo\output_files\” 文件夹下生成以该demo名称命名的文件夹,并且输出文件将会在该文件夹下生成。
Security 和 Signature demo
在运行security和signature demo之前,请确保您已经安装了OpenSSL。从OpenSSL官网下载OpenSSL 源码包,或者您可以直接与我们客服联系。获取到源码包后,解压并进行如下操作:
- 将OpenSSL文件夹拷贝到 “include”文件夹下,以确保demo中引用的OpenSSL头文件可以被识别到。
- 将 “libssl.a” 和 “libcrypto.a” 库拷贝到 “lib” 文件夹下。
- 参考其他demo的运行步骤运行该demo。
备注:OpenSSL 1.0.2 版本在security 和 signature demo中已经验证是可用的。您可以替换为其他所需的版本,但可能需要做一些相应的更改。
Compliance demo
对于如何运行compliance demo,请参阅3.35小节 “Compliance“。
HTML to PDF demo
关于如何运行该demo的更详细的信息,请参考3.37小节 “HTML转PDF“。
创建一个简单的工程
本节主要介绍如何使用Foxit PDF SDK for Mac (C++) 创建一个简单的工程,该工程将PDF文档的首页渲染成bitmap,然后将其另存为JPG图片。请按照如下的步骤操作:
1)新建一个名为 “test_mac” 的文件夹。
2)将 “foxitpdfsdk_7_2_mac” 文件夹下的 “include” 和 “lib” 文件夹拷贝到 “test_mac” 文件夹下。
3)在 “test_mac” 文件夹下,创建一个 “test_mac.cpp” 文件,然后添加代码,具体代码见2.2.3小节 “创建一个简单的工程” 中的 “test_win.cpp”。
“test_mac.cpp” 如下所示:
#include <iostream> #include "common/fs_common.h" #include "pdf/fs_pdfdoc.h" #include "pdf/fs_pdfpage.h" #include "common/fs_render.h" using namespace std; using namespace foxit; using namespace common; using namespace pdf; using namespace foxit::common; int main(int argc, char* argv[]) { // The value of "sn" can be got from "gsdk_sn.txt" (the string after "SN="). // The value of "key" can be got from "gsdk_key.txt" (the string after "Sign="). const char* sn = " "; const char* key = " "; foxit::ErrorCode code = Library::Initialize(sn, key); if (code != foxit::e_ErrSuccess) { return FALSE; } // Load a PDF document, and parse the first page of the document. PDFDoc doc("../../Sample.pdf"); ErrorCode error_code = doc.Load(); if (error_code!= foxit::e_ErrSuccess) return 0; PDFPage page = doc.GetPage(0); page.StartParse(foxit::pdf::PDFPage::e_ParsePageNormal, NULL, false); int width = static_cast<int>(page.GetWidth()); int height = static_cast<int>(page.GetHeight()); Matrix matrix = page.GetDisplayMatrix(0, 0, width, height, page.GetRotation()); // Prepare a bitmap for rendering. Bitmap bitmap(width, height, Bitmap::e_DIBArgb, NULL, 0); bitmap.FillRect(0xFFFFFFFF, NULL); // Render page. Renderer render(bitmap, false); render.StartRender(page, matrix, NULL); // Add the bitmap to image and save the image. Image img; img.AddFrame(bitmap); img.SaveAs("testpage.jpg"); return 0; }
4)在 “test_mac” 文件夹下放入了一个 “Sample.pdf” 文档。
5)创建一个Makefile。在该Makefile中,构建路径应包含PDF SDK库。使用libfsdk_mac64.dylib。Makefile文件示例如下所示:
CXX=g++ # Foxit PDF SDK lib and head files include INCLUDE_PATH=-Iinclude LIBNAME=./lib/libfsdk_mac64.dylib LDFLAGS=-Wl,-rpath,../../lib DEST_PATH=./bin/rel_gcc OBJ_PATH=./obj/rel CCFLAGS=-c DEST=-o $(DEST_PATH)/$@ OBJ_DEST= -o $(OBJ_PATH)/$@ all: test_mac dir: mkdir -p $(DEST_PATH) mkdir -p $(OBJ_PATH) test_mac.o :test_mac.cpp $(CXX) $(CCFLAGS) $(INCLUDE_PATH) $^ $(OBJ_DEST) test_mac: dir test_mac.o $(CXX) $(OBJ_PATH)/test_mac.o $(DEST) $(LDFLAGS) $(LIBNAME)
6)构建工程。打开终端,导航到 “test_mac”,然后运行 “make test_mac“以在”test_mac\bin\rel_gcc” 文件夹下生成二进制文件。
7)执行二进制文件。在终端中导航到二进制文件所在的目录,运行 “./test_mac“,然后在当前文件夹下会生成 “testpage.jpg”。
使用 SDK API
在本节中,我们将介绍Foxit PDF SDK的主要功能,并列举相关示例来展示如何使用Foxit PDF SDK C++ API将强大的PDF功能集成到您的应用程序中。您可以参阅API reference [2] 来获取示例中APIs更详细的使用说明。
初始化库
在调用任何API之前,都需要首先初始化Foxit PDF SDK。foxit::common::Library::Initialize用来初始化Foxit PDF SDK,您需要购买正式的license来获取license key和序列号。当不再需要使用Foxit PDF SDK时,请调用foxit::common::Library::Release将其释放。
备注:参数 “sn” 的值在 “gsdk_sn.txt” 中 (“SN=”后面的字符串),“key” 的值在 “gsdk_key.txt” 中 (“Sign=” 后面的字符串)。
Example:
如何初始化Foxit PDF SDK
#include "include/common/fs_common.h" using namespace foxit; using namespace common; ... const char* sn = " "; const char* key = " "; foxit::ErrorCode code = Library::Initialize(sn, key); if (code != foxit::e_ErrSuccess) { return FALSE; }
文档 (Document)
一个PDF document对象可以由一个已有的PDF文件从文件路径、内存缓冲区、自定义实现的ReaderCallback对象、输入文件流中构建。然后调用PDFDoc::Load或者PDFDoc::StartLoad加载文档内容。PDF document对象用于文档级操作,比如打开和关闭PDF文档,获取页面、metadata等。
Example:
如何从0开始创建一个PDF文档
#include "include/pdf/fs_pdfdoc.h" using namespace foxit; using namespace common; using namespace pdf; ... PDFDoc doc();
备注:创建一个新的PDF文档,该文档没有任何页面。
如何通过文件路径加载一个现有的PDF文档
#include "include/pdf/fs_pdfdoc.h" using namespace foxit; using namespace common; using namespace pdf; ... PDFDoc doc("Sample.pdf"); ErrorCode error_code = doc.Load(); if (error_code!= foxit::e_ErrSuccess) return 0;
如何通过内存缓冲区加载一个现有的PDF文档
#include "include/pdf/fs_pdfdoc.h" using namespace foxit; using namespace common; using namespace pdf; ... FILE* pFile = fopen(TEST_DOC_PATH"blank.pdf", "rb"); ASSERT_EQ(TRUE, NULL != pFile); fseek(pFile, 0, SEEK_END); long lFileSize = ftell(pFile); char* buffer = new char[lFileSize]; memset(buffer, 0, sizeof(char)*lFileSize); fseek(pFile, 0, SEEK_SET); fread(buffer, sizeof(char), lFileSize, pFile); fclose(pFile); PDFDoc doc = PDFDoc(buffer, lFileSize); ErrorCode error_code = doc.Load(); if (error_code!= foxit::e_ErrSuccess) return 0;
如何通过自定义实现的ReaderCallback对象加载一个现有的PDF文档
#include "include/pdf/fs_pdfdoc.h" using namespace foxit; using namespace common; using namespace pdf; ... class CFSFile_Read : public ReaderCallback { public: CFSFile_Read():m_fileFP(NULL) ,m_bLargeFile(FALSE) {} ~CFSFile_Read() {} bool LoadFile(const wchar_t* wFilePath, bool bLargeFile = FALSE) { std::wstring strTemp(wFilePath); string bstrFilepath = wchar2utf8(strTemp.c_str(), strTemp.size()); m_fileFP = fopen(bstrFilepath.c_str(), "rb"); if (!m_fileFP) return FALSE; m_bLargeFile = bLargeFile; return TRUE; } bool LoadFile(const char* filePath, bool bLargeFile = FALSE) { m_fileFP = fopen(filePath, "rb"); if (!m_fileFP) return FALSE; m_bLargeFile = bLargeFile; return TRUE; } FILESIZEGetSize() { if (m_bLargeFile) { #if defined(_WIN32) || defined(_WIN64) _fseeki64(m_fileFP, 0, SEEK_END); long long sizeL = _ftelli64(m_fileFP); #elif defined(__linux__) || defined(__APPLE__) fseeko(m_fileFP, 0, SEEK_END); long long sizeL = ftello(m_fileFP); #endif return sizeL; } else { fseek(m_fileFP, 0, SEEK_END); return (uint32)ftell(m_fileFP); } } int ReadBlock(void* buffer, FILESIZE offset, size_t size) { if (m_bLargeFile) { #if defined(_WIN32) || defined(_WIN64) _fseeki64(m_fileFP, offset, SEEK_SET); #elif defined(__linux__) || defined(__APPLE__) fseeko(m_fileFP, offset, SEEK_SET); #endif long long readSize = fread(buffer, 1, size, m_fileFP); return (readSize == size); } else { if (!m_fileFP) return false; if(0 != fseek(m_fileFP, offset, 0)) return false; if(0 == fread(buffer, size, 1, m_fileFP)) return false; return true; } } size_tReadBlock(void* buffer, size_t size) { if (m_bLargeFile) { #if defined(_WIN32) || defined(_WIN64) _fseeki64(m_fileFP, 0, SEEK_SET); #elif defined(__linux__) || defined(__APPLE__) fseeko(m_fileFP, 0, SEEK_SET); #endif return fread(buffer, 1, size, m_fileFP); } else { if (!m_fileFP) return false; if(0 != fseek(m_fileFP, 0, 0)) return 0; return fread(buffer, size, 1, m_fileFP); } } void Release() { if(m_fileFP) fclose(m_fileFP); m_fileFP = NULL; delete this; } private: FILE* m_fileFP; bool m_bLargeFile; } ... string inputPDFPath = "Sample.pdf"; CFSFile_Read* pFileRead = new CFSFile_Read(); If(!pFileRead->LoadFile(inputPDFPath.c_str())) Return; PDFDoc doc = PDFDoc(pFileRead); ErrorCode error_code = doc.Load(); if (error_code!= foxit::e_ErrSuccess) return 0;
如何加载PDF文档以及获取文档的首页
#include "include/pdf/fs_pdfdoc.h" #include "include/pdf/fs_pdfpage.h" using namespace foxit; using namespace common; using namespace pdf; ... PDFDoc doc("Sample.pdf"); ErrorCode error_code = doc.Load(); if (error_code!= foxit::e_ErrSuccess) return 0; PDFPage page = doc.GetPage(0); page.StartParse(foxit::pdf::PDFPage::e_ParsePageNormal, NULL, false);
如何将PDF文档另存为一个新的文档
#include "include/pdf/fs_pdfdoc.h" #include "include/pdf/fs_pdfpage.h" using namespace foxit; using namespace common; using namespace pdf; ... PDFDoc doc("Sample.pdf"); ErrorCode error_code = doc.Load(); if (error_code!= foxit::e_ErrSuccess) return 0; doc.SaveAs("new_Sample.pdf", PDFDoc::e_SaveFlagNoOriginal);
如何通过WriterCallback将PDF文档保存到内存缓冲区
#include "include/pdf/fs_pdfdoc.h" #include "include/pdf/fs_pdfpage.h" using namespace foxit; using namespace common; using namespace pdf; ... // FileWriter for saving file to memory buffer. class FileWriter:public common::file::WriterCallback { public: FileWriter() {} ~FileWriter() {} FILESIZE GetSize() { return binary_buffer_.GetSize(); } FX_BOOL Flush() { return TRUE; } FX_BOOL WriteBlock(const void* buffer,FILESIZE offset,size_t size) { return binary_buffer_.InsertBlock(offset,buffer,size); } FX_BOOL ReadBlock(void* buffer,FILESIZE offset,size_t size) { FX_LPBYTE byte_buffer = binary_buffer_.GetBuffer(); memcpy(buffer, byte_buffer + offset, size); } void Release() { } CFX_BinaryBuf GetBuffer() { return binary_buffer_; } private: CFX_BinaryBuf binary_buffer_; }; ... FileWriter* filewriter = new FileWriter(); // Assuming PDFDoc doc has been loaded. ... doc.StartSaveAs(filewriter, PDFDoc::e_SaveFlagNoOriginal); ...
页面 (Page)
PDF页面是PDF Document基础和重要的组成部分。使用函数foxit::pdf::PDFDoc::GetPage从文档中获取foxit::pdf::PDFPage对象。页面级API提供了解析/渲染/编辑 (包括创建、删除、扁平化等) 页面、获取PDF注释、获取和设置页面属性等功能。对于大多数情况,在渲染和处理页面之前,需要先对页面进行解析。
Example:
如何获取页面的大小
#include "include/pdf/fs_pdfpage.h" using namespace foxit; using namespace common; using namespace pdf; ... // Assuming PDFPage page has been loaded and parsed. int width = static_cast<int>(page.GetWidth()); int height = static_cast<int>(page.GetHeight());
如何计算页面内容的边界框
#include "include/pdf/fs_pdfpage.h" using namespace foxit; using namespace common; using namespace pdf; ... //Assuming PDFDoc doc has been loaded. //Assuming PDFPage page has been loaded and parsed. RectF ret = page.CalcContentBBox(PDFPage::e_CalcContentsBox); ...
如何创建一个PDF页面以及设置其页面大小
#include "include/pdf/fs_pdfdoc.h" #include "include/pdf/fs_pdfpage.h" using namespace foxit; using namespace common; using namespace pdf; ... // Assuming PDFDoc doc has been loaded. PDFPage page = doc.InsertPage(index, PageWidth, PageHeight);
如何删除一个PDF页面
#include "include/pdf/fs_pdfdoc.h" #include "include/pdf/fs_pdfpage.h" using namespace foxit; using namespace common; using namespace pdf; ... // Assuming PDFDoc doc has been loaded. // Remove a PDF page by page index. doc.RemovePage(index); // Remove a specified PDF page. doc.RemovePage(&page); ...
如何扁平化一个PDF页面
#include "include/pdf/fs_pdfpage.h" using namespace foxit; using namespace common; using namespace pdf; ... // Assuming PDFPage page has been loaded and parsed. // Flatten all contents of a PDF page. page.Flatten(true, PDFPage::e_FlattenAll); // Flatten a PDF page without annotations. page.Flatten(true, PDFPage::e_FlattenNoAnnot); // Flatten a PDF page without form controls. page.Flatten(true, PDFPage::e_FlattenNoFormControl); // Flatten a PDF page without annotations and form controls (Equals to nothing to be flattened). page.Flatten(true, PDFPage::e_FlattenNoAnnot | PDFPage::e_FlattenNoFormControl); ...
如何获取和设置PDF文档中的页面缩略图
#include "include/pdf/fs_pdfpage.h" using namespace foxit; using namespace common; using namespace pdf; ... // Assuming PDFPage page has been loaded and parsed. Bitmap bmp(); // Write bitmap data to the bmp object. ... // Set thumbnails to the page. page.SetThumbnail(bmp); // Load thumbnails in the page. Bitmap bitmap = page.LoadThumbnail(); ...
渲染 (Render)
PDF渲染是通过Foxit渲染引擎实现的,Foxit渲染引擎是一个图形引擎,用于将页面渲染到位图或平台设备上下文。 Foxit PDF SDK提供了APIs用来设置渲染选项/flags,例如设置 flag来决定是否渲染表单域和签名,是否绘制图像反锯齿 (anti-aliasing) 和路径反锯齿。可以使用以下APIs进行渲染:
- 渲染页面和注释时,首先使用Renderer::SetRenderContentFlags接口来决定是否同时渲染页面和注释,然后使用Renderer::StartRender接口进行渲染。Renderer::StartQuickRender接口也可以用来渲染页面,但仅用于缩略图。
- 渲染单个annotation注释,使用Renderer::RenderAnnot接口。
- 在位图上渲染,使用Renderer::StartRenderBitmap接口。
- 渲染一个重排的页面,使用Renderer::StartRenderReflowPage接口。
在Foxit PDF SDK中,Widget注释常与表单域和表单控件相关联。渲染widget注释,推荐使用如下的流程:
- 加载PDF页面后,首先渲染页面以及该页面上所有的注释 (包括widget注释)。
- 然后,如果使用pdf::interform::Filler对象来填表,则应使用pdf::interform::Filler::Render接口来渲染当前获取到焦点的表单控件,而不是使用Renderer::RenderAnnot接口。
Example:
如何将PDF页面渲染到bitmap
#include "include/common/fs_common.h" #include "include/pdf/fs_pdfdoc.h" #include "include/pdf/fs_pdfpage.h" #include "include/common/fs_render.h" using namespace foxit; using namespace common; using namespace pdf; using namespace foxit::common; // Assuming PDFPage page has been loaded and parsed. int width = static_cast<int>(page.GetWidth()); int height = static_cast<int>(page.GetHeight()); Matrix matrix = page.GetDisplayMatrix(0, 0, width, height, page.GetRotation()); // Prepare a bitmap for rendering. Bitmap bitmap(width, height, Bitmap::e_DIBArgb, NULL, 0); bitmap.FillRect(0xFFFFFFFF, NULL); // Render page. Renderer render(bitmap, false); render.StartRender(page, matrix, NULL); ...
如何渲染页面和注释
#include "include/common/fs_common.h" #include "include/pdf/fs_pdfdoc.h" #include "include/pdf/fs_pdfpage.h" #include "include/common/fs_render.h" using namespace foxit; using namespace common; using namespace pdf; using namespace foxit::common; // Assuming PDFPage page has been loaded and parsed. int width = static_cast<int>(page.GetWidth()); int height = static_cast<int>(page.GetHeight()); Matrix matrix = page.GetDisplayMatrix(0, 0, width, height, page.GetRotation()); // Prepare a bitmap for rendering. Bitmap bitmap(width, height, Bitmap::e_DIBArgb, NULL, 0); bitmap.FillRect(0xFFFFFFFF, NULL); Renderer render(bitmap, false); uint32 dwRenderFlag = Renderer::e_RenderAnnot | Renderer::e_RenderPage; render.SetRenderContentFlags(dwRenderFlag); render.StartRender(page, matrix, NULL); ...
附件 (Attachment)
在Foxit PDF SDK中,attachments指的是文档附件而不是文件附件注释。它允许将整个文件封装在文档中,就像电子邮件附件一样。Foxit PDF SDK提供应用程序APIs来访问附件,例如加载附件,获取附件,插入/删除附件,以及访问附件的属性。
Example:
如何从PDF文档中导出嵌入的附件文件,并将其另存为单个文件
#include "include/common/fs_common.h" #include "include/pdf/fs_pdfdoc.h" #include "include/pdf/fs_pdfattachments.h" using namespace foxit; using namespace common; using namespace pdf; using namespace foxit::common; // Assuming PDFDoc doc has been loaded. // Get information of attachments. Attachments attachments(doc); int count = attachments.GetCount(); for (int i = 0; i < count; i++) { WString key = attachments.GetKey(i); FileSpec file_spec = attachments.GetEmbeddedFile(key); if (!file_spec.IsEmpty()) { WString name = file_spec.GetFileName(); if (file_spec.IsEmbedded()) { WString exFilePath = "output_directory"; file_spec.ExportToFile(exFilePath); } } } ...
如何删除PDF文档中所有的附件文件
#include "include/common/fs_common.h" #include "include/pdf/fs_pdfdoc.h" #include "include/pdf/fs_pdfattachments.h" ... using namespace foxit; using namespace common; using namespace pdf; using namespace foxit::common; // Assuming PDFDoc doc has been loaded. // Get information of attachments. Attachments attachments(doc); int count = attachments.GetCount(); for (int i = 0; i < count; i++) { WString key = attachments.GetKey(i); attachment.RemoveEmbeddedFile(&key); } ...
文本页面 (Text Page)
Foxit PDF SDK提供APIs来提取,选择,搜索和检索PDF文档中的文本。 PDF文本内容存储在与特定页面相关的TextPage对象中。TextPage类可用于获取PDF页面中文本的信息,例如单个字符,单个单词,指定字符范围或矩形内的文本内容等。它还可用于构造其他文本相关类的对象,用来对文本内容执行更多操作或从文本内容访问指定信息:
- 在PDF页面的文本内容中搜索文本,使用TextPage对象来构建TextSearch对象。
- 访问类似超文本链接的文本,使用TextPage对象来构建PageTextLinks对象。
Example:
如何从PDF页面中提取文本
#include "include/common/fs_common.h" #include "include/pdf/fs_pdfdoc.h" #include "include/pdf/fs_search.h" using namespace std; using namespace foxit; using namespace foxit::common; using foxit::common::Library; using namespace pdf; ... // Assuming PDFPage page has been loaded and parsed. // Get the text page object. TextPage text_page(page); int count = text_page.GetCharCount(); if (count > 0) { WString text = text_page.GetChars(); String s_text = text.UTF8Encode(); fwrite((const char*)s_text, sizeof(char), s_text.GetLength(), file); } ...
如何在PDF文档中获取矩形区域中的文本
#include "include/common/fs_common.h" #include "include/pdf/fs_pdfdoc.h" #include "include/pdf/fs_search.h" using namespace foxit; using namespace foxit::common; using foxit::common::Library; using namespace pdf; ... RectF rect; rect.left = 90; rect.right = 450; rect.top = 595; rect.bottom = 580; TextPage textPage = new TextPage (&page, TextPage::e_ParseTextNormal); textPage.GetTextInRect(&rect); ...
文本搜索 (Text Search)
Foxit PDF SDK 提供APIs来搜索PDF文档、XFA文档、文本页面或者PDF注释中的文本。它提供了文本搜索和获取搜索结果的函数:
- 指定搜索模式和选项,使用TextSearch::SetPattern、TextSearch::SetStartPage (仅对PDF文档中的文本搜索有用)、TextSearch::SetEndPage (仅对PDF文档中的文本搜索有用)、和TextSearch::SetSearchFlags接口。
- 进行搜索,使用TextSearch::FindNext和TextSearch::FindPrev接口。
- 获取搜索结果,使用TextSearch::GetMatchXXX() 接口。
Example:
如何在PDF文档中搜索指定的文本
#include "include/common/fs_common.h" #include "include/pdf/fs_pdfdoc.h" #include "include/pdf/fs_pdfpage.h" #include "include/pdf/fs_search.h" using namespace foxit; using namespace foxit::common; using foxit::common::Library; using namespace pdf; ... // Assuming PDFDoc doc has been loaded. // Search for all pages of doc. TextSearch search(doc, NULL); int start_index = 0, end_index = doc.GetPageCount() - 1; search.SetStartPage(start_index); search.SetEndPage(end_index); WString pattern = L"Foxit"; search.SetPattern(pattern); foxit::uint32 flags = TextSearch::e_SearchNormal; search.SetSearchFlags(flags); ... int match_count = 0; while (search.FindNext()) { RectFArray rect_array = search.GetMatchRects(); match_count ++; } ...
文本链接 (Text Link)
在PDF页面中,指向网站、网络资源以及电子邮件地址的超链接文本和普通文本一样。在处理文本链接之前,用户应首先调用PageTextLinks::GetTextLink 接口来获取一个textlink对象。
Example:
如何检索PDF页面中的超链接
#include "include/common/fs_common.h" #include "include/pdf/fs_pdfdoc.h" #include "include/pdf/fs_pdfpage.h" #include "include/pdf/fs_search.h" using namespace foxit; using namespace foxit::common; using foxit::common::Library; using namespace pdf; ... // Assuming PDFPage page has been loaded and parsed. // Get the text page object. TextPage text_page(page); PageTextLinks pageTextLink(text_page); TextLink textLink = pageTextLink.GetTextLink(index); String strURL = textLink.GetURI(); ...
书签 (Bookmark)
Foxit PDF SDK提供了名为书签的导航工具,允许用户在PDF文档中快速定位和链接他们感兴趣的部分。PDF书签也称为大纲 (outline) ,每个书签包含一个目标位置或动作来描述它链接到的位置。它是一个树形的层次结构,因此在访问bookmark 树之前,必须首先调用接口pdf::PDFDoc::GetRootBookmark以获取整个bookmark树的根节点。这里,”书签根节点” 是一个抽象对象,它只有一些子节点,没有兄弟节点, 也没有任何数据 (包括bookmark数据,目标位置数据和动作数据)。因为它没有任何数据,因此无法在应用程序界面上显示,能够调用的接口只有Bookmark::GetFirstChild。
在获取书签根节点后,就可以调用以下的接口去访问其他的书签:
- 访问parent bookmark,使用Bookmark::GetParent接口。
- 访问第一个child bookmark,使用Bookmark::GetFirstChild接口。
- 访问next sibling bookmark,使用Bookmark::GetNextSibling接口。
- 插入一个新的bookmark,使用Bookmark::Insert接口。
- 移动一个bookmark,使用Bookmark::MoveTo接口。
Example:
如何遍历PDF文档中所有的书签
#include "include/common/fs_common.h" #include "include/pdf/fs_filespec.h" #include "include/pdf/fs_bookmark.h" #include "include/pdf/fs_pdfdoc.h" #include "include/pdf/fs_pdfpage.h" using namespace foxit; using namespace foxit::common; using foxit::common::Library; using namespace pdf; ... // Assuming PDFDoc doc has been loaded. Bookmark root = doc.GetRootBookmark(); Bookmark first_bookmark = root.GetFirstChild(); if (first_bookmark != null) { TraverseBookmark(first_bookmark, 0); } Private void TraverseBookmark(Bookmark root, int iLevel) { if (root != null) { Bookmark child = root.GetFirstChild(); while (child != null) { TraverseBookmark(child, iLevel + 1); child = child.GetNextSibling(); } } } ...
表单 (AcroForm)
PDF目前支持两种类型的表单,用于以交互方式收集用户信息:AcroForms 和 XFA 表单。Acroforms是基于PDF框架的原始的可填写表单。Foxit PDF SDK提供了以编程方式查看和编辑表单域的APIs。在PDF文档中,表单域通常用于收集数据。Form类提供了APIs用来获取表单域或表单控件,导入/导出表单数据,以及其他功能,例如:
- 获取表单域,使用Form::GetFieldCount和Form::GetField接口。
- 获取PDF页面中的表单控件,使用Form::GetControlCount和Form::GetControl接口。
- 从XML文件导入表单数据,使用Form::ImportFromXML接口;导出表单数据到XML文件,使用Form::ExportToXML接口。
- 获取form filler对象,使用Form::GetFormFiller接口。
从FDF/XFDF文件中导入表单数据,或者导出数据到FDF/XFDF文件,请参考pdf::PDFDoc::ImportFromFDF 和 pdf::PDFDoc::ExportToFDF 接口。
Example:
如何加载PDF中的表单
#include "include/common/fs_common.h" #include "include/pdf/fs_pdfdoc.h" #include "include/pdf/fs_pdfform.h" using namespace foxit; using namespace pdf; using namespace interform; ... // Assuming PDFDoc doc has been loaded. bool hasForm = doc.HasForm(); if(hasForm) Form form(doc); ...
如何获取表单域个数以及获取/设置其属性
#include "include/common/fs_common.h" #include "include/pdf/fs_pdfdoc.h" #include "include/pdf/interform/fs_pdfform.h" using namespace foxit; using namespace pdf; using namespace interform; ... // Assuming PDFDoc doc has been loaded. Form form(doc); int countFields = form. GetFieldCount(NULL); for (int i = 0; i < nFieldCount; i++) { Field field = form.GetField(i, filter); Field::Type type = field.GetType(); WString org_alternateName = field.GetAlternateName(); field.SetAlternateName(L"signature"); }
如何将PDF中的表单数据导出到XML文件
#include "include/common/fs_common.h" #include "include/pdf/fs_pdfdoc.h" #include "include/pdf/interform/fs_pdfform.h" using namespace foxit; using namespace pdf; using namespace interform; ... // Assuming PDFDoc doc has been loaded. Form form(doc); ... form.ExportToXML(XMLFilePath); ...
如何通过XML文件导入表单数据到PDF
#include "include/common/fs_common.h" #include "include/pdf/fs_pdfdoc.h" #include "include/pdf/interform/fs_pdfform.h" using namespace foxit; using namespace pdf; using namespace interform; ... // Assuming PDFDoc doc has been loaded. Form form(doc); ... form.ImportFromXML(XMLFilePath); ...
XFA 表单
XFA (XML Forms Architecture) 表单 是基于XML的表单,封装在PDF内。XFA提供了基于模板的语法和一系列处理规则,允许用户构建交互式表单。简单的来说,基于模板的语法定义了用户数据的字段。
Foxit PDF SDK提供了APIs用来渲染XFA表单、填表、导出和导入表单数据。
备注:
- Foxit PDF SDK 提供了两个回调类foxit::addon::xfa::AppProviderCallback 和 foxit::addon::xfa::DocProviderCallback,分别将回调对象通过Library::RegisterXFAAppProviderCallback 以及 XFADoc 的构造函数注册到SDK中。这两个类中的所有函数都是纯虚函数,需要用户自己实现。
- 使用XFA form功能,请确保授权key文件中包含 ‘XFA’的权限。
Example:
如何加载XFADoc并且显示XFA交互式表单
#include "include/common/fs_common.h" #include "include/pdf/fs_pdfdoc.h" #include "include/pdf/interform/fs_pdfform.h" #include "include/addon/xfa/fs_xfa.h" using namespace foxit; using namespace foxit::common; using namespace pdf; using namespace foxit::addon::xfa; CFS_XFAAppHandler* pXFAAppHandler = new CFS_XFAAppHandler(); // implement from foxit::addon::xfa::AppProviderCallback Library::RegisterXFAAppProviderCallback(pXFAAppHandler); WString input_file = input_path + L"xfa_dynamic.pdf"; PDFDoc doc(input_file); ErrorCode error_code = doc.Load(); if (error_code != foxit::e_ErrSuccess) { return 1; } CFS_XFADocHandler* pXFADocHandler = new CFS_XFADocHandler(); // implement from foxit::addon::xfa::DocProviderCallback XFADoc xfa_doc(doc, pXFADocHandler); xfa_doc.StartLoad(NULL); ...
如何导出和导入XFA表单数据
#include "include/common/fs_common.h" #include "include/pdf/fs_pdfdoc.h" #include "include/pdf/interform/fs_pdfform.h" #include "include/addon/xfa/fs_xfa.h" using namespace foxit; using namespace foxit::common; using namespace pdf; using namespace foxit::addon::xfa; // Assuming FSXFADoc xfa_doc has been loaded. xfa_doc.ExportData(L"xfa_form.xml", XFADoc::e_ExportDataTypeXML); xfa_doc.ResetForm(); doc.SaveAs( L"xfa_dynamic_resetform.pdf"); xfa_doc.ImportData(L"xfa_form.xml"); doc.SaveAs(L"xfa_dynamic_importdata.pdf"); ...
填表 (Form Filler)
表单填写是用户常用的功能。其允许应用程序动态填写表单。填写表单的关键点是构建一些PDF SDK调用的回调函数。请通过当前 Form对象构建一个 Filler 对象,或者当已经构建该对象则可以通过函数 Form::GetFormFiller 获取 Filler 对象。一个交互式表单只有一个 form filler 对象。对于如何使用 form filler 来填写表单,您可以参考Windows平台包中 “\examples\view_demo” 文件夹下的 “view_demo“。
表单设计 (Form Design)
可填写的PDF表单 (AcroForm) 特别适用于各种应用程序表单设计,比如税收和其他政府部门表单。表单设计提供了APIs用来向PDF文件中添加表单域或者从PDF文档中移除表单域。从零开始设计一个表单允许开发人员创建他们需要的内容和布局的表单。
Example:
如何向PDF添加一个文本表单域
#include "include/common/fs_common.h" #include "include/pdf/fs_pdfdoc.h" #include "include/pdf/fs_pdfpage.h" #include "include/pdf/interform/fs_pdfform.h" using namespace foxit; using namespace pdf; using namespace interform; ... // Assuming PDFDoc doc has been loaded. // Assuming PDFPage page has been loaded and parsed. // Add text field Control control = form.AddControl(page, L"Text Field0", Field::e_TypeTextField, RectF(50, 600, 90, 640)); control.GetField().SetValue(L"3"); // Update text field's appearance. control.GetWidget().ResetAppearanceStream(); Control control1 = form.AddControl(page, L"Text Field1", Field::e_TypeTextField, RectF(100, 600, 140, 640)); control1.GetField().SetValue(L"123"); // Update text field's appearance. control1.GetWidget().ResetAppearanceStream(); ...
如何从PDF中移除一个文本表单域
#include "include/common/fs_common.h" #include "include/pdf/fs_pdfdoc.h" #include "include/pdf/fs_pdfpage.h" #include "include/pdf/interform/fs_pdfform.h" using namespace foxit; using namespace pdf; using namespace interform; ... // Assuming PDFDoc doc has been loaded. Form form(doc); const wchar_t* filter = L"text1"; int countFields = form.GetFieldCount(NULL); for (int i = 0; i < countFields; i++) { Field field = form.GetField(i, filter); if (field.GetType() == Field::e_TypeTextField) { form.RemoveField(field); } } ...
注释 (Annotations)
常规注释
一个annotation注释将对象(如注释,线条和高亮)与PDF文档页面上的位置相关联。其提供了一种通过鼠标和键盘与用户进行交互的方式。PDF包括如Table 3-1中列出的各种标准注释类型。在这些注释类型中,许多被定义为标记注释,因为它们主要用于标记PDF文档。标记注释中作为其自身一部分的文本,可以在其他符合标准的阅读器中以其他方式显示,例如在Comments面板。Table 3-1中的 “Markup” 列用来说明是否为标记注释。
Foxit PDF SDK支持PDF Reference [1] 中定义的大多数注释类型。Foxit PDF SDK提供了注释创建,属性访问和修改,外观设置和绘制的APIs。
Table 3-1
注释类型 | 描述 | Markup | SDK是否支持 |
Text(Note) | Text annotation | Yes | Yes |
Link | Link Annotation | No | Yes |
FreeText (TypeWritter/TextBox/Callout) |
Free text annotation | Yes | Yes |
Line | Line annotation | Yes | Yes |
Square | Square annotation | Yes | Yes |
Circle | Circle annotation | Yes | Yes |
Polygon | Polygon annotation | Yes | Yes |
PolyLine | PolyLine annotation | Yes | Yes |
Highlight | Highlight annotation | Yes | Yes |
Underline | Underline annotation | Yes | Yes |
Squiggly | Squiggly annotation | Yes | Yes |
StrikeOut | StrikeOut annotation | Yes | Yes |
Stamp | Stamp annotation | Yes | Yes |
Caret | Caret annotation | Yes | Yes |
Ink(pencil) | Ink annotation | Yes | Yes |
Popup | Popup annotation | No | Yes |
File Attachment | FileAttachment annotation | Yes | Yes |
Sound | Sound annotation | Yes | No |
Movie | Movie annotation | No | No |
Widget* | Widget annotation | No | Yes |
Screen | Screen annotation | No | Yes |
PrinterMark | PrinterMark annotation | No | No |
TrapNet | Trap network annotation | No | No |
Watermark* | Watermark annotation | No | Yes |
3D | 3D annotation | No | No |
Redact | Redact annotation | Yes | Yes |
备注:
- Widget和watermark注释类型是比较特殊的。’Annotation’ 模块不支持它们。Widget类型仅在 ‘form filler’ 模块中使用,watermark类型仅在 ‘watermark’ 模块中使用。
- Foxit SDK支持名为PSI (pressure sensitive ink,压感笔迹) 的自定义注释类型。在PDF Reference [1]中没有对该注释进行描述。通常,PSI用于手写签名功能,Foxit SDK将其视为PSI注释,以便其他PDF产品可以对其进行相关处理。
Example:
如何向PDF页面中添加link注释
#include "include/common/fs_common.h" #include "include/pdf/actions/fs_action.h" #include "include/pdf/annots/fs_annot.h" #include "include/pdf/fs_pdfdoc.h" #include "include/pdf/objects/fs_pdfobject.h" #include "include/pdf/fs_pdfpage.h" using namespace foxit; using namespace foxit::common; using namespace pdf; using namespace annots; // Assuming PDFPage page has been loaded and parsed. // Assuming the annnots in the page have been loaded. // Add link annotation. annots::Link link(page.AddAnnot( Annot::e_Link, RectF(350,350,380,400))); link.SetHighlightingMode(Annot::e_HighlightingToggle); ...
如何向PDF页面中添加highlight注释,并且设置相关属性
#include "include/common/fs_common.h" #include "include/pdf/actions/fs_action.h" #include "include/pdf/annots/fs_annot.h" #include "include/pdf/fs_pdfdoc.h" #include "include/pdf/objects/fs_pdfobject.h" #include "include/pdf/fs_pdfpage.h" using namespace foxit; using namespace foxit::common; using namespace pdf; using namespace annots; // Assuming PDFPage page has been loaded and parsed. // Assuming the annnots in the page have been loaded. // Add highlight annotation. annots::Highlight highlight(page.AddAnnot(Annot::e_Highlight,RectF(10,450,100,550))); highlight.SetContent(L"Highlight"); annots::QuadPoints quad_points; quad_points.first = PointF(10, 500); quad_points.second = PointF(90, 500); quad_points.third = PointF(10, 480); quad_points.fourth = PointF(90, 480); annots::QuadPointsArray quad_points_array; quad_points_array.Add(quad_points); highlight.SetQuadPoints(quad_points_array); highlight.SetSubject(L"Highlight"); highlight.SetTitle(L"Foxit SDK"); highlight.SetCreationDateTime(GetLocalDateTime()); highlight.SetModifiedDateTime(GetLocalDateTime()); highlight.SetUniqueID(WString::FromLocal(RandomUID())); // Appearance should be reset. highlight.ResetAppearanceStream(); ...
如何在创建markup注释时设置popup信息
#include "include/common/fs_common.h" #include "include/pdf/actions/fs_action.h" #include "include/pdf/annots/fs_annot.h" #include "include/pdf/fs_pdfdoc.h" #include "include/pdf/objects/fs_pdfobject.h" #include "include/pdf/fs_pdfpage.h" using namespace foxit; using namespace foxit::common; using namespace pdf; using namespace annots; // Assuming PDFPage page has been loaded and parsed. // Assuming the annnots in the page have been loaded. // Create a new note annot and set the properties for it. annots::Note note(page.AddAnnot(Annot::e_Note, RectF(10,350,50,400))); note.SetIconName("Comment"); note.SetSubject(L"Note"); note.SetTitle(L"Foxit SDK"); note.SetContent(L"Note annotation."); note.SetCreationDateTime(GetLocalDateTime()); note.SetModifiedDateTime(GetLocalDateTime()); note.SetUniqueID(WString::FromLocal(RandomUID())); // Create a new popup annot and set it to the new note annot. Popup popup(page.AddAnnot(Annot::e_Popup, RectF(300,450,500,550))); popup.SetBorderColor(0x00FF00); popup.SetOpenStatus(false); popup.SetModifiedDateTime(GetLocalDateTime()); note.SetPopup(popup); ...
如何使用设备坐标获取PDF中特定的注释
#include "include/common/fs_common.h" #include "include/pdf/actions/fs_action.h" #include "include/pdf/annots/fs_annot.h" #include "include/pdf/fs_pdfdoc.h" #include "include/pdf/objects/fs_pdfobject.h" #include "include/pdf/fs_pdfpage.h" using namespace foxit; using namespace foxit::common; using namespace pdf; using namespace annots; // Assuming PDFDoc doc has been loaded. // Assuming PDFPage page has been loaded and parsed. ... int width = static_cast<int>(page.GetWidth()); int height = static_cast<int>(page.GetHeight()); // Get page transformation matrix. Matrix displayMatrix= page.GetDisplayMatrix(0, 0, width, height, page.GetRotation()); int iAnnotCount = page.GetAnnotCount(); for(int i=0; i<iAnnotCount; i++) { Annot pAnnot = page.GetAnnot(i); ASSERT_FALSE(pAnnot.IsEmpty()); if (Annot::e_Popup == pAnnot.GetType()) continue; RectI annotRect = pAnnot.GetDeviceRect(false, displayMatrix); PointF pt; float tolerance = 1.0; // Get the same annot (pAnnot) using annotRect. pt.x = annotRect.left + tolerance; pt.y = (annotRect.top - annotRect.bottom)/2 + annotRect.bottom; Annot gAnnot = page.GetAnnotAtDevicePoint(pt, tolerance, &displayMatrix); ... }
如何提取text markup annotation中的文本内容
#include "include/common/fs_common.h" #include "include/pdf/fs_pdfdoc.h" #include "include/pdf/fs_pdfpage.h" #include "include/pdf/fs_search.h" using namespace std; using namespace foxit; using namespace foxit::common; using foxit::common::Library; using namespace pdf; ... // Assuming PDFDoc doc has been loaded. ... PDFPage page = doc.GetPage(0); // Parse the first page. page.StartParse(foxit::pdf::PDFPage::e_ParsePageNormal, NULL, false); int annot_count = page.GetAnnotCount(); TextPage text_page(page); for (int i = 0; i < annot_count; i++) { annots::Annot annot = page.GetAnnot(i); annots::TextMarkup text_markup(annot); if (!text_markup.IsEmpty()) { // Get the texts which intersect with a text markup annotation. WString text = text_page.GetTextUnderAnnot(text_markup); } }
从FDF文件导入注释或者将注释导出到FDF文件
在Foxit PDF SDK中,可以使用来自应用程序或者FDF文件的数据来创建注释。同时,PDF SDK支持将注释导出到FDF文件。
Example:
如何从FDF文件导入注释,并将其添加到PDF文档的首页
#include "include/common/fs_common.h" #include "include/pdf/actions/fs_action.h" #include "include/pdf/annots/fs_annot.h" #include "include/pdf/fs_pdfdoc.h" #include "include/pdf/objects/fs_pdfobject.h" #include "include/pdf/fs_pdfpage.h" using namespace std; using namespace foxit; using namespace foxit::common; using foxit::common::Library; using namespace pdf; using namespace annots; // Assuming PDFDoc doc has been loaded. ... FILE* file = NULL; #if defined(_WIN32) || defined(_WIN64) fopen_s(&file, (const char*)(const char*)String::FromUnicode(fdf_file), "rb+"); #else file = fopen((const char*)(const char*)String::FromUnicode(fdf_file), "rb+"); #endif fseek(file, 0, SEEK_END); size_t file_size = (size_t)ftell(file); char* buffer = (char*)malloc(file_size * sizeof(char)); memset(buffer, 0 , file_size); fseek(file, 0, SEEK_SET); fread(buffer, sizeof(char), file_size, file); fclose(file); fdf::FDFDoc fdf_doc(buffer, file_size); pdf_doc.ImportFromFDF(fdf_doc, PDFDoc::e_Annots);
图片转换 (Image Conversion)
Foxit PDF SDK提供了PDF文件和图片之间进行转换的APIs. 应用程序可以轻松地实现图片创建和图片转换等功能,支持如下的图片格式:BMP、TIFF、PNG、JPX、JPEG和 GIF。通过Foxit PDF SDK,PDF文件和支持的图片格式 (除了GIF) 之间可以互相转换。Foxit PDF SDK只支持将GIF图片转换为PDF文件。
Example:
如何将PDF页面转换为位图文件
#include "include/common/fs_common.h" #include "include/common/fs_image.h" #include "include/pdf/fs_pdfdoc.h" #include "include/pdf/fs_pdfpage.h" #include "include/common/fs_render.h" using namespace foxit; using namespace foxit::common; using namespace pdf; // Assuming PDFDoc doc has been loaded. ... // Get page count. int nPageCount = doc.GetPageCount(); for(int i=0;i<nPageCount;i++) { PDFPage page = doc.GetPage(i); // Parse page. page.StartParse(foxit::pdf::PDFPage::e_ParsePageNormal, NULL, false); int width = static_cast<int>(page.GetWidth()); int height = static_cast<int>(page.GetHeight()); Matrix matrix = page.GetDisplayMatrix(0, 0, width, height, page.GetRotation()); // Prepare a bitmap for rendering. Bitmap bitmap(width, height, foxit::common::Bitmap::e_DIBArgb, NULL, 0); bitmap.FillRect(0xFFFFFFFF, NULL); // Render page. Renderer render(bitmap, false); render.StartRender(page, matrix, NULL); image.AddFrame(bitmap); } ...
如何将图片转换为PDF文件
#include "include/common/fs_common.h" #include "include/common/fs_image.h" #include "include/pdf/fs_pdfdoc.h" #include "include/pdf/fs_pdfpage.h" using namespace foxit; using namespace foxit::common; using namespace pdf; Image image(input_file); int count = image.GetFrameCount(); PDFDoc doc; for (int i = 0; i < count; i++) { PDFPage page = doc.InsertPage(i); page.StartParse(foxit::pdf::PDFPage::e_ParsePageNormal, NULL, false); // Add image to page. page.AddImage(image, i, PointF(0, 0), page.GetWidth(), page.GetHeight(), true); } doc.SaveAs(output_file, PDFDoc::e_SaveFlagNoOriginal); ...
水印 (Watermark)
水印是一种PDF注释,广泛用于PDF文档。水印是文档上嵌入的可见叠加层,包含文本、logo或版权声明。水印的目的是对作者工作成果的保护,防止其未经授权而被他人使用。Foxit PDF SDK提供了允许应用程序创建、插入和删除水印的APIs。
Example:
如何创建一个文本水印,并将其插入到PDF文档的第一页
#include "include/common/fs_common.h" #include "include/pdf/fs_pdfdoc.h" #include "include/pdf/fs_pdfpage.h" #include "include/pdf/fs_watermark.h" using namespace foxit; using namespace foxit::common; using foxit::common::Library; using namespace pdf; ... // Assuming PDFDoc doc has been loaded. WatermarkSettings settings; settings.flags = WatermarkSettings::e_FlagASPageContents | WatermarkSettings::e_FlagOnTop; settings.offset_x = 0; settings.offset_y = 0; settings.opacity = 90; settings.position = common::e_PosTopRight; settings.rotation = -45.f; settings.scale_x = 1.f; settings.scale_y = 1.f; WatermarkTextProperties text_properties; text_properties.alignment = CommonDefines::e_AlignmentCenter; text_properties.color = 0xF68C21; text_properties.font_style = WatermarkTextProperties::e_FontStyleNormal; text_properties.line_space = 1; text_properties.font_size = 12.f; text_properties.font = Font(Font::e_StdIDTimesB); Watermark watermark(doc, L"Foxit PDF SDK\nwww.foxitsoftware.com", text_properties, settings); watermark.InsertToPage(doc.GetPage(0)); // Save document to file ...
如何创建一个图片水印,并将其插入到PDF文档的第一页
#include "include/common/fs_common.h" #include "include/pdf/fs_pdfdoc.h" #include "include/pdf/fs_pdfpage.h" #include "include/pdf/fs_watermark.h" using namespace foxit; using namespace foxit::common; using foxit::common::Library; using namespace pdf; ... // Assuming PDFDoc doc has been loaded. WatermarkSettings settings; settings.flags = WatermarkSettings::e_FlagASPageContents | WatermarkSettings::e_FlagOnTop; settings.offset_x = 0.f; settings.offset_y = 0.f; settings.opacity = 20; settings.position = common::e_PosCenter; settings.rotation = 0.0f; Image image(image_file); Bitmap bitmap = image.GetFrameBitmap(0); settings.scale_x = page.GetWidth() * 0.618f / bitmap.GetWidth(); settings.scale_y = settings.scale_x; Watermark watermark(doc, image, 0, settings); watermark.InsertToPage(doc.GetPage(0)); // Save document to file. ...
如何从PDF页面中删除所有的水印
#include "include/common/fs_common.h" #include "include/pdf/fs_pdfdoc.h" #include "include/pdf/fs_pdfpage.h" using namespace foxit; using namespace foxit::common; using foxit::common::Library; using namespace pdf; ... // Assuming PDFPage page has been loaded and parsed. ... page.RemoveAllWatermarks(); ... // Save document to file ...
条形码 (Barcode)
条形码用于表示与某个对象相关的数据,该数据可通过光学机器进行读取。最初的条形码系统是通过平行线间宽度和间距的不同来表示数据,可称为线性条形码或一维条形码(1D)。后来条形码逐渐演变成矩形、点、六边形等2D几何图案。虽然2D系统使用了一系列符号,但是它们通常也被称为条形码。条形码最初由特定的光学扫描器进行扫描,该光学扫面器被称为条形码读取器。后来扫描器和解释软件成功应用于桌面打印机和智能手机等设备。Foxit PDF SDK提供了从给定字符串生成条形码位图的应用程序。Table 3-2列出了Foxit PDF SDK支持的条形码类型。
Table 3-2
条形码类型 | Code39 | Code128 | EAN8 | UPCA | EAN13 | ITF | PDF417 | QR |
维度 | 1D | 1D | 1D | 1D | 1D | 1D | 2D | 2D |
Example:
如何从字符串生成条形码位图
#include "include/common/fs_common.h" #include "include/common/fs_barcode.h" using namespace foxit; using namespace foxit::common; using foxit::common::Library; ... // Strings used as barcode content. WString sz_code_string = L"TEST-SHEET"; // Barcode format types. Barcode::Format code_format = Barcode::e_FormatCode39; //Format error correction level of QR code. Barcode::QRErrorCorrectionLevel sz_qr_level = Barcode::e_QRCorrectionLevelLow; //Image names for the saved image files for QR code. WString bmp_qr_name = L"/QR_CODE_TestForBarcodeQrCode_L.bmp"; // Unit width for barcode in pixels, preferred value is 1-5 pixels. int unit_width = 2; // Unit height for barcode in pixels, preferred value is >= 20 pixels. int unit_height = 120; Barcode barcode; Bitmap bitmap = barcode.GenerateBitmap(sz_code_string, code_format, unit_width, unit_height, sz_qr_level); ...
安全 (Security)
Foxit PDF SDK提供了一系列加密和解密功能,以满足不同级别的文档安全保护。用户可以使用常规密码加密和证书驱动加密,或使用自己的安全处理机制来自定义安全实现。另外,Foxit PDF SDK还提供了APIs用于集成第三方安全技术 (Microsoft RMS),允许开发人员使用Microsoft RMS SDK加密和解密PDF文档。
备注:有关RMS加密和解密更详细的信息,请参考SDK包中 “\examples\simple_demo” 文件夹下的 “security” demo。
Example:
如何使用证书加密PDF文件
#include "include/pdf/fs_pdfdoc.h" #include "include/pdf/fs_security.h" using namespace foxit; using namespace foxit::common; using foxit::common::Library; using namespace pdf; ... PDFDoc doc(input_file); ErrorCode error_code = doc.Load(); if (error_code != foxit::e_ErrSuccess) { return false; } // Do encryption. StringArray envelopes; String initial_key; WString cert_file_path = input_path + L"foxit.cer"; if (!GetCertificateInfo((const char*)String::FromUnicode(cert_file_path), envelopes, initial_key, true, 16)) { return false; } CertificateSecurityHandler handler; CertificateEncryptData encrypt_data(true, SecurityHandler::e_CipherAES, envelopes); handler.Initialize(encrypt_data, initial_key); doc.SetSecurityHandler(handler); WString output_file = output_directory + L"certificate_encrypt.pdf"; doc.SaveAs(output_file, PDFDoc::e_SaveFlagNoOriginal); ...
如何使用Foxit DRM加密PDF文件
#include "include/pdf/fs_pdfdoc.h" #include "include/pdf/fs_security.h" using namespace foxit; using namespace foxit::common; using foxit::common::Library; using namespace pdf; ... PDFDoc doc(input_file); ErrorCode error_code = doc.Load(); if (error_code != foxit::e_ErrSuccess) { return false; } // Do encryption. DRMSecurityHandler handler = DRMSecurityHandler(); const char* file_id = "Simple-DRM-file-ID"; String initialize_key = "Simple-DRM-initialize-key"; DRMEncryptData encrypt_data(true, "Simple-DRM-filter", SecurityHandler::e_CipherAES, 16, true, 0xfffffffc); handler.Initialize(encrypt_data, file_id, initialize_key); doc.SetSecurityHandler(handler); WString output_file = output_directory + L"foxit_drm_encrypt.pdf"; doc.SaveAs(output_file, PDFDoc::e_SaveFlagNoOriginal); ...
页面重排 (Reflow)
页面重排功能是在页面大小发生变化时自动重排页面内容。该功能对那些需要在不同尺寸的输出设备上显示PDF文档的应用程序具有很大的利用价值。页面重排让应用程序无需考虑设备的不同尺寸。Foxit PDF SDK提供了APIs用来创建、渲染、释放Reflow页面,以及访问Reflow页面的属性。
Example:
如何创建一个Reflow页面,并将其渲染为位图文件
#include "include/common/fs_common.h" #include "include/pdf/fs_pdfdoc.h" #include "include/pdf/fs_pdfpage.h" #include "include/pdf/fs_reflowpage.h" #include "include/common/fs_render.h" using namespace foxit; using namespace foxit::common; using foxit::common::Library; using namespace pdf; ... // Assuming PDFDoc doc has been loaded. PDFPage page = doc.GetPage(0); // Parse PDF page. page.StartParse(foxit::pdf::PDFPage::e_ParsePageNormal, NULL, false); ReflowPage reflow_page(page); // Set some arguments used for parsing the reflow page. reflow_page.SetLineSpace(0); reflow_page.SetZoom(100); reflow_page.SetParseFlags(ReflowPage::e_Normal); // Parse reflow page. reflow_page.StartParse(NULL); // Get actual size of content of reflow page. The content size does not contain the margin. float content_width = reflow_page.GetContentWidth(); float content_height = reflow_page.GetContentHeight(); // Assuming Bitmap bitmap has been created. // Render reflow page. Renderer renderer(bitmap, false); foxit::Matrix matrix = reflow_page.GetDisplayMatrix(0, 0); renderer.StartRenderReflowPage(reflow_page, matrix, NULL); ...
异步加载PDF (Asynchronous PDF)
异步加载PDF技术是一种在文档加载需要花费很长时间时,可以不用加载整个文档就可以对PDF页面进行访问的方法。该方法专为访问互联网上的PDF文件而设计。使用异步PDF技术,应用程序无需等待下载整个PDF文件就可以对其进行访问,可以打开任何已经下载加载的PDF页面。该技术为Web阅读类的应用程序提供了一种方便和有效的方式。关于如何使用异步模式打开和解析PDF页面,请参考SDK包中 “\examples\simple_demo” 文件夹下的 “async_load” demo。
压感笔迹 (Pressure Sensitive Ink)
压感笔迹 (PSI) 是一种获取变化电力输出以响应作用于压力感应设备元件上的各种变化压力或受力的技术。在PDF中,PSI通常被用于手写签名,通过捕捉手指或触控笔的压力变化来收集PSI数据。PSI数据包含操作区域的坐标和画布,并用其来绘制PSI的外观。Foxit PDF SDK允许应用程序创建PSI、访问其属性、操作ink笔迹和画布、以及释放PSI。
Example:
如何创建PSI并设置相关属性
#include "include/common/fs_common.h" #include "include/pdf/fs_pdfdoc.h" #include "include/pdf/fs_pdfpage.h" #include "include/pdf/fs_psi.h" using namespace foxit; using namespace foxit::common; using foxit::common::Library; using namespace pdf; using namespace annots; PSI psi(480, 180, true); // Set ink diameter. psi.SetDiameter(9); // Set ink color. psi.SetColor(0x434236); // Set ink opacity. psi.SetOpacity(0.8f); // Add points to pressure sensitive ink. float x = 121.3043f; float y = 326.6846f; float pressure = 0.0966f; Path::PointType type = Path::e_TypeMoveTo; psi.AddPoint(PointF(x, y), type, pressure); ...
Wrapper
Wrapper为用户提供了一种保存与PDF文档相关的数据的方法。例如,在打开一个加密未授权的PDF文档,用户会看到错误信息提示其没有权限访问该文档。在这种情况下,使用wrapper,用户即使无法访问PDF中的内容,但仍然可以访问该文档的wrapper数据。Wrapper数据可用来提供信息给用户,比如文档的解密方法。
Example:
如何打开包含wrapper数据的PDF文档
#include "include/common/fs_common.h" #include "include/pdf/fs_pdfdoc.h" #include "include/pdf/fs_pdfpage.h" #include "include/common/fs_render.h" using namespace foxit; using namespace foxit::common; using foxit::common::Library; using namespace pdf; using namespace common::file; // file_name is PDF document which includes wrapper data. PDFDoc doc(file_name); ErrorCode code = doc.Load(); if (code != foxit::e_ErrSuccess) { return false; } if(!doc.IsWrapper()){ return false; } int64 offset = doc.GetWrapperOffset(); FileReader file_reader(offset); file_reader.LoadFile(String::FromUnicode(file_name)); ...
PDF对象 (PDF Objects)
PDF中有八种类型的对象:布尔对象、数字对象、字符串对象、名称对象、数组对象、字典对象、流对象和空对象。 PDF对象是文档级文档,与页面对象(见3.24)不同,每个页面对象都与特定的页面相关联。Foxit PDF SDK提供了APIs用来创建、修改、检索和删除文档中的这些对象。
Example:
如何从目录字典中删除指定的属性
#include "include/common/fs_common.h" #include "include/pdf/fs_pdfdoc.h" #include "include/pdf/objects/fs_pdfobject.h" using namespace foxit; using namespace foxit::common; using foxit::common::Library; using namespace pdf; using namespace objects; ... // Assuming PDFDoc doc has been loaded. PDFDictionary* catalog = doc.GetCatalog(); if (NULL == catalog) return; const char* key_strings[] = { "Type", "Boolean", "Name", "String", "Array", "Dict"}; int count = sizeof(key_strings)/sizeof(key_strings[0]); for (int i = 0; i < count; i ++) { if (catalog->HasKey(key_strings[i])) catalog->RemoveAt(key_strings[i]); } ...
页面对象 (Page Object)
页面对象可以帮助对PDF对象 (关于PDF对象更详细的介绍,见3.23) 知识了解有限的开发人员能够处理PDF文档中的文本、路径、图像和画布等对象。Foxit PDF SDK提供APIs用以在页面中添加和删除PDF对象并设置特定属性。使用页面对象,用户可以从对象内容创建PDF页面。页面对象的其他可能用法包括向PDF文档添加页眉和页脚,向每个页面添加图片logo,或者根据需要生成PDF模板。
Example:
如何在PDF页面中创建一个文本对象
#include "include/common/fs_common.h" #include "include/pdf/graphics/fs_pdfgraphicsobject.h" #include "include/pdf/fs_pdfdoc.h" #include "include/pdf/fs_pdfpage.h" using namespace foxit; using namespace foxit::common; using foxit::common::Library; using namespace pdf; using namespace graphics; ... // Assuming PDFPage page has been loaded and parsed. POSITION position = page.GetLastGraphicsObjectPosition(GraphicsObject::e_TypeText); TextObject* text_object = TextObject::Create(); text_object->SetFillColor(0xFFFF7F00); // Prepare text state. TextState state; state.font_size = 80.0f; state.font = Font(L"Simsun", Font::e_StylesSmallCap, Font::e_CharsetGB2312, 0); state.textmode = TextState::e_ModeFill; text_object->SetTextState(page, state, false, 750); // Set text. text_object->SetText(L"Foxit Software"); POSITION last_position = page.InsertGraphicsObject(position, text_object); ...
如何向PDF页面中插入一个图片logo
#include "include/common/fs_common.h" #include "include/pdf/graphics/fs_pdfgraphicsobject.h" #include "include/pdf/fs_pdfdoc.h" #include "include/pdf/fs_pdfpage.h" using namespace foxit; using namespace foxit::common; using foxit::common::Library; using namespace pdf; using namespace graphics; ... //Assuming PDFPage page has been loaded and parsed. POSITION position = page.GetLastGraphicsObjectPosition(GraphicsObject::e_TypeImage); Image image(image_file); ImageObject* image_object = ImageObject::Create(page.GetDocument()); image_object->SetImage(image, 0); float width = static_cast<float>(image.GetWidth()); float height = static_cast<float>(image.GetHeight()); float page_width = page.GetWidth(); float page_height = page.GetHeight(); // Please notice the matrix value. image_object->SetMatrix(Matrix(width, 0, 0, height, (page_width - width) / 2.0f, (page_height - height) / 2.0f)); page.InsertGraphicsObject(position, image_object); page.GenerateContent(); ...
标记内容 (Marked content)
在PDF文档中,可以将一部分内容标记为标记内容元素。标记内容功能有助于管理PDF文档的逻辑结构信息并且可以用于生成加标记的PDF (tagged PDF) 。加标记的PDF具有标准的结构类型和属性,有助于提取和再利用页面内容。有关标记内容的更多详细信息,请参阅PDF reference 1.7 [1] 的第10.5章。
Example:
如何获取页面中的标记内容以及tag名称
#include "include/common/fs_common.h" #include "include/pdf/fs_pdfdoc.h" #include "include/pdf/fs_pdfpage.h" #include "include/common/fs_image.h" #include "include/pdf/graphics/fs_pdfgraphicsobject.h" #include "include/pdf/objects/fs_pdfobject.h" using namespace foxit; using namespace foxit::common; using foxit::common::Library; using namespace pdf; using namespace graphics; using namespace objects; ... // Assuming PDFPage page has been loaded and parsed. POSITION position = page.GetFirstGraphicsObjectPosition(GraphicsObject::e_TypeText); TextObject* text_obj = reinterpret_cast<TextObject*>(page.GetGraphicsObject(position)); MarkedContent* content = text_obj->GetMarkedContent(); int item_count = content->GetItemCount(); // Get marked content property for (int i = 0; i < item_count; i++) { String tag_name = content->GetItemTagName(i); int mcid = content->GetItemMCID(i); } ...
PDF 图层 (PDF Layer)
Foxit PDF SDK支持PDF图层,也称为可选内容组 (Optional Content Groups,OCG) 。用户可以选择性地查看或隐藏多图层PDF文档的不同层中的内容。多图层广泛用于许多应用领域,如CAD制图、地图、分层艺术品以及多语言文档等。
在Foxit PDF SDK中,PDF图层与图层节点相关联。要获取图层节点,用户应首先构建PDF LayerTree对象,然后调用函数LayerTree::GetRootNode以获取整个图层树的根图层节点。另外,您可以从根图层节点开始枚举图层树中的所有节点。Foxit PDF SDK提供APIs用来获取/设置图层数据,查看或隐藏不同图层中的内容,设置图层名称,添加或删除图层,以及编辑图层。
Example:
如何创建一个PDF图层
#include "include/common/fs_common.h" #include "include/pdf/fs_pdfdoc.h" #include "include/common/fs_render.h" #include "include/pdf/fs_pdflayer.h" using namespace foxit; using namespace pdf; ... // Assuming PDFDoc doc has been loaded. LayerTree layertree(doc); LayerNode root = layertree.GetRootNode(); if (root.IsEmpty()) { printf("No layer information!\r\n"); return ; } ...
如何设置所有图层节点的信息
#include "include/common/fs_common.h" #include "include/pdf/fs_pdfdoc.h" #include "include/common/fs_render.h" #include "include/pdf/fs_pdflayer.h" using namespace foxit; using namespace foxit::common; using foxit::common::Library; using namespace pdf; ... // Assuming PDFDoc doc has been loaded. void SetAllLayerNodesInformation(LayerNode layer_node) { if (layer_node.HasLayer()) { layer_node.SetDefaultVisible(true); layer_node.SetExportUsage(LayerTree::e_StateUndefined); layer_node.SetViewUsage(LayerTree::e_StateOFF); LayerPrintData print_data("subtype_print", LayerTree::e_StateON); layer_node.SetPrintUsage(print_data); LayerZoomData zoom_data(1, 10); layer_node.SetZoomUsage(zoom_data); WString new_name = WString(L"[View_OFF_Print_ON_Export_Undefined]") + layer_node.GetName(); layer_node.SetName(new_name); } int count = layer_node.GetChildrenCount(); for (int i = 0; i < count; i++) { LayerNode child = layer_node.GetChild(i); SetAllLayerNodesInformation(child); } } LayerTree layertree(doc); LayerNode root = layertree.GetRootNode(); SetAllLayerNodesInformation(root); ...
如何编辑图层树
#include "include/common/fs_common.h" #include "include/pdf/fs_pdfdoc.h" #include "include/common/fs_render.h" #include "include/pdf/fs_pdflayer.h" using namespace foxit; using namespace foxit::common; using namespace pdf; ... // Assuming PDFDoc doc has been loaded. // edit layer tree PDFDoc doc(input_file); error_code = doc.Load(); layertree = LayerTree(doc); root = layertree.GetRootNode(); int children_count = root.GetChildrenCount(); root.RemoveChild(children_count -1); LayerNode child = root.GetChild(children_count - 2); LayerNode child0 = root.GetChild(0); child.MoveTo(child0, 0); child.AddChild(0, L"AddedLayerNode", true); child.AddChild(0, L"AddedNode", false);
签名 (Signature)
PDF签名可用于创建和签署PDF文档的数字签名,从而保护文档内容的安全性并避免文档被恶意篡改。它可以让接收者确保其收到的文档是由签名者发送的,并且文档内容是完整和未被经篡的。Foxit PDF SDK提供APIs用来创建数字签名,验证签名的有效性,删除现有的数字签名,获取和设置数字签名的属性,显示签名和自定义签名表单域的外观。
备注:Foxit PDF SDK提供了默认签名回调函数,支持如下两种类型的signature filter 和 subfilter:
(1) filter: Adobe.PPKLite subfilter: adbe.pkcs7.detached
(2) filter: Adobe.PPKLite subfilter: adbe.pkcs7.sha1
如果您使用以上任意一种的signature filter 和 subfilter,您可以直接签名PDF文档和验证签名的有效性,而不需要注册自定义回调函数。
Example:
如何对PDF文档进行签名
#include "include/pdf/annots/fs_annot.h" #include "include/common/fs_image.h" #include "include/pdf/fs_pdfdoc.h" #include "include/pdf/fs_pdfpage.h" #include "include/pdf/fs_signature.h" using namespace foxit; using namespace foxit::common; using foxit::common::Library; using namespace pdf; using namespace objects; using namespace file; // AdobePPKLiteSignature const char* filter = "Adobe.PPKLite"; const char* sub_filter = "adbe.pkcs7.detached"; if (!use_default) { InitializeOpenssl(); sub_filter = "adbe.pkcs7.sha1"; SignatureCallbackImpl* sig_callback = new SignatureCallbackImpl(sub_filter); Library::RegisterSignatureCallback(filter, sub_filter, sig_callback); } printf("Use signature callback object for filter \"%s\" and sub-filter \"%s\"\r\n", filter, sub_filter); PDFPage pdf_page = pdf_doc.GetPage(0); // Add a new signature to the first page. Signature new_signature = AddSiganture(pdf_page, sub_filter); // Set filter and subfilter for the new signature. new_signature.SetFilter(filter); new_signature.SetSubFilter(sub_filter); bool is_signed = new_signature.IsSigned(); uint32 sig_state = new_signature.GetState(); printf("[Before signing] Signed?:%s\t State:%s\r\n", is_signed? "true" : "false", TransformSignatureStateToString(sig_state).c_str()); // Sign the new signature. WString signed_pdf_path = output_directory + L"signed_newsignature.pdf"; if (use_default) signed_pdf_path = output_directory + L"signed_newsignature_default_handler.pdf"; WString cert_file_path = input_path + L"foxit_all.pfx"; WString cert_file_password = L"123456"; // Cert file path will be passed back to application through callback function FSSignatureCallback::Sign(). // In this demo, the cert file path will be used for signing in callback function FSSignatureCallback::Sign(). new_signature.StartSign((const wchar_t*)cert_file_path, cert_file_password, Signature::e_DigestSHA1, (const wchar_t*)signed_pdf_path, NULL, NULL); printf("[Sign] Finished!\r\n"); is_signed = new_signature.IsSigned(); sig_state = new_signature.GetState(); printf("[After signing] Signed?:%s\tState:%s\r\n", is_signed? "true" : "false", TransformSignatureStateToString(sig_state).c_str()); // Open the signed document and verify the newly added signature (which is the last one). printf("Signed PDF file: %s\r\n", (const char*)String::FromUnicode(signed_pdf_path)); PDFDoc signed_pdf_doc((const wchar_t*)signed_pdf_path); ErrorCode error_code = signed_pdf_doc.Load(NULL); if (foxit::e_ErrSuccess !=error_code ) { printf("Fail to open the signed PDF file.\r\n"); return; } // Get the last signature which is just added and signed. int sig_count = signed_pdf_doc.GetSignatureCount(); Signature signed_signature = signed_pdf_doc.GetSignature(sig_count-1); // Verify the signature. signed_signature.StartVerify(NULL, NULL); printf("[Verify] Finished!\r\n"); is_signed = signed_signature.IsSigned(); sig_state = signed_signature.GetState(); printf("[After verifying] Signed?:%s\tState:%s\r\n", is_signed? "true" : "false", TransformSignatureStateToString(sig_state).c_str());
如何实现签名的回调函数
#include "include/pdf/annots/fs_annot.h" #include "include/common/fs_image.h" #include "include/pdf/fs_pdfdoc.h" #include "include/pdf/fs_pdfpage.h" #include "include/pdf/fs_signature.h" using namespace foxit; using namespace foxit::common; using foxit::common::Library; using namespace pdf; using namespace objects; using namespace file; // Implementation of pdf::SignatureCallback class SignatureCallbackImpl : public pdf::SignatureCallback { public: SignatureCallbackImpl(string subfilter) : sub_filter_(subfilter) , digest_context_(NULL) {} ~SignatureCallbackImpl(); virtual void Release() { delete this; } virtual bool StartCalcDigest(const ReaderCallback* file, const uint32* byte_range_array, uint32 size_of_array, const Signature& signature, const void* client_data); virtual Progressive::State ContinueCalcDigest(const void* client_data, const PauseCallback* pause); virtual String GetDigest(const void* client_data); virtual String Sign(const void* digest, uint32 digest_length, const wchar_t* cert_path, const WString& password, Signature::DigestAlgorithm digest_algorithm, void* client_data); virtual uint32 VerifySigState(const void* digest, uint32 digest_length, const void* signed_data, uint32 signed_data_len, void* client_data); virtual bool IsNeedPadData() {return false;} protected: bool GetTextFromFile(unsigned char *plainString); unsigned char* PKCS7Sign(const wchar_t* cert_file_path, String cert_file_password, String plain_text, int& signed_data_size); bool PKCS7VerifySignature(String signed_data, String plain_text); bool ParseP12File(const wchar_t* cert_file_path, String cert_file_password, EVP_PKEY** pkey, X509** x509, STACK_OF(X509)** ca); ASN1_INTEGER* CreateNonce(int bits); private: string sub_filter_; DigestContext* digest_context_; string cert_file_path_; string cert_file_password_; }; SignatureCallbackImpl::~SignatureCallbackImpl() { if (digest_context_) { delete digest_context_; digest_context_ = NULL; } } bool SignatureCallbackImpl::GetTextFromFile(unsigned char* file_buffer) { if (!digest_context_ || !digest_context_->GetFileReadCallback()) return false; ReaderCallback* file_read = digest_context_->GetFileReadCallback(); file_read->ReadBlock(file_buffer, digest_context_->GetByteRangeElement(0), digest_context_->GetByteRangeElement(1)); file_read->ReadBlock(file_buffer + (digest_context_->GetByteRangeElement(1)-digest_context_->GetByteRangeElement(0)), digest_context_->GetByteRangeElement(2), digest_context_->GetByteRangeElement(3)); return true; } bool SignatureCallbackImpl::StartCalcDigest(const ReaderCallback* file, const uint32* byte_range_array, uint32 size_of_array, const Signature& signature, const void* client_data) { if (digest_context_) { delete digest_context_; digest_context_ = NULL; } digest_context_ = new DigestContext(const_cast<ReaderCallback*>(file), byte_range_array, size_of_array); if(!SHA1_Init(&digest_context_->sha_ctx_)) { delete digest_context_; digest_context_ = NULL; return false; } return true; } Progressive::State SignatureCallbackImpl::ContinueCalcDigest(const void* client_data, const PauseCallback* pause) { if (!digest_context_) return Progressive::e_Error; uint32 file_length = digest_context_->GetByteRangeElement(1) + digest_context_->GetByteRangeElement(3); unsigned char* file_buffer = (unsigned char*)malloc(file_length); if (!file_buffer || !GetTextFromFile(file_buffer)) return Progressive::e_Error; SHA1_Update(&digest_context_->sha_ctx_, file_buffer, file_length); free(file_buffer); return Progressive::e_Finished; } String SignatureCallbackImpl::GetDigest(const void* client_data) { if (!digest_context_) return ""; unsigned char* md = reinterpret_cast<unsigned char*>(OPENSSL_malloc((SHA_DIGEST_LENGTH)*sizeof(unsigned char))); if (1 != SHA1_Final(md, &digest_context_->sha_ctx_)) return ""; String digest = String(reinterpret_cast<const char*>(md), SHA_DIGEST_LENGTH); OPENSSL_free(md); return digest; } String SignatureCallbackImpl::Sign(const void* digest, uint32 digest_length, const wchar_t* cert_path, const WString& password, Signature::DigestAlgorithm digest_algorithm, void* client_data) { if (!digest_context_) return ""; String plain_text; if ("adbe.pkcs7.sha1" == sub_filter_) { plain_text = String((const char*)digest, digest_length); } int signed_data_length = 0; unsigned char* signed_data_buffer = PKCS7Sign(cert_path, String::FromUnicode(password), plain_text, signed_data_length); if (!signed_data_buffer) return ""; String signed_data = String((const char*)signed_data_buffer, signed_data_length); free(signed_data_buffer); return signed_data; } uint32 SignatureCallbackImpl::VerifySigState(const void* digest, uint32 digest_length, const void* signed_data, uint32 signed_data_len, void* client_data) { // Usually, the content of a signature field is contain the certification of signer. // But we can't judge this certification is trusted. // For this example, the signer is ourself. So when using api PKCS7_verify to verify, // we pass NULL to it's parameter <i>certs</i>. // Meanwhile, if application should specify the certificates, we suggest pass flag PKCS7_NOINTERN to // api PKCS7_verify. if (!digest_context_) return Signature::e_StateVerifyErrorData; String plain_text; unsigned char* file_buffer = NULL; if ("adbe.pkcs7.sha1" == sub_filter_) { plain_text = String(reinterpret_cast<const char*>(digest), digest_length); } else { return Signature::e_StateUnknown; } String signed_data_str = String(reinterpret_cast<const char*>(signed_data), signed_data_len); bool ret = PKCS7VerifySignature(signed_data_str, plain_text); if (file_buffer) free(file_buffer); return ret ? Signature::e_StateVerifyNoChange : Signature::e_StateVerifyChange; } ASN1_INTEGER* SignatureCallbackImpl::CreateNonce(int bits) { unsigned char buf[20]; int len = (bits - 1) / 8 + 1; // Generating random byte sequence. if (len > (int)sizeof(buf)) { return NULL; } if (RAND_bytes(buf, len) <= 0) { return NULL; } // Find the first non-zero byte and creating ASN1_INTEGER object. int i = 0; for (i = 0; i < len && !buf[i]; ++i) ; ASN1_INTEGER* nonce = NULL; if (!(nonce = ASN1_INTEGER_new())) { ASN1_INTEGER_free(nonce); return NULL; } OPENSSL_free(nonce->data); // Allocate at least one byte. nonce->length = len - i; if (!(nonce->data = reinterpret_cast<unsigned char*>(OPENSSL_malloc(nonce->length + 1)))) { ASN1_INTEGER_free(nonce); return NULL; } memcpy(nonce->data, buf + i, nonce->length); return nonce; } bool SignatureCallbackImpl::ParseP12File(const wchar_t* cert_file_path, String cert_file_password, EVP_PKEY** pkey, X509** x509, STACK_OF(X509)** ca) { FILE* file = NULL; #if defined(_WIN32) || defined(_WIN64) _wfopen_s(&file, cert_file_path, L"rb"); #else file = fopen(String::FromUnicode(cert_file_path), "rb"); #endif // defined(_WIN32) || defined(_WIN64) if (!file) { return false; } PKCS12* pkcs12 = d2i_PKCS12_fp(file, NULL); fclose (file); if (!pkcs12) { return false; } if (!PKCS12_parse(pkcs12, (const char*)cert_file_password, pkey, x509, ca)) { return false; } PKCS12_free(pkcs12); if (!pkey) return false; return true; } unsigned char* SignatureCallbackImpl::PKCS7Sign(const wchar_t* cert_file_path, String cert_file_password, String plain_text, int& signed_data_size) { PKCS7* p7 = NULL; EVP_PKEY* pkey = NULL; X509* x509 = NULL; STACK_OF(X509)* ca = NULL; if(!ParseP12File(cert_file_path, cert_file_password, &pkey, &x509, &ca)) return NULL; p7 = PKCS7_new(); PKCS7_set_type(p7, NID_pkcs7_signed); PKCS7_content_new(p7, NID_pkcs7_data); // Application should not judge the sign algorithm with the content's length. // Here, just for convenient; if (plain_text.GetLength() > 32) PKCS7_ctrl(p7, PKCS7_OP_SET_DETACHED_SIGNATURE, 1, NULL); PKCS7_SIGNER_INFO* signer_info = PKCS7_add_signature(p7, x509, pkey, EVP_sha1()); PKCS7_add_certificate(p7, x509); for (int i = 0; i< sk_num(CHECKED_STACK_OF(X509,ca)); i++) PKCS7_add_certificate(p7, (X509*)sk_value(CHECKED_STACK_OF(X509,ca), i)); // Set source data to BIO. BIO* p7bio = PKCS7_dataInit(p7, NULL); BIO_write(p7bio, plain_text.GetBuffer(1), plain_text.GetLength()); PKCS7_dataFinal(p7, p7bio); FREE_CERT_KEY; BIO_free_all(p7bio); // Get signed data. unsigned long der_length = i2d_PKCS7(p7, NULL); unsigned char* der = reinterpret_cast<unsigned char*>(malloc(der_length)); memset(der, 0, der_length); unsigned char* der_temp = der; i2d_PKCS7(p7, &der_temp); PKCS7_free(p7); signed_data_size = der_length; return (unsigned char*)der; } bool SignatureCallbackImpl::PKCS7VerifySignature(String signed_data, String plain_text) { // Retain PKCS7 object from signed data. BIO* vin = BIO_new_mem_buf((void*)signed_data.GetBuffer(1), signed_data.GetLength()); PKCS7* p7 = d2i_PKCS7_bio(vin, NULL); STACK_OF(PKCS7_SIGNER_INFO) *sk = PKCS7_get_signer_info(p7); int sign_count = sk_PKCS7_SIGNER_INFO_num(sk); int length = 0; bool bSigAppr = false; unsigned char *p = NULL; for(int i=0;i<sign_count; i++) { PKCS7_SIGNER_INFO* sign_info = sk_PKCS7_SIGNER_INFO_value(sk,i); BIO *p7bio = BIO_new_mem_buf((void*)plain_text.GetBuffer(1), plain_text.GetLength()); X509 *x509= PKCS7_cert_from_signer_info(p7,sign_info); if(1 == PKCS7_verify(p7, NULL, NULL,p7bio, NULL, PKCS7_NOVERIFY)) bSigAppr = true; BIO_free(p7bio); } PKCS7_free(p7); BIO_free(vin); return bSigAppr; }
长期签名验证(LTV,Long term validation)
从7.0版本开始,Foxit PDF SDK提供了API接口进行长期签名验证,主要用于解决已经过期的签名的验证问题。LTV需要DSS(Document Security Store),其包含了签名的验证信息,以及需要文档时间戳签名DTS (Document Timestamp Signature),其是time stamp类型的signature。
为了支持LTV,Foxit PDF SDK提供了:
- 支持添加time stamp类型的signature,以及提供了sub filter “ETSI.RFC3161” 的默认签名回调。
- TimeStampServerMgr 和 TimeStampServer 类,用于time stamp的server设置和管理等。sub filter “ETSI.RFC3161” 的默认签名回调将会使用默认的time stamp server。
- LTVVerifier类,其提供了验证签名和向文档中添加DSS信息的功能。同时,也提供了LTVVerifier所需的一个基本默认的回调函数RevocationCallback。
以下仅以使用SDK默认的sub filter “ETSI.RFC3161” 签名回调及默认的RevocationCallback 为例来说明如何进行长期签名验证。有关更详细的信息,请参阅下载包中 “\examples\simple_demo”目录下的 “ltv” demo。
Example:
如何使用SDK默认的sub filter “ETSI.RFC3161” 签名回调及默认的RevocationCallback进行长期签名验证
#include "include/pdf/fs_pdfdoc.h" #include "include/pdf/fs_pdfpage.h" #include "include/pdf/fs_signature.h" #include "include/pdf/fs_ltvverifier.h" ... // Initialize time stamp server manager, add and set a default time stamp server, which will be used by default signature callback for time stamp signature. TimeStampServerMgr::Initialize(); TimeStampServer timestamp_server = TimeStampServerMgr::AddServer(server_name, server_url, server_username, server_password); TimeStampServerMgr::SetDefaultServer(timestamp_server); // Assume that "signed_pdf_path" represents a signed PDF document which contains signed signature. PDFDoc pdf_doc(signed_pdf_path); pdf_doc.StartLoad(); { // Use LTVVerifier to verify and add DSS. LTVVerifier ltv_verifier(pdf_doc, true, false, false, LTVVerifier::e_SignatureTSTTime); // Set verifying mode which is necessary. ltv_verifier.SetVerifyMode(LTVVerifier::e_VerifyModeETSI); SignatureVerifyResultArray sig_verify_result_array = ltv_verifier.Verify(); for (size_t i = 0; i < sig_verify_result_array.GetSize(); i++) { // ltv state would be e_LTVStateNotEnable here. SignatureVerifyResult::LTVState ltv_state = sig_verify_result_array.GetAt(i).GetLTVState(); if (sig_verify_result_array.GetAt(i).GetSignatureState() & Signature::e_StateVerifyValid) ltv_verifier.AddDSS(sig_verify_result_array.GetAt(i)); } } // Add a time stamp signature as DTS and sign it. "saved_ltv_pdf_path" represents the newly saved signed PDF file. PDFPage pdf_page = pdf_doc.GetPage(0); // The new time stamp signature will have default filter name "Adobe.PPKLite" and default subfilter name "ETSI.RFC3161". Signature timestamp_signature = pdf_page.AddSignature(RectF(), L"", Signature::e_SignatureTypeTimeStamp); Progressive sign_progressive = timestamp_signature.StartSign(L"", L"", Signature::e_DigestSHA256, saved_ltv_pdf_path); if (sign_progressive.GetRateOfProgress() != 100) sign_progressive.Continue(); // Then use LTVVeirfier to verify the new signed PDF file. PDFDoc check_pdf_doc(saved_ltv_pdf_path); check_pdf_doc.StartLoad(); { // Use LTVVeirfier to verify. LTVVerifier ltv_verifier(pdf_doc, true, false, false, LTVVerifier::e_SignatureTSTTime); // Set verifying mode which is necessary. ltv_verifier.SetVerifyMode(LTVVerifier::e_VerifyModeETSI); SignatureVerifyResultArray sig_verify_result_array = ltv_verifier.Verify(); for (size_t i = 0; i < sig_verify_result_array.GetSize(); i++) { // ltv state would be e_LTVStateEnable here. SignatureVerifyResult::LTVState ltv_state = sig_verify_result_array.GetAt(i).GetLTVState(); ... // User can get other information from SignatureVerifyResult. } } // Release time stamp server manager when everything is done. TimeStampServerMgr::Release();
PAdES
从7.0版本开始,Foxit PDF SDK支持PAdES (PDF Advanced Electronic Signature),其是CAdES签名在PDF中的应用。CAdES是高级数字签名的一种新标准,其默认subfilter是”ETSI.CAdES.detached”。PAdES 签名分为四个等级:B-B, B-T, B-LT, 和 B-LTA。
- B-B: 包含基本的必须出现的属性。
- B-T: 在B-B的基础上,包含文档时间戳或者签名时间戳,来为存在的签名提供可信的时间。
- B-LT: 在B-T的基础上,包含DSS/VRI,来提供证书和吊销信息。
- B-LTA: 在B-LT的基础上,为存在的吊销信息提供可信时间DTS。
Foxit PDF SDK提供了subfilter 为 “ETSI.CAdES.detached” 的默认签名回调,可用来签名和验证subfilter 为 “ETSI.CAdES.detached” 的签名。还提供了TimeStampServerMgr 和 TimeStampServer类,用于设置和管理time stamp server。subfilter “ETSI.CAdES.detached” 的默认签名回调将会使用默认的time stamp server。
Foxit PDF SDK 提供了从签名中获取PAdES不同等级的方法,应用层面也可以根据各个等级的要求来判定所属等级。有关如何在PDF文档中添加、签名、和验证PAdES签名的更详细信息,请参阅下载包中 “\examples\simple_demo”目录下的 “pades” demo。
PDF 行为 (PDF Action)
PDF Action代表PDF操作类的基类。Foxit PDF SDK提供了APIs用来创建一系列行为,并获取行为句柄,比如embedded goto action, JavaScript action, named action 和 launch action等。
Example:
如何创建一个URI 行为并将其插入到link注释
#include "include/common/fs_common.h" #include "include/pdf/actions/fs_action.h" #include "include/pdf/annots/fs_annot.h" #include "include/pdf/objects/fs_pdfobject.h" using namespace foxit; using namespace foxit::common; using namespace pdf; using namespace annots; // Assuming PDFPage page has been loaded and parsed. // Assuming the annnots in the page have been loaded. ... // Add link annotation annots::Link link(page.AddAnnot(Annot::e_Link, RectF(350,350,380,400))); link.SetHighlightingMode(Annot::e_HighlightingToggle); // Add action for link annotation using foxit::pdf::actions::Action; using foxit::pdf::actions::URIAction; URIAction action = (URIAction)Action::Create(page.GetDocument(), Action::e_TypeURI); action.SetTrackPositionFlag(true); action.SetURI("www.foxitsoftware.com"); link.SetAction(action); // Appearance should be reset. link.ResetAppearanceStream();
如何创建一个GoTo 行为并将其插入到link注释
#include "include/common/fs_common.h" #include "include/pdf/actions/fs_action.h" #include "include/pdf/annots/fs_annot.h" #include "include/pdf/fs_pdfdoc.h" #include "include/pdf/objects/fs_pdfobject.h" #include "include/pdf/fs_pdfpage.h" using namespace foxit; using namespace foxit::common; using namespace pdf; using namespace annots; // Assuming the PDFDoc doc has been loaded. // Assuming PDFPage page has been loaded and parsed. // Add link annotation annots::Link link(page.AddAnnot(Annot::e_Link, RectF(350,350,380,400))); link.SetHighlightingMode(Annot::e_HighlightingToggle); GotoAction action = Action::Create(page.GetDocument(), Action::e_TypeGoto); Destination newDest = Destination::CreateXYZ(page.GetDocument(), 0,0,0,0); action.SetDestination(newDest);
JavaScript
创建JavaScript是为了将Web页面的相关处理从服务器转移到基于Web的应用程序的客户端上。 Foxit PDF SDK JavaScript以JavaScript语言的形式实现新对象及其附带方法和属性的扩展。其使开发人员能够管理文档安全性,与数据库通信,处理文件附件以及操作PDF文件,因此其表现为交互式、web表单等。
JavaScript action是一种由JavaScript解释器编译和执行脚本的动作。类foxit::pdf::actions::JavaScriptAction派生自Action,并提供接口用来获取/设置JavaScript action数据。
在附录中可以查看Foxit PDF SDK 支持的JavaScript方法和属性列表。
Example:
如何添加文档级的JavaScript 动作
#include "include/pdf/actions/fs_action.h" #include "include/pdf/annots/fs_annot.h" using namespace foxit; using namespace pdf; using namespace annots; // Load Document doc. ... actions::JavaScriptAction javascript_action = (actions::JavaScriptAction)Action::Create(doc, Action::e_TypeJavaScript); javascipt_action.SetScript(L"app.alert(\"Hello Foxit \");"); AdditionalAction additional_act(doc); additional_act.SetAction(AdditionalAction::e_TriggerDocWillClose,javascipt_action); additional_act.DoJSAction(AdditionalAction::e_TriggerDocWillClose); ...
如何添加注释级的JavaScript 动作
#include "include/pdf/actions/fs_action.h" #include "include/pdf/annots/fs_annot.h" using namespace foxit; using namespace pdf; using namespace annots; // Load Document and get a widget annotation. ... actions::JavaScriptAction javascript_action = (actions::JavaScriptAction)Action::Create(page.GetDocument(), Action::e_TypeJavaScript); javascipt_action.SetScript(L"app.alert(\"Hello Foxit \");"); AdditionalAction additional_act(annot); additional_act.SetAction(AdditionalAction::e_TriggerAnnotMouseButtonPressed,javascipt_action); additional_act.DoJSAction(AdditionalAction::e_TriggerAnnotMouseButtonPressed); ...
如何添加表单级的JavaScript 动作
#include "include/pdf/actions/fs_action.h" #include "include/pdf/annots/fs_annot.h" #include "include/pdf/interform/fs_pdfform.h" using namespace foxit; using namespace pdf; using namespace annots; using namespace interform; // Load Document and get a form field. ... // Add text field. Control control = form.AddControl(page, L"Text Field0", Field::e_TypeTextField, RectF(50, 600, 90, 640)); control.GetField().SetValue(L"3"); // Update text field's appearance. control.GetWidget().ResetAppearanceStream(); Control control1 = form.AddControl(page, L"Text Field1", Field::e_TypeTextField, RectF(100, 600, 140, 640)); control1.GetField().SetValue(L"23"); // Update text field's appearance. control1.GetWidget().ResetAppearanceStream(); Control control2 = form.AddControl(page, L"Text Field2", Field::e_TypeTextField, RectF(150, 600, 190, 640)); actions::JavaScriptAction javascipt_action = (actions::JavaScriptAction)Action::Create(form.GetDocument(), Action::e_TypeJavaScript); javascipt_action.SetScript(L"AFSimple_Calculate(\"SUM\", new Array (\"Text Field0\", \"Text Field1\"));" ); Field field2 = control2.GetField(); AdditionalAction additional_act(field2); additional_act.SetAction(AdditionalAction::e_TriggerFieldRecalculateValue,javascipt_action); // Update text field's appearance. control2.GetWidget().ResetAppearanceStream(); ...
如何使用JavaScript向PDF页面添加一个新的注释
#include "include/pdf/actions/fs_action.h" #include "include/pdf/annots/fs_annot.h" // Load Document and get form field, construct a Form object and a Filler object. ... actions::JavaScriptAction javascipt_action = (actions::JavaScriptAction)Action::Create(form.GetDocument(), Action::e_TypeJavaScript); javascipt_action.SetScript(L"var annot = this.addAnnot({ page : 0, type : \"Square\", rect : [ 0, 0, 100, 100 ], name : \"UniqueID\", author : \"A. C. Robat\", contents : \"This section needs revision.\" });" ); AdditionalAction additional_act(field); additional_act.SetAction(AdditionalAction::e_TriggerAnnotCursorEnter,javascipt_action); additional_act.DoJSAction(AdditionalAction::e_TriggerAnnotCursorEnter); ...
如何使用JavaScript获取/设置注释的属性 (strokeColor, fillColor, readOnly, rect, type等)
#include "include/pdf/actions/fs_action.h" #include "include/pdf/annots/fs_annot.h" // Load Document and get form field, construct a Form object and a Filler object. ... // Get properties of annotations. actions::JavaScriptAction javascipt_action = (actions::JavaScriptAction)Action::Create(form.GetDocument(), Action::e_TypeJavaScript); javascipt_action.SetScript(L"var ann = this.getAnnot(0, \" UniqueID \"); if (ann != null) { console.println(\"Found it! type: \" + ann.type); console.println(\"readOnly: \" + ann.readOnly); console.println(\"strokeColor: \" + ann.strokeColor);console.println(\"fillColor: \" + ann.fillColor); console.println(\"rect: \" + ann.rect);}"); AdditionalAction additional_act(field); additional_act.SetAction(AdditionalAction::e_TriggerAnnotCursorEnter,javascipt_action); additional_act.DoJSAction(AdditionalAction::e_TriggerAnnotCursorEnter); // Set properties of annotations (only take strokeColor as an example). actions::JavaScriptAction javascipt_action1 = (actions::JavaScriptAction)Action::Create(form.GetDocument(), Action::e_TypeJavaScript); javascipt_action1.SetScript(L"var ann = this.getAnnot(0, \"UniqueID\");if (ann != null) { ann.strokeColor = color.blue; }"); AdditionalAction additional_act1(field1); additional_act1.SetAction(AdditionalAction::e_TriggerAnnotCursorEnter,javascipt_action1); additional_act1.DoJSAction(AdditionalAction::e_TriggerAnnotCursorEnter); ...
如何使用JavaScript销毁注释
#include "include/pdf/actions/fs_action.h" #include "include/pdf/annots/fs_annot.h" // Load Document and get form field, construct a Form object and a Filler object. ... actions::JavaScriptAction javascipt_action = (actions::JavaScriptAction)Action::Create(form.GetDocument(), Action::e_TypeJavaScript); javascipt_action.SetScript(L"var ann = this.getAnnot(0, \" UniqueID \"); if (ann != null) { ann.destroy(); } " ); AdditionalAction additional_act(field); additional_act.SetAction(AdditionalAction::e_TriggerAnnotCursorEnter,javascipt_action); additional_act.DoJSAction(AdditionalAction::e_TriggerAnnotCursorEnter); ...
密文 (Redaction)
密文是一种在保持文档布局的同时删除文档中敏感信息的功能。它可以帮助用户永久删除PDF文档中的可见文本和图片,以保护一些保密信息,如社会安全号码、信用卡信息、产品发布日期等等。
密文是一种标记注释,用于标记PDF文件的某些内容,标记的内容在注释被应用后会被删除。
执行密文,您可以使用如下的APIs:
- 调用foxit::addon::Redaction::Redaction创建一个redaction模块。如果在函数common::Library::Initialize中使用的license授权信息没有定义”Redaction”,则表示用户没有权限使用redaction相关的函数,并且构造函数会抛出foxit::e_ErrInvalidLicense异常。
- 然后调用foxit::addon::Redaction::MarkRedactAnnot创建一个redaction对象,对需要进行redaction的页面内容 (文本对象、图片对象和路径对象) 进行标记。
- 最后调用foxit::addon::Redaction::Apply 在标记区域应用redaction:永久删除标记区域的文本和图形。
备注:要使用redaction功能,请确保授权key文件中包含 ‘Redaction’ 模块。
Example:
如何将PDF文档第一页中的文本 “PDF” 设置为密文
#include "include/common/fs_common.h" #include "include/pdf/fs_pdfdoc.h" #include "include/pdf/fs_pdfpage.h" #include "include/pdf/fs_search.h" #include "include/addon/fs_redaction.h" #include "include/common/fs_render.h" using namespace foxit; using namespace common; using namespace addon; using namespace pdf; using namespace foxit::pdf::annots; ... Redaction redaction(doc); // Parse PDF page. PDFPage page = doc.GetPage(0); page.StartParse(foxit::pdf::PDFPage::e_ParsePageNormal, NULL, false); //Find Text Object to redact TextPage text_page(page); TextSearch text_search(text_page); text_search.SetPattern(L"PDF"); RectFArray rect_array; while(text_search.FindNext()) { rect_array.Append(text_search.GetMatchRects()); } if(rect_array.GetSize() > 0) { Redact redact = redaction.MarkRedactAnnot(page, rect_array); redact.ResetAppearanceStream(); doc.SaveAs(output_directory + L"AboutFoxit_redected_default.pdf"); // set border color to Green redact.SetBorderColor((long)0x00FF00); // set fill color to Blue redact.SetFillColor((long)0x0000FF); // set rollover fill color to Red redact.SetApplyFillColor((long)0xFF0000); redact.ResetAppearanceStream(); doc.SaveAs(output_directory + L"AboutFoxit_redected_setColor.pdf"); redact.SetOpacity((float)0.5); redact.ResetAppearanceStream(); doc.SaveAs(output_directory + L"AboutFoxit_redected_setOpacity.pdf"); if(redaction.Apply()) cout << "Redact page(0) succeed." << endl; else cout << "Redact page(0) failed." << endl; } doc.SaveAs(output_directory + L"AboutFoxit_redected_apply.pdf");
对比 (Comparison)
对比功能可以帮助用户查看两个版本的PDF文档之间的差异。Foxit PDF SDK提供APIs用以逐页比较两个PDF文档,并返回文档间的差异。目前,仅支持比较PDF文档中的文本,在之后的版本中,会支持更多的PDF元素。
差异可以定义为三种类型:删除、插入和替换。您可以将这些差异保存为PDF文件并标记为注释。
备注:要使用对比功能,请确保授权key文件中包含 ‘Comparison’ 模块。
Example:
如何对比两个PDF文档,并将差异保存到一个PDF文件中
#include "include/common/fs_common.h" #include "include/pdf/fs_pdfdoc.h" #include "include/pdf/fs_pdfpage.h" #include "include/pdf/fs_search.h" #include "include/addon/fs_compare.h" #include "include/common/fxcrt/fx_basic.h" using namespace foxit; using namespace common; using namespace addon; using namespace pdf; using namespace foxit::pdf::annots; ... PDFDoc base_doc("input_base_file"); ErrorCode error_code = base_doc.Load(); if (error_code != foxit::e_ErrSuccess) { return 1; } PDFDoc compared_doc("input_compared_file"); error_code = compared_doc.Load(); if (error_code != foxit::e_ErrSuccess) { return 1; } Comparison comparison(base_doc, compared_doc); // Start comparing. CompareResults result = comparison.DoCompare(0, 0, Comparison::e_CompareTypeText); CompareResultInfoArray& oldInfo = result.results_base_doc; CompareResultInfoArray& newInfo = result.results_compared_doc; int oldInfoSize = oldInfo.GetSize(); int newInfoSize = newInfo.GetSize(); PDFPage page = compared_doc.GetPage(0); for (int i=0; i<newInfoSize; i++) { const CompareResultInfo& item = newInfo.GetAt(i); CompareResultInfo::CompareResultType type = item.type; if (type == CompareResultInfo::e_CompareResultTypeDeleteText) { WString res_string; res_string.Format((FX_LPCWSTR)L"\"%S\"", (FX_LPCWSTR)item.diff_contents); // Add stamp to mark the "delete" type differences between the two documents. CreateDeleteTextStamp(page, item.rect_array, 0xff0000, res_string, L"Compare : Delete", L"Text"); } else if (type == CompareResultInfo::e_CompareResultTypeInsertText) { WString res_string; res_string.Format((FX_LPCWSTR)L"\"%S\"", (FX_LPCWSTR)item.diff_contents); // Highlight the "insert" type differences between the two documents. CreateHighlightRect(page, item.rect_array, 0x0000ff, res_string, L"Compare : Insert", L"Text"); } else if (type == CompareResultInfo::e_CompareResultTypeReplaceText) { WString res_string; res_string.Format((FX_LPCWSTR)L"[Old]: \"%S\"\r\n[New]: \"%S\"", (FX_LPCWSTR)oldInfo.GetAt(i).diff_contents, (FX_LPCWSTR)item.diff_contents); // Highlight the "replace" type differences between the two documents. CreateHighlightRect(page, item.rect_array, 0xe7651a, res_string, L"Compare : Replace", L"Text"); } } // Save the comparison result to a PDF file. compared_doc.SaveAs(output_directory + L"result.pdf");
备注:对于CreateDeleteTextStamp 和 CreateHighlightRect函数,请参考SDK包中“\examples\simple_demo”文件夹下的 “pdfcompare” demo。
光学字符识别 (OCR)
光学字符识别 (OCR) 能够将打印的文本图像翻译成机器可读的文本。OCR 普遍应用于将纸质文档扫描并创建成电子文档,也可用于现有的电子文档 (如PDF文档)。
本节将介绍如何使用Foxit PDF SDK for Windows设置OCR功能模块的使用环境。
系统需求
平台: Windows
开发语言: C++, Java, C#
License key: license key中包含 ‘OCR’ 模块的权限
SDK 版本: Foxit PDF SDK for Windows (C++, Java, C#) 6.4或更高版本
OCR模块的试用限制
对于试用版本,您需要注意如下的三条限制要求:
- 允许从第一次初始化OCREngine开始,连续试用30个自然日。
- 允许从第一次初始化OCREngine开始,对累计不超过5000页的PDF页面可以使用OCR。
- PDF页面会生成试用水印。此限制用于所有SDK模块。
OCR资源文件
请联系Foxit支持团队或者销售团队以获取OCR资源文件包。
下载并解压包后(比如,将其解压到一个名为 “ocr_addon”的目录),您可以看到OCR的资源文件如下:
- debugging_files: 用于调试OCR工程的资源文件。这些文件不能随应用程序发布。
- language_resource_CJK: CJK语言资源文件,包括Chinese-Simplified, Chinese-Traditional, Japanese, 和 Korean。
- language_resources_noCJK: 除去CJK以外的语言资源文件,包括Basque, Bulgarian, Catalan, Croatian, Czech, Danish, Dutch, English , Estonian, Faeroese, Finnish, French, Galician, German, Greek, Hebrew, Hungarian, Icelandic, Italian, Latvian(Lettish), Lithuanian, Macedonian, Maltese, Norwegian, Polish, Portuguese, Romanian, Russian, Serbian, Slovak, Slovenian, Spanish, Swedish, Thai, Turkish, Ukrainian。
- win32_lib: Win32的库资源文件。
- win64_lib: Win64的库资源文件。
- readme.txt: 介绍该目录下各个文件夹的作用,以及如何使用这些资源文件构建一个OCR的资源目录。
如何运行OCR demo
Foxit PDF SDK for Windows提供了一个OCR demo用来展示如何使用Foxit PDF SDK对PDF页面或者PDF文档进行OCR,该demo位于 “\examples\simple_demo\ocr” 文件夹下。
在Visual Studio中加载OCR demo
在Visual Studio中加载OCR demo,请选择以下两种方法中的一种:
- 在 “\examples\simple_demo” 文件夹下,根据您Visual Studio的版本双击 “simple_demo_vs2010.sln” 或者 “simple_demo_vs2015.sln” 或者 “simple_demo_vs2017.sln”。然后右击ocr demo,选择Set as StartUp Project。
- 在 “\examples\simple_demo\ocr” 文件夹下,根据您Visual Studio的版本双击”ocr_vs2010.vcxproj” 或者 “ocr_vs2015.vcxproj” 或者 “ocr_vs2017.vcxproj”。
构建一个OCR资源目录
在运行OCR demo之前,您需要首先构建一个OCR资源目录,然后将该目录的路径传给OCREngine::Initialize接口用来初始化OCR引擎。
构建一个OCR资源目录,请按照如下的步骤:
1)新建一个文件夹作为OCR的资源目录。比如,”D:/ocr_resources”。
2)根据要编译的平台架构,选择相应的库资源。
- 如果使用win32,则将 “ocr_addon/win32_lib” 文件夹下的所有文件拷贝到”D:/ocr_resources”。
- 如果使用win64,则将 “ocr_addon/win64_lib” 文件夹下的所有文件拷贝到”D:/ocr_resources”。
3)选择需要使用的语言资源。
- 如果只需要使用CIJ语言 (Chinese-Simplified, Chinese-Traditional, Japanese, 和 Korean),则将 “ocr_addon/language_resource_CJK” 文件夹下的所有文件拷贝到 “D:/ocr_resources”。
- 如果只需要使用除CIJ以外所支持的语言,则将 “ocr_addon/language_resources_noCJK” 文件下的所有文件拷贝到 “D:/ocr_resources”。
- 如果需要使用所有支持的语言,则将 “ocr_addon/language_resource_CJK” 和 “ocr_addon/language_resources_noCJK” 文件夹下所有的文件拷贝到”D:/ocr_resources”。
4)(可选) 如果需要调试demo,请根据平台架构,选择相应的调试资源文件。
- 如果使用win32,则将 “ocr_addon/debugging_files/win32” 文件夹下的文件拷贝到”D:/ocr_resources”。
- 如果使用win64,则将 “ocr_addon/debugging_files/win64” 文件夹下的文件拷贝到”D:/ocr_resources”。
备注:“ocr_addon/debugging_files” 文件夹下的文件只用于调试,请不要随产品发布。
配置demo
构建OCR资源目录后,在 “\examples\simple_demo\ocr\ocr.cpp” 文件中配置demo。
指定OCR资源目录
如下所示,添加OCR资源目录,用以初始化OCR引擎。
设置语言
设置需要被OCR引擎识别的语言。使用OCREngine::SetLanguages接口设置语言,默认是英语。
(可选) 设置 OCREngine日志文件
如果您添加调试资源文件到OCR资源目录,并且需要打印OCR引擎的整个日志记录,请取消注释OCREngine::SetLogFile 函数,如下所示:
运行demo
成功运行demo后,控制台将默认打印以下内容:
该demo将以四种不同的方式对默认的文档(“\examples\simple_demo\input_files\ocr\AboutFoxit_ocr.pdf”) 进行OCR,并在输出文件夹(“\examples\simple_demo\output_files\ocr”) 下输出四个不同的PDF文档:
- OCR Editable PDF – ocr_doc_editable.pdf
- OCR Searchable PDF – ocr_doc_searchable.pdf
- OCR Editable PDF Page – ocr_page_editable.pdf
- OCR Searchable PDF Page – ocr_page_searchable.pdf
Compliance
PDF Compliance
Foxit PDF SDK 支持PDF版本标准化转换,当前支持的版本有PDF 1.3, PDF 1.4, PDF 1.5, PDF 1.6 和 PDF 1.7。当转换到PDF 1.3版本时,如果源文档含有透明度的数据,则其会被转换到PDF 1.4版本而不是PDF 1.3版本 (PDF 1.3版本不支持透明度);如果源文档不含有任何透明度的数据,则会按预期转换到PDF 1.3版本。
PDF/A Compliance
PDF/A是一种ISO标准的PDF文件格式版本,用于电子文档的存档和长期保存。PDF/A与PDF的不同之处在于PDF/A禁用了PDF中不适合长期存档的特性,比如字体链接 (与嵌入字体相对)、加密、JavaScript、音频和视频等。
Foxit PDF SDK提供APIs用以将PDF转换为符合PDF/A标准的文档,或验证PDF是否符合PDF/A标准。支持的PDF/A标准包括PDF/A-1a、PDF/A-1b、PDF/A-2a、PDF/A-2b、PDF/A-2u、PDF/A-3a、PDF/A-3b、PDF/A-3u (ISO 19005- 1, 19005 -2 和 19005-3)。
本节将介绍如何设置相关环境以运行 ‘compliance’ demo。
系统需求
平台: Windows, Linux, Mac
开发语言: C++, Java, C#, Objective-C
License Key: license key中包含 ‘Compliance’ 模块的权限
SDK 版本: Foxit PDF SDK 6.4 或更高版本 (对于 PDF Compliance,则需要Foxit PDF SDK 7.1或更高版本)
Compliance 资源文件
请联系Foxit支持团队或者销售团队以获取Compliance资源文件包。
获取到资源文件包后,将其解压到所需目录 (比如,Windows解压到 “compliance/win“,Linux解压到 “compliance/linux“,Mac解压到 “compliance/mac“),然后您将看到Compliance的资源文件如下:
Windows平台:
Linux平台:
Mac平台:
如何运行compliance demo
Foxit PDF SDK提供了一个compliance demo用来展示如何使用Foxit PDF SDK验证PDF文档是否符合PDF/A标准,如何将PDF转换为符合PDF/A标准的文档,以及如何进行PDF版本标准化转换。该demo位于 “\examples\simple_demo\compliance” 文件夹下。
构建一个compliance资源目录
在运行compliance demo之前,您需要首先构建一个compliance资源目录,然后将该目录的路径传给ComplianceEngine::Initialize接口用来初始化compliance引擎。
Windows
在Windows平台构建一个compliance资源目录,请按照如下的步骤:
1)新建一个文件夹作为compliance的资源目录。比如,”D:/compliance _resources”。
2)将 “compliance/win” 目录下的 “ect“、”lang“、”var” 文件夹拷贝到”D:/compliance_resources”。
3)根据要编译的平台架构,选择相应的库资源。
- 如果使用win32,则将 “compliance/win/lib/x86” 文件夹下的所有文件拷贝到”D:/compliance_resources”。
- 如果使用win64,则将 “compliance/win/lib/x64” 文件夹下的所有文件拷贝到”D:/compliance_resources”。
例如,使用win32 平台架构,则compliance资源目录如下所示:
Linux
在Linux平台构建一个compliance资源目录,请按照如下的步骤:
1)新建一个文件夹作为compliance的资源目录。比如,”/root/Desktop/compliance_resources”。
2)将 “compliance/linux” 目录下的 “bin“、”ect“、”lang“、”var” 文件夹拷贝到”D:/compliance_resources”。
3)根据要编译的平台架构,选择相应的库资源。
- 如果使用linux32,则将 “compliance/linux/lib/x86” 文件夹下的所有文件拷贝到”/root/Desktop/compliance_resources”。
- 如果使用linux64,则将 “compliance/linux/lib/x64” 文件夹下的所有文件拷贝到”/root/Desktop/compliance_resources”。
例如,使用linux32平台架构,则compliance资源目录如下所示:
备注:对于Linux平台,在运行demo之前,您需要将compliance资源目录加入到系统共享库目录的查找路径中,否则ComplianceEngine::Initialize会执行失败。
例如,在运行demo之前,您可以通过命令 (export LD_LIBRARY_PATH=${LD_LIBRARY_PATH}: /root/Desktop/compliance_resources) 将compliance资源目录临时加入到LD_LIBRARY_PATH。
Mac
对于Mac平台,您可以直接使用 “compliance/mac” 资源文件夹作为compliance的资源目录。
配置demo
构建compliance资源目录后,在 “\examples\simple_demo\compliance\compliance.cpp” 文件中配置demo。
本节以Windows平台为例,展示如何在 “compliance.cpp” 文件中进行demo配置。对于Linux和Mac平台,其配置操作与Windows平台相同。
在Visual Studio中加载compliance demo (Windows),请选择以下两种方法中的一种:
- 在 “\examples\simple_demo” 文件夹下,根据您Visual Studio的版本双击 “simple_demo_vs2010.sln” 或者 “simple_demo_vs2015.sln” 或者 “simple_demo_vs2017.sln”。然后右击compliance demo,选择Set as StartUp Project。
- 在 “\examples\simple_demo\compliance” 文件夹下,根据您Visual Studio的版本双击”compliance _vs2010.vcxproj” 或者 “compliance_vs2015.vcxproj” 或者 “compliance_vs2017.vcxproj”。
指定compliance资源目录
在 “compliance.cpp” 文件中,如下所示,添加compliance资源目录,用以初始化compliance引擎。
备注:如果您已经购买了授权的license key (包含 ‘Compliance’ 模块的权限),Foxit销售团队会给您额外发送一个unlock code,用以初始化compliance引擎。
(可选) 为compliance engine设置语言
ComplianceEngine::SetLanguage 函数用来为compliance引擎设置语言。默认的语言是英语,所有支持的语言如下所示:
“Czech”, “Danish”, “Dutch”, “English”, “French”, “Finnish”, “German”, “Italian”, “Norwegian”, “Polish”, “Portuguese”, “Spanish”, “Swedish”, “Chinese-Simplified”, “Chinese-Traditional”, “Japanese”, “Korean”.
例如,取消注释 ComplianceEngine::SetLanguage 函数,并将语言设置为 “Chinese-Simplified”。
(可选) 为compliance 引擎设置临时文件夹
ComplianceEngine::SetTempFolderPath 函数用于设置一个临时文件夹以存储处理过程 (如验证或转换) 中生成的文件。如果此函数未设置自定义的临时文件夹,则将使用系统中默认的临时文件夹。
例如,取消注释 ComplianceEngine::SetTempFolderPath 函数,并将路径设置为”D:/compliance_temp” (必须为一个有效的路径)。
运行demo
成功运行demo后,控制台将默认打印以下内容:
该demo
- 验证PDF (“\examples\simple_demo\input_files\AboutFoxit.pdf”) 是否符合PDF/A-1a标准,并将此文档转换为符合PDF/A-1a标准的文档。
- 将PDF (“\examples\simple_demo\input_files\AF_ImageXObject_FormXObject.pdf”) 分别转换为PDF-1.4和PDF-1.7版本。
输出文档位于”\examples\simple_demo\output_files\compliance” 文件夹下。
优化 (Optimization)
优化功能可以通过压缩PDF文件中的图片、删除冗余数据,以及丢弃无用的用户数据等方式有效地减少PDF文件的大小,从而节省磁盘空间以及便于PDF文件的传输和存储。从7.0版本开始,优化模块提供了压缩PDF文件中彩色、灰度和黑白图像的方法,用于减少PDF文件的大小。
备注:要使用优化功能,请确保授权key文件中包含 ‘Optimization’模块。
Example:
如何通过压缩PDF文件中的彩色、灰度和黑白图像来减少PDF文件的大小
#include "include/common/fs_common.h" #include "include/pdf/fs_pdfdoc.h" #include "include/pdf/fs_pdfpage.h" #include "include/addon/optimization/fs_optimization.h" using namespace std; using namespace foxit; using namespace foxit::common; using namespace pdf; using namespace foxit::addon; PDFDoc doc("input_pdf_file"); ErrorCode error_code = doc.Load(); if (error_code != foxit::e_ErrSuccess) { printf("Error: %d\n", error_code); return 1; } Optimization_Pause pause(0,true); addon::optimization::OptimizerSettings settings; common::Progressive progressive = addon::optimization::Optimizer::Optimize(doc,settings,&pause); cout << "Optimized Start." << endl; Progressive::State progress_state = Progressive::e_ToBeContinued; while (Progressive::e_ToBeContinued == progress_state) { progress_state = progressive.Continue(); int percent = progressive.GetRateOfProgress(); String res_string; res_string.Format("Optimize progress percent: %d %",percent); std::cout<<res_string<<std::endl; } if(Progressive::e_Finished == progress_state) { doc.SaveAs(L"ImageCompression_Optimized.pdf", foxit::pdf::PDFDoc::e_SaveFlagRemoveRedundantObjects); } cout << "Optimized Finish." << endl;
HTML转PDF
对于一些内容比较多的HTML大文件或者网页,直接进行打印或者存档不太容易。Foxit PDF SDK提供API接口将在线网页或者本地HTML文件转换为PDF文件,比如发票,报告等,使其更容易打印或者存档。在HTML转PDF的过程中,Foxit PDF SDK支持在基于HTML的组织结构的基础上创建和添加PDF Tag。
本节主要介绍如何配置运行 ‘html2pdf’ demo所需的环境。
系统需求
平台: Windows, Mac
开发语言: C++, Java, C#, Objective-C
License Key: license key中包含 ‘Conversion’ 模块的权限
SDK版本: Foxit PDF SDK 7.0 或更高版本
HTML转PDF引擎资源
请联系Foxit支持团队或者销售团队以获取HTML转PDF引擎文件包。
当获取到引擎文件包后,将其解压到所需目录 (比如,Windows解压到 “D:/htmltopdf/win“,Mac解压到 “htmltopdf/mac“)。
如何运行html2pdf demo
Foxit PDF SDK提供了一个html2pdf demo用来展示如何使用Foxit PDF SDK将html文件转换为PDF文件。该demo位于 “\examples\simple_demo\html2pdf” 文件夹下。
配置demo
对于html2pdf demo,您可以在”\examples\simple_demo\html2pdf\html2pdf.cpp“文件中配置demo,或者您可以在命令行或者终端窗口中直接使用参数来对demo进行配置。以下将以Windows平台为例,在 “html2pdf.cpp” 文件中配置demo。对于Mac平台,其配置操作与Windows相同。
在Visual Studio中加载html2pdf demo (Windows),请选择以下两种方法中的一种:
- 在 “\examples\simple_demo” 文件夹下,根据您Visual Studio的版本双击 “simple_demo_vs2010.sln” 或者 “simple_demo_vs2015.sln” 或者 “simple_demo_vs2017.sln”。然后右击html2pdf demo,选择Set as StartUp Project。
- 在 “\examples\simple_demo\html2pdf” 文件夹下,根据您Visual Studio的版本双击”html2pdf_vs2010.vcxproj” 或者 “html2pdf_vs2015.vcxproj” 或者 “html2pdf_vs2017.vcxproj”。
指定html2pdf引擎资源目录
在 “html2pdf.cpp” 文件中,如下所示,添加 “fxhtml2pdf.exe” 引擎文件的路径,用以将html文件转换为PDF文件。
(可选) 指定cookies文件路径
添加cookies文件路径,该文件是从您需要转换的web页面中导出的。比如,
运行demo
运行demo (不带参数)
成功运行demo后,控制台将默认打印以下内容:
运行demo (带参数)
成功运行demo后,打开一个命令行窗口,导航到 “\examples\simple_demo\bin”,输入比如”html2pdf_dbg_x86_vs2010.exe –help” 命令查看如何使用参数来运行demo。
例如,将 “www.foxitsoftware.com” 网页转换为PDF文件,并且设置转换后的PDF页面的宽度为900 points,高度为300 points。
输出文档位于”\examples\simple_demo\output_files\html2pdf” 文件夹下。
参数描述
基本语法:
html2pdf <-html <the url or html path>> <-o <output pdf path>> <-engine <htmltopdf engine path>>
[-w <page width>] [-h <page height>] [-ml <margin left>] [-mr <margin right>]
[-mt <margin top>] [-mb <margin bottom>] [-r <page rotate degree>] [-mode <page mode>]
[-scale <whether scale page>] [-link <whether convert link>] [-tag <whether generate tag>]
[-cookies <cookies file path>] [-timeout <timeout>]
html2pdf –help
备注:
<> 必选
[ ] 可选
参数 | 描述 |
–help | 参数用法的帮助信息。 |
-html | URL或者html文件的路径。比如’-html www.foxitsoftware.com’。 |
-o | 输出PDF文件的路径。 |
-engine | “fxhtml2pdf.exe” 引擎文件的路径。 |
-w | 输出PDF文件页面的宽度,单位是points。 |
-h | 输出PDF文件页面的高度,单位是points。 |
-r | 输出PDF文件页面的旋转度。
|
-ml | 输出PDF文件页面的左边距。 |
-mr | 输出PDF文件页面的右边距。 |
-mt | 输出PDF文件页面的上边距。 |
-mb | 输出PDF文件页面的下边距。 |
-mode | 输出PDF文件的页面模式。
|
-scale | 是否缩放页面。
|
-link | 是否转换链接。
|
-tag | 是否生成tag.
|
-cookies | cookies文件路径,该文件是从您需要转换的web页面中导出的。 |
-timeout | 加载web页面的超时时间。 |
FAQ
1. 当在Visual Studio中编译demo时,如果遇到 “‘xcopy’ exited with code 9009” 错误,如何进行修复?
在Visual Studio编译demo时,如果遇到 “‘xcopy’ exited with code 9009” 错误,如下所示:
'xcopy ..\..\..\..\..\..\lib\gsdk_sn.txt ..\..\..\ /y > null xcopy ..\..\..\..\..\..\lib\gsdk_key.txt ..\..\..\ /y > null xcopy ..\..\..\..\..\..\lib\$(PlatformName)_vc10\fsdk.dll ..\..\..\ /y > null xcopy ..\..\..\..\..\..\lib\$(PlatformName)_vc10\fsdk_dotnet.dll ..\..\..\ /y > null' exited with code 9009
请注意检查以下几点:
1)检查在 “%SystemRoot%\System32” 目录下是否存在xcopy.exe,如果没有,请从其他机器上拷贝。
2)检查系统的PATH 环境变量是否设置正确。系统PATH环境变量必须包含“%SystemRoot%\System32;%SystemRoot%;”,如果xcopy 的环境变量设置是正确的,但仍然报错,可以尝试将xcopy的路径放置在最前面。因为可能是某些其他的环境变量出现拼写错误,从而导致后面的环境变量都失效了。请检查确认。
检查后,在命令行中输入xcopy命令,如果系统能够识别,关闭Visual Studio, 重启demo,上述错误应该就不会出现了。
2. 如何获取PDF文件中指定位置的文本对象,以及更改文本对象的内容?
使用Foxit PDF SDK获取PDF文件中指定位置的文本对象以及修改文本对象的内容,请按照如下的步骤:
1)打开一个PDF文件。
2)加载PDF页面并获取该页面中的页面对象。
3)使用PDFPage::GetGraphicsObjectAtPoint获取指定位置的文本对象。注意:使用页面对象获取矩形来查看文本对象的位置。
4)更改文本对象的内容并保存PDF文档。
以下是示例代码:
#include "include/common/fs_common.h" #include "include/pdf/fs_pdfdoc.h" #include "include/pdf/graphics/fs_pdfgraphicsobject.h" using namespace std; using namespace foxit; using namespace foxit::common; using foxit::common::Library; using namespace pdf; using namespace graphics; ... bool ChangeTextObjectContent() { try { WString input_file = input_path + L"AboutFoxit.pdf"; PDFDoc doc(input_file); ErrorCode error_code = doc.Load(); if (error_code != foxit::e_ErrSuccess) { printf("The Doc [%s] Error: %d\n", (const char*)String::FromUnicode(input_file), error_code); return false; } // Get original shading objects from the first PDF page. PDFPage original_page = doc.GetPage(0); original_page.StartParse(PDFPage::e_ParsePageNormal, NULL, false); foxit::PointF pointf; pointf.x = 92; pointf.y = 762; GraphicsObjectArray arr = original_page.GetGraphicsObjectsAtPoint (pointf, 10, GraphicsObject::e_TypeText ); for(int i = 0; i<arr.GetSize(); i++) { GraphicsObject* graphobj = arr.GetAt(i); TextObject * textobj = graphobj->GetTextObject(); textobj->SetText(L"Foxit Test"); } original_page.GenerateContent(); WString output_directory = output_path + L"graphics_objects/"; WString output_file = output_directory + L"After_revise.pdf"; doc.SaveAs(output_file, PDFDoc::e_SaveFlagNormal); }catch (const Exception& e) { cout << e.GetMessage() << endl; return false; } return true; }
3. 是否可以改变嵌入TIFF图像的DPI?
无法改变。PDF中图像的DPI是静态的,如果图像已经存在,Foxit PDF SDK没有更改图像DPI的功能。
解决办法是您可以使用第三方库来更改图像的DPI,然后将其添加到PDF中。
备注:Foxit PDF SDK提供了一个函数 “Image::SetDPIs”,可以用来设置图片对象的DPI属性,但是它仅支持使用Foxit PDF SDK创建或者使用 “Image::AddFrame”函数创建的图像,不支持JPX, GIF 和 TIF格式。
附录
Foxit PDF SDK支持的JavaScript列表
对象的属性或者方法
对象 | 属性/方法名称 | 支持的最低SDK版本 |
annotation properties | alignment | V7.0 |
author | V7.0 | |
contents | V7.0 | |
creationDate | V7.0 | |
fillColor | V7.0 | |
hidden | V7.0 | |
modDate | V7.0 | |
name | V7.0 | |
opacity | V7.0 | |
page | V7.0 | |
readOnly | V7.0 | |
rect | V7.0 | |
richContents | V7.1 | |
rotate | V7.0 | |
strokeColor | V7.0 | |
textSize | V7.0 | |
type | V7.0 | |
annotation method | destroy | V7.0 |
app properties | activeDocs | V4.0 |
calculate | V4.0 | |
formsVersion | V4.0 | |
fs | V4.0 | |
fullscreen | V4.0 | |
language | V4.2 | |
platform | V4.0 | |
runtimeHighlight | V4.0 | |
viewerType | V4.0 | |
viewerVariation | V4.0 | |
viewerVersion | V4.0 | |
app methods | alert | V4.0 |
beep | V4.0 | |
browseForDoc | V4.0 | |
clearInterval | V4.0 | |
clearTimeOut | V4.0 | |
launchURL | V4.0 | |
mailMsg | V4.0 | |
response | V4.0 | |
setInterval | V4.0 | |
setTimeOut | V4.0 | |
popUpMenu | V4.0 | |
color properties | black | V4.0 |
blue | V4.0 | |
cyan | V4.0 | |
dkGray | V4.0 | |
gray | V4.0 | |
green | V4.0 | |
ltGray | V4.0 | |
magenta | V4.0 | |
red | V4.0 | |
transparent | V4.0 | |
white | V4.0 | |
yellow | V4.0 | |
color methods | convert | V4.0 |
equal | V4.0 | |
document properties | author | V4.0 |
baseURL | V4.0 | |
bookmarkRoot | V7.0 | |
calculate | V4.0 | |
Collab | V4.0 | |
creationDate | V4.0 | |
creator | V4.0 | |
delay | V4.0 | |
dirty | V4.0 | |
documentFileName | V4.0 | |
external | V4.0 | |
filesize | V4.0 | |
icons | V4.0 | |
info | V4.0 | |
keywords | V4.0 | |
modDate | V4.0 | |
numFields | V4.0 | |
numPages | V4.0 | |
pageNum | V4.0 | |
path | V4.0 | |
producer | V4.0 | |
subject | V4.0 | |
title | V4.0 | |
document methods | addAnnot | V7.0 |
addField | V4.0 | |
addIcon | V4.0 | |
calculateNow | V4.0 | |
createDataObject | V6.2 | |
deletePages | V4.0 | |
exportAsFDF | V4.0 | |
flattenPages | V7.1 | |
getAnnot | V7.0 | |
getAnnots | V7.0 | |
getField | V4.0 | |
getIcon | V4.0 | |
getNthFieldName | V4.0 | |
getOCGs | V4.0 | |
getPageBox | V4.0 | |
getPageNthWord | V4.0 | |
getPageNthWordQuads | V4.0 | |
getPageNumWords | V4.0 | |
getPageRotation | V7.0 | |
getPrintParams | V4.0 | |
getURL | V4.0 | |
importAnFDF | V4.0 | |
insertPages | V6.2 | |
mailForm | V4.0 | |
V4.0 | ||
removeField | V4.0 | |
replacePages | V6.2 | |
resetForm | V4.0 | |
submitForm | V4.0 | |
mailDoc | V4.0 | |
event properties | change | V4.0 |
changeEx | V4.0 | |
commitKey | V4.0 | |
fieldFull | V4.0 | |
keyDown | V4.0 | |
modifier | V4.0 | |
name | V4.0 | |
rc | V4.0 | |
selEnd | V4.0 | |
selStart | V4.0 | |
shift | V4.0 | |
source | V4.0 | |
target | V4.0 | |
targetName | V4.0 | |
type | V4.0 | |
value | V4.0 | |
willCommit | V4.0 | |
event methods | – | – |
field properties | alignment | V4.0 |
borderStyle | V4.0 | |
buttonAlignX | V4.0 | |
buttonAlignY | V4.0 | |
buttonFitBounds | V4.0 | |
buttonPosition | V4.0 | |
buttonScaleHow | V4.0 | |
buttonScaleWhen | V4.0 | |
calcOrderIndex | V4.0 | |
charLimit | V4.0 | |
comb | V4.0 | |
commitOnSelChange | V4.0 | |
currentValueIndices | V4.0 | |
defaultValue | V4.0 | |
doNotScroll | V4.0 | |
doNotSpellCheck | V4.0 | |
delay | V4.0 | |
display | V4.0 | |
doc | V4.0 | |
editable | V4.0 | |
exportValues | V4.0 | |
hidden | V4.0 | |
fileSelect | V4.0 | |
fillColor | V4.0 | |
lineWidth | V4.0 | |
highlight | V4.0 | |
multiline | V4.0 | |
multipleSelection | V4.0 | |
name | V4.0 | |
numItems | V4.0 | |
page | V4.0 | |
password | V4.0 | |
V4.0 | ||
radiosInUnison | V4.0 | |
readonly | V4.0 | |
rect | V4.0 | |
required | V4.0 | |
richText | V4.0 | |
rotation | V4.0 | |
strokeColor | V4.0 | |
style | V4.0 | |
textColor | V4.0 | |
textFont | V4.0 | |
textSize | V4.0 | |
type | V4.0 | |
userName | V4.0 | |
value | V4.0 | |
valueAsString | V4.0 | |
field methods | browseForFileToSubmit | V4.0 |
buttonGetCaption | V4.0 | |
buttonGetIcon | V4.0 | |
buttonSetCaption | V4.0 | |
buttonSetIcon | V4.0 | |
checkThisBox | V4.0 | |
clearItems | V4.0 | |
defaultIsChecked | V4.0 | |
deleteItemAt | V4.0 | |
getArray | V4.0 | |
getItemAt | V4.0 | |
insertItemAt | V4.0 | |
isBoxChecked | V4.0 | |
isDefaultChecked | V4.0 | |
setAction | V4.0 | |
setFocus | V4.0 | |
setItems | V4.0 | |
global methods | setPersistent | V4.0 |
Icon properties | name | V4.0 |
util methods | printd | V4.0 |
printf | V4.0 | |
printx | V4.0 | |
scand | V4.0 | |
identity properties | loginName | V4.2 |
Name | V4.2 | |
corporation | V4.2 | |
V4.2 | ||
collab properties | user | V6.2 |
ocg properties | name | V6.2 |
ocg methods | setAction | V6.2 |
全局方法
方法名称 | 支持的最低SDK版本 |
AFNumber_Format | V4.0 |
AFNumber_Keystroke | V4.0 |
AFPercent_Format | V4.0 |
AFPercent_Keystroke | V4.0 |
AFDate_FormatEx | V4.0 |
AFDate_KeystrokeEx | V4.0 |
AFDate_Format | V4.0 |
AFDate_Keystroke | V4.0 |
AFTime_FormatEx | V4.0 |
AFTime_KeystrokeEx | V4.0 |
AFTime_Format | V4.0 |
AFTime_Keystroke | V4.0 |
AFSpecial_Format | V4.0 |
AFSpecial_Keystroke | V4.0 |
AFSpecial_KeystrokeEx | V4.0 |
AFSimple | V4.0 |
AFMakeNumber | V4.0 |
AFSimple_Calculate | V4.0 |
AFRange_Validate | V4.0 |
AFMergeChange | V4.0 |
AFParseDateEx | V4.0 |
AFExtractNums | V4.0 |
引用
[1] PDF reference 1.7
http://www.iso.org/iso/iso_catalogue/catalogue_tc/catalogue_detail.htm?csnumber=51502
[2]PDF reference 2.0
https://www.iso.org/standard/63534.html
[3]Foxit PDF SDK API reference
sdk_folder/doc/Foxit PDF SDK API Reference.html
备注: sdk_folder 是SDK包解压后的目录。
技术支持
您可以直接联系Foxit,请使用以下的联系方式:
线上支持:
联系销售:
- 电话: 1-866-680-3668
- 邮箱: sales@foxitsoftware.com
联系技术支持团队:
- 电话: 1-866-MYFOXIT or 1-866-693-6948
- 邮箱: support@foxitsoftware.com