1 /*  Originally created for KBoard
2     SPDX-FileCopyrightText: 2006 Maurizio Monge <maurizio.monge@gmail.com>
3 
4     SPDX-License-Identifier: BSD-2-Clause
5 */
6 
7 #ifndef __KGAMECANVAS_H__
8 #define __KGAMECANVAS_H__
9 
10 /*
11  *  Author: Maurizio Monge <maurizio.monge@gmail.com>
12  */
13 
14 // own
15 #include "libkdegamesprivate_export.h"
16 #include "kgamerendererclient.h"
17 // Qt
18 #include <QList>
19 #include <QPoint>
20 #include <QPicture>
21 #include <QPixmap>
22 #include <QPainter>
23 #include <QRect>
24 #include <QRegion>
25 #include <QWidget>
26 
27 class KGameCanvasItem;
28 
29 /**
30     \class KGameCanvasAbstract kgamecanvas.h <KGameCanvas>
31     \brief Container class.
32 
33     A KGameCanvasAbstract is a set of canvas items.
34 
35     \deprecated For new applications, use Qt's Graphics View framework or Qt Quick.
36 */
37 class KDEGAMESPRIVATE_EXPORT KGameCanvasAbstract
38 {
39 protected:
40     friend class KGameCanvasItem;
41 
42     QList<KGameCanvasItem*> m_items;
43     QList<KGameCanvasItem*> m_animated_items;
44 
45 public:
46     /** The constructor */
47     KGameCanvasAbstract();
48 
49     virtual ~KGameCanvasAbstract();
50 
51     /** Returns a const pointer to the list holding all the items in the canvas */
items()52     const QList<KGameCanvasItem*>* items() const { return &m_items; }
53 
54     /** Helper function to retrieve the topmost item at the given position */
55     KGameCanvasItem* itemAt(const QPoint &pos) const;
56 
57     /** Overload, same as above */
itemAt(int x,int y)58     KGameCanvasItem* itemAt(int x, int y) const { return itemAt(QPoint(x,y)); }
59 
60     /** Helper function to retrieve all the items at the given position,
61         starting from the topmost one. */
62     QList<KGameCanvasItem*> itemsAt(const QPoint &pos) const;
63 
64     /** Overload, same as above */
itemsAt(int x,int y)65     QList<KGameCanvasItem*> itemsAt(int x, int y) const { return itemsAt(QPoint(x,y)); }
66 
67     /** Virtual function to let know the canvas that it has animated items in it */
68     virtual void ensureAnimating() = 0;
69 
70     /** Virtual function to ensure an update is pending, called from children */
71     virtual void ensurePendingUpdate() = 0;
72 
73     /** Virtual function to update a rect */
74     virtual void invalidate(const QRect& r, bool translate = true) = 0;
75 
76     /** Virtual function to update a region */
77     virtual void invalidate(const QRegion& r, bool translate = true) = 0;
78 
79     /** Returns the toplevel non-group KGameCanvasWidget object */
80     virtual class KGameCanvasWidget* topLevelCanvas() = 0;
81 
82     /** @return Position of the abstract canvas relative to the toplevel canvas. */
83     virtual QPoint canvasPosition() const = 0;
84 };
85 
86 
87 /**
88     \class KGameCanvasItem kgamecanvas.h <KGameCanvas>
89     \brief An abstract item.
90 
91     A KGameCanvasItem is an abstract class to represent a generic item that can be
92     put in a canvas.
93 
94     \deprecated For new applications, use Qt's Graphics View framework or Qt Quick.
95 */
96 class KDEGAMESPRIVATE_EXPORT KGameCanvasItem
97 {
98 private:
99     friend class KGameCanvasAbstract;
100     friend class KGameCanvasWidget;
101     friend class KGameCanvasGroup;
102     friend class KGameCanvasAdapter;
103 
104     bool m_visible;
105     bool m_animated;
106     int  m_opacity;
107     QPoint m_pos;
108     KGameCanvasAbstract *m_canvas;
109 
110     bool m_changed;
111     QRect m_last_rect;
112 
113     static QPixmap* transparence_pixmap_cache;
114     static QPixmap* getTransparenceCache(const QSize &s);
115     virtual void paintInternal(QPainter* p, const QRect& prect, const QRegion& preg,
116                                           const QPoint &delta, double cumulative_opacity);
117 
118     void updateAfterRestack(int from, int to);
119 
120     /* function to update pending changes, called from parent */
121     virtual void updateChanges();
122 
123 public:
124     /** Constructor, it allows you to specify the reference canvas or to create
125         an orphan item that will be put into a canvas in a second moment.
126         The item is always hidden after being created.
127         Note that the restacking functions are quite intelligent and will only
128         repaint if there is an actual need of doing it. So if you call raise on
129         an item that is already (locally) on the top, no redraw will take place */
130     explicit KGameCanvasItem(KGameCanvasAbstract* canvas = nullptr);
131 
132     virtual ~KGameCanvasItem();
133 
134     /** schedule an update if the item */
135     virtual void changed();
136 
137     /** Returns true if the item is visible */
visible()138     bool visible() const { return m_visible; }
139 
140     /** Set the item as visible or hidden */
141     void setVisible(bool v);
142 
143     /** Returns true if the item is animated */
animated()144     bool animated() const { return m_animated; }
145 
146     /** Set the item as animated or not */
147     void setAnimated(bool a);
148 
149     /** Returns the opacity of the item */
opacity()150     int opacity() const { return m_opacity; }
151 
152     /** Set the item's opacity value (int the 0-255 range) */
153     void setOpacity(int o);
154 
155     /** Hides the item */
hide()156     void hide(){ setVisible(false); }
157 
158     /** Shows the item */
show()159     void show(){ setVisible(true); }
160 
161     /** Restacks the item on the top of the canvas */
162     void raise();
163 
164     /** Restacks the item on the bottom of the canvas */
165     void lower();
166 
167     /** Restacks the item immediately over ref */
168     void stackOver(KGameCanvasItem* ref);
169 
170     /** Restacks the item immediately under ref */
171     void stackUnder(KGameCanvasItem* ref);
172 
173     /** Returns the canvas that is actually "owning" the item */
canvas()174     KGameCanvasAbstract *canvas() const { return m_canvas; }
175 
176     /** Returns the toplevel canvas widget, or NULL */
topLevelCanvas()177     KGameCanvasWidget *topLevelCanvas() const { return m_canvas ? m_canvas->topLevelCanvas() : nullptr; }
178 
179     /** Lets you specify the owning canvas. Call this function with canvas
180         set to NULL to remove the item from the current canvas. */
181     void putInCanvas(KGameCanvasAbstract *canvas);
182 
183     /** Returns the position of the item */
pos()184     QPoint pos() const { return m_pos; }
185 
186     /** @return Position of the item relative to the top level canvas. */
187     QPoint absolutePosition() const;
188 
189     /** Sets a new position. Note that an update will be posted to the parent
190         canvas, and if you move an item twice in very little time, a region
191         bigger than needed will be updated, causing a possible inefficiency */
192     void moveTo(const QPoint &newpos);
193 
194     /** Overload, same as above */
moveTo(int x,int y)195     void moveTo(int x, int y) { moveTo( QPoint(x,y)); }
196 
197     /** Override this function to draw the item with the painter */
198     virtual void paint(QPainter* p) = 0;
199 
200     /** Override this function to return the rect the item will be drawn into */
201     virtual QRect rect() const = 0;
202 
203     /** Override this function to specify if the painting operations will paint over
204         each other. If not, the item will be drawn more quickly when opacity is != 255,
205         because it does not have to be painted onto a pixmap first. If you don't care
206         about the item's opacity, don't care about this function as well. */
207     virtual bool layered() const;
208 
209     /** Override this function to handle animations, the default function does nothing.
210         The argument is the number of milliseconds from the creation of the canvas, so
211         that you use it to handle the animation. */
212     virtual void advance(int msecs);
213 };
214 
215 
216 /**
217     \class KGameCanvasDummy kgamecanvas.h <KGameCanvas>
218     \brief A dummy (empty) item.
219 
220     A KGameCanvasDummy is an empty, invisible item.
221     You can use it as reference for stacking items in the canvas using the
222     stackOver and stackUnder functions.
223 
224     \deprecated For new applications, use Qt's Graphics View framework or Qt Quick.
225 */
226 class KDEGAMESPRIVATE_EXPORT KGameCanvasDummy : public KGameCanvasItem
227 {
228 public:
229     /** Constructor */
230     explicit KGameCanvasDummy(KGameCanvasAbstract* canvas = nullptr);
231 
232     ~KGameCanvasDummy() override;
233 
234     /** This function does nothing (of course) */
235     void paint(QPainter* p) override;
236 
237     /** This returns an empty rectangle */
238     QRect rect() const override;
239 };
240 
241 
242 /**
243     \class KGameCanvasGroup kgamecanvas.h <KGameCanvas>
244     \brief An item containing other items.
245 
246     A KGameCanvasGroup is an KGameCanvasItem, but it is also a KGameCanvasAbstract,
247     so you can add children items to it. Just an inner canvas, if you prefer.
248 
249     \deprecated For new applications, use Qt's Graphics View framework or Qt Quick.
250 */
251 class KDEGAMESPRIVATE_EXPORT KGameCanvasGroup : public KGameCanvasItem, public KGameCanvasAbstract
252 {
253 private:
254     mutable bool m_child_rect_changed;
255     mutable QRect m_last_child_rect;
256 
257     void paintInternal(QPainter* p, const QRect& prect, const QRegion& preg,
258                                           const QPoint& delta, double cumulative_opacity) override;
259 
260     void ensureAnimating() override;
261     void ensurePendingUpdate() override;
262     void invalidate(const QRect& r, bool translate = true) override;
263     void invalidate(const QRegion& r, bool translate = true) override;
264     void updateChanges() override;
265     void changed() override;
266 
267 public:
268     /** Constructor */
269     explicit KGameCanvasGroup(KGameCanvasAbstract* canvas = nullptr);
270 
271     ~KGameCanvasGroup() override;
272 
273     /** This paints all the children */
274     void paint(QPainter* p) override;
275 
276     /** This returns the bouding rect of all children */
277     QRect rect() const override;
278 
279     /** Animations step, updates the animation for the children */
280     void advance(int msecs) override;
281 
282     /** returns the toplevel canvas (or null if it is in an orphan tree) */
283     KGameCanvasWidget* topLevelCanvas() override;
284 
285     QPoint canvasPosition() const override;
286 };
287 
288 /**
289     \class KGameCanvasPicture kgamecanvas.h <KGameCanvas>
290     \brief A picture, ie a collection of paint operations.
291 
292     A KGameCanvasPicture is a picture that can be replayed on the canvas.
293 
294     \deprecated For new applications, use Qt's Graphics View framework or Qt Quick.
295 */
296 class KDEGAMESPRIVATE_EXPORT KGameCanvasPicture : public KGameCanvasItem
297 {
298 private:
299     QPicture m_picture;
300 
301 public:
302     /** Constructor, specifying the picture to use */
303     explicit KGameCanvasPicture(const QPicture& picture, KGameCanvasAbstract* canvas = nullptr);
304 
305     /** Constructor, creating with an empty picture */
306     explicit KGameCanvasPicture(KGameCanvasAbstract* canvas = nullptr);
307 
308     ~KGameCanvasPicture() override;
309 
310     /** Returns the picture */
picture()311     QPicture picture() const { return m_picture; }
312 
313     /** Sets the picture of the sprite */
314     void setPicture(const QPicture& picture);
315 
316     void paint(QPainter* p) override;
317     QRect rect() const override;
318 };
319 
320 /**
321     \class KGameCanvasPixmap kgamecanvas.h <KGameCanvas>
322     \brief A pixmap (sprite).
323 
324     A KGameCanvasPixmap is a pixmap that can be put in the canvas.
325 
326     \deprecated For new applications, use Qt's Graphics View framework or Qt Quick.
327 */
328 class KDEGAMESPRIVATE_EXPORT KGameCanvasPixmap : public KGameCanvasItem
329 {
330 private:
331     QPixmap m_pixmap;
332 
333 public:
334     /** Constructor, specifying the pixmap to use */
335     explicit KGameCanvasPixmap(const QPixmap& pixmap, KGameCanvasAbstract* canvas = nullptr);
336 
337     /** Constructor, creating with an empty pixmap */
338     explicit KGameCanvasPixmap(KGameCanvasAbstract* canvas = nullptr);
339 
340     ~KGameCanvasPixmap() override;
341 
342     /** Returns the pixmap */
pixmap()343     QPixmap pixmap() const { return m_pixmap; }
344 
345     /** Sets the pixmap of the sprite */
346     void setPixmap(const QPixmap& pixmap);
347 
348     void paint(QPainter* p) override;
349     QRect rect() const override;
layered()350     bool layered() const override { return false; }
351 };
352 
353 /**
354     \class KGameCanvasRenderedPixmap kgamecanvas.h <KGameCanvas>
355     \brief A sprite pixmap from KGameRenderer.
356 
357     This canvas item behaves like KGameCanvasPixmap, but the pixmaps are served
358     from a KGameRenderer. This class exists solely for the purpose of porting
359     existing applications to KGameRenderer.
360 
361     \deprecated For new applications, use Qt's Graphics View framework or Qt Quick.
362  */
363 class KDEGAMESPRIVATE_EXPORT KGameCanvasRenderedPixmap : public KGameCanvasPixmap, public KGameRendererClient
364 {
365 public:
366 	KGameCanvasRenderedPixmap(KGameRenderer* renderer, const QString& spriteKey, KGameCanvasAbstract* canvas = nullptr);
367 protected:
368 	void receivePixmap(const QPixmap& pixmap) override;
369 };
370 
371 /**
372     \class KGameCanvasTiledPixmap kgamecanvas.h <KGameCanvas>
373     \brief A tiled pixmap (brush).
374 
375     A KGameCanvasTiledPixmap is a pixmap that can be put in the canvas.
376 
377     \deprecated For new applications, use Qt's Graphics View framework or Qt Quick.
378 */
379 class KDEGAMESPRIVATE_EXPORT  KGameCanvasTiledPixmap : public KGameCanvasItem
380 {
381 private:
382     QPixmap m_pixmap;
383     QSize m_size;
384     QPoint m_origin;
385     bool m_move_orig;
386 
387 public:
388     /** Constructor, specifying the pixmap and the parameters to use */
389     KGameCanvasTiledPixmap(const QPixmap& pixmap, const QSize &size, const QPoint &origin,
390                             bool move_orig, KGameCanvasAbstract* canvas = nullptr);
391 
392     /** Constructor, creating with an empty pixmap */
393     explicit KGameCanvasTiledPixmap(KGameCanvasAbstract* canvas = nullptr);
394 
395     ~KGameCanvasTiledPixmap() override;
396 
397     /** Returns the pixmap */
pixmap()398     QPixmap pixmap() const { return m_pixmap; }
399 
400     /** Sets the pixmap of the tile */
401     void setPixmap(const QPixmap& pixmap);
402 
403     /** Sets the size */
404     void setSize(const QSize &size);
405 
406     /** The origin */
origin()407     QPoint origin() const { return m_move_orig ? m_origin + pos() : m_origin; }
408 
409     /** Sets the origin of the tiles */
410     void setOrigin(const QPoint &size);
411 
412     /** If the origin is moved */
moveOrigin()413     bool moveOrigin(){ return m_move_orig; }
414 
415     /** Sets if the origin of the brush will be moved with the pixmap */
416     void setMoveOrigin(bool move_orig);
417 
418     void paint(QPainter* p) override;
419     QRect rect() const override;
layered()420     bool layered() const override { return false; }
421 };
422 
423 
424 /**
425     \class KGameCanvasRectangle kgamecanvas.h <KGameCanvas>
426     \brief A solid rectangle.
427 
428     A KGameCanvasRectangle is a rectangle that can be put in the canvas.
429 
430     \deprecated For new applications, use Qt's Graphics View framework or Qt Quick.
431 */
432 class KDEGAMESPRIVATE_EXPORT  KGameCanvasRectangle : public KGameCanvasItem
433 {
434 private:
435     QColor m_color;
436     QSize m_size;
437 
438 public:
439     /** Constructor, specifying the pixmap and the parameters to use */
440     KGameCanvasRectangle(const QColor& color, const QSize &size, KGameCanvasAbstract* canvas = nullptr);
441 
442     /** Constructor, creating with an empty pixmap */
443     explicit KGameCanvasRectangle(KGameCanvasAbstract* canvas = nullptr);
444 
445     ~KGameCanvasRectangle() override;
446 
447     /** Returns the color */
color()448     QColor color() const { return m_color; }
449 
450     /** Sets the color */
451     void setColor(const QColor& color);
452 
453     /** Sets the size */
454     void setSize(const QSize &size);
455 
456     void paint(QPainter* p) override;
457     QRect rect() const override;
layered()458     bool layered() const override { return false; }
459 };
460 
461 /**
462     \class KGameCanvasText kgamecanvas.h <KGameCanvas>
463     \brief KGameCanvasText.
464 
465     A KGameCanvasText is a text that can be put in the canvas.
466 
467     \deprecated For new applications, use Qt's Graphics View framework or Qt Quick.
468 */
469 class KDEGAMESPRIVATE_EXPORT KGameCanvasText : public KGameCanvasItem
470 {
471 public:
472     /** Specifies the meaning of the x coordinate of the item. It can
473         refer to the start of the text, of the left, center, right of
474         the bounding rectangle. */
475     enum HPos {
476         HStart,
477         HLeft,
478         HRight,
479         HCenter
480     };
481 
482     /** Specifies the meaning of the y coordinate of the item. It can
483         refer to the baseline of the text, of the top, center, bottom of
484         the bounding rectangle. */
485     enum VPos {
486         VBaseline,
487         VTop,
488         VBottom,
489         VCenter
490     };
491 
492 private:
493     QString m_text;
494     QColor m_color;
495     QFont m_font;
496     HPos m_hpos;
497     VPos m_vpos;
498     QRect m_bounding_rect;
499 
500     QPoint offsetToDrawPos() const;
501     void calcBoundingRect();
502 
503 public:
504     /** Constructor, specifying the text and the parameters to use */
505     KGameCanvasText(const QString& text, const QColor& color,
506                     const QFont& font, HPos hp, VPos vp,
507                     KGameCanvasAbstract* canvas = nullptr);
508 
509     /** Constructor, creating with an empty text */
510     explicit KGameCanvasText(KGameCanvasAbstract* canvas = nullptr);
511 
512     ~KGameCanvasText() override;
513 
514     /** Returns the text */
text()515     QString text() const { return m_text; }
516 
517     /** Sets the text */
518     void setText(const QString& text);
519 
520     /** Returns the color */
color()521     QColor color() const { return m_color; }
522 
523     /** Sets the color */
524     void setColor(const QColor& color);
525 
526     /** Returns the font */
font()527     QFont font() const { return m_font; }
528 
529     /** Sets the font */
530     void setFont(const QFont& font);
531 
532     /** Returns the horizontal positioning style */
hPositioning()533     HPos hPositioning() const { return m_hpos; }
534 
535     /** Returns the vertical positioning style */
vPositioning()536     VPos vPositioning() const { return m_vpos; }
537 
538     /** Sets the positioning style */
539     void setPositioning(HPos hp, VPos vp);
540 
541     void paint(QPainter* p) override;
542     QRect rect() const override;
layered()543     bool layered() const override { return false; }
544 };
545 
546 /**
547     \class KGameCanvasWidget kgamecanvas.h <KGameCanvas>
548     \brief Container widget.
549 
550     A KGameCanvasWidget is a widget that can contain many KGameCanvasItem (images, rectangles, lines, etc).
551     Portions of the widget are automatically redrawn to update the changes made to the items.
552 
553     \deprecated For new applications, use Qt's Graphics View framework or Qt Quick.
554 */
555 class KDEGAMESPRIVATE_EXPORT KGameCanvasWidget : public QWidget, public KGameCanvasAbstract
556 {
557 Q_OBJECT
558 private:
559     friend class KGameCanvasItem;
560     friend class AnimationNotifier;
561 
562     class  KGameCanvasWidgetPrivate *priv;
563 
564     void ensureAnimating() override;
565     void ensurePendingUpdate() override;
566     void invalidate(const QRect& r, bool translate = true) override;
567     void invalidate(const QRegion& r, bool translate = true) override;
568 
569     void paintEvent(QPaintEvent *event) override;
570 
571 private Q_SLOTS:
572     void processAnimations();
573     void updateChanges();
574 
575 public:
576     /** The constructor */
577     explicit KGameCanvasWidget(QWidget* parent = nullptr);
578 
579     ~KGameCanvasWidget() override;
580 
581     /** Set the delay of the animation, in milliseconds */
582     void setAnimationDelay(int d);
583 
584     /** Return the number of milliseconds from the creation of the canvas
585         (see also KGameCanvasItem::advance)*/
586     int mSecs();
587 
588     /** returns 'this' */
589     KGameCanvasWidget* topLevelCanvas() override;
590 
591     /** @return 0 */
592     QPoint canvasPosition() const override;
593 };
594 
595 /**
596     \class KGameCanvasAdapter kgamecanvas.h <KGameCanvas>
597 
598     \brief A generic adapter for KGameCanvas
599 
600     KGameCanvasAdapter can be used to draw content managed by KGameCanvas
601     inside systems which do not use KGameCanvas internally for their
602     rendering.
603 
604     For example, suppose you have a widget CustomDisplay which paints itself
605     with direct QPainter calls in its paintEvent, and you want to add a
606     complex element to its rendering, which is best implemented via the KGameCanvas
607     abstractions. What you can do is to create a KGameCanvasAdapter subclass,
608     use it just like a KGameCanvasGroup, then call its render member function
609     to have a QPainter object draw it.
610 
611     A KGameCanvas adapter notifies its parent using the pure virtual function
612     updateParent, which is called when the adapter content is invalidated.
613 
614     \todo Support animations
615 
616     \deprecated For new applications, use Qt's Graphics View framework or Qt Quick.
617 */
618 class KDEGAMESPRIVATE_EXPORT KGameCanvasAdapter : public KGameCanvasAbstract
619 {
620     QRect m_child_rect;
621     bool m_child_rect_valid;
622     QRect m_invalidated_rect;
623 
ensureAnimating()624     void ensureAnimating() override { }
625     void ensurePendingUpdate() override;
626     void invalidate(const QRect& r, bool translate = true) override;
627     void invalidate(const QRegion& r, bool translate = true) override;
628 
629     QRect childRect();
630 public:
631     /** Constructor */
632     KGameCanvasAdapter();
633 
634     /**
635       * An adapter is not associated to any canvas, so this function
636       * simply returns 0.
637       */
topLevelCanvas()638     class KGameCanvasWidget* topLevelCanvas() override { return nullptr; }
639 
640     /**
641       * The absolute position of the rendered content is not well
642       * defined for KGameCanvasAdapter. We assume that the adapter
643       * will be rendered at (0,0), and leave it to the user to perform
644       * the necessary adjustments, which will depend on the chosen
645       * rendering method.
646       *
647       * @return The point (0, 0).
648       */
canvasPosition()649     QPoint canvasPosition() const override { return QPoint(0, 0); }
650 
651     /**
652       * Draw the items of the adapter using the specified painter.
653       * \param p The QPainter object to be used for rendering.
654       */
655     virtual void render(QPainter* p);
656 
657     /**
658       * Notify the parent that the adapter content inside \a rect needs
659       * to be redrawn.
660       *
661       * \a rect The bounding rectangle of the region that needs repainting.
662       */
663     virtual void updateParent(const QRect& rect) = 0;
664 };
665 
666 #endif //__KGRGAMECANVAS_H__
667