summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorben@chromium.org <ben@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-07-09 19:48:35 +0000
committerben@chromium.org <ben@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-07-09 19:48:35 +0000
commit7ee62626cfe9952c2e2c7f34f91f128b1cea8835 (patch)
tree0d87619ba52572e89956a763edfae023730b7348
parent1280270eea827aca9b676aced264a25a26efa36a (diff)
downloadchromium_src-7ee62626cfe9952c2e2c7f34f91f128b1cea8835.zip
chromium_src-7ee62626cfe9952c2e2c7f34f91f128b1cea8835.tar.gz
chromium_src-7ee62626cfe9952c2e2c7f34f91f128b1cea8835.tar.bz2
Start implementing Direct2D Canvas. Implements Save/Restore methods, FillRectInt and BeginPlatformPaint/EndPlatformPaint.http://crbug.com/48583TEST=see unittest
Review URL: http://codereview.chromium.org/2939001 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@51996 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--gfx/canvas.h4
-rw-r--r--gfx/canvas_direct2d.cc219
-rw-r--r--gfx/canvas_direct2d.h86
-rw-r--r--gfx/canvas_direct2d_unittest.cc156
-rw-r--r--gfx/canvas_skia.cc4
-rw-r--r--gfx/canvas_skia.h6
-rw-r--r--gfx/gfx.gyp15
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',