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