diff options
author | Michele Calgaro <[email protected]> | 2024-05-31 11:32:43 +0900 |
---|---|---|
committer | Michele Calgaro <[email protected]> | 2024-05-31 11:59:34 +0900 |
commit | 68b81013e8668f50fc18b7e26a520ec93a7a1251 (patch) | |
tree | d6d15d07cb34e5443a10b71f91adee1473906263 /src/canvas/qcanvas.cpp | |
parent | 1702a6daff27f5d3e6fdac16962d1828df6ca270 (diff) | |
download | tqt3-68b81013e8668f50fc18b7e26a520ec93a7a1251.tar.gz tqt3-68b81013e8668f50fc18b7e26a520ec93a7a1251.zip |
Rename nt* canvas related files to equivalent tq*
Signed-off-by: Michele Calgaro <[email protected]>
Diffstat (limited to 'src/canvas/qcanvas.cpp')
-rw-r--r-- | src/canvas/qcanvas.cpp | 5415 |
1 files changed, 0 insertions, 5415 deletions
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 [email protected]. -** -** 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 <stdlib.h> - -class TQCanvasData { -public: - TQCanvasData() : - itemDict(1013), animDict(503) - { - } - - TQPtrList<TQCanvasView> viewList; - TQPtrDict<void> itemDict; - TQPtrDict<void> 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.left()) { - r.setLeft(rect.left()); - } - if (rect.right()>r.right()) { - r.setRight(rect.right()); - } - if (rect.top()<r.top()) { - r.setTop(rect.top()); - } - if (rect.bottom()>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<count; cursor++) { - if (cluster[cursor].contains(rect)) { - // Wholly contained already. - return; - } - } - - int lowestcost=9999999; - int cheapest=-1; - cursor = 0; - while( cursor<count ) { - if (cluster[cursor].intersects(biggerrect)) { - TQRect larger=cluster[cursor]; - include(larger,rect); - int cost = larger.width()*larger.height() - - cluster[cursor].width()*cluster[cursor].height(); - - if (cost < lowestcost) { - bool bad=FALSE; - for (int c=0; c<count && !bad; c++) { - bad=cluster[c].intersects(larger) && c!=cursor; - } - if (!bad) { - cheapest=cursor; - lowestcost=cost; - } - } - } - cursor++; - } - - if (cheapest>=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<count ) { - TQRect larger=cluster[cursor]; - include(larger,rect); - int cost=larger.width()*larger.height() - - cluster[cursor].width()*cluster[cursor].height(); - if (cost < lowestcost) { - bool bad=FALSE; - for (int c=0; c<count && !bad; c++) { - bad=cluster[c].intersects(larger) && c!=cursor; - } - if (!bad) { - cheapest=cursor; - lowestcost=cost; - } - } - cursor++; - } - - // ### - // could make an heuristic guess as to whether we need to bother - // looking for a cheap merge. - - int cheapestmerge1 = -1; - int cheapestmerge2 = -1; - - int merge1 = 0; - while( merge1 < count ) { - int merge2=0; - while( merge2 < count ) { - if( merge1!=merge2) { - TQRect larger=cluster[merge1]; - include(larger,cluster[merge2]); - int cost=larger.width()*larger.height() - - cluster[merge1].width()*cluster[merge1].height() - - cluster[merge2].width()*cluster[merge2].height(); - if (cost < lowestcost) { - bool bad=FALSE; - for (int c=0; c<count && !bad; c++) { - bad=cluster[c].intersects(larger) && c!=cursor; - } - if (!bad) { - cheapestmerge1=merge1; - cheapestmerge2=merge2; - lowestcost=cost; - } - } - } - merge2++; - } - merge1++; - } - - if (cheapestmerge1>=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 <a href="commercialeditions.html">TQt Enterprise Edition</a>. -\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<TQCanvasItemPtr>*)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 <a href="commercialeditions.html">TQt Enterprise Edition</a>. -\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<void> 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<TQCanvasItem> hidden; - for (TQPtrDictIterator<void> 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<TQCanvasItem> hidden; - for (TQPtrDictIterator<void> 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<void> 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<TQRect> doneareas; - doneareas.setAutoDelete(TRUE); -#endif - - TQPtrListIterator<TQCanvasView> 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; i<clusterizer.clusters(); i++) - drawChanges(clusterizer[i]); - -#ifndef TQT_NO_TRANSFORMATIONS - for ( TQRect* r=doneareas.first(); r != 0; r=doneareas.next() ) - setUnchanged(*r); -#endif -} - - -// ### warwick - setAllChanged() is not a set function. please rename -// it. ditto setChanged(). markChanged(), perhaps? -// ### unfortunately this function is virtual, which makes renaming more difficult. Lars - -/*! - Marks the whole canvas as changed. - All views of the canvas will be entirely redrawn when - update() is called next. -*/ -void TQCanvas::setAllChanged() -{ - setChanged(TQRect(0,0,width(),height())); -} - -/*! - Marks \a area as changed. This \a area will be redrawn in all - views that are showing it when update() is called next. -*/ -void TQCanvas::setChanged(const TQRect& area) -{ - TQRect thearea = area.intersect(TQRect(0,0,width(),height())); - - int mx = (thearea.x()+thearea.width()+chunksize)/chunksize; - int my = (thearea.y()+thearea.height()+chunksize)/chunksize; - if (mx>chwidth) - mx=chwidth; - if (my>chheight) - my=chheight; - - int x=thearea.x()/chunksize; - while( x<mx) { - int y = thearea.y()/chunksize; - while( y<my ) { - chunk(x,y).change(); - y++; - } - x++; - } -} - -/*! - Marks \a area as \e unchanged. The area will \e not be redrawn in - the views for the next update(), unless it is marked or changed - again before the next call to update(). -*/ -void TQCanvas::setUnchanged(const TQRect& area) -{ - TQRect thearea = area.intersect(TQRect(0,0,width(),height())); - - int mx = (thearea.x()+thearea.width()+chunksize)/chunksize; - int my = (thearea.y()+thearea.height()+chunksize)/chunksize; - if (mx>chwidth) - mx=chwidth; - if (my>chheight) - my=chheight; - - int x=thearea.x()/chunksize; - while( x<mx) { - int y = thearea.y()/chunksize; - while( y<my ) { - chunk(x,y).takeChange(); - y++; - } - x++; - } -} - - -/*! - \internal -*/ -TQRect TQCanvas::changeBounds(const TQRect& inarea) -{ - TQRect area=inarea.intersect(TQRect(0,0,width(),height())); - - int mx = (area.x()+area.width()+chunksize)/chunksize; - int my = (area.y()+area.height()+chunksize)/chunksize; - if (mx > chwidth) - mx=chwidth; - if (my > chheight) - my=chheight; - - TQRect result; - - int x=area.x()/chunksize; - while( x<mx ) { - int y=area.y()/chunksize; - while( y<my ) { - TQCanvasChunk& ch=chunk(x,y); - if ( ch.hasChanged() ) - result |= TQRect(x,y,1,1); - y++; - } - x++; - } - - if ( !result.isEmpty() ) { - result.rLeft() *= chunksize; - result.rTop() *= chunksize; - result.rRight() *= chunksize; - result.rBottom() *= chunksize; - result.rRight() += chunksize; - result.rBottom() += chunksize; - } - - return result; -} - -/*! -\internal -Redraws the area \a inarea of the TQCanvas. -*/ -void TQCanvas::drawChanges(const TQRect& inarea) -{ - TQRect area=inarea.intersect(TQRect(0,0,width(),height())); - - TQCanvasClusterizer clusters(maxclusters); - - int mx = (area.x()+area.width()+chunksize)/chunksize; - int my = (area.y()+area.height()+chunksize)/chunksize; - if (mx > chwidth) - mx=chwidth; - if (my > chheight) - my=chheight; - - int x=area.x()/chunksize; - while( x<mx ) { - int y=area.y()/chunksize; - while( y<my ) { - TQCanvasChunk& ch=chunk(x,y); - if ( ch.hasChanged() ) - clusters.add(x,y); - y++; - } - x++; - } - - for (int i=0; i<clusters.clusters(); i++) { - TQRect elarea=clusters[i]; - elarea.setRect( - elarea.left()*chunksize, - elarea.top()*chunksize, - elarea.width()*chunksize, - elarea.height()*chunksize - ); - drawCanvasArea(elarea); - } -} - -/*! - Paints all canvas items that are in the area \a clip to \a - painter, using double-buffering if \a dbuf is TRUE. - - e.g. to print the canvas to a printer: - \code - TQPrinter pr; - if ( pr.setup() ) { - TQPainter p(&pr); - canvas.drawArea( canvas.rect(), &p ); - } - \endcode -*/ -void TQCanvas::drawArea(const TQRect& clip, TQPainter* painter, bool dbuf) -{ - if ( painter ) - drawCanvasArea( clip, painter, dbuf ); -} - -/*! - \internal -*/ -void TQCanvas::drawCanvasArea(const TQRect& inarea, TQPainter* p, bool double_buffer) -{ - TQRect area=inarea.intersect(TQRect(0,0,width(),height())); - - if ( !dblbuf ) - double_buffer = FALSE; - - if (!d->viewList.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<width() && y>=0 && y<height()) { - TQCanvasChunk& chunk=chunkContaining(x,y); - chunk.change(); - } -} - -/*! -\internal -This method adds the TQCanvasItem \a g to the list of those which need to be -drawn if the given chunk at location ( \a x, \a y ) is redrawn. Like -SetChangedChunk and SetChangedChunkContaining, this method marks the -chunk as `dirty'. -*/ -void TQCanvas::addItemToChunk(TQCanvasItem* g, int x, int y) -{ - if (validChunk(x,y)) { - chunk(x,y).add(g); - } -} - -/*! -\internal -This method removes the TQCanvasItem \a g from the list of those which need to -be drawn if the given chunk at location ( \a x, \a y ) is redrawn. Like -SetChangedChunk and SetChangedChunkContaining, this method marks the chunk -as `dirty'. -*/ -void TQCanvas::removeItemFromChunk(TQCanvasItem* g, int x, int y) -{ - if (validChunk(x,y)) { - chunk(x,y).remove(g); - } -} - - -/*! -\internal -This method adds the TQCanvasItem \a g to the list of those which need to be -drawn if the chunk containing the given pixel ( \a x, \a y ) is redrawn. Like -SetChangedChunk and SetChangedChunkContaining, this method marks the -chunk as `dirty'. -*/ -void TQCanvas::addItemToChunkContaining(TQCanvasItem* g, int x, int y) -{ - if (x>=0 && x<width() && y>=0 && y<height()) { - chunkContaining(x,y).add(g); - } -} - -/*! -\internal -This method removes the TQCanvasItem \a g from the list of those which need to -be drawn if the chunk containing the given pixel ( \a x, \a y ) is redrawn. -Like SetChangedChunk and SetChangedChunkContaining, this method -marks the chunk as `dirty'. -*/ -void TQCanvas::removeItemFromChunkContaining(TQCanvasItem* g, int x, int y) -{ - if (x>=0 && x<width() && y>=0 && y<height()) { - chunkContaining(x,y).remove(g); - } -} - -/*! - Returns the color set by setBackgroundColor(). By default, this is - white. - - This function is not a reimplementation of - TQWidget::backgroundColor() (TQCanvas is not a subclass of TQWidget), - but all TQCanvasViews that are viewing the canvas will set their - backgrounds to this color. - - \sa setBackgroundColor(), backgroundPixmap() -*/ -TQColor TQCanvas::backgroundColor() const -{ - return bgcolor; -} - -/*! - Sets the solid background to be the color \a c. - - \sa backgroundColor(), setBackgroundPixmap(), setTiles() -*/ -void TQCanvas::setBackgroundColor( const TQColor& c ) -{ - if ( bgcolor != c ) { - bgcolor = c; - TQCanvasView* view=d->viewList.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 <a href="commercialeditions.html">TQt Enterprise Edition</a>. -\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; j<h; j++) { - uchar* ml = s1image->scanLine(y1+j); - uchar* yl = s2image->scanLine(y2+j); - for (int i=0; i<w; i++) { - if (*(yl + ((x2+i) >> 3)) & (1 << ((x2+i) & 7)) - && *(ml + ((x1+i) >> 3)) & (1 << ((x1+i) & 7))) - { - return TRUE; - } - } - } - } else { - for (int j=0; j<h; j++) { - uchar* ml = s1image->scanLine(y1+j); - uchar* yl = s2image->scanLine(y2+j); - for (int i=0; i<w; i++) { - if (*(yl + ((x2+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; j<h; j++) { - uchar* yl = s2image->scanLine(y2+j); - for (int i=0; i<w; i++) { - if (*(yl + ((x2+i) >> 3)) & (1 << ((x2+i) & 7))) - { - return TRUE; - } - } - } - } else { - for (int j=0; j<h; j++) { - uchar* yl = s2image->scanLine(y2+j); - for (int i=0; i<w; i++) { - if (*(yl + ((x2+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 <a href="commercialeditions.html">TQt Enterprise Edition</a>. -\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<void> 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 <a href="commercialeditions.html">TQt Enterprise Edition</a>. -\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 <a href="commercialeditions.html">TQt Enterprise Edition</a>. -\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<TQPixmap>, 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<TQPixmap> list, TQPtrList<TQPoint> 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<framecount; i++) { - img[i]=new TQCanvasPixmap(*list.current(), *hotspots.current()); - list.next(); - hotspots.next(); - } - } -} - -/*! - Constructs a TQCanvasPixmapArray from the list of TQPixmaps in the - \a list. Each pixmap will get a hotspot according to the \a - hotspots array. If no hotspots are specified, each one is set to - be at position (0, 0). - - If an error occurs, isValid() will return FALSE. -*/ -TQCanvasPixmapArray::TQCanvasPixmapArray(TQValueList<TQPixmap> 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<TQPixmap>::iterator it; - it = list.begin(); - for (int i=0; i<framecount; i++) { - TQPoint hs = have_hotspots ? hotspots[i] : TQPoint( 0, 0 ); - img[i]=new TQCanvasPixmap( *it, hs ); - ++it; - } - } -} - -/*! - Destroys the pixmap array and all the pixmaps it contains. -*/ -TQCanvasPixmapArray::~TQCanvasPixmapArray() -{ - reset(); -} - -void TQCanvasPixmapArray::reset() -{ - for (int i=0; i<framecount; i++) - delete img[i]; - delete [] img; - img = 0; - framecount = 0; -} - -#ifndef TQT_NO_IMAGEIO -/*! - Reads one or more pixmaps into the pixmap array. - - If \a fc is not 0, \a filenamepattern 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 filenamepattern is asssumed to be a filename, - and the image contained in this file will be loaded as the first - (and only) frame. - - If \a filenamepattern does not exist, is not readable, isn't an - image, or some other error occurs, this function will return - FALSE, and isValid() will return FALSE; otherwise this function - will return TRUE. - - \sa isValid() -*/ -bool TQCanvasPixmapArray::readPixmaps( const TQString& filenamepattern, - int fc) -{ - return readPixmaps(filenamepattern,fc,FALSE); -} - -/*! - Reads new collision masks for the array. - - By default, TQCanvasSprite uses the image mask of a sprite to - detect collisions. Use this function to set your own collision - image masks. - - If count() is 1 \a filename must specify a real filename to read - the mask from. If count() is greater than 1, the \a filename must - contain a "%1" that will get replaced by the number of the mask to - be loaded, just like TQCanvasPixmapArray::readPixmaps(). - - All collision masks must be 1-bit images or this function call - will fail. - - If the file isn't readable, contains the wrong number of images, - or there is some other error, this function will return FALSE, and - the array will be flagged as invalid; otherwise this function - returns TRUE. - - \sa isValid() -*/ -bool TQCanvasPixmapArray::readCollisionMasks(const TQString& filename) -{ - return readPixmaps(filename,framecount,TRUE); -} - - -bool TQCanvasPixmapArray::readPixmaps( const TQString& datafilenamepattern, - int fc, bool maskonly) -{ - if ( !maskonly ) { - reset(); - framecount = fc; - if ( !framecount ) - framecount=1; - img = new TQCanvasPixmap*[framecount]; - } - if (!img) - return FALSE; - bool ok = TRUE; - bool arg = fc > 1; - if ( !arg ) - framecount=1; - for (int i=0; i<framecount; i++) { - TQString r; - r.sprintf("%04d",i); - if ( maskonly ) { - if (!img[i]->collision_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 <a href="commercialeditions.html">TQt Enterprise Edition</a>. -\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 <a href="commercialeditions.html">TQt Enterprise Edition</a>. -\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<<i) ) - add(xo+i,yo); - } - -#ifdef TQCANVAS_POLYGONS_DEBUG - void dbg_start() - { - if ( !dbg_wid ) { - dbg_wid = new TQWidget; - dbg_wid->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<n; j++) { - int y = pt[j].y()/cs-bounds.y(); - if (y >= 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)<<x1r); - if ( newbits ) { -#ifdef TQCANVAS_POLYGONS_DEBUG - if ( dbg_ptr ) dbg_ptr->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<<x1r); - if ( newbits1 ) { -#ifdef TQCANVAS_POLYGONS_DEBUG - if ( dbg_ptr ) dbg_ptr->setPen(TQt::green); -#endif - addBits(x1r,7,newbits1,x1q*8,y); - l[x1q] |= newbits1; - } - for (int i=x1q+1; i<x2q; i++) { - if ( l[i] != 0xff ) { - addBits(0,7,~l[i],i*8,y); - l[i]=0xff; - } - } - uchar newbits2 = (~l[x2q]) & (0xff>>(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 <a href="commercialeditions.html">TQt Enterprise Edition</a>. -\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 <a href="commercialeditions.html">TQt Enterprise Edition</a>. -\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<TQPointArray> 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 <a href="commercialeditions.html">TQt Enterprise Edition</a>. -\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<x2 ? -pw : pw ; - int py = y1<y2 ? -pw : pw ; - if ( dx && dy && (dx > 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 <a href="commercialeditions.html">TQt Enterprise Edition</a>. -\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 <a href="commercialeditions.html">TQt Enterprise Edition</a>. -\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 - <small><sup>1</sup>/<sub>16</sub></small>ths 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 <a href="commercialeditions.html">TQt Enterprise Edition</a>. -\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 "\<text\>", on \a canvas. -*/ -TQCanvasText::TQCanvasText(TQCanvas* canvas) : - TQCanvasItem(canvas), - txt("<text>"), 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 |