1 /*---------------------------------------------------------------------------*
2 Project: TwlSDK - PRC -
3 File: prc_algo_common.c
4
5 Copyright 2003-2008 Nintendo. All rights reserved.
6
7 These coded instructions, statements, and computer programs contain
8 proprietary information of Nintendo of America Inc. and/or Nintendo
9 Company Ltd., and are protected by Federal copyright law. They may
10 not be disclosed to third parties or copied or duplicated in any form,
11 in whole or in part, without the prior written consent of Nintendo.
12
13 $Date:: 2008-09-18#$
14 $Rev: 8573 $
15 $Author: okubata_ryoma $
16 *---------------------------------------------------------------------------*/
17
18 #include <nitro.h>
19 #include <nitro/prc/algo_common.h>
20 #include <nitro/prc/resample.h>
21
22 /*===========================================================================*
23 Prototype Declarations
24 *===========================================================================*/
25 static void
26 PRCi_CountPrototypeList_Common(int *wholePointCount,
27 int *wholeStrokeCount,
28 int *patternCount,
29 int *maxPointCount,
30 int *maxStrokeCount,
31 const PRCPrototypeList *prototypeList,
32 u32 kindMask, BOOL ignoreDisabledEntries);
33
34 static u32
35 PRCi_GetPrototypeDBBufferSize_Common(int wholePointCount, int wholeStrokeCount, int patternCount);
36
37 static u32
38 PRCi_SetPrototypeListBufferInfo_Common(PRCiPrototypeListBufferInfo_Common *WAInfo,
39 void *buffer,
40 int wholePointCount, int wholeStrokeCount, int patternCount);
41
42 static BOOL
43 PRCi_ExtractPrototypeList_Common(PRCPrototypeDB_Common *protoDB,
44 u32 kindMask, BOOL ignoreDisabledEntries);
45
46 static u32 PRCi_GetInputPatternBufferSize_Common(int pointCount, int strokeCount);
47
48 static u32
49 PRCi_SetPatternBufferInfo_Common(PRCiPatternBufferInfo_Common *WAInfo,
50 void *buffer, int pointCount, int strokeCount);
51
52 static BOOL
53 PRCi_ExtractInputPattern_Common(PRCInputPattern_Common *pattern,
54 const PRCStrokes *strokes,
55 int maxPointCount,
56 int maxStrokeCount, const PRCInputPatternParam_Common *param);
57
58 static void PRCi_CalcExtraValues_Common(PRCiPatternData_Common *data);
59
60 static void PRCi_GetPatternStrokes_Common(PRCStrokes *strokes, const PRCiPatternData_Common *data);
61
62
63 /*===========================================================================*
64 Variable Definitions
65 *===========================================================================*/
66
67 /*===========================================================================*
68 Functions
69 *===========================================================================*/
70
71 /*---------------------------------------------------------------------------*
72 Name: PRC_GetPrototypeDBBufferSizeEx_Common
73
74 Description: Calculates the work area size required for expanding sample DB.
75
76 Arguments: prototypeList: Sample pattern list
77 kindMask: Mask for type specification
78 ignoreDisabledEntries: Whether sample DB entries with the 'enabled' flag FALSE are ever expanded
79
80 param: Parameters for sample DB expansion
81
82 Returns: Required memory capacity for expanding sample DB.
83 *---------------------------------------------------------------------------*/
84 u32
PRC_GetPrototypeDBBufferSizeEx_Common(const PRCPrototypeList * prototypeList,u32 kindMask,BOOL ignoreDisabledEntries,const PRCPrototypeDBParam_Common * param)85 PRC_GetPrototypeDBBufferSizeEx_Common(const PRCPrototypeList *prototypeList,
86 u32 kindMask,
87 BOOL ignoreDisabledEntries,
88 const PRCPrototypeDBParam_Common *param)
89 {
90 int wholePointCount, wholeStrokeCount, patternCount;
91 int maxPointCount, maxStrokeCount;
92 SDK_ASSERT(prototypeList);
93
94 (void)param; // Ignore param
95 PRCi_CountPrototypeList_Common(&wholePointCount, &wholeStrokeCount,
96 &patternCount, &maxPointCount, &maxStrokeCount,
97 prototypeList, kindMask, ignoreDisabledEntries);
98
99 return PRCi_GetPrototypeDBBufferSize_Common(wholePointCount, wholeStrokeCount, patternCount);
100 }
101
102 /*---------------------------------------------------------------------------*
103 Name: PRC_InitPrototypeDBEx_Common
104
105 Description: Creates the PRCPrototypeDB structure.
106 A buffer region larger than the size that PRC_GetPrototypeDBBufferSize returns needs to be set up in the buffer.
107
108 Parameters during expansion can be specified with param.
109
110 Arguments: protoDB: Sample DB structure to initialize
111 buffer: Pointer to memory region used for sample DB expansion
112 (Memory area size >= return value of PRC_GetPrototypeDBBufferSize)
113 prototypeList: Sample pattern list
114 kindMask: Mask for type specification
115 ignoreDisabledEntries: Whether sample DB entries with the 'enabled' flag FALSE are ever expanded
116
117 param: Parameters for sample DB expansion
118
119 Returns: TRUE if successfully created.
120 *---------------------------------------------------------------------------*/
121 BOOL
PRC_InitPrototypeDBEx_Common(PRCPrototypeDB_Common * protoDB,void * buffer,const PRCPrototypeList * prototypeList,u32 kindMask,BOOL ignoreDisabledEntries,const PRCPrototypeDBParam_Common * param)122 PRC_InitPrototypeDBEx_Common(PRCPrototypeDB_Common *protoDB,
123 void *buffer,
124 const PRCPrototypeList *prototypeList,
125 u32 kindMask,
126 BOOL ignoreDisabledEntries, const PRCPrototypeDBParam_Common *param)
127 {
128 PRCiPrototypeListBufferInfo_Common WAInfo;
129 u32 bufferSize;
130 SDK_ASSERT(protoDB);
131 SDK_ASSERT(prototypeList);
132 SDK_ASSERT(buffer);
133 (void)param;
134
135 PRCi_CountPrototypeList_Common(&protoDB->wholePointCount, &protoDB->wholeStrokeCount,
136 &protoDB->patternCount, &protoDB->maxPointCount,
137 &protoDB->maxStrokeCount, prototypeList, kindMask,
138 ignoreDisabledEntries);
139
140 bufferSize = PRCi_SetPrototypeListBufferInfo_Common(&WAInfo, buffer,
141 protoDB->wholePointCount,
142 protoDB->wholeStrokeCount,
143 protoDB->patternCount);
144 #ifdef SDK_DEBUG
145 SDK_ASSERTMSG((bufferSize ==
146 PRC_GetPrototypeDBBufferSizeEx_Common(prototypeList, kindMask,
147 ignoreDisabledEntries, param)),
148 "Internal Error: bufferSize mismatch.");
149 #endif
150 protoDB->patterns = WAInfo.patterns;
151 protoDB->lineSegmentLengthArray = WAInfo.lineSegmentLengthArray;
152 protoDB->lineSegmentRatioToStrokeArray = WAInfo.lineSegmentRatioToStrokeArray;
153 // protoDB->lineSegmentRatioToWholeArray = WAInfo.lineSegmentRatioToWholeArray;
154 protoDB->lineSegmentAngleArray = WAInfo.lineSegmentAngleArray;
155 protoDB->strokeArray = WAInfo.strokeArray;
156 protoDB->strokeSizeArray = WAInfo.strokeSizeArray;
157 protoDB->strokeLengthArray = WAInfo.strokeLengthArray;
158 protoDB->strokeRatioArray = WAInfo.strokeRatioArray;
159 protoDB->strokeBoundingBoxArray = WAInfo.strokeBoundingBoxArray;
160
161 protoDB->normalizeSize = prototypeList->normalizeSize;
162
163 protoDB->prototypeList = prototypeList;
164 protoDB->buffer = buffer;
165 protoDB->bufferSize = bufferSize;
166
167 return PRCi_ExtractPrototypeList_Common(protoDB, kindMask, ignoreDisabledEntries);
168 }
169
170 /*---------------------------------------------------------------------------*
171 Name: PRC_GetInputPatternBufferSize_Common
172
173 Description: Calculates work area required for expanding pattern data for comparison.
174
175
176 Arguments: maxPointCount: Upper limit of number of input points (includes pen up marker)
177 maxStrokeCount: Upper limit of stroke count
178
179 Returns: Memory capacity required for expanding the pattern.
180 *---------------------------------------------------------------------------*/
PRC_GetInputPatternBufferSize_Common(int maxPointCount,int maxStrokeCount)181 u32 PRC_GetInputPatternBufferSize_Common(int maxPointCount, int maxStrokeCount)
182 {
183 return PRCi_GetInputPatternBufferSize_Common(maxPointCount, maxStrokeCount);
184 }
185
186 /*---------------------------------------------------------------------------*
187 Name: PRC_InitInputPatternEx_Common
188
189 Description: Creates PRCInputPattern structure.
190 Specification of parameters for input pattern interpretation can be done with param.
191
192 Arguments: pattern: Pattern structure to initialize
193 buffer: Pointer to memory region used for pattern expansion
194 (Region size >=return value of PRC_GetInputPatternBufferSize)
195 strokes: Raw input coordinate values before sorting
196 maxPointCount: Upper limit of number of input points (includes pen up marker)
197 maxStrokeCount: Upper limit of stroke count
198 param: Parameters for input pattern interpretation
199
200 Returns: TRUE if successfully created.
201 *---------------------------------------------------------------------------*/
202 BOOL
PRC_InitInputPatternEx_Common(PRCInputPattern_Common * pattern,void * buffer,const PRCStrokes * strokes,int maxPointCount,int maxStrokeCount,const PRCInputPatternParam_Common * param)203 PRC_InitInputPatternEx_Common(PRCInputPattern_Common *pattern,
204 void *buffer,
205 const PRCStrokes *strokes,
206 int maxPointCount,
207 int maxStrokeCount, const PRCInputPatternParam_Common *param)
208 {
209 PRCiPatternBufferInfo_Common WAInfo;
210 PRCiPatternData_Common *data;
211 u32 bufferSize;
212 SDK_ASSERT(pattern);
213 SDK_ASSERT(buffer);
214
215 bufferSize = PRCi_SetPatternBufferInfo_Common(&WAInfo, buffer, maxPointCount, maxStrokeCount);
216 #ifdef SDK_DEBUG
217 SDK_ASSERTMSG((bufferSize ==
218 PRCi_GetInputPatternBufferSize_Common(maxPointCount, maxStrokeCount)),
219 "Internal Error: bufferSize mismatch.");
220 #endif
221 data = &pattern->data;
222 data->pointArray = WAInfo.pointArray;
223 data->strokes = WAInfo.strokes;
224 data->strokeSizes = WAInfo.strokeSizes;
225 data->lineSegmentLengthArray = WAInfo.lineSegmentLengthArray;
226 data->lineSegmentRatioToStrokeArray = WAInfo.lineSegmentRatioToStrokeArray;
227 // data->lineSegmentRatioToWholeArray = WAInfo.lineSegmentRatioToWholeArray;
228 data->lineSegmentAngleArray = WAInfo.lineSegmentAngleArray;
229 data->strokeLengths = WAInfo.strokeLengths;
230 data->strokeRatios = WAInfo.strokeRatios;
231 data->strokeBoundingBoxes = WAInfo.strokeBoundingBoxes;
232
233 pattern->buffer = buffer;
234 pattern->bufferSize = bufferSize;
235
236 return PRCi_ExtractInputPattern_Common(pattern, strokes, maxPointCount, maxStrokeCount, param);
237 }
238
239 /*---------------------------------------------------------------------------*
240 Name: PRC_GetInputPatternStrokes_Common
241
242 Description: Gets dot sequence data from PRCInputPattern structure.
243
244 Arguments: strokes: Obtained dot sequence data
245 Overwriting is not permitted.
246 input: Input pattern
247
248 Returns: None.
249 *---------------------------------------------------------------------------*/
PRC_GetInputPatternStrokes_Common(PRCStrokes * strokes,const PRCInputPattern_Common * input)250 void PRC_GetInputPatternStrokes_Common(PRCStrokes *strokes, const PRCInputPattern_Common *input)
251 {
252 SDK_ASSERT(strokes);
253 SDK_ASSERT(input);
254
255 PRCi_GetPatternStrokes_Common(strokes, &input->data);
256 }
257
258
259
260 #define FMT_FX(f) ((f)>>FX32_SHIFT),(((f)&FX32_DEC_MASK)*1000/(1<<FX32_DEC_SIZE))
261 #define FMT_POINT(p) (p).x,(p).y
262 #define FMT_BB(bb) (bb).x1,(bb).y1,(bb).x2,(bb).y2
PRCi_PrintPatternData_Common(PRCiPatternData_Common * data)263 void PRCi_PrintPatternData_Common(PRCiPatternData_Common *data)
264 {
265 int iStroke, iPoint;
266
267 OS_Printf(" strokeCount: %d\n", data->strokeCount);
268 OS_Printf(" pointCount: %d\n", data->pointCount);
269 OS_Printf(" wholeLength: %d.%03d\n", FMT_FX(data->wholeLength));
270 OS_Printf(" wholeBoundingBox: (%d, %d) - (%d, %d)\n", FMT_BB(data->wholeBoundingBox));
271 for (iStroke = 0; iStroke < data->strokeCount; iStroke++)
272 {
273 OS_Printf(" Stroke #%d\n", iStroke);
274 OS_Printf(" index : %d\n", data->strokes[iStroke]);
275 OS_Printf(" size : %d\n", data->strokeSizes[iStroke]);
276 OS_Printf(" length: %d.%03d\n", FMT_FX(data->strokeLengths[iStroke]));
277 OS_Printf(" ratio : %d.%03d\n", FMT_FX(data->strokeRatios[iStroke]));
278 OS_Printf(" strokeBoundingBoxes: (%d, %d) - (%d, %d)\n",
279 FMT_BB(data->strokeBoundingBoxes[iStroke]));
280 for (iPoint = 0; iPoint < data->strokeSizes[iStroke]; iPoint++)
281 {
282 int index;
283
284 index = data->strokes[iStroke] + iPoint;
285
286 OS_Printf(" #%d: pointArray[%d] = (%d, %d)\n", iPoint, index,
287 FMT_POINT(data->pointArray[index]));
288 // OS_Printf(" length: %d.%03d, ratio: %d.%03d (%d.%03d), angle: %d\n",
289 OS_Printf(" length: %d.%03d, ratio: %d.%03d, angle: %d\n",
290 FMT_FX(data->lineSegmentLengthArray[index]),
291 FMT_FX(data->lineSegmentRatioToStrokeArray[index]),
292 // FMT_FX(data->lineSegmentRatioToWholeArray[index]),
293 data->lineSegmentAngleArray[index] * 360 / 65536);
294 }
295 }
296 #if 0
297 OS_Printf(" pointArray:\n");
298 for (iPoint = 0; iPoint < data->pointCount; iPoint++)
299 {
300 int index = iPoint;
301
302 OS_Printf(" pointArray[%d] = (%d, %d)\n", index, FMT_POINT(data->pointArray[index]));
303 // OS_Printf(" length: %d.%03d, ratio: %d.%03d (%d.%03d), angle: %d\n",
304 OS_Printf(" length: %d.%03d, ratio: %d.%03d, angle: %d\n",
305 FMT_FX(data->lineSegmentLengthArray[index]),
306 FMT_FX(data->lineSegmentRatioToStrokeArray[index]),
307 // FMT_FX(data->lineSegmentRatioToWholeArray[index]),
308 data->lineSegmentAngleArray[index] * 360 / 65536);
309 }
310 #endif
311 }
312
313
314 /*===========================================================================*
315 Static Functions
316 *===========================================================================*/
317 static void
PRCi_CountPrototypeList_Common(int * wholePointCount,int * wholeStrokeCount,int * patternCount,int * maxPointCount,int * maxStrokeCount,const PRCPrototypeList * prototypeList,u32 kindMask,BOOL ignoreDisabledEntries)318 PRCi_CountPrototypeList_Common(int *wholePointCount,
319 int *wholeStrokeCount,
320 int *patternCount,
321 int *maxPointCount,
322 int *maxStrokeCount,
323 const PRCPrototypeList *prototypeList,
324 u32 kindMask, BOOL ignoreDisabledEntries)
325 {
326 int i;
327 int pointCnt, strokeCnt, patternCnt;
328 int maxPointCnt, maxStrokeCnt;
329 const PRCPrototypeEntry *entry;
330
331 pointCnt = strokeCnt = patternCnt = 0;
332 maxPointCnt = maxStrokeCnt = 0;
333
334 entry = prototypeList->entries;
335 for (i = 0; i < prototypeList->entrySize; i++, entry++)
336 {
337 if (!entry->enabled && ignoreDisabledEntries)
338 continue;
339 if (entry->kind & kindMask)
340 {
341 pointCnt += entry->pointCount;
342 strokeCnt += entry->strokeCount;
343 patternCnt++;
344
345 if (maxPointCnt < entry->pointCount)
346 {
347 maxPointCnt = entry->pointCount;
348 }
349 if (maxStrokeCnt < entry->strokeCount)
350 {
351 maxStrokeCnt = entry->strokeCount;
352 }
353 }
354 }
355
356 *wholePointCount = pointCnt;
357 *wholeStrokeCount = strokeCnt;
358 *patternCount = patternCnt;
359 *maxPointCount = maxPointCnt;
360 *maxStrokeCount = maxStrokeCnt;
361 }
362
363 static u32
PRCi_GetPrototypeDBBufferSize_Common(int wholePointCount,int wholeStrokeCount,int patternCount)364 PRCi_GetPrototypeDBBufferSize_Common(int wholePointCount, int wholeStrokeCount, int patternCount)
365 {
366 u32 addr;
367
368 addr = 0;
369
370 addr += PRCi_ARRAY_SIZE(PRCiPrototypeEntry_Common, patternCount,);
371
372 addr += PRCi_ARRAY_SIZE(fx32, wholePointCount + 1,);
373
374 addr += PRCi_ARRAY_SIZE(int, wholeStrokeCount,);
375
376 addr += PRCi_ARRAY_SIZE(int, wholeStrokeCount,);
377
378 addr += PRCi_ARRAY_SIZE(fx32, wholeStrokeCount,);
379
380 addr += PRCi_ARRAY_SIZE(PRCBoundingBox, wholeStrokeCount,);
381
382 addr += PRCi_ARRAY_SIZE(fx16, wholePointCount + 1,);
383
384 // addr += PRCi_ARRAY_SIZE( // lineSegmentRatioToWholeArray
385 // fx16, wholePointCount+1,
386 // );
387
388 addr += PRCi_ARRAY_SIZE(u16, wholePointCount + 1,);
389
390 addr += PRCi_ARRAY_SIZE(fx16, wholeStrokeCount,);
391
392 return addr;
393 }
394
395 static u32
PRCi_SetPrototypeListBufferInfo_Common(PRCiPrototypeListBufferInfo_Common * WAInfo,void * buffer,int wholePointCount,int wholeStrokeCount,int patternCount)396 PRCi_SetPrototypeListBufferInfo_Common(PRCiPrototypeListBufferInfo_Common *WAInfo,
397 void *buffer,
398 int wholePointCount, int wholeStrokeCount, int patternCount)
399 {
400 u32 addr;
401
402 SDK_ALIGN4_ASSERT(buffer);
403
404 addr = 0;
405
406 PRCi_ALLOC_ARRAY(WAInfo->patterns, PRCiPrototypeEntry_Common, patternCount, buffer, addr);
407
408 PRCi_ALLOC_ARRAY(WAInfo->lineSegmentLengthArray, fx32, wholePointCount + 1, buffer, addr);
409
410 PRCi_ALLOC_ARRAY(WAInfo->strokeArray, int, wholeStrokeCount, buffer, addr);
411
412 PRCi_ALLOC_ARRAY(WAInfo->strokeSizeArray, int, wholeStrokeCount, buffer, addr);
413
414 PRCi_ALLOC_ARRAY(WAInfo->strokeLengthArray, fx32, wholeStrokeCount, buffer, addr);
415
416 PRCi_ALLOC_ARRAY(WAInfo->strokeBoundingBoxArray,
417 PRCBoundingBox, wholeStrokeCount, buffer, addr);
418
419 PRCi_ALLOC_ARRAY(WAInfo->lineSegmentRatioToStrokeArray,
420 fx16, wholePointCount + 1, buffer, addr);
421
422 // PRCi_ALLOC_ARRAY( WAInfo->lineSegmentRatioToWholeArray,
423 // fx16, wholePointCount+1,
424 // buffer, addr );
425
426 PRCi_ALLOC_ARRAY(WAInfo->lineSegmentAngleArray, u16, wholePointCount + 1, buffer, addr);
427
428 PRCi_ALLOC_ARRAY(WAInfo->strokeRatioArray, fx16, wholeStrokeCount, buffer, addr);
429
430 return addr;
431 }
432
433 static BOOL
PRCi_ExtractPrototypeList_Common(PRCPrototypeDB_Common * protoDB,u32 kindMask,BOOL ignoreDisabledEntries)434 PRCi_ExtractPrototypeList_Common(PRCPrototypeDB_Common *protoDB,
435 u32 kindMask, BOOL ignoreDisabledEntries)
436 {
437 int iEntry;
438 int pointCnt, strokeCnt, patternCnt;
439 int entrySize;
440 const PRCPrototypeEntry *entry;
441 PRCiPrototypeEntry_Common *pattern;
442
443 entry = protoDB->prototypeList->entries;
444 entrySize = protoDB->prototypeList->entrySize;
445
446 pointCnt = strokeCnt = patternCnt = 0;
447 pattern = protoDB->patterns;
448 for (iEntry = 0; iEntry < entrySize; iEntry++, entry++)
449 {
450 if (!entry->enabled && ignoreDisabledEntries)
451 continue;
452 if (entry->kind & kindMask)
453 {
454 PRCiPatternData_Common *data;
455
456 pattern->entry = entry;
457 data = &pattern->data;
458 data->strokeCount = entry->strokeCount;
459 data->pointCount = entry->pointCount;
460 data->pointArray = &protoDB->prototypeList->pointArray[entry->pointIndex];
461 data->strokes = &protoDB->strokeArray[strokeCnt];
462 data->strokeSizes = &protoDB->strokeSizeArray[strokeCnt];
463 data->strokeLengths = &protoDB->strokeLengthArray[strokeCnt];
464 data->strokeRatios = &protoDB->strokeRatioArray[strokeCnt];
465 data->strokeBoundingBoxes = &protoDB->strokeBoundingBoxArray[strokeCnt];
466 data->lineSegmentLengthArray = &protoDB->lineSegmentLengthArray[pointCnt];
467 data->lineSegmentRatioToStrokeArray = &protoDB->lineSegmentRatioToStrokeArray[pointCnt];
468 // data->lineSegmentRatioToWholeArray = &protoDB->lineSegmentRatioToWholeArray[pointCnt];
469 data->lineSegmentAngleArray = &protoDB->lineSegmentAngleArray[pointCnt];
470
471 PRCi_CalcExtraValues_Common((PRCiPatternData_Common *)data);
472
473 pointCnt += entry->pointCount;
474 strokeCnt += entry->strokeCount;
475 patternCnt++;
476 pattern++;
477 }
478 }
479 SDK_ASSERT(patternCnt <= entrySize);
480
481 return TRUE;
482 }
483
PRCi_GetInputPatternBufferSize_Common(int pointCount,int strokeCount)484 static u32 PRCi_GetInputPatternBufferSize_Common(int pointCount, int strokeCount)
485 {
486 u32 addr;
487
488 addr = 0;
489
490 addr += PRCi_ARRAY_SIZE(PRCPoint, pointCount,);
491
492 addr += PRCi_ARRAY_SIZE(int, strokeCount,);
493
494 addr += PRCi_ARRAY_SIZE(int, strokeCount,);
495
496 addr += PRCi_ARRAY_SIZE(fx32, pointCount + 1,);
497
498 addr += PRCi_ARRAY_SIZE(fx32, strokeCount,);
499
500 addr += PRCi_ARRAY_SIZE(PRCBoundingBox, strokeCount,);
501
502 addr += PRCi_ARRAY_SIZE(fx16, pointCount + 1,);
503
504 // addr += PRCi_ARRAY_SIZE( // lineSegmentRatioToWholeArray
505 // fx16, pointCount+1,
506 // );
507
508 addr += PRCi_ARRAY_SIZE(u16, pointCount + 1,);
509
510 addr += PRCi_ARRAY_SIZE(fx16, strokeCount,);
511
512 return addr;
513 }
514
515 static u32
PRCi_SetPatternBufferInfo_Common(PRCiPatternBufferInfo_Common * WAInfo,void * buffer,int pointCount,int strokeCount)516 PRCi_SetPatternBufferInfo_Common(PRCiPatternBufferInfo_Common *WAInfo,
517 void *buffer, int pointCount, int strokeCount)
518 {
519 u32 addr;
520
521 SDK_ALIGN4_ASSERT(buffer);
522
523 addr = 0;
524
525 PRCi_ALLOC_ARRAY(WAInfo->pointArray, PRCPoint, pointCount, buffer, addr);
526
527 PRCi_ALLOC_ARRAY(WAInfo->strokes, int, strokeCount, buffer, addr);
528
529 PRCi_ALLOC_ARRAY(WAInfo->strokeSizes, int, strokeCount, buffer, addr);
530
531 PRCi_ALLOC_ARRAY(WAInfo->lineSegmentLengthArray, fx32, pointCount + 1, buffer, addr);
532
533 PRCi_ALLOC_ARRAY(WAInfo->strokeLengths, fx32, strokeCount, buffer, addr);
534
535 PRCi_ALLOC_ARRAY(WAInfo->strokeBoundingBoxes, PRCBoundingBox, strokeCount, buffer, addr);
536
537 PRCi_ALLOC_ARRAY(WAInfo->lineSegmentRatioToStrokeArray, fx16, pointCount + 1, buffer, addr);
538
539 // PRCi_ALLOC_ARRAY( WAInfo->lineSegmentRatioToWholeArray,
540 // fx16, pointCount+1,
541 // buffer, addr );
542
543 PRCi_ALLOC_ARRAY(WAInfo->lineSegmentAngleArray, u16, pointCount + 1, buffer, addr);
544
545 PRCi_ALLOC_ARRAY(WAInfo->strokeRatios, fx16, strokeCount, buffer, addr);
546
547 return addr;
548 }
549
550 static BOOL
PRCi_ExtractInputPattern_Common(PRCInputPattern_Common * pattern,const PRCStrokes * strokes,int maxPointCount,int maxStrokeCount,const PRCInputPatternParam_Common * param)551 PRCi_ExtractInputPattern_Common(PRCInputPattern_Common *pattern,
552 const PRCStrokes *strokes,
553 int maxPointCount,
554 int maxStrokeCount, const PRCInputPatternParam_Common *param)
555 {
556 PRCiPatternData_Common *data;
557 u16 iPoint, strokeCount, wholePointCount;
558 int wx, wy, w, dx, dy;
559 u16 *selectedPoints;
560 int selectedPointNum;
561 int normalizeSize;
562 PRCResampleMethod resampleMethod;
563 int resampleThreshold;
564
565 if (param == NULL)
566 {
567 // Default value
568 normalizeSize = 0;
569 resampleMethod = PRC_RESAMPLE_DEFAULT_METHOD_COMMON;
570 resampleThreshold = PRC_RESAMPLE_DEFAULT_THRESHOLD_COMMON;
571 }
572 else
573 {
574 normalizeSize = param->normalizeSize;
575 resampleMethod = param->resampleMethod;
576 resampleThreshold = param->resampleThreshold;
577 }
578
579 if (normalizeSize > 0)
580 {
581 // Carry out normalization sometime in the future
582 // First, get the bounding box values for normalization.
583 PRCBoundingBox boundingBox;
584 PRCPoint *point;
585 int size;
586
587 boundingBox.x1 = PRC_LARGE_ENOUGH_X;
588 boundingBox.y1 = PRC_LARGE_ENOUGH_Y;
589 boundingBox.x2 = PRC_SMALL_ENOUGH_X;
590 boundingBox.y2 = PRC_SMALL_ENOUGH_Y;
591
592 point = strokes->points;
593 size = strokes->size;
594
595 for (iPoint = 0; iPoint < size; iPoint++, point++)
596 {
597 if (PRC_IsPenUpMarker(point))
598 continue;
599 if (point->x < boundingBox.x1)
600 boundingBox.x1 = point->x;
601 if (point->x > boundingBox.x2)
602 boundingBox.x2 = point->x;
603 if (point->y < boundingBox.y1)
604 boundingBox.y1 = point->y;
605 if (point->y > boundingBox.y2)
606 boundingBox.y2 = point->y;
607 }
608
609 wx = boundingBox.x2 - boundingBox.x1;
610 wy = boundingBox.y2 - boundingBox.y1;
611 w = (wx >= wy) ? wx : wy;
612 dx = (boundingBox.x1 + boundingBox.x2) / 2 - w / 2;
613 dy = (boundingBox.y1 + boundingBox.y2) / 2 - w / 2;
614 }
615
616 // All the information required for normalization has been collected at this point.
617 // From this point onward, everything from characteristic point extraction until normalization is done at once.
618 // In reality, while it would be nice to be able to overwrite the coordinate values once they were normalized to the pointArray in rawStroke, this is supposed to be nondestructive, so we can't.
619 //
620
621 // It's incredibly dirty, but in order to use lineSegmentAngleArray as a u16 array temporarily as a work area pointArray, it must be divided into two parts and used as a work area.
622 //
623 //
624
625 data = &pattern->data;
626 selectedPoints = (u16 *)data->lineSegmentAngleArray;
627 selectedPointNum = 0;
628
629 // { OSTick start, end;
630 // start = OS_GetTick();
631 if (resampleMethod == PRC_RESAMPLE_METHOD_NONE)
632 {
633 // Use the raw dot sequence data without resampling
634 if (!PRC_ResampleStrokes_None
635 (selectedPoints, &selectedPointNum, maxPointCount, maxStrokeCount, strokes, 0,
636 (void *)data->pointArray))
637 {
638 selectedPointNum = 0;
639 }
640 }
641 else
642 {
643 // Sampling with param->resampleThreshold as threshold value
644 BOOL result = FALSE;
645 int threshold;
646
647 threshold = resampleThreshold;
648 if (normalizeSize > 0)
649 {
650 // Adjust threshold by the amount of size normalization
651 if (resampleMethod == PRC_RESAMPLE_METHOD_DISTANCE
652 || resampleMethod == PRC_RESAMPLE_METHOD_RECURSIVE)
653 {
654 if (threshold > 0)
655 {
656 // threshold = (threshold * w + normalizeSize - 1) / normalizeSize;
657 // If rounded up, specifying a small threshold will make it too boring, you see.
658 threshold = threshold * w / normalizeSize;
659 if (threshold == 0)
660 threshold = 1;
661 }
662 }
663 }
664
665 switch (resampleMethod)
666 {
667 case PRC_RESAMPLE_METHOD_DISTANCE:
668 result =
669 PRC_ResampleStrokes_Distance(selectedPoints, &selectedPointNum, maxPointCount,
670 maxStrokeCount, strokes, threshold,
671 (void *)data->pointArray);
672 break;
673 case PRC_RESAMPLE_METHOD_ANGLE:
674 result =
675 PRC_ResampleStrokes_Angle(selectedPoints, &selectedPointNum, maxPointCount,
676 maxStrokeCount, strokes, threshold,
677 (void *)data->pointArray);
678 break;
679 case PRC_RESAMPLE_METHOD_RECURSIVE:
680 result =
681 PRC_ResampleStrokes_Recursive(selectedPoints, &selectedPointNum, maxPointCount,
682 maxStrokeCount, strokes, threshold,
683 (void *)data->pointArray);
684 break;
685 default:
686 OS_Warning("invalid resample method type");
687 break;
688 }
689
690 if (!result)
691 {
692 selectedPointNum = 0;
693 }
694 }
695 // end = OS_GetTick();
696 // OS_Printf("// Resample: %lld��s\n", OS_TicksToMicroSeconds(end-start));
697 // }
698
699 SDK_ASSERT(selectedPointNum <= maxPointCount);
700
701 // Pack into pointArray while normalizing the characteristic points.
702 wholePointCount = 0;
703 strokeCount = 0;
704
705 if (selectedPointNum > 0)
706 {
707 int i;
708 BOOL newFlag;
709 PRCPoint *dstPoint;
710 PRCPoint prevPoint;
711 PRCPoint *point;
712 PRCPoint *inputPoints;
713 int pointCount;
714
715 inputPoints = strokes->points;
716
717 pointCount = 0;
718 dstPoint = (PRCPoint *)data->pointArray;
719 prevPoint.x = -1;
720 prevPoint.y = -1;
721 newFlag = TRUE;
722
723 if (normalizeSize > 0)
724 {
725 // Regularize with normalizeSize
726 u32 scale;
727
728 scale = (((u32)normalizeSize) << 16) / (w + 1);
729
730 for (i = 0; i < selectedPointNum; i++)
731 {
732 s16 x, y;
733 point = &inputPoints[selectedPoints[i]];
734 if (selectedPoints[i] == (u16)-1 || PRC_IsPenUpMarker(point))
735 {
736 // End of the stroke
737 if (pointCount >= 2)
738 {
739 dstPoint->x = prevPoint.x = PRC_PEN_UP_MARKER_X;
740 dstPoint->y = prevPoint.y = PRC_PEN_UP_MARKER_Y;
741 dstPoint++;
742 wholePointCount++;
743 strokeCount++;
744 }
745 else
746 {
747 // If there are less than two points, the stroke is not valid.
748 int i;
749 for (i = 0; i < pointCount; i++)
750 {
751 // Go back
752 dstPoint--;
753 wholePointCount--;
754 }
755 }
756 newFlag = TRUE;
757 pointCount = 0;
758 }
759 else
760 {
761 // Not the end
762
763 // Regularization of the coordinates
764 // x = (s16)((int)(point->x-dx) * normalizeSize / (w+1));
765 // y = (s16)((int)(point->y-dy) * normalizeSize / (w+1));
766 x = (s16)(((u32)(point->x - dx) * scale) >> 16);
767 y = (s16)(((u32)(point->y - dy) * scale) >> 16);
768 // Don't save if coordinates are the same as those just before the normalization result
769 if (prevPoint.x != x || prevPoint.y != y)
770 {
771 dstPoint->x = prevPoint.x = x;
772 dstPoint->y = prevPoint.y = y;
773 dstPoint++;
774 wholePointCount++;
775 pointCount++;
776 }
777 newFlag = FALSE;
778 }
779 }
780 }
781 else
782 {
783 // Copied directly without normalization
784
785 for (i = 0; i < selectedPointNum; i++)
786 {
787 point = &inputPoints[selectedPoints[i]];
788 if (selectedPoints[i] == (u16)-1 || PRC_IsPenUpMarker(point))
789 {
790 // End of the stroke
791 if (pointCount >= 2)
792 {
793 dstPoint->x = prevPoint.x = PRC_PEN_UP_MARKER_X;
794 dstPoint->y = prevPoint.y = PRC_PEN_UP_MARKER_Y;
795 dstPoint++;
796 wholePointCount++;
797 strokeCount++;
798 }
799 else
800 {
801 // If there are less than two points, the stroke is not valid.
802 int i;
803 for (i = 0; i < pointCount; i++)
804 {
805 // Go back
806 dstPoint--;
807 wholePointCount--;
808 }
809 }
810 newFlag = TRUE;
811 pointCount = 0;
812 }
813 else
814 {
815 // Not the end
816
817 // Don't save if coordinates are the same as immediately before
818 if (prevPoint.x != point->x || prevPoint.y != point->y)
819 {
820 *dstPoint = prevPoint = *point;
821 dstPoint++;
822 wholePointCount++;
823 pointCount++;
824 }
825 newFlag = FALSE;
826 }
827 }
828 }
829 SDK_ASSERTMSG(newFlag, "Internal error: non-terminated resampled stroke.");
830 }
831
832 data->pointCount = wholePointCount;
833 data->strokeCount = strokeCount;
834
835 if (wholePointCount == 0)
836 {
837 pattern->normalizeSize = (normalizeSize > 0) ? normalizeSize : 1;
838 return FALSE;
839 }
840
841 // { OSTick start, end;
842 // start = OS_GetTick();
843 PRCi_CalcExtraValues_Common((PRCiPatternData_Common *)data);
844 // end = OS_GetTick();
845 // OS_Printf("// CalcExtraValues: %lld��s\n", OS_TicksToMicroSeconds(end-start));
846 // }
847
848 if (normalizeSize > 0)
849 {
850 pattern->normalizeSize = normalizeSize;
851 }
852 else
853 {
854 PRCBoundingBox *box = &pattern->data.wholeBoundingBox;
855 pattern->normalizeSize = (box->x2 - box->x1);
856 if (pattern->normalizeSize < (box->y2 - box->y1))
857 {
858 pattern->normalizeSize = box->y2 - box->y1;
859 }
860 }
861
862 return TRUE;
863 }
864
PRCi_CalcExtraValues_Common(PRCiPatternData_Common * data)865 void PRCi_CalcExtraValues_Common(PRCiPatternData_Common *data)
866 {
867 int iStroke, iPoint;
868 BOOL newFlag;
869 int size;
870 fx32 strokeLength;
871 int strokeSize;
872 PRCBoundingBox boundingBox;
873 PRCPoint prevPoint;
874 const PRCPoint *point;
875
876 data->wholeLength = 0;
877 data->wholeBoundingBox.x1 = PRC_LARGE_ENOUGH_X;
878 data->wholeBoundingBox.y1 = PRC_LARGE_ENOUGH_Y;
879 data->wholeBoundingBox.x2 = PRC_SMALL_ENOUGH_X;
880 data->wholeBoundingBox.y2 = PRC_SMALL_ENOUGH_Y;
881
882 size = data->pointCount;
883
884 // Calculate the angle and length
885 {
886 point = data->pointArray;
887
888 // The first point and first point only is initialized to the direction of the second point.
889 if (size >= 2 && !PRC_IsPenUpMarker(point + 1))
890 {
891 prevPoint.x = (s16)(point[0].x * 2 - point[1].x);
892 prevPoint.y = (s16)(point[0].y * 2 - point[1].y);
893 }
894 else
895 {
896 prevPoint = point[0]; // give up
897 }
898
899 iStroke = 0;
900 newFlag = TRUE;
901 for (iPoint = 0; iPoint < size; iPoint++)
902 {
903 fx32 segmentLength;
904 u16 segmentAngle;
905 if (!PRC_IsPenUpMarker(point))
906 {
907 if (newFlag)
908 {
909 // Point to draw from
910 SDK_ASSERT(iStroke < data->strokeCount);
911
912 data->strokes[iStroke] = iPoint;
913 strokeLength = 0;
914 strokeSize = 0;
915
916 boundingBox.x1 = point->x;
917 boundingBox.y1 = point->y;
918 boundingBox.x2 = point->x;
919 boundingBox.y2 = point->y;
920
921 segmentLength = 0;
922 segmentAngle = PRCi_CalcAngle(&prevPoint, point);
923 }
924 else
925 {
926 // Drawing is in process
927 if (point->x < boundingBox.x1)
928 boundingBox.x1 = point->x;
929 if (point->x > boundingBox.x2)
930 boundingBox.x2 = point->x;
931 if (point->y < boundingBox.y1)
932 boundingBox.y1 = point->y;
933 if (point->y > boundingBox.y2)
934 boundingBox.y2 = point->y;
935
936 segmentLength = PRCi_CalcDistance(&prevPoint, point);
937 if (segmentLength == 0)
938 {
939 segmentLength = PRC_TINY_LENGTH;
940 }
941 segmentAngle = PRCi_CalcAngle(&prevPoint, point);
942 }
943
944 strokeLength += segmentLength;
945 strokeSize++;
946
947 prevPoint = *point;
948 newFlag = FALSE;
949 }
950 else
951 {
952 // End of one stroke
953
954 SDK_ASSERTMSG(!newFlag, "the pattern contains a zero-length stroke.");
955
956 if (strokeLength == 0)
957 {
958 OS_Warning("the pattern contains a zero-Euclid-length stroke.");
959 strokeLength = PRC_TINY_LENGTH;
960 }
961
962 data->strokeLengths[iStroke] = strokeLength;
963 data->strokeSizes[iStroke] = strokeSize;
964
965 if (iPoint + 1 < size)
966 {
967 // Not included in wholeLength
968 segmentLength = PRCi_CalcDistance(&prevPoint, point + 1);
969 if (segmentLength == 0)
970 {
971 segmentLength = PRC_TINY_LENGTH;
972 }
973 segmentAngle = PRCi_CalcAngle(&prevPoint, point + 1);
974 }
975 else
976 {
977 segmentLength = 0;
978 if (iPoint >= 2 && PRC_IsPenUpMarker(point - 2) && PRC_IsPenUpMarker(point - 1))
979 {
980 segmentAngle = PRCi_CalcAngle(point - 2, point - 1);
981 }
982 else
983 {
984 segmentAngle = 0; // give up
985 }
986 }
987 data->strokeBoundingBoxes[iStroke] = boundingBox;
988
989 if (boundingBox.x1 < data->wholeBoundingBox.x1)
990 data->wholeBoundingBox.x1 = boundingBox.x1;
991 if (boundingBox.x2 > data->wholeBoundingBox.x2)
992 data->wholeBoundingBox.x2 = boundingBox.x2;
993 if (boundingBox.y1 < data->wholeBoundingBox.y1)
994 data->wholeBoundingBox.y1 = boundingBox.y1;
995 if (boundingBox.y2 > data->wholeBoundingBox.y2)
996 data->wholeBoundingBox.y2 = boundingBox.y2;
997
998 data->wholeLength += strokeLength;
999
1000 iStroke++;
1001 newFlag = TRUE;
1002 }
1003
1004 data->lineSegmentLengthArray[iPoint] = segmentLength;
1005 data->lineSegmentAngleArray[iPoint] = segmentAngle;
1006
1007 point++;
1008 }
1009 SDK_ASSERTMSG(newFlag, "the pattern contains a non-terminated stroke.");
1010
1011 if (data->wholeLength == 0)
1012 {
1013 OS_Warning("the pattern is zero-Euclid-length.");
1014 data->wholeLength = PRC_TINY_LENGTH;
1015 }
1016 }
1017
1018 // Calculate length ratio
1019 // Calculate so that the total is FX32_ONE
1020 {
1021 fx32 sumSegmentToStrokeLength, sumStrokeToWholeLength;
1022 // fx32 sumSegmentToWholeLength;
1023 fx16 prevSegmentToStrokeRatio, prevStrokeToWholeRatio;
1024 // fx16 prevSegmentToWholeRatio;
1025
1026 iStroke = 0;
1027 sumStrokeToWholeLength = 0;
1028 // sumSegmentToWholeLength = 0;
1029 sumSegmentToStrokeLength = 0;
1030 prevStrokeToWholeRatio = 0;
1031 // prevSegmentToWholeRatio = 0;
1032 prevSegmentToStrokeRatio = 0;
1033 newFlag = TRUE;
1034 point = data->pointArray;
1035 for (iPoint = 0; iPoint < size; iPoint++, point++)
1036 {
1037 fx16 tmpRatio;
1038
1039 sumSegmentToStrokeLength += data->lineSegmentLengthArray[iPoint];
1040 tmpRatio = (fx16)FX_Div(sumSegmentToStrokeLength, data->strokeLengths[iStroke]);
1041 data->lineSegmentRatioToStrokeArray[iPoint] =
1042 (fx16)(tmpRatio - prevSegmentToStrokeRatio);
1043 prevSegmentToStrokeRatio = tmpRatio;
1044
1045 // sumSegmentToWholeLength += data->lineSegmentLengthArray[iPoint];
1046 // tmpRatio =
1047 // (fx16)FX_Div( sumSegmentToWholeLength,
1048 // data->wholeLength );
1049 // data->lineSegmentRatioToWholeArray[iPoint] = (fx16)(tmpRatio - prevSegmentToWholeRatio);
1050 // prevSegmentToWholeRatio = tmpRatio;
1051
1052 if (!PRC_IsPenUpMarker(point))
1053 {
1054 if (newFlag)
1055 {
1056 sumStrokeToWholeLength += data->strokeLengths[iStroke];
1057 tmpRatio = (fx16)FX_Div(sumStrokeToWholeLength, data->wholeLength);
1058 data->strokeRatios[iStroke] = (fx16)(tmpRatio - prevStrokeToWholeRatio);
1059 prevStrokeToWholeRatio = tmpRatio;
1060 newFlag = FALSE;
1061 }
1062 }
1063 else
1064 {
1065 iStroke++;
1066 newFlag = TRUE;
1067 }
1068 }
1069 }
1070 }
1071
PRCi_GetPatternStrokes_Common(PRCStrokes * strokes,const PRCiPatternData_Common * data)1072 void PRCi_GetPatternStrokes_Common(PRCStrokes *strokes, const PRCiPatternData_Common *data)
1073 {
1074 strokes->size = data->pointCount;
1075 strokes->capacity = data->pointCount;
1076 strokes->points = (PRCPoint *)data->pointArray;
1077 }
1078
1079 /*---------------------------------------------------------------------------*
1080 End of file
1081 *---------------------------------------------------------------------------*/
1082