blob: 0dafb9caec9a561352b96f69686c92c59f4f2351 [file] [log] [blame]
/**
* Copyright 2014 Google Inc. All rights reserved.
*
* Use of this source code is governed by a BSD-style
* license that can be found in the LICENSE file.
*
* @fileoverview Description of this file.
*
* A polyfill for HTML Canvas features, including
* Path2D support.
*/
if (CanvasRenderingContext2D.prototype.ellipse === undefined) {
CanvasRenderingContext2D.prototype.ellipse = function(x, y, radiusX, radiusY, rotation, startAngle, endAngle, antiClockwise) {
this.save();
this.translate(x, y);
this.rotate(rotation);
this.scale(radiusX, radiusY);
this.arc(0, 0, 1, startAngle, endAngle, antiClockwise);
this.restore();
};
}
var BM_Path2D;
function BM_CanvasRenderingContext2D(renderer){
this.renderer = renderer;
}
(function() {
var canvasPrototype = CanvasRenderingContext2D.prototype;
var bm_canvasPrototype = BM_CanvasRenderingContext2D.prototype;
function Path_(arg) {
this.ops_ = [];
if (arg === undefined) {
return;
}
if (typeof arg == 'string') {
try {
this.ops_ = parser.parse(arg);
} catch(e) {
// Treat an invalid SVG path as an empty path.
}
} else if (arg.hasOwnProperty('ops_')) {
this.ops_ = arg.ops_.slice(0);
} else {
throw 'Error: ' + typeof arg + 'is not a valid argument to Path';
}
}
// TODO(jcgregorio) test for arcTo and implement via something.
// Path methods that map simply to the CanvasRenderingContext2D.
var simple_mapping = [
'closePath',
'moveTo',
'lineTo',
'quadraticCurveTo',
'bezierCurveTo',
'rect',
'arc',
'arcTo',
'ellipse'
];
function createFunction(name) {
return function() {
var i, len = arguments.length;
var args = [];
for(i=0;i<len;i+=1){
args.push(arguments[i]);
}
this.ops_.push({type: name, args: args});
};
}
// Add simple_mapping methods to Path2D.
for (var i=0; i<simple_mapping.length; i++) {
var name = simple_mapping[i];
Path_.prototype[name] = createFunction(name);
}
Path_.prototype.addPath = function(path, tr) {
var hasTx = false;
if (tr && (tr[0] != 1 || tr[1] !== 0 || tr[2] !== 0 || tr[3] != 1 || tr[4] !== 0 || tr[5] !== 0)) {
hasTx = true;
this.ops_.push({type: 'save', args: []});
this.ops_.push({type: 'transform', args: [tr[0], tr[1], tr[2], tr[3], tr[4], tr[5]]});
}
this.ops_ = this.ops_.concat(path.ops_);
if (hasTx) {
this.ops_.push({type: 'restore', args: []});
}
};
var original_fill = canvasPrototype.fill;
var original_stroke = canvasPrototype.stroke;
var original_clip = canvasPrototype.clip;
// Replace methods on CanvasRenderingContext2D with ones that understand Path2D.
bm_canvasPrototype.fill = function(arg) {
if (arg instanceof Path_) {
this.renderer.canvasContext.beginPath();
for (var i = 0, len = arg.ops_.length; i < len; i++) {
var op = arg.ops_[i];
if(op.type == 'transform'){
this.renderer.ctxTransform(op.args);
}else if(op.type == 'save'){
this.renderer.save();
}else if(op.type == 'restore'){
this.renderer.restore();
}else{
this.renderer.canvasContext[op.type].apply(this.renderer.canvasContext, op.args);
}
}
len = arguments.length;
var args = [];
for(i=1;i<len;i+=1){
args.push(arguments[i]);
}
original_fill.apply(this.renderer.canvasContext, args);
} else {
original_fill.apply(this.renderer.canvasContext, arguments);
}
};
bm_canvasPrototype.stroke = function(arg) {
if (arg instanceof Path_) {
this.renderer.canvasContext.beginPath();
for (var i = 0, len = arg.ops_.length; i < len; i++) {
var op = arg.ops_[i];
this.renderer.canvasContext[op.type].apply(this.renderer.canvasContext, op.args);
}
original_stroke.call(this.renderer.canvasContext);
} else {
original_stroke.call(this.renderer.canvasContext);
}
};
bm_canvasPrototype.clip = function(arg) {
if (arg instanceof Path_) {
this.renderer.canvasContext.beginPath();
for (var i = 0, len = arg.ops_.length; i < len; i++) {
var op = arg.ops_[i];
this.renderer.canvasContext[op.type].apply(this.renderer.canvasContext, op.args);
}
len = arguments.length;
var args = [];
for(i=1;i<len;i+=1){
args.push(arguments[i]);
}
original_clip.apply(this.renderer.canvasContext, args);
} else {
original_clip.apply(this.renderer.canvasContext, arguments);
}
};
// Set up externs.
BM_Path2D = Path_;
})();