Commit d9074fe0 authored by David Tseng's avatar David Tseng Committed by Commit Bot

Generalize splitting logic in ChromeVox

Bug: 1057904
Test: browser_tests --gtest_filter=ChromeVox*.*

Change-Id: I0f858a0a0d3fc2a34177446cb702212b6ededa84
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2095915
Commit-Queue: David Tseng <dtseng@chromium.org>
Reviewed-by: default avatarHiroki Sato <hirokisato@chromium.org>
Cr-Commit-Position: refs/heads/master@{#748875}
parent c3d10e4d
...@@ -94,6 +94,9 @@ UserAnnotationHandler = class { ...@@ -94,6 +94,9 @@ UserAnnotationHandler = class {
* @return {?string} * @return {?string}
*/ */
static getAnnotationForNode(node) { static getAnnotationForNode(node) {
if (!node.root) {
return null;
}
const url = node.root.docUrl || ''; const url = node.root.docUrl || '';
if (!UserAnnotationHandler.instance || if (!UserAnnotationHandler.instance ||
!UserAnnotationHandler.instance.enabled || !url) { !UserAnnotationHandler.instance.enabled || !url) {
......
...@@ -260,18 +260,54 @@ TtsBackground = class extends ChromeTtsBase { ...@@ -260,18 +260,54 @@ TtsBackground = class extends ChromeTtsBase {
* @private * @private
*/ */
speakSplittingText_(textString, queueMode, properties) { speakSplittingText_(textString, queueMode, properties) {
const lines = textString.split(/\r\n|\r|\n/); const chunks = TtsBackground.splitUntilSmall(textString, '\n\r ');
for (const line of lines) { for (const chunk of chunks) {
if (line.length > constants.OBJECT_MAX_CHARCOUNT) { this.speak(chunk, queueMode, properties);
// Skip the paragraph when it's really a large paragraph.
// TODO(1057904): Try splitting based on spaces.
continue;
}
this.speak(line, queueMode, properties);
queueMode = QueueMode.QUEUE; queueMode = QueueMode.QUEUE;
} }
} }
/**
* Splits |text| until each substring's length is smaller than or equal to
* constants.OBJECT_MAX_CHARCOUNT.
* @param {string} text
* @param {string} delimiters
* @return {!Array<string>}
*/
static splitUntilSmall(text, delimiters) {
if (text.length == 0) {
return [];
}
if (text.length <= constants.OBJECT_MAX_CHARCOUNT) {
return [text];
}
const midIndex = text.length / 2;
if (!delimiters) {
return TtsBackground
.splitUntilSmall(text.substring(0, midIndex), delimiters)
.concat(TtsBackground.splitUntilSmall(
text.substring(midIndex, text.length), delimiters));
}
const delimiter = delimiters[0];
let splitIndex = text.lastIndexOf(delimiter, midIndex);
if (splitIndex == -1) {
splitIndex = text.indexOf(delimiter, midIndex);
}
if (splitIndex == -1) {
delimiters = delimiters.slice(1);
return TtsBackground.splitUntilSmall(text, delimiters);
}
return TtsBackground
.splitUntilSmall(text.substring(0, splitIndex), delimiters)
.concat(TtsBackground.splitUntilSmall(
text.substring(splitIndex + 1, text.length), delimiters));
}
/** /**
* Use the speech queue to handle the given speech request. * Use the speech queue to handle the given speech request.
* @param {Utterance} utterance The utterance to speak. * @param {Utterance} utterance The utterance to speak.
......
...@@ -199,11 +199,52 @@ SYNC_TEST_F('ChromeVoxTtsBackgroundTest', 'SplitLongText', function() { ...@@ -199,11 +199,52 @@ SYNC_TEST_F('ChromeVoxTtsBackgroundTest', 'SplitLongText', function() {
spokenTextStrings.push(utterance.textString); spokenTextStrings.push(utterance.textString);
}; };
const baseText = 'This is a very long text.\n'; // There are three new lines, but only the first chunk exceeds the max
const numRepeats = // character count.
Math.floor(constants.OBJECT_MAX_CHARCOUNT / baseText.length); const text = 'a'.repeat(constants.OBJECT_MAX_CHARCOUNT) + '\n' +
const text = baseText + baseText.repeat(numRepeats); 'a'.repeat(10) + '\n' +
'a'.repeat(10);
tts.speak(text); tts.speak(text);
assertEquals(1 + numRepeats, spokenTextStrings.length); assertEquals(2, spokenTextStrings.length);
});
SYNC_TEST_F('ChromeVoxTtsBackgroundTest', 'SplitUntilSmall', function() {
const split = TtsBackground.splitUntilSmall;
// A single delimiter.
constants.OBJECT_MAX_CHARCOUNT = 3;
assertEqualsJSON(['12', '345', '789'], split('12345a789', 'a'));
constants.OBJECT_MAX_CHARCOUNT = 4;
assertEqualsJSON(['12', '345', '789'], split('12345a789', 'a'));
constants.OBJECT_MAX_CHARCOUNT = 7;
assertEqualsJSON(['12345', '789'], split('12345a789', 'a'));
constants.OBJECT_MAX_CHARCOUNT = 10;
assertEqualsJSON(['12345a789'], split('12345a789', 'a'));
// Multiple delimiters.
constants.OBJECT_MAX_CHARCOUNT = 3;
assertEqualsJSON(['12', '34', '57', '89'], split('1234b57a89', 'ab'));
constants.OBJECT_MAX_CHARCOUNT = 4;
assertEqualsJSON(['1234', '57', '89'], split('1234b57a89', 'ab'));
constants.OBJECT_MAX_CHARCOUNT = 5;
assertEqualsJSON(['12345', '789'], split('12345b789a', 'ab'));
assertEqualsJSON(['12345', '789a'], split('12345b789a', 'ba'));
// No delimiters.
constants.OBJECT_MAX_CHARCOUNT = 3;
assertEqualsJSON(['12', '34', '57', '89'], split('12345789', ''));
constants.OBJECT_MAX_CHARCOUNT = 4;
assertEqualsJSON(['1234', '5789'], split('12345789', ''));
// Some corner cases.
assertEqualsJSON([], split('', ''));
assertEqualsJSON(['a'], split('a', ''));
assertEqualsJSON(['a'], split('a', 'a'));
assertEqualsJSON(['a'], split('a', 'b'));
}); });
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment