Remove the old signature of NotificationManager::closePersistent().
[chromium-blink-merge.git] / chrome / browser / resources / chromeos / chromevox / braille / expanding_braille_translator.js
blob24b28b42e341882f2c9e0797f639cec845eb6724
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.
5 /**
6  * @fileoverview Translates text to braille, optionally with some parts
7  * uncontracted.
8  */
10 goog.provide('cvox.ExpandingBrailleTranslator');
12 goog.require('cvox.LibLouis');
13 goog.require('cvox.Spannable');
14 goog.require('cvox.ValueSelectionSpan');
15 goog.require('cvox.ValueSpan');
18 /**
19  * 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  * translated text.  If only one translator is provided, then that translator
22  * is used for all text regardless of selection.  If two translators
23  * are provided, then the uncontracted translator is used for some text
24  * around the selection end-points and the contracted translator is used
25  * for all other text.  When determining what text to use uncontracted
26  * translation for around a position, a region surrounding that position
27  * containing either only whitespace characters or only non-whitespace
28  * characters is used.
29  * @param {!cvox.LibLouis.Translator} defaultTranslator The translator for all
30  *     text when the uncontracted translator is not used.
31  * @param {cvox.LibLouis.Translator=} opt_uncontractedTranslator
32  *     Translator to use for uncontracted braille translation.
33  * @constructor
34  */
35 cvox.ExpandingBrailleTranslator =
36     function(defaultTranslator, opt_uncontractedTranslator) {
37   /**
38    * @type {!cvox.LibLouis.Translator}
39    * @private
40    */
41   this.defaultTranslator_ = defaultTranslator;
42   /**
43    * @type {cvox.LibLouis.Translator}
44    * @private
45    */
46   this.uncontractedTranslator_ = opt_uncontractedTranslator || null;
50 /**
51  * What expansion to apply to the part of the translated string marked by the
52  * {@code cvox.ValueSpan} spannable.
53  * @enum {number}
54  */
55 cvox.ExpandingBrailleTranslator.ExpansionType = {
56   /**
57    * Use the default translator all of the value, regardless of any selection.
58    * This is typically used when the user is in the middle of typing and the
59    * typing started outside of a word.
60    */
61   NONE: 0,
62   /**
63    * Expand text around the selection end-points if any.  If the selection is
64    * a cursor, expand the text that occupies the positions right before and
65    * after the cursor.  This is typically used when the user hasn't started
66    * typing contracted braille or when editing inside a word.
67    */
68   SELECTION: 1,
69   /**
70    * Expand all text covered by the value span.  this is typically used when
71    * the user is editing a text field where it doesn't make sense to use
72    * contracted braille (such as a url or email address).
73    */
74   ALL: 2
78 /**
79  * Translates text to braille using the translator(s) provided to the
80  * constructor.  See {@code cvox.LibLouis.Translator} for further details.
81  * @param {!cvox.Spannable} text Text to translate.
82  * @param {cvox.ExpandingBrailleTranslator.ExpansionType} expansionType
83  *     Indicates how the text marked by a value span, if any, is expanded.
84  * @param {function(!ArrayBuffer, !Array<number>, !Array<number>)}
85  *     callback Called when the translation is done.  It takes resulting
86  *         braille cells and positional mappings as parameters.
87  */
88 cvox.ExpandingBrailleTranslator.prototype.translate =
89     function(text, expansionType, callback) {
90   var expandRanges = this.findExpandRanges_(text, expansionType);
91   if (expandRanges.length == 0) {
92     this.defaultTranslator_.translate(
93         text.toString(),
94         cvox.ExpandingBrailleTranslator.nullParamsToEmptyAdapter_(
95             text.getLength(), callback));
96     return;
97   }
99   var chunks = [];
100   function addChunk(translator, start, end) {
101     chunks.push({translator: translator, start: start, end: end});
102   }
103   var lastEnd = 0;
104   for (var i = 0; i < expandRanges.length; ++i) {
105     var range = expandRanges[i];
106     if (lastEnd < range.start) {
107       addChunk(this.defaultTranslator_, lastEnd, range.start);
108     }
109     addChunk(this.uncontractedTranslator_, range.start, range.end);
110     lastEnd = range.end;
111   }
112   if (lastEnd < text.getLength()) {
113     addChunk(this.defaultTranslator_, lastEnd, text.getLength());
114   }
116   var numPendingCallbacks = chunks.length;
118   function chunkTranslated(chunk, cells, textToBraille, brailleToText) {
119     chunk.cells = cells;
120     chunk.textToBraille = textToBraille;
121     chunk.brailleToText = brailleToText;
122     if (--numPendingCallbacks <= 0) {
123       finish();
124     }
125   }
127   function finish() {
128     var totalCells = chunks.reduce(
129         function(accum, chunk) { return accum + chunk.cells.byteLength}, 0);
130     var cells = new Uint8Array(totalCells);
131     var cellPos = 0;
132     var textToBraille = [];
133     var brailleToText = [];
134     function appendAdjusted(array, toAppend, adjustment) {
135       array.push.apply(array, toAppend.map(
136           function(elem) { return adjustment + elem; }
137           ));
138     }
139     for (var i = 0, chunk; chunk = chunks[i]; ++i) {
140       cells.set(new Uint8Array(chunk.cells), cellPos);
141       appendAdjusted(textToBraille, chunk.textToBraille, cellPos);
142       appendAdjusted(brailleToText, chunk.brailleToText, chunk.start);
143       cellPos += chunk.cells.byteLength;
144     }
145     callback(cells.buffer, textToBraille, brailleToText);
146   }
148   for (var i = 0, chunk; chunk = chunks[i]; ++i) {
149     chunk.translator.translate(
150         text.toString().substring(chunk.start, chunk.end),
151         cvox.ExpandingBrailleTranslator.nullParamsToEmptyAdapter_(
152             chunk.end - chunk.start, goog.partial(chunkTranslated, chunk)));
153   }
158  * Expands a position to a range that covers the consecutive range of
159  * either whitespace or non whitespace characters around it.
160  * @param {string} str Text to look in.
161  * @param {number} pos Position to start looking at.
162  * @param {number} start Minimum value for the start position of the returned
163  *     range.
164  * @param {number} end Maximum value for the end position of the returned
165  *     range.
166  * @return {!cvox.ExpandingBrailleTranslator.Range_} The claculated range.
167  * @private
168  */
169 cvox.ExpandingBrailleTranslator.rangeForPosition_ = function(
170     str, pos, start, end) {
171   if (start < 0 || end > str.length) {
172     throw RangeError(
173         'End-points out of range looking for braille expansion range');
174   }
175   if (pos < start || pos >= end) {
176     throw RangeError(
177         'Position out of range looking for braille expansion range');
178   }
179   // Find the last chunk of either whitespace or non-whitespace before and
180   // including pos.
181   var start = str.substring(start, pos + 1).search(/(\s+|\S+)$/) + start;
182   // Find the characters to include after pos, starting at pos so that
183   // they are the same kind (either whitespace or not) as the
184   // characters starting at start.
185   var end = pos + /^(\s+|\S+)/.exec(str.substring(pos, end))[0].length;
186   return {start: start, end: end};
191  * Finds the ranges in which contracted braille should not be used.
192  * @param {!cvox.Spannable} text Text to find expansion ranges in.
193  * @param {cvox.ExpandingBrailleTranslator.ExpansionType} expansionType
194  *     Indicates how the text marked up as the value is expanded.
195  * @return {!Array<cvox.ExpandingBrailleTranslator.Range_>} The calculated
196  *     ranges.
197  * @private
198  */
199 cvox.ExpandingBrailleTranslator.prototype.findExpandRanges_ = function(
200     text, expansionType) {
201   var result = [];
202   if (this.uncontractedTranslator_ &&
203       expansionType != cvox.ExpandingBrailleTranslator.ExpansionType.NONE) {
204     var value = text.getSpanInstanceOf(cvox.ValueSpan);
205     if (value) {
206       // The below type casts are valid because the ranges must be valid when
207       // the span is known to exist.
208       var valueStart = /** @type {number} */ (text.getSpanStart(value));
209       var valueEnd = /** @type {number} */ (text.getSpanEnd(value));
210       switch (expansionType) {
211         case cvox.ExpandingBrailleTranslator.ExpansionType.SELECTION:
212           this.addRangesForSelection_(text, valueStart, valueEnd, result);
213           break;
214         case cvox.ExpandingBrailleTranslator.ExpansionType.ALL:
215           result.push({start: valueStart, end: valueEnd});
216           break;
217       }
218     }
219   }
221   return result;
226  * Finds ranges to expand around selection end points inside the value of
227  * a string.  If any ranges are found, adds them to {@code outRanges}.
228  * @param {cvox.Spannable} text Text to find ranges in.
229  * @param {number} valueStart Start of the value in {@code text}.
230  * @param {number} valueEnd End of the value in {@code text}.
231  * @param {Array<cvox.ExpandingBrailleTranslator.Range_>} outRanges
232  *     Destination for the expansion ranges.  Untouched if no ranges
233  *     are found.  Note that ranges may be coalesced.
234  * @private
235  */
236 cvox.ExpandingBrailleTranslator.prototype.addRangesForSelection_ = function(
237     text, valueStart, valueEnd, outRanges) {
238   var selection = text.getSpanInstanceOf(cvox.ValueSelectionSpan);
239   if (!selection) {
240     return;
241   }
242   var selectionStart = text.getSpanStart(selection);
243   var selectionEnd = text.getSpanEnd(selection);
244   if (selectionStart < valueStart || selectionEnd > valueEnd) {
245     return;
246   }
247   var expandPositions = [];
248   if (selectionStart == valueEnd) {
249     if (selectionStart > valueStart) {
250       expandPositions.push(selectionStart - 1);
251     }
252   } else {
253     if (selectionStart == selectionEnd && selectionStart > valueStart) {
254       expandPositions.push(selectionStart - 1);
255     }
256     expandPositions.push(selectionStart);
257     // Include the selection end if the length of the selection is
258     // greater than one (otherwise this position would be redundant).
259     if (selectionEnd > selectionStart + 1) {
260       // Look at the last actual character of the selection, not the
261       // character at the (exclusive) end position.
262       expandPositions.push(selectionEnd - 1);
263     }
264   }
266   var lastRange = outRanges[outRanges.length - 1] || null;
267   for (var i = 0; i < expandPositions.length; ++i) {
268     var range = cvox.ExpandingBrailleTranslator.rangeForPosition_(
269         text.toString(), expandPositions[i], valueStart, valueEnd);
270     if (lastRange && lastRange.end >= range.start) {
271       lastRange.end = range.end;
272     } else {
273       outRanges.push(range);
274       lastRange = range;
275     }
276   }
281  * Adapts {@code callback} to accept null arguments and treat them as if the
282  * translation result is empty.
283  * @param {number} inputLength Length of the input to the translation.
284  *     Used for populating {@code textToBraille} if null.
285  * @param {function(!ArrayBuffer, !Array<number>, !Array<number>)} callback
286  *     The callback to adapt.
287  * @return {function(ArrayBuffer, Array<number>, Array<number>)}
288  *     An adapted version of the callback.
289  * @private
290  */
291 cvox.ExpandingBrailleTranslator.nullParamsToEmptyAdapter_ =
292     function(inputLength, callback) {
293   return function(cells, textToBraille, brailleToText) {
294     if (!textToBraille) {
295       textToBraille = new Array(inputLength);
296       for (var i = 0; i < inputLength; ++i) {
297         textToBraille[i] = 0;
298       }
299     }
300     callback(cells || new ArrayBuffer(0),
301              textToBraille,
302              brailleToText || []);
303   };
308  * A character range with inclusive start and exclusive end positions.
309  * @typedef {{start: number, end: number}}
310  * @private
311  */
312 cvox.ExpandingBrailleTranslator.Range_;