512 lines
12 KiB
C++
512 lines
12 KiB
C++
/*
|
|
* (c) Copyright Ascensio System SIA 2010-2023
|
|
*
|
|
* This program is a free software product. You can redistribute it and/or
|
|
* modify it under the terms of the GNU Affero General Public License (AGPL)
|
|
* version 3 as published by the Free Software Foundation. In accordance with
|
|
* Section 7(a) of the GNU AGPL its Section 15 shall be amended to the effect
|
|
* that Ascensio System SIA expressly excludes the warranty of non-infringement
|
|
* of any third-party rights.
|
|
*
|
|
* This program is distributed WITHOUT ANY WARRANTY; without even the implied
|
|
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. For
|
|
* details, see the GNU AGPL at: http://www.gnu.org/licenses/agpl-3.0.html
|
|
*
|
|
* You can contact Ascensio System SIA at 20A-6 Ernesta Birznieka-Upish
|
|
* street, Riga, Latvia, EU, LV-1050.
|
|
*
|
|
* The interactive user interfaces in modified source and object code versions
|
|
* of the Program must display Appropriate Legal Notices, as required under
|
|
* Section 5 of the GNU AGPL version 3.
|
|
*
|
|
* Pursuant to Section 7(b) of the License you must retain the original Product
|
|
* logo when distributing the program. Pursuant to Section 7(e) we decline to
|
|
* grant you any rights under trademark law for use of our trademarks.
|
|
*
|
|
* All the Product's GUI elements, including illustrations and icon sets, as
|
|
* well as technical writing content are licensed under the terms of the
|
|
* Creative Commons Attribution-ShareAlike 4.0 International. See the License
|
|
* terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode
|
|
*
|
|
*/
|
|
#include "Brush.h"
|
|
|
|
namespace Aggplus
|
|
{
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
CBrush::CBrush(BrushType bType) : m_bType(bType)
|
|
{
|
|
}
|
|
|
|
CBrush::~CBrush()
|
|
{
|
|
}
|
|
|
|
BrushType CBrush::GetType() const
|
|
{
|
|
return m_bType;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
CBrushSolid::CBrushSolid(CColor dwColor) : CBrush(BrushTypeSolidColor), m_dwColor(dwColor)
|
|
{
|
|
}
|
|
CBrushSolid::~CBrushSolid()
|
|
{
|
|
}
|
|
CBrush* CBrushSolid::Clone() const
|
|
{
|
|
return new CBrushSolid(m_dwColor);
|
|
}
|
|
|
|
void CBrushSolid::GetColor(CColor* color) const { *color = m_dwColor; }
|
|
void CBrushSolid::SetColor(const CColor &color) { m_dwColor = color; }
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
CBrushHatch::CBrushHatch() : CBrush(BrushTypeHatchFill)
|
|
{
|
|
}
|
|
CBrushHatch::~CBrushHatch()
|
|
{
|
|
}
|
|
CBrush* CBrushHatch::Clone() const
|
|
{
|
|
CBrushHatch* clone = new CBrushHatch();
|
|
clone->m_name = m_name;
|
|
clone->m_dwColor1 = m_dwColor1;
|
|
clone->m_dwColor2 = m_dwColor2;
|
|
return clone;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
CBrushLinearGradient::CBrushLinearGradient( const PointF& p1, const PointF& p2, const CColor& c1, const CColor& c2 )
|
|
: CBrush(BrushTypeLinearGradient)
|
|
{
|
|
m_points[0] = p1;
|
|
m_points[1] = p2;
|
|
|
|
m_colors[0] = c1;
|
|
m_colors[1] = c2;
|
|
|
|
m_angle = 0;
|
|
m_wrap = Aggplus::WrapModeTile;
|
|
|
|
m_bAngleScalable = FALSE;
|
|
m_bRectable = FALSE;
|
|
m_bRelativeCoords = FALSE;
|
|
}
|
|
|
|
CBrushLinearGradient::CBrushLinearGradient( const Point& p1, const Point& p2, const CColor& c1, const CColor& c2 )
|
|
: CBrush(BrushTypeLinearGradient)
|
|
{
|
|
m_points[0].X = (float)p1.X;
|
|
m_points[0].Y = (float)p1.Y;
|
|
m_points[1].X = (float)p2.X;
|
|
m_points[1].Y = (float)p2.Y;
|
|
|
|
m_colors[0] = c1;
|
|
m_colors[1] = c2;
|
|
|
|
m_angle = 0;
|
|
|
|
m_wrap = Aggplus::WrapModeTile;
|
|
|
|
m_bAngleScalable = FALSE;
|
|
m_bRectable = FALSE;
|
|
m_bRelativeCoords = FALSE;
|
|
}
|
|
|
|
CBrushLinearGradient::CBrushLinearGradient( const RectF& rect, const CColor& c1, const CColor& c2, float angle, INT isAngleScalable )
|
|
: CBrush(BrushTypeLinearGradient)
|
|
{
|
|
m_points[0].X = rect.GetLeft();
|
|
m_points[0].Y = rect.GetTop();
|
|
m_points[1].X = rect.GetRight();
|
|
m_points[1].Y = rect.GetBottom();
|
|
|
|
m_colors[0] = c1;
|
|
m_colors[1] = c2;
|
|
|
|
m_angle = angle;
|
|
|
|
m_wrap = Aggplus::WrapModeTile;
|
|
|
|
m_bAngleScalable = isAngleScalable;
|
|
m_bRectable = TRUE;
|
|
m_bRelativeCoords = FALSE;
|
|
}
|
|
|
|
CBrushLinearGradient::CBrushLinearGradient( const Rect& rect, const CColor& c1, const CColor& c2, float angle, INT isAngleScalable )
|
|
: CBrush(BrushTypeLinearGradient)
|
|
{
|
|
m_points[0].X = (float)rect.GetLeft();
|
|
m_points[0].Y = (float)rect.GetTop();
|
|
m_points[1].X = (float)rect.GetRight();
|
|
m_points[1].Y = (float)rect.GetBottom();
|
|
|
|
m_colors[0] = c1;
|
|
m_colors[1] = c2;
|
|
|
|
m_angle = angle;
|
|
|
|
m_wrap = Aggplus::WrapModeTile;
|
|
|
|
m_bAngleScalable = isAngleScalable;
|
|
m_bRectable = TRUE;
|
|
m_bRelativeCoords = FALSE;
|
|
}
|
|
|
|
CBrushLinearGradient::CBrushLinearGradient( const RectF& rect, const CColor& c1, const CColor& c2, Aggplus::LinearGradientMode mode )
|
|
: CBrush(BrushTypeLinearGradient)
|
|
{
|
|
m_points[0].X = rect.GetLeft();
|
|
m_points[0].Y = rect.GetTop();
|
|
m_points[1].X = rect.GetRight();
|
|
m_points[1].Y = rect.GetBottom();
|
|
|
|
switch( mode )
|
|
{
|
|
case LinearGradientModeHorizontal:
|
|
m_angle = 0;
|
|
break;
|
|
|
|
case LinearGradientModeVertical:
|
|
m_angle = 90;
|
|
break;
|
|
|
|
case LinearGradientModeForwardDiagonal:
|
|
m_angle = 45;
|
|
break;
|
|
|
|
default:
|
|
m_angle = 315;
|
|
}
|
|
|
|
m_colors[0] = c1;
|
|
m_colors[1] = c2;
|
|
|
|
m_wrap = Aggplus::WrapModeTile;
|
|
|
|
m_bAngleScalable = TRUE;
|
|
m_bRectable = TRUE;
|
|
m_bRelativeCoords = FALSE;
|
|
}
|
|
|
|
CBrushLinearGradient::CBrushLinearGradient( const Rect& rect, const CColor& c1, const CColor& c2, Aggplus::LinearGradientMode mode )
|
|
: CBrush(BrushTypeLinearGradient)
|
|
{
|
|
m_points[0].X = (REAL)rect.GetLeft();
|
|
m_points[0].Y = (REAL)rect.GetTop();
|
|
m_points[1].X = (REAL)rect.GetRight();
|
|
m_points[1].Y = (REAL)rect.GetBottom();
|
|
|
|
switch( mode )
|
|
{
|
|
case LinearGradientModeHorizontal:
|
|
m_angle = 0;
|
|
break;
|
|
|
|
case LinearGradientModeVertical:
|
|
m_angle = 90;
|
|
break;
|
|
|
|
case LinearGradientModeForwardDiagonal:
|
|
m_angle = 45;
|
|
break;
|
|
|
|
default:
|
|
m_angle = 315;
|
|
}
|
|
|
|
m_colors[0] = c1;
|
|
m_colors[1] = c2;
|
|
|
|
m_wrap = Aggplus::WrapModeTile;
|
|
|
|
m_bAngleScalable = TRUE;
|
|
m_bRectable = TRUE;
|
|
m_bRelativeCoords = FALSE;
|
|
}
|
|
|
|
|
|
CBrushLinearGradient::CBrushLinearGradient( const CBrushLinearGradient& out )
|
|
: CBrush(out.m_bType)
|
|
{
|
|
m_colors[0] = out.m_colors[0];
|
|
m_colors[1] = out.m_colors[1];
|
|
m_points[0] = out.m_points[0];
|
|
m_points[1] = out.m_points[1];
|
|
|
|
m_subcolors = out.m_subcolors;
|
|
|
|
m_matrix = out.m_matrix;
|
|
m_angle = out.m_angle;
|
|
|
|
m_wrap = out.m_wrap;
|
|
m_bAngleScalable = out.m_bAngleScalable;
|
|
m_bRectable = out.m_bRectable;
|
|
m_bRelativeCoords = out.m_bRelativeCoords;
|
|
}
|
|
|
|
Status CBrushLinearGradient::GetLinearColors( CColor* colors ) const
|
|
{
|
|
if( !colors )
|
|
return InvalidParameter;
|
|
|
|
colors[0] = m_colors[0];
|
|
colors[1] = m_colors[1];
|
|
|
|
return Ok;
|
|
}
|
|
|
|
Status CBrushLinearGradient::GetRectangle( Rect *rect ) const
|
|
{
|
|
if( !rect )
|
|
return InvalidParameter;
|
|
|
|
rect->X = (int)( m_points[0].X );
|
|
rect->Y = (int)( m_points[0].Y );
|
|
rect->Width = (int)( m_points[1].X ) - rect->X;
|
|
rect->Height = (int)( m_points[1].Y ) - rect->Y;
|
|
|
|
return Ok;
|
|
}
|
|
|
|
Status CBrushLinearGradient::GetRectangle( RectF *rect ) const
|
|
{
|
|
if( !rect )
|
|
return InvalidParameter;
|
|
|
|
rect->X = m_points[0].X;
|
|
rect->Y = m_points[0].Y;
|
|
rect->Width = m_points[1].X - rect->X;
|
|
rect->Height = m_points[1].Y - rect->Y;
|
|
|
|
return Ok;
|
|
}
|
|
|
|
Status CBrushLinearGradient::GetTransform( CMatrix* matrix ) const
|
|
{
|
|
if( !matrix )
|
|
return InvalidParameter;
|
|
|
|
*matrix = m_matrix;
|
|
|
|
return Ok;
|
|
}
|
|
|
|
Status CBrushLinearGradient::MultiplyTransform( const CMatrix *matrix, MatrixOrder order)
|
|
{
|
|
if( !matrix )
|
|
return InvalidParameter;
|
|
|
|
m_matrix.Multiply( matrix, order );
|
|
|
|
return Ok;
|
|
}
|
|
|
|
Status CBrushLinearGradient::ResetTransform()
|
|
{
|
|
m_matrix.Reset();
|
|
|
|
return Ok;
|
|
}
|
|
|
|
Status CBrushLinearGradient::RotateTransform( REAL angle, MatrixOrder order )
|
|
{
|
|
m_matrix.Rotate( angle, order );
|
|
|
|
return Ok;
|
|
}
|
|
|
|
Status CBrushLinearGradient::ScaleTransform( REAL sx, REAL sy, MatrixOrder order )
|
|
{
|
|
m_matrix.Scale( sx, sy, order );
|
|
|
|
return Ok;
|
|
}
|
|
|
|
void CBrushLinearGradient::SetWrapMode( WrapMode mode )
|
|
{
|
|
m_wrap = mode;
|
|
}
|
|
|
|
WrapMode CBrushLinearGradient::GetWrapMode() const
|
|
{
|
|
return m_wrap;
|
|
}
|
|
|
|
CBrush* CBrushLinearGradient::Clone() const
|
|
{
|
|
return new CBrushLinearGradient( *this );
|
|
}
|
|
|
|
Status CBrushLinearGradient::SetInterpolationColors( const CColor *presetColors, const REAL *blendPositions, INT count )
|
|
{
|
|
m_subcolors.clear();
|
|
|
|
if( count > 0 && presetColors && blendPositions )
|
|
{
|
|
m_subcolors.resize( count );
|
|
|
|
for( int i = 0; i < count; i++ )
|
|
{
|
|
m_subcolors[i].color = presetColors[i];
|
|
m_subcolors[i].position = blendPositions[i];
|
|
}
|
|
}
|
|
|
|
return Ok;
|
|
}
|
|
|
|
Status CBrushLinearGradient::GetInterpolationColors( CColor *presetColors, REAL *blendPositions, INT count ) const
|
|
{
|
|
if( count > 0 && count <= (INT)m_subcolors.size() && presetColors && blendPositions )
|
|
{
|
|
for( int i = 0; i < count; i++ )
|
|
{
|
|
presetColors[i] = m_subcolors[i].color;
|
|
blendPositions[i] = m_subcolors[i].position;
|
|
}
|
|
}
|
|
|
|
return Ok;
|
|
}
|
|
|
|
INT CBrushLinearGradient::GetInterpolationColorsCount() const
|
|
{
|
|
return (INT)m_subcolors.size();
|
|
}
|
|
|
|
// additional methods
|
|
void CBrushLinearGradient::GetSubColor( int nIndex, CColor* pColor, float* pPosition ) const
|
|
{
|
|
*pColor = m_subcolors[nIndex].color;
|
|
*pPosition = m_subcolors[nIndex].position;
|
|
}
|
|
|
|
void CBrushLinearGradient::SetRelativeCoords( INT bRelative )
|
|
{
|
|
m_bRelativeCoords = bRelative;
|
|
}
|
|
INT CBrushLinearGradient::IsRelativeCoords() const
|
|
{
|
|
return m_bRelativeCoords;
|
|
}
|
|
|
|
INT CBrushLinearGradient::IsAngleScalable() const
|
|
{
|
|
return m_bAngleScalable;
|
|
}
|
|
INT CBrushLinearGradient::IsRectable() const
|
|
{
|
|
return m_bRectable;
|
|
}
|
|
float CBrushLinearGradient::GetAngle() const
|
|
{
|
|
return m_angle;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
CBrushTexture::CBrushTexture() : CBrush(BrushTypeTextureFill)
|
|
{
|
|
m_pImage = NULL;
|
|
m_bReleaseImage = FALSE;
|
|
Alpha = 255;
|
|
m_bUseBounds = false;
|
|
}
|
|
|
|
CBrushTexture::CBrushTexture(const std::wstring& strName, WrapMode wrapMode) : CBrush(BrushTypeTextureFill), m_wrapMode(wrapMode)
|
|
{
|
|
m_pImage = new CImage(strName);
|
|
m_bReleaseImage = TRUE;
|
|
Alpha = 255;
|
|
m_bUseBounds = false;
|
|
}
|
|
|
|
CBrushTexture::CBrushTexture(CImage *pImage, WrapMode wrapMode) : CBrush(BrushTypeTextureFill), m_wrapMode(wrapMode)
|
|
{
|
|
m_pImage = pImage;
|
|
m_bReleaseImage = FALSE;
|
|
Alpha = 255;
|
|
m_bUseBounds = false;
|
|
}
|
|
|
|
CBrushTexture::~CBrushTexture()
|
|
{
|
|
if (m_bReleaseImage)
|
|
{
|
|
RELEASEOBJECT(m_pImage);
|
|
}
|
|
}
|
|
|
|
CBrush* CBrushTexture::Clone() const
|
|
{
|
|
CBrushTexture *pRet = new CBrushTexture(m_pImage, m_wrapMode);
|
|
if( pRet )
|
|
{
|
|
pRet->m_mtx = m_mtx;
|
|
}
|
|
|
|
return pRet;
|
|
}
|
|
|
|
void CBrushTexture::TranslateTransform(double dX, double dY, MatrixOrder order)
|
|
{
|
|
m_mtx.Translate(dX, dY, order);
|
|
}
|
|
void CBrushTexture::ScaleTransform(double dX, double dY, MatrixOrder order)
|
|
{
|
|
m_mtx.Scale(dX, dY, order);
|
|
}
|
|
void CBrushTexture::RotateTransform(double angle, MatrixOrder order)
|
|
{
|
|
m_mtx.Rotate(angle, order);
|
|
}
|
|
void CBrushTexture::GetTransform(CMatrix* matrix) const
|
|
{
|
|
*matrix = m_mtx;
|
|
}
|
|
void CBrushTexture::SetTransform(const CMatrix* matrix)
|
|
{
|
|
m_mtx = *matrix;
|
|
}
|
|
|
|
void CBrushTexture::SetWrapMode(WrapMode wMode)
|
|
{
|
|
m_wrapMode = wMode;
|
|
}
|
|
WrapMode CBrushTexture::GetWrapMode() const
|
|
{
|
|
return(m_wrapMode);
|
|
}
|
|
|
|
void* CBrushTexture::GetData()
|
|
{
|
|
return m_pImage->m_pImgData;
|
|
}
|
|
void* CBrushTexture::PatternFinalize()
|
|
{
|
|
if (m_pImage->m_nStride < 0)
|
|
return m_pImage->m_pImgData - ((m_pImage->m_dwHeight - 1) * m_pImage->m_nStride);
|
|
return m_pImage->m_pImgData;
|
|
}
|
|
DWORD CBrushTexture::PatternGetWidth()
|
|
{
|
|
return m_pImage->m_dwWidth;
|
|
}
|
|
DWORD CBrushTexture::PatternGetHeight()
|
|
{
|
|
return m_pImage->m_dwHeight;
|
|
}
|
|
int CBrushTexture::PatternGetStride()
|
|
{
|
|
return m_pImage->m_nStride;
|
|
}
|
|
}
|