// SPDX-License-Identifier: GPL-2.0-or-later /** @file * @brief Enhanced Metafile Input/Output */ /* Authors: * Ulf Erikson * David Mathog * * Copyright (C) 2006-2008 Authors * * Released under GNU GPL v2+, read the file 'COPYING' for more information. */ #ifndef SEEN_EXTENSION_INTERNAL_EMF_H #define SEEN_EXTENSION_INTERNAL_EMF_H #include <3rdparty/libuemf/uemf.h> #include <3rdparty/libuemf/uemf_safe.h> #include <3rdparty/libuemf/uemf_endian.h> // for U_emf_record_sizeok() #include "extension/internal/metafile-inout.h" // picks up PNG #include "extension/implementation/implementation.h" #include "style.h" #include "text_reassemble.h" namespace Inkscape { namespace Extension { namespace Internal { #define DIRTY_NONE 0x00 #define DIRTY_TEXT 0x01 #define DIRTY_FILL 0x02 #define DIRTY_STROKE 0x04 struct EMF_OBJECT { int type = 0; int level = 0; char *lpEMFR = nullptr; }; using PEMF_OBJECT = EMF_OBJECT *; struct EMF_STRINGS { int size = 0; // number of slots allocated in strings int count = 0; // number of slots used in strings char **strings = nullptr; // place to store strings }; using PEMF_STRINGS = EMF_STRINGS *; struct EMF_DEVICE_CONTEXT { EMF_DEVICE_CONTEXT() : // SPStyle: class with constructor font_name(nullptr), clip_id(0), stroke_set(false), stroke_mode(0), stroke_idx(0), stroke_recidx(0), fill_set(false), fill_mode(0), fill_idx(0), fill_recidx(0), dirty(0), // sizeWnd, sizeView, winorg, vieworg, ScaleInX(0), ScaleInY(0), ScaleOutX(0), ScaleOutY(0), bkMode(U_TRANSPARENT), // bkColor, textColor textAlign(0) // worldTransform, cur { sizeWnd = sizel_set( 0.0, 0.0 ); sizeView = sizel_set( 0.0, 0.0 ); winorg = point32_set( 0.0, 0.0 ); vieworg = point32_set( 0.0, 0.0 ); bkColor = U_RGB(255, 255, 255); // default foreground color (white) textColor = U_RGB(0, 0, 0); // default foreground color (black) worldTransform.eM11 = 1.0; worldTransform.eM12 = 0.0; worldTransform.eM21 = 0.0; worldTransform.eM22 = 1.0; worldTransform.eDx = 0.0; worldTransform.eDy = 0.0; cur = point32_set( 0, 0 ); }; SPStyle style; char *font_name; int clip_id; // 0 if none, else 1 + index into clips bool stroke_set; int stroke_mode; // enumeration from drawmode, not used if fill_set is not True int stroke_idx; // used with DRAW_PATTERN and DRAW_IMAGE to return the appropriate fill int stroke_recidx;// record used to regenerate hatch when it needs to be redone due to bkmode, textmode, etc. change bool fill_set; int fill_mode; // enumeration from drawmode, not used if fill_set is not True int fill_idx; // used with DRAW_PATTERN and DRAW_IMAGE to return the appropriate fill int fill_recidx; // record used to regenerate hatch when it needs to be redone due to bkmode, textmode, etc. change int dirty; // holds the dirty bits for text, stroke, fill U_SIZEL sizeWnd; U_SIZEL sizeView; U_POINTL winorg; U_POINTL vieworg; double ScaleInX, ScaleInY; double ScaleOutX, ScaleOutY; uint16_t bkMode; U_COLORREF bkColor; U_COLORREF textColor; uint32_t textAlign; U_XFORM worldTransform; U_POINTL cur; }; using PEMF_DEVICE_CONTEXT = EMF_DEVICE_CONTEXT *; #define EMF_MAX_DC 128 struct EMF_CALLBACK_DATA { EMF_CALLBACK_DATA() : // dc: array, structure w/ constructor level(0), E2IdirY(1.0), D2PscaleX(1.0), D2PscaleY(1.0), MM100InX(0), MM100InY(0), PixelsInX(0), PixelsInY(0), PixelsOutX(0), PixelsOutY(0), ulCornerInX(0), ulCornerInY(0), ulCornerOutX(0), ulCornerOutY(0), mask(0), arcdir(U_AD_COUNTERCLOCKWISE), dwRop2(U_R2_COPYPEN), dwRop3(0), MMX(0),MMY(0), drawtype(0), pDesc(nullptr), // hatches, images, gradients, struct w/ constructor tri(nullptr), n_obj(0) // emf_obj; {}; Glib::ustring outsvg; Glib::ustring path; Glib::ustring outdef; Glib::ustring defs; EMF_DEVICE_CONTEXT dc[EMF_MAX_DC+1]; // FIXME: This should be dynamic.. int level; double E2IdirY; // EMF Y direction relative to Inkscape Y direction. Will be negative for MM_LOMETRIC etc. double D2PscaleX,D2PscaleY; // EMF device to Inkscape Page scale. float MM100InX, MM100InY; // size of the drawing in hundredths of a millimeter float PixelsInX, PixelsInY; // size of the drawing, in EMF device pixels float PixelsOutX, PixelsOutY; // size of the drawing, in Inkscape pixels double ulCornerInX,ulCornerInY; // Upper left corner, from header rclBounds, in logical units double ulCornerOutX,ulCornerOutY; // Upper left corner, in Inkscape pixels uint32_t mask; // Draw properties int arcdir; //U_AD_COUNTERCLOCKWISE 1 or U_AD_CLOCKWISE 2 uint32_t dwRop2; // Binary raster operation, 0 if none (use brush/pen unmolested) uint32_t dwRop3; // Ternary raster operation, 0 if none (use brush/pen unmolested) float MMX; float MMY; unsigned int drawtype; // one of 0 or U_EMR_FILLPATH, U_EMR_STROKEPATH, U_EMR_STROKEANDFILLPATH char *pDesc; // both of these end up in under the names shown here. These structures allow duplicates to be avoided. EMF_STRINGS hatches; // hold pattern names, all like EMFhatch#_$$$$$$ where # is the EMF hatch code and $$$$$$ is the color EMF_STRINGS images; // hold images, all like Image#, where # is the slot the image lives. EMF_STRINGS gradients; // hold gradient names, all like EMF[HV]_$$$$$$_$$$$$$ where $$$$$$ are the colors EMF_STRINGS clips; // hold clipping paths, referred to be the slot where the clipping path lives TR_INFO *tri; // Text Reassembly data structure int n_obj; PEMF_OBJECT emf_obj; }; using PEMF_CALLBACK_DATA = EMF_CALLBACK_DATA *; class Emf : public Metafile { public: Emf(); // Empty constructor ~Emf() override;//Destructor bool check(Inkscape::Extension::Extension *module) override; //Can this module load (always yes for now) void save(Inkscape::Extension::Output *mod, // Save the given document to the given filename SPDocument *doc, gchar const *filename) override; SPDocument *open( Inkscape::Extension::Input *mod, const gchar *uri ) override; static void init();//Initialize the class private: protected: static void print_document_to_file(SPDocument *doc, const gchar *filename); static double current_scale(PEMF_CALLBACK_DATA d); static std::string current_matrix(PEMF_CALLBACK_DATA d, double x, double y, int useoffset); static double current_rotation(PEMF_CALLBACK_DATA d); static void enlarge_hatches(PEMF_CALLBACK_DATA d); static int in_hatches(PEMF_CALLBACK_DATA d, char *test); static uint32_t add_hatch(PEMF_CALLBACK_DATA d, uint32_t hatchType, U_COLORREF hatchColor); static void enlarge_images(PEMF_CALLBACK_DATA d); static int in_images(PEMF_CALLBACK_DATA d, const char *test); static uint32_t add_image(PEMF_CALLBACK_DATA d, void *pEmr, uint32_t cbBits, uint32_t cbBmi, uint32_t iUsage, uint32_t offBits, uint32_t offBmi); static void enlarge_gradients(PEMF_CALLBACK_DATA d); static int in_gradients(PEMF_CALLBACK_DATA d, const char *test); static uint32_t add_gradient(PEMF_CALLBACK_DATA d, uint32_t gradientType, U_TRIVERTEX tv1, U_TRIVERTEX tv2); static void enlarge_clips(PEMF_CALLBACK_DATA d); static int in_clips(PEMF_CALLBACK_DATA d, const char *test); static void add_clips(PEMF_CALLBACK_DATA d, const char *clippath, unsigned int logic); static void output_style(PEMF_CALLBACK_DATA d, int iType); static double _pix_x_to_point(PEMF_CALLBACK_DATA d, double px); static double _pix_y_to_point(PEMF_CALLBACK_DATA d, double py); static double pix_to_x_point(PEMF_CALLBACK_DATA d, double px, double py); static double pix_to_y_point(PEMF_CALLBACK_DATA d, double px, double py); static double pix_to_abs_size(PEMF_CALLBACK_DATA d, double px); static void snap_to_faraway_pair(double *x, double *y); static std::string pix_to_xy(PEMF_CALLBACK_DATA d, double x, double y); static void select_pen(PEMF_CALLBACK_DATA d, int index); static void select_extpen(PEMF_CALLBACK_DATA d, int index); static void select_brush(PEMF_CALLBACK_DATA d, int index); static void select_font(PEMF_CALLBACK_DATA d, int index); static void delete_object(PEMF_CALLBACK_DATA d, int index); static void insert_object(PEMF_CALLBACK_DATA d, int index, int type, PU_ENHMETARECORD pObj); static int AI_hack(PU_EMRHEADER pEmr); static uint32_t *unknown_chars(size_t count); static void common_image_extraction(PEMF_CALLBACK_DATA d, void *pEmr, double dx, double dy, double dw, double dh, int sx, int sy, int sw, int sh, uint32_t iUsage, uint32_t offBits, uint32_t cbBits, uint32_t offBmi, uint32_t cbBmi); static int myEnhMetaFileProc(char *contents, unsigned int length, PEMF_CALLBACK_DATA d); static void free_emf_strings(EMF_STRINGS name); }; } } } /* namespace Inkscape, Extension, Implementation */ #endif /* EXTENSION_INTERNAL_EMF_H */ /* Local Variables: mode:c++ c-file-style:"stroustrup" c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +)) indent-tabs-mode:nil fill-column:99 End: */ // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :