// -*- C++ -*-
// --------------------------------------------------------------------
// The text object.
// --------------------------------------------------------------------
/*

    This file is part of the extensible drawing editor Ipe.
    Copyright (C) 1993-2007  Otfried Cheong

    Ipe 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.

    As a special exception, you have permission to link Ipe with the
    CGAL library and distribute executables, as long as you follow the
    requirements of the Gnu General Public License in regard to all of
    the software in the executable aside from CGAL.

    Ipe 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 Ipe; if not, you can find it at
    "http://www.gnu.org/copyleft/gpl.html", or write to the Free
    Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.

*/

#ifndef IPETEXT_H
#define IPETEXT_H

#include "ipeobj.h"

// --------------------------------------------------------------------

class IpeText : public IpeObject {
public:
  enum THorizontalAlignment { ELeft, ERight, EHCenter };
  enum TVerticalAlignment { EBottom, EBaseline, ETop, EVCenter };
  enum TType { ELabel = 1, EMinipage };

  explicit IpeText();
  explicit IpeText(const IpeAllAttributes &attr, IpeString data,
		   const IpeVector &pos, TType type, IpeScalar width = 10.0);
  explicit IpeText(IpeRepository *rep, const IpeXmlAttributes &attr,
		   IpeString data);
  IpeText(const IpeText &rhs);
  ~IpeText();
  virtual IpeObject *Clone() const;

  virtual IpeText *AsText();

  virtual void SaveAsXml(IpePainter &painter, IpeStream &stream,
			 IpeString layer) const;
  virtual void Draw(IpePainter &painter) const;
  virtual void Accept(IpeVisitor &visitor) const;
  virtual void AddToBBox(IpeRect &box, const IpeMatrix &m) const;
  virtual double Distance(const IpeVector &v, const IpeMatrix &m,
			  double bound) const;
  virtual void SnapVtx(const IpeVector &mouse, const IpeMatrix &m,
		       IpeVector &pos, double &bound) const;

  virtual void CheckStyle(const IpeStyleSheet *sheet,
			  IpeAttributeSeq &seq) const;

private:
  void Quadrilateral(const IpeMatrix &m, IpeVector v[4]) const;
public:
  IpeVector Align() const;

  TType Type() const;
  inline IpeVector Position() const;
  inline IpeString Text() const;
  inline IpeAttribute Size() const;
  inline IpeAttribute Style() const;

  inline bool isMinipage() const;
  void SetType(TType type);

  inline THorizontalAlignment HorizontalAlignment() const;
  inline TVerticalAlignment VerticalAlignment() const;
  void SetHorizontalAlignment(THorizontalAlignment align);
  void SetVerticalAlignment(TVerticalAlignment align);

  static TVerticalAlignment makeVAlign(IpeString str,
				       TVerticalAlignment def);
  static THorizontalAlignment makeHAlign(IpeString str,
					 THorizontalAlignment def);
  static void saveAlignment(IpeStream &stream, THorizontalAlignment h,
			    TVerticalAlignment v);

  inline IpeScalar Width() const;
  inline IpeScalar Height() const;
  inline IpeScalar Depth() const;
  inline IpeScalar TotalHeight() const;

  inline bool IsTransformable() const;

  void SetTransformable(bool transf);
  void SetSize(IpeAttribute size);
  void SetStyle(IpeAttribute style);
  void SetWidth(IpeScalar width);
  void SetText(IpeString text);

  struct XForm {
    unsigned long int iRefCount;
    IpeBuffer iStream;
    IpeRect iBBox;
    int iDepth;
    std::vector<int> iFonts;
    double iStretch;
  };

  bool isInternal() const { return iType == 0; }
  void setXForm(XForm *xform) const;
  inline const XForm *getXForm() const;

private:
  IpeVector iPos;
  IpeString iText;
  IpeAttribute iSize;
  IpeAttribute iStyle;
  mutable IpeScalar iWidth;
  mutable IpeScalar iHeight;
  mutable IpeScalar iDepth;
  TType iType;
  THorizontalAlignment iHorizontalAlignment;
  TVerticalAlignment iVerticalAlignment;
  bool iTransformable;
  mutable XForm *iXForm; // reference counted
};

// --------------------------------------------------------------------

//! Return text position.
inline IpeVector IpeText::Position() const
{
  return iPos;
}

//! Return text source.
inline IpeString IpeText::Text() const
{
  return iText;
}

//! Return font size.
inline IpeAttribute IpeText::Size() const
{
  return iSize;
}

//! Return Latex style of text object.
inline IpeAttribute IpeText::Style() const
{
  return iStyle;
}

//! Return width of text object.
inline IpeScalar IpeText::Width() const
{
  return iWidth;
}

//! Return height of text object (from baseline to top).
inline IpeScalar IpeText::Height() const
{
  return iHeight;
}

//! Return depth of text object.
inline IpeScalar IpeText::Depth() const
{
  return iDepth;
}

//! Return height + depth of text object.
inline IpeScalar IpeText::TotalHeight() const
{
  return iHeight + iDepth;
}

//! Return true if text object is formatted as a minipage.
/*! Equivalent to type being EMinipage. */
inline bool IpeText::isMinipage() const
{
  return (iType == EMinipage);
}

//! Return true if text object can be transformed.
inline bool IpeText::IsTransformable() const
{
  return iTransformable;
}

//! Return horizontal alignment of text object.
inline IpeText::THorizontalAlignment IpeText::HorizontalAlignment() const
{
  return iHorizontalAlignment;
}

//! Return vertical alignment of text object.
inline IpeText::TVerticalAlignment IpeText::VerticalAlignment() const
{
  return iVerticalAlignment;
}

//! Return the PDF representation of this text object.
/*! If Pdflatex has not been run yet, returns 0. */
inline const IpeText::XForm *IpeText::getXForm() const
{
  return iXForm;
}

// --------------------------------------------------------------------
#endif
