| 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 |