1 // Copyright 2014 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 /** 6 * @fileoverview Rule stores for the basic components of math expressions: 7 * Unicode symbols and functions. 8 * 9 * The idea of these stores is to provide a more efficient data structure to 10 * look up rules in the background page than the usual flat array of rules 11 * implemented by other stores. 12 * 13 */ 14 15 goog.provide('cvox.MathCompoundStore'); 16 goog.provide('cvox.MathSimpleStore'); 17 18 goog.require('cvox.MathStore'); 19 goog.require('cvox.SpeechRule'); 20 21 /** 22 * A base store for simple Math objects. 23 * @constructor 24 * @extends {cvox.MathStore} 25 */ 26 cvox.MathSimpleStore = function() { 27 goog.base(this); 28 }; 29 goog.inherits(cvox.MathSimpleStore, cvox.MathStore); 30 31 32 /** 33 * Turns a domain mapping from its JSON representation containing simple strings 34 * only into a list of speech rules. 35 * @param {string} name Name for the rules. 36 * @param {string} str String for precondition and constraints. 37 * @param {Object.<string, Object.<string, string>>} mapping Simple string 38 * mapping. 39 */ 40 cvox.MathSimpleStore.prototype.defineRulesFromMappings = function( 41 name, str, mapping) { 42 for (var domain in mapping) { 43 for (var style in mapping[domain]) { 44 var content = mapping[domain][style]; 45 var cstr = 'self::text() = "' + str + '"'; 46 var rule = this.defineRule( 47 name, domain + '.' + style, '[t] "' + content + '"', 48 'self::text()', cstr); 49 } 50 } 51 }; 52 53 54 /** 55 * A compound store for simple Math objects. 56 * @constructor 57 */ 58 cvox.MathCompoundStore = function() { 59 /** 60 * A set of efficient substores. 61 * @type {Object.<string, cvox.MathStore>} 62 * @private 63 */ 64 this.subStores_ = {}; 65 }; 66 goog.addSingletonGetter(cvox.MathCompoundStore); 67 68 69 /** 70 * Function creates a rule store in the compound store for a particular string, 71 * and populates it with a set of rules. 72 * @param {string} name Name of the rule. 73 * @param {string} str String used as key to refer to the rule store 74 * precondition and constr 75 * @param {Object} mappings JSON representation of mappings from styles and 76 * domains to strings, from which the speech rules will be computed. 77 */ 78 cvox.MathCompoundStore.prototype.defineRules = function(name, str, mappings) { 79 var store = new cvox.MathSimpleStore(); 80 store.defineRulesFromMappings(name, str, mappings); 81 this.subStores_[str] = store; 82 }; 83 84 85 /** 86 * Makes a speech rule for Unicode characters from its JSON representation. 87 * @param {Object} json JSON object of the speech rules. 88 */ 89 cvox.MathCompoundStore.prototype.addSymbolRules = function(json) { 90 var key = cvox.MathSimpleStore.parseUnicode_(json['key']); 91 this.defineRules(json['key'], key, json['mappings']); 92 }; 93 94 95 /** 96 * Makes a speech rule for Unicode characters from its JSON representation. 97 * @param {Object} json JSON object of the speech rules. 98 */ 99 cvox.MathCompoundStore.prototype.addFunctionRules = function(json) { 100 var names = json['names']; 101 var mappings = json['mappings']; 102 for (var j = 0, name; name = names[j]; j++) { 103 this.defineRules(name, name, mappings); 104 } 105 }; 106 107 108 /** 109 * Retrieves a rule for the given node if one exists. 110 * @param {Node} node A node. 111 * @param {!cvox.SpeechRule.DynamicCstr} dynamic Additional dynamic 112 * constraints. These are matched against properties of a rule. 113 * @return {cvox.SpeechRule} The speech rule if it exists. 114 */ 115 cvox.MathCompoundStore.prototype.lookupRule = function(node, dynamic) { 116 var store = this.subStores_[node.textContent]; 117 if (store) { 118 return store.lookupRule(node, dynamic); 119 } 120 }; 121 122 123 /** 124 * Looks up a rule for a given string and executes its actions. 125 * @param {string} text The text to be translated. 126 * @param {!cvox.SpeechRule.DynamicCstr} dynamic Additional dynamic 127 * constraints. These are matched against properties of a rule. 128 * @return {!string} The string resulting from the action of speech rule. 129 */ 130 cvox.MathCompoundStore.prototype.lookupString = function(text, dynamic) { 131 var textNode = document.createTextNode(text); 132 var rule = this.lookupRule(textNode, dynamic); 133 if (!rule) { 134 return ''; 135 } 136 return rule.action.components 137 .map(function(comp) { 138 return comp.content.slice(1, -1);}) 139 .join(' '); 140 }; 141 142 143 /** 144 * Get a set of all dynamic constraint values. 145 * @return {!Object.<cvox.SpeechRule.DynamicCstrAttrib, Array.<string>>} The 146 * object with all annotations. 147 */ 148 cvox.MathCompoundStore.prototype.getDynamicConstraintValues = function() { 149 var newCstr = {}; 150 for (var store in this.subStores_) { 151 var cstr = this.subStores_[store].getDynamicConstraintValues(); 152 for (var key in cstr) { 153 var set = newCstr[key]; 154 if (set) { 155 newCstr[key] = cvox.MathUtil.union(set, cstr[key]); 156 } else { 157 newCstr[key] = cstr[key]; 158 } 159 } 160 } 161 return newCstr; 162 }; 163 164 165 /** 166 * Parses a string with a hex representatino of a unicode code point into the 167 * corresponding unicode character. 168 * @param {string} number The code point to be parsed. 169 * @return {string} The unicode character. 170 * @private 171 */ 172 cvox.MathSimpleStore.parseUnicode_ = function(number) { 173 var keyValue = parseInt(number, 16); 174 if (keyValue < 0x10000) { 175 return String.fromCharCode(keyValue); 176 } 177 keyValue -= 0x10000; 178 var hiSurrogate = (keyValue >> 10) + 0xD800; 179 var lowSurrogate = (keyValue & 0x3FF) + 0xDC00; 180 return String.fromCharCode(hiSurrogate, lowSurrogate); 181 }; 182