blob: e9447f31b590f9eaa9107f3270adb098baebdd34 [file] [log] [blame]
/**
* Copyright (c) 2006-2015, JGraph Ltd
* Copyright (c) 2006-2015, Gaudenz Alder
*/
/**
* Class: mxAbstractCanvas2D
*
* Base class for all canvases. A description of the public API is available in <mxXmlCanvas2D>.
* All color values of <mxConstants.NONE> will be converted to null in the state.
*
* Constructor: mxAbstractCanvas2D
*
* Constructs a new abstract canvas.
*/
function mxAbstractCanvas2D()
{
/**
* Variable: converter
*
* Holds the <mxUrlConverter> to convert image URLs.
*/
this.converter = this.createUrlConverter();
this.reset();
};
/**
* Variable: state
*
* Holds the current state.
*/
mxAbstractCanvas2D.prototype.state = null;
/**
* Variable: states
*
* Stack of states.
*/
mxAbstractCanvas2D.prototype.states = null;
/**
* Variable: path
*
* Holds the current path as an array.
*/
mxAbstractCanvas2D.prototype.path = null;
/**
* Variable: rotateHtml
*
* Switch for rotation of HTML. Default is false.
*/
mxAbstractCanvas2D.prototype.rotateHtml = true;
/**
* Variable: lastX
*
* Holds the last x coordinate.
*/
mxAbstractCanvas2D.prototype.lastX = 0;
/**
* Variable: lastY
*
* Holds the last y coordinate.
*/
mxAbstractCanvas2D.prototype.lastY = 0;
/**
* Variable: moveOp
*
* Contains the string used for moving in paths. Default is 'M'.
*/
mxAbstractCanvas2D.prototype.moveOp = 'M';
/**
* Variable: lineOp
*
* Contains the string used for moving in paths. Default is 'L'.
*/
mxAbstractCanvas2D.prototype.lineOp = 'L';
/**
* Variable: quadOp
*
* Contains the string used for quadratic paths. Default is 'Q'.
*/
mxAbstractCanvas2D.prototype.quadOp = 'Q';
/**
* Variable: curveOp
*
* Contains the string used for bezier curves. Default is 'C'.
*/
mxAbstractCanvas2D.prototype.curveOp = 'C';
/**
* Variable: closeOp
*
* Holds the operator for closing curves. Default is 'Z'.
*/
mxAbstractCanvas2D.prototype.closeOp = 'Z';
/**
* Variable: pointerEvents
*
* Boolean value that specifies if events should be handled. Default is false.
*/
mxAbstractCanvas2D.prototype.pointerEvents = false;
/**
* Function: createUrlConverter
*
* Create a new <mxUrlConverter> and returns it.
*/
mxAbstractCanvas2D.prototype.createUrlConverter = function()
{
return new mxUrlConverter();
};
/**
* Function: reset
*
* Resets the state of this canvas.
*/
mxAbstractCanvas2D.prototype.reset = function()
{
this.state = this.createState();
this.states = [];
};
/**
* Function: createState
*
* Creates the state of the this canvas.
*/
mxAbstractCanvas2D.prototype.createState = function()
{
return {
dx: 0,
dy: 0,
scale: 1,
alpha: 1,
fillAlpha: 1,
strokeAlpha: 1,
fillColor: null,
gradientFillAlpha: 1,
gradientColor: null,
gradientAlpha: 1,
gradientDirection: null,
strokeColor: null,
strokeWidth: 1,
dashed: false,
dashPattern: '3 3',
fixDash: false,
lineCap: 'flat',
lineJoin: 'miter',
miterLimit: 10,
fontColor: '#000000',
fontBackgroundColor: null,
fontBorderColor: null,
fontSize: mxConstants.DEFAULT_FONTSIZE,
fontFamily: mxConstants.DEFAULT_FONTFAMILY,
fontStyle: 0,
shadow: false,
shadowColor: mxConstants.SHADOWCOLOR,
shadowAlpha: mxConstants.SHADOW_OPACITY,
shadowDx: mxConstants.SHADOW_OFFSET_X,
shadowDy: mxConstants.SHADOW_OFFSET_Y,
rotation: 0,
rotationCx: 0,
rotationCy: 0
};
};
/**
* Function: format
*
* Rounds all numbers to integers.
*/
mxAbstractCanvas2D.prototype.format = function(value)
{
return Math.round(parseFloat(value));
};
/**
* Function: addOp
*
* Adds the given operation to the path.
*/
mxAbstractCanvas2D.prototype.addOp = function()
{
if (this.path != null)
{
this.path.push(arguments[0]);
if (arguments.length > 2)
{
var s = this.state;
for (var i = 2; i < arguments.length; i += 2)
{
this.lastX = arguments[i - 1];
this.lastY = arguments[i];
this.path.push(this.format((this.lastX + s.dx) * s.scale));
this.path.push(this.format((this.lastY + s.dy) * s.scale));
}
}
}
};
/**
* Function: rotatePoint
*
* Rotates the given point and returns the result as an <mxPoint>.
*/
mxAbstractCanvas2D.prototype.rotatePoint = function(x, y, theta, cx, cy)
{
var rad = theta * (Math.PI / 180);
return mxUtils.getRotatedPoint(new mxPoint(x, y), Math.cos(rad),
Math.sin(rad), new mxPoint(cx, cy));
};
/**
* Function: save
*
* Saves the current state.
*/
mxAbstractCanvas2D.prototype.save = function()
{
this.states.push(this.state);
this.state = mxUtils.clone(this.state);
};
/**
* Function: restore
*
* Restores the current state.
*/
mxAbstractCanvas2D.prototype.restore = function()
{
if (this.states.length > 0)
{
this.state = this.states.pop();
}
};
/**
* Function: setLink
*
* Sets the current link. Hook for subclassers.
*/
mxAbstractCanvas2D.prototype.setLink = function(link)
{
// nop
};
/**
* Function: scale
*
* Scales the current state.
*/
mxAbstractCanvas2D.prototype.scale = function(value)
{
this.state.scale *= value;
this.state.strokeWidth *= value;
};
/**
* Function: translate
*
* Translates the current state.
*/
mxAbstractCanvas2D.prototype.translate = function(dx, dy)
{
this.state.dx += dx;
this.state.dy += dy;
};
/**
* Function: rotate
*
* Rotates the current state.
*/
mxAbstractCanvas2D.prototype.rotate = function(theta, flipH, flipV, cx, cy)
{
// nop
};
/**
* Function: setAlpha
*
* Sets the current alpha.
*/
mxAbstractCanvas2D.prototype.setAlpha = function(value)
{
this.state.alpha = value;
};
/**
* Function: setFillAlpha
*
* Sets the current solid fill alpha.
*/
mxAbstractCanvas2D.prototype.setFillAlpha = function(value)
{
this.state.fillAlpha = value;
};
/**
* Function: setStrokeAlpha
*
* Sets the current stroke alpha.
*/
mxAbstractCanvas2D.prototype.setStrokeAlpha = function(value)
{
this.state.strokeAlpha = value;
};
/**
* Function: setFillColor
*
* Sets the current fill color.
*/
mxAbstractCanvas2D.prototype.setFillColor = function(value)
{
if (value == mxConstants.NONE)
{
value = null;
}
this.state.fillColor = value;
this.state.gradientColor = null;
};
/**
* Function: setGradient
*
* Sets the current gradient.
*/
mxAbstractCanvas2D.prototype.setGradient = function(color1, color2, x, y, w, h, direction, alpha1, alpha2)
{
var s = this.state;
s.fillColor = color1;
s.gradientFillAlpha = (alpha1 != null) ? alpha1 : 1;
s.gradientColor = color2;
s.gradientAlpha = (alpha2 != null) ? alpha2 : 1;
s.gradientDirection = direction;
};
/**
* Function: setStrokeColor
*
* Sets the current stroke color.
*/
mxAbstractCanvas2D.prototype.setStrokeColor = function(value)
{
if (value == mxConstants.NONE)
{
value = null;
}
this.state.strokeColor = value;
};
/**
* Function: setStrokeWidth
*
* Sets the current stroke width.
*/
mxAbstractCanvas2D.prototype.setStrokeWidth = function(value)
{
this.state.strokeWidth = value;
};
/**
* Function: setDashed
*
* Enables or disables dashed lines.
*/
mxAbstractCanvas2D.prototype.setDashed = function(value, fixDash)
{
this.state.dashed = value;
this.state.fixDash = fixDash;
};
/**
* Function: setDashPattern
*
* Sets the current dash pattern.
*/
mxAbstractCanvas2D.prototype.setDashPattern = function(value)
{
this.state.dashPattern = value;
};
/**
* Function: setLineCap
*
* Sets the current line cap.
*/
mxAbstractCanvas2D.prototype.setLineCap = function(value)
{
this.state.lineCap = value;
};
/**
* Function: setLineJoin
*
* Sets the current line join.
*/
mxAbstractCanvas2D.prototype.setLineJoin = function(value)
{
this.state.lineJoin = value;
};
/**
* Function: setMiterLimit
*
* Sets the current miter limit.
*/
mxAbstractCanvas2D.prototype.setMiterLimit = function(value)
{
this.state.miterLimit = value;
};
/**
* Function: setFontColor
*
* Sets the current font color.
*/
mxAbstractCanvas2D.prototype.setFontColor = function(value)
{
if (value == mxConstants.NONE)
{
value = null;
}
this.state.fontColor = value;
};
/**
* Function: setFontColor
*
* Sets the current font color.
*/
mxAbstractCanvas2D.prototype.setFontBackgroundColor = function(value)
{
if (value == mxConstants.NONE)
{
value = null;
}
this.state.fontBackgroundColor = value;
};
/**
* Function: setFontColor
*
* Sets the current font color.
*/
mxAbstractCanvas2D.prototype.setFontBorderColor = function(value)
{
if (value == mxConstants.NONE)
{
value = null;
}
this.state.fontBorderColor = value;
};
/**
* Function: setFontSize
*
* Sets the current font size.
*/
mxAbstractCanvas2D.prototype.setFontSize = function(value)
{
this.state.fontSize = parseFloat(value);
};
/**
* Function: setFontFamily
*
* Sets the current font family.
*/
mxAbstractCanvas2D.prototype.setFontFamily = function(value)
{
this.state.fontFamily = value;
};
/**
* Function: setFontStyle
*
* Sets the current font style.
*/
mxAbstractCanvas2D.prototype.setFontStyle = function(value)
{
if (value == null)
{
value = 0;
}
this.state.fontStyle = value;
};
/**
* Function: setShadow
*
* Enables or disables and configures the current shadow.
*/
mxAbstractCanvas2D.prototype.setShadow = function(enabled)
{
this.state.shadow = enabled;
};
/**
* Function: setShadowColor
*
* Enables or disables and configures the current shadow.
*/
mxAbstractCanvas2D.prototype.setShadowColor = function(value)
{
if (value == mxConstants.NONE)
{
value = null;
}
this.state.shadowColor = value;
};
/**
* Function: setShadowAlpha
*
* Enables or disables and configures the current shadow.
*/
mxAbstractCanvas2D.prototype.setShadowAlpha = function(value)
{
this.state.shadowAlpha = value;
};
/**
* Function: setShadowOffset
*
* Enables or disables and configures the current shadow.
*/
mxAbstractCanvas2D.prototype.setShadowOffset = function(dx, dy)
{
this.state.shadowDx = dx;
this.state.shadowDy = dy;
};
/**
* Function: begin
*
* Starts a new path.
*/
mxAbstractCanvas2D.prototype.begin = function()
{
this.lastX = 0;
this.lastY = 0;
this.path = [];
};
/**
* Function: moveTo
*
* Moves the current path the given coordinates.
*/
mxAbstractCanvas2D.prototype.moveTo = function(x, y)
{
this.addOp(this.moveOp, x, y);
};
/**
* Function: lineTo
*
* Draws a line to the given coordinates. Uses moveTo with the op argument.
*/
mxAbstractCanvas2D.prototype.lineTo = function(x, y)
{
this.addOp(this.lineOp, x, y);
};
/**
* Function: quadTo
*
* Adds a quadratic curve to the current path.
*/
mxAbstractCanvas2D.prototype.quadTo = function(x1, y1, x2, y2)
{
this.addOp(this.quadOp, x1, y1, x2, y2);
};
/**
* Function: curveTo
*
* Adds a bezier curve to the current path.
*/
mxAbstractCanvas2D.prototype.curveTo = function(x1, y1, x2, y2, x3, y3)
{
this.addOp(this.curveOp, x1, y1, x2, y2, x3, y3);
};
/**
* Function: arcTo
*
* Adds the given arc to the current path. This is a synthetic operation that
* is broken down into curves.
*/
mxAbstractCanvas2D.prototype.arcTo = function(rx, ry, angle, largeArcFlag, sweepFlag, x, y)
{
var curves = mxUtils.arcToCurves(this.lastX, this.lastY, rx, ry, angle, largeArcFlag, sweepFlag, x, y);
if (curves != null)
{
for (var i = 0; i < curves.length; i += 6)
{
this.curveTo(curves[i], curves[i + 1], curves[i + 2],
curves[i + 3], curves[i + 4], curves[i + 5]);
}
}
};
/**
* Function: close
*
* Closes the current path.
*/
mxAbstractCanvas2D.prototype.close = function(x1, y1, x2, y2, x3, y3)
{
this.addOp(this.closeOp);
};
/**
* Function: end
*
* Empty implementation for backwards compatibility. This will be removed.
*/
mxAbstractCanvas2D.prototype.end = function() { };