| /* |
| * Copyright (C) 2018 Apple Inc. All Rights Reserved. |
| * |
| * Redistribution and use in source and binary forms, with or without |
| * modification, are permitted provided that the following conditions |
| * are met: |
| * 1. Redistributions of source code must retain the above copyright |
| * notice, this list of conditions and the following disclaimer. |
| * 2. Redistributions in binary form must reproduce the above copyright |
| * notice, this list of conditions and the following disclaimer in the |
| * documentation and/or other materials provided with the distribution. |
| * |
| * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY |
| * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
| * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
| * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR |
| * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, |
| * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, |
| * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR |
| * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY |
| * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
| * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| */ |
| |
| // 1()RenderView|2(1)RenderBlock|3(2)RenderBody|4(3)RenderBlock|5(3)AnonymousRenderBlock| |
| class TreeBuilder { |
| |
| createTree(document, renderTreeDump) { |
| // Root. |
| let initialBlockContainer = new Layout.BlockContainer(document, parseInt(renderTreeDump.substring(0, renderTreeDump.indexOf("(")))); |
| initialBlockContainer.setRendererName("RenderView"); |
| renderTreeDump = renderTreeDump.substring(renderTreeDump.indexOf("|") + 1); |
| |
| while (true) { |
| let endOfId = renderTreeDump.indexOf("("); |
| let boxId = parseInt(renderTreeDump.substring(0, endOfId)); |
| let endOfParentId = renderTreeDump.indexOf(")"); |
| let parentId = parseInt(renderTreeDump.substring(endOfId + 1, endOfParentId)); |
| let endOfName = renderTreeDump.indexOf("|"); |
| let name = renderTreeDump.substring(endOfParentId + 1, endOfName); |
| |
| this._createAndAttachBox(initialBlockContainer, boxId, name, parentId); |
| if (endOfName == renderTreeDump.length - 1) |
| break; |
| renderTreeDump = renderTreeDump.substring(endOfName + 1); |
| } |
| return initialBlockContainer; |
| } |
| |
| _createAndAttachBox(initialBlockContainer, id, name, parentId) { |
| let box = null; |
| let text = null; |
| let node = this._findNode(initialBlockContainer.node(), id, name); |
| if (name == "RenderBlock" || name == "RenderBody") |
| box = new Layout.BlockContainer(node, id); |
| else if (name == "RenderInline") |
| box = new Layout.InlineContainer(node, id); |
| else if (name == "RenderText") |
| text = new Text(node, id); |
| else if (name == "RenderImage") |
| box = new Layout.InlineBox(node, id); |
| else |
| box = new Layout.Box(node, id); |
| |
| if (box) |
| box.setRendererName(name); |
| |
| let parentBox = Utils.layoutBoxById(parentId, initialBlockContainer); |
| // WebKit does not construct anonymous inline container for text if the text |
| // is a direct child of a block container. |
| if (text) { |
| box = new Layout.InlineBox(null, -1); |
| box.setIsAnonymous(); |
| box.setText(text); |
| } |
| this._appendChild(parentBox, box); |
| return box; |
| } |
| |
| _appendChild(parent, child) { |
| child.setParent(parent); |
| let firstChild = parent.firstChild(); |
| if (!firstChild) { |
| parent.setFirstChild(child); |
| parent.setLastChild(child); |
| return; |
| } |
| let lastChild = parent.lastChild(); |
| lastChild.setNextSibling(child); |
| child.setPreviousSibling(lastChild); |
| parent.setLastChild(child); |
| } |
| |
| _findNode(node, boxId) { |
| // Super inefficient but this is all temporary anyway. |
| for (let currentNode = node.firstChild; currentNode; currentNode = currentNode.nextSibling) { |
| if (currentNode.rendererId == boxId) |
| return currentNode; |
| let candidate = this._findNode(currentNode, boxId); |
| if (candidate) |
| return candidate; |
| } |
| } |
| } |