Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(298)

Side by Side Diff: Source/core/paint/BlockPainter.cpp

Issue 569683004: Factor painting code from RenderBlock into BlockPainter. (Closed) Base URL: svn://svn.chromium.org/blink/trunk
Patch Set: Fixed Created 6 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « Source/core/paint/BlockPainter.h ('k') | Source/core/rendering/InlineBox.cpp » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "config.h"
6 #include "core/paint/BlockPainter.h"
7
8 #include "core/editing/Caret.h"
9 #include "core/editing/FrameSelection.h"
10 #include "core/frame/LocalFrame.h"
11 #include "core/frame/Settings.h"
12 #include "core/page/Page.h"
13 #include "core/paint/BoxPainter.h"
14 #include "core/rendering/GraphicsContextAnnotator.h"
15 #include "core/rendering/PaintInfo.h"
16 #include "core/rendering/RenderBlock.h"
17 #include "core/rendering/RenderInline.h"
18 #include "core/rendering/RenderLayer.h"
19 #include "platform/geometry/LayoutPoint.h"
20 #include "platform/geometry/LayoutRect.h"
21 #include "platform/graphics/GraphicsContextCullSaver.h"
22 #include "platform/graphics/GraphicsContextStateSaver.h"
23
24 namespace blink {
25
26 void BlockPainter::paint(PaintInfo& paintInfo, const LayoutPoint& paintOffset)
27 {
28 ANNOTATE_GRAPHICS_CONTEXT(paintInfo, &m_renderBlock);
29
30 LayoutPoint adjustedPaintOffset = paintOffset + m_renderBlock.location();
31
32 PaintPhase phase = paintInfo.phase;
33
34 LayoutRect overflowBox;
35 // Check if we need to do anything at all.
36 // FIXME: Could eliminate the isDocumentElement() check if we fix background painting so that the RenderView
37 // paints the root's background.
38 if (!m_renderBlock.isDocumentElement()) {
39 overflowBox = overflowRectForPaintRejection();
40 m_renderBlock.flipForWritingMode(overflowBox);
41 overflowBox.moveBy(adjustedPaintOffset);
42 if (!overflowBox.intersects(paintInfo.rect))
43 return;
44 }
45
46 // There are some cases where not all clipped visual overflow is accounted f or.
47 // FIXME: reduce the number of such cases.
48 ContentsClipBehavior contentsClipBehavior = ForceContentsClip;
49 if (m_renderBlock.hasOverflowClip() && !m_renderBlock.hasControlClip() && !( m_renderBlock.shouldPaintSelectionGaps() && phase == PaintPhaseForeground) && !h asCaret())
50 contentsClipBehavior = SkipContentsClipIfPossible;
51
52 bool pushedClip = m_renderBlock.pushContentsClip(paintInfo, adjustedPaintOff set, contentsClipBehavior);
53 {
54 GraphicsContextCullSaver cullSaver(*paintInfo.context);
55 // Cull if we have more than one child and we didn't already clip.
56 bool shouldCull = m_renderBlock.document().settings()->containerCullingE nabled() && !pushedClip && !m_renderBlock.isDocumentElement()
57 && m_renderBlock.firstChild() && m_renderBlock.lastChild() && m_rend erBlock.firstChild() != m_renderBlock.lastChild();
58 if (shouldCull)
59 cullSaver.cull(overflowBox);
60
61 m_renderBlock.paintObject(paintInfo, adjustedPaintOffset);
62 }
63 // FIXME: move popContentsClip out of RenderBox.
64 if (pushedClip)
65 m_renderBlock.popContentsClip(paintInfo, phase, adjustedPaintOffset);
66
67 // Our scrollbar widgets paint exactly when we tell them to, so that they wo rk properly with
68 // z-index. We paint after we painted the background/border, so that the scr ollbars will
69 // sit above the background/border.
70 if (m_renderBlock.hasOverflowClip() && m_renderBlock.style()->visibility() = = VISIBLE && (phase == PaintPhaseBlockBackground || phase == PaintPhaseChildBloc kBackground) && paintInfo.shouldPaintWithinRoot(&m_renderBlock) && !paintInfo.pa intRootBackgroundOnly())
71 m_renderBlock.layer()->scrollableArea()->paintOverflowControls(paintInfo .context, roundedIntPoint(adjustedPaintOffset), paintInfo.rect, false /* paintin gOverlayControls */);
72 }
73
74 void BlockPainter::paintChildren(PaintInfo& paintInfo, const LayoutPoint& paintO ffset)
75 {
76 for (RenderBox* child = m_renderBlock.firstChildBox(); child; child = child- >nextSiblingBox())
77 paintChild(child, paintInfo, paintOffset);
78 }
79
80 void BlockPainter::paintChild(RenderBox* child, PaintInfo& paintInfo, const Layo utPoint& paintOffset)
81 {
82 LayoutPoint childPoint = m_renderBlock.flipForWritingModeForChild(child, pai ntOffset);
83 if (!child->hasSelfPaintingLayer() && !child->isFloating())
84 child->paint(paintInfo, childPoint);
85 }
86
87 void BlockPainter::paintChildAsInlineBlock(RenderBox* child, PaintInfo& paintInf o, const LayoutPoint& paintOffset)
88 {
89 LayoutPoint childPoint = m_renderBlock.flipForWritingModeForChild(child, pai ntOffset);
90 if (!child->hasSelfPaintingLayer() && !child->isFloating())
91 paintAsInlineBlock(child, paintInfo, childPoint);
92 }
93
94 void BlockPainter::paintAsInlineBlock(RenderObject* renderer, PaintInfo& paintIn fo, const LayoutPoint& childPoint)
95 {
96 if (paintInfo.phase != PaintPhaseForeground && paintInfo.phase != PaintPhase Selection)
97 return;
98
99 // Paint all phases atomically, as though the element established its own
100 // stacking context. (See Appendix E.2, section 7.2.1.4 on
101 // inline block/table/replaced elements in the CSS2.1 specification.)
102 // This is also used by other elements (e.g. flex items and grid items).
103 bool preservePhase = paintInfo.phase == PaintPhaseSelection || paintInfo.pha se == PaintPhaseTextClip;
104 PaintInfo info(paintInfo);
105 info.phase = preservePhase ? paintInfo.phase : PaintPhaseBlockBackground;
106 renderer->paint(info, childPoint);
107 if (!preservePhase) {
108 info.phase = PaintPhaseChildBlockBackgrounds;
109 renderer->paint(info, childPoint);
110 info.phase = PaintPhaseFloat;
111 renderer->paint(info, childPoint);
112 info.phase = PaintPhaseForeground;
113 renderer->paint(info, childPoint);
114 info.phase = PaintPhaseOutline;
115 renderer->paint(info, childPoint);
116 }
117 }
118
119 void BlockPainter::paintObject(PaintInfo& paintInfo, const LayoutPoint& paintOff set)
120 {
121 PaintPhase paintPhase = paintInfo.phase;
122
123 // Adjust our painting position if we're inside a scrolled layer (e.g., an o verflow:auto div).
124 LayoutPoint scrolledOffset = paintOffset;
125 if (m_renderBlock.hasOverflowClip())
126 scrolledOffset.move(-m_renderBlock.scrolledContentOffset());
127
128 // 1. paint background, borders etc
129 if ((paintPhase == PaintPhaseBlockBackground || paintPhase == PaintPhaseChil dBlockBackground) && m_renderBlock.style()->visibility() == VISIBLE) {
130 if (m_renderBlock.hasBoxDecorationBackground())
131 m_renderBlock.paintBoxDecorationBackground(paintInfo, paintOffset);
132 if (m_renderBlock.hasColumns() && !paintInfo.paintRootBackgroundOnly())
133 paintColumnRules(paintInfo, scrolledOffset);
134 }
135
136 if (paintPhase == PaintPhaseMask && m_renderBlock.style()->visibility() == V ISIBLE) {
137 m_renderBlock.paintMask(paintInfo, paintOffset);
138 return;
139 }
140
141 if (paintPhase == PaintPhaseClippingMask && m_renderBlock.style()->visibilit y() == VISIBLE) {
142 m_renderBlock.paintClippingMask(paintInfo, paintOffset);
143 return;
144 }
145
146 // We're done. We don't bother painting any children.
147 if (paintPhase == PaintPhaseBlockBackground || paintInfo.paintRootBackground Only())
148 return;
149
150 // 2. paint contents
151 if (paintPhase != PaintPhaseSelfOutline) {
152 if (m_renderBlock.hasColumns())
153 paintColumnContents(paintInfo, scrolledOffset);
154 else
155 paintContents(paintInfo, scrolledOffset);
156 }
157
158 // 3. paint selection
159 // FIXME: Make this work with multi column layouts. For now don't fill gaps.
160 bool isPrinting = m_renderBlock.document().printing();
161 if (!isPrinting && !m_renderBlock.hasColumns())
162 paintSelection(paintInfo, scrolledOffset); // Fill in gaps in selection on lines and between blocks.
163
164 // 4. paint floats.
165 if (paintPhase == PaintPhaseFloat || paintPhase == PaintPhaseSelection || pa intPhase == PaintPhaseTextClip) {
166 if (m_renderBlock.hasColumns())
167 paintColumnContents(paintInfo, scrolledOffset, true);
168 else
169 m_renderBlock.paintFloats(paintInfo, scrolledOffset, paintPhase == P aintPhaseSelection || paintPhase == PaintPhaseTextClip);
170 }
171
172 // 5. paint outline.
173 if ((paintPhase == PaintPhaseOutline || paintPhase == PaintPhaseSelfOutline) && m_renderBlock.style()->hasOutline() && m_renderBlock.style()->visibility() = = VISIBLE) {
174 // Don't paint focus ring for anonymous block continuation because the
175 // inline element having outline-style:auto paints the whole focus ring.
176 if (!m_renderBlock.style()->outlineStyleIsAuto() || !m_renderBlock.isAno nymousBlockContinuation())
177 m_renderBlock.paintOutline(paintInfo, LayoutRect(paintOffset, m_rend erBlock.size()));
178 }
179
180 // 6. paint continuation outlines.
181 if ((paintPhase == PaintPhaseOutline || paintPhase == PaintPhaseChildOutline s))
182 paintContinuationOutlines(paintInfo, paintOffset);
183
184 // 7. paint caret.
185 // If the caret's node's render object's containing block is this block, and the paint action is PaintPhaseForeground,
186 // then paint the caret.
187 if (paintPhase == PaintPhaseForeground)
188 paintCarets(paintInfo, paintOffset);
189 }
190
191 static inline bool caretBrowsingEnabled(const Frame* frame)
192 {
193 Settings* settings = frame->settings();
194 return settings && settings->caretBrowsingEnabled();
195 }
196
197 static inline bool hasCursorCaret(const FrameSelection& selection, const RenderB lock* block, bool caretBrowsing)
198 {
199 return selection.caretRenderer() == block && (selection.hasEditableStyle() | | caretBrowsing);
200 }
201
202 static inline bool hasDragCaret(const DragCaretController& dragCaretController, const RenderBlock* block, bool caretBrowsing)
203 {
204 return dragCaretController.caretRenderer() == block && (dragCaretController. isContentEditable() || caretBrowsing);
205 }
206
207 void BlockPainter::paintCarets(PaintInfo& paintInfo, const LayoutPoint& paintOff set)
208 {
209 bool caretBrowsing = caretBrowsingEnabled(m_renderBlock.frame());
210
211 FrameSelection& selection = m_renderBlock.frame()->selection();
212 if (hasCursorCaret(selection, &m_renderBlock, caretBrowsing)) {
213 selection.paintCaret(paintInfo.context, paintOffset, paintInfo.rect);
214 }
215
216 DragCaretController& dragCaretController = m_renderBlock.frame()->page()->dr agCaretController();
217 if (hasDragCaret(dragCaretController, &m_renderBlock, caretBrowsing)) {
218 dragCaretController.paintDragCaret(m_renderBlock.frame(), paintInfo.cont ext, paintOffset, paintInfo.rect);
219 }
220 }
221
222 LayoutRect BlockPainter::overflowRectForPaintRejection() const
223 {
224 LayoutRect overflowRect = m_renderBlock.visualOverflowRect();
225 if (!m_renderBlock.hasRenderOverflow() || !m_renderBlock.usesCompositedScrol ling())
226 return overflowRect;
227
228 overflowRect.unite(m_renderBlock.layoutOverflowRect());
229 overflowRect.move(-m_renderBlock.scrolledContentOffset());
230 return overflowRect;
231 }
232
233 bool BlockPainter::hasCaret() const
234 {
235 bool caretBrowsing = caretBrowsingEnabled(m_renderBlock.frame());
236 return hasCursorCaret(m_renderBlock.frame()->selection(), &m_renderBlock, ca retBrowsing)
237 || hasDragCaret(m_renderBlock.frame()->page()->dragCaretController(), &m _renderBlock, caretBrowsing);
238 }
239
240 void BlockPainter::paintColumnRules(PaintInfo& paintInfo, const LayoutPoint& pai ntOffset)
241 {
242 const Color& ruleColor = m_renderBlock.resolveColor(CSSPropertyWebkitColumnR uleColor);
243 bool ruleTransparent = m_renderBlock.style()->columnRuleIsTransparent();
244 EBorderStyle ruleStyle = m_renderBlock.style()->columnRuleStyle();
245 LayoutUnit ruleThickness = m_renderBlock.style()->columnRuleWidth();
246 LayoutUnit colGap = m_renderBlock.columnGap();
247 bool renderRule = ruleStyle > BHIDDEN && !ruleTransparent;
248 if (!renderRule)
249 return;
250
251 ColumnInfo* colInfo = m_renderBlock.columnInfo();
252 unsigned colCount = m_renderBlock.columnCount(colInfo);
253
254 bool antialias = BoxPainter::shouldAntialiasLines(paintInfo.context);
255
256 if (colInfo->progressionAxis() == ColumnInfo::InlineAxis) {
257 bool leftToRight = m_renderBlock.style()->isLeftToRightDirection();
258 LayoutUnit currLogicalLeftOffset = leftToRight ? LayoutUnit() : m_render Block.contentLogicalWidth();
259 LayoutUnit ruleAdd = m_renderBlock.logicalLeftOffsetForContent();
260 LayoutUnit ruleLogicalLeft = leftToRight ? LayoutUnit() : m_renderBlock. contentLogicalWidth();
261 LayoutUnit inlineDirectionSize = colInfo->desiredColumnWidth();
262 BoxSide boxSide = m_renderBlock.isHorizontalWritingMode()
263 ? leftToRight ? BSLeft : BSRight
264 : leftToRight ? BSTop : BSBottom;
265
266 for (unsigned i = 0; i < colCount; i++) {
267 // Move to the next position.
268 if (leftToRight) {
269 ruleLogicalLeft += inlineDirectionSize + colGap / 2;
270 currLogicalLeftOffset += inlineDirectionSize + colGap;
271 } else {
272 ruleLogicalLeft -= (inlineDirectionSize + colGap / 2);
273 currLogicalLeftOffset -= (inlineDirectionSize + colGap);
274 }
275
276 // Now paint the column rule.
277 if (i < colCount - 1) {
278 LayoutUnit ruleLeft = m_renderBlock.isHorizontalWritingMode() ? paintOffset.x() + ruleLogicalLeft - ruleThickness / 2 + ruleAdd : paintOffset.x( ) + m_renderBlock.borderLeft() + m_renderBlock.paddingLeft();
279 LayoutUnit ruleRight = m_renderBlock.isHorizontalWritingMode() ? ruleLeft + ruleThickness : ruleLeft + m_renderBlock.contentWidth();
280 LayoutUnit ruleTop = m_renderBlock.isHorizontalWritingMode() ? p aintOffset.y() + m_renderBlock.borderTop() + m_renderBlock.paddingTop() : paintO ffset.y() + ruleLogicalLeft - ruleThickness / 2 + ruleAdd;
281 LayoutUnit ruleBottom = m_renderBlock.isHorizontalWritingMode() ? ruleTop + m_renderBlock.contentHeight() : ruleTop + ruleThickness;
282 IntRect pixelSnappedRuleRect = pixelSnappedIntRectFromEdges(rule Left, ruleTop, ruleRight, ruleBottom);
283 m_renderBlock.drawLineForBoxSide(paintInfo.context, pixelSnapped RuleRect.x(), pixelSnappedRuleRect.y(), pixelSnappedRuleRect.maxX(), pixelSnappe dRuleRect.maxY(), boxSide, ruleColor, ruleStyle, 0, 0, antialias);
284 }
285
286 ruleLogicalLeft = currLogicalLeftOffset;
287 }
288 } else {
289 bool topToBottom = !m_renderBlock.style()->isFlippedBlocksWritingMode();
290 LayoutUnit ruleLeft = m_renderBlock.isHorizontalWritingMode()
291 ? m_renderBlock.borderLeft() + m_renderBlock.paddingLeft()
292 : colGap / 2 - colGap - ruleThickness / 2 + m_renderBlock.borderBefo re() + m_renderBlock.paddingBefore();
293 LayoutUnit ruleWidth = m_renderBlock.isHorizontalWritingMode() ? m_rende rBlock.contentWidth() : ruleThickness;
294 LayoutUnit ruleTop = m_renderBlock.isHorizontalWritingMode()
295 ? colGap / 2 - colGap - ruleThickness / 2 + m_renderBlock.borderBefo re() + m_renderBlock.paddingBefore()
296 : m_renderBlock.borderStart() + m_renderBlock.paddingStart();
297 LayoutUnit ruleHeight = m_renderBlock.isHorizontalWritingMode() ? ruleTh ickness : m_renderBlock.contentHeight();
298 LayoutRect ruleRect(ruleLeft, ruleTop, ruleWidth, ruleHeight);
299
300 if (!topToBottom) {
301 if (m_renderBlock.isHorizontalWritingMode())
302 ruleRect.setY(m_renderBlock.height() - ruleRect.maxY());
303 else
304 ruleRect.setX(m_renderBlock.width() - ruleRect.maxX());
305 }
306
307 ruleRect.moveBy(paintOffset);
308
309 BoxSide boxSide = m_renderBlock.isHorizontalWritingMode()
310 ? topToBottom ? BSTop : BSBottom
311 : topToBottom ? BSLeft : BSRight;
312
313 LayoutSize step(0, topToBottom ? colInfo->columnHeight() + colGap : -(co lInfo->columnHeight() + colGap));
314 if (!m_renderBlock.isHorizontalWritingMode())
315 step = step.transposedSize();
316
317 for (unsigned i = 1; i < colCount; i++) {
318 ruleRect.move(step);
319 IntRect pixelSnappedRuleRect = pixelSnappedIntRect(ruleRect);
320 m_renderBlock.drawLineForBoxSide(paintInfo.context, pixelSnappedRule Rect.x(), pixelSnappedRuleRect.y(), pixelSnappedRuleRect.maxX(), pixelSnappedRul eRect.maxY(), boxSide, ruleColor, ruleStyle, 0, 0, antialias);
321 }
322 }
323 }
324
325 void BlockPainter::paintColumnContents(PaintInfo& paintInfo, const LayoutPoint& paintOffset, bool paintingFloats)
326 {
327 // We need to do multiple passes, breaking up our child painting into strips .
328 GraphicsContext* context = paintInfo.context;
329 ColumnInfo* colInfo = m_renderBlock.columnInfo();
330 unsigned colCount = m_renderBlock.columnCount(colInfo);
331 if (!colCount)
332 return;
333 LayoutUnit currLogicalTopOffset = 0;
334 LayoutUnit colGap = m_renderBlock.columnGap();
335 for (unsigned i = 0; i < colCount; i++) {
336 // For each rect, we clip to the rect, and then we adjust our coords.
337 LayoutRect colRect = m_renderBlock.columnRectAt(colInfo, i);
338 m_renderBlock.flipForWritingMode(colRect);
339 LayoutUnit logicalLeftOffset = (m_renderBlock.isHorizontalWritingMode() ? colRect.x() : colRect.y()) - m_renderBlock.logicalLeftOffsetForContent();
340 LayoutSize offset = m_renderBlock.isHorizontalWritingMode() ? LayoutSize (logicalLeftOffset, currLogicalTopOffset) : LayoutSize(currLogicalTopOffset, log icalLeftOffset);
341 if (colInfo->progressionAxis() == ColumnInfo::BlockAxis) {
342 if (m_renderBlock.isHorizontalWritingMode())
343 offset.expand(0, colRect.y() - m_renderBlock.borderTop() - m_ren derBlock.paddingTop());
344 else
345 offset.expand(colRect.x() - m_renderBlock.borderLeft() - m_rende rBlock.paddingLeft(), 0);
346 }
347 colRect.moveBy(paintOffset);
348 PaintInfo info(paintInfo);
349 info.rect.intersect(enclosingIntRect(colRect));
350
351 if (!info.rect.isEmpty()) {
352 GraphicsContextStateSaver stateSaver(*context);
353 LayoutRect clipRect(colRect);
354
355 if (i < colCount - 1) {
356 if (m_renderBlock.isHorizontalWritingMode())
357 clipRect.expand(colGap / 2, 0);
358 else
359 clipRect.expand(0, colGap / 2);
360 }
361 // Each strip pushes a clip, since column boxes are specified as bei ng
362 // like overflow:hidden.
363 // FIXME: Content and column rules that extend outside column boxes at the edges of the multi-column element
364 // are clipped according to the 'overflow' property.
365 context->clip(enclosingIntRect(clipRect));
366
367 // Adjust our x and y when painting.
368 LayoutPoint adjustedPaintOffset = paintOffset + offset;
369 if (paintingFloats)
370 m_renderBlock.paintFloats(info, adjustedPaintOffset, paintInfo.p hase == PaintPhaseSelection || paintInfo.phase == PaintPhaseTextClip);
371 else
372 paintContents(info, adjustedPaintOffset);
373 }
374
375 LayoutUnit blockDelta = (m_renderBlock.isHorizontalWritingMode() ? colRe ct.height() : colRect.width());
376 if (m_renderBlock.style()->isFlippedBlocksWritingMode())
377 currLogicalTopOffset += blockDelta;
378 else
379 currLogicalTopOffset -= blockDelta;
380 }
381 }
382
383 void BlockPainter::paintContents(PaintInfo& paintInfo, const LayoutPoint& paintO ffset)
384 {
385 // Avoid painting descendants of the root element when stylesheets haven't l oaded. This eliminates FOUC.
386 // It's ok not to draw, because later on, when all the stylesheets do load, styleResolverChanged() on the Document
387 // will do a full paint invalidation.
388 if (m_renderBlock.document().didLayoutWithPendingStylesheets() && !m_renderB lock.isRenderView())
389 return;
390
391 if (m_renderBlock.childrenInline()) {
392 m_renderBlock.lineBoxes()->paint(&m_renderBlock, paintInfo, paintOffset) ;
393 } else {
394 PaintPhase newPhase = (paintInfo.phase == PaintPhaseChildOutlines) ? Pai ntPhaseOutline : paintInfo.phase;
395 newPhase = (newPhase == PaintPhaseChildBlockBackgrounds) ? PaintPhaseChi ldBlockBackground : newPhase;
396
397 // We don't paint our own background, but we do let the kids paint their backgrounds.
398 PaintInfo paintInfoForChild(paintInfo);
399 paintInfoForChild.phase = newPhase;
400 paintInfoForChild.updatePaintingRootForChildren(&m_renderBlock);
401 m_renderBlock.paintChildren(paintInfoForChild, paintOffset);
402 }
403 }
404
405 void BlockPainter::paintSelection(PaintInfo& paintInfo, const LayoutPoint& paint Offset)
406 {
407 if (m_renderBlock.shouldPaintSelectionGaps() && paintInfo.phase == PaintPhas eForeground) {
408 LayoutUnit lastTop = 0;
409 LayoutUnit lastLeft = m_renderBlock.logicalLeftSelectionOffset(&m_render Block, lastTop);
410 LayoutUnit lastRight = m_renderBlock.logicalRightSelectionOffset(&m_rend erBlock, lastTop);
411 GraphicsContextStateSaver stateSaver(*paintInfo.context);
412
413 LayoutRect gapRectsBounds = m_renderBlock.selectionGaps(&m_renderBlock, paintOffset, LayoutSize(), lastTop, lastLeft, lastRight, &paintInfo);
414 if (!gapRectsBounds.isEmpty()) {
415 RenderLayer* layer = m_renderBlock.enclosingLayer();
416 gapRectsBounds.moveBy(-paintOffset);
417 if (!m_renderBlock.hasLayer()) {
418 LayoutRect localBounds(gapRectsBounds);
419 m_renderBlock.flipForWritingMode(localBounds);
420 gapRectsBounds = m_renderBlock.localToContainerQuad(FloatRect(lo calBounds), layer->renderer()).enclosingBoundingBox();
421 if (layer->renderer()->hasOverflowClip())
422 gapRectsBounds.move(layer->renderBox()->scrolledContentOffse t());
423 }
424 layer->addBlockSelectionGapsBounds(gapRectsBounds);
425 }
426 }
427 }
428
429 void BlockPainter::paintContinuationOutlines(PaintInfo& info, const LayoutPoint& paintOffset)
430 {
431 RenderInline* inlineCont = m_renderBlock.inlineElementContinuation();
432 if (inlineCont && inlineCont->style()->hasOutline() && inlineCont->style()-> visibility() == VISIBLE) {
433 RenderInline* inlineRenderer = toRenderInline(inlineCont->node()->render er());
434 RenderBlock* cb = m_renderBlock.containingBlock();
435
436 bool inlineEnclosedInSelfPaintingLayer = false;
437 for (RenderBoxModelObject* box = inlineRenderer; box != cb; box = box->p arent()->enclosingBoxModelObject()) {
438 if (box->hasSelfPaintingLayer()) {
439 inlineEnclosedInSelfPaintingLayer = true;
440 break;
441 }
442 }
443
444 // Do not add continuations for outline painting by our containing block if we are a relative positioned
445 // anonymous block (i.e. have our own layer), paint them straightaway in stead. This is because a block depends on renderers in its continuation table be ing
446 // in the same layer.
447 if (!inlineEnclosedInSelfPaintingLayer && !m_renderBlock.hasLayer())
448 cb->addContinuationWithOutline(inlineRenderer);
449 else if (!inlineRenderer->firstLineBox() || (!inlineEnclosedInSelfPainti ngLayer && m_renderBlock.hasLayer()))
450 inlineRenderer->paintOutline(info, paintOffset - m_renderBlock.locat ionOffset() + inlineRenderer->containingBlock()->location());
451 }
452
453 ContinuationOutlineTableMap* table = continuationOutlineTable();
454 if (table->isEmpty())
455 return;
456
457 OwnPtr<ListHashSet<RenderInline*> > continuations = table->take(&m_renderBlo ck);
458 if (!continuations)
459 return;
460
461 LayoutPoint accumulatedPaintOffset = paintOffset;
462 // Paint each continuation outline.
463 ListHashSet<RenderInline*>::iterator end = continuations->end();
464 for (ListHashSet<RenderInline*>::iterator it = continuations->begin(); it != end; ++it) {
465 // Need to add in the coordinates of the intervening blocks.
466 RenderInline* flow = *it;
467 RenderBlock* block = flow->containingBlock();
468 for ( ; block && block != &m_renderBlock; block = block->containingBlock ())
469 accumulatedPaintOffset.moveBy(block->location());
470 ASSERT(block);
471 flow->paintOutline(info, accumulatedPaintOffset);
472 }
473 }
474
475
476 } // namespace blink
OLDNEW
« no previous file with comments | « Source/core/paint/BlockPainter.h ('k') | Source/core/rendering/InlineBox.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698