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
|
/*=========================================================================
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 "vtkContextDevice2D.h"
#include "vtkIOExportModule.h" // For export macro
#include "vtkNew.h" // For vtkNew!
#include <array> // For std::array!
VTK_ABI_NAMESPACE_BEGIN
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 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;
};
VTK_ABI_NAMESPACE_END
#endif // vtkSVGContextDevice2D_h
|