如何在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 PRIVATE
explicit 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);
}
原文地址:https://blog.csdn.net/cuxqblt/article/details/142595037
免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!