diff options
author | ben@chromium.org <ben@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-07-23 22:23:59 +0000 |
---|---|---|
committer | ben@chromium.org <ben@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-07-23 22:23:59 +0000 |
commit | 0f4fe844bd7ca7f0fa512a2e786d9debb2831526 (patch) | |
tree | f803b71c036a9fb0286298a366e682f65325d58d /gfx | |
parent | 04dd9d9de68e20da43e7e2f13a550ea7c8ca6fa3 (diff) | |
download | chromium_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.h | 23 | ||||
-rw-r--r-- | gfx/canvas.h | 32 | ||||
-rw-r--r-- | gfx/canvas_direct2d.cc | 72 | ||||
-rw-r--r-- | gfx/canvas_direct2d.h | 8 | ||||
-rw-r--r-- | gfx/canvas_direct2d_unittest.cc | 19 | ||||
-rw-r--r-- | gfx/canvas_skia.cc | 70 | ||||
-rw-r--r-- | gfx/canvas_skia.h | 8 | ||||
-rw-r--r-- | gfx/gfx.gyp | 1 |
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', |