18f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian/* 28f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian * Copyright (C) 2008 Apple Inc. All rights reserved. 38f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian * 48f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian * Redistribution and use in source and binary forms, with or without 58f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian * modification, are permitted provided that the following conditions 68f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian * are met: 78f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian * 88f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian * 1. Redistributions of source code must retain the above copyright 98f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian * notice, this list of conditions and the following disclaimer. 108f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian * 2. Redistributions in binary form must reproduce the above copyright 118f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian * notice, this list of conditions and the following disclaimer in the 128f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian * documentation and/or other materials provided with the distribution. 138f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of 148f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian * its contributors may be used to endorse or promote products derived 158f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian * from this software without specific prior written permission. 168f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian * 178f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY 188f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 198f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 208f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY 218f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 228f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 238f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 248f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 258f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 268f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 278f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian */ 288f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian 298f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian#include "config.h" 308f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian#include "RenderLineBoxList.h" 318f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian 328f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian#include "InlineTextBox.h" 338f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian#include "RenderArena.h" 348f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian#include "RenderInline.h" 358f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian#include "RenderView.h" 368f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian#include "RootInlineBox.h" 378f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian 388f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qianusing namespace std; 398f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian 408f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qiannamespace WebCore { 418f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian 428f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian#ifndef NDEBUG 438f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng QianRenderLineBoxList::~RenderLineBoxList() 448f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian{ 458f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian ASSERT(!m_firstLineBox); 468f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian ASSERT(!m_lastLineBox); 478f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian} 488f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian#endif 498f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian 508f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qianvoid RenderLineBoxList::appendLineBox(InlineFlowBox* box) 518f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian{ 528f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian checkConsistency(); 538f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian 548f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian if (!m_firstLineBox) 558f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian m_firstLineBox = m_lastLineBox = box; 568f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian else { 578f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian m_lastLineBox->setNextLineBox(box); 588f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian box->setPreviousLineBox(m_lastLineBox); 598f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian m_lastLineBox = box; 608f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian } 618f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian 628f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian checkConsistency(); 638f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian} 648f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian 658f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qianvoid RenderLineBoxList::deleteLineBoxTree(RenderArena* arena) 668f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian{ 678f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian InlineFlowBox* line = m_firstLineBox; 688f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian InlineFlowBox* nextLine; 698f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian while (line) { 708f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian nextLine = line->nextFlowBox(); 718f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian line->deleteLine(arena); 728f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian line = nextLine; 738f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian } 748f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian m_firstLineBox = m_lastLineBox = 0; 758f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian} 768f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian 778f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qianvoid RenderLineBoxList::extractLineBox(InlineFlowBox* box) 788f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian{ 798f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian checkConsistency(); 808f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian 818f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian m_lastLineBox = box->prevFlowBox(); 828f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian if (box == m_firstLineBox) 838f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian m_firstLineBox = 0; 848f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian if (box->prevLineBox()) 858f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian box->prevLineBox()->setNextLineBox(0); 868f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian box->setPreviousLineBox(0); 878f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian for (InlineRunBox* curr = box; curr; curr = curr->nextLineBox()) 888f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian curr->setExtracted(); 898f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian 908f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian checkConsistency(); 918f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian} 928f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian 938f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qianvoid RenderLineBoxList::attachLineBox(InlineFlowBox* box) 948f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian{ 958f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian checkConsistency(); 968f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian 978f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian if (m_lastLineBox) { 988f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian m_lastLineBox->setNextLineBox(box); 998f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian box->setPreviousLineBox(m_lastLineBox); 1008f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian } else 1018f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian m_firstLineBox = box; 1028f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian InlineFlowBox* last = box; 1038f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian for (InlineFlowBox* curr = box; curr; curr = curr->nextFlowBox()) { 1048f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian curr->setExtracted(false); 1058f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian last = curr; 1068f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian } 1078f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian m_lastLineBox = last; 1088f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian 1098f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian checkConsistency(); 1108f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian} 1118f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian 1128f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qianvoid RenderLineBoxList::removeLineBox(InlineFlowBox* box) 1138f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian{ 1148f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian checkConsistency(); 1158f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian 1168f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian if (box == m_firstLineBox) 1178f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian m_firstLineBox = box->nextFlowBox(); 1188f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian if (box == m_lastLineBox) 1198f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian m_lastLineBox = box->prevFlowBox(); 1208f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian if (box->nextLineBox()) 1218f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian box->nextLineBox()->setPreviousLineBox(box->prevLineBox()); 1228f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian if (box->prevLineBox()) 1238f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian box->prevLineBox()->setNextLineBox(box->nextLineBox()); 1248f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian 1258f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian checkConsistency(); 1268f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian} 1278f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian 1288f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qianvoid RenderLineBoxList::deleteLineBoxes(RenderArena* arena) 1298f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian{ 1308f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian if (m_firstLineBox) { 1318f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian InlineRunBox* next; 1328f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian for (InlineRunBox* curr = m_firstLineBox; curr; curr = next) { 1338f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian next = curr->nextLineBox(); 1348f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian curr->destroy(arena); 1358f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian } 1368f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian m_firstLineBox = 0; 1378f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian m_lastLineBox = 0; 1388f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian } 1398f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian} 1408f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian 1418f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qianvoid RenderLineBoxList::dirtyLineBoxes() 1428f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian{ 1438f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian for (InlineRunBox* curr = firstLineBox(); curr; curr = curr->nextLineBox()) 1448f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian curr->dirtyLineBoxes(); 1458f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian} 1468f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian 1478f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qianvoid RenderLineBoxList::paint(RenderBoxModelObject* renderer, RenderObject::PaintInfo& paintInfo, int tx, int ty) const 1488f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian{ 1498f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian // Only paint during the foreground/selection phases. 1508f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian if (paintInfo.phase != PaintPhaseForeground && paintInfo.phase != PaintPhaseSelection && paintInfo.phase != PaintPhaseOutline 1518f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian && paintInfo.phase != PaintPhaseSelfOutline && paintInfo.phase != PaintPhaseChildOutlines && paintInfo.phase != PaintPhaseTextClip 1528f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian && paintInfo.phase != PaintPhaseMask) 1538f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian return; 1548f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian 1558f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian ASSERT(renderer->isRenderBlock() || (renderer->isRenderInline() && renderer->hasLayer())); // The only way an inline could paint like this is if it has a layer. 1568f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian 1578f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian // If we have no lines then we have no work to do. 1588f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian if (!firstLineBox()) 1598f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian return; 1608f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian 1618f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian // We can check the first box and last box and avoid painting if we don't 1628f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian // intersect. This is a quick short-circuit that we can take to avoid walking any lines. 1638f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian // FIXME: This check is flawed in the following extremely obscure way: 1648f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian // if some line in the middle has a huge overflow, it might actually extend below the last line. 165231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block int yPos = firstLineBox()->topVisibleOverflow() - renderer->maximalOutlineSize(paintInfo.phase); 166231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block int h = renderer->maximalOutlineSize(paintInfo.phase) + lastLineBox()->bottomVisibleOverflow() - yPos; 1678f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian yPos += ty; 1688f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian if (yPos >= paintInfo.rect.bottom() || yPos + h <= paintInfo.rect.y()) 1698f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian return; 1708f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian 1718f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian RenderObject::PaintInfo info(paintInfo); 1728f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian ListHashSet<RenderInline*> outlineObjects; 1738f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian info.outlineObjects = &outlineObjects; 1748f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian 1758f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian // See if our root lines intersect with the dirty rect. If so, then we paint 1768f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian // them. Note that boxes can easily overlap, so we can't make any assumptions 1778f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian // based off positions of our first line box or our last line box. 1788f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian RenderView* v = renderer->view(); 1798f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian bool usePrintRect = !v->printRect().isEmpty(); 1808f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian for (InlineFlowBox* curr = firstLineBox(); curr; curr = curr->nextFlowBox()) { 1818f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian if (usePrintRect) { 1828f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian // FIXME: This is a feeble effort to avoid splitting a line across two pages. 1838f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian // It is utterly inadequate, and this should not be done at paint time at all. 1848f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian // The whole way objects break across pages needs to be redone. 1858f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian // Try to avoid splitting a line vertically, but only if it's less than the height 1868f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian // of the entire page. 187231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block if (curr->bottomVisibleOverflow() - curr->topVisibleOverflow() <= v->printRect().height()) { 188231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block if (ty + curr->bottomVisibleOverflow() > v->printRect().bottom()) { 189231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block if (ty + curr->topVisibleOverflow() < v->truncatedAt()) 190231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block v->setBestTruncatedAt(ty + curr->root()->topVisibleOverflow(), renderer); 1918f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian // If we were able to truncate, don't paint. 192231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block if (ty + curr->topVisibleOverflow() >= v->truncatedAt()) 1938f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian break; 1948f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian } 1958f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian } 1968f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian } 1978f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian 198231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block int top = min(curr->topVisibleOverflow(), curr->root()->selectionTop()) - renderer->maximalOutlineSize(info.phase); 199231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block int bottom = curr->bottomVisibleOverflow() + renderer->maximalOutlineSize(info.phase); 2008f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian h = bottom - top; 2018f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian yPos = ty + top; 202643ca7872b450ea4efacab6188849e5aac2ba161Steve Block v->setMinimumColumnHeight(h); 2038f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian if (yPos < info.rect.bottom() && yPos + h > info.rect.y()) 2048f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian curr->paint(info, tx, ty); 2058f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian } 2068f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian 2078f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian if (info.phase == PaintPhaseOutline || info.phase == PaintPhaseSelfOutline || info.phase == PaintPhaseChildOutlines) { 2088f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian ListHashSet<RenderInline*>::iterator end = info.outlineObjects->end(); 2098f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian for (ListHashSet<RenderInline*>::iterator it = info.outlineObjects->begin(); it != end; ++it) { 2108f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian RenderInline* flow = *it; 2118f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian flow->paintOutline(info.context, tx, ty); 2128f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian } 2138f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian info.outlineObjects->clear(); 2148f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian } 2158f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian} 2168f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian 2178f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian 2188f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qianbool RenderLineBoxList::hitTest(RenderBoxModelObject* renderer, const HitTestRequest& request, HitTestResult& result, int x, int y, int tx, int ty, HitTestAction hitTestAction) const 2198f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian{ 2208f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian if (hitTestAction != HitTestForeground) 2218f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian return false; 2228f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian 2238f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian ASSERT(renderer->isRenderBlock() || (renderer->isRenderInline() && renderer->hasLayer())); // The only way an inline could hit test like this is if it has a layer. 2248f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian 2258f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian // If we have no lines then we have no work to do. 2268f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian if (!firstLineBox()) 2278f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian return false; 2288f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian 2298f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian // We can check the first box and last box and avoid hit testing if we don't 2308f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian // contain the point. This is a quick short-circuit that we can take to avoid walking any lines. 2318f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian // FIXME: This check is flawed in the following extremely obscure way: 2328f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian // if some line in the middle has a huge overflow, it might actually extend below the last line. 233231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block if ((y >= ty + lastLineBox()->root()->bottomVisibleOverflow()) || (y < ty + firstLineBox()->root()->topVisibleOverflow())) 2348f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian return false; 2358f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian 2368f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian // See if our root lines contain the point. If so, then we hit test 2378f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian // them further. Note that boxes can easily overlap, so we can't make any assumptions 2388f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian // based off positions of our first line box or our last line box. 2398f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian for (InlineFlowBox* curr = lastLineBox(); curr; curr = curr->prevFlowBox()) { 240231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block if (y >= ty + curr->root()->topVisibleOverflow() && y < ty + curr->root()->bottomVisibleOverflow()) { 2418f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian bool inside = curr->nodeAtPoint(request, result, x, y, tx, ty); 2428f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian if (inside) { 2438f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian renderer->updateHitTestResult(result, IntPoint(x - tx, y - ty)); 2448f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian return true; 2458f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian } 2468f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian } 2478f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian } 2488f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian 2498f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian return false; 2508f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian} 2518f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian 2528f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qianvoid RenderLineBoxList::dirtyLinesFromChangedChild(RenderObject* container, RenderObject* child) 2538f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian{ 2548f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian if (!container->parent() || (container->isRenderBlock() && (container->selfNeedsLayout() || !container->isBlockFlow()))) 2558f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian return; 2568f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian 2578f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian // If we have no first line box, then just bail early. 2588f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian if (!firstLineBox()) { 2598f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian // For an empty inline, go ahead and propagate the check up to our parent, unless the parent 2608f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian // is already dirty. 2618f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian if (container->isInline() && !container->parent()->selfNeedsLayout()) 2628f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian container->parent()->dirtyLinesFromChangedChild(container); 2638f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian return; 2648f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian } 2658f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian 2668f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian // Try to figure out which line box we belong in. First try to find a previous 2678f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian // line box by examining our siblings. If we didn't find a line box, then use our 2688f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian // parent's first line box. 2698f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian RootInlineBox* box = 0; 2708f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian RenderObject* curr = 0; 2718f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian for (curr = child->previousSibling(); curr; curr = curr->previousSibling()) { 2728f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian if (curr->isFloatingOrPositioned()) 2738f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian continue; 2748f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian 2758f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian if (curr->isReplaced()) { 2768f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian InlineBox* wrapper = toRenderBox(curr)->inlineBoxWrapper(); 2778f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian if (wrapper) 2788f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian box = wrapper->root(); 2798f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian } else if (curr->isText()) { 2808f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian InlineTextBox* textBox = toRenderText(curr)->lastTextBox(); 2818f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian if (textBox) 2828f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian box = textBox->root(); 2838f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian } else if (curr->isRenderInline()) { 2848f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian InlineRunBox* runBox = toRenderInline(curr)->lastLineBox(); 2858f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian if (runBox) 2868f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian box = runBox->root(); 2878f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian } 2888f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian 2898f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian if (box) 2908f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian break; 2918f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian } 2928f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian if (!box) 2938f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian box = firstLineBox()->root(); 2948f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian 2958f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian // If we found a line box, then dirty it. 2968f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian if (box) { 2978f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian RootInlineBox* adjacentBox; 2988f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian box->markDirty(); 2998f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian 3008f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian // dirty the adjacent lines that might be affected 3018f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian // NOTE: we dirty the previous line because RootInlineBox objects cache 3028f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian // the address of the first object on the next line after a BR, which we may be 3038f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian // invalidating here. For more info, see how RenderBlock::layoutInlineChildren 3048f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian // calls setLineBreakInfo with the result of findNextLineBreak. findNextLineBreak, 3058f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian // despite the name, actually returns the first RenderObject after the BR. 3068f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian // <rdar://problem/3849947> "Typing after pasting line does not appear until after window resize." 3078f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian adjacentBox = box->prevRootBox(); 3088f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian if (adjacentBox) 3098f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian adjacentBox->markDirty(); 3108f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian if (child->isBR() || (curr && curr->isBR())) { 3118f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian adjacentBox = box->nextRootBox(); 3128f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian if (adjacentBox) 3138f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian adjacentBox->markDirty(); 3148f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian } 3158f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian } 3168f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian} 3178f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian 3188f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian#ifndef NDEBUG 3198f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian 3208f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qianvoid RenderLineBoxList::checkConsistency() const 3218f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian{ 3228f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian#ifdef CHECK_CONSISTENCY 3238f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian const InlineFlowBox* prev = 0; 3248f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian for (const InlineFlowBox* child = m_firstLineBox; child != 0; child = child->nextFlowBox()) { 3258f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian ASSERT(child->prevFlowBox() == prev); 3268f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian prev = child; 3278f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian } 3288f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian ASSERT(prev == m_lastLineBox); 3298f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian#endif 3308f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian} 3318f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian 3328f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian#endif 3338f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian 3348f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian} 335