You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
329 lines
8.9 KiB
329 lines
8.9 KiB
/*************************************************************************** |
|
* Copyright (C) 2004 by Enrico Ros <eros.kde@email.it> * |
|
* * |
|
* 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. * |
|
***************************************************************************/ |
|
|
|
// qt/kde includes |
|
#include <qpixmap.h> |
|
#include <qstring.h> |
|
#include <qmap.h> |
|
#include <kdebug.h> |
|
|
|
// local includes |
|
#include "page.h" |
|
#include "pagetransition.h" |
|
#include "link.h" |
|
#include "conf/settings.h" |
|
#include "xpdf/TextOutputDev.h" |
|
|
|
|
|
/** class KPDFPage **/ |
|
|
|
KPDFPage::KPDFPage( uint page, float w, float h, int r ) |
|
: m_number( page ), m_rotation( r ), m_width( w ), m_height( h ), |
|
m_bookmarked( false ), m_text( 0 ), m_transition( 0 ) |
|
{ |
|
// if landscape swap width <-> height (rotate 90deg CCW) |
|
if ( r == 90 || r == 270 ) |
|
{ |
|
m_width = h; |
|
m_height = w; |
|
} |
|
// avoid Division-By-Zero problems in the program |
|
if ( m_width <= 0 ) |
|
m_width = 1; |
|
if ( m_height <= 0 ) |
|
m_height = 1; |
|
} |
|
|
|
KPDFPage::~KPDFPage() |
|
{ |
|
deletePixmapsAndRects(); |
|
deleteHighlights(); |
|
delete m_text; |
|
delete m_transition; |
|
} |
|
|
|
|
|
bool KPDFPage::hasHighlights( int id ) const |
|
{ |
|
// simple case: have no highlights |
|
if ( m_highlights.isEmpty() ) |
|
return false; |
|
// simple case: we have highlights and no id to match |
|
if ( id == -1 ) |
|
return true; |
|
// iterate on the highlights list to find an entry by id |
|
QValueList< HighlightRect * >::const_iterator it = m_highlights.begin(), end = m_highlights.end(); |
|
for ( ; it != end; ++it ) |
|
if ( (*it)->id == id ) |
|
return true; |
|
return false; |
|
} |
|
|
|
bool KPDFPage::hasPixmap( int id, int width, int height ) const |
|
{ |
|
if ( !m_pixmaps.contains( id ) ) |
|
return false; |
|
if ( width == -1 || height == -1 ) |
|
return true; |
|
QPixmap * p = m_pixmaps[ id ]; |
|
return p ? ( p->width() == width && p->height() == height ) : false; |
|
} |
|
|
|
bool KPDFPage::hasSearchPage() const |
|
{ |
|
return m_text != 0; |
|
} |
|
|
|
bool KPDFPage::hasRect( int mouseX, int mouseY ) const |
|
{ |
|
if ( m_rects.count() < 1 ) |
|
return false; |
|
QValueList< KPDFPageRect * >::const_iterator it = m_rects.begin(), end = m_rects.end(); |
|
for ( ; it != end; ++it ) |
|
if ( (*it)->contains( mouseX, mouseY ) ) |
|
return true; |
|
return false; |
|
} |
|
|
|
bool KPDFPage::hasLink( int mouseX, int mouseY ) const |
|
{ |
|
const KPDFPageRect *r; |
|
r = getRect( mouseX, mouseY); |
|
return r && r->pointerType() == KPDFPageRect::Link; |
|
} |
|
|
|
const KPDFPageRect * KPDFPage::getRect( int mouseX, int mouseY ) const |
|
{ |
|
QValueList< KPDFPageRect * >::const_iterator it = m_rects.begin(), end = m_rects.end(); |
|
for ( ; it != end; ++it ) |
|
if ( (*it)->contains( mouseX, mouseY ) ) |
|
return *it; |
|
return 0; |
|
} |
|
|
|
const KPDFPageTransition * KPDFPage::getTransition() const |
|
{ |
|
return m_transition; |
|
} |
|
|
|
const QString KPDFPage::getTextInRect( const QRect & rect, double zoom ) const |
|
{ |
|
if ( !m_text ) |
|
return QString::null; |
|
int left = (int)((double)rect.left() / zoom), |
|
top = (int)((double)rect.top() / zoom), |
|
right = (int)((double)rect.right() / zoom), |
|
bottom = (int)((double)rect.bottom() / zoom); |
|
GString * text = m_text->getText( left, top, right, bottom ); |
|
QString result = QString::fromUtf8( text->getCString() ); |
|
delete text; |
|
return result; |
|
} |
|
|
|
|
|
HighlightRect * KPDFPage::searchText( const QString & text, bool strictCase, HighlightRect * lastRect ) |
|
{ |
|
if ( text.isEmpty() ) |
|
return 0; |
|
|
|
// create a xpf's Unicode (unsigned int) array for the given text |
|
const QChar * str = text.unicode(); |
|
int len = text.length(); |
|
Unicode u[ len ]; |
|
for (int i = 0; i < len; ++i) |
|
u[i] = str[i].unicode(); |
|
|
|
// find out the direction of search |
|
enum SearchDir { FromTop, NextMatch, PrevMatch } dir = lastRect ? NextMatch : FromTop; |
|
double sLeft, sTop, sRight, sBottom; |
|
if ( dir == NextMatch ) |
|
{ |
|
sLeft = lastRect->left * m_width; |
|
sTop = lastRect->top * m_height; |
|
sRight = lastRect->right * m_width; |
|
sBottom = lastRect->bottom * m_height; |
|
} |
|
|
|
// this loop is only for 'bad case' matches |
|
bool found = false; |
|
while ( !found ) |
|
{ |
|
if ( dir == FromTop ) |
|
found = m_text->findText( u, len, gTrue, gTrue, gFalse, gFalse, &sLeft, &sTop, &sRight, &sBottom ); |
|
else if ( dir == NextMatch ) |
|
found = m_text->findText( u, len, gFalse, gTrue, gTrue, gFalse, &sLeft, &sTop, &sRight, &sBottom ); |
|
else if ( dir == PrevMatch ) |
|
// FIXME: this doesn't work as expected (luckily backward search isn't yet used) |
|
found = m_text->findText( u, len, gTrue, gFalse, gFalse, gTrue, &sLeft, &sTop, &sRight, &sBottom ); |
|
|
|
// if not found (even in case unsensitive search), terminate |
|
if ( !found ) |
|
break; |
|
|
|
// check for case sensitivity |
|
if ( strictCase ) |
|
{ |
|
// since we're in 'Case sensitive' mode, check if words are identical |
|
GString * realText = m_text->getText( sLeft, sTop, sRight, sBottom ); |
|
found = QString::fromUtf8( realText->getCString() ) == text; |
|
if ( !found && dir == FromTop ) |
|
dir = NextMatch; |
|
delete realText; |
|
} |
|
} |
|
|
|
// if the page was found, return a new normalized HighlightRect |
|
if ( found ) |
|
return new HighlightRect( sLeft / m_width, sTop / m_height, sRight / m_width, sBottom / m_height ); |
|
return 0; |
|
} |
|
|
|
void KPDFPage::setPixmap( int id, QPixmap * pixmap ) |
|
{ |
|
if ( m_pixmaps.contains( id ) ) |
|
delete m_pixmaps[id]; |
|
m_pixmaps[id] = pixmap; |
|
} |
|
|
|
void KPDFPage::setSearchPage( TextPage * tp ) |
|
{ |
|
delete m_text; |
|
m_text = tp; |
|
} |
|
|
|
void KPDFPage::setRects( const QValueList< KPDFPageRect * > rects ) |
|
{ |
|
QValueList< KPDFPageRect * >::iterator it = m_rects.begin(), end = m_rects.end(); |
|
for ( ; it != end; ++it ) |
|
delete *it; |
|
m_rects = rects; |
|
} |
|
|
|
void KPDFPage::setHighlight( HighlightRect * hr, bool add ) |
|
{ |
|
if ( !add ) |
|
deleteHighlights( hr->id ); |
|
m_highlights.append( hr ); |
|
} |
|
|
|
void KPDFPage::setTransition( const KPDFPageTransition * transition ) |
|
{ |
|
delete m_transition; |
|
m_transition = transition; |
|
} |
|
|
|
void KPDFPage::deletePixmap( int id ) |
|
{ |
|
if ( m_pixmaps.contains( id ) ) |
|
{ |
|
delete m_pixmaps[ id ]; |
|
m_pixmaps.remove( id ); |
|
} |
|
} |
|
|
|
void KPDFPage::deletePixmapsAndRects() |
|
{ |
|
// delete all stored pixmaps |
|
QMap<int,QPixmap *>::iterator it = m_pixmaps.begin(), end = m_pixmaps.end(); |
|
for ( ; it != end; ++it ) |
|
delete *it; |
|
m_pixmaps.clear(); |
|
// delete PageRects |
|
QValueList< KPDFPageRect * >::iterator rIt = m_rects.begin(), rEnd = m_rects.end(); |
|
for ( ; rIt != rEnd; ++rIt ) |
|
delete *rIt; |
|
m_rects.clear(); |
|
} |
|
|
|
void KPDFPage::deleteHighlights( int id ) |
|
{ |
|
// delete highlights by ID |
|
QValueList< HighlightRect * >::iterator it = m_highlights.begin(), end = m_highlights.end(); |
|
while ( it != end ) |
|
{ |
|
HighlightRect * highlight = *it; |
|
if ( id == -1 || highlight->id == id ) |
|
{ |
|
it = m_highlights.remove( it ); |
|
delete highlight; |
|
} |
|
else |
|
++it; |
|
} |
|
} |
|
|
|
|
|
/** class KPDFPageRect **/ |
|
|
|
KPDFPageRect::KPDFPageRect( int l, int t, int r, int b ) |
|
: m_pointerType( NoPointer ), m_pointer( 0 ) |
|
{ |
|
// assign coordinates swapping them if negative width or height |
|
m_xMin = r > l ? l : r; |
|
m_xMax = r > l ? r : l; |
|
m_yMin = b > t ? t : b; |
|
m_yMax = b > t ? b : t; |
|
} |
|
|
|
KPDFPageRect::~KPDFPageRect() |
|
{ |
|
deletePointer(); |
|
} |
|
|
|
bool KPDFPageRect::contains( int x, int y ) const |
|
{ |
|
return (x > m_xMin) && (x < m_xMax) && (y > m_yMin) && (y < m_yMax); |
|
} |
|
|
|
QRect KPDFPageRect::geometry() const |
|
{ |
|
return QRect( m_xMin, m_yMin, m_xMax - m_xMin, m_yMax - m_yMin ); |
|
} |
|
|
|
void KPDFPageRect::setPointer( void * object, enum PointerType pType ) |
|
{ |
|
deletePointer(); |
|
m_pointer = object; |
|
m_pointerType = pType; |
|
} |
|
|
|
KPDFPageRect::PointerType KPDFPageRect::pointerType() const |
|
{ |
|
return m_pointerType; |
|
} |
|
|
|
const void * KPDFPageRect::pointer() const |
|
{ |
|
return m_pointer; |
|
} |
|
|
|
void KPDFPageRect::deletePointer() |
|
{ |
|
if ( !m_pointer ) |
|
return; |
|
|
|
if ( m_pointerType == Link ) |
|
delete static_cast<KPDFLink*>( m_pointer ); |
|
else |
|
kdDebug() << "Object deletion not implemented for type '" |
|
<< m_pointerType << "' ." << endl; |
|
} |
|
|
|
|
|
/** class HighlightRect **/ |
|
|
|
HighlightRect::HighlightRect() |
|
: id( -1 ), left( 0.0 ), top( 0.0 ), right( 0.0 ), bottom( 0.0 ) |
|
{ |
|
} |
|
|
|
HighlightRect::HighlightRect( double l, double t, double r, double b ) |
|
: id( -1 ), left( l ), top( t ), right( r ), bottom( b ) |
|
{ |
|
}
|
|
|