Skip to content

书签 (Bookmark)

福昕 PDF SDK 提供了名为书签的导航工具,允许用户在 PDF 文档中快速定位和链接他们感兴趣的部分。PDF 书签也称为大纲 (outline),每个书签包含一个目标位置或动作来描述它链接到的位置。它是一个树形的层次结构,因此在访问 bookmark 树之前,必须首先获取整个 bookmark 树的根节点。这里,书签根节点 是一个抽象对象,它只有一些子节点,没有兄弟节点, 也没有任何数据 (包括 bookmark 数据,目标位置数据和动作数据)。

以 Java 开发语言为例:

获取整个 bookmark 树的根节点,使用 pdf.PDFDoc.getRootBookmark 接口。因为它没有任何数据,因此无法在应用程序界面上显示,能够调用的接口只有 Bookmark.getFirstChild

在获取书签根节点后,就可以调用以下的接口去访问其他的书签:

  • 访问 parent bookmark,使用 Bookmark.getParent 接口。
  • 访问第一个 child bookmark,使用 Bookmark.getFirstChild 接口。
  • 访问 next sibling bookmark,使用 Bookmark.getNextSibling 接口。
  • 插入一个新的 bookmark,使用 Bookmark.insert 接口。
  • 移动一个 bookmark,使用 Bookmark.moveTo 接口。

遍历 PDF 文档中所有的书签

c++
#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();
       }
        }
}
...
C
#include "include/fs_basictypes_c.h"
#include "include/fs_common_c.h"
#include "include/fs_filespec_c.h"
#include "include/fs_bookmark_c.h"
#include "include/fs_pdfdoc_c.h"
#include "include/fs_pdfpage_c.h"
...

// Assuming FS_PDFDOC_HANDLE doc has been loaded.

FS_BOOKMARK_HANDLE root;
FSDK_PDFDoc_GetRootBookmark(doc, &root);
FS_BOOKMARK_HANDLE first_bookmark;
FSDK_Bookmark_GetFirstChild(root, &first_bookmark);

if (first_bookmark != null)
{
TraverseBookmark(first_bookmark, 0);
}

Private void TraverseBookmark(FS_BOOKMARK_HANDLE root, int iLevel)
{
if (root != null)
{
                   FS_BOOKMARK_HANDLE child;
FSDK_Bookmark_GetFirstChild(root, &child);
    while (child != null)
       {
          TraverseBookmark(child, iLevel + 1);
          FSDK_Bookmark_GetNextSibling(child, &child);
       }
        }
}
...
java
import com.foxit.sdk.pdf.Bookmark;
import com.foxit.sdk.pdf.PDFDoc;
...

// Assuming PDFDoc doc has been loaded.
...

Bookmark root = doc.getRootBookmark();
if (root.isEmpty()) {
    root = doc.createRootBookmark();
}
            
String titleStr = "";
Bookmark iterBookmark = root.getFirstChild ();
if (iterBookmark.isEmpty())
    return;
while (!iterBookmark.isEmpty())
{
    titleStr = iterBookmark.getTitle();
    if (iterBookmark.hasChild())
    {
        Bookmark childBookmark = iterBookmark.getFirstChild();
        titleStr = childBookmark.getTitle();
    }
            	
    iterBookmark = iterBookmark.getNextSibling();
}
...
py
import sys
import site

if sys.version_info.major == 2:
    _PYTHON2_ = True
else:
    _PYTHON2_ = False

if _PYTHON2_:
    #replace with the python2 lib path
    site.addsitedir('../../../')
    from FoxitPDFSDKPython2 import *
else:
    from FoxitPDFSDKPython3 import *

...
# Assuming PDFDoc doc has been loaded.
root = doc.GetRootBookmark()
first_bookmark = root.GetFirstChild()

def TraverseBookmark(root, iLevel):
    if root is not None:
        child = root.GetFirstChild()
        while child is not None:    
            TraverseBookmark(child, iLevel + 1)
            child = child.GetNextSibling()

if first_bookmark is not None:
    TraverseBookmark(first_bookmark, 0)
...
objc
#include "FSPDFObjC.h"
...

// Assuming FSPDFDoc doc has been loaded.
...
FSBookmark *root = [doc getRootBookmark]; 
if (![root isEmpty]) {
    ShowBookmarkInfo(root, info, 0); 
}
void ShowBookmarkInfo(FSBookmark *bookmark, int depth) {
    if (depth > 32)
        return;
    if ([bookmark isEmpty]) {
        return;
    }
    ShowBookmarkInfo([bookmark getFirstChild], depth + 1);
    ShowBookmarkInfo([bookmark getNextSibling], depth);
}
...
js
const FSDK = require("@foxitsoftware/foxit-pdf-sdk-node");

...
// Assuming PDFDoc doc has been loaded.
let root = doc.GetRootBookmark();
let first_bookmark = root.GetFirstChild();

function TraverseBookmark(root, iLevel){
    if(!root.IsEmpty()) {
      let child = root.GetFirstChild()
      while(!child.IsEmpty()) {
        TraverseBookmark(child, iLevel + 1)
        child = child.GetNextSibling()
      }
    }
}
...
csharp
using foxit;
using foxit.common;
using foxit.common.fxcrt;
using foxit.pdf;
using foxit.pdf.actions;
...

//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();
       }
        }
}
...

向 PDF 文档中添加一个新的书签

c++
#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 std;
using namespace foxit;
using namespace foxit::common;
using foxit::common::Library;
using namespace pdf;

// Assuming PDFDoc doc has been loaded.

Bookmark root = doc.GetRootBookmark();
if (root.IsEmpty())
{
   root = doc.CreateRootBookmark();
}
Destination dest = Destination::CreateFitPage(doc, 0);
CFX_WideString ws_title;
ws_title.Format((FX_LPCWSTR)L"A bookmark to a page (index: %d)", 0);
Bookmark child = root.Insert(ws_title, foxit::pdf::Bookmark::e_PosLastChild);
child.SetDestination(dest);
child.SetColor(0xF68C21);
C
#include "include/fs_basictypes_c.h"
#include "include/fs_common_c.h"
#include "include/fs_filespec_c.h"
#include "include/fs_bookmark_c.h"
#include "include/fs_pdfdoc_c.h"
#include "include/fs_pdfpage_c.h"

int string2wstring(const char *source, size_t source_size, wchar_t *dest, size_t dest_size) {
  const char *_source;
  wchar_t *_dest;
  if (!source || !dest) return 0;
  _source = source;
  _dest = dest;
  setlocale(LC_ALL, "chs");
  mbstowcs(_dest, _source, _Dsize);
  setlocale(LC_ALL, "C");
  return (int)dest_size;
}

// Assuming FS_PDFDOC_HANDLE doc has been loaded.

FS_BOOKMARK_HANDLE root;
FSDK_PDFDoc_GetRootBookmark(doc, &root);
FS_BOOL return_value;
FSDK_Bookmark_IsEmpty(root, &return_value);
if (return_value)
{
   FSDK_PDFDoc_CreateRootBookmark(doc, &root);
}
FS_DESTINATION_HANDLE dest;
FSDK_Destination_CreateFitPage(doc, 0, &dest);
char str[128];
sprintf(str, "A bookmark to a page (index: %d)", i);
wchar_t ws_title[MAX_FILE_PATH];
FSErrorCode error_code;
string2wstring(path, MAX_FILE_PATH, ws_title, MAX_FILE_PATH);
FS_BOOKMARK_HANDLE child;
FSDK_Bookmark_Insert(root, ws_title, e_FSPosLastChild, &child);
FSDK_Bookmark_SetDestination(child, dest);
FSDK_Bookmark_SetColor(child, 0xF68C21);
java
import com.foxit.sdk.pdf.Bookmark;
import com.foxit.sdk.pdf.PDFDoc;
import com.foxit.sdk.pdf.actions.Destination;
import static com.foxit.sdk.pdf.Bookmark.e_PosLastChild;

// Assuming PDFDoc doc has been loaded.

Bookmark root = doc.getRootBookmark();
if (root.isEmpty()) {
    root = doc.createRootBookmark();
}
Destination dest = Destination.createFitPage(doc, 0);

String ws_title = String.format("A bookmark to a page (index: %d)", 0);
Bookmark child = root.insert(ws_title, e_PosLastChild);
child.setDestination(dest);
child.setColor(0xF68C21);
py
import sys
import site

if sys.version_info.major == 2:
    _PYTHON2_ = True
else:
    _PYTHON2_ = False

if _PYTHON2_:
    #replace with the python2 lib path
    site.addsitedir('../../../')
    from FoxitPDFSDKPython2 import *
else:
    from FoxitPDFSDKPython3 import *

# Assuming PDFDoc doc has been loaded.
root = doc.GetRootBookmark()
if root.IsEmpty():
    root = doc.CreateRootBookmark()

dest = Destination.CreateFitPage(doc, 0)
ws_title = str.format("A bookmark to a page (index: {})", 0)
child = root.Insert(ws_title, Bookmark.e_PosLastChild)
child.SetDestination(dest)
child.SetColor(0xF68C21)
objc
#include "FSPDFObjC.h"

// Assuming PDFDoc doc has been loaded.

FSBookmark *root = [doc getRootBookmark];
if ([root isEmpty]) {
    root = [doc createRootBookmark];
}
FSDestination *dest = [FSDestination createFitPage:doc page_index:0];
NSString *title = [NSString stringWithFormat:@"A bookmark to a page (index: %d)", 0];
FSBookmark *child = [root insert:title position:FSBookmarkPosLastChild];
[child setDestination:dest];
[child setColor:0xF68C21];
js
const FSDK = require("@foxitsoftware/foxit-pdf-sdk-node");

// Assuming PDFDoc doc has been loaded.
let root = doc.GetRootBookmark();
if (root.IsEmpty())
{
  root = doc.CreateRootBookmark();
}

let dest = FSDK.Destination.CreateFitPage(doc, i);
let ws_title = `A bookmark to a page (index: ${i})`;
let child = root.Insert(ws_title, FSDK.Bookmark.e_PosLastChild);
child.SetDestination(dest);
child.SetColor(i * 0xF68C21);
csharp
using foxit;
using foxit.common;
using foxit.common.fxcrt;
using foxit.pdf;
using foxit.pdf.actions;

// Assuming PDFDoc doc has been loaded.

Bookmark root = doc.GetRootBookmark();
if (root.IsEmpty())
{
    root = doc.CreateRootBookmark();
}
using (Destination dest = Destination.CreateFitPage(doc, 0))
{
    string ws_title = string.Format("A bookmark to a page (index: {0})", 0);

    Bookmark child;
    using (child = root.Insert(ws_title, Bookmark.Position.e_PosLastChild))
    {
        child.SetDestination(dest);
        child.SetColor(0xF68C21);
    }
}

根据 PDF 的书签信息创建目录表

c++
#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;
...

void AddTOCToPDF(PDFDoc doc) {
    //Set the table of contents configuration.
    Int32Array intarray;
    int depth = doc.GetBookmarkLevelDepth();
    if (depth > 0) {
        for (int i = 1; i <= depth; i++) {
            intarray.Add(i);
        }
    }
    WString title = L"";
    TableOfContentsConfig toc_config = TableOfContentsConfig(title, intarray, true, false);

    //Add the table of contents
    doc.AddTableOfContents(toc_config);
}
C
#include "include/fs_basictypes_c.h"
#include "include/fs_common_c.h"
#include "include/fs_filespec_c.h"
#include "include/fs_bookmark_c.h"
#include "include/fs_pdfdoc_c.h"
#include "include/fs_pdfpage_c.h"

void AddTOCToPDF(FS_PDFDOC_HANDLE& doc) {
    // Set the table of contents configuration.
    int depth = 0;
    FSDK_PDFDoc_GetBookmarkLevelDepth(doc, &depth);
    int* intarray = (int*)malloc(depth * sizeof(int));
    if (depth > 0) {
        for (int i = 1; i <= depth; i++) {
            intarray[i - 1] = i;
        }
    }
    FS_WSTR title;
    title.str = NULL;
    title.len = 0;
    FSTableOfContentsConfig toc_config;
    toc_config.bookmark_level_array = intarray;
    toc_config.bookmark_level_array_length = depth;
    toc_config.title = title;
    toc_config.is_show_serial_number = true;
    toc_config.include_toc_pages = false;

    // Add the table of contents.
    FSDK_PDFDoc_AddTableOfContents0(doc, toc_config);
    free(intarray);
}
java
import com.foxit.sdk.pdf.Bookmark;
import com.foxit.sdk.pdf.PDFDoc;
import com.foxit.sdk.pdf.actions.Destination;
import static com.foxit.sdk.pdf.Bookmark.e_PosLastChild;

static void AddTOCToPDF(PDFDoc doc) throws PDFException {
    Int32Array intarray = new Int32Array();
    int depth = doc.getBookmarkLevelDepth();
    if (depth > 0) {
      for (int i = 1; i <= depth; i++) {
          intarray.add(i);
      }
    }
    String title = "";
    TableOfContentsConfig toc_config = new TableOfContentsConfig(title, intarray, true, false);
 
    // Add the table of contents
    doc.addTableOfContents(toc_config);
}
py
import sys
import site

if sys.version_info.major == 2:
    _PYTHON2_ = True
else:
    _PYTHON2_ = False

if _PYTHON2_:
    #replace with the python2 lib path
    site.addsitedir('../../../')
    from FoxitPDFSDKPython2 import *
else:
    from FoxitPDFSDKPython3 import *
        
...
def AddTOCToPDF(doc):
    # Set the table of contents configuration.
    intarray = Int32Array()
    depth = doc.GetBookmarkLevelDepth()
    if depth > 0:
        for i in range(1, depth):
            intarray.Add(i)
            
    title = ""
    toc_config = TableOfContentsConfig(title, intarray, True, False)

    # Add the table of contents
doc.AddTableOfContents(toc_config)
objc
#include "FSPDFObjC.h"
...

void addTOCToPDF(FSPDFDoc* doc) {
    @autoreleasepool {
        // Set the table of contents configuration.
        FSInt32Array* intarray = [[FSInt32Array alloc] init];
        int depth = [doc getBookmarkLevelDepth];
        if (depth > 0) {
            for (int i = 1; i <= depth; i++) {
                [intarray add:i];
            }
        }
        NSString* title = @"";
        FSTableOfContentsConfig* toc_config = [[FSTableOfContentsConfig alloc] initWithTitle:title bookmark_level_array:intarray is_show_serial_number:true include_toc_pages:false];
 
        // Add the table of contents.
        [doc addTableOfContentsWithTableOfContentsConfig:toc_config];
    }
}
js
const FSDK = require("@foxitsoftware/foxit-pdf-sdk-node");
        
...
function AddTOCToPDF(doc){
  // Set the table of contents configuration.
  let name_array = new FSDK.Int32Array();
  depth = doc.GetBookmarkLevelDepth()
  if(depth > 0) {
    for(var i = 0; i < depth; i++) {
      name_array.Add(i);
    }
  }

  let title = ""
  let toc_config = new FSDK.TableOfContentsConfig(title, intarray, True, False)
}
// Add the table of contents
doc.AddTableOfContents(toc_config)
csharp
using foxit;
using foxit.common;
using foxit.common.fxcrt;
using foxit.pdf;
using foxit.pdf.actions;

static void AddTOCToPDF(PDFDoc doc)
{
    //Set the table of contents configuration.
    using (var intarray = new Int32Array())
    {
        int depth = doc.GetBookmarkLevelDepth();
        if (depth > 0)
        {
            for (int i = 1; i <= depth; i++)
            {
                intarray.Add(i);
            }
        }
        string title = "";
        using (var toc_config = new TableOfContentsConfig(title, intarray, true, false))
        {
            //Add the table of contents
            doc.AddTableOfContents(toc_config);
        }
    }
}