| OLD | NEW |
| 1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 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 /** @fileoverview Logic for panning a braille display within a line of braille | 5 /** @fileoverview Logic for panning a braille display within a line of braille |
| 6 * content that might not fit on a single display. | 6 * content that might not fit on a single display. |
| 7 */ | 7 */ |
| 8 | 8 |
| 9 goog.provide('cvox.PanStrategy'); | 9 goog.provide('cvox.PanStrategy'); |
| 10 | 10 |
| (...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 101 */ | 101 */ |
| 102 get displaySize() { | 102 get displaySize() { |
| 103 return this.displaySize_; | 103 return this.displaySize_; |
| 104 }, | 104 }, |
| 105 | 105 |
| 106 /** | 106 /** |
| 107 * @return {{brailleOffset: number, textOffset: number}} The offset of | 107 * @return {{brailleOffset: number, textOffset: number}} The offset of |
| 108 * braille and text indices of the current slice. | 108 * braille and text indices of the current slice. |
| 109 */ | 109 */ |
| 110 get offsetsForSlices() { | 110 get offsetsForSlices() { |
| 111 return {brailleOffset: this.viewPort_.firstRow * this.displaySize_.columns, | 111 return { |
| 112 textOffset: this.brailleToText[this.viewPort_.firstRow * | 112 brailleOffset: this.viewPort_.firstRow * this.displaySize_.columns, |
| 113 this.displaySize_.columns]}; | 113 textOffset: this.brailleToText |
| 114 [this.viewPort_.firstRow * this.displaySize_.columns] |
| 115 }; |
| 114 }, | 116 }, |
| 115 | 117 |
| 116 /** | 118 /** |
| 117 * @return {number} The number of lines in the fixedBuffer. | 119 * @return {number} The number of lines in the fixedBuffer. |
| 118 */ | 120 */ |
| 119 get fixedLineCount() { | 121 get fixedLineCount() { |
| 120 return Math.ceil(this.fixedBuffer_.byteLength / this.displaySize_.columns); | 122 return Math.ceil(this.fixedBuffer_.byteLength / this.displaySize_.columns); |
| 121 }, | 123 }, |
| 122 | 124 |
| 123 /** | 125 /** |
| 124 * @return {number} The number of lines in the wrappedBuffer. | 126 * @return {number} The number of lines in the wrappedBuffer. |
| 125 */ | 127 */ |
| 126 get wrappedLineCount() { | 128 get wrappedLineCount() { |
| 127 return Math.ceil(this.wrappedBuffer_.byteLength / | 129 return Math.ceil( |
| 128 this.displaySize_.columns); | 130 this.wrappedBuffer_.byteLength / this.displaySize_.columns); |
| 129 }, | 131 }, |
| 130 | 132 |
| 131 /** | 133 /** |
| 132 * @return {Array<number>} The map of Braille cells to the first index of the | 134 * @return {Array<number>} The map of Braille cells to the first index of the |
| 133 * corresponding text character. | 135 * corresponding text character. |
| 134 */ | 136 */ |
| 135 get brailleToText() { | 137 get brailleToText() { |
| 136 if (this.panStrategyWrapped_) | 138 if (this.panStrategyWrapped_) |
| 137 return this.wrappedBrailleToText_; | 139 return this.wrappedBrailleToText_; |
| 138 else | 140 else |
| 139 return this.fixedBrailleToText_; | 141 return this.fixedBrailleToText_; |
| 140 }, | 142 }, |
| 141 | 143 |
| 142 /** | 144 /** |
| 143 * @return {ArrayBuffer} Buffer of the slice of braille cells within the | 145 * @return {ArrayBuffer} Buffer of the slice of braille cells within the |
| 144 * bounds of the viewport. | 146 * bounds of the viewport. |
| 145 */ | 147 */ |
| 146 getCurrentBrailleViewportContents: function() { | 148 getCurrentBrailleViewportContents: function() { |
| 147 var buf = this.panStrategyWrapped_ ? | 149 var buf = |
| 148 this.wrappedBuffer_ : this.fixedBuffer_; | 150 this.panStrategyWrapped_ ? this.wrappedBuffer_ : this.fixedBuffer_; |
| 149 return buf.slice(this.viewPort_.firstRow * this.displaySize_.columns, | 151 return buf.slice( |
| 152 this.viewPort_.firstRow * this.displaySize_.columns, |
| 150 (this.viewPort_.lastRow + 1) * this.displaySize_.columns); | 153 (this.viewPort_.lastRow + 1) * this.displaySize_.columns); |
| 151 }, | 154 }, |
| 152 | 155 |
| 153 /** | 156 /** |
| 154 * @return {string} String of the slice of text letters corresponding with | 157 * @return {string} String of the slice of text letters corresponding with |
| 155 * the current braille slice. | 158 * the current braille slice. |
| 156 */ | 159 */ |
| 157 getCurrentTextViewportContents: function() { | 160 getCurrentTextViewportContents: function() { |
| 158 var brailleToText = this.brailleToText; | 161 var brailleToText = this.brailleToText; |
| 159 // Index of last braille character in slice. | 162 // Index of last braille character in slice. |
| (...skipping 21 matching lines...) Expand all Loading... |
| 181 | 184 |
| 182 /** | 185 /** |
| 183 * Sets the display size. This call may update the viewport. | 186 * Sets the display size. This call may update the viewport. |
| 184 * @param {number} rowCount the new row size, or {@code 0} if no display is | 187 * @param {number} rowCount the new row size, or {@code 0} if no display is |
| 185 * present. | 188 * present. |
| 186 * @param {number} columnCount the new column size, or {@code 0} | 189 * @param {number} columnCount the new column size, or {@code 0} |
| 187 * if no display is present. | 190 * if no display is present. |
| 188 */ | 191 */ |
| 189 setDisplaySize: function(rowCount, columnCount) { | 192 setDisplaySize: function(rowCount, columnCount) { |
| 190 this.displaySize_ = {rows: rowCount, columns: columnCount}; | 193 this.displaySize_ = {rows: rowCount, columns: columnCount}; |
| 191 this.setContent(this.textBuffer_, this.fixedBuffer_, | 194 this.setContent( |
| 192 this.fixedBrailleToText_, 0); | 195 this.textBuffer_, this.fixedBuffer_, this.fixedBrailleToText_, 0); |
| 193 }, | 196 }, |
| 194 | 197 |
| 195 /** | 198 /** |
| 196 * Sets the internal data structures that hold the fixed and wrapped buffers | 199 * Sets the internal data structures that hold the fixed and wrapped buffers |
| 197 * and maps. | 200 * and maps. |
| 198 * @param {string} textBuffer Text of the shown braille. | 201 * @param {string} textBuffer Text of the shown braille. |
| 199 * @param {!ArrayBuffer} translatedContent The new braille content. | 202 * @param {!ArrayBuffer} translatedContent The new braille content. |
| 200 * @param {Array<number>} fixedBrailleToText Map of Braille cells to the first | 203 * @param {Array<number>} fixedBrailleToText Map of Braille cells to the first |
| 201 * index of corresponding text letter. | 204 * index of corresponding text letter. |
| 202 * @param {number} targetPosition Target position. The viewport is changed | 205 * @param {number} targetPosition Target position. The viewport is changed |
| 203 * to overlap this position. | 206 * to overlap this position. |
| 204 */ | 207 */ |
| 205 setContent: function(textBuffer, translatedContent, fixedBrailleToText, | 208 setContent: function( |
| 206 targetPosition) { | 209 textBuffer, translatedContent, fixedBrailleToText, targetPosition) { |
| 207 this.viewPort_.firstRow = 0; | 210 this.viewPort_.firstRow = 0; |
| 208 this.viewPort_.lastRow = this.displaySize_.rows - 1; | 211 this.viewPort_.lastRow = this.displaySize_.rows - 1; |
| 209 this.fixedBrailleToText_ = fixedBrailleToText; | 212 this.fixedBrailleToText_ = fixedBrailleToText; |
| 210 this.wrappedBrailleToText_ = []; | 213 this.wrappedBrailleToText_ = []; |
| 211 this.textBuffer_ = textBuffer; | 214 this.textBuffer_ = textBuffer; |
| 212 this.fixedBuffer_ = translatedContent; | 215 this.fixedBuffer_ = translatedContent; |
| 213 | 216 |
| 214 // Convert the cells to Unicode braille pattern characters. | 217 // Convert the cells to Unicode braille pattern characters. |
| 215 var view = new Uint8Array(translatedContent); | 218 var view = new Uint8Array(translatedContent); |
| 216 var wrappedBrailleArray = []; | 219 var wrappedBrailleArray = []; |
| 217 | 220 |
| 218 var lastBreak = 0; | 221 var lastBreak = 0; |
| 219 var cellsPadded = 0; | 222 var cellsPadded = 0; |
| 220 var index; | 223 var index; |
| 221 for (index = 0; index < translatedContent.byteLength + cellsPadded; | 224 for (index = 0; index < translatedContent.byteLength + cellsPadded; |
| 222 index++) { | 225 index++) { |
| 223 // Is index at the beginning of a new line? | 226 // Is index at the beginning of a new line? |
| 224 if (index != 0 && index % this.displaySize_.columns == 0) { | 227 if (index != 0 && index % this.displaySize_.columns == 0) { |
| 225 if (view[index - cellsPadded] == 0) { | 228 if (view[index - cellsPadded] == 0) { |
| 226 // Delete all empty cells at the beginning of this line. | 229 // Delete all empty cells at the beginning of this line. |
| 227 while (index - cellsPadded < view.length && | 230 while (index - cellsPadded < view.length && |
| 228 view[index - cellsPadded] == 0) { | 231 view[index - cellsPadded] == 0) { |
| 229 cellsPadded--; | 232 cellsPadded--; |
| 230 } | 233 } |
| 231 index--; | 234 index--; |
| 232 lastBreak = index; | 235 lastBreak = index; |
| 233 } else if (view[index - cellsPadded - 1] != 0 && | 236 } else if ( |
| 237 view[index - cellsPadded - 1] != 0 && |
| 234 lastBreak % this.displaySize_.columns != 0) { | 238 lastBreak % this.displaySize_.columns != 0) { |
| 235 // If first cell is not empty, we need to move the whole word down to | 239 // If first cell is not empty, we need to move the whole word down to |
| 236 // this line and padd to previous line with 0's, from |lastBreak| to | 240 // this line and padd to previous line with 0's, from |lastBreak| to |
| 237 // index. The braille to text map is also updated. | 241 // index. The braille to text map is also updated. |
| 238 // If lastBreak is at the beginning of a line, that means the current | 242 // If lastBreak is at the beginning of a line, that means the current |
| 239 // word is bigger than |this.displaySize_.columns| so we shouldn't | 243 // word is bigger than |this.displaySize_.columns| so we shouldn't |
| 240 // wrap. | 244 // wrap. |
| 241 for (var j = lastBreak + 1; j < index; j++) { | 245 for (var j = lastBreak + 1; j < index; j++) { |
| 242 wrappedBrailleArray[j] = 0; | 246 wrappedBrailleArray[j] = 0; |
| 243 this.wrappedBrailleToText_[j] = this.wrappedBrailleToText_[j - 1]; | 247 this.wrappedBrailleToText_[j] = this.wrappedBrailleToText_[j - 1]; |
| (...skipping 24 matching lines...) Expand all Loading... |
| 268 new Uint8Array(this.wrappedBuffer_).set(wrappedBrailleUint8Array); | 272 new Uint8Array(this.wrappedBuffer_).set(wrappedBrailleUint8Array); |
| 269 this.panToPosition_(targetPosition); | 273 this.panToPosition_(targetPosition); |
| 270 }, | 274 }, |
| 271 | 275 |
| 272 /** | 276 /** |
| 273 * If possible, changes the viewport to a part of the line that follows | 277 * If possible, changes the viewport to a part of the line that follows |
| 274 * the current viewport. | 278 * the current viewport. |
| 275 * @return {boolean} {@code true} if the viewport was changed. | 279 * @return {boolean} {@code true} if the viewport was changed. |
| 276 */ | 280 */ |
| 277 next: function() { | 281 next: function() { |
| 278 var contentLength = this.panStrategyWrapped_ ? | 282 var contentLength = |
| 279 this.wrappedLineCount : this.fixedLineCount; | 283 this.panStrategyWrapped_ ? this.wrappedLineCount : this.fixedLineCount; |
| 280 var newStart = this.viewPort_.lastRow + 1; | 284 var newStart = this.viewPort_.lastRow + 1; |
| 281 var newEnd; | 285 var newEnd; |
| 282 if (newStart + this.displaySize_.rows - 1 < contentLength) { | 286 if (newStart + this.displaySize_.rows - 1 < contentLength) { |
| 283 newEnd = newStart + this.displaySize_.rows - 1; | 287 newEnd = newStart + this.displaySize_.rows - 1; |
| 284 } else { | 288 } else { |
| 285 newEnd = contentLength - 1; | 289 newEnd = contentLength - 1; |
| 286 } | 290 } |
| 287 if (newEnd >= newStart) { | 291 if (newEnd >= newStart) { |
| 288 this.viewPort_ = {firstRow: newStart, lastRow: newEnd}; | 292 this.viewPort_ = {firstRow: newStart, lastRow: newEnd}; |
| 289 return true; | 293 return true; |
| 290 } | 294 } |
| 291 return false; | 295 return false; |
| 292 }, | 296 }, |
| 293 | 297 |
| 294 /** | 298 /** |
| 295 * If possible, changes the viewport to a part of the line that precedes | 299 * If possible, changes the viewport to a part of the line that precedes |
| 296 * the current viewport. | 300 * the current viewport. |
| 297 * @return {boolean} {@code true} if the viewport was changed. | 301 * @return {boolean} {@code true} if the viewport was changed. |
| 298 */ | 302 */ |
| 299 previous: function() { | 303 previous: function() { |
| 300 var contentLength = this.panStrategyWrapped_ ? | 304 var contentLength = |
| 301 this.wrappedLineCount : this.fixedLineCount; | 305 this.panStrategyWrapped_ ? this.wrappedLineCount : this.fixedLineCount; |
| 302 if (this.viewPort_.firstRow > 0) { | 306 if (this.viewPort_.firstRow > 0) { |
| 303 var newStart, newEnd; | 307 var newStart, newEnd; |
| 304 if (this.viewPort_.firstRow < this.displaySize_.rows) { | 308 if (this.viewPort_.firstRow < this.displaySize_.rows) { |
| 305 newStart = 0; | 309 newStart = 0; |
| 306 newEnd = Math.min(this.displaySize_.rows, contentLength); | 310 newEnd = Math.min(this.displaySize_.rows, contentLength); |
| 307 } else { | 311 } else { |
| 308 newEnd = this.viewPort_.firstRow - 1; | 312 newEnd = this.viewPort_.firstRow - 1; |
| 309 newStart = newEnd - this.displaySize_.rows + 1; | 313 newStart = newEnd - this.displaySize_.rows + 1; |
| 310 } | 314 } |
| 311 if (newStart <= newEnd) { | 315 if (newStart <= newEnd) { |
| 312 this.viewPort_ = {firstRow: newStart, lastRow: newEnd}; | 316 this.viewPort_ = {firstRow: newStart, lastRow: newEnd}; |
| 313 return true; | 317 return true; |
| 314 } | 318 } |
| 315 } | 319 } |
| 316 return false; | 320 return false; |
| 317 }, | 321 }, |
| 318 | 322 |
| 319 /** | 323 /** |
| 320 * Moves the viewport so that it overlaps a target position without taking | 324 * Moves the viewport so that it overlaps a target position without taking |
| 321 * the current viewport position into consideration. | 325 * the current viewport position into consideration. |
| 322 * @param {number} position Target position. | 326 * @param {number} position Target position. |
| 323 */ | 327 */ |
| 324 panToPosition_: function(position) { | 328 panToPosition_: function(position) { |
| 325 if (this.displaySize_.rows * this.displaySize_.columns > 0) { | 329 if (this.displaySize_.rows * this.displaySize_.columns > 0) { |
| 326 this.viewPort_ = {firstRow: -1, lastRow: -1}; | 330 this.viewPort_ = {firstRow: -1, lastRow: -1}; |
| 327 while (this.next() && (this.viewPort_.lastRow + 1) * | 331 while (this.next() && |
| 328 this.displaySize_.columns <= position) { | 332 (this.viewPort_.lastRow + 1) * this.displaySize_.columns <= |
| 333 position) { |
| 329 // Nothing to do. | 334 // Nothing to do. |
| 330 } | 335 } |
| 331 } else { | 336 } else { |
| 332 this.viewPort_ = {firstRow: position, lastRow: position}; | 337 this.viewPort_ = {firstRow: position, lastRow: position}; |
| 333 } | 338 } |
| 334 }, | 339 }, |
| 335 }; | 340 }; |
| OLD | NEW |