[webkit-changes] cvs commit: WebKit/WebCoreSupport.subproj WebTextRenderer.h WebTextRenderer.m

Darin darin at opensource.apple.com
Wed Oct 19 23:02:39 PDT 2005


darin       05/10/19 23:02:39

  Modified:    .        ChangeLog
               khtml/html htmltokenizer.cpp
               khtml/rendering font.cpp font.h render_text.cpp
               kwq      KWQComboBox.mm KWQFontMetrics.h KWQFontMetrics.mm
                        KWQLineEdit.mm KWQListBox.mm KWQPainter.mm
                        WebCoreTextRenderer.h
               .        ChangeLog
               Misc.subproj WebKitNSStringExtras.m WebStringTruncator.m
               WebCoreSupport.subproj WebTextRenderer.h WebTextRenderer.m
  Log:
  WebCore:
  
          Reviewed by Maciej.
  
          - optimizations for a total of about 1% speed-up on PLT
  
          * khtml/html/htmltokenizer.cpp:
          (khtml::fixUpChar): Changed to be more inlinable.
          (khtml::HTMLTokenizer::processListing): Simplified the skipLF handling.
          (khtml::HTMLTokenizer::parseSpecial): Changed to call the new fixUpChar.
          (khtml::HTMLTokenizer::parseText): Simplified the skipLF handling and
          changed to call the new fixUpChar.
          (khtml::HTMLTokenizer::parseEntity): Changed to call the new fixUpChar.
          (khtml::HTMLTokenizer::parseTag): Changed to call the new fixUpChar.
          (khtml::HTMLTokenizer::write): Changed to call the new fixUpChar.
  
          * khtml/rendering/font.h: Removed the floatCharacterWidths function,
          since it's never needed. Made some more functions inline.
          * khtml/rendering/font.cpp: Removed lots of stuff that was only for the
          !APPLE_CHANGES case.
  
          * kwq/KWQFontMetrics.h: Removed the single-character width overloads, charWidth,
          and floatCharacterWidths.
          * kwq/KWQFontMetrics.mm:
          (QFontMetrics::width): Use lroundf instead of the ROUND_TO_INT macro.
          (QFontMetrics::floatWidth): Removed the bogus unneeded call to the ROUND_TO_INT macro.
  
          * khtml/rendering/render_text.cpp:
          (RenderText::cacheWidths): Use floatWidth instead of floatCharacterWidths.
  
          * kwq/KWQComboBox.mm: (QComboBox::sizeHint): Update since the floatWidthForRun
          method no longer takes a widths parameter.
          * kwq/KWQLineEdit.mm: (QLineEdit::sizeForCharacterWidth): Ditto.
          * kwq/KWQListBox.mm:
          (QListBox::sizeForNumberOfLines): Ditto.
          (-[KWQTableView drawRow:clipRect:]): Ditto.
          * kwq/KWQPainter.mm: (QPainter::drawText): Ditto. Also use lroundf instead of the
          ROUND_TO_INT macro.
  
          * kwq/WebCoreTextRenderer.h: Removed the ROUND_TO_INT macro. Changed to use bool
          instead of bit fields. Removed the widths parameter from the floatWidthForRun method.
  
  WebKit:
  
          Reviewed by Maciej.
  
          - optimizations for a total of about 1% speed-up on PLT
  
          * WebCoreSupport.subproj/WebTextRenderer.h: Updated to use bool instead of BOOL,
          since BOOL is a signed char (which is not so efficient, at least on PPC).
          * WebCoreSupport.subproj/WebTextRenderer.m:
          (isSpace): Changed BOOL to bool and UniChar to UChar32. This actually fixes a
          potential bug when the passed-in character is a non-BMP character (> FFFF).
          (isRoundingHackCharacter): Ditto.
          (widthForGlyph): Merged getUncachedWidth, widthFromMap, and widthForGlyph into
          one function. Marked it inline. Changed to include syntheticBoldOffset in the
          cached widths to save an add in the cached case. Instead of the special constant
          UNINITIALIZED_GLYPH_WIDTH, just check for a width >= 0. This allows us to use
          a negative number or NAN for the uninitialized width value -- I chose NAN.
          (overrideLayoutOperation): Use bool instead of Boolean in one place.
          (-[WebTextRenderer initWithFont:]): Use lroundf instead of ROUND_TO_INT.
          (-[WebTextRenderer floatWidthForRun:style:]): Put the code to choose the ATSU
          vs. CG code path back in here, because there are no callers inside the class
          that need to call both.
          (-[WebTextRenderer drawLineForCharacters:yOffset:width:color:thickness:]):
          Use bool instead of BOOL.
          (+[WebTextRenderer setAlwaysUseATSU:]): Ditto.
          (fontContainsString): Ditto.
          (-[WebTextRenderer computeWidthForSpace]): Ditto. Also use roundf instead of
          using ROUND_TO_INT.
          (-[WebTextRenderer setUpFont]): Use bool instead of BOOL.
          (drawGlyphs): Ditto.
          (-[WebTextRenderer CG_drawHighlightForRun:style:geometry:]): Restructure the
          code so it can use the new advanceWidthIterator function instead of the old
          widthForNextCharacter function.
          (-[WebTextRenderer CG_drawRun:style:geometry:]): Use malloc instead of calloc
          since we don't need initialization. Call CG_floatWidthForRun instead of
          floatWidthForRun -- no need to re-check whether to use the CG or ATSU code path.
          Removed code to handle a renderer of 0 since we no longer generate that in
          the renderers array in advanceWidthIterator.
          (CG_floatWidthForRun): Changed to call the new advanceWidthIterator instead of
          the old widthForNextCharacter.
          (-[WebTextRenderer extendCharacterToGlyphMapToInclude:]): Use malloc instead of
          calloc and explicitly initialize the one field that needs it. Fixed a potential
          storage leak by adding a call to WKClearGlyphVector. Initialize the renderers
          to self instead of to 0.
          (-[WebTextRenderer extendGlyphToWidthMapToInclude:]): Initialize the widths to
          NAN instead of UNINITIALIZED_GLYPH_WIDTH.
          (addDirectionalOverride): Fixed bug where the first and last character in the buffer
          could be uninitialized and where characters before and after the direction override
          could be incorrect.
          (-[WebTextRenderer ATSU_drawRun:style:geometry:]): Use bool instead of BOOL.
          (-[WebTextRenderer ATSU_pointToOffset:style:position:reversed:includePartialGlyphs:]):
          Ditto.
          (advanceWidthIteratorOneCharacter): Added new helper function for CG_pointToOffset.
          (-[WebTextRenderer CG_pointToOffset:style:position:reversed:includePartialGlyphs:]):
          Reimplemented to use advanceWidthIteratorOneCharacter instead of widthForNextCharacter.
          Also call CG_floatWidthForRun instead of floatWidthForRun since we don't need to
          reconsider whether to use CG or ATSU.
          (glyphForCharacter): Removed the map parameter and changed the renderer parameter to
          be an in-out one. Removed uneeded special case for when map is 0 and always get the
          renderer from the map. Also call extendCharacterToGlyphMapToInclude in here instead of
          making that the caller's responsibility.
          (initializeWidthIterator): Renamed to make the name shorter (removed "Character").
          Streamlned common cases like "no padding" and removed some unneeded casts. Changed to
          use advanceWidthIterator to compute width fo the first part of the run.
          (normalizeVoicingMarks): Factored this out into a separate function, since it's not part
          of the common case.
          (advanceWidthIterator): Changed widthForNextCharacter to this, eliminating per-character
          function overhead for iterating past a few characters. Merged the handling of surrogate
          pairs and of voicing marks so that we typically only have to do one "if" to rule out both.
          Merged the mirroring for RTL and uppercasing for small caps into a single boolean so that
          we only need one "if" to rule out both. Call the new glyphForCharacter. Check for the
          character '\t' first since that's cheaper than looking at tabWidth. Check tabWidth for 0
          first so that we don't have to convert it to floating point when not using it. Changed
          the special case for spaces to first check width, so that we don't bother with the rest
          of the code for glyphs not the same width as spaces. Fixed substitution code to call
          CG_floatWidthForRun -- no need to reconsider whether to use CG or ATSU. Also changed to
          properly get width from the result of that function. Merged the handling of letter spacing,
          padding, and word spacing into a single boolean so that we typically only have to do one
          "if" to rule out all three. Check for letterSpacing of 0 first so that we don't have to
          convert it to floating point when not using it. Same for padding and wordSpacing.
          Move the work from ceilCurrentWidth in line into this function. Assume that either we have
          all three pointers (widths, renderers, glyphs), or none of the three, to cut down on branches.
          (fillStyleWithAttributes): Use bool instead of BOOL.
          (shouldUseATSU): Ditto.
  
          * Misc.subproj/WebKitNSStringExtras.m: (-[NSString _web_widthWithFont:]): Update since
          the floatWidthForRun method no longer takes a widths parameter.
          * Misc.subproj/WebStringTruncator.m: (stringWidth): Ditto.
  
  Revision  Changes    Path
  1.253     +42 -0     WebCore/ChangeLog
  
  Index: ChangeLog
  ===================================================================
  RCS file: /cvs/root/WebCore/ChangeLog,v
  retrieving revision 1.252
  retrieving revision 1.253
  diff -u -r1.252 -r1.253
  --- ChangeLog	19 Oct 2005 09:15:12 -0000	1.252
  +++ ChangeLog	20 Oct 2005 06:02:20 -0000	1.253
  @@ -1,3 +1,45 @@
  +2005-10-19  Darin Adler  <darin at apple.com>
  +
  +        Reviewed by Maciej.
  +
  +        - optimizations for a total of about 1% speed-up on PLT
  +
  +        * khtml/html/htmltokenizer.cpp:
  +        (khtml::fixUpChar): Changed to be more inlinable.
  +        (khtml::HTMLTokenizer::processListing): Simplified the skipLF handling.
  +        (khtml::HTMLTokenizer::parseSpecial): Changed to call the new fixUpChar.
  +        (khtml::HTMLTokenizer::parseText): Simplified the skipLF handling and
  +        changed to call the new fixUpChar.
  +        (khtml::HTMLTokenizer::parseEntity): Changed to call the new fixUpChar.
  +        (khtml::HTMLTokenizer::parseTag): Changed to call the new fixUpChar.
  +        (khtml::HTMLTokenizer::write): Changed to call the new fixUpChar.
  +
  +        * khtml/rendering/font.h: Removed the floatCharacterWidths function,
  +        since it's never needed. Made some more functions inline.
  +        * khtml/rendering/font.cpp: Removed lots of stuff that was only for the
  +        !APPLE_CHANGES case.
  +
  +        * kwq/KWQFontMetrics.h: Removed the single-character width overloads, charWidth,
  +        and floatCharacterWidths.
  +        * kwq/KWQFontMetrics.mm:
  +        (QFontMetrics::width): Use lroundf instead of the ROUND_TO_INT macro.
  +        (QFontMetrics::floatWidth): Removed the bogus unneeded call to the ROUND_TO_INT macro.
  +
  +        * khtml/rendering/render_text.cpp:
  +        (RenderText::cacheWidths): Use floatWidth instead of floatCharacterWidths.
  +
  +        * kwq/KWQComboBox.mm: (QComboBox::sizeHint): Update since the floatWidthForRun
  +        method no longer takes a widths parameter.
  +        * kwq/KWQLineEdit.mm: (QLineEdit::sizeForCharacterWidth): Ditto.
  +        * kwq/KWQListBox.mm:
  +        (QListBox::sizeForNumberOfLines): Ditto.
  +        (-[KWQTableView drawRow:clipRect:]): Ditto.
  +        * kwq/KWQPainter.mm: (QPainter::drawText): Ditto. Also use lroundf instead of the
  +        ROUND_TO_INT macro.
  +
  +        * kwq/WebCoreTextRenderer.h: Removed the ROUND_TO_INT macro. Changed to use bool
  +        instead of bit fields. Removed the widths parameter from the floatWidthForRun method.
  +
   2005-10-19  Maciej Stachowiak  <mjs at apple.com>
   
           Reviewed by Dave.
  
  
  
  1.120     +33 -54    WebCore/khtml/html/htmltokenizer.cpp
  
  Index: htmltokenizer.cpp
  ===================================================================
  RCS file: /cvs/root/WebCore/khtml/html/htmltokenizer.cpp,v
  retrieving revision 1.119
  retrieving revision 1.120
  diff -u -r1.119 -r1.120
  --- htmltokenizer.cpp	18 Oct 2005 03:15:28 -0000	1.119
  +++ htmltokenizer.cpp	20 Oct 2005 06:02:23 -0000	1.120
  @@ -122,17 +122,12 @@
       0x02DC, 0x2122, 0x0161, 0x203A, 0x0153, 0x009D, 0x017E, 0x0178  // 98-9F
   };
   
  -static ushort mapChar(ushort c)
  -{
  -    assert(c >= 0x80 && c <= 0x9F);
  -    return windowsLatin1ExtensionArray[c - 0x80];
  -}
  -
  -static inline void fixUpChar(QChar &c)
  +static inline QChar fixUpChar(QChar c)
   {
       ushort code = c.unicode();
  -    if ((code & ~0x1F) == 0x0080)
  -        c = mapChar(code);
  +    if ((code & ~0x1F) != 0x0080)
  +        return c;
  +    return windowsLatin1ExtensionArray[code - 0x80];
   }
   
   inline bool tagMatch(const char *s1, const QChar *s2, uint length)
  @@ -264,15 +259,17 @@
       // This function adds the listing 'list' as
       // preformatted text-tokens to the token-collection
       while (!list.isEmpty()) {
  -        checkBuffer();
  -
  -        if (state.skipLF() && *list != '\n')
  -            state.setSkipLF(false);
  -
           if (state.skipLF()) {
               state.setSkipLF(false);
  -            ++list;
  -        } else if (*list == '\n' || *list == '\r') {
  +            if (*list == '\n') {
  +                ++list;
  +                continue;
  +            }
  +        }
  +
  +        checkBuffer();
  +
  +        if (*list == '\n' || *list == '\r') {
               if (state.discardLF())
                   // Ignore this LF
                   state.setDiscardLF(false); // We have discarded 1 LF
  @@ -371,8 +368,7 @@
               scriptCodeSize = scriptCodeDest-scriptCode;
           }
           else {
  -            fixUpChar(scriptCode[scriptCodeSize] = *src);
  -            ++scriptCodeSize;
  +            scriptCode[scriptCodeSize++] = fixUpChar(*src);
               ++src;
           }
       }
  @@ -677,35 +673,26 @@
   
   HTMLTokenizer::State HTMLTokenizer::parseText(TokenizerString &src, State state)
   {
  -    while (!src.isEmpty())
  -    {
  -        // do we need to enlarge the buffer?
  -        checkBuffer();
  -
  -        // ascii is okay because we only do ascii comparisons
  -        unsigned char chbegin = src->latin1();
  +    while (!src.isEmpty()) {
  +        ushort cc = src->unicode();
   
  -        if (state.skipLF() && (chbegin != '\n' ))
  +        if (state.skipLF()) {
               state.setSkipLF(false);
  +            if (cc == '\n') {
  +                ++src;
  +                continue;
  +            }
  +        }
   
  -        if (state.skipLF())
  -        {
  -            state.setSkipLF(false);
  -            ++src;
  -        } else if ((chbegin == '\n') || (chbegin == '\r'))
  -        {
  -            if (chbegin == '\r')
  -                state.setSkipLF(true);
  +        // do we need to enlarge the buffer?
  +        checkBuffer();
   
  +        if (cc == '\r') {
  +            state.setSkipLF(true);
               *dest++ = '\n';
  -            ++src;
  -        }
  -        else {
  -            *dest = *src;
  -            fixUpChar(*dest);
  -            ++dest;
  -            ++src;
  -        }
  +        } else
  +            *dest++ = fixUpChar(cc);
  +        ++src;
       }
   
       return state;
  @@ -835,10 +822,8 @@
                       ++src;
   
                   if (EntityUnicodeValue <= 0xFFFF) {
  -                    QChar c(EntityUnicodeValue);
  -                    fixUpChar(c);
                       checkBuffer();
  -                    src.push(c);
  +                    src.push(fixUpChar(EntityUnicodeValue));
                   } else {
                       // Convert to UTF-16, using surrogate code points.
                       QChar c1(0xD800 | (((EntityUnicodeValue >> 16) - 1) << 6) | ((EntityUnicodeValue >> 10) & 0x3F));
  @@ -1155,9 +1140,7 @@
                           break;
                       }
                   }
  -                *dest = *src;
  -                fixUpChar(*dest);
  -                ++dest;
  +                *dest++ = fixUpChar(*src);
                   ++src;
               }
               break;
  @@ -1191,9 +1174,7 @@
                       }
                   }
   
  -                *dest = *src;
  -                fixUpChar(*dest);
  -                ++dest;
  +                *dest++ = fixUpChar(*src);
                   ++src;
               }
               break;
  @@ -1553,9 +1534,7 @@
               if ( row > 0x05 && row < 0x10 || row > 0xfd )
                       currToken.complexText = true;
   #endif
  -            *dest = *src;
  -            fixUpChar(*dest);
  -            ++dest;
  +            *dest++ = fixUpChar(*src);
               ++src;
           }
       }
  
  
  
  1.46      +2 -205    WebCore/khtml/rendering/font.cpp
  
  Index: font.cpp
  ===================================================================
  RCS file: /cvs/root/WebCore/khtml/rendering/font.cpp,v
  retrieving revision 1.45
  retrieving revision 1.46
  diff -u -r1.45 -r1.46
  --- font.cpp	3 Oct 2005 21:12:37 -0000	1.45
  +++ font.cpp	20 Oct 2005 06:02:24 -0000	1.46
  @@ -29,18 +29,10 @@
   #include "khtml_factory.h"
   #include "khtml_settings.h"
   
  -#include <kdebug.h>
  -#include <kglobal.h>
  -
  -#include <qpainter.h>
  -#include <qfontdatabase.h>
  -#include <qpaintdevicemetrics.h>
  -
   #include <algorithm>
   
  -using namespace khtml;
  +namespace khtml {
   
  -#if APPLE_CHANGES
   void Font::drawHighlightForText( QPainter *p, int x, int y, int h, int tabWidth, int xpos, 
                        QChar *str, int slen, int pos, int len,
                        int toAdd, QPainter::TextDirection d, bool visuallyOrdered, int from, int to, QColor bg) const
  @@ -48,154 +40,16 @@
       p->drawHighlightForText(x, y, h, tabWidth, xpos, str + pos, std::min(slen - pos, len), from, to, toAdd, bg, d, visuallyOrdered,
                   letterSpacing, wordSpacing, fontDef.smallCaps);
   }
  -#endif
                        
   void Font::drawText( QPainter *p, int x, int y, int tabWidth, int xpos, QChar *str, int slen, int pos, int len,
                        int toAdd, QPainter::TextDirection d, bool visuallyOrdered, int from, int to, QColor bg ) const
   {
  -#if APPLE_CHANGES
       p->drawText(x, y, tabWidth, xpos, str + pos, std::min(slen - pos, len), from, to, toAdd, bg, d, visuallyOrdered,
                   letterSpacing, wordSpacing, fontDef.smallCaps);
  -#else
  -    QString qstr = QConstString(str, slen).qstring();
  -
  -    //fprintf (stdout, "x %d, y %d, pos %d, qstr.length() %d, len %d, toAdd %d, from %d, to %d, str \"%s\"\n", x, y, pos, qstr.length(), len, toAdd, from, to, qstr.ascii());
  -    // hack for fonts that don't have a welldefined nbsp
  -    if ( !fontDef.hasNbsp ) {
  -        // str.setLength() always does a deep copy, so the replacement code below is safe.
  -        qstr.setLength( slen );
  -        QChar *uc = (QChar *)qstr.unicode();
  -        for( int i = 0; i < slen; i++ )
  -            if ( (uc+i)->unicode() == 0xa0 )
  -            *(uc+i) = ' ';
  -    }
  -
  -    // ### fixme for RTL
  -    if ( !letterSpacing && !wordSpacing && !toAdd && from==-1 ) {
  -        // simply draw it
  -        p->drawText( x, y, tabWidth, xpos, qstr, pos, len, d );
  -    } else {
  -        int numSpaces = 0;
  -        if ( toAdd ) {
  -            for( int i = 0; i < len; i++ )
  -            if ( str[i+pos].direction() == QChar::DirWS )
  -                numSpaces++;
  -        }
  -    
  -        if ( d == QPainter::RTL ) {
  -            x += width( str, slen, pos, len ) + toAdd;
  -        }
  -        for( int i = 0; i < len; i++ ) {
  -            int chw = fm.charWidth( qstr, pos+i );
  -            if ( letterSpacing )
  -                chw += letterSpacing;
  -            if (i > 0 && (wordSpacing || toAdd) && str[i+pos].isSpace() && !str[i+pos-1].isSpace()) {
  -                chw += wordSpacing;
  -                if ( numSpaces ) {
  -                    int a = toAdd/numSpaces;
  -                    chw += a;
  -                    toAdd -= a;
  -                    numSpaces--;
  -                }
  -            }
  -            if ( d == QPainter::RTL )
  -                x -= chw;
  -            if ( to==-1 || (i>=from && i<to) )
  -            {
  -                if ( bg.isValid() )
  -                    p->fillRect( x, y-fm.ascent(), chw, fm.height(), bg );
  -
  -                p->drawText( x, y, tabWidth, xpos, qstr, pos+i, 1, d );
  -            }
  -            if ( d != QPainter::RTL )
  -                x += chw;
  -        }
  -    }
  -#endif
  -}
  -
  -#if APPLE_CHANGES
  -
  -float Font::floatWidth( QChar *chs, int slen, int pos, int len, int tabWidth, int xpos ) const
  -{
  -    return fm.floatWidth(chs, slen, pos, len, tabWidth, xpos, letterSpacing, wordSpacing, fontDef.smallCaps);
  -}
  -
  -
  -void Font::floatCharacterWidths( QChar *str, int slen, int pos, int len, int toAdd, int tabWidth, int xpos, float *buffer) const
  -{
  -    fm.floatCharacterWidths(str, slen, pos, len, toAdd, tabWidth, xpos, buffer, letterSpacing, wordSpacing, fontDef.smallCaps);
  -}
  -
  -int Font::checkSelectionPoint (QChar *s, int slen, int pos, int len, int toAdd, int tabWidth, int xpos, int x, bool reversed, bool includePartialGlyphs) const
  -{
  -    return fm.checkSelectionPoint (s, slen, pos, len, toAdd, tabWidth, xpos, letterSpacing, wordSpacing, fontDef.smallCaps, x, reversed, includePartialGlyphs);
   }
   
  -#endif
  -
  -int Font::width( QChar *chs, int slen, int pos, int len, int tabWidth, int xpos ) const
  +void Font::update(QPaintDeviceMetrics* devMetrics) const
   {
  -#if APPLE_CHANGES
  -#ifndef ROUND_TO_INT
  -#define ROUND_TO_INT(x) (unsigned int)((x)+.5)
  -#endif
  -    return ROUND_TO_INT(fm.floatWidth(chs+pos, slen-pos, 0, len, tabWidth, xpos, letterSpacing, wordSpacing, fontDef.smallCaps));
  -//    return fm.width(chs + pos, len);
  -#else
  -    QString qstr = QConstString(chs+pos, len).qstring();
  -    // hack for fonts that don't have a welldefined nbsp
  -    if ( !fontDef.hasNbsp ) {
  -	// str.setLength() always does a deep copy, so the replacement code below is safe.
  -	qstr.setLength( len );
  -	QChar *uc = (QChar *)qstr.unicode();
  -	for( int i = 0; i < len; i++ )
  -	    if ( (uc+i)->unicode() == 0xa0 )
  -		*(uc+i) = ' ';
  -    }
  -
  -    // ### might be a little inaccurate
  -    int w = fm.width( qstr );
  -
  -    if ( letterSpacing )
  -	    w += len*letterSpacing;
  -
  -    if ( wordSpacing )
  -        // add amount
  -        for( int i = 0; i < len; i++ ) {
  -            if( chs[i+pos].isSpace() )
  -            w += wordSpacing;
  -        }
  -
  -    return w;
  -#endif
  -}
  -
  -int Font::width( QChar *chs, int slen, int tabWidth, int xpos ) const
  -{
  -#if APPLE_CHANGES
  -//    return ROUND_TO_INT(fm.floatWidth(chs, slen, pos, 1, tabWidth, xpos, letterSpacing, wordSpacing));
  -    return width(chs, slen, 0, 1, tabWidth, xpos);
  -#else
  -    int w;
  -    if ( !fontDef.hasNbsp && (chs+pos)->unicode() == 0xa0 )
  -	w = fm.width( QChar( ' ' ) );
  -    else
  -	w = fm.charWidth( QConstString( chs, slen).qstring(), pos );
  -
  -    if ( letterSpacing )
  -	w += letterSpacing;
  -
  -    if ( wordSpacing && (chs+pos)->isSpace() )
  -        w += wordSpacing;
  -    return w;
  -#endif
  -}
  -
  -
  -void Font::update( QPaintDeviceMetrics* devMetrics ) const
  -{
  -#if APPLE_CHANGES
       if (fontDef.family.familyIsEmpty())
   	f.setFamily(KHTMLFactory::defaultHTMLSettings()->stdFontName());
       else
  @@ -206,63 +60,6 @@
       f.setPrinterFont(fontDef.usePrinterFont);
   
       fm.setFont(f);
  -#else
  -    f.setFamily( fontDef.family.isEmpty() ? KHTMLFactory::defaultHTMLSettings()->stdFontName() : fontDef.family );
  -    f.setItalic( fontDef.italic );
  -    f.setWeight( fontDef.weight );
  -
  -    QFontDatabase db;
  -
  -    int size = fontDef.size;
  -    int lDpiY = kMax(devMetrics->logicalDpiY(), 96);
  -
  -    // ok, now some magic to get a nice unscaled font
  -    // all other font properties should be set before this one!!!!
  -    if( !db.isSmoothlyScalable(f.family(), db.styleString(f)) )
  -    {
  -        QValueList<int> pointSizes = db.smoothSizes(f.family(), db.styleString(f));
  -        // lets see if we find a nice looking font, which is not too far away
  -        // from the requested one.
  -        // kdDebug(6080) << "khtml::setFontSize family = " << f.family() << " size requested=" << size << endl;
  -
  -        QValueList<int>::Iterator it;
  -        float diff = 1; // ### 100% deviation
  -        float bestSize = 0;
  -        for( it = pointSizes.begin(); it != pointSizes.end(); ++it )
  -        {
  -            float newDiff = ((*it)*(lDpiY/72.) - float(size))/float(size);
  -            //kdDebug( 6080 ) << "smooth font size: " << *it << " diff=" << newDiff << endl;
  -            if(newDiff < 0) newDiff = -newDiff;
  -            if(newDiff < diff)
  -            {
  -                diff = newDiff;
  -                bestSize = *it;
  -            }
  -        }
  -        //kdDebug( 6080 ) << "best smooth font size: " << bestSize << " diff=" << diff << endl;
  -        if ( bestSize != 0 && diff < 0.2 ) // 20% deviation, otherwise we use a scaled font...
  -            size = (int)((bestSize*lDpiY) / 72);
  -    }
  -
  -    // make sure we don't bust up X11
  -    size = KMAX(0, KMIN(255, size));
  -
  -//      qDebug("setting font to %s, italic=%d, weight=%d, size=%d", fontDef.family.latin1(), fontDef.italic,
  -//   	   fontDef.weight, size );
  -
  -
  -    f.setPixelSize( size );
  -
  -    fm = QFontMetrics( f );
  -
  -    fontDef.hasNbsp = fm.inFont( 0xa0 );
  -#endif
   }
   
  -#ifdef APPLE_CHANGES
  -bool Font::isFixedPitch() const
  -{
  -    return f.isFixedPitch();
   }
  -#endif
  -
  
  
  
  1.35      +66 -70    WebCore/khtml/rendering/font.h
  
  Index: font.h
  ===================================================================
  RCS file: /cvs/root/WebCore/khtml/rendering/font.h,v
  retrieving revision 1.34
  retrieving revision 1.35
  diff -u -r1.34 -r1.35
  --- font.h	30 Aug 2005 09:30:20 -0000	1.34
  +++ font.h	20 Oct 2005 06:02:24 -0000	1.35
  @@ -33,83 +33,63 @@
   
   class QPaintDeviceMetrics;
   
  +namespace khtml {
   
  -namespace khtml
  -{
   class RenderStyle;
   class CSSStyleSelector;
   
  -class FontDef
  -{
  +class FontDef {
   public:
  +    enum GenericFamilyType { eNone, eStandard, eSerif, eSansSerif, eMonospace, eCursive, eFantasy };
  +
       FontDef()
           : specifiedSize(0), computedSize(0), 
  -          italic( false ), smallCaps( false ), isAbsoluteSize(false), weight( 50 ), 
  -          genericFamily(0), hasNbsp( true )
  -#if APPLE_CHANGES
  -          , usePrinterFont( false )
  -#endif
  +          italic(false), smallCaps(false), isAbsoluteSize(false), weight(50), 
  +          genericFamily(0), usePrinterFont(false)
             {}
       
  -    bool operator == ( const FontDef &other ) const {
  -        return ( family == other.family &&
  -                 specifiedSize == other.specifiedSize &&
  -                 computedSize == other.computedSize &&
  -                 italic == other.italic &&
  -                 smallCaps == other.smallCaps &&
  -                 weight == other.weight &&
  -                 isAbsoluteSize == other.isAbsoluteSize
  -#if APPLE_CHANGES
  -                 && usePrinterFont == other.usePrinterFont
  -#endif
  -                 );
  -    }
  -
  -    enum GenericFamilyType { eNone, eStandard, eSerif, eSansSerif, eMonospace, eCursive, eFantasy };
  -
  -    void setGenericFamily(unsigned int aGenericFamily) { genericFamily = aGenericFamily; }
  +    void setGenericFamily(GenericFamilyType aGenericFamily) { genericFamily = aGenericFamily; }
       
       KWQFontFamily &firstFamily() { return family; }
  -    
  +    int computedPixelSize() const { return int(computedSize + 0.5f); }
  +
       KWQFontFamily family;
   
  -    int computedPixelSize() const { return int(computedSize+0.5); }
  -    
  -    float specifiedSize; // This is the specified CSS value.  It is independent of rendering issues such as
  -                         // integer rounding, minimum font sizes, and zooming.
  -    float computedSize; // This is the computed size adjusted for the minimum font size and the zoom
  -                        // factor.  
  -    
  +    float specifiedSize; // Specified CSS value. Independent of rendering issues such as integer
  +                         // rounding, minimum font sizes, and zooming.
  +    float computedSize;  // Computed size adjusted for the minimum font size and the zoom factor.  
  +
       bool italic 		: 1;
       bool smallCaps 		: 1;
  -    bool isAbsoluteSize    : 1;  // Whether or not CSS specified an explicit size
  +    bool isAbsoluteSize         : 1;  // Whether or not CSS specified an explicit size
                                         // (logical sizes like "medium" don't count).
       unsigned int weight 	: 8;
       unsigned int genericFamily	: 3;
  -    mutable bool hasNbsp	: 1;
  -#if APPLE_CHANGES
       bool usePrinterFont		: 1;
  -#endif
   };
   
  -
  -class Font
  +inline bool operator==(const FontDef& a, const FontDef& b)
   {
  +    return a.family == b.family
  +        && a.specifiedSize == b.specifiedSize
  +        && a.computedSize == b.computedSize
  +        && a.italic == b.italic
  +        && a.smallCaps == b.smallCaps
  +        && a.isAbsoluteSize == b.isAbsoluteSize
  +        && a.weight == b.weight
  +        && a.genericFamily == b.genericFamily
  +        && a.usePrinterFont == b.usePrinterFont;
  +}
  +
  +class Font {
       friend class RenderStyle;
       friend class CSSStyleSelector;
   
   public:
  -#if APPLE_CHANGES
       Font() : letterSpacing(0), wordSpacing(0) {}
       Font(const FontDef &fd, int l, int w) : fontDef(fd), letterSpacing(l), wordSpacing(w) {}
  -#else
  -    Font() : fontDef(), f(), fm( f ), scFont( 0 ), letterSpacing( 0 ), wordSpacing( 0 ) {}
  -    Font( const FontDef &fd, int l, int w )
  -        :  fontDef( fd ), f(), fm( f ), scFont( 0 ), letterSpacing( l ), wordSpacing( w )
  -        {}
  -#endif
   
  -    bool operator == ( const Font &other ) const {
  +    bool operator ==(const Font& other) const {
           return (fontDef == other.fontDef &&
                   letterSpacing == other.letterSpacing &&
                   wordSpacing == other.wordSpacing );
  @@ -117,40 +97,56 @@
   
       const FontDef& getFontDef() const { return fontDef; }
       
  -    void update( QPaintDeviceMetrics *devMetrics ) const;
  +    void update(QPaintDeviceMetrics *devMetrics) const;
   
  -                   
  -#if !APPLE_CHANGES
  -    void drawText( QPainter *p, int x, int y, int tabWidth, int xpos, QChar *str, int slen, int pos, int len, int width,
  -                   QPainter::TextDirection d, int from=-1, int to=-1, QColor bg=QColor() ) const;
  -
  -#else
  -    void drawText( QPainter *p, int x, int y, int tabWidth, int xpos, QChar *str, int slen, int pos, int len, int width,
  -                   QPainter::TextDirection d, bool visuallyOrdered = false, int from=-1, int to=-1, QColor bg=QColor() ) const;
  -    float floatWidth( QChar *str, int slen, int pos, int len, int tabWidth, int xpos ) const;
  -    void floatCharacterWidths( QChar *str, int slen, int pos, int len, int toAdd, int tabWidth, int xpos, float *buffer) const;
  +    void drawText(QPainter *p, int x, int y, int tabWidth, int xpos, QChar *str, int slen, int pos, int len, int width,
  +                  QPainter::TextDirection d, bool visuallyOrdered = false, int from = -1, int to = -1, QColor bg = QColor()) const;
  +    float floatWidth(QChar *str, int slen, int pos, int len, int tabWidth, int xpos) const;
       bool isFixedPitch() const;
  -    int checkSelectionPoint (QChar *s, int slen, int pos, int len, int toAdd, int tabWidth, int xpos, int x, bool reversed, bool includePartialGlyphs) const;
  -    void drawHighlightForText( QPainter *p, int x, int y, int h, int tabWidth, int xpos, 
  -                   QChar *str, int slen, int pos, int len, int width,
  -                   QPainter::TextDirection d, bool visuallyOrdered = false, int from=-1, int to=-1, QColor bg=QColor()) const;
  -#endif
  -    int width( QChar *str, int slen, int pos, int len, int tabWidth, int xpos ) const;
  -    int width( QChar *str, int slen, int tabWidth, int xpos ) const;
  +    int checkSelectionPoint(QChar *s, int slen, int pos, int len, int toAdd, int tabWidth, int xpos, int x, bool reversed, bool includePartialGlyphs) const;
  +    void drawHighlightForText(QPainter *p, int x, int y, int h, int tabWidth, int xpos, 
  +        QChar *str, int slen, int pos, int len, int width,
  +        QPainter::TextDirection d, bool visuallyOrdered = false, int from = -1, int to = -1, QColor bg = QColor()) const;
  +
  +    int width(QChar *str, int slen, int pos, int len, int tabWidth, int xpos) const;
  +    int width(QChar *str, int slen, int tabWidth, int xpos) const;
   
       bool isSmallCaps() const { return fontDef.smallCaps; }
       short getWordSpacing() const { return wordSpacing; }
  +
   private:
       FontDef fontDef;
       mutable QFont f;
       mutable QFontMetrics fm;
  -#if !APPLE_CHANGES
  -    QFont *scFont;
  -#endif
       short letterSpacing;
       short wordSpacing;
   };
   
  -};
  +inline float Font::floatWidth(QChar *chs, int slen, int pos, int len, int tabWidth, int xpos) const
  +{
  +    return fm.floatWidth(chs, slen, pos, len, tabWidth, xpos, letterSpacing, wordSpacing, fontDef.smallCaps);
  +}
  +
  +inline int Font::checkSelectionPoint(QChar *s, int slen, int pos, int len, int toAdd, int tabWidth, int xpos, int x, bool reversed, bool includePartialGlyphs) const
  +{
  +    return fm.checkSelectionPoint(s, slen, pos, len, toAdd, tabWidth, xpos, letterSpacing, wordSpacing, fontDef.smallCaps, x, reversed, includePartialGlyphs);
  +}
  +
  +inline int Font::width(QChar *chs, int slen, int pos, int len, int tabWidth, int xpos) const
  +{
  +    return lroundf(fm.floatWidth(chs + pos, slen - pos, 0, len, tabWidth, xpos, letterSpacing, wordSpacing, fontDef.smallCaps));
  +}
  +
  +inline int Font::width(QChar *chs, int slen, int tabWidth, int xpos) const
  +{
  +    return width(chs, slen, 0, 1, tabWidth, xpos);
  +}
  +
  +inline bool Font::isFixedPitch() const
  +{
  +    return f.isFixedPitch();
  +}
  +
  +}
   
   #endif
  
  
  
  1.202     +14 -58    WebCore/khtml/rendering/render_text.cpp
  
  Index: render_text.cpp
  ===================================================================
  RCS file: /cvs/root/WebCore/khtml/rendering/render_text.cpp,v
  retrieving revision 1.201
  retrieving revision 1.202
  diff -u -r1.201 -r1.202
  --- render_text.cpp	6 Oct 2005 00:53:59 -0000	1.201
  +++ render_text.cpp	20 Oct 2005 06:02:24 -0000	1.202
  @@ -21,8 +21,6 @@
    * Boston, MA 02111-1307, USA.
    *
    */
  -//#define DEBUG_LAYOUT
  -//#define BIDI_DEBUG
   
   #include "config.h"
   #include "rendering/render_text.h"
  @@ -50,6 +48,8 @@
   #include <unicode/utypes.h>
   #include <unicode/parseerr.h>
   
  +//#define DEBUG_LAYOUT
  +
   using namespace khtml;
   using namespace DOM;
   
  @@ -780,11 +780,9 @@
       m_minWidth = -1;
       m_maxWidth = -1;
   
  -#ifdef APPLE_CHANGES
       m_monospaceCharacterWidth = 0;
       m_allAsciiChecked = false;
       m_allAscii = false;
  -#endif
   
       str = _str;
       if (str) {
  @@ -816,11 +814,9 @@
               if (textToTransform.notNull())
                   setText(textToTransform.get(), true);
           }
  -#if APPLE_CHANGES
           // setText also calls cacheWidths(), so there is no need to call it again in that case.
           else
               cacheWidths();
  -#endif
       }
   }
   
  @@ -1126,8 +1122,6 @@
       }
   }
   
  -#ifdef APPLE_CHANGES
  -
   bool RenderText::allAscii() const
   {
       if (m_allAsciiChecked)
  @@ -1157,22 +1151,18 @@
   // RenderText.
   void RenderText::cacheWidths()
   {
  -    const Font *f = htmlFont( false );
  -    
  -    if (shouldUseMonospaceCache(f)){
  -        float fw;
  +    const Font *f = htmlFont(false);
  +    if (shouldUseMonospaceCache(f)) {
           QChar c(' ');
  -        f->floatCharacterWidths( &c, 1, 0, 1, 0, 0, 0, &fw);
  -        m_monospaceCharacterWidth = (int)fw;
  -    }
  -    else
  +        m_monospaceCharacterWidth = (int)f->floatWidth(&c, 1, 0, 1, 0, 0);
  +    } else {
           m_monospaceCharacterWidth = 0;
  +    }
   }
   
  -
  -inline int RenderText::widthFromCache(const Font *f, int start, int len, int tabWidth, int xpos) const
  +ALWAYS_INLINE int RenderText::widthFromCache(const Font *f, int start, int len, int tabWidth, int xpos) const
   {
  -    if (m_monospaceCharacterWidth != 0){
  +    if (m_monospaceCharacterWidth != 0) {
           int i, w = 0;
           for (i = start; i < start+len; i++){
               QChar c = str->s[i];
  @@ -1193,19 +1183,6 @@
       return f->width(str->s, str->l, start, len, tabWidth, xpos);
   }
   
  -#ifdef XXX
  -inline int RenderText::widthFromCache(const Font *f, int start, int len) const
  -{
  -    if (m_monospaceCharacterWidth != 0){
  -        return len * m_monospaceCharacterWidth;
  -    }
  -
  -    return f->width(str->s, str->l, start, len);
  -}
  -#endif
  -
  -#endif
  -
   void RenderText::trimmedMinMaxWidth(int leadWidth,
                                       int& beginMinW, bool& beginWS, 
                                       int& endMinW, bool& endWS,
  @@ -1266,11 +1243,7 @@
                   
               if (linelen)
               {
  -#if !APPLE_CHANGES
  -                endMaxW = f->width(str->s, str->l, i, linelen, tabWidth(), leadWidth + endMaxW); 
  -#else
                   endMaxW = widthFromCache(f, i, linelen, tabWidth(), leadWidth + endMaxW);
  -#endif
                   if (firstLine) {
                       firstLine = false;
                       leadWidth = 0;
  @@ -1379,11 +1352,7 @@
           int wordlen = j - i;
           if (wordlen)
           {
  -#if !APPLE_CHANGES
  -            int w = f->width(str->s, str->l, i, wordlen, tabWidth(), leadWidth + currMaxWidth);
  -#else
               int w = widthFromCache(f, i, wordlen, tabWidth(), leadWidth + currMaxWidth);
  -#endif
               currMinWidth += w;
               currMaxWidth += w;
               
  @@ -1602,17 +1571,15 @@
       if (str)
           str->deref();
   
  -#ifdef APPLE_CHANGES
       m_allAsciiChecked = false;
  -#endif
   
       str = text;
       if (str) {
           str = str->replace('\\', backslashAsCurrencySymbol());
  -        if ( style() ) {
  -            switch(style()->textTransform()) {
  -                case CAPITALIZE:   str = str->capitalize();  break;
  -                case UPPERCASE:   str = str->upper();       break;
  +        if (style()) {
  +            switch (style()->textTransform()) {
  +                case CAPITALIZE: str = str->capitalize();  break;
  +                case UPPERCASE:  str = str->upper();       break;
                   case LOWERCASE:  str = str->lower();       break;
                   case NONE:
                   default:;
  @@ -1621,9 +1588,7 @@
           str->ref();
       }
   
  -#if APPLE_CHANGES
       cacheWidths();
  -#endif
   
       // ### what should happen if we change the text of a
       // RenderBR object ?
  @@ -1631,11 +1596,6 @@
       KHTMLAssert(!str->l || str->s);
   
       setNeedsLayoutAndMinMaxRecalc();
  -    
  -#ifdef BIDI_DEBUG
  -    QConstString cstr(str->s, str->l);
  -    kdDebug( 6040 ) << "RenderText::setText( " << cstr.qstring().length() << " ) '" << cstr.qstring() << "'" << endl;
  -#endif
   }
   
   int RenderText::height() const
  @@ -1730,10 +1690,8 @@
       int w;
       if ( style()->whiteSpace() != PRE && f == &style()->htmlFont() && from == 0 && len == str->l ) {
           w = m_maxWidth;
  -#if APPLE_CHANGES
       } else if (f == &style()->htmlFont()) {
  -        w = widthFromCache (f, from, len, tabWidth(), xpos);
  -#endif
  +        w = widthFromCache(f, from, len, tabWidth(), xpos);
       } else {
   	w = f->width(str->s, str->l, from, len, tabWidth(), xpos );
       }
  @@ -1909,5 +1867,3 @@
           result = result->substring(start(), end());
       return SharedPtr<DOMStringImpl>(result);
   }
  -#undef BIDI_DEBUG
  -#undef DEBUG_LAYOUT
  
  
  
  1.69      +1 -1      WebCore/kwq/KWQComboBox.mm
  
  Index: KWQComboBox.mm
  ===================================================================
  RCS file: /cvs/root/WebCore/kwq/KWQComboBox.mm,v
  retrieving revision 1.68
  retrieving revision 1.69
  diff -u -r1.68 -r1.69
  --- KWQComboBox.mm	6 Oct 2005 15:45:54 -0000	1.68
  +++ KWQComboBox.mm	20 Oct 2005 06:02:25 -0000	1.69
  @@ -195,7 +195,7 @@
                   } else {
                       renderer = itemRenderer;
                   }
  -                float textWidth = [renderer floatWidthForRun:&run style:&style widths:0];
  +                float textWidth = [renderer floatWidthForRun:&run style:&style];
                   width = kMax(width, textWidth);
               } while (i != e);
           }
  
  
  
  1.42      +3 -9      WebCore/kwq/KWQFontMetrics.h
  
  Index: KWQFontMetrics.h
  ===================================================================
  RCS file: /cvs/root/WebCore/kwq/KWQFontMetrics.h,v
  retrieving revision 1.41
  retrieving revision 1.42
  diff -u -r1.41 -r1.42
  --- KWQFontMetrics.h	29 Jul 2005 23:42:54 -0000	1.41
  +++ KWQFontMetrics.h	20 Oct 2005 06:02:26 -0000	1.42
  @@ -29,8 +29,8 @@
   #include "KWQRect.h"
   #include "KWQSize.h"
   #include "KWQString.h"
  -#include "KWQFont.h"
   
  +class QFont;
   class QFontMetricsPrivate;
   
   class QFontMetrics {
  @@ -51,16 +51,10 @@
       int lineSpacing() const;
       float xHeight() const;
       
  -    int width(QChar, int tabWidth, int xpos) const;
  -    int width(char, int tabWidth, int xpos) const;
       int width(const QString &, int tabWidth, int xpos, int len=-1) const;
  -    int charWidth(const QString &, int pos, int tabWidth, int xpos) const;
       int width(const QChar *, int len, int tabWidth, int xpos) const;
  -    float floatWidth(const QChar *, int slen, int pos, int len,
  -                     int tabWidth, int xpos, int letterSpacing, int wordSpacing, bool smallCaps) const;
  -    float floatCharacterWidths(const QChar *, int slen, int pos, int len, int toAdd, int tabWidth, int xpos, float *buffer,
  -                               int letterSpacing, int wordSpacing, bool smallCaps) const;
  -    int checkSelectionPoint (QChar *s, int slen, int pos, int len, int toAdd, int tabWidth, int xpos, int letterSpacing, int wordSpacing, bool smallCaps, int x, bool reversed, bool includePartialGlyphs) const;
  +    float floatWidth(const QChar *, int slen, int pos, int len, int tabWidth, int xpos, int letterSpacing, int wordSpacing, bool smallCaps) const;
  +    int checkSelectionPoint(QChar *s, int slen, int pos, int len, int toAdd, int tabWidth, int xpos, int letterSpacing, int wordSpacing, bool smallCaps, int x, bool reversed, bool includePartialGlyphs) const;
   
       QRect boundingRect(QChar) const;
       QRect boundingRect(const QString &, int tabWidth, int xpos, int len=-1) const;
  
  
  
  1.92      +7 -82     WebCore/kwq/KWQFontMetrics.mm
  
  Index: KWQFontMetrics.mm
  ===================================================================
  RCS file: /cvs/root/WebCore/kwq/KWQFontMetrics.mm,v
  retrieving revision 1.91
  retrieving revision 1.92
  diff -u -r1.91 -r1.92
  --- KWQFontMetrics.mm	6 Oct 2005 15:45:54 -0000	1.91
  +++ KWQFontMetrics.mm	20 Oct 2005 06:02:26 -0000	1.92
  @@ -156,57 +156,6 @@
       return [data->getRenderer() xHeight];
   }
   
  -int QFontMetrics::width(QChar qc, int tabWidth, int xpos) const
  -{
  -    if (data.isNull()) {
  -        ERROR("called width on an empty QFontMetrics");
  -        return 0;
  -    }
  -    
  -    UniChar c = qc.unicode();
  -
  -    CREATE_FAMILY_ARRAY(data->font(), families);
  -
  -    WebCoreTextRun run;
  -    WebCoreInitializeTextRun(&run, &c, 1, 0, 1);
  -    
  -    WebCoreTextStyle style;
  -    WebCoreInitializeEmptyTextStyle(&style);
  -    style.families = families;
  -    style.tabWidth = tabWidth;
  -    style.xpos = xpos;
  -
  -    return ROUND_TO_INT([data->getRenderer() floatWidthForRun:&run style:&style widths:0]);
  -}
  -
  -int QFontMetrics::charWidth(const QString &s, int pos, int tabWidth, int xpos) const
  -{
  -    return width(s[pos], tabWidth, xpos);
  -}
  -
  -int QFontMetrics::width(char c, int tabWidth, int xpos) const
  -{
  -    if (data.isNull()) {
  -        ERROR("called width on an empty QFontMetrics");
  -        return 0;
  -    }
  -    
  -    UniChar ch = (uchar) c;
  -
  -    CREATE_FAMILY_ARRAY(data->font(), families);
  -
  -    WebCoreTextRun run;
  -    WebCoreInitializeTextRun(&run, &ch, 1, 0, 1);
  -    
  -    WebCoreTextStyle style;
  -    WebCoreInitializeEmptyTextStyle(&style);
  -    style.families = families;
  -    style.tabWidth = tabWidth;
  -    style.xpos = xpos;
  -
  -    return ROUND_TO_INT([data->getRenderer() floatWidthForRun:&run style:&style widths:0]);
  -}
  -
   int QFontMetrics::width(const QString &qstring, int tabWidth, int xpos, int len) const
   {
       if (data.isNull()) {
  @@ -227,7 +176,7 @@
       style.tabWidth = tabWidth;
       style.xpos = xpos;
   
  -    return ROUND_TO_INT([data->getRenderer() floatWidthForRun:&run style:&style widths:0]);
  +    return lroundf([data->getRenderer() floatWidthForRun:&run style:&style]);
   }
   
   int QFontMetrics::width(const QChar *uchars, int len, int tabWidth, int xpos) const
  @@ -248,11 +197,10 @@
       style.tabWidth = tabWidth;
       style.xpos = xpos;
   
  -    return ROUND_TO_INT([data->getRenderer() floatWidthForRun:&run style:&style widths:0]);
  +    return lroundf([data->getRenderer() floatWidthForRun:&run style:&style]);
   }
   
  -float QFontMetrics::floatWidth(const QChar *uchars, int slen, int pos, int len,
  -                               int tabWidth, int xpos, int letterSpacing, int wordSpacing, bool smallCaps) const
  +float QFontMetrics::floatWidth(const QChar *uchars, int slen, int pos, int len, int tabWidth, int xpos, int letterSpacing, int wordSpacing, bool smallCaps) const
   {
       if (data.isNull()) {
           ERROR("called floatWidth on an empty QFontMetrics");
  @@ -260,6 +208,7 @@
       }
   
       CREATE_FAMILY_ARRAY(data->font(), families);
  +
       WebCoreTextRun run;
       WebCoreInitializeTextRun(&run, (const UniChar *)uchars, slen, pos, pos+len);
       
  @@ -272,35 +221,10 @@
       style.smallCaps = smallCaps;
       style.families = families;
   
  -    return ROUND_TO_INT([data->getRenderer() floatWidthForRun:&run style:&style widths:0]);
  -}
  -
  -float QFontMetrics::floatCharacterWidths(const QChar *uchars, int slen, int pos, int len, int toAdd, int tabWidth, int xpos, float *buffer, int letterSpacing, int wordSpacing, bool smallCaps) const
  -{
  -    if (data.isNull()) {
  -        ERROR("called floatCharacterWidths on an empty QFontMetrics");
  -        return 0;
  -    }
  -    
  -    CREATE_FAMILY_ARRAY(data->font(), families);
  -
  -    WebCoreTextRun run;
  -    WebCoreInitializeTextRun(&run, (const UniChar *)uchars, slen, pos, pos+len);
  -    
  -    WebCoreTextStyle style;
  -    WebCoreInitializeEmptyTextStyle(&style);
  -    style.letterSpacing = letterSpacing;
  -    style.wordSpacing = wordSpacing;
  -    style.smallCaps = smallCaps;
  -    style.padding = toAdd;
  -    style.tabWidth = tabWidth;
  -    style.xpos = xpos;
  -    style.families = families;
  -
  -    return [data->getRenderer() floatWidthForRun:&run style:&style widths:buffer];
  +    return [data->getRenderer() floatWidthForRun:&run style:&style];
   }
   
  -int QFontMetrics::checkSelectionPoint (QChar *s, int slen, int pos, int len, int toAdd, int tabWidth, int xpos, int letterSpacing, int wordSpacing, bool smallCaps, int x, bool reversed, bool includePartialGlyphs) const
  +int QFontMetrics::checkSelectionPoint(QChar *s, int slen, int pos, int len, int toAdd, int tabWidth, int xpos, int letterSpacing, int wordSpacing, bool smallCaps, int x, bool reversed, bool includePartialGlyphs) const
   {
       if (data.isNull()) {
           ERROR("called checkSelectionPoint on an empty QFontMetrics");
  @@ -308,6 +232,7 @@
       }
       
       CREATE_FAMILY_ARRAY(data->font(), families);
  +
       WebCoreTextRun run;
       WebCoreInitializeTextRun(&run, (const UniChar *)s, slen, pos, pos+len);
       
  
  
  
  1.74      +1 -1      WebCore/kwq/KWQLineEdit.mm
  
  Index: KWQLineEdit.mm
  ===================================================================
  RCS file: /cvs/root/WebCore/kwq/KWQLineEdit.mm,v
  retrieving revision 1.73
  retrieving revision 1.74
  diff -u -r1.73 -r1.74
  --- KWQLineEdit.mm	6 Oct 2005 15:45:54 -0000	1.73
  +++ KWQLineEdit.mm	20 Oct 2005 06:02:26 -0000	1.74
  @@ -272,7 +272,7 @@
       WebCoreTextRun run;
       WebCoreInitializeTextRun(&run, &zero, 1, 0, 1);
   
  -    size.width += ceilf([renderer floatWidthForRun:&run style:&style widths:0] * numCharacters);
  +    size.width += ceilf([renderer floatWidthForRun:&run style:&style] * numCharacters);
   
       KWQ_UNBLOCK_EXCEPTIONS;
   
  
  
  
  1.62      +2 -2      WebCore/kwq/KWQListBox.mm
  
  Index: KWQListBox.mm
  ===================================================================
  RCS file: /cvs/root/WebCore/kwq/KWQListBox.mm,v
  retrieving revision 1.61
  retrieving revision 1.62
  diff -u -r1.61 -r1.62
  --- KWQListBox.mm	9 Oct 2005 02:36:14 -0000	1.61
  +++ KWQListBox.mm	20 Oct 2005 06:02:26 -0000	1.62
  @@ -304,7 +304,7 @@
                   int length = s.length();
                   WebCoreInitializeTextRun(&run, reinterpret_cast<const UniChar *>(s.unicode()), length, 0, length);
   
  -                float textWidth = [(((*i).type == KWQListBoxGroupLabel) ? groupLabelRenderer : renderer) floatWidthForRun:&run style:&style widths:0];
  +                float textWidth = [(((*i).type == KWQListBoxGroupLabel) ? groupLabelRenderer : renderer) floatWidthForRun:&run style:&style];
                   width = kMax(width, textWidth);
                   
                   ++i;
  @@ -727,7 +727,7 @@
       if (!rtl) {
           point.x = NSMinX(cellRect) + leftMargin;
       } else {
  -        point.x = NSMaxX(cellRect) - rightMargin - [renderer floatWidthForRun:&run style:&style widths:0];
  +        point.x = NSMaxX(cellRect) - rightMargin - [renderer floatWidthForRun:&run style:&style];
       }
       point.y = NSMaxY(cellRect) - [renderer descent] - bottomMargin;
   
  
  
  
  1.146     +2 -1      WebCore/kwq/KWQPainter.mm
  
  Index: KWQPainter.mm
  ===================================================================
  RCS file: /cvs/root/WebCore/kwq/KWQPainter.mm,v
  retrieving revision 1.145
  retrieving revision 1.146
  diff -u -r1.145 -r1.146
  --- KWQPainter.mm	6 Oct 2005 15:45:55 -0000	1.145
  +++ KWQPainter.mm	20 Oct 2005 06:02:27 -0000	1.146
  @@ -29,6 +29,7 @@
   #import <kxmlcore/Assertions.h>
   #import "KWQBrush.h"
   #import "KWQExceptions.h"
  +#import "KWQFont.h"
   #import "KWQFoundationExtras.h"
   #import "KWQPaintDevice.h"
   #import "KWQPen.h"
  @@ -636,7 +637,7 @@
       style.xpos = xpos;
       
       if (alignmentFlags & Qt::AlignRight)
  -        x -= ROUND_TO_INT([data->textRenderer floatWidthForRun:&run style:&style widths:0]);
  +        x -= lroundf([data->textRenderer floatWidthForRun:&run style:&style]);
   
       WebCoreTextGeometry geometry;
       WebCoreInitializeEmptyTextGeometry(&geometry);
  
  
  
  1.37      +14 -17    WebCore/kwq/WebCoreTextRenderer.h
  
  Index: WebCoreTextRenderer.h
  ===================================================================
  RCS file: /cvs/root/WebCore/kwq/WebCoreTextRenderer.h,v
  retrieving revision 1.36
  retrieving revision 1.37
  diff -u -r1.36 -r1.37
  --- WebCoreTextRenderer.h	24 Sep 2005 11:45:18 -0000	1.36
  +++ WebCoreTextRenderer.h	20 Oct 2005 06:02:27 -0000	1.37
  @@ -25,26 +25,22 @@
   
   #import <Cocoa/Cocoa.h>
   
  -#ifndef ROUND_TO_INT
  -#define ROUND_TO_INT(x) (unsigned int)((x)+.5)
  -#endif
  -
   struct WebCoreTextStyle
   {
       NSColor *textColor;
       NSColor *backgroundColor;
  -    float letterSpacing;
  -    float wordSpacing;
  -    float padding;
  -    float tabWidth;
  -    float xpos;
  +    int letterSpacing;
  +    int wordSpacing;
  +    int padding;
  +    int tabWidth;
  +    int xpos;
       NSString **families;
  -    unsigned smallCaps : 1;
  -    unsigned rtl : 1;
  -    unsigned directionalOverride : 1;
  -    unsigned applyRunRounding : 1;
  -    unsigned applyWordRounding : 1;
  -    unsigned attemptFontSubstitution : 1;
  +    bool smallCaps;
  +    bool rtl;
  +    bool directionalOverride;
  +    bool applyRunRounding;
  +    bool applyWordRounding;
  +    bool attemptFontSubstitution;
   };
   
   struct WebCoreTextRun
  @@ -60,7 +56,7 @@
       NSPoint point;
       float selectionY;
       float selectionHeight;
  -    bool useFontMetricsForSelectionYAndHeight : 1;
  +    bool useFontMetricsForSelectionYAndHeight;
   };
   
   #ifdef __cplusplus
  @@ -94,7 +90,7 @@
   - (float)xHeight;
   
   // horizontal metrics
  -- (float)floatWidthForRun:(const WebCoreTextRun *)run style:(const WebCoreTextStyle *)style widths:(float *)buffer;
  +- (float)floatWidthForRun:(const WebCoreTextRun *)run style:(const WebCoreTextStyle *)style;
   
   // drawing
   - (void)drawRun:(const WebCoreTextRun *)run style:(const WebCoreTextStyle *)style geometry:(const WebCoreTextGeometry *)geometry;
  @@ -105,4 +101,5 @@
   
   // selection point check
   - (int)pointToOffset:(const WebCoreTextRun *)run style:(const WebCoreTextStyle *)style position:(int)x reversed:(BOOL)reversed includePartialGlyphs:(BOOL)includePartialGlyphs;
  +
   @end
  
  
  
  1.3354    +89 -0     WebKit/ChangeLog
  
  Index: ChangeLog
  ===================================================================
  RCS file: /cvs/root/WebKit/ChangeLog,v
  retrieving revision 1.3353
  retrieving revision 1.3354
  diff -u -r1.3353 -r1.3354
  --- ChangeLog	20 Oct 2005 05:03:12 -0000	1.3353
  +++ ChangeLog	20 Oct 2005 06:02:28 -0000	1.3354
  @@ -1,3 +1,92 @@
  +2005-10-19  Darin Adler  <darin at apple.com>
  +
  +        Reviewed by Maciej.
  +
  +        - optimizations for a total of about 1% speed-up on PLT
  +
  +        * WebCoreSupport.subproj/WebTextRenderer.h: Updated to use bool instead of BOOL,
  +        since BOOL is a signed char (which is not so efficient, at least on PPC).
  +        * WebCoreSupport.subproj/WebTextRenderer.m:
  +        (isSpace): Changed BOOL to bool and UniChar to UChar32. This actually fixes a
  +        potential bug when the passed-in character is a non-BMP character (> FFFF).
  +        (isRoundingHackCharacter): Ditto.
  +        (widthForGlyph): Merged getUncachedWidth, widthFromMap, and widthForGlyph into
  +        one function. Marked it inline. Changed to include syntheticBoldOffset in the
  +        cached widths to save an add in the cached case. Instead of the special constant
  +        UNINITIALIZED_GLYPH_WIDTH, just check for a width >= 0. This allows us to use
  +        a negative number or NAN for the uninitialized width value -- I chose NAN.
  +        (overrideLayoutOperation): Use bool instead of Boolean in one place.
  +        (-[WebTextRenderer initWithFont:]): Use lroundf instead of ROUND_TO_INT.
  +        (-[WebTextRenderer floatWidthForRun:style:]): Put the code to choose the ATSU
  +        vs. CG code path back in here, because there are no callers inside the class
  +        that need to call both.
  +        (-[WebTextRenderer drawLineForCharacters:yOffset:width:color:thickness:]):
  +        Use bool instead of BOOL.
  +        (+[WebTextRenderer setAlwaysUseATSU:]): Ditto.
  +        (fontContainsString): Ditto.
  +        (-[WebTextRenderer computeWidthForSpace]): Ditto. Also use roundf instead of
  +        using ROUND_TO_INT.
  +        (-[WebTextRenderer setUpFont]): Use bool instead of BOOL.
  +        (drawGlyphs): Ditto.
  +        (-[WebTextRenderer CG_drawHighlightForRun:style:geometry:]): Restructure the
  +        code so it can use the new advanceWidthIterator function instead of the old
  +        widthForNextCharacter function.
  +        (-[WebTextRenderer CG_drawRun:style:geometry:]): Use malloc instead of calloc
  +        since we don't need initialization. Call CG_floatWidthForRun instead of
  +        floatWidthForRun -- no need to re-check whether to use the CG or ATSU code path.
  +        Removed code to handle a renderer of 0 since we no longer generate that in
  +        the renderers array in advanceWidthIterator.
  +        (CG_floatWidthForRun): Changed to call the new advanceWidthIterator instead of
  +        the old widthForNextCharacter.
  +        (-[WebTextRenderer extendCharacterToGlyphMapToInclude:]): Use malloc instead of
  +        calloc and explicitly initialize the one field that needs it. Fixed a potential
  +        storage leak by adding a call to WKClearGlyphVector. Initialize the renderers
  +        to self instead of to 0.
  +        (-[WebTextRenderer extendGlyphToWidthMapToInclude:]): Initialize the widths to
  +        NAN instead of UNINITIALIZED_GLYPH_WIDTH.
  +        (addDirectionalOverride): Fixed bug where the first and last character in the buffer
  +        could be uninitialized and where characters before and after the direction override
  +        could be incorrect.
  +        (-[WebTextRenderer ATSU_drawRun:style:geometry:]): Use bool instead of BOOL.
  +        (-[WebTextRenderer ATSU_pointToOffset:style:position:reversed:includePartialGlyphs:]):
  +        Ditto.
  +        (advanceWidthIteratorOneCharacter): Added new helper function for CG_pointToOffset.
  +        (-[WebTextRenderer CG_pointToOffset:style:position:reversed:includePartialGlyphs:]):
  +        Reimplemented to use advanceWidthIteratorOneCharacter instead of widthForNextCharacter.
  +        Also call CG_floatWidthForRun instead of floatWidthForRun since we don't need to
  +        reconsider whether to use CG or ATSU.
  +        (glyphForCharacter): Removed the map parameter and changed the renderer parameter to
  +        be an in-out one. Removed uneeded special case for when map is 0 and always get the
  +        renderer from the map. Also call extendCharacterToGlyphMapToInclude in here instead of
  +        making that the caller's responsibility.
  +        (initializeWidthIterator): Renamed to make the name shorter (removed "Character").
  +        Streamlned common cases like "no padding" and removed some unneeded casts. Changed to
  +        use advanceWidthIterator to compute width fo the first part of the run.
  +        (normalizeVoicingMarks): Factored this out into a separate function, since it's not part
  +        of the common case.
  +        (advanceWidthIterator): Changed widthForNextCharacter to this, eliminating per-character
  +        function overhead for iterating past a few characters. Merged the handling of surrogate
  +        pairs and of voicing marks so that we typically only have to do one "if" to rule out both.
  +        Merged the mirroring for RTL and uppercasing for small caps into a single boolean so that
  +        we only need one "if" to rule out both. Call the new glyphForCharacter. Check for the
  +        character '\t' first since that's cheaper than looking at tabWidth. Check tabWidth for 0
  +        first so that we don't have to convert it to floating point when not using it. Changed
  +        the special case for spaces to first check width, so that we don't bother with the rest
  +        of the code for glyphs not the same width as spaces. Fixed substitution code to call
  +        CG_floatWidthForRun -- no need to reconsider whether to use CG or ATSU. Also changed to
  +        properly get width from the result of that function. Merged the handling of letter spacing,
  +        padding, and word spacing into a single boolean so that we typically only have to do one
  +        "if" to rule out all three. Check for letterSpacing of 0 first so that we don't have to
  +        convert it to floating point when not using it. Same for padding and wordSpacing.
  +        Move the work from ceilCurrentWidth in line into this function. Assume that either we have
  +        all three pointers (widths, renderers, glyphs), or none of the three, to cut down on branches.
  +        (fillStyleWithAttributes): Use bool instead of BOOL.
  +        (shouldUseATSU): Ditto.
  +
  +        * Misc.subproj/WebKitNSStringExtras.m: (-[NSString _web_widthWithFont:]): Update since
  +        the floatWidthForRun method no longer takes a widths parameter.
  +        * Misc.subproj/WebStringTruncator.m: (stringWidth): Ditto.
  +
   2005-10-19  Tim Omernick  <tomernick at apple.com>
   
           Reviewed by eseidel & darin.
  
  
  
  1.28      +3 -4      WebKit/Misc.subproj/WebKitNSStringExtras.m
  
  Index: WebKitNSStringExtras.m
  ===================================================================
  RCS file: /cvs/root/WebKit/Misc.subproj/WebKitNSStringExtras.m,v
  retrieving revision 1.27
  retrieving revision 1.28
  diff -u -r1.27 -r1.28
  --- WebKitNSStringExtras.m	6 Oct 2005 15:46:08 -0000	1.27
  +++ WebKitNSStringExtras.m	20 Oct 2005 06:02:37 -0000	1.28
  @@ -114,7 +114,7 @@
   
       [self getCharacters:buffer];
   
  -    if (canUseFastRenderer(buffer, length)){
  +    if (canUseFastRenderer(buffer, length)) {
           WebCoreFont f;
           WebCoreInitializeFont(&f);
           f.font = font;
  @@ -126,9 +126,8 @@
           WebCoreInitializeEmptyTextStyle(&style);
           style.applyRunRounding = NO;
           style.applyWordRounding = NO;
  -        width = [renderer floatWidthForRun:&run style:&style widths: 0];
  -    }
  -    else {
  +        width = [renderer floatWidthForRun:&run style:&style];
  +    } else {
           width = [self sizeWithAttributes:[NSDictionary dictionaryWithObjectsAndKeys:font, NSFontAttributeName, nil]].width;
       }
       
  
  
  
  1.24      +1 -1      WebKit/Misc.subproj/WebStringTruncator.m
  
  Index: WebStringTruncator.m
  ===================================================================
  RCS file: /cvs/root/WebKit/Misc.subproj/WebStringTruncator.m,v
  retrieving revision 1.23
  retrieving revision 1.24
  diff -u -r1.23 -r1.24
  --- WebStringTruncator.m	6 Oct 2005 15:46:08 -0000	1.23
  +++ WebStringTruncator.m	20 Oct 2005 06:02:37 -0000	1.24
  @@ -86,7 +86,7 @@
       WebCoreInitializeEmptyTextStyle(&style);
       style.applyRunRounding = NO;
       style.applyWordRounding = NO;
  -    return [renderer floatWidthForRun:&run style:&style widths:0];
  +    return [renderer floatWidthForRun:&run style:&style];
   }
   
   static NSString *truncateString(NSString *string, float maxWidth, NSFont *font, TruncationFunction truncateToBuffer)
  
  
  
  1.40      +4 -4      WebKit/WebCoreSupport.subproj/WebTextRenderer.h
  
  Index: WebTextRenderer.h
  ===================================================================
  RCS file: /cvs/root/WebKit/WebCoreSupport.subproj/WebTextRenderer.h,v
  retrieving revision 1.39
  retrieving revision 1.40
  diff -u -r1.39 -r1.40
  --- WebTextRenderer.h	6 Oct 2005 15:46:09 -0000	1.39
  +++ WebTextRenderer.h	20 Oct 2005 06:02:37 -0000	1.40
  @@ -46,7 +46,7 @@
       GlyphMap *characterToGlyphMap;
       WidthMap *glyphToWidthMap;
   
  -    BOOL treatAsFixedPitch;
  +    bool treatAsFixedPitch;
       ATSGlyphRef spaceGlyph;
       float spaceWidth;
       float adjustedSpaceWidth;
  @@ -55,8 +55,8 @@
   @private
       WebTextRenderer *smallCapsRenderer;
       ATSUStyle _ATSUStyle;
  -    BOOL ATSUStyleInitialized;
  -    BOOL ATSUMirrors;
  +    bool ATSUStyleInitialized;
  +    bool ATSUMirrors;
   }
   
   - (id)initWithFont:(WebCoreFont)font;
  @@ -65,6 +65,6 @@
   
   @interface WebTextRenderer (WebPrivate)
   
  -+ (void)setAlwaysUseATSU:(BOOL)f;
  ++ (void)setAlwaysUseATSU:(bool)f;
   
   @end
  
  
  
  1.198     +371 -430  WebKit/WebCoreSupport.subproj/WebTextRenderer.m
  
  Index: WebTextRenderer.m
  ===================================================================
  RCS file: /cvs/root/WebKit/WebCoreSupport.subproj/WebTextRenderer.m,v
  retrieving revision 1.197
  retrieving revision 1.198
  diff -u -r1.197 -r1.198
  --- WebTextRenderer.m	20 Oct 2005 05:03:15 -0000	1.197
  +++ WebTextRenderer.m	20 Oct 2005 06:02:38 -0000	1.198
  @@ -72,10 +72,6 @@
   // This will typically be for other character sets.
   #define INCREMENTAL_BLOCK_SIZE 0x400
   
  -#define UNINITIALIZED_GLYPH_WIDTH 65535
  -
  -#define INVALID_WIDTH (-FLT_MAX)
  -
   #if !defined(ScaleEmToUnits)
   #define CONTEXT_DPI	(72.0)
   
  @@ -83,7 +79,6 @@
   #endif
   
   typedef float WebGlyphWidth;
  -typedef UInt32 UnicodeChar;
   
   struct WidthMap {
       ATSGlyphRef startRange;
  @@ -94,17 +89,17 @@
   
   typedef struct GlyphEntry {
       ATSGlyphRef glyph;
  -    WebTextRenderer *substituteRenderer;
  +    WebTextRenderer *renderer;
   } GlyphEntry;
   
   struct GlyphMap {
  -    UnicodeChar startRange;
  -    UnicodeChar endRange;
  +    UChar32 startRange;
  +    UChar32 endRange;
       GlyphMap *next;
       GlyphEntry *glyphs;
   };
   
  -typedef struct CharacterWidthIterator {
  +typedef struct WidthIterator {
       WebTextRenderer *renderer;
       const WebCoreTextRun *run;
       const WebCoreTextStyle *style;
  @@ -113,7 +108,7 @@
       float widthToStart;
       float padding;
       float padPerSpace;
  -} CharacterWidthIterator;
  +} WidthIterator;
   
   typedef struct ATSULayoutParameters
   {
  @@ -129,12 +124,10 @@
   - (WebTextRenderer *)rendererForAlternateFont:(WebCoreFont)alternateNSFont;
   
   - (WidthMap *)extendGlyphToWidthMapToInclude:(ATSGlyphRef)glyphID;
  -- (ATSGlyphRef)extendCharacterToGlyphMapToInclude:(UnicodeChar)c;
  -- (void)updateGlyphEntryForCharacter:(UnicodeChar)c glyphID:(ATSGlyphRef)glyphID substituteRenderer:(WebTextRenderer *)substituteRenderer;
  +- (ATSGlyphRef)extendCharacterToGlyphMapToInclude:(UChar32)c;
  +- (void)updateGlyphEntryForCharacter:(UChar32)c glyphID:(ATSGlyphRef)glyphID substituteRenderer:(WebTextRenderer *)substituteRenderer;
   
   // Measuring runs.
  -static inline float floatWidthForRun(WebTextRenderer *renderer, const WebCoreTextRun *run, const WebCoreTextStyle *style, float *widthBuffer, WebTextRenderer **rendererBuffer,
  -    CGGlyph *glyphBuffer, float *startPosition, int *numGlyphs);
   static float CG_floatWidthForRun(WebTextRenderer *renderer, const WebCoreTextRun *run, const WebCoreTextStyle *style, float *widthBuffer, WebTextRenderer **rendererBuffer, CGGlyph *glyphBuffer, float *startPosition, int *numGlyphsResult);
   static float ATSU_floatWidthForRun(WebTextRenderer *renderer, const WebCoreTextRun *run, const WebCoreTextStyle *style);
   
  @@ -143,14 +136,14 @@
   - (void)ATSU_drawRun:(const WebCoreTextRun *)run style:(const WebCoreTextStyle *)style geometry:(const WebCoreTextGeometry *)geometry;
   
   // Selection point detection in runs.
  -- (int)CG_pointToOffset:(const WebCoreTextRun *)run style:(const WebCoreTextStyle *)style position:(int)x reversed:(BOOL)reversed includePartialGlyphs:(BOOL)includePartialGlyphs;
  -- (int)ATSU_pointToOffset:(const WebCoreTextRun *)run style:(const WebCoreTextStyle *)style position:(int)x reversed:(BOOL)reversed includePartialGlyphs:(BOOL)includePartialGlyphs;
  +- (int)CG_pointToOffset:(const WebCoreTextRun *)run style:(const WebCoreTextStyle *)style position:(int)x reversed:(bool)reversed includePartialGlyphs:(bool)includePartialGlyphs;
  +- (int)ATSU_pointToOffset:(const WebCoreTextRun *)run style:(const WebCoreTextStyle *)style position:(int)x reversed:(bool)reversed includePartialGlyphs:(bool)includePartialGlyphs;
   
   // Drawing highlight for runs.
   - (void)CG_drawHighlightForRun:(const WebCoreTextRun *)run style:(const WebCoreTextStyle *)style geometry:(const WebCoreTextGeometry *)geometry;
   - (void)ATSU_drawHighlightForRun:(const WebCoreTextRun *)run style:(const WebCoreTextStyle *)style geometry:(const WebCoreTextGeometry *)geometry;
   
  -- (BOOL)setUpFont;
  +- (bool)setUpFont;
   
   - (ATSUTextLayout)createATSUTextLayoutForRun:(const WebCoreTextRun *)run style:(const WebCoreTextStyle *)style;
   
  @@ -160,7 +153,7 @@
   
   // Character property functions.
   
  -static inline BOOL isSpace(UniChar c)
  +static inline bool isSpace(UChar32 c)
   {
       return c == SPACE || c == '\t' || c == '\n' || c == NO_BREAK_SPACE;
   }
  @@ -176,7 +169,7 @@
       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
   };
   
  -static inline BOOL isRoundingHackCharacter(UniChar c)
  +static inline bool isRoundingHackCharacter(UChar32 c)
   {
       return (((c & ~0xFF) == 0 && isRoundingHackCharacterTable[c]));
   }
  @@ -185,43 +178,29 @@
   static void freeWidthMap(WidthMap *map);
   static void freeGlyphMap(GlyphMap *map);
   
  -static WebGlyphWidth getUncachedWidth(WebTextRenderer *renderer, WidthMap *map, ATSGlyphRef glyph)
  +static inline WebGlyphWidth widthForGlyph(WebTextRenderer *renderer, ATSGlyphRef glyph)
   {
  +    WidthMap *map;
  +    for (map = renderer->glyphToWidthMap; 1; map = map->next) {
  +        if (!map)
  +            map = [renderer extendGlyphToWidthMapToInclude:glyph];
  +        if (glyph >= map->startRange && glyph <= map->endRange)
  +            break;
  +    }
  +    WebGlyphWidth width = map->widths[glyph - map->startRange];
  +    if (width >= 0)
  +        return width;
       NSFont *font = renderer->font.font;
  -
       float pointSize = [font pointSize];
       CGAffineTransform m = CGAffineTransformMakeScale(pointSize, pointSize);
       CGSize advance;
       if (!WKGetGlyphTransformedAdvances(font, &m, &glyph, &advance)) {
           ERROR("Unable to cache glyph widths for %@ %f", [font displayName], pointSize);
  -        return 0;
  -    }
  -
  -    return advance.width;
  -}
  -
  -static inline WebGlyphWidth widthFromMap(WebTextRenderer *renderer, WidthMap *map, ATSGlyphRef glyph)
  -{
  -    while (1) {
  -        if (map == 0)
  -            map = [renderer extendGlyphToWidthMapToInclude:glyph];
  -
  -        if (glyph >= map->startRange && glyph <= map->endRange) {
  -            WebGlyphWidth width = map->widths[glyph - map->startRange];
  -            if (width == UNINITIALIZED_GLYPH_WIDTH) {
  -                width = getUncachedWidth(renderer, map, glyph);
  -                map->widths[glyph - map->startRange] = width;
  -            }
  -            return width;
  -        }
  -
  -        map = map->next;
  +        advance.width = 0;
       }
  -}    
  -
  -static inline WebGlyphWidth widthForGlyph(WebTextRenderer *renderer, ATSGlyphRef glyph)
  -{
  -    return widthFromMap(renderer, renderer->glyphToWidthMap, glyph) + renderer->syntheticBoldOffset;
  +    width = advance.width + renderer->syntheticBoldOffset;
  +    map->widths[glyph - map->startRange] = width;
  +    return width;
   }
   
   static OSStatus overrideLayoutOperation(ATSULayoutOperationSelector iCurrentOperation, ATSULineRef iLineRef, UInt32 iRefCon, void *iOperationCallbackParameterPtr, ATSULayoutOperationCallbackStatus *oCallbackStatus)
  @@ -242,7 +221,7 @@
           // The CoreGraphics interpretation of NSFontAntialiasedIntegerAdvancementsRenderingMode seems
           // to be "round each glyph's width to the nearest integer". This is not the same as ATSUI
           // does in any of its device-metrics modes.
  -        Boolean roundEachGlyph = [params->renderer->font.font renderingMode] == NSFontAntialiasedIntegerAdvancementsRenderingMode;
  +        bool roundEachGlyph = [params->renderer->font.font renderingMode] == NSFontAntialiasedIntegerAdvancementsRenderingMode;
           Fixed lastNativePos = 0;
           float lastAdjustedPos = 0;
           const WebCoreTextRun *run = params->run;
  @@ -285,21 +264,21 @@
   }
   
   // Iterator functions
  -static void initializeCharacterWidthIterator(CharacterWidthIterator *iterator, WebTextRenderer *renderer, const WebCoreTextRun *run , const WebCoreTextStyle *style);
  -static float widthForNextCharacter(CharacterWidthIterator *iterator, ATSGlyphRef *glyphUsed, WebTextRenderer **rendererUsed);
  +static void initializeWidthIterator(WidthIterator *iterator, WebTextRenderer *renderer, const WebCoreTextRun *run, const WebCoreTextStyle *style);
  +static unsigned advanceWidthIterator(WidthIterator *iterator, unsigned offset, float *widths, WebTextRenderer **renderersUsed, ATSGlyphRef *glyphsUsed);
   
  -static BOOL fillStyleWithAttributes(ATSUStyle style, NSFont *theFont);
  -static BOOL shouldUseATSU(const WebCoreTextRun *run);
  +static bool fillStyleWithAttributes(ATSUStyle style, NSFont *theFont);
  +static bool shouldUseATSU(const WebCoreTextRun *run);
   
   #if !ERROR_DISABLED
   static NSString *pathFromFont(NSFont *font);
   #endif
   
  -static void createATSULayoutParameters(ATSULayoutParameters *params, WebTextRenderer *renderer, const WebCoreTextRun *run , const WebCoreTextStyle *style);
  +static void createATSULayoutParameters(ATSULayoutParameters *params, WebTextRenderer *renderer, const WebCoreTextRun *run, const WebCoreTextStyle *style);
   static void disposeATSULayoutParameters(ATSULayoutParameters *params);
   
   // Globals
  -static BOOL alwaysUseATSU = NO;
  +static bool alwaysUseATSU = NO;
   
   @implementation WebTextRenderer
   
  @@ -405,8 +384,8 @@
       if ([familyName isEqualToString:@"Times"] || [familyName isEqualToString:@"Helvetica"] || [familyName isEqualToString:@"Courier"])
           asc += floorf(((asc + dsc) * 0.15f) + 0.5f);
   
  -    ascent = ROUND_TO_INT(asc);
  -    descent = ROUND_TO_INT(dsc);
  +    ascent = lroundf(asc);
  +    descent = lroundf(dsc);
   
       _lineGap = _lineGap > 0.0 ? floorf(_lineGap + 0.5f) : 0.0f;
       lineGap = (int)_lineGap;
  @@ -488,9 +467,11 @@
           [self CG_drawRun:run style:style geometry:geometry];
   }
   
  -- (float)floatWidthForRun:(const WebCoreTextRun *)run style:(const WebCoreTextStyle *)style widths:(float *)widthBuffer
  +- (float)floatWidthForRun:(const WebCoreTextRun *)run style:(const WebCoreTextStyle *)style
   {
  -    return floatWidthForRun(self, run, style, widthBuffer, 0, 0, 0, 0);
  +    if (shouldUseATSU(run))
  +        return ATSU_floatWidthForRun(self, run, style);
  +    return CG_floatWidthForRun(self, run, style, 0, 0, 0, 0, 0);
   }
   
   - (void)drawLineForCharacters:(NSPoint)point yOffset:(float)yOffset width: (int)width color:(NSColor *)color thickness:(float)thickness
  @@ -503,7 +484,7 @@
       // Remember that descender is negative.
       point.y -= [self lineSpacing] - [self descent];
       
  -    BOOL flag = [graphicsContext shouldAntialias];
  +    bool flag = [graphicsContext shouldAntialias];
   
       // We don't want antialiased lines on screen, but we do when printing (else they are too thick).
       if ([graphicsContext isDrawingToScreen]) {
  @@ -514,7 +495,7 @@
   
       cgContext = (CGContextRef)[graphicsContext graphicsPort];
   
  -    // hack to make thickness 2 underlines for internation text input look right
  +    // Hack to make thickness 2 underlines for international text input look right
       if (thickness > 1.5F && thickness < 2.5F) {
           yOffset += .5F;
       }
  @@ -631,7 +612,7 @@
   
   @implementation WebTextRenderer (WebInternal)
   
  -+ (void)setAlwaysUseATSU:(BOOL)f
  ++ (void)setAlwaysUseATSU:(bool)f
   {
       alwaysUseATSU = f;
   }
  @@ -652,7 +633,7 @@
       return smallCapsRenderer;
   }
   
  -static inline BOOL fontContainsString(NSFont *font, NSString *string)
  +static inline bool fontContainsString(NSFont *font, NSString *string)
   {
       NSCharacterSet *set = [[font coveredCharacterSet] invertedSet];
       return set && [string rangeOfCharacterFromSet:set].location == NSNotFound;
  @@ -741,7 +722,7 @@
   // Nasty hack to determine if we should round or ceil space widths.
   // If the font is monospace or fake monospace we ceil to ensure that 
   // every character and the space are the same width.  Otherwise we round.
  -- (BOOL)computeWidthForSpace
  +- (bool)computeWidthForSpace
   {
       spaceGlyph = [self extendCharacterToGlyphMapToInclude:SPACE];
       if (spaceGlyph == 0) {
  @@ -753,12 +734,12 @@
       spaceWidth = width;
   
       treatAsFixedPitch = [[WebTextRendererFactory sharedFactory] isFontFixedPitch:font];
  -    adjustedSpaceWidth = treatAsFixedPitch ? ceilf(width) : (int)ROUND_TO_INT(width);
  +    adjustedSpaceWidth = treatAsFixedPitch ? ceilf(width) : roundf(width);
       
       return YES;
   }
   
  -- (BOOL)setUpFont
  +- (bool)setUpFont
   {
       font.font = font.forPrinter ? [font.font printerFont] : [font.font screenFont];
   
  @@ -813,7 +794,7 @@
   
   // Useful page for testing http://home.att.net/~jameskass
   static void drawGlyphs(NSFont *font, NSColor *color, CGGlyph *glyphs, CGSize *advances, float x, float y, int numGlyphs,
  -    float syntheticBoldOffset, BOOL syntheticOblique)
  +    float syntheticBoldOffset, bool syntheticOblique)
   {
       NSGraphicsContext *gContext = [NSGraphicsContext currentContext];
       CGContextRef cgContext = (CGContextRef)[gContext graphicsPort];
  @@ -867,48 +848,34 @@
       if (run->length == 0)
           return;
   
  -    CharacterWidthIterator widthIterator;
  +    if (style->backgroundColor == nil)
  +        return;
  +
  +    [style->backgroundColor set];
  +
  +    float yPos = geometry->useFontMetricsForSelectionYAndHeight ? geometry->point.y - [self ascent] - (lineGap/2) : geometry->selectionY;
  +    float height = geometry->useFontMetricsForSelectionYAndHeight ? [self lineSpacing] : geometry->selectionHeight;
  +
       WebCoreTextRun completeRun = *run;
       completeRun.from = 0;
       completeRun.to = run->length;
  -    initializeCharacterWidthIterator(&widthIterator, self, &completeRun, style);
  -    
  -    float startPosition = 0;
   
  -    // The starting point needs to be adjusted to account for the width of
  -    // the glyphs at the start of the run.
  -    while (widthIterator.currentCharacter < (unsigned)run->from) {
  -        startPosition += widthForNextCharacter(&widthIterator, 0, 0);
  -    }
  -    float startX = startPosition + geometry->point.x;
  +    WidthIterator it;
  +    initializeWidthIterator(&it, self, &completeRun, style);
       
  -    float backgroundWidth = 0.0F;
  -    while (widthIterator.currentCharacter < (unsigned)run->to) {
  -        backgroundWidth += widthForNextCharacter(&widthIterator, 0, 0);
  -    }
  -
  -    if (style->backgroundColor != nil) {
  -        // Calculate the width of the selection background by adding
  -        // up the advances of all the glyphs in the selection.
  -        
  -        [style->backgroundColor set];
  -
  -        float yPos = geometry->useFontMetricsForSelectionYAndHeight ? geometry->point.y - [self ascent] - (lineGap/2) : geometry->selectionY;
  -        float height = geometry->useFontMetricsForSelectionYAndHeight ? [self lineSpacing] : geometry->selectionHeight;
  -        if (style->rtl) {
  -            float completeRunWidth = startPosition + backgroundWidth;
  -            while (widthIterator.currentCharacter < run->length) {
  -                completeRunWidth += widthForNextCharacter(&widthIterator, 0, 0);
  -            }
  -
  -            [NSBezierPath fillRect:NSMakeRect(geometry->point.x + completeRunWidth - startPosition - backgroundWidth, yPos, backgroundWidth, height)];
  -        } else {
  -            [NSBezierPath fillRect:NSMakeRect(startX, yPos, backgroundWidth, height)];
  -        }
  +    advanceWidthIterator(&it, run->from, 0, 0, 0);
  +    float beforeWidth = it.runWidthSoFar;
  +    advanceWidthIterator(&it, run->to, 0, 0, 0);
  +    float backgroundWidth = it.runWidthSoFar;
  +    if (style->rtl) {
  +        advanceWidthIterator(&it, run->length, 0, 0, 0);
  +        float afterWidth = it.runWidthSoFar;
  +        [NSBezierPath fillRect:NSMakeRect(geometry->point.x + afterWidth, yPos, backgroundWidth, height)];
  +    } else {
  +        [NSBezierPath fillRect:NSMakeRect(geometry->point.x + beforeWidth, yPos, backgroundWidth, height)];
       }
   }
   
  -
   - (void)CG_drawRun:(const WebCoreTextRun *)run style:(const WebCoreTextStyle *)style geometry:(const WebCoreTextGeometry *)geometry
   {
       float *widthBuffer, localWidthBuffer[LOCAL_BUFFER_SIZE];
  @@ -922,11 +889,11 @@
       if (run->length == 0)
           return;
   
  -    if (length*MAX_GLYPH_EXPANSION > LOCAL_BUFFER_SIZE) {
  -        advances = (CGSize *)calloc(length*MAX_GLYPH_EXPANSION, sizeof(CGSize));
  -        widthBuffer = (float *)calloc(length*MAX_GLYPH_EXPANSION, sizeof(float));
  -        glyphBuffer = (CGGlyph *)calloc(length*MAX_GLYPH_EXPANSION, sizeof(ATSGlyphRef));
  -        rendererBuffer = (WebTextRenderer **)calloc(length*MAX_GLYPH_EXPANSION, sizeof(WebTextRenderer *));
  +    if (length * MAX_GLYPH_EXPANSION > LOCAL_BUFFER_SIZE) {
  +        advances = malloc(length * MAX_GLYPH_EXPANSION * sizeof(CGSize));
  +        widthBuffer = malloc(length * MAX_GLYPH_EXPANSION * sizeof(float));
  +        glyphBuffer = malloc(length * MAX_GLYPH_EXPANSION * sizeof(ATSGlyphRef));
  +        rendererBuffer = malloc(length * MAX_GLYPH_EXPANSION * sizeof(WebTextRenderer *));
       } else {
           advances = localAdvanceBuffer;
           widthBuffer = localWidthBuffer;
  @@ -934,7 +901,7 @@
           rendererBuffer = localRendererBuffer;
       }
   
  -    floatWidthForRun(self, run, style, widthBuffer, rendererBuffer, glyphBuffer, &startX, &numGlyphs);
  +    CG_floatWidthForRun(self, run, style, widthBuffer, rendererBuffer, glyphBuffer, &startX, &numGlyphs);
           
       // Eek.  We couldn't generate ANY glyphs for the run.
       if (numGlyphs <= 0)
  @@ -976,17 +943,14 @@
           }
       }
   
  -    // Finally, draw the glyphs.
  -    int lastFrom = 0;
  -    int pos = 0;
  -
       // Draw each contiguous run of glyphs that use the same renderer.
  -    WebTextRenderer *currentRenderer = rendererBuffer[pos];
  +    WebTextRenderer *currentRenderer = rendererBuffer[0];
       float nextX = startX;
  -    int nextGlyph = pos;
  +    int lastFrom = 0;
  +    int nextGlyph = 0;
       while (nextGlyph < numGlyphs) {
           WebTextRenderer *nextRenderer = rendererBuffer[nextGlyph];
  -        if (nextRenderer && nextRenderer != currentRenderer) {
  +        if (nextRenderer != currentRenderer) {
               drawGlyphs(currentRenderer->font.font, style->textColor, &glyphBuffer[lastFrom], &advances[lastFrom],
                   startX, geometry->point.y, nextGlyph - lastFrom,
                   currentRenderer->syntheticBoldOffset, currentRenderer->font.syntheticOblique);
  @@ -1009,68 +973,41 @@
       }
   }
   
  -static inline float floatWidthForRun(WebTextRenderer *renderer, const WebCoreTextRun *run, const WebCoreTextStyle *style, float *widthBuffer, WebTextRenderer **rendererBuffer,
  -    CGGlyph *glyphBuffer, float *startPosition, int *numGlyphs)
  -{
  -    if (shouldUseATSU(run))
  -        return ATSU_floatWidthForRun(renderer, run, style);
  -    
  -    return CG_floatWidthForRun(renderer, run, style, widthBuffer, rendererBuffer, glyphBuffer, startPosition, numGlyphs);
  -}
  -
   static float CG_floatWidthForRun(WebTextRenderer *renderer, const WebCoreTextRun *run, const WebCoreTextStyle *style, float *widthBuffer, WebTextRenderer **rendererBuffer, CGGlyph *glyphBuffer, float *startPosition, int *numGlyphsResult)
   {
  -    float _nextWidth;
  -    CharacterWidthIterator widthIterator;
  -    WebTextRenderer *rendererUsed = nil;
  -    ATSGlyphRef glyphUsed;
  -    int numGlyphs = 0;
  -    
  -    initializeCharacterWidthIterator(&widthIterator, renderer, run, style);
  +    WidthIterator it;
  +    initializeWidthIterator(&it, renderer, run, style);
  +    int numGlyphs = advanceWidthIterator(&it, run->to, widthBuffer, rendererBuffer, glyphBuffer);
       if (startPosition)
  -        *startPosition = widthIterator.widthToStart;
  -    while (widthIterator.currentCharacter < (unsigned)widthIterator.run->to) {
  -        _nextWidth = widthForNextCharacter(&widthIterator, &glyphUsed, &rendererUsed);
  -        if (_nextWidth == INVALID_WIDTH)
  -            break;
  -        if (rendererBuffer)
  -            rendererBuffer[numGlyphs] = rendererUsed;
  -        if (glyphBuffer)
  -            glyphBuffer[numGlyphs] = glyphUsed;
  -        if (widthBuffer)
  -            widthBuffer[numGlyphs] = _nextWidth;
  -        numGlyphs++;
  -    }
  -        
  +        *startPosition = it.widthToStart;
       if (numGlyphsResult)
           *numGlyphsResult = numGlyphs;
  -
  -    return widthIterator.runWidthSoFar;
  +    return it.runWidthSoFar;
   }
   
  -- (void)updateGlyphEntryForCharacter:(UnicodeChar)c glyphID:(ATSGlyphRef)glyphID substituteRenderer:(WebTextRenderer *)substituteRenderer
  +- (void)updateGlyphEntryForCharacter:(UChar32)c glyphID:(ATSGlyphRef)glyphID substituteRenderer:(WebTextRenderer *)substituteRenderer
   {
       GlyphMap *map;
       for (map = characterToGlyphMap; map; map = map->next) {
  -        UnicodeChar start = map->startRange;
  +        UChar32 start = map->startRange;
           if (c >= start && c <= map->endRange) {
               int i = c - start;
               map->glyphs[i].glyph = glyphID;
               // This renderer will leak.
               // No problem though; we want it to stick around forever.
               // Max theoretical retain counts applied here will be num_fonts_on_system * num_glyphs_in_font.
  -            map->glyphs[i].substituteRenderer = [substituteRenderer retain];
  +            map->glyphs[i].renderer = [substituteRenderer retain];
               break;
           }
       }
   }
   
  -- (ATSGlyphRef)extendCharacterToGlyphMapToInclude:(UnicodeChar)c
  +- (ATSGlyphRef)extendCharacterToGlyphMapToInclude:(UChar32)c
   {
  -    GlyphMap *map = (GlyphMap *)calloc(1, sizeof(GlyphMap));
  +    GlyphMap *map = malloc(sizeof(GlyphMap));
       ATSLayoutRecord *glyphRecord;
       char glyphVector[WKGlyphVectorSize];
  -    UnicodeChar end, start;
  +    UChar32 end, start;
       unsigned blockSize;
       
       if (characterToGlyphMap == 0)
  @@ -1084,6 +1021,7 @@
   
       map->startRange = start;
       map->endRange = end;
  +    map->next = 0;
       
       unsigned i;
       unsigned count = end - start + 1;
  @@ -1128,14 +1066,16 @@
       if (numGlyphs != count) {
           // This should never happen, perhaps indicates a bad font?
           // If it does happen, the font substitution code will find an alternate font.
  +        WKClearGlyphVector(&glyphVector);
           free(map);
           return 0;
       }
   
  -    map->glyphs = (GlyphEntry *)calloc(count, sizeof(GlyphEntry));
  +    map->glyphs = malloc(count * sizeof(GlyphEntry));
       glyphRecord = (ATSLayoutRecord *)WKGetGlyphVectorFirstRecord(glyphVector);
       for (i = 0; i < count; i++) {
           map->glyphs[i].glyph = glyphRecord->glyphID;
  +        map->glyphs[i].renderer = self;
           glyphRecord = (ATSLayoutRecord *)((char *)glyphRecord + WKGetGlyphVectorRecordSize(glyphVector));
       }
       WKClearGlyphVector(&glyphVector);
  @@ -1190,9 +1130,9 @@
       map->endRange = end;
       count = end - start + 1;
   
  -    map->widths = (WebGlyphWidth *)malloc(count * sizeof(WebGlyphWidth));
  +    map->widths = malloc(count * sizeof(WebGlyphWidth));
       for (i = 0; i < count; i++)
  -        map->widths[i] = UNINITIALIZED_GLYPH_WIDTH;
  +        map->widths[i] = NAN;
   
       if (glyphToWidthMap == 0)
           glyphToWidthMap = map;
  @@ -1314,7 +1254,6 @@
       return layout;
   }
   
  -
   - (ATSTrapezoid)trapezoidForRun:(const WebCoreTextRun *)run style:(const WebCoreTextStyle *)style atPoint:(NSPoint )p
   {
       // The only Cocoa call here is the self call to
  @@ -1343,54 +1282,57 @@
       return firstGlyphBounds;
   }
   
  -
   static float ATSU_floatWidthForRun(WebTextRenderer *renderer, const WebCoreTextRun *run, const WebCoreTextStyle *style)
   {
  -    ATSTrapezoid oGlyphBounds;
  -    
  -    oGlyphBounds = [renderer trapezoidForRun:run style:style atPoint:NSMakePoint(0,0)];
  -    
  -    float width = 
  -        MAX(FixedToFloat(oGlyphBounds.upperRight.x), FixedToFloat(oGlyphBounds.lowerRight.x)) - 
  +    ATSTrapezoid oGlyphBounds = [renderer trapezoidForRun:run style:style atPoint:NSMakePoint(0, 0)];
  +    return MAX(FixedToFloat(oGlyphBounds.upperRight.x), FixedToFloat(oGlyphBounds.lowerRight.x)) -
           MIN(FixedToFloat(oGlyphBounds.upperLeft.x), FixedToFloat(oGlyphBounds.lowerLeft.x));
  -    
  -    return width;
   }
   
   // Be sure to free the run.characters allocated by this function.
  -static WebCoreTextRun addDirectionalOverride(const WebCoreTextRun *run, BOOL rtl)
  +static WebCoreTextRun addDirectionalOverride(const WebCoreTextRun *run, bool rtl)
   {
  -    WebCoreTextRun swappedRun;
  -    
  -    UniChar *swappedCharacters = (UniChar *)malloc(sizeof(UniChar)*(run->length+2));
  -    memcpy(swappedCharacters+1, run->characters, sizeof(UniChar)*run->length);
  -    swappedRun.from = (run->from == -1 ? 0 : run->from) + 1;
  -    swappedRun.to = (run->to == -1 ? (int)run->length - 1 : run->to + 1);
  -    swappedRun.length = run->length+2;
  -    swappedCharacters[swappedRun.from - 1] = rtl ? RIGHT_TO_LEFT_OVERRIDE : LEFT_TO_RIGHT_OVERRIDE;
  -    swappedCharacters[swappedRun.to] = POP_DIRECTIONAL_FORMATTING;
  -    swappedRun.characters = swappedCharacters;
  +    int from = run->from;
  +    int to = run->to;
  +    if (from == -1)
  +        from = 0;
  +    if (to == -1)
  +        to = run->length;
  +
  +    UniChar *charactersWithOverride = malloc(sizeof(UniChar) * (run->length + 2));
   
  -    return swappedRun;
  +    memcpy(&charactersWithOverride[0], &run->characters[0], sizeof(UniChar) * from);
  +    charactersWithOverride[from] = rtl ? RIGHT_TO_LEFT_OVERRIDE : LEFT_TO_RIGHT_OVERRIDE;
  +    memcpy(&charactersWithOverride[from + 1], &run->characters[from], sizeof(UniChar) * (to - from));
  +    charactersWithOverride[to + 1] = POP_DIRECTIONAL_FORMATTING;
  +    memcpy(&charactersWithOverride[to + 2], &run->characters[to], sizeof(UniChar) * (run->length - to));
  +
  +    WebCoreTextRun runWithOverride;
  +
  +    runWithOverride.from = from;
  +    runWithOverride.to = to + 2;
  +    runWithOverride.length = run->length + 2;
  +    runWithOverride.characters = charactersWithOverride;
  +
  +    return runWithOverride;
   }
   
   // Be sure to free the run.characters allocated by this function.
   static WebCoreTextRun applyMirroringToRun(const WebCoreTextRun *run)
   {
  -    WebCoreTextRun swappedRun;
  +    UniChar *mirroredCharacters = malloc(sizeof(UniChar)*(run->length));
       unsigned int i;
  -    
  -    UniChar *swappedCharacters = (UniChar *)malloc(sizeof(UniChar)*(run->length));
  -    for (i = 0; i < run->length; i++) {
  -        // will choke on surrogate pairs?
  -        swappedCharacters[i] = u_charMirror(run->characters[i]);
  -    }
  -    swappedRun.from = run->from;
  -    swappedRun.to = run->to;
  -    swappedRun.length = run->length;
  -    swappedRun.characters = swappedCharacters;
  +    for (i = 0; i < run->length; i++)
  +        mirroredCharacters[i] = u_charMirror(run->characters[i]);
  +
  +    WebCoreTextRun mirroredRun;
   
  -    return swappedRun;
  +    mirroredRun.from = run->from;
  +    mirroredRun.to = run->to;
  +    mirroredRun.length = run->length;
  +    mirroredRun.characters = mirroredCharacters;
  +
  +    return mirroredRun;
   }
   
   - (void)ATSU_drawHighlightForRun:(const WebCoreTextRun *)run style:(const WebCoreTextStyle *)style geometry:(const WebCoreTextGeometry *)geometry
  @@ -1511,7 +1453,7 @@
       NSGraphicsContext *gContext = [NSGraphicsContext currentContext];
       CGContextRef context = (CGContextRef)[gContext graphicsPort];
       CGContextTranslateCTM(context, geometry->point.x, geometry->point.y);
  -    BOOL flipped = [gContext isFlipped];
  +    bool flipped = [gContext isFlipped];
       if (!flipped)
           CGContextScaleCTM(context, 1.0, -1.0);
       status = ATSUDrawText(params.layout, aRun->from, runLength, 0, 0);
  @@ -1530,7 +1472,7 @@
           free((void *)swappedRun.characters);
   }
   
  -- (int)ATSU_pointToOffset:(const WebCoreTextRun *)run style:(const WebCoreTextStyle *)style position:(int)x reversed:(BOOL)reversed includePartialGlyphs:(BOOL)includePartialGlyphs
  +- (int)ATSU_pointToOffset:(const WebCoreTextRun *)run style:(const WebCoreTextStyle *)style position:(int)x reversed:(bool)reversed includePartialGlyphs:(bool)includePartialGlyphs
   {
       // The only Cocoa calls made here is to the self call to
       // _createATSUTextLayoutForRun:. This is exception-safe.
  @@ -1582,58 +1524,62 @@
       return offset - aRun->from;
   }
   
  -- (int)CG_pointToOffset:(const WebCoreTextRun *)run style:(const WebCoreTextStyle *)style position:(int)x reversed:(BOOL)reversed includePartialGlyphs:(BOOL)includePartialGlyphs
  +static bool advanceWidthIteratorOneCharacter(WidthIterator *iterator, float *totalWidth)
  +{
  +    float widths[MAX_GLYPH_EXPANSION];
  +    WebTextRenderer *renderers[MAX_GLYPH_EXPANSION];
  +    ATSGlyphRef glyphs[MAX_GLYPH_EXPANSION];            
  +    unsigned numGlyphs = advanceWidthIterator(iterator, iterator->currentCharacter + 1, widths, renderers, glyphs);
  +    unsigned i;
  +    float w = 0;
  +    for (i = 0; i < numGlyphs; ++i)
  +        w += widths[i];
  +    *totalWidth = w;
  +    return numGlyphs != 0;
  +}
  +
  +- (int)CG_pointToOffset:(const WebCoreTextRun *)run style:(const WebCoreTextStyle *)style position:(int)x reversed:(bool)reversed includePartialGlyphs:(bool)includePartialGlyphs
   {
       float delta = (float)x;
  -    unsigned offset = run->from;
  -    CharacterWidthIterator widthIterator;
  -    
  -    initializeCharacterWidthIterator(&widthIterator, self, run, style);
  +
  +    WidthIterator it;    
  +    initializeWidthIterator(&it, self, run, style);
  +
  +    unsigned offset;
   
       if (reversed) {
  -        float width = [self floatWidthForRun:run style:style widths:nil];
  -        delta -= width;
  -        while (offset < run->length) {
  -            float w = widthForNextCharacter(&widthIterator, 0, 0);
  -            if (w == INVALID_WIDTH) {
  -                // Something very bad happened, like we only have half of a surrogate pair.
  +        delta -= CG_floatWidthForRun(self, run, style, 0, 0, 0, 0, 0);
  +        while (1) {
  +            offset = it.currentCharacter;
  +            float w;
  +            if (!advanceWidthIteratorOneCharacter(&it, &w))
                   break;
  -            }
  -            else {
  -                if (w) {
  -                    if (includePartialGlyphs)
  -                       w -= w/2;
  -                    delta += w;
  -                    if (delta >= 0)
  -                        break;
  -                    if (includePartialGlyphs)
  -                        delta += w;
  -                }
  -                offset = widthIterator.currentCharacter;
  +            delta += w;
  +            if (includePartialGlyphs) {
  +                if (delta - w / 2 >= 0)
  +                    break;
  +            } else {
  +                if (delta >= 0)
  +                    break;
               }
           }
       } else {
  -        while (offset < run->length) {
  -            float w = widthForNextCharacter(&widthIterator, 0, 0);
  -            if (w == INVALID_WIDTH) {
  -                // Something very bad happened, like we only have half of a surrogate pair.
  +        while (1) {
  +            offset = it.currentCharacter;
  +            float w;
  +            if (!advanceWidthIteratorOneCharacter(&it, &w))
                   break;
  -            }
  -            else {
  -                if (w) {
  -                    if (includePartialGlyphs)
  -                        w -= w/2;
  -                    delta -= w;
  -                    if (delta <= 0) 
  -                        break;
  -                    if (includePartialGlyphs)
  -                        delta -= w;
  -                }
  -                offset = widthIterator.currentCharacter;
  +            delta -= w;
  +            if (includePartialGlyphs) {
  +                if (delta + w / 2 <= 0)
  +                    break;
  +            } else {
  +                if (delta <= 0)
  +                    break;
               }
           }
       }
  -    
  +
       return offset - run->from;
   }
   
  @@ -1661,29 +1607,25 @@
       }
   }
   
  -static inline ATSGlyphRef glyphForCharacter(GlyphMap *map, UnicodeChar c, WebTextRenderer **renderer)
  +static inline ATSGlyphRef glyphForCharacter(WebTextRenderer **renderer, UChar32 c)
   {
  -    if (map == 0)
  -        return nonGlyphID;
  -    
       // this loop is hot, so it is written to avoid LSU stalls
  -    while (map) {
  -        UnicodeChar start = map->startRange;
  -        GlyphMap *nextMap = map->next;
  +    GlyphMap *map;
  +    GlyphMap *nextMap;
  +    for (map = (*renderer)->characterToGlyphMap; map; map = nextMap) {
  +        UChar32 start = map->startRange;
  +        nextMap = map->next;
           if (c >= start && c <= map->endRange) {
               GlyphEntry *ge = &map->glyphs[c - start];
  -            WebTextRenderer *substituteRenderer = ge->substituteRenderer;
  -            if (substituteRenderer)
  -                *renderer = substituteRenderer;
  +            *renderer = ge->renderer;
               return ge->glyph;
           }
  -        map = nextMap;
       }
   
  -    return nonGlyphID;
  +    return [*renderer extendCharacterToGlyphMapToInclude:c];
   }
   
  -static void initializeCharacterWidthIterator(CharacterWidthIterator *iterator, WebTextRenderer *renderer, const WebCoreTextRun *run , const WebCoreTextStyle *style) 
  +static void initializeWidthIterator(WidthIterator *iterator, WebTextRenderer *renderer, const WebCoreTextRun *run, const WebCoreTextStyle *style) 
   {
       iterator->renderer = renderer;
       iterator->run = run;
  @@ -1693,42 +1635,37 @@
   
       // If the padding is non-zero, count the number of spaces in the run
       // and divide that by the padding for per space addition.
  -    iterator->padding = style->padding;
  -    if (iterator->padding > 0){
  -        uint numSpaces = 0;
  -        int from = run->from;
  -        int len = run->to - from;
  +    if (!style->padding) {
  +        iterator->padding = 0;
  +        iterator->padPerSpace = 0;
  +    } else {
  +        float numSpaces = 0;
           int k;
  -        for (k = from; k < from + len; k++) {
  -            if (isSpace(run->characters[k])) {
  +        for (k = run->from; k < run->to; k++)
  +            if (isSpace(run->characters[k]))
                   numSpaces++;
  -            }
  -        }
  -        iterator->padPerSpace = ceilf((((float)style->padding) / ((float)numSpaces)));
  -    }
  -    else {
  -        iterator->padPerSpace = 0;
  +
  +        iterator->padding = style->padding;
  +        iterator->padPerSpace = ceilf(iterator->padding / numSpaces);
       }
       
       // Calculate width up to starting position of the run.  This is
       // necessary to ensure that our rounding hacks are always consistently
       // applied.
  -    if (run->from != 0){
  +    if (run->from == 0) {
  +        iterator->widthToStart = 0;
  +    } else {
           WebCoreTextRun startPositionRun = *run;
           startPositionRun.from = 0;
  -        startPositionRun.to = run->from;
  -        CharacterWidthIterator startPositionIterator;
  -        initializeCharacterWidthIterator(&startPositionIterator, renderer, &startPositionRun, style);
  -        
  -        while (startPositionIterator.currentCharacter < (unsigned)startPositionRun.to)
  -            widthForNextCharacter(&startPositionIterator, 0, 0);
  +        startPositionRun.to = run->length;
  +        WidthIterator startPositionIterator;
  +        initializeWidthIterator(&startPositionIterator, renderer, &startPositionRun, style);
  +        advanceWidthIterator(&startPositionIterator, run->to, 0, 0, 0);
           iterator->widthToStart = startPositionIterator.runWidthSoFar;
       }
  -    else
  -        iterator->widthToStart = 0;
   }
   
  -static void createATSULayoutParameters(ATSULayoutParameters *params, WebTextRenderer *renderer, const WebCoreTextRun *run , const WebCoreTextStyle *style) 
  +static void createATSULayoutParameters(ATSULayoutParameters *params, WebTextRenderer *renderer, const WebCoreTextRun *run, const WebCoreTextStyle *style) 
   {
       params->renderer = renderer;
       params->run = run;
  @@ -1742,198 +1679,202 @@
       ATSUDisposeTextLayout(params->layout);
   }
   
  -static inline float ceilCurrentWidth(CharacterWidthIterator *iterator)
  +static UChar32 normalizeVoicingMarks(WidthIterator *iterator)
   {
  -    float totalWidth = iterator->widthToStart + iterator->runWidthSoFar;
  -    float delta = ceilf(totalWidth) - totalWidth;
  -    iterator->runWidthSoFar += delta;
  -    return delta;
  +    unsigned currentCharacter = iterator->currentCharacter;
  +    const WebCoreTextRun *run = iterator->run;
  +    if (currentCharacter + 1 < (unsigned)run->to) {
  +        if (u_getCombiningClass(run->characters[currentCharacter + 1]) == HIRAGANA_KATAKANA_VOICING_MARKS) {
  +            // Normalize into composed form using 3.2 rules.
  +            UChar normalizedCharacters[2] = { 0, 0 };
  +            UErrorCode uStatus = 0;                
  +            int32_t resultLength = unorm_normalize(&run->characters[currentCharacter], 2,
  +                UNORM_NFC, UNORM_UNICODE_3_2, &normalizedCharacters[0], 2, &uStatus);
  +            if (resultLength == 1 && uStatus == 0)
  +                return normalizedCharacters[0];
  +        }
  +    }
  +    return 0;
   }
   
  -// Return INVALID_WIDTH if an error is encountered or we're at the end of the range in the run.
  -static float widthForNextCharacter(CharacterWidthIterator *iterator, ATSGlyphRef *glyphUsed, WebTextRenderer **rendererUsed)
  +static unsigned advanceWidthIterator(WidthIterator *iterator, unsigned offset, float *widths, WebTextRenderer **renderersUsed, ATSGlyphRef *glyphsUsed)
   {
  -    WebTextRenderer *renderer = iterator->renderer;
       const WebCoreTextRun *run = iterator->run;
  -    const WebCoreTextStyle *style = iterator->style;
  -    unsigned currentCharacter = iterator->currentCharacter;
  +    if (offset > (unsigned)run->to)
  +        offset = run->to;
   
  -    ATSGlyphRef glyph = 0;
  -    
  -    // Check for end of run.
  -    if (currentCharacter >= (unsigned)run->to)
  -        return INVALID_WIDTH;
  +    unsigned numGlyphs = 0;
   
  +    unsigned currentCharacter = iterator->currentCharacter;
       const UniChar *cp = &run->characters[currentCharacter];
  -    
  -    UnicodeChar c = *cp;
   
  -    if (U16_IS_TRAIL(c))
  -        return INVALID_WIDTH;
  +    const WebCoreTextStyle *style = iterator->style;
  +    bool needCharTransform = style->rtl | style->smallCaps;
  +    bool hasExtraSpacing = style->letterSpacing | style->wordSpacing | style->padding;
  +
  +    float runWidthSoFar = iterator->runWidthSoFar;
   
  -    // Do we have a surrogate pair?  If so, determine the full Unicode (32 bit)
  -    // code point before glyph lookup.
  -    unsigned clusterLength = 1;
  -    if (U16_IS_LEAD(c)) {
  -        // Make sure we have another character and it's a low surrogate.
  -        if (currentCharacter + 1 >= run->length)
  -            return INVALID_WIDTH;
  -        UniChar low = cp[1];
  -        if (!U16_IS_TRAIL(low))
  -            return INVALID_WIDTH;
  -        c = U16_GET_SUPPLEMENTARY(c, low);
  -        clusterLength = 2;
  -    }
  -
  -    // Deal with Hiragana and Katakana voiced and semi-voiced syllables.
  -    // Normalize into composed form, and then look for glyph with base + combined mark.
  -    if (c >= 0x3041 && c <= 0x30FE) { // Early out to minimize performance impact. Do we have a Hiragana/Katakana character?
  -        if (currentCharacter < (unsigned)run->to) {
  -            UnicodeChar nextCharacter = run->characters[currentCharacter+1];
  -            if (u_getCombiningClass(nextCharacter) == HIRAGANA_KATAKANA_VOICING_MARKS) {
  -                // Normalize into composed form using 3.2 rules.
  -                UChar normalizedCharacters[2] = { 0, 0 };
  -                UErrorCode uStatus = 0;                
  -                int32_t resultLength = unorm_normalize(&run->characters[currentCharacter], 2,
  -                    UNORM_NFC, UNORM_UNICODE_3_2, &normalizedCharacters[0], 2, &uStatus);
  -                if (resultLength == 1 && uStatus == 0) {
  -                    c = normalizedCharacters[0];
  +    while (currentCharacter < offset) {
  +        UChar32 c = *cp;
  +
  +        unsigned clusterLength = 1;
  +        if (c >= 0x3041) {
  +            if (c <= 0x30FE) {
  +                // Deal with Hiragana and Katakana voiced and semi-voiced syllables.
  +                // Normalize into composed form, and then look for glyph with base + combined mark.
  +                // Check above for character range to minimize performance impact.
  +                UChar32 normalized = normalizeVoicingMarks(iterator);
  +                if (normalized) {
  +                    c = normalized;
                       clusterLength = 2;
                   }
  +            } else if (U16_IS_SURROGATE(c)) {
  +                if (!U16_IS_SURROGATE_LEAD(c))
  +                    break;
  +
  +                // Do we have a surrogate pair?  If so, determine the full Unicode (32 bit)
  +                // code point before glyph lookup.
  +                // Make sure we have another character and it's a low surrogate.
  +                if (currentCharacter + 1 >= run->length)
  +                    break;
  +                UniChar low = cp[1];
  +                if (!U16_IS_TRAIL(low))
  +                    break;
  +                c = U16_GET_SUPPLEMENTARY(c, low);
  +                clusterLength = 2;
               }
           }
  -    }
   
  -    if (style->rtl)
  -        c = u_charMirror(c);
  -    
  -    // If small-caps, convert lowercase to upper.
  -    if (style->smallCaps && !u_isUUppercase(c)) {
  -        UnicodeChar newC = u_toupper(c);
  -        if (newC != c) {
  -            c = newC;
  -            renderer = [renderer smallCapsRenderer];
  +        WebTextRenderer *renderer = iterator->renderer;
  +
  +        if (needCharTransform) {
  +            if (style->rtl)
  +                c = u_charMirror(c);
  +
  +            // If small-caps, convert lowercase to upper.
  +            if (style->smallCaps && !u_isUUppercase(c)) {
  +                UChar32 upperC = u_toupper(c);
  +                if (upperC != c) {
  +                    c = upperC;
  +                    renderer = [renderer smallCapsRenderer];
  +                }
  +            }
           }
  -    }
  -    
  -    glyph = glyphForCharacter(renderer->characterToGlyphMap, c, &renderer);
  -    if (glyph == nonGlyphID)
  -        glyph = [renderer extendCharacterToGlyphMapToInclude:c];
  -
  -    // Now that we have glyph and font, get its width.
  -    WebGlyphWidth width;
  -    if (style->tabWidth != 0.0F && c == '\t') {
  -        width = style->tabWidth - fmodf(style->xpos+iterator->runWidthSoFar, style->tabWidth);
  -    } else {
  -        width = widthForGlyph(renderer, glyph);
  -        // We special case spaces in two ways when applying word rounding.
  -        // First, we round spaces to an adjusted width in all fonts.
  -        // Second, in fixed-pitch fonts we ensure that all characters that
  -        // match the width of the space character have the same width as the space character.
  -        if (style->applyWordRounding && (renderer->treatAsFixedPitch ? width == renderer->spaceWidth : glyph == renderer->spaceGlyph))
  -            width = renderer->adjustedSpaceWidth;
  -    }
  -    
  -    // Try to find a substitute font if this font didn't have a glyph for a character in the
  -    // string.  If one isn't found we end up drawing and measuring the 0 glyph, usually a box.
  -    if (glyph == 0 && style->attemptFontSubstitution) {
  -        UniChar characterArray[2];
  -        unsigned characterArrayLength;
  -        
  -        if (c <= 0xFFFF) {
  -            characterArray[0] = c;
  -            characterArrayLength = 1;
  +
  +        ATSGlyphRef glyph = glyphForCharacter(&renderer, c);
  +
  +        // Now that we have glyph and font, get its width.
  +        WebGlyphWidth width;
  +        if (c == '\t' && style->tabWidth) {
  +            width = style->tabWidth - fmodf(style->xpos + runWidthSoFar, style->tabWidth);
           } else {
  -            characterArray[0] = U16_LEAD(c);
  -            characterArray[1] = U16_TRAIL(c);
  -            characterArrayLength = 2;
  -        }
  -        
  -        WebTextRenderer *substituteRenderer = [renderer substituteRendererForCharacters:characterArray
  -            length:characterArrayLength families:style->families];
  -        if (substituteRenderer) {
  -            WebCoreTextRun clusterRun;
  -            WebCoreInitializeTextRun(&clusterRun, characterArray, characterArrayLength, 0, characterArrayLength);
  -            WebCoreTextStyle clusterStyle = *iterator->style;
  -            clusterStyle.padding = 0;
  -            clusterStyle.applyRunRounding = false;
  -            clusterStyle.attemptFontSubstitution = false;
  -            
  -            int cNumGlyphs;
  -            ATSGlyphRef localGlyphBuffer[MAX_GLYPH_EXPANSION];            
  -            width = floatWidthForRun(substituteRenderer, &clusterRun, &clusterStyle, 0, 0, localGlyphBuffer, 0, &cNumGlyphs);
  -            if (cNumGlyphs == 1) {
  -                glyph = localGlyphBuffer[0];
  -                [renderer updateGlyphEntryForCharacter:c glyphID:glyph substituteRenderer:substituteRenderer];
  -                renderer = substituteRenderer;
  -            }
  +            width = widthForGlyph(renderer, glyph);
  +            // We special case spaces in two ways when applying word rounding.
  +            // First, we round spaces to an adjusted width in all fonts.
  +            // Second, in fixed-pitch fonts we ensure that all characters that
  +            // match the width of the space character have the same width as the space character.
  +            if (width == renderer->spaceWidth && (renderer->treatAsFixedPitch || glyph == renderer->spaceGlyph) && style->applyWordRounding)
  +                width = renderer->adjustedSpaceWidth;
           }
  -    }
   
  -    // Force characters that are used to determine word boundaries for the rounding hack
  -    // to be integer width, so following words will start on an integer boundary.
  -    if (style->applyWordRounding && isRoundingHackCharacter(c))
  -        width = ceilf(width);
  -    
  -    // Account for letter-spacing
  -    if (style->letterSpacing && width > 0)
  -        width += style->letterSpacing;
  -
  -    // Account for padding. WebCore uses space padding to justify text.
  -    // We distribute the specified padding over the available spaces in the run.
  -    if (isSpace(c)) {
  -        if (iterator->padding > 0) {
  -            // Only use left over padding if note evenly divisible by 
  -            // number of spaces.
  -            if (iterator->padding < iterator->padPerSpace){
  -                width += iterator->padding;
  -                iterator->padding = 0;
  -            } else {
  -                width += iterator->padPerSpace;
  -                iterator->padding -= iterator->padPerSpace;
  +        // Try to find a substitute font if this font didn't have a glyph for a character in the
  +        // string. If one isn't found we end up drawing and measuring the 0 glyph, usually a box.
  +        if (glyph == 0 && style->attemptFontSubstitution) {
  +            WebTextRenderer *substituteRenderer = [renderer substituteRendererForCharacters:cp
  +                length:clusterLength families:style->families];
  +            if (substituteRenderer) {
  +                WebCoreTextRun clusterRun = { cp, clusterLength, 0, clusterLength };
  +                WebCoreTextStyle clusterStyle = *style;
  +                clusterStyle.padding = 0;
  +                clusterStyle.applyRunRounding = NO;
  +                clusterStyle.attemptFontSubstitution = NO;
  +                
  +                int cNumGlyphs;
  +                float localWidthBuffer[MAX_GLYPH_EXPANSION];
  +                WebTextRenderer *localRendererBuffer[MAX_GLYPH_EXPANSION];
  +                ATSGlyphRef localGlyphBuffer[MAX_GLYPH_EXPANSION];            
  +                CG_floatWidthForRun(substituteRenderer, &clusterRun, &clusterStyle, localWidthBuffer, localRendererBuffer, localGlyphBuffer, 0, &cNumGlyphs);
  +                if (cNumGlyphs == 1) {
  +                    ASSERT(substituteRenderer == localRendererBuffer[0]);
  +                    width = localWidthBuffer[0];
  +                    glyph = localGlyphBuffer[0];
  +                    [renderer updateGlyphEntryForCharacter:c glyphID:glyph substituteRenderer:substituteRenderer];
  +                    renderer = substituteRenderer;
  +                }
               }
           }
  -        
  -        // Account for word-spacing.  We apply additional space between "words" by
  -        // adding width to the space character.
  -        if (currentCharacter > 0 && !isSpace(cp[-1]))
  -            width += style->wordSpacing;
  -    }
   
  -    iterator->runWidthSoFar += width;
  +        if (hasExtraSpacing) {
  +            // Account for letter-spacing.
  +            if (width && style->letterSpacing)
  +                width += style->letterSpacing;
  +
  +            if (isSpace(c)) {
  +                // Account for padding. WebCore uses space padding to justify text.
  +                // We distribute the specified padding over the available spaces in the run.
  +                if (style->padding) {
  +                    // Use left over padding if not evenly divisible by number of spaces.
  +                    if (iterator->padding < iterator->padPerSpace) {
  +                        width += iterator->padding;
  +                        iterator->padding = 0;
  +                    } else {
  +                        width += iterator->padPerSpace;
  +                        iterator->padding -= iterator->padPerSpace;
  +                    }
  +                }
   
  -    // Advance past the character we just dealt with.
  -    currentCharacter += clusterLength;
  -    iterator->currentCharacter = currentCharacter;
  +                // Account for word spacing.
  +                // We apply additional space between "words" by adding width to the space character.
  +                if (currentCharacter != 0 && !isSpace(cp[-1]) && style->wordSpacing)
  +                    width += style->wordSpacing;
  +            }
  +        }
   
  -    // Account for float/integer impedance mismatch between CG and khtml.  "Words" (characters 
  -    // followed by a character defined by isSpace()) are always an integer width.  We adjust the 
  -    // width of the last character of a "word" to ensure an integer width.  When we move khtml to
  -    // floats we can remove this (and related) hacks.
  -    //
  -    // Check to see if the next character is a "RoundingHackCharacter", if so, adjust.
  -    if (style->applyWordRounding && currentCharacter < run->length && isRoundingHackCharacter(cp[clusterLength])) {
  -        float delta = ceilCurrentWidth(iterator);
  -        if (delta)
  -            width += delta;
  -    } else {
  -        if (style->applyRunRounding && currentCharacter >= (unsigned)run->to && (run->length == 1 || run->to - run->from > 1)) {
  -            float delta = ceilCurrentWidth(iterator);
  -            if (delta)
  -                width += delta;
  +        // Advance past the character we just dealt with.
  +        cp += clusterLength;
  +        currentCharacter += clusterLength;
  +
  +        // Account for float/integer impedance mismatch between CG and KHTML. "Words" (characters 
  +        // followed by a character defined by isRoundingHackCharacter()) are always an integer width.
  +        // We adjust the width of the last character of a "word" to ensure an integer width.
  +        // If we move KHTML to floats we can remove this (and related) hacks.
  +
  +        // Force characters that are used to determine word boundaries for the rounding hack
  +        // to be integer width, so following words will start on an integer boundary.
  +        if (style->applyWordRounding && isRoundingHackCharacter(c))
  +            width = ceilf(width);
  +
  +        // Check to see if the next character is a "rounding hack character", if so, adjust
  +        // width so that the total run width will be on an integer boundary.
  +        if ((style->applyWordRounding && currentCharacter < run->length && isRoundingHackCharacter(*cp))
  +                || (style->applyRunRounding && currentCharacter >= (unsigned)run->to && (run->length == 1 || run->to - run->from > 1))) {
  +            float totalWidth = iterator->widthToStart + runWidthSoFar + width;
  +            width += ceilf(totalWidth) - totalWidth;
  +        }
  +
  +        runWidthSoFar += width;
  +
  +        if (!widths) {
  +            ASSERT(!renderersUsed);
  +            ASSERT(!glyphsUsed);
  +        } else {
  +            ASSERT(renderersUsed);
  +            ASSERT(glyphsUsed);
  +            *widths++ = width;
  +            *renderersUsed++ = renderer;
  +            *glyphsUsed++ = glyph;
           }
  +
  +        ++numGlyphs;
       }
   
  -    if (rendererUsed)
  -        *rendererUsed = renderer;
  -    
  -    if (glyphUsed)
  -        *glyphUsed = glyph;
  +    iterator->currentCharacter = currentCharacter;
  +    iterator->runWidthSoFar = runWidthSoFar;
   
  -    return width;
  +    return numGlyphs;
   }
   
  -static BOOL fillStyleWithAttributes(ATSUStyle style, NSFont *theFont)
  +static bool fillStyleWithAttributes(ATSUStyle style, NSFont *theFont)
   {
       if (!theFont)
           return NO;
  @@ -1952,7 +1893,7 @@
       return YES;
   }
   
  -static BOOL shouldUseATSU(const WebCoreTextRun *run)
  +static bool shouldUseATSU(const WebCoreTextRun *run)
   {
       if (alwaysUseATSU)
           return YES;
  
  
  



More information about the webkit-changes mailing list