forked from Kitware/VTK
-
Notifications
You must be signed in to change notification settings - Fork 0
/
vtkSVGContextDevice2D.h
288 lines (246 loc) · 10.8 KB
/
vtkSVGContextDevice2D.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
/*=========================================================================
Program: Visualization Toolkit
Module: vtkSVGContextDevice2D.h
Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
All rights reserved.
See Copyright.txt or http://www.kitware.com/Copyright.htm for details.
This software is distributed WITHOUT ANY WARRANTY; without even
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE. See the above copyright notice for more information.
=========================================================================*/
/**
* @class vtkSVGContextDevice2D
* @brief vtkContextDevice2D implementation for use with vtkSVGExporter.
*
* Limitations:
* - The Nearest/Linear texture properties are ignored, since SVG doesn't
* provide any reliable control over interpolation.
* - Embedded fonts are experimental and poorly tested. Viewer support is
* lacking at the time of writing, hence the feature is largely useless. By
* default, fonts are not embedded since they're basically useless bloat.
* - TextAsPath is enabled by default, since viewers differ wildly in how they
* handle text objects (eg. Inkscape renders at expected size, but webkit is
* way too big).
* - Pattern fills and markers are not shown on some viewers, e.g. KDE's okular
* (Webkit seems to work, though).
* - Clipping seems to be broken in most viewers. Webkit is buggy and forces the
* clip coordinates to objectBoundingBox, even when explicitly set to
* userSpaceOnUse.
* - Many viewers anti-alias the output, leaving thin outlines around the
* triangles that make up larger polygons. This is a viewer issue and there
* not much we can do about it from the VTK side of things (and most viewers
* don't seem to have an antialiasing toggle, either...).
*/
#ifndef vtkSVGContextDevice2D_h
#define vtkSVGContextDevice2D_h
#include "vtkIOExportModule.h" // For export macro
#include "vtkContextDevice2D.h"
#include "vtkNew.h" // For vtkNew!
#include <array> // For std::array!
class vtkColor3ub;
class vtkColor4ub;
class vtkPath;
class vtkRenderer;
class vtkTransform;
class vtkVector3f;
class vtkXMLDataElement;
class VTKIOEXPORT_EXPORT vtkSVGContextDevice2D: public vtkContextDevice2D
{
public:
static vtkSVGContextDevice2D* New();
vtkTypeMacro(vtkSVGContextDevice2D, vtkContextDevice2D)
void PrintSelf(ostream &os, vtkIndent indent) override;
/** The svg container element to draw into, and the global definitions
* element. */
void SetSVGContext(vtkXMLDataElement *context,
vtkXMLDataElement *defs);
/**
* EXPERIMENTAL: If true, the font glyph information will be embedded in the
* output. Default is false.
*
* @note This feature is experimental and not well tested, as most browsers
* and SVG viewers do not support rendering embedded fonts. As such, enabling
* this option typically just increases file size for no real benefit.
*
* @{
*/
vtkSetMacro(EmbedFonts, bool)
vtkGetMacro(EmbedFonts, bool)
vtkBooleanMacro(EmbedFonts, bool)
/**@}*/
/**
* If true, draw all text as path objects rather than text objects. Enabling
* this option will:
*
* - Improve portability (text will look exactly the same everywhere).
* - Increase file size (text objects are much more compact than paths).
* - Prevent text from being easily edited (text metadata is lost).
*
* Note that some text (e.g. MathText) is always rendered as a path.
*
* The default is true, as many browsers and SVG viewers render text objects
* inconsistently.
*
* @{
*/
vtkSetMacro(TextAsPath, bool)
vtkGetMacro(TextAsPath, bool)
vtkBooleanMacro(TextAsPath, bool)
/**@}*/
/**
* Set the threshold for subdividing gradient-shaded polygons/line. Default
* value is 1, and lower values yield higher quality and larger files. Larger
* values will reduce the number of primitives, but will decrease quality.
*
* A triangle / line will not be subdivided further if all of it's vertices
* satisfy the equation:
*
* |v1 - v2|^2 < thresh
*
* e.g. the squared norm of the vector between any verts must be greater than
* the threshold for subdivision to occur.
*
* @{
*/
vtkSetMacro(SubdivisionThreshold, float)
vtkGetMacro(SubdivisionThreshold, float)
/**@}*/
/**
* Write any definition information (fonts, images, etc) that are accumulated
* between actors.
*/
void GenerateDefinitions();
void Begin(vtkViewport*) override;
void End() override;
void DrawPoly(float *points, int n, unsigned char *colors = nullptr,
int nc_comps = 0) override;
void DrawLines(float *f, int n, unsigned char *colors = nullptr,
int nc_comps = 0) override;
void DrawPoints(float *points, int n, unsigned char* colors = nullptr,
int nc_comps = 0) override;
void DrawPointSprites(vtkImageData *sprite, float *points, int n,
unsigned char *colors = nullptr,
int nc_comps = 0) override;
void DrawMarkers(int shape, bool highlight, float *points, int n,
unsigned char *colors = nullptr, int nc_comps = 0) override;
void DrawQuad(float *, int) override;
void DrawQuadStrip(float *, int) override;
void DrawPolygon(float *, int) override;
void DrawColoredPolygon(float *points, int numPoints,
unsigned char *colors = nullptr,
int nc_comps = 0) override;
void DrawEllipseWedge(float x, float y, float outRx, float outRy,
float inRx, float inRy, float startAngle,
float stopAngle) override;
void DrawEllipticArc(float x, float y, float rX, float rY,
float startAngle, float stopAngle) override;
void DrawString(float *point, const vtkStdString &string) override;
void ComputeStringBounds(const vtkStdString &string,
float bounds[4]) override;
void DrawString(float *point, const vtkUnicodeString &string) override;
void ComputeStringBounds(const vtkUnicodeString &string,
float bounds[4]) override;
void ComputeJustifiedStringBounds(const char* string,
float bounds[4]) override;
void DrawMathTextString(float *point, const vtkStdString &str) override;
void DrawImage(float p[2], float scale, vtkImageData *image) override;
void DrawImage(const vtkRectf& pos, vtkImageData *image) override;
void SetColor4(unsigned char color[4]) override;
void SetTexture(vtkImageData* image, int properties) override;
void SetPointSize(float size) override;
void SetLineWidth(float width) override;
void SetLineType(int type) override;
void SetMatrix(vtkMatrix3x3 *m) override;
void GetMatrix(vtkMatrix3x3 *m) override;
void MultiplyMatrix(vtkMatrix3x3 *m) override;
void PushMatrix() override;
void PopMatrix() override;
void SetClipping(int *x) override;
void EnableClipping(bool enable) override;
protected:
vtkSVGContextDevice2D();
~vtkSVGContextDevice2D() override;
void SetViewport(vtkViewport*);
void PushGraphicsState();
void PopGraphicsState();
// Apply clipping and transform information current active node.
void SetupClippingAndTransform();
// pen -> stroke state
void ApplyPenStateToNode(vtkXMLDataElement *node);
void ApplyPenColorToNode(vtkXMLDataElement *node);
void ApplyPenOpacityToNode(vtkXMLDataElement *node);
void ApplyPenWidthToNode(vtkXMLDataElement *node);
void ApplyPenStippleToNode(vtkXMLDataElement *node);
// pen -> fill state
void ApplyPenAsFillColorToNode(vtkXMLDataElement *node);
void ApplyPenAsFillOpacityToNode(vtkXMLDataElement *node);
// brush -> fill state
void ApplyBrushStateToNode(vtkXMLDataElement *node);
void ApplyBrushColorToNode(vtkXMLDataElement *node);
void ApplyBrushOpacityToNode(vtkXMLDataElement *node);
void ApplyBrushTextureToNode(vtkXMLDataElement *node);
// tprop --> text state
void ApplyTextPropertyStateToNode(vtkXMLDataElement *node, float x, float y);
void ApplyTextPropertyStateToNodeForPath(vtkXMLDataElement *node,
float x, float y);
void ApplyTransform();
// Add marker symbols to defs, return symbol id.
std::string AddCrossSymbol(bool highlight);
std::string AddPlusSymbol(bool highlight);
std::string AddSquareSymbol(bool highlight);
std::string AddCircleSymbol(bool highlight);
std::string AddDiamondSymbol(bool highlight);
void DrawPath(vtkPath *path, std::ostream &out);
void DrawLineGradient(const vtkVector2f &p1, const vtkColor4ub &c1,
const vtkVector2f &p2, const vtkColor4ub &c2,
bool useAlpha);
void DrawTriangleGradient(const vtkVector2f &p1, const vtkColor4ub &c1,
const vtkVector2f &p2, const vtkColor4ub &c2,
const vtkVector2f &p3, const vtkColor4ub &c3,
bool useAlpha);
// Used by the Draw*Gradient methods to prevent subdividing triangles / lines
// that are already really small.
bool AreaLessThanTolerance(const vtkVector2f &p1,
const vtkVector2f &p2,
const vtkVector2f &p3);
bool LengthLessThanTolerance(const vtkVector2f &p1,
const vtkVector2f &p2);
bool ColorsAreClose(const vtkColor4ub &c1, const vtkColor4ub &c2,
bool useAlpha);
bool ColorsAreClose(const vtkColor4ub &c1, const vtkColor4ub &c2,
const vtkColor4ub &c3, bool useAlpha);
void WriteFonts();
void WriteImages();
void WritePatterns();
void WriteClipRects();
void AdjustMatrixForSVG(const double in[9], double out[9]);
void GetSVGMatrix(double svg[9]);
static bool Transform2DEqual(const double mat3[9], const double mat4[16]);
static void Matrix3ToMatrix4(const double mat3[9], double mat4[16]);
static void Matrix4ToMatrix3(const double mat4[16], double mat3[9]);
float GetScaledPenWidth();
void GetScaledPenWidth(float &x, float &y);
void TransformSize(float &x, float &y);
vtkImageData* PreparePointSprite(vtkImageData *in);
struct Details;
Details *Impl;
vtkViewport *Viewport;
vtkXMLDataElement *ContextNode;
vtkXMLDataElement *ActiveNode;
vtkXMLDataElement *DefinitionNode;
// This is a 3D transform, the 2D version doesn't support push/pop.
vtkNew<vtkTransform> Matrix;
std::array<double, 9> ActiveNodeTransform;
std::array<int, 4> ClipRect; // x, y, w, h
std::array<int, 4> ActiveNodeClipRect; // x, y, w, h
float CanvasHeight; // Used in y coordinate conversions.
float SubdivisionThreshold;
bool IsClipping;
bool ActiveNodeIsClipping;
bool EmbedFonts;
bool TextAsPath;
private:
vtkSVGContextDevice2D(const vtkSVGContextDevice2D&) = delete;
void operator=(const vtkSVGContextDevice2D&) = delete;
};
#endif // vtkSVGContextDevice2D_h