okular的设计和后端

xiaoxiao2021-02-28  79

  okular 为了支持各种格式的文档,采用了模块化的设计思路。         okular 可分为四个部分: 外壳(Shell) 部件(Part) 文档对象(Okular::Document) 后端(Okular::Generator)         外壳只是作为独立启动 okular 是嵌入部件的部分;部件主要负责呈现,比如各种书签,内容列表,菜单等;文档对象是个抽象概念,包含了文档的各个页面内容,尺寸方向等。         文档对象必须从后端获取这些内容信息,后端得把文档文件本身解析并转换为 okular 内部用于展示的通用模式,再交给文档对象。         那么内部使用的通用模式是如何的呢?看看各种文档有什么共同点吧。大家都有“页”这个概念,哪怕是图片也可以看成只有一页的文档。每个页面都有大小尺寸方向。最终,页面都可以转换成图片给用户看,就像把内容打印在一张纸上。后端最基本的任务就是得知这个文档一共有几页,然后需要转换为图片。对于放大缩小这类需求,一些基于矢量图形的文档,例如 PDF 和 PostScript,后端只需要将矢量图形渲染成需要的尺寸就可以了,而一些静态的内容,例如图像文件,后端就必须进行缩放操作再交给文档对象。         文档对象从后端获取页面图片之后便可以进行一些附加操作了,比如应用切换的特效和旋转等等。         有些格式支持从文档内容中获取文本,比如 PDF。okular 要获取这些文字,是通过用户使用鼠标选取一块区域然后再获得该区域中的文本。这种位置到文字的方式会因为缩放的关系而无法直接确定。okular 定义了一种 0 到 1 的绝对比例坐标,按照比例坐标乘以缩放系数得到对应的实际位置。比如有个文字在页面中央的位置,那么坐标即为 (0.5, 0.5)。         此外,后端还会负责获取文档的元数据信息。如文档作者、创建日期、版本、内容排版、书签、批注。         okular 的强大之处就在于后端插件的可扩展性。接下来将为你展示如何自己写一个 okular 后端。 示例中的 Magic 文档格式是假象中的东西,实际上是没有的。 最基本的后端:装入文档,获取页数,返回指定尺寸的页面图片 以下部分纯照抄,来自 okular team。 /*******************************************************************************************************************************/ class MagicDocument{ public: MagicDocument(); ~MagicDocument(); bool loadDocument( const QString &fileName ); int numberOfPages() const; QSize pageSize( int pageNumber ) const; QImage pictureOfPage( int pageNumber ) const; private: ...}; 后端的 API 是这样子的: ########################################################################## #include "magicdocument.h"#include <okular/core/generator.h>class MagicGenerator : public Okular::Generator{ public: MagicGenerator( QObject *parent, const QVariantList &args ); ~MagicGenerator(); bool loadDocument( const QString &fileName, QVector<Okular::Page*> &pages ); bool canGeneratePixmap() const; void generatePixmap( Okular::PixmapRequest *request ); protected: bool doCloseDocument(); private: MagicDocument mMagicDocument;}; ########################################################################## #include <okular/core/page.h>#include "magicgenerator.h"static KAboutData createAboutData(){ KAboutData aboutData(...); // fill the about data return aboutData;}OKULAR_EXPORT_PLUGIN(MagicGenerator, createAboutData())MagicGenerator::MagicGenerator( QObject *parent, const QVariantList &args ) : Okular::Generator( parent, args ){}MagicGenerator::~MagicGenerator(){}// loadDocument 装入文档文件并获取文档页数。文档内的每个页面都会向 pages 添加一个 Okular::Page 对象,bool MagicGenerator::loadDocument( const QString &fileName, QVector<Okular::Page*> &pages ){ if ( !mMagicDocument.loadDocument( fileName ) ) { emit error( i18n( "Unable to load document" ), -1 ); return false; } pages.resize( mMagicDocument.numberOfPages() ); for ( int i = 0; i < mMagicDocument.numberOfPages(); ++i ) { const QSize size = mMagicDocument.pageSize( i ); Okular::Page * page = new Okular::Page( i, size.width(), size.height(), Okular::Rotation0 ); pages[ i ] = page; } return true;}bool MagicGenerator::doCloseDocument(){ return true;}bool MagicGenerator::canGeneratePixmap() const{ return true;}void MagicGenerator::generatePixmap( Okular::PixmapRequest *request ){ QImage image = mMagicDocument.pictureOfPage( request->pageNumber() ); image = image.scaled( request->width(), request->height(), Qt::IgnoreAspectRatio, Qt::SmoothTransformation ); request->page()->setPixmap( request->id(), new QPixmap( QPixmap::fromImage( image ) ) ); signalPixmapRequestDone( request );} ##########################################################################
转载请注明原文地址: https://www.6miu.com/read-39587.html

最新回复(0)