Panda3D
 All Classes Functions Variables Enumerations
pnmTextMaker.cxx
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 &copy) :
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 }
 All Classes Functions Variables Enumerations