okular/core/textpage.cpp

345 lines
12 KiB
C++
Raw Normal View History

/***************************************************************************
* Copyright (C) 2005 by Piotr Szymanski <niedakh@gmail.com> *
* *
* 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. *
***************************************************************************/
#include "textpage.h"
#include "area.h"
#include "misc.h"
#include <kdebug.h>
struct SearchPoint
{
SearchPoint() : theIt( 0 ), offset_begin( -1 ), offset_end( -1 ) {}
QList<KPDFTextEntity*>::Iterator theIt;
int offset_begin;
int offset_end;
};
KPDFTextPage::~KPDFTextPage()
{
qDeleteAll(m_words);
qDeleteAll(m_searchPoints);
}
RegularAreaRect * KPDFTextPage::getTextArea ( TextSelection * sel) const
{
/**
It works like this:
There are two cursors, we need to select all the text between them. The coordinates are normalised, leftTop is (0,0)
rightBottom is (1,1), so for cursors start (sx,sy) and end (ex,ey) we start with finding text rectangles under those
points, if not we search for the first that is to the right to it in the same baseline, if none found, then we search
for the first rectangle with a baseline under the cursor, having two points that are the best rectangles to both
of the cursors: (rx,ry)x(tx,ty) for start and (ux,uy)x(vx,vy) for end, we do a
1. (rx,ry)x(1,ty)
2. (0,ty)x(1,uy)
3. (0,uy)x(vx,vy)
To find the closest rectangle to cursor (cx,cy) we search for a rectangle that either contains the cursor
or that has a left border >= cx and bottom border >= cy.
*/
RegularAreaRect * ret= new RegularAreaRect;
int it=-1,itB=-1,itE=-1;
// if (sel->itB==-1)
// ending cursor is higher then start cursor, we need to find positions in reverse
NormalizedRect *tmp=0,*start=0,*end=0;
const NormalizedPoint * startC=sel->start();
const NormalizedPoint * endC=sel->end();
if (sel->dir() == 1 || (sel->itB()==-1 && sel->dir()==0))
{
kWarning() << "running first loop\n";
for (it=0;it<m_words.count();it++)
{
tmp=m_words[it]->area;
if (tmp->contains(startC->x,startC->y)
|| ( tmp->top <= startC->y && tmp->bottom >= startC->y && tmp->left >= startC->x )
|| ( tmp->top >= startC->y))
{
/// we have found the (rx,ry)x(tx,ty)
itB=it;
kWarning() << "start is " << itB << " count is " << m_words.count() << endl;
break;
}
}
sel->itB(itB);
}
itB=sel->itB();
kWarning() << "direction is " << sel->dir() << endl;
kWarning() << "reloaded start is " << itB << " against " << sel->itB() << endl;
if (sel->dir() == 0 || (sel->itE() == -1 && sel->dir()==1))
{
kWarning() << "running second loop\n";
for (it=m_words.count()-1; it>=itB;it--)
{
tmp=m_words[it]->area;
if (tmp->contains(endC->x,endC->y)
|| ( tmp->top <= endC->y && tmp->bottom >= endC->y && tmp->right <= endC->x )
|| ( tmp->bottom <= endC->y))
{
/// we have found the (ux,uy)x(vx,vy)
itE=it;
kWarning() << "ending is " << itE << " count is " << m_words.count() << endl;
kWarning () << "conditions " << tmp->contains(endC->x,endC->y) << " "
<< ( tmp->top <= endC->y && tmp->bottom >= endC->y && tmp->right <= endC->x ) << " " <<
( tmp->top >= endC->y) << endl;
break;
}
}
sel->itE(itE);
}
kWarning() << "reloaded ending is " << itE << " against " << sel->itE() << endl;
if (sel->itB()!=-1 && sel->itE()!=-1)
{
start=m_words[sel->itB()]->area;
end=m_words[sel->itE()]->area;
NormalizedRect first,second,third;/*
first.right=1;
/// if (rx,ry)x(1,ty) intersects the end cursor, there is only one line
bool sameBaseline=end->intersects(first);
kWarning() << "sameBaseline : " << sameBaseline << endl;
if (sameBaseline)
{
first=*start;
first.right=end->right;
first.bottom=end->bottom;
for (it=qMin(sel->itB(),sel->itE()); it<=qMax(sel->itB(),sel->itE());it++)
{
tmp=m_words[it]->area;
if (tmp->intersects(&first))
ret->append(tmp);
}
}
else*/
/// finding out if there are more then one baseline between them is a hard and discussable task
/// we will create a rectangle (rx,0)x(tx,1) and will check how many times does it intersect the
/// areas, if more than one -> we have a three or over line selection
// {
first=*start;
second.top=start->bottom;
first.right=second.right=1;
third=*end;
third.left=second.left=0;
second.bottom=end->top;
for (it=qMin(sel->itB(),sel->itE()); it<=qMax(sel->itB(),sel->itE());it++)
{
tmp=m_words[it]->area;
if (tmp->intersects(&first) || tmp->intersects(&second) || tmp->intersects(&third))
ret->append(tmp);
}
// }
}
ret->simplify();
return ret;
}
- Page/Link: tooltips for links backported - Page: rotation does not switch height and width - Document/Part/Generator: 1. Add API for attaching stuff to the interface: ActionCollection and the Navigation Panel also add possibility to merge an XML .rc file with menu layout. Relevant functions are: QString Generator::getXMLFile(), returns a QString with your .rc file name. void Generator::setupGUI (KActionCollection* , QToolbox* ), add your components to the user interface 2. Supporting backend settings: If during startup, backends which provide a configuration ([X-KDE-oKularHasInternalSettings] set to true) are found, a menu item: configure backends is created, clicking on it results in loading all the generators that have settings, but not those that dont. the Generator::addPages(KConfigDialog *dlg) function should be overloaded by a generator and dlg->addPage should be used to add pages. If a user opens a file that needs an already loaded generator, the already loaded one is used instead of loading another. 3. Error/Warning/Notice sending support, to send a notice/error/warning, add a relevant notice/error/warning(QString& txt ,int duration) to the generator class, and sending a message to the user is as simple as emitting a signal! 4. Intercepting of events generated by the PageView is done by Generator::handleEvent(QEvent*), subclass it, do a switch on QEvent::type(), handle your event and return true if pageview is to proceed with its handling or false if not. 5. Support configuring the KPrinter on the generator side, use Generator::canConfigurePrinter(), return true there, and you get a nonconfigured KPrinter in your Generator::print() 6. PixmapRequest handling update: a.) Generator::canGeneratePixmap is now Generator::canGeneratePixmap(bool async) b.) Document::sendGeneratorRequests is a slot now c.) Old way of sending pixmaps (Document::requestPixmaps(QValueList<PixmapRequest*> checking if we can generate pixmap if not, waiting for receiving) is replaced with: requestPixmaps only queues the pixmap all checking if w can generate is done in sendGeneratorReqest, the sendGeneratorRequest is run in three places: 1. in requestPixmaps when we receive a request 2. in requestDone if pixmapStack is not empty 3. sendGeneratorRequest, apart from removing invalid requests, takes the current request and if generator canGeratePixmap(request->async) it removes the pixmap from stack and sends to generator if not, QTimer::singleshots to itself after 20ms, it ends when stack has no valid pixmap request 7. Added a commented out zoom field to PixmapGenerator, mightcome in handy sometime - TextPage: add instructions that handle simplyfing the RegularAreaRect, no more double painted borders in selection rectangles, this rocks. svn path=/trunk/playground/graphics/oKular/kpdf/; revision=445196
2005-08-10 16:14:39 +00:00
RegularAreaRect* KPDFTextPage::findText(int searchID, const QString &query, SearchDir & direct,
bool strictCase, const RegularAreaRect *area)
{
SearchDir dir=direct;
// invalid search request
if ( query.isEmpty() || area->isNull() )
return 0;
QList<KPDFTextEntity*>::Iterator start;
QList<KPDFTextEntity*>::Iterator end;
if ( !m_searchPoints.contains( searchID ) )
{
// if no previous run of this search is found, then set it to start
// from the beginning (respecting the search direction)
if ( dir == NextRes )
dir = FromTop;
else if ( dir == PrevRes )
dir = FromBottom;
}
bool forward = true;
switch ( dir )
{
case FromTop:
start = m_words.begin();
end = m_words.end();
break;
case FromBottom:
start = m_words.end();
end = m_words.begin();
if ( !m_words.isEmpty() )
{
--start;
}
forward = false;
break;
case NextRes:
start = m_searchPoints[ searchID ]->theIt;
end = m_words.end();
break;
case PrevRes:
start = m_searchPoints[ searchID ]->theIt;
end = m_words.begin();
forward = false;
break;
};
RegularAreaRect* ret = 0;
if ( forward )
{
ret = findTextInternalForward( searchID, query, strictCase, start, end );
}
// TODO implement backward search
#if 0
else
{
ret = findTextInternalBackward( searchID, query, strictCase, start, end );
}
#endif
return ret;
}
RegularAreaRect* KPDFTextPage::findTextInternalForward(int searchID, const QString &query,
bool strictCase, const QList<KPDFTextEntity*>::Iterator &start,
const QList<KPDFTextEntity*>::Iterator &end)
{
- Page/Link: tooltips for links backported - Page: rotation does not switch height and width - Document/Part/Generator: 1. Add API for attaching stuff to the interface: ActionCollection and the Navigation Panel also add possibility to merge an XML .rc file with menu layout. Relevant functions are: QString Generator::getXMLFile(), returns a QString with your .rc file name. void Generator::setupGUI (KActionCollection* , QToolbox* ), add your components to the user interface 2. Supporting backend settings: If during startup, backends which provide a configuration ([X-KDE-oKularHasInternalSettings] set to true) are found, a menu item: configure backends is created, clicking on it results in loading all the generators that have settings, but not those that dont. the Generator::addPages(KConfigDialog *dlg) function should be overloaded by a generator and dlg->addPage should be used to add pages. If a user opens a file that needs an already loaded generator, the already loaded one is used instead of loading another. 3. Error/Warning/Notice sending support, to send a notice/error/warning, add a relevant notice/error/warning(QString& txt ,int duration) to the generator class, and sending a message to the user is as simple as emitting a signal! 4. Intercepting of events generated by the PageView is done by Generator::handleEvent(QEvent*), subclass it, do a switch on QEvent::type(), handle your event and return true if pageview is to proceed with its handling or false if not. 5. Support configuring the KPrinter on the generator side, use Generator::canConfigurePrinter(), return true there, and you get a nonconfigured KPrinter in your Generator::print() 6. PixmapRequest handling update: a.) Generator::canGeneratePixmap is now Generator::canGeneratePixmap(bool async) b.) Document::sendGeneratorRequests is a slot now c.) Old way of sending pixmaps (Document::requestPixmaps(QValueList<PixmapRequest*> checking if we can generate pixmap if not, waiting for receiving) is replaced with: requestPixmaps only queues the pixmap all checking if w can generate is done in sendGeneratorReqest, the sendGeneratorRequest is run in three places: 1. in requestPixmaps when we receive a request 2. in requestDone if pixmapStack is not empty 3. sendGeneratorRequest, apart from removing invalid requests, takes the current request and if generator canGeratePixmap(request->async) it removes the pixmap from stack and sends to generator if not, QTimer::singleshots to itself after 20ms, it ends when stack has no valid pixmap request 7. Added a commented out zoom field to PixmapGenerator, mightcome in handy sometime - TextPage: add instructions that handle simplyfing the RegularAreaRect, no more double painted borders in selection rectangles, this rocks. svn path=/trunk/playground/graphics/oKular/kpdf/; revision=445196
2005-08-10 16:14:39 +00:00
RegularAreaRect* ret=new RegularAreaRect;
// j is the current position in our query
// len is the length of the string in kpdftextentity
// queryLeft is the length of the query we have left
QString str;
KPDFTextEntity* curEntity = 0;
int j=0, len=0, queryLeft=query.length();
int offset = 0;
bool haveMatch=false;
bool dontIncrement=false;
bool offsetMoved = false;
QList<KPDFTextEntity*>::Iterator it = start;
for ( ; it != end; ++it )
{
curEntity = *it;
str = curEntity->txt;
if ( !offsetMoved && ( it == start ) )
{
if ( m_searchPoints.contains( searchID ) )
{
offset = qMax( m_searchPoints[ searchID ]->offset_end, 0 );
}
offsetMoved = true;
}
if ( query.at(j).isSpace() )
{
// lets match newline as a space
#ifdef DEBUG_TEXTPAGE
kDebug(1223) << "newline or space" << endl;
#endif
j++;
queryLeft--;
// since we dont really need to increment this after this
// run of the loop finishes because we are not comparing it
// to any entity, rather we are deducing a situation in a document
dontIncrement=true;
}
else
{
dontIncrement=false;
len=str.length();
int min=qMin(queryLeft,len);
#ifdef DEBUG_TEXTPAGE
kDebug(1223) << str.mid(offset,min) << " : " << query.mid(j,min) << endl;
#endif
// we have equal (or less then) area of the query left as the lengt of the current
// entity
- Page/Link: tooltips for links backported - Page: rotation does not switch height and width - Document/Part/Generator: 1. Add API for attaching stuff to the interface: ActionCollection and the Navigation Panel also add possibility to merge an XML .rc file with menu layout. Relevant functions are: QString Generator::getXMLFile(), returns a QString with your .rc file name. void Generator::setupGUI (KActionCollection* , QToolbox* ), add your components to the user interface 2. Supporting backend settings: If during startup, backends which provide a configuration ([X-KDE-oKularHasInternalSettings] set to true) are found, a menu item: configure backends is created, clicking on it results in loading all the generators that have settings, but not those that dont. the Generator::addPages(KConfigDialog *dlg) function should be overloaded by a generator and dlg->addPage should be used to add pages. If a user opens a file that needs an already loaded generator, the already loaded one is used instead of loading another. 3. Error/Warning/Notice sending support, to send a notice/error/warning, add a relevant notice/error/warning(QString& txt ,int duration) to the generator class, and sending a message to the user is as simple as emitting a signal! 4. Intercepting of events generated by the PageView is done by Generator::handleEvent(QEvent*), subclass it, do a switch on QEvent::type(), handle your event and return true if pageview is to proceed with its handling or false if not. 5. Support configuring the KPrinter on the generator side, use Generator::canConfigurePrinter(), return true there, and you get a nonconfigured KPrinter in your Generator::print() 6. PixmapRequest handling update: a.) Generator::canGeneratePixmap is now Generator::canGeneratePixmap(bool async) b.) Document::sendGeneratorRequests is a slot now c.) Old way of sending pixmaps (Document::requestPixmaps(QValueList<PixmapRequest*> checking if we can generate pixmap if not, waiting for receiving) is replaced with: requestPixmaps only queues the pixmap all checking if w can generate is done in sendGeneratorReqest, the sendGeneratorRequest is run in three places: 1. in requestPixmaps when we receive a request 2. in requestDone if pixmapStack is not empty 3. sendGeneratorRequest, apart from removing invalid requests, takes the current request and if generator canGeratePixmap(request->async) it removes the pixmap from stack and sends to generator if not, QTimer::singleshots to itself after 20ms, it ends when stack has no valid pixmap request 7. Added a commented out zoom field to PixmapGenerator, mightcome in handy sometime - TextPage: add instructions that handle simplyfing the RegularAreaRect, no more double painted borders in selection rectangles, this rocks. svn path=/trunk/playground/graphics/oKular/kpdf/; revision=445196
2005-08-10 16:14:39 +00:00
if ((strictCase)
? (str.mid(offset,min) != query.mid(j,min))
: (str.mid(offset,min).toLower() != query.mid(j,min).toLower())
)
{
// we not have matched
// this means we dont have a complete match
// we need to get back to query start
// and continue the search from this place
haveMatch=false;
ret->clear();
#ifdef DEBUG_TEXTPAGE
kDebug(1223) << "\tnot matched" << endl;
#endif
j=0;
offset = 0;
queryLeft=query.length();
}
else
{
// we have a match
// move the current position in the query
// to the position after the length of this string
// we matched
// substract the length of the current entity from
// the left length of the query
#ifdef DEBUG_TEXTPAGE
kDebug(1223) << "\tmatched" << endl;
#endif
haveMatch=true;
ret->append( curEntity->area );
j+=min;
queryLeft-=min;
}
}
if (haveMatch && queryLeft==0 && j==query.length())
{
// save or update the search point for the current searchID
if ( !m_searchPoints.contains( searchID ) )
{
SearchPoint* newsp = new SearchPoint;
m_searchPoints.insert( searchID, newsp );
}
SearchPoint* sp = m_searchPoints[ searchID ];
sp->theIt = it;
sp->offset_begin = j;
sp->offset_end = j + qMin( queryLeft, len );
ret->simplify();
return ret;
}
}
// end of loop - it means that we've ended the textentities
if ( m_searchPoints.contains( searchID ) )
{
SearchPoint* sp = m_searchPoints[ searchID ];
m_searchPoints.remove( searchID );
delete sp;
}
delete ret;
return 0;
}
QString KPDFTextPage::getText(const RegularAreaRect *area) const
{
if (!area || area->isNull())
return QString();
QString ret = "";
QList<KPDFTextEntity*>::ConstIterator it,end = m_words.end();
KPDFTextEntity * last=0;
- Page/Link: tooltips for links backported - Page: rotation does not switch height and width - Document/Part/Generator: 1. Add API for attaching stuff to the interface: ActionCollection and the Navigation Panel also add possibility to merge an XML .rc file with menu layout. Relevant functions are: QString Generator::getXMLFile(), returns a QString with your .rc file name. void Generator::setupGUI (KActionCollection* , QToolbox* ), add your components to the user interface 2. Supporting backend settings: If during startup, backends which provide a configuration ([X-KDE-oKularHasInternalSettings] set to true) are found, a menu item: configure backends is created, clicking on it results in loading all the generators that have settings, but not those that dont. the Generator::addPages(KConfigDialog *dlg) function should be overloaded by a generator and dlg->addPage should be used to add pages. If a user opens a file that needs an already loaded generator, the already loaded one is used instead of loading another. 3. Error/Warning/Notice sending support, to send a notice/error/warning, add a relevant notice/error/warning(QString& txt ,int duration) to the generator class, and sending a message to the user is as simple as emitting a signal! 4. Intercepting of events generated by the PageView is done by Generator::handleEvent(QEvent*), subclass it, do a switch on QEvent::type(), handle your event and return true if pageview is to proceed with its handling or false if not. 5. Support configuring the KPrinter on the generator side, use Generator::canConfigurePrinter(), return true there, and you get a nonconfigured KPrinter in your Generator::print() 6. PixmapRequest handling update: a.) Generator::canGeneratePixmap is now Generator::canGeneratePixmap(bool async) b.) Document::sendGeneratorRequests is a slot now c.) Old way of sending pixmaps (Document::requestPixmaps(QValueList<PixmapRequest*> checking if we can generate pixmap if not, waiting for receiving) is replaced with: requestPixmaps only queues the pixmap all checking if w can generate is done in sendGeneratorReqest, the sendGeneratorRequest is run in three places: 1. in requestPixmaps when we receive a request 2. in requestDone if pixmapStack is not empty 3. sendGeneratorRequest, apart from removing invalid requests, takes the current request and if generator canGeratePixmap(request->async) it removes the pixmap from stack and sends to generator if not, QTimer::singleshots to itself after 20ms, it ends when stack has no valid pixmap request 7. Added a commented out zoom field to PixmapGenerator, mightcome in handy sometime - TextPage: add instructions that handle simplyfing the RegularAreaRect, no more double painted borders in selection rectangles, this rocks. svn path=/trunk/playground/graphics/oKular/kpdf/; revision=445196
2005-08-10 16:14:39 +00:00
for( it=m_words.begin() ; it != end; ++it )
{
- Page/Link: tooltips for links backported - Page: rotation does not switch height and width - Document/Part/Generator: 1. Add API for attaching stuff to the interface: ActionCollection and the Navigation Panel also add possibility to merge an XML .rc file with menu layout. Relevant functions are: QString Generator::getXMLFile(), returns a QString with your .rc file name. void Generator::setupGUI (KActionCollection* , QToolbox* ), add your components to the user interface 2. Supporting backend settings: If during startup, backends which provide a configuration ([X-KDE-oKularHasInternalSettings] set to true) are found, a menu item: configure backends is created, clicking on it results in loading all the generators that have settings, but not those that dont. the Generator::addPages(KConfigDialog *dlg) function should be overloaded by a generator and dlg->addPage should be used to add pages. If a user opens a file that needs an already loaded generator, the already loaded one is used instead of loading another. 3. Error/Warning/Notice sending support, to send a notice/error/warning, add a relevant notice/error/warning(QString& txt ,int duration) to the generator class, and sending a message to the user is as simple as emitting a signal! 4. Intercepting of events generated by the PageView is done by Generator::handleEvent(QEvent*), subclass it, do a switch on QEvent::type(), handle your event and return true if pageview is to proceed with its handling or false if not. 5. Support configuring the KPrinter on the generator side, use Generator::canConfigurePrinter(), return true there, and you get a nonconfigured KPrinter in your Generator::print() 6. PixmapRequest handling update: a.) Generator::canGeneratePixmap is now Generator::canGeneratePixmap(bool async) b.) Document::sendGeneratorRequests is a slot now c.) Old way of sending pixmaps (Document::requestPixmaps(QValueList<PixmapRequest*> checking if we can generate pixmap if not, waiting for receiving) is replaced with: requestPixmaps only queues the pixmap all checking if w can generate is done in sendGeneratorReqest, the sendGeneratorRequest is run in three places: 1. in requestPixmaps when we receive a request 2. in requestDone if pixmapStack is not empty 3. sendGeneratorRequest, apart from removing invalid requests, takes the current request and if generator canGeratePixmap(request->async) it removes the pixmap from stack and sends to generator if not, QTimer::singleshots to itself after 20ms, it ends when stack has no valid pixmap request 7. Added a commented out zoom field to PixmapGenerator, mightcome in handy sometime - TextPage: add instructions that handle simplyfing the RegularAreaRect, no more double painted borders in selection rectangles, this rocks. svn path=/trunk/playground/graphics/oKular/kpdf/; revision=445196
2005-08-10 16:14:39 +00:00
// provide the string FIXME?: newline handling
if (area->intersects((*it)->area))
{
// kDebug()<< "[" << (*it)->area->left << "," << (*it)->area->top << "]x["<< (*it)->area->right << "," << (*it)->area->bottom << "]\n";
ret += (*it)->txt;
last=*it;
}
}
return ret;
}
- Page/Link: tooltips for links backported - Page: rotation does not switch height and width - Document/Part/Generator: 1. Add API for attaching stuff to the interface: ActionCollection and the Navigation Panel also add possibility to merge an XML .rc file with menu layout. Relevant functions are: QString Generator::getXMLFile(), returns a QString with your .rc file name. void Generator::setupGUI (KActionCollection* , QToolbox* ), add your components to the user interface 2. Supporting backend settings: If during startup, backends which provide a configuration ([X-KDE-oKularHasInternalSettings] set to true) are found, a menu item: configure backends is created, clicking on it results in loading all the generators that have settings, but not those that dont. the Generator::addPages(KConfigDialog *dlg) function should be overloaded by a generator and dlg->addPage should be used to add pages. If a user opens a file that needs an already loaded generator, the already loaded one is used instead of loading another. 3. Error/Warning/Notice sending support, to send a notice/error/warning, add a relevant notice/error/warning(QString& txt ,int duration) to the generator class, and sending a message to the user is as simple as emitting a signal! 4. Intercepting of events generated by the PageView is done by Generator::handleEvent(QEvent*), subclass it, do a switch on QEvent::type(), handle your event and return true if pageview is to proceed with its handling or false if not. 5. Support configuring the KPrinter on the generator side, use Generator::canConfigurePrinter(), return true there, and you get a nonconfigured KPrinter in your Generator::print() 6. PixmapRequest handling update: a.) Generator::canGeneratePixmap is now Generator::canGeneratePixmap(bool async) b.) Document::sendGeneratorRequests is a slot now c.) Old way of sending pixmaps (Document::requestPixmaps(QValueList<PixmapRequest*> checking if we can generate pixmap if not, waiting for receiving) is replaced with: requestPixmaps only queues the pixmap all checking if w can generate is done in sendGeneratorReqest, the sendGeneratorRequest is run in three places: 1. in requestPixmaps when we receive a request 2. in requestDone if pixmapStack is not empty 3. sendGeneratorRequest, apart from removing invalid requests, takes the current request and if generator canGeratePixmap(request->async) it removes the pixmap from stack and sends to generator if not, QTimer::singleshots to itself after 20ms, it ends when stack has no valid pixmap request 7. Added a commented out zoom field to PixmapGenerator, mightcome in handy sometime - TextPage: add instructions that handle simplyfing the RegularAreaRect, no more double painted borders in selection rectangles, this rocks. svn path=/trunk/playground/graphics/oKular/kpdf/; revision=445196
2005-08-10 16:14:39 +00:00