okular的设计和后端

  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 );
}
##########################################################################


  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值