KDEGames

kgamecanvas.cpp
1 /* Originally created for KBoard
2  Copyright 2006 Maurizio Monge <[email protected]>
3 
4 BSD License
5 Redistribution and use in source and binary forms, with or without
6 modification, are permitted provided that the following conditions
7 are met:
8 
9 1. Redistributions of source code must retain the above copyright
10  notice, this list of conditions and the following disclaimer.
11 2. Redistributions in binary form must reproduce the above copyright
12  notice, this list of conditions and the following disclaimer in the
13  documentation and/or other materials provided with the distribution.
14 
15 THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16 IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17 OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18 IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
19 INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20 NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24 THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25  */
26 
27 // KGame namespace changes: [email protected]
28 
29 #include "kgamecanvas.h"
30 
31 #include <QPaintEvent>
32 #include <QApplication>
33 #include <QTimer>
34 #include <QTime>
35 #include <QElapsedTimer>
36 
37 /*
38  TODO:
39  - (maybe) allow an item to be destroyed while calling KGameCanvasItem::advance.
40  - When a group is hidden/destroyed should only update items (optimize for sparse groups)
41 */
42 
43 #define DEBUG_DONT_MERGE_UPDATES 0
44 #define DEBUG_CANVAS_PAINTS 0
45 
46 /*
47  KGameCanvasAbstract
48 */
50 
51 }
52 
53 KGameCanvasAbstract::~KGameCanvasAbstract() {
54  //Note: this does not delete the items, be sure not to leak memory!
55  for(int i=0;i<m_items.size();i++)
56  m_items[i]->m_canvas = nullptr;
57 }
58 
60  for(int i=m_items.size()-1;i>=0;i--) {
61  KGameCanvasItem *el = m_items[i];
62  if(el->m_visible && el->rect().contains(pt))
63  return el;
64  }
65  return nullptr;
66 }
67 
70 
71  for(int i=m_items.size()-1;i>=0;i--) {
72  KGameCanvasItem *el = m_items[i];
73  if(el->m_visible && el->rect().contains(pt))
74  retv.append(el);
75  }
76 
77  return retv;
78 }
79 
80 
81 /*
82  KGameCanvasWidget
83 */
84 class KGameCanvasWidgetPrivate {
85 public:
86  QTimer m_anim_timer;
87  QElapsedTimer m_anim_time;
88  bool m_pending_update;
89  QRegion m_pending_update_reg;
90 
91 #if DEBUG_CANVAS_PAINTS
92  bool debug_paints;
93 #endif //DEBUG_CANVAS_PAINTS
94 
95  KGameCanvasWidgetPrivate()
96  : m_pending_update(false)
97 #if DEBUG_CANVAS_PAINTS
98  , debug_paints(false)
99 #endif //DEBUG_CANVAS_PAINTS
100  {}
101 };
102 
104 : QWidget(parent)
105 , priv(new KGameCanvasWidgetPrivate()) {
106  priv->m_anim_time.start();
107  connect(&priv->m_anim_timer, &QTimer::timeout, this, &KGameCanvasWidget::processAnimations);
108 }
109 
110 KGameCanvasWidget::~KGameCanvasWidget() {
111  delete priv;
112 }
113 
114 void KGameCanvasWidget::ensureAnimating() {
115  if(!priv->m_anim_timer.isActive() )
116  priv->m_anim_timer.start();
117 }
118 
119 void KGameCanvasWidget::ensurePendingUpdate() {
120  if(priv->m_pending_update)
121  return;
122  priv->m_pending_update = true;
123 
124 #if DEBUG_DONT_MERGE_UPDATES
125  updateChanges();
126 #else //DEBUG_DONT_MERGE_UPDATES
127  QTimer::singleShot( 0, this, &KGameCanvasWidget::updateChanges );
128 #endif //DEBUG_DONT_MERGE_UPDATES
129 }
130 
131 void KGameCanvasWidget::updateChanges() {
132  for(int i=0;i<m_items.size();i++) {
133  KGameCanvasItem *el = m_items.at(i);
134 
135  if(el->m_changed)
136  el->updateChanges();
137  }
138  priv->m_pending_update = false;
139 
140 #if DEBUG_CANVAS_PAINTS
141  repaint();
142  priv->debug_paints = true;
143  repaint( priv->m_pending_update_reg );
144  QApplication::syncX();
145  priv->debug_paints = false;
146  usleep(100000);
147  repaint( priv->m_pending_update_reg );
148  QApplication::syncX();
149  usleep(100000);
150 #else //DEBUG_CANVAS_PAINTS
151  repaint( priv->m_pending_update_reg );
152 #endif //DEBUG_CANVAS_PAINTS
153 
154  priv->m_pending_update_reg = QRegion();
155 }
156 
157 void KGameCanvasWidget::invalidate(const QRect& r, bool /*translate*/) {
158  priv->m_pending_update_reg |= r;
159  ensurePendingUpdate();
160 }
161 
162 void KGameCanvasWidget::invalidate(const QRegion& r, bool /*translate*/) {
163  priv->m_pending_update_reg |= r;
164  ensurePendingUpdate();
165 }
166 
167 void KGameCanvasWidget::paintEvent(QPaintEvent *event) {
168 #if DEBUG_CANVAS_PAINTS
169  if(priv->debug_paints)
170  {
171  QPainter p(this);
172  p.fillRect(event->rect(), Qt::magenta);
173  return;
174  }
175 #endif //DEBUG_CANVAS_PAINTS
176 
177  {QPainter p(this);
178  QRect evr = event->rect();
179  QRegion evreg = event->region();
180 
181  for(int i=0;i<m_items.size();i++) {
182  KGameCanvasItem *el = m_items.at(i);
183  if( el->m_visible && evr.intersects( el->rect() )
184  && evreg.contains( el->rect() ) ) {
185  el->m_last_rect = el->rect();
186  el->paintInternal(&p, evr, evreg, QPoint(), 1.0 );
187  }
188  }}
189 }
190 
191 void KGameCanvasWidget::processAnimations() {
192  if(m_animated_items.empty() ) {
193  priv->m_anim_timer.stop();
194  return;
195  }
196 
197  int tm = priv->m_anim_time.elapsed();
198 
199  // The list MUST be copied, because it could be modified calling advance.
200  // After all since it is implicitly shared the copy will not happen unless
201  // is it actually modified
202  QList<KGameCanvasItem*> ait = m_animated_items;
203  for(int i=0;i<ait.size();i++) {
204  KGameCanvasItem *el = ait[i];
205  el->advance(tm);
206  }
207 
208  if(m_animated_items.empty() )
209  priv->m_anim_timer.stop();
210 }
211 
213  priv->m_anim_timer.setInterval(d);
214 }
215 
217  return priv->m_anim_time.elapsed();
218 }
219 
221  return this;
222 }
223 
225  return QPoint(0, 0);
226 }
227 
228 /*
229  KGameCanvasItem
230 */
232 : m_visible(false)
233 , m_animated(false)
234 , m_opacity(255)
235 , m_pos(0,0)
236 , m_canvas(KGameCanvas)
237 , m_changed(false) {
238  if(m_canvas) m_canvas->m_items.append(this);
239 }
240 
241 KGameCanvasItem::~KGameCanvasItem() {
242  if(m_canvas) {
243  m_canvas->m_items.removeAll(this);
244  if(m_animated)
245  m_canvas->m_animated_items.removeAll(this);
246  if(m_visible)
247  m_canvas->invalidate(m_last_rect, false);
248  }
249 }
250 
252  m_changed = true;
253 
254  //even if m_changed was already true we cannot optimize away this call, because maybe the
255  //item has been reparented, etc. It is a very quick call anyway.
256  if(m_canvas)
257  m_canvas->ensurePendingUpdate();
258 }
259 
260 void KGameCanvasItem::updateChanges() {
261  if(!m_changed)
262  return;
263  if(m_canvas) {
264  m_canvas->invalidate(m_last_rect, false);
265  if(m_visible)
266  m_canvas->invalidate(rect());
267  }
268  m_changed = false;
269 }
270 
271 QPixmap *KGameCanvasItem::transparence_pixmap_cache = nullptr;
272 
273 QPixmap* KGameCanvasItem::getTransparenceCache(const QSize &s) {
274  if(!transparence_pixmap_cache)
275  transparence_pixmap_cache = new QPixmap();
276  if(s.width()>transparence_pixmap_cache->width() ||
277  s.height()>transparence_pixmap_cache->height()) {
278 
279  /* Strange that a pixmap with alpha should be created this way, i think a qt bug */
280  *transparence_pixmap_cache = QPixmap::fromImage( QImage(
281  s.expandedTo(transparence_pixmap_cache->size()), QImage::Format_ARGB32 ) );
282  }
283 
284  return transparence_pixmap_cache;
285 }
286 
287 void KGameCanvasItem::paintInternal(QPainter* pp, const QRect& /*prect*/,
288  const QRegion& /*preg*/, const QPoint& /*delta*/, double cumulative_opacity) {
289  int opacity = int(cumulative_opacity*m_opacity + 0.5);
290 
291  if(opacity <= 0)
292  return;
293 
294  if(opacity >= 255) {
295  paint(pp);
296  return;
297  }
298 
299  if(!layered()) {
300  pp->setOpacity(opacity/255.0);
301  paint(pp);
302  pp->setOpacity(1.0);
303  return;
304  }
305 
306  QRect mr = rect();
307  QPixmap* cache = getTransparenceCache(mr.size());
308 
309  {
310  QPainter p(cache);
311 
312  /* clear */
313  p.setBrush(QColor(255,255,255,0));
314  p.setPen(Qt::NoPen);
316  p.drawRect(QRect(QPoint(),mr.size()));
317 
318  /* paint on the item */
319  p.translate(-mr.topLeft());
320  paint(&p);
321  p.translate(mr.topLeft());
322 
323  /* make the opacity */
324  p.setBrush( QColor(255,255,255,255-opacity) );
325  p.setPen( Qt::NoPen );
327  p.drawRect( QRect(QPoint(),mr.size()) );
328  }
329 
330  pp->drawPixmap(mr.topLeft(), *cache, QRect(QPoint(),mr.size()) );
331 }
332 
334  if(m_canvas == c)
335  return;
336 
337  if(m_canvas) {
338  if(m_visible)
339  m_canvas->invalidate(m_last_rect, false); //invalidate the previously drawn rectangle
340  m_canvas->m_items.removeAll(this);
341  if(m_animated)
342  m_canvas->m_animated_items.removeAll(this);
343  }
344 
345  m_canvas = c;
346 
347  if(m_canvas) {
348  m_canvas->m_items.append(this);
349  if(m_animated) {
350  m_canvas->m_animated_items.append(this);
351  m_canvas->ensureAnimating();
352  }
353  if(m_visible)
354  changed();
355  }
356 }
357 
359  if(m_visible == v)
360  return;
361 
362  m_visible = v;
363  if(m_canvas) {
364  if(!v)
365  m_canvas->invalidate(m_last_rect, false);
366  else
367  changed();
368  }
369  if(!v)
370  m_last_rect = QRect();
371 }
372 
374  if(m_animated == a)
375  return;
376 
377  m_animated = a;
378  if(m_canvas) {
379  if(a) {
380  m_canvas->m_animated_items.append(this);
381  m_canvas->ensureAnimating();
382  }
383  else
384  m_canvas->m_animated_items.removeAll(this);
385  }
386 }
387 
389  if (o<0) o=0;
390  if (o>255) o = 255;
391  m_opacity = o;
392 
393  if(m_canvas && m_visible)
394  changed();
395 }
396 
397 bool KGameCanvasItem::layered() const { return true; }
398 
399 void KGameCanvasItem::advance(int /*msecs*/) { }
400 
401 void KGameCanvasItem::updateAfterRestack(int from, int to)
402 {
403  int inc = from>to ? -1 : 1;
404 
405  QRegion upd;
406  for(int i=from; i!=to;i+=inc)
407  {
408  KGameCanvasItem *el = m_canvas->m_items.at(i);
409  if(!el->m_visible)
410  continue;
411 
412  QRect r = el->rect() & rect();
413  if(!r.isEmpty())
414  upd |= r;
415  }
416 
417  if(!upd.isEmpty())
418  m_canvas->invalidate(upd);
419 }
420 
422 {
423  if(!m_canvas || m_canvas->m_items.last() == this)
424  return;
425 
426  int old_pos = m_canvas->m_items.indexOf(this);
427  m_canvas->m_items.removeAt(old_pos);
428  m_canvas->m_items.append(this);
429  if(m_visible)
430  updateAfterRestack(old_pos, m_canvas->m_items.size()-1);
431 }
432 
434 {
435  if(!m_canvas || m_canvas->m_items.first() == this)
436  return;
437 
438  int old_pos = m_canvas->m_items.indexOf(this);
439  m_canvas->m_items.removeAt(old_pos);
440  m_canvas->m_items.prepend(this);
441 
442  if(m_visible)
443  updateAfterRestack(old_pos, 0);
444 }
445 
447 {
448  if(!m_canvas)
449  return;
450 
451  if(ref->m_canvas != m_canvas)
452  {
453  qCritical("KGameCanvasItem::stackOver: Argument must be a sibling item!\n");
454  return;
455  }
456 
457  int i = m_canvas->m_items.indexOf( ref );
458  if(i < m_canvas->m_items.size()-2 && m_canvas->m_items[i+1] == this)
459  return;
460 
461  int old_pos = m_canvas->m_items.indexOf(this);
462  m_canvas->m_items.removeAt(old_pos);
463  i = m_canvas->m_items.indexOf(ref);
464  m_canvas->m_items.insert(i+1,this);
465 
466  if(m_visible)
467  updateAfterRestack(old_pos, i+1);
468 }
469 
471 {
472  if(!m_canvas)
473  return;
474 
475 
476  if(ref->m_canvas != m_canvas)
477  {
478  qCritical("KGameCanvasItem::stackUnder: Argument must be a sibling item!\n");
479  return;
480  }
481 
482  int i = m_canvas->m_items.indexOf( ref );
483  if(i >= 1 && m_canvas->m_items[i-1] == this)
484  return;
485 
486  int old_pos = m_canvas->m_items.indexOf(this);
487  m_canvas->m_items.removeAt(old_pos);
488  i = m_canvas->m_items.indexOf(ref);
489  m_canvas->m_items.insert(i,this);
490 
491  if(m_visible)
492  updateAfterRestack(old_pos, i);
493 }
494 
495 void KGameCanvasItem::moveTo(const QPoint &newpos)
496 {
497  if(m_pos == newpos)
498  return;
499  m_pos = newpos;
500  if(m_visible && m_canvas)
501  changed();
502 }
503 
505 {
506  if (m_canvas) {
507  return m_canvas->canvasPosition() + m_pos;
508  }
509  else {
510  return m_pos;
511  }
512 }
513 
514 /*
515  KGameCanvasGroup
516 */
518 : KGameCanvasItem(KGameCanvas)
520 , m_child_rect_changed(true) {
521 
522 }
523 
524 KGameCanvasGroup::~KGameCanvasGroup() {
525 
526 }
527 
528 void KGameCanvasGroup::ensureAnimating() {
529  setAnimated(true);
530 }
531 
532 void KGameCanvasGroup::ensurePendingUpdate() {
533  if(!m_changed || !m_child_rect_changed) {
534  m_child_rect_changed = true;
536  }
537 }
538 
539 void KGameCanvasGroup::updateChanges() {
540  if(!m_changed)
541  return;
542  for(int i=0;i<m_items.size();i++) {
543  KGameCanvasItem *el = m_items.at(i);
544 
545  if(el->m_changed)
546  el->updateChanges();
547  }
548  m_changed = false;
549 }
550 
551 void KGameCanvasGroup::changed() {
552  if(!m_changed) {
554 
555  for(int i=0;i<m_items.size();i++)
556  m_items[i]->changed();
557  }
558 }
559 
560 void KGameCanvasGroup::invalidate(const QRect& r, bool translate) {
561  if(m_canvas)
562  m_canvas->invalidate(translate ? r.translated(m_pos) : r, translate);
563  if(!m_changed)
564  ensurePendingUpdate();
565 }
566 
567 void KGameCanvasGroup::invalidate(const QRegion& r, bool translate) {
568  if(m_canvas)
569  m_canvas->invalidate(translate ? r.translated(m_pos) : r, translate);
570  if(!m_changed)
571  ensurePendingUpdate();
572 }
573 
574 void KGameCanvasGroup::advance(int msecs) {
575 
576  // The list MUST be copied, because it could be modified calling advance.
577  // After all since it is implicitly shared the copy will not happen unless
578  // is it actually modified
579  QList<KGameCanvasItem*> ait = m_animated_items;
580  for(int i=0;i<ait.size();i++)
581  {
582  KGameCanvasItem *el = ait[i];
583  el->advance(msecs);
584  }
585 
586  if(m_animated_items.empty())
587  setAnimated(false);
588 }
589 
590 void KGameCanvasGroup::paintInternal(QPainter* p, const QRect& prect,
591  const QRegion& preg, const QPoint& delta, double cumulative_opacity) {
592  cumulative_opacity *= (m_opacity/255.0);
593 
594  QPoint adelta = delta;
595  adelta += m_pos;
596  p->translate(m_pos);
597 
598  for(int i=0;i<m_items.size();i++) {
599  KGameCanvasItem *el = m_items.at(i);
600  QRect r = el->rect().translated(adelta);
601 
602  if( el->m_visible && prect.intersects( r ) && preg.contains( r ) ) {
603  el->m_last_rect = r;
604  el->paintInternal(p,prect,preg,adelta,cumulative_opacity);
605  }
606  }
607 
608  p->translate(-m_pos);
609 }
610 
612  Q_ASSERT(!"This function should never be called");
613 }
614 
616 {
617  if(!m_child_rect_changed)
618  return m_last_child_rect.translated(m_pos);
619 
620  m_child_rect_changed = false;
621  m_last_child_rect = QRect();
622  for(int i=0;i<m_items.size();i++)
623  {
624  KGameCanvasItem *el = m_items[i];
625  if(el->m_visible)
626  m_last_child_rect |= el->rect();
627  }
628 
629  return m_last_child_rect.translated(m_pos);
630 }
631 
633 {
634  return m_canvas ? m_canvas->topLevelCanvas() : nullptr;
635 }
636 
639 }
640 
641 /*
642  KGameCanvasDummy
643 */
645  : KGameCanvasItem(KGameCanvas)
646 {
647 
648 }
649 
650 KGameCanvasDummy::~KGameCanvasDummy()
651 {
652 
653 }
654 
656 }
657 
659 {
660  return QRect();
661 }
662 
663 
664 /*
665  KGameCanvasPixmap
666 */
668  : KGameCanvasItem(KGameCanvas), m_pixmap(p) {
669 
670 }
671 
673  : KGameCanvasItem(KGameCanvas) {
674 
675 }
676 
677 KGameCanvasPixmap::~KGameCanvasPixmap() {
678 
679 }
680 
682  m_pixmap = p;
683  if(visible() && canvas() )
684  changed();
685 }
686 
688  p->drawPixmap(pos(), m_pixmap);
689 }
690 
692  return QRect(pos(), m_pixmap.size());
693 }
694 
695 KGameCanvasRenderedPixmap::KGameCanvasRenderedPixmap(KGameRenderer* renderer, const QString& spriteKey, KGameCanvasAbstract* canvas)
696  : KGameCanvasPixmap(canvas)
697  , KGameRendererClient(renderer, spriteKey)
698 {
699 }
700 
702 {
704 }
705 
706 /*
707  KGameCanvasTiledPixmap
708 */
710  bool move_orig, KGameCanvasAbstract* KGameCanvas)
711  : KGameCanvasItem(KGameCanvas)
712  , m_pixmap(pixmap)
713  , m_size(size)
714  , m_origin(origin)
715  , m_move_orig(move_orig) {
716 
717 }
718 
720  : KGameCanvasItem(KGameCanvas)
721  , m_size(0,0)
722  , m_origin(0,0)
723  , m_move_orig(false) {
724 
725 }
726 
727 KGameCanvasTiledPixmap::~KGameCanvasTiledPixmap() {
728 
729 }
730 
732  m_pixmap = pixmap;
733  if(visible() && canvas() )
734  changed();
735 }
736 
738  m_size = size;
739  if(visible() && canvas() )
740  changed();
741 }
742 
744 {
745  m_origin = m_move_orig ? origin - pos() : origin;
746 
747  if(visible() && canvas() )
748  changed();
749 }
750 
751 
753 {
754  if(move_orig && !m_move_orig)
755  m_origin -= pos();
756  if(move_orig && !m_move_orig)
757  m_origin += pos();
758  m_move_orig = move_orig;
759 }
760 
762 {
763  if(m_move_orig)
764  p->drawTiledPixmap( rect(), m_pixmap, m_origin);
765  else
766  p->drawTiledPixmap( rect(), m_pixmap, m_origin+pos() );
767 }
768 
770 {
771  return QRect(pos(), m_size);
772 }
773 
774 
775 /*
776  KGameCanvasRectangle
777 */
779  : KGameCanvasItem(KGameCanvas)
780  , m_color(color)
781  , m_size(size)
782 {
783 
784 }
785 
787  : KGameCanvasItem(KGameCanvas)
788  , m_size(0,0)
789 {
790 
791 }
792 
793 KGameCanvasRectangle::~KGameCanvasRectangle()
794 {
795 
796 }
797 
799 {
800  m_color = color;
801  if(visible() && canvas() )
802  changed();
803 }
804 
806 {
807  m_size = size;
808  if(visible() && canvas() )
809  changed();
810 }
811 
813  p->fillRect( rect(), m_color );
814 }
815 
817  return QRect(pos(), m_size);
818 }
819 
820 
821 /*
822  KGameCanvasText
823 */
825  const QFont& font, HPos hp, VPos vp,
826  KGameCanvasAbstract* KGameCanvas)
827  : KGameCanvasItem(KGameCanvas)
828  , m_text(text)
829  , m_color(color)
830  , m_font(font)
831  , m_hpos(hp)
832  , m_vpos(vp) {
833  calcBoundingRect();
834 }
835 
837  : KGameCanvasItem(KGameCanvas)
838  //, m_text("")
839  , m_color(Qt::black)
840  , m_font(QApplication::font())
841  , m_hpos(HStart)
842  , m_vpos(VBaseline) {
843 
844 }
845 
846 KGameCanvasText::~KGameCanvasText() {
847 
848 }
849 
850 void KGameCanvasText::calcBoundingRect() {
851  m_bounding_rect = QFontMetrics(m_font).boundingRect(m_text);
852  /*printf("b rect is %d %d %d %d\n",
853  m_bounding_rect.x(),
854  m_bounding_rect.y(),
855  m_bounding_rect.width(),
856  m_bounding_rect.height() );*/
857 }
858 
860  if(m_text == text)
861  return;
862  m_text = text;
863  calcBoundingRect();
864 
865  if(visible() && canvas() )
866  changed();
867 }
868 
870  m_color = color;
871 }
872 
874  m_font = font;
875  calcBoundingRect();
876 
877  if(visible() && canvas() )
878  changed();
879 }
880 
882  pos() += offsetToDrawPos();
883  m_hpos = hp;
884  m_vpos = vp;
885  pos() -= offsetToDrawPos();
886 }
887 
888 QPoint KGameCanvasText::offsetToDrawPos() const {
889  QPoint retv;
890 
891  switch(m_hpos) {
892  case HStart:
893  retv.setX(0);
894  break;
895  case HLeft:
896  retv.setX(-m_bounding_rect.left());
897  break;
898  case HRight:
899  retv.setX(-m_bounding_rect.right());
900  break;
901  case HCenter:
902  retv.setX(-(m_bounding_rect.left()+m_bounding_rect.right())/2);
903  break;
904  }
905 
906  switch(m_vpos) {
907  case VBaseline:
908  retv.setY(0);
909  break;
910  case VTop:
911  retv.setY(-m_bounding_rect.top());
912  break;
913  case VBottom:
914  retv.setY(-m_bounding_rect.bottom());
915  break;
916  case VCenter:
917  retv.setY(-(m_bounding_rect.top()+m_bounding_rect.bottom())/2);
918  break;
919  }
920 
921  return retv;
922 }
923 
925  p->setPen(m_color);
926  p->setFont(m_font);
927  p->drawText( pos() + offsetToDrawPos(), m_text);
928 }
929 
931  return m_bounding_rect.translated( pos() + offsetToDrawPos() );
932 }
933 
934 
935 /*
936  KGameCanvasPicture
937 */
939  : KGameCanvasItem(KGameCanvas), m_picture(p)
940 {
941 
942 }
943 
945  : KGameCanvasItem(KGameCanvas)
946 {
947 
948 }
949 
950 KGameCanvasPicture::~KGameCanvasPicture()
951 {
952 
953 }
954 
956 {
957  m_picture = p;
958 
959  if(visible() && canvas() )
960  changed();
961 }
962 
964 {
965  p->drawPicture(pos(), m_picture);
966 }
967 
969 {
970  return m_picture.boundingRect().translated( pos());
971 }
972 
974 : m_child_rect_valid(false)
975 {
976 }
977 
978 QRect KGameCanvasAdapter::childRect()
979 {
980  if (!m_child_rect_valid) {
981  m_child_rect = QRect();
982  for (KGameCanvasItem* el : qAsConst(m_items)) {
983  m_child_rect |= el->rect();
984  }
985  m_child_rect_valid = true;
986  }
987 
988  return m_child_rect;
989 }
990 
992 {
993  for (KGameCanvasItem* el : qAsConst(m_items)) {
994  if (el->m_visible) {
995  el->m_last_rect = el->rect();
996  el->paintInternal(painter, childRect(), childRect(), QPoint(), 1.0);
997  }
998  }
999 }
1000 
1001 void KGameCanvasAdapter::ensurePendingUpdate()
1002 {
1003  m_child_rect_valid = false;
1004 
1005  for (KGameCanvasItem* el : qAsConst(m_items)) {
1006  if (el->m_changed) {
1007  el->updateChanges();
1008  }
1009  }
1010 
1011  updateParent(m_invalidated_rect);
1012  m_invalidated_rect = QRect();
1013 }
1014 
1015 void KGameCanvasAdapter::invalidate(const QRegion& r, bool)
1016 {
1017  invalidate(r.boundingRect());
1018 }
1019 
1020 void KGameCanvasAdapter::invalidate(const QRect& r, bool)
1021 {
1022  m_invalidated_rect |= r;
1023 }
1024 
1025 
QRect rect() const override
This returns the bouding rect of all children.
void stackUnder(KGameCanvasItem *ref)
Restacks the item immediately under ref.
KGameCanvasTiledPixmap(const QPixmap &pixmap, const QSize &size, const QPoint &origin, bool move_orig, KGameCanvasAbstract *canvas=nullptr)
Constructor, specifying the pixmap and the parameters to use.
QFont font() const
Returns the font.
Definition: kgamecanvas.h:545
void setOpacity(qreal opacity)
QSize size() const const
void setAnimated(bool a)
Set the item as animated or not.
QSize size() const const
void setMoveOrigin(bool move_orig)
Sets if the origin of the brush will be moved with the pixmap.
void setAnimationDelay(int d)
Set the delay of the animation, in milliseconds.
An abstract item.
Definition: kgamecanvas.h:114
int width() const const
VPos
Specifies the meaning of the y coordinate of the item.
Definition: kgamecanvas.h:503
int width() const const
void receivePixmap(const QPixmap &pixmap) override
This method is called when the KGameRenderer has provided a new pixmap for this client (esp...
QRect boundingRect() const const
Container widget.
Definition: kgamecanvas.h:573
void fillRect(const QRectF &rectangle, const QBrush &brush)
void setCompositionMode(QPainter::CompositionMode mode)
void setFont(const QFont &font)
Sets the font.
void paint(QPainter *p) override
Override this function to draw the item with the painter.
Container class.
Definition: kgamecanvas.h:55
int right() const const
KGameCanvasPicture(const QPicture &picture, KGameCanvasAbstract *canvas=nullptr)
Constructor, specifying the picture to use.
KGameCanvasWidget(QWidget *parent=nullptr)
The constructor.
QRect rect() const override
Override this function to return the rect the item will be drawn into.
virtual void ensurePendingUpdate()=0
Virtual function to ensure an update is pending, called from children.
QList< KGameCanvasItem * > itemsAt(const QPoint &pos) const
Helper function to retrieve all the items at the given position, starting from the topmost one...
Definition: kgamecanvas.cpp:68
void moveTo(const QPoint &newpos)
Sets a new position.
QColor color() const
Returns the color.
Definition: kgamecanvas.h:539
QPixmap pixmap() const
Returns the pixmap.
Definition: kgamecanvas.h:416
const T & at(int i) const const
void removeAt(int i)
bool intersects(const QRect &rectangle) const const
QPixmap fromImage(const QImage &image, Qt::ImageConversionFlags flags)
void drawTiledPixmap(const QRectF &rectangle, const QPixmap &pixmap, const QPointF &position)
QPoint canvasPosition() const override
QRect boundingRect() const const
KGameCanvasText(const QString &text, const QColor &color, const QFont &font, HPos hp, VPos vp, KGameCanvasAbstract *canvas=nullptr)
Constructor, specifying the text and the parameters to use.
void setVisible(bool v)
Set the item as visible or hidden.
virtual void paint(QPainter *p)=0
Override this function to draw the item with the painter.
void raise()
Restacks the item on the top of the canvas.
virtual bool layered() const
Override this function to specify if the painting operations will paint over each other...
QRect rect() const override
This returns an empty rectangle.
void setSize(const QSize &size)
Sets the size.
KGameCanvasAbstract()
The constructor.
Definition: kgamecanvas.cpp:49
virtual QPoint canvasPosition() const =0
int mSecs()
Return the number of milliseconds from the creation of the canvas (see also KGameCanvasItem::advance)...
int size() const const
void setColor(const QColor &color)
Sets the color.
void setColor(const QColor &color)
Sets the color.
QPoint absolutePosition() const
KGameCanvasAbstract * canvas() const
Returns the canvas that is actually "owning" the item.
Definition: kgamecanvas.h:192
int indexOf(const T &value, int from) const const
KGameCanvasDummy(KGameCanvasAbstract *canvas=nullptr)
Constructor.
const QRect & rect() const const
KGameCanvasItem * itemAt(const QPoint &pos) const
Helper function to retrieve the topmost item at the given position.
Definition: kgamecanvas.cpp:59
void timeout()
void drawRect(const QRectF &rectangle)
QRect boundingRect(QChar ch) const const
void setFont(const QFont &font)
QRect rect() const override
Override this function to return the rect the item will be drawn into.
void append(const T &value)
void setSize(const QSize &size)
Sets the size.
bool empty() const const
KGameCanvasGroup(KGameCanvasAbstract *canvas=nullptr)
Constructor.
void paint(QPainter *p) override
Override this function to draw the item with the painter.
int top() const const
void setPen(const QColor &color)
int left() const const
QRegion translated(int dx, int dy) const const
Cache-enabled rendering of SVG themes.
Definition: kgamerenderer.h:94
void drawPixmap(const QRectF &target, const QPixmap &pixmap, const QRectF &source)
int removeAll(const T &value)
void setBrush(const QBrush &brush)
void drawText(const QPointF &position, const QString &text)
QString text() const
Returns the text.
Definition: kgamecanvas.h:533
virtual void changed()
schedule an update if the item
QRect translated(int dx, int dy) const const
T & first()
KGameCanvasWidget * topLevelCanvas() override
returns &#39;this&#39;
void paint(QPainter *p) override
Override this function to draw the item with the painter.
virtual QRect rect() const =0
Override this function to return the rect the item will be drawn into.
void paint(QPainter *p) override
Override this function to draw the item with the painter.
KGameCanvasRectangle(const QColor &color, const QSize &size, KGameCanvasAbstract *canvas=nullptr)
Constructor, specifying the pixmap and the parameters to use.
void stackOver(KGameCanvasItem *ref)
Restacks the item immediately over ref.
bool contains(const QPoint &p) const const
CompositionMode_Source
int height() const const
void putInCanvas(KGameCanvasAbstract *canvas)
Lets you specify the owning canvas.
bool isEmpty() const const
QRect rect() const override
Override this function to return the rect the item will be drawn into.
virtual void invalidate(const QRect &r, bool translate=true)=0
Virtual function to update a rect.
void repaint()
QColor color() const
Returns the color.
Definition: kgamecanvas.h:466
An object that receives pixmaps from a KGameRenderer.
void paint(QPainter *p) override
This paints all the children.
bool contains(const QRect &rectangle, bool proper) const const
void setPositioning(HPos hp, VPos vp)
Sets the positioning style.
void setPixmap(const QPixmap &pixmap)
Sets the pixmap of the sprite.
QPixmap pixmap() const
Returns the pixmap.
Definition: kgamecanvas.h:361
void setOrigin(const QPoint &size)
Sets the origin of the tiles.
virtual void advance(int msecs)
Override this function to handle animations, the default function does nothing.
QSize expandedTo(const QSize &otherSize) const const
void insert(int i, const T &value)
QPoint pos() const
Returns the position of the item.
Definition: kgamecanvas.h:202
int opacity() const
Returns the opacity of the item.
Definition: kgamecanvas.h:168
HPos
Specifies the meaning of the x coordinate of the item.
Definition: kgamecanvas.h:493
bool visible() const
Returns true if the item is visible.
Definition: kgamecanvas.h:156
T & last()
void setOpacity(int o)
Set the item&#39;s opacity value (int the 0-255 range)
virtual void ensureAnimating()=0
Virtual function to let know the canvas that it has animated items in it.
int height() const const
int bottom() const const
void setText(const QString &text)
Sets the text.
QPoint topLeft() const const
void setX(int x)
void setY(int y)
void translate(const QPointF &offset)
bool isEmpty() const const
void lower()
Restacks the item on the bottom of the canvas.
void prepend(const T &value)
KGameCanvasAdapter()
Constructor.
void drawPicture(const QPointF &point, const QPicture &picture)
QRect rect() const override
Override this function to return the rect the item will be drawn into.
KGameCanvasPixmap(const QPixmap &pixmap, KGameCanvasAbstract *canvas=nullptr)
Constructor, specifying the pixmap to use.
void advance(int msecs) override
Animations step, updates the animation for the children.
QMetaObject::Connection connect(const QObject *sender, const char *signal, const QObject *receiver, const char *method, Qt::ConnectionType type)
virtual void updateParent(const QRect &rect)=0
Notify the parent that the adapter content inside rect needs to be redrawn.
void paint(QPainter *p) override
This function does nothing (of course)
virtual bool event(QEvent *event) override
void paint(QPainter *p) override
Override this function to draw the item with the painter.
void setPixmap(const QPixmap &pixmap)
Sets the pixmap of the tile.
QPoint origin() const
The origin.
Definition: kgamecanvas.h:425
KGameCanvasItem(KGameCanvasAbstract *canvas=nullptr)
Constructor, it allows you to specify the reference canvas or to create an orphan item that will be p...
virtual void render(QPainter *p)
Draw the items of the adapter using the specified painter.
KGameCanvasWidget * topLevelCanvas() override
returns the toplevel canvas (or null if it is in an orphan tree)
void setPicture(const QPicture &picture)
Sets the picture of the sprite.
QRect rect() const override
Override this function to return the rect the item will be drawn into.
QPoint canvasPosition() const override
This file is part of the KDE documentation.
Documentation copyright © 1996-2020 The KDE developers.
Generated on Mon Nov 30 2020 22:37:54 by doxygen 1.8.11 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.