Scribus Developer Documentation - API
logo-pen

Scribus Developer Documentation - API

canvas.cpp

Go to the documentation of this file.
00001 /*
00002  For general Scribus (>=1.3.2) copyright and licensing information please refer
00003  to the COPYING file provided with the program. Following this notice may exist
00004  a copyright and/or license notice that predates the release of Scribus 1.3.2
00005  for which a new license (GPL+exception) is in place.
00006  */
00007 /***************************************************************************
00008 *                                                                         *
00009 *   This program is free software; you can redistribute it and/or modify  *
00010 *   it under the terms of the GNU General Public License as published by  *
00011 *   the Free Software Foundation; either version 2 of the License, or     *
00012 *   (at your option) any later version.                                   *
00013 *                                                                         *
00014 ***************************************************************************/
00015 
00016 
00017 #include <QDebug>
00018 
00019 
00020 #include "canvas.h"
00021 #include "canvasmode.h"
00022 #include "page.h"
00023 #include "pageitem_textframe.h"
00024 #include "prefsmanager.h"
00025 #include "scribusdoc.h"
00026 #include "scpainter.h"
00027 #include "scribusview.h"
00028 #include "selection.h"
00029 #include "util.h"
00030 
00031 #define DRAW_DEBUG_LINES 0
00032 
00033 static QPoint contentsToViewport(QPoint p)
00034 {
00035     return p;
00036 }
00037 
00038 
00039 void CanvasViewMode::init()
00040 {   
00041     scale = 1;
00042     
00043     previewMode = false;
00044     viewAsPreview = false;
00045     previewVisual = -1;
00046     
00047     m_MouseButtonPressed = false;
00048     operItemMoving = false;
00049     operItemResizing = false;
00050     operItemResizeInEditMode = false;
00051     redrawPolygon.resize(0);
00052     linkedFramesToShow.clear();
00053     
00054     drawSelectedItemsWithControls = false;
00055     drawFramelinksWithContents = false;
00056     
00057     forceRedraw = false;
00058 }
00059     
00060 Canvas::Canvas(ScribusDoc* doc, ScribusView* parent) : QWidget(parent), m_doc(doc), m_view(parent)
00061 {
00062     setAutoFillBackground(true);
00063     m_buffer = QPixmap();
00064     m_bufferRect = QRect();
00065     m_viewMode.init();
00066     m_renderMode = RENDER_NORMAL;
00067 }
00068 
00069 
00070 FPoint Canvas::localToCanvas(QPoint p) const
00071 {
00072     return FPoint(p.x() / m_viewMode.scale + m_doc->minCanvasCoordinate.x() , 
00073                   p.y() / m_viewMode.scale + m_doc->minCanvasCoordinate.y());   
00074 }
00075 /*
00076 FPoint Canvas::localToCanvas(QPointF p) const
00077 {
00078     return FPoint(p.x() / m_viewMode.scale + m_doc->minCanvasCoordinate.x() , 
00079                   p.y() / m_viewMode.scale + m_doc->minCanvasCoordinate.y());   
00080 }
00081 */
00082 QPoint Canvas::canvasToLocal(FPoint p) const
00083 {
00084     return  QPoint(qRound((p.x() - m_doc->minCanvasCoordinate.x()) * m_viewMode.scale),
00085                    qRound((p.y() - m_doc->minCanvasCoordinate.y()) * m_viewMode.scale));
00086 }
00087 
00088 QPoint Canvas::canvasToLocal(QPointF p) const
00089 {
00090     return  QPoint(qRound((p.x() - m_doc->minCanvasCoordinate.x()) * m_viewMode.scale),
00091                    qRound((p.y() - m_doc->minCanvasCoordinate.y()) * m_viewMode.scale));
00092 }
00093 
00094 QRect Canvas::canvasToLocal(QRectF p) const
00095 {
00096     return  QRect(qRound((p.x() - m_doc->minCanvasCoordinate.x()) * m_viewMode.scale),
00097                   qRound((p.y() - m_doc->minCanvasCoordinate.y()) * m_viewMode.scale),
00098                   qRound(p.width() * m_viewMode.scale), 
00099                   qRound(p.height() * m_viewMode.scale));
00100 }
00101 
00102 QPoint Canvas::canvasToGlobal(FPoint p) const
00103 {
00104     return mapToGlobal(QPoint(0,0)) + canvasToLocal(p);
00105 }
00106 
00107 QPoint Canvas::canvasToGlobal(QPointF p) const
00108 {
00109     return mapToGlobal(QPoint(0,0)) + canvasToLocal(p);
00110 }
00111 
00112 QRect Canvas::canvasToGlobal(QRectF p) const
00113 {
00114     return QRect(mapToGlobal(QPoint(0,0) + canvasToLocal(p.topLeft())), 
00115                  QSize(qRound(p.width() * m_viewMode.scale), qRound(p.height() * m_viewMode.scale)));
00116 }
00117 
00118 FPoint Canvas::globalToCanvas(QPoint p) const
00119 {
00120     return localToCanvas(p - mapToGlobal(QPoint(0,0)));
00121 }
00122 /*
00123 FPoint Canvas::globalToCanvas(QPointF p) const
00124 {
00125     return localToCanvas(p - mapToGlobal(QPoint(0, 0)));
00126 }
00127 */
00128 QRectF Canvas::globalToCanvas(QRect p) const
00129 {
00130     FPoint org = globalToCanvas(p.topLeft());
00131     return QRectF(org.x(), org.y(), p.width() / m_viewMode.scale, p.height() / m_viewMode.scale);
00132 }
00133 /*
00134 QRectF Canvas::globalToCanvas(QRectF p) const
00135 {
00136     FPoint org = globalToCanvas(p.topLeft());
00137     return QRectF(org.x(), org.y(), p.width() / m_viewMode.scale, p.height() / m_viewMode.scale);
00138 }
00139 */
00140 bool Canvas::hitsCanvasPoint(QPoint globalPoint, FPoint canvasPoint) const
00141 {
00142     QPoint localPoint1 = globalPoint - mapToGlobal(QPoint(0,0));
00143     QPoint localPoint2 = canvasToLocal(canvasPoint);
00144     int radius = m_doc->guidesSettings.grabRad;
00145     return qAbs(localPoint1.x() - localPoint2.x()) < radius
00146         && qAbs(localPoint1.y() - localPoint2.y()) < radius;
00147 }
00148 
00149 bool Canvas::hitsCanvasPoint(QPoint globalPoint, QPointF canvasPoint) const
00150 {
00151     QPoint localPoint1 = globalPoint - mapToGlobal(QPoint(0,0));
00152     QPoint localPoint2 = canvasToLocal(canvasPoint);
00153     int radius = m_doc->guidesSettings.grabRad;
00154     return qAbs(localPoint1.x() - localPoint2.x()) < radius
00155         && qAbs(localPoint1.y() - localPoint2.y()) < radius;
00156 }
00157 
00158 
00164 Canvas::FrameHandle Canvas::frameHitTest(QPointF canvasPoint, PageItem* item) const
00165 {
00166     Canvas::FrameHandle result = frameHitTest(item->getTransform().inverted().map(canvasPoint), QRectF(0, 0, item->width(), item->height()));
00167 //  qDebug() << "frameHitTest for item" << item->ItemNr 
00168 //      << item->getTransform().inverted().map(canvasPoint) 
00169 //      << item->getTransform().inverted() 
00170 //      << QRectF(0, 0, item->width(), item->height());
00171     return result;
00172 }
00173 
00174 
00175 static double length2(const QPointF& p)
00176 {
00177     return p.x()*p.x() + p.y()*p.y();
00178 }
00179 
00180 Canvas::FrameHandle Canvas::frameHitTest(QPointF canvasPoint, QRectF frame) const
00181 {
00182     FrameHandle result = INSIDE;
00183     const double radius = m_doc->guidesSettings.grabRad / m_viewMode.scale;
00184     const double radius2 = radius * radius;
00185     double resultDistance = radius2 * 10.0; // far off
00186     
00187     const double frameWidth = frame.width();
00188     const double frameHeight = frame.height();
00189     const QPointF frameOrigin = frame.topLeft();
00190     
00191     if (canvasPoint.x() < frameOrigin.x() - radius ||
00192         canvasPoint.x() > frameOrigin.x() + frameWidth + radius ||
00193         canvasPoint.y() < frameOrigin.y() - radius ||
00194         canvasPoint.y() > frameOrigin.y() + frameHeight + radius)
00195     {
00196 //      qDebug() << "framehittest" << canvasPoint << frame << "-> OUTSIDE";
00197         return OUTSIDE;
00198     }
00199     
00200     QPointF framePoint = frameOrigin;
00201     double distance = length2(canvasPoint - framePoint);
00202     if (distance < radius2 && distance < resultDistance)
00203     {
00204         result = NORTHWEST;
00205         resultDistance = distance;
00206     }
00207     
00208     framePoint.setX(frameOrigin.x() + frameWidth/2);
00209     distance = length2(canvasPoint - framePoint);
00210     if (distance < radius2 && distance < resultDistance)
00211     {
00212         result = NORTH;
00213         resultDistance = distance;
00214     }
00215     
00216     framePoint.setX(frameOrigin.x() + frameWidth);
00217     distance = length2(canvasPoint - framePoint);
00218     if (distance < radius2 && distance < resultDistance)
00219     {
00220         result = NORTHEAST;
00221         resultDistance = distance;
00222     }
00223     
00224     framePoint.setY(frameOrigin.y() + frameHeight/2);
00225     distance = length2(canvasPoint - framePoint);
00226     if (distance < radius2 && distance < resultDistance)
00227     {
00228         result = EAST;
00229         resultDistance = distance;
00230     }
00231     
00232     framePoint.setY(frameOrigin.y() + frameHeight);
00233     distance = length2(canvasPoint - framePoint);
00234     if (distance < radius2 && distance < resultDistance)
00235     {
00236         result = SOUTHEAST;
00237         resultDistance = distance;
00238     }
00239     
00240     framePoint.setX(frameOrigin.x() + frameWidth/2);
00241     distance = length2(canvasPoint - framePoint);
00242     if (distance < radius2 && distance < resultDistance)
00243     {
00244         result = SOUTH;
00245         resultDistance = distance;
00246     }
00247     
00248     framePoint.setX(frameOrigin.x());
00249     distance = length2(canvasPoint - framePoint);
00250     if (distance < radius2 && distance < resultDistance)
00251     {
00252         result = SOUTHWEST;
00253         resultDistance = distance;
00254     }
00255     
00256     framePoint.setY(frameOrigin.y() + frameHeight/2);
00257     distance = length2(canvasPoint - framePoint);
00258     if (distance < radius2 && distance < resultDistance)
00259     {
00260         result = WEST;
00261         //resultDistance = distance;
00262     }
00263     
00264 //  qDebug() << "framehittest" << canvasPoint << frame << "->" << result;
00265     return result;
00266 }
00267 
00268 
00269 PageItem* Canvas::itemUnderCursor(QPoint globalPos, PageItem* itemAbove, bool allowInGroup, bool allowMasterItems) const
00270 {
00271     PageItem* currItem;
00272     QRectF mouseArea = globalToCanvas(QRect(globalPos, QSize(2*m_doc->guidesSettings.grabRad, 2*m_doc->guidesSettings.grabRad)));
00273     // look for masterpage items first
00274     if (allowMasterItems && !m_doc->masterPageMode() && m_doc->currentPage()->FromMaster.count() != 0)
00275     {
00276         Page* Mp = m_doc->MasterPages.at(m_doc->MasterNames[m_doc->currentPage()->MPageNam]);
00277         // if itemAbove is given, we expect to find it among the masterpage items of this page
00278         int currNr = itemAbove? m_doc->currentPage()->FromMaster.indexOf(itemAbove)-1 : m_doc->currentPage()->FromMaster.count()-1;
00279         if (currNr < 0)
00280             return NULL;
00281         while (currNr >= 0)
00282         {
00283             currItem = m_doc->currentPage()->FromMaster.at(currNr);
00284             QMatrix itemPos;
00285             if ((currItem->LayerNr == m_doc->activeLayer()) && (!m_doc->layerLocked(currItem->LayerNr)))
00286             {
00287                 if (!currItem->ChangedMasterItem)
00288                 {
00289                     itemPos.translate(-Mp->xOffset() + m_doc->currentPage()->xOffset(), -Mp->yOffset() + m_doc->currentPage()->yOffset());
00290                 }
00291                 currItem->getTransform(itemPos);
00292                 QPainterPath currPath(itemPos.map(QPointF(0,0)));
00293                 currPath.lineTo(itemPos.map(QPointF(currItem->width(), 0)));
00294                 currPath.lineTo(itemPos.map(QPointF(currItem->width(), currItem->height())));
00295                 currPath.lineTo(itemPos.map(QPointF(0, currItem->height())));
00296                 currPath.closeSubpath();
00297                 QPainterPath currClip;
00298                 currClip.addPolygon(itemPos.map(QPolygonF(currItem->Clip)));
00299                 currClip.closeSubpath();
00300 //              qDebug() << "itemUnderCursor: master" << currNr << mouseArea << currPath.toFillPolygon() << currPath.intersects(mouseArea);
00301 //              if (currClip.intersects(mouseArea))
00302 //                  qDebug() << "    within Clip:" << currClip.toFillPolygon();
00303                 if (currPath.intersects(mouseArea) || currClip.intersects(mouseArea))
00304 //              if ((QRegion(itemPos.map(QPolygon(QRect(0, 0, static_cast<int>(currItem->width()), static_cast<int>(currItem->height()))))).contains(mpo.toRect())) ||
00305 //                  (QRegion(currItem->Clip * itemPos).contains(mpo.toRect())))
00306                 {
00307                     if (currItem->Groups.count() != 0 && !allowInGroup)
00308                     {
00309                         // look for the group control
00310                         // FIXME: Items or MasterPageItems??
00311                         for (int ga=0; ga < m_doc->Items->count(); ++ga)
00312                         {
00313                             if (m_doc->Items->at(ga)->Groups.count() != 0 
00314                                 && m_doc->Items->at(ga)->Groups.top() == currItem->Groups.top() 
00315                                 && m_doc->Items->at(ga)->controlsGroup())
00316                             {
00317                                 currItem = m_doc->Items->at(ga);
00318                                 break;
00319                             }
00320                         }
00321                     }
00322                     return currItem;
00323                 }
00324             }
00325             --currNr;
00326         }
00327     }
00328     // now look for normal items
00329     if (m_doc->Items->count() == 0)
00330         return NULL;
00331 
00332     int currNr = itemAbove? m_doc->Items->indexOf(itemAbove)-1 : m_doc->Items->count()-1;
00333 //  qDebug() << "itemUnderCursor searching from" << currNr << itemAbove << m_doc->Items->count();
00334     while (currNr >= 0)
00335     {
00336         currItem = m_doc->Items->at(currNr);
00337         if ((m_doc->masterPageMode())  && (!((currItem->OwnPage == -1) || (currItem->OwnPage == static_cast<int>(m_doc->currentPage()->pageNr())))))
00338         {
00339             --currNr;
00340             continue;
00341         }
00342         if ((currItem->LayerNr == m_doc->activeLayer()) && (!m_doc->layerLocked(currItem->LayerNr)))
00343         {
00344             QMatrix itemPos = currItem->getTransform();
00345             QPainterPath currPath(itemPos.map(QPointF(0,0)));
00346             currPath.lineTo(itemPos.map(QPointF(currItem->width(), 0)));
00347             currPath.lineTo(itemPos.map(QPointF(currItem->width(), currItem->height())));
00348             currPath.lineTo(itemPos.map(QPointF(0, currItem->height())));
00349             currPath.closeSubpath();
00350             QPainterPath currClip;
00351             currClip.addPolygon(itemPos.map(QPolygonF(currItem->Clip)));
00352             currClip.closeSubpath();
00353 //          qDebug() << "itemUnderCursor:" << currNr << mouseArea << currPath.toFillPolygon() << currPath.intersects(mouseArea);
00354 //          if (currClip.intersects(mouseArea))
00355 //              qDebug() << "    within Clip:" << currClip.toFillPolygon();
00356             if (currPath.intersects(mouseArea) || currClip.intersects(mouseArea))
00357 //              if ((QRegion(itemPos.map(QPolygon(QRect(0, 0, static_cast<int>(currItem->width()), static_cast<int>(currItem->height()))))).contains(mpo.toRect())) ||
00358 //              (QRegion(currItem->Clip * itemPos).contains(mpo.toRect())))
00359             {
00360                 if (currItem->Groups.count() != 0 && !allowInGroup)
00361                 {
00362                     // look for the group control
00363                     for (int ga=0; ga < m_doc->Items->count(); ++ga)
00364                     {
00365                         if (m_doc->Items->at(ga)->Groups.count() != 0 
00366                             && m_doc->Items->at(ga)->Groups.top() == currItem->Groups.top() 
00367                             && m_doc->Items->at(ga)->controlsGroup())
00368                         {
00369                             currItem = m_doc->Items->at(ga);
00370                             break;
00371                         }
00372                     }
00373                 }
00374                 return currItem;                
00375             }
00376         }
00377         --currNr;
00378     }
00379     return NULL;
00380 }
00381 
00382 
00383 /*
00384  Rendermodes:
00385  
00386  m_buffer holds the current page(s)
00387  m_bufferRect describes the contents in local coordinates:
00388 
00389  minCanvasCoordinate |-> local (0,0) 
00390  
00391  (0,0) |-> local (scale*minCanvasCoordinate) 
00392  
00393  local m_bufferRect.topLeft |-> buffer (0,0)
00394  
00395  
00396  */
00397 
00398 void Canvas::setRenderMode(RenderMode mode)
00399 {
00400     if ( (mode < RENDER_SELECTION_SEPARATE) != (m_renderMode < RENDER_SELECTION_SEPARATE) )
00401     {
00402         clearBuffers();
00403     }
00404     m_renderMode = mode;
00405 }
00406 
00407 
00408 void Canvas::clearBuffers()
00409 {
00410     m_buffer = QPixmap();
00411     m_bufferRect = QRect();
00412     m_selectionBuffer = QPixmap();
00413     m_selectionRect = QRect();
00414 }
00415 
00416 
00417 void Canvas::adjustBuffer()
00418 {
00419     QRect viewport(-x(), -y(), m_view->viewport()->width(), m_view->viewport()->height());
00420     FPoint minCanvasCoordinate = m_doc->minCanvasCoordinate;
00421     if (minCanvasCoordinate != m_oldMinCanvasCoordinate)
00422     {
00423         m_bufferRect.translate(qRound((m_oldMinCanvasCoordinate.x() - minCanvasCoordinate.x())*m_viewMode.scale),
00424                                qRound((m_oldMinCanvasCoordinate.y() - minCanvasCoordinate.y())*m_viewMode.scale));
00425         m_oldMinCanvasCoordinate = minCanvasCoordinate;
00426     }
00427 #if DRAW_DEBUG_LINES
00428     qDebug() << "adjust buffer" << m_bufferRect << "for viewport" << viewport;
00429 #endif
00430     if (!m_bufferRect.isValid())
00431     {
00432         m_bufferRect = viewport;
00433         m_buffer = QPixmap(m_bufferRect.width(), m_bufferRect.height());
00434         fillBuffer(&m_buffer, m_bufferRect.topLeft(), m_bufferRect);        
00435 #if DRAW_DEBUG_LINES
00436         QPainter p(&m_buffer);
00437         p.setPen(Qt::blue);
00438         p.drawLine(0, 0, m_buffer.width(), m_buffer.height());
00439         p.drawLine(m_buffer.width(), 0, 0, m_buffer.height());
00440         p.end();
00441 #endif
00442     }
00443     else if (!m_bufferRect.contains(viewport))
00444     {
00445         // enlarge buffer by half a screenwidth:
00446         QRect newRect(m_bufferRect);
00447         if (m_bufferRect.left() > viewport.left())
00448             newRect.setLeft(qMin(newRect.left() - viewport.width()/2, viewport.left()));
00449         if (m_bufferRect.right() < viewport.right())
00450             newRect.setRight(qMax(newRect.right() + viewport.width()/2, viewport.right()));
00451         if (m_bufferRect.top() > viewport.top())
00452             newRect.setTop(qMin(newRect.top() - viewport.height()/2, viewport.top()));
00453         if (m_bufferRect.bottom() < viewport.bottom())
00454             newRect.setBottom(qMax(newRect.bottom() + viewport.height()/2, viewport.bottom()));
00455         // if too large, try something smaller:
00456         if (newRect.width() > 3*viewport.width())
00457         {
00458             newRect.setLeft(qMax(viewport.left() - viewport.width()/2, newRect.left()));
00459             newRect.setRight(qMin(viewport.right() + viewport.width()/2, newRect.right()));
00460         }
00461         if (newRect.height() > 3*viewport.height())
00462         {
00463             newRect.setTop(qMax(viewport.top() - viewport.height()/2, newRect.top()));
00464             newRect.setBottom(qMin(viewport.bottom() + viewport.height()/2, newRect.bottom()));
00465         }
00466         if (!m_bufferRect.intersects(newRect))
00467         {
00468             qDebug() << "fresh buffer" << newRect << "was" << m_bufferRect;
00469             m_bufferRect = newRect;
00470             m_buffer = QPixmap(m_bufferRect.width(), m_bufferRect.height());
00471             fillBuffer(&m_buffer, m_bufferRect.topLeft(), m_bufferRect);        
00472 #if DRAW_DEBUG_LINES
00473             QPainter p(&m_buffer);
00474             p.setPen(Qt::blue);
00475             p.drawLine(0, 0, m_buffer.width(), m_buffer.height());
00476             p.drawLine(m_buffer.width(), 0, 0, m_buffer.height());
00477             p.end();
00478 #endif          
00479         }
00480         else
00481         {
00482             // copy buffer:
00483             QPixmap newBuffer(newRect.width(), newRect.height());
00484             QPainter p(&newBuffer);
00485             int xpos = m_bufferRect.x() - newRect.x();
00486             int ypos = m_bufferRect.y() - newRect.y();
00487             int x = 0;
00488             int y = 0;
00489             int width = m_bufferRect.width();
00490             int height = m_bufferRect.height();
00491             if (xpos < 0)
00492             {
00493                 x = -xpos;
00494                 width -= x;
00495                 xpos = 0;
00496             }
00497             if (ypos < 0)
00498             {
00499                 y = -ypos;
00500                 height -= y;
00501                 ypos = 0;
00502             }
00503             if (xpos + width > newRect.width())
00504             {
00505                 width = newRect.width() - xpos;
00506             }
00507             if (ypos + height > newRect.height())
00508             {
00509                 height = newRect.height() - ypos;
00510             }
00511             p.drawPixmap(xpos, ypos, m_buffer, x, y,  width, height);
00512 #if DRAW_DEBUG_LINES
00513             p.setPen(Qt::blue);
00514             p.drawLine(xpos, ypos+height/2, xpos+width/2, ypos);
00515             p.drawLine(xpos+width, ypos+height/2, xpos+width/2, ypos);
00516             p.drawLine(xpos, ypos+height/2, xpos+width/2, ypos+height);
00517             p.drawLine(xpos+width, ypos+height/2, xpos+width/2, ypos+height);
00518             qDebug() << "adjust buffer old" << m_bufferRect << "@" << xpos << ypos << "--> new" << newRect;
00519 #endif
00520             p.end();
00521             if (newRect.top() < m_bufferRect.top())
00522             {
00523                 fillBuffer(&newBuffer, newRect.topLeft(), 
00524                            QRect(newRect.left(), 
00525                                  newRect.top(), 
00526                                  newRect.width(), 
00527                                  m_bufferRect.top() - newRect.top() + 1));
00528             }
00529             if (newRect.bottom() > m_bufferRect.bottom())
00530             {
00531                 fillBuffer(&newBuffer, newRect.topLeft(), 
00532                            QRect(newRect.left(), 
00533                                  m_bufferRect.bottom() - 1,
00534                                  newRect.width(), 
00535                                  newRect.bottom() - m_bufferRect.bottom() + 1));
00536             }
00537             if (newRect.left() < m_bufferRect.left())
00538             {
00539                 fillBuffer(&newBuffer, newRect.topLeft(), 
00540                            QRect(newRect.left(), 
00541                                  m_bufferRect.top(), 
00542                                  m_bufferRect.left() - newRect.left() + 1, 
00543                                  m_bufferRect.height()));
00544             }
00545             if (newRect.right() > m_bufferRect.right())
00546             {
00547                 fillBuffer(&newBuffer, newRect.topLeft(), 
00548                            QRect(m_bufferRect.right() - 1, 
00549                                  m_bufferRect.top(), 
00550                                  newRect.right() - m_bufferRect.right() + 1, 
00551                                  m_bufferRect.height()));
00552             }
00553             m_buffer = newBuffer;
00554             m_bufferRect = newRect;
00555 #if DRAW_DEBUG_LINES
00556             QPainter p2(&m_buffer);
00557             p2.setPen(Qt::blue);
00558             p2.drawRect(xpos, ypos, width, height);
00559             p2.end();
00560 #endif
00561         }
00562     }
00563 }
00564 
00565 void Canvas::fillBuffer(QPaintDevice* buffer, QPoint bufferOrigin, QRect clipRect)
00566 {
00567     QPainter painter(buffer);
00568     painter.translate(-bufferOrigin.x(), -bufferOrigin.y());
00569     drawContents(&painter,
00570                  clipRect.x(),
00571                  clipRect.y(),
00572                  clipRect.width(), clipRect.height());
00573     painter.end();
00574 }
00575 
00583 void Canvas::paintEvent ( QPaintEvent * p )
00584 {
00585     if (m_doc->isLoading())
00586         return;
00587 
00588     // fill buffer if necessary
00589     adjustBuffer(); 
00590                 
00591     QPainter qp(this);
00592     
00593     switch (m_renderMode)
00594     {
00595         case RENDER_NORMAL:
00596         {
00597 #if DRAW_DEBUG_LINES
00598             qDebug() << "update Buffer:" << m_bufferRect << p->rect() << m_viewMode.forceRedraw;
00599 #endif
00600             if (m_viewMode.forceRedraw)
00601             {
00602                 fillBuffer(&m_buffer, m_bufferRect.topLeft(), p->rect());
00603             }
00604             int xV = p->rect().x() - m_bufferRect.x();
00605             int yV = p->rect().y() - m_bufferRect.y();
00606             int wV = p->rect().width();
00607             int hV = p->rect().height();
00608             if (hV > 0 && wV > 0)
00609             {
00610                 qp.drawPixmap(p->rect().x(), p->rect().y(), m_buffer, xV, yV,  wV, hV);
00611 #if DRAW_DEBUG_LINES
00612                 qDebug() << "normal rendering" << xV << yV << wV << hV << "at" << p->rect().x() << p->rect().y();
00613                 qp.setPen(Qt::blue);
00614                 qp.drawLine(p->rect().x(), p->rect().y(), p->rect().x() + p->rect().width(), p->rect().y() + p->rect().height());
00615                 qp.drawLine(p->rect().x() + p->rect().width(), p->rect().y(), p->rect().x(), p->rect().y() + p->rect().height());
00616 #endif
00617             }
00618         }
00619             if (m_doc->appMode != modeNormal)
00620             {
00621                 qp.save();
00622                 qp.scale(m_viewMode.scale, m_viewMode.scale);
00623                 qp.translate(-m_doc->minCanvasCoordinate.x() * m_viewMode.scale,
00624                              -m_doc->minCanvasCoordinate.y() * m_viewMode.scale);
00625                 drawControls( &qp );
00626                 qp.restore();
00627             }               
00628             break;
00629         case RENDER_BUFFERED:
00630             {
00631                 int xV = p->rect().x() - m_bufferRect.x();
00632                 int yV = p->rect().y() - m_bufferRect.y();
00633                 int wV = p->rect().width();
00634                 int hV = p->rect().height();
00635                 if (xV < 0)
00636                 {
00637                     wV += xV;
00638                     xV = 0;
00639                 }
00640                 if (yV < 0)
00641                 {
00642                     hV += yV;
00643                     yV = 0;
00644                 }
00645                 if (hV > 0 && wV > 0)
00646                 {
00647                     qp.drawPixmap(p->rect().x(), p->rect().y(), m_buffer, xV, yV,  wV, hV);
00648     #if DRAW_DEBUG_LINES
00649                     qDebug() << "buffered rendering" << xV << yV << wV << hV << "at" << p->rect().x() << p->rect().y();
00650                     qp.setPen(Qt::green);
00651                     qp.drawLine(p->rect().x(), p->rect().y(), p->rect().x() + p->rect().width(), p->rect().y() + p->rect().height());
00652                     qp.drawLine(p->rect().x() + p->rect().width(), p->rect().y(), p->rect().x(), p->rect().y() + p->rect().height());
00653     #endif
00654                 }
00655                 if (m_doc->appMode != modeNormal)
00656                 {
00657                     qp.save();
00658                     qp.scale(m_viewMode.scale, m_viewMode.scale);
00659                     qp.translate(-m_doc->minCanvasCoordinate.x(),
00660                                  -m_doc->minCanvasCoordinate.y());
00661                     drawControls( &qp );
00662                     qp.restore();
00663                 }
00664             }
00665             break;
00666         case RENDER_SELECTION_SEPARATE:
00667             break;
00668         case RENDER_SELECTION_BUFFERED:
00669             break;
00670         case RENDER_LEGACY:
00671         default:
00672             assert (false);
00673     }
00674     // does mode specific rendering, currently selection in legacymode and nodes in nodeedit
00675     m_view->m_canvasMode->drawControls(&qp);
00676     m_viewMode.forceRedraw = false;
00677 }
00678 
00679 
00680 void Canvas::drawContents(QPainter *psx, int clipx, int clipy, int clipw, int cliph)
00681 {
00682     qDebug() << "drawContents" << clipx << clipy << clipw << cliph;
00683     uint docPagesCount=m_doc->Pages->count();
00684     ScPainter *painter=0;
00685     QImage img = QImage(clipw, cliph, QImage::Format_ARGB32);
00686     painter = new ScPainter(&img, img.width(), img.height(), 1.0, 0);
00687     painter->clear(palette().color(QPalette::Window));
00688     painter->newPath();
00689     painter->moveTo(0, 0);
00690     painter->lineTo(clipw, 0);
00691     painter->lineTo(clipw, cliph);
00692     painter->lineTo(0, cliph);
00693     painter->closePath();
00694     painter->setClipPath();
00695     painter->translate(-clipx, -clipy);
00696     painter->setZoomFactor(m_viewMode.scale);
00697     painter->translate(-m_doc->minCanvasCoordinate.x(), -m_doc->minCanvasCoordinate.y());
00698     painter->setLineWidth(1);
00699     painter->setFillMode(ScPainter::Solid);
00700     if (!m_doc->masterPageMode())
00701     {
00702         drawBackgroundPageOutlines(painter, clipx, clipy, clipw, cliph);
00703         
00704         if (m_viewMode.viewAsPreview)
00705         {
00706             FPointArray PoLine;
00707             getClipPathForPages(&PoLine);
00708             painter->beginLayer(1.0, 0, &PoLine);
00709         }
00710         else
00711             painter->beginLayer(1.0, 0);
00712         
00713         if ((m_doc->guidesSettings.before) && (!m_viewMode.viewAsPreview))
00714         {
00715             drawGuides(painter, clipx, clipy, clipw, cliph);
00716         }
00717         for (uint a = 0; a < docPagesCount; ++a)
00718         {
00719             DrawMasterItems(painter, m_doc->Pages->at(a), QRect(clipx, clipy, clipw, cliph));
00720         }
00721         DrawPageItems(painter, QRect(clipx, clipy, clipw, cliph));
00722         painter->endLayer();
00723         if ((!m_doc->guidesSettings.before) && (!m_viewMode.viewAsPreview))
00724         {
00725             drawGuides(painter, clipx, clipy, clipw, cliph);
00726         }
00727     }
00728     else // masterPageMode
00729     {           
00730         drawBackgroundMasterpage(painter, clipx, clipy, clipw, cliph);
00731         
00732         painter->beginLayer(1.0, 0);
00733         DrawPageItems(painter, QRect(clipx, clipy, clipw, cliph));
00734         painter->endLayer();
00735         
00736         double x = m_doc->scratch.Left * m_viewMode.scale;
00737         double y = m_doc->scratch.Top * m_viewMode.scale;
00738         double w = m_doc->currentPage()->width() * m_viewMode.scale;
00739         double h = m_doc->currentPage()->height() * m_viewMode.scale;
00740         QRectF drawRect = QRectF(x, y, w+5, h+5);
00741         drawRect.translate(-m_doc->minCanvasCoordinate.x() * m_viewMode.scale, -m_doc->minCanvasCoordinate.y() * m_viewMode.scale);
00742         if ((!m_doc->guidesSettings.before) && (drawRect.intersects(QRect(clipx, clipy, clipw, cliph))))
00743             DrawPageMarks(painter, m_doc->currentPage(), QRect(clipx, clipy, clipw, cliph));
00744     }
00745     if (((m_doc->m_Selection->count() != 0) || (m_viewMode.linkedFramesToShow.count() != 0))  && (!m_viewMode.viewAsPreview))
00746     {
00747         drawFrameLinks(painter);
00748     }
00749     painter->end();
00750     psx->drawImage(clipx, clipy, img);
00751     delete painter;
00752     painter=NULL;
00753 }
00754 
00755 void Canvas::drawControls(QPainter *psx)
00756 {
00757                 /*if (redrawMode == 1) // move ruler origin...
00758 {
00759                 pp.resetMatrix();
00760                 pp.setBrush(Qt::NoBrush);
00761                 pp.setPen(QPen(Qt::black, 1.0, Qt::DotLine, Qt::FlatCap, Qt::MiterJoin));
00762                 QPoint nXY = redrawPolygon.point(0);
00763                 pp.drawLine(0, nXY.y(), this->width(), nXY.y());
00764                 pp.drawLine(nXY.x(), 0, nXY.x(), this->height());
00765                 redrawPolygon.clear();
00766 }*/
00767     psx->save();
00768     if ((m_doc->appMode == modeDrawBezierLine) && (!m_viewMode.redrawPolygon.isEmpty()) && (m_doc->m_Selection->count() != 0))
00769     {
00770         drawControlsBezierCurve(psx, m_doc->m_Selection->itemAt(0));
00771     }
00772     if (m_viewMode.m_MouseButtonPressed && (m_doc->appMode == modeMeasurementTool))
00773     {
00774         drawControlsMeasurementLine(psx);
00775     }
00776     if (m_viewMode.m_MouseButtonPressed && (m_doc->appMode == modeDrawLine))
00777     {
00778         drawControlsDrawLine(psx);
00779     }
00780     if (m_doc->appMode == modeEditGradientVectors)
00781     {
00782         drawControlsGradientVectors(psx, m_doc->m_Selection->itemAt(0));
00783     }   
00784     if (m_viewMode.operItemMoving || m_viewMode.operItemResizing)
00785     {
00786         if (m_viewMode.operItemResizing)
00787         {
00788             if (!m_viewMode.redrawPolygon.isEmpty())
00789             {
00790                 if (m_viewMode.m_MouseButtonPressed && (m_doc->appMode == modeDrawFreehandLine))
00791                 {
00792                     drawControlsFreehandLine(psx);
00793                 }
00794                 else if (m_doc->appMode != modeDrawFreehandLine)
00795                 {
00796                     qDebug() << "XXX drawControls - operItemResizing";
00797                     assert(false);
00798 //                  drawControlsHighlightRect(psx);
00799                 }
00800             }
00801         }
00802         else
00803         {
00804             drawControlsMovingItemsRect(psx);
00805         }
00806     }
00807     else
00808     {
00809         if ((m_doc->m_Selection->count() != 0) && (m_doc->appMode != modeDrawBezierLine))
00810         {
00811 //          drawControlsSelection(psx, m_doc->m_Selection->itemAt(0));
00812             /*
00813              PageItem *currItem = m_doc->m_Selection->itemAt(0);
00814              if ((m_doc->appMode == modeEditClip) && (currItem->isSelected()))
00815              {
00816                  drawControlsNodeEditPoints(psx, currItem);
00817              }
00818              else
00819              {
00820                  drawControlsSelectionSpecial(psx, currItem);
00821              }*/
00822         }
00823     }
00824     psx->restore();
00825 }   
00826 
00827 
00828 
00832 void Canvas::drawControlsMovingItemsRect(QPainter* pp)
00833 {
00834     if (m_doc->m_Selection->count() != 0)
00835     {
00836         uint selectedItemCount = m_doc->m_Selection->count();
00837         PageItem *currItem = m_doc->m_Selection->itemAt(0);
00838         if (selectedItemCount < moveWithBoxesOnlyThreshold)
00839         {
00840             for (uint cu = 0; cu < selectedItemCount; cu++)
00841             {
00842                 currItem = m_doc->m_Selection->itemAt(cu);
00843 //              pp->resetMatrix();
00844 //              QPoint out = contentsToViewport(QPoint(0, 0));
00845 //              pp->translate(out.x(), out.y());
00846 //              pp->translate(-qRound(m_doc->minCanvasCoordinate.x()*m_viewMode.scale), -qRound(m_doc->minCanvasCoordinate.y()*m_viewMode.scale));
00847                 pp->save();
00848 //              Transform(currItem, pp);
00849                 pp->translate(currItem->xPos(), currItem->yPos());
00850                 pp->rotate(currItem->rotation());                           
00851                 pp->setBrush(Qt::NoBrush);
00852                 pp->setPen(QPen(Qt::black, 1.0 / m_viewMode.scale, Qt::DotLine, Qt::FlatCap, Qt::MiterJoin));
00853                 if (selectedItemCount < moveWithFullOutlinesThreshold)
00854                 {
00855                     if (!(currItem->asLine()))
00856                         currItem->DrawPolyL(pp, currItem->Clip);
00857                     else
00858                     {
00859                         if (currItem->asLine())
00860                         {
00861                             int lw2 = 1;
00862                             int lw = 1;
00863                             Qt::PenCapStyle le = Qt::FlatCap;
00864                             if (currItem->NamedLStyle.isEmpty())
00865                             {
00866                                 lw2 = qRound(currItem->lineWidth()  / 2.0);
00867                                 lw = qRound(qMax(currItem->lineWidth(), 1.0));
00868                                 le = currItem->PLineEnd;
00869                             }
00870                             else
00871                             {
00872                                 multiLine ml = m_doc->MLineStyles[currItem->NamedLStyle];
00873                                 lw2 = qRound(ml[ml.size()-1].Width  / 2.0);
00874                                 lw = qRound(qMax(ml[ml.size()-1].Width, 1.0));
00875                                 le = static_cast<Qt::PenCapStyle>(ml[ml.size()-1].LineEnd);
00876                             }
00877                             if (le != Qt::FlatCap)
00878                                 pp->drawRect(-lw2, -lw2, qRound(currItem->width())+lw, lw);
00879                             else
00880                                 pp->drawRect(-1, -lw2, qRound(currItem->width()), lw);
00881                         }
00882                     }
00883                 }
00884                 else
00885                     pp->drawRect(0, 0, static_cast<int>(currItem->width())+1, static_cast<int>(currItem->height())+1);
00886                 pp->restore();
00887             }
00888         }
00889         else
00890         {
00891             double gx, gy, gw, gh;
00892             m_doc->m_Selection->setGroupRect();
00893             m_doc->m_Selection->getGroupRect(&gx, &gy, &gw, &gh);
00894             QPoint out = contentsToViewport(QPoint(0, 0));
00895 //          pp->resetMatrix();
00896 //          pp->translate(out.x(), out.y());
00897 //          pp->translate(-qRound(m_doc->minCanvasCoordinate.x()*m_viewMode.scale), -qRound(m_doc->minCanvasCoordinate.y()*m_viewMode.scale));
00898 //          pp->scale(m_viewMode.scale, m_viewMode.scale);
00899             pp->translate(gx, gy);
00900             pp->drawRect(QRectF(0.0, 0.0, gw, gh));
00901         }
00902     }
00903 }
00904 
00905 
00926 void Canvas::drawControlsGradientVectors(QPainter* psx, PageItem *currItem)
00927 {
00928 //  psx->resetMatrix();
00929 //  QPoint out = contentsToViewport(QPoint(0, 0));
00930 //  psx->translate(out.x(), out.y());
00931 //  psx->translate(-qRound(m_doc->minCanvasCoordinate.x()*m_viewMode.scale), -qRound(m_doc->minCanvasCoordinate.y()*m_viewMode.scale));
00932     Transform(currItem, psx);
00933     psx->setPen(QPen(Qt::blue, 1, Qt::SolidLine, Qt::FlatCap, Qt::MiterJoin));
00934     psx->setBrush(Qt::NoBrush);
00935     psx->drawLine(QPointF(currItem->GrStartX, currItem->GrStartY), QPointF(currItem->GrEndX, currItem->GrEndY));
00936     psx->setPen(QPen(Qt::magenta, 8, Qt::SolidLine, Qt::RoundCap, Qt::MiterJoin));
00937     psx->drawPoint(QPointF(currItem->GrStartX, currItem->GrStartY));
00938     psx->drawPoint(QPointF(currItem->GrEndX, currItem->GrEndY));
00939 }
00940 
00941