1531 lines
44 KiB
C
Executable File
1531 lines
44 KiB
C
Executable File
/***************************************************************************************
|
|
*
|
|
* WRITEPAD(r): Handwriting Recognition Engine (HWRE) and components.
|
|
* Copyright (c) 2001-2016 PhatWare (r) Corp. All rights reserved.
|
|
*
|
|
* Licensing and other inquires: <developer@phatware.com>
|
|
* Developer: Stan Miasnikov, et al. (c) PhatWare Corp. <http://www.phatware.com>
|
|
*
|
|
* WRITEPAD HWRE is free software: you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation, either version 3 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* THE MATERIAL EMBODIED ON THIS SOFTWARE IS PROVIDED TO YOU "AS-IS"
|
|
* AND WITHOUT WARRANTY OF ANY KIND, EXPRESS, IMPLIED OR OTHERWISE,
|
|
* INCLUDING WITHOUT LIMITATION, ANY WARRANTY OF MERCHANTABILITY OR
|
|
* FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL PHATWARE CORP.
|
|
* BE LIABLE TO YOU OR ANYONE ELSE FOR ANY DIRECT, SPECIAL, INCIDENTAL,
|
|
* INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, OR ANY DAMAGES WHATSOEVER,
|
|
* INCLUDING WITHOUT LIMITATION, LOSS OF PROFIT, LOSS OF USE, SAVINGS
|
|
* OR REVENUE, OR THE CLAIMS OF THIRD PARTIES, WHETHER OR NOT PHATWARE CORP.
|
|
* HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH LOSS, HOWEVER CAUSED AND ON
|
|
* ANY THEORY OF LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE
|
|
* POSSESSION, USE OR PERFORMANCE OF THIS SOFTWARE.
|
|
* See the GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with WritePad. If not, see <http://www.gnu.org/licenses/>.
|
|
*
|
|
**************************************************************************************/
|
|
|
|
#include <jni.h>
|
|
#include <sys/time.h>
|
|
#include <time.h>
|
|
#include <stdint.h>
|
|
#include <ctype.h>
|
|
#include <stdlib.h>
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
#include <android/log.h>
|
|
|
|
#include "InkWrapper.h"
|
|
#include "RecognizerWrapper.h"
|
|
#include "ligstate.h"
|
|
#include "letimg.h"
|
|
#include "ShapeAPI.h"
|
|
|
|
#define MAX_PATH 260
|
|
|
|
|
|
//#define USER_DICTIONARY "WritePad_User.dct"
|
|
//#define USER_STATISTICS "WritePad_Stat.lrn"
|
|
//#define USER_CORRECTOR "WritePad_Corr.cwl"
|
|
//#define DEFAULT_DICTIONARY "English"
|
|
|
|
#ifndef false
|
|
#define false 0
|
|
#endif
|
|
#ifndef true
|
|
#define true 1
|
|
#endif
|
|
|
|
|
|
static INK_DATA_PTR _inkData = NULL;
|
|
static RECOGNIZER_PTR _recognizer = NULL;
|
|
static int _currentStroke = -1;
|
|
static char _szPath[MAX_PATH] = { 0 };
|
|
|
|
#define MAX_XU_CONVERTS 5
|
|
#define MAX_CMD_WORDS 4
|
|
#define MAX_CMD_LENGHT 16
|
|
|
|
|
|
static int _iHexes[MAX_XU_CONVERTS] = { 0x08a, 0x08c, 0x09a, 0x09c, 0x09f };
|
|
static int _iUnicodes[MAX_XU_CONVERTS] = { 352, 338, 353, 339, 376 };
|
|
|
|
static int u_strlen(const unsigned short * str) {
|
|
register int i = 0;
|
|
for (i = 0; str[i] != 0 && i < 2048; i++)
|
|
;
|
|
return i;
|
|
}
|
|
|
|
// JNI BUG: if the first character of the UTF-8 string has high bit set to 1 (ie char code > 127)
|
|
// JNI crashes in this implementation. One way to avoid it is to add an extra character in front
|
|
// which code is less than 128
|
|
|
|
/* ************************************************************************** */
|
|
/* * Convert char string to UNICODE * */
|
|
/* ************************************************************************** */
|
|
|
|
static int StrToUNICODE(unsigned short * tstr, const char * str, int cMax) {
|
|
register int i, j;
|
|
|
|
for (i = 0; i < cMax && str[i] != 0; i++) {
|
|
|
|
tstr[i] = (unsigned short) (unsigned char) str[i];
|
|
/* this causes crash when translating to UTF string; do not use may relate to the bug
|
|
described above
|
|
if((unsigned char)str[i]>=0x08a && (unsigned char)str[i]<=0x09f)
|
|
{
|
|
for (j=0; j<MAX_XU_CONVERTS; j++)
|
|
{
|
|
if((unsigned char)str[i]==_iHexes[j])
|
|
tstr[i] = _iUnicodes[j];
|
|
}
|
|
}
|
|
*/
|
|
}
|
|
|
|
tstr[i] = 0;
|
|
return i;
|
|
}
|
|
|
|
/* ************************************************************************** */
|
|
/* * Convert UNICODE string to char * */
|
|
/* ************************************************************************** */
|
|
|
|
static int UNICODEtoStr(char * str, const unsigned short * tstr, int cMax)
|
|
{
|
|
register int i, j;
|
|
|
|
for (i = 0; i < cMax && tstr[i] != 0; i++)
|
|
{
|
|
if (tstr[i] < 0xff)
|
|
str[i] = ((unsigned char) tstr[i]);
|
|
else
|
|
str[i] = '?';
|
|
}
|
|
str[i] = 0;
|
|
return i;
|
|
}
|
|
|
|
static const unsigned short * UTF8ToUnicode(const unsigned char *Src)
|
|
{
|
|
if (Src == NULL || *Src == 0)
|
|
return NULL;
|
|
|
|
int i = 0;
|
|
int outputlen = 0;
|
|
int SrcLen = strlen((const char *) Src);
|
|
|
|
// unicode will be the same or shorter
|
|
int DestLen = SrcLen + 2;
|
|
unsigned short * strDest = (unsigned short *) malloc(DestLen
|
|
* sizeof(unsigned short));
|
|
if (NULL == strDest)
|
|
return NULL;
|
|
|
|
for (i = 0; i < SrcLen;) {
|
|
if (outputlen >= DestLen - 1) {
|
|
//overflow detected
|
|
break;
|
|
}
|
|
|
|
else if ((0xe0 & Src[i]) == 0xe0) {
|
|
strDest[outputlen++] = (unsigned short) ((((int) Src[i] & 0x0f)
|
|
<< 12) | (((int) Src[i + 1] & 0x3f) << 6) | (Src[i + 2]
|
|
& 0x3f));
|
|
i += 3;
|
|
} else if ((0xc0 & Src[i]) == 0xc0) {
|
|
strDest[outputlen++] = (unsigned short) (((int) Src[i] & 0x1f) << 6
|
|
| (Src[i + 1] & 0x3f));
|
|
i += 2;
|
|
} else {
|
|
strDest[outputlen++] = (unsigned short) Src[i];
|
|
++i;
|
|
}
|
|
}
|
|
strDest[outputlen] = '\0';
|
|
return strDest;
|
|
}
|
|
|
|
static const char * UnicodeToUTF8(const unsigned short *Src)
|
|
{
|
|
if (Src == NULL || *Src == 0)
|
|
return NULL;
|
|
|
|
int i = 0;
|
|
int outputlen = 0; /*bytes */
|
|
int SrcLen = u_strlen(Src);
|
|
int DstLen = 2 + 3 * SrcLen;
|
|
|
|
unsigned char * strDest = (unsigned char *) malloc(DstLen);
|
|
if (NULL == strDest)
|
|
return NULL;
|
|
|
|
for (i = 0; i < SrcLen; i++)
|
|
{
|
|
if (outputlen >= DstLen - 1) {
|
|
//overflow detected
|
|
break;
|
|
}
|
|
|
|
if (0x0800 <= Src[i]) {
|
|
strDest[outputlen++] = (((Src[i] >> 12) & 0x0f) | 0xe0);
|
|
strDest[outputlen++] = (((Src[i] >> 6) & 0x3f) | 0x80);
|
|
strDest[outputlen++] = ((Src[i] & 0x3f) | 0x80);
|
|
} else if (0x800 > Src[i] && 0x80 <= Src[i]) {
|
|
strDest[outputlen++] = (((Src[i] >> 6) & 0x1f) | 0xc0);
|
|
strDest[outputlen++] = ((Src[i] & 0x3f) | 0x80);
|
|
} else if (0x80 > Src[i]) {
|
|
strDest[outputlen++] = (unsigned char) Src[i];
|
|
}
|
|
}
|
|
strDest[outputlen] = 0;
|
|
return (const char *) strDest;
|
|
}
|
|
static jstring StringToJstringA(JNIEnv* env, const char * string)
|
|
{
|
|
jstring result = NULL;
|
|
int len = strlen(string);
|
|
unsigned short * uResult = (unsigned short *) malloc((len + 2) * sizeof( unsigned short ));
|
|
if (uResult == NULL)
|
|
return NULL;
|
|
StrToUNICODE(uResult, string, len);
|
|
const char * utfResult = UnicodeToUTF8(uResult);
|
|
free((void *) uResult);
|
|
|
|
if (NULL != utfResult)
|
|
{
|
|
result = (*env)->NewStringUTF(env, utfResult);
|
|
free((void *) utfResult);
|
|
}
|
|
else
|
|
{
|
|
result = (*env)->NewStringUTF( env, string);
|
|
}
|
|
return result;
|
|
}
|
|
|
|
|
|
static jstring StringToJstring(JNIEnv* env, const UCHR * string)
|
|
{
|
|
jstring result = NULL;
|
|
#ifdef HW_RECINT_UNICODE
|
|
const char * utfResult = UnicodeToUTF8(string);
|
|
#else
|
|
unsigned short * uResult;
|
|
int len = strlen(string);
|
|
uResult = (unsigned short *) malloc((len + 2) * sizeof( unsigned short ));
|
|
if (uResult == NULL)
|
|
return NULL;
|
|
StrToUNICODE(uResult, string, len);
|
|
const char * utfResult = UnicodeToUTF8(uResult);
|
|
free((void *) uResult);
|
|
#endif // HW_RECINT_UNICODE
|
|
|
|
if (NULL != utfResult)
|
|
{
|
|
result = (*env)->NewStringUTF(env, utfResult);
|
|
free((void *) utfResult);
|
|
}
|
|
#ifndef HW_RECINT_UNICODE
|
|
else
|
|
{
|
|
result = (*env)->NewStringUTF( env, string);
|
|
}
|
|
#endif // HW_RECINT_UNICODE
|
|
return result;
|
|
}
|
|
|
|
static const char * JstringToStringA(JNIEnv* env, jstring jstr)
|
|
{
|
|
jboolean isCopy = JNI_FALSE;
|
|
const char * string = (*env)->GetStringUTFChars(env, jstr, &isCopy );
|
|
const char * result = NULL;
|
|
|
|
const unsigned short * uString = UTF8ToUnicode((const unsigned char *)string);
|
|
if (uString != NULL)
|
|
{
|
|
int len = u_strlen(uString);
|
|
char * cString = (char *) malloc(len + 1);
|
|
UNICODEtoStr(cString, uString, len);
|
|
result = cString;
|
|
free((void *) uString);
|
|
}
|
|
else
|
|
{
|
|
result = strdup(string);
|
|
}
|
|
if ( string && isCopy == JNI_TRUE)
|
|
(*env)->ReleaseStringUTFChars(env, jstr, string);
|
|
return result;
|
|
}
|
|
|
|
static const UCHR * JstringToString(JNIEnv* env, jstring jstr)
|
|
{
|
|
jboolean isCopy = JNI_FALSE;
|
|
const char *string = (*env)->GetStringUTFChars(env, jstr, &isCopy );
|
|
const UCHR * result = NULL;
|
|
|
|
const unsigned short * uString = UTF8ToUnicode((const unsigned char *)string);
|
|
#ifdef HW_RECINT_UNICODE
|
|
result = (const UCHR *)uString;
|
|
#else
|
|
if (uString != NULL)
|
|
{
|
|
int len = u_strlen(uString);
|
|
char * cString = (char *) malloc(len + 1);
|
|
UNICODEtoStr(cString, uString, len);
|
|
result = cString;
|
|
free((void *) uString);
|
|
}
|
|
else
|
|
{
|
|
result = strdup(string);
|
|
}
|
|
#endif // HW_RECINT_UNICODE
|
|
if ( string && isCopy == JNI_TRUE)
|
|
(*env)->ReleaseStringUTFChars(env, jstr, string);
|
|
return result;
|
|
}
|
|
|
|
static long _getTime(void) {
|
|
struct timeval now;
|
|
|
|
gettimeofday(&now, NULL);
|
|
return (long) (now.tv_sec * 1000 + now.tv_usec / 1000);
|
|
}
|
|
|
|
static char userDict[MAX_PATH] = {0};
|
|
static char learner[MAX_PATH] = {0};
|
|
static char corrector[MAX_PATH] = {0};
|
|
|
|
|
|
jint Java_com_phatware_writepad_WritePadAPI_recognizerInit(JNIEnv* env, jobject thiz, jstring jpath, jint languageId, jbyteArray data, jstring pUserDict, jstring pLearner, jstring pCorrector)
|
|
{
|
|
jboolean isCopy = JNI_FALSE;
|
|
const char * path = (*env)->GetStringUTFChars(env, jpath, &isCopy);
|
|
|
|
userDict[0] = 0;
|
|
learner[0] = 0;
|
|
corrector[0] = 0;
|
|
|
|
// properly release recognizer
|
|
// Java_com_phatware_writepad_WritePadAPI_freeRecognizer( env, thiz, pUserDict, pLearner, pCorrector );
|
|
|
|
if (path != NULL)
|
|
{
|
|
strcpy(_szPath, path);
|
|
strcat(_szPath, "/");
|
|
strcpy(userDict, _szPath);
|
|
strcpy(learner, _szPath);
|
|
strcpy(corrector, _szPath);
|
|
}
|
|
|
|
const char * t = JstringToStringA(env, pUserDict);
|
|
if ( NULL != t )
|
|
{
|
|
strcat(userDict, t );
|
|
free( (void *)t );
|
|
}
|
|
t = JstringToStringA(env, pLearner);
|
|
if ( NULL != t )
|
|
{
|
|
strcat(learner, t );
|
|
free( (void *)t );
|
|
}
|
|
t = JstringToStringA(env, pCorrector);
|
|
if ( NULL != t )
|
|
{
|
|
strcat(corrector, t );
|
|
free( (void *)t );
|
|
}
|
|
|
|
if ( isCopy == JNI_TRUE && path )
|
|
(*env)->ReleaseStringUTFChars(env, jpath, path);
|
|
|
|
int flags = -1;
|
|
_inkData = INK_InitData();
|
|
if (NULL == _inkData)
|
|
{
|
|
return -1;
|
|
}
|
|
_recognizer = HWR_InitRecognizer(NULL, userDict, learner, corrector, languageId, &flags);
|
|
if (NULL == _recognizer)
|
|
{
|
|
INK_FreeData( _inkData );
|
|
_inkData = NULL;
|
|
return -1;
|
|
}
|
|
|
|
_currentStroke = -1;
|
|
|
|
isCopy = JNI_FALSE;
|
|
int dataSize = (*env)->GetArrayLength(env, data);
|
|
jboolean result;
|
|
jbyte * pMem = (*env)->GetByteArrayElements(env, data, &isCopy);
|
|
|
|
if ( dataSize > 0 )
|
|
{
|
|
result = HWR_SetLetterShapes( _recognizer, (const unsigned char *)pMem );
|
|
}
|
|
else
|
|
{
|
|
result = HWR_SetDefaultShapes( _recognizer );
|
|
}
|
|
|
|
if ( isCopy == JNI_TRUE && pMem )
|
|
(*env)->ReleaseByteArrayElements(env, data, pMem, JNI_ABORT);
|
|
|
|
return flags;
|
|
}
|
|
|
|
jboolean Java_com_phatware_writepad_WritePadAPI_resetLearner(JNIEnv* env) {
|
|
if (_recognizer != NULL) {
|
|
return HWR_ResetLearner(_recognizer, learner);
|
|
}
|
|
return false;
|
|
}
|
|
|
|
jboolean Java_com_phatware_writepad_WritePadAPI_reloadLearner(JNIEnv* env) {
|
|
if (_recognizer != NULL) {
|
|
return HWR_ReloadLearner(_recognizer, learner);
|
|
}
|
|
return false;
|
|
}
|
|
|
|
jboolean Java_com_phatware_writepad_WritePadAPI_saveLearner(JNIEnv* env) {
|
|
if (_recognizer != NULL) {
|
|
return HWR_SaveLearner(_recognizer, learner);
|
|
}
|
|
return false;
|
|
}
|
|
|
|
|
|
jboolean Java_com_phatware_writepad_WritePadAPI_resetAutocorrector(JNIEnv* env) {
|
|
if (_recognizer != NULL) {
|
|
BOOL result = HWR_ResetAutoCorrector(_recognizer, corrector);
|
|
return result;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
jboolean Java_com_phatware_writepad_WritePadAPI_reloadAutocorrector(JNIEnv* env) {
|
|
if (_recognizer != NULL) {
|
|
BOOL result = HWR_ReloadAutoCorrector(_recognizer, corrector);
|
|
return HWR_ReloadAutoCorrector(_recognizer, corrector);
|
|
}
|
|
return false;
|
|
}
|
|
|
|
jboolean Java_com_phatware_writepad_WritePadAPI_saveWordList(JNIEnv* env) {
|
|
if (_recognizer != NULL) {
|
|
return HWR_SaveWordList(_recognizer, corrector);
|
|
}
|
|
return false;
|
|
}
|
|
|
|
|
|
|
|
jboolean Java_com_phatware_writepad_WritePadAPI_resetUserDict(JNIEnv* env) {
|
|
if (_recognizer != NULL) {
|
|
BOOL result = HWR_ResetUserDict(_recognizer, userDict);
|
|
return result;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
jboolean Java_com_phatware_writepad_WritePadAPI_reloadUserDict(JNIEnv* env) {
|
|
if (_recognizer != NULL) {
|
|
BOOL result = HWR_ReloadUserDict(_recognizer, userDict);
|
|
return result;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
jboolean Java_com_phatware_writepad_WritePadAPI_isPointStroke(JNIEnv* env, jobject thiz, jint nStroke )
|
|
{
|
|
if ( _inkData != NULL )
|
|
{
|
|
CGRect rect = {0,0,0,0};
|
|
if ( nStroke < 0 )
|
|
nStroke = INK_StrokeCount( _inkData, false ) - 1;
|
|
if ( nStroke < 0 )
|
|
return false;
|
|
if ( INK_GetStrokeRect( _inkData, nStroke, &rect, false) )
|
|
{
|
|
if ( rect.size.width <= 2.0f && rect.size.height <= 2.0f )
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
jint Java_com_phatware_writepad_WritePadAPI_checkStrokeNewLine(JNIEnv* env, jobject thiz, jint nStroke )
|
|
{
|
|
int result = GEST_NONE;
|
|
if ( _inkData != NULL )
|
|
{
|
|
CGRect rect = {0,0,0,0};
|
|
CGStroke pStroke = NULL;
|
|
float width = 3.0f;
|
|
|
|
if ( nStroke < 0 )
|
|
nStroke = INK_StrokeCount( _inkData, false ) - 1;
|
|
if ( nStroke < 0 )
|
|
return 0;
|
|
if ( ! INK_GetStrokeRect( _inkData, nStroke, &rect , false) )
|
|
return 0;
|
|
int len = INK_GetStrokeP( _inkData, nStroke, &pStroke, &width, NULL);
|
|
if (len > 5)
|
|
{
|
|
result = HWR_CheckGesture( GEST_DELETE | GEST_BACK, pStroke, len, 1, 5 );
|
|
}
|
|
if (pStroke != NULL)
|
|
free((void *) pStroke);
|
|
if ( result == GEST_DELETE || result == GEST_BACK )
|
|
return 0;
|
|
if ( rect.size.width < width && rect.size.height < width )
|
|
return 0;
|
|
if ( rect.size.width > 2.0f * rect.size.height && rect.size.height <= 2.0f * width )
|
|
return 0;
|
|
|
|
int xx = (int)rect.origin.x;
|
|
int yy = (int)rect.origin.y;
|
|
return (jint)((xx & 0xffff) | ((yy << 16) &0xffff0000));
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
jint Java_com_phatware_writepad_WritePadAPI_getInkRightCoordinate(JNIEnv* env, jobject thiz )
|
|
{
|
|
if ( _inkData != NULL )
|
|
{
|
|
CGRect rect = {0,0,0,0};
|
|
|
|
if ( INK_GetDataRect( _inkData, &rect, false ) )
|
|
{
|
|
return rect.origin.x + rect.size.width;
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
jboolean Java_com_phatware_writepad_WritePadAPI_saveUserDict(JNIEnv* env)
|
|
{
|
|
if (_recognizer != NULL)
|
|
{
|
|
return HWR_SaveUserDict(_recognizer, userDict);
|
|
}
|
|
return false;
|
|
}
|
|
|
|
jboolean Java_com_phatware_writepad_WritePadAPI_setDictionaryData(JNIEnv* env, jobject thiz, jbyteArray buff)
|
|
{
|
|
jbyte * data = NULL;
|
|
jboolean result = false;
|
|
if (_recognizer == NULL)
|
|
return false;
|
|
|
|
jboolean isCopy = JNI_FALSE;
|
|
data = (*env)->GetByteArrayElements(env, buff, &isCopy );
|
|
if (data != NULL)
|
|
{
|
|
result = HWR_SetDictionaryData(_recognizer, (const char *)data, FLAG_MAINDICT);
|
|
(*env)->ReleaseByteArrayElements(env, buff, data, JNI_ABORT);
|
|
if ( isCopy == JNI_TRUE )
|
|
(*env)->ReleaseByteArrayElements(env, buff, data, JNI_ABORT);
|
|
}
|
|
return result;
|
|
}
|
|
|
|
|
|
|
|
void Java_com_phatware_writepad_WritePadAPI_freeRecognizer(JNIEnv* env, jobject thiz, jstring pUserDict, jstring pLearner, jstring pCorrector)
|
|
{
|
|
if (_recognizer != NULL)
|
|
{
|
|
if ( _szPath[0] == 0 )
|
|
{
|
|
HWR_FreeRecognizer(_recognizer, NULL, NULL, NULL );
|
|
}
|
|
else
|
|
{
|
|
char userDict[MAX_PATH];
|
|
char learner[MAX_PATH];
|
|
char corrector[MAX_PATH];
|
|
|
|
userDict[0] = 0;
|
|
learner[0] = 0;
|
|
corrector[0] = 0;
|
|
strcpy(userDict, _szPath);
|
|
strcpy(learner, _szPath);
|
|
strcpy(corrector, _szPath);
|
|
|
|
const char * t = JstringToStringA(env, pUserDict);
|
|
if ( NULL != t )
|
|
{
|
|
strcat(userDict, t );
|
|
free( (void *)t );
|
|
}
|
|
t = JstringToStringA(env, pLearner);
|
|
if ( NULL != t )
|
|
{
|
|
strcat(learner, t );
|
|
free( (void *)t );
|
|
}
|
|
t = JstringToStringA(env, pCorrector);
|
|
if ( NULL != t )
|
|
{
|
|
strcat(corrector, t );
|
|
free( (void *)t );
|
|
}
|
|
|
|
HWR_FreeRecognizer(_recognizer, userDict, learner, corrector);
|
|
}
|
|
_recognizer = NULL;
|
|
}
|
|
if (_inkData != NULL)
|
|
{
|
|
INK_FreeData(_inkData);
|
|
_inkData = NULL;
|
|
}
|
|
_currentStroke = -1;
|
|
}
|
|
|
|
|
|
|
|
jint Java_com_phatware_writepad_WritePadAPI_getRecognizerFlags(JNIEnv * env) {
|
|
jint result = 0;
|
|
if (_recognizer != NULL) {
|
|
result = HWR_GetRecognitionFlags(_recognizer);
|
|
}
|
|
return result;
|
|
}
|
|
|
|
|
|
|
|
void Java_com_phatware_writepad_WritePadAPI_setRecognizerFlags(JNIEnv * env, jobject thiz, jint flags) {
|
|
if (_recognizer != NULL) {
|
|
HWR_SetRecognitionFlags(_recognizer, (unsigned int) flags);
|
|
}
|
|
}
|
|
|
|
|
|
jint Java_com_phatware_writepad_WritePadAPI_getRecognizerMode(JNIEnv * env) {
|
|
jint result = 0;
|
|
if (_recognizer != NULL) {
|
|
result = HWR_GetRecognitionMode(_recognizer);
|
|
}
|
|
return result;
|
|
}
|
|
|
|
void Java_com_phatware_writepad_WritePadAPI_setRecognizerMode(JNIEnv * env, jobject thiz, jint mode) {
|
|
if (_recognizer != NULL) {
|
|
HWR_SetRecognitionMode(_recognizer, mode);
|
|
}
|
|
}
|
|
|
|
void Java_com_phatware_writepad_WritePadAPI_stopRecognizer(JNIEnv* env) {
|
|
if (_recognizer != NULL) {
|
|
HWR_StopAsyncReco(_recognizer);
|
|
}
|
|
}
|
|
|
|
jstring Java_com_phatware_writepad_WritePadAPI_recognizeInkData(JNIEnv* env, jobject thiz, jint nDataLen, jboolean bAsync, jboolean bFlipY, jboolean bSort )
|
|
{
|
|
jstring result = NULL;
|
|
const UCHR * recognizedText = NULL;
|
|
if (_recognizer == NULL || _inkData == NULL || INK_StrokeCount(_inkData, false) < 1)
|
|
return NULL;
|
|
INK_DATA_PTR inkCopy = NULL;
|
|
if (bAsync)
|
|
{
|
|
// create ink copy before starting recognizer.
|
|
inkCopy = INK_CreateCopy(_inkData);
|
|
}
|
|
recognizedText = HWR_RecognizeInkData(_recognizer,
|
|
(inkCopy == NULL) ? _inkData : inkCopy, 0, nDataLen, bAsync, bFlipY,
|
|
bSort, false);
|
|
if (NULL != inkCopy)
|
|
{
|
|
INK_FreeData(inkCopy);
|
|
inkCopy = NULL;
|
|
}
|
|
if (recognizedText == NULL || *recognizedText == 0)
|
|
return NULL;
|
|
|
|
result = StringToJstring(env, recognizedText);
|
|
if ((long) result == (-1))
|
|
return NULL;
|
|
return result;
|
|
}
|
|
|
|
jboolean Java_com_phatware_writepad_WritePadAPI_preRecognizeInkData(JNIEnv* env, jobject thiz, jint nDataLen) {
|
|
const char * recognizedText = NULL;
|
|
if (_recognizer == NULL || _inkData == NULL || INK_StrokeCount(_inkData, false) < 1)
|
|
return false;
|
|
return HWR_PreRecognizeInkData(_recognizer, _inkData, nDataLen, false);
|
|
}
|
|
|
|
jboolean Java_com_phatware_writepad_WritePadAPI_newStroke(JNIEnv * env, jobject thiz, jfloat width, jint color) {
|
|
jint result = -1;
|
|
if (NULL != _inkData) {
|
|
result = INK_AddEmptyStroke(_inkData, width, (COLORREF) color);
|
|
}
|
|
_currentStroke = (int) result;
|
|
return result;
|
|
}
|
|
|
|
|
|
jint Java_com_phatware_writepad_WritePadAPI_getStrokeCount(JNIEnv * env) {
|
|
jint result = -1;
|
|
if (NULL != _inkData) {
|
|
result = INK_StrokeCount(_inkData, false);
|
|
}
|
|
return result;
|
|
}
|
|
|
|
jfloatArray Java_com_phatware_writepad_WritePadAPI_getStrokePoint( JNIEnv* env, jobject thiz, jint nStroke, jint nPixels )
|
|
{
|
|
jfloatArray result = NULL;
|
|
if ( _inkData != NULL )
|
|
{
|
|
float ret[2];
|
|
int pressure = 0;
|
|
jboolean r = INK_GetStrokePointP( _inkData, nStroke, nPixels, &ret[0], &ret[1], &pressure );
|
|
if ( r )
|
|
{
|
|
result = (*env)->NewFloatArray(env, 2);
|
|
(*env)->SetFloatArrayRegion( env, result, 0, 2, ret);
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
jboolean Java_com_phatware_writepad_WritePadAPI_deleteLastStroke(JNIEnv * env) {
|
|
jboolean result = false;
|
|
if (NULL != _inkData) {
|
|
result = INK_DeleteStroke(_inkData, -1);
|
|
}
|
|
return result;
|
|
}
|
|
|
|
jboolean Java_com_phatware_writepad_WritePadAPI_deleteStroke(JNIEnv * env, jobject thiz, jint nStroke )
|
|
{
|
|
jboolean result = false;
|
|
if (NULL != _inkData) {
|
|
result = INK_DeleteStroke(_inkData, nStroke );
|
|
}
|
|
return result;
|
|
}
|
|
|
|
jint Java_com_phatware_writepad_WritePadAPI_detectGesture(JNIEnv* env, jobject thiz, jint type)
|
|
{
|
|
jint result = GEST_NONE;
|
|
|
|
if (NULL != _inkData)
|
|
{
|
|
int nCnt = INK_StrokeCount(_inkData, false);
|
|
if (nCnt > 0)
|
|
{
|
|
CGStroke pStroke = NULL;
|
|
int len = INK_GetStrokeP(_inkData, nCnt - 1, &pStroke, NULL, NULL);
|
|
if (len > 5) {
|
|
result = HWR_CheckGesture((GESTURE_TYPE) type, pStroke, len, 1, 100);
|
|
}
|
|
if (pStroke != NULL)
|
|
free((void *) pStroke);
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
jint Java_com_phatware_writepad_WritePadAPI_addPixelToStroke(JNIEnv * env, jobject thiz, jint stroke, jfloat x, jfloat y) {
|
|
jint result = -1;
|
|
if (NULL != _inkData) {
|
|
result = INK_AddPixelToStroke(_inkData, stroke, x, y, DEFAULT_PRESSURE );
|
|
}
|
|
return result;
|
|
}
|
|
|
|
jboolean Java_com_phatware_writepad_WritePadAPI_resetRecognizer(JNIEnv * env) {
|
|
if (NULL != _recognizer) {
|
|
HWR_Reset(_recognizer);
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
jboolean Java_com_phatware_writepad_WritePadAPI_resetInkData(JNIEnv * env) {
|
|
if (NULL != _inkData) {
|
|
INK_Erase(_inkData);
|
|
_currentStroke = -1;
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
jstring Java_com_phatware_writepad_WritePadAPI_languageName(JNIEnv* env, jobject thiz)
|
|
{
|
|
jstring result = StringToJstringA(env, HWR_GetLanguageName(_recognizer));
|
|
return result;
|
|
}
|
|
|
|
jint Java_com_phatware_writepad_WritePadAPI_languageID(JNIEnv * env)
|
|
{
|
|
return HWR_GetLanguageID(_recognizer);
|
|
}
|
|
|
|
jboolean Java_com_phatware_writepad_WritePadAPI_newUserDict(JNIEnv * env)
|
|
{
|
|
if (NULL != _recognizer) {
|
|
return HWR_NewUserDict(_recognizer);
|
|
}
|
|
return false;
|
|
}
|
|
|
|
jboolean Java_com_phatware_writepad_WritePadAPI_addWordToUserDict(JNIEnv * env, jobject thiz, jstring jword) {
|
|
jboolean result = false;
|
|
if (NULL != _recognizer)
|
|
{
|
|
const UCHR * strWord = JstringToString(env, jword);
|
|
if (strWord != NULL)
|
|
{
|
|
result = HWR_AddUserWordToDict(_recognizer, strWord, true);
|
|
free((void *) strWord);
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
jboolean Java_com_phatware_writepad_WritePadAPI_resetResult(JNIEnv * env, jobject thiz) {
|
|
jboolean result = false;
|
|
if (NULL != _recognizer) {
|
|
result = HWR_EmptyWordList(_recognizer);
|
|
}
|
|
return result;
|
|
}
|
|
|
|
jboolean Java_com_phatware_writepad_WritePadAPI_isWordInDict(JNIEnv * env, jobject thiz, jstring jword) {
|
|
jboolean result = false;
|
|
if (_recognizer != NULL) {
|
|
const UCHR * word = JstringToString(env, jword);
|
|
if (word != NULL) {
|
|
result = HWR_IsWordInDict(_recognizer, word);
|
|
free((void *) word);
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
jint Java_com_phatware_writepad_WritePadAPI_getResultColumnCount(JNIEnv * env, jobject thiz) {
|
|
jint result = 0;
|
|
if (NULL != _recognizer) {
|
|
result = HWR_GetResultWordCount(_recognizer);
|
|
}
|
|
return result;
|
|
}
|
|
|
|
jint Java_com_phatware_writepad_WritePadAPI_getResultRowCount(JNIEnv * env, jobject thiz, jint col) {
|
|
jint result = 0;
|
|
if (NULL != _recognizer) {
|
|
result = HWR_GetResultAlternativeCount(_recognizer, col);
|
|
}
|
|
return result;
|
|
}
|
|
|
|
|
|
jstring Java_com_phatware_writepad_WritePadAPI_getRecognizedWord(JNIEnv * env, jobject thiz, jint col, jint row) {
|
|
jstring result = NULL;
|
|
if (NULL != _recognizer)
|
|
{
|
|
const UCHR * word = HWR_GetResultWord(_recognizer, col, row);
|
|
if (word != NULL)
|
|
{
|
|
result = StringToJstring(env, word);
|
|
if ((long) result == (-1))
|
|
result = NULL;
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
jstring Java_com_phatware_writepad_WritePadAPI_getAutocorrectorWord(JNIEnv * env, jobject thiz, jstring inWord)
|
|
{
|
|
jstring result = NULL;
|
|
if (_recognizer != NULL)
|
|
{
|
|
const UCHR * word = JstringToString(env, inWord);
|
|
if (word != NULL)
|
|
{
|
|
const UCHR * outWord = HWR_AutocorrectWord(_recognizer, word);
|
|
if (NULL != outWord)
|
|
{
|
|
result = StringToJstring(env, outWord);
|
|
if ((long) result == (-1))
|
|
result = NULL;
|
|
}
|
|
free((void *) word);
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
jint Java_com_phatware_writepad_WritePadAPI_getRecognizedWeight(JNIEnv * env, jobject thiz, jint col, jint row) {
|
|
jint result = 0;
|
|
if (NULL != _recognizer) {
|
|
result = HWR_GetResultWeight(_recognizer, col, row);
|
|
}
|
|
return result;
|
|
}
|
|
|
|
jboolean Java_com_phatware_writepad_WritePadAPI_learnerAddNewWord(JNIEnv * env, jobject thiz, jstring jword, jint weight) {
|
|
jboolean result = false;
|
|
if (NULL != _recognizer) {
|
|
const UCHR * word = JstringToString(env, jword);
|
|
if (word != NULL) {
|
|
result = HWR_LearnNewWord(_recognizer, word, weight);
|
|
free((void *) word);
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
jboolean Java_com_phatware_writepad_WritePadAPI_learnerReplaceWord(JNIEnv * env, jobject thiz, jstring jword1, jint weight1,
|
|
jstring jword2, jint weight2) {
|
|
jboolean result = false;
|
|
if (NULL != _recognizer)
|
|
{
|
|
const UCHR * word1 = JstringToString(env, jword1);
|
|
const UCHR * word2 = JstringToString(env, jword2);
|
|
if (word1 != NULL && word2 != NULL)
|
|
{
|
|
result = HWR_ReplaceWord(_recognizer, word1, weight1, word2, weight2);
|
|
free((void *) word1);
|
|
free((void *) word2);
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
jboolean Java_com_phatware_writepad_WritePadAPI_autocorrectorLearnWord(JNIEnv * env, jobject thiz, jstring jword1, jstring jword2, jint flags,
|
|
jboolean bReplace) {
|
|
jboolean result = false;
|
|
if (NULL != _recognizer)
|
|
{
|
|
const UCHR * word1 = JstringToString(env, jword1);
|
|
const UCHR * word2 = JstringToString(env, jword2);
|
|
if (word1 != NULL && word2 != NULL)
|
|
{
|
|
result = HWR_AddWordToWordList(_recognizer, word1, word2, flags, bReplace);
|
|
free((void *) word1);
|
|
free((void *) word2);
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
jstring Java_com_phatware_writepad_WritePadAPI_spellCheckWord(JNIEnv * env, jobject thiz, jstring jword, jboolean showlist )
|
|
{
|
|
const UCHR * strWord = JstringToString(env, jword);
|
|
if (strWord == NULL)
|
|
{
|
|
return jword;
|
|
}
|
|
jstring newWordFrom = NULL;
|
|
UCHR * pWordList = malloc( MAX_STRING_BUFFER * sizeof( UCHR ) );
|
|
if ( NULL != pWordList )
|
|
{
|
|
memset( pWordList, 0, MAX_STRING_BUFFER * sizeof( UCHR ) );
|
|
|
|
int flag = (showlist) ? HW_SPELL_LIST : 0;
|
|
if ( HWR_SpellCheckWord( _recognizer, strWord, pWordList, MAX_STRING_BUFFER - 1, flag ) == 0 )
|
|
{
|
|
newWordFrom = StringToJstring(env, &pWordList[0]);
|
|
}
|
|
free( (void *) pWordList );
|
|
free((void *) strWord);
|
|
}
|
|
if ( newWordFrom == NULL )
|
|
return jword;
|
|
return newWordFrom;
|
|
}
|
|
|
|
|
|
JNIEnv* myEnv;
|
|
|
|
const char *kInterfacePath = "com/phatware/writepad/WritePadAPI";
|
|
|
|
|
|
static JavaVM* gJavaVM;
|
|
static jobject gInterfaceObject;
|
|
|
|
int status;
|
|
int isAttached;
|
|
|
|
jclass interfaceClass;
|
|
jmethodID method;
|
|
|
|
int EnumWordListCallback(const UCHR * szWordFrom, const UCHR * szWordTo, unsigned int nFlags, void * pParam) {
|
|
JNIEnv *env;
|
|
isAttached = 0;
|
|
|
|
status = (*gJavaVM)->GetEnv(gJavaVM, (void **) &env, JNI_VERSION_1_4);
|
|
if (status < 0) {
|
|
status = (*gJavaVM)->AttachCurrentThread(gJavaVM, &env, NULL);
|
|
if (status < 0) {
|
|
return 0;
|
|
}
|
|
isAttached = 1;
|
|
}
|
|
if (interfaceClass == NULL){
|
|
interfaceClass = (*env)->GetObjectClass(env, gInterfaceObject);
|
|
}
|
|
|
|
if (!interfaceClass) {
|
|
// __android_log_print(ANDROID_LOG_INFO, "callback_handler"," failed to get class reference");
|
|
if (isAttached == 1)
|
|
(*gJavaVM)->DetachCurrentThread(gJavaVM);
|
|
return 0;
|
|
}
|
|
/* Find the callBack method ID */
|
|
|
|
if (method == NULL)
|
|
{
|
|
method = (*env)->GetStaticMethodID(env, interfaceClass, "onEnumWord", "(Ljava/lang/String;Ljava/lang/String;I)V");
|
|
}
|
|
|
|
if (!method) {
|
|
// __android_log_print(ANDROID_LOG_INFO, "callback_handler"," failed to get method ID");
|
|
if (isAttached == 1) {
|
|
(*gJavaVM)->DetachCurrentThread(gJavaVM);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
jstring newWordFrom = StringToJstring(env, szWordFrom);
|
|
jstring newWordTo = StringToJstring(env, szWordTo);
|
|
|
|
(*env)->CallStaticVoidMethod(env, interfaceClass, method, newWordFrom, newWordTo, nFlags);
|
|
(*env)->DeleteLocalRef(env, newWordFrom);
|
|
(*env)->DeleteLocalRef(env, newWordTo);
|
|
|
|
if (isAttached == 1) {
|
|
(*gJavaVM)->DetachCurrentThread(gJavaVM);
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
int EnumUserWordsCallback(const UCHR * szWord, void * pParam) {
|
|
JNIEnv *env;
|
|
isAttached = 0;
|
|
|
|
status = (*gJavaVM)->GetEnv(gJavaVM, (void **) &env, JNI_VERSION_1_4);
|
|
if (status < 0) {
|
|
//__android_log_print(ANDROID_LOG_INFO, "callback_handler: failed to get JNI environment, assuming native thread");
|
|
status = (*gJavaVM)->AttachCurrentThread(gJavaVM, &env, NULL);
|
|
if (status < 0) {
|
|
//__android_log_print(ANDROID_LOG_INFO, "callback_handler: failed to attach ", "current thread");
|
|
return 0;
|
|
}
|
|
isAttached = 1;
|
|
}
|
|
if (interfaceClass == NULL){
|
|
interfaceClass = (*env)->GetObjectClass(env, gInterfaceObject);
|
|
}
|
|
|
|
if (!interfaceClass) {
|
|
//__android_log_print(ANDROID_LOG_INFO, "callback_handler"," failed to get class reference");
|
|
if (isAttached == 1)
|
|
(*gJavaVM)->DetachCurrentThread(gJavaVM);
|
|
return 0;
|
|
}
|
|
|
|
if (method == NULL)
|
|
{
|
|
method = (*env)->GetStaticMethodID(env, interfaceClass, "onEnumUserWords", "(Ljava/lang/String;)V");
|
|
}
|
|
|
|
if (!method) {
|
|
// __android_log_print(ANDROID_LOG_INFO, "callback_handler"," failed to get method ID");
|
|
if (isAttached == 1) {
|
|
(*gJavaVM)->DetachCurrentThread(gJavaVM);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
jstring newWord = StringToJstring(env, szWord);
|
|
(*env)->CallStaticVoidMethod(env, interfaceClass, method, newWord);
|
|
(*env)->DeleteLocalRef(env, newWord);
|
|
|
|
if (isAttached == 1) {
|
|
(*gJavaVM)->DetachCurrentThread(gJavaVM);
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
jint Java_com_phatware_writepad_WritePadAPI_getEnumUserWordsList(JNIEnv * env, jobject thiz, void * param) {
|
|
jint result = 0;
|
|
if (NULL != _recognizer) {
|
|
interfaceClass = NULL;
|
|
method = NULL;
|
|
result = HWR_EnumUserWords(_recognizer, EnumUserWordsCallback, param);
|
|
}
|
|
return result;
|
|
}
|
|
|
|
jint Java_com_phatware_writepad_WritePadAPI_getEnumWordList(JNIEnv * env, jobject thiz, void * param) {
|
|
jint result = 0;
|
|
if (NULL != _recognizer) {
|
|
interfaceClass = NULL;
|
|
method = NULL;
|
|
result = HWR_EnumWordList(_recognizer, EnumWordListCallback, param);
|
|
}
|
|
return result;
|
|
}
|
|
|
|
|
|
jboolean Java_com_phatware_writepad_WritePadAPI_isLanguageSupported(JNIEnv * env, jobject thiz, jint langID) {
|
|
return HWR_IsLanguageSupported(langID);
|
|
}
|
|
|
|
|
|
void initClassHelper(JNIEnv *env, const char *path, jobject *objptr) {
|
|
jclass cls = (*env)->FindClass(env, path);
|
|
if (!cls) {
|
|
//__android_log_print(ANDROID_LOG_INFO, "initClassHelper: failed to get %s class reference", path);
|
|
return;
|
|
}
|
|
jmethodID constr = (*env)->GetMethodID(env, cls, "<init>", "()V");
|
|
if (!constr) {
|
|
//__android_log_print(ANDROID_LOG_INFO, "initClassHelper: failed to get %s constructor", path);
|
|
return;
|
|
}
|
|
jobject obj = (*env)->NewObject(env, cls, constr);
|
|
if (!obj) {
|
|
//__android_log_print(ANDROID_LOG_INFO, "initClassHelper: failed to create a %s object", path);
|
|
return;
|
|
}
|
|
(*objptr) = (*env)->NewGlobalRef(env, obj);
|
|
}
|
|
|
|
jint JNI_OnLoad(JavaVM* vm, void* reserved) {
|
|
JNIEnv *env;
|
|
gJavaVM = vm;
|
|
if ((*vm)->GetEnv(vm, (void**) &env, JNI_VERSION_1_4) != JNI_OK)
|
|
{
|
|
//__android_log_print(ANDROID_LOG_INFO, "(Failed"," to get the environment using GetEnv()");
|
|
return -1;
|
|
}
|
|
|
|
initClassHelper(env, kInterfacePath, &gInterfaceObject);
|
|
return JNI_VERSION_1_4;
|
|
}
|
|
|
|
|
|
const LIDBType * _lidb;
|
|
LIGStatesType _groupstates;
|
|
LILetImgDrawType _lidraw;
|
|
int width;
|
|
int height;
|
|
int offsetX = -11;
|
|
int offsetY = 80;
|
|
|
|
jobject Java_com_phatware_writepad_WritePadAPI_getLetterShapes(JNIEnv * env, jobject thiz, jstring letter, int right, int bottom)
|
|
{
|
|
const char *classLetterManager = "com/phatware/writepad/preference/lettershapes/LetterManager";
|
|
jclass clsLetterManager = (*env)->FindClass(env, classLetterManager);
|
|
jmethodID constructorClsLetterManager = (*env)->GetMethodID(env, clsLetterManager, "<init>", "()V");
|
|
|
|
jmethodID beginLetterGroupCollections = (*env)->GetMethodID(env, clsLetterManager, "beginLetterGroupCollections", "(Ljava/lang/String;)V");
|
|
jmethodID endLetterGroupCollections = (*env)->GetMethodID(env, clsLetterManager, "endLetterGroupCollections", "()V");
|
|
jmethodID beginStroke = (*env)->GetMethodID(env, clsLetterManager, "beginStroke", "()V");
|
|
jmethodID endStroke = (*env)->GetMethodID(env, clsLetterManager, "endStroke", "()V");
|
|
jmethodID beginLetterGroup = (*env)->GetMethodID(env, clsLetterManager, "beginLetterGroup", "(IIFFFF)V");
|
|
jmethodID endLetterGroup = (*env)->GetMethodID(env, clsLetterManager, "endLetterGroup", "()V");
|
|
jmethodID beginLetter = (*env)->GetMethodID(env, clsLetterManager, "beginLetter", "()V");
|
|
jmethodID endLetter = (*env)->GetMethodID(env, clsLetterManager, "endLetter", "()V");
|
|
jmethodID add = (*env)->GetMethodID(env, clsLetterManager, "add", "(FF)V");
|
|
|
|
jobject letterManager = (*env)->NewObject(env, clsLetterManager, constructorClsLetterManager);
|
|
|
|
LIRectType ur, lr;
|
|
lr.left = 0;
|
|
lr.top = 0;
|
|
lr.right = right;
|
|
lr.bottom = bottom;
|
|
lr.left = ORIGIN_LEFT(lr) + LI_LET_IMG_X;
|
|
lr.right -= LI_LET_IMG_X_FROM_RIGHT;
|
|
lr.top = LI_LET_IMG_Y;
|
|
|
|
const UCHR * sLetter = JstringToString(env, letter);
|
|
if ( sLetter != NULL )
|
|
{
|
|
CalcLetterLayout( &lr, sLetter[0], &_lidraw, _lidb, (const LIGStatesType *)&_groupstates );
|
|
free( (void *)sLetter );
|
|
}
|
|
int i;
|
|
LILayoutType *unsellt;
|
|
|
|
for ( i = 0, unsellt = _lidraw.letimg; i < LI_ARRAY_LENGTH(_lidraw.letter) && _lidraw.letter[i] != 0; i++ )
|
|
{
|
|
char ch[3] = {0,')',0};
|
|
ch[0] = (char)_lidraw.letter[i];
|
|
|
|
int len = strlen(ch);
|
|
unsigned short * uResult = (unsigned short *) malloc((len + 2) * sizeof(unsigned short));
|
|
|
|
if (uResult == NULL)
|
|
return NULL;
|
|
|
|
StrToUNICODE(uResult, ch, len);
|
|
const char * utfResult = UnicodeToUTF8(uResult);
|
|
(*env)->CallVoidMethod(env, letterManager, beginLetterGroupCollections, (*env)->NewStringUTF(env, utfResult));
|
|
|
|
|
|
const LIInfoType *leti;
|
|
const LIVarType *letv;
|
|
const LILayoutType inLayout = _lidraw.letimg[i];
|
|
register int k;
|
|
|
|
/*--------------------------------draw letter layout-----------------------------------*/
|
|
if ((leti = LIGetLetterInfo( _lidb, inLayout.letter)) == 0)
|
|
{
|
|
continue;
|
|
}
|
|
int previusGroup = -1;
|
|
for ( k = 0; k < inLayout.numVar; k++) //loop letters
|
|
{
|
|
(*env)->CallVoidMethod(env, letterManager, beginLetter);
|
|
if ((letv = LIGetVariantInfo( _lidb, leti, inLayout.letterVar[k])) == 0)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
/*-------------------------------------draw letter image---------------------------------------------------------------------------*/
|
|
const LIRectType inDestRect = inLayout.letterRect[k];
|
|
enum E_LI_LETSTATE inLetState = inLayout.letState[k];
|
|
|
|
LIRectType bbox;
|
|
LIRectType dest;
|
|
LIRectType screenRect;
|
|
LIRectType baseLineRect;
|
|
LIPointType pt = { 0,0 };
|
|
|
|
if ( letv == 0 || LIGetVariantBBox( _lidb, letv, &bbox ) == LIError)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
int _width = LETTER_PEN_SIZE;
|
|
|
|
dest = inDestRect;
|
|
dest.left += _width;
|
|
dest.top += _width;
|
|
dest.right -= _width;
|
|
dest.bottom -= _width;
|
|
|
|
if (CalculateScreenRect( &bbox, &dest, &screenRect ) == LIError || LIGetVariantBaseLine( _lidb, letv, &baseLineRect ) == LIError)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
/*-------------------------------------draw single letter---------------------------------------------------------------------------*/
|
|
|
|
|
|
int nstrk = LIGetNumStrokes(letv);
|
|
int i;
|
|
float letterLastX, letterLastY;
|
|
for ( i = 0; i < nstrk; i++) //loop strokes
|
|
{
|
|
(*env)->CallVoidMethod(env, letterManager, beginStroke);
|
|
const LIStokeType * lets;
|
|
if ( (lets = LIGetStrokeInfo( _lidb, letv, i)) == 0 )
|
|
{
|
|
continue;
|
|
}
|
|
int npts = LIGetNumPoints(lets);
|
|
CGPoint * pts = (CGPoint * )malloc( sizeof( CGPoint ) * (npts+1) );
|
|
int j;
|
|
for ( j = 0; j < npts; j++) // loop points
|
|
{
|
|
LIPointType pt;
|
|
if ((pt.x = (int)LIGetPointX(lets,j)) < 0 || (pt.y = (int)LIGetPointY(lets,j)) < 0 || ConvertToScreenCoord( &pt, &bbox, &screenRect) == LIError)
|
|
{
|
|
continue;
|
|
}
|
|
letterLastX = pts[j].x = (CGFloat)pt.x;
|
|
letterLastY = pts[j].y = (CGFloat)pt.y;
|
|
(*env)->CallVoidMethod(env, letterManager, add, pts[j].x + offsetX, pts[j].y + offsetY);
|
|
|
|
}
|
|
(*env)->CallVoidMethod(env, letterManager, endStroke);
|
|
free( (void *)pts );
|
|
}
|
|
int group;
|
|
BOOL needToCloseGroup;
|
|
|
|
|
|
if ((group = LIHitTestLetterLayout( &inLayout, letterLastX,letterLastY, 1)) != previusGroup){
|
|
LIRectType r = inLayout.groupRect[group];
|
|
CGRect groupRect = { r.left + offsetX, r.top + offsetY, r.right + offsetX, r.bottom + offsetY};
|
|
if (LIGetSelectedGroup(unsellt) >= 0)
|
|
{
|
|
LISelelectGroup(unsellt, -1);
|
|
}
|
|
|
|
int groupState = inLetState == LI_OFTEN ? 0 : inLetState == LI_SOMETIMES ? 1 : inLetState == LI_RARE ? 2 : inLetState;
|
|
(*env)->CallVoidMethod(env, letterManager, beginLetterGroup, group, groupState, groupRect.origin.x, groupRect.origin.y, groupRect.size.width, groupRect.size.height);
|
|
previusGroup = group;
|
|
needToCloseGroup = previusGroup > - 1;
|
|
|
|
} else {
|
|
needToCloseGroup = false;
|
|
}
|
|
|
|
(*env)->CallVoidMethod(env, letterManager, endLetter);
|
|
if (needToCloseGroup){
|
|
(*env)->CallVoidMethod(env, letterManager, endLetterGroup);
|
|
}
|
|
|
|
|
|
}
|
|
(*env)->CallVoidMethod(env, letterManager, endLetterGroupCollections);
|
|
}
|
|
return letterManager;
|
|
}
|
|
|
|
void Java_com_phatware_writepad_WritePadAPI_initLetterShapes(JNIEnv * env, jobject thiz)
|
|
{
|
|
_lidb = (LIDBType *)LIGetLetterDB( HWR_GetLanguageID( _recognizer ) );
|
|
const unsigned char * shapes = HWR_GetLetterShapes( _recognizer );
|
|
if ( NULL != shapes ){
|
|
memcpy( _groupstates, shapes, LIG_STATES_SIZE );
|
|
}
|
|
memset( &_lidraw, 0, sizeof( _lidraw ) );
|
|
}
|
|
|
|
jstring Java_com_phatware_writepad_WritePadAPI_analyzeWordList(JNIEnv * env, jobject thiz, jstring jword)
|
|
{
|
|
const UCHR * strWord = JstringToString(env, jword);
|
|
if (strWord == NULL)
|
|
{
|
|
return jword;
|
|
}
|
|
int len = u_strlen( strWord );
|
|
jstring newWordFrom = NULL;
|
|
UCHR * pWordList = malloc( MAX_STRING_BUFFER * sizeof( UCHR ));
|
|
if ( NULL != pWordList )
|
|
{
|
|
memset( pWordList, 0, MAX_STRING_BUFFER * sizeof( UCHR ) );
|
|
|
|
if ( HWR_AnalyzeWordList( _recognizer, strWord, pWordList ) == 0 )
|
|
{
|
|
newWordFrom = StringToJstring(env, &pWordList[0]);
|
|
}
|
|
free( (void *) pWordList );
|
|
}
|
|
free((void *) strWord);
|
|
if ( newWordFrom == NULL )
|
|
return jword;
|
|
return newWordFrom;
|
|
}
|
|
|
|
jstring Java_com_phatware_writepad_WritePadAPI_wordEnsureLowerCase(JNIEnv * env, jobject thiz, jstring inWord)
|
|
{
|
|
const UCHR * cword = JstringToString(env, inWord);
|
|
jstring result = StringToJstring( env, HWR_WordEnsureLowerCase(_recognizer, cword) );
|
|
return result;
|
|
}
|
|
|
|
jbyteArray Java_com_phatware_writepad_WritePadAPI_getLetterGroupStates(JNIEnv * env, jobject thiz)
|
|
{
|
|
jbyte * groupDataArray = malloc( LIG_STATES_SIZE );
|
|
if ( NULL != groupDataArray )
|
|
{
|
|
jbyteArray data = (*env)->NewByteArray(env, LIG_STATES_SIZE );
|
|
memmove( groupDataArray, (const void *)_groupstates, LIG_STATES_SIZE );
|
|
(*env)->SetByteArrayRegion( env, data, 0, LIG_STATES_SIZE, groupDataArray );
|
|
free( (void *)groupDataArray );
|
|
return data;
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
jboolean Java_com_phatware_writepad_WritePadAPI_saveShapes(JNIEnv * env, jobject thiz)
|
|
{
|
|
return HWR_SetLetterShapes( _recognizer, _groupstates );
|
|
}
|
|
|
|
void Java_com_phatware_writepad_WritePadAPI_touchGroupLetter(JNIEnv * env, jobject thiz, jfloat x, jfloat y)
|
|
{
|
|
|
|
int k, i, group = -1;
|
|
LILayoutType * layout;
|
|
x -= offsetX;
|
|
y -= offsetY;
|
|
|
|
for ( i = 0, layout = _lidraw.letimg; i < LI_ARRAY_LENGTH(_lidraw.letter) && _lidraw.letter[i] != 0; i++, layout++)
|
|
{
|
|
if ( (group = LIHitTestLetterLayout( layout, (int)x, (int)y, 1)) >= 0 )
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
|
|
if ( group >= 0 )
|
|
{
|
|
if ( group == LIGetSelectedGroup( layout ) )
|
|
{
|
|
int letter = -1;
|
|
if ( (letter = LIHitTestLetterLayout( layout, (int)x, (int)y, 0)) >= 0 )
|
|
{
|
|
SelectNextGroupDtate( _lidb, &_lidraw, &_groupstates );
|
|
|
|
}
|
|
}
|
|
else
|
|
{
|
|
LILayoutType *unsellt;
|
|
for ( k = 0, unsellt = _lidraw.letimg; k < LI_ARRAY_LENGTH(_lidraw.letter) && _lidraw.letter[k] != 0; k++, unsellt++)
|
|
{
|
|
if (LIGetSelectedGroup(unsellt) >= 0)
|
|
{
|
|
LISelelectGroup(unsellt, -1);
|
|
break;
|
|
}
|
|
}
|
|
|
|
LISelelectGroup( layout, group );
|
|
}
|
|
}
|
|
}
|
|
|
|
jboolean Java_com_phatware_writepad_WritePadAPI_exportWordList(JNIEnv* env, jobject thiz, jstring pExportFile)
|
|
{
|
|
jboolean result = false;
|
|
if (_recognizer != NULL)
|
|
{
|
|
jboolean isCopy = JNI_FALSE;
|
|
const char *fileName = (*env)->GetStringUTFChars(env, pExportFile, &isCopy);
|
|
result = HWR_ExportWordList(_recognizer, fileName);
|
|
if ( fileName && isCopy == JNI_TRUE)
|
|
(*env)->ReleaseStringUTFChars(env, pExportFile, fileName);
|
|
}
|
|
return result;
|
|
}
|
|
|
|
jboolean Java_com_phatware_writepad_WritePadAPI_exportUserDictionary(JNIEnv* env, jobject thiz, jstring pExportFile)
|
|
{
|
|
jboolean result = false;
|
|
if (_recognizer != NULL)
|
|
{
|
|
jboolean isCopy = JNI_FALSE;
|
|
const char *fileName = (*env)->GetStringUTFChars(env, pExportFile, &isCopy );
|
|
result = HWR_ExportUserDictionary(_recognizer, fileName);
|
|
if ( fileName && isCopy == JNI_TRUE)
|
|
(*env)->ReleaseStringUTFChars(env, pExportFile, fileName);
|
|
}
|
|
return result;
|
|
}
|
|
|
|
jboolean Java_com_phatware_writepad_WritePadAPI_importWordList(JNIEnv* env, jobject thiz, jstring pImportFile)
|
|
{
|
|
jboolean result = false;
|
|
if (_recognizer != NULL)
|
|
{
|
|
jboolean isCopy = JNI_FALSE;
|
|
const char *fileName = (*env)->GetStringUTFChars(env, pImportFile, &isCopy);
|
|
result = HWR_ImportWordList(_recognizer, fileName);
|
|
if ( fileName && isCopy == JNI_TRUE)
|
|
(*env)->ReleaseStringUTFChars(env, pImportFile, fileName);
|
|
}
|
|
return result;
|
|
}
|
|
|
|
jboolean Java_com_phatware_writepad_WritePadAPI_importUserDictionary(JNIEnv* env, jobject thiz, jstring pImportFile)
|
|
{
|
|
jboolean result = false;
|
|
if (_recognizer != NULL)
|
|
{
|
|
jboolean isCopy = JNI_FALSE;
|
|
const char *fileName = (*env)->GetStringUTFChars( env, pImportFile, &isCopy);
|
|
result = HWR_ImportUserDictionary(_recognizer, fileName);
|
|
if ( fileName && isCopy == JNI_TRUE)
|
|
(*env)->ReleaseStringUTFChars(env, pImportFile, fileName);
|
|
}
|
|
return result;
|
|
}
|
|
|
|
static BOOL stringcaseiqual( CUCHR * str1, CUCHR * str2 )
|
|
{
|
|
while( *str1 != 0 && *str2 != 0 )
|
|
{
|
|
if ( tolower( *str1 ) != tolower( *str2 ) )
|
|
return false;
|
|
str1++;
|
|
str2++;
|
|
}
|
|
return ( *str1 == *str2 ) ? true : false;
|
|
}
|
|
|
|
jint Java_com_phatware_writepad_WritePadAPI_isCommand( JNIEnv* env, jobject thiz, jstring jcommand )
|
|
{
|
|
jint result = -1;
|
|
if (NULL != _recognizer)
|
|
{
|
|
int cnt = HWR_GetResultWordCount( _recognizer );
|
|
if ( cnt == 1 )
|
|
{
|
|
// if only single word was recognized
|
|
result = 0;
|
|
const UCHR * strCmd = JstringToString(env, jcommand);
|
|
if ( strCmd != NULL )
|
|
{
|
|
int alt = HWR_GetResultAlternativeCount( _recognizer, 0 );
|
|
if ( alt > MAX_CMD_WORDS )
|
|
alt = MAX_CMD_WORDS;
|
|
int i;
|
|
for ( i = 0; i < alt; i++ )
|
|
{
|
|
const UCHR * word = HWR_GetResultWord( _recognizer, 0, i );
|
|
if ( NULL != word && stringcaseiqual( strCmd, word ) )
|
|
{
|
|
result = 1;
|
|
break;
|
|
}
|
|
}
|
|
free( (void *)strCmd );
|
|
}
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|