1// Copyright 2012 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "base/containers/hash_tables.h"
6#include "cc/layers/append_quads_data.h"
7#include "cc/layers/nine_patch_layer_impl.h"
8#include "cc/quads/texture_draw_quad.h"
9#include "cc/resources/ui_resource_bitmap.h"
10#include "cc/resources/ui_resource_client.h"
11#include "cc/test/fake_impl_proxy.h"
12#include "cc/test/fake_ui_resource_layer_tree_host_impl.h"
13#include "cc/test/geometry_test_utils.h"
14#include "cc/test/layer_test_common.h"
15#include "cc/test/mock_quad_culler.h"
16#include "cc/trees/single_thread_proxy.h"
17#include "testing/gmock/include/gmock/gmock.h"
18#include "testing/gtest/include/gtest/gtest.h"
19#include "ui/gfx/rect_conversions.h"
20#include "ui/gfx/safe_integer_conversions.h"
21#include "ui/gfx/transform.h"
22
23namespace cc {
24namespace {
25
26gfx::Rect ToRoundedIntRect(gfx::RectF rect_f) {
27  return gfx::Rect(gfx::ToRoundedInt(rect_f.x()),
28                   gfx::ToRoundedInt(rect_f.y()),
29                   gfx::ToRoundedInt(rect_f.width()),
30                   gfx::ToRoundedInt(rect_f.height()));
31}
32
33void NinePatchLayerLayoutTest(gfx::Size bitmap_size,
34                              gfx::Rect aperture_rect,
35                              gfx::Size layer_size,
36                              gfx::Rect border,
37                              bool fill_center,
38                              size_t expected_quad_size) {
39  MockQuadCuller quad_culler;
40  gfx::Rect visible_content_rect(layer_size);
41  gfx::Rect expected_remaining(border.x(),
42                               border.y(),
43                               layer_size.width() - border.width(),
44                               layer_size.height() - border.height());
45
46  FakeImplProxy proxy;
47  FakeUIResourceLayerTreeHostImpl host_impl(&proxy);
48  scoped_ptr<NinePatchLayerImpl> layer =
49      NinePatchLayerImpl::Create(host_impl.active_tree(), 1);
50  layer->draw_properties().visible_content_rect = visible_content_rect;
51  layer->SetBounds(layer_size);
52  layer->SetContentBounds(layer_size);
53  layer->CreateRenderSurface();
54  layer->draw_properties().render_target = layer.get();
55
56  UIResourceId uid = 1;
57  SkBitmap skbitmap;
58  skbitmap.setConfig(
59      SkBitmap::kARGB_8888_Config, bitmap_size.width(), bitmap_size.height());
60  skbitmap.allocPixels();
61  skbitmap.setImmutable();
62  UIResourceBitmap bitmap(skbitmap);
63
64  host_impl.CreateUIResource(uid, bitmap);
65  layer->SetUIResourceId(uid);
66  layer->SetImageBounds(bitmap_size);
67  layer->SetLayout(aperture_rect, border, fill_center);
68  AppendQuadsData data;
69  layer->AppendQuads(&quad_culler, &data);
70
71  // Verify quad rects
72  const QuadList& quads = quad_culler.quad_list();
73  EXPECT_EQ(expected_quad_size, quads.size());
74
75  Region remaining(visible_content_rect);
76  for (size_t i = 0; i < quads.size(); ++i) {
77    DrawQuad* quad = quads[i];
78    gfx::Rect quad_rect = quad->rect;
79
80    EXPECT_TRUE(visible_content_rect.Contains(quad_rect)) << i;
81    EXPECT_TRUE(remaining.Contains(quad_rect)) << i;
82    remaining.Subtract(Region(quad_rect));
83  }
84
85  // Check if the left-over quad is the same size as the mapped aperture quad in
86  // layer space.
87  if (!fill_center) {
88    EXPECT_RECT_EQ(expected_remaining, gfx::ToEnclosedRect(remaining.bounds()));
89  } else {
90    EXPECT_TRUE(remaining.bounds().IsEmpty());
91  }
92
93  // Verify UV rects
94  gfx::Rect bitmap_rect(bitmap_size);
95  Region tex_remaining(bitmap_rect);
96  for (size_t i = 0; i < quads.size(); ++i) {
97    DrawQuad* quad = quads[i];
98    const TextureDrawQuad* tex_quad = TextureDrawQuad::MaterialCast(quad);
99    gfx::RectF tex_rect =
100        gfx::BoundingRect(tex_quad->uv_top_left, tex_quad->uv_bottom_right);
101    tex_rect.Scale(bitmap_size.width(), bitmap_size.height());
102    tex_remaining.Subtract(Region(ToRoundedIntRect(tex_rect)));
103  }
104
105  if (!fill_center) {
106    EXPECT_RECT_EQ(aperture_rect, tex_remaining.bounds());
107    Region aperture_region(aperture_rect);
108    EXPECT_EQ(aperture_region, tex_remaining);
109  } else {
110    EXPECT_TRUE(remaining.bounds().IsEmpty());
111  }
112}
113
114TEST(NinePatchLayerImplTest, VerifyDrawQuads) {
115  // Input is a 100x100 bitmap with a 40x50 aperture at x=20, y=30.
116  // The bounds of the layer are set to 400x400.
117  gfx::Size bitmap_size(100, 100);
118  gfx::Size layer_size(400, 500);
119  gfx::Rect aperture_rect(20, 30, 40, 50);
120  gfx::Rect border(40, 40, 80, 80);
121  bool fill_center = false;
122  size_t expected_quad_size = 8;
123  NinePatchLayerLayoutTest(bitmap_size,
124                           aperture_rect,
125                           layer_size,
126                           border,
127                           fill_center,
128                           expected_quad_size);
129
130  // The bounds of the layer are set to less than the bitmap size.
131  bitmap_size = gfx::Size(100, 100);
132  layer_size = gfx::Size(40, 50);
133  aperture_rect = gfx::Rect(20, 30, 40, 50);
134  border = gfx::Rect(10, 10, 25, 15);
135  fill_center = true;
136  expected_quad_size = 9;
137  NinePatchLayerLayoutTest(bitmap_size,
138                           aperture_rect,
139                           layer_size,
140                           border,
141                           fill_center,
142                           expected_quad_size);
143
144  // Layer and image sizes are equal.
145  bitmap_size = gfx::Size(100, 100);
146  layer_size = gfx::Size(100, 100);
147  aperture_rect = gfx::Rect(20, 30, 40, 50);
148  border = gfx::Rect(20, 30, 40, 50);
149  fill_center = true;
150  expected_quad_size = 9;
151  NinePatchLayerLayoutTest(bitmap_size,
152                           aperture_rect,
153                           layer_size,
154                           border,
155                           fill_center,
156                           expected_quad_size);
157}
158
159}  // namespace
160}  // namespace cc
161