mirror of
https://github.com/ONLYOFFICE/core.git
synced 2026-07-11 08:22:08 +08:00
382 lines
9.5 KiB
C++
382 lines
9.5 KiB
C++
#ifndef _GLYPH_STRING_H
|
||
#define _GLYPH_STRING_H
|
||
|
||
#include "FontConsts.h"
|
||
|
||
class CGlyphString
|
||
{
|
||
public:
|
||
|
||
CGlyphString()
|
||
{
|
||
m_fX = 0;
|
||
m_fY = 0;
|
||
|
||
m_fEndX = 0;
|
||
m_fEndY = 0;
|
||
|
||
m_nGlyphIndex = -1;
|
||
m_nGlyphsCount = 0;
|
||
m_pGlyphsBuffer = NULL;
|
||
|
||
m_arrCTM[0] = 1;
|
||
m_arrCTM[1] = 0;
|
||
m_arrCTM[2] = 0;
|
||
m_arrCTM[3] = 1;
|
||
m_arrCTM[4] = 0;
|
||
m_arrCTM[5] = 0;
|
||
|
||
m_fTransX = 0;
|
||
m_fTransY = 0;
|
||
}
|
||
|
||
CGlyphString(CStringW wsString, float fX = 0, float fY = 0)
|
||
{
|
||
m_nGlyphIndex = 0;
|
||
m_nGlyphsCount = wsString.GetLength();
|
||
|
||
if ( m_nGlyphsCount > 0 )
|
||
m_pGlyphsBuffer = new TGlyph[m_nGlyphsCount];
|
||
else
|
||
m_pGlyphsBuffer = NULL;
|
||
|
||
for ( int nIndex = 0; nIndex < m_nGlyphsCount; nIndex++ )
|
||
{
|
||
//memset( (void *)(m_pGlyphsBuffer + nIndex), 0x00, sizeof( TGlyph ) );
|
||
m_pGlyphsBuffer[nIndex].lUnicode = wsString.GetAt( nIndex );
|
||
m_pGlyphsBuffer[nIndex].bBitmap = false;
|
||
}
|
||
|
||
m_fX = fX;
|
||
m_fY = fY;
|
||
|
||
m_arrCTM[0] = 1;
|
||
m_arrCTM[1] = 0;
|
||
m_arrCTM[2] = 0;
|
||
m_arrCTM[3] = 1;
|
||
m_arrCTM[4] = 0;
|
||
m_arrCTM[5] = 0;
|
||
|
||
m_fTransX = 0;
|
||
m_fTransY = 0;
|
||
}
|
||
|
||
~CGlyphString()
|
||
{
|
||
if ( m_pGlyphsBuffer )
|
||
delete []m_pGlyphsBuffer;
|
||
}
|
||
|
||
|
||
void SetString(CStringW wsString, float fX = 0, float fY = 0)
|
||
{
|
||
m_fX = fX + m_fTransX;
|
||
m_fY = fY + m_fTransY;
|
||
|
||
if ( m_pGlyphsBuffer )
|
||
delete []m_pGlyphsBuffer;
|
||
|
||
m_nGlyphsCount = wsString.GetLength();
|
||
m_nGlyphIndex = 0;
|
||
|
||
m_pGlyphsBuffer = new TGlyph[m_nGlyphsCount];
|
||
for ( int nIndex = 0; nIndex < m_nGlyphsCount; nIndex++ )
|
||
{
|
||
//memset( (void *)(m_pGlyphsBuffer + nIndex), 0x00, sizeof( TGlyph ) );
|
||
m_pGlyphsBuffer[nIndex].lUnicode = wsString.GetAt( nIndex );
|
||
m_pGlyphsBuffer[nIndex].bBitmap = false;
|
||
}
|
||
}
|
||
|
||
void Reset()
|
||
{
|
||
if ( m_pGlyphsBuffer )
|
||
delete []m_pGlyphsBuffer;
|
||
|
||
m_fX = 0;
|
||
m_fY = 0;
|
||
|
||
m_fEndX = 0;
|
||
m_fEndY = 0;
|
||
|
||
m_nGlyphIndex = -1;
|
||
m_nGlyphsCount = 0;
|
||
m_pGlyphsBuffer = NULL;
|
||
|
||
m_arrCTM[0] = 1;
|
||
m_arrCTM[1] = 0;
|
||
m_arrCTM[2] = 0;
|
||
m_arrCTM[3] = 1;
|
||
m_arrCTM[4] = 0;
|
||
m_arrCTM[5] = 0;
|
||
|
||
m_fTransX = 0;
|
||
m_fTransY = 0;
|
||
}
|
||
|
||
int GetLength()
|
||
{
|
||
return m_nGlyphsCount;
|
||
}
|
||
void SetBBox(int nIndex, float fLeft, float fTop, float fRight, float fBottom)
|
||
{
|
||
if ( m_nGlyphsCount <= 0 )
|
||
return;
|
||
|
||
int nCurIndex = min( m_nGlyphsCount - 1, max( 0, nIndex ) );
|
||
|
||
m_pGlyphsBuffer[nCurIndex].fLeft = fLeft;
|
||
m_pGlyphsBuffer[nCurIndex].fTop = fTop;
|
||
m_pGlyphsBuffer[nCurIndex].fRight = fRight;
|
||
m_pGlyphsBuffer[nCurIndex].fBottom = fBottom;
|
||
}
|
||
void SetMetrics(int nIndex, float fWidth, float fHeight, float fHoriAdvance, float fHoriBearingX, float fHoriBearingY, float fVertAdvance, float fVertBearingX, float fVertBearingY)
|
||
{
|
||
if ( m_nGlyphsCount <= 0 )
|
||
return;
|
||
|
||
int nCurIndex = min( m_nGlyphsCount - 1, max( 0, nIndex ) );
|
||
|
||
m_pGlyphsBuffer[nCurIndex].oMetrics.fHeight = fHeight;
|
||
m_pGlyphsBuffer[nCurIndex].oMetrics.fHoriAdvance = fHoriAdvance;
|
||
m_pGlyphsBuffer[nCurIndex].oMetrics.fHoriBearingX = fHoriBearingX;
|
||
m_pGlyphsBuffer[nCurIndex].oMetrics.fHoriBearingY = fHoriBearingY;
|
||
m_pGlyphsBuffer[nCurIndex].oMetrics.fVertAdvance = fVertAdvance;
|
||
m_pGlyphsBuffer[nCurIndex].oMetrics.fVertBearingX = fVertBearingX;
|
||
m_pGlyphsBuffer[nCurIndex].oMetrics.fVertBearingY = fVertBearingY;
|
||
m_pGlyphsBuffer[nCurIndex].oMetrics.fWidth = fWidth;
|
||
}
|
||
void SetStartPoint(int nIndex, float fX, float fY)
|
||
{
|
||
if ( m_nGlyphsCount <= 0 )
|
||
return;
|
||
|
||
int nCurIndex = min( m_nGlyphsCount - 1, max( 0, nIndex ) );
|
||
|
||
m_pGlyphsBuffer[nCurIndex].fX = fX;
|
||
m_pGlyphsBuffer[nCurIndex].fY = fY;
|
||
}
|
||
void SetState(int nIndex, EGlyphState eState)
|
||
{
|
||
if ( m_nGlyphsCount <= 0 )
|
||
return;
|
||
|
||
int nCurIndex = min( m_nGlyphsCount - 1, max( 0, nIndex ) );
|
||
|
||
m_pGlyphsBuffer[nCurIndex].eState = eState;
|
||
}
|
||
|
||
void GetBBox(float *pfLeft, float *pfTop, float *pfRight, float *pfBottom, int nIndex = -1, int nType = 0)
|
||
{
|
||
int nCurIndex = 0;
|
||
if ( nIndex < 0 )
|
||
{
|
||
if ( m_nGlyphsCount <= 0 || m_nGlyphIndex < 1 || m_nGlyphIndex > m_nGlyphsCount )
|
||
return;
|
||
|
||
nCurIndex = m_nGlyphIndex - 1;
|
||
}
|
||
else
|
||
{
|
||
if ( m_nGlyphsCount <= 0 )
|
||
return;
|
||
|
||
nCurIndex = min( m_nGlyphsCount - 1, max( 0, nIndex ) );
|
||
}
|
||
|
||
float fBottom = -m_pGlyphsBuffer[nCurIndex].fBottom;
|
||
float fRight = m_pGlyphsBuffer[nCurIndex].fRight;
|
||
float fLeft = m_pGlyphsBuffer[nCurIndex].fLeft;
|
||
float fTop = -m_pGlyphsBuffer[nCurIndex].fTop;
|
||
|
||
|
||
if ( 0 == nType && !( 1 == m_arrCTM[0] && 0 == m_arrCTM[1] && 0 == m_arrCTM[2] && 1 == m_arrCTM[3] && 0 == m_arrCTM[4] && 0 == m_arrCTM[5] ) )
|
||
{
|
||
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> BBox
|
||
float arrfX[4] = { fLeft, fLeft, fRight, fRight };
|
||
float arrfY[4] = { fTop, fBottom, fBottom, fTop };
|
||
|
||
float fMinX = (float)(arrfX[0] * m_arrCTM[0] + arrfY[0] * m_arrCTM[2]);
|
||
float fMinY = (float)(arrfX[0] * m_arrCTM[1] + arrfY[0] * m_arrCTM[3]);
|
||
float fMaxX = fMinX;
|
||
float fMaxY = fMinY;
|
||
|
||
for ( int nIndex = 1; nIndex < 4; nIndex++ )
|
||
{
|
||
float fX = (float)(arrfX[nIndex] * m_arrCTM[0] + arrfY[nIndex] * m_arrCTM[2]);
|
||
float fY = (float)(arrfX[nIndex] * m_arrCTM[1] + arrfY[nIndex] * m_arrCTM[3]);
|
||
|
||
fMaxX = max( fMaxX, fX );
|
||
fMinX = min( fMinX, fX );
|
||
|
||
fMaxY = max( fMaxY, fY );
|
||
fMinY = min( fMinY, fY );
|
||
}
|
||
|
||
fLeft = fMinX;
|
||
fRight = fMaxX;
|
||
fTop = fMinY;
|
||
fBottom = fMaxY;
|
||
}
|
||
|
||
*pfLeft = fLeft + m_pGlyphsBuffer[nCurIndex].fX + m_fX;
|
||
*pfRight = fRight + m_pGlyphsBuffer[nCurIndex].fX + m_fX;
|
||
*pfTop = fTop + m_pGlyphsBuffer[nCurIndex].fY + m_fY;
|
||
*pfBottom = fBottom + m_pGlyphsBuffer[nCurIndex].fY + m_fY;
|
||
}
|
||
|
||
void GetBBox2(float *pfLeft, float *pfTop, float *pfRight, float *pfBottom)
|
||
{
|
||
if ( m_nGlyphsCount <= 0 )
|
||
{
|
||
*pfLeft = 0;
|
||
*pfRight = 0;
|
||
*pfBottom = 0;
|
||
*pfTop = 0;
|
||
}
|
||
|
||
float fBottom = 0;
|
||
float fRight = 0;
|
||
float fLeft = 0;
|
||
float fTop = 0;
|
||
|
||
for ( int nIndex = 0; nIndex < m_nGlyphsCount; nIndex++ )
|
||
{
|
||
fBottom = max( fBottom, -m_pGlyphsBuffer[nIndex].fBottom );
|
||
//fRight = max( fRight, m_pGlyphsBuffer[nIndex].fRight );
|
||
//fLeft = min( fLeft, m_pGlyphsBuffer[nIndex].fLeft );
|
||
fTop = min( fTop, -m_pGlyphsBuffer[nIndex].fTop );
|
||
}
|
||
|
||
if ( !( 1 == m_arrCTM[0] && 0 == m_arrCTM[1] && 0 == m_arrCTM[2] && 1 == m_arrCTM[3] && 0 == m_arrCTM[4] && 0 == m_arrCTM[5] ) )
|
||
{
|
||
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> BBox
|
||
float arrfX[4] = { fLeft, fLeft, fRight, fRight };
|
||
float arrfY[4] = { fTop, fBottom, fBottom, fTop };
|
||
|
||
float fMinX = (float)(arrfX[0] * m_arrCTM[0] + arrfY[0] * m_arrCTM[2]);
|
||
float fMinY = (float)(arrfX[0] * m_arrCTM[1] + arrfY[0] * m_arrCTM[3]);
|
||
float fMaxX = fMinX;
|
||
float fMaxY = fMinY;
|
||
|
||
for ( int nIndex = 1; nIndex < 4; nIndex++ )
|
||
{
|
||
float fX = (float)(arrfX[nIndex] * m_arrCTM[0] + arrfY[nIndex] * m_arrCTM[2]);
|
||
float fY = (float)(arrfX[nIndex] * m_arrCTM[1] + arrfY[nIndex] * m_arrCTM[3]);
|
||
|
||
fMaxX = max( fMaxX, fX );
|
||
fMinX = min( fMinX, fX );
|
||
|
||
fMaxY = max( fMaxY, fY );
|
||
fMinY = min( fMinY, fY );
|
||
}
|
||
|
||
fLeft = fMinX;
|
||
fRight = fMaxX;
|
||
fTop = fMinY;
|
||
fBottom = fMaxY;
|
||
}
|
||
|
||
fLeft += m_fX;
|
||
fRight += m_fX;
|
||
fTop += m_fY;
|
||
fBottom += m_fY;
|
||
|
||
*pfLeft = min( fLeft, min(m_fX, m_fEndX) );
|
||
*pfRight = max( fRight, max(m_fX, m_fEndX) );
|
||
*pfTop = min( fTop, min(m_fY, m_fEndY) );
|
||
*pfBottom = max( fBottom, max(m_fY, m_fEndY) );
|
||
}
|
||
|
||
void SetCTM(float fA, float fB, float fC, float fD, float fE ,float fF)
|
||
{
|
||
m_arrCTM[0] = fA;
|
||
m_arrCTM[1] = fB;
|
||
m_arrCTM[2] = fC;
|
||
m_arrCTM[3] = fD;
|
||
m_arrCTM[4] = fE;
|
||
m_arrCTM[5] = fF;
|
||
|
||
double dDet = fA * fD - fB * fC;
|
||
|
||
if ( dDet < 0.001 && dDet >= 0 )
|
||
dDet = 0.001;
|
||
else if ( dDet > - 0.001 && dDet < 0 )
|
||
dDet = -0.001;
|
||
|
||
m_dIDet = 1 / dDet;
|
||
|
||
}
|
||
void ResetCTM()
|
||
{
|
||
m_arrCTM[0] = 1;
|
||
m_arrCTM[1] = 0;
|
||
m_arrCTM[2] = 0;
|
||
m_arrCTM[3] = 1;
|
||
m_arrCTM[4] = 0;
|
||
m_arrCTM[5] = 0;
|
||
|
||
m_dIDet = 1;
|
||
}
|
||
|
||
void Transform(float *pfX, float *pfY)
|
||
{
|
||
float fX = *pfX, fY = *pfY;
|
||
|
||
*pfX = (float) ( fX * m_arrCTM[0] + fY * m_arrCTM[2] + m_arrCTM[4] );
|
||
*pfY = (float) ( fX * m_arrCTM[1] + fY * m_arrCTM[3] + m_arrCTM[5] );
|
||
}
|
||
void SetTrans(float fX, float fY)
|
||
{
|
||
m_fTransX = (float) ( m_dIDet * ( fX * m_arrCTM[3] - m_arrCTM[2] * fY ) );
|
||
m_fTransY = (float) ( m_dIDet * ( fY * m_arrCTM[0] - m_arrCTM[1] * fX ) );
|
||
}
|
||
TGlyph *GetAt(int nIndex)
|
||
{
|
||
if ( m_nGlyphsCount <= 0 )
|
||
{
|
||
return NULL;
|
||
}
|
||
|
||
int nCurIndex = min( m_nGlyphsCount - 1, max( 0, nIndex ) );
|
||
|
||
return &(m_pGlyphsBuffer[nCurIndex]);
|
||
}
|
||
|
||
BOOL GetNext(TGlyph *pGlyph)
|
||
{
|
||
if ( m_nGlyphIndex >= m_nGlyphsCount || m_nGlyphIndex < 0 )
|
||
{
|
||
pGlyph = NULL;
|
||
return FALSE;
|
||
}
|
||
|
||
*pGlyph = m_pGlyphsBuffer[m_nGlyphIndex];
|
||
m_nGlyphIndex++;
|
||
|
||
return TRUE;
|
||
}
|
||
|
||
public:
|
||
|
||
float m_fTransX;
|
||
float m_fTransY;
|
||
|
||
float m_fX; // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||
float m_fY; //
|
||
|
||
float m_fEndX; // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>
|
||
float m_fEndY; //
|
||
|
||
double m_arrCTM[6]; // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||
double m_dIDet; // (<28><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>)^(-1)
|
||
|
||
private:
|
||
|
||
TGlyph *m_pGlyphsBuffer; // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||
int m_nGlyphsCount; // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||
int m_nGlyphIndex; // <20><><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||
|
||
};
|
||
|
||
#endif /* _GLYPH_STRING_H */ |