/**
 * \file qfont_metrics.C
 * This file is part of LyX, the document processor.
 * Licence details can be found in the file COPYING.
 *
 * \author unknown
 * \author John Levon
 *
 * Full author contact details are available in file CREDITS.
 */

#include <config.h>

#include "frontends/font_metrics.h"
#include "frontends/lyx_gui.h"

#include "qfont_loader.h"

#include "language.h"


using std::string;

#ifdef I18N
#include "qt_helpers.h"
#include "lyxcodeconv.h"
extern LyXCodeConv codeconverter;
#endif


namespace font_metrics {

int maxAscent(LyXFont const & f)
{
	if (!lyx_gui::use_gui)
		return 1;
	return fontloader.metrics(f).ascent();
}


int maxDescent(LyXFont const & f)
{
	if (!lyx_gui::use_gui)
		return 1;
	// We add 1 as the value returned by QT is different than X
	// See http://doc.trolltech.com/2.3/qfontmetrics.html#200b74
	return fontloader.metrics(f).descent() + 1;
}


int ascent(lyx::char_type c, LyXFont const & f)
{
	if (!lyx_gui::use_gui)
		return 1;
	QRect const & r = fontloader.metrics(f).boundingRect(c);
	// Qt/Win 3.2.1nc (at least) corrects the GetGlyphOutlineA|W y
	// value by the height: (x, -y-height, width, height).
	// Other versions return: (x, -y, width, height)
#if defined(Q_WS_WIN) && (QT_VERSION == 0x030201)
	return -r.top() - r.height();
#else
	return -r.top();
#endif
}


int descent(lyx::char_type c, LyXFont const & f)
{
	if (!lyx_gui::use_gui)
		return 1;
	QRect const & r = fontloader.metrics(f).boundingRect(c);
	// Qt/Win 3.2.1nc (at least) corrects the GetGlyphOutlineA|W y
	// value by the height: (x, -y-height, width, height).
	// Other versions return: (x, -y, width, height)
#if defined(Q_WS_WIN) && (QT_VERSION == 0x030201)
	return r.bottom() + r.height() + 1;
#else
	return r.bottom() + 1;
#endif
}


int lbearing(lyx::char_type c, LyXFont const & f)
{
	if (!lyx_gui::use_gui)
		return 1;
	return fontloader.metrics(f).leftBearing(c);
}


int rbearing(lyx::char_type c, LyXFont const & f)
{
	if (!lyx_gui::use_gui)
		return 1;
	QFontMetrics const & m = fontloader.metrics(f);

	// Qt rbearing is from the right edge of the char's width().
	return m.width(c) - m.rightBearing(c);
}

#ifdef I18N
int width(wchar_t c,LyXFont const & f) 
{
	char mbs[5];
	wchar_t wcs[2];
	wcs[0] = c;
	wcs[1] = 0;
	wcstombs(mbs,wcs,5);

        QFontMetrics const & qm = fontloader.metrics(f);
	
        return qm.width(toqstr(mbs));
}

int width(char c, LyXFont const & f) 
{
	return width(&c, 1, f);			        
}

int width(string const & s, LyXFont const & f)
{
         if (s.empty()) return 0;
	 if (f.isSymbolFont())
                    return width(s.data(), s.length(), f);
         QFontMetrics const & qm = fontloader.metrics(f);

	 return qm.width(toqstr(s));
}
		  
#endif

Encoding const * fontencoding(LyXFont const & f)
{
	Encoding const * encoding = f.language()->encoding();
	if (f.isSymbolFont())
		encoding = encodings.symbol_encoding();
	return encoding;
}


int smallcapswidth(char const * s, size_t ls, LyXFont const & f)
{
	if (!lyx_gui::use_gui)
		return 1;
	// handle small caps ourselves ...

	LyXFont smallfont = f;
	smallfont.decSize().decSize().setShape(LyXFont::UP_SHAPE);

	QFontMetrics const & qm = fontloader.metrics(f);
	QFontMetrics const & qsmallm = fontloader.metrics(smallfont);

	Encoding const * encoding = fontencoding(f);

	int w = 0;

	for (size_t i = 0; i < ls; ++i) {
		QChar const c = QChar(encoding->ucs(s[i]));
		QChar const uc = c.upper();
		if (c != uc)
			w += qsmallm.width(uc);
		else
			w += qm.width(c);
	}
	return w;
}

#ifdef I18N
int width(wchar_t const * s, size_t ls, LyXFont const & f)
{
       QFontMetrics const & qm = fontloader.metrics(f);

           return qm.width(wtoqstr(s)); 
}
#endif


int width(char const * s, size_t ls, LyXFont const & f)
{
	if (!lyx_gui::use_gui)
		return ls;

	if (f.realShape() == LyXFont::SMALLCAPS_SHAPE)
		return smallcapswidth(s, ls, f);

	Encoding const * encoding = fontencoding(f);
	QLFontInfo & fi = fontloader.fontinfo(f);

	if (ls == 1) 
		return fi.width(encoding->ucs(s[0]));

	int w = 0;
	for (size_t i = 0; i < ls; ++i)
		w += fi.width(encoding->ucs(s[i]));

	return w;
}


int signedWidth(string const & s, LyXFont const & f)
{
	if (s[0] == '-')
		return -width(s.substr(1, s.length() - 1), f);
	else
		return width(s, f);
}


void rectText(string const & str, LyXFont const & f,
	int & w, int & ascent, int & descent)
{
	QFontMetrics const & m = fontloader.metrics(f);
	static int const d = 2;
	w = width(str, f) + d * 2 + 2;
	ascent = m.ascent() + d;
	descent = m.descent() + d;
}



void buttonText(string const & str, LyXFont const & f,
	int & w, int & ascent, int & descent)
{
	QFontMetrics const & m = fontloader.metrics(f);
	static int const d = 3;
	w = width(str, f) + d * 2 + 2;
	ascent = m.ascent() + d;
	descent = m.descent() + d;
}

} // namespace font_metrics

