Panda3D
 All Classes Functions Variables Enumerations
textProperties.cxx
00001 // Filename: textProperties.cxx
00002 // Created by:  drose (06Apr04)
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 "textProperties.h"
00016 #include "config_text.h"
00017 #include "default_font.h"
00018 #include "dynamicTextFont.h"
00019 #include "staticTextFont.h"
00020 #include "bamFile.h"
00021 #include "fontPool.h"
00022 
00023 PT(TextFont) TextProperties::_default_font;
00024 bool TextProperties::_loaded_default_font = false;
00025 
00026 TypeHandle TextProperties::_type_handle;
00027 
00028 ////////////////////////////////////////////////////////////////////
00029 //     Function: TextProperties::Constructor
00030 //       Access: Published
00031 //  Description:
00032 ////////////////////////////////////////////////////////////////////
00033 TextProperties::
00034 TextProperties() {
00035   _specified = 0;
00036 
00037   _small_caps = text_small_caps;
00038   _small_caps_scale = text_small_caps_scale;
00039   _slant = 0.0f;
00040   _underscore = false;
00041   _underscore_height = 0.0f;
00042   _align = A_left;
00043   _indent_width = 0.0f;
00044   _wordwrap_width = 0.0f;
00045   _preserve_trailing_whitespace = false;
00046   _text_color.set(1.0f, 1.0f, 1.0f, 1.0f);
00047   _shadow_color.set(0.0f, 0.0f, 0.0f, 1.0f);
00048   _shadow_offset.set(0.0f, 0.0f);
00049   _draw_order = 1;
00050   _tab_width = text_tab_width;
00051   _glyph_scale = 1.0f;
00052   _glyph_shift = 0.0f;
00053   _text_scale = 1.0f;
00054 }
00055 
00056 ////////////////////////////////////////////////////////////////////
00057 //     Function: TextProperties::Copy Constructor
00058 //       Access: Published
00059 //  Description:
00060 ////////////////////////////////////////////////////////////////////
00061 TextProperties::
00062 TextProperties(const TextProperties &copy) {
00063   (*this) = copy;
00064 }
00065 
00066 ////////////////////////////////////////////////////////////////////
00067 //     Function: TextProperties::Copy Assignment Operator
00068 //       Access: Published
00069 //  Description:
00070 ////////////////////////////////////////////////////////////////////
00071 void TextProperties::
00072 operator = (const TextProperties &copy) {
00073   _specified = copy._specified;
00074 
00075   _font = copy._font;
00076   _small_caps = copy._small_caps;
00077   _small_caps_scale = copy._small_caps_scale;
00078   _slant = copy._slant;
00079   _underscore = copy._underscore;
00080   _underscore_height = copy._underscore_height;
00081   _align = copy._align;
00082   _indent_width = copy._indent_width;
00083   _wordwrap_width = copy._wordwrap_width;
00084   _preserve_trailing_whitespace = copy._preserve_trailing_whitespace;
00085   _text_color = copy._text_color;
00086   _shadow_color = copy._shadow_color;
00087   _shadow_offset = copy._shadow_offset;
00088   _bin = copy._bin;
00089   _draw_order = copy._draw_order;
00090   _tab_width = copy._tab_width;
00091   _glyph_scale = copy._glyph_scale;
00092   _glyph_shift = copy._glyph_shift;
00093   _text_scale = copy._text_scale;
00094 }
00095 
00096 ////////////////////////////////////////////////////////////////////
00097 //     Function: TextProperties::operator ==
00098 //       Access: Published
00099 //  Description:
00100 ////////////////////////////////////////////////////////////////////
00101 bool TextProperties::
00102 operator == (const TextProperties &other) const {
00103   if (_specified != other._specified) {
00104     return false;
00105   }
00106 
00107   if ((_specified & F_has_font) && _font != other._font) {
00108     return false;
00109   }
00110   if ((_specified & F_has_small_caps) && _small_caps != other._small_caps) {
00111     return false;
00112   }
00113   if ((_specified & F_has_small_caps_scale) && _small_caps_scale != other._small_caps_scale) {
00114     return false;
00115   }
00116   if ((_specified & F_has_slant) && _slant != other._slant) {
00117     return false;
00118   }
00119   if ((_specified & F_has_underscore) && _underscore != other._underscore) {
00120     return false;
00121   }
00122   if ((_specified & F_has_underscore_height) && _underscore_height != other._underscore_height) {
00123     return false;
00124   }
00125   if ((_specified & F_has_align) && _align != other._align) {
00126     return false;
00127   }
00128   if ((_specified & F_has_indent) && _indent_width != other._indent_width) {
00129     return false;
00130   }
00131   if ((_specified & F_has_wordwrap) && _wordwrap_width != other._wordwrap_width) {
00132     return false;
00133   }
00134   if ((_specified & F_has_preserve_trailing_whitespace) && _preserve_trailing_whitespace != other._preserve_trailing_whitespace) {
00135     return false;
00136   }
00137   if ((_specified & F_has_text_color) && _text_color != other._text_color) {
00138     return false;
00139   }
00140   if ((_specified & F_has_text_color) && _text_color != other._text_color) {
00141     return false;
00142   }
00143   if ((_specified & F_has_shadow_color) && _shadow_color != other._shadow_color) {
00144     return false;
00145   }
00146   if ((_specified & F_has_shadow) && _shadow_offset != other._shadow_offset) {
00147     return false;
00148   }
00149   if ((_specified & F_has_bin) && _bin != other._bin) {
00150     return false;
00151   }
00152   if ((_specified & F_has_draw_order) && _draw_order != other._draw_order) {
00153     return false;
00154   }
00155   if ((_specified & F_has_tab_width) && _tab_width != other._tab_width) {
00156     return false;
00157   }
00158   if ((_specified & F_has_glyph_scale) && _glyph_scale != other._glyph_scale) {
00159     return false;
00160   }
00161   if ((_specified & F_has_glyph_shift) && _glyph_shift != other._glyph_shift) {
00162     return false;
00163   }
00164   if ((_specified & F_has_text_scale) && _text_scale != other._text_scale) {
00165     return false;
00166   }
00167   return true;
00168 }
00169 
00170 ////////////////////////////////////////////////////////////////////
00171 //     Function: TextProperties::clear
00172 //       Access: Published
00173 //  Description: Unsets all properties that have been specified so
00174 //               far, and resets the TextProperties structure to its
00175 //               initial empty state.
00176 ////////////////////////////////////////////////////////////////////
00177 void TextProperties::
00178 clear() {
00179   (*this) = TextProperties();
00180 }
00181 
00182 ////////////////////////////////////////////////////////////////////
00183 //     Function: TextProperties::add_properties
00184 //       Access: Published
00185 //  Description: Sets any properties that are explicitly specified in
00186 //               other on this object.  Leaves other properties
00187 //               unchanged.
00188 ////////////////////////////////////////////////////////////////////
00189 void TextProperties::
00190 add_properties(const TextProperties &other) {
00191   if (other.has_font()) {
00192     set_font(other.get_font());
00193   }
00194   if (other.has_small_caps()) {
00195     set_small_caps(other.get_small_caps());
00196     set_small_caps_scale(other.get_small_caps_scale());
00197   }
00198   if (other.has_slant()) {
00199     set_slant(other.get_slant());
00200   }
00201   if (other.has_underscore()) {
00202     set_underscore(other.get_underscore());
00203   }
00204   if (other.has_underscore_height()) {
00205     set_underscore_height(other.get_underscore_height());
00206   }
00207   if (other.has_align()) {
00208     set_align(other.get_align());
00209   }
00210   if (other.has_indent()) {
00211     set_indent(other.get_indent());
00212   }
00213   if (other.has_wordwrap()) {
00214     set_wordwrap(other.get_wordwrap());
00215   }
00216   if (other.has_text_color()) {
00217     set_text_color(other.get_text_color());
00218   }
00219   if (other.has_shadow_color()) {
00220     set_shadow_color(other.get_shadow_color());
00221   }
00222   if (other.has_shadow()) {
00223     set_shadow(other.get_shadow());
00224   }
00225   if (other.has_bin()) {
00226     set_bin(other.get_bin());
00227   }
00228   if (other.has_draw_order()) {
00229     set_draw_order(other.get_draw_order());
00230   }
00231   if (other.has_tab_width()) {
00232     set_tab_width(other.get_tab_width());
00233   }
00234 
00235   // The glyph scale and shift are a special case: rather than
00236   // replacing the previous value, they modify it, so that they apply
00237   // cumulatively to nested TextProperties.
00238   if (other.has_glyph_shift()) {
00239     set_glyph_shift(other.get_glyph_shift() * get_glyph_scale() + get_glyph_shift());
00240   }
00241   if (other.has_glyph_scale()) {
00242     set_glyph_scale(other.get_glyph_scale() * get_glyph_scale());
00243   }
00244 
00245   if (other.has_text_scale()) {
00246     set_text_scale(other.get_text_scale());
00247   }
00248 }
00249 
00250 
00251 ////////////////////////////////////////////////////////////////////
00252 //     Function: TextProperties::write
00253 //       Access: Published
00254 //  Description:
00255 ////////////////////////////////////////////////////////////////////
00256 void TextProperties::
00257 write(ostream &out, int indent_level) const {
00258   if (!is_any_specified()) {
00259     indent(out, indent_level)
00260       << "default properties\n";
00261   }
00262   if (has_font()) {
00263     if (get_font() != (TextFont *)NULL) {
00264       indent(out, indent_level)
00265         << "with font " << _font->get_name() << "\n";
00266     } else {
00267       indent(out, indent_level)
00268         << "with NULL font\n";
00269     }
00270   }
00271   if (has_small_caps()) {
00272     indent(out, indent_level)
00273       << "small caps = " << get_small_caps() << "\n";
00274   }
00275   if (has_small_caps_scale()) {
00276     indent(out, indent_level)
00277       << "small caps scale = " << get_small_caps_scale() << "\n";
00278   }
00279   if (has_slant()) {
00280     indent(out, indent_level)
00281       << "slant = " << get_slant() << "\n";
00282   }
00283   if (has_underscore()) {
00284     indent(out, indent_level)
00285       << "underscore = " << get_underscore() << "\n";
00286   }
00287   if (has_underscore_height()) {
00288     indent(out, indent_level)
00289       << "underscore_height = " << get_underscore_height() << "\n";
00290   }
00291 
00292   if (has_align()) {
00293     indent(out, indent_level)
00294       << "alignment is ";
00295     switch (get_align()) {
00296     case A_left:
00297       out << "A_left\n";
00298       break;
00299       
00300     case A_right:
00301       out << "A_right\n";
00302       break;
00303       
00304     case A_center:
00305       out << "A_center\n";
00306       break;
00307 
00308     case A_boxed_left:
00309       out << "A_boxed_left\n";
00310       break;
00311       
00312     case A_boxed_right:
00313       out << "A_boxed_right\n";
00314       break;
00315       
00316     case A_boxed_center:
00317       out << "A_boxed_center\n";
00318       break;
00319     }
00320   }
00321 
00322   if (has_indent()) {
00323     indent(out, indent_level)
00324       << "indent at " << get_indent() << " units.\n";
00325   }
00326 
00327   if (has_wordwrap()) {
00328     indent(out, indent_level)
00329       << "word-wrapping at " << get_wordwrap() << " units.\n";
00330   }
00331 
00332   if (has_text_color()) {
00333     indent(out, indent_level)
00334       << "text color is " << get_text_color() << "\n";
00335   }
00336 
00337   if (has_shadow()) {
00338     indent(out, indent_level)
00339       << "shadow at " << get_shadow() << "\n";
00340   }
00341   if (has_shadow_color()) {
00342     indent(out, indent_level)
00343       << "shadow color is " << get_shadow_color() << "\n";
00344   }
00345 
00346   if (has_bin()) {
00347     indent(out, indent_level)
00348       << "bin is " << get_bin() << "\n";
00349   }
00350   if (has_draw_order()) {
00351     indent(out, indent_level)
00352       << "draw order is " << get_draw_order() << "\n";
00353   }
00354 
00355   if (has_tab_width()) {
00356     indent(out, indent_level)
00357       << "tab width is " << get_tab_width() << "\n";
00358   }
00359 
00360   if (has_glyph_scale()) {
00361     indent(out, indent_level)
00362       << "glyph scale is " << get_glyph_scale() << "\n";
00363   }
00364   if (has_glyph_shift()) {
00365     indent(out, indent_level)
00366       << "glyph shift is " << get_glyph_shift() << "\n";
00367   }
00368 
00369   if (has_text_scale()) {
00370     indent(out, indent_level)
00371       << "text scale is " << get_text_scale() << "\n";
00372   }
00373 }
00374 
00375 ////////////////////////////////////////////////////////////////////
00376 //     Function: TextProperties::load_default_font
00377 //       Access: Private, Static
00378 //  Description: This function is called once (or never), the first
00379 //               time someone attempts to render a TextNode using the
00380 //               default font.  It should attempt to load the default
00381 //               font, using the compiled-in version if it is
00382 //               available, or whatever system file may be named in
00383 //               Configrc.
00384 ////////////////////////////////////////////////////////////////////
00385 void TextProperties::
00386 load_default_font() {
00387   _loaded_default_font = true;
00388 
00389   if (!text_default_font.empty()) {
00390     // First, attempt to load the user-specified filename.
00391     _default_font = FontPool::load_font(text_default_font.get_value());
00392     if (_default_font != (TextFont *)NULL && _default_font->is_valid()) {
00393       return;
00394     }
00395   }
00396 
00397   // Then, attempt to load the compiled-in font, if we have one.
00398 #ifdef COMPILE_IN_DEFAULT_FONT
00399 #ifdef HAVE_FREETYPE
00400   // Loading the compiled-in FreeType font is relatively easy.
00401   _default_font = new DynamicTextFont((const char *)default_font_data, 
00402                                       default_font_size, 0);
00403   // The compiled-in font seems to confuse FreeType about its winding order.
00404   ((DynamicTextFont *)_default_font.p())->set_winding_order(DynamicTextFont::WO_left);
00405 
00406 #else
00407   // The compiled-in Bam font requires creating a BamFile object to
00408   // decode it.
00409   string data((const char *)default_font_data, default_font_size);
00410 
00411 #ifdef HAVE_ZLIB
00412   // The font data is stored compressed; decompress it on-the-fly.
00413   istringstream inz(data);
00414   IDecompressStream in(&inz, false);
00415   
00416 #else
00417   // The font data is stored uncompressed, so just load it.
00418   istringstream in(data);
00419 #endif  // HAVE_ZLIB
00420   
00421   BamFile bam_file;
00422   if (bam_file.open_read(in, "default font stream")) {
00423     PT(PandaNode) node = bam_file.read_node();
00424     if (node != (PandaNode *)NULL) {
00425       _default_font = new StaticTextFont(node);
00426     }
00427   }
00428   
00429 #endif  // HAVE_FREETYPE
00430 #endif  // COMPILE_IN_DEFAULT_FONT
00431 }
 All Classes Functions Variables Enumerations