Esempio n. 1
0
int RenderBoxModelObject::pixelSnappedOffsetHeight() const
{
    return snapSizeToPixel(offsetHeight(), offsetTop());
}
IntSize pixelSnappedIntSize(const FractionalLayoutSize& s, const FractionalLayoutPoint& p)
{
    return IntSize(snapSizeToPixel(s.width(), p.x()), snapSizeToPixel(s.height(), p.y()));
}
Esempio n. 3
0
int RenderBoxModelObject::pixelSnappedOffsetWidth() const
{
    return snapSizeToPixel(offsetWidth(), offsetLeft());
}
int RenderLayerScrollableArea::pixelSnappedScrollHeight() const
{
    return snapSizeToPixel(scrollHeight(), box().clientTop() + box().y());
}
int RenderLayerScrollableArea::pixelSnappedScrollWidth() const
{
    return snapSizeToPixel(scrollWidth(), box().clientLeft() + box().x());
}
Esempio n. 6
0
TEST(LayoutUnitTest, LayoutUnitSnapSizeToPixel) {
  EXPECT_EQ(1, snapSizeToPixel(LayoutUnit(1), LayoutUnit(0)));
  EXPECT_EQ(1, snapSizeToPixel(LayoutUnit(1), LayoutUnit(0.5)));
  EXPECT_EQ(2, snapSizeToPixel(LayoutUnit(1.5), LayoutUnit(0)));
  EXPECT_EQ(2, snapSizeToPixel(LayoutUnit(1.5), LayoutUnit(0.49)));
  EXPECT_EQ(1, snapSizeToPixel(LayoutUnit(1.5), LayoutUnit(0.5)));
  EXPECT_EQ(1, snapSizeToPixel(LayoutUnit(1.5), LayoutUnit(0.75)));
  EXPECT_EQ(1, snapSizeToPixel(LayoutUnit(1.5), LayoutUnit(0.99)));
  EXPECT_EQ(2, snapSizeToPixel(LayoutUnit(1.5), LayoutUnit(1)));

  EXPECT_EQ(0, snapSizeToPixel(LayoutUnit(0.5), LayoutUnit(1.5)));
  EXPECT_EQ(0, snapSizeToPixel(LayoutUnit(0.99), LayoutUnit(1.5)));
  EXPECT_EQ(1, snapSizeToPixel(LayoutUnit(1.0), LayoutUnit(1.5)));
  EXPECT_EQ(1, snapSizeToPixel(LayoutUnit(1.49), LayoutUnit(1.5)));
  EXPECT_EQ(1, snapSizeToPixel(LayoutUnit(1.5), LayoutUnit(1.5)));

  EXPECT_EQ(101, snapSizeToPixel(LayoutUnit(100.5), LayoutUnit(100)));
  EXPECT_EQ(intMaxForLayoutUnit,
            snapSizeToPixel(LayoutUnit(intMaxForLayoutUnit), LayoutUnit(0.3)));
  EXPECT_EQ(intMinForLayoutUnit,
            snapSizeToPixel(LayoutUnit(intMinForLayoutUnit), LayoutUnit(-0.3)));
}
void BackgroundImageGeometry::calculate(
    const LayoutBoxModelObject& obj,
    const LayoutBoxModelObject* paintContainer,
    const GlobalPaintFlags globalPaintFlags,
    const FillLayer& fillLayer,
    const LayoutRect& paintRect) {
  LayoutUnit left;
  LayoutUnit top;
  LayoutSize positioningAreaSize;
  bool isLayoutView = obj.isLayoutView();
  const LayoutBox* rootBox = nullptr;
  if (isLayoutView) {
    // It is only possible reach here when root element has a box.
    Element* documentElement = obj.document().documentElement();
    DCHECK(documentElement);
    DCHECK(documentElement->layoutObject());
    DCHECK(documentElement->layoutObject()->isBox());
    rootBox = toLayoutBox(documentElement->layoutObject());
  }
  const LayoutBoxModelObject& positioningBox =
      isLayoutView ? static_cast<const LayoutBoxModelObject&>(*rootBox) : obj;

  // Determine the background positioning area and set destRect to the
  // background painting area.  destRect will be adjusted later if the
  // background is non-repeating.
  // FIXME: transforms spec says that fixed backgrounds behave like scroll
  // inside transforms.
  bool fixedAttachment = fillLayer.attachment() == FixedBackgroundAttachment;

  if (RuntimeEnabledFeatures::fastMobileScrollingEnabled()) {
    // As a side effect of an optimization to blit on scroll, we do not honor
    // the CSS property "background-attachment: fixed" because it may result in
    // rendering artifacts. Note, these artifacts only appear if we are blitting
    // on scroll of a page that has fixed background images.
    fixedAttachment = false;
  }

  if (!fixedAttachment) {
    setDestRect(paintRect);

    LayoutUnit right;
    LayoutUnit bottom;
    // Scroll and Local.
    if (fillLayer.origin() != BorderFillBox) {
      left = LayoutUnit(positioningBox.borderLeft());
      right = LayoutUnit(positioningBox.borderRight());
      top = LayoutUnit(positioningBox.borderTop());
      bottom = LayoutUnit(positioningBox.borderBottom());
      if (fillLayer.origin() == ContentFillBox) {
        left += positioningBox.paddingLeft();
        right += positioningBox.paddingRight();
        top += positioningBox.paddingTop();
        bottom += positioningBox.paddingBottom();
      }
    }

    if (isLayoutView) {
      // The background of the box generated by the root element covers the
      // entire canvas and will be painted by the view object, but the we should
      // still use the root element box for positioning.
      positioningAreaSize =
          rootBox->size() - LayoutSize(left + right, top + bottom),
      rootBox->location();
      // The input paint rect is specified in root element local coordinate
      // (i.e. a transform is applied on the context for painting), and is
      // expanded to cover the whole canvas.  Since left/top is relative to the
      // paint rect, we need to offset them back.
      left -= paintRect.x();
      top -= paintRect.y();
    } else {
      positioningAreaSize =
          paintRect.size() - LayoutSize(left + right, top + bottom);
    }
  } else {
    setHasNonLocalGeometry();

    LayoutRect viewportRect = obj.viewRect();
    if (fixedBackgroundPaintsInLocalCoordinates(obj, globalPaintFlags)) {
      viewportRect.setLocation(LayoutPoint());
    } else {
      if (FrameView* frameView = obj.view()->frameView())
        viewportRect.setLocation(IntPoint(frameView->scrollOffsetInt()));
      // Compensate the translations created by ScrollRecorders.
      // TODO(trchen): Fix this for SP phase 2. crbug.com/529963.
      viewportRect.moveBy(
          accumulatedScrollOffsetForFixedBackground(obj, paintContainer));
    }

    if (paintContainer)
      viewportRect.moveBy(
          LayoutPoint(-paintContainer->localToAbsolute(FloatPoint())));

    setDestRect(viewportRect);
    positioningAreaSize = destRect().size();
  }

  LayoutSize fillTileSize(
      calculateFillTileSize(positioningBox, fillLayer, positioningAreaSize));
  // It's necessary to apply the heuristic here prior to any further
  // calculations to avoid incorrectly using sub-pixel values that won't be
  // present in the painted tile.
  setTileSize(applySubPixelHeuristicToImageSize(fillTileSize, m_destRect));

  EFillRepeat backgroundRepeatX = fillLayer.repeatX();
  EFillRepeat backgroundRepeatY = fillLayer.repeatY();
  LayoutUnit unsnappedAvailableWidth =
      positioningAreaSize.width() - fillTileSize.width();
  LayoutUnit unsnappedAvailableHeight =
      positioningAreaSize.height() - fillTileSize.height();
  positioningAreaSize =
      LayoutSize(snapSizeToPixel(positioningAreaSize.width(), m_destRect.x()),
                 snapSizeToPixel(positioningAreaSize.height(), m_destRect.y()));
  LayoutUnit availableWidth = positioningAreaSize.width() - tileSize().width();
  LayoutUnit availableHeight =
      positioningAreaSize.height() - tileSize().height();

  LayoutUnit computedXPosition =
      roundedMinimumValueForLength(fillLayer.xPosition(), availableWidth);
  if (backgroundRepeatX == RoundFill &&
      positioningAreaSize.width() > LayoutUnit() &&
      fillTileSize.width() > LayoutUnit()) {
    int nrTiles = std::max(
        1, roundToInt(positioningAreaSize.width() / fillTileSize.width()));
    LayoutUnit roundedWidth = positioningAreaSize.width() / nrTiles;

    // Maintain aspect ratio if background-size: auto is set
    if (fillLayer.size().size.height().isAuto() &&
        backgroundRepeatY != RoundFill) {
      fillTileSize.setHeight(fillTileSize.height() * roundedWidth /
                             fillTileSize.width());
    }
    fillTileSize.setWidth(roundedWidth);

    setTileSize(applySubPixelHeuristicToImageSize(fillTileSize, m_destRect));
    setPhaseX(tileSize().width()
                  ? LayoutUnit(roundf(
                        tileSize().width() -
                        fmodf((computedXPosition + left), tileSize().width())))
                  : LayoutUnit());
    setSpaceSize(LayoutSize());
  }

  LayoutUnit computedYPosition =
      roundedMinimumValueForLength(fillLayer.yPosition(), availableHeight);
  if (backgroundRepeatY == RoundFill &&
      positioningAreaSize.height() > LayoutUnit() &&
      fillTileSize.height() > LayoutUnit()) {
    int nrTiles = std::max(
        1, roundToInt(positioningAreaSize.height() / fillTileSize.height()));
    LayoutUnit roundedHeight = positioningAreaSize.height() / nrTiles;
    // Maintain aspect ratio if background-size: auto is set
    if (fillLayer.size().size.width().isAuto() &&
        backgroundRepeatX != RoundFill) {
      fillTileSize.setWidth(fillTileSize.width() * roundedHeight /
                            fillTileSize.height());
    }
    fillTileSize.setHeight(roundedHeight);

    setTileSize(applySubPixelHeuristicToImageSize(fillTileSize, m_destRect));
    setPhaseY(tileSize().height()
                  ? LayoutUnit(roundf(
                        tileSize().height() -
                        fmodf((computedYPosition + top), tileSize().height())))
                  : LayoutUnit());
    setSpaceSize(LayoutSize());
  }

  if (backgroundRepeatX == RepeatFill) {
    setRepeatX(fillLayer, fillTileSize.width(), availableWidth,
               unsnappedAvailableWidth, left);
  } else if (backgroundRepeatX == SpaceFill &&
             tileSize().width() > LayoutUnit()) {
    LayoutUnit space = getSpaceBetweenImageTiles(positioningAreaSize.width(),
                                                 tileSize().width());
    if (space >= LayoutUnit())
      setSpaceX(space, availableWidth, left);
    else
      backgroundRepeatX = NoRepeatFill;
  }
  if (backgroundRepeatX == NoRepeatFill) {
    LayoutUnit xOffset = fillLayer.backgroundXOrigin() == RightEdge
                             ? availableWidth - computedXPosition
                             : computedXPosition;
    setNoRepeatX(left + xOffset);
  }

  if (backgroundRepeatY == RepeatFill) {
    setRepeatY(fillLayer, fillTileSize.height(), availableHeight,
               unsnappedAvailableHeight, top);
  } else if (backgroundRepeatY == SpaceFill &&
             tileSize().height() > LayoutUnit()) {
    LayoutUnit space = getSpaceBetweenImageTiles(positioningAreaSize.height(),
                                                 tileSize().height());
    if (space >= LayoutUnit())
      setSpaceY(space, availableHeight, top);
    else
      backgroundRepeatY = NoRepeatFill;
  }
  if (backgroundRepeatY == NoRepeatFill) {
    LayoutUnit yOffset = fillLayer.backgroundYOrigin() == BottomEdge
                             ? availableHeight - computedYPosition
                             : computedYPosition;
    setNoRepeatY(top + yOffset);
  }

  if (fixedAttachment)
    useFixedAttachment(paintRect.location());

  // Clip the final output rect to the paint rect
  m_destRect.intersect(paintRect);

  // Snap as-yet unsnapped values.
  setDestRect(LayoutRect(pixelSnappedIntRect(m_destRect)));
}