OLD | NEW |
| (Empty) |
1 // Copyright (c) 2010 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 <windows.h> | |
6 #include <uxtheme.h> | |
7 #include <vsstyle.h> | |
8 #include <vssym32.h> | |
9 | |
10 #include "base/command_line.h" | |
11 #include "base/ref_counted_memory.h" | |
12 #include "base/resource_util.h" | |
13 #include "base/scoped_ptr.h" | |
14 #include "gfx/brush.h" | |
15 #include "gfx/canvas_direct2d.h" | |
16 #include "gfx/canvas_skia.h" | |
17 #include "gfx/codec/png_codec.h" | |
18 #include "gfx/native_theme_win.h" | |
19 #include "gfx/rect.h" | |
20 #include "gfx/win_util.h" | |
21 #include "grit/gfx_resources.h" | |
22 #include "testing/gtest/include/gtest/gtest.h" | |
23 | |
24 | |
25 namespace { | |
26 | |
27 const char kVisibleModeFlag[] = "d2d-canvas-visible"; | |
28 const wchar_t kWindowClassName[] = L"GFXD2DTestWindowClass"; | |
29 | |
30 class TestWindow { | |
31 public: | |
32 static const int kWindowSize = 500; | |
33 static const int kWindowPosition = 10; | |
34 | |
35 TestWindow() : hwnd_(NULL) { | |
36 if (CommandLine::ForCurrentProcess()->HasSwitch(kVisibleModeFlag)) | |
37 Sleep(1000); | |
38 | |
39 RegisterMyClass(); | |
40 | |
41 hwnd_ = CreateWindowEx(0, kWindowClassName, NULL, | |
42 WS_OVERLAPPEDWINDOW, | |
43 kWindowPosition, kWindowPosition, | |
44 kWindowSize, kWindowSize, | |
45 NULL, NULL, NULL, this); | |
46 DCHECK(hwnd_); | |
47 | |
48 // Initialize the RenderTarget for the window. | |
49 rt_ = MakeHWNDRenderTarget(); | |
50 | |
51 if (CommandLine::ForCurrentProcess()->HasSwitch(kVisibleModeFlag)) | |
52 ShowWindow(hwnd(), SW_SHOW); | |
53 } | |
54 virtual ~TestWindow() { | |
55 if (CommandLine::ForCurrentProcess()->HasSwitch(kVisibleModeFlag)) | |
56 Sleep(1000); | |
57 DestroyWindow(hwnd()); | |
58 UnregisterMyClass(); | |
59 } | |
60 | |
61 HWND hwnd() const { return hwnd_; } | |
62 | |
63 ID2D1RenderTarget* rt() const { return rt_.get(); } | |
64 | |
65 private: | |
66 ID2D1RenderTarget* MakeHWNDRenderTarget() { | |
67 D2D1_RENDER_TARGET_PROPERTIES rt_properties = | |
68 D2D1::RenderTargetProperties(); | |
69 rt_properties.usage = D2D1_RENDER_TARGET_USAGE_GDI_COMPATIBLE; | |
70 | |
71 ID2D1HwndRenderTarget* rt = NULL; | |
72 gfx::CanvasDirect2D::GetD2D1Factory()->CreateHwndRenderTarget( | |
73 rt_properties, | |
74 D2D1::HwndRenderTargetProperties(hwnd(), D2D1::SizeU(500, 500)), | |
75 &rt); | |
76 return rt; | |
77 } | |
78 | |
79 void RegisterMyClass() { | |
80 WNDCLASSEX class_ex; | |
81 class_ex.cbSize = sizeof(WNDCLASSEX); | |
82 class_ex.style = CS_DBLCLKS; | |
83 class_ex.lpfnWndProc = &DefWindowProc; | |
84 class_ex.cbClsExtra = 0; | |
85 class_ex.cbWndExtra = 0; | |
86 class_ex.hInstance = NULL; | |
87 class_ex.hIcon = NULL; | |
88 class_ex.hCursor = LoadCursor(NULL, IDC_ARROW); | |
89 class_ex.hbrBackground = reinterpret_cast<HBRUSH>(COLOR_BACKGROUND); | |
90 class_ex.lpszMenuName = NULL; | |
91 class_ex.lpszClassName = kWindowClassName; | |
92 class_ex.hIconSm = class_ex.hIcon; | |
93 ATOM atom = RegisterClassEx(&class_ex); | |
94 DCHECK(atom); | |
95 } | |
96 | |
97 void UnregisterMyClass() { | |
98 ::UnregisterClass(kWindowClassName, NULL); | |
99 } | |
100 | |
101 HWND hwnd_; | |
102 | |
103 ScopedComPtr<ID2D1RenderTarget> rt_; | |
104 | |
105 DISALLOW_COPY_AND_ASSIGN(TestWindow); | |
106 }; | |
107 | |
108 // Loads a png data blob from the data resources associated with this | |
109 // executable, decodes it and returns a SkBitmap. | |
110 SkBitmap LoadBitmapFromResources(int resource_id) { | |
111 SkBitmap bitmap; | |
112 | |
113 HINSTANCE resource_instance = GetModuleHandle(NULL); | |
114 void* data_ptr; | |
115 size_t data_size; | |
116 if (base::GetDataResourceFromModule(resource_instance, resource_id, &data_ptr, | |
117 &data_size)) { | |
118 scoped_refptr<RefCountedMemory> memory(new RefCountedStaticMemory( | |
119 reinterpret_cast<const unsigned char*>(data_ptr), data_size)); | |
120 if (!memory) | |
121 return bitmap; | |
122 | |
123 if (!gfx::PNGCodec::Decode(memory->front(), memory->size(), &bitmap)) | |
124 NOTREACHED() << "Unable to decode theme image resource " << resource_id; | |
125 } | |
126 return bitmap; | |
127 } | |
128 | |
129 bool CheckForD2DCompatibility() { | |
130 if (!gfx::Direct2dIsAvailable()) { | |
131 LOG(WARNING) << "Test is disabled as it requires either Windows 7 or " << | |
132 "Vista with Platform Update KB971644"; | |
133 return false; | |
134 } | |
135 return true; | |
136 } | |
137 | |
138 } // namespace | |
139 | |
140 TEST(CanvasDirect2D, CreateCanvas) { | |
141 if (!CheckForD2DCompatibility()) | |
142 return; | |
143 TestWindow window; | |
144 gfx::CanvasDirect2D canvas(window.rt()); | |
145 } | |
146 | |
147 TEST(CanvasDirect2D, SaveRestoreNesting) { | |
148 if (!CheckForD2DCompatibility()) | |
149 return; | |
150 TestWindow window; | |
151 gfx::CanvasDirect2D canvas(window.rt()); | |
152 | |
153 // Simple. | |
154 canvas.Save(); | |
155 canvas.Restore(); | |
156 | |
157 // Nested. | |
158 canvas.Save(); | |
159 canvas.Save(); | |
160 canvas.Restore(); | |
161 canvas.Restore(); | |
162 | |
163 // Simple alpha. | |
164 canvas.SaveLayerAlpha(127); | |
165 canvas.Restore(); | |
166 | |
167 // Alpha with sub-rect. | |
168 canvas.SaveLayerAlpha(127, gfx::Rect(20, 20, 100, 100)); | |
169 canvas.Restore(); | |
170 | |
171 // Nested alpha. | |
172 canvas.Save(); | |
173 canvas.SaveLayerAlpha(127); | |
174 canvas.Save(); | |
175 canvas.Restore(); | |
176 canvas.Restore(); | |
177 canvas.Restore(); | |
178 } | |
179 | |
180 TEST(CanvasDirect2D, SaveLayerAlpha) { | |
181 if (!CheckForD2DCompatibility()) | |
182 return; | |
183 TestWindow window; | |
184 gfx::CanvasDirect2D canvas(window.rt()); | |
185 | |
186 canvas.Save(); | |
187 canvas.FillRectInt(SK_ColorBLUE, 20, 20, 100, 100); | |
188 canvas.SaveLayerAlpha(127); | |
189 canvas.FillRectInt(SK_ColorRED, 60, 60, 100, 100); | |
190 canvas.Restore(); | |
191 canvas.Restore(); | |
192 } | |
193 | |
194 TEST(CanvasDirect2D, SaveLayerAlphaWithBounds) { | |
195 if (!CheckForD2DCompatibility()) | |
196 return; | |
197 TestWindow window; | |
198 gfx::CanvasDirect2D canvas(window.rt()); | |
199 | |
200 canvas.Save(); | |
201 canvas.FillRectInt(SK_ColorBLUE, 20, 20, 100, 100); | |
202 canvas.SaveLayerAlpha(127, gfx::Rect(60, 60, 50, 50)); | |
203 canvas.FillRectInt(SK_ColorRED, 60, 60, 100, 100); | |
204 canvas.Restore(); | |
205 canvas.Restore(); | |
206 } | |
207 | |
208 TEST(CanvasDirect2D, FillRect) { | |
209 if (!CheckForD2DCompatibility()) | |
210 return; | |
211 TestWindow window; | |
212 gfx::CanvasDirect2D canvas(window.rt()); | |
213 | |
214 canvas.FillRectInt(SK_ColorRED, 20, 20, 100, 100); | |
215 } | |
216 | |
217 TEST(CanvasDirect2D, PlatformPainting) { | |
218 if (!CheckForD2DCompatibility()) | |
219 return; | |
220 TestWindow window; | |
221 gfx::CanvasDirect2D canvas(window.rt()); | |
222 | |
223 gfx::NativeDrawingContext dc = canvas.BeginPlatformPaint(); | |
224 | |
225 // Use the system theme engine to draw a native button. This only works on a | |
226 // GDI device context. | |
227 RECT r = { 20, 20, 220, 80 }; | |
228 gfx::NativeTheme::instance()->PaintButton( | |
229 dc, BP_PUSHBUTTON, PBS_NORMAL, DFCS_BUTTONPUSH, &r); | |
230 | |
231 canvas.EndPlatformPaint(); | |
232 } | |
233 | |
234 TEST(CanvasDirect2D, ClipRect) { | |
235 if (!CheckForD2DCompatibility()) | |
236 return; | |
237 TestWindow window; | |
238 gfx::CanvasDirect2D canvas(window.rt()); | |
239 | |
240 canvas.FillRectInt(SK_ColorGREEN, 0, 0, 500, 500); | |
241 canvas.ClipRectInt(20, 20, 120, 120); | |
242 canvas.FillRectInt(SK_ColorBLUE, 0, 0, 500, 500); | |
243 } | |
244 | |
245 TEST(CanvasDirect2D, ClipRectWithTranslate) { | |
246 if (!CheckForD2DCompatibility()) | |
247 return; | |
248 TestWindow window; | |
249 gfx::CanvasDirect2D canvas(window.rt()); | |
250 | |
251 // Repeat the same rendering as in ClipRect... | |
252 canvas.Save(); | |
253 canvas.FillRectInt(SK_ColorGREEN, 0, 0, 500, 500); | |
254 canvas.ClipRectInt(20, 20, 120, 120); | |
255 canvas.FillRectInt(SK_ColorBLUE, 0, 0, 500, 500); | |
256 canvas.Restore(); | |
257 | |
258 // ... then translate, clip and fill again relative to the new origin. | |
259 canvas.Save(); | |
260 canvas.TranslateInt(150, 150); | |
261 canvas.ClipRectInt(10, 10, 110, 110); | |
262 canvas.FillRectInt(SK_ColorRED, 0, 0, 500, 500); | |
263 canvas.Restore(); | |
264 } | |
265 | |
266 TEST(CanvasDirect2D, ClipRectWithScale) { | |
267 if (!CheckForD2DCompatibility()) | |
268 return; | |
269 TestWindow window; | |
270 gfx::CanvasDirect2D canvas(window.rt()); | |
271 | |
272 // Repeat the same rendering as in ClipRect... | |
273 canvas.Save(); | |
274 canvas.FillRectInt(SK_ColorGREEN, 0, 0, 500, 500); | |
275 canvas.ClipRectInt(20, 20, 120, 120); | |
276 canvas.FillRectInt(SK_ColorBLUE, 0, 0, 500, 500); | |
277 canvas.Restore(); | |
278 | |
279 // ... then translate and scale, clip and fill again relative to the new | |
280 // origin. | |
281 canvas.Save(); | |
282 canvas.TranslateInt(150, 150); | |
283 canvas.ScaleInt(2, 2); | |
284 canvas.ClipRectInt(10, 10, 110, 110); | |
285 canvas.FillRectInt(SK_ColorRED, 0, 0, 500, 500); | |
286 canvas.Restore(); | |
287 } | |
288 | |
289 TEST(CanvasDirect2D, DrawRectInt) { | |
290 if (!CheckForD2DCompatibility()) | |
291 return; | |
292 TestWindow window; | |
293 gfx::CanvasDirect2D canvas(window.rt()); | |
294 | |
295 canvas.Save(); | |
296 canvas.DrawRectInt(SK_ColorRED, 10, 10, 200, 200); | |
297 canvas.Restore(); | |
298 } | |
299 | |
300 TEST(CanvasDirect2D, DrawLineInt) { | |
301 if (!CheckForD2DCompatibility()) | |
302 return; | |
303 TestWindow window; | |
304 gfx::CanvasDirect2D canvas(window.rt()); | |
305 | |
306 canvas.Save(); | |
307 canvas.DrawLineInt(SK_ColorRED, 10, 10, 210, 210); | |
308 canvas.Restore(); | |
309 } | |
310 | |
311 TEST(CanvasDirect2D, DrawBitmapInt) { | |
312 if (!CheckForD2DCompatibility()) | |
313 return; | |
314 TestWindow window; | |
315 gfx::CanvasDirect2D canvas(window.rt()); | |
316 | |
317 SkBitmap bitmap = LoadBitmapFromResources(IDR_BITMAP_BRUSH_IMAGE); | |
318 | |
319 canvas.Save(); | |
320 canvas.DrawBitmapInt(bitmap, 100, 100); | |
321 canvas.Restore(); | |
322 } | |
323 | |
324 TEST(CanvasDirect2D, DrawBitmapInt2) { | |
325 if (!CheckForD2DCompatibility()) | |
326 return; | |
327 TestWindow window; | |
328 gfx::CanvasDirect2D canvas(window.rt()); | |
329 | |
330 SkBitmap bitmap = LoadBitmapFromResources(IDR_BITMAP_BRUSH_IMAGE); | |
331 | |
332 canvas.Save(); | |
333 canvas.DrawBitmapInt(bitmap, 5, 5, 30, 30, 10, 10, 30, 30, false); | |
334 canvas.DrawBitmapInt(bitmap, 5, 5, 30, 30, 110, 110, 100, 100, true); | |
335 canvas.DrawBitmapInt(bitmap, 5, 5, 30, 30, 220, 220, 100, 100, false); | |
336 canvas.Restore(); | |
337 } | |
338 | |
339 TEST(CanvasDirect2D, TileImageInt) { | |
340 if (!CheckForD2DCompatibility()) | |
341 return; | |
342 TestWindow window; | |
343 gfx::CanvasDirect2D canvas(window.rt()); | |
344 | |
345 SkBitmap bitmap = LoadBitmapFromResources(IDR_BITMAP_BRUSH_IMAGE); | |
346 | |
347 canvas.Save(); | |
348 canvas.TileImageInt(bitmap, 10, 10, 300, 300); | |
349 canvas.Restore(); | |
350 } | |
OLD | NEW |