wmf-inout.cpp revision f8450d10ec3de270008a8a79bea5012114805f40
/** @file
* @brief Windows-only Enhanced Metafile input and output.
*/
/* Authors:
* Ulf Erikson <ulferikson@users.sf.net>
* Jon A. Cruz <jon@joncruz.org>
* David Mathog
* Abhishek Sharma
*
* Copyright (C) 2006-2008 Authors
*
* Released under GNU GPL, read the file 'COPYING' for more information
*
* References:
* - How to Create & Play Enhanced Metafiles in Win32
* - INFO: Windows Metafile Functions & Aldus Placeable Metafiles
* - Metafile Functions
* - Metafile Structures
*/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
//#include <png.h> //This must precede text_reassemble.h or it blows up in pngconf.h when compiling
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <libuemf/symbol_convert.h>
#include "document.h"
#include "sp-root.h" // even though it is included indirectly by wmf-inout.h
#include "sp-path.h"
#include "print.h"
#include "display/drawing-item.h"
#include "clear-n_.h"
#include "util/units.h" // even though it is included indirectly by wmf-inout.h
#include "inkscape.h" // even though it is included indirectly by wmf-inout.h
#include "wmf-inout.h"
#include "wmf-print.h"
#define PRINT_WMF "org.inkscape.print.wmf"
#ifndef U_PS_JOIN_MASK
#endif
namespace Inkscape {
namespace Extension {
namespace Internal {
static bool clipset = false;
{
return;
}
{
return;
}
bool
{
return FALSE;
return TRUE;
}
void
{
unsigned int ret;
doc->ensureUpToDate();
/* Start */
/* fixme: This has to go into module constructor somehow */
/* Create new arena */
/* Print document */
if (ret) {
}
/* Release arena */
/* end */
return;
}
void
{
return;
// reserve FixPPT2 for opacity bug. Currently WMF does not export opacity values
bool new_FixPPTPatternAsHatch = mod->get_param_bool("FixPPTPatternAsHatch"); // force all patterns as standard WMF hatch
TableGen( //possibly regenerate the unicode-convert tables
);
ext->set_param_bool("FixPPTCharPos",new_FixPPTCharPos); // Remember to add any new ones to PrintWmf::init or a mysterious failure will result!
return;
}
/* WMF has no worldTransform, so this always returns 1.0. Retain it to keep WMF and WMF in sync as much as possible.*/
return 1.0;
}
/* WMF has no worldTransform, so this always returns an Identity rotation matrix, but the offsets may have values.*/
double scale = current_scale(d);
cxform << "\"matrix(";
else { cxform << "0,0"; }
cxform << ")\"";
}
/* WMF has no worldTransform, so this always returns 0. Retain it to keep WMF and WMF in sync as much as possible.*/
return 0.0;
}
/* Add another 100 blank slots to the hatches array.
*/
}
/* See if the pattern name is already in the list. If it is return its position (1->n, not 1-n-1)
*/
int i;
}
return(0);
}
/* (Conditionally) add a hatch. If a matching hatch already exists nothing happens. If one
does not exist it is added to the hatches list and also entered into <defs>.
This is also used to add the path part of the hatches, which they reference with a xlink:href
*/
char tmpcolor[8];
char bkcolor[8];
switch(hatchType){
case U_HS_SOLIDTEXTCLR:
case U_HS_DITHEREDTEXTCLR:
break;
case U_HS_SOLIDBKCLR:
case U_HS_DITHEREDBKCLR:
break;
default:
break;
}
/* For both bkMode types set the PATH + FOREGROUND COLOR for the indicated standard hatch.
This will be used late to compose, or recompose the transparent or opaque final hatch.*/
d->defs += "\n";
switch(hatchType){
case U_HS_HORIZONTAL:
d->defs += " <path id=\"";
d->defs += "\" d=\"M 0 0 6 0\" style=\"fill:none;stroke:#";
d->defs += "\" />\n";
break;
case U_HS_VERTICAL:
d->defs += " <path id=\"";
d->defs += "\" d=\"M 0 0 0 6\" style=\"fill:none;stroke:#";
d->defs += "\" />\n";
break;
case U_HS_FDIAGONAL:
d->defs += " <line id=\"sub";
d->defs += "\" x1=\"-1\" y1=\"-1\" x2=\"7\" y2=\"7\" stroke=\"#";
d->defs += "\"/>\n";
break;
case U_HS_BDIAGONAL:
d->defs += " <line id=\"sub";
d->defs += "\" x1=\"-1\" y1=\"7\" x2=\"7\" y2=\"-1\" stroke=\"#";
d->defs += "\"/>\n";
break;
case U_HS_CROSS:
d->defs += " <path id=\"";
d->defs += "\" d=\"M 0 0 6 0 M 0 0 0 6\" style=\"fill:none;stroke:#";
d->defs += "\" />\n";
break;
case U_HS_DIAGCROSS:
d->defs += " <line id=\"subfd";
d->defs += "\" x1=\"-1\" y1=\"-1\" x2=\"7\" y2=\"7\" stroke=\"#";
d->defs += "\"/>\n";
d->defs += " <line id=\"subbd";
d->defs += "\" x1=\"-1\" y1=\"7\" x2=\"7\" y2=\"-1\" stroke=\"#";
d->defs += "\"/>\n";
break;
case U_HS_SOLIDCLR:
case U_HS_DITHEREDCLR:
case U_HS_SOLIDTEXTCLR:
case U_HS_DITHEREDTEXTCLR:
case U_HS_SOLIDBKCLR:
case U_HS_DITHEREDBKCLR:
default:
d->defs += " <path id=\"";
d->defs += "\" d=\"M 0 0 6 0 6 6 0 6 z\" style=\"fill:#";
d->defs += ";stroke:none";
d->defs += "\" />\n";
break;
}
}
// References to paths possibly just created above. These will be used in the actual patterns.
switch(hatchType){
case U_HS_HORIZONTAL:
case U_HS_VERTICAL:
case U_HS_CROSS:
case U_HS_SOLIDCLR:
case U_HS_DITHEREDCLR:
case U_HS_SOLIDTEXTCLR:
case U_HS_DITHEREDTEXTCLR:
case U_HS_SOLIDBKCLR:
case U_HS_DITHEREDBKCLR:
default:
refpath += " <use xlink:href=\"#";
refpath += "\" />\n";
break;
case U_HS_FDIAGONAL:
case U_HS_BDIAGONAL:
refpath += " <use xlink:href=\"#sub";
refpath += "\" />\n";
refpath += " <use xlink:href=\"#sub";
refpath += "\" transform=\"translate(6,0)\" />\n";
refpath += " <use xlink:href=\"#sub";
refpath += "\" transform=\"translate(-6,0)\" />\n";
break;
case U_HS_DIAGCROSS:
refpath += " <use xlink:href=\"#subfd";
refpath += "\" />\n";
refpath += " <use xlink:href=\"#subfd";
refpath += "\" transform=\"translate(6,0)\"/>\n";
refpath += " <use xlink:href=\"#subfd";
refpath += "\" transform=\"translate(-6,0)\"/>\n";
refpath += " <use xlink:href=\"#subbd";
refpath += "\" />\n";
refpath += " <use xlink:href=\"#subbd";
refpath += "\" transform=\"translate(6,0)\"/>\n";
refpath += " <use xlink:href=\"#subbd";
refpath += "\" transform=\"translate(-6,0)\"/>\n";
break;
}
if(!idx){ // add it if not already present
d->defs += "\n";
d->defs += " <pattern id=\"";
d->defs += "\" xlink:href=\"#WMFhbasepattern\">\n";
d->defs += " </pattern>\n";
}
}
else { // bkMode==U_OPAQUE
/* Set up an object in the defs for this background, if there is not one already there */
d->defs += "\n";
d->defs += " <rect id=\"";
d->defs += "\" x=\"0\" y=\"0\" width=\"6\" height=\"6\" fill=\"#";
d->defs += "\" />\n";
}
// this is the pattern, its name will show up in Inkscape's pattern selector
if(!idx){ // add it if not already present
d->defs += "\n";
d->defs += " <pattern id=\"";
d->defs += "\" xlink:href=\"#WMFhbasepattern\">\n";
d->defs += " <use xlink:href=\"#";
d->defs += "\" />\n";
d->defs += " </pattern>\n";
}
}
return(idx-1);
}
/* Add another 100 blank slots to the images array.
*/
}
/* See if the image string is already in the list. If it is return its position (1->n, not 1-n-1)
*/
int i;
}
return(0);
}
/* (Conditionally) add an image from a DIB. If a matching image already exists nothing happens. If one
does not exist it is added to the images list and also entered into <defs>.
*/
int32_t width, height, colortype, numCt, invert; // if needed these values will be set by wget_DIB_params
if(iUsage == U_DIB_RGB_COLORS){
// next call returns pointers and values, but allocates no memory
if(!DIB_to_RGBA(
px, // DIB pixel array
ct, // DIB color table
numCt, // DIB color table number of entries
&rgba_px, // U_RGBA pixel array (32 bits), created by this routine, caller must free.
width, // Width of pixel array in record
height, // Height of pixel array in record
colortype, // DIB BitCount Enumeration
numCt, // Color table used if not 0
invert // If DIB rows are in opposite order from RGBA rows
)){
toPNG( // Get the image from the RGBA px into mempng
&mempng,
);
}
}
}
}
}
else { // failed conversion, insert the common bad image picture
width = 3;
height = 4;
}
if(!idx){ // add it if not already present - we looked at the actual data for comparison
d->defs += "\n";
d->defs += " <image id=\"";
d->defs += "\"\n ";
d->defs += "\n";
d->defs += base64String;
d->defs += "\"\n";
d->defs += " preserveAspectRatio=\"none\"\n";
d->defs += " />\n";
d->defs += "\n";
d->defs += " <pattern id=\"";
d->defs += "_ref\"\n ";
d->defs += "\n patternUnits=\"userSpaceOnUse\"";
d->defs += " >\n";
d->defs += " <use id=\"";
d->defs += "_ign\" ";
d->defs += " xlink:href=\"#";
d->defs += "\" />\n";
d->defs += " ";
d->defs += " </pattern>\n";
}
return(idx-1);
}
/* (Conditionally) add an image from a Bitmap16. If a matching image already exists nothing happens. If one
does not exist it is added to the images list and also entered into <defs>.
*/
numCt = 0;
invert = 0;
if(colortype < 16)return(U_WMR_INVALID); // these would need a colortable if they were a dib, no idea what bm16 is supposed to do instead.
if(!DIB_to_RGBA(// This is not really a dib, but close enough so that it still works.
px, // DIB pixel array
ct, // DIB color table (always NULL here)
numCt, // DIB color table number of entries (always 0)
&rgba_px, // U_RGBA pixel array (32 bits), created by this routine, caller must free.
width, // Width of pixel array
height, // Height of pixel array
colortype, // DIB BitCount Enumeration
numCt, // Color table used if not 0
invert // If DIB rows are in opposite order from RGBA rows
)){
toPNG( // Get the image from the RGBA px into mempng
&mempng,
);
}
}
else { // failed conversion, insert the common bad image picture
width = 3;
height = 4;
}
if(!idx){ // add it if not already present - we looked at the actual data for comparison
d->defs += "\n";
d->defs += " <image id=\"";
d->defs += "\"\n ";
d->defs += "\n";
d->defs += base64String;
d->defs += "\"\n";
d->defs += " preserveAspectRatio=\"none\"\n";
d->defs += " />\n";
d->defs += "\n";
d->defs += " <pattern id=\"";
d->defs += "_ref\"\n ";
d->defs += "\n patternUnits=\"userSpaceOnUse\"";
d->defs += " >\n";
d->defs += " <use id=\"";
d->defs += "_ign\" ";
d->defs += " xlink:href=\"#";
d->defs += "\" />\n";
d->defs += " </pattern>\n";
}
return(idx-1);
}
/* Add another 100 blank slots to the clips array.
*/
}
/* See if the pattern name is already in the list. If it is return its position (1->n, not 1-n-1)
*/
int i;
}
return(0);
}
/* (Conditionally) add a clip.
If a matching clip already exists nothing happens
If one does exist it is added to the clips list, entered into <defs>.
*/
combined_vect = sp_pathvector_boolop(new_vect, old_vect, (bool_op) op , (FillRule) fill_oddEven, (FillRule) fill_oddEven);
}
else {
}
if(!idx){ // add clip if not already present
tmp_clippath << "\n<clipPath";
tmp_clippath << "\n\tclipPathUnits=\"userSpaceOnUse\" ";
tmp_clippath << " >";
tmp_clippath << "\n\t<path d=\"";
tmp_clippath << combined;
tmp_clippath << "\"";
tmp_clippath << "\n\t/>";
tmp_clippath << "\n</clipPath>";
}
else {
}
}
void
{
// SVGOStringStream tmp_id;
char tmp[1024] = {0};
float fill_rgb[3];
float stroke_rgb[3];
// for U_WMR_BITBLT with no image, try to approximate some of these operations/
// Assume src color is "white"
if(d->dwRop3){
switch(d->dwRop3){
case U_PATINVERT: // treat all of these as black
case U_SRCINVERT:
case U_DSTINVERT:
case U_BLACKNESS:
case U_SRCERASE:
case U_NOTSRCCOPY:
break;
case U_SRCCOPY: // treat all of these as white
case U_NOTSRCERASE:
case U_PATCOPY:
case U_WHITENESS:
break;
case U_SRCPAINT: // use the existing color
case U_SRCAND:
case U_MERGECOPY:
case U_MERGEPAINT:
case U_PATPAINT:
default:
break;
}
d->dwRop3 = 0; // might as well reset it here, it must be set for each BITBLT
}
// Implement some of these, the ones where the original screen color does not matter.
// The options that merge screen and pen colors cannot be done correctly because we
// have no way of knowing what color is already on the screen. For those just pass the
// pen color through.
switch(d->dwRop2){
case U_R2_BLACK:
break;
case U_R2_NOTMERGEPEN:
case U_R2_MASKNOTPEN:
break;
case U_R2_NOTCOPYPEN:
break;
case U_R2_MASKPENNOT:
case U_R2_NOT:
case U_R2_XORPEN:
case U_R2_NOTMASKPEN:
case U_R2_NOTXORPEN:
case U_R2_NOP:
case U_R2_MERGENOTPEN:
case U_R2_COPYPEN:
case U_R2_MASKPEN:
case U_R2_MERGEPENNOT:
case U_R2_MERGEPEN:
break;
case U_R2_WHITE:
break;
default:
break;
}
// tmp_id << "\n\tid=\"" << (d->id++) << "\"";
// d->outsvg += tmp_id.str().c_str();
d->outsvg += "\n\tstyle=\"";
tmp_style << "fill:none;";
} else {
// both of these use the url(#) method
case DRAW_PATTERN:
break;
case DRAW_IMAGE:
break;
case DRAW_PAINT:
default: // <-- this should never happen, but just in case...
tmp, 1023,
"fill:#%02x%02x%02x;",
SP_COLOR_F_TO_U(fill_rgb[0]),
);
break;
}
tmp, 1023,
"fill-rule:%s;",
);
tmp_style << "fill-opacity:1;";
// if the stroke is the same as the fill, and the right size not to change the end size of the object, do not do it separately
if(
(
(
(fill_rgb[0]==stroke_rgb[0]) &&
)
)
){
}
}
tmp_style << "stroke:none;";
} else {
// both of these use the url(#) method
case DRAW_PATTERN:
break;
case DRAW_IMAGE:
break;
case DRAW_PAINT:
default: // <-- this should never happen, but just in case...
tmp, 1023,
"stroke:#%02x%02x%02x;",
);
break;
}
tmp_style << "stroke-width:" <<
}
else { // In a WMF a 0 width pixel means "1 pixel"
}
tmp_style << "stroke-linecap:" <<
(
"unknown"
) << ";";
tmp_style << "stroke-linejoin:" <<
(
"unknown"
) << ";";
// Set miter limit if known, even if it is not needed immediately (not miter)
tmp_style << "stroke-miterlimit:" <<
{
tmp_style << "stroke-dasharray:";
if (i)
tmp_style << ",";
}
tmp_style << ";";
tmp_style << "stroke-dashoffset:0;";
} else {
tmp_style << "stroke-dasharray:none;";
}
tmp_style << "stroke-opacity:1;";
}
tmp_style << "\" ";
}
double
{
double tmp;
tmp = ((((double) (px - d->dc[d->level].winorg.x))*scale) + d->dc[d->level].vieworg.x) * d->D2PscaleX;
tmp -= d->ulCornerOutX; //The WMF boundary rectangle can be anywhere, place its upper left corner in the Inkscape upper left corner
return(tmp);
}
double
{
double tmp;
tmp = ((((double) (py - d->dc[d->level].winorg.y))*scale) * d->E2IdirY + d->dc[d->level].vieworg.y) * d->D2PscaleY;
tmp -= d->ulCornerOutY; //The WMF boundary rectangle can be anywhere, place its upper left corner in the Inkscape upper left corner
return(tmp);
}
double
{
double x = _pix_x_to_point(d, px);
return x;
}
double
{
double y = _pix_y_to_point(d, py);
return y;
}
double
{
double ppx = fabs(px * (d->dc[d->level].ScaleInX ? d->dc[d->level].ScaleInX : 1.0) * d->D2PscaleX * current_scale(d));
return ppx;
}
/* returns "x,y" (without the quotes) in inkscape coordinates for a pair of WMF x,y coordinates
*/
cxform << pix_to_x_point(d,x,y);
cxform << ",";
cxform << pix_to_y_point(d,x,y);
}
void
{
int width;
if(!record){ return; }
case U_PS_DASH:
case U_PS_DOT:
case U_PS_DASHDOT:
case U_PS_DASHDOTDOT:
{
if (!d->dc[d->level].style.stroke_dasharray.values.empty() && (d->level==0 || (d->level>0 && d->dc[d->level].style.stroke_dasharray.values!=d->dc[d->level-1].style.stroke_dasharray.values)))
}
}
if (penstyle==U_PS_DASHDOTDOT) {
}
break;
}
case U_PS_SOLID:
default:
{
break;
}
}
case U_PS_ENDCAP_FLAT:
}
case U_PS_JOIN_ROUND:
}
double pen_width;
pen_width =0.0;
} else if (width) {
} else { // this stroke should always be rendered as 1 pixel wide, independent of zoom level (can that be done in SVG?)
}
double r, g, b;
}
void
{
char *record;
const char *membrush;
if(!record)return;
if(iType == U_WMR_CREATEBRUSHINDIRECT){
double r, g, b;
}
d->dc[d->level].fill_recidx = index; // used if the hatch needs to be redone due to bkMode, textmode, etc. changes
}
}
}
else if(iType == U_WMR_DIBCREATEPATTERNBRUSH){
const char *Bm16h; // Pointer to Bitmap16 header (px follows)
const char *dib; // Pointer to DIB
else if(Bm16h){
const char *px;
}
double r, g, b;
}
else {
}
}
else {
g_message("Please send WMF file to developers - select_brush U_WMR_DIBCREATEPATTERNBRUSH not bm16 or dib, not handled");
}
}
else if(iType == U_WMR_CREATEPATTERNBRUSH){
int cbPx;
const char *px;
double r, g, b;
}
else {
}
}
}
}
void
{
const char *memfont;
const char *facename;
if (!record)return;
memcpy(&font,memfont,U_SIZE_FONT_CORE); //make sure it is in a properly aligned structure before touching it
/* The logfont information always starts with a U_LOGFONT structure but the U_WMRCREATEFONTINDIRECT
is defined as U_LOGFONT_PANOSE so it can handle one of those if that is actually present. Currently only logfont
is supported, and the remainder, it it really is a U_LOGFONT_PANOSE record, is ignored
*/
/* snap the font_size to the nearest 1/32nd of a point.
(The size is converted from Pixels to points, snapped, and converted back.)
See the notes where d->D2Pscale[XY] are set for the reason why.
Typically this will set the font to the desired exact size. If some peculiar size
was intended this will, at worst, make it .03125 off, which is unlikely to be a problem. */
d->dc[d->level].style.font_style.value = (font.Italic ? SP_CSS_FONT_STYLE_ITALIC : SP_CSS_FONT_STYLE_NORMAL);
// malformed WMF with empty filename may exist, ignore font change if encountered
if(*facename){
}
else { // Malformed WMF might specify an empty font name
d->dc[d->level].font_name = strdup("Arial"); // Default font, WMF spec says device can pick whatever it wants
}
d->dc[d->level].style.baseline_shift.value = round((double)((font.Escapement + 3600) % 3600) / 10.0); // use baseline_shift instead of text_transform to avoid overflow
}
/* Find the first free hole where an object may be stored.
If there are not any return -1. This is a big error, possibly from a corrupt WMF file.
*/
{
if(index >= d->n_obj)return(-1); // this is a big problem, percolate it back up so the program can get out of this gracefully
return(index);
}
void
{
// If the active object is deleted set default draw values
}
}
d->dc[d->level].font_name = strdup("Arial"); // Default font, WMF spec says device can pick whatever it wants
}
// We are keeping a copy of the WMR rather than just a structure. Currently that is not necessary as the entire
// WMF is read in at once and is stored in a big malloc. However, in past versions it was handled
// reord by record, and we might need to do that again at some point in the future if we start running into WMF
// files too big to fit into memory.
}
}
// returns the new index, or -1 on error.
{
int index = insertable_object(d);
if(index>=0){
}
return(index);
}
/**
\fn create a UTF-32LE buffer and fill it with UNICODE unknown character
\param count number of copies of the Unicode unknown character to fill with
*/
if(!res)throw "Inkscape fatal memory allocation error - cannot continue";
return res;
}
/**
\brief store SVG for an image given the pixmap and various coordinate information
\param d
\param dib packed DIB in memory
\param dx (double) destination x in inkscape pixels
\param dy (double) destination y in inkscape pixels
\param dw (double) destination width in inkscape pixels
\param dh (double) destination height in inkscape pixels
\param sx (int) source x in src image pixels
\param sy (int) source y in src image pixels
\param iUsage
*/
tmp_image << "\n\t <image\n";
}
int32_t width, height, colortype, numCt, invert; // if needed these values will be set in wget_DIB_params
if(iUsage == U_DIB_RGB_COLORS){
// next call returns pointers and values, but allocates no memory
}
if(!DIB_to_RGBA(
px, // DIB pixel array
ct, // DIB color table
numCt, // DIB color table number of entries
&rgba_px, // U_RGBA pixel array (32 bits), created by this routine, caller must free.
width, // Width of pixel array
height, // Height of pixel array
colortype, // DIB BitCount Enumeration
numCt, // Color table used if not 0
invert // If DIB rows are in opposite order from RGBA rows
)){
sub_px = RGBA_to_RGBA( // returns either a subset (side effect: frees rgba_px) or NULL (for subset == entire image)
rgba_px, // full pixel array from DIB
width, // Width of pixel array
height, // Height of pixel array
);
toPNG( // Get the image from the RGBA px into mempng
&mempng,
);
}
}
}
}
}
}
else { // unknown or unsupported image type or failed conversion, insert the common bad image picture
}
tmp_image << " transform=" << current_matrix(d, 0.0, 0.0, 0); // returns an identity matrix, no offsets.
tmp_image << " preserveAspectRatio=\"none\"\n";
tmp_image << "/> \n";
d->path = "";
}
/**
\brief store SVG for an image given the pixmap and various coordinate information
\param d
\param Bm16 core Bitmap16 header
\param px pointer to Bitmap16 image data
\param dx (double) destination x in inkscape pixels
\param dy (double) destination y in inkscape pixels
\param dw (double) destination width in inkscape pixels
\param dh (double) destination height in inkscape pixels
\param sx (int) source x in src image pixels
\param sy (int) source y in src image pixels
\param iUsage
*/
tmp_image << "\n\t <image\n";
}
numCt = 0;
invert = 0;
}
if(colortype < 16)return; // these would need a colortable if they were a dib, no idea what bm16 is supposed to do instead.
if(!DIB_to_RGBA(// This is not really a dib, but close enough so that it still works.
px, // DIB pixel array
ct, // DIB color table (always NULL here)
numCt, // DIB color table number of entries (always 0)
&rgba_px, // U_RGBA pixel array (32 bits), created by this routine, caller must free.
width, // Width of pixel array
height, // Height of pixel array
colortype, // DIB BitCount Enumeration
numCt, // Color table used if not 0
invert // If DIB rows are in opposite order from RGBA rows
)){
sub_px = RGBA_to_RGBA( // returns either a subset (side effect: frees rgba_px) or NULL (for subset == entire image)
rgba_px, // full pixel array from DIB
width, // Width of pixel array
height, // Height of pixel array
);
toPNG( // Get the image from the RGBA px into mempng
&mempng,
);
}
}
else { // unknown or unsupported image type or failed conversion, insert the common bad image picture
}
tmp_image << " transform=" << current_matrix(d, 0.0, 0.0, 0); // returns an identity matrix, no offsets.
tmp_image << " preserveAspectRatio=\"none\"\n";
tmp_image << "/> \n";
d->path = "";
}
/**
\fn myMetaFileProc(char *contents, unsigned int length, PWMF_CALLBACK_DATA lpData)
\returns 1 on success, 0 on error
\param contents binary contents of an WMF file
\param length length in bytes of contents
\param d Inkscape data structures returned by this call
*/
//THis was a callback, just build it into a normal function
{
int OK =1;
int file_status=1;
int nSize; // size of the current record, in bytes, or an error value if <=0
/* variables used to retrieve data from WMF records */
const char *dib; // DIB style image structure
const char *px; // Image for Bm16
const char *points; // any list of U_POINT16, may not be aligned
const char *text; // returned text, Latin1 encoded
double left, right, top, bottom; // values used, because a bounding rect can have values reversed L<->R, T<->B
uint16_t tbkMode = U_TRANSPARENT; // holds proposed change to bkMode, if text is involved saving these to the DC must wait until the text is written
/* initialize the tsp for text reassembly */
tsp.x = 0.0;
tsp.y = 0.0;
tsp.boff = 0.0; /* offset to baseline from LL corner of bounding rectangle, changes with fs and taln*/
/* There is very little information in WMF headers, get what is there. In many cases pretty much everything will have to
default. If there is no placeable header we know pretty much nothing about the size of the page, in which case
assume that it is 1440 WMF pixels/inch and make the page A4 landscape. That is almost certainly the wrong page size
but it has to be set to something, and nothing horrible happens if the drawing goes off the page. */
{
off = 0;
if (!nSize) {
return(0);
}
if(!Header.nObjects){ Header.nObjects = 256; }// there _may_ be WMF files with no objects, more likely it is corrupt. Try to use it anyway.
d->low_water = 0; // completely empty at this point, so start searches at 0
// Init the new wmf_obj list elements to null, provided the
// dynamic allocation succeeded.
{
for( int i=0; i < d->n_obj; ++i )
} //if
// This is gross, scan forward looking for a SETWINDOWEXT record, use the first one found to
// define the page size
while(OK){
if(nSize){
if(iType == U_WMR_SETWINDOWEXT){
OK=0;
}
OK=0;
// Really messed up WMF, have to set the page to something, make it A4 horizontal
}
else {
}
}
else {
return(0);
}
}
off=0;
nSize = hold_nSize;
OK=1;
}
// drawing size in WMF pixels
/*
Set values for Window and ViewPort extents to 0 - not defined yet.
*/
/* Upper left corner in device units, usually both 0, but not always.
the placeable information will be ignored.
*/
d->D2PscaleX = d->D2PscaleY = Inkscape::Util::Quantity::convert(1, "in", "px")/(double) Placeable.Inch;
// drawing size in Inkscape pixels
// Upper left corner in Inkscape units
d->dc[0].style.stroke_width.value = pix_to_abs_size( d, 1 ); // This could not be set until the size of the WMF was known
dbg_str << "<!-- U_WMR_HEADER -->\n";
d->outdef += "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n";
tmp_outdef << "<svg\n";
tmp_outdef << " xmlns:svg=\"http://www.w3.org/2000/svg\"\n";
tmp_outdef << " xmlns=\"http://www.w3.org/2000/svg\"\n";
tmp_outdef << " xmlns:xlink=\"http://www.w3.org/1999/xlink\"\n";
tmp_outdef << " xmlns:sodipodi=\"http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd\"\n"; // needed for sodipodi:role
tmp_outdef << " version=\"1.0\"\n";
tmp_outdef <<
// d->defs holds any defines which are read in.
}
while(OK){
return(0); //normally should exit from while after WMREOF sets OK to false.
}
/* Currently this is a weaker check than for EMF, it only checks the size of the constant part
of the record */
if(!nSize) {
file_status = 0;
break;
}
if (wmr_mask == U_WMR_INVALID) {
file_status = 0;
break;
}
// Uncomment the following to track down toxic records
// std::cout << "record type: " << (int) iType << " name " << U_wmr_names(iType) << " length: " << nSize << " offset: " << off <<std::endl;
/* Uncomment the following to track down text problems */
//std::cout << "tri->dirty:"<< d->tri->dirty << " wmr_mask: " << std::hex << wmr_mask << std::dec << std::endl;
// incompatible change to text drawing detected (color or background change) forces out existing text
// OR
// next record is valid type and forces pending text to be drawn immediately
if ((d->dc[d->level].dirty & DIRTY_TEXT) || ((wmr_mask != U_WMR_INVALID) && (wmr_mask & U_DRAW_TEXT) && d->tri->dirty)){
TR_layout_analyze(d->tri);
}
TR_layout_2_svg(d->tri);
d->outsvg += "\n</g>\n";
}
}
// U_COLORREF and TRCOLORREF are exactly the same in memory, but the compiler needs some convincing...
if(tbkMode == U_TRANSPARENT){ (void) trinfo_load_bk(d->tri, BKCLR_NONE, *(TRCOLORREF *) &tbkColor); }
}
/* It is possible to have a series of EMF records that would result in
the following creating hash patterns which are never used. For instance, if
there were a series of records that changed the background color but did nothing
else.
*/
}
}
//std::cout << "BEFORE DRAW logic d->mask: " << std::hex << d->mask << " wmr_mask: " << wmr_mask << std::dec << std::endl;
/*
std::cout << "BEFORE DRAW"
<< " test0 " << ( d->mask & U_DRAW_VISIBLE)
<< " test1 " << ( d->mask & U_DRAW_FORCE)
<< " test2 " << (wmr_mask & U_DRAW_ALTERS)
<< " test3 " << (wmr_mask & U_DRAW_VISIBLE)
<< " test4 " << !(d->mask & U_DRAW_ONLYTO)
<< " test5 " << ((d->mask & U_DRAW_ONLYTO) && !(wmr_mask & U_DRAW_ONLYTO) )
<< std::endl;
*/
if(
(
(
((d->mask & U_DRAW_ONLYTO) && !(wmr_mask & U_DRAW_ONLYTO) )// *TO records can only be followed by other *TO records
)
)
)
){
// std::cout << "PATH DRAW at TOP <<+++++++++++++++++++++++++++++++++++++" << std::endl;
output_style(d);
d->outsvg += "\n\t";
d->outsvg += " \" /> \n";
}
// reset the flags
d->mask = 0;
d->drawtype = 0;
}
// std::cout << "AFTER DRAW logic d->mask: " << std::hex << d->mask << " wmr_mask: " << wmr_mask << std::dec << std::endl;
switch (iType)
{
case U_WMR_EOF:
{
dbg_str << "<!-- U_WMR_EOF -->\n";
OK=0;
break;
}
case U_WMR_SETBKCOLOR:
{
dbg_str << "<!-- U_WMR_SETBKCOLOR -->\n";
}
break;
}
case U_WMR_SETBKMODE:{
dbg_str << "<!-- U_WMR_SETBKMODE -->\n";
}
}
break;
}
case U_WMR_SETMAPMODE:
{
dbg_str << "<!-- U_WMR_SETMAPMODE -->\n";
switch (utmp16){
case U_MM_TEXT:
default:
// Use all values from the header.
break;
/* For all of the following the indicated scale this will be encoded in WindowExtEx/ViewportExtex
and show up in ScaleIn[XY]
*/
case U_MM_LOMETRIC: // 1 LU = 0.1 mm,
case U_MM_HIMETRIC: // 1 LU = 0.01 mm
case U_MM_LOENGLISH: // 1 LU = 0.1 in
case U_MM_HIENGLISH: // 1 LU = 0.01 in
case U_MM_TWIPS: // 1 LU = 1/1440 in
d->E2IdirY = -1.0;
// Use d->D2Pscale[XY] values from the header.
break;
case U_MM_ISOTROPIC: // ScaleIn[XY] should be set elsewhere by SETVIEWPORTEXTEX and SETWINDOWEXTEX
case U_MM_ANISOTROPIC:
break;
}
break;
}
case U_WMR_SETROP2:
{
dbg_str << "<!-- U_WMR_SETROP2 -->\n";
break;
}
case U_WMR_SETPOLYFILLMODE:
{
dbg_str << "<!-- U_WMR_SETPOLYFILLMODE -->\n";
break;
}
case U_WMR_SETSTRETCHBLTMODE:
{
dbg_str << "<!-- U_WMR_SETSTRETCHBLTMODE -->\n";
break;
}
case U_WMR_SETTEXTCOLOR:
{
dbg_str << "<!-- U_WMR_SETTEXTCOLOR -->\n";
}
// not text_dirty, because multicolored complex text is supported in libTERE
break;
}
case U_WMR_SETWINDOWORG:
{
dbg_str << "<!-- U_WMR_SETWINDOWORG -->\n";
d->ulCornerOutX = 0.0; // In the examples seen to date if this record is used with a placeable header, that header is ignored
d->ulCornerOutY = 0.0;
break;
}
case U_WMR_SETWINDOWEXT:
{
dbg_str << "<!-- U_WMR_SETWINDOWEXT -->\n";
}
}
else {
/* There are a lot WMF files in circulation with the x,y values in the setwindowext reversed. If this is detected, swap them.
There is a remote possibility that the strange scaling this implies was intended, and those will be rendered incorrectly */
double Ox = d->PixelsOutX;
double Oy = d->PixelsOutY;
int tmp;
}
}
/* Previously it used sizeWnd, but that always resulted in scale = 1 if no viewport ever appeared, and in most files, it did not */
}
/* scales logical to WMF pixels, transfer a negative sign on Y, if any */
d->dc[d->level].ScaleInX = (double) d->dc[d->level].sizeView.x / (double) d->dc[d->level].sizeWnd.x;
d->dc[d->level].ScaleInY = (double) d->dc[d->level].sizeView.y / (double) d->dc[d->level].sizeWnd.y;
d->E2IdirY = -1.0;
}
}
else {
}
break;
}
case U_WMR_SETVIEWPORTORG:
{
dbg_str << "<!-- U_WMR_SETWINDOWORG -->\n";
break;
}
case U_WMR_SETVIEWPORTEXT:
{
dbg_str << "<!-- U_WMR_SETVIEWPORTEXTEX -->\n";
}
}
}
/* scales logical to WMF pixels, transfer a negative sign on Y, if any */
d->dc[d->level].ScaleInX = (double) d->dc[d->level].sizeView.x / (double) d->dc[d->level].sizeWnd.x;
d->dc[d->level].ScaleInY = (double) d->dc[d->level].sizeView.y / (double) d->dc[d->level].sizeWnd.y;
d->E2IdirY = -1.0;
}
}
else {
}
break;
}
case U_WMR_LINETO:
{
dbg_str << "<!-- U_WMR_LINETO -->\n";
break;
}
case U_WMR_MOVETO:
{
dbg_str << "<!-- U_WMR_MOVETO -->\n";
tmp_path <<
break;
}
case U_WMR_EXCLUDECLIPRECT:
{
dbg_str << "<!-- U_WMR_EXCLUDECLIPRECT -->\n";
//outer rect, clockwise
tmp_path << "z ";
//inner rect, counterclockwise (sign of Y is reversed)
tmp_path << "z";
d->path = "";
d->drawtype = 0;
break;
}
case U_WMR_INTERSECTCLIPRECT:
{
dbg_str << "<!-- U_WMR_INTERSECTCLIPRECT -->\n";
tmp_path << "z";
d->path = "";
d->drawtype = 0;
break;
}
case U_WMR_ARC:
{
dbg_str << "<!-- U_WMR_ARC -->\n";
int f1;
if(!stat){
tmp_path << " ";
tmp_path << " ";
}
else {
dbg_str << "<!-- ARC record is invalid -->\n";
}
break;
}
case U_WMR_ELLIPSE:
{
dbg_str << "<!-- U_WMR_ELLIPSE -->\n";
d->outsvg += " <ellipse ";
output_style(d);
d->outsvg += "\n\t";
d->outsvg += "/> \n";
d->path = "";
break;
}
case U_WMR_PIE:
{
dbg_str << "<!-- U_WMR_PIE -->\n";
int f1;
tmp_path << " ";
tmp_path << " ";
tmp_path << " z ";
}
else {
dbg_str << "<!-- PIE record is invalid -->\n";
}
break;
}
case U_WMR_RECTANGLE:
{
dbg_str << "<!-- U_WMR_RECTANGLE -->\n";
tmp_rectangle << "\n\tz";
break;
}
case U_WMR_ROUNDRECT:
{
dbg_str << "<!-- U_WMR_ROUNDRECT -->\n";
double f1 = 1.0 - f;
tmp_rectangle << "\n"
<< " M "
<< "\n";
tmp_rectangle << " C "
<< " "
<< " "
<< "\n";
tmp_rectangle << " L "
<< "\n";
tmp_rectangle << " C "
<< " "
<< " "
<< "\n";
tmp_rectangle << " L "
<< "\n";
tmp_rectangle << " C "
<< " "
<< " "
<< "\n";
tmp_rectangle << " L "
<< "\n";
tmp_rectangle << " C "
<< " "
<< " "
<< "\n";
tmp_rectangle << " z\n";
break;
}
case U_WMR_PATBLT:
{
dbg_str << "<!-- U_WMR_PATBLT -->\n";
// Treat this like any other rectangle, ie, ignore the dwRop3
tmp_rectangle << "\n\tz";
break;
}
case U_WMR_SAVEDC:
{
dbg_str << "<!-- U_WMR_SAVEDC -->\n";
if (d->level < WMF_MAX_DC) {
d->dc[d->level + 1].font_name = strdup(d->dc[d->level].font_name); // or memory access problems because font name pointer duplicated
}
}
break;
}
case U_WMR_OFFSETCLIPRGN:
{
dbg_str << "<!-- U_EMR_OFFSETCLIPRGN -->\n";
double ox = pix_to_x_point(d, off.x, off.y) - pix_to_x_point(d, 0, 0); // take into account all active transforms
}
break;
}
// U_WMR_TEXTOUT should be here, but has been moved down to merge with U_WMR_EXTTEXTOUT
case U_WMR_BITBLT:
{
dbg_str << "<!-- U_WMR_BITBLT -->\n";
if(!px){
if(dwRop3 == U_NOOP)break; /* GDI applications apparently often end with this as a sort of flush(), nothing should be drawn */
tmp_rectangle << "\n\tz";
d->mask |= U_DRAW_CLOSED; // Bitblit is not really open or closed, but we need it to fill, and this is the flag for that
}
else { /* Not done yet, Bm16 image present */ }
//source position within the bitmap, in pixels
int sw = 0; // extract all of the image
int sh = 0;
break;
}
case U_WMR_STRETCHBLT:
{
dbg_str << "<!-- U_WMR_STRETCHBLT -->\n";
if(!px){
if(dwRop3 == U_NOOP)break; /* GDI applications apparently often end with this as a sort of flush(), nothing should be drawn */
tmp_rectangle << "\n\tz";
d->mask |= U_DRAW_CLOSED; // Bitblit is not really open or closed, but we need it to fill, and this is the flag for that
}
else { /* Not done yet, Bm16 image present */ }
//source position within the bitmap, in pixels
break;
}
case U_WMR_POLYGON:
case U_WMR_POLYLINE:
{
dbg_str << "<!-- U_WMR_POLYGON/POLYLINE -->\n";
uint32_t i;
if (cPts < 2)break;
for (i=1; i<cPts; i++) {
}
break;
}
case U_WMR_ESCAPE: // only 3 types of escape are implemented
{
dbg_str << "<!-- U_WMR_ESCAPE -->\n";
if(elen>=4){
if(Escape == U_MFE_SETLINECAP){
switch (utmp4 & U_PS_ENDCAP_MASK) {
case U_PS_ENDCAP_FLAT:
}
}
else if(Escape == U_MFE_SETLINEJOIN){
switch (utmp4 & U_PS_JOIN_MASK) {
case U_PS_JOIN_ROUND:
}
}
else if(Escape == U_MFE_SETMITERLIMIT){
//The function takes a float but uses a 32 bit int in the record.
float miterlimit = utmp4;
}
}
break;
}
case U_WMR_RESTOREDC:
{
dbg_str << "<!-- U_WMR_RESTOREDC -->\n";
if (DC >= 0) {
}
else {
}
if (!d->dc[old_level].style.stroke_dasharray.values.empty() && (old_level==0 || (old_level>0 && d->dc[old_level].style.stroke_dasharray.values!=d->dc[old_level-1].style.stroke_dasharray.values))){
}
}
old_level--;
}
break;
}
case U_WMR_SELECTCLIPREGION:
{
dbg_str << "<!-- U_WMR_EXTSELECTCLIPRGN -->\n";
if (utmp16 == U_RGN_COPY)
clipset = false;
break;
}
case U_WMR_SELECTOBJECT:
{
dbg_str << "<!-- U_WMR_SELECTOBJECT -->\n";
// WMF has no stock objects
{
case U_WMR_CREATEPENINDIRECT:
select_pen(d, index);
break;
case U_WMR_CREATEPATTERNBRUSH: // <- this one did not display properly on XP, DIBCREATEPATTERNBRUSH works
select_brush(d, index);
break;
case U_WMR_CREATEFONTINDIRECT:
select_font(d, index);
break;
case U_WMR_CREATEPALETTE:
case U_WMR_CREATEBITMAP:
case U_WMR_CREATEREGION:
/* these do not do anything, but their objects must be kept in the count */
break;
}
}
break;
}
case U_WMR_SETTEXTALIGN:
{
dbg_str << "<!-- U_WMR_SETTEXTALIGN -->\n";
break;
}
case U_WMR_CHORD:
{
dbg_str << "<!-- U_WMR_CHORD -->\n";
int f1;
tmp_path << " ";
tmp_path << " ";
tmp_path << " z ";
}
else {
dbg_str << "<!-- CHORD record is invalid -->\n";
}
break;
}
case U_WMR_TEXTOUT:
case U_WMR_EXTTEXTOUT:
{
if(iType == U_WMR_TEXTOUT){
dbg_str << "<!-- U_WMR_TEXTOUT -->\n";
Opts=0;
}
else {
dbg_str << "<!-- U_WMR_EXTTEXTOUT -->\n";
}
int cChars;
}
/* Rotation issues are handled entirely in libTERE now */
msdepua(dup_wt); //convert everything in Microsoft's private use area. For Symbol, Wingdings, Dingbats
}
char *ansi_text;
// Empty text or starts with an invalid escape/control sequence, which is bogus text. Throw it out before g_markup_escape_text can make things worse
}
if (ansi_text) {
tsp.y = y*0.8;
case SP_CSS_FONT_STYLE_ITALIC:
default:
case SP_CSS_FONT_STYLE_NORMAL:
}
}
// WMF only supports two types of text decoration
// WMF textalignment is a bit strange: 0x6 is center, 0x2 is right, 0x0 is left, the value 0x4 is also drawn left
ALIRIGHT);
ALITOP));
// language direction can be encoded two ways, U_TA_RTLREADING is preferred
if( (fOptions & U_ETO_RTLREADING) || (d->dc[d->level].textAlign & U_TA_RTLREADING) ){ tsp.ldir = LDIR_RL; }
tsp.ori = d->dc[d->level].style.baseline_shift.value; // For now orientation is always the same as escapement
// There is no world transform, so ori need not be further rotated
tsp.string = (uint8_t *) U_strdup(escaped_text); // this will be free'd much later at a trinfo_clear().
// when font name includes narrow it may not be set to "condensed". Narrow fonts do not work well anyway though
// as the metrics from fontconfig may not match, or the font may not be present.
int status;
TR_layout_analyze(d->tri);
}
TR_layout_2_svg(d->tri);
d->outsvg += "\n</g>\n";
}
}
}
break;
}
case U_WMR_POLYPOLYGON:
{
dbg_str << "<!-- U_WMR_POLYPOLYGON16 -->\n";
const uint16_t *aPolyCounts;
const char *Points;
int cpts; /* total number of points in Points*/
int n, i, j;
i = 0; // offset in BYTES
i += U_SIZE_POINT16;
i += U_SIZE_POINT16;
}
tmp_str << " z";
tmp_str << " \n";
}
break;
}
case U_WMR_3A:
case U_WMR_3B:
case U_WMR_3C:
case U_WMR_3D:
case U_WMR_3E:
case U_WMR_3F:
{
dbg_str << "<!-- U_WMR_3A..3F -->\n";
break;
}
case U_WMR_DIBBITBLT:
{
dbg_str << "<!-- U_WMR_DIBBITBLT -->\n";
// Treat all nonImage bitblts as a rectangular write. Definitely not correct, but at
// least it leaves objects where the operations should have been.
if (!dib) {
// should be an application of a DIBPATTERNBRUSHPT, use a solid color instead
if(dwRop3 == U_NOOP)break; /* GDI applications apparently often end with this as a sort of flush(), nothing should be drawn */
tmp_rectangle << "\n\tz";
d->mask |= U_DRAW_CLOSED; // Bitblit is not really open or closed, but we need it to fill, and this is the flag for that
}
else {
//source position within the bitmap, in pixels
int sw = 0; // extract all of the image
int sh = 0;
// usageSrc not defined, implicitly it must be U_DIB_RGB_COLORS
}
break;
}
case U_WMR_DIBSTRETCHBLT:
{
dbg_str << "<!-- U_WMR_DIBSTRETCHBLT -->\n";
// Always grab image, ignore modes.
if (dib) {
//source position within the bitmap, in pixels
// usageSrc not defined, implicitly it must be U_DIB_RGB_COLORS
}
break;
}
{
dbg_str << "<!-- U_WMR_DIBCREATEPATTERNBRUSH -->\n";
break;
}
case U_WMR_STRETCHDIB:
{
dbg_str << "<!-- U_WMR_STRETCHDIB -->\n";
break;
}
case U_WMR_44:
case U_WMR_45:
case U_WMR_46:
case U_WMR_47:
{
dbg_str << "<!-- U_WMR_44..47 -->\n";
break;
}
case U_WMR_49:
case U_WMR_4A:
case U_WMR_4B:
case U_WMR_4C:
case U_WMR_4D:
case U_WMR_4E:
case U_WMR_4F:
case U_WMR_50:
case U_WMR_51:
case U_WMR_52:
case U_WMR_53:
case U_WMR_54:
case U_WMR_55:
case U_WMR_56:
case U_WMR_57:
case U_WMR_58:
case U_WMR_59:
case U_WMR_5A:
case U_WMR_5B:
case U_WMR_5C:
case U_WMR_5D:
case U_WMR_5E:
case U_WMR_5F:
case U_WMR_60:
case U_WMR_61:
case U_WMR_62:
case U_WMR_63:
case U_WMR_64:
case U_WMR_65:
case U_WMR_66:
case U_WMR_67:
case U_WMR_68:
case U_WMR_69:
case U_WMR_6A:
case U_WMR_6B:
case U_WMR_6C:
case U_WMR_6D:
case U_WMR_6E:
case U_WMR_6F:
case U_WMR_70:
case U_WMR_71:
case U_WMR_72:
case U_WMR_73:
case U_WMR_74:
case U_WMR_75:
case U_WMR_76:
case U_WMR_77:
case U_WMR_78:
case U_WMR_79:
case U_WMR_7A:
case U_WMR_7B:
case U_WMR_7C:
case U_WMR_7D:
case U_WMR_7E:
case U_WMR_7F:
case U_WMR_80:
case U_WMR_81:
case U_WMR_82:
case U_WMR_83:
case U_WMR_84:
case U_WMR_85:
case U_WMR_86:
case U_WMR_87:
case U_WMR_88:
case U_WMR_89:
case U_WMR_8A:
case U_WMR_8B:
case U_WMR_8C:
case U_WMR_8D:
case U_WMR_8E:
case U_WMR_8F:
case U_WMR_90:
case U_WMR_91:
case U_WMR_92:
case U_WMR_93:
case U_WMR_94:
case U_WMR_95:
case U_WMR_96:
case U_WMR_97:
case U_WMR_98:
case U_WMR_99:
case U_WMR_9A:
case U_WMR_9B:
case U_WMR_9C:
case U_WMR_9D:
case U_WMR_9E:
case U_WMR_9F:
case U_WMR_A0:
case U_WMR_A1:
case U_WMR_A2:
case U_WMR_A3:
case U_WMR_A4:
case U_WMR_A5:
case U_WMR_A6:
case U_WMR_A7:
case U_WMR_A8:
case U_WMR_A9:
case U_WMR_AA:
case U_WMR_AB:
case U_WMR_AC:
case U_WMR_AD:
case U_WMR_AE:
case U_WMR_AF:
case U_WMR_B0:
case U_WMR_B1:
case U_WMR_B2:
case U_WMR_B3:
case U_WMR_B4:
case U_WMR_B5:
case U_WMR_B6:
case U_WMR_B7:
case U_WMR_B8:
case U_WMR_B9:
case U_WMR_BA:
case U_WMR_BB:
case U_WMR_BC:
case U_WMR_BD:
case U_WMR_BE:
case U_WMR_BF:
case U_WMR_C0:
case U_WMR_C1:
case U_WMR_C2:
case U_WMR_C3:
case U_WMR_C4:
case U_WMR_C5:
case U_WMR_C6:
case U_WMR_C7:
case U_WMR_C8:
case U_WMR_C9:
case U_WMR_CA:
case U_WMR_CB:
case U_WMR_CC:
case U_WMR_CD:
case U_WMR_CE:
case U_WMR_CF:
case U_WMR_D0:
case U_WMR_D1:
case U_WMR_D2:
case U_WMR_D3:
case U_WMR_D4:
case U_WMR_D5:
case U_WMR_D6:
case U_WMR_D7:
case U_WMR_D8:
case U_WMR_D9:
case U_WMR_DA:
case U_WMR_DB:
case U_WMR_DC:
case U_WMR_DD:
case U_WMR_DE:
case U_WMR_DF:
case U_WMR_E0:
case U_WMR_E1:
case U_WMR_E2:
case U_WMR_E3:
case U_WMR_E4:
case U_WMR_E5:
case U_WMR_E6:
case U_WMR_E7:
case U_WMR_E8:
case U_WMR_E9:
case U_WMR_EA:
case U_WMR_EB:
case U_WMR_EC:
case U_WMR_ED:
case U_WMR_EE:
case U_WMR_EF:
{
dbg_str << "<!-- U_WMR_EXTFLOODFILL..EF -->\n";
break;
}
case U_WMR_DELETEOBJECT:
{
dbg_str << "<!-- U_WMR_DELETEOBJECT -->\n";
delete_object(d, utmp16);
break;
}
case U_WMR_F1:
case U_WMR_F2:
case U_WMR_F3:
case U_WMR_F4:
case U_WMR_F5:
case U_WMR_F6:
{
dbg_str << "<!-- F1..F6 -->\n";
break;
}
case U_WMR_CREATEPALETTE:
{
dbg_str << "<!-- U_WMR_CREATEPALETTE -->\n";
break;
}
case U_WMR_CREATEPATTERNBRUSH:
{
dbg_str << "<!-- U_WMR_CREATEPATTERNBRUSH -->\n";
break;
}
case U_WMR_CREATEPENINDIRECT:
{
dbg_str << "<!-- U_WMR_EXTCREATEPEN -->\n";
break;
}
case U_WMR_CREATEFONTINDIRECT:
{
dbg_str << "<!-- U_WMR_CREATEFONTINDIRECT -->\n";
break;
}
{
dbg_str << "<!-- U_WMR_CREATEBRUSHINDIRECT -->\n";
break;
}
{
dbg_str << "<!-- U_WMR_CREATEBITMAPINDIRECT -->\n";
break;
}
case U_WMR_CREATEBITMAP:
{
dbg_str << "<!-- U_WMR_CREATEBITMAP -->\n";
break;
}
case U_WMR_CREATEREGION:
{
dbg_str << "<!-- U_WMR_CREATEREGION -->\n";
break;
}
default:
dbg_str << "<!-- U_WMR_??? -->\n";
break;
} //end of switch
// When testing, uncomment the following to place a comment for each processed WMR record in the SVG
// d->outsvg += dbg_str.str().c_str();
if(!nSize){ // There was some problem with the processing of this record, it is not safe to continue
file_status = 0;
break;
}
} //end of while on OK
// When testing, uncomment the following to show the final SVG derived from the WMF
// std::cout << d->outsvg << std::endl;
(void) U_wmr_properties(U_WMR_INVALID); // force the release of the lookup table memory, returned value is irrelevant
return(file_status);
}
}
}
{
return NULL;
}
d.n_obj = 0; //these might not be set otherwise if the input file is corrupt
// Default font, WMF spec says device can pick whatever it wants.
// WMF files that do not specify a font are unlikely to look very good!
// Default pen, WMF files that do not specify a pen are unlikely to look very good!
d.dc[0].style.stroke_width.value = 1.0; // will be reset to something reasonable once WMF drawing size is known
d.dc[0].stroke_set = true;
// Default brush is none - no fill. WMF files that do not specify a brush are unlikely to look very good!
d.dc[0].font_name = strdup("Arial"); // Default font, set only on lowest level, it copies up from there WMF spec says device can pick whatever it wants
// set up the size default for patterns in defs. This might not be referenced if there are no patterns defined in the drawing.
d.defs += "\n";
d.defs += " <pattern id=\"WMFhbasepattern\" \n";
d.defs += " patternUnits=\"userSpaceOnUse\"\n";
d.defs += " width=\"6\" \n";
d.defs += " height=\"6\" \n";
d.defs += " x=\"0\" \n";
d.defs += " y=\"0\"> \n";
d.defs += " </pattern> \n";
char *contents;
// set up the text reassembly system
// std::cout << "SVG Output: " << std::endl << d.outsvg << std::endl;
if (good) {
}
if (d.wmf_obj) {
int i;
for (i=0; i<d.n_obj; i++)
delete_object(&d, i);
delete[] d.wmf_obj;
}
for(int i=0; i<=WMF_MAX_DC; i++){
}
// in earlier versions no viewbox was generated and a call to setViewBoxIfMissing() was needed here.
return doc;
}
void
{
/* WMF in */
"<id>org.inkscape.input.wmf</id>\n"
"<input>\n"
"<extension>.wmf</extension>\n"
"<output_extension>org.inkscape.output.wmf</output_extension>\n"
"</input>\n"
"</inkscape-extension>", new Wmf());
/* WMF out */
"<id>org.inkscape.output.wmf</id>\n"
"<param name=\"textToPath\" gui-text=\"" N_("Convert texts to paths") "\" type=\"boolean\">true</param>\n"
"<param name=\"TnrToSymbol\" gui-text=\"" N_("Map Unicode to Symbol font") "\" type=\"boolean\">true</param>\n"
"<param name=\"TnrToWingdings\" gui-text=\"" N_("Map Unicode to Wingdings") "\" type=\"boolean\">true</param>\n"
"<param name=\"TnrToZapfDingbats\" gui-text=\"" N_("Map Unicode to Zapf Dingbats") "\" type=\"boolean\">true</param>\n"
"<param name=\"UsePUA\" gui-text=\"" N_("Use MS Unicode PUA (0xF020-0xF0FF) for converted characters") "\" type=\"boolean\">false</param>\n"
"<param name=\"FixPPTCharPos\" gui-text=\"" N_("Compensate for PPT font bug") "\" type=\"boolean\">false</param>\n"
"<param name=\"FixPPTDashLine\" gui-text=\"" N_("Convert dashed/dotted lines to single lines") "\" type=\"boolean\">false</param>\n"
"<param name=\"FixPPTGrad2Polys\" gui-text=\"" N_("Convert gradients to colored polygon series") "\" type=\"boolean\">false</param>\n"
"<param name=\"FixPPTPatternAsHatch\" gui-text=\"" N_("Map all fill patterns to standard WMF hatches") "\" type=\"boolean\">false</param>\n"
"<output>\n"
"<extension>.wmf</extension>\n"
"</output>\n"
"</inkscape-extension>", new Wmf());
return;
}
} } } /* namespace Inkscape, Extension, Implementation */
/*
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 :