1// Copyright (c) 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 "content/renderer/pepper/pepper_graphics_2d_host.h"
6
7#include "base/basictypes.h"
8#include "base/message_loop/message_loop.h"
9#include "content/renderer/pepper/gfx_conversion.h"
10#include "content/renderer/pepper/mock_renderer_ppapi_host.h"
11#include "content/renderer/pepper/ppb_image_data_impl.h"
12#include "ppapi/shared_impl/ppb_view_shared.h"
13#include "ppapi/shared_impl/proxy_lock.h"
14#include "ppapi/shared_impl/test_globals.h"
15#include "testing/gtest/include/gtest/gtest.h"
16#include "third_party/WebKit/public/platform/WebCanvas.h"
17#include "third_party/skia/include/core/SkCanvas.h"
18#include "ui/events/latency_info.h"
19#include "ui/gfx/point.h"
20#include "ui/gfx/rect.h"
21
22using blink::WebCanvas;
23
24namespace content {
25
26class PepperGraphics2DHostTest : public testing::Test {
27 public:
28  static bool ConvertToLogicalPixels(float scale,
29                                     gfx::Rect* op_rect,
30                                     gfx::Point* delta) {
31    return PepperGraphics2DHost::ConvertToLogicalPixels(scale, op_rect, delta);
32  }
33
34  PepperGraphics2DHostTest() : renderer_ppapi_host_(NULL, 12345) {}
35
36  virtual ~PepperGraphics2DHostTest() {
37    ppapi::ProxyAutoLock proxy_lock;
38    host_.reset();
39  }
40
41  void Init(PP_Instance instance,
42            const PP_Size& backing_store_size,
43            const PP_Rect& plugin_rect) {
44    renderer_view_data_.rect = plugin_rect;
45    test_globals_.GetResourceTracker()->DidCreateInstance(instance);
46    scoped_refptr<PPB_ImageData_Impl> backing_store(
47        new PPB_ImageData_Impl(instance, PPB_ImageData_Impl::ForTest()));
48    host_.reset(PepperGraphics2DHost::Create(&renderer_ppapi_host_,
49                                             instance,
50                                             12345,
51                                             backing_store_size,
52                                             PP_FALSE,
53                                             backing_store));
54    DCHECK(host_.get());
55  }
56
57  void PaintImageData(PPB_ImageData_Impl* image_data) {
58    ppapi::HostResource image_data_resource;
59    image_data_resource.SetHostResource(image_data->pp_instance(),
60                                        image_data->pp_resource());
61    host_->OnHostMsgPaintImageData(
62        NULL, image_data_resource, PP_Point(), false, PP_Rect());
63  }
64
65  void Flush() {
66    ppapi::host::HostMessageContext context(
67        ppapi::proxy::ResourceMessageCallParams(host_->pp_resource(), 0));
68    std::vector<ui::LatencyInfo> latency;
69    host_->OnHostMsgFlush(&context, latency);
70    host_->ViewFlushedPaint();
71    host_->SendOffscreenFlushAck();
72  }
73
74  void PaintToWebCanvas(SkBitmap* bitmap) {
75    scoped_ptr<WebCanvas> canvas(new WebCanvas(*bitmap));
76    gfx::Rect plugin_rect(PP_ToGfxRect(renderer_view_data_.rect));
77    host_->Paint(canvas.get(),
78                 plugin_rect,
79                 gfx::Rect(0, 0, plugin_rect.width(), plugin_rect.height()));
80  }
81
82  void ResetPageBitmap(SkBitmap* bitmap) {
83    PP_Rect plugin_rect = renderer_view_data_.rect;
84    int width = plugin_rect.point.x + plugin_rect.size.width;
85    int height = plugin_rect.point.y + plugin_rect.size.height;
86    if (bitmap->isNull() || bitmap->width() != width ||
87        bitmap->height() != height) {
88      bitmap->allocN32Pixels(width, height);
89    }
90    bitmap->eraseColor(0);
91  }
92
93 private:
94  ppapi::ViewData renderer_view_data_;
95  scoped_ptr<PepperGraphics2DHost> host_;
96  base::MessageLoop message_loop_;
97  MockRendererPpapiHost renderer_ppapi_host_;
98  ppapi::TestGlobals test_globals_;
99};
100
101TEST_F(PepperGraphics2DHostTest, ConvertToLogicalPixels) {
102  static const struct {
103    int x1;
104    int y1;
105    int w1;
106    int h1;
107    int x2;
108    int y2;
109    int w2;
110    int h2;
111    int dx1;
112    int dy1;
113    int dx2;
114    int dy2;
115    float scale;
116    bool result;
117  } tests[] = {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1.0, true},
118               {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2.0, true},
119               {0, 0, 4, 4, 0, 0, 2, 2, 0, 0, 0, 0, 0.5, true},
120               {1, 1, 4, 4, 0, 0, 3, 3, 0, 0, 0, 0, 0.5, false},
121               {53, 75, 100, 100, 53, 75, 100, 100, 0, 0, 0, 0, 1.0, true},
122               {53, 75, 100, 100, 106, 150, 200, 200, 0, 0, 0, 0, 2.0, true},
123               {53, 75, 100, 100, 26, 37, 51, 51, 0, 0, 0, 0, 0.5, false},
124               {53, 74, 100, 100, 26, 37, 51, 50, 0, 0, 0, 0, 0.5, false},
125               {-1, -1, 100, 100, -1, -1, 51, 51, 0, 0, 0, 0, 0.5, false},
126               {-2, -2, 100, 100, -1, -1, 50, 50, 4, -4, 2, -2, 0.5, true},
127               {-101, -100, 50, 50, -51, -50, 26, 25, 0, 0, 0, 0, 0.5, false},
128               {10, 10, 20, 20, 5, 5, 10, 10, 0, 0, 0, 0, 0.5, true},
129               // Cannot scroll due to partial coverage on sides
130               {11, 10, 20, 20, 5, 5, 11, 10, 0, 0, 0, 0, 0.5, false},
131               // Can scroll since backing store is actually smaller/scaling up
132               {11, 20, 100, 100, 22, 40, 200, 200, 7, 3, 14, 6, 2.0, true},
133               // Can scroll due to delta and bounds being aligned
134               {10, 10, 20, 20, 5, 5, 10, 10, 6, 4, 3, 2, 0.5, true},
135               // Cannot scroll due to dx
136               {10, 10, 20, 20, 5, 5, 10, 10, 5, 4, 2, 2, 0.5, false},
137               // Cannot scroll due to dy
138               {10, 10, 20, 20, 5, 5, 10, 10, 6, 3, 3, 1, 0.5, false},
139               // Cannot scroll due to top
140               {10, 11, 20, 20, 5, 5, 10, 11, 6, 4, 3, 2, 0.5, false},
141               // Cannot scroll due to left
142               {7, 10, 20, 20, 3, 5, 11, 10, 6, 4, 3, 2, 0.5, false},
143               // Cannot scroll due to width
144               {10, 10, 21, 20, 5, 5, 11, 10, 6, 4, 3, 2, 0.5, false},
145               // Cannot scroll due to height
146               {10, 10, 20, 51, 5, 5, 10, 26, 6, 4, 3, 2, 0.5, false},
147               // Check negative scroll deltas
148               {10, 10, 20, 20, 5, 5, 10, 10, -6, -4, -3, -2, 0.5, true},
149               {10, 10, 20, 20, 5, 5, 10, 10, -6, -3, -3, -1, 0.5, false}, };
150  for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) {
151    gfx::Rect r1(tests[i].x1, tests[i].y1, tests[i].w1, tests[i].h1);
152    gfx::Rect r2(tests[i].x2, tests[i].y2, tests[i].w2, tests[i].h2);
153    gfx::Rect orig = r1;
154    gfx::Point delta(tests[i].dx1, tests[i].dy1);
155    bool res = ConvertToLogicalPixels(tests[i].scale, &r1, &delta);
156    EXPECT_EQ(r2.ToString(), r1.ToString());
157    EXPECT_EQ(res, tests[i].result);
158    if (res) {
159      EXPECT_EQ(delta, gfx::Point(tests[i].dx2, tests[i].dy2));
160    }
161    // Reverse the scale and ensure all the original pixels are still inside
162    // the result.
163    ConvertToLogicalPixels(1.0f / tests[i].scale, &r1, NULL);
164    EXPECT_TRUE(r1.Contains(orig));
165  }
166}
167
168}  // namespace content
169