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

Side by Side Diff: chrome/browser/resources/chromeos/chromevox/braille/braille_display_manager.js

Issue 2703663002: Display images in multiline Braille (Closed)
Patch Set: Address feedback Created 3 years, 9 months 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 unified diff | Download patch
OLDNEW
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 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
50 */ 50 */
51 this.commandListener_ = function() {}; 51 this.commandListener_ = function() {};
52 /** 52 /**
53 * Current display state to show in the Virtual Braille Captions display. 53 * Current display state to show in the Virtual Braille Captions display.
54 * This is different from realDisplayState_ if the braille captions feature 54 * This is different from realDisplayState_ if the braille captions feature
55 * is enabled and there is no hardware display connected. Otherwise, it is 55 * is enabled and there is no hardware display connected. Otherwise, it is
56 * the same object as realDisplayState_. 56 * the same object as realDisplayState_.
57 * @type {!cvox.BrailleDisplayState} 57 * @type {!cvox.BrailleDisplayState}
58 * @private 58 * @private
59 */ 59 */
60 this.displayState_ = {available: false, textRowCount: undefined, 60 this.displayState_ = {available: false, textRowCount: 0,
61 textColumnCount: undefined}; 61 textColumnCount: 0};
62 /** 62 /**
63 * State reported from the chrome api, reflecting a real hardware 63 * State reported from the chrome api, reflecting a real hardware
64 * display. 64 * display.
65 * @type {!cvox.BrailleDisplayState} 65 * @type {!cvox.BrailleDisplayState}
66 * @private 66 * @private
67 */ 67 */
68 this.realDisplayState_ = this.displayState_; 68 this.realDisplayState_ = this.displayState_;
69 69
70 translatorManager.addChangeListener(function() { 70 translatorManager.addChangeListener(function() {
71 this.translateContent_(this.content_, this.expansionType_); 71 this.translateContent_(this.content_, this.expansionType_);
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
103 103
104 /** 104 /**
105 * Dots representing a cursor. 105 * Dots representing a cursor.
106 * @const 106 * @const
107 * @private 107 * @private
108 */ 108 */
109 cvox.BrailleDisplayManager.CURSOR_DOTS_ = 1 << 6 | 1 << 7; 109 cvox.BrailleDisplayManager.CURSOR_DOTS_ = 1 << 6 | 1 << 7;
110 110
111 111
112 /** 112 /**
113 * Alpha threshold for a pixel to be possibly displayed as a raised dot when
114 * converting an image to braille, where 255 means only fully-opaque
115 * pixels can be raised (if their luminance passes the luminance threshold),
116 * and 0 means that alpha is effectively ignored and only luminance matters.
117 * @const
118 * @private
119 */
120 cvox.BrailleDisplayManager.ALPHA_THRESHOLD_ = 255;
121
122
123 /**
124 * Luminance threshold for a pixel to be displayed as a raised dot when
125 * converting an image to braille, on a scale of 0 (black) to 255 (white).
126 * A pixel whose luminance is less than the given threshold will be raised.
127 * @const
128 * @private
129 */
130 cvox.BrailleDisplayManager.LUMINANCE_THRESHOLD_ = 128;
131
132
133 /**
134 * Array mapping an index in an 8-dot braille cell, in column-first order,
135 * to its corresponding bit mask in the standard braille cell encoding.
136 * @const
137 * @private
138 */
139 cvox.BrailleDisplayManager.COORDS_TO_BRAILLE_DOT_ =
140 [0x1, 0x2, 0x4, 0x40, 0x8, 0x10, 0x20, 0x80];
141
142
143 /**
113 * @param {!cvox.NavBraille} content Content to send to the braille display. 144 * @param {!cvox.NavBraille} content Content to send to the braille display.
114 * @param {!cvox.ExpandingBrailleTranslator.ExpansionType} expansionType 145 * @param {!cvox.ExpandingBrailleTranslator.ExpansionType} expansionType
115 * If the text has a {@code ValueSpan}, this indicates how that part 146 * If the text has a {@code ValueSpan}, this indicates how that part
116 * of the display content is expanded when translating to braille. 147 * of the display content is expanded when translating to braille.
117 * (See {@code cvox.ExpandingBrailleTranslator}). 148 * (See {@code cvox.ExpandingBrailleTranslator}).
118 */ 149 */
119 cvox.BrailleDisplayManager.prototype.setContent = function( 150 cvox.BrailleDisplayManager.prototype.setContent = function(
120 content, expansionType) { 151 content, expansionType) {
121 this.translateContent_(content, expansionType); 152 this.translateContent_(content, expansionType);
122 }; 153 };
123 154
124 155
125 /** 156 /**
157 * Takes an image, in the form of a data url, and displays it in braille
158 * onto the physical braille display and the virtual braille captions display.
159 * @param {!string} imageUrl The image, in the form of a data url.
160 */
161 cvox.BrailleDisplayManager.prototype.setImageContent = function(imageUrl) {
162 if (!this.displayState_.available) {
163 return;
164 }
165
166 // The number of dots in a braille cell.
167 // TODO(dmazzoni): Both multi-line braille displays we're testing with
168 // are 6-dot (2 x 3), but we should have a way to detect that via brltty.
169 var cellWidth = 2;
170 var cellHeight = 3;
171 var maxCellHeight = 4;
172
173 var rows = this.displayState_.textRowCount;
174 var columns = this.displayState_.textColumnCount;
175 var imageDataUrl = imageUrl;
176 var imgElement = document.createElement('img');
177 imgElement.src = imageDataUrl;
178 imgElement.onload = (function() {
179 var canvas = document.createElement('canvas');
180 var context = canvas.getContext('2d');
181 canvas.width = columns * cellWidth;
182 canvas.height = rows * cellHeight;
183 context.drawImage(imgElement, 0, 0, canvas.width, canvas.height);
184 var imageData = context.getImageData(0, 0, canvas.width, canvas.height);
185 var data = imageData.data;
186 var outputData = [];
187
188 // Convert image to black and white by thresholding the luminance for
189 // all opaque (non-transparent) pixels.
190 for (var i = 0; i < data.length; i += 4) {
191 var red = data[i];
192 var green = data[i + 1];
193 var blue = data[i + 2];
194 var alpha = data[i + 3];
195 var luminance =
196 0.2126 * red +
197 0.7152 * green +
198 0.0722 * blue;
199 // Show braille pin if the alpha is greater than the threshold and
200 // the luminance is less than the threshold.
201 var show = (alpha >= cvox.BrailleDisplayManager.ALPHA_THRESHOLD_ &&
202 luminance < cvox.BrailleDisplayManager.LUMINANCE_THRESHOLD_);
203 outputData.push(show);
204 }
205
206 // Convert black-and-white array to the proper encoding for Braille cells.
207 var brailleBuf = new ArrayBuffer(rows * columns);
208 var view = new Uint8Array(brailleBuf);
209 for (var i = 0; i < rows; i++) {
210 for (var j = 0; j < columns; j++) {
211 // Index in braille array
212 var brailleIndex = i * columns + j;
213 for (var x = 0; x < cellWidth; x++) {
David Tseng 2017/02/27 16:15:49 Rename x to cellColumn
dmazzoni 2017/02/28 05:08:23 Done.
214 for (var y = 0; y < cellHeight; y++) {
David Tseng 2017/02/27 16:15:49 y is a cellRow
dmazzoni 2017/02/28 05:08:23 Done.
215 var bitmapIndex =
216 (i * columns * cellHeight + j + y * columns) * cellWidth + x;
217 if (outputData[bitmapIndex]) {
218 view[brailleIndex] +=
219 cvox.BrailleDisplayManager.COORDS_TO_BRAILLE_DOT_[
220 x * maxCellHeight + y];
221 }
222 }
223 }
224 }
225 }
226
227 if (this.realDisplayState_.available) {
228 chrome.brailleDisplayPrivate.writeDots(
229 brailleBuf,
230 this.displayState_.textColumnCount,
231 this.displayState_.textRowCount);
232 }
233 if (cvox.BrailleCaptionsBackground.isEnabled()) {
234 cvox.BrailleCaptionsBackground.setImageContent(
235 brailleBuf, rows, columns);
236 }
237 }).bind(this);
238 };
239
240
241 /**
126 * Sets the command listener. When a command is invoked, the listener will be 242 * Sets the command listener. When a command is invoked, the listener will be
127 * called with the BrailleKeyEvent corresponding to the command and the content 243 * called with the BrailleKeyEvent corresponding to the command and the content
128 * that was present on the display when the command was invoked. The content 244 * that was present on the display when the command was invoked. The content
129 * is guaranteed to be identical to an object previously used as the parameter 245 * is guaranteed to be identical to an object previously used as the parameter
130 * to cvox.BrailleDisplayManager.setContent, or null if no content was set. 246 * to cvox.BrailleDisplayManager.setContent, or null if no content was set.
131 * @param {function(!cvox.BrailleKeyEvent, !cvox.NavBraille)} func The listener. 247 * @param {function(!cvox.BrailleKeyEvent, !cvox.NavBraille)} func The listener.
132 */ 248 */
133 cvox.BrailleDisplayManager.prototype.setCommandListener = function(func) { 249 cvox.BrailleDisplayManager.prototype.setCommandListener = function(func) {
134 this.commandListener_ = func; 250 this.commandListener_ = func;
135 }; 251 };
136 252
137 253
138 /** 254 /**
139 * @param {!cvox.BrailleDisplayState} newState Display state reported 255 * @return {!cvox.BrailleDisplayState} The current display state.
140 * by the extension API. 256 */
257 cvox.BrailleDisplayManager.prototype.getDisplayState = function() {
258 return this.displayState_;
259 };
260
261
262 /**
263 * @param {{available: boolean, textRowCount: (number|undefined),
264 * textColumnCount: (number|undefined)}} newState Display state reported
265 * by the extension API. Note that the type is almost the same as
266 * cvox.BrailleDisplayState except that the extension API allows
267 * some fields to be undefined, while cvox.BrailleDisplayState does not.
141 * @private 268 * @private
142 */ 269 */
143 cvox.BrailleDisplayManager.prototype.refreshDisplayState_ = function( 270 cvox.BrailleDisplayManager.prototype.refreshDisplayState_ = function(
144 newState) { 271 newState) {
145 var oldColumnCount = this.displayState_.textColumnCount || 0; 272 var oldColumnCount = this.displayState_.textColumnCount || 0;
146 var oldRowCount = this.displayState_.textRowCount || 0; 273 var oldRowCount = this.displayState_.textRowCount || 0;
147 var processDisplayState = function(displayState) { 274 var processDisplayState = function(displayState) {
148 this.displayState_ = displayState; 275 this.displayState_ = displayState;
149 var newColumnCount = displayState.textColumnCount || 0; 276 var newColumnCount = displayState.textColumnCount || 0;
150 var newRowCount = displayState.textRowCount || 0; 277 var newRowCount = displayState.textRowCount || 0;
151 278
152 if (oldColumnCount != newColumnCount || oldRowCount != newRowCount) { 279 if (oldColumnCount != newColumnCount || oldRowCount != newRowCount) {
153 this.panStrategy_.setDisplaySize(newRowCount, newColumnCount); 280 this.panStrategy_.setDisplaySize(newRowCount, newColumnCount);
154 } 281 }
155 this.refresh_(); 282 this.refresh_();
156 }.bind(this); 283 }.bind(this);
157 this.realDisplayState_ = newState; 284 this.realDisplayState_ = {
285 available: newState.available,
286 textRowCount: newState.textRowCount || 0,
287 textColumnCount: newState.textColumnCount || 0
288 };
158 if (newState.available) { 289 if (newState.available) {
159 processDisplayState(newState); 290 processDisplayState(newState);
160 // Update the dimensions of the virtual braille captions display to those 291 // Update the dimensions of the virtual braille captions display to those
161 // of a real physical display when one is plugged in. 292 // of a real physical display when one is plugged in.
162 } else { 293 } else {
163 cvox.BrailleCaptionsBackground.getVirtualDisplayState(processDisplayState); 294 cvox.BrailleCaptionsBackground.getVirtualDisplayState(processDisplayState);
164 } 295 }
165 }; 296 };
166 297
167 298
(...skipping 200 matching lines...) Expand 10 before | Expand all | Expand 10 after
368 }; 499 };
369 500
370 /** 501 /**
371 * @param {boolean} wordWrap 502 * @param {boolean} wordWrap
372 * @private 503 * @private
373 */ 504 */
374 cvox.BrailleDisplayManager.prototype.updatePanStrategy_ = function(wordWrap) { 505 cvox.BrailleDisplayManager.prototype.updatePanStrategy_ = function(wordWrap) {
375 this.panStrategy_.setPanStrategy(wordWrap); 506 this.panStrategy_.setPanStrategy(wordWrap);
376 this.refresh_(); 507 this.refresh_();
377 }; 508 };
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698