added linear and concentric gradient fill functions (modified/fixed patch from Ryan Norton)
git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@37512 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
@@ -47,6 +47,7 @@ All:
|
|||||||
All (GUI):
|
All (GUI):
|
||||||
|
|
||||||
- Added wxTreebook (uses a wxTreeCtrl to control pages).
|
- Added wxTreebook (uses a wxTreeCtrl to control pages).
|
||||||
|
- Added wxDC::GradientFillLinear/Concentric()
|
||||||
- Added wxKeyEvent::GetModifiers()
|
- Added wxKeyEvent::GetModifiers()
|
||||||
- Added wxDialog::SetEscapeId().
|
- Added wxDialog::SetEscapeId().
|
||||||
- wxItemContainerImmutable::FindString unified (affects wxRadioBox, wxListBox,
|
- wxItemContainerImmutable::FindString unified (affects wxRadioBox, wxListBox,
|
||||||
|
@@ -786,6 +786,35 @@ Gets the current user scale factor (set by \helpref{SetUserScale}{wxdcsetusersca
|
|||||||
array {\tt ( x, y )}}
|
array {\tt ( x, y )}}
|
||||||
|
|
||||||
|
|
||||||
|
\membersection{wxDC::GradientFillConcentric}\label{wxdcgradientfillconcentric}
|
||||||
|
|
||||||
|
\func{void}{GradientFillConcentric}{\param{const wxRect\&}{ rect}, \param{const wxColour\&}{ initialColour}, \param{const wxColour\&}{ destColour}}
|
||||||
|
|
||||||
|
\func{void}{GradientFillConcentric}{\param{const wxRect\&}{ rect}, \param{const wxColour\&}{ initialColour}, \param{const wxColour\&}{ destColour}, \param{const wxPoint\& }{circleCenter}}
|
||||||
|
|
||||||
|
Fill the area specified by rect with a radial gradient, starting from
|
||||||
|
\arg{initialColour} at the centre of the circle and fading to \arg{destColour}
|
||||||
|
on the circle outside.
|
||||||
|
|
||||||
|
\arg{circleCenter} are the relative coordinates of centre of the circle in
|
||||||
|
the specified \arg{rect}. If not specified, the cercle is placed at the
|
||||||
|
centre of rect.
|
||||||
|
|
||||||
|
\textbf{Note: } Currently this function is very slow, don't use it for
|
||||||
|
real-time drawing.
|
||||||
|
|
||||||
|
|
||||||
|
\membersection{wxDC::GradientFillLinear}\label{wxdcgradientfilllinear}
|
||||||
|
|
||||||
|
\func{void}{GradientFillLinear}{\param{const wxRect\&}{ rect}, \param{const wxColour\&}{ initialColour}, \param{const wxColour\&}{ destColour}, \param{wxDirection}{ nDirection = wxEAST}}
|
||||||
|
|
||||||
|
Fill the area specified by \arg{rect} with a linear gradient, starting from
|
||||||
|
\arg{initialColour} and eventually fading to \arg{destColour}. The
|
||||||
|
\arg{nDirection} specifies the direction of the colour change, default is to
|
||||||
|
use \arg{initialColour} on the left part of the rectangle and
|
||||||
|
\arg{destColour} on the right one.
|
||||||
|
|
||||||
|
|
||||||
\membersection{wxDC::LogicalToDeviceX}\label{wxdclogicaltodevicex}
|
\membersection{wxDC::LogicalToDeviceX}\label{wxdclogicaltodevicex}
|
||||||
|
|
||||||
\func{wxCoord}{LogicalToDeviceX}{\param{wxCoord}{ x}}
|
\func{wxCoord}{LogicalToDeviceX}{\param{wxCoord}{ x}}
|
||||||
|
@@ -158,6 +158,27 @@ public:
|
|||||||
int style = wxFLOOD_SURFACE)
|
int style = wxFLOOD_SURFACE)
|
||||||
{ return DoFloodFill(pt.x, pt.y, col, style); }
|
{ return DoFloodFill(pt.x, pt.y, col, style); }
|
||||||
|
|
||||||
|
// fill the area specified by rect with a radial gradient, starting from
|
||||||
|
// initialColour in the centre of the cercle and fading to destColour.
|
||||||
|
void GradientFillConcentric(const wxRect& rect,
|
||||||
|
const wxColour& initialColour,
|
||||||
|
const wxColour& destColour)
|
||||||
|
{ GradientFillConcentric(rect, initialColour, destColour,
|
||||||
|
wxPoint(rect.GetWidth() / 2,
|
||||||
|
rect.GetHeight() / 2)); }
|
||||||
|
|
||||||
|
void GradientFillConcentric(const wxRect& rect,
|
||||||
|
const wxColour& initialColour,
|
||||||
|
const wxColour& destColour,
|
||||||
|
const wxPoint& circleCenter);
|
||||||
|
|
||||||
|
// fill the area specified by rect with a linear gradient
|
||||||
|
void GradientFillLinear(const wxRect& rect,
|
||||||
|
const wxColour& initialColour,
|
||||||
|
const wxColour& destColour,
|
||||||
|
wxDirection nDirection = wxEAST)
|
||||||
|
{ DoGradientFillLinear(rect, initialColour, destColour, nDirection); }
|
||||||
|
|
||||||
bool GetPixel(wxCoord x, wxCoord y, wxColour *col) const
|
bool GetPixel(wxCoord x, wxCoord y, wxColour *col) const
|
||||||
{ return DoGetPixel(x, y, col); }
|
{ return DoGetPixel(x, y, col); }
|
||||||
bool GetPixel(const wxPoint& pt, wxColour *col) const
|
bool GetPixel(const wxPoint& pt, wxColour *col) const
|
||||||
@@ -645,6 +666,11 @@ protected:
|
|||||||
virtual bool DoFloodFill(wxCoord x, wxCoord y, const wxColour& col,
|
virtual bool DoFloodFill(wxCoord x, wxCoord y, const wxColour& col,
|
||||||
int style = wxFLOOD_SURFACE) = 0;
|
int style = wxFLOOD_SURFACE) = 0;
|
||||||
|
|
||||||
|
virtual void DoGradientFillLinear(const wxRect& rect,
|
||||||
|
const wxColour& initialColour,
|
||||||
|
const wxColour& destColour,
|
||||||
|
wxDirection nDirection = wxEAST);
|
||||||
|
|
||||||
virtual bool DoGetPixel(wxCoord x, wxCoord y, wxColour *col) const = 0;
|
virtual bool DoGetPixel(wxCoord x, wxCoord y, wxColour *col) const = 0;
|
||||||
|
|
||||||
virtual void DoDrawPoint(wxCoord x, wxCoord y) = 0;
|
virtual void DoDrawPoint(wxCoord x, wxCoord y) = 0;
|
||||||
|
@@ -164,6 +164,11 @@ protected:
|
|||||||
virtual bool DoFloodFill(wxCoord x, wxCoord y, const wxColour& col,
|
virtual bool DoFloodFill(wxCoord x, wxCoord y, const wxColour& col,
|
||||||
int style = wxFLOOD_SURFACE);
|
int style = wxFLOOD_SURFACE);
|
||||||
|
|
||||||
|
virtual void DoGradientFillLinear(const wxRect& rect,
|
||||||
|
const wxColour& initialColour,
|
||||||
|
const wxColour& destColour,
|
||||||
|
wxDirection nDirection = wxEAST);
|
||||||
|
|
||||||
virtual bool DoGetPixel(wxCoord x, wxCoord y, wxColour *col) const;
|
virtual bool DoGetPixel(wxCoord x, wxCoord y, wxColour *col) const;
|
||||||
|
|
||||||
virtual void DoDrawPoint(wxCoord x, wxCoord y);
|
virtual void DoDrawPoint(wxCoord x, wxCoord y);
|
||||||
|
@@ -60,7 +60,9 @@ enum ScreenToShow
|
|||||||
Show_Ops,
|
Show_Ops,
|
||||||
Show_Regions,
|
Show_Regions,
|
||||||
Show_Circles,
|
Show_Circles,
|
||||||
Show_Splines
|
Show_Splines,
|
||||||
|
Show_Gradient,
|
||||||
|
Show_Max
|
||||||
};
|
};
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
@@ -164,6 +166,7 @@ protected:
|
|||||||
void DrawCircles(wxDC& dc);
|
void DrawCircles(wxDC& dc);
|
||||||
void DrawSplines(wxDC& dc);
|
void DrawSplines(wxDC& dc);
|
||||||
void DrawDefault(wxDC& dc);
|
void DrawDefault(wxDC& dc);
|
||||||
|
void DrawGradients(wxDC& dc);
|
||||||
|
|
||||||
void DrawRegionsHelper(wxDC& dc, wxCoord x, bool firstTime);
|
void DrawRegionsHelper(wxDC& dc, wxCoord x, bool firstTime);
|
||||||
|
|
||||||
@@ -200,7 +203,8 @@ enum
|
|||||||
File_ShowRegions,
|
File_ShowRegions,
|
||||||
File_ShowCircles,
|
File_ShowCircles,
|
||||||
File_ShowSplines,
|
File_ShowSplines,
|
||||||
MenuShow_Last = File_ShowSplines,
|
File_ShowGradients,
|
||||||
|
MenuShow_Last = File_ShowGradients,
|
||||||
|
|
||||||
File_Clip,
|
File_Clip,
|
||||||
|
|
||||||
@@ -971,6 +975,36 @@ void MyCanvas::DrawSplines(wxDC& dc)
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MyCanvas::DrawGradients(wxDC& dc)
|
||||||
|
{
|
||||||
|
// LHS: linear
|
||||||
|
wxRect r(10, 10, 100, 100);
|
||||||
|
dc.GradientFillLinear(r, *wxWHITE, *wxBLUE, wxRIGHT);
|
||||||
|
|
||||||
|
r.Offset(0, 110);
|
||||||
|
dc.GradientFillLinear(r, *wxWHITE, *wxBLUE, wxLEFT);
|
||||||
|
|
||||||
|
r.Offset(0, 110);
|
||||||
|
dc.GradientFillLinear(r, *wxWHITE, *wxBLUE, wxDOWN);
|
||||||
|
|
||||||
|
r.Offset(0, 110);
|
||||||
|
dc.GradientFillLinear(r, *wxWHITE, *wxBLUE, wxUP);
|
||||||
|
|
||||||
|
|
||||||
|
// RHS: concentric
|
||||||
|
r = wxRect(200, 10, 100, 100);
|
||||||
|
dc.GradientFillConcentric(r, *wxBLUE, *wxWHITE);
|
||||||
|
|
||||||
|
r.Offset(0, 110);
|
||||||
|
dc.GradientFillConcentric(r, *wxWHITE, *wxBLUE);
|
||||||
|
|
||||||
|
r.Offset(0, 110);
|
||||||
|
dc.GradientFillConcentric(r, *wxBLUE, *wxWHITE, wxPoint(0, 0));
|
||||||
|
|
||||||
|
r.Offset(0, 110);
|
||||||
|
dc.GradientFillConcentric(r, *wxBLUE, *wxWHITE, wxPoint(100, 100));
|
||||||
|
}
|
||||||
|
|
||||||
void MyCanvas::DrawRegions(wxDC& dc)
|
void MyCanvas::DrawRegions(wxDC& dc)
|
||||||
{
|
{
|
||||||
dc.DrawText(_T("You should see a red rect partly covered by a cyan one ")
|
dc.DrawText(_T("You should see a red rect partly covered by a cyan one ")
|
||||||
@@ -1105,6 +1139,10 @@ void MyCanvas::OnPaint(wxPaintEvent &WXUNUSED(event))
|
|||||||
case Show_Ops:
|
case Show_Ops:
|
||||||
DrawWithLogicalOps(dc);
|
DrawWithLogicalOps(dc);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case Show_Gradient:
|
||||||
|
DrawGradients(dc);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1161,7 +1199,8 @@ MyFrame::MyFrame(const wxString& title, const wxPoint& pos, const wxSize& size)
|
|||||||
menuFile->Append(File_ShowOps, _T("&ROP screen\tF7"));
|
menuFile->Append(File_ShowOps, _T("&ROP screen\tF7"));
|
||||||
menuFile->Append(File_ShowRegions, _T("Re&gions screen\tF8"));
|
menuFile->Append(File_ShowRegions, _T("Re&gions screen\tF8"));
|
||||||
menuFile->Append(File_ShowCircles, _T("&Circles screen\tF9"));
|
menuFile->Append(File_ShowCircles, _T("&Circles screen\tF9"));
|
||||||
menuFile->Append(File_ShowSplines, _T("&Splines screen"));
|
menuFile->Append(File_ShowSplines, _T("&Splines screen\tF11"));
|
||||||
|
menuFile->Append(File_ShowGradients, _T("&Gradients screen\tF12"));
|
||||||
menuFile->AppendSeparator();
|
menuFile->AppendSeparator();
|
||||||
menuFile->AppendCheckItem(File_Clip, _T("&Clip\tCtrl-C"), _T("Clip/unclip drawing"));
|
menuFile->AppendCheckItem(File_Clip, _T("&Clip\tCtrl-C"), _T("Clip/unclip drawing"));
|
||||||
menuFile->AppendSeparator();
|
menuFile->AppendSeparator();
|
||||||
|
@@ -680,6 +680,165 @@ void wxDCBase::DrawLabel(const wxString& text,
|
|||||||
CalcBoundingBox(x0 + width0, y0 + height);
|
CalcBoundingBox(x0 + width0, y0 + height);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void wxDCBase::DoGradientFillLinear(const wxRect& rect,
|
||||||
|
const wxColour& initialColour,
|
||||||
|
const wxColour& destColour,
|
||||||
|
wxDirection nDirection)
|
||||||
|
{
|
||||||
|
// save old pen
|
||||||
|
wxPen oldPen = m_pen;
|
||||||
|
|
||||||
|
wxUint8 nR1 = destColour.Red();
|
||||||
|
wxUint8 nG1 = destColour.Green();
|
||||||
|
wxUint8 nB1 = destColour.Blue();
|
||||||
|
wxUint8 nR2 = initialColour.Red();
|
||||||
|
wxUint8 nG2 = initialColour.Green();
|
||||||
|
wxUint8 nB2 = initialColour.Blue();
|
||||||
|
wxUint8 nR, nG, nB;
|
||||||
|
|
||||||
|
if ( nDirection == wxEAST || nDirection == wxWEST )
|
||||||
|
{
|
||||||
|
wxInt32 x = rect.GetWidth();
|
||||||
|
wxInt32 w = x; // width of area to shade
|
||||||
|
wxInt32 xDelta = w/256; // height of one shade bend
|
||||||
|
if (xDelta < 1)
|
||||||
|
xDelta = 1;
|
||||||
|
|
||||||
|
while (x >= xDelta)
|
||||||
|
{
|
||||||
|
x -= xDelta;
|
||||||
|
if (nR1 > nR2)
|
||||||
|
nR = nR1 - (nR1-nR2)*(w-x)/w;
|
||||||
|
else
|
||||||
|
nR = nR1 + (nR2-nR1)*(w-x)/w;
|
||||||
|
|
||||||
|
if (nG1 > nG2)
|
||||||
|
nG = nG1 - (nG1-nG2)*(w-x)/w;
|
||||||
|
else
|
||||||
|
nG = nG1 + (nG2-nG1)*(w-x)/w;
|
||||||
|
|
||||||
|
if (nB1 > nB2)
|
||||||
|
nB = nB1 - (nB1-nB2)*(w-x)/w;
|
||||||
|
else
|
||||||
|
nB = nB1 + (nB2-nB1)*(w-x)/w;
|
||||||
|
|
||||||
|
SetPen(wxPen(wxColour(nR, nG, nB), 1, wxSOLID));
|
||||||
|
if(nDirection == wxEAST)
|
||||||
|
DrawRectangle(rect.GetLeft()+x, rect.GetTop(),
|
||||||
|
xDelta, rect.GetHeight());
|
||||||
|
else //nDirection == wxWEST
|
||||||
|
DrawRectangle(rect.GetRight()-x-xDelta, rect.GetTop(),
|
||||||
|
xDelta, rect.GetHeight());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else // nDirection == wxNORTH || nDirection == wxSOUTH
|
||||||
|
{
|
||||||
|
wxInt32 y = rect.GetHeight();
|
||||||
|
wxInt32 w = y; // height of area to shade
|
||||||
|
wxInt32 yDelta = w/255; // height of one shade bend
|
||||||
|
if (yDelta < 1)
|
||||||
|
yDelta = 1;
|
||||||
|
|
||||||
|
while (y > 0)
|
||||||
|
{
|
||||||
|
y -= yDelta;
|
||||||
|
if (nR1 > nR2)
|
||||||
|
nR = nR1 - (nR1-nR2)*(w-y)/w;
|
||||||
|
else
|
||||||
|
nR = nR1 + (nR2-nR1)*(w-y)/w;
|
||||||
|
|
||||||
|
if (nG1 > nG2)
|
||||||
|
nG = nG1 - (nG1-nG2)*(w-y)/w;
|
||||||
|
else
|
||||||
|
nG = nG1 + (nG2-nG1)*(w-y)/w;
|
||||||
|
|
||||||
|
if (nB1 > nB2)
|
||||||
|
nB = nB1 - (nB1-nB2)*(w-y)/w;
|
||||||
|
else
|
||||||
|
nB = nB1 + (nB2-nB1)*(w-y)/w;
|
||||||
|
|
||||||
|
SetPen(wxPen(wxColour(nR, nG, nB), 1, wxSOLID));
|
||||||
|
if(nDirection == wxNORTH)
|
||||||
|
DrawRectangle(rect.GetLeft(), rect.GetTop()+y,
|
||||||
|
rect.GetWidth(), yDelta);
|
||||||
|
else //nDirection == wxSOUTH
|
||||||
|
DrawRectangle(rect.GetLeft(), rect.GetBottom()-y-yDelta,
|
||||||
|
rect.GetWidth(), yDelta);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SetPen(oldPen);
|
||||||
|
}
|
||||||
|
|
||||||
|
void wxDCBase::GradientFillConcentric(const wxRect& rect,
|
||||||
|
const wxColour& initialColour,
|
||||||
|
const wxColour& destColour,
|
||||||
|
const wxPoint& circleCenter)
|
||||||
|
{
|
||||||
|
//save the old pen color
|
||||||
|
wxColour oldPenColour = m_pen.GetColour();
|
||||||
|
|
||||||
|
wxUint8 nR1 = destColour.Red();
|
||||||
|
wxUint8 nG1 = destColour.Green();
|
||||||
|
wxUint8 nB1 = destColour.Blue();
|
||||||
|
wxUint8 nR2 = initialColour.Red();
|
||||||
|
wxUint8 nG2 = initialColour.Green();
|
||||||
|
wxUint8 nB2 = initialColour.Blue();
|
||||||
|
wxUint8 nR, nG, nB;
|
||||||
|
|
||||||
|
|
||||||
|
//offsets of the current pixel
|
||||||
|
wxInt32 x, y;
|
||||||
|
|
||||||
|
//Color difference
|
||||||
|
wxInt32 nGradient;
|
||||||
|
|
||||||
|
//Radius
|
||||||
|
wxInt32 cx = rect.GetWidth() / 2;
|
||||||
|
wxInt32 cy = rect.GetHeight() / 2;
|
||||||
|
wxInt32 nRadius;
|
||||||
|
if (cx < cy)
|
||||||
|
nRadius = cx;
|
||||||
|
else
|
||||||
|
nRadius = cy;
|
||||||
|
|
||||||
|
//Offset of circle
|
||||||
|
wxInt32 nCircleOffX = circleCenter.x - (rect.GetWidth() / 2);
|
||||||
|
wxInt32 nCircleOffY = circleCenter.y - (rect.GetHeight() / 2);
|
||||||
|
|
||||||
|
for (x = 0; x < rect.GetWidth(); x++)
|
||||||
|
{
|
||||||
|
for (y = 0; y < rect.GetHeight(); y++)
|
||||||
|
{
|
||||||
|
//get color difference
|
||||||
|
nGradient = (
|
||||||
|
(nRadius -
|
||||||
|
(wxInt32)sqrt(
|
||||||
|
pow(x - cx - nCircleOffX, 2) +
|
||||||
|
pow(y - cy - nCircleOffY, 2)
|
||||||
|
)
|
||||||
|
) * 100
|
||||||
|
) / nRadius;
|
||||||
|
|
||||||
|
//normalize Gradient
|
||||||
|
if (nGradient < 0 )
|
||||||
|
nGradient = 0;
|
||||||
|
|
||||||
|
//get dest colors
|
||||||
|
nR = nR1 + ((nR2 - nR1) * nGradient / 100);
|
||||||
|
nG = nG1 + ((nG2 - nG1) * nGradient / 100);
|
||||||
|
nB = nB1 + ((nB2 - nB1) * nGradient / 100);
|
||||||
|
|
||||||
|
//set the pixel
|
||||||
|
m_pen.SetColour(wxColour(nR,nG,nB));
|
||||||
|
DrawPoint(wxPoint(x + rect.GetLeft(), y + rect.GetTop()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//return old pen color
|
||||||
|
m_pen.SetColour(oldPenColour);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Notes for wxWidgets DrawEllipticArcRot(...)
|
Notes for wxWidgets DrawEllipticArcRot(...)
|
||||||
|
|
||||||
|
123
src/msw/dc.cpp
123
src/msw/dc.cpp
@@ -196,6 +196,37 @@ private:
|
|||||||
DECLARE_NO_COPY_CLASS(StretchBltModeChanger)
|
DECLARE_NO_COPY_CLASS(StretchBltModeChanger)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// support for dynamic loading of msimg32.dll which we use for some functions
|
||||||
|
class wxMSImg32DLL
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
// return the symbol with the given name if the DLL not loaded or symbol
|
||||||
|
// not present
|
||||||
|
static void *GetSymbol(const wxChar *name)
|
||||||
|
{
|
||||||
|
wxLogNull noLog;
|
||||||
|
|
||||||
|
if ( !ms_triedToLoad )
|
||||||
|
{
|
||||||
|
ms_triedToLoad = true;
|
||||||
|
ms_dll.Load(_T("msimg32"));
|
||||||
|
}
|
||||||
|
|
||||||
|
return ms_dll.IsLoaded() ? ms_dll.GetSymbol(name) : NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
static wxDynamicLibrary ms_dll;
|
||||||
|
static bool ms_triedToLoad;
|
||||||
|
};
|
||||||
|
|
||||||
|
wxDynamicLibrary wxMSImg32DLL::ms_dll;
|
||||||
|
bool wxMSImg32DLL::ms_triedToLoad = false;
|
||||||
|
|
||||||
|
// helper macro for getting the symbols from msimg32.dll: it supposes that a
|
||||||
|
// type "name_t" is defined and casts the returned symbol to it automatically
|
||||||
|
#define wxMSIMG32_SYMBOL(name) (name ## _t)wxMSImg32DLL::GetSymbol(_T(#name))
|
||||||
|
|
||||||
// ===========================================================================
|
// ===========================================================================
|
||||||
// implementation
|
// implementation
|
||||||
// ===========================================================================
|
// ===========================================================================
|
||||||
@@ -2483,32 +2514,7 @@ static bool AlphaBlt(HDC hdcDst,
|
|||||||
HDC,int,int,int,int,
|
HDC,int,int,int,int,
|
||||||
BLENDFUNCTION);
|
BLENDFUNCTION);
|
||||||
|
|
||||||
// bitmaps can be drawn only from GUI thread so there is no need to
|
static AlphaBlend_t pfnAlphaBlend = wxMSIMG32_SYMBOL(AlphaBlend);
|
||||||
// protect this static variable from multiple threads
|
|
||||||
static bool s_triedToLoad = false;
|
|
||||||
static AlphaBlend_t pfnAlphaBlend = NULL;
|
|
||||||
if ( !s_triedToLoad )
|
|
||||||
{
|
|
||||||
s_triedToLoad = true;
|
|
||||||
|
|
||||||
// don't give errors about the DLL being unavailable, we're
|
|
||||||
// prepared to handle this
|
|
||||||
wxLogNull nolog;
|
|
||||||
|
|
||||||
wxDynamicLibrary dll(_T("msimg32.dll"));
|
|
||||||
if ( dll.IsLoaded() )
|
|
||||||
{
|
|
||||||
pfnAlphaBlend = (AlphaBlend_t)dll.GetSymbol(_T("AlphaBlend"));
|
|
||||||
if ( pfnAlphaBlend )
|
|
||||||
{
|
|
||||||
// we must keep the DLL loaded if we want to be able to
|
|
||||||
// call AlphaBlend() so just never unload it at all, not a
|
|
||||||
// big deal
|
|
||||||
dll.Detach();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( pfnAlphaBlend )
|
if ( pfnAlphaBlend )
|
||||||
{
|
{
|
||||||
BLENDFUNCTION bf;
|
BLENDFUNCTION bf;
|
||||||
@@ -2609,3 +2615,68 @@ wxAlphaBlend(HDC hdcDst, int xDst, int yDst,
|
|||||||
}
|
}
|
||||||
|
|
||||||
#endif // #ifdef wxHAVE_RAW_BITMAP
|
#endif // #ifdef wxHAVE_RAW_BITMAP
|
||||||
|
|
||||||
|
void wxDC::DoGradientFillLinear (const wxRect& rect,
|
||||||
|
const wxColour& initialColour,
|
||||||
|
const wxColour& destColour,
|
||||||
|
wxDirection nDirection)
|
||||||
|
{
|
||||||
|
// use native function if we have compile-time support it and can load it
|
||||||
|
// during run-time (linking to it statically would make the program
|
||||||
|
// unusable on earlier Windows versions)
|
||||||
|
#if defined(GRADIENT_FILL_RECT_H) && wxUSE_DYNLIB_CLASS
|
||||||
|
typedef BOOL
|
||||||
|
(WINAPI *GradientFill_t)(HDC, PTRIVERTEX, ULONG, PVOID, ULONG, ULONG);
|
||||||
|
static GradientFill_t pfnGradientFill = wxMSIMG32_SYMBOL(GradientFill);
|
||||||
|
|
||||||
|
if ( pfnGradientFill )
|
||||||
|
{
|
||||||
|
GRADIENT_RECT grect;
|
||||||
|
grect.UpperLeft = 0;
|
||||||
|
grect.LowerRight = 1;
|
||||||
|
|
||||||
|
// invert colours direction if not filling from left-to-right or
|
||||||
|
// top-to-bottom
|
||||||
|
int firstVertex = nDirection == wxNORTH || nDirection == wxWEST ? 1 : 0;
|
||||||
|
|
||||||
|
// one vertex for upper left and one for upper-right
|
||||||
|
TRIVERTEX vertices[2];
|
||||||
|
|
||||||
|
vertices[0].x = rect.GetLeft();
|
||||||
|
vertices[0].y = rect.GetTop();
|
||||||
|
vertices[1].x = rect.GetRight();
|
||||||
|
vertices[1].y = rect.GetBottom();
|
||||||
|
|
||||||
|
vertices[firstVertex].Red = initialColour.Red() << 8;
|
||||||
|
vertices[firstVertex].Green = initialColour.Green() << 8;
|
||||||
|
vertices[firstVertex].Blue = initialColour.Blue() << 8;
|
||||||
|
vertices[firstVertex].Alpha = 0;
|
||||||
|
vertices[1 - firstVertex].Red = destColour.Red() << 8;
|
||||||
|
vertices[1 - firstVertex].Green = destColour.Green() << 8;
|
||||||
|
vertices[1 - firstVertex].Blue = destColour.Blue() << 8;
|
||||||
|
vertices[1 - firstVertex].Alpha = 0;
|
||||||
|
|
||||||
|
if (nDirection == wxWEST ||
|
||||||
|
nDirection == wxEAST)
|
||||||
|
if ( (*pfnGradientFill)
|
||||||
|
(
|
||||||
|
GetHdc(),
|
||||||
|
vertices,
|
||||||
|
WXSIZEOF(vertices),
|
||||||
|
&grect,
|
||||||
|
1,
|
||||||
|
nDirection == wxWEST || nDirection == wxEAST
|
||||||
|
? GRADIENT_FILL_RECT_H
|
||||||
|
: GRADIENT_FILL_RECT_V
|
||||||
|
) )
|
||||||
|
{
|
||||||
|
// skip call of the base class version below
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
wxLogLastError(_T("GradientFill"));
|
||||||
|
}
|
||||||
|
#endif // wxUSE_DYNLIB_CLASS
|
||||||
|
|
||||||
|
wxDCBase::DoGradientFillLinear(rect, initialColour, destColour, nDirection);
|
||||||
|
}
|
||||||
|
Reference in New Issue
Block a user