From 68b81013e8668f50fc18b7e26a520ec93a7a1251 Mon Sep 17 00:00:00 2001 From: Michele Calgaro Date: Fri, 31 May 2024 11:32:43 +0900 Subject: Rename nt* canvas related files to equivalent tq* Signed-off-by: Michele Calgaro --- src/canvas/ntqcanvas.h | 816 ------- src/canvas/qcanvas.cpp | 5415 -------------------------------------------- src/canvas/qt_canvas.pri | 4 +- src/canvas/tqcanvas.cpp | 5415 ++++++++++++++++++++++++++++++++++++++++++++ src/canvas/tqcanvas.h | 816 +++++++ src/kernel/ntqt.h | 2 +- src/kernel/qpointarray.cpp | 4 +- src/tools/ntqwinexport.h | 2 +- src/tools/qfeatures.txt | 2 +- src/tools/qwinexport.cpp | 2 +- 10 files changed, 6239 insertions(+), 6239 deletions(-) delete mode 100644 src/canvas/ntqcanvas.h delete mode 100644 src/canvas/qcanvas.cpp create mode 100644 src/canvas/tqcanvas.cpp create mode 100644 src/canvas/tqcanvas.h (limited to 'src') diff --git a/src/canvas/ntqcanvas.h b/src/canvas/ntqcanvas.h deleted file mode 100644 index 9bf3d729c..000000000 --- a/src/canvas/ntqcanvas.h +++ /dev/null @@ -1,816 +0,0 @@ -/********************************************************************** -** -** Definition of TQCanvas classes -** -** Created : 991211 -** -** Copyright (C) 1999-2008 Trolltech ASA. All rights reserved. -** -** This file is part of the canvas module of the TQt GUI Toolkit. -** -** This file may be used under the terms of the GNU General -** Public License versions 2.0 or 3.0 as published by the Free -** Software Foundation and appearing in the files LICENSE.GPL2 -** and LICENSE.GPL3 included in the packaging of this file. -** Alternatively you may (at your option) use any later version -** of the GNU General Public License if such license has been -** publicly approved by Trolltech ASA (or its successors, if any) -** and the KDE Free TQt Foundation. -** -** Please review the following information to ensure GNU General -** Public Licensing requirements will be met: -** http://trolltech.com/products/qt/licenses/licensing/opensource/. -** If you are unsure which license is appropriate for your use, please -** review the following information: -** http://trolltech.com/products/qt/licenses/licensing/licensingoverview -** or contact the sales department at sales@trolltech.com. -** -** This file may be used under the terms of the Q Public License as -** defined by Trolltech ASA and appearing in the file LICENSE.TQPL -** included in the packaging of this file. Licensees holding valid TQt -** Commercial licenses may use this file in accordance with the TQt -** Commercial License Agreement provided with the Software. -** -** This file is provided "AS IS" with NO WARRANTY OF ANY KIND, -** INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE. Trolltech reserves all rights not granted -** herein. -** -**********************************************************************/ - -#ifndef TQCANVAS_H -#define TQCANVAS_H - -#ifndef QT_H -#include "ntqscrollview.h" -#include "ntqpixmap.h" -#include "ntqptrlist.h" -#include "ntqbrush.h" -#include "ntqpen.h" -#include "ntqvaluelist.h" -#include "ntqpointarray.h" -#endif // QT_H - -#if !defined( TQT_MODULE_CANVAS ) || defined( QT_LICENSE_PROFESSIONAL ) || defined( QT_INTERNAL_CANVAS ) -#define TQM_EXPORT_CANVAS -#define TQM_TEMPLATE_EXTERN_CANVAS -#else -#define TQM_EXPORT_CANVAS TQ_EXPORT -#define TQM_TEMPLATE_EXTERN_CANVAS Q_TEMPLATE_EXTERN -#endif - -#ifndef TQT_NO_CANVAS - - -class TQCanvasSprite; -class TQCanvasPolygonalItem; -class TQCanvasRectangle; -class TQCanvasPolygon; -class TQCanvasEllipse; -class TQCanvasText; -class TQCanvasLine; -class TQCanvasChunk; -class TQCanvas; -class TQCanvasItem; -class TQCanvasView; -class TQCanvasPixmap; - -#if defined(Q_TEMPLATEDLL) && ( !defined(Q_CC_BOR) || !defined(QT_MAKEDLL) || defined(Q_EXPORT_TEMPLATES) ) -// MOC_SKIP_BEGIN -TQM_TEMPLATE_EXTERN_CANVAS template class TQM_EXPORT_CANVAS TQValueListIterator< TQCanvasItem* >; -TQM_TEMPLATE_EXTERN_CANVAS template class TQM_EXPORT_CANVAS TQValueList< TQCanvasItem* >; -// MOC_SKIP_END -#endif - -class TQM_EXPORT_CANVAS TQCanvasItemList : public TQValueList { -public: - void sort(); - void drawUnique( TQPainter& painter ); - TQCanvasItemList operator+(const TQCanvasItemList &l) const; -}; - - -class TQCanvasItemExtra; - -class TQM_EXPORT_CANVAS TQCanvasItem : public TQt -{ -public: - TQCanvasItem(TQCanvas* canvas); - virtual ~TQCanvasItem(); - - double x() const - { return myx; } - double y() const - { return myy; } - double z() const - { return myz; } // (depth) - - virtual void moveBy(double dx, double dy); - void move(double x, double y); - void setX(double a) { move(a,y()); } - void setY(double a) { move(x(),a); } - void setZ(double a) { myz=a; changeChunks(); } - - bool animated() const; - virtual void setAnimated(bool y); - virtual void setVelocity( double vx, double vy); - void setXVelocity( double vx ) { setVelocity(vx,yVelocity()); } - void setYVelocity( double vy ) { setVelocity(xVelocity(),vy); } - double xVelocity() const; - double yVelocity() const; - virtual void advance(int stage); - - virtual bool collidesWith( const TQCanvasItem* ) const=0; - - TQCanvasItemList collisions(bool exact /* NO DEFAULT */ ) const; - - virtual void setCanvas(TQCanvas*); - - virtual void draw(TQPainter&)=0; - - void show(); - void hide(); - - virtual void setVisible(bool yes); - bool isVisible() const - { return (bool)vis; } - virtual void setSelected(bool yes); - bool isSelected() const - { return (bool)sel; } - virtual void setEnabled(bool yes); - bool isEnabled() const - { return (bool)ena; } - virtual void setActive(bool yes); - bool isActive() const - { return (bool)act; } -#ifndef TQT_NO_COMPAT - bool visible() const - { return (bool)vis; } - bool selected() const - { return (bool)sel; } - bool enabled() const - { return (bool)ena; } - bool active() const - { return (bool)act; } -#endif - - enum RttiValues { - Rtti_Item = 0, - Rtti_Sprite = 1, - Rtti_PolygonalItem = 2, - Rtti_Text = 3, - Rtti_Polygon = 4, - Rtti_Rectangle = 5, - Rtti_Ellipse = 6, - Rtti_Line = 7, - Rtti_Spline = 8 - }; - - virtual int rtti() const; - static int RTTI; - - virtual TQRect boundingRect() const=0; - virtual TQRect boundingRectAdvanced() const; - - TQCanvas* canvas() const - { return cnv; } - -protected: - void update() { changeChunks(); } - -private: - // For friendly subclasses... - - friend class TQCanvasPolygonalItem; - friend class TQCanvasSprite; - friend class TQCanvasRectangle; - friend class TQCanvasPolygon; - friend class TQCanvasEllipse; - friend class TQCanvasText; - friend class TQCanvasLine; - - virtual TQPointArray chunks() const; - virtual void addToChunks(); - virtual void removeFromChunks(); - virtual void changeChunks(); - virtual bool collidesWith( const TQCanvasSprite*, - const TQCanvasPolygonalItem*, - const TQCanvasRectangle*, - const TQCanvasEllipse*, - const TQCanvasText* ) const = 0; - // End of friend stuff - - TQCanvas* cnv; - static TQCanvas* current_canvas; - double myx,myy,myz; - TQCanvasItemExtra *ext; - TQCanvasItemExtra& extra(); - uint ani:1; - uint vis:1; - uint val:1; - uint sel:1; - uint ena:1; - uint act:1; -}; - - -class TQCanvasData; - -class TQM_EXPORT_CANVAS TQCanvas : public TQObject -{ - TQ_OBJECT -public: - TQCanvas( TQObject* parent = 0, const char* name = 0 ); - TQCanvas(int w, int h); - TQCanvas( TQPixmap p, int h, int v, int tilewidth, int tileheight ); - - virtual ~TQCanvas(); - - virtual void setTiles( TQPixmap tiles, int h, int v, - int tilewidth, int tileheight ); - virtual void setBackgroundPixmap( const TQPixmap& p ); - TQPixmap backgroundPixmap() const; - - virtual void setBackgroundColor( const TQColor& c ); - TQColor backgroundColor() const; - - virtual void setTile( int x, int y, int tilenum ); - int tile( int x, int y ) const - { return grid[x+y*htiles]; } - - int tilesHorizontally() const - { return htiles; } - int tilesVertically() const - { return vtiles; } - - int tileWidth() const - { return tilew; } - int tileHeight() const - { return tileh; } - - virtual void resize(int width, int height); - int width() const - { return awidth; } - int height() const - { return aheight; } - TQSize size() const - { return TQSize(awidth,aheight); } - TQRect rect() const - { return TQRect( 0, 0, awidth, aheight ); } - bool onCanvas( int x, int y ) const - { return x>=0 && y>=0 && x=0 && y>=0 && x, TQPtrList hotspots); - - TQCanvasPixmapArray(TQValueList, TQPointArray hotspots = TQPointArray() ); - ~TQCanvasPixmapArray(); - -#ifndef TQT_NO_IMAGEIO - bool readPixmaps(const TQString& datafilenamepattern, int framecount=0); - bool readCollisionMasks(const TQString& filenamepattern); -#endif - - // deprecated - bool operator!(); // Failure check. - bool isValid() const; - - TQCanvasPixmap* image(int i) const - { return img ? img[i] : 0; } - void setImage(int i, TQCanvasPixmap* p); - uint count() const - { return (uint)framecount; } - -private: -#if defined(TQ_DISABLE_COPY) - TQCanvasPixmapArray( const TQCanvasPixmapArray & ); - TQCanvasPixmapArray &operator=( const TQCanvasPixmapArray & ); -#endif -#ifndef TQT_NO_IMAGEIO - bool readPixmaps(const TQString& datafilenamepattern, int framecount, bool maskonly); -#endif - - void reset(); - int framecount; - TQCanvasPixmap** img; -}; - - -class TQM_EXPORT_CANVAS TQCanvasSprite : public TQCanvasItem -{ -public: - TQCanvasSprite(TQCanvasPixmapArray* array, TQCanvas* canvas); - - void setSequence(TQCanvasPixmapArray* seq); - - virtual ~TQCanvasSprite(); - - void move(double x, double y); - virtual void move(double x, double y, int frame); - void setFrame(int); - enum FrameAnimationType { Cycle, Oscillate }; - virtual void setFrameAnimation(FrameAnimationType=Cycle, int step=1, int state=0); - int frame() const - { return frm; } - int frameCount() const - { return images->count(); } - - int rtti() const; - static int RTTI; - - bool collidesWith( const TQCanvasItem* ) const; - - TQRect boundingRect() const; - - // is there a reason for these to be protected? Lars -//protected: - - int width() const; - int height() const; - - int leftEdge() const; - int topEdge() const; - int rightEdge() const; - int bottomEdge() const; - - int leftEdge(int nx) const; - int topEdge(int ny) const; - int rightEdge(int nx) const; - int bottomEdge(int ny) const; - TQCanvasPixmap* image() const - { return images->image(frm); } - virtual TQCanvasPixmap* imageAdvanced() const; - TQCanvasPixmap* image(int f) const - { return images->image(f); } - virtual void advance(int stage); - -public: - void draw(TQPainter& painter); - -private: -#if defined(TQ_DISABLE_COPY) - TQCanvasSprite( const TQCanvasSprite & ); - TQCanvasSprite &operator=( const TQCanvasSprite & ); -#endif - void addToChunks(); - void removeFromChunks(); - void changeChunks(); - - int frm; - ushort anim_val; - uint anim_state:2; - uint anim_type:14; - bool collidesWith( const TQCanvasSprite*, - const TQCanvasPolygonalItem*, - const TQCanvasRectangle*, - const TQCanvasEllipse*, - const TQCanvasText* ) const; - - friend bool qt_testCollision( const TQCanvasSprite* s1, - const TQCanvasSprite* s2 ); - - TQCanvasPixmapArray* images; -}; - -class TQPolygonalProcessor; - -class TQM_EXPORT_CANVAS TQCanvasPolygonalItem : public TQCanvasItem -{ -public: - TQCanvasPolygonalItem(TQCanvas* canvas); - virtual ~TQCanvasPolygonalItem(); - - bool collidesWith( const TQCanvasItem* ) const; - - virtual void setPen(TQPen p); - virtual void setBrush(TQBrush b); - - TQPen pen() const - { return pn; } - TQBrush brush() const - { return br; } - - virtual TQPointArray areaPoints() const=0; - virtual TQPointArray areaPointsAdvanced() const; - TQRect boundingRect() const; - - int rtti() const; - static int RTTI; - -protected: - void draw(TQPainter &); - virtual void drawShape(TQPainter &) = 0; - - bool winding() const; - void setWinding(bool); - - void invalidate(); - bool isValid() const - { return (bool)val; } - -private: - void scanPolygon( const TQPointArray& pa, int winding, - TQPolygonalProcessor& process ) const; - TQPointArray chunks() const; - - bool collidesWith( const TQCanvasSprite*, - const TQCanvasPolygonalItem*, - const TQCanvasRectangle*, - const TQCanvasEllipse*, - const TQCanvasText* ) const; - - TQBrush br; - TQPen pn; - uint wind:1; -}; - - -class TQM_EXPORT_CANVAS TQCanvasRectangle : public TQCanvasPolygonalItem -{ -public: - TQCanvasRectangle(TQCanvas* canvas); - TQCanvasRectangle(const TQRect&, TQCanvas* canvas); - TQCanvasRectangle(int x, int y, int width, int height, TQCanvas* canvas); - - ~TQCanvasRectangle(); - - int width() const; - int height() const; - void setSize(int w, int h); - TQSize size() const - { return TQSize(w,h); } - TQPointArray areaPoints() const; - TQRect rect() const - { return TQRect(int(x()),int(y()),w,h); } - - bool collidesWith( const TQCanvasItem* ) const; - - int rtti() const; - static int RTTI; - -protected: - void drawShape(TQPainter &); - TQPointArray chunks() const; - -private: - bool collidesWith( const TQCanvasSprite*, - const TQCanvasPolygonalItem*, - const TQCanvasRectangle*, - const TQCanvasEllipse*, - const TQCanvasText* ) const; - - int w, h; -}; - - -class TQM_EXPORT_CANVAS TQCanvasPolygon : public TQCanvasPolygonalItem -{ -public: - TQCanvasPolygon(TQCanvas* canvas); - ~TQCanvasPolygon(); - void setPoints(TQPointArray); - TQPointArray points() const; - void moveBy(double dx, double dy); - - TQPointArray areaPoints() const; - - int rtti() const; - static int RTTI; - -protected: - void drawShape(TQPainter &); - TQPointArray poly; -}; - - -class TQM_EXPORT_CANVAS TQCanvasSpline : public TQCanvasPolygon -{ -public: - TQCanvasSpline(TQCanvas* canvas); - ~TQCanvasSpline(); - - void setControlPoints(TQPointArray, bool closed=TRUE); - TQPointArray controlPoints() const; - bool closed() const; - - int rtti() const; - static int RTTI; - -private: - void recalcPoly(); - TQPointArray bez; - bool cl; -}; - - -class TQM_EXPORT_CANVAS TQCanvasLine : public TQCanvasPolygonalItem -{ -public: - TQCanvasLine(TQCanvas* canvas); - ~TQCanvasLine(); - void setPoints(int x1, int y1, int x2, int y2); - - TQPoint startPoint() const - { return TQPoint(x1,y1); } - TQPoint endPoint() const - { return TQPoint(x2,y2); } - - int rtti() const; - static int RTTI; - - void setPen(TQPen p); - void moveBy(double dx, double dy); - -protected: - void drawShape(TQPainter &); - TQPointArray areaPoints() const; - -private: - int x1,y1,x2,y2; -}; - - -class TQM_EXPORT_CANVAS TQCanvasEllipse : public TQCanvasPolygonalItem -{ - -public: - TQCanvasEllipse( TQCanvas* canvas ); - TQCanvasEllipse( int width, int height, TQCanvas* canvas ); - TQCanvasEllipse( int width, int height, int startangle, int angle, - TQCanvas* canvas ); - - ~TQCanvasEllipse(); - - int width() const; - int height() const; - void setSize(int w, int h); - void setAngles(int start, int length); - int angleStart() const - { return a1; } - int angleLength() const - { return a2; } - TQPointArray areaPoints() const; - - bool collidesWith( const TQCanvasItem* ) const; - - int rtti() const; - static int RTTI; - -protected: - void drawShape(TQPainter &); - -private: - bool collidesWith( const TQCanvasSprite*, - const TQCanvasPolygonalItem*, - const TQCanvasRectangle*, - const TQCanvasEllipse*, - const TQCanvasText* ) const; - int w, h; - int a1, a2; -}; - - -class TQCanvasTextExtra; - -class TQM_EXPORT_CANVAS TQCanvasText : public TQCanvasItem -{ -public: - TQCanvasText(TQCanvas* canvas); - TQCanvasText(const TQString&, TQCanvas* canvas); - TQCanvasText(const TQString&, TQFont, TQCanvas* canvas); - - virtual ~TQCanvasText(); - - void setText( const TQString& ); - void setFont( const TQFont& ); - void setColor( const TQColor& ); - TQString text() const; - TQFont font() const; - TQColor color() const; - - void moveBy(double dx, double dy); - - int textFlags() const - { return flags; } - void setTextFlags(int); - - TQRect boundingRect() const; - - bool collidesWith( const TQCanvasItem* ) const; - - int rtti() const; - static int RTTI; - -protected: - virtual void draw(TQPainter&); - -private: -#if defined(TQ_DISABLE_COPY) - TQCanvasText( const TQCanvasText & ); - TQCanvasText &operator=( const TQCanvasText & ); -#endif - void addToChunks(); - void removeFromChunks(); - void changeChunks(); - - void setRect(); - TQRect brect; - TQString txt; - int flags; - TQFont fnt; - TQColor col; - TQCanvasTextExtra* extra; - - bool collidesWith( const TQCanvasSprite*, - const TQCanvasPolygonalItem*, - const TQCanvasRectangle*, - const TQCanvasEllipse*, - const TQCanvasText* ) const; -}; - -#define Q_DEFINED_QCANVAS -#include "ntqwinexport.h" -#endif // TQT_NO_CANVAS - -#endif // TQCANVAS_H diff --git a/src/canvas/qcanvas.cpp b/src/canvas/qcanvas.cpp deleted file mode 100644 index 11f8a53a0..000000000 --- a/src/canvas/qcanvas.cpp +++ /dev/null @@ -1,5415 +0,0 @@ -/********************************************************************** -** -** Implementation of TQCanvas and associated classes -** -** Created : 991211 -** -** Copyright (C) 1999-2008 Trolltech ASA. All rights reserved. -** -** This file is part of the canvas module of the TQt GUI Toolkit. -** -** This file may be used under the terms of the GNU General -** Public License versions 2.0 or 3.0 as published by the Free -** Software Foundation and appearing in the files LICENSE.GPL2 -** and LICENSE.GPL3 included in the packaging of this file. -** Alternatively you may (at your option) use any later version -** of the GNU General Public License if such license has been -** publicly approved by Trolltech ASA (or its successors, if any) -** and the KDE Free TQt Foundation. -** -** Please review the following information to ensure GNU General -** Public Licensing requirements will be met: -** http://trolltech.com/products/qt/licenses/licensing/opensource/. -** If you are unsure which license is appropriate for your use, please -** review the following information: -** http://trolltech.com/products/qt/licenses/licensing/licensingoverview -** or contact the sales department at sales@trolltech.com. -** -** This file may be used under the terms of the Q Public License as -** defined by Trolltech ASA and appearing in the file LICENSE.TQPL -** included in the packaging of this file. Licensees holding valid TQt -** Commercial licenses may use this file in accordance with the TQt -** Commercial License Agreement provided with the Software. -** -** This file is provided "AS IS" with NO WARRANTY OF ANY KIND, -** INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE. Trolltech reserves all rights not granted -** herein. -** -**********************************************************************/ - -#include "ntqcanvas.h" -#ifndef TQT_NO_CANVAS -#include "ntqapplication.h" -#include "ntqbitmap.h" -#include "ntqimage.h" -#include "ntqptrdict.h" -#include "ntqpainter.h" -#include "ntqpolygonscanner.h" -#include "ntqtimer.h" -#include "ntqtl.h" - -#include - -class TQCanvasData { -public: - TQCanvasData() : - itemDict(1013), animDict(503) - { - } - - TQPtrList viewList; - TQPtrDict itemDict; - TQPtrDict animDict; -}; - -class TQCanvasViewData { -public: - TQCanvasViewData() : repaint_from_moving( FALSE ) {} -#ifndef TQT_NO_TRANSFORMATIONS - TQWMatrix xform; - TQWMatrix ixform; -#endif - bool repaint_from_moving; -}; - -// clusterizer - -class TQCanvasClusterizer { -public: - TQCanvasClusterizer(int maxclusters); - ~TQCanvasClusterizer(); - - void add(int x, int y); // 1x1 rectangle (point) - void add(int x, int y, int w, int h); - void add(const TQRect& rect); - - void clear(); - int clusters() { return count; } - const TQRect& operator[](int i); - -private: - TQRect* cluster; - int count; - const int maxcl; -}; - -static -void include(TQRect& r, const TQRect& rect) -{ - if (rect.left()r.right()) { - r.setRight(rect.right()); - } - if (rect.top()r.bottom()) { - r.setBottom(rect.bottom()); - } -} - -/* -A TQCanvasClusterizer groups rectangles (TQRects) into non-overlapping rectangles -by a merging heuristic. -*/ -TQCanvasClusterizer::TQCanvasClusterizer(int maxclusters) : - cluster(new TQRect[maxclusters]), - count(0), - maxcl(maxclusters) -{ } - -TQCanvasClusterizer::~TQCanvasClusterizer() -{ - delete [] cluster; -} - -void TQCanvasClusterizer::clear() -{ - count=0; -} - -void TQCanvasClusterizer::add(int x, int y) -{ - add(TQRect(x,y,1,1)); -} - -void TQCanvasClusterizer::add(int x, int y, int w, int h) -{ - add(TQRect(x,y,w,h)); -} - -void TQCanvasClusterizer::add(const TQRect& rect) -{ - TQRect biggerrect(rect.x()-1,rect.y()-1,rect.width()+2,rect.height()+2); - - //assert(rect.width()>0 && rect.height()>0); - - int cursor; - - for (cursor=0; cursor=0) { - include(cluster[cheapest],rect); - return; - } - - if (count < maxcl) { - cluster[count++]=rect; - return; - } - - // Do cheapest of: - // add to closest cluster - // do cheapest cluster merge, add to new cluster - - lowestcost=9999999; - cheapest=-1; - cursor=0; - while( cursor=0) { - include(cluster[cheapestmerge1],cluster[cheapestmerge2]); - cluster[cheapestmerge2]=cluster[count--]; - } else { - // if (!cheapest) debugRectangles(rect); - include(cluster[cheapest],rect); - } - - // NB: clusters do not intersect (or intersection will - // overwrite). This is a result of the above algorithm, - // given the assumption that (x,y) are ordered topleft - // to bottomright. - - // ### - // - // add explicit x/y ordering to that comment, move it to the top - // and rephrase it as pre-/post-conditions. -} - -const TQRect& TQCanvasClusterizer::operator[](int i) -{ - return cluster[i]; -} - -// end of clusterizer - - - -class TQM_EXPORT_CANVAS TQCanvasItemPtr { -public: - TQCanvasItemPtr() : ptr(0) { } - TQCanvasItemPtr( TQCanvasItem* p ) : ptr(p) { } - - bool operator<=(const TQCanvasItemPtr& that) const - { - // Order same-z objects by identity. - if (that.ptr->z()==ptr->z()) - return that.ptr <= ptr; - return that.ptr->z() <= ptr->z(); - } - bool operator<(const TQCanvasItemPtr& that) const - { - // Order same-z objects by identity. - if (that.ptr->z()==ptr->z()) - return that.ptr < ptr; - return that.ptr->z() < ptr->z(); - } - bool operator>(const TQCanvasItemPtr& that) const - { - // Order same-z objects by identity. - if (that.ptr->z()==ptr->z()) - return that.ptr > ptr; - return that.ptr->z() > ptr->z(); - } - bool operator==(const TQCanvasItemPtr& that) const - { - return that.ptr == ptr; - } - operator TQCanvasItem*() const { return ptr; } - -private: - TQCanvasItem* ptr; -}; - - -/*! - \class TQCanvasItemList - \brief The TQCanvasItemList class is a list of TQCanvasItems. -\if defined(commercial) - It is part of the TQt Enterprise Edition. -\endif - - \module canvas - \ingroup graphics - \ingroup images - - TQCanvasItemList is a TQValueList of pointers to \l{TQCanvasItem}s. - This class is used by some methods in TQCanvas that need to return - a list of canvas items. - - The \l TQValueList documentation describes how to use this list. -*/ - -/*! - \internal -*/ -void TQCanvasItemList::sort() -{ - qHeapSort(*((TQValueList*)this)); -} - -/*! - \internal -*/ -void TQCanvasItemList::drawUnique( TQPainter& painter ) -{ - TQCanvasItem* prev=0; - for (Iterator it=fromLast(); it!=end(); --it) { - TQCanvasItem *g=*it; - if (g!=prev) { - g->draw(painter); - prev=g; - } - } -} - -/*! - Returns the concatenation of this list and list \a l. -*/ -TQCanvasItemList TQCanvasItemList::operator+(const TQCanvasItemList &l) const -{ - TQCanvasItemList l2(*this); - for(const_iterator it = l.begin(); it != l.end(); ++it) - l2.append(*it); - return l2; -} - -class TQCanvasChunk { -public: - TQCanvasChunk() : changed(TRUE) { } - // Other code assumes lists are not deleted. Assignment is also - // done on ChunkRecs. So don't add that sort of thing here. - - void sort() - { - list.sort(); - } - - const TQCanvasItemList* listPtr() const - { - return &list; - } - - void add(TQCanvasItem* item) - { - list.prepend(item); - changed = TRUE; - } - - void remove(TQCanvasItem* item) - { - list.remove(item); - changed = TRUE; - } - - void change() - { - changed = TRUE; - } - - bool hasChanged() const - { - return changed; - } - - bool takeChange() - { - bool y = changed; - changed = FALSE; - return y; - } - -private: - TQCanvasItemList list; - bool changed; -}; - - -static int gcd(int a, int b) -{ - int r; - while ( (r = a%b) ) { - a=b; - b=r; - } - return b; -} - -static int scm(int a, int b) -{ - int g = gcd(a,b); - return a/g*b; -} - - - -/*! - \class TQCanvas ntqcanvas.h - \brief The TQCanvas class provides a 2D area that can contain TQCanvasItem objects. -\if defined(commercial) - It is part of the TQt Enterprise Edition. -\endif - - \ingroup abstractwidgets - \ingroup graphics - \ingroup images - \mainclass - \module canvas - - The TQCanvas class manages its 2D graphic area and all the canvas - items the area contains. The canvas has no visual appearance of - its own. Instead, it is displayed on screen using a TQCanvasView. - Multiple TQCanvasView widgets may be associated with a canvas to - provide multiple views of the same canvas. - - The canvas is optimized for large numbers of items, particularly - where only a small percentage of the items change at any - one time. If the entire display changes very frequently, you should - consider using your own custom TQScrollView subclass. - - TQt provides a rich - set of canvas item classes, e.g. TQCanvasEllipse, TQCanvasLine, - TQCanvasPolygon, TQCanvasPolygonalItem, TQCanvasRectangle, TQCanvasSpline, - TQCanvasSprite and TQCanvasText. You can subclass to create your own - canvas items; TQCanvasPolygonalItem is the most common base class used - for this purpose. - - Items appear on the canvas after their \link TQCanvasItem::show() - show()\endlink function has been called (or \link - TQCanvasItem::setVisible() setVisible(TRUE)\endlink), and \e after - update() has been called. The canvas only shows items that are - \link TQCanvasItem::setVisible() visible\endlink, and then only if - \l update() is called. (By default the canvas is white and so are - canvas items, so if nothing appears try changing colors.) - - If you created the canvas without passing a width and height to - the constructor you must also call resize(). - - Although a canvas may appear to be similar to a widget with child - widgets, there are several notable differences: - - \list - \i Canvas items are usually much faster to manipulate and redraw than - child widgets, with the speed advantage becoming especially great when - there are \e many canvas items and non-rectangular items. In most - situations canvas items are also a lot more memory efficient than child - widgets. - - \i It's easy to detect overlapping items (collision detection). - - \i The canvas can be larger than a widget. A million-by-million canvas - is perfectly possible. At such a size a widget might be very - inefficient, and some window systems might not support it at all, - whereas TQCanvas scales well. Even with a billion pixels and a million - items, finding a particular canvas item, detecting collisions, etc., - is still fast (though the memory consumption may be prohibitive - at such extremes). - - \i Two or more TQCanvasView objects can view the same canvas. - - \i An arbitrary transformation matrix can be set on each TQCanvasView - which makes it easy to zoom, rotate or shear the viewed canvas. - - \i Widgets provide a lot more functionality, such as input (TQKeyEvent, - TQMouseEvent etc.) and layout management (TQGridLayout etc.). - - \endlist - - A canvas consists of a background, a number of canvas items organized by - x, y and z coordinates, and a foreground. A canvas item's z coordinate - can be treated as a layer number -- canvas items with a higher z - coordinate appear in front of canvas items with a lower z coordinate. - - The background is white by default, but can be set to a different color - using setBackgroundColor(), or to a repeated pixmap using - setBackgroundPixmap() or to a mosaic of smaller pixmaps using - setTiles(). Individual tiles can be set with setTile(). There - are corresponding get functions, e.g. backgroundColor() and - backgroundPixmap(). - - Note that TQCanvas does not inherit from TQWidget, even though it has some - functions which provide the same functionality as those in TQWidget. One - of these is setBackgroundPixmap(); some others are resize(), size(), - width() and height(). \l TQCanvasView is the widget used to display a - canvas on the screen. - - Canvas items are added to a canvas by constructing them and passing the - canvas to the canvas item's constructor. An item can be moved to a - different canvas using TQCanvasItem::setCanvas(). - - Canvas items are movable (and in the case of TQCanvasSprites, animated) - objects that inherit TQCanvasItem. Each canvas item has a position on the - canvas (x, y coordinates) and a height (z coordinate), all of which are - held as floating-point numbers. Moving canvas items also have x and y - velocities. It's possible for a canvas item to be outside the canvas - (for example TQCanvasItem::x() is greater than width()). When a canvas - item is off the canvas, onCanvas() returns FALSE and the canvas - disregards the item. (Canvas items off the canvas do not slow down any - of the common operations on the canvas.) - - Canvas items can be moved with TQCanvasItem::move(). The advance() - function moves all TQCanvasItem::animated() canvas items and - setAdvancePeriod() makes TQCanvas move them automatically on a periodic - basis. In the context of the TQCanvas classes, to `animate' a canvas item - is to set it in motion, i.e. using TQCanvasItem::setVelocity(). Animation - of a canvas item itself, i.e. items which change over time, is enabled - by calling TQCanvasSprite::setFrameAnimation(), or more generally by - subclassing and reimplementing TQCanvasItem::advance(). To detect collisions - use one of the TQCanvasItem::collisions() functions. - - The changed parts of the canvas are redrawn (if they are visible in a - canvas view) whenever update() is called. You can either call update() - manually after having changed the contents of the canvas, or force - periodic updates using setUpdatePeriod(). If you have moving objects on - the canvas, you must call advance() every time the objects should - move one step further. Periodic calls to advance() can be forced using - setAdvancePeriod(). The advance() function will call - TQCanvasItem::advance() on every item that is \link - TQCanvasItem::animated() animated\endlink and trigger an update of the - affected areas afterwards. (A canvas item that is `animated' is simply - a canvas item that is in motion.) - - TQCanvas organizes its canvas items into \e chunks; these are areas on - the canvas that are used to speed up most operations. Many operations - start by eliminating most chunks (i.e. those which haven't changed) - and then process only the canvas items that are in the few interesting - (i.e. changed) chunks. A valid chunk, validChunk(), is one which is on - the canvas. - - The chunk size is a key factor to TQCanvas's speed: if there are too many - chunks, the speed benefit of grouping canvas items into chunks is - reduced. If the chunks are too large, it takes too long to process each - one. The TQCanvas constructor tries to pick a suitable size, but you - can call retune() to change it at any time. The chunkSize() function - returns the current chunk size. The canvas items always make sure - they're in the right chunks; all you need to make sure of is that - the canvas uses the right chunk size. A good rule of thumb is that - the size should be a bit smaller than the average canvas item - size. If you have moving objects, the chunk size should be a bit - smaller than the average size of the moving items. - - The foreground is normally nothing, but if you reimplement - drawForeground(), you can draw things in front of all the canvas - items. - - Areas can be set as changed with setChanged() and set unchanged with - setUnchanged(). The entire canvas can be set as changed with - setAllChanged(). A list of all the items on the canvas is returned by - allItems(). - - An area can be copied (painted) to a TQPainter with drawArea(). - - If the canvas is resized it emits the resized() signal. - - The examples/canvas application and the 2D graphics page of the - examples/demo application demonstrate many of TQCanvas's facilities. - - \sa TQCanvasView TQCanvasItem -*/ -void TQCanvas::init(int w, int h, int chunksze, int mxclusters) -{ - d = new TQCanvasData; - awidth=w; - aheight=h; - chunksize=chunksze; - maxclusters=mxclusters; - chwidth=(w+chunksize-1)/chunksize; - chheight=(h+chunksize-1)/chunksize; - chunks=new TQCanvasChunk[chwidth*chheight]; - update_timer = 0; - bgcolor = white; - grid = 0; - htiles = 0; - vtiles = 0; - dblbuf = TRUE; - debug_redraw_areas = FALSE; -} - -/*! - Create a TQCanvas with no size. \a parent and \a name are passed to - the TQObject superclass. - - \warning You \e must call resize() at some time after creation to - be able to use the canvas. -*/ -TQCanvas::TQCanvas( TQObject* parent, const char* name ) - : TQObject( parent, name ) -{ - init(0,0); -} - -/*! - Constructs a TQCanvas that is \a w pixels wide and \a h pixels high. -*/ -TQCanvas::TQCanvas(int w, int h) -{ - init(w,h); -} - -/*! - Constructs a TQCanvas which will be composed of \a h tiles - horizontally and \a v tiles vertically. Each tile will be an image - \a tilewidth by \a tileheight pixels taken from pixmap \a p. - - The pixmap \a p is a list of tiles, arranged left to right, (and - in the case of pixmaps that have multiple rows of tiles, top to - bottom), with tile 0 in the top-left corner, tile 1 next to the - right, and so on, e.g. - - \table - \row \i 0 \i 1 \i 2 \i 3 - \row \i 4 \i 5 \i 6 \i 7 - \endtable - - The TQCanvas is initially sized to show exactly the given number of - tiles horizontally and vertically. If it is resized to be larger, - the entire matrix of tiles will be repeated as often as necessary - to cover the area. If it is smaller, tiles to the right and bottom - will not be visible. - - \sa setTiles() -*/ -TQCanvas::TQCanvas( TQPixmap p, - int h, int v, int tilewidth, int tileheight ) -{ - init(h*tilewidth, v*tileheight, scm(tilewidth,tileheight) ); - setTiles( p, h, v, tilewidth, tileheight ); -} - -void qt_unview(TQCanvas* c) -{ - for (TQCanvasView* view=c->d->viewList.first(); view != 0; view=c->d->viewList.next()) { - view->viewing = 0; - } -} - -/*! - Destroys the canvas and all the canvas's canvas items. -*/ -TQCanvas::~TQCanvas() -{ - qt_unview(this); - TQCanvasItemList all = allItems(); - for (TQCanvasItemList::Iterator it=all.begin(); it!=all.end(); ++it) - delete *it; - delete [] chunks; - delete [] grid; - delete d; -} - -/*! -\internal -Returns the chunk at a chunk position \a i, \a j. -*/ -TQCanvasChunk& TQCanvas::chunk(int i, int j) const -{ - return chunks[i+chwidth*j]; -} - -/*! -\internal -Returns the chunk at a pixel position \a x, \a y. -*/ -TQCanvasChunk& TQCanvas::chunkContaining(int x, int y) const -{ - return chunk(x/chunksize,y/chunksize); -} - -/*! - Returns a list of all the items in the canvas. -*/ -TQCanvasItemList TQCanvas::allItems() -{ - TQCanvasItemList list; - for (TQPtrDictIterator it=d->itemDict; it.currentKey(); ++it) { - list.prepend((TQCanvasItem*)it.currentKey()); - } - return list; -} - - -/*! - Changes the size of the canvas to have a width of \a w and a - height of \a h. This is a slow operation. -*/ -void TQCanvas::resize(int w, int h) -{ - if (awidth==w && aheight==h) - return; - - TQCanvasItem* item; - TQPtrList hidden; - for (TQPtrDictIterator it=d->itemDict; it.currentKey(); ++it) { - if (((TQCanvasItem*)it.currentKey())->isVisible()) { - ((TQCanvasItem*)it.currentKey())->hide(); - hidden.append(((TQCanvasItem*)it.currentKey())); - } - } - - int nchwidth=(w+chunksize-1)/chunksize; - int nchheight=(h+chunksize-1)/chunksize; - - TQCanvasChunk* newchunks = new TQCanvasChunk[nchwidth*nchheight]; - - // Commit the new values. - // - awidth=w; - aheight=h; - chwidth=nchwidth; - chheight=nchheight; - delete [] chunks; - chunks=newchunks; - - for (item=hidden.first(); item != 0; item=hidden.next()) { - item->show(); - } - - setAllChanged(); - - emit resized(); -} - -/*! - \fn void TQCanvas::resized() - - This signal is emitted whenever the canvas is resized. Each - TQCanvasView connects to this signal to keep the scrollview's size - correct. -*/ - -/*! - Change the efficiency tuning parameters to \a mxclusters clusters, - each of size \a chunksze. This is a slow operation if there are - many objects on the canvas. - - The canvas is divided into chunks which are rectangular areas \a - chunksze wide by \a chunksze high. Use a chunk size which is about - the average size of the canvas items. If you choose a chunk size - which is too small it will increase the amount of calculation - required when drawing since each change will affect many chunks. - If you choose a chunk size which is too large the amount of - drawing required will increase because for each change, a lot of - drawing will be required since there will be many (unchanged) - canvas items which are in the same chunk as the changed canvas - items. - - Internally, a canvas uses a low-resolution "chunk matrix" to keep - track of all the items in the canvas. A 64x64 chunk matrix is the - default for a 1024x1024 pixel canvas, where each chunk collects - canvas items in a 16x16 pixel square. This default is also - affected by setTiles(). You can tune this default using this - function. For example if you have a very large canvas and want to - trade off speed for memory then you might set the chunk size to 32 - or 64. - - The \a mxclusters argument is the number of rectangular groups of - chunks that will be separately drawn. If the canvas has a large - number of small, dispersed items, this should be about that - number. Our testing suggests that a large number of clusters is - almost always best. - -*/ -void TQCanvas::retune(int chunksze, int mxclusters) -{ - maxclusters=mxclusters; - - if ( chunksize!=chunksze ) { - TQPtrList hidden; - for (TQPtrDictIterator it=d->itemDict; it.currentKey(); ++it) { - if (((TQCanvasItem*)it.currentKey())->isVisible()) { - ((TQCanvasItem*)it.currentKey())->hide(); - hidden.append(((TQCanvasItem*)it.currentKey())); - } - } - - chunksize=chunksze; - - int nchwidth=(awidth+chunksize-1)/chunksize; - int nchheight=(aheight+chunksize-1)/chunksize; - - TQCanvasChunk* newchunks = new TQCanvasChunk[nchwidth*nchheight]; - - // Commit the new values. - // - chwidth=nchwidth; - chheight=nchheight; - delete [] chunks; - chunks=newchunks; - - for (TQCanvasItem* item=hidden.first(); item != 0; item=hidden.next()) { - item->show(); - } - } -} - -/*! - \fn int TQCanvas::width() const - - Returns the width of the canvas, in pixels. -*/ - -/*! - \fn int TQCanvas::height() const - - Returns the height of the canvas, in pixels. -*/ - -/*! - \fn TQSize TQCanvas::size() const - - Returns the size of the canvas, in pixels. -*/ - -/*! - \fn TQRect TQCanvas::rect() const - - Returns a rectangle the size of the canvas. -*/ - - -/*! - \fn bool TQCanvas::onCanvas( int x, int y ) const - - Returns TRUE if the pixel position (\a x, \a y) is on the canvas; - otherwise returns FALSE. - - \sa validChunk() -*/ - -/*! - \fn bool TQCanvas::onCanvas( const TQPoint& p ) const - \overload - - Returns TRUE if the pixel position \a p is on the canvas; - otherwise returns FALSE. - - \sa validChunk() -*/ - -/*! - \fn bool TQCanvas::validChunk( int x, int y ) const - - Returns TRUE if the chunk position (\a x, \a y) is on the canvas; - otherwise returns FALSE. - - \sa onCanvas() -*/ - -/*! - \fn bool TQCanvas::validChunk( const TQPoint& p ) const - \overload - - Returns TRUE if the chunk position \a p is on the canvas; otherwise - returns FALSE. - - \sa onCanvas() -*/ - -/*! - \fn int TQCanvas::chunkSize() const - - Returns the chunk size of the canvas. - - \sa retune() -*/ - -/*! -\fn bool TQCanvas::sameChunk(int x1, int y1, int x2, int y2) const -\internal -Tells if the points ( \a x1, \a y1 ) and ( \a x2, \a y2 ) are within the same chunk. -*/ - -/*! -\internal -This method adds an the item \a item to the list of TQCanvasItem objects -in the TQCanvas. The TQCanvasItem class calls this. -*/ -void TQCanvas::addItem(TQCanvasItem* item) -{ - d->itemDict.insert((void*)item,(void*)1); -} - -/*! -\internal -This method adds the item \a item to the list of TQCanvasItem objects -to be moved. The TQCanvasItem class calls this. -*/ -void TQCanvas::addAnimation(TQCanvasItem* item) -{ - d->animDict.insert((void*)item,(void*)1); -} - -/*! -\internal -This method adds the item \a item to the list of TQCanvasItem objects -which are no longer to be moved. The TQCanvasItem class calls this. -*/ -void TQCanvas::removeAnimation(TQCanvasItem* item) -{ - d->animDict.remove((void*)item); -} - -/*! -\internal -This method removes the item \a item from the list of TQCanvasItem objects -in this TQCanvas. The TQCanvasItem class calls this. -*/ -void TQCanvas::removeItem(TQCanvasItem* item) -{ - d->itemDict.remove((void*)item); -} - -/*! -\internal -This method adds the view \a view to the list of TQCanvasView objects -viewing this TQCanvas. The TQCanvasView class calls this. -*/ -void TQCanvas::addView(TQCanvasView* view) -{ - d->viewList.append(view); - if ( htiles>1 || vtiles>1 || pm.isNull() ) - view->viewport()->setBackgroundColor(backgroundColor()); -} - -/*! -\internal -This method removes the view \a view from the list of TQCanvasView objects -viewing this TQCanvas. The TQCanvasView class calls this. -*/ -void TQCanvas::removeView(TQCanvasView* 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 TQCanvas::setAdvancePeriod(int ms) -{ - if ( ms<0 ) { - if ( update_timer ) - update_timer->stop(); - } else { - if ( update_timer ) - delete update_timer; - update_timer = new TQTimer(this); - connect(update_timer,TQ_SIGNAL(timeout()),this,TQ_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 TQCanvas::setUpdatePeriod(int ms) -{ - if ( ms<0 ) { - if ( update_timer ) - update_timer->stop(); - } else { - if ( update_timer ) - delete update_timer; - update_timer = new TQTimer(this); - connect(update_timer,TQ_SIGNAL(timeout()),this,TQ_SLOT(update())); - update_timer->start(ms); - } -} - -/*! - Moves all TQCanvasItem::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 - TQCanvasItem::advance() function of each TQCanvasItem::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 TQCanvasItem subclasses supplied with TQt do anything - interesting in phase 0. - - The canvas can be configured to call this function periodically - with setAdvancePeriod(). - - \sa update() -*/ -void TQCanvas::advance() -{ - TQPtrDictIterator it=d->animDict; - while ( it.current() ) { - TQCanvasItem* i = (TQCanvasItem*)(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() ) { - TQCanvasItem* i = (TQCanvasItem*)(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 TQCanvas::drawViewArea( TQCanvasView* view, TQPainter* p, const TQRect& vr, bool dbuf ) -{ - TQPoint tl = view->contentsToViewport(TQPoint(0,0)); - -#ifndef TQT_NO_TRANSFORMATIONS - TQWMatrix wm = view->worldMatrix(); - TQWMatrix iwm = wm.invert(); - // ivr = covers all chunks in vr - TQRect ivr = iwm.map(vr); - ivr.addCoords(-1, -1, 1, 1); - TQWMatrix twm; - twm.translate(tl.x(),tl.y()); -#else - TQRect ivr = vr; -#endif - - TQRect all(0,0,width(),height()); - - if ( !all.contains(ivr) ) { - // Need to clip with edge of canvas. - -#ifndef TQT_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). - TQPointArray a; - if ( wm.m12()==0.0 && wm.m21()==0.0 && wm.m11() == 1.0 && wm.m22() == 1.0 ) - a = TQPointArray( TQRect(all.x(),all.y(),all.width()+1,all.height()+1) ); - else - a = TQPointArray( all ); - - a = (wm*twm).map(a); -#else - TQPointArray a( TQRect(all.x(),all.y(),all.width()+1,all.height()+1) ); -#endif - if ( view->viewport()->backgroundMode() == NoBackground ) { - TQRect cvr = vr; cvr.moveBy(tl.x(),tl.y()); - p->setClipRegion(TQRegion(cvr)-TQRegion(a)); - p->fillRect(vr,view->viewport()->palette() - .brush(TQPalette::Active,TQColorGroup::Background)); - } - p->setClipRegion(a); - } - - if ( dbuf ) { - offscr = TQPixmap(vr.size().expandedTo(TQSize(1, 1))); -#ifdef TQ_WS_X11 - offscr.x11SetScreen(p->device()->x11Screen()); -#endif - TQPainter dbp(&offscr); -#ifndef TQT_NO_TRANSFORMATIONS - twm.translate(-vr.x(),-vr.y()); - twm.translate(-tl.x(),-tl.y()); - dbp.setWorldMatrix( wm*twm, TRUE ); -#else - dbp.translate(-vr.x()-tl.x(),-vr.y()-tl.y()); -#endif - dbp.setClipRect(0,0,vr.width(), vr.height()); - drawCanvasArea(ivr,&dbp,FALSE); - dbp.end(); - p->drawPixmap(vr.x(), vr.y(), offscr, 0, 0, vr.width(), vr.height()); - } else { - TQRect r = vr; r.moveBy(tl.x(),tl.y()); // move to untransformed co-ords - if ( !all.contains(ivr) ) { - TQRegion inside = p->clipRegion() & r; - //TQRegion outside = p->clipRegion() - r; - //p->setClipRegion(outside); - //p->fillRect(outside.boundingRect(),red); - p->setClipRegion(inside); - } else { - p->setClipRect(r); - } -#ifndef TQT_NO_TRANSFORMATIONS - p->setWorldMatrix( wm*twm ); -#else -#endif - p->setBrushOrigin(tl.x(), tl.y()); - drawCanvasArea(ivr,p,FALSE); - } -} - -/*! - Repaints changed areas in all views of the canvas. - - \sa advance() -*/ -void TQCanvas::update() -{ - TQCanvasClusterizer clusterizer(d->viewList.count()); -#ifndef TQT_NO_TRANSFORMATIONS - TQPtrList doneareas; - doneareas.setAutoDelete(TRUE); -#endif - - TQPtrListIterator it(d->viewList); - TQCanvasView* view; - while( (view=it.current()) != 0 ) { - ++it; -#ifndef TQT_NO_TRANSFORMATIONS - TQWMatrix wm = view->worldMatrix(); -#endif - TQRect area(view->contentsX(),view->contentsY(), - view->visibleWidth(),view->visibleHeight()); - if (area.width()>0 && area.height()>0) { -#ifndef TQT_NO_TRANSFORMATIONS - if ( !wm.isIdentity() ) { - // r = Visible area of the canvas where there are changes - TQRect r = changeBounds(view->inverseWorldMatrix().map(area)); - if ( !r.isEmpty() ) { - TQPainter p(view->viewport()); - // Translate to the coordinate system of drawViewArea(). - TQPoint tl = view->contentsToViewport(TQPoint(0,0)); - p.translate(tl.x(),tl.y()); - drawViewArea( view, &p, wm.map(r), dblbuf ); - doneareas.append(new TQRect(r)); - } - } else -#endif - { - clusterizer.add(area); - } - } - } - - for (int i=0; ichwidth) - mx=chwidth; - if (my>chheight) - my=chheight; - - int x=thearea.x()/chunksize; - while( xchwidth) - mx=chwidth; - if (my>chheight) - my=chheight; - - int x=thearea.x()/chunksize; - while( x chwidth) - mx=chwidth; - if (my > chheight) - my=chheight; - - TQRect result; - - int x=area.x()/chunksize; - while( x chwidth) - mx=chwidth; - if (my > chheight) - my=chheight; - - int x=area.x()/chunksize; - while( xviewList.first() && !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; - - TQCanvasItemList 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) - TQRegion 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 |= TQRegion(x*chunksize-area.x(),y*chunksize-area.y(), - chunksize,chunksize); - allvisible += *chunk(x,y).listPtr(); - } - } else { - allvisible += *chunk(x,y).listPtr(); - } - } - } - allvisible.sort(); - - if ( double_buffer ) { - offscr = TQPixmap(area.size().expandedTo(TQSize(1, 1))); -#ifdef TQ_WS_X11 - if (p) - offscr.x11SetScreen(p->device()->x11Screen()); -#endif - } - - if ( double_buffer && !offscr.isNull() ) { - TQPainter painter; - painter.begin(&offscr); - painter.translate(-area.x(),-area.y()); - painter.setBrushOrigin(-area.x(),-area.y()); - if ( p ) { - painter.setClipRect(TQRect(0,0,area.width(),area.height())); - } else { - painter.setClipRegion(rgn); - } - drawBackground(painter,area); - allvisible.drawUnique(painter); - drawForeground(painter,area); - painter.end(); - if ( p ) { - p->drawPixmap( area.x(), area.y(), offscr, - 0, 0, area.width(), area.height() ); - return; - } - } else if ( p ) { - drawBackground(*p,area); - allvisible.drawUnique(*p); - drawForeground(*p,area); - return; - } - - TQPoint trtr; // keeps track of total translation of rgn - - trtr -= area.topLeft(); - - for (TQCanvasView* view=d->viewList.first(); view; view=d->viewList.next()) { -#ifndef TQT_NO_TRANSFORMATIONS - if ( !view->worldMatrix().isIdentity() ) - continue; // Cannot paint those here (see callers). -#endif - TQPainter painter(view->viewport()); - TQPoint tr = view->contentsToViewport(area.topLeft()); - TQPoint nrtr = view->contentsToViewport(TQPoint(0,0)); // new translation - TQPoint rtr = nrtr - trtr; // extra translation of rgn - trtr += rtr; // add to total - if (double_buffer) { - rgn.translate(rtr.x(),rtr.y()); - painter.setClipRegion(rgn); - painter.drawPixmap(tr,offscr, TQRect(TQPoint(0,0),area.size())); - } else { - painter.translate(nrtr.x(),nrtr.y()); - rgn.translate(rtr.x(),rtr.y()); - painter.setClipRegion(rgn); - drawBackground(painter,area); - allvisible.drawUnique(painter); - drawForeground(painter,area); - painter.translate(-nrtr.x(),-nrtr.y()); - } - } -} - -/*! -\internal -This method to informs the TQCanvas 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 TQCanvasItem -must do so too. SetChangedChunkContaining can be used instead. -*/ -void TQCanvas::setChangedChunk(int x, int y) -{ - if (validChunk(x,y)) { - TQCanvasChunk& ch=chunk(x,y); - ch.change(); - } -} - -/*! -\internal -This method to informs the TQCanvas that the chunk containing a given -pixel 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 TQCanvasItem must -do so too. SetChangedChunk can be used instead. -*/ -void TQCanvas::setChangedChunkContaining(int x, int y) -{ - if (x>=0 && x=0 && y=0 && x=0 && y=0 && x=0 && yviewList.first(); - while ( view != 0 ) { - /* XXX this doesn't look right. Shouldn't this - be more like setBackgroundPixmap? : Ian */ - view->viewport()->setEraseColor( bgcolor ); - view=d->viewList.next(); - } - setAllChanged(); - } -} - -/*! - Returns the pixmap set by setBackgroundPixmap(). By default, - this is a null pixmap. - - \sa setBackgroundPixmap(), backgroundColor() -*/ -TQPixmap TQCanvas::backgroundPixmap() const -{ - return pm; -} - -/*! - Sets the solid background to be the pixmap \a p repeated as - necessary to cover the entire canvas. - - \sa backgroundPixmap(), setBackgroundColor(), setTiles() -*/ -void TQCanvas::setBackgroundPixmap( const TQPixmap& p ) -{ - setTiles(p, 1, 1, p.width(), p.height()); - TQCanvasView* view = d->viewList.first(); - while ( view != 0 ) { - view->updateContents(); - view = d->viewList.next(); - } -} - -/*! - This virtual function is called for all updates of the canvas. It - renders any background graphics using the painter \a painter, in - the area \a clip. If the canvas has a background pixmap or a tiled - background, that graphic is used, otherwise the canvas is cleared - using the background color. - - If the graphics for an area change, you must explicitly call - setChanged(const TQRect&) for the result to be visible when - update() is next called. - - \sa setBackgroundColor(), setBackgroundPixmap(), setTiles() -*/ -void TQCanvas::drawBackground(TQPainter& painter, const TQRect& clip) -{ - if ( pm.isNull() ) { - painter.fillRect(clip,bgcolor); - } else if ( !grid ) { - for (int x=clip.x()/pm.width(); - x<(clip.x()+clip.width()+pm.width()-1)/pm.width(); x++) - { - for (int y=clip.y()/pm.height(); - y<(clip.y()+clip.height()+pm.height()-1)/pm.height(); y++) - { - painter.drawPixmap(x*pm.width(), y*pm.height(),pm); - } - } - } else { - const int x1 = clip.left()/tilew; - int x2 = clip.right()/tilew; - const int y1 = clip.top()/tileh; - int y2 = clip.bottom()/tileh; - - const int roww = pm.width()/tilew; - - for (int j=y1; j<=y2; j++) { - int jj = j%tilesVertically(); - for (int i=x1; i<=x2; i++) { - int t = tile(i%tilesHorizontally(), jj); - int tx = t % roww; - int ty = t / roww; - painter.drawPixmap( i*tilew, j*tileh, pm, - tx*tilew, ty*tileh, tilew, tileh ); - } - } - } -} - -/*! - This virtual function is called for all updates of the canvas. It - renders any foreground graphics using the painter \a painter, in - the area \a clip. - - If the graphics for an area change, you must explicitly call - setChanged(const TQRect&) for the result to be visible when - update() is next called. - - The default is to draw nothing. -*/ -void TQCanvas::drawForeground(TQPainter& painter, const TQRect& clip) -{ - if ( debug_redraw_areas ) { - painter.setPen(red); - painter.setBrush(NoBrush); - painter.drawRect(clip); - } -} - -/*! - If \a y is TRUE (the default) double-buffering is switched on; - otherwise double-buffering is switched off. - - Turning off double-buffering causes the redrawn areas to flicker a - little and also gives a (usually small) performance improvement. -*/ -void TQCanvas::setDoubleBuffering(bool y) -{ - dblbuf = y; -} - - -/*! - Sets the TQCanvas to be composed of \a h tiles horizontally and \a - v tiles vertically. Each tile will be an image \a tilewidth by \a - tileheight pixels from pixmap \a p. - - The pixmap \a p is a list of tiles, arranged left to right, (and - in the case of pixmaps that have multiple rows of tiles, top to - bottom), with tile 0 in the top-left corner, tile 1 next to the - right, and so on, e.g. - - \table - \row \i 0 \i 1 \i 2 \i 3 - \row \i 4 \i 5 \i 6 \i 7 - \endtable - - If the canvas is larger than the matrix of tiles, the entire - matrix is repeated as necessary to cover the whole canvas. If it - is smaller, tiles to the right and bottom are not visible. - - The width and height of \a p must be a multiple of \a tilewidth - and \a tileheight. If they are not the function will do nothing. - - If you want to unset any tiling set, then just pass in a null - pixmap and 0 for \a h, \a v, \a tilewidth, and - \a tileheight. -*/ -void TQCanvas::setTiles( TQPixmap p, - int h, int v, int tilewidth, int tileheight ) -{ - if ( !p.isNull() && (!tilewidth || !tileheight || - p.width() % tilewidth != 0 || p.height() % tileheight != 0 ) ) - return; - - htiles = h; - vtiles = v; - delete[] grid; - pm = p; - if ( h && v && !p.isNull() ) { - grid = new ushort[h*v]; - memset( grid, 0, h*v*sizeof(ushort) ); - tilew = tilewidth; - tileh = tileheight; - } else { - grid = 0; - } - if ( h + v > 10 ) { - int s = scm(tilewidth,tileheight); - retune( s < 128 ? s : TQMAX(tilewidth,tileheight) ); - } - setAllChanged(); -} - -/*! - \fn int TQCanvas::tile( int x, int y ) const - - Returns the tile at position (\a x, \a y). Initially, all tiles - are 0. - - The parameters must be within range, i.e. - 0 \< \a x \< tilesHorizontally() and - 0 \< \a y \< tilesVertically(). - - \sa setTile() -*/ - -/*! - \fn int TQCanvas::tilesHorizontally() const - - Returns the number of tiles horizontally. -*/ - -/*! - \fn int TQCanvas::tilesVertically() const - - Returns the number of tiles vertically. -*/ - -/*! - \fn int TQCanvas::tileWidth() const - - Returns the width of each tile. -*/ - -/*! - \fn int TQCanvas::tileHeight() const - - Returns the height of each tile. -*/ - - -/*! - Sets the tile at (\a x, \a y) to use tile number \a tilenum, which - is an index into the tile pixmaps. The canvas will update - appropriately when update() is next called. - - The images are taken from the pixmap set by setTiles() and are - arranged left to right, (and in the case of pixmaps that have - multiple rows of tiles, top to bottom), with tile 0 in the - top-left corner, tile 1 next to the right, and so on, e.g. - - \table - \row \i 0 \i 1 \i 2 \i 3 - \row \i 4 \i 5 \i 6 \i 7 - \endtable - - \sa tile() setTiles() -*/ -void TQCanvas::setTile( int x, int y, int tilenum ) -{ - ushort& t = grid[x+y*htiles]; - if ( t != tilenum ) { - t = tilenum; - if ( tilew == tileh && tilew == chunksize ) - setChangedChunk( x, y ); // common case - else - setChanged( TQRect(x*tilew,y*tileh,tilew,tileh) ); - } -} - - -// lesser-used data in canvas item, plus room for extension. -// Be careful adding to this - check all usages. -class TQCanvasItemExtra { - TQCanvasItemExtra() : vx(0.0), vy(0.0) { } - double vx,vy; - friend class TQCanvasItem; -}; - - -/*! - \class TQCanvasItem ntqcanvas.h - \brief The TQCanvasItem class provides an abstract graphic object on a TQCanvas. -\if defined(commercial) - It is part of the TQt Enterprise Edition. -\endif - - \module canvas - \ingroup graphics - \ingroup images - - A variety of TQCanvasItem subclasses provide immediately usable - behaviour. This class is a pure abstract superclass providing the - behaviour that is shared among all the concrete canvas item classes. - TQCanvasItem is not intended for direct subclassing. It is much easier - to subclass one of its subclasses, e.g. TQCanvasPolygonalItem (the - commonest base class), TQCanvasRectangle, TQCanvasSprite, TQCanvasEllipse - or TQCanvasText. - - Canvas items are added to a canvas by constructing them and passing the - canvas to the canvas item's constructor. An item can be moved to a - different canvas using setCanvas(). - - Items appear on the canvas after their \link show() show()\endlink - function has been called (or \link setVisible() - setVisible(TRUE)\endlink), and \e after update() has been called. The - canvas only shows items that are \link setVisible() visible\endlink, - and then only if \l update() is called. If you created the canvas - without passing a width and height to the constructor you'll also need - to call \link TQCanvas::resize() resize()\endlink. Since the canvas - background defaults to white and canvas items default to white, - you may need to change colors to see your items. - - A TQCanvasItem object can be moved in the x(), y() and z() dimensions - using functions such as move(), moveBy(), setX(), setY() and setZ(). A - canvas item can be set in motion, `animated', using setAnimated() and - given a velocity in the x and y directions with setXVelocity() and - setYVelocity() -- the same effect can be achieved by calling - setVelocity(). Use the collidesWith() function to see if the canvas item - will collide on the \e next advance(1) and use collisions() to see what - collisions have occurred. - - Use TQCanvasSprite or your own subclass of TQCanvasSprite to create canvas - items which are animated, i.e. which change over time. - - The size of a canvas item is given by boundingRect(). Use - boundingRectAdvanced() to see what the size of the canvas item will be - \e after the next advance(1) call. - - The rtti() function is used for identifying subclasses of TQCanvasItem. - The canvas() function returns a pointer to the canvas which contains the - canvas item. - - TQCanvasItem provides the show() and isVisible() functions like those in - TQWidget. - - TQCanvasItem also provides the setEnabled(), setActive() and - setSelected() functions; these functions set the relevant boolean and - cause a repaint but the boolean values they set are not used in - TQCanvasItem itself. You can make use of these booleans in your subclasses. - - By default, canvas items have no velocity, no size, and are not in - motion. The subclasses provided in TQt do not change these defaults - except where noted. - -*/ - -/*! - \enum TQCanvasItem::RttiValues - - This enum is used to name the different types of canvas item. - - \value Rtti_Item Canvas item abstract base class - \value Rtti_Ellipse - \value Rtti_Line - \value Rtti_Polygon - \value Rtti_PolygonalItem - \value Rtti_Rectangle - \value Rtti_Spline - \value Rtti_Sprite - \value Rtti_Text - -*/ - -/*! - \fn void TQCanvasItem::update() - - Call this function to repaint the canvas's changed chunks. -*/ - -/*! - Constructs a TQCanvasItem on canvas \a canvas. - - \sa setCanvas() -*/ -TQCanvasItem::TQCanvasItem(TQCanvas* canvas) : - cnv(canvas), - myx(0),myy(0),myz(0) -{ - ani=0; - vis=0; - val=0; - sel=0; - ena=0; - act=0; - - ext = 0; - if (cnv) cnv->addItem(this); -} - -/*! - Destroys the TQCanvasItem and removes it from its canvas. -*/ -TQCanvasItem::~TQCanvasItem() -{ - if (cnv) { - cnv->removeItem(this); - cnv->removeAnimation(this); - } - delete ext; -} - -TQCanvasItemExtra& TQCanvasItem::extra() -{ - if ( !ext ) - ext = new TQCanvasItemExtra; - return *ext; -} - -/*! - \fn double TQCanvasItem::x() const - - Returns the horizontal position of the canvas item. Note that - subclasses often have an origin other than the top-left corner. -*/ - -/*! - \fn double TQCanvasItem::y() const - - Returns the vertical position of the canvas item. Note that - subclasses often have an origin other than the top-left corner. -*/ - -/*! - \fn double TQCanvasItem::z() const - - Returns the z index of the canvas item, which is used for visual - order: higher-z items obscure (are in front of) lower-z items. -*/ - -/*! - \fn void TQCanvasItem::setX(double x) - - Moves the canvas item so that its x-position is \a x. - - \sa x(), move() -*/ - -/*! - \fn void TQCanvasItem::setY(double y) - - Moves the canvas item so that its y-position is \a y. - - \sa y(), move() -*/ - -/*! - \fn void TQCanvasItem::setZ(double z) - - Sets the z index of the canvas item to \a z. Higher-z items - obscure (are in front of) lower-z items. - - \sa z(), move() -*/ - - -/*! - Moves the canvas item relative to its current position by (\a dx, - \a dy). -*/ -void TQCanvasItem::moveBy( double dx, double dy ) -{ - if ( dx || dy ) { - removeFromChunks(); - myx += dx; - myy += dy; - addToChunks(); - } -} - - -/*! - Moves the canvas item to the absolute position (\a x, \a y). -*/ -void TQCanvasItem::move( double x, double y ) -{ - moveBy( x-myx, y-myy ); -} - - -/*! - Returns TRUE if the canvas item is in motion; otherwise returns - FALSE. - - \sa setVelocity(), setAnimated() -*/ -bool TQCanvasItem::animated() const -{ - return (bool)ani; -} - -/*! - Sets the canvas item to be in motion if \a y is TRUE, or not if \a - y is FALSE. The speed and direction of the motion is set with - setVelocity(), or with setXVelocity() and setYVelocity(). - - \sa advance(), TQCanvas::advance() -*/ -void TQCanvasItem::setAnimated(bool y) -{ - if ( y != (bool)ani ) { - ani = (uint)y; - if ( y ) { - cnv->addAnimation(this); - } else { - cnv->removeAnimation(this); - } - } -} - -/*! - \fn void TQCanvasItem::setXVelocity( double vx ) - - Sets the horizontal component of the canvas item's velocity to \a vx. - - \sa setYVelocity() setVelocity() -*/ - -/*! - \fn void TQCanvasItem::setYVelocity( double vy ) - - Sets the vertical component of the canvas item's velocity to \a vy. - - \sa setXVelocity() setVelocity() -*/ - -/*! - Sets the canvas item to be in motion, moving by \a vx and \a vy - pixels in the horizontal and vertical directions respectively. - - \sa advance() setXVelocity() setYVelocity() -*/ -void TQCanvasItem::setVelocity( double vx, double vy) -{ - if ( ext || vx!=0.0 || vy!=0.0 ) { - if ( !ani ) - setAnimated(TRUE); - extra().vx = vx; - extra().vy = vy; - } -} - -/*! - Returns the horizontal velocity component of the canvas item. -*/ -double TQCanvasItem::xVelocity() const -{ - return ext ? ext->vx : 0; -} - -/*! - Returns the vertical velocity component of the canvas item. -*/ -double TQCanvasItem::yVelocity() const -{ - return ext ? ext->vy : 0; -} - -/*! - The default implementation moves the canvas item, if it is - animated(), by the preset velocity if \a phase is 1, and does - nothing if \a phase is 0. - - Note that if you reimplement this function, the reimplementation - must not change the canvas in any way, for example it must not add - or remove items. - - \sa TQCanvas::advance() setVelocity() -*/ -void TQCanvasItem::advance(int phase) -{ - if ( ext && phase==1 ) - moveBy(ext->vx,ext->vy); -} - -/*! - \fn void TQCanvasItem::draw(TQPainter& painter) - - This abstract virtual function draws the canvas item using \a painter. - - \warning When you reimplement this function, make sure that you - leave the painter in the same state as you found it. For example, - if you start by calling TQPainter::translate(50, 50), end your - code by calling TQPainter::translate(-50, -50). Be also aware that - the painter might already have some transformations set (i.e., - don't call TQPainter::resetXForm() when you're done). -*/ - -/*! - Sets the TQCanvas upon which the canvas item is to be drawn to \a c. - - \sa canvas() -*/ -void TQCanvasItem::setCanvas(TQCanvas* c) -{ - bool v=isVisible(); - setVisible(FALSE); - if (cnv) { - if (ext) - cnv->removeAnimation(this); - cnv->removeItem(this); - } - cnv=c; - if (cnv) { - cnv->addItem(this); - if ( ext ) - cnv->addAnimation(this); - } - setVisible(v); -} - -/*! - \fn TQCanvas* TQCanvasItem::canvas() const - - Returns the canvas containing the canvas item. -*/ - -/*! Shorthand for setVisible(TRUE). */ -void TQCanvasItem::show() -{ - setVisible(TRUE); -} - -/*! Shorthand for setVisible(FALSE). */ -void TQCanvasItem::hide() -{ - setVisible(FALSE); -} - -/*! - Makes the canvas item visible if \a yes is TRUE, or invisible if - \a yes is FALSE. The change takes effect when TQCanvas::update() is - next called. -*/ -void TQCanvasItem::setVisible(bool yes) -{ - if ((bool)vis!=yes) { - if (yes) { - vis=(uint)yes; - addToChunks(); - } else { - removeFromChunks(); - vis=(uint)yes; - } - } -} -/*! - \obsolete - \fn bool TQCanvasItem::visible() const - Use isVisible() instead. -*/ - -/*! - \fn bool TQCanvasItem::isVisible() const - - Returns TRUE if the canvas item is visible; otherwise returns - FALSE. - - Note that in this context TRUE does \e not mean that the canvas - item is currently in a view, merely that if a view is showing the - area where the canvas item is positioned, and the item is not - obscured by items with higher z values, and the view is not - obscured by overlaying windows, it would be visible. - - \sa setVisible(), z() -*/ - -/*! - \obsolete - \fn bool TQCanvasItem::selected() const - Use isSelected() instead. -*/ - -/*! - \fn bool TQCanvasItem::isSelected() const - - Returns TRUE if the canvas item is selected; otherwise returns FALSE. -*/ - -/*! - Sets the selected flag of the item to \a yes. If this changes the - item's selected state the item will be redrawn when - TQCanvas::update() is next called. - - The TQCanvas, TQCanvasItem and the TQt-supplied TQCanvasItem - subclasses do not make use of this value. The setSelected() - function is supplied because many applications need it, but it is - up to you how you use the isSelected() value. -*/ -void TQCanvasItem::setSelected(bool yes) -{ - if ((bool)sel!=yes) { - sel=(uint)yes; - changeChunks(); - } -} - -/*! - \obsolete - \fn bool TQCanvasItem::enabled() const - Use isEnabled() instead. -*/ - -/*! - \fn bool TQCanvasItem::isEnabled() const - - Returns TRUE if the TQCanvasItem is enabled; otherwise returns FALSE. -*/ - -/*! - Sets the enabled flag of the item to \a yes. If this changes the - item's enabled state the item will be redrawn when - TQCanvas::update() is next called. - - The TQCanvas, TQCanvasItem and the TQt-supplied TQCanvasItem - subclasses do not make use of this value. The setEnabled() - function is supplied because many applications need it, but it is - up to you how you use the isEnabled() value. -*/ -void TQCanvasItem::setEnabled(bool yes) -{ - if (ena!=(uint)yes) { - ena=(uint)yes; - changeChunks(); - } -} - -/*! - \obsolete - \fn bool TQCanvasItem::active() const - Use isActive() instead. -*/ - -/*! - \fn bool TQCanvasItem::isActive() const - - Returns TRUE if the TQCanvasItem is active; otherwise returns FALSE. -*/ - -/*! - Sets the active flag of the item to \a yes. If this changes the - item's active state the item will be redrawn when - TQCanvas::update() is next called. - - The TQCanvas, TQCanvasItem and the TQt-supplied TQCanvasItem - subclasses do not make use of this value. The setActive() function - is supplied because many applications need it, but it is up to you - how you use the isActive() value. -*/ -void TQCanvasItem::setActive(bool yes) -{ - if (act!=(uint)yes) { - act=(uint)yes; - changeChunks(); - } -} - -bool qt_testCollision(const TQCanvasSprite* s1, const TQCanvasSprite* s2) -{ - const TQImage* s2image = s2->imageAdvanced()->collision_mask; - TQRect s2area = s2->boundingRectAdvanced(); - - TQRect cyourarea(s2area.x(),s2area.y(), - s2area.width(),s2area.height()); - - TQImage* s1image=s1->imageAdvanced()->collision_mask; - - TQRect s1area = s1->boundingRectAdvanced(); - - TQRect ourarea = s1area.intersect(cyourarea); - - if ( ourarea.isEmpty() ) - return FALSE; - - int x2=ourarea.x()-cyourarea.x(); - int y2=ourarea.y()-cyourarea.y(); - int x1=ourarea.x()-s1area.x(); - int y1=ourarea.y()-s1area.y(); - int w=ourarea.width(); - int h=ourarea.height(); - - if ( !s2image ) { - if ( !s1image ) - return w>0 && h>0; - // swap everything around - int t; - t=x1; x1=x2; x2=t; - t=y1; x1=y2; y2=t; - s2image = s1image; - s1image = 0; - } - - // s2image != 0 - - // A non-linear search may be more efficient. - // Perhaps spiralling out from the center, or a simpler - // vertical expansion from the centreline. - - // We assume that sprite masks don't have - // different bit orders. - // - // Q_ASSERT(s1image->bitOrder()==s2image->bitOrder()); - - if (s1image) { - if (s1image->bitOrder() == TQImage::LittleEndian) { - for (int j=0; jscanLine(y1+j); - uchar* yl = s2image->scanLine(y2+j); - for (int i=0; i> 3)) & (1 << ((x2+i) & 7)) - && *(ml + ((x1+i) >> 3)) & (1 << ((x1+i) & 7))) - { - return TRUE; - } - } - } - } else { - for (int j=0; jscanLine(y1+j); - uchar* yl = s2image->scanLine(y2+j); - for (int i=0; i> 3)) & (1 << (7-((x2+i) & 7))) - && *(ml + ((x1+i) >> 3)) & (1 << (7-((x1+i) & 7)))) - { - return TRUE; - } - } - } - } - } else { - if (s2image->bitOrder() == TQImage::LittleEndian) { - for (int j=0; jscanLine(y2+j); - for (int i=0; i> 3)) & (1 << ((x2+i) & 7))) - { - return TRUE; - } - } - } - } else { - for (int j=0; jscanLine(y2+j); - for (int i=0; i> 3)) & (1 << (7-((x2+i) & 7)))) - { - return TRUE; - } - } - } - } - } - - return FALSE; -} - -static bool collision_double_dispatch( const TQCanvasSprite* s1, - const TQCanvasPolygonalItem* p1, - const TQCanvasRectangle* r1, - const TQCanvasEllipse* e1, - const TQCanvasText* t1, - const TQCanvasSprite* s2, - const TQCanvasPolygonalItem* p2, - const TQCanvasRectangle* r2, - const TQCanvasEllipse* e2, - const TQCanvasText* t2 ) -{ - const TQCanvasItem* i1 = s1 ? - (const TQCanvasItem*)s1 : p1 ? - (const TQCanvasItem*)p1 : r1 ? - (const TQCanvasItem*)r1 : e1 ? - (const TQCanvasItem*)e1 : (const TQCanvasItem*)t1; - const TQCanvasItem* i2 = s2 ? - (const TQCanvasItem*)s2 : p2 ? - (const TQCanvasItem*)p2 : r2 ? - (const TQCanvasItem*)r2 : e2 ? - (const TQCanvasItem*)e2 : (const TQCanvasItem*)t2; - - if ( s1 && s2 ) { - // a - return qt_testCollision(s1,s2); - } else if ( (r1 || t1 || s1) && (r2 || t2 || s2) ) { - // b - TQRect rc1 = i1->boundingRectAdvanced(); - TQRect rc2 = i2->boundingRectAdvanced(); - return rc1.intersects(rc2); - } else if ( e1 && e2 - && e1->angleLength()>=360*16 && e2->angleLength()>=360*16 - && e1->width()==e1->height() - && e2->width()==e2->height() ) { - // c - double xd = (e1->x()+e1->xVelocity())-(e2->x()+e1->xVelocity()); - double yd = (e1->y()+e1->yVelocity())-(e2->y()+e1->yVelocity()); - double rd = (e1->width()+e2->width())/2; - return xd*xd+yd*yd <= rd*rd; - } else if ( p1 && (p2 || s2 || t2) ) { - // d - TQPointArray pa1 = p1->areaPointsAdvanced(); - TQPointArray pa2 = p2 ? p2->areaPointsAdvanced() - : TQPointArray(i2->boundingRectAdvanced()); - bool col= !(TQRegion(pa1) & TQRegion(pa2,TRUE)).isEmpty(); - - return col; - } else { - return collision_double_dispatch(s2,p2,r2,e2,t2, - s1,p1,r1,e1,t1); - } -} - -/*! - \fn bool TQCanvasItem::collidesWith( const TQCanvasItem* other ) const - - Returns TRUE if the canvas item will collide with the \a other - item \e after they have moved by their current velocities; - otherwise returns FALSE. - - \sa collisions() -*/ - - -/*! - \class TQCanvasSprite ntqcanvas.h - \brief The TQCanvasSprite class provides an animated canvas item on a TQCanvas. -\if defined(commercial) - It is part of the TQt Enterprise Edition. -\endif - - \module canvas - \ingroup graphics - \ingroup images - - A canvas sprite is an object which can contain any number of images - (referred to as frames), only one of which is current, i.e. - displayed, at any one time. The images can be passed in the - constructor or set or changed later with setSequence(). If you - subclass TQCanvasSprite you can change the frame that is displayed - periodically, e.g. whenever TQCanvasItem::advance(1) is called to - create the effect of animation. - - The current frame can be set with setFrame() or with move(). The - number of frames available is given by frameCount(). The bounding - rectangle of the current frame is returned by boundingRect(). - - The current frame's image can be retrieved with image(); use - imageAdvanced() to retrieve the image for the frame that will be - shown after advance(1) is called. Use the image() overload passing - it an integer index to retrieve a particular image from the list of - frames. - - Use width() and height() to retrieve the dimensions of the current - frame. - - Use leftEdge() and rightEdge() to retrieve the current frame's - left-hand and right-hand x-coordinates respectively. Use - bottomEdge() and topEdge() to retrieve the current frame's bottom - and top y-coordinates respectively. These functions have an overload - which will accept an integer frame number to retrieve the - coordinates of a particular frame. - - TQCanvasSprite draws very quickly, at the expense of memory. - - The current frame's image can be drawn on a painter with draw(). - - Like any other canvas item, canvas sprites can be moved with - move() which sets the x and y coordinates and the frame number, as - well as with TQCanvasItem::move() and TQCanvasItem::moveBy(), or by - setting coordinates with TQCanvasItem::setX(), TQCanvasItem::setY() - and TQCanvasItem::setZ(). - -*/ - - -/*! - \reimp -*/ -bool TQCanvasSprite::collidesWith( const TQCanvasItem* i ) const -{ - return i->collidesWith(this,0,0,0,0); -} - -/*! - Returns TRUE if the canvas item collides with any of the given - items; otherwise returns FALSE. The parameters, \a s, \a p, \a r, - \a e and \a t, are all the same object, this is just a type - resolution trick. -*/ -bool TQCanvasSprite::collidesWith( const TQCanvasSprite* s, - const TQCanvasPolygonalItem* p, - const TQCanvasRectangle* r, - const TQCanvasEllipse* e, - const TQCanvasText* t ) const -{ - return collision_double_dispatch(s,p,r,e,t,this,0,0,0,0); -} - -/*! - \reimp -*/ -bool TQCanvasPolygonalItem::collidesWith( const TQCanvasItem* i ) const -{ - return i->collidesWith(0,this,0,0,0); -} - -bool TQCanvasPolygonalItem::collidesWith( const TQCanvasSprite* s, - const TQCanvasPolygonalItem* p, - const TQCanvasRectangle* r, - const TQCanvasEllipse* e, - const TQCanvasText* t ) const -{ - return collision_double_dispatch(s,p,r,e,t,0,this,0,0,0); -} - -/*! - \reimp -*/ -bool TQCanvasRectangle::collidesWith( const TQCanvasItem* i ) const -{ - return i->collidesWith(0,this,this,0,0); -} - -bool TQCanvasRectangle::collidesWith( const TQCanvasSprite* s, - const TQCanvasPolygonalItem* p, - const TQCanvasRectangle* r, - const TQCanvasEllipse* e, - const TQCanvasText* t ) const -{ - return collision_double_dispatch(s,p,r,e,t,0,this,this,0,0); -} - - -/*! - \reimp -*/ -bool TQCanvasEllipse::collidesWith( const TQCanvasItem* i ) const -{ - return i->collidesWith(0,this,0,this,0); -} - -bool TQCanvasEllipse::collidesWith( const TQCanvasSprite* s, - const TQCanvasPolygonalItem* p, - const TQCanvasRectangle* r, - const TQCanvasEllipse* e, - const TQCanvasText* t ) const -{ - return collision_double_dispatch(s,p,r,e,t,0,this,0,this,0); -} - -/*! - \reimp -*/ -bool TQCanvasText::collidesWith( const TQCanvasItem* i ) const -{ - return i->collidesWith(0,0,0,0,this); -} - -bool TQCanvasText::collidesWith( const TQCanvasSprite* s, - const TQCanvasPolygonalItem* p, - const TQCanvasRectangle* r, - const TQCanvasEllipse* e, - const TQCanvasText* t ) const -{ - return collision_double_dispatch(s,p,r,e,t,0,0,0,0,this); -} - -/*! - Returns the list of canvas items that this canvas item has - collided with. - - A collision is generally defined as occurring when the pixels of - one item draw on the pixels of another item, but not all - subclasses are so precise. Also, since pixel-wise collision - detection can be slow, this function works in either exact or - inexact mode, according to the \a exact parameter. - - If \a exact is TRUE, the canvas items returned have been - accurately tested for collision with the canvas item. - - If \a exact is FALSE, the canvas items returned are \e near the - canvas item. You can test the canvas items returned using - collidesWith() if any are interesting collision candidates. By - using this approach, you can ignore some canvas items for which - collisions are not relevant. - - The returned list is a list of TQCanvasItems, but often you will - need to cast the items to their subclass types. The safe way to do - this is to use rtti() before casting. This provides some of the - functionality of the standard C++ dynamic cast operation even on - compilers where dynamic casts are not available. - - Note that a canvas item may be `on' a canvas, e.g. it was created - with the canvas as parameter, even though its coordinates place it - beyond the edge of the canvas's area. Collision detection only - works for canvas items which are wholly or partly within the - canvas's area. - - Note that if items have a velocity (see \l setVelocity()), then - collision testing is done based on where the item \e will be when - it moves, not its current location. For example, a "ball" item - doesn't need to actually embed into a "wall" item before a - collision is detected. For items without velocity, plain - intersection is used. -*/ -TQCanvasItemList TQCanvasItem::collisions(bool exact) const -{ - return canvas()->collisions(chunks(),this,exact); -} - -/*! - Returns a list of canvas items that collide with the point \a p. - The list is ordered by z coordinates, from highest z coordinate - (front-most item) to lowest z coordinate (rear-most item). -*/ -TQCanvasItemList TQCanvas::collisions(const TQPoint& p) const -{ - return collisions(TQRect(p,TQSize(1,1))); -} - -/*! - \overload - - Returns a list of items which collide with the rectangle \a r. The - list is ordered by z coordinates, from highest z coordinate - (front-most item) to lowest z coordinate (rear-most item). -*/ -TQCanvasItemList TQCanvas::collisions(const TQRect& r) const -{ - TQCanvasRectangle i(r,(TQCanvas*)this); - i.setPen(NoPen); - i.show(); // doesn't actually show, since we destroy it - TQCanvasItemList l = i.collisions(TRUE); - l.sort(); - return l; -} - -/*! - \overload - - Returns a list of canvas items which intersect with the chunks - listed in \a chunklist, excluding \a item. If \a exact is TRUE, - only those which actually \link TQCanvasItem::collidesWith() - collide with\endlink \a item are returned; otherwise canvas items - are included just for being in the chunks. - - This is a utility function mainly used to implement the simpler - TQCanvasItem::collisions() function. -*/ -TQCanvasItemList TQCanvas::collisions(const TQPointArray& chunklist, - const TQCanvasItem* item, bool exact) const -{ - TQPtrDict seen; - TQCanvasItemList result; - for (int i=0; i<(int)chunklist.count(); i++) { - int x = chunklist[i].x(); - int y = chunklist[i].y(); - if ( validChunk(x,y) ) { - const TQCanvasItemList* l = chunk(x,y).listPtr(); - for (TQCanvasItemList::ConstIterator it=l->begin(); it!=l->end(); ++it) { - TQCanvasItem *g=*it; - if ( g != item ) { - if ( !seen.find(g) ) { - seen.replace(g,(void*)1); - if ( !exact || item->collidesWith(g) ) - result.append(g); - } - } - } - } - } - return result; -} - -/*! - \internal - Adds the item to all the chunks it covers. -*/ -void TQCanvasItem::addToChunks() -{ - if (isVisible() && canvas()) { - TQPointArray pa = chunks(); - for (int i=0; i<(int)pa.count(); i++) - canvas()->addItemToChunk(this,pa[i].x(),pa[i].y()); - val=(uint)TRUE; - } -} - -/*! - \internal - Removes the item from all the chunks it covers. -*/ -void TQCanvasItem::removeFromChunks() -{ - if (isVisible() && canvas()) { - TQPointArray pa = chunks(); - for (int i=0; i<(int)pa.count(); i++) - canvas()->removeItemFromChunk(this,pa[i].x(),pa[i].y()); - } -} - -/*! - \internal - Sets all the chunks covered by the item to be refreshed with TQCanvas::update() - is next called. -*/ -void TQCanvasItem::changeChunks() -{ - if (isVisible() && canvas()) { - if (!val) - addToChunks(); - TQPointArray pa = chunks(); - for (int i=0; i<(int)pa.count(); i++) - canvas()->setChangedChunk(pa[i].x(),pa[i].y()); - } -} - -/*! - \fn TQRect TQCanvasItem::boundingRect() const - - Returns the bounding rectangle in pixels that the canvas item covers. - - \sa boundingRectAdvanced() -*/ - -/*! - Returns the bounding rectangle of pixels that the canvas item \e - will cover after advance(1) is called. - - \sa boundingRect() -*/ -TQRect TQCanvasItem::boundingRectAdvanced() const -{ - int dx = int(x()+xVelocity())-int(x()); - int dy = int(y()+yVelocity())-int(y()); - TQRect r = boundingRect(); - r.moveBy(dx,dy); - return r; -} - -/*! - \class TQCanvasPixmap ntqcanvas.h - \brief The TQCanvasPixmap class provides pixmaps for TQCanvasSprites. -\if defined(commercial) - It is part of the TQt Enterprise Edition. -\endif - - \module canvas - \ingroup graphics - \ingroup images - - If you want to show a single pixmap on a TQCanvas use a - TQCanvasSprite with just one pixmap. - - When pixmaps are inserted into a TQCanvasPixmapArray they are held - as TQCanvasPixmaps. \l{TQCanvasSprite}s are used to show pixmaps on - \l{TQCanvas}es and hold their pixmaps in a TQCanvasPixmapArray. If - you retrieve a frame (pixmap) from a TQCanvasSprite it will be - returned as a TQCanvasPixmap. - - The pixmap is a TQPixmap and can only be set in the constructor. - There are three different constructors, one taking a TQPixmap, one - a TQImage and one a file name that refers to a file in any - supported file format (see TQImageIO). - - TQCanvasPixmap can have a hotspot which is defined in terms of an (x, - y) offset. When you create a TQCanvasPixmap from a PNG file or from - a TQImage that has a TQImage::offset(), the offset() is initialized - appropriately, otherwise the constructor leaves it at (0, 0). You - can set it later using setOffset(). When the TQCanvasPixmap is used - in a TQCanvasSprite, the offset position is the point at - TQCanvasItem::x() and TQCanvasItem::y(), not the top-left corner of - the pixmap. - - Note that for TQCanvasPixmap objects created by a TQCanvasSprite, the - position of each TQCanvasPixmap object is set so that the hotspot - stays in the same position. - - \sa TQCanvasPixmapArray TQCanvasItem TQCanvasSprite -*/ - -#ifndef TQT_NO_IMAGEIO - -/*! - Constructs a TQCanvasPixmap that uses the image stored in \a - datafilename. -*/ -TQCanvasPixmap::TQCanvasPixmap(const TQString& datafilename) -{ - TQImage image(datafilename); - init(image); -} - -#endif - -/*! - Constructs a TQCanvasPixmap from the image \a image. -*/ -TQCanvasPixmap::TQCanvasPixmap(const TQImage& image) -{ - init(image); -} -/*! - Constructs a TQCanvasPixmap from the pixmap \a pm using the offset - \a offset. -*/ -TQCanvasPixmap::TQCanvasPixmap(const TQPixmap& pm, const TQPoint& offset) -{ - init(pm,offset.x(),offset.y()); -} - -void TQCanvasPixmap::init(const TQImage& image) -{ - convertFromImage(image); - hotx = image.offset().x(); - hoty = image.offset().y(); -#ifndef TQT_NO_IMAGE_DITHER_TO_1 - if( image.hasAlphaBuffer() ) { - TQImage i = image.createAlphaMask(); - collision_mask = new TQImage(i); - } else -#endif - collision_mask = 0; -} - -void TQCanvasPixmap::init(const TQPixmap& pixmap, int hx, int hy) -{ - (TQPixmap&)*this = pixmap; - hotx = hx; - hoty = hy; - if( pixmap.mask() ) { - TQImage i = mask()->convertToImage(); - collision_mask = new TQImage(i); - } else - collision_mask = 0; -} - -/*! - Destroys the pixmap. -*/ -TQCanvasPixmap::~TQCanvasPixmap() -{ - delete collision_mask; -} - -/*! - \fn int TQCanvasPixmap::offsetX() const - - Returns the x-offset of the pixmap's hotspot. - - \sa setOffset() -*/ - -/*! - \fn int TQCanvasPixmap::offsetY() const - - Returns the y-offset of the pixmap's hotspot. - - \sa setOffset() -*/ - -/*! - \fn void TQCanvasPixmap::setOffset(int x, int y) - - Sets the offset of the pixmap's hotspot to (\a x, \a y). - - \warning Do not call this function if any TQCanvasSprites are - currently showing this pixmap. -*/ - -/*! - \class TQCanvasPixmapArray ntqcanvas.h - \brief The TQCanvasPixmapArray class provides an array of TQCanvasPixmaps. -\if defined(commercial) - It is part of the TQt Enterprise Edition. -\endif - - \module canvas - \ingroup graphics - \ingroup images - - - This class is used by TQCanvasSprite to hold an array of pixmaps. - It is used to implement animated sprites, i.e. images that change - over time, with each pixmap in the array holding one frame. - - Depending on the constructor you use you can load multiple pixmaps - into the array either from a directory (specifying a wildcard - pattern for the files), or from a list of TQPixmaps. You can also - read in a set of pixmaps after construction using readPixmaps(). - - Individual pixmaps can be set with setImage() and retrieved with - image(). The number of pixmaps in the array is returned by - count(). - - TQCanvasSprite uses an image's mask for collision detection. You - can change this by reading in a separate set of image masks using - readCollisionMasks(). - -*/ - -/*! - Constructs an invalid array (i.e. isValid() will return FALSE). - You must call readPixmaps() before being able to use this - TQCanvasPixmapArray. -*/ -TQCanvasPixmapArray::TQCanvasPixmapArray() -: framecount( 0 ), img( 0 ) -{ -} - -#ifndef TQT_NO_IMAGEIO -/*! - Constructs a TQCanvasPixmapArray from files. - - The \a fc parameter sets the number of frames to be loaded for - this image. - - If \a fc is not 0, \a datafilenamepattern should contain "%1", - e.g. "foo%1.png". The actual filenames are formed by replacing the - %1 with four-digit integers from 0 to (fc - 1), e.g. foo0000.png, - foo0001.png, foo0002.png, etc. - - If \a fc is 0, \a datafilenamepattern is asssumed to be a - filename, and the image contained in this file will be loaded as - the first (and only) frame. - - If \a datafilenamepattern does not exist, is not readable, isn't - an image, or some other error occurs, the array ends up empty and - isValid() returns FALSE. -*/ - -TQCanvasPixmapArray::TQCanvasPixmapArray( const TQString& datafilenamepattern, - int fc ) -: framecount( 0 ), img( 0 ) -{ - readPixmaps(datafilenamepattern,fc); -} -#endif - -/*! - \obsolete - Use TQCanvasPixmapArray::TQCanvasPixmapArray( TQValueList, TQPointArray ) - instead. - - Constructs a TQCanvasPixmapArray from the list of TQPixmaps \a - list. The \a hotspots list has to be of the same size as \a list. -*/ -TQCanvasPixmapArray::TQCanvasPixmapArray(TQPtrList list, TQPtrList hotspots) : - framecount(list.count()), - img(new TQCanvasPixmap*[list.count()]) -{ - if (list.count() != hotspots.count()) { - tqWarning("TQCanvasPixmapArray: lists have different lengths"); - reset(); - img = 0; - } else { - list.first(); - hotspots.first(); - for (int i=0; i list, TQPointArray hotspots) : - framecount((int)list.size()), - img(new TQCanvasPixmap*[list.size()]) -{ - bool have_hotspots = ( hotspots.size() != 0 ); - if (have_hotspots && list.count() != hotspots.count()) { - tqWarning("TQCanvasPixmapArray: lists have different lengths"); - reset(); - img = 0; - } else { - TQValueList::iterator it; - it = list.begin(); - for (int i=0; i 1; - if ( !arg ) - framecount=1; - for (int i=0; icollision_mask) - img[i]->collision_mask = new TQImage(); - img[i]->collision_mask->load( - arg ? datafilenamepattern.arg(r) : datafilenamepattern); - ok = ok - && !img[i]->collision_mask->isNull() - && img[i]->collision_mask->depth()==1; - } else { - img[i]=new TQCanvasPixmap( - arg ? datafilenamepattern.arg(r) : datafilenamepattern); - ok = ok && !img[i]->isNull(); - } - } - if ( !ok ) { - reset(); - } - return ok; -} -#endif - -/*! - \obsolete - - Use isValid() instead. - - This returns FALSE if the array is valid, and TRUE if it is not. -*/ -bool TQCanvasPixmapArray::operator!() -{ - return img==0; -} - -/*! - Returns TRUE if the pixmap array is valid; otherwise returns - FALSE. -*/ -bool TQCanvasPixmapArray::isValid() const -{ - return (img != 0); -} - -/*! - \fn TQCanvasPixmap* TQCanvasPixmapArray::image(int i) const - - Returns pixmap \a i in the array, if \a i is non-negative and less - than than count(), and returns an unspecified value otherwise. -*/ - -// ### wouldn't it be better to put empty TQCanvasPixmaps in there instead of -// initializing the additional elements in the array to 0? Lars -/*! - Replaces the pixmap at index \a i with pixmap \a p. - - The array takes ownership of \a p and will delete \a p when the - array itself is deleted. - - If \a i is beyond the end of the array the array is extended to at - least i+1 elements, with elements count() to i-1 being initialized - to 0. -*/ -void TQCanvasPixmapArray::setImage(int i, TQCanvasPixmap* p) -{ - if ( i >= framecount ) { - TQCanvasPixmap** newimg = new TQCanvasPixmap*[i+1]; - memcpy(newimg, img, sizeof( TQCanvasPixmap * )*framecount); - memset(newimg + framecount, 0, sizeof( TQCanvasPixmap * )*( i+1 - framecount ) ); - framecount = i+1; - delete [] img; - img = newimg; - } - delete img[i]; img[i]=p; -} - -/*! - \fn uint TQCanvasPixmapArray::count() const - - Returns the number of pixmaps in the array. -*/ - -/*! - Returns the x-coordinate of the current left edge of the sprite. - (This may change as the sprite animates since different frames may - have different left edges.) - - \sa rightEdge() bottomEdge() topEdge() -*/ -int TQCanvasSprite::leftEdge() const -{ - return int(x()) - image()->hotx; -} - -/*! - \overload - - Returns what the x-coordinate of the left edge of the sprite would - be if the sprite (actually its hotspot) were moved to x-position - \a nx. - - \sa rightEdge() bottomEdge() topEdge() -*/ -int TQCanvasSprite::leftEdge(int nx) const -{ - return nx - image()->hotx; -} - -/*! - Returns the y-coordinate of the top edge of the sprite. (This may - change as the sprite animates since different frames may have - different top edges.) - - \sa leftEdge() rightEdge() bottomEdge() -*/ -int TQCanvasSprite::topEdge() const -{ - return int(y()) - image()->hoty; -} - -/*! - \overload - - Returns what the y-coordinate of the top edge of the sprite would - be if the sprite (actually its hotspot) were moved to y-position - \a ny. - - \sa leftEdge() rightEdge() bottomEdge() -*/ -int TQCanvasSprite::topEdge(int ny) const -{ - return ny - image()->hoty; -} - -/*! - Returns the x-coordinate of the current right edge of the sprite. - (This may change as the sprite animates since different frames may - have different right edges.) - - \sa leftEdge() bottomEdge() topEdge() -*/ -int TQCanvasSprite::rightEdge() const -{ - return leftEdge() + image()->width()-1; -} - -/*! - \overload - - Returns what the x-coordinate of the right edge of the sprite - would be if the sprite (actually its hotspot) were moved to - x-position \a nx. - - \sa leftEdge() bottomEdge() topEdge() -*/ -int TQCanvasSprite::rightEdge(int nx) const -{ - return leftEdge(nx) + image()->width()-1; -} - -/*! - Returns the y-coordinate of the current bottom edge of the sprite. - (This may change as the sprite animates since different frames may - have different bottom edges.) - - \sa leftEdge() rightEdge() topEdge() -*/ -int TQCanvasSprite::bottomEdge() const -{ - return topEdge() + image()->height()-1; -} - -/*! - \overload - - Returns what the y-coordinate of the top edge of the sprite would - be if the sprite (actually its hotspot) were moved to y-position - \a ny. - - \sa leftEdge() rightEdge() topEdge() -*/ -int TQCanvasSprite::bottomEdge(int ny) const -{ - return topEdge(ny) + image()->height()-1; -} - -/*! - \fn TQCanvasPixmap* TQCanvasSprite::image() const - - Returns the current frame's image. - - \sa frame(), setFrame() -*/ - -/*! - \fn TQCanvasPixmap* TQCanvasSprite::image(int f) const - \overload - - Returns the image for frame \a f. Does not do any bounds checking on \a f. -*/ - -/*! - Returns the image the sprite \e will have after advance(1) is - called. By default this is the same as image(). -*/ -TQCanvasPixmap* TQCanvasSprite::imageAdvanced() const -{ - return image(); -} - -/*! - Returns the bounding rectangle for the image in the sprite's - current frame. This assumes that the images are tightly cropped - (i.e. do not have transparent pixels all along a side). -*/ -TQRect TQCanvasSprite::boundingRect() const -{ - return TQRect(leftEdge(), topEdge(), width(), height()); -} - - -/*! - \internal - Returns the chunks covered by the item. -*/ -TQPointArray TQCanvasItem::chunks() const -{ - TQPointArray r; - int n=0; - TQRect br = boundingRect(); - if (isVisible() && canvas()) { - int chunksize=canvas()->chunkSize(); - br &= TQRect(0,0,canvas()->width(),canvas()->height()); - if ( br.isValid() ) { - r.resize((br.width()/chunksize+2)*(br.height()/chunksize+2)); - for (int j=br.top()/chunksize; j<=br.bottom()/chunksize; j++) { - for (int i=br.left()/chunksize; i<=br.right()/chunksize; i++) { - r[n++] = TQPoint(i,j); - } - } - } - } - r.resize(n); - return r; -} - - -/*! - \internal - Add the sprite to the chunks in its TQCanvas which it overlaps. -*/ -void TQCanvasSprite::addToChunks() -{ - if (isVisible() && canvas()) { - int chunksize=canvas()->chunkSize(); - for (int j=topEdge()/chunksize; j<=bottomEdge()/chunksize; j++) { - for (int i=leftEdge()/chunksize; i<=rightEdge()/chunksize; i++) { - canvas()->addItemToChunk(this,i,j); - } - } - } -} - -/*! - \internal - Remove the sprite from the chunks in its TQCanvas which it overlaps. - - \sa addToChunks() -*/ -void TQCanvasSprite::removeFromChunks() -{ - if (isVisible() && canvas()) { - int chunksize=canvas()->chunkSize(); - for (int j=topEdge()/chunksize; j<=bottomEdge()/chunksize; j++) { - for (int i=leftEdge()/chunksize; i<=rightEdge()/chunksize; i++) { - canvas()->removeItemFromChunk(this,i,j); - } - } - } -} - -/*! - The width of the sprite for the current frame's image. - - \sa frame() -*/ -//### mark: Why don't we have width(int) and height(int) to be -//consistent with leftEdge() and leftEdge(int)? -int TQCanvasSprite::width() const -{ - return image()->width(); -} - -/*! - The height of the sprite for the current frame's image. - - \sa frame() -*/ -int TQCanvasSprite::height() const -{ - return image()->height(); -} - - -/*! - Draws the current frame's image at the sprite's current position - on painter \a painter. -*/ -void TQCanvasSprite::draw(TQPainter& painter) -{ - painter.drawPixmap(leftEdge(),topEdge(),*image()); -} - -/*! - \class TQCanvasView ntqcanvas.h - \brief The TQCanvasView class provides an on-screen view of a TQCanvas. -\if defined(commercial) - It is part of the TQt Enterprise Edition. -\endif - - \module canvas - \ingroup graphics - \ingroup images - - A TQCanvasView is widget which provides a view of a TQCanvas. - - If you want users to be able to interact with a canvas view, - subclass TQCanvasView. You might then reimplement - TQScrollView::contentsMousePressEvent(). For example, assuming no - transformation matrix is set: - - \code - void MyCanvasView::contentsMousePressEvent( TQMouseEvent* e ) - { - TQCanvasItemList l = canvas()->collisions(e->pos()); - for (TQCanvasItemList::Iterator it=l.begin(); it!=l.end(); ++it) { - if ( (*it)->rtti() == TQCanvasRectangle::RTTI ) - tqDebug("A TQCanvasRectangle lies somewhere at this point"); - } - } - \endcode - - The canvas view shows canvas canvas(); this can be changed using - setCanvas(). - - A transformation matrix can be used to transform the view of the - canvas in various ways, for example, zooming in or out or rotating. - For example: - - \code - TQWMatrix wm; - wm.scale( 2, 2 ); // Zooms in by 2 times - wm.rotate( 90 ); // Rotates 90 degrees counter clockwise - // around the origin. - wm.translate( 0, -canvas->height() ); - // moves the canvas down so what was visible - // before is still visible. - myCanvasView->setWorldMatrix( wm ); - \endcode - - Use setWorldMatrix() to set the canvas view's world matrix: you must - ensure that the world matrix is invertible. The current world matrix - is retrievable with worldMatrix(), and its inversion is retrievable - with inverseWorldMatrix(). - - Example: - - The following code finds the part of the canvas that is visible in - this view, i.e. the bounding rectangle of the view in canvas coordinates. - - \code - TQRect rc = TQRect( myCanvasView->contentsX(), myCanvasView->contentsY(), - myCanvasView->visibleWidth(), myCanvasView->visibleHeight() ); - TQRect canvasRect = myCanvasView->inverseWorldMatrix().mapRect(rc); - \endcode - - \sa TQWMatrix TQPainter::setWorldMatrix() - -*/ - -/*! - Constructs a TQCanvasView with parent \a parent, and name \a name, - using the widget flags \a f. The canvas view is not associated - with a canvas, so you must to call setCanvas() to view a - canvas. -*/ -TQCanvasView::TQCanvasView(TQWidget* parent, const char* name, WFlags f) : - TQScrollView(parent,name,f|WResizeNoErase|WStaticContents) -{ - d = new TQCanvasViewData; - viewing = 0; - setCanvas(0); - connect(this,TQ_SIGNAL(contentsMoving(int,int)),this,TQ_SLOT(cMoving(int,int))); -} - -/*! - \overload - - Constructs a TQCanvasView which views canvas \a canvas, with parent - \a parent, and name \a name, using the widget flags \a f. -*/ -TQCanvasView::TQCanvasView(TQCanvas* canvas, TQWidget* parent, const char* name, WFlags f) : - TQScrollView(parent,name,f|WResizeNoErase|WStaticContents) -{ - d = new TQCanvasViewData; - viewing = 0; - setCanvas(canvas); - - connect(this,TQ_SIGNAL(contentsMoving(int,int)),this,TQ_SLOT(cMoving(int,int))); -} - -/*! - Destroys the canvas view. The associated canvas is \e not deleted. -*/ -TQCanvasView::~TQCanvasView() -{ - delete d; - d = 0; - setCanvas(0); -} - -/*! - \fn TQCanvas* TQCanvasView::canvas() const - - Returns a pointer to the canvas which the TQCanvasView is currently - showing. -*/ - - -/*! - Sets the canvas that the TQCanvasView is showing to the canvas \a - canvas. -*/ -void TQCanvasView::setCanvas(TQCanvas* canvas) -{ - if (viewing) { - disconnect(viewing); - viewing->removeView(this); - } - viewing=canvas; - if (viewing) { - connect(viewing,TQ_SIGNAL(resized()), this, TQ_SLOT(updateContentsSize())); - viewing->addView(this); - } - if ( d ) // called by d'tor - updateContentsSize(); -} - -#ifndef TQT_NO_TRANSFORMATIONS -/*! - Returns a reference to the canvas view's current transformation matrix. - - \sa setWorldMatrix() inverseWorldMatrix() -*/ -const TQWMatrix &TQCanvasView::worldMatrix() const -{ - return d->xform; -} - -/*! - Returns a reference to the inverse of the canvas view's current - transformation matrix. - - \sa setWorldMatrix() worldMatrix() -*/ -const TQWMatrix &TQCanvasView::inverseWorldMatrix() const -{ - return d->ixform; -} - -/*! - Sets the transformation matrix of the TQCanvasView to \a wm. The - matrix must be invertible (i.e. if you create a world matrix that - zooms out by 2 times, then the inverse of this matrix is one that - will zoom in by 2 times). - - When you use this, you should note that the performance of the - TQCanvasView will decrease considerably. - - Returns FALSE if \a wm is not invertable; otherwise returns TRUE. - - \sa worldMatrix() inverseWorldMatrix() TQWMatrix::isInvertible() -*/ -bool TQCanvasView::setWorldMatrix( const TQWMatrix & wm ) -{ - bool ok = wm.isInvertible(); - if ( ok ) { - d->xform = wm; - d->ixform = wm.invert(); - updateContentsSize(); - viewport()->update(); - } - return ok; -} -#endif - -void TQCanvasView::updateContentsSize() -{ - if ( viewing ) { - TQRect br; -#ifndef TQT_NO_TRANSFORMATIONS - br = d->xform.map(TQRect(0,0,viewing->width(),viewing->height())); -#else - br = TQRect(0,0,viewing->width(),viewing->height()); -#endif - - if ( br.width() < contentsWidth() ) { - TQRect r(contentsToViewport(TQPoint(br.width(),0)), - TQSize(contentsWidth()-br.width(),contentsHeight())); - viewport()->erase(r); - } - if ( br.height() < contentsHeight() ) { - TQRect r(contentsToViewport(TQPoint(0,br.height())), - TQSize(contentsWidth(),contentsHeight()-br.height())); - viewport()->erase(r); - } - - resizeContents(br.width(),br.height()); - } else { - viewport()->erase(); - resizeContents(1,1); - } -} - -void TQCanvasView::cMoving(int x, int y) -{ - // A little kludge to smooth up repaints when scrolling - int dx = x - contentsX(); - int dy = y - contentsY(); - d->repaint_from_moving = TQABS(dx) < width()/8 && TQABS(dy) < height()/8; -} - -/*! - Repaints part of the TQCanvas that the canvas view is showing - starting at \a cx by \a cy, with a width of \a cw and a height of \a - ch using the painter \a p. - - \warning When double buffering is enabled, drawContents() will - not respect the current settings of the painter when setting up - the painter for the double buffer (e.g., viewport() and - window()). Also, be aware that TQCanvas::update() bypasses - drawContents(), which means any reimplementation of - drawContents() is not called. - - \sa TQCanvas::setDoubleBuffering() -*/ -void TQCanvasView::drawContents(TQPainter *p, int cx, int cy, int cw, int ch) -{ - TQRect r(cx,cy,cw,ch); - if (viewing) { - //viewing->drawViewArea(this,p,r,TRUE); - viewing->drawViewArea(this,p,r,!d->repaint_from_moving); - d->repaint_from_moving = FALSE; - } else { - p->eraseRect(r); - } -} - -/*! - \reimp - \internal - - (Implemented to get rid of a compiler warning.) -*/ -void TQCanvasView::drawContents( TQPainter * ) -{ -} - -/*! - Suggests a size sufficient to view the entire canvas. -*/ -TQSize TQCanvasView::sizeHint() const -{ - if ( !canvas() ) - return TQScrollView::sizeHint(); - // should maybe take transformations into account - return ( canvas()->size() + 2 * TQSize(frameWidth(), frameWidth()) ) - .boundedTo( 3 * TQApplication::desktop()->size() / 4 ); -} - -// ### TQt 4.0 customer request: operate on doubles rather than int. -// ### I know, almost impossible due to the use of TQRegion etc. -/*! - \class TQCanvasPolygonalItem ntqcanvas.h - \brief The TQCanvasPolygonalItem class provides a polygonal canvas item - on a TQCanvas. -\if defined(commercial) - It is part of the TQt Enterprise Edition. -\endif - - \module canvas - \ingroup graphics - \ingroup images - - The mostly rectangular classes, such as TQCanvasSprite and - TQCanvasText, use the object's bounding rectangle for movement, - repainting and collision calculations. For most other items, the - bounding rectangle can be far too large -- a diagonal line being - the worst case, and there are many other cases which are also bad. - TQCanvasPolygonalItem provides polygon-based bounding rectangle - handling, etc., which is much faster for non-rectangular items. - - Derived classes should try to define as small an area as possible - to maximize efficiency, but the polygon must \e definitely be - contained completely within the polygonal area. Calculating the - exact requirements is usually difficult, but if you allow a small - overestimate it can be easy and quick, while still getting almost - all of TQCanvasPolygonalItem's speed. - - Note that all subclasses \e must call hide() in their destructor - since hide() needs to be able to access areaPoints(). - - Normally, TQCanvasPolygonalItem uses the odd-even algorithm for - determining whether an object intersects this object. You can - change this to the winding algorithm using setWinding(). - - The bounding rectangle is available using boundingRect(). The - points bounding the polygonal item are retrieved with - areaPoints(). Use areaPointsAdvanced() to retrieve the bounding - points the polygonal item \e will have after - TQCanvasItem::advance(1) has been called. - - If the shape of the polygonal item is about to change while the - item is visible, call invalidate() before updating with a - different result from \l areaPoints(). - - By default, TQCanvasPolygonalItem objects have a black pen and no - brush (the default TQPen and TQBrush constructors). You can change - this with setPen() and setBrush(), but note that some - TQCanvasPolygonalItem subclasses only use the brush, ignoring the - pen setting. - - The polygonal item can be drawn on a painter with draw(). - Subclasses must reimplement drawShape() to draw themselves. - - Like any other canvas item polygonal items can be moved with - TQCanvasItem::move() and TQCanvasItem::moveBy(), or by setting coordinates - with TQCanvasItem::setX(), TQCanvasItem::setY() and TQCanvasItem::setZ(). - -*/ - - -/* - Since most polygonal items don't have a pen, the default is - NoPen and a black brush. -*/ -static const TQPen& defaultPolygonPen() -{ - static TQPen* dp=0; - if ( !dp ) - dp = new TQPen; - return *dp; -} - -static const TQBrush& defaultPolygonBrush() -{ - static TQBrush* db=0; - if ( !db ) - db = new TQBrush; - return *db; -} - -/*! - Constructs a TQCanvasPolygonalItem on the canvas \a canvas. -*/ -TQCanvasPolygonalItem::TQCanvasPolygonalItem(TQCanvas* canvas) : - TQCanvasItem(canvas), - br(defaultPolygonBrush()), - pn(defaultPolygonPen()) -{ - wind=0; -} - -/*! - Note that all subclasses \e must call hide() in their destructor - since hide() needs to be able to access areaPoints(). -*/ -TQCanvasPolygonalItem::~TQCanvasPolygonalItem() -{ -} - -/*! - Returns TRUE if the polygonal item uses the winding algorithm to - determine the "inside" of the polygon. Returns FALSE if it uses - the odd-even algorithm. - - The default is to use the odd-even algorithm. - - \sa setWinding() -*/ -bool TQCanvasPolygonalItem::winding() const -{ - return wind; -} - -/*! - If \a enable is TRUE, the polygonal item will use the winding - algorithm to determine the "inside" of the polygon; otherwise the - odd-even algorithm will be used. - - The default is to use the odd-even algorithm. - - \sa winding() -*/ -void TQCanvasPolygonalItem::setWinding(bool enable) -{ - wind = enable; -} - -/*! - Invalidates all information about the area covered by the canvas - item. The item will be updated automatically on the next call that - changes the item's status, for example, move() or update(). Call - this function if you are going to change the shape of the item (as - returned by areaPoints()) while the item is visible. -*/ -void TQCanvasPolygonalItem::invalidate() -{ - val = (uint)FALSE; - removeFromChunks(); -} - -/*! - \fn TQCanvasPolygonalItem::isValid() const - - Returns TRUE if the polygonal item's area information has not been - invalidated; otherwise returns FALSE. - - \sa invalidate() -*/ - -/*! - Returns the points the polygonal item \e will have after - TQCanvasItem::advance(1) is called, i.e. what the points are when - advanced by the current xVelocity() and yVelocity(). -*/ -TQPointArray TQCanvasPolygonalItem::areaPointsAdvanced() const -{ - int dx = int(x()+xVelocity())-int(x()); - int dy = int(y()+yVelocity())-int(y()); - TQPointArray r = areaPoints(); - r.detach(); // Explicit sharing is stupid. - if ( dx || dy ) - r.translate(dx,dy); - return r; -} - -//#define TQCANVAS_POLYGONS_DEBUG -#ifdef TQCANVAS_POLYGONS_DEBUG -static TQWidget* dbg_wid=0; -static TQPainter* dbg_ptr=0; -#endif - -class TQPolygonalProcessor { -public: - TQPolygonalProcessor(TQCanvas* c, const TQPointArray& pa) : - canvas(c) - { - TQRect pixelbounds = pa.boundingRect(); - int cs = canvas->chunkSize(); - TQRect canvasbounds = pixelbounds.intersect(canvas->rect()); - bounds.setLeft(canvasbounds.left()/cs); - bounds.setRight(canvasbounds.right()/cs); - bounds.setTop(canvasbounds.top()/cs); - bounds.setBottom(canvasbounds.bottom()/cs); - bitmap = TQImage(bounds.width() + 1, bounds.height(), 1, 2, TQImage::LittleEndian); - pnt = 0; - bitmap.fill(0); -#ifdef TQCANVAS_POLYGONS_DEBUG - dbg_start(); -#endif - } - - inline void add(int x, int y) - { - if ( pnt >= (int)result.size() ) { - result.resize(pnt*2+10); - } - result[pnt++] = TQPoint(x+bounds.x(),y+bounds.y()); -#ifdef TQCANVAS_POLYGONS_DEBUG - if ( dbg_ptr ) { - int cs = canvas->chunkSize(); - TQRect r(x*cs+bounds.x()*cs,y*cs+bounds.y()*cs,cs-1,cs-1); - dbg_ptr->setPen(TQt::blue); - dbg_ptr->drawRect(r); - } -#endif - } - - inline void addBits(int x1, int x2, uchar newbits, int xo, int yo) - { - for (int i=x1; i<=x2; i++) - if ( newbits & (1<resize(800,600); - dbg_wid->show(); - dbg_ptr = new TQPainter(dbg_wid); - dbg_ptr->setBrush(TQt::NoBrush); - } - dbg_ptr->fillRect(dbg_wid->rect(),TQt::white); - } -#endif - - void doSpans(int n, TQPoint* pt, int* w) - { - int cs = canvas->chunkSize(); - for (int j=0; j= bitmap.height() || y < 0) continue; - uchar* l = bitmap.scanLine(y); - int x = pt[j].x(); - int x1 = x/cs-bounds.x(); - if (x1 > bounds.width()) continue; - x1 = TQMAX(0,x1); - int x2 = (x+w[j])/cs-bounds.x(); - if (x2 < 0) continue; - x2 = TQMIN(bounds.width(), x2); - int x1q = x1/8; - int x1r = x1%8; - int x2q = x2/8; - int x2r = x2%8; -#ifdef TQCANVAS_POLYGONS_DEBUG - if ( dbg_ptr ) dbg_ptr->setPen(TQt::yellow); -#endif - if ( x1q == x2q ) { - uchar newbits = (~l[x1q]) & (((2<<(x2r-x1r))-1)<setPen(TQt::darkGreen); -#endif - addBits(x1r,x2r,newbits,x1q*8,y); - l[x1q] |= newbits; - } - } else { -#ifdef TQCANVAS_POLYGONS_DEBUG - if ( dbg_ptr ) dbg_ptr->setPen(TQt::blue); -#endif - uchar newbits1 = (~l[x1q]) & (0xff<setPen(TQt::green); -#endif - addBits(x1r,7,newbits1,x1q*8,y); - l[x1q] |= newbits1; - } - for (int i=x1q+1; i>(7-x2r)); - if ( newbits2 ) { -#ifdef TQCANVAS_POLYGONS_DEBUG - if ( dbg_ptr ) dbg_ptr->setPen(TQt::red); -#endif - addBits(0,x2r,newbits2,x2q*8,y); - l[x2q] |= newbits2; - } - } -#ifdef TQCANVAS_POLYGONS_DEBUG - if ( dbg_ptr ) { - dbg_ptr->drawLine(pt[j],pt[j]+TQPoint(w[j],0)); - } -#endif - } - result.resize(pnt); - } - - int pnt; - TQPointArray result; - TQCanvas* canvas; - TQRect bounds; - TQImage bitmap; -}; - - -TQPointArray TQCanvasPolygonalItem::chunks() const -{ - TQPointArray pa = areaPoints(); - - if ( !pa.size() ) { - pa.detach(); // Explicit sharing is stupid. - return pa; - } - - TQPolygonalProcessor processor(canvas(),pa); - - scanPolygon(pa, wind, processor); - - return processor.result; -} -/*! - Simply calls TQCanvasItem::chunks(). -*/ -TQPointArray TQCanvasRectangle::chunks() const -{ - // No need to do a polygon scan! - return TQCanvasItem::chunks(); -} - -/*! - Returns the bounding rectangle of the polygonal item, based on - areaPoints(). -*/ -TQRect TQCanvasPolygonalItem::boundingRect() const -{ - return areaPoints().boundingRect(); -} - -/*! - Reimplemented from TQCanvasItem, this draws the polygonal item by - setting the pen and brush for the item on the painter \a p and - calling drawShape(). -*/ -void TQCanvasPolygonalItem::draw(TQPainter & p) -{ - p.setPen(pn); - p.setBrush(br); - drawShape(p); -} - -/*! - \fn void TQCanvasPolygonalItem::drawShape(TQPainter & p) - - Subclasses must reimplement this function to draw their shape. The - pen and brush of \a p are already set to pen() and brush() prior - to calling this function. - - \warning When you reimplement this function, make sure that you - leave the painter in the same state as you found it. For example, - if you start by calling TQPainter::translate(50, 50), end your - code by calling TQPainter::translate(-50, -50). Be also aware that - the painter might already have some transformations set (i.e., - don't call TQPainter::resetXForm() when you're done). - - \sa draw() -*/ - -/*! - \fn TQPen TQCanvasPolygonalItem::pen() const - - Returns the TQPen used to draw the outline of the item, if any. - - \sa setPen() -*/ - -/*! - \fn TQBrush TQCanvasPolygonalItem::brush() const - - Returns the TQBrush used to fill the item, if filled. - - \sa setBrush() -*/ - -/*! - Sets the TQPen used when drawing the item to the pen \a p. - Note that many TQCanvasPolygonalItems do not use the pen value. - - \sa setBrush(), pen(), drawShape() -*/ -void TQCanvasPolygonalItem::setPen(TQPen p) -{ - if ( pn != p ) { - removeFromChunks(); - pn = p; - addToChunks(); - } -} - -/*! - Sets the TQBrush used when drawing the polygonal item to the brush \a b. - - \sa setPen(), brush(), drawShape() -*/ -void TQCanvasPolygonalItem::setBrush(TQBrush b) -{ - if ( br != b) { - br = b; - changeChunks(); - } -} - - -/*! - \class TQCanvasPolygon ntqcanvas.h - \brief The TQCanvasPolygon class provides a polygon on a TQCanvas. -\if defined(commercial) - It is part of the TQt Enterprise Edition. -\endif - - \module canvas - \ingroup graphics - \ingroup images - - Paints a polygon with a TQBrush. The polygon's points can be set in - the constructor or set or changed later using setPoints(). Use - points() to retrieve the points, or areaPoints() to retrieve the - points relative to the canvas's origin. - - The polygon can be drawn on a painter with drawShape(). - - Like any other canvas item polygons can be moved with - TQCanvasItem::move() and TQCanvasItem::moveBy(), or by setting - coordinates with TQCanvasItem::setX(), TQCanvasItem::setY() and - TQCanvasItem::setZ(). - - Note: TQCanvasPolygon does not use the pen. -*/ - -/*! - Constructs a point-less polygon on the canvas \a canvas. You - should call setPoints() before using it further. -*/ -TQCanvasPolygon::TQCanvasPolygon(TQCanvas* canvas) : - TQCanvasPolygonalItem(canvas) -{ -} - -/*! - Destroys the polygon. -*/ -TQCanvasPolygon::~TQCanvasPolygon() -{ - hide(); -} - -/*! - Draws the polygon using the painter \a p. - - Note that TQCanvasPolygon does not support an outline (the pen is - always NoPen). -*/ -void TQCanvasPolygon::drawShape(TQPainter & p) -{ - // ### why can't we draw outlines? We could use drawPolyline for it. Lars - // ### see other message. Warwick - - p.setPen(NoPen); // since TQRegion(TQPointArray) excludes outline :-( )-: - p.drawPolygon(poly); -} - -/*! - Sets the points of the polygon to be \a pa. These points will have - their x and y coordinates automatically translated by x(), y() as - the polygon is moved. -*/ -void TQCanvasPolygon::setPoints(TQPointArray pa) -{ - removeFromChunks(); - poly = pa; - poly.detach(); // Explicit sharing is stupid. - poly.translate((int)x(),(int)y()); - addToChunks(); -} - -/*! - \reimp -*/ -void TQCanvasPolygon::moveBy(double dx, double dy) -{ - // Note: does NOT call TQCanvasPolygonalItem::moveBy(), since that - // only does half this work. - // - int idx = int(x()+dx)-int(x()); - int idy = int(y()+dy)-int(y()); - if ( idx || idy ) { - removeFromChunks(); - poly.translate(idx,idy); - } - myx+=dx; - myy+=dy; - if ( idx || idy ) { - addToChunks(); - } -} - -/*! - \class TQCanvasSpline ntqcanvas.h - \brief The TQCanvasSpline class provides multi-bezier splines on a TQCanvas. -\if defined(commercial) - It is part of the TQt Enterprise Edition. -\endif - - \module canvas - \ingroup graphics - \ingroup images - - A TQCanvasSpline is a sequence of 4-point bezier curves joined - together to make a curved shape. - - You set the control points of the spline with setControlPoints(). - - If the bezier is closed(), then the first control point will be - re-used as the last control point. Therefore, a closed bezier must - have a multiple of 3 control points and an open bezier must have - one extra point. - - The beziers are not necessarily joined "smoothly". To ensure this, - set control points appropriately (general reference texts about - beziers will explain this in detail). - - Like any other canvas item splines can be moved with - TQCanvasItem::move() and TQCanvasItem::moveBy(), or by setting - coordinates with TQCanvasItem::setX(), TQCanvasItem::setY() and - TQCanvasItem::setZ(). - -*/ - -/*! - Create a spline with no control points on the canvas \a canvas. - - \sa setControlPoints() -*/ -TQCanvasSpline::TQCanvasSpline(TQCanvas* canvas) : - TQCanvasPolygon(canvas), - cl(TRUE) -{ -} - -/*! - Destroy the spline. -*/ -TQCanvasSpline::~TQCanvasSpline() -{ -} - -// ### shouldn't we handle errors more gracefully than with an assert? Lars -// ### no, since it's a programming error. Warwick -/*! - Set the spline control points to \a ctrl. - - If \a close is TRUE, then the first point in \a ctrl will be - re-used as the last point, and the number of control points must - be a multiple of 3. If \a close is FALSE, one additional control - point is required, and the number of control points must be one of - (4, 7, 10, 13, ...). - - If the number of control points doesn't meet the above conditions, - the number of points will be truncated to the largest number of - points that do meet the requirement. -*/ -void TQCanvasSpline::setControlPoints(TQPointArray ctrl, bool close) -{ - if ( (int)ctrl.count() % 3 != (close ? 0 : 1) ) { - tqWarning( "TQCanvasSpline::setControlPoints(): Number of points doesn't fit." ); - int numCurves = (ctrl.count() - (close ? 0 : 1 ))/ 3; - ctrl.resize( numCurves*3 + ( close ? 0 : 1 ) ); - } - - cl = close; - bez = ctrl; - recalcPoly(); -} - -/*! - Returns the current set of control points. - - \sa setControlPoints(), closed() -*/ -TQPointArray TQCanvasSpline::controlPoints() const -{ - return bez; -} - -/*! - Returns TRUE if the control points are a closed set; otherwise - returns FALSE. -*/ -bool TQCanvasSpline::closed() const -{ - return cl; -} - -void TQCanvasSpline::recalcPoly() -{ - TQPtrList segs; - segs.setAutoDelete(TRUE); - int n=0; - for (int i=0; i<(int)bez.count()-1; i+=3) { - TQPointArray ctrl(4); - ctrl[0] = bez[i+0]; - ctrl[1] = bez[i+1]; - ctrl[2] = bez[i+2]; - if ( cl ) - ctrl[3] = bez[(i+3)%(int)bez.count()]; - else - ctrl[3] = bez[i+3]; - TQPointArray *seg = new TQPointArray(ctrl.cubicBezier()); - n += seg->count()-1; - segs.append(seg); - } - TQPointArray p(n+1); - n=0; - for (TQPointArray* seg = segs.first(); seg; seg = segs.next()) { - for (int i=0; i<(int)seg->count()-1; i++) - p[n++] = seg->point(i); - if ( n == (int)p.count()-1 ) - p[n] = seg->point(seg->count()-1); - } - TQCanvasPolygon::setPoints(p); -} - -/*! - \fn TQPointArray TQCanvasPolygonalItem::areaPoints() const - - This function must be reimplemented by subclasses. It \e must - return the points bounding (i.e. outside and not touching) the - shape or drawing errors will occur. -*/ - -/*! - \fn TQPointArray TQCanvasPolygon::points() const - - Returns the vertices of the polygon, not translated by the position. - - \sa setPoints(), areaPoints() -*/ -TQPointArray TQCanvasPolygon::points() const -{ - TQPointArray pa = areaPoints(); - pa.translate(int(-x()),int(-y())); - return pa; -} - -/*! - Returns the vertices of the polygon translated by the polygon's - current x(), y() position, i.e. relative to the canvas's origin. - - \sa setPoints(), points() -*/ -TQPointArray TQCanvasPolygon::areaPoints() const -{ - return poly.copy(); -} - -// ### mark: Why don't we offer a constructor that lets the user set the -// points -- that way for some uses just the constructor call would be -// required? -/*! - \class TQCanvasLine ntqcanvas.h - \brief The TQCanvasLine class provides a line on a TQCanvas. -\if defined(commercial) - It is part of the TQt Enterprise Edition. -\endif - - \module canvas - \ingroup graphics - \ingroup images - - The line inherits functionality from TQCanvasPolygonalItem, for - example the setPen() function. The start and end points of the - line are set with setPoints(). - - Like any other canvas item lines can be moved with - TQCanvasItem::move() and TQCanvasItem::moveBy(), or by setting - coordinates with TQCanvasItem::setX(), TQCanvasItem::setY() and - TQCanvasItem::setZ(). -*/ - -/*! - Constructs a line from (0,0) to (0,0) on \a canvas. - - \sa setPoints(). -*/ -TQCanvasLine::TQCanvasLine(TQCanvas* canvas) : - TQCanvasPolygonalItem(canvas) -{ - x1 = y1 = x2 = y2 = 0; -} - -/*! - Destroys the line. -*/ -TQCanvasLine::~TQCanvasLine() -{ - hide(); -} - -/*! - \reimp -*/ -void TQCanvasLine::setPen(TQPen p) -{ - TQCanvasPolygonalItem::setPen(p); -} - -/*! - \fn TQPoint TQCanvasLine::startPoint () const - - Returns the start point of the line. - - \sa setPoints(), endPoint() -*/ - -/*! - \fn TQPoint TQCanvasLine::endPoint () const - - Returns the end point of the line. - - \sa setPoints(), startPoint() -*/ - -/*! - Sets the line's start point to (\a xa, \a ya) and its end point to - (\a xb, \a yb). -*/ -void TQCanvasLine::setPoints(int xa, int ya, int xb, int yb) -{ - if ( x1 != xa || x2 != xb || y1 != ya || y2 != yb ) { - removeFromChunks(); - x1 = xa; - y1 = ya; - x2 = xb; - y2 = yb; - addToChunks(); - } -} - -/*! - \reimp -*/ -void TQCanvasLine::drawShape(TQPainter &p) -{ - p.drawLine((int)(x()+x1), (int)(y()+y1), (int)(x()+x2), (int)(y()+y2)); -} - -/*! - \reimp - - Note that the area defined by the line is somewhat thicker than - the line that is actually drawn. -*/ -TQPointArray TQCanvasLine::areaPoints() const -{ - TQPointArray p(4); - int xi = int(x()); - int yi = int(y()); - int pw = pen().width(); - int dx = TQABS(x1-x2); - int dy = TQABS(y1-y2); - pw = pw*4/3+2; // approx pw*sqrt(2) - int px = x1 dy ? (dx*2/dy <= 2) : (dy*2/dx <= 2)) ) { - // steep - if ( px == py ) { - p[0] = TQPoint(x1+xi ,y1+yi+py); - p[1] = TQPoint(x2+xi-px,y2+yi ); - p[2] = TQPoint(x2+xi ,y2+yi-py); - p[3] = TQPoint(x1+xi+px,y1+yi ); - } else { - p[0] = TQPoint(x1+xi+px,y1+yi ); - p[1] = TQPoint(x2+xi ,y2+yi-py); - p[2] = TQPoint(x2+xi-px,y2+yi ); - p[3] = TQPoint(x1+xi ,y1+yi+py); - } - } else if ( dx > dy ) { - // horizontal - p[0] = TQPoint(x1+xi+px,y1+yi+py); - p[1] = TQPoint(x2+xi-px,y2+yi+py); - p[2] = TQPoint(x2+xi-px,y2+yi-py); - p[3] = TQPoint(x1+xi+px,y1+yi-py); - } else { - // vertical - p[0] = TQPoint(x1+xi+px,y1+yi+py); - p[1] = TQPoint(x2+xi+px,y2+yi-py); - p[2] = TQPoint(x2+xi-px,y2+yi-py); - p[3] = TQPoint(x1+xi-px,y1+yi+py); - } - return p; -} - -/*! - \reimp - -*/ - -void TQCanvasLine::moveBy(double dx, double dy) -{ - TQCanvasPolygonalItem::moveBy(dx, dy); -} - -/*! - \class TQCanvasRectangle ntqcanvas.h - \brief The TQCanvasRectangle class provides a rectangle on a TQCanvas. -\if defined(commercial) - It is part of the TQt Enterprise Edition. -\endif - - \module canvas - \ingroup graphics - \ingroup images - - This item paints a single rectangle which may have any pen() and - brush(), but may not be tilted/rotated. For rotated rectangles, - use TQCanvasPolygon. - - The rectangle's size and initial position can be set in the - constructor. The size can be set or changed later using setSize(). - Use height() and width() to retrieve the rectangle's dimensions. - - The rectangle can be drawn on a painter with drawShape(). - - Like any other canvas item rectangles can be moved with - TQCanvasItem::move() and TQCanvasItem::moveBy(), or by setting - coordinates with TQCanvasItem::setX(), TQCanvasItem::setY() and - TQCanvasItem::setZ(). - -*/ - -/*! - Constructs a rectangle at position (0,0) with both width and - height set to 32 pixels on \a canvas. -*/ -TQCanvasRectangle::TQCanvasRectangle(TQCanvas* canvas) : - TQCanvasPolygonalItem(canvas), - w(32), h(32) -{ -} - -/*! - Constructs a rectangle positioned and sized by \a r on \a canvas. -*/ -TQCanvasRectangle::TQCanvasRectangle(const TQRect& r, TQCanvas* canvas) : - TQCanvasPolygonalItem(canvas), - w(r.width()), h(r.height()) -{ - move(r.x(),r.y()); -} - -/*! - Constructs a rectangle at position (\a x, \a y) and size \a width - by \a height, on \a canvas. -*/ -TQCanvasRectangle::TQCanvasRectangle(int x, int y, int width, int height, - TQCanvas* canvas) : - TQCanvasPolygonalItem(canvas), - w(width), h(height) -{ - move(x,y); -} - -/*! - Destroys the rectangle. -*/ -TQCanvasRectangle::~TQCanvasRectangle() -{ - hide(); -} - - -/*! - Returns the width of the rectangle. -*/ -int TQCanvasRectangle::width() const -{ - return w; -} - -/*! - Returns the height of the rectangle. -*/ -int TQCanvasRectangle::height() const -{ - return h; -} - -/*! - Sets the \a width and \a height of the rectangle. -*/ -void TQCanvasRectangle::setSize(int width, int height) -{ - if ( w != width || h != height ) { - removeFromChunks(); - w = width; - h = height; - addToChunks(); - } -} - -/*! - \fn TQSize TQCanvasRectangle::size() const - - Returns the width() and height() of the rectangle. - - \sa rect(), setSize() -*/ - -/*! - \fn TQRect TQCanvasRectangle::rect() const - - Returns the integer-converted x(), y() position and size() of the - rectangle as a TQRect. -*/ - -/*! - \reimp -*/ -TQPointArray TQCanvasRectangle::areaPoints() const -{ - TQPointArray pa(4); - int pw = (pen().width()+1)/2; - if ( pw < 1 ) pw = 1; - if ( pen() == NoPen ) pw = 0; - pa[0] = TQPoint((int)x()-pw,(int)y()-pw); - pa[1] = pa[0] + TQPoint(w+pw*2,0); - pa[2] = pa[1] + TQPoint(0,h+pw*2); - pa[3] = pa[0] + TQPoint(0,h+pw*2); - return pa; -} - -/*! - Draws the rectangle on painter \a p. -*/ -void TQCanvasRectangle::drawShape(TQPainter & p) -{ - p.drawRect((int)x(), (int)y(), w, h); -} - - -/*! - \class TQCanvasEllipse ntqcanvas.h - \brief The TQCanvasEllipse class provides an ellipse or ellipse segment on a TQCanvas. -\if defined(commercial) - It is part of the TQt Enterprise Edition. -\endif - - \module canvas - \ingroup graphics - \ingroup images - - A canvas item that paints an ellipse or ellipse segment with a TQBrush. - The ellipse's height, width, start angle and angle length can be set - at construction time. The size can be changed at runtime with - setSize(), and the angles can be changed (if you're displaying an - ellipse segment rather than a whole ellipse) with setAngles(). - - Note that angles are specified in 16ths of a degree. - - \target anglediagram - \img qcanvasellipse.png Ellipse - - If a start angle and length angle are set then an ellipse segment - will be drawn. The start angle is the angle that goes from zero in a - counter-clockwise direction (shown in green in the diagram). The - length angle is the angle from the start angle in a - counter-clockwise direction (shown in blue in the diagram). The blue - segment is the segment of the ellipse that would be drawn. If no - start angle and length angle are specified the entire ellipse is - drawn. - - The ellipse can be drawn on a painter with drawShape(). - - Like any other canvas item ellipses can be moved with move() and - moveBy(), or by setting coordinates with setX(), setY() and setZ(). - - Note: TQCanvasEllipse does not use the pen. -*/ - -/*! - Constructs a 32x32 ellipse, centered at (0, 0) on \a canvas. -*/ -TQCanvasEllipse::TQCanvasEllipse(TQCanvas* canvas) : - TQCanvasPolygonalItem(canvas), - w(32), h(32), - a1(0), a2(360*16) -{ -} - -/*! - Constructs a \a width by \a height pixel ellipse, centered at - (0, 0) on \a canvas. -*/ -TQCanvasEllipse::TQCanvasEllipse(int width, int height, TQCanvas* canvas) : - TQCanvasPolygonalItem(canvas), - w(width),h(height), - a1(0),a2(360*16) -{ -} - -// ### add a constructor taking degrees in float. 1/16 degrees is stupid. Lars -// ### it's how TQPainter does it, so TQCanvas does too for consistency. If it's -// ### a good idea, it should be added to TQPainter, not just to TQCanvas. Warwick -/*! - Constructs a \a width by \a height pixel ellipse, centered at - (0, 0) on \a canvas. Only a segment of the ellipse is drawn, - starting at angle \a startangle, and extending for angle \a angle - (the angle length). - - Note that angles are specified in - 1/16ths of a degree. -*/ -TQCanvasEllipse::TQCanvasEllipse(int width, int height, - int startangle, int angle, TQCanvas* canvas) : - TQCanvasPolygonalItem(canvas), - w(width),h(height), - a1(startangle),a2(angle) -{ -} - -/*! - Destroys the ellipse. -*/ -TQCanvasEllipse::~TQCanvasEllipse() -{ - hide(); -} - -/*! - Returns the width of the ellipse. -*/ -int TQCanvasEllipse::width() const -{ - return w; -} - -/*! - Returns the height of the ellipse. -*/ -int TQCanvasEllipse::height() const -{ - return h; -} - -/*! - Sets the \a width and \a height of the ellipse. -*/ -void TQCanvasEllipse::setSize(int width, int height) -{ - if ( w != width || h != height ) { - removeFromChunks(); - w = width; - h = height; - addToChunks(); - } -} - -/*! - \fn int TQCanvasEllipse::angleStart() const - - Returns the start angle in 16ths of a degree. Initially - this will be 0. - - \sa setAngles(), angleLength() -*/ - -/*! - \fn int TQCanvasEllipse::angleLength() const - - Returns the length angle (the extent of the ellipse segment) in - 16ths of a degree. Initially this will be 360 * 16 (a complete - ellipse). - - \sa setAngles(), angleStart() -*/ - -/*! - Sets the angles for the ellipse. The start angle is \a start and - the extent of the segment is \a length (the angle length) from the - \a start. The angles are specified in 16ths of a degree. By - default the ellipse will start at 0 and have an angle length of - 360 * 16 (a complete ellipse). - - \sa angleStart(), angleLength() -*/ -void TQCanvasEllipse::setAngles(int start, int length) -{ - if ( a1 != start || a2 != length ) { - removeFromChunks(); - a1 = start; - a2 = length; - addToChunks(); - } -} - -/*! - \reimp -*/ -TQPointArray TQCanvasEllipse::areaPoints() const -{ - TQPointArray r; - // makeArc at 0,0, then translate so that fixed point math doesn't overflow - r.makeArc(int(x()-w/2.0+0.5)-1, int(y()-h/2.0+0.5)-1, w+3, h+3, a1, a2); - r.resize(r.size()+1); - r.setPoint(r.size()-1,int(x()),int(y())); - return r; -} - -// ### support outlines! Lars -// ### TQRegion doesn't, so we cannot (try it). Warwick -/*! - Draws the ellipse, centered at x(), y() using the painter \a p. - - Note that TQCanvasEllipse does not support an outline (the pen is - always NoPen). -*/ -void TQCanvasEllipse::drawShape(TQPainter & p) -{ - p.setPen(NoPen); // since TQRegion(TQPointArray) excludes outline :-( )-: - if ( !a1 && a2 == 360*16 ) { - p.drawEllipse(int(x()-w/2.0+0.5), int(y()-h/2.0+0.5), w, h); - } else { - p.drawPie(int(x()-w/2.0+0.5), int(y()-h/2.0+0.5), w, h, a1, a2); - } -} - - -/*! - \class TQCanvasText ntqcanvas.h - \brief The TQCanvasText class provides a text object on a TQCanvas. -\if defined(commercial) - It is part of the TQt Enterprise Edition. -\endif - - \module canvas - \ingroup graphics - \ingroup images - - A canvas text item has text with font, color and alignment - attributes. The text and font can be set in the constructor or set - or changed later with setText() and setFont(). The color is set - with setColor() and the alignment with setTextFlags(). The text - item's bounding rectangle is retrieved with boundingRect(). - - The text can be drawn on a painter with draw(). - - Like any other canvas item text items can be moved with - TQCanvasItem::move() and TQCanvasItem::moveBy(), or by setting - coordinates with TQCanvasItem::setX(), TQCanvasItem::setY() and - TQCanvasItem::setZ(). -*/ - -/*! - Constructs a TQCanvasText with the text "\", on \a canvas. -*/ -TQCanvasText::TQCanvasText(TQCanvas* canvas) : - TQCanvasItem(canvas), - txt(""), flags(0) -{ - setRect(); -} - -// ### add textflags to the constructor? Lars -/*! - Constructs a TQCanvasText with the text \a t, on canvas \a canvas. -*/ -TQCanvasText::TQCanvasText(const TQString& t, TQCanvas* canvas) : - TQCanvasItem(canvas), - txt(t), flags(0) -{ - setRect(); -} - -// ### see above -/*! - Constructs a TQCanvasText with the text \a t and font \a f, on the - canvas \a canvas. -*/ -TQCanvasText::TQCanvasText(const TQString& t, TQFont f, TQCanvas* canvas) : - TQCanvasItem(canvas), - txt(t), flags(0), - fnt(f) -{ - setRect(); -} - -/*! - Destroys the canvas text item. -*/ -TQCanvasText::~TQCanvasText() -{ - removeFromChunks(); -} - -/*! - Returns the bounding rectangle of the text. -*/ -TQRect TQCanvasText::boundingRect() const { return brect; } - -void TQCanvasText::setRect() -{ - brect = TQFontMetrics(fnt).boundingRect(int(x()), int(y()), 0, 0, flags, txt); - brect.setWidth(brect.width()+1); -} - -/*! - \fn int TQCanvasText::textFlags() const - - Returns the currently set alignment flags. - - \sa setTextFlags() TQt::AlignmentFlags -*/ - - -/*! - Sets the alignment flags to \a f. These are a bitwise OR of the - flags available to TQPainter::drawText() -- see the - \l{TQt::AlignmentFlags}. - - \sa setFont() setColor() -*/ -void TQCanvasText::setTextFlags(int f) -{ - if ( flags != f ) { - removeFromChunks(); - flags = f; - setRect(); - addToChunks(); - } -} - -/*! - Returns the text item's text. - - \sa setText() -*/ -TQString TQCanvasText::text() const -{ - return txt; -} - - -/*! - Sets the text item's text to \a t. The text may contain newlines. - - \sa text(), setFont(), setColor() setTextFlags() -*/ -void TQCanvasText::setText( const TQString& t ) -{ - if ( txt != t ) { - removeFromChunks(); - txt = t; - setRect(); - addToChunks(); - } -} - -/*! - Returns the font in which the text is drawn. - - \sa setFont() -*/ -TQFont TQCanvasText::font() const -{ - return fnt; -} - -/*! - Sets the font in which the text is drawn to font \a f. - - \sa font() -*/ -void TQCanvasText::setFont( const TQFont& f ) -{ - if ( f != fnt ) { - removeFromChunks(); - fnt = f; - setRect(); - addToChunks(); - } -} - -/*! - Returns the color of the text. - - \sa setColor() -*/ -TQColor TQCanvasText::color() const -{ - return col; -} - -/*! - Sets the color of the text to the color \a c. - - \sa color(), setFont() -*/ -void TQCanvasText::setColor(const TQColor& c) -{ - col=c; - changeChunks(); -} - - -/*! - \reimp -*/ -void TQCanvasText::moveBy(double dx, double dy) -{ - int idx = int(x()+dx)-int(x()); - int idy = int(y()+dy)-int(y()); - if ( idx || idy ) { - removeFromChunks(); - } - myx+=dx; - myy+=dy; - if ( idx || idy ) { - brect.moveBy(idx,idy); - addToChunks(); - } -} - -/*! - Draws the text using the painter \a painter. -*/ -void TQCanvasText::draw(TQPainter& painter) -{ - painter.setFont(fnt); - painter.setPen(col); - painter.drawText(brect, flags, txt); -} - -/*! - \reimp -*/ -void TQCanvasText::changeChunks() -{ - if (isVisible() && canvas()) { - int chunksize=canvas()->chunkSize(); - for (int j=brect.top()/chunksize; j<=brect.bottom()/chunksize; j++) { - for (int i=brect.left()/chunksize; i<=brect.right()/chunksize; i++) { - canvas()->setChangedChunk(i,j); - } - } - } -} - -/*! - Adds the text item to the appropriate chunks. -*/ -void TQCanvasText::addToChunks() -{ - if (isVisible() && canvas()) { - int chunksize=canvas()->chunkSize(); - for (int j=brect.top()/chunksize; j<=brect.bottom()/chunksize; j++) { - for (int i=brect.left()/chunksize; i<=brect.right()/chunksize; i++) { - canvas()->addItemToChunk(this,i,j); - } - } - } -} - -/*! - Removes the text item from the appropriate chunks. -*/ -void TQCanvasText::removeFromChunks() -{ - if (isVisible() && canvas()) { - int chunksize=canvas()->chunkSize(); - for (int j=brect.top()/chunksize; j<=brect.bottom()/chunksize; j++) { - for (int i=brect.left()/chunksize; i<=brect.right()/chunksize; i++) { - canvas()->removeItemFromChunk(this,i,j); - } - } - } -} - - -/*! - Returns 0 (TQCanvasItem::Rtti_Item). - - Make your derived classes return their own values for rtti(), so - that you can distinguish between objects returned by - TQCanvas::at(). You should use values greater than 1000 to allow - for extensions to this class. - - Overuse of this functionality can damage it's extensibility. For - example, once you have identified a base class of a TQCanvasItem - found by TQCanvas::at(), cast it to that type and call meaningful - methods rather than acting upon the object based on its rtti - value. - - For example: - - \code - TQCanvasItem* item; - // Find an item, e.g. with TQCanvasItem::collisions(). - ... - if (item->rtti() == MySprite::RTTI ) { - MySprite* s = (MySprite*)item; - if (s->isDamagable()) s->loseHitPoints(1000); - if (s->isHot()) myself->loseHitPoints(1000); - ... - } - \endcode -*/ -int TQCanvasItem::rtti() const { return RTTI; } -int TQCanvasItem::RTTI = Rtti_Item; - -/*! - Returns 1 (TQCanvasItem::Rtti_Sprite). - - \sa TQCanvasItem::rtti() -*/ -int TQCanvasSprite::rtti() const { return RTTI; } -int TQCanvasSprite::RTTI = Rtti_Sprite; - -/*! - Returns 2 (TQCanvasItem::Rtti_PolygonalItem). - - \sa TQCanvasItem::rtti() -*/ -int TQCanvasPolygonalItem::rtti() const { return RTTI; } -int TQCanvasPolygonalItem::RTTI = Rtti_PolygonalItem; - -/*! - Returns 3 (TQCanvasItem::Rtti_Text). - - \sa TQCanvasItem::rtti() -*/ -int TQCanvasText::rtti() const { return RTTI; } -int TQCanvasText::RTTI = Rtti_Text; - -/*! - Returns 4 (TQCanvasItem::Rtti_Polygon). - - \sa TQCanvasItem::rtti() -*/ -int TQCanvasPolygon::rtti() const { return RTTI; } -int TQCanvasPolygon::RTTI = Rtti_Polygon; - -/*! - Returns 5 (TQCanvasItem::Rtti_Rectangle). - - \sa TQCanvasItem::rtti() -*/ -int TQCanvasRectangle::rtti() const { return RTTI; } -int TQCanvasRectangle::RTTI = Rtti_Rectangle; - -/*! - Returns 6 (TQCanvasItem::Rtti_Ellipse). - - \sa TQCanvasItem::rtti() -*/ -int TQCanvasEllipse::rtti() const { return RTTI; } -int TQCanvasEllipse::RTTI = Rtti_Ellipse; - -/*! - Returns 7 (TQCanvasItem::Rtti_Line). - - \sa TQCanvasItem::rtti() -*/ -int TQCanvasLine::rtti() const { return RTTI; } -int TQCanvasLine::RTTI = Rtti_Line; - -/*! - Returns 8 (TQCanvasItem::Rtti_Spline). - - \sa TQCanvasItem::rtti() -*/ -int TQCanvasSpline::rtti() const { return RTTI; } -int TQCanvasSpline::RTTI = Rtti_Spline; - -/*! - Constructs a TQCanvasSprite which uses images from the - TQCanvasPixmapArray \a a. - - The sprite in initially positioned at (0, 0) on \a canvas, using - frame 0. -*/ -TQCanvasSprite::TQCanvasSprite(TQCanvasPixmapArray* a, TQCanvas* canvas) : - TQCanvasItem(canvas), - frm(0), - anim_val(0), - anim_state(0), - anim_type(0), - images(a) -{ -} - - -/*! - Set the array of images used for displaying the sprite to the - TQCanvasPixmapArray \a a. - - If the current frame() is larger than the number of images in \a - a, the current frame will be reset to 0. -*/ -void TQCanvasSprite::setSequence(TQCanvasPixmapArray* a) -{ - bool isvisible = isVisible(); - if ( isvisible && images ) - hide(); - images = a; - if ( frm >= (int)images->count() ) - frm = 0; - if ( isvisible ) - show(); -} - -/*! -\internal - -Marks any chunks the sprite touches as changed. -*/ -void TQCanvasSprite::changeChunks() -{ - if (isVisible() && canvas()) { - int chunksize=canvas()->chunkSize(); - for (int j=topEdge()/chunksize; j<=bottomEdge()/chunksize; j++) { - for (int i=leftEdge()/chunksize; i<=rightEdge()/chunksize; i++) { - canvas()->setChangedChunk(i,j); - } - } - } -} - -/*! - Destroys the sprite and removes it from the canvas. Does \e not - delete the images. -*/ -TQCanvasSprite::~TQCanvasSprite() -{ - removeFromChunks(); -} - -/*! - Sets the animation frame used for displaying the sprite to \a f, - an index into the TQCanvasSprite's TQCanvasPixmapArray. The call - will be ignored if \a f is larger than frameCount() or smaller - than 0. - - \sa frame() move() -*/ -void TQCanvasSprite::setFrame(int f) -{ - move(x(),y(),f); -} - -/*! - \enum TQCanvasSprite::FrameAnimationType - - This enum is used to identify the different types of frame - animation offered by TQCanvasSprite. - - \value Cycle at each advance the frame number will be incremented by - 1 (modulo the frame count). - \value Oscillate at each advance the frame number will be - incremented by 1 up to the frame count then decremented to by 1 to - 0, repeating this sequence forever. -*/ - -/*! - Sets the animation characteristics for the sprite. - - For \a type == \c Cycle, the frames will increase by \a step - at each advance, modulo the frameCount(). - - For \a type == \c Oscillate, the frames will increase by \a step - at each advance, up to the frameCount(), then decrease by \a step - back to 0, repeating forever. - - The \a state parameter is for internal use. -*/ -void TQCanvasSprite::setFrameAnimation(FrameAnimationType type, int step, int state) -{ - anim_val = step; - anim_type = type; - anim_state = state; - setAnimated(TRUE); -} - -/*! - Extends the default TQCanvasItem implementation to provide the - functionality of setFrameAnimation(). - - The \a phase is 0 or 1: see TQCanvasItem::advance() for details. - - \sa TQCanvasItem::advance() setVelocity() -*/ -void TQCanvasSprite::advance(int phase) -{ - if ( phase==1 ) { - int nf = frame(); - if ( anim_type == Oscillate ) { - if ( anim_state ) - nf += anim_val; - else - nf -= anim_val; - if ( nf < 0 ) { - nf = abs(anim_val); - anim_state = !anim_state; - } else if ( nf >= frameCount() ) { - nf = frameCount()-1-abs(anim_val); - anim_state = !anim_state; - } - } else { - nf = (nf + anim_val + frameCount()) % frameCount(); - } - move(x()+xVelocity(),y()+yVelocity(),nf); - } -} - - -/*! - \fn int TQCanvasSprite::frame() const - - Returns the index of the current animation frame in the - TQCanvasSprite's TQCanvasPixmapArray. - - \sa setFrame(), move() -*/ - -/*! - \fn int TQCanvasSprite::frameCount() const - - Returns the number of frames in the TQCanvasSprite's - TQCanvasPixmapArray. -*/ - - -/*! - \reimp - \internal - Moves the sprite to the position \a x, \a y. - Keep it visible. -*/ -void TQCanvasSprite::move(double x, double y) { TQCanvasItem::move(x,y); } - -/*! - \fn void TQCanvasSprite::move(double nx, double ny, int nf) - - Set the position of the sprite to \a nx, \a ny and the current - frame to \a nf. \a nf will be ignored if it is larger than - frameCount() or smaller than 0. -*/ -void TQCanvasSprite::move(double nx, double ny, int nf) -{ - if (isVisible() && canvas()) { - hide(); - TQCanvasItem::move(nx,ny); - if ( nf >= 0 && nf < frameCount() ) - frm=nf; - show(); - } else { - TQCanvasItem::move(nx,ny); - if ( nf >= 0 && nf < frameCount() ) - frm=nf; - } -} - -class TQCanvasPolygonScanner : public TQPolygonScanner { - TQPolygonalProcessor& processor; -public: - TQCanvasPolygonScanner(TQPolygonalProcessor& p) : - processor(p) - { - } - void processSpans( int n, TQPoint* point, int* width ) - { - processor.doSpans(n,point,width); - } -}; - -void TQCanvasPolygonalItem::scanPolygon(const TQPointArray& pa, int winding, TQPolygonalProcessor& process) const -{ - TQCanvasPolygonScanner scanner(process); - scanner.scan(pa,winding); -} - - -#endif // TQT_NO_CANVAS diff --git a/src/canvas/qt_canvas.pri b/src/canvas/qt_canvas.pri index e0f295b4a..0cd9c4423 100644 --- a/src/canvas/qt_canvas.pri +++ b/src/canvas/qt_canvas.pri @@ -1,6 +1,6 @@ # TQt canvas module canvas { - HEADERS += $$CANVAS_H/ntqcanvas.h - SOURCES += $$CANVAS_CPP/qcanvas.cpp + HEADERS += $$CANVAS_H/tqcanvas.h + SOURCES += $$CANVAS_CPP/tqcanvas.cpp } diff --git a/src/canvas/tqcanvas.cpp b/src/canvas/tqcanvas.cpp new file mode 100644 index 000000000..cd03790a4 --- /dev/null +++ b/src/canvas/tqcanvas.cpp @@ -0,0 +1,5415 @@ +/********************************************************************** +** +** Implementation of TQCanvas and associated classes +** +** Created : 991211 +** +** Copyright (C) 1999-2008 Trolltech ASA. All rights reserved. +** +** This file is part of the canvas module of the TQt GUI Toolkit. +** +** This file may be used under the terms of the GNU General +** Public License versions 2.0 or 3.0 as published by the Free +** Software Foundation and appearing in the files LICENSE.GPL2 +** and LICENSE.GPL3 included in the packaging of this file. +** Alternatively you may (at your option) use any later version +** of the GNU General Public License if such license has been +** publicly approved by Trolltech ASA (or its successors, if any) +** and the KDE Free TQt Foundation. +** +** Please review the following information to ensure GNU General +** Public Licensing requirements will be met: +** http://trolltech.com/products/qt/licenses/licensing/opensource/. +** If you are unsure which license is appropriate for your use, please +** review the following information: +** http://trolltech.com/products/qt/licenses/licensing/licensingoverview +** or contact the sales department at sales@trolltech.com. +** +** This file may be used under the terms of the Q Public License as +** defined by Trolltech ASA and appearing in the file LICENSE.TQPL +** included in the packaging of this file. Licensees holding valid TQt +** Commercial licenses may use this file in accordance with the TQt +** Commercial License Agreement provided with the Software. +** +** This file is provided "AS IS" with NO WARRANTY OF ANY KIND, +** INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE. Trolltech reserves all rights not granted +** herein. +** +**********************************************************************/ + +#include "tqcanvas.h" +#ifndef TQT_NO_CANVAS +#include "ntqapplication.h" +#include "ntqbitmap.h" +#include "ntqimage.h" +#include "ntqptrdict.h" +#include "ntqpainter.h" +#include "ntqpolygonscanner.h" +#include "ntqtimer.h" +#include "ntqtl.h" + +#include + +class TQCanvasData { +public: + TQCanvasData() : + itemDict(1013), animDict(503) + { + } + + TQPtrList viewList; + TQPtrDict itemDict; + TQPtrDict animDict; +}; + +class TQCanvasViewData { +public: + TQCanvasViewData() : repaint_from_moving( FALSE ) {} +#ifndef TQT_NO_TRANSFORMATIONS + TQWMatrix xform; + TQWMatrix ixform; +#endif + bool repaint_from_moving; +}; + +// clusterizer + +class TQCanvasClusterizer { +public: + TQCanvasClusterizer(int maxclusters); + ~TQCanvasClusterizer(); + + void add(int x, int y); // 1x1 rectangle (point) + void add(int x, int y, int w, int h); + void add(const TQRect& rect); + + void clear(); + int clusters() { return count; } + const TQRect& operator[](int i); + +private: + TQRect* cluster; + int count; + const int maxcl; +}; + +static +void include(TQRect& r, const TQRect& rect) +{ + if (rect.left()r.right()) { + r.setRight(rect.right()); + } + if (rect.top()r.bottom()) { + r.setBottom(rect.bottom()); + } +} + +/* +A TQCanvasClusterizer groups rectangles (TQRects) into non-overlapping rectangles +by a merging heuristic. +*/ +TQCanvasClusterizer::TQCanvasClusterizer(int maxclusters) : + cluster(new TQRect[maxclusters]), + count(0), + maxcl(maxclusters) +{ } + +TQCanvasClusterizer::~TQCanvasClusterizer() +{ + delete [] cluster; +} + +void TQCanvasClusterizer::clear() +{ + count=0; +} + +void TQCanvasClusterizer::add(int x, int y) +{ + add(TQRect(x,y,1,1)); +} + +void TQCanvasClusterizer::add(int x, int y, int w, int h) +{ + add(TQRect(x,y,w,h)); +} + +void TQCanvasClusterizer::add(const TQRect& rect) +{ + TQRect biggerrect(rect.x()-1,rect.y()-1,rect.width()+2,rect.height()+2); + + //assert(rect.width()>0 && rect.height()>0); + + int cursor; + + for (cursor=0; cursor=0) { + include(cluster[cheapest],rect); + return; + } + + if (count < maxcl) { + cluster[count++]=rect; + return; + } + + // Do cheapest of: + // add to closest cluster + // do cheapest cluster merge, add to new cluster + + lowestcost=9999999; + cheapest=-1; + cursor=0; + while( cursor=0) { + include(cluster[cheapestmerge1],cluster[cheapestmerge2]); + cluster[cheapestmerge2]=cluster[count--]; + } else { + // if (!cheapest) debugRectangles(rect); + include(cluster[cheapest],rect); + } + + // NB: clusters do not intersect (or intersection will + // overwrite). This is a result of the above algorithm, + // given the assumption that (x,y) are ordered topleft + // to bottomright. + + // ### + // + // add explicit x/y ordering to that comment, move it to the top + // and rephrase it as pre-/post-conditions. +} + +const TQRect& TQCanvasClusterizer::operator[](int i) +{ + return cluster[i]; +} + +// end of clusterizer + + + +class TQM_EXPORT_CANVAS TQCanvasItemPtr { +public: + TQCanvasItemPtr() : ptr(0) { } + TQCanvasItemPtr( TQCanvasItem* p ) : ptr(p) { } + + bool operator<=(const TQCanvasItemPtr& that) const + { + // Order same-z objects by identity. + if (that.ptr->z()==ptr->z()) + return that.ptr <= ptr; + return that.ptr->z() <= ptr->z(); + } + bool operator<(const TQCanvasItemPtr& that) const + { + // Order same-z objects by identity. + if (that.ptr->z()==ptr->z()) + return that.ptr < ptr; + return that.ptr->z() < ptr->z(); + } + bool operator>(const TQCanvasItemPtr& that) const + { + // Order same-z objects by identity. + if (that.ptr->z()==ptr->z()) + return that.ptr > ptr; + return that.ptr->z() > ptr->z(); + } + bool operator==(const TQCanvasItemPtr& that) const + { + return that.ptr == ptr; + } + operator TQCanvasItem*() const { return ptr; } + +private: + TQCanvasItem* ptr; +}; + + +/*! + \class TQCanvasItemList + \brief The TQCanvasItemList class is a list of TQCanvasItems. +\if defined(commercial) + It is part of the TQt Enterprise Edition. +\endif + + \module canvas + \ingroup graphics + \ingroup images + + TQCanvasItemList is a TQValueList of pointers to \l{TQCanvasItem}s. + This class is used by some methods in TQCanvas that need to return + a list of canvas items. + + The \l TQValueList documentation describes how to use this list. +*/ + +/*! + \internal +*/ +void TQCanvasItemList::sort() +{ + qHeapSort(*((TQValueList*)this)); +} + +/*! + \internal +*/ +void TQCanvasItemList::drawUnique( TQPainter& painter ) +{ + TQCanvasItem* prev=0; + for (Iterator it=fromLast(); it!=end(); --it) { + TQCanvasItem *g=*it; + if (g!=prev) { + g->draw(painter); + prev=g; + } + } +} + +/*! + Returns the concatenation of this list and list \a l. +*/ +TQCanvasItemList TQCanvasItemList::operator+(const TQCanvasItemList &l) const +{ + TQCanvasItemList l2(*this); + for(const_iterator it = l.begin(); it != l.end(); ++it) + l2.append(*it); + return l2; +} + +class TQCanvasChunk { +public: + TQCanvasChunk() : changed(TRUE) { } + // Other code assumes lists are not deleted. Assignment is also + // done on ChunkRecs. So don't add that sort of thing here. + + void sort() + { + list.sort(); + } + + const TQCanvasItemList* listPtr() const + { + return &list; + } + + void add(TQCanvasItem* item) + { + list.prepend(item); + changed = TRUE; + } + + void remove(TQCanvasItem* item) + { + list.remove(item); + changed = TRUE; + } + + void change() + { + changed = TRUE; + } + + bool hasChanged() const + { + return changed; + } + + bool takeChange() + { + bool y = changed; + changed = FALSE; + return y; + } + +private: + TQCanvasItemList list; + bool changed; +}; + + +static int gcd(int a, int b) +{ + int r; + while ( (r = a%b) ) { + a=b; + b=r; + } + return b; +} + +static int scm(int a, int b) +{ + int g = gcd(a,b); + return a/g*b; +} + + + +/*! + \class TQCanvas tqcanvas.h + \brief The TQCanvas class provides a 2D area that can contain TQCanvasItem objects. +\if defined(commercial) + It is part of the TQt Enterprise Edition. +\endif + + \ingroup abstractwidgets + \ingroup graphics + \ingroup images + \mainclass + \module canvas + + The TQCanvas class manages its 2D graphic area and all the canvas + items the area contains. The canvas has no visual appearance of + its own. Instead, it is displayed on screen using a TQCanvasView. + Multiple TQCanvasView widgets may be associated with a canvas to + provide multiple views of the same canvas. + + The canvas is optimized for large numbers of items, particularly + where only a small percentage of the items change at any + one time. If the entire display changes very frequently, you should + consider using your own custom TQScrollView subclass. + + TQt provides a rich + set of canvas item classes, e.g. TQCanvasEllipse, TQCanvasLine, + TQCanvasPolygon, TQCanvasPolygonalItem, TQCanvasRectangle, TQCanvasSpline, + TQCanvasSprite and TQCanvasText. You can subclass to create your own + canvas items; TQCanvasPolygonalItem is the most common base class used + for this purpose. + + Items appear on the canvas after their \link TQCanvasItem::show() + show()\endlink function has been called (or \link + TQCanvasItem::setVisible() setVisible(TRUE)\endlink), and \e after + update() has been called. The canvas only shows items that are + \link TQCanvasItem::setVisible() visible\endlink, and then only if + \l update() is called. (By default the canvas is white and so are + canvas items, so if nothing appears try changing colors.) + + If you created the canvas without passing a width and height to + the constructor you must also call resize(). + + Although a canvas may appear to be similar to a widget with child + widgets, there are several notable differences: + + \list + \i Canvas items are usually much faster to manipulate and redraw than + child widgets, with the speed advantage becoming especially great when + there are \e many canvas items and non-rectangular items. In most + situations canvas items are also a lot more memory efficient than child + widgets. + + \i It's easy to detect overlapping items (collision detection). + + \i The canvas can be larger than a widget. A million-by-million canvas + is perfectly possible. At such a size a widget might be very + inefficient, and some window systems might not support it at all, + whereas TQCanvas scales well. Even with a billion pixels and a million + items, finding a particular canvas item, detecting collisions, etc., + is still fast (though the memory consumption may be prohibitive + at such extremes). + + \i Two or more TQCanvasView objects can view the same canvas. + + \i An arbitrary transformation matrix can be set on each TQCanvasView + which makes it easy to zoom, rotate or shear the viewed canvas. + + \i Widgets provide a lot more functionality, such as input (TQKeyEvent, + TQMouseEvent etc.) and layout management (TQGridLayout etc.). + + \endlist + + A canvas consists of a background, a number of canvas items organized by + x, y and z coordinates, and a foreground. A canvas item's z coordinate + can be treated as a layer number -- canvas items with a higher z + coordinate appear in front of canvas items with a lower z coordinate. + + The background is white by default, but can be set to a different color + using setBackgroundColor(), or to a repeated pixmap using + setBackgroundPixmap() or to a mosaic of smaller pixmaps using + setTiles(). Individual tiles can be set with setTile(). There + are corresponding get functions, e.g. backgroundColor() and + backgroundPixmap(). + + Note that TQCanvas does not inherit from TQWidget, even though it has some + functions which provide the same functionality as those in TQWidget. One + of these is setBackgroundPixmap(); some others are resize(), size(), + width() and height(). \l TQCanvasView is the widget used to display a + canvas on the screen. + + Canvas items are added to a canvas by constructing them and passing the + canvas to the canvas item's constructor. An item can be moved to a + different canvas using TQCanvasItem::setCanvas(). + + Canvas items are movable (and in the case of TQCanvasSprites, animated) + objects that inherit TQCanvasItem. Each canvas item has a position on the + canvas (x, y coordinates) and a height (z coordinate), all of which are + held as floating-point numbers. Moving canvas items also have x and y + velocities. It's possible for a canvas item to be outside the canvas + (for example TQCanvasItem::x() is greater than width()). When a canvas + item is off the canvas, onCanvas() returns FALSE and the canvas + disregards the item. (Canvas items off the canvas do not slow down any + of the common operations on the canvas.) + + Canvas items can be moved with TQCanvasItem::move(). The advance() + function moves all TQCanvasItem::animated() canvas items and + setAdvancePeriod() makes TQCanvas move them automatically on a periodic + basis. In the context of the TQCanvas classes, to `animate' a canvas item + is to set it in motion, i.e. using TQCanvasItem::setVelocity(). Animation + of a canvas item itself, i.e. items which change over time, is enabled + by calling TQCanvasSprite::setFrameAnimation(), or more generally by + subclassing and reimplementing TQCanvasItem::advance(). To detect collisions + use one of the TQCanvasItem::collisions() functions. + + The changed parts of the canvas are redrawn (if they are visible in a + canvas view) whenever update() is called. You can either call update() + manually after having changed the contents of the canvas, or force + periodic updates using setUpdatePeriod(). If you have moving objects on + the canvas, you must call advance() every time the objects should + move one step further. Periodic calls to advance() can be forced using + setAdvancePeriod(). The advance() function will call + TQCanvasItem::advance() on every item that is \link + TQCanvasItem::animated() animated\endlink and trigger an update of the + affected areas afterwards. (A canvas item that is `animated' is simply + a canvas item that is in motion.) + + TQCanvas organizes its canvas items into \e chunks; these are areas on + the canvas that are used to speed up most operations. Many operations + start by eliminating most chunks (i.e. those which haven't changed) + and then process only the canvas items that are in the few interesting + (i.e. changed) chunks. A valid chunk, validChunk(), is one which is on + the canvas. + + The chunk size is a key factor to TQCanvas's speed: if there are too many + chunks, the speed benefit of grouping canvas items into chunks is + reduced. If the chunks are too large, it takes too long to process each + one. The TQCanvas constructor tries to pick a suitable size, but you + can call retune() to change it at any time. The chunkSize() function + returns the current chunk size. The canvas items always make sure + they're in the right chunks; all you need to make sure of is that + the canvas uses the right chunk size. A good rule of thumb is that + the size should be a bit smaller than the average canvas item + size. If you have moving objects, the chunk size should be a bit + smaller than the average size of the moving items. + + The foreground is normally nothing, but if you reimplement + drawForeground(), you can draw things in front of all the canvas + items. + + Areas can be set as changed with setChanged() and set unchanged with + setUnchanged(). The entire canvas can be set as changed with + setAllChanged(). A list of all the items on the canvas is returned by + allItems(). + + An area can be copied (painted) to a TQPainter with drawArea(). + + If the canvas is resized it emits the resized() signal. + + The examples/canvas application and the 2D graphics page of the + examples/demo application demonstrate many of TQCanvas's facilities. + + \sa TQCanvasView TQCanvasItem +*/ +void TQCanvas::init(int w, int h, int chunksze, int mxclusters) +{ + d = new TQCanvasData; + awidth=w; + aheight=h; + chunksize=chunksze; + maxclusters=mxclusters; + chwidth=(w+chunksize-1)/chunksize; + chheight=(h+chunksize-1)/chunksize; + chunks=new TQCanvasChunk[chwidth*chheight]; + update_timer = 0; + bgcolor = white; + grid = 0; + htiles = 0; + vtiles = 0; + dblbuf = TRUE; + debug_redraw_areas = FALSE; +} + +/*! + Create a TQCanvas with no size. \a parent and \a name are passed to + the TQObject superclass. + + \warning You \e must call resize() at some time after creation to + be able to use the canvas. +*/ +TQCanvas::TQCanvas( TQObject* parent, const char* name ) + : TQObject( parent, name ) +{ + init(0,0); +} + +/*! + Constructs a TQCanvas that is \a w pixels wide and \a h pixels high. +*/ +TQCanvas::TQCanvas(int w, int h) +{ + init(w,h); +} + +/*! + Constructs a TQCanvas which will be composed of \a h tiles + horizontally and \a v tiles vertically. Each tile will be an image + \a tilewidth by \a tileheight pixels taken from pixmap \a p. + + The pixmap \a p is a list of tiles, arranged left to right, (and + in the case of pixmaps that have multiple rows of tiles, top to + bottom), with tile 0 in the top-left corner, tile 1 next to the + right, and so on, e.g. + + \table + \row \i 0 \i 1 \i 2 \i 3 + \row \i 4 \i 5 \i 6 \i 7 + \endtable + + The TQCanvas is initially sized to show exactly the given number of + tiles horizontally and vertically. If it is resized to be larger, + the entire matrix of tiles will be repeated as often as necessary + to cover the area. If it is smaller, tiles to the right and bottom + will not be visible. + + \sa setTiles() +*/ +TQCanvas::TQCanvas( TQPixmap p, + int h, int v, int tilewidth, int tileheight ) +{ + init(h*tilewidth, v*tileheight, scm(tilewidth,tileheight) ); + setTiles( p, h, v, tilewidth, tileheight ); +} + +void qt_unview(TQCanvas* c) +{ + for (TQCanvasView* view=c->d->viewList.first(); view != 0; view=c->d->viewList.next()) { + view->viewing = 0; + } +} + +/*! + Destroys the canvas and all the canvas's canvas items. +*/ +TQCanvas::~TQCanvas() +{ + qt_unview(this); + TQCanvasItemList all = allItems(); + for (TQCanvasItemList::Iterator it=all.begin(); it!=all.end(); ++it) + delete *it; + delete [] chunks; + delete [] grid; + delete d; +} + +/*! +\internal +Returns the chunk at a chunk position \a i, \a j. +*/ +TQCanvasChunk& TQCanvas::chunk(int i, int j) const +{ + return chunks[i+chwidth*j]; +} + +/*! +\internal +Returns the chunk at a pixel position \a x, \a y. +*/ +TQCanvasChunk& TQCanvas::chunkContaining(int x, int y) const +{ + return chunk(x/chunksize,y/chunksize); +} + +/*! + Returns a list of all the items in the canvas. +*/ +TQCanvasItemList TQCanvas::allItems() +{ + TQCanvasItemList list; + for (TQPtrDictIterator it=d->itemDict; it.currentKey(); ++it) { + list.prepend((TQCanvasItem*)it.currentKey()); + } + return list; +} + + +/*! + Changes the size of the canvas to have a width of \a w and a + height of \a h. This is a slow operation. +*/ +void TQCanvas::resize(int w, int h) +{ + if (awidth==w && aheight==h) + return; + + TQCanvasItem* item; + TQPtrList hidden; + for (TQPtrDictIterator it=d->itemDict; it.currentKey(); ++it) { + if (((TQCanvasItem*)it.currentKey())->isVisible()) { + ((TQCanvasItem*)it.currentKey())->hide(); + hidden.append(((TQCanvasItem*)it.currentKey())); + } + } + + int nchwidth=(w+chunksize-1)/chunksize; + int nchheight=(h+chunksize-1)/chunksize; + + TQCanvasChunk* newchunks = new TQCanvasChunk[nchwidth*nchheight]; + + // Commit the new values. + // + awidth=w; + aheight=h; + chwidth=nchwidth; + chheight=nchheight; + delete [] chunks; + chunks=newchunks; + + for (item=hidden.first(); item != 0; item=hidden.next()) { + item->show(); + } + + setAllChanged(); + + emit resized(); +} + +/*! + \fn void TQCanvas::resized() + + This signal is emitted whenever the canvas is resized. Each + TQCanvasView connects to this signal to keep the scrollview's size + correct. +*/ + +/*! + Change the efficiency tuning parameters to \a mxclusters clusters, + each of size \a chunksze. This is a slow operation if there are + many objects on the canvas. + + The canvas is divided into chunks which are rectangular areas \a + chunksze wide by \a chunksze high. Use a chunk size which is about + the average size of the canvas items. If you choose a chunk size + which is too small it will increase the amount of calculation + required when drawing since each change will affect many chunks. + If you choose a chunk size which is too large the amount of + drawing required will increase because for each change, a lot of + drawing will be required since there will be many (unchanged) + canvas items which are in the same chunk as the changed canvas + items. + + Internally, a canvas uses a low-resolution "chunk matrix" to keep + track of all the items in the canvas. A 64x64 chunk matrix is the + default for a 1024x1024 pixel canvas, where each chunk collects + canvas items in a 16x16 pixel square. This default is also + affected by setTiles(). You can tune this default using this + function. For example if you have a very large canvas and want to + trade off speed for memory then you might set the chunk size to 32 + or 64. + + The \a mxclusters argument is the number of rectangular groups of + chunks that will be separately drawn. If the canvas has a large + number of small, dispersed items, this should be about that + number. Our testing suggests that a large number of clusters is + almost always best. + +*/ +void TQCanvas::retune(int chunksze, int mxclusters) +{ + maxclusters=mxclusters; + + if ( chunksize!=chunksze ) { + TQPtrList hidden; + for (TQPtrDictIterator it=d->itemDict; it.currentKey(); ++it) { + if (((TQCanvasItem*)it.currentKey())->isVisible()) { + ((TQCanvasItem*)it.currentKey())->hide(); + hidden.append(((TQCanvasItem*)it.currentKey())); + } + } + + chunksize=chunksze; + + int nchwidth=(awidth+chunksize-1)/chunksize; + int nchheight=(aheight+chunksize-1)/chunksize; + + TQCanvasChunk* newchunks = new TQCanvasChunk[nchwidth*nchheight]; + + // Commit the new values. + // + chwidth=nchwidth; + chheight=nchheight; + delete [] chunks; + chunks=newchunks; + + for (TQCanvasItem* item=hidden.first(); item != 0; item=hidden.next()) { + item->show(); + } + } +} + +/*! + \fn int TQCanvas::width() const + + Returns the width of the canvas, in pixels. +*/ + +/*! + \fn int TQCanvas::height() const + + Returns the height of the canvas, in pixels. +*/ + +/*! + \fn TQSize TQCanvas::size() const + + Returns the size of the canvas, in pixels. +*/ + +/*! + \fn TQRect TQCanvas::rect() const + + Returns a rectangle the size of the canvas. +*/ + + +/*! + \fn bool TQCanvas::onCanvas( int x, int y ) const + + Returns TRUE if the pixel position (\a x, \a y) is on the canvas; + otherwise returns FALSE. + + \sa validChunk() +*/ + +/*! + \fn bool TQCanvas::onCanvas( const TQPoint& p ) const + \overload + + Returns TRUE if the pixel position \a p is on the canvas; + otherwise returns FALSE. + + \sa validChunk() +*/ + +/*! + \fn bool TQCanvas::validChunk( int x, int y ) const + + Returns TRUE if the chunk position (\a x, \a y) is on the canvas; + otherwise returns FALSE. + + \sa onCanvas() +*/ + +/*! + \fn bool TQCanvas::validChunk( const TQPoint& p ) const + \overload + + Returns TRUE if the chunk position \a p is on the canvas; otherwise + returns FALSE. + + \sa onCanvas() +*/ + +/*! + \fn int TQCanvas::chunkSize() const + + Returns the chunk size of the canvas. + + \sa retune() +*/ + +/*! +\fn bool TQCanvas::sameChunk(int x1, int y1, int x2, int y2) const +\internal +Tells if the points ( \a x1, \a y1 ) and ( \a x2, \a y2 ) are within the same chunk. +*/ + +/*! +\internal +This method adds an the item \a item to the list of TQCanvasItem objects +in the TQCanvas. The TQCanvasItem class calls this. +*/ +void TQCanvas::addItem(TQCanvasItem* item) +{ + d->itemDict.insert((void*)item,(void*)1); +} + +/*! +\internal +This method adds the item \a item to the list of TQCanvasItem objects +to be moved. The TQCanvasItem class calls this. +*/ +void TQCanvas::addAnimation(TQCanvasItem* item) +{ + d->animDict.insert((void*)item,(void*)1); +} + +/*! +\internal +This method adds the item \a item to the list of TQCanvasItem objects +which are no longer to be moved. The TQCanvasItem class calls this. +*/ +void TQCanvas::removeAnimation(TQCanvasItem* item) +{ + d->animDict.remove((void*)item); +} + +/*! +\internal +This method removes the item \a item from the list of TQCanvasItem objects +in this TQCanvas. The TQCanvasItem class calls this. +*/ +void TQCanvas::removeItem(TQCanvasItem* item) +{ + d->itemDict.remove((void*)item); +} + +/*! +\internal +This method adds the view \a view to the list of TQCanvasView objects +viewing this TQCanvas. The TQCanvasView class calls this. +*/ +void TQCanvas::addView(TQCanvasView* view) +{ + d->viewList.append(view); + if ( htiles>1 || vtiles>1 || pm.isNull() ) + view->viewport()->setBackgroundColor(backgroundColor()); +} + +/*! +\internal +This method removes the view \a view from the list of TQCanvasView objects +viewing this TQCanvas. The TQCanvasView class calls this. +*/ +void TQCanvas::removeView(TQCanvasView* 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 TQCanvas::setAdvancePeriod(int ms) +{ + if ( ms<0 ) { + if ( update_timer ) + update_timer->stop(); + } else { + if ( update_timer ) + delete update_timer; + update_timer = new TQTimer(this); + connect(update_timer,TQ_SIGNAL(timeout()),this,TQ_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 TQCanvas::setUpdatePeriod(int ms) +{ + if ( ms<0 ) { + if ( update_timer ) + update_timer->stop(); + } else { + if ( update_timer ) + delete update_timer; + update_timer = new TQTimer(this); + connect(update_timer,TQ_SIGNAL(timeout()),this,TQ_SLOT(update())); + update_timer->start(ms); + } +} + +/*! + Moves all TQCanvasItem::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 + TQCanvasItem::advance() function of each TQCanvasItem::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 TQCanvasItem subclasses supplied with TQt do anything + interesting in phase 0. + + The canvas can be configured to call this function periodically + with setAdvancePeriod(). + + \sa update() +*/ +void TQCanvas::advance() +{ + TQPtrDictIterator it=d->animDict; + while ( it.current() ) { + TQCanvasItem* i = (TQCanvasItem*)(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() ) { + TQCanvasItem* i = (TQCanvasItem*)(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 TQCanvas::drawViewArea( TQCanvasView* view, TQPainter* p, const TQRect& vr, bool dbuf ) +{ + TQPoint tl = view->contentsToViewport(TQPoint(0,0)); + +#ifndef TQT_NO_TRANSFORMATIONS + TQWMatrix wm = view->worldMatrix(); + TQWMatrix iwm = wm.invert(); + // ivr = covers all chunks in vr + TQRect ivr = iwm.map(vr); + ivr.addCoords(-1, -1, 1, 1); + TQWMatrix twm; + twm.translate(tl.x(),tl.y()); +#else + TQRect ivr = vr; +#endif + + TQRect all(0,0,width(),height()); + + if ( !all.contains(ivr) ) { + // Need to clip with edge of canvas. + +#ifndef TQT_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). + TQPointArray a; + if ( wm.m12()==0.0 && wm.m21()==0.0 && wm.m11() == 1.0 && wm.m22() == 1.0 ) + a = TQPointArray( TQRect(all.x(),all.y(),all.width()+1,all.height()+1) ); + else + a = TQPointArray( all ); + + a = (wm*twm).map(a); +#else + TQPointArray a( TQRect(all.x(),all.y(),all.width()+1,all.height()+1) ); +#endif + if ( view->viewport()->backgroundMode() == NoBackground ) { + TQRect cvr = vr; cvr.moveBy(tl.x(),tl.y()); + p->setClipRegion(TQRegion(cvr)-TQRegion(a)); + p->fillRect(vr,view->viewport()->palette() + .brush(TQPalette::Active,TQColorGroup::Background)); + } + p->setClipRegion(a); + } + + if ( dbuf ) { + offscr = TQPixmap(vr.size().expandedTo(TQSize(1, 1))); +#ifdef TQ_WS_X11 + offscr.x11SetScreen(p->device()->x11Screen()); +#endif + TQPainter dbp(&offscr); +#ifndef TQT_NO_TRANSFORMATIONS + twm.translate(-vr.x(),-vr.y()); + twm.translate(-tl.x(),-tl.y()); + dbp.setWorldMatrix( wm*twm, TRUE ); +#else + dbp.translate(-vr.x()-tl.x(),-vr.y()-tl.y()); +#endif + dbp.setClipRect(0,0,vr.width(), vr.height()); + drawCanvasArea(ivr,&dbp,FALSE); + dbp.end(); + p->drawPixmap(vr.x(), vr.y(), offscr, 0, 0, vr.width(), vr.height()); + } else { + TQRect r = vr; r.moveBy(tl.x(),tl.y()); // move to untransformed co-ords + if ( !all.contains(ivr) ) { + TQRegion inside = p->clipRegion() & r; + //TQRegion outside = p->clipRegion() - r; + //p->setClipRegion(outside); + //p->fillRect(outside.boundingRect(),red); + p->setClipRegion(inside); + } else { + p->setClipRect(r); + } +#ifndef TQT_NO_TRANSFORMATIONS + p->setWorldMatrix( wm*twm ); +#else +#endif + p->setBrushOrigin(tl.x(), tl.y()); + drawCanvasArea(ivr,p,FALSE); + } +} + +/*! + Repaints changed areas in all views of the canvas. + + \sa advance() +*/ +void TQCanvas::update() +{ + TQCanvasClusterizer clusterizer(d->viewList.count()); +#ifndef TQT_NO_TRANSFORMATIONS + TQPtrList doneareas; + doneareas.setAutoDelete(TRUE); +#endif + + TQPtrListIterator it(d->viewList); + TQCanvasView* view; + while( (view=it.current()) != 0 ) { + ++it; +#ifndef TQT_NO_TRANSFORMATIONS + TQWMatrix wm = view->worldMatrix(); +#endif + TQRect area(view->contentsX(),view->contentsY(), + view->visibleWidth(),view->visibleHeight()); + if (area.width()>0 && area.height()>0) { +#ifndef TQT_NO_TRANSFORMATIONS + if ( !wm.isIdentity() ) { + // r = Visible area of the canvas where there are changes + TQRect r = changeBounds(view->inverseWorldMatrix().map(area)); + if ( !r.isEmpty() ) { + TQPainter p(view->viewport()); + // Translate to the coordinate system of drawViewArea(). + TQPoint tl = view->contentsToViewport(TQPoint(0,0)); + p.translate(tl.x(),tl.y()); + drawViewArea( view, &p, wm.map(r), dblbuf ); + doneareas.append(new TQRect(r)); + } + } else +#endif + { + clusterizer.add(area); + } + } + } + + for (int i=0; ichwidth) + mx=chwidth; + if (my>chheight) + my=chheight; + + int x=thearea.x()/chunksize; + while( xchwidth) + mx=chwidth; + if (my>chheight) + my=chheight; + + int x=thearea.x()/chunksize; + while( x chwidth) + mx=chwidth; + if (my > chheight) + my=chheight; + + TQRect result; + + int x=area.x()/chunksize; + while( x chwidth) + mx=chwidth; + if (my > chheight) + my=chheight; + + int x=area.x()/chunksize; + while( xviewList.first() && !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; + + TQCanvasItemList 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) + TQRegion 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 |= TQRegion(x*chunksize-area.x(),y*chunksize-area.y(), + chunksize,chunksize); + allvisible += *chunk(x,y).listPtr(); + } + } else { + allvisible += *chunk(x,y).listPtr(); + } + } + } + allvisible.sort(); + + if ( double_buffer ) { + offscr = TQPixmap(area.size().expandedTo(TQSize(1, 1))); +#ifdef TQ_WS_X11 + if (p) + offscr.x11SetScreen(p->device()->x11Screen()); +#endif + } + + if ( double_buffer && !offscr.isNull() ) { + TQPainter painter; + painter.begin(&offscr); + painter.translate(-area.x(),-area.y()); + painter.setBrushOrigin(-area.x(),-area.y()); + if ( p ) { + painter.setClipRect(TQRect(0,0,area.width(),area.height())); + } else { + painter.setClipRegion(rgn); + } + drawBackground(painter,area); + allvisible.drawUnique(painter); + drawForeground(painter,area); + painter.end(); + if ( p ) { + p->drawPixmap( area.x(), area.y(), offscr, + 0, 0, area.width(), area.height() ); + return; + } + } else if ( p ) { + drawBackground(*p,area); + allvisible.drawUnique(*p); + drawForeground(*p,area); + return; + } + + TQPoint trtr; // keeps track of total translation of rgn + + trtr -= area.topLeft(); + + for (TQCanvasView* view=d->viewList.first(); view; view=d->viewList.next()) { +#ifndef TQT_NO_TRANSFORMATIONS + if ( !view->worldMatrix().isIdentity() ) + continue; // Cannot paint those here (see callers). +#endif + TQPainter painter(view->viewport()); + TQPoint tr = view->contentsToViewport(area.topLeft()); + TQPoint nrtr = view->contentsToViewport(TQPoint(0,0)); // new translation + TQPoint rtr = nrtr - trtr; // extra translation of rgn + trtr += rtr; // add to total + if (double_buffer) { + rgn.translate(rtr.x(),rtr.y()); + painter.setClipRegion(rgn); + painter.drawPixmap(tr,offscr, TQRect(TQPoint(0,0),area.size())); + } else { + painter.translate(nrtr.x(),nrtr.y()); + rgn.translate(rtr.x(),rtr.y()); + painter.setClipRegion(rgn); + drawBackground(painter,area); + allvisible.drawUnique(painter); + drawForeground(painter,area); + painter.translate(-nrtr.x(),-nrtr.y()); + } + } +} + +/*! +\internal +This method to informs the TQCanvas 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 TQCanvasItem +must do so too. SetChangedChunkContaining can be used instead. +*/ +void TQCanvas::setChangedChunk(int x, int y) +{ + if (validChunk(x,y)) { + TQCanvasChunk& ch=chunk(x,y); + ch.change(); + } +} + +/*! +\internal +This method to informs the TQCanvas that the chunk containing a given +pixel 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 TQCanvasItem must +do so too. SetChangedChunk can be used instead. +*/ +void TQCanvas::setChangedChunkContaining(int x, int y) +{ + if (x>=0 && x=0 && y=0 && x=0 && y=0 && x=0 && yviewList.first(); + while ( view != 0 ) { + /* XXX this doesn't look right. Shouldn't this + be more like setBackgroundPixmap? : Ian */ + view->viewport()->setEraseColor( bgcolor ); + view=d->viewList.next(); + } + setAllChanged(); + } +} + +/*! + Returns the pixmap set by setBackgroundPixmap(). By default, + this is a null pixmap. + + \sa setBackgroundPixmap(), backgroundColor() +*/ +TQPixmap TQCanvas::backgroundPixmap() const +{ + return pm; +} + +/*! + Sets the solid background to be the pixmap \a p repeated as + necessary to cover the entire canvas. + + \sa backgroundPixmap(), setBackgroundColor(), setTiles() +*/ +void TQCanvas::setBackgroundPixmap( const TQPixmap& p ) +{ + setTiles(p, 1, 1, p.width(), p.height()); + TQCanvasView* view = d->viewList.first(); + while ( view != 0 ) { + view->updateContents(); + view = d->viewList.next(); + } +} + +/*! + This virtual function is called for all updates of the canvas. It + renders any background graphics using the painter \a painter, in + the area \a clip. If the canvas has a background pixmap or a tiled + background, that graphic is used, otherwise the canvas is cleared + using the background color. + + If the graphics for an area change, you must explicitly call + setChanged(const TQRect&) for the result to be visible when + update() is next called. + + \sa setBackgroundColor(), setBackgroundPixmap(), setTiles() +*/ +void TQCanvas::drawBackground(TQPainter& painter, const TQRect& clip) +{ + if ( pm.isNull() ) { + painter.fillRect(clip,bgcolor); + } else if ( !grid ) { + for (int x=clip.x()/pm.width(); + x<(clip.x()+clip.width()+pm.width()-1)/pm.width(); x++) + { + for (int y=clip.y()/pm.height(); + y<(clip.y()+clip.height()+pm.height()-1)/pm.height(); y++) + { + painter.drawPixmap(x*pm.width(), y*pm.height(),pm); + } + } + } else { + const int x1 = clip.left()/tilew; + int x2 = clip.right()/tilew; + const int y1 = clip.top()/tileh; + int y2 = clip.bottom()/tileh; + + const int roww = pm.width()/tilew; + + for (int j=y1; j<=y2; j++) { + int jj = j%tilesVertically(); + for (int i=x1; i<=x2; i++) { + int t = tile(i%tilesHorizontally(), jj); + int tx = t % roww; + int ty = t / roww; + painter.drawPixmap( i*tilew, j*tileh, pm, + tx*tilew, ty*tileh, tilew, tileh ); + } + } + } +} + +/*! + This virtual function is called for all updates of the canvas. It + renders any foreground graphics using the painter \a painter, in + the area \a clip. + + If the graphics for an area change, you must explicitly call + setChanged(const TQRect&) for the result to be visible when + update() is next called. + + The default is to draw nothing. +*/ +void TQCanvas::drawForeground(TQPainter& painter, const TQRect& clip) +{ + if ( debug_redraw_areas ) { + painter.setPen(red); + painter.setBrush(NoBrush); + painter.drawRect(clip); + } +} + +/*! + If \a y is TRUE (the default) double-buffering is switched on; + otherwise double-buffering is switched off. + + Turning off double-buffering causes the redrawn areas to flicker a + little and also gives a (usually small) performance improvement. +*/ +void TQCanvas::setDoubleBuffering(bool y) +{ + dblbuf = y; +} + + +/*! + Sets the TQCanvas to be composed of \a h tiles horizontally and \a + v tiles vertically. Each tile will be an image \a tilewidth by \a + tileheight pixels from pixmap \a p. + + The pixmap \a p is a list of tiles, arranged left to right, (and + in the case of pixmaps that have multiple rows of tiles, top to + bottom), with tile 0 in the top-left corner, tile 1 next to the + right, and so on, e.g. + + \table + \row \i 0 \i 1 \i 2 \i 3 + \row \i 4 \i 5 \i 6 \i 7 + \endtable + + If the canvas is larger than the matrix of tiles, the entire + matrix is repeated as necessary to cover the whole canvas. If it + is smaller, tiles to the right and bottom are not visible. + + The width and height of \a p must be a multiple of \a tilewidth + and \a tileheight. If they are not the function will do nothing. + + If you want to unset any tiling set, then just pass in a null + pixmap and 0 for \a h, \a v, \a tilewidth, and + \a tileheight. +*/ +void TQCanvas::setTiles( TQPixmap p, + int h, int v, int tilewidth, int tileheight ) +{ + if ( !p.isNull() && (!tilewidth || !tileheight || + p.width() % tilewidth != 0 || p.height() % tileheight != 0 ) ) + return; + + htiles = h; + vtiles = v; + delete[] grid; + pm = p; + if ( h && v && !p.isNull() ) { + grid = new ushort[h*v]; + memset( grid, 0, h*v*sizeof(ushort) ); + tilew = tilewidth; + tileh = tileheight; + } else { + grid = 0; + } + if ( h + v > 10 ) { + int s = scm(tilewidth,tileheight); + retune( s < 128 ? s : TQMAX(tilewidth,tileheight) ); + } + setAllChanged(); +} + +/*! + \fn int TQCanvas::tile( int x, int y ) const + + Returns the tile at position (\a x, \a y). Initially, all tiles + are 0. + + The parameters must be within range, i.e. + 0 \< \a x \< tilesHorizontally() and + 0 \< \a y \< tilesVertically(). + + \sa setTile() +*/ + +/*! + \fn int TQCanvas::tilesHorizontally() const + + Returns the number of tiles horizontally. +*/ + +/*! + \fn int TQCanvas::tilesVertically() const + + Returns the number of tiles vertically. +*/ + +/*! + \fn int TQCanvas::tileWidth() const + + Returns the width of each tile. +*/ + +/*! + \fn int TQCanvas::tileHeight() const + + Returns the height of each tile. +*/ + + +/*! + Sets the tile at (\a x, \a y) to use tile number \a tilenum, which + is an index into the tile pixmaps. The canvas will update + appropriately when update() is next called. + + The images are taken from the pixmap set by setTiles() and are + arranged left to right, (and in the case of pixmaps that have + multiple rows of tiles, top to bottom), with tile 0 in the + top-left corner, tile 1 next to the right, and so on, e.g. + + \table + \row \i 0 \i 1 \i 2 \i 3 + \row \i 4 \i 5 \i 6 \i 7 + \endtable + + \sa tile() setTiles() +*/ +void TQCanvas::setTile( int x, int y, int tilenum ) +{ + ushort& t = grid[x+y*htiles]; + if ( t != tilenum ) { + t = tilenum; + if ( tilew == tileh && tilew == chunksize ) + setChangedChunk( x, y ); // common case + else + setChanged( TQRect(x*tilew,y*tileh,tilew,tileh) ); + } +} + + +// lesser-used data in canvas item, plus room for extension. +// Be careful adding to this - check all usages. +class TQCanvasItemExtra { + TQCanvasItemExtra() : vx(0.0), vy(0.0) { } + double vx,vy; + friend class TQCanvasItem; +}; + + +/*! + \class TQCanvasItem tqcanvas.h + \brief The TQCanvasItem class provides an abstract graphic object on a TQCanvas. +\if defined(commercial) + It is part of the TQt Enterprise Edition. +\endif + + \module canvas + \ingroup graphics + \ingroup images + + A variety of TQCanvasItem subclasses provide immediately usable + behaviour. This class is a pure abstract superclass providing the + behaviour that is shared among all the concrete canvas item classes. + TQCanvasItem is not intended for direct subclassing. It is much easier + to subclass one of its subclasses, e.g. TQCanvasPolygonalItem (the + commonest base class), TQCanvasRectangle, TQCanvasSprite, TQCanvasEllipse + or TQCanvasText. + + Canvas items are added to a canvas by constructing them and passing the + canvas to the canvas item's constructor. An item can be moved to a + different canvas using setCanvas(). + + Items appear on the canvas after their \link show() show()\endlink + function has been called (or \link setVisible() + setVisible(TRUE)\endlink), and \e after update() has been called. The + canvas only shows items that are \link setVisible() visible\endlink, + and then only if \l update() is called. If you created the canvas + without passing a width and height to the constructor you'll also need + to call \link TQCanvas::resize() resize()\endlink. Since the canvas + background defaults to white and canvas items default to white, + you may need to change colors to see your items. + + A TQCanvasItem object can be moved in the x(), y() and z() dimensions + using functions such as move(), moveBy(), setX(), setY() and setZ(). A + canvas item can be set in motion, `animated', using setAnimated() and + given a velocity in the x and y directions with setXVelocity() and + setYVelocity() -- the same effect can be achieved by calling + setVelocity(). Use the collidesWith() function to see if the canvas item + will collide on the \e next advance(1) and use collisions() to see what + collisions have occurred. + + Use TQCanvasSprite or your own subclass of TQCanvasSprite to create canvas + items which are animated, i.e. which change over time. + + The size of a canvas item is given by boundingRect(). Use + boundingRectAdvanced() to see what the size of the canvas item will be + \e after the next advance(1) call. + + The rtti() function is used for identifying subclasses of TQCanvasItem. + The canvas() function returns a pointer to the canvas which contains the + canvas item. + + TQCanvasItem provides the show() and isVisible() functions like those in + TQWidget. + + TQCanvasItem also provides the setEnabled(), setActive() and + setSelected() functions; these functions set the relevant boolean and + cause a repaint but the boolean values they set are not used in + TQCanvasItem itself. You can make use of these booleans in your subclasses. + + By default, canvas items have no velocity, no size, and are not in + motion. The subclasses provided in TQt do not change these defaults + except where noted. + +*/ + +/*! + \enum TQCanvasItem::RttiValues + + This enum is used to name the different types of canvas item. + + \value Rtti_Item Canvas item abstract base class + \value Rtti_Ellipse + \value Rtti_Line + \value Rtti_Polygon + \value Rtti_PolygonalItem + \value Rtti_Rectangle + \value Rtti_Spline + \value Rtti_Sprite + \value Rtti_Text + +*/ + +/*! + \fn void TQCanvasItem::update() + + Call this function to repaint the canvas's changed chunks. +*/ + +/*! + Constructs a TQCanvasItem on canvas \a canvas. + + \sa setCanvas() +*/ +TQCanvasItem::TQCanvasItem(TQCanvas* canvas) : + cnv(canvas), + myx(0),myy(0),myz(0) +{ + ani=0; + vis=0; + val=0; + sel=0; + ena=0; + act=0; + + ext = 0; + if (cnv) cnv->addItem(this); +} + +/*! + Destroys the TQCanvasItem and removes it from its canvas. +*/ +TQCanvasItem::~TQCanvasItem() +{ + if (cnv) { + cnv->removeItem(this); + cnv->removeAnimation(this); + } + delete ext; +} + +TQCanvasItemExtra& TQCanvasItem::extra() +{ + if ( !ext ) + ext = new TQCanvasItemExtra; + return *ext; +} + +/*! + \fn double TQCanvasItem::x() const + + Returns the horizontal position of the canvas item. Note that + subclasses often have an origin other than the top-left corner. +*/ + +/*! + \fn double TQCanvasItem::y() const + + Returns the vertical position of the canvas item. Note that + subclasses often have an origin other than the top-left corner. +*/ + +/*! + \fn double TQCanvasItem::z() const + + Returns the z index of the canvas item, which is used for visual + order: higher-z items obscure (are in front of) lower-z items. +*/ + +/*! + \fn void TQCanvasItem::setX(double x) + + Moves the canvas item so that its x-position is \a x. + + \sa x(), move() +*/ + +/*! + \fn void TQCanvasItem::setY(double y) + + Moves the canvas item so that its y-position is \a y. + + \sa y(), move() +*/ + +/*! + \fn void TQCanvasItem::setZ(double z) + + Sets the z index of the canvas item to \a z. Higher-z items + obscure (are in front of) lower-z items. + + \sa z(), move() +*/ + + +/*! + Moves the canvas item relative to its current position by (\a dx, + \a dy). +*/ +void TQCanvasItem::moveBy( double dx, double dy ) +{ + if ( dx || dy ) { + removeFromChunks(); + myx += dx; + myy += dy; + addToChunks(); + } +} + + +/*! + Moves the canvas item to the absolute position (\a x, \a y). +*/ +void TQCanvasItem::move( double x, double y ) +{ + moveBy( x-myx, y-myy ); +} + + +/*! + Returns TRUE if the canvas item is in motion; otherwise returns + FALSE. + + \sa setVelocity(), setAnimated() +*/ +bool TQCanvasItem::animated() const +{ + return (bool)ani; +} + +/*! + Sets the canvas item to be in motion if \a y is TRUE, or not if \a + y is FALSE. The speed and direction of the motion is set with + setVelocity(), or with setXVelocity() and setYVelocity(). + + \sa advance(), TQCanvas::advance() +*/ +void TQCanvasItem::setAnimated(bool y) +{ + if ( y != (bool)ani ) { + ani = (uint)y; + if ( y ) { + cnv->addAnimation(this); + } else { + cnv->removeAnimation(this); + } + } +} + +/*! + \fn void TQCanvasItem::setXVelocity( double vx ) + + Sets the horizontal component of the canvas item's velocity to \a vx. + + \sa setYVelocity() setVelocity() +*/ + +/*! + \fn void TQCanvasItem::setYVelocity( double vy ) + + Sets the vertical component of the canvas item's velocity to \a vy. + + \sa setXVelocity() setVelocity() +*/ + +/*! + Sets the canvas item to be in motion, moving by \a vx and \a vy + pixels in the horizontal and vertical directions respectively. + + \sa advance() setXVelocity() setYVelocity() +*/ +void TQCanvasItem::setVelocity( double vx, double vy) +{ + if ( ext || vx!=0.0 || vy!=0.0 ) { + if ( !ani ) + setAnimated(TRUE); + extra().vx = vx; + extra().vy = vy; + } +} + +/*! + Returns the horizontal velocity component of the canvas item. +*/ +double TQCanvasItem::xVelocity() const +{ + return ext ? ext->vx : 0; +} + +/*! + Returns the vertical velocity component of the canvas item. +*/ +double TQCanvasItem::yVelocity() const +{ + return ext ? ext->vy : 0; +} + +/*! + The default implementation moves the canvas item, if it is + animated(), by the preset velocity if \a phase is 1, and does + nothing if \a phase is 0. + + Note that if you reimplement this function, the reimplementation + must not change the canvas in any way, for example it must not add + or remove items. + + \sa TQCanvas::advance() setVelocity() +*/ +void TQCanvasItem::advance(int phase) +{ + if ( ext && phase==1 ) + moveBy(ext->vx,ext->vy); +} + +/*! + \fn void TQCanvasItem::draw(TQPainter& painter) + + This abstract virtual function draws the canvas item using \a painter. + + \warning When you reimplement this function, make sure that you + leave the painter in the same state as you found it. For example, + if you start by calling TQPainter::translate(50, 50), end your + code by calling TQPainter::translate(-50, -50). Be also aware that + the painter might already have some transformations set (i.e., + don't call TQPainter::resetXForm() when you're done). +*/ + +/*! + Sets the TQCanvas upon which the canvas item is to be drawn to \a c. + + \sa canvas() +*/ +void TQCanvasItem::setCanvas(TQCanvas* c) +{ + bool v=isVisible(); + setVisible(FALSE); + if (cnv) { + if (ext) + cnv->removeAnimation(this); + cnv->removeItem(this); + } + cnv=c; + if (cnv) { + cnv->addItem(this); + if ( ext ) + cnv->addAnimation(this); + } + setVisible(v); +} + +/*! + \fn TQCanvas* TQCanvasItem::canvas() const + + Returns the canvas containing the canvas item. +*/ + +/*! Shorthand for setVisible(TRUE). */ +void TQCanvasItem::show() +{ + setVisible(TRUE); +} + +/*! Shorthand for setVisible(FALSE). */ +void TQCanvasItem::hide() +{ + setVisible(FALSE); +} + +/*! + Makes the canvas item visible if \a yes is TRUE, or invisible if + \a yes is FALSE. The change takes effect when TQCanvas::update() is + next called. +*/ +void TQCanvasItem::setVisible(bool yes) +{ + if ((bool)vis!=yes) { + if (yes) { + vis=(uint)yes; + addToChunks(); + } else { + removeFromChunks(); + vis=(uint)yes; + } + } +} +/*! + \obsolete + \fn bool TQCanvasItem::visible() const + Use isVisible() instead. +*/ + +/*! + \fn bool TQCanvasItem::isVisible() const + + Returns TRUE if the canvas item is visible; otherwise returns + FALSE. + + Note that in this context TRUE does \e not mean that the canvas + item is currently in a view, merely that if a view is showing the + area where the canvas item is positioned, and the item is not + obscured by items with higher z values, and the view is not + obscured by overlaying windows, it would be visible. + + \sa setVisible(), z() +*/ + +/*! + \obsolete + \fn bool TQCanvasItem::selected() const + Use isSelected() instead. +*/ + +/*! + \fn bool TQCanvasItem::isSelected() const + + Returns TRUE if the canvas item is selected; otherwise returns FALSE. +*/ + +/*! + Sets the selected flag of the item to \a yes. If this changes the + item's selected state the item will be redrawn when + TQCanvas::update() is next called. + + The TQCanvas, TQCanvasItem and the TQt-supplied TQCanvasItem + subclasses do not make use of this value. The setSelected() + function is supplied because many applications need it, but it is + up to you how you use the isSelected() value. +*/ +void TQCanvasItem::setSelected(bool yes) +{ + if ((bool)sel!=yes) { + sel=(uint)yes; + changeChunks(); + } +} + +/*! + \obsolete + \fn bool TQCanvasItem::enabled() const + Use isEnabled() instead. +*/ + +/*! + \fn bool TQCanvasItem::isEnabled() const + + Returns TRUE if the TQCanvasItem is enabled; otherwise returns FALSE. +*/ + +/*! + Sets the enabled flag of the item to \a yes. If this changes the + item's enabled state the item will be redrawn when + TQCanvas::update() is next called. + + The TQCanvas, TQCanvasItem and the TQt-supplied TQCanvasItem + subclasses do not make use of this value. The setEnabled() + function is supplied because many applications need it, but it is + up to you how you use the isEnabled() value. +*/ +void TQCanvasItem::setEnabled(bool yes) +{ + if (ena!=(uint)yes) { + ena=(uint)yes; + changeChunks(); + } +} + +/*! + \obsolete + \fn bool TQCanvasItem::active() const + Use isActive() instead. +*/ + +/*! + \fn bool TQCanvasItem::isActive() const + + Returns TRUE if the TQCanvasItem is active; otherwise returns FALSE. +*/ + +/*! + Sets the active flag of the item to \a yes. If this changes the + item's active state the item will be redrawn when + TQCanvas::update() is next called. + + The TQCanvas, TQCanvasItem and the TQt-supplied TQCanvasItem + subclasses do not make use of this value. The setActive() function + is supplied because many applications need it, but it is up to you + how you use the isActive() value. +*/ +void TQCanvasItem::setActive(bool yes) +{ + if (act!=(uint)yes) { + act=(uint)yes; + changeChunks(); + } +} + +bool qt_testCollision(const TQCanvasSprite* s1, const TQCanvasSprite* s2) +{ + const TQImage* s2image = s2->imageAdvanced()->collision_mask; + TQRect s2area = s2->boundingRectAdvanced(); + + TQRect cyourarea(s2area.x(),s2area.y(), + s2area.width(),s2area.height()); + + TQImage* s1image=s1->imageAdvanced()->collision_mask; + + TQRect s1area = s1->boundingRectAdvanced(); + + TQRect ourarea = s1area.intersect(cyourarea); + + if ( ourarea.isEmpty() ) + return FALSE; + + int x2=ourarea.x()-cyourarea.x(); + int y2=ourarea.y()-cyourarea.y(); + int x1=ourarea.x()-s1area.x(); + int y1=ourarea.y()-s1area.y(); + int w=ourarea.width(); + int h=ourarea.height(); + + if ( !s2image ) { + if ( !s1image ) + return w>0 && h>0; + // swap everything around + int t; + t=x1; x1=x2; x2=t; + t=y1; x1=y2; y2=t; + s2image = s1image; + s1image = 0; + } + + // s2image != 0 + + // A non-linear search may be more efficient. + // Perhaps spiralling out from the center, or a simpler + // vertical expansion from the centreline. + + // We assume that sprite masks don't have + // different bit orders. + // + // Q_ASSERT(s1image->bitOrder()==s2image->bitOrder()); + + if (s1image) { + if (s1image->bitOrder() == TQImage::LittleEndian) { + for (int j=0; jscanLine(y1+j); + uchar* yl = s2image->scanLine(y2+j); + for (int i=0; i> 3)) & (1 << ((x2+i) & 7)) + && *(ml + ((x1+i) >> 3)) & (1 << ((x1+i) & 7))) + { + return TRUE; + } + } + } + } else { + for (int j=0; jscanLine(y1+j); + uchar* yl = s2image->scanLine(y2+j); + for (int i=0; i> 3)) & (1 << (7-((x2+i) & 7))) + && *(ml + ((x1+i) >> 3)) & (1 << (7-((x1+i) & 7)))) + { + return TRUE; + } + } + } + } + } else { + if (s2image->bitOrder() == TQImage::LittleEndian) { + for (int j=0; jscanLine(y2+j); + for (int i=0; i> 3)) & (1 << ((x2+i) & 7))) + { + return TRUE; + } + } + } + } else { + for (int j=0; jscanLine(y2+j); + for (int i=0; i> 3)) & (1 << (7-((x2+i) & 7)))) + { + return TRUE; + } + } + } + } + } + + return FALSE; +} + +static bool collision_double_dispatch( const TQCanvasSprite* s1, + const TQCanvasPolygonalItem* p1, + const TQCanvasRectangle* r1, + const TQCanvasEllipse* e1, + const TQCanvasText* t1, + const TQCanvasSprite* s2, + const TQCanvasPolygonalItem* p2, + const TQCanvasRectangle* r2, + const TQCanvasEllipse* e2, + const TQCanvasText* t2 ) +{ + const TQCanvasItem* i1 = s1 ? + (const TQCanvasItem*)s1 : p1 ? + (const TQCanvasItem*)p1 : r1 ? + (const TQCanvasItem*)r1 : e1 ? + (const TQCanvasItem*)e1 : (const TQCanvasItem*)t1; + const TQCanvasItem* i2 = s2 ? + (const TQCanvasItem*)s2 : p2 ? + (const TQCanvasItem*)p2 : r2 ? + (const TQCanvasItem*)r2 : e2 ? + (const TQCanvasItem*)e2 : (const TQCanvasItem*)t2; + + if ( s1 && s2 ) { + // a + return qt_testCollision(s1,s2); + } else if ( (r1 || t1 || s1) && (r2 || t2 || s2) ) { + // b + TQRect rc1 = i1->boundingRectAdvanced(); + TQRect rc2 = i2->boundingRectAdvanced(); + return rc1.intersects(rc2); + } else if ( e1 && e2 + && e1->angleLength()>=360*16 && e2->angleLength()>=360*16 + && e1->width()==e1->height() + && e2->width()==e2->height() ) { + // c + double xd = (e1->x()+e1->xVelocity())-(e2->x()+e1->xVelocity()); + double yd = (e1->y()+e1->yVelocity())-(e2->y()+e1->yVelocity()); + double rd = (e1->width()+e2->width())/2; + return xd*xd+yd*yd <= rd*rd; + } else if ( p1 && (p2 || s2 || t2) ) { + // d + TQPointArray pa1 = p1->areaPointsAdvanced(); + TQPointArray pa2 = p2 ? p2->areaPointsAdvanced() + : TQPointArray(i2->boundingRectAdvanced()); + bool col= !(TQRegion(pa1) & TQRegion(pa2,TRUE)).isEmpty(); + + return col; + } else { + return collision_double_dispatch(s2,p2,r2,e2,t2, + s1,p1,r1,e1,t1); + } +} + +/*! + \fn bool TQCanvasItem::collidesWith( const TQCanvasItem* other ) const + + Returns TRUE if the canvas item will collide with the \a other + item \e after they have moved by their current velocities; + otherwise returns FALSE. + + \sa collisions() +*/ + + +/*! + \class TQCanvasSprite tqcanvas.h + \brief The TQCanvasSprite class provides an animated canvas item on a TQCanvas. +\if defined(commercial) + It is part of the TQt Enterprise Edition. +\endif + + \module canvas + \ingroup graphics + \ingroup images + + A canvas sprite is an object which can contain any number of images + (referred to as frames), only one of which is current, i.e. + displayed, at any one time. The images can be passed in the + constructor or set or changed later with setSequence(). If you + subclass TQCanvasSprite you can change the frame that is displayed + periodically, e.g. whenever TQCanvasItem::advance(1) is called to + create the effect of animation. + + The current frame can be set with setFrame() or with move(). The + number of frames available is given by frameCount(). The bounding + rectangle of the current frame is returned by boundingRect(). + + The current frame's image can be retrieved with image(); use + imageAdvanced() to retrieve the image for the frame that will be + shown after advance(1) is called. Use the image() overload passing + it an integer index to retrieve a particular image from the list of + frames. + + Use width() and height() to retrieve the dimensions of the current + frame. + + Use leftEdge() and rightEdge() to retrieve the current frame's + left-hand and right-hand x-coordinates respectively. Use + bottomEdge() and topEdge() to retrieve the current frame's bottom + and top y-coordinates respectively. These functions have an overload + which will accept an integer frame number to retrieve the + coordinates of a particular frame. + + TQCanvasSprite draws very quickly, at the expense of memory. + + The current frame's image can be drawn on a painter with draw(). + + Like any other canvas item, canvas sprites can be moved with + move() which sets the x and y coordinates and the frame number, as + well as with TQCanvasItem::move() and TQCanvasItem::moveBy(), or by + setting coordinates with TQCanvasItem::setX(), TQCanvasItem::setY() + and TQCanvasItem::setZ(). + +*/ + + +/*! + \reimp +*/ +bool TQCanvasSprite::collidesWith( const TQCanvasItem* i ) const +{ + return i->collidesWith(this,0,0,0,0); +} + +/*! + Returns TRUE if the canvas item collides with any of the given + items; otherwise returns FALSE. The parameters, \a s, \a p, \a r, + \a e and \a t, are all the same object, this is just a type + resolution trick. +*/ +bool TQCanvasSprite::collidesWith( const TQCanvasSprite* s, + const TQCanvasPolygonalItem* p, + const TQCanvasRectangle* r, + const TQCanvasEllipse* e, + const TQCanvasText* t ) const +{ + return collision_double_dispatch(s,p,r,e,t,this,0,0,0,0); +} + +/*! + \reimp +*/ +bool TQCanvasPolygonalItem::collidesWith( const TQCanvasItem* i ) const +{ + return i->collidesWith(0,this,0,0,0); +} + +bool TQCanvasPolygonalItem::collidesWith( const TQCanvasSprite* s, + const TQCanvasPolygonalItem* p, + const TQCanvasRectangle* r, + const TQCanvasEllipse* e, + const TQCanvasText* t ) const +{ + return collision_double_dispatch(s,p,r,e,t,0,this,0,0,0); +} + +/*! + \reimp +*/ +bool TQCanvasRectangle::collidesWith( const TQCanvasItem* i ) const +{ + return i->collidesWith(0,this,this,0,0); +} + +bool TQCanvasRectangle::collidesWith( const TQCanvasSprite* s, + const TQCanvasPolygonalItem* p, + const TQCanvasRectangle* r, + const TQCanvasEllipse* e, + const TQCanvasText* t ) const +{ + return collision_double_dispatch(s,p,r,e,t,0,this,this,0,0); +} + + +/*! + \reimp +*/ +bool TQCanvasEllipse::collidesWith( const TQCanvasItem* i ) const +{ + return i->collidesWith(0,this,0,this,0); +} + +bool TQCanvasEllipse::collidesWith( const TQCanvasSprite* s, + const TQCanvasPolygonalItem* p, + const TQCanvasRectangle* r, + const TQCanvasEllipse* e, + const TQCanvasText* t ) const +{ + return collision_double_dispatch(s,p,r,e,t,0,this,0,this,0); +} + +/*! + \reimp +*/ +bool TQCanvasText::collidesWith( const TQCanvasItem* i ) const +{ + return i->collidesWith(0,0,0,0,this); +} + +bool TQCanvasText::collidesWith( const TQCanvasSprite* s, + const TQCanvasPolygonalItem* p, + const TQCanvasRectangle* r, + const TQCanvasEllipse* e, + const TQCanvasText* t ) const +{ + return collision_double_dispatch(s,p,r,e,t,0,0,0,0,this); +} + +/*! + Returns the list of canvas items that this canvas item has + collided with. + + A collision is generally defined as occurring when the pixels of + one item draw on the pixels of another item, but not all + subclasses are so precise. Also, since pixel-wise collision + detection can be slow, this function works in either exact or + inexact mode, according to the \a exact parameter. + + If \a exact is TRUE, the canvas items returned have been + accurately tested for collision with the canvas item. + + If \a exact is FALSE, the canvas items returned are \e near the + canvas item. You can test the canvas items returned using + collidesWith() if any are interesting collision candidates. By + using this approach, you can ignore some canvas items for which + collisions are not relevant. + + The returned list is a list of TQCanvasItems, but often you will + need to cast the items to their subclass types. The safe way to do + this is to use rtti() before casting. This provides some of the + functionality of the standard C++ dynamic cast operation even on + compilers where dynamic casts are not available. + + Note that a canvas item may be `on' a canvas, e.g. it was created + with the canvas as parameter, even though its coordinates place it + beyond the edge of the canvas's area. Collision detection only + works for canvas items which are wholly or partly within the + canvas's area. + + Note that if items have a velocity (see \l setVelocity()), then + collision testing is done based on where the item \e will be when + it moves, not its current location. For example, a "ball" item + doesn't need to actually embed into a "wall" item before a + collision is detected. For items without velocity, plain + intersection is used. +*/ +TQCanvasItemList TQCanvasItem::collisions(bool exact) const +{ + return canvas()->collisions(chunks(),this,exact); +} + +/*! + Returns a list of canvas items that collide with the point \a p. + The list is ordered by z coordinates, from highest z coordinate + (front-most item) to lowest z coordinate (rear-most item). +*/ +TQCanvasItemList TQCanvas::collisions(const TQPoint& p) const +{ + return collisions(TQRect(p,TQSize(1,1))); +} + +/*! + \overload + + Returns a list of items which collide with the rectangle \a r. The + list is ordered by z coordinates, from highest z coordinate + (front-most item) to lowest z coordinate (rear-most item). +*/ +TQCanvasItemList TQCanvas::collisions(const TQRect& r) const +{ + TQCanvasRectangle i(r,(TQCanvas*)this); + i.setPen(NoPen); + i.show(); // doesn't actually show, since we destroy it + TQCanvasItemList l = i.collisions(TRUE); + l.sort(); + return l; +} + +/*! + \overload + + Returns a list of canvas items which intersect with the chunks + listed in \a chunklist, excluding \a item. If \a exact is TRUE, + only those which actually \link TQCanvasItem::collidesWith() + collide with\endlink \a item are returned; otherwise canvas items + are included just for being in the chunks. + + This is a utility function mainly used to implement the simpler + TQCanvasItem::collisions() function. +*/ +TQCanvasItemList TQCanvas::collisions(const TQPointArray& chunklist, + const TQCanvasItem* item, bool exact) const +{ + TQPtrDict seen; + TQCanvasItemList result; + for (int i=0; i<(int)chunklist.count(); i++) { + int x = chunklist[i].x(); + int y = chunklist[i].y(); + if ( validChunk(x,y) ) { + const TQCanvasItemList* l = chunk(x,y).listPtr(); + for (TQCanvasItemList::ConstIterator it=l->begin(); it!=l->end(); ++it) { + TQCanvasItem *g=*it; + if ( g != item ) { + if ( !seen.find(g) ) { + seen.replace(g,(void*)1); + if ( !exact || item->collidesWith(g) ) + result.append(g); + } + } + } + } + } + return result; +} + +/*! + \internal + Adds the item to all the chunks it covers. +*/ +void TQCanvasItem::addToChunks() +{ + if (isVisible() && canvas()) { + TQPointArray pa = chunks(); + for (int i=0; i<(int)pa.count(); i++) + canvas()->addItemToChunk(this,pa[i].x(),pa[i].y()); + val=(uint)TRUE; + } +} + +/*! + \internal + Removes the item from all the chunks it covers. +*/ +void TQCanvasItem::removeFromChunks() +{ + if (isVisible() && canvas()) { + TQPointArray pa = chunks(); + for (int i=0; i<(int)pa.count(); i++) + canvas()->removeItemFromChunk(this,pa[i].x(),pa[i].y()); + } +} + +/*! + \internal + Sets all the chunks covered by the item to be refreshed with TQCanvas::update() + is next called. +*/ +void TQCanvasItem::changeChunks() +{ + if (isVisible() && canvas()) { + if (!val) + addToChunks(); + TQPointArray pa = chunks(); + for (int i=0; i<(int)pa.count(); i++) + canvas()->setChangedChunk(pa[i].x(),pa[i].y()); + } +} + +/*! + \fn TQRect TQCanvasItem::boundingRect() const + + Returns the bounding rectangle in pixels that the canvas item covers. + + \sa boundingRectAdvanced() +*/ + +/*! + Returns the bounding rectangle of pixels that the canvas item \e + will cover after advance(1) is called. + + \sa boundingRect() +*/ +TQRect TQCanvasItem::boundingRectAdvanced() const +{ + int dx = int(x()+xVelocity())-int(x()); + int dy = int(y()+yVelocity())-int(y()); + TQRect r = boundingRect(); + r.moveBy(dx,dy); + return r; +} + +/*! + \class TQCanvasPixmap tqcanvas.h + \brief The TQCanvasPixmap class provides pixmaps for TQCanvasSprites. +\if defined(commercial) + It is part of the TQt Enterprise Edition. +\endif + + \module canvas + \ingroup graphics + \ingroup images + + If you want to show a single pixmap on a TQCanvas use a + TQCanvasSprite with just one pixmap. + + When pixmaps are inserted into a TQCanvasPixmapArray they are held + as TQCanvasPixmaps. \l{TQCanvasSprite}s are used to show pixmaps on + \l{TQCanvas}es and hold their pixmaps in a TQCanvasPixmapArray. If + you retrieve a frame (pixmap) from a TQCanvasSprite it will be + returned as a TQCanvasPixmap. + + The pixmap is a TQPixmap and can only be set in the constructor. + There are three different constructors, one taking a TQPixmap, one + a TQImage and one a file name that refers to a file in any + supported file format (see TQImageIO). + + TQCanvasPixmap can have a hotspot which is defined in terms of an (x, + y) offset. When you create a TQCanvasPixmap from a PNG file or from + a TQImage that has a TQImage::offset(), the offset() is initialized + appropriately, otherwise the constructor leaves it at (0, 0). You + can set it later using setOffset(). When the TQCanvasPixmap is used + in a TQCanvasSprite, the offset position is the point at + TQCanvasItem::x() and TQCanvasItem::y(), not the top-left corner of + the pixmap. + + Note that for TQCanvasPixmap objects created by a TQCanvasSprite, the + position of each TQCanvasPixmap object is set so that the hotspot + stays in the same position. + + \sa TQCanvasPixmapArray TQCanvasItem TQCanvasSprite +*/ + +#ifndef TQT_NO_IMAGEIO + +/*! + Constructs a TQCanvasPixmap that uses the image stored in \a + datafilename. +*/ +TQCanvasPixmap::TQCanvasPixmap(const TQString& datafilename) +{ + TQImage image(datafilename); + init(image); +} + +#endif + +/*! + Constructs a TQCanvasPixmap from the image \a image. +*/ +TQCanvasPixmap::TQCanvasPixmap(const TQImage& image) +{ + init(image); +} +/*! + Constructs a TQCanvasPixmap from the pixmap \a pm using the offset + \a offset. +*/ +TQCanvasPixmap::TQCanvasPixmap(const TQPixmap& pm, const TQPoint& offset) +{ + init(pm,offset.x(),offset.y()); +} + +void TQCanvasPixmap::init(const TQImage& image) +{ + convertFromImage(image); + hotx = image.offset().x(); + hoty = image.offset().y(); +#ifndef TQT_NO_IMAGE_DITHER_TO_1 + if( image.hasAlphaBuffer() ) { + TQImage i = image.createAlphaMask(); + collision_mask = new TQImage(i); + } else +#endif + collision_mask = 0; +} + +void TQCanvasPixmap::init(const TQPixmap& pixmap, int hx, int hy) +{ + (TQPixmap&)*this = pixmap; + hotx = hx; + hoty = hy; + if( pixmap.mask() ) { + TQImage i = mask()->convertToImage(); + collision_mask = new TQImage(i); + } else + collision_mask = 0; +} + +/*! + Destroys the pixmap. +*/ +TQCanvasPixmap::~TQCanvasPixmap() +{ + delete collision_mask; +} + +/*! + \fn int TQCanvasPixmap::offsetX() const + + Returns the x-offset of the pixmap's hotspot. + + \sa setOffset() +*/ + +/*! + \fn int TQCanvasPixmap::offsetY() const + + Returns the y-offset of the pixmap's hotspot. + + \sa setOffset() +*/ + +/*! + \fn void TQCanvasPixmap::setOffset(int x, int y) + + Sets the offset of the pixmap's hotspot to (\a x, \a y). + + \warning Do not call this function if any TQCanvasSprites are + currently showing this pixmap. +*/ + +/*! + \class TQCanvasPixmapArray tqcanvas.h + \brief The TQCanvasPixmapArray class provides an array of TQCanvasPixmaps. +\if defined(commercial) + It is part of the TQt Enterprise Edition. +\endif + + \module canvas + \ingroup graphics + \ingroup images + + + This class is used by TQCanvasSprite to hold an array of pixmaps. + It is used to implement animated sprites, i.e. images that change + over time, with each pixmap in the array holding one frame. + + Depending on the constructor you use you can load multiple pixmaps + into the array either from a directory (specifying a wildcard + pattern for the files), or from a list of TQPixmaps. You can also + read in a set of pixmaps after construction using readPixmaps(). + + Individual pixmaps can be set with setImage() and retrieved with + image(). The number of pixmaps in the array is returned by + count(). + + TQCanvasSprite uses an image's mask for collision detection. You + can change this by reading in a separate set of image masks using + readCollisionMasks(). + +*/ + +/*! + Constructs an invalid array (i.e. isValid() will return FALSE). + You must call readPixmaps() before being able to use this + TQCanvasPixmapArray. +*/ +TQCanvasPixmapArray::TQCanvasPixmapArray() +: framecount( 0 ), img( 0 ) +{ +} + +#ifndef TQT_NO_IMAGEIO +/*! + Constructs a TQCanvasPixmapArray from files. + + The \a fc parameter sets the number of frames to be loaded for + this image. + + If \a fc is not 0, \a datafilenamepattern should contain "%1", + e.g. "foo%1.png". The actual filenames are formed by replacing the + %1 with four-digit integers from 0 to (fc - 1), e.g. foo0000.png, + foo0001.png, foo0002.png, etc. + + If \a fc is 0, \a datafilenamepattern is asssumed to be a + filename, and the image contained in this file will be loaded as + the first (and only) frame. + + If \a datafilenamepattern does not exist, is not readable, isn't + an image, or some other error occurs, the array ends up empty and + isValid() returns FALSE. +*/ + +TQCanvasPixmapArray::TQCanvasPixmapArray( const TQString& datafilenamepattern, + int fc ) +: framecount( 0 ), img( 0 ) +{ + readPixmaps(datafilenamepattern,fc); +} +#endif + +/*! + \obsolete + Use TQCanvasPixmapArray::TQCanvasPixmapArray( TQValueList, TQPointArray ) + instead. + + Constructs a TQCanvasPixmapArray from the list of TQPixmaps \a + list. The \a hotspots list has to be of the same size as \a list. +*/ +TQCanvasPixmapArray::TQCanvasPixmapArray(TQPtrList list, TQPtrList hotspots) : + framecount(list.count()), + img(new TQCanvasPixmap*[list.count()]) +{ + if (list.count() != hotspots.count()) { + tqWarning("TQCanvasPixmapArray: lists have different lengths"); + reset(); + img = 0; + } else { + list.first(); + hotspots.first(); + for (int i=0; i list, TQPointArray hotspots) : + framecount((int)list.size()), + img(new TQCanvasPixmap*[list.size()]) +{ + bool have_hotspots = ( hotspots.size() != 0 ); + if (have_hotspots && list.count() != hotspots.count()) { + tqWarning("TQCanvasPixmapArray: lists have different lengths"); + reset(); + img = 0; + } else { + TQValueList::iterator it; + it = list.begin(); + for (int i=0; i 1; + if ( !arg ) + framecount=1; + for (int i=0; icollision_mask) + img[i]->collision_mask = new TQImage(); + img[i]->collision_mask->load( + arg ? datafilenamepattern.arg(r) : datafilenamepattern); + ok = ok + && !img[i]->collision_mask->isNull() + && img[i]->collision_mask->depth()==1; + } else { + img[i]=new TQCanvasPixmap( + arg ? datafilenamepattern.arg(r) : datafilenamepattern); + ok = ok && !img[i]->isNull(); + } + } + if ( !ok ) { + reset(); + } + return ok; +} +#endif + +/*! + \obsolete + + Use isValid() instead. + + This returns FALSE if the array is valid, and TRUE if it is not. +*/ +bool TQCanvasPixmapArray::operator!() +{ + return img==0; +} + +/*! + Returns TRUE if the pixmap array is valid; otherwise returns + FALSE. +*/ +bool TQCanvasPixmapArray::isValid() const +{ + return (img != 0); +} + +/*! + \fn TQCanvasPixmap* TQCanvasPixmapArray::image(int i) const + + Returns pixmap \a i in the array, if \a i is non-negative and less + than than count(), and returns an unspecified value otherwise. +*/ + +// ### wouldn't it be better to put empty TQCanvasPixmaps in there instead of +// initializing the additional elements in the array to 0? Lars +/*! + Replaces the pixmap at index \a i with pixmap \a p. + + The array takes ownership of \a p and will delete \a p when the + array itself is deleted. + + If \a i is beyond the end of the array the array is extended to at + least i+1 elements, with elements count() to i-1 being initialized + to 0. +*/ +void TQCanvasPixmapArray::setImage(int i, TQCanvasPixmap* p) +{ + if ( i >= framecount ) { + TQCanvasPixmap** newimg = new TQCanvasPixmap*[i+1]; + memcpy(newimg, img, sizeof( TQCanvasPixmap * )*framecount); + memset(newimg + framecount, 0, sizeof( TQCanvasPixmap * )*( i+1 - framecount ) ); + framecount = i+1; + delete [] img; + img = newimg; + } + delete img[i]; img[i]=p; +} + +/*! + \fn uint TQCanvasPixmapArray::count() const + + Returns the number of pixmaps in the array. +*/ + +/*! + Returns the x-coordinate of the current left edge of the sprite. + (This may change as the sprite animates since different frames may + have different left edges.) + + \sa rightEdge() bottomEdge() topEdge() +*/ +int TQCanvasSprite::leftEdge() const +{ + return int(x()) - image()->hotx; +} + +/*! + \overload + + Returns what the x-coordinate of the left edge of the sprite would + be if the sprite (actually its hotspot) were moved to x-position + \a nx. + + \sa rightEdge() bottomEdge() topEdge() +*/ +int TQCanvasSprite::leftEdge(int nx) const +{ + return nx - image()->hotx; +} + +/*! + Returns the y-coordinate of the top edge of the sprite. (This may + change as the sprite animates since different frames may have + different top edges.) + + \sa leftEdge() rightEdge() bottomEdge() +*/ +int TQCanvasSprite::topEdge() const +{ + return int(y()) - image()->hoty; +} + +/*! + \overload + + Returns what the y-coordinate of the top edge of the sprite would + be if the sprite (actually its hotspot) were moved to y-position + \a ny. + + \sa leftEdge() rightEdge() bottomEdge() +*/ +int TQCanvasSprite::topEdge(int ny) const +{ + return ny - image()->hoty; +} + +/*! + Returns the x-coordinate of the current right edge of the sprite. + (This may change as the sprite animates since different frames may + have different right edges.) + + \sa leftEdge() bottomEdge() topEdge() +*/ +int TQCanvasSprite::rightEdge() const +{ + return leftEdge() + image()->width()-1; +} + +/*! + \overload + + Returns what the x-coordinate of the right edge of the sprite + would be if the sprite (actually its hotspot) were moved to + x-position \a nx. + + \sa leftEdge() bottomEdge() topEdge() +*/ +int TQCanvasSprite::rightEdge(int nx) const +{ + return leftEdge(nx) + image()->width()-1; +} + +/*! + Returns the y-coordinate of the current bottom edge of the sprite. + (This may change as the sprite animates since different frames may + have different bottom edges.) + + \sa leftEdge() rightEdge() topEdge() +*/ +int TQCanvasSprite::bottomEdge() const +{ + return topEdge() + image()->height()-1; +} + +/*! + \overload + + Returns what the y-coordinate of the top edge of the sprite would + be if the sprite (actually its hotspot) were moved to y-position + \a ny. + + \sa leftEdge() rightEdge() topEdge() +*/ +int TQCanvasSprite::bottomEdge(int ny) const +{ + return topEdge(ny) + image()->height()-1; +} + +/*! + \fn TQCanvasPixmap* TQCanvasSprite::image() const + + Returns the current frame's image. + + \sa frame(), setFrame() +*/ + +/*! + \fn TQCanvasPixmap* TQCanvasSprite::image(int f) const + \overload + + Returns the image for frame \a f. Does not do any bounds checking on \a f. +*/ + +/*! + Returns the image the sprite \e will have after advance(1) is + called. By default this is the same as image(). +*/ +TQCanvasPixmap* TQCanvasSprite::imageAdvanced() const +{ + return image(); +} + +/*! + Returns the bounding rectangle for the image in the sprite's + current frame. This assumes that the images are tightly cropped + (i.e. do not have transparent pixels all along a side). +*/ +TQRect TQCanvasSprite::boundingRect() const +{ + return TQRect(leftEdge(), topEdge(), width(), height()); +} + + +/*! + \internal + Returns the chunks covered by the item. +*/ +TQPointArray TQCanvasItem::chunks() const +{ + TQPointArray r; + int n=0; + TQRect br = boundingRect(); + if (isVisible() && canvas()) { + int chunksize=canvas()->chunkSize(); + br &= TQRect(0,0,canvas()->width(),canvas()->height()); + if ( br.isValid() ) { + r.resize((br.width()/chunksize+2)*(br.height()/chunksize+2)); + for (int j=br.top()/chunksize; j<=br.bottom()/chunksize; j++) { + for (int i=br.left()/chunksize; i<=br.right()/chunksize; i++) { + r[n++] = TQPoint(i,j); + } + } + } + } + r.resize(n); + return r; +} + + +/*! + \internal + Add the sprite to the chunks in its TQCanvas which it overlaps. +*/ +void TQCanvasSprite::addToChunks() +{ + if (isVisible() && canvas()) { + int chunksize=canvas()->chunkSize(); + for (int j=topEdge()/chunksize; j<=bottomEdge()/chunksize; j++) { + for (int i=leftEdge()/chunksize; i<=rightEdge()/chunksize; i++) { + canvas()->addItemToChunk(this,i,j); + } + } + } +} + +/*! + \internal + Remove the sprite from the chunks in its TQCanvas which it overlaps. + + \sa addToChunks() +*/ +void TQCanvasSprite::removeFromChunks() +{ + if (isVisible() && canvas()) { + int chunksize=canvas()->chunkSize(); + for (int j=topEdge()/chunksize; j<=bottomEdge()/chunksize; j++) { + for (int i=leftEdge()/chunksize; i<=rightEdge()/chunksize; i++) { + canvas()->removeItemFromChunk(this,i,j); + } + } + } +} + +/*! + The width of the sprite for the current frame's image. + + \sa frame() +*/ +//### mark: Why don't we have width(int) and height(int) to be +//consistent with leftEdge() and leftEdge(int)? +int TQCanvasSprite::width() const +{ + return image()->width(); +} + +/*! + The height of the sprite for the current frame's image. + + \sa frame() +*/ +int TQCanvasSprite::height() const +{ + return image()->height(); +} + + +/*! + Draws the current frame's image at the sprite's current position + on painter \a painter. +*/ +void TQCanvasSprite::draw(TQPainter& painter) +{ + painter.drawPixmap(leftEdge(),topEdge(),*image()); +} + +/*! + \class TQCanvasView tqcanvas.h + \brief The TQCanvasView class provides an on-screen view of a TQCanvas. +\if defined(commercial) + It is part of the TQt Enterprise Edition. +\endif + + \module canvas + \ingroup graphics + \ingroup images + + A TQCanvasView is widget which provides a view of a TQCanvas. + + If you want users to be able to interact with a canvas view, + subclass TQCanvasView. You might then reimplement + TQScrollView::contentsMousePressEvent(). For example, assuming no + transformation matrix is set: + + \code + void MyCanvasView::contentsMousePressEvent( TQMouseEvent* e ) + { + TQCanvasItemList l = canvas()->collisions(e->pos()); + for (TQCanvasItemList::Iterator it=l.begin(); it!=l.end(); ++it) { + if ( (*it)->rtti() == TQCanvasRectangle::RTTI ) + tqDebug("A TQCanvasRectangle lies somewhere at this point"); + } + } + \endcode + + The canvas view shows canvas canvas(); this can be changed using + setCanvas(). + + A transformation matrix can be used to transform the view of the + canvas in various ways, for example, zooming in or out or rotating. + For example: + + \code + TQWMatrix wm; + wm.scale( 2, 2 ); // Zooms in by 2 times + wm.rotate( 90 ); // Rotates 90 degrees counter clockwise + // around the origin. + wm.translate( 0, -canvas->height() ); + // moves the canvas down so what was visible + // before is still visible. + myCanvasView->setWorldMatrix( wm ); + \endcode + + Use setWorldMatrix() to set the canvas view's world matrix: you must + ensure that the world matrix is invertible. The current world matrix + is retrievable with worldMatrix(), and its inversion is retrievable + with inverseWorldMatrix(). + + Example: + + The following code finds the part of the canvas that is visible in + this view, i.e. the bounding rectangle of the view in canvas coordinates. + + \code + TQRect rc = TQRect( myCanvasView->contentsX(), myCanvasView->contentsY(), + myCanvasView->visibleWidth(), myCanvasView->visibleHeight() ); + TQRect canvasRect = myCanvasView->inverseWorldMatrix().mapRect(rc); + \endcode + + \sa TQWMatrix TQPainter::setWorldMatrix() + +*/ + +/*! + Constructs a TQCanvasView with parent \a parent, and name \a name, + using the widget flags \a f. The canvas view is not associated + with a canvas, so you must to call setCanvas() to view a + canvas. +*/ +TQCanvasView::TQCanvasView(TQWidget* parent, const char* name, WFlags f) : + TQScrollView(parent,name,f|WResizeNoErase|WStaticContents) +{ + d = new TQCanvasViewData; + viewing = 0; + setCanvas(0); + connect(this,TQ_SIGNAL(contentsMoving(int,int)),this,TQ_SLOT(cMoving(int,int))); +} + +/*! + \overload + + Constructs a TQCanvasView which views canvas \a canvas, with parent + \a parent, and name \a name, using the widget flags \a f. +*/ +TQCanvasView::TQCanvasView(TQCanvas* canvas, TQWidget* parent, const char* name, WFlags f) : + TQScrollView(parent,name,f|WResizeNoErase|WStaticContents) +{ + d = new TQCanvasViewData; + viewing = 0; + setCanvas(canvas); + + connect(this,TQ_SIGNAL(contentsMoving(int,int)),this,TQ_SLOT(cMoving(int,int))); +} + +/*! + Destroys the canvas view. The associated canvas is \e not deleted. +*/ +TQCanvasView::~TQCanvasView() +{ + delete d; + d = 0; + setCanvas(0); +} + +/*! + \fn TQCanvas* TQCanvasView::canvas() const + + Returns a pointer to the canvas which the TQCanvasView is currently + showing. +*/ + + +/*! + Sets the canvas that the TQCanvasView is showing to the canvas \a + canvas. +*/ +void TQCanvasView::setCanvas(TQCanvas* canvas) +{ + if (viewing) { + disconnect(viewing); + viewing->removeView(this); + } + viewing=canvas; + if (viewing) { + connect(viewing,TQ_SIGNAL(resized()), this, TQ_SLOT(updateContentsSize())); + viewing->addView(this); + } + if ( d ) // called by d'tor + updateContentsSize(); +} + +#ifndef TQT_NO_TRANSFORMATIONS +/*! + Returns a reference to the canvas view's current transformation matrix. + + \sa setWorldMatrix() inverseWorldMatrix() +*/ +const TQWMatrix &TQCanvasView::worldMatrix() const +{ + return d->xform; +} + +/*! + Returns a reference to the inverse of the canvas view's current + transformation matrix. + + \sa setWorldMatrix() worldMatrix() +*/ +const TQWMatrix &TQCanvasView::inverseWorldMatrix() const +{ + return d->ixform; +} + +/*! + Sets the transformation matrix of the TQCanvasView to \a wm. The + matrix must be invertible (i.e. if you create a world matrix that + zooms out by 2 times, then the inverse of this matrix is one that + will zoom in by 2 times). + + When you use this, you should note that the performance of the + TQCanvasView will decrease considerably. + + Returns FALSE if \a wm is not invertable; otherwise returns TRUE. + + \sa worldMatrix() inverseWorldMatrix() TQWMatrix::isInvertible() +*/ +bool TQCanvasView::setWorldMatrix( const TQWMatrix & wm ) +{ + bool ok = wm.isInvertible(); + if ( ok ) { + d->xform = wm; + d->ixform = wm.invert(); + updateContentsSize(); + viewport()->update(); + } + return ok; +} +#endif + +void TQCanvasView::updateContentsSize() +{ + if ( viewing ) { + TQRect br; +#ifndef TQT_NO_TRANSFORMATIONS + br = d->xform.map(TQRect(0,0,viewing->width(),viewing->height())); +#else + br = TQRect(0,0,viewing->width(),viewing->height()); +#endif + + if ( br.width() < contentsWidth() ) { + TQRect r(contentsToViewport(TQPoint(br.width(),0)), + TQSize(contentsWidth()-br.width(),contentsHeight())); + viewport()->erase(r); + } + if ( br.height() < contentsHeight() ) { + TQRect r(contentsToViewport(TQPoint(0,br.height())), + TQSize(contentsWidth(),contentsHeight()-br.height())); + viewport()->erase(r); + } + + resizeContents(br.width(),br.height()); + } else { + viewport()->erase(); + resizeContents(1,1); + } +} + +void TQCanvasView::cMoving(int x, int y) +{ + // A little kludge to smooth up repaints when scrolling + int dx = x - contentsX(); + int dy = y - contentsY(); + d->repaint_from_moving = TQABS(dx) < width()/8 && TQABS(dy) < height()/8; +} + +/*! + Repaints part of the TQCanvas that the canvas view is showing + starting at \a cx by \a cy, with a width of \a cw and a height of \a + ch using the painter \a p. + + \warning When double buffering is enabled, drawContents() will + not respect the current settings of the painter when setting up + the painter for the double buffer (e.g., viewport() and + window()). Also, be aware that TQCanvas::update() bypasses + drawContents(), which means any reimplementation of + drawContents() is not called. + + \sa TQCanvas::setDoubleBuffering() +*/ +void TQCanvasView::drawContents(TQPainter *p, int cx, int cy, int cw, int ch) +{ + TQRect r(cx,cy,cw,ch); + if (viewing) { + //viewing->drawViewArea(this,p,r,TRUE); + viewing->drawViewArea(this,p,r,!d->repaint_from_moving); + d->repaint_from_moving = FALSE; + } else { + p->eraseRect(r); + } +} + +/*! + \reimp + \internal + + (Implemented to get rid of a compiler warning.) +*/ +void TQCanvasView::drawContents( TQPainter * ) +{ +} + +/*! + Suggests a size sufficient to view the entire canvas. +*/ +TQSize TQCanvasView::sizeHint() const +{ + if ( !canvas() ) + return TQScrollView::sizeHint(); + // should maybe take transformations into account + return ( canvas()->size() + 2 * TQSize(frameWidth(), frameWidth()) ) + .boundedTo( 3 * TQApplication::desktop()->size() / 4 ); +} + +// ### TQt 4.0 customer request: operate on doubles rather than int. +// ### I know, almost impossible due to the use of TQRegion etc. +/*! + \class TQCanvasPolygonalItem tqcanvas.h + \brief The TQCanvasPolygonalItem class provides a polygonal canvas item + on a TQCanvas. +\if defined(commercial) + It is part of the TQt Enterprise Edition. +\endif + + \module canvas + \ingroup graphics + \ingroup images + + The mostly rectangular classes, such as TQCanvasSprite and + TQCanvasText, use the object's bounding rectangle for movement, + repainting and collision calculations. For most other items, the + bounding rectangle can be far too large -- a diagonal line being + the worst case, and there are many other cases which are also bad. + TQCanvasPolygonalItem provides polygon-based bounding rectangle + handling, etc., which is much faster for non-rectangular items. + + Derived classes should try to define as small an area as possible + to maximize efficiency, but the polygon must \e definitely be + contained completely within the polygonal area. Calculating the + exact requirements is usually difficult, but if you allow a small + overestimate it can be easy and quick, while still getting almost + all of TQCanvasPolygonalItem's speed. + + Note that all subclasses \e must call hide() in their destructor + since hide() needs to be able to access areaPoints(). + + Normally, TQCanvasPolygonalItem uses the odd-even algorithm for + determining whether an object intersects this object. You can + change this to the winding algorithm using setWinding(). + + The bounding rectangle is available using boundingRect(). The + points bounding the polygonal item are retrieved with + areaPoints(). Use areaPointsAdvanced() to retrieve the bounding + points the polygonal item \e will have after + TQCanvasItem::advance(1) has been called. + + If the shape of the polygonal item is about to change while the + item is visible, call invalidate() before updating with a + different result from \l areaPoints(). + + By default, TQCanvasPolygonalItem objects have a black pen and no + brush (the default TQPen and TQBrush constructors). You can change + this with setPen() and setBrush(), but note that some + TQCanvasPolygonalItem subclasses only use the brush, ignoring the + pen setting. + + The polygonal item can be drawn on a painter with draw(). + Subclasses must reimplement drawShape() to draw themselves. + + Like any other canvas item polygonal items can be moved with + TQCanvasItem::move() and TQCanvasItem::moveBy(), or by setting coordinates + with TQCanvasItem::setX(), TQCanvasItem::setY() and TQCanvasItem::setZ(). + +*/ + + +/* + Since most polygonal items don't have a pen, the default is + NoPen and a black brush. +*/ +static const TQPen& defaultPolygonPen() +{ + static TQPen* dp=0; + if ( !dp ) + dp = new TQPen; + return *dp; +} + +static const TQBrush& defaultPolygonBrush() +{ + static TQBrush* db=0; + if ( !db ) + db = new TQBrush; + return *db; +} + +/*! + Constructs a TQCanvasPolygonalItem on the canvas \a canvas. +*/ +TQCanvasPolygonalItem::TQCanvasPolygonalItem(TQCanvas* canvas) : + TQCanvasItem(canvas), + br(defaultPolygonBrush()), + pn(defaultPolygonPen()) +{ + wind=0; +} + +/*! + Note that all subclasses \e must call hide() in their destructor + since hide() needs to be able to access areaPoints(). +*/ +TQCanvasPolygonalItem::~TQCanvasPolygonalItem() +{ +} + +/*! + Returns TRUE if the polygonal item uses the winding algorithm to + determine the "inside" of the polygon. Returns FALSE if it uses + the odd-even algorithm. + + The default is to use the odd-even algorithm. + + \sa setWinding() +*/ +bool TQCanvasPolygonalItem::winding() const +{ + return wind; +} + +/*! + If \a enable is TRUE, the polygonal item will use the winding + algorithm to determine the "inside" of the polygon; otherwise the + odd-even algorithm will be used. + + The default is to use the odd-even algorithm. + + \sa winding() +*/ +void TQCanvasPolygonalItem::setWinding(bool enable) +{ + wind = enable; +} + +/*! + Invalidates all information about the area covered by the canvas + item. The item will be updated automatically on the next call that + changes the item's status, for example, move() or update(). Call + this function if you are going to change the shape of the item (as + returned by areaPoints()) while the item is visible. +*/ +void TQCanvasPolygonalItem::invalidate() +{ + val = (uint)FALSE; + removeFromChunks(); +} + +/*! + \fn TQCanvasPolygonalItem::isValid() const + + Returns TRUE if the polygonal item's area information has not been + invalidated; otherwise returns FALSE. + + \sa invalidate() +*/ + +/*! + Returns the points the polygonal item \e will have after + TQCanvasItem::advance(1) is called, i.e. what the points are when + advanced by the current xVelocity() and yVelocity(). +*/ +TQPointArray TQCanvasPolygonalItem::areaPointsAdvanced() const +{ + int dx = int(x()+xVelocity())-int(x()); + int dy = int(y()+yVelocity())-int(y()); + TQPointArray r = areaPoints(); + r.detach(); // Explicit sharing is stupid. + if ( dx || dy ) + r.translate(dx,dy); + return r; +} + +//#define TQCANVAS_POLYGONS_DEBUG +#ifdef TQCANVAS_POLYGONS_DEBUG +static TQWidget* dbg_wid=0; +static TQPainter* dbg_ptr=0; +#endif + +class TQPolygonalProcessor { +public: + TQPolygonalProcessor(TQCanvas* c, const TQPointArray& pa) : + canvas(c) + { + TQRect pixelbounds = pa.boundingRect(); + int cs = canvas->chunkSize(); + TQRect canvasbounds = pixelbounds.intersect(canvas->rect()); + bounds.setLeft(canvasbounds.left()/cs); + bounds.setRight(canvasbounds.right()/cs); + bounds.setTop(canvasbounds.top()/cs); + bounds.setBottom(canvasbounds.bottom()/cs); + bitmap = TQImage(bounds.width() + 1, bounds.height(), 1, 2, TQImage::LittleEndian); + pnt = 0; + bitmap.fill(0); +#ifdef TQCANVAS_POLYGONS_DEBUG + dbg_start(); +#endif + } + + inline void add(int x, int y) + { + if ( pnt >= (int)result.size() ) { + result.resize(pnt*2+10); + } + result[pnt++] = TQPoint(x+bounds.x(),y+bounds.y()); +#ifdef TQCANVAS_POLYGONS_DEBUG + if ( dbg_ptr ) { + int cs = canvas->chunkSize(); + TQRect r(x*cs+bounds.x()*cs,y*cs+bounds.y()*cs,cs-1,cs-1); + dbg_ptr->setPen(TQt::blue); + dbg_ptr->drawRect(r); + } +#endif + } + + inline void addBits(int x1, int x2, uchar newbits, int xo, int yo) + { + for (int i=x1; i<=x2; i++) + if ( newbits & (1<resize(800,600); + dbg_wid->show(); + dbg_ptr = new TQPainter(dbg_wid); + dbg_ptr->setBrush(TQt::NoBrush); + } + dbg_ptr->fillRect(dbg_wid->rect(),TQt::white); + } +#endif + + void doSpans(int n, TQPoint* pt, int* w) + { + int cs = canvas->chunkSize(); + for (int j=0; j= bitmap.height() || y < 0) continue; + uchar* l = bitmap.scanLine(y); + int x = pt[j].x(); + int x1 = x/cs-bounds.x(); + if (x1 > bounds.width()) continue; + x1 = TQMAX(0,x1); + int x2 = (x+w[j])/cs-bounds.x(); + if (x2 < 0) continue; + x2 = TQMIN(bounds.width(), x2); + int x1q = x1/8; + int x1r = x1%8; + int x2q = x2/8; + int x2r = x2%8; +#ifdef TQCANVAS_POLYGONS_DEBUG + if ( dbg_ptr ) dbg_ptr->setPen(TQt::yellow); +#endif + if ( x1q == x2q ) { + uchar newbits = (~l[x1q]) & (((2<<(x2r-x1r))-1)<setPen(TQt::darkGreen); +#endif + addBits(x1r,x2r,newbits,x1q*8,y); + l[x1q] |= newbits; + } + } else { +#ifdef TQCANVAS_POLYGONS_DEBUG + if ( dbg_ptr ) dbg_ptr->setPen(TQt::blue); +#endif + uchar newbits1 = (~l[x1q]) & (0xff<setPen(TQt::green); +#endif + addBits(x1r,7,newbits1,x1q*8,y); + l[x1q] |= newbits1; + } + for (int i=x1q+1; i>(7-x2r)); + if ( newbits2 ) { +#ifdef TQCANVAS_POLYGONS_DEBUG + if ( dbg_ptr ) dbg_ptr->setPen(TQt::red); +#endif + addBits(0,x2r,newbits2,x2q*8,y); + l[x2q] |= newbits2; + } + } +#ifdef TQCANVAS_POLYGONS_DEBUG + if ( dbg_ptr ) { + dbg_ptr->drawLine(pt[j],pt[j]+TQPoint(w[j],0)); + } +#endif + } + result.resize(pnt); + } + + int pnt; + TQPointArray result; + TQCanvas* canvas; + TQRect bounds; + TQImage bitmap; +}; + + +TQPointArray TQCanvasPolygonalItem::chunks() const +{ + TQPointArray pa = areaPoints(); + + if ( !pa.size() ) { + pa.detach(); // Explicit sharing is stupid. + return pa; + } + + TQPolygonalProcessor processor(canvas(),pa); + + scanPolygon(pa, wind, processor); + + return processor.result; +} +/*! + Simply calls TQCanvasItem::chunks(). +*/ +TQPointArray TQCanvasRectangle::chunks() const +{ + // No need to do a polygon scan! + return TQCanvasItem::chunks(); +} + +/*! + Returns the bounding rectangle of the polygonal item, based on + areaPoints(). +*/ +TQRect TQCanvasPolygonalItem::boundingRect() const +{ + return areaPoints().boundingRect(); +} + +/*! + Reimplemented from TQCanvasItem, this draws the polygonal item by + setting the pen and brush for the item on the painter \a p and + calling drawShape(). +*/ +void TQCanvasPolygonalItem::draw(TQPainter & p) +{ + p.setPen(pn); + p.setBrush(br); + drawShape(p); +} + +/*! + \fn void TQCanvasPolygonalItem::drawShape(TQPainter & p) + + Subclasses must reimplement this function to draw their shape. The + pen and brush of \a p are already set to pen() and brush() prior + to calling this function. + + \warning When you reimplement this function, make sure that you + leave the painter in the same state as you found it. For example, + if you start by calling TQPainter::translate(50, 50), end your + code by calling TQPainter::translate(-50, -50). Be also aware that + the painter might already have some transformations set (i.e., + don't call TQPainter::resetXForm() when you're done). + + \sa draw() +*/ + +/*! + \fn TQPen TQCanvasPolygonalItem::pen() const + + Returns the TQPen used to draw the outline of the item, if any. + + \sa setPen() +*/ + +/*! + \fn TQBrush TQCanvasPolygonalItem::brush() const + + Returns the TQBrush used to fill the item, if filled. + + \sa setBrush() +*/ + +/*! + Sets the TQPen used when drawing the item to the pen \a p. + Note that many TQCanvasPolygonalItems do not use the pen value. + + \sa setBrush(), pen(), drawShape() +*/ +void TQCanvasPolygonalItem::setPen(TQPen p) +{ + if ( pn != p ) { + removeFromChunks(); + pn = p; + addToChunks(); + } +} + +/*! + Sets the TQBrush used when drawing the polygonal item to the brush \a b. + + \sa setPen(), brush(), drawShape() +*/ +void TQCanvasPolygonalItem::setBrush(TQBrush b) +{ + if ( br != b) { + br = b; + changeChunks(); + } +} + + +/*! + \class TQCanvasPolygon tqcanvas.h + \brief The TQCanvasPolygon class provides a polygon on a TQCanvas. +\if defined(commercial) + It is part of the TQt Enterprise Edition. +\endif + + \module canvas + \ingroup graphics + \ingroup images + + Paints a polygon with a TQBrush. The polygon's points can be set in + the constructor or set or changed later using setPoints(). Use + points() to retrieve the points, or areaPoints() to retrieve the + points relative to the canvas's origin. + + The polygon can be drawn on a painter with drawShape(). + + Like any other canvas item polygons can be moved with + TQCanvasItem::move() and TQCanvasItem::moveBy(), or by setting + coordinates with TQCanvasItem::setX(), TQCanvasItem::setY() and + TQCanvasItem::setZ(). + + Note: TQCanvasPolygon does not use the pen. +*/ + +/*! + Constructs a point-less polygon on the canvas \a canvas. You + should call setPoints() before using it further. +*/ +TQCanvasPolygon::TQCanvasPolygon(TQCanvas* canvas) : + TQCanvasPolygonalItem(canvas) +{ +} + +/*! + Destroys the polygon. +*/ +TQCanvasPolygon::~TQCanvasPolygon() +{ + hide(); +} + +/*! + Draws the polygon using the painter \a p. + + Note that TQCanvasPolygon does not support an outline (the pen is + always NoPen). +*/ +void TQCanvasPolygon::drawShape(TQPainter & p) +{ + // ### why can't we draw outlines? We could use drawPolyline for it. Lars + // ### see other message. Warwick + + p.setPen(NoPen); // since TQRegion(TQPointArray) excludes outline :-( )-: + p.drawPolygon(poly); +} + +/*! + Sets the points of the polygon to be \a pa. These points will have + their x and y coordinates automatically translated by x(), y() as + the polygon is moved. +*/ +void TQCanvasPolygon::setPoints(TQPointArray pa) +{ + removeFromChunks(); + poly = pa; + poly.detach(); // Explicit sharing is stupid. + poly.translate((int)x(),(int)y()); + addToChunks(); +} + +/*! + \reimp +*/ +void TQCanvasPolygon::moveBy(double dx, double dy) +{ + // Note: does NOT call TQCanvasPolygonalItem::moveBy(), since that + // only does half this work. + // + int idx = int(x()+dx)-int(x()); + int idy = int(y()+dy)-int(y()); + if ( idx || idy ) { + removeFromChunks(); + poly.translate(idx,idy); + } + myx+=dx; + myy+=dy; + if ( idx || idy ) { + addToChunks(); + } +} + +/*! + \class TQCanvasSpline tqcanvas.h + \brief The TQCanvasSpline class provides multi-bezier splines on a TQCanvas. +\if defined(commercial) + It is part of the TQt Enterprise Edition. +\endif + + \module canvas + \ingroup graphics + \ingroup images + + A TQCanvasSpline is a sequence of 4-point bezier curves joined + together to make a curved shape. + + You set the control points of the spline with setControlPoints(). + + If the bezier is closed(), then the first control point will be + re-used as the last control point. Therefore, a closed bezier must + have a multiple of 3 control points and an open bezier must have + one extra point. + + The beziers are not necessarily joined "smoothly". To ensure this, + set control points appropriately (general reference texts about + beziers will explain this in detail). + + Like any other canvas item splines can be moved with + TQCanvasItem::move() and TQCanvasItem::moveBy(), or by setting + coordinates with TQCanvasItem::setX(), TQCanvasItem::setY() and + TQCanvasItem::setZ(). + +*/ + +/*! + Create a spline with no control points on the canvas \a canvas. + + \sa setControlPoints() +*/ +TQCanvasSpline::TQCanvasSpline(TQCanvas* canvas) : + TQCanvasPolygon(canvas), + cl(TRUE) +{ +} + +/*! + Destroy the spline. +*/ +TQCanvasSpline::~TQCanvasSpline() +{ +} + +// ### shouldn't we handle errors more gracefully than with an assert? Lars +// ### no, since it's a programming error. Warwick +/*! + Set the spline control points to \a ctrl. + + If \a close is TRUE, then the first point in \a ctrl will be + re-used as the last point, and the number of control points must + be a multiple of 3. If \a close is FALSE, one additional control + point is required, and the number of control points must be one of + (4, 7, 10, 13, ...). + + If the number of control points doesn't meet the above conditions, + the number of points will be truncated to the largest number of + points that do meet the requirement. +*/ +void TQCanvasSpline::setControlPoints(TQPointArray ctrl, bool close) +{ + if ( (int)ctrl.count() % 3 != (close ? 0 : 1) ) { + tqWarning( "TQCanvasSpline::setControlPoints(): Number of points doesn't fit." ); + int numCurves = (ctrl.count() - (close ? 0 : 1 ))/ 3; + ctrl.resize( numCurves*3 + ( close ? 0 : 1 ) ); + } + + cl = close; + bez = ctrl; + recalcPoly(); +} + +/*! + Returns the current set of control points. + + \sa setControlPoints(), closed() +*/ +TQPointArray TQCanvasSpline::controlPoints() const +{ + return bez; +} + +/*! + Returns TRUE if the control points are a closed set; otherwise + returns FALSE. +*/ +bool TQCanvasSpline::closed() const +{ + return cl; +} + +void TQCanvasSpline::recalcPoly() +{ + TQPtrList segs; + segs.setAutoDelete(TRUE); + int n=0; + for (int i=0; i<(int)bez.count()-1; i+=3) { + TQPointArray ctrl(4); + ctrl[0] = bez[i+0]; + ctrl[1] = bez[i+1]; + ctrl[2] = bez[i+2]; + if ( cl ) + ctrl[3] = bez[(i+3)%(int)bez.count()]; + else + ctrl[3] = bez[i+3]; + TQPointArray *seg = new TQPointArray(ctrl.cubicBezier()); + n += seg->count()-1; + segs.append(seg); + } + TQPointArray p(n+1); + n=0; + for (TQPointArray* seg = segs.first(); seg; seg = segs.next()) { + for (int i=0; i<(int)seg->count()-1; i++) + p[n++] = seg->point(i); + if ( n == (int)p.count()-1 ) + p[n] = seg->point(seg->count()-1); + } + TQCanvasPolygon::setPoints(p); +} + +/*! + \fn TQPointArray TQCanvasPolygonalItem::areaPoints() const + + This function must be reimplemented by subclasses. It \e must + return the points bounding (i.e. outside and not touching) the + shape or drawing errors will occur. +*/ + +/*! + \fn TQPointArray TQCanvasPolygon::points() const + + Returns the vertices of the polygon, not translated by the position. + + \sa setPoints(), areaPoints() +*/ +TQPointArray TQCanvasPolygon::points() const +{ + TQPointArray pa = areaPoints(); + pa.translate(int(-x()),int(-y())); + return pa; +} + +/*! + Returns the vertices of the polygon translated by the polygon's + current x(), y() position, i.e. relative to the canvas's origin. + + \sa setPoints(), points() +*/ +TQPointArray TQCanvasPolygon::areaPoints() const +{ + return poly.copy(); +} + +// ### mark: Why don't we offer a constructor that lets the user set the +// points -- that way for some uses just the constructor call would be +// required? +/*! + \class TQCanvasLine tqcanvas.h + \brief The TQCanvasLine class provides a line on a TQCanvas. +\if defined(commercial) + It is part of the TQt Enterprise Edition. +\endif + + \module canvas + \ingroup graphics + \ingroup images + + The line inherits functionality from TQCanvasPolygonalItem, for + example the setPen() function. The start and end points of the + line are set with setPoints(). + + Like any other canvas item lines can be moved with + TQCanvasItem::move() and TQCanvasItem::moveBy(), or by setting + coordinates with TQCanvasItem::setX(), TQCanvasItem::setY() and + TQCanvasItem::setZ(). +*/ + +/*! + Constructs a line from (0,0) to (0,0) on \a canvas. + + \sa setPoints(). +*/ +TQCanvasLine::TQCanvasLine(TQCanvas* canvas) : + TQCanvasPolygonalItem(canvas) +{ + x1 = y1 = x2 = y2 = 0; +} + +/*! + Destroys the line. +*/ +TQCanvasLine::~TQCanvasLine() +{ + hide(); +} + +/*! + \reimp +*/ +void TQCanvasLine::setPen(TQPen p) +{ + TQCanvasPolygonalItem::setPen(p); +} + +/*! + \fn TQPoint TQCanvasLine::startPoint () const + + Returns the start point of the line. + + \sa setPoints(), endPoint() +*/ + +/*! + \fn TQPoint TQCanvasLine::endPoint () const + + Returns the end point of the line. + + \sa setPoints(), startPoint() +*/ + +/*! + Sets the line's start point to (\a xa, \a ya) and its end point to + (\a xb, \a yb). +*/ +void TQCanvasLine::setPoints(int xa, int ya, int xb, int yb) +{ + if ( x1 != xa || x2 != xb || y1 != ya || y2 != yb ) { + removeFromChunks(); + x1 = xa; + y1 = ya; + x2 = xb; + y2 = yb; + addToChunks(); + } +} + +/*! + \reimp +*/ +void TQCanvasLine::drawShape(TQPainter &p) +{ + p.drawLine((int)(x()+x1), (int)(y()+y1), (int)(x()+x2), (int)(y()+y2)); +} + +/*! + \reimp + + Note that the area defined by the line is somewhat thicker than + the line that is actually drawn. +*/ +TQPointArray TQCanvasLine::areaPoints() const +{ + TQPointArray p(4); + int xi = int(x()); + int yi = int(y()); + int pw = pen().width(); + int dx = TQABS(x1-x2); + int dy = TQABS(y1-y2); + pw = pw*4/3+2; // approx pw*sqrt(2) + int px = x1 dy ? (dx*2/dy <= 2) : (dy*2/dx <= 2)) ) { + // steep + if ( px == py ) { + p[0] = TQPoint(x1+xi ,y1+yi+py); + p[1] = TQPoint(x2+xi-px,y2+yi ); + p[2] = TQPoint(x2+xi ,y2+yi-py); + p[3] = TQPoint(x1+xi+px,y1+yi ); + } else { + p[0] = TQPoint(x1+xi+px,y1+yi ); + p[1] = TQPoint(x2+xi ,y2+yi-py); + p[2] = TQPoint(x2+xi-px,y2+yi ); + p[3] = TQPoint(x1+xi ,y1+yi+py); + } + } else if ( dx > dy ) { + // horizontal + p[0] = TQPoint(x1+xi+px,y1+yi+py); + p[1] = TQPoint(x2+xi-px,y2+yi+py); + p[2] = TQPoint(x2+xi-px,y2+yi-py); + p[3] = TQPoint(x1+xi+px,y1+yi-py); + } else { + // vertical + p[0] = TQPoint(x1+xi+px,y1+yi+py); + p[1] = TQPoint(x2+xi+px,y2+yi-py); + p[2] = TQPoint(x2+xi-px,y2+yi-py); + p[3] = TQPoint(x1+xi-px,y1+yi+py); + } + return p; +} + +/*! + \reimp + +*/ + +void TQCanvasLine::moveBy(double dx, double dy) +{ + TQCanvasPolygonalItem::moveBy(dx, dy); +} + +/*! + \class TQCanvasRectangle tqcanvas.h + \brief The TQCanvasRectangle class provides a rectangle on a TQCanvas. +\if defined(commercial) + It is part of the TQt Enterprise Edition. +\endif + + \module canvas + \ingroup graphics + \ingroup images + + This item paints a single rectangle which may have any pen() and + brush(), but may not be tilted/rotated. For rotated rectangles, + use TQCanvasPolygon. + + The rectangle's size and initial position can be set in the + constructor. The size can be set or changed later using setSize(). + Use height() and width() to retrieve the rectangle's dimensions. + + The rectangle can be drawn on a painter with drawShape(). + + Like any other canvas item rectangles can be moved with + TQCanvasItem::move() and TQCanvasItem::moveBy(), or by setting + coordinates with TQCanvasItem::setX(), TQCanvasItem::setY() and + TQCanvasItem::setZ(). + +*/ + +/*! + Constructs a rectangle at position (0,0) with both width and + height set to 32 pixels on \a canvas. +*/ +TQCanvasRectangle::TQCanvasRectangle(TQCanvas* canvas) : + TQCanvasPolygonalItem(canvas), + w(32), h(32) +{ +} + +/*! + Constructs a rectangle positioned and sized by \a r on \a canvas. +*/ +TQCanvasRectangle::TQCanvasRectangle(const TQRect& r, TQCanvas* canvas) : + TQCanvasPolygonalItem(canvas), + w(r.width()), h(r.height()) +{ + move(r.x(),r.y()); +} + +/*! + Constructs a rectangle at position (\a x, \a y) and size \a width + by \a height, on \a canvas. +*/ +TQCanvasRectangle::TQCanvasRectangle(int x, int y, int width, int height, + TQCanvas* canvas) : + TQCanvasPolygonalItem(canvas), + w(width), h(height) +{ + move(x,y); +} + +/*! + Destroys the rectangle. +*/ +TQCanvasRectangle::~TQCanvasRectangle() +{ + hide(); +} + + +/*! + Returns the width of the rectangle. +*/ +int TQCanvasRectangle::width() const +{ + return w; +} + +/*! + Returns the height of the rectangle. +*/ +int TQCanvasRectangle::height() const +{ + return h; +} + +/*! + Sets the \a width and \a height of the rectangle. +*/ +void TQCanvasRectangle::setSize(int width, int height) +{ + if ( w != width || h != height ) { + removeFromChunks(); + w = width; + h = height; + addToChunks(); + } +} + +/*! + \fn TQSize TQCanvasRectangle::size() const + + Returns the width() and height() of the rectangle. + + \sa rect(), setSize() +*/ + +/*! + \fn TQRect TQCanvasRectangle::rect() const + + Returns the integer-converted x(), y() position and size() of the + rectangle as a TQRect. +*/ + +/*! + \reimp +*/ +TQPointArray TQCanvasRectangle::areaPoints() const +{ + TQPointArray pa(4); + int pw = (pen().width()+1)/2; + if ( pw < 1 ) pw = 1; + if ( pen() == NoPen ) pw = 0; + pa[0] = TQPoint((int)x()-pw,(int)y()-pw); + pa[1] = pa[0] + TQPoint(w+pw*2,0); + pa[2] = pa[1] + TQPoint(0,h+pw*2); + pa[3] = pa[0] + TQPoint(0,h+pw*2); + return pa; +} + +/*! + Draws the rectangle on painter \a p. +*/ +void TQCanvasRectangle::drawShape(TQPainter & p) +{ + p.drawRect((int)x(), (int)y(), w, h); +} + + +/*! + \class TQCanvasEllipse tqcanvas.h + \brief The TQCanvasEllipse class provides an ellipse or ellipse segment on a TQCanvas. +\if defined(commercial) + It is part of the TQt Enterprise Edition. +\endif + + \module canvas + \ingroup graphics + \ingroup images + + A canvas item that paints an ellipse or ellipse segment with a TQBrush. + The ellipse's height, width, start angle and angle length can be set + at construction time. The size can be changed at runtime with + setSize(), and the angles can be changed (if you're displaying an + ellipse segment rather than a whole ellipse) with setAngles(). + + Note that angles are specified in 16ths of a degree. + + \target anglediagram + \img tqcanvasellipse.png Ellipse + + If a start angle and length angle are set then an ellipse segment + will be drawn. The start angle is the angle that goes from zero in a + counter-clockwise direction (shown in green in the diagram). The + length angle is the angle from the start angle in a + counter-clockwise direction (shown in blue in the diagram). The blue + segment is the segment of the ellipse that would be drawn. If no + start angle and length angle are specified the entire ellipse is + drawn. + + The ellipse can be drawn on a painter with drawShape(). + + Like any other canvas item ellipses can be moved with move() and + moveBy(), or by setting coordinates with setX(), setY() and setZ(). + + Note: TQCanvasEllipse does not use the pen. +*/ + +/*! + Constructs a 32x32 ellipse, centered at (0, 0) on \a canvas. +*/ +TQCanvasEllipse::TQCanvasEllipse(TQCanvas* canvas) : + TQCanvasPolygonalItem(canvas), + w(32), h(32), + a1(0), a2(360*16) +{ +} + +/*! + Constructs a \a width by \a height pixel ellipse, centered at + (0, 0) on \a canvas. +*/ +TQCanvasEllipse::TQCanvasEllipse(int width, int height, TQCanvas* canvas) : + TQCanvasPolygonalItem(canvas), + w(width),h(height), + a1(0),a2(360*16) +{ +} + +// ### add a constructor taking degrees in float. 1/16 degrees is stupid. Lars +// ### it's how TQPainter does it, so TQCanvas does too for consistency. If it's +// ### a good idea, it should be added to TQPainter, not just to TQCanvas. Warwick +/*! + Constructs a \a width by \a height pixel ellipse, centered at + (0, 0) on \a canvas. Only a segment of the ellipse is drawn, + starting at angle \a startangle, and extending for angle \a angle + (the angle length). + + Note that angles are specified in + 1/16ths of a degree. +*/ +TQCanvasEllipse::TQCanvasEllipse(int width, int height, + int startangle, int angle, TQCanvas* canvas) : + TQCanvasPolygonalItem(canvas), + w(width),h(height), + a1(startangle),a2(angle) +{ +} + +/*! + Destroys the ellipse. +*/ +TQCanvasEllipse::~TQCanvasEllipse() +{ + hide(); +} + +/*! + Returns the width of the ellipse. +*/ +int TQCanvasEllipse::width() const +{ + return w; +} + +/*! + Returns the height of the ellipse. +*/ +int TQCanvasEllipse::height() const +{ + return h; +} + +/*! + Sets the \a width and \a height of the ellipse. +*/ +void TQCanvasEllipse::setSize(int width, int height) +{ + if ( w != width || h != height ) { + removeFromChunks(); + w = width; + h = height; + addToChunks(); + } +} + +/*! + \fn int TQCanvasEllipse::angleStart() const + + Returns the start angle in 16ths of a degree. Initially + this will be 0. + + \sa setAngles(), angleLength() +*/ + +/*! + \fn int TQCanvasEllipse::angleLength() const + + Returns the length angle (the extent of the ellipse segment) in + 16ths of a degree. Initially this will be 360 * 16 (a complete + ellipse). + + \sa setAngles(), angleStart() +*/ + +/*! + Sets the angles for the ellipse. The start angle is \a start and + the extent of the segment is \a length (the angle length) from the + \a start. The angles are specified in 16ths of a degree. By + default the ellipse will start at 0 and have an angle length of + 360 * 16 (a complete ellipse). + + \sa angleStart(), angleLength() +*/ +void TQCanvasEllipse::setAngles(int start, int length) +{ + if ( a1 != start || a2 != length ) { + removeFromChunks(); + a1 = start; + a2 = length; + addToChunks(); + } +} + +/*! + \reimp +*/ +TQPointArray TQCanvasEllipse::areaPoints() const +{ + TQPointArray r; + // makeArc at 0,0, then translate so that fixed point math doesn't overflow + r.makeArc(int(x()-w/2.0+0.5)-1, int(y()-h/2.0+0.5)-1, w+3, h+3, a1, a2); + r.resize(r.size()+1); + r.setPoint(r.size()-1,int(x()),int(y())); + return r; +} + +// ### support outlines! Lars +// ### TQRegion doesn't, so we cannot (try it). Warwick +/*! + Draws the ellipse, centered at x(), y() using the painter \a p. + + Note that TQCanvasEllipse does not support an outline (the pen is + always NoPen). +*/ +void TQCanvasEllipse::drawShape(TQPainter & p) +{ + p.setPen(NoPen); // since TQRegion(TQPointArray) excludes outline :-( )-: + if ( !a1 && a2 == 360*16 ) { + p.drawEllipse(int(x()-w/2.0+0.5), int(y()-h/2.0+0.5), w, h); + } else { + p.drawPie(int(x()-w/2.0+0.5), int(y()-h/2.0+0.5), w, h, a1, a2); + } +} + + +/*! + \class TQCanvasText tqcanvas.h + \brief The TQCanvasText class provides a text object on a TQCanvas. +\if defined(commercial) + It is part of the TQt Enterprise Edition. +\endif + + \module canvas + \ingroup graphics + \ingroup images + + A canvas text item has text with font, color and alignment + attributes. The text and font can be set in the constructor or set + or changed later with setText() and setFont(). The color is set + with setColor() and the alignment with setTextFlags(). The text + item's bounding rectangle is retrieved with boundingRect(). + + The text can be drawn on a painter with draw(). + + Like any other canvas item text items can be moved with + TQCanvasItem::move() and TQCanvasItem::moveBy(), or by setting + coordinates with TQCanvasItem::setX(), TQCanvasItem::setY() and + TQCanvasItem::setZ(). +*/ + +/*! + Constructs a TQCanvasText with the text "\", on \a canvas. +*/ +TQCanvasText::TQCanvasText(TQCanvas* canvas) : + TQCanvasItem(canvas), + txt(""), flags(0) +{ + setRect(); +} + +// ### add textflags to the constructor? Lars +/*! + Constructs a TQCanvasText with the text \a t, on canvas \a canvas. +*/ +TQCanvasText::TQCanvasText(const TQString& t, TQCanvas* canvas) : + TQCanvasItem(canvas), + txt(t), flags(0) +{ + setRect(); +} + +// ### see above +/*! + Constructs a TQCanvasText with the text \a t and font \a f, on the + canvas \a canvas. +*/ +TQCanvasText::TQCanvasText(const TQString& t, TQFont f, TQCanvas* canvas) : + TQCanvasItem(canvas), + txt(t), flags(0), + fnt(f) +{ + setRect(); +} + +/*! + Destroys the canvas text item. +*/ +TQCanvasText::~TQCanvasText() +{ + removeFromChunks(); +} + +/*! + Returns the bounding rectangle of the text. +*/ +TQRect TQCanvasText::boundingRect() const { return brect; } + +void TQCanvasText::setRect() +{ + brect = TQFontMetrics(fnt).boundingRect(int(x()), int(y()), 0, 0, flags, txt); + brect.setWidth(brect.width()+1); +} + +/*! + \fn int TQCanvasText::textFlags() const + + Returns the currently set alignment flags. + + \sa setTextFlags() TQt::AlignmentFlags +*/ + + +/*! + Sets the alignment flags to \a f. These are a bitwise OR of the + flags available to TQPainter::drawText() -- see the + \l{TQt::AlignmentFlags}. + + \sa setFont() setColor() +*/ +void TQCanvasText::setTextFlags(int f) +{ + if ( flags != f ) { + removeFromChunks(); + flags = f; + setRect(); + addToChunks(); + } +} + +/*! + Returns the text item's text. + + \sa setText() +*/ +TQString TQCanvasText::text() const +{ + return txt; +} + + +/*! + Sets the text item's text to \a t. The text may contain newlines. + + \sa text(), setFont(), setColor() setTextFlags() +*/ +void TQCanvasText::setText( const TQString& t ) +{ + if ( txt != t ) { + removeFromChunks(); + txt = t; + setRect(); + addToChunks(); + } +} + +/*! + Returns the font in which the text is drawn. + + \sa setFont() +*/ +TQFont TQCanvasText::font() const +{ + return fnt; +} + +/*! + Sets the font in which the text is drawn to font \a f. + + \sa font() +*/ +void TQCanvasText::setFont( const TQFont& f ) +{ + if ( f != fnt ) { + removeFromChunks(); + fnt = f; + setRect(); + addToChunks(); + } +} + +/*! + Returns the color of the text. + + \sa setColor() +*/ +TQColor TQCanvasText::color() const +{ + return col; +} + +/*! + Sets the color of the text to the color \a c. + + \sa color(), setFont() +*/ +void TQCanvasText::setColor(const TQColor& c) +{ + col=c; + changeChunks(); +} + + +/*! + \reimp +*/ +void TQCanvasText::moveBy(double dx, double dy) +{ + int idx = int(x()+dx)-int(x()); + int idy = int(y()+dy)-int(y()); + if ( idx || idy ) { + removeFromChunks(); + } + myx+=dx; + myy+=dy; + if ( idx || idy ) { + brect.moveBy(idx,idy); + addToChunks(); + } +} + +/*! + Draws the text using the painter \a painter. +*/ +void TQCanvasText::draw(TQPainter& painter) +{ + painter.setFont(fnt); + painter.setPen(col); + painter.drawText(brect, flags, txt); +} + +/*! + \reimp +*/ +void TQCanvasText::changeChunks() +{ + if (isVisible() && canvas()) { + int chunksize=canvas()->chunkSize(); + for (int j=brect.top()/chunksize; j<=brect.bottom()/chunksize; j++) { + for (int i=brect.left()/chunksize; i<=brect.right()/chunksize; i++) { + canvas()->setChangedChunk(i,j); + } + } + } +} + +/*! + Adds the text item to the appropriate chunks. +*/ +void TQCanvasText::addToChunks() +{ + if (isVisible() && canvas()) { + int chunksize=canvas()->chunkSize(); + for (int j=brect.top()/chunksize; j<=brect.bottom()/chunksize; j++) { + for (int i=brect.left()/chunksize; i<=brect.right()/chunksize; i++) { + canvas()->addItemToChunk(this,i,j); + } + } + } +} + +/*! + Removes the text item from the appropriate chunks. +*/ +void TQCanvasText::removeFromChunks() +{ + if (isVisible() && canvas()) { + int chunksize=canvas()->chunkSize(); + for (int j=brect.top()/chunksize; j<=brect.bottom()/chunksize; j++) { + for (int i=brect.left()/chunksize; i<=brect.right()/chunksize; i++) { + canvas()->removeItemFromChunk(this,i,j); + } + } + } +} + + +/*! + Returns 0 (TQCanvasItem::Rtti_Item). + + Make your derived classes return their own values for rtti(), so + that you can distinguish between objects returned by + TQCanvas::at(). You should use values greater than 1000 to allow + for extensions to this class. + + Overuse of this functionality can damage it's extensibility. For + example, once you have identified a base class of a TQCanvasItem + found by TQCanvas::at(), cast it to that type and call meaningful + methods rather than acting upon the object based on its rtti + value. + + For example: + + \code + TQCanvasItem* item; + // Find an item, e.g. with TQCanvasItem::collisions(). + ... + if (item->rtti() == MySprite::RTTI ) { + MySprite* s = (MySprite*)item; + if (s->isDamagable()) s->loseHitPoints(1000); + if (s->isHot()) myself->loseHitPoints(1000); + ... + } + \endcode +*/ +int TQCanvasItem::rtti() const { return RTTI; } +int TQCanvasItem::RTTI = Rtti_Item; + +/*! + Returns 1 (TQCanvasItem::Rtti_Sprite). + + \sa TQCanvasItem::rtti() +*/ +int TQCanvasSprite::rtti() const { return RTTI; } +int TQCanvasSprite::RTTI = Rtti_Sprite; + +/*! + Returns 2 (TQCanvasItem::Rtti_PolygonalItem). + + \sa TQCanvasItem::rtti() +*/ +int TQCanvasPolygonalItem::rtti() const { return RTTI; } +int TQCanvasPolygonalItem::RTTI = Rtti_PolygonalItem; + +/*! + Returns 3 (TQCanvasItem::Rtti_Text). + + \sa TQCanvasItem::rtti() +*/ +int TQCanvasText::rtti() const { return RTTI; } +int TQCanvasText::RTTI = Rtti_Text; + +/*! + Returns 4 (TQCanvasItem::Rtti_Polygon). + + \sa TQCanvasItem::rtti() +*/ +int TQCanvasPolygon::rtti() const { return RTTI; } +int TQCanvasPolygon::RTTI = Rtti_Polygon; + +/*! + Returns 5 (TQCanvasItem::Rtti_Rectangle). + + \sa TQCanvasItem::rtti() +*/ +int TQCanvasRectangle::rtti() const { return RTTI; } +int TQCanvasRectangle::RTTI = Rtti_Rectangle; + +/*! + Returns 6 (TQCanvasItem::Rtti_Ellipse). + + \sa TQCanvasItem::rtti() +*/ +int TQCanvasEllipse::rtti() const { return RTTI; } +int TQCanvasEllipse::RTTI = Rtti_Ellipse; + +/*! + Returns 7 (TQCanvasItem::Rtti_Line). + + \sa TQCanvasItem::rtti() +*/ +int TQCanvasLine::rtti() const { return RTTI; } +int TQCanvasLine::RTTI = Rtti_Line; + +/*! + Returns 8 (TQCanvasItem::Rtti_Spline). + + \sa TQCanvasItem::rtti() +*/ +int TQCanvasSpline::rtti() const { return RTTI; } +int TQCanvasSpline::RTTI = Rtti_Spline; + +/*! + Constructs a TQCanvasSprite which uses images from the + TQCanvasPixmapArray \a a. + + The sprite in initially positioned at (0, 0) on \a canvas, using + frame 0. +*/ +TQCanvasSprite::TQCanvasSprite(TQCanvasPixmapArray* a, TQCanvas* canvas) : + TQCanvasItem(canvas), + frm(0), + anim_val(0), + anim_state(0), + anim_type(0), + images(a) +{ +} + + +/*! + Set the array of images used for displaying the sprite to the + TQCanvasPixmapArray \a a. + + If the current frame() is larger than the number of images in \a + a, the current frame will be reset to 0. +*/ +void TQCanvasSprite::setSequence(TQCanvasPixmapArray* a) +{ + bool isvisible = isVisible(); + if ( isvisible && images ) + hide(); + images = a; + if ( frm >= (int)images->count() ) + frm = 0; + if ( isvisible ) + show(); +} + +/*! +\internal + +Marks any chunks the sprite touches as changed. +*/ +void TQCanvasSprite::changeChunks() +{ + if (isVisible() && canvas()) { + int chunksize=canvas()->chunkSize(); + for (int j=topEdge()/chunksize; j<=bottomEdge()/chunksize; j++) { + for (int i=leftEdge()/chunksize; i<=rightEdge()/chunksize; i++) { + canvas()->setChangedChunk(i,j); + } + } + } +} + +/*! + Destroys the sprite and removes it from the canvas. Does \e not + delete the images. +*/ +TQCanvasSprite::~TQCanvasSprite() +{ + removeFromChunks(); +} + +/*! + Sets the animation frame used for displaying the sprite to \a f, + an index into the TQCanvasSprite's TQCanvasPixmapArray. The call + will be ignored if \a f is larger than frameCount() or smaller + than 0. + + \sa frame() move() +*/ +void TQCanvasSprite::setFrame(int f) +{ + move(x(),y(),f); +} + +/*! + \enum TQCanvasSprite::FrameAnimationType + + This enum is used to identify the different types of frame + animation offered by TQCanvasSprite. + + \value Cycle at each advance the frame number will be incremented by + 1 (modulo the frame count). + \value Oscillate at each advance the frame number will be + incremented by 1 up to the frame count then decremented to by 1 to + 0, repeating this sequence forever. +*/ + +/*! + Sets the animation characteristics for the sprite. + + For \a type == \c Cycle, the frames will increase by \a step + at each advance, modulo the frameCount(). + + For \a type == \c Oscillate, the frames will increase by \a step + at each advance, up to the frameCount(), then decrease by \a step + back to 0, repeating forever. + + The \a state parameter is for internal use. +*/ +void TQCanvasSprite::setFrameAnimation(FrameAnimationType type, int step, int state) +{ + anim_val = step; + anim_type = type; + anim_state = state; + setAnimated(TRUE); +} + +/*! + Extends the default TQCanvasItem implementation to provide the + functionality of setFrameAnimation(). + + The \a phase is 0 or 1: see TQCanvasItem::advance() for details. + + \sa TQCanvasItem::advance() setVelocity() +*/ +void TQCanvasSprite::advance(int phase) +{ + if ( phase==1 ) { + int nf = frame(); + if ( anim_type == Oscillate ) { + if ( anim_state ) + nf += anim_val; + else + nf -= anim_val; + if ( nf < 0 ) { + nf = abs(anim_val); + anim_state = !anim_state; + } else if ( nf >= frameCount() ) { + nf = frameCount()-1-abs(anim_val); + anim_state = !anim_state; + } + } else { + nf = (nf + anim_val + frameCount()) % frameCount(); + } + move(x()+xVelocity(),y()+yVelocity(),nf); + } +} + + +/*! + \fn int TQCanvasSprite::frame() const + + Returns the index of the current animation frame in the + TQCanvasSprite's TQCanvasPixmapArray. + + \sa setFrame(), move() +*/ + +/*! + \fn int TQCanvasSprite::frameCount() const + + Returns the number of frames in the TQCanvasSprite's + TQCanvasPixmapArray. +*/ + + +/*! + \reimp + \internal + Moves the sprite to the position \a x, \a y. + Keep it visible. +*/ +void TQCanvasSprite::move(double x, double y) { TQCanvasItem::move(x,y); } + +/*! + \fn void TQCanvasSprite::move(double nx, double ny, int nf) + + Set the position of the sprite to \a nx, \a ny and the current + frame to \a nf. \a nf will be ignored if it is larger than + frameCount() or smaller than 0. +*/ +void TQCanvasSprite::move(double nx, double ny, int nf) +{ + if (isVisible() && canvas()) { + hide(); + TQCanvasItem::move(nx,ny); + if ( nf >= 0 && nf < frameCount() ) + frm=nf; + show(); + } else { + TQCanvasItem::move(nx,ny); + if ( nf >= 0 && nf < frameCount() ) + frm=nf; + } +} + +class TQCanvasPolygonScanner : public TQPolygonScanner { + TQPolygonalProcessor& processor; +public: + TQCanvasPolygonScanner(TQPolygonalProcessor& p) : + processor(p) + { + } + void processSpans( int n, TQPoint* point, int* width ) + { + processor.doSpans(n,point,width); + } +}; + +void TQCanvasPolygonalItem::scanPolygon(const TQPointArray& pa, int winding, TQPolygonalProcessor& process) const +{ + TQCanvasPolygonScanner scanner(process); + scanner.scan(pa,winding); +} + + +#endif // TQT_NO_CANVAS diff --git a/src/canvas/tqcanvas.h b/src/canvas/tqcanvas.h new file mode 100644 index 000000000..9bf3d729c --- /dev/null +++ b/src/canvas/tqcanvas.h @@ -0,0 +1,816 @@ +/********************************************************************** +** +** Definition of TQCanvas classes +** +** Created : 991211 +** +** Copyright (C) 1999-2008 Trolltech ASA. All rights reserved. +** +** This file is part of the canvas module of the TQt GUI Toolkit. +** +** This file may be used under the terms of the GNU General +** Public License versions 2.0 or 3.0 as published by the Free +** Software Foundation and appearing in the files LICENSE.GPL2 +** and LICENSE.GPL3 included in the packaging of this file. +** Alternatively you may (at your option) use any later version +** of the GNU General Public License if such license has been +** publicly approved by Trolltech ASA (or its successors, if any) +** and the KDE Free TQt Foundation. +** +** Please review the following information to ensure GNU General +** Public Licensing requirements will be met: +** http://trolltech.com/products/qt/licenses/licensing/opensource/. +** If you are unsure which license is appropriate for your use, please +** review the following information: +** http://trolltech.com/products/qt/licenses/licensing/licensingoverview +** or contact the sales department at sales@trolltech.com. +** +** This file may be used under the terms of the Q Public License as +** defined by Trolltech ASA and appearing in the file LICENSE.TQPL +** included in the packaging of this file. Licensees holding valid TQt +** Commercial licenses may use this file in accordance with the TQt +** Commercial License Agreement provided with the Software. +** +** This file is provided "AS IS" with NO WARRANTY OF ANY KIND, +** INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE. Trolltech reserves all rights not granted +** herein. +** +**********************************************************************/ + +#ifndef TQCANVAS_H +#define TQCANVAS_H + +#ifndef QT_H +#include "ntqscrollview.h" +#include "ntqpixmap.h" +#include "ntqptrlist.h" +#include "ntqbrush.h" +#include "ntqpen.h" +#include "ntqvaluelist.h" +#include "ntqpointarray.h" +#endif // QT_H + +#if !defined( TQT_MODULE_CANVAS ) || defined( QT_LICENSE_PROFESSIONAL ) || defined( QT_INTERNAL_CANVAS ) +#define TQM_EXPORT_CANVAS +#define TQM_TEMPLATE_EXTERN_CANVAS +#else +#define TQM_EXPORT_CANVAS TQ_EXPORT +#define TQM_TEMPLATE_EXTERN_CANVAS Q_TEMPLATE_EXTERN +#endif + +#ifndef TQT_NO_CANVAS + + +class TQCanvasSprite; +class TQCanvasPolygonalItem; +class TQCanvasRectangle; +class TQCanvasPolygon; +class TQCanvasEllipse; +class TQCanvasText; +class TQCanvasLine; +class TQCanvasChunk; +class TQCanvas; +class TQCanvasItem; +class TQCanvasView; +class TQCanvasPixmap; + +#if defined(Q_TEMPLATEDLL) && ( !defined(Q_CC_BOR) || !defined(QT_MAKEDLL) || defined(Q_EXPORT_TEMPLATES) ) +// MOC_SKIP_BEGIN +TQM_TEMPLATE_EXTERN_CANVAS template class TQM_EXPORT_CANVAS TQValueListIterator< TQCanvasItem* >; +TQM_TEMPLATE_EXTERN_CANVAS template class TQM_EXPORT_CANVAS TQValueList< TQCanvasItem* >; +// MOC_SKIP_END +#endif + +class TQM_EXPORT_CANVAS TQCanvasItemList : public TQValueList { +public: + void sort(); + void drawUnique( TQPainter& painter ); + TQCanvasItemList operator+(const TQCanvasItemList &l) const; +}; + + +class TQCanvasItemExtra; + +class TQM_EXPORT_CANVAS TQCanvasItem : public TQt +{ +public: + TQCanvasItem(TQCanvas* canvas); + virtual ~TQCanvasItem(); + + double x() const + { return myx; } + double y() const + { return myy; } + double z() const + { return myz; } // (depth) + + virtual void moveBy(double dx, double dy); + void move(double x, double y); + void setX(double a) { move(a,y()); } + void setY(double a) { move(x(),a); } + void setZ(double a) { myz=a; changeChunks(); } + + bool animated() const; + virtual void setAnimated(bool y); + virtual void setVelocity( double vx, double vy); + void setXVelocity( double vx ) { setVelocity(vx,yVelocity()); } + void setYVelocity( double vy ) { setVelocity(xVelocity(),vy); } + double xVelocity() const; + double yVelocity() const; + virtual void advance(int stage); + + virtual bool collidesWith( const TQCanvasItem* ) const=0; + + TQCanvasItemList collisions(bool exact /* NO DEFAULT */ ) const; + + virtual void setCanvas(TQCanvas*); + + virtual void draw(TQPainter&)=0; + + void show(); + void hide(); + + virtual void setVisible(bool yes); + bool isVisible() const + { return (bool)vis; } + virtual void setSelected(bool yes); + bool isSelected() const + { return (bool)sel; } + virtual void setEnabled(bool yes); + bool isEnabled() const + { return (bool)ena; } + virtual void setActive(bool yes); + bool isActive() const + { return (bool)act; } +#ifndef TQT_NO_COMPAT + bool visible() const + { return (bool)vis; } + bool selected() const + { return (bool)sel; } + bool enabled() const + { return (bool)ena; } + bool active() const + { return (bool)act; } +#endif + + enum RttiValues { + Rtti_Item = 0, + Rtti_Sprite = 1, + Rtti_PolygonalItem = 2, + Rtti_Text = 3, + Rtti_Polygon = 4, + Rtti_Rectangle = 5, + Rtti_Ellipse = 6, + Rtti_Line = 7, + Rtti_Spline = 8 + }; + + virtual int rtti() const; + static int RTTI; + + virtual TQRect boundingRect() const=0; + virtual TQRect boundingRectAdvanced() const; + + TQCanvas* canvas() const + { return cnv; } + +protected: + void update() { changeChunks(); } + +private: + // For friendly subclasses... + + friend class TQCanvasPolygonalItem; + friend class TQCanvasSprite; + friend class TQCanvasRectangle; + friend class TQCanvasPolygon; + friend class TQCanvasEllipse; + friend class TQCanvasText; + friend class TQCanvasLine; + + virtual TQPointArray chunks() const; + virtual void addToChunks(); + virtual void removeFromChunks(); + virtual void changeChunks(); + virtual bool collidesWith( const TQCanvasSprite*, + const TQCanvasPolygonalItem*, + const TQCanvasRectangle*, + const TQCanvasEllipse*, + const TQCanvasText* ) const = 0; + // End of friend stuff + + TQCanvas* cnv; + static TQCanvas* current_canvas; + double myx,myy,myz; + TQCanvasItemExtra *ext; + TQCanvasItemExtra& extra(); + uint ani:1; + uint vis:1; + uint val:1; + uint sel:1; + uint ena:1; + uint act:1; +}; + + +class TQCanvasData; + +class TQM_EXPORT_CANVAS TQCanvas : public TQObject +{ + TQ_OBJECT +public: + TQCanvas( TQObject* parent = 0, const char* name = 0 ); + TQCanvas(int w, int h); + TQCanvas( TQPixmap p, int h, int v, int tilewidth, int tileheight ); + + virtual ~TQCanvas(); + + virtual void setTiles( TQPixmap tiles, int h, int v, + int tilewidth, int tileheight ); + virtual void setBackgroundPixmap( const TQPixmap& p ); + TQPixmap backgroundPixmap() const; + + virtual void setBackgroundColor( const TQColor& c ); + TQColor backgroundColor() const; + + virtual void setTile( int x, int y, int tilenum ); + int tile( int x, int y ) const + { return grid[x+y*htiles]; } + + int tilesHorizontally() const + { return htiles; } + int tilesVertically() const + { return vtiles; } + + int tileWidth() const + { return tilew; } + int tileHeight() const + { return tileh; } + + virtual void resize(int width, int height); + int width() const + { return awidth; } + int height() const + { return aheight; } + TQSize size() const + { return TQSize(awidth,aheight); } + TQRect rect() const + { return TQRect( 0, 0, awidth, aheight ); } + bool onCanvas( int x, int y ) const + { return x>=0 && y>=0 && x=0 && y>=0 && x, TQPtrList hotspots); + + TQCanvasPixmapArray(TQValueList, TQPointArray hotspots = TQPointArray() ); + ~TQCanvasPixmapArray(); + +#ifndef TQT_NO_IMAGEIO + bool readPixmaps(const TQString& datafilenamepattern, int framecount=0); + bool readCollisionMasks(const TQString& filenamepattern); +#endif + + // deprecated + bool operator!(); // Failure check. + bool isValid() const; + + TQCanvasPixmap* image(int i) const + { return img ? img[i] : 0; } + void setImage(int i, TQCanvasPixmap* p); + uint count() const + { return (uint)framecount; } + +private: +#if defined(TQ_DISABLE_COPY) + TQCanvasPixmapArray( const TQCanvasPixmapArray & ); + TQCanvasPixmapArray &operator=( const TQCanvasPixmapArray & ); +#endif +#ifndef TQT_NO_IMAGEIO + bool readPixmaps(const TQString& datafilenamepattern, int framecount, bool maskonly); +#endif + + void reset(); + int framecount; + TQCanvasPixmap** img; +}; + + +class TQM_EXPORT_CANVAS TQCanvasSprite : public TQCanvasItem +{ +public: + TQCanvasSprite(TQCanvasPixmapArray* array, TQCanvas* canvas); + + void setSequence(TQCanvasPixmapArray* seq); + + virtual ~TQCanvasSprite(); + + void move(double x, double y); + virtual void move(double x, double y, int frame); + void setFrame(int); + enum FrameAnimationType { Cycle, Oscillate }; + virtual void setFrameAnimation(FrameAnimationType=Cycle, int step=1, int state=0); + int frame() const + { return frm; } + int frameCount() const + { return images->count(); } + + int rtti() const; + static int RTTI; + + bool collidesWith( const TQCanvasItem* ) const; + + TQRect boundingRect() const; + + // is there a reason for these to be protected? Lars +//protected: + + int width() const; + int height() const; + + int leftEdge() const; + int topEdge() const; + int rightEdge() const; + int bottomEdge() const; + + int leftEdge(int nx) const; + int topEdge(int ny) const; + int rightEdge(int nx) const; + int bottomEdge(int ny) const; + TQCanvasPixmap* image() const + { return images->image(frm); } + virtual TQCanvasPixmap* imageAdvanced() const; + TQCanvasPixmap* image(int f) const + { return images->image(f); } + virtual void advance(int stage); + +public: + void draw(TQPainter& painter); + +private: +#if defined(TQ_DISABLE_COPY) + TQCanvasSprite( const TQCanvasSprite & ); + TQCanvasSprite &operator=( const TQCanvasSprite & ); +#endif + void addToChunks(); + void removeFromChunks(); + void changeChunks(); + + int frm; + ushort anim_val; + uint anim_state:2; + uint anim_type:14; + bool collidesWith( const TQCanvasSprite*, + const TQCanvasPolygonalItem*, + const TQCanvasRectangle*, + const TQCanvasEllipse*, + const TQCanvasText* ) const; + + friend bool qt_testCollision( const TQCanvasSprite* s1, + const TQCanvasSprite* s2 ); + + TQCanvasPixmapArray* images; +}; + +class TQPolygonalProcessor; + +class TQM_EXPORT_CANVAS TQCanvasPolygonalItem : public TQCanvasItem +{ +public: + TQCanvasPolygonalItem(TQCanvas* canvas); + virtual ~TQCanvasPolygonalItem(); + + bool collidesWith( const TQCanvasItem* ) const; + + virtual void setPen(TQPen p); + virtual void setBrush(TQBrush b); + + TQPen pen() const + { return pn; } + TQBrush brush() const + { return br; } + + virtual TQPointArray areaPoints() const=0; + virtual TQPointArray areaPointsAdvanced() const; + TQRect boundingRect() const; + + int rtti() const; + static int RTTI; + +protected: + void draw(TQPainter &); + virtual void drawShape(TQPainter &) = 0; + + bool winding() const; + void setWinding(bool); + + void invalidate(); + bool isValid() const + { return (bool)val; } + +private: + void scanPolygon( const TQPointArray& pa, int winding, + TQPolygonalProcessor& process ) const; + TQPointArray chunks() const; + + bool collidesWith( const TQCanvasSprite*, + const TQCanvasPolygonalItem*, + const TQCanvasRectangle*, + const TQCanvasEllipse*, + const TQCanvasText* ) const; + + TQBrush br; + TQPen pn; + uint wind:1; +}; + + +class TQM_EXPORT_CANVAS TQCanvasRectangle : public TQCanvasPolygonalItem +{ +public: + TQCanvasRectangle(TQCanvas* canvas); + TQCanvasRectangle(const TQRect&, TQCanvas* canvas); + TQCanvasRectangle(int x, int y, int width, int height, TQCanvas* canvas); + + ~TQCanvasRectangle(); + + int width() const; + int height() const; + void setSize(int w, int h); + TQSize size() const + { return TQSize(w,h); } + TQPointArray areaPoints() const; + TQRect rect() const + { return TQRect(int(x()),int(y()),w,h); } + + bool collidesWith( const TQCanvasItem* ) const; + + int rtti() const; + static int RTTI; + +protected: + void drawShape(TQPainter &); + TQPointArray chunks() const; + +private: + bool collidesWith( const TQCanvasSprite*, + const TQCanvasPolygonalItem*, + const TQCanvasRectangle*, + const TQCanvasEllipse*, + const TQCanvasText* ) const; + + int w, h; +}; + + +class TQM_EXPORT_CANVAS TQCanvasPolygon : public TQCanvasPolygonalItem +{ +public: + TQCanvasPolygon(TQCanvas* canvas); + ~TQCanvasPolygon(); + void setPoints(TQPointArray); + TQPointArray points() const; + void moveBy(double dx, double dy); + + TQPointArray areaPoints() const; + + int rtti() const; + static int RTTI; + +protected: + void drawShape(TQPainter &); + TQPointArray poly; +}; + + +class TQM_EXPORT_CANVAS TQCanvasSpline : public TQCanvasPolygon +{ +public: + TQCanvasSpline(TQCanvas* canvas); + ~TQCanvasSpline(); + + void setControlPoints(TQPointArray, bool closed=TRUE); + TQPointArray controlPoints() const; + bool closed() const; + + int rtti() const; + static int RTTI; + +private: + void recalcPoly(); + TQPointArray bez; + bool cl; +}; + + +class TQM_EXPORT_CANVAS TQCanvasLine : public TQCanvasPolygonalItem +{ +public: + TQCanvasLine(TQCanvas* canvas); + ~TQCanvasLine(); + void setPoints(int x1, int y1, int x2, int y2); + + TQPoint startPoint() const + { return TQPoint(x1,y1); } + TQPoint endPoint() const + { return TQPoint(x2,y2); } + + int rtti() const; + static int RTTI; + + void setPen(TQPen p); + void moveBy(double dx, double dy); + +protected: + void drawShape(TQPainter &); + TQPointArray areaPoints() const; + +private: + int x1,y1,x2,y2; +}; + + +class TQM_EXPORT_CANVAS TQCanvasEllipse : public TQCanvasPolygonalItem +{ + +public: + TQCanvasEllipse( TQCanvas* canvas ); + TQCanvasEllipse( int width, int height, TQCanvas* canvas ); + TQCanvasEllipse( int width, int height, int startangle, int angle, + TQCanvas* canvas ); + + ~TQCanvasEllipse(); + + int width() const; + int height() const; + void setSize(int w, int h); + void setAngles(int start, int length); + int angleStart() const + { return a1; } + int angleLength() const + { return a2; } + TQPointArray areaPoints() const; + + bool collidesWith( const TQCanvasItem* ) const; + + int rtti() const; + static int RTTI; + +protected: + void drawShape(TQPainter &); + +private: + bool collidesWith( const TQCanvasSprite*, + const TQCanvasPolygonalItem*, + const TQCanvasRectangle*, + const TQCanvasEllipse*, + const TQCanvasText* ) const; + int w, h; + int a1, a2; +}; + + +class TQCanvasTextExtra; + +class TQM_EXPORT_CANVAS TQCanvasText : public TQCanvasItem +{ +public: + TQCanvasText(TQCanvas* canvas); + TQCanvasText(const TQString&, TQCanvas* canvas); + TQCanvasText(const TQString&, TQFont, TQCanvas* canvas); + + virtual ~TQCanvasText(); + + void setText( const TQString& ); + void setFont( const TQFont& ); + void setColor( const TQColor& ); + TQString text() const; + TQFont font() const; + TQColor color() const; + + void moveBy(double dx, double dy); + + int textFlags() const + { return flags; } + void setTextFlags(int); + + TQRect boundingRect() const; + + bool collidesWith( const TQCanvasItem* ) const; + + int rtti() const; + static int RTTI; + +protected: + virtual void draw(TQPainter&); + +private: +#if defined(TQ_DISABLE_COPY) + TQCanvasText( const TQCanvasText & ); + TQCanvasText &operator=( const TQCanvasText & ); +#endif + void addToChunks(); + void removeFromChunks(); + void changeChunks(); + + void setRect(); + TQRect brect; + TQString txt; + int flags; + TQFont fnt; + TQColor col; + TQCanvasTextExtra* extra; + + bool collidesWith( const TQCanvasSprite*, + const TQCanvasPolygonalItem*, + const TQCanvasRectangle*, + const TQCanvasEllipse*, + const TQCanvasText* ) const; +}; + +#define Q_DEFINED_QCANVAS +#include "ntqwinexport.h" +#endif // TQT_NO_CANVAS + +#endif // TQCANVAS_H diff --git a/src/kernel/ntqt.h b/src/kernel/ntqt.h index 13f5eb68c..78ff48a19 100644 --- a/src/kernel/ntqt.h +++ b/src/kernel/ntqt.h @@ -218,7 +218,7 @@ #include #include #include -#include +#include #include "ntqtranslator.h" #include #include diff --git a/src/kernel/qpointarray.cpp b/src/kernel/qpointarray.cpp index 09be31380..4a4031ff6 100644 --- a/src/kernel/qpointarray.cpp +++ b/src/kernel/qpointarray.cpp @@ -483,7 +483,7 @@ static inline int fix_angle( int a ) whereas negative values mean the clockwise direction. Zero degrees is at the 3 o'clock position. - See the \link qcanvasellipse.html#anglediagram angle diagram\endlink. + See the \link tqcanvasellipse.html#anglediagram angle diagram\endlink. */ void TQPointArray::makeArc( int x, int y, int w, int h, int a1, int a2 ) @@ -586,7 +586,7 @@ qtr_elips(TQPointArray& a, int off, double dxP, double dyP, double dxQ, double d whereas negative values mean the clockwise direction. Zero degrees is at the 3 o'clock position. - See the \link qcanvasellipse.html#anglediagram angle diagram\endlink. + See the \link tqcanvasellipse.html#anglediagram angle diagram\endlink. */ void TQPointArray::makeArc( int x, int y, int w, int h, int a1, int a2, diff --git a/src/tools/ntqwinexport.h b/src/tools/ntqwinexport.h index 29d99a228..d2e5e58a3 100644 --- a/src/tools/ntqwinexport.h +++ b/src/tools/ntqwinexport.h @@ -188,7 +188,7 @@ Q_TEMPLATE_EXTERN template class TQ_EXPORT TQValueList< TQPtrVector< TQStyleShee Q_TEMPLATE_EXTERN template class TQ_EXPORT TQValueList; #endif -// qcanvas template exports +// tqcanvas template exports #if defined(Q_DEFINED_QPTRLIST) && defined(Q_DEFINED_QCANVAS) && !defined(Q_EXPORTED_QCANVAS1_TEMPLATES) #define Q_EXPORTED_QCANVAS1_TEMPLATES TQM_TEMPLATE_EXTERN_CANVAS template class TQM_EXPORT_CANVAS TQPtrListIterator< TQCanvasItem >; diff --git a/src/tools/qfeatures.txt b/src/tools/qfeatures.txt index f8e5a069c..84a25587b 100644 --- a/src/tools/qfeatures.txt +++ b/src/tools/qfeatures.txt @@ -25,7 +25,7 @@ SeeAlso: ??? Feature: CANVAS Section: Widgets Requires: SCROLLVIEW BEZIER -Name: QCanvas +Name: TQCanvas SeeAlso: ??? Feature: TOOLBOX diff --git a/src/tools/qwinexport.cpp b/src/tools/qwinexport.cpp index 8abccb8b8..bddee65df 100644 --- a/src/tools/qwinexport.cpp +++ b/src/tools/qwinexport.cpp @@ -1,6 +1,6 @@ #define Q_EXPORT_TEMPLATES -#include +#include #include #include #include -- cgit v1.2.1