/*  Inti: Integrated Foundation Classes
 *  Copyright (C) 2002-2003 The Inti Development Team.
 *
 *  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 Library General Public License for more details.
 *
 *  You should have received a copy of the GNU Library General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 */
 
//! @file inti/pango/glyph.h
//! @brief A PangoGlyphString C++ wrapper interface.
//!
//! Provides GlyphString, an objects for storing information about glyphs.

#ifndef INTI_PANGO_GLYPH_H
#define INTI_PANGO_GLYPH_H

#ifndef INTI_G_BOXED_H
#include <inti/glib/boxed.h>
#endif

#ifndef INTI_PANGO_TYPES_H
#include <inti/pango/types.h>
#endif

#ifndef __PANGO_GLYPH_H__
#include <pango/pango-glyph.h>
#endif

#ifndef _CPP_VECTOR
#include <vector>
#endif

namespace Inti {

namespace Pango {
	
class Analysis;
class Font;
class Rectangle;

//! GlyphUnit is a convenient typedef for PangoGlyphUnit.
//! The GlyphUnit type is used to store dimensions within Pango. Dimensions are stored
//! in 1/PANGO_SCALE of a device unit. (A device unit might be a pixel for screen display,
//! or a point on a printer.) PANGO_SCALE is currently 1024, and is unlikely to change,
//! but you should not depend on its exact value. The PANGO_PIXELS() macro can be used
//! to convert from glyph units into device units with correct rounding.

typedef PangoGlyphUnit GlyphUnit;

//! @class GlyphGeometry glyph.h inti/pango/glyph.h
//! @brief A PangoGlyphGeometry C++ wrapper class.
//!
//! GlyphGeometry contains the width and positioning information for a single glyph.
//! Distances are in 1/64ths of a point.

class GlyphGeometry
{
	PangoGlyphGeometry geometry_;

public:
	PangoGlyphGeometry* pango_glyph_geometry() const { return const_cast<PangoGlyphGeometry*>(&geometry_); }
	//!< Get a pointer to the PangoGlyphGeometry structure.

	GlyphUnit width() const;
	//!< Returns the logical width of the character.

	GlyphUnit x_offset() const;
	//!< Returns the horizontal offset from nominal character position.

	GlyphUnit y_offset() const;
	//!< Returns the vertical offset from nominal character position.
};

//! @class GlyphVisAttr glyph.h inti/pango/glyph.h
//! @brief A PangoGlyphVisAttr C++ wrapper class.
//!
//! GlyphVisAttr is used to communicate information between the shaping phase
//! and the rendering phase. It's contents are still evolving.

class GlyphVisAttr
{
	PangoGlyphVisAttr attr_;

public:
	PangoGlyphVisAttr* pango_glyph_vis_attr() const { return const_cast<PangoGlyphVisAttr*>(&attr_); }
	//!< Get a pointer to the PangoGlyphVisAttr structure.

	bool is_cluster_start() const;
	//!< Returns <EM>true</EM> for the first logical glyph in each cluster. Clusters are stored
	//!< in visual order, within the cluster, glyphs are always ordered in logical order, since
	//!< visual order is meaningless; that is, in Arabic text, accent glyphs follow the glyphs
	//!< for the base character.
};

//! @class GlyphInfo glyph.h inti/pango/glyph.h
//! @brief A PangoGlyphInfo C++ wrapper class.
//!
//! GlyphInfo represents a single glyph together with positioning information and visual attributes.

class GlyphInfo
{
	PangoGlyphInfo info_;

public:
	PangoGlyphInfo* pango_glyph_info() const { return const_cast<PangoGlyphInfo*>(&info_); }
	//!< Get a pointer to the PangoGlyphInfo structure.

	Glyph glpyh() const;
	//!< Returns the glyph itself.

	const GlyphGeometry& geometry() const;
	//!< Returns the glyph geometry object containing width and positioning information for the glyph.

	const GlyphVisAttr& attr() const;
	//!< Returns the GlyphVisAttr which is used to communicate information
	//!< between the shaping phase and the rendering phase.
};

//! @class GlyphString glyph.h inti/pango/glyph.h
//! @brief A PangoGlyphString C++ wrapper class.
//!
//! GlyphString is used to store strings of glyphs with geometry and visual attribute information.
//! The storage for the glyph information is owned by the structure which simplifies memory management.

class GlyphString : public G::Boxed
{
public:
//! @name Constructors
//! @{

	GlyphString();
	//!< Construct a new glyph string.

	GlyphString(const String& text, const Analysis& analysis);
	//!< Given a segment of text and the corresponding Analysis structure returned
	//!< from Pango::Context::itemize(), convert the characters in <EM>text</EM> into glyphs.
	//!< @param text The text to process.
	//!< @param analysis The Analysis structure from Pango::Context::Itemize().
	//!<
	//!< <BR>You may also pass in only a substring of the item from Pango::Context::itemize().
	//!< This constructor calls pango_shape(). There is no shape() method.

	explicit GlyphString(PangoGlyphString *string);
	//!< Construct a new glyph string from an existing PangoGlyphString.
	//!< @param string A pointer to a PangoGlyphString.
	//!<
	//!< <BR>The <EM>string</EM> can be a newly created PangoGlyphString or an existing
	//!< PangoGlyphString. The glyph string object created is a temporary object.
	//!< It doesn't take over the ownership of PangoGlyphString and PangoGlyphString
	//!< is not freed by the destructor.

	GlyphString(PangoGlyphString *string, bool copy);
	//!< Construct a new glyph string from an existing PangoGlyphString.
	//!< @param string A pointer to a PangoGlyphString.
	//!< @param copy Whether the GlyphString object should make a copy of PangoGlyphString or not.
	//!<
	//!< <BR>The <EM>string</EM> can be a newly created PangoGlyphString or an existing
	//!< PangoGlyphString. If <EM>copy</EM> is true GlyphString will make a copy
	//!< of PangoGlyphString. If <EM>copy</EM> is false GlyphString wont make
	//!< a copy but instead takes over the ownership of PangoGlyphString. Either way,
	//!< the destructor will free PangoGlyphString when the GlyphString object is
	//!< destroyed. This constructor is used by G::Boxed::wrap() to wrap PangoGlyphString
	//!< objects in a C++ wrapper.

	GlyphString(const GlyphString& src);
	//!< Copy constructor.
	//!< @param src The source GlyphString.

	virtual ~GlyphString();
	//!< Destructor.

	GlyphString& operator=(const GlyphString& src);
	//!< Assignment operator.
	//!< @param src The source GlyphString.

//! @}
//! @name Accessors
//! @{

	PangoGlyphString* pango_glyph_string() const { return (PangoGlyphString*)boxed_; }
	//!< Get a pointer to the PangoGlyphString structure.

	operator PangoGlyphString* () const;
	//!< Conversion operator; safely converts a GlyphString to a PangoGlyphString pointer.

	int size() const;
	//!< Returns the number of glyphs in the string.
	
	std::vector<GlyphInfo> glyphs() const;
	//!< Returns a vector of GlyphInfo that holds one GlyphInfo object for each glyph in the string.

	int* log_clusters() const;
	//!< For each glyph, returns the byte index of the starting character for the cluster.
	//!< The indices are relative to the start of the text corresponding to the GlyphString.

	void extents(const Font& font, Rectangle *ink_rect, Rectangle *logical_rect, int start = 0, int end = -1) const;
	//!< Compute the logical and ink extents of a sub-portion the glyph string,
	//!< or the entire glyph string.
	//!< @param font A Font.
	//!< @param ink_rect The rectangle used to store the extents of the glyph string as drawn,
	//!<                 or null to indicate that the result is not needed.
	//!< @param logical_rect The rectangle used to store the logical extents of the glyph string,
	//!<                    or null to indicate that the result is not needed.
	//!< @param start The start index in bytes, or 0 for the start of the string.
	//!< @param end The end index in bytes, or -1 for the end of the string.
	//!<
	//!< <BR>The extents are relative to the start of the glyph string range (the origin of
	//!< their coordinate system is at the start of the range, not at the start of the
	//!< entire glyph string).
	//!<
	//!< See the documentation for Pango::Font::get_glyph_extents() for details
	//!< about the interpretation of the rectangles.

	void get_logical_widths(const String& text, int embedding_level, std::vector<int>& logical_widths) const;
	//!< Given a GlyphString resulting from pango_shape() and the corresponding text,
	//!< determine the screen width corresponding to each character. 
	//!< @param text The text corresponding to the glyphs.
	//!< @param embedding_level The embedding level of the string.
	//!< @param logical_widths A reference to a vector of int to be filled in with the resulting character widths.
	//!<
	//!< <BR>When multiple characters compose a single cluster, the width of the entire cluster is
	//!< divided equally among the characters.

//! @}
//! @name Methods
//! @{

	void set_size(int length);
	//!< Resize a glyph string to the given length.
	//!< @param length The new length of the string.

	int index_to_x(const String& text, const Analysis& analysis, int index, bool trailing);
	//!< Converts from a character position to an x position.
	//!< @param text The text for the run.
	//!< @param analysis The analysis information returned from Pango::Context::itemize().
	//!< @param index The byte index within text.
	//!< @param trailing Whether we should compute the result for the beginning or end of the character.
	//!< @return The x position.
	//!<
	//!< <BR>X position is measured from the left edge of the run. Character positions are
	//!< computed by dividing up each cluster into equal portions.

	void x_to_index(const String& text, const Analysis& analysis, int x_pos, int *index, bool *trailing);
	//!< Convert from an x offset to character position. 
	//!< @param text The text for the run.
	//!< @param analysis The analysis information returned from Pango::Context::itemize().
	//!< @param x_pos The x offset (in GlyphUnit).
	//!< @param index The location to store calculated byte index within the text.
	//!< @param trailing The location to store whether the user clicked on the leading
	//!<                 or trailing edge of the character.
	//!<
	//!< <BR>Character positions are computed by dividing up each cluster into equal portions.
	//!< In scripts where positioning within a cluster is not allowed (such as Thai), the
	//!< returned value may not be a valid cursor position; the caller must combine the result
	//!< with the logical attributes for the text to compute the valid cursor position.

//! @}
};

} // namespace Pango

} // namespace Inti

#endif // INTI_PANGO_GLYPH_H

