Chromium Code Reviews| 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..71ea1f0fb2928255c6b3a4bee016d53a8deaa738 100644 |
| --- a/chrome/browser/resources/chromeos/chromevox/braille/pan_strategy.js |
| +++ b/chrome/browser/resources/chromeos/chromevox/braille/pan_strategy.js |
| @@ -19,24 +19,32 @@ cvox.PanStrategy = function() { |
| * @type {number} |
| * @private |
| */ |
| - this.displaySize_ = 0; |
| + this.rowCount_ = 0; |
| /** |
| * @type {number} |
| * @private |
| */ |
| - this.contentLength_ = 0; |
| - /** |
| - * Points before which it is desirable to break content if it doesn't fit |
| - * on the display. |
| - * @type {!Array<number>} |
| - * @private |
| - */ |
| - this.breakPoints_ = []; |
| + this.columnCount_ = 0; |
| /** |
| + * Start and end are both inclusive. |
| * @type {!cvox.PanStrategy.Range} |
| * @private |
| */ |
| this.viewPort_ = {start: 0, end: 0}; |
| + |
| + this.wrappedBuffer_ = new ArrayBuffer(0); |
| + |
| + this.fixedBuffer_ = new ArrayBuffer(0); |
| + |
| + this.wrappedBrailleToText_ = []; |
| + |
| + this.fixedBrailleToText_ = []; |
| + |
| + this.panStrategyWrapped_ = false; |
| + |
| + this.fixedLineCount_ = 0; |
| + |
| + this.wrappedLineCount_ = 0; |
|
David Tseng
2016/11/14 21:05:08
All of the members here need JS doc. Use the other
ultimatedbz
2016/11/15 00:01:17
Thanks! I actually wasn't sure how to type check.
|
| }; |
| /** |
| @@ -58,26 +66,157 @@ cvox.PanStrategy.prototype = { |
| }, |
| /** |
| + * @return {Array<number>} The offset of braille and text indices of the |
| + * 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. |
| + */ |
| + 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_; |
| + buf = buf.slice(this.viewPort.start * this.columnCount_, |
| + (this.viewPort.end + 1) * this.columnCount_); |
| + return buf; |
| + }, |
| + |
| + /** |
| + * @return {string} String of the slice of text letters corresponding with |
| + * the current braille slice. |
| + */ |
| + getCurrentTextSlice: function() { |
| + var brailleToText = this.brailleToText; |
| + // Index of last braille character in slice. |
| + var index = (this.viewPort.end + 1) * this.columnCount_ - 1; |
| + // Last text character that is in slice. |
| + var end = brailleToText[index]; |
| + // Increment index until brailleToText[index] points to a different char. |
| + while (index < brailleToText.length && brailleToText[index] == end) { |
| + index++; |
| + } |
| + return this.textBuffer.substring( |
| + 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); |
| + setDisplaySize: function(rowCount, columnCount) { |
| + this.rowCount_ = rowCount; |
| + this.columnCount_ = columnCount; |
| +// this.setContent(this.textBuffer, this.fixedBuffer_, |
| +// this.fixedBrailleToText_); |
| +// TODO do I need to set the content again? |
| }, |
| /** |
| - * 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; |
| + this.fixedBuffer_ = translatedContent; |
| + |
| + // Convert the cells to Unicode braille pattern characters. |
| + var view = new Uint8Array(translatedContent); |
| + var wrappedBrailleArray = new Uint8Array(translatedContent.byteLength * 4); |
|
dmazzoni
2016/11/14 21:37:37
Since Uint8Array can't be resized, it might make m
ultimatedbz
2016/11/15 18:04:02
I was thinking if I had to expand the Uint8array,
|
| + //TODO increase size if needed. |
| + |
| + 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. |
| + while (index - cellsPadded < view.length && |
| + view[index - cellsPadded] == 0) { |
| + cellsPadded--; |
| + } |
| + 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; |
| + this.wrappedBrailleToText_[j] = this.wrappedBrailleToText_[j - 1]; |
| + cellsPadded++; |
| + } |
| + lastBreak = index; |
| + index--; |
| + } else { |
| + wrappedBrailleArray[index] = view[index - cellsPadded]; |
| + this.wrappedBrailleToText_.push( |
| + fixedBrailleToText[index - cellsPadded]); |
| + } |
| + } else { |
| + if (view[index - cellsPadded] == 0) { |
| + lastBreak = index; |
| + } |
| + wrappedBrailleArray[index] = view[index - cellsPadded]; |
| + this.wrappedBrailleToText_.push( |
| + fixedBrailleToText[index - cellsPadded]); |
| + } |
| + } |
| + |
| + // Convert the wrapped Braille Uint8 Array back to ArrayBuffer. |
| + this.wrappedBuffer_ = new ArrayBuffer(wrappedBrailleArray.length); |
| + new Uint8Array(this.wrappedBuffer_).set(wrappedBrailleArray); |
| + this.wrappedBuffer_ = this.wrappedBuffer_.slice(0, index); |
| + |
| + // Calculate how many lines are in the fixed and wrapped buffers. |
| + this.fixedLineCount_ = this.fixedBuffer_.byteLength / this.columnCount_; |
|
dmazzoni
2016/11/14 21:37:37
How about Math.ceil(byteLength / columnCount)?
ultimatedbz
2016/11/15 18:04:02
Oh! I forgot about Math.ceil(), thanks!
|
| + if (this.fixedBuffer_.byteLength % this.columnCount_ > 0) |
| + this.fixedLineCount_++; |
| + this.wrappedLineCount_ = |
|
dmazzoni
2016/11/14 21:37:37
same
ultimatedbz
2016/11/15 18:04:02
Done.
|
| + this.wrappedBuffer_.byteLength / this.columnCount_; |
| + if (this.wrappedBuffer_.byteLength % this.columnCount_ > 0) |
| + this.wrappedLineCount_++; |
| }, |
| /** |
| @@ -86,12 +225,14 @@ cvox.PanStrategy.prototype = { |
| * @return {boolean} {@code true} if the viewport was changed. |
| */ |
| next: function() { |
| + var contentLength = this.panStrategyWrapped_ ? |
| + this.wrappedLineCount_ : this.fixedLineCount_; |
| 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 +247,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 +267,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 |
| * 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) { |
| + /* |
| if (this.displaySize_ > 0) { |
| this.viewPort_ = {start: 0, end: 0}; |
| while (this.next() && this.viewPort_.end <= position) { |
| @@ -179,42 +282,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; |
|
David Tseng
2016/11/14 21:05:08
Please don't remove these classes.
A much better
ultimatedbz
2016/11/15 00:01:17
I was thinking that if we got multiline to work, i
|
| -/** |
| - * 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; |
| + */ |
| }, |
| }; |