예제 #1
0
void InitialColumnHeightFinder::examineLine(const RootInlineBox& line) {
  LayoutUnit lineTop = line.lineTopWithLeading();
  LayoutUnit lineTopInFlowThread = flowThreadOffset() + lineTop;
  LayoutUnit minimumLogialHeight =
      columnLogicalHeightRequirementForLine(line.block().styleRef(), line);
  m_tallestUnbreakableLogicalHeight =
      std::max(m_tallestUnbreakableLogicalHeight, minimumLogialHeight);
  ASSERT(
      isFirstAfterBreak(lineTopInFlowThread) || !line.paginationStrut() ||
      !isLogicalTopWithinBounds(lineTopInFlowThread - line.paginationStrut()));
  if (isFirstAfterBreak(lineTopInFlowThread))
    recordStrutBeforeOffset(lineTopInFlowThread, line.paginationStrut());
}
예제 #2
0
void InitialColumnHeightFinder::examineBoxAfterEntering(
    const LayoutBox& box,
    LayoutUnit childLogicalHeight,
    EBreak previousBreakAfterValue) {
  if (m_lastBreakSeen > flowThreadOffset()) {
    // We have moved backwards. We're probably in a parallel flow, caused by
    // floats, sibling table cells, etc.
    m_lastBreakSeen = LayoutUnit();
  }
  if (isLogicalTopWithinBounds(flowThreadOffset() - box.paginationStrut())) {
    if (box.needsForcedBreakBefore(previousBreakAfterValue)) {
      addContentRun(flowThreadOffset());
    } else if (isFirstAfterBreak(flowThreadOffset()) &&
               m_lastBreakSeen != flowThreadOffset()) {
      // This box is first after a soft break.
      m_lastBreakSeen = flowThreadOffset();
      recordStrutBeforeOffset(flowThreadOffset(), box.paginationStrut());
    }
  }

  if (box.getPaginationBreakability() != LayoutBox::AllowAnyBreaks) {
    m_tallestUnbreakableLogicalHeight =
        std::max(m_tallestUnbreakableLogicalHeight, childLogicalHeight);
    return;
  }
  // Need to examine inner multicol containers to find their tallest unbreakable
  // piece of content.
  if (!box.isLayoutBlockFlow())
    return;
  LayoutMultiColumnFlowThread* innerFlowThread =
      toLayoutBlockFlow(box).multiColumnFlowThread();
  if (!innerFlowThread || innerFlowThread->isLayoutPagedFlowThread())
    return;
  LayoutUnit offsetInInnerFlowThread =
      flowThreadOffset() -
      innerFlowThread->blockOffsetInEnclosingFragmentationContext();
  LayoutUnit innerUnbreakableHeight =
      innerFlowThread->tallestUnbreakableLogicalHeight(offsetInInnerFlowThread);
  m_tallestUnbreakableLogicalHeight =
      std::max(m_tallestUnbreakableLogicalHeight, innerUnbreakableHeight);
}
예제 #3
0
void InitialColumnHeightFinder::examineBoxAfterEntering(
    const LayoutBox& box,
    EBreak previousBreakAfterValue) {
  if (isLogicalTopWithinBounds(flowThreadOffset() - box.paginationStrut())) {
    if (box.needsForcedBreakBefore(previousBreakAfterValue)) {
      addContentRun(flowThreadOffset());
    } else {
      ASSERT(isFirstAfterBreak(flowThreadOffset()) || !box.paginationStrut());
      if (isFirstAfterBreak(flowThreadOffset())) {
        // This box is first after a soft break.
        recordStrutBeforeOffset(flowThreadOffset(), box.paginationStrut());
      }
    }
  }

  if (box.getPaginationBreakability() != LayoutBox::AllowAnyBreaks) {
    LayoutUnit unsplittableLogicalHeight = box.logicalHeight();
    if (box.isFloating())
      unsplittableLogicalHeight += box.marginBefore() + box.marginAfter();
    m_tallestUnbreakableLogicalHeight =
        std::max(m_tallestUnbreakableLogicalHeight, unsplittableLogicalHeight);
    return;
  }
  // Need to examine inner multicol containers to find their tallest unbreakable
  // piece of content.
  if (!box.isLayoutBlockFlow())
    return;
  LayoutMultiColumnFlowThread* innerFlowThread =
      toLayoutBlockFlow(box).multiColumnFlowThread();
  if (!innerFlowThread || innerFlowThread->isLayoutPagedFlowThread())
    return;
  LayoutUnit offsetInInnerFlowThread =
      flowThreadOffset() -
      innerFlowThread->blockOffsetInEnclosingFragmentationContext();
  LayoutUnit innerUnbreakableHeight =
      innerFlowThread->tallestUnbreakableLogicalHeight(offsetInInnerFlowThread);
  m_tallestUnbreakableLogicalHeight =
      std::max(m_tallestUnbreakableLogicalHeight, innerUnbreakableHeight);
}
예제 #4
0
void MinimumSpaceShortageFinder::examineLine(const RootInlineBox& line) {
  LayoutUnit lineTop = line.lineTopWithLeading();
  LayoutUnit lineTopInFlowThread = flowThreadOffset() + lineTop;
  LayoutUnit lineHeight = line.lineBottomWithLeading() - lineTop;
  if (m_pendingStrut != LayoutUnit::min()) {
    // The previous break was before a breakable block. Here's the first line
    // after / inside that block. We want to record the distance from the top of
    // the column to the bottom of this box as space shortage.
    LayoutUnit logicalOffsetFromCurrentColumn =
        offsetFromColumnLogicalTop(lineTopInFlowThread);
    recordSpaceShortage(logicalOffsetFromCurrentColumn + lineHeight -
                        m_pendingStrut);
    m_pendingStrut = LayoutUnit::min();
    return;
  }
  ASSERT(
      isFirstAfterBreak(lineTopInFlowThread) || !line.paginationStrut() ||
      !isLogicalTopWithinBounds(lineTopInFlowThread - line.paginationStrut()));
  if (isFirstAfterBreak(lineTopInFlowThread))
    recordSpaceShortage(lineHeight - line.paginationStrut());

  // Even if the line box itself fits fine inside a column, some content may
  // overflow the line box bottom (due to restrictive line-height, for
  // instance). We should check if some portion of said overflow ends up in the
  // next column. That counts as space shortage.
  const MultiColumnFragmentainerGroup& group =
      groupAtOffset(lineTopInFlowThread);
  LayoutUnit lineBottomWithOverflow =
      lineTopInFlowThread + line.lineBottom() - lineTop;
  if (group.columnLogicalTopForOffset(lineTopInFlowThread) !=
      group.columnLogicalTopForOffset(lineBottomWithOverflow)) {
    LayoutUnit shortage =
        lineBottomWithOverflow -
        group.columnLogicalTopForOffset(lineBottomWithOverflow);
    recordSpaceShortage(shortage);
  }
}
예제 #5
0
void MinimumSpaceShortageFinder::examineBoxAfterEntering(
    const LayoutBox& box,
    LayoutUnit childLogicalHeight,
    EBreak previousBreakAfterValue) {
  LayoutBox::PaginationBreakability breakability =
      box.getPaginationBreakability();

  // Look for breaks before the child box.
  if (isLogicalTopWithinBounds(flowThreadOffset() - box.paginationStrut())) {
    if (box.needsForcedBreakBefore(previousBreakAfterValue)) {
      m_forcedBreaksCount++;
    } else {
      if (isFirstAfterBreak(flowThreadOffset())) {
        // This box is first after a soft break.
        LayoutUnit strut = box.paginationStrut();
        // Figure out how much more space we would need to prevent it from being
        // pushed to the next column.
        recordSpaceShortage(childLogicalHeight - strut);
        if (breakability != LayoutBox::ForbidBreaks &&
            m_pendingStrut == LayoutUnit::min()) {
          // We now want to look for the first piece of unbreakable content
          // (e.g. a line or a block-displayed image) inside this block. That
          // ought to be a good candidate for minimum space shortage; a much
          // better one than reporting space shortage for the entire block
          // (which we'll also do (further down), in case we couldn't find
          // anything more suitable).
          m_pendingStrut = strut;
        }
      }
    }
  }

  if (breakability != LayoutBox::ForbidBreaks) {
    // See if this breakable box crosses column boundaries.
    LayoutUnit bottomInFlowThread = flowThreadOffset() + childLogicalHeight;
    const MultiColumnFragmentainerGroup& group =
        groupAtOffset(flowThreadOffset());
    if (isFirstAfterBreak(flowThreadOffset()) ||
        group.columnLogicalTopForOffset(flowThreadOffset()) !=
            group.columnLogicalTopForOffset(bottomInFlowThread)) {
      // If the child crosses a column boundary, record space shortage, in case
      // nothing inside it has already done so. The column balancer needs to
      // know by how much it has to stretch the columns to make more content
      // fit. If no breaks are reported (but do occur), the balancer will have
      // no clue. Only measure the space after the last column boundary, in case
      // it crosses more than one.
      LayoutUnit spaceUsedInLastColumn =
          bottomInFlowThread -
          group.columnLogicalTopForOffset(bottomInFlowThread);
      recordSpaceShortage(spaceUsedInLastColumn);
    }
  }

  // If this is an inner multicol container, look for space shortage inside it.
  if (!box.isLayoutBlockFlow())
    return;
  LayoutMultiColumnFlowThread* flowThread =
      toLayoutBlockFlow(box).multiColumnFlowThread();
  if (!flowThread || flowThread->isLayoutPagedFlowThread())
    return;
  for (const LayoutMultiColumnSet* columnSet =
           flowThread->firstMultiColumnSet();
       columnSet; columnSet = columnSet->nextSiblingMultiColumnSet()) {
    // Establish an inner shortage finder for this column set in the inner
    // multicol container. We need to let it walk through all fragmentainer
    // groups in one go, or we'd miss the column boundaries between each
    // fragmentainer group. We need to record space shortage there too.
    MinimumSpaceShortageFinder innerFinder(
        *columnSet, columnSet->logicalTopInFlowThread(),
        columnSet->logicalBottomInFlowThread());
    recordSpaceShortage(innerFinder.minimumSpaceShortage());
  }
}