/*
 *  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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

#include "Be.h"


_IMPEXP_BE const BFont* be_plain_font = 0;
_IMPEXP_BE const BFont* be_bold_font = 0;
_IMPEXP_BE const BFont* be_fixed_font = 0;


namespace winBe {
std::vector<std::string> fontNames;
std::vector<std::string> fontStyles;
};


// constructor
BFont::BFont () :
fFamilyID (0),
fStyleID (0),
fSize (8),
fShear (90),
fRotation (0),
fSpacing (B_CHAR_SPACING),
fEncoding (B_ISO_8859_1),
fFace (B_REGULAR_FACE),
fFlags (B_FORCE_ANTIALIASING)
{
	fHeight.ascent = 8;
	fHeight.descent = 2;
	fHeight.leading = 1;

	_reserved[0] = 0;
	generateFont ();
}


// constructor
BFont::BFont (const BFont *font) :
fFamilyID (font->fFamilyID),
fStyleID (font->fStyleID),
fSize (font->fSize),
fShear (font->fShear),
fRotation (font->fRotation),
fSpacing (font->fSpacing),
fEncoding (font->fEncoding),
fFace (font->fFace),
fFlags (font->fFlags)
{
	fHeight.ascent = font->fHeight.ascent;
	fHeight.descent = font->fHeight.descent;
	fHeight.leading = font->fHeight.leading;

	_reserved[0] = 0;
	generateFont ();
}


// constructor
BFont::BFont (const BFont& font) :
fFamilyID (font.fFamilyID),
fStyleID (font.fStyleID),
fSize (font.fSize),
fShear (font.fShear),
fRotation (font.fRotation),
fSpacing (font.fSpacing),
fEncoding (font.fEncoding),
fFace (font.fFace),
fFlags (font.fFlags)
{
	fHeight.ascent = font.fHeight.ascent;
	fHeight.descent = font.fHeight.descent;
	fHeight.leading = font.fHeight.leading;

	_reserved[0] = 0;
	generateFont ();
}


// destructor
BFont::~BFont ()
{
	winBe::deleteFont (_reserved[0]);
}


// operator =
BFont& BFont::operator= (const BFont &font)
{
	fFamilyID = font.fFamilyID;
	fStyleID = font.fStyleID;
	fSize = font.fSize;
	fShear = font.fShear;
	fRotation = font.fRotation;
	fSpacing = font.fSpacing;
	fEncoding = font.fEncoding;
	fFace = font.fFace;
	fFlags = font.fFlags;
	fHeight.ascent = font.fHeight.ascent;
	fHeight.descent = font.fHeight.descent;
	fHeight.leading = font.fHeight.leading;

	_reserved[0] = 0;

	return *this;
}


// SetFamilyAndStyle
void BFont::SetFamilyAndStyle (uint32 code)
{
	fFamilyID = static_cast<uint16>(code & 0xFF);
	fStyleID = static_cast<uint16>(code >> 8);
	generateFont ();
}


// FamilyAndStyle
uint32 BFont::FamilyAndStyle () const
{
	return fFamilyID | fStyleID;
}


// SetSize
void BFont::SetSize (float size)
{
	fSize = size;
	generateFont ();
}


// Size
float BFont::Size () const
{
	return fSize;
}


// SetShear
void BFont::SetShear (float shear)
{
	fShear = shear;
	generateFont ();
}


// Shear
float BFont::Shear () const
{
	return fShear;
}


// SetSize
void BFont::SetRotation (float rotation)
{
	fRotation = rotation;
	generateFont ();
}


// Rotation
float BFont::Rotation () const
{
	return fRotation;
}


// SetSpacing
void BFont::SetSpacing (uint8 spacing)
{
	fSpacing = spacing;
	generateFont ();
}


// Spacing
uint8 BFont::Spacing () const
{
	return fSpacing;
}


// SetEncoding
void BFont::SetEncoding (uint8 encoding)
{
	fEncoding = encoding;
	generateFont ();
}


// Encoding
uint8 BFont::Encoding () const
{
	return fEncoding;
}


// SetFace
void BFont::SetFace (uint16 face)
{
	fFace = face;
	generateFont ();
}


// Face
uint16 BFont::Face () const
{
	return fFace;
}


// SetFlags
void BFont::SetFlags (uint32 flags)
{
	fFlags = flags;
	generateFont ();
}


// Flags
uint32 BFont::Flags () const
{
	return fFlags;
}

		
// SetFamilyAndStyle
status_t BFont::SetFamilyAndStyle (const font_family family, const font_style style)
{
	status_t result = B_ERROR;

	int families = count_font_families ();
	for (int i = 0; i < families; i++) {
		font_family name;
		get_font_family (i, &name);
		if (strcmp (name, family) == 0) {
			fFamilyID = i;

			int styles = count_font_styles (name);
			for (int j = 0; j < styles; j++) {
				font_style style_name;
				get_font_style (name, j, &style_name);
				if (strcmp (style_name, style) == 0) {
					fStyleID = j << 8;
					result = B_OK;
					break;
				}
			}

			break;
		}
	}

	generateFont ();

	return result;
}


// StringWidth
float BFont::StringWidth (const char *string) const
{
	return StringWidth (string, strlen (string));
}


// StringWidth
float BFont::StringWidth (const char *string, int32 length) const
{
	int width;
	int height;
	winBe::stringDimensions (_reserved[0], string, length, width, height);
	return static_cast<float>(width);
}


// GetHeight		
void BFont::GetHeight (font_height *height) const
{
	height->ascent = fHeight.ascent;
	height->descent = fHeight.descent;
	height->leading = fHeight.leading;
}


// generateFont
void BFont::generateFont ()
{
	if (_reserved[0])
		winBe::deleteFont (_reserved[0]);

	bool bold = false;
	bool italic = false;
	std::string style = winBe::fontStyles[fStyleID >> 8];
	if (style.find ("Bold") != std::string::npos)
		bold = true;
	if (style.find ("Italic") != std::string::npos)
		italic = true;

	_reserved[0] = winBe::createFont (winBe::fontNames[fFamilyID], static_cast<int>(fSize), bold, italic);
}


// count_font_families
_IMPEXP_BE int32 count_font_families ()
{
	return winBe::fontNames.size ();
}


// get_font_family
_IMPEXP_BE status_t get_font_family (int32 index, font_family *name, uint32 *flags/* = NULL*/)
{
	status_t result = B_ERROR;

	if (index < static_cast<int32>(winBe::fontNames.size ())) {
		strcpy (*name, winBe::fontNames[index].c_str ());
		if (flags)
			*flags = 0;
		result = B_OK;
	}

	return result;
}


// count_font_styles
_IMPEXP_BE int32 count_font_styles (font_family name)
{
	return winBe::fontStyles.size ();
}


// get_font_style
_IMPEXP_BE status_t get_font_style (font_family family, int32 index, font_style *name, uint32 *flags)
{
	status_t result = B_ERROR;

	if (index < static_cast<int32>(winBe::fontStyles.size ())) {
		strcpy (*name, winBe::fontStyles[index].c_str ());
		if (flags)
			*flags = 0;
		result = B_OK;
	}

	return result;
}


// update_font_families
_IMPEXP_BE bool update_font_families (bool check_only)
{
	return true;
}


// initFonts
void winBe::initFonts ()
{
	fontNames.push_back ("Arial");
	fontNames.push_back ("Courier New");
	fontNames.push_back ("Times New Roman");

	fontStyles.push_back ("Roman");
	fontStyles.push_back ("Bold");
	fontStyles.push_back ("Italic");
	fontStyles.push_back ("Bold Italic");

	BFont* plain_font = new BFont ();
	plain_font->SetFamilyAndStyle ("Arial", "Roman");
	plain_font->SetSize (10);
	be_plain_font = plain_font;

	BFont* bold_font = new BFont ();
	bold_font->SetFamilyAndStyle ("Arial", "Bold");
	bold_font->SetSize (10);
	be_bold_font = bold_font;

	BFont* fixed_font = new BFont ();
	fixed_font->SetFamilyAndStyle ("Courier New", "Roman");
	fixed_font->SetSize (10);
	be_fixed_font = fixed_font;
}


// cleanupFonts
void winBe::cleanupFonts ()
{
	delete const_cast<BFont*>(be_fixed_font);
	delete const_cast<BFont*>(be_bold_font);
	delete const_cast<BFont*>(be_plain_font);
}
