| 1 | // -*- c++ -*- |
| 2 | /* |
| 3 | * OGLFT: A library for drawing text with OpenGL using the FreeType library |
| 4 | * Copyright (C) 2002 lignum Computing, Inc. <oglft@lignumcomputing.com> |
| 5 | * $Id: OGLFT.h,v 1.15 2003/10/01 14:41:09 allen Exp $ |
| 6 | * |
| 7 | * This library is free software; you can redistribute it and/or |
| 8 | * modify it under the terms of the GNU Lesser General Public |
| 9 | * License as published by the Free Software Foundation; either |
| 10 | * version 2.1 of the License, or (at your option) any later version. |
| 11 | * |
| 12 | * This library is distributed in the hope that it will be useful, |
| 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| 15 | * Lesser General Public License for more details. |
| 16 | * |
| 17 | * You should have received a copy of the GNU Lesser General Public |
| 18 | * License along with this library; if not, write |
| 19 | * Free Software Foundation, Inc., |
| 20 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
| 21 | */ |
| 22 | |
| 23 | #ifndef OGLFT_H |
| 24 | #define OGLFT_H |
| 25 | |
| 26 | #include <cmath> |
| 27 | #include <map> |
| 28 | #include <list> |
| 29 | #include <vector> |
| 30 | #include <wchar.h> |
| 31 | |
| 32 | #define GL_GLEXT_PROTOTYPES |
| 33 | #ifdef PANDORA |
| 34 | #include <SDL_opengles2.h> |
| 35 | #else |
| 36 | #include <SDL_opengl.h> |
| 37 | #endif |
| 38 | #if defined(__MACOSX__) |
| 39 | #include <OpenGL/glu.h> |
| 40 | #elif defined(__MACOS__) |
| 41 | #include <glu.h> |
| 42 | #elif defined(PANDORA) |
| 43 | #include <GLES2/glu.h> |
| 44 | #else |
| 45 | #include <GL/glu.h> |
| 46 | #endif |
| 47 | |
| 48 | #include <ft2build.h> |
| 49 | #include FT_FREETYPE_H |
| 50 | #include FT_GLYPH_H |
| 51 | #include FT_OUTLINE_H |
| 52 | #include FT_TRIGONOMETRY_H |
| 53 | |
| 54 | namespace OGLFT |
| 55 | { |
| 56 | enum Coordinates |
| 57 | { |
| 58 | X, Y, Z, W |
| 59 | }; |
| 60 | |
| 61 | enum ColorSpace |
| 62 | { |
| 63 | R, G, B, A |
| 64 | }; |
| 65 | |
| 66 | // global library functions |
| 67 | bool Init_FT(void); |
| 68 | bool Uninit_FT(void); |
| 69 | |
| 70 | struct Advance |
| 71 | { |
| 72 | float dx_; |
| 73 | float dy_; |
| 74 | |
| 75 | Advance ( float dx = 0, float dy = 0 ) : dx_( dx ), dy_( dy ) |
| 76 | { |
| 77 | return; |
| 78 | } |
| 79 | |
| 80 | Advance ( FT_Vector v ) |
| 81 | { |
| 82 | dx_ = (float) (v.x / 64.); |
| 83 | dy_ = (float) (v.y / 64.); |
| 84 | } |
| 85 | |
| 86 | Advance& operator+= ( const FT_Vector v ) |
| 87 | { |
| 88 | dx_ += (float) (v.x / 64.); |
| 89 | dy_ += (float) (v.y / 64.); |
| 90 | return *this; |
| 91 | } |
| 92 | }; |
| 93 | |
| 94 | struct BBox |
| 95 | { |
| 96 | float x_min_; |
| 97 | float y_min_; |
| 98 | float x_max_; |
| 99 | float y_max_; |
| 100 | Advance advance_; |
| 101 | |
| 102 | BBox () : x_min_( 0 ), y_min_( 0 ), x_max_( 0 ), y_max_( 0 ) |
| 103 | { |
| 104 | return; |
| 105 | } |
| 106 | BBox ( FT_BBox ft_bbox ) |
| 107 | { |
| 108 | x_min_ = (float) (ft_bbox.xMin / 64.); |
| 109 | y_min_ = (float) (ft_bbox.yMin / 64.); |
| 110 | x_max_ = (float) (ft_bbox.xMax / 64.); |
| 111 | y_max_ = (float) (ft_bbox.yMax / 64.); |
| 112 | } |
| 113 | BBox& operator*= ( double k ) |
| 114 | { |
| 115 | x_min_ *= (float) k; |
| 116 | y_min_ *= (float) k; |
| 117 | x_max_ *= (float) k; |
| 118 | y_max_ *= (float) k; |
| 119 | advance_.dx_ *= (float) k; |
| 120 | advance_.dy_ *= (float) k; |
| 121 | |
| 122 | return *this; |
| 123 | } |
| 124 | BBox& operator+= ( const BBox& b ) |
| 125 | { |
| 126 | float new_value; |
| 127 | |
| 128 | new_value = b.x_min_ + advance_.dx_; |
| 129 | if ( new_value < x_min_ ) x_min_ = new_value; |
| 130 | new_value = b.y_min_ + advance_.dy_; |
| 131 | if ( new_value < y_min_ ) y_min_ = new_value; |
| 132 | new_value = b.x_max_ + advance_.dx_; |
| 133 | if ( new_value > x_max_ ) x_max_ = new_value; |
| 134 | new_value = b.y_max_ + advance_.dy_; |
| 135 | if ( new_value > y_max_ ) y_max_ = new_value; |
| 136 | |
| 137 | advance_.dx_ += b.advance_.dx_; |
| 138 | advance_.dy_ += b.advance_.dy_; |
| 139 | |
| 140 | return *this; |
| 141 | } |
| 142 | }; |
| 143 | typedef std::vector<GLuint> DisplayLists; |
| 144 | typedef DisplayLists::const_iterator DLCI; |
| 145 | typedef DisplayLists::iterator DLI; |
| 146 | class Face |
| 147 | { |
| 148 | public: |
| 149 | enum HorizontalJustification |
| 150 | { |
| 151 | LEFT, |
| 152 | ORIGIN, |
| 153 | CENTER, |
| 154 | RIGHT |
| 155 | }; |
| 156 | |
| 157 | enum VerticalJustification |
| 158 | { |
| 159 | BOTTOM, |
| 160 | BASELINE, |
| 161 | MIDDLE, |
| 162 | TOP |
| 163 | }; |
| 164 | |
| 165 | enum GlyphCompileMode |
| 166 | { |
| 167 | COMPILE, |
| 168 | IMMEDIATE |
| 169 | }; |
| 170 | |
| 171 | private: |
| 172 | struct FaceData |
| 173 | { |
| 174 | FT_Face face_; |
| 175 | bool free_on_exit_; |
| 176 | FaceData ( FT_Face face, bool free_on_exit = true ) |
| 177 | : face_( face ), free_on_exit_( free_on_exit ) |
| 178 | { |
| 179 | return; |
| 180 | } |
| 181 | }; |
| 182 | |
| 183 | protected: |
| 184 | std::vector< FaceData > faces_; |
| 185 | bool valid_; |
| 186 | enum GlyphCompileMode compile_mode_; |
| 187 | float point_size_; |
| 188 | FT_UInt resolution_; |
| 189 | bool advance_; |
| 190 | GLfloat foreground_color_[4]; |
| 191 | GLfloat background_color_[4]; |
| 192 | enum HorizontalJustification horizontal_justification_; |
| 193 | enum VerticalJustification vertical_justification_; |
| 194 | GLfloat string_rotation_; |
| 195 | FT_UInt rotation_reference_glyph_; |
| 196 | FT_Face rotation_reference_face_; |
| 197 | GLfloat rotation_offset_y_; |
| 198 | typedef std::map< FT_UInt, GLuint > GlyphDLists; |
| 199 | typedef GlyphDLists::const_iterator GDLCI; |
| 200 | typedef GlyphDLists::iterator GDLI; |
| 201 | GlyphDLists glyph_dlists_; |
| 202 | DisplayLists character_display_lists_; |
| 203 | |
| 204 | public: |
| 205 | Face ( const char* filename, float point_size = 12, FT_UInt resolution = 100 ); |
| 206 | Face ( FT_Face face, float point_size = 12, FT_UInt resolution = 100 ); |
| 207 | virtual ~Face ( void ); |
| 208 | bool isValid ( void ) const { return valid_; } |
| 209 | bool addAuxiliaryFace ( const char* filename ); |
| 210 | bool addAuxiliaryFace ( FT_Face face ); |
| 211 | void setCompileMode ( enum GlyphCompileMode compile_mode ) { compile_mode_ = compile_mode; } |
| 212 | enum GlyphCompileMode compileMode ( void ) const { return compile_mode_; } |
| 213 | void setPointSize ( float point_size ); |
| 214 | float pointSize ( void ) { return point_size_; } |
| 215 | void setResolution ( FT_UInt resolution ); |
| 216 | FT_UInt resolution ( void ) { return resolution_; } |
| 217 | void setAdvance ( bool advance ) { advance_ = advance; } |
| 218 | bool advance ( void ) const { return advance_; } |
| 219 | void setForegroundColor ( GLfloat red = 0.0, GLfloat green = 0.0, GLfloat blue = 0.0, GLfloat alpha = 1.0 ); |
| 220 | void setForegroundColor ( const GLfloat foreground_color[4] ); |
| 221 | GLfloat foregroundRed ( void ) const { return foreground_color_[R]; } |
| 222 | GLfloat foregroundGreen ( void ) const { return foreground_color_[G]; } |
| 223 | GLfloat foregroundBlue ( void ) const { return foreground_color_[B]; } |
| 224 | GLfloat foregroundAlpha ( void ) const { return foreground_color_[A]; } |
| 225 | void setBackgroundColor ( GLfloat red = 1.0, GLfloat green = 1.0, GLfloat blue = 1.0, GLfloat alpha = 0.0 ); |
| 226 | void setBackgroundColor ( const GLfloat background_color[4] ); |
| 227 | GLfloat backgroundRed ( void ) const { return background_color_[R]; } |
| 228 | GLfloat backgroundGreen ( void ) const { return background_color_[G]; } |
| 229 | GLfloat backgroundBlue ( void ) const { return background_color_[B]; } |
| 230 | GLfloat backgroundAlpha ( void ) const { return background_color_[A]; } |
| 231 | virtual void setCharacterRotationZ ( GLfloat character_rotation_z ) = 0; |
| 232 | virtual GLfloat characterRotationZ ( void ) const = 0; |
| 233 | void setCharacterRotationReference ( unsigned char c ); |
| 234 | void setStringRotation ( GLfloat string_rotation ); |
| 235 | GLfloat stringRotation ( void ) const { return string_rotation_; } |
| 236 | void setHorizontalJustification ( enum HorizontalJustification horizontal_justification ) |
| 237 | { |
| 238 | horizontal_justification_ = horizontal_justification; |
| 239 | } |
| 240 | enum HorizontalJustification horizontalJustification ( void ) const { return horizontal_justification_; } |
| 241 | void setVerticalJustification ( enum VerticalJustification vertical_justification ) |
| 242 | { |
| 243 | vertical_justification_ = vertical_justification; |
| 244 | } |
| 245 | |
| 246 | enum VerticalJustification verticaljustification ( void ) const { return vertical_justification_; } |
| 247 | void setCharacterDisplayLists ( const DisplayLists& character_display_lists ) { character_display_lists_ = character_display_lists; } |
| 248 | DisplayLists& characterDisplayLists ( void ) { return character_display_lists_; } |
| 249 | virtual double height ( void ) const = 0; |
| 250 | virtual BBox measure ( unsigned char c ) = 0; |
| 251 | virtual BBox measure ( wchar_t c ) = 0; |
| 252 | virtual BBox measure ( const char* s ); |
| 253 | virtual BBox measureRaw ( const char* s ); |
| 254 | virtual BBox measure ( const wchar_t* s ); |
| 255 | virtual BBox measure ( const wchar_t* format, double number ); |
| 256 | virtual BBox measureRaw ( const wchar_t* s ); |
| 257 | GLuint compile ( unsigned char c ); |
| 258 | GLuint compile ( const wchar_t c ); |
| 259 | void draw ( const char* s ); |
| 260 | void draw ( const wchar_t* s ); |
| 261 | void draw ( unsigned char c ); |
| 262 | void draw ( const wchar_t c ); |
| 263 | void draw ( GLfloat x, GLfloat y, unsigned char c ); |
| 264 | void draw ( GLfloat x, GLfloat y, GLfloat z, unsigned char c ); |
| 265 | void draw ( GLfloat x, GLfloat y, wchar_t c ); |
| 266 | void draw ( GLfloat x, GLfloat y, GLfloat z, wchar_t c ); |
| 267 | void draw ( GLfloat x, GLfloat y, const char* s, float *sizebox ); |
| 268 | void draw ( GLfloat x, GLfloat y, GLfloat z, const char* s ); |
| 269 | void draw ( GLfloat x, GLfloat y, const wchar_t* s ); |
| 270 | void draw ( GLfloat x, GLfloat y, GLfloat z, const wchar_t* s ); |
| 271 | int ascender ( void ) { return faces_.front().face_->ascender; } |
| 272 | int descender ( void ) { return faces_.front().face_->descender; } |
| 273 | BBox measure_nominal ( const char* s ); |
| 274 | BBox measure_nominal ( const wchar_t* s ); |
| 275 | |
| 276 | protected: |
| 277 | virtual GLuint compileGlyph ( FT_Face face, FT_UInt glyph_index ) = 0; |
| 278 | virtual void renderGlyph ( FT_Face face, FT_UInt glyph_index ) = 0; |
| 279 | virtual void setCharSize ( void ) = 0; |
| 280 | virtual void clearCaches ( void ) = 0; |
| 281 | virtual void setRotationOffset ( void ) = 0; |
| 282 | |
| 283 | private: |
| 284 | void init ( void ); |
| 285 | }; |
| 286 | |
| 287 | class Raster : public Face |
| 288 | { |
| 289 | protected: |
| 290 | GLfloat character_rotation_z_; |
| 291 | public: |
| 292 | Raster ( const char* filename, float point_size = 12, FT_UInt resolution = 100 ); |
| 293 | Raster ( FT_Face face, float point_size = 12, FT_UInt resolution = 100 ); |
| 294 | virtual ~Raster ( void ); |
| 295 | void setCharacterRotationZ ( GLfloat character_rotation_z ); |
| 296 | GLfloat characterRotationZ ( void ) const { return character_rotation_z_; } |
| 297 | double height ( void ) const; |
| 298 | BBox measure ( unsigned char c ); |
| 299 | BBox measure ( wchar_t c ); |
| 300 | BBox measure ( const char* s ) { return Face::measure( s ); } |
| 301 | BBox measure ( const wchar_t* format, double number ) { return Face::measure( format, number ); } |
| 302 | |
| 303 | private: |
| 304 | void init ( void ); |
| 305 | GLuint compileGlyph ( FT_Face face, FT_UInt glyph_index ); |
| 306 | void setCharSize ( void ); |
| 307 | void setRotationOffset ( void ); |
| 308 | void clearCaches ( void ); |
| 309 | }; |
| 310 | class Monochrome : public Raster |
| 311 | { |
| 312 | public: |
| 313 | Monochrome ( const char* filename, float point_size = 12, FT_UInt resolution = 100 ); |
| 314 | Monochrome ( FT_Face face, float point_size = 12, FT_UInt resolution = 100 ); |
| 315 | ~Monochrome ( void ); |
| 316 | |
| 317 | private: |
| 318 | GLubyte* invertBitmap ( const FT_Bitmap& bitmap ); |
| 319 | void renderGlyph ( FT_Face face, FT_UInt glyph_index ); |
| 320 | }; |
| 321 | |
| 322 | } |
| 323 | #endif /* OGLFT_H */ |
| 324 | |