Files
EgtGeomKernel/NfeFont.cpp
T
Dario Sassi 41a38fef3b EgtGeomKernel 1.5f1 :
- 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.
2014-06-03 13:19:54 +00:00

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 ;
}