1 /*
2   Copyright 2008        Brad Hards  <bradh@frogmouth.net>
3   Copyright 2009 - 2010 Inge Wallin <inge@lysator.liu.se>
4 
5   This library is free software; you can redistribute it and/or
6   modify it under the terms of the GNU Lesser General Public
7   License as published by the Free Software Foundation; either
8   version 2.1 of the License, or (at your option) any later version.
9 
10   This library is distributed in the hope that it will be useful,
11   but WITHOUT ANY WARRANTY; without even the implied warranty of
12   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13   Lesser General Public License for more details.
14 
15   You should have received a copy of the GNU Lesser General Public
16   License along with this library.  If not, see <http://www.gnu.org/licenses/>.
17 */
18 
19 #ifndef EMFOUTPUTPAINTERSTRATEGY_H
20 #define EMFOUTPUTPAINTERSTRATEGY_H
21 
22 #include "kovectorimage_export.h"
23 
24 #include <QList>
25 #include <QPainter>
26 #include <QRect> // also provides QSize, QPoint
27 #include <QString>
28 #include <QVariant>
29 
30 #include "EmfEnums.h"
31 #include "EmfHeader.h"
32 #include "EmfRecords.h"
33 #include "EmfOutput.h"
34 
35 
36 /**
37    \file
38 
39    Primary definitions for EMF output strategies
40 */
41 
42 /**
43    Namespace for Enhanced Metafile (EMF) classes
44 */
45 namespace Libemf
46 {
47 
48 class EmrTextObject;
49 
50 /**
51     QPainter based output strategy for EMF Parser.
52 
53     This class allows rendering of an EMF file to a QPixmap or any other QPaintDevice.
54 */
55 class KOVECTORIMAGE_EXPORT OutputPainterStrategy : public AbstractOutput
56 {
57 public:
58     /**
59        Constructor.
60 
61        This will probably need to take an enum to say what sort of output
62        we want.
63     */
64     OutputPainterStrategy();
65     OutputPainterStrategy( QPainter &painter, QSize &size,
66                            bool keepAspectRatio = false );
67     ~OutputPainterStrategy() override;
68 
69     void init( const Header *header ) override;
70     void cleanup( const Header *header ) override;
71     void eof() override;
72 
73     /**
74        The image that has been rendered to.
75     */
76     QImage *image();
77 
78     void createPen( quint32 ihPen, quint32 penStyle, quint32 x, quint32 y,
79 		    quint8 red, quint8 green, quint8 blue, quint8 reserved ) override;
80     void createBrushIndirect( quint32 ihBrush, quint32 BrushStyle, quint8 red,
81 			      quint8 green, quint8 blue, quint8 reserved,
82 			      quint32 BrushHatch ) override;
83     void createMonoBrush( quint32 ihBrush, Bitmap *bitmap ) override;
84     void selectObject( const quint32 ihObject ) override;
85     void deleteObject( const quint32 ihObject ) override;
86     void arc( const QRect &box, const QPoint &start, const QPoint &end ) override;
87     void chord( const QRect &box, const QPoint &start, const QPoint &end ) override;
88     void pie( const QRect &box, const QPoint &start, const QPoint &end ) override;
89     void ellipse( const QRect &box ) override;
90     void rectangle( const QRect &box ) override;
91     void setMapMode( const quint32 mapMode ) override;
92     void setMetaRgn() override;
93     void setWindowOrgEx( const QPoint &origin ) override;
94     void setWindowExtEx( const QSize &size ) override;
95     void setViewportOrgEx( const QPoint &origin ) override;
96     void setViewportExtEx( const QSize &size ) override;
97     void beginPath() override;
98     void closeFigure() override;
99     void endPath() override;
100     void setBkMode( const quint32 backgroundMode ) override;
101     void setPolyFillMode( const quint32 polyFillMode ) override;
102     void setLayout( const quint32 layoutMode ) override;
103     void extCreateFontIndirectW( const ExtCreateFontIndirectWRecord &extCreateFontIndirectW ) override;
104     void setTextAlign( const quint32 textAlignMode ) override;
105     void setTextColor( const quint8 red, const quint8 green, const quint8 blue,
106 		       const quint8 reserved ) override;
107     void setBkColor( const quint8 red, const quint8 green, const quint8 blue,
108                      const quint8 reserved ) override;
109     void setPixelV( QPoint &point, quint8 red, quint8 green, quint8 blue, quint8 reserved ) override;
110     void modifyWorldTransform( quint32 mode, float M11, float M12,
111 			       float M21, float M22, float Dx, float Dy ) override;
112     void setWorldTransform( float M11, float M12, float M21,
113 			    float M22, float Dx, float Dy ) override;
114     void extTextOut( const QRect &bounds, const EmrTextObject &textObject ) override;
115     void moveToEx( const qint32 x, const qint32 y ) override;
116     void saveDC() override;
117     void restoreDC( const qint32 savedDC ) override;
118     void lineTo( const QPoint &finishPoint ) override;
119     void arcTo( const QRect &box, const QPoint &start, const QPoint &end ) override;
120     void polygon16( const QRect &bounds, const QList<QPoint> points ) override;
121     void polyLine16( const QRect &bounds, const QList<QPoint> points ) override;
122     void polyPolygon16( const QRect &bounds, const QList< QVector< QPoint > > &points ) override;
123     void polyPolyLine16( const QRect &bounds, const QList< QVector< QPoint > > &points ) override;
124     void polyLine( const QRect &bounds, const QList<QPoint> points ) override;
125     void polyLineTo16( const QRect &bounds, const QList<QPoint> points ) override;
126     void polyBezier16( const QRect &bounds, const QList<QPoint> points ) override;
127     void polyBezierTo16( const QRect &bounds, const QList<QPoint> points ) override;
128     void fillPath( const QRect &bounds ) override;
129     void strokeAndFillPath( const QRect &bounds ) override;
130     void strokePath( const QRect &bounds ) override;
131     void setClipPath( const quint32 regionMode ) override;
132     void bitBlt( BitBltRecord &bitBltRecord ) override;
133     void setStretchBltMode( const quint32 stretchMode ) override;
134     void stretchDiBits( StretchDiBitsRecord &stretchDiBitsRecord ) override;
135 
136 private:
137     void printPainterTransform(const char *leadText);
138 
139     /// For debugging purposes: Draw the boundary box.
140     void paintBounds(const Header *header);
141 
142     /// Recalculate the world transform and then apply it to the painter
143     /// This must be called at the end of every function that changes the transform.
144     void recalculateWorldTransform();
145 
146     /**
147        Select a stock object.
148 
149        See [MS-EMF] Section 2.1.31.
150 
151        \param ihObject the stock object value
152     */
153     void selectStockObject( const quint32 ihObject );
154 
155 
156     /**
157        Helper routine to convert the EMF angle (centrepoint + radial endpoint) into
158        the Qt format (in degress - may need to multiply by 16 for some purposes)
159     */
160     qreal angleFromArc( const QPoint &centrePoint, const QPoint &radialPoint );
161 
162     /**
163       Calculate the angular difference (span) between two angles
164 
165       This should always be positive.
166     */
167     qreal angularSpan( const qreal startAngle, const qreal endAngle );
168 
169     /**
170        Convert the EMF font weight scale (0..1000) to Qt equivalent.
171 
172        This is a bit rough - the EMF spec only says 400 is normal, and
173        700 is bold.
174     */
175     int convertFontWeight( quint32 emfWeight );
176 
177 
178     Header                  *m_header;   // Save to be able to retain scaling.
179 
180     int                      m_painterSaves; // The number of times that save() was called.
181     QSize                    m_outputSize;
182     bool                     m_keepAspectRatio;
183 
184     QMap<quint32, QVariant>  m_objectTable;
185 
186     QPainterPath *m_path;
187     bool          m_currentlyBuildingPath;
188 
189     QPainter                *m_painter;
190     QTransform               m_worldTransform; // The transform inside the EMF.
191     QTransform               m_outputTransform; // The transform that the painter already had
192     qreal                    m_outputScale;
193 
194     // Everything that has to do with window and viewport calculation
195     QPoint        m_windowOrg;
196     QSize         m_windowExt;
197     QPoint        m_viewportOrg;
198     QSize         m_viewportExt;
199     bool          m_windowExtIsSet;
200     bool          m_viewportExtIsSet;
201     bool          m_windowViewportIsSet;
202 
203 #if 0
204     // This matrix is needed because the window / viewport calculation
205     // is not the last one in the chain. After that one comes the
206     // transform that the painter already has when the painting
207     // starts, and that one has to be saved and reapplied again after
208     // the window / viewport calculation is redone.
209     QTransform    m_outputTransform;
210 #endif
211 
212     // ----------------------------------------------------------------
213     //                     The playback device context
214 
215     // The Playback Device Context (PDC) contains the following:
216     //  - bitmap
217     //  - brush	(part of the painter)
218     //  - palette
219     //  - font	(part of the painter)
220     //  - pen	(part of the painter)
221     //  - region
222     //  - drawing mode
223     //  - mapping mode
224     // FIXME: what more?  textalign?  textpen?
225 
226     /**
227        The current text pen
228     */
229     QPen m_textPen;
230 
231     /**
232        The current fill rule
233     */
234     enum Qt::FillRule m_fillRule;
235 
236     /**
237        The current map mode
238     */
239     MapMode  m_mapMode;
240     /**
241         The current text alignment mode
242     */
243     quint32 m_textAlignMode;
244 
245     /**
246        The current coordinates
247     */
248     QPoint  m_currentCoords;
249 };
250 
251 }
252 
253 #endif
254