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 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 46 this.translatedContent_ = new ArrayBuffer(0); | 46 this.translatedContent_ = new ArrayBuffer(0); |
| 47 /** | 47 /** |
| 48 * @type {!ArrayBuffer} | 48 * @type {!ArrayBuffer} |
| 49 * @private | 49 * @private |
| 50 */ | 50 */ |
| 51 this.displayedContent_ = this.translatedContent_; | 51 this.displayedContent_ = this.translatedContent_; |
| 52 /** | 52 /** |
| 53 * @type {cvox.PanStrategy} | 53 * @type {cvox.PanStrategy} |
| 54 * @private | 54 * @private |
| 55 */ | 55 */ |
| 56 this.panStrategy_ = new cvox.WrappingPanStrategy(); | 56 this.panStrategy_ = new cvox.PanStrategy(); |
| 57 /** | 57 /** |
| 58 * @type {function(!cvox.BrailleKeyEvent, !cvox.NavBraille)} | 58 * @type {function(!cvox.BrailleKeyEvent, !cvox.NavBraille)} |
| 59 * @private | 59 * @private |
| 60 */ | 60 */ |
| 61 this.commandListener_ = function() {}; | 61 this.commandListener_ = function() {}; |
| 62 /** | 62 /** |
| 63 * Current display state used for width calculations. This is different from | 63 * Current display state used for width calculations. This is different from |
| 64 * realDisplayState_ if the braille captions feature is enabled and there is | 64 * realDisplayState_ if the braille captions feature is enabled and there is |
| 65 * no hardware display connected. Otherwise, it is the same object | 65 * no hardware display connected. Otherwise, it is the same object |
| 66 * as realDisplayState_. | 66 * as realDisplayState_. |
| 67 * @type {!cvox.BrailleDisplayState} | 67 * @type {!cvox.BrailleDisplayState} |
| 68 * @private | 68 * @private |
| 69 */ | 69 */ |
| 70 this.displayState_ = {available: false, textRowCount: undefined, | 70 this.displayState_ = {available: false, textRowCount: undefined, |
| 71 textColumnCount: undefined}; | 71 textColumnCount: undefined}; |
| 72 /** | 72 /** |
| 73 * State reported from the chrome api, reflecting a real hardware | 73 * State reported from the chrome api, reflecting a real hardware |
| 74 * display. | 74 * display. |
| 75 * @type {!cvox.BrailleDisplayState} | 75 * @type {!cvox.BrailleDisplayState} |
| 76 * @private | 76 * @private |
| 77 */ | 77 */ |
| 78 this.realDisplayState_ = this.displayState_; | 78 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 | 79 |
| 90 translatorManager.addChangeListener(function() { | 80 translatorManager.addChangeListener(function() { |
| 91 this.translateContent_(this.content_, this.expansionType_); | 81 this.translateContent_(this.content_, this.expansionType_); |
| 92 }.bind(this)); | 82 }.bind(this)); |
| 93 | 83 |
| 94 chrome.storage.onChanged.addListener(function(changes, area) { | 84 chrome.storage.onChanged.addListener(function(changes, area) { |
| 95 if (area == 'local' && 'brailleWordWrap' in changes) { | 85 if (area == 'local' && 'brailleWordWrap' in changes) { |
| 96 this.updatePanStrategy_(changes.brailleWordWrap.newValue); | 86 this.updatePanStrategy_(changes.brailleWordWrap.newValue); |
| 97 } | 87 } |
| 98 }.bind(this)); | 88 }.bind(this)); |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 151 }; | 141 }; |
| 152 | 142 |
| 153 | 143 |
| 154 /** | 144 /** |
| 155 * @param {!cvox.BrailleDisplayState} newState Display state reported | 145 * @param {!cvox.BrailleDisplayState} newState Display state reported |
| 156 * by the extension API. | 146 * by the extension API. |
| 157 * @private | 147 * @private |
| 158 */ | 148 */ |
| 159 cvox.BrailleDisplayManager.prototype.refreshDisplayState_ = function( | 149 cvox.BrailleDisplayManager.prototype.refreshDisplayState_ = function( |
| 160 newState) { | 150 newState) { |
| 161 var oldSize = this.displayState_.textColumnCount * | 151 var oldColumnCount = this.displayState_.textColumnCount || 0; |
| 162 this.displayState_.textRowCount || 0; | 152 var oldRowCount = this.displayState_.textRowCount || 0; |
| 163 this.realDisplayState_ = newState; | 153 this.realDisplayState_ = newState; |
| 164 if (newState.available) { | 154 if (newState.available) { |
| 165 this.displayState_ = newState; | 155 this.displayState_ = newState; |
| 156 // Update the dimensions of the virtual braille captions display those | |
| 157 // of a real physical display when one is plugged in. | |
| 158 localStorage['virtualBrailleRows'] = newState.textRowCount; | |
| 159 localStorage['virtualBrailleColumns'] = newState.textColumnCount; | |
| 166 } else { | 160 } else { |
| 167 this.displayState_ = | 161 this.displayState_ = |
| 168 cvox.BrailleCaptionsBackground.getVirtualDisplayState(); | 162 cvox.BrailleCaptionsBackground.getVirtualDisplayState(); |
| 169 } | 163 } |
| 170 var newSize = this.displayState_.textColumnCount * | 164 var newColumnCount = this.displayState_.textColumnCount || 0; |
| 171 this.displayState_.textRowCount || 0; | 165 var newRowCount = this.displayState_.textRowCount || 0; |
| 172 if (oldSize != newSize) { | 166 if (oldColumnCount != newColumnCount || oldRowCount != newRowCount) { |
| 173 this.panStrategy_.setDisplaySize(newSize); | 167 this.panStrategy_.setDisplaySize(newRowCount, newColumnCount); |
|
David Tseng
2016/11/15 17:54:59
Make the display size a pair i.e.
@type {{rows: nu
ultimatedbz
2016/11/19 03:11:58
Done. The parameters are still the same, but the i
| |
| 174 } | 168 } |
| 175 this.refresh_(); | 169 this.refresh_(); |
| 176 }; | 170 }; |
| 177 | 171 |
| 178 | 172 |
| 179 /** | 173 /** |
| 180 * Called when the state of braille captions changes. | 174 * Called when the state of braille captions changes. |
| 181 * @private | 175 * @private |
| 182 */ | 176 */ |
| 183 cvox.BrailleDisplayManager.prototype.onCaptionsStateChanged_ = function() { | 177 cvox.BrailleDisplayManager.prototype.onCaptionsStateChanged_ = function() { |
| 184 // Force reevaluation of the display state based on our stored real | 178 // Force reevaluation of the display state based on our stored real |
| 185 // hardware display state, meaning that if a real display is connected, | 179 // hardware display state, meaning that if a real display is connected, |
| 186 // that takes precedence over the state from the captions 'virtual' display. | 180 // that takes precedence over the state from the captions 'virtual' display. |
| 187 this.refreshDisplayState_(this.realDisplayState_); | 181 this.refreshDisplayState_(this.realDisplayState_); |
| 188 }; | 182 }; |
| 189 | 183 |
| 190 | 184 |
| 191 /** @private */ | 185 /** |
| 186 * Refreshes what is shown on the physical braille display and the virtual | |
| 187 * braille captions display. | |
| 188 * @private */ | |
| 192 cvox.BrailleDisplayManager.prototype.refresh_ = function() { | 189 cvox.BrailleDisplayManager.prototype.refresh_ = function() { |
| 193 if (!this.displayState_.available) { | 190 if (!this.displayState_.available) { |
| 194 return; | 191 return; |
| 195 } | 192 } |
| 196 var viewPort = this.panStrategy_.viewPort; | 193 var brailleBuf = this.panStrategy_.getCurrentBrailleSlice(); |
|
David Tseng
2016/11/15 17:54:59
Slice seems wrong in terms of multiline; maybe cal
ultimatedbz
2016/11/19 03:11:58
Done.
| |
| 197 var buf = this.displayedContent_.slice(viewPort.start, viewPort.end); | 194 var textBuf = this.panStrategy_.getCurrentTextSlice(); |
| 198 if (this.realDisplayState_.available) { | 195 if (this.realDisplayState_.available) { |
| 199 chrome.brailleDisplayPrivate.writeDots(buf, buf.byteLength, 1); | 196 chrome.brailleDisplayPrivate.writeDots(brailleBuf, |
| 197 brailleBuf.byteLength, 1); | |
| 200 } | 198 } |
| 201 if (cvox.BrailleCaptionsBackground.isEnabled()) { | 199 if (cvox.BrailleCaptionsBackground.isEnabled()) { |
| 202 var start = this.brailleToTextPosition_(viewPort.start); | 200 cvox.BrailleCaptionsBackground.setContent(textBuf, brailleBuf, |
| 203 var end = this.brailleToTextPosition_(viewPort.end); | 201 this.panStrategy_.brailleToText, this.panStrategy_.offsetsForSlices); |
| 204 cvox.BrailleCaptionsBackground.setContent( | |
| 205 this.content_.text.toString().substring(start, end), buf, | |
| 206 this.brailleToText_); | |
| 207 } | 202 } |
| 208 }; | 203 }; |
| 209 | 204 |
| 210 | |
| 211 /** | 205 /** |
| 212 * @param {!cvox.NavBraille} newContent New display content. | 206 * @param {!cvox.NavBraille} newContent New display content. |
| 213 * @param {cvox.ExpandingBrailleTranslator.ExpansionType} newExpansionType | 207 * @param {cvox.ExpandingBrailleTranslator.ExpansionType} newExpansionType |
| 214 * How the value part of of the new content should be expanded | 208 * How the value part of of the new content should be expanded |
| 215 * with regards to contractions. | 209 * with regards to contractions. |
| 216 * @private | 210 * @private |
| 217 */ | 211 */ |
| 218 cvox.BrailleDisplayManager.prototype.translateContent_ = function( | 212 cvox.BrailleDisplayManager.prototype.translateContent_ = function( |
| 219 newContent, newExpansionType) { | 213 newContent, newExpansionType) { |
| 220 var writeTranslatedContent = function(cells, textToBraille, brailleToText) { | 214 var writeTranslatedContent = function(cells, textToBraille, brailleToText) { |
| 221 this.content_ = newContent; | 215 this.content_ = newContent; |
| 222 this.expansionType_ = newExpansionType; | 216 this.expansionType_ = newExpansionType; |
| 223 this.textToBraille_ = textToBraille; | |
| 224 this.brailleToText_ = brailleToText; | |
| 225 var startIndex = this.content_.startIndex; | 217 var startIndex = this.content_.startIndex; |
| 226 var endIndex = this.content_.endIndex; | 218 var endIndex = this.content_.endIndex; |
| 227 var targetPosition; | 219 var targetPosition; |
| 228 if (startIndex >= 0) { | 220 if (startIndex >= 0) { |
| 229 var translatedStartIndex; | 221 var translatedStartIndex; |
| 230 var translatedEndIndex; | 222 var translatedEndIndex; |
| 231 if (startIndex >= textToBraille.length) { | 223 if (startIndex >= textToBraille.length) { |
| 232 // Allow the cells to be extended with one extra cell for | 224 // Allow the cells to be extended with one extra cell for |
| 233 // a carret after the last character. | 225 // a carret after the last character. |
| 234 var extCells = new ArrayBuffer(cells.byteLength + 1); | 226 var extCells = new ArrayBuffer(cells.byteLength + 1); |
| 235 new Uint8Array(extCells).set(new Uint8Array(cells)); | 227 new Uint8Array(extCells).set(cells); |
| 236 // Last byte is initialized to 0. | 228 // Last byte is initialized to 0. |
| 237 cells = extCells; | 229 cells = extCells; |
| 238 translatedStartIndex = cells.byteLength - 1; | 230 translatedStartIndex = cells.byteLength - 1; |
| 239 } else { | 231 } else { |
| 240 translatedStartIndex = textToBraille[startIndex]; | 232 translatedStartIndex = textToBraille[startIndex]; |
| 241 } | 233 } |
| 242 if (endIndex >= textToBraille.length) { | 234 if (endIndex >= textToBraille.length) { |
| 243 // endIndex can't be past-the-end of the last cell unless | 235 // endIndex can't be past-the-end of the last cell unless |
| 244 // startIndex is too, so we don't have to do another | 236 // startIndex is too, so we don't have to do another |
| 245 // extension here. | 237 // extension here. |
| 246 translatedEndIndex = cells.byteLength; | 238 translatedEndIndex = cells.byteLength; |
| 247 } else { | 239 } else { |
| 248 translatedEndIndex = textToBraille[endIndex]; | 240 translatedEndIndex = textToBraille[endIndex]; |
| 249 } | 241 } |
| 250 this.translatedContent_ = cells; | 242 this.translatedContent_ = cells; |
| 251 // Copy the translated content to a separate buffer and add the cursor | 243 // Copy the translated content to a separate buffer and add the cursor |
| 252 // to it. | 244 // to it. |
| 253 this.displayedContent_ = new ArrayBuffer(cells.byteLength); | 245 this.displayedContent_ = new ArrayBuffer(cells.byteLength); |
| 254 new Uint8Array(this.displayedContent_).set(new Uint8Array(cells)); | 246 new Uint8Array(this.displayedContent_).set(cells); |
| 255 this.writeCursor_(this.displayedContent_, | 247 this.writeCursor_(this.displayedContent_, |
| 256 translatedStartIndex, translatedEndIndex); | 248 translatedStartIndex, translatedEndIndex); |
| 257 targetPosition = translatedStartIndex; | 249 targetPosition = translatedStartIndex; |
| 258 } else { | 250 } else { |
| 259 this.translatedContent_ = this.displayedContent_ = cells; | 251 this.translatedContent_ = this.displayedContent_ = cells; |
| 260 targetPosition = 0; | 252 targetPosition = 0; |
| 261 } | 253 } |
| 262 this.panStrategy_.setContent(this.translatedContent_, targetPosition); | 254 this.panStrategy_.setContent(this.content_.text.toString(), |
| 255 this.translatedContent_, brailleToText); | |
| 256 | |
| 263 this.refresh_(); | 257 this.refresh_(); |
| 264 }.bind(this); | 258 }.bind(this); |
| 265 | 259 |
| 266 var translator = this.translatorManager_.getExpandingTranslator(); | 260 var translator = this.translatorManager_.getExpandingTranslator(); |
| 267 if (!translator) { | 261 if (!translator) { |
| 268 writeTranslatedContent(new ArrayBuffer(0), [], []); | 262 writeTranslatedContent(new ArrayBuffer(0), [], []); |
| 269 } else { | 263 } else { |
| 270 translator.translate( | 264 translator.translate( |
| 271 newContent.text, | 265 newContent.text, |
| 272 newExpansionType, | 266 newExpansionType, |
| 273 writeTranslatedContent); | 267 writeTranslatedContent); |
| 274 } | 268 } |
| 275 }; | 269 }; |
| 276 | 270 |
| 277 | 271 |
| 278 /** | 272 /** |
| 279 * @param {cvox.BrailleKeyEvent} event The key event. | 273 * @param {cvox.BrailleKeyEvent} event The key event. |
| 280 * @private | 274 * @private |
| 281 */ | 275 */ |
| 282 cvox.BrailleDisplayManager.prototype.onKeyEvent_ = function(event) { | 276 cvox.BrailleDisplayManager.prototype.onKeyEvent_ = function(event) { |
| 283 switch (event.command) { | 277 switch (event.command) { |
| 284 case cvox.BrailleKeyCommand.PAN_LEFT: | 278 case cvox.BrailleKeyCommand.PAN_LEFT: |
| 285 this.panLeft_(); | 279 this.panLeft_(); |
| 286 break; | 280 break; |
| 287 case cvox.BrailleKeyCommand.PAN_RIGHT: | 281 case cvox.BrailleKeyCommand.PAN_RIGHT: |
| 288 this.panRight_(); | 282 this.panRight_(); |
| 289 break; | 283 break; |
| 290 case cvox.BrailleKeyCommand.ROUTING: | 284 case cvox.BrailleKeyCommand.ROUTING: |
| 285 /* TODO | |
|
David Tseng
2016/11/15 17:54:59
The goal is to get this cl checked in, so please r
ultimatedbz
2016/11/15 19:31:57
I do intend to complete this block, but for the ti
David Tseng
2016/11/15 21:36:38
I would not accept this cl without this working as
ultimatedbz
2016/11/15 21:58:09
I think you are assuming that I want to commit the
ultimatedbz
2016/11/19 03:11:58
As per our offline conversation, I will leave the
ultimatedbz
2016/11/19 03:11:58
I just implemented a solution to your problem. I'm
| |
| 291 event.displayPosition = this.brailleToTextPosition_( | 286 event.displayPosition = this.brailleToTextPosition_( |
| 292 event.displayPosition + this.panStrategy_.viewPort.start); | 287 event.displayPosition + this.panStrategy_.viewPort.start); |
| 293 // fall through | 288 // fall through |
| 289 // */ | |
| 294 default: | 290 default: |
| 295 this.commandListener_(event, this.content_); | 291 this.commandListener_(event, this.content_); |
| 296 break; | 292 break; |
| 297 } | 293 } |
| 298 }; | 294 }; |
| 299 | 295 |
| 300 | 296 |
| 301 /** | 297 /** |
| 302 * Shift the display by one full display size and refresh the content. | 298 * Shift the display by one full display size and refresh the content. |
| 303 * Sends the appropriate command if the display is already at the leftmost | 299 * Sends the appropriate command if the display is already at the leftmost |
| (...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 361 /** | 357 /** |
| 362 * Returns the text position corresponding to an absolute braille position, | 358 * Returns the text position corresponding to an absolute braille position, |
| 363 * that is not accounting for the current pan position. | 359 * that is not accounting for the current pan position. |
| 364 * @private | 360 * @private |
| 365 * @param {number} braillePosition Braille position relative to the startof | 361 * @param {number} braillePosition Braille position relative to the startof |
| 366 * the translated content. | 362 * the translated content. |
| 367 * @return {number} The mapped position in code units. | 363 * @return {number} The mapped position in code units. |
| 368 */ | 364 */ |
| 369 cvox.BrailleDisplayManager.prototype.brailleToTextPosition_ = | 365 cvox.BrailleDisplayManager.prototype.brailleToTextPosition_ = |
| 370 function(braillePosition) { | 366 function(braillePosition) { |
| 371 var mapping = this.brailleToText_; | 367 // TODO I'll need to support this function |
| 368 var mapping = this.panStrategy_.brailleToText; | |
| 372 if (braillePosition < 0) { | 369 if (braillePosition < 0) { |
| 373 // This shouldn't happen. | 370 // This shouldn't happen. |
| 374 console.error('WARNING: Braille position < 0: ' + braillePosition); | 371 console.error('WARNING: Braille position < 0: ' + braillePosition); |
| 375 return 0; | 372 return 0; |
| 376 } else if (braillePosition >= mapping.length) { | 373 } else if (braillePosition >= mapping.length) { |
| 377 // This happens when the user clicks on the right part of the display | 374 // 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 | 375 // when it is not entirely filled with content. Allow addressing the |
| 379 // position after the last character. | 376 // position after the last character. |
| 380 return this.content_.text.length; | 377 return this.content_.text.length; |
| 381 } else { | 378 } else { |
| 382 return mapping[braillePosition]; | 379 return mapping[braillePosition]; |
| 383 } | 380 } |
| 384 }; | 381 }; |
| 385 | 382 |
| 386 | 383 |
| 387 /** | 384 /** |
| 388 * @param {boolean} wordWrap | 385 * @param {boolean} wordWrap |
| 389 * @private | 386 * @private |
| 390 */ | 387 */ |
| 391 cvox.BrailleDisplayManager.prototype.updatePanStrategy_ = function(wordWrap) { | 388 cvox.BrailleDisplayManager.prototype.updatePanStrategy_ = function(wordWrap) { |
| 392 var newStrategy = wordWrap ? new cvox.WrappingPanStrategy() : | 389 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_(); | 390 this.refresh_(); |
| 399 }; | 391 }; |
| OLD | NEW |