/* * PDFedit - free program for PDF document manipulation. * Copyright (C) 2006, 2007 PDFedit team: Michal Hocko, * Miroslav Jahoda, * Jozef Misutka, * Martin Petricek * * Project is hosted on http://sourceforge.net/projects/pdfedit */ #ifndef __RECT2DARRAY_H__ #define __RECT2DARRAY_H__ #include #include #include QPTRLIST #include QPTRCOLLECTION namespace gui { /* ************************************************************************************************ * BBoxOfObjectOnPage * ************************************************************************************************/ /*- */ template class BBoxOfObjectOnPage : public QRect { public: BBoxOfObjectOnPage(); BBoxOfObjectOnPage( const BBoxOfObjectOnPage & b); BBoxOfObjectOnPage( const QRect &r, T po ); // r must be normalized virtual ~BBoxOfObjectOnPage(); void setUpBBox( BBoxOfObjectOnPage * b ); void setDownBBox( BBoxOfObjectOnPage * b ); void setRightBBox( BBoxOfObjectOnPage * b ); void setLeftBBox( BBoxOfObjectOnPage * b ); void setNextLineFirstBBox( BBoxOfObjectOnPage * b ); void setPrevLineLastBBox( BBoxOfObjectOnPage * b ); void setFirstBBox( BBoxOfObjectOnPage * b ); void setLastBBox( BBoxOfObjectOnPage * b ); const BBoxOfObjectOnPage * getUpBBox( ) const; const BBoxOfObjectOnPage * getDownBBox( ) const; const BBoxOfObjectOnPage * getRightBBox( ) const; const BBoxOfObjectOnPage * getLeftBBox( ) const; const BBoxOfObjectOnPage * getNextLineFirstBBox( ) const; const BBoxOfObjectOnPage * getPrevLineLastBBox( ) const; const BBoxOfObjectOnPage * getFirstBBox( ) const; const BBoxOfObjectOnPage * getLastBBox( ) const; inline bool operator> ( const BBoxOfObjectOnPage & second ) const { return (y() > second.y()) || ((y() == second.y()) && (x() > second.x())); }; inline bool operator< ( const BBoxOfObjectOnPage & second ) const { return (y() < second.y()) || ((y() == second.y()) && (x() < second.x())); }; inline bool operator== ( const BBoxOfObjectOnPage & second ) const { return (y() == second.y()) && (x() == second.x()); }; T getObject() const; private: T object; BBoxOfObjectOnPage * ptr_up, * ptr_down, * ptr_right, * ptr_left, * ptr_first, * ptr_last, * ptr_nextLineFirst, * ptr_prevLineLast; }; /* ************************************************************************************************ * array of rectangles * ************************************************************************************************/ template class RectArray : public Q_PtrList< BBoxOfObjectOnPage > { public: RectArray(); ~RectArray(); void myAppend ( const BBoxOfObjectOnPage * item ); inline bool operator> ( const RectArray & second ) const { return getMinY() > second.getMinY(); } inline bool operator< ( const RectArray & second ) const { return getMinY() < second.getMinY(); } inline bool operator== ( const RectArray & second ) const { return getMinY() == second.getMinY(); } int getMinY() const; int getMaxY() const; void initAllBBoxPtr( RectArray * prev, RectArray * next ); protected: virtual int compareItems( Q_PtrCollection::Item s1, Q_PtrCollection::Item s2 ) { if ( *((BBoxOfObjectOnPage*)s1) == *((BBoxOfObjectOnPage*)s2) ) return 0; return ( *((BBoxOfObjectOnPage*)s1) < *((BBoxOfObjectOnPage*)s2) ? -1 : 1 ); } private: int minY; int maxY; }; /* ************************************************************************************************ * 2D array of rectangles * ************************************************************************************************/ template class Rect2DArray : public Q_PtrList< RectArray > { public: Rect2DArray(); ~Rect2DArray(); void setAutoDeleteAll( bool ada ); void sortAll(); void initAllBBoxPtr(); void myAppend( BBoxOfObjectOnPage * bbox ); protected: virtual int compareItems( Q_PtrCollection::Item s1, Q_PtrCollection::Item s2 ) { if ( *((RectArray*)s1) == *((RectArray*)s2) ) return 0; return ( *((RectArray*)s1) < *((RectArray*)s2) ? -1 : 1 ); } }; } // namespace gui #include "rect2Darray.h" #include #include "util.h" #include "debug.h" #include #include namespace gui { /* ************************************************************************************************ * BBoxOfObjectOnPage * ************************************************************************************************/ template BBoxOfObjectOnPage::BBoxOfObjectOnPage() : QRect() { ptr_up = ptr_down = ptr_right = ptr_left = ptr_nextLineFirst = ptr_prevLineLast = NULL; // object ?; } template BBoxOfObjectOnPage::BBoxOfObjectOnPage( const BBoxOfObjectOnPage & b) : QRect(b.topLeft(),b.bottomRight()) { object = b.object; ptr_up = b.ptr_up; ptr_down = b.ptr_down; ptr_right = b.ptr_right; ptr_left = b.ptr_left; ptr_first = b.ptr_first; ptr_last = b.ptr_last; ptr_nextLineFirst = b.ptr_nextLineFirst; ptr_prevLineLast = b.ptr_prevLineLast; } template BBoxOfObjectOnPage::BBoxOfObjectOnPage( const QRect &r, T po ) : // r must be normalized QRect(r.topLeft(),r.bottomRight()) // QRect(r.left(),r.top(),r.width(),r.height()) { ptr_up = ptr_down = ptr_right = ptr_left = ptr_nextLineFirst = ptr_prevLineLast = NULL; object = po; } template void BBoxOfObjectOnPage::setUpBBox( BBoxOfObjectOnPage * b ) { ptr_up = b; } template void BBoxOfObjectOnPage::setDownBBox( BBoxOfObjectOnPage * b ) { ptr_down = b; } template void BBoxOfObjectOnPage::setRightBBox( BBoxOfObjectOnPage * b ) { ptr_right = b; } template void BBoxOfObjectOnPage::setLeftBBox( BBoxOfObjectOnPage * b ) { ptr_left = b; } template void BBoxOfObjectOnPage::setNextLineFirstBBox( BBoxOfObjectOnPage * b ) { ptr_nextLineFirst = b; } template void BBoxOfObjectOnPage::setPrevLineLastBBox( BBoxOfObjectOnPage * b ) { ptr_prevLineLast = b; } template void BBoxOfObjectOnPage::setFirstBBox( BBoxOfObjectOnPage * b ) { ptr_first = b; } template void BBoxOfObjectOnPage::setLastBBox( BBoxOfObjectOnPage * b ) { ptr_last = b; } template const BBoxOfObjectOnPage * BBoxOfObjectOnPage::getUpBBox( ) const { return ptr_up; } template const BBoxOfObjectOnPage * BBoxOfObjectOnPage::getDownBBox( ) const { return ptr_down; } template const BBoxOfObjectOnPage * BBoxOfObjectOnPage::getRightBBox( ) const { return ptr_right; } template const BBoxOfObjectOnPage * BBoxOfObjectOnPage::getLeftBBox( ) const { return ptr_left; } template const BBoxOfObjectOnPage * BBoxOfObjectOnPage::getNextLineFirstBBox( ) const { return ptr_nextLineFirst; } template const BBoxOfObjectOnPage * BBoxOfObjectOnPage::getPrevLineLastBBox( ) const { return ptr_prevLineLast; } template const BBoxOfObjectOnPage * BBoxOfObjectOnPage::getFirstBBox( ) const { return ptr_first; } template const BBoxOfObjectOnPage * BBoxOfObjectOnPage::getLastBBox( ) const { return ptr_last; } template T BBoxOfObjectOnPage::getObject() const { return object; } template BBoxOfObjectOnPage::~BBoxOfObjectOnPage() { } /* ************************************************************************************************ * array of rectangles * ************************************************************************************************/ template RectArray::RectArray() : Q_PtrList< BBoxOfObjectOnPage >() { minY = std::numeric_limits::max(); maxY = std::numeric_limits::min(); this->setAutoDelete( true ); } template RectArray::~RectArray() { } template void RectArray::myAppend ( const BBoxOfObjectOnPage * item ) { if (! item->isNull()) { //TODO minY = std::min( minY, item->top() ); maxY = std::max( maxY, item->bottom() ); } append( item ); } template int RectArray::getMinY() const { return minY; } template int RectArray::getMaxY() const { return maxY; } template void RectArray::initAllBBoxPtr( RectArray * prev, RectArray * next ) { BBoxOfObjectOnPage * up = NULL, * down = NULL, * right = NULL, * left = NULL, * first = NULL, * last = NULL, * cur = NULL, * nextLineFirst = NULL, * prevLineLast = NULL, * curNextLine = NULL, * curPrevLine = NULL; Q_PtrListIterator< BBoxOfObjectOnPage > * prevLineItems = NULL, * nextLineItems = NULL; if (prev != NULL) { prevLineItems = new Q_PtrListIterator< BBoxOfObjectOnPage > (*prev); prevLineLast = prevLineItems->toLast(); curPrevLine = prevLineItems->toFirst(); } if (next != NULL) { nextLineItems = new Q_PtrListIterator< BBoxOfObjectOnPage > (*next); nextLineFirst = curNextLine = nextLineItems->toFirst(); } Q_PtrListIterator< BBoxOfObjectOnPage > currentLine (*this); cur = currentLine.toFirst(); first = this->getFirst(); last = this->getLast(); right = ++currentLine; while (cur != NULL) { if (prevLineLast) { assert( prevLineLast->top() != cur->top() ); } if (nextLineFirst) { assert( nextLineFirst->top() != cur->top() ); } cur->setPrevLineLastBBox( prevLineLast ); cur->setNextLineFirstBBox( nextLineFirst ); cur->setLeftBBox( left ); cur->setRightBBox( right ); cur->setFirstBBox( first ); cur->setLastBBox( last ); while ((curPrevLine != NULL) && (cur->x() > curPrevLine->right())) curPrevLine = ++(* prevLineItems); if ((curPrevLine != NULL) && ((std::max(curPrevLine->left(), cur->left()) <= std::min(cur->right(), curPrevLine->right()))) ) { up = curPrevLine; } else up = NULL; while ((curNextLine != NULL) && (cur->x() > curNextLine->right())) curNextLine = ++(* nextLineItems); if ((curNextLine != NULL) && ((std::max(curNextLine->left(), cur->left()) <= std::min(cur->right(), curNextLine->right()))) ) { down = curNextLine; } else down = NULL; cur->setUpBBox( up ); cur->setDownBBox( down ); left = cur; cur = right; right = ++currentLine; } } /* ************************************************************************************************ * 2D array of rectangles * ************************************************************************************************/ template Rect2DArray::Rect2DArray() : Q_PtrList< RectArray >() { this->setAutoDelete(true); } template Rect2DArray::~Rect2DArray() { } template void Rect2DArray::setAutoDeleteAll( bool ada ) { this->setAutoDelete( ada ); Q_PtrListIterator< RectArray > it ( *this ); RectArray * current = it.toFirst(); while ((current = it.current()) != NULL) { current->setAutoDelete( ada ); ++it; } } template void Rect2DArray::sortAll() { this->sort(); Q_PtrListIterator< RectArray > it ( *this ); RectArray * current = it.toFirst(); while ((current = it.current()) != NULL) { current->sort(); ++it; } } template void Rect2DArray::initAllBBoxPtr() { RectArray * prev = NULL; RectArray * current = NULL; RectArray * next = NULL; sortAll(); Q_PtrListIterator< RectArray > it ( *this ); current = it.toFirst(); next = ++it; while (current != NULL) { current->initAllBBoxPtr( prev, next ); prev = current; current = next; next = ++it; } } template void Rect2DArray::myAppend( BBoxOfObjectOnPage * bbox ) { if (bbox == NULL) return; bool toAppend = true; Q_PtrListIterator< RectArray > it ( *this ); RectArray * current = it.toFirst(); while (((current = it.current()) != NULL) && toAppend) { if ( current->getMinY() == bbox->top() ) { current->myAppend( bbox ); toAppend = false; } ++it; } if (toAppend) { current = new RectArray(); current->myAppend( bbox ); append( current ); } } } // namespace gui #endif