Logo Search packages:      
Sourcecode: fig2sxd version File versions

xfig_poly.cpp

// -*-c++-*-

// fixg2sxd - a utility to convert fig to sxd format

// Copyright (C) 2003-2006 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 int[npoints];
    y = new int[npoints];
    for( int i=0; i<npoints; ++i )
        figfile >> 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;
}

ostream& Poly::write( ostream& out )
{
    int maxx = x[0], maxy = y[0], minx=x[0], miny=y[0];
    for( int i=1; i<npoints; ++i ) { // start from 1
        if( x[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];
    }
    if( sub_type == 5 ) {
        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 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;
    }
    if( sub_type == 2 || sub_type == 4 ) { // rectangle
        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;
    }

    // store the polyline/polygon data temporarily
    Node poly("draw:polygon");
    poly["draw:z-index"] << depth2z(depth);
    poly["draw:layer"] << "layout";
    poly["svg:x"] << tr(minx) << "cm";
    poly["svg:y"] << tr(miny) << "cm";
    poly["svg:width"] << tr(maxx-minx) << "cm";
    poly["svg:height"] << tr(maxy-miny) << "cm";
    poly["svg:viewBox"] << "0 0 "<<tr_p(maxx-minx)<<' '<<tr_p(maxy-miny);
    ostringstream& p = poly["draw:points"];
    for( int i=0; i<npoints; ++i )
        p << tr_p(x[i]-minx) << ' ' << tr_p(y[i]-miny) << ' ';

    // now decide what to write
    if( sub_type == 1 ) {
        if( lfs->hasFill() ) {
            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;
        }
    }
    return out;
}


Generated by  Doxygen 1.6.0   Back to index