15c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)/*
25c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Copyright (C) 2004, 2006, 2007 Apple Inc. All rights reserved.
35c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *
45c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Redistribution and use in source and binary forms, with or without
55c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * modification, are permitted provided that the following conditions
65c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * are met:
75c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * 1. Redistributions of source code must retain the above copyright
85c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *    notice, this list of conditions and the following disclaimer.
95c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * 2. Redistributions in binary form must reproduce the above copyright
105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *    notice, this list of conditions and the following disclaimer in the
115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *    documentation and/or other materials provided with the distribution.
125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *
135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) */
255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include "config.h"
2753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/rendering/RenderTreeAsText.h"
2853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)
295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include "HTMLNames.h"
3053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/css/StylePropertySet.h"
3153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/dom/Document.h"
3253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/editing/FrameSelection.h"
3353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/html/HTMLElement.h"
3453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/page/Frame.h"
3553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/page/FrameView.h"
3653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/page/PrintContext.h"
3753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/rendering/FlowThreadController.h"
3853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/rendering/InlineTextBox.h"
3953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/rendering/RenderBR.h"
4053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/rendering/RenderDetailsMarker.h"
4153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/rendering/RenderFileUploadControl.h"
4253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/rendering/RenderInline.h"
4353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/rendering/RenderLayer.h"
4453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/rendering/RenderLayerBacking.h"
4553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/rendering/RenderListItem.h"
4653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/rendering/RenderListMarker.h"
4753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/rendering/RenderNamedFlowThread.h"
4853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/rendering/RenderPart.h"
4953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/rendering/RenderRegion.h"
5053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/rendering/RenderTableCell.h"
5153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/rendering/RenderView.h"
5253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/rendering/RenderWidget.h"
5353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/rendering/svg/RenderSVGContainer.h"
5453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/rendering/svg/RenderSVGGradientStop.h"
5553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/rendering/svg/RenderSVGImage.h"
5653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/rendering/svg/RenderSVGInlineText.h"
5753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/rendering/svg/RenderSVGPath.h"
5853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/rendering/svg/RenderSVGRoot.h"
5953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/rendering/svg/RenderSVGText.h"
6053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/rendering/svg/SVGRenderTreeAsText.h"
6193ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)#include "wtf/HexNumber.h"
6293ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)#include "wtf/UnusedParam.h"
6393ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)#include "wtf/Vector.h"
6493ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)#include "wtf/unicode/CharacterNames.h"
655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)namespace WebCore {
675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)using namespace HTMLNames;
695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)static void writeLayers(TextStream&, const RenderLayer* rootLayer, RenderLayer*, const LayoutRect& paintDirtyRect, int indent = 0, RenderAsTextBehavior = RenderAsTextBehaviorNormal);
715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)TextStream& operator<<(TextStream& ts, const IntRect& r)
735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return ts << "at (" << r.x() << "," << r.y() << ") size " << r.width() << "x" << r.height();
755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)TextStream& operator<<(TextStream& ts, const IntPoint& p)
785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return ts << "(" << p.x() << "," << p.y() << ")";
805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)TextStream& operator<<(TextStream& ts, const FloatPoint& p)
835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ts << "(" << TextStream::FormatNumberRespectingIntegers(p.x());
855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ts << "," << TextStream::FormatNumberRespectingIntegers(p.y());
865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ts << ")";
875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return ts;
885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)TextStream& operator<<(TextStream& ts, const FloatSize& s)
915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ts << "width=" << TextStream::FormatNumberRespectingIntegers(s.width());
935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ts << " height=" << TextStream::FormatNumberRespectingIntegers(s.height());
945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return ts;
955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void writeIndent(TextStream& ts, int indent)
985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    for (int i = 0; i != indent; ++i)
1005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        ts << "  ";
1015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
1025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)static void printBorderStyle(TextStream& ts, const EBorderStyle borderStyle)
1045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
1055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    switch (borderStyle) {
1065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        case BNONE:
1075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            ts << "none";
1085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            break;
1095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        case BHIDDEN:
1105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            ts << "hidden";
1115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            break;
1125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        case INSET:
1135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            ts << "inset";
1145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            break;
1155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        case GROOVE:
1165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            ts << "groove";
1175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            break;
1185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        case RIDGE:
1195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            ts << "ridge";
1205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            break;
1215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        case OUTSET:
1225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            ts << "outset";
1235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            break;
1245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        case DOTTED:
1255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            ts << "dotted";
1265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            break;
1275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        case DASHED:
1285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            ts << "dashed";
1295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            break;
1305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        case SOLID:
1315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            ts << "solid";
1325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            break;
1335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        case DOUBLE:
1345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            ts << "double";
1355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            break;
1365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
1375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ts << " ";
1395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
1405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)static String getTagName(Node* n)
1425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
1435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (n->isDocumentNode())
1445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return "";
1455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (n->nodeType() == Node::COMMENT_NODE)
1465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return "COMMENT";
1475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return n->nodeName();
1485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
1495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)static bool isEmptyOrUnstyledAppleStyleSpan(const Node* node)
1515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
1525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!node || !node->isHTMLElement() || !node->hasTagName(spanTag))
1535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return false;
1545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
155926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    const HTMLElement* elem = toHTMLElement(node);
1565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (elem->getAttribute(classAttr) != "Apple-style-span")
1575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return false;
1585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!node->hasChildNodes())
1605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return true;
1615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    const StylePropertySet* inlineStyleDecl = elem->inlineStyle();
1635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return (!inlineStyleDecl || inlineStyleDecl->isEmpty());
1645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
1655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)String quoteAndEscapeNonPrintables(const String& s)
1675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
1685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    StringBuilder result;
1695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    result.append('"');
1705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    for (unsigned i = 0; i != s.length(); ++i) {
1715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        UChar c = s[i];
1725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (c == '\\') {
1735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            result.append('\\');
1745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            result.append('\\');
1755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        } else if (c == '"') {
1765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            result.append('\\');
1775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            result.append('"');
1785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        } else if (c == '\n' || c == noBreakSpace)
1795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            result.append(' ');
1805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        else {
1815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            if (c >= 0x20 && c < 0x7F)
1825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                result.append(c);
1835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            else {
1845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                result.append('\\');
1855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                result.append('x');
1865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                result.append('{');
18702772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch                appendUnsignedAsHex(c, result);
1885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                result.append('}');
1895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            }
1905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
1915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
1925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    result.append('"');
1935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return result.toString();
1945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
1955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void RenderTreeAsText::writeRenderObject(TextStream& ts, const RenderObject& o, RenderAsTextBehavior behavior)
1975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
1985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ts << o.renderName();
1995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (behavior & RenderAsTextShowAddresses)
2015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        ts << " " << static_cast<const void*>(&o);
2025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (o.style() && o.style()->zIndex())
2045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        ts << " zI: " << o.style()->zIndex();
2055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (o.node()) {
2075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        String tagName = getTagName(o.node());
208926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        // FIXME: Temporary hack to make tests pass by simulating the old generated content output.
209926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        if (o.isPseudoElement() || (o.parent() && o.parent()->isPseudoElement()))
210926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            tagName = emptyAtom;
2115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (!tagName.isEmpty()) {
2125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            ts << " {" << tagName << "}";
2135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            // flag empty or unstyled AppleStyleSpan because we never
2145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            // want to leave them in the DOM
2155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            if (isEmptyOrUnstyledAppleStyleSpan(o.node()))
2165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                ts << " *empty or unstyled AppleStyleSpan*";
2175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
2185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
21902772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch
2205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    RenderBlock* cb = o.containingBlock();
2215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    bool adjustForTableCells = cb ? cb->isTableCell() : false;
2225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    LayoutRect r;
2245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (o.isText()) {
2255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // FIXME: Would be better to dump the bounding box x and y rather than the first run's x and y, but that would involve updating
2265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // many test results.
2275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        const RenderText& text = *toRenderText(&o);
2285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        IntRect linesBox = text.linesBoundingBox();
2295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        r = IntRect(text.firstRunX(), text.firstRunY(), linesBox.width(), linesBox.height());
2305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (adjustForTableCells && !text.firstTextBox())
2315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            adjustForTableCells = false;
2325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    } else if (o.isRenderInline()) {
2335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // FIXME: Would be better not to just dump 0, 0 as the x and y here.
2345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        const RenderInline& inlineFlow = *toRenderInline(&o);
2355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        r = IntRect(0, 0, inlineFlow.linesBoundingBox().width(), inlineFlow.linesBoundingBox().height());
2365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        adjustForTableCells = false;
2375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    } else if (o.isTableCell()) {
2385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // FIXME: Deliberately dump the "inner" box of table cells, since that is what current results reflect.  We'd like
2395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // to clean up the results to dump both the outer box and the intrinsic padding so that both bits of information are
2405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // captured by the results.
2415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        const RenderTableCell& cell = *toRenderTableCell(&o);
2425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        r = LayoutRect(cell.x(), cell.y() + cell.intrinsicPaddingBefore(), cell.width(), cell.height() - cell.intrinsicPaddingBefore() - cell.intrinsicPaddingAfter());
2435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    } else if (o.isBox())
2445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        r = toRenderBox(&o)->frameRect();
2455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // FIXME: Temporary in order to ensure compatibility with existing layout test results.
2475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (adjustForTableCells)
2485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        r.move(0, -toRenderTableCell(o.containingBlock())->intrinsicPaddingBefore());
2495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
25002772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch    ts << " " << r;
2515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!(o.isText() && !o.isBR())) {
2535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (o.isFileUploadControl())
2545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            ts << " " << quoteAndEscapeNonPrintables(toRenderFileUploadControl(&o)->fileTextValue());
2555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (o.parent()) {
2577757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch            Color color = o.resolveColor(CSSPropertyColor);
2587757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch            if (o.parent()->resolveColor(CSSPropertyColor) != color)
2595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                ts << " [color=" << color.nameForRenderTreeAsText() << "]";
2605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            // Do not dump invalid or transparent backgrounds, since that is the default.
2627757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch            Color backgroundColor = o.resolveColor(CSSPropertyBackgroundColor);
2637757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch            if (o.parent()->resolveColor(CSSPropertyBackgroundColor) != backgroundColor
26483750176c3ee2cea66c8a9751271026a5901be3aBen Murdoch                && backgroundColor.rgb())
2655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                ts << " [bgcolor=" << backgroundColor.nameForRenderTreeAsText() << "]";
26602772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch
2677757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch            Color textFillColor = o.resolveColor(CSSPropertyWebkitTextFillColor);
2687757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch            if (o.parent()->resolveColor(CSSPropertyWebkitTextFillColor) != textFillColor
26983750176c3ee2cea66c8a9751271026a5901be3aBen Murdoch                && textFillColor != color && textFillColor.rgb())
2705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                ts << " [textFillColor=" << textFillColor.nameForRenderTreeAsText() << "]";
2715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2727757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch            Color textStrokeColor = o.resolveColor(CSSPropertyWebkitTextStrokeColor);
2737757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch            if (o.parent()->resolveColor(CSSPropertyWebkitTextStrokeColor) != textStrokeColor
27483750176c3ee2cea66c8a9751271026a5901be3aBen Murdoch                && textStrokeColor != color && textStrokeColor.rgb())
2755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                ts << " [textStrokeColor=" << textStrokeColor.nameForRenderTreeAsText() << "]";
2765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            if (o.parent()->style()->textStrokeWidth() != o.style()->textStrokeWidth() && o.style()->textStrokeWidth() > 0)
2785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                ts << " [textStrokeWidth=" << o.style()->textStrokeWidth() << "]";
2795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
2805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (!o.isBoxModelObject())
2825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            return;
2835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        const RenderBoxModelObject& box = *toRenderBoxModelObject(&o);
2855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (box.borderTop() || box.borderRight() || box.borderBottom() || box.borderLeft()) {
2865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            ts << " [border:";
2875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            BorderValue prevBorder = o.style()->borderTop();
2895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            if (!box.borderTop())
2905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                ts << " none";
2915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            else {
2925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                ts << " (" << box.borderTop() << "px ";
2935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                printBorderStyle(ts, o.style()->borderTopStyle());
29483750176c3ee2cea66c8a9751271026a5901be3aBen Murdoch                Color col = o.resolveColor(CSSPropertyBorderTopColor);
2955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                ts << col.nameForRenderTreeAsText() << ")";
2965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            }
2975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            if (o.style()->borderRight() != prevBorder) {
2995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                prevBorder = o.style()->borderRight();
3005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                if (!box.borderRight())
3015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    ts << " none";
3025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                else {
3035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    ts << " (" << box.borderRight() << "px ";
3045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    printBorderStyle(ts, o.style()->borderRightStyle());
30583750176c3ee2cea66c8a9751271026a5901be3aBen Murdoch                    Color col = o.resolveColor(CSSPropertyBorderRightColor);
3065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    ts << col.nameForRenderTreeAsText() << ")";
3075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                }
3085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            }
3095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            if (o.style()->borderBottom() != prevBorder) {
3115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                prevBorder = box.style()->borderBottom();
3125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                if (!box.borderBottom())
3135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    ts << " none";
3145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                else {
3155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    ts << " (" << box.borderBottom() << "px ";
3165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    printBorderStyle(ts, o.style()->borderBottomStyle());
31783750176c3ee2cea66c8a9751271026a5901be3aBen Murdoch                    Color col = o.resolveColor(CSSPropertyBorderBottomColor);
3185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    ts << col.nameForRenderTreeAsText() << ")";
3195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                }
3205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            }
3215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            if (o.style()->borderLeft() != prevBorder) {
3235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                prevBorder = o.style()->borderLeft();
3245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                if (!box.borderLeft())
3255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    ts << " none";
3265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                else {
3275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    ts << " (" << box.borderLeft() << "px ";
3285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    printBorderStyle(ts, o.style()->borderLeftStyle());
32983750176c3ee2cea66c8a9751271026a5901be3aBen Murdoch                    Color col = o.resolveColor(CSSPropertyBorderLeftColor);
3305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    ts << col.nameForRenderTreeAsText() << ")";
3315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                }
3325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            }
3335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            ts << "]";
3355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
3365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
3375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (o.isTableCell()) {
3395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        const RenderTableCell& c = *toRenderTableCell(&o);
3405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        ts << " [r=" << c.rowIndex() << " c=" << c.col() << " rs=" << c.rowSpan() << " cs=" << c.colSpan() << "]";
3415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
3425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (o.isDetailsMarker()) {
3445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        ts << ": ";
3455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        switch (toRenderDetailsMarker(&o)->orientation()) {
3465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        case RenderDetailsMarker::Left:
3475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            ts << "left";
3485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            break;
3495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        case RenderDetailsMarker::Right:
3505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            ts << "right";
3515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            break;
3525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        case RenderDetailsMarker::Up:
3535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            ts << "up";
3545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            break;
3555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        case RenderDetailsMarker::Down:
3565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            ts << "down";
3575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            break;
3585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
3595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
3605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (o.isListMarker()) {
3625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        String text = toRenderListMarker(&o)->text();
3635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (!text.isEmpty()) {
3645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            if (text.length() != 1)
3655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                text = quoteAndEscapeNonPrintables(text);
3665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            else {
3675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                switch (text[0]) {
3685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    case bullet:
3695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                        text = "bullet";
3705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                        break;
3715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    case blackSquare:
3725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                        text = "black square";
3735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                        break;
3745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    case whiteBullet:
3755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                        text = "white bullet";
3765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                        break;
3775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    default:
3785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                        text = quoteAndEscapeNonPrintables(text);
3795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                }
3805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            }
3815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            ts << ": " << text;
3825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
3835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
38402772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch
3855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (behavior & RenderAsTextShowIDAndClass) {
3865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (Node* node = o.node()) {
3875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            if (node->hasID())
388926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)                ts << " id=\"" + toElement(node)->getIdAttribute() + "\"";
3895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            if (node->hasClass()) {
3915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                ts << " class=\"";
392591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch                Element* element = toElement(node);
393591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch                for (size_t i = 0; i < element->classNames().size(); ++i) {
3945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    if (i > 0)
3955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                        ts << " ";
396591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch                    ts << element->classNames()[i];
3975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                }
3985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                ts << "\"";
3995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            }
4005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
4015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
40202772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch
4035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (behavior & RenderAsTextShowLayoutState) {
4045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        bool needsLayout = o.selfNeedsLayout() || o.needsPositionedMovementLayout() || o.posChildNeedsLayout() || o.normalChildNeedsLayout();
4055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (needsLayout)
4065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            ts << " (needs layout:";
40702772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch
4085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        bool havePrevious = false;
4095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (o.selfNeedsLayout()) {
4105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            ts << " self";
4115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            havePrevious = true;
4125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
4135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (o.needsPositionedMovementLayout()) {
4155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            if (havePrevious)
4165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                ts << ",";
4175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            havePrevious = true;
4185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            ts << " positioned movement";
4195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
4205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (o.normalChildNeedsLayout()) {
4225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            if (havePrevious)
4235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                ts << ",";
4245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            havePrevious = true;
4255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            ts << " child";
4265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
4275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (o.posChildNeedsLayout()) {
4295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            if (havePrevious)
4305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                ts << ",";
4315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            ts << " positioned child";
4325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
4335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (needsLayout)
4355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            ts << ")";
4365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
4375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
4385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)static void writeTextRun(TextStream& ts, const RenderText& o, const InlineTextBox& run)
4405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
4415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // FIXME: For now use an "enclosingIntRect" model for x, y and logicalWidth, although this makes it harder
4425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // to detect any changes caused by the conversion to floating point. :(
4435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    int x = run.x();
4445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    int y = run.y();
4455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    int logicalWidth = ceilf(run.left() + run.logicalWidth()) - x;
4465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // FIXME: Table cell adjustment is temporary until results can be updated.
4485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (o.containingBlock()->isTableCell())
4495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        y -= toRenderTableCell(o.containingBlock())->intrinsicPaddingBefore();
45002772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch
4515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ts << "text run at (" << x << "," << y << ") width " << logicalWidth;
4525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!run.isLeftToRightDirection() || run.dirOverride()) {
4535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        ts << (!run.isLeftToRightDirection() ? " RTL" : " LTR");
4545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (run.dirOverride())
4555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            ts << " override";
4565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
4575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ts << ": "
4585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        << quoteAndEscapeNonPrintables(String(o.text()).substring(run.start(), run.len()));
4595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (run.hasHyphen())
4605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        ts << " + hyphen string " << quoteAndEscapeNonPrintables(o.style()->hyphenString());
4615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ts << "\n";
4625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
4635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void write(TextStream& ts, const RenderObject& o, int indent, RenderAsTextBehavior behavior)
4655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
4665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (o.isSVGShape()) {
4675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        write(ts, *toRenderSVGShape(&o), indent);
4685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return;
4695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
4705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (o.isSVGGradientStop()) {
4715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        writeSVGGradientStop(ts, *toRenderSVGGradientStop(&o), indent);
4725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return;
4735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
4745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (o.isSVGResourceContainer()) {
4755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        writeSVGResourceContainer(ts, o, indent);
4765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return;
4775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
4785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (o.isSVGContainer()) {
4795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        writeSVGContainer(ts, o, indent);
4805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return;
4815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
4825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (o.isSVGRoot()) {
4835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        write(ts, *toRenderSVGRoot(&o), indent);
4845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return;
4855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
4865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (o.isSVGText()) {
4875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        writeSVGText(ts, *toRenderSVGText(&o), indent);
4885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return;
4895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
4905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (o.isSVGInlineText()) {
4915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        writeSVGInlineText(ts, *toRenderSVGInlineText(&o), indent);
4925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return;
4935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
4945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (o.isSVGImage()) {
4955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        writeSVGImage(ts, *toRenderSVGImage(&o), indent);
4965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return;
4975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
4985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    writeIndent(ts, indent);
5005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
5015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    RenderTreeAsText::writeRenderObject(ts, o, behavior);
5025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ts << "\n";
5035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
5045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (o.isText() && !o.isBR()) {
5055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        const RenderText& text = *toRenderText(&o);
5065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        for (InlineTextBox* box = text.firstTextBox(); box; box = box->nextTextBox()) {
5075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            writeIndent(ts, indent + 1);
5085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            writeTextRun(ts, text, *box);
5095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
5105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
5115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
5125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    for (RenderObject* child = o.firstChild(); child; child = child->nextSibling()) {
5135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (child->hasLayer())
5145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            continue;
5155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        write(ts, *child, indent + 1, behavior);
5165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
5175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
5185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (o.isWidget()) {
5195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        Widget* widget = toRenderWidget(&o)->widget();
5205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (widget && widget->isFrameView()) {
521926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            FrameView* view = toFrameView(widget);
5225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            RenderView* root = view->frame()->contentRenderer();
5235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            if (root) {
5245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                view->layout();
5255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                RenderLayer* l = root->layer();
5265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                if (l)
5275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    writeLayers(ts, l, l, l->rect(), indent + 1, behavior);
5285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            }
5295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
5305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
5315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
5325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
5335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)enum LayerPaintPhase {
5345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    LayerPaintPhaseAll = 0,
5355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    LayerPaintPhaseBackground = -1,
5365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    LayerPaintPhaseForeground = 1
5375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)};
5385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
5395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)static void write(TextStream& ts, RenderLayer& l,
5405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                  const LayoutRect& layerBounds, const LayoutRect& backgroundClipRect, const LayoutRect& clipRect, const LayoutRect& outlineClipRect,
5415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                  LayerPaintPhase paintPhase = LayerPaintPhaseAll, int indent = 0, RenderAsTextBehavior behavior = RenderAsTextBehaviorNormal)
5425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
5435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    IntRect adjustedLayoutBounds = pixelSnappedIntRect(layerBounds);
5445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    IntRect adjustedBackgroundClipRect = pixelSnappedIntRect(backgroundClipRect);
5455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    IntRect adjustedClipRect = pixelSnappedIntRect(clipRect);
5465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    IntRect adjustedOutlineClipRect = pixelSnappedIntRect(outlineClipRect);
5475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
5485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    writeIndent(ts, indent);
5495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
5505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ts << "layer ";
55102772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch
5525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (behavior & RenderAsTextShowAddresses)
5535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        ts << static_cast<const void*>(&l) << " ";
55402772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch
5555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ts << adjustedLayoutBounds;
5565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
5575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!adjustedLayoutBounds.isEmpty()) {
5585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (!adjustedBackgroundClipRect.contains(adjustedLayoutBounds))
5595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            ts << " backgroundClip " << adjustedBackgroundClipRect;
5605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (!adjustedClipRect.contains(adjustedLayoutBounds))
5615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            ts << " clip " << adjustedClipRect;
5625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (!adjustedOutlineClipRect.contains(adjustedLayoutBounds))
5635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            ts << " outlineClip " << adjustedOutlineClipRect;
5645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
5655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
5665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (l.renderer()->hasOverflowClip()) {
5675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (l.scrollXOffset())
5685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            ts << " scrollX " << l.scrollXOffset();
5695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (l.scrollYOffset())
5705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            ts << " scrollY " << l.scrollYOffset();
5715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (l.renderBox() && l.renderBox()->pixelSnappedClientWidth() != l.scrollWidth())
5725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            ts << " scrollWidth " << l.scrollWidth();
5735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (l.renderBox() && l.renderBox()->pixelSnappedClientHeight() != l.scrollHeight())
5745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            ts << " scrollHeight " << l.scrollHeight();
5755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
5765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
5775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (paintPhase == LayerPaintPhaseBackground)
5785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        ts << " layerType: background only";
5795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    else if (paintPhase == LayerPaintPhaseForeground)
5805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        ts << " layerType: foreground only";
58102772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch
5825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (behavior & RenderAsTextShowCompositedLayers) {
5835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (l.isComposited())
5845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            ts << " (composited, bounds=" << l.backing()->compositedBounds() << ", drawsContent=" << l.backing()->graphicsLayer()->drawsContent() << ", paints into ancestor=" << l.backing()->paintsIntoCompositedAncestor() << ")";
5855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
58653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)
5875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ts << "\n";
5885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
5895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (paintPhase != LayerPaintPhaseBackground)
5905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        write(ts, *l.renderer(), indent + 1, behavior);
5915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
5925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
5935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)static void writeRenderRegionList(const RenderRegionList& flowThreadRegionList, TextStream& ts, int indent)
5945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
5955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    for (RenderRegionList::const_iterator itRR = flowThreadRegionList.begin(); itRR != flowThreadRegionList.end(); ++itRR) {
5965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        RenderRegion* renderRegion = *itRR;
5975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        writeIndent(ts, indent + 2);
5985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        ts << "RenderRegion";
5995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (renderRegion->generatingNode()) {
6005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            String tagName = getTagName(renderRegion->generatingNode());
6015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            if (!tagName.isEmpty())
6025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                ts << " {" << tagName << "}";
6035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            if (renderRegion->generatingNode()->isElementNode() && renderRegion->generatingNode()->hasID()) {
604926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)                Element* element = toElement(renderRegion->generatingNode());
6055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                ts << " #" << element->idForStyleResolution();
6065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            }
6075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            if (renderRegion->hasCustomRegionStyle())
6085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                ts << " region style: 1";
6095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            if (renderRegion->hasAutoLogicalHeight())
6105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                ts << " hasAutoLogicalHeight";
6115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
6125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (!renderRegion->isValid())
6135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            ts << " invalid";
6145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        ts << "\n";
6155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
6165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
6175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
6185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)static void writeRenderNamedFlowThreads(TextStream& ts, RenderView* renderView, const RenderLayer* rootLayer,
6195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                        const LayoutRect& paintRect, int indent, RenderAsTextBehavior behavior)
6205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
6215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!renderView->hasRenderNamedFlowThreads())
6225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return;
6235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
6245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    const RenderNamedFlowThreadList* list = renderView->flowThreadController()->renderNamedFlowThreadList();
6255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
6265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    writeIndent(ts, indent);
6275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ts << "Flow Threads\n";
6285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
6295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    for (RenderNamedFlowThreadList::const_iterator iter = list->begin(); iter != list->end(); ++iter) {
6305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        const RenderNamedFlowThread* renderFlowThread = *iter;
6315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
6325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        writeIndent(ts, indent + 1);
6335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        ts << "Thread with flow-name '" << renderFlowThread->flowThreadName() << "'\n";
6345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
6355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        RenderLayer* layer = renderFlowThread->layer();
6365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        writeLayers(ts, rootLayer, layer, paintRect, indent + 2, behavior);
6375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
6385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // Display the valid and invalid render regions attached to this flow thread.
6395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        const RenderRegionList& validRegionsList = renderFlowThread->renderRegionList();
6405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        const RenderRegionList& invalidRegionsList = renderFlowThread->invalidRenderRegionList();
6415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (!validRegionsList.isEmpty() || !invalidRegionsList.isEmpty()) {
6425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            writeIndent(ts, indent + 1);
6435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            ts << "Regions for flow '"<< renderFlowThread->flowThreadName() << "'\n";
6445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            writeRenderRegionList(validRegionsList, ts, indent);
6455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            writeRenderRegionList(invalidRegionsList, ts, indent);
6465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
6475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
6485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
6495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
6505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)static void writeLayers(TextStream& ts, const RenderLayer* rootLayer, RenderLayer* l,
6515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                        const LayoutRect& paintRect, int indent, RenderAsTextBehavior behavior)
6525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
6535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // FIXME: Apply overflow to the root layer to not break every test.  Complete hack.  Sigh.
6545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    LayoutRect paintDirtyRect(paintRect);
6555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (rootLayer == l) {
6565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        paintDirtyRect.setWidth(max<LayoutUnit>(paintDirtyRect.width(), rootLayer->renderBox()->layoutOverflowRect().maxX()));
6575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        paintDirtyRect.setHeight(max<LayoutUnit>(paintDirtyRect.height(), rootLayer->renderBox()->layoutOverflowRect().maxY()));
6585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        l->setSize(l->size().expandedTo(pixelSnappedIntSize(l->renderBox()->maxLayoutOverflow(), LayoutPoint(0, 0))));
6595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
66002772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch
6615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Calculate the clip rects we should use.
6625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    LayoutRect layerBounds;
6635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ClipRect damageRect, clipRectToApply, outlineRect;
664926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    l->calculateRects(RenderLayer::ClipRectsContext(rootLayer, 0, TemporaryClipRects), paintDirtyRect, layerBounds, damageRect, clipRectToApply, outlineRect);
6655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
6665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Ensure our lists are up-to-date.
6675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    l->updateLayerListsIfNeeded();
6685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
6695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    bool shouldPaint = (behavior & RenderAsTextShowAllLayers) ? true : l->intersectsDamageRect(layerBounds, damageRect.rect(), rootLayer);
6705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    Vector<RenderLayer*>* negList = l->negZOrderList();
6715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    bool paintsBackgroundSeparately = negList && negList->size() > 0;
6725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (shouldPaint && paintsBackgroundSeparately)
6735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        write(ts, *l, layerBounds, damageRect.rect(), clipRectToApply.rect(), outlineRect.rect(), LayerPaintPhaseBackground, indent, behavior);
6745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
6755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (negList) {
6765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        int currIndent = indent;
6775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (behavior & RenderAsTextShowLayerNesting) {
6785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            writeIndent(ts, indent);
6795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            ts << " negative z-order list(" << negList->size() << ")\n";
6805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            ++currIndent;
6815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
6825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        for (unsigned i = 0; i != negList->size(); ++i)
6835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            writeLayers(ts, rootLayer, negList->at(i), paintDirtyRect, currIndent, behavior);
6845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
6855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
6865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (shouldPaint)
6875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        write(ts, *l, layerBounds, damageRect.rect(), clipRectToApply.rect(), outlineRect.rect(), paintsBackgroundSeparately ? LayerPaintPhaseForeground : LayerPaintPhaseAll, indent, behavior);
6885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
6895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (Vector<RenderLayer*>* normalFlowList = l->normalFlowList()) {
6905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        int currIndent = indent;
6915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (behavior & RenderAsTextShowLayerNesting) {
6925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            writeIndent(ts, indent);
6935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            ts << " normal flow list(" << normalFlowList->size() << ")\n";
6945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            ++currIndent;
6955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
6965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        for (unsigned i = 0; i != normalFlowList->size(); ++i)
6975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            writeLayers(ts, rootLayer, normalFlowList->at(i), paintDirtyRect, currIndent, behavior);
6985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
6995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
7005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (Vector<RenderLayer*>* posList = l->posZOrderList()) {
7015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        int currIndent = indent;
7025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (behavior & RenderAsTextShowLayerNesting) {
7035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            writeIndent(ts, indent);
7045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            ts << " positive z-order list(" << posList->size() << ")\n";
7055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            ++currIndent;
7065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
7075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        for (unsigned i = 0; i != posList->size(); ++i)
7085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            writeLayers(ts, rootLayer, posList->at(i), paintDirtyRect, currIndent, behavior);
7095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
71002772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch
7115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Altough the RenderFlowThread requires a layer, it is not collected by its parent,
7125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // so we have to treat it as a special case.
7135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (l->renderer()->isRenderView()) {
7145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        RenderView* renderView = toRenderView(l->renderer());
7155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        writeRenderNamedFlowThreads(ts, renderView, rootLayer, paintDirtyRect, indent, behavior);
7165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
7175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
7185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
7195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)static String nodePosition(Node* node)
7205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
7215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    StringBuilder result;
7225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
7235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    Element* body = node->document()->body();
7245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    Node* parent;
7255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    for (Node* n = node; n; n = parent) {
726926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        parent = n->parentOrShadowHostNode();
7275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (n != node)
7285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            result.appendLiteral(" of ");
7295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (parent) {
7305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            if (body && n == body) {
7315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                // We don't care what offset body may be in the document.
7325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                result.appendLiteral("body");
7335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                break;
7345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            }
7355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            if (n->isShadowRoot()) {
7365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                result.append('{');
7375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                result.append(getTagName(n));
7385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                result.append('}');
7395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            } else {
7405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                result.appendLiteral("child ");
7415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                result.appendNumber(n->nodeIndex());
7425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                result.appendLiteral(" {");
7435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                result.append(getTagName(n));
7445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                result.append('}');
7455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            }
7465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        } else
7475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            result.appendLiteral("document");
7485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
7495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
7505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return result.toString();
7515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
7525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
7535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)static void writeSelection(TextStream& ts, const RenderObject* o)
7545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
7555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    Node* n = o->node();
7565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!n || !n->isDocumentNode())
7575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return;
7585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
759926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    Document* doc = toDocument(n);
7605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    Frame* frame = doc->frame();
7615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!frame)
7625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return;
7635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
7645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    VisibleSelection selection = frame->selection()->selection();
7655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (selection.isCaret()) {
7665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        ts << "caret: position " << selection.start().deprecatedEditingOffset() << " of " << nodePosition(selection.start().deprecatedNode());
7675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (selection.affinity() == UPSTREAM)
7685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            ts << " (upstream affinity)";
7695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        ts << "\n";
7705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    } else if (selection.isRange())
7715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        ts << "selection start: position " << selection.start().deprecatedEditingOffset() << " of " << nodePosition(selection.start().deprecatedNode()) << "\n"
7725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)           << "selection end:   position " << selection.end().deprecatedEditingOffset() << " of " << nodePosition(selection.end().deprecatedNode()) << "\n";
7735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
7745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
7755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)static String externalRepresentation(RenderBox* renderer, RenderAsTextBehavior behavior)
7765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
7775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    TextStream ts;
7785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!renderer->hasLayer())
7795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return ts.release();
78002772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch
7815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    RenderLayer* layer = renderer->layer();
7825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    writeLayers(ts, layer, layer, layer->rect(), 0, behavior);
7835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    writeSelection(ts, renderer);
7845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return ts.release();
7855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
7865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
7875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)String externalRepresentation(Frame* frame, RenderAsTextBehavior behavior)
7885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
7895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    RenderObject* renderer = frame->contentRenderer();
7905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!renderer || !renderer->isBox())
7915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return String();
7925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
7935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    PrintContext printContext(frame);
7945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (behavior & RenderAsTextPrintingMode)
7955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        printContext.begin(toRenderBox(renderer)->width());
7965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!(behavior & RenderAsTextDontUpdateLayout))
7975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        frame->document()->updateLayout();
7985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
7995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return externalRepresentation(toRenderBox(renderer), behavior);
8005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
8015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
8025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)String externalRepresentation(Element* element, RenderAsTextBehavior behavior)
8035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
8045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    RenderObject* renderer = element->renderer();
8055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!renderer || !renderer->isBox())
8065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return String();
8075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Doesn't support printing mode.
8085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ASSERT(!(behavior & RenderAsTextPrintingMode));
8095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!(behavior & RenderAsTextDontUpdateLayout) && element->document())
8105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        element->document()->updateLayout();
81102772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch
8125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return externalRepresentation(toRenderBox(renderer), behavior | RenderAsTextShowAllLayers);
8135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
8145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
8155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)static void writeCounterValuesFromChildren(TextStream& stream, RenderObject* parent, bool& isFirstCounter)
8165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
8175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    for (RenderObject* child = parent->firstChild(); child; child = child->nextSibling()) {
8185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (child->isCounter()) {
8195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            if (!isFirstCounter)
8205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                stream << " ";
8215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            isFirstCounter = false;
8225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            String str(toRenderText(child)->text());
8235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            stream << str;
8245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
8255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
8265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
8275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
8285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)String counterValueForElement(Element* element)
8295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
8305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Make sure the element is not freed during the layout.
8315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    RefPtr<Element> elementRef(element);
8325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    element->document()->updateLayout();
8335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    TextStream stream;
8345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    bool isFirstCounter = true;
8355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // The counter renderers should be children of :before or :after pseudo-elements.
836926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (RenderObject* before = element->pseudoElementRenderer(BEFORE))
837926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        writeCounterValuesFromChildren(stream, before, isFirstCounter);
838926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (RenderObject* after = element->pseudoElementRenderer(AFTER))
839926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        writeCounterValuesFromChildren(stream, after, isFirstCounter);
8405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return stream.release();
8415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
8425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
8435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)String markerTextForListItem(Element* element)
8445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
8455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Make sure the element is not freed during the layout.
8465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    RefPtr<Element> elementRef(element);
8475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    element->document()->updateLayout();
8485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
8495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    RenderObject* renderer = element->renderer();
8505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!renderer || !renderer->isListItem())
8515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return String();
8525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
8535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return toRenderListItem(renderer)->markerText();
8545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
8555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
8565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} // namespace WebCore
857