summaryrefslogtreecommitdiffstats
path: root/gfx
diff options
context:
space:
mode:
authorben@chromium.org <ben@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-07-29 18:17:04 +0000
committerben@chromium.org <ben@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-07-29 18:17:04 +0000
commit2caf4d005cb3b86b61ae559f08f2493e19129e3f (patch)
tree95e9eb1d2ec77fc179f5fdc26573db1449a5afb4 /gfx
parent797794bd42c10ff1dfecc25f91ec32a17d991b15 (diff)
downloadchromium_src-2caf4d005cb3b86b61ae559f08f2493e19129e3f.zip
chromium_src-2caf4d005cb3b86b61ae559f08f2493e19129e3f.tar.gz
chromium_src-2caf4d005cb3b86b61ae559f08f2493e19129e3f.tar.bz2
Add support for Radial Gradient Brush and Bitmap Brush to gfx::Canvas.
BUG=none TEST=see unittest Review URL: http://codereview.chromium.org/3058012 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@54148 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'gfx')
-rw-r--r--gfx/canvas.h34
-rw-r--r--gfx/canvas_direct2d.cc93
-rw-r--r--gfx/canvas_direct2d.h11
-rw-r--r--gfx/canvas_direct2d_unittest.cc60
-rw-r--r--gfx/canvas_skia.cc34
-rw-r--r--gfx/canvas_skia.h11
-rw-r--r--gfx/gfx.gyp49
7 files changed, 274 insertions, 18 deletions
diff --git a/gfx/canvas.h b/gfx/canvas.h
index 52857a4..6b59c6d 100644
--- a/gfx/canvas.h
+++ b/gfx/canvas.h
@@ -207,9 +207,9 @@ class Canvas {
// |positions| is a list of positions corresponding to the color stops, an
// array of floats of increasing value ranging from 0.0f to 1.0f.
// |position_count| is the size of the |colors| and |positions| arrays.
- // |tile_mode|
- // Returns an encapsulated platform shader object which the caller must
- // delete.
+ // |tile_mode| specifies how the gradient brush repeats outside its natural
+ // bounds.
+ // Returns an encapsulated platform brush object which the caller must delete.
virtual Brush* CreateLinearGradientBrush(
const gfx::Point& start_point,
const gfx::Point& end_point,
@@ -218,6 +218,34 @@ class Canvas {
size_t position_count,
TileMode tile_mode) = 0;
+ // Creates a radial gradient brush.
+ // |center_point| is the center of the circle in the brush's coordinate space.
+ // |radius| is the radius of the circle.
+ // |colors| is a list of color stops.
+ // |positions| is a list of positions corresponding to the color stops, an
+ // array of floats of increasing value ranging from 0.0f to 1.0f.
+ // |position_count| is the size of the |colors| and |positions| arrays.
+ // |tile_mode| specifies how the gradient brush repeats outside its natural
+ // bounds.
+ // Returns an encapsulated platform brush object which the caller must delete.
+ virtual Brush* CreateRadialGradientBrush(
+ const gfx::Point& center_point,
+ float radius,
+ const SkColor colors[],
+ const float positions[],
+ size_t position_count,
+ TileMode tile_mode) = 0;
+
+ // Creates a bitmap brush.
+ // |bitmap| is the bitmap to be used for the brush.
+ // |tile_mode_x,y| - specifies how the brush tiles the areas beyond those
+ // filled by its bitmap along each axis.
+ // Returns an encapsulated platform brush object which the caller must delete.
+ virtual Brush* CreateBitmapBrush(
+ const SkBitmap& bitmap,
+ TileMode tile_mode_x,
+ TileMode tile_mode_y) = 0;
+
// TODO(beng): remove this once we don't need to use any skia-specific methods
// through this interface.
// A quick and dirty way to obtain the underlying SkCanvas.
diff --git a/gfx/canvas_direct2d.cc b/gfx/canvas_direct2d.cc
index e18272c..406078d 100644
--- a/gfx/canvas_direct2d.cc
+++ b/gfx/canvas_direct2d.cc
@@ -4,6 +4,7 @@
#include "gfx/canvas_direct2d.h"
+#include "base/scoped_ptr.h"
#include "gfx/rect.h"
namespace {
@@ -44,6 +45,28 @@ D2D1_EXTEND_MODE TileModeToExtendMode(gfx::Canvas::TileMode tile_mode) {
return D2D1_EXTEND_MODE_CLAMP;
}
+ID2D1GradientStopCollection* CreateGradientStopCollection(
+ ID2D1RenderTarget* render_target,
+ const SkColor colors[],
+ const float positions[],
+ size_t position_count,
+ gfx::Canvas::TileMode tile_mode) {
+ scoped_array<D2D1_GRADIENT_STOP> gradient_stops(
+ new D2D1_GRADIENT_STOP[position_count]);
+ for (size_t i = 0; i < position_count; ++i) {
+ gradient_stops[i].color = SkColorToColorF(colors[i]);
+ gradient_stops[i].position = positions[i];
+ }
+ ID2D1GradientStopCollection* gradient_stop_collection = NULL;
+ HRESULT hr = render_target->CreateGradientStopCollection(
+ gradient_stops.get(),
+ position_count,
+ D2D1_GAMMA_2_2,
+ TileModeToExtendMode(tile_mode),
+ &gradient_stop_collection);
+ return SUCCEEDED(hr) ? gradient_stop_collection : NULL;
+}
+
// A platform wrapper for a Direct2D brush that makes sure the underlying
// ID2D1Brush COM object is released when this object is destroyed.
class Direct2DBrush : public gfx::Brush {
@@ -280,28 +303,70 @@ Brush* CanvasDirect2D::CreateLinearGradientBrush(
const float positions[],
size_t position_count,
TileMode tile_mode) {
- ID2D1GradientStopCollection* gradient_stop_collection = NULL;
- D2D1_GRADIENT_STOP* gradient_stops = new D2D1_GRADIENT_STOP[position_count];
- for (size_t i = 0; i < position_count; ++i) {
- gradient_stops[i].color = SkColorToColorF(colors[i]);
- gradient_stops[i].position = positions[i];
- }
- HRESULT hr = rt_->CreateGradientStopCollection(gradient_stops,
- position_count,
- D2D1_GAMMA_2_2,
- TileModeToExtendMode(tile_mode),
- &gradient_stop_collection);
- if (FAILED(hr))
+ ScopedComPtr<ID2D1GradientStopCollection> gradient_stop_collection(
+ CreateGradientStopCollection(rt_, colors, positions, position_count,
+ tile_mode));
+ if (!gradient_stop_collection.get())
return NULL;
ID2D1LinearGradientBrush* brush = NULL;
- hr = rt_->CreateLinearGradientBrush(
+ HRESULT hr = rt_->CreateLinearGradientBrush(
D2D1::LinearGradientBrushProperties(PointToPoint2F(start_point),
PointToPoint2F(end_point)),
gradient_stop_collection,
&brush);
+ return SUCCEEDED(hr) ? new Direct2DBrush(brush) : NULL;
+}
+
+Brush* CanvasDirect2D::CreateRadialGradientBrush(
+ const gfx::Point& center_point,
+ float radius,
+ const SkColor colors[],
+ const float positions[],
+ size_t position_count,
+ TileMode tile_mode) {
+ ScopedComPtr<ID2D1GradientStopCollection> gradient_stop_collection(
+ CreateGradientStopCollection(rt_, colors, positions, position_count,
+ tile_mode));
+ if (!gradient_stop_collection.get())
+ return NULL;
- return new Direct2DBrush(brush);
+ ID2D1RadialGradientBrush* brush = NULL;
+ HRESULT hr = rt_->CreateRadialGradientBrush(
+ D2D1::RadialGradientBrushProperties(PointToPoint2F(center_point),
+ PointToPoint2F(gfx::Point()),
+ radius,
+ radius),
+ gradient_stop_collection,
+ &brush);
+ return SUCCEEDED(hr) ? new Direct2DBrush(brush) : NULL;
+}
+
+Brush* CanvasDirect2D::CreateBitmapBrush(
+ const SkBitmap& bitmap,
+ TileMode tile_mode_x,
+ TileMode tile_mode_y) {
+ ScopedComPtr<ID2D1Bitmap> d2d1_bitmap;
+ HRESULT hr = rt_->CreateBitmap(
+ D2D1::SizeU(bitmap.width(), bitmap.height()),
+ NULL,
+ NULL,
+ D2D1::BitmapProperties(
+ D2D1::PixelFormat(DXGI_FORMAT_B8G8R8A8_UNORM,
+ D2D1_ALPHA_MODE_IGNORE)),
+ d2d1_bitmap.Receive());
+ bitmap.lockPixels();
+ d2d1_bitmap->CopyFromMemory(NULL, bitmap.getPixels(), bitmap.rowBytes());
+ bitmap.unlockPixels();
+
+ ID2D1BitmapBrush* brush = NULL;
+ hr = rt_->CreateBitmapBrush(
+ d2d1_bitmap,
+ D2D1::BitmapBrushProperties(TileModeToExtendMode(tile_mode_x),
+ TileModeToExtendMode(tile_mode_y)),
+ D2D1::BrushProperties(),
+ &brush);
+ return SUCCEEDED(hr) ? new Direct2DBrush(brush) : NULL;
}
CanvasSkia* CanvasDirect2D::AsCanvasSkia() {
diff --git a/gfx/canvas_direct2d.h b/gfx/canvas_direct2d.h
index 7ff973b..4cd5cd4 100644
--- a/gfx/canvas_direct2d.h
+++ b/gfx/canvas_direct2d.h
@@ -75,6 +75,17 @@ class CanvasDirect2D : public Canvas {
const float positions[],
size_t position_count,
TileMode tile_mode);
+ virtual Brush* CreateRadialGradientBrush(
+ const gfx::Point& center_point,
+ float radius,
+ const SkColor colors[],
+ const float positions[],
+ size_t position_count,
+ TileMode tile_mode);
+ virtual Brush* CreateBitmapBrush(
+ const SkBitmap& bitmap,
+ TileMode tile_mode_x,
+ TileMode tile_mode_y);
virtual CanvasSkia* AsCanvasSkia();
virtual const CanvasSkia* AsCanvasSkia() const;
diff --git a/gfx/canvas_direct2d_unittest.cc b/gfx/canvas_direct2d_unittest.cc
index d8c02c1..ff63302 100644
--- a/gfx/canvas_direct2d_unittest.cc
+++ b/gfx/canvas_direct2d_unittest.cc
@@ -8,13 +8,18 @@
#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/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 {
@@ -71,6 +76,27 @@ class TestWindow : public gfx::WindowImpl {
// 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) {
@@ -221,3 +247,37 @@ TEST(CanvasDirect2D, CreateLinearGradientBrush) {
canvas.FillRectInt(brush.get(), 0, 0, 500, 500);
canvas.Restore();
}
+
+TEST(CanvasDirect2D, CreateRadialGradientBrush) {
+ TestWindow window;
+ gfx::CanvasDirect2D canvas(window.rt());
+
+ canvas.Save();
+ SkColor colors[] = { SK_ColorBLUE, SK_ColorGREEN };
+ float positions[] = { 0.0f, 1.0f };
+ scoped_ptr<gfx::Brush> brush(canvas.CreateRadialGradientBrush(
+ gfx::Point(200, 200),
+ 100.0f,
+ colors,
+ positions,
+ 2,
+ gfx::Canvas::TileMode_Clamp));
+ canvas.FillRectInt(brush.get(), 0, 0, 500, 500);
+ canvas.Restore();
+}
+
+TEST(CanvasDirect2D, CreateBitmapBrush) {
+ TestWindow window;
+ gfx::CanvasDirect2D canvas(window.rt());
+
+ SkBitmap bitmap = LoadBitmapFromResources(IDR_BITMAP_BRUSH_IMAGE);
+
+ canvas.Save();
+ scoped_ptr<gfx::Brush> brush(canvas.CreateBitmapBrush(
+ bitmap,
+ gfx::Canvas::TileMode_Mirror,
+ gfx::Canvas::TileMode_Mirror));
+ canvas.FillRectInt(brush.get(), 0, 0, 500, 500);
+ canvas.Restore();
+}
+
diff --git a/gfx/canvas_skia.cc b/gfx/canvas_skia.cc
index fbdc0a9..f2c344c 100644
--- a/gfx/canvas_skia.cc
+++ b/gfx/canvas_skia.cc
@@ -18,6 +18,12 @@
namespace {
+SkPoint PointToSkPoint(const gfx::Point point) {
+ SkPoint sk_point;
+ sk_point.set(SkIntToScalar(point.x()), SkIntToScalar(point.y()));
+ return sk_point;
+}
+
SkShader::TileMode TileModeToSkShaderTileMode(gfx::Canvas::TileMode tile_mode) {
switch (tile_mode) {
case gfx::Canvas::TileMode_Clamp:
@@ -364,6 +370,34 @@ Brush* CanvasSkia::CreateLinearGradientBrush(
return new SkiaShader(shader);
}
+Brush* CanvasSkia::CreateRadialGradientBrush(
+ const gfx::Point& center_point,
+ float radius,
+ const SkColor colors[],
+ const float positions[],
+ size_t position_count,
+ TileMode tile_mode) {
+ SkShader* shader = SkGradientShader::CreateRadial(
+ PointToSkPoint(center_point),
+ radius,
+ colors,
+ positions,
+ position_count,
+ TileModeToSkShaderTileMode(tile_mode));
+ return new SkiaShader(shader);
+}
+
+Brush* CanvasSkia::CreateBitmapBrush(
+ const SkBitmap& bitmap,
+ TileMode tile_mode_x,
+ TileMode tile_mode_y) {
+ SkShader* shader = SkShader::CreateBitmapShader(
+ bitmap,
+ TileModeToSkShaderTileMode(tile_mode_x),
+ TileModeToSkShaderTileMode(tile_mode_y));
+ return new SkiaShader(shader);
+}
+
CanvasSkia* CanvasSkia::AsCanvasSkia() {
return this;
}
diff --git a/gfx/canvas_skia.h b/gfx/canvas_skia.h
index 5187ad6..71fbb42 100644
--- a/gfx/canvas_skia.h
+++ b/gfx/canvas_skia.h
@@ -131,6 +131,17 @@ class CanvasSkia : public skia::PlatformCanvas,
const float positions[],
size_t position_count,
TileMode tile_mode);
+ virtual Brush* CreateRadialGradientBrush(
+ const gfx::Point& center_point,
+ float radius,
+ const SkColor colors[],
+ const float positions[],
+ size_t position_count,
+ TileMode tile_mode);
+ virtual Brush* CreateBitmapBrush(
+ const SkBitmap& bitmap,
+ TileMode tile_mode_x,
+ TileMode tile_mode_y);
virtual CanvasSkia* AsCanvasSkia();
virtual const CanvasSkia* AsCanvasSkia() const;
diff --git a/gfx/gfx.gyp b/gfx/gfx.gyp
index e3eeb66..5947c4a 100644
--- a/gfx/gfx.gyp
+++ b/gfx/gfx.gyp
@@ -5,6 +5,9 @@
{
'variables': {
'chromium_code': 1,
+ 'grit_info_cmd': ['python', '../tools/grit/grit_info.py'],
+ 'grit_cmd': ['python', '../tools/grit/grit.py'],
+ 'grit_out_dir': '<(SHARED_INTERMEDIATE_DIR)/gfx',
},
'targets': [
{
@@ -13,6 +16,7 @@
'msvs_guid': 'C8BD2821-EAE5-4AC6-A0E4-F82CAC2956CC',
'dependencies': [
'gfx',
+ 'gfx_resources',
'../skia/skia.gyp:skia',
'../testing/gtest.gyp:gtest',
],
@@ -27,6 +31,7 @@
'run_all_unittests.cc',
'skbitmap_operations_unittest.cc',
'test_suite.h',
+ '<(SHARED_INTERMEDIATE_DIR)/gfx/gfx_resources.rc',
],
'include_dirs': [
'..',
@@ -155,7 +160,49 @@
],
}],
],
- },
+ },
+ {
+ # theme_resources also generates a .cc file, so it can't use the rules above.
+ 'target_name': 'gfx_resources',
+ 'type': 'none',
+ 'msvs_guid' : '5738AE53-E919-4987-A2EF-15FDBD8F90F6',
+ 'actions': [
+ {
+ 'action_name': 'gfx_resources',
+ 'variables': {
+ 'input_path': 'gfx_resources.grd',
+ },
+ 'inputs': [
+ '<!@(<(grit_info_cmd) --inputs <(input_path))',
+ ],
+ 'outputs': [
+ '<!@(<(grit_info_cmd) --outputs \'<(grit_out_dir)\' <(input_path))',
+ ],
+ 'action': [
+ '<@(grit_cmd)',
+ '-i', '<(input_path)', 'build',
+ '-o', '<(grit_out_dir)',
+ ],
+ 'conditions': [
+ ['use_titlecase_in_grd_files==1', {
+ 'action': ['-D', 'use_titlecase'],
+ }],
+ ],
+ 'message': 'Generating resources from <(input_path)',
+ },
+ ],
+ 'direct_dependent_settings': {
+ 'include_dirs': [
+ '<(grit_out_dir)',
+ ],
+ },
+ 'conditions': [
+ ['OS=="win"', {
+ 'dependencies': ['../build/win/system.gyp:cygwin'],
+ }],
+ ],
+ },
+
],
}