fig2sxd-0.20/0000755000175000017500000000000011101121005010505 5ustar ababfig2sxd-0.20/colors.h0000644000175000017500000000206711013412403012173 0ustar abab// -*-c++-*- // fixg2sxd - a utility to convert fig to sxd format // Copyright (C) 2003-2008 Alexander Bürger, acfb@users.sourceforge.net // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License as // published by the Free Software Foundation; either version 2 of the // License, or (at your option) any later version. // // This program is distributed in the hope that it will be useful, but // WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program; if not, write to the Free Software // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. #ifndef COLORS_H #define COLORS_H #include #include void initcolors(); void read_color( std::istream& figfile ); std::string color2string(unsigned int color); std::string colorstring(int index); #endif // COLORS_H fig2sxd-0.20/check.h0000644000175000017500000000204311013412403011741 0ustar abab// -*-c++-*- // fixg2sxd - a utility to convert fig to sxd format // Copyright (C) 2003-2008 Alexander Bürger, acfb@users.sourceforge.net // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License as // published by the Free Software Foundation; either version 2 of the // License, or (at your option) any later version. // // This program is distributed in the hope that it will be useful, but // WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program; if not, write to the Free Software // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. #ifndef CHECK_H #define CHECK_H 1 #include template void keep_range( T& value, const char* name, const T mini, const T maxi=std::numeric_limits::max() ); #endif /* CHECK_H */ fig2sxd-0.20/vector2.h0000644000175000017500000000376011013412403012257 0ustar abab// -*-c++-*- // fixg2sxd - a utility to convert fig to sxd format // Copyright (C) 2003-2008 Alexander Bürger, acfb@users.sourceforge.net // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License as // published by the Free Software Foundation; either version 2 of the // License, or (at your option) any later version. // // This program is distributed in the hope that it will be useful, but // WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program; if not, write to the Free Software // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. #ifndef VECTOR2_H #define VECTOR2_H #include template class Vector2 { T x, y; public: Vector2() : x( 0 ), y( 0 ) { } Vector2( T xx, T yy ) : x( xx ), y( yy ) { } Vector2 operator+(Vector2 const& o) const { return Vector2( x+o.x, y+o.y ); } Vector2 operator-(Vector2 const& o) const { return Vector2( x-o.x, y-o.y ); } Vector2 operator*(T f) const { return Vector2( x*f, y*f ); } Vector2 operator/(T f) const { return Vector2( x/f, y/f ); } Vector2 norm() const { return Vector2( x/length(), y/length() ); } T operator*(Vector2 const& o) const { return x*o.x + y*o.y; } T length() const { return sqrt( x*x + y*y ); } void X( T xx ) { x = xx; } void Y( T yy ) { y = yy; } T X() const { return x; } T Y() const { return y; } bool operator==(Vector2 const& o) const { return x == o.x && y == o.y; } }; template inline Vector2 operator*(T f, Vector2 v) { return Vector2( v.X()*f, v.Y()*f ); } typedef Vector2 Vector2f; typedef Vector2 Vector2i; #endif // VECTOR2_H fig2sxd-0.20/style_arrow.cpp0000644000175000017500000000516411013412403013600 0ustar abab// -*-c++-*- // fixg2sxd - a utility to convert fig to sxd format // Copyright (C) 2003-2008 Alexander Bürger, acfb@users.sourceforge.net // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License as // published by the Free Software Foundation; either version 2 of the // License, or (at your option) any later version. // // This program is distributed in the hope that it will be useful, but // WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program; if not, write to the Free Software // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. #include "styles.h" #include "check.h" // TODO: hollow arrows arrowset arrows; istream& Arrow::read( istream& figfile ) { // these two are ignored float arrow_thickness; // (1/80 inch) float arrow_height; // (Fig units) figfile >> arrow_type >> arrow_style >> arrow_thickness >> arrow_width >> arrow_height; // check that all values are in the specified ranges keep_range( arrow_type, "arrow_type", 0, 3 ); keep_range( arrow_style, "arrow_style", 0, 1 ); keep_range( arrow_thickness, "arrow_thickness", 0.f ); keep_range( arrow_width, "arrow_width", 0.f ); keep_range( arrow_height, "arrow_heigth", 0.f ); return figfile; } string Arrow::name() const { const char *names[4] = { "Stick", "ClosedTriangle", "IndentedButt", "PointedButt" }; const char styles[2] = { 'O', 'F' }; return string(names[arrow_type]) + styles[arrow_style]; } Node& Arrow::write( Node& out ) const { const int boxheight[4] = { 2000, 1000, 1000, 1250 }; const char* paths[4] = { "M0 2000 L750 0 1500 2000 1250 2000 750 500 250 2000Z", "M0 1000 L750 0 1500 1000Z", "M0 1000 L750 0 1500 1000 750 750Z", "M0 1000 L750 0 1500 1000 750 1250Z" }; Node& arrow = out.subnode("draw:marker"); arrow["draw:name"] << name(); // OOo reads arrows only if the svg:viewBox and svg:d attributes // are in this order arrow["svg:viewBox"] << "0 0 1500 " << boxheight[arrow_type]; arrow["svg:d"] << paths[ arrow_type ]; return out; } #define cmp(x) if( x < o.x ) return true; if( x > o.x ) return false bool Arrow::operator<(Arrow const& o) const { cmp( arrow_type ); cmp( arrow_style ); // cmp( arrow_width ); is compared at LineFillStyle return false; } fig2sxd-0.20/fig2sxd.10000644000175000017500000000443311076164641012171 0ustar abab.\" Hey, EMACS: -*- nroff -*- .TH FIG2SXD 1 .SH NAME fig2sxd \- utility to convert .fig to .sxd .SH SYNOPSIS .B fig2sxd .I [\-w] [\-l(ine)w(idth)1 l] figfile sxdfile .SH DESCRIPTION The program tries to convert the given file in xfig format into a sxd file for OpenOffice.org Draw. If figfile ends with .B .fig or .B .xfig and sxdfile is omitted, the output file will be named like figfile ending with .B .sxd instead of .BR .(x)fig . Using .B \- for .I figfile makes the program read from stdin so that it is possible to use .RS .sp pstoedit \-f fig .I file.ps \- | fig2sxd \- .I file.sxd .sp .RE to convert ps files. (For files with many objects you might want to use something like .RS .sp pstoedit \-f \fB'fig:\-startdepth 9999'\fP \fIfile.ps\fP \- | fig2sxd \- \fIfile.sxd\fP .sp .RE to get more layers; the output of pstoedit then is no longer a valid xfig file, but it makes the z ordering of the objects in OpenOffice.org Draw stay correct.) Using .B - for .I sxdfile makes the program write to stdout. With the .BR "\-linewidth1" " (or " "\-lw1" ")" option, the width of lines with thickness 1 in xfig can be set, unit is 1 cm. Using 0 here gives fine lines. Example: .RS .sp pstoedit \-f \fB'fig:\-startdepth 9999'\fP \fIfile.ps\fP \- | fig2sxd \-lw1 0 \- \fIfile.sxd\fP .sp .RE With the .B \-w option, out-of-specification values are only warnings but will be sanitized. .SH DEFICIENCIES Not all of the .fig objects are converted correctly: splines look quite similar, but are not exactly the same; text placement might be a little bit wrong, especially for very small font sizes; hatches look different in many cases; hollow arrows are not supported and replaced by their filled counterparts. There are various other things that could be improved. It looks like OpenOffice.org cannot read xml attribute values longer than 64kB as they might appear for very long polygons/\-lines. For unfilled polylines, fig2sxd therefore creates several smaller polylines of 500 points each and groups them together. Splitting an arbitrary filled polygon is not trivial and not implemented. .SH "SEE ALSO" .BR pstoedit (1), .BR xfig (1) and .BR http://fig2sxd.sourceforge.net/ (for updates). .SH AUTHOR Program and manual page were written by Alexander B\[:u]rger . fig2sxd-0.20/xfigobjects.h0000644000175000017500000001313011073745351013213 0ustar abab// -*-c++-*- // fixg2sxd - a utility to convert fig to sxd format // Copyright (C) 2003-2008 Alexander Bürger, acfb@users.sourceforge.net // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License as // published by the Free Software Foundation; either version 2 of the // License, or (at your option) any later version. // // This program is distributed in the hope that it will be useful, but // WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program; if not, write to the Free Software // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. #ifndef XFIGOBJCECT_H #define XFIGOBJCECT_H #include #include #include #include "vector2.h" #include "styles.h" class XfigObject { public: virtual ~XfigObject() { } int depth; virtual std::ostream& write( std::ostream& out ) = 0; }; // ------------------------------------------------------------------------ class Arc : public XfigObject { public: int sub_type; // (1: open ended arc 2: pie-wedge (closed) ) lfsset::iterator lfs; int cap_style; // (enumeration type) int direction; // (0: clockwise, 1: counterclockwise) int forward_arrow; // (0: no forward arrow, 1: on) int backward_arrow; // (0: no backward arrow, 1: on) float center_x, center_y; // (center of the arc) float x1, y1; // (Fig units, the 1st point the user entered) float x2, y2; // (Fig units, the 2nd point) float x3, y3; // (Fig units, the last point) std::istream& read( std::istream& in ); virtual std::ostream& write( std::ostream& out ); }; // ------------------------------------------------------------------------ class OpenCompound : public XfigObject { public: float upperleft_corner_x; // (Fig units) float upperleft_corner_y; // (Fig units) float lowerright_corner_x; // (Fig units) float lowerright_corner_y; // (Fig units) std::istream& read( std::istream& in ); virtual std::ostream& write( std::ostream& out ); }; // ------------------------------------------------------------------------ class CloseCompound : public XfigObject { public: std::istream& read( std::istream& in ); virtual std::ostream& write( std::ostream& out ); }; // ------------------------------------------------------------------------ class Ellipse : public XfigObject { public: int sub_type; // (1: ellipse defined by radii // 2: ellipse defined by diameters // 3: circle defined by radius // 4: circle defined by diameter) lfsset::iterator lfs; int direction; // (always 1) float angle; // (radians, the angle of the x-axis) float center_x, center_y; // (Fig units) float radius_x, radius_y; // (Fig units) float start_x, start_y; // (Fig units; the 1st point entered) float end_x, end_y; // (Fig units; the last point entered) std::istream& read( std::istream& in ); virtual std::ostream& write( std::ostream& out ); }; // ------------------------------------------------------------------------ class Poly : public XfigObject { public: int sub_type; // (1: polyline, 2: box, 3: polygon, 4: arc-box // 5: imported-picture bounding-box) lfsset::iterator lfs; int cap_style; // (enumeration type, only used for POLYLINE) int radius; // (1/80 inch, radius of arc-boxes) int forward_arrow; // (0: off, 1: on) int backward_arrow; // (0: off, 1: on) int npoints; // (number of points in line) // for images int flipped; // orientation = normal (0) or flipped (1) std::string file; // name of picture file to import float *x; float *y; std::istream& read( std::istream& in ); virtual std::ostream& write( std::ostream& out ); Poly() : x(0), y(0) { } ~Poly(); private: std::ostream& write_rectangle( std::ostream& out ); std::ostream& write_image( std::ostream& out ); std::ostream& write_poly( std::ostream& out ); void find_min_max( float& maxx, float& minx, float& maxy, float& miny, int begin, int end ); }; // ------------------------------------------------------------------------ class Spline : public XfigObject { public: int sub_type; // 0: open approximated spline, // 1: closed approximated spline // 2: open interpolated spline // 3: closed interpolated spline // 4: open x-spline // 5: closed x-spline lfsset::iterator lfs; int cap_style; // (enumeration type, only used for POLYLINE) int forward_arrow; // (0: off, 1: on) int backward_arrow; // (0: off, 1: on) int npoints; // (number of points in line) Vector2f *p; float *shapefactors; std::istream& read( std::istream& in ); virtual std::ostream& write( std::ostream& out ); Spline() : p(0), shapefactors(0) { } ~Spline(); }; // ------------------------------------------------------------------------ class Text : public XfigObject { public: tsset::iterator textstyle; float angle; // (radians, the angle of the text) float height; // (Fig units) float length; // (Fig units) float x, y; // (Fig units, coordinate of the origin // of the string. If sub_type = 0, it is the lower left corner of // the string. If sub_type = 1, it is the lower center. // Otherwise it is the lower right corner of the string.) std::string text; std::istream& read( std::istream& in ); virtual std::ostream& write( std::ostream& out ); }; #endif // XFIGOBJCECT_H fig2sxd-0.20/xmlwrite.cpp0000644000175000017500000000713111013412403013075 0ustar abab// -*-c++-*- // fixg2sxd - a utility to convert fig to sxd format // Copyright (C) 2003-2008 Alexander Bürger, acfb@users.sourceforge.net // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License as // published by the Free Software Foundation; either version 2 of the // License, or (at your option) any later version. // // This program is distributed in the hope that it will be useful, but // WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program; if not, write to the Free Software // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. #include "xmlwrite.h" using namespace std; string indent(int l) { ostringstream s; for( int i=0; isecond; } for( vector::iterator i = elements.begin(); i != elements.end(); ++i ) { delete *i; } } ostringstream& Node::att( string const& attname ) { #ifdef USE_MAP attributes_t::iterator i = attributes.find( attname ); #else attributes_t::iterator i = attributes.begin(); while( i != attributes.end() && i->first != attname ) ++i; #endif if( i != attributes.end() ) { delete i->second; #ifndef USE_MAP attributes.erase(i); #endif } ostringstream* o = new ostringstream; #ifdef USE_MAP attributes[ attname ] = o; #else attributes.push_back( pair( attname, o ) ); #endif return *o; } Node& Node::subnode( string const& subname ) { Node* n = new Node( subname ); elements.push_back( n ); return *n; } TextElement& Node::text() { TextElement* t = new TextElement(); elements.push_back( t ); indentation = false; return *t; } void Node::write(ostream& out, int level, bool pretty) const { out << indent(level) << '<' << name; for( attributes_t::const_iterator i = attributes.begin(); i != attributes.end(); ++i ) { out << ' ' << i->first << "=\"" << i->second->str() << '"'; } if( elements.empty() ) { out << "/>"; if( pretty ) out << endl; } else { out << ">"; if( pretty && indentation ) out << endl; for( vector::const_iterator i = elements.begin(); i != elements.end(); ++i ) { (*i)->write( out, level+1, pretty && indentation ); } if( pretty && indentation ) out << indent(level); out << "'; if( pretty ) out << endl; } } // ------------------------------------------------------------------------ #ifdef TEST_XMLWRITE int main() { Node root("office:body"); root["hi"] << "ho"; Node& s = root.subnode("office:bah"); s["att-no"] << "yes"; root.text().t() << "this is text!"; Node& s2 = root.subnode("office:zero"); s2["att-no"] << "yes"; cout << root; } #endif // TEST_XMLWRITE fig2sxd-0.20/xfig_poly.cpp0000644000175000017500000001656511101117275013244 0ustar abab// -*-c++-*- // fixg2sxd - a utility to convert fig to sxd format // Copyright (C) 2003-2008 Alexander Bürger, acfb@users.sourceforge.net // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License as // published by the Free Software Foundation; either version 2 of the // License, or (at your option) any later version. // // This program is distributed in the hope that it will be useful, but // WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program; if not, write to the Free Software // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. #include "xfigobjects.h" #include "check.h" #include "misc.h" #include "xmlwrite.h" Poly::~Poly() { delete x; delete y; } istream& Poly::read( istream& figfile ) { LineFillStyle lfstmp; lfstmp.read( figfile, sub_type, depth, true ); figfile >> cap_style >> radius >> forward_arrow >> backward_arrow >> npoints; keep_range( sub_type, "poly sub_type", 1, 5 ); if( sub_type == 1 ) // cap_style is used only for polyline keep_range( cap_style, "poly(polyline) cap_style", 0, 2 ); if( sub_type == 4 ) // radius is used only for arc-boxes keep_range( radius, "poly(arc-box) radius", 0 ); keep_range( forward_arrow, "poly forward_arrow", 0, 1 ); keep_range( backward_arrow, "poly backward_arrow", 0, 1 ); // limit n.o. points somewhat arbitrarily if( npoints<1 || npoints>65536 ) { ostringstream err; err << "Bad number of polygon points " << npoints << " (accepted range = [1,65536])."; throw err.str(); } if( forward_arrow != 0 ) lfstmp.read_arrow( figfile, true ); if( backward_arrow != 0 ) lfstmp.read_arrow( figfile, false ); if( sub_type == 5 ) { // picture figfile >> flipped >> file; } x = new float[npoints]; y = new float[npoints]; for( int i=0; i> x[i] >> y[i]; lfs = linefillstyles.insert( lfstmp ).first; if( sub_type == 1 ) { lfs->stylename_line(); if( lfs->area_fill != -1 ) lfs->stylename_fill(); } else { lfs->stylename(); } return figfile; } void Poly::find_min_max( float& maxx, float& minx, float& maxy, float& miny, int begin, int end ) { maxx = minx = x[begin]; maxy = miny = y[begin]; for( int i=begin+1; i maxx ) maxx = x[i]; if( y[i] > maxy ) maxy = y[i]; if( x[i] < minx ) minx = x[i]; if( y[i] < miny ) miny = y[i]; } } ostream& Poly::write( ostream& out ) { if( sub_type == 5 ) // imported-picture bounding-box return write_image( out ); else if( sub_type == 2 || sub_type == 4 ) // box or arc-box return write_rectangle( out ); else return write_poly( out ); // polyline or polygon } ostream& Poly::write_image( ostream& out ) { if( npoints != 5 ) fail( "image with != 5 points" ); // points are clockwise around the image => determine rotation // from relative position of first two points float angle = 0; float maxx=0, maxy=0, minx=0, miny=0; find_min_max( maxx, minx, maxy, miny, 0, npoints ); float width = maxx-minx, height= maxy-miny, posx=minx, posy=miny; if( x[0] == x[1] ) { swap( width, height ); if( y[0] > y[1] ) { angle = M_PI/2; posy += height; } else { angle = 3*M_PI/2; posx += width; } } else if( x[0] > x[1] ) { posx += width; posy += height; angle = M_PI; } Node image("draw:image"); image["draw:style-name"] << "gr_img"; image["draw:z-index"] << depth2z(depth); image["draw:layer"] << "layout"; if( angle == 0 ) { image["svg:x"] << tr(posx) << "cm"; image["svg:y"] << tr(posy) << "cm"; } else { image["draw:transform"] << "rotate(" << angle << ")" << "translate(" << tr(posx) << "cm " << tr(posy) << "cm)"; } image["svg:width"] << tr(width) << "cm"; image["svg:height"] << tr(height) << "cm"; image["xlink:href"] << file; image["xlink:type"] << "simple"; image["xlink:show"] << "embed"; image["xlink:actuate"] << "onLoad"; return out << image; } ostream& Poly::write_rectangle( ostream& out ) { float maxx=0, maxy=0, minx=0, miny=0; find_min_max( maxx, minx, maxy, miny, 0, npoints ); Node rect("draw:rect"); rect["draw:style-name"] << lfs->stylename(); rect["draw:z-index"] << depth2z(depth); if( sub_type == 4 ) { // rounded corners rect["draw:corner-radius"] << tr80(radius) << "cm"; } rect["draw:layer"] << "layout"; rect["svg:x"] << tr(minx) << "cm"; rect["svg:y"] << tr(miny) << "cm"; rect["svg:width"] << tr(maxx-minx) << "cm"; rect["svg:height"] << tr(maxy-miny) << "cm"; return out << rect; } ostream& Poly::write_poly( ostream& out ) { // XXX: it looks like OOo has a bug and does not read attribute // values longer than 64kB, so for a lot of points, it will not // display anything; for lines, it is to split after some points // (more difficult to split before reaching 64kB), but I do not // know how to split an arbitrary, filled polygon // in case of a long, unfilled polygon, make a group with smaller // polygons const int limit = 500; const bool long_line = (sub_type==1 && npoints>limit && lfs->hasLine() && !lfs->hasFill()); const int step = long_line ? limit : npoints; if( long_line ) { static bool warn_split = false; if( !warn_split ) { cerr << "Warning: vrey long polylines will be split into pieces of " << limit << " points." << endl; warn_split = true; } out << "" << endl; } for( int begin=0; begin= 1<<16 ) { static bool warn_long = false; if( !warn_long ) { cerr << "Warning: some polylines/polygons might be too large" " for OpenOffice.org." << endl; warn_long = true; } } // now decide what to write if( sub_type == 1 ) { // polyline if( lfs->hasFill() ) { // a polyline may be filled, but then it is missing the // last segment of the border poly["draw:style-name"] << lfs->stylename_fill(); out << poly; } if( lfs->hasLine() ) { poly.SetName("draw:polyline"); poly["draw:style-name"] << lfs->stylename_line(); out << poly; } } else { if( lfs->hasLine() || lfs->hasFill() ) { poly["draw:style-name"] << lfs->stylename(); out << poly; } } } if( long_line ) out << "" << endl; return out; } fig2sxd-0.20/xfig_text.cpp0000644000175000017500000001007111013412403013220 0ustar abab// -*-c++-*- // fixg2sxd - a utility to convert fig to sxd format // Copyright (C) 2003-2008 Alexander Bürger, acfb@users.sourceforge.net // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License as // published by the Free Software Foundation; either version 2 of the // License, or (at your option) any later version. // // This program is distributed in the hope that it will be useful, but // WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program; if not, write to the Free Software // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. #include "xfigobjects.h" #include "xmlwrite.h" #include "misc.h" #include // TODO: non-ps fonts? // TODO: symbol font does not show anything istream& Text::read( istream& figfile ) { int unused_pen_style; // (enumeration , not used) TextStyle ts; figfile >> ts.justification >> ts.color >> depth >> unused_pen_style >> ts.font >> ts.font_size >> angle >> ts.font_flags >> height >> length >> x >> y; textstyle = textstyles.insert( ts ).first; textstyle->stylenumber(); // read the string characterwise char ch; figfile.get( ch ); // skip initial space while( true ) { figfile.get( ch ); if( ch == '\\' ) { figfile.get( ch ); if( ch != '\\' ) { int ch2 = figfile.get(); int ch3 = figfile.get(); int value = 64*(ch-'0') + 8*(ch2-'0') + (ch3-'0'); if( value == 1 ) break; ch = char(value); } } text += ch; } return figfile; } ostream& Text::write( ostream& out ) { // --------- use line to position text ------------- // extracted from creating text with OOo draw, printing as ps, // converting to fig with pstoedit and making linear regression; // finally for small fonts, a correction was done const float length = 50; const float fs = textstyle->font_size; const float off = -( 0.23 + 6.63*fs ); float justify = (textstyle->justification==0) ? 0 : ((textstyle->justification==1) ? -length/2.0 : -length); float x1 = x + sin(angle)*off + cos(angle)*justify; float y1 = y + cos(angle)*off - sin(angle)*justify; float x2 = x1 + cos(angle)*length; float y2 = y1 - sin(angle)*length; Node line("draw:line"); line["draw:layer"] << "layout"; line["draw:z-index"] << depth2z(depth); line["draw:style-name"] << textstyle->stylenumber(); line["svg:x1"] << tr(x1) << "cm"; line["svg:y1"] << tr(y1) << "cm"; line["svg:x2"] << tr(x2) << "cm"; line["svg:y2"] << tr(y2) << "cm"; Node& textp=line.subnode("text:p"); if( textstyle->font/4 == 5 ) textp["text:style-name"] << "P1"; ostringstream& txt = textp.text().t(); unsigned char last=0; for( unsigned i=0; i' ' && ch < 128) || (ch==' '&&last!=' ') ) { switch( ch ) { case '<': txt << "<"; break; case '>': txt << ">"; break; case '\'': txt << "'"; break; case '\"': txt << """; break; case '&': txt << "&"; break; default: txt << text[i]; } } else if( ch == '\n' ) { // line break txt << ""; } else if( ch == ' ' ) { // multiple spaces unsigned secondspace = i; while( i"; if( text[i] != ' ' ) --i; } else if( ch>=' ') { txt << "&#" << setw(4) << setfill('0') << unsigned(ch) << ";"; } last = ch; } return out << line; } fig2sxd-0.20/zipwrite.cpp0000644000175000017500000001775211013412403013111 0ustar abab// -*-c++-*- // fixg2sxd - a utility to convert fig to sxd format // Copyright (C) 2003-2008 Alexander Bürger, acfb@users.sourceforge.net // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License as // published by the Free Software Foundation; either version 2 of the // License, or (at your option) any later version. // // This program is distributed in the hope that it will be useful, but // WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program; if not, write to the Free Software // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. #include "zipwrite.h" #include #include #include using namespace std; // ------------------------------------------------------------------------ class WriterBuf : public std::streambuf { public: typedef int (*WriteFunc)( void* user, const char* buf, unsigned length ); private: WriteFunc writefunc; void* user; unsigned bufsize; char *buf; public: WriterBuf( WriteFunc wf, void* u, unsigned bs = 1) : writefunc( wf ), user( u ), bufsize( bs < 1 ? 1 : bs ), buf( new char[ bufsize ] ) { setp( buf, buf+bufsize ); } ~WriterBuf(); protected: int overflow( int c ); int sync(); }; WriterBuf::~WriterBuf() { if( buf ) { sync(); delete buf; } } int WriterBuf::overflow( int c ) { sync(); if( c != EOF ) { *pptr() = static_cast( c ); pbump( 1 ); } return c; } int WriterBuf::sync() { int ret = 0; if( pptr() > pbase() ) { ret = writefunc( user, buf, pptr() - pbase() ); setp( buf, buf+bufsize ); } return ret; } // ------------------------------------------------------------------------ ostream& write2( ostream& out, unsigned short s ) { unsigned char bytes[2] = { (s&0xff), ((s>>8)&0xff) }; out.write( (const char*)bytes, 2 ); return out; } ostream& write4( ostream& out, unsigned int i ) { unsigned char bytes[4] = { (i&0xff), ((i>>8)&0xff), ((i>>16)&0xff), ((i>>24)&0xff) }; out.write( (const char*)bytes, 4 ); return out; } // ------------------------------------------------------------------------ ZipWriter::~ZipWriter() { Close(); const int rel_offset_central_dir = zip.tellp(); // write central directory for( fileinfos_t::iterator i=fileinfos.begin(); i!=fileinfos.end(); ++i ) { fileinfo& fi = *i; // central file header signature write4( zip, 0x02014b50 ); write2( zip, 20 ); write2( zip, 20 ); // general_purpose_bits, crc and size come later write2( zip, (1<<3 | 1<<1)); // compression method write2( zip, 8 ); write2( zip, fi.last_mod_file_time ); write2( zip, fi.last_mod_file_date ); write4( zip, fi.crc32 ); write4( zip, fi.compressed_size ); write4( zip, fi.uncompressed_size ); write2( zip, fi.file_name.length() ); // extra field length, file comment length, disk number start, // internal file attributes (each 2 bytes) write4( zip, 0 ); write4( zip, 0 ); // external file attributes write4( zip, 0 ); write4( zip, fi.rel_offset_local_header ); zip.write( fi.file_name.data(), fi.file_name.length() ); } const int rel_end_central_dir = zip.tellp(); const int size_central_dir = rel_end_central_dir - rel_offset_central_dir; // write end of central dir write4( zip, 0x06054b50 ); // disk number write2( zip, 0 ); // number of the disk with the start of the central directory write2( zip, 0 ); // n.o. entries in the centr. dir. on this disk write2( zip, fileinfos.size() ); // total number of entries in the central dir. write2( zip, fileinfos.size() ); // size of the central directory (4 bytes) write4( zip, size_central_dir ); // offset of start of central directory with respect to the // starting disk number write4( zip, rel_offset_central_dir ); // .ZIP file comment length -- comment is empty (2 bytes) write2( zip, 0 ); } ostream& ZipWriter::GetStream( const char* name ) { if( out ) Close(); fileinfo fi; fi.rel_offset_local_header = zip.tellp(); time_t now = time(0); struct tm* t = localtime(&now); fi.last_mod_file_time = (t->tm_sec/2)+(32*t->tm_min)+(2048*(uLong)t->tm_hour); fi.last_mod_file_date = (t->tm_mday)+(32*(t->tm_mon+1))+(512*(t->tm_year-1900)); // write local file header: // local_file_header_signature write4( zip, 0x04034b50 ); write2( zip, 20 ); write2( zip, (1<<3 | 1<<1)); // compression method write2( zip, 8 ); write2( zip, fi.last_mod_file_time ); write2( zip, fi.last_mod_file_date ); write4( zip, fi.crc32 = 0 ); write4( zip, fi.compressed_size = 0 ); write4( zip, fi.uncompressed_size = 0 ); fi.file_name = name; write2( zip, fi.file_name.length() ); write2( zip, 0 ); zip.write( fi.file_name.data(), fi.file_name.length() ); zs.zalloc = 0; zs.zfree = 0; zs.opaque = 0; zs.total_in = zs.total_out = 0; zs.next_out = (Bytef*)cbuf; zs.avail_out = sizeof(cbuf); if( deflateInit2( &zs, 9, Z_DEFLATED, -MAX_WBITS, MAX_MEM_LEVEL, Z_DEFAULT_STRATEGY ) != Z_OK ) { cerr << "deflateInit2" << endl; exit( -1 ); } fi.crc32 = crc32( 0, Z_NULL, 0 ); fileinfos.push_back( fi ); out = new ostream( new WriterBuf( writefunc, this, 32768 ) ); return *out; } void ZipWriter::Close() { if( !out ) return; // write everything streambuf* sb = out->rdbuf(); delete out; delete sb; out = 0; // finish zip stream int err = Z_OK; while( err == Z_OK && ( err = deflate( &zs, Z_FINISH )) == Z_OK ) { zip.write( cbuf, sizeof(cbuf) ); zs.next_out = (Bytef*)cbuf; zs.avail_out = sizeof(cbuf); } if( err == Z_STREAM_END ) { zip.write( cbuf, sizeof(cbuf)-zs.avail_out ); } else { cerr << "zip error" << endl; exit( -1 ); } if( deflateEnd( &zs ) != Z_OK ) { cerr << "deflateEnd" << endl; exit( -1 ); } fileinfo& fi = fileinfos.back(); fi.uncompressed_size = zs.total_in; fi.compressed_size = zs.total_out; // write crc and sizes write4( zip, fi.crc32 ); write4( zip, fi.uncompressed_size ); write4( zip, fi.compressed_size ); } int ZipWriter::Write( const char* buf, unsigned length ) { zs.next_in = (Bytef*)buf; zs.avail_in = length; fileinfos.back().crc32 = crc32(fileinfos.back().crc32,(Bytef*)buf,length); int err = Z_OK; while( err == Z_OK && zs.avail_in>0 ) { if( zs.avail_out == 0 ) { //flush, reset cbuf zip.write( cbuf, sizeof(cbuf) ); zs.next_out = (Bytef*)cbuf; zs.avail_out = sizeof(cbuf); } err = deflate( &zs, Z_NO_FLUSH ); } if( err != Z_OK ) { cerr << "while 1" << endl; exit( -1 ); } return 0; } int ZipWriter::writefunc( void* user, const char* buf, unsigned length ) { return ((ZipWriter*)user)->Write( buf, length ); } // ------------------------------------------------------------------------ #ifdef TEST_ZIPWRITE int main( int argc, char* argv[] ) { if( argc < 3 ) { cerr << "need 3 args" << endl; exit( -1 ); } std::ofstream zipout( argv[1] ); ZipWriter zw( zipout ); for( int f = 2; f #include #include #include #include #include class ZipWriter { struct fileinfo { unsigned short last_mod_file_time; unsigned short last_mod_file_date; unsigned int crc32; unsigned int compressed_size; unsigned int uncompressed_size; unsigned short file_name_length; unsigned int rel_offset_local_header; std::string file_name; }; typedef std::vector fileinfos_t; fileinfos_t fileinfos; std::ostream& zip; std::ostream* out; z_stream zs; char cbuf[32768]; public: ZipWriter( std::ostream& z ) : zip( z ), out(0) { } std::ostream& GetStream( const char* filename ); ~ZipWriter(); private: void Close(); int Write( const char* buf, unsigned length ); static int writefunc( void* user, const char* buf, unsigned length ); }; #endif // ZIPWRITE_H fig2sxd-0.20/colors.cpp0000644000175000017500000000613011013412403012521 0ustar abab// -*-c++-*- // fixg2sxd - a utility to convert fig to sxd format // Copyright (C) 2003-2008 Alexander Bürger, acfb@users.sourceforge.net // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License as // published by the Free Software Foundation; either version 2 of the // License, or (at your option) any later version. // // This program is distributed in the hope that it will be useful, but // WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program; if not, write to the Free Software // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. #include "colors.h" #include "misc.h" #include #include #include #include using namespace std; static unsigned int hexcolors_with_minus_1[545]; unsigned int *hexcolor = 0; void read_color( istream& figfile ) { int color_number; string hex; // XXX bad if malformed hex value! figfile >> color_number >> hex; if( color_number<32 || color_number>543 ) fail( "Color number out of range." ); hexcolor[color_number] = strtol( hex.c_str()+1, 0, 16 ); } void initcolors() { hexcolor = hexcolors_with_minus_1 + 1; hexcolor[-1] = 0x000000; // Black hexcolor[0] = 0x000000; // Black hexcolor[1] = 0x0000ff; // Blue hexcolor[2] = 0x00ff00; // Green hexcolor[3] = 0x00ffff; // Cyan hexcolor[4] = 0xff0000; // Red hexcolor[5] = 0xff00ff; // Magenta hexcolor[6] = 0xffff00; // Yellow hexcolor[7] = 0xffffff; // White hexcolor[8] = 0x000090; // four shades of blue (dark to lighter) hexcolor[9] = 0x0000b0; hexcolor[10] = 0x0000d0; hexcolor[11] = 0x87ceff; hexcolor[12] = 0x009000; // three shades of green (dark to lighter) hexcolor[13] = 0x00b000; hexcolor[14] = 0x00d000; hexcolor[15] = 0x009090; // three shades of cyan (dark to lighter) hexcolor[16] = 0x00b0b0; hexcolor[17] = 0x00d0d0; hexcolor[18] = 0x900000; // three shades of red (dark to lighter) hexcolor[19] = 0xb00000; hexcolor[20] = 0xd00000; hexcolor[21] = 0x900090; // three shades of magenta (dark to lighter) hexcolor[22] = 0xb000b0; hexcolor[23] = 0xd000d0; hexcolor[24] = 0x803000; // three shades of brown (dark to lighter) hexcolor[25] = 0xa04000; hexcolor[26] = 0xc06000; hexcolor[27] = 0xff8080; // four shades of pink (dark to lighter) hexcolor[28] = 0xffa0a0; hexcolor[29] = 0xffc0c0; hexcolor[30] = 0xffe0e0; hexcolor[31] = 0xffd700; // Gold int i; for( i=32; i<544; ++i ) hexcolor[i] = 0; } std::string colorstring(int index) { return color2string( hexcolor[index] ); } string color2string(unsigned int color) { static const char map[17] = "0123456789ABCDEF"; char tmp[8] = "#123456"; for( int i=0; i<6; ++i ) { tmp[6-i] = map[ color&0xf ]; color >>= 4; } return string(tmp); } fig2sxd-0.20/xfig_spline.cpp0000644000175000017500000002232411101117265013540 0ustar abab// -*-c++-*- // fixg2sxd - a utility to convert fig to sxd format // Copyright (C) 2003-2008 Alexander Bürger, acfb@users.sourceforge.net // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License as // published by the Free Software Foundation; either version 2 of the // License, or (at your option) any later version. // // This program is distributed in the hope that it will be useful, but // WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program; if not, write to the Free Software // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. #include "xfigobjects.h" #include "check.h" #include "misc.h" #include "vector2.h" #include "xmlwrite.h" #include // TODO: interpolated splines bad, x-splines missing // TODO: control points are not exacty as in xfig Spline::~Spline() { delete p; delete shapefactors; } istream& Spline::read( istream& figfile ) { LineFillStyle lfstmp; lfstmp.read( figfile, sub_type, depth ); figfile >> cap_style >> forward_arrow >> backward_arrow >> npoints; keep_range( sub_type, "spline sub_type", 0, 5 ); if( (sub_type&1)==0 ) // cap_style is used only for open splines keep_range( cap_style, "spline(open) cap_style", 0, 2 ); keep_range( forward_arrow, "spline forward_arrow", 0, 1 ); keep_range( backward_arrow, "spline backward_arrow", 0, 1 ); if( npoints<2 || npoints>65536 ) { ostringstream err; err << "Bad number of spline points " << npoints << " (accepted range = [2,65536])."; throw err.str(); } if( forward_arrow != 0 ) lfstmp.read_arrow( figfile, true ); if( backward_arrow != 0 ) lfstmp.read_arrow( figfile, false ); lfs = linefillstyles.insert( lfstmp ).first; lfs->stylename_line(); lfs->stylename_fill(); lfs->stylename(); // allocate more for easier loop for closed splines p = new Vector2f[npoints+2]; for( int i=0; i> x >> y; p[i] = Vector2f(x,y); } shapefactors = new float[npoints+2]; for( int i=0; i> shapefactors[i]; return figfile; } ostream& Spline::write( ostream& out ) { Vector2f moveto; // will store the initial moveto Vector2f lineto1; // will store the initial lineto for sub_type == 0 Vector2f lineto2; // will store the final lineto for sub_type == 0 vector curve; // will store sequences of controlpoint 1, // 2 and "target point" moveto = p[0]; Vector2f p0 = moveto; // first point of curveto if( sub_type == 0 || sub_type == 1 ) { // open/closed approximated spline // using middle-points was taken from fig2dev/genps Vector2f mid = (p[0]+p[1])/2; p0 = mid; if( sub_type == 0 ) { lineto1 = mid; } else { p[npoints] = p[0]; p[npoints+1] = p[1]; moveto = mid; } const int stop = (sub_type==0) ? npoints-1 : npoints+1; for( int i=1; i= 0 ) { txp = (-b.X()+sqrt(txD))/(3*a.X()); txm = (-b.X()-sqrt(txD))/(3*a.X()); } } else if ( b.X()!=0 ) { txp = txm = -0.5*c.X()/b.X(); } txp = max( min( txp, 1.0f ), 0.0f ); txm = max( min( txm, 1.0f ), 0.0f ); float xp = ((a.X()*txp + b.X() )*txp + c.X())*txp + p0.X(); float xm = ((a.X()*txm + b.X() )*txm + c.X())*txm + p0.X(); maxx = max( maxx, max( xp, xm ) ); minx = min( minx, min( xp, xm ) ); float tyD = b.Y()*b.Y()-3*a.Y()*c.Y(); float typ=0, tym=1; if( a.Y() != 0 ) { if( tyD >= 0 ) { typ = (-b.Y()+sqrt(tyD))/(3*a.Y()); tym = (-b.Y()-sqrt(tyD))/(3*a.Y()); } } else if ( b.Y()!=0 ) { typ = tym = -0.5*c.Y()/b.Y(); } typ = max( min( typ, 1.0f ), 0.0f ); tym = max( min( tym, 1.0f ), 0.0f ); float yp = ((a.Y()*typ + b.Y() )*typ + c.Y())*typ + p0.Y(); float ym = ((a.Y()*tym + b.Y() )*tym + c.Y())*tym + p0.Y(); maxy = max( maxy, max( yp, ym ) ); miny = min( miny, min( yp, ym ) ); p0 = p3; } if( sub_type == 0 ) { maxx = max( maxx, lineto1.X() ); maxx = max( maxx, lineto2.X() ); maxy = max( maxy, lineto1.Y() ); maxy = max( maxy, lineto2.Y() ); minx = min( minx, lineto1.X() ); minx = min( minx, lineto2.X() ); miny = min( miny, lineto1.Y() ); miny = min( miny, lineto2.Y() ); } const Vector2f m( minx, miny ); #if 0 Node viewBox("draw:rect"); viewBox["draw:style-name"] << lfs->stylename_line(); viewBox["draw:z-index"] << depth2z(depth); viewBox["draw:layer"] << "layout"; viewBox["svg:x"] << tr(minx) << "cm"; viewBox["svg:y"] << tr(miny) << "cm"; viewBox["svg:width"] << tr(maxx-minx) << "cm"; viewBox["svg:height"] << tr(maxy-miny) << "cm"; out << viewBox; #endif // build xml Node path("draw:path"); path["draw:style-name"] << lfs->stylename(); path["draw:z-index"] << depth2z(depth); path["draw:layer"] << "layout"; path["svg:x"] << tr(minx) << "cm"; path["svg:y"] << tr(miny) << "cm"; path["svg:width"] << tr(maxx-minx) << "cm"; path["svg:height"] << tr(maxy-miny) << "cm"; path["svg:viewBox"] << "0 0 " << tr_p(maxx-minx)<<' '< construct path from stored points ostringstream& d=path["svg:d"]; d << "M " << tr_p(moveto-m); if( sub_type == 0 ) d << "L " << tr_p(lineto1-m); for( unsigned int i=0; i= 1<<16 ) { static bool warn_long = false; if( !warn_long ) { cerr << "Warning: some splines might be too large for OpenOffice.org." << endl; warn_long = true; } } // fill it, if necessary if( sub_type % 2 == 0 ) { const string line_d = d.str(); if( lfs->hasFill() ) { d << " Z"; path["draw:style-name"] << lfs->stylename_fill(); out << path; } if( lfs->hasLine() ) { path["draw:style-name"] << lfs->stylename_line(); path["svg:d"] << line_d; out << path; } } else { d << " Z"; if( lfs->hasLine() || lfs->hasFill() ) out << path; } return out; } fig2sxd-0.20/misc.cpp0000644000175000017500000000333311013412403012155 0ustar abab// -*-c++-*- // fixg2sxd - a utility to convert fig to sxd format // Copyright (C) 2003-2008 Alexander Bürger, acfb@users.sourceforge.net // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License as // published by the Free Software Foundation; either version 2 of the // License, or (at your option) any later version. // // This program is distributed in the hope that it will be useful, but // WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program; if not, write to the Free Software // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. #include "misc.h" #include #include using namespace std; int resolution; /** Convert from xfig units (points per inch) to cm. */ float tr(float xfigunits) { return xfigunits/(resolution/2.54f); } ostream& operator<<(ostream& out, ostream_tr const& o) { return out << tr(o.v.X()) << ' ' << tr(o.v.Y()); } float tr80(float xfigunits) { return xfigunits/(80/2.54f); } int tr_p(float xfigunits) { return int(1000*tr(xfigunits)); } ostream& operator<<(ostream& out, ostream_tr_p const& o) { return out << tr_p(o.v.X()) << ' ' << tr_p(o.v.Y()); } void fail( const char* msg ) { ostringstream err; err << "Error: " << msg << endl; throw err.str(); } void skip_comment( istream& figfile ) { figfile >> ws; while( figfile.peek() == '#' ) figfile.ignore( 1<<30, '\n' ); } int depth_max; int depth2z(int depth) { return depth_max - depth; } fig2sxd-0.20/style_line.cpp0000644000175000017500000002420311062521462013402 0ustar abab// -*-c++-*- // fixg2sxd - a utility to convert fig to sxd format // Copyright (C) 2003-2008 Alexander Bürger, acfb@users.sourceforge.net // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License as // published by the Free Software Foundation; either version 2 of the // License, or (at your option) any later version. // // This program is distributed in the hope that it will be useful, but // WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program; if not, write to the Free Software // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. #include "styles.h" #include "xmlwrite.h" #include "check.h" #include "colors.h" #include "misc.h" extern unsigned int *hexcolor; // TODO: cap styles using namespace std; namespace { struct Dash { int line_style; int style_val; // xfig uses float Dash( int ls, int sv ) : line_style( ls ), style_val( sv ) { } bool operator<(Dash const& other) const; string GetNameAndWrite(Node& out) const; }; set written_dashes; string Dash::GetNameAndWrite(Node& out) const { if( line_style < 1 || line_style > 5 ) fail( "bad line_style < 1 or > 5 for dash" ); const char* names[6] = { 0/*solid*/, "dashed", "dotted", "dash-dotted", "dash-double-dotted", "dash-triple-dotted" }; ostringstream name; name << names[line_style] << '_' << style_val; if( written_dashes.find( *this ) == written_dashes.end() ) { written_dashes.insert( *this ); Node& dash = out.subnode("draw:stroke-dash"); dash["draw:dots1"] << "1"; dash["draw:dots1-length"] << (line_style == 2 ? 0.05:0.2) << "cm"; dash["draw:distance"] << tr80(style_val) << "cm"; dash["draw:style"] << "rect"; if( line_style >= 3 ) { dash["draw:dots2"] << (line_style-2); dash["draw:dots2-length"] << "0.05cm"; } dash["draw:name"] << name.str(); } return name.str(); } // ------------------------------------------------------------ struct Hatch { int style; int angle; int density; bool operator<(Hatch const& other) const; }; Hatch hatches[] = { { 1,150,3 }, { 1,30,3 }, { 2, 30,3 }, { 1,135,2 }, { 1, 45,2 }, { 2, 45,2 }, { 2,10,2 }, { 2,100,2 }, { 1, 0,3 }, { 1, 90,3 }, { 2, 0,3 }, { 2,20,3 }, { 2, 70,3 }, { 2, 15,3 }, { 2,115,3 }, { 2, 30,3 }, { 3, 0,4 }, { 2, 0,1 }, { 2, 45,1 }, { 2, 0,2 }, { 2, 40,2 }, { 2,50,2 } }; typedef pair hatch_color; set written_hatches; string write_hatch(Node& out, int h, int color) { ostringstream name; name << "Hatch_" << hatches[h].style << '_' << hatches[h].angle << '_' << hatches[h].density << '_' << color+1; hatch_color hc( hatches[h], color ); if( written_hatches.find(hc) == written_hatches.end() ) { Node& hatch = out.subnode("draw:hatch"); hatch["draw:name"] << name.str(); static const char *styles[3] = { "single", "double", "triple" }; hatch["draw:style"] << styles[hatches[h].style-1]; hatch["draw:distance"] << 0.3/hatches[h].density << "cm"; hatch["draw:rotation"] << 10*hatches[h].angle; hatch["draw:color"] << colorstring(color); written_hatches.insert( hc ); } return name.str(); } } const char* LineFillStyle::base = "Fig2SxdLine"; int LineFillStyle::number = 10; void LineFillStyle::read( istream& figfile, int& sub_type, int& depth, bool join ) { figfile >> sub_type >> line_style >> line_thickness >> pen_color >> fill_color >> depth >> pen_style >> area_fill >> style_val; if( join ) figfile >> linejoin; else linejoin = 0; keep_range( line_style, "line_style", -1, 5 ); keep_range( line_thickness, "line_thickness", 0.0f ); keep_range( pen_color, "pen_color", -1, 543 ); keep_range( fill_color, "fill_color", -1, 543 ); // pen style is unused, so ignore its value if( fill_color<=0 || fill_color==7 ) keep_range( area_fill, "area_fill", -1, 56 ); else keep_range( area_fill, "area_fill", -1, 62 ); keep_range( style_val, "style_val", 0.f ); if( join ) keep_range( linejoin, "line_join", 0, 2 ); // do not check upper limit for depth, but it should be >= 0 keep_range( depth, "depth", 0 ); } std::string LineFillStyle::stylename() const { if( mynumber == 0 ) mynumber = ++number; ostringstream tmp; tmp << base << mynumber; return tmp.str(); } std::string LineFillStyle::stylename_line() const { if( mynumber_line == 0 ) mynumber_line = ++number; ostringstream tmp; tmp << base << mynumber_line; return tmp.str(); } std::string LineFillStyle::stylename_fill() const { if( mynumber_fill == 0 ) mynumber_fill = ++number; ostringstream tmp; tmp << base << mynumber_fill; return tmp.str(); } void LineFillStyle::read_arrow( istream& figfile, bool forward ) { Arrow tmp; tmp.read( figfile ); arrowset::iterator a = arrows.insert( tmp ).first; if( forward ) forward_arrow = a; else backward_arrow = a; } bool LineFillStyle::hasLine() const { return line_thickness>0; } bool LineFillStyle::hasFill() const { return area_fill!=-1; } float LineFillStyle::linewith1 = 2.54/80.0; Node& LineFillStyle::write( Node& out ) const { int numbers[3] = { mynumber, mynumber_line, mynumber_fill }; string dashname; if( line_style>=1 && ( mynumber || mynumber_line ) ) { Dash dash( line_style, int(style_val) ); dashname = dash.GetNameAndWrite( out ); } for( int n=0; n<3; ++n ) { if( numbers[n] == 0 ) continue; Node& style = out.subnode("style:style"); style["style:name"] << base << numbers[n]; style["style:family"] << "graphics"; style["style:parent-style-name"] << base; Node& prop = style.subnode("style:properties"); if( n==0 || n==1 ) { if( forward_arrow != arrows.end() ) { prop["draw:marker-end"] << forward_arrow->name(); prop["draw:marker-end-width"] << tr(forward_arrow->arrow_width) << "cm"; } if( backward_arrow != arrows.end() ) { prop["draw:marker-start"] << backward_arrow->name(); prop["draw:marker-start-width"] << tr(backward_arrow->arrow_width) << "cm"; } } if( line_thickness==0 || n==2 ) { prop["draw:stroke"] << "none"; } else { if( linejoin >= 0 ) { const char* join[3] = { "miter", "round", "bevel" }; prop["svg:stroke-linejoin"] << join[linejoin]; } if( line_thickness == 1 ) prop["svg:stroke-width"] << linewith1 << "cm"; else prop["svg:stroke-width"] << tr80(line_thickness) << "cm"; prop["svg:stroke-color"] << colorstring(pen_color); if( dashname.length() ) { prop["draw:stroke"] << "dash"; prop["draw:stroke-dash"] << dashname; } else { prop["draw:stroke"] << "solid"; } } if( n==1 || area_fill == -1 ) { prop["draw:fill"] << "none"; } else if( area_fill >= 0 && area_fill <= 40 ) { unsigned int r= (hexcolor[fill_color] >> 16) & 0xff; unsigned int g= (hexcolor[fill_color] >> 8 ) & 0xff; unsigned int b= (hexcolor[fill_color] ) & 0xff; if( area_fill < 20 ) { r = (unsigned int)(r*area_fill/20.0); g = (unsigned int)(g*area_fill/20.0); b = (unsigned int)(b*area_fill/20.0); } else if( area_fill > 20 ) { r = 0xff - (unsigned int)((0xff-r)*area_fill/20.0); g = 0xff - (unsigned int)((0xff-g)*area_fill/20.0); b = 0xff - (unsigned int)((0xff-b)*area_fill/20.0); } unsigned int fill = (r << 16) | (g << 8) | b; prop["draw:fill"] << "solid"; prop["draw:fill-color"] << color2string( fill ); } else if( area_fill >= 41 && area_fill <= 62 ) { prop["draw:fill"] << "hatch"; prop["draw:fill-hatch-name"] << write_hatch( out, area_fill-41, pen_color ); prop["draw:fill-hatch-solid"] << "true"; prop["draw:fill-color"] << colorstring( fill_color ); } } return out; } #define cmp(x) if( x < o.x ) return true; if( x > o.x ) return false #define cmpi(x,s) if( x==s.end() ) { if( o.x!=s.end() ) return true; } \ else { if( o.x==s.end() ) return false; else if( *x<*o.x ) return true; } bool LineFillStyle::operator<(LineFillStyle const& o) const { cmp( line_style ); cmp( line_thickness ); cmp( pen_color ); cmp( fill_color ); cmp( fill_color ); cmp( pen_style ); cmp( area_fill ); cmp( style_val ); cmp( linejoin ); cmpi( forward_arrow, arrows ); cmpi( backward_arrow, arrows ); if( forward_arrow!=arrows.end() && o.forward_arrow!=arrows.end() ) cmp( forward_arrow->arrow_width ); if( backward_arrow!=arrows.end() && o.backward_arrow!=arrows.end() ) cmp( backward_arrow->arrow_width ); return false; } namespace { bool Dash::operator<(Dash const& o) const { cmp( line_style ); cmp( style_val ); return false; } bool Hatch::operator<(Hatch const& o) const { cmp( style ); cmp( angle ); cmp( density ); return false; } } lfsset linefillstyles; fig2sxd-0.20/xfig_compound.cpp0000644000175000017500000000245411013412403014066 0ustar abab// -*-c++-*- // fixg2sxd - a utility to convert fig to sxd format // Copyright (C) 2003-2008 Alexander Bürger, acfb@users.sourceforge.net // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License as // published by the Free Software Foundation; either version 2 of the // License, or (at your option) any later version. // // This program is distributed in the hope that it will be useful, but // WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program; if not, write to the Free Software // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. #include "xfigobjects.h" istream& OpenCompound::read( istream& figfile ) { figfile >> upperleft_corner_x >> upperleft_corner_y >> lowerright_corner_x >> lowerright_corner_y; return figfile; } ostream& OpenCompound::write( ostream& out ) { out << "" << endl; return out; } istream& CloseCompound::read( istream& figfile ) { return figfile; } ostream& CloseCompound::write( ostream& out ) { out << "" << endl; return out; } fig2sxd-0.20/styles.h0000644000175000017500000000632711062521430012225 0ustar abab// -*-c++-*- // fixg2sxd - a utility to convert fig to sxd format // Copyright (C) 2003-2008 Alexander Bürger, acfb@users.sourceforge.net // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License as // published by the Free Software Foundation; either version 2 of the // License, or (at your option) any later version. // // This program is distributed in the hope that it will be useful, but // WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program; if not, write to the Free Software // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. #ifndef STYLES_H #define STYLES_H #include "xmlwrite.h" #include #include #include using namespace std; class TextStyle { public: int color, font, font_flags; float font_size; // (0: Left justified 1: Center justified 2: Right justified) int justification; static const char* base; static int number; mutable int mynumber; string stylenumber() const; Node& write( Node& styles ) const; bool operator<( TextStyle const& o ) const; TextStyle() : justification(0), mynumber(0) { } }; typedef set tsset; extern tsset textstyles; // ------------------------------------------------------------------------ class Arrow { public: int arrow_type; // 0 stick, 1 closed triangle, 2 closed with indented butt, 3 // closed with pointed butt int arrow_style; // (0 hollow (white fill), 1 filled) float arrow_width; // (Fig units) bool operator<(Arrow const&) const; istream& read( istream& ); Node& write( Node& out ) const; string name() const; }; typedef set arrowset; extern arrowset arrows; // ------------------------------------------------------------------------ class LineFillStyle { public: int line_style; // (enumeration type) float line_thickness; // (1/80 inch) int pen_color; // (enumeration type, pen color) int fill_color; // (enumeration type, fill color) int pen_style; // (pen style, not used) int area_fill; // (enumeration type, -1 = no fill) float style_val; // (1/80 inch) int linejoin; arrowset::iterator forward_arrow, backward_arrow; static const char* base; void read( istream& figfile, int& sub_type, int& depth, bool join=false ); void read_arrow( istream& figfile, bool forward ); bool operator<(LineFillStyle const& o) const; static int number; std::string stylename() const; std::string stylename_line() const; std::string stylename_fill() const; Node& write( Node& out ) const; bool hasLine() const; bool hasFill() const; static float linewith1; LineFillStyle() : linejoin(-1), forward_arrow(arrows.end()), backward_arrow(arrows.end()), mynumber( 0 ), mynumber_line(0), mynumber_fill(0) { } private: mutable int mynumber, mynumber_line, mynumber_fill; }; typedef std::set lfsset; extern lfsset linefillstyles; #endif // STYLES_H fig2sxd-0.20/fig2sxd.cpp0000644000175000017500000004356011101116521012576 0ustar abab// -*-c++-*- // fixg2sxd - a utility to convert fig to sxd format // Copyright (C) 2003-2008 Alexander Bürger, acfb@users.sourceforge.net // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License as // published by the Free Software Foundation; either version 2 of the // License, or (at your option) any later version. // // This program is distributed in the hope that it will be useful, but // WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program; if not, write to the Free Software // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. #include "xfigobjects.h" #include "colors.h" #include "misc.h" #include "xmlwrite.h" #include "zipwrite.h" #include #include #include #include #include #include #include #include #include #define SOME_STYLES_ONLY_IN_CONTENT 1 using namespace std; static int papersize; static enum { Portrait, Landscape } orientation = Portrait; static const char* papersizes[15] = { "Letter", "Legal", "Ledger", "Tabloid", "A", "B", "C", "D", "E", "A4", "A3", "A2", "A1", "A0", "B5" }; // all sizes in cm static float paperwidths[15] = { 21.59 /*Letter*/, 21.59 /*Legal*/, 10, 27.958/*Tabloid*/, 10, 10, 10, 10, 10, 21.0/*A4*/, 29.7, 42.0, 59.4, 84.1 }; static float paperheights[15] = { 27.94 /*Letter*/, 35.565/*Legal*/, 10, 43.127/*Tabloid*/, 10, 10, 10, 10, 10, 29.7/*A4*/, 42.0, 59.4, 84.1, 118.9 }; static vector xfigobjects; static const char* xmlheader = ""; static const char* xmlnamespaces = " xmlns:draw=\"http://openoffice.org/2000/drawing\"" " xmlns:style=\"http://openoffice.org/2000/style\"" " xmlns:office=\"http://openoffice.org/2000/office\"" " xmlns:text=\"http://openoffice.org/2000/text\"" " xmlns:svg=\"http://www.w3.org/2000/svg\"" " xmlns:fo=\"http://www.w3.org/1999/XSL/Format\"" " xmlns:dc=\"http://purl.org/dc/elements/1.1/\"" " xmlns:meta=\"http://openoffice.org/2000/meta\"" " xmlns:xlink=\"http://www.w3.org/1999/xlink\""; static void write_file( ostream& sxdfile ) { float pw = paperwidths[papersize]; float ph = paperheights[papersize]; if( orientation == Landscape ) swap( pw, ph ); Node styles("office:styles"); Node autostyles("office:automatic-styles"); Node& linebase = styles.subnode("style:style"); linebase["style:name"] << LineFillStyle::base; linebase["style:family"] << "graphics"; linebase["style:parent-style-name"] << "standard"; Node& textbase = styles.subnode("style:style"); textbase["style:name"] << TextStyle::base; textbase["style:parent-style-name"] << "standard"; textbase["style:family"] << "graphics"; // paragraph textbase["style:class"] << "text"; Node& textbaseprop = textbase.subnode("style:properties"); textbaseprop["fo:font-family"] << "Helvetica"; textbaseprop["fo:font-weight"] << "normal"; textbaseprop["fo:font-style"] << "normal"; textbaseprop["fo:color"] << "#000000"; textbaseprop["fo:font-size"] << "10pt"; textbaseprop["fo:padding-left"] << "0cm"; textbaseprop["fo:padding-right"] << "0cm"; textbaseprop["fo:padding-top"] << "0cm"; textbaseprop["fo:padding-bottom"] << "0cm"; textbaseprop["draw:fill"] << "none"; textbaseprop["draw:stroke"] << "none"; #ifndef SOME_STYLES_ONLY_IN_CONTENT // does not work here as of OOo 2.4.0 Node& narrow = autostyles.subnode("style:style"); narrow["style:name"] << "P1"; narrow["style:family"] << "paragraph"; Node& narrowprop = narrow.subnode("style:properties"); narrowprop["style:text-scale"] << "90%"; #endif for( set::iterator i=textstyles.begin(); i!=textstyles.end(); ++i ) i->write( styles ); for( arrowset::iterator i=arrows.begin(); i!=arrows.end(); ++i ) i->write( styles ); for( set::iterator i=linefillstyles.begin(); i!=linefillstyles.end(); ++i ) i->write( styles ); Node& pm = autostyles.subnode("style:page-master"); pm["style:name"] << "PM1"; Node& pmprop = pm.subnode( "style:properties" ); pmprop["fo:margin-top"] << "0cm"; pmprop["fo:margin-bottom"] << "0cm"; pmprop["fo:margin-left"] << "0cm"; pmprop["fo:margin-right"] << "0cm"; pmprop["fo:page-width"] << pw << "cm"; pmprop["fo:page-height"] << ph << "cm"; pmprop["style:print-orientation"] << (orientation == Landscape ? "landscape" : "portrait"); Node& dp1 = autostyles.subnode("style:style"); dp1["style:family"] << "drawing-page"; dp1["style:name"] << "dp1"; Node& dp1prop = dp1.subnode("style:properties"); dp1prop["draw:background-size"] << "border"; dp1prop["draw:fill"] << "none"; Node& img = autostyles.subnode("style:style"); img["style:family"] << "graphics"; img["style:name"] << "gr_img"; Node& imgprop = img.subnode("style:properties"); imgprop["draw:stroke"] << "none"; imgprop["draw:fill"] << "none"; if( xfigobjects.size()>0 ) { // loop over all objects to find minmal/maximal depth vector::iterator i=xfigobjects.begin(); depth_max = (*i)->depth; while( ++i != xfigobjects.end() ) depth_max = max( depth_max, (*i)->depth ); } ZipWriter sxd( sxdfile ); // write mimetype sxd.GetStream("mimetype") << "application/vnd.sun.xml.draw" << endl; { // write manifest Node manifest("manifest:manifest"); manifest["xmlns:manifest"] << "http://openoffice.org/2001/manifest"; Node& zip = manifest.subnode("manifest:file-entry"); zip["manifest:media-type"] << "application/vnd.sun.xml.draw"; zip["manifest:full-path"] << "/"; Node& cx = manifest.subnode("manifest:file-entry"); cx["manifest:media-type"] << "text/xml"; cx["manifest:full-path"] << "content.xml"; Node& sx = manifest.subnode("manifest:file-entry"); sx["manifest:media-type"] << "text/xml"; sx["manifest:full-path"] << "styles.xml"; Node& mx = manifest.subnode("manifest:file-entry"); mx["manifest:media-type"] << "text/xml"; mx["manifest:full-path"] << "meta.xml"; sxd.GetStream("META-INF/manifest.xml" ) << xmlheader << endl << "" << endl << manifest; } { // write meta.xml time_t now = time(0); char creationtime[30]; strftime( creationtime, sizeof(creationtime), "%Y-%m-%dT%H:%M:%S", localtime(&now) ); sxd.GetStream("meta.xml") << xmlheader << endl << "" << endl << "" << endl << " " << endl << " fig2sxd" << endl << " " << creationtime << "" << endl << " " << endl << "" << endl; } { // write content.xml ostream& contentxml = sxd.GetStream( "content.xml" ); contentxml << xmlheader << "" << endl << "" << endl; #ifdef SOME_STYLES_ONLY_IN_CONTENT // for narrow text, scaling must be defined here; other places // do not work as of OOo 2.4.0 Node auto2("office:automatic-styles"); Node& P1 = auto2.subnode("style:style"); P1["style:name"] << "P1"; P1["style:family"] << "paragraph"; Node& P1prop = P1.subnode("style:properties"); P1prop["style:text-scale"] << "90%"; contentxml << auto2; #endif contentxml << "" << endl << "" << endl; for( vector::iterator i=xfigobjects.begin(); i != xfigobjects.end(); ++i ) (*i)->write( contentxml ); contentxml << "" << endl << "" << endl << "" << endl; } { // write styles.xml ostream& stylesxml = sxd.GetStream( "styles.xml" ); stylesxml << xmlheader << endl << "" << endl << "" << endl << styles << autostyles << "" << endl << " " << endl << " " << endl << " " << endl << " " << endl << " " << endl << " " << endl << " " << endl << " " << endl << "" << endl << "" << endl; } } static void read_file( istream& figfile ) { string linebuf; // check if it's a fig file; first line is a comment, but we // should not skip it getline( figfile, linebuf ); if( linebuf.compare( 0, 8, "#FIG 3.2" ) != 0 ) { cerr << "linebuf =>" << linebuf << "<=" << endl; fail( "Not a figfile or unknown fig format (only 3.2 is known)." ); } // read orientation skip_comment( figfile ); getline( figfile, linebuf ); if( linebuf == "Landscape" ) { orientation = Landscape; } else if( linebuf != "Portrait" ) { fail( "Bad orientation." ); } // read justification enum { Center, FlushLeft } justification = Center; skip_comment( figfile ); getline( figfile, linebuf ); if( linebuf == "Flush left" ) { justification = FlushLeft; } else if( linebuf != "Center" ) { fail( "Bad justification." ); } // read units enum { Metric, Inches } units = Metric; skip_comment( figfile ); getline( figfile, linebuf ); if( linebuf == "Inches" ) { units = Inches; } else if( linebuf != "Metric" ) { fail( "Bad units." ); } // read papersize skip_comment( figfile ); string papersize_name; figfile >> papersize_name; for( papersize=0; papersize<15; ++papersize ) { if( strcasecmp( papersize_name.c_str(), papersizes[papersize] ) == 0 ) break; } if( papersize == 15 ) fail( "Bad papersize." ); // read magnification skip_comment( figfile ); float magnification; figfile >> magnification; figfile.ignore( 1024, '\n' ); // read multipageness skip_comment( figfile ); enum { Single, Multiple } multipage = Single; getline( figfile, linebuf ); if( linebuf == "Multiple" ) { multipage = Multiple; } else if( linebuf != "Single" ) { fail( "Bad multipageness." ); } // read transparent color skip_comment( figfile ); int transparentcolor = -5; figfile >> transparentcolor; if( transparentcolor < -3 || transparentcolor > 543 ) fail( "Bad transparent color number." ); // skip optional comment skip_comment( figfile ); // read resolution and coordinate system id int coord_system; figfile >> resolution >> coord_system; if( resolution < 1 || coord_system != 2 ) fail( "Bad resolution / coord_system." ); while( 1 ) { // ignore comments; returns EOF if file ends skip_comment( figfile ); if( figfile.eof() ) break; int object_code; figfile >> object_code; switch( object_code ) { case 0: read_color( figfile ); break; case 1: { Ellipse* e = new Ellipse(); e->read( figfile ); xfigobjects.push_back( e ); break; } case 2: { Poly* p = new Poly(); p->read( figfile ); xfigobjects.push_back( p ); break; } case 3: { Spline* s = new Spline(); s->read( figfile ); xfigobjects.push_back( s ); break; } case 4: { Text* t = new Text(); t->read( figfile ); xfigobjects.push_back( t ); break; } case 5: { Arc* a = new Arc(); a->read( figfile ); xfigobjects.push_back( a ); break; } case 6: { OpenCompound* c = new OpenCompound(); c->read( figfile ); xfigobjects.push_back( c ); break; } case -6: { CloseCompound* c = new CloseCompound(); c->read( figfile ); xfigobjects.push_back( c ); break; } default: { ostringstream err; err << "Unknown object code: " << object_code; throw err.str(); } } } } static void usage( const char* cmdname, bool err=true ) { ostream& out = (err ? cerr : cout); out << cmdname << " [-w] [-l(ine)w(idth)1 l] figfile [sxdfile]" << endl << endl << "Using `-' as figfile makes the program read from stdin." << endl << endl << "Omitting sxdfile when figfile ends with .fig or .xfig, makes"<= 0" ); LineFillStyle::linewith1 = w; } if( option0( "-w", argc, argv ) ) { out_of_range_error = false; cerr << "Out of range values will be sanitized." << endl; } bool dotfig=false, dotxfig=false; string figfilename; unsigned int ffnl=0; if( argc>=2 ) { figfilename = argv[1]; ffnl = figfilename.length(); } if( argc==2 ) { dotfig = ( ffnl>4 && figfilename.rfind( ".fig")+4==ffnl ); dotxfig = ( ffnl>5 && figfilename.rfind(".xfig")+5==ffnl ); } if( argc != 3 && !dotfig && !dotxfig ) { usage( argv[0], true ); exit( EXIT_FAILURE ); } initcolors(); // read xfig file / stdin if( figfilename != "-" ) { ifstream infile( figfilename.c_str() ); read_file( infile ); } else { read_file( std::cin ); } // write sxd file / stdout string sxd; if( dotfig ) sxd = figfilename.substr(0,ffnl-4)+".sxd"; else if( dotxfig ) sxd = figfilename.substr(0,ffnl-5)+".sxd"; else sxd = argv[2]; if( sxd.empty() ) throw string( "output filename is empty" ); if( sxd != "-" ) { ofstream sxdfile( sxd.c_str(), ios::binary ); write_file( sxdfile ); } else { write_file( std::cout ); } return EXIT_SUCCESS; } int main( int argc, char* argv[] ) { try { return try_catched_main( argc, argv ); } catch( string msg ) { cerr << msg << endl << endl << "If you think this is message is caused by a problem in fig2sxd," << endl << "please contact the author(s) via http://fig2sxd.sourceforge.net/." << endl << "Thank you." << endl << endl << "To get your file converted anyway, you could try the '-w' option." << endl; return EXIT_FAILURE; } } fig2sxd-0.20/style_text.cpp0000644000175000017500000000661311013412403013432 0ustar abab// -*-c++-*- // fixg2sxd - a utility to convert fig to sxd format // Copyright (C) 2003-2008 Alexander Bürger, acfb@users.sourceforge.net // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License as // published by the Free Software Foundation; either version 2 of the // License, or (at your option) any later version. // // This program is distributed in the hope that it will be useful, but // WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program; if not, write to the Free Software // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. #include "styles.h" #include "xmlwrite.h" #include "colors.h" #include #include tsset textstyles; const char* TextStyle::base = "Fig2SxdText"; int TextStyle::number = 10; string TextStyle::stylenumber() const { if( mynumber==0 ) mynumber = ++number; ostringstream s; s << base << mynumber; return s.str(); } Node& TextStyle::write( Node& out ) const { const char* fontname = "Helvetica"; bool bold = false; bool italic = false; if( font_flags & 0x4 ) { // Postscript fonts //cout << "ps fonts" << endl; if( font == -1 ) { // default } else if( font >= 0 && font <= 31 ) { const char* fontnames[] = { "Times New Roman", "AvantGarde", "Bookman", "Courier", "Helvetica", "Helvetica", // narrow by using "narrow" text style "New Century Schoolbook", "Palatino" }; fontname = fontnames[font/4]; bold = ((font & 2) != 0); italic = ((font & 1) != 0); } else if( font>=32 && font<=34 ) { const char* fontnames[] = { "Standard Symbols L", "Zapf Chancery", "Zapf Dingbats" }; fontname = fontnames[font-32]; } } else { // LaTeX fonts if( font>=0 && font<=5 ) { const char* fontnames[] = { "Helvetica", "Times New Roman", "Times New Roman", "Times New Roman", "Courier" }; fontname = fontnames[font]; bold = (font == 2); italic = (font == 3); } } Node& style = out.subnode("style:style"); style["style:name"] << stylenumber(); style["style:family"] << "graphics"; // paragraph style["style:class"] << "text"; style["style:parent-style-name"] << base; Node& prop = style.subnode("style:properties"); prop["fo:font-family"] << fontname; prop["draw:textarea-vertical-align"] << "middle"; prop["fo:font-weight"] << (bold ? "bold" : "normal" ); prop["fo:font-style"] << (italic ? "italic" : "normal" ); prop["fo:color"] << colorstring(color); prop["fo:font-size"] << (font_size*(72.0/80.0)) << "pt"; const char* align[3] = { "left", "center", "right" }; prop["draw:textarea-horizontal-align"] << align[justification]; return out; } #define cmp(x) if( x < o.x ) return true; if( x > o.x ) return false bool TextStyle::operator<(TextStyle const& o) const { cmp( color ); cmp( font ); cmp( font_flags ); cmp( font_size ); cmp( justification ); return false; } fig2sxd-0.20/Makefile0000644000175000017500000000446411013407406012173 0ustar abab # fixg2sxd - a utility to convert fig to sxd format # Copyright (C) 2003,2004 Alexander Bürger, acfb@users.sourceforge.net # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License as # published by the Free Software Foundation; either version 2 of the # License, or (at your option) any later version. # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. # to cross-compile for win32, try: make CXX=i586-mingw32msvc-g++ # INCLUDES=-I/tmp/zlib-win32/include LIBS=/tmp/zlib-win32/lib/libz.a # to put binaries into separate directory (good for cross-compile), go # there and try: make -f ..srcdir../Makefile SRCDIR=..srcdir.. where # ..srcdir.. is the path to the source directory DESTDIR = SRCDIR= TARGET1 = fig2sxd HEADERS1 = colors.h misc.h styles.h xfigobjects.h xmlwrite.h vector2.h \ zipwrite.h SOURCES1 = fig2sxd.cpp xfig_arc.cpp xfig_compound.cpp xfig_ellipse.cpp \ xfig_poly.cpp xfig_spline.cpp xfig_text.cpp \ style_arrow.cpp style_line.cpp style_text.cpp colors.cpp misc.cpp \ xmlwrite.cpp zipwrite.cpp check.cpp OBJECTS1 = $(SOURCES1:%.cpp=%.o) TARGETS = $(TARGET1) ARCHFILES_1 = $(HEADERS1) $(SOURCES1) Makefile fig2sxd.1 ARCHFILES = $(ARCHFILES_1:%=$(MYDIR)/%) DEPEND = .depend- DEPFILES = $(SOURCES1:%.cpp=$(DEPEND)%.dep) CXX = g++ CXXFLAGS = -Wall -W -O2 -g CXXFLAGS += $(INCLUDES) LIBS = -lz $(TARGET1): $(OBJECTS1) $(CXX) -o $@ $^ $(LIBS) $(OBJECTS1): %.o: $(SRCDIR)%.cpp $(DEPEND)%.dep $(CXX) $(CXXFLAGS) -o $@ -c $< $(DEPFILES): $(DEPEND)%.dep: $(SRCDIR)%.cpp $(CXX) $(INCLUDES) -M $< > $@ -include $(DEPFILES) clean: rm -f $(TARGETS) $(OBJECTS1) $(DEPFILES) all: install install: $(TARGET1) fig2sxd.1 install -d $(DESTDIR)/bin $(DESTDIR)/share/man/man1 install -m755 $(TARGET1) $(DESTDIR)/bin install -m644 fig2sxd.1 $(DESTDIR)/share/man/man1 tgz: tar czf `date +"../fig2sxd-%Y-%m-%d-%H-%M.tar.gz"` -C $(SRCDIR)../ \ $(ARCHFILES) .PHONY: all clean fig2sxd-0.20/xmlwrite.h0000644000175000017500000000515211013412403012543 0ustar abab// -*-c++-*- // fixg2sxd - a utility to convert fig to sxd format // Copyright (C) 2003-2008 Alexander Bürger, acfb@users.sourceforge.net // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License as // published by the Free Software Foundation; either version 2 of the // License, or (at your option) any later version. // // This program is distributed in the hope that it will be useful, but // WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program; if not, write to the Free Software // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. #ifndef _hdr_XMLWRITE_H #define _hdr_XMLWRITE_H #ifdef USE_MAP #include #endif #include #include #include #include // ------------------------------------------------------------------------ class Element { public: Element() { } virtual void write(std::ostream&,int,bool) const = 0; virtual ~Element() { } private: Element(Element const&); // disabled Element& operator=(Element const&); // disabled }; inline std::ostream& operator<<( std::ostream& o, Element const* e ) { e->write( o, 0, true ); return o; } inline std::ostream& operator<<( std::ostream& o, Element const& e ) { e.write( o, 0, true ); return o; } // ------------------------------------------------------------------------ class TextElement : public Element { std::ostringstream text; public: std::ostringstream& t() { return text; } virtual void write(std::ostream&,int,bool) const; virtual ~TextElement() { } }; // ------------------------------------------------------------------------ class Node : public Element { std::string name; bool indentation; std::vector elements; #ifdef USE_MAP typedef std::map attributes_t; #else typedef std::vector > attributes_t; #endif attributes_t attributes; public: Node( std::string const& name ); ~Node(); void SetName(std::string const& aName) { name = aName; } std::ostringstream& att(std::string const& attname); std::ostringstream& operator[](std::string const& attname) { return att( attname ); } Node& subnode( std::string const& subname ); TextElement& text(); virtual void write(std::ostream&,int,bool) const; }; #endif // _hdr_XMLWRITE_H fig2sxd-0.20/check.cpp0000644000175000017500000000335511013412403012303 0ustar abab// -*-c++-*- // fixg2sxd - a utility to convert fig to sxd format // Copyright (C) 2003-2008 Alexander Bürger, acfb@users.sourceforge.net // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License as // published by the Free Software Foundation; either version 2 of the // License, or (at your option) any later version. // // This program is distributed in the hope that it will be useful, but // WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program; if not, write to the Free Software // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. #include "check.h" #include #include #include using namespace std; bool out_of_range_error=true; template void keep_range( T& value, const char* name, const T mini, const T maxi ) { assert( mini <= maxi ); if( value < mini || value > maxi ) { if( out_of_range_error ) { ostringstream o; o << "Error: " << name << '=' << value << " out of range [" << mini << ',' << maxi << "]"; throw o.str(); } else { cerr << "Warning: " << name << " was " << value << " which is out of range [" << mini << ',' << maxi << "]; set to " << mini << '.' << endl; value = mini; } } } template void keep_range( float& v, const char* name, const float l, const float u ); template void keep_range( int& v, const char* name, const int l, const int u ); fig2sxd-0.20/misc.h0000644000175000017500000000330111013412403011615 0ustar abab// -*-c++-*- // fixg2sxd - a utility to convert fig to sxd format // Copyright (C) 2003-2008 Alexander Bürger, acfb@users.sourceforge.net // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License as // published by the Free Software Foundation; either version 2 of the // License, or (at your option) any later version. // // This program is distributed in the hope that it will be useful, but // WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program; if not, write to the Free Software // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. #ifndef MISC_H #define MISC_H #include "vector2.h" #include #include extern int resolution; /** Convert from xfig units (points per inch) to cm. */ float tr(float xfigunits); struct ostream_tr { Vector2f v; ostream_tr( Vector2f const& vv ) : v( vv ) { } }; std::ostream& operator<<(std::ostream& out, ostream_tr const& o); inline ostream_tr tr(Vector2f const& xfigunits) { return ostream_tr(xfigunits); } float tr80(float xfigunits); int tr_p(float xfigunits); struct ostream_tr_p { Vector2f v; ostream_tr_p( Vector2f const& vv ) : v( vv ) { } }; std::ostream& operator<<(std::ostream& out, ostream_tr_p const& o); inline ostream_tr_p tr_p(Vector2f const& xfigunits) { return ostream_tr_p(xfigunits);} void fail( const char* msg ); void skip_comment( std::istream& figfile ); extern int depth_max; int depth2z(int depth); #endif // MISC_H fig2sxd-0.20/xfig_arc.cpp0000644000175000017500000000623511013412403013010 0ustar abab// -*-c++-*- // fixg2sxd - a utility to convert fig to sxd format // Copyright (C) 2003-2008 Alexander Bürger, acfb@users.sourceforge.net // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License as // published by the Free Software Foundation; either version 2 of the // License, or (at your option) any later version. // // This program is distributed in the hope that it will be useful, but // WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program; if not, write to the Free Software // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. #include "check.h" #include "xfigobjects.h" #include "misc.h" #include "xmlwrite.h" #include istream& Arc::read( istream& figfile ) { LineFillStyle lfstmp; lfstmp.read( figfile, sub_type, depth ); figfile >> cap_style >> direction >> forward_arrow >> backward_arrow >> center_x >> center_y >> x1 >> y1 >> x2 >> y2 >> x3 >> y3; keep_range( sub_type, "arc sub_type", 1, 2 ); keep_range( cap_style, "arc cap_style", 0, 2 ); keep_range( direction, "arc direction", 0, 1 ); keep_range( forward_arrow, "arc forward_arrow", 0, 1 ); keep_range( backward_arrow, "arc backward_arrow", 0, 1 ); if( forward_arrow != 0 ) lfstmp.read_arrow( figfile, direction == 0 ); if( backward_arrow != 0 ) lfstmp.read_arrow( figfile, direction != 0 ); lfs = linefillstyles.insert( lfstmp ).first; lfs->stylename(); lfs->stylename_line(); lfs->stylename_fill(); return figfile; } ostream& Arc::write( ostream& out ) { float radius = sqrt( (center_x - x1)*(center_x - x1) + (center_y - y1)*(center_y - y1) ); // y increases to bottom => minus sign float angle_start = -atan2( y1-center_y, x1-center_x ) * 180/M_PI; float angle_end = -atan2( y3-center_y, x3-center_x ) * 180/M_PI; if( direction == 0 ) swap( angle_end, angle_start ); Node circle("draw:circle"); circle["draw:z-index"] << depth2z(depth); circle["svg:x"] << tr(center_x-radius) << "cm"; circle["svg:y"] << tr(center_y-radius) << "cm"; //circle["svg:r"] << tr(radius) << "cm"; circle["svg:width"] << 2*tr(radius) << "cm"; circle["svg:height"] << 2*tr(radius) << "cm"; circle["draw:start-angle"] << angle_start; circle["draw:end-angle"] << angle_end; if( sub_type == 2 ) { if( lfs->hasLine() || lfs->hasFill() ) { circle["draw:style-name"] << lfs->stylename(); circle["draw:kind"] << "section"; out << circle; } } else { if( lfs->hasFill() ) { circle["draw:style-name"] << lfs->stylename_fill(); circle["draw:kind"] << "cut"; out << circle; } if( lfs->hasLine() ) { circle["draw:style-name"] << lfs->stylename_line(); circle["draw:kind"] << "arc"; out << circle; } } return out; } fig2sxd-0.20/xfig_ellipse.cpp0000644000175000017500000000464211062520600013703 0ustar abab// -*-c++-*- // fixg2sxd - a utility to convert fig to sxd format // Copyright (C) 2003-2008 Alexander Bürger, acfb@users.sourceforge.net // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License as // published by the Free Software Foundation; either version 2 of the // License, or (at your option) any later version. // // This program is distributed in the hope that it will be useful, but // WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program; if not, write to the Free Software // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. #include "xfigobjects.h" #include "check.h" #include "misc.h" #include "xmlwrite.h" istream& Ellipse::read( istream& figfile ) { LineFillStyle lfstmp; lfstmp.read( figfile, sub_type, depth ); int direction; figfile >> direction >> angle >> center_x >> center_y >> radius_x >> radius_y >> start_x >> start_y >> end_x >> end_y; keep_range( sub_type, "ellipse sub_type", 1, 4 ); // direction should be always 1, but apparently it is sometimes 0; // don't complain as it is not used anyhow //keep_range( direction, "ellipse direction", 1, 1 ); keep_range( radius_x, "ellipse radius_x", 0.0f ); keep_range( radius_y, "ellipse radius_y", 0.0f ); lfs = linefillstyles.insert( lfstmp ).first; lfs->stylename(); return figfile; } ostream& Ellipse::write( ostream& out ) { // skip invisible object if( !( lfs->hasLine() || lfs->hasFill() ) ) return out; Node ellipse("draw:ellipse"); ellipse["draw:style-name"] << lfs->stylename(); ellipse["draw:z-index"] << depth2z(depth); if(angle==0) { ellipse["svg:x"] << tr(center_x-radius_x) << "cm"; ellipse["svg:y"] << tr(center_y-radius_y) << "cm"; } else { ellipse["draw:transform"] << "rotate(" << angle << ") " << "translate(" << tr(center_x-cos(angle)*radius_x-sin(angle)*radius_y) << "cm " << tr(center_y+sin(angle)*radius_x-cos(angle)*radius_y) << "cm)"; } ellipse["svg:width"] << 2*tr(radius_x) << "cm"; ellipse["svg:height"] << 2*tr(radius_y) << "cm"; return out << ellipse; } fig2sxd-0.20/changelog0000644000175000017500000000704311101116161012372 0ustar abab2008-10-25 Alexander Bürger * version 0.20 * print warnings for long polygons, polylines and splines 2008-10-17 Alexander Bürger * version 0.19 * Split long unfilled polylines to avoid problems with OpenOffice.org being apparently unable to read xml attribute values longer than 64kB. * Accept float coordinates (although xfig specifies only integers). 2008-05-22 Alexander Bürger * version 0.18 * Set numeric locale to "C" at startup. * Fix text placement problems by explicitly setting padding to 0cm. 2007-05-16 Alexander Bürger * version 0.17 * Add includes for gcc 4.3 and other compilers. (closes: debian #417183) * Support writing to stdout. Thanks for suggesting to Duncan Simpson . 2006-11-22 Alexander Bürger * version 0.16 * Fixed problem described in sf.net bug report #1563135 by skipping more comments. Comments between lines of one object still cause problems. 2006-11-21 Alexander Bürger * version 0.15 * Improved compatibility with OOo 2. * Fixed wrong font name for Symbol font. 2006-02-08 Alexander Bürger * version 0.14 * Added range-checks for most/all? values in the input as specified in xfig's FORMAT3.2. Now it does not crash any longer for the schemat.fig example of jfig. Thanks to Patrice Moreaux (LISTIC, Universite de Savoie, France) for pointing me at this problem. 2004-07-30 Alexander Bürger * version 0.13 * Added some #include to get sqrt with g++-3.4. (closes: debian bug #262380) 2004-04-29 Alexander Bürger * version 0.12 * Fixed infinite loop when reading files with multi-line comments. 2004-04-20 Alexander Bürger * version 0.11 * Fixed bug in placement of rotated ellipses. * Very basic support for LaTeX fonts. * Tried to improve text placement for very small font sizes. 2004-01-21 Alexander Bürger * version 0.9 * Tried to make zipwrite independent of endianness. 2004-01-16 Alexander Bürger * version 0.8 * Write meta.xml, mimetype and manifest.xml; this makes including the output in other OOo documents much easier. 2004-01-15 Alexander Bürger * version 0.7 * Add short option for linewidth. * Position splines much better. Rest of malpositioning comes from different shape of the splines. 2004-01-14 Alexander Bürger * version 0.6 * Fix bug in x-splines placing them completely wrong. * Do not write control characters (below ' '). * Add option to set line thickness for thickness 1. 2004-01-14 Alexander Bürger * version 0.5 * Skip invisible lines/fills. 2004-01-11 Alexander Bürger * version 0.4 * Better placement for font sizes < 7. * Support for "Helvetica-Narrow". * Stop using different layers for line and fill in filled, open objects. * Support for more than 1000 layers. 2004-01-07 Alexander Bürger * version 0.3 * Guess output filename when just input file is given. 2004-01-03 Alexander Bürger * version 0.2 * Write sxd file directly. 2003-12-28 Alexander Bürger * version 0.1 * Initial Release.