diff options
Diffstat (limited to 'kpovmodeler/pmtext.cpp')
-rw-r--r-- | kpovmodeler/pmtext.cpp | 339 |
1 files changed, 339 insertions, 0 deletions
diff --git a/kpovmodeler/pmtext.cpp b/kpovmodeler/pmtext.cpp new file mode 100644 index 00000000..21191cbc --- /dev/null +++ b/kpovmodeler/pmtext.cpp @@ -0,0 +1,339 @@ +/* +************************************************************************** + description + -------------------- + copyright : (C) 2002 by Andreas Zehender + email : zehender@kde.org +************************************************************************** + +************************************************************************** +* * +* This program is free software; you can redistribute it and/or modify * +* it under the terms of the GNU General Public License as published by * +* the Free Software Foundation; either version 2 of the License, or * +* (at your option) any later version. * +* * +**************************************************************************/ + + +#include "pmtext.h" + +#include "pmxmlhelper.h" +#include "pmtextedit.h" +#include "pmmemento.h" +#include "pmviewstructure.h" +#include "pmresourcelocator.h" +#include "pmtruetypecache.h" +#include "pmdefaults.h" + +#include <klocale.h> + +const QString c_defaultFont = QString( "" ); +const QString c_defaultText = QString( "" ); +const double c_defaultThickness = 1.0; +const PMVector c_defaultOffset = PMVector( 0.0, 0.0 ); + +int PMText::s_parameterKey = 0; +int PMText::s_steps = c_defaultTextSteps; + +PMDefinePropertyClass( PMText, PMTextProperty ); + +PMMetaObject* PMText::s_pMetaObject = 0; +PMObject* createNewText( PMPart* part ) +{ + return new PMText( part ); +} + +PMText::PMText( PMPart* part ) + : Base( part ) +{ + m_text = c_defaultText; + m_font = c_defaultFont; + m_thickness = c_defaultThickness; + m_offset = c_defaultOffset; +} + +PMText::PMText( const PMText& t ) + : Base( t ) +{ + m_text = t.m_text; + m_font = t.m_font; + m_thickness = t.m_thickness; + m_offset = t.m_offset; +} + +PMText::~PMText( ) +{ +} + +QString PMText::description( ) const +{ + return i18n( "text" ); +} + +void PMText::serialize( QDomElement& e, QDomDocument& doc ) const +{ + e.setAttribute( "font", m_font ); + e.setAttribute( "text", m_text ); + e.setAttribute( "thickness", m_thickness ); + e.setAttribute( "offset", m_offset.serializeXML( ) ); + Base::serialize( e, doc ); +} + +void PMText::readAttributes( const PMXMLHelper& h ) +{ + m_font = h.stringAttribute( "font", c_defaultFont ); + m_text = h.stringAttribute( "text", c_defaultText ); + m_thickness = h.doubleAttribute( "thickness", c_defaultThickness ); + m_offset = h.vectorAttribute( "offset", c_defaultOffset ); + Base::readAttributes( h ); +} + +PMMetaObject* PMText::metaObject( ) const +{ + if( !s_pMetaObject ) + { + s_pMetaObject = new PMMetaObject( "Text", Base::metaObject( ), + createNewText ); + s_pMetaObject->addProperty( + new PMTextProperty( "font", &PMText::setFont, &PMText::font ) ); + s_pMetaObject->addProperty( + new PMTextProperty( "text", &PMText::setText, &PMText::text ) ); + s_pMetaObject->addProperty( + new PMTextProperty( "thickness", &PMText::setThickness, &PMText::thickness ) ); + s_pMetaObject->addProperty( + new PMTextProperty( "offset", &PMText::setOffset, &PMText::offset ) ); + } + return s_pMetaObject; +} + +void PMText::cleanUp( ) const +{ + if( s_pMetaObject ) + { + delete s_pMetaObject; + s_pMetaObject = 0; + } + Base::cleanUp( ); +} + +void PMText::setFont( const QString& f ) +{ + if( f != m_font ) + { + if( m_pMemento ) + m_pMemento->addData( s_pMetaObject, PMFontID, m_font ); + m_font = f; + setViewStructureChanged( ); + } +} + +void PMText::setText( const QString& t ) +{ + if( t != m_text ) + { + if( m_pMemento ) + m_pMemento->addData( s_pMetaObject, PMTextID, m_text ); + m_text = t; + setViewStructureChanged( ); + } +} + +void PMText::setThickness( double t ) +{ + if( t != m_thickness ) + { + if( m_pMemento ) + m_pMemento->addData( s_pMetaObject, PMThicknessID, m_thickness ); + m_thickness = t; + setViewStructureChanged( ); + } +} + +void PMText::setOffset( const PMVector& o ) +{ + if( o != m_offset ) + { + if( m_pMemento ) + m_pMemento->addData( s_pMetaObject, PMOffsetID, m_offset ); + m_offset = o; + m_offset.resize( 2 ); + setViewStructureChanged( ); + } +} + +PMDialogEditBase* PMText::editWidget( QWidget* parent ) const +{ + return new PMTextEdit( parent ); +} + +void PMText::restoreMemento( PMMemento* s ) +{ + PMMementoDataIterator it( s ); + PMMementoData* data; + + for( ; it.current( ); ++it ) + { + data = it.current( ); + if( data->objectType( ) == s_pMetaObject ) + { + switch( data->valueID( ) ) + { + case PMFontID: + setFont( data->stringData( ) ); + break; + case PMTextID: + setText( data->stringData( ) ); + break; + case PMThicknessID: + setThickness( data->doubleData( ) ); + break; + case PMOffsetID: + setOffset( data->vectorData( ) ); + break; + default: + kdError( PMArea ) << "Wrong ID in PMText::restoreMemento\n"; + break; + } + } + } + Base::restoreMemento( s ); +} + +void PMText::createViewStructure( ) +{ + // calculate needed points and lines + int nlines = 0, npoints = 0; + + QString file = PMResourceLocator::findFile( m_font ); + PMTrueTypeFont* font = PMTrueTypeCache::font( file ); + + if( font && font->isValid( ) ) + { + QTextStream str( &m_text, IO_ReadOnly ); + QChar c; + PMTrueTypeOutline* ol; + + while( !str.atEnd( ) ) + { + str >> c; + ol = font->outline( c ); + if( ol ) + { + npoints += ol->segments( ) * 2 * s_steps; + nlines += ol->segments( ) * ( 2 * s_steps + 1 ); + } + } + } + + if( !m_pViewStructure ) + m_pViewStructure = new PMViewStructure( npoints, nlines ); + else + { + if( m_pViewStructure->points( ).size( ) != ( unsigned ) npoints ) + m_pViewStructure->points( ).resize( npoints ); + if( m_pViewStructure->lines( ).size( ) != ( unsigned ) nlines ) + m_pViewStructure->lines( ).resize( nlines ); + } + + if( ( nlines > 0 ) && ( npoints > 0 ) && font ) + { + // create the view structure + QTextStream str( &m_text, IO_ReadOnly ); + QChar c, oldc; + PMTrueTypeOutline* ol; + double dp = 1.0 / s_steps; + int i; + int hnpoints = npoints / 2; + int pbase = 0; + int lbase = 0; + PMVector v2( 2 ); + PMVector v3( 3 ); + int firstPoint = 0; + PMVector coffset( 0.0, 0.0, 0.0 ); + double kerning = 0; + + PMPointArray& points = m_pViewStructure->points( ); + PMLineArray& lines = m_pViewStructure->lines( ); + + while( !str.atEnd( ) ) + { + // iterate over all characters with valid outline + + str >> c; + ol = font->outline( c ); + if( ol ) + { + // kerning offset + kerning = font->kerning( oldc, c ); + coffset[0] += kerning; + + const PMSegmentListList& out = ol->outline( ); + PMSegmentListList::ConstIterator oit; + for( oit = out.begin( ); oit != out.end( ); ++oit ) + { + // iterate over all contours + + PMSegmentList::ConstIterator sit; + PMSegmentList::ConstIterator eit = ( *oit ).end( ); + eit--; + + firstPoint = pbase; + for( sit = ( *oit ).begin( ); sit != ( *oit ).end( ); ++sit ) + { + // iterate over all segments for the current contour + + lines[lbase] = PMLine( pbase, pbase + hnpoints ); + lbase++; + + for( i = 0; i < s_steps; i++ ) + { + v2 = ( *sit ).point( i * dp ); + v3[0] = v2[0]; + v3[1] = v2[1]; + v3[2] = 0.0; + v3 += coffset; + points[pbase] = PMPoint( v3 ); + v3[2] = m_thickness; + points[pbase + hnpoints] = PMPoint( v3 ); + + if( ( i != ( s_steps - 1 ) ) || ( sit != eit ) ) + { + lines[lbase] = PMLine( pbase, pbase + 1 ); + lbase++; + lines[lbase] = PMLine( pbase + hnpoints, + pbase + hnpoints + 1 ); + lbase++; + } + else + { + lines[lbase] = PMLine( firstPoint, pbase ); + lbase++; + lines[lbase] = PMLine( firstPoint + hnpoints, + pbase + hnpoints ); + lbase++; + } + + pbase++; + } + } + } + coffset[0] -= kerning; + coffset[0] += ol->advance( ); + coffset += m_offset; + } + oldc = c; + } + if( ( lbase != nlines ) || ( pbase != hnpoints ) ) + kdError( PMArea ) << "PMText::createViewStructure is buggy!\n"; + } +} + +void PMText::setSteps( int s ) +{ + if( s >= 1 ) + s_steps = s; + else + kdDebug( PMArea ) << "PMText::setSteps: S must be greater than 0\n"; + s_parameterKey++; +} |