[webkit-changes] cvs commit: WebCore/khtml/rendering bidi.cpp break_lines.cpp break_lines.h render_text.cpp

Darin darin at opensource.apple.com
Sun Sep 4 00:42:32 PDT 2005


darin       05/09/04 00:42:32

  Modified:    .        ChangeLog
               khtml/rendering bidi.cpp break_lines.cpp break_lines.h
                        render_text.cpp
  Log:
          Reviewed and landed by Darin.
  
          - fixed <rdar://problem/3698926> so slow it feels like a hang calling UCFindTextBreak() tons of times at forum.presence-pc.com (4789)
            also http://bugzilla.opendarwin.org/show_bug.cgi?id=4789
  
          No test cases added because this is a performance fix. Existing test cases continue to work.
  
          * khtml/rendering/break_lines.h: Declare the new nextBreakablePosition and also define a new
          isBreakable function that adds an in/out "next breakable position" parameter.
          * khtml/rendering/break_lines.cpp: (khtml::nextBreakablePosition): Replaced the old isBreakable
          with this function.
  
          * khtml/rendering/bidi.cpp: (khtml::RenderBlock::findNextLineBreak): Call the new version of
          isBreakable that uses the previously-found "next breakable" position until we pass it rather
          than analyzing each position separately to see if we can break there.
  
          * khtml/rendering/render_text.cpp: (RenderText::calcMinMaxWidth): Call the new isBreakable, and
          also do some things to streamline and perhaps speed up: a) use an index withing the string rather
          than within the word when finding a word break, b) use a cached copy of the string base pointer
          and the string length rather than repeatedly dereferencing str, c) use a cached copy of the current
          character rather than repeatedly fetching it. Darin also changed one confusing use of ? : to just
          use && instead.
  
  Revision  Changes    Path
  1.84      +25 -0     WebCore/ChangeLog
  
  Index: ChangeLog
  ===================================================================
  RCS file: /cvs/root/WebCore/ChangeLog,v
  retrieving revision 1.83
  retrieving revision 1.84
  diff -u -r1.83 -r1.84
  --- ChangeLog	3 Sep 2005 23:09:57 -0000	1.83
  +++ ChangeLog	4 Sep 2005 07:42:30 -0000	1.84
  @@ -1,3 +1,28 @@
  +2005-09-04  Mitz Pettel  <opendarwin.org at mitzpettel.com>
  +
  +        Reviewed and landed by Darin.
  +
  +        - fixed <rdar://problem/3698926> so slow it feels like a hang calling UCFindTextBreak() tons of times at forum.presence-pc.com (4789)
  +          also http://bugzilla.opendarwin.org/show_bug.cgi?id=4789
  +
  +        No test cases added because this is a performance fix. Existing test cases continue to work.
  +
  +        * khtml/rendering/break_lines.h: Declare the new nextBreakablePosition and also define a new
  +        isBreakable function that adds an in/out "next breakable position" parameter.
  +        * khtml/rendering/break_lines.cpp: (khtml::nextBreakablePosition): Replaced the old isBreakable
  +        with this function.
  +
  +        * khtml/rendering/bidi.cpp: (khtml::RenderBlock::findNextLineBreak): Call the new version of
  +        isBreakable that uses the previously-found "next breakable" position until we pass it rather
  +        than analyzing each position separately to see if we can break there.
  +
  +        * khtml/rendering/render_text.cpp: (RenderText::calcMinMaxWidth): Call the new isBreakable, and
  +        also do some things to streamline and perhaps speed up: a) use an index withing the string rather
  +        than within the word when finding a word break, b) use a cached copy of the string base pointer
  +        and the string length rather than repeatedly dereferencing str, c) use a cached copy of the current
  +        character rather than repeatedly fetching it. Darin also changed one confusing use of ? : to just
  +        use && instead.
  +
   2005-09-03  David Hyatt  <hyatt at apple.com>
   
   	This patch substantially reworks how mouse clicking and double clicking work in the DOM.
  
  
  
  1.141     +4 -2      WebCore/khtml/rendering/bidi.cpp
  
  Index: bidi.cpp
  ===================================================================
  RCS file: /cvs/root/WebCore/khtml/rendering/bidi.cpp,v
  retrieving revision 1.140
  retrieving revision 1.141
  diff -u -r1.140 -r1.141
  --- bidi.cpp	15 Aug 2005 23:31:16 -0000	1.140
  +++ bidi.cpp	4 Sep 2005 07:42:31 -0000	1.141
  @@ -2074,13 +2074,14 @@
               bool appliedEndWidth = false;
   
               int wrapW = tmpW;
  +            int nextBreakable = -1;
   
               while(len) {
                   bool previousCharacterIsSpace = currentCharacterIsSpace;
                   bool previousCharacterIsWS = currentCharacterIsWS;
                   const QChar c = str[pos];
                   currentCharacterIsSpace = c == ' ' || c == '\t' || (!isPre && (c == '\n'));
  -                
  +
                   if (isPre || !currentCharacterIsSpace)
                       isLineEmpty = false;
                   
  @@ -2118,7 +2119,8 @@
   
                   if (breakWords)
                       wrapW += t->width(pos, 1, f, w+wrapW);
  -                if (c == '\n' || (!isPre && isBreakable(str, pos, strlen, breakNBSP)) || (breakWords && (w + wrapW > width))) {
  +
  +                if (c == '\n' || (!isPre && isBreakable(str, pos, strlen, nextBreakable, breakNBSP)) || (breakWords && (w + wrapW > width))) {
                       if (ignoringSpaces) {
                           if (!currentCharacterIsSpace) {
                               // Stop ignoring spaces and begin at this
  
  
  
  1.24      +54 -110   WebCore/khtml/rendering/break_lines.cpp
  
  Index: break_lines.cpp
  ===================================================================
  RCS file: /cvs/root/WebCore/khtml/rendering/break_lines.cpp,v
  retrieving revision 1.23
  retrieving revision 1.24
  diff -u -r1.23 -r1.24
  --- break_lines.cpp	27 Aug 2005 18:55:00 -0000	1.23
  +++ break_lines.cpp	4 Sep 2005 07:42:31 -0000	1.24
  @@ -1,120 +1,64 @@
  -#include <break_lines.h>
  -
  -#ifdef HAVE_THAI_BREAKS
  -#include "ThBreakIterator.h"
  +/*
  + * This file is part of the DOM implementation for KDE.
  + *
  + * Copyright (C) 2005 Apple Computer, Inc.
  + *
  + * This library is free software; you can redistribute it and/or
  + * modify it under the terms of the GNU Library General Public
  + * License as published by the Free Software Foundation; either
  + * version 2 of the License, or (at your option) any later version.
  + *
  + * This library is distributed in the hope that it will be useful,
  + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  + * Library General Public License for more details.
  + *
  + * You should have received a copy of the GNU Library General Public License
  + * along with this library; see the file COPYING.LIB.  If not, write to
  + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
  + * Boston, MA 02111-1307, USA.
  + *
  + */
   
  -static const QChar *cached = 0;
  -static QCString *cachedString = 0;
  -static ThBreakIterator *thaiIt = 0;
  -#endif
  +#include "break_lines.h"
   
  -#if APPLE_CHANGES
   #include <CoreServices/CoreServices.h>
  -#endif
  -
  -void cleanupLineBreaker()
  -{
  -#ifdef HAVE_THAI_BREAKS
  -    if ( cachedString )
  -	delete cachedString;
  -    if ( thaiIt )
  -	delete thaiIt;
  -    cached = 0;
  -#endif
  -}
   
   namespace khtml {
  -/*
  -  This function returns true, if the string can bre broken before the 
  -  character at position pos in the string s with length len
  -*/
  -bool isBreakable(const QChar *s, int pos, int len, bool breakNBSP)
  +
  +int nextBreakablePosition(const QChar *str, int pos, int len, bool breakNBSP)
   {
  -#if !APPLE_CHANGES
  -    const QChar *c = s+pos;
  -    unsigned short ch = c->unicode();
  -    if ( ch > 0xff ) {
  -	// not latin1, need to do more sophisticated checks for asian fonts
  -	unsigned char row = c->row();
  -	if ( row == 0x0e ) {
  -	    // 0e00 - 0e7f == Thai
  -	    if ( c->cell() < 0x80 ) {
  -#ifdef HAVE_THAI_BREAKS
  -		// check for thai
  -		if( s != cached ) {
  -		    // build up string of thai chars
  -		    QTextCodec *thaiCodec = QTextCodec::codecForMib(2259);
  -		    if ( !cachedString )
  -			cachedString = new QCString;
  -		    if ( !thaiIt )
  -			thaiIt = ThBreakIterator::createWordInstance(); 
  -		    *cachedString = thaiCodec->fromUnicode( QConstString( (QChar *)s, len ).qstring() );
  -		}
  -		thaiIt->setText((tchar *)cachedString->data());
  -		for(int i = thaiIt->first(); i != thaiIt->DONE; i = thaiIt->next() ) {
  -		    if( i == pos )
  -			return true;
  -		    if( i > pos )
  -			return false;
  -		}
  -		return false;
  -#else
  -		// if we don't have a thai line breaking lib, allow
  -		// breaks everywhere except directly before punctuation.
  -		return true;
  -#endif
  -	    } else 
  -		return false;
  -	}
  -	if ( row > 0x2d && row < 0xfb || row == 0x11 )
  -	    // asian line breaking. Everywhere allowed except directly
  -	    // in front of a punctuation character.
  -	    return true;
  -	else // no asian font
  -	    return c->isSpace();
  -    } else {
  -	if ( ch == ' ' || ch == '\t' || ch == '\n' )
  -	    return true;
  -    }
  -    return false;
  -#else
  -    OSStatus status = 0, findStatus = 0;
  +    OSStatus status = 0, findStatus = -1;
       static TextBreakLocatorRef breakLocator = 0;
  -    UniCharArrayOffset end;
  -    const QChar *c = s+pos;
  -    unsigned short ch = c->unicode();
  -
  -    // Newlines and spaces are always breakable, as are non-breaking spaces when breakNBSP is true.
  -    // FIXME: Tiger is not allowing breaks on spaces after bullet characters like &#183;.  We don't know
  -    // at the moment whether this behavior is correct or not.  Since Tiger is also not allowing breaks on spaces
  -    // after hyphen-like characters, this does not seem ideal for the Web.  Therefore for now we override space
  -    // characters up front and bypass the Unicode line breaking routines.
  -    if (ch == ' ' || ch == '\n' || ch == '\t' || (breakNBSP && ch == 0xa0))
  -        return true;
  -
  -    // If current character, or the previous character aren't simple latin1 then
  -    // use the UC line break locator.  UCFindTextBreak will report false if we
  -    // have a sequence of 0xa0 0x20 (nbsp, sp), so we explicity check for that
  -    // case.
  -    unsigned short lastCh = pos > 0 ? (s+pos-1)->unicode() : 0;
  -    if ((ch > 0x7f && ch != 0xa0) || (lastCh > 0x7f && lastCh != 0xa0)) {
  -        if (!breakLocator)
  -            status = UCCreateTextBreakLocator(NULL, 0, kUCTextBreakLineMask, &breakLocator);
  -        if (status == 0)
  -            findStatus = UCFindTextBreak(breakLocator, kUCTextBreakLineMask, 0, (const UniChar *)s, len, pos, &end);
  -        if (findStatus == 0)
  -            return (int)end == pos && !(lastCh == ' ' || lastCh == '\n' || lastCh == '\t' || (breakNBSP && lastCh == 0xa0));
  -
  -        // If Carbon fails, fail back on simple white space detection.
  -    }
  +    int nextUCBreak = -1;
  +    int i;
  +    unsigned short ch, lastCh;
       
  -    // Match WinIE's breaking strategy, which is to always allow breaks after hyphens and question marks.
  -    if (lastCh == '-' || lastCh == '?')
  -        return true;
  -
  -    // No other ascii chars are breakable.
  -    return false;
  -#endif    
  +    lastCh = pos > 0 ? str[pos - 1].unicode() : 0;
  +    for (i = pos; i < len; i++) {
  +        ch = str[i].unicode();
  +        if (ch == ' ' || ch == '\n' || ch == '\t' || (breakNBSP && ch == 0xa0))
  +            break;
  +        // Match WinIE's breaking strategy, which is to always allow breaks after hyphens and question marks.
  +        if (lastCh == '-' || lastCh == '?')
  +            break;
  +        // If current character, or the previous character aren't simple latin1 then
  +        // use the UC line break locator.  UCFindTextBreak will report false if we
  +        // have a sequence of 0xa0 0x20 (nbsp, sp), so we explicity check for that
  +        // case.
  +        if ((ch > 0x7f && ch != 0xa0) || (lastCh > 0x7f && lastCh != 0xa0)) {
  +            if (nextUCBreak < i) {
  +                if (!breakLocator)
  +                    status = UCCreateTextBreakLocator(NULL, 0, kUCTextBreakLineMask, &breakLocator);
  +                if (status == 0)
  +                    findStatus = UCFindTextBreak(breakLocator, kUCTextBreakLineMask, 0, (const UniChar *)str, len, i, (UniCharArrayOffset *)&nextUCBreak);
  +            }
  +            if (findStatus == 0 && i == nextUCBreak && !(lastCh == ' ' || lastCh == '\n' || lastCh == '\t' || (breakNBSP && lastCh == 0xa0)))
  +                break;
  +        }
  +        lastCh = ch;
  +    }
  +    return i;
   }
   
  -};
  +};
  \ No newline at end of file
  
  
  
  1.3       +34 -3     WebCore/khtml/rendering/break_lines.h
  
  Index: break_lines.h
  ===================================================================
  RCS file: /cvs/root/WebCore/khtml/rendering/break_lines.h,v
  retrieving revision 1.2
  retrieving revision 1.3
  diff -u -r1.2 -r1.3
  --- break_lines.h	5 Oct 2004 20:05:38 -0000	1.2
  +++ break_lines.h	4 Sep 2005 07:42:31 -0000	1.3
  @@ -1,5 +1,36 @@
  -#include <qstring.h>
  +/*
  + * This file is part of the DOM implementation for KDE.
  + *
  + * Copyright (C) 2005 Apple Computer, Inc.
  + *
  + * This library is free software; you can redistribute it and/or
  + * modify it under the terms of the GNU Library General Public
  + * License as published by the Free Software Foundation; either
  + * version 2 of the License, or (at your option) any later version.
  + *
  + * This library is distributed in the hope that it will be useful,
  + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  + * Library General Public License for more details.
  + *
  + * You should have received a copy of the GNU Library General Public License
  + * along with this library; see the file COPYING.LIB.  If not, write to
  + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
  + * Boston, MA 02111-1307, USA.
  + *
  + */
  +
  +class QChar;
   
   namespace khtml {
  -    bool isBreakable(const QChar *str, int pos, int len, bool breakNBSP = false);
  -};
  +
  +    int nextBreakablePosition(const QChar *str, int pos, int len, bool breakNBSP = false);
  +
  +    inline bool isBreakable(const QChar *str, int pos, int len, int &nextBreakable, bool breakNBSP = false)
  +    {
  +        if (pos > nextBreakable)
  +            nextBreakable = nextBreakablePosition(str, pos, len, breakNBSP);
  +        return pos == nextBreakable;
  +    }
  +
  +}
  
  
  
  1.196     +19 -13    WebCore/khtml/rendering/render_text.cpp
  
  Index: render_text.cpp
  ===================================================================
  RCS file: /cvs/root/WebCore/khtml/rendering/render_text.cpp,v
  retrieving revision 1.195
  retrieving revision 1.196
  diff -u -r1.195 -r1.196
  --- render_text.cpp	1 Sep 2005 18:03:33 -0000	1.195
  +++ render_text.cpp	4 Sep 2005 07:42:31 -0000	1.196
  @@ -1308,15 +1308,17 @@
       const Font *f = htmlFont( false );
       int wordSpacing = style()->wordSpacing();
       int len = str->l;
  +    QChar *txt = str->s;
       bool needsWordSpacing = false;
       bool ignoringSpaces = false;
       bool isSpace = false;
       bool isPre = style()->whiteSpace() == PRE;
       bool firstWord = true;
       bool firstLine = true;
  +    int nextBreakable = -1;
       for(int i = 0; i < len; i++)
       {
  -        const QChar c = str->s[i];
  +        QChar c = txt[i];
           
           bool previousCharacterIsSpace = isSpace;
           
  @@ -1354,12 +1356,18 @@
               continue;
           }
           
  -        int wordlen = 0;
  -        while (i+wordlen < len && str->s[i+wordlen] != '\n' && str->s[i+wordlen] != ' ' && str->s[i+wordlen] != '\t' &&
  -               (i+wordlen == 0 || str->s[i+wordlen].unicode() != SOFT_HYPHEN) && // Skip soft hyphens
  -               (wordlen == 0 || !isBreakable( str->s, i+wordlen, str->l)))
  -            wordlen++;
  +        bool hasBreak = isBreakable(txt, i, len, nextBreakable);
  +        int j = i;
  +        while (c != '\n' && c != ' ' && c != '\t' && (j == 0 || c.unicode() != SOFT_HYPHEN)) {
  +            j++;
  +            if (j == len)
  +                break;
  +            c = txt[j];
  +            if (isBreakable(txt, j, len, nextBreakable))
  +                break;
  +        }
               
  +        int wordlen = j - i;
           if (wordlen)
           {
   #if !APPLE_CHANGES
  @@ -1370,15 +1378,14 @@
               currMinWidth += w;
               currMaxWidth += w;
               
  -            bool isBreakableCharSpace = (i+wordlen < len) ? ((!isPre && (str->s[i+wordlen] == '\n' || str->s[i+wordlen] == '\t')) || 
  -                                                             str->s[i+wordlen] == ' ') : false;
  +            bool isBreakableCharSpace = (j < len) && ((!isPre && (c == '\n' || c == '\t')) || c == ' ');
   
  -            if (i+wordlen < len && style()->whiteSpace() == NORMAL)
  +            if (j < len && style()->whiteSpace() == NORMAL)
                   m_hasBreakableChar = true;
               
               // Add in wordSpacing to our currMaxWidth, but not if this is the last word on a line or the
               // last word in the run.
  -            if (wordSpacing && isBreakableCharSpace && !containsOnlyWhitespace(i+wordlen, len-(i+wordlen)))
  +            if (wordSpacing && isBreakableCharSpace && !containsOnlyWhitespace(j, len-j))
                   currMaxWidth += wordSpacing;
   
               if (firstWord) {
  @@ -1386,7 +1393,6 @@
                   // If the first character in the run is breakable, then we consider ourselves to have a beginning
                   // minimum width of 0, since a break could occur right before our run starts, preventing us from ever
                   // being appended to a previous text run when considering the total minimum width of the containing block.
  -                bool hasBreak = isBreakable(str->s, i, str->l);
                   if (hasBreak)
                       m_hasBreakableChar = true;
                   m_beginMinWidth = hasBreak ? 0 : w;
  @@ -1420,8 +1426,8 @@
               }
               else
               {
  -                currMaxWidth += f->width(str->s, str->l, i + wordlen, 1, tabWidth(), leadWidth + currMaxWidth);
  -                needsWordSpacing = isSpace && !previousCharacterIsSpace && i + wordlen == len-1;
  +                currMaxWidth += f->width(txt, len, i, 1, tabWidth(), leadWidth + currMaxWidth);
  +                needsWordSpacing = isSpace && !previousCharacterIsSpace && i == len-1;
               }
           }
       }
  
  
  



More information about the webkit-changes mailing list