qtcanvas.cpp
Go to the documentation of this file.
1 /****************************************************************************
2 **
3 ** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/legal
5 **
6 ** This file is part of the Qt Solutions component.
7 **
8 ** $QT_BEGIN_LICENSE:BSD$
9 ** You may use this file under the terms of the BSD license as follows:
10 **
11 ** "Redistribution and use in source and binary forms, with or without
12 ** modification, are permitted provided that the following conditions are
13 ** met:
14 ** * Redistributions of source code must retain the above copyright
15 ** notice, this list of conditions and the following disclaimer.
16 ** * Redistributions in binary form must reproduce the above copyright
17 ** notice, this list of conditions and the following disclaimer in
18 ** the documentation and/or other materials provided with the
19 ** distribution.
20 ** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names
21 ** of its contributors may be used to endorse or promote products derived
22 ** from this software without specific prior written permission.
23 **
24 **
25 ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
26 ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
27 ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
28 ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
29 ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
30 ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
31 ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
32 ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
33 ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
34 ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
35 ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
36 **
37 ** $QT_END_LICENSE$
38 **
39 ****************************************************************************/
40 
41 #include "qtcanvas.h"
42 
43 #include <stdlib.h>
44 
45 #include <QApplication>
46 #include <QBitmap>
47 #include <QDesktopWidget>
48 #include <QImage>
49 #include <QPainter>
50 #include <QTimer>
51 #include <qalgorithms.h>
52 #include <qevent.h>
53 #include <qhash.h>
54 #include <qpainterpath.h>
55 #include <qset.h>
56 using namespace Qt;
57 
59 {
60 public:
62  {
63  }
64 
65  QList<QtCanvasView*> viewList;
66  QSet<QtCanvasItem*> itemDict;
67  QSet<QtCanvasItem*> animDict;
68 };
69 
71 {
72 public:
74  {
75  }
76 
77  QMatrix xform;
78  QMatrix ixform;
80 };
81 
82 // clusterizer
83 
85 {
86 public:
87  QtCanvasClusterizer(int maxclusters);
89 
90  void add(int x, int y); // 1x1 rectangle (point)
91  void add(int x, int y, int w, int h);
92  void add(const QRect& rect);
93 
94  void clear();
95 
96  int
97  clusters() const
98  {
99  return count;
100  }
101 
102  const QRect& operator[](int i) const;
103 
104 private:
105  QRect* cluster;
106  int count;
107  const int maxcl;
108 };
109 
110 static void
111 include(QRect& r, const QRect& rect)
112 {
113  if (rect.left() < r.left())
114  {
115  r.setLeft(rect.left());
116  }
117 
118  if (rect.right() > r.right())
119  {
120  r.setRight(rect.right());
121  }
122 
123  if (rect.top() < r.top())
124  {
125  r.setTop(rect.top());
126  }
127 
128  if (rect.bottom() > r.bottom())
129  {
130  r.setBottom(rect.bottom());
131  }
132 }
133 
134 /*
135 A QtCanvasClusterizer groups rectangles (QRects) into non-overlapping rectangles
136 by a merging heuristic.
137 */
139  cluster(new QRect[maxclusters]), count(0), maxcl(maxclusters)
140 {
141 }
142 
144 {
145  delete[] cluster;
146 }
147 
148 void
150 {
151  count = 0;
152 }
153 
154 void
156 {
157  add(QRect(x, y, 1, 1));
158 }
159 
160 void
161 QtCanvasClusterizer::add(int x, int y, int w, int h)
162 {
163  add(QRect(x, y, w, h));
164 }
165 
166 void
167 QtCanvasClusterizer::add(const QRect& rect)
168 {
169  QRect biggerrect(rect.x() - 1, rect.y() - 1, rect.width() + 2, rect.height() + 2);
170 
171  //assert(rect.width()>0 && rect.height()>0);
172 
173  int cursor;
174 
175  for (cursor = 0; cursor < count; cursor++)
176  {
177  if (cluster[cursor].contains(rect))
178  {
179  // Wholly contained already.
180  return;
181  }
182  }
183 
184  int lowestcost = 9999999;
185  int cheapest = -1;
186  cursor = 0;
187 
188  while (cursor < count)
189  {
190  if (cluster[cursor].intersects(biggerrect))
191  {
192  QRect larger = cluster[cursor];
193  include(larger, rect);
194  int cost = larger.width() * larger.height() -
195  cluster[cursor].width() * cluster[cursor].height();
196 
197  if (cost < lowestcost)
198  {
199  bool bad = false;
200 
201  for (int c = 0; c < count && !bad; c++)
202  {
203  bad = cluster[c].intersects(larger) && c != cursor;
204  }
205 
206  if (!bad)
207  {
208  cheapest = cursor;
209  lowestcost = cost;
210  }
211  }
212  }
213 
214  cursor++;
215  }
216 
217  if (cheapest >= 0)
218  {
219  include(cluster[cheapest], rect);
220  return;
221  }
222 
223  if (count < maxcl)
224  {
225  cluster[count++] = rect;
226  return;
227  }
228 
229  // Do cheapest of:
230  // add to closest cluster
231  // do cheapest cluster merge, add to new cluster
232 
233  lowestcost = 9999999;
234  cheapest = -1;
235  cursor = 0;
236 
237  while (cursor < count)
238  {
239  QRect larger = cluster[cursor];
240  include(larger, rect);
241  int cost =
242  larger.width() * larger.height() - cluster[cursor].width() * cluster[cursor].height();
243 
244  if (cost < lowestcost)
245  {
246  bool bad = false;
247 
248  for (int c = 0; c < count && !bad; c++)
249  {
250  bad = cluster[c].intersects(larger) && c != cursor;
251  }
252 
253  if (!bad)
254  {
255  cheapest = cursor;
256  lowestcost = cost;
257  }
258  }
259 
260  cursor++;
261  }
262 
263  // ###
264  // could make an heuristic guess as to whether we need to bother
265  // looking for a cheap merge.
266 
267  int cheapestmerge1 = -1;
268  int cheapestmerge2 = -1;
269 
270  int merge1 = 0;
271 
272  while (merge1 < count)
273  {
274  int merge2 = 0;
275 
276  while (merge2 < count)
277  {
278  if (merge1 != merge2)
279  {
280  QRect larger = cluster[merge1];
281  include(larger, cluster[merge2]);
282  int cost = larger.width() * larger.height() -
283  cluster[merge1].width() * cluster[merge1].height() -
284  cluster[merge2].width() * cluster[merge2].height();
285 
286  if (cost < lowestcost)
287  {
288  bool bad = false;
289 
290  for (int c = 0; c < count && !bad; c++)
291  {
292  bad = cluster[c].intersects(larger) && c != cursor;
293  }
294 
295  if (!bad)
296  {
297  cheapestmerge1 = merge1;
298  cheapestmerge2 = merge2;
299  lowestcost = cost;
300  }
301  }
302  }
303 
304  merge2++;
305  }
306 
307  merge1++;
308  }
309 
310  if (cheapestmerge1 >= 0)
311  {
312  include(cluster[cheapestmerge1], cluster[cheapestmerge2]);
313  cluster[cheapestmerge2] = cluster[count--];
314  }
315  else
316  {
317  // if (!cheapest) debugRectangles(rect);
318  include(cluster[cheapest], rect);
319  }
320 
321  // NB: clusters do not intersect (or intersection will
322  // overwrite). This is a result of the above algorithm,
323  // given the assumption that (x, y) are ordered topleft
324  // to bottomright.
325 
326  // ###
327  //
328  // add explicit x/y ordering to that comment, move it to the top
329  // and rephrase it as pre-/post-conditions.
330 }
331 
332 const QRect&
334 {
335  return cluster[i];
336 }
337 
338 // end of clusterizer
339 
340 
342 {
343 public:
344  inline bool
345  operator()(const QtCanvasItem* i1, const QtCanvasItem* i2) const
346  {
347  if (i1->z() == i2->z())
348  {
349  return i1 > i2;
350  }
351 
352  return (i1->z() > i2->z());
353  }
354 };
355 
357 {
358 public:
359  QtCanvasChunk() : changed(true)
360  {
361  }
362 
363  // Other code assumes lists are not deleted. Assignment is also
364  // done on ChunkRecs. So don't add that sort of thing here.
365 
366  void
368  {
369  qSort(m_list.begin(), m_list.end(), QtCanvasItemLess());
370  }
371 
372  const QtCanvasItemList&
373  list() const
374  {
375  return m_list;
376  }
377 
378  void
380  {
381  m_list.prepend(item);
382  changed = true;
383  }
384 
385  void
387  {
388  m_list.removeAll(item);
389  changed = true;
390  }
391 
392  void
394  {
395  changed = true;
396  }
397 
398  bool
399  hasChanged() const
400  {
401  return changed;
402  }
403 
404  bool
406  {
407  bool y = changed;
408  changed = false;
409  return y;
410  }
411 
412 private:
413  QtCanvasItemList m_list;
414  bool changed;
415 };
416 
417 static int
418 gcd(int a, int b)
419 {
420  int r;
421 
422  while ((r = a % b))
423  {
424  a = b;
425  b = r;
426  }
427 
428  return b;
429 }
430 
431 static int
432 scm(int a, int b)
433 {
434  int g = gcd(a, b);
435  return a / g * b;
436 }
437 
438 /*
439  \class QtCanvas qtcanvas.h
440  \brief The QtCanvas class provides a 2D area that can contain QtCanvasItem objects.
441 
442  The QtCanvas class manages its 2D graphic area and all the canvas
443  items the area contains. The canvas has no visual appearance of
444  its own. Instead, it is displayed on screen using a QtCanvasView.
445  Multiple QtCanvasView widgets may be associated with a canvas to
446  provide multiple views of the same canvas.
447 
448  The canvas is optimized for large numbers of items, particularly
449  where only a small percentage of the items change at any
450  one time. If the entire display changes very frequently, you should
451  consider using your own custom QtScrollView subclass.
452 
453  Qt provides a rich
454  set of canvas item classes, e.g. QtCanvasEllipse, QtCanvasLine,
455  QtCanvasPolygon, QtCanvasPolygonalItem, QtCanvasRectangle, QtCanvasSpline,
456  QtCanvasSprite and QtCanvasText. You can subclass to create your own
457  canvas items; QtCanvasPolygonalItem is the most common base class used
458  for this purpose.
459 
460  Items appear on the canvas after their \link QtCanvasItem::show()
461  show()\endlink function has been called (or \link
462  QtCanvasItem::setVisible() setVisible(true)\endlink), and \e after
463  update() has been called. The canvas only shows items that are
464  \link QtCanvasItem::setVisible() visible\endlink, and then only if
465  \l update() is called. (By default the canvas is white and so are
466  canvas items, so if nothing appears try changing colors.)
467 
468  If you created the canvas without passing a width and height to
469  the constructor you must also call resize().
470 
471  Although a canvas may appear to be similar to a widget with child
472  widgets, there are several notable differences:
473 
474  \list
475  \i Canvas items are usually much faster to manipulate and redraw than
476  child widgets, with the speed advantage becoming especially great when
477  there are \e many canvas items and non-rectangular items. In most
478  situations canvas items are also a lot more memory efficient than child
479  widgets.
480 
481  \i It's easy to detect overlapping items (collision detection).
482 
483  \i The canvas can be larger than a widget. A million-by-million canvas
484  is perfectly possible. At such a size a widget might be very
485  inefficient, and some window systems might not support it at all,
486  whereas QtCanvas scales well. Even with a billion pixels and a million
487  items, finding a particular canvas item, detecting collisions, etc.,
488  is still fast (though the memory consumption may be prohibitive
489  at such extremes).
490 
491  \i Two or more QtCanvasView objects can view the same canvas.
492 
493  \i An arbitrary transformation matrix can be set on each QtCanvasView
494  which makes it easy to zoom, rotate or shear the viewed canvas.
495 
496  \i Widgets provide a lot more functionality, such as input (QKeyEvent,
497  QMouseEvent etc.) and layout management (QGridLayout etc.).
498 
499  \endlist
500 
501  A canvas consists of a background, a number of canvas items organized by
502  x, y and z coordinates, and a foreground. A canvas item's z coordinate
503  can be treated as a layer number -- canvas items with a higher z
504  coordinate appear in front of canvas items with a lower z coordinate.
505 
506  The background is white by default, but can be set to a different color
507  using setBackgroundColor(), or to a repeated pixmap using
508  setBackgroundPixmap() or to a mosaic of smaller pixmaps using
509  setTiles(). Individual tiles can be set with setTile(). There
510  are corresponding get functions, e.g. backgroundColor() and
511  backgroundPixmap().
512 
513  Note that QtCanvas does not inherit from QWidget, even though it has some
514  functions which provide the same functionality as those in QWidget. One
515  of these is setBackgroundPixmap(); some others are resize(), size(),
516  width() and height(). \l QtCanvasView is the widget used to display a
517  canvas on the screen.
518 
519  Canvas items are added to a canvas by constructing them and passing the
520  canvas to the canvas item's constructor. An item can be moved to a
521  different canvas using QtCanvasItem::setCanvas().
522 
523  Canvas items are movable (and in the case of QtCanvasSprites, animated)
524  objects that inherit QtCanvasItem. Each canvas item has a position on the
525  canvas (x, y coordinates) and a height (z coordinate), all of which are
526  held as floating-point numbers. Moving canvas items also have x and y
527  velocities. It's possible for a canvas item to be outside the canvas
528  (for example QtCanvasItem::x() is greater than width()). When a canvas
529  item is off the canvas, onCanvas() returns false and the canvas
530  disregards the item. (Canvas items off the canvas do not slow down any
531  of the common operations on the canvas.)
532 
533  Canvas items can be moved with QtCanvasItem::move(). The advance()
534  function moves all QtCanvasItem::animated() canvas items and
535  setAdvancePeriod() makes QtCanvas move them automatically on a periodic
536  basis. In the context of the QtCanvas classes, to `animate' a canvas item
537  is to set it in motion, i.e. using QtCanvasItem::setVelocity(). Animation
538  of a canvas item itself, i.e. items which change over time, is enabled
539  by calling QtCanvasSprite::setFrameAnimation(), or more generally by
540  subclassing and reimplementing QtCanvasItem::advance(). To detect collisions
541  use one of the QtCanvasItem::collisions() functions.
542 
543  The changed parts of the canvas are redrawn (if they are visible in a
544  canvas view) whenever update() is called. You can either call update()
545  manually after having changed the contents of the canvas, or force
546  periodic updates using setUpdatePeriod(). If you have moving objects on
547  the canvas, you must call advance() every time the objects should
548  move one step further. Periodic calls to advance() can be forced using
549  setAdvancePeriod(). The advance() function will call
550  QtCanvasItem::advance() on every item that is \link
551  QtCanvasItem::animated() animated\endlink and trigger an update of the
552  affected areas afterwards. (A canvas item that is `animated' is simply
553  a canvas item that is in motion.)
554 
555  QtCanvas organizes its canvas items into \e chunks; these are areas on
556  the canvas that are used to speed up most operations. Many operations
557  start by eliminating most chunks (i.e. those which haven't changed)
558  and then process only the canvas items that are in the few interesting
559  (i.e. changed) chunks. A valid chunk, validChunk(), is one which is on
560  the canvas.
561 
562  The chunk size is a key factor to QtCanvas's speed: if there are too many
563  chunks, the speed benefit of grouping canvas items into chunks is
564  reduced. If the chunks are too large, it takes too long to process each
565  one. The QtCanvas constructor tries to pick a suitable size, but you
566  can call retune() to change it at any time. The chunkSize() function
567  returns the current chunk size. The canvas items always make sure
568  they're in the right chunks; all you need to make sure of is that
569  the canvas uses the right chunk size. A good rule of thumb is that
570  the size should be a bit smaller than the average canvas item
571  size. If you have moving objects, the chunk size should be a bit
572  smaller than the average size of the moving items.
573 
574  The foreground is normally nothing, but if you reimplement
575  drawForeground(), you can draw things in front of all the canvas
576  items.
577 
578  Areas can be set as changed with setChanged() and set unchanged with
579  setUnchanged(). The entire canvas can be set as changed with
580  setAllChanged(). A list of all the items on the canvas is returned by
581  allItems().
582 
583  An area can be copied (painted) to a QPainter with drawArea().
584 
585  If the canvas is resized it emits the resized() signal.
586 
587  The examples/canvas application and the 2D graphics page of the
588  examples/demo application demonstrate many of QtCanvas's facilities.
589 
590  \sa QtCanvasView QtCanvasItem
591 */
592 void
593 QtCanvas::init(int w, int h, int chunksze, int mxclusters)
594 {
595  d = new QtCanvasData;
596  awidth = w;
597  aheight = h;
598  chunksize = chunksze;
599  maxclusters = mxclusters;
600  chwidth = (w + chunksize - 1) / chunksize;
601  chheight = (h + chunksize - 1) / chunksize;
602  chunks = new QtCanvasChunk[chwidth * chheight];
603  update_timer = 0;
604  bgcolor = white;
605  grid = 0;
606  htiles = 0;
607  vtiles = 0;
608  debug_redraw_areas = false;
609 }
610 
611 /*
612  Create a QtCanvas with no size. \a parent is passed to the QObject
613  superclass.
614 
615  \warning You \e must call resize() at some time after creation to
616  be able to use the canvas.
617 */
618 QtCanvas::QtCanvas(QObject* parent) : QObject(parent)
619 {
620  init(0, 0);
621 }
622 
623 /*
624  Constructs a QtCanvas that is \a w pixels wide and \a h pixels high.
625 */
626 QtCanvas::QtCanvas(int w, int h)
627 {
628  init(w, h);
629 }
630 
631 /*
632  Constructs a QtCanvas which will be composed of \a h tiles
633  horizontally and \a v tiles vertically. Each tile will be an image
634  \a tilewidth by \a tileheight pixels taken from pixmap \a p.
635 
636  The pixmap \a p is a list of tiles, arranged left to right, (and
637  in the case of pixmaps that have multiple rows of tiles, top to
638  bottom), with tile 0 in the top-left corner, tile 1 next to the
639  right, and so on, e.g.
640 
641  \table
642  \row \i 0 \i 1 \i 2 \i 3
643  \row \i 4 \i 5 \i 6 \i 7
644  \endtable
645 
646  The QtCanvas is initially sized to show exactly the given number of
647  tiles horizontally and vertically. If it is resized to be larger,
648  the entire matrix of tiles will be repeated as often as necessary
649  to cover the area. If it is smaller, tiles to the right and bottom
650  will not be visible.
651 
652  \sa setTiles()
653 */
654 QtCanvas::QtCanvas(QPixmap p, int h, int v, int tilewidth, int tileheight)
655 {
656  init(h * tilewidth, v * tileheight, scm(tilewidth, tileheight));
657  setTiles(p, h, v, tilewidth, tileheight);
658 }
659 
660 /*
661  Destroys the canvas and all the canvas's canvas items.
662 */
664 {
665  for (int i = 0; i < d->viewList.size(); ++i)
666  {
667  d->viewList[i]->viewing = 0;
668  }
669 
671 
672  for (QtCanvasItemList::Iterator it = all.begin(); it != all.end(); ++it)
673  {
674  delete *it;
675  }
676 
677  delete[] chunks;
678  delete[] grid;
679  delete d;
680 }
681 
682 /*
683 \internal
684 Returns the chunk at a chunk position \a i, \a j.
685 */
687 QtCanvas::chunk(int i, int j) const
688 {
689  return chunks[i + chwidth * j];
690 }
691 
692 /*
693 \internal
694 Returns the chunk at a pixel position \a x, \a y.
695 */
697 QtCanvas::chunkContaining(int x, int y) const
698 {
699  return chunk(x / chunksize, y / chunksize);
700 }
701 
702 /*
703  Returns a list of all the items in the canvas.
704 */
707 {
708  return d->itemDict.toList();
709 }
710 
711 /*
712  Changes the size of the canvas to have a width of \a w and a
713  height of \a h. This is a slow operation.
714 */
715 void
716 QtCanvas::resize(int w, int h)
717 {
718  if (awidth == w && aheight == h)
719  {
720  return;
721  }
722 
723  QList<QtCanvasItem*> hidden;
724 
725  for (QSet<QtCanvasItem*>::const_iterator it = d->itemDict.begin(); it != d->itemDict.end();
726  ++it)
727  {
728  if ((*it)->isVisible())
729  {
730  (*it)->hide();
731  hidden.append(*it);
732  }
733  }
734 
735  int nchwidth = (w + chunksize - 1) / chunksize;
736  int nchheight = (h + chunksize - 1) / chunksize;
737 
738  QtCanvasChunk* newchunks = new QtCanvasChunk[nchwidth * nchheight];
739 
740  // Commit the new values.
741  //
742  awidth = w;
743  aheight = h;
744  chwidth = nchwidth;
745  chheight = nchheight;
746  delete[] chunks;
747  chunks = newchunks;
748 
749  for (int i = 0; i < hidden.size(); ++i)
750  {
751  hidden.at(i)->show();
752  }
753 
754  setAllChanged();
755 
756  emit resized();
757 }
758 
759 /*
760  \fn void QtCanvas::resized()
761 
762  This signal is emitted whenever the canvas is resized. Each
763  QtCanvasView connects to this signal to keep the scrollview's size
764  correct.
765 */
766 
767 /*
768  Change the efficiency tuning parameters to \a mxclusters clusters,
769  each of size \a chunksze. This is a slow operation if there are
770  many objects on the canvas.
771 
772  The canvas is divided into chunks which are rectangular areas \a
773  chunksze wide by \a chunksze high. Use a chunk size which is about
774  the average size of the canvas items. If you choose a chunk size
775  which is too small it will increase the amount of calculation
776  required when drawing since each change will affect many chunks.
777  If you choose a chunk size which is too large the amount of
778  drawing required will increase because for each change, a lot of
779  drawing will be required since there will be many (unchanged)
780  canvas items which are in the same chunk as the changed canvas
781  items.
782 
783  Internally, a canvas uses a low-resolution "chunk matrix" to keep
784  track of all the items in the canvas. A 64x64 chunk matrix is the
785  default for a 1024x1024 pixel canvas, where each chunk collects
786  canvas items in a 16x16 pixel square. This default is also
787  affected by setTiles(). You can tune this default using this
788  function. For example if you have a very large canvas and want to
789  trade off speed for memory then you might set the chunk size to 32
790  or 64.
791 
792  The \a mxclusters argument is the number of rectangular groups of
793  chunks that will be separately drawn. If the canvas has a large
794  number of small, dispersed items, this should be about that
795  number. Our testing suggests that a large number of clusters is
796  almost always best.
797 
798 */
799 void
800 QtCanvas::retune(int chunksze, int mxclusters)
801 {
802  maxclusters = mxclusters;
803 
804  if (chunksize != chunksze)
805  {
806  QList<QtCanvasItem*> hidden;
807 
808  for (QSet<QtCanvasItem*>::const_iterator it = d->itemDict.begin(); it != d->itemDict.end();
809  ++it)
810  {
811  if ((*it)->isVisible())
812  {
813  (*it)->hide();
814  hidden.append(*it);
815  }
816  }
817 
818  chunksize = chunksze;
819 
820  int nchwidth = (awidth + chunksize - 1) / chunksize;
821  int nchheight = (aheight + chunksize - 1) / chunksize;
822 
823  QtCanvasChunk* newchunks = new QtCanvasChunk[nchwidth * nchheight];
824 
825  // Commit the new values.
826  //
827  chwidth = nchwidth;
828  chheight = nchheight;
829  delete[] chunks;
830  chunks = newchunks;
831 
832  for (int i = 0; i < hidden.size(); ++i)
833  {
834  hidden.at(i)->show();
835  }
836  }
837 }
838 
839 /*
840  \fn int QtCanvas::width() const
841 
842  Returns the width of the canvas, in pixels.
843 */
844 
845 /*
846  \fn int QtCanvas::height() const
847 
848  Returns the height of the canvas, in pixels.
849 */
850 
851 /*
852  \fn QSize QtCanvas::size() const
853 
854  Returns the size of the canvas, in pixels.
855 */
856 
857 /*
858  \fn QRect QtCanvas::rect() const
859 
860  Returns a rectangle the size of the canvas.
861 */
862 
863 
864 /*
865  \fn bool QtCanvas::onCanvas(int x, int y) const
866 
867  Returns true if the pixel position (\a x, \a y) is on the canvas;
868  otherwise returns false.
869 
870  \sa validChunk()
871 */
872 
873 /*
874  \fn bool QtCanvas::onCanvas(const QPoint& p) const
875  \overload
876 
877  Returns true if the pixel position \a p is on the canvas;
878  otherwise returns false.
879 
880  \sa validChunk()
881 */
882 
883 /*
884  \fn bool QtCanvas::validChunk(int x, int y) const
885 
886  Returns true if the chunk position (\a x, \a y) is on the canvas;
887  otherwise returns false.
888 
889  \sa onCanvas()
890 */
891 
892 /*
893  \fn bool QtCanvas::validChunk(const QPoint& p) const
894  \overload
895 
896  Returns true if the chunk position \a p is on the canvas; otherwise
897  returns false.
898 
899  \sa onCanvas()
900 */
901 
902 /*
903  \fn int QtCanvas::chunkSize() const
904 
905  Returns the chunk size of the canvas.
906 
907  \sa retune()
908 */
909 
910 /*
911 \fn bool QtCanvas::sameChunk(int x1, int y1, int x2, int y2) const
912 \internal
913 Tells if the points (\a x1, \a y1) and (\a x2, \a y2) are within the same chunk.
914 */
915 
916 /*
917 \internal
918 This method adds an the item \a item to the list of QtCanvasItem objects
919 in the QtCanvas. The QtCanvasItem class calls this.
920 */
921 void
923 {
924  d->itemDict.insert(item);
925 }
926 
927 /*
928 \internal
929 This method adds the item \a item to the list of QtCanvasItem objects
930 to be moved. The QtCanvasItem class calls this.
931 */
932 void
934 {
935  d->animDict.insert(item);
936 }
937 
938 /*
939 \internal
940 This method adds the item \a item to the list of QtCanvasItem objects
941 which are no longer to be moved. The QtCanvasItem class calls this.
942 */
943 void
945 {
946  d->animDict.remove(item);
947 }
948 
949 /*
950 \internal
951 This method removes the item \a item from the list of QtCanvasItem objects
952 in this QtCanvas. The QtCanvasItem class calls this.
953 */
954 void
956 {
957  d->itemDict.remove(item);
958 }
959 
960 /*
961 \internal
962 This method adds the view \a view to the list of QtCanvasView objects
963 viewing this QtCanvas. The QtCanvasView class calls this.
964 */
965 void
967 {
968  d->viewList.append(view);
969 
970  if (htiles > 1 || vtiles > 1 || pm.isNull())
971  {
972  QPalette::ColorRole role = view->widget()->backgroundRole();
973  QPalette viewPalette = view->widget()->palette();
974  viewPalette.setColor(role, backgroundColor());
975  view->widget()->setPalette(viewPalette);
976  }
977 }
978 
979 /*
980 \internal
981 This method removes the view \a view from the list of QtCanvasView objects
982 viewing this QtCanvas. The QtCanvasView class calls this.
983 */
984 void
986 {
987  d->viewList.removeAll(view);
988 }
989 
990 /*
991  Sets the canvas to call advance() every \a ms milliseconds. Any
992  previous setting by setAdvancePeriod() or setUpdatePeriod() is
993  overridden.
994 
995  If \a ms is less than 0 advancing will be stopped.
996 */
997 void
999 {
1000  if (ms < 0)
1001  {
1002  if (update_timer)
1003  {
1004  update_timer->stop();
1005  }
1006  }
1007  else
1008  {
1009  if (update_timer)
1010  {
1011  delete update_timer;
1012  }
1013 
1014  update_timer = new QTimer(this);
1015  connect(update_timer, SIGNAL(timeout()), this, SLOT(advance()));
1016  update_timer->start(ms);
1017  }
1018 }
1019 
1020 /*
1021  Sets the canvas to call update() every \a ms milliseconds. Any
1022  previous setting by setAdvancePeriod() or setUpdatePeriod() is
1023  overridden.
1024 
1025  If \a ms is less than 0 automatic updating will be stopped.
1026 */
1027 void
1029 {
1030  if (ms < 0)
1031  {
1032  if (update_timer)
1033  {
1034  update_timer->stop();
1035  }
1036  }
1037  else
1038  {
1039  if (update_timer)
1040  {
1041  delete update_timer;
1042  }
1043 
1044  update_timer = new QTimer(this);
1045  connect(update_timer, SIGNAL(timeout()), this, SLOT(update()));
1046  update_timer->start(ms);
1047  }
1048 }
1049 
1050 /*
1051  Moves all QtCanvasItem::animated() canvas items on the canvas and
1052  refreshes all changes to all views of the canvas. (An `animated'
1053  item is an item that is in motion; see setVelocity().)
1054 
1055  The advance takes place in two phases. In phase 0, the
1056  QtCanvasItem::advance() function of each QtCanvasItem::animated()
1057  canvas item is called with paramater 0. Then all these canvas
1058  items are called again, with parameter 1. In phase 0, the canvas
1059  items should not change position, merely examine other items on
1060  the canvas for which special processing is required, such as
1061  collisions between items. In phase 1, all canvas items should
1062  change positions, ignoring any other items on the canvas. This
1063  two-phase approach allows for considerations of "fairness",
1064  although no QtCanvasItem subclasses supplied with Qt do anything
1065  interesting in phase 0.
1066 
1067  The canvas can be configured to call this function periodically
1068  with setAdvancePeriod().
1069 
1070  \sa update()
1071 */
1072 void
1074 {
1075  QSetIterator<QtCanvasItem*> it = d->animDict;
1076 
1077  while (it.hasNext())
1078  {
1079  QtCanvasItem* i = it.next();
1080 
1081  if (i)
1082  {
1083  i->advance(0);
1084  }
1085  }
1086 
1087  // we expect the dict contains the exact same items as in the
1088  // first pass.
1089  it.toFront();
1090 
1091  while (it.hasNext())
1092  {
1093  QtCanvasItem* i = it.next();
1094 
1095  if (i)
1096  {
1097  i->advance(1);
1098  }
1099  }
1100 
1101  update();
1102 }
1103 
1104 // Don't call this unless you know what you're doing.
1105 // p is in the content's co-ordinate example.
1106 /*
1107  \internal
1108 */
1109 void
1110 QtCanvas::drawViewArea(QtCanvasView* view, QPainter* p, const QRect& vr, bool)
1111 {
1112  QMatrix wm = view->worldMatrix();
1113  QMatrix iwm = wm.inverted();
1114  // ivr = covers all chunks in vr
1115  QRect ivr = iwm.mapRect(vr);
1116 
1117  p->setMatrix(wm);
1118  drawCanvasArea(ivr, p, false);
1119 }
1120 
1121 /*
1122  Repaints changed areas in all views of the canvas.
1123 
1124  \sa advance()
1125 */
1126 void
1128 {
1129  QRect r = changeBounds();
1130 
1131  for (int i = 0; i < d->viewList.size(); ++i)
1132  {
1133  QtCanvasView* view = d->viewList.at(i);
1134 
1135  if (!r.isEmpty())
1136  {
1137  QRect tr = view->worldMatrix().mapRect(r);
1138  view->widget()->update(tr);
1139  }
1140  }
1141 
1142  setUnchanged(r);
1143 }
1144 
1145 /*
1146  Marks the whole canvas as changed.
1147  All views of the canvas will be entirely redrawn when
1148  update() is called next.
1149 */
1150 void
1152 {
1153  setChanged(QRect(0, 0, width(), height()));
1154 }
1155 
1156 /*
1157  Marks \a area as changed. This \a area will be redrawn in all
1158  views that are showing it when update() is called next.
1159 */
1160 void
1161 QtCanvas::setChanged(const QRect& area)
1162 {
1163  QRect thearea = area.intersected(QRect(0, 0, width(), height()));
1164 
1165  int mx = (thearea.x() + thearea.width() + chunksize) / chunksize;
1166  int my = (thearea.y() + thearea.height() + chunksize) / chunksize;
1167 
1168  if (mx > chwidth)
1169  {
1170  mx = chwidth;
1171  }
1172 
1173  if (my > chheight)
1174  {
1175  my = chheight;
1176  }
1177 
1178  int x = thearea.x() / chunksize;
1179 
1180  while (x < mx)
1181  {
1182  int y = thearea.y() / chunksize;
1183 
1184  while (y < my)
1185  {
1186  chunk(x, y).change();
1187  y++;
1188  }
1189 
1190  x++;
1191  }
1192 }
1193 
1194 /*
1195  Marks \a area as \e unchanged. The area will \e not be redrawn in
1196  the views for the next update(), unless it is marked or changed
1197  again before the next call to update().
1198 */
1199 void
1200 QtCanvas::setUnchanged(const QRect& area)
1201 {
1202  QRect thearea = area.intersected(QRect(0, 0, width(), height()));
1203 
1204  int mx = (thearea.x() + thearea.width() + chunksize) / chunksize;
1205  int my = (thearea.y() + thearea.height() + chunksize) / chunksize;
1206 
1207  if (mx > chwidth)
1208  {
1209  mx = chwidth;
1210  }
1211 
1212  if (my > chheight)
1213  {
1214  my = chheight;
1215  }
1216 
1217  int x = thearea.x() / chunksize;
1218 
1219  while (x < mx)
1220  {
1221  int y = thearea.y() / chunksize;
1222 
1223  while (y < my)
1224  {
1225  chunk(x, y).takeChange();
1226  y++;
1227  }
1228 
1229  x++;
1230  }
1231 }
1232 
1233 /*
1234  \internal
1235 */
1236 QRect
1237 QtCanvas::changeBounds()
1238 {
1239  QRect area = QRect(0, 0, width(), height());
1240 
1241  int mx = (area.x() + area.width() + chunksize) / chunksize;
1242  int my = (area.y() + area.height() + chunksize) / chunksize;
1243 
1244  if (mx > chwidth)
1245  {
1246  mx = chwidth;
1247  }
1248 
1249  if (my > chheight)
1250  {
1251  my = chheight;
1252  }
1253 
1254  QRect result;
1255 
1256  int x = area.x() / chunksize;
1257 
1258  while (x < mx)
1259  {
1260  int y = area.y() / chunksize;
1261 
1262  while (y < my)
1263  {
1264  QtCanvasChunk& ch = chunk(x, y);
1265 
1266  if (ch.hasChanged())
1267  {
1268  result |= QRect(x * chunksize, y * chunksize, chunksize + 1, chunksize + 1);
1269  }
1270 
1271  y++;
1272  }
1273 
1274  x++;
1275  }
1276 
1277  return result;
1278 }
1279 
1280 /*
1281  Paints all canvas items that are in the area \a clip to \a
1282  painter, using double-buffering if \a dbuf is true.
1283 
1284  e.g. to print the canvas to a printer:
1285  \code
1286  QPrinter pr;
1287  if (pr.setup()) {
1288  QPainter p(&pr);
1289  canvas.drawArea(canvas.rect(), &p);
1290  }
1291  \endcode
1292 */
1293 void
1294 QtCanvas::drawArea(const QRect& clip, QPainter* painter, bool dbuf)
1295 {
1296  if (painter)
1297  {
1298  drawCanvasArea(clip, painter, dbuf);
1299  }
1300 }
1301 
1302 #include <QDebug>
1303 
1304 /*
1305  \internal
1306 */
1307 void
1308 QtCanvas::drawCanvasArea(const QRect& inarea, QPainter* p, bool /*double_buffer*/)
1309 {
1310  QRect area = inarea.intersected(QRect(0, 0, width(), height()));
1311 
1312  if (!p)
1313  {
1314  return; // Nothing to do.
1315  }
1316 
1317  int lx = area.x() / chunksize;
1318  int ly = area.y() / chunksize;
1319  int mx = area.right() / chunksize;
1320  int my = area.bottom() / chunksize;
1321 
1322  if (mx >= chwidth)
1323  {
1324  mx = chwidth - 1;
1325  }
1326 
1327  if (my >= chheight)
1328  {
1329  my = chheight - 1;
1330  }
1331 
1332  QtCanvasItemList allvisible;
1333 
1334  // Stores the region within area that need to be drawn. It is relative
1335  // to area.topLeft() (so as to keep within bounds of 16-bit XRegions)
1336  QRegion rgn;
1337 
1338  for (int x = lx; x <= mx; x++)
1339  {
1340  for (int y = ly; y <= my; y++)
1341  {
1342  // Only reset change if all views updating, and
1343  // wholy within area. (conservative: ignore entire boundary)
1344  //
1345  // Disable this to help debugging.
1346  //
1347  if (!p)
1348  {
1349  if (chunk(x, y).takeChange())
1350  {
1351  // ### should at least make bands
1352  rgn |= QRegion(
1353  x * chunksize - area.x(), y * chunksize - area.y(), chunksize, chunksize);
1354  allvisible += chunk(x, y).list();
1355  }
1356  }
1357  else
1358  {
1359  allvisible += chunk(x, y).list();
1360  }
1361  }
1362  }
1363 
1364  qSort(allvisible.begin(), allvisible.end(), QtCanvasItemLess());
1365 
1366  drawBackground(*p, area);
1367 
1368  if (!allvisible.isEmpty())
1369  {
1370  QtCanvasItem* prev = 0;
1371 
1372  for (int i = allvisible.size() - 1; i >= 0; --i)
1373  {
1374  QtCanvasItem* g = allvisible[i];
1375 
1376  if (g != prev)
1377  {
1378  g->draw(*p);
1379  prev = g;
1380  }
1381  }
1382  }
1383 
1384  drawForeground(*p, area);
1385 }
1386 
1387 /*
1388 \internal
1389 This method to informs the QtCanvas that a given chunk is
1390 `dirty' and needs to be redrawn in the next Update.
1391 
1392 (\a x, \a y) is a chunk location.
1393 
1394 The sprite classes call this. Any new derived class of QtCanvasItem
1395 must do so too. SetChangedChunkContaining can be used instead.
1396 */
1397 void
1399 {
1400  if (validChunk(x, y))
1401  {
1402  QtCanvasChunk& ch = chunk(x, y);
1403  ch.change();
1404  }
1405 }
1406 
1407 /*
1408 \internal
1409 This method to informs the QtCanvas that the chunk containing a given
1410 pixel is `dirty' and needs to be redrawn in the next Update.
1411 
1412 (\a x, \a y) is a pixel location.
1413 
1414 The item classes call this. Any new derived class of QtCanvasItem must
1415 do so too. SetChangedChunk can be used instead.
1416 */
1417 void
1419 {
1420  if (x >= 0 && x < width() && y >= 0 && y < height())
1421  {
1422  QtCanvasChunk& chunk = chunkContaining(x, y);
1423  chunk.change();
1424  }
1425 }
1426 
1427 /*
1428 \internal
1429 This method adds the QtCanvasItem \a g to the list of those which need to be
1430 drawn if the given chunk at location (\a x, \a y) is redrawn. Like
1431 SetChangedChunk and SetChangedChunkContaining, this method marks the
1432 chunk as `dirty'.
1433 */
1434 void
1436 {
1437  if (validChunk(x, y))
1438  {
1439  chunk(x, y).add(g);
1440  }
1441 }
1442 
1443 /*
1444 \internal
1445 This method removes the QtCanvasItem \a g from the list of those which need to
1446 be drawn if the given chunk at location (\a x, \a y) is redrawn. Like
1447 SetChangedChunk and SetChangedChunkContaining, this method marks the chunk
1448 as `dirty'.
1449 */
1450 void
1452 {
1453  if (validChunk(x, y))
1454  {
1455  chunk(x, y).remove(g);
1456  }
1457 }
1458 
1459 /*
1460 \internal
1461 This method adds the QtCanvasItem \a g to the list of those which need to be
1462 drawn if the chunk containing the given pixel (\a x, \a y) is redrawn. Like
1463 SetChangedChunk and SetChangedChunkContaining, this method marks the
1464 chunk as `dirty'.
1465 */
1466 void
1468 {
1469  if (x >= 0 && x < width() && y >= 0 && y < height())
1470  {
1471  chunkContaining(x, y).add(g);
1472  }
1473 }
1474 
1475 /*
1476 \internal
1477 This method removes the QtCanvasItem \a g from the list of those which need to
1478 be drawn if the chunk containing the given pixel (\a x, \a y) is redrawn.
1479 Like SetChangedChunk and SetChangedChunkContaining, this method
1480 marks the chunk as `dirty'.
1481 */
1482 void
1484 {
1485  if (x >= 0 && x < width() && y >= 0 && y < height())
1486  {
1487  chunkContaining(x, y).remove(g);
1488  }
1489 }
1490 
1491 /*
1492  Returns the color set by setBackgroundColor(). By default, this is
1493  white.
1494 
1495  This function is not a reimplementation of
1496  QWidget::backgroundColor() (QtCanvas is not a subclass of QWidget),
1497  but all QtCanvasViews that are viewing the canvas will set their
1498  backgrounds to this color.
1499 
1500  \sa setBackgroundColor(), backgroundPixmap()
1501 */
1502 QColor
1504 {
1505  return bgcolor;
1506 }
1507 
1508 /*
1509  Sets the solid background to be the color \a c.
1510 
1511  \sa backgroundColor(), setBackgroundPixmap(), setTiles()
1512 */
1513 void
1515 {
1516  if (bgcolor != c)
1517  {
1518  bgcolor = c;
1519 
1520  for (int i = 0; i < d->viewList.size(); ++i)
1521  {
1522  QtCanvasView* view = d->viewList.at(i);
1523  QPalette::ColorRole role = view->widget()->backgroundRole();
1524  QPalette viewPalette = view->widget()->palette();
1525  viewPalette.setColor(role, bgcolor);
1526  view->widget()->setPalette(viewPalette);
1527  }
1528 
1529  setAllChanged();
1530  }
1531 }
1532 
1533 /*
1534  Returns the pixmap set by setBackgroundPixmap(). By default,
1535  this is a null pixmap.
1536 
1537  \sa setBackgroundPixmap(), backgroundColor()
1538 */
1539 QPixmap
1541 {
1542  return pm;
1543 }
1544 
1545 /*
1546  Sets the solid background to be the pixmap \a p repeated as
1547  necessary to cover the entire canvas.
1548 
1549  \sa backgroundPixmap(), setBackgroundColor(), setTiles()
1550 */
1551 void
1553 {
1554  setTiles(p, 1, 1, p.width(), p.height());
1555 
1556  for (int i = 0; i < d->viewList.size(); ++i)
1557  {
1558  QtCanvasView* view = d->viewList.at(i);
1559  view->widget()->update();
1560  }
1561 }
1562 
1563 /*
1564  This virtual function is called for all updates of the canvas. It
1565  renders any background graphics using the painter \a painter, in
1566  the area \a clip. If the canvas has a background pixmap or a tiled
1567  background, that graphic is used, otherwise the canvas is cleared
1568  using the background color.
1569 
1570  If the graphics for an area change, you must explicitly call
1571  setChanged(const QRect&) for the result to be visible when
1572  update() is next called.
1573 
1574  \sa setBackgroundColor(), setBackgroundPixmap(), setTiles()
1575 */
1576 void
1577 QtCanvas::drawBackground(QPainter& painter, const QRect& clip)
1578 {
1579  if (pm.isNull())
1580  {
1581  painter.fillRect(clip, bgcolor);
1582  }
1583  else if (!grid)
1584  {
1585  for (int x = clip.x() / pm.width();
1586  x < (clip.x() + clip.width() + pm.width() - 1) / pm.width();
1587  x++)
1588  {
1589  for (int y = clip.y() / pm.height();
1590  y < (clip.y() + clip.height() + pm.height() - 1) / pm.height();
1591  y++)
1592  {
1593  painter.drawPixmap(x * pm.width(), y * pm.height(), pm);
1594  }
1595  }
1596  }
1597  else
1598  {
1599  const int x1 = clip.left() / tilew;
1600  int x2 = clip.right() / tilew;
1601  const int y1 = clip.top() / tileh;
1602  int y2 = clip.bottom() / tileh;
1603 
1604  const int roww = pm.width() / tilew;
1605 
1606  for (int j = y1; j <= y2; j++)
1607  {
1608  int jj = j % tilesVertically();
1609 
1610  for (int i = x1; i <= x2; i++)
1611  {
1612  int t = tile(i % tilesHorizontally(), jj);
1613  int tx = t % roww;
1614  int ty = t / roww;
1615  painter.drawPixmap(i * tilew, j * tileh, pm, tx * tilew, ty * tileh, tilew, tileh);
1616  }
1617  }
1618  }
1619 }
1620 
1621 /*
1622  This virtual function is called for all updates of the canvas. It
1623  renders any foreground graphics using the painter \a painter, in
1624  the area \a clip.
1625 
1626  If the graphics for an area change, you must explicitly call
1627  setChanged(const QRect&) for the result to be visible when
1628  update() is next called.
1629 
1630  The default is to draw nothing.
1631 */
1632 void
1633 QtCanvas::drawForeground(QPainter& painter, const QRect& clip)
1634 {
1635  if (debug_redraw_areas)
1636  {
1637  painter.setPen(red);
1638  painter.setBrush(NoBrush);
1639  painter.drawRect(clip);
1640  }
1641 }
1642 
1643 /*
1644  Sets the QtCanvas to be composed of \a h tiles horizontally and \a
1645  v tiles vertically. Each tile will be an image \a tilewidth by \a
1646  tileheight pixels from pixmap \a p.
1647 
1648  The pixmap \a p is a list of tiles, arranged left to right, (and
1649  in the case of pixmaps that have multiple rows of tiles, top to
1650  bottom), with tile 0 in the top-left corner, tile 1 next to the
1651  right, and so on, e.g.
1652 
1653  \table
1654  \row \i 0 \i 1 \i 2 \i 3
1655  \row \i 4 \i 5 \i 6 \i 7
1656  \endtable
1657 
1658  If the canvas is larger than the matrix of tiles, the entire
1659  matrix is repeated as necessary to cover the whole canvas. If it
1660  is smaller, tiles to the right and bottom are not visible.
1661 
1662  The width and height of \a p must be a multiple of \a tilewidth
1663  and \a tileheight. If they are not the function will do nothing.
1664 
1665  If you want to unset any tiling set, then just pass in a null
1666  pixmap and 0 for \a h, \a v, \a tilewidth, and
1667  \a tileheight.
1668 */
1669 void
1670 QtCanvas::setTiles(QPixmap p, int h, int v, int tilewidth, int tileheight)
1671 {
1672  if (!p.isNull() &&
1673  (!tilewidth || !tileheight || p.width() % tilewidth != 0 || p.height() % tileheight != 0))
1674  {
1675  return;
1676  }
1677 
1678  htiles = h;
1679  vtiles = v;
1680  delete[] grid;
1681  pm = p;
1682 
1683  if (h && v && !p.isNull())
1684  {
1685  grid = new ushort[h * v];
1686  memset(grid, 0, h * v * sizeof(ushort));
1687  tilew = tilewidth;
1688  tileh = tileheight;
1689  }
1690  else
1691  {
1692  grid = 0;
1693  }
1694 
1695  if (h + v > 10)
1696  {
1697  int s = scm(tilewidth, tileheight);
1698  retune(s < 128 ? s : qMax(tilewidth, tileheight));
1699  }
1700 
1701  setAllChanged();
1702 }
1703 
1704 /*
1705  \fn int QtCanvas::tile(int x, int y) const
1706 
1707  Returns the tile at position (\a x, \a y). Initially, all tiles
1708  are 0.
1709 
1710  The parameters must be within range, i.e.
1711  0 < \a x < tilesHorizontally() and
1712  0 < \a y < tilesVertically().
1713 
1714  \sa setTile()
1715 */
1716 
1717 /*
1718  \fn int QtCanvas::tilesHorizontally() const
1719 
1720  Returns the number of tiles horizontally.
1721 */
1722 
1723 /*
1724  \fn int QtCanvas::tilesVertically() const
1725 
1726  Returns the number of tiles vertically.
1727 */
1728 
1729 /*
1730  \fn int QtCanvas::tileWidth() const
1731 
1732  Returns the width of each tile.
1733 */
1734 
1735 /*
1736  \fn int QtCanvas::tileHeight() const
1737 
1738  Returns the height of each tile.
1739 */
1740 
1741 
1742 /*
1743  Sets the tile at (\a x, \a y) to use tile number \a tilenum, which
1744  is an index into the tile pixmaps. The canvas will update
1745  appropriately when update() is next called.
1746 
1747  The images are taken from the pixmap set by setTiles() and are
1748  arranged left to right, (and in the case of pixmaps that have
1749  multiple rows of tiles, top to bottom), with tile 0 in the
1750  top-left corner, tile 1 next to the right, and so on, e.g.
1751 
1752  \table
1753  \row \i 0 \i 1 \i 2 \i 3
1754  \row \i 4 \i 5 \i 6 \i 7
1755  \endtable
1756 
1757  \sa tile() setTiles()
1758 */
1759 void
1760 QtCanvas::setTile(int x, int y, int tilenum)
1761 {
1762  ushort& t = grid[x + y * htiles];
1763 
1764  if (t != tilenum)
1765  {
1766  t = tilenum;
1767 
1768  if (tilew == tileh && tilew == chunksize)
1769  {
1770  setChangedChunk(x, y); // common case
1771  }
1772  else
1773  {
1774  setChanged(QRect(x * tilew, y * tileh, tilew, tileh));
1775  }
1776  }
1777 }
1778 
1779 // lesser-used data in canvas item, plus room for extension.
1780 // Be careful adding to this - check all usages.
1782 {
1783  QtCanvasItemExtra() : vx(0.0), vy(0.0)
1784  {
1785  }
1786 
1787  double vx, vy;
1788  friend class QtCanvasItem;
1789 };
1790 
1791 /*
1792  \class QtCanvasItem qtcanvas.h
1793  \brief The QtCanvasItem class provides an abstract graphic object on a QtCanvas.
1794 
1795  A variety of QtCanvasItem subclasses provide immediately usable
1796  behaviour. This class is a pure abstract superclass providing the
1797  behaviour that is shared among all the concrete canvas item classes.
1798  QtCanvasItem is not intended for direct subclassing. It is much easier
1799  to subclass one of its subclasses, e.g. QtCanvasPolygonalItem (the
1800  commonest base class), QtCanvasRectangle, QtCanvasSprite, QtCanvasEllipse
1801  or QtCanvasText.
1802 
1803  Canvas items are added to a canvas by constructing them and passing the
1804  canvas to the canvas item's constructor. An item can be moved to a
1805  different canvas using setCanvas().
1806 
1807  Items appear on the canvas after their \link show() show()\endlink
1808  function has been called (or \link setVisible()
1809  setVisible(true)\endlink), and \e after update() has been called. The
1810  canvas only shows items that are \link setVisible() visible\endlink,
1811  and then only if \l update() is called. If you created the canvas
1812  without passing a width and height to the constructor you'll also need
1813  to call \link QtCanvas::resize() resize()\endlink. Since the canvas
1814  background defaults to white and canvas items default to white,
1815  you may need to change colors to see your items.
1816 
1817  A QtCanvasItem object can be moved in the x(), y() and z() dimensions
1818  using functions such as move(), moveBy(), setX(), setY() and setZ(). A
1819  canvas item can be set in motion, `animated', using setAnimated() and
1820  given a velocity in the x and y directions with setXVelocity() and
1821  setYVelocity() -- the same effect can be achieved by calling
1822  setVelocity(). Use the collidesWith() function to see if the canvas item
1823  will collide on the \e next advance(1) and use collisions() to see what
1824  collisions have occurred.
1825 
1826  Use QtCanvasSprite or your own subclass of QtCanvasSprite to create canvas
1827  items which are animated, i.e. which change over time.
1828 
1829  The size of a canvas item is given by boundingRect(). Use
1830  boundingRectAdvanced() to see what the size of the canvas item will be
1831  \e after the next advance(1) call.
1832 
1833  The rtti() function is used for identifying subclasses of QtCanvasItem.
1834  The canvas() function returns a pointer to the canvas which contains the
1835  canvas item.
1836 
1837  QtCanvasItem provides the show() and isVisible() functions like those in
1838  QWidget.
1839 
1840  QtCanvasItem also provides the setEnabled(), setActive() and
1841  setSelected() functions; these functions set the relevant boolean and
1842  cause a repaint but the boolean values they set are not used in
1843  QtCanvasItem itself. You can make use of these booleans in your subclasses.
1844 
1845  By default, canvas items have no velocity, no size, and are not in
1846  motion. The subclasses provided in Qt do not change these defaults
1847  except where noted.
1848 
1849 */
1850 
1851 /*
1852  \enum QtCanvasItem::RttiValues
1853 
1854  This enum is used to name the different types of canvas item.
1855 
1856  \value Rtti_Item Canvas item abstract base class
1857  \value Rtti_Ellipse
1858  \value Rtti_Line
1859  \value Rtti_Polygon
1860  \value Rtti_PolygonalItem
1861  \value Rtti_Rectangle
1862  \value Rtti_Spline
1863  \value Rtti_Sprite
1864  \value Rtti_Text
1865 
1866 */
1867 
1868 /*
1869  \fn void QtCanvasItem::update()
1870 
1871  Call this function to repaint the canvas's changed chunks.
1872 */
1873 
1874 /*
1875  Constructs a QtCanvasItem on canvas \a canvas.
1876 
1877  \sa setCanvas()
1878 */
1879 QtCanvasItem::QtCanvasItem(QtCanvas* canvas) : cnv(canvas), myx(0), myy(0), myz(0)
1880 {
1881  ani = 0;
1882  vis = 0;
1883  val = 0;
1884  sel = 0;
1885  ena = 0;
1886  act = 0;
1887 
1888  ext = 0;
1889 
1890  if (cnv)
1891  {
1892  cnv->addItem(this);
1893  }
1894 }
1895 
1896 /*
1897  Destroys the QtCanvasItem and removes it from its canvas.
1898 */
1900 {
1901  if (cnv)
1902  {
1903  cnv->removeItem(this);
1904  cnv->removeAnimation(this);
1905  }
1906 
1907  delete ext;
1908 }
1909 
1911 QtCanvasItem::extra()
1912 {
1913  if (!ext)
1914  {
1915  ext = new QtCanvasItemExtra;
1916  }
1917 
1918  return *ext;
1919 }
1920 
1921 /*
1922  \fn double QtCanvasItem::x() const
1923 
1924  Returns the horizontal position of the canvas item. Note that
1925  subclasses often have an origin other than the top-left corner.
1926 */
1927 
1928 /*
1929  \fn double QtCanvasItem::y() const
1930 
1931  Returns the vertical position of the canvas item. Note that
1932  subclasses often have an origin other than the top-left corner.
1933 */
1934 
1935 /*
1936  \fn double QtCanvasItem::z() const
1937 
1938  Returns the z index of the canvas item, which is used for visual
1939  order: higher-z items obscure (are in front of) lower-z items.
1940 */
1941 
1942 /*
1943  \fn void QtCanvasItem::setX(double x)
1944 
1945  Moves the canvas item so that its x-position is \a x.
1946 
1947  \sa x(), move()
1948 */
1949 
1950 /*
1951  \fn void QtCanvasItem::setY(double y)
1952 
1953  Moves the canvas item so that its y-position is \a y.
1954 
1955  \sa y(), move()
1956 */
1957 
1958 /*
1959  \fn void QtCanvasItem::setZ(double z)
1960 
1961  Sets the z index of the canvas item to \a z. Higher-z items
1962  obscure (are in front of) lower-z items.
1963 
1964  \sa z(), move()
1965 */
1966 
1967 
1968 /*
1969  Moves the canvas item relative to its current position by (\a dx,
1970  \a dy).
1971 */
1972 void
1973 QtCanvasItem::moveBy(double dx, double dy)
1974 {
1975  if (dx || dy)
1976  {
1977  removeFromChunks();
1978  myx += dx;
1979  myy += dy;
1980  addToChunks();
1981  }
1982 }
1983 
1984 /*
1985  Moves the canvas item to the absolute position (\a x, \a y).
1986 */
1987 void
1988 QtCanvasItem::move(double x, double y)
1989 {
1990  moveBy(x - myx, y - myy);
1991 }
1992 
1993 /*
1994  Returns true if the canvas item is in motion; otherwise returns
1995  false.
1996 
1997  \sa setVelocity(), setAnimated()
1998 */
1999 bool
2001 {
2002  return (bool)ani;
2003 }
2004 
2005 /*
2006  Sets the canvas item to be in motion if \a y is true, or not if \a
2007  y is false. The speed and direction of the motion is set with
2008  setVelocity(), or with setXVelocity() and setYVelocity().
2009 
2010  \sa advance(), QtCanvas::advance()
2011 */
2012 void
2014 {
2015  if (y != (bool)ani)
2016  {
2017  ani = (uint)y;
2018 
2019  if (y)
2020  {
2021  cnv->addAnimation(this);
2022  }
2023  else
2024  {
2025  cnv->removeAnimation(this);
2026  }
2027  }
2028 }
2029 
2030 /*
2031  \fn void QtCanvasItem::setXVelocity(double vx)
2032 
2033  Sets the horizontal component of the canvas item's velocity to \a vx.
2034 
2035  \sa setYVelocity() setVelocity()
2036 */
2037 
2038 /*
2039  \fn void QtCanvasItem::setYVelocity(double vy)
2040 
2041  Sets the vertical component of the canvas item's velocity to \a vy.
2042 
2043  \sa setXVelocity() setVelocity()
2044 */
2045 
2046 /*
2047  Sets the canvas item to be in motion, moving by \a vx and \a vy
2048  pixels in the horizontal and vertical directions respectively.
2049 
2050  \sa advance() setXVelocity() setYVelocity()
2051 */
2052 void
2053 QtCanvasItem::setVelocity(double vx, double vy)
2054 {
2055  if (ext || vx != 0.0 || vy != 0.0)
2056  {
2057  if (!ani)
2058  {
2059  setAnimated(true);
2060  }
2061 
2062  extra().vx = vx;
2063  extra().vy = vy;
2064  }
2065 }
2066 
2067 /*
2068  Returns the horizontal velocity component of the canvas item.
2069 */
2070 double
2072 {
2073  return ext ? ext->vx : 0;
2074 }
2075 
2076 /*
2077  Returns the vertical velocity component of the canvas item.
2078 */
2079 double
2081 {
2082  return ext ? ext->vy : 0;
2083 }
2084 
2085 /*
2086  The default implementation moves the canvas item, if it is
2087  animated(), by the preset velocity if \a phase is 1, and does
2088  nothing if \a phase is 0.
2089 
2090  Note that if you reimplement this function, the reimplementation
2091  must not change the canvas in any way, for example it must not add
2092  or remove items.
2093 
2094  \sa QtCanvas::advance() setVelocity()
2095 */
2096 void
2098 {
2099  if (ext && phase == 1)
2100  {
2101  moveBy(ext->vx, ext->vy);
2102  }
2103 }
2104 
2105 /*
2106  \fn void QtCanvasItem::draw(QPainter& painter)
2107 
2108  This abstract virtual function draws the canvas item using \a painter.
2109 */
2110 
2111 /*
2112  Sets the QtCanvas upon which the canvas item is to be drawn to \a c.
2113 
2114  \sa canvas()
2115 */
2116 void
2118 {
2119  bool v = isVisible();
2120  setVisible(false);
2121 
2122  if (cnv)
2123  {
2124  if (ext)
2125  {
2126  cnv->removeAnimation(this);
2127  }
2128 
2129  cnv->removeItem(this);
2130  }
2131 
2132  cnv = c;
2133 
2134  if (cnv)
2135  {
2136  cnv->addItem(this);
2137 
2138  if (ext)
2139  {
2140  cnv->addAnimation(this);
2141  }
2142  }
2143 
2144  setVisible(v);
2145 }
2146 
2147 /*
2148  \fn QtCanvas* QtCanvasItem::canvas() const
2149 
2150  Returns the canvas containing the canvas item.
2151 */
2152 
2153 /* Shorthand for setVisible(true). */
2154 void
2156 {
2157  setVisible(true);
2158 }
2159 
2160 /* Shorthand for setVisible(false). */
2161 void
2163 {
2164  setVisible(false);
2165 }
2166 
2167 /*
2168  Makes the canvas item visible if \a yes is true, or invisible if
2169  \a yes is false. The change takes effect when QtCanvas::update() is
2170  next called.
2171 */
2172 void
2174 {
2175  if ((bool)vis != yes)
2176  {
2177  if (yes)
2178  {
2179  vis = (uint)yes;
2180  addToChunks();
2181  }
2182  else
2183  {
2184  removeFromChunks();
2185  vis = (uint)yes;
2186  }
2187  }
2188 }
2189 
2190 /*
2191  \obsolete
2192  \fn bool QtCanvasItem::visible() const
2193  Use isVisible() instead.
2194 */
2195 
2196 /*
2197  \fn bool QtCanvasItem::isVisible() const
2198 
2199  Returns true if the canvas item is visible; otherwise returns
2200  false.
2201 
2202  Note that in this context true does \e not mean that the canvas
2203  item is currently in a view, merely that if a view is showing the
2204  area where the canvas item is positioned, and the item is not
2205  obscured by items with higher z values, and the view is not
2206  obscured by overlaying windows, it would be visible.
2207 
2208  \sa setVisible(), z()
2209 */
2210 
2211 /*
2212  \obsolete
2213  \fn bool QtCanvasItem::selected() const
2214  Use isSelected() instead.
2215 */
2216 
2217 /*
2218  \fn bool QtCanvasItem::isSelected() const
2219 
2220  Returns true if the canvas item is selected; otherwise returns false.
2221 */
2222 
2223 /*
2224  Sets the selected flag of the item to \a yes. If this changes the
2225  item's selected state the item will be redrawn when
2226  QtCanvas::update() is next called.
2227 
2228  The QtCanvas, QtCanvasItem and the Qt-supplied QtCanvasItem
2229  subclasses do not make use of this value. The setSelected()
2230  function is supplied because many applications need it, but it is
2231  up to you how you use the isSelected() value.
2232 */
2233 void
2235 {
2236  if ((bool)sel != yes)
2237  {
2238  sel = (uint)yes;
2239  changeChunks();
2240  }
2241 }
2242 
2243 /*
2244  \obsolete
2245  \fn bool QtCanvasItem::enabled() const
2246  Use isEnabled() instead.
2247 */
2248 
2249 /*
2250  \fn bool QtCanvasItem::isEnabled() const
2251 
2252  Returns true if the QtCanvasItem is enabled; otherwise returns false.
2253 */
2254 
2255 /*
2256  Sets the enabled flag of the item to \a yes. If this changes the
2257  item's enabled state the item will be redrawn when
2258  QtCanvas::update() is next called.
2259 
2260  The QtCanvas, QtCanvasItem and the Qt-supplied QtCanvasItem
2261  subclasses do not make use of this value. The setEnabled()
2262  function is supplied because many applications need it, but it is
2263  up to you how you use the isEnabled() value.
2264 */
2265 void
2267 {
2268  if (ena != (uint)yes)
2269  {
2270  ena = (uint)yes;
2271  changeChunks();
2272  }
2273 }
2274 
2275 /*
2276  \obsolete
2277  \fn bool QtCanvasItem::active() const
2278  Use isActive() instead.
2279 */
2280 
2281 /*
2282  \fn bool QtCanvasItem::isActive() const
2283 
2284  Returns true if the QtCanvasItem is active; otherwise returns false.
2285 */
2286 
2287 /*
2288  Sets the active flag of the item to \a yes. If this changes the
2289  item's active state the item will be redrawn when
2290  QtCanvas::update() is next called.
2291 
2292  The QtCanvas, QtCanvasItem and the Qt-supplied QtCanvasItem
2293  subclasses do not make use of this value. The setActive() function
2294  is supplied because many applications need it, but it is up to you
2295  how you use the isActive() value.
2296 */
2297 void
2299 {
2300  if (act != (uint)yes)
2301  {
2302  act = (uint)yes;
2303  changeChunks();
2304  }
2305 }
2306 
2307 bool
2309 {
2310  const QImage* s2image = s2->imageAdvanced()->collision_mask;
2311  QRect s2area = s2->boundingRectAdvanced();
2312 
2313  QRect cyourarea(s2area.x(), s2area.y(), s2area.width(), s2area.height());
2314 
2315  QImage* s1image = s1->imageAdvanced()->collision_mask;
2316 
2317  QRect s1area = s1->boundingRectAdvanced();
2318 
2319  QRect ourarea = s1area.intersected(cyourarea);
2320 
2321  if (ourarea.isEmpty())
2322  {
2323  return false;
2324  }
2325 
2326  int x2 = ourarea.x() - cyourarea.x();
2327  int y2 = ourarea.y() - cyourarea.y();
2328  int x1 = ourarea.x() - s1area.x();
2329  int y1 = ourarea.y() - s1area.y();
2330  int w = ourarea.width();
2331  int h = ourarea.height();
2332 
2333  if (!s2image)
2334  {
2335  if (!s1image)
2336  {
2337  return w > 0 && h > 0;
2338  }
2339 
2340  // swap everything around
2341  int t;
2342  t = x1;
2343  x1 = x2;
2344  x2 = t;
2345  t = y1;
2346  x1 = y2;
2347  y2 = t;
2348  s2image = s1image;
2349  s1image = 0;
2350  }
2351 
2352  // s2image != 0
2353 
2354  // A non-linear search may be more efficient.
2355  // Perhaps spiralling out from the center, or a simpler
2356  // vertical expansion from the centreline.
2357 
2358  // We assume that sprite masks don't have
2359  // different bit orders.
2360  //
2361  // Q_ASSERT(s1image->bitOrder() == s2image->bitOrder());
2362 
2363  if (s1image)
2364  {
2365  if (s1image->format() == QImage::Format_MonoLSB)
2366  {
2367  for (int j = 0; j < h; j++)
2368  {
2369  uchar* ml = s1image->scanLine(y1 + j);
2370  const uchar* yl = s2image->scanLine(y2 + j);
2371 
2372  for (int i = 0; i < w; i++)
2373  {
2374  if (*(yl + ((x2 + i) >> 3)) & (1 << ((x2 + i) & 7)) &&
2375  *(ml + ((x1 + i) >> 3)) & (1 << ((x1 + i) & 7)))
2376  {
2377  return true;
2378  }
2379  }
2380  }
2381  }
2382  else
2383  {
2384  for (int j = 0; j < h; j++)
2385  {
2386  uchar* ml = s1image->scanLine(y1 + j);
2387  const uchar* yl = s2image->scanLine(y2 + j);
2388 
2389  for (int i = 0; i < w; i++)
2390  {
2391  if (*(yl + ((x2 + i) >> 3)) & (1 << (7 - ((x2 + i) & 7))) &&
2392  *(ml + ((x1 + i) >> 3)) & (1 << (7 - ((x1 + i) & 7))))
2393  {
2394  return true;
2395  }
2396  }
2397  }
2398  }
2399  }
2400  else
2401  {
2402  if (s2image->format() == QImage::Format_MonoLSB)
2403  {
2404  for (int j = 0; j < h; j++)
2405  {
2406  const uchar* yl = s2image->scanLine(y2 + j);
2407 
2408  for (int i = 0; i < w; i++)
2409  {
2410  if (*(yl + ((x2 + i) >> 3)) & (1 << ((x2 + i) & 7)))
2411  {
2412  return true;
2413  }
2414  }
2415  }
2416  }
2417  else
2418  {
2419  for (int j = 0; j < h; j++)
2420  {
2421  const uchar* yl = s2image->scanLine(y2 + j);
2422 
2423  for (int i = 0; i < w; i++)
2424  {
2425  if (*(yl + ((x2 + i) >> 3)) & (1 << (7 - ((x2 + i) & 7))))
2426  {
2427  return true;
2428  }
2429  }
2430  }
2431  }
2432  }
2433 
2434  return false;
2435 }
2436 
2437 static bool
2438 collision_double_dispatch(const QtCanvasSprite* s1,
2439  const QtCanvasPolygonalItem* p1,
2440  const QtCanvasRectangle* r1,
2441  const QtCanvasEllipse* e1,
2442  const QtCanvasText* t1,
2443  const QtCanvasSprite* s2,
2444  const QtCanvasPolygonalItem* p2,
2445  const QtCanvasRectangle* r2,
2446  const QtCanvasEllipse* e2,
2447  const QtCanvasText* t2)
2448 {
2449  const QtCanvasItem* i1 = s1 ? (const QtCanvasItem*)s1
2450  : p1 ? (const QtCanvasItem*)p1
2451  : r1 ? (const QtCanvasItem*)r1
2452  : e1 ? (const QtCanvasItem*)e1
2453  : (const QtCanvasItem*)t1;
2454  const QtCanvasItem* i2 = s2 ? (const QtCanvasItem*)s2
2455  : p2 ? (const QtCanvasItem*)p2
2456  : r2 ? (const QtCanvasItem*)r2
2457  : e2 ? (const QtCanvasItem*)e2
2458  : (const QtCanvasItem*)t2;
2459 
2460  if (s1 && s2)
2461  {
2462  // a
2463  return qt_testCollision(s1, s2);
2464  }
2465  else if ((r1 || t1 || s1) && (r2 || t2 || s2))
2466  {
2467  // b
2468  QRect rc1 = i1->boundingRectAdvanced();
2469  QRect rc2 = i2->boundingRectAdvanced();
2470  return rc1.intersects(rc2);
2471  }
2472  else if (e1 && e2 && e1->angleLength() >= 360 * 16 && e2->angleLength() >= 360 * 16 &&
2473  e1->width() == e1->height() && e2->width() == e2->height())
2474  {
2475  // c
2476  double xd = (e1->x() + e1->xVelocity()) - (e2->x() + e1->xVelocity());
2477  double yd = (e1->y() + e1->yVelocity()) - (e2->y() + e1->yVelocity());
2478  double rd = (e1->width() + e2->width()) / 2;
2479  return xd * xd + yd * yd <= rd * rd;
2480  }
2481  else if (p1 && (p2 || s2 || t2))
2482  {
2483  // d
2484  QPolygon pa1 = p1->areaPointsAdvanced();
2485  QPolygon pa2 = p2 ? p2->areaPointsAdvanced() : QPolygon(i2->boundingRectAdvanced());
2486  bool col = !(QRegion(pa1) & QRegion(pa2, Qt::WindingFill)).isEmpty();
2487 
2488  return col;
2489  }
2490  else
2491  {
2492  return collision_double_dispatch(s2, p2, r2, e2, t2, s1, p1, r1, e1, t1);
2493  }
2494 }
2495 
2496 /*
2497  \fn bool QtCanvasItem::collidesWith(const QtCanvasItem* other) const
2498 
2499  Returns true if the canvas item will collide with the \a other
2500  item \e after they have moved by their current velocities;
2501  otherwise returns false.
2502 
2503  \sa collisions()
2504 */
2505 
2506 
2507 /*
2508  \class QtCanvasSprite qtcanvas.h
2509  \brief The QtCanvasSprite class provides an animated canvas item on a QtCanvas.
2510 
2511  A canvas sprite is an object which can contain any number of images
2512  (referred to as frames), only one of which is current, i.e.
2513  displayed, at any one time. The images can be passed in the
2514  constructor or set or changed later with setSequence(). If you
2515  subclass QtCanvasSprite you can change the frame that is displayed
2516  periodically, e.g. whenever QtCanvasItem::advance(1) is called to
2517  create the effect of animation.
2518 
2519  The current frame can be set with setFrame() or with move(). The
2520  number of frames available is given by frameCount(). The bounding
2521  rectangle of the current frame is returned by boundingRect().
2522 
2523  The current frame's image can be retrieved with image(); use
2524  imageAdvanced() to retrieve the image for the frame that will be
2525  shown after advance(1) is called. Use the image() overload passing
2526  it an integer index to retrieve a particular image from the list of
2527  frames.
2528 
2529  Use width() and height() to retrieve the dimensions of the current
2530  frame.
2531 
2532  Use leftEdge() and rightEdge() to retrieve the current frame's
2533  left-hand and right-hand x-coordinates respectively. Use
2534  bottomEdge() and topEdge() to retrieve the current frame's bottom
2535  and top y-coordinates respectively. These functions have an overload
2536  which will accept an integer frame number to retrieve the
2537  coordinates of a particular frame.
2538 
2539  QtCanvasSprite draws very quickly, at the expense of memory.
2540 
2541  The current frame's image can be drawn on a painter with draw().
2542 
2543  Like any other canvas item, canvas sprites can be moved with
2544  move() which sets the x and y coordinates and the frame number, as
2545  well as with QtCanvasItem::move() and QtCanvasItem::moveBy(), or by
2546  setting coordinates with QtCanvasItem::setX(), QtCanvasItem::setY()
2547  and QtCanvasItem::setZ().
2548 
2549 */
2550 
2551 
2552 /*
2553  \reimp
2554 */
2555 bool
2557 {
2558  return i->collidesWith(this, 0, 0, 0, 0);
2559 }
2560 
2561 /*
2562  Returns true if the canvas item collides with any of the given
2563  items; otherwise returns false. The parameters, \a s, \a p, \a r,
2564  \a e and \a t, are all the same object, this is just a type
2565  resolution trick.
2566 */
2567 bool
2569  const QtCanvasPolygonalItem* p,
2570  const QtCanvasRectangle* r,
2571  const QtCanvasEllipse* e,
2572  const QtCanvasText* t) const
2573 {
2574  return collision_double_dispatch(s, p, r, e, t, this, 0, 0, 0, 0);
2575 }
2576 
2577 /*
2578  \reimp
2579 */
2580 bool
2582 {
2583  return i->collidesWith(0, this, 0, 0, 0);
2584 }
2585 
2586 bool
2588  const QtCanvasPolygonalItem* p,
2589  const QtCanvasRectangle* r,
2590  const QtCanvasEllipse* e,
2591  const QtCanvasText* t) const
2592 {
2593  return collision_double_dispatch(s, p, r, e, t, 0, this, 0, 0, 0);
2594 }
2595 
2596 /*
2597  \reimp
2598 */
2599 bool
2601 {
2602  return i->collidesWith(0, this, this, 0, 0);
2603 }
2604 
2605 bool
2607  const QtCanvasPolygonalItem* p,
2608  const QtCanvasRectangle* r,
2609  const QtCanvasEllipse* e,
2610  const QtCanvasText* t) const
2611 {
2612  return collision_double_dispatch(s, p, r, e, t, 0, this, this, 0, 0);
2613 }
2614 
2615 /*
2616  \reimp
2617 */
2618 bool
2620 {
2621  return i->collidesWith(0, this, 0, this, 0);
2622 }
2623 
2624 bool
2626  const QtCanvasPolygonalItem* p,
2627  const QtCanvasRectangle* r,
2628  const QtCanvasEllipse* e,
2629  const QtCanvasText* t) const
2630 {
2631  return collision_double_dispatch(s, p, r, e, t, 0, this, 0, this, 0);
2632 }
2633 
2634 /*
2635  \reimp
2636 */
2637 bool
2639 {
2640  return i->collidesWith(0, 0, 0, 0, this);
2641 }
2642 
2643 bool
2645  const QtCanvasPolygonalItem* p,
2646  const QtCanvasRectangle* r,
2647  const QtCanvasEllipse* e,
2648  const QtCanvasText* t) const
2649 {
2650  return collision_double_dispatch(s, p, r, e, t, 0, 0, 0, 0, this);
2651 }
2652 
2653 /*
2654  Returns the list of canvas items that this canvas item has
2655  collided with.
2656 
2657  A collision is generally defined as occurring when the pixels of
2658  one item draw on the pixels of another item, but not all
2659  subclasses are so precise. Also, since pixel-wise collision
2660  detection can be slow, this function works in either exact or
2661  inexact mode, according to the \a exact parameter.
2662 
2663  If \a exact is true, the canvas items returned have been
2664  accurately tested for collision with the canvas item.
2665 
2666  If \a exact is false, the canvas items returned are \e near the
2667  canvas item. You can test the canvas items returned using
2668  collidesWith() if any are interesting collision candidates. By
2669  using this approach, you can ignore some canvas items for which
2670  collisions are not relevant.
2671 
2672  The returned list is a list of QtCanvasItems, but often you will
2673  need to cast the items to their subclass types. The safe way to do
2674  this is to use rtti() before casting. This provides some of the
2675  functionality of the standard C++ dynamic cast operation even on
2676  compilers where dynamic casts are not available.
2677 
2678  Note that a canvas item may be `on' a canvas, e.g. it was created
2679  with the canvas as parameter, even though its coordinates place it
2680  beyond the edge of the canvas's area. Collision detection only
2681  works for canvas items which are wholly or partly within the
2682  canvas's area.
2683 
2684  Note that if items have a velocity (see \l setVelocity()), then
2685  collision testing is done based on where the item \e will be when
2686  it moves, not its current location. For example, a "ball" item
2687  doesn't need to actually embed into a "wall" item before a
2688  collision is detected. For items without velocity, plain
2689  intersection is used.
2690 */
2692 QtCanvasItem::collisions(bool exact) const
2693 {
2694  return canvas()->collisions(chunks(), this, exact);
2695 }
2696 
2697 /*
2698  Returns a list of canvas items that collide with the point \a p.
2699  The list is ordered by z coordinates, from highest z coordinate
2700  (front-most item) to lowest z coordinate (rear-most item).
2701 */
2703 QtCanvas::collisions(const QPoint& p) const
2704 {
2705  return collisions(QRect(p, QSize(1, 1)));
2706 }
2707 
2708 /*
2709  \overload
2710 
2711  Returns a list of items which collide with the rectangle \a r. The
2712  list is ordered by z coordinates, from highest z coordinate
2713  (front-most item) to lowest z coordinate (rear-most item).
2714 */
2716 QtCanvas::collisions(const QRect& r) const
2717 {
2718  QtCanvasRectangle i(r, (QtCanvas*)this);
2719  i.setPen(NoPen);
2720  i.show(); // doesn't actually show, since we destroy it
2721  QtCanvasItemList l = i.collisions(true);
2722  qSort(l.begin(), l.end(), QtCanvasItemLess());
2723  return l;
2724 }
2725 
2726 /*
2727  \overload
2728 
2729  Returns a list of canvas items which intersect with the chunks
2730  listed in \a chunklist, excluding \a item. If \a exact is true,
2731  only those which actually \link QtCanvasItem::collidesWith()
2732  collide with\endlink \a item are returned; otherwise canvas items
2733  are included just for being in the chunks.
2734 
2735  This is a utility function mainly used to implement the simpler
2736  QtCanvasItem::collisions() function.
2737 */
2739 QtCanvas::collisions(const QPolygon& chunklist, const QtCanvasItem* item, bool exact) const
2740 {
2741  QSet<QtCanvasItem*> seen;
2742  QtCanvasItemList result;
2743 
2744  for (int i = 0; i < (int)chunklist.count(); i++)
2745  {
2746  int x = chunklist[i].x();
2747  int y = chunklist[i].y();
2748 
2749  if (validChunk(x, y))
2750  {
2751  const QtCanvasItemList& l = chunk(x, y).list();
2752 
2753  for (int i = 0; i < l.size(); ++i)
2754  {
2755  QtCanvasItem* g = l.at(i);
2756 
2757  if (g != item)
2758  {
2759  if (!seen.contains(g))
2760  {
2761  seen.insert(g);
2762 
2763  if (!exact || item->collidesWith(g))
2764  {
2765  result.append(g);
2766  }
2767  }
2768  }
2769  }
2770  }
2771  }
2772 
2773  return result;
2774 }
2775 
2776 /*
2777  \internal
2778  Adds the item to all the chunks it covers.
2779 */
2780 void
2781 QtCanvasItem::addToChunks()
2782 {
2783  if (isVisible() && canvas())
2784  {
2785  QPolygon pa = chunks();
2786 
2787  for (int i = 0; i < (int)pa.count(); i++)
2788  {
2789  canvas()->addItemToChunk(this, pa[i].x(), pa[i].y());
2790  }
2791 
2792  val = (uint) true;
2793  }
2794 }
2795 
2796 /*
2797  \internal
2798  Removes the item from all the chunks it covers.
2799 */
2800 void
2801 QtCanvasItem::removeFromChunks()
2802 {
2803  if (isVisible() && canvas())
2804  {
2805  QPolygon pa = chunks();
2806 
2807  for (int i = 0; i < (int)pa.count(); i++)
2808  {
2809  canvas()->removeItemFromChunk(this, pa[i].x(), pa[i].y());
2810  }
2811  }
2812 }
2813 
2814 /*
2815  \internal
2816  Sets all the chunks covered by the item to be refreshed with QtCanvas::update()
2817  is next called.
2818 */
2819 void
2820 QtCanvasItem::changeChunks()
2821 {
2822  if (isVisible() && canvas())
2823  {
2824  if (!val)
2825  {
2826  addToChunks();
2827  }
2828 
2829  QPolygon pa = chunks();
2830 
2831  for (int i = 0; i < (int)pa.count(); i++)
2832  {
2833  canvas()->setChangedChunk(pa[i].x(), pa[i].y());
2834  }
2835  }
2836 }
2837 
2838 /*
2839  \fn QRect QtCanvasItem::boundingRect() const
2840 
2841  Returns the bounding rectangle in pixels that the canvas item covers.
2842 
2843  \sa boundingRectAdvanced()
2844 */
2845 
2846 /*
2847  Returns the bounding rectangle of pixels that the canvas item \e
2848  will cover after advance(1) is called.
2849 
2850  \sa boundingRect()
2851 */
2852 QRect
2854 {
2855  int dx = int(x() + xVelocity()) - int(x());
2856  int dy = int(y() + yVelocity()) - int(y());
2857  QRect r = boundingRect();
2858  r.translate(dx, dy);
2859  return r;
2860 }
2861 
2862 /*
2863  \class QtCanvasPixmap qtcanvas.h
2864  \brief The QtCanvasPixmap class provides pixmaps for QtCanvasSprites.
2865 
2866  If you want to show a single pixmap on a QtCanvas use a
2867  QtCanvasSprite with just one pixmap.
2868 
2869  When pixmaps are inserted into a QtCanvasPixmapArray they are held
2870  as QtCanvasPixmaps. \l{QtCanvasSprite}s are used to show pixmaps on
2871  \l{QtCanvas}es and hold their pixmaps in a QtCanvasPixmapArray. If
2872  you retrieve a frame (pixmap) from a QtCanvasSprite it will be
2873  returned as a QtCanvasPixmap.
2874 
2875  The pixmap is a QPixmap and can only be set in the constructor.
2876  There are three different constructors, one taking a QPixmap, one
2877  a QImage and one a file name that refers to a file in any
2878  supported file format (see QImageReader).
2879 
2880  QtCanvasPixmap can have a hotspot which is defined in terms of an (x,
2881  y) offset. When you create a QtCanvasPixmap from a PNG file or from
2882  a QImage that has a QImage::offset(), the offset() is initialized
2883  appropriately, otherwise the constructor leaves it at (0, 0). You
2884  can set it later using setOffset(). When the QtCanvasPixmap is used
2885  in a QtCanvasSprite, the offset position is the point at
2886  QtCanvasItem::x() and QtCanvasItem::y(), not the top-left corner of
2887  the pixmap.
2888 
2889  Note that for QtCanvasPixmap objects created by a QtCanvasSprite, the
2890  position of each QtCanvasPixmap object is set so that the hotspot
2891  stays in the same position.
2892 
2893  \sa QtCanvasPixmapArray QtCanvasItem QtCanvasSprite
2894 */
2895 
2896 
2897 /*
2898  Constructs a QtCanvasPixmap that uses the image stored in \a
2899  datafilename.
2900 */
2901 QtCanvasPixmap::QtCanvasPixmap(const QString& datafilename)
2902 {
2903  QImage image(datafilename);
2904  init(image);
2905 }
2906 
2907 /*
2908  Constructs a QtCanvasPixmap from the image \a image.
2909 */
2911 {
2912  init(image);
2913 }
2914 
2915 /*
2916  Constructs a QtCanvasPixmap from the pixmap \a pm using the offset
2917  \a offset.
2918 */
2919 QtCanvasPixmap::QtCanvasPixmap(const QPixmap& pm, const QPoint& offset)
2920 {
2921  init(pm, offset.x(), offset.y());
2922 }
2923 
2924 void
2925 QtCanvasPixmap::init(const QImage& image)
2926 {
2927  this->QPixmap::operator=(QPixmap::fromImage(image));
2928  hotx = image.offset().x();
2929  hoty = image.offset().y();
2930 #ifndef QT_NO_IMAGE_DITHER_TO_1
2931 
2932  if (image.hasAlphaChannel())
2933  {
2934  QImage i = image.createAlphaMask();
2935  collision_mask = new QImage(i);
2936  }
2937  else
2938 #endif
2939  collision_mask = 0;
2940 }
2941 
2942 void
2943 QtCanvasPixmap::init(const QPixmap& pixmap, int hx, int hy)
2944 {
2945  (QPixmap&)* this = pixmap;
2946  hotx = hx;
2947  hoty = hy;
2948 
2949  if (pixmap.hasAlphaChannel())
2950  {
2951  QImage i = mask().toImage();
2952  collision_mask = new QImage(i);
2953  }
2954  else
2955  {
2956  collision_mask = 0;
2957  }
2958 }
2959 
2960 /*
2961  Destroys the pixmap.
2962 */
2964 {
2965  delete collision_mask;
2966 }
2967 
2968 /*
2969  \fn int QtCanvasPixmap::offsetX() const
2970 
2971  Returns the x-offset of the pixmap's hotspot.
2972 
2973  \sa setOffset()
2974 */
2975 
2976 /*
2977  \fn int QtCanvasPixmap::offsetY() const
2978 
2979  Returns the y-offset of the pixmap's hotspot.
2980 
2981  \sa setOffset()
2982 */
2983 
2984 /*
2985  \fn void QtCanvasPixmap::setOffset(int x, int y)
2986 
2987  Sets the offset of the pixmap's hotspot to (\a x, \a y).
2988 
2989  \warning Do not call this function if any QtCanvasSprites are
2990  currently showing this pixmap.
2991 */
2992 
2993 /*
2994  \class QtCanvasPixmapArray qtcanvas.h
2995  \brief The QtCanvasPixmapArray class provides an array of QtCanvasPixmaps.
2996 
2997  This class is used by QtCanvasSprite to hold an array of pixmaps.
2998  It is used to implement animated sprites, i.e. images that change
2999  over time, with each pixmap in the array holding one frame.
3000 
3001  Depending on the constructor you use you can load multiple pixmaps
3002  into the array either from a directory (specifying a wildcard
3003  pattern for the files), or from a list of QPixmaps. You can also
3004  read in a set of pixmaps after construction using readPixmaps().
3005 
3006  Individual pixmaps can be set with setImage() and retrieved with
3007  image(). The number of pixmaps in the array is returned by
3008  count().
3009 
3010  QtCanvasSprite uses an image's mask for collision detection. You
3011  can change this by reading in a separate set of image masks using
3012  readCollisionMasks().
3013 
3014 */
3015 
3016 /*
3017  Constructs an invalid array (i.e. isValid() will return false).
3018  You must call readPixmaps() before being able to use this
3019  QtCanvasPixmapArray.
3020 */
3022 {
3023 }
3024 
3025 /*
3026  Constructs a QtCanvasPixmapArray from files.
3027 
3028  The \a fc parameter sets the number of frames to be loaded for
3029  this image.
3030 
3031  If \a fc is not 0, \a datafilenamepattern should contain "%1",
3032  e.g. "foo%1.png". The actual filenames are formed by replacing the
3033  %1 with four-digit integers from 0 to (fc - 1), e.g. foo0000.png,
3034  foo0001.png, foo0002.png, etc.
3035 
3036  If \a fc is 0, \a datafilenamepattern is asssumed to be a
3037  filename, and the image contained in this file will be loaded as
3038  the first (and only) frame.
3039 
3040  If \a datafilenamepattern does not exist, is not readable, isn't
3041  an image, or some other error occurs, the array ends up empty and
3042  isValid() returns false.
3043 */
3044 
3045 QtCanvasPixmapArray::QtCanvasPixmapArray(const QString& datafilenamepattern, int fc) :
3046  framecount(0), img(0)
3047 {
3048  readPixmaps(datafilenamepattern, fc);
3049 }
3050 
3051 /*
3052  \obsolete
3053  Use QtCanvasPixmapArray::QtCanvasPixmapArray(QtValueList<QPixmap>, QPolygon)
3054  instead.
3055 
3056  Constructs a QtCanvasPixmapArray from the list of QPixmaps \a
3057  list. The \a hotspots list has to be of the same size as \a list.
3058 */
3059 QtCanvasPixmapArray::QtCanvasPixmapArray(const QList<QPixmap>& list, const QPolygon& hotspots) :
3060  framecount(list.count()), img(new QtCanvasPixmap*[list.count()])
3061 {
3062  if (list.count() != hotspots.count())
3063  {
3064  qWarning("QtCanvasPixmapArray: lists have different lengths");
3065  reset();
3066  img = 0;
3067  }
3068  else
3069  {
3070  for (int i = 0; i < framecount; i++)
3071  {
3072  img[i] = new QtCanvasPixmap(list.at(i), hotspots.at(i));
3073  }
3074  }
3075 }
3076 
3077 /*
3078  Destroys the pixmap array and all the pixmaps it contains.
3079 */
3081 {
3082  reset();
3083 }
3084 
3085 void
3086 QtCanvasPixmapArray::reset()
3087 {
3088  for (int i = 0; i < framecount; i++)
3089  {
3090  delete img[i];
3091  }
3092 
3093  delete[] img;
3094  img = 0;
3095  framecount = 0;
3096 }
3097 
3098 /*
3099  Reads one or more pixmaps into the pixmap array.
3100 
3101  If \a fc is not 0, \a filenamepattern should contain "%1", e.g.
3102  "foo%1.png". The actual filenames are formed by replacing the %1
3103  with four-digit integers from 0 to (fc - 1), e.g. foo0000.png,
3104  foo0001.png, foo0002.png, etc.
3105 
3106  If \a fc is 0, \a filenamepattern is asssumed to be a filename,
3107  and the image contained in this file will be loaded as the first
3108  (and only) frame.
3109 
3110  If \a filenamepattern does not exist, is not readable, isn't an
3111  image, or some other error occurs, this function will return
3112  false, and isValid() will return false; otherwise this function
3113  will return true.
3114 
3115  \sa isValid()
3116 */
3117 bool
3118 QtCanvasPixmapArray::readPixmaps(const QString& filenamepattern, int fc)
3119 {
3120  return readPixmaps(filenamepattern, fc, false);
3121 }
3122 
3123 /*
3124  Reads new collision masks for the array.
3125 
3126  By default, QtCanvasSprite uses the image mask of a sprite to
3127  detect collisions. Use this function to set your own collision
3128  image masks.
3129 
3130  If count() is 1 \a filename must specify a real filename to read
3131  the mask from. If count() is greater than 1, the \a filename must
3132  contain a "%1" that will get replaced by the number of the mask to
3133  be loaded, just like QtCanvasPixmapArray::readPixmaps().
3134 
3135  All collision masks must be 1-bit images or this function call
3136  will fail.
3137 
3138  If the file isn't readable, contains the wrong number of images,
3139  or there is some other error, this function will return false, and
3140  the array will be flagged as invalid; otherwise this function
3141  returns true.
3142 
3143  \sa isValid()
3144 */
3145 bool
3147 {
3148  return readPixmaps(filename, framecount, true);
3149 }
3150 
3151 bool
3152 QtCanvasPixmapArray::readPixmaps(const QString& datafilenamepattern, int fc, bool maskonly)
3153 {
3154  if (!maskonly)
3155  {
3156  reset();
3157  framecount = fc;
3158 
3159  if (!framecount)
3160  {
3161  framecount = 1;
3162  }
3163 
3164  img = new QtCanvasPixmap*[framecount];
3165  }
3166 
3167  if (!img)
3168  {
3169  return false;
3170  }
3171 
3172  bool ok = true;
3173  bool arg = fc > 1;
3174 
3175  if (!arg)
3176  {
3177  framecount = 1;
3178  }
3179 
3180  for (int i = 0; i < framecount; i++)
3181  {
3182  QString r;
3183  r.sprintf("%04d", i);
3184 
3185  if (maskonly)
3186  {
3187  if (!img[i]->collision_mask)
3188  {
3189  img[i]->collision_mask = new QImage();
3190  }
3191 
3192  img[i]->collision_mask->load(arg ? datafilenamepattern.arg(r) : datafilenamepattern);
3193  ok = ok && !img[i]->collision_mask->isNull() && img[i]->collision_mask->depth() == 1;
3194  }
3195  else
3196  {
3197  img[i] = new QtCanvasPixmap(arg ? datafilenamepattern.arg(r) : datafilenamepattern);
3198  ok = ok && !img[i]->isNull();
3199  }
3200  }
3201 
3202  if (!ok)
3203  {
3204  reset();
3205  }
3206 
3207  return ok;
3208 }
3209 
3210 /*
3211  \obsolete
3212 
3213  Use isValid() instead.
3214 
3215  This returns false if the array is valid, and true if it is not.
3216 */
3217 bool
3219 {
3220  return img == 0;
3221 }
3222 
3223 /*
3224  Returns true if the pixmap array is valid; otherwise returns
3225  false.
3226 */
3227 bool
3229 {
3230  return (img != 0);
3231 }
3232 
3233 /*
3234  \fn QtCanvasPixmap* QtCanvasPixmapArray::image(int i) const
3235 
3236  Returns pixmap \a i in the array, if \a i is non-negative and less
3237  than than count(), and returns an unspecified value otherwise.
3238 */
3239 
3240 // ### wouldn't it be better to put empty QtCanvasPixmaps in there instead of
3241 // initializing the additional elements in the array to 0? Lars
3242 /*
3243  Replaces the pixmap at index \a i with pixmap \a p.
3244 
3245  The array takes ownership of \a p and will delete \a p when the
3246  array itself is deleted.
3247 
3248  If \a i is beyond the end of the array the array is extended to at
3249  least i+1 elements, with elements count() to i-1 being initialized
3250  to 0.
3251 */
3252 void
3254 {
3255  if (i >= framecount)
3256  {
3257  QtCanvasPixmap** newimg = new QtCanvasPixmap*[i + 1];
3258  memcpy(newimg, img, sizeof(QtCanvasPixmap*) * framecount);
3259  memset(newimg + framecount, 0, sizeof(QtCanvasPixmap*) * (i + 1 - framecount));
3260  framecount = i + 1;
3261  delete[] img;
3262  img = newimg;
3263  }
3264 
3265  delete img[i];
3266  img[i] = p;
3267 }
3268 
3269 /*
3270  \fn uint QtCanvasPixmapArray::count() const
3271 
3272  Returns the number of pixmaps in the array.
3273 */
3274 
3275 /*
3276  Returns the x-coordinate of the current left edge of the sprite.
3277  (This may change as the sprite animates since different frames may
3278  have different left edges.)
3279 
3280  \sa rightEdge() bottomEdge() topEdge()
3281 */
3282 int
3284 {
3285  return int(x()) - image()->hotx;
3286 }
3287 
3288 /*
3289  \overload
3290 
3291  Returns what the x-coordinate of the left edge of the sprite would
3292  be if the sprite (actually its hotspot) were moved to x-position
3293  \a nx.
3294 
3295  \sa rightEdge() bottomEdge() topEdge()
3296 */
3297 int
3299 {
3300  return nx - image()->hotx;
3301 }
3302 
3303 /*
3304  Returns the y-coordinate of the top edge of the sprite. (This may
3305  change as the sprite animates since different frames may have
3306  different top edges.)
3307 
3308  \sa leftEdge() rightEdge() bottomEdge()
3309 */
3310 int
3312 {
3313  return int(y()) - image()->hoty;
3314 }
3315 
3316 /*
3317  \overload
3318 
3319  Returns what the y-coordinate of the top edge of the sprite would
3320  be if the sprite (actually its hotspot) were moved to y-position
3321  \a ny.
3322 
3323  \sa leftEdge() rightEdge() bottomEdge()
3324 */
3325 int
3327 {
3328  return ny - image()->hoty;
3329 }
3330 
3331 /*
3332  Returns the x-coordinate of the current right edge of the sprite.
3333  (This may change as the sprite animates since different frames may
3334  have different right edges.)
3335 
3336  \sa leftEdge() bottomEdge() topEdge()
3337 */
3338 int
3340 {
3341  return leftEdge() + image()->width() - 1;
3342 }
3343 
3344 /*
3345  \overload
3346 
3347  Returns what the x-coordinate of the right edge of the sprite
3348  would be if the sprite (actually its hotspot) were moved to
3349  x-position \a nx.
3350 
3351  \sa leftEdge() bottomEdge() topEdge()
3352 */
3353 int
3355 {
3356  return leftEdge(nx) + image()->width() - 1;
3357 }
3358 
3359 /*
3360  Returns the y-coordinate of the current bottom edge of the sprite.
3361  (This may change as the sprite animates since different frames may
3362  have different bottom edges.)
3363 
3364  \sa leftEdge() rightEdge() topEdge()
3365 */
3366 int
3368 {
3369  return topEdge() + image()->height() - 1;
3370 }
3371 
3372 /*
3373  \overload
3374 
3375  Returns what the y-coordinate of the top edge of the sprite would
3376  be if the sprite (actually its hotspot) were moved to y-position
3377  \a ny.
3378 
3379  \sa leftEdge() rightEdge() topEdge()
3380 */
3381 int
3383 {
3384  return topEdge(ny) + image()->height() - 1;
3385 }
3386 
3387 /*
3388  \fn QtCanvasPixmap* QtCanvasSprite::image() const
3389 
3390  Returns the current frame's image.
3391 
3392  \sa frame(), setFrame()
3393 */
3394 
3395 /*
3396  \fn QtCanvasPixmap* QtCanvasSprite::image(int f) const
3397  \overload
3398 
3399  Returns the image for frame \a f. Does not do any bounds checking on \a f.
3400 */
3401 
3402 /*
3403  Returns the image the sprite \e will have after advance(1) is
3404  called. By default this is the same as image().
3405 */
3408 {
3409  return image();
3410 }
3411 
3412 /*
3413  Returns the bounding rectangle for the image in the sprite's
3414  current frame. This assumes that the images are tightly cropped
3415  (i.e. do not have transparent pixels all along a side).
3416 */
3417 QRect
3419 {
3420  return QRect(leftEdge(), topEdge(), width(), height());
3421 }
3422 
3423 /*
3424  \internal
3425  Returns the chunks covered by the item.
3426 */
3427 QPolygon
3428 QtCanvasItem::chunks() const
3429 {
3430  QPolygon r;
3431  int n = 0;
3432  QRect br = boundingRect();
3433 
3434  if (isVisible() && canvas())
3435  {
3436  int chunksize = canvas()->chunkSize();
3437  br &= QRect(0, 0, canvas()->width(), canvas()->height());
3438 
3439  if (br.isValid())
3440  {
3441  r.resize((br.width() / chunksize + 2) * (br.height() / chunksize + 2));
3442 
3443  for (int j = br.top() / chunksize; j <= br.bottom() / chunksize; j++)
3444  {
3445  for (int i = br.left() / chunksize; i <= br.right() / chunksize; i++)
3446  {
3447  r[n++] = QPoint(i, j);
3448  }
3449  }
3450  }
3451  }
3452 
3453  r.resize(n);
3454  return r;
3455 }
3456 
3457 /*
3458  \internal
3459  Add the sprite to the chunks in its QtCanvas which it overlaps.
3460 */
3461 void
3462 QtCanvasSprite::addToChunks()
3463 {
3464  if (isVisible() && canvas())
3465  {
3466  int chunksize = canvas()->chunkSize();
3467 
3468  for (int j = topEdge() / chunksize; j <= bottomEdge() / chunksize; j++)
3469  {
3470  for (int i = leftEdge() / chunksize; i <= rightEdge() / chunksize; i++)
3471  {
3472  canvas()->addItemToChunk(this, i, j);
3473  }
3474  }
3475  }
3476 }
3477 
3478 /*
3479  \internal
3480  Remove the sprite from the chunks in its QtCanvas which it overlaps.
3481 
3482  \sa addToChunks()
3483 */
3484 void
3485 QtCanvasSprite::removeFromChunks()
3486 {
3487  if (isVisible() && canvas())
3488  {
3489  int chunksize = canvas()->chunkSize();
3490 
3491  for (int j = topEdge() / chunksize; j <= bottomEdge() / chunksize; j++)
3492  {
3493  for (int i = leftEdge() / chunksize; i <= rightEdge() / chunksize; i++)
3494  {
3495  canvas()->removeItemFromChunk(this, i, j);
3496  }
3497  }
3498  }
3499 }
3500 
3501 /*
3502  The width of the sprite for the current frame's image.
3503 
3504  \sa frame()
3505 */
3506 //### mark: Why don't we have width(int) and height(int) to be
3507 //consistent with leftEdge() and leftEdge(int)?
3508 int
3510 {
3511  return image()->width();
3512 }
3513 
3514 /*
3515  The height of the sprite for the current frame's image.
3516 
3517  \sa frame()
3518 */
3519 int
3521 {
3522  return image()->height();
3523 }
3524 
3525 /*
3526  Draws the current frame's image at the sprite's current position
3527  on painter \a painter.
3528 */
3529 void
3530 QtCanvasSprite::draw(QPainter& painter)
3531 {
3532  painter.drawPixmap(leftEdge(), topEdge(), *image());
3533 }
3534 
3535 /*
3536  \class QtCanvasView qtcanvas.h
3537  \brief The QtCanvasView class provides an on-screen view of a QtCanvas.
3538 
3539  A QtCanvasView is widget which provides a view of a QtCanvas.
3540 
3541  If you want users to be able to interact with a canvas view,
3542  subclass QtCanvasView. You might then reimplement
3543  QtScrollView::contentsMousePressEvent(). For example:
3544 
3545  \code
3546  void MyCanvasView::contentsMousePressEvent(QMouseEvent* e)
3547  {
3548  QtCanvasItemList l = canvas()->collisions(e->pos());
3549  for (QtCanvasItemList::Iterator it = l.begin(); it!= l.end(); ++it) {
3550  if ((*it)->rtti() == QtCanvasRectangle::RTTI)
3551  qDebug("A QtCanvasRectangle lies somewhere at this point");
3552  }
3553  }
3554  \endcode
3555 
3556  The canvas view shows canvas canvas(); this can be changed using
3557  setCanvas().
3558 
3559  A transformation matrix can be used to transform the view of the
3560  canvas in various ways, for example, zooming in or out or rotating.
3561  For example:
3562 
3563  \code
3564  QMatrix wm;
3565  wm.scale(2, 2); // Zooms in by 2 times
3566  wm.rotate(90); // Rotates 90 degrees counter clockwise
3567  // around the origin.
3568  wm.translate(0, -canvas->height());
3569  // moves the canvas down so what was visible
3570  // before is still visible.
3571  myCanvasView->setWorldMatrix(wm);
3572  \endcode
3573 
3574  Use setWorldMatrix() to set the canvas view's world matrix: you must
3575  ensure that the world matrix is invertible. The current world matrix
3576  is retrievable with worldMatrix(), and its inversion is retrievable
3577  with inverseWorldMatrix().
3578 
3579  Example:
3580 
3581  The following code finds the part of the canvas that is visible in
3582  this view, i.e. the bounding rectangle of the view in canvas coordinates.
3583 
3584  \code
3585  QRect rc = QRect(myCanvasView->contentsX(), myCanvasView->contentsY(),
3586  myCanvasView->visibleWidth(), myCanvasView->visibleHeight());
3587  QRect canvasRect = myCanvasView->inverseWorldMatrix().mapRect(rc);
3588  \endcode
3589 
3590  \sa QMatrix QPainter::setWorldMatrix()
3591 
3592 */
3593 
3594 class QtCanvasWidget : public QWidget
3595 {
3596 public:
3597  QtCanvasWidget(QtCanvasView* view) : QWidget(view)
3598  {
3599  m_view = view;
3600  }
3601 
3602 protected:
3603  void paintEvent(QPaintEvent* e);
3604 
3605  void
3606  mousePressEvent(QMouseEvent* e)
3607  {
3609  }
3610 
3611  void
3612  mouseMoveEvent(QMouseEvent* e)
3613  {
3615  }
3616 
3617  void
3618  mouseReleaseEvent(QMouseEvent* e)
3619  {
3621  }
3622 
3623  void
3624  mouseDoubleClickEvent(QMouseEvent* e)
3625  {
3627  }
3628 
3629  void
3630  dragEnterEvent(QDragEnterEvent* e)
3631  {
3633  }
3634 
3635  void
3636  dragMoveEvent(QDragMoveEvent* e)
3637  {
3639  }
3640 
3641  void
3642  dragLeaveEvent(QDragLeaveEvent* e)
3643  {
3645  }
3646 
3647  void
3648  dropEvent(QDropEvent* e)
3649  {
3651  }
3652 
3653  void
3654  wheelEvent(QWheelEvent* e)
3655  {
3657  }
3658 
3659  void
3660  contextMenuEvent(QContextMenuEvent* e)
3661  {
3663  }
3664 
3666 };
3667 
3668 void
3670 {
3671  QPainter p(this);
3672 
3673  if (m_view->d->highQuality)
3674  {
3675  p.setRenderHint(QPainter::Antialiasing);
3676  p.setRenderHint(QPainter::SmoothPixmapTransform);
3677  }
3678 
3679  m_view->drawContents(&p, e->rect().x(), e->rect().y(), e->rect().width(), e->rect().height());
3680 }
3681 
3682 /*
3683  Constructs a QtCanvasView with parent \a parent. The canvas view
3684  is not associated with a canvas, so you must to call setCanvas()
3685  to view a canvas.
3686 */
3687 QtCanvasView::QtCanvasView(QWidget* parent) : QScrollArea(parent)
3688 {
3689  d = new QtCanvasViewData;
3690  setWidget(new QtCanvasWidget(this));
3691  d->highQuality = false;
3692  viewing = 0;
3693  setCanvas(0);
3694 }
3695 
3696 /*
3697  \overload
3698 
3699  Constructs a QtCanvasView which views canvas \a canvas, with parent
3700  \a parent.
3701 */
3702 QtCanvasView::QtCanvasView(QtCanvas* canvas, QWidget* parent) : QScrollArea(parent)
3703 {
3704  d = new QtCanvasViewData;
3705  d->highQuality = false;
3706  setWidget(new QtCanvasWidget(this));
3707  viewing = 0;
3708  setCanvas(canvas);
3709 }
3710 
3711 /*
3712  Destroys the canvas view. The associated canvas is \e not deleted.
3713 */
3715 {
3716  delete d;
3717  d = 0;
3718  setCanvas(0);
3719 }
3720 
3721 /*
3722  \property QtCanvasView::highQualityRendering
3723  \brief whether high quality rendering is turned on
3724 
3725  If high quality rendering is turned on, the canvas view will paint itself
3726  using the QPainter::Antialiasing and QPainter::SmoothPixmapTransform
3727  rendering flags.
3728 
3729  Enabling these flag will usually improve the visual appearance on the screen
3730  at the cost of rendering speed.
3731 */
3732 bool
3734 {
3735  return d->highQuality;
3736 }
3737 
3738 void
3740 {
3741  d->highQuality = enable;
3742  widget()->update();
3743 }
3744 
3745 void
3747 {
3748  e->ignore();
3749 }
3750 
3751 void
3753 {
3754  e->ignore();
3755 }
3756 
3757 void
3759 {
3760  e->ignore();
3761 }
3762 
3763 void
3765 {
3766  e->ignore();
3767 }
3768 
3769 void
3771 {
3772 }
3773 
3774 void
3776 {
3777 }
3778 
3779 void
3781 {
3782 }
3783 
3784 void
3786 {
3787 }
3788 
3789 void
3791 {
3792  e->ignore();
3793 }
3794 
3795 void
3797 {
3798  e->ignore();
3799 }
3800 
3801 /*
3802  \fn QtCanvas* QtCanvasView::canvas() const
3803 
3804  Returns a pointer to the canvas which the QtCanvasView is currently
3805  showing.
3806 */
3807 
3808 
3809 /*
3810  Sets the canvas that the QtCanvasView is showing to the canvas \a
3811  canvas.
3812 */
3813 void
3815 {
3816  if (viewing == canvas)
3817  {
3818  return;
3819  }
3820 
3821  if (viewing)
3822  {
3823  disconnect(viewing);
3824  viewing->removeView(this);
3825  }
3826 
3827  viewing = canvas;
3828 
3829  if (viewing)
3830  {
3831  connect(viewing, SIGNAL(resized()), this, SLOT(updateContentsSize()));
3832  viewing->addView(this);
3833  }
3834 
3835  if (d) // called by d'tor
3836  {
3837  updateContentsSize();
3838  }
3839 
3840  update();
3841 }
3842 
3843 /*
3844  Returns a reference to the canvas view's current transformation matrix.
3845 
3846  \sa setWorldMatrix() inverseWorldMatrix()
3847 */
3848 const QMatrix&
3850 {
3851  return d->xform;
3852 }
3853 
3854 /*
3855  Returns a reference to the inverse of the canvas view's current
3856  transformation matrix.
3857 
3858  \sa setWorldMatrix() worldMatrix()
3859 */
3860 const QMatrix&
3862 {
3863  return d->ixform;
3864 }
3865 
3866 /*
3867  Sets the transformation matrix of the QtCanvasView to \a wm. The
3868  matrix must be invertible (i.e. if you create a world matrix that
3869  zooms out by 2 times, then the inverse of this matrix is one that
3870  will zoom in by 2 times).
3871 
3872  When you use this, you should note that the performance of the
3873  QtCanvasView will decrease considerably.
3874 
3875  Returns false if \a wm is not invertable; otherwise returns true.
3876 
3877  \sa worldMatrix() inverseWorldMatrix() QMatrix::isInvertible()
3878 */
3879 bool
3881 {
3882  bool ok = wm.isInvertible();
3883 
3884  if (ok)
3885  {
3886  d->xform = wm;
3887  d->ixform = wm.inverted();
3888  updateContentsSize();
3889  widget()->update();
3890  }
3891 
3892  return ok;
3893 }
3894 
3895 void
3896 QtCanvasView::updateContentsSize()
3897 {
3898  if (viewing)
3899  {
3900  QRect br;
3901  br = d->xform.mapRect(QRect(0, 0, viewing->width(), viewing->height()));
3902 
3903  widget()->resize(br.size());
3904  }
3905  else
3906  {
3907  widget()->resize(size());
3908  }
3909 }
3910 
3911 /*
3912  Repaints part of the QtCanvas that the canvas view is showing
3913  starting at \a cx by \a cy, with a width of \a cw and a height of \a
3914  ch using the painter \a p.
3915 */
3916 void
3917 QtCanvasView::drawContents(QPainter* p, int cx, int cy, int cw, int ch)
3918 {
3919  if (!viewing)
3920  {
3921  return;
3922  }
3923 
3924  QPainterPath clipPath;
3925  clipPath.addRect(viewing->rect());
3926  p->setClipPath(d->xform.map(clipPath), Qt::IntersectClip);
3927  viewing->drawViewArea(this, p, QRect(cx, cy, cw, ch), false);
3928 }
3929 
3930 /*
3931  Suggests a size sufficient to view the entire canvas.
3932 */
3933 QSize
3935 {
3936  if (!canvas())
3937  {
3938  return QScrollArea::sizeHint();
3939  }
3940 
3941  // should maybe take transformations into account
3942  return (canvas()->size() + 2 * QSize(frameWidth(), frameWidth()))
3943  .boundedTo(3 * QApplication::desktop()->size() / 4);
3944 }
3945 
3946 /*
3947  \class QtCanvasPolygonalItem qtcanvas.h
3948  \brief The QtCanvasPolygonalItem class provides a polygonal canvas item
3949  on a QtCanvas.
3950 
3951  The mostly rectangular classes, such as QtCanvasSprite and
3952  QtCanvasText, use the object's bounding rectangle for movement,
3953  repainting and collision calculations. For most other items, the
3954  bounding rectangle can be far too large -- a diagonal line being
3955  the worst case, and there are many other cases which are also bad.
3956  QtCanvasPolygonalItem provides polygon-based bounding rectangle
3957  handling, etc., which is much faster for non-rectangular items.
3958 
3959  Derived classes should try to define as small an area as possible
3960  to maximize efficiency, but the polygon must \e definitely be
3961  contained completely within the polygonal area. Calculating the
3962  exact requirements is usually difficult, but if you allow a small
3963  overestimate it can be easy and quick, while still getting almost
3964  all of QtCanvasPolygonalItem's speed.
3965 
3966  Note that all subclasses \e must call hide() in their destructor
3967  since hide() needs to be able to access areaPoints().
3968 
3969  Normally, QtCanvasPolygonalItem uses the odd-even algorithm for
3970  determining whether an object intersects this object. You can
3971  change this to the winding algorithm using setWinding().
3972 
3973  The bounding rectangle is available using boundingRect(). The
3974  points bounding the polygonal item are retrieved with
3975  areaPoints(). Use areaPointsAdvanced() to retrieve the bounding
3976  points the polygonal item \e will have after
3977  QtCanvasItem::advance(1) has been called.
3978 
3979  If the shape of the polygonal item is about to change while the
3980  item is visible, call invalidate() before updating with a
3981  different result from \l areaPoints().
3982 
3983  By default, QtCanvasPolygonalItem objects have a black pen and no
3984  brush (the default QPen and QBrush constructors). You can change
3985  this with setPen() and setBrush(), but note that some
3986  QtCanvasPolygonalItem subclasses only use the brush, ignoring the
3987  pen setting.
3988 
3989  The polygonal item can be drawn on a painter with draw().
3990  Subclasses must reimplement drawShape() to draw themselves.
3991 
3992  Like any other canvas item polygonal items can be moved with
3993  QtCanvasItem::move() and QtCanvasItem::moveBy(), or by setting coordinates
3994  with QtCanvasItem::setX(), QtCanvasItem::setY() and QtCanvasItem::setZ().
3995 
3996 */
3997 
3998 
3999 /*
4000  Since most polygonal items don't have a pen, the default is
4001  NoPen and a black brush.
4002 */
4003 static const QPen&
4004 defaultPolygonPen()
4005 {
4006  static QPen* dp = 0;
4007 
4008  if (!dp)
4009  {
4010  dp = new QPen;
4011  }
4012 
4013  return *dp;
4014 }
4015 
4016 static const QBrush&
4017 defaultPolygonBrush()
4018 {
4019  static QBrush* db = 0;
4020 
4021  if (!db)
4022  {
4023  db = new QBrush;
4024  }
4025 
4026  return *db;
4027 }
4028 
4029 /*
4030  Constructs a QtCanvasPolygonalItem on the canvas \a canvas.
4031 */
4033  QtCanvasItem(canvas), br(defaultPolygonBrush()), pn(defaultPolygonPen())
4034 {
4035  wind = 0;
4036 }
4037 
4038 /*
4039  Note that all subclasses \e must call hide() in their destructor
4040  since hide() needs to be able to access areaPoints().
4041 */
4043 {
4044 }
4045 
4046 /*
4047  Returns true if the polygonal item uses the winding algorithm to
4048  determine the "inside" of the polygon. Returns false if it uses
4049  the odd-even algorithm.
4050 
4051  The default is to use the odd-even algorithm.
4052 
4053  \sa setWinding()
4054 */
4055 bool
4057 {
4058  return wind;
4059 }
4060 
4061 /*
4062  If \a enable is true, the polygonal item will use the winding
4063  algorithm to determine the "inside" of the polygon; otherwise the
4064  odd-even algorithm will be used.
4065 
4066  The default is to use the odd-even algorithm.
4067 
4068  \sa winding()
4069 */
4070 void
4072 {
4073  wind = enable;
4074 }
4075 
4076 /*
4077  Invalidates all information about the area covered by the canvas
4078  item. The item will be updated automatically on the next call that
4079  changes the item's status, for example, move() or update(). Call
4080  this function if you are going to change the shape of the item (as
4081  returned by areaPoints()) while the item is visible.
4082 */
4083 void
4085 {
4086  val = (uint) false;
4087  removeFromChunks();
4088 }
4089 
4090 /*
4091  \fn QtCanvasPolygonalItem::isValid() const
4092 
4093  Returns true if the polygonal item's area information has not been
4094  invalidated; otherwise returns false.
4095 
4096  \sa invalidate()
4097 */
4098 
4099 /*
4100  Returns the points the polygonal item \e will have after
4101  QtCanvasItem::advance(1) is called, i.e. what the points are when
4102  advanced by the current xVelocity() and yVelocity().
4103 */
4104 QPolygon
4106 {
4107  int dx = int(x() + xVelocity()) - int(x());
4108  int dy = int(y() + yVelocity()) - int(y());
4109  QPolygon r = areaPoints();
4110  r.detach(); // Explicit sharing is stupid.
4111 
4112  if (dx || dy)
4113  {
4114  r.translate(dx, dy);
4115  }
4116 
4117  return r;
4118 }
4119 
4120 //#define QCANVAS_POLYGONS_DEBUG
4121 #ifdef QCANVAS_POLYGONS_DEBUG
4122 static QWidget* dbg_wid = 0;
4123 static QPainter* dbg_ptr = 0;
4124 #endif
4125 
4127 {
4128 public:
4129  QPolygonalProcessor(QtCanvas* c, const QPolygon& pa) : canvas(c)
4130  {
4131  QRect pixelbounds = pa.boundingRect();
4132  int cs = canvas->chunkSize();
4133  QRect canvasbounds = pixelbounds.intersected(canvas->rect());
4134  bounds.setLeft(canvasbounds.left() / cs);
4135  bounds.setRight(canvasbounds.right() / cs);
4136  bounds.setTop(canvasbounds.top() / cs);
4137  bounds.setBottom(canvasbounds.bottom() / cs);
4138  bitmap = QImage(bounds.width(), bounds.height(), QImage::Format_MonoLSB);
4139  pnt = 0;
4140  bitmap.fill(0);
4141 #ifdef QCANVAS_POLYGONS_DEBUG
4142  dbg_start();
4143 #endif
4144  }
4145 
4146  inline void
4147  add(int x, int y)
4148  {
4149  if (pnt >= (int)result.size())
4150  {
4151  result.resize(pnt * 2 + 10);
4152  }
4153 
4154  result[pnt++] = QPoint(x + bounds.x(), y + bounds.y());
4155 #ifdef QCANVAS_POLYGONS_DEBUG
4156 
4157  if (dbg_ptr)
4158  {
4159  int cs = canvas->chunkSize();
4160  QRect r(x * cs + bounds.x() * cs, y * cs + bounds.y() * cs, cs - 1, cs - 1);
4161  dbg_ptr->setPen(Qt::blue);
4162  dbg_ptr->drawRect(r);
4163  }
4164 
4165 #endif
4166  }
4167 
4168  inline void
4169  addBits(int x1, int x2, uchar newbits, int xo, int yo)
4170  {
4171  for (int i = x1; i <= x2; i++)
4172  if (newbits & (1 << i))
4173  {
4174  add(xo + i, yo);
4175  }
4176  }
4177 
4178 #ifdef QCANVAS_POLYGONS_DEBUG
4179  void
4180  dbg_start()
4181  {
4182  if (!dbg_wid)
4183  {
4184  dbg_wid = new QWidget;
4185  dbg_wid->resize(800, 600);
4186  dbg_wid->show();
4187  dbg_ptr = new QPainter(dbg_wid);
4188  dbg_ptr->setBrush(Qt::NoBrush);
4189  }
4190 
4191  dbg_ptr->fillRect(dbg_wid->rect(), Qt::white);
4192  }
4193 #endif
4194 
4195  void
4196  doSpans(int n, QPoint* pt, int* w)
4197  {
4198  int cs = canvas->chunkSize();
4199 
4200  for (int j = 0; j < n; j++)
4201  {
4202  int y = pt[j].y() / cs - bounds.y();
4203 
4204  if (y >= bitmap.height() || y < 0)
4205  {
4206  continue;
4207  }
4208 
4209  uchar* l = bitmap.scanLine(y);
4210  int x = pt[j].x();
4211  int x1 = x / cs - bounds.x();
4212 
4213  if (x1 > bounds.width())
4214  {
4215  continue;
4216  }
4217 
4218  x1 = qMax(0, x1);
4219  int x2 = (x + w[j]) / cs - bounds.x();
4220 
4221  if (x2 < 0)
4222  {
4223  continue;
4224  }
4225 
4226  x2 = qMin(bounds.width(), x2);
4227  int x1q = x1 / 8;
4228  int x1r = x1 % 8;
4229  int x2q = x2 / 8;
4230  int x2r = x2 % 8;
4231 #ifdef QCANVAS_POLYGONS_DEBUG
4232 
4233  if (dbg_ptr)
4234  {
4235  dbg_ptr->setPen(Qt::yellow);
4236  }
4237 
4238 #endif
4239 
4240  if (x1q == x2q)
4241  {
4242  uchar newbits = (~l[x1q]) & (((2 << (x2r - x1r)) - 1) << x1r);
4243 
4244  if (newbits)
4245  {
4246 #ifdef QCANVAS_POLYGONS_DEBUG
4247 
4248  if (dbg_ptr)
4249  {
4250  dbg_ptr->setPen(Qt::darkGreen);
4251  }
4252 
4253 #endif
4254  addBits(x1r, x2r, newbits, x1q * 8, y);
4255  l[x1q] |= newbits;
4256  }
4257  }
4258  else
4259  {
4260 #ifdef QCANVAS_POLYGONS_DEBUG
4261 
4262  if (dbg_ptr)
4263  {
4264  dbg_ptr->setPen(Qt::blue);
4265  }
4266 
4267 #endif
4268  uchar newbits1 = (~l[x1q]) & (0xff << x1r);
4269 
4270  if (newbits1)
4271  {
4272 #ifdef QCANVAS_POLYGONS_DEBUG
4273 
4274  if (dbg_ptr)
4275  {
4276  dbg_ptr->setPen(Qt::green);
4277  }
4278 
4279 #endif
4280  addBits(x1r, 7, newbits1, x1q * 8, y);
4281  l[x1q] |= newbits1;
4282  }
4283 
4284  for (int i = x1q + 1; i < x2q; i++)
4285  {
4286  if (l[i] != 0xff)
4287  {
4288  addBits(0, 7, ~l[i], i * 8, y);
4289  l[i] = 0xff;
4290  }
4291  }
4292 
4293  uchar newbits2 = (~l[x2q]) & (0xff >> (7 - x2r));
4294 
4295  if (newbits2)
4296  {
4297 #ifdef QCANVAS_POLYGONS_DEBUG
4298 
4299  if (dbg_ptr)
4300  {
4301  dbg_ptr->setPen(Qt::red);
4302  }
4303 
4304 #endif
4305  addBits(0, x2r, newbits2, x2q * 8, y);
4306  l[x2q] |= newbits2;
4307  }
4308  }
4309 
4310 #ifdef QCANVAS_POLYGONS_DEBUG
4311 
4312  if (dbg_ptr)
4313  {
4314  dbg_ptr->drawLine(pt[j], pt[j] + QPoint(w[j], 0));
4315  }
4316 
4317 #endif
4318  }
4319 
4320  result.resize(pnt);
4321  }
4322 
4323  int pnt;
4324  QPolygon result;
4326  QRect bounds;
4327  QImage bitmap;
4328 };
4329 
4330 QPolygon
4331 QtCanvasPolygonalItem::chunks() const
4332 {
4333  QPolygon pa = areaPoints();
4334 
4335  if (!pa.size())
4336  {
4337  pa.detach(); // Explicit sharing is stupid.
4338  return pa;
4339  }
4340 
4341  QPolygonalProcessor processor(canvas(), pa);
4342 
4343  scanPolygon(pa, wind, processor);
4344 
4345  return processor.result;
4346 }
4347 
4348 /*
4349  Simply calls QtCanvasItem::chunks().
4350 */
4351 QPolygon
4353 {
4354  // No need to do a polygon scan!
4355  return QtCanvasItem::chunks();
4356 }
4357 
4358 /*
4359  Returns the bounding rectangle of the polygonal item, based on
4360  areaPoints().
4361 */
4362 QRect
4364 {
4365  return areaPoints().boundingRect();
4366 }
4367 
4368 /*
4369  Reimplemented from QtCanvasItem, this draws the polygonal item by
4370  setting the pen and brush for the item on the painter \a p and
4371  calling drawShape().
4372 */
4373 void
4375 {
4376  p.setPen(pn);
4377  p.setBrush(br);
4378  drawShape(p);
4379 }
4380 
4381 /*
4382  \fn void QtCanvasPolygonalItem::drawShape(QPainter & p)
4383 
4384  Subclasses must reimplement this function to draw their shape. The
4385  pen and brush of \a p are already set to pen() and brush() prior
4386  to calling this function.
4387 
4388  \sa draw()
4389 */
4390 
4391 /*
4392  \fn QPen QtCanvasPolygonalItem::pen() const
4393 
4394  Returns the QPen used to draw the outline of the item, if any.
4395 
4396  \sa setPen()
4397 */
4398 
4399 /*
4400  \fn QBrush QtCanvasPolygonalItem::brush() const
4401 
4402  Returns the QBrush used to fill the item, if filled.
4403 
4404  \sa setBrush()
4405 */
4406 
4407 /*
4408  Sets the QPen used when drawing the item to the pen \a p.
4409  Note that many QtCanvasPolygonalItems do not use the pen value.
4410 
4411  \sa setBrush(), pen(), drawShape()
4412 */
4413 void
4415 {
4416  if (pn != p)
4417  {
4418  removeFromChunks();
4419  pn = p;
4420  addToChunks();
4421  }
4422 }
4423 
4424 /*
4425  Sets the QBrush used when drawing the polygonal item to the brush \a b.
4426 
4427  \sa setPen(), brush(), drawShape()
4428 */
4429 void
4431 {
4432  if (br != b)
4433  {
4434  br = b;
4435  changeChunks();
4436  }
4437 }
4438 
4439 /*
4440  \class QtCanvasPolygon qtcanvas.h
4441  \brief The QtCanvasPolygon class provides a polygon on a QtCanvas.
4442 
4443  Paints a polygon with a QBrush. The polygon's points can be set in
4444  the constructor or set or changed later using setPoints(). Use
4445  points() to retrieve the points, or areaPoints() to retrieve the
4446  points relative to the canvas's origin.
4447 
4448  The polygon can be drawn on a painter with drawShape().
4449 
4450  Like any other canvas item polygons can be moved with
4451  QtCanvasItem::move() and QtCanvasItem::moveBy(), or by setting
4452  coordinates with QtCanvasItem::setX(), QtCanvasItem::setY() and
4453  QtCanvasItem::setZ().
4454 
4455  Note: QtCanvasPolygon does not use the pen.
4456 */
4457 
4458 /*
4459  Constructs a point-less polygon on the canvas \a canvas. You
4460  should call setPoints() before using it further.
4461 */
4463 {
4464 }
4465 
4466 /*
4467  Destroys the polygon.
4468 */
4470 {
4471  hide();
4472 }
4473 
4474 /*
4475  Draws the polygon using the painter \a p.
4476 
4477  Note that QtCanvasPolygon does not support an outline (the pen is
4478  always NoPen).
4479 */
4480 void
4482 {
4483  // ### why can't we draw outlines? We could use drawPolyline for it. Lars
4484  // ### see other message. Warwick
4485 
4486  p.setPen(NoPen); // since QRegion(QPolygon) excludes outline :-()-:
4487  p.drawPolygon(poly);
4488 }
4489 
4490 /*
4491  Sets the points of the polygon to be \a pa. These points will have
4492  their x and y coordinates automatically translated by x(), y() as
4493  the polygon is moved.
4494 */
4495 void
4497 {
4498  removeFromChunks();
4499  poly = pa;
4500  poly.detach(); // Explicit sharing is stupid.
4501  poly.translate((int)x(), (int)y());
4502  addToChunks();
4503 }
4504 
4505 /*
4506  \reimp
4507 */
4508 void
4509 QtCanvasPolygon::moveBy(double dx, double dy)
4510 {
4511  // Note: does NOT call QtCanvasPolygonalItem::moveBy(), since that
4512  // only does half this work.
4513  //
4514  int idx = int(x() + dx) - int(x());
4515  int idy = int(y() + dy) - int(y());
4516 
4517  if (idx || idy)
4518  {
4519  removeFromChunks();
4520  poly.translate(idx, idy);
4521  }
4522 
4523  myx += dx;
4524  myy += dy;
4525 
4526  if (idx || idy)
4527  {
4528  addToChunks();
4529  }
4530 }
4531 
4532 /*
4533  \class QtCanvasSpline qtcanvas.h
4534  \brief The QtCanvasSpline class provides multi-bezier splines on a QtCanvas.
4535 
4536  A QtCanvasSpline is a sequence of 4-point bezier curves joined
4537  together to make a curved shape.
4538 
4539  You set the control points of the spline with setControlPoints().
4540 
4541  If the bezier is closed(), then the first control point will be
4542  re-used as the last control point. Therefore, a closed bezier must
4543  have a multiple of 3 control points and an open bezier must have
4544  one extra point.
4545 
4546  The beziers are not necessarily joined "smoothly". To ensure this,
4547  set control points appropriately (general reference texts about
4548  beziers will explain this in detail).
4549 
4550  Like any other canvas item splines can be moved with
4551  QtCanvasItem::move() and QtCanvasItem::moveBy(), or by setting
4552  coordinates with QtCanvasItem::setX(), QtCanvasItem::setY() and
4553  QtCanvasItem::setZ().
4554 
4555 */
4556 
4557 /*
4558  Create a spline with no control points on the canvas \a canvas.
4559 
4560  \sa setControlPoints()
4561 */
4563 {
4564 }
4565 
4566 /*
4567  Destroy the spline.
4568 */
4570 {
4571 }
4572 
4573 /*
4574  Set the spline control points to \a ctrl.
4575 
4576  If \a close is true, then the first point in \a ctrl will be
4577  re-used as the last point, and the number of control points must
4578  be a multiple of 3. If \a close is false, one additional control
4579  point is required, and the number of control points must be one of
4580  (4, 7, 10, 13, ...).
4581 
4582  If the number of control points doesn't meet the above conditions,
4583  the number of points will be truncated to the largest number of
4584  points that do meet the requirement.
4585 */
4586 void
4587 QtCanvasSpline::setControlPoints(QPolygon ctrl, bool close)
4588 {
4589  if ((int)ctrl.count() % 3 != (close ? 0 : 1))
4590  {
4591  qWarning("QtCanvasSpline::setControlPoints(): Number of points doesn't fit.");
4592  int numCurves = (ctrl.count() - (close ? 0 : 1)) / 3;
4593  ctrl.resize(numCurves * 3 + (close ? 0 : 1));
4594  }
4595 
4596  cl = close;
4597  bez = ctrl;
4598  recalcPoly();
4599 }
4600 
4601 /*
4602  Returns the current set of control points.
4603 
4604  \sa setControlPoints(), closed()
4605 */
4606 QPolygon
4608 {
4609  return bez;
4610 }
4611 
4612 /*
4613  Returns true if the control points are a closed set; otherwise
4614  returns false.
4615 */
4616 bool
4618 {
4619  return cl;
4620 }
4621 
4622 void
4623 QtCanvasSpline::recalcPoly()
4624 {
4625  if (bez.count() == 0)
4626  {
4627  return;
4628  }
4629 
4630  QPainterPath path;
4631  path.moveTo(bez[0]);
4632 
4633  for (int i = 1; i < (int)bez.count() - 1; i += 3)
4634  {
4635  path.cubicTo(bez[i], bez[i + 1], cl ? bez[(i + 2) % bez.size()] : bez[i + 2]);
4636  }
4637 
4638  QPolygon p = path.toFillPolygon().toPolygon();
4640 }
4641 
4642 /*
4643  \fn QPolygon QtCanvasPolygonalItem::areaPoints() const
4644 
4645  This function must be reimplemented by subclasses. It \e must
4646  return the points bounding (i.e. outside and not touching) the
4647  shape or drawing errors will occur.
4648 */
4649 
4650 /*
4651  \fn QPolygon QtCanvasPolygon::points() const
4652 
4653  Returns the vertices of the polygon, not translated by the position.
4654 
4655  \sa setPoints(), areaPoints()
4656 */
4657 QPolygon
4659 {
4660  QPolygon pa = areaPoints();
4661  pa.translate(int(-x()), int(-y()));
4662  return pa;
4663 }
4664 
4665 /*
4666  Returns the vertices of the polygon translated by the polygon's
4667  current x(), y() position, i.e. relative to the canvas's origin.
4668 
4669  \sa setPoints(), points()
4670 */
4671 QPolygon
4673 {
4674  return poly;
4675 }
4676 
4677 /*
4678  \class QtCanvasLine qtcanvas.h
4679  \brief The QtCanvasLine class provides a line on a QtCanvas.
4680 
4681  The line inherits functionality from QtCanvasPolygonalItem, for
4682  example the setPen() function. The start and end points of the
4683  line are set with setPoints().
4684 
4685  Like any other canvas item lines can be moved with
4686  QtCanvasItem::move() and QtCanvasItem::moveBy(), or by setting
4687  coordinates with QtCanvasItem::setX(), QtCanvasItem::setY() and
4688  QtCanvasItem::setZ().
4689 */
4690 
4691 /*
4692  Constructs a line from (0, 0) to (0, 0) on \a canvas.
4693 
4694  \sa setPoints()
4695 */
4697 {
4698  x1 = y1 = x2 = y2 = 0;
4699 }
4700 
4701 /*
4702  Destroys the line.
4703 */
4705 {
4706  hide();
4707 }
4708 
4709 /*
4710  \reimp
4711 */
4712 void
4714 {
4716 }
4717 
4718 /*
4719  \fn QPoint QtCanvasLine::startPoint () const
4720 
4721  Returns the start point of the line.
4722 
4723  \sa setPoints(), endPoint()
4724 */
4725 
4726 /*
4727  \fn QPoint QtCanvasLine::endPoint () const
4728 
4729  Returns the end point of the line.
4730 
4731  \sa setPoints(), startPoint()
4732 */
4733 
4734 /*
4735  Sets the line's start point to (\a xa, \a ya) and its end point to
4736  (\a xb, \a yb).
4737 */
4738 void
4739 QtCanvasLine::setPoints(int xa, int ya, int xb, int yb)
4740 {
4741  if (x1 != xa || x2 != xb || y1 != ya || y2 != yb)
4742  {
4743  removeFromChunks();
4744  x1 = xa;
4745  y1 = ya;
4746  x2 = xb;
4747  y2 = yb;
4748  addToChunks();
4749  }
4750 }
4751 
4752 /*
4753  \reimp
4754 */
4755 void
4757 {
4758  p.drawLine((int)(x() + x1), (int)(y() + y1), (int)(x() + x2), (int)(y() + y2));
4759 }
4760 
4761 /*
4762  \reimp
4763 
4764  Note that the area defined by the line is somewhat thicker than
4765  the line that is actually drawn.
4766 */
4767 QPolygon
4769 {
4770  QPolygon p(4);
4771  int xi = int(x());
4772  int yi = int(y());
4773  int pw = pen().width();
4774  int dx = qAbs(x1 - x2);
4775  int dy = qAbs(y1 - y2);
4776  pw = pw * 4 / 3 + 2; // approx pw*sqrt(2)
4777  int px = x1 < x2 ? -pw : pw;
4778  int py = y1 < y2 ? -pw : pw;
4779 
4780  if (dx && dy && (dx > dy ? (dx * 2 / dy <= 2) : (dy * 2 / dx <= 2)))
4781  {
4782  // steep
4783  if (px == py)
4784  {
4785  p[0] = QPoint(x1 + xi, y1 + yi + py);
4786  p[1] = QPoint(x2 + xi - px, y2 + yi);
4787  p[2] = QPoint(x2 + xi, y2 + yi - py);
4788  p[3] = QPoint(x1 + xi + px, y1 + yi);
4789  }
4790  else
4791  {
4792  p[0] = QPoint(x1 + xi + px, y1 + yi);
4793  p[1] = QPoint(x2 + xi, y2 + yi - py);
4794  p[2] = QPoint(x2 + xi - px, y2 + yi);
4795  p[3] = QPoint(x1 + xi, y1 + yi + py);
4796  }
4797  }
4798  else if (dx > dy)
4799  {
4800  // horizontal
4801  p[0] = QPoint(x1 + xi + px, y1 + yi + py);
4802  p[1] = QPoint(x2 + xi - px, y2 + yi + py);
4803  p[2] = QPoint(x2 + xi - px, y2 + yi - py);
4804  p[3] = QPoint(x1 + xi + px, y1 + yi - py);
4805  }
4806  else
4807  {
4808  // vertical
4809  p[0] = QPoint(x1 + xi + px, y1 + yi + py);
4810  p[1] = QPoint(x2 + xi + px, y2 + yi - py);
4811  p[2] = QPoint(x2 + xi - px, y2 + yi - py);
4812  p[3] = QPoint(x1 + xi - px, y1 + yi + py);
4813  }
4814 
4815  return p;
4816 }
4817 
4818 /*
4819  \reimp
4820 
4821 */
4822 
4823 void
4824 QtCanvasLine::moveBy(double dx, double dy)
4825 {
4827 }
4828 
4829 /*
4830  \class QtCanvasRectangle qtcanvas.h
4831  \brief The QtCanvasRectangle class provides a rectangle on a QtCanvas.
4832 
4833  This item paints a single rectangle which may have any pen() and
4834  brush(), but may not be tilted/rotated. For rotated rectangles,
4835  use QtCanvasPolygon.
4836 
4837  The rectangle's size and initial position can be set in the
4838  constructor. The size can be set or changed later using setSize().
4839  Use height() and width() to retrieve the rectangle's dimensions.
4840 
4841  The rectangle can be drawn on a painter with drawShape().
4842 
4843  Like any other canvas item rectangles can be moved with
4844  QtCanvasItem::move() and QtCanvasItem::moveBy(), or by setting
4845  coordinates with QtCanvasItem::setX(), QtCanvasItem::setY() and
4846  QtCanvasItem::setZ().
4847 
4848 */
4849 
4850 /*
4851  Constructs a rectangle at position (0,0) with both width and
4852  height set to 32 pixels on \a canvas.
4853 */
4855 {
4856 }
4857 
4858 /*
4859  Constructs a rectangle positioned and sized by \a r on \a canvas.
4860 */
4862  QtCanvasPolygonalItem(canvas), w(r.width()), h(r.height())
4863 {
4864  move(r.x(), r.y());
4865 }
4866 
4867 /*
4868  Constructs a rectangle at position (\a x, \a y) and size \a width
4869  by \a height, on \a canvas.
4870 */
4871 QtCanvasRectangle::QtCanvasRectangle(int x, int y, int width, int height, QtCanvas* canvas) :
4872  QtCanvasPolygonalItem(canvas), w(width), h(height)
4873 {
4874  move(x, y);
4875 }
4876 
4877 /*
4878  Destroys the rectangle.
4879 */
4881 {
4882  hide();
4883 }
4884 
4885 /*
4886  Returns the width of the rectangle.
4887 */
4888 int
4890 {
4891  return w;
4892 }
4893 
4894 /*
4895  Returns the height of the rectangle.
4896 */
4897 int
4899 {
4900  return h;
4901 }
4902 
4903 /*
4904  Sets the \a width and \a height of the rectangle.
4905 */
4906 void
4907 QtCanvasRectangle::setSize(int width, int height)
4908 {
4909  if (w != width || h != height)
4910  {
4911  removeFromChunks();
4912  w = width;
4913  h = height;
4914  addToChunks();
4915  }
4916 }
4917 
4918 /*
4919  \fn QSize QtCanvasRectangle::size() const
4920 
4921  Returns the width() and height() of the rectangle.
4922 
4923  \sa rect(), setSize()
4924 */
4925 
4926 /*
4927  \fn QRect QtCanvasRectangle::rect() const
4928 
4929  Returns the integer-converted x(), y() position and size() of the
4930  rectangle as a QRect.
4931 */
4932 
4933 /*
4934  \reimp
4935 */
4936 QPolygon
4938 {
4939  QPolygon pa(4);
4940  int pw = (pen().width() + 1) / 2;
4941 
4942  if (pw < 1)
4943  {
4944  pw = 1;
4945  }
4946 
4947  if (pen() == NoPen)
4948  {
4949  pw = 0;
4950  }
4951 
4952  pa[0] = QPoint((int)x() - pw, (int)y() - pw);
4953  pa[1] = pa[0] + QPoint(w + pw * 2, 0);
4954  pa[2] = pa[1] + QPoint(0, h + pw * 2);
4955  pa[3] = pa[0] + QPoint(0, h + pw * 2);
4956  return pa;
4957 }
4958 
4959 /*
4960  Draws the rectangle on painter \a p.
4961 */
4962 void
4964 {
4965  p.drawRect((int)x(), (int)y(), w, h);
4966 }
4967 
4968 /*
4969  \class QtCanvasEllipse qtcanvas.h
4970  \brief The QtCanvasEllipse class provides an ellipse or ellipse segment on a QtCanvas.
4971 
4972  A canvas item that paints an ellipse or ellipse segment with a QBrush.
4973  The ellipse's height, width, start angle and angle length can be set
4974  at construction time. The size can be changed at runtime with
4975  setSize(), and the angles can be changed (if you're displaying an
4976  ellipse segment rather than a whole ellipse) with setAngles().
4977 
4978  Note that angles are specified in 16ths of a degree.
4979 
4980  \target anglediagram
4981  \img qcanvasellipse.png Ellipse
4982 
4983  If a start angle and length angle are set then an ellipse segment
4984  will be drawn. The start angle is the angle that goes from zero in a
4985  counter-clockwise direction (shown in green in the diagram). The
4986  length angle is the angle from the start angle in a
4987  counter-clockwise direction (shown in blue in the diagram). The blue
4988  segment is the segment of the ellipse that would be drawn. If no
4989  start angle and length angle are specified the entire ellipse is
4990  drawn.
4991 
4992  The ellipse can be drawn on a painter with drawShape().
4993 
4994  Like any other canvas item ellipses can be moved with move() and
4995  moveBy(), or by setting coordinates with setX(), setY() and setZ().
4996 
4997  Note: QtCanvasEllipse does not use the pen.
4998 */
4999 
5000 /*
5001  Constructs a 32x32 ellipse, centered at (0, 0) on \a canvas.
5002 */
5004  QtCanvasPolygonalItem(canvas), w(32), h(32), a1(0), a2(360 * 16)
5005 {
5006 }
5007 
5008 /*
5009  Constructs a \a width by \a height pixel ellipse, centered at
5010  (0, 0) on \a canvas.
5011 */
5012 QtCanvasEllipse::QtCanvasEllipse(int width, int height, QtCanvas* canvas) :
5013  QtCanvasPolygonalItem(canvas), w(width), h(height), a1(0), a2(360 * 16)
5014 {
5015 }
5016 
5017 // ### add a constructor taking degrees in float. 1/16 degrees is stupid. Lars
5018 // ### it's how QPainter does it, so QtCanvas does too for consistency. If it's
5019 // ### a good idea, it should be added to QPainter, not just to QtCanvas. Warwick
5020 /*
5021  Constructs a \a width by \a height pixel ellipse, centered at
5022  (0, 0) on \a canvas. Only a segment of the ellipse is drawn,
5023  starting at angle \a startangle, and extending for angle \a angle
5024  (the angle length).
5025 
5026  Note that angles are specified in sixteenths of a degree.
5027 */
5029  int height,
5030  int startangle,
5031  int angle,
5032  QtCanvas* canvas) :
5033  QtCanvasPolygonalItem(canvas), w(width), h(height), a1(startangle), a2(angle)
5034 {
5035 }
5036 
5037 /*
5038  Destroys the ellipse.
5039 */
5041 {
5042  hide();
5043 }
5044 
5045 /*
5046  Returns the width of the ellipse.
5047 */
5048 int
5050 {
5051  return w;
5052 }
5053 
5054 /*
5055  Returns the height of the ellipse.
5056 */
5057 int
5059 {
5060  return h;
5061 }
5062 
5063 /*
5064  Sets the \a width and \a height of the ellipse.
5065 */
5066 void
5067 QtCanvasEllipse::setSize(int width, int height)
5068 {
5069  if (w != width || h != height)
5070  {
5071  removeFromChunks();
5072  w = width;
5073  h = height;
5074  addToChunks();
5075  }
5076 }
5077 
5078 /*
5079  \fn int QtCanvasEllipse::angleStart() const
5080 
5081  Returns the start angle in 16ths of a degree. Initially
5082  this will be 0.
5083 
5084  \sa setAngles(), angleLength()
5085 */
5086 
5087 /*
5088  \fn int QtCanvasEllipse::angleLength() const
5089 
5090  Returns the length angle (the extent of the ellipse segment) in
5091  16ths of a degree. Initially this will be 360 * 16 (a complete
5092  ellipse).
5093 
5094  \sa setAngles(), angleStart()
5095 */
5096 
5097 /*
5098  Sets the angles for the ellipse. The start angle is \a start and
5099  the extent of the segment is \a length (the angle length) from the
5100  \a start. The angles are specified in 16ths of a degree. By
5101  default the ellipse will start at 0 and have an angle length of
5102  360 * 16 (a complete ellipse).
5103 
5104  \sa angleStart(), angleLength()
5105 */
5106 void
5107 QtCanvasEllipse::setAngles(int start, int length)
5108 {
5109  if (a1 != start || a2 != length)
5110  {
5111  removeFromChunks();
5112  a1 = start;
5113  a2 = length;
5114  addToChunks();
5115  }
5116 }
5117 
5118 /*
5119  \reimp
5120 */
5121 QPolygon
5123 {
5124  QPainterPath path;
5125  path.arcTo(
5126  QRectF(x() - w / 2.0 + 0.5 - 1, y() - h / 2.0 + 0.5 - 1, w + 3, h + 3), a1 / 16., a2 / 16.);
5127  return path.toFillPolygon().toPolygon();
5128 }
5129 
5130 /*
5131  Draws the ellipse, centered at x(), y() using the painter \a p.
5132 
5133  Note that QtCanvasEllipse does not support an outline (the pen is
5134  always NoPen).
5135 */
5136 void
5138 {
5139  p.setPen(NoPen); // since QRegion(QPolygon) excludes outline :-()-:
5140 
5141  if (!a1 && a2 == 360 * 16)
5142  {
5143  p.drawEllipse(int(x() - w / 2.0 + 0.5), int(y() - h / 2.0 + 0.5), w, h);
5144  }
5145  else
5146  {
5147  p.drawPie(int(x() - w / 2.0 + 0.5), int(y() - h / 2.0 + 0.5), w, h, a1, a2);
5148  }
5149 }
5150 
5151 /*
5152  \class QtCanvasText
5153  \brief The QtCanvasText class provides a text object on a QtCanvas.
5154 
5155  A canvas text item has text with font, color and alignment
5156  attributes. The text and font can be set in the constructor or set
5157  or changed later with setText() and setFont(). The color is set
5158  with setColor() and the alignment with setTextFlags(). The text
5159  item's bounding rectangle is retrieved with boundingRect().
5160 
5161  The text can be drawn on a painter with draw().
5162 
5163  Like any other canvas item text items can be moved with
5164  QtCanvasItem::move() and QtCanvasItem::moveBy(), or by setting
5165  coordinates with QtCanvasItem::setX(), QtCanvasItem::setY() and
5166  QtCanvasItem::setZ().
5167 */
5168 
5169 /*
5170  Constructs a QtCanvasText with the text "<text>", on \a canvas.
5171 */
5172 QtCanvasText::QtCanvasText(QtCanvas* canvas) : QtCanvasItem(canvas), txt("<text>"), flags(0)
5173 {
5174  setRect();
5175 }
5176 
5177 // ### add textflags to the constructor? Lars
5178 /*
5179  Constructs a QtCanvasText with the text \a t, on canvas \a canvas.
5180 */
5181 QtCanvasText::QtCanvasText(const QString& t, QtCanvas* canvas) :
5182  QtCanvasItem(canvas), txt(t), flags(0)
5183 {
5184  setRect();
5185 }
5186 
5187 // ### see above
5188 /*
5189  Constructs a QtCanvasText with the text \a t and font \a f, on the
5190  canvas \a canvas.
5191 */
5192 QtCanvasText::QtCanvasText(const QString& t, QFont f, QtCanvas* canvas) :
5193  QtCanvasItem(canvas), txt(t), flags(0), fnt(f)
5194 {
5195  setRect();
5196 }
5197 
5198 /*
5199  Destroys the canvas text item.
5200 */
5202 {
5203  removeFromChunks();
5204 }
5205 
5206 /*
5207  Returns the bounding rectangle of the text.
5208 */
5209 QRect
5211 {
5212  return brect;
5213 }
5214 
5215 void
5216 QtCanvasText::setRect()
5217 {
5218  brect = QFontMetrics(fnt).boundingRect(int(x()), int(y()), 0, 0, flags, txt);
5219 }
5220 
5221 /*
5222  \fn int QtCanvasText::textFlags() const
5223 
5224  Returns the currently set alignment flags.
5225 
5226  \sa setTextFlags() Qt::AlignmentFlag Qt::TextFlag
5227 */
5228 
5229 
5230 /*
5231  Sets the alignment flags to \a f. These are a bitwise OR of the
5232  flags available to QPainter::drawText() -- see the
5233  \l{Qt::AlignmentFlag}s and \l{Qt::TextFlag}s.
5234 
5235  \sa setFont() setColor()
5236 */
5237 void
5239 {
5240  if (flags != f)
5241  {
5242  removeFromChunks();
5243  flags = f;
5244  setRect();
5245  addToChunks();
5246  }
5247 }
5248 
5249 /*
5250  Returns the text item's text.
5251 
5252  \sa setText()
5253 */
5254 QString
5256 {
5257  return txt;
5258 }
5259 
5260 /*
5261  Sets the text item's text to \a t. The text may contain newlines.
5262 
5263  \sa text(), setFont(), setColor() setTextFlags()
5264 */
5265 void
5266 QtCanvasText::setText(const QString& t)
5267 {
5268  if (txt != t)
5269  {
5270  removeFromChunks();
5271  txt = t;
5272  setRect();
5273  addToChunks();
5274  }
5275 }
5276 
5277 /*
5278  Returns the font in which the text is drawn.
5279 
5280  \sa setFont()
5281 */
5282 QFont
5284 {
5285  return fnt;
5286 }
5287 
5288 /*
5289  Sets the font in which the text is drawn to font \a f.
5290 
5291  \sa font()
5292 */
5293 void
5294 QtCanvasText::setFont(const QFont& f)
5295 {
5296  if (f != fnt)
5297  {
5298  removeFromChunks();
5299  fnt = f;
5300  setRect();
5301  addToChunks();
5302  }
5303 }
5304 
5305 /*
5306  Returns the color of the text.
5307 
5308  \sa setColor()
5309 */
5310 QColor
5312 {
5313  return col;
5314 }
5315 
5316 /*
5317  Sets the color of the text to the color \a c.
5318 
5319  \sa color(), setFont()
5320 */
5321 void
5323 {
5324  col = c;
5325  changeChunks();
5326 }
5327 
5328 /*
5329  \reimp
5330 */
5331 void
5332 QtCanvasText::moveBy(double dx, double dy)
5333 {
5334  int idx = int(x() + dx) - int(x());
5335  int idy = int(y() + dy) - int(y());
5336 
5337  if (idx || idy)
5338  {
5339  removeFromChunks();
5340  }
5341 
5342  myx += dx;
5343  myy += dy;
5344 
5345  if (idx || idy)
5346  {
5347  brect.translate(idx, idy);
5348  addToChunks();
5349  }
5350 }
5351 
5352 /*
5353  Draws the text using the painter \a painter.
5354 */
5355 void
5356 QtCanvasText::draw(QPainter& painter)
5357 {
5358  painter.setFont(fnt);
5359  painter.setPen(col);
5360  painter.drawText(
5361  painter.fontMetrics().boundingRect(int(x()), int(y()), 0, 0, flags, txt), flags, txt);
5362 }
5363 
5364 /*
5365  \reimp
5366 */
5367 void
5368 QtCanvasText::changeChunks()
5369 {
5370  if (isVisible() && canvas())
5371  {
5372  int chunksize = canvas()->chunkSize();
5373 
5374  for (int j = brect.top() / chunksize; j <= brect.bottom() / chunksize; j++)
5375  {
5376  for (int i = brect.left() / chunksize; i <= brect.right() / chunksize; i++)
5377  {
5378  canvas()->setChangedChunk(i, j);
5379  }
5380  }
5381  }
5382 }
5383 
5384 /*
5385  Adds the text item to the appropriate chunks.
5386 */
5387 void
5388 QtCanvasText::addToChunks()
5389 {
5390  if (isVisible() && canvas())
5391  {
5392  int chunksize = canvas()->chunkSize();
5393 
5394  for (int j = brect.top() / chunksize; j <= brect.bottom() / chunksize; j++)
5395  {
5396  for (int i = brect.left() / chunksize; i <= brect.right() / chunksize; i++)
5397  {
5398  canvas()->addItemToChunk(this, i, j);
5399  }
5400  }
5401  }
5402 }
5403 
5404 /*
5405  Removes the text item from the appropriate chunks.
5406 */
5407 void
5408 QtCanvasText::removeFromChunks()
5409 {
5410  if (isVisible() && canvas())
5411  {
5412  int chunksize = canvas()->chunkSize();
5413 
5414  for (int j = brect.top() / chunksize; j <= brect.bottom() / chunksize; j++)
5415  {
5416  for (int i = brect.left() / chunksize; i <= brect.right() / chunksize; i++)
5417  {
5418  canvas()->removeItemFromChunk(this, i, j);
5419  }
5420  }
5421  }
5422 }
5423 
5424 /*
5425  Returns 0 (QtCanvasItem::Rtti_Item).
5426 
5427  Make your derived classes return their own values for rtti(), so
5428  that you can distinguish between objects returned by
5429  QtCanvas::at(). You should use values greater than 1000 to allow
5430  for extensions to this class.
5431 
5432  Overuse of this functionality can damage its extensibility. For
5433  example, once you have identified a base class of a QtCanvasItem
5434  found by QtCanvas::at(), cast it to that type and call meaningful
5435  methods rather than acting upon the object based on its rtti
5436  value.
5437 
5438  For example:
5439 
5440  \code
5441  QtCanvasItem* item;
5442  // Find an item, e.g. with QtCanvasItem::collisions().
5443  ...
5444  if (item->rtti() == MySprite::RTTI) {
5445  MySprite* s = (MySprite*)item;
5446  if (s->isDamagable()) s->loseHitPoints(1000);
5447  if (s->isHot()) myself->loseHitPoints(1000);
5448  ...
5449  }
5450  \endcode
5451 */
5452 int
5454 {
5455  return RTTI;
5456 }
5457 
5458 int QtCanvasItem::RTTI = Rtti_Item;
5459 
5460 /*
5461  Returns 1 (QtCanvasItem::Rtti_Sprite).
5462 
5463  \sa QtCanvasItem::rtti()
5464 */
5465 int
5467 {
5468  return RTTI;
5469 }
5470 
5471 int QtCanvasSprite::RTTI = Rtti_Sprite;
5472 
5473 /*
5474  Returns 2 (QtCanvasItem::Rtti_PolygonalItem).
5475 
5476  \sa QtCanvasItem::rtti()
5477 */
5478 int
5480 {
5481  return RTTI;
5482 }
5483 
5484 int QtCanvasPolygonalItem::RTTI = Rtti_PolygonalItem;
5485 
5486 /*
5487  Returns 3 (QtCanvasItem::Rtti_Text).
5488 
5489  \sa QtCanvasItem::rtti()
5490 */
5491 int
5493 {
5494  return RTTI;
5495 }
5496 
5497 int QtCanvasText::RTTI = Rtti_Text;
5498 
5499 /*
5500  Returns 4 (QtCanvasItem::Rtti_Polygon).
5501 
5502  \sa QtCanvasItem::rtti()
5503 */
5504 int
5506 {
5507  return RTTI;
5508 }
5509 
5510 int QtCanvasPolygon::RTTI = Rtti_Polygon;
5511 
5512 /*
5513  Returns 5 (QtCanvasItem::Rtti_Rectangle).
5514 
5515  \sa QtCanvasItem::rtti()
5516 */
5517 int
5519 {
5520  return RTTI;
5521 }
5522 
5523 int QtCanvasRectangle::RTTI = Rtti_Rectangle;
5524 
5525 /*
5526  Returns 6 (QtCanvasItem::Rtti_Ellipse).
5527 
5528  \sa QtCanvasItem::rtti()
5529 */
5530 int
5532 {
5533  return RTTI;
5534 }
5535 
5536 int QtCanvasEllipse::RTTI = Rtti_Ellipse;
5537 
5538 /*
5539  Returns 7 (QtCanvasItem::Rtti_Line).
5540 
5541  \sa QtCanvasItem::rtti()
5542 */
5543 int
5545 {
5546  return RTTI;
5547 }
5548 
5549 int QtCanvasLine::RTTI = Rtti_Line;
5550 
5551 /*
5552  Returns 8 (QtCanvasItem::Rtti_Spline).
5553 
5554  \sa QtCanvasItem::rtti()
5555 */
5556 int
5558 {
5559  return RTTI;
5560 }
5561 
5562 int QtCanvasSpline::RTTI = Rtti_Spline;
5563 
5564 /*
5565  Constructs a QtCanvasSprite which uses images from the
5566  QtCanvasPixmapArray \a a.
5567 
5568  The sprite in initially positioned at (0, 0) on \a canvas, using
5569  frame 0.
5570 */
5572  QtCanvasItem(canvas), frm(0), anim_val(0), anim_state(0), anim_type(0), images(a)
5573 {
5574 }
5575 
5576 /*
5577  Set the array of images used for displaying the sprite to the
5578  QtCanvasPixmapArray \a a.
5579 
5580  If the current frame() is larger than the number of images in \a
5581  a, the current frame will be reset to 0.
5582 */
5583 void
5585 {
5586  bool isvisible = isVisible();
5587 
5588  if (isvisible && images)
5589  {
5590  hide();
5591  }
5592 
5593  images = a;
5594 
5595  if (frm >= (int)images->count())
5596  {
5597  frm = 0;
5598  }
5599 
5600  if (isvisible)
5601  {
5602  show();
5603  }
5604 }
5605 
5606 /*
5607 \internal
5608 
5609 Marks any chunks the sprite touches as changed.
5610 */
5611 void
5612 QtCanvasSprite::changeChunks()
5613 {
5614  if (isVisible() && canvas())
5615  {
5616  int chunksize = canvas()->chunkSize();
5617 
5618  for (int j = topEdge() / chunksize; j <= bottomEdge() / chunksize; j++)
5619  {
5620  for (int i = leftEdge() / chunksize; i <= rightEdge() / chunksize; i++)
5621  {
5622  canvas()->setChangedChunk(i, j);
5623  }
5624  }
5625  }
5626 }
5627 
5628 /*
5629  Destroys the sprite and removes it from the canvas. Does \e not
5630  delete the images.
5631 */
5633 {
5634  removeFromChunks();
5635 }
5636 
5637 /*
5638  Sets the animation frame used for displaying the sprite to \a f,
5639  an index into the QtCanvasSprite's QtCanvasPixmapArray. The call
5640  will be ignored if \a f is larger than frameCount() or smaller
5641  than 0.
5642 
5643  \sa frame() move()
5644 */
5645 void
5647 {
5648  move(x(), y(), f);
5649 }
5650 
5651 /*
5652  \enum QtCanvasSprite::FrameAnimationType
5653 
5654  This enum is used to identify the different types of frame
5655  animation offered by QtCanvasSprite.
5656 
5657  \value Cycle at each advance the frame number will be incremented by
5658  1 (modulo the frame count).
5659  \value Oscillate at each advance the frame number will be
5660  incremented by 1 up to the frame count then decremented to by 1 to
5661  0, repeating this sequence forever.
5662 */
5663 
5664 /*
5665  Sets the animation characteristics for the sprite.
5666 
5667  For \a type == \c Cycle, the frames will increase by \a step
5668  at each advance, modulo the frameCount().
5669 
5670  For \a type == \c Oscillate, the frames will increase by \a step
5671  at each advance, up to the frameCount(), then decrease by \a step
5672  back to 0, repeating forever.
5673 
5674  The \a state parameter is for internal use.
5675 */
5676 void
5678 {
5679  anim_val = step;
5680  anim_type = type;
5681  anim_state = state;
5682  setAnimated(true);
5683 }
5684 
5685 /*
5686  Extends the default QtCanvasItem implementation to provide the
5687  functionality of setFrameAnimation().
5688 
5689  The \a phase is 0 or 1: see QtCanvasItem::advance() for details.
5690 
5691  \sa QtCanvasItem::advance() setVelocity()
5692 */
5693 void
5695 {
5696  if (phase == 1)
5697  {
5698  int nf = frame();
5699 
5700  if (anim_type == Oscillate)
5701  {
5702  if (anim_state)
5703  {
5704  nf += anim_val;
5705  }
5706  else
5707  {
5708  nf -= anim_val;
5709  }
5710 
5711  if (nf < 0)
5712  {
5713  nf = abs(anim_val);
5714  anim_state = !anim_state;
5715  }
5716  else if (nf >= frameCount())
5717  {
5718  nf = frameCount() - 1 - abs(anim_val);
5719  anim_state = !anim_state;
5720  }
5721  }
5722  else
5723  {
5724  nf = (nf + anim_val + frameCount()) % frameCount();
5725  }
5726 
5727  move(x() + xVelocity(), y() + yVelocity(), nf);
5728  }
5729 }
5730 
5731 /*
5732  \fn int QtCanvasSprite::frame() const
5733 
5734  Returns the index of the current animation frame in the
5735  QtCanvasSprite's QtCanvasPixmapArray.
5736 
5737  \sa setFrame(), move()
5738 */
5739 
5740 /*
5741  \fn int QtCanvasSprite::frameCount() const
5742 
5743  Returns the number of frames in the QtCanvasSprite's
5744  QtCanvasPixmapArray.
5745 */
5746 
5747 
5748 /*
5749  Moves the sprite to (\a x, \a y).
5750 */
5751 void
5752 QtCanvasSprite::move(double x, double y)
5753 {
5755 }
5756 
5757 /*
5758  \fn void QtCanvasSprite::move(double nx, double ny, int nf)
5759 
5760  Moves the sprite to (\a nx, \a ny) and sets the current
5761  frame to \a nf. \a nf will be ignored if it is larger than
5762  frameCount() or smaller than 0.
5763 */
5764 void
5765 QtCanvasSprite::move(double nx, double ny, int nf)
5766 {
5767  if (isVisible() && canvas())
5768  {
5769  hide();
5770  QtCanvasItem::move(nx, ny);
5771 
5772  if (nf >= 0 && nf < frameCount())
5773  {
5774  frm = nf;
5775  }
5776 
5777  show();
5778  }
5779  else
5780  {
5781  QtCanvasItem::move(nx, ny);
5782 
5783  if (nf >= 0 && nf < frameCount())
5784  {
5785  frm = nf;
5786  }
5787  }
5788 }
5789 
5790 
5791 class QPoint;
5792 
5794 {
5795 public:
5797  {
5798  }
5799 
5800  void scan(const QPolygon& pa, bool winding, int index = 0, int npoints = -1);
5801  void scan(const QPolygon& pa, bool winding, int index, int npoints, bool stitchable);
5802 
5803  enum Edge
5804  {
5805  Left = 1,
5806  Right = 2,
5807  Top = 4,
5809  };
5810 
5811  void scan(const QPolygon& pa, bool winding, int index, int npoints, Edge edges);
5812  virtual void processSpans(int n, QPoint* point, int* width) = 0;
5813 };
5814 
5815 // Based on Xserver code miFillGeneralPoly...
5816 /*
5817  *
5818  * Written by Brian Kelleher; Oct. 1985
5819  *
5820  * Routine to fill a polygon. Two fill rules are
5821  * supported: frWINDING and frEVENODD.
5822  *
5823  * See fillpoly.h for a complete description of the algorithm.
5824  */
5825 
5826 /*
5827  * These are the data structures needed to scan
5828  * convert regions. Two different scan conversion
5829  * methods are available -- the even-odd method, and
5830  * the winding number method.
5831  * The even-odd rule states that a point is inside
5832  * the polygon if a ray drawn from that point in any
5833  * direction will pass through an odd number of
5834  * path segments.
5835  * By the winding number rule, a point is decided
5836  * to be inside the polygon if a ray drawn from that
5837  * point in any direction passes through a different
5838  * number of clockwise and counterclockwise path
5839  * segments.
5840  *
5841  * These data structures are adapted somewhat from
5842  * the algorithm in (Foley/Van Dam) for scan converting
5843  * polygons.
5844  * The basic algorithm is to start at the top (smallest y)
5845  * of the polygon, stepping down to the bottom of
5846  * the polygon by incrementing the y coordinate. We
5847  * keep a list of edges which the current scanline crosses,
5848  * sorted by x. This list is called the Active Edge Table (AET)
5849  * As we change the y-coordinate, we update each entry in
5850  * in the active edge table to reflect the edges new xcoord.
5851  * This list must be sorted at each scanline in case
5852  * two edges intersect.
5853  * We also keep a data structure known as the Edge Table (ET),
5854  * which keeps track of all the edges which the current
5855  * scanline has not yet reached. The ET is basically a
5856  * list of ScanLineList structures containing a list of
5857  * edges which are entered at a given scanline. There is one
5858  * ScanLineList per scanline at which an edge is entered.
5859  * When we enter a new edge, we move it from the ET to the AET.
5860  *
5861  * From the AET, we can implement the even-odd rule as in
5862  * (Foley/Van Dam).
5863  * The winding number rule is a little trickier. We also
5864  * keep the EdgeTableEntries in the AET linked by the
5865  * nextWETE (winding EdgeTableEntry) link. This allows
5866  * the edges to be linked just as before for updating
5867  * purposes, but only uses the edges linked by the nextWETE
5868  * link as edges representing spans of the polygon to
5869  * drawn (as with the even-odd rule).
5870  */
5871 
5872 /* $XConsortium: miscanfill.h, v 1.5 94/04/17 20:27:50 dpw Exp $ */
5873 /*
5874 
5875 Copyright (c) 1987 X Consortium
5876 
5877 Permission is hereby granted, free of charge, to any person obtaining
5878 a copy of this software and associated documentation files (the
5879 "Software"), to deal in the Software without restriction, including
5880 without limitation the rights to use, copy, modify, merge, publish,
5881 distribute, sublicense, and/or sell copies of the Software, and to
5882 permit persons to whom the Software is furnished to do so, subject to
5883 the following conditions:
5884 
5885 The above copyright notice and this permission notice shall be included
5886 in all copies or substantial portions of the Software.
5887 
5888 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
5889 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
5890 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
5891 IN NO EVENT SHALL THE X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR
5892 OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
5893 ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
5894 OTHER DEALINGS IN THE SOFTWARE.
5895 
5896 Except as contained in this notice, the name of the X Consortium shall
5897 not be used in advertising or otherwise to promote the sale, use or
5898 other dealings in this Software without prior written authorization
5899 from the X Consortium.
5900 
5901 */
5902 
5903 
5904 /*
5905  * scanfill.h
5906  *
5907  * Written by Brian Kelleher; Jan 1985
5908  *
5909  * This file contains a few macros to help track
5910  * the edge of a filled object. The object is assumed
5911  * to be filled in scanline order, and thus the
5912  * algorithm used is an extension of Bresenham's line
5913  * drawing algorithm which assumes that y is always the
5914  * major axis.
5915  * Since these pieces of code are the same for any filled shape,
5916  * it is more convenient to gather the library in one
5917  * place, but since these pieces of code are also in
5918  * the inner loops of output primitives, procedure call
5919  * overhead is out of the question.
5920  * See the author for a derivation if needed.
5921  */
5922 
5923 /*
5924  * In scan converting polygons, we want to choose those pixels
5925  * which are inside the polygon. Thus, we add .5 to the starting
5926  * x coordinate for both left and right edges. Now we choose the
5927  * first pixel which is inside the pgon for the left edge and the
5928  * first pixel which is outside the pgon for the right edge.
5929  * Draw the left pixel, but not the right.
5930  *
5931  * How to add .5 to the starting x coordinate:
5932  * If the edge is moving to the right, then subtract dy from the
5933  * error term from the general form of the algorithm.
5934  * If the edge is moving to the left, then add dy to the error term.
5935  *
5936  * The reason for the difference between edges moving to the left
5937  * and edges moving to the right is simple: If an edge is moving
5938  * to the right, then we want the algorithm to flip immediately.
5939  * If it is moving to the left, then we don't want it to flip until
5940  * we traverse an entire pixel.
5941  */
5942 #define BRESINITPGON(dy, x1, x2, xStart, d, m, m1, incr1, incr2) \
5943  { \
5944  int dx; /* local storage */ \
5945  \
5946  /* \
5947  * if the edge is horizontal, then it is ignored \
5948  * and assumed not to be processed. Otherwise, do this stuff. \
5949  */ \
5950  if ((dy) != 0) \
5951  { \
5952  xStart = (x1); \
5953  dx = (x2)-xStart; \
5954  if (dx < 0) \
5955  { \
5956  m = dx / (dy); \
5957  m1 = m - 1; \
5958  incr1 = -2 * dx + 2 * (dy) * m1; \
5959  incr2 = -2 * dx + 2 * (dy) * m; \
5960  d = 2 * m * (dy)-2 * dx - 2 * (dy); \
5961  } \
5962  else \
5963  { \
5964  m = dx / (dy); \
5965  m1 = m + 1; \
5966  incr1 = 2 * dx - 2 * (dy) * m1; \
5967  incr2 = 2 * dx - 2 * (dy) * m; \
5968  d = -2 * m * (dy) + 2 * dx; \
5969  } \
5970  } \
5971  }
5972 
5973 #define BRESINCRPGON(d, minval, m, m1, incr1, incr2) \
5974  { \
5975  if (m1 > 0) \
5976  { \
5977  if (d > 0) \
5978  { \
5979  minval += m1; \
5980  d += incr1; \
5981  } \
5982  else \
5983  { \
5984  minval += m; \
5985  d += incr2; \
5986  } \
5987  } \
5988  else \
5989  { \
5990  if (d >= 0) \
5991  { \
5992  minval += m1; \
5993  d += incr1; \
5994  } \
5995  else \
5996  { \
5997  minval += m; \
5998  d += incr2; \
5999  } \
6000  } \
6001  }
6002 
6003 /*
6004  * This structure contains all of the information needed
6005  * to run the bresenham algorithm.
6006  * The variables may be hardcoded into the declarations
6007  * instead of using this structure to make use of
6008  * register declarations.
6009  */
6010 typedef struct
6012  int minor; /* minor axis */
6013  int d; /* decision variable */
6014  int m, m1; /* slope and slope+1 */
6015  int incr1, incr2; /* error increments */
6016 } BRESINFO;
6017 
6018 #define BRESINITPGONSTRUCT(dmaj, min1, min2, bres) \
6019  BRESINITPGON(dmaj, min1, min2, bres.minor, bres.d, bres.m, bres.m1, bres.incr1, bres.incr2)
6020 
6021 #define BRESINCRPGONSTRUCT(bres) \
6022  BRESINCRPGON(bres.d, bres.minor, bres.m, bres.m1, bres.incr1, bres.incr2)
6024 typedef struct _EdgeTableEntry
6026  int ymax; /* ycoord at which we exit this edge. */
6027  BRESINFO bres; /* Bresenham info to run the edge */
6028  struct _EdgeTableEntry* next; /* next in the list */
6029  struct _EdgeTableEntry* back; /* for insertion sort */
6030  struct _EdgeTableEntry* nextWETE; /* for winding num rule */
6031  int ClockWise; /* flag for winding number rule */
6032 } EdgeTableEntry;
6034 typedef struct _ScanLineList
6036  int scanline; /* the scanline represented */
6037  EdgeTableEntry* edgelist; /* header node */
6038  struct _ScanLineList* next; /* next in the list */
6039 } ScanLineList;
6041 typedef struct
6043  int ymax; /* ymax for the polygon */
6044  int ymin; /* ymin for the polygon */
6045  ScanLineList scanlines; /* header node */
6046 } EdgeTable;
6047 
6048 /*
6049  * Here is a struct to help with storage allocation
6050  * so we can allocate a big chunk at a time, and then take
6051  * pieces from this heap when we need to.
6052  */
6053 #define SLLSPERBLOCK 25
6055 typedef struct _ScanLineListBlock
6056 {
6058  struct _ScanLineListBlock* next;
6060 
6061 /*
6062  * number of points to buffer before sending them off
6063  * to scanlines() : Must be an even number
6064  */
6065 #define NUMPTSTOBUFFER 200
6066 
6067 /*
6068  *
6069  * a few macros for the inner loops of the fill code where
6070  * performance considerations don't allow a procedure call.
6071  *
6072  * Evaluate the given edge at the given scanline.
6073  * If the edge has expired, then we leave it and fix up
6074  * the active edge table; otherwise, we increment the
6075  * x value to be ready for the next scanline.
6076  * The winding number rule is in effect, so we must notify
6077  * the caller when the edge has been removed so he
6078  * can reorder the Winding Active Edge Table.
6079  */
6080 #define EVALUATEEDGEWINDING(pAET, pPrevAET, y, fixWAET) \
6081  { \
6082  if (pAET->ymax == y) \
6083  { /* leaving this edge */ \
6084  pPrevAET->next = pAET->next; \
6085  pAET = pPrevAET->next; \
6086  fixWAET = 1; \
6087  if (pAET) \
6088  pAET->back = pPrevAET; \
6089  } \
6090  else \
6091  { \
6092  BRESINCRPGONSTRUCT(pAET->bres); \
6093  pPrevAET = pAET; \
6094  pAET = pAET->next; \
6095  } \
6096  }
6097 
6098 
6099 /*
6100  * Evaluate the given edge at the given scanline.
6101  * If the edge has expired, then we leave it and fix up
6102  * the active edge table; otherwise, we increment the
6103  * x value to be ready for the next scanline.
6104  * The even-odd rule is in effect.
6105  */
6106 #define EVALUATEEDGEEVENODD(pAET, pPrevAET, y) \
6107  { \
6108  if (pAET->ymax == y) \
6109  { /* leaving this edge */ \
6110  pPrevAET->next = pAET->next; \
6111  pAET = pPrevAET->next; \
6112  if (pAET) \
6113  pAET->back = pPrevAET; \
6114  } \
6115  else \
6116  { \
6117  BRESINCRPGONSTRUCT(pAET->bres) \
6118  pPrevAET = pAET; \
6119  pAET = pAET->next; \
6120  } \
6121  }
6122 
6123 /***********************************************************
6124 
6125 Copyright (c) 1987 X Consortium
6126 
6127 Permission is hereby granted, free of charge, to any person obtaining a copy
6128 of this software and associated documentation files (the "Software"), to deal
6129 in the Software without restriction, including without limitation the rights
6130 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
6131 copies of the Software, and to permit persons to whom the Software is
6132 furnished to do so, subject to the following conditions:
6133 
6134 The above copyright notice and this permission notice shall be included in
6135 all copies or substantial portions of the Software.
6136 
6137 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
6138 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
6139 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
6140 X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
6141 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
6142 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
6143 
6144 Except as contained in this notice, the name of the X Consortium shall not be
6145 used in advertising or otherwise to promote the sale, use or other dealings
6146 in this Software without prior written authorization from the X Consortium.
6147 
6148 
6149 Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts.
6150 
6151  All Rights Reserved
6152 
6153 Permission to use, copy, modify, and distribute this software and its
6154 documentation for any purpose and without fee is hereby granted,
6155 provided that the above copyright notice appear in all copies and that
6156 both that copyright notice and this permission notice appear in
6157 supporting documentation, and that the name of Digital not be
6158 used in advertising or publicity pertaining to distribution of the
6159 software without specific, written prior permission.
6160 
6161 DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
6162 ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
6163 DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
6164 ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
6165 WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
6166 ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
6167 SOFTWARE.
6169 ******************************************************************/
6170 
6171 #define MAXINT 0x7fffffff
6172 #define MININT -MAXINT
6173 
6174 /*
6175  * fillUtils.c
6176  *
6177  * Written by Brian Kelleher; Oct. 1985
6178  *
6179  * This module contains all of the utility functions
6180  * needed to scan convert a polygon.
6181  *
6182  */
6183 /*
6184  * InsertEdgeInET
6185  *
6186  * Insert the given edge into the edge table.
6187  * First we must find the correct bucket in the
6188  * Edge table, then find the right slot in the
6189  * bucket. Finally, we can insert it.
6190  *
6191  */
6192 static bool
6193 miInsertEdgeInET(EdgeTable* ET,
6194  EdgeTableEntry* ETE,
6195  int scanline,
6196  ScanLineListBlock** SLLBlock,
6197  int* iSLLBlock)
6198 {
6199  register EdgeTableEntry *start, *prev;
6200  register ScanLineList *pSLL, *pPrevSLL;
6201  ScanLineListBlock* tmpSLLBlock;
6202 
6203  /*
6204  * find the right bucket to put the edge into
6205  */
6206  pPrevSLL = &ET->scanlines;
6207  pSLL = pPrevSLL->next;
6208 
6209  while (pSLL && (pSLL->scanline < scanline))
6210  {
6211  pPrevSLL = pSLL;
6212  pSLL = pSLL->next;
6213  }
6214 
6215  /*
6216  * reassign pSLL (pointer to ScanLineList) if necessary
6217  */
6218  if ((!pSLL) || (pSLL->scanline > scanline))
6219  {
6220  if (*iSLLBlock > SLLSPERBLOCK - 1)
6221  {
6222  tmpSLLBlock = (ScanLineListBlock*)malloc(sizeof(ScanLineListBlock));
6223 
6224  if (!tmpSLLBlock)
6225  {
6226  return false;
6227  }
6228 
6229  (*SLLBlock)->next = tmpSLLBlock;
6230  tmpSLLBlock->next = 0;
6231  *SLLBlock = tmpSLLBlock;
6232  *iSLLBlock = 0;
6233  }
6234 
6235  pSLL = &((*SLLBlock)->SLLs[(*iSLLBlock)++]);
6236 
6237  pSLL->next = pPrevSLL->next;
6238  pSLL->edgelist = 0;
6239  pPrevSLL->next = pSLL;
6240  }
6241 
6242  pSLL->scanline = scanline;
6243 
6244  /*
6245  * now insert the edge in the right bucket
6246  */
6247  prev = 0;
6248  start = pSLL->edgelist;
6249 
6250  while (start && (start->bres.minor < ETE->bres.minor))
6251  {
6252  prev = start;
6253  start = start->next;
6254  }
6255 
6256  ETE->next = start;
6257 
6258  if (prev)
6259  {
6260  prev->next = ETE;
6261  }
6262  else
6263  {
6264  pSLL->edgelist = ETE;
6265  }
6266 
6267  return true;
6268 }
6269 
6270 /*
6271  * CreateEdgeTable
6272  *
6273  * This routine creates the edge table for
6274  * scan converting polygons.
6275  * The Edge Table (ET) looks like:
6276  *
6277  * EdgeTable
6278  * --------
6279  * | ymax | ScanLineLists
6280  * |scanline|-->------------>-------------->...
6281  * -------- |scanline| |scanline|
6282  * |edgelist| |edgelist|
6283  * --------- ---------
6284  * | |
6285  * | |
6286  * V V
6287  * list of ETEs list of ETEs
6288  *
6289  * where ETE is an EdgeTableEntry data structure,
6290  * and there is one ScanLineList per scanline at
6291  * which an edge is initially entered.
6292  *
6293  */
6294 
6295 typedef struct
6296 {
6297 #if defined(Q_OS_MAC)
6298  int y, x;
6299 #else
6300  int x, y;
6301 #endif
6302 
6304 
6305 /*
6306  * Clean up our act.
6307  */
6308 static void
6309 miFreeStorage(ScanLineListBlock* pSLLBlock)
6310 {
6311  register ScanLineListBlock* tmpSLLBlock;
6312 
6313  while (pSLLBlock)
6314  {
6315  tmpSLLBlock = pSLLBlock->next;
6316  free(pSLLBlock);
6317  pSLLBlock = tmpSLLBlock;
6318  }
6319 }
6320 
6321 static bool
6322 miCreateETandAET(int count,
6323  DDXPointPtr pts,
6324  EdgeTable* ET,
6325  EdgeTableEntry* AET,
6326  EdgeTableEntry* pETEs,
6327  ScanLineListBlock* pSLLBlock)
6328 {
6329  register DDXPointPtr top, bottom;
6330  register DDXPointPtr PrevPt, CurrPt;
6331  int iSLLBlock = 0;
6332 
6333  int dy;
6334 
6335  if (count < 2)
6336  {
6337  return true;
6338  }
6339 
6340  /*
6341  * initialize the Active Edge Table
6342  */
6343  AET->next = 0;
6344  AET->back = 0;
6345  AET->nextWETE = 0;
6346  AET->bres.minor = MININT;
6347 
6348  /*
6349  * initialize the Edge Table.
6350  */
6351  ET->scanlines.next = 0;
6352  ET->ymax = MININT;
6353  ET->ymin = MAXINT;
6354  pSLLBlock->next = 0;
6355 
6356  PrevPt = &pts[count - 1];
6357 
6358  /*
6359  * for each vertex in the array of points.
6360  * In this loop we are dealing with two vertices at
6361  * a time -- these make up one edge of the polygon.
6362  */
6363  while (count--)
6364  {
6365  CurrPt = pts++;
6366 
6367  /*
6368  * find out which point is above and which is below.
6369  */
6370  if (PrevPt->y > CurrPt->y)
6371  {
6372  bottom = PrevPt, top = CurrPt;
6373  pETEs->ClockWise = 0;
6374  }
6375  else
6376  {
6377  bottom = CurrPt, top = PrevPt;
6378  pETEs->ClockWise = 1;
6379  }
6380 
6381  /*
6382  * don't add horizontal edges to the Edge table.
6383  */
6384  if (bottom->y != top->y)
6385  {
6386  pETEs->ymax = bottom->y - 1; /* -1 so we don't get last scanline */
6387 
6388  /*
6389  * initialize integer edge algorithm
6390  */
6391  dy = bottom->y - top->y;
6392  BRESINITPGONSTRUCT(dy, top->x, bottom->x, pETEs->bres)
6393 
6394  if (!miInsertEdgeInET(ET, pETEs, top->y, &pSLLBlock, &iSLLBlock))
6395  {
6396  miFreeStorage(pSLLBlock->next);
6397  return false;
6398  }
6399 
6400  ET->ymax = qMax(ET->ymax, PrevPt->y);
6401  ET->ymin = qMin(ET->ymin, PrevPt->y);
6402  pETEs++;
6403  }
6404 
6405  PrevPt = CurrPt;
6406  }
6407 
6408  return true;
6409 }
6410 
6411 /*
6412  * loadAET
6413  *
6414  * This routine moves EdgeTableEntries from the
6415  * EdgeTable into the Active Edge Table,
6416  * leaving them sorted by smaller x coordinate.
6417  *
6418  */
6419 
6420 static void
6421 miloadAET(EdgeTableEntry* AET, EdgeTableEntry* ETEs)
6422 {
6423  register EdgeTableEntry* pPrevAET;
6424  register EdgeTableEntry* tmp;
6425 
6426  pPrevAET = AET;
6427  AET = AET->next;
6428 
6429  while (ETEs)
6430  {
6431  while (AET && (AET->bres.minor < ETEs->bres.minor))
6432  {
6433  pPrevAET = AET;
6434  AET = AET->next;
6435  }
6436 
6437  tmp = ETEs->next;
6438  ETEs->next = AET;
6439 
6440  if (AET)
6441  {
6442  AET->back = ETEs;
6443  }
6444 
6445  ETEs->back = pPrevAET;
6446  pPrevAET->next = ETEs;
6447  pPrevAET = ETEs;
6448 
6449  ETEs = tmp;
6450  }
6451 }
6452 
6453 /*
6454  * computeWAET
6455  *
6456  * This routine links the AET by the
6457  * nextWETE (winding EdgeTableEntry) link for
6458  * use by the winding number rule. The final
6459  * Active Edge Table (AET) might look something
6460  * like:
6461  *
6462  * AET
6463  * ---------- --------- ---------
6464  * |ymax | |ymax | |ymax |
6465  * | ... | |... | |... |
6466  * |next |->|next |->|next |->...
6467  * |nextWETE| |nextWETE| |nextWETE|
6468  * --------- --------- ^--------
6469  * | | |
6470  * V-------------------> V---> ...
6471  *
6472  */
6473 static void
6474 micomputeWAET(EdgeTableEntry* AET)
6475 {
6476  register EdgeTableEntry* pWETE;
6477  register int inside = 1;
6478  register int isInside = 0;
6479 
6480  AET->nextWETE = 0;
6481  pWETE = AET;
6482  AET = AET->next;
6483 
6484  while (AET)
6485  {
6486  if (AET->ClockWise)
6487  {
6488  isInside++;
6489  }
6490  else
6491  {
6492  isInside--;
6493  }
6494 
6495  if ((!inside && !isInside) || (inside && isInside))
6496  {
6497  pWETE->nextWETE = AET;
6498  pWETE = AET;
6499  inside = !inside;
6500  }
6501 
6502  AET = AET->next;
6503  }
6504 
6505  pWETE->nextWETE = 0;
6506 }
6507 
6508 /*
6509  * InsertionSort
6510  *
6511  * Just a simple insertion sort using
6512  * pointers and back pointers to sort the Active
6513  * Edge Table.
6514  *
6515  */
6516 
6517 static int
6518 miInsertionSort(EdgeTableEntry* AET)
6519 {
6520  register EdgeTableEntry* pETEchase;
6521  register EdgeTableEntry* pETEinsert;
6522  register EdgeTableEntry* pETEchaseBackTMP;
6523  register int changed = 0;
6524 
6525  AET = AET->next;
6526 
6527  while (AET)
6528  {
6529  pETEinsert = AET;
6530  pETEchase = AET;
6531 
6532  while (pETEchase->back->bres.minor > AET->bres.minor)
6533  {
6534  pETEchase = pETEchase->back;
6535  }
6536 
6537  AET = AET->next;
6538 
6539  if (pETEchase != pETEinsert)
6540  {
6541  pETEchaseBackTMP = pETEchase->back;
6542  pETEinsert->back->next = AET;
6543 
6544  if (AET)
6545  {
6546  AET->back = pETEinsert->back;
6547  }
6548 
6549  pETEinsert->next = pETEchase;
6550  pETEchase->back->next = pETEinsert;
6551  pETEchase->back = pETEinsert;
6552  pETEinsert->back = pETEchaseBackTMP;
6553  changed = 1;
6554  }
6555  }
6556 
6557  return changed;
6558 }
6559 
6560 /*
6561  \overload
6562 */
6563 void
6564 QtPolygonScanner::scan(const QPolygon& pa, bool winding, int index, int npoints)
6565 {
6566  scan(pa, winding, index, npoints, true);
6567 }
6568 
6569 /*
6570  \overload
6571 
6572  If \a stitchable is false, the right and bottom edges of the
6573  polygon are included. This causes adjacent polygons to overlap.
6574 */
6575 void
6576 QtPolygonScanner::scan(const QPolygon& pa, bool winding, int index, int npoints, bool stitchable)
6577 {
6578  scan(pa,
6579  winding,
6580  index,
6581  npoints,
6582  stitchable ? Edge(Left + Top) : Edge(Left + Right + Top + Bottom));
6583 }
6584 
6585 /*
6586  Calls processSpans() for all scanlines of the polygon defined by
6587  \a npoints starting at \a index in \a pa.
6588 
6589  If \a winding is true, the Winding algorithm rather than the
6590  Odd-Even rule is used.
6591 
6592  The \a edges is any bitwise combination of:
6593  \list
6594  \i QtPolygonScanner::Left
6595  \i QtPolygonScanner::Right
6596  \i QtPolygonScanner::Top
6597  \i QtPolygonScanner::Bottom
6598  \endlist
6599  \a edges determines which edges are included.
6600 
6601  \warning The edges feature does not work properly.
6603 */
6604 void
6605 QtPolygonScanner::scan(const QPolygon& pa, bool winding, int index, int npoints, Edge edges)
6606 {
6607 
6608 
6609  DDXPointPtr ptsIn = (DDXPointPtr)pa.data();
6610  ptsIn += index;
6611  register EdgeTableEntry* pAET; /* the Active Edge Table */
6612  register int y; /* the current scanline */
6613  register int nPts = 0; /* number of pts in buffer */
6614  register EdgeTableEntry* pWETE; /* Winding Edge Table */
6615  register ScanLineList* pSLL; /* Current ScanLineList */
6616  register DDXPointPtr ptsOut; /* ptr to output buffers */
6617  int* width;
6618  DDXPointRec FirstPoint[NUMPTSTOBUFFER]; /* the output buffers */
6619  int FirstWidth[NUMPTSTOBUFFER];
6620  EdgeTableEntry* pPrevAET; /* previous AET entry */
6621  EdgeTable ET; /* Edge Table header node */
6622  EdgeTableEntry AET; /* Active ET header node */
6623  EdgeTableEntry* pETEs; /* Edge Table Entries buff */
6624  ScanLineListBlock SLLBlock; /* header for ScanLineList */
6625  int fixWAET = 0;
6626  int edge_l = (edges & Left) ? 1 : 0;
6627  int edge_r = (edges & Right) ? 1 : 0;
6628  int edge_t = 1; //#### (edges & Top) ? 1 : 0;
6629  int edge_b = (edges & Bottom) ? 1 : 0;
6630 
6631  if (npoints == -1)
6632  {
6633  npoints = pa.size();
6634  }
6635 
6636  if (npoints < 3)
6637  {
6638  return;
6639  }
6640 
6641  if (!(pETEs = (EdgeTableEntry*)malloc(sizeof(EdgeTableEntry) * npoints)))
6642  {
6643  return;
6644  }
6645 
6646  ptsOut = FirstPoint;
6647  width = FirstWidth;
6648 
6649  if (!miCreateETandAET(npoints, ptsIn, &ET, &AET, pETEs, &SLLBlock))
6650  {
6651  free(pETEs);
6652  return;
6653  }
6654 
6655  pSLL = ET.scanlines.next;
6656 
6657  if (!winding)
6658  {
6659  /*
6660  * for each scanline
6661  */
6662  for (y = ET.ymin + 1 - edge_t; y < ET.ymax + edge_b; y++)
6663  {
6664  /*
6665  * Add a new edge to the active edge table when we
6666  * get to the next edge.
6667  */
6668  if (pSLL && y == pSLL->scanline)
6669  {
6670  miloadAET(&AET, pSLL->edgelist);
6671  pSLL = pSLL->next;
6672  }
6673 
6674  pPrevAET = &AET;
6675  pAET = AET.next;
6676 
6677  /*
6678  * for each active edge
6679  */
6680  while (pAET)
6681  {
6682  ptsOut->x = pAET->bres.minor + 1 - edge_l;
6683  ptsOut++->y = y;
6684  *width++ = pAET->next->bres.minor - pAET->bres.minor - 1 + edge_l + edge_r;
6685  nPts++;
6686 
6687  /*
6688  * send out the buffer when its full
6689  */
6690  if (nPts == NUMPTSTOBUFFER)
6691  {
6692  processSpans(nPts, (QPoint*)FirstPoint, FirstWidth);
6693  ptsOut = FirstPoint;
6694  width = FirstWidth;
6695  nPts = 0;
6696  }
6697 
6698  EVALUATEEDGEEVENODD(pAET, pPrevAET, y)
6699  EVALUATEEDGEEVENODD(pAET, pPrevAET, y)
6700  }
6701 
6702  miInsertionSort(&AET);
6703  }
6704  }
6705  else /* default to WindingNumber */
6706  {
6707  /*
6708  * for each scanline
6709  */
6710  for (y = ET.ymin + 1 - edge_t; y < ET.ymax + edge_b; y++)
6711  {
6712  /*
6713  * Add a new edge to the active edge table when we
6714  * get to the next edge.
6715  */
6716  if (pSLL && y == pSLL->scanline)
6717  {
6718  miloadAET(&AET, pSLL->edgelist);
6719  micomputeWAET(&AET);
6720  pSLL = pSLL->next;
6721  }
6722 
6723  pPrevAET = &AET;
6724  pAET = AET.next;
6725  pWETE = pAET;
6726 
6727  /*
6728  * for each active edge
6729  */
6730  while (pAET)
6731  {
6732  /*
6733  * if the next edge in the active edge table is
6734  * also the next edge in the winding active edge
6735  * table.
6736  */
6737  if (pWETE == pAET)
6738  {
6739  ptsOut->x = pAET->bres.minor + 1 - edge_l;
6740  ptsOut++->y = y;
6741  *width++ = pAET->nextWETE->bres.minor - pAET->bres.minor - 1 + edge_l + edge_r;
6742  nPts++;
6743 
6744  /*
6745  * send out the buffer
6746  */
6747  if (nPts == NUMPTSTOBUFFER)
6748  {
6749  processSpans(nPts, (QPoint*)FirstPoint, FirstWidth);
6750  ptsOut = FirstPoint;
6751  width = FirstWidth;
6752  nPts = 0;
6753  }
6754 
6755  pWETE = pWETE->nextWETE;
6756 
6757  while (pWETE != pAET)
6758  {
6759  EVALUATEEDGEWINDING(pAET, pPrevAET, y, fixWAET)
6760  }
6761 
6762  pWETE = pWETE->nextWETE;
6763  }
6764 
6765  EVALUATEEDGEWINDING(pAET, pPrevAET, y, fixWAET)
6766  }
6767 
6768  /*
6769  * reevaluate the Winding active edge table if we
6770  * just had to resort it or if we just exited an edge.
6771  */
6772  if (miInsertionSort(&AET) || fixWAET)
6773  {
6774  micomputeWAET(&AET);
6775  fixWAET = 0;
6776  }
6777  }
6778  }
6779 
6780  /*
6781  * Get any spans that we missed by buffering
6782  */
6783 
6784 
6785  processSpans(nPts, (QPoint*)FirstPoint, FirstWidth);
6786  free(pETEs);
6787  miFreeStorage(SLLBlock.next);
6788 }
6789 
6790 /***** END OF X11-based CODE *****/
6791 
6792 
6794 {
6796 
6797 public:
6798  QtCanvasPolygonScanner(QPolygonalProcessor& p) : processor(p)
6799  {
6800  }
6801 
6802  void
6803  processSpans(int n, QPoint* point, int* width)
6804  {
6805  processor.doSpans(n, point, width);
6806  }
6807 };
6808 
6809 void
6810 QtCanvasPolygonalItem::scanPolygon(const QPolygon& pa,
6811  int winding,
6812  QPolygonalProcessor& process) const
6813 {
6814  QtCanvasPolygonScanner scanner(process);
6815  scanner.scan(pa, winding);
6816 }
QtCanvasSprite::Oscillate
@ Oscillate
Definition: qtcanvas.h:624
QtCanvasPolygonScanner
Definition: qtcanvas.cpp:6790
_EdgeTableEntry
Definition: qtcanvas.cpp:6021
QtCanvasPolygonalItem::drawShape
virtual void drawShape(QPainter &)=0
QtCanvasView::contentsMouseMoveEvent
virtual void contentsMouseMoveEvent(QMouseEvent *)
Definition: qtcanvas.cpp:3764
QtCanvas::backgroundColor
QColor backgroundColor() const
Definition: qtcanvas.cpp:1503
QtCanvasPixmapArray::operator!
bool operator!()
Definition: qtcanvas.cpp:3218
QtCanvasSprite::move
void move(double x, double y)
Definition: qtcanvas.cpp:5752
QtCanvas::addView
virtual void addView(QtCanvasView *)
Definition: qtcanvas.cpp:966
QtCanvasViewData::ixform
QMatrix ixform
Definition: qtcanvas.cpp:78
QtCanvasItem::boundingRect
virtual QRect boundingRect() const =0
QtPolygonScanner::Right
@ Right
Definition: qtcanvas.cpp:5806
QtCanvasItem::setEnabled
virtual void setEnabled(bool yes)
Definition: qtcanvas.cpp:2266
QtCanvasItem::setActive
virtual void setActive(bool yes)
Definition: qtcanvas.cpp:2298
QtCanvasItem::boundingRectAdvanced
virtual QRect boundingRectAdvanced() const
Definition: qtcanvas.cpp:2853
QtCanvasLine::rtti
int rtti() const
Definition: qtcanvas.cpp:5544
QtCanvasClusterizer::QtCanvasClusterizer
QtCanvasClusterizer(int maxclusters)
Definition: qtcanvas.cpp:138
QtCanvasPolygon::~QtCanvasPolygon
~QtCanvasPolygon()
Definition: qtcanvas.cpp:4469
QtCanvas::rect
QRect rect() const
Definition: qtcanvas.h:340
QtCanvasView::contentsContextMenuEvent
virtual void contentsContextMenuEvent(QContextMenuEvent *)
Definition: qtcanvas.cpp:3796
QtCanvasPixmap
Definition: qtcanvas.h:519
QtCanvasData::viewList
QList< QtCanvasView * > viewList
Definition: qtcanvas.cpp:65
QtCanvasRectangle::height
int height() const
Definition: qtcanvas.cpp:4898
QtCanvasView::setCanvas
void setCanvas(QtCanvas *v)
Definition: qtcanvas.cpp:3814
QtCanvas::update
virtual void update()
Definition: qtcanvas.cpp:1127
QtCanvas::chunkSize
int chunkSize() const
Definition: qtcanvas.h:370
DDXPointRec::y
int y
Definition: qtcanvas.cpp:6297
armarx::navigation::algorithm::astar::intersects
bool intersects(const VirtualRobot::BoundingBox &bb1, const VirtualRobot::BoundingBox &bb2)
Definition: AStarPlanner.cpp:36
QtCanvasText::setFont
void setFont(const QFont &)
Definition: qtcanvas.cpp:5294
QtCanvasPolygon::poly
QPolygon poly
Definition: qtcanvas.h:829
QtCanvas::drawArea
void drawArea(const QRect &, QPainter *p, bool double_buffer=false)
Definition: qtcanvas.cpp:1294
QtCanvasText::collidesWith
bool collidesWith(const QtCanvasItem *) const
Definition: qtcanvas.cpp:2638
EdgeTable::ymin
int ymin
Definition: qtcanvas.cpp:6041
QtCanvasChunk::takeChange
bool takeChange()
Definition: qtcanvas.cpp:405
QtCanvasPixmapArray::~QtCanvasPixmapArray
~QtCanvasPixmapArray()
Definition: qtcanvas.cpp:3080
DDXPointPtr
struct DDXPointRec * DDXPointPtr
QPolygonalProcessor::bounds
QRect bounds
Definition: qtcanvas.cpp:4326
QtCanvasEllipse::~QtCanvasEllipse
~QtCanvasEllipse()
Definition: qtcanvas.cpp:5040
QtCanvasItem::x
double x() const
Definition: qtcanvas.h:74
QtCanvasSpline::~QtCanvasSpline
~QtCanvasSpline()
Definition: qtcanvas.cpp:4569
QtCanvasItem::QtCanvasLine
friend class QtCanvasLine
Definition: qtcanvas.h:241
QtCanvasSpline::RTTI
static int RTTI
Definition: qtcanvas.h:843
QtCanvasChunk::change
void change()
Definition: qtcanvas.cpp:393
QtCanvas::addItemToChunk
void addItemToChunk(QtCanvasItem *, int i, int j)
Definition: qtcanvas.cpp:1435
QtCanvasItem::QtCanvasItem
QtCanvasItem(QtCanvas *canvas)
Definition: qtcanvas.cpp:1879
QtCanvasEllipse::width
int width() const
Definition: qtcanvas.cpp:5049
QtCanvasView::setHighQualityRendering
void setHighQualityRendering(bool enable)
Definition: qtcanvas.cpp:3739
index
uint8_t index
Definition: EtherCATFrame.h:59
QtCanvas::drawBackground
virtual void drawBackground(QPainter &, const QRect &area)
Definition: qtcanvas.cpp:1577
QPolygonalProcessor
Definition: qtcanvas.cpp:4126
QtCanvasText::boundingRect
QRect boundingRect() const
Definition: qtcanvas.cpp:5210
_ScanLineListBlock::SLLs
ScanLineList SLLs[SLLSPERBLOCK]
Definition: qtcanvas.cpp:6054
QtCanvas::removeItemFromChunk
void removeItemFromChunk(QtCanvasItem *, int i, int j)
Definition: qtcanvas.cpp:1451
QtCanvasItem::QtCanvasPolygonalItem
friend class QtCanvasPolygonalItem
Definition: qtcanvas.h:235
QtCanvasPolygon
Definition: qtcanvas.h:813
QtCanvasEllipse::areaPoints
QPolygon areaPoints() const
Definition: qtcanvas.cpp:5122
QtCanvasRectangle::width
int width() const
Definition: qtcanvas.cpp:4889
QtCanvasSprite::rightEdge
int rightEdge() const
Definition: qtcanvas.cpp:3339
QtCanvas::drawViewArea
void drawViewArea(QtCanvasView *view, QPainter *p, const QRect &r, bool dbuf)
Definition: qtcanvas.cpp:1110
list
list(APPEND SOURCES ${QT_RESOURCES}) set(COMPONENT_LIBS ArmarXGui ArmarXCoreObservers ArmarXCoreEigen3Variants PlotterController $
Definition: CMakeLists.txt:49
QtCanvasWidget::paintEvent
void paintEvent(QPaintEvent *e)
Definition: qtcanvas.cpp:3669
QtCanvasItem::moveBy
virtual void moveBy(double dx, double dy)
Definition: qtcanvas.cpp:1973
qt_testCollision
bool qt_testCollision(const QtCanvasSprite *s1, const QtCanvasSprite *s2)
Definition: qtcanvas.cpp:2308
QtCanvasEllipse::angleLength
int angleLength() const
Definition: qtcanvas.h:906
QPolygonalProcessor::addBits
void addBits(int x1, int x2, uchar newbits, int xo, int yo)
Definition: qtcanvas.cpp:4169
QtCanvasPolygon::moveBy
void moveBy(double dx, double dy)
Definition: qtcanvas.cpp:4509
DDXPointRec
Definition: qtcanvas.cpp:6292
QtCanvasLine::moveBy
void moveBy(double dx, double dy)
Definition: qtcanvas.cpp:4824
QtCanvasRectangle::collidesWith
bool collidesWith(const QtCanvasItem *) const
Definition: qtcanvas.cpp:2600
QtCanvasLine::areaPoints
QPolygon areaPoints() const
Definition: qtcanvas.cpp:4768
QPolygonalProcessor::QPolygonalProcessor
QPolygonalProcessor(QtCanvas *c, const QPolygon &pa)
Definition: qtcanvas.cpp:4129
QtCanvas::removeAnimation
virtual void removeAnimation(QtCanvasItem *)
Definition: qtcanvas.cpp:944
QtCanvas::setChanged
virtual void setChanged(const QRect &area)
Definition: qtcanvas.cpp:1161
QtCanvasLine::setPoints
void setPoints(int x1, int y1, int x2, int y2)
Definition: qtcanvas.cpp:4739
QtCanvasData
Definition: qtcanvas.cpp:58
QtCanvas::removeItemFromChunkContaining
void removeItemFromChunkContaining(QtCanvasItem *, int x, int y)
Definition: qtcanvas.cpp:1483
DDXPointRec::x
int x
Definition: qtcanvas.cpp:6297
QtCanvasView::setWorldMatrix
bool setWorldMatrix(const QMatrix &)
Definition: qtcanvas.cpp:3880
QtCanvasView::contentsDragLeaveEvent
virtual void contentsDragLeaveEvent(QDragLeaveEvent *)
Definition: qtcanvas.cpp:3780
QtPolygonScanner::Top
@ Top
Definition: qtcanvas.cpp:5807
QtCanvasItem::setCanvas
virtual void setCanvas(QtCanvas *)
Definition: qtcanvas.cpp:2117
QtCanvasItem::isVisible
bool isVisible() const
Definition: qtcanvas.h:147
QtCanvas::QtCanvas
QtCanvas(QObject *parent=0)
Definition: qtcanvas.cpp:618
QtCanvasViewData::highQuality
bool highQuality
Definition: qtcanvas.cpp:79
QtCanvasSprite::width
int width() const
Definition: qtcanvas.cpp:3509
QtCanvasWidget::dragMoveEvent
void dragMoveEvent(QDragMoveEvent *e)
Definition: qtcanvas.cpp:3636
QtCanvas::setTile
virtual void setTile(int x, int y, int tilenum)
Definition: qtcanvas.cpp:1760
QtCanvasText::setColor
void setColor(const QColor &)
Definition: qtcanvas.cpp:5322
qtcanvas.h
QtCanvasText::text
QString text() const
Definition: qtcanvas.cpp:5255
_ScanLineListBlock::next
struct _ScanLineListBlock * next
Definition: qtcanvas.cpp:6055
QtCanvas::width
int width() const
Definition: qtcanvas.h:322
_EdgeTableEntry::ymax
int ymax
Definition: qtcanvas.cpp:6023
QPolygonalProcessor::pnt
int pnt
Definition: qtcanvas.cpp:4323
QtCanvas::setTiles
virtual void setTiles(QPixmap tiles, int h, int v, int tilewidth, int tileheight)
Definition: qtcanvas.cpp:1670
c
constexpr T c
Definition: UnscentedKalmanFilterTest.cpp:46
QtCanvasWidget::contextMenuEvent
void contextMenuEvent(QContextMenuEvent *e)
Definition: qtcanvas.cpp:3660
QtCanvasPolygonalItem::RTTI
static int RTTI
Definition: qtcanvas.h:735
QtCanvasSprite::FrameAnimationType
FrameAnimationType
Definition: qtcanvas.h:621
QtCanvasItemExtra
Definition: qtcanvas.cpp:1781
QtCanvasViewData
Definition: qtcanvas.cpp:70
QtCanvasView::drawContents
virtual void drawContents(QPainter *p, int cx, int cy, int cw, int ch)
Definition: qtcanvas.cpp:3917
_EdgeTableEntry::ClockWise
int ClockWise
Definition: qtcanvas.cpp:6028
QtCanvasEllipse::collidesWith
bool collidesWith(const QtCanvasItem *) const
Definition: qtcanvas.cpp:2619
QtCanvasItem::collidesWith
virtual bool collidesWith(const QtCanvasItem *) const =0
QtCanvasItem::QtCanvasText
friend class QtCanvasText
Definition: qtcanvas.h:240
_ScanLineList::next
struct _ScanLineList * next
Definition: qtcanvas.cpp:6035
QtCanvas::collisions
QtCanvasItemList collisions(const QPoint &) const
Definition: qtcanvas.cpp:2703
QtCanvasSpline::rtti
int rtti() const
Definition: qtcanvas.cpp:5557
magic_enum::detail::n
constexpr auto n() noexcept
Definition: magic_enum.hpp:418
QtCanvasPixmapArray::count
uint count() const
Definition: qtcanvas.h:591
armarx::armem::contains
bool contains(const MemoryID &general, const MemoryID &specific)
Indicates whether general is "less specific" than, or equal to, specific, i.e.
Definition: MemoryID.cpp:563
QtCanvasPixmapArray::setImage
void setImage(int i, QtCanvasPixmap *p)
Definition: qtcanvas.cpp:3253
QtCanvasSprite::height
int height() const
Definition: qtcanvas.cpp:3520
visionx::imrecman::ok
@ ok
Definition: ImageRecordingManagerInterface.ice:45
QtCanvasRectangle::setSize
void setSize(int w, int h)
Definition: qtcanvas.cpp:4907
MAXINT
#define MAXINT
Definition: qtcanvas.cpp:6168
QtCanvasWidget::mouseDoubleClickEvent
void mouseDoubleClickEvent(QMouseEvent *e)
Definition: qtcanvas.cpp:3624
QtCanvasChunk::hasChanged
bool hasChanged() const
Definition: qtcanvas.cpp:399
QtPolygonScanner
Definition: qtcanvas.cpp:5793
QtCanvasChunk
Definition: qtcanvas.cpp:356
QtCanvasPolygonalItem::setWinding
void setWinding(bool)
Definition: qtcanvas.cpp:4071
QtCanvasChunk::add
void add(QtCanvasItem *item)
Definition: qtcanvas.cpp:379
QtCanvas::advance
virtual void advance()
Definition: qtcanvas.cpp:1073
QtCanvasSprite::advance
virtual void advance(int stage)
Definition: qtcanvas.cpp:5694
QtCanvasSpline::setControlPoints
void setControlPoints(QPolygon, bool closed=true)
Definition: qtcanvas.cpp:4587
QtCanvasChunk::QtCanvasChunk
QtCanvasChunk()
Definition: qtcanvas.cpp:359
QtCanvasRectangle::rtti
int rtti() const
Definition: qtcanvas.cpp:5518
QtCanvasView::contentsDragEnterEvent
virtual void contentsDragEnterEvent(QDragEnterEvent *)
Definition: qtcanvas.cpp:3770
QtCanvasLine::RTTI
static int RTTI
Definition: qtcanvas.h:871
QtCanvasClusterizer::clear
void clear()
Definition: qtcanvas.cpp:149
_ScanLineList::edgelist
EdgeTableEntry * edgelist
Definition: qtcanvas.cpp:6034
QtCanvas::resized
void resized()
QtCanvasPixmapArray::readCollisionMasks
bool readCollisionMasks(const QString &filenamepattern)
Definition: qtcanvas.cpp:3146
_EdgeTableEntry::nextWETE
struct _EdgeTableEntry * nextWETE
Definition: qtcanvas.cpp:6027
QtCanvas::height
int height() const
Definition: qtcanvas.h:328
QtCanvasPolygonalItem
Definition: qtcanvas.h:707
QtCanvasViewData::xform
QMatrix xform
Definition: qtcanvas.cpp:77
QtPolygonScanner::processSpans
virtual void processSpans(int n, QPoint *point, int *width)=0
QtCanvasPolygonalItem::~QtCanvasPolygonalItem
virtual ~QtCanvasPolygonalItem()
Definition: qtcanvas.cpp:4042
QtCanvas::allItems
QtCanvasItemList allItems()
Definition: qtcanvas.cpp:706
QtCanvasWidget::QtCanvasWidget
QtCanvasWidget(QtCanvasView *view)
Definition: qtcanvas.cpp:3597
QPolygonalProcessor::canvas
QtCanvas * canvas
Definition: qtcanvas.cpp:4325
armarx::armem::client::query_fns::all
auto all()
Definition: query_fns.h:9
armarx::ctrlutil::a
double a(double t, double a0, double j)
Definition: CtrlUtil.h:45
QtCanvasItem::hide
void hide()
Definition: qtcanvas.cpp:2162
QtCanvasText::rtti
int rtti() const
Definition: qtcanvas.cpp:5492
QtCanvasText::color
QColor color() const
Definition: qtcanvas.cpp:5311
QtCanvasSprite::RTTI
static int RTTI
Definition: qtcanvas.h:642
QtCanvas::setChangedChunkContaining
virtual void setChangedChunkContaining(int x, int y)
Definition: qtcanvas.cpp:1418
QtCanvas::resize
virtual void resize(int width, int height)
Definition: qtcanvas.cpp:716
armarx::abs
std::vector< T > abs(const std::vector< T > &v)
Definition: VectorHelpers.h:281
QtCanvas::setBackgroundPixmap
virtual void setBackgroundPixmap(const QPixmap &p)
Definition: qtcanvas.cpp:1552
QtCanvasViewData::QtCanvasViewData
QtCanvasViewData()
Definition: qtcanvas.cpp:73
QtCanvasClusterizer::~QtCanvasClusterizer
~QtCanvasClusterizer()
Definition: qtcanvas.cpp:143
QtCanvasWidget::mousePressEvent
void mousePressEvent(QMouseEvent *e)
Definition: qtcanvas.cpp:3606
QtCanvasPolygonalItem::setPen
virtual void setPen(QPen p)
Definition: qtcanvas.cpp:4414
QtCanvas::removeItem
virtual void removeItem(QtCanvasItem *)
Definition: qtcanvas.cpp:955
if
if(!yyvaluep)
Definition: Grammar.cpp:645
QtCanvasSprite::~QtCanvasSprite
virtual ~QtCanvasSprite()
Definition: qtcanvas.cpp:5632
QtCanvasItem::draw
virtual void draw(QPainter &)=0
QtCanvas::validChunk
bool validChunk(int x, int y) const
Definition: qtcanvas.h:358
QtCanvasRectangle
Definition: qtcanvas.h:767
QtCanvasPolygon::setPoints
void setPoints(QPolygon)
Definition: qtcanvas.cpp:4496
QtCanvasView::contentsMouseDoubleClickEvent
virtual void contentsMouseDoubleClickEvent(QMouseEvent *)
Definition: qtcanvas.cpp:3758
QtCanvasItem::QtCanvasEllipse
friend class QtCanvasEllipse
Definition: qtcanvas.h:239
QtCanvasView::contentsDragMoveEvent
virtual void contentsDragMoveEvent(QDragMoveEvent *)
Definition: qtcanvas.cpp:3775
QtCanvasClusterizer::add
void add(int x, int y)
Definition: qtcanvas.cpp:155
QtCanvasItem
Definition: qtcanvas.h:67
QtCanvasItem::RTTI
static int RTTI
Definition: qtcanvas.h:214
QtCanvasItem::setVelocity
virtual void setVelocity(double vx, double vy)
Definition: qtcanvas.cpp:2053
QtCanvasWidget::m_view
QtCanvasView * m_view
Definition: qtcanvas.cpp:3665
QtCanvasEllipse::rtti
int rtti() const
Definition: qtcanvas.cpp:5531
QtCanvasSprite::leftEdge
int leftEdge() const
Definition: qtcanvas.cpp:3283
QtCanvasChunk::list
const QtCanvasItemList & list() const
Definition: qtcanvas.cpp:373
QtCanvasPolygonalItem::areaPoints
virtual QPolygon areaPoints() const =0
EdgeTable::ymax
int ymax
Definition: qtcanvas.cpp:6040
QtCanvasSprite::frame
int frame() const
Definition: qtcanvas.h:630
QtCanvasItem::yVelocity
double yVelocity() const
Definition: qtcanvas.cpp:2080
QtCanvasView::sizeHint
virtual QSize sizeHint() const
Definition: qtcanvas.cpp:3934
ScanLineList
struct _ScanLineList ScanLineList
QtCanvasView::highQualityRendering
bool highQualityRendering
Definition: qtcanvas.h:467
QtCanvasView::contentsMousePressEvent
virtual void contentsMousePressEvent(QMouseEvent *)
Definition: qtcanvas.cpp:3746
QtCanvasView::contentsMouseReleaseEvent
virtual void contentsMouseReleaseEvent(QMouseEvent *)
Definition: qtcanvas.cpp:3752
QtCanvasRectangle::drawShape
void drawShape(QPainter &)
Definition: qtcanvas.cpp:4963
_EdgeTableEntry::next
struct _EdgeTableEntry * next
Definition: qtcanvas.cpp:6025
QtCanvasItem::y
double y() const
Definition: qtcanvas.h:80
QtCanvas::setChangedChunk
virtual void setChangedChunk(int i, int j)
Definition: qtcanvas.cpp:1398
QtCanvasSpline::controlPoints
QPolygon controlPoints() const
Definition: qtcanvas.cpp:4607
QtCanvasItem::advance
virtual void advance(int stage)
Definition: qtcanvas.cpp:2097
QtCanvasEllipse::setAngles
void setAngles(int start, int length)
Definition: qtcanvas.cpp:5107
QtCanvasItemLess
Definition: qtcanvas.cpp:341
QtCanvasPixmapArray
Definition: qtcanvas.h:563
QtCanvas::setUnchanged
virtual void setUnchanged(const QRect &area)
Definition: qtcanvas.cpp:1200
QtCanvas::setBackgroundColor
virtual void setBackgroundColor(const QColor &c)
Definition: qtcanvas.cpp:1514
filename
std::string filename
Definition: VisualizationRobot.cpp:86
QtCanvasPolygonalItem::boundingRect
QRect boundingRect() const
Definition: qtcanvas.cpp:4363
QtCanvasItem::canvas
QtCanvas * canvas() const
Definition: qtcanvas.h:220
QtCanvasEllipse::setSize
void setSize(int w, int h)
Definition: qtcanvas.cpp:5067
QtCanvasView::inverseWorldMatrix
const QMatrix & inverseWorldMatrix() const
Definition: qtcanvas.cpp:3861
QtCanvasSprite::setFrameAnimation
virtual void setFrameAnimation(FrameAnimationType=Cycle, int step=1, int state=0)
Definition: qtcanvas.cpp:5677
QtCanvasText::setText
void setText(const QString &)
Definition: qtcanvas.cpp:5266
QtCanvasChunk::sort
void sort()
Definition: qtcanvas.cpp:367
QtCanvas::tilesHorizontally
int tilesHorizontally() const
Definition: qtcanvas.h:296
QtCanvasItem::show
void show()
Definition: qtcanvas.cpp:2155
ScanLineListBlock
struct _ScanLineListBlock ScanLineListBlock
_EdgeTableEntry::bres
BRESINFO bres
Definition: qtcanvas.cpp:6024
QtCanvasItem::QtCanvasSprite
friend class QtCanvasSprite
Definition: qtcanvas.h:236
QtCanvasRectangle::RTTI
static int RTTI
Definition: qtcanvas.h:797
QPolygonalProcessor::bitmap
QImage bitmap
Definition: qtcanvas.cpp:4327
BRESINFO::minor
int minor
Definition: qtcanvas.cpp:6009
QtCanvasPolygonalItem::draw
void draw(QPainter &)
Definition: qtcanvas.cpp:4374
_EdgeTableEntry::back
struct _EdgeTableEntry * back
Definition: qtcanvas.cpp:6026
QtCanvasPolygonalItem::pen
QPen pen() const
Definition: qtcanvas.h:719
QtCanvasItemList
QList< QtCanvasItem * > QtCanvasItemList
Definition: qtcanvas.h:62
QtCanvasSpline::closed
bool closed() const
Definition: qtcanvas.cpp:4617
EdgeTableEntry
struct _EdgeTableEntry EdgeTableEntry
armarx::armem::server::ltm::util::mongodb::detail::update
bool update(mongocxx::collection &coll, const nlohmann::json &query, const nlohmann::json &update)
Definition: mongodb.cpp:68
QtCanvasText::RTTI
static int RTTI
Definition: qtcanvas.h:965
QtCanvas::drawForeground
virtual void drawForeground(QPainter &, const QRect &area)
Definition: qtcanvas.cpp:1633
QtCanvasRectangle::~QtCanvasRectangle
~QtCanvasRectangle()
Definition: qtcanvas.cpp:4880
armarx::red
QColor red()
Definition: StyleSheets.h:78
EdgeTable
Definition: qtcanvas.cpp:6038
QtCanvasPolygonalItem::areaPointsAdvanced
virtual QPolygon areaPointsAdvanced() const
Definition: qtcanvas.cpp:4105
QtCanvasLine::~QtCanvasLine
~QtCanvasLine()
Definition: qtcanvas.cpp:4704
QtCanvasChunk::remove
void remove(QtCanvasItem *item)
Definition: qtcanvas.cpp:386
QtCanvasEllipse::RTTI
static int RTTI
Definition: qtcanvas.h:916
QtCanvasWidget::mouseMoveEvent
void mouseMoveEvent(QMouseEvent *e)
Definition: qtcanvas.cpp:3612
QtCanvasWidget::wheelEvent
void wheelEvent(QWheelEvent *e)
Definition: qtcanvas.cpp:3654
QtCanvasSprite::imageAdvanced
virtual QtCanvasPixmap * imageAdvanced() const
Definition: qtcanvas.cpp:3407
NUMPTSTOBUFFER
#define NUMPTSTOBUFFER
Definition: qtcanvas.cpp:6062
QtCanvasItem::rtti
virtual int rtti() const
Definition: qtcanvas.cpp:5453
QtCanvasPolygonalItem::invalidate
void invalidate()
Definition: qtcanvas.cpp:4084
QtPolygonScanner::Left
@ Left
Definition: qtcanvas.cpp:5805
QPolygonalProcessor::add
void add(int x, int y)
Definition: qtcanvas.cpp:4147
QtCanvas::~QtCanvas
virtual ~QtCanvas()
Definition: qtcanvas.cpp:663
QtCanvasItemLess::operator()
bool operator()(const QtCanvasItem *i1, const QtCanvasItem *i2) const
Definition: qtcanvas.cpp:345
QtCanvas
Definition: qtcanvas.h:270
QtCanvasSpline::QtCanvasSpline
QtCanvasSpline(QtCanvas *canvas)
Definition: qtcanvas.cpp:4562
QtCanvasItem::z
double z() const
Definition: qtcanvas.h:86
QtCanvasText::font
QFont font() const
Definition: qtcanvas.cpp:5283
QtCanvas::backgroundPixmap
QPixmap backgroundPixmap() const
Definition: qtcanvas.cpp:1540
armarx::ctrlutil::v
double v(double t, double v0, double a0, double j)
Definition: CtrlUtil.h:39
QtCanvasView::contentsDropEvent
virtual void contentsDropEvent(QDropEvent *)
Definition: qtcanvas.cpp:3785
QtCanvasPolygonalItem::setBrush
virtual void setBrush(QBrush b)
Definition: qtcanvas.cpp:4430
QtCanvasData::animDict
QSet< QtCanvasItem * > animDict
Definition: qtcanvas.cpp:67
QtCanvasItem::animated
bool animated() const
Definition: qtcanvas.cpp:2000
QtCanvasItem::setAnimated
virtual void setAnimated(bool y)
Definition: qtcanvas.cpp:2013
BRESINITPGONSTRUCT
#define BRESINITPGONSTRUCT(dmaj, min1, min2, bres)
Definition: qtcanvas.cpp:6015
QtCanvasWidget::mouseReleaseEvent
void mouseReleaseEvent(QMouseEvent *e)
Definition: qtcanvas.cpp:3618
QtCanvasRectangle::areaPoints
QPolygon areaPoints() const
Definition: qtcanvas.cpp:4937
QtCanvasView::contentsWheelEvent
virtual void contentsWheelEvent(QWheelEvent *)
Definition: qtcanvas.cpp:3790
QtCanvas::addItem
virtual void addItem(QtCanvasItem *)
Definition: qtcanvas.cpp:922
QtCanvasSprite::collidesWith
bool collidesWith(const QtCanvasItem *) const
Definition: qtcanvas.cpp:2556
QtCanvasSprite::setFrame
void setFrame(int)
Definition: qtcanvas.cpp:5646
QtCanvas::drawCanvasArea
void drawCanvasArea(const QRect &, QPainter *p=0, bool double_buffer=true)
Definition: qtcanvas.cpp:1308
QtCanvasPixmap::QtCanvasPixmap
QtCanvasPixmap(const QString &datafilename)
Definition: qtcanvas.cpp:2901
QtCanvasItem::QtCanvasRectangle
friend class QtCanvasRectangle
Definition: qtcanvas.h:237
SLLSPERBLOCK
#define SLLSPERBLOCK
Definition: qtcanvas.cpp:6050
QtCanvasClusterizer::operator[]
const QRect & operator[](int i) const
Definition: qtcanvas.cpp:333
QtCanvas::addItemToChunkContaining
void addItemToChunkContaining(QtCanvasItem *, int x, int y)
Definition: qtcanvas.cpp:1467
_ScanLineListBlock
Definition: qtcanvas.cpp:6052
QtCanvasSprite::frameCount
int frameCount() const
Definition: qtcanvas.h:636
QtCanvasEllipse::drawShape
void drawShape(QPainter &)
Definition: qtcanvas.cpp:5137
QtCanvasWidget
Definition: qtcanvas.cpp:3594
QtCanvasClusterizer
Definition: qtcanvas.cpp:84
QtCanvasLine::drawShape
void drawShape(QPainter &)
Definition: qtcanvas.cpp:4756
QtCanvasItem::setVisible
virtual void setVisible(bool yes)
Definition: qtcanvas.cpp:2173
EVALUATEEDGEWINDING
#define EVALUATEEDGEWINDING(pAET, pPrevAET, y, fixWAET)
Definition: qtcanvas.cpp:6077
QtCanvasSprite::boundingRect
QRect boundingRect() const
Definition: qtcanvas.cpp:3418
angle
double angle(const Point &a, const Point &b, const Point &c)
Definition: point.hpp:109
QtCanvasData::itemDict
QSet< QtCanvasItem * > itemDict
Definition: qtcanvas.cpp:66
QtCanvasPixmapArray::readPixmaps
bool readPixmaps(const QString &datafilenamepattern, int framecount=0)
Definition: qtcanvas.cpp:3118
QtCanvasSprite::topEdge
int topEdge() const
Definition: qtcanvas.cpp:3311
_ScanLineList
Definition: qtcanvas.cpp:6031
QtCanvasPixmapArray::isValid
bool isValid() const
Definition: qtcanvas.cpp:3228
QtCanvas::setUpdatePeriod
virtual void setUpdatePeriod(int ms)
Definition: qtcanvas.cpp:1028
QtCanvasItem::setSelected
virtual void setSelected(bool yes)
Definition: qtcanvas.cpp:2234
_ScanLineList::scanline
int scanline
Definition: qtcanvas.cpp:6033
QtCanvasSprite::rtti
int rtti() const
Definition: qtcanvas.cpp:5466
QtCanvas::tile
int tile(int x, int y) const
Definition: qtcanvas.h:290
QtCanvasSprite::image
QtCanvasPixmap * image() const
Definition: qtcanvas.h:665
QtCanvasView
Definition: qtcanvas.h:464
QtCanvas::setAllChanged
virtual void setAllChanged()
Definition: qtcanvas.cpp:1151
QtCanvasLine::setPen
void setPen(QPen p)
Definition: qtcanvas.cpp:4713
QtCanvasView::worldMatrix
const QMatrix & worldMatrix() const
Definition: qtcanvas.cpp:3849
QtCanvasItem::xVelocity
double xVelocity() const
Definition: qtcanvas.cpp:2071
QtCanvasPolygon::rtti
int rtti() const
Definition: qtcanvas.cpp:5505
QtCanvas::addAnimation
virtual void addAnimation(QtCanvasItem *)
Definition: qtcanvas.cpp:933
QtCanvasEllipse
Definition: qtcanvas.h:884
QtCanvasView::QtCanvasWidget
friend class QtCanvasWidget
Definition: qtcanvas.h:492
QPolygonalProcessor::result
QPolygon result
Definition: qtcanvas.cpp:4324
QtPolygonScanner::Bottom
@ Bottom
Definition: qtcanvas.cpp:5808
QtCanvasPolygonScanner::processSpans
void processSpans(int n, QPoint *point, int *width)
Definition: qtcanvas.cpp:6800
QtCanvasWidget::dragLeaveEvent
void dragLeaveEvent(QDragLeaveEvent *e)
Definition: qtcanvas.cpp:3642
QtCanvasView::canvas
QtCanvas * canvas() const
Definition: qtcanvas.h:474
QtCanvasPolygonalItem::collidesWith
bool collidesWith(const QtCanvasItem *) const
Definition: qtcanvas.cpp:2581
QtCanvasPolygonalItem::rtti
int rtti() const
Definition: qtcanvas.cpp:5479
QtCanvasItem::~QtCanvasItem
virtual ~QtCanvasItem()
Definition: qtcanvas.cpp:1899
QtCanvasEllipse::height
int height() const
Definition: qtcanvas.cpp:5058
QtPolygonScanner::Edge
Edge
Definition: qtcanvas.cpp:5803
QtCanvasText::setTextFlags
void setTextFlags(int)
Definition: qtcanvas.cpp:5238
QtCanvasPolygonalItem::winding
bool winding() const
Definition: qtcanvas.cpp:4056
QtCanvas::removeView
virtual void removeView(QtCanvasView *)
Definition: qtcanvas.cpp:985
QtCanvasText::moveBy
void moveBy(double dx, double dy)
Definition: qtcanvas.cpp:5332
QtCanvasRectangle::chunks
QPolygon chunks() const
Definition: qtcanvas.cpp:4352
QtCanvasSprite
Definition: qtcanvas.h:608
QtCanvasText
Definition: qtcanvas.h:934
QtCanvasPolygon::areaPoints
QPolygon areaPoints() const
Definition: qtcanvas.cpp:4672
QtCanvasWidget::dropEvent
void dropEvent(QDropEvent *e)
Definition: qtcanvas.cpp:3648
QPolygonalProcessor::doSpans
void doSpans(int n, QPoint *pt, int *w)
Definition: qtcanvas.cpp:4196
QtCanvasItem::move
void move(double x, double y)
Definition: qtcanvas.cpp:1988
QtCanvasPolygon::points
QPolygon points() const
Definition: qtcanvas.cpp:4658
armarx::ctrlutil::s
double s(double t, double s0, double v0, double a0, double j)
Definition: CtrlUtil.h:33
QtCanvasItem::collisions
QtCanvasItemList collisions(bool exact) const
Definition: qtcanvas.cpp:2692
QtCanvasWidget::dragEnterEvent
void dragEnterEvent(QDragEnterEvent *e)
Definition: qtcanvas.cpp:3630
QtCanvasText::draw
virtual void draw(QPainter &)
Definition: qtcanvas.cpp:5356
QtCanvasView::QtCanvasView
QtCanvasView(QWidget *parent=0)
Definition: qtcanvas.cpp:3687
QtCanvas::tilesVertically
int tilesVertically() const
Definition: qtcanvas.h:302
QtCanvasData::QtCanvasData
QtCanvasData()
Definition: qtcanvas.cpp:61
QtCanvasPolygonScanner::QtCanvasPolygonScanner
QtCanvasPolygonScanner(QPolygonalProcessor &p)
Definition: qtcanvas.cpp:6795
QtCanvasText::~QtCanvasText
virtual ~QtCanvasText()
Definition: qtcanvas.cpp:5201
QtCanvasPixmap::~QtCanvasPixmap
~QtCanvasPixmap()
Definition: qtcanvas.cpp:2963
QtCanvasPolygon::drawShape
void drawShape(QPainter &)
Definition: qtcanvas.cpp:4481
armarx
This file offers overloads of toIce() and fromIce() functions for STL container types.
Definition: ArmarXTimeserver.cpp:27
EVALUATEEDGEEVENODD
#define EVALUATEEDGEEVENODD(pAET, pPrevAET, y)
Definition: qtcanvas.cpp:6103
QtCanvasClusterizer::clusters
int clusters() const
Definition: qtcanvas.cpp:97
QtPolygonScanner::scan
void scan(const QPolygon &pa, bool winding, int index=0, int npoints=-1)
Definition: qtcanvas.cpp:6561
QtCanvasSprite::draw
void draw(QPainter &painter)
Definition: qtcanvas.cpp:3530
QtCanvas::retune
virtual void retune(int chunksize, int maxclusters=100)
Definition: qtcanvas.cpp:800
cxxopts::minor
uint8_t minor
Definition: cxxopts.hpp:54
QtCanvas::setAdvancePeriod
virtual void setAdvancePeriod(int ms)
Definition: qtcanvas.cpp:998
QtCanvasView::~QtCanvasView
~QtCanvasView()
Definition: qtcanvas.cpp:3714
QtPolygonScanner::~QtPolygonScanner
virtual ~QtPolygonScanner()
Definition: qtcanvas.cpp:5796
armarx::green
QColor green()
Definition: StyleSheets.h:72
EdgeTable::scanlines
ScanLineList scanlines
Definition: qtcanvas.cpp:6042
QtCanvasItem::QtCanvasPolygon
friend class QtCanvasPolygon
Definition: qtcanvas.h:238
QtCanvasPixmapArray::QtCanvasPixmapArray
QtCanvasPixmapArray()
Definition: qtcanvas.cpp:3021
BRESINFO
Definition: qtcanvas.cpp:6007
QtCanvasSprite::bottomEdge
int bottomEdge() const
Definition: qtcanvas.cpp:3367
QtCanvasPolygon::RTTI
static int RTTI
Definition: qtcanvas.h:825
MININT
#define MININT
Definition: qtcanvas.cpp:6169
QtCanvasSprite::setSequence
void setSequence(QtCanvasPixmapArray *seq)
Definition: qtcanvas.cpp:5584