Bug 8845. Define a TextRun (similar to the old WebCoreTextRun) and
authorhyatt <hyatt@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 11 May 2006 10:19:34 +0000 (10:19 +0000)
committerhyatt <hyatt@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 11 May 2006 10:19:34 +0000 (10:19 +0000)
        make it the new API for Font and GraphicsContext when drawing/measuring
        text.

        Reviewed by andersca

        * platform/Font.cpp:
        (WebCore::m_finalRoundingWidth):
        (WebCore::WidthIterator::advance):
        (WebCore::WidthIterator::normalizeVoicingMarks):
        (WebCore::Font::width):
        (WebCore::Font::canUseGlyphCache):
        (WebCore::Font::drawSimpleText):
        (WebCore::Font::drawText):
        (WebCore::Font::floatWidth):
        (WebCore::Font::floatWidthForSimpleText):
        * platform/Font.h:
        (WebCore::TextRun::m_to):
        (WebCore::TextRun::operator[]):
        (WebCore::TextRun::data):
        (WebCore::TextRun::adjustFrom):
        (WebCore::TextRun::adjustTo):
        (WebCore::TextRun::characters):
        (WebCore::TextRun::length):
        (WebCore::TextRun::from):
        (WebCore::TextRun::to):
        * platform/GraphicsContext.cpp:
        (WebCore::GraphicsContext::drawText):
        (WebCore::GraphicsContext::drawHighlightForText):
        * platform/GraphicsContext.h:
        * platform/mac/FontMac.mm:
        (WebCore::addDirectionalOverride):
        (WebCore::overrideLayoutOperation):
        (WebCore::ATSULayoutParameters::initialize):
        (WebCore::Font::selectionRectForText):
        (WebCore::Font::drawComplexText):
        (WebCore::Font::drawHighlightForText):
        (WebCore::Font::floatWidthForComplexText):
        (WebCore::Font::checkSelectionPoint):
        * platform/win/FontWin.cpp:
        (WebCore::hackishExtentForString):
        (WebCore::Font::floatWidth):
        (WebCore::Font::drawText):
        (WebCore::Font::drawHighlightForText):
        (WebCore::Font::selectionRectForText):
        (WebCore::Font::checkSelectionPoint):
        * rendering/InlineTextBox.cpp:
        (WebCore::InlineTextBox::selectionRect):
        (WebCore::InlineTextBox::paint):
        (WebCore::InlineTextBox::paintSelection):
        (WebCore::InlineTextBox::paintMarkedTextBackground):
        (WebCore::InlineTextBox::paintTextMatchMarker):
        (WebCore::InlineTextBox::offsetForPosition):
        (WebCore::InlineTextBox::positionForOffset):
        * rendering/RenderBlock.cpp:
        (WebCore::stripTrailingSpace):
        * rendering/RenderFlexibleBox.cpp:
        (WebCore::RenderFlexibleBox::layoutVerticalBox):
        * rendering/RenderImage.cpp:
        (WebCore::RenderImage::imageChanged):
        (WebCore::RenderImage::paint):
        * rendering/RenderText.cpp:
        (WebCore::RenderText::cacheWidths):
        (WebCore::RenderText::widthFromCache):
        (WebCore::RenderText::trimmedMinMaxWidth):
        (WebCore::RenderText::calcMinMaxWidth):
        (WebCore::RenderText::width):
        * rendering/RenderTextField.cpp:
        (WebCore::RenderTextField::calcMinMaxWidth):
        * rendering/bidi.cpp:
        (WebCore::RenderBlock::tabWidth):
        (WebCore::RenderBlock::checkLinesForTextOverflow):
        * rendering/render_line.cpp:
        (WebCore::EllipsisBox::paint):
        * rendering/render_list.cpp:
        (WebCore::RenderListMarker::paint):
        (WebCore::RenderListMarker::calcMinMaxWidth):
        (WebCore::RenderListMarker::getRelativeMarkerRect):

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@14297 268f45cc-cd09-0410-ab3c-d52691b4dbfc

16 files changed:
WebCore/ChangeLog
WebCore/platform/Font.cpp
WebCore/platform/Font.h
WebCore/platform/GraphicsContext.cpp
WebCore/platform/GraphicsContext.h
WebCore/platform/mac/FontMac.mm
WebCore/platform/win/FontWin.cpp
WebCore/rendering/InlineTextBox.cpp
WebCore/rendering/RenderBlock.cpp
WebCore/rendering/RenderFlexibleBox.cpp
WebCore/rendering/RenderImage.cpp
WebCore/rendering/RenderText.cpp
WebCore/rendering/RenderTextField.cpp
WebCore/rendering/bidi.cpp
WebCore/rendering/render_line.cpp
WebCore/rendering/render_list.cpp

index 336196f9f841a11933df7dcfcfc46735ffe9f501..6a17c583b37a080e292daa8fdc089eb708cda4e0 100644 (file)
@@ -1,3 +1,84 @@
+2006-05-11  David Hyatt  <hyatt@apple.com>
+
+        Bug 8845.  Define a TextRun (similar to the old WebCoreTextRun) and
+        make it the new API for Font and GraphicsContext when drawing/measuring
+        text.
+
+        Reviewed by andersca
+
+        * platform/Font.cpp:
+        (WebCore::m_finalRoundingWidth):
+        (WebCore::WidthIterator::advance):
+        (WebCore::WidthIterator::normalizeVoicingMarks):
+        (WebCore::Font::width):
+        (WebCore::Font::canUseGlyphCache):
+        (WebCore::Font::drawSimpleText):
+        (WebCore::Font::drawText):
+        (WebCore::Font::floatWidth):
+        (WebCore::Font::floatWidthForSimpleText):
+        * platform/Font.h:
+        (WebCore::TextRun::m_to):
+        (WebCore::TextRun::operator[]):
+        (WebCore::TextRun::data):
+        (WebCore::TextRun::adjustFrom):
+        (WebCore::TextRun::adjustTo):
+        (WebCore::TextRun::characters):
+        (WebCore::TextRun::length):
+        (WebCore::TextRun::from):
+        (WebCore::TextRun::to):
+        * platform/GraphicsContext.cpp:
+        (WebCore::GraphicsContext::drawText):
+        (WebCore::GraphicsContext::drawHighlightForText):
+        * platform/GraphicsContext.h:
+        * platform/mac/FontMac.mm:
+        (WebCore::addDirectionalOverride):
+        (WebCore::overrideLayoutOperation):
+        (WebCore::ATSULayoutParameters::initialize):
+        (WebCore::Font::selectionRectForText):
+        (WebCore::Font::drawComplexText):
+        (WebCore::Font::drawHighlightForText):
+        (WebCore::Font::floatWidthForComplexText):
+        (WebCore::Font::checkSelectionPoint):
+        * platform/win/FontWin.cpp:
+        (WebCore::hackishExtentForString):
+        (WebCore::Font::floatWidth):
+        (WebCore::Font::drawText):
+        (WebCore::Font::drawHighlightForText):
+        (WebCore::Font::selectionRectForText):
+        (WebCore::Font::checkSelectionPoint):
+        * rendering/InlineTextBox.cpp:
+        (WebCore::InlineTextBox::selectionRect):
+        (WebCore::InlineTextBox::paint):
+        (WebCore::InlineTextBox::paintSelection):
+        (WebCore::InlineTextBox::paintMarkedTextBackground):
+        (WebCore::InlineTextBox::paintTextMatchMarker):
+        (WebCore::InlineTextBox::offsetForPosition):
+        (WebCore::InlineTextBox::positionForOffset):
+        * rendering/RenderBlock.cpp:
+        (WebCore::stripTrailingSpace):
+        * rendering/RenderFlexibleBox.cpp:
+        (WebCore::RenderFlexibleBox::layoutVerticalBox):
+        * rendering/RenderImage.cpp:
+        (WebCore::RenderImage::imageChanged):
+        (WebCore::RenderImage::paint):
+        * rendering/RenderText.cpp:
+        (WebCore::RenderText::cacheWidths):
+        (WebCore::RenderText::widthFromCache):
+        (WebCore::RenderText::trimmedMinMaxWidth):
+        (WebCore::RenderText::calcMinMaxWidth):
+        (WebCore::RenderText::width):
+        * rendering/RenderTextField.cpp:
+        (WebCore::RenderTextField::calcMinMaxWidth):
+        * rendering/bidi.cpp:
+        (WebCore::RenderBlock::tabWidth):
+        (WebCore::RenderBlock::checkLinesForTextOverflow):
+        * rendering/render_line.cpp:
+        (WebCore::EllipsisBox::paint):
+        * rendering/render_list.cpp:
+        (WebCore::RenderListMarker::paint):
+        (WebCore::RenderListMarker::calcMinMaxWidth):
+        (WebCore::RenderListMarker::getRelativeMarkerRect):
+
 2006-05-10  Justin Garcia  <justin.garcia@apple.com>
 
         Reviewed by darin
index 9d4caedfd3508b62a8f869e5bd5f62ce196f3584..d0c2658e96e9c4ef16a3b83e697fe3a3520ec810 100644 (file)
@@ -56,7 +56,7 @@ const uint8_t Font::gRoundingHackCharacterTable[256] = {
 };
 
 struct WidthIterator {
-    WidthIterator(const Font* font, const UChar* str, int from, int to, int len,
+    WidthIterator(const Font* font, const TextRun& run,
                   int tabWidth, int xpos, int toAdd, TextDirection dir, bool visuallyOrdered,
                   bool applyWordRounding, bool applyRunRounding, const FontData* substituteFontData);
 
@@ -64,10 +64,9 @@ struct WidthIterator {
 
     const Font* m_font;
 
-    const UChar* m_characters;
-    int m_from;
-    int m_to;
-    int m_len;
+    const TextRun& m_run;
+    int m_end;
+
     int m_tabWidth;
     int m_xPos;
     int m_toAdd;
@@ -88,13 +87,13 @@ private:
     UChar32 normalizeVoicingMarks();
 };
 
-WidthIterator::WidthIterator(const Font* font, const UChar* str, int from, int to, int len,
+WidthIterator::WidthIterator(const Font* font, const TextRun& run,
                              int tabWidth, int xpos, int toAdd, TextDirection dir, bool visuallyOrdered,
                              bool applyWordRounding, bool applyRunRounding, const FontData* substituteFontData)
-:m_font(font), m_characters((const UChar*)str), m_from(from), m_to(to), m_len(len),
+:m_font(font), m_run(run), m_end(dir == LTR ? run.to() : run.length()),
  m_tabWidth(tabWidth), m_xPos(xpos), m_toAdd(toAdd), m_dir(dir), m_visuallyOrdered(visuallyOrdered),
  m_applyWordRounding(applyWordRounding), m_applyRunRounding(applyRunRounding), m_substituteFontData(substituteFontData),
- m_currentCharacter(from), m_runWidthSoFar(0), m_finalRoundingWidth(0)
+ m_currentCharacter(run.from()), m_runWidthSoFar(0), m_finalRoundingWidth(0)
 {
     // If the padding is non-zero, count the number of spaces in the run
     // and divide that by the padding for per space addition.
@@ -103,8 +102,8 @@ WidthIterator::WidthIterator(const Font* font, const UChar* str, int from, int t
         m_padPerSpace = 0;
     } else {
         float numSpaces = 0;
-        for (int i = from; i < to; i++)
-            if (Font::treatAsSpace(m_characters[i]))
+        for (int i = run.from(); i < m_end; i++)
+            if (Font::treatAsSpace(m_run[i]))
                 numSpaces++;
 
         m_padding = toAdd;
@@ -114,23 +113,24 @@ WidthIterator::WidthIterator(const Font* font, const UChar* str, int from, int t
     // Calculate width up to starting position of the run.  This is
     // necessary to ensure that our rounding hacks are always consistently
     // applied.
-    if (m_from == 0)
+    if (run.from() == 0)
         m_widthToStart = 0;
     else {
-        WidthIterator startPositionIterator(font, str, 0, len, len, tabWidth, xpos, toAdd, dir, visuallyOrdered,
+        TextRun completeRun(run.characters(), run.length());
+        WidthIterator startPositionIterator(font, completeRun, tabWidth, xpos, toAdd, dir, visuallyOrdered,
                                             applyWordRounding, applyRunRounding, substituteFontData);
-        startPositionIterator.advance(from);
+        startPositionIterator.advance(run.from());
         m_widthToStart = startPositionIterator.m_runWidthSoFar;
     }
 }
 
 void WidthIterator::advance(int offset, GlyphBuffer* glyphBuffer)
 {
-    if (offset > m_to)
-        offset = m_to;
+    if (offset > m_end)
+        offset = m_end;
 
     int currentCharacter = m_currentCharacter;
-    const UChar* cp = &m_characters[currentCharacter];
+    const UChar* cp = m_run.data(currentCharacter);
 
     bool rtl = (m_dir == RTL);
     bool needCharTransform = rtl || m_font->isSmallCaps();
@@ -161,7 +161,7 @@ void WidthIterator::advance(int offset, GlyphBuffer* glyphBuffer)
                 // 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 >= m_len)
+                if (currentCharacter + 1 >= m_run.length())
                     break;
                 UniChar low = cp[1];
                 if (!U16_IS_TRAIL(low))
@@ -197,7 +197,7 @@ void WidthIterator::advance(int offset, GlyphBuffer* glyphBuffer)
             const FontData* substituteFontData = fontData->findSubstituteFontData(cp, clusterLength, m_font->fontDescription());
             if (substituteFontData) {
                 GlyphBuffer localGlyphBuffer;
-                m_font->floatWidthForSimpleText((UChar*)cp, clusterLength, 0, clusterLength, 0, 0, 0, m_dir, m_visuallyOrdered, 
+                m_font->floatWidthForSimpleText(TextRun((UChar*)cp, clusterLength), 0, 0, 0, m_dir, m_visuallyOrdered, 
                                                  m_applyWordRounding, false, substituteFontData, 0, &localGlyphBuffer);
                 if (localGlyphBuffer.size() == 1) {
                     assert(substituteFontData == localGlyphBuffer.fontDataAt(0));
@@ -266,8 +266,8 @@ void WidthIterator::advance(int offset, GlyphBuffer* glyphBuffer)
 
         // 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 ((m_applyWordRounding && currentCharacter < m_len && Font::isRoundingHackCharacter(*cp))
-                || (m_applyRunRounding && currentCharacter >= m_to)) {
+        if ((m_applyWordRounding && currentCharacter < m_run.length() && Font::isRoundingHackCharacter(*cp))
+                || (m_applyRunRounding && currentCharacter >= m_end)) {
             float totalWidth = m_widthToStart + runWidthSoFar + width;
             width += ceilf(totalWidth) - totalWidth;
         }
@@ -288,12 +288,12 @@ void WidthIterator::advance(int offset, GlyphBuffer* glyphBuffer)
 UChar32 WidthIterator::normalizeVoicingMarks()
 {
     int currentCharacter = m_currentCharacter;
-    if (currentCharacter + 1 < m_to) {
-        if (u_getCombiningClass(m_characters[currentCharacter + 1]) == HIRAGANA_KATAKANA_VOICING_MARKS) {
+    if (currentCharacter + 1 < m_end) {
+        if (u_getCombiningClass(m_run[currentCharacter + 1]) == HIRAGANA_KATAKANA_VOICING_MARKS) {
             // Normalize into composed form using 3.2 rules.
             UChar normalizedCharacters[2] = { 0, 0 };
             UErrorCode uStatus = (UErrorCode)0;  
-            int32_t resultLength = unorm_normalize(&m_characters[currentCharacter], 2,
+            int32_t resultLength = unorm_normalize(m_run.data(currentCharacter), 2,
                 UNORM_NFC, UNORM_UNICODE_3_2, &normalizedCharacters[0], 2, &uStatus);
             if (resultLength == 1 && uStatus == 0)
                 return normalizedCharacters[0];
@@ -356,13 +356,13 @@ void Font::update() const
     m_fontList->invalidate();
 }
 
-int Font::width(const UChar* chs, int slen, int pos, int len, int tabWidth, int xpos) const
+int Font::width(const TextRun& run, int tabWidth, int xpos) const
 {
     // FIXME: Want to define an lroundf for win32.
 #if __APPLE__
-    return lroundf(floatWidth(chs + pos, slen - pos, 0, len, tabWidth, xpos));
+    return lroundf(floatWidth(run, tabWidth, xpos));
 #else
-    return floatWidth(chs + pos, slen - pos, 0, len, tabWidth, xpos) + 0.5f;
+    return floatWidth(run, tabWidth, xpos) + 0.5f;
 #endif
 }
 
@@ -404,14 +404,14 @@ void Font::setAlwaysUseComplexPath(bool alwaysUse)
     gAlwaysUseComplexPath = alwaysUse;
 }
 
-bool Font::canUseGlyphCache(const UChar* str, int to) const
+bool Font::canUseGlyphCache(const TextRun& run) const
 {
     if (gAlwaysUseComplexPath)
         return false;
     
     // Start from 0 since drawing and highlighting also measure the characters before run->from
-    for (int i = 0; i < to; i++) {
-        UChar c = str[i];
+    for (int i = 0; i < run.to(); i++) {
+        const UChar c = run[i];
         if (c < 0x300)      // U+0300 through U+036F Combining diacritical marks
             continue;
         if (c <= 0x36F)
@@ -457,7 +457,7 @@ bool Font::canUseGlyphCache(const UChar* str, int to) const
 
 }
 
-void Font::drawSimpleText(GraphicsContext* context, const IntPoint& point, int tabWidth, int xpos, const UChar* str, int len, int from, int to,
+void Font::drawSimpleText(GraphicsContext* context, const TextRun& run, const IntPoint& point, int tabWidth, int xpos,
                           int toAdd, TextDirection dir, bool visuallyOrdered) const
 {
     // This glyph buffer holds our glyphs+advances+font data for each glyph.
@@ -465,7 +465,7 @@ void Font::drawSimpleText(GraphicsContext* context, const IntPoint& point, int t
 
     // Our measuring code will generate glyphs and advances for us.
     float startX;
-    floatWidthForSimpleText(str, len, from, to, tabWidth, xpos, toAdd, dir, visuallyOrdered, 
+    floatWidthForSimpleText(run, tabWidth, xpos, toAdd, dir, visuallyOrdered, 
                             true, true, 0,
                             &startX, &glyphBuffer);
     
@@ -502,48 +502,40 @@ void Font::drawSimpleText(GraphicsContext* context, const IntPoint& point, int t
     drawGlyphs(context, fontData, glyphBuffer, lastFrom, nextGlyph - lastFrom, startPoint);
 }
 
-void Font::drawText(GraphicsContext* context, const IntPoint& point, int tabWidth, int xpos, const UChar* str, int len, int from, int to,
+void Font::drawText(GraphicsContext* context, const TextRun& run, const IntPoint& point, int tabWidth, int xpos,
                     int toAdd, TextDirection d, bool visuallyOrdered) const
 {
-    if (len == 0)
-        return;
-
-    if (from < 0)
-        from = 0;
-    if (to < 0)
-        to = len;
-
-    if (canUseGlyphCache(str, to))
-        drawSimpleText(context, point, tabWidth, xpos, str, len, from, to, toAdd, d, visuallyOrdered);
+    if (canUseGlyphCache(run))
+        drawSimpleText(context, run, point, tabWidth, xpos, toAdd, d, visuallyOrdered);
     else
-        drawComplexText(context, point, tabWidth, xpos, str, len, from, to, toAdd, d, visuallyOrdered);
+        drawComplexText(context, run, point, tabWidth, xpos, toAdd, d, visuallyOrdered);
 }
 
-float Font::floatWidth(const UChar* str, int slen, int from, int len, int tabWidth, int xpos, bool runRounding) const
+float Font::floatWidth(const TextRun& run, int tabWidth, int xpos, bool runRounding) const
 {
-    int to = from + len;
-    if (canUseGlyphCache(str, to))
-        return floatWidthForSimpleText(str, slen, from, to, tabWidth, xpos, 0, LTR, false, true, runRounding, 0, 0, 0);
+    if (canUseGlyphCache(run))
+        return floatWidthForSimpleText(run, tabWidth, xpos, 0, LTR, false, true, runRounding, 0, 0, 0);
     else
-        return floatWidthForComplexText(str, slen, from, to, tabWidth, xpos, runRounding);
+        return floatWidthForComplexText(run, tabWidth, xpos, runRounding);
 }
 
-float Font::floatWidthForSimpleText(const UChar* str, int len, int from, int to, int tabWidth, int xpos, int toAdd, 
+float Font::floatWidthForSimpleText(const TextRun& run, int tabWidth, int xpos, int toAdd, 
                                     TextDirection dir, bool visuallyOrdered, 
                                     bool applyWordRounding, bool applyRunRounding,
                                     const FontData* substituteFont,
                                     float* startPosition, GlyphBuffer* glyphBuffer) const
 {
-    WidthIterator it(this, str, from, dir == LTR ? to : len, len, tabWidth, xpos, toAdd, dir, visuallyOrdered, 
+    
+    WidthIterator it(this, run, tabWidth, xpos, toAdd, dir, visuallyOrdered, 
                      applyWordRounding, applyRunRounding, substituteFont);
-    it.advance(to, glyphBuffer);
+    it.advance(run.to(), glyphBuffer);
     float runWidth = it.m_runWidthSoFar;
     if (startPosition) {
         if (dir == LTR)
             *startPosition = it.m_widthToStart;
         else {
             float finalRoundingWidth = it.m_finalRoundingWidth;
-            it.advance(len);
+            it.advance(run.length());
             *startPosition = it.m_runWidthSoFar - runWidth + finalRoundingWidth;
         }
     }
index 53c7a59fd2ca4032d362224903f54554c7e06244..a1295860e8267cfded57d323544b384574e8476a 100644 (file)
@@ -46,6 +46,39 @@ class FloatPoint;
 
 enum Pitch { UnknownPitch, FixedPitch, VariablePitch };
 
+class TextRun
+{
+public:
+    TextRun(const UChar* c, int len)
+    :m_characters(c), m_len(len), m_from(0), m_to(len)
+    {}
+
+    TextRun(const UChar* c, int len, int from, int to) // This constructor is only used in one place in Mac-specific code.
+    :m_characters(c), m_len(len), m_from(from), m_to(to)
+    {}
+
+    TextRun(const StringImpl* s, int offset = 0, int from = -1, int to = -1)
+    :m_characters(s->characters() + offset), m_len(s->length() - offset), m_from(adjustFrom(from)), m_to(adjustTo(to))
+    {}
+
+    const UChar operator[](int i) const { return m_characters[i]; }
+    const UChar* data(int i) const { return &m_characters[i]; }
+
+    int adjustFrom(int from) const { return from == -1 ? 0 : from; }
+    int adjustTo(int to) const { return to == -1 ? m_len : to; }
+
+    const UChar* characters() const { return m_characters; }
+    int length() const { return m_len; }
+    int from() const { return m_from; }
+    int to() const { return m_to; }
+
+private:
+    const UChar* m_characters;
+    int m_len;
+    int m_from;
+    int m_to;
+};
+
 class Font {
 public:
     Font();
@@ -74,26 +107,23 @@ public:
     
     void update() const;
 
-    void drawText(GraphicsContext*, const IntPoint&, int tabWidth, int xpos,
-                  const UChar*, int len, int from, int to, int toAdd, 
-                  TextDirection, bool visuallyOrdered) const;
-    void drawHighlightForText(GraphicsContext*, const IntPoint&, int h, int tabWidth, int xpos,
-                              const UChar*, int len, int from, int to, int toAdd, 
+    void drawText(GraphicsContext*, const TextRun&, const IntPoint&, int tabWidth, int xpos,
+                  int toAdd, TextDirection, bool visuallyOrdered) const;
+    void drawHighlightForText(GraphicsContext*, const TextRun&, const IntPoint&, int h, 
+                              int tabWidth, int xpos, int toAdd, 
                               TextDirection d, bool visuallyOrdered, const Color& backgroundColor) const;
     void drawLineForText(GraphicsContext*, const IntPoint&, int yOffset, int width) const;
     void drawLineForMisspelling(GraphicsContext*, const IntPoint&, int width) const;
     int misspellingLineThickness(GraphicsContext*) const;
 
-    float floatWidth(const UChar*, int slen, int pos, int len, int tabWidth, int xpos, bool runRounding = true) const;
+    float floatWidth(const TextRun&, int tabWidth, int xpos, bool runRounding = true) const;
     
-    int checkSelectionPoint(const UChar*, int slen, int pos, int len, int toAdd, int tabWidth, int xpos,
+    int checkSelectionPoint(const TextRun&, int toAdd, int tabWidth, int xpos,
         int x, TextDirection, bool visuallyOrdered, bool includePartialGlyphs) const;
-    IntRect selectionRectForText(const IntPoint&, int h, int tabWidth, int xpos, 
-        const UChar*, int slen, int pos, int len, int width,
-        bool rtl, bool visuallyOrdered = false, int from = -1, int to = -1) const;
+    IntRect selectionRectForText(const TextRun&, const IntPoint&, int h, int tabWidth, int xpos, int width,
+                                 bool rtl, bool visuallyOrdered = false) const;
     
-    int width(const UChar*, int slen, int pos, int len, int tabWidth, int xpos) const;
-    int width(const UChar* chs, int slen, int tabWidth = 0, int xpos = 0) const { return width(chs, slen, 0, slen, tabWidth, xpos); }
+    int width(const TextRun&, int tabWidth = 0, int xpos = 0) const;
 
     bool isSmallCaps() const { return m_fontDescription.smallCaps(); }
 
@@ -130,21 +160,20 @@ public:
 private:
 #if __APPLE__
     // FIXME: This will eventually be cross-platform, but we want to keep Windows compiling for now.
-    bool canUseGlyphCache(const UChar* str, int to) const;
-    void drawSimpleText(GraphicsContext*, const IntPoint&, int tabWidth, int xpos,
-                        const UChar*, int len, int from, int to, int toAdd, 
+    bool canUseGlyphCache(const TextRun&) const;
+    void drawSimpleText(GraphicsContext*, const TextRun&, const IntPoint&, 
+                        int tabWidth, int xpos, int toAdd, 
                         TextDirection, bool visuallyOrdered) const;
     void drawGlyphs(GraphicsContext*, const FontData*, const GlyphBuffer&, int from, int to, const FloatPoint&) const;
-    void drawComplexText(GraphicsContext*, const IntPoint&, int tabWidth, int xpos,
-                         const UChar*, int len, int from, int to, int toAdd, 
-                         TextDirection, bool visuallyOrdered) const;
-    float floatWidthForSimpleText(const UChar*, int len, int from, int to, 
+    void drawComplexText(GraphicsContext*, const TextRun&, const IntPoint&, 
+                         int tabWidth, int xpos, int toAdd, TextDirection, bool visuallyOrdered) const;
+    float floatWidthForSimpleText(const TextRun&, 
                                   int tabWidth, int xpos, int toAdd, 
                                   TextDirection, bool visuallyOrdered, 
                                   bool applyWordRounding, bool applyRunRounding,
                                   const FontData* substituteFont,
                                   float* startX, GlyphBuffer*) const;
-    float floatWidthForComplexText(const UChar*, int slen, int pos, int len, int tabWidth, int xpos, bool runRounding = true) const;
+    float floatWidthForComplexText(const TextRun&, int tabWidth, int xpos, bool runRounding = true) const;
 
     friend struct WidthIterator;
     
index 5e73fdd834089833bcd565196793741ff1da1289..aa2e65df9912ba54b9c555443bcc97bfc9b2be58 100644 (file)
@@ -192,41 +192,22 @@ void GraphicsContext::drawImage(Image* image, const IntRect& dest, const IntRect
     drawImage(image, FloatRect(dest), srcRect, op);
 }
 
-// FIXME: We should consider removing this function and having callers just call the lower-level drawText directly.
-// FIXME: We should consider changing this function to take a character pointer and length instead of a DeprecatedString.
-void GraphicsContext::drawText(const IntPoint& point, const DeprecatedString& str)
+void GraphicsContext::drawText(const TextRun& run, const IntPoint& point, int tabWidth, int xpos, int toAdd,
+                               TextDirection d, bool visuallyOrdered)
 {
     if (paintingDisabled())
         return;
-
-    drawText(point, 0, 0, reinterpret_cast<const UChar*>(str.unicode()), str.length(), 0, str.length(), 0);
-}
-
-void GraphicsContext::drawText(const IntPoint& point, int tabWidth, int xpos, const UChar* str, int slen, int pos, int len, int toAdd,
-                               TextDirection d, bool visuallyOrdered, int from, int to)
-{
-    if (paintingDisabled())
-        return;
-
-    int length = min(slen - pos, len);
-    if (length <= 0)
-        return;
     
-    font().drawText(this, point, tabWidth, xpos, str + pos, length, from, to, toAdd, d, visuallyOrdered);
+    font().drawText(this, run, point, tabWidth, xpos, toAdd, d, visuallyOrdered);
 }
 
-void GraphicsContext::drawHighlightForText(const IntPoint& point, int h, int tabWidth, int xpos, const UChar* str, int slen, int pos, int len, int toAdd,
-                                           TextDirection d, bool visuallyOrdered, int from, int to, const Color& backgroundColor)
+void GraphicsContext::drawHighlightForText(const TextRun& run, const IntPoint& point, int h, int tabWidth, int xpos, int toAdd,
+                                           TextDirection d, bool visuallyOrdered, const Color& backgroundColor)
 {
     if (paintingDisabled())
         return;
-        
-    int length = min(slen - pos, len);
-    if (length <= 0)
-        return;
 
-    return font().drawHighlightForText(this, point, h, tabWidth, xpos, str + pos, length, from, to,
-                                       toAdd, d, visuallyOrdered, backgroundColor);
+    return font().drawHighlightForText(this, run, point, h, tabWidth, xpos, toAdd, d, visuallyOrdered, backgroundColor);
 }
 
 void GraphicsContext::drawLineForText(const IntPoint& point, int yOffset, int width)
index d7d8c5e1ff3a63286dbae0091b15a7c5c36b1780..33b84a2cf3379bec146a81929f8a8cdfdd3f0158 100644 (file)
@@ -53,6 +53,7 @@ namespace WebCore {
     class IntPoint;
     class IntPointArray;
     class Path;
+    class TextRun;
 
 #if SVG_SUPPORT
     class KRenderingDeviceContext;
@@ -106,14 +107,12 @@ namespace WebCore {
         void setFocusRingClip(const IntRect&);
         void clearFocusRingClip();
 
-        void drawText(const IntPoint&, const DeprecatedString&);
-        void drawText(const IntPoint&, int tabWidth, int xpos,
-            const UChar*, int slen, int pos, int len, int toAdd,
-            TextDirection = LTR, bool visuallyOrdered = false, int from = -1, int to = -1);
-        void drawHighlightForText(const IntPoint&, int h, int tabWidth, int xpos,
-            const UChar*, int slen, int pos, int len, int toAdd,
-            TextDirection, bool visuallyOrdered,
-            int from, int to, const Color& backgroundColor);
+        void drawText(const TextRun&, const IntPoint&, int tabWidth = 0, int xpos = 0, int toAdd = 0,
+                      TextDirection = LTR, bool visuallyOrdered = false);
+        void drawHighlightForText(const TextRun&, const IntPoint&, int h, 
+                                  int tabWidth, int xpos, int toAdd, TextDirection, bool visuallyOrdered, const Color& backgroundColor);
+                                  
+        
         void drawLineForText(const IntPoint&, int yOffset, int width);
         void drawLineForMisspelling(const IntPoint&, int width);
         int misspellingLineThickness();
index fee274eb91cf72e75c5974a24122eafa210acd81..ef600f7fd3b4fadadc5d22737aeec2cfbc0ccc1e 100644 (file)
@@ -113,18 +113,16 @@ void FontFallbackList::invalidate()
 
 struct ATSULayoutParameters
 {
-    ATSULayoutParameters(UniChar* characters, int len, int from, int to, int toAdd, TextDirection dir, bool applyWordRounding, bool applyRunRounding)
-    :m_characters(characters), m_len(len), m_from(from), m_to(to), m_padding(toAdd), m_rtl(dir == RTL),
+    ATSULayoutParameters(const TextRun& run, int toAdd, TextDirection dir, bool applyWordRounding, bool applyRunRounding)
+    :m_run(run), m_padding(toAdd), m_rtl(dir == RTL),
      m_applyWordRounding(applyWordRounding), m_applyRunRounding(applyRunRounding),
      m_font(0), m_fonts(0), m_charBuffer(0), m_hasSyntheticBold(false), m_syntheticBoldPass(false), m_padPerSpace(0)
     {}
 
     void initialize(const Font* font);
 
-    UniChar* m_characters;
-    int m_len;
-    int m_from;
-    int m_to;
+    const TextRun& m_run;
+
     int m_padding;
     bool m_rtl;
     bool m_applyWordRounding;
@@ -135,26 +133,21 @@ struct ATSULayoutParameters
     ATSUTextLayout m_layout;
     const FontData **m_fonts;
     
-    UniChar *m_charBuffer;
+    UChar *m_charBuffer;
     bool m_hasSyntheticBold;
     bool m_syntheticBoldPass;
     float m_padPerSpace;
 };
 
 // Be sure to free the array allocated by this function.
-static UniChar* addDirectionalOverride(UniChar* characters, int& len, int& from, int& to, bool rtl)
+static TextRun addDirectionalOverride(const TextRun& run, bool rtl)
 {
-    UniChar *charactersWithOverride = new UniChar[len + 2];
-
+    UChar* charactersWithOverride = new UChar[run.length() + 2];
     charactersWithOverride[0] = rtl ? RIGHT_TO_LEFT_OVERRIDE : LEFT_TO_RIGHT_OVERRIDE;
-    memcpy(&charactersWithOverride[1], &characters[0], sizeof(UniChar) * len);
-    charactersWithOverride[len + 1] = POP_DIRECTIONAL_FORMATTING;
-
-    from++;
-    to++;
-    len += 2;
+    memcpy(&charactersWithOverride[1], run.data(0), sizeof(UChar) * run.length());
+    charactersWithOverride[run.length() + 1] = POP_DIRECTIONAL_FORMATTING;
 
-    return charactersWithOverride;
+    return TextRun(charactersWithOverride, run.length() + 2, run.from() + 1, run.to() + 1);
 }
 
 static void initializeATSUStyle(const FontData* fontData)
@@ -227,13 +220,13 @@ static OSStatus overrideLayoutOperation(ATSULayoutOperationSelector iCurrentOper
         
         Fixed lastNativePos = 0;
         float lastAdjustedPos = 0;
-        const UniChar *characters = params->m_characters + params->m_from;
-        const FontData **renderers = params->m_fonts + params->m_from;
+        const UChar *characters = params->m_run.data(params->m_run.from());
+        const FontData **renderers = params->m_fonts + params->m_run.from();
         const FontData *renderer;
         const FontData *lastRenderer = 0;
-        UniChar ch, nextCh;
+        UChar ch, nextCh;
         ByteCount offset = layoutRecords[0].originalOffset;
-        nextCh = *(UniChar *)(((char *)characters)+offset);
+        nextCh = *(UChar *)(((char *)characters)+offset);
         bool shouldRound = false;
         bool syntheticBoldPass = params->m_syntheticBoldPass;
         Fixed syntheticBoldOffset = 0;
@@ -279,7 +272,7 @@ static OSStatus overrideLayoutOperation(ATSULayoutOperationSelector iCurrentOper
                             padding -= params->m_padPerSpace;
                         }
                     }
-                    if (offset != 0 && !Font::treatAsSpace(*((UniChar *)(((char *)characters)+offset) - 1)) && params->m_font->wordSpacing())
+                    if (offset != 0 && !Font::treatAsSpace(*((UChar *)(((char *)characters)+offset) - 1)) && params->m_font->wordSpacing())
                         width += params->m_font->wordSpacing();
                 }
             }
@@ -288,7 +281,7 @@ static OSStatus overrideLayoutOperation(ATSULayoutOperationSelector iCurrentOper
             offset = layoutRecords[i].originalOffset;
             // Use space for nextCh at the end of the loop so that we get inside the rounding hack code.
             // We won't actually round unless the other conditions are satisfied.
-            nextCh = isLastChar ? ' ' : *(UniChar *)(((char *)characters)+offset);
+            nextCh = isLastChar ? ' ' : *(UChar *)(((char *)characters)+offset);
 
             if (Font::isRoundingHackCharacter(ch))
                 width = ceilf(width);
@@ -296,7 +289,8 @@ static OSStatus overrideLayoutOperation(ATSULayoutOperationSelector iCurrentOper
             if (Font::isRoundingHackCharacter(nextCh)
                 && (!isLastChar
                     || params->m_applyRunRounding
-                    || (params->m_to < (int)params->m_len && Font::isRoundingHackCharacter(characters[params->m_to - params->m_from])))) {
+                    || (params->m_run.to() < (int)params->m_run.length() && 
+                        Font::isRoundingHackCharacter(characters[params->m_run.to() - params->m_run.from()])))) {
                 if (!params->m_rtl)
                     lastAdjustedPos = ceilf(lastAdjustedPos);
                 else {
@@ -331,8 +325,8 @@ void ATSULayoutParameters::initialize(const Font* font)
     // FIXME: It is probably best to always allocate a buffer for RTL, since even if for this
     // fontData ATSUMirrors is true, for a substitute fontData it might be false.
     const FontData* fontData = font->primaryFont();
-    m_fonts = new const FontData*[m_len];
-    m_charBuffer = (UniChar*)((font->isSmallCaps() || (m_rtl && !fontData->m_ATSUMirrors)) ? new UniChar[m_len] : 0);
+    m_fonts = new const FontData*[m_run.length()];
+    m_charBuffer = (UChar*)((font->isSmallCaps() || (m_rtl && !fontData->m_ATSUMirrors)) ? new UChar[m_run.length()] : 0);
     
     // The only Cocoa calls here are to NSGraphicsContext, which does not raise exceptions.
 
@@ -346,17 +340,17 @@ void ATSULayoutParameters::initialize(const Font* font)
     // - \n, \t, and nonbreaking space render as a space.
     // - Other control characters do not render (other code path uses zero-width spaces).
 
-    UniCharCount totalLength = m_len;
-    UniCharArrayOffset runTo = (m_to == -1 ? totalLength : (unsigned int)m_to);
-    UniCharArrayOffset runFrom = m_from;
+    UniCharCount totalLength = m_run.length();
+    UniCharArrayOffset runTo = m_run.to();
+    UniCharArrayOffset runFrom = m_run.from();
     
     if (m_charBuffer)
-        memcpy(m_charBuffer, m_characters, totalLength * sizeof(UniChar));
+        memcpy(m_charBuffer, m_run.characters(), totalLength * sizeof(UChar));
 
     UniCharCount runLength = runTo - runFrom;
     
     status = ATSUCreateTextLayoutWithTextPtr(
-            (m_charBuffer ? m_charBuffer : m_characters),
+            (m_charBuffer ? m_charBuffer : m_run.characters()),
             runFrom,        // offset
             runLength,      // length
             totalLength,    // total length
@@ -398,7 +392,7 @@ void ATSULayoutParameters::initialize(const Font* font)
         status = ATSUMatchFontsToText(layout, substituteOffset, kATSUToTextEnd, &ATSUSubstituteFont, &substituteOffset, &substituteLength);
         if (status == kATSUFontsMatched || status == kATSUFontsNotMatched) {
             // FIXME: Should go through fallback list eventually.
-            substituteFontData = fontData->findSubstituteFontData(m_characters + substituteOffset, substituteLength, m_font->fontDescription());
+            substituteFontData = fontData->findSubstituteFontData(m_run.characters() + substituteOffset, substituteLength, m_font->fontDescription());
             if (substituteFontData) {
                 initializeATSUStyle(substituteFontData);
                 if (substituteFontData->m_ATSUStyle)
@@ -429,8 +423,8 @@ void ATSULayoutParameters::initialize(const Font* font)
             if (m_rtl && m_charBuffer && !r->m_ATSUMirrors)
                 m_charBuffer[i] = u_charMirror(m_charBuffer[i]);
             if (m_font->isSmallCaps()) {
-                UniChar c = m_charBuffer[i];
-                UniChar newC;
+                UChar c = m_charBuffer[i];
+                UChar newC;
                 if (U_GET_GC_MASK(c) & U_GC_M_MASK)
                     m_fonts[i] = isSmallCap ? r->smallCapsFontData() : r;
                 else if (!u_isUUppercase(c) && (newC = u_toupper(c)) != c) {
@@ -459,7 +453,7 @@ void ATSULayoutParameters::initialize(const Font* font)
         float numSpaces = 0;
         unsigned k;
         for (k = 0; k < totalLength; k++)
-            if (Font::treatAsSpace(m_characters[k]))
+            if (Font::treatAsSpace(m_run[k]))
                 numSpaces++;
 
         m_padPerSpace = ceilf(m_padding / numSpaces);
@@ -479,22 +473,14 @@ const FontPlatformData& Font::platformFont() const
     return m_fontList->platformFont(fontDescription());
 }
 
-IntRect Font::selectionRectForText(const IntPoint& point, int h, int tabWidth, int xpos, 
-    const UChar* str, int slen, int pos, int l, int toAdd,
-    bool rtl, bool visuallyOrdered, int from, int to) const
+IntRect Font::selectionRectForText(const TextRun& textRun, const IntPoint& point, int h, int tabWidth, int xpos, int toAdd, bool rtl, bool visuallyOrdered) const
 {
     assert(m_fontList);
-    int len = min(slen - pos, l);
 
     CREATE_FAMILY_ARRAY(fontDescription(), families);
 
-    if (from < 0)
-        from = 0;
-    if (to < 0)
-        to = len;
-
     WebCoreTextRun run;
-    WebCoreInitializeTextRun(&run, str + pos, len, from, to);
+    WebCoreInitializeTextRun(&run, textRun.characters(), textRun.length(), textRun.from(), textRun.to());
     WebCoreTextStyle style;
     WebCoreInitializeEmptyTextStyle(&style);
     style.rtl = rtl;
@@ -514,19 +500,17 @@ IntRect Font::selectionRectForText(const IntPoint& point, int h, int tabWidth, i
     geometry.useFontMetricsForSelectionYAndHeight = false;
     return enclosingIntRect(m_fontList->primaryFont(fontDescription())->selectionRectForRun(&run, &style, &geometry));
 }
-void Font::drawComplexText(GraphicsContext* graphicsContext, const IntPoint& point, int tabWidth, int xpos, const UChar* str, int len, int from, int to,
+
+void Font::drawComplexText(GraphicsContext* graphicsContext, const TextRun& run, const IntPoint& point, int tabWidth, int xpos,
                            int toAdd, TextDirection d, bool visuallyOrdered) const
 {
-    int runLength = to - from;
-    if (runLength <= 0)
-        return;
-
     OSStatus status;
-    UniChar* characters = (UniChar*)str;
-    if (visuallyOrdered)
-        characters = addDirectionalOverride(characters, len, from, to, d == RTL);
+    
+    const UChar* characters = run.characters();
+    int runLength = run.length();
 
-    ATSULayoutParameters params(characters, len, 0, len, toAdd, d, true, true);
+    TextRun adjustedRun = visuallyOrdered ? addDirectionalOverride(run, d == RTL) : run;
+    ATSULayoutParameters params(adjustedRun, toAdd, d, true, true);
     params.initialize(this);
 
     [nsColor(graphicsContext->pen().color()) set];
@@ -539,12 +523,12 @@ void Font::drawComplexText(GraphicsContext* graphicsContext, const IntPoint& poi
     bool flipped = [gContext isFlipped];
     if (!flipped)
         CGContextScaleCTM(context, 1.0, -1.0);
-    status = ATSUDrawText(params.m_layout, from, runLength, 0, 0);
+    status = ATSUDrawText(params.m_layout, adjustedRun.from(), runLength, 0, 0);
     if (status == noErr && params.m_hasSyntheticBold) {
         // Force relayout for the bold pass
         ATSUClearLayoutCache(params.m_layout, 0);
         params.m_syntheticBoldPass = true;
-        status = ATSUDrawText(params.m_layout, from, runLength, 0, 0);
+        status = ATSUDrawText(params.m_layout, adjustedRun.from(), runLength, 0, 0);
     }
     if (!flipped)
         CGContextScaleCTM(context, 1.0, -1.0);
@@ -561,21 +545,15 @@ void Font::drawComplexText(GraphicsContext* graphicsContext, const IntPoint& poi
         delete []characters;
 }
 
-void Font::drawHighlightForText(GraphicsContext* context, const IntPoint& point, int h, int tabWidth, int xpos, const UChar* str,
-                                int len, int from, int to, int toAdd,
-                                TextDirection d, bool visuallyOrdered, const Color& backgroundColor) const
+void Font::drawHighlightForText(GraphicsContext* context, const TextRun& textRun, const IntPoint& point, int h, int tabWidth, int xpos, 
+                                int toAdd, TextDirection d, bool visuallyOrdered, const Color& backgroundColor) const
 {
     // Avoid allocations, use stack array to pass font families.  Normally these
     // css fallback lists are small <= 3.
     CREATE_FAMILY_ARRAY(*this, families);
-
-    if (from < 0)
-        from = 0;
-    if (to < 0)
-        to = len;
         
     WebCoreTextRun run;
-    WebCoreInitializeTextRun(&run, str, len, from, to);    
+    WebCoreInitializeTextRun(&run, textRun.characters(), textRun.length(), textRun.from(), textRun.to());    
     WebCoreTextStyle style;
     WebCoreInitializeEmptyTextStyle(&style);
     style.textColor = nsColor(context->pen().color());
@@ -613,19 +591,16 @@ int Font::misspellingLineThickness(GraphicsContext* context) const
     return m_fontList->primaryFont(fontDescription())->misspellingLineThickness();
 }
 
-float Font::floatWidthForComplexText(const UChar* uchars, int len, int from, int to, int tabWidth, int xpos, bool runRounding) const
+float Font::floatWidthForComplexText(const TextRun& run, int tabWidth, int xpos, bool runRounding) const
 {
-    if (to - from <= 0)
-        return 0;
-
-    ATSULayoutParameters params((UniChar*)uchars, len, from, to, 0, LTR, true, runRounding);
+    ATSULayoutParameters params(run, 0, LTR, true, runRounding);
     params.initialize(this);
     
     OSStatus status;
     
     ATSTrapezoid firstGlyphBounds;
     ItemCount actualNumBounds;
-    status = ATSUGetGlyphBounds(params.m_layout, 0, 0, from, to - from, kATSUseFractionalOrigins, 1, &firstGlyphBounds, &actualNumBounds);    
+    status = ATSUGetGlyphBounds(params.m_layout, 0, 0, run.from(), run.to() - run.from(), kATSUseFractionalOrigins, 1, &firstGlyphBounds, &actualNumBounds);    
     if (status != noErr)
         LOG_ERROR("ATSUGetGlyphBounds() failed(%d)", status);
     if (actualNumBounds != 1)
@@ -637,13 +612,13 @@ float Font::floatWidthForComplexText(const UChar* uchars, int len, int from, int
            MIN(FixedToFloat(firstGlyphBounds.upperLeft.x), FixedToFloat(firstGlyphBounds.lowerLeft.x));
 }
 
-int Font::checkSelectionPoint(const UChar* s, int slen, int pos, int len, int toAdd, int tabWidth, int xpos, int x, TextDirection d, bool visuallyOrdered, bool includePartialGlyphs) const
+int Font::checkSelectionPoint(const TextRun& textRun, int toAdd, int tabWidth, int xpos, int x, TextDirection d, bool visuallyOrdered, bool includePartialGlyphs) const
 {
     assert(m_fontList);
     CREATE_FAMILY_ARRAY(fontDescription(), families);
     
     WebCoreTextRun run;
-    WebCoreInitializeTextRun(&run, s + pos, min(slen - pos, len), 0, len);
+    WebCoreInitializeTextRun(&run, textRun.characters(), textRun.length(), textRun.from(), textRun.to());
     
     WebCoreTextStyle style;
     WebCoreInitializeEmptyTextStyle(&style);
index 118135b8c52a781d3881fa951de6fe584f414888..44da5bd009b4a949bbabdd5e89e577866774c234 100644 (file)
@@ -154,7 +154,7 @@ FontData* FontFallbackList::primaryFont(const FontDescription& fontDescription)
     return defaultFont;
 }
 
-static IntSize hackishExtentForString(HDC dc, FontData* font, const UChar* str, int slen, int pos, int len, int tabWidth, int xpos)
+static IntSize hackishExtentForString(HDC dc, FontData* font, const TextRun& run, int tabWidth, int xpos)
 {
     SaveDC(dc);
 
@@ -167,7 +167,7 @@ static IntSize hackishExtentForString(HDC dc, FontData* font, const UChar* str,
     // FIXME: Handle tabs (the tabWidth and xpos parameters)
     // FIXME: Handle RTL.
     SIZE s;
-    BOOL result = GetTextExtentPoint32W(dc, (WCHAR*)(str + pos), len, &s);
+    BOOL result = GetTextExtentPoint32W(dc, (WCHAR*)(run.characters()), run.length(), &s);
 
     RestoreDC(dc, -1);
 
@@ -176,33 +176,19 @@ static IntSize hackishExtentForString(HDC dc, FontData* font, const UChar* str,
     return s;
 }
 
-float Font::floatWidth(const UChar* str, int slen, int pos, int len,
-                       int tabWidth, int xpos, bool runRounding) const
+float Font::floatWidth(const TextRun& run, int tabWidth, int xpos, bool runRounding) const
 {
     FontData* font = m_fontList->primaryFont(fontDescription());
     if (!font)
         return 0;
 
     HDC dc = GetDC((HWND)0); // FIXME: Need a way to get to the real HDC.
-    IntSize runSize = hackishExtentForString(dc, font, str, slen, pos, len, tabWidth, xpos);
+    IntSize runSize = hackishExtentForString(dc, font, run, tabWidth, xpos);
     ReleaseDC(0, dc);
     return runSize.width();
 }
 
-static void convertRange(int from, int to, int len, int& offset, int& length)
-{
-    offset = 0;
-    length = len;
-    if (from > 0) {
-        offset = from;
-        length = len - from;
-    }
-    if (to > 0)
-        length = to - from;
-}
-
-void Font::drawText(GraphicsContext* context, const IntPoint& point, int tabWidth, int xpos,
-                    const UChar* str, int len, int from, int to,
+void Font::drawText(GraphicsContext* context, const TextRun& run, const IntPoint& point, int tabWidth, int xpos,
                     int toAdd, TextDirection d, bool visuallyOrdered) const
 {
     FontData* font = m_fontList->primaryFont(fontDescription());
@@ -215,9 +201,6 @@ void Font::drawText(GraphicsContext* context, const IntPoint& point, int tabWidt
     SaveDC(dc);
     SelectObject(dc, font->platformData().hfont());
 
-    int offset, length;
-    convertRange(from, to, len, offset, length);
-
     int x = point.x();
     int y = point.y();
     y -= font->ascent();
@@ -225,14 +208,13 @@ void Font::drawText(GraphicsContext* context, const IntPoint& point, int tabWidt
     SetBkMode(dc, TRANSPARENT);
     const Color& color = context->pen().color();
     SetTextColor(dc, RGB(color.red(), color.green(), color.blue())); // FIXME: Need to support alpha in the text color.
-    TextOutW(dc, x, y, (LPCWSTR)(str+offset), length);
+    TextOutW(dc, x, y, (LPCWSTR)(run.characters()), run.length());
 
     RestoreDC(dc, -1);
     // No need to ReleaseDC the HDC borrowed from cairo
 }
 
-void Font::drawHighlightForText(GraphicsContext* context, const IntPoint& point, int h, int tabWidth, int xpos,
-                                const UChar* str, int len, int from, int to, int toAdd,
+void Font::drawHighlightForText(GraphicsContext* context, const TextRun& run, const IntPoint& point, int h, int tabWidth, int xpos,
                                 TextDirection d, bool visuallyOrdered, const Color& backgroundColor) const
 {
     if (!backgroundColor.isValid())
@@ -245,31 +227,26 @@ void Font::drawHighlightForText(GraphicsContext* context, const IntPoint& point,
     cairo_surface_t* surface = cairo_get_target(context->platformContext());
     HDC dc = cairo_win32_surface_get_dc(surface);
 
-    int offset, length;
-    convertRange(from, to, len, offset, length);
-    IntSize runSize = hackishExtentForString(dc, font, str, len, offset, length, tabWidth, xpos);
+    IntSize runSize = hackishExtentForString(dc, font, run, tabWidth, xpos);
 
     // FIXME: this const_cast should be removed when this code is made real.
     const_cast<GraphicsContext*>(context)->fillRect(IntRect(point, runSize), backgroundColor);
 }
 
-IntRect Font::selectionRectForText(const IntPoint& point, int h, int tabWidth, int xpos, const UChar* str, int slen,
-                                   int pos, int len, int toAdd, bool rtl, bool visuallyOrdered, int from, int to) const
+IntRect Font::selectionRectForText(const TextRun& run, const IntPoint& point, int h, int tabWidth, int xpos,
+                                   int toAdd, bool rtl, bool visuallyOrdered) const
 {
     FontData* font = m_fontList->primaryFont(fontDescription());
     if (!font)
         return IntRect();
 
-    int offset, length;
-    convertRange(from, to, len, offset, length);
-
     HDC dc = GetDC((HWND)0); // FIXME: Need a way to get to the real HDC.
-    IntSize runSize = hackishExtentForString(dc, font, str, slen, offset, length, tabWidth, xpos);
+    IntSize runSize = hackishExtentForString(dc, font, run, tabWidth, xpos);
     ReleaseDC(0, dc);
     return IntRect(point, runSize);
 }
 
-int Font::checkSelectionPoint(const UChar* str, int slen, int offset, int len, int toAdd, int tabWidth, int xpos, int x,
+int Font::checkSelectionPoint(const TextRun& run, int toAdd, int tabWidth, int xpos, int x,
                               TextDirection, bool visuallyOrdered, bool includePartialGlyphs) const
 {
     FontData* font = m_fontList->primaryFont(fontDescription());
@@ -286,12 +263,12 @@ int Font::checkSelectionPoint(const UChar* str, int slen, int offset, int len, i
     memset(&results, 0, sizeof(GCP_RESULTS));
     results.lStructSize = sizeof(GCP_RESULTS);
     results.lpCaretPos = caretPositions;
-    results.nGlyphs = len;
+    results.nGlyphs = run.length();
     
-    GetCharacterPlacement(dc, (LPCTSTR)(str+offset), len, 0, &results, 0);
+    GetCharacterPlacement(dc, (LPCTSTR)(run.characters()), run.length(), 0, &results, 0);
 
     unsigned selectionOffset = 0;
-    while (selectionOffset < len && caretPositions[selectionOffset] < x)
+    while (selectionOffset < run.length() && caretPositions[selectionOffset] < x)
         selectionOffset++;
 
     fastFree(caretPositions);
index 0d5443decba551d72a8ea759d7a37dfb55afac37..f43f8ae74c8ba3628367095975e5f86522fea85a 100644 (file)
@@ -117,9 +117,9 @@ IntRect InlineTextBox::selectionRect(int tx, int ty, int startPos, int endPos)
     int selHeight = rootBox->selectionHeight();
     const Font *f = textObj->font(m_firstLine);
 
-    IntRect r = f->selectionRectForText(IntPoint(tx + m_x, ty + selTop), selHeight, textObj->tabWidth(), textPos(), 
-                                        textObj->str->characters(), textObj->str->length(), m_start, m_len,
-                                        m_toAdd, m_reversed, m_dirOverride, sPos, ePos);
+    IntRect r = f->selectionRectForText(TextRun(textObj->string(), m_start, sPos, ePos),
+                                        IntPoint(tx + m_x, ty + selTop), selHeight, textObj->tabWidth(), textPos(), 
+                                        m_toAdd, m_reversed, m_dirOverride);
     if (r.x() > tx + m_x + m_width)
         r.setWidth(0);
     else if (r.right() - 1 > tx + m_x + m_width)
@@ -325,6 +325,8 @@ void InlineTextBox::paint(RenderObject::PaintInfo& i, int tx, int ty)
         }
     }
 
+    StringImpl* textStr = textObject()->string();
+
     if (!paintSelectedTextOnly && !paintSelectedTextSeparately) {
         // paint all the text
         // FIXME: Handle RTL direction, handle reversed strings.  For now truncation can only be turned on
@@ -332,8 +334,8 @@ void InlineTextBox::paint(RenderObject::PaintInfo& i, int tx, int ty)
         int endPoint = m_len;
         if (m_truncation != cNoTruncation)
             endPoint = m_truncation - m_start;
-        i.p->drawText(IntPoint(m_x + tx, m_y + ty + m_baseline), textObject()->tabWidth(), textPos(),
-                      textObject()->string()->characters(), textObject()->string()->length(), m_start, endPoint,
+        i.p->drawText(TextRun(textStr, m_start, 0, endPoint),
+                      IntPoint(m_x + tx, m_y + ty + m_baseline), textObject()->tabWidth(), textPos(),
                       m_toAdd, m_reversed ? RTL : LTR, m_dirOverride || styleToUse->visuallyOrdered());
     } else {
         int sPos, ePos;
@@ -341,18 +343,15 @@ void InlineTextBox::paint(RenderObject::PaintInfo& i, int tx, int ty)
         if (paintSelectedTextSeparately) {
             // paint only the text that is not selected
             if (sPos >= ePos)
-                i.p->drawText(IntPoint(m_x + tx, m_y + ty + m_baseline), textObject()->tabWidth(), textPos(),
-                              textObject()->string()->characters(), textObject()->string()->length(), m_start, m_len,
+                i.p->drawText(TextRun(textStr, m_start), IntPoint(m_x + tx, m_y + ty + m_baseline), textObject()->tabWidth(), textPos(),
                               m_toAdd, m_reversed ? RTL : LTR, m_dirOverride || styleToUse->visuallyOrdered());
             else {
                 if (sPos - 1 >= 0)
-                    i.p->drawText(IntPoint(m_x + tx, m_y + ty + m_baseline), textObject()->tabWidth(), textPos(),
-                                  textObject()->string()->characters(), textObject()->string()->length(), m_start, m_len,
-                                  m_toAdd, m_reversed ? RTL : LTR, m_dirOverride || styleToUse->visuallyOrdered(), 0, sPos);
+                    i.p->drawText(TextRun(textStr, m_start, 0, sPos), IntPoint(m_x + tx, m_y + ty + m_baseline), textObject()->tabWidth(), textPos(),
+                                  m_toAdd, m_reversed ? RTL : LTR, m_dirOverride || styleToUse->visuallyOrdered());
                 if (ePos < m_start + m_len)
-                    i.p->drawText(IntPoint(m_x + tx, m_y + ty + m_baseline), textObject()->tabWidth(), textPos(),
-                                  textObject()->string()->characters(), textObject()->string()->length(), m_start, m_len,
-                                  m_toAdd, m_reversed ? RTL : LTR, m_dirOverride || styleToUse->visuallyOrdered(), ePos, -1);
+                    i.p->drawText(TextRun(textStr, m_start, ePos), IntPoint(m_x + tx, m_y + ty + m_baseline), textObject()->tabWidth(), textPos(),
+                                  m_toAdd, m_reversed ? RTL : LTR, m_dirOverride || styleToUse->visuallyOrdered());
             }
         }
             
@@ -365,9 +364,8 @@ void InlineTextBox::paint(RenderObject::PaintInfo& i, int tx, int ty)
                 i.p->setShadow(IntSize(selectionTextShadow->x, selectionTextShadow->y),
                                selectionTextShadow->blur,
                                selectionTextShadow->color);
-            i.p->drawText(IntPoint(m_x + tx, m_y + ty + m_baseline), textObject()->tabWidth(), textPos(),
-                          textObject()->string()->characters(), textObject()->string()->length(), m_start, m_len,
-                          m_toAdd, m_reversed ? RTL : LTR, m_dirOverride || styleToUse->visuallyOrdered(), sPos, ePos);
+            i.p->drawText(TextRun(textStr, m_start, sPos, ePos), IntPoint(m_x + tx, m_y + ty + m_baseline), textObject()->tabWidth(), textPos(),
+                          m_toAdd, m_reversed ? RTL : LTR, m_dirOverride || styleToUse->visuallyOrdered());
             if (selectionTextShadow)
                 i.p->clearShadow();
         }
@@ -450,9 +448,8 @@ void InlineTextBox::paintSelection(GraphicsContext* p, int tx, int ty, RenderSty
     int y = r->selectionTop();
     int h = r->selectionHeight();
     p->addClip(IntRect(m_x + tx, y + ty, m_width, h));
-    p->drawHighlightForText(IntPoint(m_x + tx, y + ty), h, textObject()->tabWidth(), textPos(), 
-                            textObject()->str->characters(), textObject()->str->length(), m_start, m_len,
-                            m_toAdd, m_reversed ? RTL : LTR, m_dirOverride || style->visuallyOrdered(), sPos, ePos, c);
+    p->drawHighlightForText(TextRun(textObject()->string(), m_start, sPos, ePos), IntPoint(m_x + tx, y + ty), h, textObject()->tabWidth(), textPos(), 
+                            m_toAdd, m_reversed ? RTL : LTR, m_dirOverride || style->visuallyOrdered(), c);
     p->restore();
 }
 
@@ -474,9 +471,9 @@ void InlineTextBox::paintMarkedTextBackground(GraphicsContext* p, int tx, int ty
     RootInlineBox* r = root();
     int y = r->selectionTop();
     int h = r->selectionHeight();
-    p->drawHighlightForText(IntPoint(m_x + tx, y + ty), h, textObject()->tabWidth(), textPos(),
-                            textObject()->str->characters(), textObject()->str->length(), m_start, m_len,
-                            m_toAdd, m_reversed ? RTL : LTR, m_dirOverride || style->visuallyOrdered(), sPos, ePos, c);
+    p->drawHighlightForText(TextRun(textObject()->string(), m_start, sPos, ePos),
+                            IntPoint(m_x + tx, y + ty), h, textObject()->tabWidth(), textPos(),
+                            m_toAdd, m_reversed ? RTL : LTR, m_dirOverride || style->visuallyOrdered(), c);
     p->restore();
 }
 
@@ -573,9 +570,8 @@ void InlineTextBox::paintTextMatchMarker(GraphicsContext* pt, int _tx, int _ty,
     int sPos = max(marker.startOffset - m_start, (unsigned)0);
     int ePos = min(marker.endOffset - m_start, (unsigned)m_len);
     
-    pt->drawHighlightForText(IntPoint(m_x + _tx, y + _ty), h, textObject()->tabWidth(), textPos(), 
-                             textObject()->str->characters(), textObject()->str->length(), m_start, m_len,
-                             m_toAdd, m_reversed ? RTL : LTR, m_dirOverride || style->visuallyOrdered(), sPos, ePos, yellow);
+    pt->drawHighlightForText(TextRun(textObject()->string(), m_start, sPos, ePos), IntPoint(m_x + _tx, y + _ty), h, textObject()->tabWidth(), textPos(), 
+                             m_toAdd, m_reversed ? RTL : LTR, m_dirOverride || style->visuallyOrdered(), yellow);
     pt->restore();
 }
 
@@ -688,9 +684,9 @@ int InlineTextBox::offsetForPosition(int _x, bool includePartialGlyphs) const
     RenderText* text = static_cast<RenderText*>(m_object);
     RenderStyle *style = text->style(m_firstLine);
     const Font* f = &style->font();
-    return f->checkSelectionPoint(text->str->characters(), text->str->length(), m_start, m_len,
-        m_toAdd, text->tabWidth(), textPos(), _x - m_x,
-        m_reversed ? RTL : LTR, m_dirOverride || style->visuallyOrdered(), includePartialGlyphs);
+    return f->checkSelectionPoint(TextRun(textObject()->string(), m_start),
+                                  m_toAdd, text->tabWidth(), textPos(), _x - m_x,
+                                  m_reversed ? RTL : LTR, m_dirOverride || style->visuallyOrdered(), includePartialGlyphs);
 }
 
 int InlineTextBox::positionForOffset(int offset) const
@@ -703,8 +699,7 @@ int InlineTextBox::positionForOffset(int offset) const
     int from = m_reversed ? offset - m_start : 0;
     int to = m_reversed ? m_len : offset - m_start;
     // FIXME: Do we need to add rightBearing here?
-    return f->selectionRectForText(IntPoint(m_x, 0), 0, text->tabWidth(), textPos(), text->str->characters(), text->str->length(), m_start, m_len,
-        m_toAdd, m_reversed, m_dirOverride, from, to).right();
+    return f->selectionRectForText(TextRun(text->string(), m_start, from, to), IntPoint(m_x, 0), 0, text->tabWidth(), textPos(), m_toAdd, m_reversed, m_dirOverride).right();
 }
 
 }
index 5720301ec5e1925515d997d2af0979de8ba2f4c8..f901b4a34eaf117386a4b778d635a5e1a754ccfb 100644 (file)
@@ -2832,7 +2832,7 @@ static inline void stripTrailingSpace(int& inlineMax, int& inlineMin,
         RenderText* t = static_cast<RenderText *>(trailingSpaceChild);
         const Font *f = t->font(false);  // FIXME: Why are we ignoring first-line?
         const UChar space = ' ';
-        int spaceWidth = f->width(&space, 1);
+        int spaceWidth = f->width(TextRun(&space, 1));
         inlineMax -= spaceWidth;
         if (inlineMin > inlineMax)
             inlineMin = inlineMax;
index 318d1caebdabfa8c191b7f9e703b44b8a396b449..82983a0f43e26d19f3fc089da47659b706961795 100644 (file)
@@ -768,7 +768,7 @@ void RenderFlexibleBox::layoutVerticalBox(bool relayoutChildren)
                 static AtomicString ellipsisAndSpaceStr(ellipsisAndSpace, 2);
 
                 const Font& font = style(numVisibleLines == 1)->font();
-                int ellipsisAndSpaceWidth = font.width(ellipsisAndSpace, 2, 0, 2, 0, 0);
+                int ellipsisAndSpaceWidth = font.width(TextRun(ellipsisAndSpace, 2));
 
                 // Get ellipsis width + " " + anchor width
                 int totalWidth = ellipsisAndSpaceWidth + anchorBox->width();
index 0a016567d555f06b57e99f0bbe0b61fe662019f4..ee3b80c1a635bab23667c5df6b6351138fe70eb6 100644 (file)
@@ -104,7 +104,7 @@ void RenderImage::imageChanged(CachedImage* o)
         // we have an alt and the user meant it (its not a text we invented)
         if (!m_altText.isEmpty()) {
             const Font& font = style()->font();
-            iw = max(iw, min(font.width(m_altText.characters(), m_altText.length()), 1024));
+            iw = max(iw, min(font.width(TextRun(m_altText.characters(), m_altText.length())), 1024));
             ih = max(ih, min(font.height(), 256));
         }
 
@@ -247,12 +247,13 @@ void RenderImage::paint(PaintInfo& i, int _tx, int _ty)
                 
                 // Only draw the alt text if it'll fit within the content box,
                 // and only if it fits above the error image.
-                int textWidth = font.width(reinterpret_cast<const UChar*>(text.unicode()), text.length());
+                TextRun textRun(reinterpret_cast<const UChar*>(text.unicode()), text.length());
+                int textWidth = font.width(textRun);
                 if (errorPictureDrawn) {
                     if (usableWidth >= textWidth && font.height() <= imageY)
-                        p->drawText(IntPoint(ax, ay + ascent), text);
+                        p->drawText(textRun, IntPoint(ax, ay + ascent));
                 } else if (usableWidth >= textWidth && cHeight >= font.height())
-                    p->drawText(IntPoint(ax, ay + ascent), text);
+                    p->drawText(textRun, IntPoint(ax, ay + ascent));
             }
         }
     }
index d9d06f861d2e6e8820aeb6a3900a8e28af7299e8..c5005f090ee1e8b36b3e04452b35f32c9e0abb64 100644 (file)
@@ -460,7 +460,7 @@ void RenderText::cacheWidths()
     const Font* f = font(false);
     if (shouldUseMonospaceCache(f)) {
         const UChar c = ' ';
-        m_monospaceCharacterWidth = (int)f->floatWidth(&c, 1, 0, 1, 0, 0);
+        m_monospaceCharacterWidth = f->width(TextRun(&c, 1));
     } else {
         m_monospaceCharacterWidth = 0;
     }
@@ -486,7 +486,7 @@ ALWAYS_INLINE int RenderText::widthFromCache(const Font* f, int start, int len,
         return w;
     }
     
-    return f->width(str->characters(), str->length(), start, len, tabWidth, xpos);
+    return f->width(TextRun(string(), start, 0, len), tabWidth, xpos);
 }
 
 void RenderText::trimmedMinMaxWidth(int leadWidth,
@@ -525,7 +525,7 @@ void RenderText::trimmedMinMaxWidth(int leadWidth,
     if (stripFrontSpaces && ((*str)[0] == ' ' || ((*str)[0] == '\n' && !style()->preserveNewline()) || (*str)[0] == '\t')) {
         const Font *f = font(false); // FIXME: Why is it ok to ignore first-line here?
         const UChar space = ' ';
-        int spaceWidth = f->width(&space, 1);
+        int spaceWidth = f->width(TextRun(&space, 1));
         maxW -= spaceWidth + f->wordSpacing();
     }
     
@@ -704,7 +704,7 @@ void RenderText::calcMinMaxWidth(int leadWidth)
             }
             else
             {
-                currMaxWidth += f->width(txt, len, i, 1, tabWidth(), leadWidth + currMaxWidth);
+                currMaxWidth += f->width(TextRun(txt + i, 1), tabWidth(), leadWidth + currMaxWidth);
                 needsWordSpacing = isSpace && !previousCharacterIsSpace && i == len-1;
             }
         }
@@ -995,7 +995,7 @@ unsigned int RenderText::width(unsigned int from, unsigned int len, const Font *
     else if (f == &style()->font())
         w = widthFromCache(f, from, len, tabWidth(), xpos);
     else
-        w = f->width(str->characters(), str->length(), from, len, tabWidth(), xpos );
+        w = f->width(TextRun(string(), from, 0, len), tabWidth(), xpos );
         
     return w;
 }
index accd4e71aef87a1ceb4f154bef818a90902316a2..1b194df74645fe116802f94cf39b7324340f1e7f 100644 (file)
@@ -230,8 +230,10 @@ void RenderTextField::calcMinMaxWidth()
         if (size <= 0)
             size = 20;
 
+        // FIXME: Once we have a struct that can hold rounding hack info, we will be able to just use the 
+        // normal width method (and make floatWidth properly private).
         const UChar ch = '0';
-        int sizeWidth = (int)ceilf(style()->font().floatWidth(&ch, 1, 0, 1, 0, 0, false) * size);
+        int sizeWidth = (int)ceilf(style()->font().floatWidth(TextRun(&ch, 1), 0, 0, false) * size);
         m_maxWidth = sizeWidth;
     }
     
index 3810f97666639b9a572272a224237d027161b3c4..ab13aca20e42beaea3788d22ee83899411eabcfa 100644 (file)
@@ -846,7 +846,7 @@ int RenderBlock::tabWidth(bool isWhitespacePre)
     if (!m_tabWidth) {
         const UChar spaceChar = ' ';
         const Font& font = style()->font();
-        int spaceWidth = font.width(&spaceChar, 1);
+        int spaceWidth = font.width(TextRun(&spaceChar, 1));
         m_tabWidth = spaceWidth * 8;
         assert(m_tabWidth != 0);
     }
@@ -2559,11 +2559,12 @@ void RenderBlock::checkLinesForTextOverflow()
 {
     // Determine the width of the ellipsis using the current font.
     const UChar ellipsis = 0x2026; // FIXME: CSS3 says this is configurable, also need to use 0x002E (FULL STOP) if 0x2026 not renderable
+    TextRun ellipsisRun(&ellipsis, 1);
     static AtomicString ellipsisStr(&ellipsis, 1);
     const Font& firstLineFont = firstLineStyle()->font();
     const Font& font = style()->font();
-    int firstLineEllipsisWidth = firstLineFont.width(&ellipsis, 1);
-    int ellipsisWidth = (font == firstLineFont) ? firstLineEllipsisWidth : font.width(&ellipsis, 1);
+    int firstLineEllipsisWidth = firstLineFont.width(ellipsisRun);
+    int ellipsisWidth = (font == firstLineFont) ? firstLineEllipsisWidth : font.width(ellipsisRun);
 
     // For LTR text truncation, we want to get the right edge of our padding box, and then we want to see
     // if the right edge of a line box exceeds that.  For RTL, we use the left edge of the padding box and
index f19784ec2478a9dad3f5050e330a6e18fd32eedd..7934000aa731638244958fb2288cebe406d0fab9 100644 (file)
@@ -1085,8 +1085,7 @@ void EllipsisBox::paint(RenderObject::PaintInfo& i, int _tx, int _ty)
     }
 
     const String& str = m_str;
-    p->drawText(IntPoint(m_x + _tx, m_y + _ty + m_baseline), 0, 0, str.characters(), str.length(),
-        0, str.length(), 0, LTR, _style->visuallyOrdered(), 0, str.length());
+    p->drawText(TextRun(str.impl()), IntPoint(m_x + _tx, m_y + _ty + m_baseline), 0, 0, 0, LTR, _style->visuallyOrdered());
 
     if (setShadow)
         p->clearShadow();
index edef9e206a61b1799f9c5c33816a1b1963822173..e8ca6086b5f26c0fc6876977e26a5b86c9b7765e 100644 (file)
@@ -441,15 +441,18 @@ void RenderListMarker::paint(PaintInfo& i, int _tx, int _ty)
     default:
         if (!m_item.isEmpty()) {
             const Font& font = style()->font();
+            TextRun textRun(reinterpret_cast<const UChar*>(m_item.unicode()), m_item.length());
             if (style()->direction() == LTR) {
-                int width = font.width(reinterpret_cast<const UChar*>(m_item.unicode()), m_item.length());
-                p->drawText(marker.location(), m_item);
-                p->drawText(marker.location() + IntSize(width, 0), ". ");
+                int width = font.width(textRun);
+                p->drawText(textRun, marker.location());
+                UChar periodSpace[2] = { '.', ' ' };
+                p->drawText(TextRun(periodSpace, 2), marker.location() + IntSize(width, 0));
             } else {
-                UChar spacePeriod[2] = { '.', ' ' };
-                int width = font.width(spacePeriod, 2);
-                p->drawText(marker.location(), " .");
-                p->drawText(marker.location() + IntSize(width, 0), m_item);
+                UChar spacePeriod[2] = { ' ', '.' };
+                TextRun spacePeriodRun(spacePeriod, 2);
+                int width = font.width(spacePeriodRun);
+                p->drawText(spacePeriodRun, marker.location());
+                p->drawText(textRun, marker.location() + IntSize(width, 0));
             }
         }
     }
@@ -549,9 +552,9 @@ void RenderListMarker::calcMinMaxWidth()
     }
 
     {
-        int itemWidth = font.width(reinterpret_cast<const UChar*>(m_item.unicode()), m_item.length());
+        int itemWidth = font.width(TextRun(reinterpret_cast<const UChar*>(m_item.unicode()), m_item.length()));
         UChar periodSpace[2] = { '.', ' ' };
-        int periodSpaceWidth = font.width(periodSpace, 2);
+        int periodSpaceWidth = font.width(TextRun(periodSpace, 2));
         m_width = itemWidth + periodSpaceWidth;
     }
 
@@ -698,9 +701,9 @@ IntRect RenderListMarker::getRelativeMarkerRect()
     if (m_item.isEmpty())
         return IntRect();
 
-    int itemWidth = font.width(reinterpret_cast<const UChar*>(m_item.unicode()), m_item.length());
+    int itemWidth = font.width(TextRun(reinterpret_cast<const UChar*>(m_item.unicode()), m_item.length()));
     UChar periodSpace[2] = { '.', ' ' };
-    int periodSpaceWidth = font.width(periodSpace, 2);
+    int periodSpaceWidth = font.width(TextRun(periodSpace, 2));
     return IntRect(m_x, m_y + ascent, itemWidth + periodSpaceWidth, font.height());
 }