// -*-c++-*-

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

// Copyright (C) 2003-2022 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 <set>
#include <string>
#include <iostream>

#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
