当前位置: 首页 > news >正文

如何在C++中使用Poppler库读取PDF文件(二)

PDF目录

书籍一般都有目录,电子书也不例外。使用Poppler::Document加载PDF文件以后,就可以通过outline()方法,取得PDF文件的目录。

outline()方法的定义如下:

QVector<OutlineItem> outline() const;

我们看到,Poppler的目录是一个目录项(Poppler::OutlineItem)的列表(QVector)。

Popper::OutlineItem的默认构造函数会初始化一个空的目录项,其中不含任何跟PDF文件相关的信息。

Poppler::OutlineItem支持如下方法:

判断是否为空。上文提到,默认构造以后就是空的。

bool isNull() const;

目录项名称,即显示出来的目录项名字。

QString name() const;

目录项是否是展开状态。

bool isOpen() const;

目录项指向的页数等信息,是一个智能指针,根据这个指针,就可以取得目录具体指向什么位置。

QSharedPointer destination() const;

目录项指向的外部文件。

QString externalFileName() const;

目录项指向的URI。

QString uri() const;

目录项是否含有子项。

bool hasChildren() const;

目录项的子项列表。

QVector children() const;

所以综上,根据Poppler::Document的outline()方法,可以取得目录项的列表,再根据列表中每个目录项是否有子项,就可以完成一个目录项的遍历。

PDF链接目标

PDF文件中,除了目录以外,在正文中也会有超链接。无论是链接的视频、音频还是其它外部网址,这些都是通过LinkDestination表示的。

LinkDestination的定义为:

class POPPLER_QT6_EXPORT LinkDestination
{
public:/*** The possible kind of "viewport destination".*/enum Kind{/*** The new viewport is specified in terms of:* - possible new left coordinate (see isChangeLeft() )* - possible new top coordinate (see isChangeTop() )* - possible new zoom level (see isChangeZoom() )*/destXYZ = 1,destFit = 2,destFitH = 3,destFitV = 4,destFitR = 5,destFitB = 6,destFitBH = 7,destFitBV = 8};/// \cond PRIVATEexplicit LinkDestination(const LinkDestinationData &data);explicit LinkDestination(const QString &description);/// \endcond/*** Copy constructor.*/LinkDestination(const LinkDestination &other);/*** Destructor.*/~LinkDestination();// Accessors./*** The kind of destination.*/Kind kind() const;/*** Which page is the target of this destination.** \note this number is 1-based, so for a 5 pages document the*       valid page numbers go from 1 to 5 (both included).*/int pageNumber() const;/*** The new left for the viewport of the target page, in case* it is specified to be changed (see isChangeLeft() )*/double left() const;double bottom() const;double right() const;/*** The new top for the viewport of the target page, in case* it is specified to be changed (see isChangeTop() )*/double top() const;double zoom() const;/*** Whether the left of the viewport on the target page should* be changed.** \see left()*/bool isChangeLeft() const;/*** Whether the top of the viewport on the target page should* be changed.** \see top()*/bool isChangeTop() const;/*** Whether the zoom level should be changed.** \see zoom()*/bool isChangeZoom() const;/*** Return a string repesentation of this destination.*/QString toString() const;/*** Return the name of this destination.*/QString destinationName() const;/*** Assignment operator.*/LinkDestination &operator=(const LinkDestination &other);private:QSharedDataPointer<LinkDestinationPrivate> d;
};

其中,pageNumber()方法,返回的是目标所在的页码数。

既然有链接目标,当然就会有链接。在Poppler里面,链接的类是Poppler::Link,是一个基类,它派生了LinkGoto、LinkExecute、LinkBrowse、LinkAction、LinkSound、LinkMovie等各种具体的子类。

在Poppler::Document中取得一个Link以后,可以通过Link的

virtual LinkType linkType() const;
来取得具体类型。

LinkType是一个enum:

  enum LinkType  {  None, ///< Unknown link  Goto, ///< A "Go To" link  Execute, ///< A command to be executed  Browse, ///< An URL to be browsed (eg "http://poppler.freedesktop.org")  Action, ///< A "standard" action to be executed in the viewer  Sound, ///< A link representing a sound to be played  Movie, ///< An action to be executed on a movie  Rendition, ///< A rendition link  JavaScript, ///< A JavaScript code to be interpreted  OCGState, ///< An Optional Content Group state change  Hide, };

对应相应的子类实现。

比如,如果Link是一个LinkExecute,就可以通过它的fileName()、parameters()方法,分别取得可执行文件的路径以及执行参数。

PDF批注

如果要对PDF文件进行批注,可以使用Annotation类。

这个类也是一个基类,它的子类有TextAnnotation、LineAnnotation、GeomAnnotation、HighlightAnnotation等等。

Annotation基类中有一个

virtual SubType subType() const = 0;
纯虚函数,可以返回子类的类型。

SubType也是一个enum:

   enum SubType  {    AText = 1, ///< TextAnnotation  ALine = 2, ///< LineAnnotation  AGeom = 3, ///< GeomAnnotation  AHighlight = 4, ///< HighlightAnnotation  AStamp = 5, ///< StampAnnotation  AInk = 6, ///< InkAnnotation  ALink = 7, ///< LinkAnnotation  ACaret = 8, ///< CaretAnnotation  AFileAttachment = 9, ///< FileAttachmentAnnotation  ASound = 10, ///< SoundAnnotation  AMovie = 11, ///< MovieAnnotation  AScreen = 12, ///< ScreenAnnotation  AWidget = 13, ///< WidgetAnnotation  ARichMedia = 14 ///< RichMediaAnnotation  };

所以,Annotation的使用,与Link很相似。我们可以举一反三,很快地掌握Annotation的使用方法。

比如,如下代码就可以给一个文档的指定位置,加一行下划线:

void  
annot_line (unique_ptr<Document> doc, int pn, double x1, double y1, double x2,  double y2)  
{  auto page = doc->page(pn);  auto annot = new LineAnnotation (LineAnnotation::LineType::Polyline);  annot->setLinePoints({{x1, y1}, {x2, y2}});  page->addAnnotation(annot);  
}

或者,给PDF文件中加一行注释:

void  
annot_text (unique_ptr<Document> doc, int pn, double x1, double y1, double x2,  double y2, string_view text)  
{  auto page = doc->page (pn);  auto annot = new TextAnnotation (TextAnnotation::TextType::Linked);  annot->setBoundary ({ x1, y1, x2, y2 });  annot->setContents (QString::fromLocal8Bit (text));  page->addAnnotation (annot);  
}

http://www.mrgr.cn/news/37778.html

相关文章:

  • 计算机知识科普问答--21(101-105)
  • ubuntu20.04系统安装zookeeper简单教程
  • 为什么这款智能在线派单软件成为行业首选?
  • rust的nutyp验证和validator验证数据的方法
  • Spring Security 是一个强大的和高度可定制的身份验证和访问控制框架。它是 Spring 项目家族的一员,用于构建安全的 Java 应用程序。
  • 32 C 语言指针的长度与运算(指针加减整数、指针自增自减、同类型指针相减、指针的比较运算)
  • 【C++】 vector 迭代器失效问题
  • 复习linux网络编程
  • qt xml解析与处理
  • 使用asio 接收ps流代码并显示
  • WiFi无线连接管理安卓设备工具:WiFiADB
  • 高考技术——pandas使用
  • 指令个人记录
  • 废品回收小程序:回收更加便捷!
  • 构建5G-TSN测试平台:架构与挑战
  • 变种水仙花数 - Lily Number
  • windows@win10@Win11版本号和代号命名变迁@获取或查看windows版本号信息详情方法列举
  • C++11中智能指针以及标准模板库 My_string My_stack
  • 钉钉H5微应用Springboot+Vue开发分享
  • re轻松拆分四则运算expression(^从头匹配、(?:xxxx)非捕获组、| 交替运算符联合演习)