diff options
| author | David Mathog <> | 2013-03-08 08:27:50 +0000 |
|---|---|---|
| committer | ~suv <suv-sf@users.sourceforge.net> | 2013-03-08 08:27:50 +0000 |
| commit | e298aeb969151e2a523d3aaef737ac04b6e5b0e8 (patch) | |
| tree | df7e286cc921f8c76684567d4253c7f312e3e2ad /src/extension/internal/emf-print.cpp | |
| parent | merge from trunk (r12122) (diff) | |
| download | inkscape-e298aeb969151e2a523d3aaef737ac04b6e5b0e8.tar.gz inkscape-e298aeb969151e2a523d3aaef737ac04b6e5b0e8.zip | |
changes_2013_02_25a.patch
New: WMF import/export
implements WMF (Windows Metafile) read and write. Inkscape previously
supported that through uniconverter, which was not very good with WMF
files. The new version now has a complete wmf-print/wmf-inout
implementation, analogous to the previous emf-print/emf-inout. This
handles images, patterns, and various other goodies to the extent that
WMF does. WMF is a bit primitive, many fields are only 16 bits, so it
even more resolution sapping issues than does EMF. Given the choice,
always use the latter format.
(bzr r11668.1.52)
Diffstat (limited to 'src/extension/internal/emf-print.cpp')
| -rw-r--r-- | src/extension/internal/emf-print.cpp | 111 |
1 files changed, 53 insertions, 58 deletions
diff --git a/src/extension/internal/emf-print.cpp b/src/extension/internal/emf-print.cpp index 1eec01f39..89ffbde44 100644 --- a/src/extension/internal/emf-print.cpp +++ b/src/extension/internal/emf-print.cpp @@ -45,7 +45,6 @@ #include "inkscape-version.h" #include "sp-root.h" -#include "emf-print.h" #include "unit-constants.h" @@ -63,6 +62,9 @@ #include "2geom/svg-path-parser.h" // to get from SVG text to Geom::Path #include "display/canvas-bpath.h" // for SPWindRule +#include "emf-print.h" + + #include <string.h> extern "C" { #include "libunicode-convert/unicode-convert.h" @@ -101,13 +103,13 @@ struct GRADVALUES{ static double PX2WORLD = 20.0f; static U_XFORM worldTransform; static bool FixPPTCharPos, FixPPTDashLine, FixPPTGrad2Polys, FixPPTPatternAsHatch, FixImageRot; -static FFNEXUS *short_fflist = NULL; //only those fonts so far encountered -static FFNEXUS *long_fflist = NULL; //all the fonts described in ...\share\extensions\fontfix.conf -static EMFTRACK *et = NULL; -static EMFHANDLES *eht = NULL; +static FFNEXUS *emf_short_fflist = NULL; //only those fonts so far encountered. This is SHARED with wmf-print.cpp +static FFNEXUS *emf_long_fflist = NULL; //all the fonts described in ...\share\extensions\fontfix.conf +static EMFTRACK *et = NULL; +static EMFHANDLES *eht = NULL; static GRADVALUES gv; -void read_system_fflist(void){ //this is not called by any other source files +void PrintEmf::read_system_fflist(void){ //this is not called by any other source files FFNEXUS *temp=NULL; FFNEXUS *ptr=NULL; std::fstream fffile; @@ -116,7 +118,7 @@ char fontname[128]; double f1,f2,f3; std::string path_to_ffconf; - if(long_fflist)return; + if(emf_long_fflist)return; path_to_ffconf=INKSCAPE_EXTENSIONDIR; #ifdef WIN32 path_to_ffconf.append("\\fontfix.conf"); //Windows path syntax @@ -148,7 +150,7 @@ std::string path_to_ffconf; ptr=temp; } else { - long_fflist=ptr=temp; + emf_long_fflist=ptr=temp; } } fffile.close(); @@ -157,24 +159,24 @@ std::string path_to_ffconf; /* Looks for the fontname in the long list. If it does not find it, it adds the default values to the short list with this fontname. If it does find it, then it adds the specified values. */ -void search_long_fflist(const char *fontname, double *f1, double *f2, double *f3){ //this is not called by any other source files +void PrintEmf::search_long_fflist(const char *fontname, double *f1, double *f2, double *f3){ //this is not called by any other source files FFNEXUS *ptr=NULL; -FFNEXUS *tmp=long_fflist; - if(!long_fflist){ +FFNEXUS *tmp=emf_long_fflist; + if(!emf_long_fflist){ g_message("Programming error search_long_fflist called before read_system_fflist\n"); throw "boom"; } - ptr=long_fflist; + ptr=emf_long_fflist; while(ptr){ if(!strcmp(ptr->fontname,fontname)){ tmp=ptr; break; } ptr=ptr->next; } //tmp points at either the found name, or the default, the first entry in long_fflist - if(!short_fflist){ - ptr=short_fflist=(FFNEXUS *) malloc(sizeof(FFNEXUS)); + if(!emf_short_fflist){ + ptr=emf_short_fflist=(FFNEXUS *) malloc(sizeof(FFNEXUS)); } else { - ptr=short_fflist; + ptr=emf_short_fflist; while(ptr->next){ ptr=ptr->next; } ptr->next=(FFNEXUS *) malloc(sizeof(FFNEXUS)); ptr=ptr->next; @@ -189,16 +191,16 @@ FFNEXUS *tmp=long_fflist; /* Looks for the fontname in the short list. If it does not find it, it looks in the long_fflist. Either way it returns the f1, f2, f3 parameters for the font, even if these are for the default. */ -void search_short_fflist(const char *fontname, double *f1, double *f2, double *f3){ //this is not called by any other source files +void PrintEmf::search_short_fflist(const char *fontname, double *f1, double *f2, double *f3){ //this is not called by any other source files FFNEXUS *ptr=NULL; static FFNEXUS *last=NULL; - if(!long_fflist){ + if(!emf_long_fflist){ g_message("Programming error search_short_fflist called before read_system_fflist\n"); throw "boom"; } // This speeds things up a lot - if the same font is called twice in a row, pull it out immediately if(last && !strcmp(last->fontname,fontname)){ ptr=last; } - else { ptr=short_fflist; } // short_fflist may still be NULL + else { ptr=emf_short_fflist; } // short_fflist may still be NULL while(ptr){ if(!strcmp(ptr->fontname,fontname)){ *f1=ptr->f1; *f2=ptr->f2; *f3=ptr->f3; last=ptr; return; } ptr=ptr->next; @@ -207,7 +209,7 @@ static FFNEXUS *last=NULL; search_long_fflist(fontname, f1, f2, f3); } -void smuggle_adxky_out(const char *string, uint32_t **adx, double *ky, int *ndx, float scale){ +void PrintEmf::smuggle_adxky_out(const char *string, uint32_t **adx, double *ky, int *ndx, float scale){ float fdx; int i; uint32_t *ladx; @@ -233,7 +235,7 @@ void smuggle_adxky_out(const char *string, uint32_t **adx, double *ky, int *ndx, /* convert an 0RGB color to EMF U_COLORREF. inverse of sethexcolor() in emf-inout.cpp */ -U_COLORREF gethexcolor(uint32_t color){ +U_COLORREF PrintEmf::gethexcolor(uint32_t color){ U_COLORREF out; out = U_RGB( @@ -247,7 +249,7 @@ U_COLORREF gethexcolor(uint32_t color){ /* Translate inkscape weights to EMF weights. */ -uint32_t transweight(const unsigned int inkweight){ +uint32_t PrintEmf::transweight(const unsigned int inkweight){ if(inkweight == SP_CSS_FONT_WEIGHT_400)return(U_FW_NORMAL); if(inkweight == SP_CSS_FONT_WEIGHT_100)return(U_FW_THIN); if(inkweight == SP_CSS_FONT_WEIGHT_200)return(U_FW_EXTRALIGHT); @@ -261,16 +263,9 @@ uint32_t transweight(const unsigned int inkweight){ return(U_FW_NORMAL); } -PrintEmf::PrintEmf (void): - _width(0), - _height(0), - hbrush(0), - hbrushOld(0), - hpen(0), - use_stroke(false), - use_fill(false), - simple_shape(false) +PrintEmf::PrintEmf (void) { + // all of the class variables are initialized elsewhere, many in PrintWmf::Begin, } @@ -309,10 +304,15 @@ unsigned int PrintEmf::begin (Inkscape::Extension::Print *mod, SPDocument *doc) char *ansi_uri = (char *) utf8_fn; + // width and height in px _width = doc->getWidth(); _height = doc->getHeight(); - + + // initialize a few global variables + hbrush = hbrushOld = hpen = 0; + use_stroke = use_fill = simple_shape = false; + Inkscape::XML::Node *nv = sp_repr_lookup_name (doc->rroot, "sodipodi:namedview"); if(nv){ const char *p1 = nv->attribute("pagecolor"); @@ -455,10 +455,11 @@ unsigned int PrintEmf::comment (Inkscape::Extension::Print * /*module*/, // Where the first one is a number and the second a color in hex. // hatchType and hatchColor have been set with defaults before this is called. // -void hatch_classify(char *name, int *hatchType, U_COLORREF *hatchColor){ +void PrintEmf::hatch_classify(char *name, int *hatchType, U_COLORREF *hatchColor){ int val; uint32_t hcolor=0; - if(0!=strncmp(name,"EMFhatch",8)){ return; } // not anything we can parse + // name should be EMFhatch or WMFhatch but *MFhatch will be accepted + if(0!=strncmp(&name[1],"MFhatch",7)){ return; } // not anything we can parse name+=8; // EMFhatch already detected val = 0; while(*name && isdigit(*name)){ @@ -480,11 +481,11 @@ void hatch_classify(char *name, int *hatchType, U_COLORREF *hatchColor){ // // Recurse down from a brush pattern, try to figure out what it is. // If an image is found set a pointer to the epixbuf, else set that to NULL -// If a pattern is found with a name like EMFhatch3_3F7FFF return hatchType=3, hatchColor=3F7FFF (as a uint32_t), +// If a pattern is found with a name like [EW]MFhatch3_3F7FFF return hatchType=3, hatchColor=3F7FFF (as a uint32_t), // otherwise hatchType is set to -1 and hatchColor is not defined. // -void brush_classify(SPObject *parent, int depth, GdkPixbuf **epixbuf, int *hatchType, U_COLORREF *hatchColor){ +void PrintEmf::brush_classify(SPObject *parent, int depth, GdkPixbuf **epixbuf, int *hatchType, U_COLORREF *hatchColor){ if(depth==0){ *epixbuf = NULL; *hatchType = -1; @@ -500,7 +501,7 @@ void brush_classify(SPObject *parent, int depth, GdkPixbuf **epixbuf, int *hatch } char temp[32]; // large enough temp[31]='\0'; - strncpy(temp,pat_i->getAttribute("id"),31); // Some names may be longer than EMFhatch#_###### + strncpy(temp,pat_i->getAttribute("id"),31); // Some names may be longer than [EW]MFhatch#_###### hatch_classify(temp,hatchType,hatchColor); if(*hatchType != -1)return; @@ -526,7 +527,7 @@ void brush_classify(SPObject *parent, int depth, GdkPixbuf **epixbuf, int *hatch } //swap R/B in 4 byte pixel -void swapRBinRGBA(char *px, int pixels){ +void PrintEmf::swapRBinRGBA(char *px, int pixels){ char tmp; for(int i=0;i<pixels*4;px+=4,i+=4){ tmp=px[2]; @@ -540,7 +541,7 @@ inline float opweight(float v1, float v2, float op){ return v1*op + v2*(1.0-op); } -U_COLORREF avg_stop_color(SPGradient *gr){ +U_COLORREF PrintEmf::avg_stop_color(SPGradient *gr){ U_COLORREF cr; int last = gr->vector.stops.size() -1; if(last>=1){ @@ -566,7 +567,7 @@ U_COLORREF avg_stop_color(SPGradient *gr){ return cr; } -int hold_gradient(void *gr, int mode){ +int PrintEmf::hold_gradient(void *gr, int mode){ gv.mode = mode; gv.grad = gr; if(mode==DRAW_RADIAL_GRADIENT){ @@ -705,13 +706,6 @@ int PrintEmf::create_brush(SPStyle const *style, PU_COLORREF fcolor) if(!rec || emf_append((PU_ENHMETARECORD)rec, et, U_REC_FREE)){ throw "Fatal programming error in PrintEmf::create_brush at createbrushindirect_set"; } - hbrush = brush; // need this later for destroy_brush - - rec = selectobject_set(brush, eht); - if(!rec || emf_append((PU_ENHMETARECORD)rec, et, U_REC_FREE)){ - throw "Fatal programming error in PrintEmf::create_brush at selectobject_set"; - } - break; case DRAW_IMAGE: char *px; @@ -736,13 +730,14 @@ int PrintEmf::create_brush(SPStyle const *style, PU_COLORREF fcolor) } free(px); free(Bmi); // ct will be NULL because of colortype - - rec = selectobject_set(brush, eht); - if(!rec || emf_append((PU_ENHMETARECORD)rec, et, U_REC_FREE)){ - throw "Fatal programming error in PrintEmf::create_brush at selectobject_set"; - } break; } + hbrush = brush; // need this later for destroy_brush + rec = selectobject_set(brush, eht); + if(!rec || emf_append((PU_ENHMETARECORD)rec, et, U_REC_FREE)){ + throw "Fatal programming error in PrintEmf::create_brush at selectobject_set"; + } + rec = U_EMRSETPOLYFILLMODE_set(fmode); if(!rec || emf_append((PU_ENHMETARECORD)rec, et, U_REC_FREE)){ throw "Fatal programming error in PrintEmf::create_brush at U_EMRSETPOLYdrawmode_set"; @@ -1056,7 +1051,7 @@ unsigned int PrintEmf::release(Inkscape::Extension::Print * /*mod*/) } #define clrweight(a,b,t) ((1-t)*((double) a) + (t)*((double) b)) -inline U_COLORREF weight_opacity(U_COLORREF c1){ +inline U_COLORREF PrintEmf::weight_opacity(U_COLORREF c1){ float opa = c1.Reserved/255.0; U_COLORREF result = U_RGB( 255*opweight((float)c1.Red /255.0, gv.rgb[0], opa), @@ -1068,7 +1063,7 @@ inline U_COLORREF weight_opacity(U_COLORREF c1){ // return the color between c1 and c2, c1 for t=0, c2 for t=1.0 -U_COLORREF weight_colors(U_COLORREF c1, U_COLORREF c2, double t){ +U_COLORREF PrintEmf::weight_colors(U_COLORREF c1, U_COLORREF c2, double t){ U_COLORREF result; result.Red = clrweight(c1.Red, c2.Red, t); result.Green = clrweight(c1.Green, c2.Green, t); @@ -1104,7 +1099,7 @@ U_COLORREF weight_colors(U_COLORREF c1, U_COLORREF c2, double t){ F is in RADIANS, but the SVGEllipticalArc needs degrees! */ -Geom::PathVector center_ellipse_as_SVG_PathV(Geom::Point ctr, double rx, double ry, double F){ +Geom::PathVector PrintEmf::center_ellipse_as_SVG_PathV(Geom::Point ctr, double rx, double ry, double F){ using Geom::X; using Geom::Y; double x1,y1,x2,y2; @@ -1125,7 +1120,7 @@ Geom::PathVector center_ellipse_as_SVG_PathV(Geom::Point ctr, double rx, double /* rx2,ry2 must be larger than rx1,ry1! angle is in RADIANS */ -Geom::PathVector center_elliptical_ring_as_SVG_PathV(Geom::Point ctr, double rx1, double ry1, double rx2, double ry2, double F){ +Geom::PathVector PrintEmf::center_elliptical_ring_as_SVG_PathV(Geom::Point ctr, double rx1, double ry1, double rx2, double ry2, double F){ using Geom::X; using Geom::Y; double x11,y11,x12,y12; @@ -1152,7 +1147,7 @@ Geom::PathVector center_elliptical_ring_as_SVG_PathV(Geom::Point ctr, double rx1 } /* Elliptical hole in a large square extending from -50k to +50k */ -Geom::PathVector center_elliptical_hole_as_SVG_PathV(Geom::Point ctr, double rx, double ry, double F){ +Geom::PathVector PrintEmf::center_elliptical_hole_as_SVG_PathV(Geom::Point ctr, double rx, double ry, double F){ using Geom::X; using Geom::Y; double x1,y1,x2,y2; @@ -1176,7 +1171,7 @@ pos vector from center to leading edge neg vector from center to trailing edge width vector to side edge */ -Geom::PathVector rect_cutter(Geom::Point ctr, Geom::Point pos, Geom::Point neg, Geom::Point width){ +Geom::PathVector PrintEmf::rect_cutter(Geom::Point ctr, Geom::Point pos, Geom::Point neg, Geom::Point width){ std::vector<Geom::Path> outres; Geom::Path cutter; cutter.start( ctr + pos - width); @@ -1191,7 +1186,7 @@ Geom::PathVector rect_cutter(Geom::Point ctr, Geom::Point pos, Geom::Point neg, /* Convert from SPWindRule to livarot's FillRule This is similar to what sp_selected_path_boolop() does */ -FillRule SPWR_to_LVFR(SPWindRule wr){ +FillRule PrintEmf::SPWR_to_LVFR(SPWindRule wr){ FillRule fr; if(wr == SP_WIND_RULE_EVENODD){ fr = fill_oddEven; |
