#include #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)cOutawchList[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)cOutaeScore[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; }