CVSROOT: /sources/gnash Module name: gnash Changes by: Sandro Santilli <strk> 07/08/21 14:42:12
Modified files: . : ChangeLog server : edit_text_character.cpp edit_text_character.h text.h server/parser : edit_text_character_def.h testsuite/actionscript.all: TextField.as Log message: * server/text.h: documentation bits for text_glyph_record * server/edit_text_character.{cpp,h}: Add support for dynamic wordWrap setting and initial autoSize handling. * server/parser/edit_text_character_def.h: style & cleanups. * testsuite/actionscript.all/TextField.as: more successes. CVSWeb URLs: http://cvs.savannah.gnu.org/viewcvs/gnash/ChangeLog?cvsroot=gnash&r1=1.4057&r2=1.4058 http://cvs.savannah.gnu.org/viewcvs/gnash/server/edit_text_character.cpp?cvsroot=gnash&r1=1.102&r2=1.103 http://cvs.savannah.gnu.org/viewcvs/gnash/server/edit_text_character.h?cvsroot=gnash&r1=1.46&r2=1.47 http://cvs.savannah.gnu.org/viewcvs/gnash/server/text.h?cvsroot=gnash&r1=1.19&r2=1.20 http://cvs.savannah.gnu.org/viewcvs/gnash/server/parser/edit_text_character_def.h?cvsroot=gnash&r1=1.19&r2=1.20 http://cvs.savannah.gnu.org/viewcvs/gnash/testsuite/actionscript.all/TextField.as?cvsroot=gnash&r1=1.17&r2=1.18 Patches: Index: ChangeLog =================================================================== RCS file: /sources/gnash/gnash/ChangeLog,v retrieving revision 1.4057 retrieving revision 1.4058 diff -u -b -r1.4057 -r1.4058 --- ChangeLog 21 Aug 2007 14:14:35 -0000 1.4057 +++ ChangeLog 21 Aug 2007 14:42:11 -0000 1.4058 @@ -1,3 +1,11 @@ +2007-08-21 Sandro Santilli <[EMAIL PROTECTED]> + + * server/text.h: documentation bits for text_glyph_record + * server/edit_text_character.{cpp,h}: Add support for dynamic + wordWrap setting and initial autoSize handling. + * server/parser/edit_text_character_def.h: style & cleanups. + * testsuite/actionscript.all/TextField.as: more successes. + 2007-08-21 Chad Musick <[EMAIL PROTECTED]> * testsuite/misc-ming.all/DrawingApiTestRunner.cpp Index: server/edit_text_character.cpp =================================================================== RCS file: /sources/gnash/gnash/server/edit_text_character.cpp,v retrieving revision 1.102 retrieving revision 1.103 diff -u -b -r1.102 -r1.103 --- server/edit_text_character.cpp 21 Aug 2007 00:33:13 -0000 1.102 +++ server/edit_text_character.cpp 21 Aug 2007 14:42:12 -0000 1.103 @@ -17,7 +17,7 @@ // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA // -/* $Id: edit_text_character.cpp,v 1.102 2007/08/21 00:33:13 strk Exp $ */ +/* $Id: edit_text_character.cpp,v 1.103 2007/08/21 14:42:12 strk Exp $ */ #ifdef HAVE_CONFIG_H #include "config.h" @@ -82,6 +82,7 @@ static as_value textfield_textColor_getset(const fn_call& fn); static as_value textfield_embedFonts_getset(const fn_call& fn); static as_value textfield_autoSize_getset(const fn_call& fn); +static as_value textfield_wordWrap_getset(const fn_call& fn); // @@ -329,6 +330,8 @@ o.init_property("embedFonts", *getset, *getset); getset = new builtin_function(textfield_autoSize_getset); o.init_property("autoSize", *getset, *getset); + getset = new builtin_function(textfield_wordWrap_getset); + o.init_property("wordWrap", *getset, *getset); if ( target_version < 7 ) return; @@ -393,6 +396,7 @@ _borderColor(0,0,0,255), _textColor(m_def->get_text_color()), _embedFonts(m_def->getUseEmbeddedGlyphs()), + _wordWrap(m_def->do_word_wrap()), _autoSize(autoSizeNone), _bounds(m_def->get_bounds().getRange()) { @@ -962,9 +966,11 @@ //assert(extra_space >= 0.0f); if (extra_space <= 0.0f) { +#ifdef GNASH_DEBUG_TEXTFIELDS log_debug(_("TextField text doesn't fit in its boundaries: " "width %g, margin %g - nothing to align"), width, right_margin); +#endif return 0.0f; } @@ -1027,14 +1033,20 @@ } float scale = m_def->get_font_height() / 1024.0f; // the EM square is 1024 x 1024 + float fontDescent = _font->get_descent() * scale; + float fontLeading = _font->get_leading() * scale; + uint16_t fontHeight = m_def->get_font_height(); + uint16_t leftMargin = m_def->get_left_margin(); + uint16_t rightMargin = m_def->get_right_margin(); + uint16_t indent = m_def->get_indent(); text_glyph_record rec; // one to work on rec.m_style.setFont(_font); rec.m_style.m_color = getTextColor(); - rec.m_style.m_x_offset = PADDING_TWIPS + std::max(0, m_def->get_left_margin() + m_def->get_indent()); - rec.m_style.m_y_offset = PADDING_TWIPS + m_def->get_font_height() - + (_font->get_leading() - _font->get_descent()) * scale; - rec.m_style.m_text_height = m_def->get_font_height(); + rec.m_style.m_x_offset = PADDING_TWIPS + std::max(0, leftMargin + indent); + rec.m_style.m_y_offset = PADDING_TWIPS + fontHeight + + (fontLeading - fontDescent); + rec.m_style.m_text_height = fontHeight; rec.m_style.m_has_x_offset = true; rec.m_style.m_has_y_offset = true; @@ -1043,10 +1055,10 @@ // Start the bbox at the upper-left corner of the first glyph. - reset_bounding_box(x, y - _font->get_descent() * scale + m_def->get_font_height()); + reset_bounding_box(x, y - fontDescent + fontHeight); float leading = m_def->get_leading(); - leading += _font->get_leading() * scale; + leading += fontLeading * scale; int last_code = -1; // only used if _embedFonts int last_space_glyph = -1; @@ -1060,18 +1072,6 @@ const char* text = &_text[0]; while (uint32_t code = utf8::decode_next_unicode_character(&text)) { -// @@ try to truncate overflow text?? -#if 0 - if (y + _font->get_descent() * scale > m_def->height()) - { - // Text goes below the bottom of our bounding box. - rec.m_glyphs.resize(0); - break; - } -#endif // 0 - - //uint16_t code = m_text[j]; - if ( _embedFonts ) { x += _font->get_kerning_adjustment(last_code, (int) code) * scale; @@ -1080,7 +1080,7 @@ // Expand the bounding-box to the lower-right corner of each glyph as // we generate it. - m_text_bounding_box.expandTo(x, y + _font->get_descent() * scale); + m_text_bounding_box.expandTo(x, y + fontDescent); if (code == 13 || code == 10) { @@ -1096,9 +1096,8 @@ align_line(m_def->get_alignment(), last_line_start_record, x); // new paragraphs get the indent. - x = std::max(0, m_def->get_left_margin() + m_def->get_indent()) + - PADDING_TWIPS; - y += m_def->get_font_height() + leading; + x = std::max(0, leftMargin + indent) + PADDING_TWIPS; + y += fontHeight + leading; // Start a new record on the next line. rec.m_glyphs.resize(0); @@ -1106,7 +1105,7 @@ rec.m_style.m_color = getTextColor(); rec.m_style.m_x_offset = x; rec.m_style.m_y_offset = y; - rec.m_style.m_text_height = m_def->get_font_height(); + rec.m_style.m_text_height = fontHeight; rec.m_style.m_has_x_offset = true; rec.m_style.m_has_y_offset = true; @@ -1248,31 +1247,62 @@ after_x_advance: float width = _bounds.width(); // m_def->width() - float right_margin = m_def->get_right_margin(); + //float right_margin = m_def->get_right_margin(); - if (x >= width - right_margin - PADDING_TWIPS) + if (x >= width - rightMargin - PADDING_TWIPS) { + //log_debug("Text in character %s exceeds margins", getTarget().c_str()); // Whoops, we just exceeded the box width. // Do word-wrap if requested to do so. - // TODO: don't query the definition about wordWrap, - // we should have a wordWrap getter/setter instead ! - // Also, we should check autoSize (getAutoSize) and - // behave accordingly - // - if ( ! m_def->do_word_wrap() ) + if ( ! doWordWrap() ) + { + //log_debug(" No word wrapping"); + AutoSizeValue autoSize = getAutoSize(); + if ( autoSize != autoSizeNone ) { + static bool warned = false; + if ( ! warned ) { + log_debug(_("TextField.autoSize != 'none' TESTING")); + warned = true; + } + } + else + { + //log_debug(" autoSize=NONE!"); + // truncate long line, but keep expanding text box bool newlinefound = false; while ( (code = utf8::decode_next_unicode_character(&text)) ) { + if ( _embedFonts ) + { + x += _font->get_kerning_adjustment(last_code, (int) code) * scale; + last_code = static_cast<int>(code); + } + // Expand the bounding-box to the lower-right corner of each glyph, + // even if we don't display it + m_text_bounding_box.expandTo(x, y + fontDescent); +#ifdef GNASH_DEBUG_TEXTFIELDS + std::stringstream ss; + ss << "Text bbox expanded to " << m_text_bounding_box << "(width: " << m_text_bounding_box.width() << ")"; + log_debug("%s", ss.str().c_str()); +#endif + if (code == 13 || code == 10) { newlinefound = true; break; } + + int index = _font->get_glyph_index((uint16_t) code, _embedFonts); + x += scale * _font->get_advance(index, _embedFonts); + } if ( ! newlinefound ) break; } + } + else // do word wrap + { // Insert newline. @@ -1282,6 +1312,7 @@ x = m_def->get_left_margin() + PADDING_TWIPS; y += m_def->get_font_height() + leading; + // Start a new record on the next line. rec.m_glyphs.resize(0); rec.m_style.setFont(_font); @@ -1292,6 +1323,8 @@ rec.m_style.m_has_x_offset = true; rec.m_style.m_has_y_offset = true; + // TODO : what if m_text_glyph_records is empty ? Is it possible ? + assert(!m_text_glyph_records.empty()); text_glyph_record& last_line = m_text_glyph_records.back(); if (last_space_glyph == -1) { @@ -1325,6 +1358,7 @@ last_space_glyph = -1; last_line_start_record = m_text_glyph_records.size(); } + } if (m_cursor > character_idx) { @@ -1336,13 +1370,23 @@ // TODO: HTML markup } + // Expand bounding box to include the whole text (if autoSize) + if ( _autoSize != autoSizeNone ) + { + _bounds.expandTo(x+PADDING_TWIPS, y); + } + else + { + _bounds.expandTo(_bounds.getMaxX(), y); + } + // Add this line to our output. m_text_glyph_records.push_back(rec); float extra_space = align_line(m_def->get_alignment(), last_line_start_record, x); m_xcursor += static_cast<int>(extra_space); - m_ycursor -= m_def->get_font_height() + (_font->get_leading() - _font->get_descent()) * scale; + m_ycursor -= fontHeight + (fontLeading - fontDescent); } void @@ -1574,6 +1618,17 @@ } } +void +edit_text_character::setWordWrap(bool on) +{ + if ( _wordWrap != on ) + { + set_invalidated(); + _wordWrap=on; + format_text(); + } +} + cxform edit_text_character::get_world_cxform() const { @@ -1704,6 +1759,23 @@ } static as_value +textfield_wordWrap_getset(const fn_call& fn) +{ + boost::intrusive_ptr<edit_text_character> ptr = ensureType<edit_text_character>(fn.this_ptr); + + if ( fn.nargs == 0 ) // getter + { + return as_value(ptr->doWordWrap()); + } + else // setter + { + ptr->setWordWrap( fn.arg(0).to_bool() ); + } + + return as_value(); +} + +static as_value textfield_autoSize_getset(const fn_call& fn) { boost::intrusive_ptr<edit_text_character> ptr = ensureType<edit_text_character>(fn.this_ptr); @@ -1782,13 +1854,6 @@ { if ( val == _autoSize ) return; - static bool warned = false; - if ( ! warned ) { - log_unimpl(_("TextField.autoSize unused")); - warned = true; - } - - set_invalidated(); _autoSize = val; Index: server/edit_text_character.h =================================================================== RCS file: /sources/gnash/gnash/server/edit_text_character.h,v retrieving revision 1.46 retrieving revision 1.47 diff -u -b -r1.46 -r1.47 --- server/edit_text_character.h 21 Aug 2007 00:33:13 -0000 1.46 +++ server/edit_text_character.h 21 Aug 2007 14:42:12 -0000 1.47 @@ -206,6 +206,24 @@ /// static const char* autoSizeValueName(AutoSizeValue val); + /// \brief + /// Return true if text should continue to next available line + /// when hitting end of bounding box. + /// + bool doWordWrap() const { + return _wordWrap; + } + + /// Set wordWrap parameter + // + /// @param on + /// If true text hitting bounding box limits will continue + /// to next line. + /// If false, either text will be truncated or bounding box + /// expanded, depending on autoSize (see getAutoSize) + /// + void setWordWrap(bool on); + private: /// Return true if HTML text is allowed @@ -313,6 +331,8 @@ bool _embedFonts; + bool _wordWrap; + AutoSizeValue _autoSize; /// Area in which the text is drawn. Index: server/text.h =================================================================== RCS file: /sources/gnash/gnash/server/text.h,v retrieving revision 1.19 retrieving revision 1.20 diff -u -b -r1.19 -r1.20 --- server/text.h 18 Aug 2007 08:05:00 -0000 1.19 +++ server/text.h 21 Aug 2007 14:42:12 -0000 1.20 @@ -113,8 +113,10 @@ }; - // Helper class. - // @@ text_character_def friend ? + /// A vector of glyphs sharing the same text_style + // + /// For each glyph, this class stores index and advance values + /// class text_glyph_record { public: Index: server/parser/edit_text_character_def.h =================================================================== RCS file: /sources/gnash/gnash/server/parser/edit_text_character_def.h,v retrieving revision 1.19 retrieving revision 1.20 diff -u -b -r1.19 -r1.20 --- server/parser/edit_text_character_def.h 30 Jul 2007 18:38:15 -0000 1.19 +++ server/parser/edit_text_character_def.h 21 Aug 2007 14:42:12 -0000 1.20 @@ -231,7 +231,8 @@ return m_no_select; } - const rect& get_bound() const { + const rect& get_bound() const + { // I know it's stupid to have an alias that's nearly the same name but // get_bound() is required by the base class and get_bounds() was already // there. Should be fixed (remove get_bounds). @@ -338,15 +339,12 @@ /// extra space between box's left border and text (in twips) uint16_t m_left_margin; - //float m_left_margin; /// extra space between box's right border and text (in twips) uint16_t m_right_margin; - //float m_right_margin; /// how much to indent the first line of multiline text (in twips) uint16_t m_indent; - //float m_indent; /// \brief /// Extra space between lines Index: testsuite/actionscript.all/TextField.as =================================================================== RCS file: /sources/gnash/gnash/testsuite/actionscript.all/TextField.as,v retrieving revision 1.17 retrieving revision 1.18 diff -u -b -r1.17 -r1.18 --- testsuite/actionscript.all/TextField.as 16 Aug 2007 10:31:51 -0000 1.17 +++ testsuite/actionscript.all/TextField.as 21 Aug 2007 14:42:12 -0000 1.18 @@ -19,7 +19,7 @@ // compile this test case with Ming makeswf, and then // execute it like this gnash -1 -r 0 -v out.swf -rcsid="$Id: TextField.as,v 1.17 2007/08/16 10:31:51 strk Exp $"; +rcsid="$Id: TextField.as,v 1.18 2007/08/21 14:42:12 strk Exp $"; #include "check.as" @@ -63,7 +63,7 @@ check( !TextField.prototype.hasOwnProperty('textWidth') ); check( !TextField.prototype.hasOwnProperty('type') ); xcheck( !TextField.prototype.hasOwnProperty('variable') ); -check( !TextField.prototype.hasOwnProperty('wordWrap') ); +xcheck( !TextField.prototype.hasOwnProperty('wordWrap') ); // this is a static method check_equals(typeof(TextField.getFontList), 'function'); @@ -132,7 +132,7 @@ xcheck( TextField.prototype.hasOwnProperty('textWidth') ); xcheck( TextField.prototype.hasOwnProperty('type') ); check( TextField.prototype.hasOwnProperty('variable') ); -xcheck( TextField.prototype.hasOwnProperty('wordWrap') ); +check( TextField.prototype.hasOwnProperty('wordWrap') ); // Check TextField._alpha @@ -543,9 +543,10 @@ // Check TextField.wordWrap (should text wrap when bbox limit is hit?) -xcheck_equals(typeof(tf.wordWrap), 'boolean'); +check_equals(typeof(tf.wordWrap), 'boolean'); check( ! tf.hasOwnProperty('wordWrap') ); -xcheck_equals(tf.wordWrap, false); +check_equals(tf.wordWrap, false); +// TODO: check what can be assigned to wordWrap and what not... // Check TextField._x @@ -623,13 +624,13 @@ check_equals(tf._width, 10); origTextWidth = tf.textWidth; tf.autoSize = 'center'; -xcheck(tf._width > 10); +check(tf._width > 10); check_equals(origTextWidth, tf.textWidth); // textWidth isn't influenced by autoSize tf.autoSize = 'none'; tf.wordWrap = true; +check_equals(origTextWidth, tf.textWidth); tf._width = 10; -// Gnash ignores assigments to _width (should change TextField rendering area bounds instead) check_equals(tf._width, 10); -check_equals(origTextWidth, tf.textWidth); // textWidth isn't influenced by wordWrap +xcheck_equals(origTextWidth, tf.textWidth); // textWidth isn't influenced by wordWrap #endif // OUTPUT_VERSION > 5 _______________________________________________ Gnash-commit mailing list Gnash-commit@gnu.org http://lists.gnu.org/mailman/listinfo/gnash-commit