Publish Vulpes Preview 15 sources for desktop, Android and Tundra
Share Gaia assets and adapters, keep private profiles and development documents local, and update both public READMEs.
This commit is contained in:
parent
93e3a48004
commit
b38dea0597
25901 changed files with 9982925 additions and 369 deletions
83
gaia/apps/keyboard/js/imes/handwriting/NOTICE
Executable file
83
gaia/apps/keyboard/js/imes/handwriting/NOTICE
Executable file
|
|
@ -0,0 +1,83 @@
|
|||
Handwriting is a handwriting recoginiton input method for gaia and is licensed
|
||||
under the Apache Version 2.0, 2014. The handwriting recoginition engine is
|
||||
zinnia (http://zinnia.sourceforge.net/), which is converted to JavaScript as
|
||||
emscripten-zinnia project and hosted at:
|
||||
https://github.com/yxl/emscripten-zinnia.
|
||||
|
||||
Emscripten (https://github.com/kripken/emscripten) is used to compile the
|
||||
original C++ zinnia code into JavaScript version.
|
||||
==========================================================================
|
||||
Copyright notice for handwriting.
|
||||
|
||||
Copyright (c) 2014, Mozilla Online
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
==========================================================================
|
||||
Copyright notice for emscripten-zinnia.
|
||||
Copyright (c) 2014, Yuan Xulei
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
* Neither the name of Taku Kudo nor the names of its contributors
|
||||
may be used to endorse or promote products derived from this software
|
||||
without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
==========================================================================
|
||||
Copyright notice for zinnia.
|
||||
|
||||
Copyright (c) 2005-2007, Taku Kudo
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification, are
|
||||
permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above
|
||||
copyright notice, this list of conditions and the
|
||||
following disclaimer.
|
||||
|
||||
* Redistributions in binary form must reproduce the above
|
||||
copyright notice, this list of conditions and the
|
||||
following disclaimer in the documentation and/or other
|
||||
materials provided with the distribution.
|
||||
|
||||
* Neither the name of Taku Kudo nor the names of its contributors
|
||||
may be used to endorse or promote products derived from this software
|
||||
without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
288
gaia/apps/keyboard/js/imes/handwriting/handwriting.js
Executable file
288
gaia/apps/keyboard/js/imes/handwriting/handwriting.js
Executable file
|
|
@ -0,0 +1,288 @@
|
|||
/* -*- Mode: js; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set shiftwidth=2 tabstop=2 autoindent cindent expandtab: */
|
||||
|
||||
'use strict';
|
||||
|
||||
/* global InputMethods, KeyEvent */
|
||||
/*
|
||||
* This file implements a "glue" between FxOS Keyboard app UI and
|
||||
* the handwriting recognition library. The recognition engine works
|
||||
* in a web worker, it could support multiple languages, and communicates
|
||||
* with this "glue" with messages.
|
||||
*/
|
||||
|
||||
var HandwritingGaiaKeyboardGlue = function HandwritingGaiaKeyboardGlue() {
|
||||
this.callbacks = null;
|
||||
this.worker = null;
|
||||
|
||||
// The state of handwriting recognition engine module,
|
||||
// whether it has been loaded into web worker completely.
|
||||
this.moduleLoaded = false;
|
||||
// The state of handwriting recognition engine,
|
||||
// whether it's ready for for recognition.
|
||||
this.isReady = false;
|
||||
|
||||
this.firstCandidate = '';
|
||||
this.keypressQueue = [];
|
||||
|
||||
this.isWorking = false;
|
||||
this.isActive = false;
|
||||
|
||||
// Current language
|
||||
this.language = '';
|
||||
|
||||
this.isPredicting = false;
|
||||
|
||||
// For prediction
|
||||
this.words = '';
|
||||
|
||||
this.cachedPoints = [];
|
||||
|
||||
this.unloadWorkerTimer = undefined;
|
||||
};
|
||||
|
||||
HandwritingGaiaKeyboardGlue.prototype.DEACTIVATE_TIME = 60000; // 1 minute
|
||||
|
||||
HandwritingGaiaKeyboardGlue.prototype.init = function hr_init(callbacks) {
|
||||
this.callbacks = callbacks;
|
||||
};
|
||||
|
||||
HandwritingGaiaKeyboardGlue.prototype.uninit = function hr_uninit(callbacks) {
|
||||
this._unloadWorker();
|
||||
this.callbacks = null;
|
||||
};
|
||||
|
||||
HandwritingGaiaKeyboardGlue.prototype._loadWorker = function hr_loadWorker() {
|
||||
if (this.worker) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.worker = new Worker(this.callbacks.path + '/hwr/worker.js');
|
||||
|
||||
this.worker.onmessage = function(evt) {
|
||||
var data = evt.data;
|
||||
|
||||
switch (data.id) {
|
||||
case 'init':
|
||||
this.moduleLoaded = true;
|
||||
this.postMessage('setLang', this.language);
|
||||
break;
|
||||
case 'setLang':
|
||||
this.isReady = data.value;
|
||||
if (this.isReady) {
|
||||
this._handleCachedStrokePoints();
|
||||
}
|
||||
break;
|
||||
case 'recognize':
|
||||
this.isPredicting = false;
|
||||
this._sendCandidates(JSON.parse(data.value));
|
||||
break;
|
||||
case 'getPrediction':
|
||||
this.isPredicting = true;
|
||||
var predictions = data.value;
|
||||
if (predictions) {
|
||||
this._sendCandidates(predictions.split(' '));
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}.bind(this);
|
||||
};
|
||||
|
||||
HandwritingGaiaKeyboardGlue.prototype._unloadWorker =
|
||||
function hr_unloadWorker() {
|
||||
if (this.worker) {
|
||||
this.worker.terminate();
|
||||
}
|
||||
|
||||
this.handlers = null;
|
||||
this.worker = null;
|
||||
this.moduleLoaded = false;
|
||||
this.isReady = false;
|
||||
};
|
||||
|
||||
HandwritingGaiaKeyboardGlue.prototype.select = function hr_select(text, data) {
|
||||
this.callbacks.sendString(text);
|
||||
this.empty();
|
||||
this._start();
|
||||
|
||||
if (this.isPredicting) {
|
||||
this.words += text;
|
||||
} else {
|
||||
this.words = text;
|
||||
this.isPredicting = true;
|
||||
}
|
||||
|
||||
this.postMessage('getPrediction', this.words);
|
||||
};
|
||||
|
||||
HandwritingGaiaKeyboardGlue.prototype.click = function hr_click(keyCode) {
|
||||
this.keypressQueue.push(keyCode);
|
||||
|
||||
this._start();
|
||||
};
|
||||
|
||||
HandwritingGaiaKeyboardGlue.prototype.activate =
|
||||
function hr_activate(language, state, options) {
|
||||
var needsSetLang = this.language != language;
|
||||
this.language = language;
|
||||
|
||||
if (!this.worker) {
|
||||
this._loadWorker();
|
||||
}
|
||||
clearTimeout(this.unloadWorkerTimer);
|
||||
|
||||
// The handwriting recognition engine may be used by multiple IMEs,
|
||||
// we need set language for different IMEs.
|
||||
if (this.moduleLoaded && needsSetLang) {
|
||||
this.isReady = false;
|
||||
this.postMessage('setLang', language);
|
||||
}
|
||||
|
||||
this.isActive = true;
|
||||
};
|
||||
|
||||
HandwritingGaiaKeyboardGlue.prototype.deactivate = function hr_deactivate() {
|
||||
if (!this._isActive) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.isActive = false;
|
||||
|
||||
this._resetKeypressQueue();
|
||||
this.empty();
|
||||
|
||||
clearTimeout(this.unloadWorkerTimer);
|
||||
this.unloadWorkerTimer =
|
||||
setTimeout(this._unloadWorker.bind(this), this.DEACTIVATE_TIME);
|
||||
};
|
||||
|
||||
HandwritingGaiaKeyboardGlue.prototype.empty = function hr_empty() {
|
||||
this.firstCandidate = '';
|
||||
this.callbacks.sendCandidates([]);
|
||||
this.callbacks.endComposition();
|
||||
this.callbacks.app.handwritingPadsManager.clear();
|
||||
};
|
||||
|
||||
HandwritingGaiaKeyboardGlue.prototype.postMessage = function(id, param) {
|
||||
if (!this.moduleLoaded) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.worker.postMessage({
|
||||
id: id,
|
||||
param: param
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Send candidates list and change composition.
|
||||
* @param {Array.<string>} candidates The candidates to be sent.
|
||||
* @return {void} No return value.
|
||||
*/
|
||||
HandwritingGaiaKeyboardGlue.prototype._sendCandidates =
|
||||
function hr_sendCandidates(candidates) {
|
||||
var list = [];
|
||||
var len = candidates.length;
|
||||
for (var id = 0; id < len; id++) {
|
||||
var cand = candidates[id];
|
||||
list.push([cand, id]);
|
||||
}
|
||||
|
||||
if (len > 0) {
|
||||
this.firstCandidate = candidates[0];
|
||||
}
|
||||
|
||||
this.callbacks.sendCandidates(list);
|
||||
|
||||
if (this.isPredicting) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.firstCandidate) {
|
||||
this.callbacks.setComposition(this.firstCandidate);
|
||||
}
|
||||
};
|
||||
|
||||
HandwritingGaiaKeyboardGlue.prototype._start = function hr_start() {
|
||||
if (this.isWorking) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.isWorking = true;
|
||||
this._next();
|
||||
};
|
||||
|
||||
HandwritingGaiaKeyboardGlue.prototype._next = function hr_next() {
|
||||
if (!this.keypressQueue.length) {
|
||||
this.isWorking = false;
|
||||
return;
|
||||
}
|
||||
|
||||
var code = this.keypressQueue.shift();
|
||||
|
||||
var sendKey = true;
|
||||
|
||||
if (this.firstCandidate) {
|
||||
switch (code) {
|
||||
case KeyEvent.DOM_VK_BACK_SPACE:
|
||||
sendKey = false;
|
||||
this.empty();
|
||||
break;
|
||||
case KeyEvent.DOM_VK_RETURN:
|
||||
case KeyEvent.DOM_VK_SPACE:
|
||||
// candidate list exists; output the first candidate
|
||||
this.select(this.firstCandidate);
|
||||
this.callbacks.app.handwritingPadsManager.clear();
|
||||
sendKey = false;
|
||||
break;
|
||||
default:
|
||||
this.callbacks.endComposition(this.firstCandidate);
|
||||
this.empty();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//pass the key to IMEManager for default action
|
||||
if (sendKey) {
|
||||
this.callbacks.sendKey(code);
|
||||
}
|
||||
this._next();
|
||||
};
|
||||
|
||||
HandwritingGaiaKeyboardGlue.prototype._resetKeypressQueue =
|
||||
function hr_resetKeypressQueue() {
|
||||
this.keypressQueue = [];
|
||||
this.isWorking = false;
|
||||
};
|
||||
|
||||
// If handwriting recognition engine is loaded or initialized later
|
||||
// than user writing, there are some cached stroke points, do
|
||||
// recognition for cached stroke points.
|
||||
HandwritingGaiaKeyboardGlue.prototype._handleCachedStrokePoints =
|
||||
function hr_handleCachedStrokePoints() {
|
||||
if (this.cachedPoints.length === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.postMessage('recognize', JSON.stringify(this.cachedPoints));
|
||||
this.cachedPoints = [];
|
||||
};
|
||||
|
||||
HandwritingGaiaKeyboardGlue.prototype.sendStrokePoints =
|
||||
function hr_sendStrokePoints(strokePoints) {
|
||||
// If handwriting recognition engine is not loaded or is not ready for
|
||||
// recognition, cache the stroke points.
|
||||
if (!this.moduleLoaded || !this.isReady) {
|
||||
this.cachedPoints = strokePoints;
|
||||
return;
|
||||
}
|
||||
|
||||
this.postMessage('recognize', JSON.stringify(strokePoints));
|
||||
};
|
||||
|
||||
// Expose the engine to the Gaia keyboard
|
||||
if (typeof InputMethods !== 'undefined') {
|
||||
InputMethods.handwriting = new HandwritingGaiaKeyboardGlue();
|
||||
}
|
||||
BIN
gaia/apps/keyboard/js/imes/handwriting/hwr/emscripten_zinnia.data
Executable file
BIN
gaia/apps/keyboard/js/imes/handwriting/hwr/emscripten_zinnia.data
Executable file
Binary file not shown.
9446
gaia/apps/keyboard/js/imes/handwriting/hwr/emscripten_zinnia.js
Executable file
9446
gaia/apps/keyboard/js/imes/handwriting/hwr/emscripten_zinnia.js
Executable file
File diff suppressed because one or more lines are too long
122
gaia/apps/keyboard/js/imes/handwriting/hwr/recognition.js
Executable file
122
gaia/apps/keyboard/js/imes/handwriting/hwr/recognition.js
Executable file
|
|
@ -0,0 +1,122 @@
|
|||
'use strict';
|
||||
|
||||
var MAX_STROKE_NUM = 1000;
|
||||
|
||||
self.onmessage = function(e) {
|
||||
var data = e.data;
|
||||
|
||||
switch(data.id) {
|
||||
case 'setLang':
|
||||
var ret = Recognition.setLang(data.param);
|
||||
post('setLang', ret);
|
||||
break;
|
||||
case 'recognize':
|
||||
var words = Recognition.recognize(JSON.parse(data.param));
|
||||
post('recognize', JSON.stringify(words));
|
||||
break;
|
||||
case 'getPrediction':
|
||||
var words = Recognition.getPrediction(data.param);
|
||||
post('getPrediction', words);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
};
|
||||
|
||||
var Recognition = {
|
||||
_inited: false,
|
||||
|
||||
setLang: function(lang) {
|
||||
if (!this._lang) {
|
||||
this._lang = lang;
|
||||
return this._init(lang);
|
||||
}
|
||||
if (this._lang != lang) {
|
||||
this._lang = lang;
|
||||
this._uinit();
|
||||
return this._init(lang);
|
||||
}
|
||||
return true;
|
||||
},
|
||||
|
||||
recognize: function(points) {
|
||||
if (!this._inited) {
|
||||
return [];
|
||||
}
|
||||
|
||||
var strokes = points.slice(0, 2 * MAX_STROKE_NUM);
|
||||
// Append [-1, -1] to strokes.
|
||||
strokes.push.apply(strokes, [-1, -1]);
|
||||
this._strokeBuffer.set(strokes);
|
||||
return this._CharacterRecognize(this._strokeBuffer.byteOffset);
|
||||
},
|
||||
|
||||
getPrediction: function(words) {
|
||||
if (this._getPrediction) {
|
||||
return this._getPrediction(words);
|
||||
}
|
||||
},
|
||||
|
||||
_init: function(lang) {
|
||||
this._inited = false;
|
||||
var model = '';
|
||||
|
||||
if (lang == 'zh-Hans') {
|
||||
model = 'zh_Hans.model';
|
||||
}
|
||||
if (lang == 'zh-Hant') {
|
||||
model = 'zh_Hant.model';
|
||||
}
|
||||
|
||||
if (!Module.ccall('InitRecog',
|
||||
'number',
|
||||
['string', 'number', 'number'],
|
||||
[model, 140, 140])) {
|
||||
return false;
|
||||
}
|
||||
|
||||
this._CharacterRecognize =
|
||||
Module.cwrap('CharacterRecognize', 'string', ['number']);
|
||||
|
||||
if (Module.ccall('InitPrediction',
|
||||
'number',
|
||||
['string'],
|
||||
['dict_pinyin.data'])) {
|
||||
this._getPrediction =
|
||||
Module.cwrap('GetPrediction', 'string', ['string']);
|
||||
}
|
||||
|
||||
var buf = Module._malloc((MAX_STROKE_NUM + 1) * 4);
|
||||
this._strokeBuffer =
|
||||
new Int16Array(Module.HEAPU8.buffer, buf, (MAX_STROKE_NUM + 1) * 2);
|
||||
|
||||
this._inited = true;
|
||||
return true;
|
||||
},
|
||||
|
||||
_uinit: function() {
|
||||
Module._free(this._strokeBuffer.byteOffset);
|
||||
Module.ccall('ExitRecog', '', [], []);
|
||||
},
|
||||
|
||||
_strokeBuffer: null,
|
||||
_CharacterRecognize: null,
|
||||
_lang: '',
|
||||
_getPrediction: null
|
||||
};
|
||||
|
||||
var Module = {
|
||||
filePackagePrefixURL: './',
|
||||
canvas: {},
|
||||
stdout: null,
|
||||
_main: function() {
|
||||
post('init', true);
|
||||
}
|
||||
};
|
||||
|
||||
function post(id, value) {
|
||||
postMessage({
|
||||
id: id,
|
||||
value: value
|
||||
});
|
||||
}
|
||||
7
gaia/apps/keyboard/js/imes/handwriting/hwr/worker.js
Executable file
7
gaia/apps/keyboard/js/imes/handwriting/hwr/worker.js
Executable file
|
|
@ -0,0 +1,7 @@
|
|||
'use strict';
|
||||
|
||||
/**
|
||||
* Load Recognition, etc. into a Web Worker.
|
||||
*/
|
||||
|
||||
importScripts('recognition.js', 'emscripten_zinnia.js');
|
||||
Loading…
Reference in a new issue