Panda3D
 All Classes Functions Variables Enumerations
dynamicTextPage.cxx
00001 // Filename: dynamicTextPage.cxx
00002 // Created by:  drose (09Feb02)
00003 //
00004 ////////////////////////////////////////////////////////////////////
00005 //
00006 // PANDA 3D SOFTWARE
00007 // Copyright (c) Carnegie Mellon University.  All rights reserved.
00008 //
00009 // All use of this software is subject to the terms of the revised BSD
00010 // license.  You should have received a copy of this license along
00011 // with this source code in a file named "LICENSE."
00012 //
00013 ////////////////////////////////////////////////////////////////////
00014 
00015 #include "dynamicTextPage.h"
00016 #include "dynamicTextFont.h"
00017 
00018 #ifdef HAVE_FREETYPE
00019 
00020 
00021 TypeHandle DynamicTextPage::_type_handle;
00022 
00023 ////////////////////////////////////////////////////////////////////
00024 //     Function: DynamicTextPage::Constructor
00025 //       Access: Publiic
00026 //  Description: 
00027 ////////////////////////////////////////////////////////////////////
00028 DynamicTextPage::
00029 DynamicTextPage(DynamicTextFont *font, int page_number) : 
00030   _font(font)
00031 {
00032   // Since the texture might change frequently, don't try to compress
00033   // it by default.
00034   set_compression(CM_off);
00035 
00036   // It's usually pretty important for text to look its best, and it
00037   // doesn't usually have a high fill factor.
00038   set_quality_level(text_quality_level);
00039 
00040   _x_size = _font->get_page_x_size();
00041   _y_size = _font->get_page_y_size();
00042 
00043   setup_2d_texture(_x_size, _y_size, T_unsigned_byte, font->get_tex_format());
00044 
00045   // Assign a name to the Texture.
00046   ostringstream strm;
00047   strm << font->get_name() << "_" << page_number;
00048   set_name(strm.str());
00049 
00050   // We'd better never free this image.
00051   set_keep_ram_image(true);
00052 
00053   set_minfilter(_font->get_minfilter());
00054   set_magfilter(_font->get_magfilter());
00055 
00056   set_anisotropic_degree(_font->get_anisotropic_degree());
00057 
00058   // Clamp to an explicit invisible border, so we don't get bleeding
00059   // at the edges at all.
00060   set_wrap_u(text_wrap_mode);
00061   set_wrap_v(text_wrap_mode);
00062   set_border_color(font->get_bg());
00063 
00064   // Fill the page with the font's background color.
00065   fill_region(0, 0, _x_size, _y_size, font->get_bg());
00066 }
00067 
00068 ////////////////////////////////////////////////////////////////////
00069 //     Function: DynamicTextPage::slot_glyph
00070 //       Access: Public
00071 //  Description: Finds space within the page for a glyph of the
00072 //               indicated size.  If space is found, creates a new
00073 //               glyph object and returns it; otherwise, returns NULL.
00074 ////////////////////////////////////////////////////////////////////
00075 DynamicTextGlyph *DynamicTextPage::
00076 slot_glyph(int character, int x_size, int y_size, int margin) {
00077   int x, y;
00078   if (!find_hole(x, y, x_size, y_size)) {
00079     // No room for the glyph.
00080     return (DynamicTextGlyph *)NULL;
00081   }
00082 
00083   // The glyph can be fit at (x, y).  Slot it.
00084   PT(DynamicTextGlyph) glyph = 
00085     new DynamicTextGlyph(character, this,
00086                          x, y, x_size, y_size, margin);
00087   _glyphs.push_back(glyph);
00088   return glyph;
00089 }
00090 
00091 ////////////////////////////////////////////////////////////////////
00092 //     Function: DynamicTextPage::fill_region
00093 //       Access: Private
00094 //  Description: Fills a rectangular region of the texture with the
00095 //               indicated color.
00096 ////////////////////////////////////////////////////////////////////
00097 void DynamicTextPage::
00098 fill_region(int x, int y, int x_size, int y_size, const LColor &color) {
00099   nassertv(x >= 0 && x + x_size <= _x_size && y >= 0 && y + y_size <= _y_size);
00100   int num_components = get_num_components();
00101   if (num_components == 1) {
00102     // Luminance or alpha.
00103     int ci = 3;
00104     if (get_format() != Texture::F_alpha) {
00105       ci = 0;
00106     }
00107     
00108     unsigned char v = (unsigned char)(color[ci] * 255.0f);
00109 
00110     unsigned char *image = modify_ram_image();
00111     for (int yi = y; yi < y + y_size; yi++) {
00112       unsigned char *row = image + yi * _x_size;
00113       memset(row + x, v, x_size);
00114     }
00115 
00116   } else if (num_components == 2) {
00117     // Luminance + alpha.
00118 
00119     union {
00120       unsigned char p[2];
00121       PN_uint16 v;
00122     } v;
00123 
00124     v.p[0] = (unsigned char)(color[0] * 255.0f);
00125     v.p[1] = (unsigned char)(color[3] * 255.0f);
00126 
00127     PN_uint16 *image = (PN_uint16 *)modify_ram_image().p();
00128     for (int yi = y; yi < y + y_size; yi++) {
00129       PN_uint16 *row = image + yi * _x_size ;
00130       for (int xi = x; xi < x + x_size; xi++) {
00131         row[xi] = v.v;
00132       }
00133     }
00134 
00135   } else if (num_components == 3) {
00136     // RGB.
00137 
00138     unsigned char p0 = (unsigned char)(color[2] * 255.0f);
00139     unsigned char p1 = (unsigned char)(color[1] * 255.0f);
00140     unsigned char p2 = (unsigned char)(color[0] * 255.0f);
00141 
00142     unsigned char *image = modify_ram_image();
00143     for (int yi = y; yi < y + y_size; yi++) {
00144       unsigned char *row = image + yi * _x_size * 3;
00145       for (int xi = x; xi < x + x_size; xi++) {
00146         row[xi * 3] = p0;
00147         row[xi * 3 + 1] = p1;
00148         row[xi * 3 + 2] = p2;
00149       }
00150     }
00151     
00152   } else { // (num_components == 4)
00153     // RGBA.
00154     union {
00155       unsigned char p[4];
00156       PN_uint32 v;
00157     } v;
00158 
00159     v.p[0] = (unsigned char)(color[2] * 255.0f);
00160     v.p[1] = (unsigned char)(color[1] * 255.0f);
00161     v.p[2] = (unsigned char)(color[0] * 255.0f);
00162     v.p[3] = (unsigned char)(color[3] * 255.0f);
00163 
00164     PN_uint32 *image = (PN_uint32 *)modify_ram_image().p();
00165     for (int yi = y; yi < y + y_size; yi++) {
00166       PN_uint32 *row = image + yi * _x_size;
00167       for (int xi = x; xi < x + x_size; xi++) {
00168         row[xi] = v.v;
00169       }
00170     }
00171   }    
00172 }
00173 
00174 ////////////////////////////////////////////////////////////////////
00175 //     Function: DynamicTextPage::garbage_collect
00176 //       Access: Private
00177 //  Description: Removes all of the glyphs from the page that are no
00178 //               longer being used by any Geoms.  This should only be
00179 //               called from DynamicTextFont::garbage_collect(), since
00180 //               it is important to remove these glyphs from the
00181 //               font's index first.
00182 ////////////////////////////////////////////////////////////////////
00183 int DynamicTextPage::
00184 garbage_collect(DynamicTextFont *font) {
00185   int removed_count = 0;
00186 
00187   Glyphs new_glyphs;
00188   Glyphs::iterator gi;
00189   for (gi = _glyphs.begin(); gi != _glyphs.end(); ++gi) {
00190     DynamicTextGlyph *glyph = (*gi);
00191     if (glyph->_geom_count != 0) {
00192       // Keep this one.
00193       new_glyphs.insert(new_glyphs.end(), (*gi));
00194     } else {
00195       // Drop this one.
00196       removed_count++;
00197       glyph->erase(font);
00198     }
00199   }
00200 
00201   _glyphs.swap(new_glyphs);
00202   return removed_count;
00203 }
00204 
00205 ////////////////////////////////////////////////////////////////////
00206 //     Function: DynamicTextPage::find_hole
00207 //       Access: Private
00208 //  Description: Searches for a hole of at least x_size by y_size
00209 //               pixels somewhere within the page.  If a suitable hole
00210 //               is found, sets x and y to the top left corner and
00211 //               returns true; otherwise, returns false.
00212 ////////////////////////////////////////////////////////////////////
00213 bool DynamicTextPage::
00214 find_hole(int &x, int &y, int x_size, int y_size) const {
00215   y = 0;
00216   while (y + y_size <= _y_size) {
00217     int next_y = _y_size;
00218     // Scan along the row at 'y'.
00219     x = 0;
00220     while (x + x_size <= _x_size) {
00221       int next_x = x;
00222 
00223       // Consider the spot at x, y.
00224       DynamicTextGlyph *overlap = find_overlap(x, y, x_size, y_size);
00225 
00226       if (overlap == (DynamicTextGlyph *)NULL) {
00227         // Hooray!
00228         return true;
00229       }
00230 
00231       next_x = overlap->_x + overlap->_x_size;
00232       next_y = min(next_y, overlap->_y + overlap->_y_size);
00233       nassertr(next_x > x, false);
00234       x = next_x;
00235     }
00236 
00237     nassertr(next_y > y, false);
00238     y = next_y;
00239   }
00240 
00241   // Nope, wouldn't fit anywhere.
00242   return false;
00243 }
00244 
00245 ////////////////////////////////////////////////////////////////////
00246 //     Function: DynamicTextPage::find_overlap
00247 //       Access: Private
00248 //  Description: If the rectangle whose top left corner is x, y and
00249 //               whose size is x_size, y_size describes an empty hole
00250 //               that does not overlap any placed glyphs, returns
00251 //               NULL; otherwise, returns the first placed glyph
00252 //               that the image does overlap.  It is assumed the
00253 //               rectangle lies completely within the boundaries of
00254 //               the page itself.
00255 ////////////////////////////////////////////////////////////////////
00256 DynamicTextGlyph *DynamicTextPage::
00257 find_overlap(int x, int y, int x_size, int y_size) const {
00258   Glyphs::const_iterator gi;
00259   for (gi = _glyphs.begin(); gi != _glyphs.end(); ++gi) {
00260     DynamicTextGlyph *glyph = (*gi);
00261     if (glyph->intersects(x, y, x_size, y_size)) {
00262       return glyph;
00263     }
00264   }
00265 
00266   return (DynamicTextGlyph *)NULL;
00267 }
00268 
00269 
00270 #endif  // HAVE_FREETYPE
 All Classes Functions Variables Enumerations