Panda3D
|
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 ©) { 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 ©) { 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 }