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 <stdio.h>
6
7#include "cc/layers/append_quads_data.h"
8#include "cc/layers/nine_patch_layer_impl.h"
9#include "cc/quads/texture_draw_quad.h"
10#include "cc/test/fake_impl_proxy.h"
11#include "cc/test/fake_layer_tree_host_impl.h"
12#include "cc/test/geometry_test_utils.h"
13#include "cc/test/layer_test_common.h"
14#include "cc/test/mock_quad_culler.h"
15#include "cc/trees/single_thread_proxy.h"
16#include "testing/gmock/include/gmock/gmock.h"
17#include "testing/gtest/include/gtest/gtest.h"
18#include "ui/gfx/rect_conversions.h"
19#include "ui/gfx/safe_integer_conversions.h"
20#include "ui/gfx/transform.h"
21
22namespace cc {
23namespace {
24
25gfx::Rect ToRoundedIntRect(gfx::RectF rect_f) {
26  return gfx::Rect(gfx::ToRoundedInt(rect_f.x()),
27                   gfx::ToRoundedInt(rect_f.y()),
28                   gfx::ToRoundedInt(rect_f.width()),
29                   gfx::ToRoundedInt(rect_f.height()));
30}
31
32TEST(NinePatchLayerImplTest, VerifyDrawQuads) {
33  // Input is a 100x100 bitmap with a 40x50 aperture at x=20, y=30.
34  // The bounds of the layer are set to 400x400, so the draw quads
35  // generated should leave the border width (40) intact.
36  MockQuadCuller quad_culler;
37  gfx::Size bitmap_size(100, 100);
38  gfx::Size layer_size(400, 400);
39  gfx::Rect visible_content_rect(layer_size);
40  gfx::Rect aperture_rect(20, 30, 40, 50);
41  gfx::Rect scaled_aperture_non_uniform(20, 30, 340, 350);
42
43  FakeImplProxy proxy;
44  FakeLayerTreeHostImpl host_impl(&proxy);
45  scoped_ptr<NinePatchLayerImpl> layer =
46      NinePatchLayerImpl::Create(host_impl.active_tree(), 1);
47  layer->draw_properties().visible_content_rect = visible_content_rect;
48  layer->SetBounds(layer_size);
49  layer->SetContentBounds(layer_size);
50  layer->CreateRenderSurface();
51  layer->draw_properties().render_target = layer.get();
52  layer->SetLayout(bitmap_size, aperture_rect);
53  layer->SetResourceId(1);
54
55  // This scale should not affect the generated quad geometry, but only
56  // the shared draw transform.
57  gfx::Transform transform;
58  transform.Scale(10, 10);
59  layer->draw_properties().target_space_transform = transform;
60
61  AppendQuadsData data;
62  layer->AppendQuads(&quad_culler, &data);
63
64  // Verify quad rects
65  const QuadList& quads = quad_culler.quad_list();
66  EXPECT_EQ(8u, quads.size());
67  Region remaining(visible_content_rect);
68  for (size_t i = 0; i < quads.size(); ++i) {
69    DrawQuad* quad = quads[i];
70    gfx::Rect quad_rect = quad->rect;
71
72    EXPECT_TRUE(visible_content_rect.Contains(quad_rect)) << i;
73    EXPECT_TRUE(remaining.Contains(quad_rect)) << i;
74    EXPECT_EQ(transform, quad->quadTransform());
75    remaining.Subtract(Region(quad_rect));
76  }
77  EXPECT_RECT_EQ(scaled_aperture_non_uniform, remaining.bounds());
78  Region scaled_aperture_region(scaled_aperture_non_uniform);
79  EXPECT_EQ(scaled_aperture_region, remaining);
80
81  // Verify UV rects
82  gfx::Rect bitmap_rect(bitmap_size);
83  Region tex_remaining(bitmap_rect);
84  for (size_t i = 0; i < quads.size(); ++i) {
85    DrawQuad* quad = quads[i];
86    const TextureDrawQuad* tex_quad = TextureDrawQuad::MaterialCast(quad);
87    gfx::RectF tex_rect =
88        gfx::BoundingRect(tex_quad->uv_top_left, tex_quad->uv_bottom_right);
89    tex_rect.Scale(bitmap_size.width(), bitmap_size.height());
90    tex_remaining.Subtract(Region(ToRoundedIntRect(tex_rect)));
91  }
92  EXPECT_RECT_EQ(aperture_rect, tex_remaining.bounds());
93  Region aperture_region(aperture_rect);
94  EXPECT_EQ(aperture_region, tex_remaining);
95}
96
97TEST(NinePatchLayerImplTest, VerifyDrawQuadsForSqueezedLayer) {
98  // Test with a layer much smaller than the bitmap.
99  MockQuadCuller quad_culler;
100  gfx::Size bitmap_size(101, 101);
101  gfx::Size layer_size(51, 51);
102  gfx::Rect visible_content_rect(layer_size);
103  gfx::Rect aperture_rect(20, 30, 40, 45);  // rightWidth: 40, botHeight: 25
104
105  FakeImplProxy proxy;
106  FakeLayerTreeHostImpl host_impl(&proxy);
107  scoped_ptr<NinePatchLayerImpl> layer =
108      NinePatchLayerImpl::Create(host_impl.active_tree(), 1);
109  layer->draw_properties().visible_content_rect = visible_content_rect;
110  layer->SetBounds(layer_size);
111  layer->SetContentBounds(layer_size);
112  layer->CreateRenderSurface();
113  layer->draw_properties().render_target = layer.get();
114  layer->SetLayout(bitmap_size, aperture_rect);
115  layer->SetResourceId(1);
116
117  AppendQuadsData data;
118  layer->AppendQuads(&quad_culler, &data);
119
120  // Verify corner rects fill the layer and don't overlap
121  const QuadList& quads = quad_culler.quad_list();
122  EXPECT_EQ(4u, quads.size());
123  Region filled;
124  for (size_t i = 0; i < quads.size(); ++i) {
125    DrawQuad* quad = quads[i];
126    gfx::Rect quad_rect = quad->rect;
127
128    EXPECT_FALSE(filled.Intersects(quad_rect));
129    filled.Union(quad_rect);
130  }
131  Region expected_full(visible_content_rect);
132  EXPECT_EQ(expected_full, filled);
133
134  // Verify UV rects cover the corners of the bitmap and the crop is weighted
135  // proportionately to the relative corner sizes (for uneven apertures).
136  gfx::Rect bitmap_rect(bitmap_size);
137  Region tex_remaining(bitmap_rect);
138  for (size_t i = 0; i < quads.size(); ++i) {
139    DrawQuad* quad = quads[i];
140    const TextureDrawQuad* tex_quad = TextureDrawQuad::MaterialCast(quad);
141    gfx::RectF tex_rect =
142        gfx::BoundingRect(tex_quad->uv_top_left, tex_quad->uv_bottom_right);
143    tex_rect.Scale(bitmap_size.width(), bitmap_size.height());
144    tex_remaining.Subtract(Region(ToRoundedIntRect(tex_rect)));
145  }
146  Region expected_remaining_region = Region(gfx::Rect(bitmap_size));
147  expected_remaining_region.Subtract(gfx::Rect(0, 0, 17, 28));
148  expected_remaining_region.Subtract(gfx::Rect(67, 0, 34, 28));
149  expected_remaining_region.Subtract(gfx::Rect(0, 78, 17, 23));
150  expected_remaining_region.Subtract(gfx::Rect(67, 78, 34, 23));
151  EXPECT_EQ(expected_remaining_region, tex_remaining);
152}
153
154}  // namespace
155}  // namespace cc
156