TEST_F(DocumentMarkerControllerTest, NodeWillBeRemovedBySetInnerHTML)
{
    setBodyInnerHTML("<b><i>foo</i></b>");
    {
        RefPtrWillBeRawPtr<Element> parent = toElement(document().body()->firstChild()->firstChild());
        markNodeContents(parent);
        EXPECT_EQ(1u, markerController().markers().size());
        setBodyInnerHTML("");
    }
    // No more reference to marked node.
    Heap::collectAllGarbage();
    EXPECT_EQ(0u, markerController().markers().size());
}
TEST_P(PaintPropertyTreePrinterTest, SimpleClipTree) {
  setBodyInnerHTML("hello world");
  String clipTreeAsString = clipPropertyTreeAsString(*document().view());
  EXPECT_THAT(clipTreeAsString.ascii().data(),
              testing::MatchesRegex("root .*"
                                    "  .*Clip \\(.*\\) .*"));
}
TEST_F(PaintPropertyTreeBuilderTest, NestedOpacityEffect)
{
    setBodyInnerHTML(
        "<div id='nodeWithoutOpacity'>"
        "  <div id='childWithOpacity' style='opacity: 0.5'>"
        "    <div id='grandChildWithoutOpacity'>"
        "      <div id='greatGrandChildWithOpacity' style='opacity: 0.2'/>"
        "    </div>"
        "  </div"
        "</div>");

    LayoutObject& nodeWithoutOpacity = *document().getElementById("nodeWithoutOpacity")->layoutObject();
    ObjectPaintProperties* nodeWithoutOpacityProperties = nodeWithoutOpacity.objectPaintProperties();
    EXPECT_EQ(nullptr, nodeWithoutOpacityProperties);

    LayoutObject& childWithOpacity = *document().getElementById("childWithOpacity")->layoutObject();
    ObjectPaintProperties* childWithOpacityProperties = childWithOpacity.objectPaintProperties();
    EXPECT_EQ(0.5f, childWithOpacityProperties->effect()->opacity());
    // childWithOpacity is the root effect node.
    EXPECT_EQ(nullptr, childWithOpacityProperties->effect()->parent());

    LayoutObject& grandChildWithoutOpacity = *document().getElementById("grandChildWithoutOpacity")->layoutObject();
    EXPECT_EQ(nullptr, grandChildWithoutOpacity.objectPaintProperties());

    LayoutObject& greatGrandChildWithOpacity = *document().getElementById("greatGrandChildWithOpacity")->layoutObject();
    ObjectPaintProperties* greatGrandChildWithOpacityProperties = greatGrandChildWithOpacity.objectPaintProperties();
    EXPECT_EQ(0.2f, greatGrandChildWithOpacityProperties->effect()->opacity());
    EXPECT_EQ(childWithOpacityProperties->effect(), greatGrandChildWithOpacityProperties->effect()->parent());
}
Example #4
0
TEST_F(LayoutObjectTest, ContainingBlockStaticLayoutObjectShouldBeParent)
{
    setBodyInnerHTML("<foo style='position:static'></foo>");
    LayoutObject* bodyLayoutObject = document().body()->layoutObject();
    LayoutObject* layoutObject = bodyLayoutObject->slowFirstChild();
    EXPECT_EQ(layoutObject->containingBlock(), bodyLayoutObject);
}
Example #5
0
TEST_F(VisualRectMappingTest, LayoutText) {
  setBodyInnerHTML(
      "<style>body { margin: 0; }</style>"
      "<div id='container' style='overflow: scroll; width: 50px; height: 50px'>"
      "  <span><img style='width: 20px; height: 100px'></span>"
      "  text text text text text text text"
      "</div>");

  LayoutBlock* container =
      toLayoutBlock(getLayoutObjectByElementId("container"));
  LayoutText* text = toLayoutText(container->lastChild());

  container->setScrollTop(LayoutUnit(50));
  LayoutRect originalRect(0, 60, 20, 80);
  LayoutRect rect = originalRect;
  EXPECT_TRUE(text->mapToVisualRectInAncestorSpace(container, rect));
  rect.move(-container->scrolledContentOffset());
  EXPECT_EQ(rect, LayoutRect(0, 10, 20, 80));

  rect = originalRect;
  EXPECT_TRUE(text->mapToVisualRectInAncestorSpace(&layoutView(), rect));
  EXPECT_EQ(rect, LayoutRect(0, 10, 20, 40));
  checkPaintInvalidationStateRectMapping(rect, originalRect, *text,
                                         layoutView(), layoutView());

  rect = LayoutRect(0, 60, 80, 0);
  EXPECT_TRUE(
      text->mapToVisualRectInAncestorSpace(container, rect, EdgeInclusive));
  rect.move(-container->scrolledContentOffset());
  EXPECT_EQ(rect, LayoutRect(0, 10, 80, 0));
}
Example #6
0
TEST_F(VisualRectMappingTest, SelfFlippedWritingMode) {
  setBodyInnerHTML(
      "<div id='target' style='writing-mode: vertical-rl; box-shadow: 40px "
      "20px black;"
      "    width: 100px; height: 50px; position: absolute; top: 111px; left: "
      "222px'>"
      "</div>");

  LayoutBlock* target = toLayoutBlock(getLayoutObjectByElementId("target"));
  LayoutRect visualRect = target->localVisualRect();
  // -40 = -box_shadow_offset_x(40) (with target's top-right corner as the
  // origin)
  // 140 = width(100) + box_shadow_offset_x(40)
  // 70 = height(50) + box_shadow_offset_y(20)
  EXPECT_EQ(LayoutRect(-40, 0, 140, 70), visualRect);

  LayoutRect rect = visualRect;
  // TODO(wkorman): The calls to flipForWritingMode() here and in other test
  // cases below are necessary because mapToVisualRectInAncestorSpace()
  // currently expects the input rect to be in "physical coordinates" (*not*
  // "physical coordinates with flipped block-flow direction"), see
  // LayoutBoxModelObject.h.
  target->flipForWritingMode(rect);
  EXPECT_TRUE(target->mapToVisualRectInAncestorSpace(target, rect));
  // This rect is in physical coordinates of target.
  EXPECT_EQ(LayoutRect(0, 0, 140, 70), rect);

  rect = visualRect;
  target->flipForWritingMode(rect);
  EXPECT_TRUE(target->mapToVisualRectInAncestorSpace(&layoutView(), rect));
  EXPECT_EQ(LayoutRect(222, 111, 140, 70), rect);
  checkPaintInvalidationStateRectMapping(rect, visualRect, *target,
                                         layoutView(), layoutView());
}
TEST_F(ImageQualityControllerTest, ImageRenderingPixelated)
{
    setBodyInnerHTML("<img src='myimage' style='image-rendering: pixelated'></img>");
    LayoutObject* obj = document().body()->firstChild()->layoutObject();

    EXPECT_EQ(InterpolationNone, controller()->chooseInterpolationQuality(*obj, nullptr, nullptr, LayoutSize()));
}
// TODO(wangxianzhu): Create a version for slimming paint v2 when it supports interest rect
TEST_F(TableCellPainterTest, TableCellBackgroundInterestRect)
{
    setBodyInnerHTML(
        "<style>"
        "  td { width: 200px; height: 200px; border: none; }"
        "  tr { background-color: blue; }"
        "  table { border: none; border-spacing: 0; border-collapse: collapse; }"
        "</style>"
        "<table>"
        "  <tr><td id='cell1'></td></tr>"
        "  <tr><td id='cell2'></td></tr>"
        "</table>");

    LayoutView& layoutView = *document().layoutView();
    PaintLayer& rootLayer = *layoutView.layer();
    LayoutObject& cell1 = *document().getElementById("cell1")->layoutObject();
    LayoutObject& cell2 = *document().getElementById("cell2")->layoutObject();

    GraphicsContext context(&rootDisplayItemList());
    PaintLayerPaintingInfo paintingInfo(&rootLayer, LayoutRect(0, 0, 200, 200), GlobalPaintNormalPhase, LayoutSize());
    PaintLayerPainter(rootLayer).paintLayerContents(&context, paintingInfo, PaintLayerPaintingCompositingAllPhases);
    rootDisplayItemList().commitNewDisplayItems();

    EXPECT_DISPLAY_LIST(rootDisplayItemList().displayItems(), 2,
        TestDisplayItem(layoutView, DisplayItem::BoxDecorationBackground),
        TestDisplayItem(cell1, DisplayItem::TableCellBackgroundFromRow));

    PaintLayerPaintingInfo paintingInfo1(&rootLayer, LayoutRect(0, 300, 200, 200), GlobalPaintNormalPhase, LayoutSize());
    PaintLayerPainter(rootLayer).paintLayerContents(&context, paintingInfo1, PaintLayerPaintingCompositingAllPhases);
    rootDisplayItemList().commitNewDisplayItems();

    EXPECT_DISPLAY_LIST(rootDisplayItemList().displayItems(), 2,
        TestDisplayItem(layoutView, DisplayItem::BoxDecorationBackground),
        TestDisplayItem(cell2, DisplayItem::TableCellBackgroundFromRow));
}
TEST_F(PrintContextFrameTest, WithScrolledSubframe)
{
    MockCanvas canvas;
    document().setBaseURLOverride(KURL(ParsedURLString, "http://a.com/"));
    setBodyInnerHTML("<style>::-webkit-scrollbar { display: none }</style>"
        "<iframe id='frame' src='http://b.com/' width='500' height='500'"
        " style='border-width: 5px; margin: 5px; position: absolute; top: 90px; left: 90px'></iframe>");

    Document& frameDocument = setupChildIframe("frame", absoluteBlockHtmlForLink(10, 10, 20, 20, "http://invisible.com")
        + absoluteBlockHtmlForLink(50, 60, 70, 80, "http://partly.visible.com")
        + absoluteBlockHtmlForLink(150, 160, 170, 180, "http://www.google.com")
        + absoluteBlockHtmlForLink(250, 260, 270, 280, "http://www.google.com#fragment")
        + absoluteBlockHtmlForLink(850, 860, 70, 80, "http://another.invisible.com"));

    frameDocument.domWindow()->scrollTo(100, 100);

    printSinglePage(canvas);

    const Vector<MockCanvas::Operation>& operations = canvas.recordedOperations();
    ASSERT_EQ(3u, operations.size());
    EXPECT_EQ(MockCanvas::DrawRect, operations[0].type);
    EXPECT_SKRECT_EQ(50, 60, 70, 80, operations[0].rect); // FIXME: the rect should be clipped.
    EXPECT_EQ(MockCanvas::DrawRect, operations[1].type);
    EXPECT_SKRECT_EQ(150, 160, 170, 180, operations[1].rect);
    EXPECT_EQ(MockCanvas::DrawRect, operations[2].type);
    EXPECT_SKRECT_EQ(250, 260, 270, 280, operations[2].rect);
}
Example #10
0
TEST_F(PaintPropertyTreeBuilderTest, EffectNodesAcrossSVGHTMLBoundary)
{
    setBodyInnerHTML(
        "<svg id='svgRootWithOpacity' style='opacity: 0.3;'>"
        "  <foreignObject id='foreignObjectWithOpacity' opacity='0.4'>"
        "    <body>"
        "      <span id='spanWithOpacity' style='opacity: 0.5'/>"
        "    </body>"
        "  </foreignObject>"
        "</svg>");

    LayoutObject& svgRootWithOpacity = *document().getElementById("svgRootWithOpacity")->layoutObject();
    ObjectPaintProperties* svgRootWithOpacityProperties = svgRootWithOpacity.objectPaintProperties();
    EXPECT_EQ(0.3f, svgRootWithOpacityProperties->effect()->opacity());
    EXPECT_EQ(nullptr, svgRootWithOpacityProperties->effect()->parent());

    LayoutObject& foreignObjectWithOpacity = *document().getElementById("foreignObjectWithOpacity")->layoutObject();
    ObjectPaintProperties* foreignObjectWithOpacityProperties = foreignObjectWithOpacity.objectPaintProperties();
    EXPECT_EQ(0.4f, foreignObjectWithOpacityProperties->effect()->opacity());
    EXPECT_EQ(svgRootWithOpacityProperties->effect(), foreignObjectWithOpacityProperties->effect()->parent());

    LayoutObject& spanWithOpacity = *document().getElementById("spanWithOpacity")->layoutObject();
    ObjectPaintProperties* spanWithOpacityProperties = spanWithOpacity.objectPaintProperties();
    EXPECT_EQ(0.5f, spanWithOpacityProperties->effect()->opacity());
    EXPECT_EQ(foreignObjectWithOpacityProperties->effect(), spanWithOpacityProperties->effect()->parent());
}
Example #11
0
TEST_F(PaintPropertyTreeBuilderTest, FixedTransformAncestorAcrossSVGHTMLBoundary)
{
    setBodyInnerHTML(
        "<style> body { margin: 0px; } </style>"
        "<svg id='svg' style='transform: translate3d(1px, 2px, 3px);'>"
        "  <g id='container' transform='translate(20 30)'>"
        "    <foreignObject>"
        "      <body>"
        "        <div id='fixed' style='position: fixed; left: 200px; top: 150px;'></div>"
        "      </body>"
        "    </foreignObject>"
        "  </g>"
        "</svg>");

    LayoutObject& svg = *document().getElementById("svg")->layoutObject();
    ObjectPaintProperties* svgProperties = svg.objectPaintProperties();
    EXPECT_EQ(TransformationMatrix().translate3d(1, 2, 3), svgProperties->transform()->matrix());

    LayoutObject& container = *document().getElementById("container")->layoutObject();
    ObjectPaintProperties* containerProperties = container.objectPaintProperties();
    EXPECT_EQ(TransformationMatrix().translate(20, 30), containerProperties->transform()->matrix());
    EXPECT_EQ(svgProperties->transform(), containerProperties->transform()->parent());

    Element* fixed = document().getElementById("fixed");
    ObjectPaintProperties* fixedProperties = fixed->layoutObject()->objectPaintProperties();
    EXPECT_EQ(TransformationMatrix().translate(200, 150), fixedProperties->paintOffsetTranslation()->matrix());
    // Ensure the fixed position element is rooted at the nearest transform container.
    EXPECT_EQ(containerProperties->transform(), fixedProperties->paintOffsetTranslation()->parent());
}
Example #12
0
 void SetUp() override {
   RenderingTest::SetUp();
   enableCompositing();
   setBodyInnerHTML(
       "<style>"
       "  body {"
       "    margin: 0;"
       "    height: 0;"
       "  }"
       "  ::-webkit-scrollbar { display: none }"
       "  #target {"
       "    width: 50px;"
       "    height: 100px;"
       "    transform-origin: 0 0;"
       "  }"
       "  .border {"
       "    border-width: 20px 10px;"
       "    border-style: solid;"
       "    border-color: red;"
       "  }"
       "  .local-background {"
       "    background-attachment: local;"
       "    overflow: scroll;"
       "  }"
       "  .gradient {"
       "    background-image: linear-gradient(blue, yellow)"
       "  }"
       "</style>"
       "<div id='target' class='border'></div>");
 }
TEST_P(PaintPropertyTreePrinterTest, SimpleScrollTree) {
  setBodyInnerHTML("<div style='height: 4000px;'>hello world</div>");
  String scrollTreeAsString = scrollPropertyTreeAsString(*document().view());
  EXPECT_THAT(scrollTreeAsString.ascii().data(),
              testing::MatchesRegex("root .*"
                                    "  Scroll \\(.*\\) .*"));
}
TEST_P(PaintPropertyTreePrinterTest, SimpleEffectTree) {
  setBodyInnerHTML("<div style='opacity: 0.9;'>hello world</div>");
  String effectTreeAsString = effectPropertyTreeAsString(*document().view());
  EXPECT_THAT(effectTreeAsString.ascii().data(),
              testing::MatchesRegex("root .*"
                                    "  Effect \\(LayoutBlockFlow DIV\\) .*"));
}
TEST_F(ImageQualityControllerTest, DontKickTheAnimationTimerWhenPaintingAtTheSameSize)
{
    MockTimer* mockTimer = new MockTimer(controller(), &ImageQualityController::highQualityRepaintTimerFired);
    controller()->setTimer(mockTimer);
    setBodyInnerHTML("<img src='myimage'></img>");
    LayoutImage* img = toLayoutImage(document().body()->firstChild()->layoutObject());

    RefPtr<TestImageLowQuality> testImage = adoptRef(new TestImageLowQuality);

    // Paint once. This will kick off a timer to see if we resize it during that timer's execution.
    EXPECT_EQ(InterpolationMedium, controller()->chooseInterpolationQuality(*img, testImage.get(), testImage.get(), LayoutSize(2, 2)));

    // Go into low-quality mode now that the size changed.
    EXPECT_EQ(InterpolationLow, controller()->chooseInterpolationQuality(*img, testImage.get(), testImage.get(), LayoutSize(3, 3)));

    // Stay in low-quality mode since the size changed again.
    EXPECT_EQ(InterpolationLow, controller()->chooseInterpolationQuality(*img, testImage.get(), testImage.get(), LayoutSize(4, 4)));

    mockTimer->stop();
    EXPECT_FALSE(mockTimer->isActive());
    // Painted at the same size, so even though timer is still executing, don't go to low quality.
    EXPECT_EQ(InterpolationLow, controller()->chooseInterpolationQuality(*img, testImage.get(), testImage.get(), LayoutSize(4, 4)));
    // Check that the timer was not kicked. It should not have been, since the image was painted at the same size as last time.
    EXPECT_FALSE(mockTimer->isActive());
}
TEST_F(PaintControllerPaintTestForSlimmingPaintV2, CompositingFold) {
  setBodyInnerHTML(
      "<div id='div' style='width: 200px; height: 200px; opacity: 0.5'>"
      "  <div style='width: 100px; height: 100px; background-color: "
      "blue'></div>"
      "</div>");
  PaintLayer& htmlLayer =
      *toLayoutBoxModelObject(document().documentElement()->layoutObject())
           ->layer();
  LayoutBlock& div = *toLayoutBlock(getLayoutObjectByElementId("div"));
  LayoutObject& subDiv = *div.firstChild();

  EXPECT_DISPLAY_LIST(
      rootPaintController().getDisplayItemList(), 8,
      TestDisplayItem(layoutView(),
                      DisplayItem::kClipFrameToVisibleContentRect),
      TestDisplayItem(*layoutView().layer(), DisplayItem::kSubsequence),
      TestDisplayItem(layoutView(), documentBackgroundType),
      TestDisplayItem(htmlLayer, DisplayItem::kSubsequence),
      // The begin and end compositing display items have been folded into this
      // one.
      TestDisplayItem(subDiv, backgroundType),
      TestDisplayItem(htmlLayer, DisplayItem::kEndSubsequence),
      TestDisplayItem(*layoutView().layer(), DisplayItem::kEndSubsequence),
      TestDisplayItem(layoutView(),
                      DisplayItem::clipTypeToEndClipType(
                          DisplayItem::kClipFrameToVisibleContentRect)));
}
TEST_F(ImageQualityControllerTest, RegularImage)
{
    setBodyInnerHTML("<img src='myimage'></img>");
    LayoutObject* obj = document().body()->firstChild()->layoutObject();

    EXPECT_EQ(InterpolationDefault, controller()->chooseInterpolationQuality(*obj, nullptr, nullptr, LayoutSize()));
}
TEST_F(PrintContextTest, LinkTargetComplex)
{
    MockCanvas canvas;
    setBodyInnerHTML("<div>"
        // Link in anonymous block before a block.
        + inlineHtmlForLink("http://www.google.com", "<img style='width: 111; height: 10'>")
        + "<div> " + inlineHtmlForLink("http://www.google1.com", "<img style='width: 122; height: 20'>") + "</div>"
        // Link in anonymous block after a block, containing another block
        + inlineHtmlForLink("http://www.google2.com", "<div style='width:133; height: 30'>BLOCK</div>")
        // Link embedded in inlines
        + "<span><b><i><img style='width: 40px; height: 40px'><br>"
        + inlineHtmlForLink("http://www.google3.com", "<img style='width: 144px; height: 40px'>")
        + "</i></b></span>"
        // Link embedded in relatively positioned inline
        + "<span style='position: relative; top: 50px; left: 50px'><b><i><img style='width: 1px; height: 40px'><br>"
        + inlineHtmlForLink("http://www.google3.com", "<img style='width: 155px; height: 50px'>")
        + "</i></b></span>"
        + "</div>");
    printSinglePage(canvas);

    const Vector<MockCanvas::Operation>& operations = canvas.recordedOperations();
    ASSERT_EQ(4u, operations.size());
    EXPECT_EQ(MockCanvas::DrawRect, operations[0].type);
    EXPECT_SKRECT_EQ(0, 0, 111, 10, operations[0].rect);
    EXPECT_EQ(MockCanvas::DrawRect, operations[1].type);
    EXPECT_SKRECT_EQ(0, 10, 122, 20, operations[1].rect);
    EXPECT_EQ(MockCanvas::DrawRect, operations[2].type);
    EXPECT_SKRECT_EQ(0, 100, 144, 40, operations[2].rect);
    EXPECT_EQ(MockCanvas::DrawRect, operations[3].type);
    EXPECT_SKRECT_EQ(50, 190, 155, 50, operations[3].rect);
}
TEST_F(TextAutosizerTest, DISABLED_NestedTextSizeAdjust)
{
    setBodyInnerHTML(
        "<meta name='viewport' content='width=800'>"
        "<style>"
        "    html { font-size: 16px; }"
        "    body { width: 800px; margin: 0; overflow-y: hidden; }"
        "</style>"
        "<div id='textSizeAdjustA' style='text-size-adjust: 47%;'>"
        "    Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor"
        "    incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud"
        "    exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure"
        "    dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur."
        "    Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt"
        "    mollit anim id est laborum."
        "    <div id='textSizeAdjustB' style='text-size-adjust: 53%;'>"
        "        Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor"
        "        incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud"
        "        exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute"
        "        irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla"
        "        pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui"
        "        officia deserunt mollit anim id est laborum."
        "    </div>"
        "</div>");
    LayoutObject* textSizeAdjustA = document().getElementById("textSizeAdjustA")->layoutObject();
    EXPECT_FLOAT_EQ(16.f, textSizeAdjustA->style()->specifiedFontSize());
    // 16px * 47% = 7.52
    EXPECT_FLOAT_EQ(7.52f, textSizeAdjustA->style()->computedFontSize());
    LayoutObject* textSizeAdjustB = document().getElementById("textSizeAdjustB")->layoutObject();
    EXPECT_FLOAT_EQ(16.f, textSizeAdjustB->style()->specifiedFontSize());
    // 16px * 53% = 8.48
    EXPECT_FLOAT_EQ(8.48f, textSizeAdjustB->style()->computedFontSize());
}
Example #20
0
TEST_F(PaintLayerClipperTest, NestedContainPaintClip) {
  setBodyInnerHTML(
      "<div style='contain: paint; width: 200px; height: 200px; overflow: "
      "auto'>"
      "  <div id='target' style='contain: paint; height: 400px'>"
      "  </div>"
      "</div>");

  LayoutRect infiniteRect(LayoutRect::infiniteIntRect());
  PaintLayer* layer =
      toLayoutBoxModelObject(getLayoutObjectByElementId("target"))->layer();
  ClipRectsContext context(layer->parent(),
                           PaintingClipRectsIgnoringOverflowClip);
  LayoutRect layerBounds;
  ClipRect backgroundRect, foregroundRect;
  layer->clipper().calculateRects(context, infiniteRect, layerBounds,
                                  backgroundRect, foregroundRect);
  EXPECT_EQ(LayoutRect(0, 0, 200, 400), backgroundRect.rect());
  EXPECT_EQ(LayoutRect(0, 0, 200, 400), foregroundRect.rect());
  EXPECT_EQ(LayoutRect(0, 0, 200, 400), layerBounds);

  ClipRectsContext contextClip(layer->parent(), PaintingClipRects);
  layer->clipper().calculateRects(contextClip, infiniteRect, layerBounds,
                                  backgroundRect, foregroundRect);
  EXPECT_EQ(LayoutRect(0, 0, 200, 200), backgroundRect.rect());
  EXPECT_EQ(LayoutRect(0, 0, 200, 200), foregroundRect.rect());
  EXPECT_EQ(LayoutRect(0, 0, 200, 400), layerBounds);
}
Example #21
0
TEST_F(VisualRectMappingTest, LayoutViewSubpixelRounding) {
  document().setBaseURLOverride(KURL(ParsedURLString, "http://test.com"));
  setBodyInnerHTML(
      "<style>body { margin: 0; }</style>"
      "<div id=frameContainer style='position: relative; left: 0.5px'>"
      "  <iframe style='position: relative; left: 0.5px' "
      "src='http://test.com' width='200' height='200' frameBorder='0'></iframe>"
      "</div>");
  setChildFrameHTML(
      "<style>body { margin: 0; }</style><div id='target' style='position: "
      "relative; width: 100px; height: 100px; left: 0.5px'>");

  document().view()->updateAllLifecyclePhases();

  LayoutBlock* frameContainer =
      toLayoutBlock(getLayoutObjectByElementId("frameContainer"));
  LayoutObject* target =
      childDocument().getElementById("target")->layoutObject();
  LayoutRect rect(0, 0, 100, 100);
  EXPECT_TRUE(target->mapToVisualRectInAncestorSpace(frameContainer, rect));
  // When passing from the iframe to the parent frame, the rect of (0.5, 0, 100,
  // 100) is expanded to (0, 0, 100, 100), and then offset by the 0.5 offset of
  // frameContainer.
  EXPECT_EQ(LayoutRect(LayoutPoint(DoublePoint(0.5, 0)), LayoutSize(101, 100)),
            rect);
}
TEST_F(PaintLayerScrollableAreaTest, OpaqueLayersPromotedOnStyleChange) {
  RuntimeEnabledFeatures::setCompositeOpaqueScrollersEnabled(true);

  setBodyInnerHTML(
      "<style>"
      "#scroller { overflow: scroll; height: 200px; width: 200px; background: "
      "rgba(255,255,255,0.5) local content-box; }"
      "#scrolled { height: 300px; }"
      "</style>"
      "<div id=\"scroller\"><div id=\"scrolled\"></div></div>");
  document().view()->updateAllLifecyclePhases();

  EXPECT_TRUE(RuntimeEnabledFeatures::compositeOpaqueScrollersEnabled());
  Element* scroller = document().getElementById("scroller");
  PaintLayer* paintLayer =
      toLayoutBoxModelObject(scroller->layoutObject())->layer();
  ASSERT_TRUE(paintLayer);
  EXPECT_FALSE(paintLayer->needsCompositedScrolling());

  // Change the background to transparent
  scroller->setAttribute(HTMLNames::styleAttr,
                         "background: white local content-box;");
  document().view()->updateAllLifecyclePhases();
  paintLayer = toLayoutBoxModelObject(scroller->layoutObject())->layer();
  ASSERT_TRUE(paintLayer);
  EXPECT_TRUE(paintLayer->needsCompositedScrolling());
  EXPECT_TRUE(paintLayer->graphicsLayerBacking());
  ASSERT_TRUE(paintLayer->graphicsLayerBackingForScrolling());
  EXPECT_TRUE(paintLayer->graphicsLayerBackingForScrolling()->contentsOpaque());
}
Example #23
0
TEST_F(VisualRectMappingTest, ContainerOverflowHidden) {
  setBodyInnerHTML(
      "<div id='container' style='position: absolute; top: 111px; left: 222px;"
      "    border: 10px solid red; overflow: hidden; width: 50px; height: "
      "80px;'>"
      "    <div id='target' style='box-shadow: 40px 20px black; width: 100px; "
      "height: 90px'></div>"
      "</div>");

  LayoutBlock* container =
      toLayoutBlock(getLayoutObjectByElementId("container"));
  EXPECT_EQ(LayoutUnit(), container->scrollTop());
  EXPECT_EQ(LayoutUnit(), container->scrollLeft());
  container->setScrollTop(LayoutUnit(27));
  container->setScrollLeft(LayoutUnit(28));
  document().view()->updateAllLifecyclePhases();

  LayoutBlock* target = toLayoutBlock(getLayoutObjectByElementId("target"));
  LayoutRect targetVisualRect = target->localVisualRect();
  // 140 = width(100) + box_shadow_offset_x(40)
  // 110 = height(90) + box_shadow_offset_y(20)
  EXPECT_EQ(LayoutRect(0, 0, 140, 110), targetVisualRect);
  LayoutRect rect = targetVisualRect;
  EXPECT_TRUE(target->mapToVisualRectInAncestorSpace(target, rect));
  EXPECT_EQ(LayoutRect(0, 0, 140, 110), rect);

  rect = targetVisualRect;
  EXPECT_TRUE(target->mapToVisualRectInAncestorSpace(container, rect));
  // Rect is not clipped by container's overflow clip.
  EXPECT_EQ(LayoutRect(10, 10, 140, 110), rect);
}
Example #24
0
TEST_F(LayoutObjectTest, DisplayInlineBlockCreateObject) {
  setBodyInnerHTML("<foo style='display:inline-block'></foo>");
  LayoutObject* layoutObject = document().body()->firstChild()->layoutObject();
  EXPECT_NE(nullptr, layoutObject);
  EXPECT_TRUE(layoutObject->isLayoutBlockFlow());
  EXPECT_TRUE(layoutObject->isInline());
}
Example #25
0
TEST_F(VisualRectMappingTest, LayoutInline) {
  document().setBaseURLOverride(KURL(ParsedURLString, "http://test.com"));
  setBodyInnerHTML(
      "<style>body { margin: 0; }</style>"
      "<div id='container' style='overflow: scroll; width: 50px; height: 50px'>"
      "  <span><img style='width: 20px; height: 100px'></span>"
      "  <span id=leaf></span></div>");

  LayoutBlock* container =
      toLayoutBlock(getLayoutObjectByElementId("container"));
  LayoutObject* leaf = container->lastChild();

  container->setScrollTop(LayoutUnit(50));
  LayoutRect originalRect(0, 60, 20, 80);
  LayoutRect rect = originalRect;
  EXPECT_TRUE(leaf->mapToVisualRectInAncestorSpace(container, rect));
  rect.move(-container->scrolledContentOffset());
  EXPECT_EQ(rect, LayoutRect(0, 10, 20, 80));

  rect = originalRect;
  EXPECT_TRUE(leaf->mapToVisualRectInAncestorSpace(&layoutView(), rect));
  EXPECT_EQ(rect, LayoutRect(0, 10, 20, 40));
  checkPaintInvalidationStateRectMapping(rect, originalRect, *leaf,
                                         layoutView(), layoutView());

  rect = LayoutRect(0, 60, 80, 0);
  EXPECT_TRUE(
      leaf->mapToVisualRectInAncestorSpace(container, rect, EdgeInclusive));
  rect.move(-container->scrolledContentOffset());
  EXPECT_EQ(rect, LayoutRect(0, 10, 80, 0));
}
Example #26
0
TEST_F(LayoutObjectTest,
       ContainingBlockAbsoluteLayoutObjectShouldBeLayoutView) {
  setBodyInnerHTML("<foo style='position:absolute'></foo>");
  LayoutObject* layoutObject =
      document().body()->layoutObject()->slowFirstChild();
  EXPECT_EQ(layoutObject->containingBlock(), layoutView());
}
Example #27
0
TEST_F(LayoutObjectTest, ContainingBlockAbsoluteLayoutObjectShouldBeNonStaticallyPositionedBlockAncestor)
{
    setBodyInnerHTML("<div style='position:relative'><bar style='position:absolute'></bar></div>");
    LayoutObject* containingBlocklayoutObject = document().body()->layoutObject()->slowFirstChild();
    LayoutObject* layoutObject = containingBlocklayoutObject->slowFirstChild();
    EXPECT_EQ(layoutObject->containingBlock(), containingBlocklayoutObject);
}
TEST_F(ImageQualityControllerTest, LowQualityFilterForLiveResize)
{
    MockTimer* mockTimer = new MockTimer(controller(), &ImageQualityController::highQualityRepaintTimerFired);
    controller()->setTimer(mockTimer);
    setBodyInnerHTML("<img src='myimage'></img>");
    LayoutImage* img = toLayoutImage(document().body()->firstChild()->layoutObject());

    RefPtr<TestImageLowQuality> testImage = adoptRef(new TestImageLowQuality);

    // Start a resize
    document().frame()->view()->willStartLiveResize();
    EXPECT_EQ(InterpolationLow, controller()->chooseInterpolationQuality(*img, testImage.get(), testImage.get(), LayoutSize(2, 2)));

    document().frame()->view()->willEndLiveResize();

    // End of live resize, but timer has not fired. Therefore paint at non-low quality.
    EXPECT_EQ(InterpolationMedium, controller()->chooseInterpolationQuality(*img, testImage.get(), testImage.get(), LayoutSize(3, 3)));

    // Start another resize
    document().frame()->view()->willStartLiveResize();
    EXPECT_EQ(InterpolationLow, controller()->chooseInterpolationQuality(*img, testImage.get(), testImage.get(), LayoutSize(3, 3)));

    // While still in resize, expire the timer.
    document().frame()->view()->willEndLiveResize();

    mockTimer->fire();
    // End of live resize, and timer has fired. Therefore paint at non-low quality, even though the size has changed.
    EXPECT_EQ(InterpolationMedium, controller()->chooseInterpolationQuality(*img, testImage.get(), testImage.get(), LayoutSize(4, 4)));
}
TEST_F(PaintPropertyTreeBuilderTest, TransformNodeDoesNotAffectEffectNodes)
{
    setBodyInnerHTML(
        "<div id='nodeWithOpacity' style='opacity: 0.6'>"
        "  <div id='childWithTransform' style='transform: translate3d(10px, 10px, 0px);'>"
        "    <div id='grandChildWithOpacity' style='opacity: 0.4'/>"
        "  </div"
        "</div>");

    LayoutObject& nodeWithOpacity = *document().getElementById("nodeWithOpacity")->layoutObject();
    ObjectPaintProperties* nodeWithOpacityProperties = nodeWithOpacity.objectPaintProperties();
    EXPECT_EQ(0.6f, nodeWithOpacityProperties->effect()->opacity());
    EXPECT_EQ(nullptr, nodeWithOpacityProperties->effect()->parent());
    EXPECT_EQ(nullptr, nodeWithOpacityProperties->transform());

    LayoutObject& childWithTransform = *document().getElementById("childWithTransform")->layoutObject();
    ObjectPaintProperties* childWithTransformProperties = childWithTransform.objectPaintProperties();
    EXPECT_EQ(nullptr, childWithTransformProperties->effect());
    EXPECT_EQ(TransformationMatrix().translate(10, 10), childWithTransformProperties->transform()->matrix());

    LayoutObject& grandChildWithOpacity = *document().getElementById("grandChildWithOpacity")->layoutObject();
    ObjectPaintProperties* grandChildWithOpacityProperties = grandChildWithOpacity.objectPaintProperties();
    EXPECT_EQ(0.4f, grandChildWithOpacityProperties->effect()->opacity());
    EXPECT_EQ(nodeWithOpacityProperties->effect(), grandChildWithOpacityProperties->effect()->parent());
    EXPECT_EQ(nullptr, grandChildWithOpacityProperties->transform());
}
Example #30
0
TEST_P(PrePaintTreeWalkTest, PropertyTreesRebuiltWithBorderInvalidation) {
  setBodyInnerHTML(
      "<style>"
      "  body { margin: 0; }"
      "  #transformed { transform: translate(100px, 100px); }"
      "  .border { border: 10px solid black; }"
      "</style>"
      "<div id='transformed'></div>");

  auto* transformedElement = document().getElementById("transformed");
  const auto* transformedProperties =
      transformedElement->layoutObject()->paintProperties();
  EXPECT_EQ(TransformationMatrix().translate(100, 100),
            transformedProperties->transform()->matrix());

  // Artifically change the transform node.
  const_cast<ObjectPaintProperties*>(transformedProperties)->clearTransform();
  EXPECT_EQ(nullptr, transformedProperties->transform());

  // Cause a paint invalidation.
  transformedElement->setAttribute(HTMLNames::classAttr, "border");
  document().view()->updateAllLifecyclePhases();

  // Should have changed back.
  EXPECT_EQ(TransformationMatrix().translate(100, 100),
            transformedProperties->transform()->matrix());
}