text:
namespace cc {
namespace {

static gfx::Rect ViewportInLayerSpace(
    const gfx::Transform& transform,
    const gfx::Size& device_viewport) {

  gfx::Transform inverse;
  if (!transform.GetInverse(&inverse))
    return gfx::Rect();

  gfx::RectF viewport_in_layer_space = MathUtil::ProjectClippedRect(
      inverse, gfx::RectF(gfx::Point(0, 0), device_viewport));
  return ToEnclosingRect(viewport_in_layer_space);
}

class TestablePictureLayerTiling : public PictureLayerTiling {
 public:
  using PictureLayerTiling::SetLiveTilesRect;
  using PictureLayerTiling::TileAt;

  static scoped_ptr<TestablePictureLayerTiling> Create(
      float contents_scale,
      scoped_refptr<RasterSource> raster_source,
      PictureLayerTilingClient* client,
      const LayerTreeSettings& settings) {
    return make_scoped_ptr(new TestablePictureLayerTiling(
        contents_scale, raster_source, client,
        settings.max_tiles_for_interest_area,
        settings.skewport_target_time_in_seconds,
        settings.skewport_extrapolation_limit_in_content_pixels));
  }

  gfx::Rect live_tiles_rect() const { return live_tiles_rect_; }

  using PictureLayerTiling::ComputeSkewport;
  using PictureLayerTiling::RemoveTileAt;

 protected:
  TestablePictureLayerTiling(float contents_scale,
                             scoped_refptr<RasterSource> raster_source,
                             PictureLayerTilingClient* client,
                             size_t max_tiles_for_interest_area,
                             float skewport_target_time,
                             int skewport_extrapolation_limit)
      : PictureLayerTiling(contents_scale,
                           raster_source,
                           client,
                           max_tiles_for_interest_area,
                           skewport_target_time,
                           skewport_extrapolation_limit) {}
};

class PictureLayerTilingIteratorTest : public testing::Test {
 public:
  PictureLayerTilingIteratorTest() {}
  ~PictureLayerTilingIteratorTest() override {}

  void Initialize(const gfx::Size& tile_size,
                  float contents_scale,
                  const gfx::Size& layer_bounds) {
    client_.SetTileSize(tile_size);
    client_.set_tree(PENDING_TREE);
    scoped_refptr<FakePicturePileImpl> pile =
        FakePicturePileImpl::CreateFilledPileWithDefaultTileSize(layer_bounds);
    tiling_ = TestablePictureLayerTiling::Create(contents_scale, pile, &client_,
                                                 LayerTreeSettings());
  }

  void SetLiveRectAndVerifyTiles(const gfx::Rect& live_tiles_rect) {
    tiling_->SetLiveTilesRect(live_tiles_rect);

    std::vector<Tile*> tiles = tiling_->AllTilesForTesting();
    for (std::vector<Tile*>::iterator iter = tiles.begin();
         iter != tiles.end();
         ++iter) {
      EXPECT_TRUE(live_tiles_rect.Intersects((*iter)->content_rect()));
    }
  }

  void VerifyTilesExactlyCoverRect(
      float rect_scale,
      const gfx::Rect& request_rect,
      const gfx::Rect& expect_rect) {
    EXPECT_TRUE(request_rect.Contains(expect_rect));

    // Iterators are not valid if this ratio is too large (i.e. the
    // tiling is too high-res for a low-res destination rect.)  This is an
    // artifact of snapping geometry to integer coordinates and then mapping
    // back to floating point texture coordinates.
    float dest_to_contents_scale = tiling_->contents_scale() / rect_scale;
    ASSERT_LE(dest_to_contents_scale, 2.0);

    Region remaining = expect_rect;
    for (PictureLayerTiling::CoverageIterator
             iter(tiling_.get(), rect_scale, request_rect);
         iter;
         ++iter) {
      // Geometry cannot overlap previous geometry at all
      gfx::Rect geometry = iter.geometry_rect();
      EXPECT_TRUE(expect_rect.Contains(geometry));
      EXPECT_TRUE(remaining.Contains(geometry));
      remaining.Subtract(geometry);

      // Sanity check that texture coords are within the texture rect.
      gfx::RectF texture_rect = iter.texture_rect();
      EXPECT_GE(texture_rect.x(), 0);
      EXPECT_GE(texture_rect.y(), 0);
      EXPECT_LE(texture_rect.right(), client_.TileSize().width());
      EXPECT_LE(texture_rect.bottom(), client_.TileSize().height());
    }

    // The entire rect must be filled by geometry from the tiling.
    EXPECT_TRUE(remaining.IsEmpty());
  }

  void VerifyTilesExactlyCoverRect(float rect_scale, const gfx::Rect& rect) {
    VerifyTilesExactlyCoverRect(rect_scale, rect, rect);
  }

  void VerifyTiles(
      float rect_scale,
      const gfx::Rect& rect,
      base::Callback<void(Tile* tile,
                          const gfx::Rect& geometry_rect)> callback) {
    VerifyTiles(tiling_.get(),
                rect_scale,
                rect,
                callback);
  }

  void VerifyTiles(
      PictureLayerTiling* tiling,
      float rect_scale,
      const gfx::Rect& rect,
      base::Callback<void(Tile* tile,
                          const gfx::Rect& geometry_rect)> callback) {
    Region remaining = rect;
    for (PictureLayerTiling::CoverageIterator iter(tiling, rect_scale, rect);
         iter;
         ++iter) {
      remaining.Subtract(iter.geometry_rect());
      callback.Run(*iter, iter.geometry_rect());
    }
    EXPECT_TRUE(remaining.IsEmpty());
  }

  void VerifyTilesCoverNonContainedRect(float rect_scale,
                                        const gfx::Rect& dest_rect) {
    float dest_to_contents_scale = tiling_->contents_scale() / rect_scale;
    gfx::Rect clamped_rect = gfx::ScaleToEnclosingRect(
        gfx::Rect(tiling_->tiling_size()), 1.f / dest_to_contents_scale);
    clamped_rect.Intersect(dest_rect);
    VerifyTilesExactlyCoverRect(rect_scale, dest_rect, clamped_rect);
  }

 protected:
  FakePictureLayerTilingClient client_;
  scoped_ptr<TestablePictureLayerTiling> tiling_;

 private:
  DISALLOW_COPY_AND_ASSIGN(PictureLayerTilingIteratorTest);
};

TEST_F(PictureLayerTilingIteratorTest, ResizeDeletesTiles) {
  // Verifies that a resize with invalidation for newly exposed pixels will
  // deletes tiles that intersect that invalidation.
  gfx::Size tile_size(100, 100);
  gfx::Size original_layer_size(10, 10);
  Initialize(tile_size, 1.f, original_layer_size);
  SetLiveRectAndVerifyTiles(gfx::Rect(original_layer_size));

  // Tiling only has one tile, since its total size is less than one.
  EXPECT_TRUE(tiling_->TileAt(0, 0));

  // Stop creating tiles so that any invalidations are left as holes.
  gfx::Size new_layer_size(200, 200);
  scoped_refptr<FakePicturePileImpl> pile =
      FakePicturePileImpl::CreateEmptyPileWithDefaultTileSize(new_layer_size);

  Region invalidation =
      SubtractRegions(gfx::Rect(tile_size), gfx::Rect(original_layer_size));
  tiling_->SetRasterSourceAndResize(pile);
  EXPECT_TRUE(tiling_->TileAt(0, 0));
  tiling_->Invalidate(invalidation);
  EXPECT_FALSE(tiling_->TileAt(0, 0));
}

TEST_F(PictureLayerTilingIteratorTest, CreateMissingTilesStaysInsideLiveRect) {
  // The tiling has three rows and columns.
  Initialize(gfx::Size(100, 100), 1.f, gfx::Size(250, 250));
  EXPECT_EQ(3, tiling_->TilingDataForTesting().num_tiles_x());
  EXPECT_EQ(3, tiling_->TilingDataForTesting().num_tiles_y());

  // The live tiles rect is at the very edge of the right-most and
  // bottom-most tiles. Their border pixels would still be inside the live
  // tiles rect, but the tiles should not exist just for that.
  int right = tiling_->TilingDataForTesting().TileBounds(2, 2).x();
  int bottom = tiling_->TilingDataForTesting().TileBounds(2, 2).y();

  SetLiveRectAndVerifyTiles(gfx::Rect(right, bottom));
  EXPECT_FALSE(tiling_->TileAt(2, 0));
  EXPECT_FALSE(tiling_->TileAt(2, 1));
  EXPECT_FALSE(tiling_->TileAt(2, 2));
  EXPECT_FALSE(tiling_->TileAt(1, 2));
  EXPECT_FALSE(tiling_->TileAt(0, 2));

  // Verify CreateMissingTilesInLiveTilesRect respects this.
  tiling_->CreateMissingTilesInLiveTilesRect();
  EXPECT_FALSE(tiling_->TileAt(2, 0));
  EXPECT_FALSE(tiling_->TileAt(2, 1));
  EXPECT_FALSE(tiling_->TileAt(2, 2));
  EXPECT_FALSE(tiling_->TileAt(1, 2));
  EXPECT_FALSE(tiling_->TileAt(0, 2));
}

TEST_F(PictureLayerTilingIteratorTest, ResizeTilingOverTileBorders) {
  // The tiling has four rows and three columns.
  Initialize(gfx::Size(100, 100), 1.f, gfx::Size(250, 350));
  EXPECT_EQ(3, tiling_->TilingDataForTesting().num_tiles_x());
  EXPECT_EQ(4, tiling_->TilingDataForTesting().num_tiles_y());

  // The live tiles rect covers the whole tiling.
  SetLiveRectAndVerifyTiles(gfx::Rect(250, 350));

  // Tiles in the bottom row and right column exist.
  EXPECT_TRUE(tiling_->TileAt(2, 0));
  EXPECT_TRUE(tiling_->TileAt(2, 1));
  EXPECT_TRUE(tiling_->TileAt(2, 2));
  EXPECT_TRUE(tiling_->TileAt(2, 3));
  EXPECT_TRUE(tiling_->TileAt(1, 3));
  EXPECT_TRUE(tiling_->TileAt(0, 3));

  int right = tiling_->TilingDataForTesting().TileBounds(2, 2).x();
  int bottom = tiling_->TilingDataForTesting().TileBounds(2, 3).y();

  // Shrink the tiling so that the last tile row/column is entirely in the
  // border pixels of the interior tiles. That row/column is removed.
  scoped_refptr<FakePicturePileImpl> pile =
      FakePicturePileImpl::CreateFilledPileWithDefaultTileSize(
          gfx::Size(right + 1, bottom + 1));
  tiling_->SetRasterSourceAndResize(pile);
  EXPECT_EQ(2, tiling_->TilingDataForTesting().num_tiles_x());
  EXPECT_EQ(3, tiling_->TilingDataForTesting().num_tiles_y());

  // The live tiles rect was clamped to the pile size.
  EXPECT_EQ(gfx::Rect(right + 1, bottom + 1), tiling_->live_tiles_rect());

  // Since the row/column is gone, the tiles should be gone too.
  EXPECT_FALSE(tiling_->TileAt(2, 0));
  EXPECT_FALSE(tiling_->TileAt(2, 1));
  EXPECT_FALSE(tiling_->TileAt(2, 2));
  EXPECT_FALSE(tiling_->TileAt(2, 3));
  EXPECT_FALSE(tiling_->TileAt(1, 3));
  EXPECT_FALSE(tiling_->TileAt(0, 3));

  // Growing outside the current right/bottom tiles border pixels should create
  // the tiles again, even though the live rect has not changed size.
  pile = FakePicturePileImpl::CreateFilledPileWithDefaultTileSize(
      gfx::Size(right + 2, bottom + 2));
  tiling_->SetRasterSourceAndResize(pile);
  EXPECT_EQ(3, tiling_->TilingDataForTesting().num_tiles_x());
  EXPECT_EQ(4, tiling_->TilingDataForTesting().num_tiles_y());

  // Not changed.
  EXPECT_EQ(gfx::Rect(right + 1, bottom + 1), tiling_->live_tiles_rect());

  // The last row/column tiles are inside the live tiles rect.
  EXPECT_TRUE(gfx::Rect(right + 1, bottom + 1).Intersects(
      tiling_->TilingDataForTesting().TileBounds(2, 0)));
  EXPECT_TRUE(gfx::Rect(right + 1, bottom + 1).Intersects(
      tiling_->TilingDataForTesting().TileBounds(0, 3)));

  EXPECT_TRUE(tiling_->TileAt(2, 0));
  EXPECT_TRUE(tiling_->TileAt(2, 1));
  EXPECT_TRUE(tiling_->TileAt(2, 2));
  EXPECT_TRUE(tiling_->TileAt(2, 3));
  EXPECT_TRUE(tiling_->TileAt(1, 3));
  EXPECT_TRUE(tiling_->TileAt(0, 3));
}

TEST_F(PictureLayerTilingIteratorTest, ResizeLiveTileRectOverTileBorders) {
  // The tiling has three rows and columns.
  Initialize(gfx::Size(100, 100), 1.f, gfx::Size(250, 350));
  EXPECT_EQ(3, tiling_->TilingDataForTesting().num_tiles_x());
  EXPECT_EQ(4, tiling_->TilingDataForTesting().num_tiles_y());

  // The live tiles rect covers the whole tiling.
  SetLiveRectAndVerifyTiles(gfx::Rect(250, 350));

  // Tiles in the bottom row and right column exist.
  EXPECT_TRUE(tiling_->TileAt(2, 0));
  EXPECT_TRUE(tiling_->TileAt(2, 1));
  EXPECT_TRUE(tiling_->TileAt(2, 2));
  EXPECT_TRUE(tiling_->TileAt(2, 3));
  EXPECT_TRUE(tiling_->TileAt(1, 3));
  EXPECT_TRUE(tiling_->TileAt(0, 3));

  // Shrink the live tiles rect to the very edge of the right-most and
  // bottom-most tiles. Their border pixels would still be inside the live
  // tiles rect, but the tiles should not exist just for that.
  int right = tiling_->TilingDataForTesting().TileBounds(2, 3).x();
  int bottom = tiling_->TilingDataForTesting().TileBounds(2, 3).y();

  SetLiveRectAndVerifyTiles(gfx::Rect(right, bottom));
  EXPECT_FALSE(tiling_->TileAt(2, 0));
  EXPECT_FALSE(tiling_->TileAt(2, 1));
  EXPECT_FALSE(tiling_->TileAt(2, 2));
  EXPECT_FALSE(tiling_->TileAt(2, 3));
  EXPECT_FALSE(tiling_->TileAt(1, 3));
  EXPECT_FALSE(tiling_->TileAt(0, 3));

  // Including the bottom row and right column again, should create the tiles.
  SetLiveRectAndVerifyTiles(gfx::Rect(right + 1, bottom + 1));
  EXPECT_TRUE(tiling_->TileAt(2, 0));
  EXPECT_TRUE(tiling_->TileAt(2, 1));
  EXPECT_TRUE(tiling_->TileAt(2, 2));
  EXPECT_TRUE(tiling_->TileAt(2, 3));
  EXPECT_TRUE(tiling_->TileAt(1, 2));
  EXPECT_TRUE(tiling_->TileAt(0, 2));

  // Shrink the live tiles rect to the very edge of the left-most and
  // top-most tiles. Their border pixels would still be inside the live
  // tiles rect, but the tiles should not exist just for that.
  int left = tiling_->TilingDataForTesting().TileBounds(0, 0).right();
  int top = tiling_->TilingDataForTesting().TileBounds(0, 0).bottom();

  SetLiveRectAndVerifyTiles(gfx::Rect(left, top, 250 - left, 350 - top));
  EXPECT_FALSE(tiling_->TileAt(0, 3));
  EXPECT_FALSE(tiling_->TileAt(0, 2));
  EXPECT_FALSE(tiling_->TileAt(0, 1));
  EXPECT_FALSE(tiling_->TileAt(0, 0));
  EXPECT_FALSE(tiling_->TileAt(1, 0));
  EXPECT_FALSE(tiling_->TileAt(2, 0));

  // Including the top row and left column again, should create the tiles.
  SetLiveRectAndVerifyTiles(
      gfx::Rect(left - 1, top - 1, 250 - left, 350 - top));
  EXPECT_TRUE(tiling_->TileAt(0, 3));
  EXPECT_TRUE(tiling_->TileAt(0, 2));
  EXPECT_TRUE(tiling_->TileAt(0, 1));
  EXPECT_TRUE(tiling_->TileAt(0, 0));
  EXPECT_TRUE(tiling_->TileAt(1, 0));
  EXPECT_TRUE(tiling_->TileAt(2, 0));
}

TEST_F(PictureLayerTilingIteratorTest, ResizeLiveTileRectOverSameTiles) {
  // The tiling has four rows and three columns.
  Initialize(gfx::Size(100, 100), 1.f, gfx::Size(250, 350));
  EXPECT_EQ(3, tiling_->TilingDataForTesting().num_tiles_x());
  EXPECT_EQ(4, tiling_->TilingDataForTesting().num_tiles_y());

  // The live tiles rect covers the whole tiling.
  SetLiveRectAndVerifyTiles(gfx::Rect(250, 350));

  // All tiles exist.
  for (int i = 0; i < 3; ++i) {
    for (int j = 0; j < 4; ++j)
      EXPECT_TRUE(tiling_->TileAt(i, j)) << i << "," << j;
  }

  // Shrink the live tiles rect, but still cover all the tiles.
  SetLiveRectAndVerifyTiles(gfx::Rect(1, 1, 249, 349));

  // All tiles still exist.
  for (int i = 0; i < 3; ++i) {
    for (int j = 0; j < 4; ++j)
      EXPECT_TRUE(tiling_->TileAt(i, j)) << i << "," << j;
  }

  // Grow the live tiles rect, but still cover all the same tiles.
  SetLiveRectAndVerifyTiles(gfx::Rect(0, 0, 250, 350));

  // All tiles still exist.
  for (int i = 0; i < 3; ++i) {
    for (int j = 0; j < 4; ++j)
      EXPECT_TRUE(tiling_->TileAt(i, j)) << i << "," << j;
  }
}

TEST_F(PictureLayerTilingIteratorTest, ResizeOverBorderPixelsDeletesTiles) {
  // Verifies that a resize with invalidation for newly exposed pixels will
  // deletes tiles that intersect that invalidation.
  gfx::Size tile_size(100, 100);
  gfx::Size original_layer_size(99, 99);
  Initialize(tile_size, 1.f, original_layer_size);
  SetLiveRectAndVerifyTiles(gfx::Rect(original_layer_size));

  // Tiling only has one tile, since its total size is less than one.
  EXPECT_TRUE(tiling_->TileAt(0, 0));

  // Stop creating tiles so that any invalidations are left as holes.
  scoped_refptr<FakePicturePileImpl> pile =
      FakePicturePileImpl::CreateEmptyPileWithDefaultTileSize(
          gfx::Size(200, 200));
  tiling_->SetRasterSourceAndResize(pile);

  Region invalidation =
      SubtractRegions(gfx::Rect(tile_size), gfx::Rect(original_layer_size));
  EXPECT_TRUE(tiling_->TileAt(0, 0));
  tiling_->Invalidate(invalidation);
  EXPECT_FALSE(tiling_->TileAt(0, 0));

  // The original tile was the same size after resize, but it would include new
  // border pixels.
  EXPECT_EQ(gfx::Rect(original_layer_size),
            tiling_->TilingDataForTesting().TileBounds(0, 0));
}

TEST_F(PictureLayerTilingIteratorTest, LiveTilesExactlyCoverLiveTileRect) {
  Initialize(gfx::Size(100, 100), 1.f, gfx::Size(1099, 801));
  SetLiveRectAndVerifyTiles(gfx::Rect(100, 100));
  SetLiveRectAndVerifyTiles(gfx::Rect(101, 99));
  SetLiveRectAndVerifyTiles(gfx::Rect(1099, 1));
  SetLiveRectAndVerifyTiles(gfx::Rect(1, 801));
  SetLiveRectAndVerifyTiles(gfx::Rect(1099, 1));
  SetLiveRectAndVerifyTiles(gfx::Rect(201, 800));
}

TEST_F(PictureLayerTilingIteratorTest, IteratorCoversLayerBoundsNoScale) {
  Initialize(gfx::Size(100, 100), 1.f, gfx::Size(1099, 801));
  VerifyTilesExactlyCoverRect(1, gfx::Rect());
  VerifyTilesExactlyCoverRect(1, gfx::Rect(0, 0, 1099, 801));
  VerifyTilesExactlyCoverRect(1, gfx::Rect(52, 83, 789, 412));

  // With borders, a size of 3x3 = 1 pixel of content.
  Initialize(gfx::Size(3, 3), 1.f, gfx::Size(10, 10));
  VerifyTilesExactlyCoverRect(1, gfx::Rect(0, 0, 1, 1));
  VerifyTilesExactlyCoverRect(1, gfx::Rect(0, 0, 2, 2));
  VerifyTilesExactlyCoverRect(1, gfx::Rect(1, 1, 2, 2));
  VerifyTilesExactlyCoverRect(1, gfx::Rect(3, 2, 5, 2));
}

TEST_F(PictureLayerTilingIteratorTest, IteratorCoversLayerBoundsTilingScale) {
  Initialize(gfx::Size(200, 100), 2.0f, gfx::Size(1005, 2010));
  VerifyTilesExactlyCoverRect(1, gfx::Rect());
  VerifyTilesExactlyCoverRect(1, gfx::Rect(0, 0, 1005, 2010));
  VerifyTilesExactlyCoverRect(1, gfx::Rect(50, 112, 512, 381));

  Initialize(gfx::Size(3, 3), 2.0f, gfx::Size(10, 10));
  VerifyTilesExactlyCoverRect(1, gfx::Rect());
  VerifyTilesExactlyCoverRect(1, gfx::Rect(0, 0, 1, 1));
  VerifyTilesExactlyCoverRect(1, gfx::Rect(0, 0, 2, 2));
  VerifyTilesExactlyCoverRect(1, gfx::Rect(1, 1, 2, 2));
  VerifyTilesExactlyCoverRect(1, gfx::Rect(3, 2, 5, 2));

  Initialize(gfx::Size(100, 200), 0.5f, gfx::Size(1005, 2010));
  VerifyTilesExactlyCoverRect(1, gfx::Rect(0, 0, 1005, 2010));
  VerifyTilesExactlyCoverRect(1, gfx::Rect(50, 112, 512, 381));

  Initialize(gfx::Size(150, 250), 0.37f, gfx::Size(1005, 2010));
  VerifyTilesExactlyCoverRect(1, gfx::Rect(0, 0, 1005, 2010));
  VerifyTilesExactlyCoverRect(1, gfx::Rect(50, 112, 512, 381));

  Initialize(gfx::Size(312, 123), 0.01f, gfx::Size(1005, 2010));
  VerifyTilesExactlyCoverRect(1, gfx::Rect(0, 0, 1005, 2010));
  VerifyTilesExactlyCoverRect(1, gfx::Rect(50, 112, 512, 381));
}

TEST_F(PictureLayerTilingIteratorTest, IteratorCoversLayerBoundsBothScale) {
  Initialize(gfx::Size(50, 50), 4.0f, gfx::Size(800, 600));
  VerifyTilesExactlyCoverRect(2.0f, gfx::Rect());
  VerifyTilesExactlyCoverRect(2.0f, gfx::Rect(0, 0, 1600, 1200));
  VerifyTilesExactlyCoverRect(2.0f, gfx::Rect(512, 365, 253, 182));

  float scale = 6.7f;
  gfx::Size bounds(800, 600);
  gfx::Rect full_rect(gfx::ToCeiledSize(gfx::ScaleSize(bounds, scale)));
  Initialize(gfx::Size(256, 512), 5.2f, bounds);
  VerifyTilesExactlyCoverRect(scale, full_rect);
  VerifyTilesExactlyCoverRect(scale, gfx::Rect(2014, 1579, 867, 1033));
}

TEST_F(PictureLayerTilingIteratorTest, IteratorEmptyRect) {
  Initialize(gfx::Size(100, 100), 1.0f, gfx::Size(800, 600));

  gfx::Rect empty;
  PictureLayerTiling::CoverageIterator iter(tiling_.get(), 1.0f, empty);
  EXPECT_FALSE(iter);
}

TEST_F(PictureLayerTilingIteratorTest, NonIntersectingRect) {
  Initialize(gfx::Size(100, 100), 1.0f, gfx::Size(800, 600));
  gfx::Rect non_intersecting(1000, 1000, 50, 50);
  PictureLayerTiling::CoverageIterator iter(tiling_.get(), 1, non_intersecting);
  EXPECT_FALSE(iter);
}

TEST_F(PictureLayerTilingIteratorTest, LayerEdgeTextureCoordinates) {
  Initialize(gfx::Size(300, 300), 1.0f, gfx::Size(256, 256));
  // All of these sizes are 256x256, scaled and ceiled.
  VerifyTilesExactlyCoverRect(1.0f, gfx::Rect(0, 0, 256, 256));
  VerifyTilesExactlyCoverRect(0.8f, gfx::Rect(0, 0, 205, 205));
  VerifyTilesExactlyCoverRect(1.2f, gfx::Rect(0, 0, 308, 308));
}

TEST_F(PictureLayerTilingIteratorTest, NonContainedDestRect) {
  Initialize(gfx::Size(100, 100), 1.0f, gfx::Size(400, 400));

  // Too large in all dimensions
  VerifyTilesCoverNonContainedRect(1.0f, gfx::Rect(-1000, -1000, 2000, 2000));
  VerifyTilesCoverNonContainedRect(1.5f, gfx::Rect(-1000, -1000, 2000, 2000));
  VerifyTilesCoverNonContainedRect(0.5f, gfx::Rect(-1000, -1000, 2000, 2000));

  // Partially covering content, but too large
  VerifyTilesCoverNonContainedRect(1.0f, gfx::Rect(-1000, 100, 2000, 100));
  VerifyTilesCoverNonContainedRect(1.5f, gfx::Rect(-1000, 100, 2000, 100));
  VerifyTilesCoverNonContainedRect(0.5f, gfx::Rect(-1000, 100, 2000, 100));
}

TEST(PictureLayerTilingTest, SkewportLimits) {
  FakePictureLayerTilingClient client;
  client.set_tree(ACTIVE_TREE);

  gfx::Rect viewport(0, 0, 100, 100);
  gfx::Size layer_bounds(200, 200);

  client.SetTileSize(gfx::Size(100, 100));
  LayerTreeSettings settings;
  settings.max_tiles_for_interest_area = 10000;
  settings.skewport_extrapolation_limit_in_content_pixels = 75;

  scoped_refptr<FakePicturePileImpl> pile =
      FakePicturePileImpl::CreateFilledPileWithDefaultTileSize(layer_bounds);
  scoped_ptr<TestablePictureLayerTiling> tiling =
      TestablePictureLayerTiling::Create(1.0f, pile, &client, settings);

  tiling->ComputeTilePriorityRects(viewport, 1.f, 1.0, Occlusion());

  // Move viewport down 50 pixels in 0.5 seconds.
  gfx::Rect down_skewport =
      tiling->ComputeSkewport(1.5, gfx::Rect(0, 50, 100, 100));

  EXPECT_EQ(0, down_skewport.x());
  EXPECT_EQ(50, down_skewport.y());
  EXPECT_EQ(100, down_skewport.width());
  EXPECT_EQ(175, down_skewport.height());
  EXPECT_TRUE(down_skewport.Contains(gfx::Rect(0, 50, 100, 100)));

  // Move viewport down 50 and right 10 pixels.
  gfx::Rect down_right_skewport =
      tiling->ComputeSkewport(1.5, gfx::Rect(10, 50, 100, 100));

  EXPECT_EQ(10, down_right_skewport.x());
  EXPECT_EQ(50, down_right_skewport.y());
  EXPECT_EQ(120, down_right_skewport.width());
  EXPECT_EQ(175, down_right_skewport.height());
  EXPECT_TRUE(down_right_skewport.Contains(gfx::Rect(10, 50, 100, 100)));

  // Move viewport left.
  gfx::Rect left_skewport =
      tiling->ComputeSkewport(1.5, gfx::Rect(-50, 0, 100, 100));

  EXPECT_EQ(-125, left_skewport.x());
  EXPECT_EQ(0, left_skewport.y());
  EXPECT_EQ(175, left_skewport.width());
  EXPECT_EQ(100, left_skewport.height());
  EXPECT_TRUE(left_skewport.Contains(gfx::Rect(-50, 0, 100, 100)));

  // Expand viewport.
  gfx::Rect expand_skewport =
      tiling->ComputeSkewport(1.5, gfx::Rect(-50, -50, 200, 200));

  // x and y moved by -75 (-50 - 75 = -125).
  // right side and bottom side moved by 75 [(350 - 125) - (200 - 50) = 75].
  EXPECT_EQ(-125, expand_skewport.x());
  EXPECT_EQ(-125, expand_skewport.y());
  EXPECT_EQ(350, expand_skewport.width());
  EXPECT_EQ(350, expand_skewport.height());
  EXPECT_TRUE(expand_skewport.Contains(gfx::Rect(-50, -50, 200, 200)));

  // Expand the viewport past the limit.
  gfx::Rect big_expand_skewport =
      tiling->ComputeSkewport(1.5, gfx::Rect(-500, -500, 1500, 1500));

  EXPECT_EQ(-575, big_expand_skewport.x());
  EXPECT_EQ(-575, big_expand_skewport.y());
  EXPECT_EQ(1650, big_expand_skewport.width());
  EXPECT_EQ(1650, big_expand_skewport.height());
  EXPECT_TRUE(big_expand_skewport.Contains(gfx::Rect(-500, -500, 1500, 1500)));
}

TEST(PictureLayerTilingTest, ComputeSkewport) {
  FakePictureLayerTilingClient client;

  gfx::Rect viewport(0, 0, 100, 100);
  gfx::Size layer_bounds(200, 200);

  client.SetTileSize(gfx::Size(100, 100));
  client.set_tree(ACTIVE_TREE);

  scoped_refptr<FakePicturePileImpl> pile =
      FakePicturePileImpl::CreateFilledPileWithDefaultTileSize(layer_bounds);
  scoped_ptr<TestablePictureLayerTiling> tiling =
      TestablePictureLayerTiling::Create(1.0f, pile, &client,
                                         LayerTreeSettings());

  tiling->ComputeTilePriorityRects(viewport, 1.f, 1.0, Occlusion());

  // Move viewport down 50 pixels in 0.5 seconds.
  gfx::Rect down_skewport =
      tiling->ComputeSkewport(1.5, gfx::Rect(0, 50, 100, 100));

  EXPECT_EQ(0, down_skewport.x());
  EXPECT_EQ(50, down_skewport.y());
  EXPECT_EQ(100, down_skewport.width());
  EXPECT_EQ(200, down_skewport.height());

  // Shrink viewport.
  gfx::Rect shrink_skewport =
      tiling->ComputeSkewport(1.5, gfx::Rect(25, 25, 50, 50));

  EXPECT_EQ(25, shrink_skewport.x());
  EXPECT_EQ(25, shrink_skewport.y());
  EXPECT_EQ(50, shrink_skewport.width());
  EXPECT_EQ(50, shrink_skewport.height());

  // Move viewport down 50 and right 10 pixels.
  gfx::Rect down_right_skewport =
      tiling->ComputeSkewport(1.5, gfx::Rect(10, 50, 100, 100));

  EXPECT_EQ(10, down_right_skewport.x());
  EXPECT_EQ(50, down_right_skewport.y());
  EXPECT_EQ(120, down_right_skewport.width());
  EXPECT_EQ(200, down_right_skewport.height());

  // Move viewport left.
  gfx::Rect left_skewport =
      tiling->ComputeSkewport(1.5, gfx::Rect(-20, 0, 100, 100));

  EXPECT_EQ(-60, left_skewport.x());
  EXPECT_EQ(0, left_skewport.y());
  EXPECT_EQ(140, left_skewport.width());
  EXPECT_EQ(100, left_skewport.height());

  // Expand viewport in 0.2 seconds.
  gfx::Rect expanded_skewport =
      tiling->ComputeSkewport(1.2, gfx::Rect(-5, -5, 110, 110));

  EXPECT_EQ(-30, expanded_skewport.x());
  EXPECT_EQ(-30, expanded_skewport.y());
  EXPECT_EQ(160, expanded_skewport.width());
  EXPECT_EQ(160, expanded_skewport.height());
}

TEST(PictureLayerTilingTest, ViewportDistanceWithScale) {
  FakePictureLayerTilingClient client;

  gfx::Rect viewport(0, 0, 100, 100);
  gfx::Size layer_bounds(1500, 1500);

  client.SetTileSize(gfx::Size(10, 10));
  client.set_tree(ACTIVE_TREE);
  LayerTreeSettings settings;
  settings.max_tiles_for_interest_area = 10000;

  // Tiling at 0.25 scale: this should create 47x47 tiles of size 10x10.
  // The reason is that each tile has a one pixel border, so tile at (1, 2)
  // for instance begins at (8, 16) pixels. So tile at (46, 46) will begin at
  // (368, 368) and extend to the end of 1500 * 0.25 = 375 edge of the
  // tiling.
  scoped_refptr<FakePicturePileImpl> pile =
      FakePicturePileImpl::CreateFilledPileWithDefaultTileSize(layer_bounds);
  scoped_ptr<TestablePictureLayerTiling> tiling =
      TestablePictureLayerTiling::Create(0.25f, pile, &client, settings);
  gfx::Rect viewport_in_content_space =
      gfx::ToEnclosedRect(gfx::ScaleRect(viewport, 0.25f));

  tiling->ComputeTilePriorityRects(viewport, 1.f, 1.0, Occlusion());
  tiling->UpdateAllTilePrioritiesForTesting();

  gfx::Rect soon_rect = viewport;
  soon_rect.Inset(-312.f, -312.f, -312.f, -312.f);
  gfx::Rect soon_rect_in_content_space =
      gfx::ToEnclosedRect(gfx::ScaleRect(soon_rect, 0.25f));

  // Sanity checks.
  for (int i = 0; i < 47; ++i) {
    for (int j = 0; j < 47; ++j) {
      EXPECT_TRUE(tiling->TileAt(i, j)) << "i: " << i << " j: " << j;
    }
  }
  for (int i = 0; i < 47; ++i) {
    EXPECT_FALSE(tiling->TileAt(i, 47)) << "i: " << i;
    EXPECT_FALSE(tiling->TileAt(47, i)) << "i: " << i;
  }

  // No movement in the viewport implies that tiles will either be NOW
  // or EVENTUALLY, with the exception of tiles that are between 0 and 312
  // pixels away from the viewport, which will be in the SOON bin.
  bool have_now = false;
  bool have_eventually = false;
  bool have_soon = false;
  for (int i = 0; i < 47; ++i) {
    for (int j = 0; j < 47; ++j) {
      Tile* tile = tiling->TileAt(i, j);
      TilePriority priority = tile->priority(ACTIVE_TREE);

      gfx::Rect tile_rect = tiling->TilingDataForTesting().TileBounds(i, j);
      if (viewport_in_content_space.Intersects(tile_rect)) {
        EXPECT_EQ(TilePriority::NOW, priority.priority_bin);
        EXPECT_FLOAT_EQ(0.f, priority.distance_to_visible);
        have_now = true;
      } else if (soon_rect_in_content_space.Intersects(tile_rect)) {
        EXPECT_EQ(TilePriority::SOON, priority.priority_bin);
        have_soon = true;
      } else {
        EXPECT_EQ(TilePriority::EVENTUALLY, priority.priority_bin);
        EXPECT_GT(priority.distance_to_visible, 0.f);
        have_eventually = true;
      }
    }
  }

  EXPECT_TRUE(have_now);
  EXPECT_TRUE(have_soon);
  EXPECT_TRUE(have_eventually);

  // Spot check some distances.
  // Tile at 5, 1 should begin at 41x9 in content space (without borders),
  // so the distance to a viewport that ends at 25x25 in content space
  // should be 17 (41 - 25 + 1). In layer space, then that should be
  // 17 / 0.25 = 68 pixels.

  // We can verify that the content rect (with borders) is one pixel off
  // 41,9 8x8 on all sides.
  EXPECT_EQ(tiling->TileAt(5, 1)->content_rect().ToString(), "40,8 10x10");

  TilePriority priority = tiling->TileAt(5, 1)->priority(ACTIVE_TREE);
  EXPECT_FLOAT_EQ(68.f, priority.distance_to_visible);

  priority = tiling->TileAt(2, 5)->priority(ACTIVE_TREE);
  EXPECT_FLOAT_EQ(68.f, priority.distance_to_visible);

  priority = tiling->TileAt(3, 4)->priority(ACTIVE_TREE);
  EXPECT_FLOAT_EQ(40.f, priority.distance_to_visible);

  // Move the viewport down 40 pixels.
  viewport = gfx::Rect(0, 40, 100, 100);
  viewport_in_content_space =
      gfx::ToEnclosedRect(gfx::ScaleRect(viewport, 0.25f));
  gfx::Rect skewport = tiling->ComputeSkewport(2.0, viewport_in_content_space);

  soon_rect = viewport;
  soon_rect.Inset(-312.f, -312.f, -312.f, -312.f);
  soon_rect_in_content_space =
      gfx::ToEnclosedRect(gfx::ScaleRect(soon_rect, 0.25f));

  EXPECT_EQ(0, skewport.x());
  EXPECT_EQ(10, skewport.y());
  EXPECT_EQ(25, skewport.width());
  EXPECT_EQ(35, skewport.height());

  tiling->ComputeTilePriorityRects(viewport, 1.f, 2.0, Occlusion());
  tiling->UpdateAllTilePrioritiesForTesting();

  have_now = false;
  have_eventually = false;
  have_soon = false;

  // Viewport moved, so we expect to find some NOW tiles, some SOON tiles and
  // some EVENTUALLY tiles.
  for (int i = 0; i < 47; ++i) {
    for (int j = 0; j < 47; ++j) {
      Tile* tile = tiling->TileAt(i, j);
      TilePriority priority = tile->priority(ACTIVE_TREE);

      gfx::Rect tile_rect = tiling->TilingDataForTesting().TileBounds(i, j);
      if (viewport_in_content_space.Intersects(tile_rect)) {
        EXPECT_EQ(TilePriority::NOW, priority.priority_bin) << "i: " << i
                                                            << " j: " << j;
        EXPECT_FLOAT_EQ(0.f, priority.distance_to_visible) << "i: " << i
                                                           << " j: " << j;
        have_now = true;
      } else if (skewport.Intersects(tile_rect) ||
                 soon_rect_in_content_space.Intersects(tile_rect)) {
        EXPECT_EQ(TilePriority::SOON, priority.priority_bin) << "i: " << i
                                                             << " j: " << j;
        EXPECT_GT(priority.distance_to_visible, 0.f) << "i: " << i
                                                     << " j: " << j;
        have_soon = true;
      } else {
        EXPECT_EQ(TilePriority::EVENTUALLY, priority.priority_bin)
            << "i: " << i << " j: " << j;
        EXPECT_GT(priority.distance_to_visible, 0.f) << "i: " << i
                                                     << " j: " << j;
        have_eventually = true;
      }
    }
  }

  EXPECT_TRUE(have_now);
  EXPECT_TRUE(have_soon);
  EXPECT_TRUE(have_eventually);

  priority = tiling->TileAt(5, 1)->priority(ACTIVE_TREE);
  EXPECT_FLOAT_EQ(68.f, priority.distance_to_visible);

  priority = tiling->TileAt(2, 5)->priority(ACTIVE_TREE);
  EXPECT_FLOAT_EQ(28.f, priority.distance_to_visible);

  priority = tiling->TileAt(3, 4)->priority(ACTIVE_TREE);
  EXPECT_FLOAT_EQ(4.f, priority.distance_to_visible);

  // Change the underlying layer scale.
  tiling->ComputeTilePriorityRects(viewport, 2.0f, 3.0, Occlusion());
  tiling->UpdateAllTilePrioritiesForTesting();

  priority = tiling->TileAt(5, 1)->priority(ACTIVE_TREE);
  EXPECT_FLOAT_EQ(136.f, priority.distance_to_visible);

  priority = tiling->TileAt(2, 5)->priority(ACTIVE_TREE);
  EXPECT_FLOAT_EQ(56.f, priority.distance_to_visible);

  priority = tiling->TileAt(3, 4)->priority(ACTIVE_TREE);
  EXPECT_FLOAT_EQ(8.f, priority.distance_to_visible);

  // Test additional scales.
  tiling = TestablePictureLayerTiling::Create(0.2f, pile, &client,
                                              LayerTreeSettings());
  tiling->ComputeTilePriorityRects(viewport, 1.0f, 4.0, Occlusion());
  tiling->UpdateAllTilePrioritiesForTesting();

  priority = tiling->TileAt(5, 1)->priority(ACTIVE_TREE);
  EXPECT_FLOAT_EQ(110.f, priority.distance_to_visible);

  priority = tiling->TileAt(2, 5)->priority(ACTIVE_TREE);
  EXPECT_FLOAT_EQ(70.f, priority.distance_to_visible);

  priority = tiling->TileAt(3, 4)->priority(ACTIVE_TREE);
  EXPECT_FLOAT_EQ(60.f, priority.distance_to_visible);

  tiling->ComputeTilePriorityRects(viewport, 0.5f, 5.0, Occlusion());
  tiling->UpdateAllTilePrioritiesForTesting();

  priority = tiling->TileAt(5, 1)->priority(ACTIVE_TREE);
  EXPECT_FLOAT_EQ(55.f, priority.distance_to_visible);

  priority = tiling->TileAt(2, 5)->priority(ACTIVE_TREE);
  EXPECT_FLOAT_EQ(35.f, priority.distance_to_visible);

  priority = tiling->TileAt(3, 4)->priority(ACTIVE_TREE);
  EXPECT_FLOAT_EQ(30.f, priority.distance_to_visible);
}

TEST(PictureLayerTilingTest, ExpandRectEqual) {
  gfx::Rect in(40, 50, 100, 200);
  gfx::Rect bounds(-1000, -1000, 10000, 10000);
  int64 target_area = 100 * 200;
  gfx::Rect out = PictureLayerTiling::ExpandRectEquallyToAreaBoundedBy(
      in, target_area, bounds, NULL);
  EXPECT_EQ(in.ToString(), out.ToString());
}

TEST(PictureLayerTilingTest, ExpandRectSmaller) {
  gfx::Rect in(40, 50, 100, 200);
  gfx::Rect bounds(-1000, -1000, 10000, 10000);
  int64 target_area = 100 * 100;
  gfx::Rect out = PictureLayerTiling::ExpandRectEquallyToAreaBoundedBy(
      in, target_area, bounds, NULL);
  EXPECT_EQ(out.bottom() - in.bottom(), in.y() - out.y());
  EXPECT_EQ(out.right() - in.right(), in.x() - out.x());
  EXPECT_EQ(out.width() - in.width(), out.height() - in.height());

  // |in| represents the visible rect, and |out| represents the eventually rect.
  // If the eventually rect doesn't contain the visible rect, we will start
  // losing tiles.
  EXPECT_TRUE(out.Contains(in));
  EXPECT_TRUE(bounds.Contains(out));
}

TEST(PictureLayerTilingTest, ExpandRectUnbounded) {
  gfx::Rect in(40, 50, 100, 200);
  gfx::Rect bounds(-1000, -1000, 10000, 10000);
  int64 target_area = 200 * 200;
  gfx::Rect out = PictureLayerTiling::ExpandRectEquallyToAreaBoundedBy(
      in, target_area, bounds, NULL);
  EXPECT_EQ(out.bottom() - in.bottom(), in.y() - out.y());
  EXPECT_EQ(out.right() - in.right(), in.x() - out.x());
  EXPECT_EQ(out.width() - in.width(), out.height() - in.height());
  EXPECT_NEAR(200 * 200, out.width() * out.height(), 100);
  EXPECT_TRUE(bounds.Contains(out));
}

TEST(PictureLayerTilingTest, ExpandRectBoundedSmaller) {
  gfx::Rect in(40, 50, 100, 200);
  gfx::Rect bounds(50, 60, 40, 30);
  int64 target_area = 200 * 200;
  gfx::Rect out = PictureLayerTiling::ExpandRectEquallyToAreaBoundedBy(
      in, target_area, bounds, NULL);
  EXPECT_EQ(bounds.ToString(), out.ToString());
}

TEST(PictureLayerTilingTest, ExpandRectBoundedEqual) {
  gfx::Rect in(40, 50, 100, 200);
  gfx::Rect bounds = in;
  int64 target_area = 200 * 200;
  gfx::Rect out = PictureLayerTiling::ExpandRectEquallyToAreaBoundedBy(
      in, target_area, bounds, NULL);
  EXPECT_EQ(bounds.ToString(), out.ToString());
}

TEST(PictureLayerTilingTest, ExpandRectBoundedSmallerStretchVertical) {
  gfx::Rect in(40, 50, 100, 200);
  gfx::Rect bounds(45, 0, 90, 300);
  int64 target_area = 200 * 200;
  gfx::Rect out = PictureLayerTiling::ExpandRectEquallyToAreaBoundedBy(
      in, target_area, bounds, NULL);
  EXPECT_EQ(bounds.ToString(), out.ToString());
}

TEST(PictureLayerTilingTest, ExpandRectBoundedEqualStretchVertical) {
  gfx::Rect in(40, 50, 100, 200);
  gfx::Rect bounds(40, 0, 100, 300);
  int64 target_area = 200 * 200;
  gfx::Rect out = PictureLayerTiling::ExpandRectEquallyToAreaBoundedBy(
      in, target_area, bounds, NULL);
  EXPECT_EQ(bounds.ToString(), out.ToString());
}

TEST(PictureLayerTilingTest, ExpandRectBoundedSmallerStretchHorizontal) {
  gfx::Rect in(40, 50, 100, 200);
  gfx::Rect bounds(0, 55, 180, 190);
  int64 target_area = 200 * 200;
  gfx::Rect out = PictureLayerTiling::ExpandRectEquallyToAreaBoundedBy(
      in, target_area, bounds, NULL);
  EXPECT_EQ(bounds.ToString(), out.ToString());
}

TEST(PictureLayerTilingTest, ExpandRectBoundedEqualStretchHorizontal) {
  gfx::Rect in(40, 50, 100, 200);
  gfx::Rect bounds(0, 50, 180, 200);
  int64 target_area = 200 * 200;
  gfx::Rect out = PictureLayerTiling::ExpandRectEquallyToAreaBoundedBy(
      in, target_area, bounds, NULL);
  EXPECT_EQ(bounds.ToString(), out.ToString());
}

TEST(PictureLayerTilingTest, ExpandRectBoundedLeft) {
  gfx::Rect in(40, 50, 100, 200);
  gfx::Rect bounds(20, -1000, 10000, 10000);
  int64 target_area = 200 * 200;
  gfx::Rect out = PictureLayerTiling::ExpandRectEquallyToAreaBoundedBy(
      in, target_area, bounds, NULL);
  EXPECT_EQ(out.bottom() - in.bottom(), in.y() - out.y());
  EXPECT_EQ(out.bottom() - in.bottom(), out.right() - in.right());
  EXPECT_LE(out.width() * out.height(), target_area);
  EXPECT_GT(out.width() * out.height(),
            target_area - out.width() - out.height() * 2);
  EXPECT_TRUE(bounds.Contains(out));
}

TEST(PictureLayerTilingTest, ExpandRectBoundedRight) {
  gfx::Rect in(40, 50, 100, 200);
  gfx::Rect bounds(-1000, -1000, 1000+120, 10000);
  int64 target_area = 200 * 200;
  gfx::Rect out = PictureLayerTiling::ExpandRectEquallyToAreaBoundedBy(
      in, target_area, bounds, NULL);
  EXPECT_EQ(out.bottom() - in.bottom(), in.y() - out.y());
  EXPECT_EQ(out.bottom() - in.bottom(), in.x() - out.x());
  EXPECT_LE(out.width() * out.height(), target_area);
  EXPECT_GT(out.width() * out.height(),
            target_area - out.width() - out.height() * 2);
  EXPECT_TRUE(bounds.Contains(out));
}

TEST(PictureLayerTilingTest, ExpandRectBoundedTop) {
  gfx::Rect in(40, 50, 100, 200);
  gfx::Rect bounds(-1000, 30, 10000, 10000);
  int64 target_area = 200 * 200;
  gfx::Rect out = PictureLayerTiling::ExpandRectEquallyToAreaBoundedBy(
      in, target_area, bounds, NULL);
  EXPECT_EQ(out.right() - in.right(), in.x() - out.x());
  EXPECT_EQ(out.right() - in.right(), out.bottom() - in.bottom());
  EXPECT_LE(out.width() * out.height(), target_area);
  EXPECT_GT(out.width() * out.height(),
            target_area - out.width() * 2 - out.height());
  EXPECT_TRUE(bounds.Contains(out));
}

TEST(PictureLayerTilingTest, ExpandRectBoundedBottom) {
  gfx::Rect in(40, 50, 100, 200);
  gfx::Rect bounds(-1000, -1000, 10000, 1000 + 220);
  int64 target_area = 200 * 200;
  gfx::Rect out = PictureLayerTiling::ExpandRectEquallyToAreaBoundedBy(
      in, target_area, bounds, NULL);
  EXPECT_EQ(out.right() - in.right(), in.x() - out.x());
  EXPECT_EQ(out.right() - in.right(), in.y() - out.y());
  EXPECT_LE(out.width() * out.height(), target_area);
  EXPECT_GT(out.width() * out.height(),
            target_area - out.width() * 2 - out.height());
  EXPECT_TRUE(bounds.Contains(out));
}

TEST(PictureLayerTilingTest, ExpandRectSquishedHorizontally) {
  gfx::Rect in(40, 50, 100, 200);
  gfx::Rect bounds(0, -4000, 100+40+20, 100000);
  int64 target_area = 400 * 400;
  gfx::Rect out = PictureLayerTiling::ExpandRectEquallyToAreaBoundedBy(
      in, target_area, bounds, NULL);
  EXPECT_EQ(20, out.right() - in.right());
  EXPECT_EQ(40, in.x() - out.x());
  EXPECT_EQ(out.bottom() - in.bottom(), in.y() - out.y());
  EXPECT_LE(out.width() * out.height(), target_area);
  EXPECT_GT(out.width() * out.height(),
            target_area - out.width() * 2);
  EXPECT_TRUE(bounds.Contains(out));
}

TEST(PictureLayerTilingTest, ExpandRectSquishedVertically) {
  gfx::Rect in(40, 50, 100, 200);
  gfx::Rect bounds(-4000, 0, 100000, 200+50+30);
  int64 target_area = 400 * 400;
  gfx::Rect out = PictureLayerTiling::ExpandRectEquallyToAreaBoundedBy(
      in, target_area, bounds, NULL);
  EXPECT_EQ(30, out.bottom() - in.bottom());
  EXPECT_EQ(50, in.y() - out.y());
  EXPECT_EQ(out.right() - in.right(), in.x() - out.x());
  EXPECT_LE(out.width() * out.height(), target_area);
  EXPECT_GT(out.width() * out.height(),
            target_area - out.height() * 2);
  EXPECT_TRUE(bounds.Contains(out));
}

TEST(PictureLayerTilingTest, ExpandRectOutOfBoundsFarAway) {
  gfx::Rect in(400, 500, 100, 200);
  gfx::Rect bounds(0, 0, 10, 10);
  int64 target_area = 400 * 400;
  gfx::Rect out = PictureLayerTiling::ExpandRectEquallyToAreaBoundedBy(
      in, target_area, bounds, NULL);
  EXPECT_TRUE(out.IsEmpty());
}

TEST(PictureLayerTilingTest, ExpandRectOutOfBoundsExpandedFullyCover) {
  gfx::Rect in(40, 50, 100, 100);
  gfx::Rect bounds(0, 0, 10, 10);
  int64 target_area = 400 * 400;
  gfx::Rect out = PictureLayerTiling::ExpandRectEquallyToAreaBoundedBy(
      in, target_area, bounds, NULL);
  EXPECT_EQ(bounds.ToString(), out.ToString());
}

TEST(PictureLayerTilingTest, ExpandRectOutOfBoundsExpandedPartlyCover) {
  gfx::Rect in(600, 600, 100, 100);
  gfx::Rect bounds(0, 0, 500, 500);
  int64 target_area = 400 * 400;
  gfx::Rect out = PictureLayerTiling::ExpandRectEquallyToAreaBoundedBy(
      in, target_area, bounds, NULL);
  EXPECT_EQ(bounds.right(), out.right());
  EXPECT_EQ(bounds.bottom(), out.bottom());
  EXPECT_LE(out.width() * out.height(), target_area);
  EXPECT_GT(out.width() * out.height(),
            target_area - out.width() - out.height());
  EXPECT_TRUE(bounds.Contains(out));
}

TEST(PictureLayerTilingTest, EmptyStartingRect) {
  // If a layer has a non-invertible transform, then the starting rect
  // for the layer would be empty.
  gfx::Rect in(40, 40, 0, 0);
  gfx::Rect bounds(0, 0, 10, 10);
  int64 target_area = 400 * 400;
  gfx::Rect out = PictureLayerTiling::ExpandRectEquallyToAreaBoundedBy(
      in, target_area, bounds, NULL);
  EXPECT_TRUE(out.IsEmpty());
}

static void TileExists(bool exists, Tile* tile,
                       const gfx::Rect& geometry_rect) {
  EXPECT_EQ(exists, tile != NULL) << geometry_rect.ToString();
}

TEST_F(PictureLayerTilingIteratorTest, TilesExist) {
  gfx::Size layer_bounds(1099, 801);
  Initialize(gfx::Size(100, 100), 1.f, layer_bounds);
  VerifyTilesExactlyCoverRect(1.f, gfx::Rect(layer_bounds));
  VerifyTiles(1.f, gfx::Rect(layer_bounds), base::Bind(&TileExists, false));

  client_.set_tree(ACTIVE_TREE);
  tiling_->ComputeTilePriorityRects(
      gfx::Rect(layer_bounds),  // visible content rect
      1.f,                      // current contents scale
      1.0,                      // current frame time
      Occlusion());
  VerifyTiles(1.f, gfx::Rect(layer_bounds), base::Bind(&TileExists, true));

  // Make the viewport rect empty. All tiles are killed and become zombies.
  tiling_->ComputeTilePriorityRects(gfx::Rect(),  // visible content rect
                                    1.f,          // current contents scale
                                    2.0,          // current frame time
                                    Occlusion());
  VerifyTiles(1.f, gfx::Rect(layer_bounds), base::Bind(&TileExists, false));
}

TEST_F(PictureLayerTilingIteratorTest, TilesExistGiantViewport) {
  gfx::Size layer_bounds(1099, 801);
  Initialize(gfx::Size(100, 100), 1.f, layer_bounds);
  VerifyTilesExactlyCoverRect(1.f, gfx::Rect(layer_bounds));
  VerifyTiles(1.f, gfx::Rect(layer_bounds), base::Bind(&TileExists, false));

  gfx::Rect giant_rect(-10000000, -10000000, 1000000000, 1000000000);

  client_.set_tree(ACTIVE_TREE);
  tiling_->ComputeTilePriorityRects(
      gfx::Rect(layer_bounds),  // visible content rect
      1.f,                      // current contents scale
      1.0,                      // current frame time
      Occlusion());
  VerifyTiles(1.f, gfx::Rect(layer_bounds), base::Bind(&TileExists, true));

  // If the visible content rect is empty, it should still have live tiles.
  tiling_->ComputeTilePriorityRects(giant_rect,  // visible content rect
                                    1.f,         // current contents scale
                                    2.0,         // current frame time
                                    Occlusion());
  VerifyTiles(1.f, gfx::Rect(layer_bounds), base::Bind(&TileExists, true));
}

TEST_F(PictureLayerTilingIteratorTest, TilesExistOutsideViewport) {
  gfx::Size layer_bounds(1099, 801);
  Initialize(gfx::Size(100, 100), 1.f, layer_bounds);
  VerifyTilesExactlyCoverRect(1.f, gfx::Rect(layer_bounds));
  VerifyTiles(1.f, gfx::Rect(layer_bounds), base::Bind(&TileExists, false));

  // This rect does not intersect with the layer, as the layer is outside the
  // viewport.
  gfx::Rect viewport_rect(1100, 0, 1000, 1000);
  EXPECT_FALSE(viewport_rect.Intersects(gfx::Rect(layer_bounds)));

  client_.set_tree(ACTIVE_TREE);
  tiling_->ComputeTilePriorityRects(viewport_rect,  // visible content rect
                                    1.f,            // current contents scale
                                    1.0,            // current frame time
                                    Occlusion());
  VerifyTiles(1.f, gfx::Rect(layer_bounds), base::Bind(&TileExists, true));
}

static void TilesIntersectingRectExist(const gfx::Rect& rect,
                                       bool intersect_exists,
                                       Tile* tile,
                                       const gfx::Rect& geometry_rect) {
  bool intersects = rect.Intersects(geometry_rect);
  bool expected_exists = intersect_exists ? intersects : !intersects;
  EXPECT_EQ(expected_exists, tile != NULL)
      << "Rects intersecting " << rect.ToString() << " should exist. "
      << "Current tile rect is " << geometry_rect.ToString();
}

TEST_F(PictureLayerTilingIteratorTest,
       TilesExistLargeViewportAndLayerWithSmallVisibleArea) {
  gfx::Size layer_bounds(10000, 10000);
  client_.SetTileSize(gfx::Size(100, 100));
  client_.set_tree(PENDING_TREE);
  LayerTreeSettings settings;
  settings.max_tiles_for_interest_area = 1;

  scoped_refptr<FakePicturePileImpl> pile =
      FakePicturePileImpl::CreateFilledPileWithDefaultTileSize(layer_bounds);
  tiling_ = TestablePictureLayerTiling::Create(1.f, pile, &client_, settings);
  VerifyTilesExactlyCoverRect(1.f, gfx::Rect(layer_bounds));
  VerifyTiles(1.f, gfx::Rect(layer_bounds), base::Bind(&TileExists, false));

  gfx::Rect visible_rect(8000, 8000, 50, 50);

  client_.set_tree(ACTIVE_TREE);
  tiling_->ComputeTilePriorityRects(visible_rect,  // visible content rect
                                    1.f,           // current contents scale
                                    1.0,           // current frame time
                                    Occlusion());
  VerifyTiles(1.f,
              gfx::Rect(layer_bounds),
              base::Bind(&TilesIntersectingRectExist, visible_rect, true));
}

TEST(ComputeTilePriorityRectsTest, VisibleTiles) {
  // The TilePriority of visible tiles should have zero distance_to_visible
  // and time_to_visible.
  FakePictureLayerTilingClient client;

  gfx::Size device_viewport(800, 600);
  gfx::Size last_layer_bounds(200, 200);
  gfx::Size current_layer_bounds(200, 200);
  float current_layer_contents_scale = 1.f;
  gfx::Transform current_screen_transform;
  double current_frame_time_in_seconds = 1.0;

  gfx::Rect viewport_in_layer_space = ViewportInLayerSpace(
      current_screen_transform, device_viewport);

  client.SetTileSize(gfx::Size(100, 100));
  client.set_tree(ACTIVE_TREE);

  scoped_refptr<FakePicturePileImpl> pile =
      FakePicturePileImpl::CreateFilledPileWithDefaultTileSize(
          current_layer_bounds);
  scoped_ptr<TestablePictureLayerTiling> tiling =
      TestablePictureLayerTiling::Create(1.0f, pile, &client,
                                         LayerTreeSettings());

  tiling->ComputeTilePriorityRects(viewport_in_layer_space,
                                   current_layer_contents_scale,
                                   current_frame_time_in_seconds, Occlusion());
  tiling->UpdateAllTilePrioritiesForTesting();

  ASSERT_TRUE(tiling->TileAt(0, 0));
  ASSERT_TRUE(tiling->TileAt(0, 1));
  ASSERT_TRUE(tiling->TileAt(1, 0));
  ASSERT_TRUE(tiling->TileAt(1, 1));

  TilePriority priority = tiling->TileAt(0, 0)->priority(ACTIVE_TREE);
  EXPECT_FLOAT_EQ(0.f, priority.distance_to_visible);
  EXPECT_FLOAT_EQ(TilePriority::NOW, priority.priority_bin);

  priority = tiling->TileAt(0, 1)->priority(ACTIVE_TREE);
  EXPECT_FLOAT_EQ(0.f, priority.distance_to_visible);
  EXPECT_FLOAT_EQ(TilePriority::NOW, priority.priority_bin);

  priority = tiling->TileAt(1, 0)->priority(ACTIVE_TREE);
  EXPECT_FLOAT_EQ(0.f, priority.distance_to_visible);
  EXPECT_FLOAT_EQ(TilePriority::NOW, priority.priority_bin);

  priority = tiling->TileAt(1, 1)->priority(ACTIVE_TREE);
  EXPECT_FLOAT_EQ(0.f, priority.distance_to_visible);
  EXPECT_FLOAT_EQ(TilePriority::NOW, priority.priority_bin);
}

TEST(ComputeTilePriorityRectsTest, OffscreenTiles) {
  // The TilePriority of offscreen tiles (without movement) should have nonzero
  // distance_to_visible and infinite time_to_visible.
  FakePictureLayerTilingClient client;

  gfx::Size device_viewport(800, 600);
  gfx::Size last_layer_bounds(200, 200);
  gfx::Size current_layer_bounds(200, 200);
  float current_layer_contents_scale = 1.f;
  gfx::Transform last_screen_transform;
  gfx::Transform current_screen_transform;
  double current_frame_time_in_seconds = 1.0;

  current_screen_transform.Translate(850, 0);
  last_screen_transform = current_screen_transform;

  gfx::Rect viewport_in_layer_space = ViewportInLayerSpace(
      current_screen_transform, device_viewport);

  client.SetTileSize(gfx::Size(100, 100));
  client.set_tree(ACTIVE_TREE);

  scoped_refptr<FakePicturePileImpl> pile =
      FakePicturePileImpl::CreateFilledPileWithDefaultTileSize(
          current_layer_bounds);
  scoped_ptr<TestablePictureLayerTiling> tiling =
      TestablePictureLayerTiling::Create(1.0f, pile, &client,
                                         LayerTreeSettings());

  tiling->ComputeTilePriorityRects(viewport_in_layer_space,
                                   current_layer_contents_scale,
                                   current_frame_time_in_seconds, Occlusion());
  tiling->UpdateAllTilePrioritiesForTesting();

  ASSERT_TRUE(tiling->TileAt(0, 0));
  ASSERT_TRUE(tiling->TileAt(0, 1));
  ASSERT_TRUE(tiling->TileAt(1, 0));
  ASSERT_TRUE(tiling->TileAt(1, 1));

  TilePriority priority = tiling->TileAt(0, 0)->priority(ACTIVE_TREE);
  EXPECT_GT(priority.distance_to_visible, 0.f);
  EXPECT_NE(TilePriority::NOW, priority.priority_bin);

  priority = tiling->TileAt(0, 1)->priority(ACTIVE_TREE);
  EXPECT_GT(priority.distance_to_visible, 0.f);
  EXPECT_NE(TilePriority::NOW, priority.priority_bin);

  priority = tiling->TileAt(1, 0)->priority(ACTIVE_TREE);
  EXPECT_GT(priority.distance_to_visible, 0.f);
  EXPECT_NE(TilePriority::NOW, priority.priority_bin);

  priority = tiling->TileAt(1, 1)->priority(ACTIVE_TREE);
  EXPECT_GT(priority.distance_to_visible, 0.f);
  EXPECT_NE(TilePriority::NOW, priority.priority_bin);

  // Furthermore, in this scenario tiles on the right hand side should have a
  // larger distance to visible.
  TilePriority left = tiling->TileAt(0, 0)->priority(ACTIVE_TREE);
  TilePriority right = tiling->TileAt(1, 0)->priority(ACTIVE_TREE);
  EXPECT_GT(right.distance_to_visible, left.distance_to_visible);

  left = tiling->TileAt(0, 1)->priority(ACTIVE_TREE);
  right = tiling->TileAt(1, 1)->priority(ACTIVE_TREE);
  EXPECT_GT(right.distance_to_visible, left.distance_to_visible);
}

TEST(ComputeTilePriorityRectsTest, PartiallyOffscreenLayer) {
  // Sanity check that a layer with some tiles visible and others offscreen has
  // correct TilePriorities for each tile.
  FakePictureLayerTilingClient client;

  gfx::Size device_viewport(800, 600);
  gfx::Size last_layer_bounds(200, 200);
  gfx::Size current_layer_bounds(200, 200);
  float current_layer_contents_scale = 1.f;
  gfx::Transform last_screen_transform;
  gfx::Transform current_screen_transform;
  double current_frame_time_in_seconds = 1.0;

  current_screen_transform.Translate(705, 505);
  last_screen_transform = current_screen_transform;

  gfx::Rect viewport_in_layer_space = ViewportInLayerSpace(
      current_screen_transform, device_viewport);

  client.SetTileSize(gfx::Size(100, 100));
  client.set_tree(ACTIVE_TREE);

  scoped_refptr<FakePicturePileImpl> pile =
      FakePicturePileImpl::CreateFilledPileWithDefaultTileSize(
          current_layer_bounds);
  scoped_ptr<TestablePictureLayerTiling> tiling =
      TestablePictureLayerTiling::Create(1.0f, pile, &client,
                                         LayerTreeSettings());

  tiling->ComputeTilePriorityRects(viewport_in_layer_space,
                                   current_layer_contents_scale,
                                   current_frame_time_in_seconds, Occlusion());
  tiling->UpdateAllTilePrioritiesForTesting();

  ASSERT_TRUE(tiling->TileAt(0, 0));
  ASSERT_TRUE(tiling->TileAt(0, 1));
  ASSERT_TRUE(tiling->TileAt(1, 0));
  ASSERT_TRUE(tiling->TileAt(1, 1));

  TilePriority priority = tiling->TileAt(0, 0)->priority(ACTIVE_TREE);
  EXPECT_FLOAT_EQ(0.f, priority.distance_to_visible);
  EXPECT_FLOAT_EQ(TilePriority::NOW, priority.priority_bin);

  priority = tiling->TileAt(0, 1)->priority(ACTIVE_TREE);
  EXPECT_GT(priority.distance_to_visible, 0.f);
  EXPECT_NE(TilePriority::NOW, priority.priority_bin);

  priority = tiling->TileAt(1, 0)->priority(ACTIVE_TREE);
  EXPECT_GT(priority.distance_to_visible, 0.f);
  EXPECT_NE(TilePriority::NOW, priority.priority_bin);

  priority = tiling->TileAt(1, 1)->priority(ACTIVE_TREE);
  EXPECT_GT(priority.distance_to_visible, 0.f);
  EXPECT_NE(TilePriority::NOW, priority.priority_bin);
}

TEST(ComputeTilePriorityRectsTest, PartiallyOffscreenRotatedLayer) {
  // Each tile of a layer may be affected differently by a transform; Check
  // that ComputeTilePriorityRects correctly accounts for the transform between
  // layer space and screen space.
  FakePictureLayerTilingClient client;

  gfx::Size device_viewport(800, 600);
  gfx::Size last_layer_bounds(200, 200);
  gfx::Size current_layer_bounds(200, 200);
  float current_layer_contents_scale = 1.f;
  gfx::Transform last_screen_transform;
  gfx::Transform current_screen_transform;
  double current_frame_time_in_seconds = 1.0;

  // A diagonally rotated layer that is partially off the bottom of the screen.
  // In this configuration, only the top-left tile would be visible.
  current_screen_transform.Translate(600, 750);
  current_screen_transform.RotateAboutZAxis(45);
  last_screen_transform = current_screen_transform;

  gfx::Rect viewport_in_layer_space = ViewportInLayerSpace(
      current_screen_transform, device_viewport);

  client.SetTileSize(gfx::Size(100, 100));
  client.set_tree(ACTIVE_TREE);

  scoped_refptr<FakePicturePileImpl> pile =
      FakePicturePileImpl::CreateFilledPileWithDefaultTileSize(
          current_layer_bounds);
  scoped_ptr<TestablePictureLayerTiling> tiling =
      TestablePictureLayerTiling::Create(1.0f, pile, &client,
                                         LayerTreeSettings());

  tiling->ComputeTilePriorityRects(viewport_in_layer_space,
                                   current_layer_contents_scale,
                                   current_frame_time_in_seconds, Occlusion());
  tiling->UpdateAllTilePrioritiesForTesting();

  ASSERT_TRUE(tiling->TileAt(0, 0));
  ASSERT_TRUE(tiling->TileAt(0, 1));
  ASSERT_TRUE(tiling->TileAt(1, 0));
  ASSERT_TRUE(tiling->TileAt(1, 1));

  TilePriority priority = tiling->TileAt(0, 0)->priority(ACTIVE_TREE);
  EXPECT_FLOAT_EQ(0.f, priority.distance_to_visible);
  EXPECT_EQ(TilePriority::NOW, priority.priority_bin);

  priority = tiling->TileAt(0, 1)->priority(ACTIVE_TREE);
  EXPECT_FLOAT_EQ(0.f, priority.distance_to_visible);
  EXPECT_EQ(TilePriority::NOW, priority.priority_bin);

  priority = tiling->TileAt(1, 0)->priority(ACTIVE_TREE);
  EXPECT_GT(priority.distance_to_visible, 0.f);
  EXPECT_NE(TilePriority::NOW, priority.priority_bin);

  priority = tiling->TileAt(1, 1)->priority(ACTIVE_TREE);
  EXPECT_GT(priority.distance_to_visible, 0.f);
  EXPECT_NE(TilePriority::NOW, priority.priority_bin);

  // Furthermore, in this scenario the bottom-right tile should have the larger
  // distance to visible.
  TilePriority top_left = tiling->TileAt(0, 0)->priority(ACTIVE_TREE);
  TilePriority top_right = tiling->TileAt(1, 0)->priority(ACTIVE_TREE);
  TilePriority bottom_right = tiling->TileAt(1, 1)->priority(ACTIVE_TREE);
  EXPECT_GT(top_right.distance_to_visible, top_left.distance_to_visible);

  EXPECT_EQ(bottom_right.distance_to_visible, top_right.distance_to_visible);
}

TEST(ComputeTilePriorityRectsTest, PerspectiveLayer) {
  // Perspective transforms need to take a different code path.
  // This test checks tile priorities of a perspective layer.
  FakePictureLayerTilingClient client;

  gfx::Size device_viewport(800, 600);
  gfx::Rect visible_layer_rect(0, 0, 0, 0);  // offscreen.
  gfx::Size last_layer_bounds(200, 200);
  gfx::Size current_layer_bounds(200, 200);
  float current_layer_contents_scale = 1.f;
  gfx::Transform last_screen_transform;
  gfx::Transform current_screen_transform;
  double current_frame_time_in_seconds = 1.0;

  // A 3d perspective layer rotated about its Y axis, translated to almost
  // fully offscreen. The left side will appear closer (i.e. larger in 2d) than
  // the right side, so the top-left tile will technically be closer than the
  // top-right.

  // Translate layer to offscreen
  current_screen_transform.Translate(400.0, 630.0);
  // Apply perspective about the center of the layer
  current_screen_transform.Translate(100.0, 100.0);
  current_screen_transform.ApplyPerspectiveDepth(100.0);
  current_screen_transform.RotateAboutYAxis(10.0);
  current_screen_transform.Translate(-100.0, -100.0);
  last_screen_transform = current_screen_transform;

  // Sanity check that this transform wouldn't cause w<0 clipping.
  bool clipped;
  MathUtil::MapQuad(current_screen_transform,
                    gfx::QuadF(gfx::RectF(0, 0, 200, 200)),
                    &clipped);
  ASSERT_FALSE(clipped);

  gfx::Rect viewport_in_layer_space = ViewportInLayerSpace(
      current_screen_transform, device_viewport);

  client.SetTileSize(gfx::Size(100, 100));
  client.set_tree(ACTIVE_TREE);

  scoped_refptr<FakePicturePileImpl> pile =
      FakePicturePileImpl::CreateFilledPileWithDefaultTileSize(
          current_layer_bounds);
  scoped_ptr<TestablePictureLayerTiling> tiling =
      TestablePictureLayerTiling::Create(1.0f, pile, &client,
                                         LayerTreeSettings());

  tiling->ComputeTilePriorityRects(viewport_in_layer_space,
                                   current_layer_contents_scale,
                                   current_frame_time_in_seconds, Occlusion());
  tiling->UpdateAllTilePrioritiesForTesting();

  ASSERT_TRUE(tiling->TileAt(0, 0));
  ASSERT_TRUE(tiling->TileAt(0, 1));
  ASSERT_TRUE(tiling->TileAt(1, 0));
  ASSERT_TRUE(tiling->TileAt(1, 1));

  // All tiles will have a positive distance_to_visible
  // and an infinite time_to_visible.
  TilePriority priority = tiling->TileAt(0, 0)->priority(ACTIVE_TREE);
  EXPECT_FLOAT_EQ(priority.distance_to_visible, 0.f);
  EXPECT_EQ(TilePriority::NOW, priority.priority_bin);

  priority = tiling->TileAt(0, 1)->priority(ACTIVE_TREE);
  EXPECT_GT(priority.distance_to_visible, 0.f);
  EXPECT_NE(TilePriority::NOW, priority.priority_bin);

  priority = tiling->TileAt(1, 0)->priority(ACTIVE_TREE);
  EXPECT_FLOAT_EQ(priority.distance_to_visible, 0.f);
  EXPECT_EQ(TilePriority::NOW, priority.priority_bin);

  priority = tiling->TileAt(1, 1)->priority(ACTIVE_TREE);
  EXPECT_GT(priority.distance_to_visible, 0.f);
  EXPECT_NE(TilePriority::NOW, priority.priority_bin);

  // Furthermore, in this scenario the top-left distance_to_visible
  // will be smallest, followed by top-right. The bottom layers
  // will of course be further than the top layers.
  TilePriority top_left = tiling->TileAt(0, 0)->priority(ACTIVE_TREE);
  TilePriority top_right = tiling->TileAt(1, 0)->priority(ACTIVE_TREE);
  TilePriority bottom_left = tiling->TileAt(0, 1)->priority(ACTIVE_TREE);
  TilePriority bottom_right = tiling->TileAt(1, 1)->priority(ACTIVE_TREE);

  EXPECT_GT(bottom_right.distance_to_visible, top_right.distance_to_visible);

  EXPECT_GT(bottom_left.distance_to_visible, top_left.distance_to_visible);
}

TEST(ComputeTilePriorityRectsTest, PerspectiveLayerClippedByW) {
  // Perspective transforms need to take a different code path.
  // This test checks tile priorities of a perspective layer.
  FakePictureLayerTilingClient client;

  gfx::Size device_viewport(800, 600);
  gfx::Size last_layer_bounds(200, 200);
  gfx::Size current_layer_bounds(200, 200);
  float current_layer_contents_scale = 1.f;
  gfx::Transform last_screen_transform;
  gfx::Transform current_screen_transform;
  double current_frame_time_in_seconds = 1.0;

  // A 3d perspective layer rotated about its Y axis, translated to almost
  // fully offscreen. The left side will appear closer (i.e. larger in 2d) than
  // the right side, so the top-left tile will technically be closer than the
  // top-right.

  // Translate layer to offscreen
  current_screen_transform.Translate(400.0, 970.0);
  // Apply perspective and rotation about the center of the layer
  current_screen_transform.Translate(100.0, 100.0);
  current_screen_transform.ApplyPerspectiveDepth(10.0);
  current_screen_transform.RotateAboutYAxis(10.0);
  current_screen_transform.Translate(-100.0, -100.0);
  last_screen_transform = current_screen_transform;

  // Sanity check that this transform does cause w<0 clipping for the left side
  // of the layer, but not the right side.
  bool clipped;
  MathUtil::MapQuad(current_screen_transform,
                    gfx::QuadF(gfx::RectF(0, 0, 100, 200)),
                    &clipped);
  ASSERT_TRUE(clipped);

  MathUtil::MapQuad(current_screen_transform,
                    gfx::QuadF(gfx::RectF(100, 0, 100, 200)),
                    &clipped);
  ASSERT_FALSE(clipped);

  gfx::Rect viewport_in_layer_space = ViewportInLayerSpace(
      current_screen_transform, device_viewport);

  client.SetTileSize(gfx::Size(100, 100));
  client.set_tree(ACTIVE_TREE);

  scoped_refptr<FakePicturePileImpl> pile =
      FakePicturePileImpl::CreateFilledPileWithDefaultTileSize(
          current_layer_bounds);
  scoped_ptr<TestablePictureLayerTiling> tiling =
      TestablePictureLayerTiling::Create(1.0f, pile, &client,
                                         LayerTreeSettings());

  tiling->ComputeTilePriorityRects(viewport_in_layer_space,
                                   current_layer_contents_scale,
                                   current_frame_time_in_seconds, Occlusion());
  tiling->UpdateAllTilePrioritiesForTesting();

  ASSERT_TRUE(tiling->TileAt(0, 0));
  ASSERT_TRUE(tiling->TileAt(0, 1));
  ASSERT_TRUE(tiling->TileAt(1, 0));
  ASSERT_TRUE(tiling->TileAt(1, 1));

  // Left-side tiles will be clipped by the transform, so we have to assume
  // they are visible just in case.
  TilePriority priority = tiling->TileAt(0, 0)->priority(ACTIVE_TREE);
  EXPECT_FLOAT_EQ(0.f, priority.distance_to_visible);
  EXPECT_FLOAT_EQ(TilePriority::NOW, priority.priority_bin);

  priority = tiling->TileAt(0, 1)->priority(ACTIVE_TREE);
  EXPECT_GT(priority.distance_to_visible, 0.f);
  EXPECT_NE(TilePriority::NOW, priority.priority_bin);

  // Right-side tiles will have a positive distance_to_visible
  // and an infinite time_to_visible.
  priority = tiling->TileAt(1, 0)->priority(ACTIVE_TREE);
  EXPECT_FLOAT_EQ(priority.distance_to_visible, 0.f);
  EXPECT_EQ(TilePriority::NOW, priority.priority_bin);

  priority = tiling->TileAt(1, 1)->priority(ACTIVE_TREE);
  EXPECT_GT(priority.distance_to_visible, 0.f);
  EXPECT_NE(TilePriority::NOW, priority.priority_bin);
}

TEST(ComputeTilePriorityRectsTest, BasicMotion) {
  // Test that time_to_visible is computed correctly when
  // there is some motion.
  FakePictureLayerTilingClient client;

  gfx::Size device_viewport(800, 600);
  gfx::Rect visible_layer_rect(0, 0, 0, 0);
  gfx::Size last_layer_bounds(200, 200);
  gfx::Size current_layer_bounds(200, 200);
  float last_layer_contents_scale = 1.f;
  float current_layer_contents_scale = 1.f;
  gfx::Transform last_screen_transform;
  gfx::Transform current_screen_transform;
  double last_frame_time_in_seconds = 1.0;
  double current_frame_time_in_seconds = 2.0;

  // Offscreen layer is coming closer to viewport at 1000 pixels per second.
  current_screen_transform.Translate(1800, 0);
  last_screen_transform.Translate(2800, 0);

  gfx::Rect viewport_in_layer_space = ViewportInLayerSpace(
      current_screen_transform, device_viewport);

  client.SetTileSize(gfx::Size(100, 100));
  client.set_tree(ACTIVE_TREE);
  LayerTreeSettings settings;
  settings.max_tiles_for_interest_area = 10000;

  scoped_refptr<FakePicturePileImpl> pile =
      FakePicturePileImpl::CreateFilledPileWithDefaultTileSize(
          current_layer_bounds);
  scoped_ptr<TestablePictureLayerTiling> tiling =
      TestablePictureLayerTiling::Create(1.0f, pile, &client, settings);

  // previous ("last") frame
  tiling->ComputeTilePriorityRects(viewport_in_layer_space,
                                   last_layer_contents_scale,
                                   last_frame_time_in_seconds, Occlusion());

  // current frame
  tiling->ComputeTilePriorityRects(viewport_in_layer_space,
                                   current_layer_contents_scale,
                                   current_frame_time_in_seconds, Occlusion());
  tiling->UpdateAllTilePrioritiesForTesting();

  ASSERT_TRUE(tiling->TileAt(0, 0));
  ASSERT_TRUE(tiling->TileAt(0, 1));
  ASSERT_TRUE(tiling->TileAt(1, 0));
  ASSERT_TRUE(tiling->TileAt(1, 1));

  TilePriority priority = tiling->TileAt(0, 0)->priority(ACTIVE_TREE);
  EXPECT_GT(priority.distance_to_visible, 0.f);
  EXPECT_NE(TilePriority::NOW, priority.priority_bin);

  priority = tiling->TileAt(0, 1)->priority(ACTIVE_TREE);
  EXPECT_GT(priority.distance_to_visible, 0.f);
  EXPECT_NE(TilePriority::NOW, priority.priority_bin);

  // time_to_visible for the right hand side layers needs an extra 0.099
  // seconds because this tile is 99 pixels further away.
  priority = tiling->TileAt(1, 0)->priority(ACTIVE_TREE);
  EXPECT_GT(priority.distance_to_visible, 0.f);
  EXPECT_NE(TilePriority::NOW, priority.priority_bin);

  priority = tiling->TileAt(1, 1)->priority(ACTIVE_TREE);
  EXPECT_GT(priority.distance_to_visible, 0.f);
  EXPECT_NE(TilePriority::NOW, priority.priority_bin);
}

TEST(ComputeTilePriorityRectsTest, RotationMotion) {
  // Each tile of a layer may be affected differently by a transform; Check
  // that ComputeTilePriorityRects correctly accounts for the transform between
  // layer space and screen space.

  FakePictureLayerTilingClient client;
  scoped_ptr<TestablePictureLayerTiling> tiling;

  gfx::Size device_viewport(800, 600);
  gfx::Rect visible_layer_rect(0, 0, 0, 0);  // offscren.
  gfx::Size last_layer_bounds(200, 200);
  gfx::Size current_layer_bounds(200, 200);
  float last_layer_contents_scale = 1.f;
  float current_layer_contents_scale = 1.f;
  gfx::Transform last_screen_transform;
  gfx::Transform current_screen_transform;
  double last_frame_time_in_seconds = 1.0;
  double current_frame_time_in_seconds = 2.0;

  // Rotation motion is set up specifically so that:
  //  - rotation occurs about the center of the layer
  //  - the top-left tile becomes visible on rotation
  //  - the top-right tile will have an infinite time_to_visible
  //    because it is rotating away from viewport.
  //  - bottom-left layer will have a positive non-zero time_to_visible
  //    because it is rotating toward the viewport.
  current_screen_transform.Translate(400, 550);
  current_screen_transform.RotateAboutZAxis(45);

  last_screen_transform.Translate(400, 550);

  gfx::Rect viewport_in_layer_space = ViewportInLayerSpace(
      current_screen_transform, device_viewport);

  client.SetTileSize(gfx::Size(100, 100));
  client.set_tree(ACTIVE_TREE);

  scoped_refptr<FakePicturePileImpl> pile =
      FakePicturePileImpl::CreateFilledPileWithDefaultTileSize(
          current_layer_bounds);
  tiling = TestablePictureLayerTiling::Create(1.0f, pile, &client,
                                              LayerTreeSettings());

  // previous ("last") frame
  tiling->ComputeTilePriorityRects(viewport_in_layer_space,
                                   last_layer_contents_scale,
                                   last_frame_time_in_seconds, Occlusion());

  // current frame
  tiling->ComputeTilePriorityRects(viewport_in_layer_space,
                                   current_layer_contents_scale,
                                   current_frame_time_in_seconds, Occlusion());
  tiling->UpdateAllTilePrioritiesForTesting();

  ASSERT_TRUE(tiling->TileAt(0, 0));
  ASSERT_TRUE(tiling->TileAt(0, 1));
  ASSERT_TRUE(tiling->TileAt(1, 0));
  ASSERT_TRUE(tiling->TileAt(1, 1));

  TilePriority priority = tiling->TileAt(0, 0)->priority(ACTIVE_TREE);
  EXPECT_FLOAT_EQ(0.f, priority.distance_to_visible);
  EXPECT_EQ(TilePriority::NOW, priority.priority_bin);

  priority = tiling->TileAt(0, 1)->priority(ACTIVE_TREE);
  EXPECT_FLOAT_EQ(0.f, priority.distance_to_visible);
  EXPECT_EQ(TilePriority::NOW, priority.priority_bin);

  priority = tiling->TileAt(1, 0)->priority(ACTIVE_TREE);
  EXPECT_FLOAT_EQ(0.f, priority.distance_to_visible);
  EXPECT_EQ(TilePriority::NOW, priority.priority_bin);
}

TEST(PictureLayerTilingTest, RecycledTilesCleared) {
  // This test performs the following:
  // Setup:
  // - Two tilings, one active one recycled with all tiles shared.
  // Procedure:
  // - Viewport moves somewhere far away and active tiling clears tiles.
  // - Viewport moves back and a new active tiling tile is created.
  // Result:
  // - Recycle tiling does _not_ have the tile in the same location (thus it
  //   will be shared next time a pending tiling is created).

  FakePictureLayerTilingClient active_client;

  active_client.SetTileSize(gfx::Size(100, 100));
  active_client.set_tree(ACTIVE_TREE);
  LayerTreeSettings settings;
  settings.max_tiles_for_interest_area = 10;

  scoped_refptr<FakePicturePileImpl> pile =
      FakePicturePileImpl::CreateFilledPileWithDefaultTileSize(
          gfx::Size(10000, 10000));
  scoped_ptr<TestablePictureLayerTiling> active_tiling =
      TestablePictureLayerTiling::Create(1.0f, pile, &active_client, settings);
  // Create all tiles on this tiling.
  active_tiling->ComputeTilePriorityRects(gfx::Rect(0, 0, 100, 100), 1.0f, 1.0f,
                                          Occlusion());

  FakePictureLayerTilingClient recycle_client;
  recycle_client.SetTileSize(gfx::Size(100, 100));
  recycle_client.set_tree(PENDING_TREE);
  recycle_client.set_twin_tiling(active_tiling.get());

  pile = FakePicturePileImpl::CreateFilledPileWithDefaultTileSize(
      gfx::Size(10000, 10000));
  scoped_ptr<TestablePictureLayerTiling> recycle_tiling =
      TestablePictureLayerTiling::Create(1.0f, pile, &recycle_client, settings);

  // Create all tiles on the second tiling. All tiles should be shared.
  recycle_tiling->ComputeTilePriorityRects(gfx::Rect(0, 0, 100, 100), 1.0f,
                                           1.0f, Occlusion());

  // Set the second tiling as recycled.
  active_client.set_twin_tiling(NULL);
  active_client.set_recycled_twin_tiling(recycle_tiling.get());
  recycle_client.set_twin_tiling(NULL);

  // Verify that tiles exist and are shared.
  EXPECT_TRUE(active_tiling->TileAt(0, 0));
  EXPECT_TRUE(recycle_tiling->TileAt(0, 0));
  EXPECT_EQ(active_tiling->TileAt(0, 0), recycle_tiling->TileAt(0, 0));

  // Move the viewport far away from the (0, 0) tile.
  active_tiling->ComputeTilePriorityRects(gfx::Rect(9000, 9000, 100, 100), 1.0f,
                                          2.0, Occlusion());
  // Ensure the tile was deleted on both tilings.
  EXPECT_FALSE(active_tiling->TileAt(0, 0));
  EXPECT_FALSE(recycle_tiling->TileAt(0, 0));

  // Move the viewport back to (0, 0) tile.
  active_tiling->ComputeTilePriorityRects(gfx::Rect(0, 0, 100, 100), 1.0f, 3.0,
                                          Occlusion());

  // Ensure that we now have a tile here on both tilings again.
  EXPECT_TRUE(active_tiling->TileAt(0, 0));
  EXPECT_TRUE(recycle_tiling->TileAt(0, 0));
}

TEST(PictureLayerTilingTest, RecycledTilesClearedOnReset) {
  FakePictureLayerTilingClient active_client;
  active_client.SetTileSize(gfx::Size(100, 100));
  active_client.set_tree(ACTIVE_TREE);

  scoped_refptr<FakePicturePileImpl> pile =
      FakePicturePileImpl::CreateFilledPileWithDefaultTileSize(
          gfx::Size(100, 100));
  scoped_ptr<TestablePictureLayerTiling> active_tiling =
      TestablePictureLayerTiling::Create(1.0f, pile, &active_client,
                                         LayerTreeSettings());
  // Create all tiles on this tiling.
  active_tiling->ComputeTilePriorityRects(gfx::Rect(0, 0, 100, 100), 1.0f, 1.0f,
                                          Occlusion());

  FakePictureLayerTilingClient recycle_client;
  recycle_client.SetTileSize(gfx::Size(100, 100));
  recycle_client.set_tree(PENDING_TREE);
  recycle_client.set_twin_tiling(active_tiling.get());

  LayerTreeSettings settings;
  settings.max_tiles_for_interest_area = 10;

  pile = FakePicturePileImpl::CreateFilledPileWithDefaultTileSize(
      gfx::Size(100, 100));
  scoped_ptr<TestablePictureLayerTiling> recycle_tiling =
      TestablePictureLayerTiling::Create(1.0f, pile, &recycle_client, settings);

  // Create all tiles on the recycle tiling. All tiles should be shared.
  recycle_tiling->ComputeTilePriorityRects(gfx::Rect(0, 0, 100, 100), 1.0f,
                                           1.0f, Occlusion());

  // Set the second tiling as recycled.
  active_client.set_twin_tiling(NULL);
  active_client.set_recycled_twin_tiling(recycle_tiling.get());
  recycle_client.set_twin_tiling(NULL);

  // Verify that tiles exist and are shared.
  EXPECT_TRUE(active_tiling->TileAt(0, 0));
  EXPECT_TRUE(recycle_tiling->TileAt(0, 0));
  EXPECT_EQ(active_tiling->TileAt(0, 0), recycle_tiling->TileAt(0, 0));

  // Reset the active tiling. The recycle tiles should be released too.
  active_tiling->Reset();
  EXPECT_FALSE(active_tiling->TileAt(0, 0));
  EXPECT_FALSE(recycle_tiling->TileAt(0, 0));
}

TEST_F(PictureLayerTilingIteratorTest, ResizeTilesAndUpdateToCurrent) {
  // The tiling has four rows and three columns.
  Initialize(gfx::Size(150, 100), 1.f, gfx::Size(250, 150));
  tiling_->CreateAllTilesForTesting();
  EXPECT_EQ(150, tiling_->TilingDataForTesting().max_texture_size().width());
  EXPECT_EQ(100, tiling_->TilingDataForTesting().max_texture_size().height());
  EXPECT_EQ(4u, tiling_->AllRefTilesForTesting().size());

  client_.SetTileSize(gfx::Size(250, 200));
  client_.set_tree(PENDING_TREE);

  // Tile size in the tiling should still be 150x100.
  EXPECT_EQ(150, tiling_->TilingDataForTesting().max_texture_size().width());
  EXPECT_EQ(100, tiling_->TilingDataForTesting().max_texture_size().height());

  // The layer's size isn't changed, but the tile size was.
  scoped_refptr<FakePicturePileImpl> pile =
      FakePicturePileImpl::CreateFilledPileWithDefaultTileSize(
          gfx::Size(250, 150));
  tiling_->SetRasterSourceAndResize(pile);

  // Tile size in the tiling should be resized to 250x200.
  EXPECT_EQ(250, tiling_->TilingDataForTesting().max_texture_size().width());
  EXPECT_EQ(200, tiling_->TilingDataForTesting().max_texture_size().height());
  EXPECT_EQ(0u, tiling_->AllRefTilesForTesting().size());
}

}  // namespace
}  // namespace cc


text:
// <copyright file="ScenarioOutlineRunner.cs" company="xBehave.net contributors">
//  Copyright (c) xBehave.net contributors. All rights reserved.
// </copyright>

namespace Xbehave.Execution
{
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Threading;
    using System.Threading.Tasks;
    using Xbehave.Execution.Extensions;
    using Xunit.Abstractions;
    using Xunit.Sdk;

    public class ScenarioOutlineRunner : XunitTestCaseRunner
    {
        private static readonly object[] noArguments = new object[0];

        private readonly IMessageSink diagnosticMessageSink;
        private readonly ScenarioRunnerFactory scenarioRunnerFactory;
        private readonly ExceptionAggregator cleanupAggregator = new ExceptionAggregator();
        private readonly List<ScenarioRunner> scenarioRunners = new List<ScenarioRunner>();
        private readonly List<IDisposable> disposables = new List<IDisposable>();
        private Exception dataDiscoveryException;

        public ScenarioOutlineRunner(
            IMessageSink diagnosticMessageSink,
            IXunitTestCase scenarioOutline,
            string displayName,
            string skipReason,
            object[] constructorArguments,
            IMessageBus messageBus,
            ExceptionAggregator aggregator,
            CancellationTokenSource cancellationTokenSource)
            : base(
                scenarioOutline,
                displayName,
                skipReason,
                constructorArguments,
                noArguments,
                messageBus,
                aggregator,
                cancellationTokenSource)
        {
            this.diagnosticMessageSink = diagnosticMessageSink;
            this.scenarioRunnerFactory = new ScenarioRunnerFactory(
                this.TestCase,
                this.DisplayName,
                this.MessageBus,
                this.TestClass,
                this.ConstructorArguments,
                this.SkipReason,
                this.BeforeAfterAttributes,
                this.Aggregator,
                this.CancellationTokenSource);
        }

        protected override async Task AfterTestCaseStartingAsync()
        {
            await base.AfterTestCaseStartingAsync();

            try
            {
                var dataAttributes = this.TestCase.TestMethod.Method.GetCustomAttributes(typeof(DataAttribute)).ToList();
                foreach (var dataAttribute in dataAttributes)
                {
                    var discovererAttribute = dataAttribute.GetCustomAttributes(typeof(DataDiscovererAttribute)).First();
                    var discoverer =
                        ExtensibilityPointFactory.GetDataDiscoverer(this.diagnosticMessageSink, discovererAttribute);

                    foreach (var dataRow in discoverer.GetData(dataAttribute, this.TestCase.TestMethod.Method))
                    {
                        this.disposables.AddRange(dataRow.OfType<IDisposable>());
                        this.scenarioRunners.Add(this.scenarioRunnerFactory.Create(dataRow));
                    }
                }

                if (!this.scenarioRunners.Any())
                {
                    this.scenarioRunners.Add(this.scenarioRunnerFactory.Create(noArguments));
                }
            }
            catch (Exception ex)
            {
                this.dataDiscoveryException = ex;
            }
        }

        protected override async Task<RunSummary> RunTestAsync()
        {
            if (this.dataDiscoveryException != null)
            {
                this.MessageBus.Queue(
                    new XunitTest(this.TestCase, this.DisplayName),
                    test => new TestFailed(test, 0, null, this.dataDiscoveryException.Unwrap()),
                    this.CancellationTokenSource);

                return new RunSummary { Total = 1, Failed = 1 };
            }

            var summary = new RunSummary();
            foreach (var scenarioRunner in this.scenarioRunners)
            {
                summary.Aggregate(await scenarioRunner.RunAsync());
            }

            // Run the cleanup here so we can include cleanup time in the run summary,
            // but save any exceptions so we can surface them during the cleanup phase,
            // so they get properly reported as test case cleanup failures.
            var timer = new ExecutionTimer();
            foreach (var disposable in this.disposables)
            {
                timer.Aggregate(() => this.cleanupAggregator.Run(() => disposable.Dispose()));
            }

            summary.Time += timer.Total;
            return summary;
        }

        protected override Task BeforeTestCaseFinishedAsync()
        {
            this.Aggregator.Aggregate(this.cleanupAggregator);

            return base.BeforeTestCaseFinishedAsync();
        }
    }
}

redpajama_set_name: RedPajamaGithub


text:
<?php

namespace PHPExiftool\Driver\Tag\ID3v24;

use JMS\Serializer\Annotation\ExclusionPolicy;
use PHPExiftool\Driver\AbstractTag;

/**
 * @ExclusionPolicy("all")
 */
class InternetRadioStationURL extends AbstractTag
{

    protected $Id = 'WORS';

    protected $Name = 'InternetRadioStationURL';

    protected $FullName = 'ID3::v2_4';

    protected $GroupName = 'ID3v2_4';

    protected $g0 = 'ID3';

    protected $g1 = 'ID3v2_4';

    protected $g2 = 'Audio';

    protected $Type = '?';

    protected $Writable = false;

    protected $Description = 'Internet Radio Station URL';
}


text:
.nav-container {
  position: fixed;
  top: var(--navbar-height);
  left: 0;
  width: 100%;
  font-size: calc(17 / var(--rem-base) * 1rem);
  z-index: var(--z-index-nav);
  visibility: hidden;
}

@media screen and (min-width: 769px) {
  .nav-container {
    width: var(--nav-width);
  }
}

@media screen and (min-width: 1024px) {
  .nav-container {
    font-size: calc(15.5 / var(--rem-base) * 1rem);
    flex: none;
    position: static;
    top: 0;
    visibility: visible;
  }
}

.nav-container.is-active {
  visibility: visible;
}

.nav {
  background: var(--nav-background);
  position: relative;
  top: var(--toolbar-height);
  height: var(--nav-height);
}

@media screen and (min-width: 769px) {
  .nav {
    box-shadow: 0.5px 0 3px var(--nav-border-color);
  }
}

@media screen and (min-width: 1024px) {
  .nav {
    top: var(--navbar-height);
    box-shadow: none;
    position: sticky;
    height: var(--nav-height--desktop);
  }
}

.nav .panels {
  display: flex;
  flex-direction: column;
  height: inherit;
}

html.is-clipped--nav {
  overflow-y: hidden;
}

.nav-panel-menu {
  overflow-y: scroll;
  overscroll-behavior: none;
  height: var(--nav-panel-menu-height);
}

.nav-panel-menu:not(.is-active) .nav-menu {
  opacity: 0.75;
}

/* Solr Changes - Start */
.nav-panel-menu:not(.is-active) .nav-menu::after {
  /* Solr Changes - End */
  content: "";
  background: rgba(0, 0, 0, 0.5);
  display: block;
  position: absolute;
  top: 0;
  right: 0;
  bottom: 0;
  left: 0;
}

.nav-menu {
  min-height: 100%;
  /* Solr Changes - Start */
  padding: 0.01rem 0.75rem;
  /* Solr Changes - End */
  line-height: var(--nav-line-height);
  position: relative;
}

.nav-menu h3.title {
  color: var(--nav-heading-font-color);
  font-size: inherit;
  font-weight: var(--body-font-weight-bold);
  margin: 0;
  padding: 0.25em 0 0.125em;
}

.nav-menu a {
  color: inherit;
}

/* Solr Changes - Start */
.nav-list {
  margin: 0 0 0 0.75rem;
}

.nav-menu > ul.nav-list {
  padding-top: 0;
}
/* Solr Changes - End */

.nav-menu > .nav-list + .nav-list {
  margin-top: 0.5rem;
}

.nav-item {
  list-style: none;
  /* Solr Changes - Start */
  margin-top: 10px;
  /* Solr Changes - End */
}

/* adds some breathing room below a nested list */
.nav-item-toggle ~ .nav-list {
  padding-bottom: 0.125rem;
}

/* matches list without a title */
.nav-item[data-depth="0"] > .nav-list:first-child {
  display: block;
  margin: 0;
}

.nav-item:not(.is-active) > .nav-list {
  display: none;
}

.nav-item-toggle {
  background: transparent url(../img/caret.svg) no-repeat center / 50%;
  border: none;
  outline: none;
  line-height: inherit;
  position: absolute;
  height: calc(var(--nav-line-height) * 1em);
  width: calc(var(--nav-line-height) * 1em);
  margin-top: -0.05em;
  margin-left: calc(var(--nav-line-height) * -1em);
}

.nav-item.is-active > .nav-item-toggle {
  transform: rotate(90deg);
}

.is-current-page > .nav-link,
.is-current-page > .nav-text {
  font-weight: var(--body-font-weight-bold);
  /* Solr Changes - Start */
  color: var(--color-solr-primary-orange);
  /* Solr Changes - End */
}

.nav-panel-explore {
  background: var(--nav-background);
  display: flex;
  flex-direction: column;
  /* Solr Changes - Start */
  position: sticky;
  top: var(--navbar-height);
  /* Solr Changes - End */
  right: 0;
  /* Solr Removals - Start
  bottom: 0;
  Solr Removals - End */
  /* Solr Additions - Start */
  z-index: 2;
  /* Solr Additions - End */
  left: 0;
}

.nav-panel-explore:not(:first-child) {
  top: auto;
  /* Solr Changes - Start */
  max-height: 100%;
  /* Solr Changes - End */
}

.nav-panel-explore .context {
  font-size: calc(15 / var(--rem-base) * 1rem);
  flex-shrink: 0;
  /* Solr Removals - Start
  color: var(--nav-muted-color);
   Solr Removals - End */
  /* Solr Additions - Start */
  font-weight: var(--body-font-weight-bold);
  /* Solr Additions - End */
  box-shadow: 0 -1px 0 var(--nav-panel-divider-color);
  padding: 0 0.5rem;
  display: flex;
  align-items: center;
  justify-content: space-between;
  cursor: pointer;
  line-height: 1;
  height: var(--drawer-height);
}

.nav-panel-explore .context .version {
  display: flex;
  align-items: inherit;
}

.nav-panel-explore .context .version::after {
  content: "";
  background: url(../img/chevron.svg) no-repeat center right / auto 100%;
  width: 1.25em;
  height: 0.75em;
}

.nav-panel-explore .components {
  line-height: var(--doc-line-height);
  flex-grow: 1;
  box-shadow: inset 0 1px 5px var(--nav-panel-divider-color);
  background: var(--nav-secondary-background);
  padding: 0.5rem 0.75rem 0 0.75rem;
  margin: 0;
  overflow-y: scroll;
  max-height: 100%;
  display: block;
}

.nav-panel-explore:not(.is-active) .components {
  display: none;
}

.nav-panel-explore .component {
  display: block;
}

.nav-panel-explore .component + .component {
  margin-top: 0.5rem;
}

.nav-panel-explore .component:last-child {
  margin-bottom: 0.75rem;
}

.nav-panel-explore .component .title {
  font-weight: var(--body-font-weight-bold);
  color: inherit;
}

.nav-panel-explore .versions {
  display: flex;
  flex-wrap: wrap;
  list-style: none;
  padding-left: 0;
  margin-top: -0.25rem;
  line-height: 1;
}

.nav-panel-explore .component .version {
  display: block;
  margin: 0.375rem 0.375rem 0 0;
}

.nav-panel-explore .component .version a {
  border: 1px solid var(--nav-border-color);
  border-radius: 0.25rem;
  color: inherit;
  opacity: 0.75;
  white-space: nowrap;
  padding: 0.125em 0.25em;
  display: inherit;
}

.nav-panel-explore .component .is-current a {
  border-color: currentColor;
  opacity: 0.9;
  font-weight: var(--body-font-weight-bold);
}


text:
from google.cloud import domains_v1beta1

def sample_configure_dns_settings():
    # Create a client
    client = domains_v1beta1.DomainsClient()

    # Initialize request argument(s)
    request = domains_v1beta1.ConfigureDnsSettingsRequest(
        registration="registration_value",
    )

    # Make the request
    operation = client.configure_dns_settings(request=request)

    print("Waiting for operation to complete...")

    response = operation.result()

    # Handle the response
    print(response)

# [END domains_v1beta1_generated_Domains_ConfigureDnsSettings_sync]


text:
using System;
using System.Threading.Tasks;
using RawRabbit.Context;
using RawRabbit.Extensions.MessageSequence.Model;

namespace RawRabbit.Extensions.MessageSequence.Configuration.Abstraction
{
	public interface IMessageSequenceBuilder<TMessageContext> where TMessageContext : IMessageContext
	{
		IMessageSequenceBuilder<TMessageContext> When<TMessage>(Func<TMessage, TMessageContext, Task> func, Action<IStepOptionBuilder> options = null);
		MessageSequence<TMessage> Complete<TMessage>();
	}
}


text:
<?xml version="1.0" encoding="UTF-8"?>
<!--
  ~ Copyright (c) 2017, WSO2 Inc. (http://wso2.com) All Rights Reserved.
  ~
  ~ Licensed under the Apache License, Version 2.0 (the "License");
  ~ you may not use this file except in compliance with the License.
  ~ You may obtain a copy of the License at
  ~
  ~ http://www.apache.org/licenses/LICENSE-2.0
  ~
  ~ Unless required by applicable law or agreed to in writing, software
  ~ distributed under the License is distributed on an "AS IS" BASIS,
  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  ~ See the License for the specific language governing permissions and
  ~ limitations under the License.
  -->

<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">

    <parent>
        <groupId>org.wso2.is</groupId>
        <artifactId>wso2is-analytics-integration</artifactId>
        <version>5.8.0-beta5-SNAPSHOT</version>
        <relativePath>../pom.xml</relativePath>
    </parent>
    <modelVersion>4.0.0</modelVersion>
    <artifactId>test-results-service</artifactId>
    <name>Integration Test- Siddhi Events Service</name>

    <dependencies>
    <!-- Uncomment the following if you want to enable metrics & monitoring -->
    <!--
    <dependency>
       <groupId>org.wso2.msf4j</groupId>
       <artifactId>msf4j-analytics</artifactId>
    </dependency>
    -->
        <dependency>
            <groupId>io.swagger</groupId>
            <artifactId>swagger-annotations</artifactId>
            <version>1.5.8</version>
        </dependency>
        <dependency>
            <groupId>org.codehaus.jackson</groupId>
            <artifactId>jackson-mapper-asl</artifactId>
            <version>1.9.9</version>
        </dependency>
        <dependency>
            <groupId>org.codehaus.jackson</groupId>
            <artifactId>jackson-jaxrs</artifactId>
            <version>1.1.1</version>
        </dependency>
        <dependency>
            <groupId>org.wso2.msf4j</groupId>
            <artifactId>msf4j-core</artifactId>
        </dependency>
        <dependency>
            <groupId>org.testng</groupId>
            <artifactId>testng</artifactId>
            <optional>true</optional>
        </dependency>
    </dependencies>
    <build>
        <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-assembly-plugin</artifactId>
            <executions>
                <execution>
                    <phase>package</phase>
                    <goals>
                        <goal>single</goal>
                    </goals>
                </execution>
            </executions>
            <configuration>
                <archive>
                    <manifest>
                        <addClasspath>true</addClasspath>
                        <mainClass>org.wso2.sp.tests.eventscollector.Application</mainClass>
                    </manifest>
                </archive>
                <descriptorRefs>
                    <descriptorRef>jar-with-dependencies</descriptorRef>
                </descriptorRefs>
                <appendAssemblyId>false</appendAssemblyId>
            </configuration>
        </plugin>
        </plugins>
    </build>
    <properties>
    <microservice.mainClass>org.wso2.sp.tests.eventscollector.Application</microservice.mainClass>
	<maven.findbugsplugin.version.exclude>findbugs-exclude.xml</maven.findbugsplugin.version.exclude>
    </properties>

</project>


text:
Get a collection of photos from flickr and is able to search by tags

Part 1:
Your task, should you choose to accept it, is to build a single page app which will show the amazing collection of photo's on flickr tagged "coffee". This application must have the following attributes
Single Page App
Infinite Scroll
Responsive layout
Mobile Friendly
Part 2:
Extend your application to give users the ability to search by a tag and view a stream of photos matching the tag.
Search by tag
Infinite scroll
Responsive layout
Maintain browser history stack
(Bonus) tag/word prediction
(Extra bonus) preview of photos for predicted tag
Write and document any key design decisions you made

To submit your response
Feel free to use either a public or private repository on Bitbucket or github.
Either share this repository with chaitanya@beattheq.com or send us a link.
For bonus points, deploy the application to Heroku or AWS and send us a URL
For super bonus points, have your unit tests running using a CI tool such as Travis and status displayed in the README file in your repository.


text:
<!DOCTYPE html>
<link href="resources/flexbox.css" rel="stylesheet">


text:
% Recursive Least-Squares Algorithm with exponential weighting
%
% From S. Haykin, "Adaptive Filtering Theory (3rd Ed.)", Prentice Hall,
% Chapter 13.
%
% This file is part of the Kernel Adaptive Filtering Toolbox for Matlab.
% http://sourceforge.net/projects/kafbox/

classdef rls

    properties (GetAccess = 'public', SetAccess = 'private')
        lambda = .99; % forgetting factor
        c = 1E-4; % regularization
    end

    properties (GetAccess = 'public', SetAccess = 'private')
        P = []; % inverse correlation matrix
        w = []; % filter coefficients
    end

    methods

        function obj = rls(parameters) % constructor
            if (nargin > 0) % copy valid parameters
                for fn = fieldnames(parameters)',
                    if strmatch(fn,fieldnames(obj),'exact'),
                        obj.(fn{1}) = parameters.(fn{1});
                    end
                end
            end
        end

        function y_est = evaluate(obj,x) % evaluate the algorithm
            if numel(obj.w)>0
                y_est = x*obj.w;
            else
                y_est = zeros(size(x,1),1);
            end
        end

        function obj = train(obj,x,y) % train the algorithm
            if numel(obj.w)==0, % initialize
                m = length(x);
                obj.w = zeros(m,1);
                obj.P = obj.c\eye(m);
            end

            k = obj.P*x'/(obj.lambda+x*obj.P*x');
            z = y - x*obj.w;
            obj.w = obj.w + k*z;
            obj.P = obj.lambda\(obj.P - k*x*obj.P);
        end

    end
end


text:
ACCEPTED

#### According to
Index Fungorum

#### Published in
null

#### Original name
Trematosphaeria faginea Morgan

### Remarks
null


text:
#import "ViewController.h"
#import "NSString+Gender.h"

#define publicID 38783200

@implementation ViewController

#pragma mark - View lifecycle

- (void)viewDidLoad
{
    [super viewDidLoad];

    _vkontakte = [Vkontakte sharedInstance];
    _vkontakte.delegate = self;
    [_vkontakte checkIfUserInGroupId:publicID needToSignAfterChecking:NO];
    [self refreshButtonState];
}

- (void)refreshButtonState
{
    if (![_vkontakte isAuthorized])
    {
        [_loginB setTitle:@"Login"
                 forState:UIControlStateNormal];
        [self hideControls:YES];
    }
    else
    {
        [_loginB setTitle:@"Logout"
                 forState:UIControlStateNormal];
        [self hideControls:NO];
        [_vkontakte getUserInfo];
    }
}

- (void)hideControls:(BOOL)hide
{
    [_userImage setHidden:hide];
    [_userName setHidden:hide];
    [_userSurName setHidden:hide];
    [_userBDate setHidden:hide];
    [_userGender setHidden:hide];

    [_signToGroup setHidden:hide];
    [_postMessage setHidden:hide];
    [_postImage setHidden:hide];
    [_postMessageWithLink setHidden:hide];
    [_postImageWithLink setHidden:hide];
    [_postImageWithLinkAndText setHidden:hide];
}

- (void)viewDidUnload
{
    [super viewDidUnload];
    // Release any retained subviews of the main view.
    // e.g. self.myOutlet = nil;
}

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
    // Return YES for supported orientations
    return (interfaceOrientation != UIInterfaceOrientationPortraitUpsideDown);
}

- (IBAction)loginPressed:(id)sender
{
    if (![_vkontakte isAuthorized])
    {
        [_vkontakte authenticate];
    }
    else
    {
        [_vkontakte logout];
    }
}

-(IBAction)signToGroup:(id)sender{
    [_vkontakte checkIfUserInGroupId:publicID needToSignAfterChecking:YES];
}

- (IBAction)postMessagePressed:(id)sender
{
    [_vkontakte postMessageToWall:@"Vkontakte iOS SDK"];
}

- (IBAction)postImagePressed:(id)sender
{
    [_vkontakte postImageToWall:[UIImage imageNamed:@"iTunesArtwork"]];
}

- (IBAction)postMessageWithLinkPressed:(id)sender
{
    [_vkontakte postMessageToWall:@"Vkontakte iOS SDK"
                             link:[NSURL URLWithString:@"https://github.com/StonerHawk/Vkontakte-iOS-SDK"]];
}

- (IBAction)postImageWithTextPressed:(id)sender
{
    [_vkontakte postImageToWall:[UIImage imageNamed:@"iTunesArtwork"]
                           text:@"Vkontakte iOS SDK"];
}

- (IBAction)postImageWithTextAndLinkPressed:(id)sender
{
    [_vkontakte postImageToWall:[UIImage imageNamed:@"iTunesArtwork"]
                           text:@"Vkontakte iOS SDK"
                           link:[NSURL URLWithString:@"https://github.com/StonerHawk/Vkontakte-iOS-SDK"]];
}

#pragma mark - VkontakteDelegate

- (void)vkontakteDidFailedWithError:(NSError *)error
{
    [self dismissModalViewControllerAnimated:YES];
}

- (void)showVkontakteAuthController:(UIViewController *)controller
{
    if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad)
    {
        controller.modalPresentationStyle = UIModalPresentationFormSheet;
    }

    [self presentModalViewController:controller animated:YES];
}

- (void)vkontakteAuthControllerDidCancelled
{
    [self dismissModalViewControllerAnimated:YES];
}

- (void)vkontakteDidFinishLogin:(Vkontakte *)vkontakte
{
    [self dismissModalViewControllerAnimated:YES];
    [self refreshButtonState];
}

- (void)vkontakteDidFinishLogOut:(Vkontakte *)vkontakte
{
    [self refreshButtonState];
}

- (void)vkontakteDidFinishGettinUserInfo:(NSDictionary *)info
{
    NSLog(@"%@", info);

    NSString *photoUrl = [info objectForKey:@"photo_big"];
    NSData *photoData = [NSData dataWithContentsOfURL:[NSURL URLWithString:photoUrl]];
    _userImage.image = [UIImage imageWithData:photoData];

    _userName.text = [info objectForKey:@"first_name"];
    _userSurName.text = [info objectForKey:@"last_name"];
    _userBDate.text = [info objectForKey:@"bdate"];
    _userGender.text = [NSString stringWithGenderId:[[info objectForKey:@"sex"] intValue]];
}

- (void)vkontakteDidFinishPostingToWall:(NSDictionary *)responce
{
    NSLog(@"%@", responce);
}

-(void)vkontakteDidFinishCheckingIfUserSignedTheGroup:(NSDictionary *)info{
    NSNumber *response = [info objectForKey:@"response"];
    if ([response intValue]==1) {
        [_signToGroup setTitle:@"Вы уже подписаны на эту группу" forState:UIControlStateNormal];
    }else{
       [_signToGroup setTitle:@"Вы еще не подписаны на эту группу" forState:UIControlStateNormal];
    }
}

-(void)vkontakteDidFinishSigningTheGroup:(NSDictionary *)info{
    NSNumber *response = [info objectForKey:@"response"];
    if ([response intValue]==1) {
        [_signToGroup setTitle:@"Вы в нашей группе" forState:UIControlStateNormal];
        [_signToGroup setUserInteractionEnabled:NO];
        [_signToGroup setAlpha:0.9f];
    }
}

@end