Пример #1
0
void LayoutImage::computeIntrinsicSizingInfo(
    IntrinsicSizingInfo& intrinsicSizingInfo) const {
  LayoutReplaced::computeIntrinsicSizingInfo(intrinsicSizingInfo);

  // Our intrinsicSize is empty if we're laying out generated images with
  // relative width/height. Figure out the right intrinsic size to use.
  if (intrinsicSizingInfo.size.isEmpty() &&
      m_imageResource->imageHasRelativeSize()) {
    LayoutObject* containingBlock =
        isOutOfFlowPositioned() ? container() : this->containingBlock();
    if (containingBlock->isBox()) {
      LayoutBox* box = toLayoutBox(containingBlock);
      intrinsicSizingInfo.size.setWidth(box->availableLogicalWidth().toFloat());
      intrinsicSizingInfo.size.setHeight(
          box->availableLogicalHeight(IncludeMarginBorderPadding).toFloat());
    }
  }
  // Don't compute an intrinsic ratio to preserve historical WebKit behavior if
  // we're painting alt text and/or a broken image.
  // Video is excluded from this behavior because video elements have a default
  // aspect ratio that a failed poster image load should not override.
  if (m_imageResource && m_imageResource->errorOccurred() && !isVideo()) {
    intrinsicSizingInfo.aspectRatio = FloatSize(1, 1);
    return;
  }
}
BackgroundBleedAvoidance BoxDecorationData::determineBackgroundBleedAvoidance(const LayoutBox& layoutBox)
{
    if (layoutBox.isDocumentElement())
        return BackgroundBleedNone;

    if (!hasBackground)
        return BackgroundBleedNone;

    const ComputedStyle& boxStyle = layoutBox.styleRef();
    const bool hasBorderRadius = boxStyle.hasBorderRadius();
    if (!hasBorderDecoration || !hasBorderRadius || layoutBox.canRenderBorderImage()) {
        if (layoutBox.backgroundShouldAlwaysBeClipped())
            return BackgroundBleedClipOnly;
        // Border radius clipping may require layer bleed avoidance if we are going to draw
        // an image over something else, because we do not want the antialiasing to lead to bleeding
        if (boxStyle.hasBackgroundImage() && hasBorderRadius) {
            // But if the top layer is opaque for the purposes of background painting, we do not
            // need the bleed avoidance because we will not paint anything behind the top layer.
            // But only if we need to draw something underneath.
            const FillLayer& fillLayer = layoutBox.style()->backgroundLayers();
            if ((backgroundColor.alpha() || fillLayer.next()) && !BoxPainter::isFillLayerOpaque(fillLayer, layoutBox))
                return BackgroundBleedClipLayer;
        }
        return BackgroundBleedNone;
    }

    if (borderObscuresBackgroundEdge(boxStyle))
        return BackgroundBleedShrinkBackground;

    return BackgroundBleedClipLayer;
}
void LayoutMultiColumnFlowThread::skipColumnSpanner(LayoutBox* layoutObject, LayoutUnit logicalTopInFlowThread)
{
    ASSERT(layoutObject->isColumnSpanAll());
    LayoutMultiColumnSpannerPlaceholder* placeholder = layoutObject->spannerPlaceholder();
    LayoutBox* previousColumnBox = placeholder->previousSiblingMultiColumnBox();
    if (previousColumnBox && previousColumnBox->isLayoutMultiColumnSet()) {
        LayoutMultiColumnSet* columnSet = toLayoutMultiColumnSet(previousColumnBox);
        if (logicalTopInFlowThread < columnSet->logicalTopInFlowThread())
            logicalTopInFlowThread = columnSet->logicalTopInFlowThread(); // Negative margins may cause this.
        columnSet->endFlow(logicalTopInFlowThread);
    }
    LayoutBox* nextColumnBox = placeholder->nextSiblingMultiColumnBox();
    if (nextColumnBox && nextColumnBox->isLayoutMultiColumnSet()) {
        LayoutMultiColumnSet* nextSet = toLayoutMultiColumnSet(nextColumnBox);
        m_lastSetWorkedOn = nextSet;
        nextSet->beginFlow(logicalTopInFlowThread);
    }

    // We'll lay out of spanners after flow thread layout has finished (during layout of the spanner
    // placeholders). There may be containing blocks for out-of-flow positioned descendants of the
    // spanner in the flow thread, so that out-of-flow objects inside the spanner will be laid out
    // as part of flow thread layout (even if the spanner itself won't). We need to add such
    // out-of-flow positioned objects to their containing blocks now, or they'll never get laid
    // out. Since it's non-trivial to determine if we need this, and where such out-of-flow objects
    // might be, just go through the whole subtree.
    for (LayoutObject* descendant = layoutObject->slowFirstChild(); descendant; descendant = descendant->nextInPreOrder()) {
        if (descendant->isBox() && descendant->isOutOfFlowPositioned())
            descendant->containingBlock()->insertPositionedObject(toLayoutBox(descendant));
    }
}
void LayoutMultiColumnFlowThread::layoutColumns(SubtreeLayoutScope& layoutScope)
{
    // Since we ended up here, it means that the multicol container (our parent) needed
    // layout. Since contents of the multicol container are diverted to the flow thread, the flow
    // thread needs layout as well.
    layoutScope.setChildNeedsLayout(this);

    m_blockOffsetInEnclosingFragmentationContext = enclosingFragmentationContext() ? multiColumnBlockFlow()->offsetFromLogicalTopOfFirstPage() : LayoutUnit();

    for (LayoutBox* columnBox = firstMultiColumnBox(); columnBox; columnBox = columnBox->nextSiblingMultiColumnBox()) {
        if (!columnBox->isLayoutMultiColumnSet()) {
            ASSERT(columnBox->isLayoutMultiColumnSpannerPlaceholder()); // no other type is expected.
            continue;
        }
        LayoutMultiColumnSet* columnSet = toLayoutMultiColumnSet(columnBox);
        layoutScope.setChildNeedsLayout(columnSet);
        if (!m_columnHeightsChanged) {
            // This is the initial layout pass. We need to reset the column height, because contents
            // typically have changed.
            columnSet->resetColumnHeight();
        }
        // Since column sets are regular block flow objects, and their position is changed in
        // regular block layout code (with no means for the multicol code to notice unless we add
        // hooks there), store the previous position now. If it changes in the imminent layout
        // pass, we may have to rebalance its columns.
        columnSet->storeOldPosition();
    }

    m_columnHeightsChanged = false;
    invalidateColumnSets();
    layout();
    validateColumnSets();
}
Пример #5
0
void LayoutTableRow::styleDidChange(StyleDifference diff, const ComputedStyle* oldStyle)
{
    ASSERT(style()->display() == TABLE_ROW);

    LayoutBox::styleDidChange(diff, oldStyle);
    propagateStyleToAnonymousChildren();

    if (section() && oldStyle && style()->logicalHeight() != oldStyle->logicalHeight())
        section()->rowLogicalHeightChanged(this);

    // If border was changed, notify table.
    if (parent()) {
        LayoutTable* table = this->table();
        if (table && !table->selfNeedsLayout() && !table->normalChildNeedsLayout() && oldStyle && oldStyle->border() != style()->border())
            table->invalidateCollapsedBorders();

        if (table && oldStyle && diff.needsFullLayout() && needsLayout() && table->collapseBorders() && borderWidthChanged(oldStyle, style())) {
            // If the border width changes on a row, we need to make sure the cells in the row know to lay out again.
            // This only happens when borders are collapsed, since they end up affecting the border sides of the cell
            // itself.
            for (LayoutBox* childBox = firstChildBox(); childBox; childBox = childBox->nextSiblingBox()) {
                if (!childBox->isTableCell())
                    continue;
                childBox->setChildNeedsLayout();
            }
        }
    }
}
Пример #6
0
void LayoutTextControlSingleLine::autoscroll(const IntPoint& position) {
  LayoutBox* layoutObject = innerEditorElement()->layoutBox();
  if (!layoutObject)
    return;

  layoutObject->autoscroll(position);
}
void CanvasRenderingContext2D::scrollPathIntoViewInternal(const Path& path) {
  if (!state().isTransformInvertible() || path.isEmpty())
    return;

  canvas()->document().updateStyleAndLayoutIgnorePendingStylesheets();

  LayoutObject* renderer = canvas()->layoutObject();
  LayoutBox* layoutBox = canvas()->layoutBox();
  if (!renderer || !layoutBox)
    return;

  // Apply transformation and get the bounding rect
  Path transformedPath = path;
  transformedPath.transform(state().transform());
  FloatRect boundingRect = transformedPath.boundingRect();

  // Offset by the canvas rect
  LayoutRect pathRect(boundingRect);
  IntRect canvasRect = layoutBox->absoluteContentBox();
  pathRect.moveBy(canvasRect.location());

  renderer->scrollRectToVisible(pathRect, ScrollAlignment::alignCenterAlways,
                                ScrollAlignment::alignTopAlways);

  // TODO: should implement "inform the user" that the caret and/or
  // selection the specified rectangle of the canvas. See
  // http://crbug.com/357987
}
TEST_F(ScrollingCoordinatorTest, fastFractionalScrollingDiv)
{
    registerMockedHttpURLLoad("fractional-scroll-div.html");
    navigateTo(m_baseURL + "fractional-scroll-div.html");
    forceFullCompositingUpdate();

    Document* document = frame()->document();
    Element* scrollableElement = document->getElementById("scroller");
    ASSERT(scrollableElement);

    scrollableElement->setScrollTop(1.0);
    scrollableElement->setScrollLeft(1.0);
    forceFullCompositingUpdate();

    // Make sure the fractional scroll offset change 1.0 -> 1.2 gets propagated
    // to compositor.
    scrollableElement->setScrollTop(1.2);
    scrollableElement->setScrollLeft(1.2);
    forceFullCompositingUpdate();

    LayoutObject* layoutObject = scrollableElement->layoutObject();
    ASSERT_TRUE(layoutObject->isBox());
    LayoutBox* box = toLayoutBox(layoutObject);
    ASSERT_TRUE(box->usesCompositedScrolling());
    CompositedLayerMapping* compositedLayerMapping = box->layer()->compositedLayerMapping();
    ASSERT_TRUE(compositedLayerMapping->hasScrollingLayer());
    ASSERT(compositedLayerMapping->scrollingContentsLayer());
    WebLayer* webScrollLayer = compositedLayerMapping->scrollingContentsLayer()->platformLayer();
    ASSERT_TRUE(webScrollLayer);
    ASSERT_NEAR(1.2, webScrollLayer->scrollPositionDouble().x, 0.01);
    ASSERT_NEAR(1.2, webScrollLayer->scrollPositionDouble().y, 0.01);
}
void FieldsetPainter::paintMask(const PaintInfo& paintInfo, const LayoutPoint& paintOffset)
{
    if (m_layoutFieldset.style()->visibility() != VISIBLE || paintInfo.phase != PaintPhaseMask)
        return;

    LayoutRect paintRect = LayoutRect(paintOffset, m_layoutFieldset.size());
    LayoutBox* legend = m_layoutFieldset.findInFlowLegend();
    if (!legend)
        return BoxPainter(m_layoutFieldset).paintMask(paintInfo, paintOffset);

    if (LayoutObjectDrawingRecorder::useCachedDrawingIfPossible(paintInfo.context, m_layoutFieldset, paintInfo.phase, paintOffset))
        return;

    // FIXME: We need to work with "rl" and "bt" block flow directions.  In those
    // cases the legend is embedded in the right and bottom borders respectively.
    // https://bugs.webkit.org/show_bug.cgi?id=47236
    if (m_layoutFieldset.style()->isHorizontalWritingMode()) {
        LayoutUnit yOff = (legend->location().y() > LayoutUnit()) ? LayoutUnit() : (legend->size().height() - m_layoutFieldset.borderTop()) / 2;
        paintRect.expand(LayoutUnit(), -yOff);
        paintRect.move(LayoutUnit(), yOff);
    } else {
        LayoutUnit xOff = (legend->location().x() > LayoutUnit()) ? LayoutUnit() : (legend->size().width() - m_layoutFieldset.borderLeft()) / 2;
        paintRect.expand(-xOff, LayoutUnit());
        paintRect.move(xOff, LayoutUnit());
    }

    LayoutObjectDrawingRecorder recorder(paintInfo.context, m_layoutFieldset, paintInfo.phase, paintRect, paintOffset);
    BoxPainter(m_layoutFieldset).paintMaskImages(paintInfo, paintRect);
}
LayoutBox* LayoutBox::create() {
    LayoutBox* ret = new LayoutBox();
    if (ret->init())
        return ret;
    else
        return NULL;
}
Пример #11
0
HTMLAreaElement* HitTestResult::imageAreaForImage() const
{
    ASSERT(m_innerNode);
    HTMLImageElement* imageElement = nullptr;
    if (isHTMLImageElement(m_innerNode)) {
        imageElement = toHTMLImageElement(m_innerNode);
    } else if (m_innerNode->isInShadowTree()) {
        if (m_innerNode->containingShadowRoot()->type() == ShadowRootType::UserAgent) {
            if (isHTMLImageElement(m_innerNode->shadowHost()))
                imageElement = toHTMLImageElement(m_innerNode->shadowHost());
        }
    }

    if (!imageElement || !imageElement->layoutObject() || !imageElement->layoutObject()->isBox())
        return nullptr;

    HTMLMapElement* map = imageElement->treeScope().getImageMap(imageElement->fastGetAttribute(usemapAttr));
    if (!map)
        return nullptr;

    LayoutBox* box = toLayoutBox(imageElement->layoutObject());
    LayoutRect contentBox = box->contentBoxRect();
    float scaleFactor = 1 / box->style()->effectiveZoom();
    LayoutPoint location = localPoint();
    location.scale(scaleFactor, scaleFactor);

    return map->areaForPoint(location, contentBox.size());
}
Пример #12
0
static FloatPoint perspectiveOrigin(const LayoutBox& box) {
  const ComputedStyle& style = box.styleRef();
  FloatSize borderBoxSize(box.size());
  return FloatPoint(
      floatValueForLength(style.perspectiveOriginX(), borderBoxSize.width()),
      floatValueForLength(style.perspectiveOriginY(), borderBoxSize.height()));
}
Пример #13
0
	bool Init() override
	{
		m_commonGUIStyle = g_commonGUIStyle;
		m_canvas = Utility::MakeRef(new Canvas());

		// Load textures for song select
		m_style = SongSelectStyle::Get(g_application);

		// Split between statistics and selection wheel (in percentage)
		const float screenSplit = 0.4f;

		// Statistics window
		m_statisticsWindow = Ref<SongStatistics>(new SongStatistics(m_style));
		Canvas::Slot* statisticsSlot = m_canvas->Add(m_statisticsWindow.As<GUIElementBase>());
		statisticsSlot->anchor = Anchor(0, 0, screenSplit, 1.0f);
		statisticsSlot->SetZOrder(2);

		// Background
		Panel* background = new Panel();
		background->imageFillMode = FillMode::Fill;
		background->texture = g_application->LoadTexture("bg.png");
		background->color = Color(0.5f);
		Canvas::Slot* bgSlot = m_canvas->Add(background->MakeShared());
		bgSlot->anchor = Anchors::Full;
		bgSlot->SetZOrder(-2);

		LayoutBox* box = new LayoutBox();
		Canvas::Slot* boxSlot = m_canvas->Add(box->MakeShared());
		boxSlot->anchor = Anchor(screenSplit, 0, 1.0f, 1.0f);
		box->layoutDirection = LayoutBox::Vertical;
		{
			m_searchField = Ref<TextInputField>(new TextInputField(m_commonGUIStyle));
			LayoutBox::Slot* searchFieldSlot = box->Add(m_searchField.As<GUIElementBase>());
			searchFieldSlot->fillX = true;
			m_searchField->OnTextUpdated.Add(this, &SongSelect_Impl::OnSearchTermChanged);

			m_selectionWheel = Ref<SelectionWheel>(new SelectionWheel(m_style));
			LayoutBox::Slot* selectionSlot = box->Add(m_selectionWheel.As<GUIElementBase>());
			selectionSlot->fillY = true;
			m_selectionWheel->OnMapSelected.Add(this, &SongSelect_Impl::OnMapSelected);
			m_selectionWheel->OnDifficultySelected.Add(this, &SongSelect_Impl::OnDifficultySelected);
		}

		// Select interface sound
		m_selectSound = g_audio->CreateSample("audio/menu_click.wav");

		// Setup the map database
		m_mapDatabase.AddSearchPath(g_gameConfig.GetString(GameConfigKeys::SongFolder));

		m_mapDatabase.OnMapsAdded.Add(m_selectionWheel.GetData(), &SelectionWheel::OnMapsAdded);
		m_mapDatabase.OnMapsUpdated.Add(m_selectionWheel.GetData(), &SelectionWheel::OnMapsUpdated);
		m_mapDatabase.OnMapsRemoved.Add(m_selectionWheel.GetData(), &SelectionWheel::OnMapsRemoved);
		m_mapDatabase.OnMapsCleared.Add(m_selectionWheel.GetData(), &SelectionWheel::OnMapsCleared);
		m_mapDatabase.StartSearching();

		m_selectionWheel->SelectRandom();

		return true;
	}
Пример #14
0
static LayoutRect getShapeImageMarginRect(const LayoutBox& layoutBox, const LayoutSize& referenceBoxLogicalSize)
{
    LayoutPoint marginBoxOrigin(-layoutBox.marginLogicalLeft() - layoutBox.borderAndPaddingLogicalLeft(), -layoutBox.marginBefore() - layoutBox.borderBefore() - layoutBox.paddingBefore());
    LayoutSize marginBoxSizeDelta(layoutBox.marginLogicalWidth() + layoutBox.borderAndPaddingLogicalWidth(), layoutBox.marginLogicalHeight() + layoutBox.borderAndPaddingLogicalHeight());
    LayoutSize marginRectSize(referenceBoxLogicalSize + marginBoxSizeDelta);
    marginRectSize.clampNegativeToZero();
    return LayoutRect(marginBoxOrigin, marginRectSize);
}
Пример #15
0
static FloatPoint3D transformOrigin(const LayoutBox& box) {
  const ComputedStyle& style = box.styleRef();
  FloatSize borderBoxSize(box.size());
  return FloatPoint3D(
      floatValueForLength(style.transformOriginX(), borderBoxSize.width()),
      floatValueForLength(style.transformOriginY(), borderBoxSize.height()),
      style.transformOriginZ());
}
BoxDecorationData::BoxDecorationData(const LayoutBox& layoutBox)
{
    backgroundColor = layoutBox.style()->visitedDependentColor(CSSPropertyBackgroundColor);
    hasBackground = backgroundColor.alpha() || layoutBox.style()->hasBackgroundImage();
    ASSERT(hasBackground == layoutBox.style()->hasBackground());
    hasBorderDecoration = layoutBox.style()->hasBorderDecoration();
    hasAppearance = layoutBox.style()->hasAppearance();
    bleedAvoidance = determineBackgroundBleedAvoidance(layoutBox);
}
Пример #17
0
void BlockPainter::paintChild(const LayoutBox& child,
                              const PaintInfo& paintInfo,
                              const LayoutPoint& paintOffset) {
  LayoutPoint childPoint =
      m_layoutBlock.flipForWritingModeForChild(&child, paintOffset);
  if (!child.hasSelfPaintingLayer() && !child.isFloating() &&
      !child.isColumnSpanAll())
    child.paint(paintInfo, childPoint);
}
Пример #18
0
LayoutState::LayoutState(LayoutBox& layoutObject,
                         bool containingBlockLogicalWidthChanged)
    : m_containingBlockLogicalWidthChanged(containingBlockLogicalWidthChanged),
      m_next(layoutObject.view()->layoutState()),
      m_layoutObject(layoutObject) {
  if (layoutObject.isLayoutFlowThread())
    m_flowThread = toLayoutFlowThread(&layoutObject);
  else
    m_flowThread = m_next->flowThread();
  m_paginationStateChanged = m_next->m_paginationStateChanged;
  layoutObject.view()->pushLayoutState(*this);
  m_heightOffsetForTableHeaders = m_next->heightOffsetForTableHeaders();

  if (layoutObject.isLayoutFlowThread()) {
    // Entering a new pagination context.
    m_paginationOffset = LayoutSize();
    m_isPaginated = true;
    return;
  }

  // Disable pagination for objects we don't support. For now this includes
  // overflow:scroll/auto, inline blocks and writing mode roots. Additionally,
  // pagination inside SVG is not allowed.
  if (layoutObject.getPaginationBreakability() == LayoutBox::ForbidBreaks ||
      (m_layoutObject.isSVG() && !m_layoutObject.isSVGRoot())) {
    m_flowThread = nullptr;
    m_isPaginated = false;
    return;
  }

  m_isPaginated = m_next->m_isPaginated;
  if (!m_isPaginated)
    return;

  // Now adjust the pagination offset, so that we can easily figure out how far
  // away we are from the start of the pagination context.
  m_paginationOffset = m_next->m_paginationOffset;
  bool fixed = layoutObject.isOutOfFlowPositioned() &&
               layoutObject.style()->position() == FixedPosition;
  if (fixed)
    return;
  m_paginationOffset =
      m_next->m_paginationOffset + layoutObject.locationOffset();
  if (!layoutObject.isOutOfFlowPositioned())
    return;
  if (LayoutObject* container = layoutObject.container()) {
    if (container->style()->hasInFlowPosition() &&
        container->isLayoutInline()) {
      m_paginationOffset +=
          toLayoutInline(container)->offsetForInFlowPositionedInline(
              layoutObject);
    }
  }

  // FIXME: <http://bugs.webkit.org/show_bug.cgi?id=13443> Apply control clip if
  // present.
}
Пример #19
0
void BlockPainter::paintAllChildPhasesAtomically(
    const LayoutBox& child,
    const PaintInfo& paintInfo,
    const LayoutPoint& paintOffset) {
  LayoutPoint childPoint =
      m_layoutBlock.flipForWritingModeForChild(&child, paintOffset);
  if (!child.hasSelfPaintingLayer() && !child.isFloating())
    ObjectPainter(child).paintAllPhasesAtomically(paintInfo, childPoint);
}
Пример #20
0
void LayoutSlider::layout()
{
    // FIXME: Find a way to cascade appearance.
    // http://webkit.org/b/62535
    LayoutBox* thumbBox = sliderThumbElement()->layoutBox();
    if (thumbBox && thumbBox->isSliderThumb())
        toLayoutSliderThumb(thumbBox)->updateAppearance(styleRef());

    LayoutFlexibleBox::layout();
}
static LayoutObject* lastLayoutObjectInSet(LayoutMultiColumnSet* multicolSet)
{
    LayoutBox* sibling = multicolSet->nextSiblingMultiColumnBox();
    if (!sibling)
        return nullptr; // By right we should return lastLeafChild() here, but the caller doesn't care, so just return 0.
    // Adjacent column content sets should not occur. We would have no way of figuring out what each
    // of them contains then.
    ASSERT(sibling->isLayoutMultiColumnSpannerPlaceholder());
    LayoutBox* spanner = toLayoutMultiColumnSpannerPlaceholder(sibling)->layoutObjectInFlowThread();
    return previousInPreOrderSkippingOutOfFlow(multicolSet->multiColumnFlowThread(), spanner);
}
static LayoutObject* firstLayoutObjectInSet(LayoutMultiColumnSet* multicolSet)
{
    LayoutBox* sibling = multicolSet->previousSiblingMultiColumnBox();
    if (!sibling)
        return multicolSet->flowThread()->firstChild();
    // Adjacent column content sets should not occur. We would have no way of figuring out what each
    // of them contains then.
    ASSERT(sibling->isLayoutMultiColumnSpannerPlaceholder());
    LayoutBox* spanner = toLayoutMultiColumnSpannerPlaceholder(sibling)->layoutObjectInFlowThread();
    return nextInPreOrderAfterChildrenSkippingOutOfFlow(multicolSet->multiColumnFlowThread(), spanner);
}
void LayoutMultiColumnSpannerPlaceholder::willBeRemovedFromTree()
{
    if (m_layoutObjectInFlowThread) {
        LayoutBox* exSpanner = m_layoutObjectInFlowThread;
        m_layoutObjectInFlowThread->clearSpannerPlaceholder();
        // Even if the placeholder is going away, the object in the flow thread might live on. Since
        // it's not a spanner anymore, it needs to be relaid out.
        exSpanner->setNeedsLayoutAndPrefWidthsRecalc(LayoutInvalidationReason::ColumnsChanged);
    }
    LayoutBox::willBeRemovedFromTree();
}
Пример #24
0
inline LayoutUnit borderBeforeInWritingMode(const LayoutBox& layoutBox, WritingMode writingMode)
{
    switch (writingMode) {
    case TopToBottomWritingMode: return layoutBox.borderTop();
    case LeftToRightWritingMode: return layoutBox.borderLeft();
    case RightToLeftWritingMode: return layoutBox.borderRight();
    }

    ASSERT_NOT_REACHED();
    return layoutBox.borderBefore();
}
Пример #25
0
void ColumnBalancer::traverseSubtree(const LayoutBox& box) {
  if (box.childrenInline() && box.isLayoutBlockFlow()) {
    // Look for breaks between lines.
    traverseLines(toLayoutBlockFlow(box));
  }

  // Look for breaks between and inside block-level children. Even if this is a
  // block flow with inline children, there may be interesting floats to examine
  // here.
  traverseChildren(box);
}
Пример #26
0
void ColumnBalancer::traverseSubtree(const LayoutBox& box)
{
    if (box.childrenInline() && box.isLayoutBlockFlow()) {
        // Look for breaks between lines.
        for (const RootInlineBox* line = toLayoutBlockFlow(box).firstRootBox(); line; line = line->nextRootBox()) {
            LayoutUnit lineTopInFlowThread = m_flowThreadOffset + line->lineTopWithLeading();
            if (lineTopInFlowThread < group().logicalTopInFlowThread())
                continue;
            if (lineTopInFlowThread >= group().logicalBottomInFlowThread())
                break;
            examineLine(*line);
        }
    }

    const LayoutFlowThread* flowThread = group().columnSet().flowThread();
    bool isHorizontalWritingMode = flowThread->isHorizontalWritingMode();

    // Look for breaks between and inside block-level children. Even if this is a block flow with
    // inline children, there may be interesting floats to examine here.
    for (const LayoutObject* child = box.slowFirstChild(); child; child = child->nextSibling()) {
        if (!child->isBox() || child->isInline())
            continue;
        const LayoutBox& childBox = toLayoutBox(*child);
        LayoutRect overflowRect = childBox.layoutOverflowRect();
        LayoutUnit childLogicalBottomWithOverflow = childBox.logicalTop() + (isHorizontalWritingMode ? overflowRect.maxY() : overflowRect.maxX());
        if (m_flowThreadOffset + childLogicalBottomWithOverflow <= group().logicalTopInFlowThread()) {
            // This child is fully above the fragmentainer group we're examining.
            continue;
        }
        LayoutUnit childLogicalTopWithOverflow = childBox.logicalTop() + (isHorizontalWritingMode ? overflowRect.y() : overflowRect.x());
        if (m_flowThreadOffset + childLogicalTopWithOverflow >= group().logicalBottomInFlowThread()) {
            // This child is fully below the fragmentainer group we're examining. We cannot just
            // stop here, though, thanks to negative margins. So keep looking.
            continue;
        }
        if (childBox.isOutOfFlowPositioned() || childBox.isColumnSpanAll())
            continue;

        // Tables are wicked. Both table rows and table cells are relative to their table section.
        LayoutUnit offsetForThisChild = childBox.isTableRow() ? LayoutUnit() : childBox.logicalTop();
        m_flowThreadOffset += offsetForThisChild;

        examineBoxAfterEntering(childBox);
        // Unless the child is unsplittable, or if the child establishes an inner multicol
        // container, we descend into its subtree for further examination.
        if (childBox.paginationBreakability() != LayoutBox::ForbidBreaks
            && (!childBox.isLayoutBlockFlow() || !toLayoutBlockFlow(childBox).multiColumnFlowThread()))
            traverseSubtree(childBox);
        examineBoxBeforeLeaving(childBox);

        m_flowThreadOffset -= offsetForThisChild;
    }
}
Пример #27
0
void MinimumSpaceShortageFinder::examineBoxBeforeLeaving(const LayoutBox& box)
{
    if (m_pendingStrut == LayoutUnit::min() || box.paginationBreakability() != LayoutBox::ForbidBreaks)
        return;

    // The previous break was before a breakable block. Here's the first piece of unbreakable
    // content 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 = flowThreadOffset() - group().columnLogicalTopForOffset(flowThreadOffset());
    recordSpaceShortage(logicalOffsetFromCurrentColumn + box.logicalHeight() - m_pendingStrut);
    m_pendingStrut = LayoutUnit::min();
}
void LayoutMultiColumnFlowThread::destroySpannerPlaceholder(LayoutMultiColumnSpannerPlaceholder* placeholder)
{
    if (LayoutBox* nextColumnBox = placeholder->nextSiblingMultiColumnBox()) {
        LayoutBox* previousColumnBox = placeholder->previousSiblingMultiColumnBox();
        if (nextColumnBox && nextColumnBox->isLayoutMultiColumnSet()
            && previousColumnBox && previousColumnBox->isLayoutMultiColumnSet()) {
            // Need to merge two column sets.
            nextColumnBox->destroy();
            invalidateColumnSets();
        }
    }
    placeholder->destroy();
}
Пример #29
0
inline LayoutUnit borderStartWithStyleForWritingMode(const LayoutBox& layoutBox, const ComputedStyle* style)
{
    if (style->isHorizontalWritingMode()) {
        if (style->isLeftToRightDirection())
            return layoutBox.borderLeft();

        return layoutBox.borderRight();
    }
    if (style->isLeftToRightDirection())
        return layoutBox.borderTop();

    return layoutBox.borderBottom();
}
// Returns true if the scroll control is invalidated.
static bool invalidatePaintOfScrollControlIfNeeded(const LayoutRect& newPaintInvalidationRect, const LayoutRect& previousPaintInvalidationRect, bool needsPaintInvalidation, LayoutBox& box, const LayoutBoxModelObject& paintInvalidationContainer)
{
    bool shouldInvalidateNewRect = needsPaintInvalidation;
    if (newPaintInvalidationRect != previousPaintInvalidationRect) {
        box.invalidatePaintUsingContainer(paintInvalidationContainer, previousPaintInvalidationRect, PaintInvalidationScroll);
        shouldInvalidateNewRect = true;
    }
    if (shouldInvalidateNewRect) {
        box.invalidatePaintUsingContainer(paintInvalidationContainer, newPaintInvalidationRect, PaintInvalidationScroll);
        box.enclosingLayer()->setNeedsRepaint();
        return true;
    }
    return false;
}