diff options
-rw-r--r-- | gfx/canvas.h | 4 | ||||
-rw-r--r-- | gfx/canvas_direct2d.cc | 219 | ||||
-rw-r--r-- | gfx/canvas_direct2d.h | 86 | ||||
-rw-r--r-- | gfx/canvas_direct2d_unittest.cc | 156 | ||||
-rw-r--r-- | gfx/canvas_skia.cc | 4 | ||||
-rw-r--r-- | gfx/canvas_skia.h | 6 | ||||
-rw-r--r-- | gfx/gfx.gyp | 15 |
7 files changed, 483 insertions, 7 deletions
diff --git a/gfx/canvas.h b/gfx/canvas.h index 430a88f..af1dd01 100644 --- a/gfx/canvas.h +++ b/gfx/canvas.h @@ -74,8 +74,8 @@ class Canvas { // at the specified alpha once Restore() is called. // |layer_bounds| are the bounds of the layer relative to the current // transform. - virtual void SaveLayerAlpha(U8CPU alpha) = 0; - virtual void SaveLayerAlpha(U8CPU alpha, const gfx::Rect& layer_bounds) = 0; + virtual void SaveLayerAlpha(uint8 alpha) = 0; + virtual void SaveLayerAlpha(uint8 alpha, const gfx::Rect& layer_bounds) = 0; // Restores the drawing state after a call to Save*(). It is an error to // call Restore() more times than Save*(). diff --git a/gfx/canvas_direct2d.cc b/gfx/canvas_direct2d.cc new file mode 100644 index 0000000..754882c --- /dev/null +++ b/gfx/canvas_direct2d.cc @@ -0,0 +1,219 @@ +// 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 "gfx/canvas_direct2d.h" + +#include "gfx/rect.h" + +namespace { + +// Converts a SkColor to a ColorF. +D2D1_COLOR_F SkColorToColorF(SkColor color) { + return D2D1::ColorF(static_cast<float>(SkColorGetR(color)) / 0xFF, + static_cast<float>(SkColorGetG(color)) / 0xFF, + static_cast<float>(SkColorGetB(color)) / 0xFF, + static_cast<float>(SkColorGetA(color)) / 0xFF); +} + +D2D1_RECT_F RectToRectF(int x, int y, int w, int h) { + return D2D1::RectF(static_cast<float>(x), static_cast<float>(y), + static_cast<float>(x + w), static_cast<float>(y + h)); +} + +D2D1_RECT_F RectToRectF(const gfx::Rect& rect) { + return RectToRectF(rect.x(), rect.y(), rect.width(), rect.height()); +} + +} // namespace + +namespace gfx { + +// static +ID2D1Factory* CanvasDirect2D::d2d1_factory_ = NULL; + +//////////////////////////////////////////////////////////////////////////////// +// CanvasDirect2D, public: + +CanvasDirect2D::CanvasDirect2D(ID2D1RenderTarget* rt) : rt_(rt) { + rt_->BeginDraw(); +} + +CanvasDirect2D::~CanvasDirect2D() { + rt_->EndDraw(); +} + +// static +ID2D1Factory* CanvasDirect2D::GetD2D1Factory() { + if (!d2d1_factory_) + D2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED, &d2d1_factory_); + return d2d1_factory_; +} + +//////////////////////////////////////////////////////////////////////////////// +// CanvasDirect2D, Canvas implementation: + +void CanvasDirect2D::Save() { + if (!drawing_state_block_) + GetD2D1Factory()->CreateDrawingStateBlock(drawing_state_block_.Receive()); + rt_->SaveDrawingState(drawing_state_block_.get()); + layers_.push(NULL); +} + +void CanvasDirect2D::SaveLayerAlpha(uint8 alpha) { + SaveLayerAlpha(alpha, gfx::Rect()); +} + +void CanvasDirect2D::SaveLayerAlpha(uint8 alpha, + const gfx::Rect& layer_bounds) { + D2D1_RECT_F bounds = D2D1::InfiniteRect(); + if (!layer_bounds.IsEmpty()) + bounds = RectToRectF(layer_bounds); + ID2D1Layer* layer = NULL; + HRESULT hr = rt_->CreateLayer(NULL, &layer); + if (SUCCEEDED(hr)) { + rt_->PushLayer(D2D1::LayerParameters(bounds, + NULL, + D2D1_ANTIALIAS_MODE_PER_PRIMITIVE, + D2D1::IdentityMatrix(), + static_cast<float>(alpha) / 0xFF, + NULL, + D2D1_LAYER_OPTIONS_NONE), + layer); + } + layers_.push(layer); +} + +void CanvasDirect2D::Restore() { + ID2D1Layer* layer = layers_.top(); + if (layer) { + rt_->PopLayer(); + layer->Release(); + } + layers_.pop(); + rt_->RestoreDrawingState(drawing_state_block_); +} + +bool CanvasDirect2D::GetClipRect(gfx::Rect* clip_rect) { + return false; +} + +bool CanvasDirect2D::ClipRectInt(int x, int y, int w, int h) { + return false; +} + +bool CanvasDirect2D::IntersectsClipRectInt(int x, int y, int w, int h) { + return false; +} + +void CanvasDirect2D::TranslateInt(int x, int y) { +} + +void CanvasDirect2D::ScaleInt(int x, int y) { +} + +void CanvasDirect2D::FillRectInt(int x, int y, int w, int h, + const SkPaint& paint) { +} + +void CanvasDirect2D::FillRectInt(const SkColor& color, int x, int y, int w, + int h) { + ScopedComPtr<ID2D1SolidColorBrush> solid_brush; + rt_->CreateSolidColorBrush(SkColorToColorF(color), solid_brush.Receive()); + rt_->FillRectangle(RectToRectF(x, y, w, h), solid_brush); +} + +void CanvasDirect2D::DrawRectInt(const SkColor& color, int x, int y, int w, + int h) { + +} + +void CanvasDirect2D::DrawRectInt(const SkColor& color, int x, int y, int w, + int h, SkXfermode::Mode mode) { + +} + +void CanvasDirect2D::DrawLineInt(const SkColor& color, int x1, int y1, int x2, + int y2) { + +} + +void CanvasDirect2D::DrawBitmapInt(const SkBitmap& bitmap, int x, int y) { +} + +void CanvasDirect2D::DrawBitmapInt(const SkBitmap& bitmap, int x, int y, + const SkPaint& paint) { + +} + +void CanvasDirect2D::DrawBitmapInt(const SkBitmap& bitmap, int src_x, int src_y, + int src_w, int src_h, int dest_x, int dest_y, + int dest_w, int dest_h, bool filter) { + +} + +void CanvasDirect2D::DrawBitmapInt(const SkBitmap& bitmap, int src_x, int src_y, + int src_w, int src_h, int dest_x, int dest_y, + int dest_w, int dest_h, bool filter, + const SkPaint& paint) { + +} + +void CanvasDirect2D::DrawStringInt(const std::wstring& text, + const gfx::Font& font, + const SkColor& color, int x, int y, int w, + int h) { + +} + +void CanvasDirect2D::DrawStringInt(const std::wstring& text, + const gfx::Font& font, + const SkColor& color, + const gfx::Rect& display_rect) { + +} + +void CanvasDirect2D::DrawStringInt(const std::wstring& text, + const gfx::Font& font, + const SkColor& color, + int x, int y, int w, int h, + int flags) { + +} + +void CanvasDirect2D::DrawFocusRect(int x, int y, int width, int height) { +} + +void CanvasDirect2D::TileImageInt(const SkBitmap& bitmap, int x, int y, int w, + int h) { +} + +void CanvasDirect2D::TileImageInt(const SkBitmap& bitmap, int src_x, int src_y, + int dest_x, int dest_y, int w, int h) { + +} + +gfx::NativeDrawingContext CanvasDirect2D::BeginPlatformPaint() { + DCHECK(!interop_rt_.get()); + interop_rt_.QueryFrom(rt_); + HDC dc = NULL; + if (interop_rt_.get()) + interop_rt_->GetDC(D2D1_DC_INITIALIZE_MODE_COPY, &dc); + return dc; +} + +void CanvasDirect2D::EndPlatformPaint() { + DCHECK(interop_rt_.get()); + interop_rt_->ReleaseDC(NULL); + interop_rt_.release(); +} + +CanvasSkia* CanvasDirect2D::AsCanvasSkia() { + return NULL; +} + +const CanvasSkia* CanvasDirect2D::AsCanvasSkia() const { + return NULL; +} + +} // namespace gfx diff --git a/gfx/canvas_direct2d.h b/gfx/canvas_direct2d.h new file mode 100644 index 0000000..f4bc143 --- /dev/null +++ b/gfx/canvas_direct2d.h @@ -0,0 +1,86 @@ +// 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. + +#ifndef GFX_CANVAS_DIRECT2D_H_ +#define GFX_CANVAS_DIRECT2D_H_ + +#include <d2d1.h> + +#include <stack> + +#include "base/scoped_comptr_win.h" +#include "gfx/canvas.h" + +namespace gfx { + +class CanvasDirect2D : public Canvas { + public: + // Creates an empty Canvas. + explicit CanvasDirect2D(ID2D1RenderTarget* rt); + virtual ~CanvasDirect2D(); + + // Retrieves the application's D2D1 Factory. + static ID2D1Factory* GetD2D1Factory(); + + // Overridden from Canvas: + virtual void Save(); + virtual void SaveLayerAlpha(uint8 alpha); + virtual void SaveLayerAlpha(uint8 alpha, const gfx::Rect& layer_bounds); + virtual void Restore(); + virtual bool GetClipRect(gfx::Rect* clip_rect); + virtual bool ClipRectInt(int x, int y, int w, int h); + virtual bool IntersectsClipRectInt(int x, int y, int w, int h); + virtual void TranslateInt(int x, int y); + virtual void ScaleInt(int x, int y); + virtual void FillRectInt(int x, int y, int w, int h, + const SkPaint& paint); + virtual void FillRectInt(const SkColor& color, int x, int y, int w, + int h); + virtual void DrawRectInt(const SkColor& color, int x, int y, int w, + int h); + virtual void DrawRectInt(const SkColor& color, int x, int y, int w, int h, + SkXfermode::Mode mode); + virtual void DrawLineInt(const SkColor& color, int x1, int y1, int x2, + int y2); + virtual void DrawBitmapInt(const SkBitmap& bitmap, int x, int y); + virtual void DrawBitmapInt(const SkBitmap& bitmap, int x, int y, + const SkPaint& paint); + virtual void DrawBitmapInt(const SkBitmap& bitmap, int src_x, int src_y, + int src_w, int src_h, int dest_x, int dest_y, + int dest_w, int dest_h, bool filter); + virtual void DrawBitmapInt(const SkBitmap& bitmap, int src_x, int src_y, + int src_w, int src_h, int dest_x, int dest_y, + int dest_w, int dest_h, bool filter, + const SkPaint& paint); + virtual void DrawStringInt(const std::wstring& text, const gfx::Font& font, + const SkColor& color, int x, int y, int w, + int h); + virtual void DrawStringInt(const std::wstring& text, const gfx::Font& font, + const SkColor& color, + const gfx::Rect& display_rect); + virtual void DrawStringInt(const std::wstring& text, const gfx::Font& font, + const SkColor& color, int x, int y, int w, int h, + int flags); + virtual void DrawFocusRect(int x, int y, int width, int height); + virtual void TileImageInt(const SkBitmap& bitmap, int x, int y, int w, int h); + virtual void TileImageInt(const SkBitmap& bitmap, int src_x, int src_y, + int dest_x, int dest_y, int w, int h); + virtual gfx::NativeDrawingContext BeginPlatformPaint(); + virtual void EndPlatformPaint(); + virtual CanvasSkia* AsCanvasSkia(); + virtual const CanvasSkia* AsCanvasSkia() const; + + private: + ID2D1RenderTarget* rt_; + ScopedComPtr<ID2D1GdiInteropRenderTarget> interop_rt_; + ScopedComPtr<ID2D1DrawingStateBlock> drawing_state_block_; + static ID2D1Factory* d2d1_factory_; + std::stack<ID2D1Layer*> layers_; + + DISALLOW_COPY_AND_ASSIGN(CanvasDirect2D); +}; + +} // namespace gfx; + +#endif // GFX_CANVAS_DIRECT2D_H_ diff --git a/gfx/canvas_direct2d_unittest.cc b/gfx/canvas_direct2d_unittest.cc new file mode 100644 index 0000000..0b5ce0f --- /dev/null +++ b/gfx/canvas_direct2d_unittest.cc @@ -0,0 +1,156 @@ +// 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 "gfx/canvas_direct2d.h" +#include "gfx/canvas_skia.h" +#include "gfx/native_theme_win.h" +#include "gfx/window_impl.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"; + +} // 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(); +} + diff --git a/gfx/canvas_skia.cc b/gfx/canvas_skia.cc index fbf26c9..d747f74 100644 --- a/gfx/canvas_skia.cc +++ b/gfx/canvas_skia.cc @@ -36,12 +36,12 @@ void CanvasSkia::Save() { save(); } -void CanvasSkia::SaveLayerAlpha(U8CPU alpha) { +void CanvasSkia::SaveLayerAlpha(uint8 alpha) { saveLayerAlpha(NULL, alpha); } -void CanvasSkia::SaveLayerAlpha(U8CPU alpha, const gfx::Rect& layer_bounds) { +void CanvasSkia::SaveLayerAlpha(uint8 alpha, const gfx::Rect& layer_bounds) { SkRect bounds; bounds.set(SkIntToScalar(layer_bounds.x()), SkIntToScalar(layer_bounds.y()), diff --git a/gfx/canvas_skia.h b/gfx/canvas_skia.h index e3633a5..115bd83 100644 --- a/gfx/canvas_skia.h +++ b/gfx/canvas_skia.h @@ -79,10 +79,10 @@ class CanvasSkia : public skia::PlatformCanvas, // Extracts a bitmap from the contents of this canvas. SkBitmap ExtractBitmap() const; - // Overridden from Canvas2: + // Overridden from Canvas: virtual void Save(); - virtual void SaveLayerAlpha(U8CPU alpha); - virtual void SaveLayerAlpha(U8CPU alpha, const gfx::Rect& layer_bounds); + virtual void SaveLayerAlpha(uint8 alpha); + virtual void SaveLayerAlpha(uint8 alpha, const gfx::Rect& layer_bounds); virtual void Restore(); virtual bool GetClipRect(gfx::Rect* clip_rect); virtual bool ClipRectInt(int x, int y, int w, int h); diff --git a/gfx/gfx.gyp b/gfx/gfx.gyp index 898b981..859c6f3f 100644 --- a/gfx/gfx.gyp +++ b/gfx/gfx.gyp @@ -33,9 +33,22 @@ 'conditions': [ ['OS=="win"', { 'sources': [ + 'canvas_direct2d_unittest.cc', 'icon_util_unittest.cc', 'native_theme_win_unittest.cc', ], + 'include_dirs': [ + '..', + '<(DEPTH)/third_party/wtl/include', + ], + 'msvs_settings': { + 'VCLinkerTool': { + 'AdditionalDependencies': [ + 'd2d1.lib', + 'd3d10_1.lib', + ], + }, + } }], ['OS=="linux" or OS=="freebsd" or OS=="openbsd"', { 'dependencies': [ @@ -107,6 +120,8 @@ 'conditions': [ ['OS=="win"', { 'sources': [ + 'canvas_direct2d.cc', + 'canvas_direct2d.h', 'gdi_util.cc', 'gdi_util.h', 'icon_util.cc', |