1 // This may look like C code, but it's really -*- C++ -*-
2 /*
3  * Copyright (C) 2008 Emweb bv, Herent, Belgium.
4  *
5  * See the LICENSE file for terms of use.
6  */
7 #ifndef WCANVAS_PAINT_DEVICE_H_
8 #define WCANVAS_PAINT_DEVICE_H_
9 
10 #include <Wt/WBrush.h>
11 #include <Wt/WFont.h>
12 #include <Wt/WObject.h>
13 #include <Wt/WPaintDevice.h>
14 #include <Wt/WPainterPath.h>
15 #include <Wt/WPen.h>
16 #include <Wt/WPointF.h>
17 #include <Wt/WShadow.h>
18 #include <Wt/WTransform.h>
19 
20 #include <sstream>
21 
22 namespace Wt {
23 
24 class DomElement;
25 class WTransform;
26 class ServerSideFontMetrics;
27 
28 /*! \class WCanvasPaintDevice Wt/WCanvasPaintDevice.h Wt/WCanvasPaintDevice.h
29  *  \brief A paint device for rendering using the HTML 5 &lt;canvas&gt; element.
30  *
31  * The %WCanvasPaintDevice is used by WPaintedWidget to render to the
32  * browser using the HTML 5 &lt;canvas&gt; element. You usually will
33  * not use the device directly, but rather rely on WPaintedWidget to
34  * use this device when appropriate.
35  *
36  * \note Older browsers do not have text support in &lt;canvas&gt;.
37  * Text is then rendered in an overlayed DIV and a consequence text is
38  * not subject to rotation and scaling components of the current
39  * transformation (but does take into account translation). On most
40  * browser you can use the WSvgImage or WVmlImage paint devices which
41  * do support text natively.
42  *
43  * \ingroup painting
44  */
45 class WT_API WCanvasPaintDevice : public WObject, public WPaintDevice
46 {
47 public:
48   /*! \brief Create a canvas paint device.
49    */
50   WCanvasPaintDevice(const WLength& width, const WLength& height,
51 		     bool paintUpdate = false);
52   virtual ~WCanvasPaintDevice();
53 
54   virtual WFlags<PaintDeviceFeatureFlag> features() const override;
55   virtual void setChanged(WFlags<PainterChangeFlag> flags) override;
56   virtual void drawArc(const WRectF& rect, double startAngle, double spanAngle)
57     override;
58   virtual void drawImage(const WRectF& rect, const std::string& imgUri,
59                          int imgWidth, int imgHeight, const WRectF& sourceRect) override;
60   virtual void drawLine(double x1, double y1, double x2, double y2) override;
61   virtual void drawPath(const WPainterPath& path) override;
62   virtual void drawStencilAlongPath(const WPainterPath &stencil,
63 				    const WPainterPath &path,
64                                     bool softClipping);
65   virtual void drawRect(const WRectF& rectangle) override;
66   virtual void drawText(const WRectF& rect,
67 			WFlags<AlignmentFlag> alignmentFlags,
68 			TextFlag textFlag,
69 			const WString& text,
70                         const WPointF *clipPoint) override;
71   virtual void drawTextOnPath(const WRectF &rect,
72 			      WFlags<AlignmentFlag> alignmentFlags,
73 			      const std::vector<WString> &text,
74 			      const WTransform &transform,
75 			      const WPainterPath &path,
76 			      double angle, double lineHeight,
77 			      bool softClipping);
78   virtual WTextItem measureText(const WString& text, double maxWidth = -1,
79 				bool wordWrap = false) override;
80   virtual WFontMetrics fontMetrics() override;
81   virtual void init() override;
82   virtual void done() override;
paintActive()83   virtual bool paintActive() const override { return painter_ != nullptr; }
84 
85   void render(const std::string &paintedWidgetJsRef,
86               const std::string& canvasId,
87               DomElement* text,
88               const std::string& updateAreasJs);
89   void renderPaintCommands(std::stringstream& js, const std::string& element);
90 
width()91   virtual WLength width() const override { return width_; }
height()92   virtual WLength height() const override { return height_; }
93 
94 protected:
painter()95   virtual WPainter *painter() const override { return painter_; }
setPainter(WPainter * painter)96   virtual void setPainter(WPainter *painter) override { painter_ = painter; }
97 
98 private:
99   enum class TextMethod { MozText, Html5Text, DomText };
100 
101   WLength     width_, height_;
102   WPainter   *painter_;
103   WFlags<PainterChangeFlag> changeFlags_;
104   bool        paintUpdate_;
105 
106   TextMethod  textMethod_;
107 
108   bool        currentNoPen_, currentNoBrush_, lastTransformWasIdentity_;
109 
110   WTransform  currentTransform_;
111   WBrush      currentBrush_;
112   WPen        currentPen_;
113   WShadow     currentShadow_;
114   WFont       currentFont_;
115   WPointF     pathTranslation_;
116   WPainterPath currentClipPath_;
117   WTransform currentClipTransform_;
118   bool currentClippingEnabled_;
119   ServerSideFontMetrics *fontMetrics_;
120 
121   std::stringstream js_;
122   std::vector<DomElement *> textElements_;
123   std::vector<std::string> images_;
124 
125   void finishPath();
126   void renderTransform(std::stringstream& s, const WTransform& t);
127   void renderStateChanges(bool resetPathTranslation);
128   void resetPathTranslation();
129   void drawPlainPath(std::stringstream& s, const WPainterPath& path);
130 
131   int createImage(const std::string& imgUri);
132 
textMethod()133   TextMethod textMethod() const { return textMethod_; }
134 
135   friend class WWidgetCanvasPainter;
136 };
137 
138 }
139 
140 #endif // WCANVAS_PAINT_DEVICE_H_
141