OLD | NEW |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 /** | 5 /** |
6 * @fileoverview Translates text to braille, optionally with some parts | 6 * @fileoverview Translates text to braille, optionally with some parts |
7 * uncontracted. | 7 * uncontracted. |
8 */ | 8 */ |
9 | 9 |
10 goog.provide('cvox.ExpandingBrailleTranslator'); | 10 goog.provide('cvox.ExpandingBrailleTranslator'); |
11 | 11 |
| 12 goog.require('cvox.ExtraCellsSpan'); |
12 goog.require('cvox.LibLouis'); | 13 goog.require('cvox.LibLouis'); |
13 goog.require('cvox.Spannable'); | 14 goog.require('cvox.Spannable'); |
14 goog.require('cvox.ValueSelectionSpan'); | 15 goog.require('cvox.ValueSelectionSpan'); |
15 goog.require('cvox.ValueSpan'); | 16 goog.require('cvox.ValueSpan'); |
16 | 17 |
17 | 18 |
18 /** | 19 /** |
19 * A wrapper around one or two braille translators that uses contracted | 20 * A wrapper around one or two braille translators that uses contracted |
20 * braille or not based on the selection start- and end-points (if any) in the | 21 * braille or not based on the selection start- and end-points (if any) in the |
21 * translated text. If only one translator is provided, then that translator | 22 * translated text. If only one translator is provided, then that translator |
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
81 * @param {!cvox.Spannable} text Text to translate. | 82 * @param {!cvox.Spannable} text Text to translate. |
82 * @param {cvox.ExpandingBrailleTranslator.ExpansionType} expansionType | 83 * @param {cvox.ExpandingBrailleTranslator.ExpansionType} expansionType |
83 * Indicates how the text marked by a value span, if any, is expanded. | 84 * Indicates how the text marked by a value span, if any, is expanded. |
84 * @param {function(!ArrayBuffer, !Array<number>, !Array<number>)} | 85 * @param {function(!ArrayBuffer, !Array<number>, !Array<number>)} |
85 * callback Called when the translation is done. It takes resulting | 86 * callback Called when the translation is done. It takes resulting |
86 * braille cells and positional mappings as parameters. | 87 * braille cells and positional mappings as parameters. |
87 */ | 88 */ |
88 cvox.ExpandingBrailleTranslator.prototype.translate = | 89 cvox.ExpandingBrailleTranslator.prototype.translate = |
89 function(text, expansionType, callback) { | 90 function(text, expansionType, callback) { |
90 var expandRanges = this.findExpandRanges_(text, expansionType); | 91 var expandRanges = this.findExpandRanges_(text, expansionType); |
91 if (expandRanges.length == 0) { | 92 var extraCellsSpans = text.getSpansInstanceOf(cvox.ExtraCellsSpan) |
| 93 .filter(function(span) { return span.cells.byteLength > 0;}); |
| 94 var extraCellsPositions = extraCellsSpans.map(function(span) { |
| 95 return text.getSpanStart(span); |
| 96 }); |
| 97 if (expandRanges.length == 0 && extraCellsSpans.length == 0) { |
92 this.defaultTranslator_.translate( | 98 this.defaultTranslator_.translate( |
93 text.toString(), | 99 text.toString(), |
94 cvox.ExpandingBrailleTranslator.nullParamsToEmptyAdapter_( | 100 cvox.ExpandingBrailleTranslator.nullParamsToEmptyAdapter_( |
95 text.getLength(), callback)); | 101 text.getLength(), callback)); |
96 return; | 102 return; |
97 } | 103 } |
98 | 104 |
99 var chunks = []; | 105 var chunks = []; |
| 106 function maybeAddChunkToTranslate(translator, start, end) { |
| 107 if (start < end) |
| 108 chunks.push({translator: translator, start: start, end: end}); |
| 109 } |
| 110 function addExtraCellsChunk(pos, cells) { |
| 111 var chunk = {translator: null, |
| 112 start: pos, |
| 113 end: pos, |
| 114 cells: cells, |
| 115 textToBraille: [], |
| 116 brailleToText: new Array(cells.byteLength)}; |
| 117 for (var i = 0; i < cells.byteLength; ++i) |
| 118 chunk.brailleToText[i] = 0; |
| 119 chunks.push(chunk); |
| 120 } |
100 function addChunk(translator, start, end) { | 121 function addChunk(translator, start, end) { |
101 chunks.push({translator: translator, start: start, end: end}); | 122 while (extraCellsSpans.length > 0 && extraCellsPositions[0] <= end) { |
| 123 maybeAddChunkToTranslate(translator, start, extraCellsPositions[0]); |
| 124 start = extraCellsPositions.shift(); |
| 125 addExtraCellsChunk(start, extraCellsSpans.shift().cells); |
| 126 } |
| 127 maybeAddChunkToTranslate(translator, start, end); |
102 } | 128 } |
103 var lastEnd = 0; | 129 var lastEnd = 0; |
104 for (var i = 0; i < expandRanges.length; ++i) { | 130 for (var i = 0; i < expandRanges.length; ++i) { |
105 var range = expandRanges[i]; | 131 var range = expandRanges[i]; |
106 if (lastEnd < range.start) { | 132 if (lastEnd < range.start) { |
107 addChunk(this.defaultTranslator_, lastEnd, range.start); | 133 addChunk(this.defaultTranslator_, lastEnd, range.start); |
108 } | 134 } |
109 addChunk(this.uncontractedTranslator_, range.start, range.end); | 135 addChunk(this.uncontractedTranslator_, range.start, range.end); |
110 lastEnd = range.end; | 136 lastEnd = range.end; |
111 } | 137 } |
112 if (lastEnd < text.getLength()) { | 138 addChunk(this.defaultTranslator_, lastEnd, text.getLength()); |
113 addChunk(this.defaultTranslator_, lastEnd, text.getLength()); | |
114 } | |
115 | 139 |
116 var numPendingCallbacks = chunks.length; | 140 var chunksToTranslate = chunks.filter(function(chunk) { |
| 141 return chunk.translator; |
| 142 }); |
| 143 var numPendingCallbacks = chunksToTranslate.length; |
117 | 144 |
118 function chunkTranslated(chunk, cells, textToBraille, brailleToText) { | 145 function chunkTranslated(chunk, cells, textToBraille, brailleToText) { |
119 chunk.cells = cells; | 146 chunk.cells = cells; |
120 chunk.textToBraille = textToBraille; | 147 chunk.textToBraille = textToBraille; |
121 chunk.brailleToText = brailleToText; | 148 chunk.brailleToText = brailleToText; |
122 if (--numPendingCallbacks <= 0) { | 149 if (--numPendingCallbacks <= 0) |
123 finish(); | 150 finish(); |
124 } | |
125 } | 151 } |
126 | 152 |
127 function finish() { | 153 function finish() { |
128 var totalCells = chunks.reduce( | 154 var totalCells = chunks.reduce( |
129 function(accum, chunk) { return accum + chunk.cells.byteLength}, 0); | 155 function(accum, chunk) { return accum + chunk.cells.byteLength}, 0); |
130 var cells = new Uint8Array(totalCells); | 156 var cells = new Uint8Array(totalCells); |
131 var cellPos = 0; | 157 var cellPos = 0; |
132 var textToBraille = []; | 158 var textToBraille = []; |
133 var brailleToText = []; | 159 var brailleToText = []; |
134 function appendAdjusted(array, toAppend, adjustment) { | 160 function appendAdjusted(array, toAppend, adjustment) { |
135 array.push.apply(array, toAppend.map( | 161 array.push.apply(array, toAppend.map( |
136 function(elem) { return adjustment + elem; } | 162 function(elem) { return adjustment + elem; } |
137 )); | 163 )); |
138 } | 164 } |
139 for (var i = 0, chunk; chunk = chunks[i]; ++i) { | 165 for (var i = 0, chunk; chunk = chunks[i]; ++i) { |
140 cells.set(new Uint8Array(chunk.cells), cellPos); | 166 cells.set(new Uint8Array(chunk.cells), cellPos); |
141 appendAdjusted(textToBraille, chunk.textToBraille, cellPos); | 167 appendAdjusted(textToBraille, chunk.textToBraille, cellPos); |
142 appendAdjusted(brailleToText, chunk.brailleToText, chunk.start); | 168 appendAdjusted(brailleToText, chunk.brailleToText, chunk.start); |
143 cellPos += chunk.cells.byteLength; | 169 cellPos += chunk.cells.byteLength; |
144 } | 170 } |
145 callback(cells.buffer, textToBraille, brailleToText); | 171 callback(cells.buffer, textToBraille, brailleToText); |
146 } | 172 } |
147 | 173 |
148 for (var i = 0, chunk; chunk = chunks[i]; ++i) { | 174 if (chunksToTranslate.length > 0) { |
149 chunk.translator.translate( | 175 chunksToTranslate.forEach(function(chunk) { |
150 text.toString().substring(chunk.start, chunk.end), | 176 chunk.translator.translate( |
151 cvox.ExpandingBrailleTranslator.nullParamsToEmptyAdapter_( | 177 text.toString().substring(chunk.start, chunk.end), |
152 chunk.end - chunk.start, goog.partial(chunkTranslated, chunk))); | 178 cvox.ExpandingBrailleTranslator.nullParamsToEmptyAdapter_( |
| 179 chunk.end - chunk.start, goog.partial(chunkTranslated, chunk))); |
| 180 }); |
| 181 } else { |
| 182 finish(); |
153 } | 183 } |
154 }; | 184 }; |
155 | 185 |
156 | 186 |
157 /** | 187 /** |
158 * Expands a position to a range that covers the consecutive range of | 188 * Expands a position to a range that covers the consecutive range of |
159 * either whitespace or non whitespace characters around it. | 189 * either whitespace or non whitespace characters around it. |
160 * @param {string} str Text to look in. | 190 * @param {string} str Text to look in. |
161 * @param {number} pos Position to start looking at. | 191 * @param {number} pos Position to start looking at. |
162 * @param {number} start Minimum value for the start position of the returned | 192 * @param {number} start Minimum value for the start position of the returned |
(...skipping 140 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
303 }; | 333 }; |
304 }; | 334 }; |
305 | 335 |
306 | 336 |
307 /** | 337 /** |
308 * A character range with inclusive start and exclusive end positions. | 338 * A character range with inclusive start and exclusive end positions. |
309 * @typedef {{start: number, end: number}} | 339 * @typedef {{start: number, end: number}} |
310 * @private | 340 * @private |
311 */ | 341 */ |
312 cvox.ExpandingBrailleTranslator.Range_; | 342 cvox.ExpandingBrailleTranslator.Range_; |
OLD | NEW |