41a38fef3b
- aggiunta entità testo (con font Nfe e di sistema) - in tutte le rotate ora l'angolo è in gradi - aggiunta trasformazione Shear (scorrimento) - aggiunta trsformazione LocToLoc - Set/GetInfo specializzate per i diversi tipi di informazioni - Copy e Relocate con possibilità di indicare l'entità di riferimento rispetto a cui inserire - aggiunte trasformazioni a PolyLine.
326 lines
10 KiB
C++
326 lines
10 KiB
C++
//----------------------------------------------------------------------------
|
|
// EgalTech 2014-2014
|
|
//----------------------------------------------------------------------------
|
|
// File : NfeFont.cpp Data : 29.05.14 Versione : 1.5f1
|
|
// Contenuto : Implementazione della classe NfeFont (formato font proprietario).
|
|
//
|
|
//
|
|
//
|
|
// Modifiche : 29.05.14 DS Creazione modulo.
|
|
//
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
//--------------------------- Include ----------------------------------------
|
|
#include "stdafx.h"
|
|
#include "NfeFont.h"
|
|
#include "/EgtDev/Include/EGkGeomDB.h"
|
|
#include "/EgtDev/Include/EGkGdbIterator.h"
|
|
#include "/EgtDev/Include/EGkCurve.h"
|
|
#include "/EgtDev/Include/EGkCurveAux.h"
|
|
#include "/EgtDev/Include/EgtPointerOwner.h"
|
|
#include "/EgtDev/Include/EgnStringUtils.h"
|
|
#include "/EgtDev/Include/EGnStringDecoder.h"
|
|
#include "/EgtDev/Include/EgnFileUtils.h"
|
|
|
|
using namespace std ;
|
|
|
|
//----------------------------------------------------------------------------
|
|
const string NFE_H = "H" ;
|
|
const string NFE_HCAP = "HCAP" ;
|
|
const string NFE_HX = "HX" ;
|
|
const string NFE_ASC = "ASC" ;
|
|
const string NFE_DESC = "DESC" ;
|
|
const string NFE_ADV = "ADV" ;
|
|
const string NFE_ITALIC = "ITL" ;
|
|
const double NFE_ITALIC_STD_SHEAR_COEFF = 0.25 ;
|
|
const int NFE_MIN_CHAR = 32 ;
|
|
const int NFE_ERR_CHAR = 127 ;
|
|
const string NFE_LEN_CHAR = "L" ;
|
|
|
|
//----------------------------------------------------------------------------
|
|
NfeFont::NfeFont( void)
|
|
{
|
|
m_pGDB = nullptr ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
NfeFont::~NfeFont( void)
|
|
{
|
|
if ( m_pGDB != nullptr)
|
|
delete m_pGDB ;
|
|
m_pGDB = nullptr ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
NfeFont::SetCurrFont( const string& sFont, int nWeight, bool bItalic,
|
|
double dHeight, double dRatio, double dAddAdvance)
|
|
{
|
|
string sFontUp = sFont ;
|
|
ToUpper( sFontUp) ;
|
|
|
|
// se il font non è già caricato
|
|
if ( m_pGDB == nullptr || m_sFont != sFontUp) {
|
|
// pulisco la path del font
|
|
m_sFont.clear() ;
|
|
// se necessario creo GDB
|
|
if ( m_pGDB == nullptr) {
|
|
m_pGDB = CreateGeomDB() ;
|
|
if ( m_pGDB == nullptr)
|
|
return false ;
|
|
}
|
|
// pulisco e inizializzo GDB
|
|
m_pGDB->Init() ;
|
|
// carico il font
|
|
if ( ! m_pGDB->Load( sFont))
|
|
return false ;
|
|
// recupero i parametri generali del font (devono essere nel gruppo 1)
|
|
PtrOwner<IGdbIterator> pIter( CreateGdbIterator( m_pGDB)) ;
|
|
if ( ! IsValid( pIter))
|
|
return false ;
|
|
if ( ! pIter->GoTo( 1))
|
|
return false ;
|
|
if ( ! pIter->GetInfo( NFE_H, m_dH) ||
|
|
! pIter->GetInfo( NFE_HCAP, m_dHCap) ||
|
|
! pIter->GetInfo( NFE_HX, m_dHx) ||
|
|
! pIter->GetInfo( NFE_ASC, m_dAsc) ||
|
|
! pIter->GetInfo( NFE_DESC, m_dDesc) ||
|
|
! pIter->GetInfo( NFE_ADV, m_dAdv))
|
|
return false ;
|
|
if ( m_dH < EPS_SMALL || m_dHCap < EPS_SMALL || m_dHx < EPS_SMALL)
|
|
return false ;
|
|
if ( ! pIter->GetInfo( NFE_ITALIC, m_dItalicShearCoeff))
|
|
m_dItalicShearCoeff = NFE_ITALIC_STD_SHEAR_COEFF ;
|
|
// aggiorno la path del font
|
|
m_sFont = sFontUp ;
|
|
}
|
|
|
|
// salvo i dati
|
|
m_nWeight = nWeight ;
|
|
m_bItalic = bItalic ;
|
|
m_dHeight = dHeight ;
|
|
m_dRatio = dRatio ;
|
|
m_dAddAdvance = dAddAdvance ;
|
|
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
NfeFont::GetCapHeight( double& dCapH)
|
|
{
|
|
// verifico esistenza font corrente
|
|
if ( m_pGDB == nullptr || m_sFont.empty())
|
|
return false ;
|
|
|
|
// uso il fattore di scala per Y = m_dHeight / m_dHCap
|
|
dCapH = m_dHCap * m_dHeight / m_dHCap ;
|
|
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
NfeFont::GetAscent( double& dAsc)
|
|
{
|
|
// verifico esistenza font corrente
|
|
if ( m_pGDB == nullptr || m_sFont.empty())
|
|
return false ;
|
|
|
|
// uso il fattore di scala per Y = m_dHeight / m_dHCap
|
|
dAsc = m_dAsc * m_dHeight / m_dHCap ;
|
|
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
NfeFont::GetDescent( double& dDesc)
|
|
{
|
|
// verifico esistenza font corrente
|
|
if ( m_pGDB == nullptr || m_sFont.empty())
|
|
return false ;
|
|
|
|
// uso il fattore di scala per Y = m_dHeight / m_dHCap
|
|
dDesc = m_dDesc * m_dHeight / m_dHCap ;
|
|
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
NfeFont::GetLength( const string& sText, double& dLen)
|
|
{
|
|
// verifico esistenza font corrente
|
|
if ( m_pGDB == nullptr || m_sFont.empty())
|
|
return false ;
|
|
|
|
// creo un iteratore
|
|
PtrOwner<IGdbIterator> pIter( CreateGdbIterator( m_pGDB)) ;
|
|
if ( ! IsValid( pIter))
|
|
return false ;
|
|
|
|
// calcolo il fattore di scala
|
|
double dScaX = m_dHeight / m_dHCap * m_dRatio ;
|
|
|
|
// converto i byte della stringa in codici carattere
|
|
UINTVECTOR vCode ;
|
|
GetCodePoints( sText, vCode) ;
|
|
|
|
// scandisco i codici
|
|
dLen = 0 ;
|
|
for ( unsigned int i = 0 ; i < vCode.size() ; ++ i) {
|
|
// gruppo del carattere
|
|
int nGroup = sText[i] ;
|
|
if ( nGroup < NFE_MIN_CHAR || m_pGDB->GetGdbType( nGroup) == GDB_TY_NONE)
|
|
nGroup = NFE_ERR_CHAR ;
|
|
// recupero lo spostamento per il prossimo carattere
|
|
double dAdvance ;
|
|
if ( ! m_pGDB->GetInfo( nGroup, NFE_LEN_CHAR, dAdvance))
|
|
dAdvance = m_dAdv ;
|
|
dLen += dAdvance * dScaX + m_dAddAdvance ;
|
|
}
|
|
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
NfeFont::GetBBox( const string& sText, BBox3d& b3Box)
|
|
{
|
|
// recupero le dimensioni
|
|
double dAsc ;
|
|
if ( ! GetAscent( dAsc))
|
|
return false ;
|
|
double dDesc ;
|
|
if ( ! GetDescent( dDesc))
|
|
return false ;
|
|
double dLen ;
|
|
if ( ! GetLength( sText, dLen))
|
|
return false ;
|
|
|
|
// assegno l'ingombro
|
|
b3Box.Set( 0, - dDesc, 0, dLen, dAsc, 0) ;
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
NfeFont::GetOutline( const string& sText, ICURVEPLIST& lstPC)
|
|
{
|
|
// verifico esistenza font corrente
|
|
if ( m_pGDB == nullptr || m_sFont.empty())
|
|
return false ;
|
|
|
|
// creo un iteratore
|
|
PtrOwner<IGdbIterator> pIter( CreateGdbIterator( m_pGDB)) ;
|
|
if ( ! IsValid( pIter))
|
|
return false ;
|
|
|
|
// calcolo i fattori di scala
|
|
double dScaY = m_dHeight / m_dHCap ;
|
|
double dScaX = dScaY * m_dRatio ;
|
|
double dScaZ = 1 ;
|
|
|
|
// converto i byte della stringa in codici carattere
|
|
UINTVECTOR vCode ;
|
|
GetCodePoints( sText, vCode) ;
|
|
|
|
// scandisco i codici
|
|
Vector3d vtMove ;
|
|
for ( unsigned int i = 0 ; i < vCode.size() ; ++ i) {
|
|
// verifico esistenza del gruppo del carattere
|
|
int nGroup = vCode[i] ;
|
|
if ( nGroup < NFE_MIN_CHAR || m_pGDB->GetGdbType( nGroup) == GDB_TY_NONE)
|
|
nGroup = NFE_ERR_CHAR ;
|
|
// ciclo sulle entità geometriche del carattere
|
|
bool bIter = pIter->GoToFirstInGroup( nGroup) ;
|
|
while ( bIter) {
|
|
ICurve* pCrv = GetCurve( pIter->GetGeoObj()) ;
|
|
if ( pCrv != nullptr) {
|
|
ICurve* pCopyCrv = GetCurve( pCrv->Clone()) ;
|
|
if ( pCopyCrv == nullptr)
|
|
return false ;
|
|
lstPC.push_back( pCopyCrv) ;
|
|
if ( m_bItalic) {
|
|
// se arco, devo trasformarlo in curva di Bezier (semplice o composta)
|
|
if ( pCopyCrv->GetType() == CRV_ARC) {
|
|
ICurve* pCrvNew ;
|
|
if ( ! ArcToBezierCurve( pCopyCrv, pCrvNew))
|
|
return false ;
|
|
// elimino l'arco e lo sostituisco con la curva di Bezier
|
|
delete pCopyCrv ;
|
|
lstPC.back() = pCrvNew ;
|
|
}
|
|
pCopyCrv->Shear( ORIG, Y_AX, X_AX, m_dItalicShearCoeff) ;
|
|
}
|
|
pCopyCrv->Scale( GLOB_FRM, dScaX, dScaY, dScaZ) ;
|
|
pCopyCrv->Translate( vtMove) ;
|
|
}
|
|
bIter = pIter->GoToNext() ;
|
|
}
|
|
// recupero lo spostamento per il prossimo carattere
|
|
double dAdvance ;
|
|
if ( ! m_pGDB->GetInfo( nGroup, NFE_LEN_CHAR, dAdvance))
|
|
dAdvance = m_dAdv ;
|
|
vtMove += Vector3d( ( dAdvance * dScaX + m_dAddAdvance), 0, 0) ;
|
|
}
|
|
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
NfeFont::ApproxWithLines( const string& sText, double dLinTol, double dAngTolDeg, POLYLINELIST& lstPL)
|
|
{
|
|
// verifico esistenza font corrente
|
|
if ( m_pGDB == nullptr || m_sFont.empty())
|
|
return false ;
|
|
|
|
// creo un iteratore
|
|
PtrOwner<IGdbIterator> pIter( CreateGdbIterator( m_pGDB)) ;
|
|
if ( ! IsValid( pIter))
|
|
return false ;
|
|
|
|
// calcolo i fattori di scala
|
|
double dScaY = m_dHeight / m_dHCap ;
|
|
double dScaX = dScaY * m_dRatio ;
|
|
double dScaZ = 1 ;
|
|
double dInvScaMed = 1 / max( ( dScaX + dScaY) / 2, EPS_SMALL) ;
|
|
|
|
// converto i byte della stringa in codici carattere
|
|
UINTVECTOR vCode ;
|
|
GetCodePoints( sText, vCode) ;
|
|
|
|
// scandisco i codici
|
|
Vector3d vtMove ;
|
|
for ( unsigned int i = 0 ; i < vCode.size() ; ++ i) {
|
|
// verifico esistenza del gruppo del carattere
|
|
int nGroup = vCode[i] ;
|
|
if ( nGroup < NFE_MIN_CHAR || m_pGDB->GetGdbType( nGroup) == GDB_TY_NONE)
|
|
nGroup = NFE_ERR_CHAR ;
|
|
// ciclo sulle entità geometriche del carattere
|
|
bool bIter = pIter->GoToFirstInGroup( nGroup) ;
|
|
while ( bIter) {
|
|
ICurve* pCrv = GetCurve( pIter->GetGeoObj()) ;
|
|
if ( pCrv != nullptr) {
|
|
lstPL.push_back( PolyLine()) ;
|
|
pCrv->ApproxWithLines( dLinTol * dInvScaMed, dAngTolDeg, lstPL.back()) ;
|
|
if ( m_bItalic)
|
|
lstPL.back().Shear( ORIG, Y_AX, X_AX, m_dItalicShearCoeff) ;
|
|
lstPL.back().Scale( GLOB_FRM, dScaX, dScaY, dScaZ) ;
|
|
lstPL.back().Translate( vtMove) ;
|
|
}
|
|
bIter = pIter->GoToNext() ;
|
|
}
|
|
// recupero lo spostamento per il prossimo carattere
|
|
double dAdvance ;
|
|
if ( ! m_pGDB->GetInfo( nGroup, NFE_LEN_CHAR, dAdvance))
|
|
dAdvance = m_dAdv ;
|
|
vtMove += Vector3d( ( dAdvance * dScaX + m_dAddAdvance), 0, 0) ;
|
|
}
|
|
|
|
return true ;
|
|
}
|