Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 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 | 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 /** | 5 /** |
| 6 * @fileoverview Puts text on a braille display. | 6 * @fileoverview Puts text on a braille display. |
| 7 * | 7 * |
| 8 */ | 8 */ |
| 9 | 9 |
| 10 goog.provide('cvox.BrailleDisplayManager'); | 10 goog.provide('cvox.BrailleDisplayManager'); |
| (...skipping 22 matching lines...) Expand all Loading... | |
| 33 * @private | 33 * @private |
| 34 */ | 34 */ |
| 35 this.content_ = new cvox.NavBraille({}); | 35 this.content_ = new cvox.NavBraille({}); |
| 36 /** | 36 /** |
| 37 * @type {!cvox.ExpandingBrailleTranslator.ExpansionType} valueExpansion | 37 * @type {!cvox.ExpandingBrailleTranslator.ExpansionType} valueExpansion |
| 38 * @private | 38 * @private |
| 39 */ | 39 */ |
| 40 this.expansionType_ = | 40 this.expansionType_ = |
| 41 cvox.ExpandingBrailleTranslator.ExpansionType.SELECTION; | 41 cvox.ExpandingBrailleTranslator.ExpansionType.SELECTION; |
| 42 /** | 42 /** |
| 43 * @type {!ArrayBuffer} | |
| 44 * @private | |
| 45 */ | |
| 46 this.translatedContent_ = new ArrayBuffer(0); | |
| 47 /** | |
| 48 * @type {!ArrayBuffer} | |
| 49 * @private | |
| 50 */ | |
| 51 this.displayedContent_ = this.translatedContent_; | |
| 52 /** | |
| 53 * @type {cvox.PanStrategy} | 43 * @type {cvox.PanStrategy} |
| 54 * @private | 44 * @private |
| 55 */ | 45 */ |
| 56 this.panStrategy_ = new cvox.WrappingPanStrategy(); | 46 this.panStrategy_ = new cvox.PanStrategy(); |
| 57 /** | 47 /** |
| 58 * @type {function(!cvox.BrailleKeyEvent, !cvox.NavBraille)} | 48 * @type {function(!cvox.BrailleKeyEvent, !cvox.NavBraille)} |
| 59 * @private | 49 * @private |
| 60 */ | 50 */ |
| 61 this.commandListener_ = function() {}; | 51 this.commandListener_ = function() {}; |
| 62 /** | 52 /** |
| 63 * Current display state used for width calculations. This is different from | 53 * Current display state to show in the Virtual Braille Captions display. |
| 64 * realDisplayState_ if the braille captions feature is enabled and there is | 54 * This is different from realDisplayState_ if the braille captions feature |
| 65 * no hardware display connected. Otherwise, it is the same object | 55 * is enabled and there is no hardware display connected. Otherwise, it is |
| 66 * as realDisplayState_. | 56 * the same object as realDisplayState_. |
| 67 * @type {!cvox.BrailleDisplayState} | 57 * @type {!cvox.BrailleDisplayState} |
| 68 * @private | 58 * @private |
| 69 */ | 59 */ |
| 70 this.displayState_ = {available: false, textRowCount: undefined, | 60 this.displayState_ = {available: false, textRowCount: undefined, |
| 71 textColumnCount: undefined}; | 61 textColumnCount: undefined}; |
| 72 /** | 62 /** |
| 73 * State reported from the chrome api, reflecting a real hardware | 63 * State reported from the chrome api, reflecting a real hardware |
| 74 * display. | 64 * display. |
| 75 * @type {!cvox.BrailleDisplayState} | 65 * @type {!cvox.BrailleDisplayState} |
| 76 * @private | 66 * @private |
| 77 */ | 67 */ |
| 78 this.realDisplayState_ = this.displayState_; | 68 this.realDisplayState_ = this.displayState_; |
| 79 /** | |
| 80 * @type {!Array<number>} | |
| 81 * @private | |
| 82 */ | |
| 83 this.textToBraille_ = []; | |
| 84 /** | |
| 85 * @type {!Array<number>} | |
| 86 * @private | |
| 87 */ | |
| 88 this.brailleToText_ = []; | |
| 89 | 69 |
| 90 translatorManager.addChangeListener(function() { | 70 translatorManager.addChangeListener(function() { |
| 91 this.translateContent_(this.content_, this.expansionType_); | 71 this.translateContent_(this.content_, this.expansionType_); |
| 92 }.bind(this)); | 72 }.bind(this)); |
| 93 | 73 |
| 94 chrome.storage.onChanged.addListener(function(changes, area) { | 74 chrome.storage.onChanged.addListener(function(changes, area) { |
| 95 if (area == 'local' && 'brailleWordWrap' in changes) { | 75 if (area == 'local' && 'brailleWordWrap' in changes) { |
| 96 this.updatePanStrategy_(changes.brailleWordWrap.newValue); | 76 this.updatePanStrategy_(changes.brailleWordWrap.newValue); |
| 97 } | 77 } |
| 98 }.bind(this)); | 78 }.bind(this)); |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 151 }; | 131 }; |
| 152 | 132 |
| 153 | 133 |
| 154 /** | 134 /** |
| 155 * @param {!cvox.BrailleDisplayState} newState Display state reported | 135 * @param {!cvox.BrailleDisplayState} newState Display state reported |
| 156 * by the extension API. | 136 * by the extension API. |
| 157 * @private | 137 * @private |
| 158 */ | 138 */ |
| 159 cvox.BrailleDisplayManager.prototype.refreshDisplayState_ = function( | 139 cvox.BrailleDisplayManager.prototype.refreshDisplayState_ = function( |
| 160 newState) { | 140 newState) { |
| 161 var oldSize = this.displayState_.textColumnCount * | 141 var oldColumnCount = this.displayState_.textColumnCount || 0; |
| 162 this.displayState_.textRowCount || 0; | 142 var oldRowCount = this.displayState_.textRowCount || 0; |
| 163 this.realDisplayState_ = newState; | 143 this.realDisplayState_ = newState; |
| 164 if (newState.available) { | 144 if (newState.available) { |
| 165 this.displayState_ = newState; | 145 this.displayState_ = newState; |
| 146 // Update the dimensions of the virtual braille captions display to those | |
| 147 // of a real physical display when one is plugged in. | |
| 166 } else { | 148 } else { |
| 167 this.displayState_ = | 149 this.displayState_ = |
| 168 cvox.BrailleCaptionsBackground.getVirtualDisplayState(); | 150 cvox.BrailleCaptionsBackground.getVirtualDisplayState(); |
| 169 } | 151 } |
| 170 var newSize = this.displayState_.textColumnCount * | 152 var newColumnCount = this.displayState_.textColumnCount || 0; |
| 171 this.displayState_.textRowCount || 0; | 153 var newRowCount = this.displayState_.textRowCount || 0; |
| 172 if (oldSize != newSize) { | 154 |
| 173 this.panStrategy_.setDisplaySize(newSize); | 155 if (oldColumnCount != newColumnCount || oldRowCount != newRowCount) { |
| 156 this.panStrategy_.setDisplaySize(newRowCount, newColumnCount); | |
| 174 } | 157 } |
| 175 this.refresh_(); | 158 this.refresh_(); |
| 176 }; | 159 }; |
| 177 | 160 |
| 178 | 161 |
| 179 /** | 162 /** |
| 180 * Called when the state of braille captions changes. | 163 * Called when the state of braille captions changes. |
| 181 * @private | 164 * @private |
| 182 */ | 165 */ |
| 183 cvox.BrailleDisplayManager.prototype.onCaptionsStateChanged_ = function() { | 166 cvox.BrailleDisplayManager.prototype.onCaptionsStateChanged_ = function() { |
| 184 // Force reevaluation of the display state based on our stored real | 167 // Force reevaluation of the display state based on our stored real |
| 185 // hardware display state, meaning that if a real display is connected, | 168 // hardware display state, meaning that if a real display is connected, |
| 186 // that takes precedence over the state from the captions 'virtual' display. | 169 // that takes precedence over the state from the captions 'virtual' display. |
| 187 this.refreshDisplayState_(this.realDisplayState_); | 170 this.refreshDisplayState_(this.realDisplayState_); |
| 188 }; | 171 }; |
| 189 | 172 |
| 190 | 173 |
| 191 /** @private */ | 174 /** |
| 175 * Refreshes what is shown on the physical braille display and the virtual | |
| 176 * braille captions display. | |
| 177 * @private */ | |
|
David Tseng
2016/11/30 22:11:54
nit: move */ to a new line
ultimatedbz
2016/12/01 05:12:14
Done.
| |
| 192 cvox.BrailleDisplayManager.prototype.refresh_ = function() { | 178 cvox.BrailleDisplayManager.prototype.refresh_ = function() { |
| 193 if (!this.displayState_.available) { | 179 if (!this.displayState_.available) { |
| 194 return; | 180 return; |
| 195 } | 181 } |
| 196 var viewPort = this.panStrategy_.viewPort; | 182 var brailleBuf = this.panStrategy_.getCurrentBrailleViewportContents(); |
| 197 var buf = this.displayedContent_.slice(viewPort.start, viewPort.end); | 183 var textBuf = this.panStrategy_.getCurrentTextSlice(); |
|
David Tseng
2016/11/30 22:11:54
Maybe make this getCurrentTextViewPortContents
ultimatedbz
2016/12/01 05:12:15
Done.
| |
| 198 if (this.realDisplayState_.available) { | 184 if (this.realDisplayState_.available) { |
| 199 chrome.brailleDisplayPrivate.writeDots(buf, buf.byteLength, 1); | 185 chrome.brailleDisplayPrivate.writeDots(brailleBuf, |
| 186 brailleBuf.byteLength, 1); | |
| 200 } | 187 } |
| 201 if (cvox.BrailleCaptionsBackground.isEnabled()) { | 188 if (cvox.BrailleCaptionsBackground.isEnabled()) { |
| 202 var start = this.brailleToTextPosition_(viewPort.start); | 189 cvox.BrailleCaptionsBackground.setContent(textBuf, brailleBuf, |
| 203 var end = this.brailleToTextPosition_(viewPort.end); | 190 this.panStrategy_.brailleToText, this.panStrategy_.offsetsForSlices, |
| 204 cvox.BrailleCaptionsBackground.setContent( | 191 this.displayState_.textRowCount, this.displayState_.textColumnCount); |
| 205 this.content_.text.toString().substring(start, end), buf, | |
| 206 this.brailleToText_); | |
| 207 } | 192 } |
| 208 }; | 193 }; |
| 209 | 194 |
| 210 | |
| 211 /** | 195 /** |
| 212 * @param {!cvox.NavBraille} newContent New display content. | 196 * @param {!cvox.NavBraille} newContent New display content. |
| 213 * @param {cvox.ExpandingBrailleTranslator.ExpansionType} newExpansionType | 197 * @param {cvox.ExpandingBrailleTranslator.ExpansionType} newExpansionType |
| 214 * How the value part of of the new content should be expanded | 198 * How the value part of of the new content should be expanded |
| 215 * with regards to contractions. | 199 * with regards to contractions. |
| 216 * @private | 200 * @private |
| 217 */ | 201 */ |
| 218 cvox.BrailleDisplayManager.prototype.translateContent_ = function( | 202 cvox.BrailleDisplayManager.prototype.translateContent_ = function( |
| 219 newContent, newExpansionType) { | 203 newContent, newExpansionType) { |
| 220 var writeTranslatedContent = function(cells, textToBraille, brailleToText) { | 204 var writeTranslatedContent = function(cells, textToBraille, brailleToText) { |
| 221 this.content_ = newContent; | 205 this.content_ = newContent; |
| 222 this.expansionType_ = newExpansionType; | 206 this.expansionType_ = newExpansionType; |
| 223 this.textToBraille_ = textToBraille; | |
| 224 this.brailleToText_ = brailleToText; | |
| 225 var startIndex = this.content_.startIndex; | 207 var startIndex = this.content_.startIndex; |
| 226 var endIndex = this.content_.endIndex; | 208 var endIndex = this.content_.endIndex; |
| 227 var targetPosition; | 209 var targetPosition; |
| 228 if (startIndex >= 0) { | 210 if (startIndex >= 0) { |
| 229 var translatedStartIndex; | 211 var translatedStartIndex; |
| 230 var translatedEndIndex; | 212 var translatedEndIndex; |
| 231 if (startIndex >= textToBraille.length) { | 213 if (startIndex >= textToBraille.length) { |
| 232 // Allow the cells to be extended with one extra cell for | 214 // Allow the cells to be extended with one extra cell for |
| 233 // a carret after the last character. | 215 // a carret after the last character. |
| 234 var extCells = new ArrayBuffer(cells.byteLength + 1); | 216 var extCells = new ArrayBuffer(cells.byteLength + 1); |
| 235 new Uint8Array(extCells).set(new Uint8Array(cells)); | 217 new Uint8Array(extCells).set(new Uint8Array(cells)); |
| 236 // Last byte is initialized to 0. | 218 // Last byte is initialized to 0. |
| 237 cells = extCells; | 219 cells = extCells; |
| 238 translatedStartIndex = cells.byteLength - 1; | 220 translatedStartIndex = cells.byteLength - 1; |
| 239 } else { | 221 } else { |
| 240 translatedStartIndex = textToBraille[startIndex]; | 222 translatedStartIndex = textToBraille[startIndex]; |
| 241 } | 223 } |
| 242 if (endIndex >= textToBraille.length) { | 224 if (endIndex >= textToBraille.length) { |
| 243 // endIndex can't be past-the-end of the last cell unless | 225 // endIndex can't be past-the-end of the last cell unless |
| 244 // startIndex is too, so we don't have to do another | 226 // startIndex is too, so we don't have to do another |
| 245 // extension here. | 227 // extension here. |
| 246 translatedEndIndex = cells.byteLength; | 228 translatedEndIndex = cells.byteLength; |
| 247 } else { | 229 } else { |
| 248 translatedEndIndex = textToBraille[endIndex]; | 230 translatedEndIndex = textToBraille[endIndex]; |
| 249 } | 231 } |
| 250 this.translatedContent_ = cells; | 232 // Add the cursor to cells. |
| 251 // Copy the translated content to a separate buffer and add the cursor | 233 this.writeCursor_(cells, translatedStartIndex, translatedEndIndex); |
| 252 // to it. | |
| 253 this.displayedContent_ = new ArrayBuffer(cells.byteLength); | |
| 254 new Uint8Array(this.displayedContent_).set(new Uint8Array(cells)); | |
| 255 this.writeCursor_(this.displayedContent_, | |
| 256 translatedStartIndex, translatedEndIndex); | |
| 257 targetPosition = translatedStartIndex; | 234 targetPosition = translatedStartIndex; |
| 258 } else { | 235 } else { |
| 259 this.translatedContent_ = this.displayedContent_ = cells; | |
| 260 targetPosition = 0; | 236 targetPosition = 0; |
| 261 } | 237 } |
| 262 this.panStrategy_.setContent(this.translatedContent_, targetPosition); | 238 this.panStrategy_.setContent(this.content_.text.toString(), |
| 239 cells, brailleToText, targetPosition); | |
|
David Tseng
2016/11/30 22:11:54
Optional: to help the reviewer and any future read
ultimatedbz
2016/12/01 05:12:15
Acknowledged.
| |
| 240 | |
| 263 this.refresh_(); | 241 this.refresh_(); |
| 264 }.bind(this); | 242 }.bind(this); |
| 265 | 243 |
| 266 var translator = this.translatorManager_.getExpandingTranslator(); | 244 var translator = this.translatorManager_.getExpandingTranslator(); |
| 267 if (!translator) { | 245 if (!translator) { |
| 268 writeTranslatedContent(new ArrayBuffer(0), [], []); | 246 writeTranslatedContent(new ArrayBuffer(0), [], []); |
| 269 } else { | 247 } else { |
| 270 translator.translate( | 248 translator.translate( |
| 271 newContent.text, | 249 newContent.text, |
| 272 newExpansionType, | 250 newExpansionType, |
| 273 writeTranslatedContent); | 251 writeTranslatedContent); |
| 274 } | 252 } |
| 275 }; | 253 }; |
| 276 | 254 |
| 277 | 255 |
| 278 /** | 256 /** |
| 279 * @param {cvox.BrailleKeyEvent} event The key event. | 257 * @param {cvox.BrailleKeyEvent} event The key event. |
| 280 * @private | 258 * @private |
| 281 */ | 259 */ |
| 282 cvox.BrailleDisplayManager.prototype.onKeyEvent_ = function(event) { | 260 cvox.BrailleDisplayManager.prototype.onKeyEvent_ = function(event) { |
| 283 switch (event.command) { | 261 switch (event.command) { |
| 284 case cvox.BrailleKeyCommand.PAN_LEFT: | 262 case cvox.BrailleKeyCommand.PAN_LEFT: |
| 285 this.panLeft_(); | 263 this.panLeft_(); |
| 286 break; | 264 break; |
| 287 case cvox.BrailleKeyCommand.PAN_RIGHT: | 265 case cvox.BrailleKeyCommand.PAN_RIGHT: |
| 288 this.panRight_(); | 266 this.panRight_(); |
| 289 break; | 267 break; |
| 290 case cvox.BrailleKeyCommand.ROUTING: | 268 case cvox.BrailleKeyCommand.ROUTING: |
| 291 event.displayPosition = this.brailleToTextPosition_( | 269 event.displayPosition = this.brailleToTextPosition_( |
| 292 event.displayPosition + this.panStrategy_.viewPort.start); | 270 event.displayPosition + this.panStrategy_.viewPort.firstRow * |
| 271 this.panStrategy_.displaySize.columns); | |
| 293 // fall through | 272 // fall through |
| 294 default: | 273 default: |
| 295 this.commandListener_(event, this.content_); | 274 this.commandListener_(event, this.content_); |
| 296 break; | 275 break; |
| 297 } | 276 } |
| 298 }; | 277 }; |
| 299 | 278 |
| 300 | 279 |
| 301 /** | 280 /** |
| 302 * Shift the display by one full display size and refresh the content. | 281 * Shift the display by one full display size and refresh the content. |
| (...skipping 21 matching lines...) Expand all Loading... | |
| 324 cvox.BrailleDisplayManager.prototype.panRight_ = function() { | 303 cvox.BrailleDisplayManager.prototype.panRight_ = function() { |
| 325 if (this.panStrategy_.next()) { | 304 if (this.panStrategy_.next()) { |
| 326 this.refresh_(); | 305 this.refresh_(); |
| 327 } else { | 306 } else { |
| 328 this.commandListener_({ | 307 this.commandListener_({ |
| 329 command: cvox.BrailleKeyCommand.PAN_RIGHT | 308 command: cvox.BrailleKeyCommand.PAN_RIGHT |
| 330 }, this.content_); | 309 }, this.content_); |
| 331 } | 310 } |
| 332 }; | 311 }; |
| 333 | 312 |
| 334 | |
| 335 /** | 313 /** |
| 336 * Writes a cursor in the specified range into translated content. | 314 * Writes a cursor in the specified range into translated content. |
| 337 * @param {ArrayBuffer} buffer Buffer to add cursor to. | 315 * @param {ArrayBuffer} buffer Buffer to add cursor to. |
| 338 * @param {number} startIndex The start index to place the cursor. | 316 * @param {number} startIndex The start index to place the cursor. |
| 339 * @param {number} endIndex The end index to place the cursor (exclusive). | 317 * @param {number} endIndex The end index to place the cursor (exclusive). |
| 340 * @private | 318 * @private |
| 341 */ | 319 */ |
| 342 cvox.BrailleDisplayManager.prototype.writeCursor_ = function( | 320 cvox.BrailleDisplayManager.prototype.writeCursor_ = function( |
| 343 buffer, startIndex, endIndex) { | 321 buffer, startIndex, endIndex) { |
| 344 if (startIndex < 0 || startIndex >= buffer.byteLength || | 322 if (startIndex < 0 || startIndex >= buffer.byteLength || |
| 345 endIndex < startIndex || endIndex > buffer.byteLength) { | 323 endIndex < startIndex || endIndex > buffer.byteLength) { |
| 346 return; | 324 return; |
| 347 } | 325 } |
| 348 if (startIndex == endIndex) { | 326 if (startIndex == endIndex) { |
| 349 endIndex = startIndex + 1; | 327 endIndex = startIndex + 1; |
| 350 } | 328 } |
| 351 var dataView = new DataView(buffer); | 329 var dataView = new DataView(buffer); |
| 352 while (startIndex < endIndex) { | 330 while (startIndex < endIndex) { |
| 353 var value = dataView.getUint8(startIndex); | 331 var value = dataView.getUint8(startIndex); |
| 354 value |= cvox.BrailleDisplayManager.CURSOR_DOTS_; | 332 value |= cvox.BrailleDisplayManager.CURSOR_DOTS_; |
| 355 dataView.setUint8(startIndex, value); | 333 dataView.setUint8(startIndex, value); |
| 356 startIndex++; | 334 startIndex++; |
| 357 } | 335 } |
| 358 }; | 336 }; |
| 359 | 337 |
| 360 | |
| 361 /** | 338 /** |
| 362 * Returns the text position corresponding to an absolute braille position, | 339 * Returns the text position corresponding to an absolute braille position, |
| 363 * that is not accounting for the current pan position. | 340 * that is not accounting for the current pan position. |
| 364 * @private | 341 * @private |
| 365 * @param {number} braillePosition Braille position relative to the startof | 342 * @param {number} braillePosition Braille position relative to the startof |
| 366 * the translated content. | 343 * the translated content. |
| 367 * @return {number} The mapped position in code units. | 344 * @return {number} The mapped position in code units. |
| 368 */ | 345 */ |
| 369 cvox.BrailleDisplayManager.prototype.brailleToTextPosition_ = | 346 cvox.BrailleDisplayManager.prototype.brailleToTextPosition_ = |
| 370 function(braillePosition) { | 347 function(braillePosition) { |
| 371 var mapping = this.brailleToText_; | 348 var mapping = this.panStrategy_.brailleToText; |
| 372 if (braillePosition < 0) { | 349 if (braillePosition < 0) { |
| 373 // This shouldn't happen. | 350 // This shouldn't happen. |
| 374 console.error('WARNING: Braille position < 0: ' + braillePosition); | |
|
David Tseng
2016/11/30 22:11:54
Doesn't seem like this should be removed.
ultimatedbz
2016/12/01 05:12:15
Thanks for catching this!
| |
| 375 return 0; | 351 return 0; |
| 376 } else if (braillePosition >= mapping.length) { | 352 } else if (braillePosition >= mapping.length) { |
| 377 // This happens when the user clicks on the right part of the display | 353 // This happens when the user clicks on the right part of the display |
| 378 // when it is not entirely filled with content. Allow addressing the | 354 // when it is not entirely filled with content. Allow addressing the |
| 379 // position after the last character. | 355 // position after the last character. |
| 380 return this.content_.text.length; | 356 return this.content_.text.length; |
| 381 } else { | 357 } else { |
| 382 return mapping[braillePosition]; | 358 return mapping[braillePosition]; |
| 383 } | 359 } |
| 384 }; | 360 }; |
| 385 | 361 |
| 386 | |
| 387 /** | 362 /** |
| 388 * @param {boolean} wordWrap | 363 * @param {boolean} wordWrap |
| 389 * @private | 364 * @private |
| 390 */ | 365 */ |
| 391 cvox.BrailleDisplayManager.prototype.updatePanStrategy_ = function(wordWrap) { | 366 cvox.BrailleDisplayManager.prototype.updatePanStrategy_ = function(wordWrap) { |
| 392 var newStrategy = wordWrap ? new cvox.WrappingPanStrategy() : | 367 this.panStrategy_.setPanStrategy(wordWrap); |
| 393 new cvox.FixedPanStrategy(); | |
| 394 newStrategy.setDisplaySize(this.displayState_.textColumnCount || 0); | |
| 395 newStrategy.setContent(this.translatedContent_, | |
| 396 this.panStrategy_.viewPort.start); | |
| 397 this.panStrategy_ = newStrategy; | |
| 398 this.refresh_(); | 368 this.refresh_(); |
| 399 }; | 369 }; |
| OLD | NEW |