Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1774)

Unified Diff: chrome/browser/resources/chromeos/chromevox/braille/pan_strategy.js

Issue 2496823002: Implement word wrapping and panning in multiline Braille. (Closed)
Patch Set: Addressed code reviews. Created 4 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: chrome/browser/resources/chromeos/chromevox/braille/pan_strategy.js
diff --git a/chrome/browser/resources/chromeos/chromevox/braille/pan_strategy.js b/chrome/browser/resources/chromeos/chromevox/braille/pan_strategy.js
index 9984b263efff43d017cd7e99aeb440cd876d7940..536ee0ff5e3285df1b01863f8b6dcc16e590f537 100644
--- a/chrome/browser/resources/chromeos/chromevox/braille/pan_strategy.js
+++ b/chrome/browser/resources/chromeos/chromevox/braille/pan_strategy.js
@@ -19,24 +19,67 @@ cvox.PanStrategy = function() {
* @type {number}
* @private
*/
- this.displaySize_ = 0;
+ this.rowCount_ = 0;
/**
* @type {number}
* @private
*/
- this.contentLength_ = 0;
+ this.columnCount_ = 0;
/**
- * Points before which it is desirable to break content if it doesn't fit
- * on the display.
- * @type {!Array<number>}
+ * Start and end are both inclusive.
+ * @type {!cvox.PanStrategy.Range}
* @private
*/
- this.breakPoints_ = [];
+ this.viewPort_ = {start: 0, end: 0};
+
/**
- * @type {!cvox.PanStrategy.Range}
+ * Start and end are both inclusive.
+ * @type {ArrayBuffer}
* @private
*/
- this.viewPort_ = {start: 0, end: 0};
+ this.wrappedBuffer_ = new ArrayBuffer(0);
+
+ /**
+ * Start and end are both inclusive.
+ * @type {ArrayBuffer}
+ * @private
+ */
+ this.fixedBuffer_ = new ArrayBuffer(0);
+
+ /**
+ * Start and end are both inclusive.
+ * @type {Array}
David Tseng 2016/11/15 17:55:00 Array<number>
ultimatedbz 2016/11/19 03:11:59 Done.
+ * @private
+ */
+ this.wrappedBrailleToText_ = [];
+
+ /**
+ * Start and end are both inclusive.
David Tseng 2016/11/15 17:55:00 Fix these comments.
ultimatedbz 2016/11/19 03:11:59 Done.
+ * @type {Array}
+ * @private
+ */
+ this.fixedBrailleToText_ = [];
+
+ /**
+ * Start and end are both inclusive.
+ * @type {boolean}
+ * @private
+ */
+ this.panStrategyWrapped_ = false;
+
+ /**
+ * Start and end are both inclusive.
+ * @type {number}
+ * @private
+ */
+ this.fixedLineCount_ = 0;
David Tseng 2016/11/16 16:56:01 You don't need this (and the below) members. Just
ultimatedbz 2016/11/19 03:11:58 Done.
+
+ /**
+ * Start and end are both inclusive.
+ * @type {number}
+ * @private
+ */
+ this.wrappedLineCount_ = 0;
};
/**
@@ -58,26 +101,154 @@ cvox.PanStrategy.prototype = {
},
/**
+ * @return {Array<number>} The offset of braille and text indices of the
David Tseng 2016/11/15 17:55:00 Make this an Object e.g. {brailleOffset: number, t
ultimatedbz 2016/11/19 03:11:58 Done.
+ * current slice.
+ */
+ get offsetsForSlices() {
+ return [this.viewPort_.start * this.columnCount_,
+ this.brailleToText[this.viewPort_.start * this.columnCount_]];
+ },
+
+ /**
+ * @return {Array<number>} The map of Braille cells to the first index of the
+ * corresponding text character.
David Tseng 2016/11/15 17:55:00 @return {Array<number}
ultimatedbz 2016/11/19 03:11:59 I'm not sure what you're suggesting? Thanks!
+ */
+ get brailleToText() {
+ if (this.panStrategyWrapped_)
+ return this.wrappedBrailleToText_;
+ else
+ return this.fixedBrailleToText_;
+ },
+
+ /**
+ * @return {ArrayBuffer} Buffer of the slice of braille cells within the
+ * bounds of the viewport.
+ */
+ getCurrentBrailleSlice: function() {
+ var buf = this.panStrategyWrapped_ ?
+ this.wrappedBuffer_ : this.fixedBuffer_;
David Tseng 2016/11/15 17:54:59 Part of why it was nice to have different classes
ultimatedbz 2016/11/19 03:11:59 As per our offline conversation, we'll be keeping
+ buf = buf.slice(this.viewPort.start * this.columnCount_,
David Tseng 2016/11/15 17:54:59 return buff.slice...
ultimatedbz 2016/11/19 03:11:59 Done.
+ (this.viewPort.end + 1) * this.columnCount_);
David Tseng 2016/11/15 17:55:00 Why not just make the viewport index into the buff
ultimatedbz 2016/11/19 03:11:59 How about firstRow and lastRow?
+ return buf;
+ },
+
+ /**
+ * @return {string} String of the slice of text letters corresponding with
+ * the current braille slice.
David Tseng 2016/11/15 17:54:59 @return {Array<number>}
David Tseng 2016/11/16 16:56:01 Disregard.
+ */
+ getCurrentTextSlice: function() {
+ var brailleToText = this.brailleToText;
+ // Index of last braille character in slice.
+ var index = (this.viewPort.end + 1) * this.columnCount_ - 1;
David Tseng 2016/11/15 17:54:59 This just looks wrong (mostly the viewport.end + 1
ultimatedbz 2016/11/15 19:31:57 Right, so I know it looks a bit janky, but this.vi
David Tseng 2016/11/15 21:36:38 pan_strategy_test.unitjs awaits; I am generally ok
+ // Index of first text character that the last braille character points to.
+ var end = brailleToText[index];
+ // Increment index until brailleToText[index] points to a different char.
+ // This is the cutoff point, as substring cuts up to, but not including,
+ // brailleToText[index].
+ while (index < brailleToText.length && brailleToText[index] == end) {
+ index++;
+ }
David Tseng 2016/11/15 17:54:59 nit: no curlies for single lined if bodies.
David Tseng 2016/11/15 21:36:38 Ignore this :).
+ return this.textBuffer.substring(
David Tseng 2016/11/15 17:54:59 This deserves some unit tests to exercises the var
+ brailleToText[this.viewPort.start * this.columnCount_],
+ brailleToText[index]);
+ },
+
+ /**
+ * Sets the current pan strategy and resets the viewport.
+ */
+ setPanStrategy: function(wordWrap) {
+ this.panStrategyWrapped_ = wordWrap;
+ this.viewPort_.start = 0;
+ this.viewPort_.end = this.rowCount_ - 1;
+ },
+
+ /**
* Sets the display size. This call may update the viewport.
- * @param {number} size the new display size, or {@code 0} if no display is
+ * @param {number} rowCount the new row size, or {@code 0} if no display is
* present.
+ * @param {number} columnCount the new column size, or {@code 0}
+ * if no display is present.
*/
- setDisplaySize: function(size) {
- this.displaySize_ = size;
- this.panToPosition_(this.viewPort_.start);
David Tseng 2016/11/15 17:54:59 You'll want ot keep this around I suspect.
ultimatedbz 2016/11/19 03:11:59 Acknowledged.
+ setDisplaySize: function(rowCount, columnCount) {
+ this.rowCount_ = rowCount;
+ this.columnCount_ = columnCount;
},
/**
- * Sets the current content that panning should happen within. This call may
- * change the viewport.
- * @param {!ArrayBuffer} translatedContent The new content.
- * @param {number} targetPosition Target position. The viewport is changed
- * to overlap this position.
+ * Sets the internal data structures that hold the fixed and wrapped buffers
+ * and maps.
+ * @param {string} textBuffer Text of the shown braille.
+ * @param {!ArrayBuffer} translatedContent The new braille content.
+ * @param {Array<number>} fixedBrailleToText Map of Braille cells to the first
+ * index of corresponding text letter.
*/
- setContent: function(translatedContent, targetPosition) {
- this.breakPoints_ = this.calculateBreakPoints_(translatedContent);
- this.contentLength_ = translatedContent.byteLength;
- this.panToPosition_(targetPosition);
+ setContent: function(textBuffer, translatedContent, fixedBrailleToText) {
+ this.viewPort_.start = 0;
+ this.viewPort_.end = this.rowCount_ - 1;
+ this.fixedBrailleToText_ = fixedBrailleToText;
+ this.wrappedBrailleToText_ = [];
+ this.textBuffer = textBuffer;
David Tseng 2016/11/16 16:56:01 This isn't annotated and set in the constructor.
ultimatedbz 2016/11/19 03:11:59 Done.
+ this.fixedBuffer_ = translatedContent;
David Tseng 2016/11/16 16:56:01 Note that I think there are some tricky ownership
ultimatedbz 2016/11/19 03:11:58 I've now given the panStrategy full ownership of t
+
+ // Convert the cells to Unicode braille pattern characters.
+ var view = new Uint8Array(translatedContent);
+ var wrappedBrailleArray = [];
+
+ var lastBreak = 0;
+ var cellsPadded = 0;
+ var index;
+ for (index = 0; index < translatedContent.byteLength + cellsPadded;
+ index++) {
+ // Is index at the beginning of a new line?
+ if (index != 0 && index % this.columnCount_ == 0) {
+ if (view[index - cellsPadded] == 0) {
+ // On Delete all 0's at beginning of new line.
David Tseng 2016/11/15 17:55:00 Rephrase
ultimatedbz 2016/11/19 03:11:58 Done.
+ while (index - cellsPadded < view.length &&
+ view[index - cellsPadded] == 0) {
+ cellsPadded--;
+ }
David Tseng 2016/11/15 17:55:00 nit: remove curlies
ultimatedbz 2016/11/15 19:31:57 Is it okay to remove the curly braces, even though
David Tseng 2016/11/15 21:36:38 Good question. It looks like this file keeps curly
+ index--;
+ } else if (view[index - cellsPadded - 1] != 0 &&
+ lastBreak % this.columnCount_ != 0) {
+ // If first cell is not empty, we need to move the whole word down to
+ // this line and padd to previous line with 0's, from |lastBreak| to
+ // index. The braille to text map is also updated.
+ // If lastBreak is at the beginning of a line, that means the current
+ // word is bigger than |this.columnCount_| so we shouldn't wrap.
+ for (var j = lastBreak + 1; j < index; j++) {
+ wrappedBrailleArray[j] = 0;
David Tseng 2016/11/15 17:55:00 A few things: - this absolutely needs tests - for
+ this.wrappedBrailleToText_[j] = this.wrappedBrailleToText_[j - 1];
+ cellsPadded++;
+ }
+ lastBreak = index;
+ index--;
+ } else {
+ // |lastBreak| is at the beginning of a line, so current word is
+ // bigger than |this.columnCount_| so we shouldn't wrap.
+ wrappedBrailleArray.push(view[index - cellsPadded]);
+ this.wrappedBrailleToText_.push(
+ fixedBrailleToText[index - cellsPadded]);
+ }
+ } else {
+ if (view[index - cellsPadded] == 0) {
+ lastBreak = index;
+ }
+ wrappedBrailleArray.push(view[index - cellsPadded]);
+ this.wrappedBrailleToText_.push(
+ fixedBrailleToText[index - cellsPadded]);
+ }
+ }
+
+ // Convert the wrapped Braille Uint8 Array back to ArrayBuffer.
+ var wrappedBrailleUint8Array = new Uint8Array(wrappedBrailleArray);
+ this.wrappedBuffer_ = new ArrayBuffer(wrappedBrailleUint8Array.length);
+ new Uint8Array(this.wrappedBuffer_).set(wrappedBrailleUint8Array);
+
+ // Calculate how many lines are in the fixed and wrapped buffers.
+ this.fixedLineCount_ =
+ Math.ceil(this.fixedBuffer_.byteLength / this.columnCount_);
+ this.wrappedLineCount_ =
+ Math.ceil(this.wrappedBuffer_.byteLength / this.columnCount_);
David Tseng 2016/11/15 17:54:59 Optional: You might consider even storing a 2d arr
ultimatedbz 2016/11/15 19:31:57 Acknowledged.
},
/**
@@ -86,12 +257,14 @@ cvox.PanStrategy.prototype = {
* @return {boolean} {@code true} if the viewport was changed.
*/
next: function() {
+ var contentLength = this.panStrategyWrapped_ ?
+ this.wrappedLineCount_ : this.fixedLineCount_;
David Tseng 2016/11/15 17:54:59 I'm even more convinced now that you should separa
ultimatedbz 2016/11/15 19:31:57 I agree.
var newStart = this.viewPort_.end;
var newEnd;
- if (newStart + this.displaySize_ < this.contentLength_) {
- newEnd = this.extendRight_(newStart);
+ if (newStart + this.rowCount_ - 1 < contentLength) {
+ newEnd = newStart + this.rowCount_ - 1;
} else {
- newEnd = this.contentLength_;
+ newEnd = contentLength;
}
if (newEnd > newStart) {
this.viewPort_ = {start: newStart, end: newEnd};
@@ -106,24 +279,16 @@ cvox.PanStrategy.prototype = {
* @return {boolean} {@code true} if the viewport was changed.
*/
previous: function() {
+ var contentLength = this.panStrategyWrapped_ ?
+ this.wrappedLineCount_ : this.fixedLineCount_;
if (this.viewPort_.start > 0) {
var newStart, newEnd;
- if (this.viewPort_.start <= this.displaySize_) {
+ if (this.viewPort_.start < this.rowCount_) {
newStart = 0;
- newEnd = this.extendRight_(newStart);
+ newEnd = Math.min(this.rowCount_, contentLength);
} else {
newEnd = this.viewPort_.start;
- var limit = newEnd - this.displaySize_;
- newStart = limit;
- var pos = 0;
- while (pos < this.breakPoints_.length &&
- this.breakPoints_[pos] < limit) {
- pos++;
- }
- if (pos < this.breakPoints_.length &&
- this.breakPoints_[pos] < newEnd) {
- newStart = this.breakPoints_[pos];
- }
+ newStart = newEnd - this.rowCount_ + 1;
}
if (newStart < newEnd) {
this.viewPort_ = {start: newStart, end: newEnd};
@@ -134,43 +299,13 @@ cvox.PanStrategy.prototype = {
},
/**
- * Finds the end position for a new viewport start position, considering
- * current breakpoints as well as display size and content length.
- * @param {number} from Start of the region to extend.
- * @return {number}
- * @private
- */
- extendRight_: function(from) {
- var limit = Math.min(from + this.displaySize_, this.contentLength_);
- var pos = 0;
- var result = limit;
- while (pos < this.breakPoints_.length && this.breakPoints_[pos] <= from) {
- pos++;
- }
- while (pos < this.breakPoints_.length && this.breakPoints_[pos] <= limit) {
- result = this.breakPoints_[pos];
- pos++;
- }
- return result;
- },
-
- /**
- * Overridden by subclasses to provide breakpoints given translated
- * braille cell content.
- * @param {!ArrayBuffer} content New display content.
- * @return {!Array<number>} The points before which it is desirable to break
- * content if needed or the empty array if no points are more desirable
- * than any position.
- * @private
- */
- calculateBreakPoints_: function(content) {return [];},
-
- /**
+ * TODO need to implement for routing
* Moves the viewport so that it overlaps a target position without taking
* the current viewport position into consideration.
* @param {number} position Target position.
*/
panToPosition_: function(position) {
+ /*
David Tseng 2016/11/15 17:55:00 Don't do this, even in a work in progress cl.
ultimatedbz 2016/11/15 19:31:57 What should I do instead? The code would just brea
David Tseng 2016/11/15 21:36:38 Well, could you see how this method works and see
ultimatedbz 2016/11/15 22:25:42 Sorry, I should have clarified my question. My que
David Tseng 2016/11/16 16:56:01 As mentioned before, you're breaking things either
ultimatedbz 2016/11/19 03:11:58 Yep, this makes a lot more sense, and I'm glad we
if (this.displaySize_ > 0) {
this.viewPort_ = {start: 0, end: 0};
while (this.next() && this.viewPort_.end <= position) {
@@ -179,42 +314,6 @@ cvox.PanStrategy.prototype = {
} else {
this.viewPort_ = {start: position, end: position};
}
- },
-};
-
-/**
- * A pan strategy that fits as much content on the display as possible, that
- * is, it doesn't do any wrapping.
- * @constructor
- * @extends {cvox.PanStrategy}
- */
-cvox.FixedPanStrategy = cvox.PanStrategy;
-/**
- * A pan strategy that tries to wrap 'words' when breaking content.
- * A 'word' in this context is just a chunk of non-blank braille cells
- * delimited by blank cells.
- * @constructor
- * @extends {cvox.PanStrategy}
- */
-cvox.WrappingPanStrategy = function() {
- cvox.PanStrategy.call(this);
-};
-
-cvox.WrappingPanStrategy.prototype = {
- __proto__: cvox.PanStrategy.prototype,
-
- /** @override */
- calculateBreakPoints_: function(content) {
- var view = new Uint8Array(content);
- var newContentLength = view.length;
- var result = [];
- var lastCellWasBlank = false;
- for (var pos = 0; pos < view.length; ++pos) {
- if (lastCellWasBlank && view[pos] != 0) {
- result.push(pos);
- }
- lastCellWasBlank = (view[pos] == 0);
- }
- return result;
+ */
},
};

Powered by Google App Engine
This is Rietveld 408576698