summaryrefslogtreecommitdiffstats
path: root/gfx
diff options
context:
space:
mode:
authorben@chromium.org <ben@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-07-23 22:23:59 +0000
committerben@chromium.org <ben@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-07-23 22:23:59 +0000
commit0f4fe844bd7ca7f0fa512a2e786d9debb2831526 (patch)
treef803b71c036a9fb0286298a366e682f65325d58d /gfx
parent04dd9d9de68e20da43e7e2f13a550ea7c8ca6fa3 (diff)
downloadchromium_src-0f4fe844bd7ca7f0fa512a2e786d9debb2831526.zip
chromium_src-0f4fe844bd7ca7f0fa512a2e786d9debb2831526.tar.gz
chromium_src-0f4fe844bd7ca7f0fa512a2e786d9debb2831526.tar.bz2
Add support for brushes to gfx::Canvas... right now just LinearGradientBrush.
A native brush is created by gfx::Canvas::CreateLinearGradientBrush wrapped in a gfx::Brush. When gfx::Brush is deleted the platform wrapper frees the native brush. BUG=none TEST=see unittest. Review URL: http://codereview.chromium.org/3038019 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@53534 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'gfx')
-rw-r--r--gfx/brush.h23
-rw-r--r--gfx/canvas.h32
-rw-r--r--gfx/canvas_direct2d.cc72
-rw-r--r--gfx/canvas_direct2d.h8
-rw-r--r--gfx/canvas_direct2d_unittest.cc19
-rw-r--r--gfx/canvas_skia.cc70
-rw-r--r--gfx/canvas_skia.h8
-rw-r--r--gfx/gfx.gyp1
8 files changed, 232 insertions, 1 deletions
diff --git a/gfx/brush.h b/gfx/brush.h
new file mode 100644
index 0000000..0f6fbfb
--- /dev/null
+++ b/gfx/brush.h
@@ -0,0 +1,23 @@
+// 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_BRUSH_H_
+#define GFX_BRUSH_H_
+
+namespace gfx {
+
+// An object that encapsulates a platform native brush.
+// Subclasses handle memory management of the underlying native brush.
+class Brush {
+ public:
+ Brush() {}
+ virtual ~Brush() {}
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(Brush);
+};
+
+} // namespace gfx
+
+#endif // GFX_BRUSH_H_
diff --git a/gfx/canvas.h b/gfx/canvas.h
index 49c67f2..d7f18fc 100644
--- a/gfx/canvas.h
+++ b/gfx/canvas.h
@@ -7,14 +7,17 @@
#include <string>
+#include "gfx/brush.h"
#include "gfx/native_widget_types.h"
// TODO(beng): remove this include when we no longer depend on SkTypes.
#include "skia/ext/platform_canvas.h"
namespace gfx {
+class Brush;
class CanvasSkia;
class Font;
+class Point;
class Rect;
// TODO(beng): documentation.
@@ -103,6 +106,10 @@ class Canvas {
virtual void FillRectInt(const SkColor& color, int x, int y, int w,
int h) = 0;
+ // Fills the specified region with the specified brush.
+ virtual void FillRectInt(const gfx::Brush* brush, int x, int y, int w,
+ int h) = 0;
+
// Draws a single pixel rect in the specified region with the specified
// color, using a transfer mode of SkXfermode::kSrcOver_Mode.
//
@@ -185,6 +192,31 @@ class Canvas {
// returned by BeginPlatformPaint().
virtual void EndPlatformPaint() = 0;
+ // Defines how a brush paints the area outside its normal content area.
+ enum TileMode {
+ TileMode_Clamp,
+ TileMode_Repeat,
+ TileMode_Mirror
+ };
+
+ // Creates a linear gradient brush.
+ // |start_point| and |end_point| are the pixel positions of the start and end
+ // points of the gradient.
+ // |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|
+ // Returns an encapsulated platform shader object which the caller must
+ // delete.
+ virtual Brush* CreateLinearGradientBrush(
+ const gfx::Point& start_point,
+ const gfx::Point& end_point,
+ const SkColor colors[],
+ const float positions[],
+ size_t position_count,
+ TileMode tile_mode) = 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 b187455..e18272c 100644
--- a/gfx/canvas_direct2d.cc
+++ b/gfx/canvas_direct2d.cc
@@ -25,6 +25,41 @@ D2D1_RECT_F RectToRectF(const gfx::Rect& rect) {
return RectToRectF(rect.x(), rect.y(), rect.width(), rect.height());
}
+D2D1_POINT_2F PointToPoint2F(const gfx::Point& point) {
+ return D2D1::Point2F(static_cast<float>(point.x()),
+ static_cast<float>(point.y()));
+}
+
+D2D1_EXTEND_MODE TileModeToExtendMode(gfx::Canvas::TileMode tile_mode) {
+ switch (tile_mode) {
+ case gfx::Canvas::TileMode_Clamp:
+ return D2D1_EXTEND_MODE_CLAMP;
+ case gfx::Canvas::TileMode_Mirror:
+ return D2D1_EXTEND_MODE_MIRROR;
+ case gfx::Canvas::TileMode_Repeat:
+ return D2D1_EXTEND_MODE_WRAP;
+ default:
+ NOTREACHED() << "Invalid TileMode";
+ }
+ return D2D1_EXTEND_MODE_CLAMP;
+}
+
+// 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 {
+ public:
+ explicit Direct2DBrush(ID2D1Brush* brush) : brush_(brush) {
+ }
+
+ ID2D1Brush* brush() const { return brush_.get(); }
+
+ private:
+ ScopedComPtr<ID2D1Brush> brush_;
+
+ DISALLOW_COPY_AND_ASSIGN(Direct2DBrush);
+};
+
+
} // namespace
namespace gfx {
@@ -147,6 +182,12 @@ void CanvasDirect2D::FillRectInt(const SkColor& color, int x, int y, int w,
rt_->FillRectangle(RectToRectF(x, y, w, h), solid_brush);
}
+void CanvasDirect2D::FillRectInt(const gfx::Brush* brush, int x, int y, int w,
+ int h) {
+ const Direct2DBrush* d2d_brush = static_cast<const Direct2DBrush*>(brush);
+ rt_->FillRectangle(RectToRectF(x, y, w, h), d2d_brush->brush());
+}
+
void CanvasDirect2D::DrawRectInt(const SkColor& color, int x, int y, int w,
int h) {
@@ -232,6 +273,37 @@ void CanvasDirect2D::EndPlatformPaint() {
interop_rt_.release();
}
+Brush* CanvasDirect2D::CreateLinearGradientBrush(
+ const gfx::Point& start_point,
+ const gfx::Point& end_point,
+ const SkColor colors[],
+ 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))
+ return NULL;
+
+ ID2D1LinearGradientBrush* brush = NULL;
+ hr = rt_->CreateLinearGradientBrush(
+ D2D1::LinearGradientBrushProperties(PointToPoint2F(start_point),
+ PointToPoint2F(end_point)),
+ gradient_stop_collection,
+ &brush);
+
+ return new Direct2DBrush(brush);
+}
+
CanvasSkia* CanvasDirect2D::AsCanvasSkia() {
return NULL;
}
diff --git a/gfx/canvas_direct2d.h b/gfx/canvas_direct2d.h
index 26c3f87..6056047 100644
--- a/gfx/canvas_direct2d.h
+++ b/gfx/canvas_direct2d.h
@@ -35,6 +35,7 @@ class CanvasDirect2D : public Canvas {
const SkPaint& paint);
virtual void FillRectInt(const SkColor& color, int x, int y, int w,
int h);
+ virtual void FillRectInt(const gfx::Brush* brush, 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,
@@ -66,6 +67,13 @@ class CanvasDirect2D : public Canvas {
int dest_x, int dest_y, int w, int h);
virtual gfx::NativeDrawingContext BeginPlatformPaint();
virtual void EndPlatformPaint();
+ virtual Brush* CreateLinearGradientBrush(
+ const gfx::Point& start_point,
+ const gfx::Point& end_point,
+ const SkColor colors[],
+ const float positions[],
+ size_t position_count,
+ TileMode tile_mode);
virtual CanvasSkia* AsCanvasSkia();
virtual const CanvasSkia* AsCanvasSkia() const;
diff --git a/gfx/canvas_direct2d_unittest.cc b/gfx/canvas_direct2d_unittest.cc
index 541e3f0..d8c02c1 100644
--- a/gfx/canvas_direct2d_unittest.cc
+++ b/gfx/canvas_direct2d_unittest.cc
@@ -8,6 +8,7 @@
#include <vssym32.h>
#include "base/command_line.h"
+#include "base/scoped_ptr.h"
#include "gfx/canvas_direct2d.h"
#include "gfx/canvas_skia.h"
#include "gfx/native_theme_win.h"
@@ -202,3 +203,21 @@ TEST(CanvasDirect2D, ClipRectWithScale) {
canvas.FillRectInt(SK_ColorRED, 0, 0, 500, 500);
canvas.Restore();
}
+
+TEST(CanvasDirect2D, CreateLinearGradientBrush) {
+ TestWindow window;
+ gfx::CanvasDirect2D canvas(window.rt());
+
+ canvas.Save();
+ SkColor colors[] = { SK_ColorRED, SK_ColorWHITE };
+ float positions[] = { 0.0f, 1.0f };
+ scoped_ptr<gfx::Brush> brush(canvas.CreateLinearGradientBrush(
+ gfx::Point(0, 0),
+ gfx::Point(100, 0),
+ colors,
+ positions,
+ 2,
+ gfx::Canvas::TileMode_Clamp));
+ canvas.FillRectInt(brush.get(), 0, 0, 500, 500);
+ canvas.Restore();
+}
diff --git a/gfx/canvas_skia.cc b/gfx/canvas_skia.cc
index d5f2008..fbdc0a9 100644
--- a/gfx/canvas_skia.cc
+++ b/gfx/canvas_skia.cc
@@ -10,12 +10,50 @@
#include "base/logging.h"
#include "gfx/font.h"
#include "gfx/rect.h"
-#include "third_party/skia/include/core/SkShader.h"
+#include "third_party/skia/include/effects/SkGradientShader.h"
#if defined(OS_WIN)
#include "gfx/canvas_skia_paint.h"
#endif
+namespace {
+
+SkShader::TileMode TileModeToSkShaderTileMode(gfx::Canvas::TileMode tile_mode) {
+ switch (tile_mode) {
+ case gfx::Canvas::TileMode_Clamp:
+ return SkShader::kClamp_TileMode;
+ case gfx::Canvas::TileMode_Mirror:
+ return SkShader::kMirror_TileMode;
+ case gfx::Canvas::TileMode_Repeat:
+ return SkShader::kRepeat_TileMode;
+ default:
+ NOTREACHED() << "Invalid TileMode";
+ }
+ return SkShader::kClamp_TileMode;
+}
+
+// A platform wrapper for a Skia shader that makes sure the underlying
+// SkShader object is unref'ed when this object is destroyed.
+class SkiaShader : public gfx::Brush {
+ public:
+ explicit SkiaShader(SkShader* shader) : shader_(shader) {
+ }
+ virtual ~SkiaShader() {
+ shader_->unref();
+ }
+
+ // Accessor for shader, so it can be associated with a SkPaint.
+ SkShader* shader() const { return shader_; }
+
+ private:
+ SkShader* shader_;
+
+ DISALLOW_COPY_AND_ASSIGN(SkiaShader);
+};
+
+
+} // namespace
+
namespace gfx {
////////////////////////////////////////////////////////////////////////////////
@@ -87,6 +125,15 @@ void CanvasSkia::FillRectInt(const SkColor& color, int x, int y, int w, int h) {
FillRectInt(x, y, w, h, paint);
}
+void CanvasSkia::FillRectInt(const gfx::Brush* brush, int x, int y, int w,
+ int h) {
+ const SkiaShader* shader = static_cast<const SkiaShader*>(brush);
+ SkPaint paint;
+ paint.setShader(shader->shader());
+ // TODO(beng): set shader transform to match canvas transform.
+ FillRectInt(x, y, w, h, paint);
+}
+
void CanvasSkia::FillRectInt(int x, int y, int w, int h, const SkPaint& paint) {
SkIRect rc = {x, y, x + w, y + h};
drawIRect(rc, paint);
@@ -296,6 +343,27 @@ void CanvasSkia::EndPlatformPaint() {
endPlatformPaint();
}
+Brush* CanvasSkia::CreateLinearGradientBrush(
+ const gfx::Point& start_point,
+ const gfx::Point& end_point,
+ const SkColor colors[],
+ const float positions[],
+ size_t position_count,
+ TileMode tile_mode) {
+ SkPoint boundary_points[2];
+ boundary_points[0].set(SkIntToScalar(start_point.x()),
+ SkIntToScalar(start_point.y()));
+ boundary_points[1].set(SkIntToScalar(start_point.y()),
+ SkIntToScalar(start_point.y()));
+ SkShader* shader = SkGradientShader::CreateLinear(
+ boundary_points,
+ colors,
+ positions,
+ position_count,
+ TileModeToSkShaderTileMode(tile_mode));
+ return new SkiaShader(shader);
+}
+
CanvasSkia* CanvasSkia::AsCanvasSkia() {
return this;
}
diff --git a/gfx/canvas_skia.h b/gfx/canvas_skia.h
index 0e2f7e9..37827a7 100644
--- a/gfx/canvas_skia.h
+++ b/gfx/canvas_skia.h
@@ -91,6 +91,7 @@ class CanvasSkia : public skia::PlatformCanvas,
const SkPaint& paint);
virtual void FillRectInt(const SkColor& color, int x, int y, int w,
int h);
+ virtual void FillRectInt(const gfx::Brush* brush, 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,
@@ -122,6 +123,13 @@ class CanvasSkia : public skia::PlatformCanvas,
int dest_x, int dest_y, int w, int h);
virtual gfx::NativeDrawingContext BeginPlatformPaint();
virtual void EndPlatformPaint();
+ virtual Brush* CreateLinearGradientBrush(
+ const gfx::Point& start_point,
+ const gfx::Point& end_point,
+ const SkColor colors[],
+ const float positions[],
+ size_t position_count,
+ TileMode tile_mode);
virtual CanvasSkia* AsCanvasSkia();
virtual const CanvasSkia* AsCanvasSkia() const;
diff --git a/gfx/gfx.gyp b/gfx/gfx.gyp
index d51919b..e3eeb66 100644
--- a/gfx/gfx.gyp
+++ b/gfx/gfx.gyp
@@ -76,6 +76,7 @@
'sources': [
'blit.cc',
'blit.h',
+ 'brush.h',
'canvas.h',
'canvas_skia.h',
'canvas_skia.cc',