| // Copyright (c) 2010 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include <windows.h> |
| #include <uxtheme.h> |
| #include <vsstyle.h> |
| #include <vssym32.h> |
| |
| #include "base/command_line.h" |
| #include "base/ref_counted_memory.h" |
| #include "base/resource_util.h" |
| #include "base/scoped_ptr.h" |
| #include "gfx/brush.h" |
| #include "gfx/canvas_direct2d.h" |
| #include "gfx/canvas_skia.h" |
| #include "gfx/codec/png_codec.h" |
| #include "gfx/native_theme_win.h" |
| #include "gfx/window_impl.h" |
| #include "grit/gfx_resources.h" |
| #include "testing/gtest/include/gtest/gtest.h" |
| |
| |
| namespace { |
| |
| class TestWindow : public gfx::WindowImpl { |
| public: |
| static const int kWindowSize = 500; |
| static const int kWindowPosition = 10; |
| |
| static const wchar_t* kVisibleModeFlag; |
| |
| TestWindow() { |
| if (CommandLine::ForCurrentProcess()->HasSwitch(kVisibleModeFlag)) |
| Sleep(1000); |
| |
| // Create the window. |
| Init(NULL, |
| gfx::Rect(kWindowPosition, kWindowPosition, kWindowSize, kWindowSize)); |
| |
| // Initialize the RenderTarget for the window. |
| rt_ = MakeHWNDRenderTarget(); |
| |
| if (CommandLine::ForCurrentProcess()->HasSwitch(kVisibleModeFlag)) |
| ShowWindow(hwnd(), SW_SHOW); |
| } |
| virtual ~TestWindow() { |
| if (CommandLine::ForCurrentProcess()->HasSwitch(kVisibleModeFlag)) |
| Sleep(1000); |
| DestroyWindow(hwnd()); |
| } |
| |
| ID2D1RenderTarget* rt() const { return rt_.get(); } |
| |
| BEGIN_MSG_MAP_EX(TestWindow) |
| END_MSG_MAP() |
| |
| private: |
| ID2D1RenderTarget* MakeHWNDRenderTarget() { |
| D2D1_RENDER_TARGET_PROPERTIES rt_properties = |
| D2D1::RenderTargetProperties(); |
| rt_properties.usage = D2D1_RENDER_TARGET_USAGE_GDI_COMPATIBLE; |
| |
| ID2D1HwndRenderTarget* rt = NULL; |
| gfx::CanvasDirect2D::GetD2D1Factory()->CreateHwndRenderTarget( |
| rt_properties, |
| D2D1::HwndRenderTargetProperties(hwnd(), D2D1::SizeU(500, 500)), |
| &rt); |
| return rt; |
| } |
| |
| ScopedComPtr<ID2D1RenderTarget> rt_; |
| |
| DISALLOW_COPY_AND_ASSIGN(TestWindow); |
| }; |
| |
| // static |
| const wchar_t* TestWindow::kVisibleModeFlag = L"d2d-canvas-visible"; |
| |
| // Loads a png data blob from the data resources associated with this |
| // executable, decodes it and returns a SkBitmap. |
| SkBitmap LoadBitmapFromResources(int resource_id) { |
| SkBitmap bitmap; |
| |
| HINSTANCE resource_instance = _AtlBaseModule.GetResourceInstance(); |
| void* data_ptr; |
| size_t data_size; |
| if (base::GetDataResourceFromModule(resource_instance, resource_id, &data_ptr, |
| &data_size)) { |
| scoped_refptr<RefCountedMemory> memory(new RefCountedStaticMemory( |
| reinterpret_cast<const unsigned char*>(data_ptr), data_size)); |
| if (!memory) |
| return bitmap; |
| |
| if (!gfx::PNGCodec::Decode(memory->front(), memory->size(), &bitmap)) |
| NOTREACHED() << "Unable to decode theme image resource " << resource_id; |
| } |
| return bitmap; |
| } |
| |
| } // namespace |
| |
| TEST(CanvasDirect2D, CreateCanvas) { |
| TestWindow window; |
| gfx::CanvasDirect2D canvas(window.rt()); |
| } |
| |
| TEST(CanvasDirect2D, SaveRestoreNesting) { |
| TestWindow window; |
| gfx::CanvasDirect2D canvas(window.rt()); |
| |
| // Simple. |
| canvas.Save(); |
| canvas.Restore(); |
| |
| // Nested. |
| canvas.Save(); |
| canvas.Save(); |
| canvas.Restore(); |
| canvas.Restore(); |
| |
| // Simple alpha. |
| canvas.SaveLayerAlpha(127); |
| canvas.Restore(); |
| |
| // Alpha with sub-rect. |
| canvas.SaveLayerAlpha(127, gfx::Rect(20, 20, 100, 100)); |
| canvas.Restore(); |
| |
| // Nested alpha. |
| canvas.Save(); |
| canvas.SaveLayerAlpha(127); |
| canvas.Save(); |
| canvas.Restore(); |
| canvas.Restore(); |
| canvas.Restore(); |
| } |
| |
| TEST(CanvasDirect2D, SaveLayerAlpha) { |
| TestWindow window; |
| gfx::CanvasDirect2D canvas(window.rt()); |
| |
| canvas.Save(); |
| canvas.FillRectInt(SK_ColorBLUE, 20, 20, 100, 100); |
| canvas.SaveLayerAlpha(127); |
| canvas.FillRectInt(SK_ColorRED, 60, 60, 100, 100); |
| canvas.Restore(); |
| canvas.Restore(); |
| } |
| |
| TEST(CanvasDirect2D, SaveLayerAlphaWithBounds) { |
| TestWindow window; |
| gfx::CanvasDirect2D canvas(window.rt()); |
| |
| canvas.Save(); |
| canvas.FillRectInt(SK_ColorBLUE, 20, 20, 100, 100); |
| canvas.SaveLayerAlpha(127, gfx::Rect(60, 60, 50, 50)); |
| canvas.FillRectInt(SK_ColorRED, 60, 60, 100, 100); |
| canvas.Restore(); |
| canvas.Restore(); |
| } |
| |
| TEST(CanvasDirect2D, FillRect) { |
| TestWindow window; |
| gfx::CanvasDirect2D canvas(window.rt()); |
| |
| canvas.FillRectInt(SK_ColorRED, 20, 20, 100, 100); |
| } |
| |
| TEST(CanvasDirect2D, PlatformPainting) { |
| TestWindow window; |
| gfx::CanvasDirect2D canvas(window.rt()); |
| |
| gfx::NativeDrawingContext dc = canvas.BeginPlatformPaint(); |
| |
| // Use the system theme engine to draw a native button. This only works on a |
| // GDI device context. |
| RECT r = { 20, 20, 220, 80 }; |
| gfx::NativeTheme::instance()->PaintButton( |
| dc, BP_PUSHBUTTON, PBS_NORMAL, DFCS_BUTTONPUSH, &r); |
| |
| canvas.EndPlatformPaint(); |
| } |
| |
| TEST(CanvasDirect2D, ClipRect) { |
| TestWindow window; |
| gfx::CanvasDirect2D canvas(window.rt()); |
| |
| canvas.FillRectInt(SK_ColorGREEN, 0, 0, 500, 500); |
| canvas.ClipRectInt(20, 20, 120, 120); |
| canvas.FillRectInt(SK_ColorBLUE, 0, 0, 500, 500); |
| } |
| |
| TEST(CanvasDirect2D, ClipRectWithTranslate) { |
| TestWindow window; |
| gfx::CanvasDirect2D canvas(window.rt()); |
| |
| // Repeat the same rendering as in ClipRect... |
| canvas.Save(); |
| canvas.FillRectInt(SK_ColorGREEN, 0, 0, 500, 500); |
| canvas.ClipRectInt(20, 20, 120, 120); |
| canvas.FillRectInt(SK_ColorBLUE, 0, 0, 500, 500); |
| canvas.Restore(); |
| |
| // ... then translate, clip and fill again relative to the new origin. |
| canvas.Save(); |
| canvas.TranslateInt(150, 150); |
| canvas.ClipRectInt(10, 10, 110, 110); |
| canvas.FillRectInt(SK_ColorRED, 0, 0, 500, 500); |
| canvas.Restore(); |
| } |
| |
| TEST(CanvasDirect2D, ClipRectWithScale) { |
| TestWindow window; |
| gfx::CanvasDirect2D canvas(window.rt()); |
| |
| // Repeat the same rendering as in ClipRect... |
| canvas.Save(); |
| canvas.FillRectInt(SK_ColorGREEN, 0, 0, 500, 500); |
| canvas.ClipRectInt(20, 20, 120, 120); |
| canvas.FillRectInt(SK_ColorBLUE, 0, 0, 500, 500); |
| canvas.Restore(); |
| |
| // ... then translate and scale, clip and fill again relative to the new |
| // origin. |
| canvas.Save(); |
| canvas.TranslateInt(150, 150); |
| canvas.ScaleInt(2, 2); |
| canvas.ClipRectInt(10, 10, 110, 110); |
| canvas.FillRectInt(SK_ColorRED, 0, 0, 500, 500); |
| canvas.Restore(); |
| } |
| |
| TEST(CanvasDirect2D, DrawRectInt) { |
| TestWindow window; |
| gfx::CanvasDirect2D canvas(window.rt()); |
| |
| canvas.Save(); |
| canvas.DrawRectInt(SK_ColorRED, 10, 10, 200, 200); |
| canvas.Restore(); |
| } |
| |
| TEST(CanvasDirect2D, DrawLineInt) { |
| TestWindow window; |
| gfx::CanvasDirect2D canvas(window.rt()); |
| |
| canvas.Save(); |
| canvas.DrawLineInt(SK_ColorRED, 10, 10, 210, 210); |
| canvas.Restore(); |
| } |
| |
| TEST(CanvasDirect2D, DrawBitmapInt) { |
| TestWindow window; |
| gfx::CanvasDirect2D canvas(window.rt()); |
| |
| SkBitmap bitmap = LoadBitmapFromResources(IDR_BITMAP_BRUSH_IMAGE); |
| |
| canvas.Save(); |
| canvas.DrawBitmapInt(bitmap, 100, 100); |
| canvas.Restore(); |
| } |
| |
| TEST(CanvasDirect2D, DrawBitmapInt2) { |
| TestWindow window; |
| gfx::CanvasDirect2D canvas(window.rt()); |
| |
| SkBitmap bitmap = LoadBitmapFromResources(IDR_BITMAP_BRUSH_IMAGE); |
| |
| canvas.Save(); |
| canvas.DrawBitmapInt(bitmap, 5, 5, 30, 30, 10, 10, 30, 30, false); |
| canvas.DrawBitmapInt(bitmap, 5, 5, 30, 30, 110, 110, 100, 100, true); |
| canvas.DrawBitmapInt(bitmap, 5, 5, 30, 30, 220, 220, 100, 100, false); |
| canvas.Restore(); |
| } |
| |
| TEST(CanvasDirect2D, TileImageInt) { |
| TestWindow window; |
| gfx::CanvasDirect2D canvas(window.rt()); |
| |
| SkBitmap bitmap = LoadBitmapFromResources(IDR_BITMAP_BRUSH_IMAGE); |
| |
| canvas.Save(); |
| canvas.TileImageInt(bitmap, 10, 10, 300, 300); |
| canvas.Restore(); |
| } |