⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 qimpenchar.cpp

📁 Trolltech公司发布的图形界面操作系统。可在qt-embedded-2.3.7平台上编译为嵌入式图形界面操作系统。
💻 CPP
字号:
/************************************************************************ Copyright (C) 2000-2002 Trolltech AS.  All rights reserved.**** This file is part of the Qtopia Environment.**** This file may be distributed and/or modified under the terms of the** GNU General Public License version 2 as published by the Free Software** Foundation and appearing in the file LICENSE.GPL included in the** packaging of this file.**** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.**** See http://www.trolltech.com/gpl/ for GPL licensing information.**** Contact info@trolltech.com if any conditions of this licensing are** not clear to you.************************************************************************/#include <qfile.h>#include <qtl.h>#include <math.h>#include <limits.h>#include <errno.h>#include <qdatastream.h>#include <qapplication.h>#include "qimpencombining.h"#include "qimpenchar.h"#define QIMPEN_MATCH_THRESHOLD	    200000const QIMPenSpecialKeys qimpen_specialKeys[] = {    { Qt::Key_Escape,		QT_TRANSLATE_NOOP("Handwriting","[Esc]") },    { Qt::Key_Tab,		QT_TRANSLATE_NOOP("Handwriting","[Tab]") },    { Qt::Key_Backspace,	QT_TRANSLATE_NOOP("Handwriting","[BackSpace]") },    { Qt::Key_Return,		QT_TRANSLATE_NOOP("Handwriting","[Return]") },    { QIMPenChar::Caps,		QT_TRANSLATE_NOOP("Handwriting","[Uppercase]") },    { QIMPenChar::CapsLock,	QT_TRANSLATE_NOOP("Handwriting","[Caps Lock]") },    { QIMPenChar::Shortcut,	QT_TRANSLATE_NOOP("Handwriting","[Shortcut]") },    { QIMPenChar::Punctuation,  QT_TRANSLATE_NOOP("Handwriting","[Punctuation]") },    { QIMPenChar::Symbol,	QT_TRANSLATE_NOOP("Handwriting","[Symbol]") },    { QIMPenChar::Extended,	QT_TRANSLATE_NOOP("Handwriting","[Extended]") },    { Qt::Key_unknown,	        0 } };/*!  \class QIMPenChar qimpenchar.h  \brief The QIMPenChar class handles a single character.  Can calculate closeness of match to  another character.*/QIMPenChar::QIMPenChar(){    flags = 0;    strokes.setAutoDelete( TRUE );}QIMPenChar::QIMPenChar( const QIMPenChar &chr ){    strokes.setAutoDelete( TRUE );    ch = chr.ch;    flags = chr.flags;    d = chr.d;    QIMPenStrokeIterator it( chr.strokes );    while ( it.current() ) {        strokes.append( new QIMPenStroke( *it.current() ) );        ++it;    }}QIMPenChar &QIMPenChar::operator=( const QIMPenChar &chr ){    strokes.clear();    ch = chr.ch;    flags = chr.flags;    d = chr.d;    QIMPenStrokeIterator it( chr.strokes );    while ( it.current() ) {        strokes.append( new QIMPenStroke( *it.current() ) );        ++it;    }    return *this;}QString QIMPenChar::name() const{    QString n;    if ( (ch & 0x0000FFFF) == 0 ) {	int code = ch >> 16;	for ( int i = 0; qimpen_specialKeys[i].code != Qt::Key_unknown; i++ ) {	    if ( qimpen_specialKeys[i].code == code ) {		n = qApp->translate("Handwriting", qimpen_specialKeys[i].name);		break;	    }	}    } else {	n = QChar( ch & 0x0000FFFF );    }    return n;}void QIMPenChar::clear(){    ch = 0;    flags = 0;    d = QString::null;    strokes.clear();}unsigned int QIMPenChar::strokeLength( int s ) const{    QIMPenStrokeIterator it( strokes );    while ( it.current() && s ) {	++it;	--s;    }    if ( it.current() )	return it.current()->length();    return 0;}/*!  Add a stroke, \a st, to the character*/void QIMPenChar::addStroke( QIMPenStroke *st ){    QIMPenStroke *stroke = new QIMPenStroke( *st );    strokes.append( stroke );}/*!  Return an indicator of the closeness of this character to \a pen.  Lower value is better.*/int QIMPenChar::match( QIMPenChar *pen ){/*    if ( strokes.count() > pen->strokes.count() )        return INT_MAX;*/    int err = 0;    int maxErr = 0;    int diff = 0;    QIMPenStrokeIterator it1( strokes );    QIMPenStrokeIterator it2( pen->strokes );    err = it1.current()->match( it2.current() );    if ( err > maxErr )	maxErr = err;    ++it1;    ++it2;    while ( err < 400000 && it1.current() && it2.current() ) {        QPoint p1 = it1.current()->boundingRect().center() -		    strokes.getFirst()->boundingRect().center();        QPoint p2 = it2.current()->boundingRect().center() -		    pen->strokes.getFirst()->boundingRect().center();        int xdiff = QABS( p1.x() - p2.x() ) - 6;        int ydiff = QABS( p1.y() - p2.y() ) - 5;	if ( xdiff < 0 )	    xdiff = 0;	if ( ydiff < 0 )	    ydiff = 0;	if ( xdiff > 10 || ydiff > 10 ) { // not a chance#ifdef DEBUG_QIMPEN	    qDebug( "char %c, stroke starting pt diff excessive", pen->ch );#endif	    return INT_MAX;	}        diff += xdiff*xdiff + ydiff*ydiff;	err = it1.current()->match( it2.current() );	if ( err > maxErr )	    maxErr = err;        ++it1;        ++it2;    }    maxErr += diff * diff * 6; // magic weighting :)#ifdef DEBUG_QIMPEN    qDebug( "char: %c, maxErr %d, diff %d, (%d)", pen->ch, maxErr, diff, strokes.count() );#endif    return maxErr;}/*!  Return the bounding rect of this character.  It may have sides with  negative coords since its origin is where the user started drawing  the character.*/QRect QIMPenChar::boundingRect(){    QRect br;    QIMPenStroke *st = strokes.first();    while ( st ) {        br |= st->boundingRect();        st = strokes.next();    }    return br;}/*!  Write the character's data to the stream.*/QDataStream &operator<< (QDataStream &s, const QIMPenChar &ws){    s << ws.ch;    s << ws.flags;    if ( ws.flags & QIMPenChar::Data )	s << ws.d;    s << ws.strokes.count();    QIMPenStrokeIterator it( ws.strokes );    while ( it.current() ) {        s << *it.current();        ++it;    }    return s;}/*!  Read the character's data from the stream.*/QDataStream &operator>> (QDataStream &s, QIMPenChar &ws){    s >> ws.ch;    s >> ws.flags;    if ( ws.flags & QIMPenChar::Data )	s >> ws.d;    unsigned size;    s >> size;    for ( unsigned i = 0; i < size; i++ ) {        QIMPenStroke *st = new QIMPenStroke();        s >> *st;        ws.strokes.append( st );    }    return s;}//===========================================================================bool QIMPenCharMatch::operator>( const QIMPenCharMatch &m ){    return error > m.error;}bool QIMPenCharMatch::operator<( const QIMPenCharMatch &m ){    return error < m.error;}bool QIMPenCharMatch::operator<=( const QIMPenCharMatch &m ){    return error <= m.error;}//===========================================================================/*!  \class QIMPenCharSet qimpenchar.h  \brief The QIMPenCharSet class maintains a set of related characters.*/QIMPenCharSet::QIMPenCharSet(){    chars.setAutoDelete( TRUE );    desc = qApp->translate("Handwriting","Unnamed","Character set name");    csTitle = "abc";    csType = Unknown;    maxStrokes = 0;}/*!  Construct and load a characters set from file \a fn.*/QIMPenCharSet::QIMPenCharSet( const QString &fn ){    chars.setAutoDelete( TRUE );    desc = qApp->translate("Handwriting","Unnamed","Character set name");    csTitle = "abc";    csType = Unknown;    maxStrokes = 0;    load( fn, System );}const QString &QIMPenCharSet::filename( Domain d ) const{    if ( d == System )	return sysFilename;    else	return userFilename;}void QIMPenCharSet::setFilename( const QString &fn, Domain d ){    if ( d == System )	sysFilename = fn;    else if ( d == User )	userFilename = fn;}/*!  Load a character set from file \a fn, in the domain \a d.*/bool QIMPenCharSet::load( const QString &fn, Domain d ){    setFilename( fn, d );    bool ok = FALSE;    QFile file( fn );    if ( file.open( IO_ReadOnly ) ) {        QDataStream ds( &file );	QString version;	ds >> version;        ds >> csTitle;        ds >> desc;	int major = version.mid( 4, 1 ).toInt();	int minor = version.mid( 6 ).toInt();	if ( major >= 1 && minor > 0 ) {	    ds >> (Q_INT8 &)csType;	} else {	    if ( csTitle == "abc" )		csType = Lower;	    else if ( csTitle == "ABC" )		csType = Upper;	    else if ( csTitle == "123" )		csType = Numeric;	    else if ( fn == "Combining" ) // No tr		csType = Combining;	}        while ( !ds.atEnd() ) {            QIMPenChar *pc = new QIMPenChar;            ds >> *pc;	    if ( d == User )		markDeleted( pc->character() ); // override system            addChar( pc );        }	if ( file.status() == IO_Ok )	    ok = TRUE;    }    return ok;}/*!  Save this character set, in the domain \a d.*/bool QIMPenCharSet::save( Domain d ){    if ( filename( d ).isEmpty() )        return FALSE;    bool ok = FALSE;    QString fn = filename( d );    QString tmpFn = fn + ".new";    QFile file( tmpFn );    if ( file.open( IO_WriteOnly|IO_Raw ) ) {        QDataStream ds( &file );	ds << QString( "QPT 1.1" );        ds << csTitle;        ds << desc;	ds << (Q_INT8)csType;        QIMPenCharIterator ci( chars );        for ( ; ci.current(); ++ci ) {	    QIMPenChar *pc = ci.current();	    if ( ( (d == System) && pc->testFlag( QIMPenChar::System ) ) ||		 ( (d == User) && !pc->testFlag( QIMPenChar::System ) ) ) {		ds << *pc;	    }	    if ( file.status() != IO_Ok )		break;        }	if ( file.status() == IO_Ok )	    ok = TRUE;    }    if ( ok ) {	if ( ::rename( tmpFn.latin1(), fn.latin1() ) < 0 ) {	    qWarning( "problem renaming file %s to %s, errno: %d",		    tmpFn.latin1(), fn.latin1(), errno );	    // remove the tmp file, otherwise, it will just lay around...	    QFile::remove( tmpFn.latin1() );	    ok = FALSE;	}    }    return ok;}QIMPenChar *QIMPenCharSet::at( int i ){    return chars.at(i);}void QIMPenCharSet::markDeleted( uint ch ){    QIMPenCharIterator ci( chars );    for ( ; ci.current(); ++ci ) {	QIMPenChar *pc = ci.current();	if ( pc->character() == ch && pc->testFlag( QIMPenChar::System ) )	    pc->setFlag( QIMPenChar::Deleted );    }}/*!  Find the best matches for \a ch in this character set.*/QIMPenCharMatchList QIMPenCharSet::match( QIMPenChar *ch ){    QIMPenCharMatchList matches;    QIMPenCharIterator ci( chars );    for ( ; ci.current(); ++ci ) {	QIMPenChar *tmplChar = ci.current();        if ( tmplChar->testFlag( QIMPenChar::Deleted ) ) {            continue;        }	int err;	if ( ch->penStrokes().count() <= tmplChar->penStrokes().count() ) {	    err = ch->match( tmplChar );	    if ( err <= QIMPEN_MATCH_THRESHOLD ) {		if (tmplChar->penStrokes().count() != ch->penStrokes().count())		    err = QMIN(err*3, QIMPEN_MATCH_THRESHOLD);		QIMPenCharMatchList::Iterator it;		for ( it = matches.begin(); it != matches.end(); ++it ) {		    if ( (*it).penChar->character() == tmplChar->character() &&			 (*it).penChar->penStrokes().count() == tmplChar->penStrokes().count() ) {			if ( (*it).error > err )			    (*it).error = err;			break;		    }		}		if ( it == matches.end() ) {		    QIMPenCharMatch m;		    m.error = err;		    m.penChar = tmplChar;		    matches.append( m );		}	    }	}    }    qHeapSort( matches );/*    QIMPenCharMatchList::Iterator it;    for ( it = matches.begin(); it != matches.end(); ++it ) {	qDebug( "Match: \'%c\', error %d, strokes %d", (*it).penChar->character(),				(*it).error, (*it).penChar->penStrokes().count() );    }*/    return matches;}/*!  Add a character \a ch to this set.  QIMPenCharSet will delete this character when it is no longer needed.*/void QIMPenCharSet::addChar( QIMPenChar *ch ){    if ( ch->penStrokes().count() > maxStrokes )        maxStrokes = ch->penStrokes().count();    chars.append( ch );}/*!  Remove a character by reference \a ch from this set.  QIMPenCharSet will delete this character.*/void QIMPenCharSet::removeChar( QIMPenChar *ch ){    chars.remove( ch );}/*!  Move the character \a ch up the list of characters.*/void QIMPenCharSet::up( QIMPenChar *ch ){    int idx = chars.findRef( ch );    if ( idx > 0 ) {        chars.take();        chars.insert( idx - 1, ch );    }}/*!  Move the character \a ch down the list of characters.*/void QIMPenCharSet::down( QIMPenChar *ch ){    int idx = chars.findRef( ch );    if ( idx >= 0 && idx < (int)chars.count() - 1 ) {        chars.take();        chars.insert( idx + 1, ch );    }}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -