Panda3D
|
00001 // Filename: textMaker.cxx 00002 // Created by: drose (03Apr02) 00003 // 00004 ////////////////////////////////////////////////////////////////////// 00005 // PANDA 3D SOFTWARE 00006 // Copyright (c) Carnegie Mellon University. All rights reserved. 00007 // 00008 // All use of this software is subject to the terms of the revised BSD 00009 // license. You should have received a copy of this license along 00010 // with this source code in a file named "LICENSE." 00011 // 00012 //////////////////////////////////////////////////////////////////// 00013 00014 #include "pnmTextMaker.h" 00015 #include "pnmTextGlyph.h" 00016 #include "filename.h" 00017 #include "pnmImage.h" 00018 00019 //////////////////////////////////////////////////////////////////// 00020 // Function: PNMTextMaker::Constructor 00021 // Access: Public 00022 // Description: The constructor expects the name of some font file 00023 // that FreeType can read, along with face_index, 00024 // indicating which font within the file to load 00025 // (usually 0). 00026 //////////////////////////////////////////////////////////////////// 00027 PNMTextMaker:: 00028 PNMTextMaker(const Filename &font_filename, int face_index) { 00029 initialize(); 00030 _is_valid = load_font(font_filename, face_index); 00031 } 00032 00033 //////////////////////////////////////////////////////////////////// 00034 // Function: PNMTextMaker::Constructor 00035 // Access: Public 00036 // Description: This constructor works as above, but it takes the 00037 // font data from an in-memory buffer instead of from a 00038 // named file. 00039 //////////////////////////////////////////////////////////////////// 00040 PNMTextMaker:: 00041 PNMTextMaker(const char *font_data, int data_length, int face_index) { 00042 initialize(); 00043 _is_valid = load_font(font_data, data_length, face_index); 00044 } 00045 00046 //////////////////////////////////////////////////////////////////// 00047 // Function: PNMTextMaker::Copy Constructor 00048 // Access: Public 00049 // Description: 00050 //////////////////////////////////////////////////////////////////// 00051 PNMTextMaker:: 00052 PNMTextMaker(const PNMTextMaker ©) : 00053 FreetypeFont(copy), 00054 _is_valid(copy._is_valid), 00055 _align(copy._align), 00056 _interior_flag(copy._interior_flag), 00057 _fg(copy._fg), 00058 _interior(copy._interior) 00059 { 00060 } 00061 00062 //////////////////////////////////////////////////////////////////// 00063 // Function: PNMTextMaker::Destructor 00064 // Access: Public 00065 // Description: 00066 //////////////////////////////////////////////////////////////////// 00067 PNMTextMaker:: 00068 ~PNMTextMaker() { 00069 empty_cache(); 00070 } 00071 00072 //////////////////////////////////////////////////////////////////// 00073 // Function: PNMTextMaker::generate_into 00074 // Access: Public 00075 // Description: Generates a single line of text into the indicated 00076 // image at the indicated position; the return value is 00077 // the total width in pixels. 00078 //////////////////////////////////////////////////////////////////// 00079 int PNMTextMaker:: 00080 generate_into(const wstring &text, PNMImage &dest_image, int x, int y) { 00081 // First, measure the total width in pixels. 00082 int width = calc_width(text); 00083 00084 int xp = x; 00085 int yp = y; 00086 00087 switch (_align) { 00088 case A_left: 00089 xp = x; 00090 break; 00091 00092 case A_center: 00093 xp = x - (width / 2); 00094 break; 00095 00096 case A_right: 00097 xp = x - width; 00098 break; 00099 } 00100 00101 // Now place the text. 00102 wstring::const_iterator ti; 00103 for (ti = text.begin(); ti != text.end(); ++ti) { 00104 int ch = (*ti); 00105 PNMTextGlyph *glyph = get_glyph(ch); 00106 if (_interior_flag) { 00107 glyph->place(dest_image, xp, yp, _fg, _interior); 00108 } else { 00109 glyph->place(dest_image, xp, yp, _fg); 00110 } 00111 xp += glyph->get_advance(); 00112 } 00113 00114 return width; 00115 } 00116 00117 //////////////////////////////////////////////////////////////////// 00118 // Function: PNMTextMaker::calc_width 00119 // Access: Public 00120 // Description: Returns the width in pixels of the indicated line of 00121 // text. 00122 //////////////////////////////////////////////////////////////////// 00123 int PNMTextMaker:: 00124 calc_width(const wstring &text) { 00125 int width = 0; 00126 wstring::const_iterator ti; 00127 for (ti = text.begin(); ti != text.end(); ++ti) { 00128 int ch = (*ti); 00129 PNMTextGlyph *glyph = get_glyph(ch); 00130 width += glyph->get_advance(); 00131 } 00132 return width; 00133 } 00134 00135 //////////////////////////////////////////////////////////////////// 00136 // Function: PNMTextMaker::get_glyph 00137 // Access: Public 00138 // Description: Returns the glyph for the indicated index, or NULL if 00139 // it is not defined in the font. 00140 //////////////////////////////////////////////////////////////////// 00141 PNMTextGlyph *PNMTextMaker:: 00142 get_glyph(int character) { 00143 FT_Face face = acquire_face(); 00144 int glyph_index = FT_Get_Char_Index(face, character); 00145 release_face(face); 00146 00147 Glyphs::iterator gi; 00148 gi = _glyphs.find(glyph_index); 00149 if (gi != _glyphs.end()) { 00150 return (*gi).second; 00151 } 00152 00153 PNMTextGlyph *glyph = make_glyph(glyph_index); 00154 _glyphs.insert(Glyphs::value_type(glyph_index, glyph)); 00155 return glyph; 00156 } 00157 00158 //////////////////////////////////////////////////////////////////// 00159 // Function: PNMTextMaker::initialize 00160 // Access: Private 00161 // Description: Called from both constructors to set up some initial 00162 // values. 00163 //////////////////////////////////////////////////////////////////// 00164 void PNMTextMaker:: 00165 initialize() { 00166 _align = A_left; 00167 _interior_flag = false; 00168 _fg.set(0.0f, 0.0f, 0.0f, 1.0f); 00169 _interior.set(0.5f, 0.5f, 0.5f, 1.0f); 00170 } 00171 00172 //////////////////////////////////////////////////////////////////// 00173 // Function: PNMTextMaker::make_glyph 00174 // Access: Private 00175 // Description: Creates a new PNMTextGlyph object for the indicated 00176 // index, if possible. 00177 //////////////////////////////////////////////////////////////////// 00178 PNMTextGlyph *PNMTextMaker:: 00179 make_glyph(int glyph_index) { 00180 FT_Face face = acquire_face(); 00181 if (!load_glyph(face, glyph_index)) { 00182 release_face(face); 00183 return (PNMTextGlyph *)NULL; 00184 } 00185 00186 FT_GlyphSlot slot = face->glyph; 00187 00188 FT_Bitmap &bitmap = slot->bitmap; 00189 00190 double advance = slot->advance.x / 64.0; 00191 00192 PNMTextGlyph *glyph = new PNMTextGlyph(advance); 00193 00194 if (bitmap.width == 0 || bitmap.rows == 0) { 00195 // If we got an empty bitmap, it's a special case. 00196 glyph->rescale(_scale_factor); 00197 00198 } else { 00199 PNMImage &glyph_image = glyph->_image; 00200 glyph_image.clear(bitmap.width, bitmap.rows, 3); 00201 copy_bitmap_to_pnmimage(bitmap, glyph_image); 00202 00203 glyph->_top = slot->bitmap_top; 00204 glyph->_left = slot->bitmap_left; 00205 00206 if (_interior_flag) { 00207 glyph->determine_interior(); 00208 } 00209 glyph->rescale(_scale_factor); 00210 } 00211 00212 release_face(face); 00213 return glyph; 00214 } 00215 00216 //////////////////////////////////////////////////////////////////// 00217 // Function: PNMTextMaker::empty_cache 00218 // Access: Private 00219 // Description: Empties the cache of previously-generated glyphs. 00220 //////////////////////////////////////////////////////////////////// 00221 void PNMTextMaker:: 00222 empty_cache() { 00223 Glyphs::iterator gi; 00224 for (gi = _glyphs.begin(); gi != _glyphs.end(); ++gi) { 00225 PNMTextGlyph *glyph = (*gi).second; 00226 delete glyph; 00227 } 00228 }