// Filename: textProperties.cxx // Created by: drose (06Apr04) // //////////////////////////////////////////////////////////////////// // // PANDA 3D SOFTWARE // Copyright (c) Carnegie Mellon University. All rights reserved. // // All use of this software is subject to the terms of the revised BSD // license. You should have received a copy of this license along // with this source code in a file named "LICENSE." // //////////////////////////////////////////////////////////////////// #include "textProperties.h" #include "config_text.h" #include "default_font.h" #include "dynamicTextFont.h" #include "staticTextFont.h" #include "bamFile.h" #include "fontPool.h" PT(TextFont) TextProperties::_default_font; bool TextProperties::_loaded_default_font = false; TypeHandle TextProperties::_type_handle; //////////////////////////////////////////////////////////////////// // Function: TextProperties::Constructor // Access: Published // Description: //////////////////////////////////////////////////////////////////// TextProperties:: TextProperties() { _specified = 0; _small_caps = text_small_caps; _small_caps_scale = text_small_caps_scale; _slant = 0.0f; _underscore = false; _underscore_height = 0.0f; _align = A_left; _indent_width = 0.0f; _wordwrap_width = 0.0f; _preserve_trailing_whitespace = false; _text_color.set(1.0f, 1.0f, 1.0f, 1.0f); _shadow_color.set(0.0f, 0.0f, 0.0f, 1.0f); _shadow_offset.set(0.0f, 0.0f); _draw_order = 1; _tab_width = text_tab_width; _glyph_scale = 1.0f; _glyph_shift = 0.0f; _text_scale = 1.0f; } //////////////////////////////////////////////////////////////////// // Function: TextProperties::Copy Constructor // Access: Published // Description: //////////////////////////////////////////////////////////////////// TextProperties:: TextProperties(const TextProperties ©) { (*this) = copy; } //////////////////////////////////////////////////////////////////// // Function: TextProperties::Copy Assignment Operator // Access: Published // Description: //////////////////////////////////////////////////////////////////// void TextProperties:: operator = (const TextProperties ©) { _specified = copy._specified; _font = copy._font; _small_caps = copy._small_caps; _small_caps_scale = copy._small_caps_scale; _slant = copy._slant; _underscore = copy._underscore; _underscore_height = copy._underscore_height; _align = copy._align; _indent_width = copy._indent_width; _wordwrap_width = copy._wordwrap_width; _preserve_trailing_whitespace = copy._preserve_trailing_whitespace; _text_color = copy._text_color; _shadow_color = copy._shadow_color; _shadow_offset = copy._shadow_offset; _bin = copy._bin; _draw_order = copy._draw_order; _tab_width = copy._tab_width; _glyph_scale = copy._glyph_scale; _glyph_shift = copy._glyph_shift; _text_scale = copy._text_scale; } //////////////////////////////////////////////////////////////////// // Function: TextProperties::operator == // Access: Published // Description: //////////////////////////////////////////////////////////////////// bool TextProperties:: operator == (const TextProperties &other) const { if (_specified != other._specified) { return false; } if ((_specified & F_has_font) && _font != other._font) { return false; } if ((_specified & F_has_small_caps) && _small_caps != other._small_caps) { return false; } if ((_specified & F_has_small_caps_scale) && _small_caps_scale != other._small_caps_scale) { return false; } if ((_specified & F_has_slant) && _slant != other._slant) { return false; } if ((_specified & F_has_underscore) && _underscore != other._underscore) { return false; } if ((_specified & F_has_underscore_height) && _underscore_height != other._underscore_height) { return false; } if ((_specified & F_has_align) && _align != other._align) { return false; } if ((_specified & F_has_indent) && _indent_width != other._indent_width) { return false; } if ((_specified & F_has_wordwrap) && _wordwrap_width != other._wordwrap_width) { return false; } if ((_specified & F_has_preserve_trailing_whitespace) && _preserve_trailing_whitespace != other._preserve_trailing_whitespace) { return false; } if ((_specified & F_has_text_color) && _text_color != other._text_color) { return false; } if ((_specified & F_has_text_color) && _text_color != other._text_color) { return false; } if ((_specified & F_has_shadow_color) && _shadow_color != other._shadow_color) { return false; } if ((_specified & F_has_shadow) && _shadow_offset != other._shadow_offset) { return false; } if ((_specified & F_has_bin) && _bin != other._bin) { return false; } if ((_specified & F_has_draw_order) && _draw_order != other._draw_order) { return false; } if ((_specified & F_has_tab_width) && _tab_width != other._tab_width) { return false; } if ((_specified & F_has_glyph_scale) && _glyph_scale != other._glyph_scale) { return false; } if ((_specified & F_has_glyph_shift) && _glyph_shift != other._glyph_shift) { return false; } if ((_specified & F_has_text_scale) && _text_scale != other._text_scale) { return false; } return true; } //////////////////////////////////////////////////////////////////// // Function: TextProperties::clear // Access: Published // Description: Unsets all properties that have been specified so // far, and resets the TextProperties structure to its // initial empty state. //////////////////////////////////////////////////////////////////// void TextProperties:: clear() { (*this) = TextProperties(); } //////////////////////////////////////////////////////////////////// // Function: TextProperties::add_properties // Access: Published // Description: Sets any properties that are explicitly specified in // other on this object. Leaves other properties // unchanged. //////////////////////////////////////////////////////////////////// void TextProperties:: add_properties(const TextProperties &other) { if (other.has_font()) { set_font(other.get_font()); } if (other.has_small_caps()) { set_small_caps(other.get_small_caps()); set_small_caps_scale(other.get_small_caps_scale()); } if (other.has_slant()) { set_slant(other.get_slant()); } if (other.has_underscore()) { set_underscore(other.get_underscore()); } if (other.has_underscore_height()) { set_underscore_height(other.get_underscore_height()); } if (other.has_align()) { set_align(other.get_align()); } if (other.has_indent()) { set_indent(other.get_indent()); } if (other.has_wordwrap()) { set_wordwrap(other.get_wordwrap()); } if (other.has_text_color()) { set_text_color(other.get_text_color()); } if (other.has_shadow_color()) { set_shadow_color(other.get_shadow_color()); } if (other.has_shadow()) { set_shadow(other.get_shadow()); } if (other.has_bin()) { set_bin(other.get_bin()); } if (other.has_draw_order()) { set_draw_order(other.get_draw_order()); } if (other.has_tab_width()) { set_tab_width(other.get_tab_width()); } // The glyph scale and shift are a special case: rather than // replacing the previous value, they modify it, so that they apply // cumulatively to nested TextProperties. if (other.has_glyph_shift()) { set_glyph_shift(other.get_glyph_shift() * get_glyph_scale() + get_glyph_shift()); } if (other.has_glyph_scale()) { set_glyph_scale(other.get_glyph_scale() * get_glyph_scale()); } if (other.has_text_scale()) { set_text_scale(other.get_text_scale()); } } //////////////////////////////////////////////////////////////////// // Function: TextProperties::write // Access: Published // Description: //////////////////////////////////////////////////////////////////// void TextProperties:: write(ostream &out, int indent_level) const { if (!is_any_specified()) { indent(out, indent_level) << "default properties\n"; } if (has_font()) { if (get_font() != (TextFont *)NULL) { indent(out, indent_level) << "with font " << _font->get_name() << "\n"; } else { indent(out, indent_level) << "with NULL font\n"; } } if (has_small_caps()) { indent(out, indent_level) << "small caps = " << get_small_caps() << "\n"; } if (has_small_caps_scale()) { indent(out, indent_level) << "small caps scale = " << get_small_caps_scale() << "\n"; } if (has_slant()) { indent(out, indent_level) << "slant = " << get_slant() << "\n"; } if (has_underscore()) { indent(out, indent_level) << "underscore = " << get_underscore() << "\n"; } if (has_underscore_height()) { indent(out, indent_level) << "underscore_height = " << get_underscore_height() << "\n"; } if (has_align()) { indent(out, indent_level) << "alignment is "; switch (get_align()) { case A_left: out << "A_left\n"; break; case A_right: out << "A_right\n"; break; case A_center: out << "A_center\n"; break; case A_boxed_left: out << "A_boxed_left\n"; break; case A_boxed_right: out << "A_boxed_right\n"; break; case A_boxed_center: out << "A_boxed_center\n"; break; } } if (has_indent()) { indent(out, indent_level) << "indent at " << get_indent() << " units.\n"; } if (has_wordwrap()) { indent(out, indent_level) << "word-wrapping at " << get_wordwrap() << " units.\n"; } if (has_text_color()) { indent(out, indent_level) << "text color is " << get_text_color() << "\n"; } if (has_shadow()) { indent(out, indent_level) << "shadow at " << get_shadow() << "\n"; } if (has_shadow_color()) { indent(out, indent_level) << "shadow color is " << get_shadow_color() << "\n"; } if (has_bin()) { indent(out, indent_level) << "bin is " << get_bin() << "\n"; } if (has_draw_order()) { indent(out, indent_level) << "draw order is " << get_draw_order() << "\n"; } if (has_tab_width()) { indent(out, indent_level) << "tab width is " << get_tab_width() << "\n"; } if (has_glyph_scale()) { indent(out, indent_level) << "glyph scale is " << get_glyph_scale() << "\n"; } if (has_glyph_shift()) { indent(out, indent_level) << "glyph shift is " << get_glyph_shift() << "\n"; } if (has_text_scale()) { indent(out, indent_level) << "text scale is " << get_text_scale() << "\n"; } } //////////////////////////////////////////////////////////////////// // Function: TextProperties::load_default_font // Access: Private, Static // Description: This function is called once (or never), the first // time someone attempts to render a TextNode using the // default font. It should attempt to load the default // font, using the compiled-in version if it is // available, or whatever system file may be named in // Configrc. //////////////////////////////////////////////////////////////////// void TextProperties:: load_default_font() { _loaded_default_font = true; if (!text_default_font.empty()) { // First, attempt to load the user-specified filename. _default_font = FontPool::load_font(text_default_font.get_value()); if (_default_font != (TextFont *)NULL && _default_font->is_valid()) { return; } } // Then, attempt to load the compiled-in font, if we have one. #ifdef COMPILE_IN_DEFAULT_FONT #ifdef HAVE_FREETYPE // Loading the compiled-in FreeType font is relatively easy. _default_font = new DynamicTextFont((const char *)default_font_data, default_font_size, 0); // The compiled-in font seems to confuse FreeType about its winding order. ((DynamicTextFont *)_default_font.p())->set_winding_order(DynamicTextFont::WO_left); #else // The compiled-in Bam font requires creating a BamFile object to // decode it. string data((const char *)default_font_data, default_font_size); #ifdef HAVE_ZLIB // The font data is stored compressed; decompress it on-the-fly. istringstream inz(data); IDecompressStream in(&inz, false); #else // The font data is stored uncompressed, so just load it. istringstream in(data); #endif // HAVE_ZLIB BamFile bam_file; if (bam_file.open_read(in, "default font stream")) { PT(PandaNode) node = bam_file.read_node(); if (node != (PandaNode *)NULL) { _default_font = new StaticTextFont(node); } } #endif // HAVE_FREETYPE #endif // COMPILE_IN_DEFAULT_FONT }