326 lines
9 KiB
C
326 lines
9 KiB
C
|
#include <stdlib.h>
|
||
|
#include "common.h"
|
||
|
#include "score.h"
|
||
|
#include "runnet.h"
|
||
|
#include "jaws.h"
|
||
|
#include "fugu.h"
|
||
|
#include "sole.h"
|
||
|
#include "nnet.h"
|
||
|
|
||
|
extern LOCRUN_INFO g_locRunInfo;
|
||
|
|
||
|
// validates the header of the Jaws net
|
||
|
BOOL CheckJawsNetHeader (void *pData)
|
||
|
{
|
||
|
NNET_HEADER *pHeader = (NNET_HEADER *)pData;
|
||
|
|
||
|
// wrong magic number
|
||
|
ASSERT (pHeader->dwFileType == JAWS_FILE_TYPE);
|
||
|
|
||
|
if (pHeader->dwFileType != JAWS_FILE_TYPE)
|
||
|
{
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
// check version
|
||
|
ASSERT(pHeader->iFileVer >= JAWS_OLD_FILE_VERSION);
|
||
|
ASSERT(pHeader->iMinCodeVer <= JAWS_CUR_FILE_VERSION);
|
||
|
|
||
|
ASSERT ( !memcmp ( pHeader->adwSignature,
|
||
|
g_locRunInfo.adwSignature,
|
||
|
sizeof (pHeader->adwSignature)
|
||
|
)
|
||
|
);
|
||
|
|
||
|
ASSERT (pHeader->cSpace == 1);
|
||
|
|
||
|
if ( pHeader->iFileVer >= JAWS_OLD_FILE_VERSION &&
|
||
|
pHeader->iMinCodeVer <= JAWS_CUR_FILE_VERSION &&
|
||
|
!memcmp ( pHeader->adwSignature,
|
||
|
g_locRunInfo.adwSignature,
|
||
|
sizeof (pHeader->adwSignature)
|
||
|
) &&
|
||
|
pHeader->cSpace == 1
|
||
|
)
|
||
|
{
|
||
|
return TRUE;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
return FALSE;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
BOOL JawsLoadPointer(JAWS_LOAD_INFO *pJaws)
|
||
|
{
|
||
|
NNET_SPACE_HEADER *pSpaceHeader;
|
||
|
|
||
|
if (!CheckJawsNetHeader (pJaws->info.pbMapping))
|
||
|
return FALSE;
|
||
|
|
||
|
// point to the one and only space header
|
||
|
pSpaceHeader = (NNET_SPACE_HEADER *)(pJaws->info.pbMapping + sizeof (NNET_HEADER));
|
||
|
|
||
|
if ( restoreLocalConnectNet ( pJaws->info.pbMapping + pSpaceHeader->iDataOffset,
|
||
|
0, &pJaws->net
|
||
|
) == NULL
|
||
|
)
|
||
|
{
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
pJaws->iNetSize =
|
||
|
getRunTimeNetMemoryRequirements (pJaws->info.pbMapping + pSpaceHeader->iDataOffset);
|
||
|
|
||
|
if (pJaws->iNetSize <= 0)
|
||
|
{
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
///////////////////////////////////////
|
||
|
//
|
||
|
// JawsLoadFile
|
||
|
//
|
||
|
// Load otter/fugu/sole combiner from file
|
||
|
//
|
||
|
// Parameters:
|
||
|
// pInfo: [out] Information about the mapped file
|
||
|
// wszPath: [in] Path to load from
|
||
|
//
|
||
|
// Return values:
|
||
|
// TRUE on successful, FALSE otherwise.
|
||
|
//
|
||
|
//////////////////////////////////////
|
||
|
BOOL JawsLoadFile(JAWS_LOAD_INFO *pJaws, wchar_t *wszPath)
|
||
|
{
|
||
|
wchar_t wszFile[_MAX_PATH];
|
||
|
|
||
|
// Generate path to file.
|
||
|
FormatPath(wszFile, wszPath, (wchar_t *)0, (wchar_t *)0, (wchar_t *)0, L"jaws.bin");
|
||
|
|
||
|
if (!DoOpenFile(&pJaws->info, wszFile))
|
||
|
{
|
||
|
return FALSE;
|
||
|
}
|
||
|
return JawsLoadPointer(pJaws);
|
||
|
}
|
||
|
|
||
|
///////////////////////////////////////
|
||
|
//
|
||
|
// JawsUnloadFile
|
||
|
//
|
||
|
// Load otter/fugu/sole combiner from file
|
||
|
//
|
||
|
// Parameters:
|
||
|
// pInfo: [out] File to unmap
|
||
|
//
|
||
|
// Return values:
|
||
|
// TRUE on successful, FALSE otherwise.
|
||
|
//
|
||
|
//////////////////////////////////////
|
||
|
BOOL JawsUnloadFile(JAWS_LOAD_INFO *pJaws)
|
||
|
{
|
||
|
return DoCloseFile(&pJaws->info);
|
||
|
}
|
||
|
|
||
|
BOOL JawsLoadRes(JAWS_LOAD_INFO *pJaws, HINSTANCE hInst, int nResID, int nType)
|
||
|
{
|
||
|
if (DoLoadResource(&pJaws->info, hInst, nResID, nType) == NULL)
|
||
|
{
|
||
|
return FALSE;
|
||
|
}
|
||
|
return JawsLoadPointer(pJaws);
|
||
|
}
|
||
|
|
||
|
// describe the codepoint
|
||
|
RREAL *CodePointFlags(ALC alc, RREAL *pFeat)
|
||
|
{
|
||
|
*(pFeat++) = ((alc & ALC_NUMERIC) ? 65535 : 0);
|
||
|
*(pFeat++) = ((alc & ALC_ALPHA) ? 65535 : 0);
|
||
|
*(pFeat++) = ((alc & (ALC_PUNC | ALC_NUMERIC_PUNC | ALC_OTHER)) ? 65535 : 0);
|
||
|
*(pFeat++) = ((alc & (ALC_HIRAGANA | ALC_JAMO | ALC_BOPOMOFO)) ? 65535 : 0);
|
||
|
*(pFeat++) = ((alc & (ALC_KATAKANA | ALC_HANGUL_ALL)) ? 65535 : 0);
|
||
|
*(pFeat++) = ((alc & (ALC_KANJI_ALL)) ? 65535 : 0);
|
||
|
return pFeat;
|
||
|
}
|
||
|
|
||
|
// Given an alt list with dense and possibly folded codes in it, run through it
|
||
|
// and expand the folded lists. The unfolded alt list is returned in place.
|
||
|
// This function assumes that the list begins with better alternates, as those
|
||
|
// later in the list will get dropped if we run out of space.
|
||
|
static void UnfoldCodes(ALT_LIST *pAltList, LOCRUN_INFO *pLocRunInfo, CHARSET *cs)
|
||
|
{
|
||
|
int i, cOut=0;
|
||
|
ALT_LIST newAltList; // This will be where the new alt list is constructed.
|
||
|
|
||
|
// For each alternate in the input list and while we have space in the output list
|
||
|
for (i=0; i<(int)pAltList->cAlt && (int)cOut<MAX_ALT_LIST; i++) {
|
||
|
|
||
|
// Check if the alternate is a folded coded
|
||
|
if (LocRunIsFoldedCode(pLocRunInfo,pAltList->awchList[i])) {
|
||
|
int kndex;
|
||
|
// If it is a folded code, look up the folding set
|
||
|
wchar_t *pFoldingSet = LocRunFolded2FoldingSet(pLocRunInfo, pAltList->awchList[i]);
|
||
|
|
||
|
// Run through the folding set, adding non-NUL items to the output list
|
||
|
// (until the output list is full)
|
||
|
for (kndex = 0;
|
||
|
kndex < LOCRUN_FOLD_MAX_ALTERNATES && pFoldingSet[kndex] != 0 && (int)cOut<MAX_ALT_LIST;
|
||
|
kndex++) {
|
||
|
if (IsAllowedChar(pLocRunInfo, cs, pFoldingSet[kndex]))
|
||
|
{
|
||
|
newAltList.awchList[cOut]=pFoldingSet[kndex];
|
||
|
newAltList.aeScore[cOut]=pAltList->aeScore[i];
|
||
|
cOut++;
|
||
|
#ifdef DISABLE_UNFOLDING
|
||
|
// If unfolding is disabled, then stop after producing one unfolded code.
|
||
|
// This way we don't push results later in the alt list out of the alt
|
||
|
// list, while still allowing the recognizer to return unicodes for each
|
||
|
// alternate.
|
||
|
break;
|
||
|
#endif
|
||
|
}
|
||
|
}
|
||
|
} else {
|
||
|
// Dense codes that are not folded get added directly
|
||
|
newAltList.awchList[cOut]=pAltList->awchList[i];
|
||
|
newAltList.aeScore[cOut]=pAltList->aeScore[i];
|
||
|
cOut++;
|
||
|
}
|
||
|
}
|
||
|
// Store the length of the output list
|
||
|
newAltList.cAlt=cOut;
|
||
|
|
||
|
// Copy the output list over the input.
|
||
|
*pAltList=newAltList;
|
||
|
}
|
||
|
|
||
|
int JawsFeaturize(FUGU_LOAD_INFO *pFugu, SOLE_LOAD_INFO *pSole, LOCRUN_INFO *pLocRunInfo,
|
||
|
GLYPH *pGlyph, RECT *pGuide,
|
||
|
CHARSET *pCharSet, RREAL *pFeat, ALT_LIST *pAltList,
|
||
|
BOOL *pfAgree)
|
||
|
{
|
||
|
int i;
|
||
|
ALT_LIST altListFugu;
|
||
|
ALT_LIST altListSole;
|
||
|
|
||
|
wchar_t wchSoleTop1;
|
||
|
float flSoleTop1;
|
||
|
|
||
|
if (FuguMatch(&pFugu->fugu, &altListFugu, MAX_ALT_LIST, pGlyph, NULL, pCharSet, pLocRunInfo) < 0)
|
||
|
{
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
UnfoldCodes(&altListFugu, pLocRunInfo, pCharSet);
|
||
|
altListSole = altListFugu;
|
||
|
|
||
|
if (SoleMatchRescore(pSole, &wchSoleTop1, &flSoleTop1, &altListSole, MAX_ALT_LIST,
|
||
|
pGlyph, pGuide, pCharSet, pLocRunInfo) < 0)
|
||
|
{
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
*pAltList = altListSole;
|
||
|
|
||
|
if (altListFugu.cAlt > 0 && wchSoleTop1 == altListFugu.awchList[0])
|
||
|
{
|
||
|
*pfAgree = TRUE;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
*pfAgree = FALSE;
|
||
|
if (altListFugu.cAlt > JAWS_NUM_ALTERNATES)
|
||
|
{
|
||
|
pAltList->cAlt = JAWS_NUM_ALTERNATES;
|
||
|
}
|
||
|
for (i = 0; i < JAWS_NUM_ALTERNATES; i++)
|
||
|
{
|
||
|
extern UNIGRAM_INFO g_unigramInfo;
|
||
|
if (i < (int) altListFugu.cAlt)
|
||
|
{
|
||
|
*(pFeat++) = (int) (altListFugu.aeScore[i] * 65535);
|
||
|
*(pFeat++) = (int) (altListSole.aeScore[i] * 65535);
|
||
|
*(pFeat++) = (int) (-UnigramCost(&g_unigramInfo, altListFugu.awchList[i]) * 100 * 256);
|
||
|
pFeat = CodePointFlags(LocRun2ALC(pLocRunInfo, altListFugu.awchList[i]), pFeat);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
*(pFeat++) = 0;
|
||
|
*(pFeat++) = 0;
|
||
|
*(pFeat++) = (int) (-UnigramCost(&g_unigramInfo, 0xFFFE) * 100 * 256);
|
||
|
pFeat = CodePointFlags(0, pFeat);
|
||
|
}
|
||
|
}
|
||
|
*(pFeat++) = (CframeGLYPH(pGlyph) - 1) * 65535;
|
||
|
}
|
||
|
return pAltList->cAlt;
|
||
|
}
|
||
|
|
||
|
///////////////////////////////////////
|
||
|
//
|
||
|
// JawsMatch
|
||
|
//
|
||
|
// Invoke Fugu/Otter/Sole combiner on a character.
|
||
|
//
|
||
|
// Parameters:
|
||
|
// pFugu: [in] Fugu database to use
|
||
|
// pAltList: [in/out] Alt list to rewrite the scores of
|
||
|
// cAlt: [in] The maximum number of alternates to return
|
||
|
// pGlyph: [in] The ink to recognize
|
||
|
// pGuide: [in] Guide to scale ink to
|
||
|
// pCharSet: [in] Filter for the characters to be returned
|
||
|
// pLocRunInfo: [in] Pointer to the locale database
|
||
|
//
|
||
|
// Return values:
|
||
|
// Returned the number of items in the alt list, or -1 if there is an error
|
||
|
//
|
||
|
//////////////////////////////////////
|
||
|
int JawsMatch(JAWS_LOAD_INFO *pJaws, FUGU_LOAD_INFO *pFugu, SOLE_LOAD_INFO *pSole,
|
||
|
ALT_LIST *pAltList, int cAlt, GLYPH *pGlyph, RECT *pGuide,
|
||
|
CHARSET *pCharSet, LOCRUN_INFO *pLocRunInfo)
|
||
|
{
|
||
|
int i;
|
||
|
RREAL *pNetOut;
|
||
|
int iWinner, cOut;
|
||
|
BOOL fAgree;
|
||
|
RREAL *pFeat = (RREAL *) ExternAlloc(pJaws->iNetSize * sizeof(RREAL));
|
||
|
if (pFeat == NULL)
|
||
|
{
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
if (JawsFeaturize(pFugu, pSole, pLocRunInfo, pGlyph, pGuide, pCharSet, pFeat, pAltList, &fAgree) < 0)
|
||
|
{
|
||
|
ExternFree(pFeat);
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
if (!fAgree)
|
||
|
{
|
||
|
pNetOut = runLocalConnectNet(&pJaws->net, pFeat, &iWinner, &cOut);
|
||
|
if (cOut < (int) pAltList->cAlt)
|
||
|
{
|
||
|
pAltList->cAlt = cOut;
|
||
|
}
|
||
|
for (i = 0; i < (int) pAltList->cAlt; i++)
|
||
|
{
|
||
|
pAltList->aeScore[i] = (float) *(pNetOut++) / (float) SOFT_MAX_UNITY;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
for (i = 0; i < (int) pAltList->cAlt; i++)
|
||
|
{
|
||
|
pAltList->aeScore[i] = ((float) -ProbToScore(pAltList->aeScore[i])) / (float) 256.0;
|
||
|
}
|
||
|
|
||
|
SortAltList(pAltList);
|
||
|
|
||
|
ExternFree(pFeat);
|
||
|
return pAltList->cAlt;
|
||
|
}
|
||
|
|