// 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 #include #include #include #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 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 memory(new RefCountedStaticMemory( reinterpret_cast(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(); }