@maxgraph/core
Version:
maxGraph is a fully client side JavaScript diagramming library that uses SVG and HTML for rendering.
435 lines (431 loc) • 13.1 kB
JavaScript
"use strict";
/*
Copyright 2021-present The maxGraph project Contributors
Copyright (c) 2006-2015, JGraph Ltd
Copyright (c) 2006-2015, Gaudenz Alder
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const mathUtils_js_1 = require("../../util/mathUtils.js");
const Constants_js_1 = require("../../util/Constants.js");
const UrlConverter_js_1 = __importDefault(require("../../util/UrlConverter.js"));
const Point_js_1 = __importDefault(require("../geometry/Point.js"));
const cloneUtils_js_1 = require("../../util/cloneUtils.js");
const config_js_1 = require("../../util/config.js");
/**
* Base class for all canvases.
*
* The following methods make up the public interface of the canvas 2D for all painting in mxGraph:
*
* - {@link save}, {@link restore}
* - {@link scale}, {@link translate}, {@link rotate}
* - {@link setAlpha}, {@link setFillAlpha}, {@link setStrokeAlpha}, {@link setFillColor}, {@link setGradient},
* {@link setStrokeColor}, {@link setStrokeWidth}, {@link setDashed}, {@link setDashPattern}, {@link setLineCap},
* {@link setLineJoin}, {@link setMiterLimit}
* - {@link setFontColor}, {@link setFontBackgroundColor}, {@link setFontBorderColor}, {@link setFontSize},
* {@link setFontFamily}, {@link setFontStyle}
* - {@link setShadow}, {@link setShadowColor}, {@link setShadowAlpha}, {@link setShadowOffset}
* - {@link rect}, {@link roundrect}, {@link ellipse}, {@link image}, {@link text}
* - {@link begin}, {@link moveTo}, {@link lineTo}, {@link quadTo}, {@link curveTo}
* - {@link stroke}, {@link fill}, {@link fillAndStroke}
*
* {@link arcTo} is an additional method for drawing paths.
* This is a synthetic method, meaning that it is turned into a sequence of curves by default.
* Subclasses may add native support for arcs.
*
* All color values of {@link NONE} will be converted to null in the state.
*/
class AbstractCanvas2D {
constructor() {
/**
* Holds the current state.
*/
this.state = this.createState();
/**
* Stack of states.
*/
this.states = [];
/**
* Holds the current path as an array.
*/
this.path = [];
/**
* Switch for rotation of HTML. Default is false.
*/
this.rotateHtml = true;
/**
* Holds the last x coordinate.
*/
this.lastX = 0;
/**
* Holds the last y coordinate.
*/
this.lastY = 0;
/**
* Contains the string used for moving in paths. Default is 'M'.
*/
this.moveOp = 'M';
/**
* Contains the string used for moving in paths. Default is 'L'.
*/
this.lineOp = 'L';
/**
* Contains the string used for quadratic paths. Default is 'Q'.
*/
this.quadOp = 'Q';
/**
* Contains the string used for bezier curves. Default is 'C'.
*/
this.curveOp = 'C';
/**
* Holds the operator for closing curves. Default is 'Z'.
*/
this.closeOp = 'Z';
/**
* Boolean value that specifies if events should be handled. Default is false.
*/
this.pointerEvents = false;
// from Polyline (maybe from other shapes also)
this.pointerEventsValue = null;
/**
* Adds the given operation to the path.
*/
this.addOp = (op, ...args) => {
this.path.push(op);
if (args.length > 1) {
const s = this.state;
for (let i = 1; i < args.length; i += 2) {
this.lastX = args[i - 1];
this.lastY = args[i];
this.path.push(this.format((this.lastX + s.dx) * s.scale));
this.path.push(this.format((this.lastY + s.dy) * s.scale));
}
}
};
this.converter = this.createUrlConverter();
this.reset();
}
/**
* Create a new <UrlConverter> and returns it.
*/
createUrlConverter() {
return new UrlConverter_js_1.default();
}
/**
* Resets the state of this canvas.
*/
reset() {
this.state = this.createState();
this.states = [];
}
/**
* Creates the state of the this canvas.
*/
createState() {
return {
dx: 0,
dy: 0,
scale: 1,
alpha: 1,
fillAlpha: 1,
strokeAlpha: 1,
fillColor: Constants_js_1.NONE,
gradientFillAlpha: 1,
gradientColor: Constants_js_1.NONE,
gradientAlpha: 1,
gradientDirection: 'east',
strokeColor: Constants_js_1.NONE,
strokeWidth: 1,
dashed: false,
dashPattern: '3 3',
fixDash: false,
lineCap: 'flat',
lineJoin: 'miter',
miterLimit: 10,
fontColor: '#000000',
fontBackgroundColor: Constants_js_1.NONE,
fontBorderColor: Constants_js_1.NONE,
fontSize: Constants_js_1.DEFAULT_FONTSIZE,
fontFamily: Constants_js_1.DEFAULT_FONTFAMILY,
fontStyle: 0,
shadow: false,
shadowColor: config_js_1.StyleDefaultsConfig.shadowColor,
shadowAlpha: config_js_1.StyleDefaultsConfig.shadowOpacity,
shadowDx: config_js_1.StyleDefaultsConfig.shadowOffsetX,
shadowDy: config_js_1.StyleDefaultsConfig.shadowOffsetY,
rotation: 0,
rotationCx: 0,
rotationCy: 0,
};
}
/**
* Rounds all numbers to integers.
*/
format(value) {
return Math.round(value);
}
/**
* Rotates the given point and returns the result as an {@link Point}.
*/
rotatePoint(x, y, theta, cx, cy) {
const rad = theta * (Math.PI / 180);
return (0, mathUtils_js_1.getRotatedPoint)(new Point_js_1.default(x, y), Math.cos(rad), Math.sin(rad), new Point_js_1.default(cx, cy));
}
/**
* Saves the current state.
*/
save() {
this.states.push(this.state);
this.state = (0, cloneUtils_js_1.clone)(this.state);
}
/**
* Restores the current state.
*/
restore() {
const state = this.states.pop();
if (state)
this.state = state;
}
/**
* Sets the current link. Hook for subclassers.
*/
setLink(link) {
// nop
}
/**
* Scales the current state.
*/
scale(value) {
this.state.scale *= value;
if (this.state.strokeWidth !== null)
this.state.strokeWidth *= value;
}
/**
* Translates the current state.
*/
translate(dx, dy) {
this.state.dx += dx;
this.state.dy += dy;
}
/**
* Rotates the current state.
*/
rotate(theta, flipH, flipV, cx, cy) {
// nop
}
/**
* Sets the current alpha.
*/
setAlpha(value) {
this.state.alpha = value;
}
/**
* Sets the current solid fill alpha.
*/
setFillAlpha(value) {
this.state.fillAlpha = value;
}
/**
* Sets the current stroke alpha.
*/
setStrokeAlpha(value) {
this.state.strokeAlpha = value;
}
/**
* Sets the current fill color.
*/
setFillColor(value) {
this.state.fillColor = value ?? Constants_js_1.NONE;
this.state.gradientColor = Constants_js_1.NONE;
}
/**
* Sets the current gradient.
*/
setGradient(color1, color2, x, y, w, h, direction, alpha1 = 1, alpha2 = 1) {
const s = this.state;
s.fillColor = color1;
s.gradientFillAlpha = alpha1;
s.gradientColor = color2;
s.gradientAlpha = alpha2;
s.gradientDirection = direction;
}
/**
* Sets the current stroke color.
*/
setStrokeColor(value) {
this.state.strokeColor = value ?? Constants_js_1.NONE;
}
/**
* Sets the current stroke width.
*/
setStrokeWidth(value) {
this.state.strokeWidth = value;
}
/**
* Enables or disables dashed lines.
*/
setDashed(value, fixDash = false) {
this.state.dashed = value;
this.state.fixDash = fixDash;
}
/**
* Sets the current dash pattern.
*/
setDashPattern(value) {
this.state.dashPattern = value;
}
/**
* Sets the current line cap.
*/
setLineCap(value) {
this.state.lineCap = value;
}
/**
* Sets the current line join.
*/
setLineJoin(value) {
this.state.lineJoin = value;
}
/**
* Sets the current miter limit.
*/
setMiterLimit(value) {
this.state.miterLimit = value;
}
/**
* Sets the current font color.
*/
setFontColor(value) {
this.state.fontColor = value ?? Constants_js_1.NONE;
}
/**
* Sets the current font background color.
*/
setFontBackgroundColor(value) {
this.state.fontBackgroundColor = value ?? Constants_js_1.NONE;
}
/**
* Sets the current font border color.
*/
setFontBorderColor(value) {
this.state.fontBorderColor = value ?? Constants_js_1.NONE;
}
/**
* Sets the current font size.
*/
setFontSize(value) {
this.state.fontSize = value;
}
/**
* Sets the current font family.
*/
setFontFamily(value) {
this.state.fontFamily = value;
}
/**
* Sets the current font style.
*/
setFontStyle(value) {
this.state.fontStyle = value;
}
/**
* Enables or disables and configures the current shadow.
*/
setShadow(enabled) {
this.state.shadow = enabled;
}
/**
* Sets the current shadow color.
*
* @param value Hexadecimal representation of the color or `none`.
*/
setShadowColor(value) {
this.state.shadowColor = value ?? Constants_js_1.NONE;
}
/**
* Sets the current shadow alpha.
*
* @param value Number that represents the new alpha. Possible values are between 1 (opaque) and 0 (transparent).
*/
setShadowAlpha(value) {
this.state.shadowAlpha = value;
}
/**
* Sets the current shadow offset.
*
* @param dx Number that represents the horizontal offset of the shadow.
* @param dy Number that represents the vertical offset of the shadow.
*/
setShadowOffset(dx, dy) {
this.state.shadowDx = dx;
this.state.shadowDy = dy;
}
/**
* Starts a new path.
*/
begin() {
this.lastX = 0;
this.lastY = 0;
this.path = [];
}
/**
* Moves the current path the given coordinates.
*/
moveTo(x, y) {
this.addOp(this.moveOp, x, y);
}
/**
* Draws a line to the given coordinates. Uses moveTo with the op argument.
*/
lineTo(x, y) {
this.addOp(this.lineOp, x, y);
}
/**
* Adds a quadratic curve to the current path.
*/
quadTo(x1, y1, x2, y2) {
this.addOp(this.quadOp, x1, y1, x2, y2);
}
/**
* Adds a bezier curve to the current path.
*/
curveTo(x1, y1, x2, y2, x3, y3) {
this.addOp(this.curveOp, x1, y1, x2, y2, x3, y3);
}
/**
* Adds the given arc to the current path. This is a synthetic operation that
* is broken down into curves.
* @param rx: The x distance between the current position
* and the center of the ellipse around which to arc
* @param ry: The y distance between the current position
* and the center of the ellipse around which to arc
* @param x: The x position of the end point of the arc
* @param y: The y position of the end point of the arc
*/
arcTo(rx, ry, angle, largeArcFlag, sweepFlag, x, y) {
const curves = (0, mathUtils_js_1.arcToCurves)(this.lastX, this.lastY, rx, ry, angle, largeArcFlag, sweepFlag, x, y);
if (curves != null) {
for (let 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]);
}
}
}
/**
* Closes the current path.
*/
close(x1, y1, x2, y2, x3, y3) {
this.addOp(this.closeOp);
}
}
exports.default = AbstractCanvas2D;