static float cummulatedWidthOrHeightOfTextChunk(SVGTextChunk& chunk, bool calcWidthOnly)
{
    float length = 0.0f;
    Vector<SVGChar>::iterator charIt = chunk.start;

    Vector<SVGInlineBoxCharacterRange>::iterator it = chunk.boxes.begin();
    Vector<SVGInlineBoxCharacterRange>::iterator end = chunk.boxes.end();

    for (; it != end; ++it) {
        SVGInlineBoxCharacterRange& range = *it;

        SVGInlineTextBox* box = static_cast<SVGInlineTextBox*>(range.box);
        RenderStyle* style = box->renderer()->style();

        for (int i = range.startOffset; i < range.endOffset; ++i) {
            ASSERT(charIt <= chunk.end);

            // Determine how many characters - starting from the current - can be measured at once.
            // Important for non-absolute positioned non-latin1 text (ie. Arabic) where ie. the width
            // of a string is not the sum of the boundaries of all contained glyphs.
            Vector<SVGChar>::iterator itSearch = charIt + 1;
            Vector<SVGChar>::iterator endSearch = charIt + range.endOffset - i;
            while (itSearch != endSearch) {
                // No need to check for 'isHidden()' here as this function is not called for text paths.
                if (itSearch->drawnSeperated)
                    break;

                itSearch++;
            }

            unsigned int positionOffset = itSearch - charIt;

            // Calculate width/height of subrange
            SVGInlineBoxCharacterRange subRange;
            subRange.box = range.box;
            subRange.startOffset = i;
            subRange.endOffset = i + positionOffset;

            if (calcWidthOnly)
                length += cummulatedWidthOfInlineBoxCharacterRange(subRange);
            else
                length += cummulatedHeightOfInlineBoxCharacterRange(subRange);

            // Calculate gap between the previous & current range
            // <text x="10 50 70">ABCD</text> - we need to take the gaps between A & B into account
            // so add "40" as width, and analogous for B & C, add "20" as width.
            if (itSearch > chunk.start && itSearch < chunk.end) {
                SVGChar& lastCharacter = *(itSearch - 1);
                SVGChar& currentCharacter = *itSearch;

                int charsConsumed = 0;
                float glyphWidth = 0.0f;
                float glyphHeight = 0.0f;
                String glyphName;
                String unicodeString;
                box->measureCharacter(style, i + positionOffset - 1, charsConsumed, glyphName, unicodeString, glyphWidth, glyphHeight);

                if (calcWidthOnly)
                    length += currentCharacter.x - lastCharacter.x - glyphWidth;
                else
                    length += currentCharacter.y - lastCharacter.y - glyphHeight;
            }

            // Advance processed characters
            i += positionOffset - 1;
            charIt = itSearch;
        }
    }

    ASSERT(charIt == chunk.end);
    return length;
}
static inline void writeSVGInlineTextBox(TextStream& ts, SVGInlineTextBox* textBox, int indent)
{
    SVGRootInlineBox* rootBox = textBox->svgRootInlineBox();
    if (!rootBox)
        return;

    Vector<SVGTextChunk>& chunks = const_cast<Vector<SVGTextChunk>& >(rootBox->svgTextChunks());

    Vector<SVGTextChunk>::iterator it = chunks.begin();
    Vector<SVGTextChunk>::iterator end = chunks.end();

    // Write text chunks
    unsigned int i = 1;
    for (; it != end; ++it) {
        SVGTextChunk& cur = *it;

        // Write inline box character ranges
        Vector<SVGInlineBoxCharacterRange>::iterator boxIt = cur.boxes.begin();
        Vector<SVGInlineBoxCharacterRange>::iterator boxEnd = cur.boxes.end();

        if (!containsInlineTextBox(cur, textBox)) {
            i++;
            continue;
        }

        writeIndent(ts, indent + 1);

        unsigned int j = 1;
        ts << "chunk " << i << " ";

        if (cur.anchor == TA_MIDDLE) {
            ts << "(middle anchor";
            if (cur.isVerticalText)
                ts << ", vertical";
            ts << ") ";
        } else if (cur.anchor == TA_END) {
            ts << "(end anchor";
            if (cur.isVerticalText)
                ts << ", vertical";
            ts << ") ";
        } else if (cur.isVerticalText)
            ts << "(vertical) ";

        unsigned int totalOffset = 0;

        for (; boxIt != boxEnd; ++boxIt) {
            SVGInlineBoxCharacterRange& range = *boxIt;

            unsigned int offset = range.endOffset - range.startOffset;
            ASSERT(cur.start + totalOffset <= cur.end);
    
            totalOffset += offset;
      
            if (textBox != static_cast<SVGInlineTextBox*>(range.box)) {
                j++;
                continue;
            }
  
            FloatPoint topLeft = topLeftPositionOfCharacterRange(cur.start + totalOffset - offset, cur.start + totalOffset);

            ts << "text run " << j << " at (" << topLeft.x() << "," << topLeft.y() << ") ";
            ts << "startOffset " << range.startOffset << " endOffset " << range.endOffset;

            if (cur.isVerticalText)
                ts << " height " << cummulatedHeightOfInlineBoxCharacterRange(range);
            else
                ts << " width " << cummulatedWidthOfInlineBoxCharacterRange(range);

            if (textBox->direction() == RTL || textBox->m_dirOverride) {
                ts << (textBox->direction() == RTL ? " RTL" : " LTR");

                if (textBox->m_dirOverride)
                    ts << " override";
            }

            ts << ": " << quoteAndEscapeNonPrintables(String(textBox->textRenderer()->text()).substring(textBox->start() + range.startOffset, offset)) << "\n";

            j++;
        }

        i++;
    }
}