diff options
| author | David Mathog <> | 2013-03-21 14:07:06 +0000 |
|---|---|---|
| committer | ~suv <suv-sf@users.sourceforge.net> | 2013-03-21 14:07:06 +0000 |
| commit | a2dc24e823a4e36b1a7551e87108c011e47df971 (patch) | |
| tree | bdbc991c585152842f8b139cf9777a88c42147e0 /src | |
| parent | INX: fix typo in internal WMF input/output filetypename (diff) | |
| download | inkscape-a2dc24e823a4e36b1a7551e87108c011e47df971.tar.gz inkscape-a2dc24e823a4e36b1a7551e87108c011e47df971.zip | |
988601-changes_2013_03_20a.patch
1. Fixes the clang warnings noted in a post above, other than those
associated with alignment caused by casting.
2. Fixes some minor rounding errors in both WMF and EMF input/output.
Round trip open/save cycles are conservative for EMF and WMF files
(excluding any features that are not full supported in inkscape or the
target file format, for instance, gradients, which must be emulated.)
3. Fixed a missing break in the input WMF LINETO record handling, which
was falling through into the MOVETO and generating a harmless extra "M"
operation in a path.
4. WMF has no POLYPOLYLINE record. However input that maps into
essentially a polypolyline record in SVG is common, for instance dashed
lines that have been converted to line segments. These end up in SVG as
a series of M L M L draw commands in the path. Earlier each M L pair
was going out as a polyline record, now they go as a series of
MOVETO/LINETO records. The primary reason for this change is that
without this change the behavior described in (2) does not occur.
5. Fixed an issue where polyline and polygon records in some instances
ended up with an extra copy of their last point.
(bzr r11668.1.62)
Diffstat (limited to 'src')
| -rw-r--r-- | src/extension/internal/emf-inout.cpp | 15 | ||||
| -rw-r--r-- | src/extension/internal/emf-inout.h | 73 | ||||
| -rw-r--r-- | src/extension/internal/emf-print.cpp | 15 | ||||
| -rw-r--r-- | src/extension/internal/uemf_utf.c | 5 | ||||
| -rw-r--r-- | src/extension/internal/uwmf.c | 8 | ||||
| -rw-r--r-- | src/extension/internal/wmf-inout.cpp | 5 | ||||
| -rw-r--r-- | src/extension/internal/wmf-print.cpp | 66 |
7 files changed, 103 insertions, 84 deletions
diff --git a/src/extension/internal/emf-inout.cpp b/src/extension/internal/emf-inout.cpp index 7a5757235..aaa817c61 100644 --- a/src/extension/internal/emf-inout.cpp +++ b/src/extension/internal/emf-inout.cpp @@ -61,11 +61,10 @@ namespace Inkscape { namespace Extension { namespace Internal { - -static U_RECTL rc_old; -static bool clipset = false; -static uint32_t ICMmode=0; // not used yet, but code to read it from EMF implemented -static uint32_t BLTmode=0; +static U_RECTL rc_old = rectl_set(pointl_set(-1,-1),pointl_set(-1,-1)); +static bool clipset = false; +static uint32_t ICMmode = 0; // not used yet, but code to read it from EMF implemented +static uint32_t BLTmode = 0; /** Construct a PNG in memory from an RGB from the EMF file @@ -291,8 +290,8 @@ Emf::save(Inkscape::Extension::Output *mod, SPDocument *doc, gchar const *filena if (ext == NULL) return; - bool new_val = mod->get_param_bool("textToPath"); - bool new_FixPPTCharPos = mod->get_param_bool("FixPPTCharPos"); // character position bug + bool new_val = mod->get_param_bool("textToPath"); + bool new_FixPPTCharPos = mod->get_param_bool("FixPPTCharPos"); // character position bug // reserve FixPPT2 for opacity bug. Currently EMF does not export opacity values bool new_FixPPTDashLine = mod->get_param_bool("FixPPTDashLine"); // dashed line bug bool new_FixPPTGrad2Polys = mod->get_param_bool("FixPPTGrad2Polys"); // gradient bug @@ -1415,7 +1414,7 @@ Emf::select_font(PEMF_CALLBACK_DATA d, int index) d->dc[d->level].font_name = strdup("Arial"); // Default font, EMF spec says device can pick whatever it wants } } - d->dc[d->level].style.baseline_shift.value = ((pEmr->elfw.elfLogFont.lfEscapement + 3600) % 3600) / 10; // use baseline_shift instead of text_transform to avoid overflow + d->dc[d->level].style.baseline_shift.value = round((double)((pEmr->elfw.elfLogFont.lfEscapement + 3600) % 3600)) / 10.0; // use baseline_shift instead of text_transform to avoid overflow } void diff --git a/src/extension/internal/emf-inout.h b/src/extension/internal/emf-inout.h index 7d56339fe..b723f067f 100644 --- a/src/extension/internal/emf-inout.h +++ b/src/extension/internal/emf-inout.h @@ -136,6 +136,7 @@ typedef struct { class Emf : Inkscape::Extension::Implementation::Implementation { //This is a derived class public: + Emf(); // Empty constructor virtual ~Emf();//Destructor @@ -152,42 +153,44 @@ public: static void init(void);//Initialize the class private: + protected: - static pixel_t *pixel_at (bitmap_t * bitmap, int x, int y); - static void my_png_write_data(png_structp png_ptr, png_bytep data, png_size_t length); - static void toPNG(PMEMPNG accum, int width, int height, const char *px); - static uint32_t sethexcolor(U_COLORREF color); - 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, 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 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 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); + + static pixel_t *pixel_at (bitmap_t * bitmap, int x, int y); + static void my_png_write_data(png_structp png_ptr, png_bytep data, png_size_t length); + static void toPNG(PMEMPNG accum, int width, int height, const char *px); + static uint32_t sethexcolor(U_COLORREF color); + 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, 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 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 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); }; diff --git a/src/extension/internal/emf-print.cpp b/src/extension/internal/emf-print.cpp index 3296a1be6..2a9f734d1 100644 --- a/src/extension/internal/emf-print.cpp +++ b/src/extension/internal/emf-print.cpp @@ -972,7 +972,7 @@ int PrintEmf::create_pen(SPStyle const *style, const Geom::Affine &transform) double scale = sqrt( (p[X]*p[X]) + (p[Y]*p[Y]) ) / sqrt(2); if(!style->stroke_width.computed){return 0;} //if width is 0 do not (reset) the pen, it should already be NULL_PEN - uint32_t linewidth = MAX( 1, (uint32_t) (scale * style->stroke_width.computed * PX2WORLD) ); + uint32_t linewidth = MAX( 1, (uint32_t) round(scale * style->stroke_width.computed * PX2WORLD) ); if ( style->stroke_linecap.computed == 0){ linecap = U_PS_ENDCAP_FLAT; } else if (style->stroke_linecap.computed == 1){ linecap = U_PS_ENDCAP_ROUND; } @@ -1516,13 +1516,8 @@ bool PrintEmf::print_simple_shape(Geom::PathVector const &pathv, const Geom::Aff { nodes++; - if ( is_straight_curve(*cit) ) { - lines++; - } - else if (Geom::CubicBezier const *cubic = dynamic_cast<Geom::CubicBezier const*>(&*cit)) { - cubic = cubic; - curves++; - } + if ( is_straight_curve(*cit) ) { lines++; } + else if(&*cit) { curves++; } } } @@ -2044,8 +2039,8 @@ unsigned int PrintEmf::text(Inkscape::Extension::Print * /*mod*/, char const *te U_LOGFONT lf = logfont_set( textheight, 0, - rot, - rot, + round(rot), + round(rot), transweight(style->font_weight.computed), (style->font_style.computed == SP_CSS_FONT_STYLE_ITALIC), style->text_decoration.underline, diff --git a/src/extension/internal/uemf_utf.c b/src/extension/internal/uemf_utf.c index 294897124..48d2510f0 100644 --- a/src/extension/internal/uemf_utf.c +++ b/src/extension/internal/uemf_utf.c @@ -10,8 +10,8 @@ /* File: uemf_utf.c -Version: 0.0.3 -Date: 24-JAN-2013 +Version: 0.0.4 +Date: 19-MAR-2013 Author: David Mathog, Biology Division, Caltech email: mathog@caltech.edu Copyright: 2013 David Mathog and California Institute of Technology (Caltech) @@ -489,6 +489,7 @@ char *U_Latin1ToUtf8( size_t srclen,dstlen,status; if(max){ srclen = max; } else { srclen = strlen(src)+1; } // include terminator, will waste some space + dstlen = (1 + 2*srclen); // This should always work because all latin1 convert to 1 or 2 byte UTF8, it might waste some space dst2 = dst = calloc(dstlen,1); if(!dst)return(NULL); iconv_t conv = iconv_open("UTF-8", "LATIN1"); // everything should translate diff --git a/src/extension/internal/uwmf.c b/src/extension/internal/uwmf.c index 566fb0065..9d916ecee 100644 --- a/src/extension/internal/uwmf.c +++ b/src/extension/internal/uwmf.c @@ -17,8 +17,8 @@ /* File: uwmf.c -Version: 0.0.10 -Date: 27-FEB-2013 +Version: 0.0.11 +Date: 19-MAR-2013 Author: David Mathog, Biology Division, Caltech email: mathog@caltech.edu Copyright: 2013 David Mathog and California Institute of Technology (Caltech) @@ -1496,8 +1496,8 @@ int wmf_finish( // Set the header fields which were unknown up until this point - if((((PU_WMRPLACEABLE) wt->buf)->Key == 0x9AC6CDD7)){ off = U_SIZE_WMRPLACEABLE; } - else { off = 0; } + if(((PU_WMRPLACEABLE) wt->buf)->Key == 0x9AC6CDD7){ off = U_SIZE_WMRPLACEABLE; } + else { off = 0; } record = (wt->buf + off); tmp = (wt->used)/2; diff --git a/src/extension/internal/wmf-inout.cpp b/src/extension/internal/wmf-inout.cpp index 196fc488a..56757d0d0 100644 --- a/src/extension/internal/wmf-inout.cpp +++ b/src/extension/internal/wmf-inout.cpp @@ -1289,7 +1289,7 @@ Wmf::select_font(PWMF_CALLBACK_DATA d, int index) 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 = ((font.Escapement + 3600) % 3600) / 10; // use baseline_shift instead of text_transform to avoid overflow + 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. @@ -2037,7 +2037,8 @@ std::cout << "BEFORE DRAW" d->mask |= wmr_mask; tmp_path << "\n\tL " << pix_to_xy( d, pt16.x, pt16.y) << " "; - } + break; + } case U_WMR_MOVETO: { dbg_str << "<!-- U_WMR_MOVETO -->\n"; diff --git a/src/extension/internal/wmf-print.cpp b/src/extension/internal/wmf-print.cpp index 0a0d06ea1..5ac8d46eb 100644 --- a/src/extension/internal/wmf-print.cpp +++ b/src/extension/internal/wmf-print.cpp @@ -863,7 +863,7 @@ int PrintWmf::create_pen(SPStyle const *style, const Geom::Affine &transform) double scale = sqrt( (p[X]*p[X]) + (p[Y]*p[Y]) ) / sqrt(2); if(!style->stroke_width.computed){return 0;} //if width is 0 do not (reset) the pen, it should already be NULL_PEN - linewidth = MAX( 1, (uint32_t) (scale * style->stroke_width.computed * PX2WORLD) ); + linewidth = MAX( 1, (uint32_t) round(scale * style->stroke_width.computed * PX2WORLD) ); // most WMF readers will ignore linecap and linejoin, but set them anyway. Inkscape itself can read them back in. @@ -1374,13 +1374,8 @@ bool PrintWmf::print_simple_shape(Geom::PathVector const &pathv, const Geom::Aff { nodes++; - if ( is_straight_curve(*cit) ) { - lines++; - } - else if (Geom::CubicBezier const *cubic = dynamic_cast<Geom::CubicBezier const*>(&*cit)) { - cubic = cubic; - curves++; - } + if ( is_straight_curve(*cit) ) { lines++; } + else if (&*cit) { curves++; } } } @@ -1618,8 +1613,11 @@ unsigned int PrintWmf::print_pathv(Geom::PathVector const &pathv, const Geom::Af /** For all Subpaths in the <path> */ - /* If the path consists entirely of closed subpaths use polypolygon, for all paths. Otherwise use - polygon or polyline separately on each path. The former allows path delimited donuts and the like, which + /* If the path consists entirely of closed subpaths use one polypolygon. + Otherwise use a mix of polygon or polyline separately on each path. + If the polyline turns out to be single line segments, use a series of MOVETO/LINETO instead, + because WMF has no POLYPOLYLINE. + The former allows path delimited donuts and the like, which cannot be represented in WMF with polygon or polyline because there is no external way to combine paths as there is in EMF or SVG. For polygons specify the last point the same as the first. The WMF/EMF manuals say that the @@ -1634,7 +1632,7 @@ unsigned int PrintWmf::print_pathv(Geom::PathVector const &pathv, const Geom::Af else { nPolys=0; break; } } - if(nPolys){ // a single polypolygon + if(nPolys > 1){ // a single polypolygon, a single polygon falls through to the else pt16hold = pt16ptr = (PU_POINT16) malloc(totPoints * sizeof(U_POINT16)); if(!pt16ptr)return(false); @@ -1647,7 +1645,7 @@ unsigned int PrintWmf::print_pathv(Geom::PathVector const &pathv, const Geom::Af using Geom::Y; - *n16ptr++ = 1 + pit->size_default(); // points in the subpath + *n16ptr++ = pit->size_default(); // points in the subpath /** For each segment in the subpath */ @@ -1657,7 +1655,7 @@ unsigned int PrintWmf::print_pathv(Geom::PathVector const &pathv, const Geom::Af p1[Y] = (p1[Y] * PX2WORLD); *pt16ptr++ = point16_set((int32_t) round(p1[X]), (int32_t) round(p1[Y])); - for (Geom::Path::const_iterator cit = pit->begin(); cit != pit->end_default(); ++cit) + for (Geom::Path::const_iterator cit = pit->begin(); cit != pit->end_open(); ++cit) { Geom::Point p1 = cit->finalPoint(); @@ -1679,12 +1677,16 @@ unsigned int PrintWmf::print_pathv(Geom::PathVector const &pathv, const Geom::Af { using Geom::X; using Geom::Y; - + + /* Malformatted Polylines with a sequence like M L M M L have been seen, the 2nd M does nothing + and that point must not go into the output. */ + if(!(pit->size_default())){ continue; } /* Figure out how many points there are, make an array big enough to hold them, and store - all the points. This is the same for open or closed path. Note that size_default() ignores - the first point, for some reason. + all the points. This is the same for open or closed path. This gives the upper bound for + the number of points. The actual number used is calculated on the fly. */ int nPoints = 1 + pit->size_default(); + pt16hold = pt16ptr = (PU_POINT16) malloc(nPoints * sizeof(U_POINT16)); if(!pt16ptr)break; @@ -1695,8 +1697,9 @@ unsigned int PrintWmf::print_pathv(Geom::PathVector const &pathv, const Geom::Af p1[X] = (p1[X] * PX2WORLD); p1[Y] = (p1[Y] * PX2WORLD); *pt16ptr++ = point16_set((int32_t) round(p1[X]), (int32_t) round(p1[Y])); + nPoints = 1; - for (Geom::Path::const_iterator cit = pit->begin(); cit != pit->end_default(); ++cit) + for (Geom::Path::const_iterator cit = pit->begin(); cit != pit->end_default(); ++cit, nPoints++) { Geom::Point p1 = cit->finalPoint(); @@ -1705,10 +1708,27 @@ unsigned int PrintWmf::print_pathv(Geom::PathVector const &pathv, const Geom::Af *pt16ptr++ = point16_set((int32_t) round(p1[X]), (int32_t) round(p1[Y])); } - if (pit->end_default() == pit->end_closed()) { rec = U_WMRPOLYGON_set(nPoints, pt16hold); } - else { rec = U_WMRPOLYLINE_set(nPoints, pt16hold); } - if(!rec || wmf_append((PU_METARECORD)rec, wt, U_REC_FREE)){ - g_error("Fatal programming error in PrintWmf::print_pathv at U_WMRPOLYGON/POLYLINE_set"); + if (pit->end_default() == pit->end_closed()) { + rec = U_WMRPOLYGON_set(nPoints, pt16hold); + if(!rec || wmf_append((PU_METARECORD)rec, wt, U_REC_FREE)){ + g_error("Fatal programming error in PrintWmf::print_pathv at U_WMRPOLYGON_set"); + } + } + else if(nPoints>2) { + rec = U_WMRPOLYLINE_set(nPoints, pt16hold); + if(!rec || wmf_append((PU_METARECORD)rec, wt, U_REC_FREE)){ + g_error("Fatal programming error in PrintWmf::print_pathv at U_POLYLINE_set"); + } + } + else if(nPoints == 2) { + rec = U_WMRMOVETO_set(pt16hold[0]); + if(!rec || wmf_append((PU_METARECORD)rec, wt, U_REC_FREE)){ + g_error("Fatal programming error in PrintWmf::print_pathv at U_WMRMOVETO_set"); + } + rec = U_WMRLINETO_set(pt16hold[1]); + if(!rec || wmf_append((PU_METARECORD)rec, wt, U_REC_FREE)){ + g_error("Fatal programming error in PrintWmf::print_pathv at U_WMRLINETO_set"); + } } free(pt16hold); } @@ -1814,8 +1834,8 @@ unsigned int PrintWmf::text(Inkscape::Extension::Print * /*mod*/, char const *te PU_FONT puf = U_FONT_set( textheight, 0, - rot, - rot, + round(rot), + round(rot), transweight(style->font_weight.computed), (style->font_style.computed == SP_CSS_FONT_STYLE_ITALIC), style->text_decoration.underline, |
