EgtGeomKernel 1.5f2 :
- aggiunta gestione testi multilinea - migliorie e correzioni varie sui testi.
This commit is contained in:
+574
@@ -0,0 +1,574 @@
|
||||
//----------------------------------------------------------------------------
|
||||
// EgalTech 2014-2014
|
||||
//----------------------------------------------------------------------------
|
||||
// File : FontOs.cpp Data : 05.06.14 Versione : 1.5f2
|
||||
// Contenuto : Implementazione della classe OsFont (font di sistema).
|
||||
//
|
||||
//
|
||||
//
|
||||
// Modifiche : 01.06.14 DS Creazione modulo.
|
||||
//
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
//--------------------------- Include ----------------------------------------
|
||||
#include "stdafx.h"
|
||||
#include "FontOs.h"
|
||||
#include "FontAux.h"
|
||||
#include "/EgtDev/Include/EGkGeomDB.h"
|
||||
#include "/EgtDev/Include/EGkGdbIterator.h"
|
||||
#include "/EgtDev/Include/EGkCurve.h"
|
||||
#include "/EgtDev/Include/EGkCurveAux.h"
|
||||
#include "/EgtDev/Include/EgkCurveComposite.h"
|
||||
#include "/EgtDev/Include/EgkCurveLine.h"
|
||||
#include "/EgtDev/Include/EgkCurveBezier.h"
|
||||
#include "/EgtDev/Include/EgtPointerOwner.h"
|
||||
#include "/EgtDev/Include/EgnStringUtils.h"
|
||||
#include "/EgtDev/Include/EGnStringConverter.h"
|
||||
#include "/EgtDev/Include/EGnStringDecoder.h"
|
||||
#include "/EgtDev/Include/EgnFileUtils.h"
|
||||
|
||||
using namespace std ;
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
const int OSF_HSTD = 100 ;
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
OsFont::OsFont( void)
|
||||
{
|
||||
m_hDC = nullptr ;
|
||||
m_hFont = nullptr ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
OsFont::~OsFont( void)
|
||||
{
|
||||
if ( m_hFont != nullptr)
|
||||
DeleteObject( m_hFont) ;
|
||||
m_hFont = nullptr ;
|
||||
if ( m_hDC != nullptr)
|
||||
ReleaseDC( NULL, m_hDC) ;
|
||||
m_hDC = nullptr ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
OsFont::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_sFont != sFontUp) {
|
||||
// pulisco la path del font
|
||||
m_sFont.clear() ;
|
||||
// cancello eventuale precedente font
|
||||
if ( m_hFont != nullptr)
|
||||
DeleteObject( m_hFont) ;
|
||||
// se necessario, recupero il device di schermo
|
||||
if ( m_hDC == nullptr)
|
||||
m_hDC = GetDC( nullptr) ;
|
||||
if ( m_hDC == nullptr)
|
||||
return false ;
|
||||
::SetMapMode( m_hDC, MM_TEXT) ;
|
||||
// creo il font
|
||||
m_hFont = CreateFontW( - OSF_HSTD, 0, 0, 0, nWeight, bItalic, false, false, DEFAULT_CHARSET,
|
||||
OUT_TT_ONLY_PRECIS, CLIP_DEFAULT_PRECIS, PROOF_QUALITY, DEFAULT_PITCH,
|
||||
stringtoW( sFont)) ;
|
||||
if ( m_hFont == nullptr)
|
||||
return false ;
|
||||
// aggiorno dati del font
|
||||
if ( ! CalcFontData())
|
||||
return false ;
|
||||
// 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
|
||||
OsFont::CalcFontData( void)
|
||||
{
|
||||
// verifico esistenza font corrente (non controllo nome)
|
||||
if ( m_hDC == nullptr || m_hFont == nullptr)
|
||||
return false ;
|
||||
|
||||
// rendo corrente il font
|
||||
HFONT hPrevFont = (HFONT) SelectObject( m_hDC, m_hFont) ;
|
||||
if ( hPrevFont == nullptr)
|
||||
return false ;
|
||||
|
||||
// dati generali
|
||||
TEXTMETRIC tm ;
|
||||
if ( ! GetTextMetrics( m_hDC, &tm))
|
||||
return false ;
|
||||
double dCoeff = (( tm.tmHeight > 0) ? double( OSF_HSTD) / tm.tmHeight : 1) ;
|
||||
m_dH = ( tm.tmHeight + tm.tmExternalLeading) * dCoeff ;
|
||||
m_dHCap = ( tm.tmAscent - tm.tmInternalLeading) * dCoeff ;
|
||||
m_dHx = 0.6667 * m_dHCap ; // approx
|
||||
m_dAsc = tm.tmAscent * dCoeff ;
|
||||
m_dDesc = tm.tmDescent * dCoeff ;
|
||||
m_dAdv = tm.tmMaxCharWidth * dCoeff ;
|
||||
|
||||
// cerco dato più preciso su altezza delle maiuscole
|
||||
GLYPHMETRICS gm ;
|
||||
MAT2 mat = { {0,1},{0,0},{0,0},{0,1}} ;
|
||||
// recupero l'altezza della lettera 'H' (72)
|
||||
DWORD dwSize = GetGlyphOutlineW( m_hDC, 72, GGO_NATIVE, &gm, 0, NULL, &mat) ;
|
||||
if ( dwSize != GDI_ERROR) {
|
||||
m_dHCap = gm.gmBlackBoxY ;
|
||||
m_dHx = 0.6667 * m_dHCap ; // approx
|
||||
}
|
||||
|
||||
// ripristino il font originale
|
||||
SelectObject( m_hDC, hPrevFont) ;
|
||||
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
OsFont::GetCapHeight( double& dCapH)
|
||||
{
|
||||
// verifico esistenza font corrente
|
||||
if ( m_hDC == nullptr || m_hFont == 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
|
||||
OsFont::GetAscent( double& dAsc)
|
||||
{
|
||||
// verifico esistenza font corrente
|
||||
if ( m_hDC == nullptr || m_hFont == 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
|
||||
OsFont::GetDescent( double& dDesc)
|
||||
{
|
||||
// verifico esistenza font corrente
|
||||
if ( m_hDC == nullptr || m_hFont == 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
|
||||
OsFont::GetXBox( const string& sText, int nInsPos, bool bCapOrBound, BBox3d& b3Box)
|
||||
{
|
||||
// verifico esistenza font corrente
|
||||
if ( m_hDC == nullptr || m_hFont == nullptr || m_sFont.empty())
|
||||
return false ;
|
||||
|
||||
// rendo corrente il font
|
||||
HFONT hPrevFont = (HFONT) SelectObject( m_hDC, m_hFont) ;
|
||||
if ( hPrevFont == nullptr)
|
||||
return false ;
|
||||
|
||||
// calcolo i fattori di scala
|
||||
double dScaY = m_dHeight / m_dHCap ;
|
||||
double dScaX = dScaY * m_dRatio ;
|
||||
|
||||
// recupero altezza maiuscole, ascent, descent e interlinea
|
||||
double dHCap = m_dHeight ;
|
||||
double dAscent = m_dAsc * m_dHeight / m_dHCap ;
|
||||
double dDescent = m_dDesc * m_dHeight / m_dHCap ;
|
||||
double dH = m_dH * m_dHeight / m_dHCap ;
|
||||
|
||||
// converto i byte della stringa in codici carattere
|
||||
UINTVECTOR vCode ;
|
||||
GetCodePoints( sText, vCode) ;
|
||||
|
||||
// scandisco i codici
|
||||
double dCurrW = 0 ;
|
||||
double dMaxW = 0 ;
|
||||
double dMinH = 0 ;
|
||||
for ( unsigned int i = 0 ; i < vCode.size() ; ++ i) {
|
||||
// verifico se comando di a capo
|
||||
int nLbLen ;
|
||||
if ( IsLineBreak( vCode, i, nLbLen)) {
|
||||
dCurrW = 0 ;
|
||||
dMinH -= dH ;
|
||||
i += nLbLen ;
|
||||
continue ;
|
||||
}
|
||||
// recupero l'avanzamento di ogni carattere
|
||||
ABC abc ;
|
||||
double dAdvance ;
|
||||
if ( GetCharABCWidths( m_hDC, vCode[i], vCode[i], &abc))
|
||||
dAdvance = ( abc.abcA + abc.abcB + abc.abcC) ;
|
||||
else
|
||||
dAdvance = m_dAdv ;
|
||||
dCurrW += dAdvance * dScaX + m_dAddAdvance ;
|
||||
if ( dCurrW > dMaxW)
|
||||
dMaxW = dCurrW ;
|
||||
}
|
||||
|
||||
// punti estremi
|
||||
Point3d ptMin( 0, dMinH - ( bCapOrBound ? 0 : dDescent), 0) ;
|
||||
Point3d ptMax( dMaxW, ( bCapOrBound ? dHCap : dAscent), 0) ;
|
||||
// sistemazioni per la posizione del punto di inserimento
|
||||
Vector3d vtIpMove = GetTextInsertPointMove( dMaxW, dHCap, dMinH, nInsPos) ;
|
||||
ptMin.Translate( vtIpMove) ;
|
||||
ptMax.Translate( vtIpMove) ;
|
||||
|
||||
// assegno l'ingombro
|
||||
b3Box.Set( ptMin, ptMax) ;
|
||||
|
||||
// ripristino il font originale
|
||||
SelectObject( m_hDC, hPrevFont) ;
|
||||
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
OsFont::GetOutline( const string& sText, int nInsPos, ICURVEPLIST& lstPC)
|
||||
{
|
||||
// verifico esistenza font corrente
|
||||
if ( m_hDC == nullptr || m_hFont == nullptr || m_sFont.empty())
|
||||
return false ;
|
||||
|
||||
// rendo corrente il font
|
||||
HFONT hPrevFont = (HFONT) SelectObject( m_hDC, m_hFont) ;
|
||||
if ( hPrevFont == nullptr)
|
||||
return false ;
|
||||
|
||||
// calcolo i fattori di scala
|
||||
double dScaY = m_dHeight / m_dHCap ;
|
||||
double dScaX = dScaY * m_dRatio ;
|
||||
double dScaZ = 1 ;
|
||||
|
||||
// recupero altezza maiuscole e interlinea
|
||||
double dHCap = m_dHeight ;
|
||||
double dH = m_dH * m_dHeight / m_dHCap ;
|
||||
|
||||
// converto i byte della stringa in codici carattere
|
||||
UINTVECTOR vCode ;
|
||||
GetCodePoints( sText, vCode) ;
|
||||
|
||||
// ciclo sui codici
|
||||
double dMaxW = 0 ;
|
||||
double dMinH = 0 ;
|
||||
Vector3d vtMove ;
|
||||
ICURVEPLIST lstTmpPC ;
|
||||
for ( unsigned int i = 0 ; i < vCode.size() ; ++ i) {
|
||||
// verifico se comando di a capo
|
||||
int nLbLen ;
|
||||
if ( IsLineBreak( vCode, i, nLbLen)) {
|
||||
vtMove.Set( 0, vtMove.y - dH, 0) ;
|
||||
if ( vtMove.y < dMinH)
|
||||
dMinH = vtMove.y ;
|
||||
i += nLbLen ;
|
||||
continue ;
|
||||
}
|
||||
// recupero l'outline
|
||||
double dAdvance ;
|
||||
if ( ! GetCharOutline( vCode[i], dAdvance, lstTmpPC))
|
||||
return false ;
|
||||
// lo trasformo opportunamente
|
||||
ICURVEPLIST::iterator iIter ;
|
||||
for ( iIter = lstTmpPC.begin() ; iIter != lstTmpPC.end() ; ++ iIter) {
|
||||
// trasformazioni
|
||||
(*iIter)->Scale( GLOB_FRM, dScaX, dScaY, dScaZ) ;
|
||||
(*iIter)->Translate( vtMove) ;
|
||||
// inserimento nella lista principale
|
||||
lstPC.push_back( (*iIter)) ;
|
||||
}
|
||||
vtMove += Vector3d( dAdvance * dScaX + m_dAddAdvance, 0, 0) ;
|
||||
if ( vtMove.x > dMaxW)
|
||||
dMaxW = vtMove.x ;
|
||||
// ciclo di pulizia ( non devo cancellare le curve, perchè spostate nella lista principale)
|
||||
lstTmpPC.clear() ;
|
||||
}
|
||||
|
||||
// sistemazioni per la posizione del punto di inserimento
|
||||
Vector3d vtIpMove = GetTextInsertPointMove( dMaxW, dHCap, dMinH, nInsPos) ;
|
||||
ICURVEPLIST::iterator iIter ;
|
||||
for ( iIter = lstPC.begin() ; iIter != lstPC.end() ; ++ iIter)
|
||||
(*iIter)->Translate( vtIpMove) ;
|
||||
|
||||
// ripristino il font originale
|
||||
SelectObject( m_hDC, hPrevFont) ;
|
||||
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
OsFont::ApproxWithLines( const string& sText, int nInsPos, double dLinTol, double dAngTolDeg,
|
||||
POLYLINELIST& lstPL)
|
||||
{
|
||||
// verifico esistenza font corrente
|
||||
if ( m_hDC == nullptr || m_hFont == nullptr || m_sFont.empty())
|
||||
return false ;
|
||||
|
||||
// rendo corrente il font
|
||||
HFONT hPrevFont = (HFONT) SelectObject( m_hDC, m_hFont) ;
|
||||
if ( hPrevFont == nullptr)
|
||||
return false ;
|
||||
|
||||
// calcolo i fattori di scala
|
||||
double dScaY = m_dHeight / m_dHCap ;
|
||||
double dScaX = dScaY * m_dRatio ;
|
||||
double dScaZ = 1 ;
|
||||
|
||||
// recupero altezza maiuscole e interlinea
|
||||
double dHCap = m_dHeight ;
|
||||
double dH = m_dH * m_dHeight / m_dHCap ;
|
||||
|
||||
// converto i byte della stringa in codici carattere
|
||||
UINTVECTOR vCode ;
|
||||
GetCodePoints( sText, vCode) ;
|
||||
|
||||
// ciclo sui caratteri
|
||||
double dMaxW = 0 ;
|
||||
double dMinH = 0 ;
|
||||
Vector3d vtMove ;
|
||||
ICURVEPLIST lstPC ;
|
||||
for ( unsigned int i = 0 ; i < vCode.size() ; ++ i) {
|
||||
// verifico se comando di a capo
|
||||
int nLbLen ;
|
||||
if ( IsLineBreak( vCode, i, nLbLen)) {
|
||||
vtMove.Set( 0, vtMove.y - dH, 0) ;
|
||||
if ( vtMove.y < dMinH)
|
||||
dMinH = vtMove.y ;
|
||||
i += nLbLen ;
|
||||
continue ;
|
||||
}
|
||||
// recupero l'outline
|
||||
double dAdvance ;
|
||||
if ( ! GetCharOutline( vCode[i], dAdvance, lstPC))
|
||||
return false ;
|
||||
// lo approssimo con segmenti di retta
|
||||
ICURVEPLIST::iterator iIter ;
|
||||
for ( iIter = lstPC.begin() ; iIter != lstPC.end() ; ++ iIter) {
|
||||
lstPL.push_back( PolyLine()) ;
|
||||
if ( (*iIter)->ApproxWithLines( dLinTol, dAngTolDeg, lstPL.back())) {
|
||||
lstPL.back().Scale( GLOB_FRM, dScaX, dScaY, dScaZ) ;
|
||||
lstPL.back().Translate( vtMove) ;
|
||||
}
|
||||
}
|
||||
vtMove += Vector3d( dAdvance * dScaX + m_dAddAdvance, 0, 0) ;
|
||||
if ( vtMove.x > dMaxW)
|
||||
dMaxW = vtMove.x ;
|
||||
// ciclo di pulizia
|
||||
for ( iIter = lstPC.begin() ; iIter != lstPC.end() ; ++ iIter)
|
||||
delete (*iIter) ;
|
||||
lstPC.clear() ;
|
||||
}
|
||||
|
||||
// sistemazioni per la posizione del punto di inserimento
|
||||
Vector3d vtIpMove = GetTextInsertPointMove( dMaxW, dHCap, dMinH, nInsPos) ;
|
||||
POLYLINELIST::iterator iIter ;
|
||||
for ( iIter = lstPL.begin() ; iIter != lstPL.end() ; ++ iIter)
|
||||
(*iIter).Translate( vtIpMove) ;
|
||||
|
||||
// ripristino il font originale
|
||||
SelectObject( m_hDC, hPrevFont) ;
|
||||
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
double
|
||||
DoubleFromFixed( FIXED fx)
|
||||
{
|
||||
return ( double( fx.value) + double( fx.fract) * ( 1.0 / 65536.0)) ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
FIXED
|
||||
MediaTwoFixed( FIXED fx1, FIXED fx2)
|
||||
{
|
||||
long l = 0L ;
|
||||
|
||||
l = (*((long*)&(fx1)) + *((long*)&(fx2))) / 2L ;
|
||||
|
||||
return (*(FIXED*)&l) ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
OsFont::GetCharOutline( unsigned int nChar, double& dAdvance, ICURVEPLIST& lstPC)
|
||||
{
|
||||
GLYPHMETRICS gm ;
|
||||
MAT2 mat = { {0,1},{0,0},{0,0},{0,1}} ;
|
||||
// recupero la dimensione necessaria del buffer e lo alloco
|
||||
DWORD dwSize = GetGlyphOutlineW( m_hDC, nChar, GGO_NATIVE, &gm, 0, NULL, &mat) ;
|
||||
if ( dwSize == GDI_ERROR)
|
||||
return false ;
|
||||
PtrOwner<char> pBuffer( new char[dwSize]) ;
|
||||
if ( ! ::IsValid( pBuffer))
|
||||
return false ;
|
||||
// recupero l'outline
|
||||
DWORD dErr = GetGlyphOutlineW( m_hDC, nChar, GGO_NATIVE, &gm, dwSize, ::Get( pBuffer), &mat) ;
|
||||
if ( dErr == GDI_ERROR) {
|
||||
//delete pBuffer ;
|
||||
return false ;
|
||||
}
|
||||
|
||||
// assegno l'avanzamento al prossimo carattere
|
||||
dAdvance = gm.gmCellIncX ;
|
||||
|
||||
// mentre esistono nuovi contorni
|
||||
LPTTPOLYGONHEADER pHeader = (LPTTPOLYGONHEADER) ::Get( pBuffer) ;
|
||||
while ( (LPSTR) pHeader < ( ::Get( pBuffer) + ptrdiff_t( dwSize))) {
|
||||
|
||||
// leggo un nuovo contorno
|
||||
if ( pHeader->dwType == TT_POLYGON_TYPE) {
|
||||
|
||||
// creo curva composita
|
||||
PtrOwner<ICurveComposite> pCCompo( CreateCurveComposite()) ;
|
||||
if ( ! ::IsValid( pCCompo))
|
||||
return false ;
|
||||
|
||||
// posizionamento sul punto iniziale
|
||||
Point3d ptFirst( DoubleFromFixed( pHeader->pfxStart.x),
|
||||
DoubleFromFixed( pHeader->pfxStart.y),
|
||||
0) ;
|
||||
Point3d ptLast = ptFirst ;
|
||||
|
||||
// puntatore alla prima polycurva
|
||||
LPTTPOLYCURVE pCurve = (LPTTPOLYCURVE)( pHeader + 1) ;
|
||||
|
||||
// mentre esistono polycurve
|
||||
while ( (LPSTR) pCurve < ( (LPSTR) pHeader + ptrdiff_t( pHeader->cb))) {
|
||||
// numero punti
|
||||
int nPnt = pCurve->cpfx ;
|
||||
// se rette
|
||||
if ( pCurve->wType == TT_PRIM_LINE) {
|
||||
for ( int i = 0 ; i < nPnt ; ++ i ) {
|
||||
Point3d ptP( DoubleFromFixed( pCurve->apfx[i].x),
|
||||
DoubleFromFixed( pCurve->apfx[i].y),
|
||||
0) ;
|
||||
if ( ! AreSamePointNear( ptLast, ptP)) {
|
||||
// aggiungo la retta alla curva composita
|
||||
if ( ! AddLineToCompo( ::Get( pCCompo), ptLast, ptP))
|
||||
return false ;
|
||||
// salvo punto come ultimo
|
||||
ptLast = ptP ;
|
||||
}
|
||||
}
|
||||
}
|
||||
// se curve di Bezier quadratiche
|
||||
else if ( pCurve->wType == TT_PRIM_QSPLINE) {
|
||||
for ( int i = 0 ; i < nPnt - 1 ; ++ i ) {
|
||||
// punto medio CBezier
|
||||
Point3d ptM( DoubleFromFixed( pCurve->apfx[i].x),
|
||||
DoubleFromFixed( pCurve->apfx[i].y),
|
||||
0) ;
|
||||
// punto finale CBezier
|
||||
POINTFX pfEnd ;
|
||||
// se non è alla fine è il medio dei due punti adiacenti del poligono
|
||||
if ( i < ( nPnt - 2)) {
|
||||
pfEnd.x = MediaTwoFixed( pCurve->apfx[i].x, pCurve->apfx[i+1].x) ;
|
||||
pfEnd.y = MediaTwoFixed( pCurve->apfx[i].y, pCurve->apfx[i+1].y) ;
|
||||
}
|
||||
else
|
||||
pfEnd = pCurve->apfx[i+1] ;
|
||||
Point3d ptE( DoubleFromFixed( pfEnd.x),
|
||||
DoubleFromFixed( pfEnd.y),
|
||||
0) ;
|
||||
// aggiungo la curva di Bezier quadratica alla curva composita
|
||||
if ( ! AddCBezierQuadToCompo( ::Get( pCCompo), ptLast, ptM, ptE))
|
||||
return false ;
|
||||
// salvo punto finale come ultimo
|
||||
ptLast = ptE ;
|
||||
}
|
||||
}
|
||||
// altrimenti errore
|
||||
else {
|
||||
return false ;
|
||||
}
|
||||
// si passa alla polycurva successiva
|
||||
pCurve = (LPTTPOLYCURVE) &( pCurve->apfx[nPnt]) ;
|
||||
}
|
||||
// si aggiunge, se necessario, una linea retta per chiudere la curva
|
||||
if ( ! AreSamePointNear( ptFirst, ptLast)) {
|
||||
// aggiungo la retta alla curva composita
|
||||
if ( ! AddLineToCompo( ::Get( pCCompo), ptLast, ptFirst))
|
||||
return false ;
|
||||
// salvo ultimo punto
|
||||
ptLast = ptFirst ;
|
||||
}
|
||||
// se curva composita ok, la inserisco in lista
|
||||
if ( pCCompo->IsValid())
|
||||
lstPC.push_back( ::Release( pCCompo)) ;
|
||||
}
|
||||
// mi sposto sul prossimo contorno
|
||||
pHeader = (LPTTPOLYGONHEADER) ( (LPSTR) pHeader + ptrdiff_t( pHeader->cb)) ;
|
||||
}
|
||||
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
OsFont::AddLineToCompo( ICurveComposite* pCCompo, const Point3d& ptStart, const Point3d& ptEnd)
|
||||
{
|
||||
// verifico curva composita
|
||||
if ( pCCompo == nullptr)
|
||||
return false ;
|
||||
|
||||
// creo retta, la imposto e la inserisco nella curva composita
|
||||
PtrOwner<ICurveLine> pCLine( CreateCurveLine()) ;
|
||||
if ( ! ::IsValid( pCLine))
|
||||
return false ;
|
||||
if ( ! pCLine->Set( ptStart, ptEnd))
|
||||
return false ;
|
||||
if ( ! pCCompo->AddCurve( ::Release( pCLine)))
|
||||
return false ;
|
||||
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
OsFont::AddCBezierQuadToCompo( ICurveComposite* pCCompo,
|
||||
const Point3d& ptStart, const Point3d& ptMid, const Point3d& ptEnd)
|
||||
{
|
||||
// verifico curva composita
|
||||
if ( pCCompo == nullptr)
|
||||
return false ;
|
||||
|
||||
// creo curva di Bezier quadratica, la imposto e la inserisco nella curva composita
|
||||
PtrOwner<ICurveBezier> pCBezier( CreateCurveBezier()) ;
|
||||
if ( ! ::IsValid( pCBezier))
|
||||
return false ;
|
||||
if ( ! pCBezier->Init( 2, false) ||
|
||||
! pCBezier->SetControlPoint( 0, ptStart) ||
|
||||
! pCBezier->SetControlPoint( 1, ptMid) ||
|
||||
! pCBezier->SetControlPoint( 2, ptEnd))
|
||||
return false ;
|
||||
if ( ! pCCompo->AddCurve( ::Release( pCBezier)))
|
||||
return false ;
|
||||
|
||||
return true ;
|
||||
}
|
||||
Reference in New Issue
Block a user