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

📄 char.cpp

📁 Trolltech公司发布的图形界面操作系统。可在qt-embedded-2.3.10平台上编译为嵌入式图形界面操作系统。
💻 CPP
字号:
/************************************************************************ Copyright (C) 2000-2005 Trolltech AS.  All rights reserved.**** This file is part of the Qtopia Environment.** ** 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.** ** A copy of the GNU GPL license version 2 is included in this package as ** LICENSE.GPL.**** This program is distributed in the hope that it will be useful, but** WITHOUT ANY WARRANTY; without even the implied warranty of** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. ** See the GNU General Public License for more details.**** In addition, as a special exception Trolltech gives permission to link** the code of this program with Qtopia applications copyrighted, developed** and distributed by Trolltech under the terms of the Qtopia Personal Use** License Agreement. You must comply with the GNU General Public License** in all respects for all of the code used other than the applications** licensed under the Qtopia Personal Use License Agreement. If you modify** this file, you may extend this exception to your version of the file,** but you are not obligated to do so. If you do not wish to do so, delete** this exception statement from your version.** ** 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>#ifdef Q_WS_QWS#include <qtopia/qpeapplication.h>#include <qtopia/global.h>#else#include <qapplication.h>#endif#include "combining.h"#include "char.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::NextWord,	QT_TRANSLATE_NOOP("Handwriting","[Next Word]") },    { QIMPenChar::WordPopup,	QT_TRANSLATE_NOOP("Handwriting","[Word Menu]") }, // word popup    { QIMPenChar::SymbolPopup,	QT_TRANSLATE_NOOP("Handwriting","[Symbol Menu]") },    { QIMPenChar::ModePopup,	QT_TRANSLATE_NOOP("Handwriting","[Mode Menu]") },    { Qt::Key_unknown,	        0 } };/*!  \class QIMPenChar char.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;    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;    QIMPenStrokeIterator it( chr.strokes );    while ( it.current() ) {        strokes.append( new QIMPenStroke( *it.current() ) );        ++it;    }    return *this;}QString QIMPenChar::name() const{    return name(ch);}QString QIMPenChar::name(unsigned int ch){    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;    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;    /* currently the multi-stroke gravity checks are not       canvas height dependent, they should be */    while ( err < 400000 && it1.current() && it2.current() ) {	// the difference between the center of this stroke	// and the center of the first stroke.        QPoint p1 = it1.current()->boundingRect().center() -		    strokes.getFirst()->boundingRect().center();	// scale to canvas height	p1 = p1 * 75 / it1.current()->canvasHeight();	// the difference between the center of this stroke	// and the center of the first stroke.        QPoint p2 = it2.current()->boundingRect().center() -		    pen->strokes.getFirst()->boundingRect().center();	// scale to canvas height	p1 = p1 * 75 / it1.current()->canvasHeight();        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;    // never write data, its old hat.    if ( ws.flags & QIMPenChar::Data )	s << (ws.flags ^ QIMPenChar::Data);    else 	s << ws.flags;    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 ) {	QString d;	s >> d;	// then throw away.    }    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"; // No tr;    csType = Unknown;    maxStrokes = 0;    load( fn );}void QIMPenCharSet::clear(){    if (count() > 0) {	chars.clear();    }}void QIMPenCharSet::setDescription( const QString &d ){    if (d != desc) {	desc = d;    }}void QIMPenCharSet::setTitle( const QString &t ){    if (t != csTitle) {	csTitle = t;    }}void QIMPenCharSet::setType( Type t ){    if (t != csType) {	csType = t;    }}const QString &QIMPenCharSet::filename( ) const{    return userFilename;}void QIMPenCharSet::setFilename( const QString &fn ){    if (fn != userFilename) {	userFilename = fn;    }}#ifdef Q_WS_QWSQString QIMPenCharSet::systemPath( ) const{    static const QString sysPath(QPEApplication::qpeDir() + "etc/qimpen/"); // no tr    return sysPath + userFilename;}QString QIMPenCharSet::userPath() const{    return Global::applicationFileName("qimpen",userFilename); // no tr}#endif/*!  Load a character set from file \a fn, in the domain \a d.*/bool QIMPenCharSet::load( const QString &fn ){    clear();    if (!fn.isEmpty())	setFilename( fn );    bool ok = FALSE;#ifdef Q_WS_QWS    for (int isUser = 0; isUser < 2; ++isUser) {	QString path;	if (isUser == 1)	    path = userPath();	else	    path = systemPath();#else	QString path = fn;#endif	QFile file( path );	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" ) // no tr		    csType = Lower;		else if ( csTitle == "ABC" ) // no tr		    csType = Upper;		else if ( csTitle == "123" ) // no tr		    csType = Numeric;		else if ( fn == "Combining" ) // No tr		    csType = Combining;	    }	    while ( !ds.atEnd() ) {		QIMPenChar *pc = new QIMPenChar;		ds >> *pc;#ifdef Q_WS_QWS		if ( isUser == 1 )#endif		    markDeleted( pc->character() ); // override system		addChar( pc );	    }	    if ( file.status() == IO_Ok )		ok = TRUE;	}#ifdef Q_WS_QWS    }#endif    return ok;}/*!  Save this character set, in the domain \a d.*/bool QIMPenCharSet::save( ) const{    bool ok = FALSE;#ifdef Q_WS_QWS    QString fn = userPath();#else    QString fn = userFilename;#endif    QString tmpFn = fn + ".new"; // no tr    QFile file( tmpFn );    if ( file.open( IO_WriteOnly|IO_Raw ) ) {        QDataStream ds( &file );	ds << QString( "QPT 1.1" ); // no tr        ds << csTitle;        ds << desc;	ds << (Q_INT8)csType;        QIMPenCharIterator ci( chars );        for ( ; ci.current(); ++ci ) {	    QIMPenChar *pc = ci.current();#ifdef Q_WS_QWS	    // only save user char's, not system char's.	    if ( !pc->testFlag( QIMPenChar::System ) ) {		ds << *pc;	    }#else		ds << *pc;#endif	    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 each character in set.    for ( ; ci.current(); ++ci ) {	QIMPenChar *tmplChar = ci.current();        if ( tmplChar->testFlag( QIMPenChar::Deleted ) ) {            continue;        }	int err;	// if the stroke to match against has equal or less strokes	if ( ch->penStrokes().count() <= tmplChar->penStrokes().count() ) {	    // check how well it matches, 	    err = ch->match( tmplChar );	    // and if it is less than the threshold	    if ( err <= QIMPEN_MATCH_THRESHOLD ) {		// compare stroke count again		if (tmplChar->penStrokes().count() != ch->penStrokes().count())		    err = QMIN(err*3, QIMPEN_MATCH_THRESHOLD);		QIMPenCharMatchList::Iterator it;		// Correct the error if an existing char match		// has greater error (e.g. two ways of writing 'a')		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 this char isn't already a match		if ( it == matches.end() ) {		    // add it as a match		    QIMPenCharMatch m;		    m.error = err;		    m.penChar = tmplChar;		    matches.append( m );		}	    }	}    }    // sort and return.    qHeapSort( matches );    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 + -