📄 q3canvas.cpp
字号:
\internalThis method removes the view \a view from the list of Q3CanvasView objectsviewing this Q3Canvas. The Q3CanvasView class calls this.*/void Q3Canvas::removeView(Q3CanvasView* view){ d->viewList.removeRef(view);}/*! Sets the canvas to call advance() every \a ms milliseconds. Any previous setting by setAdvancePeriod() or setUpdatePeriod() is overridden. If \a ms is less than 0 advancing will be stopped.*/void Q3Canvas::setAdvancePeriod(int ms){ if (ms<0) { if (update_timer) update_timer->stop(); } else { if (update_timer) delete update_timer; update_timer = new QTimer(this); connect(update_timer,SIGNAL(timeout()),this,SLOT(advance())); update_timer->start(ms); }}/*! Sets the canvas to call update() every \a ms milliseconds. Any previous setting by setAdvancePeriod() or setUpdatePeriod() is overridden. If \a ms is less than 0 automatic updating will be stopped.*/void Q3Canvas::setUpdatePeriod(int ms){ if (ms<0) { if (update_timer) update_timer->stop(); } else { if (update_timer) delete update_timer; update_timer = new QTimer(this); connect(update_timer,SIGNAL(timeout()),this,SLOT(update())); update_timer->start(ms); }}/*! Moves all Q3CanvasItem::animated() canvas items on the canvas and refreshes all changes to all views of the canvas. (An `animated' item is an item that is in motion; see setVelocity().) The advance takes place in two phases. In phase 0, the Q3CanvasItem::advance() function of each Q3CanvasItem::animated() canvas item is called with paramater 0. Then all these canvas items are called again, with parameter 1. In phase 0, the canvas items should not change position, merely examine other items on the canvas for which special processing is required, such as collisions between items. In phase 1, all canvas items should change positions, ignoring any other items on the canvas. This two-phase approach allows for considerations of "fairness", although no Q3CanvasItem subclasses supplied with Qt do anything interesting in phase 0. The canvas can be configured to call this function periodically with setAdvancePeriod(). \sa update()*/void Q3Canvas::advance(){ Q3PtrDictIterator<void> it=d->animDict; while (it.current()) { Q3CanvasItem* i = (Q3CanvasItem*)(void*)it.currentKey(); ++it; if (i) i->advance(0); } // we expect the dict contains the exact same items as in the // first pass. it.toFirst(); while (it.current()) { Q3CanvasItem* i = (Q3CanvasItem*)(void*)it.currentKey(); ++it; if (i) i->advance(1); } update();}// Don't call this unless you know what you're doing.// p is in the content's co-ordinate example./*! \internal*/void Q3Canvas::drawViewArea(Q3CanvasView* view, QPainter* p, const QRect& vr, bool){ QPoint tl = view->contentsToViewport(QPoint(0,0));#ifndef QT_NO_TRANSFORMATIONS QMatrix wm = view->worldMatrix(); QMatrix iwm = wm.invert(); // ivr = covers all chunks in vr QRect ivr = iwm.map(vr); QMatrix twm; twm.translate(tl.x(),tl.y());#else QRect ivr = vr;#endif QRect all(0,0,width(),height()); if (!all.contains(ivr)) { // Need to clip with edge of canvas.#ifndef QT_NO_TRANSFORMATIONS // For translation-only transformation, it is safe to include the right // and bottom edges, but otherwise, these must be excluded since they // are not precisely defined (different bresenham paths). Q3PointArray a; if (wm.m12()==0.0 && wm.m21()==0.0 && wm.m11() == 1.0 && wm.m22() == 1.0) a = Q3PointArray(QRect(all.x(),all.y(),all.width()+1,all.height()+1)); else a = Q3PointArray(all); a = (wm*twm).map(a);#else Q3PointArray a(QRect(all.x(),all.y(),all.width()+1,all.height()+1));#endif if (view->viewport()->backgroundMode() == NoBackground) { QRect cvr = vr; cvr.moveBy(tl.x(),tl.y()); qt_setclipregion(p, QRegion(cvr)-QRegion(a)); p->fillRect(vr,view->viewport()->palette() .brush(QPalette::Active,QPalette::Window)); } qt_setclipregion(p, a); } QRect r = vr; r.moveBy(tl.x(),tl.y()); // move to untransformed co-ords if (!all.contains(ivr)) { QRegion inside = p->clipRegion() & r; //QRegion outside = p->clipRegion() - r; //p->setClipRegion(outside); //p->fillRect(outside.boundingRect(),red); qt_setclipregion(p, inside); } else { qt_setcliprect(p, r); }#ifndef QT_NO_TRANSFORMATIONS p->setWorldMatrix(wm*twm);#else#endif drawCanvasArea(ivr,p,false);}/*! Repaints changed areas in all views of the canvas. \sa advance()*/void Q3Canvas::update(){ // ##### fix QT_NO_TRANSFORMATIONS#ifndef QT_NO_TRANSFORMATIONS Q3PtrList<QRect> doneareas; doneareas.setAutoDelete(true);#endif Q3PtrListIterator<Q3CanvasView> it(d->viewList); Q3CanvasView* view; while((view=it.current()) != 0) { ++it;#ifndef QT_NO_TRANSFORMATIONS QMatrix wm = view->worldMatrix();#endif QRect area(view->contentsX(),view->contentsY(), view->visibleWidth(),view->visibleHeight()); if (area.width()>0 && area.height()>0) {#ifndef QT_NO_TRANSFORMATIONS // r = Visible area of the canvas where there are changes QRect r = changeBounds(view->inverseWorldMatrix().map(area)); if (!r.isEmpty()) { QRect tr = wm.map(r); tr.moveBy(-view->contentsX(), -view->contentsY()); view->viewport()->update(tr); doneareas.append(new QRect(r)); }#endif } }#ifndef QT_NO_TRANSFORMATIONS for (QRect* r=doneareas.first(); r != 0; r=doneareas.next()) setUnchanged(*r);#endif}/*! Marks the whole canvas as changed. All views of the canvas will be entirely redrawn when update() is called next.*/void Q3Canvas::setAllChanged(){ setChanged(QRect(0,0,width(),height()));}/*! Marks \a area as changed. This \a area will be redrawn in all views that are showing it when update() is called next.*/void Q3Canvas::setChanged(const QRect& area){ QRect thearea = area.intersected(QRect(0, 0, width(), height())); int mx = (thearea.x()+thearea.width()+chunksize)/chunksize; int my = (thearea.y()+thearea.height()+chunksize)/chunksize; if (mx>chwidth) mx=chwidth; if (my>chheight) my=chheight; int x=thearea.x()/chunksize; while(x<mx) { int y = thearea.y()/chunksize; while(y<my) { chunk(x,y).change(); y++; } x++; }}/*! Marks \a area as \e unchanged. The area will \e not be redrawn in the views for the next update(), unless it is marked or changed again before the next call to update().*/void Q3Canvas::setUnchanged(const QRect& area){ QRect thearea = area.intersected(QRect(0, 0, width(), height())); int mx = (thearea.x()+thearea.width()+chunksize)/chunksize; int my = (thearea.y()+thearea.height()+chunksize)/chunksize; if (mx>chwidth) mx=chwidth; if (my>chheight) my=chheight; int x=thearea.x()/chunksize; while(x<mx) { int y = thearea.y()/chunksize; while(y<my) { chunk(x,y).takeChange(); y++; } x++; }}/*! \internal*/QRect Q3Canvas::changeBounds(const QRect& inarea){ QRect area = inarea.intersected(QRect(0, 0, width(), height())); int mx = (area.x()+area.width()+chunksize)/chunksize; int my = (area.y()+area.height()+chunksize)/chunksize; if (mx > chwidth) mx=chwidth; if (my > chheight) my=chheight; QRect result; int x=area.x()/chunksize; while(x<mx) { int y=area.y()/chunksize; while(y<my) { Q3CanvasChunk& ch=chunk(x,y); if (ch.hasChanged()) result |= QRect(x,y,1,1); y++; } x++; } if (!result.isEmpty()) { result.rLeft() *= chunksize; result.rTop() *= chunksize; result.rRight() *= chunksize; result.rBottom() *= chunksize; result.rRight() += chunksize; result.rBottom() += chunksize; } return result;}void Q3Canvas::ensureOffScrSize(int osw, int osh){ if (osw > offscr.width() || osh > offscr.height()) offscr.resize(QMAX(osw,offscr.width()), QMAX(osh,offscr.height())); else if (offscr.width() == 0 || offscr.height() == 0) offscr.resize(QMAX(offscr.width(), 1), QMAX(offscr.height(), 1));}/*! Paints all canvas items that are in the area \a clip to \a painter, using double-buffering if \a dbuf is true. e.g. to print the canvas to a printer: \code QPrinter pr; if (pr.setup()) { QPainter p(&pr); canvas.drawArea(canvas.rect(), &p); } \endcode*/void Q3Canvas::drawArea(const QRect& clip, QPainter* painter, bool dbuf){ if (painter) drawCanvasArea(clip, painter, dbuf);}#include <qdebug.h>/*! \internal*/void Q3Canvas::drawCanvasArea(const QRect& inarea, QPainter* p, bool /*double_buffer*/){ QRect area=inarea.intersected(QRect(0,0,width(),height())); if (!p) return; // Nothing to do. int lx=area.x()/chunksize; int ly=area.y()/chunksize; int mx=area.right()/chunksize; int my=area.bottom()/chunksize; if (mx>=chwidth) mx=chwidth-1; if (my>=chheight) my=chheight-1; Q3CanvasItemList allvisible; // Stores the region within area that need to be drawn. It is relative // to area.topLeft() (so as to keep within bounds of 16-bit XRegions) QRegion rgn; for (int x=lx; x<=mx; x++) { for (int y=ly; y<=my; y++) { // Only reset change if all views updating, and // wholy within area. (conservative: ignore entire boundary) // // Disable this to help debugging. // if (!p) { if (chunk(x,y).takeChange()) { // ### should at least make bands rgn |= QRegion(x*chunksize-area.x(),y*chunksize-area.y(), chunksize,chunksize); allvisible += *chunk(x,y).listPtr(); } } else { allvisible += *chunk(x,y).listPtr(); } } } allvisible.sort(); drawBackground(*p,area); allvisible.drawUnique(*p); drawForeground(*p,area);}/*!\internalThis method to informs the Q3Canvas that a given chunk is`dirty' and needs to be redrawn in the next Update.(\a x,\a y) is a chunk location.The sprite classes call this. Any new derived class of Q3CanvasItemmust do so too. SetChangedChunkContaining can be used instead.*/void Q3Canvas::setChangedChunk(int x, int y){ if (validChunk(x,y)) { Q3CanvasChunk& ch=chunk(x,y); ch.change(); }}/*!\internalThis method to informs the Q3Canvas that the chunk containing a givenpixel is `dirty' and needs to be redrawn in the next Update.(\a x,\a y) is a pixel location.The item classes call this. Any new derived class of Q3CanvasItem mustdo so too. SetChangedChunk can be used instead.*/void Q3Canvas::setChangedChunkContaining(int x, int y){ if (x>=0 && x<width() && y>=0 && y<height()) { Q3CanvasChunk& chunk=chunkContaining(x,y); chunk.change(); }}/*!\internalThis method adds the Q3CanvasItem \a g to the list of those which need to bedrawn if the given chunk at location (\a x, \a y) is redrawn. LikeSetChangedChunk and SetChangedChunkContaining, this method marks thechunk as `dirty'.*/void Q3Canvas::addItemToChunk(Q3CanvasItem* g, int x, int y){ if (validChunk(x,y)) { chunk(x,y).add(g); }}/*!\internalThis method removes the Q3CanvasItem \a g from the list of those which need tobe drawn if the given chunk at location (\a x, \a y) is redrawn. LikeSetChangedChunk and SetChangedChunkContaining, this method marks the chunkas `dirty'.*/void Q3Canvas::removeItemFromChunk(Q3CanvasItem* g, int x, int y){ if (validChunk(x,y)) { chunk(x,y).remove(g); }}/*!\internalThis method adds the Q3CanvasItem \a g to the list of those which need to bedrawn if the chunk containing the given pixel (\a x, \a y) is redrawn. LikeSetChangedChunk and SetChangedChunkContaining, this method marks thechunk as `dirty'.*/void Q3Canvas::addItemToChunkContaining(Q3CanvasItem* g, int x, int y){ if (x>=0 && x<width() && y>=0 && y<height()) { chunkContaining(x,y).add(g); }}/*!\internalThis method removes the Q3CanvasItem \a g from the list of those which need tobe drawn if the chunk containing the given pixel (\a x, \a y) is redrawn.Like SetChangedChunk and SetChangedChunkContaining, this methodmarks the chunk as `dirty'.*/void Q3Canvas::removeItemFromChunkContaining(Q3CanvasItem* g, int x, int y){ if (x>=0 && x<width() && y>=0 && y<height()) { chunkContaining(x,y).remove(g); }}/*! Returns the color set by setBackgroundColor(). By default, this is white.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -