Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
seleniumhq
GitHub Repository: seleniumhq/selenium
Path: blob/trunk/third_party/closure/goog/graphics/canvaselement.js
2868 views
1
// Copyright 2007 The Closure Library Authors. All Rights Reserved.
2
//
3
// Licensed under the Apache License, Version 2.0 (the "License");
4
// you may not use this file except in compliance with the License.
5
// You may obtain a copy of the License at
6
//
7
// http://www.apache.org/licenses/LICENSE-2.0
8
//
9
// Unless required by applicable law or agreed to in writing, software
10
// distributed under the License is distributed on an "AS-IS" BASIS,
11
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
// See the License for the specific language governing permissions and
13
// limitations under the License.
14
15
16
/**
17
* @fileoverview Objects representing shapes drawn on a canvas.
18
* @author [email protected] (Robby Walker)
19
*/
20
21
goog.provide('goog.graphics.CanvasEllipseElement');
22
goog.provide('goog.graphics.CanvasGroupElement');
23
goog.provide('goog.graphics.CanvasImageElement');
24
goog.provide('goog.graphics.CanvasPathElement');
25
goog.provide('goog.graphics.CanvasRectElement');
26
goog.provide('goog.graphics.CanvasTextElement');
27
28
29
goog.require('goog.array');
30
goog.require('goog.dom');
31
goog.require('goog.dom.TagName');
32
goog.require('goog.dom.safe');
33
goog.require('goog.graphics.EllipseElement');
34
goog.require('goog.graphics.Font');
35
goog.require('goog.graphics.GroupElement');
36
goog.require('goog.graphics.ImageElement');
37
goog.require('goog.graphics.Path');
38
goog.require('goog.graphics.PathElement');
39
goog.require('goog.graphics.RectElement');
40
goog.require('goog.graphics.TextElement');
41
goog.require('goog.html.SafeHtml');
42
goog.require('goog.html.uncheckedconversions');
43
goog.require('goog.math');
44
goog.require('goog.string');
45
goog.require('goog.string.Const');
46
47
48
49
/**
50
* Object representing a group of objects in a canvas.
51
* This is an implementation of the goog.graphics.GroupElement interface.
52
* You should not construct objects from this constructor. The graphics
53
* will return the object for you.
54
* @param {goog.graphics.CanvasGraphics} graphics The graphics creating
55
* this element.
56
* @constructor
57
* @extends {goog.graphics.GroupElement}
58
* @deprecated goog.graphics is deprecated. It existed to abstract over browser
59
* differences before the canvas tag was widely supported. See
60
* http://en.wikipedia.org/wiki/Canvas_element for details.
61
* @final
62
*/
63
goog.graphics.CanvasGroupElement = function(graphics) {
64
goog.graphics.GroupElement.call(this, null, graphics);
65
66
67
/**
68
* Children contained by this group.
69
* @type {Array<goog.graphics.Element>}
70
* @private
71
*/
72
this.children_ = [];
73
};
74
goog.inherits(goog.graphics.CanvasGroupElement, goog.graphics.GroupElement);
75
76
77
/**
78
* Remove all drawing elements from the group.
79
* @override
80
*/
81
goog.graphics.CanvasGroupElement.prototype.clear = function() {
82
if (this.children_.length) {
83
this.children_.length = 0;
84
this.getGraphics().redraw();
85
}
86
};
87
88
89
/**
90
* Set the size of the group element.
91
* @param {number|string} width The width of the group element.
92
* @param {number|string} height The height of the group element.
93
* @override
94
*/
95
goog.graphics.CanvasGroupElement.prototype.setSize = function(width, height) {
96
// Do nothing.
97
};
98
99
100
/**
101
* Append a child to the group. Does not draw it
102
* @param {goog.graphics.Element} element The child to append.
103
*/
104
goog.graphics.CanvasGroupElement.prototype.appendChild = function(element) {
105
this.children_.push(element);
106
};
107
108
109
/**
110
* Draw the group.
111
* @param {CanvasRenderingContext2D} ctx The context to draw the element in.
112
*/
113
goog.graphics.CanvasGroupElement.prototype.draw = function(ctx) {
114
for (var i = 0, len = this.children_.length; i < len; i++) {
115
this.getGraphics().drawElement(this.children_[i]);
116
}
117
};
118
119
120
/**
121
* Removes an element from the group.
122
* @param {!goog.graphics.Element} elem the element to remove.
123
*/
124
goog.graphics.CanvasGroupElement.prototype.removeElement = function(elem) {
125
goog.array.removeIf(this.children_, function(child) {
126
// If the child has children (and thus is a group element)
127
// call removeElement on that group
128
if (child.children_) {
129
child.removeElement(elem);
130
return false;
131
} else {
132
return child === elem;
133
}
134
});
135
};
136
137
138
139
/**
140
* Thin wrapper for canvas ellipse elements.
141
* This is an implementation of the goog.graphics.EllipseElement interface.
142
* You should not construct objects from this constructor. The graphics
143
* will return the object for you.
144
* @param {Element} element The DOM element to wrap.
145
* @param {goog.graphics.CanvasGraphics} graphics The graphics creating
146
* this element.
147
* @param {number} cx Center X coordinate.
148
* @param {number} cy Center Y coordinate.
149
* @param {number} rx Radius length for the x-axis.
150
* @param {number} ry Radius length for the y-axis.
151
* @param {goog.graphics.Stroke} stroke The stroke to use for this element.
152
* @param {goog.graphics.Fill} fill The fill to use for this element.
153
* @constructor
154
* @extends {goog.graphics.EllipseElement}
155
* @final
156
*/
157
goog.graphics.CanvasEllipseElement = function(
158
element, graphics, cx, cy, rx, ry, stroke, fill) {
159
goog.graphics.EllipseElement.call(this, element, graphics, stroke, fill);
160
161
/**
162
* X coordinate of the ellipse center.
163
* @type {number}
164
* @private
165
*/
166
this.cx_ = cx;
167
168
169
/**
170
* Y coordinate of the ellipse center.
171
* @type {number}
172
* @private
173
*/
174
this.cy_ = cy;
175
176
177
/**
178
* Radius length for the x-axis.
179
* @type {number}
180
* @private
181
*/
182
this.rx_ = rx;
183
184
185
/**
186
* Radius length for the y-axis.
187
* @type {number}
188
* @private
189
*/
190
this.ry_ = ry;
191
192
193
/**
194
* Internal path approximating an ellipse.
195
* @type {goog.graphics.Path}
196
* @private
197
*/
198
this.path_ = new goog.graphics.Path();
199
this.setUpPath_();
200
201
/**
202
* Internal path element that actually does the drawing.
203
* @type {goog.graphics.CanvasPathElement}
204
* @private
205
*/
206
this.pathElement_ = new goog.graphics.CanvasPathElement(
207
null, graphics, this.path_, stroke, fill);
208
};
209
goog.inherits(goog.graphics.CanvasEllipseElement, goog.graphics.EllipseElement);
210
211
212
/**
213
* Sets up the path.
214
* @private
215
*/
216
goog.graphics.CanvasEllipseElement.prototype.setUpPath_ = function() {
217
this.path_.clear();
218
this.path_.moveTo(
219
this.cx_ + goog.math.angleDx(0, this.rx_),
220
this.cy_ + goog.math.angleDy(0, this.ry_));
221
this.path_.arcTo(this.rx_, this.ry_, 0, 360);
222
this.path_.close();
223
};
224
225
226
/**
227
* Update the center point of the ellipse.
228
* @param {number} cx Center X coordinate.
229
* @param {number} cy Center Y coordinate.
230
* @override
231
*/
232
goog.graphics.CanvasEllipseElement.prototype.setCenter = function(cx, cy) {
233
this.cx_ = cx;
234
this.cy_ = cy;
235
this.setUpPath_();
236
this.pathElement_.setPath(/** @type {!goog.graphics.Path} */ (this.path_));
237
};
238
239
240
/**
241
* Update the radius of the ellipse.
242
* @param {number} rx Center X coordinate.
243
* @param {number} ry Center Y coordinate.
244
* @override
245
*/
246
goog.graphics.CanvasEllipseElement.prototype.setRadius = function(rx, ry) {
247
this.rx_ = rx;
248
this.ry_ = ry;
249
this.setUpPath_();
250
this.pathElement_.setPath(/** @type {!goog.graphics.Path} */ (this.path_));
251
};
252
253
254
/**
255
* Draw the ellipse. Should be treated as package scope.
256
* @param {CanvasRenderingContext2D} ctx The context to draw the element in.
257
*/
258
goog.graphics.CanvasEllipseElement.prototype.draw = function(ctx) {
259
this.pathElement_.draw(ctx);
260
};
261
262
263
264
/**
265
* Thin wrapper for canvas rectangle elements.
266
* This is an implementation of the goog.graphics.RectElement interface.
267
* You should not construct objects from this constructor. The graphics
268
* will return the object for you.
269
* @param {Element} element The DOM element to wrap.
270
* @param {goog.graphics.CanvasGraphics} graphics The graphics creating
271
* this element.
272
* @param {number} x X coordinate (left).
273
* @param {number} y Y coordinate (top).
274
* @param {number} w Width of rectangle.
275
* @param {number} h Height of rectangle.
276
* @param {goog.graphics.Stroke} stroke The stroke to use for this element.
277
* @param {goog.graphics.Fill} fill The fill to use for this element.
278
* @constructor
279
* @extends {goog.graphics.RectElement}
280
* @final
281
*/
282
goog.graphics.CanvasRectElement = function(
283
element, graphics, x, y, w, h, stroke, fill) {
284
goog.graphics.RectElement.call(this, element, graphics, stroke, fill);
285
286
/**
287
* X coordinate of the top left corner.
288
* @type {number}
289
* @private
290
*/
291
this.x_ = x;
292
293
294
/**
295
* Y coordinate of the top left corner.
296
* @type {number}
297
* @private
298
*/
299
this.y_ = y;
300
301
302
/**
303
* Width of the rectangle.
304
* @type {number}
305
* @private
306
*/
307
this.w_ = w;
308
309
310
/**
311
* Height of the rectangle.
312
* @type {number}
313
* @private
314
*/
315
this.h_ = h;
316
};
317
goog.inherits(goog.graphics.CanvasRectElement, goog.graphics.RectElement);
318
319
320
/**
321
* Update the position of the rectangle.
322
* @param {number} x X coordinate (left).
323
* @param {number} y Y coordinate (top).
324
* @override
325
*/
326
goog.graphics.CanvasRectElement.prototype.setPosition = function(x, y) {
327
this.x_ = x;
328
this.y_ = y;
329
if (this.drawn_) {
330
this.getGraphics().redraw();
331
}
332
};
333
334
335
/**
336
* Whether the rectangle has been drawn yet.
337
* @type {boolean}
338
* @private
339
*/
340
goog.graphics.CanvasRectElement.prototype.drawn_ = false;
341
342
343
/**
344
* Update the size of the rectangle.
345
* @param {number} width Width of rectangle.
346
* @param {number} height Height of rectangle.
347
* @override
348
*/
349
goog.graphics.CanvasRectElement.prototype.setSize = function(width, height) {
350
this.w_ = width;
351
this.h_ = height;
352
if (this.drawn_) {
353
this.getGraphics().redraw();
354
}
355
};
356
357
358
/**
359
* Draw the rectangle. Should be treated as package scope.
360
* @param {CanvasRenderingContext2D} ctx The context to draw the element in.
361
*/
362
goog.graphics.CanvasRectElement.prototype.draw = function(ctx) {
363
this.drawn_ = true;
364
ctx.beginPath();
365
ctx.moveTo(this.x_, this.y_);
366
ctx.lineTo(this.x_, this.y_ + this.h_);
367
ctx.lineTo(this.x_ + this.w_, this.y_ + this.h_);
368
ctx.lineTo(this.x_ + this.w_, this.y_);
369
ctx.closePath();
370
};
371
372
373
374
/**
375
* Thin wrapper for canvas path elements.
376
* This is an implementation of the goog.graphics.PathElement interface.
377
* You should not construct objects from this constructor. The graphics
378
* will return the object for you.
379
* @param {Element} element The DOM element to wrap.
380
* @param {goog.graphics.CanvasGraphics} graphics The graphics creating
381
* this element.
382
* @param {!goog.graphics.Path} path The path object to draw.
383
* @param {goog.graphics.Stroke} stroke The stroke to use for this element.
384
* @param {goog.graphics.Fill} fill The fill to use for this element.
385
* @constructor
386
* @extends {goog.graphics.PathElement}
387
* @final
388
*/
389
goog.graphics.CanvasPathElement = function(
390
element, graphics, path, stroke, fill) {
391
goog.graphics.PathElement.call(this, element, graphics, stroke, fill);
392
393
this.setPath(path);
394
};
395
goog.inherits(goog.graphics.CanvasPathElement, goog.graphics.PathElement);
396
397
398
/**
399
* Whether the shape has been drawn yet.
400
* @type {boolean}
401
* @private
402
*/
403
goog.graphics.CanvasPathElement.prototype.drawn_ = false;
404
405
406
/**
407
* The path to draw.
408
* @type {goog.graphics.Path}
409
* @private
410
*/
411
goog.graphics.CanvasPathElement.prototype.path_;
412
413
414
/**
415
* Update the underlying path.
416
* @param {!goog.graphics.Path} path The path object to draw.
417
* @override
418
*/
419
goog.graphics.CanvasPathElement.prototype.setPath = function(path) {
420
this.path_ =
421
path.isSimple() ? path : goog.graphics.Path.createSimplifiedPath(path);
422
if (this.drawn_) {
423
this.getGraphics().redraw();
424
}
425
};
426
427
428
/**
429
* Draw the path. Should be treated as package scope.
430
* @param {CanvasRenderingContext2D} ctx The context to draw the element in.
431
* @suppress {deprecated} goog.graphics is deprecated.
432
*/
433
goog.graphics.CanvasPathElement.prototype.draw = function(ctx) {
434
this.drawn_ = true;
435
436
ctx.beginPath();
437
this.path_.forEachSegment(function(segment, args) {
438
switch (segment) {
439
case goog.graphics.Path.Segment.MOVETO:
440
ctx.moveTo(args[0], args[1]);
441
break;
442
case goog.graphics.Path.Segment.LINETO:
443
for (var i = 0; i < args.length; i += 2) {
444
ctx.lineTo(args[i], args[i + 1]);
445
}
446
break;
447
case goog.graphics.Path.Segment.CURVETO:
448
for (var i = 0; i < args.length; i += 6) {
449
ctx.bezierCurveTo(
450
args[i], args[i + 1], args[i + 2], args[i + 3], args[i + 4],
451
args[i + 5]);
452
}
453
break;
454
case goog.graphics.Path.Segment.ARCTO:
455
throw Error('Canvas paths cannot contain arcs');
456
case goog.graphics.Path.Segment.CLOSE:
457
ctx.closePath();
458
break;
459
}
460
});
461
};
462
463
464
465
/**
466
* Thin wrapper for canvas text elements.
467
* This is an implementation of the goog.graphics.TextElement interface.
468
* You should not construct objects from this constructor. The graphics
469
* will return the object for you.
470
* @param {!goog.graphics.CanvasGraphics} graphics The graphics creating
471
* this element.
472
* @param {string} text The text to draw.
473
* @param {number} x1 X coordinate of start of line.
474
* @param {number} y1 Y coordinate of start of line.
475
* @param {number} x2 X coordinate of end of line.
476
* @param {number} y2 Y coordinate of end of line.
477
* @param {?string} align Horizontal alignment: left (default), center, right.
478
* @param {!goog.graphics.Font} font Font describing the font properties.
479
* @param {goog.graphics.Stroke} stroke The stroke to use for this element.
480
* @param {goog.graphics.Fill} fill The fill to use for this element.
481
* @constructor
482
* @extends {goog.graphics.TextElement}
483
* @final
484
*/
485
goog.graphics.CanvasTextElement = function(
486
graphics, text, x1, y1, x2, y2, align, font, stroke, fill) {
487
var element = goog.dom.createDom(
488
goog.dom.TagName.DIV,
489
{'style': 'display:table;position:absolute;padding:0;margin:0;border:0'});
490
goog.graphics.TextElement.call(this, element, graphics, stroke, fill);
491
492
/**
493
* The text to draw.
494
* @type {string}
495
* @private
496
*/
497
this.text_ = text;
498
499
/**
500
* X coordinate of the start of the line the text is drawn on.
501
* @type {number}
502
* @private
503
*/
504
this.x1_ = x1;
505
506
/**
507
* Y coordinate of the start of the line the text is drawn on.
508
* @type {number}
509
* @private
510
*/
511
this.y1_ = y1;
512
513
/**
514
* X coordinate of the end of the line the text is drawn on.
515
* @type {number}
516
* @private
517
*/
518
this.x2_ = x2;
519
520
/**
521
* Y coordinate of the end of the line the text is drawn on.
522
* @type {number}
523
* @private
524
*/
525
this.y2_ = y2;
526
527
/**
528
* Horizontal alignment: left (default), center, right.
529
* @type {string}
530
* @private
531
*/
532
this.align_ = align || 'left';
533
534
/**
535
* Font object describing the font properties.
536
* @type {goog.graphics.Font}
537
* @private
538
*/
539
this.font_ = font;
540
541
/**
542
* The inner element that contains the text.
543
* @type {Element}
544
* @private
545
*/
546
this.innerElement_ = goog.dom.createDom(
547
goog.dom.TagName.DIV,
548
{'style': 'display:table-cell;padding: 0;margin: 0;border: 0'});
549
550
this.updateStyle_();
551
this.updateText_();
552
553
// Append to the DOM.
554
graphics.getElement().appendChild(element);
555
element.appendChild(this.innerElement_);
556
};
557
goog.inherits(goog.graphics.CanvasTextElement, goog.graphics.TextElement);
558
559
560
/**
561
* Update the displayed text of the element.
562
* @param {string} text The text to draw.
563
* @override
564
*/
565
goog.graphics.CanvasTextElement.prototype.setText = function(text) {
566
this.text_ = text;
567
this.updateText_();
568
};
569
570
571
/**
572
* Sets the fill for this element.
573
* @param {goog.graphics.Fill} fill The fill object.
574
* @override
575
*/
576
goog.graphics.CanvasTextElement.prototype.setFill = function(fill) {
577
this.fill = fill;
578
var element = this.getElement();
579
if (element) {
580
element.style.color = fill.getColor() || fill.getColor1();
581
}
582
};
583
584
585
/**
586
* Sets the stroke for this element.
587
* @param {goog.graphics.Stroke} stroke The stroke object.
588
* @override
589
*/
590
goog.graphics.CanvasTextElement.prototype.setStroke = function(stroke) {
591
// Ignore stroke
592
};
593
594
595
/**
596
* Draw the text. Should be treated as package scope.
597
* @param {CanvasRenderingContext2D} ctx The context to draw the element in.
598
*/
599
goog.graphics.CanvasTextElement.prototype.draw = function(ctx) {
600
// Do nothing - the text is already drawn.
601
};
602
603
604
/**
605
* Update the styles of the DIVs.
606
* @private
607
*/
608
goog.graphics.CanvasTextElement.prototype.updateStyle_ = function() {
609
var x1 = this.x1_;
610
var x2 = this.x2_;
611
var y1 = this.y1_;
612
var y2 = this.y2_;
613
var align = this.align_;
614
var font = this.font_;
615
var style = this.getElement().style;
616
var scaleX = this.getGraphics().getPixelScaleX();
617
var scaleY = this.getGraphics().getPixelScaleY();
618
619
if (x1 == x2) {
620
// Special case vertical text
621
style.lineHeight = '90%';
622
623
this.innerElement_.style.verticalAlign =
624
align == 'center' ? 'middle' : align == 'left' ?
625
(y1 < y2 ? 'top' : 'bottom') :
626
y1 < y2 ? 'bottom' : 'top';
627
style.textAlign = 'center';
628
629
var w = font.size * scaleX;
630
style.top = Math.round(Math.min(y1, y2) * scaleY) + 'px';
631
style.left = Math.round((x1 - w / 2) * scaleX) + 'px';
632
style.width = Math.round(w) + 'px';
633
style.height = Math.abs(y1 - y2) * scaleY + 'px';
634
635
style.fontSize = font.size * 0.6 * scaleY + 'pt';
636
} else {
637
style.lineHeight = '100%';
638
this.innerElement_.style.verticalAlign = 'top';
639
style.textAlign = align;
640
641
style.top = Math.round(((y1 + y2) / 2 - font.size * 2 / 3) * scaleY) + 'px';
642
style.left = Math.round(x1 * scaleX) + 'px';
643
style.width = Math.round(Math.abs(x2 - x1) * scaleX) + 'px';
644
style.height = 'auto';
645
646
style.fontSize = font.size * scaleY + 'pt';
647
}
648
649
style.fontWeight = font.bold ? 'bold' : 'normal';
650
style.fontStyle = font.italic ? 'italic' : 'normal';
651
style.fontFamily = font.family;
652
653
var fill = this.getFill();
654
style.color = fill.getColor() || fill.getColor1();
655
};
656
657
658
/**
659
* Update the text content.
660
* @private
661
*/
662
goog.graphics.CanvasTextElement.prototype.updateText_ = function() {
663
if (this.x1_ == this.x2_) {
664
// Special case vertical text
665
var html =
666
goog.array
667
.map(
668
this.text_.split(''),
669
function(entry) { return goog.string.htmlEscape(entry); })
670
.join('<br>');
671
// Creating a SafeHtml for each character would be quite expensive, and it's
672
// obvious that this is safe, so an unchecked conversion is appropriate.
673
var safeHtml =
674
goog.html.uncheckedconversions
675
.safeHtmlFromStringKnownToSatisfyTypeContract(
676
goog.string.Const.from('Concatenate escaped chars and <br>'),
677
html);
678
goog.dom.safe.setInnerHtml(
679
/** @type {!Element} */ (this.innerElement_), safeHtml);
680
} else {
681
goog.dom.safe.setInnerHtml(
682
/** @type {!Element} */ (this.innerElement_),
683
goog.html.SafeHtml.htmlEscape(this.text_));
684
}
685
};
686
687
688
689
/**
690
* Thin wrapper for canvas image elements.
691
* This is an implementation of the goog.graphics.ImageElement interface.
692
* You should not construct objects from this constructor. The graphics
693
* will return the object for you.
694
* @param {Element} element The DOM element to wrap.
695
* @param {goog.graphics.CanvasGraphics} graphics The graphics creating
696
* this element.
697
* @param {number} x X coordinate (left).
698
* @param {number} y Y coordinate (top).
699
* @param {number} w Width of rectangle.
700
* @param {number} h Height of rectangle.
701
* @param {string} src Source of the image.
702
* @constructor
703
* @extends {goog.graphics.ImageElement}
704
* @final
705
*/
706
goog.graphics.CanvasImageElement = function(
707
element, graphics, x, y, w, h, src) {
708
goog.graphics.ImageElement.call(this, element, graphics);
709
710
/**
711
* X coordinate of the top left corner.
712
* @type {number}
713
* @private
714
*/
715
this.x_ = x;
716
717
718
/**
719
* Y coordinate of the top left corner.
720
* @type {number}
721
* @private
722
*/
723
this.y_ = y;
724
725
726
/**
727
* Width of the rectangle.
728
* @type {number}
729
* @private
730
*/
731
this.w_ = w;
732
733
734
/**
735
* Height of the rectangle.
736
* @type {number}
737
* @private
738
*/
739
this.h_ = h;
740
741
742
/**
743
* URL of the image source.
744
* @type {string}
745
* @private
746
*/
747
this.src_ = src;
748
};
749
goog.inherits(goog.graphics.CanvasImageElement, goog.graphics.ImageElement);
750
751
752
/**
753
* Whether the image has been drawn yet.
754
* @type {boolean}
755
* @private
756
*/
757
goog.graphics.CanvasImageElement.prototype.drawn_ = false;
758
759
760
/**
761
* Update the position of the image.
762
* @param {number} x X coordinate (left).
763
* @param {number} y Y coordinate (top).
764
* @override
765
*/
766
goog.graphics.CanvasImageElement.prototype.setPosition = function(x, y) {
767
this.x_ = x;
768
this.y_ = y;
769
if (this.drawn_) {
770
this.getGraphics().redraw();
771
}
772
};
773
774
775
/**
776
* Update the size of the image.
777
* @param {number} width Width of rectangle.
778
* @param {number} height Height of rectangle.
779
* @override
780
*/
781
goog.graphics.CanvasImageElement.prototype.setSize = function(width, height) {
782
this.w_ = width;
783
this.h_ = height;
784
if (this.drawn_) {
785
this.getGraphics().redraw();
786
}
787
};
788
789
790
/**
791
* Update the source of the image.
792
* @param {string} src Source of the image.
793
* @override
794
*/
795
goog.graphics.CanvasImageElement.prototype.setSource = function(src) {
796
this.src_ = src;
797
if (this.drawn_) {
798
// TODO(robbyw): Probably need to reload the image here.
799
this.getGraphics().redraw();
800
}
801
};
802
803
804
/**
805
* Draw the image. Should be treated as package scope.
806
* @param {CanvasRenderingContext2D} ctx The context to draw the element in.
807
*/
808
goog.graphics.CanvasImageElement.prototype.draw = function(ctx) {
809
if (this.img_) {
810
if (this.w_ && this.h_) {
811
// If the image is already loaded, draw it.
812
ctx.drawImage(this.img_, this.x_, this.y_, this.w_, this.h_);
813
}
814
this.drawn_ = true;
815
816
} else {
817
// Otherwise, load it.
818
var img = new Image();
819
img.onload = goog.bind(this.handleImageLoad_, this, img);
820
// TODO(robbyw): Handle image load errors.
821
img.src = this.src_;
822
}
823
};
824
825
826
/**
827
* Handle an image load.
828
* @param {Element} img The image element that finished loading.
829
* @private
830
*/
831
goog.graphics.CanvasImageElement.prototype.handleImageLoad_ = function(img) {
832
this.img_ = img;
833
834
// TODO(robbyw): Add a small delay to catch batched images
835
this.getGraphics().redraw();
836
};
837
838