1 /*=========================================================================
2 
3   Program:   Visualization Toolkit
4   Module:    vtkPDFContextDevice2D.h
5 
6   Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
7   All rights reserved.
8   See Copyright.txt or http://www.kitware.com/Copyright.htm for details.
9 
10      This software is distributed WITHOUT ANY WARRANTY; without even
11      the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
12      PURPOSE.  See the above copyright notice for more information.
13 
14 =========================================================================*/
15 /**
16  * @class vtkPDFContextDevice2D
17  * @brief vtkContextDevice2D implementation for use with vtkPDFExporter.
18  *
19  * Quirks:
20  * - Libharu does not support RGBA images. If an alpha channel is present in any
21  *   drawn images, it will be blended into an opaque background filled with the
22  *   active Brush color to produce a flat RGB image.
23  */
24 
25 #ifndef vtkPDFContextDevice2D_h
26 #define vtkPDFContextDevice2D_h
27 
28 #include "vtkIOExportPDFModule.h" // For export macro
29 #include "vtkContextDevice2D.h"
30 #include "vtkNew.h" // For vtkNew!
31 
32 class vtkColor3ub;
33 class vtkPath;
34 class vtkRenderer;
35 class vtkTransform;
36 
37 class VTKIOEXPORTPDF_EXPORT vtkPDFContextDevice2D: public vtkContextDevice2D
38 {
39 public:
40   static vtkPDFContextDevice2D* New();
41   vtkTypeMacro(vtkPDFContextDevice2D, vtkContextDevice2D)
42   void PrintSelf(ostream &os, vtkIndent indent) override;
43 
44   /**
45    * Set the HPDF_Doc and HPDF_Page to use while exporting the scene. The
46    * type is void* to keep the libharu opaque types from leaking into headers.
47    * This function expects HPDF_Document* and HPDF_Page* as the arguments.
48    */
49   void SetHaruObjects(void *doc, void *page);
50 
51   void SetRenderer(vtkRenderer*);
52 
53   void DrawPoly(float *points, int n, unsigned char *colors = nullptr,
54                 int nc_comps = 0) override;
55   void DrawLines(float *f, int n, unsigned char *colors = nullptr,
56                  int nc_comps = 0) override;
57   void DrawPoints(float *points, int n, unsigned char* colors = nullptr,
58                   int nc_comps = 0) override;
59   void DrawPointSprites(vtkImageData *sprite, float *points, int n,
60                         unsigned char *colors = nullptr,
61                         int nc_comps = 0) override;
62   void DrawMarkers(int shape, bool highlight, float *points, int n,
63                    unsigned char *colors = nullptr, int nc_comps = 0) override;
64   void DrawQuad(float *, int) override;
65   void DrawQuadStrip(float *, int) override;
66   void DrawPolygon(float *, int) override;
67   void DrawColoredPolygon(float *points, int numPoints,
68                           unsigned char *colors = nullptr,
69                           int nc_comps = 0) override;
70   void DrawEllipseWedge(float x, float y, float outRx, float outRy,
71                         float inRx, float inRy, float startAngle,
72                         float stopAngle) override;
73   void DrawEllipticArc(float x, float y, float rX, float rY,
74                        float startAngle, float stopAngle) override;
75   void DrawString(float *point, const vtkStdString &string) override;
76   void ComputeStringBounds(const vtkStdString &string,
77                            float bounds[4]) override;
78   void DrawString(float *point, const vtkUnicodeString &string) override;
79   void ComputeStringBounds(const vtkUnicodeString &string,
80                            float bounds[4]) override;
81   void ComputeJustifiedStringBounds(const char* string,
82                                     float bounds[4]) override;
83   void DrawMathTextString(float *point, const vtkStdString &str) override;
84   void DrawImage(float p[2], float scale, vtkImageData *image) override;
85   void DrawImage(const vtkRectf& pos, vtkImageData *image) override;
86   void SetColor4(unsigned char color[4]) override;
87   void SetTexture(vtkImageData* image, int properties) override;
88   void SetPointSize(float size) override;
89   void SetLineWidth(float width) override;
90   void DrawPolyData(float p[2], float scale, vtkPolyData* polyData,
91                     vtkUnsignedCharArray* colors, int scalarMode) override;
92 
93   void SetLineType(int type) override;
94   void SetMatrix(vtkMatrix3x3 *m) override;
95   void GetMatrix(vtkMatrix3x3 *m) override;
96   void MultiplyMatrix(vtkMatrix3x3 *m) override;
97   void PushMatrix() override;
98   void PopMatrix() override;
99   void SetClipping(int *x) override;
100   void EnableClipping(bool enable) override;
101 
102 protected:
103   vtkPDFContextDevice2D();
104   ~vtkPDFContextDevice2D() override;
105 
106   void PushGraphicsState();
107   void PopGraphicsState();
108 
109   void ApplyPenState();
110   void ApplyStrokeColor(unsigned char *color, int numComps);
111   void ApplyLineWidth(float width);
112   void ApplyLineType(int type);
113   void Stroke();
114 
115   void ApplyPenStateAsFill();
116   void ApplyBrushState();
117   void ApplyTextPropertyState();
118   void ApplyFillColor(unsigned char *color, int numComps);
119   void ApplyFillAlpha(unsigned char alpha);
120   void Fill(bool stroke = false);
121   void FillEvenOdd(bool stroke = false);
122 
123   void BeginClipPathForTexture();
124   void RegisterTexturePoints(float *data, int numPoints);
125   void FillTexture();
126 
127   // converts input to RGB if needed. Call Delete() on the returned object when
128   // finished with it.
129   vtkImageData* PrepareImageData(vtkImageData *in);
130 
131   void DrawEllipticArcSegments(float x, float y, float rX, float rY,
132                                float startAngle, float stopAngle,
133                                bool startPath);
134   int GetNumberOfArcIterations(float rX, float rY,
135                                float startAngle, float stopAngle);
136 
137   void DrawCrossMarkers(bool highlight, float *points, int n,
138                         unsigned char *colors, int nc_comps);
139   void DrawPlusMarkers(bool highlight, float *points, int n,
140                        unsigned char *colors, int nc_comps);
141   void DrawSquareMarkers(bool highlight, float *points, int n,
142                          unsigned char *colors, int nc_comps);
143   void DrawCircleMarkers(bool highlight, float *points, int n,
144                          unsigned char *colors, int nc_comps);
145   void DrawDiamondMarkers(bool highlight, float *points, int n,
146                           unsigned char *colors, int nc_comps);
147 
148   void DrawPath(vtkPath *path, float x, float y);
149 
150   void ApplyTransform();
151 
152   // This is weird, but the pen width must not be affected by the transform's
153   // scaling factors. This function returns the unscaled x/y components of
154   // the pen width.
155   vtkVector2f GetUnscaledPenWidth();
156 
157   // Converts a 2D transform matrix into a 3D transform matrix, or vice versa
158   static void Matrix3ToMatrix4(vtkMatrix3x3 *mat3, double mat4[16]);
159   static void Matrix4ToMatrix3(double mat4[16], vtkMatrix3x3 *mat3);
160   static void Matrix4ToMatrix3(double mat4[16], double mat3[9]);
161 
162   // Convert a 3D transform matrix to an HPDF transformation.
163   // trans = {a, b, c, d, x, y}, which define the transform:
164   // | a b x |
165   // | c d y |
166   // | 0 0 1 |
167   static void Matrix4ToHPDFTransform(const double mat4[16], float hpdfMat[6]);
168   static void Matrix3ToHPDFTransform(const double mat4[9], float hpdfMat[6]);
169   static void HPDFTransformToMatrix3(float a, float b, float c, float d,
170                                      float x, float y, double mat3[9]);
171 
172   struct Details;
173   Details *Impl;
174 
175   // This is a 3D transform, the 2D version doesn't support push/pop.
176   vtkNew<vtkTransform> Matrix;
177 
178   vtkRenderer *Renderer;
179   float PointSize;
180   float ClipBox[4]; // x, y, w, h
181 
182   bool IsInTexturedFill;
183   float TextureBounds[4]; // xmin, xmax, ymin, ymax; used for placing textures
184 
185 private:
186   vtkPDFContextDevice2D(const vtkPDFContextDevice2D&) = delete;
187   void operator=(const vtkPDFContextDevice2D&) = delete;
188 };
189 
190 #endif // vtkPDFContextDevice2D_h
191