/*************************************************************************** * Copyright (C) 2007 by Tobias Koenig * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * ***************************************************************************/ #ifndef _OKULAR_TEXTDOCUMENTGENERATOR_P_H_ #define _OKULAR_TEXTDOCUMENTGENERATOR_P_H_ #include #include #include #include "action.h" #include "document.h" #include "textdocumentgenerator.h" namespace Okular { class Utils { public: static void calculateBoundingRect( QTextDocument *document, int startPosition, int endPosition, QRectF &rect, int &page ) { const QSizeF pageSize = document->pageSize(); const QTextBlock startBlock = document->findBlock( startPosition ); const QRectF startBoundingRect = document->documentLayout()->blockBoundingRect( startBlock ); const QTextBlock endBlock = document->findBlock( endPosition ); const QRectF endBoundingRect = document->documentLayout()->blockBoundingRect( endBlock ); QTextLayout *startLayout = startBlock.layout(); QTextLayout *endLayout = endBlock.layout(); int startPos = startPosition - startBlock.position(); int endPos = endPosition - endBlock.position(); const QTextLine startLine = startLayout->lineForTextPosition( startPos ); const QTextLine endLine = endLayout->lineForTextPosition( endPos ); double x = startBoundingRect.x() + startLine.cursorToX( startPos ); double y = startBoundingRect.y() + startLine.y(); double r = endBoundingRect.x() + endLine.cursorToX( endPos ); double b = endBoundingRect.y() + endLine.y() + endLine.height(); int offset = qRound( y ) % qRound( pageSize.height() ); if ( x > r ) { // line break, so return a pseudo character on the start line rect = QRectF( x / pageSize.width(), offset / pageSize.height(), 3 / pageSize.width(), startLine.height() / pageSize.height() ); page = -1; return; } page = qRound( y ) / qRound( pageSize.height() ); rect = QRectF( x / pageSize.width(), offset / pageSize.height(), (r - x) / pageSize.width(), (b - y) / pageSize.height() ); } static void calculatePositions( QTextDocument *document, int page, int &start, int &end ) { const QAbstractTextDocumentLayout *layout = document->documentLayout(); const QSizeF pageSize = document->pageSize(); double margin = document->rootFrame()->frameFormat().margin(); /** * Take the upper left and lower left corner including the margin */ start = layout->hitTest( QPointF( margin, (page * pageSize.height()) + margin ), Qt::FuzzyHit ); end = layout->hitTest( QPointF( margin, ((page + 1) * pageSize.height()) - margin ), Qt::FuzzyHit ); } static Okular::DocumentViewport calculateViewport( QTextDocument *document, const QTextBlock &block ) { const QSizeF pageSize = document->pageSize(); const QRectF rect = document->documentLayout()->blockBoundingRect( block ); int page = qRound( rect.y() ) / qRound( pageSize.height() ); int offset = qRound( rect.y() ) % qRound( pageSize.height() ); Okular::DocumentViewport viewport( page ); viewport.rePos.normalizedX = (double)rect.x() / (double)pageSize.width(); viewport.rePos.normalizedY = (double)offset / (double)pageSize.height(); viewport.rePos.enabled = true; viewport.rePos.pos = Okular::DocumentViewport::Center; return viewport; } }; class TextDocumentConverter::Private { }; class TextDocumentGenerator::Private { friend class TextDocumentConverter; public: Private( TextDocumentGenerator *parent, TextDocumentConverter *converter ) : mParent( parent ), mConverter( converter ), mDocument( 0 ) { } ~Private() { delete mConverter; delete mDocument; } void calculateBoundingRect( int startPosition, int endPosition, QRectF &rect, int &page ) const; void calculatePositions( int page, int &start, int &end ) const; Okular::TextPage* createTextPage( int ) const; void addAction( Action *action, int cursorBegin, int cursorEnd ); void addAnnotation( Annotation *annotation, int cursorBegin, int cursorEnd ); void addTitle( int level, const QString &title, const QTextBlock &position ); void addMetaData( const QString &key, const QString &value, const QString &title ); void generateLinkInfos(); void generateAnnotationInfos(); void generateTitleInfos(); TextDocumentGenerator *mParent; TextDocumentConverter *mConverter; QTextDocument *mDocument; Okular::DocumentInfo mDocumentInfo; Okular::DocumentSynopsis mDocumentSynopsis; struct TitlePosition { int level; QString title; QTextBlock block; }; QList mTitlePositions; struct LinkPosition { int startPosition; int endPosition; Action *link; }; QList mLinkPositions; struct LinkInfo { int page; QRectF boundingRect; Action *link; }; QList mLinkInfos; struct AnnotationPosition { int startPosition; int endPosition; Annotation *annotation; }; QList mAnnotationPositions; struct AnnotationInfo { int page; QRectF boundingRect; Annotation *annotation; }; QList mAnnotationInfos; }; } #endif