OLD | NEW |
1 /* | 1 /* |
2 * Copyright (C) 1999 Lars Knoll (knoll@kde.org) | 2 * Copyright (C) 1999 Lars Knoll (knoll@kde.org) |
3 * (C) 1999 Antti Koivisto (koivisto@kde.org) | 3 * (C) 1999 Antti Koivisto (koivisto@kde.org) |
4 * (C) 2007 David Smith (catfish.man@gmail.com) | 4 * (C) 2007 David Smith (catfish.man@gmail.com) |
5 * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Apple Inc.
All rights reserved. | 5 * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Apple Inc.
All rights reserved. |
6 * Copyright (C) Research In Motion Limited 2010. All rights reserved. | 6 * Copyright (C) Research In Motion Limited 2010. All rights reserved. |
7 * | 7 * |
8 * This library is free software; you can redistribute it and/or | 8 * This library is free software; you can redistribute it and/or |
9 * modify it under the terms of the GNU Library General Public | 9 * modify it under the terms of the GNU Library General Public |
10 * License as published by the Free Software Foundation; either | 10 * License as published by the Free Software Foundation; either |
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
86 struct SameSizeAsRenderBlockRareData { | 86 struct SameSizeAsRenderBlockRareData { |
87 int paginationStrut; | 87 int paginationStrut; |
88 int pageLogicalOffset; | 88 int pageLogicalOffset; |
89 void* pointers[1]; | 89 void* pointers[1]; |
90 uint32_t bitfields; | 90 uint32_t bitfields; |
91 }; | 91 }; |
92 | 92 |
93 COMPILE_ASSERT(sizeof(RenderBlock) == sizeof(SameSizeAsRenderBlock), RenderBlock
_should_stay_small); | 93 COMPILE_ASSERT(sizeof(RenderBlock) == sizeof(SameSizeAsRenderBlock), RenderBlock
_should_stay_small); |
94 COMPILE_ASSERT(sizeof(RenderBlock::RenderBlockRareData) == sizeof(SameSizeAsRend
erBlockRareData), RenderBlockRareData_should_stay_small); | 94 COMPILE_ASSERT(sizeof(RenderBlock::RenderBlockRareData) == sizeof(SameSizeAsRend
erBlockRareData), RenderBlockRareData_should_stay_small); |
95 | 95 |
96 typedef WTF::HashMap<const RenderBox*, OwnPtr<ColumnInfo> > ColumnInfoMap; | |
97 static ColumnInfoMap* gColumnInfoMap = 0; | |
98 | |
99 static TrackedDescendantsMap* gPositionedDescendantsMap = 0; | 96 static TrackedDescendantsMap* gPositionedDescendantsMap = 0; |
100 static TrackedDescendantsMap* gPercentHeightDescendantsMap = 0; | 97 static TrackedDescendantsMap* gPercentHeightDescendantsMap = 0; |
101 | 98 |
102 static TrackedContainerMap* gPositionedContainerMap = 0; | 99 static TrackedContainerMap* gPositionedContainerMap = 0; |
103 static TrackedContainerMap* gPercentHeightContainerMap = 0; | 100 static TrackedContainerMap* gPercentHeightContainerMap = 0; |
104 | 101 |
105 typedef WTF::HashMap<RenderBlock*, OwnPtr<ListHashSet<RenderInline*> > > Continu
ationOutlineTableMap; | 102 typedef WTF::HashMap<RenderBlock*, OwnPtr<ListHashSet<RenderInline*> > > Continu
ationOutlineTableMap; |
106 | 103 |
107 typedef WTF::HashSet<RenderBlock*> DelayedUpdateScrollInfoSet; | 104 typedef WTF::HashSet<RenderBlock*> DelayedUpdateScrollInfoSet; |
108 static int gDelayUpdateScrollInfo = 0; | 105 static int gDelayUpdateScrollInfo = 0; |
109 static DelayedUpdateScrollInfoSet* gDelayedUpdateScrollInfoSet = 0; | 106 static DelayedUpdateScrollInfoSet* gDelayedUpdateScrollInfoSet = 0; |
110 | 107 |
111 static bool gColumnFlowSplitEnabled = true; | |
112 | |
113 // This class helps dispatching the 'overflow' event on layout change. overflow
can be set on RenderBoxes, yet the existing code | 108 // This class helps dispatching the 'overflow' event on layout change. overflow
can be set on RenderBoxes, yet the existing code |
114 // only works on RenderBlocks. If this changes, this class should be shared with
other RenderBoxes. | 109 // only works on RenderBlocks. If this changes, this class should be shared with
other RenderBoxes. |
115 class OverflowEventDispatcher { | 110 class OverflowEventDispatcher { |
116 WTF_MAKE_NONCOPYABLE(OverflowEventDispatcher); | 111 WTF_MAKE_NONCOPYABLE(OverflowEventDispatcher); |
117 public: | 112 public: |
118 OverflowEventDispatcher(const RenderBlock* block) | 113 OverflowEventDispatcher(const RenderBlock* block) |
119 : m_block(block) | 114 : m_block(block) |
120 { | 115 { |
121 m_shouldDispatchEvent = !m_block->isAnonymous() && m_block->hasOverflowC
lip() && m_block->document().hasListenerType(Document::OVERFLOWCHANGED_LISTENER)
; | 116 m_shouldDispatchEvent = !m_block->isAnonymous() && m_block->hasOverflowC
lip() && m_block->document().hasListenerType(Document::OVERFLOWCHANGED_LISTENER)
; |
122 if (m_shouldDispatchEvent) { | 117 if (m_shouldDispatchEvent) { |
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
211 if (blockStyle.boxReflect()) | 206 if (blockStyle.boxReflect()) |
212 appendImageIfNotNull(images, blockStyle.boxReflect()->mask().image()); | 207 appendImageIfNotNull(images, blockStyle.boxReflect()->mask().image()); |
213 appendImageIfNotNull(images, blockStyle.listStyleImage()); | 208 appendImageIfNotNull(images, blockStyle.listStyleImage()); |
214 appendImageIfNotNull(images, blockStyle.borderImageSource()); | 209 appendImageIfNotNull(images, blockStyle.borderImageSource()); |
215 appendImageIfNotNull(images, blockStyle.maskBoxImageSource()); | 210 appendImageIfNotNull(images, blockStyle.maskBoxImageSource()); |
216 } | 211 } |
217 | 212 |
218 RenderBlock::~RenderBlock() | 213 RenderBlock::~RenderBlock() |
219 { | 214 { |
220 ResourceLoadPriorityOptimizer::resourceLoadPriorityOptimizer()->removeRender
Object(this); | 215 ResourceLoadPriorityOptimizer::resourceLoadPriorityOptimizer()->removeRender
Object(this); |
221 if (hasColumns()) | |
222 gColumnInfoMap->take(this); | |
223 if (gPercentHeightDescendantsMap) | 216 if (gPercentHeightDescendantsMap) |
224 removeBlockFromDescendantAndContainerMaps(this, gPercentHeightDescendant
sMap, gPercentHeightContainerMap); | 217 removeBlockFromDescendantAndContainerMaps(this, gPercentHeightDescendant
sMap, gPercentHeightContainerMap); |
225 if (gPositionedDescendantsMap) | 218 if (gPositionedDescendantsMap) |
226 removeBlockFromDescendantAndContainerMaps(this, gPositionedDescendantsMa
p, gPositionedContainerMap); | 219 removeBlockFromDescendantAndContainerMaps(this, gPositionedDescendantsMa
p, gPositionedContainerMap); |
227 } | 220 } |
228 | 221 |
229 void RenderBlock::willBeDestroyed() | 222 void RenderBlock::willBeDestroyed() |
230 { | 223 { |
231 // Mark as being destroyed to avoid trouble with merges in removeChild(). | 224 // Mark as being destroyed to avoid trouble with merges in removeChild(). |
232 m_beingDestroyed = true; | 225 m_beingDestroyed = true; |
(...skipping 148 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
381 } | 374 } |
382 | 375 |
383 if (!beforeChild && !last->firstChild()) | 376 if (!beforeChild && !last->firstChild()) |
384 return nextToLast; | 377 return nextToLast; |
385 return last; | 378 return last; |
386 } | 379 } |
387 | 380 |
388 void RenderBlock::addChildToContinuation(RenderObject* newChild, RenderObject* b
eforeChild) | 381 void RenderBlock::addChildToContinuation(RenderObject* newChild, RenderObject* b
eforeChild) |
389 { | 382 { |
390 RenderBlock* flow = continuationBefore(beforeChild); | 383 RenderBlock* flow = continuationBefore(beforeChild); |
391 ASSERT(!beforeChild || beforeChild->parent()->isAnonymousColumnSpanBlock() |
| beforeChild->parent()->isRenderBlock()); | 384 ASSERT(!beforeChild || beforeChild->parent()->isRenderBlock()); |
392 RenderBoxModelObject* beforeChildParent = 0; | 385 RenderBoxModelObject* beforeChildParent = 0; |
393 if (beforeChild) | 386 if (beforeChild) |
394 beforeChildParent = toRenderBoxModelObject(beforeChild->parent()); | 387 beforeChildParent = toRenderBoxModelObject(beforeChild->parent()); |
395 else { | 388 else { |
396 RenderBoxModelObject* cont = flow->continuation(); | 389 RenderBoxModelObject* cont = flow->continuation(); |
397 if (cont) | 390 if (cont) |
398 beforeChildParent = cont; | 391 beforeChildParent = cont; |
399 else | 392 else |
400 beforeChildParent = flow; | 393 beforeChildParent = flow; |
401 } | 394 } |
402 | 395 |
403 if (newChild->isFloatingOrOutOfFlowPositioned()) { | 396 if (newChild->isFloatingOrOutOfFlowPositioned()) { |
404 beforeChildParent->addChildIgnoringContinuation(newChild, beforeChild); | 397 beforeChildParent->addChildIgnoringContinuation(newChild, beforeChild); |
405 return; | 398 return; |
406 } | 399 } |
407 | 400 |
408 // A continuation always consists of two potential candidates: a block or an
anonymous | |
409 // column span box holding column span children. | |
410 bool childIsNormal = newChild->isInline() || !newChild->style()->columnSpan(
); | |
411 bool bcpIsNormal = beforeChildParent->isInline() || !beforeChildParent->styl
e()->columnSpan(); | |
412 bool flowIsNormal = flow->isInline() || !flow->style()->columnSpan(); | |
413 | |
414 if (flow == beforeChildParent) { | 401 if (flow == beforeChildParent) { |
415 flow->addChildIgnoringContinuation(newChild, beforeChild); | 402 flow->addChildIgnoringContinuation(newChild, beforeChild); |
416 return; | 403 return; |
417 } | 404 } |
418 | 405 |
419 // The goal here is to match up if we can, so that we can coalesce and creat
e the | |
420 // minimal # of continuations needed for the inline. | |
421 if (childIsNormal == bcpIsNormal) { | |
422 beforeChildParent->addChildIgnoringContinuation(newChild, beforeChild); | |
423 return; | |
424 } | |
425 if (flowIsNormal == childIsNormal) { | |
426 flow->addChildIgnoringContinuation(newChild, 0); // Just treat like an a
ppend. | |
427 return; | |
428 } | |
429 beforeChildParent->addChildIgnoringContinuation(newChild, beforeChild); | 406 beforeChildParent->addChildIgnoringContinuation(newChild, beforeChild); |
430 } | 407 } |
431 | 408 |
432 | |
433 void RenderBlock::addChildToAnonymousColumnBlocks(RenderObject* newChild, Render
Object* beforeChild) | |
434 { | |
435 ASSERT(!continuation()); // We don't yet support column spans that aren't im
mediate children of the multi-column block. | |
436 | |
437 // The goal is to locate a suitable box in which to place our child. | |
438 RenderBlock* beforeChildParent = 0; | |
439 if (beforeChild) { | |
440 RenderObject* curr = beforeChild; | |
441 while (curr && curr->parent() != this) | |
442 curr = curr->parent(); | |
443 beforeChildParent = toRenderBlock(curr); | |
444 ASSERT(beforeChildParent); | |
445 ASSERT(beforeChildParent->isAnonymousColumnsBlock() || beforeChildParent
->isAnonymousColumnSpanBlock()); | |
446 } else | |
447 beforeChildParent = toRenderBlock(lastChild()); | |
448 | |
449 // If the new child is floating or positioned it can just go in that block. | |
450 if (newChild->isFloatingOrOutOfFlowPositioned()) { | |
451 beforeChildParent->addChildIgnoringAnonymousColumnBlocks(newChild, befor
eChild); | |
452 return; | |
453 } | |
454 | |
455 // See if the child can be placed in the box. | |
456 bool newChildHasColumnSpan = newChild->style()->columnSpan() && !newChild->i
sInline(); | |
457 bool beforeChildParentHoldsColumnSpans = beforeChildParent->isAnonymousColum
nSpanBlock(); | |
458 | |
459 if (newChildHasColumnSpan == beforeChildParentHoldsColumnSpans) { | |
460 beforeChildParent->addChildIgnoringAnonymousColumnBlocks(newChild, befor
eChild); | |
461 return; | |
462 } | |
463 | |
464 if (!beforeChild) { | |
465 // Create a new block of the correct type. | |
466 RenderBlock* newBox = newChildHasColumnSpan ? createAnonymousColumnSpanB
lock() : createAnonymousColumnsBlock(); | |
467 children()->appendChildNode(this, newBox); | |
468 newBox->addChildIgnoringAnonymousColumnBlocks(newChild, 0); | |
469 return; | |
470 } | |
471 | |
472 RenderObject* immediateChild = beforeChild; | |
473 bool isPreviousBlockViable = true; | |
474 while (immediateChild->parent() != this) { | |
475 if (isPreviousBlockViable) | |
476 isPreviousBlockViable = !immediateChild->previousSibling(); | |
477 immediateChild = immediateChild->parent(); | |
478 } | |
479 if (isPreviousBlockViable && immediateChild->previousSibling()) { | |
480 toRenderBlock(immediateChild->previousSibling())->addChildIgnoringAnonym
ousColumnBlocks(newChild, 0); // Treat like an append. | |
481 return; | |
482 } | |
483 | |
484 // Split our anonymous blocks. | |
485 RenderObject* newBeforeChild = splitAnonymousBoxesAroundChild(beforeChild); | |
486 | |
487 | |
488 // Create a new anonymous box of the appropriate type. | |
489 RenderBlock* newBox = newChildHasColumnSpan ? createAnonymousColumnSpanBlock
() : createAnonymousColumnsBlock(); | |
490 children()->insertChildNode(this, newBox, newBeforeChild); | |
491 newBox->addChildIgnoringAnonymousColumnBlocks(newChild, 0); | |
492 return; | |
493 } | |
494 | |
495 RenderBlockFlow* RenderBlock::containingColumnsBlock(bool allowAnonymousColumnBl
ock) | |
496 { | |
497 RenderBlock* firstChildIgnoringAnonymousWrappers = 0; | |
498 for (RenderObject* curr = this; curr; curr = curr->parent()) { | |
499 if (!curr->isRenderBlock() || curr->isFloatingOrOutOfFlowPositioned() ||
curr->isTableCell() || curr->isRoot() || curr->isRenderView() || curr->hasOverf
lowClip() | |
500 || curr->isInlineBlockOrInlineTable()) | |
501 return 0; | |
502 | |
503 // FIXME: Renderers that do special management of their children (tables
, buttons, | |
504 // lists, flexboxes, etc.) breaks when the flow is split through them. D
isabling | |
505 // multi-column for them to avoid this problem.) | |
506 if (!curr->isRenderBlockFlow() || curr->isListItem()) | |
507 return 0; | |
508 | |
509 RenderBlockFlow* currBlock = toRenderBlockFlow(curr); | |
510 if (!currBlock->createsAnonymousWrapper()) | |
511 firstChildIgnoringAnonymousWrappers = currBlock; | |
512 | |
513 if (currBlock->style()->specifiesColumns() && (allowAnonymousColumnBlock
|| !currBlock->isAnonymousColumnsBlock())) | |
514 return toRenderBlockFlow(firstChildIgnoringAnonymousWrappers); | |
515 | |
516 if (currBlock->isAnonymousColumnSpanBlock()) | |
517 return 0; | |
518 } | |
519 return 0; | |
520 } | |
521 | |
522 RenderBlock* RenderBlock::clone() const | 409 RenderBlock* RenderBlock::clone() const |
523 { | 410 { |
524 RenderBlock* cloneBlock; | 411 RenderBlock* cloneBlock; |
525 if (isAnonymousBlock()) { | 412 if (isAnonymousBlock()) { |
526 cloneBlock = createAnonymousBlock(); | 413 cloneBlock = createAnonymousBlock(); |
527 cloneBlock->setChildrenInline(childrenInline()); | 414 cloneBlock->setChildrenInline(childrenInline()); |
528 } | 415 } |
529 else { | 416 else { |
530 RenderObject* cloneRenderer = toElement(node())->createRenderer(style())
; | 417 RenderObject* cloneRenderer = toElement(node())->createRenderer(style())
; |
531 cloneBlock = toRenderBlock(cloneRenderer); | 418 cloneBlock = toRenderBlock(cloneRenderer); |
532 cloneBlock->setStyle(style()); | 419 cloneBlock->setStyle(style()); |
533 | 420 |
534 // This takes care of setting the right value of childrenInline in case | 421 // This takes care of setting the right value of childrenInline in case |
535 // generated content is added to cloneBlock and 'this' does not have | 422 // generated content is added to cloneBlock and 'this' does not have |
536 // generated content added yet. | 423 // generated content added yet. |
537 cloneBlock->setChildrenInline(cloneBlock->firstChild() ? cloneBlock->fir
stChild()->isInline() : childrenInline()); | 424 cloneBlock->setChildrenInline(cloneBlock->firstChild() ? cloneBlock->fir
stChild()->isInline() : childrenInline()); |
538 } | 425 } |
539 cloneBlock->setFlowThreadState(flowThreadState()); | 426 cloneBlock->setFlowThreadState(flowThreadState()); |
540 return cloneBlock; | 427 return cloneBlock; |
541 } | 428 } |
542 | 429 |
543 void RenderBlock::splitBlocks(RenderBlock* fromBlock, RenderBlock* toBlock, | |
544 RenderBlock* middleBlock, | |
545 RenderObject* beforeChild, RenderBoxModelObject* o
ldCont) | |
546 { | |
547 // Create a clone of this inline. | |
548 RenderBlock* cloneBlock = clone(); | |
549 if (!isAnonymousBlock()) | |
550 cloneBlock->setContinuation(oldCont); | |
551 | |
552 if (!beforeChild && isAfterContent(lastChild())) | |
553 beforeChild = lastChild(); | |
554 | |
555 // If we are moving inline children from |this| to cloneBlock, then we need | |
556 // to clear our line box tree. | |
557 if (beforeChild && childrenInline()) | |
558 deleteLineBoxTree(); | |
559 | |
560 // Now take all of the children from beforeChild to the end and remove | |
561 // them from |this| and place them in the clone. | |
562 moveChildrenTo(cloneBlock, beforeChild, 0, true); | |
563 | |
564 // Hook |clone| up as the continuation of the middle block. | |
565 if (!cloneBlock->isAnonymousBlock()) | |
566 middleBlock->setContinuation(cloneBlock); | |
567 | |
568 // We have been reparented and are now under the fromBlock. We need | |
569 // to walk up our block parent chain until we hit the containing anonymous c
olumns block. | |
570 // Once we hit the anonymous columns block we're done. | |
571 RenderBoxModelObject* curr = toRenderBoxModelObject(parent()); | |
572 RenderBoxModelObject* currChild = this; | |
573 RenderObject* currChildNextSibling = currChild->nextSibling(); | |
574 | |
575 while (curr && curr->isDescendantOf(fromBlock) && curr != fromBlock) { | |
576 ASSERT_WITH_SECURITY_IMPLICATION(curr->isRenderBlock()); | |
577 | |
578 RenderBlock* blockCurr = toRenderBlock(curr); | |
579 | |
580 // Create a new clone. | |
581 RenderBlock* cloneChild = cloneBlock; | |
582 cloneBlock = blockCurr->clone(); | |
583 | |
584 // Insert our child clone as the first child. | |
585 cloneBlock->addChildIgnoringContinuation(cloneChild, 0); | |
586 | |
587 // Hook the clone up as a continuation of |curr|. Note we do encounter | |
588 // anonymous blocks possibly as we walk up the block chain. When we spl
it an | |
589 // anonymous block, there's no need to do any continuation hookup, since
we haven't | |
590 // actually split a real element. | |
591 if (!blockCurr->isAnonymousBlock()) { | |
592 oldCont = blockCurr->continuation(); | |
593 blockCurr->setContinuation(cloneBlock); | |
594 cloneBlock->setContinuation(oldCont); | |
595 } | |
596 | |
597 // Now we need to take all of the children starting from the first child | |
598 // *after* currChild and append them all to the clone. | |
599 blockCurr->moveChildrenTo(cloneBlock, currChildNextSibling, 0, true); | |
600 | |
601 // Keep walking up the chain. | |
602 currChild = curr; | |
603 currChildNextSibling = currChild->nextSibling(); | |
604 curr = toRenderBoxModelObject(curr->parent()); | |
605 } | |
606 | |
607 // Now we are at the columns block level. We need to put the clone into the
toBlock. | |
608 toBlock->children()->appendChildNode(toBlock, cloneBlock); | |
609 | |
610 // Now take all the children after currChild and remove them from the fromBl
ock | |
611 // and put them in the toBlock. | |
612 fromBlock->moveChildrenTo(toBlock, currChildNextSibling, 0, true); | |
613 } | |
614 | |
615 void RenderBlock::splitFlow(RenderObject* beforeChild, RenderBlock* newBlockBox, | |
616 RenderObject* newChild, RenderBoxModelObject* oldCon
t) | |
617 { | |
618 RenderBlock* pre = 0; | |
619 RenderBlock* block = containingColumnsBlock(); | |
620 | |
621 // Delete our line boxes before we do the inline split into continuations. | |
622 block->deleteLineBoxTree(); | |
623 | |
624 bool madeNewBeforeBlock = false; | |
625 if (block->isAnonymousColumnsBlock()) { | |
626 // We can reuse this block and make it the preBlock of the next continua
tion. | |
627 pre = block; | |
628 pre->removePositionedObjects(0); | |
629 if (block->isRenderBlockFlow()) | |
630 toRenderBlockFlow(pre)->removeFloatingObjects(); | |
631 block = toRenderBlock(block->parent()); | |
632 } else { | |
633 // No anonymous block available for use. Make one. | |
634 pre = block->createAnonymousColumnsBlock(); | |
635 pre->setChildrenInline(false); | |
636 madeNewBeforeBlock = true; | |
637 } | |
638 | |
639 RenderBlock* post = block->createAnonymousColumnsBlock(); | |
640 post->setChildrenInline(false); | |
641 | |
642 RenderObject* boxFirst = madeNewBeforeBlock ? block->firstChild() : pre->nex
tSibling(); | |
643 if (madeNewBeforeBlock) | |
644 block->children()->insertChildNode(block, pre, boxFirst); | |
645 block->children()->insertChildNode(block, newBlockBox, boxFirst); | |
646 block->children()->insertChildNode(block, post, boxFirst); | |
647 block->setChildrenInline(false); | |
648 | |
649 if (madeNewBeforeBlock) | |
650 block->moveChildrenTo(pre, boxFirst, 0, true); | |
651 | |
652 splitBlocks(pre, post, newBlockBox, beforeChild, oldCont); | |
653 | |
654 // We already know the newBlockBox isn't going to contain inline kids, so av
oid wasting | |
655 // time in makeChildrenNonInline by just setting this explicitly up front. | |
656 newBlockBox->setChildrenInline(false); | |
657 | |
658 newBlockBox->addChild(newChild); | |
659 | |
660 // Always just do a full layout in order to ensure that line boxes (especial
ly wrappers for images) | |
661 // get deleted properly. Because objects moves from the pre block into the
post block, we want to | |
662 // make new line boxes instead of leaving the old line boxes around. | |
663 pre->setNeedsLayoutAndPrefWidthsRecalc(); | |
664 block->setNeedsLayoutAndPrefWidthsRecalc(); | |
665 post->setNeedsLayoutAndPrefWidthsRecalc(); | |
666 } | |
667 | |
668 void RenderBlock::makeChildrenAnonymousColumnBlocks(RenderObject* beforeChild, R
enderBlockFlow* newBlockBox, RenderObject* newChild) | |
669 { | |
670 RenderBlockFlow* pre = 0; | |
671 RenderBlockFlow* post = 0; | |
672 RenderBlock* block = this; // Eventually block will not just be |this|, but
will also be a block nested inside |this|. Assign to a variable | |
673 // so that we don't have to patch all of the rest
of the code later on. | |
674 | |
675 // Delete the block's line boxes before we do the split. | |
676 block->deleteLineBoxTree(); | |
677 | |
678 if (beforeChild && beforeChild->parent() != this) | |
679 beforeChild = splitAnonymousBoxesAroundChild(beforeChild); | |
680 | |
681 if (beforeChild != firstChild()) { | |
682 pre = block->createAnonymousColumnsBlock(); | |
683 pre->setChildrenInline(block->childrenInline()); | |
684 } | |
685 | |
686 if (beforeChild) { | |
687 post = block->createAnonymousColumnsBlock(); | |
688 post->setChildrenInline(block->childrenInline()); | |
689 } | |
690 | |
691 RenderObject* boxFirst = block->firstChild(); | |
692 if (pre) | |
693 block->children()->insertChildNode(block, pre, boxFirst); | |
694 block->children()->insertChildNode(block, newBlockBox, boxFirst); | |
695 if (post) | |
696 block->children()->insertChildNode(block, post, boxFirst); | |
697 block->setChildrenInline(false); | |
698 | |
699 // The pre/post blocks always have layers, so we know to always do a full in
sert/remove (so we pass true as the last argument). | |
700 block->moveChildrenTo(pre, boxFirst, beforeChild, true); | |
701 block->moveChildrenTo(post, beforeChild, 0, true); | |
702 | |
703 // We already know the newBlockBox isn't going to contain inline kids, so av
oid wasting | |
704 // time in makeChildrenNonInline by just setting this explicitly up front. | |
705 newBlockBox->setChildrenInline(false); | |
706 | |
707 newBlockBox->addChild(newChild); | |
708 | |
709 // Always just do a full layout in order to ensure that line boxes (especial
ly wrappers for images) | |
710 // get deleted properly. Because objects moved from the pre block into the
post block, we want to | |
711 // make new line boxes instead of leaving the old line boxes around. | |
712 if (pre) | |
713 pre->setNeedsLayoutAndPrefWidthsRecalc(); | |
714 block->setNeedsLayoutAndPrefWidthsRecalc(); | |
715 if (post) | |
716 post->setNeedsLayoutAndPrefWidthsRecalc(); | |
717 } | |
718 | |
719 RenderBlockFlow* RenderBlock::columnsBlockForSpanningElement(RenderObject* newCh
ild) | |
720 { | |
721 // FIXME: This function is the gateway for the addition of column-span suppo
rt. It will | |
722 // be added to in three stages: | |
723 // (1) Immediate children of a multi-column block can span. | |
724 // (2) Nested block-level children with only block-level ancestors between t
hem and the multi-column block can span. | |
725 // (3) Nested children with block or inline ancestors between them and the m
ulti-column block can span (this is when we | |
726 // cross the streams and have to cope with both types of continuations mixed
together). | |
727 // This function currently supports (1) and (2). | |
728 RenderBlockFlow* columnsBlockAncestor = 0; | |
729 if (!newChild->isText() && newChild->style()->columnSpan() && !newChild->isB
eforeOrAfterContent() | |
730 && !newChild->isFloatingOrOutOfFlowPositioned() && !newChild->isInline()
&& !isAnonymousColumnSpanBlock()) { | |
731 columnsBlockAncestor = containingColumnsBlock(false); | |
732 if (columnsBlockAncestor) { | |
733 // Make sure that none of the parent ancestors have a continuation. | |
734 // If yes, we do not want split the block into continuations. | |
735 RenderObject* curr = this; | |
736 while (curr && curr != columnsBlockAncestor) { | |
737 if (curr->isRenderBlock() && toRenderBlock(curr)->continuation()
) { | |
738 columnsBlockAncestor = 0; | |
739 break; | |
740 } | |
741 curr = curr->parent(); | |
742 } | |
743 } | |
744 } | |
745 return columnsBlockAncestor; | |
746 } | |
747 | |
748 void RenderBlock::addChildIgnoringAnonymousColumnBlocks(RenderObject* newChild,
RenderObject* beforeChild) | 430 void RenderBlock::addChildIgnoringAnonymousColumnBlocks(RenderObject* newChild,
RenderObject* beforeChild) |
749 { | 431 { |
750 if (beforeChild && beforeChild->parent() != this) { | 432 if (beforeChild && beforeChild->parent() != this) { |
751 RenderObject* beforeChildContainer = beforeChild->parent(); | 433 RenderObject* beforeChildContainer = beforeChild->parent(); |
752 while (beforeChildContainer->parent() != this) | 434 while (beforeChildContainer->parent() != this) |
753 beforeChildContainer = beforeChildContainer->parent(); | 435 beforeChildContainer = beforeChildContainer->parent(); |
754 ASSERT(beforeChildContainer); | 436 ASSERT(beforeChildContainer); |
755 | 437 |
756 if (beforeChildContainer->isAnonymous()) { | 438 if (beforeChildContainer->isAnonymous()) { |
757 // If the requested beforeChild is not one of our children, then thi
s is because | 439 // If the requested beforeChild is not one of our children, then thi
s is because |
(...skipping 23 matching lines...) Expand all Loading... |
781 | 463 |
782 ASSERT(beforeChild->parent() == this); | 464 ASSERT(beforeChild->parent() == this); |
783 if (beforeChild->parent() != this) { | 465 if (beforeChild->parent() != this) { |
784 // We should never reach here. If we do, we need to use the | 466 // We should never reach here. If we do, we need to use the |
785 // safe fallback to use the topmost beforeChild container. | 467 // safe fallback to use the topmost beforeChild container. |
786 beforeChild = beforeChildContainer; | 468 beforeChild = beforeChildContainer; |
787 } | 469 } |
788 } | 470 } |
789 } | 471 } |
790 | 472 |
791 // Check for a spanning element in columns. | |
792 if (gColumnFlowSplitEnabled) { | |
793 RenderBlockFlow* columnsBlockAncestor = columnsBlockForSpanningElement(n
ewChild); | |
794 if (columnsBlockAncestor) { | |
795 TemporaryChange<bool> columnFlowSplitEnabled(gColumnFlowSplitEnabled
, false); | |
796 // We are placing a column-span element inside a block. | |
797 RenderBlockFlow* newBox = createAnonymousColumnSpanBlock(); | |
798 | |
799 if (columnsBlockAncestor != this && !isRenderFlowThread()) { | |
800 // We are nested inside a multi-column element and are being spl
it by the span. We have to break up | |
801 // our block into continuations. | |
802 RenderBoxModelObject* oldContinuation = continuation(); | |
803 | |
804 // When we split an anonymous block, there's no need to do any c
ontinuation hookup, | |
805 // since we haven't actually split a real element. | |
806 if (!isAnonymousBlock()) | |
807 setContinuation(newBox); | |
808 | |
809 splitFlow(beforeChild, newBox, newChild, oldContinuation); | |
810 return; | |
811 } | |
812 | |
813 // We have to perform a split of this block's children. This involve
s creating an anonymous block box to hold | |
814 // the column-spanning |newChild|. We take all of the children from
before |newChild| and put them into | |
815 // one anonymous columns block, and all of the children after |newCh
ild| go into another anonymous block. | |
816 makeChildrenAnonymousColumnBlocks(beforeChild, newBox, newChild); | |
817 return; | |
818 } | |
819 } | |
820 | |
821 bool madeBoxesNonInline = false; | 473 bool madeBoxesNonInline = false; |
822 | 474 |
823 // A block has to either have all of its children inline, or all of its chil
dren as blocks. | 475 // A block has to either have all of its children inline, or all of its chil
dren as blocks. |
824 // So, if our children are currently inline and a block child has to be inse
rted, we move all our | 476 // So, if our children are currently inline and a block child has to be inse
rted, we move all our |
825 // inline children into anonymous block boxes. | 477 // inline children into anonymous block boxes. |
826 if (childrenInline() && !newChild->isInline() && !newChild->isFloatingOrOutO
fFlowPositioned()) { | 478 if (childrenInline() && !newChild->isInline() && !newChild->isFloatingOrOutO
fFlowPositioned()) { |
827 // This is a block with inline content. Wrap the inline content in anony
mous blocks. | 479 // This is a block with inline content. Wrap the inline content in anony
mous blocks. |
828 makeChildrenNonInline(beforeChild); | 480 makeChildrenNonInline(beforeChild); |
829 madeBoxesNonInline = true; | 481 madeBoxesNonInline = true; |
830 | 482 |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
863 void RenderBlock::addChild(RenderObject* newChild, RenderObject* beforeChild) | 515 void RenderBlock::addChild(RenderObject* newChild, RenderObject* beforeChild) |
864 { | 516 { |
865 if (continuation() && !isAnonymousBlock()) | 517 if (continuation() && !isAnonymousBlock()) |
866 addChildToContinuation(newChild, beforeChild); | 518 addChildToContinuation(newChild, beforeChild); |
867 else | 519 else |
868 addChildIgnoringContinuation(newChild, beforeChild); | 520 addChildIgnoringContinuation(newChild, beforeChild); |
869 } | 521 } |
870 | 522 |
871 void RenderBlock::addChildIgnoringContinuation(RenderObject* newChild, RenderObj
ect* beforeChild) | 523 void RenderBlock::addChildIgnoringContinuation(RenderObject* newChild, RenderObj
ect* beforeChild) |
872 { | 524 { |
873 if (!isAnonymousBlock() && firstChild() && (firstChild()->isAnonymousColumns
Block() || firstChild()->isAnonymousColumnSpanBlock())) | 525 addChildIgnoringAnonymousColumnBlocks(newChild, beforeChild); |
874 addChildToAnonymousColumnBlocks(newChild, beforeChild); | |
875 else | |
876 addChildIgnoringAnonymousColumnBlocks(newChild, beforeChild); | |
877 } | 526 } |
878 | 527 |
879 static void getInlineRun(RenderObject* start, RenderObject* boundary, | 528 static void getInlineRun(RenderObject* start, RenderObject* boundary, |
880 RenderObject*& inlineRunStart, | 529 RenderObject*& inlineRunStart, |
881 RenderObject*& inlineRunEnd) | 530 RenderObject*& inlineRunEnd) |
882 { | 531 { |
883 // Beginning at |start| we find the largest contiguous run of inlines that | 532 // Beginning at |start| we find the largest contiguous run of inlines that |
884 // we can. We denote the run with start and end points, |inlineRunStart| | 533 // we can. We denote the run with start and end points, |inlineRunStart| |
885 // and |inlineRunEnd|. Note that these two values may be the same if | 534 // and |inlineRunEnd|. Note that these two values may be the same if |
886 // we encounter only one inline. | 535 // we encounter only one inline. |
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
964 #endif | 613 #endif |
965 | 614 |
966 repaint(); | 615 repaint(); |
967 } | 616 } |
968 | 617 |
969 void RenderBlock::removeLeftoverAnonymousBlock(RenderBlock* child) | 618 void RenderBlock::removeLeftoverAnonymousBlock(RenderBlock* child) |
970 { | 619 { |
971 ASSERT(child->isAnonymousBlock()); | 620 ASSERT(child->isAnonymousBlock()); |
972 ASSERT(!child->childrenInline()); | 621 ASSERT(!child->childrenInline()); |
973 | 622 |
974 if (child->continuation() || (child->firstChild() && (child->isAnonymousColu
mnSpanBlock() || child->isAnonymousColumnsBlock()))) | 623 if (child->continuation()) |
975 return; | 624 return; |
976 | 625 |
977 RenderObject* firstAnChild = child->m_children.firstChild(); | 626 RenderObject* firstAnChild = child->m_children.firstChild(); |
978 RenderObject* lastAnChild = child->m_children.lastChild(); | 627 RenderObject* lastAnChild = child->m_children.lastChild(); |
979 if (firstAnChild) { | 628 if (firstAnChild) { |
980 RenderObject* o = firstAnChild; | 629 RenderObject* o = firstAnChild; |
981 while (o) { | 630 while (o) { |
982 o->setParent(this); | 631 o->setParent(this); |
983 o = o->nextSibling(); | 632 o = o->nextSibling(); |
984 } | 633 } |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1024 return false; | 673 return false; |
1025 | 674 |
1026 if ((prev && (!prev->isAnonymousBlock() || toRenderBlock(prev)->continuation
() || toRenderBlock(prev)->beingDestroyed())) | 675 if ((prev && (!prev->isAnonymousBlock() || toRenderBlock(prev)->continuation
() || toRenderBlock(prev)->beingDestroyed())) |
1027 || (next && (!next->isAnonymousBlock() || toRenderBlock(next)->continuat
ion() || toRenderBlock(next)->beingDestroyed()))) | 676 || (next && (!next->isAnonymousBlock() || toRenderBlock(next)->continuat
ion() || toRenderBlock(next)->beingDestroyed()))) |
1028 return false; | 677 return false; |
1029 | 678 |
1030 if ((prev && (prev->isRubyRun() || prev->isRubyBase())) | 679 if ((prev && (prev->isRubyRun() || prev->isRubyBase())) |
1031 || (next && (next->isRubyRun() || next->isRubyBase()))) | 680 || (next && (next->isRubyRun() || next->isRubyBase()))) |
1032 return false; | 681 return false; |
1033 | 682 |
1034 if (!prev || !next) | 683 return true; |
1035 return true; | |
1036 | |
1037 // Make sure the types of the anonymous blocks match up. | |
1038 return prev->isAnonymousColumnsBlock() == next->isAnonymousColumnsBlock() | |
1039 && prev->isAnonymousColumnSpanBlock() == next->isAnonymousColumnSpanB
lock(); | |
1040 } | 684 } |
1041 | 685 |
1042 void RenderBlock::collapseAnonymousBlockChild(RenderBlock* parent, RenderBlock*
child) | 686 void RenderBlock::collapseAnonymousBlockChild(RenderBlock* parent, RenderBlock*
child) |
1043 { | 687 { |
1044 // It's possible that this block's destruction may have been triggered by th
e | 688 // It's possible that this block's destruction may have been triggered by th
e |
1045 // child's removal. Just bail if the anonymous child block is already being | 689 // child's removal. Just bail if the anonymous child block is already being |
1046 // destroyed. See crbug.com/282088 | 690 // destroyed. See crbug.com/282088 |
1047 if (child->beingDestroyed()) | 691 if (child->beingDestroyed()) |
1048 return; | 692 return; |
1049 parent->setNeedsLayoutAndPrefWidthsRecalc(); | 693 parent->setNeedsLayoutAndPrefWidthsRecalc(); |
(...skipping 15 matching lines...) Expand all Loading... |
1065 | 709 |
1066 void RenderBlock::removeChild(RenderObject* oldChild) | 710 void RenderBlock::removeChild(RenderObject* oldChild) |
1067 { | 711 { |
1068 // No need to waste time in merging or removing empty anonymous blocks. | 712 // No need to waste time in merging or removing empty anonymous blocks. |
1069 // We can just bail out if our document is getting destroyed. | 713 // We can just bail out if our document is getting destroyed. |
1070 if (documentBeingDestroyed()) { | 714 if (documentBeingDestroyed()) { |
1071 RenderBox::removeChild(oldChild); | 715 RenderBox::removeChild(oldChild); |
1072 return; | 716 return; |
1073 } | 717 } |
1074 | 718 |
1075 // This protects against column split flows when anonymous blocks are gettin
g merged. | |
1076 TemporaryChange<bool> columnFlowSplitEnabled(gColumnFlowSplitEnabled, false)
; | |
1077 | |
1078 // If this child is a block, and if our previous and next siblings are | 719 // If this child is a block, and if our previous and next siblings are |
1079 // both anonymous blocks with inline content, then we can go ahead and | 720 // both anonymous blocks with inline content, then we can go ahead and |
1080 // fold the inline content back together. | 721 // fold the inline content back together. |
1081 RenderObject* prev = oldChild->previousSibling(); | 722 RenderObject* prev = oldChild->previousSibling(); |
1082 RenderObject* next = oldChild->nextSibling(); | 723 RenderObject* next = oldChild->nextSibling(); |
1083 bool canMergeAnonymousBlocks = canMergeContiguousAnonymousBlocks(oldChild, p
rev, next); | 724 bool canMergeAnonymousBlocks = canMergeContiguousAnonymousBlocks(oldChild, p
rev, next); |
1084 if (canMergeAnonymousBlocks && prev && next) { | 725 if (canMergeAnonymousBlocks && prev && next) { |
1085 prev->setNeedsLayoutAndPrefWidthsRecalc(); | 726 prev->setNeedsLayoutAndPrefWidthsRecalc(); |
1086 RenderBlockFlow* nextBlock = toRenderBlockFlow(next); | 727 RenderBlockFlow* nextBlock = toRenderBlockFlow(next); |
1087 RenderBlockFlow* prevBlock = toRenderBlockFlow(prev); | 728 RenderBlockFlow* prevBlock = toRenderBlockFlow(prev); |
(...skipping 395 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1483 | 1124 |
1484 void RenderBlock::computeRegionRangeForBlock(RenderFlowThread* flowThread) | 1125 void RenderBlock::computeRegionRangeForBlock(RenderFlowThread* flowThread) |
1485 { | 1126 { |
1486 if (flowThread) | 1127 if (flowThread) |
1487 flowThread->setRegionRangeForBox(this, offsetFromLogicalTopOfFirstPage()
); | 1128 flowThread->setRegionRangeForBox(this, offsetFromLogicalTopOfFirstPage()
); |
1488 } | 1129 } |
1489 | 1130 |
1490 bool RenderBlock::updateLogicalWidthAndColumnWidth() | 1131 bool RenderBlock::updateLogicalWidthAndColumnWidth() |
1491 { | 1132 { |
1492 LayoutUnit oldWidth = logicalWidth(); | 1133 LayoutUnit oldWidth = logicalWidth(); |
1493 LayoutUnit oldColumnWidth = desiredColumnWidth(); | |
1494 | 1134 |
1495 updateLogicalWidth(); | 1135 updateLogicalWidth(); |
1496 calcColumnWidth(); | |
1497 | 1136 |
1498 bool hasBorderOrPaddingLogicalWidthChanged = m_hasBorderOrPaddingLogicalWidt
hChanged; | 1137 bool hasBorderOrPaddingLogicalWidthChanged = m_hasBorderOrPaddingLogicalWidt
hChanged; |
1499 m_hasBorderOrPaddingLogicalWidthChanged = false; | 1138 m_hasBorderOrPaddingLogicalWidthChanged = false; |
1500 | 1139 |
1501 return oldWidth != logicalWidth() || oldColumnWidth != desiredColumnWidth()
|| hasBorderOrPaddingLogicalWidthChanged; | 1140 return oldWidth != logicalWidth() || hasBorderOrPaddingLogicalWidthChanged; |
1502 } | 1141 } |
1503 | 1142 |
1504 void RenderBlock::checkForPaginationLogicalHeightChange(LayoutUnit& pageLogicalH
eight, bool& pageLogicalHeightChanged, bool& hasSpecifiedPageLogicalHeight) | 1143 void RenderBlock::checkForPaginationLogicalHeightChange(LayoutUnit& pageLogicalH
eight, bool& pageLogicalHeightChanged, bool& hasSpecifiedPageLogicalHeight) |
1505 { | 1144 { |
1506 ColumnInfo* colInfo = columnInfo(); | 1145 if (isRenderFlowThread()) { |
1507 if (hasColumns()) { | |
1508 if (!pageLogicalHeight) { | |
1509 LayoutUnit oldLogicalHeight = logicalHeight(); | |
1510 setLogicalHeight(0); | |
1511 // We need to go ahead and set our explicit page height if one exist
s, so that we can | |
1512 // avoid doing two layout passes. | |
1513 updateLogicalHeight(); | |
1514 LayoutUnit columnHeight = contentLogicalHeight(); | |
1515 if (columnHeight > 0) { | |
1516 pageLogicalHeight = columnHeight; | |
1517 hasSpecifiedPageLogicalHeight = true; | |
1518 } | |
1519 setLogicalHeight(oldLogicalHeight); | |
1520 } | |
1521 if (colInfo->columnHeight() != pageLogicalHeight && everHadLayout()) { | |
1522 colInfo->setColumnHeight(pageLogicalHeight); | |
1523 pageLogicalHeightChanged = true; | |
1524 } | |
1525 | |
1526 if (!hasSpecifiedPageLogicalHeight && !pageLogicalHeight) | |
1527 colInfo->clearForcedBreaks(); | |
1528 | |
1529 colInfo->setPaginationUnit(paginationUnit()); | |
1530 } else if (isRenderFlowThread()) { | |
1531 pageLogicalHeight = 1; // This is just a hack to always make sure we hav
e a page logical height. | 1146 pageLogicalHeight = 1; // This is just a hack to always make sure we hav
e a page logical height. |
1532 pageLogicalHeightChanged = toRenderFlowThread(this)->pageLogicalSizeChan
ged(); | 1147 pageLogicalHeightChanged = toRenderFlowThread(this)->pageLogicalSizeChan
ged(); |
1533 } | 1148 } |
1534 } | 1149 } |
1535 | 1150 |
1536 void RenderBlock::layoutBlock(bool) | 1151 void RenderBlock::layoutBlock(bool) |
1537 { | 1152 { |
1538 ASSERT_NOT_REACHED(); | 1153 ASSERT_NOT_REACHED(); |
1539 clearNeedsLayout(); | 1154 clearNeedsLayout(); |
1540 } | 1155 } |
1541 | 1156 |
1542 void RenderBlock::addOverflowFromChildren() | 1157 void RenderBlock::addOverflowFromChildren() |
1543 { | 1158 { |
1544 if (!hasColumns()) { | 1159 if (childrenInline()) |
1545 if (childrenInline()) | 1160 toRenderBlockFlow(this)->addOverflowFromInlineChildren(); |
1546 toRenderBlockFlow(this)->addOverflowFromInlineChildren(); | 1161 else |
1547 else | 1162 addOverflowFromBlockChildren(); |
1548 addOverflowFromBlockChildren(); | |
1549 } else { | |
1550 ColumnInfo* colInfo = columnInfo(); | |
1551 if (columnCount(colInfo)) { | |
1552 LayoutRect lastRect = columnRectAt(colInfo, columnCount(colInfo) - 1
); | |
1553 addLayoutOverflow(lastRect); | |
1554 addContentsVisualOverflow(lastRect); | |
1555 } | |
1556 } | |
1557 } | 1163 } |
1558 | 1164 |
1559 void RenderBlock::computeOverflow(LayoutUnit oldClientAfterEdge, bool) | 1165 void RenderBlock::computeOverflow(LayoutUnit oldClientAfterEdge, bool) |
1560 { | 1166 { |
1561 m_overflow.clear(); | 1167 m_overflow.clear(); |
1562 | 1168 |
1563 // Add overflow from children. | 1169 // Add overflow from children. |
1564 addOverflowFromChildren(); | 1170 addOverflowFromChildren(); |
1565 | 1171 |
1566 // Add in the overflow from positioned objects. | 1172 // Add in the overflow from positioned objects. |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1622 return; | 1228 return; |
1623 | 1229 |
1624 IntRect inflatedRect = pixelSnappedBorderBoxRect(); | 1230 IntRect inflatedRect = pixelSnappedBorderBoxRect(); |
1625 RenderTheme::theme().adjustRepaintRect(this, inflatedRect); | 1231 RenderTheme::theme().adjustRepaintRect(this, inflatedRect); |
1626 addVisualOverflow(inflatedRect); | 1232 addVisualOverflow(inflatedRect); |
1627 } | 1233 } |
1628 | 1234 |
1629 bool RenderBlock::expandsToEncloseOverhangingFloats() const | 1235 bool RenderBlock::expandsToEncloseOverhangingFloats() const |
1630 { | 1236 { |
1631 return isInlineBlockOrInlineTable() || isFloatingOrOutOfFlowPositioned() ||
hasOverflowClip() || (parent() && parent()->isFlexibleBoxIncludingDeprecated()) | 1237 return isInlineBlockOrInlineTable() || isFloatingOrOutOfFlowPositioned() ||
hasOverflowClip() || (parent() && parent()->isFlexibleBoxIncludingDeprecated()) |
1632 || hasColumns() || isTableCell() || isTableCaption() || isFieldset()
|| isWritingModeRoot() || isRoot(); | 1238 || isTableCell() || isTableCaption() || isFieldset() || isWritingModeRoo
t() || isRoot(); |
1633 } | 1239 } |
1634 | 1240 |
1635 void RenderBlock::determineLogicalLeftPositionForChild(RenderBox* child, ApplyLa
youtDeltaMode applyDelta) | 1241 void RenderBlock::determineLogicalLeftPositionForChild(RenderBox* child, ApplyLa
youtDeltaMode applyDelta) |
1636 { | 1242 { |
1637 LayoutUnit startPosition = borderStart() + paddingStart(); | 1243 LayoutUnit startPosition = borderStart() + paddingStart(); |
1638 if (style()->shouldPlaceBlockDirectionScrollbarOnLogicalLeft()) | 1244 if (style()->shouldPlaceBlockDirectionScrollbarOnLogicalLeft()) |
1639 startPosition -= verticalScrollbarWidth(); | 1245 startPosition -= verticalScrollbarWidth(); |
1640 LayoutUnit totalAvailableLogicalWidth = borderAndPaddingLogicalWidth() + ava
ilableLogicalWidth(); | 1246 LayoutUnit totalAvailableLogicalWidth = borderAndPaddingLogicalWidth() + ava
ilableLogicalWidth(); |
1641 | 1247 |
1642 // Add in our start margin. | 1248 // Add in our start margin. |
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1718 box->layoutIfNeeded(); | 1324 box->layoutIfNeeded(); |
1719 } | 1325 } |
1720 } | 1326 } |
1721 } | 1327 } |
1722 | 1328 |
1723 bool RenderBlock::simplifiedLayout() | 1329 bool RenderBlock::simplifiedLayout() |
1724 { | 1330 { |
1725 if ((!posChildNeedsLayout() && !needsSimplifiedNormalFlowLayout()) || normal
ChildNeedsLayout() || selfNeedsLayout()) | 1331 if ((!posChildNeedsLayout() && !needsSimplifiedNormalFlowLayout()) || normal
ChildNeedsLayout() || selfNeedsLayout()) |
1726 return false; | 1332 return false; |
1727 | 1333 |
1728 LayoutStateMaintainer statePusher(view(), this, locationOffset(), hasColumns
() || hasTransform() || hasReflection() || style()->isFlippedBlocksWritingMode()
); | 1334 LayoutStateMaintainer statePusher(view(), this, locationOffset(), hasTransfo
rm() || hasReflection() || style()->isFlippedBlocksWritingMode()); |
1729 | 1335 |
1730 if (needsPositionedMovementLayout() && !tryLayoutDoingPositionedMovementOnly
()) | 1336 if (needsPositionedMovementLayout() && !tryLayoutDoingPositionedMovementOnly
()) |
1731 return false; | 1337 return false; |
1732 | 1338 |
1733 // Lay out positioned descendants or objects that just need to recompute ove
rflow. | 1339 // Lay out positioned descendants or objects that just need to recompute ove
rflow. |
1734 if (needsSimplifiedNormalFlowLayout()) | 1340 if (needsSimplifiedNormalFlowLayout()) |
1735 simplifiedNormalFlowLayout(); | 1341 simplifiedNormalFlowLayout(); |
1736 | 1342 |
1737 // Make sure a forced break is applied after the content if we are a flow th
read in a simplified layout. | 1343 // Make sure a forced break is applied after the content if we are a flow th
read in a simplified layout. |
1738 // This ensures the size information is correctly computed for the last auto
-height region receiving content. | 1344 // This ensures the size information is correctly computed for the last auto
-height region receiving content. |
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1812 margin += marginRight.value(); | 1418 margin += marginRight.value(); |
1813 return margin; | 1419 return margin; |
1814 } | 1420 } |
1815 | 1421 |
1816 void RenderBlock::layoutPositionedObjects(bool relayoutChildren, bool fixedPosit
ionObjectsOnly) | 1422 void RenderBlock::layoutPositionedObjects(bool relayoutChildren, bool fixedPosit
ionObjectsOnly) |
1817 { | 1423 { |
1818 TrackedRendererListHashSet* positionedDescendants = positionedObjects(); | 1424 TrackedRendererListHashSet* positionedDescendants = positionedObjects(); |
1819 if (!positionedDescendants) | 1425 if (!positionedDescendants) |
1820 return; | 1426 return; |
1821 | 1427 |
1822 if (hasColumns()) | |
1823 view()->layoutState()->clearPaginationInformation(); // Positioned objec
ts are not part of the column flow, so they don't paginate with the columns. | |
1824 | |
1825 RenderBox* r; | 1428 RenderBox* r; |
1826 TrackedRendererListHashSet::iterator end = positionedDescendants->end(); | 1429 TrackedRendererListHashSet::iterator end = positionedDescendants->end(); |
1827 for (TrackedRendererListHashSet::iterator it = positionedDescendants->begin(
); it != end; ++it) { | 1430 for (TrackedRendererListHashSet::iterator it = positionedDescendants->begin(
); it != end; ++it) { |
1828 r = *it; | 1431 r = *it; |
1829 | 1432 |
1830 SubtreeLayoutScope layoutScope(r); | 1433 SubtreeLayoutScope layoutScope(r); |
1831 // A fixed position element with an absolute positioned ancestor has no
way of knowing if the latter has changed position. So | 1434 // A fixed position element with an absolute positioned ancestor has no
way of knowing if the latter has changed position. So |
1832 // if this is a fixed position element, mark it for layout if it has an
abspos ancestor and needs to move with that ancestor, i.e. | 1435 // if this is a fixed position element, mark it for layout if it has an
abspos ancestor and needs to move with that ancestor, i.e. |
1833 // it has static position. | 1436 // it has static position. |
1834 markFixedPositionObjectForLayoutIfNeeded(r, layoutScope); | 1437 markFixedPositionObjectForLayoutIfNeeded(r, layoutScope); |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1867 r->updateLogicalWidth(); | 1470 r->updateLogicalWidth(); |
1868 oldLogicalTop = logicalTopForChild(r); | 1471 oldLogicalTop = logicalTopForChild(r); |
1869 } | 1472 } |
1870 | 1473 |
1871 r->layoutIfNeeded(); | 1474 r->layoutIfNeeded(); |
1872 | 1475 |
1873 // Lay out again if our estimate was wrong. | 1476 // Lay out again if our estimate was wrong. |
1874 if (needsBlockDirectionLocationSetBeforeLayout && logicalTopForChild(r)
!= oldLogicalTop) | 1477 if (needsBlockDirectionLocationSetBeforeLayout && logicalTopForChild(r)
!= oldLogicalTop) |
1875 r->forceChildLayout(); | 1478 r->forceChildLayout(); |
1876 } | 1479 } |
1877 | |
1878 if (hasColumns()) | |
1879 view()->layoutState()->m_columnInfo = columnInfo(); // FIXME: Kind of gr
oss. We just put this back into the layout state so that pop() will work. | |
1880 } | 1480 } |
1881 | 1481 |
1882 void RenderBlock::markPositionedObjectsForLayout() | 1482 void RenderBlock::markPositionedObjectsForLayout() |
1883 { | 1483 { |
1884 TrackedRendererListHashSet* positionedDescendants = positionedObjects(); | 1484 TrackedRendererListHashSet* positionedDescendants = positionedObjects(); |
1885 if (positionedDescendants) { | 1485 if (positionedDescendants) { |
1886 RenderBox* r; | 1486 RenderBox* r; |
1887 TrackedRendererListHashSet::iterator end = positionedDescendants->end(); | 1487 TrackedRendererListHashSet::iterator end = positionedDescendants->end(); |
1888 for (TrackedRendererListHashSet::iterator it = positionedDescendants->be
gin(); it != end; ++it) { | 1488 for (TrackedRendererListHashSet::iterator it = positionedDescendants->be
gin(); it != end; ++it) { |
1889 r = *it; | 1489 r = *it; |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1933 if (pushedClip) | 1533 if (pushedClip) |
1934 popContentsClip(paintInfo, phase, adjustedPaintOffset); | 1534 popContentsClip(paintInfo, phase, adjustedPaintOffset); |
1935 | 1535 |
1936 // Our scrollbar widgets paint exactly when we tell them to, so that they wo
rk properly with | 1536 // Our scrollbar widgets paint exactly when we tell them to, so that they wo
rk properly with |
1937 // z-index. We paint after we painted the background/border, so that the sc
rollbars will | 1537 // z-index. We paint after we painted the background/border, so that the sc
rollbars will |
1938 // sit above the background/border. | 1538 // sit above the background/border. |
1939 if (hasOverflowClip() && style()->visibility() == VISIBLE && (phase == Paint
PhaseBlockBackground || phase == PaintPhaseChildBlockBackground) && paintInfo.sh
ouldPaintWithinRoot(this) && !paintInfo.paintRootBackgroundOnly()) | 1539 if (hasOverflowClip() && style()->visibility() == VISIBLE && (phase == Paint
PhaseBlockBackground || phase == PaintPhaseChildBlockBackground) && paintInfo.sh
ouldPaintWithinRoot(this) && !paintInfo.paintRootBackgroundOnly()) |
1940 layer()->scrollableArea()->paintOverflowControls(paintInfo.context, roun
dedIntPoint(adjustedPaintOffset), paintInfo.rect, false /* paintingOverlayContro
ls */); | 1540 layer()->scrollableArea()->paintOverflowControls(paintInfo.context, roun
dedIntPoint(adjustedPaintOffset), paintInfo.rect, false /* paintingOverlayContro
ls */); |
1941 } | 1541 } |
1942 | 1542 |
1943 void RenderBlock::paintColumnRules(PaintInfo& paintInfo, const LayoutPoint& pain
tOffset) | |
1944 { | |
1945 if (paintInfo.context->paintingDisabled()) | |
1946 return; | |
1947 | |
1948 const Color& ruleColor = resolveColor(CSSPropertyWebkitColumnRuleColor); | |
1949 bool ruleTransparent = style()->columnRuleIsTransparent(); | |
1950 EBorderStyle ruleStyle = style()->columnRuleStyle(); | |
1951 LayoutUnit ruleThickness = style()->columnRuleWidth(); | |
1952 LayoutUnit colGap = columnGap(); | |
1953 bool renderRule = ruleStyle > BHIDDEN && !ruleTransparent; | |
1954 if (!renderRule) | |
1955 return; | |
1956 | |
1957 ColumnInfo* colInfo = columnInfo(); | |
1958 unsigned colCount = columnCount(colInfo); | |
1959 | |
1960 bool antialias = shouldAntialiasLines(paintInfo.context); | |
1961 | |
1962 if (colInfo->progressionAxis() == ColumnInfo::InlineAxis) { | |
1963 bool leftToRight = style()->isLeftToRightDirection() ^ colInfo->progress
ionIsReversed(); | |
1964 LayoutUnit currLogicalLeftOffset = leftToRight ? LayoutUnit() : contentL
ogicalWidth(); | |
1965 LayoutUnit ruleAdd = logicalLeftOffsetForContent(); | |
1966 LayoutUnit ruleLogicalLeft = leftToRight ? LayoutUnit() : contentLogical
Width(); | |
1967 LayoutUnit inlineDirectionSize = colInfo->desiredColumnWidth(); | |
1968 BoxSide boxSide = isHorizontalWritingMode() | |
1969 ? leftToRight ? BSLeft : BSRight | |
1970 : leftToRight ? BSTop : BSBottom; | |
1971 | |
1972 for (unsigned i = 0; i < colCount; i++) { | |
1973 // Move to the next position. | |
1974 if (leftToRight) { | |
1975 ruleLogicalLeft += inlineDirectionSize + colGap / 2; | |
1976 currLogicalLeftOffset += inlineDirectionSize + colGap; | |
1977 } else { | |
1978 ruleLogicalLeft -= (inlineDirectionSize + colGap / 2); | |
1979 currLogicalLeftOffset -= (inlineDirectionSize + colGap); | |
1980 } | |
1981 | |
1982 // Now paint the column rule. | |
1983 if (i < colCount - 1) { | |
1984 LayoutUnit ruleLeft = isHorizontalWritingMode() ? paintOffset.x(
) + ruleLogicalLeft - ruleThickness / 2 + ruleAdd : paintOffset.x() + borderLeft
() + paddingLeft(); | |
1985 LayoutUnit ruleRight = isHorizontalWritingMode() ? ruleLeft + ru
leThickness : ruleLeft + contentWidth(); | |
1986 LayoutUnit ruleTop = isHorizontalWritingMode() ? paintOffset.y()
+ borderTop() + paddingTop() : paintOffset.y() + ruleLogicalLeft - ruleThicknes
s / 2 + ruleAdd; | |
1987 LayoutUnit ruleBottom = isHorizontalWritingMode() ? ruleTop + co
ntentHeight() : ruleTop + ruleThickness; | |
1988 IntRect pixelSnappedRuleRect = pixelSnappedIntRectFromEdges(rule
Left, ruleTop, ruleRight, ruleBottom); | |
1989 drawLineForBoxSide(paintInfo.context, pixelSnappedRuleRect.x(),
pixelSnappedRuleRect.y(), pixelSnappedRuleRect.maxX(), pixelSnappedRuleRect.maxY
(), boxSide, ruleColor, ruleStyle, 0, 0, antialias); | |
1990 } | |
1991 | |
1992 ruleLogicalLeft = currLogicalLeftOffset; | |
1993 } | |
1994 } else { | |
1995 bool topToBottom = !style()->isFlippedBlocksWritingMode() ^ colInfo->pro
gressionIsReversed(); | |
1996 LayoutUnit ruleLeft = isHorizontalWritingMode() | |
1997 ? borderLeft() + paddingLeft() | |
1998 : colGap / 2 - colGap - ruleThickness / 2 + (!colInfo->progressionIs
Reversed() ? borderBefore() + paddingBefore() : borderAfter() + paddingAfter()); | |
1999 LayoutUnit ruleWidth = isHorizontalWritingMode() ? contentWidth() : rule
Thickness; | |
2000 LayoutUnit ruleTop = isHorizontalWritingMode() | |
2001 ? colGap / 2 - colGap - ruleThickness / 2 + (!colInfo->progressionIs
Reversed() ? borderBefore() + paddingBefore() : borderAfter() + paddingAfter()) | |
2002 : borderStart() + paddingStart(); | |
2003 LayoutUnit ruleHeight = isHorizontalWritingMode() ? ruleThickness : cont
entHeight(); | |
2004 LayoutRect ruleRect(ruleLeft, ruleTop, ruleWidth, ruleHeight); | |
2005 | |
2006 if (!topToBottom) { | |
2007 if (isHorizontalWritingMode()) | |
2008 ruleRect.setY(height() - ruleRect.maxY()); | |
2009 else | |
2010 ruleRect.setX(width() - ruleRect.maxX()); | |
2011 } | |
2012 | |
2013 ruleRect.moveBy(paintOffset); | |
2014 | |
2015 BoxSide boxSide = isHorizontalWritingMode() | |
2016 ? topToBottom ? BSTop : BSBottom | |
2017 : topToBottom ? BSLeft : BSRight; | |
2018 | |
2019 LayoutSize step(0, topToBottom ? colInfo->columnHeight() + colGap : -(co
lInfo->columnHeight() + colGap)); | |
2020 if (!isHorizontalWritingMode()) | |
2021 step = step.transposedSize(); | |
2022 | |
2023 for (unsigned i = 1; i < colCount; i++) { | |
2024 ruleRect.move(step); | |
2025 IntRect pixelSnappedRuleRect = pixelSnappedIntRect(ruleRect); | |
2026 drawLineForBoxSide(paintInfo.context, pixelSnappedRuleRect.x(), pixe
lSnappedRuleRect.y(), pixelSnappedRuleRect.maxX(), pixelSnappedRuleRect.maxY(),
boxSide, ruleColor, ruleStyle, 0, 0, antialias); | |
2027 } | |
2028 } | |
2029 } | |
2030 | |
2031 void RenderBlock::paintColumnContents(PaintInfo& paintInfo, const LayoutPoint& p
aintOffset, bool paintingFloats) | |
2032 { | |
2033 // We need to do multiple passes, breaking up our child painting into strips
. | |
2034 GraphicsContext* context = paintInfo.context; | |
2035 ColumnInfo* colInfo = columnInfo(); | |
2036 unsigned colCount = columnCount(colInfo); | |
2037 if (!colCount) | |
2038 return; | |
2039 LayoutUnit currLogicalTopOffset = 0; | |
2040 LayoutUnit colGap = columnGap(); | |
2041 for (unsigned i = 0; i < colCount; i++) { | |
2042 // For each rect, we clip to the rect, and then we adjust our coords. | |
2043 LayoutRect colRect = columnRectAt(colInfo, i); | |
2044 flipForWritingMode(colRect); | |
2045 LayoutUnit logicalLeftOffset = (isHorizontalWritingMode() ? colRect.x()
: colRect.y()) - logicalLeftOffsetForContent(); | |
2046 LayoutSize offset = isHorizontalWritingMode() ? LayoutSize(logicalLeftOf
fset, currLogicalTopOffset) : LayoutSize(currLogicalTopOffset, logicalLeftOffset
); | |
2047 if (colInfo->progressionAxis() == ColumnInfo::BlockAxis) { | |
2048 if (isHorizontalWritingMode()) | |
2049 offset.expand(0, colRect.y() - borderTop() - paddingTop()); | |
2050 else | |
2051 offset.expand(colRect.x() - borderLeft() - paddingLeft(), 0); | |
2052 } | |
2053 colRect.moveBy(paintOffset); | |
2054 PaintInfo info(paintInfo); | |
2055 info.rect.intersect(pixelSnappedIntRect(colRect)); | |
2056 | |
2057 if (!info.rect.isEmpty()) { | |
2058 GraphicsContextStateSaver stateSaver(*context); | |
2059 LayoutRect clipRect(colRect); | |
2060 | |
2061 if (i < colCount - 1) { | |
2062 if (isHorizontalWritingMode()) | |
2063 clipRect.expand(colGap / 2, 0); | |
2064 else | |
2065 clipRect.expand(0, colGap / 2); | |
2066 } | |
2067 // Each strip pushes a clip, since column boxes are specified as bei
ng | |
2068 // like overflow:hidden. | |
2069 // FIXME: Content and column rules that extend outside column boxes
at the edges of the multi-column element | |
2070 // are clipped according to the 'overflow' property. | |
2071 context->clip(pixelSnappedIntRect(clipRect)); | |
2072 | |
2073 // Adjust our x and y when painting. | |
2074 LayoutPoint adjustedPaintOffset = paintOffset + offset; | |
2075 if (paintingFloats) | |
2076 paintFloats(info, adjustedPaintOffset, paintInfo.phase == PaintP
haseSelection || paintInfo.phase == PaintPhaseTextClip); | |
2077 else | |
2078 paintContents(info, adjustedPaintOffset); | |
2079 } | |
2080 | |
2081 LayoutUnit blockDelta = (isHorizontalWritingMode() ? colRect.height() :
colRect.width()); | |
2082 if (style()->isFlippedBlocksWritingMode()) | |
2083 currLogicalTopOffset += blockDelta; | |
2084 else | |
2085 currLogicalTopOffset -= blockDelta; | |
2086 } | |
2087 } | |
2088 | |
2089 void RenderBlock::paintContents(PaintInfo& paintInfo, const LayoutPoint& paintOf
fset) | 1543 void RenderBlock::paintContents(PaintInfo& paintInfo, const LayoutPoint& paintOf
fset) |
2090 { | 1544 { |
2091 // Avoid painting descendants of the root element when stylesheets haven't l
oaded. This eliminates FOUC. | 1545 // Avoid painting descendants of the root element when stylesheets haven't l
oaded. This eliminates FOUC. |
2092 // It's ok not to draw, because later on, when all the stylesheets do load,
styleResolverChanged() on the Document | 1546 // It's ok not to draw, because later on, when all the stylesheets do load,
styleResolverChanged() on the Document |
2093 // will do a full repaint. | 1547 // will do a full repaint. |
2094 if (document().didLayoutWithPendingStylesheets() && !isRenderView()) | 1548 if (document().didLayoutWithPendingStylesheets() && !isRenderView()) |
2095 return; | 1549 return; |
2096 | 1550 |
2097 if (childrenInline()) | 1551 if (childrenInline()) |
2098 m_lineBoxes.paint(this, paintInfo, paintOffset); | 1552 m_lineBoxes.paint(this, paintInfo, paintOffset); |
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2186 | 1640 |
2187 // Adjust our painting position if we're inside a scrolled layer (e.g., an o
verflow:auto div). | 1641 // Adjust our painting position if we're inside a scrolled layer (e.g., an o
verflow:auto div). |
2188 LayoutPoint scrolledOffset = paintOffset; | 1642 LayoutPoint scrolledOffset = paintOffset; |
2189 if (hasOverflowClip()) | 1643 if (hasOverflowClip()) |
2190 scrolledOffset.move(-scrolledContentOffset()); | 1644 scrolledOffset.move(-scrolledContentOffset()); |
2191 | 1645 |
2192 // 1. paint background, borders etc | 1646 // 1. paint background, borders etc |
2193 if ((paintPhase == PaintPhaseBlockBackground || paintPhase == PaintPhaseChil
dBlockBackground) && style()->visibility() == VISIBLE) { | 1647 if ((paintPhase == PaintPhaseBlockBackground || paintPhase == PaintPhaseChil
dBlockBackground) && style()->visibility() == VISIBLE) { |
2194 if (hasBoxDecorations()) | 1648 if (hasBoxDecorations()) |
2195 paintBoxDecorations(paintInfo, paintOffset); | 1649 paintBoxDecorations(paintInfo, paintOffset); |
2196 if (hasColumns() && !paintInfo.paintRootBackgroundOnly()) | |
2197 paintColumnRules(paintInfo, scrolledOffset); | |
2198 } | 1650 } |
2199 | 1651 |
2200 if (paintPhase == PaintPhaseMask && style()->visibility() == VISIBLE) { | 1652 if (paintPhase == PaintPhaseMask && style()->visibility() == VISIBLE) { |
2201 paintMask(paintInfo, paintOffset); | 1653 paintMask(paintInfo, paintOffset); |
2202 return; | 1654 return; |
2203 } | 1655 } |
2204 | 1656 |
2205 if (paintPhase == PaintPhaseClippingMask && style()->visibility() == VISIBLE
) { | 1657 if (paintPhase == PaintPhaseClippingMask && style()->visibility() == VISIBLE
) { |
2206 paintClippingMask(paintInfo, paintOffset); | 1658 paintClippingMask(paintInfo, paintOffset); |
2207 return; | 1659 return; |
2208 } | 1660 } |
2209 | 1661 |
2210 // We're done. We don't bother painting any children. | 1662 // We're done. We don't bother painting any children. |
2211 if (paintPhase == PaintPhaseBlockBackground || paintInfo.paintRootBackground
Only()) | 1663 if (paintPhase == PaintPhaseBlockBackground || paintInfo.paintRootBackground
Only()) |
2212 return; | 1664 return; |
2213 | 1665 |
2214 // 2. paint contents | 1666 // 2. paint contents |
2215 if (paintPhase != PaintPhaseSelfOutline) { | 1667 if (paintPhase != PaintPhaseSelfOutline) |
2216 if (hasColumns()) | 1668 paintContents(paintInfo, scrolledOffset); |
2217 paintColumnContents(paintInfo, scrolledOffset); | |
2218 else | |
2219 paintContents(paintInfo, scrolledOffset); | |
2220 } | |
2221 | 1669 |
2222 // 3. paint selection | 1670 // 3. paint selection |
2223 // FIXME: Make this work with multi column layouts. For now don't fill gaps
. | 1671 // FIXME: Make this work with multi column layouts. For now don't fill gaps
. |
2224 bool isPrinting = document().printing(); | 1672 bool isPrinting = document().printing(); |
2225 if (!isPrinting && !hasColumns()) | 1673 if (!isPrinting) |
2226 paintSelection(paintInfo, scrolledOffset); // Fill in gaps in selection
on lines and between blocks. | 1674 paintSelection(paintInfo, scrolledOffset); // Fill in gaps in selection
on lines and between blocks. |
2227 | 1675 |
2228 // 4. paint floats. | 1676 // 4. paint floats. |
2229 if (paintPhase == PaintPhaseFloat || paintPhase == PaintPhaseSelection || pa
intPhase == PaintPhaseTextClip) { | 1677 if (paintPhase == PaintPhaseFloat || paintPhase == PaintPhaseSelection || pa
intPhase == PaintPhaseTextClip) |
2230 if (hasColumns()) | 1678 paintFloats(paintInfo, scrolledOffset, paintPhase == PaintPhaseSelection
|| paintPhase == PaintPhaseTextClip); |
2231 paintColumnContents(paintInfo, scrolledOffset, true); | |
2232 else | |
2233 paintFloats(paintInfo, scrolledOffset, paintPhase == PaintPhaseSelec
tion || paintPhase == PaintPhaseTextClip); | |
2234 } | |
2235 | 1679 |
2236 // 5. paint outline. | 1680 // 5. paint outline. |
2237 if ((paintPhase == PaintPhaseOutline || paintPhase == PaintPhaseSelfOutline)
&& hasOutline() && style()->visibility() == VISIBLE) | 1681 if ((paintPhase == PaintPhaseOutline || paintPhase == PaintPhaseSelfOutline)
&& hasOutline() && style()->visibility() == VISIBLE) |
2238 paintOutline(paintInfo, LayoutRect(paintOffset, size())); | 1682 paintOutline(paintInfo, LayoutRect(paintOffset, size())); |
2239 | 1683 |
2240 // 6. paint continuation outlines. | 1684 // 6. paint continuation outlines. |
2241 if ((paintPhase == PaintPhaseOutline || paintPhase == PaintPhaseChildOutline
s)) { | 1685 if ((paintPhase == PaintPhaseOutline || paintPhase == PaintPhaseChildOutline
s)) { |
2242 RenderInline* inlineCont = inlineElementContinuation(); | 1686 RenderInline* inlineCont = inlineElementContinuation(); |
2243 if (inlineCont && inlineCont->hasOutline() && inlineCont->style()->visib
ility() == VISIBLE) { | 1687 if (inlineCont && inlineCont->hasOutline() && inlineCont->style()->visib
ility() == VISIBLE) { |
2244 RenderInline* inlineRenderer = toRenderInline(inlineCont->node()->re
nderer()); | 1688 RenderInline* inlineRenderer = toRenderInline(inlineCont->node()->re
nderer()); |
(...skipping 230 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2475 clipOutPositionedObjects(paintInfo, LayoutPoint(cb->x(), cb->y()
), cb->positionedObjects()); // FIXME: Not right for flipped writing modes. | 1919 clipOutPositionedObjects(paintInfo, LayoutPoint(cb->x(), cb->y()
), cb->positionedObjects()); // FIXME: Not right for flipped writing modes. |
2476 clipOutFloatingObjects(rootBlock, paintInfo, rootBlockPhysicalPosition,
offsetFromRootBlock); | 1920 clipOutFloatingObjects(rootBlock, paintInfo, rootBlockPhysicalPosition,
offsetFromRootBlock); |
2477 } | 1921 } |
2478 | 1922 |
2479 // FIXME: overflow: auto/scroll regions need more math here, since painting
in the border box is different from painting in the padding box (one is scrolled
, the other is | 1923 // FIXME: overflow: auto/scroll regions need more math here, since painting
in the border box is different from painting in the padding box (one is scrolled
, the other is |
2480 // fixed). | 1924 // fixed). |
2481 GapRects result; | 1925 GapRects result; |
2482 if (!isRenderBlockFlow() && !isFlexibleBoxIncludingDeprecated()) // FIXME: M
ake multi-column selection gap filling work someday. | 1926 if (!isRenderBlockFlow() && !isFlexibleBoxIncludingDeprecated()) // FIXME: M
ake multi-column selection gap filling work someday. |
2483 return result; | 1927 return result; |
2484 | 1928 |
2485 if (hasColumns() || hasTransform() || style()->columnSpan()) { | 1929 if (hasTransform() || style()->columnSpan()) { |
2486 // FIXME: We should learn how to gap fill multiple columns and transform
s eventually. | 1930 // FIXME: We should learn how to gap fill multiple columns and transform
s eventually. |
2487 lastLogicalTop = rootBlock->blockDirectionOffset(offsetFromRootBlock) +
logicalHeight(); | 1931 lastLogicalTop = rootBlock->blockDirectionOffset(offsetFromRootBlock) +
logicalHeight(); |
2488 lastLogicalLeft = logicalLeftSelectionOffset(rootBlock, logicalHeight())
; | 1932 lastLogicalLeft = logicalLeftSelectionOffset(rootBlock, logicalHeight())
; |
2489 lastLogicalRight = logicalRightSelectionOffset(rootBlock, logicalHeight(
)); | 1933 lastLogicalRight = logicalRightSelectionOffset(rootBlock, logicalHeight(
)); |
2490 return result; | 1934 return result; |
2491 } | 1935 } |
2492 | 1936 |
2493 if (childrenInline()) | 1937 if (childrenInline()) |
2494 result = toRenderBlockFlow(this)->inlineSelectionGaps(rootBlock, rootBlo
ckPhysicalPosition, offsetFromRootBlock, lastLogicalTop, lastLogicalLeft, lastLo
gicalRight, paintInfo); | 1938 result = toRenderBlockFlow(this)->inlineSelectionGaps(rootBlock, rootBlo
ckPhysicalPosition, offsetFromRootBlock, lastLogicalTop, lastLogicalLeft, lastLo
gicalRight, paintInfo); |
2495 else | 1939 else |
(...skipping 414 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2910 afterLowest = lowestDirtyLine; | 2354 afterLowest = lowestDirtyLine; |
2911 lowestDirtyLine = lowestDirtyLine->prevRootBox(); | 2355 lowestDirtyLine = lowestDirtyLine->prevRootBox(); |
2912 } | 2356 } |
2913 | 2357 |
2914 while (afterLowest && afterLowest != highest && (afterLowest->lineBottomWith
Leading() >= logicalTop || afterLowest->lineBottomWithLeading() < 0)) { | 2358 while (afterLowest && afterLowest != highest && (afterLowest->lineBottomWith
Leading() >= logicalTop || afterLowest->lineBottomWithLeading() < 0)) { |
2915 afterLowest->markDirty(); | 2359 afterLowest->markDirty(); |
2916 afterLowest = afterLowest->prevRootBox(); | 2360 afterLowest = afterLowest->prevRootBox(); |
2917 } | 2361 } |
2918 } | 2362 } |
2919 | 2363 |
2920 bool RenderBlock::avoidsFloats() const | |
2921 { | |
2922 // Floats can't intrude into our box if we have a non-auto column count or w
idth. | |
2923 return RenderBox::avoidsFloats() || !style()->hasAutoColumnCount() || !style
()->hasAutoColumnWidth(); | |
2924 } | |
2925 | |
2926 void RenderBlock::markShapeInsideDescendantsForLayout() | 2364 void RenderBlock::markShapeInsideDescendantsForLayout() |
2927 { | 2365 { |
2928 if (!everHadLayout()) | 2366 if (!everHadLayout()) |
2929 return; | 2367 return; |
2930 if (childrenInline()) { | 2368 if (childrenInline()) { |
2931 setNeedsLayout(); | 2369 setNeedsLayout(); |
2932 return; | 2370 return; |
2933 } | 2371 } |
2934 for (RenderObject* child = firstChild(); child; child = child->nextSibling()
) { | 2372 for (RenderObject* child = firstChild(); child; child = child->nextSibling()
) { |
2935 if (!child->isRenderBlock()) | 2373 if (!child->isRenderBlock()) |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2981 // If we have clipping, then we can't have any spillout. | 2419 // If we have clipping, then we can't have any spillout. |
2982 bool useOverflowClip = hasOverflowClip() && !hasSelfPaintingLayer(); | 2420 bool useOverflowClip = hasOverflowClip() && !hasSelfPaintingLayer(); |
2983 bool useClip = (hasControlClip() || useOverflowClip); | 2421 bool useClip = (hasControlClip() || useOverflowClip); |
2984 bool checkChildren = !useClip || (hasControlClip() ? locationInContainer.int
ersects(controlClipRect(adjustedLocation)) : locationInContainer.intersects(over
flowClipRect(adjustedLocation, locationInContainer.region(), IncludeOverlayScrol
lbarSize))); | 2422 bool checkChildren = !useClip || (hasControlClip() ? locationInContainer.int
ersects(controlClipRect(adjustedLocation)) : locationInContainer.intersects(over
flowClipRect(adjustedLocation, locationInContainer.region(), IncludeOverlayScrol
lbarSize))); |
2985 if (checkChildren) { | 2423 if (checkChildren) { |
2986 // Hit test descendants first. | 2424 // Hit test descendants first. |
2987 LayoutSize scrolledOffset(localOffset); | 2425 LayoutSize scrolledOffset(localOffset); |
2988 if (hasOverflowClip()) | 2426 if (hasOverflowClip()) |
2989 scrolledOffset -= scrolledContentOffset(); | 2427 scrolledOffset -= scrolledContentOffset(); |
2990 | 2428 |
2991 // Hit test contents if we don't have columns. | 2429 if (hitTestContents(request, result, locationInContainer, toLayoutPoint(
scrolledOffset), hitTestAction)) { |
2992 if (!hasColumns()) { | |
2993 if (hitTestContents(request, result, locationInContainer, toLayoutPo
int(scrolledOffset), hitTestAction)) { | |
2994 updateHitTestResult(result, flipForWritingMode(locationInContain
er.point() - localOffset)); | |
2995 return true; | |
2996 } | |
2997 if (hitTestAction == HitTestFloat && hitTestFloats(request, result,
locationInContainer, toLayoutPoint(scrolledOffset))) | |
2998 return true; | |
2999 } else if (hitTestColumns(request, result, locationInContainer, toLayout
Point(scrolledOffset), hitTestAction)) { | |
3000 updateHitTestResult(result, flipForWritingMode(locationInContainer.p
oint() - localOffset)); | 2430 updateHitTestResult(result, flipForWritingMode(locationInContainer.p
oint() - localOffset)); |
3001 return true; | 2431 return true; |
3002 } | 2432 } |
| 2433 if (hitTestAction == HitTestFloat && hitTestFloats(request, result, loca
tionInContainer, toLayoutPoint(scrolledOffset))) |
| 2434 return true; |
3003 } | 2435 } |
3004 | 2436 |
3005 // Check if the point is outside radii. | 2437 // Check if the point is outside radii. |
3006 if (!isRenderView() && style()->hasBorderRadius()) { | 2438 if (!isRenderView() && style()->hasBorderRadius()) { |
3007 LayoutRect borderRect = borderBoxRect(); | 2439 LayoutRect borderRect = borderBoxRect(); |
3008 borderRect.moveBy(adjustedLocation); | 2440 borderRect.moveBy(adjustedLocation); |
3009 RoundedRect border = style()->getRoundedBorderFor(borderRect); | 2441 RoundedRect border = style()->getRoundedBorderFor(borderRect); |
3010 if (!locationInContainer.intersects(border)) | 2442 if (!locationInContainer.intersects(border)) |
3011 return false; | 2443 return false; |
3012 } | 2444 } |
3013 | 2445 |
3014 // Now hit test our background | 2446 // Now hit test our background |
3015 if (hitTestAction == HitTestBlockBackground || hitTestAction == HitTestChild
BlockBackground) { | 2447 if (hitTestAction == HitTestBlockBackground || hitTestAction == HitTestChild
BlockBackground) { |
3016 LayoutRect boundsRect(adjustedLocation, size()); | 2448 LayoutRect boundsRect(adjustedLocation, size()); |
3017 if (visibleToHitTestRequest(request) && locationInContainer.intersects(b
oundsRect)) { | 2449 if (visibleToHitTestRequest(request) && locationInContainer.intersects(b
oundsRect)) { |
3018 updateHitTestResult(result, flipForWritingMode(locationInContainer.p
oint() - localOffset)); | 2450 updateHitTestResult(result, flipForWritingMode(locationInContainer.p
oint() - localOffset)); |
3019 if (!result.addNodeToRectBasedTestResult(nodeForHitTest(), request,
locationInContainer, boundsRect)) | 2451 if (!result.addNodeToRectBasedTestResult(nodeForHitTest(), request,
locationInContainer, boundsRect)) |
3020 return true; | 2452 return true; |
3021 } | 2453 } |
3022 } | 2454 } |
3023 | 2455 |
3024 return false; | 2456 return false; |
3025 } | 2457 } |
3026 | 2458 |
3027 class ColumnRectIterator { | |
3028 WTF_MAKE_NONCOPYABLE(ColumnRectIterator); | |
3029 public: | |
3030 ColumnRectIterator(const RenderBlock& block) | |
3031 : m_block(block) | |
3032 , m_colInfo(block.columnInfo()) | |
3033 , m_direction(m_block.style()->isFlippedBlocksWritingMode() ? 1 : -1) | |
3034 , m_isHorizontal(block.isHorizontalWritingMode()) | |
3035 , m_logicalLeft(block.logicalLeftOffsetForContent()) | |
3036 { | |
3037 int colCount = m_colInfo->columnCount(); | |
3038 m_colIndex = colCount - 1; | |
3039 m_currLogicalTopOffset = colCount * m_colInfo->columnHeight() * m_direct
ion; | |
3040 update(); | |
3041 } | |
3042 | |
3043 void advance() | |
3044 { | |
3045 ASSERT(hasMore()); | |
3046 m_colIndex--; | |
3047 update(); | |
3048 } | |
3049 | |
3050 LayoutRect columnRect() const { return m_colRect; } | |
3051 bool hasMore() const { return m_colIndex >= 0; } | |
3052 | |
3053 void adjust(LayoutSize& offset) const | |
3054 { | |
3055 LayoutUnit currLogicalLeftOffset = (m_isHorizontal ? m_colRect.x() : m_c
olRect.y()) - m_logicalLeft; | |
3056 offset += m_isHorizontal ? LayoutSize(currLogicalLeftOffset, m_currLogic
alTopOffset) : LayoutSize(m_currLogicalTopOffset, currLogicalLeftOffset); | |
3057 if (m_colInfo->progressionAxis() == ColumnInfo::BlockAxis) { | |
3058 if (m_isHorizontal) | |
3059 offset.expand(0, m_colRect.y() - m_block.borderTop() - m_block.p
addingTop()); | |
3060 else | |
3061 offset.expand(m_colRect.x() - m_block.borderLeft() - m_block.pad
dingLeft(), 0); | |
3062 } | |
3063 } | |
3064 | |
3065 private: | |
3066 void update() | |
3067 { | |
3068 if (m_colIndex < 0) | |
3069 return; | |
3070 | |
3071 m_colRect = m_block.columnRectAt(const_cast<ColumnInfo*>(m_colInfo), m_c
olIndex); | |
3072 m_block.flipForWritingMode(m_colRect); | |
3073 m_currLogicalTopOffset -= (m_isHorizontal ? m_colRect.height() : m_colRe
ct.width()) * m_direction; | |
3074 } | |
3075 | |
3076 const RenderBlock& m_block; | |
3077 const ColumnInfo* const m_colInfo; | |
3078 const int m_direction; | |
3079 const bool m_isHorizontal; | |
3080 const LayoutUnit m_logicalLeft; | |
3081 int m_colIndex; | |
3082 LayoutUnit m_currLogicalTopOffset; | |
3083 LayoutRect m_colRect; | |
3084 }; | |
3085 | |
3086 bool RenderBlock::hitTestColumns(const HitTestRequest& request, HitTestResult& r
esult, const HitTestLocation& locationInContainer, const LayoutPoint& accumulate
dOffset, HitTestAction hitTestAction) | |
3087 { | |
3088 // We need to do multiple passes, breaking up our hit testing into strips. | |
3089 if (!hasColumns()) | |
3090 return false; | |
3091 | |
3092 for (ColumnRectIterator it(*this); it.hasMore(); it.advance()) { | |
3093 LayoutRect hitRect = locationInContainer.boundingBox(); | |
3094 LayoutRect colRect = it.columnRect(); | |
3095 colRect.moveBy(accumulatedOffset); | |
3096 if (locationInContainer.intersects(colRect)) { | |
3097 // The point is inside this column. | |
3098 // Adjust accumulatedOffset to change where we hit test. | |
3099 LayoutSize offset; | |
3100 it.adjust(offset); | |
3101 LayoutPoint finalLocation = accumulatedOffset + offset; | |
3102 if (!result.isRectBasedTest() || colRect.contains(hitRect)) | |
3103 return hitTestContents(request, result, locationInContainer, fin
alLocation, hitTestAction) || (hitTestAction == HitTestFloat && hitTestFloats(re
quest, result, locationInContainer, finalLocation)); | |
3104 | |
3105 hitTestContents(request, result, locationInContainer, finalLocation,
hitTestAction); | |
3106 } | |
3107 } | |
3108 | |
3109 return false; | |
3110 } | |
3111 | |
3112 void RenderBlock::adjustForColumnRect(LayoutSize& offset, const LayoutPoint& loc
ationInContainer) const | |
3113 { | |
3114 for (ColumnRectIterator it(*this); it.hasMore(); it.advance()) { | |
3115 LayoutRect colRect = it.columnRect(); | |
3116 if (colRect.contains(locationInContainer)) { | |
3117 it.adjust(offset); | |
3118 return; | |
3119 } | |
3120 } | |
3121 } | |
3122 | |
3123 bool RenderBlock::hitTestContents(const HitTestRequest& request, HitTestResult&
result, const HitTestLocation& locationInContainer, const LayoutPoint& accumulat
edOffset, HitTestAction hitTestAction) | 2459 bool RenderBlock::hitTestContents(const HitTestRequest& request, HitTestResult&
result, const HitTestLocation& locationInContainer, const LayoutPoint& accumulat
edOffset, HitTestAction hitTestAction) |
3124 { | 2460 { |
3125 if (isRenderRegion()) | 2461 if (isRenderRegion()) |
3126 return toRenderRegion(this)->hitTestFlowThreadContents(request, result,
locationInContainer, accumulatedOffset, hitTestAction); | 2462 return toRenderRegion(this)->hitTestFlowThreadContents(request, result,
locationInContainer, accumulatedOffset, hitTestAction); |
3127 | 2463 |
3128 if (childrenInline() && !isTable()) { | 2464 if (childrenInline() && !isTable()) { |
3129 // We have to hit-test our line boxes. | 2465 // We have to hit-test our line boxes. |
3130 if (m_lineBoxes.hitTest(this, request, result, locationInContainer, accu
mulatedOffset, hitTestAction)) | 2466 if (m_lineBoxes.hitTest(this, request, result, locationInContainer, accu
mulatedOffset, hitTestAction)) |
3131 return true; | 2467 return true; |
3132 } else { | 2468 } else { |
(...skipping 216 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3349 return RenderBox::positionForPoint(point); | 2685 return RenderBox::positionForPoint(point); |
3350 } | 2686 } |
3351 | 2687 |
3352 void RenderBlock::offsetForContents(LayoutPoint& offset) const | 2688 void RenderBlock::offsetForContents(LayoutPoint& offset) const |
3353 { | 2689 { |
3354 offset = flipForWritingMode(offset); | 2690 offset = flipForWritingMode(offset); |
3355 | 2691 |
3356 if (hasOverflowClip()) | 2692 if (hasOverflowClip()) |
3357 offset += scrolledContentOffset(); | 2693 offset += scrolledContentOffset(); |
3358 | 2694 |
3359 if (hasColumns()) | |
3360 adjustPointToColumnContents(offset); | |
3361 | |
3362 offset = flipForWritingMode(offset); | 2695 offset = flipForWritingMode(offset); |
3363 } | 2696 } |
3364 | 2697 |
3365 LayoutUnit RenderBlock::availableLogicalWidth() const | |
3366 { | |
3367 // If we have multiple columns, then the available logical width is reduced
to our column width. | |
3368 if (hasColumns()) | |
3369 return desiredColumnWidth(); | |
3370 return RenderBox::availableLogicalWidth(); | |
3371 } | |
3372 | |
3373 int RenderBlock::columnGap() const | 2698 int RenderBlock::columnGap() const |
3374 { | 2699 { |
3375 if (style()->hasNormalColumnGap()) | 2700 if (style()->hasNormalColumnGap()) |
3376 return style()->fontDescription().computedPixelSize(); // "1em" is recom
mended as the normal gap setting. Matches <p> margins. | 2701 return style()->fontDescription().computedPixelSize(); // "1em" is recom
mended as the normal gap setting. Matches <p> margins. |
3377 return static_cast<int>(style()->columnGap()); | 2702 return static_cast<int>(style()->columnGap()); |
3378 } | 2703 } |
3379 | 2704 |
3380 void RenderBlock::calcColumnWidth() | |
3381 { | |
3382 if (document().regionBasedColumnsEnabled()) | |
3383 return; | |
3384 | |
3385 // Calculate our column width and column count. | |
3386 // FIXME: Can overflow on fast/block/float/float-not-removed-from-next-sibli
ng4.html, see https://bugs.webkit.org/show_bug.cgi?id=68744 | |
3387 unsigned desiredColumnCount = 1; | |
3388 LayoutUnit desiredColumnWidth = contentLogicalWidth(); | |
3389 | |
3390 // For now, we don't support multi-column layouts when printing, since we ha
ve to do a lot of work for proper pagination. | |
3391 if (document().paginated() || (style()->hasAutoColumnCount() && style()->has
AutoColumnWidth()) || !style()->hasInlineColumnAxis()) { | |
3392 setDesiredColumnCountAndWidth(desiredColumnCount, desiredColumnWidth); | |
3393 return; | |
3394 } | |
3395 | |
3396 LayoutUnit availWidth = desiredColumnWidth; | |
3397 LayoutUnit colGap = columnGap(); | |
3398 LayoutUnit colWidth = max<LayoutUnit>(1, LayoutUnit(style()->columnWidth()))
; | |
3399 int colCount = max<int>(1, style()->columnCount()); | |
3400 | |
3401 if (style()->hasAutoColumnWidth() && !style()->hasAutoColumnCount()) { | |
3402 desiredColumnCount = colCount; | |
3403 desiredColumnWidth = max<LayoutUnit>(0, (availWidth - ((desiredColumnCou
nt - 1) * colGap)) / desiredColumnCount); | |
3404 } else if (!style()->hasAutoColumnWidth() && style()->hasAutoColumnCount())
{ | |
3405 desiredColumnCount = max<LayoutUnit>(1, (availWidth + colGap) / (colWidt
h + colGap)); | |
3406 desiredColumnWidth = ((availWidth + colGap) / desiredColumnCount) - colG
ap; | |
3407 } else { | |
3408 desiredColumnCount = max<LayoutUnit>(min<LayoutUnit>(colCount, (availWid
th + colGap) / (colWidth + colGap)), 1); | |
3409 desiredColumnWidth = ((availWidth + colGap) / desiredColumnCount) - colG
ap; | |
3410 } | |
3411 setDesiredColumnCountAndWidth(desiredColumnCount, desiredColumnWidth); | |
3412 } | |
3413 | |
3414 bool RenderBlock::requiresColumns(int desiredColumnCount) const | 2705 bool RenderBlock::requiresColumns(int desiredColumnCount) const |
3415 { | 2706 { |
3416 // If overflow-y is set to paged-x or paged-y on the body or html element, w
e'll handle the paginating | 2707 // If overflow-y is set to paged-x or paged-y on the body or html element, w
e'll handle the paginating |
3417 // in the RenderView instead. | 2708 // in the RenderView instead. |
3418 bool isPaginated = (style()->overflowY() == OPAGEDX || style()->overflowY()
== OPAGEDY) && !(isRoot() || isBody()); | 2709 bool isPaginated = (style()->overflowY() == OPAGEDX || style()->overflowY()
== OPAGEDY) && !(isRoot() || isBody()); |
3419 | 2710 |
3420 return firstChild() | 2711 return firstChild() |
3421 && (desiredColumnCount != 1 || !style()->hasAutoColumnWidth() || !style(
)->hasInlineColumnAxis() || isPaginated) | 2712 && (desiredColumnCount != 1 || !style()->hasAutoColumnWidth() || !style(
)->hasInlineColumnAxis() || isPaginated); |
3422 && !firstChild()->isAnonymousColumnsBlock() | |
3423 && !firstChild()->isAnonymousColumnSpanBlock(); | |
3424 } | |
3425 | |
3426 void RenderBlock::setDesiredColumnCountAndWidth(int count, LayoutUnit width) | |
3427 { | |
3428 bool destroyColumns = !requiresColumns(count); | |
3429 if (destroyColumns) { | |
3430 if (hasColumns()) { | |
3431 gColumnInfoMap->take(this); | |
3432 setHasColumns(false); | |
3433 } | |
3434 } else { | |
3435 ColumnInfo* info; | |
3436 if (hasColumns()) | |
3437 info = gColumnInfoMap->get(this); | |
3438 else { | |
3439 if (!gColumnInfoMap) | |
3440 gColumnInfoMap = new ColumnInfoMap; | |
3441 info = new ColumnInfo; | |
3442 gColumnInfoMap->add(this, adoptPtr(info)); | |
3443 setHasColumns(true); | |
3444 } | |
3445 info->setDesiredColumnCount(count); | |
3446 info->setDesiredColumnWidth(width); | |
3447 info->setProgressionAxis(style()->hasInlineColumnAxis() ? ColumnInfo::In
lineAxis : ColumnInfo::BlockAxis); | |
3448 info->setProgressionIsReversed(style()->columnProgression() == ReverseCo
lumnProgression); | |
3449 } | |
3450 } | |
3451 | |
3452 void RenderBlock::updateColumnInfoFromStyle(RenderStyle* style) | |
3453 { | |
3454 if (!hasColumns()) | |
3455 return; | |
3456 | |
3457 ColumnInfo* info = gColumnInfoMap->get(this); | |
3458 | |
3459 bool needsLayout = false; | |
3460 ColumnInfo::Axis oldAxis = info->progressionAxis(); | |
3461 ColumnInfo::Axis newAxis = style->hasInlineColumnAxis() ? ColumnInfo::Inline
Axis : ColumnInfo::BlockAxis; | |
3462 if (oldAxis != newAxis) { | |
3463 info->setProgressionAxis(newAxis); | |
3464 needsLayout = true; | |
3465 } | |
3466 | |
3467 bool oldProgressionIsReversed = info->progressionIsReversed(); | |
3468 bool newProgressionIsReversed = style->columnProgression() == ReverseColumnP
rogression; | |
3469 if (oldProgressionIsReversed != newProgressionIsReversed) { | |
3470 info->setProgressionIsReversed(newProgressionIsReversed); | |
3471 needsLayout = true; | |
3472 } | |
3473 | |
3474 if (needsLayout) | |
3475 setNeedsLayoutAndPrefWidthsRecalc(); | |
3476 } | |
3477 | |
3478 LayoutUnit RenderBlock::desiredColumnWidth() const | |
3479 { | |
3480 if (!hasColumns()) | |
3481 return contentLogicalWidth(); | |
3482 return gColumnInfoMap->get(this)->desiredColumnWidth(); | |
3483 } | |
3484 | |
3485 ColumnInfo* RenderBlock::columnInfo() const | |
3486 { | |
3487 if (!hasColumns()) | |
3488 return 0; | |
3489 return gColumnInfoMap->get(this); | |
3490 } | |
3491 | |
3492 unsigned RenderBlock::columnCount(ColumnInfo* colInfo) const | |
3493 { | |
3494 ASSERT(hasColumns()); | |
3495 ASSERT(gColumnInfoMap->get(this) == colInfo); | |
3496 return colInfo->columnCount(); | |
3497 } | |
3498 | |
3499 LayoutRect RenderBlock::columnRectAt(ColumnInfo* colInfo, unsigned index) const | |
3500 { | |
3501 ASSERT(hasColumns() && gColumnInfoMap->get(this) == colInfo); | |
3502 | |
3503 // Compute the appropriate rect based off our information. | |
3504 LayoutUnit colLogicalWidth = colInfo->desiredColumnWidth(); | |
3505 LayoutUnit colLogicalHeight = colInfo->columnHeight(); | |
3506 LayoutUnit colLogicalTop = borderBefore() + paddingBefore(); | |
3507 LayoutUnit colLogicalLeft = logicalLeftOffsetForContent(); | |
3508 LayoutUnit colGap = columnGap(); | |
3509 if (colInfo->progressionAxis() == ColumnInfo::InlineAxis) { | |
3510 if (style()->isLeftToRightDirection() ^ colInfo->progressionIsReversed()
) | |
3511 colLogicalLeft += index * (colLogicalWidth + colGap); | |
3512 else | |
3513 colLogicalLeft += contentLogicalWidth() - colLogicalWidth - index *
(colLogicalWidth + colGap); | |
3514 } else { | |
3515 if (!colInfo->progressionIsReversed()) | |
3516 colLogicalTop += index * (colLogicalHeight + colGap); | |
3517 else | |
3518 colLogicalTop += contentLogicalHeight() - colLogicalHeight - index *
(colLogicalHeight + colGap); | |
3519 } | |
3520 | |
3521 if (isHorizontalWritingMode()) | |
3522 return LayoutRect(colLogicalLeft, colLogicalTop, colLogicalWidth, colLog
icalHeight); | |
3523 return LayoutRect(colLogicalTop, colLogicalLeft, colLogicalHeight, colLogica
lWidth); | |
3524 } | 2713 } |
3525 | 2714 |
3526 bool RenderBlock::relayoutToAvoidWidows(LayoutStateMaintainer& statePusher) | 2715 bool RenderBlock::relayoutToAvoidWidows(LayoutStateMaintainer& statePusher) |
3527 { | 2716 { |
3528 if (!shouldBreakAtLineToAvoidWidow()) | 2717 if (!shouldBreakAtLineToAvoidWidow()) |
3529 return false; | 2718 return false; |
3530 | 2719 |
3531 statePusher.pop(); | 2720 statePusher.pop(); |
3532 setEverHadLayout(true); | 2721 setEverHadLayout(true); |
3533 layoutBlock(false); | 2722 layoutBlock(false); |
3534 return true; | 2723 return true; |
3535 } | 2724 } |
3536 | 2725 |
3537 void RenderBlock::adjustPointToColumnContents(LayoutPoint& point) const | |
3538 { | |
3539 // Just bail if we have no columns. | |
3540 if (!hasColumns()) | |
3541 return; | |
3542 | |
3543 ColumnInfo* colInfo = columnInfo(); | |
3544 if (!columnCount(colInfo)) | |
3545 return; | |
3546 | |
3547 // Determine which columns we intersect. | |
3548 LayoutUnit colGap = columnGap(); | |
3549 LayoutUnit halfColGap = colGap / 2; | |
3550 LayoutPoint columnPoint(columnRectAt(colInfo, 0).location()); | |
3551 LayoutUnit logicalOffset = 0; | |
3552 for (unsigned i = 0; i < colInfo->columnCount(); i++) { | |
3553 // Add in half the column gap to the left and right of the rect. | |
3554 LayoutRect colRect = columnRectAt(colInfo, i); | |
3555 flipForWritingMode(colRect); | |
3556 if (isHorizontalWritingMode() == (colInfo->progressionAxis() == ColumnIn
fo::InlineAxis)) { | |
3557 LayoutRect gapAndColumnRect(colRect.x() - halfColGap, colRect.y(), c
olRect.width() + colGap, colRect.height()); | |
3558 if (point.x() >= gapAndColumnRect.x() && point.x() < gapAndColumnRec
t.maxX()) { | |
3559 if (colInfo->progressionAxis() == ColumnInfo::InlineAxis) { | |
3560 // FIXME: The clamping that follows is not completely right
for right-to-left | |
3561 // content. | |
3562 // Clamp everything above the column to its top left. | |
3563 if (point.y() < gapAndColumnRect.y()) | |
3564 point = gapAndColumnRect.location(); | |
3565 // Clamp everything below the column to the next column's to
p left. If there is | |
3566 // no next column, this still maps to just after this column
. | |
3567 else if (point.y() >= gapAndColumnRect.maxY()) { | |
3568 point = gapAndColumnRect.location(); | |
3569 point.move(0, gapAndColumnRect.height()); | |
3570 } | |
3571 } else { | |
3572 if (point.x() < colRect.x()) | |
3573 point.setX(colRect.x()); | |
3574 else if (point.x() >= colRect.maxX()) | |
3575 point.setX(colRect.maxX() - 1); | |
3576 } | |
3577 | |
3578 // We're inside the column. Translate the x and y into our colu
mn coordinate space. | |
3579 if (colInfo->progressionAxis() == ColumnInfo::InlineAxis) | |
3580 point.move(columnPoint.x() - colRect.x(), (!style()->isFlipp
edBlocksWritingMode() ? logicalOffset : -logicalOffset)); | |
3581 else | |
3582 point.move((!style()->isFlippedBlocksWritingMode() ? logical
Offset : -logicalOffset) - colRect.x() + borderLeft() + paddingLeft(), 0); | |
3583 return; | |
3584 } | |
3585 | |
3586 // Move to the next position. | |
3587 logicalOffset += colInfo->progressionAxis() == ColumnInfo::InlineAxi
s ? colRect.height() : colRect.width(); | |
3588 } else { | |
3589 LayoutRect gapAndColumnRect(colRect.x(), colRect.y() - halfColGap, c
olRect.width(), colRect.height() + colGap); | |
3590 if (point.y() >= gapAndColumnRect.y() && point.y() < gapAndColumnRec
t.maxY()) { | |
3591 if (colInfo->progressionAxis() == ColumnInfo::InlineAxis) { | |
3592 // FIXME: The clamping that follows is not completely right
for right-to-left | |
3593 // content. | |
3594 // Clamp everything above the column to its top left. | |
3595 if (point.x() < gapAndColumnRect.x()) | |
3596 point = gapAndColumnRect.location(); | |
3597 // Clamp everything below the column to the next column's to
p left. If there is | |
3598 // no next column, this still maps to just after this column
. | |
3599 else if (point.x() >= gapAndColumnRect.maxX()) { | |
3600 point = gapAndColumnRect.location(); | |
3601 point.move(gapAndColumnRect.width(), 0); | |
3602 } | |
3603 } else { | |
3604 if (point.y() < colRect.y()) | |
3605 point.setY(colRect.y()); | |
3606 else if (point.y() >= colRect.maxY()) | |
3607 point.setY(colRect.maxY() - 1); | |
3608 } | |
3609 | |
3610 // We're inside the column. Translate the x and y into our colu
mn coordinate space. | |
3611 if (colInfo->progressionAxis() == ColumnInfo::InlineAxis) | |
3612 point.move((!style()->isFlippedBlocksWritingMode() ? logical
Offset : -logicalOffset), columnPoint.y() - colRect.y()); | |
3613 else | |
3614 point.move(0, (!style()->isFlippedBlocksWritingMode() ? logi
calOffset : -logicalOffset) - colRect.y() + borderTop() + paddingTop()); | |
3615 return; | |
3616 } | |
3617 | |
3618 // Move to the next position. | |
3619 logicalOffset += colInfo->progressionAxis() == ColumnInfo::InlineAxi
s ? colRect.width() : colRect.height(); | |
3620 } | |
3621 } | |
3622 } | |
3623 | |
3624 void RenderBlock::adjustRectForColumns(LayoutRect& r) const | |
3625 { | |
3626 // Just bail if we have no columns. | |
3627 if (!hasColumns()) | |
3628 return; | |
3629 | |
3630 ColumnInfo* colInfo = columnInfo(); | |
3631 | |
3632 // Determine which columns we intersect. | |
3633 unsigned colCount = columnCount(colInfo); | |
3634 if (!colCount) | |
3635 return; | |
3636 | |
3637 // Begin with a result rect that is empty. | |
3638 LayoutRect result; | |
3639 | |
3640 bool isHorizontal = isHorizontalWritingMode(); | |
3641 LayoutUnit beforeBorderPadding = borderBefore() + paddingBefore(); | |
3642 LayoutUnit colHeight = colInfo->columnHeight(); | |
3643 if (!colHeight) | |
3644 return; | |
3645 | |
3646 LayoutUnit startOffset = max(isHorizontal ? r.y() : r.x(), beforeBorderPaddi
ng); | |
3647 LayoutUnit endOffset = max(min<LayoutUnit>(isHorizontal ? r.maxY() : r.maxX(
), beforeBorderPadding + colCount * colHeight), beforeBorderPadding); | |
3648 | |
3649 // FIXME: Can overflow on fast/block/float/float-not-removed-from-next-sibli
ng4.html, see https://bugs.webkit.org/show_bug.cgi?id=68744 | |
3650 unsigned startColumn = (startOffset - beforeBorderPadding) / colHeight; | |
3651 unsigned endColumn = (endOffset - beforeBorderPadding) / colHeight; | |
3652 | |
3653 if (startColumn == endColumn) { | |
3654 // The rect is fully contained within one column. Adjust for our offsets | |
3655 // and repaint only that portion. | |
3656 LayoutUnit logicalLeftOffset = logicalLeftOffsetForContent(); | |
3657 LayoutRect colRect = columnRectAt(colInfo, startColumn); | |
3658 LayoutRect repaintRect = r; | |
3659 | |
3660 if (colInfo->progressionAxis() == ColumnInfo::InlineAxis) { | |
3661 if (isHorizontal) | |
3662 repaintRect.move(colRect.x() - logicalLeftOffset, - static_cast<
int>(startColumn) * colHeight); | |
3663 else | |
3664 repaintRect.move(- static_cast<int>(startColumn) * colHeight, co
lRect.y() - logicalLeftOffset); | |
3665 } else { | |
3666 if (isHorizontal) | |
3667 repaintRect.move(0, colRect.y() - startColumn * colHeight - befo
reBorderPadding); | |
3668 else | |
3669 repaintRect.move(colRect.x() - startColumn * colHeight - beforeB
orderPadding, 0); | |
3670 } | |
3671 repaintRect.intersect(colRect); | |
3672 result.unite(repaintRect); | |
3673 } else { | |
3674 // We span multiple columns. We can just unite the start and end column
to get the final | |
3675 // repaint rect. | |
3676 result.unite(columnRectAt(colInfo, startColumn)); | |
3677 result.unite(columnRectAt(colInfo, endColumn)); | |
3678 } | |
3679 | |
3680 r = result; | |
3681 } | |
3682 | |
3683 LayoutPoint RenderBlock::flipForWritingModeIncludingColumns(const LayoutPoint& p
oint) const | |
3684 { | |
3685 ASSERT(hasColumns()); | |
3686 if (!hasColumns() || !style()->isFlippedBlocksWritingMode()) | |
3687 return point; | |
3688 ColumnInfo* colInfo = columnInfo(); | |
3689 LayoutUnit columnLogicalHeight = colInfo->columnHeight(); | |
3690 LayoutUnit expandedLogicalHeight = borderBefore() + paddingBefore() + column
Count(colInfo) * columnLogicalHeight + borderAfter() + paddingAfter() + scrollba
rLogicalHeight(); | |
3691 if (isHorizontalWritingMode()) | |
3692 return LayoutPoint(point.x(), expandedLogicalHeight - point.y()); | |
3693 return LayoutPoint(expandedLogicalHeight - point.x(), point.y()); | |
3694 } | |
3695 | |
3696 void RenderBlock::adjustStartEdgeForWritingModeIncludingColumns(LayoutRect& rect
) const | |
3697 { | |
3698 ASSERT(hasColumns()); | |
3699 if (!hasColumns() || !style()->isFlippedBlocksWritingMode()) | |
3700 return; | |
3701 | |
3702 ColumnInfo* colInfo = columnInfo(); | |
3703 LayoutUnit columnLogicalHeight = colInfo->columnHeight(); | |
3704 LayoutUnit expandedLogicalHeight = borderBefore() + paddingBefore() + column
Count(colInfo) * columnLogicalHeight + borderAfter() + paddingAfter() + scrollba
rLogicalHeight(); | |
3705 | |
3706 if (isHorizontalWritingMode()) | |
3707 rect.setY(expandedLogicalHeight - rect.maxY()); | |
3708 else | |
3709 rect.setX(expandedLogicalHeight - rect.maxX()); | |
3710 } | |
3711 | |
3712 void RenderBlock::adjustForColumns(LayoutSize& offset, const LayoutPoint& point)
const | |
3713 { | |
3714 if (!hasColumns()) | |
3715 return; | |
3716 | |
3717 ColumnInfo* colInfo = columnInfo(); | |
3718 | |
3719 LayoutUnit logicalLeft = logicalLeftOffsetForContent(); | |
3720 unsigned colCount = columnCount(colInfo); | |
3721 LayoutUnit colLogicalWidth = colInfo->desiredColumnWidth(); | |
3722 LayoutUnit colLogicalHeight = colInfo->columnHeight(); | |
3723 | |
3724 for (unsigned i = 0; i < colCount; ++i) { | |
3725 // Compute the edges for a given column in the block progression directi
on. | |
3726 LayoutRect sliceRect = LayoutRect(logicalLeft, borderBefore() + paddingB
efore() + i * colLogicalHeight, colLogicalWidth, colLogicalHeight); | |
3727 if (!isHorizontalWritingMode()) | |
3728 sliceRect = sliceRect.transposedRect(); | |
3729 | |
3730 LayoutUnit logicalOffset = i * colLogicalHeight; | |
3731 | |
3732 // Now we're in the same coordinate space as the point. See if it is in
side the rectangle. | |
3733 if (isHorizontalWritingMode()) { | |
3734 if (point.y() >= sliceRect.y() && point.y() < sliceRect.maxY()) { | |
3735 if (colInfo->progressionAxis() == ColumnInfo::InlineAxis) | |
3736 offset.expand(columnRectAt(colInfo, i).x() - logicalLeft, -l
ogicalOffset); | |
3737 else | |
3738 offset.expand(0, columnRectAt(colInfo, i).y() - logicalOffse
t - borderBefore() - paddingBefore()); | |
3739 return; | |
3740 } | |
3741 } else { | |
3742 if (point.x() >= sliceRect.x() && point.x() < sliceRect.maxX()) { | |
3743 if (colInfo->progressionAxis() == ColumnInfo::InlineAxis) | |
3744 offset.expand(-logicalOffset, columnRectAt(colInfo, i).y() -
logicalLeft); | |
3745 else | |
3746 offset.expand(columnRectAt(colInfo, i).x() - logicalOffset -
borderBefore() - paddingBefore(), 0); | |
3747 return; | |
3748 } | |
3749 } | |
3750 } | |
3751 } | |
3752 | |
3753 void RenderBlock::computeIntrinsicLogicalWidths(LayoutUnit& minLogicalWidth, Lay
outUnit& maxLogicalWidth) const | 2726 void RenderBlock::computeIntrinsicLogicalWidths(LayoutUnit& minLogicalWidth, Lay
outUnit& maxLogicalWidth) const |
3754 { | 2727 { |
3755 if (childrenInline()) { | 2728 if (childrenInline()) { |
3756 // FIXME: Remove this const_cast. | 2729 // FIXME: Remove this const_cast. |
3757 const_cast<RenderBlock*>(this)->computeInlinePreferredLogicalWidths(minL
ogicalWidth, maxLogicalWidth); | 2730 const_cast<RenderBlock*>(this)->computeInlinePreferredLogicalWidths(minL
ogicalWidth, maxLogicalWidth); |
3758 } else | 2731 } else |
3759 computeBlockPreferredLogicalWidths(minLogicalWidth, maxLogicalWidth); | 2732 computeBlockPreferredLogicalWidths(minLogicalWidth, maxLogicalWidth); |
3760 | 2733 |
3761 maxLogicalWidth = max(minLogicalWidth, maxLogicalWidth); | 2734 maxLogicalWidth = max(minLogicalWidth, maxLogicalWidth); |
3762 | 2735 |
(...skipping 1427 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5190 LayoutRect rect(layerOffset.x() + curr->x(), layerOffset.y() + top,
curr->width(), bottom - top); | 4163 LayoutRect rect(layerOffset.x() + curr->x(), layerOffset.y() + top,
curr->width(), bottom - top); |
5191 // It's common for this rect to be entirely contained in our box, so
exclude that simple case. | 4164 // It's common for this rect to be entirely contained in our box, so
exclude that simple case. |
5192 if (!rect.isEmpty() && (rects.isEmpty() || !rects[0].contains(rect))
) | 4165 if (!rect.isEmpty() && (rects.isEmpty() || !rects[0].contains(rect))
) |
5193 rects.append(rect); | 4166 rects.append(rect); |
5194 } | 4167 } |
5195 } | 4168 } |
5196 } | 4169 } |
5197 | 4170 |
5198 RenderBox* RenderBlock::createAnonymousBoxWithSameTypeAs(const RenderObject* par
ent) const | 4171 RenderBox* RenderBlock::createAnonymousBoxWithSameTypeAs(const RenderObject* par
ent) const |
5199 { | 4172 { |
5200 if (isAnonymousColumnsBlock()) | |
5201 return createAnonymousColumnsWithParentRenderer(parent); | |
5202 if (isAnonymousColumnSpanBlock()) | |
5203 return createAnonymousColumnSpanWithParentRenderer(parent); | |
5204 return createAnonymousWithParentRendererAndDisplay(parent, style()->display(
)); | 4173 return createAnonymousWithParentRendererAndDisplay(parent, style()->display(
)); |
5205 } | 4174 } |
5206 | 4175 |
5207 bool RenderBlock::hasNextPage(LayoutUnit logicalOffset, PageBoundaryRule pageBou
ndaryRule) const | 4176 bool RenderBlock::hasNextPage(LayoutUnit logicalOffset, PageBoundaryRule pageBou
ndaryRule) const |
5208 { | 4177 { |
5209 ASSERT(view()->layoutState() && view()->layoutState()->isPaginated()); | 4178 ASSERT(view()->layoutState() && view()->layoutState()->isPaginated()); |
5210 | 4179 |
5211 RenderFlowThread* flowThread = flowThreadContainingBlock(); | 4180 RenderFlowThread* flowThread = flowThreadContainingBlock(); |
5212 if (!flowThread) | 4181 if (!flowThread) |
5213 return true; // Printing and multi-column both make new pages to accommo
date content. | 4182 return true; // Printing and multi-column both make new pages to accommo
date content. |
(...skipping 15 matching lines...) Expand all Loading... |
5229 if (!pageLogicalHeight) | 4198 if (!pageLogicalHeight) |
5230 return logicalOffset; | 4199 return logicalOffset; |
5231 | 4200 |
5232 // The logicalOffset is in our coordinate space. We can add in our pushed o
ffset. | 4201 // The logicalOffset is in our coordinate space. We can add in our pushed o
ffset. |
5233 LayoutUnit remainingLogicalHeight = pageRemainingLogicalHeightForOffset(logi
calOffset); | 4202 LayoutUnit remainingLogicalHeight = pageRemainingLogicalHeightForOffset(logi
calOffset); |
5234 if (pageBoundaryRule == ExcludePageBoundary) | 4203 if (pageBoundaryRule == ExcludePageBoundary) |
5235 return logicalOffset + (remainingLogicalHeight ? remainingLogicalHeight
: pageLogicalHeight); | 4204 return logicalOffset + (remainingLogicalHeight ? remainingLogicalHeight
: pageLogicalHeight); |
5236 return logicalOffset + remainingLogicalHeight; | 4205 return logicalOffset + remainingLogicalHeight; |
5237 } | 4206 } |
5238 | 4207 |
5239 ColumnInfo::PaginationUnit RenderBlock::paginationUnit() const | |
5240 { | |
5241 return ColumnInfo::Column; | |
5242 } | |
5243 | |
5244 LayoutUnit RenderBlock::pageLogicalTopForOffset(LayoutUnit offset) const | 4208 LayoutUnit RenderBlock::pageLogicalTopForOffset(LayoutUnit offset) const |
5245 { | 4209 { |
5246 RenderView* renderView = view(); | 4210 RenderView* renderView = view(); |
5247 LayoutUnit firstPageLogicalTop = isHorizontalWritingMode() ? renderView->lay
outState()->m_pageOffset.height() : renderView->layoutState()->m_pageOffset.widt
h(); | 4211 LayoutUnit firstPageLogicalTop = isHorizontalWritingMode() ? renderView->lay
outState()->m_pageOffset.height() : renderView->layoutState()->m_pageOffset.widt
h(); |
5248 LayoutUnit blockLogicalTop = isHorizontalWritingMode() ? renderView->layoutS
tate()->m_layoutOffset.height() : renderView->layoutState()->m_layoutOffset.widt
h(); | 4212 LayoutUnit blockLogicalTop = isHorizontalWritingMode() ? renderView->layoutS
tate()->m_layoutOffset.height() : renderView->layoutState()->m_layoutOffset.widt
h(); |
5249 | 4213 |
5250 LayoutUnit cumulativeOffset = offset + blockLogicalTop; | 4214 LayoutUnit cumulativeOffset = offset + blockLogicalTop; |
5251 RenderFlowThread* flowThread = flowThreadContainingBlock(); | 4215 RenderFlowThread* flowThread = flowThreadContainingBlock(); |
5252 if (!flowThread) { | 4216 if (!flowThread) { |
5253 LayoutUnit pageLogicalHeight = renderView->layoutState()->pageLogicalHei
ght(); | 4217 LayoutUnit pageLogicalHeight = renderView->layoutState()->pageLogicalHei
ght(); |
(...skipping 28 matching lines...) Expand all Loading... |
5282 remainingHeight = intMod(remainingHeight, pageLogicalHeight); | 4246 remainingHeight = intMod(remainingHeight, pageLogicalHeight); |
5283 } | 4247 } |
5284 return remainingHeight; | 4248 return remainingHeight; |
5285 } | 4249 } |
5286 | 4250 |
5287 return flowThread->pageRemainingLogicalHeightForOffset(offset, pageBoundaryR
ule); | 4251 return flowThread->pageRemainingLogicalHeightForOffset(offset, pageBoundaryR
ule); |
5288 } | 4252 } |
5289 | 4253 |
5290 LayoutUnit RenderBlock::adjustForUnsplittableChild(RenderBox* child, LayoutUnit
logicalOffset, bool includeMargins) | 4254 LayoutUnit RenderBlock::adjustForUnsplittableChild(RenderBox* child, LayoutUnit
logicalOffset, bool includeMargins) |
5291 { | 4255 { |
5292 bool checkColumnBreaks = view()->layoutState()->isPaginatingColumns(); | 4256 bool checkPageBreaks = view()->layoutState()->m_pageLogicalHeight; |
5293 bool checkPageBreaks = !checkColumnBreaks && view()->layoutState()->m_pageLo
gicalHeight; | |
5294 RenderFlowThread* flowThread = flowThreadContainingBlock(); | 4257 RenderFlowThread* flowThread = flowThreadContainingBlock(); |
5295 bool checkRegionBreaks = flowThread && flowThread->isRenderNamedFlowThread()
; | 4258 bool checkRegionBreaks = flowThread && flowThread->isRenderNamedFlowThread()
; |
5296 bool isUnsplittable = child->isUnsplittableForPagination() || (checkColumnBr
eaks && child->style()->columnBreakInside() == PBAVOID) | 4259 bool isUnsplittable = child->isUnsplittableForPagination() |
5297 || (checkPageBreaks && child->style()->pageBreakInside() == PBAVOID) | 4260 || (checkPageBreaks && child->style()->pageBreakInside() == PBAVOID) |
5298 || (checkRegionBreaks && child->style()->regionBreakInside() == PBAVOID)
; | 4261 || (checkRegionBreaks && child->style()->regionBreakInside() == PBAVOID)
; |
5299 if (!isUnsplittable) | 4262 if (!isUnsplittable) |
5300 return logicalOffset; | 4263 return logicalOffset; |
5301 LayoutUnit childLogicalHeight = logicalHeightForChild(child) + (includeMargi
ns ? marginBeforeForChild(child) + marginAfterForChild(child) : LayoutUnit()); | 4264 LayoutUnit childLogicalHeight = logicalHeightForChild(child) + (includeMargi
ns ? marginBeforeForChild(child) + marginAfterForChild(child) : LayoutUnit()); |
5302 LayoutUnit pageLogicalHeight = pageLogicalHeightForOffset(logicalOffset); | 4265 LayoutUnit pageLogicalHeight = pageLogicalHeightForOffset(logicalOffset); |
5303 bool hasUniformPageLogicalHeight = !flowThread || flowThread->regionsHaveUni
formLogicalHeight(); | 4266 bool hasUniformPageLogicalHeight = !flowThread || flowThread->regionsHaveUni
formLogicalHeight(); |
5304 updateMinimumPageHeight(logicalOffset, childLogicalHeight); | 4267 updateMinimumPageHeight(logicalOffset, childLogicalHeight); |
5305 if (!pageLogicalHeight || (hasUniformPageLogicalHeight && childLogicalHeight
> pageLogicalHeight) | 4268 if (!pageLogicalHeight || (hasUniformPageLogicalHeight && childLogicalHeight
> pageLogicalHeight) |
5306 || !hasNextPage(logicalOffset)) | 4269 || !hasNextPage(logicalOffset)) |
(...skipping 25 matching lines...) Expand all Loading... |
5332 void RenderBlock::setPageBreak(LayoutUnit offset, LayoutUnit spaceShortage) | 4295 void RenderBlock::setPageBreak(LayoutUnit offset, LayoutUnit spaceShortage) |
5333 { | 4296 { |
5334 if (RenderFlowThread* flowThread = flowThreadContainingBlock()) | 4297 if (RenderFlowThread* flowThread = flowThreadContainingBlock()) |
5335 flowThread->setPageBreak(offsetFromLogicalTopOfFirstPage() + offset, spa
ceShortage); | 4298 flowThread->setPageBreak(offsetFromLogicalTopOfFirstPage() + offset, spa
ceShortage); |
5336 } | 4299 } |
5337 | 4300 |
5338 void RenderBlock::updateMinimumPageHeight(LayoutUnit offset, LayoutUnit minHeigh
t) | 4301 void RenderBlock::updateMinimumPageHeight(LayoutUnit offset, LayoutUnit minHeigh
t) |
5339 { | 4302 { |
5340 if (RenderFlowThread* flowThread = flowThreadContainingBlock()) | 4303 if (RenderFlowThread* flowThread = flowThreadContainingBlock()) |
5341 flowThread->updateMinimumPageHeight(offsetFromLogicalTopOfFirstPage() +
offset, minHeight); | 4304 flowThread->updateMinimumPageHeight(offsetFromLogicalTopOfFirstPage() +
offset, minHeight); |
5342 else if (ColumnInfo* colInfo = view()->layoutState()->m_columnInfo) | |
5343 colInfo->updateMinimumColumnHeight(minHeight); | |
5344 } | 4305 } |
5345 | 4306 |
5346 static inline LayoutUnit calculateMinimumPageHeight(RenderStyle* renderStyle, Ro
otInlineBox* lastLine, LayoutUnit lineTop, LayoutUnit lineBottom) | 4307 static inline LayoutUnit calculateMinimumPageHeight(RenderStyle* renderStyle, Ro
otInlineBox* lastLine, LayoutUnit lineTop, LayoutUnit lineBottom) |
5347 { | 4308 { |
5348 // We may require a certain minimum number of lines per page in order to sat
isfy | 4309 // We may require a certain minimum number of lines per page in order to sat
isfy |
5349 // orphans and widows, and that may affect the minimum page height. | 4310 // orphans and widows, and that may affect the minimum page height. |
5350 unsigned lineCount = max<unsigned>(renderStyle->hasAutoOrphans() ? 1 : rende
rStyle->orphans(), renderStyle->hasAutoWidows() ? 1 : renderStyle->widows()); | 4311 unsigned lineCount = max<unsigned>(renderStyle->hasAutoOrphans() ? 1 : rende
rStyle->orphans(), renderStyle->hasAutoWidows() ? 1 : renderStyle->widows()); |
5351 if (lineCount > 1) { | 4312 if (lineCount > 1) { |
5352 RootInlineBox* line = lastLine; | 4313 RootInlineBox* line = lastLine; |
5353 for (unsigned i = 1; i < lineCount && line->prevRootBox(); i++) | 4314 for (unsigned i = 1; i < lineCount && line->prevRootBox(); i++) |
(...skipping 240 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5594 | 4555 |
5595 const char* RenderBlock::renderName() const | 4556 const char* RenderBlock::renderName() const |
5596 { | 4557 { |
5597 if (isBody()) | 4558 if (isBody()) |
5598 return "RenderBody"; // FIXME: Temporary hack until we know that the reg
ression tests pass. | 4559 return "RenderBody"; // FIXME: Temporary hack until we know that the reg
ression tests pass. |
5599 | 4560 |
5600 if (isFloating()) | 4561 if (isFloating()) |
5601 return "RenderBlock (floating)"; | 4562 return "RenderBlock (floating)"; |
5602 if (isOutOfFlowPositioned()) | 4563 if (isOutOfFlowPositioned()) |
5603 return "RenderBlock (positioned)"; | 4564 return "RenderBlock (positioned)"; |
5604 if (isAnonymousColumnsBlock()) | |
5605 return "RenderBlock (anonymous multi-column)"; | |
5606 if (isAnonymousColumnSpanBlock()) | |
5607 return "RenderBlock (anonymous multi-column span)"; | |
5608 if (isAnonymousBlock()) | 4565 if (isAnonymousBlock()) |
5609 return "RenderBlock (anonymous)"; | 4566 return "RenderBlock (anonymous)"; |
5610 // FIXME: Temporary hack while the new generated content system is being imp
lemented. | 4567 // FIXME: Temporary hack while the new generated content system is being imp
lemented. |
5611 if (isPseudoElement()) | 4568 if (isPseudoElement()) |
5612 return "RenderBlock (generated)"; | 4569 return "RenderBlock (generated)"; |
5613 if (isAnonymous()) | 4570 if (isAnonymous()) |
5614 return "RenderBlock (generated)"; | 4571 return "RenderBlock (generated)"; |
5615 if (isRelPositioned()) | 4572 if (isRelPositioned()) |
5616 return "RenderBlock (relative positioned)"; | 4573 return "RenderBlock (relative positioned)"; |
5617 if (isStickyPositioned()) | 4574 if (isStickyPositioned()) |
(...skipping 16 matching lines...) Expand all Loading... |
5634 } else { | 4591 } else { |
5635 newBox = RenderBlockFlow::createAnonymous(&parent->document()); | 4592 newBox = RenderBlockFlow::createAnonymous(&parent->document()); |
5636 newDisplay = BLOCK; | 4593 newDisplay = BLOCK; |
5637 } | 4594 } |
5638 | 4595 |
5639 RefPtr<RenderStyle> newStyle = RenderStyle::createAnonymousStyleWithDisplay(
parent->style(), newDisplay); | 4596 RefPtr<RenderStyle> newStyle = RenderStyle::createAnonymousStyleWithDisplay(
parent->style(), newDisplay); |
5640 newBox->setStyle(newStyle.release()); | 4597 newBox->setStyle(newStyle.release()); |
5641 return newBox; | 4598 return newBox; |
5642 } | 4599 } |
5643 | 4600 |
5644 RenderBlockFlow* RenderBlock::createAnonymousColumnsWithParentRenderer(const Ren
derObject* parent) | |
5645 { | |
5646 RefPtr<RenderStyle> newStyle = RenderStyle::createAnonymousStyleWithDisplay(
parent->style(), BLOCK); | |
5647 newStyle->inheritColumnPropertiesFrom(parent->style()); | |
5648 | |
5649 RenderBlockFlow* newBox = RenderBlockFlow::createAnonymous(&parent->document
()); | |
5650 newBox->setStyle(newStyle.release()); | |
5651 return newBox; | |
5652 } | |
5653 | |
5654 RenderBlockFlow* RenderBlock::createAnonymousColumnSpanWithParentRenderer(const
RenderObject* parent) | |
5655 { | |
5656 RefPtr<RenderStyle> newStyle = RenderStyle::createAnonymousStyleWithDisplay(
parent->style(), BLOCK); | |
5657 newStyle->setColumnSpan(ColumnSpanAll); | |
5658 | |
5659 RenderBlockFlow* newBox = RenderBlockFlow::createAnonymous(&parent->document
()); | |
5660 newBox->setStyle(newStyle.release()); | |
5661 return newBox; | |
5662 } | |
5663 | |
5664 #ifndef NDEBUG | 4601 #ifndef NDEBUG |
5665 void RenderBlock::checkPositionedObjectsNeedLayout() | 4602 void RenderBlock::checkPositionedObjectsNeedLayout() |
5666 { | 4603 { |
5667 if (!gPositionedDescendantsMap) | 4604 if (!gPositionedDescendantsMap) |
5668 return; | 4605 return; |
5669 | 4606 |
5670 if (TrackedRendererListHashSet* positionedDescendantSet = positionedObjects(
)) { | 4607 if (TrackedRendererListHashSet* positionedDescendantSet = positionedObjects(
)) { |
5671 TrackedRendererListHashSet::const_iterator end = positionedDescendantSet
->end(); | 4608 TrackedRendererListHashSet::const_iterator end = positionedDescendantSet
->end(); |
5672 for (TrackedRendererListHashSet::const_iterator it = positionedDescendan
tSet->begin(); it != end; ++it) { | 4609 for (TrackedRendererListHashSet::const_iterator it = positionedDescendan
tSet->begin(); it != end; ++it) { |
5673 RenderBox* currBox = *it; | 4610 RenderBox* currBox = *it; |
5674 ASSERT(!currBox->needsLayout()); | 4611 ASSERT(!currBox->needsLayout()); |
5675 } | 4612 } |
5676 } | 4613 } |
5677 } | 4614 } |
5678 | 4615 |
5679 void RenderBlock::showLineTreeAndMark(const InlineBox* markedBox1, const char* m
arkedLabel1, const InlineBox* markedBox2, const char* markedLabel2, const Render
Object* obj) const | 4616 void RenderBlock::showLineTreeAndMark(const InlineBox* markedBox1, const char* m
arkedLabel1, const InlineBox* markedBox2, const char* markedLabel2, const Render
Object* obj) const |
5680 { | 4617 { |
5681 showRenderObject(); | 4618 showRenderObject(); |
5682 for (const RootInlineBox* root = firstRootBox(); root; root = root->nextRoot
Box()) | 4619 for (const RootInlineBox* root = firstRootBox(); root; root = root->nextRoot
Box()) |
5683 root->showLineTreeAndMark(markedBox1, markedLabel1, markedBox2, markedLa
bel2, obj, 1); | 4620 root->showLineTreeAndMark(markedBox1, markedLabel1, markedBox2, markedLa
bel2, obj, 1); |
5684 } | 4621 } |
5685 | 4622 |
5686 #endif | 4623 #endif |
5687 | 4624 |
5688 } // namespace WebCore | 4625 } // namespace WebCore |
OLD | NEW |