| 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 |