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