blob: bb0820d8149c73cfa736f063083513f6ef30e128 [file] [log] [blame]
// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "core/paint/LineBoxListPainter.h"
#include "core/layout/LayoutBoxModelObject.h"
#include "core/layout/api/LineLayoutBoxModel.h"
#include "core/layout/line/InlineFlowBox.h"
#include "core/layout/line/LineBoxList.h"
#include "core/layout/line/RootInlineBox.h"
#include "core/paint/ObjectPainter.h"
#include "core/paint/PaintInfo.h"
#include "platform/graphics/paint/PaintController.h"
namespace blink {
static void addPDFURLRectsForInlineChildrenRecursively(
const LayoutObject& layoutObject,
const PaintInfo& paintInfo,
const LayoutPoint& paintOffset) {
for (LayoutObject* child = layoutObject.slowFirstChild(); child;
child = child->nextSibling()) {
if (!child->isLayoutInline() ||
toLayoutBoxModelObject(child)->hasSelfPaintingLayer())
continue;
ObjectPainter(*child).addPDFURLRectIfNeeded(paintInfo, paintOffset);
addPDFURLRectsForInlineChildrenRecursively(*child, paintInfo, paintOffset);
}
}
void LineBoxListPainter::paint(const LayoutBoxModelObject& layoutObject,
const PaintInfo& paintInfo,
const LayoutPoint& paintOffset) const {
DCHECK(!shouldPaintSelfOutline(paintInfo.phase) &&
!shouldPaintDescendantOutlines(paintInfo.phase));
// Only paint during the foreground/selection phases.
if (paintInfo.phase != PaintPhaseForeground &&
paintInfo.phase != PaintPhaseSelection &&
paintInfo.phase != PaintPhaseTextClip &&
paintInfo.phase != PaintPhaseMask)
return;
// The only way an inline could paint like this is if it has a layer.
DCHECK(layoutObject.isLayoutBlock() ||
(layoutObject.isLayoutInline() && layoutObject.hasLayer()));
if (paintInfo.phase == PaintPhaseForeground && paintInfo.isPrinting())
addPDFURLRectsForInlineChildrenRecursively(layoutObject, paintInfo,
paintOffset);
// If we have no lines then we have no work to do.
if (!m_lineBoxList.firstLineBox())
return;
if (!m_lineBoxList.anyLineIntersectsRect(
LineLayoutBoxModel(const_cast<LayoutBoxModelObject*>(&layoutObject)),
paintInfo.cullRect(), paintOffset))
return;
PaintInfo info(paintInfo);
// See if our root lines intersect with the dirty rect. If so, then we paint
// them. Note that boxes can easily overlap, so we can't make any assumptions
// based off positions of our first line box or our last line box.
for (InlineFlowBox* curr = m_lineBoxList.firstLineBox(); curr;
curr = curr->nextLineBox()) {
if (m_lineBoxList.lineIntersectsDirtyRect(
LineLayoutBoxModel(
const_cast<LayoutBoxModelObject*>(&layoutObject)),
curr, info.cullRect(), paintOffset)) {
RootInlineBox& root = curr->root();
curr->paint(info, paintOffset, root.lineTop(), root.lineBottom());
}
}
}
static void invalidateLineBoxPaintOffsetsInternal(
PaintController& paintController,
InlineFlowBox* inlineBox) {
#if 0
// TODO(wangxianzhu): Implement this with PaintInvalidator.
paintController.invalidatePaintOffset(*inlineBox);
for (InlineBox* child = inlineBox->firstChild(); child; child = child->nextOnLine()) {
if (!child->getLineLayoutItem().isText() && child->boxModelObject().hasSelfPaintingLayer())
continue;
if (child->isInlineFlowBox())
invalidateLineBoxPaintOffsetsInternal(paintController, toInlineFlowBox(child));
else
paintController.invalidatePaintOffset(*child);
}
#endif
}
void LineBoxListPainter::invalidateLineBoxPaintOffsets(
const PaintInfo& paintInfo) const {
PaintController& paintController = paintInfo.context.getPaintController();
for (InlineFlowBox* curr = m_lineBoxList.firstLineBox(); curr;
curr = curr->nextLineBox())
invalidateLineBoxPaintOffsetsInternal(paintController, curr);
}
} // namespace blink