OLD | NEW |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "config.h" | 5 #include "config.h" |
6 #include "core/paint/BlockPainter.h" | 6 #include "core/paint/BlockPainter.h" |
7 | 7 |
8 #include "core/editing/FrameSelection.h" | 8 #include "core/editing/FrameSelection.h" |
9 #include "core/frame/Settings.h" | 9 #include "core/frame/Settings.h" |
10 #include "core/layout/LayoutFlexibleBox.h" | 10 #include "core/layout/LayoutFlexibleBox.h" |
(...skipping 183 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
194 PaintInfo scrolledPaintInfo(paintInfo); | 194 PaintInfo scrolledPaintInfo(paintInfo); |
195 Optional<ScrollRecorder> scrollRecorder; | 195 Optional<ScrollRecorder> scrollRecorder; |
196 if (m_layoutBlock.hasOverflowClip()) { | 196 if (m_layoutBlock.hasOverflowClip()) { |
197 IntSize scrollOffset = m_layoutBlock.scrolledContentOffset(); | 197 IntSize scrollOffset = m_layoutBlock.scrolledContentOffset(); |
198 if (m_layoutBlock.layer()->scrollsOverflow() || !scrollOffset.isZero
()) { | 198 if (m_layoutBlock.layer()->scrollsOverflow() || !scrollOffset.isZero
()) { |
199 scrollRecorder.emplace(*paintInfo.context, m_layoutBlock, paintP
hase, scrollOffset); | 199 scrollRecorder.emplace(*paintInfo.context, m_layoutBlock, paintP
hase, scrollOffset); |
200 scrolledPaintInfo.rect.move(scrollOffset); | 200 scrolledPaintInfo.rect.move(scrollOffset); |
201 } | 201 } |
202 } | 202 } |
203 | 203 |
204 if ((paintPhase == PaintPhaseBlockBackground || paintPhase == PaintPhase
ChildBlockBackground) | |
205 && m_layoutBlock.style()->visibility() == VISIBLE | |
206 && m_layoutBlock.hasColumns() | |
207 && !paintInfo.paintRootBackgroundOnly()) { | |
208 LayoutObjectDrawingRecorder recorder(*paintInfo.context, m_layoutBlo
ck, DisplayItem::ColumnRules, bounds); | |
209 if (!recorder.canUseCachedDrawing()) | |
210 paintColumnRules(scrolledPaintInfo, paintOffset); | |
211 } | |
212 | |
213 // We're done. We don't bother painting any children. | 204 // We're done. We don't bother painting any children. |
214 if (paintPhase == PaintPhaseBlockBackground || paintInfo.paintRootBackgr
oundOnly()) | 205 if (paintPhase == PaintPhaseBlockBackground || paintInfo.paintRootBackgr
oundOnly()) |
215 return; | 206 return; |
216 | 207 |
217 if (paintPhase != PaintPhaseSelfOutline) { | 208 if (paintPhase != PaintPhaseSelfOutline) |
218 if (m_layoutBlock.hasColumns()) | 209 paintContents(scrolledPaintInfo, paintOffset); |
219 paintColumnContents(scrolledPaintInfo, paintOffset); | |
220 else | |
221 paintContents(scrolledPaintInfo, paintOffset); | |
222 } | |
223 | 210 |
224 // FIXME: Make this work with multi column layouts. For now don't fill g
aps. | 211 if (!m_layoutBlock.document().printing()) |
225 bool isPrinting = m_layoutBlock.document().printing(); | |
226 if (!isPrinting && !m_layoutBlock.hasColumns()) | |
227 m_layoutBlock.paintSelection(scrolledPaintInfo, paintOffset); // Fil
l in gaps in selection on lines and between blocks. | 212 m_layoutBlock.paintSelection(scrolledPaintInfo, paintOffset); // Fil
l in gaps in selection on lines and between blocks. |
228 | 213 |
229 if (paintPhase == PaintPhaseFloat || paintPhase == PaintPhaseSelection |
| paintPhase == PaintPhaseTextClip) { | 214 if (paintPhase == PaintPhaseFloat || paintPhase == PaintPhaseSelection |
| paintPhase == PaintPhaseTextClip) |
230 if (m_layoutBlock.hasColumns()) | 215 m_layoutBlock.paintFloats(scrolledPaintInfo, paintOffset, paintPhase
== PaintPhaseSelection || paintPhase == PaintPhaseTextClip); |
231 paintColumnContents(scrolledPaintInfo, paintOffset, true); | |
232 else | |
233 m_layoutBlock.paintFloats(scrolledPaintInfo, paintOffset, paintP
hase == PaintPhaseSelection || paintPhase == PaintPhaseTextClip); | |
234 } | |
235 } | 216 } |
236 | 217 |
237 if ((paintPhase == PaintPhaseOutline || paintPhase == PaintPhaseSelfOutline)
&& m_layoutBlock.style()->hasOutline() && m_layoutBlock.style()->visibility() =
= VISIBLE) { | 218 if ((paintPhase == PaintPhaseOutline || paintPhase == PaintPhaseSelfOutline)
&& m_layoutBlock.style()->hasOutline() && m_layoutBlock.style()->visibility() =
= VISIBLE) { |
238 // Don't paint focus ring for anonymous block continuation because the | 219 // Don't paint focus ring for anonymous block continuation because the |
239 // inline element having outline-style:auto paints the whole focus ring. | 220 // inline element having outline-style:auto paints the whole focus ring. |
240 if (!m_layoutBlock.style()->outlineStyleIsAuto() || !m_layoutBlock.isAno
nymousBlockContinuation()) | 221 if (!m_layoutBlock.style()->outlineStyleIsAuto() || !m_layoutBlock.isAno
nymousBlockContinuation()) |
241 ObjectPainter(m_layoutBlock).paintOutline(paintInfo, LayoutRect(pain
tOffset, m_layoutBlock.size()), bounds); | 222 ObjectPainter(m_layoutBlock).paintOutline(paintInfo, LayoutRect(pain
tOffset, m_layoutBlock.size()), bounds); |
242 } | 223 } |
243 | 224 |
244 if (paintPhase == PaintPhaseOutline || paintPhase == PaintPhaseChildOutlines
) | 225 if (paintPhase == PaintPhaseOutline || paintPhase == PaintPhaseChildOutlines
) |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
295 return overflowRect; | 276 return overflowRect; |
296 } | 277 } |
297 | 278 |
298 bool BlockPainter::hasCaret() const | 279 bool BlockPainter::hasCaret() const |
299 { | 280 { |
300 bool caretBrowsing = caretBrowsingEnabled(m_layoutBlock.frame()); | 281 bool caretBrowsing = caretBrowsingEnabled(m_layoutBlock.frame()); |
301 return hasCursorCaret(m_layoutBlock.frame()->selection(), &m_layoutBlock, ca
retBrowsing) | 282 return hasCursorCaret(m_layoutBlock.frame()->selection(), &m_layoutBlock, ca
retBrowsing) |
302 || hasDragCaret(m_layoutBlock.frame()->page()->dragCaretController(), &m
_layoutBlock, caretBrowsing); | 283 || hasDragCaret(m_layoutBlock.frame()->page()->dragCaretController(), &m
_layoutBlock, caretBrowsing); |
303 } | 284 } |
304 | 285 |
305 void BlockPainter::paintColumnRules(const PaintInfo& paintInfo, const LayoutPoin
t& paintOffset) | |
306 { | |
307 const Color& ruleColor = m_layoutBlock.resolveColor(CSSPropertyWebkitColumnR
uleColor); | |
308 bool ruleTransparent = m_layoutBlock.style()->columnRuleIsTransparent(); | |
309 EBorderStyle ruleStyle = m_layoutBlock.style()->columnRuleStyle(); | |
310 LayoutUnit ruleThickness = m_layoutBlock.style()->columnRuleWidth(); | |
311 LayoutUnit colGap = m_layoutBlock.columnGap(); | |
312 bool renderRule = ruleStyle > BHIDDEN && !ruleTransparent; | |
313 if (!renderRule) | |
314 return; | |
315 | |
316 ColumnInfo* colInfo = m_layoutBlock.columnInfo(); | |
317 unsigned colCount = m_layoutBlock.columnCount(colInfo); | |
318 | |
319 bool antialias = BoxPainter::shouldAntialiasLines(paintInfo.context); | |
320 | |
321 if (colInfo->progressionAxis() == ColumnInfo::InlineAxis) { | |
322 bool leftToRight = m_layoutBlock.style()->isLeftToRightDirection(); | |
323 LayoutUnit currLogicalLeftOffset = leftToRight ? LayoutUnit() : m_layout
Block.contentLogicalWidth(); | |
324 LayoutUnit ruleAdd = m_layoutBlock.logicalLeftOffsetForContent(); | |
325 LayoutUnit ruleLogicalLeft = leftToRight ? LayoutUnit() : m_layoutBlock.
contentLogicalWidth(); | |
326 LayoutUnit inlineDirectionSize = colInfo->desiredColumnWidth(); | |
327 BoxSide boxSide = m_layoutBlock.isHorizontalWritingMode() | |
328 ? leftToRight ? BSLeft : BSRight | |
329 : leftToRight ? BSTop : BSBottom; | |
330 | |
331 for (unsigned i = 0; i < colCount; i++) { | |
332 // Move to the next position. | |
333 if (leftToRight) { | |
334 ruleLogicalLeft += inlineDirectionSize + colGap / 2; | |
335 currLogicalLeftOffset += inlineDirectionSize + colGap; | |
336 } else { | |
337 ruleLogicalLeft -= (inlineDirectionSize + colGap / 2); | |
338 currLogicalLeftOffset -= (inlineDirectionSize + colGap); | |
339 } | |
340 | |
341 // Now paint the column rule. | |
342 if (i < colCount - 1) { | |
343 LayoutUnit ruleLeft = m_layoutBlock.isHorizontalWritingMode() ?
paintOffset.x() + ruleLogicalLeft - ruleThickness / 2 + ruleAdd : paintOffset.x(
) + m_layoutBlock.borderLeft() + m_layoutBlock.paddingLeft(); | |
344 LayoutUnit ruleRight = m_layoutBlock.isHorizontalWritingMode() ?
ruleLeft + ruleThickness : ruleLeft + m_layoutBlock.contentWidth(); | |
345 LayoutUnit ruleTop = m_layoutBlock.isHorizontalWritingMode() ? p
aintOffset.y() + m_layoutBlock.borderTop() + m_layoutBlock.paddingTop() : paintO
ffset.y() + ruleLogicalLeft - ruleThickness / 2 + ruleAdd; | |
346 LayoutUnit ruleBottom = m_layoutBlock.isHorizontalWritingMode()
? ruleTop + m_layoutBlock.contentHeight() : ruleTop + ruleThickness; | |
347 IntRect pixelSnappedRuleRect = pixelSnappedIntRectFromEdges(rule
Left, ruleTop, ruleRight, ruleBottom); | |
348 ObjectPainter::drawLineForBoxSide(paintInfo.context, pixelSnappe
dRuleRect.x(), pixelSnappedRuleRect.y(), pixelSnappedRuleRect.maxX(), pixelSnapp
edRuleRect.maxY(), boxSide, ruleColor, ruleStyle, 0, 0, antialias); | |
349 } | |
350 | |
351 ruleLogicalLeft = currLogicalLeftOffset; | |
352 } | |
353 } else { | |
354 bool topToBottom = !m_layoutBlock.style()->isFlippedBlocksWritingMode(); | |
355 LayoutUnit ruleLeft = m_layoutBlock.isHorizontalWritingMode() | |
356 ? m_layoutBlock.borderLeft() + m_layoutBlock.paddingLeft() | |
357 : colGap / 2 - colGap - ruleThickness / 2 + m_layoutBlock.borderBefo
re() + m_layoutBlock.paddingBefore(); | |
358 LayoutUnit ruleWidth = m_layoutBlock.isHorizontalWritingMode() ? m_layou
tBlock.contentWidth() : ruleThickness; | |
359 LayoutUnit ruleTop = m_layoutBlock.isHorizontalWritingMode() | |
360 ? colGap / 2 - colGap - ruleThickness / 2 + m_layoutBlock.borderBefo
re() + m_layoutBlock.paddingBefore() | |
361 : m_layoutBlock.borderStart() + m_layoutBlock.paddingStart(); | |
362 LayoutUnit ruleHeight = m_layoutBlock.isHorizontalWritingMode() ? ruleTh
ickness : m_layoutBlock.contentHeight(); | |
363 LayoutRect ruleRect(ruleLeft, ruleTop, ruleWidth, ruleHeight); | |
364 | |
365 if (!topToBottom) { | |
366 if (m_layoutBlock.isHorizontalWritingMode()) | |
367 ruleRect.setY(m_layoutBlock.size().height() - ruleRect.maxY()); | |
368 else | |
369 ruleRect.setX(m_layoutBlock.size().width() - ruleRect.maxX()); | |
370 } | |
371 | |
372 ruleRect.moveBy(paintOffset); | |
373 | |
374 BoxSide boxSide = m_layoutBlock.isHorizontalWritingMode() | |
375 ? topToBottom ? BSTop : BSBottom | |
376 : topToBottom ? BSLeft : BSRight; | |
377 | |
378 LayoutSize step(0, topToBottom ? colInfo->columnHeight() + colGap : -(co
lInfo->columnHeight() + colGap)); | |
379 if (!m_layoutBlock.isHorizontalWritingMode()) | |
380 step = step.transposedSize(); | |
381 | |
382 for (unsigned i = 1; i < colCount; i++) { | |
383 ruleRect.move(step); | |
384 IntRect pixelSnappedRuleRect = pixelSnappedIntRect(ruleRect); | |
385 ObjectPainter::drawLineForBoxSide(paintInfo.context, pixelSnappedRul
eRect.x(), pixelSnappedRuleRect.y(), pixelSnappedRuleRect.maxX(), pixelSnappedRu
leRect.maxY(), boxSide, ruleColor, ruleStyle, 0, 0, antialias); | |
386 } | |
387 } | |
388 } | |
389 | |
390 void BlockPainter::paintColumnContents(const PaintInfo& paintInfo, const LayoutP
oint& paintOffset, bool paintingFloats) | |
391 { | |
392 // We need to do multiple passes, breaking up our child painting into strips
. | |
393 ColumnInfo* colInfo = m_layoutBlock.columnInfo(); | |
394 unsigned colCount = m_layoutBlock.columnCount(colInfo); | |
395 if (!colCount) | |
396 return; | |
397 LayoutUnit currLogicalTopOffset = 0; | |
398 LayoutUnit colGap = m_layoutBlock.columnGap(); | |
399 | |
400 for (unsigned i = 0; i < colCount; i++) { | |
401 ScopeRecorder scopeRecorder(*paintInfo.context, m_layoutBlock); | |
402 | |
403 // For each rect, we clip to the rect, and then we adjust our coords. | |
404 LayoutRect colRect = m_layoutBlock.columnRectAt(colInfo, i); | |
405 m_layoutBlock.flipForWritingMode(colRect); | |
406 LayoutUnit logicalLeftOffset = (m_layoutBlock.isHorizontalWritingMode()
? colRect.x() : colRect.y()) - m_layoutBlock.logicalLeftOffsetForContent(); | |
407 LayoutSize offset = m_layoutBlock.isHorizontalWritingMode() ? LayoutSize
(logicalLeftOffset, currLogicalTopOffset) : LayoutSize(currLogicalTopOffset, log
icalLeftOffset); | |
408 if (colInfo->progressionAxis() == ColumnInfo::BlockAxis) { | |
409 if (m_layoutBlock.isHorizontalWritingMode()) | |
410 offset.expand(0, colRect.y() - m_layoutBlock.borderTop() - m_lay
outBlock.paddingTop()); | |
411 else | |
412 offset.expand(colRect.x() - m_layoutBlock.borderLeft() - m_layou
tBlock.paddingLeft(), 0); | |
413 } | |
414 colRect.moveBy(paintOffset); | |
415 PaintInfo info(paintInfo); | |
416 info.rect.intersect(enclosingIntRect(colRect)); | |
417 | |
418 if (!info.rect.isEmpty()) { | |
419 LayoutRect clipRect(colRect); | |
420 | |
421 if (i < colCount - 1) { | |
422 if (m_layoutBlock.isHorizontalWritingMode()) | |
423 clipRect.expand(colGap / 2, 0); | |
424 else | |
425 clipRect.expand(0, colGap / 2); | |
426 } | |
427 // Each strip pushes a clip, since column boxes are specified as bei
ng | |
428 // like overflow:hidden. | |
429 // FIXME: Content and column rules that extend outside column boxes
at the edges of the multi-column element | |
430 // are clipped according to the 'overflow' property. | |
431 ClipRecorder clipRecorder(*paintInfo.context, m_layoutBlock, | |
432 DisplayItem::paintPhaseToClipColumnBoundsType(paintInfo.phase),
LayoutRect(enclosingIntRect(clipRect))); | |
433 | |
434 // Adjust our x and y when painting. | |
435 LayoutPoint adjustedPaintOffset = paintOffset + offset; | |
436 if (paintingFloats) | |
437 m_layoutBlock.paintFloats(info, adjustedPaintOffset, paintInfo.p
hase == PaintPhaseSelection || paintInfo.phase == PaintPhaseTextClip); | |
438 else | |
439 paintContents(info, adjustedPaintOffset); | |
440 } | |
441 | |
442 LayoutUnit blockDelta = (m_layoutBlock.isHorizontalWritingMode() ? colRe
ct.height() : colRect.width()); | |
443 if (m_layoutBlock.style()->isFlippedBlocksWritingMode()) | |
444 currLogicalTopOffset += blockDelta; | |
445 else | |
446 currLogicalTopOffset -= blockDelta; | |
447 } | |
448 } | |
449 | |
450 void BlockPainter::paintContents(const PaintInfo& paintInfo, const LayoutPoint&
paintOffset) | 286 void BlockPainter::paintContents(const PaintInfo& paintInfo, const LayoutPoint&
paintOffset) |
451 { | 287 { |
452 // Avoid painting descendants of the root element when stylesheets haven't l
oaded. This eliminates FOUC. | 288 // Avoid painting descendants of the root element when stylesheets haven't l
oaded. This eliminates FOUC. |
453 // It's ok not to draw, because later on, when all the stylesheets do load,
styleResolverChanged() on the Document | 289 // It's ok not to draw, because later on, when all the stylesheets do load,
styleResolverChanged() on the Document |
454 // will do a full paint invalidation. | 290 // will do a full paint invalidation. |
455 if (m_layoutBlock.document().didLayoutWithPendingStylesheets() && !m_layoutB
lock.isLayoutView()) | 291 if (m_layoutBlock.document().didLayoutWithPendingStylesheets() && !m_layoutB
lock.isLayoutView()) |
456 return; | 292 return; |
457 | 293 |
458 if (m_layoutBlock.childrenInline()) { | 294 if (m_layoutBlock.childrenInline()) { |
459 LineBoxListPainter(*m_layoutBlock.lineBoxes()).paint(&m_layoutBlock, pai
ntInfo, paintOffset); | 295 LineBoxListPainter(*m_layoutBlock.lineBoxes()).paint(&m_layoutBlock, pai
ntInfo, paintOffset); |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
510 LayoutBlock* block = flow->containingBlock(); | 346 LayoutBlock* block = flow->containingBlock(); |
511 for ( ; block && block != &m_layoutBlock; block = block->containingBlock
()) | 347 for ( ; block && block != &m_layoutBlock; block = block->containingBlock
()) |
512 accumulatedPaintOffset.moveBy(block->location()); | 348 accumulatedPaintOffset.moveBy(block->location()); |
513 ASSERT(block); | 349 ASSERT(block); |
514 InlinePainter(*flow).paintOutline(info, accumulatedPaintOffset); | 350 InlinePainter(*flow).paintOutline(info, accumulatedPaintOffset); |
515 } | 351 } |
516 } | 352 } |
517 | 353 |
518 | 354 |
519 } // namespace blink | 355 } // namespace blink |
OLD | NEW |