/*
 *  psychlops_g_font.h
 *  Psychlops Standard Library (Universal)
 *
 *  Last Modified 2005/09/25 by Kenchi HOSOKAWA
 *  (C) 2005 Kenchi HOSOKAWA, Kazushi MARUYA, Takao SATO
 */

#ifndef HEADER_PSYCHLOPS_GRAPHIC_FONT
#define HEADER_PSYCHLOPS_GRAPHIC_FONT

#include "psychlops_g_fundamental.h"
#include "psychlops_g_module.h"
#include "psychlops_g_shape.h"
#include "../ApplicationInterfaces/psychlops_code_snippets.h"
#include <string>
#include <map>

namespace Psychlops {

	class Font;
	class Letters;
	class Canvas;
	class Display;
	class APICanvasProperties;
	class APIImageProperties;
	class APIFontProperties;
/*
	class Font {
		friend class Letters;

		public:
		double x_height, cap_height, descender_height, ascender_height;

		virtual ~Font();
		virtual double getWidthOf(char * str);
		virtual double getWidthOf(std::string str) = 0;
	};
*/


	class Font {
		friend class Canvas;
		private:
		static bool initialized;
		static const size_t ASCII_NUM = 128;
		static const size_t font_minimum_proportion[ASCII_NUM];
		static Image *font_minimum;
		static void initializeFontMinimum();

		public:
		static Font default_font;

		enum Style { normal_style, italic, oblique };
		enum Weight { normal_weight=400, bold=700 };
		double size;
		int weight;
		Style style;
		std::vector<std::wstring> family;

		Font();
		Font(double size_, int weight_=400, Style style_ = normal_style, std::wstring family_=L"default");
		Font(std::wstring family_, double size_, int weight_=400, Style style_ = normal_style);
		Font(const wchar_t* family_, double size_, int weight_=400, Style style_ = normal_style);
		virtual ~Font();
		Font& set(double size_, int weight_=400, Style style_ = normal_style, std::wstring family_=L"");
		Font& set(std::wstring family_, double size_, int weight_=400, Style style_ = normal_style);
		Font& set(const wchar_t* family_, double size_, int weight_=400, Style style_ = normal_style);
	};


	class Letters : virtual public Shape, virtual public FigureDatum {
		friend class Canvas;
		friend class APICanvasProperties;
		friend class APIImageProperties;
		friend class APIFontProperties;

		protected:
		struct Cache {
			APIFontProperties* id;
			bool dirty;
			Cache();
			Cache(APIFontProperties* id__, bool dirty__);
		};
		typedef std::map<DrawableWithCache*, Cache> CacheID;
		mutable CacheID caches;
//		bool cached;
		double width_, height_;

		public:
		Font font;
		std::wstring str;
		enum HorizontalAlign { NOT_SPECIFIED=-1, TEXT_ALIGN_LEFT=0, TEXT_ALIGN_CENTER, TEXT_ALIGN_RIGHT };
		HorizontalAlign align;
		enum VerticalAlign { BASELINE, TEXT_ALIGN_TOP, TEXT_ALIGN_MIDDLE, TEXT_ALIGN_BOTTOM, TEXT_ALIGN_TEXT_TOP, TEXT_ALIGN_TEXT_BOTTOM };
		VerticalAlign vertical_align;
		//enum AlignmentBaseline { AUTO=0, BASELINE, BEFORE_EDGE, TEXT_BEFORE_EDGE, MIDDLE, CENTRAL, AFTER_EDGE, TEXT_AFTER_EDGE, IDEOGRAPHIC, ALPHABETIC, HANGING, MATHEMATICAL, INHERIT };
		//AlignmentBaseline alignment_baseline;

		Letters();
		Letters(const char *init_str, int size_, const Font& init_font = Font::default_font);
		Letters(const char *init_str, const Font& init_font = Font::default_font);
		Letters(const std::wstring &init_str, const Font& init_font = Font::default_font);
		virtual ~Letters();
		virtual Font& getFont();
		virtual std::wstring& getString();
		virtual Letters& setFont(const Font &init_font);
		virtual Letters& setString(const char *init_str);
		virtual Letters& setString(const char *init_str, int size_);
		virtual Letters& setString(const std::wstring &init_str);
				virtual Letters& string(const char *init_str);
				virtual Letters& string(const char *init_str, int size_);
				virtual Letters& string(const std::wstring &init_str);
		virtual Letters& cache(DrawableWithCache &target = *DrawableWithCache::prime);
		virtual Letters& uncache(DrawableWithCache &target = *DrawableWithCache::prime);
		virtual Letters& operator =(const std::wstring &init_str);
		using Shape::centering;
		virtual Letters& centering(const Point& p);
		virtual Letters& centering(const Point& p, bool realign_flag);
		virtual Letters& locate(const Point& p);
		virtual Letters& locate(double x, double y, double z=0.0);

		virtual Letters& draw(Drawable &target = *Drawable::prime);
		virtual Letters& draw(const Color &col, Drawable &target = *Drawable::prime);
		virtual Letters& draw(const Stroke &strk, Drawable &target = *Drawable::prime);
		virtual Letters& draw(const Color &col, HorizontalAlign horiz_align, Drawable &target = *Drawable::prime);
	};

}	/*	<- namespace Psycholops 	*/


#endif
