Skip to content

Commit 8f7cfda

Browse files
Merge pull request #656 from highperformancecoder/copilot/refactor-item-draw-method
Copilot/refactor item draw method
2 parents b5041f0 + 526b5cf commit 8f7cfda

76 files changed

Lines changed: 23489 additions & 23695 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

engine/cairoShimCairo.cc

Lines changed: 27 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
#endif
1414

1515
using namespace std;
16+
using ecolab::Pango;
1617

1718
namespace minsky
1819
{
@@ -98,17 +99,33 @@ namespace minsky
9899
{cairo_set_source_rgba(cairo,r,g,b,a);}
99100

100101
// Text operations
101-
void CairoShimCairo::showText(const std::string& text) const
102-
{cairo_show_text(cairo,text.c_str());}
103-
104-
void CairoShimCairo::setFontSize(double size) const
105-
{cairo_set_font_size(cairo, size);}
106-
107-
void CairoShimCairo::selectFontFace(const std::string& family, cairo_font_slant_t slant, cairo_font_weight_t weight) const
108-
{cairo_select_font_face(cairo, family.c_str(), slant, weight);}
102+
void CairoShimCairo::initPango(Pango& pango,const TextProperties& tp) const
103+
{
104+
if (!tp.markup.empty())
105+
pango.setMarkup(tp.markup);
106+
else if (!tp.plainText.empty())
107+
pango.setText(tp.plainText);
108+
pango.angle=tp.angle;
109+
if (isfinite(tp.fontSize))
110+
pango.setFontSize(tp.fontSize);
111+
if (!tp.fontFamily.empty())
112+
pango.setFontFamily(tp.fontFamily.c_str());
113+
}
114+
115+
void CairoShimCairo::showText(const TextProperties& tp) const
116+
{
117+
if (tp.markup.empty() && tp.plainText.empty()) return;
118+
Pango pango(cairo);
119+
initPango(pango,tp);
120+
pango.show();
121+
}
109122

110-
void CairoShimCairo::textExtents(const std::string& text, cairo_text_extents_t& extents) const
111-
{cairo_text_extents(cairo,text.c_str(),&extents);}
123+
TextExtents CairoShimCairo::textExtents(const TextProperties& tp) const
124+
{
125+
Pango pango(cairo);
126+
initPango(pango,tp);
127+
return {pango.left(), pango.top(), pango.width(), pango.height()};
128+
}
112129

113130
// Transformation operations
114131
void CairoShimCairo::identityMatrix() const
@@ -137,18 +154,6 @@ namespace minsky
137154
void CairoShimCairo::setTolerance(double tolerance) const
138155
{cairo_set_tolerance(cairo, tolerance);}
139156

140-
// Pango support
141-
ecolab::Pango& CairoShimCairo::pango() const
142-
{
143-
if (!m_pango) newPango();
144-
return *m_pango;
145-
}
146-
ecolab::Pango& CairoShimCairo::newPango() const
147-
{
148-
m_pango.reset(new ecolab::Pango(cairo));
149-
return *m_pango;
150-
}
151-
152157
// SVG rendering support
153158
void CairoShimCairo::renderSVG(const SVGRenderer& svgRenderer, double width, double height) const
154159
{

engine/cairoShimCairo.h

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ namespace minsky
1414
class CairoShimCairo: public ICairoShim
1515
{
1616
cairo_t* cairo;
17-
mutable std::unique_ptr<ecolab::Pango> m_pango;
17+
void initPango(ecolab::Pango&,const TextProperties&) const;
1818
CairoShimCairo(const CairoShimCairo&)=delete;
1919
void operator=(const CairoShimCairo&)=delete;
2020
public:
@@ -56,10 +56,8 @@ namespace minsky
5656
void setSourceRGBA(double r, double g, double b, double a) const override;
5757

5858
// Text operations
59-
void showText(const std::string& text) const override;
60-
void setFontSize(double size) const override;
61-
void selectFontFace(const std::string& family, cairo_font_slant_t slant, cairo_font_weight_t weight) const override;
62-
void textExtents(const std::string& text, cairo_text_extents_t& extents) const override;
59+
void showText(const TextProperties& text) const override;
60+
TextExtents textExtents(const TextProperties& text) const override;
6361

6462
// Transformation operations
6563
void identityMatrix() const override;
@@ -75,15 +73,13 @@ namespace minsky
7573
// Tolerance
7674
void setTolerance(double tolerance) const override;
7775

78-
// Pango support
79-
ecolab::Pango& pango() const override;
80-
ecolab::Pango& newPango() const override;
81-
8276
// SVG rendering support
8377
void renderSVG(const SVGRenderer& svgRenderer, double width, double height) const override;
8478

8579
// TEMPORARY: Internal accessor for migration - to be removed once all implementations are updated
8680
cairo_t* _internalGetCairoContext() const { return cairo; }
81+
82+
void* context() const override {return cairo;}
8783
};
8884

8985
}

model/ICairoShim.h

Lines changed: 101 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -20,91 +20,162 @@
2020
#ifndef ICAIROSHIM_H
2121
#define ICAIROSHIM_H
2222

23+
#include <cmath>
24+
#include <memory>
2325
#include <string>
2426
#include <cairo.h>
2527

26-
// Forward declarations
27-
namespace ecolab { class Pango; }
28-
2928
namespace minsky
3029
{
3130
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+
};
3274

3375
/// Abstract interface for Cairo drawing operations
3476
class ICairoShim
3577
{
3678
public:
3779
virtual ~ICairoShim() = default;
3880

39-
// Drawing operations
81+
/// @{ Drawing operations
4082
virtual void moveTo(double x, double y) const = 0;
4183
virtual void lineTo(double x, double y) const = 0;
4284
virtual void relMoveTo(double x, double y) const = 0;
4385
virtual void relLineTo(double x, double y) const = 0;
4486
virtual void arc(double x, double y, double radius, double start, double end) const = 0;
4587
virtual void curveTo(double x1, double y1, double x2, double y2, double x3, double y3) const = 0;
4688
virtual void rectangle(double x, double y, double width, double height) const = 0;
47-
48-
// Path operations
89+
/// @}
90+
91+
/// @{ Path operations
4992
virtual void newPath() const = 0;
5093
virtual void newSubPath() const = 0;
5194
virtual void closePath() const = 0;
5295
virtual void getCurrentPoint(double& x, double& y) const = 0;
53-
54-
// Fill and stroke operations
96+
/// @}
97+
98+
/// @{ Fill and stroke operations
5599
virtual void fill() const = 0;
56100
virtual void fillPreserve() const = 0;
57101
virtual void stroke() const = 0;
58102
virtual void strokePreserve() const = 0;
59103
virtual void clip() const = 0;
60104
virtual void resetClip() const = 0;
61105
virtual void paint() const = 0;
62-
63-
// Line properties
106+
/// @}
107+
108+
/// @{ Line properties
64109
virtual void setLineWidth(double width) const = 0;
65110
virtual double getLineWidth() const = 0;
66111
virtual void setDash(const double* dashes, int num_dashes, double offset) const = 0;
67112
virtual void setFillRule(cairo_fill_rule_t fill_rule) const = 0;
68-
69-
// Color operations
113+
/// @}
114+
115+
/// @{ Color operations
70116
virtual void setSourceRGB(double r, double g, double b) const = 0;
71117
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
80134
virtual void identityMatrix() const = 0;
81135
virtual void translate(double x, double y) const = 0;
82136
virtual void scale(double sx, double sy) const = 0;
83137
virtual void rotate(double angle) const = 0;
84138
virtual void userToDevice(double& x, double& y) const = 0;
85-
86-
// Context state operations
139+
/// @}
140+
141+
/// @{ Context state operations
87142
virtual void save() const = 0;
88143
virtual void restore() const = 0;
89-
90-
// Tolerance
144+
/// @}
145+
146+
/// Tolerance
91147
virtual void setTolerance(double tolerance) const = 0;
92148

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-
99149
// SVG rendering support
100150
/// Render an SVG resource into a region of size width x height
101151
/// @param svgRenderer - Reference to SVGRenderer containing the loaded SVG resource
102152
/// @param width - target width for rendering
103153
/// @param height - target height for rendering
104154
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);}
105162
};
106163

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+
};
107171

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+
108179
}
109180

110181
#include "ICairoShim.xcd"

model/cairoItems.cc

Lines changed: 23 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@
2828
#include "minsky.h"
2929

3030
#include "cairoItems.h"
31-
#include "../engine/cairoShimCairo.h"
31+
#include "cairoShimCairo.h"
3232
#include "operation.h"
3333
#include "latexMarkup.h"
3434
#include <arrays.h>
@@ -46,47 +46,51 @@ using namespace boost::geometry;
4646

4747
namespace
4848
{
49+
// for use when calculating bounding boxes, but not drawing to anything?
4950
cairo::Surface dummySurf(cairo_image_surface_create(CAIRO_FORMAT_A1, 100,100));
51+
CairoShimCairo dummyCairoShim(dummySurf.cairo());
5052
}
5153

52-
RenderVariable::RenderVariable(const VariableBase& var, cairo_t* cairo):
53-
Pango(cairo? cairo: dummySurf.cairo()), var(var), cairo(cairo)
54+
RenderVariable::RenderVariable(const VariableBase& var, const ICairoShim& shim):
55+
var(var), cairoShim(shim), m_context(cairoShim.context())
5456
{
55-
setFontSize(12);
57+
TextProperties textProperties;
58+
textProperties.fontSize=12;
5659
if (var.type()==VariableType::constant)
5760
{
5861
try
5962
{
6063
auto val=var.engExp();
6164
if (val.engExp==-3) val.engExp=0; //0.001-1.0
62-
setMarkup(var.mantissa(val)+expMultiplier(val.engExp));
65+
textProperties.markup=var.mantissa(val)+expMultiplier(val.engExp);
6366
}
6467
catch (const std::exception& ex)
6568
{
66-
setMarkup("0");
69+
textProperties.markup="0";
6770
}
68-
w=0.5*Pango::width();
69-
h=0.5*Pango::height();
71+
auto bbox=shim.textExtents(textProperties);
72+
w=0.5*bbox.width;
73+
h=0.5*bbox.height;
74+
hoffs=bbox.top;
7075
}
7176
else
7277
{
73-
setMarkup(latexToPango(var.name()));
74-
w=0.5*Pango::width();
75-
h=0.5*Pango::height();
78+
textProperties.markup=latexToPango(var.name());
79+
auto bbox=shim.textExtents(textProperties);
80+
w=0.5*bbox.width;
81+
h=0.5*bbox.height;
7682
if (!var.ioVar())
77-
{ // add additional space for numerical display
78-
w+=12;
83+
{ // add additional space for numerical display
84+
w+=12;
7985
h+=4;
8086
}
87+
hoffs=bbox.top;
8188
}
82-
hoffs=Pango::top();
89+
cachedRenderer=cairoShim.cachedRender(textProperties);
8390
}
8491

85-
void RenderVariable::draw()
86-
{
87-
CairoShimCairo shim(cairo);
88-
var.draw(shim);
89-
}
92+
RenderVariable::RenderVariable(const VariableBase& var):
93+
RenderVariable(var, dummyCairoShim) {}
9094

9195
bool RenderVariable::inImage(float x, float y)
9296
{

0 commit comments

Comments
 (0)