00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00031 #ifndef _GG_Font_h_
00032 #define _GG_Font_h_
00033
00034 #include <GG/AlignmentFlags.h>
00035 #include <GG/Texture.h>
00036
00037 #include <set>
00038
00039 #include <boost/serialization/access.hpp>
00040
00041
00042 typedef unsigned long FT_ULong;
00043 struct FT_FaceRec_;
00044 typedef struct FT_FaceRec_* FT_Face;
00045
00046 namespace GG {
00047
00049 GG_API std::string " from a Clr object with color channels...">RgbaTag(const Clr& c);
00050
00052 GG_FLAG_TYPE(TextFormat);
00053 extern GG_API const TextFormat FORMAT_NONE;
00054 extern GG_API const TextFormat FORMAT_VCENTER;
00055 extern GG_API const TextFormat FORMAT_TOP;
00056 extern GG_API const TextFormat FORMAT_BOTTOM;
00057 extern GG_API const TextFormat FORMAT_CENTER;
00058 extern GG_API const TextFormat FORMAT_LEFT;
00059 extern GG_API const TextFormat FORMAT_RIGHT;
00060 extern GG_API const TextFormat FORMAT_WORDBREAK;
00061 extern GG_API const TextFormat FORMAT_LINEWRAP;
00062 extern GG_API const TextFormat FORMAT_IGNORETAGS;
00063
00064
00108 class GG_API Font
00109 {
00110 public:
00112 struct GG_API TextElement
00113 {
00115 enum TextElementType {
00116 OPEN_TAG,
00117 CLOSE_TAG,
00118 TEXT,
00119 WHITESPACE,
00120 NEWLINE
00121 };
00122
00123 TextElement(bool ws, bool nl);
00124 virtual ~TextElement();
00125
00126 int Width() const;
00127 virtual TextElementType Type() const;
00128 virtual int OriginalStringChars() const;
00129
00130 std::string text;
00131 std::vector<int> widths;
00132 const bool whitespace;
00133 const bool newline;
00134
00135 protected:
00136 TextElement();
00137
00138 private:
00139 friend class boost::serialization::access;
00140 template <class Archive>
00141 void serialize(Archive& ar, const unsigned int version);
00142 };
00143
00145 struct GG_API FormattingTag : TextElement
00146 {
00147 FormattingTag(bool close);
00148
00149 virtual TextElementType Type() const;
00150 virtual int OriginalStringChars() const;
00151
00152 std::vector<std::string> params;
00153 std::string original_tag_text;
00154 const bool close_tag;
00155
00156 private:
00157 FormattingTag();
00158 friend class boost::serialization::access;
00159 template <class Archive>
00160 void serialize(Archive& ar, const unsigned int version);
00161 };
00162
00166 struct GG_API LineData
00167 {
00168 LineData();
00169
00172 struct GG_API CharData
00173 {
00174 CharData();
00175 CharData(int extent_, int original_index, const std::vector<boost::shared_ptr<TextElement> >& tags_);
00176
00177 int extent;
00178 int original_char_index;
00179 std::vector<boost::shared_ptr<FormattingTag> >
00180 tags;
00181
00182 private:
00183 friend class boost::serialization::access;
00184 template <class Archive>
00185 void serialize(Archive& ar, const unsigned int version);
00186 };
00187
00188 int Width() const;
00189 bool Empty() const;
00190
00191 std::vector<CharData> char_data;
00192 Alignment justification;
00193
00194 private:
00195 friend class boost::serialization::access;
00196 template <class Archive>
00197 void serialize(Archive& ar, const unsigned int version);
00198 };
00199
00202 struct GG_API RenderState
00203 {
00204 RenderState();
00205
00206 bool ignore_tags;
00207 bool use_italics;
00208 bool draw_underline;
00209 bool color_set;
00210 Clr curr_color;
00211 };
00212
00214 enum GlyphRange {
00215 NUMBER = 1 << 0,
00216 ALPHA_UPPER = 1 << 1,
00217 ALPHA_LOWER = 1 << 2,
00218 SYMBOL = 1 << 3,
00219 ALL_DEFINED_RANGES = NUMBER | ALPHA_UPPER | ALPHA_LOWER | SYMBOL,
00220 ALL_CHARS = (1 << 5) - 1
00221 };
00222
00224
00226 Font(const std::string& font_filename, int pts, unsigned int range = ALL_DEFINED_RANGES);
00227 virtual ~Font();
00228
00229
00231 const std::string&FontName() const;
00232 int PointSize() const;
00233
00235 int GetGlyphRange() const;
00236
00237 int Ascent() const;
00238 int Descent() const;
00239 int Height() const;
00240 int Lineskip() const;
00241 int SpaceWidth() const;
00242 int RenderGlyph(const Pt& pt, char c) const;
00243 int RenderGlyph(int x, int y, char c) const;
00244 int RenderText(const Pt& pt, const std::string& text) const;
00245 int RenderText(int x, int y, const std::string& text) const;
00246 void RenderText(const Pt& pt1, const Pt& pt2, const std::string& text, Flags<TextFormat>& format, const std::vector<LineData>* line_data = 0, RenderState* render_state = 0) const;
00247 void RenderText(int x1, int y1, int x2, int y2, const std::string& text, Flags<TextFormat>& format, const std::vector<LineData>* line_data = 0, RenderState* render_state = 0) const;
00248 void RenderText(const Pt& pt1, const Pt& pt2, const std::string& text, Flags<TextFormat>& format, const std::vector<LineData>& line_data, RenderState& render_state, int begin_line, int begin_char, int end_line, int end_char) const;
00249 void RenderText(int x1, int y1, int x2, int y2, const std::string& text, Flags<TextFormat>& format, const std::vector<LineData>& line_data, RenderState& render_state, int begin_line, int begin_char, int end_line, int end_char) const;
00250 Pt DetermineLines(const std::string& text, Flags<TextFormat>& format, int box_width, std::vector<LineData>& lines) const;
00251 Pt TextExtent(const std::string& text, Flags<TextFormat> format = FORMAT_NONE, int box_width = 0) const;
00252
00253
00254 static void RegisterKnownTag(const std::string& tag);
00255 static void RemoveKnownTag(const std::string& tag);
00256 static void ClearKnownTags();
00257
00259
00260 GG_ABSTRACT_EXCEPTION(Exception);
00261
00263 GG_CONCRETE_EXCEPTION(BadFile, GG::Font, Exception);
00264
00266 GG_CONCRETE_EXCEPTION(InvalidPointSize, GG::Font, Exception);
00267
00269 GG_CONCRETE_EXCEPTION(InvalidRangeFlags, GG::Font, Exception);
00270
00272 GG_CONCRETE_EXCEPTION(UnscalableFont, GG::Font, Exception);
00273
00275 GG_CONCRETE_EXCEPTION(BadFace, GG::Font, Exception);
00276
00278 GG_CONCRETE_EXCEPTION(BadPointSize, GG::Font, Exception);
00279
00281 GG_CONCRETE_EXCEPTION(BadGlyph, GG::Font, Exception);
00283
00284 protected:
00286 Font();
00287
00288
00289 private:
00292 struct Glyph
00293 {
00294 Glyph() : left_bearing(0), advance(0), width(0) {}
00295 Glyph(const boost::shared_ptr<Texture>& texture, int x1, int y1, int x2, int y2, int lb, int adv) :
00296 sub_texture(texture, x1, y1, x2, y2), left_bearing(lb), advance(adv), width(x2 - x1) {}
00297
00298 SubTexture sub_texture;
00299 int left_bearing;
00300 int advance;
00301 int width;
00302 };
00303 struct HandleTagFunctor;
00304
00305 void Init(const std::string& font_filename, int pts, unsigned int range);
00306 bool GenerateGlyph(FT_Face font, FT_ULong ch);
00307 inline int RenderGlyph(int x, int y, const Glyph& glyph, const RenderState* render_state) const;
00308 void HandleTag(const boost::shared_ptr<FormattingTag>& tag, double* orig_color, RenderState& render_state) const;
00309
00310 std::string m_font_filename;
00311 int m_pt_sz;
00312 int m_glyph_range;
00313 int m_ascent;
00314 int m_descent;
00315 int m_height;
00316 int m_lineskip;
00317 double m_underline_offset;
00318 double m_underline_height;
00319 double m_italics_offset;
00320 int m_space_width;
00321 std::map<FT_ULong, Glyph>
00322 m_glyphs;
00323 std::vector<boost::shared_ptr<Texture> >
00324 m_textures;
00325
00326 static std::set<std::string> s_action_tags;
00327 static std::set<std::string> s_known_tags;
00328
00329 friend struct HandleTagFunctor;
00330
00331 friend class boost::serialization::access;
00332 template <class Archive>
00333 void serialize(Archive& ar, const unsigned int version);
00334 };
00335
00336
00337 GG_ENUM_MAP_BEGIN(Font::GlyphRange)
00338 GG_ENUM_MAP_INSERT(Font::NUMBER)
00339 GG_ENUM_MAP_INSERT(Font::ALPHA_UPPER)
00340 GG_ENUM_MAP_INSERT(Font::ALPHA_LOWER)
00341 GG_ENUM_MAP_INSERT(Font::SYMBOL)
00342 GG_ENUM_MAP_INSERT(Font::ALL_DEFINED_RANGES)
00343 GG_ENUM_MAP_INSERT(Font::ALL_CHARS)
00344 GG_ENUM_MAP_END
00345
00346 GG_ENUM_STREAM_IN(Font::GlyphRange)
00347 GG_ENUM_STREAM_OUT(Font::GlyphRange)
00348
00349
00359 class GG_API FontManager
00360 {
00361 private:
00363 struct FontKey
00364 {
00365 FontKey(const std::string& str, int pts);
00366 bool operator<(const FontKey& rhs) const;
00367
00368 std::string filename;
00369 int points;
00370 };
00371
00372 public:
00374 boost::shared_ptr<Font> GetFont(const std::string& font_filename, int pts, unsigned int range = Font::ALL_DEFINED_RANGES);
00375 void FreeFont(const std::string& font_filename, int pts);
00376
00377
00378 private:
00379 FontManager();
00380
00381 std::map<FontKey, boost::shared_ptr<Font> > m_rendered_fonts;
00382
00383 friend FontManager& GetFontManager();
00384 };
00385
00387 FontManager& GetFontManager();
00388
00390 GG_EXCEPTION(FailedFTLibraryInit);
00391
00392 }
00393
00394
00395 template <class Archive>
00396 void GG::Font::TextElement::serialize(Archive& ar, const unsigned int version)
00397 {
00398 ar & BOOST_SERIALIZATION_NVP(text)
00399 & BOOST_SERIALIZATION_NVP(widths)
00400 & boost::serialization::make_nvp("whitespace", const_cast<bool&>(whitespace))
00401 & boost::serialization::make_nvp("newline", const_cast<bool&>(newline));
00402 }
00403
00404 template <class Archive>
00405 void GG::Font::FormattingTag::serialize(Archive& ar, const unsigned int version)
00406 {
00407 ar & BOOST_SERIALIZATION_BASE_OBJECT_NVP(TextElement)
00408 & BOOST_SERIALIZATION_NVP(params)
00409 & BOOST_SERIALIZATION_NVP(original_tag_text)
00410 & boost::serialization::make_nvp("close_tag", const_cast<bool&>(close_tag));
00411 }
00412
00413 template <class Archive>
00414 void GG::Font::LineData::CharData::serialize(Archive& ar, const unsigned int version)
00415 {
00416 ar & BOOST_SERIALIZATION_NVP(extent)
00417 & BOOST_SERIALIZATION_NVP(original_char_index)
00418 & BOOST_SERIALIZATION_NVP(tags);
00419 }
00420
00421 template <class Archive>
00422 void GG::Font::LineData::serialize(Archive& ar, const unsigned int version)
00423 {
00424 ar & BOOST_SERIALIZATION_NVP(char_data)
00425 & BOOST_SERIALIZATION_NVP(justification);
00426 }
00427
00428 template <class Archive>
00429 void GG::Font::serialize(Archive& ar, const unsigned int version)
00430 {
00431 ar & BOOST_SERIALIZATION_NVP(m_font_filename)
00432 & BOOST_SERIALIZATION_NVP(m_pt_sz)
00433 & BOOST_SERIALIZATION_NVP(m_glyph_range);
00434
00435 if (Archive::is_loading::value) {
00436 if (!m_font_filename.empty() && 0 < m_pt_sz) {
00437 try {
00438 Init(m_font_filename, m_pt_sz, m_glyph_range);
00439 } catch (const Exception& e) {
00440
00441 }
00442 }
00443 }
00444 }
00445
00446 #endif // _GG_Font_h_