Add support for gradient stops to wxGraphicsContext.

Allow specifying a set of gradient stops instead of just the beginning and
ending colours. Add the new wxGraphicsGradientStop(s) classes and new
wxGraphicsContext::Create{Linear,Radial}GradientBrush() overloads. Also change
the same methods of wxGraphicsRenderer to take wxGraphicsGradientStops instead
of a pair of colours.

Implement the new API for MSW and Cairo. OS X still uses just the two colours
for now.

Closes #11897.

git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@63857 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
Vadim Zeitlin
2010-04-05 12:15:11 +00:00
parent cd300ef760
commit 4ee4c7b948
8 changed files with 714 additions and 184 deletions

View File

@@ -499,6 +499,7 @@ All (GUI):
- Add "initial selection" parameter to wxGetSingleChoice() (Nikolay Tjushkov). - Add "initial selection" parameter to wxGetSingleChoice() (Nikolay Tjushkov).
- Implement wxDocument::Revert() (troelsk). - Implement wxDocument::Revert() (troelsk).
- Allow overriding print preview frame creation in docview (troelsk). - Allow overriding print preview frame creation in docview (troelsk).
- Added support for gradient stops in wxGraphicsContext (Kit Bishop).
- Added wxTransparentColour. - Added wxTransparentColour.
GTK: GTK:

View File

@@ -19,6 +19,7 @@
#include "wx/geometry.h" #include "wx/geometry.h"
#include "wx/dynarray.h" #include "wx/dynarray.h"
#include "wx/dc.h" #include "wx/dc.h"
#include "wx/vector.h"
enum wxAntialiasMode enum wxAntialiasMode
{ {
@@ -304,6 +305,81 @@ private:
extern WXDLLIMPEXP_DATA_CORE(wxGraphicsPath) wxNullGraphicsPath; extern WXDLLIMPEXP_DATA_CORE(wxGraphicsPath) wxNullGraphicsPath;
// Describes a single gradient stop.
class wxGraphicsGradientStop
{
public:
wxGraphicsGradientStop(wxColour col, float pos)
: m_col(col),
m_pos(pos)
{
}
// default copy ctor, assignment operator and dtor are ok
const wxColour& GetColour() const { return m_col; }
void SetColour(const wxColour& col) { m_col = col; }
float GetPosition() const { return m_pos; }
void SetPosition(float pos)
{
wxASSERT_MSG( pos >= 0 && pos < 1, "invalid gradient stop position" );
m_pos = pos;
}
private:
// The colour of this gradient band.
wxColour m_col;
// Its starting position: 0 is the beginning and 1 is the end.
float m_pos;
};
// A collection of gradient stops ordered by their positions (from lowest to
// highest). The first stop (index 0, position 0.0) is always the starting
// colour and the last one (index GetCount() - 1, position 1.0) is the end
// colour.
class WXDLLIMPEXP_CORE wxGraphicsGradientStops
{
public:
wxGraphicsGradientStops(wxColour startCol = wxTransparentColour,
wxColour endCol = wxTransparentColour)
{
// we can't use Add() here as it relies on having start/end stops as
// first/last array elements so do it manually
m_stops.push_back(wxGraphicsGradientStop(startCol, 0.));
m_stops.push_back(wxGraphicsGradientStop(endCol, 1.));
}
// default copy ctor, assignment operator and dtor are ok for this class
// Add a stop in correct order.
void Add(const wxGraphicsGradientStop& stop);
void Add(wxColour col, float pos) { Add(wxGraphicsGradientStop(col, pos)); }
// Get the number of stops.
unsigned GetCount() const { return m_stops.size(); }
// Return the stop at the given index (which must be valid).
wxGraphicsGradientStop Item(unsigned n) const { return m_stops.at(n); }
// Get/set start and end colours.
void SetStartColour(wxColour col)
{ m_stops[0].SetColour(col); }
wxColour GetStartColour() const
{ return m_stops[0].GetColour(); }
void SetEndColour(wxColour col)
{ m_stops[m_stops.size() - 1].SetColour(col); }
wxColour GetEndColour() const
{ return m_stops[m_stops.size() - 1].GetColour(); }
private:
// All the stops stored in ascending order of positions.
wxVector<wxGraphicsGradientStop> m_stops;
};
class WXDLLIMPEXP_CORE wxGraphicsContext : public wxGraphicsObject class WXDLLIMPEXP_CORE wxGraphicsContext : public wxGraphicsObject
{ {
public: public:
@@ -348,14 +424,29 @@ public:
virtual wxGraphicsBrush CreateBrush(const wxBrush& brush ) const; virtual wxGraphicsBrush CreateBrush(const wxBrush& brush ) const;
// sets the brush to a linear gradient, starting at (x1,y1) with color c1 to (x2,y2) with color c2 // sets the brush to a linear gradient, starting at (x1,y1) and ending at
virtual wxGraphicsBrush CreateLinearGradientBrush( wxDouble x1, wxDouble y1, wxDouble x2, wxDouble y2, // (x2,y2) with the given boundary colours or the specified stops
const wxColour&c1, const wxColour&c2) const; wxGraphicsBrush
CreateLinearGradientBrush(wxDouble x1, wxDouble y1,
wxDouble x2, wxDouble y2,
const wxColour& c1, const wxColour& c2) const;
wxGraphicsBrush
CreateLinearGradientBrush(wxDouble x1, wxDouble y1,
wxDouble x2, wxDouble y2,
const wxGraphicsGradientStops& stops) const;
// sets the brush to a radial gradient originating at (xo,yc) with color oColor and ends on a circle around (xc,yc) // sets the brush to a radial gradient originating at (xo,yc) and ending
// with radius r and color cColor // on a circle around (xc,yc) with the given radius; the colours may be
virtual wxGraphicsBrush CreateRadialGradientBrush( wxDouble xo, wxDouble yo, wxDouble xc, wxDouble yc, wxDouble radius, // specified by just the two extremes or the full array of gradient stops
const wxColour &oColor, const wxColour &cColor) const; wxGraphicsBrush
CreateRadialGradientBrush(wxDouble xo, wxDouble yo,
wxDouble xc, wxDouble yc, wxDouble radius,
const wxColour& oColor, const wxColour& cColor) const;
wxGraphicsBrush
CreateRadialGradientBrush(wxDouble xo, wxDouble yo,
wxDouble xc, wxDouble yc, wxDouble radius,
const wxGraphicsGradientStops& stops) const;
// sets the font // sets the font
virtual wxGraphicsFont CreateFont( const wxFont &font , const wxColour &col = *wxBLACK ) const; virtual wxGraphicsFont CreateFont( const wxFont &font , const wxColour &col = *wxBLACK ) const;
@@ -644,21 +735,26 @@ public:
virtual wxGraphicsBrush CreateBrush(const wxBrush& brush ) = 0; virtual wxGraphicsBrush CreateBrush(const wxBrush& brush ) = 0;
// sets the brush to a linear gradient, starting at (x1,y1) with color c1 to (x2,y2) with color c2 // Gradient brush creation functions may not honour all the stops specified
virtual wxGraphicsBrush CreateLinearGradientBrush( wxDouble x1, wxDouble y1, wxDouble x2, wxDouble y2, // stops and use just its boundary colours (this is currently the case
const wxColour&c1, const wxColour&c2) = 0; // under OS X)
virtual wxGraphicsBrush
CreateLinearGradientBrush(wxDouble x1, wxDouble y1,
wxDouble x2, wxDouble y2,
const wxGraphicsGradientStops& stops) = 0;
// sets the brush to a radial gradient originating at (xo,yc) with color oColor and ends on a circle around (xc,yc) virtual wxGraphicsBrush
// with radius r and color cColor CreateRadialGradientBrush(wxDouble xo, wxDouble yo,
virtual wxGraphicsBrush CreateRadialGradientBrush( wxDouble xo, wxDouble yo, wxDouble xc, wxDouble yc, wxDouble radius, wxDouble xc, wxDouble yc,
const wxColour &oColor, const wxColour &cColor) = 0; wxDouble radius,
const wxGraphicsGradientStops& stops) = 0;
// sets the font // sets the font
virtual wxGraphicsFont CreateFont( const wxFont &font , const wxColour &col = *wxBLACK ) = 0; virtual wxGraphicsFont CreateFont( const wxFont &font , const wxColour &col = *wxBLACK ) = 0;
// create a native bitmap representation // create a native bitmap representation
virtual wxGraphicsBitmap CreateBitmap( const wxBitmap &bitmap ) = 0; virtual wxGraphicsBitmap CreateBitmap( const wxBitmap &bitmap ) = 0;
// create a graphics bitmap from a native bitmap // create a graphics bitmap from a native bitmap
virtual wxGraphicsBitmap CreateBitmapFromNativeBitmap( void* bitmap ) = 0; virtual wxGraphicsBitmap CreateBitmapFromNativeBitmap( void* bitmap ) = 0;

View File

@@ -206,14 +206,14 @@ public:
enum wxAntialiasMode enum wxAntialiasMode
{ {
/** No anti-aliasing */ /** No anti-aliasing */
wxANTIALIAS_NONE, wxANTIALIAS_NONE,
/** The default anti-aliasing */ /** The default anti-aliasing */
wxANTIALIAS_DEFAULT, wxANTIALIAS_DEFAULT,
}; };
/** /**
Compositing is done using Porter-Duff compositions Compositing is done using Porter-Duff compositions
(see http://keithp.com/~keithp/porterduff/p253-porter.pdf) with (see http://keithp.com/~keithp/porterduff/p253-porter.pdf) with
wxGraphicsContext::SetCompositionMode wxGraphicsContext::SetCompositionMode
@@ -361,15 +361,25 @@ public:
static wxGraphicsContext* CreateFromNativeWindow(void* window); static wxGraphicsContext* CreateFromNativeWindow(void* window);
/** /**
Creates a native brush, having a linear gradient, starting at Creates a native brush with a linear gradient.
(@a x1, @a y1) with color @a c1 to (@a x2, @a y2) with color @a c2.
The brush starts at (@a x1, @a y1) and ends at (@a x2, @a y2). Either
just the start and end gradient colours (@a c1 and @a c2) or full set
of gradient @a stops can be specified.
The version taking wxGraphicsGradientStops is new in wxWidgets 2.9.1.
*/ */
virtual wxGraphicsBrush CreateLinearGradientBrush(wxDouble x1, //@{
wxDouble y1, wxGraphicsBrush
wxDouble x2, CreateLinearGradientBrush(wxDouble x1, wxDouble y1,
wxDouble y2, wxDouble x2, wxDouble y2,
const wxColour& c1, const wxColour& c1, const wxColour& c2) const;
const wxColour& c2) const;
wxGraphicsBrush
CreateLinearGradientBrush(wxDouble x1, wxDouble y1,
wxDouble x2, wxDouble y2,
const wxGraphicsGradientStops& stops) const;
//@}
/** /**
Creates a native affine transformation matrix from the passed in Creates a native affine transformation matrix from the passed in
@@ -391,15 +401,30 @@ public:
virtual wxGraphicsPen CreatePen(const wxPen& pen) const; virtual wxGraphicsPen CreatePen(const wxPen& pen) const;
/** /**
Creates a native brush, having a radial gradient originating at Creates a native brush with a radial gradient.
(@a xo, @a yc) with color @a oColour and ends on a circle around
(@a xc, @a yc) with the given @a radius and color @a cColour. The brush originats at (@a xo, @a yc) and ends on a circle around
(@a xc, @a yc) with the given @a radius.
The gradient may be specified either by its start and end colours @a
oColor and @a cColor or by a full set of gradient @a stops.
The version taking wxGraphicsGradientStops is new in wxWidgets 2.9.1.
*/ */
virtual wxGraphicsBrush CreateRadialGradientBrush(wxDouble xo, wxDouble yo, //@{
wxDouble xc, wxDouble yc, virtual wxGraphicsBrush
wxDouble radius, CreateRadialGradientBrush(wxDouble xo, wxDouble yo,
const wxColour& oColor, wxDouble xc, wxDouble yc,
const wxColour& cColor) const; wxDouble radius,
const wxColour& oColor,
const wxColour& cColor) const;
virtual wxGraphicsBrush
CreateRadialGradientBrush(wxDouble xo, wxDouble yo,
wxDouble xc, wxDouble yc,
wxDouble radius,
const wxGraphicsGradientStops& stops) = 0;
//@}
/** /**
Draws the bitmap. In case of a mono bitmap, this is treated as a mask Draws the bitmap. In case of a mono bitmap, this is treated as a mask
@@ -611,39 +636,152 @@ public:
virtual void Translate(wxDouble dx, wxDouble dy) = 0; virtual void Translate(wxDouble dx, wxDouble dy) = 0;
/** /**
Redirects all rendering is done into a fully transparent temporary context Redirects all rendering is done into a fully transparent temporary context
*/ */
virtual void BeginLayer(wxDouble opacity) = 0; virtual void BeginLayer(wxDouble opacity) = 0;
/** /**
Composites back the drawings into the context with the opacity given at Composites back the drawings into the context with the opacity given at
the BeginLayer call the BeginLayer call
*/ */
virtual void EndLayer() = 0; virtual void EndLayer() = 0;
/** /**
Sets the antialiasing mode, returns true if it supported Sets the antialiasing mode, returns true if it supported
*/ */
virtual bool SetAntialiasMode(wxAntialiasMode antialias) = 0; virtual bool SetAntialiasMode(wxAntialiasMode antialias) = 0;
/** /**
Returns the current shape antialiasing mode Returns the current shape antialiasing mode
*/ */
virtual wxAntialiasMode GetAntialiasMode() const ; virtual wxAntialiasMode GetAntialiasMode() const ;
/** /**
Sets the compositing operator, returns true if it supported Sets the compositing operator, returns true if it supported
*/ */
virtual bool SetCompositionMode(wxCompositionMode op) = 0; virtual bool SetCompositionMode(wxCompositionMode op) = 0;
/** /**
Returns the current compositing operator Returns the current compositing operator
*/ */
virtual wxCompositionMode GetCompositionMode() const; virtual wxCompositionMode GetCompositionMode() const;
}; };
/**
Represents a single gradient stop in a collection of gradient stops as
represented by wxGraphicsGradientStops.
@library{wxcore}
@category{gdi}
@since 2.9.1
*/
class wxGraphicsGradientStop
{
public:
/**
Creates a stop with the given colour and position.
@param col The colour of this stop. Note that the alpha component of
the colour is honoured thus allowing the background colours to
partially show through the gradient.
@param pos The stop position, must be in [0, 1) range with 0 being the
beginning and 1 the end of the gradient (but it doesn't make sense
to create a stop at position 1 because it would never be visible
anyhow).
*/
wxGraphicsGradientStop(wxColour col, float pos);
/// Return the stop colour.
const wxColour& GetColour() const;
/**
Change the stop colour.
@param col The new colour.
*/
void SetColour(const wxColour& col);
/// Return the stop position.
float GetPosition() const;
/**
Change the stop position.
@param pos The new position, must always be in [0, 1) range.
*/
void SetPosition(float pos);
};
/**
Represents a collection of wxGraphicGradientStop values for use with
CreateLinearGradientBrush and CreateRadialGradientBrush.
The stops are maintained in order of position. If two or more stops are
added with the same position then the one(s) added later come later.
This can be useful for producing discontinuities in the colour gradient.
Notice that this class is write-once, you can't modify the stops once they
had been added.
@library{wxcore}
@category{gdi}
@since 2.9.1
*/
class wxGraphicsGradientStops
{
public:
/**
Initializes the gradient stops with the given boundary colours.
Creates a wxGraphicsGradientStops instance with start colour given
by @a startCol and end colour given by @a endCol.
*/
wxGraphicsGradientStops(wxColour startCol = wxTransparentColour,
wxColour endCol = wxTransparentColour);
/**
Add a new stop.
*/
//@{
void Add(const wxGraphicsGradientStop& stop);
void Add(wxColour col, float pos);
//@}
/**
Returns the stop at the given index.
@param n The index, must be in [0, GetCount()) range.
*/
wxGraphicsGradientStop Item(unsigned n) const;
/**
Returns the number of stops.
*/
unsigned GetCount() const;
/**
Set the start colour to @a col
*/
void SetStartColour(wxColour col);
/**
Returns the start colour.
*/
wxColour GetStartColour() const;
/**
Set the end colour to @a col
*/
void SetEndColour(wxColour col);
/**
Returns the end colour.
*/
wxColour GetEndColour() const;
};
/** /**
@class wxGraphicsRenderer @class wxGraphicsRenderer
@@ -707,7 +845,7 @@ public:
virtual wxGraphicsContext* CreateContextFromNativeWindow(void* window) = 0; virtual wxGraphicsContext* CreateContextFromNativeWindow(void* window) = 0;
/** /**
Creates a wxGraphicsContext that can be used for measuring texts only. Creates a wxGraphicsContext that can be used for measuring texts only.
No drawing commands are allowed. No drawing commands are allowed.
*/ */
virtual wxGraphicsContext * CreateMeasuringContext() = 0; virtual wxGraphicsContext * CreateMeasuringContext() = 0;
@@ -718,16 +856,18 @@ public:
virtual wxGraphicsFont CreateFont(const wxFont& font, virtual wxGraphicsFont CreateFont(const wxFont& font,
const wxColour& col = *wxBLACK) = 0; const wxColour& col = *wxBLACK) = 0;
/** /**
Creates a native brush, having a linear gradient, starting at Creates a native brush with a linear gradient.
(@a x1, @a y1) with color @a c1 to (@a x2, @a y2) with color @a c2.
Stops support is new since wxWidgets 2.9.1, previously only the start
and end colours could be specified.
*/ */
virtual wxGraphicsBrush CreateLinearGradientBrush(wxDouble x1, virtual wxGraphicsBrush CreateLinearGradientBrush(wxDouble x1,
wxDouble y1, wxDouble y1,
wxDouble x2, wxDouble x2,
wxDouble y2, wxDouble y2,
const wxColour& c1, const wxGraphicsGradientStops& stops) = 0;
const wxColour& c2) = 0;
/** /**
Creates a native affine transformation matrix from the passed in Creates a native affine transformation matrix from the passed in
@@ -749,15 +889,15 @@ public:
virtual wxGraphicsPen CreatePen(const wxPen& pen) = 0; virtual wxGraphicsPen CreatePen(const wxPen& pen) = 0;
/** /**
Creates a native brush, having a radial gradient originating at Creates a native brush with a radial gradient.
(@a xo, @a yc) with color @a oColour and ends on a circle around
(@a xc, @a yc) with the given @a radius and color @a cColour. Stops support is new since wxWidgets 2.9.1, previously only the start
and end colours could be specified.
*/ */
virtual wxGraphicsBrush CreateRadialGradientBrush(wxDouble xo, wxDouble yo, virtual wxGraphicsBrush CreateRadialGradientBrush(wxDouble xo, wxDouble yo,
wxDouble xc, wxDouble yc, wxDouble xc, wxDouble yc,
wxDouble radius, wxDouble radius,
const wxColour& oColour, const wxGraphicsGradientStops& stops) = 0;
const wxColour& cColour) = 0;
/** /**
Returns the default renderer on this platform. On OS X this is the Core Returns the default renderer on this platform. On OS X this is the Core

View File

@@ -955,7 +955,7 @@ void MyCanvas::DrawGraphics(wxGraphicsContext* gc)
{ {
wxFont font = wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT); wxFont font = wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT);
gc->SetFont(font,*wxBLACK); gc->SetFont(font,*wxBLACK);
// make a path that contains a circle and some lines, centered at 0,0 // make a path that contains a circle and some lines, centered at 0,0
wxGraphicsPath path = gc->CreatePath() ; wxGraphicsPath path = gc->CreatePath() ;
path.AddCircle( 0, 0, BASE2 ); path.AddCircle( 0, 0, BASE2 );
@@ -965,14 +965,14 @@ void MyCanvas::DrawGraphics(wxGraphicsContext* gc)
path.AddLineToPoint(BASE2, 0); path.AddLineToPoint(BASE2, 0);
path.CloseSubpath(); path.CloseSubpath();
path.AddRectangle(-BASE4, -BASE4/2, BASE2, BASE4); path.AddRectangle(-BASE4, -BASE4/2, BASE2, BASE4);
// Now use that path to demonstrate various capbilites of the grpahics context // Now use that path to demonstrate various capbilites of the grpahics context
gc->PushState(); // save current translation/scale/other state gc->PushState(); // save current translation/scale/other state
gc->Translate(60, 75); // reposition the context origin gc->Translate(60, 75); // reposition the context origin
gc->SetPen(wxPen("navy", 1)); gc->SetPen(wxPen("navy", 1));
gc->SetBrush(wxBrush("pink")); gc->SetBrush(wxBrush("pink"));
for( int i = 0 ; i < 3 ; ++i ) for( int i = 0 ; i < 3 ; ++i )
{ {
wxString label; wxString label;
@@ -1005,11 +1005,11 @@ void MyCanvas::DrawGraphics(wxGraphicsContext* gc)
} }
gc->Translate(2*BASE, 0); gc->Translate(2*BASE, 0);
} }
gc->PopState(); // restore saved state gc->PopState(); // restore saved state
gc->PushState(); // save it again gc->PushState(); // save it again
gc->Translate(60, 200); // offset to the lower part of the window gc->Translate(60, 200); // offset to the lower part of the window
gc->DrawText("Scale", 0, -BASE2); gc->DrawText("Scale", 0, -BASE2);
gc->Translate(0, 20); gc->Translate(0, 20);
@@ -1017,14 +1017,14 @@ void MyCanvas::DrawGraphics(wxGraphicsContext* gc)
for( int i = 0 ; i < 8 ; ++i ) for( int i = 0 ; i < 8 ; ++i )
{ {
gc->Scale(1.08, 1.08); // increase scale by 8% gc->Scale(1.08, 1.08); // increase scale by 8%
gc->Translate(5,5); gc->Translate(5,5);
gc->DrawPath(path); gc->DrawPath(path);
} }
gc->PopState(); // restore saved state gc->PopState(); // restore saved state
gc->PushState(); // save it again gc->PushState(); // save it again
gc->Translate(400, 200); gc->Translate(400, 200);
gc->DrawText("Rotate", 0, -BASE2); gc->DrawText("Rotate", 0, -BASE2);
// Move the origin over to the next location // Move the origin over to the next location
@@ -1034,16 +1034,16 @@ void MyCanvas::DrawGraphics(wxGraphicsContext* gc)
// and changing colors as we go // and changing colors as we go
for ( int angle = 0 ; angle < 360 ; angle += 30 ) for ( int angle = 0 ; angle < 360 ; angle += 30 )
{ {
gc->PushState(); // save this new current state so we can gc->PushState(); // save this new current state so we can
// pop back to it at the end of the loop // pop back to it at the end of the loop
wxImage::RGBValue val = wxImage::HSVtoRGB(wxImage::HSVValue(float(angle)/360, 1, 1)); wxImage::RGBValue val = wxImage::HSVtoRGB(wxImage::HSVValue(float(angle)/360, 1, 1));
gc->SetBrush(wxBrush(wxColour(val.red, val.green, val.blue, 64))); gc->SetBrush(wxBrush(wxColour(val.red, val.green, val.blue, 64)));
gc->SetPen(wxPen(wxColour(val.red, val.green, val.blue, 128))); gc->SetPen(wxPen(wxColour(val.red, val.green, val.blue, 128)));
// use translate to artfully reposition each drawn path // use translate to artfully reposition each drawn path
gc->Translate(1.5 * BASE2 * cos(DegToRad(angle)), gc->Translate(1.5 * BASE2 * cos(DegToRad(angle)),
1.5 * BASE2 * sin(DegToRad(angle))); 1.5 * BASE2 * sin(DegToRad(angle)));
// use Rotate to rotate the path // use Rotate to rotate the path
gc->Rotate(DegToRad(angle)); gc->Rotate(DegToRad(angle));
@@ -1231,6 +1231,7 @@ void MyCanvas::DrawGradients(wxDC& dc)
r.Offset(0, TEXT_HEIGHT); r.Offset(0, TEXT_HEIGHT);
dc.GradientFillLinear(r, *wxWHITE, *wxBLUE, wxUP); dc.GradientFillLinear(r, *wxWHITE, *wxBLUE, wxUP);
wxRect gfr = wxRect(r);
// RHS: concentric // RHS: concentric
r = wxRect(200, 10, 50, 50); r = wxRect(200, 10, 50, 50);
@@ -1283,6 +1284,127 @@ void MyCanvas::DrawGradients(wxDC& dc)
dc.DrawRectangle(r4); dc.DrawRectangle(r4);
r4.Deflate(1); r4.Deflate(1);
dc.GradientFillLinear(r4, wxColour(0,0,0), wxColour(0,255,0), wxWEST); dc.GradientFillLinear(r4, wxColour(0,0,0), wxColour(0,255,0), wxWEST);
#if wxUSE_GRAPHICS_CONTEXT
if (m_useContext)
{
wxGCDC &gdc = (wxGCDC&)dc;
wxGraphicsContext *gc = gdc.GetGraphicsContext();
wxGraphicsPath pth;
wxGraphicsGradientStops stops;
gfr.Offset(0, gfr.height + 10);
dc.DrawText(wxT("Linear Gradient with Stops"), gfr.x, gfr.y);
gfr.Offset(0, TEXT_HEIGHT);
stops = wxGraphicsGradientStops(wxColour(255,0,0), wxColour(0,0,255));
stops.Add(wxColour(255,255,0), 0.33f);
stops.Add(wxColour(0,255,0), 0.67f);
gc->SetBrush(gc->CreateLinearGradientBrush(gfr.x, gfr.y,
gfr.x + gfr.width, gfr.y + gfr.height,
stops));
pth = gc->CreatePath();
pth.MoveToPoint(gfr.x,gfr.y);
pth.AddLineToPoint(gfr.x + gfr.width,gfr.y);
pth.AddLineToPoint(gfr.x + gfr.width,gfr.y+gfr.height);
pth.AddLineToPoint(gfr.x,gfr.y+gfr.height);
pth.CloseSubpath();
gc->FillPath(pth);
gfr.Offset(0, gfr.height + 10);
dc.DrawText(wxT("Radial Gradient with Stops"), gfr.x, gfr.y);
gfr.Offset(0, TEXT_HEIGHT);
gc->SetBrush(gc->CreateRadialGradientBrush(gfr.x + gfr.width / 2,
gfr.y + gfr.height / 2,
gfr.x + gfr.width / 2,
gfr.y + gfr.height / 2,
gfr.width / 2,
stops));
pth = gc->CreatePath();
pth.MoveToPoint(gfr.x,gfr.y);
pth.AddLineToPoint(gfr.x + gfr.width,gfr.y);
pth.AddLineToPoint(gfr.x + gfr.width,gfr.y+gfr.height);
pth.AddLineToPoint(gfr.x,gfr.y+gfr.height);
pth.CloseSubpath();
gc->FillPath(pth);
gfr.Offset(0, gfr.height + 10);
dc.DrawText(wxT("Linear Gradient with Stops and Gaps"), gfr.x, gfr.y);
gfr.Offset(0, TEXT_HEIGHT);
stops = wxGraphicsGradientStops(wxColour(255,0,0), wxColour(0,0,255));
stops.Add(wxColour(255,255,0), 0.33f);
stops.Add(wxTransparentColour, 0.33f);
stops.Add(wxTransparentColour, 0.67f);
stops.Add(wxColour(0,255,0), 0.67f);
gc->SetBrush(gc->CreateLinearGradientBrush(gfr.x, gfr.y + gfr.height,
gfr.x + gfr.width, gfr.y,
stops));
pth = gc->CreatePath();
pth.MoveToPoint(gfr.x,gfr.y);
pth.AddLineToPoint(gfr.x + gfr.width,gfr.y);
pth.AddLineToPoint(gfr.x + gfr.width,gfr.y+gfr.height);
pth.AddLineToPoint(gfr.x,gfr.y+gfr.height);
pth.CloseSubpath();
gc->FillPath(pth);
gfr.Offset(0, gfr.height + 10);
dc.DrawText(wxT("Radial Gradient with Stops and Gaps"), gfr.x, gfr.y);
gfr.Offset(0, TEXT_HEIGHT);
gc->SetBrush(gc->CreateRadialGradientBrush(gfr.x + gfr.width / 2,
gfr.y + gfr.height / 2,
gfr.x + gfr.width / 2,
gfr.y + gfr.height / 2,
gfr.width / 2,
stops));
pth = gc->CreatePath();
pth.MoveToPoint(gfr.x,gfr.y);
pth.AddLineToPoint(gfr.x + gfr.width,gfr.y);
pth.AddLineToPoint(gfr.x + gfr.width,gfr.y+gfr.height);
pth.AddLineToPoint(gfr.x,gfr.y+gfr.height);
pth.CloseSubpath();
gc->FillPath(pth);
gfr.Offset(0, gfr.height + 10);
dc.DrawText(wxT("Gradients with Stops and Transparency"), gfr.x, gfr.y);
gfr.Offset(0, TEXT_HEIGHT);
stops = wxGraphicsGradientStops(wxColour(255,0,0), wxTransparentColour);
stops.Add(wxColour(255,0,0), 0.33f);
stops.Add(wxTransparentColour, 0.33f);
stops.Add(wxTransparentColour, 0.67f);
stops.Add(wxColour(0,0,255), 0.67f);
stops.Add(wxColour(0,0,255), 1.0f);
pth = gc->CreatePath();
pth.MoveToPoint(gfr.x,gfr.y);
pth.AddLineToPoint(gfr.x + gfr.width,gfr.y);
pth.AddLineToPoint(gfr.x + gfr.width,gfr.y+gfr.height);
pth.AddLineToPoint(gfr.x,gfr.y+gfr.height);
pth.CloseSubpath();
gc->SetBrush(gc->CreateRadialGradientBrush(gfr.x + gfr.width / 2,
gfr.y + gfr.height / 2,
gfr.x + gfr.width / 2,
gfr.y + gfr.height / 2,
gfr.width / 2,
stops));
gc->FillPath(pth);
stops = wxGraphicsGradientStops(wxColour(255,0,0, 128), wxColour(0,0,255, 128));
stops.Add(wxColour(255,255,0,128), 0.33f);
stops.Add(wxColour(0,255,0,128), 0.67f);
gc->SetBrush(gc->CreateLinearGradientBrush(gfr.x, gfr.y,
gfr.x + gfr.width, gfr.y,
stops));
gc->FillPath(pth);
}
#endif // wxUSE_GRAPHICS_CONTEXT
} }
void MyCanvas::DrawRegions(wxDC& dc) void MyCanvas::DrawRegions(wxDC& dc)
@@ -1474,7 +1596,7 @@ void MyCanvas::OnMouseMove(wxMouseEvent &event)
str.Printf( wxT("Current mouse position: %d,%d"), (int)x, (int)y ); str.Printf( wxT("Current mouse position: %d,%d"), (int)x, (int)y );
m_owner->SetStatusText( str ); m_owner->SetStatusText( str );
} }
if ( m_rubberBand ) if ( m_rubberBand )
{ {
int x,y, xx, yy ; int x,y, xx, yy ;
@@ -1504,8 +1626,8 @@ void MyCanvas::OnMouseMove(wxMouseEvent &event)
void MyCanvas::OnMouseDown(wxMouseEvent &event) void MyCanvas::OnMouseDown(wxMouseEvent &event)
{ {
int x,y,xx,yy ; int x,y,xx,yy ;
event.GetPosition(&x,&y); event.GetPosition(&x,&y);
CalcUnscrolledPosition( x, y, &xx, &yy ); CalcUnscrolledPosition( x, y, &xx, &yy );
m_anchorpoint = wxPoint( xx , yy ) ; m_anchorpoint = wxPoint( xx , yy ) ;
m_currentpoint = m_anchorpoint ; m_currentpoint = m_anchorpoint ;
@@ -1530,9 +1652,9 @@ void MyCanvas::OnMouseUp(wxMouseEvent &event)
int x,y,xx,yy ; int x,y,xx,yy ;
event.GetPosition(&x,&y); event.GetPosition(&x,&y);
CalcUnscrolledPosition( x, y, &xx, &yy ); CalcUnscrolledPosition( x, y, &xx, &yy );
wxString str; wxString str;
str.Printf( wxT("Rectangle selection from %d,%d to %d,%d"), str.Printf( wxT("Rectangle selection from %d,%d to %d,%d"),
m_anchorpoint.x, m_anchorpoint.y , (int)xx, (int)yy ); m_anchorpoint.x, m_anchorpoint.y , (int)xx, (int)yy );
wxMessageBox( str , wxT("Rubber-Banding") ); wxMessageBox( str , wxT("Rubber-Banding") );
@@ -1658,8 +1780,8 @@ MyFrame::MyFrame(const wxString& title, const wxPoint& pos, const wxSize& size)
m_xAxisReversed = m_xAxisReversed =
m_yAxisReversed = false; m_yAxisReversed = false;
m_backgroundMode = wxSOLID; m_backgroundMode = wxSOLID;
m_colourForeground = *wxRED; m_colourForeground = *wxBLACK;
m_colourBackground = *wxBLUE; m_colourBackground = *wxLIGHT_GREY;
m_textureBackground = false; m_textureBackground = false;
m_canvas = new MyCanvas( this ); m_canvas = new MyCanvas( this );

View File

@@ -489,6 +489,41 @@ void wxGraphicsPathData::AddArcToPoint( wxDouble x1, wxDouble y1 , wxDouble x2,
AddLineToPoint(p2.m_x,p2.m_y); AddLineToPoint(p2.m_x,p2.m_y);
} }
//-----------------------------------------------------------------------------
// wxGraphicsGradientStops
//-----------------------------------------------------------------------------
void wxGraphicsGradientStops::Add(const wxGraphicsGradientStop& stop)
{
for ( wxVector<wxGraphicsGradientStop>::iterator it = m_stops.begin();
it != m_stops.end();
++it )
{
if ( stop.GetPosition() < it->GetPosition() )
{
if ( it != m_stops.begin() )
{
m_stops.insert(it, stop);
}
else // we shouldn't be inserting it at the beginning
{
wxFAIL_MSG( "invalid gradient stop position < 0" );
}
return;
}
}
if ( stop.GetPosition() == 1. )
{
m_stops.insert(m_stops.end() - 1, stop);
}
else
{
wxFAIL_MSG( "invalid gradient stop position >= 1" );
}
}
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// wxGraphicsContext Convenience Methods // wxGraphicsContext Convenience Methods
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@@ -753,19 +788,55 @@ wxGraphicsBrush wxGraphicsContext::CreateBrush(const wxBrush& brush ) const
return GetRenderer()->CreateBrush(brush); return GetRenderer()->CreateBrush(brush);
} }
// sets the brush to a linear gradient, starting at (x1,y1) with color c1 to (x2,y2) with color c2 wxGraphicsBrush
wxGraphicsBrush wxGraphicsContext::CreateLinearGradientBrush( wxDouble x1, wxDouble y1, wxDouble x2, wxDouble y2, wxGraphicsContext::CreateLinearGradientBrush(
const wxColour&c1, const wxColour&c2) const wxDouble x1, wxDouble y1,
wxDouble x2, wxDouble y2,
const wxColour& c1, const wxColour& c2) const
{ {
return GetRenderer()->CreateLinearGradientBrush(x1,y1,x2,y2,c1,c2); return GetRenderer()->CreateLinearGradientBrush
(
x1, y1,
x2, y2,
wxGraphicsGradientStops(c1,c2)
);
} }
// sets the brush to a radial gradient originating at (xo,yc) with color oColor and ends on a circle around (xc,yc) wxGraphicsBrush
// with radius r and color cColor wxGraphicsContext::CreateLinearGradientBrush(
wxGraphicsBrush wxGraphicsContext::CreateRadialGradientBrush( wxDouble xo, wxDouble yo, wxDouble xc, wxDouble yc, wxDouble radius, wxDouble x1, wxDouble y1,
const wxColour &oColor, const wxColour &cColor) const wxDouble x2, wxDouble y2,
const wxGraphicsGradientStops& gradientStops) const
{ {
return GetRenderer()->CreateRadialGradientBrush(xo,yo,xc,yc,radius,oColor,cColor); return GetRenderer()->CreateLinearGradientBrush(x1,y1,x2,y2, gradientStops);
}
wxGraphicsBrush
wxGraphicsContext::CreateRadialGradientBrush(
wxDouble xo, wxDouble yo,
wxDouble xc, wxDouble yc, wxDouble radius,
const wxColour &oColor, const wxColour &cColor) const
{
return GetRenderer()->CreateRadialGradientBrush
(
xo, yo,
xc, yc, radius,
wxGraphicsGradientStops(oColor, cColor)
);
}
wxGraphicsBrush
wxGraphicsContext::CreateRadialGradientBrush(
wxDouble xo, wxDouble yo,
wxDouble xc, wxDouble yc, wxDouble radius,
const wxGraphicsGradientStops& gradientStops) const
{
return GetRenderer()->CreateRadialGradientBrush
(
xo, yo,
xc, yc, radius,
gradientStops
);
} }
// sets the font // sets the font

View File

@@ -248,14 +248,20 @@ public:
~wxCairoBrushData (); ~wxCairoBrushData ();
virtual void Apply( wxGraphicsContext* context ); virtual void Apply( wxGraphicsContext* context );
void CreateLinearGradientBrush( wxDouble x1, wxDouble y1, wxDouble x2, wxDouble y2,
const wxColour&c1, const wxColour&c2 ); void CreateLinearGradientBrush(wxDouble x1, wxDouble y1,
void CreateRadialGradientBrush( wxDouble xo, wxDouble yo, wxDouble xc, wxDouble yc, wxDouble radius, wxDouble x2, wxDouble y2,
const wxColour &oColor, const wxColour &cColor ); const wxGraphicsGradientStops& stops);
void CreateRadialGradientBrush(wxDouble xo, wxDouble yo,
wxDouble xc, wxDouble yc, wxDouble radius,
const wxGraphicsGradientStops& stops);
protected: protected:
virtual void Init(); virtual void Init();
// common part of Create{Linear,Radial}GradientBrush()
void AddGradientStops(const wxGraphicsGradientStops& stops);
private : private :
double m_red; double m_red;
double m_green; double m_green;
@@ -683,26 +689,50 @@ void wxCairoBrushData::Apply( wxGraphicsContext* context )
} }
} }
void wxCairoBrushData::CreateLinearGradientBrush( wxDouble x1, wxDouble y1, wxDouble x2, wxDouble y2, void wxCairoBrushData::AddGradientStops(const wxGraphicsGradientStops& stops)
const wxColour&c1, const wxColour&c2 )
{ {
m_brushPattern = cairo_pattern_create_linear(x1,y1,x2,y2); // loop over all the stops, they include the beginning and ending ones
cairo_pattern_add_color_stop_rgba(m_brushPattern,0.0,c1.Red()/255.0, const unsigned numStops = stops.GetCount();
c1.Green()/255.0, c1.Blue()/255.0,c1.Alpha()/255.0); for ( unsigned n = 0; n < numStops; n++ )
cairo_pattern_add_color_stop_rgba(m_brushPattern,1.0,c2.Red()/255.0, {
c2.Green()/255.0, c2.Blue()/255.0,c2.Alpha()/255.0); const wxGraphicsGradientStop stop = stops.Item(n);
wxASSERT_MSG(cairo_pattern_status(m_brushPattern) == CAIRO_STATUS_SUCCESS, wxT("Couldn't create cairo pattern"));
const wxColour col = stop.GetColour();
cairo_pattern_add_color_stop_rgba
(
m_brushPattern,
stop.GetPosition(),
col.Red()/255.0,
col.Green()/255.0,
col.Blue()/255.0,
col.Alpha()/255.0
);
}
wxASSERT_MSG(cairo_pattern_status(m_brushPattern) == CAIRO_STATUS_SUCCESS,
wxT("Couldn't create cairo pattern"));
} }
void wxCairoBrushData::CreateRadialGradientBrush( wxDouble xo, wxDouble yo, wxDouble xc, wxDouble yc, wxDouble radius, void
const wxColour &oColor, const wxColour &cColor ) wxCairoBrushData::CreateLinearGradientBrush(wxDouble x1, wxDouble y1,
wxDouble x2, wxDouble y2,
const wxGraphicsGradientStops& stops)
{
m_brushPattern = cairo_pattern_create_linear(x1,y1,x2,y2);
AddGradientStops(stops);
}
void
wxCairoBrushData::CreateRadialGradientBrush(wxDouble xo, wxDouble yo,
wxDouble xc, wxDouble yc,
wxDouble radius,
const wxGraphicsGradientStops& stops)
{ {
m_brushPattern = cairo_pattern_create_radial(xo,yo,0.0,xc,yc,radius); m_brushPattern = cairo_pattern_create_radial(xo,yo,0.0,xc,yc,radius);
cairo_pattern_add_color_stop_rgba(m_brushPattern,0.0,oColor.Red()/255.0,
oColor.Green()/255.0, oColor.Blue()/255.0,oColor.Alpha()/255.0); AddGradientStops(stops);
cairo_pattern_add_color_stop_rgba(m_brushPattern,1.0,cColor.Red()/255.0,
cColor.Green()/255.0, cColor.Blue()/255.0,cColor.Alpha()/255.0);
wxASSERT_MSG(cairo_pattern_status(m_brushPattern) == CAIRO_STATUS_SUCCESS, wxT("Couldn't create cairo pattern"));
} }
void wxCairoBrushData::Init() void wxCairoBrushData::Init()
@@ -1113,10 +1143,10 @@ wxCairoBitmapData::~wxCairoBitmapData()
{ {
if (m_pattern) if (m_pattern)
cairo_pattern_destroy(m_pattern); cairo_pattern_destroy(m_pattern);
if (m_surface) if (m_surface)
cairo_surface_destroy(m_surface); cairo_surface_destroy(m_surface);
delete [] m_buffer; delete [] m_buffer;
} }
@@ -1735,14 +1765,16 @@ public :
virtual wxGraphicsBrush CreateBrush(const wxBrush& brush ) ; virtual wxGraphicsBrush CreateBrush(const wxBrush& brush ) ;
// sets the brush to a linear gradient, starting at (x1,y1) with color c1 to (x2,y2) with color c2 virtual wxGraphicsBrush
virtual wxGraphicsBrush CreateLinearGradientBrush( wxDouble x1, wxDouble y1, wxDouble x2, wxDouble y2, CreateLinearGradientBrush(wxDouble x1, wxDouble y1,
const wxColour&c1, const wxColour&c2) ; wxDouble x2, wxDouble y2,
const wxGraphicsGradientStops& stops);
// sets the brush to a radial gradient originating at (xo,yc) with color oColor and ends on a circle around (xc,yc) virtual wxGraphicsBrush
// with radius r and color cColor CreateRadialGradientBrush(wxDouble xo, wxDouble yo,
virtual wxGraphicsBrush CreateRadialGradientBrush( wxDouble xo, wxDouble yo, wxDouble xc, wxDouble yc, wxDouble radius, wxDouble xc, wxDouble yc,
const wxColour &oColor, const wxColour &cColor) ; wxDouble radius,
const wxGraphicsGradientStops& stops);
// sets the font // sets the font
virtual wxGraphicsFont CreateFont( const wxFont &font , const wxColour &col = *wxBLACK ) ; virtual wxGraphicsFont CreateFont( const wxFont &font , const wxColour &col = *wxBLACK ) ;
@@ -1874,25 +1906,26 @@ wxGraphicsBrush wxCairoRenderer::CreateBrush(const wxBrush& brush )
} }
} }
// sets the brush to a linear gradient, starting at (x1,y1) with color c1 to (x2,y2) with color c2 wxGraphicsBrush
wxGraphicsBrush wxCairoRenderer::CreateLinearGradientBrush( wxDouble x1, wxDouble y1, wxDouble x2, wxDouble y2, wxCairoRenderer::CreateLinearGradientBrush(wxDouble x1, wxDouble y1,
const wxColour&c1, const wxColour&c2) wxDouble x2, wxDouble y2,
const wxGraphicsGradientStops& stops)
{ {
wxGraphicsBrush p; wxGraphicsBrush p;
wxCairoBrushData* d = new wxCairoBrushData( this ); wxCairoBrushData* d = new wxCairoBrushData( this );
d->CreateLinearGradientBrush(x1, y1, x2, y2, c1, c2); d->CreateLinearGradientBrush(x1, y1, x2, y2, stops);
p.SetRefData(d); p.SetRefData(d);
return p; return p;
} }
// sets the brush to a radial gradient originating at (xo,yc) with color oColor and ends on a circle around (xc,yc) wxGraphicsBrush
// with radius r and color cColor wxCairoRenderer::CreateRadialGradientBrush(wxDouble xo, wxDouble yo,
wxGraphicsBrush wxCairoRenderer::CreateRadialGradientBrush( wxDouble xo, wxDouble yo, wxDouble xc, wxDouble yc, wxDouble radius, wxDouble xc, wxDouble yc, wxDouble r,
const wxColour &oColor, const wxColour &cColor) const wxGraphicsGradientStops& stops)
{ {
wxGraphicsBrush p; wxGraphicsBrush p;
wxCairoBrushData* d = new wxCairoBrushData( this ); wxCairoBrushData* d = new wxCairoBrushData( this );
d->CreateRadialGradientBrush(xo,yo,xc,yc,radius,oColor,cColor); d->CreateRadialGradientBrush(xo, yo, xc, yc, r, stops);
p.SetRefData(d); p.SetRefData(d);
return p; return p;
} }

View File

@@ -246,16 +246,24 @@ public:
wxGDIPlusBrushData( wxGraphicsRenderer* renderer, const wxBrush &brush ); wxGDIPlusBrushData( wxGraphicsRenderer* renderer, const wxBrush &brush );
~wxGDIPlusBrushData (); ~wxGDIPlusBrushData ();
void CreateLinearGradientBrush( wxDouble x1, wxDouble y1, wxDouble x2, wxDouble y2, void CreateLinearGradientBrush(wxDouble x1, wxDouble y1,
const wxColour&c1, const wxColour&c2 ); wxDouble x2, wxDouble y2,
void CreateRadialGradientBrush( wxDouble xo, wxDouble yo, wxDouble xc, wxDouble yc, wxDouble radius, const wxGraphicsGradientStops& stops);
const wxColour &oColor, const wxColour &cColor ); void CreateRadialGradientBrush(wxDouble xo, wxDouble yo,
wxDouble xc, wxDouble yc,
wxDouble radius,
const wxGraphicsGradientStops& stops);
virtual Brush* GetGDIPlusBrush() { return m_brush; } virtual Brush* GetGDIPlusBrush() { return m_brush; }
protected: protected:
virtual void Init(); virtual void Init();
private : private:
// common part of Create{Linear,Radial}GradientBrush()
template <typename T>
void SetGradientStops(T *brush, const wxGraphicsGradientStops& stops);
Brush* m_brush; Brush* m_brush;
Image* m_brushImage; Image* m_brushImage;
GraphicsPath* m_brushPath; GraphicsPath* m_brushPath;
@@ -628,28 +636,67 @@ void wxGDIPlusBrushData::Init()
m_brushPath= NULL; m_brushPath= NULL;
} }
void wxGDIPlusBrushData::CreateLinearGradientBrush( wxDouble x1, wxDouble y1, wxDouble x2, wxDouble y2, const wxColour&c1, const wxColour&c2) template <typename T>
void
wxGDIPlusBrushData::SetGradientStops(T *brush,
const wxGraphicsGradientStops& stops)
{ {
m_brush = new LinearGradientBrush( PointF( x1,y1) , PointF( x2,y2), const unsigned numStops = stops.GetCount();
Color( c1.Alpha(), c1.Red(),c1.Green() , c1.Blue() ), if ( numStops <= 2 )
Color( c2.Alpha(), c2.Red(),c2.Green() , c2.Blue() )); {
// initial and final colours are set during the brush creation, nothing
// more to do
return;
}
wxVector<Color> colors(numStops);
wxVector<REAL> positions(numStops);
for ( unsigned i = 0; i < numStops; i++ )
{
wxGraphicsGradientStop stop = stops.Item(i);
colors[i] = wxColourToColor(stop.GetColour());
positions[i] = stop.GetPosition();
}
brush->SetInterpolationColors(&colors[0], &positions[0], numStops);
} }
void wxGDIPlusBrushData::CreateRadialGradientBrush( wxDouble xo, wxDouble yo, wxDouble xc, wxDouble yc, wxDouble radius, void
const wxColour &oColor, const wxColour &cColor) wxGDIPlusBrushData::CreateLinearGradientBrush(wxDouble x1, wxDouble y1,
wxDouble x2, wxDouble y2,
const wxGraphicsGradientStops& stops)
{
LinearGradientBrush * const
brush = new LinearGradientBrush(PointF(x1, y1) , PointF(x2, y2),
wxColourToColor(stops.GetStartColour()),
wxColourToColor(stops.GetEndColour()));
m_brush = brush;
SetGradientStops(brush, stops);
}
void
wxGDIPlusBrushData::CreateRadialGradientBrush(wxDouble xo, wxDouble yo,
wxDouble xc, wxDouble yc,
wxDouble radius,
const wxGraphicsGradientStops& stops)
{ {
// Create a path that consists of a single circle.
m_brushPath = new GraphicsPath(); m_brushPath = new GraphicsPath();
m_brushPath->AddEllipse( (REAL)(xc-radius), (REAL)(yc-radius), (REAL)(2*radius), (REAL)(2*radius)); m_brushPath->AddEllipse( (REAL)(xc-radius), (REAL)(yc-radius),
(REAL)(2*radius), (REAL)(2*radius));
PathGradientBrush *b = new PathGradientBrush(m_brushPath); PathGradientBrush * const brush = new PathGradientBrush(m_brushPath);
m_brush = b; m_brush = brush;
b->SetCenterPoint( PointF(xo,yo)); brush->SetCenterPoint(PointF(xo, yo));
b->SetCenterColor(Color( oColor.Alpha(), oColor.Red(),oColor.Green() , oColor.Blue() )); brush->SetCenterColor(wxColourToColor(stops.GetStartColour()));
Color colors[] = {Color( cColor.Alpha(), cColor.Red(),cColor.Green() , cColor.Blue() )}; const Color col(wxColourToColor(stops.GetEndColour()));
int count = 1; int count = 1;
b->SetSurroundColors(colors, &count); brush->SetSurroundColors(&col, &count);
SetGradientStops(brush, stops);
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@@ -1596,15 +1643,16 @@ public :
virtual wxGraphicsBrush CreateBrush(const wxBrush& brush ) ; virtual wxGraphicsBrush CreateBrush(const wxBrush& brush ) ;
// sets the brush to a linear gradient, starting at (x1,y1) with color c1 to (x2,y2) with color c2 virtual wxGraphicsBrush
virtual wxGraphicsBrush CreateLinearGradientBrush( wxDouble x1, wxDouble y1, wxDouble x2, wxDouble y2, CreateLinearGradientBrush(wxDouble x1, wxDouble y1,
const wxColour&c1, const wxColour&c2) ; wxDouble x2, wxDouble y2,
const wxGraphicsGradientStops& stops);
// sets the brush to a radial gradient originating at (xo,yc) with color oColor and ends on a circle around (xc,yc)
// with radius r and color cColor
virtual wxGraphicsBrush CreateRadialGradientBrush( wxDouble xo, wxDouble yo, wxDouble xc, wxDouble yc, wxDouble radius,
const wxColour &oColor, const wxColour &cColor) ;
virtual wxGraphicsBrush
CreateRadialGradientBrush(wxDouble xo, wxDouble yo,
wxDouble xc, wxDouble yc,
wxDouble radius,
const wxGraphicsGradientStops& stops);
// sets the font // sets the font
virtual wxGraphicsFont CreateFont( const wxFont &font , const wxColour &col = *wxBLACK ) ; virtual wxGraphicsFont CreateFont( const wxFont &font , const wxColour &col = *wxBLACK ) ;
@@ -1613,7 +1661,7 @@ public :
// create a graphics bitmap from a native bitmap // create a graphics bitmap from a native bitmap
virtual wxGraphicsBitmap CreateBitmapFromNativeBitmap( void* bitmap ); virtual wxGraphicsBitmap CreateBitmapFromNativeBitmap( void* bitmap );
// create a subimage from a native image representation // create a subimage from a native image representation
virtual wxGraphicsBitmap CreateSubBitmap( const wxGraphicsBitmap &bitmap, wxDouble x, wxDouble y, wxDouble w, wxDouble h ); virtual wxGraphicsBitmap CreateSubBitmap( const wxGraphicsBitmap &bitmap, wxDouble x, wxDouble y, wxDouble w, wxDouble h );
@@ -1789,27 +1837,29 @@ wxGraphicsBrush wxGDIPlusRenderer::CreateBrush(const wxBrush& brush )
} }
} }
// sets the brush to a linear gradient, starting at (x1,y1) with color c1 to (x2,y2) with color c2 wxGraphicsBrush
wxGraphicsBrush wxGDIPlusRenderer::CreateLinearGradientBrush( wxDouble x1, wxDouble y1, wxDouble x2, wxDouble y2, wxGDIPlusRenderer::CreateLinearGradientBrush(wxDouble x1, wxDouble y1,
const wxColour&c1, const wxColour&c2) wxDouble x2, wxDouble y2,
const wxGraphicsGradientStops& stops)
{ {
ENSURE_LOADED_OR_RETURN(wxNullGraphicsBrush); ENSURE_LOADED_OR_RETURN(wxNullGraphicsBrush);
wxGraphicsBrush p; wxGraphicsBrush p;
wxGDIPlusBrushData* d = new wxGDIPlusBrushData( this ); wxGDIPlusBrushData* d = new wxGDIPlusBrushData( this );
d->CreateLinearGradientBrush(x1, y1, x2, y2, c1, c2); d->CreateLinearGradientBrush(x1, y1, x2, y2, stops);
p.SetRefData(d); p.SetRefData(d);
return p; return p;
} }
// sets the brush to a radial gradient originating at (xo,yc) with color oColor and ends on a circle around (xc,yc) wxGraphicsBrush
// with radius r and color cColor wxGDIPlusRenderer::CreateRadialGradientBrush(wxDouble xo, wxDouble yo,
wxGraphicsBrush wxGDIPlusRenderer::CreateRadialGradientBrush( wxDouble xo, wxDouble yo, wxDouble xc, wxDouble yc, wxDouble radius, wxDouble xc, wxDouble yc,
const wxColour &oColor, const wxColour &cColor) wxDouble radius,
const wxGraphicsGradientStops& stops)
{ {
ENSURE_LOADED_OR_RETURN(wxNullGraphicsBrush); ENSURE_LOADED_OR_RETURN(wxNullGraphicsBrush);
wxGraphicsBrush p; wxGraphicsBrush p;
wxGDIPlusBrushData* d = new wxGDIPlusBrushData( this ); wxGDIPlusBrushData* d = new wxGDIPlusBrushData( this );
d->CreateRadialGradientBrush(xo,yo,xc,yc,radius,oColor,cColor); d->CreateRadialGradientBrush(xo,yo,xc,yc,radius,stops);
p.SetRefData(d); p.SetRefData(d);
return p; return p;
} }

View File

@@ -666,15 +666,18 @@ public:
~wxMacCoreGraphicsBrushData (); ~wxMacCoreGraphicsBrushData ();
virtual void Apply( wxGraphicsContext* context ); virtual void Apply( wxGraphicsContext* context );
void CreateLinearGradientBrush( wxDouble x1, wxDouble y1, wxDouble x2, wxDouble y2, void CreateLinearGradientBrush(wxDouble x1, wxDouble y1,
const wxColour&c1, const wxColour&c2 ); wxDouble x2, wxDouble y2,
void CreateRadialGradientBrush( wxDouble xo, wxDouble yo, wxDouble xc, wxDouble yc, wxDouble radius, const wxGraphicsGradientStops& stops);
const wxColour &oColor, const wxColour &cColor ); void CreateRadialGradientBrush(wxDouble xo, wxDouble yo,
wxDouble xc, wxDouble yc, wxDouble radius,
const wxGraphicsGradientStops& stops);
virtual bool IsShading() { return m_isShading; } virtual bool IsShading() { return m_isShading; }
CGShadingRef GetShading() { return m_shading; } CGShadingRef GetShading() { return m_shading; }
protected: protected:
CGFunctionRef CreateGradientFunction( const wxColour& c1, const wxColour& c2 ); CGFunctionRef CreateGradientFunction(const wxGraphicsGradientStops& stops);
static void CalculateShadingValues (void *info, const CGFloat *in, CGFloat *out); static void CalculateShadingValues (void *info, const CGFloat *in, CGFloat *out);
virtual void Init(); virtual void Init();
@@ -691,19 +694,24 @@ wxMacCoreGraphicsBrushData::wxMacCoreGraphicsBrushData( wxGraphicsRenderer* rend
Init(); Init();
} }
void wxMacCoreGraphicsBrushData::CreateLinearGradientBrush( wxDouble x1, wxDouble y1, wxDouble x2, wxDouble y2, void
const wxColour&c1, const wxColour&c2 ) wxMacCoreGraphicsBrushData::CreateLinearGradientBrush(wxDouble x1, wxDouble y1,
wxDouble x2, wxDouble y2,
const wxGraphicsGradientStops& stops)
{ {
m_gradientFunction = CreateGradientFunction( c1, c2 ); m_gradientFunction = CreateGradientFunction(stops);
m_shading = CGShadingCreateAxial( wxMacGetGenericRGBColorSpace(), CGPointMake((CGFloat) x1, (CGFloat) y1), m_shading = CGShadingCreateAxial( wxMacGetGenericRGBColorSpace(), CGPointMake((CGFloat) x1, (CGFloat) y1),
CGPointMake((CGFloat) x2,(CGFloat) y2), m_gradientFunction, true, true ) ; CGPointMake((CGFloat) x2,(CGFloat) y2), m_gradientFunction, true, true ) ;
m_isShading = true ; m_isShading = true ;
} }
void wxMacCoreGraphicsBrushData::CreateRadialGradientBrush( wxDouble xo, wxDouble yo, wxDouble xc, wxDouble yc, wxDouble radius, void
const wxColour &oColor, const wxColour &cColor ) wxMacCoreGraphicsBrushData::CreateRadialGradientBrush(wxDouble xo, wxDouble yo,
wxDouble xc, wxDouble yc,
wxDouble radius,
const wxGraphicsGradientStops& stops)
{ {
m_gradientFunction = CreateGradientFunction( oColor, cColor ); m_gradientFunction = CreateGradientFunction(stops);
m_shading = CGShadingCreateRadial( wxMacGetGenericRGBColorSpace(), CGPointMake((CGFloat) xo,(CGFloat) yo), 0, m_shading = CGShadingCreateRadial( wxMacGetGenericRGBColorSpace(), CGPointMake((CGFloat) xo,(CGFloat) yo), 0,
CGPointMake((CGFloat) xc,(CGFloat) yc), (CGFloat) radius, m_gradientFunction, true, true ) ; CGPointMake((CGFloat) xc,(CGFloat) yc), (CGFloat) radius, m_gradientFunction, true, true ) ;
m_isShading = true ; m_isShading = true ;
@@ -759,8 +767,13 @@ void wxMacCoreGraphicsBrushData::CalculateShadingValues (void *info, const CGFlo
} }
} }
CGFunctionRef wxMacCoreGraphicsBrushData::CreateGradientFunction( const wxColour& c1, const wxColour& c2 ) CGFunctionRef
wxMacCoreGraphicsBrushData::CreateGradientFunction(const wxGraphicsGradientStops& stops)
{ {
// TODO: implement support for intermediate gradient stops
const wxColour c1 = stops.GetStartColour();
const wxColour c2 = stops.GetEndColour();
static const CGFunctionCallbacks callbacks = { 0, &CalculateShadingValues, NULL }; static const CGFunctionCallbacks callbacks = { 0, &CalculateShadingValues, NULL };
static const CGFloat input_value_range [2] = { 0, 1 }; static const CGFloat input_value_range [2] = { 0, 1 };
static const CGFloat output_value_ranges [8] = { 0, 1, 0, 1, 0, 1, 0, 1 }; static const CGFloat output_value_ranges [8] = { 0, 1, 0, 1, 0, 1, 0, 1 };
@@ -1138,7 +1151,7 @@ public :
// appends a rectangle as a new closed subpath // appends a rectangle as a new closed subpath
virtual void AddRectangle( wxDouble x, wxDouble y, wxDouble w, wxDouble h ); virtual void AddRectangle( wxDouble x, wxDouble y, wxDouble w, wxDouble h );
// appends a circle as a new closed subpath // appends a circle as a new closed subpath
virtual void AddCircle( wxDouble x, wxDouble y, wxDouble r ); virtual void AddCircle( wxDouble x, wxDouble y, wxDouble r );
// appends an ellipsis as a new closed subpath fitting the passed rectangle // appends an ellipsis as a new closed subpath fitting the passed rectangle
@@ -2618,14 +2631,16 @@ public :
virtual wxGraphicsBrush CreateBrush(const wxBrush& brush ) ; virtual wxGraphicsBrush CreateBrush(const wxBrush& brush ) ;
// sets the brush to a linear gradient, starting at (x1,y1) with color c1 to (x2,y2) with color c2 virtual wxGraphicsBrush
virtual wxGraphicsBrush CreateLinearGradientBrush( wxDouble x1, wxDouble y1, wxDouble x2, wxDouble y2, CreateLinearGradientBrush(wxDouble x1, wxDouble y1,
const wxColour&c1, const wxColour&c2) ; wxDouble x2, wxDouble y2,
const wxGraphicsGradientStops& stops);
// sets the brush to a radial gradient originating at (xo,yc) with color oColor and ends on a circle around (xc,yc) virtual wxGraphicsBrush
// with radius r and color cColor CreateRadialGradientBrush(wxDouble xo, wxDouble yo,
virtual wxGraphicsBrush CreateRadialGradientBrush( wxDouble xo, wxDouble yo, wxDouble xc, wxDouble yc, wxDouble radius, wxDouble xc, wxDouble yc,
const wxColour &oColor, const wxColour &cColor) ; wxDouble radius,
const wxGraphicsGradientStops& stops);
// sets the font // sets the font
virtual wxGraphicsFont CreateFont( const wxFont &font , const wxColour &col = *wxBLACK ) ; virtual wxGraphicsFont CreateFont( const wxFont &font , const wxColour &col = *wxBLACK ) ;
@@ -2819,25 +2834,27 @@ wxGraphicsBitmap wxMacCoreGraphicsRenderer::CreateSubBitmap( const wxGraphicsBit
return wxNullGraphicsBitmap; return wxNullGraphicsBitmap;
} }
// sets the brush to a linear gradient, starting at (x1,y1) with color c1 to (x2,y2) with color c2 wxGraphicsBrush
wxGraphicsBrush wxMacCoreGraphicsRenderer::CreateLinearGradientBrush( wxDouble x1, wxDouble y1, wxDouble x2, wxDouble y2, wxMacCoreGraphicsRenderer::CreateLinearGradientBrush(wxDouble x1, wxDouble y1,
const wxColour&c1, const wxColour&c2) wxDouble x2, wxDouble y2,
const wxGraphicsGradientStops& stops)
{ {
wxGraphicsBrush p; wxGraphicsBrush p;
wxMacCoreGraphicsBrushData* d = new wxMacCoreGraphicsBrushData( this ); wxMacCoreGraphicsBrushData* d = new wxMacCoreGraphicsBrushData( this );
d->CreateLinearGradientBrush(x1, y1, x2, y2, c1, c2); d->CreateLinearGradientBrush(x1, y1, x2, y2, stops);
p.SetRefData(d); p.SetRefData(d);
return p; return p;
} }
// sets the brush to a radial gradient originating at (xo,yc) with color oColor and ends on a circle around (xc,yc) wxGraphicsBrush
// with radius r and color cColor wxMacCoreGraphicsRenderer::CreateRadialGradientBrush(wxDouble xo, wxDouble yo,
wxGraphicsBrush wxMacCoreGraphicsRenderer::CreateRadialGradientBrush( wxDouble xo, wxDouble yo, wxDouble xc, wxDouble yc, wxDouble radius, wxDouble xc, wxDouble yc,
const wxColour &oColor, const wxColour &cColor) wxDouble radius,
const wxGraphicsGradientStops& stops)
{ {
wxGraphicsBrush p; wxGraphicsBrush p;
wxMacCoreGraphicsBrushData* d = new wxMacCoreGraphicsBrushData( this ); wxMacCoreGraphicsBrushData* d = new wxMacCoreGraphicsBrushData( this );
d->CreateRadialGradientBrush(xo,yo,xc,yc,radius,oColor,cColor); d->CreateRadialGradientBrush(xo, yo, xc, yc, radius, stops);
p.SetRefData(d); p.SetRefData(d);
return p; return p;
} }