|
20 | 20 | #ifndef ICAIROSHIM_H |
21 | 21 | #define ICAIROSHIM_H |
22 | 22 |
|
| 23 | +#include <cmath> |
| 24 | +#include <memory> |
23 | 25 | #include <string> |
24 | 26 | #include <cairo.h> |
25 | 27 |
|
26 | | -// Forward declarations |
27 | | -namespace ecolab { class Pango; } |
28 | | - |
29 | 28 | namespace minsky |
30 | 29 | { |
31 | 30 | class SVGRenderer; |
| 31 | + |
| 32 | + struct TextProperties |
| 33 | + { |
| 34 | + // markup overrides the text entry |
| 35 | + std::string markup, plainText; |
| 36 | + double fontSize=std::nan(""); |
| 37 | + double angle=0; |
| 38 | + std::string fontFamily; |
| 39 | + TextProperties(const std::string& markup="", const std::string& plainText="", double fontSize=std::nan("")): |
| 40 | + markup(markup), plainText(plainText), fontSize(fontSize) {} |
| 41 | + TextProperties(const std::string& markup, double fontSize): |
| 42 | + markup(markup), fontSize(fontSize) {} |
| 43 | + }; |
| 44 | + |
| 45 | + struct TextExtents |
| 46 | + { |
| 47 | + double left, top, width, height; |
| 48 | + }; |
| 49 | + |
| 50 | + /// cache results of font rendering to amortise setup costs |
| 51 | + class ICacheRender |
| 52 | + { |
| 53 | + public: |
| 54 | + virtual ~ICacheRender()=default; |
| 55 | + virtual void show()=0; |
| 56 | + virtual TextExtents extents() const=0; |
| 57 | + virtual void* context() const=0; |
| 58 | + }; |
| 59 | + |
| 60 | + class ICairoShim; |
| 61 | + |
| 62 | + /// a simple minded implementation that doesn't cache |
| 63 | + class NonCachedRenderer: public ICacheRender |
| 64 | + { |
| 65 | + TextProperties text; |
| 66 | + const ICairoShim& shim; |
| 67 | + public: |
| 68 | + NonCachedRenderer(const TextProperties& text, const ICairoShim& shim): |
| 69 | + text(text), shim(shim) {} |
| 70 | + void show() override; |
| 71 | + TextExtents extents() const override; |
| 72 | + void* context() const override; |
| 73 | + }; |
32 | 74 |
|
33 | 75 | /// Abstract interface for Cairo drawing operations |
34 | 76 | class ICairoShim |
35 | 77 | { |
36 | 78 | public: |
37 | 79 | virtual ~ICairoShim() = default; |
38 | 80 |
|
39 | | - // Drawing operations |
| 81 | + /// @{ Drawing operations |
40 | 82 | virtual void moveTo(double x, double y) const = 0; |
41 | 83 | virtual void lineTo(double x, double y) const = 0; |
42 | 84 | virtual void relMoveTo(double x, double y) const = 0; |
43 | 85 | virtual void relLineTo(double x, double y) const = 0; |
44 | 86 | virtual void arc(double x, double y, double radius, double start, double end) const = 0; |
45 | 87 | virtual void curveTo(double x1, double y1, double x2, double y2, double x3, double y3) const = 0; |
46 | 88 | virtual void rectangle(double x, double y, double width, double height) const = 0; |
47 | | - |
48 | | - // Path operations |
| 89 | + /// @} |
| 90 | + |
| 91 | + /// @{ Path operations |
49 | 92 | virtual void newPath() const = 0; |
50 | 93 | virtual void newSubPath() const = 0; |
51 | 94 | virtual void closePath() const = 0; |
52 | 95 | virtual void getCurrentPoint(double& x, double& y) const = 0; |
53 | | - |
54 | | - // Fill and stroke operations |
| 96 | + /// @} |
| 97 | + |
| 98 | + /// @{ Fill and stroke operations |
55 | 99 | virtual void fill() const = 0; |
56 | 100 | virtual void fillPreserve() const = 0; |
57 | 101 | virtual void stroke() const = 0; |
58 | 102 | virtual void strokePreserve() const = 0; |
59 | 103 | virtual void clip() const = 0; |
60 | 104 | virtual void resetClip() const = 0; |
61 | 105 | virtual void paint() const = 0; |
62 | | - |
63 | | - // Line properties |
| 106 | + /// @} |
| 107 | + |
| 108 | + /// @{ Line properties |
64 | 109 | virtual void setLineWidth(double width) const = 0; |
65 | 110 | virtual double getLineWidth() const = 0; |
66 | 111 | virtual void setDash(const double* dashes, int num_dashes, double offset) const = 0; |
67 | 112 | virtual void setFillRule(cairo_fill_rule_t fill_rule) const = 0; |
68 | | - |
69 | | - // Color operations |
| 113 | + /// @} |
| 114 | + |
| 115 | + /// @{ Color operations |
70 | 116 | virtual void setSourceRGB(double r, double g, double b) const = 0; |
71 | 117 | virtual void setSourceRGBA(double r, double g, double b, double a) const = 0; |
72 | | - |
73 | | - // Text operations |
74 | | - virtual void showText(const std::string& text) const = 0; |
75 | | - virtual void setFontSize(double size) const = 0; |
76 | | - virtual void selectFontFace(const std::string& family, cairo_font_slant_t slant, cairo_font_weight_t weight) const = 0; |
77 | | - virtual void textExtents(const std::string& text, cairo_text_extents_t& extents) const = 0; |
78 | | - |
79 | | - // Transformation operations |
| 118 | + /// @} |
| 119 | + |
| 120 | + /// render text |
| 121 | + virtual void showText(const TextProperties& text) const = 0; |
| 122 | + /// show markup text |
| 123 | + void showText(const std::string& s, double fs=std::nan("")) const |
| 124 | + {showText(TextProperties(s,fs));} |
| 125 | + /// show text with no markup interpretation |
| 126 | + void showPlainText(const std::string& s, double fs=std::nan("")) const |
| 127 | + {showText(TextProperties("",s,fs));} |
| 128 | +// virtual void setFontSize(double size) const = 0; |
| 129 | +// virtual void selectFontFace(const std::string& family, cairo_font_slant_t slant, cairo_font_weight_t weight) const = 0; |
| 130 | + /// return metrics for a given bit of text |
| 131 | + virtual TextExtents textExtents(const TextProperties& text) const = 0; |
| 132 | + |
| 133 | + /// @{ Transformation operations |
80 | 134 | virtual void identityMatrix() const = 0; |
81 | 135 | virtual void translate(double x, double y) const = 0; |
82 | 136 | virtual void scale(double sx, double sy) const = 0; |
83 | 137 | virtual void rotate(double angle) const = 0; |
84 | 138 | virtual void userToDevice(double& x, double& y) const = 0; |
85 | | - |
86 | | - // Context state operations |
| 139 | + /// @} |
| 140 | + |
| 141 | + /// @{ Context state operations |
87 | 142 | virtual void save() const = 0; |
88 | 143 | virtual void restore() const = 0; |
89 | | - |
90 | | - // Tolerance |
| 144 | + /// @} |
| 145 | + |
| 146 | + /// Tolerance |
91 | 147 | virtual void setTolerance(double tolerance) const = 0; |
92 | 148 |
|
93 | | - // TODO: this needs to be fixed with a proper text rendering interface. |
94 | | - // For now use a newPango call that resets the pango |
95 | | - // Pango support for text rendering |
96 | | - virtual ecolab::Pango& pango() const = 0; |
97 | | - virtual ecolab::Pango& newPango() const = 0; |
98 | | - |
99 | 149 | // SVG rendering support |
100 | 150 | /// Render an SVG resource into a region of size width x height |
101 | 151 | /// @param svgRenderer - Reference to SVGRenderer containing the loaded SVG resource |
102 | 152 | /// @param width - target width for rendering |
103 | 153 | /// @param height - target height for rendering |
104 | 154 | virtual void renderSVG(const SVGRenderer& svgRenderer, double width, double height) const = 0; |
| 155 | + |
| 156 | + /// returns reference to underlying context for caching purposes |
| 157 | + virtual void* context() const=0; |
| 158 | + |
| 159 | + /// return a cached object of rendered text |
| 160 | + virtual std::unique_ptr<ICacheRender> cachedRender(const TextProperties& tp) const |
| 161 | + {return std::make_unique<NonCachedRenderer>(tp,*this);} |
105 | 162 | }; |
106 | 163 |
|
| 164 | + /// RAII wrapper around save/restore |
| 165 | + struct CairoShimSave |
| 166 | + { |
| 167 | + const ICairoShim& shim; |
| 168 | + CairoShimSave(const ICairoShim& shim): shim(shim) {shim.save();} |
| 169 | + ~CairoShimSave() {shim.restore();} |
| 170 | + }; |
107 | 171 |
|
| 172 | + inline void NonCachedRenderer::show() |
| 173 | + {shim.showText(text);} |
| 174 | + inline TextExtents NonCachedRenderer::extents() const |
| 175 | + {return shim.textExtents(text);} |
| 176 | + inline void* NonCachedRenderer::context() const |
| 177 | + {return shim.context();} |
| 178 | + |
108 | 179 | } |
109 | 180 |
|
110 | 181 | #include "ICairoShim.xcd" |
|
0 commit comments