286 lines
7.5 KiB
C++
286 lines
7.5 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 "FontPath.h"
|
|
|
|
//-------------------------------------------------------------------------------------------------------------------------------
|
|
// CPath
|
|
//-------------------------------------------------------------------------------------------------------------------------------
|
|
|
|
// Path может быть в одном из трех следующий состояний:
|
|
//
|
|
// 1. Нет текущей точки -- ни одного или более законченных SubPaths
|
|
// [m_nCurSubpath == m_nPointsCount]
|
|
//
|
|
// 2. Одна точка в SubPaths
|
|
// [m_nCurSubpath == m_nPointsCount - 1]
|
|
//
|
|
// 3. Открытый SubPaths c двумя или более точками
|
|
// [m_nCurSubpath < m_nPointsCount - 1]
|
|
|
|
CFontPath::CFontPath() : NSFonts::IFontPath()
|
|
{
|
|
m_pPoints = NULL;
|
|
m_pFlags = NULL;
|
|
m_nPointsCount = m_nSize = 0;
|
|
m_nCurSubpath = 0;
|
|
|
|
m_pHints = NULL;
|
|
m_nHintsCount = m_nHintsSize = 0;
|
|
}
|
|
|
|
CFontPath::CFontPath(CFontPath *pPath) : NSFonts::IFontPath()
|
|
{
|
|
m_nPointsCount = pPath->m_nPointsCount;
|
|
m_nSize = pPath->m_nSize;
|
|
m_pPoints = (TPathPoint *)malloc( m_nSize * sizeof(TPathPoint) );
|
|
m_pFlags = (unsigned char *)malloc( m_nSize * sizeof(unsigned char) );
|
|
|
|
memcpy( m_pPoints, pPath->m_pPoints, m_nPointsCount * sizeof(TPathPoint) );
|
|
memcpy( m_pFlags, pPath->m_pFlags, m_nPointsCount * sizeof(unsigned char) );
|
|
|
|
m_nCurSubpath = pPath->m_nCurSubpath;
|
|
|
|
if ( pPath->m_pHints )
|
|
{
|
|
m_nHintsCount = m_nHintsSize = pPath->m_nHintsCount;
|
|
m_pHints = (TPathHint *)malloc( m_nHintsSize * sizeof(TPathHint) );
|
|
memcpy( m_pHints, pPath->m_pHints, m_nHintsCount * sizeof(TPathHint) );
|
|
}
|
|
else
|
|
{
|
|
m_pHints = NULL;
|
|
}
|
|
}
|
|
|
|
CFontPath::~CFontPath()
|
|
{
|
|
free( m_pPoints );
|
|
free( m_pFlags );
|
|
free( m_pHints );
|
|
}
|
|
|
|
void CFontPath::Resize(int nPointsCount)
|
|
{
|
|
if ( m_nPointsCount + nPointsCount > m_nSize )
|
|
{
|
|
if ( m_nSize == 0 )
|
|
{
|
|
m_nSize = 32;
|
|
}
|
|
while ( m_nSize < m_nPointsCount + nPointsCount )
|
|
{
|
|
m_nSize *= 2;
|
|
}
|
|
m_pPoints = (TPathPoint *)realloc( m_pPoints, m_nSize * sizeof(TPathPoint) );
|
|
m_pFlags = (unsigned char *)realloc( m_pFlags, m_nSize * sizeof(unsigned char) );
|
|
}
|
|
}
|
|
|
|
void CFontPath::Append(CFontPath *pPath)
|
|
{
|
|
m_nCurSubpath = m_nPointsCount + pPath->m_nCurSubpath;
|
|
Resize( pPath->m_nPointsCount );
|
|
|
|
for ( int nIndex = 0; nIndex < pPath->m_nPointsCount; ++nIndex )
|
|
{
|
|
m_pPoints[m_nPointsCount] = pPath->m_pPoints[nIndex];
|
|
m_pFlags[m_nPointsCount] = pPath->m_pFlags[nIndex];
|
|
++m_nPointsCount;
|
|
}
|
|
}
|
|
|
|
int CFontPath::MoveTo(double dX, double dY)
|
|
{
|
|
if ( OnePointSubpath() )
|
|
{
|
|
return -1;
|
|
}
|
|
Resize(1);
|
|
m_pPoints[m_nPointsCount].dX = dX;
|
|
m_pPoints[m_nPointsCount].dY = dY;
|
|
m_pFlags[m_nPointsCount] = PathFirst | PathLast;
|
|
m_nCurSubpath = m_nPointsCount++;
|
|
|
|
return 0;
|
|
}
|
|
|
|
int CFontPath::LineTo(double dX, double dY)
|
|
{
|
|
if ( NoCurrentPoint() )
|
|
{
|
|
return -1;
|
|
}
|
|
m_pFlags[m_nPointsCount - 1] &= ~PathLast;
|
|
Resize(1);
|
|
|
|
m_pPoints[m_nPointsCount].dX = dX;
|
|
m_pPoints[m_nPointsCount].dY = dY;
|
|
m_pFlags[m_nPointsCount] = PathLast;
|
|
++m_nPointsCount;
|
|
|
|
return 0;
|
|
}
|
|
|
|
int CFontPath::CurveTo(double dX1, double dY1, double dX2, double dY2, double dX3, double dY3)
|
|
{
|
|
if ( NoCurrentPoint() )
|
|
{
|
|
return -1;
|
|
}
|
|
|
|
m_pFlags[m_nPointsCount-1] &= ~PathLast;
|
|
Resize(3);
|
|
|
|
m_pPoints[m_nPointsCount].dX = dX1;
|
|
m_pPoints[m_nPointsCount].dY = dY1;
|
|
m_pFlags[m_nPointsCount] = PathCurve;
|
|
++m_nPointsCount;
|
|
|
|
m_pPoints[m_nPointsCount].dX = dX2;
|
|
m_pPoints[m_nPointsCount].dY = dY2;
|
|
m_pFlags[m_nPointsCount] = PathCurve;
|
|
++m_nPointsCount;
|
|
|
|
m_pPoints[m_nPointsCount].dX = dX3;
|
|
m_pPoints[m_nPointsCount].dY = dY3;
|
|
m_pFlags[m_nPointsCount] = PathLast;
|
|
++m_nPointsCount;
|
|
|
|
return 0;
|
|
}
|
|
|
|
int CFontPath::Close()
|
|
{
|
|
if ( NoCurrentPoint() )
|
|
{
|
|
return -1;
|
|
}
|
|
if ( m_nCurSubpath == m_nPointsCount - 1 || m_pPoints[m_nPointsCount - 1].dX != m_pPoints[m_nCurSubpath].dX || m_pPoints[m_nPointsCount - 1].dY != m_pPoints[m_nCurSubpath].dY )
|
|
{
|
|
LineTo( m_pPoints[m_nCurSubpath].dX, m_pPoints[m_nCurSubpath].dY );
|
|
}
|
|
|
|
m_pFlags[m_nCurSubpath] |= PathClosed;
|
|
m_pFlags[m_nPointsCount - 1] |= PathClosed;
|
|
m_nCurSubpath = m_nPointsCount;
|
|
|
|
return 0;
|
|
}
|
|
|
|
void CFontPath::AddStrokeAdjustHint(int nFirstControl, int nSecondControl, int nFirstPoint, int nLastPoint)
|
|
{
|
|
if ( m_nHintsCount == m_nHintsSize )
|
|
{
|
|
m_nHintsSize = m_nHintsCount ? 2 * m_nHintsCount : 8;
|
|
m_pHints = (TPathHint *)realloc( m_pHints, m_nHintsSize * sizeof(TPathHint) );
|
|
}
|
|
m_pHints[m_nHintsCount].nFirstControl = nFirstControl;
|
|
m_pHints[m_nHintsCount].nSecondControl = nSecondControl;
|
|
m_pHints[m_nHintsCount].nFirstPoint = nFirstPoint;
|
|
m_pHints[m_nHintsCount].nLastPoint = nLastPoint;
|
|
|
|
++m_nHintsCount;
|
|
}
|
|
|
|
void CFontPath::Offset(double dDx, double dDy)
|
|
{
|
|
for ( int nIndex = 0; nIndex < m_nPointsCount; ++nIndex )
|
|
{
|
|
m_pPoints[nIndex].dX += dDx;
|
|
m_pPoints[nIndex].dY += dDy;
|
|
}
|
|
}
|
|
|
|
void CFontPath::Reverse()
|
|
{
|
|
for ( int nIndex = 0; nIndex < m_nPointsCount; ++nIndex )
|
|
{
|
|
m_pPoints[nIndex].dY = -m_pPoints[nIndex].dY;
|
|
}
|
|
}
|
|
|
|
void CFontPath::ToMM(double dHorDpi, double dVerDpi)
|
|
{
|
|
for ( int nIndex = 0; nIndex < m_nPointsCount; ++nIndex )
|
|
{
|
|
m_pPoints[nIndex].dX *= 25.4 / dHorDpi;
|
|
m_pPoints[nIndex].dY *= 25.4 / dVerDpi;
|
|
}
|
|
}
|
|
|
|
INT CFontPath::GetCurPoint(double *pdX, double *pdY)
|
|
{
|
|
if ( NoCurrentPoint() )
|
|
{
|
|
return FALSE;
|
|
}
|
|
*pdX = m_pPoints[m_nPointsCount - 1].dX;
|
|
*pdY = m_pPoints[m_nPointsCount - 1].dY;
|
|
return TRUE;
|
|
}
|
|
|
|
int CFontPath::ToInterface(NSFonts::ISimpleGraphicsPath* pPath)
|
|
{
|
|
if ( !pPath )
|
|
return FALSE;
|
|
|
|
for ( int nIndex = 0; nIndex < m_nPointsCount; )
|
|
{
|
|
TPathPoint oPoint = m_pPoints[nIndex];
|
|
unsigned char nFlag = m_pFlags[nIndex];
|
|
|
|
if ( nFlag & PathFirst )
|
|
{
|
|
pPath->_MoveTo( oPoint.dX, oPoint.dY );
|
|
nIndex++;
|
|
}
|
|
else if ( nFlag & PathCurve )
|
|
{
|
|
pPath->_CurveTo( m_pPoints[nIndex + 0].dX, m_pPoints[nIndex + 0].dY, m_pPoints[nIndex + 1].dX, m_pPoints[nIndex + 1].dY, m_pPoints[nIndex + 2].dX, m_pPoints[nIndex + 2].dY );
|
|
nIndex += 3;
|
|
}
|
|
else
|
|
{
|
|
pPath->_LineTo( oPoint.dX, oPoint.dY );
|
|
nIndex++;
|
|
}
|
|
|
|
if ( nFlag & PathClosed && nFlag & PathLast )
|
|
{
|
|
pPath->_Close();
|
|
}
|
|
|
|
}
|
|
|
|
return TRUE;
|
|
}
|