Compare commits

...

4 Commits

Author SHA1 Message Date
c22407d445 Fix CGraphicsPath 2025-05-12 19:19:38 +03:00
f80c07e275 Rollback 2025-05-12 18:35:39 +03:00
748def3c76 Add comments 2025-04-29 10:10:12 +03:00
7f173e2013 Refactoring CClip 2025-04-28 14:14:48 +03:00
4 changed files with 158 additions and 336 deletions

View File

@ -33,164 +33,22 @@
namespace Aggplus
{
/////////////////////////////////////////////////////////////////////////////////////
CClipMask::CClipMask() : m_pixf(m_alpha_rbuf)
{
m_pMask = NULL;
m_bIsClip = false;
m_lWidth = 0;
m_lHeight = 0;
}
CClipMask::~CClipMask()
{
Destroy();
}
void CClipMask::Destroy()
{
if (NULL != m_pMask)
delete [] m_pMask;
}
void CClipMask::Reset()
{
m_bIsClip = false;
}
void CClipMask::Create(LONG width, LONG height)
{
Destroy();
m_pMask = new BYTE[width * height];
m_alpha_rbuf.attach(m_pMask, width, height, width);
m_lWidth = width;
m_lHeight = height;
m_pixf.attach(m_alpha_rbuf);
m_base_renderer.attach(m_pixf);
m_renderer.attach(m_base_renderer);
m_renderer.color(agg::gray8(0xFF, 0xFF));
}
void CClipMask::ResetClip()
{
}
void CClipMask::GenerateClip(CGraphicsPath* pPath, CMatrix* pMatrix)
{
if (NULL == pPath)
return;
memset(m_pMask, 0, m_lWidth * m_lHeight);
m_rasterizer.reset();
typedef agg::conv_transform<agg::path_storage> trans_type;
trans_type trans(pPath->m_internal->m_agg_ps, pMatrix->m_internal->m_agg_mtx);
typedef agg::conv_curve<trans_type> conv_crv_type;
conv_crv_type c_c_path(trans);
m_rasterizer.add_path(c_c_path);
agg::render_scanlines(m_rasterizer, m_sl, m_renderer);
m_bIsClip = true;
}
agg::rendering_buffer CClipMask::GetRenderingBuffer()
{
return m_alpha_rbuf;
}
BYTE* CClipMask::GetMask()
{
return m_pMask;
}
bool CClipMask::IsClip()
{
return m_bIsClip;
}
/////////////////////////////////////////////////////////////////////////////////////
CClip::CClip() : m_pixf(m_alpha_rbuf)
{
m_pMask = NULL;
m_bIsClip = false;
m_lWidth = 0;
m_lHeight = 0;
}
CClip::~CClip()
{
Destroy();
}
void CClip::Destroy()
{
if (NULL != m_pMask)
delete [] m_pMask;
}
void CClip::Reset()
{
m_bIsClip = false;
}
void CClip::Create(LONG width, LONG height)
{
}
void CClip::ResetClip()
{
}
void CClip::GenerateClip(CGraphicsPath* pPath, CMatrix* pMatrix)
{
if (NULL == pPath)
return;
m_rasterizer.reset();
typedef agg::conv_transform<agg::path_storage> trans_type;
trans_type trans(pPath->m_internal->m_agg_ps, pMatrix->m_internal->m_agg_mtx);
typedef agg::conv_curve<trans_type> conv_crv_type;
conv_crv_type c_c_path(trans);
m_rasterizer.add_path(c_c_path);
m_bIsClip = true;
}
agg::rendering_buffer CClip::GetRenderingBuffer()
{
return m_alpha_rbuf;
}
BYTE* CClip::GetMask()
{
return m_pMask;
}
bool CClip::IsClip()
{
return m_bIsClip;
}
/////////////////////////////////////////////////////////////////////////////////////
CClipMulti::CClipMulti()
{
m_bIsClip = false;
m_bIsClip2 = false;
}
CClipMulti::~CClipMulti()
{
}
/**
* @brief CClipMulti::GetRasterizer
*
* @return Ponter to new rasterizer if there was no
* clip yet, otherwise - nullptr
*/
CClipMulti::clip_rasterizer* CClipMulti::GetRasterizer()
{
if (!m_bIsClip)
@ -198,7 +56,8 @@ namespace Aggplus
m_rasterizer.reset();
return &m_rasterizer;
}
return NULL;
return nullptr;
}
void CClipMulti::Create(LONG width, LONG height)
@ -210,9 +69,16 @@ namespace Aggplus
m_bIsClip2 = false;
}
/**
* @brief CClipMulti::GenerateClip
* @param pPath - vector graphics path for clip
* @param pMatrix - transform matrix
*
* Create new rasterizer from path with transform maatrix and start clip.
*/
void CClipMulti::GenerateClip(CGraphicsPath* pPath, CMatrix* pMatrix)
{
if (NULL == pPath)
if (pPath == nullptr)
return;
m_rasterizer.reset();
@ -228,6 +94,12 @@ namespace Aggplus
GenerateClip2(pPath->m_internal->m_bEvenOdd);
}
/**
* @brief CClipMulti::GenerateClip2
* @param bEvenOdd - fill mode
*
* Set fill mode and start clip 1.
*/
void CClipMulti::GenerateClip2(bool bEvenOdd)
{
m_rasterizer.filling_rule(bEvenOdd ? agg::fill_even_odd : agg::fill_non_zero);
@ -236,6 +108,16 @@ namespace Aggplus
m_bIsClip2 = false;
}
/**
* @brief CClipMulti::Combine
* @param bEvenOdd - fill mode
* @param op - boolean operation
* @param pRasterizer - another rasterizer for clip
*
* Performs the boolean operation. If there is no clip - create it.
* If the first paart of the clip, execute it in storage. Perform
* the second clip with storage.
*/
void CClipMulti::Combine(bool bEvenOdd, agg::sbool_op_e op, clip_rasterizer* pRasterizer)
{
if (!pRasterizer)
@ -246,10 +128,9 @@ namespace Aggplus
if (!m_bIsClip2)
{
// смешивать надо с растерайзером
pRasterizer->filling_rule(bEvenOdd ? agg::fill_even_odd : agg::fill_non_zero);
scanline_type sl1;
scanline_type sl1;
scanline_type sl2;
scanline_type sl;
@ -259,36 +140,29 @@ namespace Aggplus
}
else
{
// надо смешивать со стораджем
pRasterizer->filling_rule(op ? agg::fill_even_odd : agg::fill_non_zero);
scanline_type sl1;
scanline_type sl1;
scanline_type sl2;
scanline_type sl;
scanline_type sl;
agg::sbool_combine_shapes_aa(op, *pRasterizer, (m_lCurStorage == 1) ? m_storage1 : m_storage2, sl1, sl2, sl,
(m_lCurStorage == 1) ? m_storage2 : m_storage1);
(m_lCurStorage == 1) ? m_storage2 : m_storage1);
if (1 == m_lCurStorage)
{
//m_storage1.prepare();
m_lCurStorage = 2;
}
else
{
//m_storage2.prepare();
m_lCurStorage = 1;
}
}
m_bIsClip2 = true;
}
bool CClipMulti::IsClip()
bool CClipMulti::IsClip() const
{
return m_bIsClip;
}
bool CClipMulti::IsClip2()
bool CClipMulti::IsClip2() const
{
return m_bIsClip2;
}
@ -296,10 +170,6 @@ namespace Aggplus
void CClipMulti::Reset()
{
m_rasterizer.reset();
//m_storage1.prepare();
//m_storage2.prepare();
m_bIsClip = false;
m_bIsClip2 = false;
}

View File

@ -54,96 +54,28 @@
namespace Aggplus
{
class CClipMask
{
typedef agg::renderer_base<agg::pixfmt_gray8> ren_base;
typedef agg::renderer_scanline_aa_solid<ren_base> renderer;
friend class CGraphicsPath;
public:
BYTE* m_pMask;
LONG m_lWidth;
LONG m_lHeight;
agg::rendering_buffer m_alpha_rbuf;
agg::rasterizer_scanline_aa<agg::rasterizer_sl_clip_dbl> m_rasterizer;
agg::pixfmt_gray8 m_pixf;
ren_base m_base_renderer;
renderer m_renderer;
agg::scanline_p8 m_sl;
bool m_bIsClip;
public:
CClipMask();
~CClipMask();
void Destroy();
void Reset();
public:
void Create(LONG width, LONG height);
void ResetClip();
void GenerateClip(CGraphicsPath* pPath, CMatrix* pMatrix);
agg::rendering_buffer GetRenderingBuffer();
BYTE* GetMask();
bool IsClip();
};
class CClip
{
typedef agg::renderer_base<agg::pixfmt_gray8> ren_base;
typedef agg::renderer_scanline_aa_solid<ren_base> renderer;
friend class CGraphicsPath;
public:
BYTE* m_pMask;
LONG m_lWidth;
LONG m_lHeight;
agg::rendering_buffer m_alpha_rbuf;
agg::rasterizer_scanline_aa<agg::rasterizer_sl_clip_dbl> m_rasterizer;
agg::pixfmt_gray8 m_pixf;
ren_base m_base_renderer;
renderer m_renderer;
agg::scanline_p8 m_sl;
bool m_bIsClip;
public:
CClip();
~CClip();
void Destroy();
void Reset();
public:
void Create(LONG width, LONG height);
void ResetClip();
void GenerateClip(CGraphicsPath* pPath, CMatrix* pMatrix);
agg::rendering_buffer GetRenderingBuffer();
BYTE* GetMask();
bool IsClip();
};
/**
* @class CClipMulti
* @brief Class providing boolean logic
* for a raster graphics clip.
*
* Boolean algebra for rasterizer scanlines, which are
* received from CGraphicsPath.
*/
class CClipMulti
{
public:
typedef agg::scanline_p8 scanline_type;
typedef agg::rasterizer_scanline_aa<agg::rasterizer_sl_clip_dbl> clip_rasterizer;
typedef agg::rasterizer_scanline_aa<agg::rasterizer_sl_clip_dbl> clip_rasterizer;
clip_rasterizer m_rasterizer;
/**
* @brief Interfaces for implementation graphics renderer scanlines.
*
* Scan lines can be stored in rasterizer as in case clip1
* or in storage otherwise(clip2).
*/
agg::scanline_storage_aa8 m_storage1;
agg::scanline_storage_aa8 m_storage2;
@ -167,8 +99,8 @@ public:
void Combine(bool bEvenOdd, agg::sbool_op_e op, clip_rasterizer* pRasterizer);
bool IsClip();
bool IsClip2();
bool IsClip() const;
bool IsClip2() const;
void Reset();
};

View File

@ -57,7 +57,6 @@ namespace Aggplus
*this = paths[0];
else
{
StartFigure();
for (const auto& p : paths)
{
unsigned length = p.GetPointCount();
@ -76,6 +75,7 @@ namespace Aggplus
j += 2;
}
}
//AddPath(p);
if (p.Is_poly_closed()) CloseFigure();
}
}
@ -139,11 +139,13 @@ namespace Aggplus
m_internal->m_agg_ps.move_to(x, y);
return Ok;
}
Status CGraphicsPath::LineTo(double x, double y)
{
m_internal->m_agg_ps.line_to(x, y);
return Ok;
}
Status CGraphicsPath::CurveTo(double x1, double y1, double x2, double y2, double x3, double y3)
{
m_internal->m_agg_ps.curve4(x1, y1, x2, y2, x3, y3);
@ -152,17 +154,17 @@ namespace Aggplus
Status CGraphicsPath::AddLine(double x1, double y1, double x2, double y2)
{
if (Is_poly_closed())
{
m_internal->m_agg_ps.move_to(x1, y1);
}
else
{
m_internal->m_agg_ps.line_to(x1, y1);
}
if (Is_poly_closed())
{
m_internal->m_agg_ps.move_to(x1, y1);
}
else
{
m_internal->m_agg_ps.line_to(x1, y1);
}
m_internal->m_agg_ps.line_to(x2, y2);
return Ok;
m_internal->m_agg_ps.line_to(x2, y2);
return Ok;
}
Status CGraphicsPath::AddLines(double* pPoints, int nCount)
@ -171,22 +173,12 @@ namespace Aggplus
{
return InvalidParameter;
}
int nRet = 0;
if (!m_internal->m_bIsMoveTo)
{
MoveTo(pPoints[0], pPoints[1]);
}
/*if (Is_poly_closed())
{
m_agg_ps.move_to((double)pPoints[0], (double)pPoints[1]);
}
else
{
m_agg_ps.line_to((double)pPoints[0], (double)pPoints[1]);
}*/
int n = (nCount / 2) - 1;
for (int i = 1; i <= n; ++i)
@ -194,6 +186,7 @@ namespace Aggplus
const double* points = &pPoints[i * 2];
m_internal->m_agg_ps.line_to(points[0], points[1]);
}
return Ok;
}
@ -207,6 +200,7 @@ namespace Aggplus
m_internal->m_agg_ps.curve4(x2, y2, x3, y3, x4, y4);
return Ok;
}
Status CGraphicsPath::AddBeziers(double* pPoints, int nCount)
{
if (8 > nCount)
@ -256,22 +250,24 @@ namespace Aggplus
m_internal->m_agg_ps.join_path(arc, 0);
return Ok;
}
Status CGraphicsPath::AddRectangle(double x, double y, double width, double height)
{
m_internal->m_agg_ps.move_to(x, y);
m_internal->m_agg_ps.line_to(x + width, y);
m_internal->m_agg_ps.line_to(x + width, y + height);
m_internal->m_agg_ps.line_to(x, y + height);
m_internal->m_agg_ps.line_to(x, y);
m_internal->m_agg_ps.close_polygon();
return Ok;
}
Status CGraphicsPath::AddPolygon(double* pPoints, int nCount)
{
if (2 > nCount)
{
return InvalidParameter;
}
int nRet = 0;
if (Is_poly_closed())
{
@ -293,6 +289,7 @@ namespace Aggplus
m_internal->m_agg_ps.close_polygon();
return Ok;
}
Status CGraphicsPath::AddPath(const CGraphicsPath& oPath)
{
typedef agg::conv_curve<agg::path_storage> conv_crv_type;
@ -303,6 +300,7 @@ namespace Aggplus
m_internal->m_agg_ps.join_path(p3, 0);
return Ok;
}
Status CGraphicsPath::AddArc(double x, double y, double width, double height, double startAngle, double sweepAngle)
{
if(sweepAngle >= 360.0)
@ -470,6 +468,7 @@ namespace Aggplus
}
return (Ok == MoveTo(x, y));
}
bool CGraphicsPath::_LineTo(double x, double y)
{
if (NULL != m_internal->m_pTransform)
@ -478,6 +477,7 @@ namespace Aggplus
}
return (Ok == LineTo(x, y));
}
bool CGraphicsPath::_CurveTo(double x1, double y1, double x2, double y2, double x3, double y3)
{
if (NULL != m_internal->m_pTransform)
@ -488,6 +488,7 @@ namespace Aggplus
}
return (Ok == CurveTo(x1, y1, x2, y2, x3, y3));
}
bool CGraphicsPath::_Close()
{
return (Ok == CloseFigure());
@ -502,6 +503,7 @@ namespace Aggplus
pFont->LoadString1(strText, (float)x, (float)y);
return (TRUE == pFont->GetStringPath(this)) ? Ok : InvalidParameter;
}
Status CGraphicsPath::AddString(const unsigned int* pGids, const unsigned int nGidsCount, NSFonts::IFontManager* pFont, double x, double y)
{
if (NULL == pFont)
@ -580,40 +582,40 @@ namespace Aggplus
m_internal->m_agg_ps = psNew;
}
int CGraphicsPath::EllipseArc(double fX, double fY, double fXRad, double fYRad, double fAngle1, double fAngle2, INT bClockDirection)
int CGraphicsPath::EllipseArc(double fX, double fY, double fXRad, double fYRad, double fAngle1, double fAngle2, bool bClockDirection)
{
int nRet = 0;
while ( fAngle1 < 0 )
while (fAngle1 < 0)
fAngle1 += 360;
while ( fAngle1 > 360 )
while (fAngle1 > 360)
fAngle1 -= 360;
while ( fAngle2 < 0 )
while (fAngle2 < 0)
fAngle2 += 360;
while ( fAngle2 >= 360 )
while (fAngle2 >= 360)
fAngle2 -= 360;
if ( !bClockDirection )
if (!bClockDirection)
{
if ( fAngle1 <= fAngle2 )
nRet = EllipseArc2( fX, fY, fXRad, fYRad, fAngle1, fAngle2, FALSE );
if (fAngle1 <= fAngle2)
nRet = EllipseArc2(fX, fY, fXRad, fYRad, fAngle1, fAngle2, false);
else
{
nRet += EllipseArc2( fX, fY, fXRad, fYRad, fAngle1, 360, FALSE );
nRet += EllipseArc2( fX, fY, fXRad, fYRad, 0, fAngle2, FALSE );
nRet += EllipseArc2(fX, fY, fXRad, fYRad, fAngle1, 360, false);
nRet += EllipseArc2(fX, fY, fXRad, fYRad, 0, fAngle2, false);
}
}
else
{
if ( fAngle1 >= fAngle2 )
nRet = EllipseArc2( fX, fY, fXRad, fYRad, fAngle1, fAngle2, TRUE );
if (fAngle1 >= fAngle2)
nRet = EllipseArc2(fX, fY, fXRad, fYRad, fAngle1, fAngle2, true);
else
{
nRet += EllipseArc2( fX, fY, fXRad, fYRad, fAngle1, 0, TRUE );
nRet += EllipseArc2( fX, fY, fXRad, fYRad, 360, fAngle2, TRUE );
nRet += EllipseArc2(fX, fY, fXRad, fYRad, fAngle1, 0, true);
nRet += EllipseArc2(fX, fY, fXRad, fYRad, 360, fAngle2, true);
}
}
return nRet;
@ -624,10 +626,10 @@ namespace Aggplus
// Функция для перевода реального угла в параметрическое задание эллписа
// т.е. x= a cos(t) y = b sin(t) - параметрическое задание эллписа.
// x = r cos(p), y = r sin(p) => t = atan2( sin(p) / b, cos(p) / a );
return atan2( sin( fAngle ) / fYRad, cos( fAngle ) / fXRad );
return atan2(sin(fAngle) / fYRad, cos(fAngle) / fXRad);
}
int CGraphicsPath::EllipseArc2(double fX, double fY, double fXRad, double fYRad, double fAngle1, double fAngle2, INT bClockDirection)
int CGraphicsPath::EllipseArc2(double fX, double fY, double fXRad, double fYRad, double fAngle1, double fAngle2, bool bClockDirection)
{
// переведем углы в радианы
int nRet = 0;
@ -638,79 +640,75 @@ namespace Aggplus
// Выясним в каких четвертях находятся начальная и конечная точки
unsigned int nFirstPointQuard = int(fAngle1) / 90 + 1;
unsigned int nSecondPointQuard = int(fAngle2) / 90 + 1;
nSecondPointQuard = std::min( 4, std::max( 1, (int)nSecondPointQuard ) );
nFirstPointQuard = std::min( 4, std::max( 1, (int)nFirstPointQuard ) );
nSecondPointQuard = std::min(4, std::max(1, (int)nSecondPointQuard));
nFirstPointQuard = std::min(4, std::max(1, (int)nFirstPointQuard));
// Проведем линию в начальную точку дуги
double fStartX = 0.0, fStartY = 0.0, fEndX = 0.0, fEndY = 0.0;
fStartX = fX + fXRad * cos( AngToEllPrm( dAngle1, fXRad, fYRad ) );
fStartY = fY + fYRad * sin( AngToEllPrm( dAngle1, fXRad, fYRad ) );
fStartX = fX + fXRad * cos(AngToEllPrm(dAngle1, fXRad, fYRad));
fStartY = fY + fYRad * sin(AngToEllPrm(dAngle1, fXRad, fYRad));
LineTo(fStartX, fStartY);
// Дальше рисуем по четверям
double fCurX = fStartX, fCurY = fStartY;
double dStartAngle = dAngle1;
double dEndAngle = 0;
if ( !bClockDirection )
if (!bClockDirection)
{
for( unsigned int nIndex = nFirstPointQuard; nIndex <= nSecondPointQuard; nIndex++ )
for(unsigned int nIndex = nFirstPointQuard; nIndex <= nSecondPointQuard; nIndex++)
{
if ( nIndex == nSecondPointQuard )
if (nIndex == nSecondPointQuard)
dEndAngle = dAngle2;
else
dEndAngle = (90 * (nIndex ) ) * 3.141592f / 180;
if ( !( nIndex == nFirstPointQuard ) )
dStartAngle = (90 * (nIndex - 1 ) ) * 3.141592f / 180;
dEndAngle = (90 * nIndex) * 3.141592f / 180;
if (!( nIndex == nFirstPointQuard))
dStartAngle = (90 * (nIndex - 1)) * 3.141592f / 180;
EllipseArc3(fX, fY, fXRad, fYRad, AngToEllPrm( dStartAngle, fXRad, fYRad ), AngToEllPrm( dEndAngle, fXRad, fYRad ), &fEndX, &fEndY, FALSE);
EllipseArc3(fX, fY, fXRad, fYRad, AngToEllPrm(dStartAngle, fXRad, fYRad), AngToEllPrm(dEndAngle, fXRad, fYRad), &fEndX, &fEndY, false);
}
}
else
{
for( unsigned int nIndex = nFirstPointQuard; nIndex >= nSecondPointQuard; nIndex-- )
for(unsigned int nIndex = nFirstPointQuard; nIndex >= nSecondPointQuard; nIndex--)
{
if ( nIndex == nFirstPointQuard )
if (nIndex == nFirstPointQuard)
dStartAngle = dAngle1;
else
dStartAngle = (90 * (nIndex ) ) * 3.141592f / 180;
if ( !( nIndex == nSecondPointQuard ) )
dEndAngle = (90 * (nIndex - 1 ) ) * 3.141592f / 180;
dStartAngle = (90 * nIndex) * 3.141592f / 180;
if (!( nIndex == nSecondPointQuard))
dEndAngle = (90 * (nIndex - 1)) * 3.141592f / 180;
else
dEndAngle = dAngle2;
EllipseArc3(fX, fY, fXRad, fYRad, AngToEllPrm( dStartAngle, fXRad, fYRad ), AngToEllPrm( dEndAngle, fXRad, fYRad ), &fEndX, &fEndY, FALSE);
EllipseArc3(fX, fY, fXRad, fYRad, AngToEllPrm(dStartAngle, fXRad, fYRad), AngToEllPrm(dEndAngle, fXRad, fYRad), &fEndX, &fEndY, false);
}
}
return nRet;
}
int CGraphicsPath::EllipseArc3(double fX, double fY, double fXRad, double fYRad, double dAngle1, double dAngle2, double *pfXCur, double *pfYCur, INT bClockDirection)
int CGraphicsPath::EllipseArc3(double fX, double fY, double fXRad, double fYRad, double dAngle1, double dAngle2, double *pfXCur, double *pfYCur, bool bClockDirection)
{
// Рассчитаем начальную, конечную и контрольные точки
double fX1 = 0.0, fX2 = 0.0, fY1 = 0.0, fY2 = 0.0;
double fCX1 = 0.0, fCX2 = 0.0, fCY1 = 0.0, fCY2 = 0.0;
double fAlpha = sin( dAngle2 - dAngle1 ) * ( sqrt( 4.0 + 3.0 * tan( (dAngle2 - dAngle1) / 2.0 ) * tan( (dAngle2 - dAngle1) / 2.0 ) ) - 1.0 ) / 3.0;
double fAlpha = sin(dAngle2 - dAngle1) * (sqrt( 4.0 + 3.0 * tan((dAngle2 - dAngle1) / 2.0) * tan((dAngle2 - dAngle1) / 2.0 )) - 1.0 ) / 3.0;
double fKoef = 1;
fX1 = fX + fXRad * cos(dAngle1);
fY1 = fY + fYRad * sin(dAngle1);
fX1 = fX + fXRad * cos( dAngle1 );
fY1 = fY + fYRad * sin( dAngle1 );
fX2 = fX + fXRad * cos(dAngle2);
fY2 = fY + fYRad * sin(dAngle2);
fX2 = fX + fXRad * cos( dAngle2 );
fY2 = fY + fYRad * sin( dAngle2 );
fCX1 = fX1 - fAlpha * fXRad * sin (dAngle1);
fCY1 = fY1 + fAlpha * fYRad * cos (dAngle1);
fCX1 = fX1 - fAlpha * fXRad * sin ( dAngle1 );
fCY1 = fY1 + fAlpha * fYRad * cos ( dAngle1 );
fCX2 = fX2 + fAlpha * fXRad * sin (dAngle2);
fCY2 = fY2 - fAlpha * fYRad * cos (dAngle2);
fCX2 = fX2 + fAlpha * fXRad * sin ( dAngle2 );
fCY2 = fY2 - fAlpha * fYRad * cos ( dAngle2 );
if ( !bClockDirection )
if (!bClockDirection)
{
CurveTo(fCX1, fCY1, fCX2, fCY2, fX2, fY2);
@ -1043,8 +1041,6 @@ namespace Aggplus
return false;
}
int nRet = 0;
if (!m_internal->m_bIsMoveTo)
{
_MoveTo(pData[0], pData[1]);
@ -1373,8 +1369,6 @@ namespace Aggplus
_LineTo(fStartX, fStartY);
// Дальше рисуем по четверям
double fCurX = fStartX, fCurY = fStartY;
double dStartAngle = dAngle1;
double dEndAngle = 0;
@ -1420,8 +1414,6 @@ namespace Aggplus
double fAlpha = sin( dAngle2 - dAngle1 ) * ( sqrt( 4.0 + 3.0 * tan( (dAngle2 - dAngle1) / 2.0 ) * tan( (dAngle2 - dAngle1) / 2.0 ) ) - 1.0 ) / 3.0;
double fKoef = 1;
fX1 = fX + fXRad * cos( dAngle1 );
fY1 = fY + fYRad * sin( dAngle1 );

View File

@ -42,6 +42,11 @@
namespace Aggplus
{
/**
* @class CGraphicsPath
*
* A container class that implements the logic of graphic paths.
*/
class CGraphicsPath_private;
class GRAPHICS_DECL CGraphicsPath : public NSFonts::ISimpleGraphicsPath
{
@ -57,6 +62,9 @@ namespace Aggplus
Status Reset();
void SetRuler(bool bEvenOdd);
/**
* @brief Methods implementing basic path commands.
*/
Status StartFigure();
Status CloseFigure();
bool Is_poly_closed() const;
@ -64,7 +72,10 @@ namespace Aggplus
Status LineTo(double x, double y);
Status CurveTo(double x1, double y1, double x2, double y2, double x3, double y3);
// методы, которые просто будем сводить к трем основным
/**
* @brief Methods implementing additional commands for
* more convenient creation of path.
*/
Status AddLine(double x1, double y1, double x2, double y2);
Status AddLines(double* pPoints, int nCount);
Status AddBezier(double x1, double y1, double x2, double y2, double x3, double y3, double x4, double y4);
@ -76,6 +87,9 @@ namespace Aggplus
Status AddPath(const CGraphicsPath& oPath);
Status AddArc(double x, double y, double width, double height, double startAngle, double sweepAngle);
/**
* @brief Getter methods.
*/
ULONG GetPointCount() const;
Status GetPathPoints(PointF* points, int count) const;
Status GetLastPoint(double& x, double& y);
@ -83,27 +97,41 @@ namespace Aggplus
void GetBounds(double& left, double& top, double& width, double& height) const;
void GetBoundsAccurate(double& left, double& top, double& width, double& height) const;
/**
* @brief Methods implementing baasic path commands using
* a transformation matrix to points.
*/
Status Transform(const CMatrix* matrix);
virtual bool _MoveTo(double x, double y);
virtual bool _LineTo(double x, double y);
virtual bool _CurveTo(double x1, double y1, double x2, double y2, double x3, double y3);
virtual bool _Close();
/**
* @brief Methods for adding paths for text in Font manager.
*/
Status AddString(const std::wstring& strText, NSFonts::IFontManager* pFont, double x, double y);
Status AddString(const unsigned int* pGids, const unsigned int nGidsCount, NSFonts::IFontManager* pFont, double x, double y);
Status AddStringC(const LONG& lText, NSFonts::IFontManager* pFont, double x, double y);
void z_Stroke(const double& size);
void Widen(const double& size, const Aggplus::LineJoin& join, const CMatrix* matrix, float flatness);
int EllipseArc(double fX, double fY, double fXRad, double fYRad, double fAngle1, double fAngle2, INT bClockDirection);
/**
* @brief Methods implementing commands for creating arcs
* (simple versions of Bezier curves).
*/
int EllipseArc(double fX, double fY, double fXRad, double fYRad, double fAngle1, double fAngle2, bool bClockDirection);
double AngToEllPrm(double fAngle, double fXRad, double fYRad);
int EllipseArc2(double fX, double fY, double fXRad, double fYRad, double fAngle1, double fAngle2, INT bClockDirection);
int EllipseArc3(double fX, double fY, double fXRad, double fYRad, double dAngle1, double dAngle2, double* pfXCur, double* pfYCur, INT bClockDirection = FALSE);
int EllipseArc2(double fX, double fY, double fXRad, double fYRad, double fAngle1, double fAngle2, bool bClockDirection);
int EllipseArc3(double fX, double fY, double fXRad, double fYRad, double dAngle1, double dAngle2, double* pfXCur, double* pfYCur, bool bClockDirection = false);
int Ellipse(double fX, double fY, double fXRad, double fYRad);
Status AddArc2(double fX, double fY, double fWidth, double fHeight, double fStartAngle, double fSweepAngle);
bool IsPointInPath(const double& x, const double& y);
// Methods for Path Clip
/**
* @brief Methods that are used when performing Boolean operations
* on paths.
*/
unsigned GetCloseCount() const noexcept;
unsigned GetMoveCount() const noexcept;
bool IsClockwise() const noexcept;