1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /** @file
3  * @brief Windows Metafile Input/Output
4  */
5 /* Authors:
6  *   Ulf Erikson <ulferikson@users.sf.net>
7  *
8  * Copyright (C) 2006-2008 Authors
9  *
10  * Released under GNU GPL v2+, read the file 'COPYING' for more information.
11  */
12 #ifndef SEEN_EXTENSION_INTERNAL_WMF_H
13 #define SEEN_EXTENSION_INTERNAL_WMF_H
14 
15 #include <3rdparty/libuemf/uwmf.h>
16 #include "extension/internal/metafile-inout.h"  // picks up PNG
17 #include "extension/implementation/implementation.h"
18 #include "style.h"
19 #include "text_reassemble.h"
20 
21 namespace Inkscape {
22 namespace Extension {
23 namespace Internal {
24 
25 #define DIRTY_NONE   0x00
26 #define DIRTY_TEXT   0x01
27 #define DIRTY_FILL   0x02
28 #define DIRTY_STROKE 0x04 // not used currently
29 
30 struct WMF_OBJECT {
31     int type = 0;
32     int level = 0;
33     char *record = nullptr;
34 };
35 using PWMF_OBJECT = WMF_OBJECT *;
36 
37 struct WMF_STRINGS {
38     int size = 0;               // number of slots allocated in strings
39     int count = 0;              // number of slots used in strings
40     char **strings = nullptr;   // place to store strings
41 };
42 using PWMF_STRINGS = WMF_STRINGS *;
43 
44 struct WMF_DEVICE_CONTEXT {
WMF_DEVICE_CONTEXTWMF_DEVICE_CONTEXT45     WMF_DEVICE_CONTEXT() :
46         // SPStyle: class with constructor
47         font_name(nullptr),
48         clip_id(0),
49         stroke_set(false), stroke_mode(0), stroke_idx(0), stroke_recidx(0),
50         fill_set(false),   fill_mode(0),   fill_idx(0),   fill_recidx(0),
51         dirty(0),
52         active_pen(-1), active_brush(-1), active_font(-1),  // -1 when the default is used
53         // sizeWnd, sizeView, winorg, vieworg,
54         ScaleInX(0), ScaleInY(0),
55         ScaleOutX(0), ScaleOutY(0),
56         bkMode(U_TRANSPARENT),
57         // bkColor, textColor
58         textAlign(0)
59         // worldTransform, cur
60     {
61         font_name = nullptr;
62         sizeWnd = point16_set( 0.0, 0.0 );
63         sizeView = point16_set( 0.0, 0.0 );
64         winorg = point16_set( 0.0, 0.0 );
65         vieworg = point16_set( 0.0, 0.0 );
66         bkColor = U_RGB(255, 255, 255); // default foreground color (white)
67         textColor = U_RGB(0, 0, 0);     // default foreground color (black)
68         cur = point16_set( 0.0, 0.0 );
69     };
70     SPStyle         style;
71     char           *font_name;
72     int             clip_id;      // 0 if none, else 1 + index into clips
73     bool            stroke_set;
74     int             stroke_mode;  // enumeration from drawmode, not used if fill_set is not True
75     int             stroke_idx;   // used with DRAW_PATTERN and DRAW_IMAGE to return the appropriate fill
76     int             stroke_recidx;// record used to regenerate hatch when it needs to be redone due to bkmode, textmode, etc. change
77     bool            fill_set;
78     int             fill_mode;    // enumeration from drawmode, not used if fill_set is not True
79     int             fill_idx;     // used with DRAW_PATTERN and DRAW_IMAGE to return the appropriate fill
80     int             fill_recidx;  // record used to regenerate hatch when it needs to be redone due to bkmode, textmode, etc. change
81     int             dirty;        // holds the dirty bits for text, stroke, fill
82     int             active_pen;   // used when the active object is deleted to set the default values, -1 is none active
83     int             active_brush; // ditto
84     int             active_font;  // ditto. also used to hold object number in case font needs to be remade due to textcolor change.
85     U_POINT16       sizeWnd;
86     U_POINT16       sizeView;
87     U_POINT16       winorg;
88     U_POINT16       vieworg;
89     double          ScaleInX, ScaleInY;
90     double          ScaleOutX, ScaleOutY;
91     uint16_t        bkMode;
92     U_COLORREF      bkColor;
93     U_COLORREF      textColor;
94     uint16_t        textAlign;
95     U_POINT16       cur;
96 };
97 using PWMF_DEVICE_CONTEXT = WMF_DEVICE_CONTEXT *;
98 
99 #define WMF_MAX_DC 128
100 
101 
102 // like this causes a mysterious crash on the return from Wmf::open
103 //typedef struct emf_callback_data {
104 // this fixes it, so some confusion between this struct and the one in emf-inout???
105 //typedef struct wmf_callback_data {
106 // as does this
107 struct WMF_CALLBACK_DATA {
108 
WMF_CALLBACK_DATAWMF_CALLBACK_DATA109     WMF_CALLBACK_DATA() :
110         // dc: array, structure w/ constructor
111         level(0),
112         E2IdirY(1.0),
113         D2PscaleX(1.0), D2PscaleY(1.0),
114         PixelsInX(0), PixelsInY(0),
115         PixelsOutX(0), PixelsOutY(0),
116         ulCornerInX(0), ulCornerInY(0),
117         ulCornerOutX(0), ulCornerOutY(0),
118         mask(0),
119         arcdir(U_AD_COUNTERCLOCKWISE),
120         dwRop2(U_R2_COPYPEN), dwRop3(0),
121         id(0), drawtype(0),
122         // hatches, images, gradients,  struct w/ constructor
123         tri(nullptr),
124         n_obj(0),
125         low_water(0)
126         //wmf_obj
127     {};
128 
129     Glib::ustring outsvg;
130     Glib::ustring path;
131     Glib::ustring outdef;
132     Glib::ustring defs;
133 
134     WMF_DEVICE_CONTEXT dc[WMF_MAX_DC+1]; // FIXME: This should be dynamic..
135     int level;
136 
137     double E2IdirY;                     // WMF Y direction relative to Inkscape Y direction.  Will be negative for MM_LOMETRIC etc.
138     double D2PscaleX,D2PscaleY;         // WMF device to Inkscape Page scale.
139     float  PixelsInX, PixelsInY;        // size of the drawing, in WMF device pixels
140     float  PixelsOutX, PixelsOutY;      // size of the drawing, in Inkscape pixels
141     double ulCornerInX,ulCornerInY;     // Upper left corner, from header rclBounds, in logical units
142     double ulCornerOutX,ulCornerOutY;   // Upper left corner, in Inkscape pixels
143     uint32_t mask;                      // Draw properties
144     int arcdir;                         // U_AD_COUNTERCLOCKWISE 1 or U_AD_CLOCKWISE 2
145 
146     uint32_t dwRop2;                    // Binary raster operation, 0 if none (use brush/pen unmolested)
147     uint32_t dwRop3;                    // Ternary raster operation, 0 if none (use brush/pen unmolested)
148 
149     unsigned int id;
150     unsigned int drawtype;    // one of 0 or U_WMR_FILLPATH, U_WMR_STROKEPATH, U_WMR_STROKEANDFILLPATH
151                               // both of these end up in <defs> under the names shown here.  These structures allow duplicates to be avoided.
152     WMF_STRINGS hatches;      // hold pattern names, all like WMFhatch#_$$$$$$ where # is the WMF hatch code and $$$$$$ is the color
153     WMF_STRINGS images;       // hold images, all like Image#, where # is the slot the image lives.
154     WMF_STRINGS clips;        // hold clipping paths, referred to be the slot where the clipping path lives
155     TR_INFO    *tri;          // Text Reassembly data structure
156 
157 
158     int n_obj;
159     int low_water;            // first object slot which _might_ be unoccupied.  Everything below is filled.
160     PWMF_OBJECT wmf_obj;
161 };
162 using PWMF_CALLBACK_DATA = WMF_CALLBACK_DATA *;
163 
164 class Wmf : public Metafile
165 {
166 
167 public:
168     Wmf(); // Empty constructor
169 
170     ~Wmf() override;//Destructor
171 
172     bool check(Inkscape::Extension::Extension *module) override; //Can this module load (always yes for now)
173 
174     void save(Inkscape::Extension::Output *mod, // Save the given document to the given filename
175               SPDocument *doc,
176               gchar const *filename) override;
177 
178     SPDocument *open( Inkscape::Extension::Input *mod,
179                                 const gchar *uri ) override;
180 
181     static void init();//Initialize the class
182 
183 private:
184 protected:
185    static void        print_document_to_file(SPDocument *doc, const gchar *filename);
186    static double      current_scale(PWMF_CALLBACK_DATA d);
187    static std::string current_matrix(PWMF_CALLBACK_DATA d, double x, double y, int useoffset);
188    static double      current_rotation(PWMF_CALLBACK_DATA d);
189    static void        enlarge_hatches(PWMF_CALLBACK_DATA d);
190    static int         in_hatches(PWMF_CALLBACK_DATA d, char *test);
191    static uint32_t    add_hatch(PWMF_CALLBACK_DATA d, uint32_t hatchType, U_COLORREF hatchColor);
192    static void        enlarge_images(PWMF_CALLBACK_DATA d);
193    static int         in_images(PWMF_CALLBACK_DATA d, char *test);
194    static uint32_t    add_dib_image(PWMF_CALLBACK_DATA d, const char *dib, uint32_t iUsage);
195    static uint32_t    add_bm16_image(PWMF_CALLBACK_DATA d, U_BITMAP16 Bm16, const char *px);
196 
197    static void        enlarge_clips(PWMF_CALLBACK_DATA d);
198    static int         in_clips(PWMF_CALLBACK_DATA d, const char *test);
199    static void        add_clips(PWMF_CALLBACK_DATA d, const char *clippath, unsigned int logic);
200 
201    static void        output_style(PWMF_CALLBACK_DATA d);
202    static double      _pix_x_to_point(PWMF_CALLBACK_DATA d, double px);
203    static double      _pix_y_to_point(PWMF_CALLBACK_DATA d, double py);
204    static double      pix_to_x_point(PWMF_CALLBACK_DATA d, double px, double py);
205    static double      pix_to_y_point(PWMF_CALLBACK_DATA d, double px, double py);
206    static double      pix_to_abs_size(PWMF_CALLBACK_DATA d, double px);
207    static std::string pix_to_xy(PWMF_CALLBACK_DATA d, double x, double y);
208    static void        select_brush(PWMF_CALLBACK_DATA d, int index);
209    static void        select_font(PWMF_CALLBACK_DATA d, int index);
210    static void        select_pen(PWMF_CALLBACK_DATA d, int index);
211    static int         insertable_object(PWMF_CALLBACK_DATA d);
212    static void        delete_object(PWMF_CALLBACK_DATA d, int index);
213    static int         insert_object(PWMF_CALLBACK_DATA d, int type, const char *record);
214    static uint32_t   *unknown_chars(size_t count);
215    static void        common_dib_to_image(PWMF_CALLBACK_DATA d, const char *dib,
216                          double dx, double dy, double dw, double dh, int sx, int sy, int sw, int sh, uint32_t iUsage);
217    static void        common_bm16_to_image(PWMF_CALLBACK_DATA d, U_BITMAP16 Bm16, const char *px,
218                          double dx, double dy, double dw, double dh, int sx, int sy, int sw, int sh);
219    static int         myMetaFileProc(const char *contents, unsigned int length, PWMF_CALLBACK_DATA d);
220    static void        free_wmf_strings(WMF_STRINGS name);
221 
222 };
223 
224 } } }  /* namespace Inkscape, Extension, Implementation */
225 
226 
227 #endif /* EXTENSION_INTERNAL_WMF_H */
228 
229 /*
230   Local Variables:
231   mode:c++
232   c-file-style:"stroustrup"
233   c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
234   indent-tabs-mode:nil
235   fill-column:99
236   End:
237 */
238 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
239