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++; } }