summaryrefslogtreecommitdiff
path: root/inputmethods/handwriting/qimpenchar.cpp
Unidiff
Diffstat (limited to 'inputmethods/handwriting/qimpenchar.cpp') (more/less context) (ignore whitespace changes)
-rw-r--r--inputmethods/handwriting/qimpenchar.cpp9
1 files changed, 5 insertions, 4 deletions
diff --git a/inputmethods/handwriting/qimpenchar.cpp b/inputmethods/handwriting/qimpenchar.cpp
index 929f370..db5d135 100644
--- a/inputmethods/handwriting/qimpenchar.cpp
+++ b/inputmethods/handwriting/qimpenchar.cpp
@@ -1,76 +1,77 @@
1/********************************************************************** 1/**********************************************************************
2 ** Copyright (C) 2000 Trolltech AS. All rights reserved. 2 ** Copyright (C) 2000 Trolltech AS. All rights reserved.
3 ** 3 **
4 ** This file is part of Qtopia Environment. 4 ** This file is part of Qtopia Environment.
5 ** 5 **
6 ** This file may be distributed and/or modified under the terms of the 6 ** This file may be distributed and/or modified under the terms of the
7 ** GNU General Public License version 2 as published by the Free Software 7 ** GNU General Public License version 2 as published by the Free Software
8 ** Foundation and appearing in the file LICENSE.GPL included in the 8 ** Foundation and appearing in the file LICENSE.GPL included in the
9 ** packaging of this file. 9 ** packaging of this file.
10 ** 10 **
11 ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE 11 ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
12 ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 12 ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
13 ** 13 **
14 ** See http://www.trolltech.com/gpl/ for GPL licensing information. 14 ** See http://www.trolltech.com/gpl/ for GPL licensing information.
15 ** 15 **
16 ** Contact info@trolltech.com if any conditions of this licensing are 16 ** Contact info@trolltech.com if any conditions of this licensing are
17 ** not clear to you. 17 ** not clear to you.
18 ** 18 **
19 **********************************************************************/ 19 **********************************************************************/
20 20
21#include <qfile.h> 21#include <qfile.h>
22#include <qtl.h> 22#include <qtl.h>
23#include <math.h> 23#include <math.h>
24#include <limits.h> 24#include <limits.h>
25#include <errno.h> 25#include <errno.h>
26#include <qdatastream.h> 26#include <qdatastream.h>
27#include "qimpencombining.h" 27#include "qimpencombining.h"
28#include "qimpenchar.h" 28#include "qimpenchar.h"
29#include "opie2/odebug.h"
29 30
30 #define QIMPEN_MATCH_THRESHOLD 200000 31 #define QIMPEN_MATCH_THRESHOLD 200000
31 32
32const QIMPenSpecialKeys qimpen_specialKeys[] = { 33const QIMPenSpecialKeys qimpen_specialKeys[] = {
33 { Qt::Key_Escape, "[Esc]" }, 34 { Qt::Key_Escape, "[Esc]" },
34 { Qt::Key_Tab, "[Tab]" }, 35 { Qt::Key_Tab, "[Tab]" },
35 { Qt::Key_Backspace,"[BackSpace]" }, 36 { Qt::Key_Backspace,"[BackSpace]" },
36 { Qt::Key_Return, "[Return]" }, 37 { Qt::Key_Return, "[Return]" },
37 { QIMPenChar::Caps, "[Uppercase]" }, 38 { QIMPenChar::Caps, "[Uppercase]" },
38 { QIMPenChar::CapsLock,"[Caps Lock]" }, 39 { QIMPenChar::CapsLock,"[Caps Lock]" },
39 { QIMPenChar::Shortcut,"[Shortcut]" }, 40 { QIMPenChar::Shortcut,"[Shortcut]" },
40 { QIMPenChar::Punctuation, "[Punctuation]" }, 41 { QIMPenChar::Punctuation, "[Punctuation]" },
41 { QIMPenChar::Symbol,"[Symbol]" }, 42 { QIMPenChar::Symbol,"[Symbol]" },
42 { QIMPenChar::Extended,"[Extended]" }, 43 { QIMPenChar::Extended,"[Extended]" },
43 { Qt::Key_unknown, 0 } }; 44 { Qt::Key_unknown, 0 } };
44 45
45 46
46/*! 47/*!
47 \class QIMPenChar qimpenchar.h 48 \class QIMPenChar qimpenchar.h
48 49
49 Handles a single character. Can calculate closeness of match to 50 Handles a single character. Can calculate closeness of match to
50 another character. 51 another character.
51 */ 52 */
52 53
53QIMPenChar::QIMPenChar() 54QIMPenChar::QIMPenChar()
54{ 55{
55 flags = 0; 56 flags = 0;
56 strokes.setAutoDelete( TRUE ); 57 strokes.setAutoDelete( TRUE );
57} 58}
58 59
59QIMPenChar::QIMPenChar( const QIMPenChar &chr ) 60QIMPenChar::QIMPenChar( const QIMPenChar &chr )
60{ 61{
61 strokes.setAutoDelete( TRUE ); 62 strokes.setAutoDelete( TRUE );
62 ch = chr.ch; 63 ch = chr.ch;
63 flags = chr.flags; 64 flags = chr.flags;
64 d = chr.d; 65 d = chr.d;
65 QIMPenStrokeIterator it( chr.strokes ); 66 QIMPenStrokeIterator it( chr.strokes );
66 while ( it.current() ) { 67 while ( it.current() ) {
67 strokes.append( new QIMPenStroke( *it.current() ) ); 68 strokes.append( new QIMPenStroke( *it.current() ) );
68 ++it; 69 ++it;
69 } 70 }
70} 71}
71 72
72QIMPenChar &QIMPenChar::operator=( const QIMPenChar &chr ) 73QIMPenChar &QIMPenChar::operator=( const QIMPenChar &chr )
73{ 74{
74 strokes.clear(); 75 strokes.clear();
75 ch = chr.ch; 76 ch = chr.ch;
76 flags = chr.flags; 77 flags = chr.flags;
@@ -122,112 +123,112 @@ unsigned int QIMPenChar::strokeLength( int s ) const
122 if ( it.current() ) 123 if ( it.current() )
123 return it.current()->length(); 124 return it.current()->length();
124 125
125 return 0; 126 return 0;
126} 127}
127 128
128/*! 129/*!
129 Add a stroke to the character 130 Add a stroke to the character
130 */ 131 */
131void QIMPenChar::addStroke( QIMPenStroke *st ) 132void QIMPenChar::addStroke( QIMPenStroke *st )
132{ 133{
133 QIMPenStroke *stroke = new QIMPenStroke( *st ); 134 QIMPenStroke *stroke = new QIMPenStroke( *st );
134 strokes.append( stroke ); 135 strokes.append( stroke );
135} 136}
136 137
137/*! 138/*!
138 Return an indicator of the closeness of this character to \a pen. 139 Return an indicator of the closeness of this character to \a pen.
139 Lower value is better. 140 Lower value is better.
140 */ 141 */
141int QIMPenChar::match( QIMPenChar *pen ) 142int QIMPenChar::match( QIMPenChar *pen )
142{ 143{
143 /* 144 /*
144 if ( strokes.count() > pen->strokes.count() ) 145 if ( strokes.count() > pen->strokes.count() )
145 return INT_MAX; 146 return INT_MAX;
146 */ 147 */
147 int err = 0; 148 int err = 0;
148 int maxErr = 0; 149 int maxErr = 0;
149 int diff = 0; 150 int diff = 0;
150 QIMPenStrokeIterator it1( strokes ); 151 QIMPenStrokeIterator it1( strokes );
151 QIMPenStrokeIterator it2( pen->strokes ); 152 QIMPenStrokeIterator it2( pen->strokes );
152 err = it1.current()->match( it2.current() ); 153 err = it1.current()->match( it2.current() );
153 if ( err > maxErr ) 154 if ( err > maxErr )
154 maxErr = err; 155 maxErr = err;
155 ++it1; 156 ++it1;
156 ++it2; 157 ++it2;
157 while ( err < 400000 && it1.current() && it2.current() ) { 158 while ( err < 400000 && it1.current() && it2.current() ) {
158 QPoint p1 = it1.current()->boundingRect().center() - 159 QPoint p1 = it1.current()->boundingRect().center() -
159 strokes.getFirst()->boundingRect().center(); 160 strokes.getFirst()->boundingRect().center();
160 QPoint p2 = it2.current()->boundingRect().center() - 161 QPoint p2 = it2.current()->boundingRect().center() -
161 pen->strokes.getFirst()->boundingRect().center(); 162 pen->strokes.getFirst()->boundingRect().center();
162 int xdiff = QABS( p1.x() - p2.x() ) - 6; 163 int xdiff = QABS( p1.x() - p2.x() ) - 6;
163 int ydiff = QABS( p1.y() - p2.y() ) - 5; 164 int ydiff = QABS( p1.y() - p2.y() ) - 5;
164 if ( xdiff < 0 ) 165 if ( xdiff < 0 )
165 xdiff = 0; 166 xdiff = 0;
166 if ( ydiff < 0 ) 167 if ( ydiff < 0 )
167 ydiff = 0; 168 ydiff = 0;
168 if ( xdiff > 10 || ydiff > 10 ) { // not a chance 169 if ( xdiff > 10 || ydiff > 10 ) { // not a chance
169#ifdef DEBUG_QIMPEN 170#ifdef DEBUG_QIMPEN
170 qDebug( "char %c, stroke starting pt diff excessive", pen->ch ); 171 odebug << "char " << pen->ch <<", stroke starting pt diff excessive" << oendl;
171#endif 172#endif
172 return INT_MAX; 173 return INT_MAX;
173 } 174 }
174 diff += xdiff*xdiff + ydiff*ydiff; 175 diff += xdiff*xdiff + ydiff*ydiff;
175 err = it1.current()->match( it2.current() ); 176 err = it1.current()->match( it2.current() );
176 if ( err > maxErr ) 177 if ( err > maxErr )
177 maxErr = err; 178 maxErr = err;
178 ++it1; 179 ++it1;
179 ++it2; 180 ++it2;
180 } 181 }
181 182
182 maxErr += diff * diff * 6; // magic weighting :) 183 maxErr += diff * diff * 6; // magic weighting :)
183 184
184#ifdef DEBUG_QIMPEN 185#ifdef DEBUG_QIMPEN
185 qDebug( "char: %c, maxErr %d, diff %d, (%d)", pen->ch, maxErr, diff, strokes.count() ); 186 odebug << "char: " << pen->ch << ", maxErr " << maxErr << ", diff " << diff << ", " << strokes.count() << oendl;
186#endif 187#endif
187 return maxErr; 188 return maxErr;
188} 189}
189 190
190/*! 191/*!
191 Return the bounding rect of this character. It may have sides with 192 Return the bounding rect of this character. It may have sides with
192 negative coords since its origin is where the user started drawing 193 negative coords since its origin is where the user started drawing
193 the character. 194 the character.
194 */ 195 */
195QRect QIMPenChar::boundingRect() 196QRect QIMPenChar::boundingRect()
196{ 197{
197 QRect br; 198 QRect br;
198 QIMPenStroke *st = strokes.first(); 199 QIMPenStroke *st = strokes.first();
199 while ( st ) { 200 while ( st ) {
200 br |= st->boundingRect(); 201 br |= st->boundingRect();
201 st = strokes.next(); 202 st = strokes.next();
202 } 203 }
203 204
204 return br; 205 return br;
205} 206}
206 207
207 208
208/*! 209/*!
209 Write the character's data to the stream. 210 Write the character's data to the stream.
210 */ 211 */
211QDataStream &operator<< (QDataStream &s, const QIMPenChar &ws) 212QDataStream &operator<< (QDataStream &s, const QIMPenChar &ws)
212{ 213{
213 s << ws.ch; 214 s << ws.ch;
214 s << ws.flags; 215 s << ws.flags;
215 if ( ws.flags & QIMPenChar::Data ) 216 if ( ws.flags & QIMPenChar::Data )
216 s << ws.d; 217 s << ws.d;
217 s << ws.strokes.count(); 218 s << ws.strokes.count();
218 QIMPenStrokeIterator it( ws.strokes ); 219 QIMPenStrokeIterator it( ws.strokes );
219 while ( it.current() ) { 220 while ( it.current() ) {
220 s << *it.current(); 221 s << *it.current();
221 ++it; 222 ++it;
222 } 223 }
223 224
224 return s; 225 return s;
225} 226}
226 227
227/*! 228/*!
228 Read the character's data from the stream. 229 Read the character's data from the stream.
229 */ 230 */
230QDataStream &operator>> (QDataStream &s, QIMPenChar &ws) 231QDataStream &operator>> (QDataStream &s, QIMPenChar &ws)
231{ 232{
232 s >> ws.ch; 233 s >> ws.ch;
233 s >> ws.flags; 234 s >> ws.flags;
@@ -413,98 +414,98 @@ void QIMPenCharSet::markDeleted( uint ch )
413 for ( ; ci.current(); ++ci ) { 414 for ( ; ci.current(); ++ci ) {
414 QIMPenChar *pc = ci.current(); 415 QIMPenChar *pc = ci.current();
415 if ( pc->character() == ch && pc->testFlag( QIMPenChar::System ) ) 416 if ( pc->character() == ch && pc->testFlag( QIMPenChar::System ) )
416 pc->setFlag( QIMPenChar::Deleted ); 417 pc->setFlag( QIMPenChar::Deleted );
417 } 418 }
418} 419}
419 420
420/*! 421/*!
421 Find the best matches for \a ch in this character set. 422 Find the best matches for \a ch in this character set.
422 */ 423 */
423QIMPenCharMatchList QIMPenCharSet::match( QIMPenChar *ch ) 424QIMPenCharMatchList QIMPenCharSet::match( QIMPenChar *ch )
424{ 425{
425 QIMPenCharMatchList matches; 426 QIMPenCharMatchList matches;
426 427
427 QIMPenCharIterator ci( chars ); 428 QIMPenCharIterator ci( chars );
428 for ( ; ci.current(); ++ci ) { 429 for ( ; ci.current(); ++ci ) {
429 QIMPenChar *tmplChar = ci.current(); 430 QIMPenChar *tmplChar = ci.current();
430 if ( tmplChar->testFlag( QIMPenChar::Deleted ) ) { 431 if ( tmplChar->testFlag( QIMPenChar::Deleted ) ) {
431 continue; 432 continue;
432 } 433 }
433 int err; 434 int err;
434 if ( ch->penStrokes().count() <= tmplChar->penStrokes().count() ) { 435 if ( ch->penStrokes().count() <= tmplChar->penStrokes().count() ) {
435 err = ch->match( tmplChar ); 436 err = ch->match( tmplChar );
436 if ( err <= QIMPEN_MATCH_THRESHOLD ) { 437 if ( err <= QIMPEN_MATCH_THRESHOLD ) {
437 if (tmplChar->penStrokes().count() != ch->penStrokes().count()) 438 if (tmplChar->penStrokes().count() != ch->penStrokes().count())
438 err = QMIN(err*3, QIMPEN_MATCH_THRESHOLD); 439 err = QMIN(err*3, QIMPEN_MATCH_THRESHOLD);
439 QIMPenCharMatchList::Iterator it; 440 QIMPenCharMatchList::Iterator it;
440 for ( it = matches.begin(); it != matches.end(); ++it ) { 441 for ( it = matches.begin(); it != matches.end(); ++it ) {
441 if ( (*it).penChar->character() == tmplChar->character() && 442 if ( (*it).penChar->character() == tmplChar->character() &&
442 (*it).penChar->penStrokes().count() == tmplChar->penStrokes().count() ) { 443 (*it).penChar->penStrokes().count() == tmplChar->penStrokes().count() ) {
443 if ( (*it).error > err ) 444 if ( (*it).error > err )
444 (*it).error = err; 445 (*it).error = err;
445 break; 446 break;
446 } 447 }
447 } 448 }
448 if ( it == matches.end() ) { 449 if ( it == matches.end() ) {
449 QIMPenCharMatch m; 450 QIMPenCharMatch m;
450 m.error = err; 451 m.error = err;
451 m.penChar = tmplChar; 452 m.penChar = tmplChar;
452 matches.append( m ); 453 matches.append( m );
453 } 454 }
454 } 455 }
455 } 456 }
456 } 457 }
457 qHeapSort( matches ); 458 qHeapSort( matches );
458 /* 459 /*
459 QIMPenCharMatchList::Iterator it; 460 QIMPenCharMatchList::Iterator it;
460 for ( it = matches.begin(); it != matches.end(); ++it ) { 461 for ( it = matches.begin(); it != matches.end(); ++it ) {
461 qDebug( "Match: \'%c\', error %d, strokes %d", (*it).penChar->character(), 462
462 (*it).error, (*it).penChar->penStrokes().count() ); 463 odebug << "Match: \'" << (*it).penChar->character() "\', error " << (*it).error ", strokes " <<(*it).penChar->penStrokes().count() << oendl;
463 } 464 }
464 */ 465 */
465 return matches; 466 return matches;
466} 467}
467 468
468/*! 469/*!
469 Add a character \a ch to this set. 470 Add a character \a ch to this set.
470 QIMPenCharSet will delete this character when it is no longer needed. 471 QIMPenCharSet will delete this character when it is no longer needed.
471 */ 472 */
472void QIMPenCharSet::addChar( QIMPenChar *ch ) 473void QIMPenCharSet::addChar( QIMPenChar *ch )
473{ 474{
474 if ( ch->penStrokes().count() > maxStrokes ) 475 if ( ch->penStrokes().count() > maxStrokes )
475 maxStrokes = ch->penStrokes().count(); 476 maxStrokes = ch->penStrokes().count();
476 chars.append( ch ); 477 chars.append( ch );
477} 478}
478 479
479/*! 480/*!
480 Remove a character by reference \a ch from this set. 481 Remove a character by reference \a ch from this set.
481 QIMPenCharSet will delete this character. 482 QIMPenCharSet will delete this character.
482 */ 483 */
483void QIMPenCharSet::removeChar( QIMPenChar *ch ) 484void QIMPenCharSet::removeChar( QIMPenChar *ch )
484{ 485{
485 chars.remove( ch ); 486 chars.remove( ch );
486} 487}
487 488
488/*! 489/*!
489 Move the character up the list of characters. 490 Move the character up the list of characters.
490 */ 491 */
491void QIMPenCharSet::up( QIMPenChar *ch ) 492void QIMPenCharSet::up( QIMPenChar *ch )
492{ 493{
493 int idx = chars.findRef( ch ); 494 int idx = chars.findRef( ch );
494 if ( idx > 0 ) { 495 if ( idx > 0 ) {
495 chars.take(); 496 chars.take();
496 chars.insert( idx - 1, ch ); 497 chars.insert( idx - 1, ch );
497 } 498 }
498} 499}
499 500
500/*! 501/*!
501 Move the character down the list of characters. 502 Move the character down the list of characters.
502 */ 503 */
503void QIMPenCharSet::down( QIMPenChar *ch ) 504void QIMPenCharSet::down( QIMPenChar *ch )
504{ 505{
505 int idx = chars.findRef( ch ); 506 int idx = chars.findRef( ch );
506 if ( idx >= 0 && idx < (int)chars.count() - 1 ) { 507 if ( idx >= 0 && idx < (int)chars.count() - 1 ) {
507 chars.take(); 508 chars.take();
508 chars.insert( idx + 1, ch ); 509 chars.insert( idx + 1, ch );
509 } 510 }
510} 511}